seriffic Claude Opus 4.7 (1M context) commited on
Commit
7cb5930
·
1 Parent(s): 052e77a

docs: full README + new EMISSIONS / DEPLOY / CHANGELOG / CONTRIBUTING

Browse files

Documents the post-droplet L4 topology, the per-call NVML energy
ledger, and the production deploy commands so the repo presents
itself the way an open-source civic tech project should — without
breaking any of the existing app structure or deploy paths.

New files
- docs/EMISSIONS.md full pipeline for real GPU power readings:
what's measured vs. estimated, the NVML
sampler in inference-vllm/proxy.py, the
bracket-sample LLM client path, the
hardware fallback table, and how to verify
with scripts/probe_stones_fire.py.
- docs/DEPLOY.md production topology diagram, env-var
reference for both Spaces, per-Space
deploy commands, local-dev recipes.
- CHANGELOG.md release log starting from the v0.5.0
hackathon submission tag.
- CONTRIBUTING.md quickstart + repo structure + house style
for outside contributors.

Updated
- README.md new "Inference energy — measured, not
estimated" section; live-demo blurb
reflects the L4 reality and the
RIPRAP_HARDWARE_LABEL override; new
Repository Structure section pointing at
each subtree; source-of-truth list adds
proxy.py + emissions.py. Hackathon
submission framing preserved.
- docs/ARCHITECTURE.md May 2026 banner at the top noting the
droplet retirement and pointing at
DEPLOY.md + EMISSIONS.md for current
infrastructure.

Bug fix
- web/main.py added explicit /favicon.svg, /favicon.png,
/favicon.ico, /robots.txt routes. They
were 404-ing under the SvelteKit SPA
fallback (only /_app was mounted off the
build directory), so the dam-mark logo
never reached the browser tab. Verified
via FastAPI TestClient: all three favicon
paths now serve the SvelteKit-built
artwork at 200.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

ARCHITECTURE.md CHANGED
@@ -1,5 +1,16 @@
1
  # Riprap architecture
2
 
 
 
 
 
 
 
 
 
 
 
 
3
  > **What it is.** A web tool that takes any NYC address and produces a
4
  > short, citation-grounded **flood-exposure briefing**. A tier (1–4)
5
  > with a paragraph of evidence, where every numeric claim links back to
 
1
  # Riprap architecture
2
 
3
+ > **Update, May 2026.** The MI300X DigitalOcean droplet that hosted
4
+ > production vLLM + EO models was decommissioned 2026-05-06; inference
5
+ > now serves from the NVIDIA L4 HF Space `msradam/riprap-vllm` and a
6
+ > matching FastAPI proxy that surfaces real per-call GPU power
7
+ > readings on every response. The MI300X language preserved in this
8
+ > document remains accurate for the original AMD-judging deploy
9
+ > (recoverable via [`docs/DROPLET-RUNBOOK.md`](DROPLET-RUNBOOK.md) +
10
+ > `RIPRAP_HARDWARE_LABEL=AMD MI300X`); current production topology +
11
+ > deploy commands live in [`docs/DEPLOY.md`](DEPLOY.md), and the
12
+ > emissions ledger is documented in [`docs/EMISSIONS.md`](EMISSIONS.md).
13
+
14
  > **What it is.** A web tool that takes any NYC address and produces a
15
  > short, citation-grounded **flood-exposure briefing**. A tier (1–4)
16
  > with a paragraph of evidence, where every numeric claim links back to
CHANGELOG.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ All notable changes to Riprap. The hackathon submission tag is
4
+ `v0.5.0` (build 2026-05-07); subsequent dates record polish work
5
+ that landed on the hackathon-period production deploys.
6
+
7
+ ## [Unreleased] — 2026-05-09 (Saturday)
8
+
9
+ ### Added
10
+ - **Per-query inference energy ledger** with real NVML readings off
11
+ the L4 GPU. The status row on the Findings region now reports
12
+ total Wh + total tokens for every briefing, with a leading icon
13
+ (`✓` / `◐` / `~`) disclosing whether the number was measured or
14
+ estimated. Full breakdown documented in
15
+ [`docs/EMISSIONS.md`](docs/EMISSIONS.md).
16
+ - `inference-vllm/proxy.py`: 100 ms-cadence NVML sampler, response
17
+ headers `X-GPU-Power-W` / `X-GPU-Energy-J` on every forwarded
18
+ POST, and a `GET /v1/power` endpoint for bracket-sampling clients.
19
+ - `app/emissions.py` — new module with a thread-local `Tracker` that
20
+ records every LLM and ML inference call (model, hardware, tokens,
21
+ duration, joules) with a `measured: bool` flag per row.
22
+ - `scripts/probe_stones_fire.py` — programmatic CI that runs an
23
+ address query against the lablab UI and asserts all five Stones
24
+ fire, no `torchvision::nms` / `deps unavailable` dep regression,
25
+ and the `emissions` block carries `nvidia_l4` hardware.
26
+ - `docs/EMISSIONS.md`, `docs/DEPLOY.md`, `CHANGELOG.md`,
27
+ `CONTRIBUTING.md`.
28
+
29
+ ### Changed
30
+ - The `RunHealthStrip` chip dropped the cloud-energy comparison
31
+ (the sign convention was misleading and the comparison is now
32
+ redundant given real measurements). New format:
33
+ `<icon> X.X Wh / Y.YK tok inference`.
34
+ - `app/llm.py:_default_hardware_label` defaults to `"NVIDIA L4"`
35
+ when remote vLLM is configured (was `"AMD MI300X"`, a stale
36
+ string from the droplet days).
37
+ - `app/llm.py:chat()` now brackets every completion with two GETs
38
+ to the inference Space's `/v1/power` endpoint; the average powers
39
+ the LLM-call energy reading instead of the data-sheet estimate.
40
+ - `app/inference.py:_post()` reads NVML headers off the proxy
41
+ response and forwards real joules into `emissions.record_ml`.
42
+
43
+ ### Fixed
44
+ - `app/flood_layers/prithvi_live.py`: when the configured remote
45
+ inference call fails (`RemoteUnreachable`), the specialist no
46
+ longer falls through to the local terratorch path. The local
47
+ path crashes with `RuntimeError: operator torchvision::nms does
48
+ not exist` on the cpu-basic UI Space; surfacing a clean
49
+ `remote prithvi-pluvial unreachable` skip is correct.
50
+ - `app/context/terramind_nyc.py:_try_remote()`: returns a
51
+ `{"ok": False, "skipped": "remote terramind/<adapter>: ..."}`
52
+ sentinel on remote failure, instead of `None` which was
53
+ silently masked as `deps unavailable on this deployment`.
54
+ - `web/main.py`: explicit `/favicon.svg`, `/favicon.png`,
55
+ `/favicon.ico`, `/robots.txt` routes — they were 404-ing under
56
+ the SvelteKit SPA fallback because only `/_app` was mounted off
57
+ the build directory.
58
+
59
+ ### Documentation
60
+ - Full README rewrite reflecting the post-droplet L4 topology, the
61
+ new emissions feature, and updated repo structure. Hackathon
62
+ framing preserved.
63
+ - New `docs/DEPLOY.md` with the production topology, env-var
64
+ reference, and per-Space deploy commands.
65
+ - New `docs/EMISSIONS.md` documenting what's measured vs. estimated,
66
+ the NVML pipeline, and how to verify.
67
+
68
+ ### Infrastructure note
69
+ - The DigitalOcean MI300X droplet was decommissioned 2026-05-06.
70
+ All production inference now serves from `msradam/riprap-vllm`
71
+ (NVIDIA L4). The MI300X runbook is preserved in
72
+ [`docs/DROPLET-RUNBOOK.md`](docs/DROPLET-RUNBOOK.md) for anyone
73
+ reproducing the AMD-judging setup; setting
74
+ `RIPRAP_HARDWARE_LABEL=AMD MI300X` swaps the emissions profile
75
+ back when redeploying to that hardware.
76
+
77
+ ---
78
+
79
+ ## [v0.5.0] — 2026-05-07
80
+
81
+ Hackathon submission tag.
82
+
83
+ ### Added
84
+ - Five-Stone Burr FSM with Granite-native document-role messages
85
+ - Mellea four-check rejection sampling for the Capstone
86
+ - SvelteKit UI with SSE streaming, briefing prose, evidence-card
87
+ grid, MapLibre overlay, citation drawer
88
+ - Three NYC-specialised foundation models published Apache-2.0:
89
+ `msradam/TerraMind-NYC-Adapters` (LULC + Buildings + TiM LoRAs),
90
+ `msradam/Prithvi-EO-2.0-NYC-Pluvial`,
91
+ `msradam/Granite-TTM-r2-Battery-Surge`
92
+ - 30+ FSM specialists across hazard memory, asset registers, live
93
+ observation, forecasting, and citation-grounded synthesis
CONTRIBUTING.md ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ Riprap is the hackathon submission for the AMD × lablab.ai
4
+ Developer Hackathon, but the source ships under Apache 2.0 and is
5
+ intended to be reusable as a template for citation-grounded civic
6
+ AI in any flood-vulnerable region. Pull requests welcome.
7
+
8
+ ## Quickstart
9
+
10
+ Python 3.12 + `uv`:
11
+
12
+ ```bash
13
+ git clone https://github.com/msradam/riprap-nyc
14
+ cd riprap-nyc
15
+ uv venv && uv pip install -r requirements.txt
16
+ ```
17
+
18
+ SvelteKit (the build is committed; only rebuild when sources
19
+ change under `web/sveltekit/src`):
20
+
21
+ ```bash
22
+ cd web/sveltekit && npm ci && npm run build && cd ../..
23
+ ```
24
+
25
+ Run the dev server locally pointing at the production inference
26
+ Space (real Granite + EO models, real NVML energy readings):
27
+
28
+ ```bash
29
+ RIPRAP_LLM_PRIMARY=vllm \
30
+ RIPRAP_LLM_BASE_URL=https://msradam-riprap-vllm.hf.space/v1 \
31
+ RIPRAP_LLM_API_KEY=<token> \
32
+ RIPRAP_ML_BACKEND=remote \
33
+ RIPRAP_ML_BASE_URL=https://msradam-riprap-vllm.hf.space \
34
+ RIPRAP_ML_API_KEY=<token> \
35
+ .venv/bin/uvicorn web.main:app --host 127.0.0.1 --port 7860
36
+ ```
37
+
38
+ Or run pure-local with Ollama (no GPU readings; data-sheet estimate):
39
+
40
+ ```bash
41
+ ollama pull granite4.1:3b granite4.1:8b
42
+ .venv/bin/uvicorn web.main:app --host 127.0.0.1 --port 7860
43
+ ```
44
+
45
+ ## Verifying changes
46
+
47
+ Two probe scripts exercise the live deployment end-to-end:
48
+
49
+ ```bash
50
+ # All five Stones must fire on the canonical address; emissions
51
+ # block must carry nvidia_l4 hardware; no torchvision/terratorch
52
+ # dep regressions in the trace.
53
+ PYTHONPATH=. uv run python scripts/probe_stones_fire.py --timeout 600
54
+
55
+ # Full canonical suite — five NYC addresses, intent-aware checks,
56
+ # Mellea grounding budget, no specialist crashes.
57
+ .venv/bin/python scripts/probe_addresses.py \
58
+ --base https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space
59
+ ```
60
+
61
+ Both default to the lablab UI Space; pass `--base http://127.0.0.1:7860`
62
+ to hit a local server.
63
+
64
+ ## Structure
65
+
66
+ ```
67
+ app/ Python package — the FSM and its specialists
68
+ ├── fsm.py Burr FSM, one @action per probe
69
+ ├── llm.py LiteLLM Router shim (Ollama / vLLM)
70
+ ├── inference.py HTTP client for the riprap-models service
71
+ ├── emissions.py Per-query energy + token tracker
72
+ ├── stones/ Stone taxonomy (NAME / TAGLINE / collect())
73
+ ├── flood_layers/ Cornerstone probes (sandy, dep, microtopo, …)
74
+ ├── context/ Keystone + Touchstone register + EO probes
75
+ ├── live/ Lodestone forecast probes
76
+ ├── intents/ single_address / neighborhood / compare / live_now
77
+ ├── reconcile.py Capstone — Granite-native document reconcile
78
+ └── mellea_validator.py Mellea four-check rejection sampling
79
+
80
+ web/ FastAPI + SvelteKit
81
+ ├── main.py FastAPI app, SSE streaming, layer endpoints
82
+ ├── sveltekit/ Primary UI (adapter-static; build committed)
83
+ └── static/ Legacy custom-element pages (still mounted)
84
+
85
+ inference-vllm/ Inference Space source (vLLM + EO models + proxy)
86
+ ├── Dockerfile L4 image, bakes Granite 4.1 8B FP8 + EO deps
87
+ ├── entrypoint.sh Boots vllm, riprap-models, proxy as subprocesses
88
+ └── proxy.py Bearer-auth + NVML power sampler + SSE pass-through
89
+
90
+ inference/ Ollama-backed inference Space (fallback variant)
91
+ services/riprap-models/ The EO/forecast specialist HTTP service
92
+
93
+ scripts/
94
+ ├── probe_stones_fire.py Programmatic Stone-fire CI
95
+ ├── probe_addresses.py Canonical 5-address suite
96
+ ├── deploy_vllm_space.sh Deploy the L4 inference Space
97
+ ├── deploy_personal_space.sh Deploy the personal L4 mirror
98
+ ├── deploy_inference_space.sh Deploy the Ollama-backed inference Space
99
+ └── … Register builders, raster bakers, etc.
100
+
101
+ experiments/ Reproduction recipes for the three NYC fine-tunes
102
+ docs/ Architecture, methodology, deploy, emissions, runbooks
103
+ tests/ pytest suite (envelope + compare-shape tests)
104
+ ```
105
+
106
+ ## Style
107
+
108
+ - Python 3.12; `uv` for package management.
109
+ - LLM calls go through `app/llm.py` — never import `litellm` /
110
+ `ollama` directly from a specialist. The `chat()` shim wraps both
111
+ backends and the energy ledger reads off it.
112
+ - Remote ML calls go through `app/inference.py::_post`. Specialists
113
+ may try local fallback only when `inference.remote_enabled()` is
114
+ False; once a remote call has been attempted, return a clean
115
+ `{ok: False, skipped: ...}` on failure rather than crashing
116
+ through to local code paths that may not be installed.
117
+ - Every specialist emits one trace record per call with `step` /
118
+ `ok` / `elapsed_s` / `result` / `err` so the SSE stream and the
119
+ emissions tracker can reason about it.
120
+
121
+ ## Reporting issues
122
+
123
+ GitHub issues at <https://github.com/msradam/riprap-nyc/issues>.
124
+ For hackathon-period demo issues during May 4–10 2026, the live
125
+ deploy at
126
+ <https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space>
127
+ is the source of truth.
README.md CHANGED
@@ -11,33 +11,36 @@ pinned: false
11
  <img src="assets/logo@2x.png" width="72" height="72" alt="Riprap dam mark" />
12
  </p>
13
 
14
- # Riprap — citation-grounded NYC flood-exposure briefings
15
-
16
- Riprap takes any NYC address (or neighborhood, or development-permit
17
- query) and produces a four-section briefing — Status, Empirical
18
- evidence, Modeled scenarios, Policy context. Every numeric claim is
19
- anchored to a `[doc_id]` citation that resolves to a named primary
20
- public-record source. If the model cannot cite a number, the model
21
- does not publish that number.
22
-
23
- The Capstone reconciler is **IBM Granite 4.1 8B**, served via Ollama
24
- on T4 or vLLM on AMD MI300X, wrapped in **Mellea**-validated rejection
25
- sampling. Sentences that fail one of four grounding checks
26
- (`numerics_grounded`, `no_placeholder_tokens`, `citations_dense`,
27
- `citations_resolve`) are rerolled with surgical feedback until the
28
- budget is exhausted.
29
 
30
  Live demo: <https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space>
31
 
32
  ---
33
 
34
- ## What it looks like
 
 
 
 
 
35
 
36
- ![Riprap flood-exposure briefing for 80 Pioneer Street, Brooklyn](assets/screenshots/hero.png)
 
 
 
 
 
37
 
38
- *A citation-grounded flood-exposure briefing for 80 Pioneer Street in
39
- Red Hook. Generated in roughly 7 seconds against AMD MI300X. Every
40
- numeric claim cites a primary public-record source.*
41
 
42
  ---
43
 
@@ -47,11 +50,19 @@ Three ways to use Riprap, in increasing order of self-host:
47
 
48
  ### 1. Try the live demo
49
 
50
- The hosted Space runs the full pipeline against a live AMD MI300X
51
- inference backend. Type any NYC address.
52
 
53
  <https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space>
54
 
 
 
 
 
 
 
 
 
 
55
  ### 2. Run locally with Docker
56
 
57
  ```bash
@@ -65,8 +76,8 @@ docker compose up
65
 
66
  Visit `http://localhost:7860`.
67
 
68
- To self-host the GPU inference half (vLLM + the ML specialist
69
- service) on an AMD ROCm or NVIDIA CUDA box, run:
70
 
71
  ```bash
72
  docker compose --profile with-models up
@@ -111,14 +122,38 @@ group those probes into five legible roles:
111
 
112
  | Stone | Role | What fires |
113
  |---|---|---|
114
- | **Cornerstone** | The Hazard Reader. What NYC's ground remembers. | Sandy 2012 inundation extent, NYC DEP stormwater scenarios, 2021 Ida USGS high-water marks, baked Prithvi-EO Ida-attributable polygons, USGS 3DEP DEM + HAND/TWI |
115
  | **Keystone** | The Asset Register. What's exposed. | MTA subway entrances, NYCHA developments, NYC DOE schools, NYS DOH hospitals, **TerraMind-NYC Buildings LoRA** |
116
  | **Touchstone** | The Live Observer. Current state of the city. | FloodNet ultrasonic depth sensors, NYC 311 flood complaints, NWS hourly METAR, NOAA tide-gauge water levels, **Prithvi-EO 2.0 NYC-Pluvial v2**, **TerraMind-NYC LULC LoRA** |
117
  | **Lodestone** | The Projector. What's coming. | NWS public flood alerts, Granite TTM r2 surge nowcast (zero-shot, 6-min cadence, 9.6 h horizon), per-address 311 weekly forecast, FloodNet sensor recurrence forecast, **Granite-TTM-r2-Battery-Surge fine-tune** (96 h hourly horizon) |
118
  | **Capstone** | The Synthesiser. Citation-grounded briefing. | Granite 4.1 + Mellea rejection sampling |
119
 
120
- The four data-Stones run sequentially per query; the Capstone
121
- reconciles their documents into one cited paragraph.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  ---
124
 
@@ -133,13 +168,14 @@ full-FT baseline), TiM 0.6023, Buildings 0.5511. Trained in around 18
133
  minutes on a single MI300X.
134
 
135
  **[`msradam/Prithvi-EO-2.0-NYC-Pluvial`](https://huggingface.co/msradam/Prithvi-EO-2.0-NYC-Pluvial).**
136
- NYC pluvial-flood fine-tune of Prithvi-EO 2.0. Test flood IoU 0.5979
137
- vs 0.10 on the Sen1Floods11 base, a 6× lift. Lovász-Softmax loss with
138
  copy-paste augmentation.
139
 
140
  **[`msradam/Granite-TTM-r2-Battery-Surge`](https://huggingface.co/msradam/Granite-TTM-r2-Battery-Surge).**
141
- NYC Battery storm-surge nowcast fine-tune of Granite TimeSeries TTM
142
- r2. Test MAE 0.1091 m, 41% vs persistence and 25% vs zero-shot.
 
143
 
144
  All three are loaded at runtime by their respective FSM probes in
145
  `app/context/` and `app/live/`. Reproduction recipes live under
@@ -172,10 +208,18 @@ NYC address ──► Granite 4.1 3B planner ──► Plan{intent, targets, spe
172
  SSE stream → SvelteKit UI (briefing, trace, map)
173
  ```
174
 
175
- LLM inference is dispatched through `app/llm.py`, a LiteLLM Router
176
- shim with two backends: **Ollama** (T4 / local) and **vLLM** (AMD
177
- MI300X). Same `chat()` signature in both directions; vLLM is primary
178
- for the demo, Ollama is the auto-failover.
 
 
 
 
 
 
 
 
179
 
180
  Source-of-truth pointers:
181
 
@@ -192,8 +236,47 @@ Source-of-truth pointers:
192
  `plan / step / token / mellea_attempt / final` events plus the
193
  `stone_start / stone_done` envelope around each Stone group.
194
  - `web/sveltekit/`: primary UI (SvelteKit + adapter-static).
 
 
 
 
 
 
 
 
 
 
 
195
 
196
- For the long-form architecture document, see [`ARCHITECTURE.md`](ARCHITECTURE.md).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
  ---
199
 
@@ -210,7 +293,7 @@ aggregators.
210
  | Hurricane Ida 2021 USGS high-water marks | USGS Short-Term Network | Empirical validation points |
211
  | FloodNet ultrasonic sensor network | NYU CUSP / FloodNet | Live water-depth observations |
212
  | NYC 311 flood complaints | NYC Open Data | Empirical complaint history |
213
- | NOAA tide gauge The Battery | NOAA CO-OPS | Live tide and surge level |
214
  | NWS METAR | National Weather Service | Hourly precipitation |
215
  | NWS public flood alerts | National Weather Service | Active warnings and watches |
216
  | MTA subway entrances | MTA / NYC Open Data | Transit asset register |
@@ -223,28 +306,47 @@ aggregators.
223
  | Sentinel-2 MSI imagery | ESA / Copernicus | Prithvi + TerraMind inputs |
224
 
225
  The full data licence map and vintage table is enumerated in
226
- [`ARCHITECTURE.md`](ARCHITECTURE.md).
227
 
228
  ---
229
 
230
- ## What Riprap is not
231
-
232
- The civil engineer carries the stamp. Riprap surfaces the evidence the
233
- engineer judges.
234
-
235
- - **Not a hydraulic model.** Riprap does not replace HEC-RAS, SWMM, or
236
- ICM. It synthesises evidence from completed modelling work; it does
237
- not produce new flow or stage estimates.
238
- - **Not a stamped deliverable.** The briefing is a starting point for
239
- a memo, not the memo itself. Professional judgment, field
240
- reconnaissance, and the engineer's stamp are required for any
241
- actionable output.
242
- - **Not a substitute for site investigation.** Microtopography is from
243
- 1 m USGS 3DEP LiDAR, appropriate for screening, not for design.
244
- - **Not a risk score.** Riprap does not output a 1–10 or 1–100 number.
245
- Score-based tools (First Street, ClimateCheck, Jupiter) are
246
- different products for different audiences. Riprap is the evidence
247
- audit trail behind any such judgment.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
  ---
250
 
@@ -267,30 +369,30 @@ If you reference Riprap in academic or professional work:
267
 
268
  ## License
269
 
270
- Apache 2.0 (this repository). The three NYC-specialised fine-tunes
271
- above are also Apache 2.0; underlying upstream models retain their
272
- own permissive licences (see each `MODEL_CARD.md`).
273
 
274
- HF Space configuration reference:
275
- <https://huggingface.co/docs/hub/spaces-config-reference>.
 
 
 
276
 
277
  ---
278
 
279
  ## Acknowledgments
280
 
281
- - **AMD Developer Cloud** MI300X compute that made the three
282
- Apache-2.0 NYC fine-tunes feasible.
283
- - **AMD x lablab.ai Developer Hackathon** the venue.
284
- - **IBM Research** Granite 4.1, Granite Embedding 278M, Granite TTM
285
- r2, Mellea, and the rest of the open-source Granite ecosystem.
286
- - **NASA / IBM Prithvi-EO 2.0** and **IBM / ESA TerraMind 1.0** the
287
  geospatial foundation models behind the NYC fine-tunes.
288
- - **NYU CUSP / FloodNet** the public sensor network whose data
289
- Riprap reads live.
290
- - **Andrew Hicks** civil-engineering review of the methodology, and
291
- framing for what Riprap is not.
292
- - **The Riprap dam mark** — ["Dam" by Chintuza](https://thenounproject.com/icon/dam-4516918/)
293
  via the Noun Project, licensed CC-BY 3.0. The original SVG embedded
294
- the attribution as on-canvas text; Riprap's `assets/logo*.svg`
295
- strips the embedded text and carries the credit here in body copy
296
- instead, per the Creative Commons attribution requirement.
 
11
  <img src="assets/logo@2x.png" width="72" height="72" alt="Riprap dam mark" />
12
  </p>
13
 
14
+ # Riprap
15
+
16
+ ## Flood risk analysis for any NYC address.
17
+
18
+ A multi-agent AI system that reads satellites, watches sensors, forecasts
19
+ surges, and refuses to ship a sentence it cannot ground in a citation.
20
+
21
+ ![Riprap flood-exposure briefing for DUMBO, Brooklyn](assets/screenshots/hero.png)
 
 
 
 
 
 
 
22
 
23
  Live demo: <https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space>
24
 
25
  ---
26
 
27
+ ## The problem Riprap solves
28
+
29
+ NYC has spent decades publishing the flood-exposure inputs an engineer needs:
30
+ Sandy 2012 inundation, NYC DEP stormwater scenarios, FloodNet sensors, NOAA
31
+ tide gauges, USGS 3DEP LiDAR, 311 complaints, MTA, NYCHA, schools, hospitals.
32
+ The data is public. None of it composes itself.
33
 
34
+ Every engineer doing a drainage review, every resilience office siting a
35
+ capital project, every climate-adaptation team prioritising blocks
36
+ reassembles the same evidence by hand, per address, from a dozen agencies. A
37
+ briefing that should be a tool call ends up as a half-day of manual joins.
38
+ Existing tools either return opaque vendor risk scores or skip the audit
39
+ trail a stamped engineering memo actually requires.
40
 
41
+ Riprap composes it. Type any NYC address, get a four-section,
42
+ citation-grounded briefing in about two minutes, with every claim pointing
43
+ back to a `[doc_id]` in public-record data.
44
 
45
  ---
46
 
 
50
 
51
  ### 1. Try the live demo
52
 
53
+ The hosted Space runs the full pipeline. Type any NYC address.
 
54
 
55
  <https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space>
56
 
57
+ The hackathon submission was originally built against an AMD Instinct
58
+ MI300X via the AMD Developer Cloud, where the three NYC-specialised
59
+ fine-tunes were trained. For the hackathon-period demo, inference now
60
+ serves from an NVIDIA L4 Hugging Face Space (`msradam/riprap-vllm`)
61
+ co-hosting vLLM + the EO model stack — see
62
+ [`docs/DEPLOY.md`](docs/DEPLOY.md). Setting
63
+ `RIPRAP_HARDWARE_LABEL=AMD MI300X` on a redeploy swaps the energy
64
+ ledger back to MI300X figures.
65
+
66
  ### 2. Run locally with Docker
67
 
68
  ```bash
 
76
 
77
  Visit `http://localhost:7860`.
78
 
79
+ To self-host the GPU inference half (vLLM + the ML specialist service) on
80
+ an AMD ROCm or NVIDIA CUDA box, run:
81
 
82
  ```bash
83
  docker compose --profile with-models up
 
122
 
123
  | Stone | Role | What fires |
124
  |---|---|---|
125
+ | **Cornerstone** | The Hazard Reader. What the ground remembers. | Sandy 2012 inundation extent, NYC DEP stormwater scenarios, 2021 Ida USGS high-water marks, baked Prithvi-EO Ida-attributable polygons, USGS 3DEP DEM + HAND/TWI |
126
  | **Keystone** | The Asset Register. What's exposed. | MTA subway entrances, NYCHA developments, NYC DOE schools, NYS DOH hospitals, **TerraMind-NYC Buildings LoRA** |
127
  | **Touchstone** | The Live Observer. Current state of the city. | FloodNet ultrasonic depth sensors, NYC 311 flood complaints, NWS hourly METAR, NOAA tide-gauge water levels, **Prithvi-EO 2.0 NYC-Pluvial v2**, **TerraMind-NYC LULC LoRA** |
128
  | **Lodestone** | The Projector. What's coming. | NWS public flood alerts, Granite TTM r2 surge nowcast (zero-shot, 6-min cadence, 9.6 h horizon), per-address 311 weekly forecast, FloodNet sensor recurrence forecast, **Granite-TTM-r2-Battery-Surge fine-tune** (96 h hourly horizon) |
129
  | **Capstone** | The Synthesiser. Citation-grounded briefing. | Granite 4.1 + Mellea rejection sampling |
130
 
131
+ The four data-Stones run sequentially per query; the Capstone reconciles
132
+ their documents into one cited briefing.
133
+
134
+ ---
135
+
136
+ ## The Five Stones beyond NYC
137
+
138
+ The Five Stones taxonomy is a city-agnostic template for any
139
+ flood-vulnerable region with the right data scaffolding. The five roles
140
+ generalise; only the probes plugged into each Stone change.
141
+
142
+ | Stone | Role | What you replace |
143
+ |---|---|---|
144
+ | **Cornerstone** | Hazard memory | Local historical inundation extents, regional DEM, regulatory floodplain maps |
145
+ | **Keystone** | Asset registers | The transit, housing, education, and healthcare polygons your jurisdiction publishes |
146
+ | **Touchstone** | Live observation | Whatever live sensors and complaint streams the city or region exposes (FloodNet has analogues in Houston, Boston, Miami) |
147
+ | **Lodestone** | Forecasts | Local NWS forecast office output, regional surge or hydrologic models, time-series fine-tunes for your tide gauge |
148
+ | **Capstone** | Citation-grounded synthesis | Same |
149
+
150
+ The architectural commitments transfer unchanged: Burr FSM with one
151
+ `@action` per probe, Granite-native `role="document"` reconciliation,
152
+ Mellea four-check grounding, SSE streaming to a SvelteKit map UI, every
153
+ claim cited to its source. To port Riprap to a new city, you reimplement
154
+ each Stone's `collect()` against local data and retrain the EO and
155
+ time-series fine-tunes on your jurisdiction's imagery and gauges. The
156
+ agentic shell stays the same.
157
 
158
  ---
159
 
 
168
  minutes on a single MI300X.
169
 
170
  **[`msradam/Prithvi-EO-2.0-NYC-Pluvial`](https://huggingface.co/msradam/Prithvi-EO-2.0-NYC-Pluvial).**
171
+ NYC pluvial-flood fine-tune of Prithvi-EO 2.0. Test flood IoU 0.5979 vs
172
+ 0.10 on the Sen1Floods11 base, a 6× lift. Lovász-Softmax loss with
173
  copy-paste augmentation.
174
 
175
  **[`msradam/Granite-TTM-r2-Battery-Surge`](https://huggingface.co/msradam/Granite-TTM-r2-Battery-Surge).**
176
+ NYC Battery storm-surge nowcast fine-tune of Granite TimeSeries TTM r2.
177
+ Test MAE 0.1091 m, 41% better than persistence and 25% better than
178
+ zero-shot.
179
 
180
  All three are loaded at runtime by their respective FSM probes in
181
  `app/context/` and `app/live/`. Reproduction recipes live under
 
208
  SSE stream → SvelteKit UI (briefing, trace, map)
209
  ```
210
 
211
+ LLM inference is dispatched through `app/llm.py`, a LiteLLM Router shim
212
+ with two backends: **Ollama** (local dev) and **vLLM** (AMD MI300X or
213
+ NVIDIA L4 — currently L4 on `msradam/riprap-vllm`). Same `chat()`
214
+ signature in both directions; vLLM is primary for the demo, Ollama is
215
+ the auto-failover.
216
+
217
+ ML model inference (Prithvi-EO, TerraMind, TTM, GLiNER, Granite
218
+ Embedding) goes through `app/inference.py::_post`, a thin HTTP client
219
+ that hits the bearer-authenticated proxy on the inference Space. The
220
+ proxy forwards to vLLM or to the riprap-models service co-resident on
221
+ the same L4, and stamps real GPU power readings onto every response —
222
+ see the energy section below.
223
 
224
  Source-of-truth pointers:
225
 
 
236
  `plan / step / token / mellea_attempt / final` events plus the
237
  `stone_start / stone_done` envelope around each Stone group.
238
  - `web/sveltekit/`: primary UI (SvelteKit + adapter-static).
239
+ - `inference-vllm/proxy.py`: bearer-auth proxy on the L4 inference
240
+ Space; runs the NVML power sampler that the energy ledger reads.
241
+ - `app/emissions.py`: per-query Tracker + hardware profiles. Records
242
+ every LLM and ML inference call with `measured: bool`.
243
+
244
+ For the long-form architecture document, see
245
+ [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md). Methodology and
246
+ civil-engineering framing in
247
+ [`docs/METHODOLOGY.md`](docs/METHODOLOGY.md). Lit review in
248
+ [`docs/RESEARCH.md`](docs/RESEARCH.md). Production deploy
249
+ topology in [`docs/DEPLOY.md`](docs/DEPLOY.md).
250
 
251
+ ---
252
+
253
+ ## Inference energy — measured, not estimated
254
+
255
+ Riprap reports the energy and token cost of every inference call it
256
+ makes during a briefing. The status row on the Findings region
257
+ displays a single chip:
258
+
259
+ ```
260
+ ✓ 1.4 Wh / 6.9K tok inference
261
+ ```
262
+
263
+ The `✓` icon means every recorded call came back with a real reading
264
+ off the L4 GPU via `nvmlDeviceGetPowerUsage`. The inference Space
265
+ runs a 100 ms-cadence NVML sampler in the proxy and stamps
266
+ `X-GPU-Power-W` / `X-GPU-Energy-J` on every response; the LLM client
267
+ brackets each completion with two GETs to `/v1/power` because LiteLLM
268
+ hides response headers. When the proxy is unreachable, the chip
269
+ shows `~` or `◐` and the row falls back to a data-sheet sustained-
270
+ power estimate.
271
+
272
+ Per-call records carry `prompt_tokens`, `completion_tokens`,
273
+ `duration_s`, `power_w`, `joules`, and a `measured: bool` flag. The
274
+ full ledger is shipped on the SSE `final` event under
275
+ `emissions.calls`, so any consumer (dashboard, billing model,
276
+ reproducibility check) can reuse the data.
277
+
278
+ Detailed pipeline + verification recipe in
279
+ [`docs/EMISSIONS.md`](docs/EMISSIONS.md).
280
 
281
  ---
282
 
 
293
  | Hurricane Ida 2021 USGS high-water marks | USGS Short-Term Network | Empirical validation points |
294
  | FloodNet ultrasonic sensor network | NYU CUSP / FloodNet | Live water-depth observations |
295
  | NYC 311 flood complaints | NYC Open Data | Empirical complaint history |
296
+ | NOAA tide gauge, The Battery | NOAA CO-OPS | Live tide and surge level |
297
  | NWS METAR | National Weather Service | Hourly precipitation |
298
  | NWS public flood alerts | National Weather Service | Active warnings and watches |
299
  | MTA subway entrances | MTA / NYC Open Data | Transit asset register |
 
306
  | Sentinel-2 MSI imagery | ESA / Copernicus | Prithvi + TerraMind inputs |
307
 
308
  The full data licence map and vintage table is enumerated in
309
+ [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
310
 
311
  ---
312
 
313
+ ## Repository structure
314
+
315
+ ```
316
+ app/ Python — Burr FSM, specialists, reconciler
317
+ ├── fsm.py One @action per probe, plus the Stones taxonomy
318
+ ├── llm.py LiteLLM Router shim (Ollama / vLLM)
319
+ ├── inference.py HTTP client for the riprap-models service
320
+ ├── emissions.py Per-query energy + token ledger (real NVML)
321
+ ├── reconcile.py Granite-native document reconcile (Capstone)
322
+ ├── mellea_validator.py Mellea four-check rejection sampling
323
+ ├── stones/, intents/ Stone definitions + intent dispatchers
324
+ ├── flood_layers/ Cornerstone hazard probes
325
+ ├── context/, registers/ Keystone + Touchstone register / EO probes
326
+ └── live/ Lodestone forecast probes
327
+
328
+ web/ FastAPI + SvelteKit
329
+ ├── main.py FastAPI app, SSE streaming, layer endpoints
330
+ ├── sveltekit/ Primary UI (adapter-static; build committed)
331
+ └── static/ Legacy custom-element pages (still mounted)
332
+
333
+ inference-vllm/ Inference Space (vLLM + EO models + proxy)
334
+ ├── Dockerfile L4 image, bakes Granite 4.1 8B FP8 + EO deps
335
+ ├── entrypoint.sh Boots vllm, riprap-models, proxy together
336
+ └── proxy.py Bearer-auth + NVML sampler + SSE pass-through
337
+
338
+ inference/ Ollama-backed inference Space (fallback)
339
+ services/riprap-models/ EO/forecast specialist HTTP service
340
+
341
+ scripts/ Probes, register builders, deploy commands
342
+ experiments/ Reproduction recipes for the three NYC fine-tunes
343
+ docs/ ARCHITECTURE · DEPLOY · EMISSIONS · METHODOLOGY · RESEARCH
344
+ tests/ pytest suite (envelope + compare-shape)
345
+ ```
346
+
347
+ [`CONTRIBUTING.md`](CONTRIBUTING.md) covers dev setup, the probe
348
+ scripts, and house style. [`CHANGELOG.md`](CHANGELOG.md) tracks
349
+ changes since the v0.5.0 hackathon submission.
350
 
351
  ---
352
 
 
369
 
370
  ## License
371
 
372
+ Apache 2.0. See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).
 
 
373
 
374
+ The three NYC-specialised fine-tunes above are also Apache 2.0;
375
+ underlying upstream models retain their own permissive licences (see
376
+ each `MODEL_CARD.md`). Public-record data sources retain their own
377
+ access terms; the licence map is in
378
+ [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
379
 
380
  ---
381
 
382
  ## Acknowledgments
383
 
384
+ - **AMD Developer Cloud**, MI300X compute that made the three Apache-2.0
385
+ NYC fine-tunes feasible.
386
+ - **AMD × lablab.ai Developer Hackathon**, the venue.
387
+ - **IBM Research**, Granite 4.1, Granite Embedding 278M, Granite TTM r2,
388
+ Mellea, and the rest of the open-source Granite ecosystem.
389
+ - **NASA / IBM Prithvi-EO 2.0** and **IBM / ESA TerraMind 1.0**, the
390
  geospatial foundation models behind the NYC fine-tunes.
391
+ - **NYU CUSP / FloodNet**, the public sensor network whose data Riprap
392
+ reads live.
393
+ - **Andrew Hicks**, civil-engineering review of the methodology.
394
+ - **The Riprap dam mark**, ["Dam" by Chintuza](https://thenounproject.com/icon/dam-4516918/)
 
395
  via the Noun Project, licensed CC-BY 3.0. The original SVG embedded
396
+ the attribution as on-canvas text; Riprap's `assets/logo*.svg` strips
397
+ the embedded text and carries the credit here in body copy instead,
398
+ per the Creative Commons attribution requirement.
docs/DEPLOY.md ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deployment topology
2
+
3
+ Riprap is composed of two HF Spaces in production. The **UI Space**
4
+ is CPU-only and contains the FastAPI + SvelteKit front-end; the
5
+ **inference Space** is an L4 GPU and runs vLLM (Granite 4.1 8B FP8)
6
+ plus the EO model stack co-resident.
7
+
8
+ ```
9
+ ┌──────────────────────────────────────────────┐
10
+ │ msradam/riprap-vllm (NVIDIA L4, 24 GB) │
11
+ │ │
12
+ │ :7860 proxy.py bearer-auth FastAPI │
13
+ │ ├─ /v1/chat/* /v1/embeddings → :8000 │
14
+ │ └─ /v1/{prithvi,terramind,...} → :7861 │
15
+ │ └─ /v1/power NVML readings │
16
+ │ │
17
+ │ :8000 vLLM Granite 4.1 8B FP8 │
18
+ │ :7861 riprap-models │
19
+ │ Prithvi-EO 2.0 NYC-Pluvial │
20
+ │ TerraMind LULC + Buildings │
21
+ │ Granite TTM r2 │
22
+ │ GLiNER + Granite Embedding 278M │
23
+ └────────────────────▲─────────────────────────┘
24
+ │ bearer-auth HTTPS
25
+
26
+ ┌─────────────────────────────┴──────────────────────────┐
27
+ │ lablab-ai-amd-developer-hackathon/riprap-nyc │
28
+ │ Hackathon submission UI · cpu-basic │
29
+ │ │
30
+ │ FastAPI (web/main.py) + SvelteKit static build │
31
+ │ Burr FSM (app/fsm.py) │
32
+ │ │
33
+ │ RIPRAP_LLM_BASE_URL = …/v1 │
34
+ │ RIPRAP_ML_BASE_URL = … │
35
+ └────────────────────────────────────────────────────────┘
36
+ ```
37
+
38
+ The UI Space holds no GPU weights and contacts no commercial APIs.
39
+ Every model call routes through the bearer-authenticated proxy on
40
+ the inference Space.
41
+
42
+ ---
43
+
44
+ ## Hugging Face Spaces
45
+
46
+ ### `lablab-ai-amd-developer-hackathon/riprap-nyc` — UI Space
47
+
48
+ The hackathon submission. CPU-basic tier. Image built from the root
49
+ `Dockerfile`. Holds no model weights — every inference call goes
50
+ remote via env vars.
51
+
52
+ **Required Space variables:**
53
+
54
+ ```
55
+ RIPRAP_LLM_PRIMARY = vllm
56
+ RIPRAP_LLM_BASE_URL = https://msradam-riprap-vllm.hf.space/v1
57
+ RIPRAP_LLM_VLLM_8B_NAME = granite4.1:8b
58
+ RIPRAP_ML_BACKEND = remote
59
+ RIPRAP_ML_BASE_URL = https://msradam-riprap-vllm.hf.space
60
+ RIPRAP_NYCHA_REGISTERS = 1
61
+ RIPRAP_HEAVY_SPECIALISTS = 1
62
+ RIPRAP_PRITHVI_LIVE_ENABLE= 1
63
+ RIPRAP_TERRAMIND_ENABLE = 1
64
+ RIPRAP_EO_CHIP_ENABLE = 1
65
+ ```
66
+
67
+ **Required secrets** (set via Settings → Variables and secrets):
68
+
69
+ ```
70
+ RIPRAP_LLM_API_KEY bearer token shared with the inference Space
71
+ RIPRAP_ML_API_KEY bearer token shared with the inference Space
72
+ HF_TOKEN for register / catalog downloads
73
+ ```
74
+
75
+ ### `msradam/riprap-vllm` — Inference Space
76
+
77
+ L4 (`l4x1`) tier. Image built from `inference-vllm/Dockerfile`.
78
+ Bakes Granite 4.1 8B FP8 weights and the EO model dependencies
79
+ (terratorch + peft + diffusers + segmentation-models-pytorch +
80
+ nvidia-ml-py for NVML power sampling).
81
+
82
+ **Required secret:**
83
+
84
+ ```
85
+ RIPRAP_PROXY_TOKEN bearer token; must match RIPRAP_LLM_API_KEY /
86
+ RIPRAP_ML_API_KEY on the UI Spaces
87
+ ```
88
+
89
+ **Endpoints:**
90
+
91
+ | Path | Routes to | Notes |
92
+ |---|---|---|
93
+ | `POST /v1/chat/completions` | vLLM | Granite 4.1 8B FP8, OpenAI-compat |
94
+ | `POST /v1/completions` | vLLM | OpenAI-compat |
95
+ | `GET /v1/models` | vLLM | served-model-name family |
96
+ | `POST /v1/embeddings` | riprap-models | Granite Embedding 278M |
97
+ | `POST /v1/prithvi-pluvial` | riprap-models | Prithvi-EO 2.0 NYC-Pluvial |
98
+ | `POST /v1/terramind` | riprap-models | TerraMind LULC / Buildings / synthesis |
99
+ | `POST /v1/ttm-forecast` | riprap-models | Granite TTM r2 + Battery surge |
100
+ | `POST /v1/gliner-extract` | riprap-models | GLiNER typed-entity |
101
+ | `GET /v1/power` | proxy | Real NVML power (W) — see `docs/EMISSIONS.md` |
102
+ | `GET /healthz` | proxy + both backends | Aggregates health status |
103
+
104
+ All `/v1/*` endpoints require `Authorization: Bearer <PROXY_TOKEN>`.
105
+ `/v1/power` and the bracket-sampling LLM client path are described
106
+ in [`docs/EMISSIONS.md`](EMISSIONS.md).
107
+
108
+ ---
109
+
110
+ ## Personal mirror — `msradam/riprap`
111
+
112
+ Self-contained L4 mirror that runs the full stack (UI + vLLM + EO
113
+ models) in a single container. Used for parallel demos when the
114
+ shared inference Space is busy. Built from `Dockerfile.l4`.
115
+
116
+ ```bash
117
+ scripts/deploy_personal_space.sh
118
+ ```
119
+
120
+ This is paused by default for the hackathon period to keep the L4
121
+ budget on the primary inference Space.
122
+
123
+ ---
124
+
125
+ ## Local development
126
+
127
+ ### Pure local (Ollama)
128
+
129
+ ```bash
130
+ uv venv && uv pip install -r requirements.txt
131
+ cd web/sveltekit && npm ci && npm run build && cd ../..
132
+ ollama pull granite4.1:3b
133
+ ollama pull granite4.1:8b
134
+ .venv/bin/uvicorn web.main:app --host 127.0.0.1 --port 7860
135
+ ```
136
+
137
+ Visit `http://127.0.0.1:7860`. Inference runs locally — no GPU
138
+ power readings (the chip will display the data-sheet estimate with
139
+ a `~` icon).
140
+
141
+ ### Local UI, remote inference
142
+
143
+ ```bash
144
+ RIPRAP_LLM_PRIMARY=vllm \
145
+ RIPRAP_LLM_BASE_URL=https://msradam-riprap-vllm.hf.space/v1 \
146
+ RIPRAP_LLM_API_KEY=<token> \
147
+ RIPRAP_ML_BACKEND=remote \
148
+ RIPRAP_ML_BASE_URL=https://msradam-riprap-vllm.hf.space \
149
+ RIPRAP_ML_API_KEY=<token> \
150
+ .venv/bin/uvicorn web.main:app --host 127.0.0.1 --port 7860
151
+ ```
152
+
153
+ Same flow as the hosted UI Space, but rendered locally. Real NVML
154
+ power readings come back through the proxy headers and bracket
155
+ samples just like in production.
156
+
157
+ ---
158
+
159
+ ## Deploy commands
160
+
161
+ | Target | Script | Notes |
162
+ |---|---|---|
163
+ | Inference Space (`msradam/riprap-vllm`) | `scripts/deploy_vllm_space.sh` | Orphan-branch push from `inference-vllm/` |
164
+ | UI Space (`lablab-ai-amd-developer-hackathon/riprap-nyc`) | cherry-pick onto `huggingface/main` then `git push huggingface` | HF Spaces' xet hook rejects pushes that walk through commits with binaries; cherry-picking from a clean ancestor avoids it |
165
+ | Personal mirror (`msradam/riprap`) | `scripts/deploy_personal_space.sh` | Orphan-branch push from `Dockerfile.l4` |
166
+ | Inference fallback (`msradam/riprap-inference`) | `scripts/deploy_inference_space.sh` | Ollama-backed mirror; redundant when riprap-vllm is up |
167
+
168
+ ---
169
+
170
+ ## Verifying a deploy
171
+
172
+ ```bash
173
+ PYTHONPATH=. uv run python scripts/probe_stones_fire.py --timeout 600
174
+ ```
175
+
176
+ Asserts: all five Stones fire, no torchvision/terratorch dep
177
+ regression, the `emissions` block reports `nvidia_l4` hardware, and
178
+ real NVML measurements come through (`n_measured` ≈ `n_calls`).
179
+
180
+ The address probe sweeps the full canonical set (5 NYC addresses):
181
+
182
+ ```bash
183
+ .venv/bin/python scripts/probe_addresses.py \
184
+ --base https://lablab-ai-amd-developer-hackathon-riprap-nyc.hf.space
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Historical notes
190
+
191
+ The hackathon submission was originally built against an AMD MI300X
192
+ DigitalOcean droplet (running both vLLM and the EO model service).
193
+ The droplet was decommissioned **2026-05-06** and inference moved
194
+ to the L4 HF Spaces above. The bring-up runbook for the MI300X
195
+ droplet is preserved in [`docs/DROPLET-RUNBOOK.md`](DROPLET-RUNBOOK.md)
196
+ for anyone reproducing the original AMD-judging setup; setting
197
+ `RIPRAP_HARDWARE_LABEL=AMD MI300X` on a droplet redeploy will swap
198
+ the emissions ledger back to the MI300X data-sheet figures.
docs/EMISSIONS.md ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Per-query inference energy ledger
2
+
3
+ Riprap surfaces the energy and token cost of every inference call it
4
+ makes during a briefing. The numbers are **measured off the L4 GPU**
5
+ when the inference Space is reachable — not data-sheet estimates.
6
+
7
+ ```
8
+ 5 Stones · 21 fired · 11 evidence cards · 14.0s wall-clock · ✓ 1.4 Wh / 6.9K tok inference
9
+ ```
10
+
11
+ The chip on the Findings status row reports total energy (Wh) plus
12
+ total tokens. The leading icon discloses how the number was derived:
13
+
14
+ | Icon | Meaning |
15
+ |---|---|
16
+ | `✓` | All recorded calls came back with a real NVML reading from the L4 GPU |
17
+ | `◐` | Some calls measured, others fell back to the data-sheet estimate |
18
+ | `~` | All calls used the data-sheet estimate (proxy unreachable, NVML disabled, or local-only run) |
19
+
20
+ Hover the chip for the full breakdown — call count, hardware, prompt
21
+ vs completion split, and the method.
22
+
23
+ ---
24
+
25
+ ## What's measured vs. what's estimated
26
+
27
+ | Field | Source |
28
+ |---|---|
29
+ | `duration_s` | Real wallclock on the client side (`time.monotonic` around each call) |
30
+ | `prompt_tokens`, `completion_tokens` | Reported by the model server (LiteLLM `usage` block) for non-stream LLM calls |
31
+ | `completion_tokens` (streaming) | Estimated as `len(response_text) / 4` when the backend doesn't surface a final usage block (Ollama path) |
32
+ | `power_w` | **Measured** — `nvmlDeviceGetPowerUsage` on the L4 inference Space, sampled every 100 ms, mean of samples bracketing each call |
33
+ | `wh`, `joules` | `power_w × duration_s` (when `measured: true`) or `data-sheet_W × duration_s` (when `measured: false`) |
34
+
35
+ Each call record on the ledger carries a `measured: bool` flag plus
36
+ the exact `power_w` value used so a reviewer can audit any row.
37
+
38
+ ---
39
+
40
+ ## How the measurement works
41
+
42
+ The L4 inference Space (`msradam/riprap-vllm`) runs a FastAPI proxy
43
+ in front of vLLM (port 8000) and the riprap-models EO service
44
+ (port 7861). The proxy initialises NVML at startup and runs a
45
+ background sampler that reads `nvmlDeviceGetPowerUsage` every
46
+ 100 ms into a 60-second ring buffer.
47
+
48
+ ```
49
+ inference-vllm/proxy.py::_power_sampler
50
+ ├── NVML init at startup, single L4 device handle
51
+ ├── 100 ms ring buffer (600 samples = 60 s of history)
52
+ └── degrades to no-op if NVML init fails
53
+ ```
54
+
55
+ When the proxy forwards a POST to vLLM or riprap-models, it stamps
56
+ the upstream call window `(t0, t1)` and computes the mean power
57
+ across the samples that fall inside that window. The result lands
58
+ on the response as headers:
59
+
60
+ ```
61
+ X-GPU-Power-W mean draw in watts
62
+ X-GPU-Energy-J energy in joules over the window
63
+ X-GPU-Duration-S forwarded-call duration in seconds
64
+ X-GPU-Device "NVIDIA L4"
65
+ ```
66
+
67
+ `app/inference.py::_post()` reads those headers off the proxy
68
+ response and forwards them into `emissions.Tracker.record_ml`. The
69
+ tracker stamps `measured=True` and uses the exact joule value.
70
+
71
+ For the LLM client path (`app/llm.py::chat()`) we route through
72
+ LiteLLM, which doesn't surface response headers. So instead the
73
+ client brackets the call with two GETs to `/v1/power`:
74
+
75
+ ```python
76
+ p0 = _sample_gpu_power_w() # ~50 ms, returns 1 s avg
77
+ t0 = time.monotonic()
78
+ resp = _router.completion(...) # the actual LLM call
79
+ duration_s = time.monotonic() - t0
80
+ p1 = _sample_gpu_power_w() # ~50 ms, returns 1 s avg
81
+ avg = (p0 + p1) / 2
82
+ ```
83
+
84
+ `avg` is the average power during the call; `avg × duration_s`
85
+ gives joules. The tracker records `power_w_real=avg`,
86
+ `joules_real=avg×duration_s`, and `measured=True`.
87
+
88
+ ---
89
+
90
+ ## Hardware profiles (`app/emissions.HARDWARE`)
91
+
92
+ The fallback path uses a sustained-power figure from the hardware
93
+ data sheet when no real measurement is available:
94
+
95
+ | Key | Label | Sustained W | Source |
96
+ |---|---|---|---|
97
+ | `nvidia_l4` | NVIDIA L4 | 60 | L4 data sheet (72 W TGP, Ada Lovelace) |
98
+ | `amd_mi300x` | AMD MI300X | 600 | MI300X data sheet (750 W TDP); used when `RIPRAP_HARDWARE_LABEL=AMD MI300X` |
99
+ | `nvidia_t4` | NVIDIA T4 | 50 | T4 data sheet (70 W max) |
100
+ | `apple_m` | Apple M-series | 20 | ml.energy / community measurements |
101
+ | `cpu_server` | x86 CPU | 30 | Typical sustained server-core load |
102
+
103
+ The fallback only fires when the proxy is unreachable, NVML init
104
+ failed, or the call streamed (we currently don't measure streamed
105
+ LLM calls precisely; they bracket-sample as best-effort).
106
+
107
+ ---
108
+
109
+ ## End-to-end shape
110
+
111
+ ```
112
+ Lablab UI Space (cpu-basic, FastAPI + SvelteKit)
113
+
114
+ │ Tracker installed per-query in web/main.py:
115
+ │ install(Tracker())
116
+
117
+ ├── planner — app/llm.py::chat
118
+ │ ├─ GET /v1/power (bracket-start)
119
+ │ ├─ POST /v1/chat/completions
120
+ │ └─ GET /v1/power (bracket-end)
121
+
122
+ ├── FSM specialists — app/inference.py::_post
123
+ │ POST /v1/{prithvi-pluvial, terramind, ...}
124
+ │ ← X-GPU-Power-W, X-GPU-Energy-J headers
125
+
126
+ └── reconciler — app/llm.py::chat (Mellea-validated)
127
+ same bracket pattern as planner
128
+
129
+
130
+ Tracker.summarize() → emissions block on /api/agent/stream final
131
+
132
+
133
+ SvelteKit RunHealthStrip — chip rendered with measured-icon
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Verifying
139
+
140
+ `scripts/probe_stones_fire.py` runs an end-to-end address query
141
+ against the lablab UI and asserts:
142
+
143
+ 1. All five Stones fire
144
+ 2. No specialist returns the legacy dep-regression strings
145
+ (`torchvision::nms`, `deps unavailable on this deployment:
146
+ terratorch`)
147
+ 3. The final `emissions` block carries `nvidia_l4` hardware and
148
+ non-zero tokens
149
+
150
+ ```bash
151
+ PYTHONPATH=. uv run python scripts/probe_stones_fire.py --timeout 600
152
+ ```
153
+
154
+ The first call after a Space restart pays a ~120 s vLLM CUDA-graph
155
+ compile penalty; warm queries land at < 0.5 Wh / ~7 K tokens.
156
+
157
+ ---
158
+
159
+ ## Why this matters
160
+
161
+ Inference cost is usually invisible. AI tools that publish a
162
+ "green" or "low-energy" claim mostly cite a vendor data sheet or a
163
+ research mean. Riprap reports the actual joules drawn off the
164
+ device under the load of a single user query — auditable down to
165
+ the row.
166
+
167
+ The raw ledger is shipped on the SSE `final` event under
168
+ `emissions.calls`, so any consumer (dashboard, billing model,
169
+ reproducibility check) can reuse the data without round-tripping
170
+ back through Riprap.
web/main.py CHANGED
@@ -12,7 +12,7 @@ from pathlib import Path
12
  warnings.filterwarnings("ignore")
13
 
14
  from fastapi import FastAPI, Request # noqa: E402
15
- from fastapi.responses import FileResponse, StreamingResponse # noqa: E402
16
  from fastapi.staticfiles import StaticFiles # noqa: E402
17
 
18
  from app import emissions # noqa: E402
@@ -96,6 +96,38 @@ app.mount("/static", StaticFiles(directory=STATIC), name="static")
96
  if SVELTEKIT_BUILD.exists():
97
  app.mount("/_app", StaticFiles(directory=SVELTEKIT_BUILD / "_app"), name="sveltekit_assets")
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  import json as _json # noqa: E402
100
 
101
  import geopandas as _gpd # noqa: E402
 
12
  warnings.filterwarnings("ignore")
13
 
14
  from fastapi import FastAPI, Request # noqa: E402
15
+ from fastapi.responses import FileResponse, JSONResponse, StreamingResponse # noqa: E402
16
  from fastapi.staticfiles import StaticFiles # noqa: E402
17
 
18
  from app import emissions # noqa: E402
 
96
  if SVELTEKIT_BUILD.exists():
97
  app.mount("/_app", StaticFiles(directory=SVELTEKIT_BUILD / "_app"), name="sveltekit_assets")
98
 
99
+ # Top-level static assets the SvelteKit build emits next to the HTML
100
+ # entry points (favicon.svg / favicon.png / robots.txt). These would
101
+ # fall through to the SPA fallback and 404 without explicit routes;
102
+ # adapter-static expects them under /, not /_app.
103
+ def _serve_build_asset(name: str):
104
+ p = SVELTEKIT_BUILD / name
105
+ if not p.exists():
106
+ return JSONResponse({"detail": "Not Found"}, status_code=404)
107
+ return FileResponse(p, headers={"Cache-Control": "public, max-age=86400"})
108
+
109
+
110
+ @app.get("/favicon.svg", include_in_schema=False)
111
+ def _favicon_svg():
112
+ return _serve_build_asset("favicon.svg")
113
+
114
+
115
+ @app.get("/favicon.png", include_in_schema=False)
116
+ def _favicon_png():
117
+ return _serve_build_asset("favicon.png")
118
+
119
+
120
+ @app.get("/favicon.ico", include_in_schema=False)
121
+ def _favicon_ico():
122
+ # No .ico in the build, but browsers still probe for it. Redirect-
123
+ # by-content to the PNG so the tab gets the dam mark either way.
124
+ return _serve_build_asset("favicon.png")
125
+
126
+
127
+ @app.get("/robots.txt", include_in_schema=False)
128
+ def _robots():
129
+ return _serve_build_asset("robots.txt")
130
+
131
  import json as _json # noqa: E402
132
 
133
  import geopandas as _gpd # noqa: E402
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.C_DzDADc.js" rel="modulepreload">
10
- <link href="/_app/immutable/chunks/DJJH9JR_.js" rel="modulepreload">
11
  <link href="/_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
12
- <link href="/_app/immutable/entry/app.DmxSSduu.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.DInKAumT.js" rel="modulepreload">
18
  <link href="/_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
19
- <link href="/_app/immutable/chunks/D8NyAcAP.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,15 +28,15 @@
28
  <div style="display: contents">
29
  <script>
30
  {
31
- __sveltekit_a2xq49 = {
32
  base: ""
33
  };
34
 
35
  const element = document.currentScript.parentElement;
36
 
37
  Promise.all([
38
- import("/_app/immutable/entry/start.C_DzDADc.js"),
39
- import("/_app/immutable/entry/app.DmxSSduu.js")
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.C7t2uk4E.js" rel="modulepreload">
10
+ <link href="/_app/immutable/chunks/B8_P3YrA.js" rel="modulepreload">
11
  <link href="/_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
12
+ <link href="/_app/immutable/entry/app.DaTkeYDu.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.Bxzl5Ruo.js" rel="modulepreload">
18
  <link href="/_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
19
+ <link href="/_app/immutable/chunks/Bs7n3R20.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_ual5r0 = {
32
  base: ""
33
  };
34
 
35
  const element = document.currentScript.parentElement;
36
 
37
  Promise.all([
38
+ import("/_app/immutable/entry/start.C7t2uk4E.js"),
39
+ import("/_app/immutable/entry/app.DaTkeYDu.js")
40
  ]).then(([kit, app]) => {
41
  kit.start(app, element);
42
  });
web/sveltekit/build/_app/immutable/chunks/{DJJH9JR_.js → B8_P3YrA.js} RENAMED
@@ -1 +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 $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_a2xq49)==null?void 0:ht.base)??"";var pt;const nn=((pt=globalThis.__sveltekit_a2xq49)==null?void 0:pt.assets)??U??"",rn="1778353518826",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:C};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,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: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(C)}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_a2xq49&&(globalThis.__sveltekit_a2xq49.query,globalThis.__sveltekit_a2xq49.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: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]??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 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 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(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 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 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 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 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 K;const w=V;V=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(),V===l&&(V=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,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 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=(K=Bt)==null?void 0:K()),At=!0}else await $t(g,Ve,!1);const{activeElement:$}=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!==$&&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)),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 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===$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(!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?$e(location)===$e(_.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&&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 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 $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 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(C),{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,j as s};
 
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 $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_ual5r0)==null?void 0:ht.base)??"";var pt;const nn=((pt=globalThis.__sveltekit_ual5r0)==null?void 0:pt.assets)??U??"",rn="1778356341060",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:C};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,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: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(C)}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_ual5r0&&(globalThis.__sveltekit_ual5r0.query,globalThis.__sveltekit_ual5r0.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: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]??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 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 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(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 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 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 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 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 K;const w=V;V=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(),V===l&&(V=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,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 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=(K=Bt)==null?void 0:K()),At=!0}else await $t(g,Ve,!1);const{activeElement:$}=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!==$&&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)),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 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===$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(!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?$e(location)===$e(_.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&&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 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 $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 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(C),{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,j as s};
web/sveltekit/build/_app/immutable/chunks/{D8NyAcAP.js → Bs7n3R20.js} RENAMED
@@ -1 +1 @@
1
- import{s as e,p as r}from"./DJJH9JR_.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};
 
1
+ import{s as e,p as r}from"./B8_P3YrA.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.DmxSSduu.js → app.DaTkeYDu.js} RENAMED
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.DInKAumT.js","../chunks/CWw6qgC_.js","../chunks/BTUA7_xE.js","../chunks/DxQlA7U2.js","../chunks/Bd-v_9Ud.js","../chunks/CW0zSL4D.js","../chunks/D8NyAcAP.js","../chunks/DJJH9JR_.js","../chunks/DCD6_LXk.js","../chunks/B0XoTt7U.js","../assets/RipMark.ClxF_PAC.css","../chunks/DixtWtwq.js","../assets/0.DiQNUxm-.css","../nodes/1.OjBWYT1y.js","../nodes/2.B2rqoVXS.js","../chunks/cDW0xQNP.js","../chunks/25_y8TFd.js","../chunks/CXQd8Y6F.js","../chunks/D907np-5.js","../assets/2.BD53GLFY.css","../nodes/3.CU36QLul.js","../chunks/BatqQaKj.js","../assets/Briefing.Dmn9LgiV.css","../assets/3.BZfqQRM0.css","../nodes/4.JuDtCP-e.js","../chunks/DDAjlznB.js","../assets/stoneRegistry.uOtksRcS.css","../assets/4.C9CQZyPb.css","../nodes/5.CRCvLD8F.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.DInKAumT.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]),import.meta.url),()=>b(()=>import("../nodes/1.OjBWYT1y.js"),__vite__mapDeps([13,1,2,6,7]),import.meta.url),()=>b(()=>import("../nodes/2.B2rqoVXS.js"),__vite__mapDeps([14,1,2,11,15,8,9,5,10,16,7,17,18,19]),import.meta.url),()=>b(()=>import("../nodes/3.CU36QLul.js"),__vite__mapDeps([20,1,2,4,16,15,6,7,21,5,3,9,22,23]),import.meta.url),()=>b(()=>import("../nodes/4.JuDtCP-e.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.CRCvLD8F.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};
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["../nodes/0.Bxzl5Ruo.js","../chunks/CWw6qgC_.js","../chunks/BTUA7_xE.js","../chunks/DxQlA7U2.js","../chunks/Bd-v_9Ud.js","../chunks/CW0zSL4D.js","../chunks/Bs7n3R20.js","../chunks/B8_P3YrA.js","../chunks/DCD6_LXk.js","../chunks/B0XoTt7U.js","../assets/RipMark.ClxF_PAC.css","../chunks/DixtWtwq.js","../assets/0.DiQNUxm-.css","../nodes/1.yqsn2Hmg.js","../nodes/2.6wNqJ7i-.js","../chunks/cDW0xQNP.js","../chunks/25_y8TFd.js","../chunks/CXQd8Y6F.js","../chunks/D907np-5.js","../assets/2.BD53GLFY.css","../nodes/3.Cw8Vd7-r.js","../chunks/BatqQaKj.js","../assets/Briefing.Dmn9LgiV.css","../assets/3.BZfqQRM0.css","../nodes/4.Ck4WhzVi.js","../chunks/DDAjlznB.js","../assets/stoneRegistry.uOtksRcS.css","../assets/4.C9CQZyPb.css","../nodes/5.CRCvLD8F.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.Bxzl5Ruo.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12]),import.meta.url),()=>b(()=>import("../nodes/1.yqsn2Hmg.js"),__vite__mapDeps([13,1,2,6,7]),import.meta.url),()=>b(()=>import("../nodes/2.6wNqJ7i-.js"),__vite__mapDeps([14,1,2,11,15,8,9,5,10,16,7,17,18,19]),import.meta.url),()=>b(()=>import("../nodes/3.Cw8Vd7-r.js"),__vite__mapDeps([20,1,2,4,16,15,6,7,21,5,3,9,22,23]),import.meta.url),()=>b(()=>import("../nodes/4.Ck4WhzVi.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.CRCvLD8F.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.C7t2uk4E.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{l as o,a as r}from"../chunks/B8_P3YrA.js";export{o as load_css,r as start};
web/sveltekit/build/_app/immutable/entry/start.C_DzDADc.js DELETED
@@ -1 +0,0 @@
1
- import{l as o,a as r}from"../chunks/DJJH9JR_.js";export{o as load_css,r as start};
 
 
web/sveltekit/build/_app/immutable/nodes/{0.DInKAumT.js → 0.Bxzl5Ruo.js} RENAMED
@@ -1,2 +1,2 @@
1
- import{c as E,a as u,s as M,f as v,d as z,e as H}from"../chunks/CWw6qgC_.js";import{p as O,f as R,o as p,a as $,al as f,s as t,c as o,r as i,t as P,aR as L}from"../chunks/BTUA7_xE.js";import{b as r,s as W}from"../chunks/DxQlA7U2.js";import{i as x}from"../chunks/Bd-v_9Ud.js";import{p as B}from"../chunks/CW0zSL4D.js";import{p as D}from"../chunks/D8NyAcAP.js";import{R as U}from"../chunks/DCD6_LXk.js";import{s as G}from"../chunks/B0XoTt7U.js";import"../chunks/DixtWtwq.js";const V=!0,J=!0,K="never",xe=Object.freeze(Object.defineProperty({__proto__:null,prerender:V,ssr:J,trailingSlash:K},Symbol.toStringTag,{value:"Module"}));var Q=v('<span class="status-sep svelte-1bjixce">·</span> <span class="status-step svelte-1bjixce"> </span>',1),X=v('<span class="status-sep svelte-1bjixce">·</span> <span class="status-progress svelte-1bjixce"> </span>',1),Z=v('<span class="status-sep svelte-1bjixce">·</span> <span class="status-err svelte-1bjixce"> </span>',1),ee=v('<span class="status svelte-1bjixce" aria-live="polite" aria-atomic="true"><span class="status-dot svelte-1bjixce" aria-hidden="true"></span> <span class="status-phase svelte-1bjixce"> </span> <!> <!> <!></span>');function ae(h,l){O(l,!0);const N={geocode:"geocoding",nta_resolve:"resolving NTA",sandy_inundation:"Sandy 2012",dep_stormwater:"DEP scenarios",floodnet:"FloodNet sensors",nyc311:"NYC 311 history",noaa_tides:"NOAA tides",nws_alerts:"NWS alerts",nws_obs:"NWS hourly obs",ttm_forecast:"TTM r2 surge (zero-shot)",ttm_311_forecast:"TTM r2 weekly 311",ttm_battery_surge:"TTM Battery (NYC fine-tune)",floodnet_forecast:"FloodNet recurrence forecast",ida_hwm_2021:"Ida 2021 HWMs",prithvi_eo_v2:"Ida 2021 polygons (baked lookup)",prithvi_eo_live:"Prithvi-NYC-Pluvial v2 segmentation",microtopo_lidar:"LiDAR microtopo",mta_entrance_exposure:"MTA entrances",nycha_development_exposure:"NYCHA developments",doe_school_exposure:"DOE schools",doh_hospital_exposure:"NYS DOH hospitals",terramind_synthesis:"TerraMind v1 synthesis",terramind_lulc:"TerraMind LULC",terramind_buildings:"TerraMind Buildings",eo_chip_fetch:"fetching S2/S1/DEM chip",rag_granite_embedding:"RAG retrieval",gliner_extract:"GLiNER typed extraction"};let T=f(()=>r.phase!=="idle"&&r.phase!=="done"),k=f(()=>{switch(r.phase){case"planning":return"planning intent";case"specialists":return"gathering evidence";case"reconciling":return"reconciling";case"streaming":return r.attempt>1?`writing (reroll ${r.attempt-1})`:"writing briefing";case"error":return"error";default:return""}}),g=f(()=>{const a=r.activeStep;return a?N[a]??a:null}),m=f(()=>{if(r.phase!=="specialists"&&r.phase!=="reconciling")return null;const a=r.firedCount,d=r.totalSpecialists;return d?`${a}/${d}`:a>0?`${a}`:null}),w=f(()=>r.phase==="error"?"err":"live");var A=E(),_=R(A);{var j=a=>{var d=ee(),e=t(o(d),2),C=o(e,!0);i(e);var S=t(e,2);{var s=n=>{var b=Q(),y=t(R(b),2),q=o(y,!0);i(y),P(()=>M(q,p(g))),u(n,b)};x(S,n=>{p(g)&&n(s)})}var c=t(S,2);{var F=n=>{var b=X(),y=t(R(b),2),q=o(y,!0);i(y),P(()=>M(q,p(m))),u(n,b)};x(c,n=>{p(m)&&n(F)})}var Y=t(c,2);{var I=n=>{var b=Z(),y=t(R(b),2),q=o(y,!0);i(y),P(()=>M(q,r.errorMessage)),u(n,b)};x(Y,n=>{r.phase==="error"&&r.errorMessage&&n(I)})}i(d),P(()=>{G(d,"data-kind",p(w)),M(C,p(k))}),u(a,d)};x(_,a=>{p(T)&&a(j)})}u(h,A),$()}var re=v('<button type="button" class="app-header-query" aria-label="Edit query"><span class="app-header-query-icon" aria-hidden="true">⌕</span> <span class="app-header-query-text"> </span> <span class="app-header-query-edit">edit</span></button>'),te=v('<button type="button" class="app-header-link app-header-link-button svelte-f1belb" aria-label="Open curated PDF view of completed briefing in new tab">export PDF</button>'),se=v('<header class="app-header no-print" data-screen-label="App header"><div class="app-header-inner"><div class="app-header-left"><a href="/" class="riprap-wordmark" aria-label="Riprap — home"><!>riprap</a> <span class="app-header-sep">/</span> <span class="app-header-context">flood-exposure briefing</span></div> <div class="app-header-mid"><!></div> <div class="app-header-right"><a class="app-header-link" href="#methodology">methodology</a> <!> <!></div></div></header>');function ne(h,l){O(l,!0);let N=B(l,"query",3,null);function T(){if(typeof window>"u")return;const s=D.params.queryId??(D.url.pathname==="/q/sample"?"sample":"");s&&window.open(`/print/${encodeURIComponent(s)}`,"_blank","noopener")}var k=se(),g=o(k),m=o(g),w=o(m),A=o(w);U(A,{size:20}),L(),i(w),L(4),i(m);var _=t(m,2),j=o(_);{var a=s=>{var c=re(),F=t(o(c),2),Y=o(F,!0);i(F),L(2),i(c),P(()=>M(Y,N())),H("click",c,function(...I){var n;(n=l.onResetCold)==null||n.apply(this,I)}),u(s,c)};x(j,s=>{N()&&s(a)})}i(_);var d=t(_,2),e=t(o(d),2);{var C=s=>{var c=te();H("click",c,T),u(s,c)};x(e,s=>{r.ready&&s(C)})}var S=t(e,2);ae(S,{}),i(d),i(g),i(k),u(h,k),$()}z(["click"]);var oe=v(`<footer class="app-footer no-print"><div class="app-footer-inner"><p class="app-footer-guard"><strong>Riprap does not predict damage.</strong> This tool is for professional analytical work, not personal property decisions.
2
  For residents, see <a href="https://www.floodhelpny.org">FloodHelpNY</a> · <a href="https://www.floodnet.nyc">FloodNet NYC</a>.</p> <p class="app-footer-build">All foundation models Apache-2.0 · All data from public-record federal, state, and city sources · No commercial APIs contacted at runtime · Riprap v0.5.0 · build 2026-05-07</p> <p class="app-footer-credits">Dam mark: <a href="https://thenounproject.com/icon/dam-4516918/">"Dam" by Chintuza</a> via the Noun Project, CC-BY 3.0.</p></div></footer>`);function ie(h){var l=oe();u(h,l)}var pe=v('<a href="#region-briefing" class="skip-link">Skip to briefing</a> <a href="#region-map" class="skip-link" style="left: -9999px;">Skip to map</a> <a href="#region-trace" class="skip-link" style="left: -9999px;">Skip to trace</a>',1);function le(h){var l=pe();L(4),u(h,l)}var de=v("<!> <!>",1),ce=v('<!> <main class="svelte-12qhfyh"><!></main> <!>',1);function ke(h,l){O(l,!0);let N=f(()=>()=>{const e=D.params.queryId;if(!e)return null;try{return decodeURIComponent(e)}catch{return e}}),T=f(()=>D.url.pathname.startsWith("/print/")),k=f(()=>D.url.pathname==="/"),g=f(()=>p(T)||p(k));var m=ce(),w=R(m);{var A=e=>{var C=de(),S=R(C);le(S);var s=t(S,2);{let c=f(()=>p(N)());ne(s,{get query(){return p(c)},onResetCold:()=>window.location.href="/"})}u(e,C)};x(w,e=>{p(g)||e(A)})}var _=t(w,2),j=o(_);W(j,()=>l.children),i(_);var a=t(_,2);{var d=e=>{ie(e)};x(a,e=>{p(g)||e(d)})}u(h,m),$()}export{ke as component,xe as universal};
 
1
+ import{c as E,a as u,s as M,f as v,d as z,e as H}from"../chunks/CWw6qgC_.js";import{p as O,f as R,o as p,a as $,al as f,s as t,c as o,r as i,t as P,aR as L}from"../chunks/BTUA7_xE.js";import{b as r,s as W}from"../chunks/DxQlA7U2.js";import{i as x}from"../chunks/Bd-v_9Ud.js";import{p as B}from"../chunks/CW0zSL4D.js";import{p as D}from"../chunks/Bs7n3R20.js";import{R as U}from"../chunks/DCD6_LXk.js";import{s as G}from"../chunks/B0XoTt7U.js";import"../chunks/DixtWtwq.js";const V=!0,J=!0,K="never",xe=Object.freeze(Object.defineProperty({__proto__:null,prerender:V,ssr:J,trailingSlash:K},Symbol.toStringTag,{value:"Module"}));var Q=v('<span class="status-sep svelte-1bjixce">·</span> <span class="status-step svelte-1bjixce"> </span>',1),X=v('<span class="status-sep svelte-1bjixce">·</span> <span class="status-progress svelte-1bjixce"> </span>',1),Z=v('<span class="status-sep svelte-1bjixce">·</span> <span class="status-err svelte-1bjixce"> </span>',1),ee=v('<span class="status svelte-1bjixce" aria-live="polite" aria-atomic="true"><span class="status-dot svelte-1bjixce" aria-hidden="true"></span> <span class="status-phase svelte-1bjixce"> </span> <!> <!> <!></span>');function ae(h,l){O(l,!0);const N={geocode:"geocoding",nta_resolve:"resolving NTA",sandy_inundation:"Sandy 2012",dep_stormwater:"DEP scenarios",floodnet:"FloodNet sensors",nyc311:"NYC 311 history",noaa_tides:"NOAA tides",nws_alerts:"NWS alerts",nws_obs:"NWS hourly obs",ttm_forecast:"TTM r2 surge (zero-shot)",ttm_311_forecast:"TTM r2 weekly 311",ttm_battery_surge:"TTM Battery (NYC fine-tune)",floodnet_forecast:"FloodNet recurrence forecast",ida_hwm_2021:"Ida 2021 HWMs",prithvi_eo_v2:"Ida 2021 polygons (baked lookup)",prithvi_eo_live:"Prithvi-NYC-Pluvial v2 segmentation",microtopo_lidar:"LiDAR microtopo",mta_entrance_exposure:"MTA entrances",nycha_development_exposure:"NYCHA developments",doe_school_exposure:"DOE schools",doh_hospital_exposure:"NYS DOH hospitals",terramind_synthesis:"TerraMind v1 synthesis",terramind_lulc:"TerraMind LULC",terramind_buildings:"TerraMind Buildings",eo_chip_fetch:"fetching S2/S1/DEM chip",rag_granite_embedding:"RAG retrieval",gliner_extract:"GLiNER typed extraction"};let T=f(()=>r.phase!=="idle"&&r.phase!=="done"),k=f(()=>{switch(r.phase){case"planning":return"planning intent";case"specialists":return"gathering evidence";case"reconciling":return"reconciling";case"streaming":return r.attempt>1?`writing (reroll ${r.attempt-1})`:"writing briefing";case"error":return"error";default:return""}}),g=f(()=>{const a=r.activeStep;return a?N[a]??a:null}),m=f(()=>{if(r.phase!=="specialists"&&r.phase!=="reconciling")return null;const a=r.firedCount,d=r.totalSpecialists;return d?`${a}/${d}`:a>0?`${a}`:null}),w=f(()=>r.phase==="error"?"err":"live");var A=E(),_=R(A);{var j=a=>{var d=ee(),e=t(o(d),2),C=o(e,!0);i(e);var S=t(e,2);{var s=n=>{var b=Q(),y=t(R(b),2),q=o(y,!0);i(y),P(()=>M(q,p(g))),u(n,b)};x(S,n=>{p(g)&&n(s)})}var c=t(S,2);{var F=n=>{var b=X(),y=t(R(b),2),q=o(y,!0);i(y),P(()=>M(q,p(m))),u(n,b)};x(c,n=>{p(m)&&n(F)})}var Y=t(c,2);{var I=n=>{var b=Z(),y=t(R(b),2),q=o(y,!0);i(y),P(()=>M(q,r.errorMessage)),u(n,b)};x(Y,n=>{r.phase==="error"&&r.errorMessage&&n(I)})}i(d),P(()=>{G(d,"data-kind",p(w)),M(C,p(k))}),u(a,d)};x(_,a=>{p(T)&&a(j)})}u(h,A),$()}var re=v('<button type="button" class="app-header-query" aria-label="Edit query"><span class="app-header-query-icon" aria-hidden="true">⌕</span> <span class="app-header-query-text"> </span> <span class="app-header-query-edit">edit</span></button>'),te=v('<button type="button" class="app-header-link app-header-link-button svelte-f1belb" aria-label="Open curated PDF view of completed briefing in new tab">export PDF</button>'),se=v('<header class="app-header no-print" data-screen-label="App header"><div class="app-header-inner"><div class="app-header-left"><a href="/" class="riprap-wordmark" aria-label="Riprap — home"><!>riprap</a> <span class="app-header-sep">/</span> <span class="app-header-context">flood-exposure briefing</span></div> <div class="app-header-mid"><!></div> <div class="app-header-right"><a class="app-header-link" href="#methodology">methodology</a> <!> <!></div></div></header>');function ne(h,l){O(l,!0);let N=B(l,"query",3,null);function T(){if(typeof window>"u")return;const s=D.params.queryId??(D.url.pathname==="/q/sample"?"sample":"");s&&window.open(`/print/${encodeURIComponent(s)}`,"_blank","noopener")}var k=se(),g=o(k),m=o(g),w=o(m),A=o(w);U(A,{size:20}),L(),i(w),L(4),i(m);var _=t(m,2),j=o(_);{var a=s=>{var c=re(),F=t(o(c),2),Y=o(F,!0);i(F),L(2),i(c),P(()=>M(Y,N())),H("click",c,function(...I){var n;(n=l.onResetCold)==null||n.apply(this,I)}),u(s,c)};x(j,s=>{N()&&s(a)})}i(_);var d=t(_,2),e=t(o(d),2);{var C=s=>{var c=te();H("click",c,T),u(s,c)};x(e,s=>{r.ready&&s(C)})}var S=t(e,2);ae(S,{}),i(d),i(g),i(k),u(h,k),$()}z(["click"]);var oe=v(`<footer class="app-footer no-print"><div class="app-footer-inner"><p class="app-footer-guard"><strong>Riprap does not predict damage.</strong> This tool is for professional analytical work, not personal property decisions.
2
  For residents, see <a href="https://www.floodhelpny.org">FloodHelpNY</a> · <a href="https://www.floodnet.nyc">FloodNet NYC</a>.</p> <p class="app-footer-build">All foundation models Apache-2.0 · All data from public-record federal, state, and city sources · No commercial APIs contacted at runtime · Riprap v0.5.0 · build 2026-05-07</p> <p class="app-footer-credits">Dam mark: <a href="https://thenounproject.com/icon/dam-4516918/">"Dam" by Chintuza</a> via the Noun Project, CC-BY 3.0.</p></div></footer>`);function ie(h){var l=oe();u(h,l)}var pe=v('<a href="#region-briefing" class="skip-link">Skip to briefing</a> <a href="#region-map" class="skip-link" style="left: -9999px;">Skip to map</a> <a href="#region-trace" class="skip-link" style="left: -9999px;">Skip to trace</a>',1);function le(h){var l=pe();L(4),u(h,l)}var de=v("<!> <!>",1),ce=v('<!> <main class="svelte-12qhfyh"><!></main> <!>',1);function ke(h,l){O(l,!0);let N=f(()=>()=>{const e=D.params.queryId;if(!e)return null;try{return decodeURIComponent(e)}catch{return e}}),T=f(()=>D.url.pathname.startsWith("/print/")),k=f(()=>D.url.pathname==="/"),g=f(()=>p(T)||p(k));var m=ce(),w=R(m);{var A=e=>{var C=de(),S=R(C);le(S);var s=t(S,2);{let c=f(()=>p(N)());ne(s,{get query(){return p(c)},onResetCold:()=>window.location.href="/"})}u(e,C)};x(w,e=>{p(g)||e(A)})}var _=t(w,2),j=o(_);W(j,()=>l.children),i(_);var a=t(_,2);{var d=e=>{ie(e)};x(a,e=>{p(g)||e(d)})}u(h,m),$()}export{ke as component,xe as universal};
web/sveltekit/build/_app/immutable/nodes/{1.OjBWYT1y.js → 1.yqsn2Hmg.js} RENAMED
@@ -1 +1 @@
1
- import{a as c,f as u,s as e}from"../chunks/CWw6qgC_.js";import{p as v,f as l,t as _,a as g,c as p,r as o,s as x}from"../chunks/BTUA7_xE.js";import{p as m}from"../chunks/D8NyAcAP.js";var d=u("<h1> </h1> <p> </p>",1);function k(f,i){v(i,!0);var t=d(),r=l(t),h=p(r,!0);o(r);var a=x(r,2),n=p(a,!0);o(a),_(()=>{var s;e(h,m.status),e(n,(s=m.error)==null?void 0:s.message)}),c(f,t),g()}export{k as component};
 
1
+ import{a as c,f as u,s as e}from"../chunks/CWw6qgC_.js";import{p as v,f as l,t as _,a as g,c as p,r as o,s as x}from"../chunks/BTUA7_xE.js";import{p as m}from"../chunks/Bs7n3R20.js";var d=u("<h1> </h1> <p> </p>",1);function k(f,i){v(i,!0);var t=d(),r=l(t),h=p(r,!0);o(r);var a=x(r,2),n=p(a,!0);o(a),_(()=>{var s;e(h,m.status),e(n,(s=m.error)==null?void 0:s.message)}),c(f,t),g()}export{k as component};
web/sveltekit/build/_app/immutable/nodes/{2.B2rqoVXS.js → 2.6wNqJ7i-.js} RENAMED
@@ -1,4 +1,4 @@
1
- import{a as m,f as w,d as D,l as I,e as G,s as g}from"../chunks/CWw6qgC_.js";import"../chunks/DixtWtwq.js";import{b9 as U,y as S,ar as K,$ as R,_ as V,h as Q,Y as Z,aq as J,am as E,ba as q,bb as X,o as d,bc as ee,af as ae,c,aR as k,r as o,p as P,a5 as N,a as M,a4 as A,s as f,t as T,ai as se,Z as te,ak as re}from"../chunks/BTUA7_xE.js";import{h as ne}from"../chunks/cDW0xQNP.js";import{R as le}from"../chunks/DCD6_LXk.js";import{e as $}from"../chunks/25_y8TFd.js";import{r as ie,a as oe,s as de,b as ce}from"../chunks/B0XoTt7U.js";import{g as B}from"../chunks/DJJH9JR_.js";import{b as ve,_ as pe}from"../chunks/CXQd8Y6F.js";import{P as fe}from"../chunks/D907np-5.js";function ue(e,s,r=s){var t=new WeakSet;U(e,"input",async a=>{var n=a?e.defaultValue:e.value;if(n=L(e)?C(n):n,r(n),S!==null&&t.add(S),await K(),n!==(n=s())){var u=e.selectionStart,l=e.selectionEnd,v=e.value.length;if(e.value=n??"",l!==null){var i=e.value.length;u===l&&l===v&&i>v?(e.selectionStart=i,e.selectionEnd=i):(e.selectionStart=u,e.selectionEnd=Math.min(l,i))}}}),(Q&&e.defaultValue!==e.value||R(s)==null&&e.value)&&(r(L(e)?C(e.value):e.value),S!==null&&t.add(S)),V(()=>{var a=s();if(e===document.activeElement){var n=S;if(t.has(n))return}L(e)&&a===C(e.value)||e.type==="date"&&!a&&!e.value||a!==e.value&&(e.value=a??"")})}function L(e){var s=e.type;return s==="number"||s==="range"}function C(e){return e===""?null:+e}function me(e=!1){const s=Z,r=s.l.u;if(!r)return;let t=()=>ee(s.s);if(e){let a=0,n={};const u=ae(()=>{let l=!1;const v=s.s;for(const i in v)v[i]!==n[i]&&(n[i]=v[i],l=!0);return l&&a++,a});t=()=>d(u)}r.b.length&&J(()=>{H(s,t),q(r.b)}),E(()=>{const a=R(()=>r.m.map(X));return()=>{for(const n of a)typeof n=="function"&&n()}}),r.a.length&&E(()=>{H(s,t),q(r.a)})}function H(e,s){if(e.l.s)for(const r of e.l.s)d(r);s()}var we=w('<header class="land-header svelte-1ct2rgk"><span class="riprap-wordmark"><!>riprap</span> <span class="land-header-sep svelte-1ct2rgk">/</span> <span class="land-header-context svelte-1ct2rgk">Flood Exposure Briefing · NYC</span> <nav class="land-header-nav svelte-1ct2rgk"><a href="#methodology" class="svelte-1ct2rgk">Methodology</a> <a href="#sources" class="svelte-1ct2rgk">Sources</a></nav></header>');function he(e){var s=we(),r=c(s),t=c(r);le(t,{size:22}),k(),o(r),k(6),o(s),m(e,s)}var ye=w("<span> </span>"),ge=w('<main class="land-hero svelte-drzq4r"><h1 class="land-hero-h1 svelte-drzq4r"><span class="land-hero-headline svelte-drzq4r">A flood exposure briefing<br/> for <em class="svelte-drzq4r">any place</em> in New York City.</span> <span class="land-hero-deck svelte-drzq4r">Type an address. Get a written briefing where every numeric claim links to its primary public-record source.</span></h1> <form class="land-query svelte-drzq4r" role="search"><span class="land-query-prompt svelte-drzq4r" aria-hidden="true">›</span> <input type="text" placeholder="Address, neighborhood, or BBL. e.g. 80 Pioneer Street, Red Hook" class="land-query-input svelte-drzq4r" aria-label="Query an address, neighborhood, or BBL"/> <button type="submit" class="land-query-submit svelte-drzq4r">Brief this place →</button></form> <div class="land-cycling svelte-drzq4r" aria-live="polite"><span class="land-cycling-label svelte-drzq4r">Try:</span> <button type="button" class="land-cycling-rail svelte-drzq4r" title="Run this example"></button></div></main>');function je(e,s){P(s,!0);const r=["80 Pioneer Street, Red Hook","Coney Island Hospital","PS 188, Lower East Side","Hammels Houses, Rockaway","Bowling Green station","555 W 57th Street"];let t=A(""),a=A(0);E(()=>{if(typeof window>"u")return;const p=setInterval(()=>{N(a,(d(a)+1)%r.length)},2200);return()=>clearInterval(p)});function n(){const p=d(t).trim();p&&B(`/q/${encodeURIComponent(p)}`)}function u(){const p=r[d(a)];B(`/q/${encodeURIComponent(p)}`)}var l=ge(),v=f(c(l),2),i=f(c(v),2);ie(i),k(2),o(v);var j=f(v,2),y=f(c(j),2);$(y,22,()=>r,p=>p,(p,b,F)=>{var h=ye();let x;var _=c(h,!0);o(h),T(()=>{x=oe(h,1,"land-cycling-item svelte-drzq4r",null,x,{"is-active":d(F)===d(a)}),de(h,"aria-hidden",d(F)!==d(a)),g(_,b)}),m(p,h)}),o(y),o(j),o(l),I("submit",v,p=>{p.preventDefault(),n()}),ue(i,()=>d(t),p=>N(t,p)),G("click",y,u),m(e,l),M()}D(["click"]);var be=w('<div class="land-mapmini svelte-1g1r73s" role="img" aria-label="Live mini-map preview of Red Hook flood exposure layers"><div class="land-mapmini-canvas svelte-1g1r73s"></div> <div class="land-mapmini-legend svelte-1g1r73s"><span class="svelte-1g1r73s"><span class="lm-sw lm-sw-emp svelte-1g1r73s"></span>empirical</span> <span class="svelte-1g1r73s"><span class="lm-sw lm-sw-mod svelte-1g1r73s"></span>modeled</span> <span class="svelte-1g1r73s"><span class="lm-sw lm-sw-prx svelte-1g1r73s"></span>proxy</span></div></div>');function _e(e,s){P(s,!0);const r=[-74.0096,40.6776];let t=A(null),a=null;se(()=>{let l=!1;return(async()=>{if(!d(t)||l)return;const v=await pe(()=>import("../chunks/D4L2lGt1.js").then(i=>i.m),[],import.meta.url);l||!d(t)||(a=new v.Map({container:d(t),style:fe,center:r,zoom:14.5,interactive:!1,attributionControl:!1}),a.on("load",()=>{a&&(a.addSource("fema-ae",{type:"geojson",data:{type:"FeatureCollection",features:[{type:"Feature",properties:{},geometry:{type:"Polygon",coordinates:[[[-74.014,40.679],[-74.007,40.68],[-74.005,40.677],[-74.009,40.6755],[-74.014,40.679]]]}}]}}),a.addLayer({id:"fema-ae-fill",type:"fill",source:"fema-ae",paint:{"fill-color":"#2A6FA8","fill-opacity":.22}}),a.addLayer({id:"fema-ae-line",type:"line",source:"fema-ae",paint:{"line-color":"#2A6FA8","line-width":1,"line-dasharray":[3,2]}}),a.addSource("hwm-contour",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"LineString",coordinates:[[-74.0125,40.679],[-74.0105,40.6792],[-74.008,40.679],[-74.006,40.6786]]}}}),a.addLayer({id:"hwm-contour-line",type:"line",source:"hwm-contour",paint:{"line-color":"#0B5394","line-width":1.4}}),a.addSource("proxy-311",{type:"geojson",data:{type:"FeatureCollection",features:[[-74.0118,40.677],[-74.0114,40.6767],[-74.0121,40.6772]].map(i=>({type:"Feature",properties:{},geometry:{type:"Point",coordinates:i}}))}}),a.addLayer({id:"proxy-311-circle",type:"circle",source:"proxy-311",paint:{"circle-radius":3,"circle-color":"transparent","circle-stroke-color":"#6B6B6B","circle-stroke-width":1}}),a.addSource("floodnet",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"Point",coordinates:[-74.0103,40.6788]}}}),a.addLayer({id:"floodnet-pin",type:"circle",source:"floodnet",paint:{"circle-radius":4,"circle-color":"#0B5394","circle-stroke-color":"#FFFFFF","circle-stroke-width":1}}),a.addSource("addr",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"Point",coordinates:r}}}),a.addLayer({id:"addr-ring",type:"circle",source:"addr",paint:{"circle-radius":9,"circle-color":"transparent","circle-stroke-color":"#0F172A","circle-stroke-width":1.4}}),a.addLayer({id:"addr-dot",type:"circle",source:"addr",paint:{"circle-radius":3,"circle-color":"#0F172A"}}))}))})(),()=>{l=!0,a&&(a.remove(),a=null)}});var n=be(),u=c(n);ve(u,l=>N(t,l),()=>d(t)),k(2),o(n),m(e,n),M()}var Se=w(`<section class="land-section svelte-1anw2jf"><div class="land-section-head svelte-1anw2jf"><span class="section-label">What you'll get back</span> <span class="land-section-meta svelte-1anw2jf">A grounded paragraph with citations, not a chatbot answer.</span></div> <div class="land-preview-grid svelte-1anw2jf"><div class="land-preview-pane land-preview-pane-excerpt svelte-1anw2jf"><div class="land-preview-eyebrow svelte-1anw2jf">Briefing excerpt</div> <p class="land-preview-body svelte-1anw2jf">The lot sits inside the FEMA <span class="land-preview-cite svelte-1anw2jf">1% AE flood zone <sup class="svelte-1anw2jf">[c3]</sup></span>,
2
  with Sandy high-water marks recorded <span class="land-preview-cite svelte-1anw2jf">4.7 ft above grade <sup class="svelte-1anw2jf">[c1]</sup></span>.
3
  FloodNet FN-BK-018 has logged <span class="land-preview-cite svelte-1anw2jf">14 nuisance floods since 2023 <sup class="svelte-1anw2jf">[c2]</sup></span>.</p> <div class="land-preview-cites svelte-1anw2jf"><div class="land-preview-cite-row svelte-1anw2jf"><span class="land-preview-cite-pin svelte-1anw2jf">[c1]</span> <span class="land-preview-cite-src svelte-1anw2jf">USGS HWM · Sandy 2012</span> <span class="land-preview-cite-tier svelte-1anw2jf">empirical</span></div> <div class="land-preview-cite-row svelte-1anw2jf"><span class="land-preview-cite-pin svelte-1anw2jf">[c2]</span> <span class="land-preview-cite-src svelte-1anw2jf">FloodNet FN-BK-018</span> <span class="land-preview-cite-tier svelte-1anw2jf">empirical</span></div> <div class="land-preview-cite-row svelte-1anw2jf"><span class="land-preview-cite-pin svelte-1anw2jf">[c3]</span> <span class="land-preview-cite-src svelte-1anw2jf">FEMA NFHL · 36047C0207</span> <span class="land-preview-cite-tier svelte-1anw2jf">modeled</span></div></div></div> <div class="land-preview-pane land-preview-pane-cards svelte-1anw2jf"><div class="land-preview-eyebrow svelte-1anw2jf">Evidence cards</div> <div class="land-evcard-grid svelte-1anw2jf"><article class="land-evcard land-evcard-empirical svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">empirical</span> <span class="land-evcard-id svelte-1anw2jf">e1</span></header> <div class="land-evcard-claim svelte-1anw2jf">4.7 ft Sandy storm-surge HWM at address</div> <div class="land-evcard-source svelte-1anw2jf">USGS High-Water Mark database · 2012</div></article> <article class="land-evcard land-evcard-empirical svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">empirical</span> <span class="land-evcard-id svelte-1anw2jf">e2</span></header> <div class="land-evcard-claim svelte-1anw2jf">14 nuisance-flood events, 2023–2026</div> <div class="land-evcard-source svelte-1anw2jf">FloodNet FN-BK-018 · 2 blocks north</div></article> <article class="land-evcard land-evcard-modeled svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">modeled</span> <span class="land-evcard-id svelte-1anw2jf">e3</span></header> <div class="land-evcard-claim svelte-1anw2jf">FEMA 1% annual-chance (AE) flood zone</div> <div class="land-evcard-source svelte-1anw2jf">FEMA NFHL · panel 36047C0207</div></article> <article class="land-evcard land-evcard-modeled svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">modeled</span> <span class="land-evcard-id svelte-1anw2jf">e5</span></header> <div class="land-evcard-claim svelte-1anw2jf">+30 in MSL by 2070 (NPCC4 high)</div> <div class="land-evcard-source svelte-1anw2jf">NPCC4 SLR projection · 2024</div></article></div></div> <div class="land-preview-pane land-preview-pane-map svelte-1anw2jf"><div class="land-preview-eyebrow svelte-1anw2jf">Map</div> <!> <div class="land-preview-mapmeta svelte-1anw2jf">80 Pioneer St, Red Hook · z14.5 · Carto Positron</div></div></div></section>`);function ke(e){var s=Se(),r=f(c(s),2),t=f(c(r),4),a=f(c(t),2);_e(a,{}),k(2),o(t),o(r),o(s),m(e,s)}var Fe=w('<article class="land-stones-detail-cell svelte-1v6nt1t"><div class="land-stones-detail-num svelte-1v6nt1t"> </div> <h3 class="land-stones-detail-name svelte-1v6nt1t"> </h3> <div class="land-stones-detail-role svelte-1v6nt1t"> </div> <p class="land-stones-detail-tag svelte-1v6nt1t"> </p> <div class="land-stones-detail-sources svelte-1v6nt1t"> </div></article>'),xe=w(`<section class="land-section-stones-detail svelte-1v6nt1t" id="methodology"><div class="land-page svelte-1v6nt1t"><div class="land-section-head svelte-1v6nt1t"><span class="section-label">How Riprap reads a place</span> <span class="land-section-meta svelte-1v6nt1t">Five Stones · one taxonomy · every briefing</span></div> <p class="land-stones-deck svelte-1v6nt1t">Each briefing routes through a fixed taxonomy of public-record specialists. Each Stone is a class of evidence.
4
  Together they form the briefing, and every claim in the output traces back to the Stone that produced it.</p> <div class="land-stones-detail svelte-1v6nt1t"></div></div></section>`);function Le(e,s){P(s,!1);const r=[{name:"Cornerstone",role:"the hazard reader",tag:"what NYC's ground remembers",sources:"USGS HWMs · FEMA NFHL · DEP stormwater · Prithvi historical",tint:"var(--stone-cornerstone)"},{name:"Keystone",role:"the asset register",tag:"what's exposed",sources:"MTA · NYCHA · DOE · DOH · PLUTO",tint:"var(--stone-keystone)"},{name:"Touchstone",role:"the live observer",tag:"what's happening now",sources:"FloodNet sensors · 311 complaints · NWS · NOAA tide gauges",tint:"var(--stone-touchstone)"},{name:"Lodestone",role:"the projector",tag:"what's coming",sources:"NPCC4 · Granite TTM (zero-shot + NYC fine-tune) · NWS alerts",tint:"var(--stone-lodestone)"},{name:"Capstone",role:"the synthesizer",tag:"writes it all down",sources:"Granite 4.1 composer · Mellea grounding-check · WeasyPrint",tint:"var(--stone-capstone)"}];me();var t=xe(),a=c(t),n=f(c(a),4);$(n,7,()=>r,u=>u.name,(u,l,v)=>{var i=Fe();let j;var y=c(i),p=c(y,!0);o(y);var b=f(y,2),F=c(b,!0);o(b);var h=f(b,2),x=c(h,!0);o(h);var _=f(h,2),O=c(_,!0);o(_);var z=f(_,2),W=c(z,!0);o(z),o(i),T(Y=>{j=ce(i,"",j,{"--stone-tint":d(l).tint}),g(p,Y),g(F,d(l).name),g(x,d(l).role),g(O,d(l).tag),g(W,d(l).sources)},[()=>String(d(v)+1).padStart(2,"0")]),m(u,i)}),o(n),o(a),o(t),m(e,t),M()}var Ce=w('<footer class="land-footer svelte-1dcj612"><span class="land-footer-tiers svelte-1dcj612"><span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-emp svelte-1dcj612"></span>empirical</span> <span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-mod svelte-1dcj612"></span>modeled</span> <span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-prx svelte-1dcj612"></span>proxy</span> <span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-syn svelte-1dcj612"></span>synthetic</span></span> <span class="land-footer-build">Riprap v0.4.6 · NYC OpenData · FEMA NFHL · USGS · NPCC4 · Dam mark by Chintuza, Noun Project (CC-BY)</span></footer>');function Ee(e){var s=Ce();m(e,s)}var Ne=w('<meta name="description" content="A citation-grounded flood-exposure briefing tool for any address, neighborhood, or BBL in New York City."/>'),Ae=w('<div class="land svelte-1uha8ag"><!> <div class="land-page svelte-1uha8ag"><!> <!></div> <!> <!></div>');function We(e){var s=Ae();ne("1uha8ag",v=>{var i=Ne();te(()=>{re.title="Riprap — Flood Exposure Briefing for NYC"}),m(v,i)});var r=c(s);he(r);var t=f(r,2),a=c(t);je(a,{});var n=f(a,2);ke(n),o(t);var u=f(t,2);Le(u,{});var l=f(u,2);Ee(l),o(s),m(e,s)}export{We as component};
 
1
+ import{a as m,f as w,d as D,l as I,e as G,s as g}from"../chunks/CWw6qgC_.js";import"../chunks/DixtWtwq.js";import{b9 as U,y as S,ar as K,$ as R,_ as V,h as Q,Y as Z,aq as J,am as E,ba as q,bb as X,o as d,bc as ee,af as ae,c,aR as k,r as o,p as P,a5 as N,a as M,a4 as A,s as f,t as T,ai as se,Z as te,ak as re}from"../chunks/BTUA7_xE.js";import{h as ne}from"../chunks/cDW0xQNP.js";import{R as le}from"../chunks/DCD6_LXk.js";import{e as $}from"../chunks/25_y8TFd.js";import{r as ie,a as oe,s as de,b as ce}from"../chunks/B0XoTt7U.js";import{g as B}from"../chunks/B8_P3YrA.js";import{b as ve,_ as pe}from"../chunks/CXQd8Y6F.js";import{P as fe}from"../chunks/D907np-5.js";function ue(e,s,r=s){var t=new WeakSet;U(e,"input",async a=>{var n=a?e.defaultValue:e.value;if(n=L(e)?C(n):n,r(n),S!==null&&t.add(S),await K(),n!==(n=s())){var u=e.selectionStart,l=e.selectionEnd,v=e.value.length;if(e.value=n??"",l!==null){var i=e.value.length;u===l&&l===v&&i>v?(e.selectionStart=i,e.selectionEnd=i):(e.selectionStart=u,e.selectionEnd=Math.min(l,i))}}}),(Q&&e.defaultValue!==e.value||R(s)==null&&e.value)&&(r(L(e)?C(e.value):e.value),S!==null&&t.add(S)),V(()=>{var a=s();if(e===document.activeElement){var n=S;if(t.has(n))return}L(e)&&a===C(e.value)||e.type==="date"&&!a&&!e.value||a!==e.value&&(e.value=a??"")})}function L(e){var s=e.type;return s==="number"||s==="range"}function C(e){return e===""?null:+e}function me(e=!1){const s=Z,r=s.l.u;if(!r)return;let t=()=>ee(s.s);if(e){let a=0,n={};const u=ae(()=>{let l=!1;const v=s.s;for(const i in v)v[i]!==n[i]&&(n[i]=v[i],l=!0);return l&&a++,a});t=()=>d(u)}r.b.length&&J(()=>{H(s,t),q(r.b)}),E(()=>{const a=R(()=>r.m.map(X));return()=>{for(const n of a)typeof n=="function"&&n()}}),r.a.length&&E(()=>{H(s,t),q(r.a)})}function H(e,s){if(e.l.s)for(const r of e.l.s)d(r);s()}var we=w('<header class="land-header svelte-1ct2rgk"><span class="riprap-wordmark"><!>riprap</span> <span class="land-header-sep svelte-1ct2rgk">/</span> <span class="land-header-context svelte-1ct2rgk">Flood Exposure Briefing · NYC</span> <nav class="land-header-nav svelte-1ct2rgk"><a href="#methodology" class="svelte-1ct2rgk">Methodology</a> <a href="#sources" class="svelte-1ct2rgk">Sources</a></nav></header>');function he(e){var s=we(),r=c(s),t=c(r);le(t,{size:22}),k(),o(r),k(6),o(s),m(e,s)}var ye=w("<span> </span>"),ge=w('<main class="land-hero svelte-drzq4r"><h1 class="land-hero-h1 svelte-drzq4r"><span class="land-hero-headline svelte-drzq4r">A flood exposure briefing<br/> for <em class="svelte-drzq4r">any place</em> in New York City.</span> <span class="land-hero-deck svelte-drzq4r">Type an address. Get a written briefing where every numeric claim links to its primary public-record source.</span></h1> <form class="land-query svelte-drzq4r" role="search"><span class="land-query-prompt svelte-drzq4r" aria-hidden="true">›</span> <input type="text" placeholder="Address, neighborhood, or BBL. e.g. 80 Pioneer Street, Red Hook" class="land-query-input svelte-drzq4r" aria-label="Query an address, neighborhood, or BBL"/> <button type="submit" class="land-query-submit svelte-drzq4r">Brief this place →</button></form> <div class="land-cycling svelte-drzq4r" aria-live="polite"><span class="land-cycling-label svelte-drzq4r">Try:</span> <button type="button" class="land-cycling-rail svelte-drzq4r" title="Run this example"></button></div></main>');function je(e,s){P(s,!0);const r=["80 Pioneer Street, Red Hook","Coney Island Hospital","PS 188, Lower East Side","Hammels Houses, Rockaway","Bowling Green station","555 W 57th Street"];let t=A(""),a=A(0);E(()=>{if(typeof window>"u")return;const p=setInterval(()=>{N(a,(d(a)+1)%r.length)},2200);return()=>clearInterval(p)});function n(){const p=d(t).trim();p&&B(`/q/${encodeURIComponent(p)}`)}function u(){const p=r[d(a)];B(`/q/${encodeURIComponent(p)}`)}var l=ge(),v=f(c(l),2),i=f(c(v),2);ie(i),k(2),o(v);var j=f(v,2),y=f(c(j),2);$(y,22,()=>r,p=>p,(p,b,F)=>{var h=ye();let x;var _=c(h,!0);o(h),T(()=>{x=oe(h,1,"land-cycling-item svelte-drzq4r",null,x,{"is-active":d(F)===d(a)}),de(h,"aria-hidden",d(F)!==d(a)),g(_,b)}),m(p,h)}),o(y),o(j),o(l),I("submit",v,p=>{p.preventDefault(),n()}),ue(i,()=>d(t),p=>N(t,p)),G("click",y,u),m(e,l),M()}D(["click"]);var be=w('<div class="land-mapmini svelte-1g1r73s" role="img" aria-label="Live mini-map preview of Red Hook flood exposure layers"><div class="land-mapmini-canvas svelte-1g1r73s"></div> <div class="land-mapmini-legend svelte-1g1r73s"><span class="svelte-1g1r73s"><span class="lm-sw lm-sw-emp svelte-1g1r73s"></span>empirical</span> <span class="svelte-1g1r73s"><span class="lm-sw lm-sw-mod svelte-1g1r73s"></span>modeled</span> <span class="svelte-1g1r73s"><span class="lm-sw lm-sw-prx svelte-1g1r73s"></span>proxy</span></div></div>');function _e(e,s){P(s,!0);const r=[-74.0096,40.6776];let t=A(null),a=null;se(()=>{let l=!1;return(async()=>{if(!d(t)||l)return;const v=await pe(()=>import("../chunks/D4L2lGt1.js").then(i=>i.m),[],import.meta.url);l||!d(t)||(a=new v.Map({container:d(t),style:fe,center:r,zoom:14.5,interactive:!1,attributionControl:!1}),a.on("load",()=>{a&&(a.addSource("fema-ae",{type:"geojson",data:{type:"FeatureCollection",features:[{type:"Feature",properties:{},geometry:{type:"Polygon",coordinates:[[[-74.014,40.679],[-74.007,40.68],[-74.005,40.677],[-74.009,40.6755],[-74.014,40.679]]]}}]}}),a.addLayer({id:"fema-ae-fill",type:"fill",source:"fema-ae",paint:{"fill-color":"#2A6FA8","fill-opacity":.22}}),a.addLayer({id:"fema-ae-line",type:"line",source:"fema-ae",paint:{"line-color":"#2A6FA8","line-width":1,"line-dasharray":[3,2]}}),a.addSource("hwm-contour",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"LineString",coordinates:[[-74.0125,40.679],[-74.0105,40.6792],[-74.008,40.679],[-74.006,40.6786]]}}}),a.addLayer({id:"hwm-contour-line",type:"line",source:"hwm-contour",paint:{"line-color":"#0B5394","line-width":1.4}}),a.addSource("proxy-311",{type:"geojson",data:{type:"FeatureCollection",features:[[-74.0118,40.677],[-74.0114,40.6767],[-74.0121,40.6772]].map(i=>({type:"Feature",properties:{},geometry:{type:"Point",coordinates:i}}))}}),a.addLayer({id:"proxy-311-circle",type:"circle",source:"proxy-311",paint:{"circle-radius":3,"circle-color":"transparent","circle-stroke-color":"#6B6B6B","circle-stroke-width":1}}),a.addSource("floodnet",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"Point",coordinates:[-74.0103,40.6788]}}}),a.addLayer({id:"floodnet-pin",type:"circle",source:"floodnet",paint:{"circle-radius":4,"circle-color":"#0B5394","circle-stroke-color":"#FFFFFF","circle-stroke-width":1}}),a.addSource("addr",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"Point",coordinates:r}}}),a.addLayer({id:"addr-ring",type:"circle",source:"addr",paint:{"circle-radius":9,"circle-color":"transparent","circle-stroke-color":"#0F172A","circle-stroke-width":1.4}}),a.addLayer({id:"addr-dot",type:"circle",source:"addr",paint:{"circle-radius":3,"circle-color":"#0F172A"}}))}))})(),()=>{l=!0,a&&(a.remove(),a=null)}});var n=be(),u=c(n);ve(u,l=>N(t,l),()=>d(t)),k(2),o(n),m(e,n),M()}var Se=w(`<section class="land-section svelte-1anw2jf"><div class="land-section-head svelte-1anw2jf"><span class="section-label">What you'll get back</span> <span class="land-section-meta svelte-1anw2jf">A grounded paragraph with citations, not a chatbot answer.</span></div> <div class="land-preview-grid svelte-1anw2jf"><div class="land-preview-pane land-preview-pane-excerpt svelte-1anw2jf"><div class="land-preview-eyebrow svelte-1anw2jf">Briefing excerpt</div> <p class="land-preview-body svelte-1anw2jf">The lot sits inside the FEMA <span class="land-preview-cite svelte-1anw2jf">1% AE flood zone <sup class="svelte-1anw2jf">[c3]</sup></span>,
2
  with Sandy high-water marks recorded <span class="land-preview-cite svelte-1anw2jf">4.7 ft above grade <sup class="svelte-1anw2jf">[c1]</sup></span>.
3
  FloodNet FN-BK-018 has logged <span class="land-preview-cite svelte-1anw2jf">14 nuisance floods since 2023 <sup class="svelte-1anw2jf">[c2]</sup></span>.</p> <div class="land-preview-cites svelte-1anw2jf"><div class="land-preview-cite-row svelte-1anw2jf"><span class="land-preview-cite-pin svelte-1anw2jf">[c1]</span> <span class="land-preview-cite-src svelte-1anw2jf">USGS HWM · Sandy 2012</span> <span class="land-preview-cite-tier svelte-1anw2jf">empirical</span></div> <div class="land-preview-cite-row svelte-1anw2jf"><span class="land-preview-cite-pin svelte-1anw2jf">[c2]</span> <span class="land-preview-cite-src svelte-1anw2jf">FloodNet FN-BK-018</span> <span class="land-preview-cite-tier svelte-1anw2jf">empirical</span></div> <div class="land-preview-cite-row svelte-1anw2jf"><span class="land-preview-cite-pin svelte-1anw2jf">[c3]</span> <span class="land-preview-cite-src svelte-1anw2jf">FEMA NFHL · 36047C0207</span> <span class="land-preview-cite-tier svelte-1anw2jf">modeled</span></div></div></div> <div class="land-preview-pane land-preview-pane-cards svelte-1anw2jf"><div class="land-preview-eyebrow svelte-1anw2jf">Evidence cards</div> <div class="land-evcard-grid svelte-1anw2jf"><article class="land-evcard land-evcard-empirical svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">empirical</span> <span class="land-evcard-id svelte-1anw2jf">e1</span></header> <div class="land-evcard-claim svelte-1anw2jf">4.7 ft Sandy storm-surge HWM at address</div> <div class="land-evcard-source svelte-1anw2jf">USGS High-Water Mark database · 2012</div></article> <article class="land-evcard land-evcard-empirical svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">empirical</span> <span class="land-evcard-id svelte-1anw2jf">e2</span></header> <div class="land-evcard-claim svelte-1anw2jf">14 nuisance-flood events, 2023–2026</div> <div class="land-evcard-source svelte-1anw2jf">FloodNet FN-BK-018 · 2 blocks north</div></article> <article class="land-evcard land-evcard-modeled svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">modeled</span> <span class="land-evcard-id svelte-1anw2jf">e3</span></header> <div class="land-evcard-claim svelte-1anw2jf">FEMA 1% annual-chance (AE) flood zone</div> <div class="land-evcard-source svelte-1anw2jf">FEMA NFHL · panel 36047C0207</div></article> <article class="land-evcard land-evcard-modeled svelte-1anw2jf"><header class="land-evcard-head svelte-1anw2jf"><span class="land-evcard-tier svelte-1anw2jf">modeled</span> <span class="land-evcard-id svelte-1anw2jf">e5</span></header> <div class="land-evcard-claim svelte-1anw2jf">+30 in MSL by 2070 (NPCC4 high)</div> <div class="land-evcard-source svelte-1anw2jf">NPCC4 SLR projection · 2024</div></article></div></div> <div class="land-preview-pane land-preview-pane-map svelte-1anw2jf"><div class="land-preview-eyebrow svelte-1anw2jf">Map</div> <!> <div class="land-preview-mapmeta svelte-1anw2jf">80 Pioneer St, Red Hook · z14.5 · Carto Positron</div></div></div></section>`);function ke(e){var s=Se(),r=f(c(s),2),t=f(c(r),4),a=f(c(t),2);_e(a,{}),k(2),o(t),o(r),o(s),m(e,s)}var Fe=w('<article class="land-stones-detail-cell svelte-1v6nt1t"><div class="land-stones-detail-num svelte-1v6nt1t"> </div> <h3 class="land-stones-detail-name svelte-1v6nt1t"> </h3> <div class="land-stones-detail-role svelte-1v6nt1t"> </div> <p class="land-stones-detail-tag svelte-1v6nt1t"> </p> <div class="land-stones-detail-sources svelte-1v6nt1t"> </div></article>'),xe=w(`<section class="land-section-stones-detail svelte-1v6nt1t" id="methodology"><div class="land-page svelte-1v6nt1t"><div class="land-section-head svelte-1v6nt1t"><span class="section-label">How Riprap reads a place</span> <span class="land-section-meta svelte-1v6nt1t">Five Stones · one taxonomy · every briefing</span></div> <p class="land-stones-deck svelte-1v6nt1t">Each briefing routes through a fixed taxonomy of public-record specialists. Each Stone is a class of evidence.
4
  Together they form the briefing, and every claim in the output traces back to the Stone that produced it.</p> <div class="land-stones-detail svelte-1v6nt1t"></div></div></section>`);function Le(e,s){P(s,!1);const r=[{name:"Cornerstone",role:"the hazard reader",tag:"what NYC's ground remembers",sources:"USGS HWMs · FEMA NFHL · DEP stormwater · Prithvi historical",tint:"var(--stone-cornerstone)"},{name:"Keystone",role:"the asset register",tag:"what's exposed",sources:"MTA · NYCHA · DOE · DOH · PLUTO",tint:"var(--stone-keystone)"},{name:"Touchstone",role:"the live observer",tag:"what's happening now",sources:"FloodNet sensors · 311 complaints · NWS · NOAA tide gauges",tint:"var(--stone-touchstone)"},{name:"Lodestone",role:"the projector",tag:"what's coming",sources:"NPCC4 · Granite TTM (zero-shot + NYC fine-tune) · NWS alerts",tint:"var(--stone-lodestone)"},{name:"Capstone",role:"the synthesizer",tag:"writes it all down",sources:"Granite 4.1 composer · Mellea grounding-check · WeasyPrint",tint:"var(--stone-capstone)"}];me();var t=xe(),a=c(t),n=f(c(a),4);$(n,7,()=>r,u=>u.name,(u,l,v)=>{var i=Fe();let j;var y=c(i),p=c(y,!0);o(y);var b=f(y,2),F=c(b,!0);o(b);var h=f(b,2),x=c(h,!0);o(h);var _=f(h,2),O=c(_,!0);o(_);var z=f(_,2),W=c(z,!0);o(z),o(i),T(Y=>{j=ce(i,"",j,{"--stone-tint":d(l).tint}),g(p,Y),g(F,d(l).name),g(x,d(l).role),g(O,d(l).tag),g(W,d(l).sources)},[()=>String(d(v)+1).padStart(2,"0")]),m(u,i)}),o(n),o(a),o(t),m(e,t),M()}var Ce=w('<footer class="land-footer svelte-1dcj612"><span class="land-footer-tiers svelte-1dcj612"><span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-emp svelte-1dcj612"></span>empirical</span> <span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-mod svelte-1dcj612"></span>modeled</span> <span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-prx svelte-1dcj612"></span>proxy</span> <span class="land-footer-tier svelte-1dcj612"><span class="lm-sw lm-sw-syn svelte-1dcj612"></span>synthetic</span></span> <span class="land-footer-build">Riprap v0.4.6 · NYC OpenData · FEMA NFHL · USGS · NPCC4 · Dam mark by Chintuza, Noun Project (CC-BY)</span></footer>');function Ee(e){var s=Ce();m(e,s)}var Ne=w('<meta name="description" content="A citation-grounded flood-exposure briefing tool for any address, neighborhood, or BBL in New York City."/>'),Ae=w('<div class="land svelte-1uha8ag"><!> <div class="land-page svelte-1uha8ag"><!> <!></div> <!> <!></div>');function We(e){var s=Ae();ne("1uha8ag",v=>{var i=Ne();te(()=>{re.title="Riprap — Flood Exposure Briefing for NYC"}),m(v,i)});var r=c(s);he(r);var t=f(r,2),a=c(t);je(a,{});var n=f(a,2);ke(n),o(t);var u=f(t,2);Le(u,{});var l=f(u,2);Ee(l),o(s),m(e,s)}export{We as component};
web/sveltekit/build/_app/immutable/nodes/{3.CU36QLul.js → 3.Cw8Vd7-r.js} RENAMED
@@ -1,4 +1,4 @@
1
- import{d as ge,c as he,a as v,s as l,e as xe,f as p}from"../chunks/CWw6qgC_.js";import{p as ye,ai as we,f as $e,a as ke,aj as qe,o as e,a5 as F,ak as je,al as d,a4 as I,c as a,s,r as t,t as M}from"../chunks/BTUA7_xE.js";import{i as O}from"../chunks/Bd-v_9Ud.js";import{e as Se}from"../chunks/25_y8TFd.js";import{h as Fe}from"../chunks/cDW0xQNP.js";import{p as Ie}from"../chunks/D8NyAcAP.js";import{B as Me,T as Oe}from"../chunks/BatqQaKj.js";import{l as Te}from"../chunks/DxQlA7U2.js";const Pe=!1,Re=!1,Ue=Object.freeze(Object.defineProperty({__proto__:null,prerender:Pe,ssr:Re},Symbol.toStringTag,{value:"Module"}));var Ae=p(`<div class="empty svelte-uialbm"><h1 class="svelte-uialbm">No briefing snapshot found</h1> <p>Run a briefing first at <a href="/" class="svelte-uialbm">riprap home</a>; once it finishes,
2
  use <strong>export PDF</strong> from the header to open this view.
3
  Snapshots are stored per-browser and persist between runs of the same query.</p></div>`),Be=p('<div class="curl svelte-uialbm"> </div>'),De=p('<li class="svelte-uialbm"><span class="cn svelte-uialbm"> </span> <span class="cglyph svelte-uialbm"><!></span> <span class="csrc svelte-uialbm"> </span> <span class="cvint svelte-uialbm"> </span> <div class="ctitle svelte-uialbm"> </div> <!> <div class="cdocid svelte-uialbm">doc_id <code> </code></div></li>'),Ge=p('<section class="print-citations svelte-uialbm"><h2 class="svelte-uialbm">Citations</h2> <ol class="svelte-uialbm"></ol></section>'),ze=p('<article class="print-doc svelte-uialbm"><header class="print-head svelte-uialbm"><div class="print-head-top svelte-uialbm"><span class="wordmark svelte-uialbm">riprap</span> <span class="meta"> </span></div> <h1 class="print-title svelte-uialbm"> </h1> <div class="print-sub svelte-uialbm">intent <strong> </strong> </div></header> <div class="print-controls no-print svelte-uialbm"><button type="button" class="svelte-uialbm">print / save as PDF</button> <span class="hint svelte-uialbm"> </span></div> <!> <!> <footer class="print-foot svelte-uialbm"> </footer></article>'),Le=p('<div class="empty svelte-uialbm"><p>Loading…</p></div>');function Ve(Q,U){ye(U,!0);let V=d(()=>Ie.params.queryId??""),i=I(null),T=I(!1),P=I(!1);we(()=>{const r=Te(e(V));if(!r){F(T,!0);return}F(i,r,!0),requestAnimationFrame(()=>{requestAnimationFrame(()=>{typeof window<"u"&&(window.print(),F(P,!0))})})});function X(){typeof window<"u"&&window.print()}let R=d(()=>e(i)?Object.values(e(i).citations).sort((r,n)=>r.n-n.n):[]),A=d(()=>e(i)?new Date(e(i).generatedAt).toISOString().slice(0,10):"");var B=he();Fe("uialbm",r=>{qe(()=>{var n;je.title=`Riprap briefing — ${((n=e(i))==null?void 0:n.queryText)??"export"??""}`})});var Y=$e(B);{var Z=r=>{var n=Ae();v(r,n)},ee=r=>{var n=ze(),c=a(n),u=a(c),D=s(a(u),2),ae=a(D);t(D),t(u);var m=s(u,2),se=a(m,!0);t(m);var G=s(m,2),f=s(a(G)),re=a(f,!0);t(f);var ie=s(f);t(G),t(c);var b=s(c,2),z=a(b),L=s(z,2),ne=a(L,!0);t(L),t(b);var N=s(b,2);Me(N,{get blocks(){return e(i).blocks},get citations(){return e(i).citations},streaming:!1});var C=s(N,2);{var le=_=>{var g=Ge(),W=s(a(g),2);Se(W,21,()=>e(R),h=>h.id,(h,o)=>{var x=De(),y=a(x),ve=a(y);t(y);var w=s(y,2),pe=a(w);Oe(pe,{get tier(){return e(o).tier},size:9,get color(){return`var(--tier-${e(o).tier??""})`}}),t(w);var $=s(w,2),de=a($,!0);t($);var k=s($,2),ce=a(k);t(k);var q=s(k,2),ue=a(q,!0);t(q);var H=s(q,2);{var me=j=>{var S=Be(),_e=a(S,!0);t(S),M(()=>l(_e,e(o).url)),v(j,S)},fe=d(()=>e(o).url&&e(o).url.startsWith("http"));O(H,j=>{e(fe)&&j(me)})}var J=s(H,2),K=s(a(J)),be=a(K,!0);t(K),t(J),t(x),M(()=>{l(ve,`[${e(o).n??""}]`),l(de,e(o).source),l(ce,`v. ${e(o).vintage??""}`),l(ue,e(o).title),l(be,e(o).docId)}),v(h,x)}),t(W),t(g),v(_,g)};O(C,_=>{e(R).length&&_(le)})}var E=s(C,2),oe=a(E);t(E),t(n),M(()=>{l(ae,`flood-exposure briefing · v0.4.2 · ${e(A)??""}`),l(se,e(i).queryText),l(re,e(i).intent??"briefing"),l(ie,` · ${e(i).specialists??""} specialists
4
  · ${e(i).attempts??1??""} reconcile${(e(i).attempts??1)===1?"":"s"}
 
1
+ import{d as ge,c as he,a as v,s as l,e as xe,f as p}from"../chunks/CWw6qgC_.js";import{p as ye,ai as we,f as $e,a as ke,aj as qe,o as e,a5 as F,ak as je,al as d,a4 as I,c as a,s,r as t,t as M}from"../chunks/BTUA7_xE.js";import{i as O}from"../chunks/Bd-v_9Ud.js";import{e as Se}from"../chunks/25_y8TFd.js";import{h as Fe}from"../chunks/cDW0xQNP.js";import{p as Ie}from"../chunks/Bs7n3R20.js";import{B as Me,T as Oe}from"../chunks/BatqQaKj.js";import{l as Te}from"../chunks/DxQlA7U2.js";const Pe=!1,Re=!1,Ue=Object.freeze(Object.defineProperty({__proto__:null,prerender:Pe,ssr:Re},Symbol.toStringTag,{value:"Module"}));var Ae=p(`<div class="empty svelte-uialbm"><h1 class="svelte-uialbm">No briefing snapshot found</h1> <p>Run a briefing first at <a href="/" class="svelte-uialbm">riprap home</a>; once it finishes,
2
  use <strong>export PDF</strong> from the header to open this view.
3
  Snapshots are stored per-browser and persist between runs of the same query.</p></div>`),Be=p('<div class="curl svelte-uialbm"> </div>'),De=p('<li class="svelte-uialbm"><span class="cn svelte-uialbm"> </span> <span class="cglyph svelte-uialbm"><!></span> <span class="csrc svelte-uialbm"> </span> <span class="cvint svelte-uialbm"> </span> <div class="ctitle svelte-uialbm"> </div> <!> <div class="cdocid svelte-uialbm">doc_id <code> </code></div></li>'),Ge=p('<section class="print-citations svelte-uialbm"><h2 class="svelte-uialbm">Citations</h2> <ol class="svelte-uialbm"></ol></section>'),ze=p('<article class="print-doc svelte-uialbm"><header class="print-head svelte-uialbm"><div class="print-head-top svelte-uialbm"><span class="wordmark svelte-uialbm">riprap</span> <span class="meta"> </span></div> <h1 class="print-title svelte-uialbm"> </h1> <div class="print-sub svelte-uialbm">intent <strong> </strong> </div></header> <div class="print-controls no-print svelte-uialbm"><button type="button" class="svelte-uialbm">print / save as PDF</button> <span class="hint svelte-uialbm"> </span></div> <!> <!> <footer class="print-foot svelte-uialbm"> </footer></article>'),Le=p('<div class="empty svelte-uialbm"><p>Loading…</p></div>');function Ve(Q,U){ye(U,!0);let V=d(()=>Ie.params.queryId??""),i=I(null),T=I(!1),P=I(!1);we(()=>{const r=Te(e(V));if(!r){F(T,!0);return}F(i,r,!0),requestAnimationFrame(()=>{requestAnimationFrame(()=>{typeof window<"u"&&(window.print(),F(P,!0))})})});function X(){typeof window<"u"&&window.print()}let R=d(()=>e(i)?Object.values(e(i).citations).sort((r,n)=>r.n-n.n):[]),A=d(()=>e(i)?new Date(e(i).generatedAt).toISOString().slice(0,10):"");var B=he();Fe("uialbm",r=>{qe(()=>{var n;je.title=`Riprap briefing — ${((n=e(i))==null?void 0:n.queryText)??"export"??""}`})});var Y=$e(B);{var Z=r=>{var n=Ae();v(r,n)},ee=r=>{var n=ze(),c=a(n),u=a(c),D=s(a(u),2),ae=a(D);t(D),t(u);var m=s(u,2),se=a(m,!0);t(m);var G=s(m,2),f=s(a(G)),re=a(f,!0);t(f);var ie=s(f);t(G),t(c);var b=s(c,2),z=a(b),L=s(z,2),ne=a(L,!0);t(L),t(b);var N=s(b,2);Me(N,{get blocks(){return e(i).blocks},get citations(){return e(i).citations},streaming:!1});var C=s(N,2);{var le=_=>{var g=Ge(),W=s(a(g),2);Se(W,21,()=>e(R),h=>h.id,(h,o)=>{var x=De(),y=a(x),ve=a(y);t(y);var w=s(y,2),pe=a(w);Oe(pe,{get tier(){return e(o).tier},size:9,get color(){return`var(--tier-${e(o).tier??""})`}}),t(w);var $=s(w,2),de=a($,!0);t($);var k=s($,2),ce=a(k);t(k);var q=s(k,2),ue=a(q,!0);t(q);var H=s(q,2);{var me=j=>{var S=Be(),_e=a(S,!0);t(S),M(()=>l(_e,e(o).url)),v(j,S)},fe=d(()=>e(o).url&&e(o).url.startsWith("http"));O(H,j=>{e(fe)&&j(me)})}var J=s(H,2),K=s(a(J)),be=a(K,!0);t(K),t(J),t(x),M(()=>{l(ve,`[${e(o).n??""}]`),l(de,e(o).source),l(ce,`v. ${e(o).vintage??""}`),l(ue,e(o).title),l(be,e(o).docId)}),v(h,x)}),t(W),t(g),v(_,g)};O(C,_=>{e(R).length&&_(le)})}var E=s(C,2),oe=a(E);t(E),t(n),M(()=>{l(ae,`flood-exposure briefing · v0.4.2 · ${e(A)??""}`),l(se,e(i).queryText),l(re,e(i).intent??"briefing"),l(ie,` · ${e(i).specialists??""} specialists
4
  · ${e(i).attempts??1??""} reconcile${(e(i).attempts??1)===1?"":"s"}
web/sveltekit/build/_app/immutable/nodes/{4.JuDtCP-e.js → 4.Ck4WhzVi.js} RENAMED
The diff for this file is too large to render. See raw diff
 
web/sveltekit/build/_app/version.json CHANGED
@@ -1 +1 @@
1
- {"version":"1778353518826"}
 
1
+ {"version":"1778356341060"}
web/sveltekit/build/index.html CHANGED
@@ -6,21 +6,21 @@
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.C_DzDADc.js" rel="modulepreload">
10
- <link href="./_app/immutable/chunks/DJJH9JR_.js" rel="modulepreload">
11
  <link href="./_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
12
- <link href="./_app/immutable/entry/app.DmxSSduu.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.DInKAumT.js" rel="modulepreload">
18
  <link href="./_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
19
- <link href="./_app/immutable/chunks/D8NyAcAP.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">
23
- <link href="./_app/immutable/nodes/2.B2rqoVXS.js" rel="modulepreload">
24
  <link href="./_app/immutable/chunks/cDW0xQNP.js" rel="modulepreload">
25
  <link href="./_app/immutable/chunks/25_y8TFd.js" rel="modulepreload">
26
  <link href="./_app/immutable/chunks/D907np-5.js" rel="modulepreload">
@@ -37,15 +37,15 @@
37
 
38
  <script>
39
  {
40
- __sveltekit_a2xq49 = {
41
  base: new URL(".", location).pathname.slice(0, -1)
42
  };
43
 
44
  const element = document.currentScript.parentElement;
45
 
46
  Promise.all([
47
- import("./_app/immutable/entry/start.C_DzDADc.js"),
48
- import("./_app/immutable/entry/app.DmxSSduu.js")
49
  ]).then(([kit, app]) => {
50
  kit.start(app, element, {
51
  node_ids: [0, 2],
 
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.C7t2uk4E.js" rel="modulepreload">
10
+ <link href="./_app/immutable/chunks/B8_P3YrA.js" rel="modulepreload">
11
  <link href="./_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
12
+ <link href="./_app/immutable/entry/app.DaTkeYDu.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.Bxzl5Ruo.js" rel="modulepreload">
18
  <link href="./_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
19
+ <link href="./_app/immutable/chunks/Bs7n3R20.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">
23
+ <link href="./_app/immutable/nodes/2.6wNqJ7i-.js" rel="modulepreload">
24
  <link href="./_app/immutable/chunks/cDW0xQNP.js" rel="modulepreload">
25
  <link href="./_app/immutable/chunks/25_y8TFd.js" rel="modulepreload">
26
  <link href="./_app/immutable/chunks/D907np-5.js" rel="modulepreload">
 
37
 
38
  <script>
39
  {
40
+ __sveltekit_ual5r0 = {
41
  base: new URL(".", location).pathname.slice(0, -1)
42
  };
43
 
44
  const element = document.currentScript.parentElement;
45
 
46
  Promise.all([
47
+ import("./_app/immutable/entry/start.C7t2uk4E.js"),
48
+ import("./_app/immutable/entry/app.DaTkeYDu.js")
49
  ]).then(([kit, app]) => {
50
  kit.start(app, element, {
51
  node_ids: [0, 2],
web/sveltekit/build/q/sample.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.C_DzDADc.js" rel="modulepreload">
10
- <link href="../_app/immutable/chunks/DJJH9JR_.js" rel="modulepreload">
11
  <link href="../_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
12
- <link href="../_app/immutable/entry/app.DmxSSduu.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.DInKAumT.js" rel="modulepreload">
18
  <link href="../_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
19
- <link href="../_app/immutable/chunks/D8NyAcAP.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">
@@ -38,15 +38,15 @@
38
 
39
  <script>
40
  {
41
- __sveltekit_a2xq49 = {
42
  base: new URL("..", location).pathname.slice(0, -1)
43
  };
44
 
45
  const element = document.currentScript.parentElement;
46
 
47
  Promise.all([
48
- import("../_app/immutable/entry/start.C_DzDADc.js"),
49
- import("../_app/immutable/entry/app.DmxSSduu.js")
50
  ]).then(([kit, app]) => {
51
  kit.start(app, element, {
52
  node_ids: [0, 5],
 
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.C7t2uk4E.js" rel="modulepreload">
10
+ <link href="../_app/immutable/chunks/B8_P3YrA.js" rel="modulepreload">
11
  <link href="../_app/immutable/chunks/BTUA7_xE.js" rel="modulepreload">
12
+ <link href="../_app/immutable/entry/app.DaTkeYDu.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.Bxzl5Ruo.js" rel="modulepreload">
18
  <link href="../_app/immutable/chunks/DxQlA7U2.js" rel="modulepreload">
19
+ <link href="../_app/immutable/chunks/Bs7n3R20.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">
 
38
 
39
  <script>
40
  {
41
+ __sveltekit_ual5r0 = {
42
  base: new URL("..", location).pathname.slice(0, -1)
43
  };
44
 
45
  const element = document.currentScript.parentElement;
46
 
47
  Promise.all([
48
+ import("../_app/immutable/entry/start.C7t2uk4E.js"),
49
+ import("../_app/immutable/entry/app.DaTkeYDu.js")
50
  ]).then(([kit, app]) => {
51
  kit.start(app, element, {
52
  node_ids: [0, 5],