From 03952e0e48bca50f468b7280d7613a8e28a09feb Mon Sep 17 00:00:00 2001
From: Umang Dhawan
Date: Mon, 24 Aug 2026 14:29:47 -0500
Subject: [PATCH 1/2] release: ship complete canvas map in v0.20.0
---
.github/workflows/pages.yml | 20 +-
CHANGELOG.md | 24 +
CLAUDE.md | 89 +-
README.md | 69 +-
codemble/adapters/project.py | 11 +-
.../{index-BpwjRXVi.js => index-DzCSIcHk.js} | 4 +-
...{index-DgSklSeG.css => index-R8cZVoqz.css} | 2 +-
codemble/web_dist/index.html | 4 +-
docs-site/package.json | 2 +-
docs-site/public/shots/easy-mode.png | Bin 72369 -> 70824 bytes
docs-site/public/shots/galaxy-lit.png | Bin 225011 -> 225129 bytes
docs-site/public/shots/galaxy.png | Bin 276417 -> 280333 bytes
docs-site/public/shots/home-proved.png | Bin 206806 -> 206310 bytes
docs-site/public/shots/map-architecture.png | Bin 63947 -> 61809 bytes
docs-site/public/shots/map-workflow.png | Bin 73342 -> 72694 bytes
docs-site/public/shots/study-impact.png | Bin 116765 -> 113978 bytes
docs-site/public/shots/study-panel.png | Bin 78733 -> 75999 bytes
docs-site/public/shots/system.png | Bin 155323 -> 153947 bytes
docs-site/release.json | 24 +-
docs-site/scripts/check-release-facts.mjs | 13 +
docs-site/src/components/AtlasJourney.astro | 10 +-
docs-site/src/content/docs/architecture.md | 4 +-
.../src/content/docs/checks-and-lighting.md | 2 +-
docs-site/src/content/docs/download.md | 42 +-
docs-site/src/content/docs/early-testing.md | 10 +-
docs-site/src/content/docs/installation.md | 18 +-
docs-site/src/content/docs/introduction.md | 2 +-
docs-site/src/content/docs/parser-scale.md | 46 +-
docs-site/src/content/docs/quickstart.md | 12 +-
docs-site/src/content/docs/roadmap.md | 18 +-
docs-site/src/content/docs/star-chart.md | 2 +-
docs-site/src/content/docs/study-panel.md | 4 +-
docs-site/src/content/docs/the-galaxy.md | 13 +-
docs-site/src/pages/index.astro | 6 +-
docs/releases/v0.20.0.md | 50 +
pyproject.toml | 7 +-
scripts/serve_large_project_gate.py | 5 +-
tests/test_smoke.py | 4 +-
web/package-lock.json | 4 +-
web/package.json | 4 +-
web/scripts/capture_product_shots.mjs | 14 +-
web/scripts/check_large_project.mjs | 130 ++-
web/scripts/check_map_canvas_renderer.mjs | 220 +++++
web/scripts/check_panel_reach.mjs | 7 +-
web/scripts/check_space_budget.mjs | 7 +-
web/scripts/check_userflow_repairs.mjs | 185 +++-
web/src/App.jsx | 4 +-
web/src/MapView.jsx | 854 ++++++++++--------
web/src/celestialBodies.js | 4 +-
web/src/mapCanvasRenderer.js | 500 ++++++++++
web/src/styles.css | 182 +---
51 files changed, 1891 insertions(+), 741 deletions(-)
rename codemble/web_dist/assets/{index-BpwjRXVi.js => index-DzCSIcHk.js} (95%)
rename codemble/web_dist/assets/{index-DgSklSeG.css => index-R8cZVoqz.css} (71%)
create mode 100644 docs/releases/v0.20.0.md
create mode 100644 web/scripts/check_map_canvas_renderer.mjs
create mode 100644 web/src/mapCanvasRenderer.js
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 47123ca..58bbbf2 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -26,10 +26,28 @@ jobs:
with:
node-version: "22"
- uses: actions/configure-pages@v6
- - name: Build Astro site
+ # A version-bump commit can reach main before trusted publishing has
+ # finished. Never deploy copy that says "PyPI published" until PyPI,
+ # GitHub assets, and the checksum ledger already agree with the manifest.
+ # Ordinary docs-only updates pass on the first attempt; a release
+ # transition waits for the release-published workflow instead of briefly
+ # making a future version look stable.
+ - name: Wait for the public release ledger
run: |
cd docs-site
npm install
+ for attempt in $(seq 1 30); do
+ if npm run check:release:live; then
+ exit 0
+ fi
+ if [ "$attempt" -lt 30 ]; then
+ sleep 20
+ fi
+ done
+ exit 1
+ - name: Build Astro site
+ run: |
+ cd docs-site
npm run build
- uses: actions/upload-pages-artifact@v5
with:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40e8dad..5ffab9d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,30 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) · Versioning:
## [Unreleased]
+## [0.20.0] - 2026-08-24
+
+### Added
+- The Architecture and Workflow maps now use a complete, viewport-rendered
+ canvas surface. The default all-language map keeps every parser-owned module
+ and route represented, searchable, keyboard reachable, and recoverable;
+ explicit language focus keeps the complete named projection. Neither path
+ creates one DOM element per item.
+- The canvas Map exposes one stable keyboard focus target with directional,
+ Home/End, and Enter/Space navigation, plus a full-label readout for clipped
+ identifiers.
+
+### Changed
+- The default supported-project cap moves from 1,000 to 5,000 files after the
+ complete Map passed the same predeclared backend, Chromium, and WebKit gate.
+- Empty canvas space preserves drag-to-pan while emitted box coordinates and
+ renderer-owned painted-row bounds retain direct activation. Architecture
+ and Workflow keep their existing parser-owned coordinates, certainty,
+ progress, and language channels.
+
+### Fixed
+- Map recovery now gates on the first visible canvas slice rather than merely
+ the presence of an empty canvas element.
+
## [0.19.2] - 2026-08-21
### Changed
diff --git a/CLAUDE.md b/CLAUDE.md
index 5c74296..8eb506b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -203,13 +203,15 @@ evidence continues in parallel — exercise the loop on real learner projects.
The v0.1.0 Python learner-acceptance issue stays open; technical completion
does not claim those external runs passed.
-**NEXT — scale, and the deepening that is genuinely left.** The slate is now
-mostly done: Python's call resolution and lens (v0.11.0), and JS/TS builtin
-classification plus test-demoted entrypoint ranking (v0.12.0). **The
-TypeScript "deepening" was measured and largely refused** — see the Decision
-Log; TS's unproven edges are 80% honest boundaries and 1% fan-out, so copying
-Python's receiver resolution would have been work against a problem that is not
-there. What actually remains:
+**NEXT — the privacy boundary for read-only sharing.** The parser and scale
+slate is now complete through the v0.20.0 candidate: Python's call resolution
+and lens (v0.11.0), JS/TS builtin classification and entrypoint ranking
+(v0.12.0), bounded parser evidence (v0.19.0), and a complete canvas Map that
+passes the 5,000-module backend, Chromium, and WebKit gate. The next build phase
+must define provenance, expiry, deletion, and source-exclusion for the planned
+shareable read-only galaxy link before adding its only cloud touch.
+
+The prior scale decisions remain recorded because the measurements are reusable:
**All three items previously listed here were measured, and two of them were
refused on the evidence.** Recorded because the measurements are reusable:
@@ -232,12 +234,11 @@ refused on the evidence.** Recorded because the measurements are reusable:
5,000 modules, but WebKit could not stabilize the first-run Skip control
within the 5 s interaction budget while 5,000 SVG boxes committed.
-What is genuinely next: a canvas-backed **complete Map**, then the same 5,000-
-module Chromium and WebKit gate. Delivery may change, but every module remains
-represented, searchable, keyboard reachable, and recoverable; logical LOD that
-hides modules is not an acceptable shortcut. The ordinary cap stays 1,000
-until that gate passes. Phase 3 remains the shareable read-only galaxy link and
-extra quest types.
+The canvas Map changes delivery only: every module remains represented,
+searchable, keyboard reachable, and recoverable; logical LOD that hides modules
+is still not acceptable. The ordinary cap is 5,000 after the schema-4 candidate
+gate passed both engines. Phase 3 remains the shareable read-only galaxy link
+and extra quest types.
**LATER — Phase 3 (months ~7–9).** Shareable read-only galaxy link (the only
cloud touch). Extra quest types: trace-a-request, fix-the-failing-test.
@@ -245,12 +246,33 @@ Polish, then the coordinated launch (Show HN / X; lit-galaxy GIF as hero).
## Current State **[AGENT-MAINTAINED]**
-**Current milestone: M16 parser evidence and scale gates** · Last updated:
-2026-08-21 · Session note: two compact user-flow repairs shipped as verified
-stable v0.19.2 without changing parser, graph, checks, progress, providers,
-or release-scale truth.
-
-**The candidate closes two measured P2 gaps.** WebKit may leave focus on
+**Current milestone: M17 complete canvas Map and 5,000-file scale** · Last updated:
+2026-08-24 · Session note: the v0.20.0 candidate replaces per-item Map SVG DOM
+with complete viewport canvas delivery, improves keyboard/pointer/readout flow,
+and promotes the ordinary supported-file cap only after the full gate passes.
+
+**The v0.20.0 candidate completes the next measured phase.** Architecture and
+Workflow retain backend coordinates and every module/route in one complete
+prepared scene for the current language projection while drawing only the
+native-scroll viewport. The default all-language projection retains the entire
+Map; an explicit language focus remains a named learner-controlled filter. One
+listbox focus target replaces thousands of tab stops; arrows, Home/End, and
+Enter/Space remain direct, clipped canvas labels get a complete wrapping
+contextual readout, and empty space alone owns drag-to-pan. The revised schema-4
+5,000-module receipt passes at 4.870 s cold, 1.668 s no-change, and 170,606,592
+bytes process RSS.
+Chromium/WebKit each hold 99 DOM elements, all 5,000 boxes and 4,999 routes,
+direct final-module keyboard/Finder arrival, visible recovery in 76–82 ms,
+and zero page overflow at 320 px. The semantic oracle retains zero regressions.
+Native Safari visual acceptance was unavailable because the Mac was locked;
+WebKit engine acceptance and inspected 1440/320 captures passed without being
+misreported as Safari.
+
+Previously (2026-08-21) · Session note: two compact user-flow repairs shipped
+as verified stable v0.19.2 without changing parser, graph, checks, progress,
+providers, or then-current release-scale truth.
+
+**The v0.19.2 candidate closed two measured P2 gaps.** WebKit may leave focus on
`` after a pointer activates Menu, so the disclosure's subtree handler
never received Escape; the existing window arbiter now owns that dismissal and
returns focus without retreating a level. At 320–405px widths, the sticky quiz
@@ -1703,6 +1725,24 @@ Chromium's complete 5,000-module view passes every declared budget, WebKit's
failure remains visible and prevents a cap increase, and the production SPA is
rebuilt from the reviewed source.
+### M17 — Complete canvas Map and 5,000-file scale ✅ (2026-08-24)
+- [x] Replace per-module/per-route SVG DOM with complete viewport-rendered
+ Architecture and Workflow canvas scenes while preserving backend layout
+- [x] Keep every module represented, searchable, keyboard reachable, and
+ recoverable; add no logical LOD or second source of truth
+- [x] Provide one focusable Map surface with directional, Home/End, and
+ Enter/Space navigation plus a full-label readout
+- [x] Preserve native scroll extent, zoom, fit, empty-space drag-to-pan,
+ parser-owned pointer hits, responsive geometry, and reduced motion
+- [x] Pass the schema-4 complete 5,000-module backend, Chromium, and WebKit gate
+ before moving the ordinary cap from 1,000 to 5,000
+
+**Acceptance:** 532 Python tests, Ruff, the complete frontend contract/build,
+the semantic oracle, and exact 5,000-module source-scene counts pass; both
+engines remain below the DOM, resource, usable-time, input, keyboard, recovery,
+event-loop, memory, and 320 px overflow budgets; the production SPA and public
+evidence are rebuilt from the reviewed source.
+
## Decision Log **[AGENT-MAINTAINED — append only]**
| Date | Decision | Why |
@@ -1912,6 +1952,10 @@ rebuilt from the reviewed source.
| 2026-08-21 | Compact Menu dismissal is owned by the window Escape arbiter, and the compact quiz owns the footer row below the rail | WebKit does not guarantee that a pointer-clicked button receives focus, so the rail subtree could not hear Escape when focus stayed on body; one ordered window owner closes it and restores Menu focus without navigation. The quiz's absolute panel ended above the footer with 437px at 320x640, so top-aligning the question still put the final answer under the sticky action through 405px. Using the same fixed below-rail boundary as Study gains the otherwise redundant status row while preserving the rail, sticky action, parser-owned question, and all four complete answer targets |
| 2026-08-21 | Compact quiz arrival sets the panel scroll position directly and repeats alignment after local fonts settle; its browser gate measures after the 420ms panel entrance | The first v0.19.2 exact-main CI run proved that Ubuntu WebKit could ignore `scrollIntoView({behavior: "instant"})` during panel entry even though Chromium and macOS WebKit accepted it: at 320x640 all four 84px answer rows existed, but the last sat at 779-863px behind an action beginning at 588px. Direct scroll ownership removes that engine-dependent request, and the post-font alignment makes late identifier wrapping explicit. The repair preserves the 124px navigation rail, complete parser-owned identifiers, and 44px targets rather than passing by truncating or shrinking the choices |
| 2026-08-21 | v0.19.2 becomes stable only after the failed first candidate is repaired and the replacement tag passes exact-SHA outside-in proof | The first main candidate correctly remained unreleased when Ubuntu WebKit exposed the hidden fourth quiz answer. Replacement tag `v0.19.2` (`af33aa0`) peels to `466c130`; main CI `32547669499`, Pages `32547669498`, and trusted publish `32548094677` are green. Fresh GitHub bytes, PyPI, and `SHA256SUMS.txt` agree on wheel `8d6183d2…7492a6` and sdist `b570ecc3…50ad7`; a cold Python 3.11 install reports 0.19.2 and carries `index-BpwjRXVi.js` plus `index-DgSklSeG.css`. The follow-up changes only this operating truth and must never move the release tag |
+| 2026-08-24 | The complete Map uses one complete prepared scene per explicit language projection and a native-scroll viewport canvas; culling is draw delivery only, never logical LOD | A 5,000-box SVG created 35,102 DOM elements and destabilized WebKit before first-run interaction. The default all-language canvas retains all 5,000 boxes and 4,999 routes while drawing five or six visible boxes with 99 DOM elements; language focus remains a named learner-controlled projection. Backend coordinates, certainty, language, progress, Finder, recovery, and accessibility remain authoritative; one position-aware active descendant replaces thousands of tab stops, and hit testing accepts only emitted box coordinates plus renderer-owned painted-row bounds. Removing the canvas still leaves the complete current projection and every navigation target in data |
+| 2026-08-24 | The ordinary supported-file cap moves from 1,000 to 5,000 only after the schema-4 backend, Chromium, and WebKit receipt passes | The final candidate records 4.870 s cold, 1.668 s no-change, 170,606,592-byte process RSS high-water, complete 5,000/4,999 source-scene counts, 99 DOM elements per engine, 32.9–40.9 ms canvas arrival with item-specific active-descendant identity and 5,000-of-5,000 set position, 30.9–31.0 ms Finder p95, 76.0–81.1 ms recovery, and zero 320 px overflow. The previous one-engine result did not authorize promotion; this cross-engine result does. Above 5,000 remains an explicit scope prompt, not a hidden or unbounded claim |
+| 2026-08-24 | Pages proves the live release ledger before deploying release copy | A main version-bump commit can land before trusted publishing finishes, while the site already says the new version is stable and PyPI-published. The Pages workflow now retries the outside-in release check for a bounded ten minutes before building: ordinary docs changes pass immediately, and a release transition waits until PyPI metadata, GitHub release assets, downloaded hashes, and `SHA256SUMS.txt` match the committed manifest. This preserves exact-main CI and tag ordering without briefly publishing a future version as stable |
+| 2026-08-24 | A release candidate proves hosted CI on a PR, then publishes its exact local-main tag before moving origin/main | GitHub renders default-branch README copy independently of Pages, so pushing a version-bump commit to main before PyPI would still label an unpublished version stable. The candidate branch and PR give the exact commit hosted CI; local main then fast-forwards to that reviewed commit and owns the annotated tag while origin/main remains on the prior stable release. Only after trusted publishing and outside-in artifact proof does that same commit move origin/main. README media is tag-pinned, so PyPI never borrows older default-branch screenshots during the transition |
## Non-Goals — do NOT build (point here when asked)
@@ -1933,7 +1977,7 @@ rebuilt from the reviewed source.
2026-07-29** (see Decision Log): deterministic procedural celestial art is
approved **at the System tier only**. Bodies there carry an fBm crust, a rim
atmosphere and slow surface rotation. What remains OUT: procedural surfaces
- at Galaxy range (a level-of-detail limit, not a taste one — up to ~1,000
+ at Galaxy range (a level-of-detail limit, not a taste one — up to ~5,000
systems draw there), and any decoration that is not seeded purely by node id.
Decoration may never encode a fact; every semantic channel stays parser-owned
@@ -1971,13 +2015,12 @@ rebuilt from the reviewed source.
## Edge cases & limits
-- >~1,000 supported source files → prompt to scope to a subdirectory; a complete
- canvas Map plus the two-engine 5,000-module gate is required before this moves
+- >~5,000 supported source files → prompt to scope to a subdirectory
- No clear entrypoint → ranked candidates; user picks Home
- Syntax errors / partial parses → parse what you can, flag the rest, never crash
- Missing/invalid key → galaxy + structure + checks work; explanations show "add your key"
- Unsupported-language files → outside the graph and never guessed
-- No WebGL → the plain-SVG Map remains available; the 3D Galaxy does not
+- No WebGL → the complete Canvas 2D Map remains available; the 3D Galaxy does not
## Definition of done — Phase 0
diff --git a/README.md b/README.md
index 69288e3..e37394b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
- Codemble v0.19.2 · every module is represented before the first lesson ·
+ Codemble v0.20.0 · every module is represented before the first lesson ·
related systems and proven routes share a subtle colour cue ·
visiting charts a route; passing checks lights a system amber
> [!IMPORTANT]
-> **The screen above and the packaged app are both v0.19.2.** The PyPI release
+> **The screen above and the packaged app are both v0.20.0.** The PyPI release
> maps Python, JavaScript, TypeScript, Go, Java, Rust, C#, and mixed projects;
> it includes First Flight, the local project-brief export, proven import-cycle
> facts, parser-owned feature journeys, deeper application/test role detection
@@ -52,43 +52,43 @@
## Start here
-### Run v0.19.2 — recommended
+### Run v0.20.0 — recommended
Install [uv](https://docs.astral.sh/uv/) once, then open Codemble whenever you
need it:
| | Step | Command |
| :---: | --- | --- |
-| | **Install uv** — a clean Python app runner | `brew install uv` |
-| | **Open this release** — pick a project in the browser | `uvx --from codemble==0.19.2 codemble` |
+| | **Install uv** — a clean Python app runner | `brew install uv` |
+| | **Open this release** — pick a project in the browser | `uvx --from codemble==0.20.0 codemble` |
No Homebrew? Use uv's [official installer](https://docs.astral.sh/uv/getting-started/installation/),
-or install permanently with `pipx install codemble==0.19.2` and run `codemble`.
+or install permanently with `pipx install codemble==0.20.0` and run `codemble`.
Pass a folder to skip the project picker:
-`uvx --from codemble==0.19.2 codemble ./my-project`.
+`uvx --from codemble==0.20.0 codemble ./my-project`.
Use the shorter `uvx codemble` when you intentionally want whatever release is
newest on PyPI.
-### Build the same v0.19.2 app from source
+### Build the same v0.20.0 app from source
Use this route when you want an editable checkout:
```bash
-git clone --branch v0.19.2 --depth 1 https://github.com/udhawan97/Codemble.git
+git clone --branch v0.20.0 --depth 1 https://github.com/udhawan97/Codemble.git
cd Codemble
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
@@ -104,13 +104,13 @@ the verification commands.
| | Plain-English answer |
| :---: | --- |
-| | **Explore first.** Every module is represented on the first frame. Subtle colour joins systems inside the same import community, while proven bridges stay neutral and possible routes stay dashed. First Flight gives Home a short, repeatable orientation path. |
-| | **See how it fits together.** Switch between a 3D galaxy, an import architecture map, and the call workflow from Home. |
-| | **Follow one feature end to end.** Study lays out a parser-proven route from Home through files and calls to the selected feature. Easy guides one step at a time; Expert adds the current step's parser evidence and clearly scoped selected-feature impact and verification candidates. |
-| | **Know what a change touches.** Impact traces what depends on a structure and what it depends on, with real file locations and certainty labels. |
-| | **Prove what you understand.** Graph-derived checks—not a narrator—are the only way to light a system amber. |
-| | **Keep the project local.** Parsing, maps, source, Impact, checks, and progress stay on your machine. |
-| | **Read mixed projects.** Python, JavaScript, TypeScript, Go, Java, Rust, and C# share one graph and one honesty contract. |
+| | **Explore first.** Every module is represented on the first frame. Subtle colour joins systems inside the same import community, while proven bridges stay neutral and possible routes stay dashed. First Flight gives Home a short, repeatable orientation path. |
+| | **See how it fits together.** Switch between a 3D galaxy, an import architecture map, and the call workflow from Home. |
+| | **Follow one feature end to end.** Study lays out a parser-proven route from Home through files and calls to the selected feature. Easy guides one step at a time; Expert adds the current step's parser evidence and clearly scoped selected-feature impact and verification candidates. |
+| | **Know what a change touches.** Impact traces what depends on a structure and what it depends on, with real file locations and certainty labels. |
+| | **Prove what you understand.** Graph-derived checks—not a narrator—are the only way to light a system amber. |
+| | **Keep the project local.** Parsing, maps, source, Impact, checks, and progress stay on your machine. |
+| | **Read mixed projects.** Python, JavaScript, TypeScript, Go, Java, Rust, and C# share one graph and one honesty contract. |
Codemble reads supported source. It does **not** run your app, package scripts,
compilers, or tests.
@@ -119,12 +119,12 @@ compilers, or tests.
| 01 · Explore | 02 · Map |
| --- | --- |
-| | |
+| | |
| Follow a colour corridor or take First Flight; keyboard focus keeps the active system and its neighbours on the current route mesh named. | Follow real imports from Home; unreachable modules are counted, not erased. |
| 03 · Inspect | 04 · Prove |
| --- | --- |
-| | |
+| | |
| See what a structure controls and what can break it—no model needed. | Pass checks drawn from the graph; only then does the system turn amber. |
### One graph, two useful views
@@ -137,8 +137,11 @@ compilers, or tests.
| **Star chart** | Project overview, proven import cycles, progress, and a local Markdown export | Carry parser-owned facts into a handoff |
| **Study** | One feature journey, real source, integrated Impact and Connections, Lens notes, and optional narration | Understand how one structure reaches the application |
-The Map is plain SVG, so it remains usable on a machine that cannot render the
-WebGL galaxy. Easy mode shows an overview and guides one cited journey step at a
+The default all-language Map is a complete viewport-rendered canvas; an explicit
+language focus keeps every item in that named projection. Both remain usable on
+a machine that cannot render the WebGL galaxy without creating one DOM element
+per module.
+Easy mode shows an overview and guides one cited journey step at a
time. Expert mode keeps that exact step selected and adds its parser rule and
observation evidence. Impact, Connections, and bounded test candidates describe
the selected feature as a whole, not the current route step. Neither mode
@@ -187,7 +190,7 @@ export CODEMBLE_OLLAMA_MODEL=gemma4:12b
- **Supported languages:** `.py`, `.js`, `.jsx`, `.mjs`, `.cjs`, `.ts`,
`.tsx`, `.mts`, `.cts`, `.go`, `.java`, `.rs`, and `.cs`.
-- **Scale:** above roughly 1,000 supported files, choose a subdirectory in the
+- **Scale:** above roughly 5,000 supported files, choose a subdirectory in the
picker or pass `--path ./project/src`.
- **Ambiguous Home:** choose a parser-ranked candidate in the app or pass
`--entrypoint NODE_ID`.
@@ -234,8 +237,8 @@ project:
| Horizon | Work |
| --- | --- |
-| **Now** | Collect unaided learner evidence and correctness reports on v0.19.2 |
-| **Next** | A canvas-backed complete Map, then the same 5,000-module Chromium and WebKit gate |
+| **Now** | Collect unaided learner evidence and correctness reports on v0.20.0 |
+| **Next** | Design the privacy boundary for the planned read-only galaxy link |
| **Later** | Read-only sharing, new quest types, and a coordinated public launch |
Milestones move only when their acceptance evidence exists. See the
diff --git a/codemble/adapters/project.py b/codemble/adapters/project.py
index 1149729..cb107cb 100644
--- a/codemble/adapters/project.py
+++ b/codemble/adapters/project.py
@@ -155,11 +155,12 @@ def cache_info(self) -> dict[str, int]:
return self._evidence_cache.info()
- # Raised from 300 with the Phase C threaded parse and staged loading screen.
- # The 2026-08-14 complete 5k Map gate passed Chromium but failed WebKit's
- # interaction budget, so explicit --path scopes may go larger while the
- # ordinary picker stays here until a complete canvas Map passes both.
- scale_cap = 1000
+ # Raised from 1,000 only after the complete canvas Map kept every one of
+ # 5,000 modules and 4,999 routes represented while the same backend,
+ # Chromium, WebKit, Finder, direct-keyboard, recovery, and 320px budgets
+ # passed. Explicit --path scopes may still go larger; the ordinary picker
+ # stops at the largest complete cross-engine receipt.
+ scale_cap = 5000
def intake(self, path: Path, *, explicit: bool = False) -> ProjectIntake:
"""Resolve one project scope and every adapter's owned files."""
diff --git a/codemble/web_dist/assets/index-BpwjRXVi.js b/codemble/web_dist/assets/index-DzCSIcHk.js
similarity index 95%
rename from codemble/web_dist/assets/index-BpwjRXVi.js
rename to codemble/web_dist/assets/index-DzCSIcHk.js
index 35df61f..9573d70 100644
--- a/codemble/web_dist/assets/index-BpwjRXVi.js
+++ b/codemble/web_dist/assets/index-DzCSIcHk.js
@@ -5449,5 +5449,5 @@ void main(){
gl_FragColor = vec4(color, 1.0);
}
-`;Object.freeze({vertex:$W,fragment:eG});function tG(e){let t=2166136261,n=String(e??``);for(let e=0;e>>0)/4294967296}function nG(e=32){return new yo(1,e,Math.max(8,e/2))}function rG({node:e,color:t,palette:n}){return new jo({vertexShader:$W,fragmentShader:eG,uniforms:{uBase:{value:new H(t)},uAmber:{value:new H(n.star)},uSeed:{value:tG(e.id)},uLit:{value:+!!e.understood},uPartial:{value:+!!e.partial},uClass:{value:+(e.kind===`class`)},uDim:{value:+!!e.focusDim}}})}function iG({node:e,color:t,palette:n,radius:r,geometry:i}){let a=new na(i,rG({node:e,color:t,palette:n}));return a.scale.setScalar(r),a.rotation.set(tG(`${e.id}:tilt`)*.9-.45,tG(e.id)*Math.PI*2,0),a.userData.codembleBody=!0,a}function aG(e,{reducedMotion:t=!1}={}){if(t)return()=>{};let n=0,r=performance.now(),i=()=>{let t=performance.now(),a=Math.min(.05,(t-r)/1e3);r=t,e.traverse(e=>{e.userData?.codembleBody&&(e.rotation.y+=a*.06)}),n=requestAnimationFrame(i)};return n=requestAnimationFrame(i),()=>cancelAnimationFrame(n)}var oG=`.orientation-copy button, .legend-toggle`,sG=`.orientation-bar, .keyboard-focus`;function cG({host:e,renderer:t,getStyle:n=e=>getComputedStyle(e)}){let r=e?.getBoundingClientRect?.(),i=lG(r,t),a=e?.closest?.(`.map-stage`);return Object.freeze(!a||!r?{viewport:i,clickObstructions:Object.freeze([]),nameObstructions:Object.freeze([])}:{viewport:i,clickObstructions:uG(a,oG,r,{accepts:e=>n(e).pointerEvents!==`none`}),nameObstructions:uG(a,sG,r)})}function lG(e,t){if(e?.width&&e?.height)return Object.freeze({width:e.width,height:e.height});let n=t?.width?.(),r=t?.height?.();return n&&r?Object.freeze({width:n,height:r}):null}function uG(e,t,n,{accepts:r=()=>!0}={}){let i=[];for(let a of e.querySelectorAll(t)){if(!r(a))continue;let e=a.getBoundingClientRect();!e.width||!e.height||i.push(Object.freeze({left:e.left-n.left,right:e.right-n.left,top:e.top-n.top,bottom:e.bottom-n.top}))}return Object.freeze(i)}var dG=1600,fG=.22,pG=.52,mG=.74,hG=3,gG=7;function _G(e){let t=Math.min(1,Math.max(0,e)),n=(e,n)=>Math.min(1,Math.max(0,(t-e)/(n-e)));return Object.freeze({ignite:n(0,fG),travel:n(fG,pG),flare:n(pG,mG),settle:n(mG,1)})}function vG(e,t,n=new Map){let r=[];for(let n of t??[]){if(!n?.certain)continue;let t=n.dst===e?n.src:n.src===e?n.dst:null;t===null||t===e||r.push(t)}let i=[...new Set(r)];return i.sort((e,t)=>{let r=n.get(e),i=n.get(t);return(typeof r==`number`?r:2**53-1)-(typeof i==`number`?i:2**53-1)||e.localeCompare(t)}),i.slice(0,hG)}function yG({scene:e,regionId:t,palette:n,dressing:r,routes:i=[],hopsById:a=new Map}){if(Bd())return()=>{};let o=e.getObjectByName(`codemble-system-${t}`);if(!o)return()=>{};let s=[];o.traverse(e=>{e.isSprite&&s.push([e,e.material.opacity,e.scale.clone()])});let c=s.map(([e])=>e.material.color.clone()),l=new H(n.star),u=new V;o.getWorldPosition(u);let d=[];if(r?.spark)for(let n of vG(t,i,a)){let t=e.getObjectByName(`codemble-system-${n}`);if(!t)continue;let i=new V;t.getWorldPosition(i);let a=r.spark();a.scale.setScalar(gG),a.position.copy(i),e.add(a),d.push({sprite:a,origin:i})}let f=()=>{s.forEach(([e,t,n],r)=>{e.material.color.copy(c[r]),e.material.opacity=t,e.scale.copy(n)});for(let{sprite:t}of d)e.remove(t),t.material.opacity=0;d.length=0},p=0,m=performance.now(),h=()=>{let e=Math.min(1,(performance.now()-m)/dG),t=_G(e),n=1-(1-t.travel)**3;for(let{sprite:e,origin:r}of d)e.position.lerpVectors(r,u,n),e.material.opacity=t.flare>0?0:Math.min(1,t.ignite)*.9;let r=Math.sin(Math.min(1,t.flare)*Math.PI*.5)*(1-t.settle);if(s.forEach(([e,t,n],i)=>{e.material.color.copy(c[i]).lerp(l,r*.85),e.material.opacity=t+r*.5,e.scale.copy(n).multiplyScalar(1+r*.45)}),e<1){p=requestAnimationFrame(h);return}f()};return p=requestAnimationFrame(h),()=>{cancelAnimationFrame(p),f()}}function bG(e){if(!e?.selected_entrypoint)return[];let t=new Map((e.nodes??[]).map(e=>[e.id,e])),n=new Map((e.regions??[]).map(e=>[e.id,e])),r=t.get(e.selected_entrypoint),i=r?n.get(r.region):null;if(!i?.home)return[];let a=new Map;for(let r of e.edges??[]){if(r.kind!==`import`||r.external||r.certain!==!0)continue;let e=t.get(r.src)?.region,i=t.get(r.dst)?.region;!e||!i||e===i||!n.has(e)||!n.has(i)||(a.has(e)||a.set(e,new Set),a.get(e).add(i))}let o=new Map,s=new Map;for(let t of e.region_edges??[])!n.has(t.src)||!n.has(t.dst)||t.src===t.dst||(o.has(t.src)||o.set(t.src,new Set),s.has(t.dst)||s.set(t.dst,new Set),o.get(t.src).add(t.dst),s.get(t.dst).add(t.src));return[i,...[...a.get(i.id)??[]].map(e=>n.get(e)).filter(Boolean).sort((e,t)=>(t.centrality??0)-(e.centrality??0)||String(e.id).localeCompare(String(t.id)))].slice(0,6).map(e=>({id:e.id,language:e.language,usedBy:s.get(e.id)?.size??0,uses:o.get(e.id)?.size??0,home:e.id===i.id}))}function xG(e,{active:t,reducedMotion:n}){return t&&n?0:e}var SG=(e,t)=>e.x*t.x+e.y*t.y+e.z*t.z,CG=(e,t)=>({x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x});function wG(e){if(!e)return null;let{x:t,y:n,z:r}=e;if(!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r))return null;let i=Math.hypot(t,n,r);return i>0?{x:t/i,y:n/i,z:r/i}:null}function TG({points:e,direction:t,fov:n,aspect:r,margin:i=.1}){let a=wG(t);if(!a||!Array.isArray(e)||e.length===0||!Number.isFinite(n)||n<=0||n>=180||!Number.isFinite(r)||r<=0)return null;let o=1-Math.min(Math.max(i,0),.9),s=Math.tan(n*Math.PI/360)*o,c=s*r,l=wG(CG(Math.abs(a.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},a));if(!l)return null;let u=CG(a,l),d=0;for(let t of e){if(!t)continue;let{x:e,y:n,z:r}=t;if(!Number.isFinite(e)||!Number.isFinite(n)||!Number.isFinite(r))continue;let i=SG(t,a),o=Number.isFinite(t.radius)?Math.max(0,t.radius):0,f=(Math.abs(SG(t,l))+o)/c,p=(Math.abs(SG(t,u))+o)/s;d=Math.max(d,i+f,i+p)}return d>0?d:null}function EG(e,t){let n=wG(e);return!n||!Number.isFinite(t)?null:{x:n.x*t,y:n.y*t,z:n.z*t}}var DG=24,OG=30;function kG(e,t){if(!e.length)return 0;let n=n=>{let r=-1/0,i=1/0;for(let a=0;ar&&(r=o),o0?r=e:i=e}return(r+i)/2}function AG({points:e,direction:t,fov:n,aspect:r,margin:i=.1}){let a=wG(t);if(!a||!Array.isArray(e)||e.length===0)return null;let o=e.filter(e=>e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.z));if(!o.length)return null;let s=wG(CG(Math.abs(a.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},a));if(!s)return null;let c=CG(a,s),l=e=>{let t=1/0,n=-1/0;for(let r of o){let i=SG(r,e);in&&(n=i)}return(t+n)/2},u={x:s.x*l(s)+c.x*l(c)+a.x*l(a),y:s.y*l(s)+c.y*l(c)+a.y*l(a),z:s.z*l(s)+c.z*l(c)+a.z*l(a)},d=()=>o.map(e=>({x:e.x-u.x,y:e.y-u.y,z:e.z-u.z,radius:e.radius})),f=TG({points:d(),direction:t,fov:n,aspect:r,margin:i});if(f===null)return null;for(let e=0;ee.language===t),r=new Set(n.map(e=>e.id)),i=new Set(e.nodes.map(e=>e.id)),a=new Set(n.map(e=>e.region)),o=new Set(n.map(e=>e.file));return{...e,nodes:n,edges:e.edges.filter(e=>r.has(e.src)&&(r.has(e.dst)||e.external||!i.has(e.dst))),entrypoint_candidates:e.entrypoint_candidates.filter(e=>r.has(e)),selected_entrypoint:r.has(e.selected_entrypoint)?e.selected_entrypoint:null,file_hashes:Object.fromEntries(Object.entries(e.file_hashes).filter(([e])=>o.has(e))),concept_annotations:e.concept_annotations.filter(e=>e.language===t&&r.has(e.node_id)),role_evidence:(e.role_evidence??[]).filter(e=>r.has(e.node_id)),regions:e.regions.filter(e=>a.has(e.id)),region_edges:e.region_edges.filter(e=>a.has(e.src)&&a.has(e.dst)),partial_files:e.partial_files.filter(e=>o.has(e))}}function NG(e,t){if(!e||!t||t===`all`)return e;let n=e.architecture,r=n.boxes.filter(e=>e.language===t),i=new Set(r.map(e=>e.id)),a=e.workflow;return{...e,architecture:{...n,boxes:r,edges:n.edges.filter(e=>i.has(e.src)&&i.has(e.dst)),unreachable:n.unreachable.filter(e=>i.has(e))},workflow:{...a,nodes:a.nodes.filter(e=>e.language===t),unreachable:a.unreachable.filter(e=>e.language===t)}}}function PG(e){let t=new Map;for(let n of e.regions)t.set(n.language,(t.get(n.language)??0)+1);let n=[...t].map(([e,t])=>({id:e,label:LG(e),shortLabel:RG(e),count:t})).sort((e,t)=>e.label.localeCompare(t.label));return[{id:`all`,label:`All languages`,shortLabel:`All`,count:e.regions.length},...n]}function FG(e,t){let n=new Map(e.nodes.map(e=>[e.id,e])),r=new Map;for(let i of e.concept_annotations??[]){let e=`${i.language}:${i.concept}`,a=r.get(e)??{language:i.language,concept:i.concept,occurrences:0,nodeIds:new Set,studiedNodeIds:new Set,understoodNodeIds:new Set};a.occurrences+=1,a.nodeIds.add(i.node_id),t.has(i.node_id)&&a.studiedNodeIds.add(i.node_id),n.get(i.node_id)?.understood&&a.understoodNodeIds.add(i.node_id),r.set(e,a)}return[...r.values()].map(e=>({language:e.language,concept:e.concept,occurrences:e.occurrences,nodes:e.nodeIds.size,studied_nodes:e.studiedNodeIds.size,understood_nodes:e.understoodNodeIds.size})).sort((e,t)=>e.language.localeCompare(t.language)||e.concept.localeCompare(t.concept))}function IG(e){let t={javascript:`JavaScript`,jsx:`JSX`,typescript:`TypeScript`,csharp:`C#`,"linq-query":`LINQ Query`};return t[e]?t[e]:e.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function LG(e){return IG(e)}function RG(e){return e===`javascript`?`JS`:e===`typescript`?`TS`:LG(e)}var zG=Object.freeze({python:`--cm-neb-python`,javascript:`--cm-neb-js`,typescript:`--cm-neb-ts`,go:`--cm-neb-go`,java:`--cm-neb-java`,rust:`--cm-neb-rust`,csharp:`--cm-neb-csharp`});function BG(e){let t=zG[e];return t?`var(${t})`:null}var VG=2;function HG(e,{showAll:t=!1,selectionId:n=null,visitedIds:r=null}={}){let i=()=>new Set(e.regions.map(e=>e.id));if(t||!e.regions.some(e=>e.home))return i();let a=new Set,o=new Set;for(let t of e.regions)typeof t.hops_from_home==`number`&&t.hops_from_home<=VG&&a.add(t.id),t.understood&&o.add(t.id),r&&r.has(t.id)&&o.add(t.id);n&&o.add(n);for(let e of o)a.add(e);for(let t of e.region_edges)(o.has(t.src)||o.has(t.dst))&&(a.add(t.src),a.add(t.dst));return a}function UG(e,t){if(!e||!e.length)return null;let n=e.reduce((e,t)=>e+t.count,0);return t===`easy`?`${WG(e.map(e=>`${e.count} ${e.language??e.extension}`))} ${n===1?`file`:`files`} not included`:`${e.map(e=>`${e.count} ${e.extension}`).join(` · `)} not charted`}function WG(e){return e.length<=1?e.join(``):`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}function GG(e){let t=new Map;for(let n of e.nodes)t.has(n.region)||t.set(n.region,n.file);return t}function KG(e){let t=e.split(`/`).filter(Boolean);return t.length>1?t.slice(-2).join(`/`):t[0]??e}function qG(e){let t=GG(e);return e.regions.map(e=>({id:e.id,file:t.get(e.id)??e.id,label:KG(t.get(e.id)??e.id),language:e.language,community:e.community,understood:e.understood,home:e.home,hops:typeof e.hops_from_home==`number`?e.hops_from_home:null,centrality:e.centrality,loc:e.loc})).sort((e,t)=>e.label.localeCompare(t.label)||e.id.localeCompare(t.id))}function JG(e){if(!e.length)return``;let t=e.map(e=>e.file.split(`/`).slice(0,-1)),n=t[0];for(let e of t.slice(1)){let t=0;for(;t{let n=JG(t),r=n.endsWith(`/`)?n:``;return{community:e,name:n,members:t.map(e=>({...e,display:r&&e.file.startsWith(r)?e.file.slice(r.length):e.file})).sort((e,t)=>e.display.localeCompare(t.display))}}).sort((e,t)=>t.members.length-e.members.length||e.community-t.community)}var XG=new Set([`tests`,`test`,`__tests__`,`spec`,`specs`]);function ZG(e){return String(e).split(`/`).slice(0,-1).some(e=>XG.has(e))}function QG(e){if(!e?.length)return null;let t=e=>String(e).split(`/`).filter(Boolean)[0]??null,n=t(e[0]);return n&&e.every(e=>t(e)===n)?n:null}var $G=5,eK=2;function tK(e){return Number.isInteger(e)&&e>=0&&e<8?e:null}var nK=Object.freeze({bright:1,mid:.72,dim:.5}),rK=.32;function iK(e){let t=/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/.exec(String(e));return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}function aK(e,t,n){let r=iK(e),i=iK(t);if(!r||!i)return e;let a=e=>Math.round(r[e]*n+i[e]*(1-n));return`rgb(${a(0)}, ${a(1)}, ${a(2)})`}function oK(e,t,n,r){let i=tK(t),a=i===null?null:e.communities?.[i];if(!a)return EK(n,e,r);let o=n>=r?`bright`:n>=1?`mid`:`dim`;return aK(a,e.ground,nK[o])}function sK(e,t){let n=tK(t),r=n===null?null:e.communities?.[n];return r?aK(r,e.route,rK):e.route}var cK=e=>e.charted===!0,lK=e=>e.charted===!1;function uK(e,t,n){let{activeId:r,neighborIds:i}=t??{};return r?e.id===r?n.orbit:i?.has(e.id)?e.color:n.faded:e.color}function dK(e,t,n,r){if(e.focusDim)return n.faded;let{activeId:i,neighborIds:a}=t??{},o=e.certain?e.color??n.route:n.routePossible;if(!i)return o;let s=r(e.source),c=r(e.target);return s===i||c===i?e.certain?n.orbit:n.routePossible:a?.has(s)&&a?.has(c)?o:n.faded}function fK(e,t,n=null){let r=e=>n===null||n.has(e),i=GG(e),a=new Map(e.regions.map(e=>[e.id,e])),o=vK(e.region_edges);return{nodes:e.regions.map(n=>{let a=r(n.id);return{...n,usedBy:o.usedBy.get(n.id)??0,uses:o.uses.get(n.id)??0,kind:`region`,name:n.id,label:KG(i.get(n.id)??n.id),charted:a,fx:n.x,fy:n.y,fz:n.z,val:xK(n.loc,5,24),color:n.understood?t.star:e.nodes.some(e=>e.region===n.id&&e.partial)?t.routePossible:oK(t,n.community_family,n.centrality,$G),focusDim:!1}}),links:e.region_edges.filter(e=>r(e.src)&&r(e.dst)).map(e=>{let n=a.get(e.src),r=a.get(e.dst),i=n?.community===r?.community&&n?.community_family===r?.community_family?tK(n?.community_family):null;return{...e,source:e.src,target:e.dst,color:e.certain?sK(t,i):t.routePossible,community_family:i,focusDim:!1}})}}function pK(e,t,n,{selectedId:r=null}={}){let i=e.nodes.filter(e=>e.region===t),a=new Set(i.map(e=>e.id)),o=e.regions.find(e=>e.id===t)?.community_family,s=e.edges.filter(e=>e.kind===`call`&&!e.external&&a.has(e.src)&&a.has(e.dst)),c=vK(e.edges.filter(e=>!e.external)),l=new Set(r?[r]:[]);if(r)for(let e of s)e.src===r&&l.add(e.dst),e.dst===r&&l.add(e.src);return{nodes:i.map(e=>({...e,usedBy:c.usedBy.get(e.id)??0,uses:c.uses.get(e.id)??0,fx:e.system_x,fy:e.system_y,fz:e.system_z,val:xK(e.loc,2.8,11),color:e.understood?n.star:e.partial?n.routePossible:oK(n,o,e.centrality,eK),selected:e.id===r,focusDim:!!r&&!l.has(e.id)})),links:s.map(e=>({...e,source:e.src,target:e.dst,color:e.certain?n.route:n.routePossible,focusDim:!!r&&e.src!==r&&e.dst!==r}))}}function mK(e){return e.regions.find(e=>e.home)??e.regions[0]??null}function hK(e){let t=String(e?.project_root??``);return(t.split(`/`).filter(Boolean).at(-1)??t)||`Local project`}function gK(e,t){if(!e?.length)return null;let n=[...e].sort((e,t)=>t.length-e.length||e.join(`\0`).localeCompare(t.join(`\0`)))[0].join(`, `);return t===`easy`?`${e.length} ${e.length===1?`file circle`:`file circles`} found. Largest group: ${n}. Each file can reach every other through proven imports.`:`${e.length} proven import ${e.length===1?`cycle group`:`cycle groups`}. Largest strongly connected group: ${n}.`}function _K(e){let t=e?.regions??[],n=e?.nodes??[],r=e?.edges??[],i=new Map;for(let e of t)i.set(e.language,(i.get(e.language)??0)+1);let a=new Map;for(let e of n)a.set(e.language,(a.get(e.language)??0)+1);let o=[...i.entries()].sort((e,t)=>t[1]-e[1]||String(e[0]).localeCompare(String(t[0]))).map(([e,t])=>({language:e,label:LG(e),count:t,structures:a.get(e)??0})),s=e=>t.filter(t=>Number.isFinite(t[e])).sort((t,n)=>n[e]-t[e]||String(t.id).localeCompare(String(n.id))).slice(0,5).map(t=>({id:t.id,value:t[e]})),c=mK(e);return{projectName:hK(e),modules:t.length,structures:n.length,lines:t.reduce((e,t)=>e+(t.loc??0),0),languages:o,home:e?.selected_entrypoint&&c?{id:c.id,language:c.language}:null,biggest:s(`loc`),busiest:s(`centrality`),unreadable:(e?.partial_files??[]).length,unsupported:(e?.unsupported_sources??[]).reduce((e,t)=>e+(t.count??0),0),unsupportedSources:[...e?.unsupported_sources??[]].map(e=>({extension:e.extension,language:e.language,count:e.count??0})).sort((e,t)=>String(e.extension).localeCompare(String(t.extension))||String(e.language).localeCompare(String(t.language))),relationships:{proven:r.filter(e=>e.certain===!0).length,hedged:r.filter(e=>e.certain===!1).length},importCycles:(e?.import_cycles??[]).map(e=>[...e]),understood:t.filter(e=>e.understood).length}}function vK(e){let t=new Map,n=new Map;for(let r of e??[])n.set(r.src,(n.get(r.src)??0)+1),t.set(r.dst,(t.get(r.dst)??0)+1);return{usedBy:t,uses:n}}function yK(e){let t=e.kind===`region`?`star system`:e.kind,n=e.partial?` · unchartable · syntax error`:``,r=e.home?` · Home`:``,i=(e.usedBy?` · used by ${e.usedBy}`:``)+(e.uses?` · uses ${e.uses}`:``),a=e.system_orbit?.kind===`unreached`?` · no proven call path`:Number.isInteger(e.system_orbit?.call_depth)&&e.system_orbit.call_depth>0?` · call layer ${e.system_orbit.call_depth}`:``;return`${e.name} · ${t} · ${e.loc} LOC${r}${i}${n}${a}`}function bK(e){let t=e.kind===`import`?`import`:e.kind===`call`?`call`:`import route`,n=e.certain?`certain`:t===`call`?`possible call`:`possible import`,r=typeof e.weight==`number`?` · ${e.weight} ${e.weight===1?`import`:`imports`}`:``,i=typeof e.lineno==`number`?` · line ${e.lineno}`:``;return`${e.src} → ${e.dst} · ${t} · ${n}${r}${i}`}function xK(e,t,n){return Math.min(n,Math.max(t,Math.sqrt(Math.max(1,e))*1.15))}var SK=1.6,CK=6.5;function wK(e){return Math.cbrt(e?.val??1)*SK}function TK(e){return wK(e)*CK/2}function EK(e,t,n){return e>=n?t.nodeBright:e>=1?t.node:t.nodeDim}var DK={GALAXY:{min:120,max:640},SYSTEM:{min:55,max:320},STUDY:{min:22,max:170}},OK={GALAXY:{x:0,y:165,z:286},SYSTEM:{x:0,y:52,z:150}},kK=1.15,AK={x:20,y:15,z:42};function jK(e){if(!e)return null;let{width:t,height:n}=e;return!Number.isFinite(t)||!Number.isFinite(n)||t<=0||n<=0?null:t/n}var MK=e=>e.map(e=>({x:e.fx??e.x??0,y:e.fy??e.y??0,z:e.fz??e.z??0,radius:TK(e)})),NK=e=>{let t=[];for(let n of e??[])for(let e of n.radii??[])t.push({x:e,y:0,z:0},{x:-e,y:0,z:0},{x:0,y:0,z:e},{x:0,y:0,z:-e});return t};function PK({level:e,nodes:t,orbitPlan:n,fov:r,aspect:i,viewport:a,chrome:o}){let s=OK[e]??OK.GALAXY,c=DK[e]??DK.GALAXY,l=e===jG.GALAXY?[]:NK(n),u=Array.isArray(t)?t:[],d=e=>[...MK(e),...l],f=e=>AG({points:d(e),direction:s,fov:r,aspect:i}),p=u.filter(cK),m=(p.length?f(p):null)??f(u),h={target:m?.target??{x:0,y:0,z:0},distance:m?.distance??Math.hypot(s.x,s.y,s.z)},{target:g,distance:_}=m?IK({...h,points:d(p.length?p:u),direction:s,fov:r,viewport:a,chrome:o}):h,v=EG(s,_)??s,y=TG({points:d(u).map(e=>({x:e.x-g.x,y:e.y-g.y,z:e.z-g.z,radius:e.radius})),direction:s,fov:r,aspect:i});return{position:{x:g.x+v.x,y:g.y+v.y,z:g.z+v.z},target:g,distance:_,min:Math.min(c.min,_),max:Math.max(c.max,(y??_)*kK),fitted:m!==null}}function FK(e,t){let{width:n,height:r}=e??{};if(!Number.isFinite(n)||!Number.isFinite(r)||n<=0||r<=0)return null;let i={left:0,right:n,top:0,bottom:r},a=(t??[]).filter(e=>e&&Number.isFinite(e.left)&&Number.isFinite(e.right)&&Number.isFinite(e.top)&&Number.isFinite(e.bottom));for(let e=0;ee.lefti.left&&e.topi.top);if(!e)break;i=[{...i,right:Math.max(i.left,e.left)},{...i,left:Math.min(i.right,e.right)},{...i,bottom:Math.max(i.top,e.top)},{...i,top:Math.min(i.bottom,e.bottom)}].reduce((e,t)=>{let n=e=>Math.max(0,e.right-e.left)*Math.max(0,e.bottom-e.top);return n(t)>n(e)?t:e})}let o={left:i.left,right:i.right,top:i.top,bottom:i.bottom,width:Math.max(0,i.right-i.left),height:Math.max(0,i.bottom-i.top)};return o.width>0&&o.height>0?o:null}function IK({target:e,distance:t,points:n,direction:r,fov:i,viewport:a,chrome:o,margin:s=.1}){let c={target:e,distance:t},l=LK(r),u=FK(a,o);if(!l||!u||!Number.isFinite(t)||!Number.isFinite(i)||!Array.isArray(n)||!n.length)return c;let{width:d,height:f}=a;if(u.width>=d&&u.height>=f)return c;let p=LK(RK(Math.abs(l.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},l));if(!p)return c;let m=RK(l,p),h=i*Math.PI/360,g=t=>{let r=1/0,i=-1/0,a=1/0,o=-1/0;for(let s of n){let n={x:s.x-e.x,y:s.y-e.y,z:s.z-e.z},c=t-zK(n,l);if(c<=0)continue;let u=2*c*Math.tan(h)/f;if(!(u>0))continue;let d=Number.isFinite(s.radius)?Math.max(0,s.radius):0,g=zK(n,p)/u,_=zK(n,m)/u,v=d/u;r=Math.min(r,g-v),i=Math.max(i,g+v),a=Math.min(a,_-v),o=Math.max(o,_+v)}return!Number.isFinite(r)||!Number.isFinite(a)?null:{width:i-r,height:o-a,x:(r+i)/2,y:(a+o)/2}},_=g(t);if(!_)return c;let v=1-Math.min(.9,Math.max(0,s)),y=Math.max(1,_.width/Math.max(1,u.width*v),_.height/Math.max(1,u.height*v)),b=t*y,x=y===1?_:g(b);if(!x)return c;let S=2*b*Math.tan(h)/f,C=u.left+u.width/2-d/2,w=u.top+u.height/2-f/2,T=(x.x-C)*S,E=(x.y+w)*S;return{distance:b,target:{x:e.x+p.x*T+m.x*E,y:e.y+p.y*T+m.y*E,z:e.z+p.z*T+m.z*E}}}function LK(e){if(!e)return null;let{x:t,y:n,z:r}=e;if(![t,n,r].every(Number.isFinite))return null;let i=Math.hypot(t,n,r);return i>0?{x:t/i,y:n/i,z:r/i}:null}function RK(e,t){return{x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x}}function zK(e,t){return e.x*t.x+e.y*t.y+e.z*t.z}function BK(e){return DK[e]??DK.GALAXY}function VK(e){if(!e)return null;let{system_x:t,system_y:n,system_z:r}=e;return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)?null:{position:{x:t+AK.x,y:n+AK.y,z:r+AK.z},target:{x:t,y:n,z:r}}}var HK=Object.freeze({width:132,height:30}),UK=Object.freeze({far:14,near:44}),WK=Object.freeze([0,-1,1,-2,2]),GK=4,KK=.034;function qK(e,{radius:t,aspect:n}){return e.scale.set(KK*n,KK,1),e.userData.baseOffsetY=t*2.2+1.2,e.position.set(0,e.userData.baseOffsetY,0),e.visible=!1,e.userData.codembleLabel=!0,e.userData.screenWidthFraction=KK*n,e.userData.screenHeightFraction=KK,e}function JK(e){let t=YK(e),n=new V,r=new V;function i({scene:e,camera:i,width:a,height:o,distance:s,distanceBounds:c,activeNodeId:l=null,neighborIds:u=null,chrome:d=[]}){let f=XK(e);for(let e of f)e.visible=!1;if(!f.length||!t.size)return Object.freeze({budget:0,shown:0,visibleIds:Object.freeze([])});let p=ZK(s,c),m=[];for(let e of f){let s=e.userData.nodeId,c=e.parent;if(!c)continue;c.getWorldPosition(r);let d=e.userData.baseOffsetY??0,f=QK(r,d,i,a,o,n);if(!f)continue;let p=QK(r,d+1,i,a,o,n),h=p?Math.abs(p.screenY-f.screenY):0;m.push({sprite:e,nodeId:s,origin:r.clone(),base:d,pixelsPerUnit:h,anchor:f,halfWidth:(e.userData.screenWidthFraction??.14)*o/2,halfHeight:(e.userData.screenHeightFraction??.034)*o/2,rank:s===l?-2:u?.has(s)?-1:t.get(s)??1/0})}m.sort((e,t)=>e.rank-t.rank||e.nodeId.localeCompare(t.nodeId));let h=new Set,g=[];for(let e of m){if(g.length>=p)break;let t=$K(e,{camera:i,width:a,height:o,projected:n,taken:h,chrome:d});if(t){for(let e of t.cells)h.add(e);e.sprite.position.y=e.base+t.offset,e.sprite.visible=!0,g.push(e.nodeId)}}return Object.freeze({budget:p,shown:g.length,visibleIds:Object.freeze(g)})}function a(e){for(let t of XK(e))t.visible=!1}return Object.freeze({hide:a,place:i})}function YK(e){let t=e.filter(e=>e.label).map(e=>({id:e.id,weight:(e.home?3e6:0)+(e.understood?1e6:0)+(e.centrality??0)*1e3})).sort((e,t)=>t.weight-e.weight||e.id.localeCompare(t.id));return new Map(t.map((e,t)=>[e.id,t]))}function XK(e){let t=[];return e.traverse(e=>{e.userData?.codembleLabel&&t.push(e)}),t}function ZK(e,t){let n=Math.max(1,t.max-t.min),r=1-Math.min(1,Math.max(0,(e-t.min)/n));return Math.round(UK.far+(UK.near-UK.far)*r)}function QK(e,t,n,r,i,a){if(a.set(e.x,e.y+t,e.z).project(n),a.z>1)return null;let o=(a.x*.5+.5)*r,s=(-a.y*.5+.5)*i;return o<0||o>r||s<0||s>i?null:{screenX:o,screenY:s}}function $K(e,{camera:t,width:n,height:r,projected:i,taken:a,chrome:o}){let s=e.pixelsPerUnit?(e.halfHeight*2+GK)/e.pixelsPerUnit:0;for(let c of WK){let l=c*s,u=c===0?e.anchor:QK(e.origin,e.base+l,t,n,r,i);if(!u||!eq(u,e,n,r)||!tq(u,e,o))continue;let d=nq(u,e);if(!d.some(e=>a.has(e)))return{cells:d,offset:l}}return null}function eq(e,{halfWidth:t,halfHeight:n},r,i){return e.screenX-t>=0&&e.screenX+t<=r&&e.screenY-n>=0&&e.screenY+n<=i}function tq(e,{halfWidth:t,halfHeight:n},r){if(!r?.length)return!0;let i=e.screenX-t,a=e.screenX+t,o=e.screenY-n,s=e.screenY+n;return!r.some(e=>ie.left&&oe.top)}function nq(e,{halfWidth:t,halfHeight:n}){let r=Math.floor((e.screenX-t)/HK.width),i=Math.floor((e.screenX+t)/HK.width),a=Math.floor((e.screenY-n)/HK.height),o=Math.floor((e.screenY+n)/HK.height),s=[];for(let e=r;e<=i;e+=1)for(let t=a;t<=o;t+=1)s.push(`${e}:${t}`);return s}var rq=128,iq=256,aq=.026;function oq(e,t){let n=document.createElement(`canvas`);n.width=e,n.height=e;let r=n.getContext(`2d`),i=r.createRadialGradient(e/2,e/2,0,e/2,e/2,e/2);for(let[e,n]of t)i.addColorStop(e,`rgba(255, 255, 255, ${n})`);r.fillStyle=i,r.fillRect(0,0,e,e);let a=new La(n);return a.colorSpace=ot,a}function sq(e){let t=document.createElement(`canvas`);t.width=e,t.height=e;let n=t.getContext(`2d`);n.strokeStyle=`rgba(255, 255, 255, 1)`,n.lineWidth=e*.05,n.beginPath(),n.arc(e/2,e/2,e*.4,0,Math.PI*2),n.stroke();let r=new La(t);return r.colorSpace=ot,r}function cq(e){let t=[];function n(e){let n=e.dispose.bind(e);return e.dispose=()=>{},t.push(n),e}let r=n(oq(rq,[[0,.85],[.25,.42],[.6,.1],[1,0]])),i=n(oq(iq,[[0,.32],[.45,.14],[.8,.03],[1,0]])),a=n(sq(rq)),o=new Map,s=new Map,c=null,l=new Map;function u(t){return l.has(t)||l.set(t,n(dq(t,e))),l.get(t)}function d(t){return o.has(t)||o.set(t,n(new bi({map:r,color:new H(t).multiply(new H(e.starHalo)),blending:2,transparent:!0,depthWrite:!1,opacity:.6}))),o.get(t)}return{halo(e,t){let n=new Pi(d(e.color));return n.scale.setScalar(t*6.5),n.renderOrder=-1,n},nebula(e,t){s.has(e)||s.set(e,n(new bi({map:i,color:new H(e),blending:2,transparent:!0,depthWrite:!1,opacity:.16})));let r=new Pi(s.get(e));return r.scale.setScalar(t),r.renderOrder=-2,r},spark(){c||=n(new bi({map:r,color:new H(e.star),blending:2,transparent:!0,depthWrite:!1,opacity:0}));let t=new Pi(c);return t.renderOrder=2,t},reticle(t){let n=new Pi(new bi({map:a,color:new H(e.orbit),transparent:!0,depthWrite:!1,depthTest:!1}));return n.scale.setScalar(t*5),n.renderOrder=3,n},label(e,t){let n=u(e),r=new Pi(n);return qK(r,{radius:t,aspect:n.userData.aspect??4}),r.renderOrder=4,r},guideLabel(e){let t=u(e),n=new Pi(t),r=t.userData.aspect??4;return n.scale.set(aq*r,aq,1),n.renderOrder=2,n},dispose(){for(let e of t)e();t.length=0,o.clear(),s.clear(),c=null,l.clear()}}}var lq=34,uq=12;function dq(e,t){let n=document.createElement(`canvas`),r=n.getContext(`2d`),i=`${lq}px "JetBrains Mono", ui-monospace, monospace`;r.font=i;let a=Math.ceil(r.measureText(e).width)+uq*2;n.width=a,n.height=58,r.font=i,r.textBaseline=`middle`,r.textAlign=`center`,r.fillStyle=t.labelPlate,fq(r,0,0,a,58,8),r.fill(),r.fillStyle=t.labelInk,r.fillText(e,a/2,30);let o=new La(n);o.colorSpace=ot;let s=new bi({map:o,transparent:!0,depthWrite:!1,depthTest:!1,sizeAttenuation:!1});s.userData.aspect=a/58;let c=s.dispose.bind(s);return s.dispose=()=>{o.dispose(),c()},s}function fq(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.arcTo(t+r,n,t+r,n+i,a),e.arcTo(t+r,n+i,t,n+i,a),e.arcTo(t,n+i,t,n,a),e.arcTo(t,n,t+r,n,a),e.closePath()}function pq(e){return Object.entries(e??{}).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}:${t}`).join(`|`)}function mq(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}function hq(e){let t=2166136261;for(let n=0;n>>0}function gq(e,t,n=3200,r=1600){let i=mq(hq(e)),a=new Float32Array(n*3),o=new Float32Array(n*3),s=new Float32Array(n),c=new H(t.starCool??t.nodeDim),l=new H(t.starPale??t.nodeBright),u=new H;for(let e=0;evq(t,e),r=e=>vq(t,e);return e.addEventListener(`pointerdown`,n,{capture:!0}),e.addEventListener(`lostpointercapture`,r,{capture:!0}),()=>{e.removeEventListener(`pointerdown`,n,{capture:!0}),e.removeEventListener(`lostpointercapture`,r,{capture:!0})}}var bq=2.4,xq=1.8,Sq=.62;function Cq(e,t){let n=new Ho({color:new H(t),dashSize:bq,gapSize:xq,transparent:!0,opacity:Sq,depthWrite:!1}),r=new Ta(new mi,n);return r.userData.codembleRouteLink=e,r.renderOrder=-1,r}function wq(e,t,n,r){let i=t?t.getPoints(30):[new V(n.x,n.y??0,n.z??0),new V(r.x,r.y??0,r.z??0)],a=e.geometry.getAttribute(`position`);return(!a||a.count!==i.length)&&e.geometry.setAttribute(`position`,new Qr(new Float32Array(i.length*3),3)),e.geometry.setFromPoints(i),e.geometry.computeBoundingSphere(),e.computeLineDistances(),!0}function Tq(e,t){e.traverse(e=>{let n=e.userData?.codembleRouteLink;!n||!e.material||e.material.color.set(t(n))})}var Eq=128,Dq=-.72;function Oq(e){let t=new Map;for(let n of e??[]){let e=n.system_orbit;if(!e||!Number.isInteger(e.ring)||e.ring<=0||!Number.isFinite(e.radius)||e.radius<=0)continue;t.has(e.ring)||t.set(e.ring,{callDepths:new Set,kinds:new Set,radii:new Set});let r=t.get(e.ring);r.callDepths.add(e.call_depth??null),r.kinds.add(e.kind),r.radii.add(e.radius)}return[...t.entries()].sort(([e],[t])=>e-t).map(([e,t])=>{let n=[...t.callDepths],r=n.length===1?n[0]:null,i=[...t.kinds].sort(),a=i.every(e=>e===`unreached`);return{ring:e,callDepth:r,kinds:i,radii:[...t.radii].sort((e,t)=>e-t),label:a?`No proven path`:r===null?`Mixed call evidence`:`Layer ${r}`,unproven:a}})}function kq(e,t,n){let r=new sr;r.name=`codemble-system-orbits`;for(let i of e){let e=i.unproven?new Ho({color:t.faded,dashSize:3,gapSize:2,opacity:.72,transparent:!0,depthWrite:!1}):new _a({color:t.route,opacity:.52,transparent:!0,depthWrite:!1});for(let t of i.radii){let n=new Da(new mi().setFromPoints(Array.from({length:Eq},(e,n)=>{let r=n/Eq*Math.PI*2;return new V(Math.cos(r)*t,0,Math.sin(r)*t)})),e);n.userData.codembleOrbitGuide=!0,n.renderOrder=-1,i.unproven&&n.computeLineDistances(),r.add(n)}let a=Math.max(...i.radii),o=n.guideLabel(i.label);o.position.set(Math.cos(Dq)*a,2.5,Math.sin(Dq)*a),o.userData.codembleOrbitGuideLabel=!0,r.add(o)}return r}function Aq(e){let t=new Set;e.traverse(e=>{e.userData?.codembleOrbitGuide&&(e.geometry?.dispose(),e.material&&t.add(e.material))});for(let e of t)e.dispose()}var jq=.16,Mq=1.5,Nq=110,Pq=6,Fq=Object.freeze({requestFrame:e=>requestAnimationFrame(e),cancelFrame:e=>cancelAnimationFrame(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e),setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),now:()=>performance.now()}),Iq=Object.freeze({rendererFactory:e=>XW({controlType:`orbit`})(e),assertWebGL(){let e=document.createElement(`canvas`);if(!e.getContext(`webgl2`)&&!e.getContext(`webgl`))throw Error(`Codemble needs WebGL to draw your galaxy. Enable WebGL and reload.`)},ResizeObserver:globalThis.ResizeObserver,createDressing:cq,createBodyGeometry:nG,createBodySpin:aG,createSystemOrbitGuides:kq,disposeSystemOrbitGuides:Aq,createStarfield:gq,createGalacticGlow:_q,attachBloom:zd,guardOrbitPointerState:yq,runDawnSequence:yG,createNameAtlas:JK,documentElement:()=>document.documentElement,search:()=>window.location.search});function Lq({host:e,palette:t,reducedMotion:n,onHoverNode:r,onAdvance:i,onDawnConsumed:a,dependencies:o={},clock:s=Fq}){let c={...Iq,...o},l=!1,u=null,d=null,f=null,p=null,m=null,h=null,g=null,_=()=>{},v=()=>{},y=null,b=null,x=!1,S=null,C={activeId:null,neighborIds:new Set},w=null,T=null,E=()=>{},D=null,O=null,k=null,A=null,ee=null,te=e=>uK(e,C,t),j=e=>dK(e,C,t,zq),ne=e=>{if(e.focusDim)return .4;let t=Math.min(2.2,.45+(e.weight??1)*.25);if(!C.activeId)return t;let n=zq(e.source),r=zq(e.target);return n===C.activeId||r===C.activeId?t+.9:t};function re(){c.assertWebGL(),p=c.createDressing(t),m=c.createBodyGeometry(),d=c.rendererFactory(e).backgroundColor(t.ground).showNavInfo(!1).enableNavigationControls(!0).enableNodeDrag(!1).warmupTicks(0).cooldownTicks(0).nodeId(`id`).nodeLabel(yK).nodeVal(`val`).nodeColor(te).nodeRelSize(SK).nodeResolution(8).nodeOpacity(.82).nodeThreeObject(e=>Rq(e,t,p,S,{level:u?.level,bodyGeometry:m})).nodeThreeObjectExtend(!0).linkColor(j).linkLabel(bK).linkOpacity(.5).linkWidth(ne).linkCurvature(.12).linkThreeObject(e=>e.certain?null:Cq(e,j(e))).linkPositionUpdate((e,{start:t,end:n},r)=>!r.certain&&wq(e,r.__curve,t,n)).linkVisibility(e=>!(u?.mode===`easy`&&e.focusDim)).linkHoverPrecision(4).linkDirectionalArrowRelPos(1).linkDirectionalArrowColor(j).linkDirectionalParticles(e=>e.kind===`call`&&e.certain&&!e.focusDim&&!n?2:0).linkDirectionalParticleSpeed(.006).linkDirectionalParticleWidth(1.1).linkDirectionalParticleColor(()=>t.orbit).onNodeHover(t=>{l||(e.style.cursor=t?`pointer`:`default`,r(t?.id??null))}).onNodeClick(e=>{l||i(e)}),y=s.requestFrame(()=>{l||e.querySelector(`.scene-nav-info`)?.remove()}),f=d.controls(),f.enablePan=!1,f.enableDamping=!n,f.dampingFactor=.12,f.rotateSpeed=.55,f.zoomSpeed=.7,f.minPolarAngle=jq,f.maxPolarAngle=Mq;let a=()=>{l||(x=!0)};f.addEventListener(`start`,a),v=()=>f?.removeEventListener(`start`,a),_=c.guardOrbitPointerState(e,f),h=c.attachBloom(d,e.getBoundingClientRect()),g=new c.ResizeObserver(([e])=>{if(l)return;let{width:t,height:n}=e.contentRect;d.width(t).height(n);let r=jK(e.contentRect);!x&&r!==null&&b?.(r)}),g.observe(e)}function M(t,n){if(!u)return;let{data:r,level:i,orbitPlan:a}=u,o=cG({host:e,renderer:d}),s=PK({level:i,nodes:r.nodes,orbitPlan:a,fov:d.camera()?.fov,aspect:n??jK(e.getBoundingClientRect())??jK({width:d.width(),height:d.height()}),viewport:o.viewport,chrome:i===jG.SYSTEM?o.clickObstructions:[]});f.minDistance=s.min,f.maxDistance=s.max,d.cameraPosition(s.position,s.target,t)}function N(){E(),E=()=>{},T&&=(d.scene().remove(T),c.disposeSystemOrbitGuides(T),null),!(u.level===jG.GALAXY||!u.orbitPlan.length)&&(T=c.createSystemOrbitGuides(u.orbitPlan,t,p),d.scene().add(T),E=c.createBodySpin(d.scene(),{reducedMotion:n}))}function ie(){ae();let e=c.createStarfield(u.starfieldSeed,t),n=c.createGalacticGlow(t);d.scene().add(e),d.scene().add(n),w={starfield:e,glow:n}}function ae(){!w||!d||(d.scene().remove(w.starfield),w.starfield.geometry?.dispose(),w.starfield.material?.dispose(),d.scene().remove(w.glow),w.glow.material?.map?.dispose(),w.glow.material?.dispose(),w=null)}function oe(){D&&=(D.cancelled=!0,D.frame!==null&&s.cancelFrame(D.frame),D.stop(),null)}function P(e){if(O=e,a?.(e),n)return;oe();let r={cancelled:!1,frame:null,stop:()=>{}};D=r;let i=n=>{if(l||r.cancelled||D!==r)return;let a=d.scene();if(a.getObjectByName(`codemble-system-${e}`)||n>=Pq){r.frame=null,r.stop=c.runDawnSequence({scene:a,regionId:e,palette:t,dressing:p,routes:u?.graph?.region_edges??[],hopsById:new Map((u?.graph?.regions??[]).map(e=>[e.id,e.hops_from_home]))});return}r.frame=s.requestFrame(()=>i(n+1))};r.frame=s.requestFrame(()=>i(0))}function se(){A!==null&&s.clearInterval(A),k&&d&&k.hide(d.scene()),A=null,k=c.createNameAtlas(u.data.nodes);let t=d.scene(),n=()=>{if(!(l||!k))try{let n=d.camera(),r=BK(u.level),i=f?{min:f.minDistance??r.min,max:f.maxDistance??r.max}:r,a=f?n.position.distanceTo(f.target):n.position.length(),o=cG({host:e,renderer:d});k.place({scene:t,camera:n,width:d.width(),height:d.height(),distance:a,distanceBounds:i,activeNodeId:C.activeId,neighborIds:C.neighborIds,chrome:o.nameObstructions})}catch(e){A!==null&&s.clearInterval(A),A=null,k.hide(t),console.error(`Codemble: label declutter failed, names disabled`,e)}};n(),A=s.setInterval(n,Nq)}function F(){ee!==null&&s.clearTimeout(ee),ee=null,!(!new URLSearchParams(c.search()).has(`benchmark`)||u.data.nodes.length<900)&&(c.documentElement().removeAttribute(`data-codemble-fps`),ee=s.setTimeout(()=>{if(ee=null,l)return;let e=d.renderer(),t=d.postProcessingComposer(),n=s.now();for(let e=0;e<60;e+=1)t.render();e.getContext().finish();let r=s.now()-n;c.documentElement().dataset.codembleFps=(60*1e3/r).toFixed(1)},1e3))}function ce(e){if(l)return;let t=u;if(u=e,(!t||t.data!==e.data||t.level!==e.level||t.mode!==e.mode||t.orbitPlan!==e.orbitPlan)&&(d.nodeResolution(e.data.nodes.length>=900?4:8).nodeThreeObjectExtend(e.level===jG.GALAXY).linkVisibility(t=>!(e.mode===`easy`&&t.focusDim)).linkDirectionalArrowLength(e.level===jG.GALAXY?0:3.2).graphData(e.data),M(xG(420,{active:e.firstFlightActive,reducedMotion:n})),x=!1,b=e=>M(0,e)),(!t||t.level!==e.level||t.orbitPlan!==e.orbitPlan)&&N(),(!t||t.starfieldSeed!==e.starfieldSeed)&&ie(),e.level===jG.GALAXY?e.pendingDawnRegionId&&e.pendingDawnRegionId!==O&&P(e.pendingDawnRegionId):oe(),!t||t.data!==e.data||t.hoverNodeId!==e.hoverNodeId||t.focusedNodeId!==e.focusedNodeId||t.level!==e.level||t.selectedNode?.id!==e.selectedNode?.id){let t=e.hoverNodeId??e.focusedNodeId??(e.level===jG.STUDY?e.selectedNode?.id??null:null),n=new Set;if(t)for(let r of e.data.links){let e=zq(r.source),i=zq(r.target);e===t&&n.add(i),i===t&&n.add(e)}C={activeId:t,neighborIds:n},d.nodeColor(e=>te(e)).linkColor(e=>j(e)).linkWidth(e=>ne(e)).linkDirectionalArrowColor(e=>j(e)),Tq(d.scene(),j)}if((!t||t.focusedNodeId!==e.focusedNodeId)&&(S=e.focusedNodeId,d.refresh()),(!t||t.data.nodes!==e.data.nodes||t.hoverNodeId!==e.hoverNodeId||t.focusedNodeId!==e.focusedNodeId||t.level!==e.level)&&se(),(!t||t.data.nodes.length!==e.data.nodes.length)&&F(),e.level===jG.STUDY&&(!t||t.level!==e.level||t.selectedNode!==e.selectedNode)){let t=VK(e.selectedNode);t&&d.cameraPosition(t.position,t.target,420)}}function le(){l||(l=!0,g?.disconnect(),g=null,v(),v=()=>{},y!==null&&s.cancelFrame(y),y=null,_(),_=()=>{},E(),E=()=>{},T&&d&&(d.scene().remove(T),c.disposeSystemOrbitGuides(T),T=null),oe(),A!==null&&s.clearInterval(A),A=null,k&&d&&k.hide(d.scene()),k=null,ee!==null&&s.clearTimeout(ee),ee=null,ae(),d?.pauseAnimation(),h?.dispose(),h=null,d?._destructor(),p?.dispose(),p=null,m?.dispose(),m=null,f=null,d=null,e.replaceChildren(),b=null)}try{re()}catch(e){throw le(),e}return Object.freeze({update:ce,dispose:le})}function Rq(e,t,n,r,{level:i,bodyGeometry:a}={}){let o=new sr;o.name=e.kind===`region`?`codemble-system-${e.id}`:`codemble-node-${e.id}`;let s=wK(e),c=i&&i!==jG.GALAXY&&a;c&&o.add(iG({node:e,color:e.color,palette:t,radius:s,geometry:a}));let l=lK(e);if(!e.focusDim&&!l&&!c&&o.add(n.halo(e,s)),e.kind===`region`&&!l){let r=t.nebula[e.language];r&&o.add(n.nebula(r,s*14))}if(e.label){let t=n.label(e.label,s);t.userData.nodeId=e.id,o.add(t)}if(e.home){let e=new na(new bo(s*1.7,Math.max(.18,s*.07),8,36),new Wi({color:t.home}));e.rotation.x=Math.PI/2.8,o.add(e)}if(e.kind===`class`&&!e.focusDim){let e=new na(new bo(s*1.45,Math.max(.1,s*.045),6,28),new Wi({color:t.route}));e.rotation.x=Math.PI/2.4,o.add(e)}if(e.selected){let e=new na(new bo(s*2.1,Math.max(.16,s*.05),6,24),new Wi({color:t.orbit}));e.rotation.x=Math.PI/2.8,o.add(e)}return e.id===r&&o.add(n.reticle(s)),o}function zq(e){return typeof e==`object`&&e?e.id:e}var Bq=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),$=o(((e,t)=>{t.exports=Bq()}))();function Vq({graph:e,level:t,region:n,selectedNode:r,hoverNodeId:i,pendingDawnRegionId:a,revealedRegionIds:o,mode:s,firstFlightActive:c,onHoverNode:l,onAdvance:u,onRetreat:d,onDawnConsumed:f}){let p=(0,_.useRef)(null),m=(0,_.useRef)(null),h=(0,_.useRef)(u),g=(0,_.useRef)(d),v=(0,_.useRef)(l),y=(0,_.useRef)(f),[b,x]=(0,_.useState)(0),[S,C]=(0,_.useState)(!1),[w,T]=(0,_.useState)(``),E=(0,_.useMemo)(Uq,[]),D=(0,_.useMemo)(Bd,[]),O=pq(e.file_hashes),k=(0,_.useMemo)(()=>t===jG.GALAXY?fK(e,E,o):pK(e,n?.id,E,{selectedId:r?.id}),[e,t,E,n?.id,o,r?.id]),A=(0,_.useMemo)(()=>t===jG.GALAXY?[]:Oq(k.nodes),[k.nodes,t]);(0,_.useEffect)(()=>{h.current=u,g.current=d,v.current=l,y.current=f},[u,d,l,f]),(0,_.useEffect)(()=>{let e=p.current;if(e)try{let t=Lq({host:e,palette:E,reducedMotion:D,onHoverNode:e=>v.current(e),onAdvance:e=>h.current(e),onDawnConsumed:e=>y.current?.(e)});return m.current=t,T(``),()=>{t.dispose(),m.current===t&&(m.current=null)}}catch(e){let t=e instanceof Error?e.message:String(e);T(t.startsWith(`Codemble needs WebGL`)?t:`The galaxy could not start: ${t}`);return}},[E,D]),(0,_.useEffect)(()=>{m.current?.update({graph:e,data:k,level:t,mode:s,orbitPlan:A,selectedNode:r,hoverNodeId:i,pendingDawnRegionId:a,starfieldSeed:O,firstFlightActive:c,focusedNodeId:S?k.nodes[b]?.id??null:null})},[k,c,b,e,i,S,t,s,A,a,r,O]),(0,_.useEffect)(()=>{x(0),C(!1)},[k,t,s,A]);let ee=k.nodes[b]??null;function te(e){if(e.key===`ArrowRight`||e.key===`ArrowDown`)e.preventDefault(),x(e=>(e+1)%Math.max(1,k.nodes.length));else if(e.key===`ArrowLeft`||e.key===`ArrowUp`)e.preventDefault(),x(e=>(e-1+k.nodes.length)%Math.max(1,k.nodes.length));else if(e.key===`Enter`&&ee)e.preventDefault(),h.current(ee);else if(e.key===`Escape`||e.key===`Backspace`){if(e.key===`Escape`&&c)return;e.preventDefault(),g.current()}}return w?(0,$.jsxs)(`section`,{className:`webgl-error`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The sky could not open.`}),(0,$.jsx)(`p`,{children:w}),(0,$.jsxs)(`p`,{children:[`The `,s===`easy`?`Diagram`:`Map`,` layer works without WebGL — switch to it at the top of the window to explore the same code.`]})]}):(0,$.jsxs)(`div`,{className:`galaxy-frame`,role:`application`,tabIndex:`0`,"aria-label":`Codemble ${t.toLowerCase()} view. Drag to orbit, scroll to zoom. Use arrow keys to choose a node and Enter to move closer.${t===jG.GALAXY?``:` Solid guides are parser-proven call layers; a dashed guide has no proven call path.`}`,onFocus:()=>C(!0),onBlur:()=>{v.current(null)},onKeyDown:te,children:[(0,$.jsx)(`div`,{ref:p,className:`galaxy-canvas`,"aria-hidden":`true`,onPointerLeave:()=>v.current(null)}),S&&ee?(0,$.jsx)(`output`,{className:`keyboard-focus`,"aria-live":`polite`,children:yK(ee)}):null]})}function Hq(e){let t=document.createElement(`canvas`).getContext(`2d`);t.fillStyle=`#000000`,t.fillStyle=e,t.fillRect(0,0,1,1);let[n,r,i]=t.getImageData(0,0,1,1).data;return`rgb(${n}, ${r}, ${i})`}function Uq(){let e=getComputedStyle(document.documentElement),t=t=>Hq(e.getPropertyValue(t).trim());return Object.freeze({ground:t(`--cm-sky`),skyGlow:t(`--cm-sky-glow`),home:t(`--cm-ink`),orbit:t(`--cm-orbit`),nodeBright:t(`--cm-node-bright`),node:t(`--cm-node-mid`),nodeDim:t(`--cm-node-unlit`),starCool:t(`--cm-star-cool`),starPale:t(`--cm-star-pale`),route:t(`--cm-route`),routePossible:t(`--cm-route-possible`),faded:t(`--cm-hairline-soft`),star:t(`--cm-star-high`),starHalo:t(`--cm-star-halo`),nebula:Object.freeze(Object.fromEntries(Object.entries(zG).map(([e,n])=>[e,t(n)]))),communities:Object.freeze(Array.from({length:8},(e,n)=>t(`--cm-com-${n}`))),labelPlate:e.getPropertyValue(`--cm-label-plate`).trim(),labelInk:e.getPropertyValue(`--cm-label-ink`).trim()})}function Wq({hint:e,onFollow:t,firstFlight:n}){let r=(0,_.useRef)(null),i=(0,_.useRef)(!1);if((0,_.useLayoutEffect)(()=>{n?.active&&!i.current&&r.current?.focus(),i.current=n?.active===!0},[n?.active]),n?.active){let{stop:e,index:t,total:i,mode:a}=n;return(0,$.jsxs)(`output`,{className:`hint-chip first-flight`,"aria-live":`polite`,"data-first-flight":`active`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),(0,$.jsxs)(`strong`,{children:[`First Flight · `,t+1,` of `,i]}),(0,$.jsx)(`span`,{className:`first-flight__system`,children:e.id}),(0,$.jsxs)(`small`,{children:[a===`easy`?`${e.language} file`:`${e.language} system`,` · used by ${e.usedBy} · uses ${e.uses}`]}),(0,$.jsxs)(`span`,{className:`first-flight__actions`,children:[(0,$.jsx)(`button`,{type:`button`,disabled:t===0,onClick:n.onBack,children:`Back`}),t+1{let e=i.current;e&&!e.open&&e.showModal(),a.current?.focus()},[]);function c(){i.current?.close(),t()}return(0,$.jsxs)(`dialog`,{ref:i,className:`coach-marks`,"aria-labelledby":`coach-heading`,onCancel:e=>{e.preventDefault(),c()},children:[(0,$.jsxs)(`p`,{className:`coach-marks__progress`,children:[`Step `,n+1,` of `,o.length]}),(0,$.jsx)(`h1`,{id:`coach-heading`,children:s.title}),(0,$.jsx)(`p`,{children:s.body}),(0,$.jsxs)(`div`,{className:`coach-marks__actions`,children:[(0,$.jsx)(`button`,{type:`button`,className:`coach-skip`,onClick:c,children:`Skip`}),(0,$.jsx)(`button`,{ref:a,type:`button`,className:`check-primary`,onClick:()=>n+1=r&&o<=r+e&&s>=i&&s<=i+t}var eJ=.35;function tJ(e,t,n,r){if(!e||!t||!n||!r)return 1;let i=Zq(e,t,n,r);return i>=.35?i:Xq(Math.min(eJ,e/n))}function nJ(){let e=new Map;return Object.freeze({read(t){let n=e.get(t);return n?{...n}:null},write(t,n){e.set(t,{scale:Xq(n.scale),scrollLeft:Math.max(0,n.scrollLeft),scrollTop:Math.max(0,n.scrollTop)})},clear(){e.clear()}})}var rJ=1.25;function iJ({contentWidth:e,contentHeight:t,label:n,viewKey:r,viewportStore:i,focusPoint:a,children:o}){let s=(0,_.useRef)(null),c=(0,_.useRef)(i.read(r)),[l,u]=(0,_.useState)(()=>c.current?.scale??1),[d,f]=(0,_.useState)(!1),p=(0,_.useRef)(null),m=(0,_.useRef)(!1),h=Math.round(l*100),g=(0,_.useCallback)(()=>{let e=s.current;e&&i.write(r,{scale:l,scrollLeft:e.scrollLeft,scrollTop:e.scrollTop})},[l,r,i]),v=(0,_.useCallback)(()=>{let n=s.current?.getBoundingClientRect();!n||!e||!t||u(tJ(n.width,n.height,e,t))},[e,t]);(0,_.useLayoutEffect)(()=>{let e=s.current;if(!e||m.current)return;let t=0;return t=requestAnimationFrame(()=>{let t=e.getBoundingClientRect(),n=c.current,r=n&&(!a||$q({viewportWidth:t.width,viewportHeight:t.height,scale:n.scale,scrollLeft:n.scrollLeft,scrollTop:n.scrollTop,point:a}));if(r)e.scrollLeft=n.scrollLeft,e.scrollTop=n.scrollTop;else if(t.width<640&&a){let n=Qq({viewportWidth:t.width,viewportHeight:t.height,scale:l,point:a});e.scrollLeft=n.scrollLeft,e.scrollTop=n.scrollTop}else n&&!r&&(e.scrollLeft=0,e.scrollTop=0);m.current=!0,g()}),()=>cancelAnimationFrame(t)},[a,g,l]),(0,_.useEffect)(()=>{if(!m.current)return;let e=requestAnimationFrame(g);return()=>cancelAnimationFrame(e)},[g]),(0,_.useEffect)(()=>{let e=s.current;if(!e)return;let t=null,n=new ResizeObserver(([n])=>{let{width:r,height:i}=n.contentRect,o=t;if(t={width:r,height:i},!o||!a||!m.current||Math.abs(r-o.width)<1&&Math.abs(i-o.height)<1||$q({viewportWidth:r,viewportHeight:i,scale:l,scrollLeft:e.scrollLeft,scrollTop:e.scrollTop,point:a}))return;let s=Qq({viewportWidth:r,viewportHeight:i,scale:l,point:a});e.scrollLeft=s.scrollLeft,e.scrollTop=s.scrollTop,g()});return n.observe(e),()=>n.disconnect()},[a,g,l]);function y(e){if(e.button!==0||e.target.closest(`[role='button']`))return;let t=s.current;p.current={x:e.clientX,y:e.clientY,left:t.scrollLeft,top:t.scrollTop},f(!0),t.setPointerCapture(e.pointerId)}function b(e){if(!p.current)return;let t=s.current;t.scrollLeft=p.current.left-(e.clientX-p.current.x),t.scrollTop=p.current.top-(e.clientY-p.current.y)}function x(e){p.current&&(p.current=null,f(!1),s.current?.releasePointerCapture?.(e.pointerId))}return(0,$.jsxs)(`div`,{className:`map-canvas`,children:[(0,$.jsxs)(`div`,{className:`map-zoom`,role:`group`,"aria-label":`Zoom ${n}`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom out`,disabled:l<=.05,onClick:()=>u(e=>Xq(e/rJ)),children:`−`}),(0,$.jsx)(`button`,{type:`button`,onClick:v,children:`Fit`}),(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Reset zoom to 100%. Current zoom ${h}%.`,title:`Reset zoom to 100%`,onClick:()=>u(1),children:[h,`%`]}),(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom in`,disabled:l>=2.5,onClick:()=>u(e=>Xq(e*rJ)),children:`+`})]}),(0,$.jsx)(`div`,{ref:s,className:`map-scroll`,"data-panning":d||void 0,onPointerDown:y,onPointerMove:b,onPointerUp:x,onPointerCancel:x,onScroll:()=>{m.current&&g()},children:(0,$.jsx)(`div`,{className:`map-canvas__sized`,style:{width:e*l,height:t*l},children:o})})]})}function aJ(e){return BG(e)??`var(--cm-hairline)`}function oJ(e){return e.map(([e,t],n)=>`${n===0?`M`:`L`} ${e} ${t}`).join(` `)}function sJ(e){return 1+Math.min(2.5,(Math.max(1,e)-1)*.5)}var cJ=13,lJ=.62,uJ=14,dJ=6;function fJ(e,t){let n=t-uJ-dJ,r=Math.max(1,Math.floor(n/(cJ*lJ)));return e.length<=r?e:`${e.slice(0,Math.max(1,r-1))}…`}function pJ({data:e,mapTab:t,mode:n,communityIndexByRegion:r,selectedRegionId:i,hasEntrypointCandidates:a,unsupportedSources:o,importCycles:s,error:c,onSelectTab:l,onSelectRegion:u,onSelectNode:d,onRetry:f,viewportStore:p,languageFocusLabel:m=``,onClearLanguageFocus:h,children:g}){return(0,$.jsxs)(`section`,{className:`map-view`,"aria-label":`Two-dimensional project map`,children:[(0,$.jsxs)(`nav`,{className:`map-tabs`,"aria-label":`Map view`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`architecture`,onClick:()=>l(`architecture`),children:n===`easy`?`How it fits together`:`Architecture`}),(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`workflow`,onClick:()=>l(`workflow`),children:n===`easy`?`What runs first`:`Workflow`})]}),g,c?(0,$.jsxs)(`div`,{className:`map-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The map did not load.`}),(0,$.jsxs)(`p`,{children:[c,` The galaxy layer is unaffected.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:f,children:`Try again`})]}):e?t===`architecture`?(0,$.jsx)(hJ,{architecture:e.architecture,mode:n,communityIndexByRegion:r,selectedRegionId:i,hasEntrypointCandidates:a,onSelectRegion:u,viewportStore:p,languageFocusLabel:m,onClearLanguageFocus:h}):(0,$.jsx)(gJ,{workflow:e.workflow,mode:n,selectedRegionId:i,hasEntrypointCandidates:a,onSelectNode:d,viewportStore:p,languageFocusLabel:m,onClearLanguageFocus:h}):(0,$.jsx)(`p`,{className:`map-loading`,role:`status`,children:`Laying out parser evidence…`}),UG(o,n)?(0,$.jsxs)(`p`,{className:`map-note`,children:[UG(o,n),n===`easy`?` — Codemble does not read that language yet, so none of it is drawn here.`:` — outside every registered adapter; no structure is inferred for them.`]}):null,gK(s,n)?(0,$.jsx)(`p`,{className:`map-note`,children:gK(s,n)}):null]})}var mJ=8;function hJ({architecture:e,mode:t,communityIndexByRegion:n,selectedRegionId:r,hasEntrypointCandidates:i,onSelectRegion:a,viewportStore:o,languageFocusLabel:s,onClearLanguageFocus:c}){let l=new Map(e.boxes.map(e=>[e.id,e])),[u,d]=(0,_.useState)(e.unreachable.length<=mJ),f=new Set(e.unreachable),p=e.boxes.length>0&&e.boxes.every(e=>f.has(e.id)),m=u||p,h=m?e.boxes:e.boxes.filter(e=>!f.has(e.id)),g=m?e.height:h.reduce((e,t)=>Math.max(e,t.y+t.height),0),v=l.get(r)??l.get(e.home)??e.boxes.find(e=>e.home)??e.boxes[0],y=v?{x:v.x+32+v.width/2,y:v.y+32+v.height/2}:null;return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(iJ,{contentWidth:e.width+64,contentHeight:g+64,label:`the architecture map`,viewKey:`architecture:${e.home??`none`}`,viewportStore:o,focusPoint:y,children:(0,$.jsxs)(`svg`,{className:`architecture-map`,width:`100%`,height:`100%`,preserveAspectRatio:`xMidYMin meet`,viewBox:`-32 -32 ${e.width+64} ${g+64}`,role:`group`,"aria-label":e.home?`${e.boxes.length} modules in ${e.layer_count} import layers from Home`:`${e.boxes.length} modules in ${e.layer_count} import layers, measured from the modules nothing imports`,children:[(0,$.jsxs)(`defs`,{children:[(0,$.jsx)(`marker`,{id:`architecture-arrow`,className:`architecture-map__arrow`,markerWidth:`9`,markerHeight:`8`,refX:`9`,refY:`4`,orient:`auto`,markerUnits:`userSpaceOnUse`,children:(0,$.jsx)(`path`,{d:`M 0 0 L 9 4 L 0 8 Z`,fill:`currentColor`})}),(0,$.jsx)(`marker`,{id:`architecture-cycle-arrow`,className:`architecture-map__arrow is-cycle`,markerWidth:`9`,markerHeight:`8`,refX:`9`,refY:`4`,orient:`auto`,markerUnits:`userSpaceOnUse`,children:(0,$.jsx)(`path`,{d:`M 0 0 L 9 4 L 0 8 Z`,fill:`currentColor`})})]}),(0,$.jsx)(`g`,{className:`architecture-map__edges`,children:e.edges.map(e=>{let t=l.get(e.src),n=l.get(e.dst);return!t||!n||!m&&(f.has(e.src)||f.has(e.dst))?null:(0,$.jsx)(`path`,{d:oJ(e.points),strokeDasharray:e.certain?void 0:`5 4`,strokeWidth:sJ(e.weight),markerEnd:`url(#${e.cycle?`architecture-cycle-arrow`:`architecture-arrow`})`,className:`architecture-map__edge${e.cycle?` is-cycle`:``}${e.certain?``:` is-possible`}`},`${e.src}->${e.dst}`)})}),h.map(e=>(0,$.jsxs)(`g`,{className:`architecture-map__box`,"data-understood":e.understood,"data-home":e.home,"data-reachable":e.reachable,"data-partial":e.partial,style:n?.has(e.id)?{"--box-com":`var(--cm-com-${n.get(e.id)})`}:void 0,"data-selected":e.id===r,transform:`translate(${e.x} ${e.y})`,role:`button`,tabIndex:0,"aria-label":`${e.label}, ${e.node_count} ${e.node_count===1?`structure`:`structures`}, ${e.loc} ${e.loc===1?`line`:`lines`}${e.understood?`, understood`:`, not yet understood`}${e.home?`, Home`:``}${e.reachable?``:`, no import route from Home`}${e.partial?`, unchartable, syntax error`:``}`,onClick:()=>a(e.id),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),a(e.id))},children:[(0,$.jsxs)(`title`,{children:[e.label,e.partial?` — unchartable, syntax error`:``]}),(0,$.jsx)(`rect`,{width:e.width,height:e.height,rx:`3`}),(0,$.jsx)(`rect`,{className:`box-tint`,width:`4`,height:e.height,style:{fill:aJ(e.language)}}),e.partial?(0,$.jsx)(`path`,{className:`box-partial`,d:`M ${e.width-16} 2 L ${e.width-2} 2 L ${e.width-2} 16 Z`}):null,(0,$.jsx)(`text`,{x:uJ,y:`24`,children:fJ(e.short_label??e.label,e.width)}),(0,$.jsx)(`text`,{className:`box-meta`,x:`14`,y:`42`,children:t===`easy`?`${e.node_count} ${e.node_count===1?`piece`:`pieces`}`:`${e.node_count} ${e.node_count===1?`node`:`nodes`} · ${e.loc} LOC`})]},e.id))]})}),e.home?null:(0,$.jsxs)(`p`,{className:`map-note`,children:[`No Home is selected, so these layers run from the modules nothing else imports rather than from your entrypoint. Both are read from your imports, not guessed.`,` `,i?`Pick your starting point with “Change Home” to see the same modules layered by what the project runs first.`:`This project has no parser-recognisable entrypoint, so there is no “runs first” order to layer by instead.`]}),p?(0,$.jsxs)(`p`,{className:`map-note`,children:[s?`Home is not written in ${s}, so none of these ${e.boxes.length} ${e.boxes.length===1?`module`:`modules`} has an import route to it. They are drawn in file order rather than layered by guesswork.`:`None of these ${e.boxes.length} ${e.boxes.length===1?`module`:`modules`} has an import route from Home, so they are drawn in file order rather than layered by guesswork.`,` `,s&&c?(0,$.jsx)(`button`,{type:`button`,className:`map-note__toggle`,onClick:c,children:`Show all languages`}):null]}):e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`module has`:`modules have`,` no import route from Home`,u?`, so ${e.unreachable.length===1?`it sits`:`they sit`} in the bottom rows rather than being placed by guesswork.`:`. They are folded away so your connected code stays readable — nothing is hidden from the count.`,` `,(0,$.jsx)(`button`,{type:`button`,className:`map-note__toggle`,"aria-expanded":u,onClick:()=>d(e=>!e),children:u?`Fold them away`:`Show them`})]}):null]})}function gJ({workflow:e,mode:t,selectedRegionId:n,hasEntrypointCandidates:r,onSelectNode:i,viewportStore:a,languageFocusLabel:o,onClearLanguageFocus:s}){if(e.root&&e.nodes.length===0)return(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:o?`Nothing in ${o} runs from Home.`:`Nothing runs from Home yet.`}),(0,$.jsx)(`p`,{children:o?`This tab follows what Home calls, and Home is not written in ${o} — so no ${o} structure appears on a parser-proven call route. The other tab still maps how these modules import each other.`:`This tab follows what Home calls, and the parser proved no call route out of it yet.`}),o&&s?(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Show all languages`}):null]});if(!e.root)return r?(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No Home is selected.`}),(0,$.jsx)(`p`,{children:`The workflow tree starts at your entrypoint. Pick Home and this tab will show what runs first, then what that calls.`})]}):(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No “runs first” order to show.`}),(0,$.jsx)(`p`,{children:`This project has no parser-recognisable entrypoint — nothing here declares a startup structure Codemble recognises, and it will not guess one. The other tab still maps how your modules import each other.`})]});let c=new Map(e.nodes.map(e=>[e.order,e])),l=e.nodes.find(t=>t.id===e.root)??e.nodes[0],u=l?{x:l.x+24,y:l.y+32}:null;return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(iJ,{contentWidth:e.width+32,contentHeight:e.height+32,label:`the workflow tree`,viewKey:`workflow:${e.root}`,viewportStore:a,focusPoint:u,children:(0,$.jsxs)(`svg`,{className:`workflow-tree`,width:`100%`,height:`100%`,preserveAspectRatio:`xMinYMin meet`,viewBox:`-16 -16 ${e.width+32} ${e.height+32}`,role:`group`,"aria-label":`Call tree from ${e.root}, ${e.nodes.length} steps deep to ${e.depth_count} levels`,children:[(0,$.jsx)(`g`,{className:`workflow-tree__edges`,children:e.nodes.map(e=>{if(e.parent===null)return null;let t=[...c.values()].filter(t=>t.id===e.parent&&t.order(0,$.jsxs)(`g`,{className:`workflow-tree__row`,"data-understood":e.understood,"data-cut":e.cut??void 0,"data-partial":e.partial,"data-relation":e.relation,"data-selected":e.region===n,transform:`translate(${e.x} ${e.y})`,role:`button`,tabIndex:0,"aria-label":`${e.label} at ${e.file}:${e.lineno}${e.certain?``:`, possible call`}${e.cut===`cycle`?`, repeats an earlier step`:``}${e.cut===`repeat`?`, already shown above`:``}${e.partial?`, unchartable, syntax error`:``}`,onClick:()=>i(e.id),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),i(e.id))},children:[(0,$.jsx)(`circle`,{cx:`8`,cy:`16`,r:`4`}),(0,$.jsxs)(`text`,{x:`20`,y:`20`,children:[(0,$.jsx)(`tspan`,{children:e.label}),(0,$.jsxs)(`tspan`,{className:`row-meta`,children:[e.relation===`defines`?t===`easy`?` — lives here`:` — defined in this module`:e.certain?``:` — possible call`,e.cut===`cycle`?` — loops back`:``,e.cut===`repeat`?` — shown above`:``,e.partial?t===`easy`?` — could not be read`:` — unchartable`:``]})]})]},e.order))]})}),e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`structure is`:`structures are`,` never reached from Home by a parser-proven call. They are listed as unreached rather than attached to the tree by guesswork.`]}):null]})}var _J=m(),vJ=[{mode:`easy`,label:`New to coding?`},{mode:`expert`,label:`I build software`}],yJ=[{mode:`easy`,label:`Easy`},{mode:`expert`,label:`Expert`}];function bJ({mode:e,modeChosen:t,onChoose:n}){let r=(0,_.useRef)(null);(0,_.useLayoutEffect)(()=>{let e=r.current;e&&t===!1&&!e.open&&e.showModal()},[t]);function i(e){r.current?.close(),n(e)}return t===null?null:t?(0,$.jsxs)(`fieldset`,{className:`mode-toggle`,children:[(0,$.jsx)(`legend`,{className:`mode-toggle__label`,children:`Audience`}),(0,$.jsx)(`div`,{className:`mode-toggle__options`,children:yJ.map(t=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:`radio`,name:`audience-mode`,value:t.mode,checked:e===t.mode,onChange:()=>i(t.mode)}),(0,$.jsx)(`span`,{children:t.label})]},t.mode))})]}):(0,_J.createPortal)((0,$.jsxs)(`dialog`,{ref:r,className:`mode-gate`,"aria-labelledby":`mode-gate-heading`,"aria-describedby":`mode-gate-detail`,onCancel:e=>e.preventDefault(),children:[(0,$.jsx)(`h1`,{id:`mode-gate-heading`,children:`New to coding, or do you build software already?`}),(0,$.jsx)(`p`,{id:`mode-gate-detail`,children:`This changes how much Codemble explains and how much it assumes you already know.`}),(0,$.jsx)(`div`,{className:`mode-gate__options`,children:vJ.map(e=>(0,$.jsx)(`button`,{type:`button`,onClick:()=>i(e.mode),children:e.label},e.mode))})]}),document.body)}function xJ(e,t){let n=e?.steps??[];return n.length?n.some(e=>e.id===t)?t:n[0].id:null}function SJ(e,t,n){let r=e?.steps??[];if(!r.length)return null;let i=xJ(e,t),a=Math.max(0,r.findIndex(e=>e.id===i));return r[Math.max(0,Math.min(r.length-1,a+n))].id}function CJ(e,t,n){let r=e?.steps??[],i=xJ(e,t),a=r.findIndex(e=>e.id===i);if(a<0)return null;let o=r[a];return{id:o.id,index:a,total:r.length,position:`${a+1} of ${r.length}`,heading:wJ(o),summary:TJ(o),citation:o.declaration?.citation??o.citation??null,observationCitation:o.observation?.citation??null,isFirst:a===0,isLast:a===r.length-1,isTarget:!!o.is_target,expertDetails:n===`expert`?{layer:String(o.layer??`unknown`).replaceAll(`-`,` `),relation:o.relation??`unknown`,ruleId:o.rule_id??null,nodeId:o.node_id??null}:null}}function wJ(e){return e.relation===`home`?`Start at Home: ${e.name}`:e.relation===`import`?`Open ${e.name}`:e.relation===`call`?`Follow the call to ${e.name}`:e.relation===`role`?e.role===`ui-renderer`?`Reach the screen in ${e.name}`:e.role===`test`?`Enter through test surface ${e.name}`:`Enter through ${e.name}`:`Read ${e.name}`}function TJ(e){return e.relation===`home`?`The parser ranked this as the project's starting point.`:e.relation===`import`?`A certain import connects the previous file to this declaration.`:e.relation===`call`?e.is_target?`A certain call reaches the structure you selected.`:`A certain call continues the runtime route through this structure.`:e.relation===`role`?e.role===`route-handler`?`A parser-proven route registration is where a request reaches the application.`:e.role===`ui-renderer`?`Parser-proven rendering syntax connects this function to the visible interface.`:e.role===`test`?`Only a parser-proven test surface reaches this route; it is not an application screen.`:`The parser proved this is an application entry before the runtime route continues.`:`This is the next parser-proven declaration on the route.`}function EJ({node:e,study:t,error:n,mode:r,explanation:i,explanationLoading:a,explanationError:o,llmStatus:s,onSelectNode:c,onRetryStudy:l,onRetryNarration:u,onClose:d,revealSource:f=!1}){let p=(0,_.useRef)(null),m=(0,_.useRef)(null),h=(0,_.useRef)(null),g=(0,_.useRef)(null),v=(0,_.useRef)(null),y=(0,_.useRef)(null),b=t?.learning_journey??null,[x,S]=(0,_.useState)(null),C=!!t?.source;(0,_.useEffect)(()=>{p.current?.scrollTo({top:0,behavior:`auto`}),m.current?.focus({preventScroll:!0})},[e.id,f]),(0,_.useEffect)(()=>{n&&(p.current?.scrollTo({top:0,behavior:`auto`}),h.current?.focus({preventScroll:!0}))},[n,e.id]),(0,_.useEffect)(()=>{!f||!C||y.current!==e.id&&(y.current=e.id,g.current?.scrollIntoView({block:`start`,behavior:`auto`}),v.current?.focus({preventScroll:!0}))},[f,C,e.id]),(0,_.useEffect)(()=>{S(e=>xJ(b,e))},[b]);function w(){p.current?.scrollTo({top:0,behavior:`auto`}),m.current?.focus({preventScroll:!0}),l()}function T(){m.current?.focus({preventScroll:!0}),u()}return(0,$.jsxs)(`aside`,{ref:p,className:`study-preview`,"aria-label":`Selected source structure`,"aria-busy":!t&&!n,children:[(0,$.jsxs)(`header`,{className:`study-preview__header`,children:[d?(0,$.jsx)(`button`,{className:`check-close study-preview__close`,type:`button`,onClick:d,children:`Close`}):null,(0,$.jsxs)(`p`,{className:`study-preview__path`,children:[e.file,`:`,e.lineno]}),(0,$.jsx)(`h1`,{ref:m,tabIndex:-1,children:e.name})]}),n?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,children:[(0,$.jsx)(`h2`,{ref:h,tabIndex:-1,children:`Study data did not load.`}),(0,$.jsxs)(`p`,{children:[n,` The parser map is still available.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:w,children:`Try again`})]}):null,!t&&!n?(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:`Reading parser evidence…`}):null,(0,$.jsxs)(`div`,{className:`study-content`,children:[t?(0,$.jsx)(OJ,{journey:b,activeStepId:x,onActiveStepChange:S,impact:t.impact,neighbors:t.neighbors,node:e,mode:r,onSelectNode:c}):null,t?(0,$.jsx)(DJ,{node:e,mode:r}):null,t?(0,$.jsx)(AJ,{structural:t.structural,mode:r}):null,(0,$.jsx)(UJ,{explanation:i,loading:a,error:o,llmStatus:s,mode:r,node:e,onSelectNode:c,onRetry:T}),t?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(VJ,{source:t.source,anchorRef:g,headingRef:v}),(0,$.jsx)(BJ,{lens:t.lens,language:e.language,mode:r})]}):null]})]})}function DJ({node:e,mode:t}){return(0,$.jsx)(`section`,{className:`study-facts`,"aria-label":`Selected structure facts`,children:(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`What it is`:`Kind`}),(0,$.jsx)(`dd`,{children:e.kind})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`Length`:`Span`}),(0,$.jsxs)(`dd`,{children:[e.loc,` `,e.loc===1?`line`:`lines`]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`Called by`:`Callers`}),(0,$.jsx)(`dd`,{children:e.centrality})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`Evidence`:`Resolution`}),(0,$.jsx)(`dd`,{children:e.partial?t===`easy`?`Could not be fully read`:`Partial parse`:t===`easy`?`Proven from your code`:`Parser-proven`})]})]})})}function OJ({journey:e,activeStepId:t,onActiveStepChange:n,impact:r,neighbors:i,node:a,mode:o,onSelectNode:s}){let[c,l]=(0,_.useState)(``),u=CJ(e,t,o),d=e?.steps??[],f=e?.possible_frontier??[],p=e?.verification_candidates??[];(0,_.useEffect)(()=>l(``),[e?.fingerprint]);function m(t){n(t);let r=CJ(e,t,o);r&&l(`Journey step ${r.position}: ${r.heading}`)}function h(n){let r=SJ(e,t,n);r&&m(r)}return(0,$.jsxs)(`section`,{className:`learning-journey`,"aria-labelledby":`learning-journey-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`learning-journey-heading`,children:`Feature journey`}),(0,$.jsx)(`span`,{children:`Parser evidence`})]}),d.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`ol`,{className:`journey-overview`,"aria-label":`Feature journey steps`,children:d.map((t,n)=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-current":t.id===u?.id?`step`:void 0,"aria-label":`Step ${n+1}: ${CJ(e,t.id,o)?.heading}`,onClick:()=>m(t.id),children:[(0,$.jsx)(`span`,{children:n+1}),(0,$.jsx)(`small`,{children:t.layer.replaceAll(`-`,` `)})]})},t.id))}),u?(0,$.jsxs)(`article`,{className:`journey-current`,"data-step-id":u.id,children:[(0,$.jsxs)(`p`,{className:`journey-position`,children:[`Step `,u.position]}),(0,$.jsx)(`h3`,{children:u.heading}),(0,$.jsx)(`p`,{children:u.summary}),(0,$.jsxs)(`div`,{className:`journey-citations`,children:[u.observationCitation?(0,$.jsxs)(`span`,{children:[`Observed at `,(0,$.jsx)(`code`,{children:u.observationCitation})]}):null,(0,$.jsxs)(`span`,{children:[`Declaration `,(0,$.jsx)(`code`,{children:u.citation})]})]}),(0,$.jsxs)(`div`,{className:`journey-controls`,"aria-label":`Journey controls`,children:[(0,$.jsx)(`button`,{type:`button`,onClick:()=>h(-1),disabled:u.isFirst,children:`Back`}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>h(1),disabled:u.isLast,children:`Next`}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>m(d[0].id),disabled:u.isFirst,children:`Replay`})]}),u.expertDetails?(0,$.jsxs)(`dl`,{className:`journey-expert-facts`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Layer`}),(0,$.jsx)(`dd`,{children:u.expertDetails.layer})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Relation`}),(0,$.jsx)(`dd`,{children:u.expertDetails.relation})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Node ID`}),(0,$.jsx)(`dd`,{children:u.expertDetails.nodeId})]}),u.expertDetails.ruleId?(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Parser rule`}),(0,$.jsx)(`dd`,{children:u.expertDetails.ruleId})]}):null]}):null]}):null]}):null,(0,$.jsx)(`span`,{className:`visually-hidden`,"aria-live":`polite`,"aria-atomic":`true`,children:c}),e?.break?(0,$.jsxs)(`div`,{className:`journey-break`,role:`note`,children:[(0,$.jsx)(`strong`,{children:`Proof stops here`}),(0,$.jsx)(`p`,{children:e.break.message}),e.break.citation?(0,$.jsx)(`code`,{children:e.break.citation}):null]}):null,f.length?(0,$.jsxs)(`div`,{className:`journey-possible`,children:[(0,$.jsx)(`h3`,{children:`Possible next evidence`}),(0,$.jsx)(`p`,{children:`These parser observations are not part of the proven route.`}),(0,$.jsx)(`ul`,{children:f.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsxs)(`strong`,{children:[`Possible `,e.relation]}),(0,$.jsxs)(`span`,{children:[e.observation.citation,` → `,e.declaration.citation]})]},`${e.relation}-${e.source_node_id}-${e.target_node_id}-${e.observation.citation}`))})]}):null,(0,$.jsxs)(`details`,{className:`journey-support`,open:o===`expert`,children:[(0,$.jsx)(`summary`,{children:o===`easy`?`Explore selected feature impact and connections`:`Selected feature impact, connections, and verification`}),(0,$.jsxs)(`p`,{className:`journey-support-scope`,children:[`These facts belong to `,a.name,`, the selected feature. They stay fixed while you move between journey steps.`]}),(0,$.jsx)(jJ,{impact:r,mode:o,onSelectNode:s}),(0,$.jsx)(PJ,{neighbors:i,node:a,mode:o,onSelectNode:s}),o===`expert`?(0,$.jsx)(kJ,{items:p,onSelectNode:s}):null]})]})}function kJ({items:e,onSelectNode:t}){return(0,$.jsxs)(`section`,{className:`journey-verification`,"aria-labelledby":`journey-verification-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`journey-verification-heading`,children:`Selected feature verification candidates`}),(0,$.jsx)(`span`,{children:`Parser-linked`})]}),e.length?(0,$.jsx)(`ul`,{className:`impact-list`,children:e.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Open verification candidate ${e.name}; ${e.certain?`certain route`:`possible route`}; depth ${e.depth}; ${e.declaration.citation}`,onClick:()=>t(e.node_id),children:[(0,$.jsx)(`span`,{className:`impact-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`impact-meta`,children:[`depth `,e.depth,e.certain?` · certain route`:` · possible route`]}),(0,$.jsx)(`span`,{className:`impact-citation`,children:e.declaration.citation})]})},e.node_id))}):(0,$.jsx)(`p`,{className:`study-loading`,children:`No connected test evidence was found.`}),(0,$.jsx)(`p`,{className:`journey-candidate-note`,children:`These are parser-linked candidate verification points, not proof that a test passes.`})]})}function AJ({structural:e,mode:t}){return e?(0,$.jsxs)(`section`,{className:`structural-summary`,"aria-labelledby":`structural-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`structural-heading`,children:t===`easy`?`What this is`:`Structural summary`}),(0,$.jsx)(`span`,{children:`No model needed`})]}),(0,$.jsx)(`p`,{children:e[t]??e.easy})]}):null}function jJ({impact:e,mode:t,onSelectNode:n}){if(!e)return null;let r=e.affects??[],i=e.depends_on??[];if(!r.length&&!i.length)return null;let a=t===`easy`;return(0,$.jsxs)(`section`,{className:`impact-widget`,"aria-labelledby":`impact-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`impact-heading`,children:a?`What the selected feature touches`:`Selected feature impact`}),(0,$.jsx)(`span`,{children:`No model needed`})]}),(0,$.jsxs)(`div`,{className:`impact-columns`,children:[(0,$.jsx)(MJ,{title:a?`Change this and these change too`:`Change this → affected`,empty:a?`Nothing else in your code would notice if you changed this.`:`No parser-proven dependents.`,items:r,mode:t,onSelectNode:n}),(0,$.jsx)(MJ,{title:a?`This needs these to work`:`Depends on → breaks if changed`,empty:a?`This does not rely on anything else in your code.`:`No parser-proven dependencies.`,items:i,mode:t,onSelectNode:n})]}),e.truncated?(0,$.jsx)(`p`,{className:`study-loading`,children:a?`Traced ${e.max_depth} steps out; the chain continues past that.`:`Traced to depth ${e.max_depth}; deeper reach is not shown.`}):null]})}function MJ({title:e,empty:t,items:n,mode:r,onSelectNode:i}){return(0,$.jsxs)(`div`,{className:`impact-column`,children:[(0,$.jsx)(`h3`,{children:e}),n.length===0?(0,$.jsx)(`p`,{className:`study-loading`,children:t}):(0,$.jsx)(`ul`,{className:`impact-list`,children:n.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-label":`${e.name} — ${e.depth===1?`direct`:`${e.depth} steps away`}${e.certain?``:`, possible`} — ${e.citation}`,onClick:()=>i(e.node_id),children:[(0,$.jsx)(`span`,{className:`impact-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`impact-meta`,children:[e.depth===1?r===`easy`?`directly`:`direct`:r===`easy`?`${e.depth} steps away`:`depth ${e.depth}`,e.certain?``:r===`easy`?` · possible link`:` · possible`]}),(0,$.jsx)(`span`,{className:`impact-citation`,children:e.citation})]})},e.node_id))})]})}var NJ=8;function PJ({neighbors:e,node:t,mode:n,onSelectNode:r}){let i=e??[],a=i.filter(e=>e.direction===`inbound`),o=i.filter(e=>e.direction===`outbound`);return(0,$.jsxs)(`section`,{className:`connections`,"aria-labelledby":`connections-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`connections-heading`,children:n===`easy`?`What the selected feature connects to`:`Selected feature connections`}),(0,$.jsxs)(`span`,{children:[i.length,` parser `,i.length===1?`relationship`:`relationships`]})]}),i.length===0?(0,$.jsx)(`p`,{className:`study-loading`,children:n===`easy`?`Nothing in your code reaches this yet, and it does not reach anything else.`:`The parser observed no relationship into or out of this structure.`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(zJ,{inbound:a,outbound:o,node:t}),(0,$.jsx)(FJ,{title:n===`easy`?`Uses this`:`Inbound`,items:a,mode:n,onSelectNode:r}),(0,$.jsx)(FJ,{title:n===`easy`?`This uses`:`Outbound`,items:o,mode:n,onSelectNode:r})]})]})}function FJ({title:e,items:t,mode:n,onSelectNode:r}){return t.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:e}),(0,$.jsx)(`ul`,{className:`connection-list`,children:t.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-label":`${e.name} — ${IJ(e,n)}, ${LJ(e,n)} — ${e.citation}`,onClick:()=>r(e.node_id),children:[(0,$.jsx)(`span`,{className:`connection-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`connection-meta`,children:[IJ(e,n),` · `,LJ(e,n)]}),(0,$.jsx)(`span`,{className:`source-citation`,children:e.citation})]})},`${e.direction}-${e.node_id}`))})]}):null}function IJ(e,t){return e.relationship===`import`?e.direction===`inbound`?t===`easy`?`brings this in`:`import · inbound`:t===`easy`?`this brings it in`:`import · outbound`:e.direction===`inbound`?t===`easy`?`calls this`:`call · inbound`:t===`easy`?`this calls it`:`call · outbound`}function LJ(e,t){return e.certain?`certain`:e.relationship===`import`?t===`easy`?`possible link, not certain`:`possible import`:t===`easy`?`possible link, not certain`:`possible call`}function RJ(e){let t=String(e??``);return t.length<=18?t:`…${t.slice(-17)}`}function zJ({inbound:e,outbound:t,node:n}){let r=e.slice(0,NJ),i=t.slice(0,NJ),a=Math.max(r.length,i.length,1)*22+16,o=a/2,s=(e,t)=>(e+1)*a/(t+1);return(0,$.jsxs)(`svg`,{className:`mini-constellation`,viewBox:`0 0 280 ${a}`,role:`img`,"aria-label":`${e.length} inbound and ${t.length} outbound parser relationships for ${n.name}`,children:[r.map((e,t)=>(0,$.jsx)(`line`,{x1:`26`,y1:s(t,r.length),x2:`132`,y2:o,strokeDasharray:e.certain?void 0:`3 3`},`in-line-${e.node_id}`)),r.map((e,t)=>(0,$.jsx)(`text`,{className:`mini-constellation__name`,x:`8`,y:s(t,r.length)-7,textAnchor:`start`,children:RJ(e.name)},`in-name-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`text`,{className:`mini-constellation__name`,x:`272`,y:s(t,i.length)-7,textAnchor:`end`,children:RJ(e.name)},`out-name-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`line`,{x1:`148`,y1:o,x2:`254`,y2:s(t,i.length),strokeDasharray:e.certain?void 0:`3 3`},`out-line-${e.node_id}`)),r.map((e,t)=>(0,$.jsx)(`circle`,{cx:`22`,cy:s(t,r.length),r:`4`},`in-dot-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`circle`,{cx:`258`,cy:s(t,i.length),r:`4`},`out-dot-${e.node_id}`)),(0,$.jsx)(`circle`,{className:`mini-constellation__self`,cx:`140`,cy:o,r:`6`})]})}function BJ({lens:e,language:t,mode:n}){return e?.length?(0,$.jsxs)(`section`,{className:`lens-study`,"aria-labelledby":`lens-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsxs)(`h2`,{id:`lens-heading`,children:[IG(t),` lens`]}),(0,$.jsxs)(`span`,{children:[e.length,` detected`]})]}),(0,$.jsx)(`div`,{className:`lens-notes`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`lens-note`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h3`,{children:e.title}),(0,$.jsx)(GJ,{citation:e.citation,fallbackLine:e.line})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:e.note_voices[n]}),(0,$.jsx)(`code`,{children:e.snippet})]})]},`${e.concept}-${e.line}-${e.snippet}`))})]}):null}function VJ({source:e,anchorRef:t,headingRef:n}){return(0,$.jsxs)(`section`,{className:`source-study`,"aria-labelledby":`source-heading`,ref:t,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{ref:n,id:`source-heading`,tabIndex:-1,children:`Real source`}),(0,$.jsxs)(`span`,{title:`${e.file}:${e.start_line}–${e.end_line}`,children:[e.file,`:`,e.start_line,`–`,e.end_line]})]}),(0,$.jsx)(`ol`,{className:`source-code`,start:e.start_line,"aria-label":`Source excerpt from ${e.file}`,children:e.lines.map(e=>(0,$.jsx)(`li`,{id:`source-L${e.number}`,"data-line":e.number,children:(0,$.jsx)(`code`,{children:e.text||` `})},e.number))})]})}var HJ={grounding:`The explanation was withheld.`,unavailable:`Codemble could not reach the model.`,rejected:`The model refused the request.`,timeout:`The model is taking longer than expected.`,provider:`The model's reply could not be read.`};function UJ({explanation:e,loading:t,error:n,llmStatus:r,mode:i,node:a,onSelectNode:o,onRetry:s}){if(t)return(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:i===`easy`?`Asking your model to explain this in plain language…`:`Requesting a grounded narration for this structure…`});if(n)return(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`The explanation request failed.`}),(0,$.jsx)(`p`,{children:n}),(0,$.jsx)(`p`,{children:`Every fact above and below this block came from the parser and is unaffected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]});if(!e)return null;if(e.status===`no_key`)return(0,$.jsx)(WJ,{message:e.message,llmStatus:r,mode:i});if(e.status===`error`||e.status===`timeout`){let t=e.reason===`grounding`;return(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:HJ[e.reason]??HJ.provider}),(0,$.jsx)(`p`,{children:e.message}),t?(0,$.jsx)(`p`,{children:`Codemble will not display provider output that falls outside parser evidence.`}):null,(0,$.jsx)(`p`,{children:`Every fact from the parser on this panel is unaffected.`}),e.retryable===!1?null:(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]})}return e.status===`partial`?(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`Narration stays off for partial source.`}),(0,$.jsx)(`p`,{children:e.message})]}):(0,$.jsxs)(`section`,{className:`grounded-explanation`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,role:`status`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:i===`easy`?`In plain language`:`Grounded explanation`}),(0,$.jsx)(`span`,{children:e.cached?`Local cache`:e.provider})]}),(0,$.jsxs)(`p`,{children:[e.summary.text,` `,(0,$.jsx)(GJ,{citation:e.summary.citation,fallbackLine:a.lineno})]}),e.excerpt?.truncated?(0,$.jsx)(`p`,{className:`study-loading`,children:i===`easy`?`This file is long, so the model was shown lines ${e.excerpt.first}–${e.excerpt.last} of ${e.excerpt.total}.`:`Narrated from an excerpt: lines ${e.excerpt.first}–${e.excerpt.last} of ${e.excerpt.total}.`}):null,e.withheld>0?(0,$.jsxs)(`p`,{className:`study-loading`,children:[e.withheld,` `,e.withheld===1?`part`:`parts`,` of the reply `,e.withheld===1?`was`:`were`,` malformed and left out.`]}):null,e.walkthrough.length?(0,$.jsxs)(`details`,{className:`walkthrough-disclosure`,children:[(0,$.jsx)(`summary`,{children:i===`easy`?`Walk me through it line by line (${e.walkthrough.length})`:`Line walkthrough (${e.walkthrough.length})`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.walkthrough.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`p`,{children:e.text}),(0,$.jsx)(GJ,{citation:e.citation,fallbackLine:e.line})]},`${e.citation}-${e.text}`))})]}):null,e.relationships.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:i===`easy`?`How it fits in`:`Parser relationships`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.relationships.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`strong`,{children:e.certain?e.node_id:`Possible: ${e.node_id}`}),(0,$.jsx)(`p`,{children:e.text}),(0,$.jsxs)(`button`,{className:`source-citation source-citation--button`,type:`button`,onClick:()=>o(e.node_id),children:[`Study `,e.citation]})]},`${e.node_id}-${e.text}`))})]}):null]})}function WJ({message:e,llmStatus:t,mode:n}){let r=t?.ollama??null;return(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:n===`easy`?`The plain-language write-up needs a model.`:`No narration provider is configured.`}),(0,$.jsx)(`p`,{children:e}),r?(0,$.jsx)(`p`,{children:r.running?`Ollama is already running on this machine. Set CODEMBLE_PROVIDER=ollama and CODEMBLE_OLLAMA_MODEL=${r.recommended}, then restart Codemble to narrate without sending code anywhere.`:`Want to stay fully local? Install Ollama, run "ollama pull ${r.recommended}" (or ${r.fallback} on a smaller machine), set CODEMBLE_PROVIDER=ollama, then restart Codemble.`}):null,(0,$.jsx)(`p`,{children:`Everything else on this panel is parser evidence and works without any model at all.`})]})}function GJ({citation:e,fallbackLine:t}){return(0,$.jsx)(`a`,{className:`source-citation`,href:`#source-L${Number(e.split(`:`).at(-1))||t}`,children:e})}var KJ=Object.freeze([]),qJ=new Set;function JJ(){let e=new WeakMap,t=new WeakMap,n=new WeakMap,r=new WeakMap,i=new WeakMap,a=new WeakMap,o=null,s=null,c=null,l=null;function u(e){let t=e.graph,n=t?d(t,e.languageFocus):null,r=n?p(n):null,i=e.level,a=r?.regionById.get(e.region?.id)??null,o=e.selectedNode;n&&(a?o&&(o=r.nodeById.get(o.id)??null,!o&&i===jG.STUDY&&(i=jG.SYSTEM)):(a=mK(n),o=null,i=jG.GALAXY));let s=e.studiedNodeIds;return{...e,focusedGraph:n,focusedMapData:f(e.mapData,e.languageFocus),entrypointOpen:!!t&&!e.entrypointDismissed,level:i,region:a,selectedNode:o,languageOptions:t?m(t):KJ,projectName:t?g(t):`Loading local project`,chart:n?_(n,s):KJ,focusedStudiedCount:n?v(n,s):0,hint:n?y(n,e.mode,i,a?.id??null,e.layer,t,e.languageFocus):null,revealedRegionIds:n?b(n,e.showAll,a?.id??null,e.visitedRegionIds):qJ,moduleIndex:n?h(n):KJ}}function d(t,n){let r=e.get(t);r||(r=new Map,e.set(t,r));let i=n||`all`;return r.has(i)||r.set(i,MG(t,n)),r.get(i)}function f(e,n){if(!e)return e;let r=t.get(e);r||(r=new Map,t.set(e,r));let i=n||`all`;return r.has(i)||r.set(i,NG(e,n)),r.get(i)}function p(e){return n.has(e)||n.set(e,{nodeById:new Map(e.nodes.map(e=>[e.id,e])),regionById:new Map(e.regions.map(e=>[e.id,e]))}),n.get(e)}function m(e){return r.has(e)||r.set(e,PG(e)),r.get(e)}function h(e){return i.has(e)||i.set(e,qG(e)),i.get(e)}function g(e){return a.has(e)||a.set(e,hK(e)),a.get(e)}function _(e,t){return(!o||o.graph!==e||o.studiedNodeIds!==t)&&(o={graph:e,studiedNodeIds:t,value:FG(e,t)}),o.value}function v(e,t){return(!s||s.graph!==e||s.studiedNodeIds!==t)&&(s={graph:e,studiedNodeIds:t,value:e.nodes.filter(e=>t.has(e.id)).length}),s.value}function y(e,t,n,r,i,a,o){return(!c||c.graph!==e||c.mode!==t||c.level!==n||c.regionId!==r||c.layer!==i||c.projectGraph!==a||c.languageFocus!==o)&&(c={graph:e,mode:t,level:n,regionId:r,layer:i,projectGraph:a,languageFocus:o,value:ZJ(e,{mode:t,level:n,regionId:r,layer:i,projectGraph:a,languageFocus:o})}),c.value}function b(e,t,n,r){return(!l||l.graph!==e||l.showAll!==t||l.selectionId!==n||l.visitedIds!==r)&&(l={graph:e,showAll:t,selectionId:n,visitedIds:r,value:HG(e,{showAll:t,selectionId:n,visitedIds:r})}),l.value}return Object.freeze({derive:u})}var YJ=1.5;function XJ({homeChosen:e,homeOutsideFocus:t,languageFocus:n,hops:r}){return e?t?`Home is not written in ${LG(n)}.`:r===0?`Home is not lit yet.`:Number.isFinite(r)?`${r} ${r===1?`route`:`routes`} from Home.`:`No import route reaches it from Home.`:`No Home is chosen, so there is no route to measure from.`}function ZJ(e,{mode:t,level:n,regionId:r,layer:i,projectGraph:a,languageFocus:o}){if(t!==`easy`)return null;let s=e.regions.filter(e=>!e.understood);if(!s.length)return null;let c=(a??e).regions.some(e=>e.home),l=c&&!e.regions.some(e=>e.home),u=GG(e),d=s.map(e=>{let t=typeof e.hops_from_home==`number`?e.hops_from_home:1/0;return{regionId:e.id,hops:t,biasedHops:ZG(u.get(e.id)??``)?t+YJ:t,structures:typeof e.node_count==`number`?e.node_count:0}}).sort((e,t)=>e.biasedHops-t.biasedHops||t.structures-e.structures||e.regionId.localeCompare(t.regionId))[0],{biasedHops:f,...p}=d,m={...p,message:`Study ${d.regionId} next`,reason:XJ({homeChosen:c,homeOutsideFocus:l,languageFocus:o,hops:d.hops})};return n===jG.STUDY?r===d.regionId?{...m,message:`Prove you understand ${d.regionId}`,reason:`Questions come from this file, not from a model.`,action:{type:`OPEN_CHECKS`},actionLabel:`Prove understanding`}:{...m,action:{type:`OPEN_REGION`,regionId:d.regionId},actionLabel:`Open ${d.regionId}`}:n!==jG.SYSTEM||r!==d.regionId?{...m,action:{type:`OPEN_REGION`,regionId:d.regionId},actionLabel:`Open ${d.regionId}`}:i===`map`?e.nodes.some(e=>e.id===d.regionId)?{...m,reason:`Read it before proving it.`,action:null,actionLabel:null}:{...m,reason:`Its parser-proven structures are visible in Galaxy.`,action:{type:`SET_LAYER`,layer:`galaxy`},actionLabel:`View structures`}:{...m,reason:`Choose one of its parser-proven structures.`,action:null,actionLabel:null}}var QJ=`Codemble's local server is not responding. Your source files and saved progress are unchanged. Start Codemble again, then try again.`;function $J(e){return Number.isInteger(e?.status)?eY(e):QJ}function eY(e){return e instanceof Error?e.message:String(e)}var tY=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}}),nY=300,rY=400,iY=4e3,aY=8,oY=Object.freeze([Object.freeze({id:`discovering`,copy:`Finding your source files`}),Object.freeze({id:`parsing`,copy:`Reading each file`}),Object.freeze({id:`resolving`,copy:`Connecting imports and calls`}),Object.freeze({id:`checks`,copy:`Building graph-only checks`}),Object.freeze({id:`layout`,copy:`Placing your galaxy`})]);function sY({adapter:e,clock:t=tY,onReady:n=async()=>{}}={}){if(!e)throw TypeError(`Project mapping requires a learner adapter.`);let r=new Set,i=cY({phase:`idle`,error:``,picker:null,progress:null,failure:null}),a=0,o=null,s=null,c=null,l=null;function u(){return i}function d(e){return r.add(e),()=>r.delete(e)}function f(e){i=cY({...i,...e});for(let e of r)e()}async function p(){a+=1;let t=a;b(),lY(o),o=new AbortController;let n=o;f({phase:`idle`,error:``,picker:null,progress:null,failure:null});try{let[r,o]=await Promise.all([e.loadRecents({signal:n.signal}),e.browsePicker(null,{signal:n.signal})]);if(t!==a||n.signal.aborted)return i;f({phase:`picking`,picker:{...o,recents:r.recents,error:``,retryPath:null,scale:null,busy:!1}})}catch(e){!uY(e)&&t===a&&f({phase:`error`,error:$J(e)})}return i}async function m(t){if(i.phase!==`picking`||i.picker?.busy)return;lY(o),o=new AbortController;let n=o,r=a;f({failure:null});try{let s=await e.browsePicker(t,{signal:n.signal});o===n&&r===a&&!n.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...s,error:``,retryPath:null,scale:null}})}catch(e){o===n&&r===a&&!uY(e)&&i.phase===`picking`&&f({picker:{...i.picker,error:$J(e),retryPath:t}})}}async function h(t){if(i.phase!==`picking`||i.picker?.busy)return;a+=1;let r=a;lY(o),b(),o=new AbortController;let s=o;f({failure:null,picker:{...i.picker,busy:!0,error:``,retryPath:null,scale:null}});try{let o=await e.selectProject(t,{signal:s.signal});if(r!==a||s.signal.aborted||i.phase!==`picking`)return o;if(o.state===`parsing`)return f({progress:{state:`parsing`,stage:`discovering`,detail:null,files_done:0,files_total:0,error:null,pollError:``,attempts:0,pollOutage:!1,path:t}}),_(0,r),o;if(o.state===`ready`)return y(),await n(),o;if(o.state===`scale`){let t=await e.browsePicker(o.root,{signal:s.signal});return r===a&&!s.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...t,busy:!1,scale:o}}),o}let c=o.detail??``;return f({picker:{...i.picker,busy:!1,error:c},failure:c?{path:t,detail:c}:null}),o}catch(e){if(r===a&&!uY(e)&&i.phase===`picking`){let n=fY(e);f({picker:{...i.picker,busy:!1,error:n},failure:{path:t,detail:n}})}return}}async function g(){lY(c),c=new AbortController;let t=c;try{await e.resetProject({signal:t.signal})}catch(e){if(uY(e))return!1;if(dY(e))throw e}return t.signal.aborted?!1:(a+=1,lY(o),o=null,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null}),!0)}function _(e,n){l!==null&&t.clearTimeout(l),l=t.setTimeout(async()=>{l=null,await v(n)},e)}async function v(t){if(!i.progress||t!==a)return;lY(s),s=new AbortController;let r=s,o=i.progress,c;try{c=await e.fetchParseProgress({signal:r.signal})}catch(e){if(s!==r||t!==a||uY(e)||!i.progress)return;let n=o.attempts+1;f({progress:{...o,pollError:fY(e),attempts:n,pollOutage:n>=aY}}),_(Math.min(iY,rY*2**(n-1)),t);return}if(!(s!==r||t!==a||!i.progress)){if(c.state===`ready`){y(),await n();return}if(c.state===`error`||c.state===`idle`){b();let e=c.error??``;f({progress:null,picker:{...i.picker,busy:!1,error:e},failure:e?{path:o.path,detail:e}:null});return}f({progress:{...o,...c,pollError:``,attempts:0,pollOutage:!1}}),_(nY,t)}}function y(){a+=1,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null})}function b(){lY(s),s=null,l!==null&&(t.clearTimeout(l),l=null)}function x(){a+=1;for(let e of[o,s,c])lY(e);o=null,c=null,b(),r.clear()}return Object.freeze({browse:m,dispose:x,getSnapshot:u,reset:g,select:h,start:p,subscribe:d})}function cY(e){return Object.freeze(e)}function lY(e){e&&!e.signal.aborted&&e.abort()}function uY(e){return e?.name===`AbortError`}function dY(e){return Number.isInteger(e?.status)}function fY(e){return e instanceof Error?e.message:String(e)}var pY=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}});function mY({adapter:e=_Y(),clock:t=pY}={}){let n=new Set,r=JJ(),i=r.derive({status:`idle`,error:``,graph:null,level:jG.GALAXY,region:null,selectedNode:null,studyData:null,studyError:``,explanation:null,explanationLoading:!1,explanationError:``,showChart:!1,studiedNodeIds:new Set,visitedRegionIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,picker:null,parseProgress:null,projectFailure:null,layer:`galaxy`,layerChosen:!1,mapTab:`architecture`,mapData:null,mapError:``,coachmarksSeen:bY(),llmStatus:null,hoverNodeId:null,showAll:CY(),finderOpen:!1,sidebarOpen:!1,legendOpen:!1,mode:`easy`,modeChosen:null}),a=0,o=0,s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,h=null;function g(){return i}function _(e){return n.add(e),()=>n.delete(e)}function v(e,{preserveChecks:t=!1}={}){let a=i,o=r.derive({...a,...e});if(o.level!==a.level||o.region?.id!==a.region?.id){let e={hoverNodeId:null};t||(TY(u),TY(d),u=null,d=null,e.showChecks=!1,e.checkData=null,e.checkError=``),o=r.derive({...o,...e})}i=Object.freeze(o);for(let e of n)e()}let y=sY({adapter:e,clock:t,async onReady(){a+=1;let e=a;return TY(s),s=new AbortController,S(s,e)}}),b=y.subscribe(()=>{let e=y.getSnapshot(),t={picker:e.picker,parseProgress:e.progress,projectFailure:e.failure};e.phase===`picking`&&(t.status=`picking`),e.phase===`error`&&(t.status=`error`,t.error=e.error),v(t)});async function x(){a+=1;let t=a;TY(s),s=new AbortController;let n=s;v({status:`loading`,error:``});let r;try{r=await e.loadPickerState({signal:n.signal})}catch(e){return!EY(e)&&t===a&&v({status:`error`,error:$J(e)}),i}return t!==a||n.signal.aborted?i:r.state===`unpicked`?(await y.start(),i):S(n,t)}async function S(t,n){v({status:`loading`,error:``,picker:null});try{let r=await e.loadGraph({signal:t.signal});if(n!==a||t.signal.aborted)return i;v({status:`ready`,graph:r,region:mK(r),error:``,entrypointDismissed:!!r.selected_entrypoint})}catch(e){!EY(e)&&n===a&&v({status:`error`,error:$J(e)})}return await C(t,n),i}async function C(t,n){let r=o,[s,c,l]=await Promise.allSettled([(async()=>e.loadMode({signal:t.signal}))(),(async()=>e.fetchLlmStatus({signal:t.signal}))(),(async()=>e.fetchVisited?.({signal:t.signal}))()]);if(!(n!==a||t.signal.aborted)){if(l.status===`fulfilled`&&Array.isArray(l.value?.visited)&&v({visitedRegionIds:new Set(l.value.visited)}),r===o){let e=s.status===`fulfilled`?s.value:null;e?.mode===`easy`||e?.mode===`expert`?ne(e.mode,e.chosen===!0):i.modeChosen===null&&v({modeChosen:!0})}c.status===`fulfilled`&&v({llmStatus:c.value})}}async function w(){let t=a;if(await e.clearProgress({}),v({visitedRegionIds:new Set}),t!==a)return i;a+=1;let n=a;TY(s),s=new AbortController,TY(p),p=null,v({mapData:null,mapError:``});let r=await S(s,n);return n===a&&i.layer===`map`&&await le(),r}async function T(){return await y.reset()?(N(),TY(f),f=null,TY(p),p=null,TY(m),m=null,v({graph:null,parseProgress:null,projectFailure:null,region:null,selectedNode:null,level:jG.GALAXY,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1,showChart:!1,studiedNodeIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,llmStatus:null,picker:null,mapData:null,mapError:``}),x()):i}async function E(e){switch(e.type){case`ADVANCE`:return A(e.node);case`ADVANCE_REGION`:k(e.regionId);return;case`FOLLOW_HINT`:return D();case`RETREAT`:ee();return;case`SELECT_STUDY_NODE`:return te(e.nodeId);case`SET_LANGUAGE_FOCUS`:j(e.language);return;case`SET_MODE`:return re(e.mode);case`HOVER_NODE`:i.hoverNodeId!==(e.nodeId??null)&&v({hoverNodeId:e.nodeId??null});return;case`SHOW_CHART`:v({showChart:!0});return;case`HIDE_CHART`:v({showChart:!1});return;case`OPEN_CHECKS`:return ae();case`CLOSE_CHECKS`:P();return;case`SUBMIT_CHECK`:return se(e.checkId,e.selectedIds);case`CONSUME_DAWN`:fe(e.regionId);return;case`SELECT_ENTRYPOINT`:return F(e.nodeId);case`DISMISS_ENTRYPOINT`:v({entrypointDismissed:!0});return;case`CHANGE_HOME`:N(),v({entrypointDismissed:!1,entrypointError:``,level:jG.GALAXY,selectedNode:null,showChart:!1,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1});return;case`BROWSE_PICKER`:return y.browse(e.path);case`SELECT_PROJECT`:return y.select(e.path);case`RESET_PROJECT`:return T();case`CLEAR_PROGRESS`:return w();case`SET_LAYER`:return ce(e.layer);case`SET_MAP_TAB`:v({mapTab:e.tab});return;case`DISMISS_COACHMARKS`:xY(),v({coachmarksSeen:!0});return;case`SET_LEVEL_GALAXY`:N(),v({level:jG.GALAXY,selectedNode:null});return;case`TOGGLE_SHOW_ALL`:wY(!i.showAll),v({showAll:!i.showAll});return;case`SET_FINDER_OPEN`:v({finderOpen:e.open});return;case`TOGGLE_SIDEBAR`:v({sidebarOpen:!i.sidebarOpen});return;case`TOGGLE_LEGEND`:v({legendOpen:!i.legendOpen});return;case`GO_TO_REGION`:return v({finderOpen:!1}),k(e.regionId);default:throw Error(`Unknown learner-session event: ${e.type}`)}}function D(){let e=i.hint?.action;if(e){if(e.type===`OPEN_REGION`){k(e.regionId);return}if(e.type===`SET_LAYER`)return ce(e.layer);if(e.type===`OPEN_STUDY`)return te(e.nodeId);if(e.type===`OPEN_CHECKS`)return i.level===jG.STUDY&&ee(),ae()}}function O(t){!t||i.visitedRegionIds.has(t)||(v({visitedRegionIds:new Set(i.visitedRegionIds).add(t)}),Promise.resolve(e.markVisited?.(t)).catch(()=>{}))}function k(e){let t=i.graph?.regions.find(t=>t.id===e);t&&(N(),O(t.id),v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:t,selectedNode:null,level:jG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}async function A(e){if(!(!i.focusedGraph||!e)){if(i.level===jG.GALAXY){let t=i.focusedGraph.regions.find(t=>t.id===e.id)??e;N(),O(t.id),v({region:t,selectedNode:null,level:jG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1});return}if(i.level===jG.SYSTEM){let t=i.focusedGraph.nodes.find(t=>t.id===e.id)??e;return v({selectedNode:t,level:jG.STUDY}),M(t.id)}if(i.level===jG.STUDY){let t=i.focusedGraph.nodes.find(t=>t.id===e.id);return!t||t.id===i.selectedNode?.id?void 0:(v({selectedNode:t}),M(t.id))}}}function ee(){i.level===jG.STUDY?(N(),v({selectedNode:null,level:jG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1})):i.level===jG.SYSTEM&&v({level:jG.GALAXY})}async function te(e){let t=i.graph?.nodes.find(t=>t.id===e);if(!t)return;let n=i.graph.regions.find(e=>e.id===t.region);return n&&O(n.id),v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:n??i.region,selectedNode:t,level:jG.STUDY}),M(t.id)}function j(e){let t=i.selectedNode?.id;v({languageFocus:e}),t&&i.selectedNode?.id!==t&&(N(),v({studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}function ne(e,t){let n=i.layerChosen?i.layer:e===`easy`?`map`:`galaxy`;v({mode:e,layer:n,modeChosen:t}),n===`map`&&le()}async function re(t){if(t!==`easy`&&t!==`expert`)return;let n=i.mode,r=i.modeChosen;if(t===n&&i.modeChosen)return;o+=1,TY(m),m=new AbortController;let s=m,c=a;ne(t,!0);try{await e.saveMode(t,{signal:s.signal})}catch(e){m===s&&c===a&&!EY(e)&&ne(n,r);return}if(!(c!==a||s.signal.aborted)&&i.level===jG.STUDY&&i.selectedNode)return ie(i.selectedNode.id)}async function M(t){N(),c=new AbortController;let n=c;v({studyData:null,studyError:``}),ie(t);try{let r=await e.loadStudy(t,{signal:n.signal});if(n.signal.aborted||i.level!==jG.STUDY||i.selectedNode?.id!==t)return;v({studyData:r,studiedNodeIds:new Set(i.studiedNodeIds).add(r.node.id)})}catch(e){c===n&&!n.signal.aborted&&!EY(e)&&i.selectedNode?.id===t&&v({studyError:DY(e)})}}function N(){TY(c),c=null,TY(l),l=null}async function ie(t){TY(l),l=new AbortController;let n=l;v({explanation:null,explanationError:``,explanationLoading:!0});try{let r=await e.loadExplanation(t,i.mode,{signal:n.signal});if(n.signal.aborted||i.level!==jG.STUDY||i.selectedNode?.id!==t)return;v({explanation:r,explanationLoading:!1})}catch(e){l===n&&!n.signal.aborted&&!EY(e)&&i.selectedNode?.id===t&&v({explanationError:DY(e),explanationLoading:!1})}}async function ae(){if(!i.region)return;let e=i.region.id;return v({showChecks:!0,checkData:null,checkError:``}),oe(e)}async function oe(t){TY(u),u=new AbortController;let n=u;try{let r=await e.loadChecks(t,{signal:n.signal});return!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkData:r,checkError:``},{preserveChecks:!0}),r}catch(e){u===n&&!EY(e)&&!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkError:DY(e)},{preserveChecks:!0});return}}function P(){TY(u),u=null,v({showChecks:!1,checkData:null,checkError:``})}async function se(t,n){if(!i.region)return;let r=i.region.id;TY(d),d=new AbortController;let a=d,o=await e.submitCheck(r,t,n,{signal:a.signal});if(a.signal.aborted||i.region?.id!==r)return o;if(o.correct&&await oe(r),o.region_understood){let t=await e.loadGraph({signal:a.signal});!a.signal.aborted&&i.region?.id===r&&(TY(p),p=null,v({graph:t,region:t.regions.find(e=>e.id===r),mapData:null,mapError:``},{preserveChecks:!0}),de(r),i.layer===`map`&&await le())}return o}async function F(t){let n=a;TY(f),f=new AbortController;let r=f;v({entrypointError:``});try{let o=await e.selectEntrypoint(t,{signal:r.signal});return n!==a||r.signal.aborted?i:(TY(p),p=null,v({graph:o,region:mK(o),entrypointError:``,entrypointDismissed:!0,mapData:null,mapError:``}),i.layer===`map`&&await le(),o)}catch(e){f===r&&n===a&&!r.signal.aborted&&!EY(e)&&v({entrypointError:DY(e)});return}}async function ce(e){if(v({layer:e,layerChosen:!0}),e===`map`)return le()}function le(){if(!i.mapData)return p&&!p.signal.aborted&&!i.mapError?void 0:ue()}async function ue(){let t=a;TY(p),p=new AbortController;let n=p;v({mapError:``});try{let r=await e.fetchMap({signal:n.signal});return t===a&&!n.signal.aborted&&v({mapData:r,mapError:``}),r}catch(e){p===n&&t===a&&!n.signal.aborted&&!EY(e)&&v({mapError:DY(e),mapData:null});return}}function de(e){h!==null&&t.clearTimeout(h),v({litRegionId:e,pendingDawnRegionId:e}),h=t.setTimeout(()=>{h=null,i.litRegionId===e&&v({litRegionId:null})},520)}function fe(e){i.pendingDawnRegionId===e&&v({pendingDawnRegionId:null})}function pe(){a+=1;for(let e of[s,c,l,u,d,f,p,m])TY(e);s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,b(),y.dispose(),h!==null&&(t.clearTimeout(h),h=null)}return Object.freeze({dispatch:E,dispose:pe,getSnapshot:g,start:x,subscribe:_})}var hY=6e4;function gY(e,t){if(typeof AbortSignal?.timeout!=`function`||typeof AbortSignal?.any!=`function`)return e;let n=AbortSignal.timeout(t);return{...e,signal:e.signal?AbortSignal.any([e.signal,n]):n}}function _Y(e=globalThis.fetch){if(typeof e!=`function`)throw TypeError(`Learner-session HTTP adapter requires fetch.`);async function t(t,n,r={}){let i;try{i=await e(t,r)}catch(e){throw e instanceof Error&&e.name===`TimeoutError`?Error(`${n} timed out. Codemble is still running — try again.`):e}if(!i.ok){let e=(await i.json().catch(()=>null))?.detail,t=Error(typeof e==`string`&&e?e:`${n} returned ${i.status}.`);throw t.status=i.status,t}return i.json()}return Object.freeze({loadGraph(e={}){return t(`/api/graph`,`Graph request`,e)},fetchMap(e={}){return t(`/api/map`,`Map request`,e)},loadStudy(e,n={}){return t(`/api/node/${encodeURIComponent(e)}/study`,`Study request`,n)},loadExplanation(e,n,r={}){return t(`/api/node/${encodeURIComponent(e)}/explanation?mode=${encodeURIComponent(n)}`,`Explanation request`,gY(r,hY))},loadChecks(e,n={}){return t(`/api/regions/${encodeURIComponent(e)}/checks`,`Checks request`,n)},submitCheck(e,n,r,i={}){return t(`/api/regions/${encodeURIComponent(e)}/checks/${encodeURIComponent(n)}`,`Check submission`,{...i,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selected_ids:r})})},selectEntrypoint(e,n={}){return t(`/api/entrypoint`,`Home selection`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({node_id:e})})},loadMode(e={}){return t(`/api/mode`,`Mode request`,e)},saveMode(e,n={}){return t(`/api/mode`,`Mode update`,{...n,method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({mode:e})})},fetchLlmStatus(e={}){return t(`/api/llm/status`,`Model status`,e)},resetProject(e={}){return t(`/api/picker/reset`,`Project reset`,{...e,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirmed:!0})})},loadPickerState(e={}){return t(`/api/picker/state`,`Picker state`,e)},browsePicker(e,n={}){return t(`/api/picker/browse${e?`?path=${encodeURIComponent(e)}`:``}`,`Folder listing`,n)},loadRecents(e={}){return t(`/api/picker/recents`,`Recent projects`,e)},fetchParseProgress(e={}){return t(`/api/picker/progress`,`Parse progress`,e)},clearProgress(e={}){return t(`/api/progress`,`Progress reset`,{...e,method:`DELETE`})},fetchVisited(e={}){return t(`/api/progress/visited`,`Explored regions`,e)},markVisited(e,n={}){return t(`/api/progress/visited`,`Explored regions`,{...n,method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({region_id:e})})},async selectProject(t,n={}){let r=await e(`/api/picker/select`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t})}),i=await r.json().catch(()=>null);if(r.ok)return{state:r.status===202?`parsing`:`ready`};let a=i?.detail;return a&&typeof a==`object`&&a.reason===`scale`?{state:`scale`,...a}:{state:`error`,detail:typeof a==`string`?a:`Project selection returned ${r.status}.`}}})}var vY=`codemble.coachmarks.seen`;function yY(){if(typeof document>`u`)return null;try{return globalThis.localStorage??null}catch{return null}}function bY(){try{return yY()?.getItem(vY)===`1`}catch{return!1}}function xY(){try{yY()?.setItem(vY,`1`)}catch{}}var SY=`codemble.galaxy.showAll`;function CY(){try{return yY()?.getItem(SY)===`1`}catch{return!1}}function wY(e){try{let t=yY();e?t?.setItem(SY,`1`):t?.removeItem(SY)}catch{}}function TY(e){e&&!e.signal.aborted&&e.abort()}function EY(e){return e instanceof Error&&e.name===`AbortError`}function DY(e){return e instanceof Error?e.message:String(e)}var OY=Object.freeze([{id:`editableField`,open:e=>e.editableFocus===!0,dismissible:!1},{id:`nativeDialog`,open:e=>e.nativeDialogOpen===!0,dismissible:!1},{id:`railDisclosure`,open:e=>e.railDisclosureOpen===!0,dismissible:!0},{id:`checks`,open:e=>e.showChecks===!0,dismissible:!0},{id:`sidebar`,open:e=>e.sidebarOpen===!0,dismissible:!0},{id:`finder`,open:e=>e.finderOpen===!0,dismissible:!1},{id:`entrypoint`,open:e=>e.entrypointOpen===!0,dismissible:!1},{id:`chart`,open:e=>e.showChart===!0,dismissible:!0},{id:`firstFlight`,open:e=>e.firstFlightOpen===!0,dismissible:!0}]);function kY(e){let t=OY.find(t=>t.open(e??{}));return t?{id:t.id,dismissible:t.dismissible}:null}function AY(e={}){if(e.ready!==!0)return null;let t=kY(e);return t?t.dismissible?{kind:`dismiss`,surface:t.id}:null:e.canRetreat?{kind:`retreat`}:null}function jY(e){return String(e??``).replace(/[\\`*_[\]<>#|]/g,`\\$&`)}function MY(e,t,n=`${t}s`){return`${e} ${e===1?t:n}`}function NY(e){return`${String(e?.projectName??`local-project`).normalize(`NFKD`).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`local-project`}-codemble-brief.md`}function PY(e,{charted:t=0}={}){let n=e?.languages??[],r=e?.busiest??[],i=e?.unsupportedSources??[],a=e?.relationships??{proven:0,hedged:0},o=e?.importCycles??[],s=e?.modules??0,c=e?.structures??0,l=e?.understood??0;return[`# ${jY(e?.projectName??`Local project`)} — Codemble project brief`,``,`> Generated locally from Codemble's parser graph. It contains no AI-generated narration.`,``,`## Project shape`,``,`- ${MY(s,`file`)} containing ${MY(c,`structure`)}.`,`- ${e?.lines??0} lines across parser-supported source files.`,``,`### Languages`,``,`| Language | Files | Structures |`,`| --- | ---: | ---: |`,...n.length?n.map(e=>`| ${jY(e.label)} | ${e.count} | ${e.structures} |`):[`| None reported | 0 | 0 |`],``,`## Home`,``,e?.home?`- Codemble resolved Home as ${jY(e.home.id)} (${jY(e.home.language)}).`:`- No Home entrypoint was resolved; this brief does not invent one.`,``,`## Called from the most places`,``,...r.length?r.map(e=>`- ${jY(e.id)} — called from ${MY(e.value,`place`)}.`):[`- No module has a reported caller count.`],``,`## Proven import cycles`,``,...o.length?o.map(e=>`- Strongly connected group: ${e.map(jY).join(`, `)}. Each file can reach every other through proven imports.`):[`- None reported.`],``,`## Parser evidence`,``,`- Proven relationships: ${a.proven}.`,`- Hedged relationships: ${a.hedged}. Hedged relationships are possible parser matches, not proven links.`,`- Files Codemble could not read: ${e?.unreadable??0}.`,...i.length?[`- Unsupported source files:`,...i.map(e=>` - ${jY(e.extension||`unknown extension`)} (${jY(e.language||`unknown language`)}): ${e.count}`)]:[`- Unsupported source files: 0.`],``,`## Learning progress`,``,`- Charted systems: ${t} of ${s}. Charted means visited, not understood.`,`- Understood systems: ${l} of ${s}. Understood means a graph-derived check passed.`,``].join(`
-`)}function FY(){let e=(0,_.useRef)(null),t=(0,_.useRef)(null),n=(0,_.useRef)(null),r=(0,_.useRef)(null),i=(0,_.useRef)(!1),a=(0,_.useRef)(null),o=(0,_.useRef)(null),s=(0,_.useRef)(null),c=(0,_.useRef)(!1),l=(0,_.useRef)(null),u=(0,_.useRef)(null),[d,f]=(0,_.useState)(!1),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(null),v=(0,_.useMemo)(()=>nJ(),[]),y=(0,_.useMemo)(()=>mY({adapter:_Y()}),[]),b=(0,_.useSyncExternalStore)(y.subscribe,y.getSnapshot,y.getSnapshot);(0,_.useEffect)(()=>(y.start(),()=>y.dispose()),[y]),(0,_.useEffect)(()=>{b.status!==`ready`&&(f(!1),g(null),v.clear())},[v,b.status]),(0,_.useEffect)(()=>{let e=window.matchMedia(`(min-width: 40rem)`),t=e=>{e.matches&&f(!1)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]),(0,_.useEffect)(()=>{function e(e){(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),r.current=document.activeElement===document.body?null:document.activeElement,y.dispatch({type:`SET_FINDER_OPEN`,open:!0}))}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[y]);let x={railDisclosure:()=>{f(!1),Pe(e)},checks:()=>Ie(),sidebar:()=>L(),chart:()=>{y.dispatch({type:`HIDE_CHART`}),Pe(a)},firstFlight:()=>He()};(0,_.useEffect)(()=>{function e(e){if(e.key!==`Escape`)return;let t=AY(RY(y.getSnapshot(),{firstFlightOpen:c.current}));if(t){if(e.preventDefault(),t.kind===`dismiss`){x[t.surface]();return}y.dispatch({type:`RETREAT`})}}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[y]);let{chart:S,checkData:C,checkError:w,coachmarksSeen:T,entrypointError:E,entrypointOpen:D,error:O,explanation:k,explanationError:A,explanationLoading:ee,finderOpen:te,focusedGraph:j,focusedMapData:ne,focusedStudiedCount:re,graph:M,hint:N,hoverNodeId:ie,languageFocus:ae,languageOptions:oe,layer:P,legendOpen:se,level:F,litRegionId:ce,llmStatus:le,mapError:ue,mapTab:de,mode:fe,modeChosen:pe,moduleIndex:me,parseProgress:he,pendingDawnRegionId:ge,picker:_e,projectName:ve,projectFailure:ye,region:be,revealedRegionIds:xe,visitedRegionIds:Se,selectedNode:Ce,showAll:we,showChart:Te,showChecks:Ee,sidebarOpen:De,status:Oe,studyData:ke,studyError:Ae}=b;(0,_.useLayoutEffect)(()=>{!i.current||te||F!==jG.SYSTEM||!u.current||(setTimeout(()=>u.current?.focus(),0),i.current=!1,r.current=null)},[te,F,be?.id]);let je=(0,_.useMemo)(()=>bG(M),[M]),Me=je[h]??null,I=h!==null&&Me!==null;c.current=I;let Ne=(0,_.useMemo)(()=>{if(!j)return null;let e=new Map;for(let t of j.regions){let n=tK(t.community_family);n!==null&&e.set(t.id,n)}return e},[j]);function Pe(t,n){setTimeout(()=>{for(let r of[t,n,e]){let e=r&&`current`in r?r.current:r;if(e?.isConnected&&e.getClientRects().length){e.focus();return}}},0)}function Fe(e){y.dispatch({type:`TOGGLE_SIDEBAR`}),De&&Pe(e.currentTarget,t)}function L(){y.dispatch({type:`TOGGLE_SIDEBAR`}),Pe(t)}function Ie(){y.dispatch({type:`CLOSE_CHECKS`}),Pe(o,u)}function Le(e){r.current=e.currentTarget,y.dispatch({type:`SET_FINDER_OPEN`,open:!0})}function Re(){i.current||(i.current=!1,y.dispatch({type:`SET_FINDER_OPEN`,open:!1}),Pe(r.current,n),r.current=null)}function ze(e){i.current=!0,y.dispatch({type:`GO_TO_REGION`,regionId:e})}function Be(){y.dispatch({type:`FOLLOW_HINT`}),y.getSnapshot().showChecks||Pe(u)}function Ve(e){let t=je[e];t&&(g(e),y.dispatch({type:`SET_LAYER`,layer:`galaxy`}),y.dispatch({type:`GO_TO_REGION`,regionId:t.id}))}function He(){g(null),Pe(s)}function Ue(){y.dispatch({type:`DISMISS_COACHMARKS`}),requestAnimationFrame(()=>l.current?.focus())}if(O)return(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The graph did not load.`}),(0,$.jsx)(`p`,{children:O}),(0,$.jsx)(`p`,{children:`Your progress is stored on this machine and is not affected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>y.start(),children:`Try again`})]});if(he)return(0,$.jsx)(BY,{progress:he,onCancel:()=>y.dispatch({type:`RESET_PROJECT`})});if(Oe===`picking`&&_e)return(0,$.jsx)(VY,{picker:_e,failure:ye,onBrowse:e=>y.dispatch({type:`BROWSE_PICKER`,path:e}),onSelect:e=>y.dispatch({type:`SELECT_PROJECT`,path:e})});if(!M||!j||!be)return(0,$.jsx)(`main`,{className:`load-state`,"aria-busy":`true`,children:(0,$.jsx)(`p`,{children:`Mapping parser evidence…`})});let We=P===`map`?`map`:`galaxy`,Ge=j.nodes.some(e=>e.id===be.id)?be.id:null,Ke=F===jG.SYSTEM&&P===`galaxy`?Oq(j.nodes.filter(e=>e.region===be.id)):[],qe=F===jG.SYSTEM?(0,$.jsxs)(`section`,{ref:u,className:`orientation-copy orientation-copy--system${P===`map`?` orientation-copy--inline`:``}`,tabIndex:-1,children:[(0,$.jsx)(`p`,{children:j.nodes.some(e=>e.region===be.id&&e.partial)?`${be.node_count} source ${be.node_count===1?`file remains`:`files remain`} visible · ${be.loc} lines. The module is unchartable beyond raw source because it has a syntax error.`:P===`map`?`The ${be.node_count} parser-proven ${be.node_count===1?`structure`:`structures`} inside this module ${be.node_count===1?`is`:`are`} drawn as planets in the Galaxy layer. This map shows how modules connect, not what is inside them.`:`${be.node_count} parser-proven ${be.node_count===1?`structure`:`structures`} · ${be.loc} ${be.loc===1?`line`:`lines`} in this system.`}),Ke.length?(0,$.jsxs)(`p`,{className:`system-orbit-note`,children:[(0,$.jsx)(`span`,{children:`Call layers`}),Ke.map(e=>(0,$.jsx)(`i`,{"data-unproven":e.unproven||void 0,children:e.label},e.ring)),(0,$.jsxs)(`small`,{children:[`Solid guides use certain calls only`,Ke.some(e=>e.unproven)?`; dashed means no proven path.`:`.`]})]}):null,(0,$.jsxs)(`div`,{className:`orientation-copy__actions`,children:[P===`map`&&Ge?(0,$.jsx)(`button`,{className:`check-launch check-launch--read`,type:`button`,onClick:()=>{m(!0),y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:Ge})},children:`Read the source`}):null,(0,$.jsx)(`button`,{ref:o,className:`check-launch`,type:`button`,onClick:()=>y.dispatch({type:`OPEN_CHECKS`}),children:j.nodes.some(e=>e.region===be.id&&e.partial)?`Check availability`:be.understood?`Review understanding`:`Prove understanding`})]})]}):null;return(0,$.jsxs)(`main`,{className:`app-shell`,"data-level":Te?`chart`:F.toLowerCase(),"data-mode":fe,children:[(0,$.jsxs)(`header`,{className:`instrument-rail`,children:[(0,$.jsxs)(`div`,{className:`brand-lockup`,children:[(0,$.jsx)(`span`,{className:`brand-mark`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`strong`,{children:`Codemble`}),(0,$.jsx)(`span`,{children:ve})]})]}),(0,$.jsx)(`nav`,{className:`location`,"aria-label":`Breadcrumb`,"aria-live":`polite`,children:Te?(0,$.jsx)(`span`,{"aria-current":`page`,children:`Star chart`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`button`,{type:`button`,disabled:F===jG.GALAXY,"aria-current":F===jG.GALAXY?`page`:void 0,onClick:()=>y.dispatch({type:`SET_LEVEL_GALAXY`}),children:`All modules`}),F===jG.GALAXY?(0,$.jsxs)(`small`,{children:[` · Home `,M.selected_entrypoint&&mK(M)?(0,$.jsx)(`button`,{type:`button`,className:`breadcrumb-home`,onClick:()=>y.dispatch({type:`ADVANCE_REGION`,regionId:mK(M).id}),children:mK(M).id}):M.selected_entrypoint?`unresolved`:`unselected`]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`button`,{type:`button`,disabled:F===jG.SYSTEM,"aria-current":F===jG.SYSTEM?`page`:void 0,onClick:()=>y.dispatch({type:`RETREAT`}),children:be.id})]}),F===jG.STUDY&&Ce?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`span`,{"aria-current":`page`,children:Ce.name})]}):null,ae===`all`?null:(0,$.jsxs)(`small`,{children:[` · `,LG(ae),` focus`]})]})}),(0,$.jsxs)(`div`,{className:`rail-overflow`,"data-open":d||void 0,children:[(0,$.jsxs)(`button`,{ref:e,className:`mobile-menu-trigger`,type:`button`,"aria-expanded":d,"aria-controls":`rail-overflow-panel`,onClick:()=>f(e=>!e),children:[(0,$.jsx)(`span`,{className:`rail-trigger__compact`,children:`Menu`}),(0,$.jsx)(`span`,{className:`rail-trigger__wide`,children:`More`})]}),(0,$.jsxs)(`div`,{className:`rail-overflow__panel`,id:`rail-overflow-panel`,onClickCapture:e=>{e.target.closest(`button`)&&!e.target.closest(`.switch-project`)&&f(!1)},children:[(0,$.jsxs)(`div`,{className:`rail-actions`,children:[(0,$.jsx)(`button`,{ref:t,className:`rail-action`,type:`button`,"aria-pressed":De,onClick:Fe,children:`Modules`}),(0,$.jsxs)(`button`,{ref:n,className:`rail-action`,type:`button`,onClick:Le,children:[`Find `,(0,$.jsx)(`kbd`,{children:`⌘K`})]}),Te?(0,$.jsxs)(`button`,{ref:a,className:`rail-action`,type:`button`,onClick:()=>{y.dispatch({type:`HIDE_CHART`}),Pe(a)},children:[`Back to `,We]}):(0,$.jsxs)($.Fragment,{children:[F===jG.GALAXY?null:(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>y.dispatch({type:`RETREAT`}),children:F===jG.STUDY?P===`map`?`Back to the module`:`Back to system`:`Back to ${We}`}),(0,$.jsx)(`button`,{ref:a,className:`rail-action`,type:`button`,onClick:()=>y.dispatch({type:`SHOW_CHART`}),children:`Star chart`})]})]}),(0,$.jsxs)(`div`,{className:`rail-more`,children:[M.entrypoint_candidates.length?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>y.dispatch({type:`CHANGE_HOME`}),children:`Change Home`}):null,(0,$.jsx)(YY,{onConfirm:()=>y.dispatch({type:`RESET_PROJECT`})})]}),(0,$.jsxs)(`div`,{className:`rail-controls`,children:[P===`galaxy`?(0,$.jsx)(`button`,{className:`rail-action rail-action--toggle`,type:`button`,"aria-pressed":we,title:`Draw every module at once, including the ones no route from Home reaches`,onClick:()=>y.dispatch({type:`TOGGLE_SHOW_ALL`}),children:`Show all`}):null,(0,$.jsx)(qY,{layer:P,mode:fe,onChange:e=>y.dispatch({type:`SET_LAYER`,layer:e})}),(0,$.jsx)(JY,{options:oe,value:ae,onChange:e=>y.dispatch({type:`SET_LANGUAGE_FOCUS`,language:e})}),(0,$.jsx)(bJ,{mode:fe,modeChosen:pe,onChoose:e=>y.dispatch({type:`SET_MODE`,mode:e})})]})]})]})]}),Te?(0,$.jsxs)(`section`,{className:`chart-stage`,"aria-label":`Language concept progress`,children:[De?(0,$.jsx)(KY,{index:me,currentRegionId:null,onGo:e=>y.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:L}):null,(0,$.jsx)(eX,{chart:S,studiedCount:re,exploredCount:Se.size,projectName:ve,mode:fe,overview:_K(M),onClearProgress:()=>y.dispatch({type:`CLEAR_PROGRESS`})})]}):(0,$.jsxs)(`section`,{ref:l,className:`map-stage`,"aria-label":`Parser-proven project map`,tabIndex:-1,children:[De?(0,$.jsx)(KY,{index:me,currentRegionId:F===jG.GALAXY?null:be?.id,onGo:e=>y.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:L}):null,P===`map`?(0,$.jsx)(pJ,{data:ne,mapTab:de,mode:fe,communityIndexByRegion:Ne,selectedRegionId:F===jG.GALAXY?void 0:be?.id,hasEntrypointCandidates:M.entrypoint_candidates.length>0,unsupportedSources:j.unsupported_sources,importCycles:M.import_cycles,error:ue,languageFocus:ae,languageFocusLabel:ae===`all`?``:LG(ae),onClearLanguageFocus:()=>y.dispatch({type:`SET_LANGUAGE_FOCUS`,language:`all`}),onSelectTab:e=>y.dispatch({type:`SET_MAP_TAB`,tab:e}),onSelectRegion:e=>y.dispatch({type:`ADVANCE_REGION`,regionId:e}),onSelectNode:e=>{m(!1),y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:e})},onRetry:()=>y.dispatch({type:`SET_LAYER`,layer:`map`}),viewportStore:v,children:qe}):(0,$.jsx)(Vq,{graph:j,level:F,region:be,selectedNode:Ce,hoverNodeId:ie,pendingDawnRegionId:ge,revealedRegionIds:xe,mode:fe,firstFlightActive:I,onHoverNode:e=>y.dispatch({type:`HOVER_NODE`,nodeId:e}),onAdvance:e=>y.dispatch({type:`ADVANCE`,node:e}),onRetreat:()=>y.dispatch({type:`RETREAT`}),onDawnConsumed:e=>y.dispatch({type:`CONSUME_DAWN`,regionId:e})}),(0,$.jsx)(`button`,{className:`legend-toggle`,type:`button`,"aria-expanded":se,onPointerEnter:()=>y.dispatch({type:`HOVER_NODE`,nodeId:null}),onClick:()=>y.dispatch({type:`TOGGLE_LEGEND`}),children:`Key`}),(0,$.jsxs)(`aside`,{className:`map-legend`,hidden:!se,tabIndex:0,"aria-label":P===`map`?`Map legend`:`Galaxy legend`,onPointerEnter:()=>y.dispatch({type:`HOVER_NODE`,nodeId:null}),onKeyDown:e=>{let t=e.currentTarget,n=Math.max(48,t.clientHeight*.8),r={ArrowDown:32,ArrowUp:-32,PageDown:n,PageUp:-n}[e.key];r===void 0?(e.key===`Home`||e.key===`End`)&&(e.preventDefault(),t.scrollTop=e.key===`Home`?0:t.scrollHeight):(e.preventDefault(),t.scrollBy({top:r,behavior:`auto`}))},children:[P===`galaxy`?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-size`}),`Size · `,fe===`easy`?`how much code`:`lines of code`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-brightness`}),`Brighter · `,fe===`easy`?`used in more places`:`more distinct callers`]})]}):null,(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--dim`}),`Dim · `,fe===`easy`?`not proven yet`:`not understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--lit`}),`Amber · `,fe===`easy`?`you proved you understand it`:`understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--partial`}),fe===`easy`?`Could not be read`:`Unchartable · syntax error`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-route`}),fe===`easy`?`Certain connection`:`Parser edge · certain`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-route legend-route--possible legend-route--dashed`}),fe===`easy`?`Possible connection`:`Possible relationship`]}),P===`galaxy`&&F===jG.GALAXY||P===`map`&&de===`architecture`?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`span`,{children:[(0,$.jsxs)(`span`,{className:`legend-communities`,"aria-hidden":`true`,children:[(0,$.jsx)(`i`,{}),(0,$.jsx)(`i`,{}),(0,$.jsx)(`i`,{}),(0,$.jsx)(`i`,{})]}),fe===`easy`?`Colour family · related systems and their shared routes`:`Hue family · one import community; internal routes inherit a tint`]}),oe.filter(e=>e.id!==`all`).map(e=>(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-tint`,style:{background:BG(e.id)??void 0}}),` `,e.label]},e.id))]}):null]}),P===`galaxy`&&F===jG.GALAXY?(0,$.jsxs)(`p`,{className:`orientation-bar`,children:[(0,$.jsxs)(`span`,{children:[j.regions.length,` `,ae===`all`?j.regions.length===1?`system`:`systems`:`${LG(ae)} ${j.regions.length===1?`system`:`systems`}`]}),(0,$.jsx)(`span`,{className:`orientation-bar__charted`,children:we?`all charted`:`${xe.size} charted`}),j.partial_files.length?(0,$.jsxs)(`span`,{className:`partial-summary`,children:[j.partial_files.length,` `,fe===`easy`?`could not be read`:`unchartable · syntax error`,QG(j.partial_files)?` · ${j.partial_files.length===1?`in`:`all under`} ${QG(j.partial_files)}/`:``]}):null,UG(j.unsupported_sources,fe)?(0,$.jsx)(`span`,{className:`unsupported-summary`,children:UG(j.unsupported_sources,fe)}):null]}):null,P===`galaxy`?qe:null,F===jG.SYSTEM&&Ee?(0,$.jsx)(ZY,{suite:C,error:w,mode:fe,overviewNoun:We,onClose:Ie,onSubmit:(e,t)=>y.dispatch({type:`SUBMIT_CHECK`,checkId:e,selectedIds:t})}):null,pe===!0&&D&&F===jG.GALAXY?(0,$.jsx)(XY,{candidates:M.entrypoint_candidates,nodes:M.nodes,selectedEntrypoint:M.selected_entrypoint,mode:fe,error:E,onSelect:e=>y.dispatch({type:`SELECT_ENTRYPOINT`,nodeId:e}),onContinue:()=>y.dispatch({type:`DISMISS_ENTRYPOINT`})}):null,ce?(0,$.jsxs)(`output`,{className:`illumination-pulse`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),(0,$.jsxs)(`strong`,{children:[ce,` understood`]})]}):null,F===jG.STUDY&&Ce?(0,$.jsx)(EJ,{node:Ce,study:ke,error:Ae,mode:fe,explanation:k,explanationLoading:ee,explanationError:A,llmStatus:le,revealSource:p,onSelectNode:e=>{m(!1),y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:e})},onRetryStudy:()=>y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:Ce.id}),onRetryNarration:()=>y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:Ce.id}),onClose:()=>{m(!1),y.dispatch({type:`RETREAT`})}}):null,pe===!0&&!D&&!T?(0,$.jsx)(qq,{layer:P,onDismiss:Ue}):null]}),te?(0,$.jsx)(GY,{index:me,onGo:ze,onClose:Re}):null,!Te&&!Ee&&pe===!0&&!D&&T?(0,$.jsx)(Wq,{hint:N,onFollow:Be,firstFlight:{available:je.length>0,active:I,stop:Me,index:h??0,total:je.length,mode:fe,triggerRef:s,onStart:()=>Ve(0),onBack:()=>Ve(h-1),onNext:()=>Ve(h+1),onExit:He}}):null,(0,$.jsxs)(`footer`,{className:`status-line`,children:[(0,$.jsx)(`span`,{children:Te?`${S.length} concepts detected`:ae===`all`?`${M.nodes.length} nodes · ${M.edges.length} edges`:`${j.nodes.length}/${M.nodes.length} nodes · ${j.edges.length} focused edges`}),(0,$.jsx)(`span`,{children:Te?`${re} focused structures studied this session`:P===`map`?`Click a box or row to study · Switch tabs to change view`:`Drag to orbit · Scroll to zoom · Click to move closer · Escape to move back`}),(0,$.jsx)(`span`,{children:`Local only`})]})]})}var IY=Object.fromEntries(oY.map(({id:e,copy:t})=>[e,t])),LY=oY.map(({id:e})=>e);function RY(e,{firstFlightOpen:t=!1}={}){return{ready:e.status===`ready`,canRetreat:e.layer===`map`&&e.level!==jG.GALAXY,showChart:e.showChart,finderOpen:e.finderOpen,sidebarOpen:e.sidebarOpen,showChecks:e.showChecks,entrypointOpen:e.entrypointOpen,firstFlightOpen:t,nativeDialogOpen:document.querySelector(`dialog[open]`)!==null,railDisclosureOpen:document.querySelector(`.rail-overflow[data-open]`)!==null,editableFocus:zY(document.activeElement)}}function zY(e){if(!e)return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable===!0}function BY({progress:e,onCancel:t}){let{stage:n,detail:r,files_done:i,files_total:a,pollError:o,pollOutage:s,attempts:c,path:l}=e,[u,d]=(0,_.useState)(!1),[f,p]=(0,_.useState)(``),m=(0,_.useRef)(null),h=LY.indexOf(n);(0,_.useEffect)(()=>{m.current?.focus()},[]);async function g(){d(!0),p(``);try{await t()}catch(e){p(e.message),d(!1)}}return(0,$.jsxs)(`main`,{className:`loading-screen`,children:[(0,$.jsxs)(`header`,{className:`loading-header`,children:[(0,$.jsx)(`p`,{className:`picker-wordmark`,children:`Codemble`}),(0,$.jsxs)(`h1`,{ref:m,tabIndex:-1,children:[`Mapping `,(0,$.jsx)(`span`,{className:`loading-path`,children:l})]}),(0,$.jsx)(`p`,{className:`loading-subtitle`,children:`Parsing runs on your machine. Nothing is sent anywhere.`})]}),(0,$.jsx)(`ol`,{className:`loading-stages`,"aria-label":`Parse stages`,children:LY.map((e,t)=>{let n=t{let e=m.current;l?p.current?.focus():e&&f.current?.focus(),m.current=!!l},[l]),(0,$.jsxs)(`main`,{className:`picker-screen`,"aria-busy":d,children:[(0,$.jsxs)(`header`,{className:`picker-header`,children:[(0,$.jsx)(`p`,{className:`picker-wordmark`,children:`Codemble`}),(0,$.jsx)(`h1`,{children:`Choose the project to chart`}),(0,$.jsx)(`p`,{className:`picker-subtitle`,children:`Codemble reads the folder locally and turns it into a galaxy. Nothing leaves this machine.`})]}),s.length?(0,$.jsxs)(`section`,{className:`picker-recents`,"aria-labelledby":`picker-recents-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-recents-heading`,children:`Continue where you left off`}),(0,$.jsx)(`ul`,{children:s.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:d,onClick:()=>r(e.project_root),children:[(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.project_root}),(0,$.jsxs)(`span`,{className:`picker-recent-lit`,children:[e.understood_count,` `,e.understood_count===1?`system`:`systems`,` lit last visit`]})]})},e.project_root))})]}):null,u?(0,$.jsx)(HY,{scale:u,busy:d,onBrowse:n}):null,t?(0,$.jsx)(WY,{failure:t,busy:d,onSelect:r}):c?(0,$.jsxs)(`div`,{className:`picker-error`,children:[(0,$.jsx)(`p`,{role:`alert`,children:c}),l?(0,$.jsx)(`button`,{ref:p,className:`picker-retry`,type:`button`,disabled:d,onClick:()=>n(l),children:`Try this folder again`}):null]}):null,(0,$.jsxs)(`section`,{className:`picker-browser`,"aria-labelledby":`picker-browser-heading`,children:[(0,$.jsx)(`h2`,{ref:f,id:`picker-browser-heading`,tabIndex:-1,children:`Browse folders`}),(0,$.jsx)(`p`,{className:`picker-path`,children:i}),(0,$.jsxs)(`ul`,{children:[a?(0,$.jsx)(`li`,{children:(0,$.jsx)(`button`,{type:`button`,disabled:d,onClick:()=>n(a),children:`↑ Up`})}):null,o.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:d,onClick:()=>n(e.path),children:[e.name,`/`]})},e.path))]}),(0,$.jsx)(`button`,{className:`picker-select`,type:`button`,disabled:d,onClick:()=>r(i),children:d?`Mapping…`:`Map this folder`})]})]})}function HY({scale:e,busy:t,onBrowse:n}){let r=e.suggestions.filter(e=>e.path!==`.`);return(0,$.jsxs)(`section`,{className:`picker-scale`,role:`alert`,"aria-labelledby":`picker-scale-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-scale-heading`,children:`That folder is too big to map at once.`}),(0,$.jsxs)(`p`,{children:[`It has `,e.file_count,` supported source files; Codemble maps up to`,` `,e.scale_cap,`. Choose a smaller scope — busiest first.`]}),r.length?(0,$.jsx)(`ul`,{className:`picker-scale-scopes`,children:r.map(r=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:t,onClick:()=>n(`${e.root}/${r.path}`),children:[(0,$.jsxs)(`span`,{children:[r.path,`/`]}),(0,$.jsxs)(`small`,{children:[r.file_count,` files`]})]})},r.path))}):null,(0,$.jsx)(UY,{busy:t,onBrowse:n})]})}function UY({busy:e,onBrowse:t}){let[n,r]=(0,_.useState)(``);return(0,$.jsxs)(`form`,{className:`picker-path-entry`,onSubmit:e=>{e.preventDefault();let r=n.trim();r&&t(r)},children:[(0,$.jsx)(`label`,{htmlFor:`picker-path-input`,children:`Or type a folder path`}),(0,$.jsx)(`input`,{id:`picker-path-input`,name:`project-path`,type:`text`,value:n,disabled:e,autoComplete:`off`,spellCheck:!1,placeholder:`/Users/you/project/src`,onChange:e=>r(e.target.value)}),(0,$.jsx)(`button`,{type:`submit`,disabled:e||!n.trim(),children:`Go`})]})}function WY({failure:e,busy:t,onSelect:n}){return(0,$.jsxs)(`section`,{className:`picker-failure`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`Codemble could not map that folder.`}),(0,$.jsx)(`p`,{children:`Nothing on disk changed, and no project's saved progress was touched. Try it again, or choose a different folder below.`}),(0,$.jsxs)(`p`,{className:`picker-failure__detail`,children:[(0,$.jsx)(`span`,{children:`What the parser reported`}),(0,$.jsx)(`code`,{children:e.detail})]}),(0,$.jsxs)(`button`,{className:`picker-select`,type:`button`,disabled:t,onClick:()=>n(e.path),children:[`Try `,(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.path}),` again`]})]})}function GY({index:e,onGo:t,onClose:n}){let[r,i]=(0,_.useState)(``),[a,o]=(0,_.useState)(0),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useMemo)(()=>{let t=r.trim().toLowerCase();return t?e.filter(e=>e.label.toLowerCase().includes(t)||e.file.toLowerCase().includes(t)).slice(0,60):[...e].sort((e,t)=>Number(t.home)-Number(e.home)||Number(t.understood)-Number(e.understood)||t.centrality-e.centrality||e.label.localeCompare(t.label)||e.id.localeCompare(t.id)).slice(0,60)},[e,r]);(0,_.useLayoutEffect)(()=>{let e=s.current;e&&!e.open&&e.showModal(),c.current?.focus()},[]),(0,_.useEffect)(()=>o(0),[r]);let u=l[Math.min(a,l.length-1)]??null;function d(e){e.key===`ArrowDown`?(e.preventDefault(),o(e=>Math.min(e+1,l.length-1))):e.key===`ArrowUp`?(e.preventDefault(),o(e=>Math.max(e-1,0))):e.key===`Enter`&&u?(e.preventDefault(),t(u.id)):e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),n())}return(0,$.jsxs)(`dialog`,{ref:s,className:`module-finder`,"aria-label":`Find a module`,onCancel:e=>{e.preventDefault(),n()},onClose:n,children:[(0,$.jsx)(`input`,{ref:c,name:`module-search`,type:`search`,value:r,placeholder:`Find a module…`,"aria-label":`Find a module by name or path`,autoComplete:`off`,spellCheck:!1,onChange:e=>i(e.target.value),onKeyDown:d}),(0,$.jsx)(`ul`,{role:`listbox`,"aria-label":`Matching modules`,children:l.map((e,n)=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n===a,"data-active":n===a||void 0,onMouseEnter:()=>o(n),onClick:()=>t(e.id),children:[(0,$.jsx)(`strong`,{children:e.label}),e.file===e.label?e.hops===0?null:(0,$.jsx)(`small`,{children:typeof e.hops==`number`?`${e.hops} ${e.hops===1?`route`:`routes`} from Home`:`no route from Home`}):(0,$.jsx)(`small`,{children:e.file}),e.home?(0,$.jsx)(`em`,{children:`Home`}):e.understood?(0,$.jsx)(`em`,{children:`lit`}):null]})},e.id))}),l.length?null:(0,$.jsx)(`p`,{className:`module-finder__empty`,children:`No module matches that.`})]})}function KY({index:e,currentRegionId:t,onGo:n,onClose:r}){let i=(0,_.useMemo)(()=>YG(e),[e]),a=(0,_.useRef)(null);return(0,_.useLayoutEffect)(()=>{a.current?.focus()},[]),(0,$.jsxs)(`aside`,{className:`index-sidebar`,"aria-label":`Project index`,children:[(0,$.jsxs)(`header`,{children:[(0,$.jsx)(`h2`,{children:`Modules`}),(0,$.jsx)(`button`,{ref:a,type:`button`,onClick:r,"aria-label":`Close the project index`,children:`×`})]}),(0,$.jsx)(`div`,{className:`index-sidebar__scroll`,children:i.map(e=>(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{title:e.name,children:e.name}),(0,$.jsx)(`ul`,{children:e.members.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-current":e.id===t?`true`:void 0,"data-lit":e.understood||void 0,title:e.file,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.display??e.label}),e.home?(0,$.jsx)(`em`,{children:`Home`}):null]})},e.id))})]},e.community))})]})}function qY({layer:e,mode:t,onChange:n}){return(0,$.jsx)(`nav`,{className:`layer-switcher`,"aria-label":`View layer`,children:[{id:`galaxy`,label:`Galaxy`},{id:`map`,label:t===`easy`?`Diagram`:`Map`}].map(t=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":e===t.id,onClick:()=>n(t.id),children:t.label},t.id))})}function JY({options:e,value:t,onChange:n}){return e.length<=2?null:(0,$.jsxs)(`nav`,{className:`language-focus`,"aria-label":`Language focus`,children:[(0,$.jsx)(`span`,{className:`language-focus__label`,children:`Focus`}),(0,$.jsx)(`div`,{children:e.map(e=>(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Focus ${e.label}: ${e.count} ${e.count===1?`system`:`systems`}`,"aria-pressed":t===e.id,title:e.label,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.shortLabel}),(0,$.jsx)(`small`,{children:e.count})]},e.id))})]})}function YY({onConfirm:e}){let[t,n]=(0,_.useState)(!1),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(``),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useRef)(!1);(0,_.useEffect)(()=>{t?c.current?.focus():l.current&&s.current?.focus(),l.current=t},[t]);function u(){n(!1),o(``)}async function d(){i(!0),o(``);try{await e()}catch(e){o(e.message),i(!1)}}return(0,$.jsx)(`div`,{className:`switch-project`,"data-confirming":t||void 0,role:t?`group`:void 0,"aria-label":t?`Switch project`:void 0,tabIndex:t?-1:void 0,ref:t?c:void 0,onKeyDown:e=>{e.key===`Escape`&&t&&!r&&u()},children:t?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`p`,{children:`Progress is saved per project, so this galaxy comes back lit.`}),a?(0,$.jsx)(`p`,{className:`switch-project__error`,role:`alert`,children:a}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:d,children:r?`Releasing…`:`Switch`}),(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:u,children:`Cancel`})]})]}):(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,ref:s,onClick:()=>n(!0),children:`Switch project`})})}function XY({candidates:e,nodes:t,selectedEntrypoint:n,mode:r,error:i,onSelect:a,onContinue:o}){let s=new Map(t.map(e=>[e.id,e])),c=(0,_.useMemo)(()=>{let t=new Map;for(let n of e){let e=s.get(n),r=(e?.file??n).split(`/`).filter(Boolean),i=r.length>1?`${r[0]}/`:`project root`;t.has(i)||t.set(i,[]),t.get(i).push({candidate:n,node:e})}return[...t].map(([e,t])=>({name:e,rows:t,bestRank:Math.min(...t.map(e=>e.node?.entrypoint_rank??2**53-1))})).sort((e,t)=>e.bestRank-t.bestRank||e.name.localeCompare(t.name)).map((e,t)=>({...e,open:t===0||e.bestRank===0}))},[e,t]),l=c[0]?.rows[0]?.candidate??null,u=(0,_.useRef)(null),d=(0,_.useRef)(null);return(0,_.useLayoutEffect)(()=>{let e=d.current;e&&!e.open&&e.showModal(),u.current?.focus()},[]),(0,$.jsxs)(`dialog`,{ref:d,className:`entrypoint-picker`,"aria-labelledby":`entrypoint-heading`,onCancel:e=>e.preventDefault(),children:[(0,$.jsx)(`p`,{children:`Home calibration`}),(0,$.jsx)(`h1`,{id:`entrypoint-heading`,children:e.length?`Where does your project start?`:`No clear entrypoint found.`}),(0,$.jsx)(`p`,{children:e.length?r===`easy`?`Your project could start from more than one place, and Codemble will not guess. Pick the one you actually run — best guess first.`:`The parser found ranked candidates but cannot choose one honestly. Select the structure you run.`:`No file here declares a startup structure the parser recognises, and Codemble will not guess one. Explore the map without Home — every system, check, explanation, and lens note still works.`}),e.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`p`,{className:`entrypoint-count`,children:[e.length,` ranked`,` `,e.length===1?`candidate`:`candidates`,` in `,c.length,` `,c.length===1?`scope`:`scopes`]}),(0,$.jsx)(`div`,{className:`entrypoint-scroll`,children:c.map(e=>(0,$.jsxs)(`details`,{open:e.open,children:[(0,$.jsxs)(`summary`,{children:[(0,$.jsx)(`span`,{children:e.name}),(0,$.jsxs)(`small`,{children:[e.rows.length,` `,e.rows.length===1?`candidate`:`candidates`]})]}),(0,$.jsx)(`div`,{className:`entrypoint-candidates`,children:e.rows.map(({candidate:e,node:t})=>(0,$.jsxs)(`button`,{ref:e===l?u:void 0,type:`button`,onClick:()=>a(e),children:[(0,$.jsx)(`span`,{children:e}),(0,$.jsxs)(`small`,{children:[t?.file,`:`,t?.lineno,` ·`,` `,r===`easy`?`candidate ${(t?.entrypoint_rank??0)+1}`:`parser rank ${t?.entrypoint_rank}`]})]},e))})]},e.name))})]}):null,i?(0,$.jsx)(`p`,{className:`entrypoint-error`,role:`alert`,children:i}):null,(0,$.jsx)(`button`,{ref:e.length?void 0:u,className:`entrypoint-continue`,type:`button`,onClick:o,children:n?`Keep current Home`:`Explore without Home`})]})}function ZY({suite:e,error:t,mode:n,overviewNoun:r,onClose:i,onSubmit:a}){let o=e?.checks.find(e=>!e.passed)??null,s=e?.checks.filter(e=>e.passed).length??0,[c,l]=(0,_.useState)(()=>new Set),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(``),[m,h]=(0,_.useState)(!1),[g,v]=(0,_.useState)(``),y=(0,_.useRef)(null),b=(0,_.useRef)(null),x=(0,_.useRef)(null),S=(0,_.useRef)(null),C=(0,_.useRef)(null),w=(0,_.useRef)(null),T=(0,_.useRef)(null);(0,_.useEffect)(()=>{l(new Set),d(null),v(``)},[o?.id]),(0,_.useLayoutEffect)(()=>{y.current?.focus()},[]),(0,_.useLayoutEffect)(()=>{e?.region_understood?S.current?.focus():u?b.current?.focus():f&&x.current?.focus()},[e?.region_understood,u,f]),(0,_.useLayoutEffect)(()=>{u&&C.current?.scrollIntoView({block:`nearest`})},[u]),(0,_.useLayoutEffect)(()=>{if(!o)return;let e=w.current,t=T.current;if(!e||!t)return;let n=!1,r=0,i=()=>{if(n||!window.matchMedia(`(max-width: 39.999rem)`).matches&&e.scrollHeight<=e.clientHeight+1)return;let r=t.getBoundingClientRect().top-e.getBoundingClientRect().top;e.scrollTop+=r};return i(),r=window.requestAnimationFrame(i),document.fonts?.ready.then(()=>{n||(window.cancelAnimationFrame(r),r=window.requestAnimationFrame(i))}),()=>{n=!0,window.cancelAnimationFrame(r)}},[o?.id]);function E(e,t){p(``),l(n=>{if(!t)return new Set([e]);let r=new Set(n);return r.has(e)?r.delete(e):r.add(e),r})}async function D(e){if(e.preventDefault(),!(!o||c.size===0)){h(!0),v(``);try{let e=await a(o.id,[...c]);e.correct?(p(e.message),d(null)):(p(``),d(e))}catch(e){v(e.message)}finally{h(!1)}}}return(0,$.jsxs)(`aside`,{ref:w,className:`check-panel`,"aria-label":`Graph-derived understanding checks`,children:[(0,$.jsxs)(`header`,{className:`check-panel__header`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:n===`easy`?`Quiz · answers come from your code, not AI`:`Active recall · graph only`}),(0,$.jsx)(`h1`,{ref:y,tabIndex:-1,children:e?.region_id??`Loading checks`})]}),(0,$.jsx)(`button`,{className:`check-close`,type:`button`,onClick:i,children:`Close`})]}),t||g?(0,$.jsxs)(`div`,{className:`check-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The checks did not load.`}),(0,$.jsxs)(`p`,{children:[t||g,` The galaxy remains available.`]})]}):null,!e&&!t?(0,$.jsx)(`p`,{className:`check-loading`,role:`status`,children:`Deriving answers from parser edges…`}):null,e?.region_understood?(0,$.jsxs)(`div`,{className:`check-complete`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{className:`check-complete__star`,"aria-hidden":`true`,children:`✦`}),(0,$.jsx)(`h2`,{children:r===`map`?`Module lit.`:`System lit.`}),(0,$.jsx)(`p`,{children:n===`easy`?`Codemble remembers the exact code you proved. Edit this file and only this ${r===`map`?`module`:`system`} dims again.`:`This region's source hash matches the checks you passed. Edit its file and only this system will dim again.`}),(0,$.jsxs)(`button`,{ref:S,className:`check-primary`,type:`button`,onClick:i,children:[`Back to the `,r===`map`?`module`:`system`]})]}):null,e&&!e.region_understood&&e.checks.length===0?(0,$.jsxs)(`div`,{className:`check-state`,children:[(0,$.jsx)(`h2`,{children:`No safe check yet.`}),(0,$.jsx)(`p`,{children:`Every question here is answered by the parser graph, and this region has no certain relationship Codemble can build one from. It stays dim rather than lighting on a question that would prove nothing. Import this module somewhere, or call something inside it, and its checks appear.`})]}):null,e&&!e.region_understood&&e.checks.length>0&&!o?(0,$.jsxs)(`div`,{className:`check-state`,children:[(0,$.jsx)(`h2`,{children:`These checks are out of date.`}),(0,$.jsx)(`p`,{children:`This module is dim again, but this panel is still holding the answers from before. Reopen it to get the questions back — nothing you proved has been lost anywhere else.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:i,children:`Reopen the checks`})]}):null,o&&!e.region_understood?(0,$.jsxs)(`form`,{className:`active-check`,onSubmit:D,children:[(0,$.jsxs)(`div`,{className:`check-progress`,children:[(0,$.jsxs)(`span`,{children:[`Check `,s+1,` of `,e.checks.length]}),(0,$.jsx)(`progress`,{value:s,max:e.checks.length})]}),f?(0,$.jsxs)(`p`,{ref:x,className:`check-affirmation`,role:`status`,tabIndex:-1,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),` `,f]}):null,(0,$.jsxs)(`fieldset`,{ref:T,children:[(0,$.jsx)(`legend`,{children:o.prompt_voices[n]}),o.multiple?(0,$.jsx)(`p`,{children:`Select every answer supported by the graph.`}):null,(0,$.jsx)(`div`,{className:`check-options`,children:o.options.map(e=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:o.multiple?`checkbox`:`radio`,name:`answer-${o.id}`,value:e.id,checked:c.has(e.id),onChange:()=>E(e.id,o.multiple)}),(0,$.jsx)(`span`,{children:e.label})]},e.id))})]}),u&&!u.correct?(0,$.jsx)(`div`,{ref:b,className:`check-feedback`,role:`status`,tabIndex:-1,children:(0,$.jsx)(`strong`,{children:u.message})}):null,(0,$.jsx)(`div`,{className:`check-submit-bar`,children:(0,$.jsx)(`button`,{ref:C,className:`check-primary`,type:`submit`,disabled:!c.size||m,children:m?`Checking parser evidence…`:`Check answer`})})]}):null]})}function QY({overview:e,mode:t,charted:n}){let r=t===`easy`,i=e.languages.map(e=>`${e.label} ${e.count}`).join(` · `);return(0,$.jsxs)(`section`,{className:`project-summary`,"aria-label":`Project summary`,children:[(0,$.jsxs)(`p`,{className:`project-summary__lead`,children:[r?`${e.modules} files of code, holding ${e.structures} functions and classes between them.`:`${e.modules} modules · ${e.structures} structures · ${e.lines} lines.`,` `,e.home?r?`It starts at ${e.home.id}.`:`Entrypoint ${e.home.id}.`:r?`Codemble could not tell which file starts it.`:`No entrypoint resolved.`]}),(0,$.jsxs)(`dl`,{className:`project-summary__facts`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Written in`:`Languages`}),(0,$.jsx)(`dd`,{children:i||`—`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Biggest files`:`Largest by LOC`}),(0,$.jsx)(`dd`,{children:e.biggest.length?e.biggest.map(e=>`${KG(e.id)} (${e.value})`).join(`, `):`—`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Called from the most places`:`Highest centrality`}),(0,$.jsx)(`dd`,{children:e.busiest.length?e.busiest.map(e=>`${KG(e.id)} (${e.value})`).join(`, `):`—`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`You have proved`:`Understood`}),(0,$.jsxs)(`dd`,{children:[e.understood,` of `,e.modules,` `,r?e.modules===1?`file`:`files`:`modules`]})]}),e.unreadable||e.unsupported?(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Not included`:`Outside the graph`}),(0,$.jsx)(`dd`,{children:[e.unreadable?`${e.unreadable} ${e.unreadable===1?`file`:`files`} could not be read`:``,e.unsupported?`${e.unsupported} in a language Codemble does not parse`:``].filter(Boolean).join(` · `)})]}):null,e.importCycles.length?(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Files that bring each other in`:`Proven import cycles`}),(0,$.jsxs)(`dd`,{children:[e.importCycles.length,` `,e.importCycles.length===1?`cycle group`:`cycle groups`,` · `,e.importCycles.slice().sort((e,t)=>t.length-e.length||e.join(`\0`).localeCompare(t.join(`\0`)))[0].join(`, `),` · each file can reach every other through proven imports`]})]}):null]}),(0,$.jsx)(`button`,{className:`project-summary__export`,type:`button`,onClick:()=>$Y(e,n),children:r?`Save a project guide`:`Export Markdown brief`})]})}function $Y(e,t){let n=PY(e,{charted:t}),r=URL.createObjectURL(new Blob([n],{type:`text/markdown;charset=utf-8`})),i=document.createElement(`a`);i.href=r,i.download=NY(e),document.body.append(i),i.click(),i.remove(),window.setTimeout(()=>URL.revokeObjectURL(r),0)}function eX({chart:e,studiedCount:t,exploredCount:n,projectName:r,mode:i,overview:a,onClearProgress:o}){let s=e.filter(e=>e.understood_nodes>0).length,c=(0,_.useRef)(null);return(0,_.useLayoutEffect)(()=>{c.current?.focus()},[]),(0,$.jsxs)(`section`,{className:`star-chart-screen`,"aria-labelledby":`star-chart-heading`,children:[(0,$.jsxs)(`header`,{className:`star-chart-intro`,children:[(0,$.jsx)(`p`,{children:r}),(0,$.jsx)(`h1`,{ref:c,id:`star-chart-heading`,tabIndex:-1,children:`What this project is.`}),a?(0,$.jsx)(QY,{overview:a,mode:i,charted:n}):null,(0,$.jsx)(`h2`,{className:`star-chart-section`,children:i===`easy`?`Ideas your code uses`:`Parser-detected concepts`}),(0,$.jsx)(`p`,{children:`Explored counts the systems you have flown to. Encountered comes from real syntax. Studied tracks this session. Understood lights only after graph-derived checks pass.`}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Systems explored`}),(0,$.jsx)(`dd`,{children:n})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts encountered`}),(0,$.jsx)(`dd`,{children:e.length})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied this session`}),(0,$.jsx)(`dd`,{children:t})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts understood`}),(0,$.jsx)(`dd`,{children:s})]})]})]}),(0,$.jsx)(`div`,{className:`concept-ledger`,role:`list`,"aria-label":`Language concept progress`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`concept-row`,role:`listitem`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h2`,{children:IG(e.concept)}),(0,$.jsxs)(`span`,{children:[IG(e.language),` · `,e.occurrences,` parser `,e.occurrences===1?`occurrence`:`occurrences`]})]}),(0,$.jsx)(`div`,{className:`concept-meter`,"aria-label":`${e.understood_nodes} of ${e.nodes} ${e.nodes===1?`structure`:`structures`} understood`,children:(0,$.jsx)(`span`,{style:{width:`${e.nodes?e.understood_nodes/e.nodes*100:0}%`}})}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied (session)`}),(0,$.jsxs)(`dd`,{children:[e.studied_nodes,`/`,e.nodes]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Understood`}),(0,$.jsxs)(`dd`,{children:[e.understood_nodes,`/`,e.nodes]})]})]})]},`${e.language}:${e.concept}`))}),(0,$.jsx)(tX,{projectName:r,onConfirm:o})]})}function tX({projectName:e,onConfirm:t}){let[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(``),c=(0,_.useRef)(null),l=(0,_.useRef)(null),u=(0,_.useRef)(!1);(0,_.useEffect)(()=>{n?l.current?.focus():u.current&&c.current?.focus(),u.current=n},[n]);function d(){r(!1),s(``)}async function f(){a(!0),s(``);try{await t(),r(!1)}catch(e){s(e.message)}finally{a(!1)}}return n?(0,$.jsxs)(`section`,{className:`progress-reset progress-reset--confirming`,role:`group`,"aria-label":`Clear this project's progress`,tabIndex:-1,ref:l,onKeyDown:e=>{e.key===`Escape`&&!i&&d()},children:[(0,$.jsxs)(`p`,{role:`alert`,children:[`This dims every system you lit in `,e,` and cannot be undone. Your other projects keep their progress, and no source file is touched.`]}),o?(0,$.jsx)(`p`,{className:`progress-reset__error`,role:`alert`,children:o}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`check-primary progress-reset__confirm`,type:`button`,disabled:i,onClick:f,children:i?`Clearing…`:`Yes, clear ${e}`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,disabled:i,onClick:d,children:`Keep it`})]})]}):(0,$.jsxs)(`section`,{className:`progress-reset`,children:[(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,ref:c,onClick:()=>r(!0),children:`Clear this project's progress`}),(0,$.jsxs)(`p`,{children:[`Start `,e,` over with every system dim again.`]})]})}var nX=class extends _.Component{constructor(e){super(e),this.state={message:``}}static getDerivedStateFromError(e){return{message:e instanceof Error?e.message:String(e)}}componentDidCatch(e,t){console.error(`Codemble stopped rendering:`,e,t?.componentStack)}render(){return this.state.message?(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The galaxy stopped rendering.`}),(0,$.jsx)(`p`,{children:this.state.message}),(0,$.jsx)(`p`,{children:`Your progress is saved on this machine; reloading re-reads it.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>window.location.reload(),children:`Reload Codemble`})]}):this.props.children}};(0,v.createRoot)(document.getElementById(`root`)).render((0,$.jsx)(_.StrictMode,{children:(0,$.jsx)(nX,{children:(0,$.jsx)(FY,{})})}));
\ No newline at end of file
+`;Object.freeze({vertex:$W,fragment:eG});function tG(e){let t=2166136261,n=String(e??``);for(let e=0;e>>0)/4294967296}function nG(e=32){return new yo(1,e,Math.max(8,e/2))}function rG({node:e,color:t,palette:n}){return new jo({vertexShader:$W,fragmentShader:eG,uniforms:{uBase:{value:new H(t)},uAmber:{value:new H(n.star)},uSeed:{value:tG(e.id)},uLit:{value:+!!e.understood},uPartial:{value:+!!e.partial},uClass:{value:+(e.kind===`class`)},uDim:{value:+!!e.focusDim}}})}function iG({node:e,color:t,palette:n,radius:r,geometry:i}){let a=new na(i,rG({node:e,color:t,palette:n}));return a.scale.setScalar(r),a.rotation.set(tG(`${e.id}:tilt`)*.9-.45,tG(e.id)*Math.PI*2,0),a.userData.codembleBody=!0,a}function aG(e,{reducedMotion:t=!1}={}){if(t)return()=>{};let n=0,r=performance.now(),i=()=>{let t=performance.now(),a=Math.min(.05,(t-r)/1e3);r=t,e.traverse(e=>{e.userData?.codembleBody&&(e.rotation.y+=a*.06)}),n=requestAnimationFrame(i)};return n=requestAnimationFrame(i),()=>cancelAnimationFrame(n)}var oG=`.orientation-copy button, .legend-toggle`,sG=`.orientation-bar, .keyboard-focus`;function cG({host:e,renderer:t,getStyle:n=e=>getComputedStyle(e)}){let r=e?.getBoundingClientRect?.(),i=lG(r,t),a=e?.closest?.(`.map-stage`);return Object.freeze(!a||!r?{viewport:i,clickObstructions:Object.freeze([]),nameObstructions:Object.freeze([])}:{viewport:i,clickObstructions:uG(a,oG,r,{accepts:e=>n(e).pointerEvents!==`none`}),nameObstructions:uG(a,sG,r)})}function lG(e,t){if(e?.width&&e?.height)return Object.freeze({width:e.width,height:e.height});let n=t?.width?.(),r=t?.height?.();return n&&r?Object.freeze({width:n,height:r}):null}function uG(e,t,n,{accepts:r=()=>!0}={}){let i=[];for(let a of e.querySelectorAll(t)){if(!r(a))continue;let e=a.getBoundingClientRect();!e.width||!e.height||i.push(Object.freeze({left:e.left-n.left,right:e.right-n.left,top:e.top-n.top,bottom:e.bottom-n.top}))}return Object.freeze(i)}var dG=1600,fG=.22,pG=.52,mG=.74,hG=3,gG=7;function _G(e){let t=Math.min(1,Math.max(0,e)),n=(e,n)=>Math.min(1,Math.max(0,(t-e)/(n-e)));return Object.freeze({ignite:n(0,fG),travel:n(fG,pG),flare:n(pG,mG),settle:n(mG,1)})}function vG(e,t,n=new Map){let r=[];for(let n of t??[]){if(!n?.certain)continue;let t=n.dst===e?n.src:n.src===e?n.dst:null;t===null||t===e||r.push(t)}let i=[...new Set(r)];return i.sort((e,t)=>{let r=n.get(e),i=n.get(t);return(typeof r==`number`?r:2**53-1)-(typeof i==`number`?i:2**53-1)||e.localeCompare(t)}),i.slice(0,hG)}function yG({scene:e,regionId:t,palette:n,dressing:r,routes:i=[],hopsById:a=new Map}){if(Bd())return()=>{};let o=e.getObjectByName(`codemble-system-${t}`);if(!o)return()=>{};let s=[];o.traverse(e=>{e.isSprite&&s.push([e,e.material.opacity,e.scale.clone()])});let c=s.map(([e])=>e.material.color.clone()),l=new H(n.star),u=new V;o.getWorldPosition(u);let d=[];if(r?.spark)for(let n of vG(t,i,a)){let t=e.getObjectByName(`codemble-system-${n}`);if(!t)continue;let i=new V;t.getWorldPosition(i);let a=r.spark();a.scale.setScalar(gG),a.position.copy(i),e.add(a),d.push({sprite:a,origin:i})}let f=()=>{s.forEach(([e,t,n],r)=>{e.material.color.copy(c[r]),e.material.opacity=t,e.scale.copy(n)});for(let{sprite:t}of d)e.remove(t),t.material.opacity=0;d.length=0},p=0,m=performance.now(),h=()=>{let e=Math.min(1,(performance.now()-m)/dG),t=_G(e),n=1-(1-t.travel)**3;for(let{sprite:e,origin:r}of d)e.position.lerpVectors(r,u,n),e.material.opacity=t.flare>0?0:Math.min(1,t.ignite)*.9;let r=Math.sin(Math.min(1,t.flare)*Math.PI*.5)*(1-t.settle);if(s.forEach(([e,t,n],i)=>{e.material.color.copy(c[i]).lerp(l,r*.85),e.material.opacity=t+r*.5,e.scale.copy(n).multiplyScalar(1+r*.45)}),e<1){p=requestAnimationFrame(h);return}f()};return p=requestAnimationFrame(h),()=>{cancelAnimationFrame(p),f()}}function bG(e){if(!e?.selected_entrypoint)return[];let t=new Map((e.nodes??[]).map(e=>[e.id,e])),n=new Map((e.regions??[]).map(e=>[e.id,e])),r=t.get(e.selected_entrypoint),i=r?n.get(r.region):null;if(!i?.home)return[];let a=new Map;for(let r of e.edges??[]){if(r.kind!==`import`||r.external||r.certain!==!0)continue;let e=t.get(r.src)?.region,i=t.get(r.dst)?.region;!e||!i||e===i||!n.has(e)||!n.has(i)||(a.has(e)||a.set(e,new Set),a.get(e).add(i))}let o=new Map,s=new Map;for(let t of e.region_edges??[])!n.has(t.src)||!n.has(t.dst)||t.src===t.dst||(o.has(t.src)||o.set(t.src,new Set),s.has(t.dst)||s.set(t.dst,new Set),o.get(t.src).add(t.dst),s.get(t.dst).add(t.src));return[i,...[...a.get(i.id)??[]].map(e=>n.get(e)).filter(Boolean).sort((e,t)=>(t.centrality??0)-(e.centrality??0)||String(e.id).localeCompare(String(t.id)))].slice(0,6).map(e=>({id:e.id,language:e.language,usedBy:s.get(e.id)?.size??0,uses:o.get(e.id)?.size??0,home:e.id===i.id}))}function xG(e,{active:t,reducedMotion:n}){return t&&n?0:e}var SG=(e,t)=>e.x*t.x+e.y*t.y+e.z*t.z,CG=(e,t)=>({x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x});function wG(e){if(!e)return null;let{x:t,y:n,z:r}=e;if(!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r))return null;let i=Math.hypot(t,n,r);return i>0?{x:t/i,y:n/i,z:r/i}:null}function TG({points:e,direction:t,fov:n,aspect:r,margin:i=.1}){let a=wG(t);if(!a||!Array.isArray(e)||e.length===0||!Number.isFinite(n)||n<=0||n>=180||!Number.isFinite(r)||r<=0)return null;let o=1-Math.min(Math.max(i,0),.9),s=Math.tan(n*Math.PI/360)*o,c=s*r,l=wG(CG(Math.abs(a.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},a));if(!l)return null;let u=CG(a,l),d=0;for(let t of e){if(!t)continue;let{x:e,y:n,z:r}=t;if(!Number.isFinite(e)||!Number.isFinite(n)||!Number.isFinite(r))continue;let i=SG(t,a),o=Number.isFinite(t.radius)?Math.max(0,t.radius):0,f=(Math.abs(SG(t,l))+o)/c,p=(Math.abs(SG(t,u))+o)/s;d=Math.max(d,i+f,i+p)}return d>0?d:null}function EG(e,t){let n=wG(e);return!n||!Number.isFinite(t)?null:{x:n.x*t,y:n.y*t,z:n.z*t}}var DG=24,OG=30;function kG(e,t){if(!e.length)return 0;let n=n=>{let r=-1/0,i=1/0;for(let a=0;ar&&(r=o),o0?r=e:i=e}return(r+i)/2}function AG({points:e,direction:t,fov:n,aspect:r,margin:i=.1}){let a=wG(t);if(!a||!Array.isArray(e)||e.length===0)return null;let o=e.filter(e=>e&&Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.z));if(!o.length)return null;let s=wG(CG(Math.abs(a.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},a));if(!s)return null;let c=CG(a,s),l=e=>{let t=1/0,n=-1/0;for(let r of o){let i=SG(r,e);in&&(n=i)}return(t+n)/2},u={x:s.x*l(s)+c.x*l(c)+a.x*l(a),y:s.y*l(s)+c.y*l(c)+a.y*l(a),z:s.z*l(s)+c.z*l(c)+a.z*l(a)},d=()=>o.map(e=>({x:e.x-u.x,y:e.y-u.y,z:e.z-u.z,radius:e.radius})),f=TG({points:d(),direction:t,fov:n,aspect:r,margin:i});if(f===null)return null;for(let e=0;ee.language===t),r=new Set(n.map(e=>e.id)),i=new Set(e.nodes.map(e=>e.id)),a=new Set(n.map(e=>e.region)),o=new Set(n.map(e=>e.file));return{...e,nodes:n,edges:e.edges.filter(e=>r.has(e.src)&&(r.has(e.dst)||e.external||!i.has(e.dst))),entrypoint_candidates:e.entrypoint_candidates.filter(e=>r.has(e)),selected_entrypoint:r.has(e.selected_entrypoint)?e.selected_entrypoint:null,file_hashes:Object.fromEntries(Object.entries(e.file_hashes).filter(([e])=>o.has(e))),concept_annotations:e.concept_annotations.filter(e=>e.language===t&&r.has(e.node_id)),role_evidence:(e.role_evidence??[]).filter(e=>r.has(e.node_id)),regions:e.regions.filter(e=>a.has(e.id)),region_edges:e.region_edges.filter(e=>a.has(e.src)&&a.has(e.dst)),partial_files:e.partial_files.filter(e=>o.has(e))}}function NG(e,t){if(!e||!t||t===`all`)return e;let n=e.architecture,r=n.boxes.filter(e=>e.language===t),i=new Set(r.map(e=>e.id)),a=e.workflow;return{...e,architecture:{...n,boxes:r,edges:n.edges.filter(e=>i.has(e.src)&&i.has(e.dst)),unreachable:n.unreachable.filter(e=>i.has(e))},workflow:{...a,nodes:a.nodes.filter(e=>e.language===t),unreachable:a.unreachable.filter(e=>e.language===t)}}}function PG(e){let t=new Map;for(let n of e.regions)t.set(n.language,(t.get(n.language)??0)+1);let n=[...t].map(([e,t])=>({id:e,label:LG(e),shortLabel:RG(e),count:t})).sort((e,t)=>e.label.localeCompare(t.label));return[{id:`all`,label:`All languages`,shortLabel:`All`,count:e.regions.length},...n]}function FG(e,t){let n=new Map(e.nodes.map(e=>[e.id,e])),r=new Map;for(let i of e.concept_annotations??[]){let e=`${i.language}:${i.concept}`,a=r.get(e)??{language:i.language,concept:i.concept,occurrences:0,nodeIds:new Set,studiedNodeIds:new Set,understoodNodeIds:new Set};a.occurrences+=1,a.nodeIds.add(i.node_id),t.has(i.node_id)&&a.studiedNodeIds.add(i.node_id),n.get(i.node_id)?.understood&&a.understoodNodeIds.add(i.node_id),r.set(e,a)}return[...r.values()].map(e=>({language:e.language,concept:e.concept,occurrences:e.occurrences,nodes:e.nodeIds.size,studied_nodes:e.studiedNodeIds.size,understood_nodes:e.understoodNodeIds.size})).sort((e,t)=>e.language.localeCompare(t.language)||e.concept.localeCompare(t.concept))}function IG(e){let t={javascript:`JavaScript`,jsx:`JSX`,typescript:`TypeScript`,csharp:`C#`,"linq-query":`LINQ Query`};return t[e]?t[e]:e.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function LG(e){return IG(e)}function RG(e){return e===`javascript`?`JS`:e===`typescript`?`TS`:LG(e)}var zG=Object.freeze({python:`--cm-neb-python`,javascript:`--cm-neb-js`,typescript:`--cm-neb-ts`,go:`--cm-neb-go`,java:`--cm-neb-java`,rust:`--cm-neb-rust`,csharp:`--cm-neb-csharp`});function BG(e){let t=zG[e];return t?`var(${t})`:null}var VG=2;function HG(e,{showAll:t=!1,selectionId:n=null,visitedIds:r=null}={}){let i=()=>new Set(e.regions.map(e=>e.id));if(t||!e.regions.some(e=>e.home))return i();let a=new Set,o=new Set;for(let t of e.regions)typeof t.hops_from_home==`number`&&t.hops_from_home<=VG&&a.add(t.id),t.understood&&o.add(t.id),r&&r.has(t.id)&&o.add(t.id);n&&o.add(n);for(let e of o)a.add(e);for(let t of e.region_edges)(o.has(t.src)||o.has(t.dst))&&(a.add(t.src),a.add(t.dst));return a}function UG(e,t){if(!e||!e.length)return null;let n=e.reduce((e,t)=>e+t.count,0);return t===`easy`?`${WG(e.map(e=>`${e.count} ${e.language??e.extension}`))} ${n===1?`file`:`files`} not included`:`${e.map(e=>`${e.count} ${e.extension}`).join(` · `)} not charted`}function WG(e){return e.length<=1?e.join(``):`${e.slice(0,-1).join(`, `)} and ${e[e.length-1]}`}function GG(e){let t=new Map;for(let n of e.nodes)t.has(n.region)||t.set(n.region,n.file);return t}function KG(e){let t=e.split(`/`).filter(Boolean);return t.length>1?t.slice(-2).join(`/`):t[0]??e}function qG(e){let t=GG(e);return e.regions.map(e=>({id:e.id,file:t.get(e.id)??e.id,label:KG(t.get(e.id)??e.id),language:e.language,community:e.community,understood:e.understood,home:e.home,hops:typeof e.hops_from_home==`number`?e.hops_from_home:null,centrality:e.centrality,loc:e.loc})).sort((e,t)=>e.label.localeCompare(t.label)||e.id.localeCompare(t.id))}function JG(e){if(!e.length)return``;let t=e.map(e=>e.file.split(`/`).slice(0,-1)),n=t[0];for(let e of t.slice(1)){let t=0;for(;t{let n=JG(t),r=n.endsWith(`/`)?n:``;return{community:e,name:n,members:t.map(e=>({...e,display:r&&e.file.startsWith(r)?e.file.slice(r.length):e.file})).sort((e,t)=>e.display.localeCompare(t.display))}}).sort((e,t)=>t.members.length-e.members.length||e.community-t.community)}var XG=new Set([`tests`,`test`,`__tests__`,`spec`,`specs`]);function ZG(e){return String(e).split(`/`).slice(0,-1).some(e=>XG.has(e))}function QG(e){if(!e?.length)return null;let t=e=>String(e).split(`/`).filter(Boolean)[0]??null,n=t(e[0]);return n&&e.every(e=>t(e)===n)?n:null}var $G=5,eK=2;function tK(e){return Number.isInteger(e)&&e>=0&&e<8?e:null}var nK=Object.freeze({bright:1,mid:.72,dim:.5}),rK=.32;function iK(e){let t=/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/.exec(String(e));return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}function aK(e,t,n){let r=iK(e),i=iK(t);if(!r||!i)return e;let a=e=>Math.round(r[e]*n+i[e]*(1-n));return`rgb(${a(0)}, ${a(1)}, ${a(2)})`}function oK(e,t,n,r){let i=tK(t),a=i===null?null:e.communities?.[i];if(!a)return EK(n,e,r);let o=n>=r?`bright`:n>=1?`mid`:`dim`;return aK(a,e.ground,nK[o])}function sK(e,t){let n=tK(t),r=n===null?null:e.communities?.[n];return r?aK(r,e.route,rK):e.route}var cK=e=>e.charted===!0,lK=e=>e.charted===!1;function uK(e,t,n){let{activeId:r,neighborIds:i}=t??{};return r?e.id===r?n.orbit:i?.has(e.id)?e.color:n.faded:e.color}function dK(e,t,n,r){if(e.focusDim)return n.faded;let{activeId:i,neighborIds:a}=t??{},o=e.certain?e.color??n.route:n.routePossible;if(!i)return o;let s=r(e.source),c=r(e.target);return s===i||c===i?e.certain?n.orbit:n.routePossible:a?.has(s)&&a?.has(c)?o:n.faded}function fK(e,t,n=null){let r=e=>n===null||n.has(e),i=GG(e),a=new Map(e.regions.map(e=>[e.id,e])),o=vK(e.region_edges);return{nodes:e.regions.map(n=>{let a=r(n.id);return{...n,usedBy:o.usedBy.get(n.id)??0,uses:o.uses.get(n.id)??0,kind:`region`,name:n.id,label:KG(i.get(n.id)??n.id),charted:a,fx:n.x,fy:n.y,fz:n.z,val:xK(n.loc,5,24),color:n.understood?t.star:e.nodes.some(e=>e.region===n.id&&e.partial)?t.routePossible:oK(t,n.community_family,n.centrality,$G),focusDim:!1}}),links:e.region_edges.filter(e=>r(e.src)&&r(e.dst)).map(e=>{let n=a.get(e.src),r=a.get(e.dst),i=n?.community===r?.community&&n?.community_family===r?.community_family?tK(n?.community_family):null;return{...e,source:e.src,target:e.dst,color:e.certain?sK(t,i):t.routePossible,community_family:i,focusDim:!1}})}}function pK(e,t,n,{selectedId:r=null}={}){let i=e.nodes.filter(e=>e.region===t),a=new Set(i.map(e=>e.id)),o=e.regions.find(e=>e.id===t)?.community_family,s=e.edges.filter(e=>e.kind===`call`&&!e.external&&a.has(e.src)&&a.has(e.dst)),c=vK(e.edges.filter(e=>!e.external)),l=new Set(r?[r]:[]);if(r)for(let e of s)e.src===r&&l.add(e.dst),e.dst===r&&l.add(e.src);return{nodes:i.map(e=>({...e,usedBy:c.usedBy.get(e.id)??0,uses:c.uses.get(e.id)??0,fx:e.system_x,fy:e.system_y,fz:e.system_z,val:xK(e.loc,2.8,11),color:e.understood?n.star:e.partial?n.routePossible:oK(n,o,e.centrality,eK),selected:e.id===r,focusDim:!!r&&!l.has(e.id)})),links:s.map(e=>({...e,source:e.src,target:e.dst,color:e.certain?n.route:n.routePossible,focusDim:!!r&&e.src!==r&&e.dst!==r}))}}function mK(e){return e.regions.find(e=>e.home)??e.regions[0]??null}function hK(e){let t=String(e?.project_root??``);return(t.split(`/`).filter(Boolean).at(-1)??t)||`Local project`}function gK(e,t){if(!e?.length)return null;let n=[...e].sort((e,t)=>t.length-e.length||e.join(`\0`).localeCompare(t.join(`\0`)))[0].join(`, `);return t===`easy`?`${e.length} ${e.length===1?`file circle`:`file circles`} found. Largest group: ${n}. Each file can reach every other through proven imports.`:`${e.length} proven import ${e.length===1?`cycle group`:`cycle groups`}. Largest strongly connected group: ${n}.`}function _K(e){let t=e?.regions??[],n=e?.nodes??[],r=e?.edges??[],i=new Map;for(let e of t)i.set(e.language,(i.get(e.language)??0)+1);let a=new Map;for(let e of n)a.set(e.language,(a.get(e.language)??0)+1);let o=[...i.entries()].sort((e,t)=>t[1]-e[1]||String(e[0]).localeCompare(String(t[0]))).map(([e,t])=>({language:e,label:LG(e),count:t,structures:a.get(e)??0})),s=e=>t.filter(t=>Number.isFinite(t[e])).sort((t,n)=>n[e]-t[e]||String(t.id).localeCompare(String(n.id))).slice(0,5).map(t=>({id:t.id,value:t[e]})),c=mK(e);return{projectName:hK(e),modules:t.length,structures:n.length,lines:t.reduce((e,t)=>e+(t.loc??0),0),languages:o,home:e?.selected_entrypoint&&c?{id:c.id,language:c.language}:null,biggest:s(`loc`),busiest:s(`centrality`),unreadable:(e?.partial_files??[]).length,unsupported:(e?.unsupported_sources??[]).reduce((e,t)=>e+(t.count??0),0),unsupportedSources:[...e?.unsupported_sources??[]].map(e=>({extension:e.extension,language:e.language,count:e.count??0})).sort((e,t)=>String(e.extension).localeCompare(String(t.extension))||String(e.language).localeCompare(String(t.language))),relationships:{proven:r.filter(e=>e.certain===!0).length,hedged:r.filter(e=>e.certain===!1).length},importCycles:(e?.import_cycles??[]).map(e=>[...e]),understood:t.filter(e=>e.understood).length}}function vK(e){let t=new Map,n=new Map;for(let r of e??[])n.set(r.src,(n.get(r.src)??0)+1),t.set(r.dst,(t.get(r.dst)??0)+1);return{usedBy:t,uses:n}}function yK(e){let t=e.kind===`region`?`star system`:e.kind,n=e.partial?` · unchartable · syntax error`:``,r=e.home?` · Home`:``,i=(e.usedBy?` · used by ${e.usedBy}`:``)+(e.uses?` · uses ${e.uses}`:``),a=e.system_orbit?.kind===`unreached`?` · no proven call path`:Number.isInteger(e.system_orbit?.call_depth)&&e.system_orbit.call_depth>0?` · call layer ${e.system_orbit.call_depth}`:``;return`${e.name} · ${t} · ${e.loc} LOC${r}${i}${n}${a}`}function bK(e){let t=e.kind===`import`?`import`:e.kind===`call`?`call`:`import route`,n=e.certain?`certain`:t===`call`?`possible call`:`possible import`,r=typeof e.weight==`number`?` · ${e.weight} ${e.weight===1?`import`:`imports`}`:``,i=typeof e.lineno==`number`?` · line ${e.lineno}`:``;return`${e.src} → ${e.dst} · ${t} · ${n}${r}${i}`}function xK(e,t,n){return Math.min(n,Math.max(t,Math.sqrt(Math.max(1,e))*1.15))}var SK=1.6,CK=6.5;function wK(e){return Math.cbrt(e?.val??1)*SK}function TK(e){return wK(e)*CK/2}function EK(e,t,n){return e>=n?t.nodeBright:e>=1?t.node:t.nodeDim}var DK={GALAXY:{min:120,max:640},SYSTEM:{min:55,max:320},STUDY:{min:22,max:170}},OK={GALAXY:{x:0,y:165,z:286},SYSTEM:{x:0,y:52,z:150}},kK=1.15,AK={x:20,y:15,z:42};function jK(e){if(!e)return null;let{width:t,height:n}=e;return!Number.isFinite(t)||!Number.isFinite(n)||t<=0||n<=0?null:t/n}var MK=e=>e.map(e=>({x:e.fx??e.x??0,y:e.fy??e.y??0,z:e.fz??e.z??0,radius:TK(e)})),NK=e=>{let t=[];for(let n of e??[])for(let e of n.radii??[])t.push({x:e,y:0,z:0},{x:-e,y:0,z:0},{x:0,y:0,z:e},{x:0,y:0,z:-e});return t};function PK({level:e,nodes:t,orbitPlan:n,fov:r,aspect:i,viewport:a,chrome:o}){let s=OK[e]??OK.GALAXY,c=DK[e]??DK.GALAXY,l=e===jG.GALAXY?[]:NK(n),u=Array.isArray(t)?t:[],d=e=>[...MK(e),...l],f=e=>AG({points:d(e),direction:s,fov:r,aspect:i}),p=u.filter(cK),m=(p.length?f(p):null)??f(u),h={target:m?.target??{x:0,y:0,z:0},distance:m?.distance??Math.hypot(s.x,s.y,s.z)},{target:g,distance:_}=m?IK({...h,points:d(p.length?p:u),direction:s,fov:r,viewport:a,chrome:o}):h,v=EG(s,_)??s,y=TG({points:d(u).map(e=>({x:e.x-g.x,y:e.y-g.y,z:e.z-g.z,radius:e.radius})),direction:s,fov:r,aspect:i});return{position:{x:g.x+v.x,y:g.y+v.y,z:g.z+v.z},target:g,distance:_,min:Math.min(c.min,_),max:Math.max(c.max,(y??_)*kK),fitted:m!==null}}function FK(e,t){let{width:n,height:r}=e??{};if(!Number.isFinite(n)||!Number.isFinite(r)||n<=0||r<=0)return null;let i={left:0,right:n,top:0,bottom:r},a=(t??[]).filter(e=>e&&Number.isFinite(e.left)&&Number.isFinite(e.right)&&Number.isFinite(e.top)&&Number.isFinite(e.bottom));for(let e=0;ee.lefti.left&&e.topi.top);if(!e)break;i=[{...i,right:Math.max(i.left,e.left)},{...i,left:Math.min(i.right,e.right)},{...i,bottom:Math.max(i.top,e.top)},{...i,top:Math.min(i.bottom,e.bottom)}].reduce((e,t)=>{let n=e=>Math.max(0,e.right-e.left)*Math.max(0,e.bottom-e.top);return n(t)>n(e)?t:e})}let o={left:i.left,right:i.right,top:i.top,bottom:i.bottom,width:Math.max(0,i.right-i.left),height:Math.max(0,i.bottom-i.top)};return o.width>0&&o.height>0?o:null}function IK({target:e,distance:t,points:n,direction:r,fov:i,viewport:a,chrome:o,margin:s=.1}){let c={target:e,distance:t},l=LK(r),u=FK(a,o);if(!l||!u||!Number.isFinite(t)||!Number.isFinite(i)||!Array.isArray(n)||!n.length)return c;let{width:d,height:f}=a;if(u.width>=d&&u.height>=f)return c;let p=LK(RK(Math.abs(l.y)>.9?{x:1,y:0,z:0}:{x:0,y:1,z:0},l));if(!p)return c;let m=RK(l,p),h=i*Math.PI/360,g=t=>{let r=1/0,i=-1/0,a=1/0,o=-1/0;for(let s of n){let n={x:s.x-e.x,y:s.y-e.y,z:s.z-e.z},c=t-zK(n,l);if(c<=0)continue;let u=2*c*Math.tan(h)/f;if(!(u>0))continue;let d=Number.isFinite(s.radius)?Math.max(0,s.radius):0,g=zK(n,p)/u,_=zK(n,m)/u,v=d/u;r=Math.min(r,g-v),i=Math.max(i,g+v),a=Math.min(a,_-v),o=Math.max(o,_+v)}return!Number.isFinite(r)||!Number.isFinite(a)?null:{width:i-r,height:o-a,x:(r+i)/2,y:(a+o)/2}},_=g(t);if(!_)return c;let v=1-Math.min(.9,Math.max(0,s)),y=Math.max(1,_.width/Math.max(1,u.width*v),_.height/Math.max(1,u.height*v)),b=t*y,x=y===1?_:g(b);if(!x)return c;let S=2*b*Math.tan(h)/f,C=u.left+u.width/2-d/2,w=u.top+u.height/2-f/2,T=(x.x-C)*S,E=(x.y+w)*S;return{distance:b,target:{x:e.x+p.x*T+m.x*E,y:e.y+p.y*T+m.y*E,z:e.z+p.z*T+m.z*E}}}function LK(e){if(!e)return null;let{x:t,y:n,z:r}=e;if(![t,n,r].every(Number.isFinite))return null;let i=Math.hypot(t,n,r);return i>0?{x:t/i,y:n/i,z:r/i}:null}function RK(e,t){return{x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x}}function zK(e,t){return e.x*t.x+e.y*t.y+e.z*t.z}function BK(e){return DK[e]??DK.GALAXY}function VK(e){if(!e)return null;let{system_x:t,system_y:n,system_z:r}=e;return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(r)?null:{position:{x:t+AK.x,y:n+AK.y,z:r+AK.z},target:{x:t,y:n,z:r}}}var HK=Object.freeze({width:132,height:30}),UK=Object.freeze({far:14,near:44}),WK=Object.freeze([0,-1,1,-2,2]),GK=4,KK=.034;function qK(e,{radius:t,aspect:n}){return e.scale.set(KK*n,KK,1),e.userData.baseOffsetY=t*2.2+1.2,e.position.set(0,e.userData.baseOffsetY,0),e.visible=!1,e.userData.codembleLabel=!0,e.userData.screenWidthFraction=KK*n,e.userData.screenHeightFraction=KK,e}function JK(e){let t=YK(e),n=new V,r=new V;function i({scene:e,camera:i,width:a,height:o,distance:s,distanceBounds:c,activeNodeId:l=null,neighborIds:u=null,chrome:d=[]}){let f=XK(e);for(let e of f)e.visible=!1;if(!f.length||!t.size)return Object.freeze({budget:0,shown:0,visibleIds:Object.freeze([])});let p=ZK(s,c),m=[];for(let e of f){let s=e.userData.nodeId,c=e.parent;if(!c)continue;c.getWorldPosition(r);let d=e.userData.baseOffsetY??0,f=QK(r,d,i,a,o,n);if(!f)continue;let p=QK(r,d+1,i,a,o,n),h=p?Math.abs(p.screenY-f.screenY):0;m.push({sprite:e,nodeId:s,origin:r.clone(),base:d,pixelsPerUnit:h,anchor:f,halfWidth:(e.userData.screenWidthFraction??.14)*o/2,halfHeight:(e.userData.screenHeightFraction??.034)*o/2,rank:s===l?-2:u?.has(s)?-1:t.get(s)??1/0})}m.sort((e,t)=>e.rank-t.rank||e.nodeId.localeCompare(t.nodeId));let h=new Set,g=[];for(let e of m){if(g.length>=p)break;let t=$K(e,{camera:i,width:a,height:o,projected:n,taken:h,chrome:d});if(t){for(let e of t.cells)h.add(e);e.sprite.position.y=e.base+t.offset,e.sprite.visible=!0,g.push(e.nodeId)}}return Object.freeze({budget:p,shown:g.length,visibleIds:Object.freeze(g)})}function a(e){for(let t of XK(e))t.visible=!1}return Object.freeze({hide:a,place:i})}function YK(e){let t=e.filter(e=>e.label).map(e=>({id:e.id,weight:(e.home?3e6:0)+(e.understood?1e6:0)+(e.centrality??0)*1e3})).sort((e,t)=>t.weight-e.weight||e.id.localeCompare(t.id));return new Map(t.map((e,t)=>[e.id,t]))}function XK(e){let t=[];return e.traverse(e=>{e.userData?.codembleLabel&&t.push(e)}),t}function ZK(e,t){let n=Math.max(1,t.max-t.min),r=1-Math.min(1,Math.max(0,(e-t.min)/n));return Math.round(UK.far+(UK.near-UK.far)*r)}function QK(e,t,n,r,i,a){if(a.set(e.x,e.y+t,e.z).project(n),a.z>1)return null;let o=(a.x*.5+.5)*r,s=(-a.y*.5+.5)*i;return o<0||o>r||s<0||s>i?null:{screenX:o,screenY:s}}function $K(e,{camera:t,width:n,height:r,projected:i,taken:a,chrome:o}){let s=e.pixelsPerUnit?(e.halfHeight*2+GK)/e.pixelsPerUnit:0;for(let c of WK){let l=c*s,u=c===0?e.anchor:QK(e.origin,e.base+l,t,n,r,i);if(!u||!eq(u,e,n,r)||!tq(u,e,o))continue;let d=nq(u,e);if(!d.some(e=>a.has(e)))return{cells:d,offset:l}}return null}function eq(e,{halfWidth:t,halfHeight:n},r,i){return e.screenX-t>=0&&e.screenX+t<=r&&e.screenY-n>=0&&e.screenY+n<=i}function tq(e,{halfWidth:t,halfHeight:n},r){if(!r?.length)return!0;let i=e.screenX-t,a=e.screenX+t,o=e.screenY-n,s=e.screenY+n;return!r.some(e=>ie.left&&oe.top)}function nq(e,{halfWidth:t,halfHeight:n}){let r=Math.floor((e.screenX-t)/HK.width),i=Math.floor((e.screenX+t)/HK.width),a=Math.floor((e.screenY-n)/HK.height),o=Math.floor((e.screenY+n)/HK.height),s=[];for(let e=r;e<=i;e+=1)for(let t=a;t<=o;t+=1)s.push(`${e}:${t}`);return s}var rq=128,iq=256,aq=.026;function oq(e,t){let n=document.createElement(`canvas`);n.width=e,n.height=e;let r=n.getContext(`2d`),i=r.createRadialGradient(e/2,e/2,0,e/2,e/2,e/2);for(let[e,n]of t)i.addColorStop(e,`rgba(255, 255, 255, ${n})`);r.fillStyle=i,r.fillRect(0,0,e,e);let a=new La(n);return a.colorSpace=ot,a}function sq(e){let t=document.createElement(`canvas`);t.width=e,t.height=e;let n=t.getContext(`2d`);n.strokeStyle=`rgba(255, 255, 255, 1)`,n.lineWidth=e*.05,n.beginPath(),n.arc(e/2,e/2,e*.4,0,Math.PI*2),n.stroke();let r=new La(t);return r.colorSpace=ot,r}function cq(e){let t=[];function n(e){let n=e.dispose.bind(e);return e.dispose=()=>{},t.push(n),e}let r=n(oq(rq,[[0,.85],[.25,.42],[.6,.1],[1,0]])),i=n(oq(iq,[[0,.32],[.45,.14],[.8,.03],[1,0]])),a=n(sq(rq)),o=new Map,s=new Map,c=null,l=new Map;function u(t){return l.has(t)||l.set(t,n(dq(t,e))),l.get(t)}function d(t){return o.has(t)||o.set(t,n(new bi({map:r,color:new H(t).multiply(new H(e.starHalo)),blending:2,transparent:!0,depthWrite:!1,opacity:.6}))),o.get(t)}return{halo(e,t){let n=new Pi(d(e.color));return n.scale.setScalar(t*6.5),n.renderOrder=-1,n},nebula(e,t){s.has(e)||s.set(e,n(new bi({map:i,color:new H(e),blending:2,transparent:!0,depthWrite:!1,opacity:.16})));let r=new Pi(s.get(e));return r.scale.setScalar(t),r.renderOrder=-2,r},spark(){c||=n(new bi({map:r,color:new H(e.star),blending:2,transparent:!0,depthWrite:!1,opacity:0}));let t=new Pi(c);return t.renderOrder=2,t},reticle(t){let n=new Pi(new bi({map:a,color:new H(e.orbit),transparent:!0,depthWrite:!1,depthTest:!1}));return n.scale.setScalar(t*5),n.renderOrder=3,n},label(e,t){let n=u(e),r=new Pi(n);return qK(r,{radius:t,aspect:n.userData.aspect??4}),r.renderOrder=4,r},guideLabel(e){let t=u(e),n=new Pi(t),r=t.userData.aspect??4;return n.scale.set(aq*r,aq,1),n.renderOrder=2,n},dispose(){for(let e of t)e();t.length=0,o.clear(),s.clear(),c=null,l.clear()}}}var lq=34,uq=12;function dq(e,t){let n=document.createElement(`canvas`),r=n.getContext(`2d`),i=`${lq}px "JetBrains Mono", ui-monospace, monospace`;r.font=i;let a=Math.ceil(r.measureText(e).width)+uq*2;n.width=a,n.height=58,r.font=i,r.textBaseline=`middle`,r.textAlign=`center`,r.fillStyle=t.labelPlate,fq(r,0,0,a,58,8),r.fill(),r.fillStyle=t.labelInk,r.fillText(e,a/2,30);let o=new La(n);o.colorSpace=ot;let s=new bi({map:o,transparent:!0,depthWrite:!1,depthTest:!1,sizeAttenuation:!1});s.userData.aspect=a/58;let c=s.dispose.bind(s);return s.dispose=()=>{o.dispose(),c()},s}function fq(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.arcTo(t+r,n,t+r,n+i,a),e.arcTo(t+r,n+i,t,n+i,a),e.arcTo(t,n+i,t,n,a),e.arcTo(t,n,t+r,n,a),e.closePath()}function pq(e){return Object.entries(e??{}).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}:${t}`).join(`|`)}function mq(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}function hq(e){let t=2166136261;for(let n=0;n>>0}function gq(e,t,n=3200,r=1600){let i=mq(hq(e)),a=new Float32Array(n*3),o=new Float32Array(n*3),s=new Float32Array(n),c=new H(t.starCool??t.nodeDim),l=new H(t.starPale??t.nodeBright),u=new H;for(let e=0;evq(t,e),r=e=>vq(t,e);return e.addEventListener(`pointerdown`,n,{capture:!0}),e.addEventListener(`lostpointercapture`,r,{capture:!0}),()=>{e.removeEventListener(`pointerdown`,n,{capture:!0}),e.removeEventListener(`lostpointercapture`,r,{capture:!0})}}var bq=2.4,xq=1.8,Sq=.62;function Cq(e,t){let n=new Ho({color:new H(t),dashSize:bq,gapSize:xq,transparent:!0,opacity:Sq,depthWrite:!1}),r=new Ta(new mi,n);return r.userData.codembleRouteLink=e,r.renderOrder=-1,r}function wq(e,t,n,r){let i=t?t.getPoints(30):[new V(n.x,n.y??0,n.z??0),new V(r.x,r.y??0,r.z??0)],a=e.geometry.getAttribute(`position`);return(!a||a.count!==i.length)&&e.geometry.setAttribute(`position`,new Qr(new Float32Array(i.length*3),3)),e.geometry.setFromPoints(i),e.geometry.computeBoundingSphere(),e.computeLineDistances(),!0}function Tq(e,t){e.traverse(e=>{let n=e.userData?.codembleRouteLink;!n||!e.material||e.material.color.set(t(n))})}var Eq=128,Dq=-.72;function Oq(e){let t=new Map;for(let n of e??[]){let e=n.system_orbit;if(!e||!Number.isInteger(e.ring)||e.ring<=0||!Number.isFinite(e.radius)||e.radius<=0)continue;t.has(e.ring)||t.set(e.ring,{callDepths:new Set,kinds:new Set,radii:new Set});let r=t.get(e.ring);r.callDepths.add(e.call_depth??null),r.kinds.add(e.kind),r.radii.add(e.radius)}return[...t.entries()].sort(([e],[t])=>e-t).map(([e,t])=>{let n=[...t.callDepths],r=n.length===1?n[0]:null,i=[...t.kinds].sort(),a=i.every(e=>e===`unreached`);return{ring:e,callDepth:r,kinds:i,radii:[...t.radii].sort((e,t)=>e-t),label:a?`No proven path`:r===null?`Mixed call evidence`:`Layer ${r}`,unproven:a}})}function kq(e,t,n){let r=new sr;r.name=`codemble-system-orbits`;for(let i of e){let e=i.unproven?new Ho({color:t.faded,dashSize:3,gapSize:2,opacity:.72,transparent:!0,depthWrite:!1}):new _a({color:t.route,opacity:.52,transparent:!0,depthWrite:!1});for(let t of i.radii){let n=new Da(new mi().setFromPoints(Array.from({length:Eq},(e,n)=>{let r=n/Eq*Math.PI*2;return new V(Math.cos(r)*t,0,Math.sin(r)*t)})),e);n.userData.codembleOrbitGuide=!0,n.renderOrder=-1,i.unproven&&n.computeLineDistances(),r.add(n)}let a=Math.max(...i.radii),o=n.guideLabel(i.label);o.position.set(Math.cos(Dq)*a,2.5,Math.sin(Dq)*a),o.userData.codembleOrbitGuideLabel=!0,r.add(o)}return r}function Aq(e){let t=new Set;e.traverse(e=>{e.userData?.codembleOrbitGuide&&(e.geometry?.dispose(),e.material&&t.add(e.material))});for(let e of t)e.dispose()}var jq=.16,Mq=1.5,Nq=110,Pq=6,Fq=Object.freeze({requestFrame:e=>requestAnimationFrame(e),cancelFrame:e=>cancelAnimationFrame(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e),setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),now:()=>performance.now()}),Iq=Object.freeze({rendererFactory:e=>XW({controlType:`orbit`})(e),assertWebGL(){let e=document.createElement(`canvas`);if(!e.getContext(`webgl2`)&&!e.getContext(`webgl`))throw Error(`Codemble needs WebGL to draw your galaxy. Enable WebGL and reload.`)},ResizeObserver:globalThis.ResizeObserver,createDressing:cq,createBodyGeometry:nG,createBodySpin:aG,createSystemOrbitGuides:kq,disposeSystemOrbitGuides:Aq,createStarfield:gq,createGalacticGlow:_q,attachBloom:zd,guardOrbitPointerState:yq,runDawnSequence:yG,createNameAtlas:JK,documentElement:()=>document.documentElement,search:()=>window.location.search});function Lq({host:e,palette:t,reducedMotion:n,onHoverNode:r,onAdvance:i,onDawnConsumed:a,dependencies:o={},clock:s=Fq}){let c={...Iq,...o},l=!1,u=null,d=null,f=null,p=null,m=null,h=null,g=null,_=()=>{},v=()=>{},y=null,b=null,x=!1,S=null,C={activeId:null,neighborIds:new Set},w=null,T=null,E=()=>{},D=null,O=null,k=null,A=null,ee=null,te=e=>uK(e,C,t),j=e=>dK(e,C,t,zq),ne=e=>{if(e.focusDim)return .4;let t=Math.min(2.2,.45+(e.weight??1)*.25);if(!C.activeId)return t;let n=zq(e.source),r=zq(e.target);return n===C.activeId||r===C.activeId?t+.9:t};function re(){c.assertWebGL(),p=c.createDressing(t),m=c.createBodyGeometry(),d=c.rendererFactory(e).backgroundColor(t.ground).showNavInfo(!1).enableNavigationControls(!0).enableNodeDrag(!1).warmupTicks(0).cooldownTicks(0).nodeId(`id`).nodeLabel(yK).nodeVal(`val`).nodeColor(te).nodeRelSize(SK).nodeResolution(8).nodeOpacity(.82).nodeThreeObject(e=>Rq(e,t,p,S,{level:u?.level,bodyGeometry:m})).nodeThreeObjectExtend(!0).linkColor(j).linkLabel(bK).linkOpacity(.5).linkWidth(ne).linkCurvature(.12).linkThreeObject(e=>e.certain?null:Cq(e,j(e))).linkPositionUpdate((e,{start:t,end:n},r)=>!r.certain&&wq(e,r.__curve,t,n)).linkVisibility(e=>!(u?.mode===`easy`&&e.focusDim)).linkHoverPrecision(4).linkDirectionalArrowRelPos(1).linkDirectionalArrowColor(j).linkDirectionalParticles(e=>e.kind===`call`&&e.certain&&!e.focusDim&&!n?2:0).linkDirectionalParticleSpeed(.006).linkDirectionalParticleWidth(1.1).linkDirectionalParticleColor(()=>t.orbit).onNodeHover(t=>{l||(e.style.cursor=t?`pointer`:`default`,r(t?.id??null))}).onNodeClick(e=>{l||i(e)}),y=s.requestFrame(()=>{l||e.querySelector(`.scene-nav-info`)?.remove()}),f=d.controls(),f.enablePan=!1,f.enableDamping=!n,f.dampingFactor=.12,f.rotateSpeed=.55,f.zoomSpeed=.7,f.minPolarAngle=jq,f.maxPolarAngle=Mq;let a=()=>{l||(x=!0)};f.addEventListener(`start`,a),v=()=>f?.removeEventListener(`start`,a),_=c.guardOrbitPointerState(e,f),h=c.attachBloom(d,e.getBoundingClientRect()),g=new c.ResizeObserver(([e])=>{if(l)return;let{width:t,height:n}=e.contentRect;d.width(t).height(n);let r=jK(e.contentRect);!x&&r!==null&&b?.(r)}),g.observe(e)}function M(t,n){if(!u)return;let{data:r,level:i,orbitPlan:a}=u,o=cG({host:e,renderer:d}),s=PK({level:i,nodes:r.nodes,orbitPlan:a,fov:d.camera()?.fov,aspect:n??jK(e.getBoundingClientRect())??jK({width:d.width(),height:d.height()}),viewport:o.viewport,chrome:i===jG.SYSTEM?o.clickObstructions:[]});f.minDistance=s.min,f.maxDistance=s.max,d.cameraPosition(s.position,s.target,t)}function N(){E(),E=()=>{},T&&=(d.scene().remove(T),c.disposeSystemOrbitGuides(T),null),!(u.level===jG.GALAXY||!u.orbitPlan.length)&&(T=c.createSystemOrbitGuides(u.orbitPlan,t,p),d.scene().add(T),E=c.createBodySpin(d.scene(),{reducedMotion:n}))}function ie(){ae();let e=c.createStarfield(u.starfieldSeed,t),n=c.createGalacticGlow(t);d.scene().add(e),d.scene().add(n),w={starfield:e,glow:n}}function ae(){!w||!d||(d.scene().remove(w.starfield),w.starfield.geometry?.dispose(),w.starfield.material?.dispose(),d.scene().remove(w.glow),w.glow.material?.map?.dispose(),w.glow.material?.dispose(),w=null)}function oe(){D&&=(D.cancelled=!0,D.frame!==null&&s.cancelFrame(D.frame),D.stop(),null)}function P(e){if(O=e,a?.(e),n)return;oe();let r={cancelled:!1,frame:null,stop:()=>{}};D=r;let i=n=>{if(l||r.cancelled||D!==r)return;let a=d.scene();if(a.getObjectByName(`codemble-system-${e}`)||n>=Pq){r.frame=null,r.stop=c.runDawnSequence({scene:a,regionId:e,palette:t,dressing:p,routes:u?.graph?.region_edges??[],hopsById:new Map((u?.graph?.regions??[]).map(e=>[e.id,e.hops_from_home]))});return}r.frame=s.requestFrame(()=>i(n+1))};r.frame=s.requestFrame(()=>i(0))}function se(){A!==null&&s.clearInterval(A),k&&d&&k.hide(d.scene()),A=null,k=c.createNameAtlas(u.data.nodes);let t=d.scene(),n=()=>{if(!(l||!k))try{let n=d.camera(),r=BK(u.level),i=f?{min:f.minDistance??r.min,max:f.maxDistance??r.max}:r,a=f?n.position.distanceTo(f.target):n.position.length(),o=cG({host:e,renderer:d});k.place({scene:t,camera:n,width:d.width(),height:d.height(),distance:a,distanceBounds:i,activeNodeId:C.activeId,neighborIds:C.neighborIds,chrome:o.nameObstructions})}catch(e){A!==null&&s.clearInterval(A),A=null,k.hide(t),console.error(`Codemble: label declutter failed, names disabled`,e)}};n(),A=s.setInterval(n,Nq)}function F(){ee!==null&&s.clearTimeout(ee),ee=null,!(!new URLSearchParams(c.search()).has(`benchmark`)||u.data.nodes.length<900)&&(c.documentElement().removeAttribute(`data-codemble-fps`),ee=s.setTimeout(()=>{if(ee=null,l)return;let e=d.renderer(),t=d.postProcessingComposer(),n=s.now();for(let e=0;e<60;e+=1)t.render();e.getContext().finish();let r=s.now()-n;c.documentElement().dataset.codembleFps=(60*1e3/r).toFixed(1)},1e3))}function ce(e){if(l)return;let t=u;if(u=e,(!t||t.data!==e.data||t.level!==e.level||t.mode!==e.mode||t.orbitPlan!==e.orbitPlan)&&(d.nodeResolution(e.data.nodes.length>=900?4:8).nodeThreeObjectExtend(e.level===jG.GALAXY).linkVisibility(t=>!(e.mode===`easy`&&t.focusDim)).linkDirectionalArrowLength(e.level===jG.GALAXY?0:3.2).graphData(e.data),M(xG(420,{active:e.firstFlightActive,reducedMotion:n})),x=!1,b=e=>M(0,e)),(!t||t.level!==e.level||t.orbitPlan!==e.orbitPlan)&&N(),(!t||t.starfieldSeed!==e.starfieldSeed)&&ie(),e.level===jG.GALAXY?e.pendingDawnRegionId&&e.pendingDawnRegionId!==O&&P(e.pendingDawnRegionId):oe(),!t||t.data!==e.data||t.hoverNodeId!==e.hoverNodeId||t.focusedNodeId!==e.focusedNodeId||t.level!==e.level||t.selectedNode?.id!==e.selectedNode?.id){let t=e.hoverNodeId??e.focusedNodeId??(e.level===jG.STUDY?e.selectedNode?.id??null:null),n=new Set;if(t)for(let r of e.data.links){let e=zq(r.source),i=zq(r.target);e===t&&n.add(i),i===t&&n.add(e)}C={activeId:t,neighborIds:n},d.nodeColor(e=>te(e)).linkColor(e=>j(e)).linkWidth(e=>ne(e)).linkDirectionalArrowColor(e=>j(e)),Tq(d.scene(),j)}if((!t||t.focusedNodeId!==e.focusedNodeId)&&(S=e.focusedNodeId,d.refresh()),(!t||t.data.nodes!==e.data.nodes||t.hoverNodeId!==e.hoverNodeId||t.focusedNodeId!==e.focusedNodeId||t.level!==e.level)&&se(),(!t||t.data.nodes.length!==e.data.nodes.length)&&F(),e.level===jG.STUDY&&(!t||t.level!==e.level||t.selectedNode!==e.selectedNode)){let t=VK(e.selectedNode);t&&d.cameraPosition(t.position,t.target,420)}}function le(){l||(l=!0,g?.disconnect(),g=null,v(),v=()=>{},y!==null&&s.cancelFrame(y),y=null,_(),_=()=>{},E(),E=()=>{},T&&d&&(d.scene().remove(T),c.disposeSystemOrbitGuides(T),T=null),oe(),A!==null&&s.clearInterval(A),A=null,k&&d&&k.hide(d.scene()),k=null,ee!==null&&s.clearTimeout(ee),ee=null,ae(),d?.pauseAnimation(),h?.dispose(),h=null,d?._destructor(),p?.dispose(),p=null,m?.dispose(),m=null,f=null,d=null,e.replaceChildren(),b=null)}try{re()}catch(e){throw le(),e}return Object.freeze({update:ce,dispose:le})}function Rq(e,t,n,r,{level:i,bodyGeometry:a}={}){let o=new sr;o.name=e.kind===`region`?`codemble-system-${e.id}`:`codemble-node-${e.id}`;let s=wK(e),c=i&&i!==jG.GALAXY&&a;c&&o.add(iG({node:e,color:e.color,palette:t,radius:s,geometry:a}));let l=lK(e);if(!e.focusDim&&!l&&!c&&o.add(n.halo(e,s)),e.kind===`region`&&!l){let r=t.nebula[e.language];r&&o.add(n.nebula(r,s*14))}if(e.label){let t=n.label(e.label,s);t.userData.nodeId=e.id,o.add(t)}if(e.home){let e=new na(new bo(s*1.7,Math.max(.18,s*.07),8,36),new Wi({color:t.home}));e.rotation.x=Math.PI/2.8,o.add(e)}if(e.kind===`class`&&!e.focusDim){let e=new na(new bo(s*1.45,Math.max(.1,s*.045),6,28),new Wi({color:t.route}));e.rotation.x=Math.PI/2.4,o.add(e)}if(e.selected){let e=new na(new bo(s*2.1,Math.max(.16,s*.05),6,24),new Wi({color:t.orbit}));e.rotation.x=Math.PI/2.8,o.add(e)}return e.id===r&&o.add(n.reticle(s)),o}function zq(e){return typeof e==`object`&&e?e.id:e}var Bq=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),$=o(((e,t)=>{t.exports=Bq()}))();function Vq({graph:e,level:t,region:n,selectedNode:r,hoverNodeId:i,pendingDawnRegionId:a,revealedRegionIds:o,mode:s,firstFlightActive:c,onHoverNode:l,onAdvance:u,onRetreat:d,onDawnConsumed:f}){let p=(0,_.useRef)(null),m=(0,_.useRef)(null),h=(0,_.useRef)(u),g=(0,_.useRef)(d),v=(0,_.useRef)(l),y=(0,_.useRef)(f),[b,x]=(0,_.useState)(0),[S,C]=(0,_.useState)(!1),[w,T]=(0,_.useState)(``),E=(0,_.useMemo)(Uq,[]),D=(0,_.useMemo)(Bd,[]),O=pq(e.file_hashes),k=(0,_.useMemo)(()=>t===jG.GALAXY?fK(e,E,o):pK(e,n?.id,E,{selectedId:r?.id}),[e,t,E,n?.id,o,r?.id]),A=(0,_.useMemo)(()=>t===jG.GALAXY?[]:Oq(k.nodes),[k.nodes,t]);(0,_.useEffect)(()=>{h.current=u,g.current=d,v.current=l,y.current=f},[u,d,l,f]),(0,_.useEffect)(()=>{let e=p.current;if(e)try{let t=Lq({host:e,palette:E,reducedMotion:D,onHoverNode:e=>v.current(e),onAdvance:e=>h.current(e),onDawnConsumed:e=>y.current?.(e)});return m.current=t,T(``),()=>{t.dispose(),m.current===t&&(m.current=null)}}catch(e){let t=e instanceof Error?e.message:String(e);T(t.startsWith(`Codemble needs WebGL`)?t:`The galaxy could not start: ${t}`);return}},[E,D]),(0,_.useEffect)(()=>{m.current?.update({graph:e,data:k,level:t,mode:s,orbitPlan:A,selectedNode:r,hoverNodeId:i,pendingDawnRegionId:a,starfieldSeed:O,firstFlightActive:c,focusedNodeId:S?k.nodes[b]?.id??null:null})},[k,c,b,e,i,S,t,s,A,a,r,O]),(0,_.useEffect)(()=>{x(0),C(!1)},[k,t,s,A]);let ee=k.nodes[b]??null;function te(e){if(e.key===`ArrowRight`||e.key===`ArrowDown`)e.preventDefault(),x(e=>(e+1)%Math.max(1,k.nodes.length));else if(e.key===`ArrowLeft`||e.key===`ArrowUp`)e.preventDefault(),x(e=>(e-1+k.nodes.length)%Math.max(1,k.nodes.length));else if(e.key===`Enter`&&ee)e.preventDefault(),h.current(ee);else if(e.key===`Escape`||e.key===`Backspace`){if(e.key===`Escape`&&c)return;e.preventDefault(),g.current()}}return w?(0,$.jsxs)(`section`,{className:`webgl-error`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The sky could not open.`}),(0,$.jsx)(`p`,{children:w}),(0,$.jsxs)(`p`,{children:[`The `,s===`easy`?`Diagram`:`Map`,` layer works without WebGL — switch to it at the top of the window to explore the same code.`]})]}):(0,$.jsxs)(`div`,{className:`galaxy-frame`,role:`application`,tabIndex:`0`,"aria-label":`Codemble ${t.toLowerCase()} view. Drag to orbit, scroll to zoom. Use arrow keys to choose a node and Enter to move closer.${t===jG.GALAXY?``:` Solid guides are parser-proven call layers; a dashed guide has no proven call path.`}`,onFocus:()=>C(!0),onBlur:()=>{v.current(null)},onKeyDown:te,children:[(0,$.jsx)(`div`,{ref:p,className:`galaxy-canvas`,"aria-hidden":`true`,onPointerLeave:()=>v.current(null)}),S&&ee?(0,$.jsx)(`output`,{className:`keyboard-focus`,"aria-live":`polite`,children:yK(ee)}):null]})}function Hq(e){let t=document.createElement(`canvas`).getContext(`2d`);t.fillStyle=`#000000`,t.fillStyle=e,t.fillRect(0,0,1,1);let[n,r,i]=t.getImageData(0,0,1,1).data;return`rgb(${n}, ${r}, ${i})`}function Uq(){let e=getComputedStyle(document.documentElement),t=t=>Hq(e.getPropertyValue(t).trim());return Object.freeze({ground:t(`--cm-sky`),skyGlow:t(`--cm-sky-glow`),home:t(`--cm-ink`),orbit:t(`--cm-orbit`),nodeBright:t(`--cm-node-bright`),node:t(`--cm-node-mid`),nodeDim:t(`--cm-node-unlit`),starCool:t(`--cm-star-cool`),starPale:t(`--cm-star-pale`),route:t(`--cm-route`),routePossible:t(`--cm-route-possible`),faded:t(`--cm-hairline-soft`),star:t(`--cm-star-high`),starHalo:t(`--cm-star-halo`),nebula:Object.freeze(Object.fromEntries(Object.entries(zG).map(([e,n])=>[e,t(n)]))),communities:Object.freeze(Array.from({length:8},(e,n)=>t(`--cm-com-${n}`))),labelPlate:e.getPropertyValue(`--cm-label-plate`).trim(),labelInk:e.getPropertyValue(`--cm-label-ink`).trim()})}function Wq({hint:e,onFollow:t,firstFlight:n}){let r=(0,_.useRef)(null),i=(0,_.useRef)(!1);if((0,_.useLayoutEffect)(()=>{n?.active&&!i.current&&r.current?.focus(),i.current=n?.active===!0},[n?.active]),n?.active){let{stop:e,index:t,total:i,mode:a}=n;return(0,$.jsxs)(`output`,{className:`hint-chip first-flight`,"aria-live":`polite`,"data-first-flight":`active`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),(0,$.jsxs)(`strong`,{children:[`First Flight · `,t+1,` of `,i]}),(0,$.jsx)(`span`,{className:`first-flight__system`,children:e.id}),(0,$.jsxs)(`small`,{children:[a===`easy`?`${e.language} file`:`${e.language} system`,` · used by ${e.usedBy} · uses ${e.uses}`]}),(0,$.jsxs)(`span`,{className:`first-flight__actions`,children:[(0,$.jsx)(`button`,{type:`button`,disabled:t===0,onClick:n.onBack,children:`Back`}),t+1{let e=i.current;e&&!e.open&&e.showModal(),a.current?.focus()},[]);function c(){i.current?.close(),t()}return(0,$.jsxs)(`dialog`,{ref:i,className:`coach-marks`,"aria-labelledby":`coach-heading`,onCancel:e=>{e.preventDefault(),c()},children:[(0,$.jsxs)(`p`,{className:`coach-marks__progress`,children:[`Step `,n+1,` of `,o.length]}),(0,$.jsx)(`h1`,{id:`coach-heading`,children:s.title}),(0,$.jsx)(`p`,{children:s.body}),(0,$.jsxs)(`div`,{className:`coach-marks__actions`,children:[(0,$.jsx)(`button`,{type:`button`,className:`coach-skip`,onClick:c,children:`Skip`}),(0,$.jsx)(`button`,{ref:a,type:`button`,className:`check-primary`,onClick:()=>n+1({left:Math.min(e.left,t),top:Math.min(e.top,n),right:Math.max(e.right,t),bottom:Math.max(e.bottom,n)}),{left:1/0,top:1/0,right:-1/0,bottom:-1/0})}function iJ(e,t){return!(e.rightt.right||e.bottomt.bottom)}function aJ(e,t){let n=new Map;for(let r of e){let e=t(r),i=Math.floor(e.top/Xq),a=Math.floor(e.bottom/Xq);for(let e=i;e<=a;e+=1){let t=n.get(e)??[];t.push(r),n.set(e,t)}}return n}function oJ(e){let t=Math.max(e.scale||1,1e-4);return{left:(e.scrollLeft-(e.offsetX||0))/t-nJ,top:e.scrollTop/t-nJ,right:(e.scrollLeft-(e.offsetX||0)+e.width)/t+nJ,bottom:(e.scrollTop+e.height)/t+nJ}}function sJ(e,t){let n=t-eJ-tJ,r=Math.max(1,Math.floor(n/(Qq*$q)));return e.length<=r?e:`${e.slice(0,Math.max(1,r-1))}…`}function cJ(e,{communityIndexByRegion:t=null}={}){let n=e.boxes.map(e=>({...e,drawX:e.x+Jq,drawY:e.y+Jq,communityFamily:t?.get(e.id)??null})).sort((e,t)=>e.y-t.y||e.x-t.x||e.id.localeCompare(t.id)),r=new Map(n.map(e=>[e.id,e])),i=aJ(n,e=>({left:e.drawX,top:e.drawY,right:e.drawX+e.width,bottom:e.drawY+e.height})),a=e.edges.filter(e=>r.has(e.src)&&r.has(e.dst)).map(e=>{let t=e.points.map(([e,t])=>[e+Jq,t+Jq]);return{...e,points:t,bounds:rJ(t)}});return Object.freeze({kind:`architecture`,boxes:n,boxById:r,boxesByBand:i,edges:a,padding:Jq})}function lJ(e,t){let n=oJ(t);return{boxes:e.boxes.filter(e=>iJ(n,{left:e.drawX,top:e.drawY,right:e.drawX+e.width,bottom:e.drawY+e.height})),edges:e.edges.filter(e=>iJ(n,e.bounds))}}function uJ(e,t){return e.boxesByBand.get(Math.floor(t.y/Xq))?.find(e=>t.x>=e.drawX&&t.x<=e.drawX+e.width&&t.y>=e.drawY&&t.y<=e.drawY+e.height)??null}function dJ(e,t,n,r,i){if(!e.length)return null;if(n===`Home`)return e[0];if(n===`End`)return e.at(-1);let a=Math.max(0,e.findIndex(e=>r(e)===t)),o=e[a]??e[0],s=i(o),c={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[n];if(!c)return o;let l=e.filter(e=>r(e)!==r(o)).map(e=>{let t=i(e),n=t.x-s.x,r=t.y-s.y;return{item:e,forward:n*c[0]+r*c[1],cross:Math.abs(n*c[1]-r*c[0])}}).filter(e=>e.forward>0).sort((e,t)=>e.cross/e.forward-t.cross/t.forward||Math.hypot(e.forward,e.cross)-Math.hypot(t.forward,t.cross)||r(e.item).localeCompare(r(t.item)));if(l.length)return l[0].item;let u=n===`ArrowLeft`||n===`ArrowUp`?a-1:a+1;return e[Math.max(0,Math.min(e.length-1,u))]}function fJ(e,t,n){return dJ(e.boxes,t,n,e=>e.id,e=>({x:e.drawX+e.width/2,y:e.drawY+e.height/2}))}function pJ(e){return`${e.label}, ${e.node_count} ${e.node_count===1?`structure`:`structures`}, ${e.loc} ${e.loc===1?`line`:`lines`}${e.understood?`, understood`:`, not yet understood`}${e.home?`, Home`:``}${e.reachable?``:`, no import route from Home`}${e.partial?`, unchartable, syntax error`:``}`}function mJ(e){let t=[...e.nodes].sort((e,t)=>e.order-t.order).map(e=>{let t=e.x+Yq,n=e.y+Yq,r=e.label.length*13*$q,i=Math.max(vJ(e,`easy`).length,vJ(e,`expert`).length)*11*$q;return{...e,drawX:t,drawY:n,bounds:{left:t,top:n,right:t+20+r+i+8,bottom:n+Zq}}}),n=new Map,r=[];for(let e of t){let t=e.parent===null?null:n.get(e.parent)??null;if(t){let n=[[t.drawX+8,t.drawY+20],[t.drawX+8,e.drawY+12],[e.drawX+8,e.drawY+12]];r.push({row:e,parent:t,points:n,bounds:rJ(n)})}n.set(e.id,e)}return Object.freeze({kind:`workflow`,rows:t,rowByOrder:new Map(t.map(e=>[e.order,e])),rowsByBand:aJ(t,e=>e.bounds),edges:r,padding:Yq})}function hJ(e,t){let n=oJ(t);return{rows:e.rows.filter(e=>iJ(n,e.bounds)),edges:e.edges.filter(e=>iJ(n,e.bounds))}}function gJ(e,t){return e.rowsByBand.get(Math.floor(t.y/Xq))?.find(e=>t.x>=e.bounds.left&&t.x<=e.bounds.right&&t.y>=e.bounds.top&&t.y<=e.bounds.bottom)??null}function _J(e,t,n){if(!e.rows.length)return null;if(n===`Home`)return e.rows[0];if(n===`End`)return e.rows.at(-1);let r=Math.max(0,e.rows.findIndex(e=>e.order===t)),i=e.rows[r]??e.rows[0];if(n===`ArrowLeft`&&i.parent!==null)return e.rows.slice(0,r).reverse().find(e=>e.id===i.parent)??i;if(n===`ArrowRight`)return e.rows.slice(r+1).find(e=>e.parent===i.id)??i;let a=n===`ArrowUp`?-1:+(n===`ArrowDown`);return e.rows[r+a]??i}function vJ(e,t){let n=[];return e.relation===`defines`?n.push(t===`easy`?`lives here`:`defined in this module`):e.certain||n.push(`possible call`),e.cut===`cycle`&&n.push(`loops back`),e.cut===`repeat`&&n.push(`shown above`),e.partial&&n.push(t===`easy`?`could not be read`:`unchartable`),n.map(e=>` — ${e}`).join(``)}function yJ(e){return`${e.label} at ${e.file}:${e.lineno}${e.certain?``:`, possible call`}${e.cut===`cycle`?`, repeats an earlier step`:``}${e.cut===`repeat`?`, already shown above`:``}${e.partial?`, unchartable, syntax error`:``}`}function bJ(e,t,n){return e?.getPropertyValue?.(t)?.trim()||n}function xJ(e){let t=e.match(/^#([0-9a-f]{6})$/i)?.[1];if(t)return[0,2,4].map(e=>Number.parseInt(t.slice(e,e+2),16));let n=e.match(/^rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)/i);return n?n.slice(1).map(Number):null}function SJ(e,t,n){let r=xJ(e),i=xJ(t);return!r||!i?t:`rgb(${r.map((e,t)=>Math.round(e*n+i[t]*(1-n))).join(` `)})`}function CJ(e){let t=bJ(e,`--cm-ground-2`,`#101a3e`),n=Array.from({length:8},(n,r)=>SJ(bJ(e,`--cm-com-${r}`,t),t,.16));return Object.freeze({ground2:t,hairline:bJ(e,`--cm-hairline`,`#24325c`),ink:bJ(e,`--cm-ink`,`#eef2fa`),ink3:bJ(e,`--cm-ink-3`,`#7d8aa8`),route:bJ(e,`--cm-route`,`rgb(96 113 152)`),possible:bJ(e,`--cm-route-possible`,`rgb(146 160 194)`),understood:bJ(e,`--cm-star-high`,`#f6d087`),interaction:bJ(e,`--cm-orbit`,`#82abec`),mono:bJ(e,`--cm-font-mono`,`monospace`),communities:n,language:{python:bJ(e,`--cm-neb-python`,`rgb(112 166 144)`),javascript:bJ(e,`--cm-neb-js`,`rgb(161 151 185)`),typescript:bJ(e,`--cm-neb-ts`,`rgb(119 161 186)`),go:bJ(e,`--cm-neb-go`,`rgb(132 178 161)`),java:bJ(e,`--cm-neb-java`,`rgb(177 154 137)`),rust:bJ(e,`--cm-neb-rust`,`rgb(183 145 132)`),csharp:bJ(e,`--cm-neb-csharp`,`rgb(157 146 184)`)}})}function wJ(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.lineTo(t+r-a,n),e.quadraticCurveTo(t+r,n,t+r,n+a),e.lineTo(t+r,n+i-a),e.quadraticCurveTo(t+r,n+i,t+r-a,n+i),e.lineTo(t+a,n+i),e.quadraticCurveTo(t,n+i,t,n+i-a),e.lineTo(t,n+a),e.quadraticCurveTo(t,n,t+a,n),e.closePath()}function TJ(e,t){e.save(),e.translate((t.offsetX||0)-t.scrollLeft,-t.scrollTop),e.scale(t.scale,t.scale),e.lineCap=`round`,e.lineJoin=`round`}function EJ(e,t,n){if(t.length<2)return;let[r,i]=t.at(-2),[a,o]=t.at(-1),s=Math.atan2(o-i,a-r);e.save(),e.translate(a,o),e.rotate(s),e.fillStyle=n,e.beginPath(),e.moveTo(0,0),e.lineTo(-9,-4),e.lineTo(-9,4),e.closePath(),e.fill(),e.restore()}function DJ(e,t,n,r,i={}){let a=lJ(t,n);TJ(e,n);for(let t of a.edges){let n=t.certain&&!t.cycle?r.route:r.possible;e.strokeStyle=n,e.lineWidth=1+Math.min(2.5,(Math.max(1,t.weight)-1)*.5),e.setLineDash(t.certain?[]:[5,4]),e.beginPath(),t.points.forEach(([t,n],r)=>r===0?e.moveTo(t,n):e.lineTo(t,n)),e.stroke(),e.setLineDash([]),EJ(e,t.points,n)}for(let t of a.boxes){let n=t.drawX,a=t.drawY,o=t.communityFamily===null?r.ground2:r.communities[t.communityFamily]??r.ground2;wJ(e,n,a,t.width,t.height,3),e.fillStyle=o,e.fill(),e.strokeStyle=t.understood?r.understood:t.partial?r.possible:r.hairline,e.lineWidth=t.home?2:1,e.setLineDash(t.reachable?[]:[4,3]),e.stroke(),e.setLineDash([]),e.fillStyle=r.language[t.language]??r.hairline,e.fillRect(n,a,4,t.height),t.partial&&(e.fillStyle=r.possible,e.beginPath(),e.moveTo(n+t.width-16,a+2),e.lineTo(n+t.width-2,a+2),e.lineTo(n+t.width-2,a+16),e.closePath(),e.fill()),(t.id===i.selectedId||t.id===i.activeId||t.id===i.hoverId)&&(wJ(e,n-3,a-3,t.width+6,t.height+6,5),e.strokeStyle=r.interaction,e.lineWidth=t.id===i.activeId&&i.keyboardFocused?2.5:1.5,e.stroke()),e.fillStyle=r.ink,e.font=`13px ${r.mono}`,e.fillText(sJ(t.short_label??t.label,t.width),n+14,a+24),e.fillStyle=r.ink3,e.font=`11px ${r.mono}`;let s=i.mode===`easy`?`${t.node_count} ${t.node_count===1?`piece`:`pieces`}`:`${t.node_count} ${t.node_count===1?`node`:`nodes`} · ${t.loc} LOC`;e.fillText(s,n+14,a+42)}return e.restore(),{visibleBoxes:a.boxes.length,visibleEdges:a.edges.length}}function OJ(e,t,n,r,i={}){let a=hJ(t,n);TJ(e,n);for(let t of a.edges)e.strokeStyle=t.row.certain?r.route:r.possible,e.lineWidth=1.2,e.setLineDash(t.row.certain?[]:[5,4]),e.beginPath(),t.points.forEach(([t,n],r)=>r===0?e.moveTo(t,n):e.lineTo(t,n)),e.stroke();e.setLineDash([]);for(let t of a.rows){let n=t.drawX,a=t.drawY;e.fillStyle=t.understood?r.understood:t.partial||t.cut?r.possible:r.ink3,e.beginPath(),e.arc(n+8,a+16,4,0,Math.PI*2),e.fill(),(t.region===i.selectedRegionId||t.order===i.activeOrder||t.order===i.hoverOrder)&&(e.strokeStyle=r.interaction,e.lineWidth=t.order===i.activeOrder&&i.keyboardFocused?2.5:1.5,e.beginPath(),e.arc(n+8,a+16,7,0,Math.PI*2),e.stroke()),e.fillStyle=r.ink,e.font=`13px ${r.mono}`;let o=e.measureText(t.label).width;e.fillText(t.label,n+20,a+20),e.fillStyle=r.ink3,e.font=`11px ${r.mono}`,e.fillText(vJ(t,i.mode),n+20+o,a+20)}return e.restore(),{visibleRows:a.rows.length,visibleEdges:a.edges.length}}var kJ=Object.freeze({architecturePadding:Jq,workflowPadding:Yq}),AJ=.05,jJ=2.5;function MJ(e){return Math.min(jJ,Math.max(AJ,e))}function NJ(e,t,n,r){return!e||!t||!n||!r?1:MJ(Math.min(e/n,t/r))}function PJ({viewportWidth:e,viewportHeight:t,scale:n,point:r}){return{scrollLeft:Math.max(0,r.x*n-e/2),scrollTop:Math.max(0,r.y*n-t/2)}}function FJ({viewportWidth:e,viewportHeight:t,scale:n,scrollLeft:r,scrollTop:i,point:a}){if(!a||!e||!t)return!1;let o=a.x*n,s=a.y*n;return o>=r&&o<=r+e&&s>=i&&s<=i+t}var IJ=.35;function LJ(e,t,n,r){if(!e||!t||!n||!r)return 1;let i=NJ(e,t,n,r);return i>=.35?i:MJ(Math.min(IJ,e/n))}function RJ(){let e=new Map;return Object.freeze({read(t){let n=e.get(t);return n?{...n}:null},write(t,n){e.set(t,{scale:MJ(n.scale),scrollLeft:Math.max(0,n.scrollLeft),scrollTop:Math.max(0,n.scrollTop)})},clear(){e.clear()}})}var zJ=1.25;function BJ({contentWidth:e,contentHeight:t,label:n,viewKey:r,viewportStore:i,focusPoint:a,centerInline:o=!1,children:s}){let c=(0,_.useRef)(null),l=(0,_.useRef)(i.read(r)),[u,d]=(0,_.useState)(()=>l.current?.scale??1),[f,p]=(0,_.useState)(!1),m=(0,_.useRef)(null),h=(0,_.useRef)(!1),g=(0,_.useRef)(0),[v,y]=(0,_.useState)({width:0,height:0,scrollLeft:0,scrollTop:0}),b=Math.round(u*100),x=(0,_.useCallback)(()=>{let e=c.current;if(!e)return;let t={width:e.clientWidth,height:e.clientHeight,scrollLeft:e.scrollLeft,scrollTop:e.scrollTop};y(e=>e.width===t.width&&e.height===t.height&&e.scrollLeft===t.scrollLeft&&e.scrollTop===t.scrollTop?e:t)},[]),S=(0,_.useCallback)(()=>{cancelAnimationFrame(g.current),g.current=requestAnimationFrame(x)},[x]);(0,_.useEffect)(()=>()=>cancelAnimationFrame(g.current),[]);let C=(0,_.useCallback)(()=>{let e=c.current;e&&i.write(r,{scale:u,scrollLeft:e.scrollLeft,scrollTop:e.scrollTop})},[u,r,i]),w=(0,_.useCallback)(()=>{let n=c.current?.getBoundingClientRect();!n||!e||!t||d(LJ(n.width,n.height,e,t))},[e,t]);(0,_.useLayoutEffect)(()=>{let e=c.current;if(!e||h.current)return;let t=0;return t=requestAnimationFrame(()=>{let t=e.getBoundingClientRect(),n=l.current,r=n&&(!a||FJ({viewportWidth:t.width,viewportHeight:t.height,scale:n.scale,scrollLeft:n.scrollLeft,scrollTop:n.scrollTop,point:a}));if(r)e.scrollLeft=n.scrollLeft,e.scrollTop=n.scrollTop;else if(t.width<640&&a){let n=PJ({viewportWidth:t.width,viewportHeight:t.height,scale:u,point:a});e.scrollLeft=n.scrollLeft,e.scrollTop=n.scrollTop}else n&&!r&&(e.scrollLeft=0,e.scrollTop=0);h.current=!0,C(),x()}),()=>cancelAnimationFrame(t)},[a,x,C,u]),(0,_.useEffect)(()=>{if(!h.current)return;let e=requestAnimationFrame(()=>{C(),x()});return()=>cancelAnimationFrame(e)},[x,C]),(0,_.useEffect)(()=>{let e=c.current;if(!e)return;let t=null,n=new ResizeObserver(([n])=>{let{width:r,height:i}=n.contentRect,o=t;if(t={width:r,height:i},!o||!a||!h.current||Math.abs(r-o.width)<1&&Math.abs(i-o.height)<1||FJ({viewportWidth:r,viewportHeight:i,scale:u,scrollLeft:e.scrollLeft,scrollTop:e.scrollTop,point:a}))return;let s=PJ({viewportWidth:r,viewportHeight:i,scale:u,point:a});e.scrollLeft=s.scrollLeft,e.scrollTop=s.scrollTop,C(),S()});return n.observe(e),()=>n.disconnect()},[a,S,C,u]);let T=o?Math.max(0,(v.width-e*u)/2):0,E=(0,_.useCallback)((e,t=0)=>{let n=c.current;if(!n||!e)return;let r=e.x*u+t,i=e.y*u;n.scrollLeft=Math.max(0,r-n.clientWidth/2),n.scrollTop=Math.max(0,i-n.clientHeight/2),C(),S()},[S,C,u]);function D(e){if(e.button!==0||e.target.closest(`[role='button']`))return;let t=c.current;m.current={x:e.clientX,y:e.clientY,left:t.scrollLeft,top:t.scrollTop},p(!0),t.setPointerCapture(e.pointerId)}function O(e){if(!m.current)return;let t=c.current;t.scrollLeft=m.current.left-(e.clientX-m.current.x),t.scrollTop=m.current.top-(e.clientY-m.current.y)}function k(e){m.current&&(m.current=null,p(!1),c.current?.releasePointerCapture?.(e.pointerId))}return(0,$.jsxs)(`div`,{className:`map-canvas`,children:[(0,$.jsxs)(`div`,{className:`map-zoom`,role:`group`,"aria-label":`Zoom ${n}`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom out`,disabled:u<=.05,onClick:()=>d(e=>MJ(e/zJ)),children:`−`}),(0,$.jsx)(`button`,{type:`button`,onClick:w,children:`Fit`}),(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Reset zoom to 100%. Current zoom ${b}%.`,title:`Reset zoom to 100%`,onClick:()=>d(1),children:[b,`%`]}),(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom in`,disabled:u>=2.5,onClick:()=>d(e=>MJ(e*zJ)),children:`+`})]}),(0,$.jsx)(`div`,{ref:c,className:`map-scroll`,"data-panning":f||void 0,onPointerDown:D,onPointerMove:O,onPointerUp:k,onPointerCancel:k,onScroll:()=>{h.current&&(C(),S())},children:(0,$.jsx)(`div`,{className:`map-canvas__sized`,style:{width:e*u,height:t*u},children:typeof s==`function`?s({offsetX:T,revealPoint:E,scale:u,viewport:{...v,offsetX:T,scale:u}}):s})})]})}function VJ({ariaLabel:e,canvasClassName:t,drawScene:n,edgeCount:r,fallbackItem:i,hitTarget:a,itemForKey:o,itemIdentity:s,itemKey:c,itemLabel:l,itemPoint:u,itemReadout:d,keyboardTarget:f,onActivate:p,preferredKey:m,revealPoint:h,scene:g,viewport:v}){let y=(0,_.useRef)(null),b=(0,_.useRef)(null),x=(0,_.useId)(),S=(0,_.useRef)(m),[C,w]=(0,_.useState)(m??(i?c(i):null)),[T,E]=(0,_.useState)(null),[D,O]=(0,_.useState)(!1),[k,A]=(0,_.useState)(0),ee=(0,_.useMemo)(()=>CJ(getComputedStyle(document.documentElement)),[]);(0,_.useEffect)(()=>{let e=!1;return document.fonts?.ready?.then(()=>{e||A(e=>e+1)}),()=>{e=!0}},[]),(0,_.useEffect)(()=>{let e=S.current!==m;S.current=m,w(t=>e&&m!=null&&o(m)?m:o(t)?t:m!=null&&o(m)?m:i?c(i):null)},[i,o,c,m]);let te=C===null?null:o(C),j=T===null?null:o(T),ne=te?l(te):``,re=j??(D?te:null),M=g.kind===`architecture`?g.boxes:g.rows,N=te?M.findIndex(e=>c(e)===c(te))+1:0,ie=te?[...new TextEncoder().encode(String(s(te)))].map(e=>e.toString(16).padStart(2,`0`)).join(``):``,ae=N&&ie?`${x}-active-${N}-${ie}`:void 0;(0,_.useLayoutEffect)(()=>{let e=y.current;if(!e||v.width<1||v.height<1)return;let t=Math.min(2,Math.max(1,window.devicePixelRatio||1)),r=Math.max(1,Math.round(v.width*t)),i=Math.max(1,Math.round(v.height*t));e.width!==r&&(e.width=r),e.height!==i&&(e.height=i),e.style.width=`${v.width}px`,e.style.height=`${v.height}px`;let a=e.getContext(`2d`);a.setTransform(t,0,0,t,0,0),a.clearRect(0,0,v.width,v.height);let o=n(a,{activeKey:C,hoverKey:T,keyboardFocused:D,palette:ee,viewport:v});e.dataset.visibleItems=String(o.visibleItems),e.dataset.visibleEdges=String(o.visibleEdges)},[C,n,k,T,D,ee,v]);function oe(e){let t=y.current.getBoundingClientRect();return{x:(e.clientX-t.left+v.scrollLeft-(v.offsetX||0))/v.scale,y:(e.clientY-t.top+v.scrollTop)/v.scale}}function P(e){h(u(e),v.offsetX||0)}function se(e){if(e.key===`Enter`||e.key===` `){if(!te)return;e.preventDefault(),p(te);return}if(!/^(ArrowLeft|ArrowRight|ArrowUp|ArrowDown|Home|End)$/.test(e.key))return;e.preventDefault();let t=f(g,C,e.key);t&&(w(c(t)),P(t))}function F(e){return a(g,oe(e))}return(0,$.jsxs)(`div`,{className:`map-canvas-surface ${t}`,role:`listbox`,tabIndex:0,"aria-label":`${e}. Use arrow keys to move, Home or End to jump, and Enter or Space to open.`,"aria-activedescendant":ae,"data-item-count":M.length,"data-edge-count":r,onFocus:()=>O(!0),onBlur:()=>O(!1),onKeyDown:se,style:{width:v.width,height:v.height},children:[(0,$.jsx)(`canvas`,{ref:y,"aria-hidden":`true`,title:re?d(re):ne,onPointerDown:e=>{let t=F(e);b.current=t?c(t):null,t&&e.stopPropagation()},onPointerMove:e=>{if(e.buttons)return;let t=F(e);E(t?c(t):null)},onPointerLeave:()=>E(null),onClick:e=>{let t=F(e);!t||c(t)!==b.current||(w(c(t)),p(t))}}),re?(0,$.jsx)(`span`,{className:`map-canvas-readout`,"aria-hidden":`true`,children:d(re)}):null,te?(0,$.jsx)(`span`,{id:ae,role:`option`,"aria-selected":`true`,"aria-posinset":N,"aria-setsize":M.length,className:`map-canvas-active-option`,children:ne}):null]})}function HJ({data:e,mapTab:t,mode:n,communityIndexByRegion:r,selectedRegionId:i,hasEntrypointCandidates:a,unsupportedSources:o,importCycles:s,error:c,onSelectTab:l,onSelectRegion:u,onSelectNode:d,onRetry:f,viewportStore:p,languageFocusLabel:m=``,onClearLanguageFocus:h,children:g}){return(0,$.jsxs)(`section`,{className:`map-view`,"aria-label":`Two-dimensional project map`,children:[(0,$.jsxs)(`nav`,{className:`map-tabs`,"aria-label":`Map view`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`architecture`,onClick:()=>l(`architecture`),children:n===`easy`?`How it fits together`:`Architecture`}),(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`workflow`,onClick:()=>l(`workflow`),children:n===`easy`?`What runs first`:`Workflow`})]}),g,c?(0,$.jsxs)(`div`,{className:`map-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The map did not load.`}),(0,$.jsxs)(`p`,{children:[c,` The galaxy layer is unaffected.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:f,children:`Try again`})]}):e?t===`architecture`?(0,$.jsx)(qJ,{architecture:e.architecture,mode:n,communityIndexByRegion:r,selectedRegionId:i,hasEntrypointCandidates:a,onSelectRegion:u,viewportStore:p,languageFocusLabel:m,onClearLanguageFocus:h}):(0,$.jsx)(JJ,{workflow:e.workflow,mode:n,selectedRegionId:i,hasEntrypointCandidates:a,onSelectNode:d,viewportStore:p,languageFocusLabel:m,onClearLanguageFocus:h}):(0,$.jsx)(`p`,{className:`map-loading`,role:`status`,children:`Laying out parser evidence…`}),UG(o,n)?(0,$.jsxs)(`p`,{className:`map-note`,children:[UG(o,n),n===`easy`?` — Codemble does not read that language yet, so none of it is drawn here.`:` — outside every registered adapter; no structure is inferred for them.`]}):null,gK(s,n)?(0,$.jsx)(`p`,{className:`map-note`,children:gK(s,n)}):null]})}var UJ=e=>e.id,WJ=e=>({x:e.drawX+e.width/2,y:e.drawY+e.height/2}),GJ=e=>e.order,KJ=e=>({x:e.drawX+8,y:e.drawY+16});function qJ({architecture:e,mode:t,communityIndexByRegion:n,selectedRegionId:r,hasEntrypointCandidates:i,onSelectRegion:a,viewportStore:o,languageFocusLabel:s,onClearLanguageFocus:c}){let l=(0,_.useMemo)(()=>new Set(e.unreachable),[e.unreachable]),u=e.boxes.length>0&&e.boxes.every(e=>l.has(e.id)),d=(0,_.useMemo)(()=>cJ(e,{communityIndexByRegion:n}),[e,n]),f=d.boxById.get(r)??d.boxById.get(e.home)??d.boxes.find(e=>e.home)??d.boxes[0]??null,p=f?WJ(f):null,m=(0,_.useCallback)(e=>d.boxById.get(e)??null,[d]),h=(0,_.useCallback)((e,n)=>{let i=DJ(e,d,n.viewport,n.palette,{activeId:n.activeKey,hoverId:n.hoverKey,keyboardFocused:n.keyboardFocused,mode:t,selectedId:r});return{visibleItems:i.visibleBoxes,visibleEdges:i.visibleEdges}},[t,d,r]),g=e.home?`${e.boxes.length} modules in ${e.layer_count} import layers from Home`:`${e.boxes.length} modules in ${e.layer_count} import layers, measured from the modules nothing imports`;return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(BJ,{contentWidth:e.width+kJ.architecturePadding*2,contentHeight:e.height+kJ.architecturePadding*2,label:`the architecture map`,viewKey:`architecture:${e.home??`none`}`,viewportStore:o,focusPoint:p,centerInline:!0,children:({revealPoint:e,viewport:t})=>(0,$.jsx)(VJ,{ariaLabel:g,canvasClassName:`architecture-map-canvas`,drawScene:h,edgeCount:d.edges.length,fallbackItem:f,hitTarget:uJ,itemForKey:m,itemIdentity:e=>e.id,itemKey:UJ,itemLabel:pJ,itemPoint:WJ,itemReadout:e=>e.label,keyboardTarget:fJ,onActivate:e=>a(e.id),preferredKey:d.boxById.has(r)?r:f?.id,revealPoint:e,scene:d,viewport:t})}),e.home?null:(0,$.jsxs)(`p`,{className:`map-note`,children:[`No Home is selected, so these layers run from the modules nothing else imports rather than from your entrypoint. Both are read from your imports, not guessed.`,` `,i?`Pick your starting point with “Change Home” to see the same modules layered by what the project runs first.`:`This project has no parser-recognisable entrypoint, so there is no “runs first” order to layer by instead.`]}),u?(0,$.jsxs)(`p`,{className:`map-note`,children:[s?`Home is not written in ${s}, so none of these ${e.boxes.length} ${e.boxes.length===1?`module`:`modules`} has an import route to it. They are drawn in file order rather than layered by guesswork.`:`None of these ${e.boxes.length} ${e.boxes.length===1?`module`:`modules`} has an import route from Home, so they are drawn in file order rather than layered by guesswork.`,` `,s&&c?(0,$.jsx)(`button`,{type:`button`,className:`map-note__toggle`,onClick:c,children:`Show all languages`}):null]}):e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`module has`:`modules have`,` no import route from Home, so `,e.unreachable.length===1?`it sits`:`they sit`,` `,`in the bottom rows rather than being placed by guesswork. Every module remains searchable, drawable, and keyboard reachable.`]}):null]})}function JJ({workflow:e,mode:t,selectedRegionId:n,hasEntrypointCandidates:r,onSelectNode:i,viewportStore:a,languageFocusLabel:o,onClearLanguageFocus:s}){return e.root&&e.nodes.length===0?(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:o?`Nothing in ${o} runs from Home.`:`Nothing runs from Home yet.`}),(0,$.jsx)(`p`,{children:o?`This tab follows what Home calls, and Home is not written in ${o} — so no ${o} structure appears on a parser-proven call route. The other tab still maps how these modules import each other.`:`This tab follows what Home calls, and the parser proved no call route out of it yet.`}),o&&s?(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Show all languages`}):null]}):e.root?(0,$.jsx)(YJ,{workflow:e,mode:t,selectedRegionId:n,onSelectNode:i,viewportStore:a}):r?(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No Home is selected.`}),(0,$.jsx)(`p`,{children:`The workflow tree starts at your entrypoint. Pick Home and this tab will show what runs first, then what that calls.`})]}):(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No “runs first” order to show.`}),(0,$.jsx)(`p`,{children:`This project has no parser-recognisable entrypoint — nothing here declares a startup structure Codemble recognises, and it will not guess one. The other tab still maps how your modules import each other.`})]})}function YJ({workflow:e,mode:t,selectedRegionId:n,onSelectNode:r,viewportStore:i}){let a=(0,_.useMemo)(()=>mJ(e),[e]),o=a.rows.find(e=>e.region===n)??null??a.rows.find(t=>t.id===e.root)??a.rows[0]??null,s=o?KJ(o):null,c=(0,_.useCallback)(e=>a.rowByOrder.get(Number(e))??null,[a]),l=(0,_.useCallback)((e,r)=>{let i=OJ(e,a,r.viewport,r.palette,{activeOrder:r.activeKey,hoverOrder:r.hoverKey,keyboardFocused:r.keyboardFocused,mode:t,selectedRegionId:n});return{visibleItems:i.visibleRows,visibleEdges:i.visibleEdges}},[t,a,n]);return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(BJ,{contentWidth:e.width+kJ.workflowPadding*2,contentHeight:e.height+kJ.workflowPadding*2,label:`the workflow tree`,viewKey:`workflow:${e.root}`,viewportStore:i,focusPoint:s,children:({revealPoint:t,viewport:n})=>(0,$.jsx)(VJ,{ariaLabel:`Call tree from ${e.root}, ${e.nodes.length} steps deep to ${e.depth_count} levels`,canvasClassName:`workflow-map-canvas`,drawScene:l,edgeCount:a.edges.length,fallbackItem:o,hitTarget:gJ,itemForKey:c,itemIdentity:e=>`${e.order}:${e.id}:${e.file}:${e.lineno}`,itemKey:GJ,itemLabel:yJ,itemPoint:KJ,itemReadout:e=>`${e.label} · ${e.file}:${e.lineno}`,keyboardTarget:_J,onActivate:e=>r(e.id),preferredKey:o?.order,revealPoint:t,scene:a,viewport:n})}),e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`structure is`:`structures are`,` never reached from Home by a parser-proven call. They are listed as unreached rather than attached to the tree by guesswork.`]}):null]})}var XJ=m(),ZJ=[{mode:`easy`,label:`New to coding?`},{mode:`expert`,label:`I build software`}],QJ=[{mode:`easy`,label:`Easy`},{mode:`expert`,label:`Expert`}];function $J({mode:e,modeChosen:t,onChoose:n}){let r=(0,_.useRef)(null);(0,_.useLayoutEffect)(()=>{let e=r.current;e&&t===!1&&!e.open&&e.showModal()},[t]);function i(e){r.current?.close(),n(e)}return t===null?null:t?(0,$.jsxs)(`fieldset`,{className:`mode-toggle`,children:[(0,$.jsx)(`legend`,{className:`mode-toggle__label`,children:`Audience`}),(0,$.jsx)(`div`,{className:`mode-toggle__options`,children:QJ.map(t=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:`radio`,name:`audience-mode`,value:t.mode,checked:e===t.mode,onChange:()=>i(t.mode)}),(0,$.jsx)(`span`,{children:t.label})]},t.mode))})]}):(0,XJ.createPortal)((0,$.jsxs)(`dialog`,{ref:r,className:`mode-gate`,"aria-labelledby":`mode-gate-heading`,"aria-describedby":`mode-gate-detail`,onCancel:e=>e.preventDefault(),children:[(0,$.jsx)(`h1`,{id:`mode-gate-heading`,children:`New to coding, or do you build software already?`}),(0,$.jsx)(`p`,{id:`mode-gate-detail`,children:`This changes how much Codemble explains and how much it assumes you already know.`}),(0,$.jsx)(`div`,{className:`mode-gate__options`,children:ZJ.map(e=>(0,$.jsx)(`button`,{type:`button`,onClick:()=>i(e.mode),children:e.label},e.mode))})]}),document.body)}function eY(e,t){let n=e?.steps??[];return n.length?n.some(e=>e.id===t)?t:n[0].id:null}function tY(e,t,n){let r=e?.steps??[];if(!r.length)return null;let i=eY(e,t),a=Math.max(0,r.findIndex(e=>e.id===i));return r[Math.max(0,Math.min(r.length-1,a+n))].id}function nY(e,t,n){let r=e?.steps??[],i=eY(e,t),a=r.findIndex(e=>e.id===i);if(a<0)return null;let o=r[a];return{id:o.id,index:a,total:r.length,position:`${a+1} of ${r.length}`,heading:rY(o),summary:iY(o),citation:o.declaration?.citation??o.citation??null,observationCitation:o.observation?.citation??null,isFirst:a===0,isLast:a===r.length-1,isTarget:!!o.is_target,expertDetails:n===`expert`?{layer:String(o.layer??`unknown`).replaceAll(`-`,` `),relation:o.relation??`unknown`,ruleId:o.rule_id??null,nodeId:o.node_id??null}:null}}function rY(e){return e.relation===`home`?`Start at Home: ${e.name}`:e.relation===`import`?`Open ${e.name}`:e.relation===`call`?`Follow the call to ${e.name}`:e.relation===`role`?e.role===`ui-renderer`?`Reach the screen in ${e.name}`:e.role===`test`?`Enter through test surface ${e.name}`:`Enter through ${e.name}`:`Read ${e.name}`}function iY(e){return e.relation===`home`?`The parser ranked this as the project's starting point.`:e.relation===`import`?`A certain import connects the previous file to this declaration.`:e.relation===`call`?e.is_target?`A certain call reaches the structure you selected.`:`A certain call continues the runtime route through this structure.`:e.relation===`role`?e.role===`route-handler`?`A parser-proven route registration is where a request reaches the application.`:e.role===`ui-renderer`?`Parser-proven rendering syntax connects this function to the visible interface.`:e.role===`test`?`Only a parser-proven test surface reaches this route; it is not an application screen.`:`The parser proved this is an application entry before the runtime route continues.`:`This is the next parser-proven declaration on the route.`}function aY({node:e,study:t,error:n,mode:r,explanation:i,explanationLoading:a,explanationError:o,llmStatus:s,onSelectNode:c,onRetryStudy:l,onRetryNarration:u,onClose:d,revealSource:f=!1}){let p=(0,_.useRef)(null),m=(0,_.useRef)(null),h=(0,_.useRef)(null),g=(0,_.useRef)(null),v=(0,_.useRef)(null),y=(0,_.useRef)(null),b=t?.learning_journey??null,[x,S]=(0,_.useState)(null),C=!!t?.source;(0,_.useEffect)(()=>{p.current?.scrollTo({top:0,behavior:`auto`}),m.current?.focus({preventScroll:!0})},[e.id,f]),(0,_.useEffect)(()=>{n&&(p.current?.scrollTo({top:0,behavior:`auto`}),h.current?.focus({preventScroll:!0}))},[n,e.id]),(0,_.useEffect)(()=>{!f||!C||y.current!==e.id&&(y.current=e.id,g.current?.scrollIntoView({block:`start`,behavior:`auto`}),v.current?.focus({preventScroll:!0}))},[f,C,e.id]),(0,_.useEffect)(()=>{S(e=>eY(b,e))},[b]);function w(){p.current?.scrollTo({top:0,behavior:`auto`}),m.current?.focus({preventScroll:!0}),l()}function T(){m.current?.focus({preventScroll:!0}),u()}return(0,$.jsxs)(`aside`,{ref:p,className:`study-preview`,"aria-label":`Selected source structure`,"aria-busy":!t&&!n,children:[(0,$.jsxs)(`header`,{className:`study-preview__header`,children:[d?(0,$.jsx)(`button`,{className:`check-close study-preview__close`,type:`button`,onClick:d,children:`Close`}):null,(0,$.jsxs)(`p`,{className:`study-preview__path`,children:[e.file,`:`,e.lineno]}),(0,$.jsx)(`h1`,{ref:m,tabIndex:-1,children:e.name})]}),n?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,children:[(0,$.jsx)(`h2`,{ref:h,tabIndex:-1,children:`Study data did not load.`}),(0,$.jsxs)(`p`,{children:[n,` The parser map is still available.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:w,children:`Try again`})]}):null,!t&&!n?(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:`Reading parser evidence…`}):null,(0,$.jsxs)(`div`,{className:`study-content`,children:[t?(0,$.jsx)(sY,{journey:b,activeStepId:x,onActiveStepChange:S,impact:t.impact,neighbors:t.neighbors,node:e,mode:r,onSelectNode:c}):null,t?(0,$.jsx)(oY,{node:e,mode:r}):null,t?(0,$.jsx)(lY,{structural:t.structural,mode:r}):null,(0,$.jsx)(SY,{explanation:i,loading:a,error:o,llmStatus:s,mode:r,node:e,onSelectNode:c,onRetry:T}),t?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(bY,{source:t.source,anchorRef:g,headingRef:v}),(0,$.jsx)(yY,{lens:t.lens,language:e.language,mode:r})]}):null]})]})}function oY({node:e,mode:t}){return(0,$.jsx)(`section`,{className:`study-facts`,"aria-label":`Selected structure facts`,children:(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`What it is`:`Kind`}),(0,$.jsx)(`dd`,{children:e.kind})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`Length`:`Span`}),(0,$.jsxs)(`dd`,{children:[e.loc,` `,e.loc===1?`line`:`lines`]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`Called by`:`Callers`}),(0,$.jsx)(`dd`,{children:e.centrality})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:t===`easy`?`Evidence`:`Resolution`}),(0,$.jsx)(`dd`,{children:e.partial?t===`easy`?`Could not be fully read`:`Partial parse`:t===`easy`?`Proven from your code`:`Parser-proven`})]})]})})}function sY({journey:e,activeStepId:t,onActiveStepChange:n,impact:r,neighbors:i,node:a,mode:o,onSelectNode:s}){let[c,l]=(0,_.useState)(``),u=nY(e,t,o),d=e?.steps??[],f=e?.possible_frontier??[],p=e?.verification_candidates??[];(0,_.useEffect)(()=>l(``),[e?.fingerprint]);function m(t){n(t);let r=nY(e,t,o);r&&l(`Journey step ${r.position}: ${r.heading}`)}function h(n){let r=tY(e,t,n);r&&m(r)}return(0,$.jsxs)(`section`,{className:`learning-journey`,"aria-labelledby":`learning-journey-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`learning-journey-heading`,children:`Feature journey`}),(0,$.jsx)(`span`,{children:`Parser evidence`})]}),d.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`ol`,{className:`journey-overview`,"aria-label":`Feature journey steps`,children:d.map((t,n)=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-current":t.id===u?.id?`step`:void 0,"aria-label":`Step ${n+1}: ${nY(e,t.id,o)?.heading}`,onClick:()=>m(t.id),children:[(0,$.jsx)(`span`,{children:n+1}),(0,$.jsx)(`small`,{children:t.layer.replaceAll(`-`,` `)})]})},t.id))}),u?(0,$.jsxs)(`article`,{className:`journey-current`,"data-step-id":u.id,children:[(0,$.jsxs)(`p`,{className:`journey-position`,children:[`Step `,u.position]}),(0,$.jsx)(`h3`,{children:u.heading}),(0,$.jsx)(`p`,{children:u.summary}),(0,$.jsxs)(`div`,{className:`journey-citations`,children:[u.observationCitation?(0,$.jsxs)(`span`,{children:[`Observed at `,(0,$.jsx)(`code`,{children:u.observationCitation})]}):null,(0,$.jsxs)(`span`,{children:[`Declaration `,(0,$.jsx)(`code`,{children:u.citation})]})]}),(0,$.jsxs)(`div`,{className:`journey-controls`,"aria-label":`Journey controls`,children:[(0,$.jsx)(`button`,{type:`button`,onClick:()=>h(-1),disabled:u.isFirst,children:`Back`}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>h(1),disabled:u.isLast,children:`Next`}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>m(d[0].id),disabled:u.isFirst,children:`Replay`})]}),u.expertDetails?(0,$.jsxs)(`dl`,{className:`journey-expert-facts`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Layer`}),(0,$.jsx)(`dd`,{children:u.expertDetails.layer})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Relation`}),(0,$.jsx)(`dd`,{children:u.expertDetails.relation})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Node ID`}),(0,$.jsx)(`dd`,{children:u.expertDetails.nodeId})]}),u.expertDetails.ruleId?(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Parser rule`}),(0,$.jsx)(`dd`,{children:u.expertDetails.ruleId})]}):null]}):null]}):null]}):null,(0,$.jsx)(`span`,{className:`visually-hidden`,"aria-live":`polite`,"aria-atomic":`true`,children:c}),e?.break?(0,$.jsxs)(`div`,{className:`journey-break`,role:`note`,children:[(0,$.jsx)(`strong`,{children:`Proof stops here`}),(0,$.jsx)(`p`,{children:e.break.message}),e.break.citation?(0,$.jsx)(`code`,{children:e.break.citation}):null]}):null,f.length?(0,$.jsxs)(`div`,{className:`journey-possible`,children:[(0,$.jsx)(`h3`,{children:`Possible next evidence`}),(0,$.jsx)(`p`,{children:`These parser observations are not part of the proven route.`}),(0,$.jsx)(`ul`,{children:f.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsxs)(`strong`,{children:[`Possible `,e.relation]}),(0,$.jsxs)(`span`,{children:[e.observation.citation,` → `,e.declaration.citation]})]},`${e.relation}-${e.source_node_id}-${e.target_node_id}-${e.observation.citation}`))})]}):null,(0,$.jsxs)(`details`,{className:`journey-support`,open:o===`expert`,children:[(0,$.jsx)(`summary`,{children:o===`easy`?`Explore selected feature impact and connections`:`Selected feature impact, connections, and verification`}),(0,$.jsxs)(`p`,{className:`journey-support-scope`,children:[`These facts belong to `,a.name,`, the selected feature. They stay fixed while you move between journey steps.`]}),(0,$.jsx)(uY,{impact:r,mode:o,onSelectNode:s}),(0,$.jsx)(pY,{neighbors:i,node:a,mode:o,onSelectNode:s}),o===`expert`?(0,$.jsx)(cY,{items:p,onSelectNode:s}):null]})]})}function cY({items:e,onSelectNode:t}){return(0,$.jsxs)(`section`,{className:`journey-verification`,"aria-labelledby":`journey-verification-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`journey-verification-heading`,children:`Selected feature verification candidates`}),(0,$.jsx)(`span`,{children:`Parser-linked`})]}),e.length?(0,$.jsx)(`ul`,{className:`impact-list`,children:e.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Open verification candidate ${e.name}; ${e.certain?`certain route`:`possible route`}; depth ${e.depth}; ${e.declaration.citation}`,onClick:()=>t(e.node_id),children:[(0,$.jsx)(`span`,{className:`impact-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`impact-meta`,children:[`depth `,e.depth,e.certain?` · certain route`:` · possible route`]}),(0,$.jsx)(`span`,{className:`impact-citation`,children:e.declaration.citation})]})},e.node_id))}):(0,$.jsx)(`p`,{className:`study-loading`,children:`No connected test evidence was found.`}),(0,$.jsx)(`p`,{className:`journey-candidate-note`,children:`These are parser-linked candidate verification points, not proof that a test passes.`})]})}function lY({structural:e,mode:t}){return e?(0,$.jsxs)(`section`,{className:`structural-summary`,"aria-labelledby":`structural-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`structural-heading`,children:t===`easy`?`What this is`:`Structural summary`}),(0,$.jsx)(`span`,{children:`No model needed`})]}),(0,$.jsx)(`p`,{children:e[t]??e.easy})]}):null}function uY({impact:e,mode:t,onSelectNode:n}){if(!e)return null;let r=e.affects??[],i=e.depends_on??[];if(!r.length&&!i.length)return null;let a=t===`easy`;return(0,$.jsxs)(`section`,{className:`impact-widget`,"aria-labelledby":`impact-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`impact-heading`,children:a?`What the selected feature touches`:`Selected feature impact`}),(0,$.jsx)(`span`,{children:`No model needed`})]}),(0,$.jsxs)(`div`,{className:`impact-columns`,children:[(0,$.jsx)(dY,{title:a?`Change this and these change too`:`Change this → affected`,empty:a?`Nothing else in your code would notice if you changed this.`:`No parser-proven dependents.`,items:r,mode:t,onSelectNode:n}),(0,$.jsx)(dY,{title:a?`This needs these to work`:`Depends on → breaks if changed`,empty:a?`This does not rely on anything else in your code.`:`No parser-proven dependencies.`,items:i,mode:t,onSelectNode:n})]}),e.truncated?(0,$.jsx)(`p`,{className:`study-loading`,children:a?`Traced ${e.max_depth} steps out; the chain continues past that.`:`Traced to depth ${e.max_depth}; deeper reach is not shown.`}):null]})}function dY({title:e,empty:t,items:n,mode:r,onSelectNode:i}){return(0,$.jsxs)(`div`,{className:`impact-column`,children:[(0,$.jsx)(`h3`,{children:e}),n.length===0?(0,$.jsx)(`p`,{className:`study-loading`,children:t}):(0,$.jsx)(`ul`,{className:`impact-list`,children:n.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-label":`${e.name} — ${e.depth===1?`direct`:`${e.depth} steps away`}${e.certain?``:`, possible`} — ${e.citation}`,onClick:()=>i(e.node_id),children:[(0,$.jsx)(`span`,{className:`impact-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`impact-meta`,children:[e.depth===1?r===`easy`?`directly`:`direct`:r===`easy`?`${e.depth} steps away`:`depth ${e.depth}`,e.certain?``:r===`easy`?` · possible link`:` · possible`]}),(0,$.jsx)(`span`,{className:`impact-citation`,children:e.citation})]})},e.node_id))})]})}var fY=8;function pY({neighbors:e,node:t,mode:n,onSelectNode:r}){let i=e??[],a=i.filter(e=>e.direction===`inbound`),o=i.filter(e=>e.direction===`outbound`);return(0,$.jsxs)(`section`,{className:`connections`,"aria-labelledby":`connections-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`connections-heading`,children:n===`easy`?`What the selected feature connects to`:`Selected feature connections`}),(0,$.jsxs)(`span`,{children:[i.length,` parser `,i.length===1?`relationship`:`relationships`]})]}),i.length===0?(0,$.jsx)(`p`,{className:`study-loading`,children:n===`easy`?`Nothing in your code reaches this yet, and it does not reach anything else.`:`The parser observed no relationship into or out of this structure.`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(vY,{inbound:a,outbound:o,node:t}),(0,$.jsx)(mY,{title:n===`easy`?`Uses this`:`Inbound`,items:a,mode:n,onSelectNode:r}),(0,$.jsx)(mY,{title:n===`easy`?`This uses`:`Outbound`,items:o,mode:n,onSelectNode:r})]})]})}function mY({title:e,items:t,mode:n,onSelectNode:r}){return t.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:e}),(0,$.jsx)(`ul`,{className:`connection-list`,children:t.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-label":`${e.name} — ${hY(e,n)}, ${gY(e,n)} — ${e.citation}`,onClick:()=>r(e.node_id),children:[(0,$.jsx)(`span`,{className:`connection-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`connection-meta`,children:[hY(e,n),` · `,gY(e,n)]}),(0,$.jsx)(`span`,{className:`source-citation`,children:e.citation})]})},`${e.direction}-${e.node_id}`))})]}):null}function hY(e,t){return e.relationship===`import`?e.direction===`inbound`?t===`easy`?`brings this in`:`import · inbound`:t===`easy`?`this brings it in`:`import · outbound`:e.direction===`inbound`?t===`easy`?`calls this`:`call · inbound`:t===`easy`?`this calls it`:`call · outbound`}function gY(e,t){return e.certain?`certain`:e.relationship===`import`?t===`easy`?`possible link, not certain`:`possible import`:t===`easy`?`possible link, not certain`:`possible call`}function _Y(e){let t=String(e??``);return t.length<=18?t:`…${t.slice(-17)}`}function vY({inbound:e,outbound:t,node:n}){let r=e.slice(0,fY),i=t.slice(0,fY),a=Math.max(r.length,i.length,1)*22+16,o=a/2,s=(e,t)=>(e+1)*a/(t+1);return(0,$.jsxs)(`svg`,{className:`mini-constellation`,viewBox:`0 0 280 ${a}`,role:`img`,"aria-label":`${e.length} inbound and ${t.length} outbound parser relationships for ${n.name}`,children:[r.map((e,t)=>(0,$.jsx)(`line`,{x1:`26`,y1:s(t,r.length),x2:`132`,y2:o,strokeDasharray:e.certain?void 0:`3 3`},`in-line-${e.node_id}`)),r.map((e,t)=>(0,$.jsx)(`text`,{className:`mini-constellation__name`,x:`8`,y:s(t,r.length)-7,textAnchor:`start`,children:_Y(e.name)},`in-name-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`text`,{className:`mini-constellation__name`,x:`272`,y:s(t,i.length)-7,textAnchor:`end`,children:_Y(e.name)},`out-name-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`line`,{x1:`148`,y1:o,x2:`254`,y2:s(t,i.length),strokeDasharray:e.certain?void 0:`3 3`},`out-line-${e.node_id}`)),r.map((e,t)=>(0,$.jsx)(`circle`,{cx:`22`,cy:s(t,r.length),r:`4`},`in-dot-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`circle`,{cx:`258`,cy:s(t,i.length),r:`4`},`out-dot-${e.node_id}`)),(0,$.jsx)(`circle`,{className:`mini-constellation__self`,cx:`140`,cy:o,r:`6`})]})}function yY({lens:e,language:t,mode:n}){return e?.length?(0,$.jsxs)(`section`,{className:`lens-study`,"aria-labelledby":`lens-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsxs)(`h2`,{id:`lens-heading`,children:[IG(t),` lens`]}),(0,$.jsxs)(`span`,{children:[e.length,` detected`]})]}),(0,$.jsx)(`div`,{className:`lens-notes`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`lens-note`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h3`,{children:e.title}),(0,$.jsx)(wY,{citation:e.citation,fallbackLine:e.line})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:e.note_voices[n]}),(0,$.jsx)(`code`,{children:e.snippet})]})]},`${e.concept}-${e.line}-${e.snippet}`))})]}):null}function bY({source:e,anchorRef:t,headingRef:n}){return(0,$.jsxs)(`section`,{className:`source-study`,"aria-labelledby":`source-heading`,ref:t,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{ref:n,id:`source-heading`,tabIndex:-1,children:`Real source`}),(0,$.jsxs)(`span`,{title:`${e.file}:${e.start_line}–${e.end_line}`,children:[e.file,`:`,e.start_line,`–`,e.end_line]})]}),(0,$.jsx)(`ol`,{className:`source-code`,start:e.start_line,"aria-label":`Source excerpt from ${e.file}`,children:e.lines.map(e=>(0,$.jsx)(`li`,{id:`source-L${e.number}`,"data-line":e.number,children:(0,$.jsx)(`code`,{children:e.text||` `})},e.number))})]})}var xY={grounding:`The explanation was withheld.`,unavailable:`Codemble could not reach the model.`,rejected:`The model refused the request.`,timeout:`The model is taking longer than expected.`,provider:`The model's reply could not be read.`};function SY({explanation:e,loading:t,error:n,llmStatus:r,mode:i,node:a,onSelectNode:o,onRetry:s}){if(t)return(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:i===`easy`?`Asking your model to explain this in plain language…`:`Requesting a grounded narration for this structure…`});if(n)return(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`The explanation request failed.`}),(0,$.jsx)(`p`,{children:n}),(0,$.jsx)(`p`,{children:`Every fact above and below this block came from the parser and is unaffected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]});if(!e)return null;if(e.status===`no_key`)return(0,$.jsx)(CY,{message:e.message,llmStatus:r,mode:i});if(e.status===`error`||e.status===`timeout`){let t=e.reason===`grounding`;return(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:xY[e.reason]??xY.provider}),(0,$.jsx)(`p`,{children:e.message}),t?(0,$.jsx)(`p`,{children:`Codemble will not display provider output that falls outside parser evidence.`}):null,(0,$.jsx)(`p`,{children:`Every fact from the parser on this panel is unaffected.`}),e.retryable===!1?null:(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]})}return e.status===`partial`?(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`Narration stays off for partial source.`}),(0,$.jsx)(`p`,{children:e.message})]}):(0,$.jsxs)(`section`,{className:`grounded-explanation`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,role:`status`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:i===`easy`?`In plain language`:`Grounded explanation`}),(0,$.jsx)(`span`,{children:e.cached?`Local cache`:e.provider})]}),(0,$.jsxs)(`p`,{children:[e.summary.text,` `,(0,$.jsx)(wY,{citation:e.summary.citation,fallbackLine:a.lineno})]}),e.excerpt?.truncated?(0,$.jsx)(`p`,{className:`study-loading`,children:i===`easy`?`This file is long, so the model was shown lines ${e.excerpt.first}–${e.excerpt.last} of ${e.excerpt.total}.`:`Narrated from an excerpt: lines ${e.excerpt.first}–${e.excerpt.last} of ${e.excerpt.total}.`}):null,e.withheld>0?(0,$.jsxs)(`p`,{className:`study-loading`,children:[e.withheld,` `,e.withheld===1?`part`:`parts`,` of the reply `,e.withheld===1?`was`:`were`,` malformed and left out.`]}):null,e.walkthrough.length?(0,$.jsxs)(`details`,{className:`walkthrough-disclosure`,children:[(0,$.jsx)(`summary`,{children:i===`easy`?`Walk me through it line by line (${e.walkthrough.length})`:`Line walkthrough (${e.walkthrough.length})`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.walkthrough.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`p`,{children:e.text}),(0,$.jsx)(wY,{citation:e.citation,fallbackLine:e.line})]},`${e.citation}-${e.text}`))})]}):null,e.relationships.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:i===`easy`?`How it fits in`:`Parser relationships`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.relationships.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`strong`,{children:e.certain?e.node_id:`Possible: ${e.node_id}`}),(0,$.jsx)(`p`,{children:e.text}),(0,$.jsxs)(`button`,{className:`source-citation source-citation--button`,type:`button`,onClick:()=>o(e.node_id),children:[`Study `,e.citation]})]},`${e.node_id}-${e.text}`))})]}):null]})}function CY({message:e,llmStatus:t,mode:n}){let r=t?.ollama??null;return(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:n===`easy`?`The plain-language write-up needs a model.`:`No narration provider is configured.`}),(0,$.jsx)(`p`,{children:e}),r?(0,$.jsx)(`p`,{children:r.running?`Ollama is already running on this machine. Set CODEMBLE_PROVIDER=ollama and CODEMBLE_OLLAMA_MODEL=${r.recommended}, then restart Codemble to narrate without sending code anywhere.`:`Want to stay fully local? Install Ollama, run "ollama pull ${r.recommended}" (or ${r.fallback} on a smaller machine), set CODEMBLE_PROVIDER=ollama, then restart Codemble.`}):null,(0,$.jsx)(`p`,{children:`Everything else on this panel is parser evidence and works without any model at all.`})]})}function wY({citation:e,fallbackLine:t}){return(0,$.jsx)(`a`,{className:`source-citation`,href:`#source-L${Number(e.split(`:`).at(-1))||t}`,children:e})}var TY=Object.freeze([]),EY=new Set;function DY(){let e=new WeakMap,t=new WeakMap,n=new WeakMap,r=new WeakMap,i=new WeakMap,a=new WeakMap,o=null,s=null,c=null,l=null;function u(e){let t=e.graph,n=t?d(t,e.languageFocus):null,r=n?p(n):null,i=e.level,a=r?.regionById.get(e.region?.id)??null,o=e.selectedNode;n&&(a?o&&(o=r.nodeById.get(o.id)??null,!o&&i===jG.STUDY&&(i=jG.SYSTEM)):(a=mK(n),o=null,i=jG.GALAXY));let s=e.studiedNodeIds;return{...e,focusedGraph:n,focusedMapData:f(e.mapData,e.languageFocus),entrypointOpen:!!t&&!e.entrypointDismissed,level:i,region:a,selectedNode:o,languageOptions:t?m(t):TY,projectName:t?g(t):`Loading local project`,chart:n?_(n,s):TY,focusedStudiedCount:n?v(n,s):0,hint:n?y(n,e.mode,i,a?.id??null,e.layer,t,e.languageFocus):null,revealedRegionIds:n?b(n,e.showAll,a?.id??null,e.visitedRegionIds):EY,moduleIndex:n?h(n):TY}}function d(t,n){let r=e.get(t);r||(r=new Map,e.set(t,r));let i=n||`all`;return r.has(i)||r.set(i,MG(t,n)),r.get(i)}function f(e,n){if(!e)return e;let r=t.get(e);r||(r=new Map,t.set(e,r));let i=n||`all`;return r.has(i)||r.set(i,NG(e,n)),r.get(i)}function p(e){return n.has(e)||n.set(e,{nodeById:new Map(e.nodes.map(e=>[e.id,e])),regionById:new Map(e.regions.map(e=>[e.id,e]))}),n.get(e)}function m(e){return r.has(e)||r.set(e,PG(e)),r.get(e)}function h(e){return i.has(e)||i.set(e,qG(e)),i.get(e)}function g(e){return a.has(e)||a.set(e,hK(e)),a.get(e)}function _(e,t){return(!o||o.graph!==e||o.studiedNodeIds!==t)&&(o={graph:e,studiedNodeIds:t,value:FG(e,t)}),o.value}function v(e,t){return(!s||s.graph!==e||s.studiedNodeIds!==t)&&(s={graph:e,studiedNodeIds:t,value:e.nodes.filter(e=>t.has(e.id)).length}),s.value}function y(e,t,n,r,i,a,o){return(!c||c.graph!==e||c.mode!==t||c.level!==n||c.regionId!==r||c.layer!==i||c.projectGraph!==a||c.languageFocus!==o)&&(c={graph:e,mode:t,level:n,regionId:r,layer:i,projectGraph:a,languageFocus:o,value:AY(e,{mode:t,level:n,regionId:r,layer:i,projectGraph:a,languageFocus:o})}),c.value}function b(e,t,n,r){return(!l||l.graph!==e||l.showAll!==t||l.selectionId!==n||l.visitedIds!==r)&&(l={graph:e,showAll:t,selectionId:n,visitedIds:r,value:HG(e,{showAll:t,selectionId:n,visitedIds:r})}),l.value}return Object.freeze({derive:u})}var OY=1.5;function kY({homeChosen:e,homeOutsideFocus:t,languageFocus:n,hops:r}){return e?t?`Home is not written in ${LG(n)}.`:r===0?`Home is not lit yet.`:Number.isFinite(r)?`${r} ${r===1?`route`:`routes`} from Home.`:`No import route reaches it from Home.`:`No Home is chosen, so there is no route to measure from.`}function AY(e,{mode:t,level:n,regionId:r,layer:i,projectGraph:a,languageFocus:o}){if(t!==`easy`)return null;let s=e.regions.filter(e=>!e.understood);if(!s.length)return null;let c=(a??e).regions.some(e=>e.home),l=c&&!e.regions.some(e=>e.home),u=GG(e),d=s.map(e=>{let t=typeof e.hops_from_home==`number`?e.hops_from_home:1/0;return{regionId:e.id,hops:t,biasedHops:ZG(u.get(e.id)??``)?t+OY:t,structures:typeof e.node_count==`number`?e.node_count:0}}).sort((e,t)=>e.biasedHops-t.biasedHops||t.structures-e.structures||e.regionId.localeCompare(t.regionId))[0],{biasedHops:f,...p}=d,m={...p,message:`Study ${d.regionId} next`,reason:kY({homeChosen:c,homeOutsideFocus:l,languageFocus:o,hops:d.hops})};return n===jG.STUDY?r===d.regionId?{...m,message:`Prove you understand ${d.regionId}`,reason:`Questions come from this file, not from a model.`,action:{type:`OPEN_CHECKS`},actionLabel:`Prove understanding`}:{...m,action:{type:`OPEN_REGION`,regionId:d.regionId},actionLabel:`Open ${d.regionId}`}:n!==jG.SYSTEM||r!==d.regionId?{...m,action:{type:`OPEN_REGION`,regionId:d.regionId},actionLabel:`Open ${d.regionId}`}:i===`map`?e.nodes.some(e=>e.id===d.regionId)?{...m,reason:`Read it before proving it.`,action:null,actionLabel:null}:{...m,reason:`Its parser-proven structures are visible in Galaxy.`,action:{type:`SET_LAYER`,layer:`galaxy`},actionLabel:`View structures`}:{...m,reason:`Choose one of its parser-proven structures.`,action:null,actionLabel:null}}var jY=`Codemble's local server is not responding. Your source files and saved progress are unchanged. Start Codemble again, then try again.`;function MY(e){return Number.isInteger(e?.status)?NY(e):jY}function NY(e){return e instanceof Error?e.message:String(e)}var PY=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}}),FY=300,IY=400,LY=4e3,RY=8,zY=Object.freeze([Object.freeze({id:`discovering`,copy:`Finding your source files`}),Object.freeze({id:`parsing`,copy:`Reading each file`}),Object.freeze({id:`resolving`,copy:`Connecting imports and calls`}),Object.freeze({id:`checks`,copy:`Building graph-only checks`}),Object.freeze({id:`layout`,copy:`Placing your galaxy`})]);function BY({adapter:e,clock:t=PY,onReady:n=async()=>{}}={}){if(!e)throw TypeError(`Project mapping requires a learner adapter.`);let r=new Set,i=VY({phase:`idle`,error:``,picker:null,progress:null,failure:null}),a=0,o=null,s=null,c=null,l=null;function u(){return i}function d(e){return r.add(e),()=>r.delete(e)}function f(e){i=VY({...i,...e});for(let e of r)e()}async function p(){a+=1;let t=a;b(),HY(o),o=new AbortController;let n=o;f({phase:`idle`,error:``,picker:null,progress:null,failure:null});try{let[r,o]=await Promise.all([e.loadRecents({signal:n.signal}),e.browsePicker(null,{signal:n.signal})]);if(t!==a||n.signal.aborted)return i;f({phase:`picking`,picker:{...o,recents:r.recents,error:``,retryPath:null,scale:null,busy:!1}})}catch(e){!UY(e)&&t===a&&f({phase:`error`,error:MY(e)})}return i}async function m(t){if(i.phase!==`picking`||i.picker?.busy)return;HY(o),o=new AbortController;let n=o,r=a;f({failure:null});try{let s=await e.browsePicker(t,{signal:n.signal});o===n&&r===a&&!n.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...s,error:``,retryPath:null,scale:null}})}catch(e){o===n&&r===a&&!UY(e)&&i.phase===`picking`&&f({picker:{...i.picker,error:MY(e),retryPath:t}})}}async function h(t){if(i.phase!==`picking`||i.picker?.busy)return;a+=1;let r=a;HY(o),b(),o=new AbortController;let s=o;f({failure:null,picker:{...i.picker,busy:!0,error:``,retryPath:null,scale:null}});try{let o=await e.selectProject(t,{signal:s.signal});if(r!==a||s.signal.aborted||i.phase!==`picking`)return o;if(o.state===`parsing`)return f({progress:{state:`parsing`,stage:`discovering`,detail:null,files_done:0,files_total:0,error:null,pollError:``,attempts:0,pollOutage:!1,path:t}}),_(0,r),o;if(o.state===`ready`)return y(),await n(),o;if(o.state===`scale`){let t=await e.browsePicker(o.root,{signal:s.signal});return r===a&&!s.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...t,busy:!1,scale:o}}),o}let c=o.detail??``;return f({picker:{...i.picker,busy:!1,error:c},failure:c?{path:t,detail:c}:null}),o}catch(e){if(r===a&&!UY(e)&&i.phase===`picking`){let n=GY(e);f({picker:{...i.picker,busy:!1,error:n},failure:{path:t,detail:n}})}return}}async function g(){HY(c),c=new AbortController;let t=c;try{await e.resetProject({signal:t.signal})}catch(e){if(UY(e))return!1;if(WY(e))throw e}return t.signal.aborted?!1:(a+=1,HY(o),o=null,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null}),!0)}function _(e,n){l!==null&&t.clearTimeout(l),l=t.setTimeout(async()=>{l=null,await v(n)},e)}async function v(t){if(!i.progress||t!==a)return;HY(s),s=new AbortController;let r=s,o=i.progress,c;try{c=await e.fetchParseProgress({signal:r.signal})}catch(e){if(s!==r||t!==a||UY(e)||!i.progress)return;let n=o.attempts+1;f({progress:{...o,pollError:GY(e),attempts:n,pollOutage:n>=RY}}),_(Math.min(LY,IY*2**(n-1)),t);return}if(!(s!==r||t!==a||!i.progress)){if(c.state===`ready`){y(),await n();return}if(c.state===`error`||c.state===`idle`){b();let e=c.error??``;f({progress:null,picker:{...i.picker,busy:!1,error:e},failure:e?{path:o.path,detail:e}:null});return}f({progress:{...o,...c,pollError:``,attempts:0,pollOutage:!1}}),_(FY,t)}}function y(){a+=1,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null})}function b(){HY(s),s=null,l!==null&&(t.clearTimeout(l),l=null)}function x(){a+=1;for(let e of[o,s,c])HY(e);o=null,c=null,b(),r.clear()}return Object.freeze({browse:m,dispose:x,getSnapshot:u,reset:g,select:h,start:p,subscribe:d})}function VY(e){return Object.freeze(e)}function HY(e){e&&!e.signal.aborted&&e.abort()}function UY(e){return e?.name===`AbortError`}function WY(e){return Number.isInteger(e?.status)}function GY(e){return e instanceof Error?e.message:String(e)}var KY=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}});function qY({adapter:e=XY(),clock:t=KY}={}){let n=new Set,r=DY(),i=r.derive({status:`idle`,error:``,graph:null,level:jG.GALAXY,region:null,selectedNode:null,studyData:null,studyError:``,explanation:null,explanationLoading:!1,explanationError:``,showChart:!1,studiedNodeIds:new Set,visitedRegionIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,picker:null,parseProgress:null,projectFailure:null,layer:`galaxy`,layerChosen:!1,mapTab:`architecture`,mapData:null,mapError:``,coachmarksSeen:$Y(),llmStatus:null,hoverNodeId:null,showAll:nX(),finderOpen:!1,sidebarOpen:!1,legendOpen:!1,mode:`easy`,modeChosen:null}),a=0,o=0,s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,h=null;function g(){return i}function _(e){return n.add(e),()=>n.delete(e)}function v(e,{preserveChecks:t=!1}={}){let a=i,o=r.derive({...a,...e});if(o.level!==a.level||o.region?.id!==a.region?.id){let e={hoverNodeId:null};t||(iX(u),iX(d),u=null,d=null,e.showChecks=!1,e.checkData=null,e.checkError=``),o=r.derive({...o,...e})}i=Object.freeze(o);for(let e of n)e()}let y=BY({adapter:e,clock:t,async onReady(){a+=1;let e=a;return iX(s),s=new AbortController,S(s,e)}}),b=y.subscribe(()=>{let e=y.getSnapshot(),t={picker:e.picker,parseProgress:e.progress,projectFailure:e.failure};e.phase===`picking`&&(t.status=`picking`),e.phase===`error`&&(t.status=`error`,t.error=e.error),v(t)});async function x(){a+=1;let t=a;iX(s),s=new AbortController;let n=s;v({status:`loading`,error:``});let r;try{r=await e.loadPickerState({signal:n.signal})}catch(e){return!aX(e)&&t===a&&v({status:`error`,error:MY(e)}),i}return t!==a||n.signal.aborted?i:r.state===`unpicked`?(await y.start(),i):S(n,t)}async function S(t,n){v({status:`loading`,error:``,picker:null});try{let r=await e.loadGraph({signal:t.signal});if(n!==a||t.signal.aborted)return i;v({status:`ready`,graph:r,region:mK(r),error:``,entrypointDismissed:!!r.selected_entrypoint})}catch(e){!aX(e)&&n===a&&v({status:`error`,error:MY(e)})}return await C(t,n),i}async function C(t,n){let r=o,[s,c,l]=await Promise.allSettled([(async()=>e.loadMode({signal:t.signal}))(),(async()=>e.fetchLlmStatus({signal:t.signal}))(),(async()=>e.fetchVisited?.({signal:t.signal}))()]);if(!(n!==a||t.signal.aborted)){if(l.status===`fulfilled`&&Array.isArray(l.value?.visited)&&v({visitedRegionIds:new Set(l.value.visited)}),r===o){let e=s.status===`fulfilled`?s.value:null;e?.mode===`easy`||e?.mode===`expert`?ne(e.mode,e.chosen===!0):i.modeChosen===null&&v({modeChosen:!0})}c.status===`fulfilled`&&v({llmStatus:c.value})}}async function w(){let t=a;if(await e.clearProgress({}),v({visitedRegionIds:new Set}),t!==a)return i;a+=1;let n=a;iX(s),s=new AbortController,iX(p),p=null,v({mapData:null,mapError:``});let r=await S(s,n);return n===a&&i.layer===`map`&&await le(),r}async function T(){return await y.reset()?(N(),iX(f),f=null,iX(p),p=null,iX(m),m=null,v({graph:null,parseProgress:null,projectFailure:null,region:null,selectedNode:null,level:jG.GALAXY,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1,showChart:!1,studiedNodeIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,llmStatus:null,picker:null,mapData:null,mapError:``}),x()):i}async function E(e){switch(e.type){case`ADVANCE`:return A(e.node);case`ADVANCE_REGION`:k(e.regionId);return;case`FOLLOW_HINT`:return D();case`RETREAT`:ee();return;case`SELECT_STUDY_NODE`:return te(e.nodeId);case`SET_LANGUAGE_FOCUS`:j(e.language);return;case`SET_MODE`:return re(e.mode);case`HOVER_NODE`:i.hoverNodeId!==(e.nodeId??null)&&v({hoverNodeId:e.nodeId??null});return;case`SHOW_CHART`:v({showChart:!0});return;case`HIDE_CHART`:v({showChart:!1});return;case`OPEN_CHECKS`:return ae();case`CLOSE_CHECKS`:P();return;case`SUBMIT_CHECK`:return se(e.checkId,e.selectedIds);case`CONSUME_DAWN`:fe(e.regionId);return;case`SELECT_ENTRYPOINT`:return F(e.nodeId);case`DISMISS_ENTRYPOINT`:v({entrypointDismissed:!0});return;case`CHANGE_HOME`:N(),v({entrypointDismissed:!1,entrypointError:``,level:jG.GALAXY,selectedNode:null,showChart:!1,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1});return;case`BROWSE_PICKER`:return y.browse(e.path);case`SELECT_PROJECT`:return y.select(e.path);case`RESET_PROJECT`:return T();case`CLEAR_PROGRESS`:return w();case`SET_LAYER`:return ce(e.layer);case`SET_MAP_TAB`:v({mapTab:e.tab});return;case`DISMISS_COACHMARKS`:eX(),v({coachmarksSeen:!0});return;case`SET_LEVEL_GALAXY`:N(),v({level:jG.GALAXY,selectedNode:null});return;case`TOGGLE_SHOW_ALL`:rX(!i.showAll),v({showAll:!i.showAll});return;case`SET_FINDER_OPEN`:v({finderOpen:e.open});return;case`TOGGLE_SIDEBAR`:v({sidebarOpen:!i.sidebarOpen});return;case`TOGGLE_LEGEND`:v({legendOpen:!i.legendOpen});return;case`GO_TO_REGION`:return v({finderOpen:!1}),k(e.regionId);default:throw Error(`Unknown learner-session event: ${e.type}`)}}function D(){let e=i.hint?.action;if(e){if(e.type===`OPEN_REGION`){k(e.regionId);return}if(e.type===`SET_LAYER`)return ce(e.layer);if(e.type===`OPEN_STUDY`)return te(e.nodeId);if(e.type===`OPEN_CHECKS`)return i.level===jG.STUDY&&ee(),ae()}}function O(t){!t||i.visitedRegionIds.has(t)||(v({visitedRegionIds:new Set(i.visitedRegionIds).add(t)}),Promise.resolve(e.markVisited?.(t)).catch(()=>{}))}function k(e){let t=i.graph?.regions.find(t=>t.id===e);t&&(N(),O(t.id),v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:t,selectedNode:null,level:jG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}async function A(e){if(!(!i.focusedGraph||!e)){if(i.level===jG.GALAXY){let t=i.focusedGraph.regions.find(t=>t.id===e.id)??e;N(),O(t.id),v({region:t,selectedNode:null,level:jG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1});return}if(i.level===jG.SYSTEM){let t=i.focusedGraph.nodes.find(t=>t.id===e.id)??e;return v({selectedNode:t,level:jG.STUDY}),M(t.id)}if(i.level===jG.STUDY){let t=i.focusedGraph.nodes.find(t=>t.id===e.id);return!t||t.id===i.selectedNode?.id?void 0:(v({selectedNode:t}),M(t.id))}}}function ee(){i.level===jG.STUDY?(N(),v({selectedNode:null,level:jG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1})):i.level===jG.SYSTEM&&v({level:jG.GALAXY})}async function te(e){let t=i.graph?.nodes.find(t=>t.id===e);if(!t)return;let n=i.graph.regions.find(e=>e.id===t.region);return n&&O(n.id),v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:n??i.region,selectedNode:t,level:jG.STUDY}),M(t.id)}function j(e){let t=i.selectedNode?.id;v({languageFocus:e}),t&&i.selectedNode?.id!==t&&(N(),v({studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}function ne(e,t){let n=i.layerChosen?i.layer:e===`easy`?`map`:`galaxy`;v({mode:e,layer:n,modeChosen:t}),n===`map`&&le()}async function re(t){if(t!==`easy`&&t!==`expert`)return;let n=i.mode,r=i.modeChosen;if(t===n&&i.modeChosen)return;o+=1,iX(m),m=new AbortController;let s=m,c=a;ne(t,!0);try{await e.saveMode(t,{signal:s.signal})}catch(e){m===s&&c===a&&!aX(e)&&ne(n,r);return}if(!(c!==a||s.signal.aborted)&&i.level===jG.STUDY&&i.selectedNode)return ie(i.selectedNode.id)}async function M(t){N(),c=new AbortController;let n=c;v({studyData:null,studyError:``}),ie(t);try{let r=await e.loadStudy(t,{signal:n.signal});if(n.signal.aborted||i.level!==jG.STUDY||i.selectedNode?.id!==t)return;v({studyData:r,studiedNodeIds:new Set(i.studiedNodeIds).add(r.node.id)})}catch(e){c===n&&!n.signal.aborted&&!aX(e)&&i.selectedNode?.id===t&&v({studyError:oX(e)})}}function N(){iX(c),c=null,iX(l),l=null}async function ie(t){iX(l),l=new AbortController;let n=l;v({explanation:null,explanationError:``,explanationLoading:!0});try{let r=await e.loadExplanation(t,i.mode,{signal:n.signal});if(n.signal.aborted||i.level!==jG.STUDY||i.selectedNode?.id!==t)return;v({explanation:r,explanationLoading:!1})}catch(e){l===n&&!n.signal.aborted&&!aX(e)&&i.selectedNode?.id===t&&v({explanationError:oX(e),explanationLoading:!1})}}async function ae(){if(!i.region)return;let e=i.region.id;return v({showChecks:!0,checkData:null,checkError:``}),oe(e)}async function oe(t){iX(u),u=new AbortController;let n=u;try{let r=await e.loadChecks(t,{signal:n.signal});return!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkData:r,checkError:``},{preserveChecks:!0}),r}catch(e){u===n&&!aX(e)&&!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkError:oX(e)},{preserveChecks:!0});return}}function P(){iX(u),u=null,v({showChecks:!1,checkData:null,checkError:``})}async function se(t,n){if(!i.region)return;let r=i.region.id;iX(d),d=new AbortController;let a=d,o=await e.submitCheck(r,t,n,{signal:a.signal});if(a.signal.aborted||i.region?.id!==r)return o;if(o.correct&&await oe(r),o.region_understood){let t=await e.loadGraph({signal:a.signal});!a.signal.aborted&&i.region?.id===r&&(iX(p),p=null,v({graph:t,region:t.regions.find(e=>e.id===r),mapData:null,mapError:``},{preserveChecks:!0}),de(r),i.layer===`map`&&await le())}return o}async function F(t){let n=a;iX(f),f=new AbortController;let r=f;v({entrypointError:``});try{let o=await e.selectEntrypoint(t,{signal:r.signal});return n!==a||r.signal.aborted?i:(iX(p),p=null,v({graph:o,region:mK(o),entrypointError:``,entrypointDismissed:!0,mapData:null,mapError:``}),i.layer===`map`&&await le(),o)}catch(e){f===r&&n===a&&!r.signal.aborted&&!aX(e)&&v({entrypointError:oX(e)});return}}async function ce(e){if(v({layer:e,layerChosen:!0}),e===`map`)return le()}function le(){if(!i.mapData)return p&&!p.signal.aborted&&!i.mapError?void 0:ue()}async function ue(){let t=a;iX(p),p=new AbortController;let n=p;v({mapError:``});try{let r=await e.fetchMap({signal:n.signal});return t===a&&!n.signal.aborted&&v({mapData:r,mapError:``}),r}catch(e){p===n&&t===a&&!n.signal.aborted&&!aX(e)&&v({mapError:oX(e),mapData:null});return}}function de(e){h!==null&&t.clearTimeout(h),v({litRegionId:e,pendingDawnRegionId:e}),h=t.setTimeout(()=>{h=null,i.litRegionId===e&&v({litRegionId:null})},520)}function fe(e){i.pendingDawnRegionId===e&&v({pendingDawnRegionId:null})}function pe(){a+=1;for(let e of[s,c,l,u,d,f,p,m])iX(e);s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,b(),y.dispose(),h!==null&&(t.clearTimeout(h),h=null)}return Object.freeze({dispatch:E,dispose:pe,getSnapshot:g,start:x,subscribe:_})}var JY=6e4;function YY(e,t){if(typeof AbortSignal?.timeout!=`function`||typeof AbortSignal?.any!=`function`)return e;let n=AbortSignal.timeout(t);return{...e,signal:e.signal?AbortSignal.any([e.signal,n]):n}}function XY(e=globalThis.fetch){if(typeof e!=`function`)throw TypeError(`Learner-session HTTP adapter requires fetch.`);async function t(t,n,r={}){let i;try{i=await e(t,r)}catch(e){throw e instanceof Error&&e.name===`TimeoutError`?Error(`${n} timed out. Codemble is still running — try again.`):e}if(!i.ok){let e=(await i.json().catch(()=>null))?.detail,t=Error(typeof e==`string`&&e?e:`${n} returned ${i.status}.`);throw t.status=i.status,t}return i.json()}return Object.freeze({loadGraph(e={}){return t(`/api/graph`,`Graph request`,e)},fetchMap(e={}){return t(`/api/map`,`Map request`,e)},loadStudy(e,n={}){return t(`/api/node/${encodeURIComponent(e)}/study`,`Study request`,n)},loadExplanation(e,n,r={}){return t(`/api/node/${encodeURIComponent(e)}/explanation?mode=${encodeURIComponent(n)}`,`Explanation request`,YY(r,JY))},loadChecks(e,n={}){return t(`/api/regions/${encodeURIComponent(e)}/checks`,`Checks request`,n)},submitCheck(e,n,r,i={}){return t(`/api/regions/${encodeURIComponent(e)}/checks/${encodeURIComponent(n)}`,`Check submission`,{...i,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selected_ids:r})})},selectEntrypoint(e,n={}){return t(`/api/entrypoint`,`Home selection`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({node_id:e})})},loadMode(e={}){return t(`/api/mode`,`Mode request`,e)},saveMode(e,n={}){return t(`/api/mode`,`Mode update`,{...n,method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({mode:e})})},fetchLlmStatus(e={}){return t(`/api/llm/status`,`Model status`,e)},resetProject(e={}){return t(`/api/picker/reset`,`Project reset`,{...e,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirmed:!0})})},loadPickerState(e={}){return t(`/api/picker/state`,`Picker state`,e)},browsePicker(e,n={}){return t(`/api/picker/browse${e?`?path=${encodeURIComponent(e)}`:``}`,`Folder listing`,n)},loadRecents(e={}){return t(`/api/picker/recents`,`Recent projects`,e)},fetchParseProgress(e={}){return t(`/api/picker/progress`,`Parse progress`,e)},clearProgress(e={}){return t(`/api/progress`,`Progress reset`,{...e,method:`DELETE`})},fetchVisited(e={}){return t(`/api/progress/visited`,`Explored regions`,e)},markVisited(e,n={}){return t(`/api/progress/visited`,`Explored regions`,{...n,method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({region_id:e})})},async selectProject(t,n={}){let r=await e(`/api/picker/select`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t})}),i=await r.json().catch(()=>null);if(r.ok)return{state:r.status===202?`parsing`:`ready`};let a=i?.detail;return a&&typeof a==`object`&&a.reason===`scale`?{state:`scale`,...a}:{state:`error`,detail:typeof a==`string`?a:`Project selection returned ${r.status}.`}}})}var ZY=`codemble.coachmarks.seen`;function QY(){if(typeof document>`u`)return null;try{return globalThis.localStorage??null}catch{return null}}function $Y(){try{return QY()?.getItem(ZY)===`1`}catch{return!1}}function eX(){try{QY()?.setItem(ZY,`1`)}catch{}}var tX=`codemble.galaxy.showAll`;function nX(){try{return QY()?.getItem(tX)===`1`}catch{return!1}}function rX(e){try{let t=QY();e?t?.setItem(tX,`1`):t?.removeItem(tX)}catch{}}function iX(e){e&&!e.signal.aborted&&e.abort()}function aX(e){return e instanceof Error&&e.name===`AbortError`}function oX(e){return e instanceof Error?e.message:String(e)}var sX=Object.freeze([{id:`editableField`,open:e=>e.editableFocus===!0,dismissible:!1},{id:`nativeDialog`,open:e=>e.nativeDialogOpen===!0,dismissible:!1},{id:`railDisclosure`,open:e=>e.railDisclosureOpen===!0,dismissible:!0},{id:`checks`,open:e=>e.showChecks===!0,dismissible:!0},{id:`sidebar`,open:e=>e.sidebarOpen===!0,dismissible:!0},{id:`finder`,open:e=>e.finderOpen===!0,dismissible:!1},{id:`entrypoint`,open:e=>e.entrypointOpen===!0,dismissible:!1},{id:`chart`,open:e=>e.showChart===!0,dismissible:!0},{id:`firstFlight`,open:e=>e.firstFlightOpen===!0,dismissible:!0}]);function cX(e){let t=sX.find(t=>t.open(e??{}));return t?{id:t.id,dismissible:t.dismissible}:null}function lX(e={}){if(e.ready!==!0)return null;let t=cX(e);return t?t.dismissible?{kind:`dismiss`,surface:t.id}:null:e.canRetreat?{kind:`retreat`}:null}function uX(e){return String(e??``).replace(/[\\`*_[\]<>#|]/g,`\\$&`)}function dX(e,t,n=`${t}s`){return`${e} ${e===1?t:n}`}function fX(e){return`${String(e?.projectName??`local-project`).normalize(`NFKD`).toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`local-project`}-codemble-brief.md`}function pX(e,{charted:t=0}={}){let n=e?.languages??[],r=e?.busiest??[],i=e?.unsupportedSources??[],a=e?.relationships??{proven:0,hedged:0},o=e?.importCycles??[],s=e?.modules??0,c=e?.structures??0,l=e?.understood??0;return[`# ${uX(e?.projectName??`Local project`)} — Codemble project brief`,``,`> Generated locally from Codemble's parser graph. It contains no AI-generated narration.`,``,`## Project shape`,``,`- ${dX(s,`file`)} containing ${dX(c,`structure`)}.`,`- ${e?.lines??0} lines across parser-supported source files.`,``,`### Languages`,``,`| Language | Files | Structures |`,`| --- | ---: | ---: |`,...n.length?n.map(e=>`| ${uX(e.label)} | ${e.count} | ${e.structures} |`):[`| None reported | 0 | 0 |`],``,`## Home`,``,e?.home?`- Codemble resolved Home as ${uX(e.home.id)} (${uX(e.home.language)}).`:`- No Home entrypoint was resolved; this brief does not invent one.`,``,`## Called from the most places`,``,...r.length?r.map(e=>`- ${uX(e.id)} — called from ${dX(e.value,`place`)}.`):[`- No module has a reported caller count.`],``,`## Proven import cycles`,``,...o.length?o.map(e=>`- Strongly connected group: ${e.map(uX).join(`, `)}. Each file can reach every other through proven imports.`):[`- None reported.`],``,`## Parser evidence`,``,`- Proven relationships: ${a.proven}.`,`- Hedged relationships: ${a.hedged}. Hedged relationships are possible parser matches, not proven links.`,`- Files Codemble could not read: ${e?.unreadable??0}.`,...i.length?[`- Unsupported source files:`,...i.map(e=>` - ${uX(e.extension||`unknown extension`)} (${uX(e.language||`unknown language`)}): ${e.count}`)]:[`- Unsupported source files: 0.`],``,`## Learning progress`,``,`- Charted systems: ${t} of ${s}. Charted means visited, not understood.`,`- Understood systems: ${l} of ${s}. Understood means a graph-derived check passed.`,``].join(`
+`)}function mX(){let e=(0,_.useRef)(null),t=(0,_.useRef)(null),n=(0,_.useRef)(null),r=(0,_.useRef)(null),i=(0,_.useRef)(!1),a=(0,_.useRef)(null),o=(0,_.useRef)(null),s=(0,_.useRef)(null),c=(0,_.useRef)(!1),l=(0,_.useRef)(null),u=(0,_.useRef)(null),[d,f]=(0,_.useState)(!1),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(null),v=(0,_.useMemo)(()=>RJ(),[]),y=(0,_.useMemo)(()=>qY({adapter:XY()}),[]),b=(0,_.useSyncExternalStore)(y.subscribe,y.getSnapshot,y.getSnapshot);(0,_.useEffect)(()=>(y.start(),()=>y.dispose()),[y]),(0,_.useEffect)(()=>{b.status!==`ready`&&(f(!1),g(null),v.clear())},[v,b.status]),(0,_.useEffect)(()=>{let e=window.matchMedia(`(min-width: 40rem)`),t=e=>{e.matches&&f(!1)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]),(0,_.useEffect)(()=>{function e(e){(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),r.current=document.activeElement===document.body?null:document.activeElement,y.dispatch({type:`SET_FINDER_OPEN`,open:!0}))}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[y]);let x={railDisclosure:()=>{f(!1),Pe(e)},checks:()=>Ie(),sidebar:()=>L(),chart:()=>{y.dispatch({type:`HIDE_CHART`}),Pe(a)},firstFlight:()=>He()};(0,_.useEffect)(()=>{function e(e){if(e.key!==`Escape`)return;let t=lX(_X(y.getSnapshot(),{firstFlightOpen:c.current}));if(t){if(e.preventDefault(),t.kind===`dismiss`){x[t.surface]();return}y.dispatch({type:`RETREAT`})}}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[y]);let{chart:S,checkData:C,checkError:w,coachmarksSeen:T,entrypointError:E,entrypointOpen:D,error:O,explanation:k,explanationError:A,explanationLoading:ee,finderOpen:te,focusedGraph:j,focusedMapData:ne,focusedStudiedCount:re,graph:M,hint:N,hoverNodeId:ie,languageFocus:ae,languageOptions:oe,layer:P,legendOpen:se,level:F,litRegionId:ce,llmStatus:le,mapError:ue,mapTab:de,mode:fe,modeChosen:pe,moduleIndex:me,parseProgress:he,pendingDawnRegionId:ge,picker:_e,projectName:ve,projectFailure:ye,region:be,revealedRegionIds:xe,visitedRegionIds:Se,selectedNode:Ce,showAll:we,showChart:Te,showChecks:Ee,sidebarOpen:De,status:Oe,studyData:ke,studyError:Ae}=b;(0,_.useLayoutEffect)(()=>{!i.current||te||F!==jG.SYSTEM||!u.current||(setTimeout(()=>u.current?.focus(),0),i.current=!1,r.current=null)},[te,F,be?.id]);let je=(0,_.useMemo)(()=>bG(M),[M]),Me=je[h]??null,I=h!==null&&Me!==null;c.current=I;let Ne=(0,_.useMemo)(()=>{if(!j)return null;let e=new Map;for(let t of j.regions){let n=tK(t.community_family);n!==null&&e.set(t.id,n)}return e},[j]);function Pe(t,n){setTimeout(()=>{for(let r of[t,n,e]){let e=r&&`current`in r?r.current:r;if(e?.isConnected&&e.getClientRects().length){e.focus();return}}},0)}function Fe(e){y.dispatch({type:`TOGGLE_SIDEBAR`}),De&&Pe(e.currentTarget,t)}function L(){y.dispatch({type:`TOGGLE_SIDEBAR`}),Pe(t)}function Ie(){y.dispatch({type:`CLOSE_CHECKS`}),Pe(o,u)}function Le(e){r.current=e.currentTarget,y.dispatch({type:`SET_FINDER_OPEN`,open:!0})}function Re(){i.current||(i.current=!1,y.dispatch({type:`SET_FINDER_OPEN`,open:!1}),Pe(r.current,n),r.current=null)}function ze(e){i.current=!0,y.dispatch({type:`GO_TO_REGION`,regionId:e})}function Be(){y.dispatch({type:`FOLLOW_HINT`}),y.getSnapshot().showChecks||Pe(u)}function Ve(e){let t=je[e];t&&(g(e),y.dispatch({type:`SET_LAYER`,layer:`galaxy`}),y.dispatch({type:`GO_TO_REGION`,regionId:t.id}))}function He(){g(null),Pe(s)}function Ue(){y.dispatch({type:`DISMISS_COACHMARKS`}),requestAnimationFrame(()=>l.current?.focus())}if(O)return(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The graph did not load.`}),(0,$.jsx)(`p`,{children:O}),(0,$.jsx)(`p`,{children:`Your progress is stored on this machine and is not affected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>y.start(),children:`Try again`})]});if(he)return(0,$.jsx)(yX,{progress:he,onCancel:()=>y.dispatch({type:`RESET_PROJECT`})});if(Oe===`picking`&&_e)return(0,$.jsx)(bX,{picker:_e,failure:ye,onBrowse:e=>y.dispatch({type:`BROWSE_PICKER`,path:e}),onSelect:e=>y.dispatch({type:`SELECT_PROJECT`,path:e})});if(!M||!j||!be)return(0,$.jsx)(`main`,{className:`load-state`,"aria-busy":`true`,children:(0,$.jsx)(`p`,{children:`Mapping parser evidence…`})});let We=P===`map`?`map`:`galaxy`,Ge=j.nodes.some(e=>e.id===be.id)?be.id:null,Ke=F===jG.SYSTEM&&P===`galaxy`?Oq(j.nodes.filter(e=>e.region===be.id)):[],qe=F===jG.SYSTEM?(0,$.jsxs)(`section`,{ref:u,className:`orientation-copy orientation-copy--system${P===`map`?` orientation-copy--inline`:``}`,tabIndex:-1,children:[(0,$.jsx)(`p`,{children:j.nodes.some(e=>e.region===be.id&&e.partial)?`${be.node_count} source ${be.node_count===1?`file remains`:`files remain`} visible · ${be.loc} lines. The module is unchartable beyond raw source because it has a syntax error.`:P===`map`?`The ${be.node_count} parser-proven ${be.node_count===1?`structure`:`structures`} inside this module ${be.node_count===1?`is`:`are`} drawn as planets in the Galaxy layer. This map shows how modules connect, not what is inside them.`:`${be.node_count} parser-proven ${be.node_count===1?`structure`:`structures`} · ${be.loc} ${be.loc===1?`line`:`lines`} in this system.`}),Ke.length?(0,$.jsxs)(`p`,{className:`system-orbit-note`,children:[(0,$.jsx)(`span`,{children:`Call layers`}),Ke.map(e=>(0,$.jsx)(`i`,{"data-unproven":e.unproven||void 0,children:e.label},e.ring)),(0,$.jsxs)(`small`,{children:[`Solid guides use certain calls only`,Ke.some(e=>e.unproven)?`; dashed means no proven path.`:`.`]})]}):null,(0,$.jsxs)(`div`,{className:`orientation-copy__actions`,children:[P===`map`&&Ge?(0,$.jsx)(`button`,{className:`check-launch check-launch--read`,type:`button`,onClick:()=>{m(!0),y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:Ge})},children:`Read the source`}):null,(0,$.jsx)(`button`,{ref:o,className:`check-launch`,type:`button`,onClick:()=>y.dispatch({type:`OPEN_CHECKS`}),children:j.nodes.some(e=>e.region===be.id&&e.partial)?`Check availability`:be.understood?`Review understanding`:`Prove understanding`})]})]}):null;return(0,$.jsxs)(`main`,{className:`app-shell`,"data-level":Te?`chart`:F.toLowerCase(),"data-mode":fe,children:[(0,$.jsxs)(`header`,{className:`instrument-rail`,children:[(0,$.jsxs)(`div`,{className:`brand-lockup`,children:[(0,$.jsx)(`span`,{className:`brand-mark`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`strong`,{children:`Codemble`}),(0,$.jsx)(`span`,{children:ve})]})]}),(0,$.jsx)(`nav`,{className:`location`,"aria-label":`Breadcrumb`,"aria-live":`polite`,children:Te?(0,$.jsx)(`span`,{"aria-current":`page`,children:`Star chart`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`button`,{type:`button`,disabled:F===jG.GALAXY,"aria-current":F===jG.GALAXY?`page`:void 0,onClick:()=>y.dispatch({type:`SET_LEVEL_GALAXY`}),children:`All modules`}),F===jG.GALAXY?(0,$.jsxs)(`small`,{children:[` · Home `,M.selected_entrypoint&&mK(M)?(0,$.jsx)(`button`,{type:`button`,className:`breadcrumb-home`,onClick:()=>y.dispatch({type:`ADVANCE_REGION`,regionId:mK(M).id}),children:mK(M).id}):M.selected_entrypoint?`unresolved`:`unselected`]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`button`,{type:`button`,disabled:F===jG.SYSTEM,"aria-current":F===jG.SYSTEM?`page`:void 0,onClick:()=>y.dispatch({type:`RETREAT`}),children:be.id})]}),F===jG.STUDY&&Ce?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`span`,{"aria-current":`page`,children:Ce.name})]}):null,ae===`all`?null:(0,$.jsxs)(`small`,{children:[` · `,LG(ae),` focus`]})]})}),(0,$.jsxs)(`div`,{className:`rail-overflow`,"data-open":d||void 0,children:[(0,$.jsxs)(`button`,{ref:e,className:`mobile-menu-trigger`,type:`button`,"aria-expanded":d,"aria-controls":`rail-overflow-panel`,onClick:()=>f(e=>!e),children:[(0,$.jsx)(`span`,{className:`rail-trigger__compact`,children:`Menu`}),(0,$.jsx)(`span`,{className:`rail-trigger__wide`,children:`More`})]}),(0,$.jsxs)(`div`,{className:`rail-overflow__panel`,id:`rail-overflow-panel`,onClickCapture:e=>{e.target.closest(`button`)&&!e.target.closest(`.switch-project`)&&f(!1)},children:[(0,$.jsxs)(`div`,{className:`rail-actions`,children:[(0,$.jsx)(`button`,{ref:t,className:`rail-action`,type:`button`,"aria-pressed":De,onClick:Fe,children:`Modules`}),(0,$.jsxs)(`button`,{ref:n,className:`rail-action`,type:`button`,onClick:Le,children:[`Find `,(0,$.jsx)(`kbd`,{children:`⌘K`})]}),Te?(0,$.jsxs)(`button`,{ref:a,className:`rail-action`,type:`button`,onClick:()=>{y.dispatch({type:`HIDE_CHART`}),Pe(a)},children:[`Back to `,We]}):(0,$.jsxs)($.Fragment,{children:[F===jG.GALAXY?null:(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>y.dispatch({type:`RETREAT`}),children:F===jG.STUDY?P===`map`?`Back to the module`:`Back to system`:`Back to ${We}`}),(0,$.jsx)(`button`,{ref:a,className:`rail-action`,type:`button`,onClick:()=>y.dispatch({type:`SHOW_CHART`}),children:`Star chart`})]})]}),(0,$.jsxs)(`div`,{className:`rail-more`,children:[M.entrypoint_candidates.length?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>y.dispatch({type:`CHANGE_HOME`}),children:`Change Home`}):null,(0,$.jsx)(OX,{onConfirm:()=>y.dispatch({type:`RESET_PROJECT`})})]}),(0,$.jsxs)(`div`,{className:`rail-controls`,children:[P===`galaxy`?(0,$.jsx)(`button`,{className:`rail-action rail-action--toggle`,type:`button`,"aria-pressed":we,title:`Draw every module at once, including the ones no route from Home reaches`,onClick:()=>y.dispatch({type:`TOGGLE_SHOW_ALL`}),children:`Show all`}):null,(0,$.jsx)(EX,{layer:P,mode:fe,onChange:e=>y.dispatch({type:`SET_LAYER`,layer:e})}),(0,$.jsx)(DX,{options:oe,value:ae,onChange:e=>y.dispatch({type:`SET_LANGUAGE_FOCUS`,language:e})}),(0,$.jsx)($J,{mode:fe,modeChosen:pe,onChoose:e=>y.dispatch({type:`SET_MODE`,mode:e})})]})]})]})]}),Te?(0,$.jsxs)(`section`,{className:`chart-stage`,"aria-label":`Language concept progress`,children:[De?(0,$.jsx)(TX,{index:me,currentRegionId:null,onGo:e=>y.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:L}):null,(0,$.jsx)(NX,{chart:S,studiedCount:re,exploredCount:Se.size,projectName:ve,mode:fe,overview:_K(M),onClearProgress:()=>y.dispatch({type:`CLEAR_PROGRESS`})})]}):(0,$.jsxs)(`section`,{ref:l,className:`map-stage`,"aria-label":`Parser-proven project map`,tabIndex:-1,children:[De?(0,$.jsx)(TX,{index:me,currentRegionId:F===jG.GALAXY?null:be?.id,onGo:e=>y.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:L}):null,P===`map`?(0,$.jsx)(HJ,{data:ne,mapTab:de,mode:fe,communityIndexByRegion:Ne,selectedRegionId:F===jG.GALAXY?void 0:be?.id,hasEntrypointCandidates:M.entrypoint_candidates.length>0,unsupportedSources:j.unsupported_sources,importCycles:M.import_cycles,error:ue,languageFocus:ae,languageFocusLabel:ae===`all`?``:LG(ae),onClearLanguageFocus:()=>y.dispatch({type:`SET_LANGUAGE_FOCUS`,language:`all`}),onSelectTab:e=>y.dispatch({type:`SET_MAP_TAB`,tab:e}),onSelectRegion:e=>y.dispatch({type:`ADVANCE_REGION`,regionId:e}),onSelectNode:e=>{m(!1),y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:e})},onRetry:()=>y.dispatch({type:`SET_LAYER`,layer:`map`}),viewportStore:v,children:qe}):(0,$.jsx)(Vq,{graph:j,level:F,region:be,selectedNode:Ce,hoverNodeId:ie,pendingDawnRegionId:ge,revealedRegionIds:xe,mode:fe,firstFlightActive:I,onHoverNode:e=>y.dispatch({type:`HOVER_NODE`,nodeId:e}),onAdvance:e=>y.dispatch({type:`ADVANCE`,node:e}),onRetreat:()=>y.dispatch({type:`RETREAT`}),onDawnConsumed:e=>y.dispatch({type:`CONSUME_DAWN`,regionId:e})}),(0,$.jsx)(`button`,{className:`legend-toggle`,type:`button`,"aria-expanded":se,onPointerEnter:()=>y.dispatch({type:`HOVER_NODE`,nodeId:null}),onClick:()=>y.dispatch({type:`TOGGLE_LEGEND`}),children:`Key`}),(0,$.jsxs)(`aside`,{className:`map-legend`,hidden:!se,tabIndex:0,"aria-label":P===`map`?`Map legend`:`Galaxy legend`,onPointerEnter:()=>y.dispatch({type:`HOVER_NODE`,nodeId:null}),onKeyDown:e=>{let t=e.currentTarget,n=Math.max(48,t.clientHeight*.8),r={ArrowDown:32,ArrowUp:-32,PageDown:n,PageUp:-n}[e.key];r===void 0?(e.key===`Home`||e.key===`End`)&&(e.preventDefault(),t.scrollTop=e.key===`Home`?0:t.scrollHeight):(e.preventDefault(),t.scrollBy({top:r,behavior:`auto`}))},children:[P===`galaxy`?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-size`}),`Size · `,fe===`easy`?`how much code`:`lines of code`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-brightness`}),`Brighter · `,fe===`easy`?`used in more places`:`more distinct callers`]})]}):null,(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--dim`}),`Dim · `,fe===`easy`?`not proven yet`:`not understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--lit`}),`Amber · `,fe===`easy`?`you proved you understand it`:`understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--partial`}),fe===`easy`?`Could not be read`:`Unchartable · syntax error`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-route`}),fe===`easy`?`Certain connection`:`Parser edge · certain`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-route legend-route--possible legend-route--dashed`}),fe===`easy`?`Possible connection`:`Possible relationship`]}),P===`galaxy`&&F===jG.GALAXY||P===`map`&&de===`architecture`?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`span`,{children:[(0,$.jsxs)(`span`,{className:`legend-communities`,"aria-hidden":`true`,children:[(0,$.jsx)(`i`,{}),(0,$.jsx)(`i`,{}),(0,$.jsx)(`i`,{}),(0,$.jsx)(`i`,{})]}),fe===`easy`?`Colour family · related systems and their shared routes`:`Hue family · one import community; internal routes inherit a tint`]}),oe.filter(e=>e.id!==`all`).map(e=>(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-tint`,style:{background:BG(e.id)??void 0}}),` `,e.label]},e.id))]}):null]}),P===`galaxy`&&F===jG.GALAXY?(0,$.jsxs)(`p`,{className:`orientation-bar`,children:[(0,$.jsxs)(`span`,{children:[j.regions.length,` `,ae===`all`?j.regions.length===1?`system`:`systems`:`${LG(ae)} ${j.regions.length===1?`system`:`systems`}`]}),(0,$.jsx)(`span`,{className:`orientation-bar__charted`,children:we?`all charted`:`${xe.size} charted`}),j.partial_files.length?(0,$.jsxs)(`span`,{className:`partial-summary`,children:[j.partial_files.length,` `,fe===`easy`?`could not be read`:`unchartable · syntax error`,QG(j.partial_files)?` · ${j.partial_files.length===1?`in`:`all under`} ${QG(j.partial_files)}/`:``]}):null,UG(j.unsupported_sources,fe)?(0,$.jsx)(`span`,{className:`unsupported-summary`,children:UG(j.unsupported_sources,fe)}):null]}):null,P===`galaxy`?qe:null,F===jG.SYSTEM&&Ee?(0,$.jsx)(AX,{suite:C,error:w,mode:fe,overviewNoun:We,onClose:Ie,onSubmit:(e,t)=>y.dispatch({type:`SUBMIT_CHECK`,checkId:e,selectedIds:t})}):null,pe===!0&&D&&F===jG.GALAXY?(0,$.jsx)(kX,{candidates:M.entrypoint_candidates,nodes:M.nodes,selectedEntrypoint:M.selected_entrypoint,mode:fe,error:E,onSelect:e=>y.dispatch({type:`SELECT_ENTRYPOINT`,nodeId:e}),onContinue:()=>y.dispatch({type:`DISMISS_ENTRYPOINT`})}):null,ce?(0,$.jsxs)(`output`,{className:`illumination-pulse`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),(0,$.jsxs)(`strong`,{children:[ce,` understood`]})]}):null,F===jG.STUDY&&Ce?(0,$.jsx)(aY,{node:Ce,study:ke,error:Ae,mode:fe,explanation:k,explanationLoading:ee,explanationError:A,llmStatus:le,revealSource:p,onSelectNode:e=>{m(!1),y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:e})},onRetryStudy:()=>y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:Ce.id}),onRetryNarration:()=>y.dispatch({type:`SELECT_STUDY_NODE`,nodeId:Ce.id}),onClose:()=>{m(!1),y.dispatch({type:`RETREAT`})}}):null,pe===!0&&!D&&!T?(0,$.jsx)(qq,{layer:P,onDismiss:Ue}):null]}),te?(0,$.jsx)(wX,{index:me,onGo:ze,onClose:Re}):null,!Te&&!Ee&&pe===!0&&!D&&T?(0,$.jsx)(Wq,{hint:N,onFollow:Be,firstFlight:{available:je.length>0,active:I,stop:Me,index:h??0,total:je.length,mode:fe,triggerRef:s,onStart:()=>Ve(0),onBack:()=>Ve(h-1),onNext:()=>Ve(h+1),onExit:He}}):null,(0,$.jsxs)(`footer`,{className:`status-line`,children:[(0,$.jsx)(`span`,{children:Te?`${S.length} concepts detected`:ae===`all`?`${M.nodes.length} nodes · ${M.edges.length} edges`:`${j.nodes.length}/${M.nodes.length} nodes · ${j.edges.length} focused edges`}),(0,$.jsx)(`span`,{children:Te?`${re} focused structures studied this session`:P===`map`?`Click a box or row to study · Switch tabs to change view`:`Drag to orbit · Scroll to zoom · Click to move closer · Escape to move back`}),(0,$.jsx)(`span`,{children:`Local only`})]})]})}var hX=Object.fromEntries(zY.map(({id:e,copy:t})=>[e,t])),gX=zY.map(({id:e})=>e);function _X(e,{firstFlightOpen:t=!1}={}){return{ready:e.status===`ready`,canRetreat:e.layer===`map`&&e.level!==jG.GALAXY,showChart:e.showChart,finderOpen:e.finderOpen,sidebarOpen:e.sidebarOpen,showChecks:e.showChecks,entrypointOpen:e.entrypointOpen,firstFlightOpen:t,nativeDialogOpen:document.querySelector(`dialog[open]`)!==null,railDisclosureOpen:document.querySelector(`.rail-overflow[data-open]`)!==null,editableFocus:vX(document.activeElement)}}function vX(e){if(!e)return!1;let t=e.tagName;return t===`INPUT`||t===`TEXTAREA`||t===`SELECT`||e.isContentEditable===!0}function yX({progress:e,onCancel:t}){let{stage:n,detail:r,files_done:i,files_total:a,pollError:o,pollOutage:s,attempts:c,path:l}=e,[u,d]=(0,_.useState)(!1),[f,p]=(0,_.useState)(``),m=(0,_.useRef)(null),h=gX.indexOf(n);(0,_.useEffect)(()=>{m.current?.focus()},[]);async function g(){d(!0),p(``);try{await t()}catch(e){p(e.message),d(!1)}}return(0,$.jsxs)(`main`,{className:`loading-screen`,children:[(0,$.jsxs)(`header`,{className:`loading-header`,children:[(0,$.jsx)(`p`,{className:`picker-wordmark`,children:`Codemble`}),(0,$.jsxs)(`h1`,{ref:m,tabIndex:-1,children:[`Mapping `,(0,$.jsx)(`span`,{className:`loading-path`,children:l})]}),(0,$.jsx)(`p`,{className:`loading-subtitle`,children:`Parsing runs on your machine. Nothing is sent anywhere.`})]}),(0,$.jsx)(`ol`,{className:`loading-stages`,"aria-label":`Parse stages`,children:gX.map((e,t)=>{let n=t{let e=m.current;l?p.current?.focus():e&&f.current?.focus(),m.current=!!l},[l]),(0,$.jsxs)(`main`,{className:`picker-screen`,"aria-busy":d,children:[(0,$.jsxs)(`header`,{className:`picker-header`,children:[(0,$.jsx)(`p`,{className:`picker-wordmark`,children:`Codemble`}),(0,$.jsx)(`h1`,{children:`Choose the project to chart`}),(0,$.jsx)(`p`,{className:`picker-subtitle`,children:`Codemble reads the folder locally and turns it into a galaxy. Nothing leaves this machine.`})]}),s.length?(0,$.jsxs)(`section`,{className:`picker-recents`,"aria-labelledby":`picker-recents-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-recents-heading`,children:`Continue where you left off`}),(0,$.jsx)(`ul`,{children:s.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:d,onClick:()=>r(e.project_root),children:[(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.project_root}),(0,$.jsxs)(`span`,{className:`picker-recent-lit`,children:[e.understood_count,` `,e.understood_count===1?`system`:`systems`,` lit last visit`]})]})},e.project_root))})]}):null,u?(0,$.jsx)(xX,{scale:u,busy:d,onBrowse:n}):null,t?(0,$.jsx)(CX,{failure:t,busy:d,onSelect:r}):c?(0,$.jsxs)(`div`,{className:`picker-error`,children:[(0,$.jsx)(`p`,{role:`alert`,children:c}),l?(0,$.jsx)(`button`,{ref:p,className:`picker-retry`,type:`button`,disabled:d,onClick:()=>n(l),children:`Try this folder again`}):null]}):null,(0,$.jsxs)(`section`,{className:`picker-browser`,"aria-labelledby":`picker-browser-heading`,children:[(0,$.jsx)(`h2`,{ref:f,id:`picker-browser-heading`,tabIndex:-1,children:`Browse folders`}),(0,$.jsx)(`p`,{className:`picker-path`,children:i}),(0,$.jsxs)(`ul`,{children:[a?(0,$.jsx)(`li`,{children:(0,$.jsx)(`button`,{type:`button`,disabled:d,onClick:()=>n(a),children:`↑ Up`})}):null,o.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:d,onClick:()=>n(e.path),children:[e.name,`/`]})},e.path))]}),(0,$.jsx)(`button`,{className:`picker-select`,type:`button`,disabled:d,onClick:()=>r(i),children:d?`Mapping…`:`Map this folder`})]})]})}function xX({scale:e,busy:t,onBrowse:n}){let r=e.suggestions.filter(e=>e.path!==`.`);return(0,$.jsxs)(`section`,{className:`picker-scale`,role:`alert`,"aria-labelledby":`picker-scale-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-scale-heading`,children:`That folder is too big to map at once.`}),(0,$.jsxs)(`p`,{children:[`It has `,e.file_count,` supported source files; Codemble maps up to`,` `,e.scale_cap,`. Choose a smaller scope — busiest first.`]}),r.length?(0,$.jsx)(`ul`,{className:`picker-scale-scopes`,children:r.map(r=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:t,onClick:()=>n(`${e.root}/${r.path}`),children:[(0,$.jsxs)(`span`,{children:[r.path,`/`]}),(0,$.jsxs)(`small`,{children:[r.file_count,` files`]})]})},r.path))}):null,(0,$.jsx)(SX,{busy:t,onBrowse:n})]})}function SX({busy:e,onBrowse:t}){let[n,r]=(0,_.useState)(``);return(0,$.jsxs)(`form`,{className:`picker-path-entry`,onSubmit:e=>{e.preventDefault();let r=n.trim();r&&t(r)},children:[(0,$.jsx)(`label`,{htmlFor:`picker-path-input`,children:`Or type a folder path`}),(0,$.jsx)(`input`,{id:`picker-path-input`,name:`project-path`,type:`text`,value:n,disabled:e,autoComplete:`off`,spellCheck:!1,placeholder:`/Users/you/project/src`,onChange:e=>r(e.target.value)}),(0,$.jsx)(`button`,{type:`submit`,disabled:e||!n.trim(),children:`Go`})]})}function CX({failure:e,busy:t,onSelect:n}){return(0,$.jsxs)(`section`,{className:`picker-failure`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`Codemble could not map that folder.`}),(0,$.jsx)(`p`,{children:`Nothing on disk changed, and no project's saved progress was touched. Try it again, or choose a different folder below.`}),(0,$.jsxs)(`p`,{className:`picker-failure__detail`,children:[(0,$.jsx)(`span`,{children:`What the parser reported`}),(0,$.jsx)(`code`,{children:e.detail})]}),(0,$.jsxs)(`button`,{className:`picker-select`,type:`button`,disabled:t,onClick:()=>n(e.path),children:[`Try `,(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.path}),` again`]})]})}function wX({index:e,onGo:t,onClose:n}){let[r,i]=(0,_.useState)(``),[a,o]=(0,_.useState)(0),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useMemo)(()=>{let t=r.trim().toLowerCase();return t?e.filter(e=>e.label.toLowerCase().includes(t)||e.file.toLowerCase().includes(t)).slice(0,60):[...e].sort((e,t)=>Number(t.home)-Number(e.home)||Number(t.understood)-Number(e.understood)||t.centrality-e.centrality||e.label.localeCompare(t.label)||e.id.localeCompare(t.id)).slice(0,60)},[e,r]);(0,_.useLayoutEffect)(()=>{let e=s.current;e&&!e.open&&e.showModal(),c.current?.focus()},[]),(0,_.useEffect)(()=>o(0),[r]);let u=l[Math.min(a,l.length-1)]??null;function d(e){e.key===`ArrowDown`?(e.preventDefault(),o(e=>Math.min(e+1,l.length-1))):e.key===`ArrowUp`?(e.preventDefault(),o(e=>Math.max(e-1,0))):e.key===`Enter`&&u?(e.preventDefault(),t(u.id)):e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),n())}return(0,$.jsxs)(`dialog`,{ref:s,className:`module-finder`,"aria-label":`Find a module`,onCancel:e=>{e.preventDefault(),n()},onClose:n,children:[(0,$.jsx)(`input`,{ref:c,name:`module-search`,type:`search`,value:r,placeholder:`Find a module…`,"aria-label":`Find a module by name or path`,autoComplete:`off`,spellCheck:!1,onChange:e=>i(e.target.value),onKeyDown:d}),(0,$.jsx)(`ul`,{role:`listbox`,"aria-label":`Matching modules`,children:l.map((e,n)=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n===a,"data-active":n===a||void 0,onMouseEnter:()=>o(n),onClick:()=>t(e.id),children:[(0,$.jsx)(`strong`,{children:e.label}),e.file===e.label?e.hops===0?null:(0,$.jsx)(`small`,{children:typeof e.hops==`number`?`${e.hops} ${e.hops===1?`route`:`routes`} from Home`:`no route from Home`}):(0,$.jsx)(`small`,{children:e.file}),e.home?(0,$.jsx)(`em`,{children:`Home`}):e.understood?(0,$.jsx)(`em`,{children:`lit`}):null]})},e.id))}),l.length?null:(0,$.jsx)(`p`,{className:`module-finder__empty`,children:`No module matches that.`})]})}function TX({index:e,currentRegionId:t,onGo:n,onClose:r}){let i=(0,_.useMemo)(()=>YG(e),[e]),a=(0,_.useRef)(null);return(0,_.useLayoutEffect)(()=>{a.current?.focus()},[]),(0,$.jsxs)(`aside`,{className:`index-sidebar`,"aria-label":`Project index`,children:[(0,$.jsxs)(`header`,{children:[(0,$.jsx)(`h2`,{children:`Modules`}),(0,$.jsx)(`button`,{ref:a,type:`button`,onClick:r,"aria-label":`Close the project index`,children:`×`})]}),(0,$.jsx)(`div`,{className:`index-sidebar__scroll`,children:i.map(e=>(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{title:e.name,children:e.name}),(0,$.jsx)(`ul`,{children:e.members.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-current":e.id===t?`true`:void 0,"data-lit":e.understood||void 0,title:e.file,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.display??e.label}),e.home?(0,$.jsx)(`em`,{children:`Home`}):null]})},e.id))})]},e.community))})]})}function EX({layer:e,mode:t,onChange:n}){return(0,$.jsx)(`nav`,{className:`layer-switcher`,"aria-label":`View layer`,children:[{id:`galaxy`,label:`Galaxy`},{id:`map`,label:t===`easy`?`Diagram`:`Map`}].map(t=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":e===t.id,onClick:()=>n(t.id),children:t.label},t.id))})}function DX({options:e,value:t,onChange:n}){return e.length<=2?null:(0,$.jsxs)(`nav`,{className:`language-focus`,"aria-label":`Language focus`,children:[(0,$.jsx)(`span`,{className:`language-focus__label`,children:`Focus`}),(0,$.jsx)(`div`,{children:e.map(e=>(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Focus ${e.label}: ${e.count} ${e.count===1?`system`:`systems`}`,"aria-pressed":t===e.id,title:e.label,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.shortLabel}),(0,$.jsx)(`small`,{children:e.count})]},e.id))})]})}function OX({onConfirm:e}){let[t,n]=(0,_.useState)(!1),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(``),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useRef)(!1);(0,_.useEffect)(()=>{t?c.current?.focus():l.current&&s.current?.focus(),l.current=t},[t]);function u(){n(!1),o(``)}async function d(){i(!0),o(``);try{await e()}catch(e){o(e.message),i(!1)}}return(0,$.jsx)(`div`,{className:`switch-project`,"data-confirming":t||void 0,role:t?`group`:void 0,"aria-label":t?`Switch project`:void 0,tabIndex:t?-1:void 0,ref:t?c:void 0,onKeyDown:e=>{e.key===`Escape`&&t&&!r&&u()},children:t?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`p`,{children:`Progress is saved per project, so this galaxy comes back lit.`}),a?(0,$.jsx)(`p`,{className:`switch-project__error`,role:`alert`,children:a}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:d,children:r?`Releasing…`:`Switch`}),(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:u,children:`Cancel`})]})]}):(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,ref:s,onClick:()=>n(!0),children:`Switch project`})})}function kX({candidates:e,nodes:t,selectedEntrypoint:n,mode:r,error:i,onSelect:a,onContinue:o}){let s=new Map(t.map(e=>[e.id,e])),c=(0,_.useMemo)(()=>{let t=new Map;for(let n of e){let e=s.get(n),r=(e?.file??n).split(`/`).filter(Boolean),i=r.length>1?`${r[0]}/`:`project root`;t.has(i)||t.set(i,[]),t.get(i).push({candidate:n,node:e})}return[...t].map(([e,t])=>({name:e,rows:t,bestRank:Math.min(...t.map(e=>e.node?.entrypoint_rank??2**53-1))})).sort((e,t)=>e.bestRank-t.bestRank||e.name.localeCompare(t.name)).map((e,t)=>({...e,open:t===0||e.bestRank===0}))},[e,t]),l=c[0]?.rows[0]?.candidate??null,u=(0,_.useRef)(null),d=(0,_.useRef)(null);return(0,_.useLayoutEffect)(()=>{let e=d.current;e&&!e.open&&e.showModal(),u.current?.focus()},[]),(0,$.jsxs)(`dialog`,{ref:d,className:`entrypoint-picker`,"aria-labelledby":`entrypoint-heading`,onCancel:e=>e.preventDefault(),children:[(0,$.jsx)(`p`,{children:`Home calibration`}),(0,$.jsx)(`h1`,{id:`entrypoint-heading`,children:e.length?`Where does your project start?`:`No clear entrypoint found.`}),(0,$.jsx)(`p`,{children:e.length?r===`easy`?`Your project could start from more than one place, and Codemble will not guess. Pick the one you actually run — best guess first.`:`The parser found ranked candidates but cannot choose one honestly. Select the structure you run.`:`No file here declares a startup structure the parser recognises, and Codemble will not guess one. Explore the map without Home — every system, check, explanation, and lens note still works.`}),e.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`p`,{className:`entrypoint-count`,children:[e.length,` ranked`,` `,e.length===1?`candidate`:`candidates`,` in `,c.length,` `,c.length===1?`scope`:`scopes`]}),(0,$.jsx)(`div`,{className:`entrypoint-scroll`,children:c.map(e=>(0,$.jsxs)(`details`,{open:e.open,children:[(0,$.jsxs)(`summary`,{children:[(0,$.jsx)(`span`,{children:e.name}),(0,$.jsxs)(`small`,{children:[e.rows.length,` `,e.rows.length===1?`candidate`:`candidates`]})]}),(0,$.jsx)(`div`,{className:`entrypoint-candidates`,children:e.rows.map(({candidate:e,node:t})=>(0,$.jsxs)(`button`,{ref:e===l?u:void 0,type:`button`,onClick:()=>a(e),children:[(0,$.jsx)(`span`,{children:e}),(0,$.jsxs)(`small`,{children:[t?.file,`:`,t?.lineno,` ·`,` `,r===`easy`?`candidate ${(t?.entrypoint_rank??0)+1}`:`parser rank ${t?.entrypoint_rank}`]})]},e))})]},e.name))})]}):null,i?(0,$.jsx)(`p`,{className:`entrypoint-error`,role:`alert`,children:i}):null,(0,$.jsx)(`button`,{ref:e.length?void 0:u,className:`entrypoint-continue`,type:`button`,onClick:o,children:n?`Keep current Home`:`Explore without Home`})]})}function AX({suite:e,error:t,mode:n,overviewNoun:r,onClose:i,onSubmit:a}){let o=e?.checks.find(e=>!e.passed)??null,s=e?.checks.filter(e=>e.passed).length??0,[c,l]=(0,_.useState)(()=>new Set),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(``),[m,h]=(0,_.useState)(!1),[g,v]=(0,_.useState)(``),y=(0,_.useRef)(null),b=(0,_.useRef)(null),x=(0,_.useRef)(null),S=(0,_.useRef)(null),C=(0,_.useRef)(null),w=(0,_.useRef)(null),T=(0,_.useRef)(null);(0,_.useEffect)(()=>{l(new Set),d(null),v(``)},[o?.id]),(0,_.useLayoutEffect)(()=>{y.current?.focus()},[]),(0,_.useLayoutEffect)(()=>{e?.region_understood?S.current?.focus():u?b.current?.focus():f&&x.current?.focus()},[e?.region_understood,u,f]),(0,_.useLayoutEffect)(()=>{u&&C.current?.scrollIntoView({block:`nearest`})},[u]),(0,_.useLayoutEffect)(()=>{if(!o)return;let e=w.current,t=T.current;if(!e||!t)return;let n=!1,r=0,i=()=>{if(n||!window.matchMedia(`(max-width: 39.999rem)`).matches&&e.scrollHeight<=e.clientHeight+1)return;let r=t.getBoundingClientRect().top-e.getBoundingClientRect().top;e.scrollTop+=r};return i(),r=window.requestAnimationFrame(i),document.fonts?.ready.then(()=>{n||(window.cancelAnimationFrame(r),r=window.requestAnimationFrame(i))}),()=>{n=!0,window.cancelAnimationFrame(r)}},[o?.id]);function E(e,t){p(``),l(n=>{if(!t)return new Set([e]);let r=new Set(n);return r.has(e)?r.delete(e):r.add(e),r})}async function D(e){if(e.preventDefault(),!(!o||c.size===0)){h(!0),v(``);try{let e=await a(o.id,[...c]);e.correct?(p(e.message),d(null)):(p(``),d(e))}catch(e){v(e.message)}finally{h(!1)}}}return(0,$.jsxs)(`aside`,{ref:w,className:`check-panel`,"aria-label":`Graph-derived understanding checks`,children:[(0,$.jsxs)(`header`,{className:`check-panel__header`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:n===`easy`?`Quiz · answers come from your code, not AI`:`Active recall · graph only`}),(0,$.jsx)(`h1`,{ref:y,tabIndex:-1,children:e?.region_id??`Loading checks`})]}),(0,$.jsx)(`button`,{className:`check-close`,type:`button`,onClick:i,children:`Close`})]}),t||g?(0,$.jsxs)(`div`,{className:`check-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The checks did not load.`}),(0,$.jsxs)(`p`,{children:[t||g,` The galaxy remains available.`]})]}):null,!e&&!t?(0,$.jsx)(`p`,{className:`check-loading`,role:`status`,children:`Deriving answers from parser edges…`}):null,e?.region_understood?(0,$.jsxs)(`div`,{className:`check-complete`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{className:`check-complete__star`,"aria-hidden":`true`,children:`✦`}),(0,$.jsx)(`h2`,{children:r===`map`?`Module lit.`:`System lit.`}),(0,$.jsx)(`p`,{children:n===`easy`?`Codemble remembers the exact code you proved. Edit this file and only this ${r===`map`?`module`:`system`} dims again.`:`This region's source hash matches the checks you passed. Edit its file and only this system will dim again.`}),(0,$.jsxs)(`button`,{ref:S,className:`check-primary`,type:`button`,onClick:i,children:[`Back to the `,r===`map`?`module`:`system`]})]}):null,e&&!e.region_understood&&e.checks.length===0?(0,$.jsxs)(`div`,{className:`check-state`,children:[(0,$.jsx)(`h2`,{children:`No safe check yet.`}),(0,$.jsx)(`p`,{children:`Every question here is answered by the parser graph, and this region has no certain relationship Codemble can build one from. It stays dim rather than lighting on a question that would prove nothing. Import this module somewhere, or call something inside it, and its checks appear.`})]}):null,e&&!e.region_understood&&e.checks.length>0&&!o?(0,$.jsxs)(`div`,{className:`check-state`,children:[(0,$.jsx)(`h2`,{children:`These checks are out of date.`}),(0,$.jsx)(`p`,{children:`This module is dim again, but this panel is still holding the answers from before. Reopen it to get the questions back — nothing you proved has been lost anywhere else.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:i,children:`Reopen the checks`})]}):null,o&&!e.region_understood?(0,$.jsxs)(`form`,{className:`active-check`,onSubmit:D,children:[(0,$.jsxs)(`div`,{className:`check-progress`,children:[(0,$.jsxs)(`span`,{children:[`Check `,s+1,` of `,e.checks.length]}),(0,$.jsx)(`progress`,{value:s,max:e.checks.length})]}),f?(0,$.jsxs)(`p`,{ref:x,className:`check-affirmation`,role:`status`,tabIndex:-1,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),` `,f]}):null,(0,$.jsxs)(`fieldset`,{ref:T,children:[(0,$.jsx)(`legend`,{children:o.prompt_voices[n]}),o.multiple?(0,$.jsx)(`p`,{children:`Select every answer supported by the graph.`}):null,(0,$.jsx)(`div`,{className:`check-options`,children:o.options.map(e=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:o.multiple?`checkbox`:`radio`,name:`answer-${o.id}`,value:e.id,checked:c.has(e.id),onChange:()=>E(e.id,o.multiple)}),(0,$.jsx)(`span`,{children:e.label})]},e.id))})]}),u&&!u.correct?(0,$.jsx)(`div`,{ref:b,className:`check-feedback`,role:`status`,tabIndex:-1,children:(0,$.jsx)(`strong`,{children:u.message})}):null,(0,$.jsx)(`div`,{className:`check-submit-bar`,children:(0,$.jsx)(`button`,{ref:C,className:`check-primary`,type:`submit`,disabled:!c.size||m,children:m?`Checking parser evidence…`:`Check answer`})})]}):null]})}function jX({overview:e,mode:t,charted:n}){let r=t===`easy`,i=e.languages.map(e=>`${e.label} ${e.count}`).join(` · `);return(0,$.jsxs)(`section`,{className:`project-summary`,"aria-label":`Project summary`,children:[(0,$.jsxs)(`p`,{className:`project-summary__lead`,children:[r?`${e.modules} files of code, holding ${e.structures} functions and classes between them.`:`${e.modules} modules · ${e.structures} structures · ${e.lines} lines.`,` `,e.home?r?`It starts at ${e.home.id}.`:`Entrypoint ${e.home.id}.`:r?`Codemble could not tell which file starts it.`:`No entrypoint resolved.`]}),(0,$.jsxs)(`dl`,{className:`project-summary__facts`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Written in`:`Languages`}),(0,$.jsx)(`dd`,{children:i||`—`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Biggest files`:`Largest by LOC`}),(0,$.jsx)(`dd`,{children:e.biggest.length?e.biggest.map(e=>`${KG(e.id)} (${e.value})`).join(`, `):`—`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Called from the most places`:`Highest centrality`}),(0,$.jsx)(`dd`,{children:e.busiest.length?e.busiest.map(e=>`${KG(e.id)} (${e.value})`).join(`, `):`—`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`You have proved`:`Understood`}),(0,$.jsxs)(`dd`,{children:[e.understood,` of `,e.modules,` `,r?e.modules===1?`file`:`files`:`modules`]})]}),e.unreadable||e.unsupported?(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Not included`:`Outside the graph`}),(0,$.jsx)(`dd`,{children:[e.unreadable?`${e.unreadable} ${e.unreadable===1?`file`:`files`} could not be read`:``,e.unsupported?`${e.unsupported} in a language Codemble does not parse`:``].filter(Boolean).join(` · `)})]}):null,e.importCycles.length?(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r?`Files that bring each other in`:`Proven import cycles`}),(0,$.jsxs)(`dd`,{children:[e.importCycles.length,` `,e.importCycles.length===1?`cycle group`:`cycle groups`,` · `,e.importCycles.slice().sort((e,t)=>t.length-e.length||e.join(`\0`).localeCompare(t.join(`\0`)))[0].join(`, `),` · each file can reach every other through proven imports`]})]}):null]}),(0,$.jsx)(`button`,{className:`project-summary__export`,type:`button`,onClick:()=>MX(e,n),children:r?`Save a project guide`:`Export Markdown brief`})]})}function MX(e,t){let n=pX(e,{charted:t}),r=URL.createObjectURL(new Blob([n],{type:`text/markdown;charset=utf-8`})),i=document.createElement(`a`);i.href=r,i.download=fX(e),document.body.append(i),i.click(),i.remove(),window.setTimeout(()=>URL.revokeObjectURL(r),0)}function NX({chart:e,studiedCount:t,exploredCount:n,projectName:r,mode:i,overview:a,onClearProgress:o}){let s=e.filter(e=>e.understood_nodes>0).length,c=(0,_.useRef)(null);return(0,_.useLayoutEffect)(()=>{c.current?.focus()},[]),(0,$.jsxs)(`section`,{className:`star-chart-screen`,"aria-labelledby":`star-chart-heading`,children:[(0,$.jsxs)(`header`,{className:`star-chart-intro`,children:[(0,$.jsx)(`p`,{children:r}),(0,$.jsx)(`h1`,{ref:c,id:`star-chart-heading`,tabIndex:-1,children:`What this project is.`}),a?(0,$.jsx)(jX,{overview:a,mode:i,charted:n}):null,(0,$.jsx)(`h2`,{className:`star-chart-section`,children:i===`easy`?`Ideas your code uses`:`Parser-detected concepts`}),(0,$.jsx)(`p`,{children:`Explored counts the systems you have flown to. Encountered comes from real syntax. Studied tracks this session. Understood lights only after graph-derived checks pass.`}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Systems explored`}),(0,$.jsx)(`dd`,{children:n})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts encountered`}),(0,$.jsx)(`dd`,{children:e.length})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied this session`}),(0,$.jsx)(`dd`,{children:t})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts understood`}),(0,$.jsx)(`dd`,{children:s})]})]})]}),(0,$.jsx)(`div`,{className:`concept-ledger`,role:`list`,"aria-label":`Language concept progress`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`concept-row`,role:`listitem`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h2`,{children:IG(e.concept)}),(0,$.jsxs)(`span`,{children:[IG(e.language),` · `,e.occurrences,` parser `,e.occurrences===1?`occurrence`:`occurrences`]})]}),(0,$.jsx)(`div`,{className:`concept-meter`,"aria-label":`${e.understood_nodes} of ${e.nodes} ${e.nodes===1?`structure`:`structures`} understood`,children:(0,$.jsx)(`span`,{style:{width:`${e.nodes?e.understood_nodes/e.nodes*100:0}%`}})}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied (session)`}),(0,$.jsxs)(`dd`,{children:[e.studied_nodes,`/`,e.nodes]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Understood`}),(0,$.jsxs)(`dd`,{children:[e.understood_nodes,`/`,e.nodes]})]})]})]},`${e.language}:${e.concept}`))}),(0,$.jsx)(PX,{projectName:r,onConfirm:o})]})}function PX({projectName:e,onConfirm:t}){let[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(``),c=(0,_.useRef)(null),l=(0,_.useRef)(null),u=(0,_.useRef)(!1);(0,_.useEffect)(()=>{n?l.current?.focus():u.current&&c.current?.focus(),u.current=n},[n]);function d(){r(!1),s(``)}async function f(){a(!0),s(``);try{await t(),r(!1)}catch(e){s(e.message)}finally{a(!1)}}return n?(0,$.jsxs)(`section`,{className:`progress-reset progress-reset--confirming`,role:`group`,"aria-label":`Clear this project's progress`,tabIndex:-1,ref:l,onKeyDown:e=>{e.key===`Escape`&&!i&&d()},children:[(0,$.jsxs)(`p`,{role:`alert`,children:[`This dims every system you lit in `,e,` and cannot be undone. Your other projects keep their progress, and no source file is touched.`]}),o?(0,$.jsx)(`p`,{className:`progress-reset__error`,role:`alert`,children:o}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`check-primary progress-reset__confirm`,type:`button`,disabled:i,onClick:f,children:i?`Clearing…`:`Yes, clear ${e}`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,disabled:i,onClick:d,children:`Keep it`})]})]}):(0,$.jsxs)(`section`,{className:`progress-reset`,children:[(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,ref:c,onClick:()=>r(!0),children:`Clear this project's progress`}),(0,$.jsxs)(`p`,{children:[`Start `,e,` over with every system dim again.`]})]})}var FX=class extends _.Component{constructor(e){super(e),this.state={message:``}}static getDerivedStateFromError(e){return{message:e instanceof Error?e.message:String(e)}}componentDidCatch(e,t){console.error(`Codemble stopped rendering:`,e,t?.componentStack)}render(){return this.state.message?(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The galaxy stopped rendering.`}),(0,$.jsx)(`p`,{children:this.state.message}),(0,$.jsx)(`p`,{children:`Your progress is saved on this machine; reloading re-reads it.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>window.location.reload(),children:`Reload Codemble`})]}):this.props.children}};(0,v.createRoot)(document.getElementById(`root`)).render((0,$.jsx)(_.StrictMode,{children:(0,$.jsx)(FX,{children:(0,$.jsx)(mX,{})})}));
\ No newline at end of file
diff --git a/codemble/web_dist/assets/index-DgSklSeG.css b/codemble/web_dist/assets/index-R8cZVoqz.css
similarity index 71%
rename from codemble/web_dist/assets/index-DgSklSeG.css
rename to codemble/web_dist/assets/index-R8cZVoqz.css
index f6894a0..8f1e90d 100644
--- a/codemble/web_dist/assets/index-DgSklSeG.css
+++ b/codemble/web_dist/assets/index-R8cZVoqz.css
@@ -1 +1 @@
-@font-face{font-family:Zen Kaku Gothic New;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/zen-kaku-gothic-new-latin-400-normal-BEdayliK.woff2)format("woff2"),url(/assets/zen-kaku-gothic-new-latin-400-normal-CPSmNJAU.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/shippori-mincho-latin-500-normal-XI1O8euf.woff2)format("woff2"),url(/assets/shippori-mincho-latin-500-normal-C-QwvIb3.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/shippori-mincho-latin-700-normal-DHcmzUO5.woff2)format("woff2"),url(/assets/shippori-mincho-latin-700-normal-CkoCYOiI.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff)format("woff")}:root{--cm-font-display:"Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif;--cm-font-body:"Zen Kaku Gothic New", "Hiragino Sans", system-ui, sans-serif;--cm-font-mono:"JetBrains Mono", ui-monospace, monospace;--cm-text-xs:.75rem;--cm-text-sm:.875rem;--cm-text-base:1rem;--cm-text-lg:1.25rem;--cm-text-xl:clamp(1.25rem, .5vw + 1.1rem, 1.5rem);--cm-text-display:clamp(1.75rem, 3vw + 1rem, 3.25rem);--cm-space-2xs:.125rem;--cm-space-xs:.5rem;--cm-space-sm:.75rem;--cm-space-md:1rem;--cm-space-lg:2rem;--cm-space-xl:4rem;--cm-space-2xl:6rem;--cm-radius:.25rem;--cm-rule:1px;--cm-ease:cubic-bezier(.16, .7, .3, 1);--cm-dur-quick:.16s;--cm-dur-reveal:.42s;--cm-dur-warp:.9s;--cm-z-base:1;--cm-z-raised:10;--cm-z-sticky:200;--cm-z-panel:400;--cm-ground:#070b1c;--cm-ground-2:#101a3e;--cm-hairline:#24325c;--cm-hairline-soft:#17203f;--cm-ink:#eef2fa;--cm-ink-2:#9aa8c4;--cm-ink-3:#7d8aa8;--cm-star:#e89b2e;--cm-star-high:#f6d087;--cm-orbit:#82abec;--cm-orbit-deep:#2b4d96;--cm-orbit-low:#14264a;--cm-error:oklch(72% .16 28);--cm-scrim:color-mix(in srgb, var(--cm-ground) 82%, transparent);--cm-sidebar-width:min(19rem, 82vw);--cm-sky:#131f4b;--cm-sky-glow:#2a4b91;--cm-node-unlit:#7381a2;--cm-node-mid:#8e9ab4;--cm-node-bright:#a9b1c5;--cm-star-cool:#96b4ec;--cm-star-pale:#d6def0;--cm-route-possible:#92a0c2;--cm-route:#607198;--cm-neb-python:#70a690;--cm-neb-js:#a197b9;--cm-neb-ts:#77a1ba;--cm-neb-go:#62a7ae;--cm-neb-java:#c48c98;--cm-neb-rust:#c38ab2;--cm-neb-csharp:#78a957;--cm-star-halo:#f2efe9;--cm-com-0:#88c3ac;--cm-com-1:#c7acdb;--cm-com-2:#acbd8a;--cm-com-3:#89bfca;--cm-com-4:#dea9b7;--cm-com-5:#caafbd;--cm-com-6:#7cc69b;--cm-com-7:#b9b0e0;--cm-label-plate:#090e1cd1;--cm-label-ink:#d6dbe7}*{box-sizing:border-box}html,body,#root{width:100%;min-height:100%;margin:0;overflow-x:clip}html{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}body{background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-body);font-size:var(--cm-text-base);line-height:1.55}button,output{font:inherit}button:focus-visible,[href]:focus-visible,[tabindex]:focus-visible,input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:3px}.app-shell{background:var(--cm-ground);width:100%;height:100dvh;min-height:100dvh;color:var(--cm-ink);grid-template-rows:auto minmax(0,1fr) auto auto;grid-template-columns:minmax(0,1fr);display:grid;position:relative;overflow:hidden}.instrument-rail{z-index:calc(var(--cm-z-panel) + 2);align-items:center;gap:var(--cm-space-sm) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-left));border-block-end:1px solid var(--cm-hairline);background:var(--cm-ground);grid-row:1;grid-template-columns:minmax(0,1fr) auto;display:grid;position:relative}.brand-lockup{align-items:center;gap:var(--cm-space-sm);min-width:0;max-width:18rem;display:flex}.brand-lockup div{min-width:0;display:grid}.brand-lockup strong{font-family:var(--cm-font-display);letter-spacing:-.02em;text-overflow:ellipsis;white-space:nowrap;font-weight:700;overflow:hidden}.brand-lockup span:not(.brand-mark),.home-readout,.location{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.brand-mark{width:var(--cm-space-md);height:var(--cm-space-md);border:1px solid var(--cm-ink-2);background:var(--cm-ink);border-radius:50%}.location{grid-area:2/1/auto/-1;margin:0}.rail-overflow{grid-area:1/2;justify-self:end}.mobile-menu-trigger{min-width:44px;min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;place-items:center;font-weight:600;display:grid}.rail-overflow__panel{z-index:var(--cm-z-panel);gap:var(--cm-space-md);max-height:calc(100dvh - 5rem);padding:var(--cm-space-md);border-block:1px solid var(--cm-hairline);background:var(--cm-ground-2);display:none;position:absolute;inset-block-start:100%;inset-inline:0;overflow-y:auto;box-shadow:0 1rem 2.5rem #00000061}.rail-overflow[data-open] .rail-overflow__panel{display:grid}.instrument-rail:has(.rail-overflow[data-open]){z-index:calc(var(--cm-z-panel) + 2)}@media not all and (width>=64rem){.rail-overflow__panel .rail-actions,.rail-overflow__panel .rail-controls{grid-area:auto;justify-content:start}}.rail-action{min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;white-space:nowrap;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}@media (hover:hover) and (pointer:fine){.rail-action:hover{background:var(--cm-orbit-low)}}.rail-action:active{transform:translateY(1px)}.rail-action:disabled,.rail-action[aria-disabled=true]{opacity:.5;cursor:not-allowed}.rail-action[data-state=loading]{color:var(--cm-ink-2)}.rail-action[data-state=error]{border-color:var(--cm-error)}.rail-action[data-state=success]{border-color:var(--cm-star);color:var(--cm-star)}.rail-actions{justify-content:end;align-items:center;gap:var(--cm-space-sm);flex-wrap:wrap;grid-area:2/1/auto/-1;min-width:0;display:flex}.rail-more{justify-content:end;align-items:center;gap:var(--cm-space-sm);flex-wrap:wrap;grid-area:3/1/auto/-1;min-width:0;display:flex}.rail-controls{align-items:center;gap:var(--cm-space-md);flex-wrap:wrap;grid-area:4/1/auto/-1;min-width:0;display:flex}.rail-trigger__wide{display:none}.switch-project{display:contents}.switch-project[data-confirming]{gap:var(--cm-space-xs);padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);display:grid}.switch-project[data-confirming] p{max-width:26ch;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.switch-project__error{color:var(--cm-error)!important}.switch-project[data-confirming]>div{gap:var(--cm-space-xs);display:flex}.language-focus{align-items:center;gap:var(--cm-space-sm);min-width:0;color:var(--cm-ink-3);scrollbar-width:none;display:flex;overflow-x:auto}.language-focus::-webkit-scrollbar{display:none}.language-focus__label{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none}.language-focus>div{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.language-focus button{justify-content:center;align-items:center;gap:var(--cm-space-xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border:0;border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap;background:0 0;display:inline-flex}.language-focus button:last-child{border-inline-end:0}.language-focus button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-orbit)}.language-focus button small{color:var(--cm-ink-3);font-size:inherit;font-variant-numeric:tabular-nums}@media (hover:hover) and (pointer:fine){.language-focus button:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.language-focus button[aria-pressed=true]:hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-toggle{align-items:center;gap:var(--cm-space-sm);border:0;grid-area:4/1/auto/-1;min-width:0;margin:0;padding:0;display:flex}.mode-toggle__label{float:inline-start;color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none;margin-inline-end:var(--cm-space-sm);padding:0}.mode-toggle__options{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.mode-toggle__options label{align-items:center;gap:var(--cm-space-2xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);display:inline-flex}.mode-toggle__options label:last-child{border-inline-end:0}.mode-toggle__options label:has(input:checked){background:var(--cm-orbit-low);color:var(--cm-orbit)}.mode-toggle__options input{width:1rem;height:1rem;accent-color:var(--cm-orbit);margin:0}@media (hover:hover) and (pointer:fine){.mode-toggle__options label:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.mode-toggle__options label:has(input:checked):hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-gate{width:min(26rem, calc(100% - var(--cm-space-xl)));max-height:min(86%,30rem);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;margin:auto;overflow:auto}.mode-gate::backdrop{background:var(--cm-scrim)}.mode-gate h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin:0;font-style:normal;line-height:1.15}.mode-gate p{max-width:42ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.mode-gate__options{gap:var(--cm-space-sm);margin-block-start:var(--cm-space-lg);display:grid}.mode-gate__options button{min-height:52px;padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;font:inherit;text-align:start;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease);font-weight:600}@media (hover:hover) and (pointer:fine){.mode-gate__options button:hover{background:var(--cm-orbit-low);color:var(--cm-ink)}}.mode-gate__options button:active{transform:translateY(1px)}.map-stage{background:var(--cm-ground);grid-row:2;min-width:0;max-width:100%;min-height:0;position:relative;overflow:clip}.chart-stage{background:var(--cm-ground);grid-row:2;min-width:0;min-height:0;position:relative;overflow:hidden}.chart-stage .star-chart-screen{height:100%}.galaxy-frame,.galaxy-canvas{z-index:var(--cm-z-base);position:absolute;inset:0}.galaxy-frame{overflow:hidden}.galaxy-canvas canvas{display:block}.keyboard-focus{max-width:min(34rem, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-sm) var(--cm-space-md);border-inline-start:2px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);position:absolute;inset-block-end:var(--cm-space-md);inset-inline-start:var(--cm-space-md)}.orientation-bar{z-index:var(--cm-z-raised);gap:var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);pointer-events:none;flex-wrap:wrap;margin:0;display:flex;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-bar>*+:before{content:"· ";color:var(--cm-hairline)}.orientation-bar__charted{color:var(--cm-ink-2)}.index-sidebar{z-index:var(--cm-z-panel);width:var(--cm-sidebar-width);border-inline-end:1px solid var(--cm-hairline);background:var(--cm-ground-2);flex-direction:column;display:flex;position:absolute;inset-block:0;inset-inline-start:0}@media (width>=60rem){:is(.map-stage:has(.index-sidebar) .galaxy-frame,.map-stage:has(.index-sidebar) .map-view){inset-inline-start:var(--cm-sidebar-width)}:is(.map-stage:has(.index-sidebar) .orientation-bar,.map-stage:has(.index-sidebar) .orientation-copy){inset-inline-start:calc(var(--cm-sidebar-width) + var(--cm-space-md))}}.index-sidebar>header{justify-content:space-between;align-items:center;gap:var(--cm-space-sm);padding:var(--cm-space-sm) var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:flex}.index-sidebar h2{color:var(--cm-ink);font-size:var(--cm-text-sm);letter-spacing:.08em;text-transform:uppercase;margin:0}.index-sidebar>header button{border-radius:var(--cm-radius);min-width:32px;min-height:32px;color:var(--cm-ink-2);font-size:var(--cm-text-lg);cursor:pointer;background:0 0;border:1px solid #0000;line-height:1}.index-sidebar>header button:hover,.index-sidebar>header button:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar__scroll{flex:1;padding-block-end:var(--cm-space-lg);overflow-y:auto}.index-sidebar section{padding-block-start:var(--cm-space-sm)}.index-sidebar h3{padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;margin:0;font-weight:400;overflow:hidden}.index-sidebar ul{margin:0;padding:0;list-style:none}.index-sidebar li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.index-sidebar li button span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.index-sidebar li button:hover,.index-sidebar li button:focus-visible{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.index-sidebar li button[aria-current=true]{border-inline-start-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar li button[data-lit] span{color:var(--cm-star-high)}.index-sidebar li em{color:var(--cm-ink-3);font-size:var(--cm-text-xs);font-style:normal}.module-finder{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);width:min(34rem,92vw);max-height:70vh;color:var(--cm-ink);padding:0}.module-finder::backdrop{background:var(--cm-scrim)}.module-finder input{width:100%;padding:var(--cm-space-md);border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-base);background:0 0}.module-finder input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:-2px}.module-finder ul{max-height:50vh;padding:var(--cm-space-2xs) 0;margin:0;list-style:none;overflow-y:auto}.module-finder li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:36px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.module-finder li button[data-active]{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.module-finder li strong{font-weight:400}.module-finder li small{color:var(--cm-ink-3);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.module-finder li em{color:var(--cm-star-high);font-style:normal}.module-finder__empty{padding:var(--cm-space-md);color:var(--cm-ink-3);font-size:var(--cm-text-sm);margin:0}.rail-action kbd{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin-inline-start:var(--cm-space-2xs)}.rail-action--toggle[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.orientation-copy{z-index:var(--cm-z-raised);max-width:min(28rem, calc(100% - var(--cm-space-lg)));pointer-events:none;position:absolute;inset-block-start:clamp(var(--cm-space-lg), 8vh, var(--cm-space-2xl));inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-copy--system{inset-block-start:var(--cm-space-lg)}.orientation-copy h1,.study-preview h1,.load-state h1,.webgl-error h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;font-weight:700;line-height:1.08}.orientation-copy p,.study-preview p{max-width:55ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.orientation-copy .system-orbit-note{align-items:center;gap:var(--cm-space-2xs) var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);flex-wrap:wrap;display:flex}.system-orbit-note>span{color:var(--cm-ink-2);text-transform:uppercase;letter-spacing:.08em}.system-orbit-note i{border-inline-start:1.5rem solid var(--cm-route);color:var(--cm-ink-2);padding-inline-start:var(--cm-space-sm);font-style:normal;line-height:1}.system-orbit-note i[data-unproven]{border-inline-start-color:var(--cm-hairline-soft);text-underline-offset:.22em;-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.system-orbit-note small{color:var(--cm-ink-3);font-size:inherit;flex-basis:100%}.orientation-copy--inline{z-index:auto;pointer-events:auto;flex-direction:column;flex:none;max-width:none;display:flex;position:static}.orientation-copy--inline h1{font-size:var(--cm-text-lg)}.orientation-copy--inline p{font-size:var(--cm-text-sm);margin-block-start:var(--cm-space-2xs)}.orientation-copy__actions{gap:var(--cm-space-sm);flex-wrap:wrap;align-items:center;margin-block-start:var(--cm-space-sm);display:flex}.orientation-copy__actions .check-launch{margin-block-start:0}.check-launch--read{border-color:var(--cm-hairline);color:var(--cm-ink)}.check-launch--read:hover,.check-launch--read:focus-visible{border-color:var(--cm-orbit);color:var(--cm-orbit)}.check-launch,.check-primary,.check-close{border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);min-height:44px;color:var(--cm-orbit);cursor:pointer;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}.check-launch{padding-inline:var(--cm-space-md);pointer-events:auto;margin-block-start:var(--cm-space-md);position:relative}.check-primary{padding-inline:var(--cm-space-lg);justify-self:start;margin-block-start:var(--cm-space-sm)}.check-submit-bar{z-index:1;padding-block:var(--cm-space-xs) var(--cm-space-md);background:var(--cm-ground-2);margin-block-end:calc(-1 * var(--cm-space-lg));display:grid;position:sticky;inset-block-end:calc(-1 * var(--cm-space-lg))}.check-submit-bar .check-primary{margin-block-start:0}.active-check :is(fieldset,.check-feedback){scroll-margin-block-end:5rem}.check-close{padding-inline:var(--cm-space-md);border-color:var(--cm-hairline);color:var(--cm-ink-2)}@media (hover:hover) and (pointer:fine){.check-launch:hover,.check-primary:hover,.check-close:hover{background:var(--cm-orbit-low);color:var(--cm-ink)}}.check-launch:active,.check-primary:active,.check-close:active{transform:translateY(1px)}.check-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.legend-toggle{z-index:var(--cm-z-sticky);min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-end:var(--cm-space-md)}.legend-toggle:hover,.legend-toggle:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.legend-toggle[aria-expanded=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.map-legend{--cm-legend-top:calc(var(--cm-space-md) + 40px);z-index:var(--cm-z-sticky);max-width:min(38rem, calc(100% - 2 * var(--cm-space-md)));max-height:min(60vh, 30rem, calc(100dvh - 124px - var(--cm-legend-top) - var(--cm-space-md)));gap:var(--cm-space-2xs) var(--cm-space-md);padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);--cm-scroll-cover:var(--cm-ground-2);background-color:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);grid-template-columns:minmax(0,1fr);display:none;position:absolute;inset-block-start:var(--cm-legend-top);inset-inline-end:var(--cm-space-md);overflow-y:auto;box-shadow:0 16px 40px #04081452}.map-legend:not([hidden]){display:grid}.map-stage:has(.map-view) .map-legend{--cm-legend-top:calc(var(--cm-space-md) + 40px + 44px)}.map-legend span{align-items:center;gap:var(--cm-space-sm);white-space:normal;min-width:0;display:inline-flex}.legend-dot{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:50%;display:inline-block}.legend-dot--dim{background:var(--cm-ink-3)}.legend-dot--lit{background:var(--cm-star-high)}.legend-dot--partial{background:var(--cm-route-possible);clip-path:polygon(0 0,100% 0,100% 100%);border-radius:0}.legend-route{width:var(--cm-space-md);border-block-start:2px solid var(--cm-route)}.legend-route--possible{border-block-start-color:var(--cm-route-possible)}.partial-summary,.unsupported-summary{border-inline-start:2px solid var(--cm-route-possible);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);color:var(--cm-ink)!important}.entrypoint-picker{z-index:var(--cm-z-panel);width:min(36rem, calc(100vw - var(--cm-space-xl)));max-height:min(80dvh,42rem);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);background:var(--cm-ground-2);color:var(--cm-ink);animation:entrypoint-enter var(--cm-dur-reveal) var(--cm-ease) both}.entrypoint-picker[open]{flex-direction:column;display:flex;overflow:hidden}.entrypoint-picker::backdrop{background:color-mix(in srgb, var(--cm-ground) 88%, transparent)}.entrypoint-picker>p:first-child{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.entrypoint-picker h1{margin:var(--cm-space-sm) 0 0;overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);line-height:1.1}.entrypoint-picker>p:not(:first-child){margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.entrypoint-count{margin-block:var(--cm-space-md) 0;color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.entrypoint-scroll{min-height:0;border-block-start:1px solid var(--cm-hairline);flex:auto;margin-block-start:var(--cm-space-sm);overflow-y:auto}@media (width<=39.999rem),(height<=44rem){.entrypoint-picker{width:calc(100vw - (2 * var(--cm-space-sm)));height:calc(100dvh - (2 * var(--cm-space-sm)));max-height:none;padding:var(--cm-space-md);animation-name:entrypoint-enter-reduced}.entrypoint-scroll{flex-basis:min(10rem,28dvh);min-height:min(7.5rem,22dvh)}}@media (height<=32rem){.entrypoint-picker{padding:var(--cm-space-sm)}.entrypoint-picker h1{font-size:var(--cm-text-lg);margin-block-start:var(--cm-space-xs)}.entrypoint-picker>p:not(:first-child),.entrypoint-count,.entrypoint-continue{margin-block-start:var(--cm-space-xs)}.entrypoint-picker>p:not(:first-child){font-size:var(--cm-text-xs);line-height:1.3}.entrypoint-scroll{flex-basis:min(6rem,24dvh);min-height:min(4rem,18dvh)}}.entrypoint-scroll details{border-block-end:1px solid var(--cm-hairline)}.entrypoint-scroll summary{justify-content:space-between;align-items:baseline;gap:var(--cm-space-sm);padding:var(--cm-space-sm) 0;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;display:flex}.entrypoint-scroll summary small{color:var(--cm-ink-3)}.entrypoint-candidates{border-block-start:1px solid var(--cm-hairline)}.entrypoint-candidates button{gap:var(--cm-space-xs);width:100%;min-height:58px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.entrypoint-candidates button span{overflow-wrap:anywhere;font-family:var(--cm-font-mono)}.entrypoint-candidates button small{color:var(--cm-ink-3);font-family:var(--cm-font-mono)}@media (hover:hover) and (pointer:fine){.entrypoint-candidates button:hover{color:var(--cm-orbit)}}.entrypoint-continue{width:100%;min-height:44px;padding:var(--cm-space-xs) 0 0;border:0;border-block-start:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;text-underline-offset:3px;background:0 0;flex:none;margin-block-start:var(--cm-space-md);text-decoration:underline}.entrypoint-error{color:var(--cm-error)!important}.illumination-pulse{z-index:var(--cm-z-raised);color:var(--cm-star);pointer-events:none;animation:illumination-pulse .42s var(--cm-ease) both;justify-items:center;display:grid;position:absolute;inset-block-start:50%;inset-inline-start:25%;transform:translate(-50%,-50%)}.illumination-pulse span{filter:drop-shadow(0 0 18px var(--cm-star));font-size:clamp(3rem,8vw,6rem);line-height:1}.illumination-pulse strong{color:var(--cm-ink);font-family:var(--cm-font-display)}.structural-summary p{max-width:62ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink)}.mini-constellation{width:100%;max-width:22rem;height:auto;margin-block-start:var(--cm-space-md)}.mini-constellation line{stroke:var(--cm-route);stroke-width:1px}.mini-constellation__name{fill:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:9px}.mini-constellation circle{fill:var(--cm-ink-3)}.mini-constellation__self{fill:var(--cm-orbit)}.connections h3{margin:var(--cm-space-lg) 0 0;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;font-weight:500}.connection-list{margin:var(--cm-space-xs) 0 0;border-block-start:1px solid var(--cm-hairline);padding:0;list-style:none}.connection-list button{gap:var(--cm-space-2xs);width:100%;min-height:52px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.connection-name{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.connection-meta{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}@media (hover:hover) and (pointer:fine){.connection-list button:hover .connection-name{color:var(--cm-orbit)}}.load-state .check-primary,.study-notice .check-primary{justify-self:start;margin-block-start:var(--cm-space-md)}.study-preview{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:72%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background-color:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.check-panel{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:76%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background-color:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.study-preview,.check-panel,.star-chart-screen,.module-finder ul,.index-sidebar__scroll,.map-legend,.map-view{--cm-scroll-cover:var(--cm-ground-2);background-image:linear-gradient(var(--cm-scroll-cover) 30%, transparent), linear-gradient(transparent, var(--cm-scroll-cover) 70%), radial-gradient(farthest-side at 50% 0, #0000008c, transparent), radial-gradient(farthest-side at 50% 100%, #0000008c, transparent);background-position:0 0,0 100%,0 0,0 100%;background-repeat:no-repeat;background-size:100% 2.5rem,100% 2.5rem,100% .85rem,100% .85rem;background-attachment:local,local,scroll,scroll}.star-chart-screen{--cm-scroll-cover:var(--cm-ground)}.check-panel__header{justify-content:space-between;align-items:start;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-lg);display:flex}.check-panel__header p,.check-panel__header h1{margin:0}.check-panel__header p,.check-progress span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-panel__header h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin-block-start:var(--cm-space-xs);line-height:1.1}.check-loading,.check-state,.check-complete,.active-check{margin-block-start:var(--cm-space-lg)}.check-loading,.check-state p,.check-complete p,.active-check fieldset>p{max-width:60ch;color:var(--cm-ink-2)}.check-state h2,.check-complete h2{font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0}.check-state p,.check-complete p{margin:var(--cm-space-sm) 0 0}.check-complete{gap:var(--cm-space-sm);display:grid}.check-complete__star{color:var(--cm-star);font-size:var(--cm-text-display);line-height:1}.check-progress{align-items:center;gap:var(--cm-space-md);grid-template-columns:auto minmax(5rem,1fr);margin-block-end:var(--cm-space-xl);display:grid}.check-progress progress{background:var(--cm-hairline);width:100%;height:2px;color:var(--cm-star);border:0}.check-progress progress::-webkit-progress-bar{background:var(--cm-hairline)}.check-progress progress::-webkit-progress-value{background:var(--cm-star)}.check-progress progress::-moz-progress-bar{background:var(--cm-star)}.active-check{gap:var(--cm-space-lg);display:grid}.active-check fieldset{border:0;min-width:0;margin:0;padding:0}.active-check legend{overflow-wrap:break-word;max-width:100%;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);padding:0;font-weight:700;line-height:1.15}.active-check fieldset>p{margin:var(--cm-space-sm) 0 0}.check-options{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.check-options label{align-items:center;gap:var(--cm-space-md);min-height:52px;padding-block:var(--cm-space-sm);border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;grid-template-columns:auto minmax(0,1fr);display:grid}.check-options label:has(input:checked){color:var(--cm-ink)}.check-options input{width:1rem;height:1rem;accent-color:var(--cm-star);margin:0}.check-options span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.check-feedback{gap:var(--cm-space-xs);padding:var(--cm-space-md);border-inline-start:2px solid var(--cm-error);background:var(--cm-ground);color:var(--cm-ink-2);display:grid}.check-feedback strong{color:var(--cm-ink)}.check-feedback span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-affirmation{align-items:baseline;gap:var(--cm-space-xs);margin:0 0 var(--cm-space-lg);border-inline-start:2px solid var(--cm-star);color:var(--cm-star-high);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);display:flex}.study-preview__path{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);color:var(--cm-orbit)!important}.study-preview__header{display:block}.study-preview dl{gap:var(--cm-space-md);margin:var(--cm-space-lg) 0 0;grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.study-preview dl div{border-block-start:1px solid var(--cm-hairline);padding-block-start:var(--cm-space-sm)}.study-preview dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.study-preview dd{margin:var(--cm-space-2xs) 0 0;font-variant-numeric:tabular-nums}.study-content{gap:var(--cm-space-xl);min-width:0;margin-block-start:var(--cm-space-xl);display:grid}.study-content>*{min-width:0}.study-section-heading{justify-content:space-between;align-items:center;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-sm);display:flex}.study-section-heading h2,.study-notice h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal;line-height:1.15}.study-section-heading span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap}.source-code{width:100%;min-width:0;max-height:22rem;margin:var(--cm-space-md) 0 0;padding:var(--cm-space-sm) 0;border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);counter-reset:source-line;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);tab-size:4;line-height:1.65;list-style:none;overflow:auto}.source-code li{min-width:max-content;padding-inline:var(--cm-space-sm) var(--cm-space-md);grid-template-columns:3.25rem minmax(0,1fr);display:grid}.source-code li:before{content:attr(data-line);color:var(--cm-ink-3);text-align:end;-webkit-user-select:none;user-select:none;padding-inline-end:var(--cm-space-md)}.source-code li:target{background:var(--cm-orbit-low)}.source-code code{font:inherit;white-space:pre}.grounded-explanation>p,.study-notice p,.study-loading,.evidence-list p{max-width:65ch;color:var(--cm-ink-2)}.grounded-explanation>p,.study-notice p,.study-loading{margin:var(--cm-space-md) 0 0}.grounded-explanation h3{margin:var(--cm-space-lg) 0 var(--cm-space-sm);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.source-citation{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-underline-offset:2px;text-decoration-thickness:1px}.source-citation:active{color:var(--cm-ink)}@media (hover:hover) and (pointer:fine){.source-citation:hover{color:var(--cm-ink)}}.source-citation--button{cursor:pointer;background:0 0;border:0;padding:0}.source-citation--button:disabled{color:var(--cm-ink-3);cursor:not-allowed}.evidence-list{gap:var(--cm-space-sm);margin:0;padding:0;list-style:none;display:grid}.evidence-list li,.study-notice{padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground)}.evidence-list p{margin:0 0 var(--cm-space-xs)}.evidence-list strong{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);margin-block-end:var(--cm-space-xs);display:block}.lens-notes{margin-block-start:var(--cm-space-sm);display:grid}.lens-note{gap:var(--cm-space-sm);min-width:0;padding-block:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:grid}.lens-note h3{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.lens-note p{max-width:65ch;margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.lens-note code{min-width:0;padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:pre;display:block;overflow-x:auto}.star-chart-screen{min-width:0;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-xl) max(var(--cm-space-md), env(safe-area-inset-left));background-color:var(--cm-ground);overflow:auto}.star-chart-intro{max-width:72rem;margin-inline:auto;padding-block-end:var(--cm-space-xl);display:block}.star-chart-intro>p:first-child{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;line-height:1.08}.star-chart-intro>p:not(:first-child){max-width:65ch;margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.star-chart-intro dl{gap:var(--cm-space-md);margin:var(--cm-space-xl) 0 0;padding-block:var(--cm-space-md);border-block:1px solid var(--cm-hairline);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.star-chart-intro dt,.concept-row dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro dd{margin:var(--cm-space-xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);font-variant-numeric:tabular-nums}.concept-ledger{border-block-start:1px solid var(--cm-hairline);max-width:72rem;margin-inline:auto}.concept-row{align-items:center;gap:var(--cm-space-lg);min-width:0;padding-block:var(--cm-space-lg);border-block-end:1px solid var(--cm-hairline);grid-template-columns:minmax(10rem,.7fr) minmax(8rem,1.2fr) auto;display:grid}.concept-row h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal}.concept-row>div:first-child>span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.concept-meter{background:var(--cm-hairline);height:2px;overflow:hidden}.concept-meter span{background:var(--cm-star);height:100%;display:block}.concept-row dl{align-items:center;gap:var(--cm-space-lg);margin:0;display:flex}.concept-row dl div{min-width:5rem}.concept-row dd{margin:var(--cm-space-xs) 0 0;font-variant-numeric:tabular-nums}.status-line{z-index:var(--cm-z-sticky);justify-content:space-between;gap:var(--cm-space-2xs) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-sm), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;grid-row:4;display:flex;position:relative}.status-line span{white-space:normal}.status-line span:nth-child(2){display:none}.load-state,.webgl-error{align-content:center;gap:var(--cm-space-md);min-height:100dvh;padding:var(--cm-space-lg);background:var(--cm-ground);color:var(--cm-ink);display:grid}.load-state p,.webgl-error p{max-width:65ch;color:var(--cm-ink-2);margin:0}@keyframes panel-enter{0%{opacity:0;transform:translateY(var(--cm-space-md))}to{opacity:1;transform:translateY(0)}}@keyframes entrypoint-enter{0%{opacity:0;transform:translateY(var(--cm-space-md))}to{opacity:1;transform:translateY(0)}}@keyframes illumination-pulse{0%{opacity:0;transform:translate(-50%,-50%)scale(.75)}45%{opacity:1;transform:translate(-50%,-50%)scale(1.08)}to{opacity:0;transform:translate(-50%,-50%)scale(1)}}@media (width>=40rem){.status-line span{white-space:nowrap;display:inline}.lens-note{gap:var(--cm-space-lg);grid-template-columns:minmax(8rem,.35fr) minmax(0,1fr)}.study-preview{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(48rem,60%);max-height:none;inset-block:0;inset-inline-start:auto}.check-panel{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(42rem,56%);max-height:none;inset-block:0;inset-inline-start:auto}}@media (width>=64rem){.instrument-rail{grid-template-columns:minmax(0,auto) minmax(9rem,1fr) auto auto}.rail-overflow{display:contents}.rail-overflow__panel,.rail-overflow[data-open] .rail-overflow__panel{display:contents;position:static}.location{grid-area:1/2}.rail-action,.home-readout{justify-self:end}.rail-actions{flex-wrap:nowrap;grid-area:1/3;justify-content:flex-end;min-width:max-content}.rail-more{z-index:var(--cm-z-panel);width:max-content;max-width:min(22rem,100%);padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);grid-area:auto;display:none;position:absolute;inset-block-start:100%;inset-inline-end:max(var(--cm-space-md), env(safe-area-inset-right));box-shadow:0 1rem 2.5rem #00000061}.rail-overflow[data-open] .rail-more{display:flex}.mobile-menu-trigger{min-width:0;padding-inline:var(--cm-space-sm);grid-area:1/4;place-self:center end}.rail-trigger__compact{display:none}.rail-trigger__wide{display:inline}.rail-controls{grid-area:2/1/auto/-1;justify-self:center}.language-focus{flex:12rem}}@media (width<=39.999rem){.study-preview{border-block-start:1px solid var(--cm-hairline);max-height:none;position:fixed;inset-block:7.75rem 0}.app-shell:has(.study-preview) .instrument-rail{z-index:calc(var(--cm-z-panel) + 2)}.check-panel{border-block-start:0;max-height:none;position:fixed;inset-block:7.75rem 0;inset-inline:0}.check-panel__header{padding-block-end:var(--cm-space-md)}.check-loading,.check-state,.check-complete,.active-check{margin-block-start:var(--cm-space-md)}.active-check{gap:var(--cm-space-md)}.check-options{margin-block-start:var(--cm-space-md)}}@media (width<=48rem){.illumination-pulse{inset-block-start:35%;inset-inline-start:50%}.star-chart-intro dl{grid-template-columns:1fr}.concept-row{gap:var(--cm-space-md);grid-template-columns:1fr}.concept-row dl{justify-content:space-between}}@media (width>=60rem){.map-stage:has(.map-view) .map-legend{grid-template-columns:repeat(2,auto)}.map-legend span{white-space:nowrap}.chart-stage:has(.index-sidebar) .star-chart-screen{margin-inline-start:var(--cm-sidebar-width)}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.15s!important;animation-duration:.15s!important;animation-iteration-count:1!important}.study-preview,.check-panel,.mode-gate{animation-name:panel-enter-reduced}.entrypoint-picker{animation-name:entrypoint-enter-reduced}.illumination-pulse{animation-name:illumination-pulse-reduced}}@keyframes panel-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes entrypoint-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes illumination-pulse-reduced{0%{opacity:0}50%{opacity:1}to{opacity:0}}.picker-screen{gap:var(--cm-space-lg);min-height:100vh;padding:var(--cm-space-2xl) var(--cm-space-xl);flex-direction:column;max-width:44rem;margin:0 auto;display:flex}.picker-wordmark{font-family:var(--cm-font-display);font-size:var(--cm-text-sm);letter-spacing:.2em;text-transform:uppercase;color:var(--cm-ink-3)}.picker-subtitle{color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.picker-recents ul,.picker-browser ul{margin:var(--cm-space-sm) 0 0;gap:var(--cm-space-2xs);flex-direction:column;padding:0;list-style:none;display:flex}.picker-recents button,.picker-browser ul button{justify-content:space-between;gap:var(--cm-space-sm);width:100%;padding:var(--cm-space-xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);text-align:left;cursor:pointer;display:flex}.picker-recents button:hover,.picker-recents button:focus-visible,.picker-browser ul button:hover,.picker-browser ul button:focus-visible{border-color:var(--cm-orbit)}.picker-recents button{flex-wrap:wrap}.picker-recent-path{overflow-wrap:anywhere;min-width:0}.picker-recent-lit{color:var(--cm-star);white-space:nowrap}.picker-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2);overflow-wrap:anywhere}.picker-scale,.picker-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-error{color:var(--cm-error)}.picker-error p{margin:0}.picker-retry{min-height:44px;padding:var(--cm-space-xs) var(--cm-space-md);border:1px solid var(--cm-error);border-radius:var(--cm-radius);color:var(--cm-ink);cursor:pointer;background:0 0;margin-block-start:var(--cm-space-sm)}.picker-retry:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:2px}.picker-select{padding:var(--cm-space-xs) var(--cm-space-lg);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-base);cursor:pointer;align-self:flex-start}.picker-select:disabled{opacity:.6;cursor:progress}.layer-switcher{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);display:inline-flex;overflow:hidden}.layer-switcher button{padding:var(--cm-space-2xs) var(--cm-space-sm);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.layer-switcher button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-ink)}.map-view{gap:var(--cm-space-sm);padding:var(--cm-space-md);--cm-scroll-cover:var(--cm-ground);background-color:var(--cm-ground);flex-direction:column;display:flex;position:absolute;inset:0;overflow:hidden auto}.map-tabs{gap:var(--cm-space-xs);flex:none;display:flex}.map-tabs button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.map-tabs button[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-ink)}.map-canvas{flex-direction:column;flex:auto;min-block-size:6rem;display:flex;position:relative}.map-zoom{z-index:var(--cm-z-raised);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);gap:1px;display:flex;position:absolute;inset-block-start:var(--cm-space-sm);inset-inline-end:var(--cm-space-sm)}.map-zoom button{min-width:34px;min-height:30px;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.map-zoom button:hover:not(:disabled),.map-zoom button:focus-visible{color:var(--cm-orbit)}.map-zoom button:disabled{color:var(--cm-ink-3);cursor:default}@media (width<=40rem){.map-tabs{flex-wrap:wrap;padding-inline-end:4.5rem}.map-zoom{align-self:flex-end;margin-block-end:var(--cm-space-xs);position:static}.map-canvas{min-block-size:8.5rem}}.map-scroll{overscroll-behavior:contain;cursor:grab;background:linear-gradient(var(--cm-ground) 30%, transparent) 0 0 / 100% 2.5rem local no-repeat, linear-gradient(transparent, var(--cm-ground) 70%) 0 100% / 100% 2.5rem local no-repeat, linear-gradient(to right, var(--cm-ground) 30%, transparent) 0 0 / 2.5rem 100% local no-repeat, linear-gradient(to left, var(--cm-ground) 30%, transparent) 100% 0 / 2.5rem 100% local no-repeat, radial-gradient(farthest-side at 50% 0, #0000008c, transparent) 0 0 / 100% .85rem scroll no-repeat, radial-gradient(farthest-side at 50% 100%, #0000008c, transparent) 0 100% / 100% .85rem scroll no-repeat, radial-gradient(farthest-side at 0 50%, #00000073, transparent) 0 0 / .85rem 100% scroll no-repeat, radial-gradient(farthest-side at 100% 50%, #00000073, transparent) 100% 0 / .85rem 100% scroll no-repeat;flex:auto;overflow:auto}.map-scroll[data-panning]{cursor:grabbing;-webkit-user-select:none;user-select:none}.map-canvas__sized{min-width:100%}.architecture-map,.workflow-tree{min-height:0;display:block}.architecture-map__edges path{color:var(--cm-route);stroke:currentColor;fill:none;stroke-linecap:round;stroke-linejoin:round}.architecture-map__edges path.is-possible,.architecture-map__edges path.is-cycle{color:var(--cm-route-possible)}.architecture-map__arrow{color:var(--cm-route)}.architecture-map__arrow.is-cycle{color:var(--cm-route-possible)}.workflow-tree__edges path{stroke:var(--cm-route);stroke-width:1.2px;fill:none}.workflow-tree__edges path.is-possible{stroke:var(--cm-route-possible)}.architecture-map__box rect{fill:color-mix(in srgb, var(--box-com,var(--cm-ground-2)) 16%, var(--cm-ground-2));stroke:var(--cm-hairline)}.architecture-map__box .box-tint{stroke:none}.architecture-map__box text{fill:var(--cm-ink);font-family:var(--cm-font-mono);font-size:13px}.architecture-map__box .box-meta{fill:var(--cm-ink-3);font-size:11px}.architecture-map__box[data-partial=true] rect:first-of-type{stroke:var(--cm-route-possible)}.architecture-map__box .box-partial{fill:var(--cm-route-possible);stroke:none}.architecture-map__box[data-understood=true] rect:first-of-type{stroke:var(--cm-star-high)}.architecture-map__box[data-home=true] rect:first-of-type{stroke-width:2px}.architecture-map__box[data-reachable=false] rect:first-of-type{stroke-dasharray:4 3}.architecture-map__box:focus-visible rect:first-of-type,.workflow-tree__row:focus-visible circle{outline:2px solid var(--cm-orbit);outline-offset:2px}.architecture-map__box,.workflow-tree__row{cursor:pointer}.workflow-tree__row circle{fill:var(--cm-ink-3)}.workflow-tree__row[data-partial=true] circle,.workflow-tree__row[data-cut] circle{fill:var(--cm-route-possible)}.workflow-tree__row[data-understood=true] circle{fill:var(--cm-star-high)}.workflow-tree__row text{fill:var(--cm-ink);font-family:var(--cm-font-mono);font-size:13px}.workflow-tree__row .row-meta{fill:var(--cm-ink-3);font-size:11px}.architecture-map__box[data-selected=true] rect:first-of-type{outline:2px solid var(--cm-orbit);outline-offset:3px}.workflow-tree__row[data-selected=true] circle{stroke:var(--cm-orbit);stroke-width:2px}.map-note,.map-loading{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);flex:none;margin:0}.map-state{text-align:center;max-width:46ch;color:var(--cm-ink-2);margin:auto}.hint-chip{z-index:calc(var(--cm-z-panel) + 1);align-items:center;gap:var(--cm-space-sm);min-width:0;padding:var(--cm-space-sm) var(--cm-space-md);border-block:1px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-size:var(--cm-text-sm);flex-wrap:wrap;grid-row:3;display:flex;position:static}@media (width<=40rem){.hint-chip{max-block-size:40vh;overflow-y:auto}.hint-chip small{text-overflow:ellipsis;white-space:nowrap;flex:100%;overflow:hidden}}.hint-chip small{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.hint-chip button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.first-flight__system{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-mono)}.first-flight__actions{gap:var(--cm-space-xs);flex-wrap:wrap;margin-inline-start:auto;display:flex}.first-flight__actions button[disabled]{border-color:var(--cm-hairline);color:var(--cm-ink-3);cursor:default}@media (width<=40rem){.first-flight__system,.first-flight__actions{flex:100%}.first-flight__actions{margin-inline-start:0}}.location button{color:var(--cm-orbit);font:inherit;cursor:pointer;background:0 0;border:0;padding:0}.location button[disabled]{color:var(--cm-ink-2);cursor:default}.location button:not([disabled]):hover{text-decoration:underline}.coach-marks{inset-block:auto var(--cm-space-lg);width:min(38ch, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);margin-inline:auto;inset-inline:0}.coach-marks::backdrop{background:var(--cm-scrim)}.coach-marks__progress{margin:0 0 var(--cm-space-2xs);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.coach-marks h1{margin:0 0 var(--cm-space-xs);font-size:var(--cm-text-lg)}.coach-marks__actions{justify-content:space-between;gap:var(--cm-space-sm);margin-block-start:var(--cm-space-md);display:flex}.coach-skip{color:var(--cm-ink-3);cursor:pointer;background:0 0;border:0}.legend-tint{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:2px;display:inline-block}.legend-communities{gap:2px;display:inline-flex}.legend-communities i{width:calc(var(--cm-space-sm) / 1.6);height:var(--cm-space-sm);border-radius:2px;display:inline-block}.legend-communities i:first-child{background:var(--cm-com-0)}.legend-communities i:nth-child(2){background:var(--cm-com-1)}.legend-communities i:nth-child(3){background:var(--cm-com-2)}.legend-communities i:nth-child(4){background:var(--cm-com-3)}.map-note__toggle{border:var(--cm-rule) solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-orbit);font:inherit;font-size:var(--cm-text-xs);padding:var(--cm-space-2xs) var(--cm-space-sm);cursor:pointer;background:0 0}.map-note__toggle:hover,.map-note__toggle:focus-visible{border-color:var(--cm-orbit)}.legend-route--dashed{border-block-start-style:dashed}.legend-size{width:var(--cm-space-md);height:var(--cm-space-sm);background:var(--cm-ink-3);border-radius:50%;display:inline-block}.legend-brightness{width:var(--cm-space-md);height:var(--cm-space-sm);background:linear-gradient(90deg, var(--cm-node-unlit), var(--cm-ink-2));display:inline-block}.app-shell[data-mode=easy]{--cm-text-xs:.8125rem;--cm-text-sm:.9375rem;--cm-text-base:1.125rem;--cm-text-lg:1.375rem;--cm-space-sm:1rem;--cm-space-md:1.375rem;--cm-space-lg:2.5rem;font-size:var(--cm-text-base);line-height:1.7}.app-shell[data-mode=easy] .orientation-copy p,.app-shell[data-mode=easy] .study-preview p,.app-shell[data-mode=easy] .grounded-explanation>p,.app-shell[data-mode=easy] .study-notice p,.app-shell[data-mode=easy] .evidence-list p,.app-shell[data-mode=easy] .lens-note p,.app-shell[data-mode=easy] .active-check fieldset>p,.app-shell[data-mode=easy] .check-state p,.app-shell[data-mode=easy] .check-complete p,.app-shell[data-mode=easy] .check-loading{max-width:46ch}.app-shell[data-mode] .orientation-copy--inline>p{max-width:72ch}.app-shell[data-mode=easy] .language-focus__label,.app-shell[data-mode=easy] .mode-toggle__label{text-transform:none;letter-spacing:normal}.loading-screen{gap:var(--cm-space-md);max-width:44rem;min-height:100vh;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-left));align-content:center;justify-items:start;margin:0 auto;display:grid}.loading-header h1{min-width:0;margin:var(--cm-space-2xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);overflow-wrap:anywhere;line-height:1.15}.loading-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2)}.loading-subtitle{margin:var(--cm-space-xs) 0 0;color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-stages{gap:var(--cm-space-2xs);width:100%;margin:0;padding:0;list-style:none;display:grid}.loading-stages li{justify-content:space-between;gap:var(--cm-space-sm);padding:var(--cm-space-xs) var(--cm-space-sm);border-left:2px solid var(--cm-hairline);color:var(--cm-ink-3);font-size:var(--cm-text-sm);flex-wrap:wrap;display:flex}.loading-stages li[data-state=active]{border-left-color:var(--cm-orbit);color:var(--cm-ink)}.loading-stages li[data-state=done]{border-left-color:var(--cm-orbit-deep);color:var(--cm-ink-2)}.loading-stages small{font-family:var(--cm-font-mono);color:var(--cm-ink-2)}.loading-meter{width:100%;height:var(--cm-space-xs);accent-color:var(--cm-orbit)}.loading-live{color:var(--cm-ink);font-size:var(--cm-text-sm)}.loading-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);width:100%;padding:var(--cm-space-sm);color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-actions{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.loading-actions button{padding:var(--cm-space-xs) var(--cm-space-md)}.picker-scale h2,.picker-failure h2{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base)}.picker-scale-scopes{gap:var(--cm-space-xs);margin:var(--cm-space-sm) 0;flex-wrap:wrap;padding:0;list-style:none;display:flex}.picker-scale-scopes button{align-items:flex-start;gap:var(--cm-space-2xs);min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);cursor:pointer;flex-direction:column;display:flex}.picker-scale-scopes button:hover:not(:disabled),.picker-scale-scopes button:focus-visible{border-color:var(--cm-orbit)}.picker-scale-scopes button:disabled{opacity:.6;cursor:progress}.picker-scale-scopes small{color:var(--cm-ink-2)}.picker-path-entry{gap:var(--cm-space-xs);flex-wrap:wrap;align-items:center;display:flex}.picker-path-entry label{color:var(--cm-ink-2)}.picker-path-entry input{min-width:0;min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-xs);background:var(--cm-ground);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);flex:14rem}.picker-path-entry button{min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-md);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-sm);cursor:pointer}.picker-path-entry button:disabled{opacity:.6;cursor:not-allowed}.picker-failure{border:1px solid var(--cm-error);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-failure>p{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.picker-failure__detail{gap:var(--cm-space-2xs);display:grid}.picker-failure__detail span{color:var(--cm-ink-3);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em}.picker-failure__detail code{max-height:8rem;padding:var(--cm-space-xs);background:var(--cm-ground-2);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);overflow-wrap:anywhere;display:block;overflow:auto}.picker-failure .picker-select{min-height:44px;font-size:var(--cm-text-sm);align-self:flex-start}.progress-reset{align-items:center;gap:var(--cm-space-sm);max-width:72rem;margin:var(--cm-space-lg) auto 0;padding-top:var(--cm-space-md);border-top:1px solid var(--cm-hairline);flex-wrap:wrap;display:flex}.progress-reset p{color:var(--cm-ink-2);font-size:var(--cm-text-sm);margin:0}.progress-reset button{min-height:44px;padding-inline:var(--cm-space-md);font-size:var(--cm-text-sm)}.progress-reset--confirming{justify-items:start;gap:var(--cm-space-sm);display:grid}.progress-reset--confirming>p[role=alert]{max-width:60ch;color:var(--cm-ink)}.progress-reset--confirming>div{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.progress-reset__confirm{border-color:var(--cm-error);color:var(--cm-error)}.progress-reset__error{color:var(--cm-error)}.learning-journey{min-width:0}.journey-overview{gap:var(--cm-space-2xs);margin:var(--cm-space-md) 0 0;padding:0 0 var(--cm-space-xs);scrollbar-width:thin;grid-auto-columns:minmax(4.5rem,1fr);grid-auto-flow:column;list-style:none;display:grid;overflow-x:auto}.journey-overview button{width:100%;min-height:44px;padding:var(--cm-space-xs);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);cursor:pointer;text-align:start;background:0 0;align-content:center;justify-items:start;gap:1px;display:grid}.journey-overview button[aria-current=step]{border-color:var(--cm-orbit);background:var(--cm-orbit-low);color:var(--cm-ink)}.journey-overview button>span,.journey-overview button>small,.journey-position,.journey-citations,.journey-expert-facts,.journey-controls,.journey-break code,.journey-possible span,.journey-candidate-note,.journey-support-scope{font-family:var(--cm-font-mono)}.journey-overview button>span{color:var(--cm-orbit);font-size:var(--cm-text-sm)}.journey-overview button>small{text-transform:uppercase;font-size:.625rem;line-height:1.2}.journey-current{gap:var(--cm-space-sm);padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-inline-start:3px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);margin-block-start:var(--cm-space-sm);display:grid}.journey-position{font-size:var(--cm-text-xs);text-transform:uppercase;color:var(--cm-orbit)!important;margin:0!important}.journey-current h3{font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal}.journey-current>p:not(.journey-position){color:var(--cm-ink-2);margin:0}.journey-citations{gap:var(--cm-space-xs) var(--cm-space-md);color:var(--cm-ink-3);font-size:var(--cm-text-xs);flex-wrap:wrap;display:flex}.journey-citations code,.journey-break code{color:var(--cm-orbit);overflow-wrap:anywhere}.study-preview .journey-expert-facts{gap:var(--cm-space-sm);grid-template-columns:repeat(auto-fit,minmax(8rem,1fr));margin:0}.journey-expert-facts dd{overflow-wrap:anywhere;font-size:var(--cm-text-xs)}.journey-controls{gap:var(--cm-space-xs);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.journey-controls button{min-height:44px;padding:var(--cm-space-xs);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);cursor:pointer;background:0 0}.journey-controls button:nth-child(2){border-color:var(--cm-orbit);color:var(--cm-orbit)}.journey-controls button:disabled{color:var(--cm-ink-3);cursor:not-allowed;opacity:.55}.journey-break,.journey-possible{padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);margin-block-start:var(--cm-space-md)}.journey-break{border-inline-start:3px solid var(--cm-error)}.journey-break p,.journey-possible p{margin:var(--cm-space-xs) 0 0;color:var(--cm-ink-2)}.journey-possible h3{font-family:var(--cm-font-display);font-size:var(--cm-text-base);margin:0;font-style:normal}.journey-possible ul{gap:var(--cm-space-xs);margin:var(--cm-space-md) 0 0;padding:0;list-style:none;display:grid}.journey-possible li{gap:var(--cm-space-2xs);border-block-start:1px solid var(--cm-hairline);padding-block-start:var(--cm-space-xs);display:grid}.journey-possible span,.journey-candidate-note{color:var(--cm-ink-3);font-size:var(--cm-text-xs);overflow-wrap:anywhere}.journey-support{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.journey-support>summary{min-height:44px;padding-block:var(--cm-space-sm);color:var(--cm-orbit);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.journey-support>section{margin-block-start:var(--cm-space-lg)}.journey-support-scope{margin:0}.journey-candidate-note{margin-block-start:var(--cm-space-sm)}.visually-hidden{clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;width:1px!important;height:1px!important;position:absolute!important;overflow:hidden!important}@media (width<=20rem){.study-preview{padding:var(--cm-space-sm) var(--cm-space-md) max(var(--cm-space-sm), env(safe-area-inset-bottom))}.study-content{gap:var(--cm-space-md);margin-block-start:var(--cm-space-xs)}.study-preview dl{gap:var(--cm-space-sm);margin-block-start:var(--cm-space-md)}.journey-current{gap:var(--cm-space-xs);padding:var(--cm-space-xs)}.journey-overview{margin-block-start:var(--cm-space-xs)}.journey-current>p:not(.journey-position){font-size:var(--cm-text-sm);line-height:1.45}.journey-controls{gap:var(--cm-space-2xs)}}@media (width<=22.5rem){.app-shell[data-level=study] .hint-chip{gap:var(--cm-space-xs)}.app-shell[data-level=study] .hint-chip button{padding-inline:var(--cm-space-xs)}.source-study .study-section-heading{gap:var(--cm-space-xs)}.source-study .study-section-heading h2{overflow-wrap:normal;flex:none}.source-study .study-section-heading span{text-overflow:ellipsis;min-width:0;overflow:hidden}}.impact-columns{gap:var(--cm-space-md);grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));display:grid}.impact-column h3{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);letter-spacing:.04em;text-transform:uppercase;margin:0;font-weight:500}.impact-list{margin:var(--cm-space-2xs) 0 0;border-block-start:1px solid var(--cm-hairline);padding:0;list-style:none}.impact-list button{gap:var(--cm-space-2xs);width:100%;min-height:44px;padding:var(--cm-space-xs) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.impact-name{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.impact-meta,.impact-citation{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.impact-citation{overflow-wrap:anywhere}@media (hover:hover) and (pointer:fine){.impact-list button:hover .impact-name{color:var(--cm-orbit)}}.walkthrough-disclosure>summary{min-height:44px;padding:var(--cm-space-xs) 0;color:var(--cm-orbit);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.walkthrough-disclosure>summary:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:2px}.project-summary{margin-block:var(--cm-space-lg);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2)}.project-summary__lead{max-width:60ch;margin:0 0 var(--cm-space-lg);color:var(--cm-ink);font-size:var(--cm-text-lg);line-height:1.4}.project-summary__facts{gap:var(--cm-space-md) var(--cm-space-xl);grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));margin:0;display:grid}.project-summary__facts>div{min-width:0}.project-summary__facts dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.project-summary__facts dd{margin:var(--cm-space-2xs) 0 0;overflow-wrap:break-word;color:var(--cm-ink)}.project-summary__export{min-height:44px;padding:var(--cm-space-xs) var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);cursor:pointer;font:500 var(--cm-text-sm) / 1.3 var(--cm-font-mono);background:0 0;margin-block-start:var(--cm-space-lg)}.project-summary__export:hover{background:color-mix(in srgb, var(--cm-orbit) 10%, transparent)}.project-summary__export:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:3px}.star-chart-section{margin-block:var(--cm-space-xl) 0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg)}
+@font-face{font-family:Zen Kaku Gothic New;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/zen-kaku-gothic-new-latin-400-normal-BEdayliK.woff2)format("woff2"),url(/assets/zen-kaku-gothic-new-latin-400-normal-CPSmNJAU.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/shippori-mincho-latin-500-normal-XI1O8euf.woff2)format("woff2"),url(/assets/shippori-mincho-latin-500-normal-C-QwvIb3.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/shippori-mincho-latin-700-normal-DHcmzUO5.woff2)format("woff2"),url(/assets/shippori-mincho-latin-700-normal-CkoCYOiI.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff)format("woff")}:root{--cm-font-display:"Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif;--cm-font-body:"Zen Kaku Gothic New", "Hiragino Sans", system-ui, sans-serif;--cm-font-mono:"JetBrains Mono", ui-monospace, monospace;--cm-text-xs:.75rem;--cm-text-sm:.875rem;--cm-text-base:1rem;--cm-text-lg:1.25rem;--cm-text-xl:clamp(1.25rem, .5vw + 1.1rem, 1.5rem);--cm-text-display:clamp(1.75rem, 3vw + 1rem, 3.25rem);--cm-space-2xs:.125rem;--cm-space-xs:.5rem;--cm-space-sm:.75rem;--cm-space-md:1rem;--cm-space-lg:2rem;--cm-space-xl:4rem;--cm-space-2xl:6rem;--cm-radius:.25rem;--cm-rule:1px;--cm-ease:cubic-bezier(.16, .7, .3, 1);--cm-dur-quick:.16s;--cm-dur-reveal:.42s;--cm-dur-warp:.9s;--cm-z-base:1;--cm-z-raised:10;--cm-z-sticky:200;--cm-z-panel:400;--cm-ground:#070b1c;--cm-ground-2:#101a3e;--cm-hairline:#24325c;--cm-hairline-soft:#17203f;--cm-ink:#eef2fa;--cm-ink-2:#9aa8c4;--cm-ink-3:#7d8aa8;--cm-star:#e89b2e;--cm-star-high:#f6d087;--cm-orbit:#82abec;--cm-orbit-deep:#2b4d96;--cm-orbit-low:#14264a;--cm-error:oklch(72% .16 28);--cm-scrim:color-mix(in srgb, var(--cm-ground) 82%, transparent);--cm-sidebar-width:min(19rem, 82vw);--cm-sky:#131f4b;--cm-sky-glow:#2a4b91;--cm-node-unlit:#7381a2;--cm-node-mid:#8e9ab4;--cm-node-bright:#a9b1c5;--cm-star-cool:#96b4ec;--cm-star-pale:#d6def0;--cm-route-possible:#92a0c2;--cm-route:#607198;--cm-neb-python:#70a690;--cm-neb-js:#a197b9;--cm-neb-ts:#77a1ba;--cm-neb-go:#62a7ae;--cm-neb-java:#c48c98;--cm-neb-rust:#c38ab2;--cm-neb-csharp:#78a957;--cm-star-halo:#f2efe9;--cm-com-0:#88c3ac;--cm-com-1:#c7acdb;--cm-com-2:#acbd8a;--cm-com-3:#89bfca;--cm-com-4:#dea9b7;--cm-com-5:#caafbd;--cm-com-6:#7cc69b;--cm-com-7:#b9b0e0;--cm-label-plate:#090e1cd1;--cm-label-ink:#d6dbe7}*{box-sizing:border-box}html,body,#root{width:100%;min-height:100%;margin:0;overflow-x:clip}html{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}body{background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-body);font-size:var(--cm-text-base);line-height:1.55}button,output{font:inherit}button:focus-visible,[href]:focus-visible,[tabindex]:focus-visible,input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:3px}.app-shell{background:var(--cm-ground);width:100%;height:100dvh;min-height:100dvh;color:var(--cm-ink);grid-template-rows:auto minmax(0,1fr) auto auto;grid-template-columns:minmax(0,1fr);display:grid;position:relative;overflow:hidden}.instrument-rail{z-index:calc(var(--cm-z-panel) + 2);align-items:center;gap:var(--cm-space-sm) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-left));border-block-end:1px solid var(--cm-hairline);background:var(--cm-ground);grid-row:1;grid-template-columns:minmax(0,1fr) auto;display:grid;position:relative}.brand-lockup{align-items:center;gap:var(--cm-space-sm);min-width:0;max-width:18rem;display:flex}.brand-lockup div{min-width:0;display:grid}.brand-lockup strong{font-family:var(--cm-font-display);letter-spacing:-.02em;text-overflow:ellipsis;white-space:nowrap;font-weight:700;overflow:hidden}.brand-lockup span:not(.brand-mark),.home-readout,.location{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.brand-mark{width:var(--cm-space-md);height:var(--cm-space-md);border:1px solid var(--cm-ink-2);background:var(--cm-ink);border-radius:50%}.location{grid-area:2/1/auto/-1;margin:0}.rail-overflow{grid-area:1/2;justify-self:end}.mobile-menu-trigger{min-width:44px;min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;place-items:center;font-weight:600;display:grid}.rail-overflow__panel{z-index:var(--cm-z-panel);gap:var(--cm-space-md);max-height:calc(100dvh - 5rem);padding:var(--cm-space-md);border-block:1px solid var(--cm-hairline);background:var(--cm-ground-2);display:none;position:absolute;inset-block-start:100%;inset-inline:0;overflow-y:auto;box-shadow:0 1rem 2.5rem #00000061}.rail-overflow[data-open] .rail-overflow__panel{display:grid}.instrument-rail:has(.rail-overflow[data-open]){z-index:calc(var(--cm-z-panel) + 2)}@media not all and (width>=64rem){.rail-overflow__panel .rail-actions,.rail-overflow__panel .rail-controls{grid-area:auto;justify-content:start}}.rail-action{min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;white-space:nowrap;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}@media (hover:hover) and (pointer:fine){.rail-action:hover{background:var(--cm-orbit-low)}}.rail-action:active{transform:translateY(1px)}.rail-action:disabled,.rail-action[aria-disabled=true]{opacity:.5;cursor:not-allowed}.rail-action[data-state=loading]{color:var(--cm-ink-2)}.rail-action[data-state=error]{border-color:var(--cm-error)}.rail-action[data-state=success]{border-color:var(--cm-star);color:var(--cm-star)}.rail-actions{justify-content:end;align-items:center;gap:var(--cm-space-sm);flex-wrap:wrap;grid-area:2/1/auto/-1;min-width:0;display:flex}.rail-more{justify-content:end;align-items:center;gap:var(--cm-space-sm);flex-wrap:wrap;grid-area:3/1/auto/-1;min-width:0;display:flex}.rail-controls{align-items:center;gap:var(--cm-space-md);flex-wrap:wrap;grid-area:4/1/auto/-1;min-width:0;display:flex}.rail-trigger__wide{display:none}.switch-project{display:contents}.switch-project[data-confirming]{gap:var(--cm-space-xs);padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);display:grid}.switch-project[data-confirming] p{max-width:26ch;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.switch-project__error{color:var(--cm-error)!important}.switch-project[data-confirming]>div{gap:var(--cm-space-xs);display:flex}.language-focus{align-items:center;gap:var(--cm-space-sm);min-width:0;color:var(--cm-ink-3);scrollbar-width:none;display:flex;overflow-x:auto}.language-focus::-webkit-scrollbar{display:none}.language-focus__label{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none}.language-focus>div{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.language-focus button{justify-content:center;align-items:center;gap:var(--cm-space-xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border:0;border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap;background:0 0;display:inline-flex}.language-focus button:last-child{border-inline-end:0}.language-focus button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-orbit)}.language-focus button small{color:var(--cm-ink-3);font-size:inherit;font-variant-numeric:tabular-nums}@media (hover:hover) and (pointer:fine){.language-focus button:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.language-focus button[aria-pressed=true]:hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-toggle{align-items:center;gap:var(--cm-space-sm);border:0;grid-area:4/1/auto/-1;min-width:0;margin:0;padding:0;display:flex}.mode-toggle__label{float:inline-start;color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none;margin-inline-end:var(--cm-space-sm);padding:0}.mode-toggle__options{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.mode-toggle__options label{align-items:center;gap:var(--cm-space-2xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);display:inline-flex}.mode-toggle__options label:last-child{border-inline-end:0}.mode-toggle__options label:has(input:checked){background:var(--cm-orbit-low);color:var(--cm-orbit)}.mode-toggle__options input{width:1rem;height:1rem;accent-color:var(--cm-orbit);margin:0}@media (hover:hover) and (pointer:fine){.mode-toggle__options label:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.mode-toggle__options label:has(input:checked):hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-gate{width:min(26rem, calc(100% - var(--cm-space-xl)));max-height:min(86%,30rem);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;margin:auto;overflow:auto}.mode-gate::backdrop{background:var(--cm-scrim)}.mode-gate h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin:0;font-style:normal;line-height:1.15}.mode-gate p{max-width:42ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.mode-gate__options{gap:var(--cm-space-sm);margin-block-start:var(--cm-space-lg);display:grid}.mode-gate__options button{min-height:52px;padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;font:inherit;text-align:start;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease);font-weight:600}@media (hover:hover) and (pointer:fine){.mode-gate__options button:hover{background:var(--cm-orbit-low);color:var(--cm-ink)}}.mode-gate__options button:active{transform:translateY(1px)}.map-stage{background:var(--cm-ground);grid-row:2;min-width:0;max-width:100%;min-height:0;position:relative;overflow:clip}.chart-stage{background:var(--cm-ground);grid-row:2;min-width:0;min-height:0;position:relative;overflow:hidden}.chart-stage .star-chart-screen{height:100%}.galaxy-frame,.galaxy-canvas{z-index:var(--cm-z-base);position:absolute;inset:0}.galaxy-frame{overflow:hidden}.galaxy-canvas canvas{display:block}.keyboard-focus{max-width:min(34rem, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-sm) var(--cm-space-md);border-inline-start:2px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);position:absolute;inset-block-end:var(--cm-space-md);inset-inline-start:var(--cm-space-md)}.orientation-bar{z-index:var(--cm-z-raised);gap:var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);pointer-events:none;flex-wrap:wrap;margin:0;display:flex;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-bar>*+:before{content:"· ";color:var(--cm-hairline)}.orientation-bar__charted{color:var(--cm-ink-2)}.index-sidebar{z-index:var(--cm-z-panel);width:var(--cm-sidebar-width);border-inline-end:1px solid var(--cm-hairline);background:var(--cm-ground-2);flex-direction:column;display:flex;position:absolute;inset-block:0;inset-inline-start:0}@media (width>=60rem){:is(.map-stage:has(.index-sidebar) .galaxy-frame,.map-stage:has(.index-sidebar) .map-view){inset-inline-start:var(--cm-sidebar-width)}:is(.map-stage:has(.index-sidebar) .orientation-bar,.map-stage:has(.index-sidebar) .orientation-copy){inset-inline-start:calc(var(--cm-sidebar-width) + var(--cm-space-md))}}.index-sidebar>header{justify-content:space-between;align-items:center;gap:var(--cm-space-sm);padding:var(--cm-space-sm) var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:flex}.index-sidebar h2{color:var(--cm-ink);font-size:var(--cm-text-sm);letter-spacing:.08em;text-transform:uppercase;margin:0}.index-sidebar>header button{border-radius:var(--cm-radius);min-width:32px;min-height:32px;color:var(--cm-ink-2);font-size:var(--cm-text-lg);cursor:pointer;background:0 0;border:1px solid #0000;line-height:1}.index-sidebar>header button:hover,.index-sidebar>header button:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar__scroll{flex:1;padding-block-end:var(--cm-space-lg);overflow-y:auto}.index-sidebar section{padding-block-start:var(--cm-space-sm)}.index-sidebar h3{padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;margin:0;font-weight:400;overflow:hidden}.index-sidebar ul{margin:0;padding:0;list-style:none}.index-sidebar li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.index-sidebar li button span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.index-sidebar li button:hover,.index-sidebar li button:focus-visible{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.index-sidebar li button[aria-current=true]{border-inline-start-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar li button[data-lit] span{color:var(--cm-star-high)}.index-sidebar li em{color:var(--cm-ink-3);font-size:var(--cm-text-xs);font-style:normal}.module-finder{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);width:min(34rem,92vw);max-height:70vh;color:var(--cm-ink);padding:0}.module-finder::backdrop{background:var(--cm-scrim)}.module-finder input{width:100%;padding:var(--cm-space-md);border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-base);background:0 0}.module-finder input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:-2px}.module-finder ul{max-height:50vh;padding:var(--cm-space-2xs) 0;margin:0;list-style:none;overflow-y:auto}.module-finder li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:36px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.module-finder li button[data-active]{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.module-finder li strong{font-weight:400}.module-finder li small{color:var(--cm-ink-3);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.module-finder li em{color:var(--cm-star-high);font-style:normal}.module-finder__empty{padding:var(--cm-space-md);color:var(--cm-ink-3);font-size:var(--cm-text-sm);margin:0}.rail-action kbd{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin-inline-start:var(--cm-space-2xs)}.rail-action--toggle[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.orientation-copy{z-index:var(--cm-z-raised);max-width:min(28rem, calc(100% - var(--cm-space-lg)));pointer-events:none;position:absolute;inset-block-start:clamp(var(--cm-space-lg), 8vh, var(--cm-space-2xl));inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-copy--system{inset-block-start:var(--cm-space-lg)}.orientation-copy h1,.study-preview h1,.load-state h1,.webgl-error h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;font-weight:700;line-height:1.08}.orientation-copy p,.study-preview p{max-width:55ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.orientation-copy .system-orbit-note{align-items:center;gap:var(--cm-space-2xs) var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);flex-wrap:wrap;display:flex}.system-orbit-note>span{color:var(--cm-ink-2);text-transform:uppercase;letter-spacing:.08em}.system-orbit-note i{border-inline-start:1.5rem solid var(--cm-route);color:var(--cm-ink-2);padding-inline-start:var(--cm-space-sm);font-style:normal;line-height:1}.system-orbit-note i[data-unproven]{border-inline-start-color:var(--cm-hairline-soft);text-underline-offset:.22em;-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.system-orbit-note small{color:var(--cm-ink-3);font-size:inherit;flex-basis:100%}.orientation-copy--inline{z-index:auto;pointer-events:auto;flex-direction:column;flex:none;max-width:none;display:flex;position:static}.orientation-copy--inline h1{font-size:var(--cm-text-lg)}.orientation-copy--inline p{font-size:var(--cm-text-sm);margin-block-start:var(--cm-space-2xs)}.orientation-copy__actions{gap:var(--cm-space-sm);flex-wrap:wrap;align-items:center;margin-block-start:var(--cm-space-sm);display:flex}.orientation-copy__actions .check-launch{margin-block-start:0}.check-launch--read{border-color:var(--cm-hairline);color:var(--cm-ink)}.check-launch--read:hover,.check-launch--read:focus-visible{border-color:var(--cm-orbit);color:var(--cm-orbit)}.check-launch,.check-primary,.check-close{border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);min-height:44px;color:var(--cm-orbit);cursor:pointer;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}.check-launch{padding-inline:var(--cm-space-md);pointer-events:auto;margin-block-start:var(--cm-space-md);position:relative}.check-primary{padding-inline:var(--cm-space-lg);justify-self:start;margin-block-start:var(--cm-space-sm)}.check-submit-bar{z-index:1;padding-block:var(--cm-space-xs) var(--cm-space-md);background:var(--cm-ground-2);margin-block-end:calc(-1 * var(--cm-space-lg));display:grid;position:sticky;inset-block-end:calc(-1 * var(--cm-space-lg))}.check-submit-bar .check-primary{margin-block-start:0}.active-check :is(fieldset,.check-feedback){scroll-margin-block-end:5rem}.check-close{padding-inline:var(--cm-space-md);border-color:var(--cm-hairline);color:var(--cm-ink-2)}@media (hover:hover) and (pointer:fine){.check-launch:hover,.check-primary:hover,.check-close:hover{background:var(--cm-orbit-low);color:var(--cm-ink)}}.check-launch:active,.check-primary:active,.check-close:active{transform:translateY(1px)}.check-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.legend-toggle{z-index:var(--cm-z-sticky);min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-end:var(--cm-space-md)}.legend-toggle:hover,.legend-toggle:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.legend-toggle[aria-expanded=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.map-legend{--cm-legend-top:calc(var(--cm-space-md) + 40px);z-index:var(--cm-z-sticky);max-width:min(38rem, calc(100% - 2 * var(--cm-space-md)));max-height:min(60vh, 30rem, calc(100dvh - 124px - var(--cm-legend-top) - var(--cm-space-md)));gap:var(--cm-space-2xs) var(--cm-space-md);padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);--cm-scroll-cover:var(--cm-ground-2);background-color:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);grid-template-columns:minmax(0,1fr);display:none;position:absolute;inset-block-start:var(--cm-legend-top);inset-inline-end:var(--cm-space-md);overflow-y:auto;box-shadow:0 16px 40px #04081452}.map-legend:not([hidden]){display:grid}.map-stage:has(.map-view) .map-legend{--cm-legend-top:calc(var(--cm-space-md) + 40px + 44px)}.map-legend span{align-items:center;gap:var(--cm-space-sm);white-space:normal;min-width:0;display:inline-flex}.legend-dot{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:50%;display:inline-block}.legend-dot--dim{background:var(--cm-ink-3)}.legend-dot--lit{background:var(--cm-star-high)}.legend-dot--partial{background:var(--cm-route-possible);clip-path:polygon(0 0,100% 0,100% 100%);border-radius:0}.legend-route{width:var(--cm-space-md);border-block-start:2px solid var(--cm-route)}.legend-route--possible{border-block-start-color:var(--cm-route-possible)}.partial-summary,.unsupported-summary{border-inline-start:2px solid var(--cm-route-possible);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);color:var(--cm-ink)!important}.entrypoint-picker{z-index:var(--cm-z-panel);width:min(36rem, calc(100vw - var(--cm-space-xl)));max-height:min(80dvh,42rem);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);background:var(--cm-ground-2);color:var(--cm-ink);animation:entrypoint-enter var(--cm-dur-reveal) var(--cm-ease) both}.entrypoint-picker[open]{flex-direction:column;display:flex;overflow:hidden}.entrypoint-picker::backdrop{background:color-mix(in srgb, var(--cm-ground) 88%, transparent)}.entrypoint-picker>p:first-child{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.entrypoint-picker h1{margin:var(--cm-space-sm) 0 0;overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);line-height:1.1}.entrypoint-picker>p:not(:first-child){margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.entrypoint-count{margin-block:var(--cm-space-md) 0;color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.entrypoint-scroll{min-height:0;border-block-start:1px solid var(--cm-hairline);flex:auto;margin-block-start:var(--cm-space-sm);overflow-y:auto}@media (width<=39.999rem),(height<=44rem){.entrypoint-picker{width:calc(100vw - (2 * var(--cm-space-sm)));height:calc(100dvh - (2 * var(--cm-space-sm)));max-height:none;padding:var(--cm-space-md);animation-name:entrypoint-enter-reduced}.entrypoint-scroll{flex-basis:min(10rem,28dvh);min-height:min(7.5rem,22dvh)}}@media (height<=32rem){.entrypoint-picker{padding:var(--cm-space-sm)}.entrypoint-picker h1{font-size:var(--cm-text-lg);margin-block-start:var(--cm-space-xs)}.entrypoint-picker>p:not(:first-child),.entrypoint-count,.entrypoint-continue{margin-block-start:var(--cm-space-xs)}.entrypoint-picker>p:not(:first-child){font-size:var(--cm-text-xs);line-height:1.3}.entrypoint-scroll{flex-basis:min(6rem,24dvh);min-height:min(4rem,18dvh)}}.entrypoint-scroll details{border-block-end:1px solid var(--cm-hairline)}.entrypoint-scroll summary{justify-content:space-between;align-items:baseline;gap:var(--cm-space-sm);padding:var(--cm-space-sm) 0;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;display:flex}.entrypoint-scroll summary small{color:var(--cm-ink-3)}.entrypoint-candidates{border-block-start:1px solid var(--cm-hairline)}.entrypoint-candidates button{gap:var(--cm-space-xs);width:100%;min-height:58px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.entrypoint-candidates button span{overflow-wrap:anywhere;font-family:var(--cm-font-mono)}.entrypoint-candidates button small{color:var(--cm-ink-3);font-family:var(--cm-font-mono)}@media (hover:hover) and (pointer:fine){.entrypoint-candidates button:hover{color:var(--cm-orbit)}}.entrypoint-continue{width:100%;min-height:44px;padding:var(--cm-space-xs) 0 0;border:0;border-block-start:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;text-underline-offset:3px;background:0 0;flex:none;margin-block-start:var(--cm-space-md);text-decoration:underline}.entrypoint-error{color:var(--cm-error)!important}.illumination-pulse{z-index:var(--cm-z-raised);color:var(--cm-star);pointer-events:none;animation:illumination-pulse .42s var(--cm-ease) both;justify-items:center;display:grid;position:absolute;inset-block-start:50%;inset-inline-start:25%;transform:translate(-50%,-50%)}.illumination-pulse span{filter:drop-shadow(0 0 18px var(--cm-star));font-size:clamp(3rem,8vw,6rem);line-height:1}.illumination-pulse strong{color:var(--cm-ink);font-family:var(--cm-font-display)}.structural-summary p{max-width:62ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink)}.mini-constellation{width:100%;max-width:22rem;height:auto;margin-block-start:var(--cm-space-md)}.mini-constellation line{stroke:var(--cm-route);stroke-width:1px}.mini-constellation__name{fill:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:9px}.mini-constellation circle{fill:var(--cm-ink-3)}.mini-constellation__self{fill:var(--cm-orbit)}.connections h3{margin:var(--cm-space-lg) 0 0;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;font-weight:500}.connection-list{margin:var(--cm-space-xs) 0 0;border-block-start:1px solid var(--cm-hairline);padding:0;list-style:none}.connection-list button{gap:var(--cm-space-2xs);width:100%;min-height:52px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.connection-name{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.connection-meta{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}@media (hover:hover) and (pointer:fine){.connection-list button:hover .connection-name{color:var(--cm-orbit)}}.load-state .check-primary,.study-notice .check-primary{justify-self:start;margin-block-start:var(--cm-space-md)}.study-preview{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:72%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background-color:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.check-panel{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:76%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background-color:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.study-preview,.check-panel,.star-chart-screen,.module-finder ul,.index-sidebar__scroll,.map-legend,.map-view{--cm-scroll-cover:var(--cm-ground-2);background-image:linear-gradient(var(--cm-scroll-cover) 30%, transparent), linear-gradient(transparent, var(--cm-scroll-cover) 70%), radial-gradient(farthest-side at 50% 0, #0000008c, transparent), radial-gradient(farthest-side at 50% 100%, #0000008c, transparent);background-position:0 0,0 100%,0 0,0 100%;background-repeat:no-repeat;background-size:100% 2.5rem,100% 2.5rem,100% .85rem,100% .85rem;background-attachment:local,local,scroll,scroll}.star-chart-screen{--cm-scroll-cover:var(--cm-ground)}.check-panel__header{justify-content:space-between;align-items:start;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-lg);display:flex}.check-panel__header p,.check-panel__header h1{margin:0}.check-panel__header p,.check-progress span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-panel__header h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin-block-start:var(--cm-space-xs);line-height:1.1}.check-loading,.check-state,.check-complete,.active-check{margin-block-start:var(--cm-space-lg)}.check-loading,.check-state p,.check-complete p,.active-check fieldset>p{max-width:60ch;color:var(--cm-ink-2)}.check-state h2,.check-complete h2{font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0}.check-state p,.check-complete p{margin:var(--cm-space-sm) 0 0}.check-complete{gap:var(--cm-space-sm);display:grid}.check-complete__star{color:var(--cm-star);font-size:var(--cm-text-display);line-height:1}.check-progress{align-items:center;gap:var(--cm-space-md);grid-template-columns:auto minmax(5rem,1fr);margin-block-end:var(--cm-space-xl);display:grid}.check-progress progress{background:var(--cm-hairline);width:100%;height:2px;color:var(--cm-star);border:0}.check-progress progress::-webkit-progress-bar{background:var(--cm-hairline)}.check-progress progress::-webkit-progress-value{background:var(--cm-star)}.check-progress progress::-moz-progress-bar{background:var(--cm-star)}.active-check{gap:var(--cm-space-lg);display:grid}.active-check fieldset{border:0;min-width:0;margin:0;padding:0}.active-check legend{overflow-wrap:break-word;max-width:100%;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);padding:0;font-weight:700;line-height:1.15}.active-check fieldset>p{margin:var(--cm-space-sm) 0 0}.check-options{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.check-options label{align-items:center;gap:var(--cm-space-md);min-height:52px;padding-block:var(--cm-space-sm);border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;grid-template-columns:auto minmax(0,1fr);display:grid}.check-options label:has(input:checked){color:var(--cm-ink)}.check-options input{width:1rem;height:1rem;accent-color:var(--cm-star);margin:0}.check-options span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.check-feedback{gap:var(--cm-space-xs);padding:var(--cm-space-md);border-inline-start:2px solid var(--cm-error);background:var(--cm-ground);color:var(--cm-ink-2);display:grid}.check-feedback strong{color:var(--cm-ink)}.check-feedback span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-affirmation{align-items:baseline;gap:var(--cm-space-xs);margin:0 0 var(--cm-space-lg);border-inline-start:2px solid var(--cm-star);color:var(--cm-star-high);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);display:flex}.study-preview__path{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);color:var(--cm-orbit)!important}.study-preview__header{display:block}.study-preview dl{gap:var(--cm-space-md);margin:var(--cm-space-lg) 0 0;grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.study-preview dl div{border-block-start:1px solid var(--cm-hairline);padding-block-start:var(--cm-space-sm)}.study-preview dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.study-preview dd{margin:var(--cm-space-2xs) 0 0;font-variant-numeric:tabular-nums}.study-content{gap:var(--cm-space-xl);min-width:0;margin-block-start:var(--cm-space-xl);display:grid}.study-content>*{min-width:0}.study-section-heading{justify-content:space-between;align-items:center;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-sm);display:flex}.study-section-heading h2,.study-notice h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal;line-height:1.15}.study-section-heading span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap}.source-code{width:100%;min-width:0;max-height:22rem;margin:var(--cm-space-md) 0 0;padding:var(--cm-space-sm) 0;border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);counter-reset:source-line;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);tab-size:4;line-height:1.65;list-style:none;overflow:auto}.source-code li{min-width:max-content;padding-inline:var(--cm-space-sm) var(--cm-space-md);grid-template-columns:3.25rem minmax(0,1fr);display:grid}.source-code li:before{content:attr(data-line);color:var(--cm-ink-3);text-align:end;-webkit-user-select:none;user-select:none;padding-inline-end:var(--cm-space-md)}.source-code li:target{background:var(--cm-orbit-low)}.source-code code{font:inherit;white-space:pre}.grounded-explanation>p,.study-notice p,.study-loading,.evidence-list p{max-width:65ch;color:var(--cm-ink-2)}.grounded-explanation>p,.study-notice p,.study-loading{margin:var(--cm-space-md) 0 0}.grounded-explanation h3{margin:var(--cm-space-lg) 0 var(--cm-space-sm);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.source-citation{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-underline-offset:2px;text-decoration-thickness:1px}.source-citation:active{color:var(--cm-ink)}@media (hover:hover) and (pointer:fine){.source-citation:hover{color:var(--cm-ink)}}.source-citation--button{cursor:pointer;background:0 0;border:0;padding:0}.source-citation--button:disabled{color:var(--cm-ink-3);cursor:not-allowed}.evidence-list{gap:var(--cm-space-sm);margin:0;padding:0;list-style:none;display:grid}.evidence-list li,.study-notice{padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground)}.evidence-list p{margin:0 0 var(--cm-space-xs)}.evidence-list strong{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);margin-block-end:var(--cm-space-xs);display:block}.lens-notes{margin-block-start:var(--cm-space-sm);display:grid}.lens-note{gap:var(--cm-space-sm);min-width:0;padding-block:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:grid}.lens-note h3{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.lens-note p{max-width:65ch;margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.lens-note code{min-width:0;padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:pre;display:block;overflow-x:auto}.star-chart-screen{min-width:0;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-xl) max(var(--cm-space-md), env(safe-area-inset-left));background-color:var(--cm-ground);overflow:auto}.star-chart-intro{max-width:72rem;margin-inline:auto;padding-block-end:var(--cm-space-xl);display:block}.star-chart-intro>p:first-child{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;line-height:1.08}.star-chart-intro>p:not(:first-child){max-width:65ch;margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.star-chart-intro dl{gap:var(--cm-space-md);margin:var(--cm-space-xl) 0 0;padding-block:var(--cm-space-md);border-block:1px solid var(--cm-hairline);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.star-chart-intro dt,.concept-row dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro dd{margin:var(--cm-space-xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);font-variant-numeric:tabular-nums}.concept-ledger{border-block-start:1px solid var(--cm-hairline);max-width:72rem;margin-inline:auto}.concept-row{align-items:center;gap:var(--cm-space-lg);min-width:0;padding-block:var(--cm-space-lg);border-block-end:1px solid var(--cm-hairline);grid-template-columns:minmax(10rem,.7fr) minmax(8rem,1.2fr) auto;display:grid}.concept-row h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal}.concept-row>div:first-child>span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.concept-meter{background:var(--cm-hairline);height:2px;overflow:hidden}.concept-meter span{background:var(--cm-star);height:100%;display:block}.concept-row dl{align-items:center;gap:var(--cm-space-lg);margin:0;display:flex}.concept-row dl div{min-width:5rem}.concept-row dd{margin:var(--cm-space-xs) 0 0;font-variant-numeric:tabular-nums}.status-line{z-index:var(--cm-z-sticky);justify-content:space-between;gap:var(--cm-space-2xs) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-sm), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;grid-row:4;display:flex;position:relative}.status-line span{white-space:normal}.status-line span:nth-child(2){display:none}.load-state,.webgl-error{align-content:center;gap:var(--cm-space-md);min-height:100dvh;padding:var(--cm-space-lg);background:var(--cm-ground);color:var(--cm-ink);display:grid}.load-state p,.webgl-error p{max-width:65ch;color:var(--cm-ink-2);margin:0}@keyframes panel-enter{0%{opacity:0;transform:translateY(var(--cm-space-md))}to{opacity:1;transform:translateY(0)}}@keyframes entrypoint-enter{0%{opacity:0;transform:translateY(var(--cm-space-md))}to{opacity:1;transform:translateY(0)}}@keyframes illumination-pulse{0%{opacity:0;transform:translate(-50%,-50%)scale(.75)}45%{opacity:1;transform:translate(-50%,-50%)scale(1.08)}to{opacity:0;transform:translate(-50%,-50%)scale(1)}}@media (width>=40rem){.status-line span{white-space:nowrap;display:inline}.lens-note{gap:var(--cm-space-lg);grid-template-columns:minmax(8rem,.35fr) minmax(0,1fr)}.study-preview{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(48rem,60%);max-height:none;inset-block:0;inset-inline-start:auto}.check-panel{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(42rem,56%);max-height:none;inset-block:0;inset-inline-start:auto}}@media (width>=64rem){.instrument-rail{grid-template-columns:minmax(0,auto) minmax(9rem,1fr) auto auto}.rail-overflow{display:contents}.rail-overflow__panel,.rail-overflow[data-open] .rail-overflow__panel{display:contents;position:static}.location{grid-area:1/2}.rail-action,.home-readout{justify-self:end}.rail-actions{flex-wrap:nowrap;grid-area:1/3;justify-content:flex-end;min-width:max-content}.rail-more{z-index:var(--cm-z-panel);width:max-content;max-width:min(22rem,100%);padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);grid-area:auto;display:none;position:absolute;inset-block-start:100%;inset-inline-end:max(var(--cm-space-md), env(safe-area-inset-right));box-shadow:0 1rem 2.5rem #00000061}.rail-overflow[data-open] .rail-more{display:flex}.mobile-menu-trigger{min-width:0;padding-inline:var(--cm-space-sm);grid-area:1/4;place-self:center end}.rail-trigger__compact{display:none}.rail-trigger__wide{display:inline}.rail-controls{grid-area:2/1/auto/-1;justify-self:center}.language-focus{flex:12rem}}@media (width<=39.999rem){.study-preview{border-block-start:1px solid var(--cm-hairline);max-height:none;position:fixed;inset-block:7.75rem 0}.app-shell:has(.study-preview) .instrument-rail{z-index:calc(var(--cm-z-panel) + 2)}.check-panel{border-block-start:0;max-height:none;position:fixed;inset-block:7.75rem 0;inset-inline:0}.check-panel__header{padding-block-end:var(--cm-space-md)}.check-loading,.check-state,.check-complete,.active-check{margin-block-start:var(--cm-space-md)}.active-check{gap:var(--cm-space-md)}.check-options{margin-block-start:var(--cm-space-md)}}@media (width<=48rem){.illumination-pulse{inset-block-start:35%;inset-inline-start:50%}.star-chart-intro dl{grid-template-columns:1fr}.concept-row{gap:var(--cm-space-md);grid-template-columns:1fr}.concept-row dl{justify-content:space-between}}@media (width>=60rem){.map-stage:has(.map-view) .map-legend{grid-template-columns:repeat(2,auto)}.map-legend span{white-space:nowrap}.chart-stage:has(.index-sidebar) .star-chart-screen{margin-inline-start:var(--cm-sidebar-width)}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.15s!important;animation-duration:.15s!important;animation-iteration-count:1!important}.study-preview,.check-panel,.mode-gate{animation-name:panel-enter-reduced}.entrypoint-picker{animation-name:entrypoint-enter-reduced}.illumination-pulse{animation-name:illumination-pulse-reduced}}@keyframes panel-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes entrypoint-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes illumination-pulse-reduced{0%{opacity:0}50%{opacity:1}to{opacity:0}}.picker-screen{gap:var(--cm-space-lg);min-height:100vh;padding:var(--cm-space-2xl) var(--cm-space-xl);flex-direction:column;max-width:44rem;margin:0 auto;display:flex}.picker-wordmark{font-family:var(--cm-font-display);font-size:var(--cm-text-sm);letter-spacing:.2em;text-transform:uppercase;color:var(--cm-ink-3)}.picker-subtitle{color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.picker-recents ul,.picker-browser ul{margin:var(--cm-space-sm) 0 0;gap:var(--cm-space-2xs);flex-direction:column;padding:0;list-style:none;display:flex}.picker-recents button,.picker-browser ul button{justify-content:space-between;gap:var(--cm-space-sm);width:100%;padding:var(--cm-space-xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);text-align:left;cursor:pointer;display:flex}.picker-recents button:hover,.picker-recents button:focus-visible,.picker-browser ul button:hover,.picker-browser ul button:focus-visible{border-color:var(--cm-orbit)}.picker-recents button{flex-wrap:wrap}.picker-recent-path{overflow-wrap:anywhere;min-width:0}.picker-recent-lit{color:var(--cm-star);white-space:nowrap}.picker-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2);overflow-wrap:anywhere}.picker-scale,.picker-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-error{color:var(--cm-error)}.picker-error p{margin:0}.picker-retry{min-height:44px;padding:var(--cm-space-xs) var(--cm-space-md);border:1px solid var(--cm-error);border-radius:var(--cm-radius);color:var(--cm-ink);cursor:pointer;background:0 0;margin-block-start:var(--cm-space-sm)}.picker-retry:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:2px}.picker-select{padding:var(--cm-space-xs) var(--cm-space-lg);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-base);cursor:pointer;align-self:flex-start}.picker-select:disabled{opacity:.6;cursor:progress}.layer-switcher{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);display:inline-flex;overflow:hidden}.layer-switcher button{padding:var(--cm-space-2xs) var(--cm-space-sm);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.layer-switcher button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-ink)}.map-view{gap:var(--cm-space-sm);padding:var(--cm-space-md);--cm-scroll-cover:var(--cm-ground);background-color:var(--cm-ground);flex-direction:column;display:flex;position:absolute;inset:0;overflow:hidden auto}.map-tabs{gap:var(--cm-space-xs);flex:none;display:flex}.map-tabs button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.map-tabs button[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-ink)}.map-canvas{flex-direction:column;flex:auto;min-block-size:6rem;display:flex;position:relative}.map-zoom{z-index:var(--cm-z-raised);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);gap:1px;display:flex;position:absolute;inset-block-start:var(--cm-space-sm);inset-inline-end:var(--cm-space-sm)}.map-zoom button{min-width:34px;min-height:30px;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.map-zoom button:hover:not(:disabled),.map-zoom button:focus-visible{color:var(--cm-orbit)}.map-zoom button:disabled{color:var(--cm-ink-3);cursor:default}@media (width<=40rem){.map-tabs{flex-wrap:wrap;padding-inline-end:4.5rem}.map-zoom{align-self:flex-end;margin-block-end:var(--cm-space-xs);position:static}.map-canvas{min-block-size:8.5rem}}.map-scroll{overscroll-behavior:contain;cursor:grab;background:linear-gradient(var(--cm-ground) 30%, transparent) 0 0 / 100% 2.5rem local no-repeat, linear-gradient(transparent, var(--cm-ground) 70%) 0 100% / 100% 2.5rem local no-repeat, linear-gradient(to right, var(--cm-ground) 30%, transparent) 0 0 / 2.5rem 100% local no-repeat, linear-gradient(to left, var(--cm-ground) 30%, transparent) 100% 0 / 2.5rem 100% local no-repeat, radial-gradient(farthest-side at 50% 0, #0000008c, transparent) 0 0 / 100% .85rem scroll no-repeat, radial-gradient(farthest-side at 50% 100%, #0000008c, transparent) 0 100% / 100% .85rem scroll no-repeat, radial-gradient(farthest-side at 0 50%, #00000073, transparent) 0 0 / .85rem 100% scroll no-repeat, radial-gradient(farthest-side at 100% 50%, #00000073, transparent) 100% 0 / .85rem 100% scroll no-repeat;flex:auto;overflow:auto}.map-scroll[data-panning]{cursor:grabbing;-webkit-user-select:none;user-select:none}.map-canvas__sized{min-width:100%}.map-canvas-surface{contain:strict;max-width:100%;max-height:100%;display:block;position:sticky;inset-block-start:0;inset-inline-start:0;overflow:hidden}.map-canvas-surface:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:-3px}.map-canvas-surface canvas{display:block}.map-canvas-readout{max-width:calc(100% - var(--cm-space-sm) * 2);padding:var(--cm-space-2xs) var(--cm-space-xs);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);overflow-wrap:anywhere;white-space:normal;pointer-events:none;background:#101a3eeb;position:absolute;inset-block-end:var(--cm-space-sm);inset-inline-start:var(--cm-space-sm)}.map-canvas-active-option{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.map-note,.map-loading{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);flex:none;margin:0}.map-state{text-align:center;max-width:46ch;color:var(--cm-ink-2);margin:auto}.hint-chip{z-index:calc(var(--cm-z-panel) + 1);align-items:center;gap:var(--cm-space-sm);min-width:0;padding:var(--cm-space-sm) var(--cm-space-md);border-block:1px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-size:var(--cm-text-sm);flex-wrap:wrap;grid-row:3;display:flex;position:static}@media (width<=40rem){.hint-chip{max-block-size:40vh;overflow-y:auto}.hint-chip small{text-overflow:ellipsis;white-space:nowrap;flex:100%;overflow:hidden}}.hint-chip small{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.hint-chip button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.first-flight__system{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-mono)}.first-flight__actions{gap:var(--cm-space-xs);flex-wrap:wrap;margin-inline-start:auto;display:flex}.first-flight__actions button[disabled]{border-color:var(--cm-hairline);color:var(--cm-ink-3);cursor:default}@media (width<=40rem){.first-flight__system,.first-flight__actions{flex:100%}.first-flight__actions{margin-inline-start:0}}.location button{color:var(--cm-orbit);font:inherit;cursor:pointer;background:0 0;border:0;padding:0}.location button[disabled]{color:var(--cm-ink-2);cursor:default}.location button:not([disabled]):hover{text-decoration:underline}.coach-marks{inset-block:auto var(--cm-space-lg);width:min(38ch, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);margin-inline:auto;inset-inline:0}.coach-marks::backdrop{background:var(--cm-scrim)}.coach-marks__progress{margin:0 0 var(--cm-space-2xs);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.coach-marks h1{margin:0 0 var(--cm-space-xs);font-size:var(--cm-text-lg)}.coach-marks__actions{justify-content:space-between;gap:var(--cm-space-sm);margin-block-start:var(--cm-space-md);display:flex}.coach-skip{color:var(--cm-ink-3);cursor:pointer;background:0 0;border:0}.legend-tint{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:2px;display:inline-block}.legend-communities{gap:2px;display:inline-flex}.legend-communities i{width:calc(var(--cm-space-sm) / 1.6);height:var(--cm-space-sm);border-radius:2px;display:inline-block}.legend-communities i:first-child{background:var(--cm-com-0)}.legend-communities i:nth-child(2){background:var(--cm-com-1)}.legend-communities i:nth-child(3){background:var(--cm-com-2)}.legend-communities i:nth-child(4){background:var(--cm-com-3)}.map-note__toggle{border:var(--cm-rule) solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-orbit);font:inherit;font-size:var(--cm-text-xs);padding:var(--cm-space-2xs) var(--cm-space-sm);cursor:pointer;background:0 0}.map-note__toggle:hover,.map-note__toggle:focus-visible{border-color:var(--cm-orbit)}.legend-route--dashed{border-block-start-style:dashed}.legend-size{width:var(--cm-space-md);height:var(--cm-space-sm);background:var(--cm-ink-3);border-radius:50%;display:inline-block}.legend-brightness{width:var(--cm-space-md);height:var(--cm-space-sm);background:linear-gradient(90deg, var(--cm-node-unlit), var(--cm-ink-2));display:inline-block}.app-shell[data-mode=easy]{--cm-text-xs:.8125rem;--cm-text-sm:.9375rem;--cm-text-base:1.125rem;--cm-text-lg:1.375rem;--cm-space-sm:1rem;--cm-space-md:1.375rem;--cm-space-lg:2.5rem;font-size:var(--cm-text-base);line-height:1.7}.app-shell[data-mode=easy] .orientation-copy p,.app-shell[data-mode=easy] .study-preview p,.app-shell[data-mode=easy] .grounded-explanation>p,.app-shell[data-mode=easy] .study-notice p,.app-shell[data-mode=easy] .evidence-list p,.app-shell[data-mode=easy] .lens-note p,.app-shell[data-mode=easy] .active-check fieldset>p,.app-shell[data-mode=easy] .check-state p,.app-shell[data-mode=easy] .check-complete p,.app-shell[data-mode=easy] .check-loading{max-width:46ch}.app-shell[data-mode] .orientation-copy--inline>p{max-width:72ch}.app-shell[data-mode=easy] .language-focus__label,.app-shell[data-mode=easy] .mode-toggle__label{text-transform:none;letter-spacing:normal}.loading-screen{gap:var(--cm-space-md);max-width:44rem;min-height:100vh;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-left));align-content:center;justify-items:start;margin:0 auto;display:grid}.loading-header h1{min-width:0;margin:var(--cm-space-2xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);overflow-wrap:anywhere;line-height:1.15}.loading-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2)}.loading-subtitle{margin:var(--cm-space-xs) 0 0;color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-stages{gap:var(--cm-space-2xs);width:100%;margin:0;padding:0;list-style:none;display:grid}.loading-stages li{justify-content:space-between;gap:var(--cm-space-sm);padding:var(--cm-space-xs) var(--cm-space-sm);border-left:2px solid var(--cm-hairline);color:var(--cm-ink-3);font-size:var(--cm-text-sm);flex-wrap:wrap;display:flex}.loading-stages li[data-state=active]{border-left-color:var(--cm-orbit);color:var(--cm-ink)}.loading-stages li[data-state=done]{border-left-color:var(--cm-orbit-deep);color:var(--cm-ink-2)}.loading-stages small{font-family:var(--cm-font-mono);color:var(--cm-ink-2)}.loading-meter{width:100%;height:var(--cm-space-xs);accent-color:var(--cm-orbit)}.loading-live{color:var(--cm-ink);font-size:var(--cm-text-sm)}.loading-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);width:100%;padding:var(--cm-space-sm);color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-actions{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.loading-actions button{padding:var(--cm-space-xs) var(--cm-space-md)}.picker-scale h2,.picker-failure h2{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base)}.picker-scale-scopes{gap:var(--cm-space-xs);margin:var(--cm-space-sm) 0;flex-wrap:wrap;padding:0;list-style:none;display:flex}.picker-scale-scopes button{align-items:flex-start;gap:var(--cm-space-2xs);min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);cursor:pointer;flex-direction:column;display:flex}.picker-scale-scopes button:hover:not(:disabled),.picker-scale-scopes button:focus-visible{border-color:var(--cm-orbit)}.picker-scale-scopes button:disabled{opacity:.6;cursor:progress}.picker-scale-scopes small{color:var(--cm-ink-2)}.picker-path-entry{gap:var(--cm-space-xs);flex-wrap:wrap;align-items:center;display:flex}.picker-path-entry label{color:var(--cm-ink-2)}.picker-path-entry input{min-width:0;min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-xs);background:var(--cm-ground);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);flex:14rem}.picker-path-entry button{min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-md);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-sm);cursor:pointer}.picker-path-entry button:disabled{opacity:.6;cursor:not-allowed}.picker-failure{border:1px solid var(--cm-error);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-failure>p{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.picker-failure__detail{gap:var(--cm-space-2xs);display:grid}.picker-failure__detail span{color:var(--cm-ink-3);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em}.picker-failure__detail code{max-height:8rem;padding:var(--cm-space-xs);background:var(--cm-ground-2);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);overflow-wrap:anywhere;display:block;overflow:auto}.picker-failure .picker-select{min-height:44px;font-size:var(--cm-text-sm);align-self:flex-start}.progress-reset{align-items:center;gap:var(--cm-space-sm);max-width:72rem;margin:var(--cm-space-lg) auto 0;padding-top:var(--cm-space-md);border-top:1px solid var(--cm-hairline);flex-wrap:wrap;display:flex}.progress-reset p{color:var(--cm-ink-2);font-size:var(--cm-text-sm);margin:0}.progress-reset button{min-height:44px;padding-inline:var(--cm-space-md);font-size:var(--cm-text-sm)}.progress-reset--confirming{justify-items:start;gap:var(--cm-space-sm);display:grid}.progress-reset--confirming>p[role=alert]{max-width:60ch;color:var(--cm-ink)}.progress-reset--confirming>div{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.progress-reset__confirm{border-color:var(--cm-error);color:var(--cm-error)}.progress-reset__error{color:var(--cm-error)}.learning-journey{min-width:0}.journey-overview{gap:var(--cm-space-2xs);margin:var(--cm-space-md) 0 0;padding:0 0 var(--cm-space-xs);scrollbar-width:thin;grid-auto-columns:minmax(4.5rem,1fr);grid-auto-flow:column;list-style:none;display:grid;overflow-x:auto}.journey-overview button{width:100%;min-height:44px;padding:var(--cm-space-xs);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);cursor:pointer;text-align:start;background:0 0;align-content:center;justify-items:start;gap:1px;display:grid}.journey-overview button[aria-current=step]{border-color:var(--cm-orbit);background:var(--cm-orbit-low);color:var(--cm-ink)}.journey-overview button>span,.journey-overview button>small,.journey-position,.journey-citations,.journey-expert-facts,.journey-controls,.journey-break code,.journey-possible span,.journey-candidate-note,.journey-support-scope{font-family:var(--cm-font-mono)}.journey-overview button>span{color:var(--cm-orbit);font-size:var(--cm-text-sm)}.journey-overview button>small{text-transform:uppercase;font-size:.625rem;line-height:1.2}.journey-current{gap:var(--cm-space-sm);padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-inline-start:3px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);margin-block-start:var(--cm-space-sm);display:grid}.journey-position{font-size:var(--cm-text-xs);text-transform:uppercase;color:var(--cm-orbit)!important;margin:0!important}.journey-current h3{font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal}.journey-current>p:not(.journey-position){color:var(--cm-ink-2);margin:0}.journey-citations{gap:var(--cm-space-xs) var(--cm-space-md);color:var(--cm-ink-3);font-size:var(--cm-text-xs);flex-wrap:wrap;display:flex}.journey-citations code,.journey-break code{color:var(--cm-orbit);overflow-wrap:anywhere}.study-preview .journey-expert-facts{gap:var(--cm-space-sm);grid-template-columns:repeat(auto-fit,minmax(8rem,1fr));margin:0}.journey-expert-facts dd{overflow-wrap:anywhere;font-size:var(--cm-text-xs)}.journey-controls{gap:var(--cm-space-xs);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.journey-controls button{min-height:44px;padding:var(--cm-space-xs);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);cursor:pointer;background:0 0}.journey-controls button:nth-child(2){border-color:var(--cm-orbit);color:var(--cm-orbit)}.journey-controls button:disabled{color:var(--cm-ink-3);cursor:not-allowed;opacity:.55}.journey-break,.journey-possible{padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);margin-block-start:var(--cm-space-md)}.journey-break{border-inline-start:3px solid var(--cm-error)}.journey-break p,.journey-possible p{margin:var(--cm-space-xs) 0 0;color:var(--cm-ink-2)}.journey-possible h3{font-family:var(--cm-font-display);font-size:var(--cm-text-base);margin:0;font-style:normal}.journey-possible ul{gap:var(--cm-space-xs);margin:var(--cm-space-md) 0 0;padding:0;list-style:none;display:grid}.journey-possible li{gap:var(--cm-space-2xs);border-block-start:1px solid var(--cm-hairline);padding-block-start:var(--cm-space-xs);display:grid}.journey-possible span,.journey-candidate-note{color:var(--cm-ink-3);font-size:var(--cm-text-xs);overflow-wrap:anywhere}.journey-support{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.journey-support>summary{min-height:44px;padding-block:var(--cm-space-sm);color:var(--cm-orbit);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.journey-support>section{margin-block-start:var(--cm-space-lg)}.journey-support-scope{margin:0}.journey-candidate-note{margin-block-start:var(--cm-space-sm)}.visually-hidden{clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;width:1px!important;height:1px!important;position:absolute!important;overflow:hidden!important}@media (width<=20rem){.study-preview{padding:var(--cm-space-sm) var(--cm-space-md) max(var(--cm-space-sm), env(safe-area-inset-bottom))}.study-content{gap:var(--cm-space-md);margin-block-start:var(--cm-space-xs)}.study-preview dl{gap:var(--cm-space-sm);margin-block-start:var(--cm-space-md)}.journey-current{gap:var(--cm-space-xs);padding:var(--cm-space-xs)}.journey-overview{margin-block-start:var(--cm-space-xs)}.journey-current>p:not(.journey-position){font-size:var(--cm-text-sm);line-height:1.45}.journey-controls{gap:var(--cm-space-2xs)}}@media (width<=22.5rem){.app-shell[data-level=study] .hint-chip{gap:var(--cm-space-xs)}.app-shell[data-level=study] .hint-chip button{padding-inline:var(--cm-space-xs)}.source-study .study-section-heading{gap:var(--cm-space-xs)}.source-study .study-section-heading h2{overflow-wrap:normal;flex:none}.source-study .study-section-heading span{text-overflow:ellipsis;min-width:0;overflow:hidden}}.impact-columns{gap:var(--cm-space-md);grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));display:grid}.impact-column h3{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);letter-spacing:.04em;text-transform:uppercase;margin:0;font-weight:500}.impact-list{margin:var(--cm-space-2xs) 0 0;border-block-start:1px solid var(--cm-hairline);padding:0;list-style:none}.impact-list button{gap:var(--cm-space-2xs);width:100%;min-height:44px;padding:var(--cm-space-xs) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.impact-name{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.impact-meta,.impact-citation{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.impact-citation{overflow-wrap:anywhere}@media (hover:hover) and (pointer:fine){.impact-list button:hover .impact-name{color:var(--cm-orbit)}}.walkthrough-disclosure>summary{min-height:44px;padding:var(--cm-space-xs) 0;color:var(--cm-orbit);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.walkthrough-disclosure>summary:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:2px}.project-summary{margin-block:var(--cm-space-lg);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2)}.project-summary__lead{max-width:60ch;margin:0 0 var(--cm-space-lg);color:var(--cm-ink);font-size:var(--cm-text-lg);line-height:1.4}.project-summary__facts{gap:var(--cm-space-md) var(--cm-space-xl);grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));margin:0;display:grid}.project-summary__facts>div{min-width:0}.project-summary__facts dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.project-summary__facts dd{margin:var(--cm-space-2xs) 0 0;overflow-wrap:break-word;color:var(--cm-ink)}.project-summary__export{min-height:44px;padding:var(--cm-space-xs) var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);cursor:pointer;font:500 var(--cm-text-sm) / 1.3 var(--cm-font-mono);background:0 0;margin-block-start:var(--cm-space-lg)}.project-summary__export:hover{background:color-mix(in srgb, var(--cm-orbit) 10%, transparent)}.project-summary__export:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:3px}.star-chart-section{margin-block:var(--cm-space-xl) 0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg)}
diff --git a/codemble/web_dist/index.html b/codemble/web_dist/index.html
index 15f6051..e74d252 100644
--- a/codemble/web_dist/index.html
+++ b/codemble/web_dist/index.html
@@ -9,8 +9,8 @@
content="Explore the parser-proven structure of your local project with Codemble."
/>
Codemble · Your code, mapped
-
-
+
+
diff --git a/docs-site/package.json b/docs-site/package.json
index 325843b..7562db1 100644
--- a/docs-site/package.json
+++ b/docs-site/package.json
@@ -1,7 +1,7 @@
{
"name": "codemble-docs",
"type": "module",
- "version": "0.19.2",
+ "version": "0.20.0",
"private": true,
"scripts": {
"dev": "astro dev",
diff --git a/docs-site/public/shots/easy-mode.png b/docs-site/public/shots/easy-mode.png
index 89be0807b815bf5cf7a40a83d5d6ff56d6e2cd4a..60e14e73507e6aa9a65482b818cbadcc202cdb86 100644
GIT binary patch
literal 70824
zcmc$lWmFq$+wbetfZfu<#@hm=cyWiexEC*8iU%t$L8`a~NGa~_5`qONP#{=vNeEB~
z4hb5ZoZ0(%-*=sL*7=xo75{TQ2!uzX^Y?{va$aQ
z;1R&@bl}z1e-DN|ZZQ0N@QU!@gUZ}@{=@2f`xmfzWWt73S+y+N9F!`ksZonSt;Vm
zIZtrVRx{W}Q?vdHIB(={p>3(UqvNT|UU*7a9;goG)LuE(>?;vJ?@wQI@8N8kQwC<-(z+ONnf_^*cWrIw2`!!3v2t~Ri`
zb)fbas+KoH&GDy&2Qmv)@X7>=)DyE!#A9WB@GaNCe~VRFoDrQhGi8oOlrlN~8OJLN_%)yQ
zrz715>nLkmTOPBf#f=HaZ4BJ3YJtYeYRPe`V&1V`yVPJ%Bh|p@-8*F;PtQ7?QP!5}
zdS?U-2K8iTWnCfs>hAWxIDH%wLov!j`tr}>y>bPg!bHYEXqDUyXMeto!+CB_8jg~4
zBun~aBqZeGZkwB%_enPeoT!!?M_<3r=O{$Ce0ArDvPi#F`~AXW7M9Ly;ILRN`{}Cu
zHj)Ar71cizaOKMEy+CK{I&*}CZh?AY42x1s@p=g7vu8DSsH>yexr$!POg6yJ)|Qh}
zM^Vv#L^>}YoBf}a8<*Ld@oRU+j=7}JIAG^jAsoR*s}#$0;W~HU;NM%fcfRIBExZ&G
zavIHpc;@BhF-ZGM1yd&RSwP_9_{nmU3KRJGXnw-p&Y|=Ua39?EetuFxrlgM)E3PSX
z{<~}2#WPYC8WDf)U6w)KVoAU#MOC72V+M*_*u`3(?)W7gP@B;yU_;>0UG{m
zbBM^&(#_UD%yNE!^;p5g%E}6ye5|uGkaU?Y>S_+{$&fao6Ll#9a|JI|e~2_p&Da&T?)BXp-QDZ2JUO
z5(l^M-|v&XREYZYpS5$Ty=V9FKBF+clP}ocA1%ldazHx@AKVEl$311-+grEGguwI2
zmM@iKvb{i{L;aN|v;;RBJIJLZf3S+Mbri;5XOcR@(w5ZZ%%L9%5^2oBZ>qvJ(Uz
z+D!W&)0w3kZ}+i5&pT6QDLQ4Mw9ekNb9PG>ehrd@uh=U}j8DNYzMp8($GFOnUUK6K
zbhxixg==~jna;q%=77;GHfPGYMgC^*Uicj+XXmqn_4Or>SI)n!P)wQEWO?}`pwN8J
zC`L(tTyOR*V>Er%I}?+MQp45rlSm^Yqdfs`Zf;2vuo-fF%x;1*BqXGSu~0L8eX?B5
z60V_Lca$4_=l1P5z7mTz7kk+zWA@Rx4YSCc@?VhzPX@2$j*1YAy=CBhKNCD69SFe61r$_ty``6iz=#ta;Iwi%x^A7BxoKv4Qu3YrC=mudp6nce%T7i|6(=_WJ7wqXh<(`>10%L1`KQq%Y-;q^Ql;qb6@&V_
zs$t#j?L$cH-0%M3-glo>bNOql>Z^S?`WW(gD0y~w3hlfW-?r&DM)mV1+!RId*wq`s=
zF;TRY{T_f%8SfU$@CVf>=H9t?FZkkcCfxB}L2px~X
z;2&YCt(r^pOO<<8GlN-~A$cpyNfu+|@+0*%mVu%yZ=cZ#Iq()o6eht>1z5$_&cvDf
zSa^gLM$R#qRxBoOCy5|qSmzi^2KKQWO!t3xaAr!IjKzp@*z`=}47db=z2T!?qZ$ec
zUza{~b^1WeoT7_P?CtD5o(s{f>IgMJ{;r+xGV+;zdi}~Pl8Q~G#(a-?GC0e-wu0^}
z#wT+tP3rmJrAG&Sn-NBw<4Bn(y#ZgByganXmoSuft;saX)$SSL3nt*qIGJzhK$n)6NScHv>!;*GwxFfXbR>)BcjUC8##%8+qdSQ#BrA?vKfi(PdQWFndR4%xmtY3Uc6sL4t>w
zW}Au_I6sSsrNBX}Tkri$N^^YVWEP!VIhgs(H4aw>7i2WVe4S~wE#c*H
zw9`cU=t*PuZ;!&q&R@%D{lJki5s9G{2Ej_#L!(_rN)WJeGf!)IQz!Mq6d37vS#sVg
z6vuOt!(P~CjGTMQ#^$$_Vgs&sHINnX?@07cZvtM7ajwl!G|hpptr&+>PRqt+I0^XT
zrjs&*xL>qunHw8na3pg|J_36tSb_1lK)Bz>8B_FQ%5mDdx7UpqiWL+X)nb&bc|Uj5
z7g$wQcZy5(6D-h(M+!S^?AIu!A6?L>CdaqDnl$pr*iMW0HH2H%*Hs7qNlnj`nR(74
ztG72-oDwsNaQc_xQfnY}->iza
zF;|5)1qRBEzqa?YCw}m6xE8sH98kX35+K0BqhJ`Hp1=lvLg6wIB7Nrf#`8FWU>*~B
zR~rxUf4gtlAGIg=QV292^q$~WSy=e|1aFl5BkgUo5xj{9Y*0Sszs*-$kuf=k%r@>M
z26nf#?wuJ{WJ>1Y9Dh|wB|Lc*tkn97(#cG(HStyZNRwIUhW>2ghhqHpb7nqb_Hklj
z;z%xY0tG$&riiog$;nNeGrt}i?Pn=dGqX~?T`B*AW9O0f$)M8j0guUCP_p7STEm4aS!DY+MpZF7<>S^*
z?~#)~p_!>7&fH7EyNl%#8Bu;q-R01LyY!zQS{fqf#s>oC@y(Xmm3^FyVjmGY37jE_rb8`_4%*v#`N
zsY>IfVPvCwPlYrpL&j~f_x1ASng}RGDpi!7X6kr)x=zR$^u#YNJ3IRZKje>P%nUEWKD;P2Mm{109yuaoKxxVWCHnS}nVYHvZzG#jWyMZeukGqnP_*jN!B
zy6vZ&>MTY@9SB)b>4wu=^ZaVYF{({Lv
zTBo@djcwkoAJy90Bj6*vAwD(5rO4AcY%V&U?lVTnWm1)T`4x#?^!oXxuv3%6_T7A3
z*Y9oy@wNT6uENXHrPTr+j0gz*23bx@O-bR&AdLY=gMO0x?EGw=Uf7v~Rz6Y$?XA;#
ziA&Gx`quUB_)n~+9zMNR%|_+bB`}XFIsx9UXYTknUJDV#w0r$>XWj&KiFCHrS%EMR
z39G7jeDn;uNY_$VA7mv=*IMoG{oa@KT<7;3|K_Pe9i<^4Fv@2kb~GlMS%RRYrKP8%
zEk-;Rt5Y4y(48~;;8cQWSSMq->HFVWz;R5z$>sSw3IFKSnVO!TX=zSIY!?EK)=pg-
zp?&(y!C(la+9BYejf~kp7F@0nJ7SbfYm~eWazzC+nIp-SMs*%8pY%*Isc4O8elCy}c+~Gbi=JyVBdNHbzd9jU#?L0*0%DMm5Ji45nHWK_##YqkIO`SC@CfF?bR4Vnx`BxAVLZAep0{N6A#Dc
z#BcAg92F8Z%{G>19BkU)^yBi91%$@4Xgg?0bV_~GNBnqnDUD5RwNWWiq#hc>I7{`I
zwqlK4SCETKvZtMk-ODXxi#J2I#fWL6|J+dST&=lkhL(=D-~DI0e)|K{ZEb0KGVze4
zVDlpP)i5*n4^DGdpE*x%BL5%`#&P3`T^QSh&)M1c4O;odpBe;3-Hd^5eP-|aMziDc
z{bSPRv#+xbF9e0e`71stNTa?r37-kk=?bdRCJwwkN!0OHeX|_4KaqYMW+%&bWLQFBYTD@AYF3E%+7P8^aC6>odOV^HQMg|ixQcg{
z^u9P9^AQ}4Jav;HZD4B5KYDvLdzyo_GJ|68YpJTIi3h4)C=O=$5|@ShVLUD0LT>?<
z$9^lXaD{ZfO*Lk&19-=n(~px;bg&H>*?s5r@^;tt0B
zQX*`Ru{uz5cak&j^A_jYH%NcW`Sg0GuhxbyeNeCxLI>tP;m=}mywdwaHr9o-DVv)!
z(%?UVmss?pO^gS7cM{nwZkS240r!&U0#7B7BTlzPE7NCc_rRn`rCP4F=<_^d8Qi*7
zo=g3DETy$i#cFP4uWZmhdYvv>LK$ZCd}&f4(^Ra