sync: bring HF Space to parity with origin/main (squash, XET-backed)
Browse filesSquash-merge of all commits on origin/main not present on HF Space:
- fix(riprap-models): port v2 test_transform patch (services container)
- feat(map): wire TerraMind LULC + Ida 2021 HWM map layers
- fix(map): MapLegend booleans, FloodNet tier proxy
- fix(slides): deck visual fixes
- docs: live-system screenshots (now as LFS/XET pointers, not raw blobs)
- chore: repo cleanup, session artifacts to docs/sessions/
- chore: LFS tracking rules for screenshot and slide PNGs/PPTX
Binary files (screenshots + deck.pptx) are stored as git-lfs/git-xet
pointers so HF's pre-receive hook accepts them. git-xet handles
upload to XET object store during the push.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This view is limited to 50 files because it contains too many changes. See raw diff
- .gitignore +10 -0
- README.md +8 -0
- assets/screenshots/2026-05-06/briefing-pioneer-capstone-b.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-capstone.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-cornerstone.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-keystone-silent.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-lodestone.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-overview.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-touchstone-a.png +3 -0
- assets/screenshots/2026-05-06/briefing-pioneer-touchstone-b.png +3 -0
- assets/screenshots/2026-05-06/briefing-ps188-capstone.png +3 -0
- assets/screenshots/2026-05-06/landing-page.png +3 -0
- assets/screenshots/hero.png +3 -0
- docs/RIPRAP-OWNER-BRIEF.md +570 -0
- docs/sessions/2026-05-W19/CHANGES-2026-05-06.md +279 -0
- docs/sessions/2026-05-W19/CODE-MORNING-BRIEF-2026-05-06.md +210 -0
- docs/sessions/2026-05-W19/COMMS-OVERNIGHT-2026-05-06-MORNING-BRIEF.md +176 -0
- docs/sessions/2026-05-W19/OVERNIGHT-2026-05-06-MORNING-BRIEF.md +275 -0
- docs/sessions/2026-05-W19/OVERNIGHT-2026-05-06-OUT-OF-SCOPE.md +77 -0
- {audit → docs/sessions/2026-05-W19/audit}/2026-05-03-evening-audit.md +0 -0
- {audit → docs/sessions/2026-05-W19/audit}/2026-05-04-morning-handoff.md +0 -0
- {audit → docs/sessions/2026-05-W19/audit}/AUDIT-2026-05-06.md +0 -0
- services/riprap-models/main.py +16 -0
- slides/asce/deck.html +0 -0
- slides/asce/deck.md +2 -8
- slides/asce/deck.pdf +2 -2
- slides/asce/deck.pptx +2 -2
- slides/asce/riprap.css +1 -1
- slides/deck.001.png +3 -0
- slides/deck.002.png +3 -0
- slides/deck.003.png +3 -0
- slides/deck.004.png +3 -0
- slides/deck.005.png +3 -0
- slides/deck.006.png +3 -0
- slides/deck.007.png +3 -0
- slides/deck.008.png +3 -0
- slides/deck.009.png +3 -0
- slides/deck.md +2 -12
- slides/riprap.css +1 -1
- uv.lock +3 -0
- web/main.py +29 -0
- web/sveltekit/build/200.html +8 -8
- web/sveltekit/build/_app/immutable/chunks/BZuv-XBZ.js +37 -0
- web/sveltekit/build/_app/immutable/chunks/Bm3kUygK.js +0 -27
- web/sveltekit/build/_app/immutable/chunks/Br29PcKx.js +0 -1
- web/sveltekit/build/_app/immutable/chunks/DtzoFJKK.js +1 -0
- web/sveltekit/build/_app/immutable/chunks/{Gqex3HJQ.js → qPYGiFsf.js} +1 -1
- web/sveltekit/build/_app/immutable/entry/{app.3Jr9HSQZ.js → app.CUBM1aCV.js} +2 -2
- web/sveltekit/build/_app/immutable/entry/start.CPaKwhlY.js +0 -1
- web/sveltekit/build/_app/immutable/entry/start.d_1AXvI4.js +1 -0
.gitignore
CHANGED
|
@@ -39,3 +39,13 @@ pitch/screenshots-*/
|
|
| 39 |
slides/deck.pdf
|
| 40 |
slides/deck.html
|
| 41 |
slides/deck.pptx
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
slides/deck.pdf
|
| 40 |
slides/deck.html
|
| 41 |
slides/deck.pptx
|
| 42 |
+
|
| 43 |
+
# Session artifacts
|
| 44 |
+
/tmp/riprap-*
|
| 45 |
+
.deploy-state
|
| 46 |
+
*.bak
|
| 47 |
+
*.swp
|
| 48 |
+
*.swo
|
| 49 |
+
|
| 50 |
+
# Sensitive
|
| 51 |
+
AMD_TOKEN
|
README.md
CHANGED
|
@@ -29,6 +29,14 @@ Live demo: <https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space>
|
|
| 29 |
|
| 30 |
---
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
## How Riprap works: the Five Stones
|
| 33 |
|
| 34 |
Behind every briefing, around 25 atomic data probes fan out across NYC
|
|
|
|
| 29 |
|
| 30 |
---
|
| 31 |
|
| 32 |
+
## What it looks like
|
| 33 |
+
|
| 34 |
+

|
| 35 |
+
|
| 36 |
+
*A citation-grounded flood-exposure briefing for 80 Pioneer Street in Red Hook. Generated in ~7 seconds against AMD MI300X. Every numeric claim cites a primary public-record source.*
|
| 37 |
+
|
| 38 |
+
---
|
| 39 |
+
|
| 40 |
## How Riprap works: the Five Stones
|
| 41 |
|
| 42 |
Behind every briefing, around 25 atomic data probes fan out across NYC
|
assets/screenshots/2026-05-06/briefing-pioneer-capstone-b.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-capstone.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-cornerstone.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-keystone-silent.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-lodestone.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-overview.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-touchstone-a.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-pioneer-touchstone-b.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/briefing-ps188-capstone.png
ADDED
|
Git LFS Details
|
assets/screenshots/2026-05-06/landing-page.png
ADDED
|
Git LFS Details
|
assets/screenshots/hero.png
ADDED
|
Git LFS Details
|
docs/RIPRAP-OWNER-BRIEF.md
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Riprap — Owner's Brief
|
| 2 |
+
|
| 3 |
+
---
|
| 4 |
+
|
| 5 |
+
## 1. The system in one paragraph
|
| 6 |
+
|
| 7 |
+
Riprap takes any NYC address, neighborhood, or development-permit query and produces a four-section flood-exposure briefing where every numeric claim is anchored to a `[doc_id]` citation that traces back to the source dataset, agency report, or model output. A natural-language planner (Granite 4.1 3b) routes each query to one of four intent paths; the chosen path fans out across up to ~25 atomic data specialists; a synthesizer (Granite 4.1 8b) reads only the specialist outputs that fired and writes the briefing; a Mellea rejection sampler checks four grounding invariants and rerolls if any fail. The system is NYC-specific and public-record-only: all data comes from NYC OpenData, USGS, NOAA, NWS, or FloodNet, and all four models run inside the container — no vendor LLM is contacted at runtime. The output is a tier 1–4 exposure score (deterministic, published rubric, not generated by the LLM) plus a cited paragraph in prose. What Riprap does not do: damage probability, insurance rating, flood prediction, or any claim about basement apartments or infrastructure that isn't in a public register.
|
| 8 |
+
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
## 2. Architecture map
|
| 12 |
+
|
| 13 |
+
### HTTP request lifecycle
|
| 14 |
+
|
| 15 |
+
```
|
| 16 |
+
User browser → GET /api/agent/stream?q=<query>
|
| 17 |
+
web/main.py: api_agent_stream() (async SSE generator)
|
| 18 |
+
runs runner() in a threadpool executor
|
| 19 |
+
app/planner.plan(q, on_token=...) → streams plan_token events while Granite generates
|
| 20 |
+
returns Plan(intent, targets, specialists, rationale)
|
| 21 |
+
out_q.put({kind:"plan", ...}) → SSE plan event
|
| 22 |
+
intent dispatch:
|
| 23 |
+
"single_address" → app/intents/single_address.run(plan, q, progress_q, strict=True)
|
| 24 |
+
"neighborhood" → app/intents/neighborhood.run(plan, q, progress_q, strict=True)
|
| 25 |
+
"development_check" → app/intents/development_check.run(plan, q, progress_q, strict=True)
|
| 26 |
+
"live_now" → app/intents/live_now.run(plan, q, progress_q)
|
| 27 |
+
"not_implemented" → inline JSON response, no FSM
|
| 28 |
+
each intent calls fsm.iter_steps() or its own specialist loop
|
| 29 |
+
→ out_q.put({kind:"step", ...}) per specialist
|
| 30 |
+
→ out_q.put({kind:"token", ...}) per Granite reconcile chunk
|
| 31 |
+
→ out_q.put({kind:"mellea_attempt", ...}) per Mellea pass/fail
|
| 32 |
+
out_q.put({kind:"final", ...})
|
| 33 |
+
event_stream() async generator reads out_q, wraps steps in
|
| 34 |
+
stone_start / stone_done envelope keyed by _STEP_TO_STONE dict,
|
| 35 |
+
yields SSE frames
|
| 36 |
+
SSE response header: Cache-Control: no-cache, X-Accel-Buffering: no
|
| 37 |
+
```
|
| 38 |
+
|
| 39 |
+
### Planner: `app/planner.py`
|
| 40 |
+
|
| 41 |
+
- Entry: `plan(query, model, on_token) → Plan`
|
| 42 |
+
- Model: `RIPRAP_PLANNER_MODEL` env, default `granite4.1:3b`
|
| 43 |
+
- Uses `llm.chat(format="json")` with `temperature=0` for deterministic JSON output via Ollama's constrained-decode mode
|
| 44 |
+
- Pre-filter: `_not_implemented_message(query)` checks two regex patterns (retrospective, ranking) and returns early with a `Plan(intent="not_implemented")` so no LLM call is made
|
| 45 |
+
- Post-validator: `_validate(d, raw_query)` sanitizes intent, targets, specialists against the declared INTENTS/SPECIALISTS dicts; adds floor specialists via `_required_specialists(intent)` if planner omitted them
|
| 46 |
+
- Floor specialists (always added regardless of planner output): geocode+sandy+dep_stormwater+microtopo for single_address; nta_resolve+sandy+dep_stormwater+nyc311 for neighborhood; nws_alerts+noaa_tides for live_now
|
| 47 |
+
- Returns: `Plan(intent, targets: list[dict], specialists: list[str], rationale: str)`
|
| 48 |
+
|
| 49 |
+
### FSM: `app/fsm.py`
|
| 50 |
+
|
| 51 |
+
- Entry: `build_app(query) → Burr Application`; `run(query) → dict`; `iter_steps(query) → generator`
|
| 52 |
+
- Burr 0.x `ApplicationBuilder` with `with_state(query=query, trace=[])`, `with_entrypoint("geocode")`
|
| 53 |
+
- Actions registered in dict order, transitions are consecutive pairs (linear, not DAG)
|
| 54 |
+
- Each `@action` writes one state key + appends to `trace` list
|
| 55 |
+
- Out-of-NYC guard: `_NYC_S/W/N/E = 40.49, -74.27, 40.92, -73.69` — NYC-specific specialists skip with `"out of NYC scope"` reason; live/national specialists (NWS/NOAA/TTM) run unconditionally
|
| 56 |
+
- Thread-locals for streaming (since Burr runs sync in a background thread):
|
| 57 |
+
- `set_strict_mode(bool)` / `_current_strict_mode()`
|
| 58 |
+
- `set_token_callback(fn)` / `_current_token_callback()`
|
| 59 |
+
- `set_mellea_attempt_callback(fn)` / `_current_mellea_attempt_callback()`
|
| 60 |
+
- `set_planned_specialists(set)` / `_current_planned_specialists()`
|
| 61 |
+
- `set_user_query(str)` / `_current_user_query()`
|
| 62 |
+
- `set_planner_intent(str)` / `_current_planner_intent()`
|
| 63 |
+
- `iter_steps` spawns a daemon thread running `app.iterate(halt_after=["reconcile"])`; snaps threadlocals from caller thread and re-installs on iterate thread; deduplicates trace records by (step_name, started_at)
|
| 64 |
+
- Heavy-specialist gate: `_HEAVY_SPECIALISTS_ENABLED` = True when `RIPRAP_LLM_PRIMARY != ollama` OR `RIPRAP_ML_BASE_URL` is set; otherwise False. Controls whether prithvi_live, terramind, eo_chip, terramind_lulc, terramind_buildings fire
|
| 65 |
+
- NYCHA register gate: `_NYCHA_REGISTERS_ENABLED` = controlled by `RIPRAP_NYCHA_REGISTERS=1` (default off); registers load a 91 MB GeoJSON file on first call
|
| 66 |
+
|
| 67 |
+
### Full action sequence (default, single_address)
|
| 68 |
+
|
| 69 |
+
| # | Action name | State key written | Data source |
|
| 70 |
+
|---|---|---|---|
|
| 71 |
+
| 1 | geocode | geocode, lat, lon | NYC DCP Geosearch → OSM Nominatim fallback |
|
| 72 |
+
| 2 | sandy | sandy | data/sandy_inundation.geojson (lru_cache) |
|
| 73 |
+
| 3 | dep | dep | data/dep/*.gdb (3 scenarios, lru_cache) |
|
| 74 |
+
| 4 | floodnet | floodnet | api.floodnet.nyc Hasura GraphQL |
|
| 75 |
+
| 5 | nyc311 | nyc311 | Socrata erm2-nwe9 |
|
| 76 |
+
| 6 | noaa_tides | noaa_tides | api.tidesandcurrents.noaa.gov |
|
| 77 |
+
| 7 | nws_alerts | nws_alerts | api.weather.gov/alerts/active |
|
| 78 |
+
| 8 | nws_obs | nws_obs | api.weather.gov/stations/<id>/observations |
|
| 79 |
+
| 9 | ttm_forecast | ttm_forecast | ibm-granite/granite-timeseries-ttm-r2 (in-process or remote) |
|
| 80 |
+
| 10 | ttm_311_forecast | ttm_311_forecast | TTM r2 on local 311 weekly series |
|
| 81 |
+
| 11 | floodnet_forecast | floodnet_forecast | TTM r2 on nearest FloodNet sensor history |
|
| 82 |
+
| 12 | ttm_battery_surge | ttm_battery_surge | msradam/Granite-TTM-r2-Battery-Surge (remote or local) |
|
| 83 |
+
| 13 | microtopo | microtopo | data/nyc_dem_30m.tif, twi.tif, hand.tif |
|
| 84 |
+
| 14 | ida_hwm | ida_hwm | data/ida_2021_hwms_ny.geojson |
|
| 85 |
+
| 15 | mta_entrances | mta_entrances | data/mta_entrances.geojson |
|
| 86 |
+
| 16 | prithvi | prithvi_water | data/prithvi_ida_2021.geojson (166 polygons) |
|
| 87 |
+
| 17–22 | (heavy, if enabled) | prithvi_live, terramind, eo_chip, terramind_lulc, terramind_buildings | STAC/Sentinel-2, msradam/TerraMind-NYC-Adapters |
|
| 88 |
+
| 23 | rag | rag | Granite Embedding 278M over corpus/*.pdf (5 PDFs) |
|
| 89 |
+
| 24 | gliner | gliner | GLiNER typed-entity extraction over RAG hits |
|
| 90 |
+
| 25 | reconcile | paragraph, audit, mellea | Granite 4.1:8b via Mellea strict sampler |
|
| 91 |
+
|
| 92 |
+
### Capstone reconciliation: `app/reconcile.py` + `app/mellea_validator.py`
|
| 93 |
+
|
| 94 |
+
- `build_documents(state) → list[dict]` — emits one `{"role": "document <doc_id>", "content": "..."}` per specialist that fired, in Stones order; gatted by both specialist fire status and the out-of-NYC guard
|
| 95 |
+
- `trim_docs_to_plan(doc_msgs, planned_specialists)` — drops doc messages not matching planner's specialist set; saves ~30–50% prompt tokens; `RIPRAP_TRIM_DOCS=0` disables
|
| 96 |
+
- `EXTRA_SYSTEM_PROMPT` — the 4-section skeleton with the citation-discipline rules
|
| 97 |
+
- `augment_system_prompt(EXTRA_SYSTEM_PROMPT, query, intent)` — calls `app/framing.detect()` to classify question type (11 types, deterministic regex), then appends a `QUESTION-AWARE OPENING:` directive to the system prompt for non-generic questions
|
| 98 |
+
- Strict path (production): `reconcile_strict_streaming(doc_msgs, system_prompt, ...)` in `app/mellea_validator.py`
|
| 99 |
+
- Streams each attempt's tokens via `on_token(delta, attempt_idx)` callback
|
| 100 |
+
- After each attempt runs four checks, fires `on_attempt_end(attempt_idx, passed, failed)` callback
|
| 101 |
+
- On failure, appends a feedback user-turn naming failing sentences and rerolls
|
| 102 |
+
- Budget: `DEFAULT_LOOP_BUDGET` = 2 (Ollama primary) or 3 (vLLM primary), overridable via `RIPRAP_MELLEA_MAX_ATTEMPTS`
|
| 103 |
+
- Legacy path (non-strict): `reconcile.reconcile(state)` → streams tokens, then calls `verify_paragraph()` which drops sentences with ungrounded numbers (post-hoc, not rejection-sampling)
|
| 104 |
+
- The `step_reconcile` action detects strict mode via `_current_strict_mode()` and routes to one or the other
|
| 105 |
+
|
| 106 |
+
### Four Mellea grounding checks (`app/mellea_validator.py`)
|
| 107 |
+
|
| 108 |
+
1. **`numerics_grounded`** — `_check_no_invented_numbers()`: every non-trivial number in output appears verbatim in haystack (joined document content). Trivial set: `{0–10, 100, 311, 911, 211}`. Number regex: `\b-?\d[\d,]*(?:\.\d+)?\b` (word-boundary — skips `QN1206`, `B12`)
|
| 109 |
+
2. **`no_placeholder_tokens`** — `_check_no_placeholder_tokens()`: output contains none of `[source]`, `<document`, `</document`, `[doc_id]`
|
| 110 |
+
3. **`citations_dense`** — `_check_every_claim_cited()`: each non-trivial number has a `[doc_id]` citation somewhere in the same sentence (sentence boundary: `\.[\s)]` or end of string)
|
| 111 |
+
4. **`citations_resolve`** — `_check_referenced_doc_ids_exist()`: every `[id]` cited in output is a member of the input doc_id set
|
| 112 |
+
|
| 113 |
+
### SSE event vocabulary (`/api/agent/stream`)
|
| 114 |
+
|
| 115 |
+
| event | payload | when |
|
| 116 |
+
|---|---|---|
|
| 117 |
+
| `hello` | `{query}` | connection open |
|
| 118 |
+
| `plan_token` | `{delta}` | planner JSON tokens |
|
| 119 |
+
| `plan` | `{intent, targets, specialists, rationale}` | planner done |
|
| 120 |
+
| `stone_start` | `{name, tagline, description}` | first step in a Stone fires |
|
| 121 |
+
| `step` | `{step, ok, elapsed_s, result?, err?}` | each FSM action completes |
|
| 122 |
+
| `token` | `{delta, attempt?}` | Granite reconcile chunk (attempt idx resets on reroll) |
|
| 123 |
+
| `mellea_attempt` | `{attempt, passed, failed}` | end of each Mellea attempt |
|
| 124 |
+
| `stone_done` | `{name, tagline, description, n_steps}` | last step in a Stone done |
|
| 125 |
+
| `final` | full state dict (geocode, sandy, dep, paragraph, mellea, energy, ...) | reconcile done |
|
| 126 |
+
| `error` | `{err}` | exception |
|
| 127 |
+
| `done` | `{}` | stream closing |
|
| 128 |
+
|
| 129 |
+
---
|
| 130 |
+
|
| 131 |
+
## 3. The Five Stones, one section each
|
| 132 |
+
|
| 133 |
+
### Cornerstone — Hazard Reader
|
| 134 |
+
|
| 135 |
+
**Job:** Establish the historical and modeled flood record at the address. These are static datasets that do not change between queries.
|
| 136 |
+
|
| 137 |
+
**Specialists (file:function, what it does):**
|
| 138 |
+
|
| 139 |
+
| Specialist | File:function | What it returns |
|
| 140 |
+
|---|---|---|
|
| 141 |
+
| `step_sandy` | `fsm.py:step_sandy` | Boolean: inside 2012 Sandy Inundation Zone; `gpd.sjoin` point-in-polygon against `data/sandy_inundation.geojson` (91 MB) |
|
| 142 |
+
| `step_dep` | `fsm.py:step_dep` | Three DEP stormwater scenarios: `dep_extreme_2080` (3.66 in/hr rainfall, 2080 SLR), `dep_moderate_2050` (2.13 in/hr, 2050 SLR), `dep_moderate_current`; depth class 1–3 per point |
|
| 143 |
+
| `step_microtopo` | `fsm.py:step_microtopo` | Point elevation (m), HAND (height above nearest drainage, m), TWI (topographic wetness index), rel_elev_pct_200m, rel_elev_pct_750m, basin_relief_m from rasters in `data/` |
|
| 144 |
+
| `step_ida_hwm` | `fsm.py:step_ida_hwm` | USGS Hurricane Ida 2021 high-water marks; n_within_800m, max_height_above_gnd_ft, nearest_dist_m |
|
| 145 |
+
| `step_prithvi` | `fsm.py:step_prithvi` | Point-in-polygon against 166 pre-computed polygons in `data/prithvi_ida_2021.geojson`; inside_water_polygon bool, nearest_distance_m |
|
| 146 |
+
|
| 147 |
+
**Data sources:**
|
| 148 |
+
- Sandy: NYC OpenData `5xsi-dfpx` — downloaded to `data/sandy_inundation.geojson`
|
| 149 |
+
- DEP: NYC DEP Stormwater Flood Maps (2021), Esri FileGDBs at `data/dep/*.gdb`
|
| 150 |
+
- Microtopo: USGS 3DEP 30 m DEM via py3dep + whitebox-workflows for TWI/HAND computation, baked to `data/nyc_dem_30m.tif`, `data/twi.tif`, `data/hand.tif` by `scripts/compute_hydrology_indices.py`
|
| 151 |
+
- Ida HWMs: USGS STN Event 312 (NY State), baked to `data/ida_2021_hwms_ny.geojson` by `scripts/fetch_ida_hwms.py`
|
| 152 |
+
- Prithvi polygons: offline Prithvi-EO 2.0 segmentation on Sentinel-2 HLS tile (pre-event 2021-08-25, post-event 2021-09-02), baked to `data/prithvi_ida_2021.geojson` by `scripts/run_prithvi_ida.py`
|
| 153 |
+
|
| 154 |
+
**Models invoked:** Prithvi-EO 2.0 ran offline (TerraTorch) to produce the 166-polygon GeoJSON; no live model at query time for this Stone
|
| 155 |
+
|
| 156 |
+
**Failure modes:** Sandy/DEP/Prithvi fail silently if GeoJSON/GDB load errors; microtopo/ida_hwm fail if raster files absent from `data/`; all check `_in_nyc()` and skip with "out of NYC scope" for non-NYC addresses
|
| 157 |
+
|
| 158 |
+
**UI evidence cards:** Sandy inundation zone (boolean), DEP scenario depth classes (three cards), microtopo terrain indices, Ida HWM count/height, Prithvi polygon proximity
|
| 159 |
+
|
| 160 |
+
---
|
| 161 |
+
|
| 162 |
+
### Keystone — Asset Register
|
| 163 |
+
|
| 164 |
+
**Job:** Quantify what public assets (transit, housing, schools, hospitals, buildings) are exposed to the hazards the Cornerstone established.
|
| 165 |
+
|
| 166 |
+
**Specialists (file:function):**
|
| 167 |
+
|
| 168 |
+
| Specialist | File:function | What it returns |
|
| 169 |
+
|---|---|---|
|
| 170 |
+
| `step_mta_entrances` | `fsm.py:step_mta_entrances` | MTA subway entrances within 500 m: n_entrances, n_inside_sandy_2012, n_in_dep_extreme_2080; per-entrance elevation + HAND |
|
| 171 |
+
| `step_nycha` | `fsm.py:step_nycha` | NYCHA developments within 1.5 km: n_developments, n_majority_inside_sandy_2012, n_with_dep_2080_overlap; per-development footprint overlap percentages |
|
| 172 |
+
| `step_doe_schools` | `fsm.py:step_doe_schools` | DOE schools within 1 km: n_schools, n_inside_sandy_2012, n_in_dep_extreme_2080 |
|
| 173 |
+
| `step_doh_hospitals` | `fsm.py:step_doh_hospitals` | NYS DOH hospitals within 2 km: n_hospitals, n_inside_sandy_2012, n_in_dep_extreme_2080 |
|
| 174 |
+
| `step_terramind_buildings` | `fsm.py:step_terramind_buildings` | msradam/TerraMind-NYC-Adapters Buildings LoRA: pct_buildings, n_building_components in per-query Sentinel-2 chip; heavy, needs `_HEAVY_SPECIALISTS_ENABLED` |
|
| 175 |
+
|
| 176 |
+
**Data sources:**
|
| 177 |
+
- MTA: `data/mta_entrances.geojson` (pre-computed register with elevation + flood layer joins)
|
| 178 |
+
- NYCHA: `data/registers/nycha.json` (built by `scripts/build_nycha_register.py`)
|
| 179 |
+
- DOE schools: `data/registers/schools.json`
|
| 180 |
+
- DOH hospitals: fetched from NYS DOH Health Facility Certification (vn5v-hh5r) at register-build time
|
| 181 |
+
- TerraMind-Buildings: `msradam/TerraMind-NYC-Adapters` adapter `nyc-buildings-v1`, via `app/context/terramind_nyc.py:buildings()`
|
| 182 |
+
|
| 183 |
+
**Models invoked:** msradam/TerraMind-NYC-Adapters (TerraMind 1.0 base + Buildings LoRA), ~1.6 GB base + ~325 MB LoRA, loaded lazily and cached; runs on RIPRAP_ML remote if configured
|
| 184 |
+
|
| 185 |
+
**Failure modes:** NYCHA/DOE/DOH registers require `RIPRAP_NYCHA_REGISTERS=1` and the 91 MB sandy GeoJSON to be loaded — they fire disabled by default on local dev. TerraMind-Buildings skips silently if `eo_chip` didn't fire, deps unavailable, or heavy disabled
|
| 186 |
+
|
| 187 |
+
**UI evidence cards:** MTA entrance exposure summary, NYCHA development exposure, school exposure, hospital exposure, TerraMind building footprint fraction
|
| 188 |
+
|
| 189 |
+
---
|
| 190 |
+
|
| 191 |
+
### Touchstone — Live Observer
|
| 192 |
+
|
| 193 |
+
**Job:** Report current conditions — what sensors, 311 data, and EO imagery show right now.
|
| 194 |
+
|
| 195 |
+
**Specialists (file:function):**
|
| 196 |
+
|
| 197 |
+
| Specialist | File:function | What it returns |
|
| 198 |
+
|---|---|---|
|
| 199 |
+
| `step_floodnet` | `fsm.py:step_floodnet` | FloodNet sensors within 600 m: n_sensors, n_sensors_with_events, n_flood_events_3y, peak_event (max_depth_mm) |
|
| 200 |
+
| `step_311` | `fsm.py:step_311` | NYC 311 flood complaints within 200 m, last 5 years: count, by_descriptor breakdown, by_year |
|
| 201 |
+
| `step_nws_obs` | `fsm.py:step_nws_obs` | Nearest ASOS hourly METAR: station_id, precip_last_hour_mm, precip_last_3h_mm, precip_last_6h_mm |
|
| 202 |
+
| `step_noaa_tides` | `fsm.py:step_noaa_tides` | Nearest of 3 NOAA gauges (Battery 8518750, Kings Point 8516945, Sandy Hook 8531680): observed_ft_mllw, predicted_ft_mllw, residual_ft |
|
| 203 |
+
| `step_prithvi_live` | `fsm.py:step_prithvi_live` | Live Sentinel-2 L2A water segmentation via msradam/Prithvi-EO-2.0-NYC-Pluvial v2; pct_water_within_500m, pct_water_full, scene_date, cloud_cover; heavy |
|
| 204 |
+
| `step_terramind_lulc` | `fsm.py:step_terramind_lulc` | msradam/TerraMind-NYC-Adapters LULC LoRA: dominant_class, dominant_pct, per-class fractions; heavy |
|
| 205 |
+
|
| 206 |
+
**Data sources:**
|
| 207 |
+
- FloodNet: `https://api.floodnet.nyc/v1/graphql` — Hasura GraphQL, no auth; ~350 sensors
|
| 208 |
+
- 311: Socrata `erm2-nwe9` (live API call, 200 m buffer, last 5 years)
|
| 209 |
+
- NWS obs: `https://api.weather.gov/stations/<id>/observations/latest`; nearest of KNYC, KLGA, KJFK, KEWR, KFRG
|
| 210 |
+
- NOAA tides: `https://api.tidesandcurrents.noaa.gov/api/prod/datagetter`; 6-min cadence
|
| 211 |
+
- Prithvi live: Microsoft Planetary Computer STAC API for Sentinel-2 L2A; msradam/Prithvi-EO-2.0-NYC-Pluvial v2 weights
|
| 212 |
+
- TerraMind LULC: shared chip from `step_eo_chip` (also STAC/Planetary Computer)
|
| 213 |
+
|
| 214 |
+
**Models invoked:** Prithvi-EO-2.0-NYC-Pluvial v2 (300 M params, TerraTorch, flood IoU 0.5979 vs 0.10 base); TerraMind-NYC-Adapters LULC LoRA (mIoU 0.5866, +6.13 pp over full-FT)
|
| 215 |
+
|
| 216 |
+
**Failure modes:** FloodNet GraphQL call sets `verify=False` (self-signed cert); 311 Socrata times out gracefully; NOAA/NWS calls have 15-20 s timeouts; Prithvi/TerraMind LULC require `_HEAVY_SPECIALISTS_ENABLED` and `app/context/eo_chip_cache.py:fetch()` succeeding
|
| 217 |
+
|
| 218 |
+
---
|
| 219 |
+
|
| 220 |
+
### Lodestone — Projector
|
| 221 |
+
|
| 222 |
+
**Job:** Report forward-looking signals — NWS alerts, surge forecasts, and complaint-rate trends.
|
| 223 |
+
|
| 224 |
+
**Specialists (file:function):**
|
| 225 |
+
|
| 226 |
+
| Specialist | File:function | What it returns |
|
| 227 |
+
|---|---|---|
|
| 228 |
+
| `step_nws_alerts` | `fsm.py:step_nws_alerts` | Active NWS flood-relevant alerts at point (Flash Flood, Coastal Flood, etc.): n_active, list of alerts with event/severity/urgency/expires |
|
| 229 |
+
| `step_ttm_forecast` | `fsm.py:step_ttm_forecast` | TTM r2 zero-shot Battery surge residual: context 512 steps (~51 h at 6-min), horizon 96 steps (~9.6 h); forecast_peak_ft, forecast_peak_minutes_ahead; only emits doc when interesting (peak > 0.3 ft) |
|
| 230 |
+
| `step_ttm_311_forecast` | `fsm.py:step_ttm_311_forecast` | TTM r2 zero-shot on 52 weeks of 311 complaint history → 4-week forecast; forecast_mean_per_week, forecast_peak_per_week, accelerating flag |
|
| 231 |
+
| `step_floodnet_forecast` | `fsm.py:step_floodnet_forecast` | TTM r2 on nearest FloodNet sensor flood-event recurrence; forecast_28d_expected_events, accelerating; silent if sensor history too sparse |
|
| 232 |
+
| `step_ttm_battery_surge` | `fsm.py:step_ttm_battery_surge` | msradam/Granite-TTM-r2-Battery-Surge fine-tune: hourly cadence, 96 h horizon; forecast_peak_m, forecast_peak_hours_ahead; only emits doc when interesting |
|
| 233 |
+
|
| 234 |
+
**Data sources:**
|
| 235 |
+
- NWS alerts: `https://api.weather.gov/alerts/active` filtered to flood event types at the point's county
|
| 236 |
+
- TTM context data: live pull from NOAA CO-OPS 6-min water level (for Battery/Kings Point/Sandy Hook); Socrata 311 history; FloodNet GraphQL event history
|
| 237 |
+
- Battery surge fine-tune: NOAA hourly verified water level from Battery gauge (NOAA 8518750), loaded by `app/live/ttm_battery_surge.py`
|
| 238 |
+
|
| 239 |
+
**Models invoked:** ibm-granite/granite-timeseries-ttm-r2 (1.5 M params, ~30 MB, CPU-viable, zero-shot); msradam/Granite-TTM-r2-Battery-Surge fine-tune (same backbone, test MAE 0.1091 m, −41% vs persistence, −25% vs zero-shot)
|
| 240 |
+
|
| 241 |
+
**Failure modes:** NWS alerts call gracefully returns `n_active=0` on timeout; TTM models loaded lazily via `app/live/ttm_forecast.py:_load_model()` with `_DEPS_OK = False` fallback pattern; all Lodestone specialists fire unconditionally (no NYC bbox gate except floodnet/311 which are NYC-specific)
|
| 242 |
+
|
| 243 |
+
---
|
| 244 |
+
|
| 245 |
+
### Capstone — Synthesizer
|
| 246 |
+
|
| 247 |
+
**Job:** Read all documents produced by the four data-Stones and write a citation-grounded four-section prose briefing.
|
| 248 |
+
|
| 249 |
+
**Entry:** `app/mellea_validator.py:reconcile_strict_streaming(doc_msgs, system_prompt, user_prompt, loop_budget, on_token, on_attempt_end)`
|
| 250 |
+
|
| 251 |
+
**Document ordering in prompt:** geocode preamble → Cornerstone (sandy, dep_*, ida_hwm, prithvi_water, microtopo) → Keystone (mta_entrance_*, nycha_dev_*, doe_school_*, nyc_hospital_*, tm_buildings) → Touchstone (floodnet, nyc311, nws_obs, noaa_tides, prithvi_live, tm_lulc) → Lodestone (nws_alerts, ttm_forecast, ttm_311_forecast, floodnet_forecast_*, ttm_battery) → Policy (rag_*, gliner_*)
|
| 252 |
+
|
| 253 |
+
**Four-section skeleton (from `EXTRA_SYSTEM_PROMPT`):**
|
| 254 |
+
- **Status.** — dominant exposure signal, strongest doc_id citation
|
| 255 |
+
- **Empirical evidence.** �� Sandy, 311, FloodNet, Ida HWMs, Prithvi polygons
|
| 256 |
+
- **Modeled scenarios.** — DEP dep_* scenarios, microtopo terrain (HAND, TWI, percentile)
|
| 257 |
+
- **Policy context.** — one sentence per RAG hit, citing agency name + rag_* doc_id
|
| 258 |
+
|
| 259 |
+
**Four grounding checks (described in §2 above):** `numerics_grounded`, `no_placeholder_tokens`, `citations_dense`, `citations_resolve`
|
| 260 |
+
|
| 261 |
+
**Reroll feedback mechanism:** `_failing_sentences_for_citations(text)` identifies sentences with uncited numbers; on reroll the feedback user-turn names those specific sentences and instructs surgical citation additions
|
| 262 |
+
|
| 263 |
+
**Model:** `RIPRAP_RECONCILER_MODEL` env, default `granite4.1:8b`; `num_ctx=4096`, `num_predict=400`
|
| 264 |
+
|
| 265 |
+
**Return shape from `step_reconcile`:** `{paragraph, audit: {raw, dropped}, mellea: {rerolls, n_attempts, requirements_passed, requirements_failed, requirements_total, model, loop_budget}}`
|
| 266 |
+
|
| 267 |
+
---
|
| 268 |
+
|
| 269 |
+
## 4. The three NYC fine-tunes
|
| 270 |
+
|
| 271 |
+
### msradam/Prithvi-EO-2.0-NYC-Pluvial
|
| 272 |
+
|
| 273 |
+
- **HF Hub path:** `msradam/Prithvi-EO-2.0-NYC-Pluvial`
|
| 274 |
+
- **Base model:** IBM/NASA Prithvi-EO 2.0 (300 M params, ViT-L foundation model pre-trained on HLS Sentinel-2 multispectral imagery), Apache-2.0
|
| 275 |
+
- **Training data:** NYC HLS Sentinel-2 tiles with pluvial flood labels derived from USGS Ida HWM survey and NYC DEP records; Lovász-Softmax loss with copy-paste augmentation; trained on AMD Instinct MI300X
|
| 276 |
+
- **Metrics:** Test flood IoU 0.5979 vs 0.10 on Sen1Floods11 base (6× improvement)
|
| 277 |
+
- **Invocation:** Two paths:
|
| 278 |
+
- Offline (Cornerstone): produced `data/prithvi_ida_2021.geojson` via `scripts/run_prithvi_ida.py`; runtime does point-in-polygon, no model call
|
| 279 |
+
- Live (Touchstone): `app/flood_layers/prithvi_live.py:fetch(lat, lon)` — fetches latest Sentinel-2 L2A chip from Planetary Computer STAC, runs model forward pass, returns `pct_water_within_500m`, `pct_water_full`; slow (~30 s), gated by `_HEAVY_SPECIALISTS_ENABLED`; input 6-band S2L2A chip, output binary segmentation mask
|
| 280 |
+
- **Degradation:** If Planetary Computer STAC unavailable or cloud cover too high, `fetch()` returns `{ok: False, skipped: "...reason..."}` and no doc is emitted
|
| 281 |
+
|
| 282 |
+
### msradam/TerraMind-NYC-Adapters
|
| 283 |
+
|
| 284 |
+
- **HF Hub path:** `msradam/TerraMind-NYC-Adapters`
|
| 285 |
+
- **Base model:** TerraMind 1.0 (IBM/ESA any-to-any generative EO foundation model), Apache-2.0
|
| 286 |
+
- **Training data:** NYC Sentinel-2 + SAR chips matched to ESRI Land Cover 2020–2022 labels (LULC adapter) and NYC building footprints (Buildings adapter); trained on AMD Instinct MI300X in ~18 minutes
|
| 287 |
+
- **Metrics:** LULC test mIoU 0.5866 (+6.13 pp over full-FT baseline); Buildings test mIoU 0.5511; TiM 0.6023
|
| 288 |
+
- **Two adapters:**
|
| 289 |
+
- `lulc` — 5-class land cover (water, built, vegetation, bare, agriculture); invoked by `step_terramind_lulc` via `app/context/terramind_nyc.py:lulc(s2_tensor, s1rtc, dem)`
|
| 290 |
+
- `buildings` — binary building footprint mask; invoked by `step_terramind_buildings` via `app/context/terramind_nyc.py:buildings(s2_tensor, s1rtc, dem)`
|
| 291 |
+
- **Shared chip:** Both consume tensors from `step_eo_chip` → `app/context/eo_chip_cache.py:fetch(lat, lon)`, which fetches S2L2A + S1RTC + DEM chip once per query
|
| 292 |
+
- **Degradation:** If `eo_chip` didn't fire successfully, both LoRA specialists silently no-op. Lazy load + cached in-process; first call ~30 s, subsequent calls ~3–7 s
|
| 293 |
+
|
| 294 |
+
### msradam/Granite-TTM-r2-Battery-Surge
|
| 295 |
+
|
| 296 |
+
- **HF Hub path:** `msradam/Granite-TTM-r2-Battery-Surge`
|
| 297 |
+
- **Base model:** ibm-granite/granite-timeseries-ttm-r2 (1.5 M params, Tiny Time Mixer, Ekambaram et al. NeurIPS 2024), Apache-2.0
|
| 298 |
+
- **Training data:** NOAA CO-OPS Battery gauge (station 8518750) hourly verified water level, surge residual computed as verified minus harmonic tide; trained on AMD Instinct MI300X
|
| 299 |
+
- **Metrics:** Test MAE 0.1091 m, −41% vs persistence, −25% vs zero-shot TTM r2
|
| 300 |
+
- **Invocation:** `app/live/ttm_battery_surge.py:fetch()` — loads model via `tsfm_public.get_model()`, fetches NOAA hourly context, returns `{available, context_hours, horizon_hours: 96, forecast_peak_m, forecast_peak_hours_ahead, interesting}`; in-process on CPU
|
| 301 |
+
- **Input shape:** `(context_length, 1)` float tensor of hourly surge residuals; context = 336 h (~14 days)
|
| 302 |
+
- **Output shape:** `(96,)` hourly forecast, scanned for peak
|
| 303 |
+
- **Degradation:** `_DEPS_OK` module-level flag set at import time; on failure returns `{available: False, reason: "..."}`, no doc emitted
|
| 304 |
+
|
| 305 |
+
---
|
| 306 |
+
|
| 307 |
+
## 5. The deployment topology
|
| 308 |
+
|
| 309 |
+
### Local development
|
| 310 |
+
|
| 311 |
+
- Python 3.12 venv (`.venv`), `uv` for package management
|
| 312 |
+
- Ollama serving `granite4.1:3b` + `granite4.1:8b` locally
|
| 313 |
+
- `uvicorn web.main:app --host 127.0.0.1 --port 7860`
|
| 314 |
+
- `_HEAVY_SPECIALISTS_ENABLED = False` by default (no `RIPRAP_ML_BASE_URL` set, no vLLM)
|
| 315 |
+
- `RIPRAP_NYCHA_REGISTERS = 0` by default (heavy 91 MB GeoJSON loads)
|
| 316 |
+
- Granite Embedding 278M and TTM r2 download to HF cache on first query (~280 MB + ~30 MB)
|
| 317 |
+
- SvelteKit UI built at `web/sveltekit/build/`; rebuild only needed when sources change
|
| 318 |
+
|
| 319 |
+
### HF Space (production demo URL)
|
| 320 |
+
|
| 321 |
+
- URL: `https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space`
|
| 322 |
+
- Docker SDK, base `nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04`, hardware `cpu-basic` (actual hardware is cpu-basic, not T4 — the ARCHITECTURE.md mentions T4 but the Dockerfile's GPU notes are aspirational)
|
| 323 |
+
- Python 3.10 inside container (pinning `mellea<0.4`, `transformers<5`, `huggingface_hub<1`)
|
| 324 |
+
- `entrypoint.sh` flow:
|
| 325 |
+
1. Attempts EO toolchain install at runtime to `$HOME/.eo-pkgs` (bypasses HF build disk limit); if fails, terramind/prithvi-live silently skip
|
| 326 |
+
2. Starts `ollama serve` in background, polls until ready (up to 60 s)
|
| 327 |
+
3. Pulls `granite4.1:8b` at runtime if not cached (~5 GB, ~2 min first cold start); 3b is optional
|
| 328 |
+
4. Pre-warms 8b via `curl POST /api/generate` with `keep_alive=24h`
|
| 329 |
+
5. Launches `uvicorn web.main:app --host 0.0.0.0 --port 7860`
|
| 330 |
+
- `RIPRAP_OLLAMA_3B_TAG=granite4.1:8b` set in Dockerfile so planner routes to 8b (avoids disk cost of two separate model pulls)
|
| 331 |
+
- `web/main.py:_warm_caches()` on startup: loads sandy + DEP layers, optionally NYCHA registers, warms RAG (Granite Embedding 278M + 5 PDFs), pre-imports heavy ML stacks to avoid import races, warms Ollama models via HTTP
|
| 332 |
+
|
| 333 |
+
### AMD MI300X droplet (demo GPU path — currently destroyed)
|
| 334 |
+
|
| 335 |
+
- Two Docker containers on same host, both with `--device=/dev/kfd --device=/dev/dri`
|
| 336 |
+
- Container 1: `vllm/vllm-openai-rocm:v0.17.1` — serves `granite-4.1-8b` on port 8001
|
| 337 |
+
- `--max-model-len 8192`, `--served-model-name granite-4.1-8b`
|
| 338 |
+
- `GLOO_SOCKET_IFNAME=eth0` required or gloo fails to bind
|
| 339 |
+
- Container 2: `riprap-models:latest` (built from `services/riprap-models/Dockerfile`) — FastAPI on port 8002 (or 7860 per scripts)
|
| 340 |
+
- Endpoints: `GET /healthz`, `POST /v1/prithvi-pluvial`, `POST /v1/terramind`, `POST /v1/ttm-forecast`, `POST /v1/granite-embed`, `POST /v1/gliner-extract`
|
| 341 |
+
- Model loading: lazy + per-model threading.Lock to prevent double-load on concurrent requests
|
| 342 |
+
- ROCm device: `cuda` (ROCm's CUDA shim maps `cuda` to first `/dev/kfd` device)
|
| 343 |
+
|
| 344 |
+
**Env vars to connect HF Space to droplet:**
|
| 345 |
+
```
|
| 346 |
+
RIPRAP_LLM_PRIMARY=vllm
|
| 347 |
+
RIPRAP_LLM_BASE_URL=http://<ip>:8001/v1
|
| 348 |
+
RIPRAP_LLM_API_KEY=<token>
|
| 349 |
+
RIPRAP_ML_BASE_URL=http://<ip>:8002
|
| 350 |
+
RIPRAP_ML_API_KEY=<token>
|
| 351 |
+
```
|
| 352 |
+
|
| 353 |
+
**What breaks if droplet IP changes:** Set the four env vars above via `huggingface-cli space variables` and restart the Space. The LiteLLM Router builds at import time from env, so a Space restart is required.
|
| 354 |
+
|
| 355 |
+
**Deterministic redeploy:** `scripts/deploy_droplet.sh <new-ip> $TOKEN` — idempotent, ~10–20 min first run (pulls images, builds riprap-models); re-runs on same droplet ~1 min. Known fragile: `safetensors==0.8.0rc0` pin in `services/riprap-models/requirements-full.txt` is an RC and may fail on future pip resolves.
|
| 356 |
+
|
| 357 |
+
---
|
| 358 |
+
|
| 359 |
+
## 6. One query traced end-to-end: "80 Pioneer Street, Brooklyn"
|
| 360 |
+
|
| 361 |
+
**Query enters:** `GET /api/agent/stream?q=80+Pioneer+Street%2C+Brooklyn`
|
| 362 |
+
|
| 363 |
+
**1. Planner** (`app/planner.py:plan`)
|
| 364 |
+
- No not-implemented regex matches
|
| 365 |
+
- Calls `llm.chat(model="granite4.1:3b", messages=[system, user], format="json", stream=True, temperature=0)`
|
| 366 |
+
- Streams `plan_token` SSE events as JSON generates
|
| 367 |
+
- Returns `Plan(intent="single_address", targets=[{type:"address", text:"80 Pioneer Street, Brooklyn"}], specialists=[...], rationale="...")`
|
| 368 |
+
- Validator adds floor specialists: geocode, sandy, dep_stormwater, microtopo
|
| 369 |
+
- SSE: `plan` event emitted
|
| 370 |
+
|
| 371 |
+
**2. single_address.run** (`app/intents/single_address.py:run`)
|
| 372 |
+
- Sets threadlocals: `strict=True`, `planned_specialists={...}`, `user_query="80 Pioneer Street, Brooklyn"`, `planner_intent="single_address"`
|
| 373 |
+
- Registers `on_token` and `on_mellea_attempt` callbacks on `progress_q`
|
| 374 |
+
- Calls `fsm.iter_steps("80 Pioneer Street, Brooklyn")`
|
| 375 |
+
|
| 376 |
+
**3. FSM: step_geocode**
|
| 377 |
+
- `app/geocode.py:geocode_one("80 Pioneer Street, Brooklyn")`
|
| 378 |
+
- Detects borough hint "Brooklyn", calls DCP Geosearch with `size=8`, filters for Brooklyn results
|
| 379 |
+
- Returns `GeocodeHit(address="80 Pioneer Street, Brooklyn, NY 11231", borough="Brooklyn", lat=40.6772, lon=-74.0070, bbl="3-00589-0003", ...)`
|
| 380 |
+
- State: `{geocode: {...}, lat: 40.6772, lon: -74.0070}`
|
| 381 |
+
- SSE: `step` event `{step: "geocode", ok: true, elapsed_s: 0.4, result: {address:..., lat:..., lon:...}}`
|
| 382 |
+
|
| 383 |
+
**4. FSM: step_sandy**
|
| 384 |
+
- Confirmed inside NYC bbox
|
| 385 |
+
- `sandy_inundation.join(point)` — spatial join against `data/sandy_inundation.geojson`
|
| 386 |
+
- Red Hook is inside the 2012 Sandy inundation zone → `sandy=True`
|
| 387 |
+
- State: `{sandy: True}`
|
| 388 |
+
- SSE: `step` event → opens `stone_start: Cornerstone`
|
| 389 |
+
|
| 390 |
+
**5. FSM: step_dep**
|
| 391 |
+
- `dep_stormwater.join(pt, scen)` for each of 3 scenarios against `data/dep/*.gdb`
|
| 392 |
+
- Likely returns `dep_moderate_2050: depth_class=2 (Deep & Contiguous 1-4 ft)`, `dep_extreme_2080: depth_class=3 (Deep Contiguous >4 ft)`, `dep_moderate_current: depth_class=1`
|
| 393 |
+
|
| 394 |
+
**6–8. FSM: step_floodnet, step_311, step_noaa_tides**
|
| 395 |
+
- FloodNet: GraphQL POST to `api.floodnet.nyc` — checks sensors within 600 m of (40.6772, -74.0070)
|
| 396 |
+
- 311: Socrata API call for flood complaints within 200 m, last 5 years
|
| 397 |
+
- NOAA: fetches Battery gauge (closest of 3 stations to Red Hook), returns observed/predicted/residual
|
| 398 |
+
|
| 399 |
+
**9–12. FSM: TTM forecast steps**
|
| 400 |
+
- `ttm_forecast.summary_for_point(40.6772, -74.0070)`: loads ibm-granite/granite-timeseries-ttm-r2, fetches 512 steps of Battery residual history via NOAA, forecasts 96 steps ahead; emits doc only if peak > 0.3 ft
|
| 401 |
+
- `ttm_311_forecast.weekly_311_forecast_for_point(...)`: fetches 52-week complaint history for 200 m buffer from 311, runs TTM zero-shot
|
| 402 |
+
- `floodnet_forecast.summary_for_point(...)`: nearest sensor historical events → TTM recurrence forecast
|
| 403 |
+
- `ttm_battery_surge.fetch()`: msradam/Granite-TTM-r2-Battery-Surge, hourly context → 96 h forecast
|
| 404 |
+
|
| 405 |
+
**13–14. FSM: step_microtopo, step_ida_hwm**
|
| 406 |
+
- `microtopo.microtopo_at(40.6772, -74.0070)`: samples `data/nyc_dem_30m.tif`, `hand.tif`, `twi.tif` at point; returns elevation ~3 m, HAND ~0.8 m (near drainage), TWI ~11
|
| 407 |
+
- `ida_hwm.summary_for_point(...)`: checks `data/ida_2021_hwms_ny.geojson` within 800 m — Ida hit Queens hardest, Red Hook had no USGS HWMs
|
| 408 |
+
|
| 409 |
+
**15. FSM: step_mta_entrances**
|
| 410 |
+
- `app/registers/mta_entrances.py:summary_for_point(...)`: loads `data/mta_entrances.geojson`, finds entrances within 500 m (likely Smith-9th and Carroll St A/C/G stations)
|
| 411 |
+
|
| 412 |
+
**16. FSM: step_prithvi**
|
| 413 |
+
- `prithvi_water.summary_for_point(40.6772, -74.0070)`: point-in-polygon against `data/prithvi_ida_2021.geojson` 166 polygons; Red Hook is coastal — likely `inside_water_polygon=True` or close proximity
|
| 414 |
+
|
| 415 |
+
**17. FSM: step_rag**
|
| 416 |
+
- Builds query: "address 80 Pioneer Street, Brooklyn; inside Hurricane Sandy 2012 inundation zone; in Deep Contiguous pluvial scenario; flood resilience plan..."
|
| 417 |
+
- `rag.retrieve(q, k=3, min_score=0.45)`: Granite Embedding 278M cosine similarity over embedded corpus; likely returns `rag_npcc4` (NPCC4 coastal) + `rag_mta` (MTA Resilience Roadmap coastal references) + `rag_comptroller`
|
| 418 |
+
- External reads: none after startup (RAG index built at startup via `rag.warm()`)
|
| 419 |
+
|
| 420 |
+
**18. FSM: step_gliner**
|
| 421 |
+
- `gliner_extract.extract_for_rag_hits(hits)`: GLiNER NER extraction over RAG paragraphs; extracts agency names, dollar amounts, infrastructure projects, NYC locations, date ranges
|
| 422 |
+
- Emits `gliner_{source}` doc messages
|
| 423 |
+
|
| 424 |
+
**19. FSM: step_reconcile**
|
| 425 |
+
- `_current_strict_mode() = True`
|
| 426 |
+
- `build_documents(snap)` → ~15 doc messages
|
| 427 |
+
- `trim_docs_to_plan(doc_msgs, planned_specialists)` → drops specialists planner didn't ask for
|
| 428 |
+
- `augment_system_prompt(EXTRA_SYSTEM_PROMPT, query="80 Pioneer Street, Brooklyn", intent="single_address")` → `framing.detect()` → `generic_exposure` → no directive added (Red Hook query has no question-shape keywords)
|
| 429 |
+
- `reconcile_strict_streaming(doc_msgs, framed_prompt, loop_budget=2, on_token=..., on_attempt_end=...)`
|
| 430 |
+
- Attempt 0: streams tokens to frontend; runs 4 checks; likely passes
|
| 431 |
+
- If fails: feedback user-turn names failing sentences, attempt 1
|
| 432 |
+
- Emits: paragraph, mellea metadata (`rerolls=0`, `requirements_passed=[4/4]`)
|
| 433 |
+
- SSE: multiple `token` events → `mellea_attempt` event → `stone_done: Capstone` → `final` event
|
| 434 |
+
|
| 435 |
+
**Scoring** (computed in `web/main.py` from final state, or explicitly via `app/score.py:composite()`):
|
| 436 |
+
- `sandy=True` → empirical.sandy=1.0 → floor triggered (tier capped at 2)
|
| 437 |
+
- `dep_moderate_2050 depth_class=2` → regulatory.dep_moderate_2050=0.75
|
| 438 |
+
- `microtopo HAND=0.8` → hydrological.hand_band=1.0 (HAND < 1 m)
|
| 439 |
+
- composite likely ≥ 1.5 → raw tier 1; floor_applied=True → final tier capped at min(1,2) = 1 (floor is a floor, not a ceiling — the actual rule caps tier at no worse than 2; since tier 1 is better than tier 2, the floor is satisfied: tier stays 1)
|
| 440 |
+
- Final tier: 1 (High exposure)
|
| 441 |
+
|
| 442 |
+
---
|
| 443 |
+
|
| 444 |
+
## 7. What's robust vs fragile
|
| 445 |
+
|
| 446 |
+
### Robust (load-bearing, tested)
|
| 447 |
+
|
| 448 |
+
- **Silence-over-confabulation in specialists:** Every FSM action returns the declared state key as `None` on failure; `build_documents()` gates on `state.get(key) is not None`; Granite never invents content from absent documents. Pattern is consistent across 25 specialists.
|
| 449 |
+
- **NYC-scope guard:** `_in_nyc()` check in every FSM action + `build_documents()` scope_note mechanism for out-of-NYC addresses. National specialists (NOAA, NWS) still fire and a live-conditions-only briefing is produced.
|
| 450 |
+
- **LiteLLM Router failover:** `app/llm.py` auto-fails from vLLM to Ollama on timeout/5xx. `num_retries=0` so the Router doesn't burn seconds re-hitting dead endpoints. The Ollama fallback fires from the same call site.
|
| 451 |
+
- **Planner validator floor:** `_required_specialists()` adds geocode/sandy/dep/microtopo even if planner forgot them; prevents silent missing-Stone briefings.
|
| 452 |
+
- **Four Mellea grounding checks with reroll feedback:** The `_failing_sentences_for_citations()` targeted feedback mechanism is the reason neighborhood queries went from chronic 3/4 → 4/4. The identifier-aware `\b` regex in `_NUM_RE` is specifically why it stopped false-firing on NTA codes.
|
| 453 |
+
- **End-to-end probe suite:** `scripts/probe_addresses.py` drives `/api/agent/stream` against 5 addresses (442 E Houston, 80 Pioneer, 100 Gold, Hollis, Coney Island), asserts Stone fire patterns + Mellea 4/4 + four-section structure. Last green run: 5/5, 5.8–13.1 s per address at `RIPRAP_MELLEA_MAX_ATTEMPTS=3`.
|
| 454 |
+
- **Startup warmup in `web/main.py:_warm_caches()`:** Sandy, DEP, RAG, Ollama models, and heavy ML module pre-imports all happen before the first request. The startup function catches exceptions individually so one failure doesn't kill the app.
|
| 455 |
+
- **Threadlocal cleanup in `finally:` blocks:** `app/intents/single_address.py` always resets all five threadlocals in a `finally:` clause, preventing state bleeding between requests.
|
| 456 |
+
|
| 457 |
+
### Fragile (single points of failure, missing error handling)
|
| 458 |
+
|
| 459 |
+
- **Burr FSM concurrent queries:** `iter_steps()` mutates module-level Burr state. Two concurrent `single_address` queries to the same uvicorn worker will interleave threadlocals. No per-request isolation. Production HF Space is single-worker; local dev with `--workers 2` would break.
|
| 460 |
+
- **`build_documents()` complexity radon F=101:** ~750-line function with one `if`/`elif` branch per specialist. Order matters for the Granite prompt. Small edits risk subtle doc-ordering regressions that are silent but affect citation density.
|
| 461 |
+
- **entrypoint.sh EO install:** Runtime `pip install --target` for terratorch/einops/diffusers/timm/torchvision into `$HOME/.eo-pkgs` is brittle — if pip fails mid-install the marker isn't created and the next container start retries, but if the Space's filesystem cache persists a partial install, it might never clear. The build log won't show this failure clearly.
|
| 462 |
+
- **Droplet redeploy: Dockerfile unverified end-to-end:** The last full E2E Dockerfile build was never confirmed — the bootstrap droplet was destroyed before final verification. `safetensors==0.8.0rc0` in `services/riprap-models/requirements-full.txt` is an RC that may fail on a fresh pip resolve.
|
| 463 |
+
- **NOAA/NWS live calls without rate-limit handling:** `app/context/noaa_tides.py` and `nws_obs.py` call live APIs on every request with no caching, no retry-after handling. Under concurrent load or NOAA outage, specialists fail silently (returns `error` key in result dict) but every request re-hits the failed endpoint.
|
| 464 |
+
- **FloodNet GraphQL `verify=False`:** Certificate validation disabled in `app/context/floodnet.py:_gql()`. This is a permanent workaround for FloodNet's self-signed cert, not a temporary workaround.
|
| 465 |
+
- **Static asset cache:** `web/sveltekit/build/` assets have no cache-busting. When iterating on Svelte sources, browser hard-reload is required.
|
| 466 |
+
- **Planner 3b → 8b alias on HF Space:** `RIPRAP_OLLAMA_3B_TAG=granite4.1:8b` in the Dockerfile means both planner and reconciler use the 8b on the Space. If 3b is never pulled, the `granite4.1:3b` model is absent and an explicit call to that tag would fail. Current routing via the alias system prevents this, but a direct tag reference in new code would break.
|
| 467 |
+
- **vLLM `[doc_id=X]` normalization in `app/llm.py:_normalize_citations()`:** Applied per-chunk in streaming and once on non-streaming responses. If vLLM ever batches citation tokens across two stream chunks, the regex would miss them. This hasn't happened in practice but is a known theoretical gap.
|
| 468 |
+
- **RAG startup failure doesn't prevent startup:** `rag.warm()` is wrapped in a try/except that prints and continues. If sentence-transformers fails to load, all queries return without policy context — the briefing still works but silently loses the RAG section.
|
| 469 |
+
- **Mellea API shape versioning:** `reconcile_strict()` uses `mellea.start_session(backend_name="ollama")` from Mellea 0.3/0.4 (HF has 0.3, local has 0.4). The `_extract_text()` and `_extract_attempts()` helpers duck-type multiple attribute names. `reconcile_strict_streaming()` avoids Mellea's session entirely (hand-rolled) and is version-independent — this is the production path. The `reconcile_strict()` function is only exercised in offline contexts.
|
| 470 |
+
- **NYC 311 Socrata calls uncached:** Each query fetches fresh from Socrata. Under rate-limit or extended 311 maintenance, the specialist returns `n=0` and no 311 doc is emitted; the briefing silently lacks that signal.
|
| 471 |
+
|
| 472 |
+
### Known gaps / out-of-scope
|
| 473 |
+
|
| 474 |
+
- **`compare` intent defined in planner.py INTENTS dict** but no routing to a `compare.py` intent module exists in `web/main.py:api_agent_stream`. Planner would route to it but the runner would fall through to `single_address`.
|
| 475 |
+
- **Retrospective mode** (`what would Riprap have said on date X`): blocked at planner with not-implemented message. No historical data replay exists.
|
| 476 |
+
- **Cross-register ranking** (`rank top 5 neighborhoods by flood exposure`): blocked at planner. Would require a cross-register join that doesn't exist.
|
| 477 |
+
- **FEMA NFHL integration:** FEMA 1% and 0.2% floodplain indicators are in the scoring rubric (`app/score.py:REGULATORY`) but the corresponding FSM step and data layer are absent — they're stubbed at 0 in practice. The score still works but the FEMA regulatory sub-index doesn't contribute.
|
| 478 |
+
- **Sub-surface flooding (Ida basement mode):** Optical satellites can't see basement flooding. Prithvi correctly emits no polygons for inland Queens. This is documented as an honest scope limit, not a bug.
|
| 479 |
+
- **`/api/compare` endpoint** exists at `web/main.py:compare_stream` and works as a two-parallel-FSM-runs endpoint, but the SvelteKit UI doesn't expose a compare page (legacy `compare.html` was retired in v0.4.5).
|
| 480 |
+
|
| 481 |
+
---
|
| 482 |
+
|
| 483 |
+
## 8. The non-obvious decisions
|
| 484 |
+
|
| 485 |
+
### Why not a risk score from 0–100
|
| 486 |
+
|
| 487 |
+
The tier is a deterministic, published rubric (Cutter et al. 2003 construction, Tate 2012 equal-weights argument, Balica 2012 empirical floor). A continuous score would imply calibration against labeled damage outcomes — which don't exist here. Riprap has no closed claim records; producing "flood risk 0.73" without claims-driven calibration would be a fabricated precision. The tier is explicitly a prior (METHODOLOGY.md §1). FEMA Risk Rating 2.0 is the product to use if you want claims-driven numbers.
|
| 488 |
+
|
| 489 |
+
### Why silence over confabulation
|
| 490 |
+
|
| 491 |
+
Specialists that don't fire emit nothing. `build_documents()` gates on `state.get(key) is not None`. Granite's post-training includes grounded-generation discipline ("don't generate from absent documents"). This plus the Mellea citation checks means a calm-weather query produces no NWS-alerts section in the briefing rather than "no alerts were found" — that would be correct but uncitable. The section is absent. This is explicit in the system prompt: "Omit any section whose supporting facts are absent from the documents."
|
| 492 |
+
|
| 493 |
+
### Why public-record-only at runtime
|
| 494 |
+
|
| 495 |
+
Data governance: a newsroom with FOIL'd documents, or an agency with internal capital plans, can't paste that data into a vendor LLM (ARCHITECTURE.md §11). All specialist data comes from NYC OpenData, USGS, NOAA, NWS, FloodNet NYC (public sensor network). No commercial data; no private address databases. The system is reproducible and auditable.
|
| 496 |
+
|
| 497 |
+
### Why the four epistemic tiers (empirical / modeled / proxy / synthetic)
|
| 498 |
+
|
| 499 |
+
The distinction matters for how much weight to give each signal, documented in ARCHITECTURE.md §1.2. Empirical (Sandy HWMs, Ida HWMs, FloodNet events) = something flooded a place and was measured. Modeled scenarios (DEP, FEMA NFHL) = hydraulic simulation under assumptions. Proxy (311 complaints, HAND, TWI) = indirect indicators. Synthetic prior (TerraMind synthesis) = generative model output, never "imaged" or "reconstructed." The `build_documents()` function embeds these interpretive framing sentences directly into the doc bodies so Granite is instructed in the document itself how to characterize each source.
|
| 500 |
+
|
| 501 |
+
### Why the Five Stones names
|
| 502 |
+
|
| 503 |
+
Functional grouping for a trace UI with 25+ specialists. Stonework vocabulary maps to function: Cornerstone remembers the foundation (static hazard record); Keystone is the load-bearing arch piece (what's exposed); Touchstone is the evaluative reference (current state); Lodestone draws you toward something (forecast pull); Capstone is the crown that holds the vault (synthesis). The names let a non-technical demo audience follow the 25-step trace without reading each step label.
|
| 504 |
+
|
| 505 |
+
### Why citation-grounded prose vs structured output
|
| 506 |
+
|
| 507 |
+
JSON structured output (tier + per-field arrays) is easy to produce but hard to cite in a grant application or news article. The four-section prose format with `[doc_id]` tags produces text a planner can quote in a FEMA BRIC sub-application or a journalist can use verbatim with inline sourcing. The citation tags map to clickable source chips in the frontend. Structured JSON of the underlying specialist outputs is also available in the `final` SSE event for machine consumption.
|
| 508 |
+
|
| 509 |
+
### Why Mellea rejection sampling (vs post-hoc sentence dropping)
|
| 510 |
+
|
| 511 |
+
The original `verify_paragraph()` in `app/reconcile.py` drops sentences after generation. This produces a shorter briefing and a silent quality improvement — but the user sees a briefing that may have had sentences removed. The Mellea rejection sampler rerolls the entire generation when it fails, and streams each attempt's tokens to the user live (visible progress), then shows a green/amber inline banner. The user understands the system is enforcing quality, not silently deleting content. Psychologically this is more defensible in a professional context.
|
| 512 |
+
|
| 513 |
+
### Why planner-then-Capstone two-LLM split
|
| 514 |
+
|
| 515 |
+
The planner is a structured-output routing task (small JSON, deterministic, temperature=0). It should be fast and cheap. The reconciler is a long-form synthesis task requiring dense citation discipline — it benefits from the larger context window and stronger instruction-following of the 8b model. Using 3b for routing keeps TTFB low (planner JSON appears in ~2 s vs ~8 s for 8b). On the HF Space both aliases map to 8b via `RIPRAP_OLLAMA_3B_TAG=granite4.1:8b` to avoid disk cost, accepting the TTFB penalty.
|
| 516 |
+
|
| 517 |
+
### Why LiteLLM Router
|
| 518 |
+
|
| 519 |
+
The alternative was a hand-rolled `if primary == "vllm": ... else: ollama.chat(...)` dispatch. LiteLLM's Router gives model aliasing, failover, and a common call signature for free. The ~250-line shim in `app/llm.py` covers: Ollama-vs-vLLM backend selection, document-role message extraction for vLLM's HF chat template, `[doc_id=X]` → `[X]` citation normalization, JSON-mode translation, and backend info for the UI badge. Any future backend (mlx-lm, llama.cpp, etc.) is a 10-line entry in `_build_router()`.
|
| 520 |
+
|
| 521 |
+
### Why vLLM emits `[doc_id=X]` while Ollama emits `[X]`
|
| 522 |
+
|
| 523 |
+
Ollama's Granite 4.1 Modelfile template lifts `role="document <id>"` messages into a `<documents>` block and the model emits bare `[X]` citations. The HF tokenizer template used by vLLM emits `[doc_id=X]`. The rest of Riprap (Mellea regex, frontend citation chip parser, sources footer) was written against `[X]`. The `_CITE_NORMALIZE_RE` in `app/llm.py` normalizes per-chunk in streaming, preventing any vLLM-specific citation format from leaking downstream.
|
| 524 |
+
|
| 525 |
+
### Why Prithvi runs offline (baked GeoJSON) while TTM runs live
|
| 526 |
+
|
| 527 |
+
Prithvi-EO 2.0 with TerraTorch needs GPU and minutes per HLS tile. Running it per-query on a CPU-basic Space is not viable. The 166-polygon GeoJSON was computed once on AMD MI300X, filtered (>30,000 sqft to drop noise, <1 km² to drop tidal artifacts), and committed. The runtime FSM does point-in-polygon (milliseconds). This is honest about what EO models earn their keep on: a one-time defensible event-level signal, not per-request inference. TTM r2 at 1.5 M params runs in milliseconds on CPU — no such tradeoff exists.
|
| 528 |
+
|
| 529 |
+
### Why `citations_dense` uses sentence scope, not character window
|
| 530 |
+
|
| 531 |
+
The original implementation used `~40 chars` proximity between a number and its citation tag. This was fragile for normal English sentence structure ("The address has **11 flood-related complaints** [nyc311] within 200 m"). The citation might be 60 chars from the number. Switching to sentence scope (`.[\s)]` split) eliminated the chronic 3/4 neighborhood-query failure mode. "Sentence scope" is also how human readers actually assign attribution — the citation at the end of the sentence covers the claim anywhere in that sentence.
|
| 532 |
+
|
| 533 |
+
---
|
| 534 |
+
|
| 535 |
+
## 9. What's next
|
| 536 |
+
|
| 537 |
+
From `OPEN-ISSUES.md`, `CLAUDE.md` polish targets, and code-level TODO comments, in priority order for the May 13 ASCE presentation:
|
| 538 |
+
|
| 539 |
+
1. **Demo-script dry run against live Space.** Space sometimes sleeps after idle; cold start is 30–90 s. Pre-ping the Space before presenting. Verify the backend pill shows correct hardware.
|
| 540 |
+
2. **`compare` intent wiring.** `planner.py` declares the `compare` intent (noted as `NOT_IMPLEMENTED` comment — actually the planner doesn't short-circuit compare, it just routes to single_address by default). If you want the compare flow to work end-to-end, `web/main.py:api_agent_stream` needs routing to `i_addr.run` twice in parallel, or a new `compare.py` intent module.
|
| 541 |
+
3. **FEMA NFHL layer.** The scoring rubric has `fema_1pct` and `fema_02pct` weights but no FSM step or data layer. Adding the FEMA NFHL download and a `step_fema_nfhl` action would materially improve Regulatory sub-index accuracy for addresses in AE/VE zones that aren't in Sandy extent.
|
| 542 |
+
4. **NYCHA/DOE/DOH registers on Space.** `RIPRAP_NYCHA_REGISTERS=0` by default. Enabling on HF Space would add 3 more Keystone specialists to every single_address query but requires the 91 MB sandy GeoJSON pre-load to complete within Space startup time.
|
| 543 |
+
5. **Droplet redeploy verification.** The `services/riprap-models/Dockerfile` was never tested end-to-end. The `safetensors==0.8.0rc0` RC pin is the most likely failure point. Next droplet bring-up should test this first.
|
| 544 |
+
6. **Experiments `OPEN-ISSUES.md` items.** All four issues are in `experiments/` only (F821 numpy annotation in exp17, f-string Py 3.12+ syntax in exp18, B023 closure variable in exp05, F841 unused api in exp18). Won't affect production but clean up the codebase.
|
| 545 |
+
7. **Reranker integration.** `app/rag.py` has a full `_ensure_reranker()` and `RIPRAP_RERANKER_ENABLE` flag for `ibm-granite/granite-embedding-reranker-english-r2` cross-encoder. Off by default (no HF Space disk for the CrossEncoder model). Enabling on the AMD droplet path would improve Policy context quality at no latency cost.
|
| 546 |
+
8. **Historical replay / retrospective mode.** Blocked at planner with not-implemented message. Substantial feature: would require snapshotting specialist output at query time or storing NOAA/311/FloodNet historical pull results.
|
| 547 |
+
|
| 548 |
+
---
|
| 549 |
+
|
| 550 |
+
## 10. Quick reference: files that matter
|
| 551 |
+
|
| 552 |
+
| Task | Open first |
|
| 553 |
+
|---|---|
|
| 554 |
+
| **Add a new specialist** | `app/fsm.py` (add `@action` + wire into `build_app()`), `app/reconcile.py:build_documents()` (add doc emission), `app/intents/single_address.py` (no change usually needed), `web/sveltekit/src/` (add step label + source card) |
|
| 555 |
+
| **Change the briefing structure / system prompt** | `app/reconcile.py:EXTRA_SYSTEM_PROMPT`, then `app/intents/neighborhood.py:EXTRA_SYSTEM_PROMPT` for neighborhood path; rebuild `web/sveltekit` if adding new section rendering |
|
| 556 |
+
| **Tune the Mellea grounding checks** | `app/mellea_validator.py` — `_NUM_RE`, `_TRIVIAL_NUMS`, `_check_every_claim_cited()`, `_failing_sentences_for_citations()` |
|
| 557 |
+
| **Change which backend (vLLM vs Ollama)** | `app/llm.py` env vars; no code change needed |
|
| 558 |
+
| **Add a new intent** | `app/planner.py:INTENTS` + `SPECIALISTS` entries, `_required_specialists()`, then new `app/intents/<intent>.py`; wire in `web/main.py:api_agent_stream` and `api_agent` |
|
| 559 |
+
| **Change the exposure tier scoring** | `app/score.py:REGULATORY/HYDROLOGICAL/EMPIRICAL` dicts + `TIER_BREAKPOINTS`; update `METHODOLOGY.md` |
|
| 560 |
+
| **Debug why a specialist fired wrong** | `scripts/probe_mellea.py --query "<address>" --runs 1`; check step events in SSE stream; look at `final.mellea.requirements_failed` |
|
| 561 |
+
| **Rebuild the frontend** | `cd web/sveltekit && npm run build` (new design-system UI); `cd web/svelte && npm run build` (legacy Svelte 5 custom elements to `web/static/dist/riprap.js`) |
|
| 562 |
+
| **Run the full end-to-end test** | `.venv/bin/python scripts/probe_addresses.py` |
|
| 563 |
+
| **Rebuild the pre-computed registers** | `scripts/build_mta_entrances_register.py`, `scripts/build_nycha_register.py`, `scripts/build_schools_register.py` |
|
| 564 |
+
| **Rebuild Prithvi Ida polygons** | `scripts/run_prithvi_ida.py` — needs GPU + TerraTorch |
|
| 565 |
+
| **Rebuild the pitch deck** | `cd slides && make pdf html pptx` (needs marp-cli) |
|
| 566 |
+
| **Add a question-type framing** | `app/framing.py:_PATTERNS` + `_DIRECTIVES` |
|
| 567 |
+
| **Understand why a doc was missing from the briefing** | Check `build_documents()` in `app/reconcile.py` — each block has an explicit gate condition; also check `trim_docs_to_plan()` |
|
| 568 |
+
| **Understand the SSE stream structure** | `web/main.py:api_agent_stream`, the `_STEP_TO_STONE` dict, and the stone_start/stone_done wrapping logic |
|
| 569 |
+
| **Deploy to HF Space** | `git push && git push huggingface main`; monitor rebuild via `curl -sf "https://huggingface.co/api/spaces/lablab-ai-amd-developer-hackathon/riprap-nyc/runtime" | python3 -m json.tool` |
|
| 570 |
+
| **Deploy to AMD droplet** | `scripts/deploy_droplet.sh <ip> <token>`, then set Space env vars via `huggingface-cli space variables`, restart Space |
|
docs/sessions/2026-05-W19/CHANGES-2026-05-06.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deck changes — 2026-05-06 overnight pass
|
| 2 |
+
|
| 3 |
+
Branch: `comms-overnight-2026-05-06`
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
# Deck changes — 2026-05-06 content pass
|
| 8 |
+
|
| 9 |
+
Branch: `slides/content-pass-2026-05-06`
|
| 10 |
+
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
## Slide-by-slide diff
|
| 14 |
+
|
| 15 |
+
### Slide 02 · Solution — REFRAMED
|
| 16 |
+
|
| 17 |
+
**Lead rewritten to foreground what Riprap is, not the citation principle.**
|
| 18 |
+
Previous headline: "Every number cites its source. Or it doesn't appear."
|
| 19 |
+
New headline: "A flood-exposure briefing for any place in New York City."
|
| 20 |
+
|
| 21 |
+
The citation discipline is now a supporting sentence below the screenshot
|
| 22 |
+
placeholder ("Behind the prose: every numeric claim links to its primary
|
| 23 |
+
public-record source. Mellea rejection sampling refuses to publish what it
|
| 24 |
+
can't cite."), not the slide's thesis.
|
| 25 |
+
|
| 26 |
+
**Briefing codeblock removed.** The 442 East Houston example paragraph was
|
| 27 |
+
the slide's dominant visual. It has been replaced by a large screenshot
|
| 28 |
+
placeholder (min-height 240px) with the caption "[ screenshot of
|
| 29 |
+
riprap.nyc landing — to be added ]". The screenshot will carry the
|
| 30 |
+
demo-evidence load once captured from the live app.
|
| 31 |
+
|
| 32 |
+
**New subhead added.** Sets context before the placeholder: "Type an
|
| 33 |
+
address or neighborhood. Get a written briefing in 5–13 seconds, fusing
|
| 34 |
+
four temporal modes — Sandy 2012 inundation, current 311 history, FloodNet
|
| 35 |
+
sensor reads, NPCC4 projections — into one cited paragraph."
|
| 36 |
+
|
| 37 |
+
### Slide 04 · Architecture — EVIDENCE CARDS ADDED
|
| 38 |
+
|
| 39 |
+
**Four text-only Stone columns replaced by four evidence cards.** The cards
|
| 40 |
+
are reproduced as static inline HTML using the existing design-system
|
| 41 |
+
tokens (CSS custom properties from riprap.css), matching the EvidenceCard
|
| 42 |
+
component shape: source label + vintage tag, card title, data body with
|
| 43 |
+
Stone color, and doc_id footer with border-top divider.
|
| 44 |
+
|
| 45 |
+
Card content and origin:
|
| 46 |
+
- **Cornerstone · USGS 3DEP** — "Microtopography (HAND / TWI)" — four-row
|
| 47 |
+
stat grid: HAND 0.82 m, TWI 14.3, Elev 2.1 m MSL, Pct lower 78%.
|
| 48 |
+
Numbers are representative USGS 3DEP values for an LES test address.
|
| 49 |
+
doc_id: [topo]. Color: #475569 (slate).
|
| 50 |
+
- **Keystone · TerraMind-NYC** — "Building footprint coverage" — scalar
|
| 51 |
+
"48.41%" with sub "250 m radius · Buildings LoRA adapter". Sourced from
|
| 52 |
+
the TerraMind-NYC-Adapters experiment (experiments/20_terramind/).
|
| 53 |
+
doc_id: [keystone_bldg]. Color: #1A4480 (federal navy).
|
| 54 |
+
- **Touchstone · NYC 311** — "Flood complaints · 200 m buffer" — scalar
|
| 55 |
+
"19" service requests, "5-yr lookback". This exact figure appears in the
|
| 56 |
+
briefing codeblock that was removed from slide 02, sourced from the
|
| 57 |
+
442 E Houston probe. doc_id: [nyc311]. Color: #0E7490 (cyan).
|
| 58 |
+
- **Lodestone · Granite TTM r2** — "Surge residual nowcast" — scalar
|
| 59 |
+
"0.22 ft", "peak surge residual · 9.6 h horizon". Consistent with the
|
| 60 |
+
TTM r2 model's forecast horizon for Battery gauge residuals.
|
| 61 |
+
doc_id: [ttm_surge]. Color: #92400E (amber).
|
| 62 |
+
|
| 63 |
+
No existing PNG/SVG exports were found in slides/ or web/static/assets/.
|
| 64 |
+
Cards were reproduced in HTML/CSS rather than screenshotted — pragmatic
|
| 65 |
+
given the live app state at commit time.
|
| 66 |
+
|
| 67 |
+
**Flow header and Capstone footer preserved unchanged.**
|
| 68 |
+
|
| 69 |
+
Caption added below cards: "Real evidence cards rendered by the live
|
| 70 |
+
system · 442 East Houston Street, Manhattan."
|
| 71 |
+
|
| 72 |
+
### Slide 06 · Demo — CURTAIN-RAISE REWRITE
|
| 73 |
+
|
| 74 |
+
**"Try it live." replaced by "Live demo." — stripped to transitional handoff.**
|
| 75 |
+
Three "Watch for" cards removed (useful for silent reading; distract as a
|
| 76 |
+
video lead-in). The query is now the visual anchor, rendered in 28px mono
|
| 77 |
+
bold, centered, with no competing elements.
|
| 78 |
+
|
| 79 |
+
URL changed from `github.com/msradam/riprap-nyc` (full GitHub URL in
|
| 80 |
+
mono) to `riprap.nyc` (domain only, in accent blue). The GitHub URL
|
| 81 |
+
appears on the CTA slide where it belongs.
|
| 82 |
+
|
| 83 |
+
Footer stats line added: "13 seconds end-to-end · 4/4 grounding checks ·
|
| 84 |
+
all sources public-record" — matches the appendix receipts table.
|
| 85 |
+
|
| 86 |
+
### Slide 07 · What's next — COLUMNS REFRAMED
|
| 87 |
+
|
| 88 |
+
**ASCE conference reference dropped.** "Ida calibration · ASCE NY"
|
| 89 |
+
column removed (conference-specific, not relevant to the hackathon
|
| 90 |
+
audience).
|
| 91 |
+
|
| 92 |
+
**Methodology paper column dropped.** Replaced by "Historical-event mode"
|
| 93 |
+
— a first-class feature framing of retrospective FSM runs for calibration
|
| 94 |
+
against Sandy, Ida, Beryl. More concrete and demo-relevant than an
|
| 95 |
+
academic venue target.
|
| 96 |
+
|
| 97 |
+
**Stones v1.1 column rewritten** as "Break out the Stones" — same idea,
|
| 98 |
+
reframed around composability for civic-tech projects rather than version
|
| 99 |
+
numbering.
|
| 100 |
+
|
| 101 |
+
**New city list expanded.** Previous footer: "Houston (Harvey + Beryl
|
| 102 |
+
2024), Miami (king tides), Boston (CSO floods)". New column two:
|
| 103 |
+
Houston, Miami, Boston, Jakarta, Manila, Dhaka. Signals international
|
| 104 |
+
reach without claiming delivery.
|
| 105 |
+
|
| 106 |
+
**Slide title changed** from "The longer arc." to "What's next." —
|
| 107 |
+
matches the eyebrow label.
|
| 108 |
+
|
| 109 |
+
**Lead line repositioned** from footer paragraph to slide subhead
|
| 110 |
+
(mono, muted): "The architecture is NYC-specific by data choice,
|
| 111 |
+
not by code."
|
| 112 |
+
|
| 113 |
+
### CTA slide (slide 09) · URL FIX
|
| 114 |
+
|
| 115 |
+
**GitHub URL line-wrap fixed.** Previous: `# github.com/msradam/riprap-nyc`
|
| 116 |
+
as an h1 at 96px — wraps at the hyphen in the PDF render, producing
|
| 117 |
+
"riprap" / "nyc" on separate lines.
|
| 118 |
+
|
| 119 |
+
Fix: replaced the markdown h1 with an inline HTML div replicating all
|
| 120 |
+
h1 visual properties (IBM Plex Sans Bold, letter-spacing -0.03em, var
|
| 121 |
+
(--paper) color, same margin) but at 68px with `white-space: nowrap`.
|
| 122 |
+
68px is the largest size at which "github.com/msradam/riprap-nyc" (30
|
| 123 |
+
chars) fits within the CTA slide's 1104px content width (88px padding
|
| 124 |
+
each side). riprap.css unchanged.
|
| 125 |
+
|
| 126 |
+
---
|
| 127 |
+
|
| 128 |
+
## Visual regressions observed during rebuild
|
| 129 |
+
|
| 130 |
+
None. All 10 slides rendered without overflow warnings from Marp. The
|
| 131 |
+
architecture slide is dense but within bounds — the 4-card grid sits
|
| 132 |
+
between the flow header and Capstone footer with the caption line below.
|
| 133 |
+
|
| 134 |
+
## Where evidence card visuals came from
|
| 135 |
+
|
| 136 |
+
Reproduced in static HTML/CSS within the Marp slide. No existing PNG/SVG
|
| 137 |
+
card exports were found in the repo. The design tokens (CSS variables)
|
| 138 |
+
from riprap.css render identically in Marp/Puppeteer as in the SvelteKit
|
| 139 |
+
UI. Source data for each card is documented in the slide-by-slide diff
|
| 140 |
+
above.
|
| 141 |
+
|
| 142 |
+
---
|
| 143 |
+
|
| 144 |
+
## Slide-by-slide diff
|
| 145 |
+
|
| 146 |
+
### Cover (slide 1) — LOCKED, no changes
|
| 147 |
+
|
| 148 |
+
### Slide 01 · The problem — MODIFIED
|
| 149 |
+
|
| 150 |
+
**Quote attribution corrected.**
|
| 151 |
+
The removal took effect November 14, 2025, with CNN/TechCrunch coverage
|
| 152 |
+
on December 1–2. The prior slide said "Dec 2·2025 · CNN" and presented
|
| 153 |
+
the quote as a direct citation. Updated label to "Nov 14·2025 · CNN /
|
| 154 |
+
TechCrunch (paraphrase)" and reworded to "Zillow removed climate risk
|
| 155 |
+
scores from listings under pressure from the real-estate industry. In
|
| 156 |
+
their place: a link, far less visible." This is accurate to the
|
| 157 |
+
TechCrunch reporting and clearly marked as paraphrase.
|
| 158 |
+
|
| 159 |
+
**"Not a score" line added.**
|
| 160 |
+
New sentence at the bottom of the slide:
|
| 161 |
+
"Riprap is not a property-risk score. It is the audit trail behind one."
|
| 162 |
+
This is the True-Flood-Risk-vs-Riprap distinction. It positions Riprap
|
| 163 |
+
as the tool that produces the audit evidence, not a competing score
|
| 164 |
+
product — which is the honest framing and also the strongest counter
|
| 165 |
+
to the Zillow pullout narrative.
|
| 166 |
+
|
| 167 |
+
### Slide 02 · What riprap is — UNCHANGED
|
| 168 |
+
|
| 169 |
+
### NEW slide 03 · Architecture — INSERTED
|
| 170 |
+
|
| 171 |
+
New slide between "What riprap is" (former slide 02) and the track
|
| 172 |
+
slide (former slide 03, now slide 04). Rationale: the deck had no
|
| 173 |
+
architectural diagram. A judge scanning a 9-slide deck in 30 seconds
|
| 174 |
+
gets the system shape from this slide before the receipts slide.
|
| 175 |
+
|
| 176 |
+
Content: left-to-right then top-to-bottom flow:
|
| 177 |
+
- Free-text query → Planner (Granite 4.1 3B, intent classification)
|
| 178 |
+
- Planner routes to four evidence Stones (Cornerstone / Keystone /
|
| 179 |
+
Touchstone / Lodestone) displayed in a 4-column grid with Stone
|
| 180 |
+
color from the design system, tagline, and named data sources /
|
| 181 |
+
models under each
|
| 182 |
+
- Capstone (Granite 4.1 8B + Mellea, four named citation checks)
|
| 183 |
+
- Cited 4-section briefing, [doc_id] on every number
|
| 184 |
+
|
| 185 |
+
Title: "Five Stones fan out. One cited briefing comes back."
|
| 186 |
+
|
| 187 |
+
### Slide 03 → NEW slide 04 · The track — MODIFIED
|
| 188 |
+
|
| 189 |
+
**Major reframe.** Prior title: "Three of four hackathon tracks. One
|
| 190 |
+
project." New title: "Submitted to Fine-Tuning on AMD GPUs."
|
| 191 |
+
|
| 192 |
+
Prior framing listed all four tracks including "Build in Public ·
|
| 193 |
+
Skipped" (with muted opacity). Reads as hedging. New framing:
|
| 194 |
+
|
| 195 |
+
- Fine-Tuning track is marked "Primary" with full-opacity engaged
|
| 196 |
+
style and the explicit "Submitting here." label in the detail row.
|
| 197 |
+
Evidence: three Apache-2.0 NYC fine-tunes trained on MI300X,
|
| 198 |
+
published on HF Hub — named in the detail row.
|
| 199 |
+
- Agents and Vision tracks remain in the table marked "Supporting."
|
| 200 |
+
They are evidence of system depth, not co-primary claims.
|
| 201 |
+
- "Build in Public · Skipped" row dropped entirely.
|
| 202 |
+
|
| 203 |
+
**Rationale from research pass.** Fine-Tuning is the track with the
|
| 204 |
+
strongest verifiable artifacts. The three HF Hub model repos are public,
|
| 205 |
+
Apache-2.0, and the training code is in the repo. No other visible
|
| 206 |
+
submission to the hackathon has three published fine-tune artifacts.
|
| 207 |
+
Domain specificity (NYC flood risk) is the second differentiator.
|
| 208 |
+
|
| 209 |
+
### Slide 04 → NEW slide 05 · The receipts — UNCHANGED
|
| 210 |
+
|
| 211 |
+
The 5/5 address probe table and the three stat boxes are unchanged.
|
| 212 |
+
The numbers (5.8–13.1 s wall-clock, 4/4 Mellea grounding) come from
|
| 213 |
+
`scripts/probe_addresses.py` at 5/5 PASS. The instructions flagged
|
| 214 |
+
dependency on Track A's 20-query suite results; Track A has not yet
|
| 215 |
+
completed. **Flag for Adam before submission:** confirm the Mellea
|
| 216 |
+
4/4 claim holds in the 20-query suite when that run completes.
|
| 217 |
+
|
| 218 |
+
### Slide 05 → NEW slide 06 · Why it matters — UNCHANGED
|
| 219 |
+
|
| 220 |
+
Slide voice and content preserved exactly.
|
| 221 |
+
|
| 222 |
+
### Slide 06 → NEW slide 07 · What's next — REPLACED
|
| 223 |
+
|
| 224 |
+
Prior content: "Live demo" — endpoint URL, query, blockquote.
|
| 225 |
+
Reason to change: a live-demo slide is inert in a PDF or recorded
|
| 226 |
+
video. The URL belongs in the video recording, not a static slide.
|
| 227 |
+
|
| 228 |
+
New content: "The longer arc" — three boxes:
|
| 229 |
+
1. Ida calibration for ASCE NY (retrospective FSM run, May 2026
|
| 230 |
+
presentation target)
|
| 231 |
+
2. Stones v1.1 as standalone packages (Cornerstone, Touchstone,
|
| 232 |
+
Keystone, Lodestone published independently)
|
| 233 |
+
3. Methodology paper (citation-grounding pipeline as replicable
|
| 234 |
+
pattern for any geospatial LLM; open-access venue target)
|
| 235 |
+
|
| 236 |
+
Footer line: the cross-city scaffold note (Houston, Miami, Boston).
|
| 237 |
+
|
| 238 |
+
Rationale: shows the ASCE audience (who will see an adapted version
|
| 239 |
+
of this deck on May 13) where the technical work is going. The
|
| 240 |
+
hackathon audience sees the broader ambition. The slide is reusable
|
| 241 |
+
without modification for the ASCE talk.
|
| 242 |
+
|
| 243 |
+
### CTA (slide 8) — LOCKED, no changes
|
| 244 |
+
|
| 245 |
+
---
|
| 246 |
+
|
| 247 |
+
## Slide count
|
| 248 |
+
|
| 249 |
+
Before: 8 (cover + 6 content + CTA)
|
| 250 |
+
After: 9 (cover + 7 content + CTA)
|
| 251 |
+
|
| 252 |
+
The added slide is the architecture diagram. All other changes are
|
| 253 |
+
in-place content replacements.
|
| 254 |
+
|
| 255 |
+
---
|
| 256 |
+
|
| 257 |
+
## What was not changed
|
| 258 |
+
|
| 259 |
+
- The briefing codeblock on slide 02 — the output sample is the
|
| 260 |
+
deck's best visual and was left verbatim.
|
| 261 |
+
- All typography, color, and CSS class usage — the voice and register
|
| 262 |
+
are preserved.
|
| 263 |
+
- Source labels and specific numbers — no statistics were introduced
|
| 264 |
+
that are not already in RESEARCH.md or the probe suite results.
|
| 265 |
+
- The CNN/TechCrunch Zillow story date — confirmed real (Dec 2, 2025
|
| 266 |
+
CNN article; Nov 14 removal date). Attribution updated to mark
|
| 267 |
+
paraphrase.
|
| 268 |
+
|
| 269 |
+
---
|
| 270 |
+
|
| 271 |
+
## Outstanding verification item
|
| 272 |
+
|
| 273 |
+
**Slide 05 (THE RECEIPTS): 4/4 Mellea claim.**
|
| 274 |
+
The 5/5 address probe confirms 4/4 for these five addresses. Track A's
|
| 275 |
+
20-query suite has not yet completed. Before submitting to the hackathon,
|
| 276 |
+
run the full 20-query suite and confirm the numbers hold. If any query
|
| 277 |
+
produces < 4/4, either update the slide to reflect the actual number or
|
| 278 |
+
add a qualifier ("median 4/4 across the address probe suite"). Do not
|
| 279 |
+
ship a number that is not grounded.
|
docs/sessions/2026-05-W19/CODE-MORNING-BRIEF-2026-05-06.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Code Morning Brief — 2026-05-06
|
| 2 |
+
|
| 3 |
+
Engineering pass: bug fixes + AMD GPU deploy. All fixes committed to `main`.
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## Final state — end of day 2026-05-06
|
| 8 |
+
|
| 9 |
+
**5/5 address probe PASS on AMD MI300X vLLM path.**
|
| 10 |
+
|
| 11 |
+
```
|
| 12 |
+
[1/5] '442 East Houston Street, Manhattan' PASS 9.8s mellea=4/4 rerolls=1
|
| 13 |
+
[2/5] '80 Pioneer Street, Brooklyn' PASS 7.0s mellea=4/4 rerolls=0
|
| 14 |
+
[3/5] '100 Gold Street, Manhattan' PASS 10.2s mellea=4/4 rerolls=1
|
| 15 |
+
[4/5] 'Hollis, Queens' PASS 4.9s mellea=4/4 rerolls=0
|
| 16 |
+
[5/5] 'Coney Island, Brooklyn' PASS 4.3s mellea=4/4 rerolls=0
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
Demo queries captured at `/tmp/gpu-demo-q01.json`, `/tmp/gpu-demo-q02.json`,
|
| 20 |
+
`/tmp/gpu-demo-q13.json` (q13 captured in earlier session).
|
| 21 |
+
|
| 22 |
+
---
|
| 23 |
+
|
| 24 |
+
## Bugs resolved
|
| 25 |
+
|
| 26 |
+
### 1. Graceful not_implemented for retrospective + ranking queries
|
| 27 |
+
|
| 28 |
+
**Files:** `app/planner.py` — commit `d3fa102`
|
| 29 |
+
|
| 30 |
+
Pre-flight regex intercept before the LLM call short-circuits two
|
| 31 |
+
categories of queries that Riprap doesn't support and previously
|
| 32 |
+
silently misrouted:
|
| 33 |
+
|
| 34 |
+
- **Retrospective (q14/q18):** "What would Riprap have said on
|
| 35 |
+
Hurricane Ida?", "What was the flood status as of August 2021?" →
|
| 36 |
+
Returns `Plan(intent="not_implemented")` with a user-facing message.
|
| 37 |
+
- **Ranking (q15):** "Rank top 5 NYCHA buildings by flood exposure" →
|
| 38 |
+
Same treatment.
|
| 39 |
+
|
| 40 |
+
`web/main.py` handles `not_implemented` in both the streaming
|
| 41 |
+
(`/api/agent/stream`) and non-streaming (`/api/agent`) paths — emits
|
| 42 |
+
the message as a `final` event with `status: "not_implemented"` and
|
| 43 |
+
zeroed Mellea fields. No LLM call is made.
|
| 44 |
+
|
| 45 |
+
### 2. [doc_id] placeholder leaking from reconcile prompt
|
| 46 |
+
|
| 47 |
+
**Files:** `app/mellea_validator.py`, `app/reconcile.py` — commit `f68243b`
|
| 48 |
+
|
| 49 |
+
Root cause: `EXTRA_SYSTEM_PROMPT` used `[doc_id]` as an example
|
| 50 |
+
placeholder in the section skeleton. Granite echoed it literally.
|
| 51 |
+
Mellea's `citations_resolve` check then failed.
|
| 52 |
+
|
| 53 |
+
Two-part fix:
|
| 54 |
+
1. `mellea_validator.py` — added `[doc_id]` to `_check_no_placeholder_tokens`.
|
| 55 |
+
2. `reconcile.py` — rewrote `EXTRA_SYSTEM_PROMPT` to use real doc_id
|
| 56 |
+
examples (`[sandy]`, `[nyc311]`, `[microtopo]`, etc.) instead of
|
| 57 |
+
`[doc_id]` placeholders.
|
| 58 |
+
|
| 59 |
+
### 3. Geocoder fallback when Planning Labs API is down
|
| 60 |
+
|
| 61 |
+
**File:** `app/geocode.py` — commit `70892d1`
|
| 62 |
+
|
| 63 |
+
NYC Planning Labs Geosearch (`geosearch.planninglabs.nyc`) returned
|
| 64 |
+
503 during the session. All single_address queries failed "no coords".
|
| 65 |
+
|
| 66 |
+
Fix: Added `try/except` around `geocode(text, limit=8)` in
|
| 67 |
+
`geocode_one()`. Any exception (503, connection error, timeout) now
|
| 68 |
+
falls back to Nominatim, matching the existing upstate-hint path.
|
| 69 |
+
|
| 70 |
+
### 4. STAC searches hang indefinitely without HTTP timeout
|
| 71 |
+
|
| 72 |
+
**Files:** `app/context/eo_chip_cache.py`, `app/flood_layers/prithvi_live.py` — commit `70892d1`
|
| 73 |
+
|
| 74 |
+
`pystac_client` STAC searches and `rioxarray` COG downloads have no
|
| 75 |
+
per-request HTTP timeout; they hung indefinitely when Planetary Computer
|
| 76 |
+
was slow or unreachable.
|
| 77 |
+
|
| 78 |
+
Fix: Wrapped both `fetch()` functions in a
|
| 79 |
+
`concurrent.futures.ThreadPoolExecutor` with a hard wall-clock cap
|
| 80 |
+
(`timeout_s + 15 s`). The FSM step now always returns within budget
|
| 81 |
+
with `{"ok": False, "skipped": "timed out"}` on STAC hangs.
|
| 82 |
+
|
| 83 |
+
Controlled by existing `RIPRAP_EO_CHIP_ENABLE` / `RIPRAP_PRITHVI_LIVE_ENABLE`
|
| 84 |
+
env flags (default `1`). Set to `0` to skip STAC lookups entirely.
|
| 85 |
+
|
| 86 |
+
### 5. NYCHA/DOE/DOH registers hang on first query (91 MB polygon load)
|
| 87 |
+
|
| 88 |
+
**Files:** `app/fsm.py`, `web/main.py` — commit `70892d1`
|
| 89 |
+
|
| 90 |
+
`app/registers/nycha.py:_load_sandy_2263()` loads the full 91 MB
|
| 91 |
+
`data/sandy_inundation.geojson` via geopandas on first call. GDAL's
|
| 92 |
+
polygon-organisation pass on that file triggers a "processing may be
|
| 93 |
+
really slow" path — 3–5 min on M3 local dev, making the first
|
| 94 |
+
single_address query appear hung.
|
| 95 |
+
|
| 96 |
+
Fix: Split nycha / doe_schools / doh_hospitals behind a new
|
| 97 |
+
`RIPRAP_NYCHA_REGISTERS` env flag (default `0`, independent of the
|
| 98 |
+
GPU-heavy `RIPRAP_HEAVY_SPECIALISTS` flag). When set to `1`,
|
| 99 |
+
`web/main.py` pre-warms the lru_caches at startup.
|
| 100 |
+
|
| 101 |
+
For the demo: nycha/doe/doh data is absent from the briefing (Pioneer
|
| 102 |
+
Street and Gold Street have no NYCHA developments in the 2000 m radius
|
| 103 |
+
anyway). Re-enable post-demo when the server has a 3-min startup budget.
|
| 104 |
+
|
| 105 |
+
### 6. riprap-models Dockerfile: ROCm torch replaced by CUDA torch
|
| 106 |
+
|
| 107 |
+
**File:** `services/riprap-models/Dockerfile` — commits `488d524`, `8899d4a`
|
| 108 |
+
|
| 109 |
+
pip's resolver replaced the AMD ROCm `torch 2.9.1+git8907517` with CUDA
|
| 110 |
+
`torch 2.10.0` from PyPI. Fix: multi-stage build; Stage 1 captures clean
|
| 111 |
+
ROCm site-packages, Stage 2 installs deps, then COPY restores ROCm torch.
|
| 112 |
+
vLLM ENTRYPOINT conflict (`vllm: error: unrecognized arguments`) fixed by
|
| 113 |
+
`ENTRYPOINT []` in the Dockerfile.
|
| 114 |
+
|
| 115 |
+
---
|
| 116 |
+
|
| 117 |
+
## GPU deploy status
|
| 118 |
+
|
| 119 |
+
**Droplet:** `134.199.193.99` (AMD MI300X, DigitalOcean GPU)
|
| 120 |
+
|
| 121 |
+
| Container | Image | Port | Status |
|
| 122 |
+
|-----------------|-----------------------------------|------|---------|
|
| 123 |
+
| `vllm` | `vllm/vllm-openai-rocm:v0.17.1` | 8001 | Running |
|
| 124 |
+
| `riprap-models` | `riprap-models:latest` | 7860 | Running |
|
| 125 |
+
|
| 126 |
+
vLLM serves `granite-4.1-8b` at `http://134.199.193.99:8001/v1`.
|
| 127 |
+
riprap-models correct embedding route: `/v1/granite-embed` (smoke test
|
| 128 |
+
script still lists `/v1/embedding` — fix documented in `OPEN-ISSUES.md`).
|
| 129 |
+
|
| 130 |
+
**Bearer token:** stored in `AMD_TOKEN` at repo root (gitignored).
|
| 131 |
+
|
| 132 |
+
---
|
| 133 |
+
|
| 134 |
+
## Environment variables
|
| 135 |
+
|
| 136 |
+
```bash
|
| 137 |
+
# Local dev → AMD GPU
|
| 138 |
+
export RIPRAP_LLM_PRIMARY=vllm
|
| 139 |
+
export RIPRAP_LLM_BASE_URL=http://134.199.193.99:8001/v1
|
| 140 |
+
export RIPRAP_LLM_API_KEY=$(cat AMD_TOKEN)
|
| 141 |
+
export RIPRAP_ML_BASE_URL=http://134.199.193.99:7860
|
| 142 |
+
export RIPRAP_ML_API_KEY=$(cat AMD_TOKEN)
|
| 143 |
+
export RIPRAP_EO_CHIP_ENABLE=0 # skip STAC lookups (Planetary Computer slow)
|
| 144 |
+
export RIPRAP_PRITHVI_LIVE_ENABLE=0 # skip STAC lookups
|
| 145 |
+
export RIPRAP_TERRAMIND_ENABLE=0 # skip DEM diffusion (slow on CPU)
|
| 146 |
+
# RIPRAP_NYCHA_REGISTERS defaults to 0 — don't set unless startup warmup is acceptable
|
| 147 |
+
|
| 148 |
+
.venv/bin/uvicorn web.main:app --host 127.0.0.1 --port 7861 --log-level info
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
HF Space env (huggingface-cli space variables):
|
| 152 |
+
```
|
| 153 |
+
RIPRAP_LLM_BASE_URL=http://134.199.193.99:8001/v1
|
| 154 |
+
RIPRAP_LLM_API_KEY=<token>
|
| 155 |
+
RIPRAP_ML_BASE_URL=http://134.199.193.99:7860
|
| 156 |
+
RIPRAP_ML_API_KEY=<token>
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
---
|
| 160 |
+
|
| 161 |
+
## How to verify
|
| 162 |
+
|
| 163 |
+
```bash
|
| 164 |
+
# 1. Smoke test
|
| 165 |
+
TOKEN=$(cat AMD_TOKEN)
|
| 166 |
+
scripts/smoke_test_gpu.sh 134.199.193.99 "$TOKEN"
|
| 167 |
+
# Expect: vllm_models PASS, vllm_chat_post PASS, models_health PASS,
|
| 168 |
+
# models_granite_embed_post PASS (correct route: /v1/granite-embed)
|
| 169 |
+
# vllm_chat GET FAIL (expected — GET is not a chat endpoint)
|
| 170 |
+
|
| 171 |
+
# 2. Full 5-address end-to-end probe via local server → AMD
|
| 172 |
+
RIPRAP_LLM_PRIMARY=vllm \
|
| 173 |
+
RIPRAP_LLM_BASE_URL=http://134.199.193.99:8001/v1 \
|
| 174 |
+
RIPRAP_LLM_API_KEY=$(cat AMD_TOKEN) \
|
| 175 |
+
RIPRAP_ML_BASE_URL=http://134.199.193.99:7860 \
|
| 176 |
+
RIPRAP_ML_API_KEY=$(cat AMD_TOKEN) \
|
| 177 |
+
RIPRAP_EO_CHIP_ENABLE=0 \
|
| 178 |
+
RIPRAP_PRITHVI_LIVE_ENABLE=0 \
|
| 179 |
+
RIPRAP_TERRAMIND_ENABLE=0 \
|
| 180 |
+
.venv/bin/python scripts/probe_addresses.py
|
| 181 |
+
# Want: 5/5 PASS
|
| 182 |
+
|
| 183 |
+
# 3. Manual vLLM smoke
|
| 184 |
+
curl -s -X POST http://134.199.193.99:8001/v1/chat/completions \
|
| 185 |
+
-H "Authorization: Bearer $(cat AMD_TOKEN)" \
|
| 186 |
+
-H "Content-Type: application/json" \
|
| 187 |
+
-d '{"model":"granite-4.1-8b","messages":[{"role":"user","content":"Reply OK"}],"max_tokens":4}' \
|
| 188 |
+
| python3 -m json.tool
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
---
|
| 192 |
+
|
| 193 |
+
## Droplet redeploy (if destroyed)
|
| 194 |
+
|
| 195 |
+
```bash
|
| 196 |
+
TOKEN=$(openssl rand -base64 24)
|
| 197 |
+
scripts/deploy_droplet.sh <new-ip> "$TOKEN"
|
| 198 |
+
# ~10-20 min on a fresh droplet
|
| 199 |
+
```
|
| 200 |
+
|
| 201 |
+
See `CLAUDE.md` → "Droplet redeploy" for full details.
|
| 202 |
+
|
| 203 |
+
---
|
| 204 |
+
|
| 205 |
+
## Open issues
|
| 206 |
+
|
| 207 |
+
See `OPEN-ISSUES.md`:
|
| 208 |
+
1. `experiments/` bugs (numpy annotation, f-string Py 3.12, closure loop, dead api)
|
| 209 |
+
2. `scripts/smoke_test_gpu.sh` tests `/v1/embedding` — correct route is `/v1/granite-embed`
|
| 210 |
+
3. NYCHA/DOE/DOH registers disabled by default — enable post-demo with `RIPRAP_NYCHA_REGISTERS=1` + startup warmup
|
docs/sessions/2026-05-W19/COMMS-OVERNIGHT-2026-05-06-MORNING-BRIEF.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Morning brief — comms overnight pass, 2026-05-07
|
| 2 |
+
|
| 3 |
+
Branch: `comms-overnight-2026-05-06`
|
| 4 |
+
Work is local-only, not pushed to remote or HF.
|
| 5 |
+
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
## Status
|
| 9 |
+
|
| 10 |
+
All four work streams completed. Research memos are in `research/`.
|
| 11 |
+
Deck is revised (9 slides, built to PDF/HTML/PPTX locally). Submission
|
| 12 |
+
copy is drafted in `submission/COPY-DRAFTS.md`. Cover image was not
|
| 13 |
+
auto-generated — a design brief is in that same file with the quickest
|
| 14 |
+
path (re-export the deck cover slide as PNG). One verification item
|
| 15 |
+
remains open before submission: the Mellea 4/4 claim on slide 05.
|
| 16 |
+
|
| 17 |
+
There is a branch-state anomaly to be aware of: commits during this
|
| 18 |
+
session landed on both `comms-overnight-2026-05-06` (the intended
|
| 19 |
+
branch) and `overnight-2026-05-06` (a prior session's branch). The
|
| 20 |
+
content is the same on both. `comms-overnight-2026-05-06` has the clean
|
| 21 |
+
set (research + deck + change log + submission copy). You can merge
|
| 22 |
+
either branch; both are local-only.
|
| 23 |
+
|
| 24 |
+
---
|
| 25 |
+
|
| 26 |
+
## Research pass — five bullets each
|
| 27 |
+
|
| 28 |
+
### AMD hackathon landscape (`research/AMD-HACKATHON-LANDSCAPE.md`)
|
| 29 |
+
|
| 30 |
+
- **Agents track dominates the visible field.** Most in-flight
|
| 31 |
+
submissions are multi-agent orchestration systems. Fine-Tuning
|
| 32 |
+
submissions are sparse; NyayaLLM is the only comparable one
|
| 33 |
+
(domain-specific legal LLM on MI300X), but it's single-model,
|
| 34 |
+
single-jurisdiction, and has no published artifacts.
|
| 35 |
+
- **Three published Apache-2.0 fine-tunes is the differentiator.**
|
| 36 |
+
No other visible submission mentions published model artifacts.
|
| 37 |
+
The three HF Hub repos are verifiable; judges can clone and run them.
|
| 38 |
+
- **The domain-tool penalty is real.** A 13-second cited flood briefing
|
| 39 |
+
is harder to demo than a 7-agent crisis system that spawns child
|
| 40 |
+
agents in real time. The architecture slide and the receipts table
|
| 41 |
+
need to close that gap before the civic-tech hook can land.
|
| 42 |
+
- **"Three of four tracks" was a liability.** The hackathon is
|
| 43 |
+
one-track submission. "Engaged in three tracks" reads as hedging.
|
| 44 |
+
Fine-Tuning is the right single-track argument.
|
| 45 |
+
- **Lablab.ai submission pages 403'd.** Project descriptions above are
|
| 46 |
+
from search snippets only. The full 30+ project list requires a
|
| 47 |
+
logged-in lablab.ai session. The landscape read is directional, not
|
| 48 |
+
exhaustive.
|
| 49 |
+
|
| 50 |
+
### Pitch deck landscape (`research/PITCH-DECK-LANDSCAPE.md`)
|
| 51 |
+
|
| 52 |
+
- **Problem-first into receipts-first is the right pattern for Riprap.**
|
| 53 |
+
The Zillow pullout gives the problem in one CNN headline. The 5/5
|
| 54 |
+
table is the receipts. Demo in the middle, fine-tune evidence before
|
| 55 |
+
the civic case.
|
| 56 |
+
- **The architecture diagram was the single biggest missing slide.**
|
| 57 |
+
Judges scanning a PDF without a system diagram can't assess technical
|
| 58 |
+
depth. The new slide 03 (Five Stones → Capstone flow) does that work
|
| 59 |
+
in one scan.
|
| 60 |
+
- **The "Live Demo" slide was inert in a static deck.** Repurposing to
|
| 61 |
+
"What's Next" opens the longer arc visible to both the hackathon
|
| 62 |
+
audience (May 10) and the ASCE audience (May 13). No content loss.
|
| 63 |
+
- **Do not lead with AI vocabulary; lead with civic vocabulary.**
|
| 64 |
+
"RPL §462(2)" and "NYC DEP" are signals of domain expertise, not
|
| 65 |
+
buzzwords. Name them early in the video, not in the deck's second
|
| 66 |
+
half.
|
| 67 |
+
- **5-minute video structure:** 0:00 problem sentence, 0:20 demo,
|
| 68 |
+
0:50 architecture, 1:30 receipts, 2:00 track argument (fine-tunes),
|
| 69 |
+
2:30 civic case, 3:30 what's next, 4:00 CTA. Full breakdown in the
|
| 70 |
+
research memo.
|
| 71 |
+
|
| 72 |
+
---
|
| 73 |
+
|
| 74 |
+
## Deck changes — condensed
|
| 75 |
+
|
| 76 |
+
| Slide | Before | After |
|
| 77 |
+
|---|---|---|
|
| 78 |
+
| 01 · Problem | CNN quote as direct citation, no counter-positioning | Quote marked as paraphrase, corrected to Nov 14 removal date; added "not a score" distinction |
|
| 79 |
+
| 02 · What riprap is | Unchanged | Unchanged |
|
| 80 |
+
| NEW 03 · Architecture | Did not exist | New: query → Planner → 4 evidence Stones (with data sources named) → Capstone + Mellea → briefing |
|
| 81 |
+
| 03 → 04 · The track | "Three of four tracks. One project." + Build in Public Skipped row | "Submitted to Fine-Tuning." Fine-Tuning = Primary, Agents/Vision = Supporting. Skipped row removed. |
|
| 82 |
+
| 04 → 05 · Receipts | Unchanged | Unchanged (see open item below) |
|
| 83 |
+
| 05 → 06 · Why it matters | Unchanged | Unchanged |
|
| 84 |
+
| 06 → 07 · Now / Demo | Live demo URL + blockquote (inert in static deck) | WHAT'S NEXT: Ida/ASCE calibration, Stones v1.1 packages, methodology paper |
|
| 85 |
+
| CTA | Unchanged | Unchanged |
|
| 86 |
+
|
| 87 |
+
Slide count: 8 → 9.
|
| 88 |
+
|
| 89 |
+
---
|
| 90 |
+
|
| 91 |
+
## Cover image
|
| 92 |
+
|
| 93 |
+
The cover image (`submission/cover-16x9.png`) was not auto-generated.
|
| 94 |
+
Design brief is in `submission/COPY-DRAFTS.md`.
|
| 95 |
+
|
| 96 |
+
**Quickest path:** export the cover slide from the deck PDF as a
|
| 97 |
+
1920×1080 PNG. The Marp cover slide already uses the correct tokens,
|
| 98 |
+
dam mark, and layout. From `slides/`:
|
| 99 |
+
|
| 100 |
+
```
|
| 101 |
+
npx @marp-team/marp-cli@latest deck.md --theme riprap.css \
|
| 102 |
+
--allow-local-files --images png
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
This generates `deck.001.png` (the cover slide) which is the 16:9
|
| 106 |
+
thumbnail. Rename to `submission/cover-16x9.png`.
|
| 107 |
+
|
| 108 |
+
---
|
| 109 |
+
|
| 110 |
+
## Submission copy — recommended
|
| 111 |
+
|
| 112 |
+
**Title:** `Riprap — Cited NYC flood briefings on AMD` (42 chars)
|
| 113 |
+
|
| 114 |
+
**Short (237 chars):**
|
| 115 |
+
Riprap writes NYC flood-exposure briefings where every numeric claim cites its source — or doesn't appear. Granite 4.1 8B on AMD MI300X, three Apache-2.0 NYC fine-tunes, Mellea citation grounding. 5/5 addresses, 4/4 checks every run.
|
| 116 |
+
|
| 117 |
+
**Long (~280 words):** in `submission/COPY-DRAFTS.md`, no changes needed.
|
| 118 |
+
|
| 119 |
+
**Runner-up title:** `Riprap: citation-grounded flood briefings`
|
| 120 |
+
|
| 121 |
+
---
|
| 122 |
+
|
| 123 |
+
## Three things to look at first
|
| 124 |
+
|
| 125 |
+
1. **Run the 20-query Mellea probe suite and check slide 05.**
|
| 126 |
+
The deck's "4/4 every run" claim is verified against the 5-address
|
| 127 |
+
probe. If Track A's 20-query stakeholder suite is complete, check
|
| 128 |
+
the grounding results. If any query failed at < 4/4, update the
|
| 129 |
+
slide. Do not submit a deck with a "4/4" claim that doesn't hold
|
| 130 |
+
across the wider suite. Command from `scripts/`:
|
| 131 |
+
```
|
| 132 |
+
.venv/bin/python scripts/probe_addresses.py
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
2. **Generate the cover image** from the deck cover slide (see above).
|
| 136 |
+
One npx command, one rename. Takes 2 minutes.
|
| 137 |
+
|
| 138 |
+
3. **Review the architecture slide (new slide 03)** in the rendered PDF.
|
| 139 |
+
It uses inline styles and box-grid classes. Verify it renders cleanly
|
| 140 |
+
in the PDF before submission — particularly the four Stone columns and
|
| 141 |
+
the Capstone row at the bottom. If the layout is cramped, reducing the
|
| 142 |
+
Stone cell font sizes by 1–2px will fix it. Source: `slides/deck.md`
|
| 143 |
+
lines ~103–160.
|
| 144 |
+
|
| 145 |
+
---
|
| 146 |
+
|
| 147 |
+
## Open questions that need Adam's call
|
| 148 |
+
|
| 149 |
+
**1. Track submission: Fine-Tuning is the call, but confirm.**
|
| 150 |
+
The research pass found no evidence against Fine-Tuning as primary. If
|
| 151 |
+
you have information about lablab.ai's scoring criteria that suggests
|
| 152 |
+
Agents is stronger (e.g., the FSM + Burr architecture is judged
|
| 153 |
+
separately), change slide 04 before submission. The deck frame is easy
|
| 154 |
+
to swap — the track-row badges are the only change.
|
| 155 |
+
|
| 156 |
+
**2. The CNN quote on slide 01 — exact vs paraphrase.**
|
| 157 |
+
Current: "Zillow removed climate risk scores from listings under pressure
|
| 158 |
+
from the real-estate industry. In their place: a link, far less visible."
|
| 159 |
+
Marked as paraphrase. If you want a direct quote for a public-facing
|
| 160 |
+
deck, the TechCrunch version is: "Zillow removed the listings' climate
|
| 161 |
+
scores. In their place is a subtle link to their records at First Street."
|
| 162 |
+
(TechCrunch, Dec 1, 2025.) Either is defensible; this is an editorial
|
| 163 |
+
call.
|
| 164 |
+
|
| 165 |
+
**3. ASCE talk (May 13) — which slides to adapt.**
|
| 166 |
+
The new "What's Next" slide (07) and the "Why it Matters" slide (06)
|
| 167 |
+
are the ASCE-relevant ones. For ASCE, slide 04 (The Track) should be
|
| 168 |
+
replaced with a "Methods" slide. The architecture diagram (slide 03)
|
| 169 |
+
and receipts (slide 05) travel unchanged. Make the branch decision:
|
| 170 |
+
fork a new `asce-2026-05-13` branch off this deck or iterate in place.
|
| 171 |
+
|
| 172 |
+
**4. `overnight-2026-05-06` branch cleanup.**
|
| 173 |
+
That branch has duplicate commits plus `e203d5f tests: add 20-query
|
| 174 |
+
stakeholder integration suite` from the prior session. Decide whether
|
| 175 |
+
to merge it into main, keep it as a holding branch, or delete it. The
|
| 176 |
+
comms work you need is all on `comms-overnight-2026-05-06`.
|
docs/sessions/2026-05-W19/OVERNIGHT-2026-05-06-MORNING-BRIEF.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Overnight pass — morning brief — 2026-05-06
|
| 2 |
+
|
| 3 |
+
> Branch: `overnight-2026-05-06`. Local-only, not pushed, not deployed.
|
| 4 |
+
> Read this in 5 min; everything detailed lives in linked sub-reports.
|
| 5 |
+
|
| 6 |
+
## Status one-liner
|
| 7 |
+
|
| 8 |
+
All four work streams landed. The audit committed mechanical fixes
|
| 9 |
+
only and flagged real bugs in `experiments/` for triage. The 20-query
|
| 10 |
+
suite ran twice (baseline + framed) end-to-end against local Granite +
|
| 11 |
+
local specialists. The question-aware Capstone framing lifted mean
|
| 12 |
+
framing 2.25 → 2.80 and produced three verdict-style openings (q01
|
| 13 |
+
"Yes", q02 "Disclosure is warranted", q13 "Vulnerability assessment:")
|
| 14 |
+
where there were zero before. The framing's stop condition fired
|
| 15 |
+
(12 < 3); option (a) — planner sub-classifier — is sketched in
|
| 16 |
+
`docs/QUESTION-AWARE-FRAMING.md` but explicitly NOT implemented per
|
| 17 |
+
your "don't silently expand scope" rule. One out-of-scope geocoder
|
| 18 |
+
bug surfaced and is documented in
|
| 19 |
+
`OVERNIGHT-2026-05-06-OUT-OF-SCOPE.md` (NOT fixed).
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## 1. Code audit — `audit/AUDIT-2026-05-06.md`
|
| 24 |
+
|
| 25 |
+
`ruff` found 106 issues across the whole repo. Mechanical fixes
|
| 26 |
+
applied to production code paths only (`app/`, `web/`, `scripts/`,
|
| 27 |
+
`services/`, `tests/`); `experiments/` was left alone. Vulture
|
| 28 |
+
confirmed only one F401 worth removing (`io` in `app/inference.py`);
|
| 29 |
+
the rest are kept per Adam's "vulture-confirmed only" rule.
|
| 30 |
+
|
| 31 |
+
**The four real bugs in `experiments/` (NOT touched, flagged for
|
| 32 |
+
Adam to triage):**
|
| 33 |
+
1. `experiments/17_riprap_integration/terramind_nyc.py:117` —
|
| 34 |
+
F821 references `np` in a type annotation; numpy isn't imported
|
| 35 |
+
at module top.
|
| 36 |
+
2. `experiments/18_terramind_nyc_lora/shared/eval_adapter.py:125` —
|
| 37 |
+
Py 3.12 nested f-string; will fail to import on the HF Space (3.10).
|
| 38 |
+
3. `experiments/05_terramind_nyc_finetune/training/verify_phase1.py:438` —
|
| 39 |
+
B023 closure-over-loop-variable, the standard "all closures see
|
| 40 |
+
the last value" trap.
|
| 41 |
+
4. `experiments/18_terramind_nyc_lora/shared/publish_hf.py:107` —
|
| 42 |
+
F841 `api` assigned but never used; may be a missing
|
| 43 |
+
`api.upload_*` call.
|
| 44 |
+
|
| 45 |
+
**Complexity hotspots** (flagged, NOT refactored — pre-demo freeze):
|
| 46 |
+
- `app/reconcile.py:build_documents` is **F=178** by cyclomatic
|
| 47 |
+
complexity. CLAUDE.md explicitly says don't touch pre-demo. Held.
|
| 48 |
+
- Other C+ functions: `mellea_validator.reconcile_strict_streaming` (D=23),
|
| 49 |
+
`planner._validate` (D=22), `rag.retrieve` (C=20), three more at
|
| 50 |
+
C=16-18. All expected; none touched.
|
| 51 |
+
|
| 52 |
+
**Lowest MI modules (still passable, not urgent):**
|
| 53 |
+
`app/intents/neighborhood.py` (32), `web/main.py` (37),
|
| 54 |
+
`scripts/probe_addresses.py` (36). Length is the cost of being
|
| 55 |
+
data-heavy / demo-front-door / probe-tester respectively. Post-demo
|
| 56 |
+
candidates for refactor.
|
| 57 |
+
|
| 58 |
+
**Commit:** `9cc6ec4 audit: mechanical fixes from ruff + vulture`.
|
| 59 |
+
|
| 60 |
+
---
|
| 61 |
+
|
| 62 |
+
## 2. 20-query stakeholder integration suite — `tests/integration/results/2026-05-06/SUMMARY.md`
|
| 63 |
+
|
| 64 |
+
The suite at `tests/integration/stakeholder_queries.py` drives
|
| 65 |
+
`/api/agent/stream` against 20 queries derived from `RESEARCH.md`:
|
| 66 |
+
six verbatim personas, six adapted variants, eight lateral use cases.
|
| 67 |
+
Per query it captures planner intent, Stones invoked / fired /
|
| 68 |
+
silent_by_design / errored, wall-clock per Stone, the briefing prose,
|
| 69 |
+
citations resolved, Mellea grounding pass-rate + rerolls, and a
|
| 70 |
+
**framing score** (0-5) for the opening paragraph against a
|
| 71 |
+
per-question-type rubric.
|
| 72 |
+
|
| 73 |
+
**Outputs in `tests/integration/results/2026-05-06/`:**
|
| 74 |
+
- `q01-resident-pioneer.json` ... `q20-control-astoria.json` — full
|
| 75 |
+
per-query payload (plan, paragraph, steps, mellea, framing rationale).
|
| 76 |
+
- `SUMMARY.md` — table of all 20 (intent, time, grounding,
|
| 77 |
+
framing, status).
|
| 78 |
+
- `FAILURES.md` — full briefings + proximate cause for any query
|
| 79 |
+
that errored, timed out, missed Mellea, or returned no prose.
|
| 80 |
+
|
| 81 |
+
**Baseline run summary:**
|
| 82 |
+
- 20/20 OK (no errors, no timeouts).
|
| 83 |
+
- Mean framing score: **2.25** (mostly stuck at 2 = "on-topic exposure
|
| 84 |
+
language but no question-aware framing").
|
| 85 |
+
- Queries with framing ≥ 3: 5 / 20 (q06, q07, q14, q18, q19 — note q07,
|
| 86 |
+
q14, q18, q19 scored 3 only because they returned the canned
|
| 87 |
+
"No grounded data available for this address." which the rubric
|
| 88 |
+
scores as 3 = place-referenced).
|
| 89 |
+
- 4 queries had Mellea 0/4: q07 (lease query, geocoder failed),
|
| 90 |
+
q14 (retrospective query, geocoder failed), q15 (NYCHA ranking,
|
| 91 |
+
planner mis-routed to dev_check with 0 steps), q16 (FloodNet
|
| 92 |
+
live_now with no active signals), q18 (court exhibit retrospective,
|
| 93 |
+
geocoder failed), q19 (BBMCR project name, NTA didn't resolve).
|
| 94 |
+
- The geocoder failures are documented in
|
| 95 |
+
`OVERNIGHT-2026-05-06-OUT-OF-SCOPE.md` — same root cause: the
|
| 96 |
+
length-ratio heuristic in `app/intents/single_address.py:33`
|
| 97 |
+
rejects the planner's correctly-extracted address when the user's
|
| 98 |
+
query is conversational.
|
| 99 |
+
|
| 100 |
+
**Baseline commit:** `e203d5f tests: add 20-query stakeholder integration suite`.
|
| 101 |
+
Per-query JSONs preserved at
|
| 102 |
+
`tests/integration/results/2026-05-06/baseline/`.
|
| 103 |
+
|
| 104 |
+
---
|
| 105 |
+
|
| 106 |
+
## 3. Question-aware Capstone framing — `docs/QUESTION-AWARE-FRAMING.md` + `tests/integration/results/2026-05-06/FRAMING-DELTA.md`
|
| 107 |
+
|
| 108 |
+
**Diagnosis (full version: `docs/QUESTION-AWARE-FRAMING.md`).** Three
|
| 109 |
+
options were on the table: (a) planner sub-classifier, (b) Capstone
|
| 110 |
+
prompt-conditional, (c) both. **Recommendation and what landed: (b).**
|
| 111 |
+
The four-section evidence structure (Status / Empirical / Modeled /
|
| 112 |
+
Policy) and the four Mellea grounding checks stay byte-identical;
|
| 113 |
+
only the Status sentence's directive changes.
|
| 114 |
+
|
| 115 |
+
**Implementation:**
|
| 116 |
+
- New `app/framing.py` — 11 question types, regex-based deterministic
|
| 117 |
+
detector, per-type opening-directive table, `augment_system_prompt`.
|
| 118 |
+
- `app/fsm.py` — new `set_user_query` + `set_planner_intent`
|
| 119 |
+
threadlocals; `step_reconcile` augments
|
| 120 |
+
`app.reconcile.EXTRA_SYSTEM_PROMPT` before passing to
|
| 121 |
+
`reconcile_strict_streaming`.
|
| 122 |
+
- `app/intents/single_address.py` — sets/resets the new threadlocals.
|
| 123 |
+
- `app/intents/neighborhood.py`, `development_check.py`,
|
| 124 |
+
`live_now.py` — augment their own EXTRA_SYSTEM_PROMPT before
|
| 125 |
+
reconcile.
|
| 126 |
+
|
| 127 |
+
**Detector accuracy against suite labels:** 14/20 verbatim. The 6
|
| 128 |
+
mismatches are all bare-place queries where the suite's persona-
|
| 129 |
+
imposed label isn't discoverable from the query text alone — these
|
| 130 |
+
fall back to `journalism` (bare neighborhood) or `generic_exposure`
|
| 131 |
+
(bare address, baseline behavior preserved).
|
| 132 |
+
|
| 133 |
+
**Before/after framing delta** (full report:
|
| 134 |
+
`tests/integration/results/2026-05-06/FRAMING-DELTA.md`):
|
| 135 |
+
|
| 136 |
+
| Metric | Baseline | Framed | Δ |
|
| 137 |
+
|--------|---------:|-------:|---:|
|
| 138 |
+
| Mean framing | 2.25 | 2.80 | +0.55 |
|
| 139 |
+
| ≥ 3/5 | 5 | 8 | +3 |
|
| 140 |
+
| ≥ 4/5 | 2 | 5 | +3 |
|
| 141 |
+
| ≥ 5/5 | 0 | 3 | +3 |
|
| 142 |
+
|
| 143 |
+
**The three queries that hit 5/5** (verdict-style openings — the
|
| 144 |
+
demo-critical wins):
|
| 145 |
+
- **q01** resident habitability — opening flipped from "exposed to
|
| 146 |
+
historical flood events..." to "**Yes**, this address is exposed
|
| 147 |
+
to flood risk based on its inclusion within the Hurricane Sandy
|
| 148 |
+
inundation zone..."
|
| 149 |
+
- **q02** attorney disclosure — opening flipped to "**Disclosure is
|
| 150 |
+
warranted** because the site experiences moderate flood exposure
|
| 151 |
+
as indicated by 56.6% of surrounding cells..."
|
| 152 |
+
- **q13** grant evidence — opening flipped to "**Vulnerability
|
| 153 |
+
assessment**: Chinatown-Two Bridges (NTA MN0301) in Manhattan
|
| 154 |
+
exhibits moderate flood exposure..."
|
| 155 |
+
|
| 156 |
+
**Mellea net change:** +4 improved (3/4 → 4/4), -2 regressed (q01
|
| 157 |
+
4/4 → 3/4, q06 3/4 → 2/4), 14 unchanged. Net +2 grounding checks
|
| 158 |
+
gained across the suite.
|
| 159 |
+
|
| 160 |
+
**Stop condition: FIRED.** 12 / 20 framed queries scored below 3
|
| 161 |
+
(threshold > 5 ⇒ stop). Per Adam's instruction, NOT iterating further
|
| 162 |
+
on the prompt-conditional. Triage of the 12 + sketch of what option
|
| 163 |
+
(a) — planner sub-classifier — would require lives in
|
| 164 |
+
`docs/QUESTION-AWARE-FRAMING.md` §"Outcome of the 2026-05-06 framed
|
| 165 |
+
run" + §"What option (a) would require." Headline:
|
| 166 |
+
|
| 167 |
+
- 4 / 12 are rubric-vs-directive vocabulary mismatch (bare
|
| 168 |
+
neighborhood → journalism directive applied, but rubric scored
|
| 169 |
+
for capital_planning markers). Not a framing failure.
|
| 170 |
+
- 4 / 12 are short-prose-floor failures (geocoder + planner short
|
| 171 |
+
circuit). No framing change can fix these.
|
| 172 |
+
- 4 / 12 are cases where Granite ignored the soft directive. These
|
| 173 |
+
are where option (a) would actually help.
|
| 174 |
+
|
| 175 |
+
**Commits:** `1a82fde framing: question-aware Capstone opening`,
|
| 176 |
+
`342dd4d framing: clarify the directive's scope`,
|
| 177 |
+
`f40ebd2 tests: add FRAMING-DELTA.md generator`,
|
| 178 |
+
`9c61976 tests: baseline + framed run results`.
|
| 179 |
+
|
| 180 |
+
---
|
| 181 |
+
|
| 182 |
+
## 4. Branch state
|
| 183 |
+
|
| 184 |
+
Branch: **`overnight-2026-05-06`**, local only. To inspect:
|
| 185 |
+
|
| 186 |
+
```bash
|
| 187 |
+
git log --oneline overnight-2026-05-06 ^main
|
| 188 |
+
```
|
| 189 |
+
|
| 190 |
+
Commit chronology (newest first; Adam's parallel `comms-` commits
|
| 191 |
+
get auto-merged in via the runtime so they may interleave):
|
| 192 |
+
|
| 193 |
+
- `9c61976 tests: baseline + framed run results, 2026-05-06`
|
| 194 |
+
- `342dd4d framing: clarify the directive's scope is the Status sentence only`
|
| 195 |
+
- `e81962b docs: log out-of-scope findings from the overnight pass`
|
| 196 |
+
- `8894517 docs: morning brief skeleton`
|
| 197 |
+
- `f40ebd2 tests: add FRAMING-DELTA.md generator`
|
| 198 |
+
- `1a82fde framing: question-aware Capstone opening (Capstone prompt-conditional)`
|
| 199 |
+
- `e203d5f tests: add 20-query stakeholder integration suite`
|
| 200 |
+
- `9cc6ec4 audit: mechanical fixes from ruff + vulture`
|
| 201 |
+
|
| 202 |
+
Plus auto-merged commits from Adam's `comms-overnight-2026-05-06`
|
| 203 |
+
work (slides, research, submission docs).
|
| 204 |
+
|
| 205 |
+
To revert any single piece:
|
| 206 |
+
|
| 207 |
+
```bash
|
| 208 |
+
git revert <commit-sha> # safe: creates a new commit that undoes
|
| 209 |
+
git checkout main # discard the branch entirely
|
| 210 |
+
git branch -D overnight-2026-05-06
|
| 211 |
+
```
|
| 212 |
+
|
| 213 |
+
The framing change touches 5 files; reverting `1a82fde` is a clean
|
| 214 |
+
backout if the framed run shows regressions.
|
| 215 |
+
|
| 216 |
+
---
|
| 217 |
+
|
| 218 |
+
## 5. Three things to look at first when you open the laptop
|
| 219 |
+
|
| 220 |
+
1. **`tests/integration/results/2026-05-06/FRAMING-DELTA.md`** — the
|
| 221 |
+
per-query opening diff is the most useful artifact in the pass.
|
| 222 |
+
Read q01, q02, q13 first (the three queries that hit 5/5 — these
|
| 223 |
+
are the demo wins). Then the four "Granite ignored the directive"
|
| 224 |
+
cases triaged in `docs/QUESTION-AWARE-FRAMING.md` ("Outcome of the
|
| 225 |
+
2026-05-06 framed run" §3) — those are where option (a) would
|
| 226 |
+
actually pay off if you decide to spend the 2-3 hours.
|
| 227 |
+
2. **`OVERNIGHT-2026-05-06-OUT-OF-SCOPE.md`** — one real bug
|
| 228 |
+
surfaced: the planner-vs-query length-ratio threshold in
|
| 229 |
+
`app/intents/single_address.py:33` rejects the planner's
|
| 230 |
+
correctly-extracted address whenever the user's query is long and
|
| 231 |
+
conversational. Failure mode is "No grounded data available" with
|
| 232 |
+
Mellea 0/4. Hits q07 (resident lease question), q14
|
| 233 |
+
(retrospective), q18 (court exhibit) — exactly the conversational
|
| 234 |
+
personas the demo arc wants to handle gracefully. Suggested fix
|
| 235 |
+
is in the doc; NOT applied.
|
| 236 |
+
3. **`audit/AUDIT-2026-05-06.md` punch list** — the four
|
| 237 |
+
`experiments/` bugs flagged at the top. Real bugs the demo
|
| 238 |
+
hides because nobody imports them at runtime; if anyone tries to
|
| 239 |
+
reproduce the fine-tunes during the hackathon Q&A, they'll hit
|
| 240 |
+
`experiments/18` failing to import on Py 3.10 (nested f-string).
|
| 241 |
+
|
| 242 |
+
---
|
| 243 |
+
|
| 244 |
+
## What did NOT land
|
| 245 |
+
|
| 246 |
+
- **No deployment, no push.** Per instructions; both targets
|
| 247 |
+
untouched.
|
| 248 |
+
- **No refactor of `build_documents` / Mellea checks / FSM
|
| 249 |
+
structure.** All flagged in `audit/AUDIT-2026-05-06.md` as
|
| 250 |
+
post-demo work.
|
| 251 |
+
- **No new dependencies.** All work used `ruff` / `vulture` / `radon`
|
| 252 |
+
(already installed via `uv tool install`) and the existing repo
|
| 253 |
+
code.
|
| 254 |
+
- **No planner sub-classifier (option a).** The diagnosis recommends
|
| 255 |
+
(b) only; if the framed run's stop condition fires (>5 queries with
|
| 256 |
+
framing < 3), `docs/QUESTION-AWARE-FRAMING.md` describes what (a)
|
| 257 |
+
would require.
|
| 258 |
+
|
| 259 |
+
---
|
| 260 |
+
|
| 261 |
+
## Operating notes for the morning
|
| 262 |
+
|
| 263 |
+
- Local server: `nohup .venv/bin/uvicorn web.main:app --host 127.0.0.1
|
| 264 |
+
--port 7860 ...` was running on port 7860 throughout the night.
|
| 265 |
+
Check `ps -fp $(pgrep -f "uvicorn web.main")` to see if it's still
|
| 266 |
+
alive; safe to kill with `pkill -f "uvicorn web.main"`.
|
| 267 |
+
- Server log: `/tmp/riprap-overnight/server.log`.
|
| 268 |
+
- Suite run logs: `/tmp/riprap-overnight/suite-baseline.log`,
|
| 269 |
+
`/tmp/riprap-overnight/suite-framed.log`.
|
| 270 |
+
|
| 271 |
+
---
|
| 272 |
+
|
| 273 |
+
_Faithful account, not victory lap: this brief should match the
|
| 274 |
+
commit log + the on-disk reports exactly. If anything here doesn't,
|
| 275 |
+
trust the file system, not the brief._
|
docs/sessions/2026-05-W19/OVERNIGHT-2026-05-06-OUT-OF-SCOPE.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Out-of-scope findings — 2026-05-06 overnight pass
|
| 2 |
+
|
| 3 |
+
These were discovered during the overnight pass but are outside the
|
| 4 |
+
scope Adam authorised. **NOT FIXED.** Documented here per his
|
| 5 |
+
explicit instruction so they're easy to triage.
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## 1. Geocoder rejects planner's extracted address on conversational queries
|
| 10 |
+
|
| 11 |
+
**File:** `app/intents/single_address.py:33`
|
| 12 |
+
|
| 13 |
+
```python
|
| 14 |
+
addr = planner_addr if (planner_addr and len(planner_addr) >= len(query) * 0.7) else query
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
**Failure mode.** When the user asks a conversational, multi-clause
|
| 18 |
+
question like:
|
| 19 |
+
|
| 20 |
+
> *"I just got a lease for 504 Grand Street, Lower East Side. The
|
| 21 |
+
> landlord says no flood history. Is that true?"*
|
| 22 |
+
|
| 23 |
+
the planner correctly extracts `"504 Grand Street, Lower East Side"`
|
| 24 |
+
into `targets[0].text` (38 chars). But the conditional rejects this
|
| 25 |
+
extracted address because it's less than 70% of the full query
|
| 26 |
+
(108 chars) — so `addr` falls back to the full query, which the
|
| 27 |
+
NYC DCP Geosearch geocoder cannot parse, returning "no geocoder
|
| 28 |
+
match." The FSM then runs all 19 specialists without coordinates,
|
| 29 |
+
each returning "no coords," and the briefing emits the canonical
|
| 30 |
+
silence-over-confabulation `"No grounded data available for this
|
| 31 |
+
address."` with mellea 0/4 (no claims to check).
|
| 32 |
+
|
| 33 |
+
**Discovered:** suite query q07 (Resident, disclosure-suspicion).
|
| 34 |
+
The `tests/integration/results/2026-05-06/q07-resident-grand-disclosure.json`
|
| 35 |
+
payload shows `geocode.err = "no geocoder match"` and 17 downstream
|
| 36 |
+
steps with `err = "no coords"`.
|
| 37 |
+
|
| 38 |
+
**Why the 70% threshold exists.** A defensive heuristic against the
|
| 39 |
+
planner stripping too much of the user's address into a partial token
|
| 40 |
+
(e.g. "Pioneer" instead of "80 Pioneer Street, Brooklyn"). The
|
| 41 |
+
threshold was tuned for short queries where a stripped result is
|
| 42 |
+
suspicious; it backfires on long queries where the planner correctly
|
| 43 |
+
distilled a clean address out of conversational filler.
|
| 44 |
+
|
| 45 |
+
**Why this matters.** This is exactly the persona shape that the
|
| 46 |
+
demo wants to handle gracefully — a renter asking a real,
|
| 47 |
+
conversational question. RESEARCH.md §1 frames the resident persona
|
| 48 |
+
as "the FloodHelpNY swap-in," and conversational queries are the
|
| 49 |
+
distinguishing feature. Today the system silently produces an empty
|
| 50 |
+
briefing on this shape.
|
| 51 |
+
|
| 52 |
+
**Suggested fix (NOT applied).** Trust the planner's extracted address
|
| 53 |
+
unconditionally when it parses as an NYC street form (house number +
|
| 54 |
+
street name + borough). Replace the length-ratio heuristic with a
|
| 55 |
+
shape check. Out of scope for this overnight pass because it requires
|
| 56 |
+
re-running the address probe to confirm no regression on the curated
|
| 57 |
+
addresses.
|
| 58 |
+
|
| 59 |
+
**Workaround for the demo:** type a clean address.
|
| 60 |
+
|
| 61 |
+
---
|
| 62 |
+
|
| 63 |
+
## 2. Suite runner caveats discovered during the overnight pass
|
| 64 |
+
|
| 65 |
+
These are not bugs — just things worth knowing for a future session.
|
| 66 |
+
|
| 67 |
+
- `tests/integration/stakeholder_queries.py` writes per-query JSON
|
| 68 |
+
after each query (defensive against partial completion). The
|
| 69 |
+
SUMMARY.md is only written at the end. If the suite is killed
|
| 70 |
+
mid-run, the JSONs are still readable; the SUMMARY can be
|
| 71 |
+
regenerated by a small wrapper that walks the JSON dir.
|
| 72 |
+
- The framing-rubric scorer (`score_framing` in the suite) is
|
| 73 |
+
intentionally pessimistic — it only assigns a 5 if a verdict marker
|
| 74 |
+
matches, even if the briefing's prose is high-quality. A high-quality
|
| 75 |
+
generic Status section will still score 3 (place named) or 4 (topic
|
| 76 |
+
named without verdict). The 0-5 scale is a delta-detector, not an
|
| 77 |
+
absolute quality measure.
|
{audit → docs/sessions/2026-05-W19/audit}/2026-05-03-evening-audit.md
RENAMED
|
File without changes
|
{audit → docs/sessions/2026-05-W19/audit}/2026-05-04-morning-handoff.md
RENAMED
|
File without changes
|
{audit → docs/sessions/2026-05-W19/audit}/AUDIT-2026-05-06.md
RENAMED
|
File without changes
|
services/riprap-models/main.py
CHANGED
|
@@ -138,6 +138,22 @@ def _load_prithvi():
|
|
| 138 |
if v2_yaml and v2_ckpt:
|
| 139 |
log.info("prithvi: building from v2 yaml=%s ckpt=%s", v2_yaml, v2_ckpt)
|
| 140 |
m = LightningInferenceModel.from_config(v2_yaml, v2_ckpt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
else:
|
| 142 |
log.info("prithvi: v2 unavailable, falling back to base")
|
| 143 |
base_ckpt = hf_hub_download(
|
|
|
|
| 138 |
if v2_yaml and v2_ckpt:
|
| 139 |
log.info("prithvi: building from v2 yaml=%s ckpt=%s", v2_yaml, v2_ckpt)
|
| 140 |
m = LightningInferenceModel.from_config(v2_yaml, v2_ckpt)
|
| 141 |
+
# prithvi_nyc_phase14.yaml uses GenericNonGeoSegmentationDataModule
|
| 142 |
+
# which omits test_transform (→ None). IBM inference.py:run_model()
|
| 143 |
+
# calls it on a 3D image dict; patch to match the IBM base contract.
|
| 144 |
+
if getattr(getattr(m, 'datamodule', None),
|
| 145 |
+
'test_transform', None) is None:
|
| 146 |
+
import albumentations as A
|
| 147 |
+
import kornia.augmentation as _Ka
|
| 148 |
+
from albumentations.pytorch import ToTensorV2
|
| 149 |
+
m.datamodule.test_transform = A.Compose([ToTensorV2()])
|
| 150 |
+
_old = m.datamodule.aug
|
| 151 |
+
m.datamodule.aug = _Ka.AugmentationSequential(
|
| 152 |
+
_Ka.Normalize(_old.means.view(-1).tolist(),
|
| 153 |
+
_old.stds.view(-1).tolist()),
|
| 154 |
+
data_keys=None)
|
| 155 |
+
log.info("prithvi: patched v2 datamodule transforms "
|
| 156 |
+
"for IBM inference.py compat")
|
| 157 |
else:
|
| 158 |
log.info("prithvi: v2 unavailable, falling back to base")
|
| 159 |
base_ckpt = hf_hub_download(
|
slides/asce/deck.html
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
slides/asce/deck.md
CHANGED
|
@@ -88,16 +88,10 @@ description: ASCE NY State Convention, Albany, May 13, 2026
|
|
| 88 |
|
| 89 |
# A flood-exposure briefing for any place in New York City.
|
| 90 |
|
| 91 |
-
<
|
| 92 |
-
|
| 93 |
-
<div style="border: 2px dashed #94A3B8; background: #E8ECF2; display: flex; align-items: center; justify-content: center; height: 260px; border-radius: 2px; margin-bottom: 10px;">
|
| 94 |
-
<p style="font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); text-align: center; margin: 0; padding: 24px;">
|
| 95 |
-
[ live system screenshot, to be added ]
|
| 96 |
-
</p>
|
| 97 |
</div>
|
| 98 |
|
| 99 |
-
<p style="font-size: 15px; color: var(--ink-3); margin: 0;">Behind the prose: every numeric claim links to its primary public-record source. Mellea rejection sampling refuses to publish what it can’t cite.</p>
|
| 100 |
-
|
| 101 |
---
|
| 102 |
|
| 103 |
<div class="eyebrow">03 · Architecture</div>
|
|
|
|
| 88 |
|
| 89 |
# A flood-exposure briefing for any place in New York City.
|
| 90 |
|
| 91 |
+
<div style="border: 2px solid #94A3B8; border-radius: 2px; overflow: hidden; height: 450px;">
|
| 92 |
+
<img src="../../assets/screenshots/hero.png" style="width: 100%; height: 100%; object-fit: cover; object-position: top;" />
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
</div>
|
| 94 |
|
|
|
|
|
|
|
| 95 |
---
|
| 96 |
|
| 97 |
<div class="eyebrow">03 · Architecture</div>
|
slides/asce/deck.pdf
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6eb04d32338e74ddd075350836c24f3f770bca4702e01e9075f6e37e2e5fdc67
|
| 3 |
+
size 952490
|
slides/asce/deck.pptx
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7d59c1aacabb3cbb5e1ff579f5ed109315b9d571d86dc78f8b5a4c1c647b39ff
|
| 3 |
+
size 3176371
|
slides/asce/riprap.css
CHANGED
|
@@ -70,7 +70,7 @@ section {
|
|
| 70 |
|
| 71 |
/* Bottom-left wordmark on every slide except lead/cta. */
|
| 72 |
section::before {
|
| 73 |
-
content: "▌ riprap
|
| 74 |
position: absolute;
|
| 75 |
left: 64px;
|
| 76 |
bottom: 28px;
|
|
|
|
| 70 |
|
| 71 |
/* Bottom-left wordmark on every slide except lead/cta. */
|
| 72 |
section::before {
|
| 73 |
+
content: "▌ riprap";
|
| 74 |
position: absolute;
|
| 75 |
left: 64px;
|
| 76 |
bottom: 28px;
|
slides/deck.001.png
ADDED
|
Git LFS Details
|
slides/deck.002.png
ADDED
|
Git LFS Details
|
slides/deck.003.png
ADDED
|
Git LFS Details
|
slides/deck.004.png
ADDED
|
Git LFS Details
|
slides/deck.005.png
ADDED
|
Git LFS Details
|
slides/deck.006.png
ADDED
|
Git LFS Details
|
slides/deck.007.png
ADDED
|
Git LFS Details
|
slides/deck.008.png
ADDED
|
Git LFS Details
|
slides/deck.009.png
ADDED
|
Git LFS Details
|
slides/deck.md
CHANGED
|
@@ -74,16 +74,10 @@ description: AMD x lablab.ai Developer Hackathon, May 4–10 2026
|
|
| 74 |
|
| 75 |
# A flood-exposure briefing for any place in New York City.
|
| 76 |
|
| 77 |
-
<
|
| 78 |
-
|
| 79 |
-
<div style="border: 2px dashed #94A3B8; background: #E8ECF2; display: flex; align-items: center; justify-content: center; height: 280px; border-radius: 2px; margin-bottom: 10px;">
|
| 80 |
-
<p style="font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); text-align: center; margin: 0; padding: 24px;">
|
| 81 |
-
[ screenshot of riprap.nyc landing — to be added ]
|
| 82 |
-
</p>
|
| 83 |
</div>
|
| 84 |
|
| 85 |
-
<p style="font-size: 15px; color: var(--ink-3); margin: 0;">Behind the prose: every numeric claim links to its primary public-record source. Mellea rejection sampling refuses to publish what it can’t cite.</p>
|
| 86 |
-
|
| 87 |
---
|
| 88 |
|
| 89 |
<div class="eyebrow">03 · The civic-tech case</div>
|
|
@@ -261,10 +255,6 @@ description: AMD x lablab.ai Developer Hackathon, May 4–10 2026
|
|
| 261 |
<p style="font-family: var(--font-mono); font-size: 28px; font-weight: 700; color: var(--ink); margin: 0 auto; max-width: 860px; line-height: 1.35;">“I’m thinking about renting an apartment at 80 Pioneer Street, Brooklyn. Should I worry?”</p>
|
| 262 |
</div>
|
| 263 |
|
| 264 |
-
<div style="text-align: center; margin-bottom: 40px;">
|
| 265 |
-
<span style="font-family: var(--font-mono); font-size: 20px; letter-spacing: 0.06em; color: var(--accent); font-weight: 700;">riprap.nyc</span>
|
| 266 |
-
</div>
|
| 267 |
-
|
| 268 |
<p style="text-align: center; font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); margin: 0 auto; max-width: none;">13 seconds end-to-end · 4/4 grounding checks · all sources public-record</p>
|
| 269 |
|
| 270 |
---
|
|
|
|
| 74 |
|
| 75 |
# A flood-exposure briefing for any place in New York City.
|
| 76 |
|
| 77 |
+
<div style="border: 2px solid #94A3B8; border-radius: 2px; overflow: hidden; height: 470px;">
|
| 78 |
+
<img src="../assets/screenshots/hero.png" style="width: 100%; height: 100%; object-fit: cover; object-position: top;" />
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
</div>
|
| 80 |
|
|
|
|
|
|
|
| 81 |
---
|
| 82 |
|
| 83 |
<div class="eyebrow">03 · The civic-tech case</div>
|
|
|
|
| 255 |
<p style="font-family: var(--font-mono); font-size: 28px; font-weight: 700; color: var(--ink); margin: 0 auto; max-width: 860px; line-height: 1.35;">“I’m thinking about renting an apartment at 80 Pioneer Street, Brooklyn. Should I worry?”</p>
|
| 256 |
</div>
|
| 257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
<p style="text-align: center; font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); margin: 0 auto; max-width: none;">13 seconds end-to-end · 4/4 grounding checks · all sources public-record</p>
|
| 259 |
|
| 260 |
---
|
slides/riprap.css
CHANGED
|
@@ -70,7 +70,7 @@ section {
|
|
| 70 |
|
| 71 |
/* Bottom-left wordmark on every slide except lead/cta. */
|
| 72 |
section::before {
|
| 73 |
-
content: "▌ riprap
|
| 74 |
position: absolute;
|
| 75 |
left: 64px;
|
| 76 |
bottom: 28px;
|
|
|
|
| 70 |
|
| 71 |
/* Bottom-left wordmark on every slide except lead/cta. */
|
| 72 |
section::before {
|
| 73 |
+
content: "▌ riprap";
|
| 74 |
position: absolute;
|
| 75 |
left: 64px;
|
| 76 |
bottom: 28px;
|
uv.lock
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version = 1
|
| 2 |
+
revision = 3
|
| 3 |
+
requires-python = ">=3.12"
|
web/main.py
CHANGED
|
@@ -840,6 +840,35 @@ def layer_prithvi_water(lat: float, lon: float, r: float = 1500):
|
|
| 840 |
headers={"Cache-Control": "public, max-age=3600"})
|
| 841 |
|
| 842 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 843 |
@app.get("/api/floodnet_near")
|
| 844 |
def floodnet_near(lat: float, lon: float, r: float = 1000):
|
| 845 |
sensors = floodnet.sensors_near(lat, lon, r)
|
|
|
|
| 840 |
headers={"Cache-Control": "public, max-age=3600"})
|
| 841 |
|
| 842 |
|
| 843 |
+
@app.get("/api/layers/ida_hwm")
|
| 844 |
+
def layer_ida_hwm(lat: float, lon: float, r: float = 1500):
|
| 845 |
+
"""USGS Hurricane Ida 2021 high-water marks within radius_m of (lat, lon).
|
| 846 |
+
Returns GeoJSON FeatureCollection of Point features. No geopandas needed —
|
| 847 |
+
HWMs are already points so haversine filter is sufficient."""
|
| 848 |
+
from app.flood_layers import ida_hwm as _ida
|
| 849 |
+
features = []
|
| 850 |
+
for f in _ida._load():
|
| 851 |
+
flon, flat = f["geometry"]["coordinates"]
|
| 852 |
+
d = _ida._haversine_m(lat, lon, flat, flon)
|
| 853 |
+
if d <= r:
|
| 854 |
+
p = f["properties"]
|
| 855 |
+
features.append({
|
| 856 |
+
"type": "Feature",
|
| 857 |
+
"geometry": f["geometry"],
|
| 858 |
+
"properties": {
|
| 859 |
+
"hwm_id": p.get("hwm_id"),
|
| 860 |
+
"site_description": p.get("site_description"),
|
| 861 |
+
"elev_ft": p.get("elev_ft"),
|
| 862 |
+
"height_above_gnd_ft": p.get("height_above_gnd"),
|
| 863 |
+
"hwm_quality": p.get("hwm_quality"),
|
| 864 |
+
"waterbody": p.get("waterbody"),
|
| 865 |
+
"distance_m": round(d, 0),
|
| 866 |
+
},
|
| 867 |
+
})
|
| 868 |
+
return JSONResponse({"type": "FeatureCollection", "features": features},
|
| 869 |
+
headers={"Cache-Control": "public, max-age=3600"})
|
| 870 |
+
|
| 871 |
+
|
| 872 |
@app.get("/api/floodnet_near")
|
| 873 |
def floodnet_near(lat: float, lon: float, r: float = 1000):
|
| 874 |
sensors = floodnet.sensors_near(lat, lon, r)
|
web/sveltekit/build/200.html
CHANGED
|
@@ -6,17 +6,17 @@
|
|
| 6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 7 |
<meta name="description" content="Riprap — citation-grounded NYC flood-exposure briefings." />
|
| 8 |
<title>Riprap — flood-exposure briefing</title>
|
| 9 |
-
<link href="/_app/immutable/entry/start.
|
| 10 |
-
<link href="/_app/immutable/chunks/
|
| 11 |
<link href="/_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
|
| 12 |
-
<link href="/_app/immutable/entry/app.
|
| 13 |
<link href="/_app/immutable/chunks/CXQd8Y6F.js" rel="modulepreload">
|
| 14 |
<link href="/_app/immutable/chunks/CWw6qgC_.js" rel="modulepreload">
|
| 15 |
<link href="/_app/immutable/chunks/Bd-v_9Ud.js" rel="modulepreload">
|
| 16 |
<link href="/_app/immutable/chunks/CW0zSL4D.js" rel="modulepreload">
|
| 17 |
-
<link href="/_app/immutable/nodes/0.
|
| 18 |
<link href="/_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
|
| 19 |
-
<link href="/_app/immutable/chunks/
|
| 20 |
<link href="/_app/immutable/chunks/DCD6_LXk.js" rel="modulepreload">
|
| 21 |
<link href="/_app/immutable/chunks/B0XoTt7U.js" rel="modulepreload">
|
| 22 |
<link href="/_app/immutable/chunks/DixtWtwq.js" rel="modulepreload">
|
|
@@ -28,15 +28,15 @@
|
|
| 28 |
<div style="display: contents">
|
| 29 |
<script>
|
| 30 |
{
|
| 31 |
-
|
| 32 |
base: ""
|
| 33 |
};
|
| 34 |
|
| 35 |
const element = document.currentScript.parentElement;
|
| 36 |
|
| 37 |
Promise.all([
|
| 38 |
-
import("/_app/immutable/entry/start.
|
| 39 |
-
import("/_app/immutable/entry/app.
|
| 40 |
]).then(([kit, app]) => {
|
| 41 |
kit.start(app, element);
|
| 42 |
});
|
|
|
|
| 6 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 7 |
<meta name="description" content="Riprap — citation-grounded NYC flood-exposure briefings." />
|
| 8 |
<title>Riprap — flood-exposure briefing</title>
|
| 9 |
+
<link href="/_app/immutable/entry/start.d_1AXvI4.js" rel="modulepreload">
|
| 10 |
+
<link href="/_app/immutable/chunks/DtzoFJKK.js" rel="modulepreload">
|
| 11 |
<link href="/_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
|
| 12 |
+
<link href="/_app/immutable/entry/app.CUBM1aCV.js" rel="modulepreload">
|
| 13 |
<link href="/_app/immutable/chunks/CXQd8Y6F.js" rel="modulepreload">
|
| 14 |
<link href="/_app/immutable/chunks/CWw6qgC_.js" rel="modulepreload">
|
| 15 |
<link href="/_app/immutable/chunks/Bd-v_9Ud.js" rel="modulepreload">
|
| 16 |
<link href="/_app/immutable/chunks/CW0zSL4D.js" rel="modulepreload">
|
| 17 |
+
<link href="/_app/immutable/nodes/0.BWtmkq4k.js" rel="modulepreload">
|
| 18 |
<link href="/_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
|
| 19 |
+
<link href="/_app/immutable/chunks/qPYGiFsf.js" rel="modulepreload">
|
| 20 |
<link href="/_app/immutable/chunks/DCD6_LXk.js" rel="modulepreload">
|
| 21 |
<link href="/_app/immutable/chunks/B0XoTt7U.js" rel="modulepreload">
|
| 22 |
<link href="/_app/immutable/chunks/DixtWtwq.js" rel="modulepreload">
|
|
|
|
| 28 |
<div style="display: contents">
|
| 29 |
<script>
|
| 30 |
{
|
| 31 |
+
__sveltekit_1h3t6jb = {
|
| 32 |
base: ""
|
| 33 |
};
|
| 34 |
|
| 35 |
const element = document.currentScript.parentElement;
|
| 36 |
|
| 37 |
Promise.all([
|
| 38 |
+
import("/_app/immutable/entry/start.d_1AXvI4.js"),
|
| 39 |
+
import("/_app/immutable/entry/app.CUBM1aCV.js")
|
| 40 |
]).then(([kit, app]) => {
|
| 41 |
kit.start(app, element);
|
| 42 |
});
|
web/sveltekit/build/_app/immutable/chunks/BZuv-XBZ.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import{k as Ie,o as De,a as c,f as p,s as f,t as ye,d as Ce,c as xe,e as Ne,b as me}from"./CWw6qgC_.js";import{h as ce,n as Ae,j as we,bd as ze,d as Oe,a3 as He,aW as Ye,b7 as je,k as We,b as Ue,e as Le,i as ke,a0 as Ge,av as Ke,p as X,t as C,a as J,s as n,c as r,r as t,aR as re,o as a,al as q,am as le,ai as Qe,be as Ve,a5 as pe,a4 as Se,f as ee}from"./BTUA7_xE.js";import{B as Ze,i as A}from"./Bd-v_9Ud.js";import{e as te,i as de}from"./25_y8TFd.js";import{s as _,a as ue,b as oe,c as Xe,C as Je}from"./B0XoTt7U.js";import{T as ge,c as $e,b as et,d as Re}from"./BatqQaKj.js";import{b as tt,_ as at}from"./CXQd8Y6F.js";import{p as ie}from"./CW0zSL4D.js";import{P as rt}from"./D907np-5.js";function st(R,e,S,m,M,i){let g=ce;ce&&Ae();var d=null;ce&&we.nodeType===ze&&(d=we,Ae());var x=ce?we:R,h=new Ze(x,!1);Oe(()=>{const k=e()||null;var y=k==="svg"?je:void 0;if(k===null){h.ensure(null,null);return}return h.ensure(k,o=>{if(k){if(d=ce?d:Ye(k,y),Ie(d,d),m){ce&&De(k)&&d.append(document.createComment(""));var s=ce?We(d):d.appendChild(Ue());ce&&(s===null?Le(!1):ke(s)),m(d,s)}Ge.nodes.end=d,o.before(d)}ce&&ke(o)}),()=>{}},He),Ke(()=>{}),g&&(Le(!0),ke(x))}var it=p('<a target="_blank" rel="noopener noreferrer"> </a>'),nt=p('<li><span class="citation-num"> </span> <div class="citation-body"><div class="citation-line-1"><!> <span class="citation-source"> </span> <span class="citation-vintage"> </span></div> <div class="citation-title"><!></div> <div class="citation-meta"><span class="citation-docid"> </span> <span class="citation-retrieved"> </span></div></div></li>'),lt=p(`<aside class="citation-drawer svelte-1p339fd" aria-label="Citations"><div class="citation-drawer-head"><span class="section-label"> </span> <span class="citation-drawer-meta">live · primary sources</span></div> <ol class="citation-list"></ol> <div class="citation-drawer-foot"><span class="section-label">Trust signals</span> <p class="citation-foot-copy">All foundation models Apache-2.0. All data from public-record federal,
|
| 2 |
+
state, and city sources. No commercial APIs contacted at runtime.</p></div></aside>`);function Lr(R,e){X(e,!0);let S=q(()=>Object.values(e.citations).sort((x,h)=>x.n-h.n));var m=lt(),M=r(m),i=r(M),g=r(i);t(i),re(2),t(M);var d=n(M,2);te(d,21,()=>a(S),x=>x.id,(x,h)=>{var k=nt();let y;var o=r(k),s=r(o);t(o);var l=n(o,2),b=r(l),N=r(b);ge(N,{get tier(){return a(h).tier},size:10,get color(){return`var(--tier-${a(h).tier??""})`}});var u=n(N,2),v=r(u,!0);t(u);var w=n(u,2),B=r(w);t(w),t(b);var E=n(b,2),D=r(E);{var H=F=>{var j=it(),K=r(j,!0);t(j),C(()=>{_(j,"href",a(h).url),f(K,a(h).title)}),c(F,j)},I=q(()=>a(h).url&&a(h).url.startsWith("http")),z=F=>{var j=ye();C(()=>f(j,a(h).title)),c(F,j)};A(D,F=>{a(I)?F(H):F(z,-1)})}t(E);var O=n(E,2),W=r(O),T=r(W,!0);t(W);var P=n(W,2),L=r(P);t(P),t(O),t(l),t(k),C(()=>{_(k,"id",`cite-${a(h).id??""}`),y=ue(k,1,"citation-item",null,y,{"is-active":$e.active===a(h).id}),f(s,`[${a(h).n??""}]`),f(v,a(h).source),f(B,`v. ${a(h).vintage??""}`),f(T,a(h).docId),f(L,`retr. ${a(h).retrieved??""}`)}),c(x,k)}),t(d),re(2),t(m),C(()=>f(g,`Citations · ${a(S).length??""}`)),c(R,m),J()}const Fe=`<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
|
| 3 |
+
<rect width="12" height="12" fill="rgba(42,111,168,0.18)"/>
|
| 4 |
+
<g stroke="#2A6FA8" stroke-width="1.4">
|
| 5 |
+
<line x1="-2" y1="2" x2="14" y2="-14"/>
|
| 6 |
+
<line x1="-2" y1="8" x2="14" y2="-8"/>
|
| 7 |
+
<line x1="-2" y1="14" x2="14" y2="-2"/>
|
| 8 |
+
<line x1="-2" y1="20" x2="14" y2="4"/>
|
| 9 |
+
</g>
|
| 10 |
+
</svg>`,ot=`<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
|
| 11 |
+
<rect width="12" height="12" fill="rgba(42,111,168,0.16)"/>
|
| 12 |
+
<g stroke="#2A6FA8" stroke-width="1.1">
|
| 13 |
+
<line x1="-2" y1="6" x2="14" y2="-10"/>
|
| 14 |
+
<line x1="-2" y1="14" x2="14" y2="-2"/>
|
| 15 |
+
<line x1="-2" y1="22" x2="14" y2="6"/>
|
| 16 |
+
</g>
|
| 17 |
+
</svg>`;async function dt(R,e){const S=new Blob([R],{type:"image/svg+xml"}),m=URL.createObjectURL(S);try{return await new Promise((i,g)=>{const d=new Image(e,e);d.onload=()=>i(d),d.onerror=x=>g(x),d.src=m})}finally{URL.revokeObjectURL(m)}}async function vt(R){const e=[["syn-stripe-45",Fe,12],["syn-stripe-45-2x",Fe,24],["syn-stripe-45-low",ot,12]];for(const[S,m,M]of e)if(!R.hasImage(S))try{const i=await dt(m,M);R.addImage(S,i,{pixelRatio:M/12})}catch(i){console.warn(`syn-stripe registration failed for ${S}`,i)}}var ct=p('<span class="link-badge svelte-wk2bu4" aria-hidden="true"> </span>'),ut=p('<div class="map-frame svelte-wk2bu4"><div role="application" class="rip-map-container svelte-wk2bu4"></div> <!></div>');function Rr(R,e){X(e,!0);let S=ie(e,"activeLayers",19,()=>({empirical:!0,modeled:!0,synthetic:!0,proxy:!0})),m=ie(e,"linkedKey",3,null),M=Se(null),i=null,g=Se(!1);const d={type:"FeatureCollection",features:[]};function x(l,b){if(!i||!a(g))return;const N=i.getSource(l);N&&N.setData(b??d)}function h(l,b){!i||!a(g)||i.getLayer(l)&&i.setLayoutProperty(l,"visibility",b?"visible":"none")}le(()=>{x("sandy-empirical",e.sandyEmpirical)}),le(()=>{x("dep-modeled",e.depModeled)}),le(()=>{x("syn-prior",e.syntheticPrior)}),le(()=>{x("proxy-311",e.proxy311)}),le(()=>{x("register-points",e.registerPoints)}),le(()=>{x("register-polygons",e.registerPolygons)}),le(()=>{x("terramind-lulc",e.terramindLulc)}),le(()=>{x("ida-hwm",e.idaHwm)}),le(()=>{h("tier-empirical-fill",S().empirical),h("tier-empirical-line",S().empirical),h("ida-hwm-circle",S().empirical),h("tier-modeled-fill",S().modeled),h("tier-modeled-line",S().modeled),h("tier-synthetic-fill",S().synthetic),h("tier-synthetic-line",S().synthetic),h("terramind-lulc-fill",S().synthetic),h("terramind-lulc-line",S().synthetic),h("tier-proxy-dots",S().proxy)}),le(()=>{!i||!a(g)||i.flyTo({center:[e.address.lon,e.address.lat],zoom:15,essential:!0})}),Qe(async()=>{if(!a(M))return;const l=await at(()=>import("./D4L2lGt1.js").then(b=>b.m),[],import.meta.url);i=new l.Map({container:a(M),style:rt,center:[e.address.lon,e.address.lat],zoom:15,attributionControl:{compact:!0}}),i.addControl(new l.NavigationControl({visualizePitch:!1}),"top-right"),i.addControl(new l.ScaleControl({maxWidth:100,unit:"imperial"}),"bottom-left"),i.on("load",()=>{if(!i)return;window.__riprapMap=i,vt(i);const b=()=>({type:"FeatureCollection",features:[]});i.addSource("sandy-empirical",{type:"geojson",data:e.sandyEmpirical??b()}),i.addSource("dep-modeled",{type:"geojson",data:e.depModeled??b()}),i.addSource("syn-prior",{type:"geojson",data:e.syntheticPrior??b()}),i.addSource("proxy-311",{type:"geojson",data:e.proxy311??b()}),i.addSource("register-points",{type:"geojson",data:e.registerPoints??b()}),i.addSource("register-polygons",{type:"geojson",data:e.registerPolygons??b()}),i.addSource("terramind-lulc",{type:"geojson",data:e.terramindLulc??b()}),i.addSource("ida-hwm",{type:"geojson",data:e.idaHwm??b()}),i.addSource("queried-address",{type:"geojson",data:{type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"Point",coordinates:[e.address.lon,e.address.lat]},properties:{label:e.address.label}}]}}),i.addLayer({id:"tier-empirical-fill",type:"fill",source:"sandy-empirical",paint:{"fill-color":"#0B5394","fill-opacity":.4}}),i.addLayer({id:"tier-empirical-line",type:"line",source:"sandy-empirical",paint:{"line-color":"#0B5394","line-width":1.5}}),i.addLayer({id:"tier-modeled-fill",type:"fill",source:"dep-modeled",paint:{"fill-color":"#2A6FA8","fill-opacity":.25}}),i.addLayer({id:"tier-modeled-line",type:"line",source:"dep-modeled",paint:{"line-color":"#2A6FA8","line-width":1.5}}),i.addLayer({id:"tier-synthetic-fill",type:"fill",source:"syn-prior",paint:{"fill-pattern":"syn-stripe-45","fill-opacity":.65}}),i.addLayer({id:"tier-synthetic-line",type:"line",source:"syn-prior",paint:{"line-color":"#2A6FA8","line-width":1.5,"line-dasharray":[4,3]}}),i.addLayer({id:"tier-proxy-dots",type:"circle",source:"proxy-311",paint:{"circle-color":"transparent","circle-stroke-color":"#6B6B6B","circle-stroke-width":1.25,"circle-radius":["interpolate",["linear"],["coalesce",["get","count"],1],1,3,5,6,15,9,30,12]}}),i.addLayer({id:"terramind-lulc-fill",type:"fill",source:"terramind-lulc",paint:{"fill-color":["get","fill_color"],"fill-opacity":.25}}),i.addLayer({id:"terramind-lulc-line",type:"line",source:"terramind-lulc",paint:{"line-color":["get","fill_color"],"line-width":.75,"line-opacity":.45,"line-dasharray":[3,2]}}),i.addLayer({id:"register-polygons-fill",type:"fill",source:"register-polygons",paint:{"fill-color":"#0B5394","fill-opacity":["interpolate",["linear"],["coalesce",["get","pct_inside_sandy"],0],0,.1,25,.2,50,.32,75,.45]}}),i.addLayer({id:"register-polygons-line",type:"line",source:"register-polygons",paint:{"line-color":"#0B5394","line-width":1,"line-opacity":.85}}),i.addLayer({id:"ida-hwm-circle",type:"circle",source:"ida-hwm",paint:{"circle-color":"#D97706","circle-stroke-color":"#F4F6F9","circle-stroke-width":1.5,"circle-radius":["interpolate",["linear"],["coalesce",["get","height_above_gnd_ft"],.5],0,5,1,7,3,9,5,12],"circle-opacity":.92}}),i.on("mouseenter","ida-hwm-circle",()=>{i&&(i.getCanvas().style.cursor="pointer")}),i.on("mouseleave","ida-hwm-circle",()=>{i&&(i.getCanvas().style.cursor="")}),i.on("click","ida-hwm-circle",N=>{var W;if(!i||!((W=N.features)!=null&&W.length))return;const u=N.features[0],v=u.properties??{},w=String(v.site_description??"?"),B=v.elev_ft!=null?`${Number(v.elev_ft).toFixed(1)} ft NAVD88`:"—",E=v.height_above_gnd_ft!=null?`${Number(v.height_above_gnd_ft).toFixed(2)} ft above ground`:"—",D=String(v.hwm_quality??""),H=v.distance_m!=null?`${v.distance_m} m from query`:"",I=`
|
| 18 |
+
<div style="font-family: 'IBM Plex Sans', system-ui; font-size: 12px; max-width: 220px;">
|
| 19 |
+
<div style="font-weight: 600; color: #D97706; font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase;">Ida 2021 HWM · USGS</div>
|
| 20 |
+
<div style="margin-top: 4px; color: #0F172A; font-size: 12px;">${w}</div>
|
| 21 |
+
<div style="margin-top: 6px; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: #6B6B6B;">
|
| 22 |
+
elev: ${B}<br>
|
| 23 |
+
mark: ${E}<br>
|
| 24 |
+
${D?`quality: ${D}<br>`:""}
|
| 25 |
+
${H}
|
| 26 |
+
</div>
|
| 27 |
+
</div>`,z=new l.Popup({closeButton:!0,offset:12}),O=u.geometry.coordinates;z.setLngLat(O).setHTML(I).addTo(i)}),i.addLayer({id:"register-points-circle",type:"circle",source:"register-points",paint:{"circle-color":["case",["==",["get","inside_sandy_2012"],!0],"#0B5394","#6B6B6B"],"circle-stroke-color":"#F4F6F9","circle-stroke-width":1.25,"circle-radius":["match",["get","kind"],"subway",4,"school",5,"hospital",6,"nycha",7,4],"circle-opacity":.9}}),i.on("mouseenter","register-points-circle",()=>{i&&(i.getCanvas().style.cursor="pointer")}),i.on("mouseleave","register-points-circle",()=>{i&&(i.getCanvas().style.cursor="")}),i.on("click","register-points-circle",N=>{var O;if(!i||!((O=N.features)!=null&&O.length))return;const u=N.features[0],v=u.properties??{},w=String(v.name??"?"),B=String(v.kind??"?"),E=v.inside_sandy_2012===!0||v.inside_sandy_2012==="true",D=String(v.doc_id??""),H=`
|
| 28 |
+
<div style="font-family: 'IBM Plex Sans', system-ui; font-size: 12px;">
|
| 29 |
+
<div style="font-weight: 600; color: #0F172A;">${w}</div>
|
| 30 |
+
<div style="color: #6B6B6B; font-size: 11px; margin-top: 2px;">${B}</div>
|
| 31 |
+
<div style="margin-top: 6px;">
|
| 32 |
+
<span style="font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: ${E?"#0B5394":"#6B6B6B"};">
|
| 33 |
+
inside_sandy_2012=${E}
|
| 34 |
+
</span>
|
| 35 |
+
</div>
|
| 36 |
+
${D?`<div style="margin-top: 4px; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: #005EA2;">[${D}]</div>`:""}
|
| 37 |
+
</div>`,I=new l.Popup({closeButton:!0,offset:12}),z=u.geometry.coordinates;I.setLngLat(z).setHTML(H).addTo(i)}),i.addLayer({id:"queried-halo",type:"circle",source:"queried-address",paint:{"circle-color":"rgba(209, 124, 0, 0.20)","circle-radius":16}}),i.addLayer({id:"queried-pin",type:"circle",source:"queried-address",paint:{"circle-color":"#005EA2","circle-stroke-color":"#F4F6F9","circle-stroke-width":2,"circle-radius":7}}),i.addLayer({id:"queried-label",type:"symbol",source:"queried-address",layout:{"text-field":["get","label"],"text-font":["Open Sans Semibold","Arial Unicode MS Bold"],"text-size":12,"text-offset":[0,-1.6],"text-anchor":"bottom"},paint:{"text-color":"#0F172A","text-halo-color":"#F4F6F9","text-halo-width":1.5}}),pe(g,!0)})}),Ve(()=>{i==null||i.remove(),i=null});var k=ut(),y=r(k);tt(y,l=>pe(M,l),()=>a(M));var o=n(y,2);{var s=l=>{var b=ct(),N=r(b);t(b),C(()=>f(N,`linked: ${m()??""}`)),c(l,b)};A(o,l=>{m()&&l(s)})}t(k),C(()=>{_(k,"data-linked",m()??""),_(y,"aria-label",`Flood-exposure map for ${e.address.label??""}`)}),c(R,k),J()}const Be=["cornerstone","keystone","touchstone","lodestone","capstone"],Me={cornerstone:{name:"Cornerstone",role:"the hazard reader",tag:"what NYC's ground remembers"},keystone:{name:"Keystone",role:"the asset register",tag:"what's exposed"},touchstone:{name:"Touchstone",role:"the live observer",tag:"what's happening now"},lodestone:{name:"Lodestone",role:"the projector",tag:"what's coming"},capstone:{name:"Capstone",role:"the synthesizer",tag:"writes it all down with citations"}};var gt=p('<span class="layers-count svelte-1g2dety"> </span>'),ht=p('<li class="layers-row layers-row-empty svelte-1g2dety"><span class="layers-empty-text svelte-1g2dety">no map layers — see Findings cards</span></li>'),mt=p('<li class="layers-row layers-row-empty svelte-1g2dety"><span class="layers-empty-text svelte-1g2dety">not a map layer</span></li>'),ft=p('<span class="layers-state-dim svelte-1g2dety" title="Not yet wired to map source">off · catalog</span>'),_t=p('<li><span class="layers-glyph svelte-1g2dety" aria-hidden="true"><!></span> <span class="layers-text svelte-1g2dety"><span class="layers-label svelte-1g2dety"> </span> <span class="layers-meta svelte-1g2dety"> <!></span></span> <span class="layers-state svelte-1g2dety"><!></span></li>'),yt=p('<details open=""><summary class="svelte-1g2dety"><span class="layers-caret svelte-1g2dety" aria-hidden="true">▾</span> <span class="layers-stone-name svelte-1g2dety"> </span> <span class="layers-stone-tag svelte-1g2dety"> </span> <!></summary> <ul class="layers-list svelte-1g2dety"><!></ul></details>'),pt=p('<button type="button"><!> <span> </span> <span class="layers-master-state svelte-1g2dety"> </span></button>'),xt=p('<aside class="layers-panel svelte-1g2dety" aria-label="Map layers grouped by Stone"><div class="layers-head svelte-1g2dety"><span class="section-label">Layers · grouped by Stone</span></div> <!> <div class="layers-masters svelte-1g2dety" role="group" aria-label="Master tier toggles"><span class="section-label">Tier toggles</span> <div class="layers-master-row svelte-1g2dety"></div></div></aside>');function Fr(R,e){X(e,!0);const S={cornerstone:[{label:"Sandy Inundation Zone (2012)",source:"NYC OEM",tier:"empirical",wired:!0},{label:"FEMA / DEP scenarios",source:"FEMA · NYC DEP",tier:"modeled",wired:!0},{label:"Ida HWM points (2021)",source:"USGS STN",tier:"empirical",wired:!0},{label:"Microtopography (HAND/TWI)",source:"USGS 3DEP",tier:"proxy",wired:!1}],keystone:[{label:"MTA subway entrances",source:"MTA Open Data",tier:"empirical",wired:!0},{label:"NYCHA developments",source:"NYC OD phvi-damg",tier:"empirical",wired:!0},{label:"DOE schools",source:"NYC DOE Locations",tier:"empirical",wired:!0},{label:"DOH hospitals",source:"NYS DOH vn5v-hh5r",tier:"empirical",wired:!0},{label:"TerraMind Buildings (current)",source:"msradam/TerraMind-NYC-Adapters",tier:"synthetic",wired:!1}],touchstone:[{label:"311 flood complaints",source:"NYC 311",tier:"proxy",wired:!1},{label:"FloodNet sensors",source:"FloodNet NYC",tier:"proxy",wired:!0},{label:"TerraMind LULC (current)",source:"msradam/TerraMind-NYC-Adapters",tier:"synthetic",wired:!0},{label:"Prithvi-NYC-Pluvial flood pred.",source:"msradam/Prithvi-EO-2.0-NYC-Pluvial",tier:"modeled",wired:!1}],lodestone:[],capstone:[]};function m(k){return!!e.active[k.tier]}function M(k){return S[k].length}const i=[{k:"empirical",tier:"empirical",label:"EMP"},{k:"modeled",tier:"modeled",label:"MOD"},{k:"proxy",tier:"proxy",label:"PRX"},{k:"synthetic",tier:"synthetic",label:"SYN"}];var g=xt(),d=n(r(g),2);te(d,16,()=>Be,k=>k,(k,y)=>{var o=yt(),s=r(o),l=n(r(s),2),b=r(l,!0);t(l);var N=n(l,2),u=r(N);t(N);var v=n(N,2);{var w=O=>{var W=gt(),T=r(W,!0);t(W),C(P=>f(T,P),[()=>M(y)]),c(O,W)},B=q(()=>M(y)>0);A(v,O=>{a(B)&&O(w)})}t(s);var E=n(s,2),D=r(E);{var H=O=>{var W=ht();c(O,W)},I=O=>{var W=mt();c(O,W)},z=O=>{var W=xe(),T=ee(W);te(T,17,()=>S[y],de,(P,L)=>{var F=_t();let j;var K=r(F),ae=r(K);ge(ae,{get tier(){return a(L).tier},size:11,get color(){return`var(--tier-${a(L).tier??""})`}}),t(K);var Q=n(K,2),Z=r(Q),ne=r(Z,!0);t(Z);var Y=n(Z,2),V=r(Y),G=n(V);et(G,{get tier(){return a(L).tier},compact:!0}),t(Y),t(Q);var U=n(Q,2),$=r(U);{var ve=se=>{var _e=ft();c(se,_e)},fe=se=>{var _e=ye("on");c(se,_e)},be=q(()=>m(a(L))),he=se=>{var _e=ye("off");c(se,_e)};A($,se=>{a(L).wired?a(be)?se(fe,1):se(he,-1):se(ve)})}t(U),t(F),C(()=>{j=ue(F,1,"layers-row svelte-1g2dety",null,j,{dim:!a(L).wired}),f(ne,a(L).label),f(V,`${a(L).source??""} · `)}),c(P,F)}),c(O,W)};A(D,O=>{y==="lodestone"?O(H):y==="capstone"?O(I,1):O(z,-1)})}t(E),t(o),C(()=>{ue(o,1,`layers-group region-${y??""}`,"svelte-1g2dety"),f(b,Me[y].name),f(u,`— ${Me[y].tag??""}`)}),c(k,o)});var x=n(d,2),h=n(r(x),2);te(h,21,()=>i,k=>k.k,(k,y)=>{var o=pt();let s;var l=r(o);ge(l,{get tier(){return a(y).tier},size:11,get color(){return`var(--tier-${a(y).tier??""})`}});var b=n(l,2),N=r(b,!0);t(b);var u=n(b,2),v=r(u,!0);t(u),t(o),C(()=>{s=ue(o,1,"layers-master svelte-1g2dety",null,s,{"is-on":e.active[a(y).k]}),_(o,"aria-pressed",e.active[a(y).k]),f(N,a(y).label),f(v,e.active[a(y).k]?"ON":"OFF")}),Ne("click",o,()=>e.onToggle(a(y).k)),c(k,o)}),t(h),t(x),t(g),c(R,g),J()}Ce(["click"]);var bt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-silent svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> silent</span>',1),wt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-warn svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> warned</span>',1),kt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-err svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> errored</span>',1),St=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-notinvoked svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> not invoked</span>',1),Mt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> cache</span>',1),Ct=p('<div class="rh svelte-1vuwkv4"><span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> Stones</span> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> fired</span> <!> <!> <!> <!> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> </span> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> wall-clock</span> <!> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-total svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> registered</span></div>');function Nt(R,e){X(e,!0);function S(Y){return Y.flatMap(V=>V.children?[V,...S(V.children)]:[V])}let m=q(()=>e.stones.flatMap(Y=>S(Y.members))),M=q(()=>a(m).length),i=q(()=>a(m).filter(Y=>Y.status==="fired"||Y.status==="warned").length),g=q(()=>a(m).filter(Y=>Y.status==="silent_by_design").length),d=q(()=>a(m).filter(Y=>Y.status==="warned").length),x=q(()=>a(m).filter(Y=>Y.status==="errored").length),h=q(()=>a(m).filter(Y=>Y.status==="not_invoked").length),k=q(()=>e.wallSeconds==null?"—":e.wallSeconds<1?`${Math.round(e.wallSeconds*1e3)}ms`:`${e.wallSeconds.toFixed(1)}s`);var y=Ct(),o=r(y),s=r(o),l=r(s,!0);t(s),re(),t(o);var b=n(o,4),N=r(b),u=r(N,!0);t(N),re(),t(b);var v=n(b,2);{var w=Y=>{var V=bt(),G=n(ee(V),2),U=r(G),$=r(U,!0);t(U),re(),t(G),C(()=>f($,a(g))),c(Y,V)};A(v,Y=>{a(g)>0&&Y(w)})}var B=n(v,2);{var E=Y=>{var V=wt(),G=n(ee(V),2),U=r(G),$=r(U,!0);t(U),re(),t(G),C(()=>f($,a(d))),c(Y,V)};A(B,Y=>{a(d)>0&&Y(E)})}var D=n(B,2);{var H=Y=>{var V=kt(),G=n(ee(V),2),U=r(G),$=r(U,!0);t(U),re(),t(G),C(()=>f($,a(x))),c(Y,V)};A(D,Y=>{a(x)>0&&Y(H)})}var I=n(D,2);{var z=Y=>{var V=St(),G=n(ee(V),2),U=r(G),$=r(U,!0);t(U),re(),t(G),C(()=>f($,a(h))),c(Y,V)};A(I,Y=>{a(h)>0&&Y(z)})}var O=n(I,4),W=r(O),T=r(W,!0);t(W);var P=n(W);t(O);var L=n(O,4),F=r(L),j=r(F,!0);t(F),re(),t(L);var K=n(L,2);{var ae=Y=>{var V=Mt(),G=n(ee(V),2),U=r(G),$=r(U);t(U),re(),t(G),C(ve=>f($,`${ve??""}%`),[()=>Math.round(e.cacheHit*100)]),c(Y,V)};A(K,Y=>{e.cacheHit!=null&&Y(ae)})}var Q=n(K,4),Z=r(Q),ne=r(Z,!0);t(Z),re(),t(Q),t(y),C(()=>{f(l,e.stones.length),f(u,a(i)),f(T,e.cards.length),f(P,` evidence card${e.cards.length===1?"":"s"}`),f(j,a(k)),f(ne,a(M))}),c(R,y),J()}var Bt=p('<div class="subhead svelte-lygj3j"> </div>'),At=p('<p class="body-prose svelte-lygj3j"> </p>'),Lt=p('<div class="body body-headline svelte-lygj3j"><div class="headline svelte-lygj3j"> </div> <!> <!></div>');function Rt(R,e){X(e,!0);var S=Lt(),m=r(S),M=r(m,!0);t(m);var i=n(m,2);{var g=h=>{var k=Bt(),y=r(k,!0);t(k),C(()=>f(y,e.card.subhead)),c(h,k)};A(i,h=>{e.card.subhead&&h(g)})}var d=n(i,2);{var x=h=>{var k=At(),y=r(k,!0);t(k),C(()=>f(y,e.card.body)),c(h,k)};A(d,h=>{e.card.body&&h(x)})}t(S),C(()=>{oe(m,`color: var(--tier-${e.card.tier??""});`),f(M,e.card.headline??"")}),c(R,S),J()}var Ft=p('<th class="svelte-1nlkuao"> </th>'),Et=p('<td class="svelte-1nlkuao"> </td>'),Pt=p('<tr class="svelte-1nlkuao"></tr>'),Tt=p('<div class="body-sub svelte-1nlkuao"> </div>'),qt=p('<div class="body body-tabular svelte-1nlkuao"><table class="t svelte-1nlkuao"><thead><tr></tr></thead><tbody></tbody></table> <!></div>');function It(R,e){X(e,!0);var S=qt(),m=r(S),M=r(m),i=r(M);te(i,21,()=>e.card.columns??[],de,(h,k)=>{var y=Ft(),o=r(y,!0);t(y),C(()=>f(o,a(k))),c(h,y)}),t(i),t(M);var g=n(M);te(g,21,()=>e.card.rows??[],de,(h,k)=>{var y=Pt();te(y,21,()=>a(k),de,(o,s)=>{var l=Et(),b=r(l,!0);t(l),C(()=>f(b,a(s))),c(o,l)}),t(y),c(h,y)}),t(g),t(m);var d=n(m,2);{var x=h=>{var k=Tt(),y=r(k,!0);t(k),C(()=>f(y,e.card.sub)),c(h,k)};A(d,h=>{e.card.sub&&h(x)})}t(S),c(R,S),J()}var Dt=p('<div class="cell svelte-stf9c8"><div class="value svelte-stf9c8"> </div> <div class="label svelte-stf9c8"> </div></div>'),zt=p('<div class="body-sub svelte-stf9c8"> </div>'),Ot=p('<div class="body body-scalars svelte-stf9c8"><div class="row svelte-stf9c8"></div> <!></div>');function Ht(R,e){X(e,!0);var S=Ot(),m=r(S);te(m,21,()=>e.card.scalars??[],de,(g,d)=>{var x=Dt(),h=r(x),k=r(h,!0);t(h);var y=n(h,2),o=r(y,!0);t(y),t(x),C(()=>{oe(h,`color: var(--tier-${e.card.tier??""});`),f(k,a(d).value),f(o,a(d).label)}),c(g,x)}),t(m);var M=n(m,2);{var i=g=>{var d=zt(),x=r(d,!0);t(d),C(()=>f(x,e.card.sub)),c(g,d)};A(M,g=>{e.card.sub&&g(i)})}t(S),c(R,S),J()}var Yt=p('<div class="headline svelte-jrppts"> </div>'),jt=p('<div class="subhead svelte-jrppts"> </div>'),Wt=me("<rect></rect>"),Ut=p('<div class="body-sub svelte-jrppts"> </div>'),Gt=p('<div class="body-sub svelte-jrppts"> </div>'),Kt=p('<div class="body body-spark svelte-jrppts"><!> <!> <svg width="100%" preserveAspectRatio="none" aria-hidden="true" class="svelte-jrppts"></svg> <!> <!></div>');function Qt(R,e){X(e,!0);const S=240,m=38;let M=q(()=>e.card.spark??e.card.histogram??[]),i=q(()=>Math.max(...a(M),1)),g=q(()=>a(M).length),d=q(()=>Math.max(2,S/Math.max(a(g),1)-1.5));var x=Kt(),h=r(x);{var k=v=>{var w=Yt(),B=r(w,!0);t(w),C(()=>{oe(w,`color: var(--tier-${e.card.tier??""});`),f(B,e.card.headline)}),c(v,w)};A(h,v=>{e.card.headline&&v(k)})}var y=n(h,2);{var o=v=>{var w=jt(),B=r(w,!0);t(w),C(()=>f(B,e.card.subhead)),c(v,w)};A(y,v=>{e.card.subhead&&v(o)})}var s=n(y,2);_(s,"viewBox","0 0 240 38"),_(s,"height",m),te(s,21,()=>a(M),de,(v,w,B)=>{var E=Wt();C(()=>{_(E,"x",B/a(g)*S+.5),_(E,"y",m-a(w)/a(i)*m),_(E,"width",a(d)),_(E,"height",a(w)/a(i)*m),_(E,"fill",`var(--tier-${e.card.tier??""})`)}),c(v,E)}),t(s);var l=n(s,2);{var b=v=>{var w=Ut(),B=r(w,!0);t(w),C(()=>f(B,e.card.sparkSub)),c(v,w)};A(l,v=>{e.card.sparkSub&&v(b)})}var N=n(l,2);{var u=v=>{var w=Gt(),B=r(w,!0);t(w),C(()=>f(B,e.card.sub)),c(v,w)};A(N,v=>{!e.card.sparkSub&&e.card.sub&&v(u)})}t(x),c(R,x),J()}var Vt=p('<span class="headline svelte-48vbub"> </span>'),Zt=p('<span class="subhead svelte-48vbub"> </span>'),Xt=p('<span class="spatial-note svelte-48vbub"> </span>'),Jt=p("<span> </span>"),$t=p('<div class="body-sub svelte-48vbub"><!> <!></div>'),ea=p('<div class="body body-timeseries svelte-48vbub"><div class="ts-header svelte-48vbub"><!> <!></div> <svg width="100%" aria-hidden="true" class="svelte-48vbub"><line stroke="#C9C9C5" stroke-width="0.5" stroke-dasharray="2 2"></line><path fill="none" stroke-width="1.4"></path><circle r="3"></circle><text font-size="9" font-family="IBM Plex Mono" text-anchor="middle"> </text><text font-size="8" font-family="IBM Plex Mono" fill="#6B6B6B">now</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#6B6B6B"> </text></svg> <!></div>');function Ee(R,e){X(e,!0);const S=240,m=84,M=6,i=q(()=>e.card.timeseries??{hours:96,peak:{x:38,y:47},peakLabel:""}),g=q(()=>h(a(i))),d=q(()=>k(a(g),a(i))),x=q(()=>y(a(g),a(d)));function h(P){const L=[];for(let F=0;F<=P.hours;F++){const j=6*Math.sin(F/12.42*Math.PI*2),K=38*Math.exp(-Math.pow((F-P.peak.x)/12,2));L.push({x:F,y:j+K+4})}return L}function k(P,L){const F=Math.max(...P.map(K=>K.y),L.peak.y),j=Math.min(...P.map(K=>K.y),-10);return{sx:K=>M+K/L.hours*(S-M*2),sy:K=>m-M-14-(K-j)/(F-j)*(m-M*2-14)}}function y(P,L){return P.map((F,j)=>`${j?"L":"M"} ${L.sx(F.x)} ${L.sy(F.y)}`).join(" ")}var o=ea(),s=r(o),l=r(s);{var b=P=>{var L=Vt(),F=r(L,!0);t(L),C(()=>{oe(L,`color: var(--tier-${e.card.tier??""});`),f(F,e.card.headline)}),c(P,L)};A(l,P=>{e.card.headline&&P(b)})}var N=n(l,2);{var u=P=>{var L=Zt(),F=r(L,!0);t(L),C(()=>f(F,e.card.subhead)),c(P,L)};A(N,P=>{e.card.subhead&&P(u)})}t(s);var v=n(s,2);_(v,"viewBox","0 0 240 84"),_(v,"height",m);var w=r(v);_(w,"x1",M),_(w,"x2",S-M);var B=n(w),E=n(B),D=n(E),H=r(D,!0);t(D);var I=n(D);_(I,"x",M),_(I,"y",m-2);var z=n(I);_(z,"x",S-M),_(z,"y",m-2);var O=r(z);t(z),t(v);var W=n(v,2);{var T=P=>{var L=$t(),F=r(L);{var j=Q=>{var Z=Xt(),ne=r(Z,!0);t(Z),C(()=>f(ne,e.card.spatialNote)),c(Q,Z)};A(F,Q=>{e.card.spatialNote&&Q(j)})}var K=n(F,2);{var ae=Q=>{var Z=Jt(),ne=r(Z,!0);t(Z),C(()=>f(ne,e.card.sub)),c(Q,Z)};A(K,Q=>{e.card.sub&&Q(ae)})}t(L),c(P,L)};A(W,P=>{(e.card.spatialNote||e.card.sub)&&P(T)})}t(o),C((P,L,F,j,K,ae)=>{_(w,"y1",P),_(w,"y2",L),_(B,"d",a(x)),_(B,"stroke",`var(--tier-${e.card.tier??""})`),_(E,"cx",F),_(E,"cy",j),_(E,"fill",`var(--tier-${e.card.tier??""})`),_(D,"x",K),_(D,"y",ae),_(D,"fill",`var(--tier-${e.card.tier??""})`),f(H,a(i).peakLabel),f(O,`+${a(i).hours??""}h`)},[()=>a(d).sy(0),()=>a(d).sy(0),()=>a(d).sx(a(i).peak.x),()=>a(d).sy(a(i).peak.y),()=>a(d).sx(a(i).peak.x),()=>a(d).sy(a(i).peak.y)-6]),c(R,o),J()}var ta=p('<span class="ft-stat svelte-1y25lfh"><span class="ft-stat-k svelte-1y25lfh">RMSE</span> </span>'),aa=p('<span class="ft-stat ft-skill svelte-1y25lfh"> </span>'),ra=p('<span class="ft-badge svelte-1y25lfh" title="Trained on this hardware"> </span>'),sa=p('<a class="ft-link svelte-1y25lfh" target="_blank" rel="noopener noreferrer">Model card ↗</a>'),ia=p('<!> <div class="ft-footer svelte-1y25lfh"><!> <!> <!> <!></div>',1);function na(R,e){X(e,!0);var S=ia(),m=ee(S);Ee(m,{get card(){return e.card}});var M=n(m,2),i=r(M);{var g=s=>{var l=ta(),b=n(r(l));t(l),C(()=>f(b,` ${e.card.rmse??""}`)),c(s,l)};A(i,s=>{e.card.rmse&&s(g)})}var d=n(i,2);{var x=s=>{var l=aa(),b=r(l,!0);t(l),C(()=>f(b,e.card.skillVsPersistence)),c(s,l)};A(d,s=>{e.card.skillVsPersistence&&s(x)})}var h=n(d,2);{var k=s=>{var l=ra(),b=r(l,!0);t(l),C(()=>f(b,e.card.hardwareBadge)),c(s,l)};A(h,s=>{e.card.hardwareBadge&&s(k)})}var y=n(h,2);{var o=s=>{var l=sa();C(b=>_(l,"href",b),[()=>e.card.hfModelCard.startsWith("http")?e.card.hfModelCard:`https://${e.card.hfModelCard}`]),c(s,l)};A(y,s=>{e.card.hfModelCard&&s(o)})}t(M),c(R,S),J()}var la=me('<circle r="2.2"></circle><text font-size="9" font-family="IBM Plex Mono" text-anchor="middle" fill="#6B6B6B"> </text>',1),oa=p('<div class="body-sub svelte-gqkhpe"> </div>'),da=p('<div class="body body-forecast svelte-gqkhpe"><svg width="100%" aria-hidden="true" class="svelte-gqkhpe"><path fill-opacity="0.18"></path><path fill="none" stroke-width="1.5"></path><!></svg> <!></div>');function va(R,e){X(e,!0);const S=240,m=88,M=6;let i=q(()=>e.card.forecast??[]),g=q(()=>a(i).map((v,w)=>M+w/Math.max(a(i).length-1,1)*(S-M*2))),d=q(()=>Math.max(...a(i).map(v=>v.high),1));function x(v){return m-M-v/a(d)*(m-M*2-12)}let h=q(()=>a(g).map((v,w)=>`${w?"L":"M"} ${v} ${x(a(i)[w].mid)}`).join(" ")),k=q(()=>{if(!a(i).length)return"";const v=a(g).map((B,E)=>`${B} ${x(a(i)[E].low)}`).join(" L "),w=[...a(g)].reverse().map((B,E)=>`${B} ${x(a(i)[a(i).length-1-E].high)}`).join(" L ");return`M ${v} L ${w} Z`});var y=da(),o=r(y);_(o,"viewBox","0 0 240 88"),_(o,"height",m);var s=r(o),l=n(s),b=n(l);te(b,17,()=>a(i),de,(v,w,B)=>{var E=la(),D=ee(E),H=n(D);_(H,"y",m-1);var I=r(H,!0);t(H),C(z=>{_(D,"cx",a(g)[B]),_(D,"cy",z),_(D,"fill",`var(--tier-${e.card.tier??""})`),_(H,"x",a(g)[B]),f(I,a(w).year)},[()=>x(a(w).mid)]),c(v,E)}),t(o);var N=n(o,2);{var u=v=>{var w=oa(),B=r(w,!0);t(w),C(()=>f(B,e.card.sub)),c(v,w)};A(N,v=>{e.card.sub&&v(u)})}t(y),C(()=>{_(s,"d",a(k)),_(s,"fill",`var(--tier-${e.card.tier??""})`),_(l,"d",a(h)),_(l,"stroke",`var(--tier-${e.card.tier??""})`)}),c(R,y),J()}var ca=me('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#E8ECF2"></rect><g stroke="#D9D6CC" stroke-width="0.6"><line x1="0" y1="40" y2="40"></line><line x1="0" y1="80" y2="80"></line><line x1="60" y1="0" x2="60"></line><line x1="160" y1="0" x2="160"></line></g><path d="M20 50 Q 60 38 90 56 Q 120 76 150 64 Q 180 50 180 86 Q 130 100 70 96 Q 30 92 20 76 Z" fill="rgba(42,111,168,0.32)" stroke="#2A6FA8" stroke-width="0.7"></path><path d="M40 60 Q 80 54 110 70 Q 140 84 160 78 Q 165 90 130 92 Q 80 90 50 82 Z" fill="rgba(11,83,148,0.36)" stroke="#0B5394" stroke-width="0.6"></path><circle cx="120" cy="74" r="3.2" fill="#005EA2" stroke="#F4F6F9" stroke-width="1.3"></circle><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#6B6B6B">2.13 in/hr · MOD</text></svg>'),ua=me('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#E8ECF2"></rect><g stroke="#D9D6CC" stroke-width="0.6"><line x1="0" y1="40" y2="40"></line><line x1="0" y1="80" y2="80"></line><line x1="60" y1="0" x2="60"></line><line x1="160" y1="0" x2="160"></line></g><path d="M180 92 Q 200 88 215 96 Q 220 105 200 104 Q 185 102 180 96 Z" fill="rgba(42,111,168,0.18)" stroke="#2A6FA8" stroke-width="0.5" stroke-dasharray="2 2"></path><circle cx="120" cy="60" r="3.2" fill="#005EA2" stroke="#F4F6F9" stroke-width="1.3"></circle><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#6B6B6B">no ponding · MOD</text></svg>'),ga=me('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><defs><pattern id="rt-s2-rgb" x="0" y="0" width="6" height="6" patternUnits="userSpaceOnUse"><rect width="6" height="6" fill="#7A8E6A"></rect><rect x="0" y="0" width="3" height="3" fill="#8D9C7A"></rect><rect x="3" y="3" width="3" height="3" fill="#69795D"></rect></pattern></defs><rect fill="url(#rt-s2-rgb)"></rect><rect x="0" y="55" height="6" fill="#A8A496"></rect><rect x="115" y="0" width="8" fill="#A8A496"></rect><ellipse cx="50" cy="92" rx="6" ry="3" fill="#2A6FA8" fill-opacity="0.65"></ellipse><text x="6" y="14" font-size="9" font-family="IBM Plex Mono" fill="#F4F6F9">PRITHVI · 0.3%</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#F4F6F9">scene 2026-05-02</text></svg>'),ha=me('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#E8ECF2"></rect><rect x="0" y="0" width="80" height="60" fill="#C66"></rect><rect x="80" y="0" width="60" height="60" fill="#C66"></rect><rect x="140" y="0" width="100" height="38" fill="#C66"></rect><rect x="140" y="38" width="100" height="22" fill="#5B7FB4"></rect><rect x="0" y="60" width="100" height="60" fill="#C66"></rect><rect x="100" y="60" width="50" height="40" fill="#5B8A4A"></rect><rect x="150" y="60" width="50" height="60" fill="#D9C75A"></rect><rect x="200" y="60" width="40" height="60" fill="#C66"></rect><rect x="100" y="100" width="50" height="20" fill="#A89A78"></rect><text x="6" y="14" font-size="9" font-family="IBM Plex Mono" fill="#F4F6F9">LULC · TerraMind</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#F4F6F9">scene 2026-05-02</text></svg>'),ma=me('<rect fill="rgba(42,111,168,0.55)" stroke="#2A6FA8" stroke-width="0.4"></rect>'),fa=me('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#3A3A38"></rect><!><text x="6" y="14" font-size="9" font-family="IBM Plex Mono" fill="#F4F6F9">BLDG · TerraMind</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#F4F6F9">36.2% built</text></svg>'),_a=p('<div class="thumb-placeholder svelte-1lx1psy">raster preview</div>');function Pe(R,e){var M=xe(),i=ee(M);{var g=o=>{var s=ca();_(s,"viewBox","0 0 240 120"),_(s,"height",120);var l=r(s);_(l,"width",240),_(l,"height",120);var b=n(l),N=r(b);_(N,"x2",240);var u=n(N);_(u,"x2",240);var v=n(u);_(v,"y2",120);var w=n(v);_(w,"y2",120),t(b);var B=n(b,4);_(B,"x",234),_(B,"y",115),t(s),c(o,s)},d=o=>{var s=ua();_(s,"viewBox","0 0 240 120"),_(s,"height",120);var l=r(s);_(l,"width",240),_(l,"height",120);var b=n(l),N=r(b);_(N,"x2",240);var u=n(N);_(u,"x2",240);var v=n(u);_(v,"y2",120);var w=n(v);_(w,"y2",120),t(b);var B=n(b,3);_(B,"x",234),_(B,"y",115),t(s),c(o,s)},x=o=>{var s=ga();_(s,"viewBox","0 0 240 120"),_(s,"height",120);var l=n(r(s));_(l,"width",240),_(l,"height",120);var b=n(l);_(b,"width",240);var N=n(b);_(N,"height",120);var u=n(N,3);_(u,"x",234),_(u,"y",115),t(s),c(o,s)},h=o=>{var s=ha();_(s,"viewBox","0 0 240 120"),_(s,"height",120);var l=r(s);_(l,"width",240),_(l,"height",120);var b=n(l,11);_(b,"x",234),_(b,"y",115),t(s),c(o,s)},k=o=>{var s=fa();_(s,"viewBox","0 0 240 120"),_(s,"height",120);var l=r(s);_(l,"width",240),_(l,"height",120);var b=n(l);te(b,16,()=>[[10,10,28,18],[42,10,30,16],[78,10,40,22],[124,10,32,18],[162,10,30,18],[198,10,32,18],[10,32,28,16],[42,30,30,18],[124,32,32,16],[162,32,30,16],[198,32,32,16],[10,55,28,18],[42,55,30,18],[78,55,40,18],[124,55,32,18],[162,55,30,18],[198,55,32,18],[10,80,28,16],[42,80,30,16],[78,80,40,16],[124,80,32,16],[162,80,30,16],[10,100,28,12],[42,100,30,12],[78,100,40,12]],de,(u,v)=>{var w=ma();C(()=>{_(w,"x",v[0]),_(w,"y",v[1]),_(w,"width",v[2]),_(w,"height",v[3])}),c(u,w)});var N=n(b,2);_(N,"x",234),_(N,"y",115),t(s),c(o,s)},y=o=>{var s=_a();c(o,s)};A(i,o=>{e.kind==="stormwater"?o(g):e.kind==="stormwater-dry"?o(d,1):e.kind==="prithvi"?o(x,2):e.kind==="lulc"?o(h,3):e.kind==="buildings"?o(k,4):o(y,-1)})}c(R,M)}var ya=p('<span class="illustrative svelte-1m43x1m" title="Illustrative rendering, not source pixels">illustrative</span>'),pa=p('<span class="svelte-1m43x1m"> </span>'),xa=p('<div class="raster-headline svelte-1m43x1m"><span class="svelte-1m43x1m"> </span> <!></div>'),ba=p('<div class="body-sub svelte-1m43x1m"> </div>'),wa=p('<div class="body body-raster svelte-1m43x1m"><div class="frame svelte-1m43x1m"><!> <!></div> <!> <!></div>');function ka(R,e){X(e,!0);var S=wa(),m=r(S),M=r(m);Pe(M,{get kind(){return e.card.rasterKind}});var i=n(M,2);{var g=y=>{var o=ya();c(y,o)};A(i,y=>{(e.card.illustrative||e.card.tier==="synthetic")&&y(g)})}t(m);var d=n(m,2);{var x=y=>{var o=xa(),s=r(o),l=r(s,!0);t(s);var b=n(s,2);{var N=u=>{var v=pa(),w=r(v);t(v),C(()=>f(w,`· ${e.card.subhead??""}`)),c(u,v)};A(b,u=>{e.card.subhead&&u(N)})}t(o),C(()=>{oe(s,`color: var(--tier-${e.card.tier??""});`),f(l,e.card.headline)}),c(y,o)};A(d,y=>{e.card.headline&&y(x)})}var h=n(d,2);{var k=y=>{var o=ba(),s=r(o,!0);t(o),C(()=>f(s,e.card.sub)),c(y,o)};A(h,y=>{e.card.sub&&y(k)})}t(S),c(R,S),J()}var Sa=p('<span class="illustrative svelte-1td276x" title="Illustrative rendering, not source pixels">illustrative</span>'),Ma=p('<span class="bar-seg svelte-1td276x"></span>'),Ca=p('<li class="svelte-1td276x"><span class="swatch svelte-1td276x"></span> <span class="legend-k svelte-1td276x"> </span> <span class="legend-pct svelte-1td276x"> </span></li>'),Na=p('<div class="bar svelte-1td276x" role="img" aria-label="LULC class mix"></div> <ul class="legend svelte-1td276x"></ul>',1),Ba=p('<div class="body-sub svelte-1td276x"> </div>'),Aa=p('<div class="body body-lulc svelte-1td276x"><div class="frame svelte-1td276x"><!> <!></div> <!> <!></div>');function La(R,e){X(e,!0);let S=q(()=>(e.card.classMix??[]).reduce((o,s)=>o+(s.pct||0),0)||1);var m=Aa(),M=r(m),i=r(M);{let o=q(()=>e.card.rasterKind??"lulc");Pe(i,{get kind(){return a(o)}})}var g=n(i,2);{var d=o=>{var s=Sa();c(o,s)};A(g,o=>{(e.card.illustrative||e.card.tier==="synthetic")&&o(d)})}t(M);var x=n(M,2);{var h=o=>{var s=Na(),l=ee(s);te(l,21,()=>e.card.classMix,N=>N.k,(N,u)=>{var v=Ma();let w;C(()=>{_(v,"title",`${a(u).k??""}: ${a(u).pct??""}%`),w=oe(v,"",w,{"flex-grow":a(u).pct/a(S),background:a(u).color})}),c(N,v)}),t(l);var b=n(l,2);te(b,21,()=>e.card.classMix,N=>N.k,(N,u)=>{var v=Ca(),w=r(v);let B;var E=n(w,2),D=r(E,!0);t(E);var H=n(E,2),I=r(H);t(H),t(v),C(()=>{B=oe(w,"",B,{background:a(u).color}),f(D,a(u).k),f(I,`${a(u).pct??""}%`)}),c(N,v)}),t(b),c(o,s)};A(x,o=>{var s;(s=e.card.classMix)!=null&&s.length&&o(h)})}var k=n(x,2);{var y=o=>{var s=Ba(),l=r(s,!0);t(s),C(()=>f(l,e.card.sub)),c(o,s)};A(k,o=>{e.card.sub&&o(y)})}t(m),c(R,m),J()}var Ra=p('<span class="reg-label svelte-1iup6im"> </span> <span class="reg-source svelte-1iup6im"> </span>',1),Fa=p('<span class="reg-silent svelte-1iup6im"> </span>'),Ea=p('<li><span class="reg-tag svelte-1iup6im"><!> <span> </span></span> <!></li>'),Pa=p('<div class="body-sub svelte-1iup6im"> </div>'),Ta=p('<div class="body body-register svelte-1iup6im"><ul class="reg-list svelte-1iup6im"></ul> <!></div>');function qa(R,e){X(e,!0);var S=Ta(),m=r(S);te(m,21,()=>e.card.registers??[],de,(g,d)=>{var x=Ea();let h;var k=r(x),y=r(k);ge(y,{get tier(){return a(d).tier},size:9,get color(){return`var(--tier-${a(d).tier??""})`}});var o=n(y,2),s=r(o,!0);t(o),t(k);var l=n(k,2);{var b=u=>{var v=Ra(),w=ee(v),B=r(w,!0);t(w);var E=n(w,2),D=r(E,!0);t(E),C(()=>{_(w,"title",a(d).detail?`${a(d).label} — ${a(d).detail}`:a(d).label),f(B,a(d).label),f(D,a(d).sourceId??"")}),c(u,v)},N=u=>{var v=Fa(),w=r(v,!0);t(v),C(()=>f(w,a(d).note)),c(u,v)};A(l,u=>{a(d).label?u(b):u(N,-1)})}t(x),C(()=>{h=ue(x,1,"reg-row svelte-1iup6im",null,h,{silent:!a(d).label}),_(k,"title",a(d).tier),f(s,a(d).reg)}),c(g,x)}),t(m);var M=n(m,2);{var i=g=>{var d=Pa(),x=r(d,!0);t(d),C(()=>f(x,e.card.sub)),c(g,d)};A(M,g=>{e.card.sub&&g(i)})}t(S),c(R,S),J()}var Ia=p('<div class="cell-aux svelte-1swqabu"> </div>'),Da=p('<div class="cell svelte-1swqabu"><div class="cell-tier svelte-1swqabu"><!> <span class="cell-label"> </span></div> <div class="cell-value svelte-1swqabu"> </div> <!></div>'),za=p('<div class="cell-aux svelte-1swqabu"> </div>'),Oa=p('<div class="cell svelte-1swqabu"><div class="cell-tier svelte-1swqabu"><!> <span class="cell-label"> </span></div> <div class="cell-value svelte-1swqabu"> </div> <!></div>'),Ha=p('<div class="cmp-delta svelte-1swqabu"> </div>'),Ya=p('<div class="body-sub svelte-1swqabu"> </div>'),ja=p('<div class="body body-comparison svelte-1swqabu"><div class="cmp-grid svelte-1swqabu"><!> <div class="divider svelte-1swqabu" aria-hidden="true">vs</div> <!></div> <!> <!></div>');function Wa(R,e){X(e,!0);var S=ja(),m=r(S),M=r(m);{var i=o=>{var s=Da(),l=r(s),b=r(l);ge(b,{get tier(){return e.card.left.tier},size:10,get color(){return`var(--tier-${e.card.left.tier??""})`}});var N=n(b,2),u=r(N,!0);t(N),t(l);var v=n(l,2),w=r(v,!0);t(v);var B=n(v,2);{var E=D=>{var H=Ia(),I=r(H,!0);t(H),C(()=>f(I,e.card.left.aux)),c(D,H)};A(B,D=>{e.card.left.aux&&D(E)})}t(s),C(()=>{f(u,e.card.left.label),oe(v,`color: var(--tier-${e.card.left.tier??""});`),f(w,e.card.left.value)}),c(o,s)};A(M,o=>{e.card.left&&o(i)})}var g=n(M,4);{var d=o=>{var s=Oa(),l=r(s),b=r(l);ge(b,{get tier(){return e.card.right.tier},size:10,get color(){return`var(--tier-${e.card.right.tier??""})`}});var N=n(b,2),u=r(N,!0);t(N),t(l);var v=n(l,2),w=r(v,!0);t(v);var B=n(v,2);{var E=D=>{var H=za(),I=r(H,!0);t(H),C(()=>f(I,e.card.right.aux)),c(D,H)};A(B,D=>{e.card.right.aux&&D(E)})}t(s),C(()=>{f(u,e.card.right.label),oe(v,`color: var(--tier-${e.card.right.tier??""});`),f(w,e.card.right.value)}),c(o,s)};A(g,o=>{e.card.right&&o(d)})}t(m);var x=n(m,2);{var h=o=>{var s=Ha(),l=r(s,!0);t(s),C(()=>f(l,e.card.delta)),c(o,s)};A(x,o=>{e.card.delta&&o(h)})}var k=n(x,2);{var y=o=>{var s=Ya(),l=r(s,!0);t(s),C(()=>f(l,e.card.sub)),c(o,s)};A(k,o=>{e.card.sub&&o(y)})}t(S),c(R,S),J()}var Ua=p('<div class="meta-row svelte-e40scu"><dt class="svelte-e40scu"> </dt> <dd class="svelte-e40scu"> </dd></div>'),Ga=p('<div class="body-sub svelte-e40scu"> </div>'),Ka=p('<div class="body body-meta svelte-e40scu"><dl class="meta-list svelte-e40scu"></dl> <!></div>');function Qa(R,e){X(e,!0);var S=Ka(),m=r(S);te(m,21,()=>e.card.metaRows??[],de,(g,d)=>{var x=Ua(),h=r(x),k=r(h,!0);t(h);var y=n(h,2),o=r(y,!0);t(y),t(x),C(()=>{f(k,a(d).k),f(o,a(d).v)}),c(g,x)}),t(m);var M=n(m,2);{var i=g=>{var d=Ga(),x=r(d,!0);t(d),C(()=>f(x,e.card.sub)),c(g,d)};A(M,g=>{e.card.sub&&g(i)})}t(S),c(R,S),J()}var Va=p('<div class="unknown svelte-1x6xqhh"> </div>');function Za(R,e){X(e,!0);var S=xe(),m=ee(S);{var M=u=>{Rt(u,{get card(){return e.card}})},i=u=>{It(u,{get card(){return e.card}})},g=u=>{Ht(u,{get card(){return e.card}})},d=u=>{Qt(u,{get card(){return e.card}})},x=u=>{Ee(u,{get card(){return e.card}})},h=u=>{na(u,{get card(){return e.card}})},k=u=>{va(u,{get card(){return e.card}})},y=u=>{ka(u,{get card(){return e.card}})},o=u=>{La(u,{get card(){return e.card}})},s=u=>{qa(u,{get card(){return e.card}})},l=u=>{Wa(u,{get card(){return e.card}})},b=u=>{Qa(u,{get card(){return e.card}})},N=u=>{var v=Va(),w=r(v);t(v),C(()=>f(w,`unknown variant: ${e.card.variant??""}`)),c(u,v)};A(m,u=>{e.card.variant==="headline"?u(M):e.card.variant==="tabular"?u(i,1):e.card.variant==="scalars"?u(g,2):e.card.variant==="spark"||e.card.variant==="histogram"?u(d,3):e.card.variant==="timeseries"?u(x,4):e.card.variant==="timeseries-ft"?u(h,5):e.card.variant==="forecast"?u(k,6):e.card.variant==="raster"||e.card.variant==="raster-pred"?u(y,7):e.card.variant==="lulc"?u(o,8):e.card.variant==="register"?u(s,9):e.card.variant==="comparison"?u(l,10):e.card.variant==="meta"?u(b,11):u(N,-1)})}c(R,S),J()}var Xa=p('<button type="button" class="fc-foot-cite svelte-1nuvnzu"><span class="fc-foot-docid svelte-1nuvnzu"> </span> <span class="fc-foot-arrow svelte-1nuvnzu" aria-hidden="true">→</span></button>'),Ja=p('<span class="fc-foot-docid fc-foot-docid-mute svelte-1nuvnzu"> </span>'),$a=p('<header class="fc-head svelte-1nuvnzu"><div class="fc-head-source svelte-1nuvnzu"><!> <span class="fc-head-source-label svelte-1nuvnzu"> </span></div> <span class="fc-head-vintage svelte-1nuvnzu"> </span></header> <h4 class="fc-title svelte-1nuvnzu"> </h4> <!> <footer class="fc-foot svelte-1nuvnzu"><!> <span><!> <span> </span></span></footer>',1);function Te(R,e){X(e,!0);let S=ie(e,"density",3,"comfortable"),m=ie(e,"linkedKey",3,null),M=q(()=>m()!=null&&e.card.mapLayer!=null&&e.card.mapLayer===m()),i=q(()=>Re[e.card.tier].short),g=q(()=>e.card.mapLayer!=null);function d(){var s;e.card.mapLayer&&((s=e.onLink)==null||s.call(e,e.card.mapLayer))}function x(){var s;e.card.mapLayer&&((s=e.onLink)==null||s.call(e,null))}function h(s){var l;s.stopPropagation(),e.card.citeId&&((l=e.onCite)==null||l.call(e,e.card.citeId))}function k(s){var l;a(g)&&(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),(l=e.onLink)==null||l.call(e,e.card.mapLayer??null))}var y=xe(),o=ee(y);st(o,()=>a(g)?"button":"article",!1,(s,l)=>{Xe(s,()=>({type:a(g)?"button":void 0,role:a(g)?"button":"article",class:`fc fc-${e.card.variant??""} fc-tier-${e.card.tier??""}`,"aria-labelledby":`fc-${e.card.id}-title`,"aria-label":`${Re[e.card.tier].label} card · ${e.card.title} · ${e.card.source}`,onpointerenter:d,onpointerleave:x,onfocus:d,onblur:x,onkeydown:k,[Je]:{"is-compact":S()==="compact","is-linked":a(M),"is-interactive":a(g),"has-illustrative":e.card.illustrative||e.card.tier==="synthetic"||e.card.variant==="comparison"}}),void 0,void 0,void 0,"svelte-1nuvnzu");var b=$a(),N=ee(b),u=r(N),v=r(u);ge(v,{get tier(){return e.card.tier},size:11,get color(){return`var(--tier-${e.card.tier??""})`}});var w=n(v,2),B=r(w,!0);t(w),t(u);var E=n(u,2),D=r(E);t(E),t(N);var H=n(N,2),I=r(H,!0);t(H);var z=n(H,2);Za(z,{get card(){return e.card}});var O=n(z,2),W=r(O);{var T=ae=>{var Q=Xa(),Z=r(Q),ne=r(Z,!0);t(Z),re(2),t(Q),C(()=>{_(Q,"title",`Open ${e.card.docId} in citation drawer`),f(ne,e.card.docId)}),Ne("click",Q,h),c(ae,Q)},P=ae=>{var Q=Ja(),Z=r(Q,!0);t(Q),C(()=>f(Z,e.card.docId)),c(ae,Q)};A(W,ae=>{e.card.citeId?ae(T):ae(P,-1)})}var L=n(W,2),F=r(L);ge(F,{get tier(){return e.card.tier},size:9,get color(){return`var(--tier-${e.card.tier??""})`}});var j=n(F,2),K=r(j,!0);t(j),t(L),t(O),C(()=>{_(w,"title",e.card.agency),f(B,e.card.source),f(D,`v. ${e.card.vintage??""}`),_(H,"id",`fc-${e.card.id}-title`),f(I,e.card.title),ue(L,1,`fc-tier-badge fc-tier-badge-${e.card.tier??""}`,"svelte-1nuvnzu"),_(L,"aria-label",`epistemic tier ${a(i)}`),f(K,a(i))}),c(l,b)}),c(R,y),J()}Ce(["click"]);var er=p('<span class="sep svelte-1qqbvs2">·</span> <span class="silent svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> silent</span>',1),tr=p('<span class="sep svelte-1qqbvs2">·</span> <span class="warn svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> warn</span>',1),ar=p('<span class="sep svelte-1qqbvs2">·</span> <span class="err svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> errored</span>',1),rr=p('<span class="sep svelte-1qqbvs2">·</span> <span class="notinvoked svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> not invoked</span>',1),sr=p('<span class="tally svelte-1qqbvs2"><span class="cards"> </span> <span class="sep svelte-1qqbvs2">·</span> <span class="fired"><strong class="svelte-1qqbvs2"> </strong> fired</span> <!> <!> <!> <!> <span class="sep svelte-1qqbvs2">·</span> <span class="ms"><strong class="svelte-1qqbvs2"> </strong></span></span>');function ir(R,e){X(e,!0);function S(T){return T.flatMap(P=>P.children?[P,...S(P.children)]:[P])}let m=q(()=>S(e.members)),M=q(()=>a(m).filter(T=>T.status==="fired"||T.status==="warned").length),i=q(()=>a(m).filter(T=>T.status==="silent_by_design").length),g=q(()=>a(m).filter(T=>T.status==="warned").length),d=q(()=>a(m).filter(T=>T.status==="errored").length),x=q(()=>a(m).filter(T=>T.status==="not_invoked").length),h=q(()=>e.members.reduce((T,P)=>Math.max(T,P.ms??0),0));function k(T){return T===0?"—":T<1e3?`${T}ms`:`${(T/1e3).toFixed(1)}s`}var y=sr(),o=r(y),s=r(o);t(o);var l=n(o,4),b=r(l),N=r(b,!0);t(b),re(),t(l);var u=n(l,2);{var v=T=>{var P=er(),L=n(ee(P),2),F=r(L),j=r(F,!0);t(F),re(),t(L),C(()=>f(j,a(i))),c(T,P)};A(u,T=>{a(i)>0&&T(v)})}var w=n(u,2);{var B=T=>{var P=tr(),L=n(ee(P),2),F=r(L),j=r(F,!0);t(F),re(),t(L),C(()=>f(j,a(g))),c(T,P)};A(w,T=>{a(g)>0&&T(B)})}var E=n(w,2);{var D=T=>{var P=ar(),L=n(ee(P),2),F=r(L),j=r(F,!0);t(F),re(),t(L),C(()=>f(j,a(d))),c(T,P)};A(E,T=>{a(d)>0&&T(D)})}var H=n(E,2);{var I=T=>{var P=rr(),L=n(ee(P),2),F=r(L),j=r(F,!0);t(F),re(),t(L),C(()=>f(j,a(x))),c(T,P)};A(H,T=>{a(x)>0&&T(I)})}var z=n(H,4),O=r(z),W=r(O,!0);t(O),t(z),t(y),C(T=>{f(s,`${e.cardCount??""} card${e.cardCount===1?"":"s"}`),f(N,a(M)),f(W,T)},[()=>k(a(h))]),c(R,y),J()}var nr=p('<span class="prov-tier svelte-qakefz"><!></span>'),lr=p('<span class="prov-note svelte-qakefz"> </span>'),or=p('<span class="prov-ms svelte-qakefz"> </span>'),dr=p('<li class="prov-children svelte-qakefz"><!></li>'),vr=p('<li><span class="prov-pip svelte-qakefz" aria-hidden="true"> </span> <span class="prov-id svelte-qakefz"> </span> <!> <span class="prov-name svelte-qakefz"> </span> <!> <!></li> <!>',1),cr=p('<ul class="prov-tree svelte-qakefz"></ul>');function qe(R,e){X(e,!0);let S=ie(e,"depth",3,0);function m(g){return{fired:"●",silent_by_design:"○",warned:"▲",errored:"■",not_invoked:"□"}[g]}function M(g){return g.status==="warned"?"#B7791F":g.status==="errored"?"#B91C1C":g.status==="silent_by_design"||g.status==="not_invoked"?"var(--ink-tertiary)":g.tier?`var(--tier-${g.tier})`:"var(--ink)"}var i=cr();te(i,21,()=>e.members,g=>g.id,(g,d)=>{var x=vr(),h=ee(x),k=r(h),y=r(k,!0);t(k);var o=n(k,2),s=r(o,!0);t(o);var l=n(o,2);{var b=I=>{var z=nr(),O=r(z);{let W=q(()=>`var(--tier-${a(d).tier})`);ge(O,{get tier(){return a(d).tier},size:9,get color(){return a(W)}})}t(z),c(I,z)};A(l,I=>{a(d).tier&&I(b)})}var N=n(l,2),u=r(N,!0);t(N);var v=n(N,2);{var w=I=>{var z=lr(),O=r(z);t(z),C(()=>f(O,`— ${a(d).note??""}`)),c(I,z)};A(v,I=>{a(d).note&&I(w)})}var B=n(v,2);{var E=I=>{var z=or(),O=r(z,!0);t(z),C(W=>f(O,W),[()=>a(d).ms<1e3?`${a(d).ms}ms`:`${(a(d).ms/1e3).toFixed(1)}s`]),c(I,z)};A(B,I=>{a(d).ms!=null&&I(E)})}t(h);var D=n(h,2);{var H=I=>{var z=dr(),O=r(z);{let W=q(()=>S()+1);qe(O,{get members(){return a(d).children},get depth(){return a(W)}})}t(z),c(I,z)};A(D,I=>{var z;(z=a(d).children)!=null&&z.length&&I(H)})}C((I,z)=>{ue(h,1,`prov-row prov-status-${a(d).status??""}`,"svelte-qakefz"),oe(k,`color: ${I??""};`),f(y,z),f(s,a(d).id),f(u,a(d).name)},[()=>M(a(d)),()=>m(a(d).status)]),c(g,x)}),t(i),C(()=>oe(i,`--depth: ${S()??""};`)),c(R,i),J()}var ur=p('<div class="silent svelte-16iv0n8"><span class="silent-tag svelte-16iv0n8">silent</span> <p class="silent-prose svelte-16iv0n8"><!></p></div>'),gr=p("<div></div>"),hr=p('<div class="prov-body svelte-16iv0n8"><!></div>'),mr=p('<section><header class="region-head svelte-16iv0n8"><div class="region-head-left svelte-16iv0n8"><span class="region-num svelte-16iv0n8"> </span> <h3 class="region-name svelte-16iv0n8"> </h3> <span class="region-role svelte-16iv0n8"> </span> <span class="region-tag svelte-16iv0n8"> </span></div> <!></header> <!> <div class="prov svelte-16iv0n8"><button type="button" class="prov-toggle svelte-16iv0n8"><span class="prov-caret svelte-16iv0n8" aria-hidden="true"> </span> <span class="prov-label"> </span> <span class="prov-meta svelte-16iv0n8"> </span></button> <!></div></section>');function fr(R,e){X(e,!0);let S=ie(e,"density",3,"comfortable"),m=ie(e,"provenanceMode",3,"smart"),M=ie(e,"linkedKey",3,null),i=q(()=>Me[e.stone]),g=q(()=>`${Be.indexOf(e.stone)+1}`.padStart(2,"0")),d=q(()=>e.stone==="capstone");function x(G){return G.flatMap(U=>U.children?[U,...x(U.children)]:[U])}let h=q(()=>x(e.trace.members)),k=q(()=>a(h).length),y=q(()=>a(h).some(G=>G.status==="warned"||G.status==="errored"||G.status==="not_invoked")),o=q(()=>m()==="all-expanded"?!0:m()==="all-collapsed"?!1:a(y)),s=Se(null),l=q(()=>a(s)??a(o));le(()=>{m(),pe(s,null)});var b=mr(),N=r(b),u=r(N),v=r(u),w=r(v,!0);t(v);var B=n(v,2),E=r(B,!0);t(B);var D=n(B,2),H=r(D);t(D);var I=n(D,2),z=r(I,!0);t(I),t(u);var O=n(u,2);ir(O,{get cardCount(){return e.cards.length},get members(){return e.trace.members}}),t(N);var W=n(N,2);{var T=G=>{var U=ur(),$=n(r(U),2),ve=r($);{var fe=he=>{var se=ye("No projection cards landed for this query. Atomic functions still ran (see provenance) and returned silence rather than confabulation.");c(he,se)},be=he=>{var se=ye("No cards for this Stone on this query.");c(he,se)};A(ve,he=>{e.stone==="lodestone"?he(fe):he(be,-1)})}t($),t(U),c(G,U)},P=G=>{var U=gr();let $;te(U,21,()=>e.cards,ve=>ve.id,(ve,fe)=>{Te(ve,{get card(){return a(fe)},get density(){return S()},get linkedKey(){return M()},get onCite(){return e.onCite},get onLink(){return e.onLink}})}),t(U),C(()=>$=ue(U,1,"rail svelte-16iv0n8",null,$,{"rail-capstone":a(d)})),c(G,U)};A(W,G=>{e.cards.length===0?G(T):G(P,-1)})}var L=n(W,2),F=r(L),j=r(F),K=r(j,!0);t(j);var ae=n(j,2),Q=r(ae);t(ae);var Z=n(ae,2),ne=r(Z);t(Z),t(F);var Y=n(F,2);{var V=G=>{var U=hr(),$=r(U);qe($,{get members(){return e.trace.members}}),t(U),C(()=>_(U,"id",`prov-body-${e.stone}`)),c(G,U)};A(Y,G=>{a(l)&&G(V)})}t(L),t(b),C(()=>{ue(b,1,`region region-${e.stone??""}`,"svelte-16iv0n8"),_(b,"aria-labelledby",`region-h-${e.stone}`),_(b,"data-stone",e.stone),f(w,a(g)),_(B,"id",`region-h-${e.stone}`),f(E,a(i).name),f(H,`· ${a(i).role??""}`),f(z,a(i).tag),_(F,"aria-expanded",a(l)),_(F,"aria-controls",`prov-body-${e.stone}`),f(K,a(l)?"▾":"▸"),f(Q,`${a(l)?"Hide":"Show"} provenance`),f(ne,`· ${a(k)??""} function${a(k)===1?"":"s"}`)}),Ne("click",F,()=>pe(s,!a(l))),c(R,b),J()}Ce(["click"]);var _r=p('<section class="region region-grammar svelte-gwg123" aria-label="Card grammar reference"><header class="region-head svelte-gwg123"><div class="region-head-left svelte-gwg123"><span class="region-num svelte-gwg123">SPEC</span> <h3 class="region-name svelte-gwg123">Card grammar</h3> <span class="region-role svelte-gwg123">· every body variant in the system</span> <span class="region-tag svelte-gwg123">stubs, not findings</span></div> <span class="grammar-count svelte-gwg123"> </span></header> <div class="rail svelte-gwg123"></div></section>');function yr(R,e){let S=ie(e,"density",3,"comfortable");const m=[{id:"grm-headline",stone:"cornerstone",tier:"modeled",variant:"headline",source:"FEMA",agency:"spec",vintage:"spec",title:"Single big number, scenario-tagged",headline:"Zone AE",subhead:"preliminary FIRM, panel ID",sub:"Use when the answer is one categorical state.",docId:"DS-HEADLINE"},{id:"grm-tabular",stone:"cornerstone",tier:"empirical",variant:"tabular",source:"USGS",agency:"spec",vintage:"spec",title:"Small table of observations",columns:["id","value","dist."],rows:[["ROW-001","1.2 m","0.18 mi"],["ROW-002","0.9 m","0.32 mi"],["ROW-003","0.7 m","0.41 mi"]],sub:"Use when 3–8 records each carry the same fields.",docId:"DS-TABULAR"},{id:"grm-scalars",stone:"touchstone",tier:"empirical",variant:"scalars",source:"NWS",agency:"spec",vintage:"spec",title:"Trio of scalar readings",scalars:[{value:"0.02 in",label:"precip · 24h"},{value:"11 mph",label:"wind"},{value:"63°F",label:"temp"}],sub:"Use for current-state dashboards.",docId:"DS-SCALARS"},{id:"grm-spark",stone:"touchstone",tier:"empirical",variant:"spark",source:"FloodNet",agency:"spec",vintage:"spec",title:"Sparkline of recent events",headline:"n events",subhead:"window · peak",spark:[1,2,4,3,7,12,8,5,3,2,4,9,6],docId:"DS-SPARK"},{id:"grm-histogram",stone:"touchstone",tier:"proxy",variant:"histogram",source:"NYC 311",agency:"spec",vintage:"spec",title:"Histogram of binned counts",headline:"n calls",subhead:"window · seasonal note",histogram:[3,2,1,0,1,4,7,12,18,11,5,3,4,2,1,0,2,3,8,9,4,2,1,0],docId:"DS-HIST"},{id:"grm-timeseries",stone:"lodestone",tier:"modeled",variant:"timeseries",source:"Granite TTM",agency:"spec",vintage:"spec",title:"Forecast curve with horizon",headline:"+0.41 m peak",subhead:"+38h · 90% CI",timeseries:{hours:96,peak:{x:38,y:41},peakLabel:"+0.41 m"},spatialNote:"regional",sub:"Spatial-index callout when station ≠ point-of-query.",docId:"DS-TS"},{id:"grm-forecast",stone:"lodestone",tier:"modeled",variant:"forecast",source:"NPCC4",agency:"spec",vintage:"spec",title:"Long-horizon scenario projections",forecast:[{year:2030,low:4,mid:6,high:9},{year:2050,low:13,mid:22,high:30},{year:2100,low:38,mid:71,high:114}],sub:"Use for decadal+ uncertainty cones.",docId:"DS-FCST"},{id:"grm-raster",stone:"cornerstone",tier:"modeled",variant:"raster",source:"NYC DEP",agency:"spec",vintage:"spec",title:"Raster snapshot, mapped layer",rasterKind:"stormwater",headline:"ponding",subhead:"scenario · pixel summary",sub:"Use for any 2D model output.",docId:"DS-RASTER"},{id:"grm-rasterpred",stone:"touchstone",tier:"modeled",variant:"raster-pred",source:"Prithvi-NYC",agency:"spec",vintage:"spec",title:"Raster prediction, illustrative",rasterKind:"prithvi",headline:"n% flooded",subhead:"model · scene id",illustrative:!0,sub:"Same chrome as raster + illustrative tag.",docId:"DS-RASTERPRED"},{id:"grm-register",stone:"keystone",tier:"empirical",variant:"register",source:"NYC OpenData",agency:"spec",vintage:"spec",title:"Composite register list",registers:[{reg:"MTA",tier:"empirical",label:"Station entrance",detail:"0.18 mi · 5",sourceId:"MTA-X",note:null},{reg:"NYCHA",tier:"empirical",label:"Development",detail:"0.41 mi · 2,878 res.",sourceId:"NYCHA-Y",note:null},{reg:"DOH",tier:"empirical",label:null,detail:null,sourceId:null,note:"no acute-care hospital within 1.0 mi"}],sub:"Use when many specialists join into one Stone.",docId:"DS-REGISTER"},{id:"grm-comparison",stone:"keystone",tier:"synthetic",variant:"comparison",source:"EMP × SYN",agency:"spec",vintage:"spec",title:"Documented vs. interpreted",left:{tier:"empirical",label:"documented",value:"31.4%",aux:"n polygons"},right:{tier:"synthetic",label:"interpreted",value:"29.8%",aux:"n polygons"},delta:"Δ = −1.6 pp · agreement strong",sub:"Use to surface model–ground-truth deltas.",docId:"DS-CMP"},{id:"grm-meta",stone:"capstone",tier:"modeled",variant:"meta",source:"Mellea",agency:"spec",vintage:"spec",title:"Capstone reconciliation",metaRows:[{k:"claims",v:"12 / 12 grounded"},{k:"tier mix",v:"EMP 5 · MOD 4 · PRX 2 · SYN 1"},{k:"tier-1 freshness",v:"median 38 d"},{k:"warnings",v:"0"}],sub:"Use to expose the synthesis layer's audit.",docId:"DS-META"}];var M=_r(),i=r(M),g=n(r(i),2),d=r(g);t(g),t(i);var x=n(i,2);te(x,21,()=>m,h=>h.id,(h,k)=>{Te(h,{get card(){return a(k)},get density(){return S()}})}),t(x),t(M),C(()=>f(d,`${m.length??""} variants`)),c(R,M)}var pr=p('<section class="findings svelte-ci42t5" aria-label="Findings, grouped by Stone"><header class="findings-head svelte-ci42t5"><h2 class="findings-h2 svelte-ci42t5">Findings · grouped by Stone</h2> <span class="findings-tagline svelte-ci42t5">cards = what each Stone found · provenance collapses below</span></header> <!> <!> <!></section>');function Er(R,e){X(e,!0);let S=ie(e,"density",3,"comfortable"),m=ie(e,"provenanceMode",3,"smart"),M=ie(e,"showGrammar",3,!1),i=ie(e,"linkedKey",3,null),g=q(()=>{const s={cornerstone:[],keystone:[],touchstone:[],lodestone:[],capstone:[]};for(const l of e.data.cards)s[l.stone].push(l);return s}),d=q(()=>{const s={cornerstone:{key:"cornerstone",members:[]},keystone:{key:"keystone",members:[]},touchstone:{key:"touchstone",members:[]},lodestone:{key:"lodestone",members:[]},capstone:{key:"capstone",members:[]}};for(const l of e.data.stones)s[l.key]=l;return s});var x=pr(),h=n(r(x),2);Nt(h,{get cards(){return e.data.cards},get stones(){return e.data.stones},get wallSeconds(){return e.data.wallSeconds},get cacheHit(){return e.data.cacheHit}});var k=n(h,2);te(k,16,()=>Be,s=>s,(s,l)=>{fr(s,{get stone(){return l},get cards(){return a(g)[l]},get trace(){return a(d)[l]},get density(){return S()},get provenanceMode(){return m()},get linkedKey(){return i()},get onCite(){return e.onCite},get onLink(){return e.onLink}})});var y=n(k,2);{var o=s=>{yr(s,{get density(){return S()}})};A(y,s=>{M()&&s(o)})}t(x),c(R,x),J()}const xr={cornerstone:[{id:"CORN-001",name:"sandy_inundation.lookup",stepNames:["sandy_inundation","sandy_nta"],tier:"empirical",skipReason:"Sandy 2012 inundation: query outside NYC bounds"},{id:"CORN-002",name:"dep_stormwater.lookup",stepNames:["dep_stormwater","dep_extreme_2080_nta","dep_moderate_2050_nta","dep_moderate_current_nta"],tier:"modeled",skipReason:"NYC DEP stormwater scenarios: query outside NYC bounds"},{id:"CORN-003",name:"usgs_hwm.spatial_join",stepNames:["ida_hwm_2021"],tier:"empirical",skipReason:"USGS Ida HWMs: no marks within 800 m of address"},{id:"CORN-004",name:"prithvi_water.lookup",stepNames:["prithvi_eo_v2"],tier:"modeled",skipReason:"Prithvi-EO Ida polygons: no polygons within 500 m"},{id:"CORN-005",name:"microtopo.dem_hand_twi",stepNames:["microtopo_lidar","microtopo_nta"],tier:"proxy",skipReason:"USGS 3DEP DEM: query outside NYC raster coverage"}],keystone:[{id:"KEY-001",name:"mta_entrance_exposure",stepNames:["mta_entrance_exposure"],tier:"empirical",skipReason:"no entrances within radius"},{id:"KEY-002",name:"nycha.development_join",stepNames:["nycha_development_exposure"],tier:"empirical",skipReason:"no NYCHA developments within 1.0 mi"},{id:"KEY-003",name:"doe.school_join",stepNames:["doe_school_exposure"],tier:"empirical",skipReason:"no DOE schools within 1.0 mi"},{id:"KEY-004",name:"doh.facility_join",stepNames:["doh_hospital_exposure"],tier:"empirical",skipReason:"no acute-care hospitals within 1.0 mi"},{id:"KEY-005",name:"pluto.lot_lookup",stepNames:["pluto_lookup"],tier:"empirical",skipReason:"PLUTO join skipped: queried address not in NYC PLUTO dataset"},{id:"KEY-006",name:"terramind.buildings",stepNames:["terramind_buildings","terramind_synthesis"],tier:"modeled",skipReason:"TerraMind Buildings adapter: heavy specialist disabled (RIPRAP_HEAVY_SPECIALISTS=0)"}],touchstone:[{id:"TCH-001",name:"floodnet.history",stepNames:["floodnet"],tier:"empirical",skipReason:"FloodNet sensor: no deployments within 600 m"},{id:"TCH-002",name:"nyc311.flood_complaints",stepNames:["nyc311","nyc311_nta"],tier:"proxy",skipReason:"NYC 311: no flood-relevant complaints within 200 m"},{id:"TCH-003",name:"nws_obs.metar",stepNames:["nws_obs"],tier:"empirical",skipReason:"NWS hourly METAR: nearest ASOS reports no precipitation"},{id:"TCH-004",name:"noaa_coops.recent",stepNames:["noaa_tides"],tier:"empirical",skipReason:"NOAA tide gauge: nearest station >25 km from address"},{id:"TCH-005",name:"prithvi_nyc_pluvial",stepNames:["prithvi_eo_live"],tier:"modeled",skipReason:"Prithvi-NYC-Pluvial: live segmentation specialist disabled or no <30% cloud Sentinel-2 in last 120 d"},{id:"TCH-006",name:"terramind.lulc",stepNames:["terramind_lulc"],tier:"synthetic",skipReason:"TerraMind LULC adapter: heavy specialist disabled or eo_chip fetch silent"}],lodestone:[{id:"LOD-001",name:"nws_alerts.flood_relevant",stepNames:["nws_alerts"],tier:"modeled",skipReason:"NWS public alerts: no active flood-relevant alerts at this address"},{id:"LOD-002",name:"ttm_battery_surge.zero_shot",stepNames:["ttm_forecast"],tier:"modeled",skipReason:"Granite TTM r2 zero-shot: forecast not interesting (peak |residual| < 0.3 ft)"},{id:"LOD-003",name:"ttm_battery_surge.fine_tune",stepNames:["ttm_battery_surge"],tier:"modeled",skipReason:"Granite TTM Battery fine-tune: forecast not interesting (peak |residual| < 0.3 m)"},{id:"LOD-004",name:"ttm_311_forecast",stepNames:["ttm_311_forecast"],tier:"modeled",skipReason:"NYC 311 weekly forecast: no per-address history to extrapolate"},{id:"LOD-005",name:"floodnet_forecast",stepNames:["floodnet_forecast"],tier:"modeled",skipReason:"FloodNet sensor recurrence: sensor has < silent-floor historical events; forecast omitted"},{id:"LOD-006",name:"npcc4.slr_projection",stepNames:["npcc4_projection"],tier:"modeled",skipReason:"NPCC4 SLR projection: not yet wired into FSM (static reference card on hold)"}],capstone:[{id:"CAP-001",name:"rag.granite_embedding",stepNames:["rag_granite_embedding"],tier:"proxy",skipReason:"Granite Embedding RAG: no policy retrieval (out-of-NYC scope)"},{id:"CAP-002",name:"gliner.typed_extraction",stepNames:["gliner_extract"],tier:"proxy",skipReason:"GLiNER typed extraction: no RAG hits to extract over"},{id:"CAP-003",name:"granite41.compose_briefing",stepNames:["reconcile_granite41","mellea_reconcile_address","reconcile_neighborhood","reconcile_development","reconcile_live_now"],tier:"modeled",skipReason:"Reconciler did not run (no grounded data available)"},{id:"CAP-004",name:"mellea.grounding_check",stepNames:["mellea_grounding"],tier:"modeled",skipReason:"Mellea grounding-check: rolled into reconcile step on this run"}]};function Pr(R,e){const S=xr[R]??[],m=new Map;for(const g of e)m.set(g.name,g);const M=[],i=new Set;for(const g of S){let d;for(const x of g.stepNames){const h=m.get(x);if(h){d=h,i.add(x);break}}d?M.push({...d,id:g.id,name:g.name,tier:d.tier??g.tier??null}):M.push({id:g.id,name:g.name,status:"not_invoked",tier:g.tier??null,note:g.skipReason})}for(const g of e)i.has(g.name)||M.push(g);return M}export{Lr as C,Er as F,Fr as M,Rr as R,Pr as f};
|
web/sveltekit/build/_app/immutable/chunks/Bm3kUygK.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
| 1 |
-
import{k as Ie,o as De,a as v,f as p,s as f,t as ye,d as Ce,c as xe,e as Ne,b as _e}from"./CWw6qgC_.js";import{h as ve,n as Be,j as we,bd as Oe,d as ze,a3 as He,aW as Ye,b7 as je,k as We,b as Ue,e as Re,i as ke,a0 as Ke,av as Ge,p as X,t as C,a as J,s as i,c as r,r as t,aR as re,o as a,al as q,am as ce,ai as Qe,be as Ve,a5 as pe,a4 as Se,f as ee}from"./BTUA7_xE.js";import{B as Ze,i as A}from"./Bd-v_9Ud.js";import{e as te,i as oe}from"./25_y8TFd.js";import{s as m,a as ue,b as le,c as Xe,C as Je}from"./B0XoTt7U.js";import{T as ge,c as $e,b as et,d as Le}from"./BatqQaKj.js";import{b as tt,_ as at}from"./CXQd8Y6F.js";import{p as ie}from"./CW0zSL4D.js";import{P as rt}from"./D907np-5.js";function st(L,e,S,_,M,n){let u=ve;ve&&Be();var d=null;ve&&we.nodeType===Oe&&(d=we,Be());var x=ve?we:L,h=new Ze(x,!1);ze(()=>{const w=e()||null;var y=w==="svg"?je:void 0;if(w===null){h.ensure(null,null);return}return h.ensure(w,o=>{if(w){if(d=ve?d:Ye(w,y),Ie(d,d),_){ve&&De(w)&&d.append(document.createComment(""));var s=ve?We(d):d.appendChild(Ue());ve&&(s===null?Re(!1):ke(s)),_(d,s)}Ke.nodes.end=d,o.before(d)}ve&&ke(o)}),()=>{}},He),Ge(()=>{}),u&&(Re(!0),ke(x))}var it=p('<a target="_blank" rel="noopener noreferrer"> </a>'),nt=p('<li><span class="citation-num"> </span> <div class="citation-body"><div class="citation-line-1"><!> <span class="citation-source"> </span> <span class="citation-vintage"> </span></div> <div class="citation-title"><!></div> <div class="citation-meta"><span class="citation-docid"> </span> <span class="citation-retrieved"> </span></div></div></li>'),lt=p(`<aside class="citation-drawer svelte-1p339fd" aria-label="Citations"><div class="citation-drawer-head"><span class="section-label"> </span> <span class="citation-drawer-meta">live · primary sources</span></div> <ol class="citation-list"></ol> <div class="citation-drawer-foot"><span class="section-label">Trust signals</span> <p class="citation-foot-copy">All foundation models Apache-2.0. All data from public-record federal,
|
| 2 |
-
state, and city sources. No commercial APIs contacted at runtime.</p></div></aside>`);function Rr(L,e){X(e,!0);let S=q(()=>Object.values(e.citations).sort((x,h)=>x.n-h.n));var _=lt(),M=r(_),n=r(M),u=r(n);t(n),re(2),t(M);var d=i(M,2);te(d,21,()=>a(S),x=>x.id,(x,h)=>{var w=nt();let y;var o=r(w),s=r(o);t(o);var l=i(o,2),b=r(l),N=r(b);ge(N,{get tier(){return a(h).tier},size:10,get color(){return`var(--tier-${a(h).tier??""})`}});var g=i(N,2),c=r(g,!0);t(g);var k=i(g,2),R=r(k);t(k),t(b);var P=i(b,2),D=r(P);{var j=E=>{var Y=it(),G=r(Y,!0);t(Y),C(()=>{m(Y,"href",a(h).url),f(G,a(h).title)}),v(E,Y)},I=q(()=>a(h).url&&a(h).url.startsWith("http")),O=E=>{var Y=ye();C(()=>f(Y,a(h).title)),v(E,Y)};A(D,E=>{a(I)?E(j):E(O,-1)})}t(P);var z=i(P,2),U=r(z),T=r(U,!0);t(U);var F=i(U,2),B=r(F);t(F),t(z),t(l),t(w),C(()=>{m(w,"id",`cite-${a(h).id??""}`),y=ue(w,1,"citation-item",null,y,{"is-active":$e.active===a(h).id}),f(s,`[${a(h).n??""}]`),f(c,a(h).source),f(R,`v. ${a(h).vintage??""}`),f(T,a(h).docId),f(B,`retr. ${a(h).retrieved??""}`)}),v(x,w)}),t(d),re(2),t(_),C(()=>f(u,`Citations · ${a(S).length??""}`)),v(L,_),J()}const Ee=`<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
|
| 3 |
-
<rect width="12" height="12" fill="rgba(42,111,168,0.18)"/>
|
| 4 |
-
<g stroke="#2A6FA8" stroke-width="1.4">
|
| 5 |
-
<line x1="-2" y1="2" x2="14" y2="-14"/>
|
| 6 |
-
<line x1="-2" y1="8" x2="14" y2="-8"/>
|
| 7 |
-
<line x1="-2" y1="14" x2="14" y2="-2"/>
|
| 8 |
-
<line x1="-2" y1="20" x2="14" y2="4"/>
|
| 9 |
-
</g>
|
| 10 |
-
</svg>`,ot=`<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
|
| 11 |
-
<rect width="12" height="12" fill="rgba(42,111,168,0.16)"/>
|
| 12 |
-
<g stroke="#2A6FA8" stroke-width="1.1">
|
| 13 |
-
<line x1="-2" y1="6" x2="14" y2="-10"/>
|
| 14 |
-
<line x1="-2" y1="14" x2="14" y2="-2"/>
|
| 15 |
-
<line x1="-2" y1="22" x2="14" y2="6"/>
|
| 16 |
-
</g>
|
| 17 |
-
</svg>`;async function dt(L,e){const S=new Blob([L],{type:"image/svg+xml"}),_=URL.createObjectURL(S);try{return await new Promise((n,u)=>{const d=new Image(e,e);d.onload=()=>n(d),d.onerror=x=>u(x),d.src=_})}finally{URL.revokeObjectURL(_)}}async function vt(L){const e=[["syn-stripe-45",Ee,12],["syn-stripe-45-2x",Ee,24],["syn-stripe-45-low",ot,12]];for(const[S,_,M]of e)if(!L.hasImage(S))try{const n=await dt(_,M);L.addImage(S,n,{pixelRatio:M/12})}catch(n){console.warn(`syn-stripe registration failed for ${S}`,n)}}var ct=p('<span class="link-badge svelte-wk2bu4" aria-hidden="true"> </span>'),ut=p('<div class="map-frame svelte-wk2bu4"><div role="application" class="rip-map-container svelte-wk2bu4"></div> <!></div>');function Lr(L,e){X(e,!0);let S=ie(e,"activeLayers",19,()=>({empirical:!0,modeled:!0,synthetic:!0,proxy:!0})),_=ie(e,"linkedKey",3,null),M=Se(null),n=null,u=Se(!1);const d={type:"FeatureCollection",features:[]};function x(l,b){if(!n||!a(u))return;const N=n.getSource(l);N&&N.setData(b??d)}function h(l,b){!n||!a(u)||n.getLayer(l)&&n.setLayoutProperty(l,"visibility",b?"visible":"none")}ce(()=>{x("sandy-empirical",e.sandyEmpirical)}),ce(()=>{x("dep-modeled",e.depModeled)}),ce(()=>{x("syn-prior",e.syntheticPrior)}),ce(()=>{x("proxy-311",e.proxy311)}),ce(()=>{x("register-points",e.registerPoints)}),ce(()=>{x("register-polygons",e.registerPolygons)}),ce(()=>{h("tier-empirical-fill",S().empirical),h("tier-empirical-line",S().empirical),h("tier-modeled-fill",S().modeled),h("tier-modeled-line",S().modeled),h("tier-synthetic-fill",S().synthetic),h("tier-synthetic-line",S().synthetic),h("tier-proxy-dots",S().proxy)}),ce(()=>{!n||!a(u)||n.flyTo({center:[e.address.lon,e.address.lat],zoom:15,essential:!0})}),Qe(async()=>{if(!a(M))return;const l=await at(()=>import("./D4L2lGt1.js").then(b=>b.m),[],import.meta.url);n=new l.Map({container:a(M),style:rt,center:[e.address.lon,e.address.lat],zoom:15,attributionControl:{compact:!0}}),n.addControl(new l.NavigationControl({visualizePitch:!1}),"top-right"),n.addControl(new l.ScaleControl({maxWidth:100,unit:"imperial"}),"bottom-left"),n.on("load",()=>{if(!n)return;window.__riprapMap=n,vt(n);const b=()=>({type:"FeatureCollection",features:[]});n.addSource("sandy-empirical",{type:"geojson",data:e.sandyEmpirical??b()}),n.addSource("dep-modeled",{type:"geojson",data:e.depModeled??b()}),n.addSource("syn-prior",{type:"geojson",data:e.syntheticPrior??b()}),n.addSource("proxy-311",{type:"geojson",data:e.proxy311??b()}),n.addSource("register-points",{type:"geojson",data:e.registerPoints??b()}),n.addSource("register-polygons",{type:"geojson",data:e.registerPolygons??b()}),n.addSource("queried-address",{type:"geojson",data:{type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"Point",coordinates:[e.address.lon,e.address.lat]},properties:{label:e.address.label}}]}}),n.addLayer({id:"tier-empirical-fill",type:"fill",source:"sandy-empirical",paint:{"fill-color":"#0B5394","fill-opacity":.4}}),n.addLayer({id:"tier-empirical-line",type:"line",source:"sandy-empirical",paint:{"line-color":"#0B5394","line-width":1.5}}),n.addLayer({id:"tier-modeled-fill",type:"fill",source:"dep-modeled",paint:{"fill-color":"#2A6FA8","fill-opacity":.25}}),n.addLayer({id:"tier-modeled-line",type:"line",source:"dep-modeled",paint:{"line-color":"#2A6FA8","line-width":1.5}}),n.addLayer({id:"tier-synthetic-fill",type:"fill",source:"syn-prior",paint:{"fill-pattern":"syn-stripe-45","fill-opacity":.65}}),n.addLayer({id:"tier-synthetic-line",type:"line",source:"syn-prior",paint:{"line-color":"#2A6FA8","line-width":1.5,"line-dasharray":[4,3]}}),n.addLayer({id:"tier-proxy-dots",type:"circle",source:"proxy-311",paint:{"circle-color":"transparent","circle-stroke-color":"#6B6B6B","circle-stroke-width":1.25,"circle-radius":["interpolate",["linear"],["coalesce",["get","count"],1],1,3,5,6,15,9,30,12]}}),n.addLayer({id:"register-polygons-fill",type:"fill",source:"register-polygons",paint:{"fill-color":"#0B5394","fill-opacity":["interpolate",["linear"],["coalesce",["get","pct_inside_sandy"],0],0,.1,25,.2,50,.32,75,.45]}}),n.addLayer({id:"register-polygons-line",type:"line",source:"register-polygons",paint:{"line-color":"#0B5394","line-width":1,"line-opacity":.85}}),n.addLayer({id:"register-points-circle",type:"circle",source:"register-points",paint:{"circle-color":["case",["==",["get","inside_sandy_2012"],!0],"#0B5394","#6B6B6B"],"circle-stroke-color":"#F4F6F9","circle-stroke-width":1.25,"circle-radius":["match",["get","kind"],"subway",4,"school",5,"hospital",6,"nycha",7,4],"circle-opacity":.9}}),n.on("mouseenter","register-points-circle",()=>{n&&(n.getCanvas().style.cursor="pointer")}),n.on("mouseleave","register-points-circle",()=>{n&&(n.getCanvas().style.cursor="")}),n.on("click","register-points-circle",N=>{var z;if(!n||!((z=N.features)!=null&&z.length))return;const g=N.features[0],c=g.properties??{},k=String(c.name??"?"),R=String(c.kind??"?"),P=c.inside_sandy_2012===!0||c.inside_sandy_2012==="true",D=String(c.doc_id??""),j=`
|
| 18 |
-
<div style="font-family: 'IBM Plex Sans', system-ui; font-size: 12px;">
|
| 19 |
-
<div style="font-weight: 600; color: #0F172A;">${k}</div>
|
| 20 |
-
<div style="color: #6B6B6B; font-size: 11px; margin-top: 2px;">${R}</div>
|
| 21 |
-
<div style="margin-top: 6px;">
|
| 22 |
-
<span style="font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: ${P?"#0B5394":"#6B6B6B"};">
|
| 23 |
-
inside_sandy_2012=${P}
|
| 24 |
-
</span>
|
| 25 |
-
</div>
|
| 26 |
-
${D?`<div style="margin-top: 4px; font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; color: #005EA2;">[${D}]</div>`:""}
|
| 27 |
-
</div>`,I=new l.Popup({closeButton:!0,offset:12}),O=g.geometry.coordinates;I.setLngLat(O).setHTML(j).addTo(n)}),n.addLayer({id:"queried-halo",type:"circle",source:"queried-address",paint:{"circle-color":"rgba(209, 124, 0, 0.20)","circle-radius":16}}),n.addLayer({id:"queried-pin",type:"circle",source:"queried-address",paint:{"circle-color":"#005EA2","circle-stroke-color":"#F4F6F9","circle-stroke-width":2,"circle-radius":7}}),n.addLayer({id:"queried-label",type:"symbol",source:"queried-address",layout:{"text-field":["get","label"],"text-font":["Open Sans Semibold","Arial Unicode MS Bold"],"text-size":12,"text-offset":[0,-1.6],"text-anchor":"bottom"},paint:{"text-color":"#0F172A","text-halo-color":"#F4F6F9","text-halo-width":1.5}}),pe(u,!0)})}),Ve(()=>{n==null||n.remove(),n=null});var w=ut(),y=r(w);tt(y,l=>pe(M,l),()=>a(M));var o=i(y,2);{var s=l=>{var b=ct(),N=r(b);t(b),C(()=>f(N,`linked: ${_()??""}`)),v(l,b)};A(o,l=>{_()&&l(s)})}t(w),C(()=>{m(w,"data-linked",_()??""),m(y,"aria-label",`Flood-exposure map for ${e.address.label??""}`)}),v(L,w),J()}const Ae=["cornerstone","keystone","touchstone","lodestone","capstone"],Me={cornerstone:{name:"Cornerstone",role:"the hazard reader",tag:"what NYC's ground remembers"},keystone:{name:"Keystone",role:"the asset register",tag:"what's exposed"},touchstone:{name:"Touchstone",role:"the live observer",tag:"what's happening now"},lodestone:{name:"Lodestone",role:"the projector",tag:"what's coming"},capstone:{name:"Capstone",role:"the synthesizer",tag:"writes it all down with citations"}};var gt=p('<span class="layers-count svelte-1g2dety"> </span>'),ht=p('<li class="layers-row layers-row-empty svelte-1g2dety"><span class="layers-empty-text svelte-1g2dety">no map layers — see Findings cards</span></li>'),_t=p('<li class="layers-row layers-row-empty svelte-1g2dety"><span class="layers-empty-text svelte-1g2dety">not a map layer</span></li>'),ft=p('<span class="layers-state-dim svelte-1g2dety" title="Not yet wired to map source">off · catalog</span>'),mt=p('<li><span class="layers-glyph svelte-1g2dety" aria-hidden="true"><!></span> <span class="layers-text svelte-1g2dety"><span class="layers-label svelte-1g2dety"> </span> <span class="layers-meta svelte-1g2dety"> <!></span></span> <span class="layers-state svelte-1g2dety"><!></span></li>'),yt=p('<details open=""><summary class="svelte-1g2dety"><span class="layers-caret svelte-1g2dety" aria-hidden="true">▾</span> <span class="layers-stone-name svelte-1g2dety"> </span> <span class="layers-stone-tag svelte-1g2dety"> </span> <!></summary> <ul class="layers-list svelte-1g2dety"><!></ul></details>'),pt=p('<button type="button"><!> <span> </span> <span class="layers-master-state svelte-1g2dety"> </span></button>'),xt=p('<aside class="layers-panel svelte-1g2dety" aria-label="Map layers grouped by Stone"><div class="layers-head svelte-1g2dety"><span class="section-label">Layers · grouped by Stone</span></div> <!> <div class="layers-masters svelte-1g2dety" role="group" aria-label="Master tier toggles"><span class="section-label">Tier toggles</span> <div class="layers-master-row svelte-1g2dety"></div></div></aside>');function Er(L,e){X(e,!0);const S={cornerstone:[{label:"Sandy Inundation Zone (2012)",source:"NYC OEM",tier:"empirical",wired:!0},{label:"FEMA / DEP scenarios",source:"FEMA · NYC DEP",tier:"modeled",wired:!0},{label:"Ida HWM points (2021)",source:"USGS STN",tier:"empirical",wired:!1},{label:"Microtopography (HAND/TWI)",source:"USGS 3DEP",tier:"proxy",wired:!1}],keystone:[{label:"MTA subway entrances",source:"MTA Open Data",tier:"empirical",wired:!0},{label:"NYCHA developments",source:"NYC OD phvi-damg",tier:"empirical",wired:!0},{label:"DOE schools",source:"NYC DOE Locations",tier:"empirical",wired:!0},{label:"DOH hospitals",source:"NYS DOH vn5v-hh5r",tier:"empirical",wired:!0},{label:"TerraMind Buildings (current)",source:"msradam/TerraMind-NYC-Adapters",tier:"synthetic",wired:!1}],touchstone:[{label:"311 flood complaints",source:"NYC 311",tier:"proxy",wired:!0},{label:"FloodNet sensors",source:"FloodNet NYC",tier:"empirical",wired:!1},{label:"TerraMind LULC (current)",source:"msradam/TerraMind-NYC-Adapters",tier:"synthetic",wired:!1},{label:"Prithvi-NYC-Pluvial flood pred.",source:"msradam/Prithvi-EO-2.0-NYC-Pluvial",tier:"modeled",wired:!1}],lodestone:[],capstone:[]};function _(w){return!!e.active[w.tier]}function M(w){return S[w].length}const n=[{k:"empirical",tier:"empirical",label:"EMP"},{k:"modeled",tier:"modeled",label:"MOD"},{k:"proxy",tier:"proxy",label:"PRX"},{k:"synthetic",tier:"synthetic",label:"SYN"}];var u=xt(),d=i(r(u),2);te(d,16,()=>Ae,w=>w,(w,y)=>{var o=yt(),s=r(o),l=i(r(s),2),b=r(l,!0);t(l);var N=i(l,2),g=r(N);t(N);var c=i(N,2);{var k=z=>{var U=gt(),T=r(U,!0);t(U),C(F=>f(T,F),[()=>M(y)]),v(z,U)},R=q(()=>M(y)>0);A(c,z=>{a(R)&&z(k)})}t(s);var P=i(s,2),D=r(P);{var j=z=>{var U=ht();v(z,U)},I=z=>{var U=_t();v(z,U)},O=z=>{var U=xe(),T=ee(U);te(T,17,()=>S[y],oe,(F,B)=>{var E=mt();let Y;var G=r(E),ae=r(G);ge(ae,{get tier(){return a(B).tier},size:11,get color(){return`var(--tier-${a(B).tier??""})`}}),t(G);var Q=i(G,2),Z=r(Q),ne=r(Z,!0);t(Z);var H=i(Z,2),V=r(H),K=i(V);et(K,{get tier(){return a(B).tier},compact:!0}),t(H),t(Q);var W=i(Q,2),$=r(W);{var de=se=>{var me=ft();v(se,me)},fe=se=>{var me=ye("on");v(se,me)},be=q(()=>_(a(B))),he=se=>{var me=ye("off");v(se,me)};A($,se=>{a(B).wired?a(be)?se(fe,1):se(he,-1):se(de)})}t(W),t(E),C(()=>{Y=ue(E,1,"layers-row svelte-1g2dety",null,Y,{dim:!a(B).wired}),f(ne,a(B).label),f(V,`${a(B).source??""} · `)}),v(F,E)}),v(z,U)};A(D,z=>{y==="lodestone"?z(j):y==="capstone"?z(I,1):z(O,-1)})}t(P),t(o),C(()=>{ue(o,1,`layers-group region-${y??""}`,"svelte-1g2dety"),f(b,Me[y].name),f(g,`— ${Me[y].tag??""}`)}),v(w,o)});var x=i(d,2),h=i(r(x),2);te(h,21,()=>n,w=>w.k,(w,y)=>{var o=pt();let s;var l=r(o);ge(l,{get tier(){return a(y).tier},size:11,get color(){return`var(--tier-${a(y).tier??""})`}});var b=i(l,2),N=r(b,!0);t(b);var g=i(b,2),c=r(g,!0);t(g),t(o),C(()=>{s=ue(o,1,"layers-master svelte-1g2dety",null,s,{"is-on":e.active[a(y).k]}),m(o,"aria-pressed",e.active[a(y).k]),f(N,a(y).label),f(c,e.active[a(y).k]?"ON":"OFF")}),Ne("click",o,()=>e.onToggle(a(y).k)),v(w,o)}),t(h),t(x),t(u),v(L,u),J()}Ce(["click"]);var bt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-silent svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> silent</span>',1),wt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-warn svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> warned</span>',1),kt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-err svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> errored</span>',1),St=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-notinvoked svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> not invoked</span>',1),Mt=p('<span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> cache</span>',1),Ct=p('<div class="rh svelte-1vuwkv4"><span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> Stones</span> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> fired</span> <!> <!> <!> <!> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> </span> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> wall-clock</span> <!> <span class="rh-sep svelte-1vuwkv4">·</span> <span class="rh-item rh-total svelte-1vuwkv4"><strong class="svelte-1vuwkv4"> </strong> registered</span></div>');function Nt(L,e){X(e,!0);function S(H){return H.flatMap(V=>V.children?[V,...S(V.children)]:[V])}let _=q(()=>e.stones.flatMap(H=>S(H.members))),M=q(()=>a(_).length),n=q(()=>a(_).filter(H=>H.status==="fired"||H.status==="warned").length),u=q(()=>a(_).filter(H=>H.status==="silent_by_design").length),d=q(()=>a(_).filter(H=>H.status==="warned").length),x=q(()=>a(_).filter(H=>H.status==="errored").length),h=q(()=>a(_).filter(H=>H.status==="not_invoked").length),w=q(()=>e.wallSeconds==null?"—":e.wallSeconds<1?`${Math.round(e.wallSeconds*1e3)}ms`:`${e.wallSeconds.toFixed(1)}s`);var y=Ct(),o=r(y),s=r(o),l=r(s,!0);t(s),re(),t(o);var b=i(o,4),N=r(b),g=r(N,!0);t(N),re(),t(b);var c=i(b,2);{var k=H=>{var V=bt(),K=i(ee(V),2),W=r(K),$=r(W,!0);t(W),re(),t(K),C(()=>f($,a(u))),v(H,V)};A(c,H=>{a(u)>0&&H(k)})}var R=i(c,2);{var P=H=>{var V=wt(),K=i(ee(V),2),W=r(K),$=r(W,!0);t(W),re(),t(K),C(()=>f($,a(d))),v(H,V)};A(R,H=>{a(d)>0&&H(P)})}var D=i(R,2);{var j=H=>{var V=kt(),K=i(ee(V),2),W=r(K),$=r(W,!0);t(W),re(),t(K),C(()=>f($,a(x))),v(H,V)};A(D,H=>{a(x)>0&&H(j)})}var I=i(D,2);{var O=H=>{var V=St(),K=i(ee(V),2),W=r(K),$=r(W,!0);t(W),re(),t(K),C(()=>f($,a(h))),v(H,V)};A(I,H=>{a(h)>0&&H(O)})}var z=i(I,4),U=r(z),T=r(U,!0);t(U);var F=i(U);t(z);var B=i(z,4),E=r(B),Y=r(E,!0);t(E),re(),t(B);var G=i(B,2);{var ae=H=>{var V=Mt(),K=i(ee(V),2),W=r(K),$=r(W);t(W),re(),t(K),C(de=>f($,`${de??""}%`),[()=>Math.round(e.cacheHit*100)]),v(H,V)};A(G,H=>{e.cacheHit!=null&&H(ae)})}var Q=i(G,4),Z=r(Q),ne=r(Z,!0);t(Z),re(),t(Q),t(y),C(()=>{f(l,e.stones.length),f(g,a(n)),f(T,e.cards.length),f(F,` evidence card${e.cards.length===1?"":"s"}`),f(Y,a(w)),f(ne,a(M))}),v(L,y),J()}var At=p('<div class="subhead svelte-lygj3j"> </div>'),Bt=p('<p class="body-prose svelte-lygj3j"> </p>'),Rt=p('<div class="body body-headline svelte-lygj3j"><div class="headline svelte-lygj3j"> </div> <!> <!></div>');function Lt(L,e){X(e,!0);var S=Rt(),_=r(S),M=r(_,!0);t(_);var n=i(_,2);{var u=h=>{var w=At(),y=r(w,!0);t(w),C(()=>f(y,e.card.subhead)),v(h,w)};A(n,h=>{e.card.subhead&&h(u)})}var d=i(n,2);{var x=h=>{var w=Bt(),y=r(w,!0);t(w),C(()=>f(y,e.card.body)),v(h,w)};A(d,h=>{e.card.body&&h(x)})}t(S),C(()=>{le(_,`color: var(--tier-${e.card.tier??""});`),f(M,e.card.headline??"")}),v(L,S),J()}var Et=p('<th class="svelte-1nlkuao"> </th>'),Ft=p('<td class="svelte-1nlkuao"> </td>'),Pt=p('<tr class="svelte-1nlkuao"></tr>'),Tt=p('<div class="body-sub svelte-1nlkuao"> </div>'),qt=p('<div class="body body-tabular svelte-1nlkuao"><table class="t svelte-1nlkuao"><thead><tr></tr></thead><tbody></tbody></table> <!></div>');function It(L,e){X(e,!0);var S=qt(),_=r(S),M=r(_),n=r(M);te(n,21,()=>e.card.columns??[],oe,(h,w)=>{var y=Et(),o=r(y,!0);t(y),C(()=>f(o,a(w))),v(h,y)}),t(n),t(M);var u=i(M);te(u,21,()=>e.card.rows??[],oe,(h,w)=>{var y=Pt();te(y,21,()=>a(w),oe,(o,s)=>{var l=Ft(),b=r(l,!0);t(l),C(()=>f(b,a(s))),v(o,l)}),t(y),v(h,y)}),t(u),t(_);var d=i(_,2);{var x=h=>{var w=Tt(),y=r(w,!0);t(w),C(()=>f(y,e.card.sub)),v(h,w)};A(d,h=>{e.card.sub&&h(x)})}t(S),v(L,S),J()}var Dt=p('<div class="cell svelte-stf9c8"><div class="value svelte-stf9c8"> </div> <div class="label svelte-stf9c8"> </div></div>'),Ot=p('<div class="body-sub svelte-stf9c8"> </div>'),zt=p('<div class="body body-scalars svelte-stf9c8"><div class="row svelte-stf9c8"></div> <!></div>');function Ht(L,e){X(e,!0);var S=zt(),_=r(S);te(_,21,()=>e.card.scalars??[],oe,(u,d)=>{var x=Dt(),h=r(x),w=r(h,!0);t(h);var y=i(h,2),o=r(y,!0);t(y),t(x),C(()=>{le(h,`color: var(--tier-${e.card.tier??""});`),f(w,a(d).value),f(o,a(d).label)}),v(u,x)}),t(_);var M=i(_,2);{var n=u=>{var d=Ot(),x=r(d,!0);t(d),C(()=>f(x,e.card.sub)),v(u,d)};A(M,u=>{e.card.sub&&u(n)})}t(S),v(L,S),J()}var Yt=p('<div class="headline svelte-jrppts"> </div>'),jt=p('<div class="subhead svelte-jrppts"> </div>'),Wt=_e("<rect></rect>"),Ut=p('<div class="body-sub svelte-jrppts"> </div>'),Kt=p('<div class="body-sub svelte-jrppts"> </div>'),Gt=p('<div class="body body-spark svelte-jrppts"><!> <!> <svg width="100%" preserveAspectRatio="none" aria-hidden="true" class="svelte-jrppts"></svg> <!> <!></div>');function Qt(L,e){X(e,!0);const S=240,_=38;let M=q(()=>e.card.spark??e.card.histogram??[]),n=q(()=>Math.max(...a(M),1)),u=q(()=>a(M).length),d=q(()=>Math.max(2,S/Math.max(a(u),1)-1.5));var x=Gt(),h=r(x);{var w=c=>{var k=Yt(),R=r(k,!0);t(k),C(()=>{le(k,`color: var(--tier-${e.card.tier??""});`),f(R,e.card.headline)}),v(c,k)};A(h,c=>{e.card.headline&&c(w)})}var y=i(h,2);{var o=c=>{var k=jt(),R=r(k,!0);t(k),C(()=>f(R,e.card.subhead)),v(c,k)};A(y,c=>{e.card.subhead&&c(o)})}var s=i(y,2);m(s,"viewBox","0 0 240 38"),m(s,"height",_),te(s,21,()=>a(M),oe,(c,k,R)=>{var P=Wt();C(()=>{m(P,"x",R/a(u)*S+.5),m(P,"y",_-a(k)/a(n)*_),m(P,"width",a(d)),m(P,"height",a(k)/a(n)*_),m(P,"fill",`var(--tier-${e.card.tier??""})`)}),v(c,P)}),t(s);var l=i(s,2);{var b=c=>{var k=Ut(),R=r(k,!0);t(k),C(()=>f(R,e.card.sparkSub)),v(c,k)};A(l,c=>{e.card.sparkSub&&c(b)})}var N=i(l,2);{var g=c=>{var k=Kt(),R=r(k,!0);t(k),C(()=>f(R,e.card.sub)),v(c,k)};A(N,c=>{!e.card.sparkSub&&e.card.sub&&c(g)})}t(x),v(L,x),J()}var Vt=p('<span class="headline svelte-48vbub"> </span>'),Zt=p('<span class="subhead svelte-48vbub"> </span>'),Xt=p('<span class="spatial-note svelte-48vbub"> </span>'),Jt=p("<span> </span>"),$t=p('<div class="body-sub svelte-48vbub"><!> <!></div>'),ea=p('<div class="body body-timeseries svelte-48vbub"><div class="ts-header svelte-48vbub"><!> <!></div> <svg width="100%" aria-hidden="true" class="svelte-48vbub"><line stroke="#C9C9C5" stroke-width="0.5" stroke-dasharray="2 2"></line><path fill="none" stroke-width="1.4"></path><circle r="3"></circle><text font-size="9" font-family="IBM Plex Mono" text-anchor="middle"> </text><text font-size="8" font-family="IBM Plex Mono" fill="#6B6B6B">now</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#6B6B6B"> </text></svg> <!></div>');function Fe(L,e){X(e,!0);const S=240,_=84,M=6,n=q(()=>e.card.timeseries??{hours:96,peak:{x:38,y:47},peakLabel:""}),u=q(()=>h(a(n))),d=q(()=>w(a(u),a(n))),x=q(()=>y(a(u),a(d)));function h(F){const B=[];for(let E=0;E<=F.hours;E++){const Y=6*Math.sin(E/12.42*Math.PI*2),G=38*Math.exp(-Math.pow((E-F.peak.x)/12,2));B.push({x:E,y:Y+G+4})}return B}function w(F,B){const E=Math.max(...F.map(G=>G.y),B.peak.y),Y=Math.min(...F.map(G=>G.y),-10);return{sx:G=>M+G/B.hours*(S-M*2),sy:G=>_-M-14-(G-Y)/(E-Y)*(_-M*2-14)}}function y(F,B){return F.map((E,Y)=>`${Y?"L":"M"} ${B.sx(E.x)} ${B.sy(E.y)}`).join(" ")}var o=ea(),s=r(o),l=r(s);{var b=F=>{var B=Vt(),E=r(B,!0);t(B),C(()=>{le(B,`color: var(--tier-${e.card.tier??""});`),f(E,e.card.headline)}),v(F,B)};A(l,F=>{e.card.headline&&F(b)})}var N=i(l,2);{var g=F=>{var B=Zt(),E=r(B,!0);t(B),C(()=>f(E,e.card.subhead)),v(F,B)};A(N,F=>{e.card.subhead&&F(g)})}t(s);var c=i(s,2);m(c,"viewBox","0 0 240 84"),m(c,"height",_);var k=r(c);m(k,"x1",M),m(k,"x2",S-M);var R=i(k),P=i(R),D=i(P),j=r(D,!0);t(D);var I=i(D);m(I,"x",M),m(I,"y",_-2);var O=i(I);m(O,"x",S-M),m(O,"y",_-2);var z=r(O);t(O),t(c);var U=i(c,2);{var T=F=>{var B=$t(),E=r(B);{var Y=Q=>{var Z=Xt(),ne=r(Z,!0);t(Z),C(()=>f(ne,e.card.spatialNote)),v(Q,Z)};A(E,Q=>{e.card.spatialNote&&Q(Y)})}var G=i(E,2);{var ae=Q=>{var Z=Jt(),ne=r(Z,!0);t(Z),C(()=>f(ne,e.card.sub)),v(Q,Z)};A(G,Q=>{e.card.sub&&Q(ae)})}t(B),v(F,B)};A(U,F=>{(e.card.spatialNote||e.card.sub)&&F(T)})}t(o),C((F,B,E,Y,G,ae)=>{m(k,"y1",F),m(k,"y2",B),m(R,"d",a(x)),m(R,"stroke",`var(--tier-${e.card.tier??""})`),m(P,"cx",E),m(P,"cy",Y),m(P,"fill",`var(--tier-${e.card.tier??""})`),m(D,"x",G),m(D,"y",ae),m(D,"fill",`var(--tier-${e.card.tier??""})`),f(j,a(n).peakLabel),f(z,`+${a(n).hours??""}h`)},[()=>a(d).sy(0),()=>a(d).sy(0),()=>a(d).sx(a(n).peak.x),()=>a(d).sy(a(n).peak.y),()=>a(d).sx(a(n).peak.x),()=>a(d).sy(a(n).peak.y)-6]),v(L,o),J()}var ta=p('<span class="ft-stat svelte-1y25lfh"><span class="ft-stat-k svelte-1y25lfh">RMSE</span> </span>'),aa=p('<span class="ft-stat ft-skill svelte-1y25lfh"> </span>'),ra=p('<span class="ft-badge svelte-1y25lfh" title="Trained on this hardware"> </span>'),sa=p('<a class="ft-link svelte-1y25lfh" target="_blank" rel="noopener noreferrer">Model card ↗</a>'),ia=p('<!> <div class="ft-footer svelte-1y25lfh"><!> <!> <!> <!></div>',1);function na(L,e){X(e,!0);var S=ia(),_=ee(S);Fe(_,{get card(){return e.card}});var M=i(_,2),n=r(M);{var u=s=>{var l=ta(),b=i(r(l));t(l),C(()=>f(b,` ${e.card.rmse??""}`)),v(s,l)};A(n,s=>{e.card.rmse&&s(u)})}var d=i(n,2);{var x=s=>{var l=aa(),b=r(l,!0);t(l),C(()=>f(b,e.card.skillVsPersistence)),v(s,l)};A(d,s=>{e.card.skillVsPersistence&&s(x)})}var h=i(d,2);{var w=s=>{var l=ra(),b=r(l,!0);t(l),C(()=>f(b,e.card.hardwareBadge)),v(s,l)};A(h,s=>{e.card.hardwareBadge&&s(w)})}var y=i(h,2);{var o=s=>{var l=sa();C(b=>m(l,"href",b),[()=>e.card.hfModelCard.startsWith("http")?e.card.hfModelCard:`https://${e.card.hfModelCard}`]),v(s,l)};A(y,s=>{e.card.hfModelCard&&s(o)})}t(M),v(L,S),J()}var la=_e('<circle r="2.2"></circle><text font-size="9" font-family="IBM Plex Mono" text-anchor="middle" fill="#6B6B6B"> </text>',1),oa=p('<div class="body-sub svelte-gqkhpe"> </div>'),da=p('<div class="body body-forecast svelte-gqkhpe"><svg width="100%" aria-hidden="true" class="svelte-gqkhpe"><path fill-opacity="0.18"></path><path fill="none" stroke-width="1.5"></path><!></svg> <!></div>');function va(L,e){X(e,!0);const S=240,_=88,M=6;let n=q(()=>e.card.forecast??[]),u=q(()=>a(n).map((c,k)=>M+k/Math.max(a(n).length-1,1)*(S-M*2))),d=q(()=>Math.max(...a(n).map(c=>c.high),1));function x(c){return _-M-c/a(d)*(_-M*2-12)}let h=q(()=>a(u).map((c,k)=>`${k?"L":"M"} ${c} ${x(a(n)[k].mid)}`).join(" ")),w=q(()=>{if(!a(n).length)return"";const c=a(u).map((R,P)=>`${R} ${x(a(n)[P].low)}`).join(" L "),k=[...a(u)].reverse().map((R,P)=>`${R} ${x(a(n)[a(n).length-1-P].high)}`).join(" L ");return`M ${c} L ${k} Z`});var y=da(),o=r(y);m(o,"viewBox","0 0 240 88"),m(o,"height",_);var s=r(o),l=i(s),b=i(l);te(b,17,()=>a(n),oe,(c,k,R)=>{var P=la(),D=ee(P),j=i(D);m(j,"y",_-1);var I=r(j,!0);t(j),C(O=>{m(D,"cx",a(u)[R]),m(D,"cy",O),m(D,"fill",`var(--tier-${e.card.tier??""})`),m(j,"x",a(u)[R]),f(I,a(k).year)},[()=>x(a(k).mid)]),v(c,P)}),t(o);var N=i(o,2);{var g=c=>{var k=oa(),R=r(k,!0);t(k),C(()=>f(R,e.card.sub)),v(c,k)};A(N,c=>{e.card.sub&&c(g)})}t(y),C(()=>{m(s,"d",a(w)),m(s,"fill",`var(--tier-${e.card.tier??""})`),m(l,"d",a(h)),m(l,"stroke",`var(--tier-${e.card.tier??""})`)}),v(L,y),J()}var ca=_e('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#E8ECF2"></rect><g stroke="#D9D6CC" stroke-width="0.6"><line x1="0" y1="40" y2="40"></line><line x1="0" y1="80" y2="80"></line><line x1="60" y1="0" x2="60"></line><line x1="160" y1="0" x2="160"></line></g><path d="M20 50 Q 60 38 90 56 Q 120 76 150 64 Q 180 50 180 86 Q 130 100 70 96 Q 30 92 20 76 Z" fill="rgba(42,111,168,0.32)" stroke="#2A6FA8" stroke-width="0.7"></path><path d="M40 60 Q 80 54 110 70 Q 140 84 160 78 Q 165 90 130 92 Q 80 90 50 82 Z" fill="rgba(11,83,148,0.36)" stroke="#0B5394" stroke-width="0.6"></path><circle cx="120" cy="74" r="3.2" fill="#005EA2" stroke="#F4F6F9" stroke-width="1.3"></circle><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#6B6B6B">2.13 in/hr · MOD</text></svg>'),ua=_e('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#E8ECF2"></rect><g stroke="#D9D6CC" stroke-width="0.6"><line x1="0" y1="40" y2="40"></line><line x1="0" y1="80" y2="80"></line><line x1="60" y1="0" x2="60"></line><line x1="160" y1="0" x2="160"></line></g><path d="M180 92 Q 200 88 215 96 Q 220 105 200 104 Q 185 102 180 96 Z" fill="rgba(42,111,168,0.18)" stroke="#2A6FA8" stroke-width="0.5" stroke-dasharray="2 2"></path><circle cx="120" cy="60" r="3.2" fill="#005EA2" stroke="#F4F6F9" stroke-width="1.3"></circle><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#6B6B6B">no ponding · MOD</text></svg>'),ga=_e('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><defs><pattern id="rt-s2-rgb" x="0" y="0" width="6" height="6" patternUnits="userSpaceOnUse"><rect width="6" height="6" fill="#7A8E6A"></rect><rect x="0" y="0" width="3" height="3" fill="#8D9C7A"></rect><rect x="3" y="3" width="3" height="3" fill="#69795D"></rect></pattern></defs><rect fill="url(#rt-s2-rgb)"></rect><rect x="0" y="55" height="6" fill="#A8A496"></rect><rect x="115" y="0" width="8" fill="#A8A496"></rect><ellipse cx="50" cy="92" rx="6" ry="3" fill="#2A6FA8" fill-opacity="0.65"></ellipse><text x="6" y="14" font-size="9" font-family="IBM Plex Mono" fill="#F4F6F9">PRITHVI · 0.3%</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#F4F6F9">scene 2026-05-02</text></svg>'),ha=_e('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#E8ECF2"></rect><rect x="0" y="0" width="80" height="60" fill="#C66"></rect><rect x="80" y="0" width="60" height="60" fill="#C66"></rect><rect x="140" y="0" width="100" height="38" fill="#C66"></rect><rect x="140" y="38" width="100" height="22" fill="#5B7FB4"></rect><rect x="0" y="60" width="100" height="60" fill="#C66"></rect><rect x="100" y="60" width="50" height="40" fill="#5B8A4A"></rect><rect x="150" y="60" width="50" height="60" fill="#D9C75A"></rect><rect x="200" y="60" width="40" height="60" fill="#C66"></rect><rect x="100" y="100" width="50" height="20" fill="#A89A78"></rect><text x="6" y="14" font-size="9" font-family="IBM Plex Mono" fill="#F4F6F9">LULC · TerraMind</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#F4F6F9">scene 2026-05-02</text></svg>'),_a=_e('<rect fill="rgba(42,111,168,0.55)" stroke="#2A6FA8" stroke-width="0.4"></rect>'),fa=_e('<svg width="100%" aria-hidden="true" class="svelte-1lx1psy"><rect fill="#3A3A38"></rect><!><text x="6" y="14" font-size="9" font-family="IBM Plex Mono" fill="#F4F6F9">BLDG · TerraMind</text><text font-size="8" font-family="IBM Plex Mono" text-anchor="end" fill="#F4F6F9">36.2% built</text></svg>'),ma=p('<div class="thumb-placeholder svelte-1lx1psy">raster preview</div>');function Pe(L,e){var M=xe(),n=ee(M);{var u=o=>{var s=ca();m(s,"viewBox","0 0 240 120"),m(s,"height",120);var l=r(s);m(l,"width",240),m(l,"height",120);var b=i(l),N=r(b);m(N,"x2",240);var g=i(N);m(g,"x2",240);var c=i(g);m(c,"y2",120);var k=i(c);m(k,"y2",120),t(b);var R=i(b,4);m(R,"x",234),m(R,"y",115),t(s),v(o,s)},d=o=>{var s=ua();m(s,"viewBox","0 0 240 120"),m(s,"height",120);var l=r(s);m(l,"width",240),m(l,"height",120);var b=i(l),N=r(b);m(N,"x2",240);var g=i(N);m(g,"x2",240);var c=i(g);m(c,"y2",120);var k=i(c);m(k,"y2",120),t(b);var R=i(b,3);m(R,"x",234),m(R,"y",115),t(s),v(o,s)},x=o=>{var s=ga();m(s,"viewBox","0 0 240 120"),m(s,"height",120);var l=i(r(s));m(l,"width",240),m(l,"height",120);var b=i(l);m(b,"width",240);var N=i(b);m(N,"height",120);var g=i(N,3);m(g,"x",234),m(g,"y",115),t(s),v(o,s)},h=o=>{var s=ha();m(s,"viewBox","0 0 240 120"),m(s,"height",120);var l=r(s);m(l,"width",240),m(l,"height",120);var b=i(l,11);m(b,"x",234),m(b,"y",115),t(s),v(o,s)},w=o=>{var s=fa();m(s,"viewBox","0 0 240 120"),m(s,"height",120);var l=r(s);m(l,"width",240),m(l,"height",120);var b=i(l);te(b,16,()=>[[10,10,28,18],[42,10,30,16],[78,10,40,22],[124,10,32,18],[162,10,30,18],[198,10,32,18],[10,32,28,16],[42,30,30,18],[124,32,32,16],[162,32,30,16],[198,32,32,16],[10,55,28,18],[42,55,30,18],[78,55,40,18],[124,55,32,18],[162,55,30,18],[198,55,32,18],[10,80,28,16],[42,80,30,16],[78,80,40,16],[124,80,32,16],[162,80,30,16],[10,100,28,12],[42,100,30,12],[78,100,40,12]],oe,(g,c)=>{var k=_a();C(()=>{m(k,"x",c[0]),m(k,"y",c[1]),m(k,"width",c[2]),m(k,"height",c[3])}),v(g,k)});var N=i(b,2);m(N,"x",234),m(N,"y",115),t(s),v(o,s)},y=o=>{var s=ma();v(o,s)};A(n,o=>{e.kind==="stormwater"?o(u):e.kind==="stormwater-dry"?o(d,1):e.kind==="prithvi"?o(x,2):e.kind==="lulc"?o(h,3):e.kind==="buildings"?o(w,4):o(y,-1)})}v(L,M)}var ya=p('<span class="illustrative svelte-1m43x1m" title="Illustrative rendering, not source pixels">illustrative</span>'),pa=p('<span class="svelte-1m43x1m"> </span>'),xa=p('<div class="raster-headline svelte-1m43x1m"><span class="svelte-1m43x1m"> </span> <!></div>'),ba=p('<div class="body-sub svelte-1m43x1m"> </div>'),wa=p('<div class="body body-raster svelte-1m43x1m"><div class="frame svelte-1m43x1m"><!> <!></div> <!> <!></div>');function ka(L,e){X(e,!0);var S=wa(),_=r(S),M=r(_);Pe(M,{get kind(){return e.card.rasterKind}});var n=i(M,2);{var u=y=>{var o=ya();v(y,o)};A(n,y=>{(e.card.illustrative||e.card.tier==="synthetic")&&y(u)})}t(_);var d=i(_,2);{var x=y=>{var o=xa(),s=r(o),l=r(s,!0);t(s);var b=i(s,2);{var N=g=>{var c=pa(),k=r(c);t(c),C(()=>f(k,`· ${e.card.subhead??""}`)),v(g,c)};A(b,g=>{e.card.subhead&&g(N)})}t(o),C(()=>{le(s,`color: var(--tier-${e.card.tier??""});`),f(l,e.card.headline)}),v(y,o)};A(d,y=>{e.card.headline&&y(x)})}var h=i(d,2);{var w=y=>{var o=ba(),s=r(o,!0);t(o),C(()=>f(s,e.card.sub)),v(y,o)};A(h,y=>{e.card.sub&&y(w)})}t(S),v(L,S),J()}var Sa=p('<span class="illustrative svelte-1td276x" title="Illustrative rendering, not source pixels">illustrative</span>'),Ma=p('<span class="bar-seg svelte-1td276x"></span>'),Ca=p('<li class="svelte-1td276x"><span class="swatch svelte-1td276x"></span> <span class="legend-k svelte-1td276x"> </span> <span class="legend-pct svelte-1td276x"> </span></li>'),Na=p('<div class="bar svelte-1td276x" role="img" aria-label="LULC class mix"></div> <ul class="legend svelte-1td276x"></ul>',1),Aa=p('<div class="body-sub svelte-1td276x"> </div>'),Ba=p('<div class="body body-lulc svelte-1td276x"><div class="frame svelte-1td276x"><!> <!></div> <!> <!></div>');function Ra(L,e){X(e,!0);let S=q(()=>(e.card.classMix??[]).reduce((o,s)=>o+(s.pct||0),0)||1);var _=Ba(),M=r(_),n=r(M);{let o=q(()=>e.card.rasterKind??"lulc");Pe(n,{get kind(){return a(o)}})}var u=i(n,2);{var d=o=>{var s=Sa();v(o,s)};A(u,o=>{(e.card.illustrative||e.card.tier==="synthetic")&&o(d)})}t(M);var x=i(M,2);{var h=o=>{var s=Na(),l=ee(s);te(l,21,()=>e.card.classMix,N=>N.k,(N,g)=>{var c=Ma();let k;C(()=>{m(c,"title",`${a(g).k??""}: ${a(g).pct??""}%`),k=le(c,"",k,{"flex-grow":a(g).pct/a(S),background:a(g).color})}),v(N,c)}),t(l);var b=i(l,2);te(b,21,()=>e.card.classMix,N=>N.k,(N,g)=>{var c=Ca(),k=r(c);let R;var P=i(k,2),D=r(P,!0);t(P);var j=i(P,2),I=r(j);t(j),t(c),C(()=>{R=le(k,"",R,{background:a(g).color}),f(D,a(g).k),f(I,`${a(g).pct??""}%`)}),v(N,c)}),t(b),v(o,s)};A(x,o=>{var s;(s=e.card.classMix)!=null&&s.length&&o(h)})}var w=i(x,2);{var y=o=>{var s=Aa(),l=r(s,!0);t(s),C(()=>f(l,e.card.sub)),v(o,s)};A(w,o=>{e.card.sub&&o(y)})}t(_),v(L,_),J()}var La=p('<span class="reg-label svelte-1iup6im"> </span> <span class="reg-source svelte-1iup6im"> </span>',1),Ea=p('<span class="reg-silent svelte-1iup6im"> </span>'),Fa=p('<li><span class="reg-tag svelte-1iup6im"><!> <span> </span></span> <!></li>'),Pa=p('<div class="body-sub svelte-1iup6im"> </div>'),Ta=p('<div class="body body-register svelte-1iup6im"><ul class="reg-list svelte-1iup6im"></ul> <!></div>');function qa(L,e){X(e,!0);var S=Ta(),_=r(S);te(_,21,()=>e.card.registers??[],oe,(u,d)=>{var x=Fa();let h;var w=r(x),y=r(w);ge(y,{get tier(){return a(d).tier},size:9,get color(){return`var(--tier-${a(d).tier??""})`}});var o=i(y,2),s=r(o,!0);t(o),t(w);var l=i(w,2);{var b=g=>{var c=La(),k=ee(c),R=r(k,!0);t(k);var P=i(k,2),D=r(P,!0);t(P),C(()=>{m(k,"title",a(d).detail?`${a(d).label} — ${a(d).detail}`:a(d).label),f(R,a(d).label),f(D,a(d).sourceId??"")}),v(g,c)},N=g=>{var c=Ea(),k=r(c,!0);t(c),C(()=>f(k,a(d).note)),v(g,c)};A(l,g=>{a(d).label?g(b):g(N,-1)})}t(x),C(()=>{h=ue(x,1,"reg-row svelte-1iup6im",null,h,{silent:!a(d).label}),m(w,"title",a(d).tier),f(s,a(d).reg)}),v(u,x)}),t(_);var M=i(_,2);{var n=u=>{var d=Pa(),x=r(d,!0);t(d),C(()=>f(x,e.card.sub)),v(u,d)};A(M,u=>{e.card.sub&&u(n)})}t(S),v(L,S),J()}var Ia=p('<div class="cell-aux svelte-1swqabu"> </div>'),Da=p('<div class="cell svelte-1swqabu"><div class="cell-tier svelte-1swqabu"><!> <span class="cell-label"> </span></div> <div class="cell-value svelte-1swqabu"> </div> <!></div>'),Oa=p('<div class="cell-aux svelte-1swqabu"> </div>'),za=p('<div class="cell svelte-1swqabu"><div class="cell-tier svelte-1swqabu"><!> <span class="cell-label"> </span></div> <div class="cell-value svelte-1swqabu"> </div> <!></div>'),Ha=p('<div class="cmp-delta svelte-1swqabu"> </div>'),Ya=p('<div class="body-sub svelte-1swqabu"> </div>'),ja=p('<div class="body body-comparison svelte-1swqabu"><div class="cmp-grid svelte-1swqabu"><!> <div class="divider svelte-1swqabu" aria-hidden="true">vs</div> <!></div> <!> <!></div>');function Wa(L,e){X(e,!0);var S=ja(),_=r(S),M=r(_);{var n=o=>{var s=Da(),l=r(s),b=r(l);ge(b,{get tier(){return e.card.left.tier},size:10,get color(){return`var(--tier-${e.card.left.tier??""})`}});var N=i(b,2),g=r(N,!0);t(N),t(l);var c=i(l,2),k=r(c,!0);t(c);var R=i(c,2);{var P=D=>{var j=Ia(),I=r(j,!0);t(j),C(()=>f(I,e.card.left.aux)),v(D,j)};A(R,D=>{e.card.left.aux&&D(P)})}t(s),C(()=>{f(g,e.card.left.label),le(c,`color: var(--tier-${e.card.left.tier??""});`),f(k,e.card.left.value)}),v(o,s)};A(M,o=>{e.card.left&&o(n)})}var u=i(M,4);{var d=o=>{var s=za(),l=r(s),b=r(l);ge(b,{get tier(){return e.card.right.tier},size:10,get color(){return`var(--tier-${e.card.right.tier??""})`}});var N=i(b,2),g=r(N,!0);t(N),t(l);var c=i(l,2),k=r(c,!0);t(c);var R=i(c,2);{var P=D=>{var j=Oa(),I=r(j,!0);t(j),C(()=>f(I,e.card.right.aux)),v(D,j)};A(R,D=>{e.card.right.aux&&D(P)})}t(s),C(()=>{f(g,e.card.right.label),le(c,`color: var(--tier-${e.card.right.tier??""});`),f(k,e.card.right.value)}),v(o,s)};A(u,o=>{e.card.right&&o(d)})}t(_);var x=i(_,2);{var h=o=>{var s=Ha(),l=r(s,!0);t(s),C(()=>f(l,e.card.delta)),v(o,s)};A(x,o=>{e.card.delta&&o(h)})}var w=i(x,2);{var y=o=>{var s=Ya(),l=r(s,!0);t(s),C(()=>f(l,e.card.sub)),v(o,s)};A(w,o=>{e.card.sub&&o(y)})}t(S),v(L,S),J()}var Ua=p('<div class="meta-row svelte-e40scu"><dt class="svelte-e40scu"> </dt> <dd class="svelte-e40scu"> </dd></div>'),Ka=p('<div class="body-sub svelte-e40scu"> </div>'),Ga=p('<div class="body body-meta svelte-e40scu"><dl class="meta-list svelte-e40scu"></dl> <!></div>');function Qa(L,e){X(e,!0);var S=Ga(),_=r(S);te(_,21,()=>e.card.metaRows??[],oe,(u,d)=>{var x=Ua(),h=r(x),w=r(h,!0);t(h);var y=i(h,2),o=r(y,!0);t(y),t(x),C(()=>{f(w,a(d).k),f(o,a(d).v)}),v(u,x)}),t(_);var M=i(_,2);{var n=u=>{var d=Ka(),x=r(d,!0);t(d),C(()=>f(x,e.card.sub)),v(u,d)};A(M,u=>{e.card.sub&&u(n)})}t(S),v(L,S),J()}var Va=p('<div class="unknown svelte-1x6xqhh"> </div>');function Za(L,e){X(e,!0);var S=xe(),_=ee(S);{var M=g=>{Lt(g,{get card(){return e.card}})},n=g=>{It(g,{get card(){return e.card}})},u=g=>{Ht(g,{get card(){return e.card}})},d=g=>{Qt(g,{get card(){return e.card}})},x=g=>{Fe(g,{get card(){return e.card}})},h=g=>{na(g,{get card(){return e.card}})},w=g=>{va(g,{get card(){return e.card}})},y=g=>{ka(g,{get card(){return e.card}})},o=g=>{Ra(g,{get card(){return e.card}})},s=g=>{qa(g,{get card(){return e.card}})},l=g=>{Wa(g,{get card(){return e.card}})},b=g=>{Qa(g,{get card(){return e.card}})},N=g=>{var c=Va(),k=r(c);t(c),C(()=>f(k,`unknown variant: ${e.card.variant??""}`)),v(g,c)};A(_,g=>{e.card.variant==="headline"?g(M):e.card.variant==="tabular"?g(n,1):e.card.variant==="scalars"?g(u,2):e.card.variant==="spark"||e.card.variant==="histogram"?g(d,3):e.card.variant==="timeseries"?g(x,4):e.card.variant==="timeseries-ft"?g(h,5):e.card.variant==="forecast"?g(w,6):e.card.variant==="raster"||e.card.variant==="raster-pred"?g(y,7):e.card.variant==="lulc"?g(o,8):e.card.variant==="register"?g(s,9):e.card.variant==="comparison"?g(l,10):e.card.variant==="meta"?g(b,11):g(N,-1)})}v(L,S),J()}var Xa=p('<button type="button" class="fc-foot-cite svelte-1nuvnzu"><span class="fc-foot-docid svelte-1nuvnzu"> </span> <span class="fc-foot-arrow svelte-1nuvnzu" aria-hidden="true">→</span></button>'),Ja=p('<span class="fc-foot-docid fc-foot-docid-mute svelte-1nuvnzu"> </span>'),$a=p('<header class="fc-head svelte-1nuvnzu"><div class="fc-head-source svelte-1nuvnzu"><!> <span class="fc-head-source-label svelte-1nuvnzu"> </span></div> <span class="fc-head-vintage svelte-1nuvnzu"> </span></header> <h4 class="fc-title svelte-1nuvnzu"> </h4> <!> <footer class="fc-foot svelte-1nuvnzu"><!> <span><!> <span> </span></span></footer>',1);function Te(L,e){X(e,!0);let S=ie(e,"density",3,"comfortable"),_=ie(e,"linkedKey",3,null),M=q(()=>_()!=null&&e.card.mapLayer!=null&&e.card.mapLayer===_()),n=q(()=>Le[e.card.tier].short),u=q(()=>e.card.mapLayer!=null);function d(){var s;e.card.mapLayer&&((s=e.onLink)==null||s.call(e,e.card.mapLayer))}function x(){var s;e.card.mapLayer&&((s=e.onLink)==null||s.call(e,null))}function h(s){var l;s.stopPropagation(),e.card.citeId&&((l=e.onCite)==null||l.call(e,e.card.citeId))}function w(s){var l;a(u)&&(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),(l=e.onLink)==null||l.call(e,e.card.mapLayer??null))}var y=xe(),o=ee(y);st(o,()=>a(u)?"button":"article",!1,(s,l)=>{Xe(s,()=>({type:a(u)?"button":void 0,role:a(u)?"button":"article",class:`fc fc-${e.card.variant??""} fc-tier-${e.card.tier??""}`,"aria-labelledby":`fc-${e.card.id}-title`,"aria-label":`${Le[e.card.tier].label} card · ${e.card.title} · ${e.card.source}`,onpointerenter:d,onpointerleave:x,onfocus:d,onblur:x,onkeydown:w,[Je]:{"is-compact":S()==="compact","is-linked":a(M),"is-interactive":a(u),"has-illustrative":e.card.illustrative||e.card.tier==="synthetic"||e.card.variant==="comparison"}}),void 0,void 0,void 0,"svelte-1nuvnzu");var b=$a(),N=ee(b),g=r(N),c=r(g);ge(c,{get tier(){return e.card.tier},size:11,get color(){return`var(--tier-${e.card.tier??""})`}});var k=i(c,2),R=r(k,!0);t(k),t(g);var P=i(g,2),D=r(P);t(P),t(N);var j=i(N,2),I=r(j,!0);t(j);var O=i(j,2);Za(O,{get card(){return e.card}});var z=i(O,2),U=r(z);{var T=ae=>{var Q=Xa(),Z=r(Q),ne=r(Z,!0);t(Z),re(2),t(Q),C(()=>{m(Q,"title",`Open ${e.card.docId} in citation drawer`),f(ne,e.card.docId)}),Ne("click",Q,h),v(ae,Q)},F=ae=>{var Q=Ja(),Z=r(Q,!0);t(Q),C(()=>f(Z,e.card.docId)),v(ae,Q)};A(U,ae=>{e.card.citeId?ae(T):ae(F,-1)})}var B=i(U,2),E=r(B);ge(E,{get tier(){return e.card.tier},size:9,get color(){return`var(--tier-${e.card.tier??""})`}});var Y=i(E,2),G=r(Y,!0);t(Y),t(B),t(z),C(()=>{m(k,"title",e.card.agency),f(R,e.card.source),f(D,`v. ${e.card.vintage??""}`),m(j,"id",`fc-${e.card.id}-title`),f(I,e.card.title),ue(B,1,`fc-tier-badge fc-tier-badge-${e.card.tier??""}`,"svelte-1nuvnzu"),m(B,"aria-label",`epistemic tier ${a(n)}`),f(G,a(n))}),v(l,b)}),v(L,y),J()}Ce(["click"]);var er=p('<span class="sep svelte-1qqbvs2">·</span> <span class="silent svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> silent</span>',1),tr=p('<span class="sep svelte-1qqbvs2">·</span> <span class="warn svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> warn</span>',1),ar=p('<span class="sep svelte-1qqbvs2">·</span> <span class="err svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> errored</span>',1),rr=p('<span class="sep svelte-1qqbvs2">·</span> <span class="notinvoked svelte-1qqbvs2"><strong class="svelte-1qqbvs2"> </strong> not invoked</span>',1),sr=p('<span class="tally svelte-1qqbvs2"><span class="cards"> </span> <span class="sep svelte-1qqbvs2">·</span> <span class="fired"><strong class="svelte-1qqbvs2"> </strong> fired</span> <!> <!> <!> <!> <span class="sep svelte-1qqbvs2">·</span> <span class="ms"><strong class="svelte-1qqbvs2"> </strong></span></span>');function ir(L,e){X(e,!0);function S(T){return T.flatMap(F=>F.children?[F,...S(F.children)]:[F])}let _=q(()=>S(e.members)),M=q(()=>a(_).filter(T=>T.status==="fired"||T.status==="warned").length),n=q(()=>a(_).filter(T=>T.status==="silent_by_design").length),u=q(()=>a(_).filter(T=>T.status==="warned").length),d=q(()=>a(_).filter(T=>T.status==="errored").length),x=q(()=>a(_).filter(T=>T.status==="not_invoked").length),h=q(()=>e.members.reduce((T,F)=>Math.max(T,F.ms??0),0));function w(T){return T===0?"—":T<1e3?`${T}ms`:`${(T/1e3).toFixed(1)}s`}var y=sr(),o=r(y),s=r(o);t(o);var l=i(o,4),b=r(l),N=r(b,!0);t(b),re(),t(l);var g=i(l,2);{var c=T=>{var F=er(),B=i(ee(F),2),E=r(B),Y=r(E,!0);t(E),re(),t(B),C(()=>f(Y,a(n))),v(T,F)};A(g,T=>{a(n)>0&&T(c)})}var k=i(g,2);{var R=T=>{var F=tr(),B=i(ee(F),2),E=r(B),Y=r(E,!0);t(E),re(),t(B),C(()=>f(Y,a(u))),v(T,F)};A(k,T=>{a(u)>0&&T(R)})}var P=i(k,2);{var D=T=>{var F=ar(),B=i(ee(F),2),E=r(B),Y=r(E,!0);t(E),re(),t(B),C(()=>f(Y,a(d))),v(T,F)};A(P,T=>{a(d)>0&&T(D)})}var j=i(P,2);{var I=T=>{var F=rr(),B=i(ee(F),2),E=r(B),Y=r(E,!0);t(E),re(),t(B),C(()=>f(Y,a(x))),v(T,F)};A(j,T=>{a(x)>0&&T(I)})}var O=i(j,4),z=r(O),U=r(z,!0);t(z),t(O),t(y),C(T=>{f(s,`${e.cardCount??""} card${e.cardCount===1?"":"s"}`),f(N,a(M)),f(U,T)},[()=>w(a(h))]),v(L,y),J()}var nr=p('<span class="prov-tier svelte-qakefz"><!></span>'),lr=p('<span class="prov-note svelte-qakefz"> </span>'),or=p('<span class="prov-ms svelte-qakefz"> </span>'),dr=p('<li class="prov-children svelte-qakefz"><!></li>'),vr=p('<li><span class="prov-pip svelte-qakefz" aria-hidden="true"> </span> <span class="prov-id svelte-qakefz"> </span> <!> <span class="prov-name svelte-qakefz"> </span> <!> <!></li> <!>',1),cr=p('<ul class="prov-tree svelte-qakefz"></ul>');function qe(L,e){X(e,!0);let S=ie(e,"depth",3,0);function _(u){return{fired:"●",silent_by_design:"○",warned:"▲",errored:"■",not_invoked:"□"}[u]}function M(u){return u.status==="warned"?"#B7791F":u.status==="errored"?"#B91C1C":u.status==="silent_by_design"||u.status==="not_invoked"?"var(--ink-tertiary)":u.tier?`var(--tier-${u.tier})`:"var(--ink)"}var n=cr();te(n,21,()=>e.members,u=>u.id,(u,d)=>{var x=vr(),h=ee(x),w=r(h),y=r(w,!0);t(w);var o=i(w,2),s=r(o,!0);t(o);var l=i(o,2);{var b=I=>{var O=nr(),z=r(O);{let U=q(()=>`var(--tier-${a(d).tier})`);ge(z,{get tier(){return a(d).tier},size:9,get color(){return a(U)}})}t(O),v(I,O)};A(l,I=>{a(d).tier&&I(b)})}var N=i(l,2),g=r(N,!0);t(N);var c=i(N,2);{var k=I=>{var O=lr(),z=r(O);t(O),C(()=>f(z,`— ${a(d).note??""}`)),v(I,O)};A(c,I=>{a(d).note&&I(k)})}var R=i(c,2);{var P=I=>{var O=or(),z=r(O,!0);t(O),C(U=>f(z,U),[()=>a(d).ms<1e3?`${a(d).ms}ms`:`${(a(d).ms/1e3).toFixed(1)}s`]),v(I,O)};A(R,I=>{a(d).ms!=null&&I(P)})}t(h);var D=i(h,2);{var j=I=>{var O=dr(),z=r(O);{let U=q(()=>S()+1);qe(z,{get members(){return a(d).children},get depth(){return a(U)}})}t(O),v(I,O)};A(D,I=>{var O;(O=a(d).children)!=null&&O.length&&I(j)})}C((I,O)=>{ue(h,1,`prov-row prov-status-${a(d).status??""}`,"svelte-qakefz"),le(w,`color: ${I??""};`),f(y,O),f(s,a(d).id),f(g,a(d).name)},[()=>M(a(d)),()=>_(a(d).status)]),v(u,x)}),t(n),C(()=>le(n,`--depth: ${S()??""};`)),v(L,n),J()}var ur=p('<div class="silent svelte-16iv0n8"><span class="silent-tag svelte-16iv0n8">silent</span> <p class="silent-prose svelte-16iv0n8"><!></p></div>'),gr=p("<div></div>"),hr=p('<div class="prov-body svelte-16iv0n8"><!></div>'),_r=p('<section><header class="region-head svelte-16iv0n8"><div class="region-head-left svelte-16iv0n8"><span class="region-num svelte-16iv0n8"> </span> <h3 class="region-name svelte-16iv0n8"> </h3> <span class="region-role svelte-16iv0n8"> </span> <span class="region-tag svelte-16iv0n8"> </span></div> <!></header> <!> <div class="prov svelte-16iv0n8"><button type="button" class="prov-toggle svelte-16iv0n8"><span class="prov-caret svelte-16iv0n8" aria-hidden="true"> </span> <span class="prov-label"> </span> <span class="prov-meta svelte-16iv0n8"> </span></button> <!></div></section>');function fr(L,e){X(e,!0);let S=ie(e,"density",3,"comfortable"),_=ie(e,"provenanceMode",3,"smart"),M=ie(e,"linkedKey",3,null),n=q(()=>Me[e.stone]),u=q(()=>`${Ae.indexOf(e.stone)+1}`.padStart(2,"0")),d=q(()=>e.stone==="capstone");function x(K){return K.flatMap(W=>W.children?[W,...x(W.children)]:[W])}let h=q(()=>x(e.trace.members)),w=q(()=>a(h).length),y=q(()=>a(h).some(K=>K.status==="warned"||K.status==="errored"||K.status==="not_invoked")),o=q(()=>_()==="all-expanded"?!0:_()==="all-collapsed"?!1:a(y)),s=Se(null),l=q(()=>a(s)??a(o));ce(()=>{_(),pe(s,null)});var b=_r(),N=r(b),g=r(N),c=r(g),k=r(c,!0);t(c);var R=i(c,2),P=r(R,!0);t(R);var D=i(R,2),j=r(D);t(D);var I=i(D,2),O=r(I,!0);t(I),t(g);var z=i(g,2);ir(z,{get cardCount(){return e.cards.length},get members(){return e.trace.members}}),t(N);var U=i(N,2);{var T=K=>{var W=ur(),$=i(r(W),2),de=r($);{var fe=he=>{var se=ye("No projection cards landed for this query. Atomic functions still ran (see provenance) and returned silence rather than confabulation.");v(he,se)},be=he=>{var se=ye("No cards for this Stone on this query.");v(he,se)};A(de,he=>{e.stone==="lodestone"?he(fe):he(be,-1)})}t($),t(W),v(K,W)},F=K=>{var W=gr();let $;te(W,21,()=>e.cards,de=>de.id,(de,fe)=>{Te(de,{get card(){return a(fe)},get density(){return S()},get linkedKey(){return M()},get onCite(){return e.onCite},get onLink(){return e.onLink}})}),t(W),C(()=>$=ue(W,1,"rail svelte-16iv0n8",null,$,{"rail-capstone":a(d)})),v(K,W)};A(U,K=>{e.cards.length===0?K(T):K(F,-1)})}var B=i(U,2),E=r(B),Y=r(E),G=r(Y,!0);t(Y);var ae=i(Y,2),Q=r(ae);t(ae);var Z=i(ae,2),ne=r(Z);t(Z),t(E);var H=i(E,2);{var V=K=>{var W=hr(),$=r(W);qe($,{get members(){return e.trace.members}}),t(W),C(()=>m(W,"id",`prov-body-${e.stone}`)),v(K,W)};A(H,K=>{a(l)&&K(V)})}t(B),t(b),C(()=>{ue(b,1,`region region-${e.stone??""}`,"svelte-16iv0n8"),m(b,"aria-labelledby",`region-h-${e.stone}`),m(b,"data-stone",e.stone),f(k,a(u)),m(R,"id",`region-h-${e.stone}`),f(P,a(n).name),f(j,`· ${a(n).role??""}`),f(O,a(n).tag),m(E,"aria-expanded",a(l)),m(E,"aria-controls",`prov-body-${e.stone}`),f(G,a(l)?"▾":"▸"),f(Q,`${a(l)?"Hide":"Show"} provenance`),f(ne,`· ${a(w)??""} function${a(w)===1?"":"s"}`)}),Ne("click",E,()=>pe(s,!a(l))),v(L,b),J()}Ce(["click"]);var mr=p('<section class="region region-grammar svelte-gwg123" aria-label="Card grammar reference"><header class="region-head svelte-gwg123"><div class="region-head-left svelte-gwg123"><span class="region-num svelte-gwg123">SPEC</span> <h3 class="region-name svelte-gwg123">Card grammar</h3> <span class="region-role svelte-gwg123">· every body variant in the system</span> <span class="region-tag svelte-gwg123">stubs, not findings</span></div> <span class="grammar-count svelte-gwg123"> </span></header> <div class="rail svelte-gwg123"></div></section>');function yr(L,e){let S=ie(e,"density",3,"comfortable");const _=[{id:"grm-headline",stone:"cornerstone",tier:"modeled",variant:"headline",source:"FEMA",agency:"spec",vintage:"spec",title:"Single big number, scenario-tagged",headline:"Zone AE",subhead:"preliminary FIRM, panel ID",sub:"Use when the answer is one categorical state.",docId:"DS-HEADLINE"},{id:"grm-tabular",stone:"cornerstone",tier:"empirical",variant:"tabular",source:"USGS",agency:"spec",vintage:"spec",title:"Small table of observations",columns:["id","value","dist."],rows:[["ROW-001","1.2 m","0.18 mi"],["ROW-002","0.9 m","0.32 mi"],["ROW-003","0.7 m","0.41 mi"]],sub:"Use when 3–8 records each carry the same fields.",docId:"DS-TABULAR"},{id:"grm-scalars",stone:"touchstone",tier:"empirical",variant:"scalars",source:"NWS",agency:"spec",vintage:"spec",title:"Trio of scalar readings",scalars:[{value:"0.02 in",label:"precip · 24h"},{value:"11 mph",label:"wind"},{value:"63°F",label:"temp"}],sub:"Use for current-state dashboards.",docId:"DS-SCALARS"},{id:"grm-spark",stone:"touchstone",tier:"empirical",variant:"spark",source:"FloodNet",agency:"spec",vintage:"spec",title:"Sparkline of recent events",headline:"n events",subhead:"window · peak",spark:[1,2,4,3,7,12,8,5,3,2,4,9,6],docId:"DS-SPARK"},{id:"grm-histogram",stone:"touchstone",tier:"proxy",variant:"histogram",source:"NYC 311",agency:"spec",vintage:"spec",title:"Histogram of binned counts",headline:"n calls",subhead:"window · seasonal note",histogram:[3,2,1,0,1,4,7,12,18,11,5,3,4,2,1,0,2,3,8,9,4,2,1,0],docId:"DS-HIST"},{id:"grm-timeseries",stone:"lodestone",tier:"modeled",variant:"timeseries",source:"Granite TTM",agency:"spec",vintage:"spec",title:"Forecast curve with horizon",headline:"+0.41 m peak",subhead:"+38h · 90% CI",timeseries:{hours:96,peak:{x:38,y:41},peakLabel:"+0.41 m"},spatialNote:"regional",sub:"Spatial-index callout when station ≠ point-of-query.",docId:"DS-TS"},{id:"grm-forecast",stone:"lodestone",tier:"modeled",variant:"forecast",source:"NPCC4",agency:"spec",vintage:"spec",title:"Long-horizon scenario projections",forecast:[{year:2030,low:4,mid:6,high:9},{year:2050,low:13,mid:22,high:30},{year:2100,low:38,mid:71,high:114}],sub:"Use for decadal+ uncertainty cones.",docId:"DS-FCST"},{id:"grm-raster",stone:"cornerstone",tier:"modeled",variant:"raster",source:"NYC DEP",agency:"spec",vintage:"spec",title:"Raster snapshot, mapped layer",rasterKind:"stormwater",headline:"ponding",subhead:"scenario · pixel summary",sub:"Use for any 2D model output.",docId:"DS-RASTER"},{id:"grm-rasterpred",stone:"touchstone",tier:"modeled",variant:"raster-pred",source:"Prithvi-NYC",agency:"spec",vintage:"spec",title:"Raster prediction, illustrative",rasterKind:"prithvi",headline:"n% flooded",subhead:"model · scene id",illustrative:!0,sub:"Same chrome as raster + illustrative tag.",docId:"DS-RASTERPRED"},{id:"grm-register",stone:"keystone",tier:"empirical",variant:"register",source:"NYC OpenData",agency:"spec",vintage:"spec",title:"Composite register list",registers:[{reg:"MTA",tier:"empirical",label:"Station entrance",detail:"0.18 mi · 5",sourceId:"MTA-X",note:null},{reg:"NYCHA",tier:"empirical",label:"Development",detail:"0.41 mi · 2,878 res.",sourceId:"NYCHA-Y",note:null},{reg:"DOH",tier:"empirical",label:null,detail:null,sourceId:null,note:"no acute-care hospital within 1.0 mi"}],sub:"Use when many specialists join into one Stone.",docId:"DS-REGISTER"},{id:"grm-comparison",stone:"keystone",tier:"synthetic",variant:"comparison",source:"EMP × SYN",agency:"spec",vintage:"spec",title:"Documented vs. interpreted",left:{tier:"empirical",label:"documented",value:"31.4%",aux:"n polygons"},right:{tier:"synthetic",label:"interpreted",value:"29.8%",aux:"n polygons"},delta:"Δ = −1.6 pp · agreement strong",sub:"Use to surface model–ground-truth deltas.",docId:"DS-CMP"},{id:"grm-meta",stone:"capstone",tier:"modeled",variant:"meta",source:"Mellea",agency:"spec",vintage:"spec",title:"Capstone reconciliation",metaRows:[{k:"claims",v:"12 / 12 grounded"},{k:"tier mix",v:"EMP 5 · MOD 4 · PRX 2 · SYN 1"},{k:"tier-1 freshness",v:"median 38 d"},{k:"warnings",v:"0"}],sub:"Use to expose the synthesis layer's audit.",docId:"DS-META"}];var M=mr(),n=r(M),u=i(r(n),2),d=r(u);t(u),t(n);var x=i(n,2);te(x,21,()=>_,h=>h.id,(h,w)=>{Te(h,{get card(){return a(w)},get density(){return S()}})}),t(x),t(M),C(()=>f(d,`${_.length??""} variants`)),v(L,M)}var pr=p('<section class="findings svelte-ci42t5" aria-label="Findings, grouped by Stone"><header class="findings-head svelte-ci42t5"><h2 class="findings-h2 svelte-ci42t5">Findings · grouped by Stone</h2> <span class="findings-tagline svelte-ci42t5">cards = what each Stone found · provenance collapses below</span></header> <!> <!> <!></section>');function Fr(L,e){X(e,!0);let S=ie(e,"density",3,"comfortable"),_=ie(e,"provenanceMode",3,"smart"),M=ie(e,"showGrammar",3,!1),n=ie(e,"linkedKey",3,null),u=q(()=>{const s={cornerstone:[],keystone:[],touchstone:[],lodestone:[],capstone:[]};for(const l of e.data.cards)s[l.stone].push(l);return s}),d=q(()=>{const s={cornerstone:{key:"cornerstone",members:[]},keystone:{key:"keystone",members:[]},touchstone:{key:"touchstone",members:[]},lodestone:{key:"lodestone",members:[]},capstone:{key:"capstone",members:[]}};for(const l of e.data.stones)s[l.key]=l;return s});var x=pr(),h=i(r(x),2);Nt(h,{get cards(){return e.data.cards},get stones(){return e.data.stones},get wallSeconds(){return e.data.wallSeconds},get cacheHit(){return e.data.cacheHit}});var w=i(h,2);te(w,16,()=>Ae,s=>s,(s,l)=>{fr(s,{get stone(){return l},get cards(){return a(u)[l]},get trace(){return a(d)[l]},get density(){return S()},get provenanceMode(){return _()},get linkedKey(){return n()},get onCite(){return e.onCite},get onLink(){return e.onLink}})});var y=i(w,2);{var o=s=>{yr(s,{get density(){return S()}})};A(y,s=>{M()&&s(o)})}t(x),v(L,x),J()}const xr={cornerstone:[{id:"CORN-001",name:"sandy_inundation.lookup",stepNames:["sandy_inundation","sandy_nta"],tier:"empirical",skipReason:"Sandy 2012 inundation: query outside NYC bounds"},{id:"CORN-002",name:"dep_stormwater.lookup",stepNames:["dep_stormwater","dep_extreme_2080_nta","dep_moderate_2050_nta","dep_moderate_current_nta"],tier:"modeled",skipReason:"NYC DEP stormwater scenarios: query outside NYC bounds"},{id:"CORN-003",name:"usgs_hwm.spatial_join",stepNames:["ida_hwm_2021"],tier:"empirical",skipReason:"USGS Ida HWMs: no marks within 800 m of address"},{id:"CORN-004",name:"prithvi_water.lookup",stepNames:["prithvi_eo_v2"],tier:"modeled",skipReason:"Prithvi-EO Ida polygons: no polygons within 500 m"},{id:"CORN-005",name:"microtopo.dem_hand_twi",stepNames:["microtopo_lidar","microtopo_nta"],tier:"proxy",skipReason:"USGS 3DEP DEM: query outside NYC raster coverage"}],keystone:[{id:"KEY-001",name:"mta_entrance_exposure",stepNames:["mta_entrance_exposure"],tier:"empirical",skipReason:"no entrances within radius"},{id:"KEY-002",name:"nycha.development_join",stepNames:["nycha_development_exposure"],tier:"empirical",skipReason:"no NYCHA developments within 1.0 mi"},{id:"KEY-003",name:"doe.school_join",stepNames:["doe_school_exposure"],tier:"empirical",skipReason:"no DOE schools within 1.0 mi"},{id:"KEY-004",name:"doh.facility_join",stepNames:["doh_hospital_exposure"],tier:"empirical",skipReason:"no acute-care hospitals within 1.0 mi"},{id:"KEY-005",name:"pluto.lot_lookup",stepNames:["pluto_lookup"],tier:"empirical",skipReason:"PLUTO join skipped: queried address not in NYC PLUTO dataset"},{id:"KEY-006",name:"terramind.buildings",stepNames:["terramind_buildings","terramind_synthesis"],tier:"modeled",skipReason:"TerraMind Buildings adapter: heavy specialist disabled (RIPRAP_HEAVY_SPECIALISTS=0)"}],touchstone:[{id:"TCH-001",name:"floodnet.history",stepNames:["floodnet"],tier:"empirical",skipReason:"FloodNet sensor: no deployments within 600 m"},{id:"TCH-002",name:"nyc311.flood_complaints",stepNames:["nyc311","nyc311_nta"],tier:"proxy",skipReason:"NYC 311: no flood-relevant complaints within 200 m"},{id:"TCH-003",name:"nws_obs.metar",stepNames:["nws_obs"],tier:"empirical",skipReason:"NWS hourly METAR: nearest ASOS reports no precipitation"},{id:"TCH-004",name:"noaa_coops.recent",stepNames:["noaa_tides"],tier:"empirical",skipReason:"NOAA tide gauge: nearest station >25 km from address"},{id:"TCH-005",name:"prithvi_nyc_pluvial",stepNames:["prithvi_eo_live"],tier:"modeled",skipReason:"Prithvi-NYC-Pluvial: live segmentation specialist disabled or no <30% cloud Sentinel-2 in last 120 d"},{id:"TCH-006",name:"terramind.lulc",stepNames:["terramind_lulc"],tier:"synthetic",skipReason:"TerraMind LULC adapter: heavy specialist disabled or eo_chip fetch silent"}],lodestone:[{id:"LOD-001",name:"nws_alerts.flood_relevant",stepNames:["nws_alerts"],tier:"modeled",skipReason:"NWS public alerts: no active flood-relevant alerts at this address"},{id:"LOD-002",name:"ttm_battery_surge.zero_shot",stepNames:["ttm_forecast"],tier:"modeled",skipReason:"Granite TTM r2 zero-shot: forecast not interesting (peak |residual| < 0.3 ft)"},{id:"LOD-003",name:"ttm_battery_surge.fine_tune",stepNames:["ttm_battery_surge"],tier:"modeled",skipReason:"Granite TTM Battery fine-tune: forecast not interesting (peak |residual| < 0.3 m)"},{id:"LOD-004",name:"ttm_311_forecast",stepNames:["ttm_311_forecast"],tier:"modeled",skipReason:"NYC 311 weekly forecast: no per-address history to extrapolate"},{id:"LOD-005",name:"floodnet_forecast",stepNames:["floodnet_forecast"],tier:"modeled",skipReason:"FloodNet sensor recurrence: sensor has < silent-floor historical events; forecast omitted"},{id:"LOD-006",name:"npcc4.slr_projection",stepNames:["npcc4_projection"],tier:"modeled",skipReason:"NPCC4 SLR projection: not yet wired into FSM (static reference card on hold)"}],capstone:[{id:"CAP-001",name:"rag.granite_embedding",stepNames:["rag_granite_embedding"],tier:"proxy",skipReason:"Granite Embedding RAG: no policy retrieval (out-of-NYC scope)"},{id:"CAP-002",name:"gliner.typed_extraction",stepNames:["gliner_extract"],tier:"proxy",skipReason:"GLiNER typed extraction: no RAG hits to extract over"},{id:"CAP-003",name:"granite41.compose_briefing",stepNames:["reconcile_granite41","mellea_reconcile_address","reconcile_neighborhood","reconcile_development","reconcile_live_now"],tier:"modeled",skipReason:"Reconciler did not run (no grounded data available)"},{id:"CAP-004",name:"mellea.grounding_check",stepNames:["mellea_grounding"],tier:"modeled",skipReason:"Mellea grounding-check: rolled into reconcile step on this run"}]};function Pr(L,e){const S=xr[L]??[],_=new Map;for(const u of e)_.set(u.name,u);const M=[],n=new Set;for(const u of S){let d;for(const x of u.stepNames){const h=_.get(x);if(h){d=h,n.add(x);break}}d?M.push({...d,id:u.id,name:u.name,tier:d.tier??u.tier??null}):M.push({id:u.id,name:u.name,status:"not_invoked",tier:u.tier??null,note:u.skipReason})}for(const u of e)n.has(u.name)||M.push(u);return M}export{Rr as C,Fr as F,Er as M,Lr as R,Pr as f};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web/sveltekit/build/_app/immutable/chunks/Br29PcKx.js
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
var rt=e=>{throw TypeError(e)};var Dt=(e,t,n)=>t.has(e)||rt("Cannot "+n);var y=(e,t,n)=>(Dt(e,t,"read from private field"),n?n.call(e):t.get(e)),A=(e,t,n)=>t.has(e)?rt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n);import{bf as Pe,bg as zt,ai as at,a4 as T,o as I,a5 as O,ar as we,bh as Vt}from"./BTUA7_xE.js";const K=[];function Be(e,t=Pe){let n=null;const a=new Set;function r(o){if(zt(e,o)&&(e=o,n)){const l=!K.length;for(const c of a)c[1](),K.push(c,e);if(l){for(let c=0;c<K.length;c+=2)K[c][0](K[c+1]);K.length=0}}}function i(o){r(o(e))}function s(o,l=Pe){const c=[o,l];return a.add(c),a.size===1&&(n=t(r,i)||Pe),o(e),()=>{a.delete(c),a.size===0&&n&&(n(),n=null)}}return{set:r,update:i,subscribe:s}}class Ke{constructor(t,n){this.status=t,typeof n=="string"?this.body={message:n}:n?this.body=n:this.body={message:`Error: ${t}`}}toString(){return JSON.stringify(this.body)}}class Me{constructor(t,n){try{new Headers({location:n})}catch{throw new Error(`Invalid redirect location ${JSON.stringify(n)}: this string contains characters that cannot be used in HTTP headers`)}this.status=t,this.location=n}}class Fe extends Error{constructor(t,n,a){super(a),this.status=t,this.text=n}}new URL("sveltekit-internal://");function Bt(e,t){return e==="/"||t==="ignore"?e:t==="never"?e.endsWith("/")?e.slice(0,-1):e:t==="always"&&!e.endsWith("/")?e+"/":e}function Kt(e){return e.split("%25").map(decodeURI).join("%25")}function Mt(e){for(const t in e)e[t]=decodeURIComponent(e[t]);return e}function $e({href:e}){return e.split("#")[0]}function C(){}function Ft(...e){let t=5381;for(const n of e)if(typeof n=="string"){let a=n.length;for(;a;)t=t*33^n.charCodeAt(--a)}else if(ArrayBuffer.isView(n)){const a=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let r=a.length;for(;r;)t=t*33^a[--r]}else throw new TypeError("value must be a string or TypedArray");return(t>>>0).toString(36)}new TextEncoder;function Gt(e){const t=atob(e),n=new Uint8Array(t.length);for(let a=0;a<t.length;a++)n[a]=t.charCodeAt(a);return n}const Ht=window.fetch;window.fetch=(e,t)=>((e instanceof Request?e.method:(t==null?void 0:t.method)||"GET")!=="GET"&&X.delete(Ge(e)),Ht(e,t));const X=new Map;function Wt(e,t){const n=Ge(e,t),a=document.querySelector(n);if(a!=null&&a.textContent){a.remove();let{body:r,...i}=JSON.parse(a.textContent);const s=a.getAttribute("data-ttl");return s&&X.set(n,{body:r,init:i,ttl:1e3*Number(s)}),a.getAttribute("data-b64")!==null&&(r=Gt(r)),Promise.resolve(new Response(r,i))}return window.fetch(e,t)}function Jt(e,t,n){if(X.size>0){const a=Ge(e,n),r=X.get(a);if(r){if(performance.now()<r.ttl&&["default","force-cache","only-if-cached",void 0].includes(n==null?void 0:n.cache))return new Response(r.body,r.init);X.delete(a)}}return window.fetch(t,n)}function Ge(e,t){let a=`script[data-sveltekit-fetched][data-url=${JSON.stringify(e instanceof Request?e.url:e)}]`;if(t!=null&&t.headers||t!=null&&t.body){const r=[];t.headers&&r.push([...new Headers(t.headers)].join(",")),t.body&&(typeof t.body=="string"||ArrayBuffer.isView(t.body))&&r.push(t.body),a+=`[data-hash="${Ft(...r)}"]`}return a}const Yt=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;function Xt(e){const t=[];return{pattern:e==="/"?/^\/$/:new RegExp(`^${Zt(e).map(a=>{const r=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(a);if(r)return t.push({name:r[1],matcher:r[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const i=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(a);if(i)return t.push({name:i[1],matcher:i[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!a)return;const s=a.split(/\[(.+?)\](?!\])/);return"/"+s.map((l,c)=>{if(c%2){if(l.startsWith("x+"))return Ce(String.fromCharCode(parseInt(l.slice(2),16)));if(l.startsWith("u+"))return Ce(String.fromCharCode(...l.slice(2).split("-").map(m=>parseInt(m,16))));const d=Yt.exec(l),[,u,w,p,f]=d;return t.push({name:p,matcher:f,optional:!!u,rest:!!w,chained:w?c===1&&s[0]==="":!1}),w?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return Ce(l)}).join("")}).join("")}/?$`),params:t}}function Qt(e){return e!==""&&!/^\([^)]+\)$/.test(e)}function Zt(e){return e.slice(1).split("/").filter(Qt)}function en(e,t,n){const a={},r=e.slice(1),i=r.filter(o=>o!==void 0);let s=0;for(let o=0;o<t.length;o+=1){const l=t[o];let c=r[o-s];if(l.chained&&l.rest&&s&&(c=r.slice(o-s,o+1).filter(d=>d).join("/"),s=0),c===void 0)if(l.rest)c="";else continue;if(!l.matcher||n[l.matcher](c)){a[l.name]=c;const d=t[o+1],u=r[o+1];d&&!d.rest&&d.optional&&u&&l.chained&&(s=0),!d&&!u&&Object.keys(a).length===i.length&&(s=0);continue}if(l.optional&&l.chained){s++;continue}return}if(!s)return a}function Ce(e){return e.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function tn({nodes:e,server_loads:t,dictionary:n,matchers:a}){const r=new Set(t);return Object.entries(n).map(([o,[l,c,d]])=>{const{pattern:u,params:w}=Xt(o),p={id:o,exec:f=>{const m=u.exec(f);if(m)return en(m,w,a)},errors:[1,...d||[]].map(f=>e[f]),layouts:[0,...c||[]].map(s),leaf:i(l)};return p.errors.length=p.layouts.length=Math.max(p.errors.length,p.layouts.length),p});function i(o){const l=o<0;return l&&(o=~o),[l,e[o]]}function s(o){return o===void 0?o:[r.has(o),e[o]]}}function wt(e,t=JSON.parse){try{return t(sessionStorage[e])}catch{}}function ot(e,t,n=JSON.stringify){const a=n(t);try{sessionStorage[e]=a}catch{}}var ht;const U=((ht=globalThis.__sveltekit_zbrfxa)==null?void 0:ht.base)??"";var pt;const nn=((pt=globalThis.__sveltekit_zbrfxa)==null?void 0:pt.assets)??U??"",rn="1778043659942",vt="sveltekit:snapshot",yt="sveltekit:scroll",bt="sveltekit:states",an="sveltekit:pageurl",F="sveltekit:history",Z="sveltekit:navigation",D={tap:1,hover:2,viewport:3,eager:4,off:-1,false:-1},Ue=location.origin;function He(e){if(e instanceof URL)return e;let t=document.baseURI;if(!t){const n=document.getElementsByTagName("base");t=n.length?n[0].href:document.URL}return new URL(e,t)}function V(){return{x:pageXOffset,y:pageYOffset}}function M(e,t){return e.getAttribute(`data-sveltekit-${t}`)}const st={...D,"":D.hover};function kt(e){let t=e.assignedSlot??e.parentNode;return(t==null?void 0:t.nodeType)===11&&(t=t.host),t}function St(e,t){for(;e&&e!==t;){if(e.nodeName.toUpperCase()==="A"&&e.hasAttribute("href"))return e;e=kt(e)}}function qe(e,t,n){let a;try{if(a=new URL(e instanceof SVGAElement?e.href.baseVal:e.href,document.baseURI),n&&a.hash.match(/^#[^/]/)){const o=location.hash.split("#")[1]||"/";a.hash=`#${o}${a.hash}`}}catch{}const r=e instanceof SVGAElement?e.target.baseVal:e.target,i=!a||!!r||Ae(a,t,n)||(e.getAttribute("rel")||"").split(/\s+/).includes("external"),s=(a==null?void 0:a.origin)===Ue&&e.hasAttribute("download");return{url:a,external:i,target:r,download:s}}function ve(e){let t=null,n=null,a=null,r=null,i=null,s=null,o=e;for(;o&&o!==document.documentElement;)a===null&&(a=M(o,"preload-code")),r===null&&(r=M(o,"preload-data")),t===null&&(t=M(o,"keepfocus")),n===null&&(n=M(o,"noscroll")),i===null&&(i=M(o,"reload")),s===null&&(s=M(o,"replacestate")),o=kt(o);function l(c){switch(c){case"":case"true":return!0;case"off":case"false":return!1;default:return}}return{preload_code:st[a??"off"],preload_data:st[r??"off"],keepfocus:l(t),noscroll:l(n),reload:l(i),replace_state:l(s)}}function it(e){const t=Be(e);let n=!0;function a(){n=!0,t.update(s=>s)}function r(s){n=!1,t.set(s)}function i(s){let o;return t.subscribe(l=>{(o===void 0||n&&l!==o)&&s(o=l)})}return{notify:a,set:r,subscribe:i}}const Et={v:C};function on(){const{set:e,subscribe:t}=Be(!1);let n;async function a(){clearTimeout(n);try{const r=await fetch(`${nn}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!r.ok)return!1;const s=(await r.json()).version!==rn;return s&&(e(!0),Et.v(),clearTimeout(n)),s}catch{return!1}}return{subscribe:t,check:a}}function Ae(e,t,n){return e.origin!==Ue||!e.pathname.startsWith(t)?!0:n?e.pathname!==location.pathname:!1}function Pn(e){}const Rt=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...Rt];const sn=new Set([...Rt]);[...sn];function ln(e){return e.filter(t=>t!=null)}function me(e,t){return e+"/"+t}function We(e){return e instanceof Ke||e instanceof Fe?e.status:500}function cn(e){return e instanceof Fe?e.text:"Internal Error"}let R,ee,je;const fn=at.toString().includes("$$")||/function \w+\(\) \{\}/.test(at.toString()),lt="a:";var oe,se,ie,le,ce,fe,ue,de,gt,he,mt,pe,_t;fn?(R={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL(lt)},ee={current:null},je={current:!1}):(R=new(gt=class{constructor(){A(this,oe,T({}));A(this,se,T(null));A(this,ie,T(null));A(this,le,T({}));A(this,ce,T({id:null}));A(this,fe,T({}));A(this,ue,T(-1));A(this,de,T(new URL(lt)))}get data(){return I(y(this,oe))}set data(t){O(y(this,oe),t)}get form(){return I(y(this,se))}set form(t){O(y(this,se),t)}get error(){return I(y(this,ie))}set error(t){O(y(this,ie),t)}get params(){return I(y(this,le))}set params(t){O(y(this,le),t)}get route(){return I(y(this,ce))}set route(t){O(y(this,ce),t)}get state(){return I(y(this,fe))}set state(t){O(y(this,fe),t)}get status(){return I(y(this,ue))}set status(t){O(y(this,ue),t)}get url(){return I(y(this,de))}set url(t){O(y(this,de),t)}},oe=new WeakMap,se=new WeakMap,ie=new WeakMap,le=new WeakMap,ce=new WeakMap,fe=new WeakMap,ue=new WeakMap,de=new WeakMap,gt),ee=new(mt=class{constructor(){A(this,he,T(null))}get current(){return I(y(this,he))}set current(t){O(y(this,he),t)}},he=new WeakMap,mt),je=new(_t=class{constructor(){A(this,pe,T(!1))}get current(){return I(y(this,pe))}set current(t){O(y(this,pe),t)}},pe=new WeakMap,_t),Et.v=()=>je.current=!0);function un(e){Object.assign(R,e)}const dn=new Set(["icon","shortcut icon","apple-touch-icon"]);let J=null;const N=wt(yt)??{},te=wt(vt)??{},j={url:it({}),page:it({}),navigating:Be(null),updated:on()};function Je(e){N[e]=V()}function hn(e,t){let n=e+1;for(;N[n];)delete N[n],n+=1;for(n=t+1;te[n];)delete te[n],n+=1}function ne(e,t=!1){return t?location.replace(e.href):location.href=e.href,new Promise(C)}async function xt(){if("serviceWorker"in navigator){const e=await navigator.serviceWorker.getRegistration(U||"/");e&&await e.update()}}let Ye,De,ye,P,ze,S;const be=[],ke=[];let v=null;function Se(){var e;(e=v==null?void 0:v.fork)==null||e.then(t=>t==null?void 0:t.discard()),v=null}const _e=new Map,Lt=new Set,pn=new Set,Q=new Set;let _={branch:[],error:null,url:null},Ut=!1,Ee=!1,ct=!0,re=!1,Y=!1,At=!1,Xe=!1,Tt,k,L,z;const Re=new Set,ft=new Map,ut=new Map;async function Nn(e,t,n){var i,s,o,l;globalThis.__sveltekit_zbrfxa&&(globalThis.__sveltekit_zbrfxa.query,globalThis.__sveltekit_zbrfxa.prerender),document.URL!==location.href&&(location.href=location.href),S=e,await((s=(i=e.hooks).init)==null?void 0:s.call(i)),Ye=tn(e),P=document.documentElement,ze=t,De=e.nodes[0],ye=e.nodes[1],De(),ye(),k=(o=history.state)==null?void 0:o[F],L=(l=history.state)==null?void 0:l[Z],k||(k=L=Date.now(),history.replaceState({...history.state,[F]:k,[Z]:L},""));const a=N[k];function r(){a&&(history.scrollRestoration="manual",scrollTo(a.x,a.y))}n?(r(),await Ln(ze,n)):(await G({type:"enter",url:He(S.hash?Tn(new URL(location.href)):location.href),replace_state:!0}),r()),xn()}function gn(){be.length=0,Xe=!1}function It(e){ke.some(t=>t==null?void 0:t.snapshot)&&(te[e]=ke.map(t=>{var n;return(n=t==null?void 0:t.snapshot)==null?void 0:n.capture()}))}function Ot(e){var t;(t=te[e])==null||t.forEach((n,a)=>{var r,i;(i=(r=ke[a])==null?void 0:r.snapshot)==null||i.restore(n)})}function dt(){Je(k),ot(yt,N),It(L),ot(vt,te)}async function Pt(e,t,n,a){let r,i;t.invalidateAll&&Se(),await G({type:"goto",url:He(e),keepfocus:t.keepFocus,noscroll:t.noScroll,replace_state:t.replaceState,state:t.state,redirect_count:n,nav_token:a,accept:()=>{if(t.invalidateAll){Xe=!0,r=new Set;for(const[s,o]of ft)for(const l of o.keys())r.add(me(s,l));i=new Set;for(const[s,o]of ut)for(const l of o.keys())i.add(me(s,l))}t.invalidate&&t.invalidate.forEach(Rn)}}),t.invalidateAll&&we().then(we).then(()=>{for(const[s,o]of ft)for(const[l,{resource:c}]of o)r!=null&&r.has(me(s,l))&&c.refresh();for(const[s,o]of ut)for(const[l,{resource:c}]of o)i!=null&&i.has(me(s,l))&&c.reconnect()})}async function mn(e){if(e.id!==(v==null?void 0:v.id)){Se();const t={};Re.add(t),v={id:e.id,token:t,promise:Ct({...e,preload:t}).then(n=>(Re.delete(t),n.type==="loaded"&&n.state.error&&Se(),n)),fork:null}}return v.promise}async function Ne(e){var n;const t=(n=await Te(e,!1))==null?void 0:n.route;t&&await Promise.all([...t.layouts,t.leaf].filter(Boolean).map(a=>a[1]()))}async function $t(e,t,n){var i;const a={params:_.params,route:{id:((i=_.route)==null?void 0:i.id)??null},url:new URL(location.href)};_={...e.state,nav:a};const r=document.querySelector("style[data-sveltekit]");if(r&&r.remove(),Object.assign(R,e.props.page),Tt=new S.root({target:t,props:{...e.props,stores:j,components:ke},hydrate:n,sync:!1,transformError:void 0}),await Promise.resolve(),Ot(L),n){const s={from:null,to:{...a,scroll:N[k]??V()},willUnload:!1,type:"enter",complete:Promise.resolve()};Q.forEach(o=>o(s))}Ee=!0}async function xe({url:e,params:t,branch:n,errors:a,status:r,error:i,route:s,form:o}){let l="never";if(U&&(e.pathname===U||e.pathname===U+"/"))l="always";else for(const f of n)(f==null?void 0:f.slash)!==void 0&&(l=f.slash);e.pathname=Bt(e.pathname,l),e.search=e.search;const c={type:"loaded",state:{url:e,params:t,branch:n,error:i,route:s},props:{constructors:ln(n).map(f=>f.node.component),page:nt(R)}};o!==void 0&&(c.props.form=o);let d={},u=!R,w=0;for(let f=0;f<Math.max(n.length,_.branch.length);f+=1){const m=n[f],h=_.branch[f];(m==null?void 0:m.data)!==(h==null?void 0:h.data)&&(u=!0),m&&(d={...d,...m.data},u&&(c.props[`data_${w}`]=d),w+=1)}return(!_.url||e.href!==_.url.href||_.error!==i||o!==void 0&&o!==R.form||u)&&(c.props.page={error:i,params:t,route:{id:(s==null?void 0:s.id)??null},state:{},status:r,url:new URL(e),form:o??null,data:u?d:R.data}),c}async function Qe({loader:e,parent:t,url:n,params:a,route:r,server_data_node:i}){var c,d;let s=null;const o={dependencies:new Set,params:new Set,parent:!1,route:!1,url:!1,search_params:new Set},l=await e();return{node:l,loader:e,server:i,universal:(c=l.universal)!=null&&c.load?{type:"data",data:s,uses:o}:null,data:s??(i==null?void 0:i.data)??null,slash:((d=l.universal)==null?void 0:d.trailingSlash)??(i==null?void 0:i.slash)}}function _n(e,t,n){let a=e instanceof Request?e.url:e;const r=new URL(a,n);r.origin===n.origin&&(a=r.href.slice(n.origin.length));const i=Ee?Jt(a,r.href,t):Wt(a,t);return{resolved:r,promise:i}}function wn(e,t,n,a,r,i){if(Xe)return!0;if(!r)return!1;if(r.parent&&e||r.route&&t||r.url&&n)return!0;for(const s of r.search_params)if(a.has(s))return!0;for(const s of r.params)if(i[s]!==_.params[s])return!0;for(const s of r.dependencies)if(be.some(o=>o(new URL(s))))return!0;return!1}function Ze(e,t){return(e==null?void 0:e.type)==="data"?e:(e==null?void 0:e.type)==="skip"?t??null:null}function vn(e,t){if(!e)return new Set(t.searchParams.keys());const n=new Set([...e.searchParams.keys(),...t.searchParams.keys()]);for(const a of n){const r=e.searchParams.getAll(a),i=t.searchParams.getAll(a);r.every(s=>i.includes(s))&&i.every(s=>r.includes(s))&&n.delete(a)}return n}function yn({error:e,url:t,route:n,params:a}){return{type:"loaded",state:{error:e,url:t,route:n,params:a,branch:[]},props:{page:nt(R),constructors:[]}}}async function Ct({id:e,invalidating:t,url:n,params:a,route:r,preload:i}){if((v==null?void 0:v.id)===e)return Re.delete(v.token),v.promise;const{errors:s,layouts:o,leaf:l}=r,c=[...o,l];s.forEach(h=>h==null?void 0:h().catch(C)),c.forEach(h=>h==null?void 0:h[1]().catch(C));const d=_.url?e!==Le(_.url):!1,u=_.route?r.id!==_.route.id:!1,w=vn(_.url,n);let p=!1;const f=c.map(async(h,g)=>{var $;if(!h)return;const b=_.branch[g];return h[1]===(b==null?void 0:b.loader)&&!wn(p,u,d,w,($=b.universal)==null?void 0:$.uses,a)?b:(p=!0,Qe({loader:h[1],url:n,params:a,route:r,parent:async()=>{var ge;const q={};for(let B=0;B<g;B+=1)Object.assign(q,(ge=await f[B])==null?void 0:ge.data);return q},server_data_node:Ze(h[0]?{type:"skip"}:null,h[0]?b==null?void 0:b.server:void 0)}))});for(const h of f)h.catch(C);const m=[];for(let h=0;h<c.length;h+=1)if(c[h])try{m.push(await f[h])}catch(g){if(g instanceof Me)return{type:"redirect",location:g.location};if(Re.has(i))return yn({error:await ae(g,{params:a,url:n,route:{id:r.id}}),url:n,params:a,route:r});let b=We(g),x;if(g instanceof Ke)x=g.body;else{if(await j.updated.check())return await xt(),await ne(n);x=await ae(g,{params:a,url:n,route:{id:r.id}})}const $=await bn(h,m,s);return $?xe({url:n,params:a,branch:m.slice(0,$.idx).concat($.node),errors:s,status:b,error:x,route:r}):await Nt(n,{id:r.id},x,b)}else m.push(void 0);return xe({url:n,params:a,branch:m,errors:s,status:200,error:null,route:r,form:t?void 0:null})}async function bn(e,t,n){for(;e--;)if(n[e]){let a=e;for(;!t[a];)a-=1;try{return{idx:a+1,node:{node:await n[e](),loader:n[e],data:{},server:null,universal:null}}}catch{continue}}}async function et({status:e,error:t,url:n,route:a}){const r={};let i=null;try{const s=await Qe({loader:De,url:n,params:r,route:a,parent:()=>Promise.resolve({}),server_data_node:Ze(i)}),o={node:await ye(),loader:ye,universal:null,server:null,data:null};return xe({url:n,params:r,branch:[s,o],status:e,error:t,errors:[],route:null})}catch(s){if(s instanceof Me)return Pt(new URL(s.location,location.href),{},0);throw s}}async function kn(e){const t=e.href;if(_e.has(t))return _e.get(t);let n;try{const a=(async()=>{let r=await S.hooks.reroute({url:new URL(e),fetch:async(i,s)=>_n(i,s,e).promise})??e;if(typeof r=="string"){const i=new URL(e);S.hash?i.hash=r:i.pathname=r,r=i}return r})();_e.set(t,a),n=await a}catch{_e.delete(t);return}return n}async function Te(e,t){if(e&&!Ae(e,U,S.hash)){const n=await kn(e);if(!n)return;const a=Sn(n);for(const r of Ye){const i=r.exec(a);if(i)return{id:Le(e),invalidating:t,route:r,params:Mt(i),url:e}}}}function Sn(e){return Kt(S.hash?e.hash.replace(/^#/,"").replace(/[?#].+/,""):e.pathname.slice(U.length))||"/"}function Le(e){return(S.hash?e.hash.replace(/^#/,""):e.pathname)+e.search}function jt({url:e,type:t,intent:n,delta:a,event:r,scroll:i}){let s=!1;const o=tt(_,n,e,t,i??null);a!==void 0&&(o.navigation.delta=a),r!==void 0&&(o.navigation.event=r);const l={...o.navigation,cancel:()=>{s=!0,o.reject(new Error("navigation cancelled"))}};return re||Lt.forEach(c=>c(l)),s?null:o}async function G({type:e,url:t,popped:n,keepfocus:a,noscroll:r,replace_state:i,state:s={},redirect_count:o=0,nav_token:l={},accept:c=C,block:d=C,event:u}){var B;const w=z;z=l;const p=await Te(t,!1),f=e==="enter"?tt(_,p,t,e):jt({url:t,type:e,delta:n==null?void 0:n.delta,intent:p,scroll:n==null?void 0:n.scroll,event:u});if(!f){d(),z===l&&(z=w);return}const m=k,h=L;c(),re=!0,Ee&&f.navigation.type!=="enter"&&j.navigating.set(ee.current=f.navigation);let g=p&&await Ct(p);if(!g){if(Ae(t,U,S.hash))return await ne(t,i);g=await Nt(t,{id:null},await ae(new Fe(404,"Not Found",`Not found: ${t.pathname}`),{url:t,params:{},route:{id:null}}),404,i)}if(t=(p==null?void 0:p.url)||t,z!==l)return f.reject(new Error("navigation aborted")),!1;if(g.type==="redirect"){if(o<20){await G({type:e,url:new URL(g.location,t),popped:n,keepfocus:a,noscroll:r,replace_state:i,state:s,redirect_count:o+1,nav_token:l}),f.fulfil(void 0);return}g=await et({status:500,error:await ae(new Error("Redirect loop"),{url:t,params:{},route:{id:null}}),url:t,route:{id:null}})}else g.props.page.status>=400&&await j.updated.check()&&(await xt(),await ne(t,i));if(gn(),Je(m),It(h),g.props.page.url.pathname!==t.pathname&&(t.pathname=g.props.page.url.pathname),s=n?n.state:s,!n){const E=i?0:1,H={[F]:k+=E,[Z]:L+=E,[bt]:s};(i?history.replaceState:history.pushState).call(history,H,"",t),i||hn(k,L)}const b=p&&(v==null?void 0:v.id)===p.id?v.fork:null;v!=null&&v.fork&&!b&&Se(),v=null,g.props.page.state=s;let x;if(Ee){const E=(await Promise.all(Array.from(pn,W=>W(f.navigation)))).filter(W=>typeof W=="function");if(E.length>0){let W=function(){E.forEach(Oe=>{Q.delete(Oe)})};E.push(W),E.forEach(Oe=>{Q.add(Oe)})}const H=f.navigation.to;_={...g.state,nav:{params:H.params,route:H.route,url:H.url}},g.props.page&&(g.props.page.url=t);const Ie=b&&await b;Ie?x=Ie.commit():(J=null,Tt.$set(g.props),J&&Object.assign(g.props.page,J),un(g.props.page),x=(B=Vt)==null?void 0:B()),At=!0}else await $t(g,ze,!1);const{activeElement:$}=document;await x,await we(),await we();let q=null;if(ct){const E=n?n.scroll:r?V():null;E?scrollTo(E.x,E.y):(q=t.hash&&document.getElementById(qt(t)))?q.scrollIntoView():scrollTo(0,0)}const ge=document.activeElement!==$&&document.activeElement!==document.body;!a&&!ge&&An(t,!q),ct=!0,g.props.page&&(J&&Object.assign(g.props.page,J),Object.assign(R,g.props.page)),re=!1,e==="popstate"&&Ot(L),f.fulfil(void 0),f.navigation.to&&(f.navigation.to.scroll=V()),Q.forEach(E=>E(f.navigation)),j.navigating.set(ee.current=null)}async function Nt(e,t,n,a,r){return e.origin===Ue&&e.pathname===location.pathname&&!Ut?await et({status:a,error:n,url:e,route:t}):await ne(e,r)}function En(){let e,t={element:void 0,href:void 0},n;P.addEventListener("mousemove",o=>{const l=o.target;clearTimeout(e),e=setTimeout(()=>{i(l,D.hover)},20)});function a(o){o.defaultPrevented||i(o.composedPath()[0],D.tap)}P.addEventListener("mousedown",a),P.addEventListener("touchstart",a,{passive:!0});const r=new IntersectionObserver(o=>{for(const l of o)l.isIntersecting&&(Ne(new URL(l.target.href)),r.unobserve(l.target))},{threshold:0});async function i(o,l){const c=St(o,P),d=c===t.element&&(c==null?void 0:c.href)===t.href&&l>=n;if(!c||d)return;const{url:u,external:w,download:p}=qe(c,U,S.hash);if(w||p)return;const f=ve(c),m=u&&Le(_.url)===Le(u);if(!(f.reload||m))if(l<=f.preload_data){t={element:c,href:c.href},n=D.tap;const h=await Te(u,!1);if(!h)return;mn(h)}else l<=f.preload_code&&(t={element:c,href:c.href},n=l,Ne(u))}function s(){r.disconnect();for(const o of P.querySelectorAll("a")){const{url:l,external:c,download:d}=qe(o,U,S.hash);if(c||d)continue;const u=ve(o);u.reload||(u.preload_code===D.viewport&&r.observe(o),u.preload_code===D.eager&&Ne(l))}}Q.add(s),s()}function ae(e,t){if(e instanceof Ke)return e.body;const n=We(e),a=cn(e);return S.hooks.handleError({error:e,event:t,status:n,message:a})??{message:a}}function qn(e,t={}){return e=new URL(He(e)),e.origin!==Ue?Promise.reject(new Error("goto: invalid URL")):Pt(e,t,0)}function Rn(e){if(typeof e=="function")be.push(e);else{const{href:t}=new URL(e,location.href);be.push(n=>n.href===t)}}function xn(){var t;history.scrollRestoration="manual",addEventListener("beforeunload",n=>{let a=!1;if(dt(),!re){const r=tt(_,void 0,null,"leave"),i={...r.navigation,cancel:()=>{a=!0,r.reject(new Error("navigation cancelled"))}};Lt.forEach(s=>s(i))}a?(n.preventDefault(),n.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&dt()}),(t=navigator.connection)!=null&&t.saveData||En(),P.addEventListener("click",async n=>{if(n.button||n.which!==1||n.metaKey||n.ctrlKey||n.shiftKey||n.altKey||n.defaultPrevented)return;const a=St(n.composedPath()[0],P);if(!a)return;const{url:r,external:i,target:s,download:o}=qe(a,U,S.hash);if(!r)return;if(s==="_parent"||s==="_top"){if(window.parent!==window)return}else if(s&&s!=="_self")return;const l=ve(a);if(!(a instanceof SVGAElement)&&r.protocol!==location.protocol&&!(r.protocol==="https:"||r.protocol==="http:")||o)return;const[d,u]=(S.hash?r.hash.replace(/^#/,""):r.href).split("#"),w=d===$e(location);if(i||l.reload&&(!w||!u)){jt({url:r,type:"link",event:n})?re=!0:n.preventDefault();return}if(u!==void 0&&w){const[,p]=_.url.href.split("#");if(p===u){if(n.preventDefault(),u===""||u==="top"&&a.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const f=a.ownerDocument.getElementById(decodeURIComponent(u));f&&(f.scrollIntoView(),f.focus())}return}if(Y=!0,Je(k),e(r),!l.replace_state)return;Y=!1}n.preventDefault(),await new Promise(p=>{requestAnimationFrame(()=>{setTimeout(p,0)}),setTimeout(p,100)}),await G({type:"link",url:r,keepfocus:l.keepfocus,noscroll:l.noscroll,replace_state:l.replace_state??r.href===location.href,event:n})}),P.addEventListener("submit",n=>{if(n.defaultPrevented)return;const a=HTMLFormElement.prototype.cloneNode.call(n.target),r=n.submitter;if(((r==null?void 0:r.formTarget)||a.target)==="_blank"||((r==null?void 0:r.formMethod)||a.method)!=="get")return;const o=new URL((r==null?void 0:r.hasAttribute("formaction"))&&(r==null?void 0:r.formAction)||a.action);if(Ae(o,U,!1))return;const l=n.target,c=ve(l);if(c.reload)return;n.preventDefault(),n.stopPropagation();const d=new FormData(l,r);o.search=new URLSearchParams(d).toString(),G({type:"form",url:o,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??o.href===location.href,event:n})}),addEventListener("popstate",async n=>{var a;if(!Ve){if((a=n.state)!=null&&a[F]){const r=n.state[F];if(z={},r===k)return;const i=N[r],s=n.state[bt]??{},o=new URL(n.state[an]??location.href),l=n.state[Z],c=_.url?$e(location)===$e(_.url):!1;if(l===L&&(At||c)){s!==R.state&&(R.state=s),e(o),N[k]=V(),i&&scrollTo(i.x,i.y),k=r;return}const u=r-k;await G({type:"popstate",url:o,popped:{state:s,scroll:i,delta:u},accept:()=>{k=r,L=l},block:()=>{history.go(-u)},nav_token:z,event:n})}else if(!Y){const r=new URL(location.href);e(r),S.hash&&location.reload()}}}),addEventListener("hashchange",()=>{Y&&(Y=!1,history.replaceState({...history.state,[F]:++k,[Z]:L},"",location.href))});for(const n of document.querySelectorAll("link"))dn.has(n.rel)&&(n.href=n.href);addEventListener("pageshow",n=>{n.persisted&&j.navigating.set(ee.current=null)});function e(n){_.url=R.url=n,j.page.set(nt(R)),j.page.notify()}}async function Ln(e,{status:t=200,error:n,node_ids:a,params:r,route:i,server_route:s,data:o,form:l}){Ut=!0;const c=new URL(location.href);let d;({params:r={},route:i={id:null}}=await Te(c,!1)||{}),d=Ye.find(({id:p})=>p===i.id);let u,w=!0;try{const p=a.map(async(m,h)=>{const g=o[h];return g!=null&&g.uses&&(g.uses=Un(g.uses)),Qe({loader:S.nodes[m],url:c,params:r,route:i,parent:async()=>{const b={};for(let x=0;x<h;x+=1)Object.assign(b,(await p[x]).data);return b},server_data_node:Ze(g)})}),f=await Promise.all(p);if(d){const m=d.layouts;for(let h=0;h<m.length;h++)m[h]||f.splice(h,0,void 0)}u=await xe({url:c,params:r,branch:f,status:t,error:n,errors:d==null?void 0:d.errors,form:l,route:d??null})}catch(p){if(p instanceof Me){await ne(new URL(p.location,location.href));return}u=await et({status:We(p),error:await ae(p,{url:c,params:r,route:i}),url:c,route:i}),e.textContent="",w=!1}finally{}u.props.page&&(u.props.page.state={}),await $t(u,e,w)}function Un(e){return{dependencies:new Set((e==null?void 0:e.dependencies)??[]),params:new Set((e==null?void 0:e.params)??[]),parent:!!(e!=null&&e.parent),route:!!(e!=null&&e.route),url:!!(e!=null&&e.url),search_params:new Set((e==null?void 0:e.search_params)??[])}}let Ve=!1;function An(e,t=!0){const n=document.querySelector("[autofocus]");if(n)n.focus();else{const a=qt(e);if(a&&document.getElementById(a)){const{x:i,y:s}=V();setTimeout(()=>{const o=history.state;Ve=!0,location.replace(new URL(`#${a}`,location.href)),history.replaceState(o,"",e),t&&scrollTo(i,s),Ve=!1})}else{const i=document.body,s=i.getAttribute("tabindex");i.tabIndex=-1,i.focus({preventScroll:!0,focusVisible:!1}),s!==null?i.setAttribute("tabindex",s):i.removeAttribute("tabindex")}const r=getSelection();if(r&&r.type!=="None"){const i=[];for(let s=0;s<r.rangeCount;s+=1)i.push(r.getRangeAt(s));setTimeout(()=>{if(r.rangeCount===i.length){for(let s=0;s<r.rangeCount;s+=1){const o=i[s],l=r.getRangeAt(s);if(o.commonAncestorContainer!==l.commonAncestorContainer||o.startContainer!==l.startContainer||o.endContainer!==l.endContainer||o.startOffset!==l.startOffset||o.endOffset!==l.endOffset)return}r.removeAllRanges()}})}}}function tt(e,t,n,a,r=null){var c,d;let i,s;const o=new Promise((u,w)=>{i=u,s=w});return o.catch(C),{navigation:{from:{params:e.params,route:{id:((c=e.route)==null?void 0:c.id)??null},url:e.url,scroll:V()},to:n&&{params:(t==null?void 0:t.params)??null,route:{id:((d=t==null?void 0:t.route)==null?void 0:d.id)??null},url:n,scroll:r},willUnload:!t,type:a,complete:o},fulfil:i,reject:s}}function nt(e){return{data:e.data,error:e.error,form:e.form,params:e.params,route:e.route,state:e.state,status:e.status,url:e.url}}function Tn(e){const t=new URL(e);return t.hash=decodeURIComponent(e.hash),t}function qt(e){let t;if(S.hash){const[,,n]=e.hash.split("#",3);t=n??""}else t=e.hash.slice(1);return decodeURIComponent(t)}export{Nn as a,qn as g,Pn as l,R as p,j as s};
|
|
|
|
|
|
web/sveltekit/build/_app/immutable/chunks/DtzoFJKK.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
var rt=e=>{throw TypeError(e)};var Dt=(e,t,n)=>t.has(e)||rt("Cannot "+n);var y=(e,t,n)=>(Dt(e,t,"read from private field"),n?n.call(e):t.get(e)),A=(e,t,n)=>t.has(e)?rt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n);import{bf as Pe,bg as Vt,ai as at,a4 as T,o as I,a5 as O,ar as we,bh as Bt}from"./BTUA7_xE.js";const M=[];function Ke(e,t=Pe){let n=null;const a=new Set;function r(o){if(Vt(e,o)&&(e=o,n)){const l=!M.length;for(const c of a)c[1](),M.push(c,e);if(l){for(let c=0;c<M.length;c+=2)M[c][0](M[c+1]);M.length=0}}}function i(o){r(o(e))}function s(o,l=Pe){const c=[o,l];return a.add(c),a.size===1&&(n=t(r,i)||Pe),o(e),()=>{a.delete(c),a.size===0&&n&&(n(),n=null)}}return{set:r,update:i,subscribe:s}}class Me{constructor(t,n){this.status=t,typeof n=="string"?this.body={message:n}:n?this.body=n:this.body={message:`Error: ${t}`}}toString(){return JSON.stringify(this.body)}}class ze{constructor(t,n){try{new Headers({location:n})}catch{throw new Error(`Invalid redirect location ${JSON.stringify(n)}: this string contains characters that cannot be used in HTTP headers`)}this.status=t,this.location=n}}class Fe extends Error{constructor(t,n,a){super(a),this.status=t,this.text=n}}new URL("sveltekit-internal://");function Kt(e,t){return e==="/"||t==="ignore"?e:t==="never"?e.endsWith("/")?e.slice(0,-1):e:t==="always"&&!e.endsWith("/")?e+"/":e}function Mt(e){return e.split("%25").map(decodeURI).join("%25")}function zt(e){for(const t in e)e[t]=decodeURIComponent(e[t]);return e}function je({href:e}){return e.split("#")[0]}function $(){}function Ft(...e){let t=5381;for(const n of e)if(typeof n=="string"){let a=n.length;for(;a;)t=t*33^n.charCodeAt(--a)}else if(ArrayBuffer.isView(n)){const a=new Uint8Array(n.buffer,n.byteOffset,n.byteLength);let r=a.length;for(;r;)t=t*33^a[--r]}else throw new TypeError("value must be a string or TypedArray");return(t>>>0).toString(36)}new TextEncoder;function Gt(e){const t=atob(e),n=new Uint8Array(t.length);for(let a=0;a<t.length;a++)n[a]=t.charCodeAt(a);return n}const Ht=window.fetch;window.fetch=(e,t)=>((e instanceof Request?e.method:(t==null?void 0:t.method)||"GET")!=="GET"&&X.delete(Ge(e)),Ht(e,t));const X=new Map;function Wt(e,t){const n=Ge(e,t),a=document.querySelector(n);if(a!=null&&a.textContent){a.remove();let{body:r,...i}=JSON.parse(a.textContent);const s=a.getAttribute("data-ttl");return s&&X.set(n,{body:r,init:i,ttl:1e3*Number(s)}),a.getAttribute("data-b64")!==null&&(r=Gt(r)),Promise.resolve(new Response(r,i))}return window.fetch(e,t)}function Jt(e,t,n){if(X.size>0){const a=Ge(e,n),r=X.get(a);if(r){if(performance.now()<r.ttl&&["default","force-cache","only-if-cached",void 0].includes(n==null?void 0:n.cache))return new Response(r.body,r.init);X.delete(a)}}return window.fetch(t,n)}function Ge(e,t){let a=`script[data-sveltekit-fetched][data-url=${JSON.stringify(e instanceof Request?e.url:e)}]`;if(t!=null&&t.headers||t!=null&&t.body){const r=[];t.headers&&r.push([...new Headers(t.headers)].join(",")),t.body&&(typeof t.body=="string"||ArrayBuffer.isView(t.body))&&r.push(t.body),a+=`[data-hash="${Ft(...r)}"]`}return a}const Yt=/^(\[)?(\.\.\.)?(\w+)(?:=(\w+))?(\])?$/;function Xt(e){const t=[];return{pattern:e==="/"?/^\/$/:new RegExp(`^${Zt(e).map(a=>{const r=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(a);if(r)return t.push({name:r[1],matcher:r[2],optional:!1,rest:!0,chained:!0}),"(?:/([^]*))?";const i=/^\[\[(\w+)(?:=(\w+))?\]\]$/.exec(a);if(i)return t.push({name:i[1],matcher:i[2],optional:!0,rest:!1,chained:!0}),"(?:/([^/]+))?";if(!a)return;const s=a.split(/\[(.+?)\](?!\])/);return"/"+s.map((l,c)=>{if(c%2){if(l.startsWith("x+"))return $e(String.fromCharCode(parseInt(l.slice(2),16)));if(l.startsWith("u+"))return $e(String.fromCharCode(...l.slice(2).split("-").map(m=>parseInt(m,16))));const d=Yt.exec(l),[,u,w,p,f]=d;return t.push({name:p,matcher:f,optional:!!u,rest:!!w,chained:w?c===1&&s[0]==="":!1}),w?"([^]*?)":u?"([^/]*)?":"([^/]+?)"}return $e(l)}).join("")}).join("")}/?$`),params:t}}function Qt(e){return e!==""&&!/^\([^)]+\)$/.test(e)}function Zt(e){return e.slice(1).split("/").filter(Qt)}function en(e,t,n){const a={},r=e.slice(1),i=r.filter(o=>o!==void 0);let s=0;for(let o=0;o<t.length;o+=1){const l=t[o];let c=r[o-s];if(l.chained&&l.rest&&s&&(c=r.slice(o-s,o+1).filter(d=>d).join("/"),s=0),c===void 0)if(l.rest)c="";else continue;if(!l.matcher||n[l.matcher](c)){a[l.name]=c;const d=t[o+1],u=r[o+1];d&&!d.rest&&d.optional&&u&&l.chained&&(s=0),!d&&!u&&Object.keys(a).length===i.length&&(s=0);continue}if(l.optional&&l.chained){s++;continue}return}if(!s)return a}function $e(e){return e.normalize().replace(/[[\]]/g,"\\$&").replace(/%/g,"%25").replace(/\//g,"%2[Ff]").replace(/\?/g,"%3[Ff]").replace(/#/g,"%23").replace(/[.*+?^${}()|\\]/g,"\\$&")}function tn({nodes:e,server_loads:t,dictionary:n,matchers:a}){const r=new Set(t);return Object.entries(n).map(([o,[l,c,d]])=>{const{pattern:u,params:w}=Xt(o),p={id:o,exec:f=>{const m=u.exec(f);if(m)return en(m,w,a)},errors:[1,...d||[]].map(f=>e[f]),layouts:[0,...c||[]].map(s),leaf:i(l)};return p.errors.length=p.layouts.length=Math.max(p.errors.length,p.layouts.length),p});function i(o){const l=o<0;return l&&(o=~o),[l,e[o]]}function s(o){return o===void 0?o:[r.has(o),e[o]]}}function wt(e,t=JSON.parse){try{return t(sessionStorage[e])}catch{}}function ot(e,t,n=JSON.stringify){const a=n(t);try{sessionStorage[e]=a}catch{}}var ht;const U=((ht=globalThis.__sveltekit_1h3t6jb)==null?void 0:ht.base)??"";var pt;const nn=((pt=globalThis.__sveltekit_1h3t6jb)==null?void 0:pt.assets)??U??"",rn="1778092701107",vt="sveltekit:snapshot",yt="sveltekit:scroll",bt="sveltekit:states",an="sveltekit:pageurl",F="sveltekit:history",Z="sveltekit:navigation",D={tap:1,hover:2,viewport:3,eager:4,off:-1,false:-1},Ue=location.origin;function He(e){if(e instanceof URL)return e;let t=document.baseURI;if(!t){const n=document.getElementsByTagName("base");t=n.length?n[0].href:document.URL}return new URL(e,t)}function B(){return{x:pageXOffset,y:pageYOffset}}function z(e,t){return e.getAttribute(`data-sveltekit-${t}`)}const st={...D,"":D.hover};function kt(e){let t=e.assignedSlot??e.parentNode;return(t==null?void 0:t.nodeType)===11&&(t=t.host),t}function St(e,t){for(;e&&e!==t;){if(e.nodeName.toUpperCase()==="A"&&e.hasAttribute("href"))return e;e=kt(e)}}function qe(e,t,n){let a;try{if(a=new URL(e instanceof SVGAElement?e.href.baseVal:e.href,document.baseURI),n&&a.hash.match(/^#[^/]/)){const o=location.hash.split("#")[1]||"/";a.hash=`#${o}${a.hash}`}}catch{}const r=e instanceof SVGAElement?e.target.baseVal:e.target,i=!a||!!r||Ae(a,t,n)||(e.getAttribute("rel")||"").split(/\s+/).includes("external"),s=(a==null?void 0:a.origin)===Ue&&e.hasAttribute("download");return{url:a,external:i,target:r,download:s}}function ve(e){let t=null,n=null,a=null,r=null,i=null,s=null,o=e;for(;o&&o!==document.documentElement;)a===null&&(a=z(o,"preload-code")),r===null&&(r=z(o,"preload-data")),t===null&&(t=z(o,"keepfocus")),n===null&&(n=z(o,"noscroll")),i===null&&(i=z(o,"reload")),s===null&&(s=z(o,"replacestate")),o=kt(o);function l(c){switch(c){case"":case"true":return!0;case"off":case"false":return!1;default:return}}return{preload_code:st[a??"off"],preload_data:st[r??"off"],keepfocus:l(t),noscroll:l(n),reload:l(i),replace_state:l(s)}}function it(e){const t=Ke(e);let n=!0;function a(){n=!0,t.update(s=>s)}function r(s){n=!1,t.set(s)}function i(s){let o;return t.subscribe(l=>{(o===void 0||n&&l!==o)&&s(o=l)})}return{notify:a,set:r,subscribe:i}}const Et={v:$};function on(){const{set:e,subscribe:t}=Ke(!1);let n;async function a(){clearTimeout(n);try{const r=await fetch(`${nn}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(!r.ok)return!1;const s=(await r.json()).version!==rn;return s&&(e(!0),Et.v(),clearTimeout(n)),s}catch{return!1}}return{subscribe:t,check:a}}function Ae(e,t,n){return e.origin!==Ue||!e.pathname.startsWith(t)?!0:n?e.pathname!==location.pathname:!1}function Pn(e){}const Rt=new Set(["load","prerender","csr","ssr","trailingSlash","config"]);[...Rt];const sn=new Set([...Rt]);[...sn];function ln(e){return e.filter(t=>t!=null)}function me(e,t){return e+"/"+t}function We(e){return e instanceof Me||e instanceof Fe?e.status:500}function cn(e){return e instanceof Fe?e.text:"Internal Error"}let R,ee,Ce;const fn=at.toString().includes("$$")||/function \w+\(\) \{\}/.test(at.toString()),lt="a:";var oe,se,ie,le,ce,fe,ue,de,gt,he,mt,pe,_t;fn?(R={data:{},form:null,error:null,params:{},route:{id:null},state:{},status:-1,url:new URL(lt)},ee={current:null},Ce={current:!1}):(R=new(gt=class{constructor(){A(this,oe,T({}));A(this,se,T(null));A(this,ie,T(null));A(this,le,T({}));A(this,ce,T({id:null}));A(this,fe,T({}));A(this,ue,T(-1));A(this,de,T(new URL(lt)))}get data(){return I(y(this,oe))}set data(t){O(y(this,oe),t)}get form(){return I(y(this,se))}set form(t){O(y(this,se),t)}get error(){return I(y(this,ie))}set error(t){O(y(this,ie),t)}get params(){return I(y(this,le))}set params(t){O(y(this,le),t)}get route(){return I(y(this,ce))}set route(t){O(y(this,ce),t)}get state(){return I(y(this,fe))}set state(t){O(y(this,fe),t)}get status(){return I(y(this,ue))}set status(t){O(y(this,ue),t)}get url(){return I(y(this,de))}set url(t){O(y(this,de),t)}},oe=new WeakMap,se=new WeakMap,ie=new WeakMap,le=new WeakMap,ce=new WeakMap,fe=new WeakMap,ue=new WeakMap,de=new WeakMap,gt),ee=new(mt=class{constructor(){A(this,he,T(null))}get current(){return I(y(this,he))}set current(t){O(y(this,he),t)}},he=new WeakMap,mt),Ce=new(_t=class{constructor(){A(this,pe,T(!1))}get current(){return I(y(this,pe))}set current(t){O(y(this,pe),t)}},pe=new WeakMap,_t),Et.v=()=>Ce.current=!0);function un(e){Object.assign(R,e)}const dn=new Set(["icon","shortcut icon","apple-touch-icon"]);let J=null;const N=wt(yt)??{},te=wt(vt)??{},C={url:it({}),page:it({}),navigating:Ke(null),updated:on()};function Je(e){N[e]=B()}function hn(e,t){let n=e+1;for(;N[n];)delete N[n],n+=1;for(n=t+1;te[n];)delete te[n],n+=1}function ne(e,t=!1){return t?location.replace(e.href):location.href=e.href,new Promise($)}async function xt(){if("serviceWorker"in navigator){const e=await navigator.serviceWorker.getRegistration(U||"/");e&&await e.update()}}let Ye,De,ye,P,Ve,S;const be=[],ke=[];let v=null;function Se(){var e;(e=v==null?void 0:v.fork)==null||e.then(t=>t==null?void 0:t.discard()),v=null}const _e=new Map,Lt=new Set,pn=new Set,Q=new Set;let _={branch:[],error:null,url:null},Ut=!1,Ee=!1,ct=!0,re=!1,Y=!1,At=!1,Xe=!1,Tt,k,L,V;const Re=new Set,ft=new Map,ut=new Map;async function Nn(e,t,n){var i,s,o,l;globalThis.__sveltekit_1h3t6jb&&(globalThis.__sveltekit_1h3t6jb.query,globalThis.__sveltekit_1h3t6jb.prerender),document.URL!==location.href&&(location.href=location.href),S=e,await((s=(i=e.hooks).init)==null?void 0:s.call(i)),Ye=tn(e),P=document.documentElement,Ve=t,De=e.nodes[0],ye=e.nodes[1],De(),ye(),k=(o=history.state)==null?void 0:o[F],L=(l=history.state)==null?void 0:l[Z],k||(k=L=Date.now(),history.replaceState({...history.state,[F]:k,[Z]:L},""));const a=N[k];function r(){a&&(history.scrollRestoration="manual",scrollTo(a.x,a.y))}n?(r(),await Ln(Ve,n)):(await G({type:"enter",url:He(S.hash?Tn(new URL(location.href)):location.href),replace_state:!0}),r()),xn()}function gn(){be.length=0,Xe=!1}function It(e){ke.some(t=>t==null?void 0:t.snapshot)&&(te[e]=ke.map(t=>{var n;return(n=t==null?void 0:t.snapshot)==null?void 0:n.capture()}))}function Ot(e){var t;(t=te[e])==null||t.forEach((n,a)=>{var r,i;(i=(r=ke[a])==null?void 0:r.snapshot)==null||i.restore(n)})}function dt(){Je(k),ot(yt,N),It(L),ot(vt,te)}async function Pt(e,t,n,a){let r,i;t.invalidateAll&&Se(),await G({type:"goto",url:He(e),keepfocus:t.keepFocus,noscroll:t.noScroll,replace_state:t.replaceState,state:t.state,redirect_count:n,nav_token:a,accept:()=>{if(t.invalidateAll){Xe=!0,r=new Set;for(const[s,o]of ft)for(const l of o.keys())r.add(me(s,l));i=new Set;for(const[s,o]of ut)for(const l of o.keys())i.add(me(s,l))}t.invalidate&&t.invalidate.forEach(Rn)}}),t.invalidateAll&&we().then(we).then(()=>{for(const[s,o]of ft)for(const[l,{resource:c}]of o)r!=null&&r.has(me(s,l))&&c.refresh();for(const[s,o]of ut)for(const[l,{resource:c}]of o)i!=null&&i.has(me(s,l))&&c.reconnect()})}async function mn(e){if(e.id!==(v==null?void 0:v.id)){Se();const t={};Re.add(t),v={id:e.id,token:t,promise:$t({...e,preload:t}).then(n=>(Re.delete(t),n.type==="loaded"&&n.state.error&&Se(),n)),fork:null}}return v.promise}async function Ne(e){var n;const t=(n=await Te(e,!1))==null?void 0:n.route;t&&await Promise.all([...t.layouts,t.leaf].filter(Boolean).map(a=>a[1]()))}async function jt(e,t,n){var i;const a={params:_.params,route:{id:((i=_.route)==null?void 0:i.id)??null},url:new URL(location.href)};_={...e.state,nav:a};const r=document.querySelector("style[data-sveltekit]");if(r&&r.remove(),Object.assign(R,e.props.page),Tt=new S.root({target:t,props:{...e.props,stores:C,components:ke},hydrate:n,sync:!1,transformError:void 0}),await Promise.resolve(),Ot(L),n){const s={from:null,to:{...a,scroll:N[k]??B()},willUnload:!1,type:"enter",complete:Promise.resolve()};Q.forEach(o=>o(s))}Ee=!0}async function xe({url:e,params:t,branch:n,errors:a,status:r,error:i,route:s,form:o}){let l="never";if(U&&(e.pathname===U||e.pathname===U+"/"))l="always";else for(const f of n)(f==null?void 0:f.slash)!==void 0&&(l=f.slash);e.pathname=Kt(e.pathname,l),e.search=e.search;const c={type:"loaded",state:{url:e,params:t,branch:n,error:i,route:s},props:{constructors:ln(n).map(f=>f.node.component),page:nt(R)}};o!==void 0&&(c.props.form=o);let d={},u=!R,w=0;for(let f=0;f<Math.max(n.length,_.branch.length);f+=1){const m=n[f],h=_.branch[f];(m==null?void 0:m.data)!==(h==null?void 0:h.data)&&(u=!0),m&&(d={...d,...m.data},u&&(c.props[`data_${w}`]=d),w+=1)}return(!_.url||e.href!==_.url.href||_.error!==i||o!==void 0&&o!==R.form||u)&&(c.props.page={error:i,params:t,route:{id:(s==null?void 0:s.id)??null},state:{},status:r,url:new URL(e),form:o??null,data:u?d:R.data}),c}async function Qe({loader:e,parent:t,url:n,params:a,route:r,server_data_node:i}){var c,d;let s=null;const o={dependencies:new Set,params:new Set,parent:!1,route:!1,url:!1,search_params:new Set},l=await e();return{node:l,loader:e,server:i,universal:(c=l.universal)!=null&&c.load?{type:"data",data:s,uses:o}:null,data:s??(i==null?void 0:i.data)??null,slash:((d=l.universal)==null?void 0:d.trailingSlash)??(i==null?void 0:i.slash)}}function _n(e,t,n){let a=e instanceof Request?e.url:e;const r=new URL(a,n);r.origin===n.origin&&(a=r.href.slice(n.origin.length));const i=Ee?Jt(a,r.href,t):Wt(a,t);return{resolved:r,promise:i}}function wn(e,t,n,a,r,i){if(Xe)return!0;if(!r)return!1;if(r.parent&&e||r.route&&t||r.url&&n)return!0;for(const s of r.search_params)if(a.has(s))return!0;for(const s of r.params)if(i[s]!==_.params[s])return!0;for(const s of r.dependencies)if(be.some(o=>o(new URL(s))))return!0;return!1}function Ze(e,t){return(e==null?void 0:e.type)==="data"?e:(e==null?void 0:e.type)==="skip"?t??null:null}function vn(e,t){if(!e)return new Set(t.searchParams.keys());const n=new Set([...e.searchParams.keys(),...t.searchParams.keys()]);for(const a of n){const r=e.searchParams.getAll(a),i=t.searchParams.getAll(a);r.every(s=>i.includes(s))&&i.every(s=>r.includes(s))&&n.delete(a)}return n}function yn({error:e,url:t,route:n,params:a}){return{type:"loaded",state:{error:e,url:t,route:n,params:a,branch:[]},props:{page:nt(R),constructors:[]}}}async function $t({id:e,invalidating:t,url:n,params:a,route:r,preload:i}){if((v==null?void 0:v.id)===e)return Re.delete(v.token),v.promise;const{errors:s,layouts:o,leaf:l}=r,c=[...o,l];s.forEach(h=>h==null?void 0:h().catch($)),c.forEach(h=>h==null?void 0:h[1]().catch($));const d=_.url?e!==Le(_.url):!1,u=_.route?r.id!==_.route.id:!1,w=vn(_.url,n);let p=!1;const f=c.map(async(h,g)=>{var j;if(!h)return;const b=_.branch[g];return h[1]===(b==null?void 0:b.loader)&&!wn(p,u,d,w,(j=b.universal)==null?void 0:j.uses,a)?b:(p=!0,Qe({loader:h[1],url:n,params:a,route:r,parent:async()=>{var ge;const q={};for(let K=0;K<g;K+=1)Object.assign(q,(ge=await f[K])==null?void 0:ge.data);return q},server_data_node:Ze(h[0]?{type:"skip"}:null,h[0]?b==null?void 0:b.server:void 0)}))});for(const h of f)h.catch($);const m=[];for(let h=0;h<c.length;h+=1)if(c[h])try{m.push(await f[h])}catch(g){if(g instanceof ze)return{type:"redirect",location:g.location};if(Re.has(i))return yn({error:await ae(g,{params:a,url:n,route:{id:r.id}}),url:n,params:a,route:r});let b=We(g),x;if(g instanceof Me)x=g.body;else{if(await C.updated.check())return await xt(),await ne(n);x=await ae(g,{params:a,url:n,route:{id:r.id}})}const j=await bn(h,m,s);return j?xe({url:n,params:a,branch:m.slice(0,j.idx).concat(j.node),errors:s,status:b,error:x,route:r}):await Nt(n,{id:r.id},x,b)}else m.push(void 0);return xe({url:n,params:a,branch:m,errors:s,status:200,error:null,route:r,form:t?void 0:null})}async function bn(e,t,n){for(;e--;)if(n[e]){let a=e;for(;!t[a];)a-=1;try{return{idx:a+1,node:{node:await n[e](),loader:n[e],data:{},server:null,universal:null}}}catch{continue}}}async function et({status:e,error:t,url:n,route:a}){const r={};let i=null;try{const s=await Qe({loader:De,url:n,params:r,route:a,parent:()=>Promise.resolve({}),server_data_node:Ze(i)}),o={node:await ye(),loader:ye,universal:null,server:null,data:null};return xe({url:n,params:r,branch:[s,o],status:e,error:t,errors:[],route:null})}catch(s){if(s instanceof ze)return Pt(new URL(s.location,location.href),{},0);throw s}}async function kn(e){const t=e.href;if(_e.has(t))return _e.get(t);let n;try{const a=(async()=>{let r=await S.hooks.reroute({url:new URL(e),fetch:async(i,s)=>_n(i,s,e).promise})??e;if(typeof r=="string"){const i=new URL(e);S.hash?i.hash=r:i.pathname=r,r=i}return r})();_e.set(t,a),n=await a}catch{_e.delete(t);return}return n}async function Te(e,t){if(e&&!Ae(e,U,S.hash)){const n=await kn(e);if(!n)return;const a=Sn(n);for(const r of Ye){const i=r.exec(a);if(i)return{id:Le(e),invalidating:t,route:r,params:zt(i),url:e}}}}function Sn(e){return Mt(S.hash?e.hash.replace(/^#/,"").replace(/[?#].+/,""):e.pathname.slice(U.length))||"/"}function Le(e){return(S.hash?e.hash.replace(/^#/,""):e.pathname)+e.search}function Ct({url:e,type:t,intent:n,delta:a,event:r,scroll:i}){let s=!1;const o=tt(_,n,e,t,i??null);a!==void 0&&(o.navigation.delta=a),r!==void 0&&(o.navigation.event=r);const l={...o.navigation,cancel:()=>{s=!0,o.reject(new Error("navigation cancelled"))}};return re||Lt.forEach(c=>c(l)),s?null:o}async function G({type:e,url:t,popped:n,keepfocus:a,noscroll:r,replace_state:i,state:s={},redirect_count:o=0,nav_token:l={},accept:c=$,block:d=$,event:u}){var K;const w=V;V=l;const p=await Te(t,!1),f=e==="enter"?tt(_,p,t,e):Ct({url:t,type:e,delta:n==null?void 0:n.delta,intent:p,scroll:n==null?void 0:n.scroll,event:u});if(!f){d(),V===l&&(V=w);return}const m=k,h=L;c(),re=!0,Ee&&f.navigation.type!=="enter"&&C.navigating.set(ee.current=f.navigation);let g=p&&await $t(p);if(!g){if(Ae(t,U,S.hash))return await ne(t,i);g=await Nt(t,{id:null},await ae(new Fe(404,"Not Found",`Not found: ${t.pathname}`),{url:t,params:{},route:{id:null}}),404,i)}if(t=(p==null?void 0:p.url)||t,V!==l)return f.reject(new Error("navigation aborted")),!1;if(g.type==="redirect"){if(o<20){await G({type:e,url:new URL(g.location,t),popped:n,keepfocus:a,noscroll:r,replace_state:i,state:s,redirect_count:o+1,nav_token:l}),f.fulfil(void 0);return}g=await et({status:500,error:await ae(new Error("Redirect loop"),{url:t,params:{},route:{id:null}}),url:t,route:{id:null}})}else g.props.page.status>=400&&await C.updated.check()&&(await xt(),await ne(t,i));if(gn(),Je(m),It(h),g.props.page.url.pathname!==t.pathname&&(t.pathname=g.props.page.url.pathname),s=n?n.state:s,!n){const E=i?0:1,H={[F]:k+=E,[Z]:L+=E,[bt]:s};(i?history.replaceState:history.pushState).call(history,H,"",t),i||hn(k,L)}const b=p&&(v==null?void 0:v.id)===p.id?v.fork:null;v!=null&&v.fork&&!b&&Se(),v=null,g.props.page.state=s;let x;if(Ee){const E=(await Promise.all(Array.from(pn,W=>W(f.navigation)))).filter(W=>typeof W=="function");if(E.length>0){let W=function(){E.forEach(Oe=>{Q.delete(Oe)})};E.push(W),E.forEach(Oe=>{Q.add(Oe)})}const H=f.navigation.to;_={...g.state,nav:{params:H.params,route:H.route,url:H.url}},g.props.page&&(g.props.page.url=t);const Ie=b&&await b;Ie?x=Ie.commit():(J=null,Tt.$set(g.props),J&&Object.assign(g.props.page,J),un(g.props.page),x=(K=Bt)==null?void 0:K()),At=!0}else await jt(g,Ve,!1);const{activeElement:j}=document;await x,await we(),await we();let q=null;if(ct){const E=n?n.scroll:r?B():null;E?scrollTo(E.x,E.y):(q=t.hash&&document.getElementById(qt(t)))?q.scrollIntoView():scrollTo(0,0)}const ge=document.activeElement!==j&&document.activeElement!==document.body;!a&&!ge&&An(t,!q),ct=!0,g.props.page&&(J&&Object.assign(g.props.page,J),Object.assign(R,g.props.page)),re=!1,e==="popstate"&&Ot(L),f.fulfil(void 0),f.navigation.to&&(f.navigation.to.scroll=B()),Q.forEach(E=>E(f.navigation)),C.navigating.set(ee.current=null)}async function Nt(e,t,n,a,r){return e.origin===Ue&&e.pathname===location.pathname&&!Ut?await et({status:a,error:n,url:e,route:t}):await ne(e,r)}function En(){let e,t={element:void 0,href:void 0},n;P.addEventListener("mousemove",o=>{const l=o.target;clearTimeout(e),e=setTimeout(()=>{i(l,D.hover)},20)});function a(o){o.defaultPrevented||i(o.composedPath()[0],D.tap)}P.addEventListener("mousedown",a),P.addEventListener("touchstart",a,{passive:!0});const r=new IntersectionObserver(o=>{for(const l of o)l.isIntersecting&&(Ne(new URL(l.target.href)),r.unobserve(l.target))},{threshold:0});async function i(o,l){const c=St(o,P),d=c===t.element&&(c==null?void 0:c.href)===t.href&&l>=n;if(!c||d)return;const{url:u,external:w,download:p}=qe(c,U,S.hash);if(w||p)return;const f=ve(c),m=u&&Le(_.url)===Le(u);if(!(f.reload||m))if(l<=f.preload_data){t={element:c,href:c.href},n=D.tap;const h=await Te(u,!1);if(!h)return;mn(h)}else l<=f.preload_code&&(t={element:c,href:c.href},n=l,Ne(u))}function s(){r.disconnect();for(const o of P.querySelectorAll("a")){const{url:l,external:c,download:d}=qe(o,U,S.hash);if(c||d)continue;const u=ve(o);u.reload||(u.preload_code===D.viewport&&r.observe(o),u.preload_code===D.eager&&Ne(l))}}Q.add(s),s()}function ae(e,t){if(e instanceof Me)return e.body;const n=We(e),a=cn(e);return S.hooks.handleError({error:e,event:t,status:n,message:a})??{message:a}}function qn(e,t={}){return e=new URL(He(e)),e.origin!==Ue?Promise.reject(new Error("goto: invalid URL")):Pt(e,t,0)}function Rn(e){if(typeof e=="function")be.push(e);else{const{href:t}=new URL(e,location.href);be.push(n=>n.href===t)}}function xn(){var t;history.scrollRestoration="manual",addEventListener("beforeunload",n=>{let a=!1;if(dt(),!re){const r=tt(_,void 0,null,"leave"),i={...r.navigation,cancel:()=>{a=!0,r.reject(new Error("navigation cancelled"))}};Lt.forEach(s=>s(i))}a?(n.preventDefault(),n.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&dt()}),(t=navigator.connection)!=null&&t.saveData||En(),P.addEventListener("click",async n=>{if(n.button||n.which!==1||n.metaKey||n.ctrlKey||n.shiftKey||n.altKey||n.defaultPrevented)return;const a=St(n.composedPath()[0],P);if(!a)return;const{url:r,external:i,target:s,download:o}=qe(a,U,S.hash);if(!r)return;if(s==="_parent"||s==="_top"){if(window.parent!==window)return}else if(s&&s!=="_self")return;const l=ve(a);if(!(a instanceof SVGAElement)&&r.protocol!==location.protocol&&!(r.protocol==="https:"||r.protocol==="http:")||o)return;const[d,u]=(S.hash?r.hash.replace(/^#/,""):r.href).split("#"),w=d===je(location);if(i||l.reload&&(!w||!u)){Ct({url:r,type:"link",event:n})?re=!0:n.preventDefault();return}if(u!==void 0&&w){const[,p]=_.url.href.split("#");if(p===u){if(n.preventDefault(),u===""||u==="top"&&a.ownerDocument.getElementById("top")===null)scrollTo({top:0});else{const f=a.ownerDocument.getElementById(decodeURIComponent(u));f&&(f.scrollIntoView(),f.focus())}return}if(Y=!0,Je(k),e(r),!l.replace_state)return;Y=!1}n.preventDefault(),await new Promise(p=>{requestAnimationFrame(()=>{setTimeout(p,0)}),setTimeout(p,100)}),await G({type:"link",url:r,keepfocus:l.keepfocus,noscroll:l.noscroll,replace_state:l.replace_state??r.href===location.href,event:n})}),P.addEventListener("submit",n=>{if(n.defaultPrevented)return;const a=HTMLFormElement.prototype.cloneNode.call(n.target),r=n.submitter;if(((r==null?void 0:r.formTarget)||a.target)==="_blank"||((r==null?void 0:r.formMethod)||a.method)!=="get")return;const o=new URL((r==null?void 0:r.hasAttribute("formaction"))&&(r==null?void 0:r.formAction)||a.action);if(Ae(o,U,!1))return;const l=n.target,c=ve(l);if(c.reload)return;n.preventDefault(),n.stopPropagation();const d=new FormData(l,r);o.search=new URLSearchParams(d).toString(),G({type:"form",url:o,keepfocus:c.keepfocus,noscroll:c.noscroll,replace_state:c.replace_state??o.href===location.href,event:n})}),addEventListener("popstate",async n=>{var a;if(!Be){if((a=n.state)!=null&&a[F]){const r=n.state[F];if(V={},r===k)return;const i=N[r],s=n.state[bt]??{},o=new URL(n.state[an]??location.href),l=n.state[Z],c=_.url?je(location)===je(_.url):!1;if(l===L&&(At||c)){s!==R.state&&(R.state=s),e(o),N[k]=B(),i&&scrollTo(i.x,i.y),k=r;return}const u=r-k;await G({type:"popstate",url:o,popped:{state:s,scroll:i,delta:u},accept:()=>{k=r,L=l},block:()=>{history.go(-u)},nav_token:V,event:n})}else if(!Y){const r=new URL(location.href);e(r),S.hash&&location.reload()}}}),addEventListener("hashchange",()=>{Y&&(Y=!1,history.replaceState({...history.state,[F]:++k,[Z]:L},"",location.href))});for(const n of document.querySelectorAll("link"))dn.has(n.rel)&&(n.href=n.href);addEventListener("pageshow",n=>{n.persisted&&C.navigating.set(ee.current=null)});function e(n){_.url=R.url=n,C.page.set(nt(R)),C.page.notify()}}async function Ln(e,{status:t=200,error:n,node_ids:a,params:r,route:i,server_route:s,data:o,form:l}){Ut=!0;const c=new URL(location.href);let d;({params:r={},route:i={id:null}}=await Te(c,!1)||{}),d=Ye.find(({id:p})=>p===i.id);let u,w=!0;try{const p=a.map(async(m,h)=>{const g=o[h];return g!=null&&g.uses&&(g.uses=Un(g.uses)),Qe({loader:S.nodes[m],url:c,params:r,route:i,parent:async()=>{const b={};for(let x=0;x<h;x+=1)Object.assign(b,(await p[x]).data);return b},server_data_node:Ze(g)})}),f=await Promise.all(p);if(d){const m=d.layouts;for(let h=0;h<m.length;h++)m[h]||f.splice(h,0,void 0)}u=await xe({url:c,params:r,branch:f,status:t,error:n,errors:d==null?void 0:d.errors,form:l,route:d??null})}catch(p){if(p instanceof ze){await ne(new URL(p.location,location.href));return}u=await et({status:We(p),error:await ae(p,{url:c,params:r,route:i}),url:c,route:i}),e.textContent="",w=!1}finally{}u.props.page&&(u.props.page.state={}),await jt(u,e,w)}function Un(e){return{dependencies:new Set((e==null?void 0:e.dependencies)??[]),params:new Set((e==null?void 0:e.params)??[]),parent:!!(e!=null&&e.parent),route:!!(e!=null&&e.route),url:!!(e!=null&&e.url),search_params:new Set((e==null?void 0:e.search_params)??[])}}let Be=!1;function An(e,t=!0){const n=document.querySelector("[autofocus]");if(n)n.focus();else{const a=qt(e);if(a&&document.getElementById(a)){const{x:i,y:s}=B();setTimeout(()=>{const o=history.state;Be=!0,location.replace(new URL(`#${a}`,location.href)),history.replaceState(o,"",e),t&&scrollTo(i,s),Be=!1})}else{const i=document.body,s=i.getAttribute("tabindex");i.tabIndex=-1,i.focus({preventScroll:!0,focusVisible:!1}),s!==null?i.setAttribute("tabindex",s):i.removeAttribute("tabindex")}const r=getSelection();if(r&&r.type!=="None"){const i=[];for(let s=0;s<r.rangeCount;s+=1)i.push(r.getRangeAt(s));setTimeout(()=>{if(r.rangeCount===i.length){for(let s=0;s<r.rangeCount;s+=1){const o=i[s],l=r.getRangeAt(s);if(o.commonAncestorContainer!==l.commonAncestorContainer||o.startContainer!==l.startContainer||o.endContainer!==l.endContainer||o.startOffset!==l.startOffset||o.endOffset!==l.endOffset)return}r.removeAllRanges()}})}}}function tt(e,t,n,a,r=null){var c,d;let i,s;const o=new Promise((u,w)=>{i=u,s=w});return o.catch($),{navigation:{from:{params:e.params,route:{id:((c=e.route)==null?void 0:c.id)??null},url:e.url,scroll:B()},to:n&&{params:(t==null?void 0:t.params)??null,route:{id:((d=t==null?void 0:t.route)==null?void 0:d.id)??null},url:n,scroll:r},willUnload:!t,type:a,complete:o},fulfil:i,reject:s}}function nt(e){return{data:e.data,error:e.error,form:e.form,params:e.params,route:e.route,state:e.state,status:e.status,url:e.url}}function Tn(e){const t=new URL(e);return t.hash=decodeURIComponent(e.hash),t}function qt(e){let t;if(S.hash){const[,,n]=e.hash.split("#",3);t=n??""}else t=e.hash.slice(1);return decodeURIComponent(t)}export{Nn as a,qn as g,Pn as l,R as p,C as s};
|
web/sveltekit/build/_app/immutable/chunks/{Gqex3HJQ.js → qPYGiFsf.js}
RENAMED
|
@@ -1 +1 @@
|
|
| 1 |
-
import{s as e,p as r}from"./
|
|
|
|
| 1 |
+
import{s as e,p as r}from"./DtzoFJKK.js";const t={get error(){return r.error},get params(){return r.params},get status(){return r.status},get url(){return r.url}};e.updated.check;const a=t;export{a as p};
|
web/sveltekit/build/_app/immutable/entry/{app.3Jr9HSQZ.js → app.CUBM1aCV.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
| 1 |
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.
|
| 2 |
-
var S=e=>{throw TypeError(e)};var M=(e,t,r)=>t.has(e)||S("Cannot "+r);var c=(e,t,r)=>(M(e,t,"read from private field"),r?r.call(e):t.get(e)),p=(e,t,r)=>t.has(e)?S("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),I=(e,t,r,n)=>(M(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r);import{b as L,_ as b}from"../chunks/CXQd8Y6F.js";import{h as N,n as W,d as X,a3 as Z,q as $,v as tt,i as et,e as B,an as rt,j as at,a5 as A,ah as st,o as l,ao as nt,ap as ot,L as it,p as ct,aq as ut,am as dt,ai as mt,ar as _t,f as x,s as lt,a as ft,a4 as j,c as ht,r as vt,t as gt,al as k}from"../chunks/BTUA7_xE.js";import{h as yt,m as Et,u as bt,a as R,c as w,f as F,t as Rt,s as Pt}from"../chunks/CWw6qgC_.js";import{B as Ot,i as D}from"../chunks/Bd-v_9Ud.js";import{p as q}from"../chunks/CW0zSL4D.js";function V(e,t,r){var n;N&&(n=at,W());var o=new Ot(e);X(()=>{var i=t()??null;if(N){var a=$(n),s=a===rt,_=i!==null;if(s!==_){var P=tt();et(P),o.anchor=P,B(!1),o.ensure(i,i&&(y=>r(y,i))),B(!0);return}}o.ensure(i,i&&(y=>r(y,i)))},Z)}function Tt(e){return class extends xt{constructor(t){super({component:e,...t})}}}var f,d;class xt{constructor(t){p(this,f);p(this,d);var i;var r=new Map,n=(a,s)=>{var _=it(s,!1,!1);return r.set(a,_),_};const o=new Proxy({...t.props||{},$$events:{}},{get(a,s){return l(r.get(s)??n(s,Reflect.get(a,s)))},has(a,s){return s===st?!0:(l(r.get(s)??n(s,Reflect.get(a,s))),Reflect.has(a,s))},set(a,s,_){return A(r.get(s)??n(s,_),_),Reflect.set(a,s,_)}});I(this,d,(t.hydrate?yt:Et)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover,transformError:t.transformError})),(!((i=t==null?void 0:t.props)!=null&&i.$$host)||t.sync===!1)&&nt(),I(this,f,o.$$events);for(const a of Object.keys(c(this,d)))a==="$set"||a==="$destroy"||a==="$on"||ot(this,a,{get(){return c(this,d)[a]},set(s){c(this,d)[a]=s},enumerable:!0});c(this,d).$set=a=>{Object.assign(o,a)},c(this,d).$destroy=()=>{bt(c(this,d))}}$set(t){c(this,d).$set(t)}$on(t,r){c(this,f)[t]=c(this,f)[t]||[];const n=(...o)=>r.call(this,...o);return c(this,f)[t].push(n),()=>{c(this,f)[t]=c(this,f)[t].filter(o=>o!==n)}}$destroy(){c(this,d).$destroy()}}f=new WeakMap,d=new WeakMap;const St={};var At=F('<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px"><!></div>'),pt=F("<!> <!>",1);function It(e,t){ct(t,!0);let r=q(t,"components",23,()=>[]),n=q(t,"data_0",3,null),o=q(t,"data_1",3,null);ut(()=>t.stores.page.set(t.page)),dt(()=>{t.stores,t.page,t.constructors,r(),t.form,n(),o(),t.stores.page.notify()});let i=j(!1),a=j(!1),s=j(null);mt(()=>{const u=t.stores.page.subscribe(()=>{l(i)&&(A(a,!0),_t().then(()=>{A(s,document.title||"untitled page",!0)}))});return A(i,!0),u});const _=k(()=>t.constructors[1]);var P=pt(),y=x(P);{var G=u=>{const h=k(()=>t.constructors[0]);var v=w(),O=x(v);V(O,()=>l(h),(g,E)=>{L(E(g,{get data(){return n()},get form(){return t.form},get params(){return t.page.params},children:(m,jt)=>{var C=w(),K=x(C);V(K,()=>l(_),(Q,U)=>{L(U(Q,{get data(){return o()},get form(){return t.form},get params(){return t.page.params}}),T=>r()[1]=T,()=>{var T;return(T=r())==null?void 0:T[1]})}),R(m,C)},$$slots:{default:!0}}),m=>r()[0]=m,()=>{var m;return(m=r())==null?void 0:m[0]})}),R(u,v)},H=u=>{const h=k(()=>t.constructors[0]);var v=w(),O=x(v);V(O,()=>l(h),(g,E)=>{L(E(g,{get data(){return n()},get form(){return t.form},get params(){return t.page.params}}),m=>r()[0]=m,()=>{var m;return(m=r())==null?void 0:m[0]})}),R(u,v)};D(y,u=>{t.constructors[1]?u(G):u(H,-1)})}var z=lt(y,2);{var J=u=>{var h=At(),v=ht(h);{var O=g=>{var E=Rt();gt(()=>Pt(E,l(s))),R(g,E)};D(v,g=>{l(a)&&g(O)})}vt(h),R(u,h)};D(z,u=>{l(i)&&u(J)})}R(e,P),ft()}const Mt=Tt(It),Nt=[()=>b(()=>import("../nodes/0.
|
|
|
|
| 1 |
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.BWtmkq4k.js","../chunks/CWw6qgC_.js","../chunks/BTUA7_xE.js","../chunks/DxQlA7U2.js","../chunks/Bd-v_9Ud.js","../chunks/CW0zSL4D.js","../chunks/qPYGiFsf.js","../chunks/DtzoFJKK.js","../chunks/DCD6_LXk.js","../chunks/B0XoTt7U.js","../assets/RipMark.ClxF_PAC.css","../chunks/DixtWtwq.js","../assets/0.DiQNUxm-.css","../nodes/1.B7PnFUJS.js","../nodes/2.Buuzbd2q.js","../chunks/cDW0xQNP.js","../chunks/25_y8TFd.js","../chunks/CXQd8Y6F.js","../chunks/D907np-5.js","../assets/2.BD53GLFY.css","../nodes/3.TFkYs5Wp.js","../chunks/BatqQaKj.js","../assets/Briefing.Dmn9LgiV.css","../assets/3.BZfqQRM0.css","../nodes/4.xLGntVAz.js","../chunks/BZuv-XBZ.js","../assets/stoneRegistry.bHiraU77.css","../assets/4.BIuIAgmk.css","../nodes/5.BFrkSt3u.js"])))=>i.map(i=>d[i]);
|
| 2 |
+
var S=e=>{throw TypeError(e)};var M=(e,t,r)=>t.has(e)||S("Cannot "+r);var c=(e,t,r)=>(M(e,t,"read from private field"),r?r.call(e):t.get(e)),p=(e,t,r)=>t.has(e)?S("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),I=(e,t,r,n)=>(M(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r);import{b as L,_ as b}from"../chunks/CXQd8Y6F.js";import{h as N,n as W,d as X,a3 as Z,q as $,v as tt,i as et,e as B,an as rt,j as at,a5 as A,ah as st,o as l,ao as nt,ap as ot,L as it,p as ct,aq as ut,am as dt,ai as mt,ar as _t,f as x,s as lt,a as ft,a4 as j,c as ht,r as vt,t as gt,al as k}from"../chunks/BTUA7_xE.js";import{h as yt,m as Et,u as bt,a as R,c as w,f as F,t as Rt,s as Pt}from"../chunks/CWw6qgC_.js";import{B as Ot,i as D}from"../chunks/Bd-v_9Ud.js";import{p as q}from"../chunks/CW0zSL4D.js";function V(e,t,r){var n;N&&(n=at,W());var o=new Ot(e);X(()=>{var i=t()??null;if(N){var a=$(n),s=a===rt,_=i!==null;if(s!==_){var P=tt();et(P),o.anchor=P,B(!1),o.ensure(i,i&&(y=>r(y,i))),B(!0);return}}o.ensure(i,i&&(y=>r(y,i)))},Z)}function Tt(e){return class extends xt{constructor(t){super({component:e,...t})}}}var f,d;class xt{constructor(t){p(this,f);p(this,d);var i;var r=new Map,n=(a,s)=>{var _=it(s,!1,!1);return r.set(a,_),_};const o=new Proxy({...t.props||{},$$events:{}},{get(a,s){return l(r.get(s)??n(s,Reflect.get(a,s)))},has(a,s){return s===st?!0:(l(r.get(s)??n(s,Reflect.get(a,s))),Reflect.has(a,s))},set(a,s,_){return A(r.get(s)??n(s,_),_),Reflect.set(a,s,_)}});I(this,d,(t.hydrate?yt:Et)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover,transformError:t.transformError})),(!((i=t==null?void 0:t.props)!=null&&i.$$host)||t.sync===!1)&&nt(),I(this,f,o.$$events);for(const a of Object.keys(c(this,d)))a==="$set"||a==="$destroy"||a==="$on"||ot(this,a,{get(){return c(this,d)[a]},set(s){c(this,d)[a]=s},enumerable:!0});c(this,d).$set=a=>{Object.assign(o,a)},c(this,d).$destroy=()=>{bt(c(this,d))}}$set(t){c(this,d).$set(t)}$on(t,r){c(this,f)[t]=c(this,f)[t]||[];const n=(...o)=>r.call(this,...o);return c(this,f)[t].push(n),()=>{c(this,f)[t]=c(this,f)[t].filter(o=>o!==n)}}$destroy(){c(this,d).$destroy()}}f=new WeakMap,d=new WeakMap;const St={};var At=F('<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px"><!></div>'),pt=F("<!> <!>",1);function It(e,t){ct(t,!0);let r=q(t,"components",23,()=>[]),n=q(t,"data_0",3,null),o=q(t,"data_1",3,null);ut(()=>t.stores.page.set(t.page)),dt(()=>{t.stores,t.page,t.constructors,r(),t.form,n(),o(),t.stores.page.notify()});let i=j(!1),a=j(!1),s=j(null);mt(()=>{const u=t.stores.page.subscribe(()=>{l(i)&&(A(a,!0),_t().then(()=>{A(s,document.title||"untitled page",!0)}))});return A(i,!0),u});const _=k(()=>t.constructors[1]);var P=pt(),y=x(P);{var G=u=>{const h=k(()=>t.constructors[0]);var v=w(),O=x(v);V(O,()=>l(h),(g,E)=>{L(E(g,{get data(){return n()},get form(){return t.form},get params(){return t.page.params},children:(m,jt)=>{var C=w(),K=x(C);V(K,()=>l(_),(Q,U)=>{L(U(Q,{get data(){return o()},get form(){return t.form},get params(){return t.page.params}}),T=>r()[1]=T,()=>{var T;return(T=r())==null?void 0:T[1]})}),R(m,C)},$$slots:{default:!0}}),m=>r()[0]=m,()=>{var m;return(m=r())==null?void 0:m[0]})}),R(u,v)},H=u=>{const h=k(()=>t.constructors[0]);var v=w(),O=x(v);V(O,()=>l(h),(g,E)=>{L(E(g,{get data(){return n()},get form(){return t.form},get params(){return t.page.params}}),m=>r()[0]=m,()=>{var m;return(m=r())==null?void 0:m[0]})}),R(u,v)};D(y,u=>{t.constructors[1]?u(G):u(H,-1)})}var z=lt(y,2);{var J=u=>{var h=At(),v=ht(h);{var O=g=>{var E=Rt();gt(()=>Pt(E,l(s))),R(g,E)};D(v,g=>{l(a)&&g(O)})}vt(h),R(u,h)};D(z,u=>{l(i)&&u(J)})}R(e,P),ft()}const Mt=Tt(It),Nt=[()=>b(()=>import("../nodes/0.BWtmkq4k.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]),import.meta.url),()=>b(()=>import("../nodes/1.B7PnFUJS.js"),__vite__mapDeps([13,1,2,6,7]),import.meta.url),()=>b(()=>import("../nodes/2.Buuzbd2q.js"),__vite__mapDeps([14,1,2,11,15,8,9,5,10,16,7,17,18,19]),import.meta.url),()=>b(()=>import("../nodes/3.TFkYs5Wp.js"),__vite__mapDeps([20,1,2,4,16,15,6,7,21,5,3,9,22,23]),import.meta.url),()=>b(()=>import("../nodes/4.xLGntVAz.js"),__vite__mapDeps([24,1,2,4,6,7,21,16,5,3,9,22,25,17,18,26,11,27]),import.meta.url),()=>b(()=>import("../nodes/5.BFrkSt3u.js"),__vite__mapDeps([28,1,2,21,4,16,5,3,9,22,25,17,18,26]),import.meta.url)],Bt=[],Ft={"/":[2],"/print/[queryId]":[3],"/q/sample":[5],"/q/[queryId]":[4]},Y={handleError:(({error:e})=>{console.error(e)}),reroute:(()=>{}),transport:{}},Lt=Object.fromEntries(Object.entries(Y.transport).map(([e,t])=>[e,t.decode])),Yt=Object.fromEntries(Object.entries(Y.transport).map(([e,t])=>[e,t.encode])),Gt=!1,Ht=(e,t)=>Lt[e](t);export{Ht as decode,Lt as decoders,Ft as dictionary,Yt as encoders,Gt as hash,Y as hooks,St as matchers,Nt as nodes,Mt as root,Bt as server_loads};
|
web/sveltekit/build/_app/immutable/entry/start.CPaKwhlY.js
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
import{l as o,a as r}from"../chunks/Br29PcKx.js";export{o as load_css,r as start};
|
|
|
|
|
|
web/sveltekit/build/_app/immutable/entry/start.d_1AXvI4.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{l as o,a as r}from"../chunks/DtzoFJKK.js";export{o as load_css,r as start};
|