diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..d079320fc0089792fda7151a5caa51a08cb62721 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +trackio/assets/badge.png filter=lfs diff=lfs merge=lfs -text +trackio/assets/trackio_logo_old.png filter=lfs diff=lfs merge=lfs -text diff --git a/trackio/CHANGELOG.md b/trackio/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..d5b8617a2f3f59cd1bd37dc711805e306ebc13dc --- /dev/null +++ b/trackio/CHANGELOG.md @@ -0,0 +1,400 @@ +# trackio + +## 0.31.4 + +### Features + +- [#628](https://github.com/gradio-app/trackio/pull/628) [`3eeaa99`](https://github.com/gradio-app/trackio/commit/3eeaa99bd05bef69053b9a1b5c7af3abf56c360c) - let `logbook cell figure` embed image files directly. Thanks @abidlabs!/n `trackio logbook cell figure` now accepts an image path via a new `--image`/n flag, and `--html ` transparently embeds the file when it points at an/n image. Previously the only way to add a PNG/JPG figure was to hand-encode it/n into an `` data-URI, and passing an image path to `--html` crashed with a/n `UnicodeDecodeError` (the binary file was read as UTF-8 text). Images are/n embedded as responsive base64 data URIs. The Python API `add_figure_cell` gains/n a matching `image=` parameter. + +## 0.31.3 + +### Features + +- [#626](https://github.com/gradio-app/trackio/pull/626) [`174aecf`](https://github.com/gradio-app/trackio/commit/174aecff33e6d1cc8d71965a73538c0510abed46) - Fix logbook Markdown escaping and figure hotspot navigation. Thanks @abidlabs! + +## 0.31.2 + +### Features + +- [#624](https://github.com/gradio-app/trackio/pull/624) [`a0918ed`](https://github.com/gradio-app/trackio/commit/a0918edc7594bb211f9e6871546b9d36939f0658) - Fix poster hotspot navigation after iframe load. Thanks @abidlabs! + +## 0.31.1 + +### Features + +- [#621](https://github.com/gradio-app/trackio/pull/621) [`a40f1a4`](https://github.com/gradio-app/trackio/commit/a40f1a464c51652ecdeab04d999659d71b76047e) - add native fullscreen mode for logbook figures. Thanks @abidlabs! +- [#623](https://github.com/gradio-app/trackio/pull/623) [`31fd4d7`](https://github.com/gradio-app/trackio/commit/31fd4d7b4004f0c511484f089e6a550da1b4d71e) - let interactive logbook figures navigate to logbook pages. Thanks @abidlabs! + +## 0.31.0 + +### Features + +- [#601](https://github.com/gradio-app/trackio/pull/601) [`8c49140`](https://github.com/gradio-app/trackio/commit/8c491406c54685369d43f3a9c4d4a0e99108bc49) - browse artifacts from the UI. Thanks @Saba9! +- [#602](https://github.com/gradio-app/trackio/pull/602) [`1ae1558`](https://github.com/gradio-app/trackio/commit/1ae155803b5450b181a47767255421499074c70b) - feat: add Artifact.add_reference to reference external objects without copy. Thanks @adrien-grl! + +## 0.30.4 + +### Features + +- [#618](https://github.com/gradio-app/trackio/pull/618) [`64c18f6`](https://github.com/gradio-app/trackio/commit/64c18f65bf98d6f54040395a1ca0473347ba6a2b) - Logbook: share button on figures + `logbook pin` CLI. Thanks @abidlabs! + +## 0.30.3 + +### Features + +- [#616](https://github.com/gradio-app/trackio/pull/616) [`645498b`](https://github.com/gradio-app/trackio/commit/645498be37bafab28f884a36e80c5bc0eab06cd9) - Logbook single page. Thanks @abidlabs! + +## 0.30.2 + +### Features + +- [#614](https://github.com/gradio-app/trackio/pull/614) [`eba80c7`](https://github.com/gradio-app/trackio/commit/eba80c7464af250519a90b8ac3179ff6652b651a) - Render logbooks as single-page documents with section navigation and contextual resources. Thanks @abidlabs! +- [#612](https://github.com/gradio-app/trackio/pull/612) [`2c1b943`](https://github.com/gradio-app/trackio/commit/2c1b9436b093e9f9335c99c10fe4b6afa622e314) - Warn that logbook open is experimental. Thanks @abidlabs! +- [#611](https://github.com/gradio-app/trackio/pull/611) [`96b1d94`](https://github.com/gradio-app/trackio/commit/96b1d94def7596aa1302864cbfc57942dd63822b) - Logbook: auto-capture output artifacts and live-embedded dashboard cells. Thanks @abidlabs! + +## 0.30.1 + +### Features + +- [#609](https://github.com/gradio-app/trackio/pull/609) [`2ed1295`](https://github.com/gradio-app/trackio/commit/2ed12959c73aa9c04ca1096cf7a8315ce2886ed1) - Serve live logbook preview from open. Thanks @abidlabs! + +## 0.30.0 + +### Features + +- [#603](https://github.com/gradio-app/trackio/pull/603) [`a793fd8`](https://github.com/gradio-app/trackio/commit/a793fd88827482134bce295c6228e117de64566a) - Move default artifact downloads under `./.trackio/artifact-downloads/` so materialized files stay out of the project root. Thanks @abidlabs! +- [#604](https://github.com/gradio-app/trackio/pull/604) [`dd3b8ee`](https://github.com/gradio-app/trackio/commit/dd3b8eeef4e0da8bf0df6238617e20ae81f3e564) - docs: clarify artifact types. Thanks @abidlabs! +- [#586](https://github.com/gradio-app/trackio/pull/586) [`7db4c3b`](https://github.com/gradio-app/trackio/commit/7db4c3b6de6ff4903daf7dabed8842f212c8b7fd) - artifact tracking API — `log_artifact`, `use_artifact`, and an `Artifact` class for versioned, named file collections with aliases, content-addressed deduplication, and producer/consumer run lineage; works offline and syncs blobs to Hugging Face Spaces/Datasets. Thanks @Saba9! +- [#597](https://github.com/gradio-app/trackio/pull/597) [`5ba561e`](https://github.com/gradio-app/trackio/commit/5ba561e1b4023abdf63624f4fb396367ed6e9e76) - Add experiment logbooks: shareable static-Space lab notebooks. Thanks @abidlabs! + +## 0.29.0 + +### Features + +- [#593](https://github.com/gradio-app/trackio/pull/593) [`ca4722c`](https://github.com/gradio-app/trackio/commit/ca4722c19d2219a3a78b5977149873b9dff73f34) - Add CLI command to list Trackio Spaces. Thanks @abidlabs! + +## 0.28.1 + +### Features + +- [#589](https://github.com/gradio-app/trackio/pull/589) [`5e9905d`](https://github.com/gradio-app/trackio/commit/5e9905d7815bb063f2d9bb38aa76177405c5e2b4) - Reduce Metrics page log payloads by requesting scalar-only metrics and add URL x-axis initialization/fallback handling. Thanks @evalstate! +- [#590](https://github.com/gradio-app/trackio/pull/590) [`56493a6`](https://github.com/gradio-app/trackio/commit/56493a6e9a0114b8655ab44b8c3dec7bae2a5df5) - Use TRACKIO_WRITE_TOKEN for server write token. Thanks @abidlabs! + +## 0.28.0 + +### Features + +- [#582](https://github.com/gradio-app/trackio/pull/582) [`d9dabb5`](https://github.com/gradio-app/trackio/commit/d9dabb5bda8147ad7c9203646358bd0880fa6521) - Add JSONL inbox fragments: durable logging when the Space is unreachable and on network filesystems. Thanks @abidlabs! + +## 0.27.0 + +### Features + +- [#567](https://github.com/gradio-app/trackio/pull/567) [`8c0ce21`](https://github.com/gradio-app/trackio/commit/8c0ce21ff9746d7c6a250684b1b5f0f3f04e0520) - Add CPU, RAM, disk, network and sensor metrics monitoring for non-Apple devices. Thanks @yannsadowski! +- [#571](https://github.com/gradio-app/trackio/pull/571) [`57bc7df`](https://github.com/gradio-app/trackio/commit/57bc7df27ecd7b3ff543dbd2bff5c94182bfb69e) - Fix IndexError when importing CSV with no numeric metric columns. Thanks @Ckal! +- [#577](https://github.com/gradio-app/trackio/pull/577) [`db0e730`](https://github.com/gradio-app/trackio/commit/db0e730463103142688c1c0efef9ff68a52e281d) - Sort and paginate media items. Thanks @abidlabs! +- [#576](https://github.com/gradio-app/trackio/pull/576) [`6f635e2`](https://github.com/gradio-app/trackio/commit/6f635e22553ce2deaece6a0d6289475ab8683040) - Render plot/metric titles as searchable DOM text. Thanks @abidlabs! +- [#579](https://github.com/gradio-app/trackio/pull/579) [`cf7759e`](https://github.com/gradio-app/trackio/commit/cf7759efaab73ce1e98a8a2355dc1f65d54bc775) - Merge image viewer with current media page, credit to @catwell. Thanks @abidlabs! + +## 0.26.0 + +### Features + +- [#553](https://github.com/gradio-app/trackio/pull/553) [`06011ac`](https://github.com/gradio-app/trackio/commit/06011acc9c73341fd234f9cd8eaf96d5a34ad8ce) - fix: serve static-Space assets at /static/trackio. Thanks @abidlabs! +- [#563](https://github.com/gradio-app/trackio/pull/563) [`551569c`](https://github.com/gradio-app/trackio/commit/551569c16fb56ec63249ebdc28348d326ccf7126) - Fix Traces UI a bit. Thanks @abidlabs! +- [#550](https://github.com/gradio-app/trackio/pull/550) [`5690acd`](https://github.com/gradio-app/trackio/commit/5690acda5da303c63ad332451afeab3e9750fd1a) - fix: keep sparse metrics sparse through smoothing. Thanks @abidlabs! +- [#551](https://github.com/gradio-app/trackio/pull/551) [`0ef7266`](https://github.com/gradio-app/trackio/commit/0ef72660695cf932f3906ddbf33d41d087280a22) - add "group by" dropdown to sidebar. Thanks @Saba9! +- [#538](https://github.com/gradio-app/trackio/pull/538) [`a15c1a8`](https://github.com/gradio-app/trackio/commit/a15c1a8877c07514e0596630bb7c7299299994a9) - Subdue empty dashboard tabs. Thanks @abidlabs! +- [#559](https://github.com/gradio-app/trackio/pull/559) [`0b53a41`](https://github.com/gradio-app/trackio/commit/0b53a413909598f92138b6b6395a91c2d5034faf) - Store traces separately from metrics. Thanks @abidlabs! +- [#556](https://github.com/gradio-app/trackio/pull/556) [`d110001`](https://github.com/gradio-app/trackio/commit/d110001dbd9f6b262dfe41f2b702e3a71aa0cfc9) - fix: keep selected x-axis option in dropdown and dismiss dropdown on re-click. Thanks @Saba9! +- [#560](https://github.com/gradio-app/trackio/pull/560) [`aee2923`](https://github.com/gradio-app/trackio/commit/aee2923d3ada4f74d62d065c16f1f6a56a295e48) - Paginate Traces tab with step filter. Thanks @abidlabs! + +### Fixes + +- [#540](https://github.com/gradio-app/trackio/pull/540) [`0b674ac`](https://github.com/gradio-app/trackio/commit/0b674ac6438738de89bc5b3fb700ccfd8a39368c) - raise default metrics sampling cap from 1500 to 3000 so client-side smoothing on the Metrics tab runs over higher-resolution data. Thanks @edbeeching! + +## 0.25.1 + +### Features + +- [#535](https://github.com/gradio-app/trackio/pull/535) [`d7f1b27`](https://github.com/gradio-app/trackio/commit/d7f1b27a98f185d2d97ef54975d5865e0b5243c9) - Avoid HF token leaks in static snapshots. Thanks @abidlabs! + +## 0.25.0 + +### Features + +- [#533](https://github.com/gradio-app/trackio/pull/533) [`08bc5eb`](https://github.com/gradio-app/trackio/commit/08bc5eb090525d3ff5f7fa4233c30c42162aa74c) - Fix Windows-only emoji mojibake when uploading Space README. Thanks @tomaarsen! +- [#518](https://github.com/gradio-app/trackio/pull/518) [`e7ed176`](https://github.com/gradio-app/trackio/commit/e7ed176da53d8b49290fddd890b3d18c0b9b958f) - Traces in Trackio. Thanks @abidlabs! +- [#531](https://github.com/gradio-app/trackio/pull/531) [`27a50a3`](https://github.com/gradio-app/trackio/commit/27a50a37362020304b774344b4c774ff548985b6) - Add configurable custom frontends for Trackio. Thanks @abidlabs! + +## 0.24.2 + +### Features + +- [#527](https://github.com/gradio-app/trackio/pull/527) [`7d1c0b9`](https://github.com/gradio-app/trackio/commit/7d1c0b9c37ce9a9845e6bbe6c083da9d36084caf) - Fix dashboard UX issues: smoothing in share URL, run selection, and run filtering. Thanks @abidlabs! +- [#526](https://github.com/gradio-app/trackio/pull/526) [`643878a`](https://github.com/gradio-app/trackio/commit/643878a82985fab9e6675f769ff0107cb46e042a) - Add emoji to README and deploy README content. Thanks @qgallouedec! +- [#529](https://github.com/gradio-app/trackio/pull/529) [`a77972b`](https://github.com/gradio-app/trackio/commit/a77972b68541ebe9e056824e69c9bbca3979ece4) - Remove pydub dependency. Thanks @abidlabs! + +## 0.24.1 + +### Features + +- [#524](https://github.com/gradio-app/trackio/pull/524) [`65a6897`](https://github.com/gradio-app/trackio/commit/65a6897561b465fc8f05550562f8da1ba3c99060) - Fix `trackio skills add`. Thanks @abidlabs! +- [#522](https://github.com/gradio-app/trackio/pull/522) [`05aaca7`](https://github.com/gradio-app/trackio/commit/05aaca7f166bf7667b60b40656d677532a4bdd6e) - relax `starlette` dependency and fix import style. Thanks @abidlabs! +- [#525](https://github.com/gradio-app/trackio/pull/525) [`32c05c5`](https://github.com/gradio-app/trackio/commit/32c05c5d5e3aa84ca7099a6fa08a9093ccd4b95f) - Restore sidebar share and embed snippets, and fix query parameter regression. Thanks @abidlabs! + +## 0.24.0 + +### Features + +- [#502](https://github.com/gradio-app/trackio/pull/502) [`3b397df`](https://github.com/gradio-app/trackio/commit/3b397dfbaff9de137b088f3cad528117e14faab1) - Add docs on SQL & Parquet schema / format, as well as a new CLI command: `trackio query project --project PROJECT --sql SQL_QUERY`. Thanks @abidlabs! +- [#506](https://github.com/gradio-app/trackio/pull/506) [`498bbc4`](https://github.com/gradio-app/trackio/commit/498bbc47f66cc90cc5776f363d001a5571941c00) - Scope bucket sync to trackio/ subtree to avoid walking the HF cache. Thanks @abidlabs! +- [#505](https://github.com/gradio-app/trackio/pull/505) [`8e26ab9`](https://github.com/gradio-app/trackio/commit/8e26ab93b5d9caa2f81334f6fff42fb9cefbb232) - Add an `id` field to `Run` which is used internally, allowing users to have multiple runs with the same run name. Thanks @abidlabs! +- [#517](https://github.com/gradio-app/trackio/pull/517) [`29e1034`](https://github.com/gradio-app/trackio/commit/29e1034b795567ec5ed6d19c5a946915a6498e2a) - Fix static exports, Space bucket handling, and other misc issues. Thanks @abidlabs! +- [#489](https://github.com/gradio-app/trackio/pull/489) [`1b96db3`](https://github.com/gradio-app/trackio/commit/1b96db39c8fd4326e621ee2336b0fca4f263a18a) - Remove `gradio` dependency in `trackio` -- only `gradio_client` is needed locally anymore. Also lazily import `pandas` and remove it as a dependency. Thanks @abidlabs! +- [#513](https://github.com/gradio-app/trackio/pull/513) [`d54d290`](https://github.com/gradio-app/trackio/commit/d54d290fcb1bb08358b558a43a962f78abe990ea) - Reduce HF Spaces 429s: polling tuning and batched metric logs API. Thanks @abidlabs! +- [#516](https://github.com/gradio-app/trackio/pull/516) [`afe2959`](https://github.com/gradio-app/trackio/commit/afe295988928a3ea3ded38bdb5bb05cca85d3c74) - Fix run list order and legend overflow. Thanks @abidlabs! +- [#515](https://github.com/gradio-app/trackio/pull/515) [`0a242b8`](https://github.com/gradio-app/trackio/commit/0a242b85127b02f532b24c7fd2bb046580cc7641) - Add Gradio-compatible /gradio_api routes on Spaces. Thanks @abidlabs! +- [#510](https://github.com/gradio-app/trackio/pull/510) [`60bbc86`](https://github.com/gradio-app/trackio/commit/60bbc86b4e7f880de72075e5bf31b093709bb5a4) - Add server_url and TRACKIO_SERVER_URL for self-hosted servers; space_id and TRACKIO_SPACE_ID take precedence when both are set. Thanks @abidlabs! +- [#509](https://github.com/gradio-app/trackio/pull/509) [`21c099a`](https://github.com/gradio-app/trackio/commit/21c099aa830a278973fab4c7c58a0139f417caa4) - Fix: Open browser with write_token so trackio show allows mutations. Thanks @abidlabs! + +## 0.23.0 + +### Features + +- [#494](https://github.com/gradio-app/trackio/pull/494) [`e8a897d`](https://github.com/gradio-app/trackio/commit/e8a897d2266d9b2558f72d768b0b21f4d0a8781b) - Add a settings/CLI page to Trackio. Thanks @abidlabs! +- [#481](https://github.com/gradio-app/trackio/pull/481) [`882647e`](https://github.com/gradio-app/trackio/commit/882647ec1599cf04500d03b5ca75ddc2733682e2) - Add multi-GPU system metrics support. Thanks @Saba9! +- [#485](https://github.com/gradio-app/trackio/pull/485) [`46a3cc3`](https://github.com/gradio-app/trackio/commit/46a3cc3758719e171417612efee102a487e71ebd) - Fix/remove flaky E2E space tests. Thanks @abidlabs! +- [#501](https://github.com/gradio-app/trackio/pull/501) [`06ea885`](https://github.com/gradio-app/trackio/commit/06ea8852f5e40ab3f1cf629a0a01af5c17f847a1) - Fix SQLite corruption on bucket-mounted Spaces. Thanks @abidlabs! +- [#496](https://github.com/gradio-app/trackio/pull/496) [`af23d74`](https://github.com/gradio-app/trackio/commit/af23d74438b146c4a3512ace15ea984656e943ed) - Prevent trackio errors from crashing the user's training loop. Thanks @abidlabs! + +## 0.22.0 + +### Features + +- [#484](https://github.com/gradio-app/trackio/pull/484) [`cc05ada`](https://github.com/gradio-app/trackio/commit/cc05ada8e89773f3a894af99b801ef680f64418f) - Fix duplicate columns in parquet export. Thanks @abidlabs! +- [#487](https://github.com/gradio-app/trackio/pull/487) [`853f764`](https://github.com/gradio-app/trackio/commit/853f7646a70d12633afaa4f69db86425aa665413) - Relax `PIL` dependency and remove `plotly` as it's no longer used. Thanks @abidlabs! + +## 0.21.2 + +### Features + +- [#482](https://github.com/gradio-app/trackio/pull/482) [`f62180a`](https://github.com/gradio-app/trackio/commit/f62180a0218bc99a259d5ca110a0384a6cae11c8) - Use server-side bucket copy when freezing Spaces. Thanks @abidlabs! + +## 0.21.1 + +### Features + +- [#475](https://github.com/gradio-app/trackio/pull/475) [`fcb476c`](https://github.com/gradio-app/trackio/commit/fcb476cd37a40923e9679aaf966f41d582a878a8) - Tweaks. Thanks @abidlabs! +- [#477](https://github.com/gradio-app/trackio/pull/477) [`7d52dfd`](https://github.com/gradio-app/trackio/commit/7d52dfdce5b6eff6a34501a6d5a620220663cf09) - Fix `.sync()` and add `.freeze()` as a separate methods. Thanks @abidlabs! + +## 0.21.0 + +### Features + +- [#467](https://github.com/gradio-app/trackio/pull/467) [`f357deb`](https://github.com/gradio-app/trackio/commit/f357debf78957e4c1f2b901bee4f77cf397298b4) - Allow logged metrics as x-axis choices. Thanks @abidlabs! +- [#474](https://github.com/gradio-app/trackio/pull/474) [`655673d`](https://github.com/gradio-app/trackio/commit/655673d4c6b7c8b7ee8f87f2589f2dbbc3d2ef91) - Fix file descriptor leak from `sqlite3.connect`. Thanks @abidlabs! +- [#470](https://github.com/gradio-app/trackio/pull/470) [`bea8c9d`](https://github.com/gradio-app/trackio/commit/bea8c9dcae0b59d071b6c779c97ee525c9bbf6e7) - Restores tooltips to line plots and fixes the call to uses TTL instead of OAuth. Thanks @abidlabs! +- [#471](https://github.com/gradio-app/trackio/pull/471) [`246fce0`](https://github.com/gradio-app/trackio/commit/246fce0a01619e1c2c538c67b3e460883334d500) - Deprecate dataset backend in favor of buckets. Thanks @abidlabs! +- [#465](https://github.com/gradio-app/trackio/pull/465) [`3e11174`](https://github.com/gradio-app/trackio/commit/3e1117438bb8168b802245a33059affa558ae519) - Use HF buckets as backend. Thanks @abidlabs! +- [#469](https://github.com/gradio-app/trackio/pull/469) [`915d170`](https://github.com/gradio-app/trackio/commit/915d17045133172b59195acfdcc70709229668aa) - Make static Spaces work with Buckets and also allow conversion from Gradio SDK to Static Spaces. Thanks @abidlabs! + +## 0.20.2 + +### Features + +- [#464](https://github.com/gradio-app/trackio/pull/464) [`c89ebb3`](https://github.com/gradio-app/trackio/commit/c89ebb3b50f695bc7f16cbc6f46dce86f79a01e9) - Improve rendering of curves. Thanks @abidlabs! +- [#462](https://github.com/gradio-app/trackio/pull/462) [`9160b78`](https://github.com/gradio-app/trackio/commit/9160b78ff6f258f0b87a4f34a24e7d0b5dfbf2fb) - Refactor plot title to display only the metric name without the path. Thanks @qgallouedec! + +## 0.20.1 + +### Features + +- [#454](https://github.com/gradio-app/trackio/pull/454) [`22881db`](https://github.com/gradio-app/trackio/commit/22881dbbbb6b81197a00a19853771007093d61e4) - Bar chart single point. Thanks @abidlabs! +- [#455](https://github.com/gradio-app/trackio/pull/455) [`f8db51a`](https://github.com/gradio-app/trackio/commit/f8db51a20ca61ef703f3f2c2ee1ebd9c4f239cf2) - Adds a static Trackio mode via `trackio.sync(sdk="static")` and support for the `TRACKIO_SPACE_ID` environment variable. Thanks @abidlabs! + +## 0.20.0 + +### Features + +- [#450](https://github.com/gradio-app/trackio/pull/450) [`b0571ef`](https://github.com/gradio-app/trackio/commit/b0571ef6207a1ce346696f858ad2b7b584dd194f) - Use Svelte source for Gradio components directly in Trackio dashboard. Thanks @abidlabs! + +## 0.19.0 + +### Features + +- [#445](https://github.com/gradio-app/trackio/pull/445) [`cef4a58`](https://github.com/gradio-app/trackio/commit/cef4a583cb76f4091fc6c0e5783124ee84f8e243) - Add remote HF Space support to CLI. Thanks @abidlabs! +- [#444](https://github.com/gradio-app/trackio/pull/444) [`358f2a9`](https://github.com/gradio-app/trackio/commit/358f2a9ca238ee8b90b5a8c96220da287e0698fb) - Fix alerts placeholder flashing on reports page. Thanks @abidlabs! + +## 0.18.0 + +### Features + +- [#435](https://github.com/gradio-app/trackio/pull/435) [`4a47112`](https://github.com/gradio-app/trackio/commit/4a471128e18a39e45fad48a67fd711c5ae9e4aed) - feat: allow hiding section header accordions. Thanks @Saba9! +- [#439](https://github.com/gradio-app/trackio/pull/439) [`18e9650`](https://github.com/gradio-app/trackio/commit/18e96503d5a3a7cf926e92782d457e23c19942bd) - Add alerts with webhooks, CLI, and documentation. Thanks @abidlabs! +- [#438](https://github.com/gradio-app/trackio/pull/438) [`0875ccd`](https://github.com/gradio-app/trackio/commit/0875ccd3d8a41b1376f64030f21cfe8cdcc73b05) - Add "share this view" functionality. Thanks @qgallouedec! +- [#409](https://github.com/gradio-app/trackio/pull/409) [`9282403`](https://github.com/gradio-app/trackio/commit/9282403d8896d48679b0f888208a7ba5bdd4271a) - Add Apple Silicon GPU and system monitoring support. Thanks @znation! +- [#434](https://github.com/gradio-app/trackio/pull/434) [`4193223`](https://github.com/gradio-app/trackio/commit/41932230a3a2e1c16405dba08ecba5a42f11d1a8) - fix: table slider crash. Thanks @Saba9! + +### Fixes + +- [#441](https://github.com/gradio-app/trackio/pull/441) [`3a2d11d`](https://github.com/gradio-app/trackio/commit/3a2d11dab0b4b37c925abc30ef84b0e2910321ee) - preserve x-axis step when toggling run checkboxes. Thanks @Saba9! + +## 0.17.0 + +### Features + +- [#428](https://github.com/gradio-app/trackio/pull/428) [`f7dd1ce`](https://github.com/gradio-app/trackio/commit/f7dd1ce2dc8a1936f9983467fcbcf93bfef01e09) - feat: add ability to rename runs. Thanks @Saba9! +- [#437](https://github.com/gradio-app/trackio/pull/437) [`2727c0b`](https://github.com/gradio-app/trackio/commit/2727c0b0755f48f7f186162ea45185c98f6b5516) - Add markdown reports across Trackio. Thanks @abidlabs! +- [#427](https://github.com/gradio-app/trackio/pull/427) [`5aeb9ed`](https://github.com/gradio-app/trackio/commit/5aeb9edcfd2068d309d9d64f172dcbcc327be1ab) - Make Trackio logging much more robust. Thanks @abidlabs! + +## 0.16.1 + +### Features + +- [#431](https://github.com/gradio-app/trackio/pull/431) [`c7ce55b`](https://github.com/gradio-app/trackio/commit/c7ce55b14dd5eb0c2165fb15df17dd60721c9325) - Lazy load the UI when trackio is imported. Thanks @abidlabs! + +## 0.16.0 + +### Features + +- [#426](https://github.com/gradio-app/trackio/pull/426) [`ead4dc8`](https://github.com/gradio-app/trackio/commit/ead4dc8e74ee2d8e47d61bca0a7668456acf49be) - Fix redundant double rendering of group checkboxes. Thanks @abidlabs! +- [#413](https://github.com/gradio-app/trackio/pull/413) [`39c4750`](https://github.com/gradio-app/trackio/commit/39c4750951d554ba6eb4d58847c6bb444b2891a8) - Check `dist-packages` when checking for source installation. Thanks @sergiopaniego! +- [#423](https://github.com/gradio-app/trackio/pull/423) [`2e52ab3`](https://github.com/gradio-app/trackio/commit/2e52ab303e3041718a6a56fbf84d0848aca9ad67) - Fix legend outline visibility issue. Thanks @Raghunath-Balaji! +- [#407](https://github.com/gradio-app/trackio/pull/407) [`c8a384d`](https://github.com/gradio-app/trackio/commit/c8a384ddfe5a295cecf862a26178d40e48acb424) - Fix pytests that were failling locally on MacOS. Thanks @abidlabs! +- [#405](https://github.com/gradio-app/trackio/pull/405) [`35aae4e`](https://github.com/gradio-app/trackio/commit/35aae4e3aa3e2b2888887528478b9dc6a9808bda) - Add conditional padding for HF Space dashboard when not in iframe. Thanks @znation! + +## 0.15.0 + +### Features + +- [#397](https://github.com/gradio-app/trackio/pull/397) [`6b38ad0`](https://github.com/gradio-app/trackio/commit/6b38ad02e5d73a0df49c4eede7e91331282ece04) - Adds `--host` cli option support. Thanks @abidlabs! +- [#396](https://github.com/gradio-app/trackio/pull/396) [`4a4d1ab`](https://github.com/gradio-app/trackio/commit/4a4d1ab85e63d923132a3fa7afa5d90e16431bec) - Fix run selection issue. Thanks @abidlabs! +- [#394](https://github.com/gradio-app/trackio/pull/394) [`c47a3a3`](https://github.com/gradio-app/trackio/commit/c47a3a31f8c4b83bce1aa7fc22eeba3d9021ad3d) - Add wandb-compatible API for trackio. Thanks @abidlabs! +- [#378](https://github.com/gradio-app/trackio/pull/378) [`b02046a`](https://github.com/gradio-app/trackio/commit/b02046a5b0dad7c9854e099a87f884afba4aecb2) - Add JSON export button for line plots and upgrade gradio dependency. Thanks @JamshedAli18! + +## 0.14.2 + +### Features + +- [#386](https://github.com/gradio-app/trackio/pull/386) [`f9452cd`](https://github.com/gradio-app/trackio/commit/f9452cdb8f0819368f3610f7ac0ed08957305275) - Fixing some issues related to deployed Trackio Spaces. Thanks @abidlabs! + +## 0.14.1 + +### Features + +- [#382](https://github.com/gradio-app/trackio/pull/382) [`44fe9bb`](https://github.com/gradio-app/trackio/commit/44fe9bb264fb2aafb0ec302ff15227c045819a2c) - Fix app file path when Trackio is not installed from source. Thanks @abidlabs! +- [#380](https://github.com/gradio-app/trackio/pull/380) [`c3f4cff`](https://github.com/gradio-app/trackio/commit/c3f4cff74bc5676e812773d8571454894fcdc7cc) - Add CLI commands for querying projects, runs, and metrics. Thanks @abidlabs! + +## 0.14.0 + +### Features + +- [#377](https://github.com/gradio-app/trackio/pull/377) [`5c5015b`](https://github.com/gradio-app/trackio/commit/5c5015b68c85c5de51111dad983f735c27b9a05f) - fixed wrapping issue in Runs table. Thanks @gaganchapa! +- [#374](https://github.com/gradio-app/trackio/pull/374) [`388e26b`](https://github.com/gradio-app/trackio/commit/388e26b9e9f24cd7ad203affe9b709be885b3d24) - Save Optimized Parquet files. Thanks @lhoestq! +- [#371](https://github.com/gradio-app/trackio/pull/371) [`fbace9c`](https://github.com/gradio-app/trackio/commit/fbace9cd7732c166f34d268f54b05bb06846cc5d) - Add GPU metrics logging. Thanks @kashif! +- [#367](https://github.com/gradio-app/trackio/pull/367) [`862840c`](https://github.com/gradio-app/trackio/commit/862840c13e30fc960cbee5b9eac4d3c25beba9de) - Add option to only show latest run, and fix the double logo issue. Thanks @abidlabs! + +## 0.13.1 + +### Features + +- [#369](https://github.com/gradio-app/trackio/pull/369) [`767e9fe`](https://github.com/gradio-app/trackio/commit/767e9fe095d7c6ed102016caf927c1517fb8618c) - tiny pr removing unnecessary code. Thanks @abidlabs! + +## 0.13.0 + +### Features + +- [#358](https://github.com/gradio-app/trackio/pull/358) [`073715d`](https://github.com/gradio-app/trackio/commit/073715d1caf8282f68890117f09c3ac301205312) - Improvements to `trackio.sync()`. Thanks @abidlabs! + +## 0.12.0 + +### Features + +- [#357](https://github.com/gradio-app/trackio/pull/357) [`02ba815`](https://github.com/gradio-app/trackio/commit/02ba815358060f1966052de051a5bdb09702920e) - Redesign media and tables to show up on separate page. Thanks @abidlabs! +- [#359](https://github.com/gradio-app/trackio/pull/359) [`08fe9c9`](https://github.com/gradio-app/trackio/commit/08fe9c9ddd7fe99ee811555fdfb62df9ab88e939) - docs: Improve docstrings. Thanks @qgallouedec! + +## 0.11.0 + +### Features + +- [#355](https://github.com/gradio-app/trackio/pull/355) [`ea51f49`](https://github.com/gradio-app/trackio/commit/ea51f4954922f21be76ef828700420fe9a912c4b) - Color code run checkboxes and match with plot lines. Thanks @abidlabs! +- [#353](https://github.com/gradio-app/trackio/pull/353) [`8abe691`](https://github.com/gradio-app/trackio/commit/8abe6919aeefe21fc7a23af814883efbb037c21f) - Remove show_api from demo.launch. Thanks @sergiopaniego! +- [#351](https://github.com/gradio-app/trackio/pull/351) [`8a8957e`](https://github.com/gradio-app/trackio/commit/8a8957e530dd7908d1fef7f2df030303f808101f) - Add `trackio.save()`. Thanks @abidlabs! + +## 0.10.0 + +### Features + +- [#305](https://github.com/gradio-app/trackio/pull/305) [`e64883a`](https://github.com/gradio-app/trackio/commit/e64883a51f7b8b93f7d48b8afe55acdb62238b71) - bump to gradio 6.0, make `trackio` compatible, and fix related issues. Thanks @abidlabs! + +## 0.9.1 + +### Features + +- [#344](https://github.com/gradio-app/trackio/pull/344) [`7e01024`](https://github.com/gradio-app/trackio/commit/7e010241d9a34794e0ce0dc19c1a6f0cf94ba856) - Avoid redundant calls to /whoami-v2. Thanks @Wauplin! + +## 0.9.0 + +### Features + +- [#343](https://github.com/gradio-app/trackio/pull/343) [`51bea30`](https://github.com/gradio-app/trackio/commit/51bea30f2877adff8e6497466d3a799400a0a049) - Sync offline projects to Hugging Face spaces. Thanks @candemircan! +- [#341](https://github.com/gradio-app/trackio/pull/341) [`4fd841f`](https://github.com/gradio-app/trackio/commit/4fd841fa190e15071b02f6fba7683ef4f393a654) - Adds a basic UI test to `trackio`. Thanks @abidlabs! +- [#339](https://github.com/gradio-app/trackio/pull/339) [`011d91b`](https://github.com/gradio-app/trackio/commit/011d91bb6ae266516fd250a349285670a8049d05) - Allow customzing the trackio color palette. Thanks @abidlabs! + +## 0.8.1 + +### Features + +- [#336](https://github.com/gradio-app/trackio/pull/336) [`5f9f51d`](https://github.com/gradio-app/trackio/commit/5f9f51dac8677f240d7c42c3e3b2660a22aee138) - Support a list of `Trackio.Image` in a `trackio.Table` cell. Thanks @abidlabs! + +## 0.8.0 + +### Features + +- [#331](https://github.com/gradio-app/trackio/pull/331) [`2c02d0f`](https://github.com/gradio-app/trackio/commit/2c02d0fd0a5824160528782402bb0dd4083396d5) - Truncate table string values that are greater than 250 characters (configuirable via env variable). Thanks @abidlabs! +- [#324](https://github.com/gradio-app/trackio/pull/324) [`50b2122`](https://github.com/gradio-app/trackio/commit/50b2122e7965ac82a72e6cb3b7d048bc10a2a6b1) - Add log y-axis functionality to UI. Thanks @abidlabs! +- [#326](https://github.com/gradio-app/trackio/pull/326) [`61dc1f4`](https://github.com/gradio-app/trackio/commit/61dc1f40af2f545f8e70395ddf0dbb8aee6b60d5) - Fix: improve table rendering for metrics in Trackio Dashboard. Thanks @vigneshwaran! +- [#328](https://github.com/gradio-app/trackio/pull/328) [`6857cbb`](https://github.com/gradio-app/trackio/commit/6857cbbe557a59a4642f210ec42566d108294e63) - Support trackio.Table with trackio.Image columns. Thanks @abidlabs! +- [#323](https://github.com/gradio-app/trackio/pull/323) [`6857cbb`](https://github.com/gradio-app/trackio/commit/6857cbbe557a59a4642f210ec42566d108294e63) - add Trackio client implementations in Go, Rust, and JS. Thanks @vaibhav-research! + +## 0.7.0 + +### Features + +- [#277](https://github.com/gradio-app/trackio/pull/277) [`db35601`](https://github.com/gradio-app/trackio/commit/db35601b9c023423c4654c9909b8ab73e58737de) - fix: make grouped runs view reflect live updates. Thanks @Saba9! +- [#320](https://github.com/gradio-app/trackio/pull/320) [`24ae739`](https://github.com/gradio-app/trackio/commit/24ae73969b09fb3126acd2f91647cdfbf8cf72a1) - Add additional query parms for xmin, xmax, and smoothing. Thanks @abidlabs! +- [#270](https://github.com/gradio-app/trackio/pull/270) [`cd1dfc3`](https://github.com/gradio-app/trackio/commit/cd1dfc3dc641b4499ac6d4a1b066fa8e2b52c57b) - feature: add support for logging audio. Thanks @Saba9! + +## 0.6.0 + +### Features + +- [#309](https://github.com/gradio-app/trackio/pull/309) [`1df2353`](https://github.com/gradio-app/trackio/commit/1df23534d6c01938c8db9c0f584ffa23e8d6021d) - Add histogram support with wandb-compatible API. Thanks @abidlabs! +- [#315](https://github.com/gradio-app/trackio/pull/315) [`76ba060`](https://github.com/gradio-app/trackio/commit/76ba06055dc43ca8f03b79f3e72d761949bd19a8) - Add guards to avoid silent fails. Thanks @Xmaster6y! +- [#313](https://github.com/gradio-app/trackio/pull/313) [`a606b3e`](https://github.com/gradio-app/trackio/commit/a606b3e1c5edf3d4cf9f31bd50605226a5a1c5d0) - No longer prevent certain keys from being used. Instead, dunderify them to prevent collisions with internal usage. Thanks @abidlabs! +- [#317](https://github.com/gradio-app/trackio/pull/317) [`27370a5`](https://github.com/gradio-app/trackio/commit/27370a595d0dbdf7eebbe7159d2ba778f039da44) - quick fixes for trackio.histogram. Thanks @abidlabs! +- [#312](https://github.com/gradio-app/trackio/pull/312) [`aa0f3bf`](https://github.com/gradio-app/trackio/commit/aa0f3bf372e7a0dd592a38af699c998363830eeb) - Fix video logging by adding TRACKIO_DIR to allowed_paths. Thanks @abidlabs! + +## 0.5.3 + +### Features + +- [#300](https://github.com/gradio-app/trackio/pull/300) [`5e4cacf`](https://github.com/gradio-app/trackio/commit/5e4cacf2e7ce527b4ce60de3a5bc05d2c02c77fb) - Adds more environment variables to allow customization of Trackio dashboard. Thanks @abidlabs! + +## 0.5.2 + +### Features + +- [#293](https://github.com/gradio-app/trackio/pull/293) [`64afc28`](https://github.com/gradio-app/trackio/commit/64afc28d3ea1dfd821472dc6bf0b8ed35a9b74be) - Ensures that the TRACKIO_DIR environment variable is respected. Thanks @abidlabs! +- [#287](https://github.com/gradio-app/trackio/pull/287) [`cd3e929`](https://github.com/gradio-app/trackio/commit/cd3e9294320949e6b8b829239069a43d5d7ff4c1) - fix(sqlite): unify .sqlite extension, allow export when DBs exist, clean WAL sidecars on import. Thanks @vaibhav-research! + +### Fixes + +- [#291](https://github.com/gradio-app/trackio/pull/291) [`3b5adc3`](https://github.com/gradio-app/trackio/commit/3b5adc3d1f452dbab7a714d235f4974782f93730) - Fix the wheel build. Thanks @pngwn! + +## 0.5.1 + +### Fixes + +- [#278](https://github.com/gradio-app/trackio/pull/278) [`314c054`](https://github.com/gradio-app/trackio/commit/314c05438007ddfea3383e06fd19143e27468e2d) - Fix row orientation of metrics plots. Thanks @abidlabs! \ No newline at end of file diff --git a/trackio/__init__.py b/trackio/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a8bf4b819e9dff5ea846bd6aa914d12cbc75c1b0 --- /dev/null +++ b/trackio/__init__.py @@ -0,0 +1,1216 @@ +import atexit +import glob +import json +import logging +import os +import shutil +import warnings +import webbrowser +from pathlib import Path +from typing import Any + +import huggingface_hub +from gradio_client import handle_file +from huggingface_hub import SpaceStorage +from huggingface_hub.errors import LocalTokenNotFoundError + +from trackio import context_vars, deploy, utils +from trackio.alerts import AlertLevel +from trackio.api import Api +from trackio.apple_gpu import apple_gpu_available +from trackio.apple_gpu import log_apple_gpu as _log_apple_gpu +from trackio.artifact import Artifact +from trackio.cpu import cpu_available +from trackio.cpu import log_cpu as _log_cpu +from trackio.deploy import freeze, sync +from trackio.frontend_config import resolve_frontend_dir +from trackio.gpu import gpu_available +from trackio.gpu import log_gpu as _log_nvidia_gpu +from trackio.histogram import Histogram +from trackio.imports import import_csv, import_tf_events +from trackio.launch import launch_trackio_dashboard +from trackio.markdown import Markdown +from trackio.media import ( + TrackioAudio, + TrackioImage, + TrackioVideo, + get_project_media_path, +) +from trackio.references import ( + ReferenceHandler, + ResolvedReference, + register_reference_handler, +) +from trackio.remote_client import RemoteClient +from trackio.run import Run +from trackio.server import TrackioDashboardApp, build_starlette_app_only +from trackio.sqlite_storage import SQLiteStorage +from trackio.table import Table +from trackio.trace import Trace +from trackio.typehints import UploadEntry +from trackio.utils import TRACKIO_DIR, TRACKIO_LOGO_DIR, _emit_nonfatal_warning + +logging.getLogger("httpx").setLevel(logging.WARNING) + +__version__ = json.loads(Path(__file__).parent.joinpath("package.json").read_text())[ + "version" +] + + +class _TupleNoPrint(tuple): + def __repr__(self) -> str: + return "" + + +__all__ = [ + "init", + "log", + "log_system", + "log_gpu", + "log_artifact", + "use_artifact", + "log_cpu", + "finish", + "alert", + "AlertLevel", + "show", + "sync", + "freeze", + "delete_project", + "import_csv", + "import_tf_events", + "save", + "Artifact", + "ReferenceHandler", + "ResolvedReference", + "register_reference_handler", + "Image", + "Video", + "Audio", + "Table", + "Trace", + "Histogram", + "Markdown", + "Api", + "TRACKIO_LOGO_DIR", +] + +Audio = TrackioAudio +Image = TrackioImage +Video = TrackioVideo + + +config = {} + +_atexit_registered = False +_spaces_created_this_session: set[str] = set() +_projects_notified_auto_log_hw: set[str] = set() + + +def _cleanup_current_run(): + run = context_vars.current_run.get() + if run is not None: + try: + run.finish() + except Exception: + pass + + +def _safe_get_runs_for_init( + project: str, + space_id: str | None, + server_base_url: str | None, + write_token: str | None, + resume: str, + remote_client: RemoteClient | None = None, + check_existing_for_never: bool = False, +) -> list[str]: + if space_id is not None or server_base_url is not None: + if resume == "never" and not check_existing_for_never: + return [] + if remote_client is not None: + source = space_id or server_base_url + try: + runs = remote_client.predict( + project=project, api_name="/get_runs_for_project" + ) + return runs if isinstance(runs, list) else [] + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not inspect existing runs for project '{project}' on '{source}': {e}. Continuing without resume metadata." + ) + return [] + try: + return SQLiteStorage.get_runs(project) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not inspect existing runs for project '{project}': {e}. Continuing without resume metadata." + ) + return [] + + +def _safe_get_latest_run_for_init( + project: str, + name: str, + space_id: str | None = None, + server_base_url: str | None = None, + write_token: str | None = None, + remote_client: RemoteClient | None = None, +) -> dict | None: + if ( + space_id is not None or server_base_url is not None + ) and remote_client is not None: + source = space_id or server_base_url + try: + runs = remote_client.predict( + project=project, api_name="/get_runs_for_project" + ) + if not isinstance(runs, list): + return None + matches = [r for r in runs if isinstance(r, dict) and r.get("name") == name] + if not matches: + return None + matches.sort(key=lambda r: r.get("created_at") or "", reverse=True) + return matches[0] + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not inspect existing runs for project '{project}' on '{source}': {e}. Continuing without resume metadata." + ) + return None + try: + return SQLiteStorage.get_latest_run_record_by_name(project, name) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not inspect existing runs for project '{project}': {e}. Continuing without resume metadata." + ) + return None + + +def _safe_get_last_step_for_init( + project: str, + run_name: str, + space_id: str | None, + server_base_url: str | None, + write_token: str | None, + resumed: bool, + run_id: str | None = None, + remote_client: RemoteClient | None = None, +) -> int | None: + if not resumed: + return None + if ( + space_id is not None or server_base_url is not None + ) and remote_client is not None: + source = space_id or server_base_url + try: + summary_kwargs: dict[str, Any] = { + "project": project, + "api_name": "/get_run_summary", + } + if run_id is not None: + summary_kwargs["run_id"] = run_id + else: + summary_kwargs["run"] = run_name + summary = remote_client.predict(**summary_kwargs) + if isinstance(summary, dict): + last_step = summary.get("last_step") + return last_step if isinstance(last_step, int) else None + return None + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not recover the previous step for run '{run_name}' on '{source}': {e}. Continuing from step 0." + ) + return None + try: + return SQLiteStorage.get_max_step_for_run(project, run_name, run_id=run_id) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not recover the previous step for run '{run_name}': {e}. Continuing from step 0." + ) + return None + + +def init( + project: str, + name: str | None = None, + group: str | None = None, + space_id: str | None = None, + server_url: str | None = None, + space_storage: SpaceStorage | None = None, + dataset_id: str | None = None, + bucket_id: str | None = None, + config: dict | None = None, + resume: str = "never", + settings: Any = None, + private: bool | None = None, + embed: bool = True, + auto_log_gpu: bool | None = None, + gpu_log_interval: float = 10.0, + auto_log_cpu: bool | None = None, + cpu_log_interval: float = 10.0, + webhook_url: str | None = None, + webhook_min_level: AlertLevel | str | None = None, +) -> Run: + """ + Creates a new Trackio project and returns a [`Run`] object. + + Args: + project (`str`): + The name of the project (can be an existing project to continue tracking or + a new project to start tracking from scratch). + name (`str`, *optional*): + The name of the run (if not provided, a default name will be generated). + group (`str`, *optional*): + The name of the group which this run belongs to in order to help organize + related runs together. You can toggle the entire group's visibility in the + dashboard. + space_id (`str`, *optional*): + If provided, the project will be logged to a Hugging Face Space instead of + a local directory. Should be a complete Space name like + `"username/reponame"` or `"orgname/reponame"`, or just `"reponame"` in which + case the Space will be created in the currently-logged-in Hugging Face + user's namespace. If the Space does not exist, it will be created. If the + Space already exists, the project will be logged to it. Can also be set + via the `TRACKIO_SPACE_ID` environment variable. You cannot log to a + Space that has been **frozen** (converted to the static SDK); use + ``trackio.sync(..., sdk="static")`` only after you are done logging. + Takes precedence over `server_url` and `TRACKIO_SERVER_URL` when more than + one is set. + server_url (`str`, *optional*): + Base URL of a self-hosted Trackio server (``http://`` or ``https://``), or the + write-access URL from ``trackio.show()`` which may include a ``write_token`` query + parameter. The client sends that token on each request (``X-Trackio-Write-Token``); + you can also set ``TRACKIO_WRITE_TOKEN`` instead of embedding the token in the URL. + When set, metrics are sent to that server over HTTP instead of creating or syncing + to a Hugging Face Space. Can also be set via the ``TRACKIO_SERVER_URL`` environment + variable. Ignored when ``space_id`` or ``TRACKIO_SPACE_ID`` is set. + space_storage ([`~huggingface_hub.SpaceStorage`], *optional*): + Choice of persistent storage tier. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + bucket_id (`str`, *optional*): + The ID of the Hugging Face Bucket to use for metric persistence. By default, + when a `space_id` is provided and `bucket_id` is not explicitly set, a + bucket is auto-generated from the space_id. Buckets provide + S3-like storage without git overhead - the SQLite database is stored directly + via `hf-mount` in the Space. Specify a Bucket with name like + `"username/bucketname"` or just `"bucketname"`. + config (`dict`, *optional*): + A dictionary of configuration options. Provided for compatibility with + `wandb.init()`. + resume (`str`, *optional*, defaults to `"never"`): + Controls how to handle resuming a run. Can be one of: + + - `"must"`: Must resume the run with the given name, raises error if run + doesn't exist + - `"allow"`: Resume the run if it exists, otherwise create a new run + - `"never"`: Never resume a run, always create a new one + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + settings (`Any`, *optional*): + Not used. Provided for compatibility with `wandb.init()`. + embed (`bool`, *optional*, defaults to `True`): + If running inside a Jupyter/Colab notebook, whether the dashboard should + automatically be embedded in the cell when trackio.init() is called. For + local runs, this launches a local Trackio dashboard and embeds it. For Space runs, + this embeds the Space URL. In Colab, the local dashboard will be accessible + via a public share URL when `share=True`. + auto_log_gpu (`bool` or `None`, *optional*, defaults to `None`): + Controls automatic GPU metrics logging. If `None` (default), GPU logging + is automatically enabled when `nvidia-ml-py` is installed and an NVIDIA + GPU or Apple M series is detected. Set to `True` to force enable or + `False` to disable. + gpu_log_interval (`float`, *optional*, defaults to `10.0`): + The interval in seconds between automatic GPU metric logs. + Only used when `auto_log_gpu=True`. + auto_log_cpu (`bool` or `None`, *optional*, defaults to `None`): + Controls automatic CPU and RAM metrics logging (utilization, memory, + disk I/O, network I/O, and sensors). If `None` (default), CPU logging + is automatically enabled when `psutil` is installed. Set to `True` to + force enable or `False` to disable. + cpu_log_interval (`float`, *optional*, defaults to `10.0`): + The interval in seconds between automatic CPU metric logs. + Only used when CPU auto-logging is enabled. + webhook_url (`str`, *optional*): + A webhook URL to POST alert payloads to when `trackio.alert()` is + called. Supports Slack and Discord webhook URLs natively (payloads + are formatted automatically). Can also be set via the + `TRACKIO_WEBHOOK_URL` environment variable. Individual alerts can + override this URL by passing `webhook_url` to `trackio.alert()`. + webhook_min_level (`AlertLevel` or `str`, *optional*): + Minimum alert level that should trigger webhook delivery. + For example, `AlertLevel.WARN` sends only `WARN` and `ERROR` + alerts to the webhook destination. Can also be set via + `TRACKIO_WEBHOOK_MIN_LEVEL`. + Returns: + `Run`: A [`Run`] object that can be used to log metrics and finish the run. + """ + SQLiteStorage.validate_project_name(project) + + if settings is not None: + _emit_nonfatal_warning( + "* Warning: settings is not used. Provided for compatibility with wandb.init(). Please create an issue at: https://github.com/gradio-app/trackio/issues if you need a specific feature implemented." + ) + + previous_run = context_vars.current_run.get() + if previous_run is not None: + try: + previous_run.finish() + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not finish the previous run '{previous_run.name}': {e}. Continuing with new run." + ) + context_vars.current_run.set(None) + + bucket_id_was_explicit = bucket_id is not None + space_id, server_url = utils.resolve_space_id_and_server_url(space_id, server_url) + if bucket_id is None and utils.on_spaces(): + bucket_id = os.environ.get("TRACKIO_BUCKET_ID") + if server_url is not None and not server_url.startswith(("http://", "https://")): + raise ValueError( + f"`server_url` must be a full URL starting with http:// or https://, got: {server_url!r}" + ) + server_base_url: str | None = None + write_token_resolved: str | None = None + if server_url is not None: + server_base_url, tok = utils.parse_trackio_server_url(server_url) + write_token_resolved = tok or os.environ.get("TRACKIO_WRITE_TOKEN") + if not write_token_resolved: + raise ValueError( + "Self-hosted logging requires a write token: add write_token to the server URL, " + "or set the TRACKIO_WRITE_TOKEN environment variable." + ) + if server_url is not None and (dataset_id is not None or bucket_id is not None): + raise ValueError( + "`dataset_id` and `bucket_id` are Hugging Face Spaces concepts and are not " + "compatible with `server_url`. Configure storage on the self-hosted server." + ) + if space_id is None and dataset_id is not None: + raise ValueError("Must provide a `space_id` when `dataset_id` is provided.") + if dataset_id is not None and bucket_id is not None: + raise ValueError("Cannot provide both `dataset_id` and `bucket_id`.") + try: + space_id, dataset_id, bucket_id = utils.preprocess_space_and_dataset_ids( + space_id, dataset_id, bucket_id + ) + if ( + space_id is not None + and dataset_id is None + and bucket_id is not None + and not bucket_id_was_explicit + and not utils.on_spaces() + ): + bucket_id = deploy.resolve_auto_bucket_id(space_id, bucket_id) + except LocalTokenNotFoundError as e: + raise LocalTokenNotFoundError( + f"You must be logged in to Hugging Face locally when `space_id` is provided to deploy to a Space. {e}" + ) from e + + if space_id is None and bucket_id is not None: + _emit_nonfatal_warning( + "trackio.init() has `bucket_id` set but `space_id` is None: metrics will be logged " + "locally only. Pass `space_id` to create or use a Hugging Face Space, which will be " + "attached to the Hugging Face Bucket.", + UserWarning, + stacklevel=2, + ) + + if space_id is not None: + deploy.raise_if_space_is_frozen_for_logging(space_id) + + remote_source = space_id or server_base_url + + if remote_source is not None: + url = remote_source + context_vars.current_server.set(url) + if space_id is not None: + context_vars.current_space_id.set(space_id) + context_vars.current_server_write_token.set(None) + else: + context_vars.current_space_id.set(None) + context_vars.current_server_write_token.set(write_token_resolved) + else: + url = None + context_vars.current_server.set(None) + context_vars.current_space_id.set(None) + context_vars.current_server_write_token.set(None) + + _should_embed_local = False + + newly_created_space = False + if space_id is not None and space_id in _spaces_created_this_session: + if deploy.space_is_running(space_id): + _spaces_created_this_session.discard(space_id) + else: + newly_created_space = True + + if ( + context_vars.current_project.get() is None + or context_vars.current_project.get() != project + ): + print(f"* Trackio project initialized: {project}") + + if bucket_id is not None: + if utils.on_spaces(): + os.environ["TRACKIO_BUCKET_ID"] = bucket_id + bucket_url = f"https://huggingface.co/buckets/{bucket_id}" + print( + f"* Trackio metrics will be synced to Hugging Face Bucket: {bucket_url}" + ) + elif dataset_id is not None: + if utils.on_spaces(): + os.environ["TRACKIO_DATASET_ID"] = dataset_id + print( + f"* Trackio metrics will be synced to Hugging Face Dataset: {dataset_id}" + ) + if remote_source is None: + print(f"* Trackio metrics logged to: {TRACKIO_DIR}") + _should_embed_local = embed and utils.is_in_notebook() + if not _should_embed_local: + utils.print_dashboard_instructions(project) + elif server_base_url is not None: + print( + f"* Trackio metrics will be sent to self-hosted server: {server_base_url}" + ) + if utils.is_in_notebook() and embed: + utils.embed_url_in_notebook(server_base_url) + else: + try: + if deploy.create_space_if_not_exists( + space_id, + space_storage, + dataset_id, + bucket_id, + private, + ): + _spaces_created_this_session.add(space_id) + newly_created_space = True + user_name, space_name = space_id.split("/") + space_url = deploy.SPACE_HOST_URL.format( + user_name=user_name, space_name=space_name + ) + if utils.is_in_notebook() and embed: + utils.embed_url_in_notebook(space_url) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not prepare Space '{space_id}': {e}. Logging will continue in local fallback mode until the Space is reachable." + ) + context_vars.current_project.set(project) + + remote_client = None + if space_id is not None and not newly_created_space: + try: + remote_client = RemoteClient( + space_id, + hf_token=huggingface_hub.utils.get_token(), + verbose=False, + ) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not create a remote client for Space '{space_id}': {e}. Continuing with local fallback metadata lookups." + ) + elif server_base_url is not None: + try: + remote_client = RemoteClient( + server_base_url, + hf_token=None, + write_token=write_token_resolved, + verbose=False, + ) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not create a remote client for '{server_base_url}': {e}. Continuing with local fallback metadata lookups." + ) + + existing_run_records = _safe_get_runs_for_init( + project, + space_id, + server_base_url, + write_token_resolved, + resume, + remote_client=remote_client, + check_existing_for_never=name is not None, + ) + existing_runs = [ + r["name"] if isinstance(r, dict) else r for r in existing_run_records + ] + + existing_run = ( + _safe_get_latest_run_for_init( + project, + name, + space_id=space_id, + server_base_url=server_base_url, + write_token=write_token_resolved, + remote_client=remote_client, + ) + if name is not None + else None + ) + resolved_run_id = None + + if resume == "must": + if name is None: + raise ValueError("Must provide a run name when resume='must'") + if existing_run is None: + raise ValueError(f"Run '{name}' does not exist in project '{project}'") + resumed = True + resolved_run_id = existing_run["id"] + elif resume == "allow": + resumed = existing_run is not None + if resumed: + resolved_run_id = existing_run["id"] + elif resume == "never": + resumed = False + else: + raise ValueError("resume must be one of: 'must', 'allow', or 'never'") + + initial_last_step = ( + _safe_get_last_step_for_init( + project, + name, + space_id, + server_base_url, + write_token_resolved, + resumed, + run_id=resolved_run_id, + remote_client=remote_client, + ) + if name is not None + else None + ) + + auto_log_cpu_detected = False + if auto_log_cpu is None: + auto_log_cpu_detected = cpu_available() + auto_log_cpu = auto_log_cpu_detected + + auto_log_gpu_detected = False + nvidia_available = False + apple_available = False + if auto_log_gpu is None: + nvidia_available = gpu_available() + apple_available = apple_gpu_available() + auto_log_gpu_detected = nvidia_available or apple_available + auto_log_gpu = auto_log_gpu_detected + + if project not in _projects_notified_auto_log_hw: + if nvidia_available: + print("* NVIDIA GPU detected, enabling automatic GPU metrics logging") + elif apple_available: + print( + "* Apple Silicon detected, enabling automatic GPU/system metrics logging" + ) + if auto_log_cpu_detected: + print("* psutil detected, enabling automatic CPU/system metrics logging") + if auto_log_gpu_detected or auto_log_cpu_detected: + _projects_notified_auto_log_hw.add(project) + + run = Run( + url=url, + project=project, + client=None, + name=name, + run_id=resolved_run_id, + group=group, + config=config, + space_id=space_id, + bucket_id=bucket_id, + server_base_url=server_base_url, + write_token=write_token_resolved, + existing_runs=existing_runs, + initial_last_step=initial_last_step, + auto_log_gpu=auto_log_gpu, + gpu_log_interval=gpu_log_interval, + auto_log_cpu=auto_log_cpu, + cpu_log_interval=cpu_log_interval, + webhook_url=webhook_url, + webhook_min_level=webhook_min_level, + ) + + if space_id is not None: + try: + SQLiteStorage.set_project_metadata(project, "space_id", space_id) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not persist Space metadata for project '{project}': {e}. Logging will continue." + ) + try: + if SQLiteStorage.has_pending_data(project): + run._has_local_buffer = True + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not inspect pending buffered data for project '{project}': {e}. Logging will continue." + ) + + global _atexit_registered + if not _atexit_registered: + atexit.register(_cleanup_current_run) + _atexit_registered = True + + if resumed: + print(f"* Resumed existing run: {run.name}") + else: + print(f"* Created new run: {run.name}") + + context_vars.current_run.set(run) + globals()["config"] = run.config + + if space_id is not None or server_url is None: + try: + from trackio import logbook as _logbook # noqa: PLC0415 + + _logbook.auto_note_dashboard(project, space_id=space_id) + except Exception: + pass + + if _should_embed_local: + try: + show(project=project, open_browser=False, block_thread=False) + except Exception as e: + _emit_nonfatal_warning( + f"trackio.init() could not auto-launch the dashboard: {e}. Logging will continue." + ) + + return run + + +def log(metrics: dict, step: int | None = None) -> None: + """ + Logs metrics to the current run. + + Args: + metrics (`dict`): + A dictionary of metrics to log. + step (`int`, *optional*): + The step number. If not provided, the step will be incremented + automatically. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log().") + run.log( + metrics=metrics, + step=step, + ) + + +def log_system(metrics: dict) -> None: + """ + Logs system metrics (GPU, etc.) to the current run using timestamps instead of steps. + + Args: + metrics (`dict`): + A dictionary of system metrics to log. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_system().") + run.log_system(metrics=metrics) + + +def log_artifact( + artifact_or_path: Artifact | str | Path, + name: str | None = None, + type: str | None = None, + aliases: list[str] | None = None, +) -> Artifact: + """ + Logs an artifact as an output of the current run. + + Args: + artifact_or_path (`Artifact`, `str`, or `Path`): + The artifact to log (must have at least one file added via + `add_file` or `add_dir`), or a path to a file or directory to + log as a new artifact. + name (`str`, *optional*): + Artifact name when logging a path. Defaults to + `run--`. Must not be passed with an `Artifact`. + type (`str`, *optional*): + Artifact type when logging a path (e.g. `"model"`, `"dataset"`). + Defaults to `"unspecified"`. Must not be passed with an + `Artifact`. + aliases (`list[str]`, *optional*): + Aliases to rotate onto the resulting version, alongside `latest` + (assigned automatically whenever a new version is created). Your + aliases rotate onto the version even when identical content is + de-duplicated. + + Returns: + The logged `Artifact` instance, hydrated with `version`, `aliases`, + `size`, `manifest`, and `project` set. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_artifact().") + return run.log_artifact(artifact_or_path, name=name, type=type, aliases=aliases) + + +def use_artifact( + artifact_or_name: Artifact | str, + type: str | None = None, +) -> Artifact: + """ + Fetches an artifact and records it as an input to the current run. + + Args: + artifact_or_name (`Artifact` or `str`): + An already-logged `Artifact`, or an artifact name. A bare name + (`"my-model"`) resolves to `:latest`; you can also pin a version + (`"my-model:v3"`) or resolve an alias (`"my-model:prod"`). + type (`str`, *optional*): + If given, checked against the stored artifact type, raising if it + does not match. + + Returns: + The fetched `Artifact`, hydrated and ready to `download()`. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.use_artifact().") + return run.use_artifact(artifact_or_name, type=type) + + +def log_gpu(run: Run | None = None, device: int | None = None) -> dict: + """ + Log GPU metrics to the current or specified run as system metrics. + Automatically detects whether an NVIDIA or Apple GPU is available and calls + the appropriate logging method. + + Args: + run: Optional Run instance. If None, uses current run from context. + device: CUDA device index to collect metrics from (NVIDIA GPUs only). + If None, collects from all GPUs visible to this process. + This parameter is ignored for Apple GPUs. + + Returns: + dict: The GPU metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_gpu() + trackio.log_gpu(device=0) + ``` + """ + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_gpu().") + + if gpu_available(): + return _log_nvidia_gpu(run=run, device=device) + elif apple_gpu_available(): + return _log_apple_gpu(run=run) + else: + _emit_nonfatal_warning( + "No GPU detected. Install nvidia-ml-py for NVIDIA GPU support " + "or psutil for Apple Silicon support." + ) + return {} + + +def log_cpu(run: Run | None = None) -> dict: + """ + Log CPU, RAM, disk, network, and sensor metrics to the current or specified run + as system metrics. + + Args: + run: Optional Run instance. If None, uses current run from context. + + Returns: + dict: The CPU and system metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_cpu() + ``` + """ + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_cpu().") + + return _log_cpu(run=run) + + +def finish(): + """ + Finishes the current run. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.finish().") + try: + run.finish() + finally: + context_vars.current_run.set(None) + + +def alert( + title: str, + text: str | None = None, + level: AlertLevel = AlertLevel.WARN, + webhook_url: str | None = None, +) -> None: + """ + Fires an alert immediately on the current run. The alert is printed to the + terminal, stored in the database, and displayed in the dashboard. If a + webhook URL is configured (via `trackio.init()`, the `TRACKIO_WEBHOOK_URL` + environment variable, or the `webhook_url` parameter here), the alert is + also POSTed to that URL. + + Args: + title (`str`): + A short title for the alert. + text (`str`, *optional*): + A longer description with details about the alert. + level (`AlertLevel`, *optional*, defaults to `AlertLevel.WARN`): + The severity level. One of `AlertLevel.INFO`, `AlertLevel.WARN`, + or `AlertLevel.ERROR`. + webhook_url (`str`, *optional*): + A webhook URL to send this specific alert to. Overrides any + URL set in `trackio.init()` or the `TRACKIO_WEBHOOK_URL` + environment variable. Supports Slack and Discord webhook + URLs natively. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.alert().") + run.alert(title=title, text=text, level=level, webhook_url=webhook_url) + + +def delete_project(project: str, force: bool = False) -> bool: + """ + Deletes a project by removing its local SQLite database. + + Args: + project (`str`): + The name of the project to delete. + force (`bool`, *optional*, defaults to `False`): + If `True`, deletes the project without prompting for confirmation. + If `False`, prompts the user to confirm before deleting. + + Returns: + `bool`: `True` if the project was deleted, `False` otherwise. + """ + db_path = SQLiteStorage.get_project_db_path(project) + + if not db_path.exists(): + print(f"* Project '{project}' does not exist.") + return False + + if not force: + response = input( + f"Are you sure you want to delete project '{project}'? " + f"This will permanently delete all runs and metrics. (y/N): " + ) + if response.lower() not in ["y", "yes"]: + print("* Deletion cancelled.") + return False + + try: + db_path.unlink() + + for suffix in ("-wal", "-shm"): + sidecar = Path(str(db_path) + suffix) + if sidecar.exists(): + sidecar.unlink() + + for parquet_path in SQLiteStorage._project_parquet_paths(db_path): + if parquet_path.exists(): + parquet_path.unlink() + + for asset_dir in ( + utils.project_artifacts_dir(project), + utils.project_media_dir(project), + ): + if asset_dir.exists(): + shutil.rmtree(asset_dir, ignore_errors=True) + + print(f"* Project '{project}' has been deleted.") + return True + except Exception as e: + print(f"* Error deleting project '{project}': {e}") + return False + + +def save( + glob_str: str | Path, + project: str | None = None, +) -> str: + """ + Saves files to a project (not linked to a specific run). If Trackio is running + locally, the file(s) will be copied to the project's files directory. If Trackio is + running in a Space, the file(s) will be uploaded to the Space's files directory. + + Args: + glob_str (`str` or `Path`): + The file path or glob pattern to save. Can be a single file or a pattern + matching multiple files (e.g., `"*.py"`, `"models/**/*.pth"`). + project (`str`, *optional*): + The name of the project to save files to. If not provided, uses the current + project from `trackio.init()`. If no project is initialized, raises an + error. + + Returns: + `str`: The path where the file(s) were saved (project's files directory). + + Example: + ```python + import trackio + + trackio.init(project="my-project") + trackio.save("config.yaml") + trackio.save("models/*.pth") + ``` + """ + if project is None: + project = context_vars.current_project.get() + if project is None: + raise RuntimeError( + "No project specified. Either call trackio.init() first or provide a " + "project parameter to trackio.save()." + ) + + glob_str = Path(glob_str) + base_path = Path.cwd().resolve() + + matched_files = [] + if glob_str.is_file(): + matched_files = [glob_str.resolve()] + else: + pattern = str(glob_str) + if not glob_str.is_absolute(): + pattern = str((Path.cwd() / glob_str).resolve()) + matched_files = [ + Path(f).resolve() + for f in glob.glob(pattern, recursive=True) + if Path(f).is_file() + ] + + if not matched_files: + raise ValueError(f"No files found matching pattern: {glob_str}") + + current_run = context_vars.current_run.get() + is_local = ( + current_run._is_local + if current_run is not None + else ( + context_vars.current_space_id.get() is None + and context_vars.current_server.get() is None + ) + ) + + if is_local: + for file_path in matched_files: + try: + relative_to_base = file_path.relative_to(base_path) + except ValueError: + relative_to_base = Path(file_path.name) + + if current_run is not None: + current_run._queue_upload( + file_path, + step=None, + relative_path=str(relative_to_base.parent), + use_run_name=False, + ) + else: + media_path = get_project_media_path( + project=project, + run=None, + step=None, + relative_path=str(relative_to_base), + ) + shutil.copy(str(file_path), str(media_path)) + else: + url = context_vars.current_server.get() + + upload_entries = [] + for file_path in matched_files: + try: + relative_to_base = file_path.relative_to(base_path) + except ValueError: + relative_to_base = Path(file_path.name) + + if current_run is not None: + current_run._queue_upload( + file_path, + step=None, + relative_path=str(relative_to_base.parent), + use_run_name=False, + ) + else: + upload_entry: UploadEntry = { + "project": project, + "run": None, + "step": None, + "relative_path": str(relative_to_base), + "uploaded_file": handle_file(file_path), + } + upload_entries.append(upload_entry) + + if upload_entries: + if url is None: + raise RuntimeError( + "No server available. Call trackio.init() before trackio.save() to start the server." + ) + + try: + wt = context_vars.current_server_write_token.get() + if wt is not None: + client = RemoteClient( + url, + hf_token=None, + write_token=wt, + httpx_kwargs={"timeout": 90}, + ) + else: + client = RemoteClient( + url, + hf_token=huggingface_hub.utils.get_token(), + httpx_kwargs={"timeout": 90}, + ) + client.predict( + api_name="/bulk_upload_media", + uploads=upload_entries, + hf_token=huggingface_hub.utils.get_token() if wt is None else None, + ) + except Exception as e: + _emit_nonfatal_warning( + f"Failed to upload files: {e}. " + "Files may not be available in the dashboard." + ) + + return str(utils.project_media_dir(project) / "files") + + +def show( + project: str | None = None, + *, + theme: Any = None, + mcp_server: bool | None = None, + footer: bool = True, + color_palette: list[str] | None = None, + open_browser: bool = True, + block_thread: bool | None = None, + host: str | None = None, + share: bool | None = None, + server_port: int | None = None, + frontend_dir: str | Path | None = None, +): + """ + Launches the Trackio dashboard. + + Args: + project (`str`, *optional*): + The name of the project whose runs to show. If not provided, all projects + will be shown and the user can select one. + theme (`Any`, *optional*): + Ignored. Kept for backward compatibility; Trackio no longer uses Gradio themes. + mcp_server (`bool`, *optional*): + If `True`, the dashboard exposes an MCP server at `/mcp` when the optional + `trackio[mcp]` dependency is installed. If `None` (default), the + `GRADIO_MCP_SERVER` environment variable is used (e.g. on Spaces). + footer (`bool`, *optional*, defaults to `True`): + Whether to include `footer=false` in the write-token URL when `False`. + This can also be controlled via the `footer` query parameter in the URL. + color_palette (`list[str]`, *optional*): + A list of hex color codes to use for plot lines. If not provided, the + `TRACKIO_COLOR_PALETTE` environment variable will be used (comma-separated + hex codes), or if that is not set, the default color palette will be used. + Example: `['#FF0000', '#00FF00', '#0000FF']` + open_browser (`bool`, *optional*, defaults to `True`): + If `True` and not in a notebook, a new browser tab will be opened with the + dashboard. If `False`, the browser will not be opened. + block_thread (`bool`, *optional*): + If `True`, the main thread will be blocked until the dashboard is closed. + If `None` (default behavior), then the main thread will not be blocked if the + dashboard is launched in a notebook, otherwise the main thread will be blocked. + host (`str`, *optional*): + The host to bind the server to. If not provided, defaults to `'127.0.0.1'` + (localhost only). Set to `'0.0.0.0'` to allow remote access. + share (`bool`, *optional*): + If `True`, creates a temporary public URL (Gradio-compatible tunnel). On Colab + or hosted notebooks, defaults to `True` unless overridden. + server_port (`int`, *optional*): + Port to bind. If not set, scans from `GRADIO_SERVER_PORT` (default 7860). + frontend_dir (`str | Path`, *optional*): + Directory containing a custom static frontend. Must contain `index.html`. + If not provided, Trackio checks `TRACKIO_FRONTEND_DIR`, then the persistent + Trackio config, then the bundled frontend. If an explicit `frontend_dir` + points to a missing or empty directory, Trackio copies in the starter + template and serves that directory. + + Returns: + `app`: The dashboard handle (`.close()` stops the server). + `url`: The local URL of the dashboard. + `share_url`: The public share URL, if any. + `full_url`: The full URL including the write token (share URL when sharing, else local). + """ + if theme is not None and theme != "default": + warnings.warn( + "The theme argument is ignored; Trackio no longer depends on Gradio themes.", + UserWarning, + stacklevel=2, + ) + + if color_palette is not None: + os.environ["TRACKIO_COLOR_PALETTE"] = ",".join(color_palette) + + _mcp_server = ( + mcp_server + if mcp_server is not None + else os.environ.get("GRADIO_MCP_SERVER", "False") == "True" + ) + + resolved_frontend = resolve_frontend_dir(frontend_dir, announce=True) + starlette_app, wt = build_starlette_app_only( + mcp_server=_mcp_server, + frontend_dir=str(resolved_frontend.path), + ) + local_url, share_url, _local_api_url, uv_server = launch_trackio_dashboard( + starlette_app, + server_name=host, + server_port=server_port, + share=share, + mcp_server=_mcp_server, + quiet=True, + ) + server = TrackioDashboardApp(starlette_app, uv_server, wt) + + base_root = (share_url or local_url).rstrip("/") + base_url = base_root + "/" + dashboard_url = base_url + if project: + dashboard_url += f"?project={project}" + full_url = utils.get_full_url( + base_root, + project=project, + write_token=wt, + footer=footer, + ) + + if not utils.is_in_notebook(): + print(f"\033[1m\033[38;5;208m* Trackio UI launched at: {dashboard_url}\033[0m") + utils.print_write_token_instructions(full_url) + if open_browser: + webbrowser.open(full_url) + block_thread = block_thread if block_thread is not None else True + else: + utils.embed_url_in_notebook(full_url) + block_thread = block_thread if block_thread is not None else False + + if block_thread: + utils.block_main_thread_until_keyboard_interrupt() + return _TupleNoPrint((server, local_url, share_url, full_url)) diff --git a/trackio/_vendor/__init__.py b/trackio/_vendor/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/trackio/_vendor/gradio_exceptions.py b/trackio/_vendor/gradio_exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..34696b9e534896b66557bab78a2d78709c07e351 --- /dev/null +++ b/trackio/_vendor/gradio_exceptions.py @@ -0,0 +1,6 @@ +class ChecksumMismatchError(Exception): + pass + + +class ShareCertificateWriteError(Exception): + pass diff --git a/trackio/_vendor/networking.py b/trackio/_vendor/networking.py new file mode 100644 index 0000000000000000000000000000000000000000..04ef35763f89eb813059ea6fc91a7316ecd2f2de --- /dev/null +++ b/trackio/_vendor/networking.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +import os +import time +import warnings +from pathlib import Path +from urllib.parse import urlparse, urlunparse + +import httpx + +from trackio._vendor.gradio_exceptions import ShareCertificateWriteError +from trackio._vendor.tunneling import CERTIFICATE_PATH, Tunnel + +GRADIO_API_SERVER = "https://api.gradio.app/v3/tunnel-request" +GRADIO_SHARE_SERVER_ADDRESS = os.getenv("GRADIO_SHARE_SERVER_ADDRESS") + + +def setup_tunnel( + local_host: str, + local_port: int, + share_token: str, + share_server_address: str | None, + share_server_tls_certificate: str | None, +) -> str: + share_server_address = ( + GRADIO_SHARE_SERVER_ADDRESS + if share_server_address is None + else share_server_address + ) + if share_server_address is None: + try: + response = httpx.get(GRADIO_API_SERVER, timeout=30) + payload = response.json()[0] + remote_host, remote_port = payload["host"], int(payload["port"]) + certificate = payload["root_ca"] + except Exception as e: + raise RuntimeError( + "Could not get share link from Gradio API Server." + ) from e + try: + Path(CERTIFICATE_PATH).parent.mkdir(parents=True, exist_ok=True) + with open(CERTIFICATE_PATH, "w") as f: + f.write(certificate) + except Exception as e: + raise ShareCertificateWriteError( + f"{e}. This can happen if the current working directory is read-only." + ) from e + share_server_tls_certificate = CERTIFICATE_PATH + + else: + remote_host, remote_port = share_server_address.split(":") + remote_port = int(remote_port) + tunnel = Tunnel( + remote_host, + remote_port, + local_host, + local_port, + share_token, + share_server_tls_certificate, + ) + address = tunnel.start_tunnel() + return address + + +def url_ok(url: str) -> bool: + try: + for _ in range(5): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + r = httpx.head(url, timeout=3, verify=False) + if r.status_code in (200, 401, 302, 303, 307): + return True + time.sleep(0.500) + except (ConnectionError, httpx.ConnectError, httpx.TimeoutException): + return False + return False + + +def normalize_share_url(share_url: str, share_server_protocol: str) -> str: + parsed_url = urlparse(share_url) + return urlunparse((share_server_protocol,) + parsed_url[1:]) diff --git a/trackio/_vendor/tunneling.py b/trackio/_vendor/tunneling.py new file mode 100644 index 0000000000000000000000000000000000000000..6bd6258ed043ba70b07bb1e928bf009864206000 --- /dev/null +++ b/trackio/_vendor/tunneling.py @@ -0,0 +1,191 @@ +import atexit +import hashlib +import os +import platform +import re +import stat +import subprocess +import sys +import time +from pathlib import Path + +import httpx +from huggingface_hub.constants import HF_HOME + +from trackio._vendor.gradio_exceptions import ChecksumMismatchError + +VERSION = "0.3" +CURRENT_TUNNELS: list["Tunnel"] = [] + +machine = platform.machine() +if machine == "x86_64": + machine = "amd64" +elif machine == "aarch64": + machine = "arm64" + +BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}" +EXTENSION = ".exe" if os.name == "nt" else "" +BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}" + +CHECKSUMS = { + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_windows_amd64.exe": "14bc0ea470be5d67d79a07412bd21de8a0a179c6ac1116d7764f68e942dc9ceb", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_amd64": "c791d1f047b41ff5885772fc4bf20b797c6059bbd82abb9e31de15e55d6a57c4", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_arm64": "823ced25104de6dc3c9f4798dbb43f20e681207279e6ab89c40e2176ccbf70cd", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_darwin_amd64": "930f8face3365810ce16689da81b7d1941fda4466225a7bbcbced9a2916a6e15", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_darwin_arm64": "dfac50c690aca459ed5158fad8bfbe99f9282baf4166cf7c410a6673fbc1f327", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_arm": "4b563beb2e36c448cc688174e20b53af38dc1ff2b5e362d4ddd1401f2affbfb7", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_freebsd_386": "cb0a56c764ecf96dd54ed601d240c564f060ee4e58202d65ffca17c1a51ce19c", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_freebsd_amd64": "516d9e6903513869a011ddcd1ec206167ad1eb5dd6640d21057acc258edecbbb", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_386": "4c2f2a48cd71571498c0ac8a4d42a055f22cb7f14b4b5a2b0d584220fd60a283", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mips": "b309ecd594d4f0f7f33e556a80d4b67aef9319c00a8334648a618e56b23cb9e0", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mips64": "0372ef5505baa6f3b64c6295a86541b24b7b0dbe4ef28b344992e21f47624b7b", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_riscv64": "1658eed7e8c14ea76e1d95749d58441ce24147c3d559381832c725c29cfc3df3", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mipsle": "a2aaba16961d3372b79bd7a28976fcd0f0bbaebc2b50d5a7a71af2240747960f", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_windows_386.exe": "721b90550195a83e15f2176d8f85a48d5a25822757cb872e9723d4bccc4e5bb6", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mips64le": "796481edd609f31962b45cc0ab4c9798d040205ae3bf354ed1b72fb432d796b8", +} + +CHUNK_SIZE = 128 + +BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}" +BINARY_FOLDER = Path(HF_HOME) / "trackio" / "frpc" +BINARY_PATH = str(BINARY_FOLDER / BINARY_FILENAME) + +TUNNEL_TIMEOUT_SECONDS = 30 +TUNNEL_ERROR_MESSAGE = ( + "Could not create share URL. " + "Please check the appended log from frpc for more information:" +) + +CERTIFICATE_PATH = ".trackio/certificate.pem" + + +class Tunnel: + def __init__( + self, + remote_host: str, + remote_port: int, + local_host: str, + local_port: int, + share_token: str, + share_server_tls_certificate: str | None, + ): + self.proc = None + self.url = None + self.remote_host = remote_host + self.remote_port = remote_port + self.local_host = local_host + self.local_port = local_port + self.share_token = share_token + self.share_server_tls_certificate = share_server_tls_certificate + + @staticmethod + def download_binary(): + if not Path(BINARY_PATH).exists(): + Path(BINARY_FOLDER).mkdir(parents=True, exist_ok=True) + resp = httpx.get(BINARY_URL, timeout=30) + + if resp.status_code == 403: + raise OSError( + f"Cannot set up a share link as this platform is incompatible. Please " + f"create a GitHub issue with information about your platform: {platform.uname()}" + ) + + resp.raise_for_status() + + with open(BINARY_PATH, "wb") as file: + file.write(resp.content) + st = os.stat(BINARY_PATH) + os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC) + + if BINARY_URL in CHECKSUMS: + sha = hashlib.sha256() + with open(BINARY_PATH, "rb") as f: + for chunk in iter(lambda: f.read(CHUNK_SIZE * sha.block_size), b""): + sha.update(chunk) + calculated_hash = sha.hexdigest() + + if calculated_hash != CHECKSUMS[BINARY_URL]: + raise ChecksumMismatchError() + + def start_tunnel(self) -> str: + self.download_binary() + self.url = self._start_tunnel(BINARY_PATH) + return self.url + + def kill(self): + if self.proc is not None: + print(f"Killing tunnel {self.local_host}:{self.local_port} <> {self.url}") + self.proc.terminate() + self.proc = None + + def _start_tunnel(self, binary: str) -> str: + CURRENT_TUNNELS.append(self) + command = [ + binary, + "http", + "-n", + self.share_token, + "-l", + str(self.local_port), + "-i", + self.local_host, + "--uc", + "--sd", + "random", + "--ue", + "--server_addr", + f"{self.remote_host}:{self.remote_port}", + "--disable_log_color", + ] + if self.share_server_tls_certificate is not None: + command.extend( + [ + "--tls_enable", + "--tls_trusted_ca_file", + self.share_server_tls_certificate, + ] + ) + self.proc = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + atexit.register(self.kill) + return self._read_url_from_tunnel_stream() + + def _read_url_from_tunnel_stream(self) -> str: + start_timestamp = time.time() + + log = [] + url = "" + + def _raise_tunnel_error(): + log_text = "\n".join(log) + print(log_text, file=sys.stderr) + raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}") + + while url == "": + if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS: + _raise_tunnel_error() + + assert self.proc is not None # noqa: S101 + if self.proc.stdout is None: + continue + + line = self.proc.stdout.readline() + line = line.decode("utf-8") + + if line == "": + continue + + log.append(line.strip()) + + if "start proxy success" in line: + result = re.search("start proxy success: (.+)\n", line) + if result is None: + _raise_tunnel_error() + else: + url = result.group(1) + elif "login to server failed" in line: + _raise_tunnel_error() + + return url diff --git a/trackio/alerts.py b/trackio/alerts.py new file mode 100644 index 0000000000000000000000000000000000000000..646b9786eacb91fca5270189a78280293e045fc0 --- /dev/null +++ b/trackio/alerts.py @@ -0,0 +1,184 @@ +import json +import logging +import ssl +import urllib.request +from enum import Enum + +try: + import certifi + + _SSL_CONTEXT = ssl.create_default_context(cafile=certifi.where()) +except ImportError: + _SSL_CONTEXT = None + +logger = logging.getLogger(__name__) + + +class AlertLevel(str, Enum): + INFO = "info" + WARN = "warn" + ERROR = "error" + + +ALERT_LEVEL_ORDER = { + AlertLevel.INFO: 0, + AlertLevel.WARN: 1, + AlertLevel.ERROR: 2, +} + +ALERT_COLORS = { + AlertLevel.INFO: "\033[94m", + AlertLevel.WARN: "\033[93m", + AlertLevel.ERROR: "\033[91m", +} +RESET_COLOR = "\033[0m" + +LEVEL_EMOJI = { + AlertLevel.INFO: "ℹ️", + AlertLevel.WARN: "⚠️", + AlertLevel.ERROR: "🚨", +} + + +def format_alert_terminal( + level: AlertLevel, title: str, text: str | None, step: int | None +) -> str: + color = ALERT_COLORS.get(level, "") + step_str = f" (step {step})" if step is not None else "" + if text: + return f"{color}[TRACKIO {level.value.upper()}]{RESET_COLOR} {title}: {text}{step_str}" + return f"{color}[TRACKIO {level.value.upper()}]{RESET_COLOR} {title}{step_str}" + + +def _is_slack_url(url: str) -> bool: + return "hooks.slack.com" in url + + +def _is_discord_url(url: str) -> bool: + return "discord.com/api/webhooks" in url or "discordapp.com/api/webhooks" in url + + +def _build_slack_payload( + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, +) -> dict: + emoji = LEVEL_EMOJI.get(level, "") + step_str = f" • Step {step}" if step is not None else "" + header = f"{emoji} *[{level.value.upper()}] {title}*" + context = f"Project: {project} • Run: {run}{step_str}" + blocks = [ + {"type": "section", "text": {"type": "mrkdwn", "text": header}}, + ] + if text: + blocks.append({"type": "section", "text": {"type": "mrkdwn", "text": text}}) + blocks.append( + {"type": "context", "elements": [{"type": "mrkdwn", "text": context}]} + ) + return {"blocks": blocks} + + +def _build_discord_payload( + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, +) -> dict: + color_map = { + AlertLevel.INFO: 3447003, + AlertLevel.WARN: 16776960, + AlertLevel.ERROR: 15158332, + } + emoji = LEVEL_EMOJI.get(level, "") + step_str = f" • Step {step}" if step is not None else "" + embed = { + "title": f"{emoji} [{level.value.upper()}] {title}", + "color": color_map.get(level, 0), + "footer": {"text": f"Project: {project} • Run: {run}{step_str}"}, + } + if text: + embed["description"] = text + return {"embeds": [embed]} + + +def _build_generic_payload( + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, + timestamp: str | None, +) -> dict: + return { + "level": level.value, + "title": title, + "text": text, + "project": project, + "run": run, + "step": step, + "timestamp": timestamp, + } + + +def parse_alert_level(level: AlertLevel | str) -> AlertLevel: + if isinstance(level, AlertLevel): + return level + normalized = level.lower().strip() + try: + return AlertLevel(normalized) + except ValueError as e: + allowed = ", ".join(lvl.value for lvl in AlertLevel) + raise ValueError( + f"Invalid alert level '{level}'. Expected one of: {allowed}." + ) from e + + +def resolve_webhook_min_level( + webhook_min_level: AlertLevel | str | None, +) -> AlertLevel | None: + if webhook_min_level is None: + return None + return parse_alert_level(webhook_min_level) + + +def should_send_webhook( + level: AlertLevel, webhook_min_level: AlertLevel | None +) -> bool: + if webhook_min_level is None: + return True + return ALERT_LEVEL_ORDER[level] >= ALERT_LEVEL_ORDER[webhook_min_level] + + +def send_webhook( + url: str, + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, + timestamp: str | None = None, +) -> None: + if _is_slack_url(url): + payload = _build_slack_payload(level, title, text, project, run, step) + elif _is_discord_url(url): + payload = _build_discord_payload(level, title, text, project, run, step) + else: + payload = _build_generic_payload( + level, title, text, project, run, step, timestamp + ) + + data = json.dumps(payload).encode("utf-8") + req = urllib.request.Request( + url, data=data, headers={"Content-Type": "application/json"} + ) + try: + urllib.request.urlopen(req, timeout=10, context=_SSL_CONTEXT) + except Exception as e: + logger.warning(f"Failed to send webhook to {url}: {e}") diff --git a/trackio/api.py b/trackio/api.py new file mode 100644 index 0000000000000000000000000000000000000000..ef81ce388aec14dddd1a5b43959c728cacf0ac1c --- /dev/null +++ b/trackio/api.py @@ -0,0 +1,99 @@ +from typing import Iterator + +from trackio.sqlite_storage import SQLiteStorage + + +class Run: + def __init__(self, project: str, name: str, run_id: str | None = None): + self.project = project + self.name = name + self._id = run_id or name + self._config = None + + @property + def id(self) -> str: + return self._id + + @property + def config(self) -> dict | None: + if self._config is None: + self._config = SQLiteStorage.get_run_config( + self.project, self.name, run_id=self.id + ) + return self._config + + def alerts(self, level: str | None = None, since: str | None = None) -> list[dict]: + return SQLiteStorage.get_alerts( + self.project, run_name=self.name, run_id=self.id, level=level, since=since + ) + + def delete(self) -> bool: + return SQLiteStorage.delete_run(self.project, self.name, run_id=self.id) + + def move(self, new_project: str) -> bool: + success = SQLiteStorage.move_run( + self.project, self.name, new_project, run_id=self.id + ) + if success: + self.project = new_project + return success + + def rename(self, new_name: str) -> "Run": + SQLiteStorage.rename_run(self.project, self.name, new_name, run_id=self.id) + self.name = new_name + return self + + def __repr__(self) -> str: + return f"" + + +class Runs: + def __init__(self, project: str): + self.project = project + self._runs = None + + def _load_runs(self): + if self._runs is None: + records = SQLiteStorage.get_run_records(self.project) + self._runs = [ + Run( + self.project, + str(record["name"]), + run_id=str(record["id"]) if record["id"] is not None else None, + ) + for record in records + ] + + def __iter__(self) -> Iterator[Run]: + self._load_runs() + return iter(self._runs) + + def __getitem__(self, index: int) -> Run: + self._load_runs() + return self._runs[index] + + def __len__(self) -> int: + self._load_runs() + return len(self._runs) + + def __repr__(self) -> str: + self._load_runs() + return f"" + + +class Api: + def runs(self, project: str) -> Runs: + if not SQLiteStorage.get_project_db_path(project).exists(): + raise ValueError(f"Project '{project}' does not exist") + return Runs(project) + + def alerts( + self, + project: str, + run: str | None = None, + level: str | None = None, + since: str | None = None, + ) -> list[dict]: + if not SQLiteStorage.get_project_db_path(project).exists(): + raise ValueError(f"Project '{project}' does not exist") + return SQLiteStorage.get_alerts(project, run_name=run, level=level, since=since) diff --git a/trackio/apple_gpu.py b/trackio/apple_gpu.py new file mode 100644 index 0000000000000000000000000000000000000000..3373bf6ddc8dcde19b2d6b15e7ce46e86df00dc1 --- /dev/null +++ b/trackio/apple_gpu.py @@ -0,0 +1,206 @@ +import platform +import subprocess +import sys +import threading +import warnings +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from trackio.run import Run + +psutil: Any = None +PSUTIL_AVAILABLE = False +_monitor_lock = threading.Lock() + + +def _ensure_psutil(): + global PSUTIL_AVAILABLE, psutil + if PSUTIL_AVAILABLE: + return psutil + try: + import psutil as _psutil + + psutil = _psutil + PSUTIL_AVAILABLE = True + return psutil + except ImportError: + raise ImportError( + "psutil is required for Apple Silicon monitoring. " + "Install it with: pip install psutil" + ) + + +def is_apple_silicon() -> bool: + """Check if running on Apple Silicon (M1/M2/M3/M4).""" + if platform.system() != "Darwin": + return False + + try: + result = subprocess.run( + ["sysctl", "-n", "machdep.cpu.brand_string"], + capture_output=True, + text=True, + timeout=1, + ) + cpu_brand = result.stdout.strip() + return "Apple" in cpu_brand + except Exception: + return False + + +def get_gpu_info() -> dict[str, Any]: + """Get Apple GPU information using ioreg.""" + try: + result = subprocess.run( + ["ioreg", "-r", "-d", "1", "-w", "0", "-c", "IOAccelerator"], + capture_output=True, + text=True, + timeout=2, + ) + + if result.returncode == 0 and result.stdout: + lines = result.stdout.strip().split("\n") + for line in lines: + if "IOAccelerator" in line and "class" in line: + return {"detected": True, "type": "Apple GPU"} + else: + print("Error collecting Apple GPU info. ioreg stdout was:", file=sys.stderr) + print(result.stdout, file=sys.stderr) + print("ioreg stderr was:", file=sys.stderr) + print(result.stderr, file=sys.stderr) + + result = subprocess.run( + ["system_profiler", "SPDisplaysDataType"], + capture_output=True, + text=True, + timeout=3, + ) + + if result.returncode == 0 and "Apple" in result.stdout: + for line in result.stdout.split("\n"): + if "Chipset Model:" in line: + model = line.split(":")[-1].strip() + return {"detected": True, "type": model} + + except Exception: + pass + + return {"detected": False} + + +def apple_gpu_available() -> bool: + """ + Check if Apple GPU monitoring is available. + + Returns True if running on Apple Silicon (M-series chips) and psutil is installed. + """ + try: + _ensure_psutil() + return is_apple_silicon() + except ImportError: + return False + except Exception: + return False + + +def collect_apple_metrics(include_cpu_metrics: bool = True) -> dict: + """ + Collect system metrics for Apple Silicon. + + Returns: + Dictionary of system metrics including CPU, memory, and GPU info. + """ + metrics = {} + + if include_cpu_metrics: + from trackio.cpu import collect_cpu_metrics + + metrics.update(collect_cpu_metrics(include_static=True)) + + gpu_info = get_gpu_info() + if gpu_info.get("detected"): + metrics["gpu/detected"] = 1 + + return metrics + + +class AppleGpuMonitor: + def __init__( + self, run: "Run", interval: float = 10.0, include_cpu_metrics: bool = True + ): + self._run = run + self._interval = interval + self._include_cpu_metrics = include_cpu_metrics + self._stop_flag = threading.Event() + self._thread: "threading.Thread | None" = None + + def start(self): + if not is_apple_silicon(): + warnings.warn( + "auto_log_gpu=True but not running on Apple Silicon. " + "Apple GPU logging disabled." + ) + return + + if not PSUTIL_AVAILABLE: + try: + _ensure_psutil() + except ImportError: + warnings.warn( + "auto_log_gpu=True but psutil not installed. " + "Install with: pip install psutil" + ) + return + + self._thread = threading.Thread(target=self._monitor_loop, daemon=True) + self._thread.start() + + def stop(self): + self._stop_flag.set() + if self._thread is not None: + self._thread.join(timeout=2.0) + + def _monitor_loop(self): + while not self._stop_flag.is_set(): + try: + metrics = collect_apple_metrics( + include_cpu_metrics=self._include_cpu_metrics + ) + if metrics: + self._run.log_system(metrics) + except Exception: + pass + + self._stop_flag.wait(timeout=self._interval) + + +def log_apple_gpu(run: "Run | None" = None) -> dict: + """ + Log Apple Silicon system metrics to the current or specified run. + + Args: + run: Optional Run instance. If None, uses current run from context. + + Returns: + dict: The system metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_apple_gpu() + ``` + """ + from trackio import context_vars + + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_apple_gpu().") + + metrics = collect_apple_metrics() + if metrics: + run.log_system(metrics) + return metrics diff --git a/trackio/artifact.py b/trackio/artifact.py new file mode 100644 index 0000000000000000000000000000000000000000..c764a34520e3eb038e544eee69e0e01c6f77e61c --- /dev/null +++ b/trackio/artifact.py @@ -0,0 +1,552 @@ +import os +import shutil +from pathlib import Path + +import httpx +from huggingface_hub.utils import get_token + +from trackio import cas, references, utils +from trackio.remote_client import _merge_client_headers, _resolve_src_url +from trackio.typehints import ETag, Manifest, ManifestEntry, Sha256Digest, URIStr + + +def _materialize(blob: Path, dst: Path, size: int) -> None: + """Copy `blob` to `dst` unless `dst` already matches the blob's size and + mtime. + """ + dst.parent.mkdir(parents=True, exist_ok=True) + blob_stat = blob.stat() + if dst.is_file(): + dst_stat = dst.stat() + if dst_stat.st_size == size and dst_stat.st_mtime_ns == blob_stat.st_mtime_ns: + return + partial = dst.parent / cas.partial_blob_name(dst.name) + try: + shutil.copyfile(blob, partial) + os.utime(partial, ns=(blob_stat.st_atime_ns, blob_stat.st_mtime_ns)) + os.replace(partial, dst) + except Exception: + partial.unlink(missing_ok=True) + raise + + +def _fetch_blob_from_remote( + remote_source: dict, + project: str, + digest: Sha256Digest, + target_path: Path, +) -> None: + space_id = remote_source.get("space_id") + src = space_id or remote_source.get("server_base_url") + if not src: + raise RuntimeError( + "Artifact has _remote_source set but neither space_id nor " + "server_base_url is populated." + ) + base_url = _resolve_src_url(src).rstrip("/") + url = f"{base_url}/artifact_blob/{utils.canonical_project_name(project)}/{digest}" + headers = _merge_client_headers( + get_token() if space_id else None, + remote_source.get("write_token"), + ) + with httpx.stream( + "GET", + url, + headers=headers, + timeout=httpx.Timeout(connect=10.0, read=300.0, write=10.0, pool=10.0), + ) as response: + if response.status_code == 404: + raise FileNotFoundError( + f"Artifact blob {digest} not available on remote at {url}" + ) + response.raise_for_status() + cas.stage_blob_from_chunks( + response.iter_bytes(), + claimed_digest=digest, + target_path=target_path, + ) + + +def _materialize_reference( + uri: str, scheme: str, dest: Path, digest: Sha256Digest | ETag | URIStr +) -> None: + """Fetch the object at `uri` into `dest`, idempotently and atomically. + + If `dest` already exists it is left untouched and nothing is fetched: + reference digests are opaque, so a file already present is assumed current + (mirroring the size/mtime idempotence of `_materialize`), letting a repeated + `download()` skip references already on disk. + + Otherwise, when a real checksum was recorded, the source is re-probed and + compared. When the digest doesn't exist, or when it cannot be re-probed, + the comparison is skipped and the artifact is still materialized. + """ + if dest.is_file(): + return + if len(digest) > 0 and digest != uri: + try: + resolved = references.resolve_reference( + uri, scheme, checksum=True, max_objects=1 + )[0] + except Exception: + resolved = None + current_digest = resolved.digest if resolved is not None else None + if current_digest is not None and current_digest != digest: + utils._emit_nonfatal_warning( + f"Reference {uri!r} may have changed since it was logged " + f"(recorded digest {digest}, current {current_digest})." + ) + dest.parent.mkdir(parents=True, exist_ok=True) + partial = dest.parent / cas.partial_blob_name(dest.name) + try: + references.fetch_reference(uri, scheme, partial) + os.replace(partial, dest) + except Exception: + partial.unlink(missing_ok=True) + raise + + +class Artifact: + """ + A versioned, named bundle of files and references attached to a project. + + Construct an `Artifact`, add files to it with `add_file` / `add_dir` + (bytes staged into content-addressed storage) or `add_reference` (an + external URI recorded without copying any bytes), then persist it with + `trackio.log_artifact`. Logging freezes the artifact and populates its + read-only `version`, `aliases`, `size`, and `manifest`. + + Args: + name (`str`): + Artifact name, unique within the project. Must match + `^[A-Za-z0-9._-]+$` (letters, digits, dot, underscore, hyphen). + type (`str`): + Free-form category such as `"model"` or `"dataset"`, used to group + artifacts. + description (`str`, *optional*): + Human-readable description of the artifact. + metadata (`dict`, *optional*): + Arbitrary JSON-serializable metadata stored alongside the version. + """ + + def __init__( + self, + name: str, + type: str, + description: str | None = None, + metadata: dict | None = None, + ): + cas.validate_artifact_name(name) + self._name = name + self._type = type + self._description = description + self._metadata: dict = dict(metadata) if metadata else {} + self._pending_files: list[tuple[Path, str]] = [] + self._pending_references: list[ + tuple[str, str, Sha256Digest | ETag | URIStr, int] + ] = [] + self._logged = False + self._version: int | None = None + self._aliases: tuple[str, ...] = () + self._size: int | None = None + self._manifest: Manifest | None = None + self._manifest_digest: Sha256Digest | None = None + self._project: str | None = None + self._remote_source: dict | None = None + + @property + def name(self) -> str: + """Artifact name, unique within its project.""" + return self._name + + @property + def type(self) -> str: + """Free-form category such as `"model"` or `"dataset"`.""" + return self._type + + @property + def description(self) -> str | None: + """Human-readable description, or None if unset.""" + return self._description + + @description.setter + def description(self, value: str | None) -> None: + self._description = value + + @property + def metadata(self) -> dict: + """Live, mutable metadata dict; assignments like `art.metadata["k"] = v` + made before logging are preserved.""" + return self._metadata + + @metadata.setter + def metadata(self, value: dict | None) -> None: + self._metadata = dict(value) if value else {} + + @property + def version(self) -> str | None: + """Version string in `"v"` form (e.g. `"v3"`), or None if the + artifact has not been logged or fetched yet.""" + return None if self._version is None else f"v{self._version}" + + @property + def aliases(self) -> tuple[str, ...]: + """Aliases pointing at this version, e.g. `("latest", "prod")`.""" + return self._aliases + + @property + def size(self) -> int | None: + """Total size in bytes of the artifact's files plus any referenced data + whose size is known, or None if not yet logged.""" + return self._size + + @property + def manifest(self) -> Manifest | None: + """List of manifest entries describing the artifact's contents, or None + if not yet logged or fetched. File entries carry `path`, `digest`, and + `size`; reference entries carry `path`, `ref` (a URI), `size`, and a + `digest` — a sha256 for local/LFS references, the provider's opaque ETag + for HTTP or object-store references, or the URI itself when no checksum + is available. Returns a fresh copy on each access.""" + return None if self._manifest is None else [dict(e) for e in self._manifest] + + @property + def manifest_digest(self) -> Sha256Digest | None: + """Digest over the manifest (file paths plus their content), used to + de-duplicate re-logged content; None until logged or fetched.""" + return self._manifest_digest + + @property + def digest(self) -> Sha256Digest | None: + """Alias of `manifest_digest`.""" + return self._manifest_digest + + @property + def qualified_name(self) -> str: + """`"/:v"` for a logged or fetched artifact.""" + if self._project is None or self._version is None: + raise RuntimeError( + "Artifact has no qualified name until it is logged or fetched." + ) + return f"{self._project}/{self._name}:v{self._version}" + + @property + def project(self) -> str | None: + """Project the artifact belongs to, or None until logged or fetched.""" + return self._project + + def wait(self, timeout: int | None = None) -> "Artifact": + """No-op: trackio logs artifacts synchronously, so the artifact is + already committed by the time `log_artifact` returns.""" + if not self._logged: + raise RuntimeError( + "Cannot wait on an Artifact that has not been logged; " + "call log_artifact first." + ) + return self + + def add_file(self, local_path: str | Path, name: str | None = None) -> None: + """Stage a single file for inclusion in the artifact. + + Args: + local_path (`str` or `Path`): + Path to an existing regular file to add. + name (`str`, *optional*): + Logical path the file is stored under inside the artifact. + Defaults to the file's basename. + """ + if self._logged: + raise RuntimeError( + "Cannot add files to an Artifact that has already been logged or fetched." + ) + src = Path(local_path).resolve() + if not src.is_file(): + raise ValueError(f"Not a regular file: {local_path}") + logical = cas.validate_logical_path(name if name is not None else src.name) + self._pending_files.append((src, logical)) + + def add_dir(self, local_dir: str | Path, name: str | None = None) -> None: + """Stage every regular file under a directory, recursively. + + Symlinks are skipped. + + Args: + local_dir (`str` or `Path`): + Path to an existing directory whose files are added. + name (`str`, *optional*): + Logical path prefix for the added files. Defaults to no prefix, + so files keep their paths relative to `local_dir`. + """ + if self._logged: + raise RuntimeError( + "Cannot add files to an Artifact that has already been logged or fetched." + ) + root = Path(local_dir).resolve() + if not root.is_dir(): + raise ValueError(f"Not a directory: {local_dir}") + prefix = cas.validate_logical_path(name.rstrip("/")) + "/" if name else "" + for dirpath, dirnames, filenames in os.walk(root, followlinks=False): + dirnames.sort() + for filename in sorted(filenames): + entry = Path(dirpath) / filename + if entry.is_symlink() or not entry.is_file(): + continue + rel = entry.relative_to(root).as_posix() + logical = cas.validate_logical_path(prefix + rel) + self._pending_files.append((entry, logical)) + + def add_reference( + self, + uri: str, + name: str | None = None, + checksum: bool = True, + max_objects: int | None = None, + ) -> None: + """Stage a reference to external data, without copying any bytes. + + Unlike `add_file`/`add_dir`, a reference records the data's URI (plus, + when available, a size and checksum) *without staging the bytes into + the content-addressed store*. This is how you version and track + lineage over large or already-durably-stored datasets that must not be + duplicated. + + A URI that denotes a directory (`file://`, `hf://`, or a prefix + expanded by a custom handler) is expanded into one entry per object, + capped by `max_objects`. Reference bytes are never uploaded to a Space + or bucket. + + The URI is stored verbatim in the artifact manifest, and manifests may + be synced to a shared Hugging Face Dataset — so a signed URI triggers a + warning for security reasons; please prefer the object's canonical + unsigned URI (e.g. `s3://bucket/key`). + + Args: + uri (`str`): + Location of the referenced data, percent-encoded (build local + URIs with `pathlib.Path.as_uri()`). `file://`, `http(s)://`, + and `hf://` are resolved and fetched natively; any other scheme + (`s3://`, `gs://`, Azure blob URLs, ...) requires a custom + `ReferenceHandler` registered via + `trackio.register_reference_handler` — see the artifacts + documentation for complete examples — and raises otherwise. + name (`str`, *optional*): + Logical path the reference is stored under. Defaults to the last + segment of `uri`; for an expanded prefix (ending with /) it is the + prefix under which each object's relative path is nested. + checksum (`bool`, *optional*, defaults to `True`): + When `True`, probes the source to derive its size and a + checksum (and to expand a directory/prefix): `file://` is + stream-hashed to a sha256, `hf://` uses its LFS sha256 or git + blob id, and `http(s)://` uses the server `ETag`. This may read + the filesystem or make network requests. When no checksum can + be obtained for a *remote* source (e.g. no ETag), the URI + itself is used as the `digest` and a warning is emitted. A + local `file://` path that does not exist instead raises. Pass + `checksum=False` to skip remote probing entirely. + max_objects (`int`, *optional*): + Cap on how many objects a directory/prefix expands into (default + 10,000); exceeding it raises. + """ + if self._logged: + raise RuntimeError( + "Cannot add references to an Artifact that has already been " + "logged or fetched." + ) + scheme, normalized = references.validate_reference_uri(uri) + if references.looks_signed(normalized): + utils._emit_nonfatal_warning( + f"Reference {uri!r} looks like a signed URL, and the full URI " + "(embedded credential included) is stored in the artifact " + "manifest, which may be synced to a shared HF Dataset. Prefer " + "the object's canonical unsigned URI (e.g. s3://bucket/key or " + "the URL without its signed query string)." + ) + cap = references.DEFAULT_MAX_OBJECTS if max_objects is None else max_objects + resolved = references.resolve_reference(normalized, scheme, checksum, cap) + if not resolved: + raise ValueError(f"Reference URI {uri!r} matched no objects.") + used_uri_fallback = False + name_prefix = f"{name.rstrip('/')}/" if name is not None else "" + for entry in resolved: + if entry.relkey is None: + logical = self._reference_logical_name(name, entry.uri, uri) + else: + logical = cas.validate_logical_path(name_prefix + entry.relkey) + ref_digest: Sha256Digest | ETag | URIStr | None = entry.digest + if ref_digest is None: + ref_digest = URIStr(entry.uri) + used_uri_fallback = True + ref_size = 0 if entry.size is None else entry.size + self._pending_references.append((logical, entry.uri, ref_digest, ref_size)) + if checksum and used_uri_fallback: + utils._emit_nonfatal_warning( + f"Reference {uri!r} was recorded without a content checksum, so its " + "version identity is its URI; re-logging changed content at the same " + "location will reuse the existing version instead of creating a new " + f"one. {references.checksum_hint(scheme, normalized)}" + ) + + @staticmethod + def _reference_logical_name(name: str | None, resolved_uri: str, uri: str) -> str: + if name is not None: + return cas.validate_logical_path(name) + derived = references.default_reference_name(resolved_uri) + if not derived: + raise ValueError( + f"Could not derive a name from URI {uri!r}; pass name= explicitly." + ) + return cas.validate_logical_path(derived) + + def _build_manifest(self, project: str) -> Manifest: + if not self._pending_files and not self._pending_references: + raise ValueError( + f"Artifact {self._name!r} has no files or references; " + "call add_file/add_dir/add_reference first." + ) + cas.assert_manifest_paths_compatible( + [logical for _, logical in self._pending_files] + + [logical for logical, *_ in self._pending_references] + ) + + entries: Manifest = [] + for src, logical in self._pending_files: + digest, size = cas.stage_blob_into_project(src, project) + entries.append({"path": logical, "digest": digest, "size": size}) + for logical, uri, ref_digest, ref_size in self._pending_references: + entry: ManifestEntry = { + "path": logical, + "ref": uri, + "digest": ref_digest, + "size": ref_size, + } + entries.append(entry) + return entries + + def _hydrate_from_db( + self, + *, + project: str, + version: int, + aliases: list[str], + manifest: Manifest, + manifest_digest: Sha256Digest, + size_bytes: int, + description: str | None = None, + metadata: dict | None = None, + ) -> None: + if description is not None: + self._description = description + if metadata is not None: + self._metadata = dict(metadata) + self._project = project + self._version = version + self._aliases = tuple(aliases) + self._manifest = [dict(e) for e in manifest] + self._manifest_digest = manifest_digest + self._size = size_bytes + self._logged = True + + def download(self, root: str | Path | None = None) -> str: + """Materialize the artifact's files into a local directory. + + Files are copied from Trackio's content-addressed cache (and fetched + from the remote when missing locally), so repeated calls are cheap and + idempotent. + + Reference entries added via `add_reference` are fetched here too: the + object at each reference URI is downloaded into the directory (via the + bundled `httpx` for `http(s)://`, `huggingface_hub` for `hf://`, and + the registered custom `ReferenceHandler` for any other scheme). Each + object is written atomically and calls are idempotent. Because reference digests + are opaque (a provider ETag or the URI itself), a present file is assumed + current and is not re-verified against the source, and a source whose + re-probed checksum no longer matches the recorded one is downloaded + anyway with a warning. Downloading can transfer a large amount of data; + to work with the URIs without downloading, read them from the `references` + property or `get_entry_uri` instead. A missing source, an unreachable + server, or a scheme with no registered handler raises. + + Args: + root (`str` or `Path`, *optional*): + Directory to write the files into. Defaults to + `./.trackio/artifact-downloads//_v/`, + keyed by project so same-named artifacts from different projects + never collide, and by the resolved version so a moving alias + like `latest` never leaves behind stale files from a previous + version. + + Returns: + The absolute path to the download directory, as a string. + """ + if not self._logged: + raise RuntimeError( + "Cannot download an Artifact that has not been logged or fetched." + ) + if self._manifest is None or self._project is None or self._version is None: + raise RuntimeError("Artifact is missing manifest, project, or version.") + + if root is None: + project = utils.canonical_project_name(self._project) + root_path = ( + Path.cwd() + / ".trackio" + / "artifact-downloads" + / project + / f"{self._name}_v{self._version}" + ) + else: + root_path = Path(root) + root_path.mkdir(parents=True, exist_ok=True) + + for entry in self._manifest: + logical = cas.validate_logical_path(entry["path"]) + if references.is_reference_entry(entry): + scheme, uri = references.validate_reference_uri(entry["ref"]) + _materialize_reference( + uri, scheme, root_path / logical, entry["digest"] + ) + continue + digest = cas.validate_digest(entry["digest"]) + blob = cas.blob_path(self._project, digest) + if not blob.is_file(): + if self._remote_source is None: + raise FileNotFoundError( + f"Artifact blob {digest} not available locally or " + "remotely. The producer machine may not have shipped " + "this blob yet." + ) + _fetch_blob_from_remote( + self._remote_source, self._project, digest, blob + ) + _materialize(blob, root_path / logical, entry["size"]) + + return str(root_path) + + @property + def references(self) -> list[dict]: + """Reference entries (each with `path`, `ref`, `size`, and a `digest`) + recorded via `add_reference`. These point at external data not stored in + Trackio; read them to work with the URIs without downloading (unlike + `download()`, which fetches them). Returns a fresh copy on each access; + empty if the artifact has no references or has not been logged yet.""" + if self._manifest is None: + return [] + return [dict(e) for e in self._manifest if references.is_reference_entry(e)] + + def get_entry_uri(self, name: str) -> str | None: + """Return the URI recorded for the reference entry at logical path + `name`, or None if there is no reference entry with that name.""" + if self._manifest is None: + return None + for entry in self._manifest: + if entry.get("path") == name and references.is_reference_entry(entry): + return entry["ref"] + return None + + def __repr__(self) -> str: + parts: list[str] = [f"name={self._name!r}", f"type={self._type!r}"] + if self._version is not None: + parts.append(f"version=v{self._version}") + if self._aliases: + parts.append(f"aliases={list(self._aliases)!r}") + return f"Artifact({', '.join(parts)})" diff --git a/trackio/asgi_app.py b/trackio/asgi_app.py new file mode 100644 index 0000000000000000000000000000000000000000..ffb0fd7f97a47677bb88aea99f93f40537c7e9f5 --- /dev/null +++ b/trackio/asgi_app.py @@ -0,0 +1,531 @@ +from __future__ import annotations + +import inspect +import json +import logging +import math +import secrets +import tempfile +import threading +from collections.abc import Callable +from pathlib import Path +from typing import Any, get_args, get_origin +from urllib.parse import unquote + +from starlette.applications import Starlette +from starlette.requests import Request +from starlette.responses import FileResponse, JSONResponse, Response, StreamingResponse +from starlette.routing import Route + +from trackio import utils +from trackio.exceptions import TrackioAPIError +from trackio.remote_client import HTTP_API_VERSION + +logger = logging.getLogger("trackio.asgi_app") + +_PACKAGE_JSON_PATH = Path(__file__).parent / "package.json" +_TRACKIO_PACKAGE_VERSION = json.loads(_PACKAGE_JSON_PATH.read_text())["version"] + + +def _normalize_allowed_file_roots( + allowed_file_roots: list[str | Path] | None, +) -> tuple[Path, ...]: + roots = [] + for root in allowed_file_roots or []: + roots.append(Path(root).resolve()) + return tuple(roots) + + +def _is_allowed_file_path(path: Path, allowed_roots: tuple[Path, ...]) -> bool: + resolved_path = path.resolve(strict=False) + for root in allowed_roots: + try: + resolved_path.relative_to(root) + return True + except ValueError: + continue + return False + + +def _json_safe(data: Any) -> Any: + if data is None or isinstance(data, (str, bool, int)): + return data + if isinstance(data, float): + return data if math.isfinite(data) else None + if isinstance(data, dict): + return {k: _json_safe(v) for k, v in data.items()} + if isinstance(data, (list, tuple)): + return [_json_safe(v) for v in data] + if hasattr(data, "item"): + try: + return _json_safe(data.item()) + except Exception: + pass + return str(data) + + +def register_uploaded_temp_file(request: Request, file_path: str | Path) -> None: + resolved_path = Path(file_path).resolve(strict=False) + with request.app.state.uploaded_temp_files_lock: + request.app.state.uploaded_temp_files.add(resolved_path) + + +def consume_uploaded_temp_file(request: Request, file_data: Any) -> Path: + file_path = file_data.get("path") if isinstance(file_data, dict) else None + if not isinstance(file_path, str) or not file_path: + raise TrackioAPIError("Expected uploaded file metadata with a valid path.") + + resolved_path = Path(file_path).resolve(strict=False) + with request.app.state.uploaded_temp_files_lock: + if resolved_path not in request.app.state.uploaded_temp_files: + raise TrackioAPIError( + "Uploaded file was not created by this Trackio server." + ) + request.app.state.uploaded_temp_files.remove(resolved_path) + + if not resolved_path.is_file(): + raise TrackioAPIError("Uploaded file is missing.") + + return resolved_path + + +def cleanup_uploaded_temp_file(file_path: str | Path) -> None: + try: + Path(file_path).unlink(missing_ok=True) + except Exception: + pass + + +def _invoke_handler( + fn: Any, + request: Request, + args: list[Any] | None = None, + kwargs: dict[str, Any] | None = None, +) -> Any: + sig = inspect.signature(fn) + params = list(sig.parameters.values()) + positional_args: list[Any] = [] + keyword_args: dict[str, Any] = {} + args = list(args or []) + kwargs = dict(kwargs or {}) + data_index = 0 + + for param in params: + if param.name == "request": + keyword_args["request"] = request + elif param.kind == inspect.Parameter.VAR_POSITIONAL: + positional_args.extend(args[data_index:]) + data_index = len(args) + elif param.kind == inspect.Parameter.VAR_KEYWORD: + keyword_args.update(kwargs) + kwargs.clear() + elif param.name in kwargs: + keyword_args[param.name] = kwargs.pop(param.name) + elif param.kind in ( + inspect.Parameter.POSITIONAL_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD, + ) and data_index < len(args): + positional_args.append(args[data_index]) + data_index += 1 + elif param.default is inspect.Signature.empty and param.kind not in ( + inspect.Parameter.VAR_POSITIONAL, + inspect.Parameter.VAR_KEYWORD, + ): + raise TrackioAPIError(f"Missing required parameter: {param.name}") + + return fn(*positional_args, **keyword_args) + + +async def version_handler(request: Request) -> Response: + mcp_enabled = bool(getattr(request.app.state, "mcp_enabled", False)) + return JSONResponse( + { + "version": _TRACKIO_PACKAGE_VERSION, + "api_version": HTTP_API_VERSION, + "api_transport": "http", + "mcp_enabled": mcp_enabled, + "mcp_path": "/mcp" if mcp_enabled else None, + } + ) + + +def _json_schema_and_python_type(annotation: Any) -> tuple[dict[str, Any], str]: + if annotation is inspect.Parameter.empty: + return {"type": "object"}, "Any" + origin = get_origin(annotation) + args = get_args(annotation) + if origin is not None and args: + non_none = tuple(a for a in args if a is not type(None)) + if len(non_none) == 1 and len(args) > 1: + return _json_schema_and_python_type(non_none[0]) + if origin is list: + inner, py_inner = _json_schema_and_python_type( + args[0] if args else inspect.Parameter.empty + ) + return {"type": "array", "items": inner}, f"list[{py_inner}]" + if origin is dict: + return {"type": "object"}, "dict" + if annotation in (str, bytes): + return {"type": "string"}, "str" + if annotation is int: + return {"type": "integer"}, "int" + if annotation is float: + return {"type": "number"}, "float" + if annotation is bool: + return {"type": "boolean"}, "bool" + name = getattr(annotation, "__name__", None) + if name: + return {"type": "object"}, name + return {"type": "object"}, "Any" + + +def build_gradio_api_info(api_registry: dict[str, Any]) -> dict[str, Any]: + named_endpoints: dict[str, Any] = {} + for name in sorted(api_registry.keys()): + fn = api_registry[name] + if not callable(fn): + continue + sig = inspect.signature(fn) + parameters: list[dict[str, Any]] = [] + for pname, param in sig.parameters.items(): + if pname == "request": + continue + jtype, pytype = _json_schema_and_python_type(param.annotation) + has_default = param.default is not inspect.Parameter.empty + parameters.append( + { + "label": pname, + "parameter_name": pname, + "parameter_has_default": has_default, + "parameter_default": None if not has_default else param.default, + "type": jtype, + "python_type": {"type": pytype, "description": ""}, + "component": "Api", + "example_input": None, + } + ) + ret_ann = sig.return_annotation + if ret_ann is inspect.Signature.empty: + ret_ann = Any + rjtype, rpytype = _json_schema_and_python_type(ret_ann) + returns = [ + { + "label": "result", + "type": rjtype, + "python_type": {"type": rpytype, "description": ""}, + "component": "Api", + } + ] + named_endpoints[f"/{name}"] = { + "parameters": parameters, + "returns": returns, + "api_visibility": "public", + } + return {"named_endpoints": named_endpoints, "unnamed_endpoints": {}} + + +_MAX_GRADIO_CALL_EVENTS = 256 + + +def _hf_token_value_is_unset(value: Any) -> bool: + if value is None: + return True + if isinstance(value, str) and value.strip() == "": + return True + return False + + +def _authorization_bearer_token(request: Request) -> str | None: + auth = request.headers.get("authorization") or request.headers.get("Authorization") + if not auth: + return None + parts = auth.split() + if len(parts) != 2 or parts[0].lower() != "bearer": + return None + tok = parts[1].strip() + return tok or None + + +def _maybe_apply_hf_token_from_authorization( + request: Request, fn: Any, args: list[Any], kwargs: dict[str, Any] +) -> None: + if not utils.on_spaces(): + return + token = _authorization_bearer_token(request) + if not token: + return + sig = inspect.signature(fn) + if "hf_token" not in sig.parameters: + return + params = [p for p in sig.parameters.values() if p.name != "request"] + names = [p.name for p in params] + if "hf_token" not in names: + return + idx = names.index("hf_token") + if "hf_token" in kwargs: + if _hf_token_value_is_unset(kwargs["hf_token"]): + kwargs["hf_token"] = token + return + if idx < len(args): + if _hf_token_value_is_unset(args[idx]): + args[idx] = token + return + kwargs["hf_token"] = token + + +def _store_gradio_call_result( + request: Request, event_id: str, api_name: str, data: Any +) -> None: + with request.app.state.gradio_call_events_lock: + d = request.app.state.gradio_call_events + while len(d) >= _MAX_GRADIO_CALL_EVENTS: + d.pop(next(iter(d))) + d[event_id] = {"api_name": api_name, "data": data} + + +async def run_api_request(request: Request, api_name: str) -> Response: + api_registry = request.app.state.api_registry + fn = api_registry.get(api_name) + if fn is None: + return JSONResponse({"error": f"Unknown API: {api_name}"}, status_code=404) + + try: + body = await request.json() + except Exception: + body = {} + + args: list[Any] = [] + kwargs: dict[str, Any] = {} + if isinstance(body, dict): + if "args" in body or "kwargs" in body: + args = body.get("args") or [] + kwargs = body.get("kwargs") or {} + elif "data" in body and isinstance(body["data"], list): + args = body["data"] + else: + kwargs = body + elif isinstance(body, list): + args = body + elif body is not None: + args = [body] + + if not isinstance(args, list): + args = [args] + if not isinstance(kwargs, dict): + kwargs = {} + + _maybe_apply_hf_token_from_authorization(request, fn, args, kwargs) + + try: + result = _invoke_handler(fn, request, args=args, kwargs=kwargs) + return JSONResponse({"data": _json_safe(result)}) + except TrackioAPIError as e: + return JSONResponse({"error": str(e)}, status_code=400) + except Exception as e: + return JSONResponse({"error": str(e)}, status_code=500) + + +async def api_handler(request: Request) -> Response: + return await run_api_request(request, request.path_params["api_name"]) + + +async def gradio_api_info_handler(request: Request) -> Response: + return JSONResponse( + build_gradio_api_info(request.app.state.api_registry), + headers={"Cache-Control": "no-store"}, + ) + + +async def gradio_call_post_handler(request: Request) -> Response: + api_name = request.path_params["api_name"] + resp = await run_api_request(request, api_name) + if resp.status_code != 200: + return resp + body = json.loads(bytes(resp.body).decode()) + event_id = secrets.token_urlsafe(16) + _store_gradio_call_result(request, event_id, api_name, body["data"]) + return JSONResponse({"event_id": event_id}) + + +async def gradio_call_poll_handler(request: Request) -> Response: + api_name = request.path_params["api_name"] + event_id = request.path_params["event_id"] + with request.app.state.gradio_call_events_lock: + event = request.app.state.gradio_call_events.pop(event_id, None) + if event is None: + logger.info("gradio_api poll: unknown or expired event_id") + return JSONResponse({"error": "Unknown or expired event_id"}, status_code=404) + if event.get("api_name") != api_name: + logger.info( + "gradio_api poll: api_name mismatch (path=%r, stored=%r)", + api_name, + event.get("api_name"), + ) + with request.app.state.gradio_call_events_lock: + d = request.app.state.gradio_call_events + while len(d) >= _MAX_GRADIO_CALL_EVENTS: + d.pop(next(iter(d))) + d[event_id] = event + return JSONResponse({"error": "Unknown or expired event_id"}, status_code=404) + + data = event["data"] + payload = json.dumps(_json_safe([data])) + + async def sse() -> Any: + yield f"event: complete\ndata: {payload}\n\n" + + return StreamingResponse( + sse(), + media_type="text/event-stream", + headers={ + "Cache-Control": "no-store", + "X-Accel-Buffering": "no", + }, + ) + + +async def upload_handler(request: Request) -> Response: + upload_authorizer = getattr(request.app.state, "upload_authorizer", None) + if callable(upload_authorizer): + try: + upload_authorizer(request) + except TrackioAPIError as e: + return JSONResponse({"error": str(e)}, status_code=400) + + form = await request.form() + uploads = form.getlist("files") + saved_paths = [] + for upload in uploads: + suffix = Path(getattr(upload, "filename", "") or "").suffix + with tempfile.NamedTemporaryFile( + delete=False, + prefix="trackio-upload-", + suffix=suffix, + ) as tmp: + tmp.write(await upload.read()) + register_uploaded_temp_file(request, tmp.name) + saved_paths.append(tmp.name) + return JSONResponse({"paths": saved_paths}) + + +async def gradio_upload_alias_handler(request: Request) -> Response: + return await upload_handler(request) + + +_DISALLOWED_FILE_SUFFIXES = frozenset( + {".db", ".db-journal", ".db-wal", ".db-shm", ".sqlite", ".sqlite3"} +) + + +async def file_handler(request: Request) -> Response: + fs_path = request.query_params.get("path") + if fs_path is None: + return Response("Missing path", status_code=400) + fp = Path(unquote(fs_path)).resolve(strict=False) + if fp.suffix.lower() in _DISALLOWED_FILE_SUFFIXES: + return Response("Not found", status_code=404) + if _is_allowed_file_path(fp, (utils.ARTIFACTS_DIR.resolve(),)): + return Response("Not found", status_code=404) + allowed_roots = getattr(request.app.state, "allowed_file_roots", ()) + if fp.is_file() and _is_allowed_file_path(fp, allowed_roots): + return FileResponse(str(fp)) + return Response("Not found", status_code=404) + + +async def artifact_blob_handler(request: Request) -> Response: + from trackio import cas # noqa: PLC0415 + from trackio import server as _server # noqa: PLC0415 + + project = request.path_params.get("project") + digest = request.path_params.get("digest") + try: + project = _server._validate_project_name(project) + digest = _server._validate_sha256_digest(digest) + except TrackioAPIError: + return Response("Not found", status_code=404) + blob = cas.blob_path(project, digest) + if not blob.is_file(): + return Response("Not found", status_code=404) + return FileResponse(str(blob)) + + +def create_trackio_starlette_app( + oauth_routes: list[Route], + api_registry: dict[str, Any], + extra_routes: list[Any] | None = None, + mcp_lifespan: Any = None, + mcp_enabled: bool = False, + allowed_file_roots: list[str | Path] | None = None, + upload_authorizer: Callable[[Request], None] | None = None, +) -> Starlette: + routes: list[Any] = list(oauth_routes) + routes.extend( + [ + Route("/version", endpoint=version_handler, methods=["GET"]), + Route("/api/upload", endpoint=upload_handler, methods=["POST"]), + Route("/api/{api_name:str}", endpoint=api_handler, methods=["POST"]), + Route("/file", endpoint=file_handler, methods=["GET"]), + Route( + "/artifact_blob/{project:str}/{digest:str}", + endpoint=artifact_blob_handler, + methods=["GET"], + ), + ] + ) + if utils.on_spaces(): + routes.extend( + [ + Route( + "/gradio_api/info", + endpoint=gradio_api_info_handler, + methods=["GET"], + ), + Route( + "/gradio_api/info/", + endpoint=gradio_api_info_handler, + methods=["GET"], + ), + Route( + "/gradio_api/upload", + endpoint=gradio_upload_alias_handler, + methods=["POST"], + ), + Route( + "/gradio_api/upload/", + endpoint=gradio_upload_alias_handler, + methods=["POST"], + ), + Route( + "/gradio_api/call/{api_name:str}", + endpoint=gradio_call_post_handler, + methods=["POST"], + ), + Route( + "/gradio_api/call/{api_name:str}/", + endpoint=gradio_call_post_handler, + methods=["POST"], + ), + Route( + "/gradio_api/call/{api_name:str}/{event_id:str}", + endpoint=gradio_call_poll_handler, + methods=["GET"], + ), + Route( + "/gradio_api/call/{api_name:str}/{event_id:str}/", + endpoint=gradio_call_poll_handler, + methods=["GET"], + ), + ] + ) + routes.extend(extra_routes or []) + app = Starlette(routes=routes, lifespan=mcp_lifespan) + app.state.api_registry = api_registry + app.state.mcp_enabled = mcp_enabled + app.state.allowed_file_roots = _normalize_allowed_file_roots(allowed_file_roots) + app.state.upload_authorizer = upload_authorizer + app.state.uploaded_temp_files = set() + app.state.uploaded_temp_files_lock = threading.Lock() + if utils.on_spaces(): + app.state.gradio_call_events = {} + app.state.gradio_call_events_lock = threading.Lock() + return app diff --git a/trackio/assets/badge.png b/trackio/assets/badge.png new file mode 100644 index 0000000000000000000000000000000000000000..03e0340873223b3ecb45f3ebf09512f6d6746ec2 --- /dev/null +++ b/trackio/assets/badge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:206b7847247e83279f498510a2760338a03116bb5141a658d71ec14429f9ea9e +size 169669 diff --git a/trackio/assets/trackio_logo_dark.png b/trackio/assets/trackio_logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e6ff7e0a3580bca040d9ec3ea8c91e8cca469e61 Binary files /dev/null and b/trackio/assets/trackio_logo_dark.png differ diff --git a/trackio/assets/trackio_logo_light.png b/trackio/assets/trackio_logo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..b3438262c61989e6c6d16df4801a8935136115b3 Binary files /dev/null and b/trackio/assets/trackio_logo_light.png differ diff --git a/trackio/assets/trackio_logo_old.png b/trackio/assets/trackio_logo_old.png new file mode 100644 index 0000000000000000000000000000000000000000..48a07d40b83e23c9cc9dc0cb6544a3c6ad62b57f --- /dev/null +++ b/trackio/assets/trackio_logo_old.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3922c4d1e465270ad4d8abb12023f3beed5d9f7f338528a4c0ac21dcf358a1c8 +size 487101 diff --git a/trackio/assets/trackio_logo_type_dark.png b/trackio/assets/trackio_logo_type_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6f80a3191e514a8a0beaa6ab2011e5baf8df5eda Binary files /dev/null and b/trackio/assets/trackio_logo_type_dark.png differ diff --git a/trackio/assets/trackio_logo_type_dark_transparent.png b/trackio/assets/trackio_logo_type_dark_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..2495f610c975917290b57706133b38621a58cb8b Binary files /dev/null and b/trackio/assets/trackio_logo_type_dark_transparent.png differ diff --git a/trackio/assets/trackio_logo_type_light.png b/trackio/assets/trackio_logo_type_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f07866d245ea897b9aba417b29403f7f91cc8bbd Binary files /dev/null and b/trackio/assets/trackio_logo_type_light.png differ diff --git a/trackio/assets/trackio_logo_type_light_transparent.png b/trackio/assets/trackio_logo_type_light_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..a20b4d5e64c61c91546577645310593fe3493508 Binary files /dev/null and b/trackio/assets/trackio_logo_type_light_transparent.png differ diff --git a/trackio/bucket_storage.py b/trackio/bucket_storage.py new file mode 100644 index 0000000000000000000000000000000000000000..feafcfb902bf83a255cb6b8618409d6d7c341c9a --- /dev/null +++ b/trackio/bucket_storage.py @@ -0,0 +1,208 @@ +import tempfile +from pathlib import Path + +import huggingface_hub + +from trackio.cas import is_partial_blob +from trackio.sqlite_storage import SQLiteStorage +from trackio.utils import ( + TRACKIO_DIR, + canonical_project_name, + project_artifacts_dir, + project_media_dir, +) + + +def create_bucket_if_not_exists(bucket_id: str, private: bool | None = None) -> None: + huggingface_hub.create_bucket(bucket_id, private=private, exist_ok=True) + + +LOGBOOK_FILES_BUCKET_PREFIX = "logbook-files" + + +def upload_logbook_path_artifacts_to_bucket( + bucket_id: str, entries: list[dict] +) -> list[str]: + """Uploads local files referenced by path-artifact cells, preserving their + relative path under a stable bucket prefix. Returns the relative paths that + were actually uploaded (missing files are skipped).""" + additions: list[tuple[str, str]] = [] + uploaded: list[str] = [] + for entry in entries: + local_path = Path(entry["abs_path"]) + if not local_path.is_file(): + continue + remote_path = f"{LOGBOOK_FILES_BUCKET_PREFIX}/{entry['path']}" + additions.append((str(local_path), remote_path)) + uploaded.append(entry["path"]) + if additions: + huggingface_hub.batch_bucket_files( + bucket_id, add=additions, token=huggingface_hub.utils.get_token() + ) + return uploaded + + +def _list_bucket_file_paths(bucket_id: str, prefix: str | None = None) -> list[str]: + items = huggingface_hub.list_bucket_tree(bucket_id, prefix=prefix, recursive=True) + return [ + item.path + for item in items + if getattr(item, "type", None) == "file" and getattr(item, "path", None) + ] + + +def download_bucket_to_trackio_dir(bucket_id: str) -> None: + TRACKIO_DIR.mkdir(parents=True, exist_ok=True) + huggingface_hub.sync_bucket( + source=f"hf://buckets/{bucket_id}/trackio", + dest=str(TRACKIO_DIR), + quiet=True, + ) + + +def upload_project_to_bucket(project: str, bucket_id: str) -> None: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + raise FileNotFoundError(f"No database found for project '{project}'") + + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + conn.execute("PRAGMA wal_checkpoint(TRUNCATE)") + + files_to_add = [(str(db_path), f"trackio/{db_path.name}")] + + media_dir = project_media_dir(project) + if media_dir.exists(): + for media_file in media_dir.rglob("*"): + if media_file.is_file(): + rel = media_file.relative_to(TRACKIO_DIR) + files_to_add.append((str(media_file), f"trackio/{rel.as_posix()}")) + + artifacts_dir = project_artifacts_dir(project) + if artifacts_dir.exists(): + for blob_file in artifacts_dir.rglob("*"): + if not blob_file.is_file(): + continue + if is_partial_blob(blob_file.name): + continue + rel = blob_file.relative_to(TRACKIO_DIR) + files_to_add.append((str(blob_file), f"trackio/{rel.as_posix()}")) + + huggingface_hub.batch_bucket_files(bucket_id, add=files_to_add) + + +def _download_db_from_bucket( + project: str, bucket_id: str, dest_path: Path | None = None +) -> bool: + db_filename = SQLiteStorage.get_project_db_filename(project) + remote_path = f"trackio/{db_filename}" + local_path = dest_path or SQLiteStorage.get_project_db_path(project) + local_path.parent.mkdir(parents=True, exist_ok=True) + try: + huggingface_hub.download_bucket_files( + bucket_id, + files=[(remote_path, str(local_path))], + token=huggingface_hub.utils.get_token(), + ) + return local_path.exists() + except Exception: + return False + + +def _local_db_has_data(project: str) -> bool: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists() or db_path.stat().st_size == 0: + return False + try: + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + count = conn.execute("SELECT COUNT(*) FROM metrics").fetchone()[0] + return count > 0 + except Exception: + return False + + +def _export_and_upload_static( + project: str, + dest_bucket_id: str, + db_path: Path, + media_dir: Path | None = None, + artifacts_dir: Path | None = None, +) -> None: + with tempfile.TemporaryDirectory() as tmp_dir: + output_dir = Path(tmp_dir) + SQLiteStorage.export_for_static_space( + project, output_dir, db_path_override=db_path + ) + + files_to_add = [] + for f in output_dir.rglob("*"): + if f.is_file(): + rel = f.relative_to(output_dir) + files_to_add.append((str(f), rel.as_posix())) + + if media_dir and media_dir.exists(): + for f in media_dir.rglob("*"): + if f.is_file(): + rel = f.relative_to(media_dir) + files_to_add.append((str(f), f"media/{rel.as_posix()}")) + + if artifacts_dir and artifacts_dir.exists(): + for f in artifacts_dir.rglob("*"): + if f.is_file() and not is_partial_blob(f.name): + rel = f.relative_to(artifacts_dir) + files_to_add.append((str(f), f"artifacts/{rel.as_posix()}")) + + huggingface_hub.batch_bucket_files(dest_bucket_id, add=files_to_add) + + +def _copy_project_prefix_between_buckets( + source_bucket_id: str, dest_bucket_id: str, project: str, kind: str +) -> None: + source_prefix = f"trackio/{kind}/{canonical_project_name(project)}/" + files_to_copy = _list_bucket_file_paths(source_bucket_id, prefix=source_prefix) + if not files_to_copy: + return + + huggingface_hub.copy_files( + f"hf://buckets/{source_bucket_id}/{source_prefix}", + f"hf://buckets/{dest_bucket_id}/{kind}/", + ) + + +def upload_project_to_bucket_for_static(project: str, bucket_id: str) -> None: + if not _local_db_has_data(project): + _download_db_from_bucket(project, bucket_id) + + db_path = SQLiteStorage.get_project_db_path(project) + _export_and_upload_static( + project, + bucket_id, + db_path, + project_media_dir(project), + project_artifacts_dir(project), + ) + + +def export_from_bucket_for_static( + source_bucket_id: str, + dest_bucket_id: str, + project: str, +) -> None: + with tempfile.TemporaryDirectory() as work_dir: + work_path = Path(work_dir) + db_path = work_path / SQLiteStorage.get_project_db_filename(project) + + if not _download_db_from_bucket(project, source_bucket_id, dest_path=db_path): + raise FileNotFoundError( + f"Could not download database for project '{project}' " + f"from bucket '{source_bucket_id}'." + ) + + _export_and_upload_static(project, dest_bucket_id, db_path) + for kind in ("media", "artifacts"): + _copy_project_prefix_between_buckets( + source_bucket_id, dest_bucket_id, project, kind + ) diff --git a/trackio/cas.py b/trackio/cas.py new file mode 100644 index 0000000000000000000000000000000000000000..92f797078ae5d74a78d921ccebf1384a34314b44 --- /dev/null +++ b/trackio/cas.py @@ -0,0 +1,214 @@ +"""Content-addressed storage (CAS) helpers shared by the artifact client, +server, and storage layers. +""" + +import hashlib +import os +import re +import uuid +from collections.abc import Iterable, Iterator +from pathlib import Path + +from trackio import utils +from trackio.typehints import Sha256Digest + +SHA256_DIGEST_RE = re.compile(r"^[0-9a-f]{64}$") +ARTIFACT_VERSION_SPEC_RE = re.compile(r"^v(\d+)$") +ARTIFACT_NAME_RE = re.compile(r"^[A-Za-z0-9._-]+\Z") +HASH_CHUNK_SIZE = 1024 * 1024 +PARTIAL_BLOB_MARKER = ".partial." +PARTIAL_BLOB_GLOB = f"*{PARTIAL_BLOB_MARKER}*" + + +def partial_blob_name(base: str = "") -> str: + """Temp filename for an in-flight blob write, excluded from sync/export.""" + return f"{base}{PARTIAL_BLOB_MARKER}{uuid.uuid4().hex}" + + +def is_partial_blob(filename: str) -> bool: + return PARTIAL_BLOB_MARKER in filename + + +def validate_artifact_name(name: str) -> str: + if not isinstance(name, str) or not ARTIFACT_NAME_RE.match(name): + raise ValueError( + f"Artifact name {name!r} must match ^[A-Za-z0-9._-]+$ " + "(letters, digits, dot, underscore, hyphen)." + ) + return name + + +def validate_aliases(aliases: list[str] | None) -> list[str]: + if aliases is None: + return [] + if isinstance(aliases, str) or not isinstance(aliases, (list, tuple)): + raise ValueError( + f"aliases must be a list of strings, got {type(aliases).__name__}." + ) + validated: list[str] = [] + for alias in aliases: + if not isinstance(alias, str) or not alias: + raise ValueError(f"Alias {alias!r} must be a non-empty string.") + if not ARTIFACT_NAME_RE.match(alias): + raise ValueError( + f"Alias {alias!r} must match ^[A-Za-z0-9._-]+$ " + "(letters, digits, dot, underscore, hyphen)." + ) + if ARTIFACT_VERSION_SPEC_RE.match(alias): + raise ValueError( + f"Alias {alias!r} is reserved for version pointers (vN); " + "choose another." + ) + validated.append(alias) + return validated + + +def _project_blobs_root(project: str) -> Path: + return utils.project_artifacts_dir(project) / "blobs" / "sha256" + + +def blob_path(project: str, digest: Sha256Digest) -> Path: + return _project_blobs_root(project) / digest[:2] / digest + + +def hash_file(path: Path) -> tuple[Sha256Digest, int]: + size = path.stat().st_size + file_digest = getattr(hashlib, "file_digest", None) + if file_digest is not None: + with path.open("rb") as f: + sha = file_digest(f, "sha256") + else: + sha = hashlib.sha256() + with path.open("rb") as f: + while chunk := f.read(HASH_CHUNK_SIZE): + sha.update(chunk) + return Sha256Digest(sha.hexdigest()), size + + +def validate_logical_path(logical: str) -> str: + """Validate a manifest logical path: relative, no `.`/`..` segments, no + backslashes, no drive letters, non-empty. Returns the path unchanged. + """ + if not isinstance(logical, str) or not logical: + raise ValueError(f"Invalid artifact path: {logical!r} (must be non-empty)") + if "\\" in logical or "\x00" in logical: + raise ValueError( + f"Invalid artifact path {logical!r}: backslashes and NUL are not allowed" + ) + if logical.startswith("/") or re.match(r"^[A-Za-z]:", logical): + raise ValueError(f"Invalid artifact path {logical!r}: must be relative") + parts = logical.split("/") + if any(part in ("", ".", "..") for part in parts): + raise ValueError( + f"Invalid artifact path {logical!r}: " + "'.', '..', and empty segments are not allowed" + ) + return logical + + +def assert_manifest_paths_compatible(paths: Iterable[str]) -> None: + """Validate a manifest's logical paths as a set: reject exact duplicates and + file/directory prefix collisions. A path cannot be both a file and a + directory, so `sub` and `sub/x` (or `a/b` and `a/b/c`) cannot coexist; + siblings like `a/b` and `a/c` are fine. + """ + seen: set[str] = set() + for p in paths: + if p in seen: + raise ValueError(f"Duplicate logical path in manifest: {p!r}") + seen.add(p) + for p in seen: + parts = p.split("/") + for i in range(1, len(parts)): + ancestor = "/".join(parts[:i]) + if ancestor in seen: + raise ValueError( + f"Artifact path {p!r} collides with {ancestor!r}: a path " + "cannot be both a file and a directory in the same artifact." + ) + + +def validate_digest(digest: str) -> Sha256Digest: + """Validate that `digest` is a 64-char lowercase sha256 hex string and + return it unchanged. + """ + if not isinstance(digest, str) or not SHA256_DIGEST_RE.match(digest): + raise ValueError(f"Invalid artifact blob digest: {digest!r}") + return Sha256Digest(digest) + + +def stage_blob_from_chunks( + chunks: Iterable[bytes], + claimed_digest: Sha256Digest, + target_path: Path, +) -> None: + """Stream `chunks` to `target_path`, verifying they hash to `claimed_digest`. + No-op if `target_path` already exists (the chunks are not consumed). + """ + if target_path.is_file(): + return + target_path.parent.mkdir(parents=True, exist_ok=True) + partial = target_path.parent / partial_blob_name(target_path.name) + sha = hashlib.sha256() + try: + with partial.open("wb") as dst: + for chunk in chunks: + if not chunk: + continue + sha.update(chunk) + dst.write(chunk) + actual = sha.hexdigest() + if actual != claimed_digest: + raise ValueError( + f"Digest mismatch: claimed {claimed_digest}, computed {actual}" + ) + os.replace(partial, target_path) + except Exception: + partial.unlink(missing_ok=True) + raise + + +def stage_blob_from_file( + src_path: Path, + claimed_digest: Sha256Digest, + target_path: Path, +) -> None: + """Copy `src_path` to `target_path`, verifying it hashes to `claimed_digest`.""" + if target_path.is_file(): + return + + def _file_chunks() -> Iterator[bytes]: + with src_path.open("rb") as src: + while chunk := src.read(HASH_CHUNK_SIZE): + yield chunk + + stage_blob_from_chunks(_file_chunks(), claimed_digest, target_path) + + +def stage_blob_into_project(src_path: Path, project: str) -> tuple[Sha256Digest, int]: + """Copy `src_path` into the project's CAS in a single pass, computing its + sha256 and size while writing. Returns `(digest, size)`. If the blob is + already present, the copy is discarded. + """ + blobs_root = _project_blobs_root(project) + blobs_root.mkdir(parents=True, exist_ok=True) + partial = blobs_root / partial_blob_name() + sha = hashlib.sha256() + size = 0 + try: + with src_path.open("rb") as src, partial.open("wb") as dst: + while chunk := src.read(HASH_CHUNK_SIZE): + sha.update(chunk) + dst.write(chunk) + size += len(chunk) + digest = Sha256Digest(sha.hexdigest()) + target = blob_path(project, digest) + if target.is_file(): + partial.unlink(missing_ok=True) + return digest, size + target.parent.mkdir(parents=True, exist_ok=True) + os.replace(partial, target) + return digest, size + except Exception: + partial.unlink(missing_ok=True) + raise diff --git a/trackio/cli.py b/trackio/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..460ce0d388c305301511e69909c582649d83b092 --- /dev/null +++ b/trackio/cli.py @@ -0,0 +1,2307 @@ +import argparse +import os +import re +import sys +from pathlib import Path + +import huggingface_hub + +import trackio +from trackio import freeze, show, sync +from trackio.cli_helpers import ( + error_exit, + format_alerts, + format_artifact, + format_artifacts, + format_json, + format_list, + format_metric_values, + format_project_summary, + format_query_result, + format_run_summary, + format_snapshot, + format_spaces, + format_system_metric_names, + format_system_metrics, +) +from trackio.frontend_config import ( + TRACKIO_CONFIG_PATH, + get_persisted_frontend_dir, + set_persisted_frontend_dir, + unset_persisted_frontend_dir, +) +from trackio.markdown import Markdown +from trackio.server import get_project_summary, get_run_summary +from trackio.sqlite_storage import SQLiteStorage + + +def _get_space(args): + return getattr(args, "space", None) + + +def _get_remote(args): + from trackio.remote_client import RemoteClient + + space = _get_space(args) + if not space: + return None + hf_token = getattr(args, "hf_token", None) + return RemoteClient(space, hf_token=hf_token) + + +def _handle_status(): + print("Reading local Trackio projects...\n") + projects = SQLiteStorage.get_projects() + if not projects: + print("No Trackio projects found.") + return + + local_projects = [] + synced_projects = [] + unsynced_projects = [] + + for project in projects: + space_id = SQLiteStorage.get_space_id(project) + if space_id is None: + local_projects.append(project) + elif SQLiteStorage.has_pending_data(project): + unsynced_projects.append(project) + else: + synced_projects.append(project) + + print("Finished reading Trackio projects") + if local_projects: + print(f" * {len(local_projects)} local trackio project(s) [OK]") + if synced_projects: + print(f" * {len(synced_projects)} trackio project(s) synced to Spaces [OK]") + if unsynced_projects: + print( + f" * {len(unsynced_projects)} trackio project(s) with unsynced changes [WARNING]:" + ) + for p in unsynced_projects: + print(f" - {p}") + + if unsynced_projects: + print( + f"\nRun `trackio sync --project {unsynced_projects[0]}` to sync. " + "Or run `trackio sync --all` to sync all unsynced changes." + ) + + +def _handle_sync(args): + from trackio.deploy import sync_incremental + + if args.sync_all and args.project: + error_exit("Cannot use --all and --project together.") + if not args.sync_all and not args.project: + error_exit("Must provide either --project or --all.") + + if args.sync_all: + projects = SQLiteStorage.get_projects() + synced_any = False + for project in projects: + space_id = SQLiteStorage.get_space_id(project) + if space_id and SQLiteStorage.has_pending_data(project): + sync_incremental( + project, + space_id, + private=args.private, + pending_only=True, + frontend_dir=args.frontend, + ) + synced_any = True + if not synced_any: + print("No projects with unsynced data found.") + else: + space_id = args.space_id + if space_id is None: + space_id = SQLiteStorage.get_space_id(args.project) + sync( + project=args.project, + space_id=space_id, + private=args.private, + force=args.force, + sdk=args.sdk, + frontend_dir=args.frontend, + ) + + +def _handle_config(args): + if args.config_command == "get": + frontend_dir = get_persisted_frontend_dir() + if frontend_dir is None: + print("No Trackio frontend config is set.") + print(f"Config file: {TRACKIO_CONFIG_PATH}") + return + print(f"frontend: {frontend_dir}") + print(f"config: {TRACKIO_CONFIG_PATH}") + return + + if args.config_command == "set": + try: + frontend_dir = set_persisted_frontend_dir(args.frontend) + except ValueError as e: + error_exit(str(e)) + print(f"Saved Trackio default frontend: {frontend_dir}") + print("Reset with `trackio config unset frontend`.") + return + + if args.config_command == "unset": + removed = unset_persisted_frontend_dir() + if removed: + print("Removed Trackio default frontend.") + else: + print("No Trackio default frontend was set.") + return + + +def _extract_reports( + run: str, logs: list[dict], report_name: str | None = None +) -> list[dict]: + reports = [] + for log in logs: + timestamp = log.get("timestamp") + step = log.get("step") + for key, value in log.items(): + if report_name is not None and key != report_name: + continue + if isinstance(value, dict) and value.get("_type") == Markdown.TYPE: + content = value.get("_value") + if isinstance(content, str): + reports.append( + { + "run": run, + "report": key, + "step": step, + "timestamp": timestamp, + "content": content, + } + ) + return reports + + +def _handle_query(args): + remote = _get_remote(args) + try: + if remote: + result = remote.predict(args.project, args.sql, api_name="/query_project") + else: + result = SQLiteStorage.query_project(args.project, args.sql) + except FileNotFoundError as e: + error_exit(str(e)) + except ValueError as e: + error_exit(str(e)) + + if args.json: + print(format_json(result)) + else: + print(format_query_result(result)) + + +def _datetime_to_iso(value): + return value.isoformat() if value is not None else None + + +def _space_url(space) -> str | None: + host = getattr(space, "host", None) + if host: + return host if host.startswith("http") else f"https://{host}" + + subdomain = getattr(space, "subdomain", None) + if subdomain: + return f"https://{subdomain}.hf.space" + + space_id = getattr(space, "id", None) + if not space_id: + return None + return f"https://huggingface.co/spaces/{space_id}" + + +def _serialize_space(space) -> dict: + space_id = getattr(space, "id", "") + namespace, _, name = space_id.partition("/") + return { + "id": space_id, + "namespace": namespace, + "name": name or space_id, + "author": getattr(space, "author", None) or namespace, + "private": bool(getattr(space, "private", False)), + "sdk": getattr(space, "sdk", None), + "url": _space_url(space), + "last_modified": _datetime_to_iso( + getattr(space, "last_modified", None) + or getattr(space, "lastModified", None) + ), + "created_at": _datetime_to_iso(getattr(space, "created_at", None)), + "tags": getattr(space, "tags", None) or [], + } + + +def _maybe_handle_logbook_run_argv() -> bool: + argv = sys.argv[1:] + try: + logbook_idx = argv.index("logbook") + except ValueError: + return False + if len(argv) <= logbook_idx + 1 or argv[logbook_idx + 1] != "run": + return False + + run_argv = argv[logbook_idx + 2 :] + + run_parser = argparse.ArgumentParser( + prog=f"{os.path.basename(sys.argv[0])} logbook run", + description=( + "Run a command; log the command, its scripts, and output to a page" + ), + ) + run_parser.add_argument("--page", help="Page title or slug") + run_parser.add_argument("--title", help="Cell title") + run_parser.add_argument( + "--no-artifacts", + action="store_true", + help="Do not record output model/data files as artifact cells", + ) + if "--" in run_argv: + sep = run_argv.index("--") + opts = run_parser.parse_args(run_argv[:sep]) + command = run_argv[sep + 1 :] + else: + opts, command = run_parser.parse_known_args(run_argv) + if not command: + run_parser.error("No command provided. Use: trackio logbook run -- ") + args = argparse.Namespace( + logbook_action="run", + page=opts.page, + title=opts.title, + no_artifacts=opts.no_artifacts, + command=command, + ) + _handle_logbook(args) + return True + + +def _maybe_rewrite_logbook_read_argv() -> None: + argv = sys.argv + for i in range(1, len(argv) - 1): + if argv[i] == "logbook" and argv[i + 1] == "read": + j = i + 2 + if ( + j < len(argv) + and not argv[j].startswith("-") + and argv[j] not in ("pages", "page", "cell") + ): + argv[j : j + 1] = ["--path", argv[j]] + return + + +def _trackio_space_namespaces(api, token: str | None, author: str | None) -> list[str]: + if author: + return [author] + + if not token: + error_exit( + "Log in with `huggingface-cli login`, pass `--hf-token`, or provide `--author`." + ) + + try: + whoami = api.whoami(token=token, cache=True) + except Exception as e: + error_exit(f"Failed to read Hugging Face account information: {e}") + + namespaces = [whoami["name"]] + for org in whoami.get("orgs", []): + org_name = org.get("name") if isinstance(org, dict) else org + if org_name: + namespaces.append(org_name) + + return list(dict.fromkeys(namespaces)) + + +def _handle_list_spaces(args): + if _get_space(args): + error_exit("The 'list spaces' command does not support --space.") + if args.limit is not None and args.limit < 0: + error_exit("--limit must be zero or greater.") + + token = args.hf_token or huggingface_hub.utils.get_token() + api = huggingface_hub.HfApi(token=token) + namespaces = _trackio_space_namespaces(api, token, args.author) + + spaces_by_id = {} + try: + for namespace in namespaces: + spaces = api.list_spaces( + author=namespace, + filter="trackio", + full=True, + token=token, + ) + for space in spaces: + space_id = getattr(space, "id", None) + if space_id: + spaces_by_id[space_id] = _serialize_space(space) + except Exception as e: + error_exit(f"Failed to list Trackio Spaces: {e}") + + spaces = sorted( + spaces_by_id.values(), + key=lambda space: space.get("last_modified") or "", + reverse=True, + ) + if args.limit is not None: + spaces = spaces[: args.limit] + + if args.json: + print(format_json({"spaces": spaces})) + else: + print(format_spaces(spaces)) + + +def main(): + if _maybe_handle_logbook_run_argv(): + return + _maybe_rewrite_logbook_read_argv() + + parser = argparse.ArgumentParser(description="Trackio CLI") + parser.add_argument( + "--version", + action="version", + version=f"trackio {trackio.__version__}", + ) + parser.add_argument( + "--space", + required=False, + help="HF Space ID (e.g. 'user/space') or Space URL to query remotely.", + ) + parser.add_argument( + "--hf-token", + required=False, + help="HF token for accessing private Spaces.", + ) + subparsers = parser.add_subparsers(dest="command") + + ui_parser = subparsers.add_parser( + "show", help="Show the Trackio dashboard UI for a project" + ) + ui_parser.add_argument( + "--project", required=False, help="Project name to show in the dashboard" + ) + ui_parser.add_argument( + "--theme", + required=False, + default="default", + help="A Gradio Theme to use for the dashboard instead of the default, can be a built-in theme (e.g. 'soft', 'citrus'), or a theme from the Hub (e.g. 'gstaff/xkcd').", + ) + ui_parser.add_argument( + "--mcp-server", + action="store_true", + help="Enable MCP server functionality. The Trackio dashboard will be set up as an MCP server and certain functions will be exposed as MCP tools.", + ) + ui_parser.add_argument( + "--footer", + action="store_true", + default=True, + help="Show the Gradio footer. Use --no-footer to hide it.", + ) + ui_parser.add_argument( + "--no-footer", + dest="footer", + action="store_false", + help="Hide the Gradio footer.", + ) + ui_parser.add_argument( + "--color-palette", + required=False, + help="Comma-separated list of hex color codes for plot lines (e.g. '#FF0000,#00FF00,#0000FF'). If not provided, the TRACKIO_COLOR_PALETTE environment variable will be used, or the default palette if not set.", + ) + ui_parser.add_argument( + "--host", + required=False, + help="Host to bind the server to (e.g. '0.0.0.0' for remote access). If not provided, defaults to '127.0.0.1' (localhost only).", + ) + ui_parser.add_argument( + "--frontend", + required=False, + help="Custom frontend directory to serve. Must contain index.html.", + ) + + subparsers.add_parser( + "status", + help="Show the status of all local Trackio projects, including sync status.", + ) + + sync_parser = subparsers.add_parser( + "sync", + help="Sync a local project's database to a Hugging Face Space. If the Space does not exist, it will be created.", + ) + sync_parser.add_argument( + "--project", + required=False, + help="The name of the local project.", + ) + sync_parser.add_argument( + "--space-id", + required=False, + help="The Hugging Face Space ID where the project will be synced (e.g. username/space_id). If not provided, uses the previously-configured Space.", + ) + sync_parser.add_argument( + "--all", + action="store_true", + dest="sync_all", + help="Sync all projects that have unsynced data to their configured Spaces.", + ) + sync_parser.add_argument( + "--private", + action="store_true", + help="Make the Hugging Face Space private if creating a new Space. By default, the repo will be public unless the organization's default is private. This value is ignored if the repo already exists.", + ) + sync_parser.add_argument( + "--force", + action="store_true", + help="Overwrite the existing database without prompting for confirmation.", + ) + sync_parser.add_argument( + "--sdk", + choices=["gradio", "static"], + default="gradio", + help="The type of Space to deploy. 'gradio' (default) deploys a live Gradio server. 'static' deploys a static Space that reads from an HF Bucket.", + ) + sync_parser.add_argument( + "--frontend", + required=False, + help="Custom frontend directory to deploy. Must contain index.html.", + ) + + freeze_parser = subparsers.add_parser( + "freeze", + help="Create a one-time static Space snapshot from a project's data.", + ) + freeze_parser.add_argument( + "--space-id", + required=True, + help="The source Gradio Space ID (e.g. username/space_id).", + ) + freeze_parser.add_argument( + "--project", + required=True, + help="The name of the project to freeze into a static snapshot.", + ) + freeze_parser.add_argument( + "--new-space-id", + required=False, + help="The Space ID for the new static Space. Defaults to {space_id}_static.", + ) + freeze_parser.add_argument( + "--private", + action="store_true", + help="Make the new static Space private.", + ) + freeze_parser.add_argument( + "--frontend", + required=False, + help="Custom frontend directory to deploy to the frozen static Space.", + ) + + config_parser = subparsers.add_parser( + "config", + help="Manage persistent Trackio configuration.", + ) + config_subparsers = config_parser.add_subparsers( + dest="config_command", + required=True, + ) + config_subparsers.add_parser("get", help="Show current Trackio config.") + config_set_parser = config_subparsers.add_parser( + "set", + help="Set a persistent Trackio config value.", + ) + config_set_parser.add_argument( + "key", + choices=["frontend"], + help="Config key to set.", + ) + config_set_parser.add_argument( + "frontend", + help="Frontend directory to persist.", + ) + config_unset_parser = config_subparsers.add_parser( + "unset", + help="Unset a persistent Trackio config value.", + ) + config_unset_parser.add_argument( + "key", + choices=["frontend"], + help="Config key to unset.", + ) + + list_parser = subparsers.add_parser( + "list", + help="List projects, runs, or metrics", + ) + list_subparsers = list_parser.add_subparsers(dest="list_type", required=True) + + list_projects_parser = list_subparsers.add_parser( + "projects", + help="List all projects", + ) + list_projects_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_spaces_parser = list_subparsers.add_parser( + "spaces", + help="List Trackio Spaces for your Hugging Face account and organizations", + ) + list_spaces_parser.add_argument( + "--author", + required=False, + help="Only list Trackio Spaces under this user or organization namespace.", + ) + list_spaces_parser.add_argument( + "--limit", + type=int, + required=False, + help="Maximum number of Spaces to return.", + ) + list_spaces_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_runs_parser = list_subparsers.add_parser( + "runs", + help="List runs for a project", + ) + list_runs_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_runs_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_metrics_parser = list_subparsers.add_parser( + "metrics", + help="List metrics for a run", + ) + list_metrics_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_metrics_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + list_metrics_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_system_metrics_parser = list_subparsers.add_parser( + "system-metrics", + help="List system metrics for a run", + ) + list_system_metrics_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_system_metrics_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + list_system_metrics_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_alerts_parser = list_subparsers.add_parser( + "alerts", + help="List alerts for a project or run", + ) + list_alerts_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_alerts_parser.add_argument( + "--run", + required=False, + help="Run name (optional)", + ) + list_alerts_parser.add_argument( + "--level", + required=False, + help="Filter by alert level (info, warn, error)", + ) + list_alerts_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + list_alerts_parser.add_argument( + "--since", + required=False, + help="Only show alerts after this ISO 8601 timestamp", + ) + + list_reports_parser = list_subparsers.add_parser( + "reports", + help="List markdown reports for a project or run", + ) + list_reports_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_reports_parser.add_argument( + "--run", + required=False, + help="Run name (optional)", + ) + list_reports_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_artifacts_parser = list_subparsers.add_parser( + "artifacts", + help="List artifacts for a project", + ) + list_artifacts_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_artifacts_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_parser = subparsers.add_parser( + "get", + help="Get project, run, or metric information", + ) + get_subparsers = get_parser.add_subparsers(dest="get_type", required=True) + + get_project_parser = get_subparsers.add_parser( + "project", + help="Get project summary", + ) + get_project_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_project_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_run_parser = get_subparsers.add_parser( + "run", + help="Get run summary", + ) + get_run_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_run_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_run_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_artifact_parser = get_subparsers.add_parser( + "artifact", + help="Get an artifact version (manifest, aliases, metadata)", + ) + get_artifact_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_artifact_parser.add_argument( + "--name", + required=True, + help="Artifact name", + ) + get_artifact_parser.add_argument( + "--version", + required=False, + help="Version or alias to resolve (e.g. 'v2' or 'best'). Defaults to latest.", + ) + get_artifact_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_metric_parser = get_subparsers.add_parser( + "metric", + help="Get metric values for a run", + ) + get_metric_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_metric_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_metric_parser.add_argument( + "--metric", + required=True, + help="Metric name", + ) + get_metric_parser.add_argument( + "--step", + type=int, + required=False, + help="Get metric at exactly this step", + ) + get_metric_parser.add_argument( + "--around", + type=int, + required=False, + help="Get metrics around this step (use with --window)", + ) + get_metric_parser.add_argument( + "--at-time", + required=False, + help="Get metrics around this ISO 8601 timestamp (use with --window)", + ) + get_metric_parser.add_argument( + "--window", + type=int, + required=False, + default=10, + help="Window size: ±steps for --around, ±seconds for --at-time (default: 10)", + ) + get_metric_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_snapshot_parser = get_subparsers.add_parser( + "snapshot", + help="Get all metrics at/around a step or timestamp", + ) + get_snapshot_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_snapshot_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_snapshot_parser.add_argument( + "--step", + type=int, + required=False, + help="Get all metrics at exactly this step", + ) + get_snapshot_parser.add_argument( + "--around", + type=int, + required=False, + help="Get all metrics around this step (use with --window)", + ) + get_snapshot_parser.add_argument( + "--at-time", + required=False, + help="Get all metrics around this ISO 8601 timestamp (use with --window)", + ) + get_snapshot_parser.add_argument( + "--window", + type=int, + required=False, + default=10, + help="Window size: ±steps for --around, ±seconds for --at-time (default: 10)", + ) + get_snapshot_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_system_metric_parser = get_subparsers.add_parser( + "system-metric", + help="Get system metric values for a run", + ) + get_system_metric_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_system_metric_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_system_metric_parser.add_argument( + "--metric", + required=False, + help="System metric name (optional, if not provided returns all system metrics)", + ) + get_system_metric_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_alerts_parser = get_subparsers.add_parser( + "alerts", + help="Get alerts for a project or run", + ) + get_alerts_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_alerts_parser.add_argument( + "--run", + required=False, + help="Run name (optional)", + ) + get_alerts_parser.add_argument( + "--level", + required=False, + help="Filter by alert level (info, warn, error)", + ) + get_alerts_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + get_alerts_parser.add_argument( + "--since", + required=False, + help="Only show alerts after this ISO 8601 timestamp", + ) + + get_report_parser = get_subparsers.add_parser( + "report", + help="Get markdown report entries for a run", + ) + get_report_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_report_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_report_parser.add_argument( + "--report", + required=True, + help="Report metric name", + ) + get_report_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + query_parser = subparsers.add_parser( + "query", + help="Run a read-only SQL query against a project database", + ) + query_subparsers = query_parser.add_subparsers(dest="query_type", required=True) + query_project_parser = query_subparsers.add_parser( + "project", + help="Run a read-only SQL query against a project's SQLite database", + ) + query_project_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + query_project_parser.add_argument( + "--sql", + required=True, + help="Read-only SQL query to execute", + ) + query_project_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + skills_parser = subparsers.add_parser( + "skills", + help="Manage Trackio skills for AI coding assistants", + ) + skills_subparsers = skills_parser.add_subparsers( + dest="skills_action", required=True + ) + skills_add_parser = skills_subparsers.add_parser( + "add", + help=( + "Install the Trackio skill to the central .agents/skills location; " + "pass agent flags to also symlink it for specific assistants" + ), + ) + skills_add_parser.add_argument( + "--cursor", + action="store_true", + help="Install for Cursor", + ) + skills_add_parser.add_argument( + "--claude", + action="store_true", + help="Install for Claude Code", + ) + skills_add_parser.add_argument( + "--codex", + action="store_true", + help="Install for Codex", + ) + skills_add_parser.add_argument( + "--opencode", + action="store_true", + help="Install for OpenCode", + ) + skills_add_parser.add_argument( + "--pi", + action="store_true", + help="Install for pi", + ) + skills_add_parser.add_argument( + "--global", + dest="global_", + action="store_true", + help="Install globally (user-level) instead of in the current project directory", + ) + skills_add_parser.add_argument( + "--dest", + type=str, + required=False, + help="Install into a custom destination (path to skills directory)", + ) + skills_add_parser.add_argument( + "--force", + action="store_true", + help="Overwrite existing skill if it already exists", + ) + skills_add_parser.add_argument( + "--no-command", + dest="no_command", + action="store_true", + help="Do not install the /logbook slash command alongside the skill", + ) + skills_add_parser.add_argument( + "--no-hook", + dest="no_hook", + action="store_true", + help="Do not install the Claude Code hook that mirrors todos into the logbook", + ) + + logbook_parser = subparsers.add_parser( + "logbook", + help="Create and publish a shareable experiment logbook", + ) + logbook_sub = logbook_parser.add_subparsers( + dest="logbook_action", + required=True, + metavar="{open,cell,run,page,read,serve,publish,sync}", + ) + + lb_open = logbook_sub.add_parser( + "open", help="Start or attach to the logbook in this directory" + ) + lb_open.add_argument( + "space_id", nargs="?", help="Optional HF Space id to publish to" + ) + lb_open.add_argument("--title", help="Logbook title (only when creating)") + lb_open.add_argument( + "--no-serve", + action="store_true", + help="Open or attach without launching the local logbook preview", + ) + lb_open.add_argument("--port", type=int, default=7861) + lb_open.add_argument("--no-browser", action="store_true") + + lb_cell = logbook_sub.add_parser( + "cell", help="Append a typed notebook-style cell to a logbook page" + ) + lb_cell_sub = lb_cell.add_subparsers(dest="cell_type", required=True) + + lb_cell_md = lb_cell_sub.add_parser("markdown", help="Append a markdown cell") + lb_cell_md.add_argument( + "body", + help="Markdown body (literal \\n escape sequences are converted to line breaks)", + ) + lb_cell_md.add_argument("--title", help="Cell title") + lb_cell_md.add_argument("--page", help="Page title or slug") + lb_cell_art = lb_cell_sub.add_parser( + "artifact", help="Append an artifact cell referencing a Trackio artifact" + ) + lb_cell_art.add_argument("name", help="Artifact reference project/name:vN") + lb_cell_art.add_argument("--title", help="Cell title") + lb_cell_art.add_argument("--page", help="Page title or slug") + lb_cell_art.add_argument( + "--type", + dest="artifact_type", + help='Artifact type, e.g. "dataset" or "model"', + ) + + lb_cell_code = lb_cell_sub.add_parser("code", help="Append a code cell") + lb_cell_code.add_argument("--title", help="Cell title") + lb_cell_code.add_argument("--page", help="Page title or slug") + lb_cell_code.add_argument( + "--code", action="append", default=[], help="Path to code/config to include" + ) + lb_cell_code.add_argument("--code-text", help="Inline code to include") + lb_cell_code.add_argument("--language", help="Language for --code-text") + lb_cell_code.add_argument("--output", required=True, help="Output text") + + lb_cell_figure = lb_cell_sub.add_parser("figure", help="Append a figure cell") + lb_cell_figure.add_argument("--title", help="Cell title") + lb_cell_figure.add_argument("--page", help="Page title or slug") + lb_cell_figure.add_argument( + "--html", help="Path to an HTML or image file, or inline HTML text" + ) + lb_cell_figure.add_argument("--html-text", help="Inline HTML text") + lb_cell_figure.add_argument( + "--image", help="Path to an image file (PNG, JPG, GIF, WEBP, SVG, ...)" + ) + lb_cell_figure.add_argument("--raw", help="Path/URL/text for raw data") + lb_cell_figure.add_argument("--raw-text", help="Inline raw data") + + lb_cell_dash = lb_cell_sub.add_parser( + "dashboard", help="Embed a Trackio dashboard for a project" + ) + lb_cell_dash.add_argument("project", help="Trackio project name") + lb_cell_dash.add_argument( + "--space", + dest="space_id", + help="HF Space id (owner/name) hosting the dashboard", + ) + lb_cell_dash.add_argument("--title", help="Cell title") + lb_cell_dash.add_argument("--page", help="Page title or slug") + + lb_run = logbook_sub.add_parser( + "run", + help="Run a command; log the command, its scripts, and output to a page", + ) + lb_run.add_argument("--page", help="Page title or slug") + lb_run.add_argument("--title", help="Cell title") + lb_run.add_argument( + "--no-artifacts", + action="store_true", + help="Do not record output model/data files as artifact cells", + ) + lb_run.add_argument("command", nargs="*") + + lb_page = logbook_sub.add_parser( + "page", help="Create or select a page and make it the default target" + ) + lb_page.add_argument("title", help="Page title") + + lb_read = logbook_sub.add_parser( + "read", help="Read logbook pages/cells in an agent-friendly form" + ) + lb_read.add_argument( + "--path", + help=( + "Logbook to read: local path, HF Space id, or URL " + "(can also be passed positionally: trackio logbook read )" + ), + ) + lb_read.add_argument("--json", action="store_true", help="Output JSON") + lb_read.add_argument( + "--head", + type=int, + default=None, + help="Lines of code shown per code cell (default 3; 0 hides code)", + ) + lb_read.add_argument( + "--tail", + type=int, + default=None, + help="Lines of output shown per code cell (default 3; 0 hides output)", + ) + lb_read.add_argument( + "--raw-limit", + type=int, + default=None, + help="Inline figure raw data up to this many chars (default 500; 0 disables)", + ) + lb_read_sub = lb_read.add_subparsers(dest="read_target") + lb_read_pages = lb_read_sub.add_parser("pages", help="List logbook pages") + lb_read_pages.add_argument("--json", action="store_true", help="Output JSON") + lb_read_page = lb_read_sub.add_parser("page", help="Read a page for agents") + lb_read_page.add_argument("page", nargs="?", help="Page title or slug") + lb_read_page.add_argument("--json", action="store_true", help="Output JSON") + lb_read_page.add_argument( + "--head", type=int, default=argparse.SUPPRESS, help="Code lines per code cell" + ) + lb_read_page.add_argument( + "--tail", type=int, default=argparse.SUPPRESS, help="Output lines per code cell" + ) + lb_read_page.add_argument( + "--raw-limit", + type=int, + default=argparse.SUPPRESS, + help="Inline figure raw data up to this many chars", + ) + lb_read_cell = lb_read_sub.add_parser("cell", help="Read one cell by id") + lb_read_cell.add_argument("cell_id", help="Cell id") + lb_read_cell.add_argument("--json", action="store_true", help="Output JSON") + lb_read_cell.add_argument("--full", action="store_true", help="Include full body") + lb_read_cell.add_argument( + "--raw", action="store_true", help="Include figure raw data" + ) + lb_read_cell.add_argument("--html", action="store_true", help="Include figure HTML") + + lb_serve = logbook_sub.add_parser("serve", help="Preview the logbook locally") + lb_serve.add_argument("path", nargs="?", help="Logbook workspace/path to serve") + lb_serve.add_argument("--port", type=int, default=7861) + lb_serve.add_argument("--no-browser", action="store_true") + + lb_pub = logbook_sub.add_parser( + "publish", help="Publish to a static HF Space (first publish enables auto-sync)" + ) + lb_pub.add_argument("space_id", nargs="?", help="HF Space id (username/space)") + lb_pub.add_argument( + "--private", + action="store_true", + help="Make the logbook and any promoted dashboards/buckets private", + ) + + lb_pin = logbook_sub.add_parser( + "pin", + help="Pin (or unpin) a cell so it surfaces on the logbook intro", + ) + lb_pin.add_argument( + "cell_id", + nargs="?", + help="Cell id to pin (default: the most recent cell on the target page)", + ) + lb_pin.add_argument( + "--page", + help="Page title or slug to scope the search / pick the last cell from", + ) + lb_pin.add_argument( + "--unpin", action="store_true", help="Unpin the cell instead of pinning it" + ) + + logbook_sub.add_parser( + "sync", help="Push local edits to the Space now (after the first publish)" + ) + + logbook_sub.add_parser("_sync") + logbook_sub.add_parser("sync-todos") + + args, unknown_args = parser.parse_known_args() + if unknown_args: + trailing_global_parser = argparse.ArgumentParser(add_help=False) + trailing_global_parser.add_argument("--space", required=False) + trailing_global_parser.add_argument("--hf-token", required=False) + trailing_globals, remaining_unknown = trailing_global_parser.parse_known_args( + unknown_args + ) + if remaining_unknown: + parser.error(f"unrecognized arguments: {' '.join(remaining_unknown)}") + if trailing_globals.space is not None: + args.space = trailing_globals.space + if trailing_globals.hf_token is not None: + args.hf_token = trailing_globals.hf_token + + if args.command in ("show", "status", "sync", "freeze", "skills") and _get_space( + args + ): + error_exit( + f"The '{args.command}' command does not support --space (remote mode)." + ) + + if args.command == "show": + color_palette = None + if args.color_palette: + color_palette = [color.strip() for color in args.color_palette.split(",")] + show( + project=args.project, + theme=args.theme, + mcp_server=args.mcp_server, + footer=args.footer, + color_palette=color_palette, + host=args.host, + frontend_dir=args.frontend, + ) + elif args.command == "status": + _handle_status() + elif args.command == "sync": + _handle_sync(args) + elif args.command == "freeze": + freeze( + space_id=args.space_id, + project=args.project, + new_space_id=args.new_space_id, + private=args.private, + frontend_dir=args.frontend, + ) + elif args.command == "config": + _handle_config(args) + elif args.command == "list": + if args.list_type == "spaces": + _handle_list_spaces(args) + return + + remote = _get_remote(args) + if args.list_type == "projects": + if remote: + projects = remote.predict(api_name="/get_all_projects") + else: + projects = SQLiteStorage.get_projects() + if args.json: + print(format_json({"projects": projects})) + else: + print(format_list(projects, "Projects")) + elif args.list_type == "runs": + if remote: + run_records = remote.predict( + args.project, api_name="/get_runs_for_project" + ) + runs = [r["name"] if isinstance(r, dict) else r for r in run_records] + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.json: + print(format_json({"project": args.project, "runs": runs})) + else: + print(format_list(runs, f"Runs in '{args.project}'")) + elif args.list_type == "metrics": + if remote: + metrics = remote.predict( + args.project, args.run, api_name="/get_metrics_for_run" + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + metrics = SQLiteStorage.get_all_metrics_for_run(args.project, args.run) + if args.json: + print( + format_json( + {"project": args.project, "run": args.run, "metrics": metrics} + ) + ) + else: + print( + format_list( + metrics, f"Metrics for '{args.run}' in '{args.project}'" + ) + ) + elif args.list_type == "system-metrics": + if remote: + system_metrics = remote.predict( + args.project, args.run, api_name="/get_system_metrics_for_run" + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + system_metrics = SQLiteStorage.get_all_system_metrics_for_run( + args.project, args.run + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "system_metrics": system_metrics, + } + ) + ) + else: + print(format_system_metric_names(system_metrics)) + elif args.list_type == "alerts": + if remote: + alerts = remote.predict( + args.project, + args.run, + args.level, + args.since, + api_name="/get_alerts", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + alerts = SQLiteStorage.get_alerts( + args.project, + run_name=args.run, + level=args.level, + since=args.since, + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "level": args.level, + "since": args.since, + "alerts": alerts, + } + ) + ) + else: + print(format_alerts(alerts)) + elif args.list_type == "reports": + if remote: + run_records = remote.predict( + args.project, api_name="/get_runs_for_project" + ) + runs = [r["name"] if isinstance(r, dict) else r for r in run_records] + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run and args.run not in runs: + error_exit(f"Run '{args.run}' not found in project '{args.project}'.") + + target_runs = [args.run] if args.run else runs + all_reports = [] + for run_name in target_runs: + if remote: + logs = remote.predict(args.project, run_name, api_name="/get_logs") + else: + logs = SQLiteStorage.get_logs(args.project, run_name) + all_reports.extend(_extract_reports(run_name, logs)) + + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "reports": all_reports, + } + ) + ) + else: + report_lines = [ + f"{entry['run']} | {entry['report']} | step={entry['step']} | {entry['timestamp']}" + for entry in all_reports + ] + if args.run: + print( + format_list( + report_lines, + f"Reports for '{args.run}' in '{args.project}'", + ) + ) + else: + print(format_list(report_lines, f"Reports in '{args.project}'")) + elif args.list_type == "artifacts": + if remote: + artifacts = remote.predict(args.project, api_name="/get_artifacts") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + artifacts = SQLiteStorage.get_artifacts(args.project) + if args.json: + print(format_json({"project": args.project, "artifacts": artifacts})) + else: + print(format_artifacts(artifacts, args.project)) + elif args.command == "get": + remote = _get_remote(args) + if args.get_type == "artifact": + if remote: + record = remote.predict( + args.project, + args.name, + args.version, + api_name="/get_artifact_manifest", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + record = SQLiteStorage.get_artifact_manifest( + args.project, args.name, args.version + ) + if record is None: + spec = f":{args.version}" if args.version else "" + error_exit( + f"Artifact '{args.name}{spec}' not found in project " + f"'{args.project}'." + ) + if args.json: + print(format_json(record)) + else: + print(format_artifact(record)) + elif args.get_type == "project": + if remote: + summary = remote.predict(args.project, api_name="/get_project_summary") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + summary = get_project_summary(args.project) + if args.json: + print(format_json(summary)) + else: + print(format_project_summary(summary)) + elif args.get_type == "run": + if remote: + summary = remote.predict( + args.project, args.run, api_name="/get_run_summary" + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + summary = get_run_summary(args.project, args.run) + if args.json: + print(format_json(summary)) + else: + print(format_run_summary(summary)) + elif args.get_type == "metric": + at_time = getattr(args, "at_time", None) + if remote: + values = remote.predict( + args.project, + args.run, + args.metric, + args.step, + args.around, + at_time, + args.window, + api_name="/get_metric_values", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + metrics = SQLiteStorage.get_all_metrics_for_run(args.project, args.run) + if args.metric not in metrics: + error_exit( + f"Metric '{args.metric}' not found in run '{args.run}' of project '{args.project}'." + ) + values = SQLiteStorage.get_metric_values( + args.project, + args.run, + args.metric, + step=args.step, + around_step=args.around, + at_time=at_time, + window=args.window, + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "metric": args.metric, + "values": values, + } + ) + ) + else: + print(format_metric_values(values)) + elif args.get_type == "snapshot": + if not args.step and not args.around and not getattr(args, "at_time", None): + error_exit( + "Provide --step, --around (with --window), or --at-time (with --window)." + ) + at_time = getattr(args, "at_time", None) + if remote: + snapshot = remote.predict( + args.project, + args.run, + args.step, + args.around, + at_time, + args.window, + api_name="/get_snapshot", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + snapshot = SQLiteStorage.get_snapshot( + args.project, + args.run, + step=args.step, + around_step=args.around, + at_time=at_time, + window=args.window, + ) + if args.json: + result = { + "project": args.project, + "run": args.run, + "metrics": snapshot, + } + if args.step is not None: + result["step"] = args.step + if args.around is not None: + result["around"] = args.around + result["window"] = args.window + if at_time is not None: + result["at_time"] = at_time + result["window"] = args.window + print(format_json(result)) + else: + print(format_snapshot(snapshot)) + elif args.get_type == "system-metric": + if remote: + system_metrics = remote.predict( + args.project, args.run, api_name="/get_system_logs" + ) + if args.metric: + all_system_metric_names = remote.predict( + args.project, + args.run, + api_name="/get_system_metrics_for_run", + ) + if args.metric not in all_system_metric_names: + error_exit( + f"System metric '{args.metric}' not found in run '{args.run}' of project '{args.project}'." + ) + filtered_metrics = [ + { + k: v + for k, v in entry.items() + if k == "timestamp" or k == args.metric + } + for entry in system_metrics + if args.metric in entry + ] + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "metric": args.metric, + "values": filtered_metrics, + } + ) + ) + else: + print(format_system_metrics(filtered_metrics)) + else: + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "system_metrics": system_metrics, + } + ) + ) + else: + print(format_system_metrics(system_metrics)) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + if args.metric: + system_metrics = SQLiteStorage.get_system_logs( + args.project, args.run + ) + all_system_metric_names = ( + SQLiteStorage.get_all_system_metrics_for_run( + args.project, args.run + ) + ) + if args.metric not in all_system_metric_names: + error_exit( + f"System metric '{args.metric}' not found in run '{args.run}' of project '{args.project}'." + ) + filtered_metrics = [ + { + k: v + for k, v in entry.items() + if k == "timestamp" or k == args.metric + } + for entry in system_metrics + if args.metric in entry + ] + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "metric": args.metric, + "values": filtered_metrics, + } + ) + ) + else: + print(format_system_metrics(filtered_metrics)) + else: + system_metrics = SQLiteStorage.get_system_logs( + args.project, args.run + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "system_metrics": system_metrics, + } + ) + ) + else: + print(format_system_metrics(system_metrics)) + elif args.get_type == "alerts": + if remote: + alerts = remote.predict( + args.project, + args.run, + args.level, + args.since, + api_name="/get_alerts", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + alerts = SQLiteStorage.get_alerts( + args.project, + run_name=args.run, + level=args.level, + since=args.since, + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "level": args.level, + "since": args.since, + "alerts": alerts, + } + ) + ) + else: + print(format_alerts(alerts)) + elif args.get_type == "report": + if remote: + logs = remote.predict(args.project, args.run, api_name="/get_logs") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + logs = SQLiteStorage.get_logs(args.project, args.run) + + reports = _extract_reports(args.run, logs, report_name=args.report) + if not reports: + error_exit( + f"Report '{args.report}' not found in run '{args.run}' of project '{args.project}'." + ) + + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "report": args.report, + "values": reports, + } + ) + ) + else: + output = [] + for idx, entry in enumerate(reports, start=1): + output.append( + f"Entry {idx} | step={entry['step']} | timestamp={entry['timestamp']}" + ) + output.append(entry["content"]) + if idx < len(reports): + output.append("-" * 80) + print("\n".join(output)) + elif args.command == "query": + if args.query_type == "project": + _handle_query(args) + elif args.command == "skills": + if args.skills_action == "add": + _handle_skills_add(args) + elif args.command == "logbook": + _handle_logbook(args) + else: + parser.print_help() + + +def _sync_suffix(lb, proj): + if lb.is_autosync(proj): + space = lb.read_metadata(proj).get("space_id") + return f" · syncing to {space}…" + return "" + + +def _logbook_cell_target(lb, proj, args): + return lb.resolve_page(proj, getattr(args, "page", None)) + + +def _print_logbook_pages(pages): + if not pages: + print("No pages.") + return + print("Pages:") + for page in pages: + count = page["cell_count"] + print( + f"- {page['slug']} · {page['title']} · " + f"{count} cell{'' if count == 1 else 's'}" + ) + + +def _print_logbook_page_outline(page): + print(f"Page: {page['title']} ({page['slug']})") + if not page["cells"]: + print("No cells.") + return + for cell in page["cells"]: + created = ( + f" · {cell['created_at'].replace('T', ' ')[:16]}" + if cell.get("created_at") + else "" + ) + print(f"\n### {cell['title']} · {cell['type']} · {cell['id']}{created}") + if cell.get("preview"): + print(cell["preview"].rstrip()) + print( + "\nFetch full payloads with: trackio logbook read cell " + "[--full|--raw|--html]" + ) + + +def _print_logbook_cell(cell): + print(f"Cell: {cell['title']} ({cell['id']})") + print(f"Page: {cell['page_title']} ({cell['page']})") + print(f"Type: {cell['type']}") + if cell.get("created_at"): + print(f"Created: {cell['created_at']}") + content_keys = [key for key in ("body", "raw", "html") if key in cell] + if not content_keys: + if cell["type"] == "code": + print("\nBody omitted. Use --full to include code/output.") + elif cell["type"] == "figure": + print("\nFigure content omitted. Use --raw, --html, or --full.") + return + for key in content_keys: + label = key.upper() + print(f"\n--- {label} ---\n") + print(cell[key]) + + +def _read_logbook_payload(path_or_text, inline_text): + if inline_text is not None: + return inline_text + if not path_or_text: + return "" + path = Path(path_or_text) + if path.is_file(): + return path.read_text(encoding="utf-8") + return path_or_text + + +def _handle_logbook(args): + from trackio import logbook as lb + + action = args.logbook_action + try: + if action == "open": + print("Warning: Trackio Logbook is an experimental feature.") + proj = lb.find_project_dir() + if proj is not None: + if args.space_id: + metadata = lb.read_metadata(proj) + metadata["space_id"] = args.space_id + lb.write_metadata(proj, metadata) + print(f"Attached to existing logbook at {lb.logbook_root(proj)}") + if args.title: + print( + "Note: --title was ignored because this logbook already " + "exists. To retitle it, edit the '# ...' heading in " + f"{lb.logbook_root(proj) / 'pages' / 'index.md'}." + ) + elif args.space_id: + proj = lb.clone_logbook(args.space_id) + if proj is not None: + print( + f"Cloned logbook from {args.space_id} into " + f"{lb.logbook_root(proj)}" + ) + if proj is None: + proj = lb.create_logbook( + args.title or os.path.basename(os.getcwd()), space_id=args.space_id + ) + print(f"Opened logbook at {lb.logbook_root(proj)}") + if args.space_id: + print(f"Will publish to: {args.space_id}") + if not args.no_serve: + lb.start_preview(proj, port=args.port, open_browser=not args.no_browser) + elif action == "run": + proj = lb.require_project_dir() + command = list(args.command or []) + if command and command[0] == "--": + command = command[1:] + if not command: + error_exit("No command provided. Use: trackio logbook run -- ") + rc = lb.run_and_log( + proj, + command, + page=args.page, + title=args.title, + capture_artifacts=not getattr(args, "no_artifacts", False), + ) + slug = lb.read_metadata(proj).get("last_page", "?") + print(f"Logged run to page '{slug}'.{_sync_suffix(lb, proj)}") + sys.exit(rc) + elif action == "cell": + proj = lb.require_project_dir() + slug = _logbook_cell_target(lb, proj, args) + if args.cell_type == "markdown": + # Agent/tool callers often send a single argument containing + # escaped newlines. Treat those as Markdown line breaks while + # preserving normal shell-provided newlines unchanged. + body = args.body.replace("\\r\\n", "\n").replace("\\n", "\n") + lb.add_markdown_cell(proj, slug, body, title=args.title) + elif args.cell_type == "artifact": + lb.add_artifact_cell( + proj, + slug, + args.name, + title=args.title, + artifact_type=args.artifact_type, + ) + elif args.cell_type == "code": + lb.add_code_cell( + proj, + slug, + args.output, + title=args.title, + code_paths=args.code, + code_text=args.code_text, + language=args.language, + ) + elif args.cell_type == "figure": + if args.image: + html = lb.figure_html_from_image(args.image) + elif ( + args.html + and args.html_text is None + and Path(args.html).is_file() + and lb.is_figure_image_path(args.html) + ): + # `--html plot.png` — embed the image instead of trying to + # read a binary file as UTF-8 text. + html = lb.figure_html_from_image(args.html) + else: + html = _read_logbook_payload(args.html, args.html_text) + raw = _read_logbook_payload(args.raw, args.raw_text) + lb.add_figure_cell( + proj, + slug, + html=html, + raw=raw, + title=args.title, + ) + elif args.cell_type == "dashboard": + lb.add_dashboard_cell( + proj, + slug, + args.project, + space_id=args.space_id, + title=args.title, + ) + print( + f"Logged {args.cell_type} cell to page " + f"'{slug}'.{_sync_suffix(lb, proj)}" + ) + lb.trigger_autosync(proj) + elif action == "page": + proj = lb.require_project_dir() + page_slug = lb.ensure_page(proj, args.title) + print(f"Selected page '{page_slug}' as default.{_sync_suffix(lb, proj)}") + lb.trigger_autosync(proj) + elif action == "pin": + proj = lb.require_project_dir() + cell_id = args.cell_id or lb.last_cell_id(proj, page=args.page) + if not cell_id: + error_exit( + "No cell to pin. Pass a cell id, or add a cell first " + "(optionally scope with --page)." + ) + res = lb.set_cell_pinned( + proj, cell_id, pinned=not args.unpin, page=args.page + ) + verb = "Unpinned" if args.unpin else "Pinned" + print( + f"{verb} cell {cell_id} on page " + f"'{res['page']}'.{_sync_suffix(lb, proj)}" + ) + lb.trigger_autosync(proj) + elif action == "read": + proj = lb.resolve_read_source(args.path) + preview_opts = { + "head": lb.DEFAULT_HEAD + if getattr(args, "head", None) is None + else args.head, + "tail": lb.DEFAULT_TAIL + if getattr(args, "tail", None) is None + else args.tail, + "raw_limit": lb.DEFAULT_RAW_LIMIT + if getattr(args, "raw_limit", None) is None + else args.raw_limit, + } + if args.read_target is None: + if args.json: + print(format_json(lb.read_logbook_data(proj, **preview_opts))) + else: + print(lb.read_logbook(proj, **preview_opts)) + elif args.read_target == "pages": + pages = lb.list_pages(proj) + if args.json: + print(format_json({"pages": pages})) + else: + _print_logbook_pages(pages) + elif args.read_target == "page": + page = lb.read_page_outline(proj, args.page, **preview_opts) + if args.json: + print(format_json(page)) + else: + _print_logbook_page_outline(page) + elif args.read_target == "cell": + cell = lb.read_cell( + proj, + args.cell_id, + include_full=args.full, + include_raw=args.raw, + include_html=args.html, + ) + if args.json: + print(format_json(cell)) + else: + _print_logbook_cell(cell) + elif action == "_sync": + lb.sync_worker() + elif action == "sync-todos": + lb.sync_todos_from_stdin() + elif action == "serve": + lb.serve(path=args.path, port=args.port, open_browser=not args.no_browser) + elif action == "publish": + url = lb.publish(space_id=args.space_id, private=args.private) + print(f"Published: {url}") + space_id = lb.read_metadata(lb.require_project_dir()).get("space_id") + if space_id: + subdomain = re.sub(r"[^a-z0-9]+", "-", space_id.lower()).strip("-") + print(f"Rendered at: https://{subdomain}.static.hf.space/") + elif action == "sync": + proj = lb.require_project_dir() + if not lb.is_autosync(proj): + error_exit("Publish first: trackio logbook publish ") + lb.trigger_autosync(proj) + print(f"Syncing to {lb.read_metadata(proj).get('space_id')}…") + except lb.LogbookError as e: + error_exit(str(e)) + + +def _handle_skills_add(args): + import shutil + from pathlib import Path + + CENTRAL_LOCAL = Path(".agents/skills") + CENTRAL_GLOBAL = Path("~/.agents/skills") + CLAUDE_LOCAL = Path(".claude/skills") + CLAUDE_GLOBAL = Path("~/.claude/skills") + + SKILL_ID = "trackio" + GITHUB_RAW = "https://raw.githubusercontent.com/gradio-app/trackio/main" + SKILL_PREFIX = ".agents/skills/trackio" + SKILL_FILES = [ + "SKILL.md", + "alerts.md", + "logging_metrics.md", + "retrieving_metrics.md", + "storage_schema.md", + "logbook.md", + ] + COMMAND_PREFIX = ".agents/commands" + COMMAND_FILE = "logbook.md" + + REPO_ROOT = Path(__file__).resolve().parent.parent + USE_LOCAL = (REPO_ROOT / SKILL_PREFIX / "SKILL.md").is_file() + + if USE_LOCAL: + print(f"Using local Trackio source at {REPO_ROOT}") + + def download(url: str) -> str: + from huggingface_hub.utils import get_session + + try: + response = get_session().get(url) + response.raise_for_status() + except Exception as e: + error_exit( + f"Failed to download {url}\n{e}\n\n" + "Make sure you have internet access. The skill files are fetched from " + "the Trackio GitHub repository." + ) + return response.text + + def get_content(prefix: str, fname: str) -> str: + if USE_LOCAL: + local = REPO_ROOT / prefix / fname + if local.is_file(): + return local.read_text(encoding="utf-8") + return download(f"{GITHUB_RAW}/{prefix}/{fname}") + + def remove_existing(path: Path, force: bool): + if not (path.exists() or path.is_symlink()): + return + if not force: + error_exit( + f"Skill already exists at {path}.\nRe-run with --force to overwrite." + ) + if path.is_dir() and not path.is_symlink(): + shutil.rmtree(path) + else: + path.unlink() + + def install_to(skills_dir: Path, force: bool) -> Path: + skills_dir = skills_dir.expanduser().resolve() + skills_dir.mkdir(parents=True, exist_ok=True) + dest = skills_dir / SKILL_ID + remove_existing(dest, force) + dest.mkdir() + for fname in SKILL_FILES: + (dest / fname).write_text( + get_content(SKILL_PREFIX, fname), encoding="utf-8" + ) + return dest + + def create_symlink( + agent_skills_dir: Path, central_skill_path: Path, force: bool + ) -> Path: + agent_skills_dir = agent_skills_dir.expanduser().resolve() + agent_skills_dir.mkdir(parents=True, exist_ok=True) + link_path = agent_skills_dir / SKILL_ID + remove_existing(link_path, force) + link_path.symlink_to(os.path.relpath(central_skill_path, agent_skills_dir)) + return link_path + + def install_command( + command_dir: Path, force: bool, strip_frontmatter: bool = False + ) -> Path: + import re + + command_dir = command_dir.expanduser().resolve() + command_dir.mkdir(parents=True, exist_ok=True) + dest = command_dir / COMMAND_FILE + if dest.exists() and not force: + error_exit( + f"Command already exists at {dest}.\nRe-run with --force to overwrite." + ) + content = get_content(COMMAND_PREFIX, COMMAND_FILE) + if strip_frontmatter: + content = re.sub(r"\A---\n.*?\n---\n+", "", content, flags=re.S) + dest.write_text(content, encoding="utf-8") + return dest + + global_targets = { + "cursor": Path("~/.cursor/skills"), + "claude": CLAUDE_GLOBAL, + "codex": Path("~/.codex/skills"), + "opencode": Path("~/.opencode/skills"), + "pi": Path("~/.pi/agent/skills"), + } + local_targets = { + "cursor": Path(".cursor/skills"), + "claude": CLAUDE_LOCAL, + "codex": Path(".codex/skills"), + "opencode": Path(".opencode/skills"), + "pi": Path(".pi/skills"), + } + targets_dict = global_targets if args.global_ else local_targets + + command_targets_global = { + "cursor": Path("~/.cursor/commands"), + "claude": Path("~/.claude/commands"), + "codex": Path("~/.codex/prompts"), + "opencode": Path("~/.config/opencode/commands"), + "pi": Path("~/.pi/agent/prompts"), + } + command_targets_local = { + "cursor": Path(".cursor/commands"), + "claude": Path(".claude/commands"), + "codex": Path("~/.codex/prompts"), + "opencode": Path(".opencode/commands"), + "pi": Path(".pi/prompts"), + } + command_dict = command_targets_global if args.global_ else command_targets_local + COMMAND_NOTES = { + "codex": " (Codex only reads ~/.codex/prompts; restart Codex to pick it up)" + } + STRIP_FRONTMATTER = {"pi"} + + if args.dest: + if ( + args.cursor + or args.claude + or args.codex + or args.opencode + or args.pi + or args.global_ + ): + error_exit("--dest cannot be combined with agent flags or --global.") + skill_dest = install_to(Path(args.dest), args.force) + print(f"Installed '{SKILL_ID}' to {skill_dest}") + return + + selected = [ + name + for name, flag in ( + ("cursor", args.cursor), + ("claude", args.claude), + ("codex", args.codex), + ("opencode", args.opencode), + ("pi", args.pi), + ) + if flag + ] + + central_path = CENTRAL_GLOBAL if args.global_ else CENTRAL_LOCAL + central_skill_path = install_to(central_path, args.force) + print(f"Installed '{SKILL_ID}' to central location: {central_skill_path}") + + for name in selected: + link_path = create_symlink(targets_dict[name], central_skill_path, args.force) + print(f"Created symlink: {link_path}") + + if not args.no_command: + for name in selected: + if name in command_dict: + cmd_path = install_command( + command_dict[name], + args.force, + strip_frontmatter=name in STRIP_FRONTMATTER, + ) + note = COMMAND_NOTES.get(name, "") + print(f"Installed '/logbook' command: {cmd_path}{note}") + else: + print( + f"Skipped '/logbook' command for {name} " + "(no slash-command directory convention)." + ) + + if args.claude and not args.no_hook: + hook_path = _install_claude_logbook_hook(args.global_) + if hook_path: + print(f"Installed logbook todo-sync hook: {hook_path}") + + +def _install_claude_logbook_hook(global_: bool): + import json + from pathlib import Path + + settings = ( + Path("~/.claude/settings.json") if global_ else Path(".claude/settings.json") + ).expanduser() + settings.parent.mkdir(parents=True, exist_ok=True) + data = {} + if settings.exists(): + try: + data = json.loads(settings.read_text(encoding="utf-8")) + except Exception: + print(f"Could not parse {settings}; skipping hook install.") + return None + command = "trackio logbook sync-todos" + hooks = data.setdefault("hooks", {}) + post = hooks.setdefault("PostToolUse", []) + for entry in post: + for h in entry.get("hooks", []): + if h.get("command") == command: + return settings + post.append( + { + "matcher": "TodoWrite", + "hooks": [{"type": "command", "command": command}], + } + ) + settings.write_text(json.dumps(data, indent=2), encoding="utf-8") + return settings + + +if __name__ == "__main__": + main() diff --git a/trackio/cli_helpers.py b/trackio/cli_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..dd27ae5278561dd09a52e309de0c3a5abf82f70b --- /dev/null +++ b/trackio/cli_helpers.py @@ -0,0 +1,268 @@ +import json +import sys +from typing import Any + +from trackio import references + + +def format_json(data: Any) -> str: + """Format data as JSON.""" + return json.dumps(data, indent=2) + + +def format_list(items: list[str], title: str | None = None) -> str: + """Format a list of items in human-readable format.""" + if not items: + return f"No {title.lower() if title else 'items'} found." + + output = [] + if title: + output.append(f"{title}:") + + for item in items: + output.append(f" - {item}") + + return "\n".join(output) + + +def format_artifacts(artifacts: list[dict], project: str | None = None) -> str: + """Format a project's artifacts in human-readable format.""" + if not artifacts: + return "No artifacts found." + + title = f"Artifacts in '{project}'" if project else "Artifacts" + output = [f"{title}:"] + for art in artifacts: + latest = art.get("latest_version") + version = f"v{latest}" if latest is not None else "(no versions)" + aliases = art.get("aliases") or [] + alias_str = f" [{', '.join(aliases)}]" if aliases else "" + output.append( + f" - {art['name']} ({art.get('type', '?')}) " + f"latest={version}{alias_str} " + f"versions={art.get('num_versions', 0)}" + ) + if art.get("description"): + output.append(f" {art['description']}") + return "\n".join(output) + + +def format_artifact(record: dict) -> str: + """Format a single resolved artifact version in human-readable format.""" + lines = [ + f"Artifact: {record['name']} (v{record['version']})", + f" type: {record.get('type')}", + ] + if record.get("description"): + lines.append(f" description: {record['description']}") + aliases = record.get("aliases") or [] + if aliases: + lines.append(f" aliases: {', '.join(aliases)}") + if record.get("metadata"): + lines.append(f" metadata: {record['metadata']}") + lines.append(f" size: {record.get('size_bytes')} bytes") + lines.append(f" digest: {record.get('manifest_digest')}") + manifest = record.get("manifest") or [] + lines.append(f" files ({len(manifest)}):") + for entry in manifest: + if references.is_reference_entry(entry): + lines.append(f" - {entry['path']} -> {entry['ref']} (reference)") + else: + lines.append(f" - {entry['path']} ({entry['size']} bytes)") + return "\n".join(lines) + + +def format_spaces(spaces: list[dict]) -> str: + """Format HF Spaces in human-readable format.""" + if not spaces: + return "No Trackio Spaces found." + + output = ["Trackio Spaces:"] + for space in spaces: + visibility = "private" if space.get("private") else "public" + output.append(f" - {space['id']} ({visibility})") + if space.get("url"): + output.append(f" {space['url']}") + + return "\n".join(output) + + +def format_project_summary(summary: dict) -> str: + """Format project summary in human-readable format.""" + output = [f"Project: {summary['project']}"] + output.append(f"Number of runs: {summary['num_runs']}") + + if summary["runs"]: + output.append("\nRuns:") + for run in summary["runs"]: + output.append(f" - {run}") + else: + output.append("\nNo runs found.") + + if summary.get("last_activity"): + output.append(f"\nLast activity (max step): {summary['last_activity']}") + + return "\n".join(output) + + +def format_run_summary(summary: dict) -> str: + """Format run summary in human-readable format.""" + output = [f"Project: {summary['project']}"] + output.append(f"Run: {summary['run']}") + output.append(f"Number of logs: {summary['num_logs']}") + + if summary.get("last_step") is not None: + output.append(f"Last step: {summary['last_step']}") + + if summary.get("metrics"): + output.append("\nMetrics:") + for metric in summary["metrics"]: + output.append(f" - {metric}") + else: + output.append("\nNo metrics found.") + + config = summary.get("config") + if config: + output.append("\nConfig:") + config_display = {k: v for k, v in config.items() if not k.startswith("_")} + if config_display: + for key, value in config_display.items(): + output.append(f" {key}: {value}") + else: + output.append(" (no config)") + else: + output.append("\nConfig: (no config)") + + return "\n".join(output) + + +def format_metric_values(values: list[dict]) -> str: + """Format metric values in human-readable format.""" + if not values: + return "No metric values found." + + output = [f"Found {len(values)} value(s):\n"] + output.append("Step | Timestamp | Value") + output.append("-" * 50) + + for value in values: + step = value.get("step", "N/A") + timestamp = value.get("timestamp", "N/A") + val = value.get("value", "N/A") + output.append(f"{step} | {timestamp} | {val}") + + return "\n".join(output) + + +def format_system_metrics(metrics: list[dict]) -> str: + """Format system metrics in human-readable format.""" + if not metrics: + return "No system metrics found." + + output = [f"Found {len(metrics)} system metric entry/entries:\n"] + + for i, entry in enumerate(metrics): + timestamp = entry.get("timestamp", "N/A") + output.append(f"\nEntry {i + 1} (Timestamp: {timestamp}):") + for key, value in entry.items(): + if key != "timestamp": + output.append(f" {key}: {value}") + + return "\n".join(output) + + +def format_system_metric_names(names: list[str]) -> str: + """Format system metric names in human-readable format.""" + return format_list(names, "System Metrics") + + +def format_snapshot(snapshot: dict[str, list[dict]]) -> str: + """Format a metrics snapshot in human-readable format.""" + if not snapshot: + return "No metrics found in the specified range." + + output = [] + for metric_name, values in sorted(snapshot.items()): + output.append(f"\n{metric_name}:") + output.append(" Step | Timestamp | Value") + output.append(" " + "-" * 48) + for v in values: + step = v.get("step", "N/A") + ts = v.get("timestamp", "N/A") + val = v.get("value", "N/A") + output.append(f" {step} | {ts} | {val}") + + return "\n".join(output) + + +def format_alerts(alerts: list[dict]) -> str: + """Format alerts in human-readable format.""" + if not alerts: + return "No alerts found." + + output = [f"Found {len(alerts)} alert(s):\n"] + output.append("Timestamp | Run | Level | Title | Text | Step") + output.append("-" * 80) + + for a in alerts: + ts = a.get("timestamp", "N/A") + run = a.get("run", "N/A") + level = a.get("level", "N/A").upper() + title = a.get("title", "") + text = a.get("text", "") or "" + step = a.get("step", "N/A") + output.append(f"{ts} | {run} | {level} | {title} | {text} | {step}") + + return "\n".join(output) + + +def format_query_result(result: dict[str, Any]) -> str: + """Format SQL query results in human-readable format.""" + columns = result.get("columns", []) + rows = result.get("rows", []) + row_count = result.get("row_count", 0) + + if not columns: + return f"Query returned {row_count} row(s)." + + rendered_rows = [] + for row in rows: + rendered_rows.append( + [ + "" if row.get(column) is None else str(row.get(column)) + for column in columns + ] + ) + + widths = [] + for idx, column in enumerate(columns): + cell_width = max( + (len(rendered_row[idx]) for rendered_row in rendered_rows), default=0 + ) + widths.append(max(len(column), cell_width)) + + header = " | ".join( + column.ljust(width) for column, width in zip(columns, widths, strict=False) + ) + separator = "-+-".join("-" * width for width in widths) + output = [f"Query returned {row_count} row(s).", header, separator] + + if not rendered_rows: + output.append("(no rows)") + return "\n".join(output) + + for rendered_row in rendered_rows: + output.append( + " | ".join( + value.ljust(width) + for value, width in zip(rendered_row, widths, strict=False) + ) + ) + + return "\n".join(output) + + +def error_exit(message: str, code: int = 1) -> None: + """Print error message and exit.""" + print(f"Error: {message}", file=sys.stderr) + sys.exit(code) diff --git a/trackio/commit_scheduler.py b/trackio/commit_scheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..2e1cbabc2f9e576def2332cd4fbdc5788828ace6 --- /dev/null +++ b/trackio/commit_scheduler.py @@ -0,0 +1,310 @@ +# Originally copied from https://github.com/huggingface/huggingface_hub/blob/d0a948fc2a32ed6e557042a95ef3e4af97ec4a7c/src/huggingface_hub/_commit_scheduler.py + +import atexit +import logging +import time +from concurrent.futures import Future +from dataclasses import dataclass +from pathlib import Path +from threading import Lock, Thread +from typing import Callable, Dict, List, Union + +from huggingface_hub.hf_api import ( + DEFAULT_IGNORE_PATTERNS, + CommitInfo, + CommitOperationAdd, + HfApi, +) +from huggingface_hub.utils import filter_repo_objects + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class _FileToUpload: + """Temporary dataclass to store info about files to upload. Not meant to be used directly.""" + + local_path: Path + path_in_repo: str + size_limit: int + last_modified: float + + +class CommitScheduler: + """ + Scheduler to upload a local folder to the Hub at regular intervals (e.g. push to hub every 5 minutes). + + The recommended way to use the scheduler is to use it as a context manager. This ensures that the scheduler is + properly stopped and the last commit is triggered when the script ends. The scheduler can also be stopped manually + with the `stop` method. Checkout the [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#scheduled-uploads) + to learn more about how to use it. + + Args: + repo_id (`str`): + The id of the repo to commit to. + folder_path (`str` or `Path`): + Path to the local folder to upload regularly. + every (`int` or `float`, *optional*): + The number of minutes between each commit. Defaults to 5 minutes. + path_in_repo (`str`, *optional*): + Relative path of the directory in the repo, for example: `"checkpoints/"`. Defaults to the root folder + of the repository. + repo_type (`str`, *optional*): + The type of the repo to commit to. Defaults to `model`. + revision (`str`, *optional*): + The revision of the repo to commit to. Defaults to `main`. + private (`bool`, *optional*): + Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. + token (`str`, *optional*): + The token to use to commit to the repo. Defaults to the token saved on the machine. + allow_patterns (`List[str]` or `str`, *optional*): + If provided, only files matching at least one pattern are uploaded. + ignore_patterns (`List[str]` or `str`, *optional*): + If provided, files matching any of the patterns are not uploaded. + squash_history (`bool`, *optional*): + Whether to squash the history of the repo after each commit. Defaults to `False`. Squashing commits is + useful to avoid degraded performances on the repo when it grows too large. + hf_api (`HfApi`, *optional*): + The [`HfApi`] client to use to commit to the Hub. Can be set with custom settings (user agent, token,...). + on_before_commit (`Callable[[], None]`, *optional*): + If specified, a function that will be called before the CommitScheduler lists files to create a commit. + + Example: + ```py + >>> from pathlib import Path + >>> from huggingface_hub import CommitScheduler + + # Scheduler uploads every 10 minutes + >>> csv_path = Path("watched_folder/data.csv") + >>> CommitScheduler(repo_id="test_scheduler", repo_type="dataset", folder_path=csv_path.parent, every=10) + + >>> with csv_path.open("a") as f: + ... f.write("first line") + + # Some time later (...) + >>> with csv_path.open("a") as f: + ... f.write("second line") + ``` + + Example using a context manager: + ```py + >>> from pathlib import Path + >>> from huggingface_hub import CommitScheduler + + >>> with CommitScheduler(repo_id="test_scheduler", repo_type="dataset", folder_path="watched_folder", every=10) as scheduler: + ... csv_path = Path("watched_folder/data.csv") + ... with csv_path.open("a") as f: + ... f.write("first line") + ... (...) + ... with csv_path.open("a") as f: + ... f.write("second line") + + # Scheduler is now stopped and last commit have been triggered + ``` + """ + + def __init__( + self, + *, + repo_id: str, + folder_path: Union[str, Path], + every: Union[int, float] = 5, + path_in_repo: str | None = None, + repo_type: str | None = None, + revision: str | None = None, + private: bool | None = None, + token: str | None = None, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + squash_history: bool = False, + hf_api: HfApi | None = None, + on_before_commit: Callable[[], None] | None = None, + ) -> None: + self.api = hf_api or HfApi(token=token) + self.on_before_commit = on_before_commit + + # Folder + self.folder_path = Path(folder_path).expanduser().resolve() + self.path_in_repo = path_in_repo or "" + self.allow_patterns = allow_patterns + + if ignore_patterns is None: + ignore_patterns = [] + elif isinstance(ignore_patterns, str): + ignore_patterns = [ignore_patterns] + self.ignore_patterns = ignore_patterns + DEFAULT_IGNORE_PATTERNS + + if self.folder_path.is_file(): + raise ValueError( + f"'folder_path' must be a directory, not a file: '{self.folder_path}'." + ) + self.folder_path.mkdir(parents=True, exist_ok=True) + + # Repository + repo_url = self.api.create_repo( + repo_id=repo_id, private=private, repo_type=repo_type, exist_ok=True + ) + self.repo_id = repo_url.repo_id + self.repo_type = repo_type + self.revision = revision + self.token = token + + self.last_uploaded: Dict[Path, float] = {} + self.last_push_time: float | None = None + + if not every > 0: + raise ValueError(f"'every' must be a positive integer, not '{every}'.") + self.lock = Lock() + self.every = every + self.squash_history = squash_history + + logger.info( + f"Scheduled job to push '{self.folder_path}' to '{self.repo_id}' every {self.every} minutes." + ) + self._scheduler_thread = Thread(target=self._run_scheduler, daemon=True) + self._scheduler_thread.start() + atexit.register(self._push_to_hub) + + self.__stopped = False + + def stop(self) -> None: + """Stop the scheduler. + + A stopped scheduler cannot be restarted. Mostly for tests purposes. + """ + self.__stopped = True + + def __enter__(self) -> "CommitScheduler": + return self + + def __exit__(self, exc_type, exc_value, traceback) -> None: + # Upload last changes before exiting + self.trigger().result() + self.stop() + return + + def _run_scheduler(self) -> None: + """Dumb thread waiting between each scheduled push to Hub.""" + while True: + self.last_future = self.trigger() + time.sleep(self.every * 60) + if self.__stopped: + break + + def trigger(self) -> Future: + """Trigger a `push_to_hub` and return a future. + + This method is automatically called every `every` minutes. You can also call it manually to trigger a commit + immediately, without waiting for the next scheduled commit. + """ + return self.api.run_as_future(self._push_to_hub) + + def _push_to_hub(self) -> CommitInfo | None: + if self.__stopped: # If stopped, already scheduled commits are ignored + return None + + logger.info("(Background) scheduled commit triggered.") + try: + value = self.push_to_hub() + if self.squash_history: + logger.info("(Background) squashing repo history.") + self.api.super_squash_history( + repo_id=self.repo_id, repo_type=self.repo_type, branch=self.revision + ) + return value + except Exception as e: + logger.error( + f"Error while pushing to Hub: {e}" + ) # Depending on the setup, error might be silenced + raise + + def push_to_hub(self) -> CommitInfo | None: + """ + Push folder to the Hub and return the commit info. + + + + This method is not meant to be called directly. It is run in the background by the scheduler, respecting a + queue mechanism to avoid concurrent commits. Making a direct call to the method might lead to concurrency + issues. + + + + The default behavior of `push_to_hub` is to assume an append-only folder. It lists all files in the folder and + uploads only changed files. If no changes are found, the method returns without committing anything. If you want + to change this behavior, you can inherit from [`CommitScheduler`] and override this method. This can be useful + for example to compress data together in a single file before committing. For more details and examples, check + out our [integration guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/upload#scheduled-uploads). + """ + # Check files to upload (with lock) + with self.lock: + if self.on_before_commit is not None: + self.on_before_commit() + + logger.debug("Listing files to upload for scheduled commit.") + + # List files from folder (taken from `_prepare_upload_folder_additions`) + relpath_to_abspath = { + path.relative_to(self.folder_path).as_posix(): path + for path in sorted( + self.folder_path.glob("**/*") + ) # sorted to be deterministic + if path.is_file() + } + prefix = f"{self.path_in_repo.strip('/')}/" if self.path_in_repo else "" + + # Filter with pattern + filter out unchanged files + retrieve current file size + files_to_upload: List[_FileToUpload] = [] + for relpath in filter_repo_objects( + relpath_to_abspath.keys(), + allow_patterns=self.allow_patterns, + ignore_patterns=self.ignore_patterns, + ): + local_path = relpath_to_abspath[relpath] + stat = local_path.stat() + if ( + self.last_uploaded.get(local_path) is None + or self.last_uploaded[local_path] != stat.st_mtime + ): + files_to_upload.append( + _FileToUpload( + local_path=local_path, + path_in_repo=prefix + relpath, + size_limit=stat.st_size, + last_modified=stat.st_mtime, + ) + ) + + # Return if nothing to upload + if len(files_to_upload) == 0: + logger.debug("Dropping schedule commit: no changed file to upload.") + return None + + # Convert `_FileToUpload` as `CommitOperationAdd` (=> compute file shas + limit to file size) + logger.debug("Removing unchanged files since previous scheduled commit.") + add_operations = [ + CommitOperationAdd( + # TODO: Cap the file to its current size, even if the user append data to it while a scheduled commit is happening + # (requires an upstream fix for XET-535: `hf_xet` should support `BinaryIO` for upload) + path_or_fileobj=file_to_upload.local_path, + path_in_repo=file_to_upload.path_in_repo, + ) + for file_to_upload in files_to_upload + ] + + # Upload files (append mode expected - no need for lock) + logger.debug("Uploading files for scheduled commit.") + commit_info = self.api.create_commit( + repo_id=self.repo_id, + repo_type=self.repo_type, + operations=add_operations, + commit_message="Scheduled Commit", + revision=self.revision, + ) + + for file in files_to_upload: + self.last_uploaded[file.local_path] = file.last_modified + + self.last_push_time = time.time() + + return commit_info diff --git a/trackio/compression.py b/trackio/compression.py new file mode 100644 index 0000000000000000000000000000000000000000..a6b0a59e46d56237c6cc5da742cfb653fd72648a --- /dev/null +++ b/trackio/compression.py @@ -0,0 +1,169 @@ +from __future__ import annotations + +import gzip +import io +from typing import NoReturn + +from starlette.datastructures import Headers, MutableHeaders +from starlette.types import ASGIApp, Message, Receive, Scope, Send + +try: + import brotli + + HAS_BROTLI = True +except ImportError: + brotli = None + HAS_BROTLI = False + +COMPRESSIBLE_CONTENT_TYPES = ( + "application/json", + "application/javascript", + "application/manifest+json", + "application/xml", + "application/xhtml+xml", + "image/svg+xml", + "text/", +) + + +class CompressionMiddleware: + """Negotiates Brotli, then gzip, then identity based on Accept-Encoding. + + Only text-like content types are compressed, so already-compressed media + (images, audio, video) and zero-copy file sends pass through untouched. + """ + + def __init__( + self, + app: ASGIApp, + minimum_size: int = 512, + gzip_level: int = 6, + brotli_quality: int = 5, + ) -> None: + self.app = app + self.minimum_size = minimum_size + self.gzip_level = gzip_level + self.brotli_quality = brotli_quality + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + accept_encoding = Headers(scope=scope).get("Accept-Encoding", "") + responder: _CompressionResponder + if HAS_BROTLI and "br" in accept_encoding: + responder = _BrotliResponder( + self.app, self.minimum_size, self.brotli_quality + ) + elif "gzip" in accept_encoding: + responder = _GZipResponder(self.app, self.minimum_size, self.gzip_level) + else: + responder = _CompressionResponder(self.app, self.minimum_size) + + await responder(scope, receive, send) + + +class _CompressionResponder: + content_encoding: str = "" + + def __init__(self, app: ASGIApp, minimum_size: int) -> None: + self.app = app + self.minimum_size = minimum_size + self.send: Send = _unattached_send + self.initial_message: Message = {} + self.started = False + self.passthrough = True + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + self.send = send + await self.app(scope, receive, self.send_with_compression) + + async def send_with_compression(self, message: Message) -> None: + message_type = message["type"] + if message_type == "http.response.start": + self.initial_message = message + headers = Headers(raw=message["headers"]) + content_type = headers.get("content-type", "") + already_encoded = "content-encoding" in headers + self.passthrough = already_encoded or not content_type.startswith( + COMPRESSIBLE_CONTENT_TYPES + ) + elif message_type == "http.response.body" and self.passthrough: + if not self.started: + self.started = True + await self.send(self.initial_message) + await self.send(message) + elif message_type == "http.response.body" and not self.started: + self.started = True + body = message.get("body", b"") + more_body = message.get("more_body", False) + if len(body) < self.minimum_size and not more_body: + await self.send(self.initial_message) + await self.send(message) + else: + compressed = self.apply_compression(body, more_body=more_body) + headers = MutableHeaders(raw=self.initial_message["headers"]) + headers.add_vary_header("Accept-Encoding") + if compressed != body: + headers["Content-Encoding"] = self.content_encoding + if more_body: + del headers["Content-Length"] + else: + headers["Content-Length"] = str(len(compressed)) + message["body"] = compressed + await self.send(self.initial_message) + await self.send(message) + elif message_type == "http.response.body": + body = message.get("body", b"") + more_body = message.get("more_body", False) + message["body"] = self.apply_compression(body, more_body=more_body) + await self.send(message) + elif message_type == "http.response.pathsend": + await self.send(self.initial_message) + await self.send(message) + + def apply_compression(self, body: bytes, *, more_body: bool) -> bytes: + return body + + +class _GZipResponder(_CompressionResponder): + content_encoding = "gzip" + + def __init__(self, app: ASGIApp, minimum_size: int, compresslevel: int) -> None: + super().__init__(app, minimum_size) + self.buffer = io.BytesIO() + self.file = gzip.GzipFile( + mode="wb", fileobj=self.buffer, compresslevel=compresslevel + ) + + async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + with self.buffer, self.file: + await super().__call__(scope, receive, send) + + def apply_compression(self, body: bytes, *, more_body: bool) -> bytes: + self.file.write(body) + if not more_body: + self.file.close() + data = self.buffer.getvalue() + self.buffer.seek(0) + self.buffer.truncate() + return data + + +class _BrotliResponder(_CompressionResponder): + content_encoding = "br" + + def __init__(self, app: ASGIApp, minimum_size: int, quality: int) -> None: + super().__init__(app, minimum_size) + self.compressor = brotli.Compressor(quality=quality) + + def apply_compression(self, body: bytes, *, more_body: bool) -> bytes: + data = self.compressor.process(body) + if not more_body: + data += self.compressor.finish() + return data + + +async def _unattached_send(message: Message) -> NoReturn: + raise RuntimeError("send awaitable not set") diff --git a/trackio/context_vars.py b/trackio/context_vars.py new file mode 100644 index 0000000000000000000000000000000000000000..ef1404001b8856446ec2940eee81578d634a51fd --- /dev/null +++ b/trackio/context_vars.py @@ -0,0 +1,21 @@ +import contextvars +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from trackio.run import Run + +current_run: contextvars.ContextVar["Run | None"] = contextvars.ContextVar( + "current_run", default=None +) +current_project: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_project", default=None +) +current_server: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_server", default=None +) +current_space_id: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_space_id", default=None +) +current_server_write_token: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_server_write_token", default=None +) diff --git a/trackio/cpu.py b/trackio/cpu.py new file mode 100644 index 0000000000000000000000000000000000000000..e11274786d1f17d7d5415286f2fd79a96f7ae2dc --- /dev/null +++ b/trackio/cpu.py @@ -0,0 +1,303 @@ +import importlib +import threading +import time +import warnings +from typing import TYPE_CHECKING, Any + +from trackio import context_vars + +if TYPE_CHECKING: + from trackio.run import Run + +psutil: Any = None +PSUTIL_AVAILABLE = False +_psutil_lock = threading.Lock() + + +def _ensure_psutil(): + global PSUTIL_AVAILABLE, psutil + if PSUTIL_AVAILABLE: + return psutil + with _psutil_lock: + if PSUTIL_AVAILABLE: + return psutil + try: + psutil = importlib.import_module("psutil") + PSUTIL_AVAILABLE = True + return psutil + except ImportError: + raise ImportError( + "psutil is required for CPU and RAM monitoring. " + "Install it with: pip install psutil" + ) + + +def cpu_available() -> bool: + """ + Check if CPU and RAM monitoring is available. + + Returns True if psutil is installed. + """ + try: + _ensure_psutil() + return True + except ImportError: + return False + except Exception: + return False + + +def collect_cpu_metrics( + prev_disk_counters: Any = None, + prev_net_counters: Any = None, + elapsed: float | None = None, + include_static: bool = True, +) -> dict: + """ + Collect CPU, RAM, disk, network, and sensor metrics using psutil. + + Args: + prev_disk_counters: Previous disk I/O counters for computing read/write rates. + If None, only cumulative values are reported. + prev_net_counters: Previous network I/O counters for computing send/recv rates. + If None, only cumulative values are reported. + elapsed: Seconds since prev_disk_counters and prev_net_counters were captured. + If None or non-positive, cumulative values are reported instead of rates. + include_static: Whether to include mostly static metrics such as CPU + frequency and core counts. + + Returns: + Dictionary of system metrics. + """ + if not PSUTIL_AVAILABLE: + try: + _ensure_psutil() + except ImportError: + return {} + + metrics = {} + + try: + per_core = psutil.cpu_percent(interval=0.1, percpu=True) + for i, pct in enumerate(per_core): + metrics[f"cpu/{i}/utilization"] = pct + if per_core: + metrics["cpu/utilization"] = sum(per_core) / len(per_core) + except Exception: + pass + + if include_static: + try: + cpu_freq = psutil.cpu_freq() + if cpu_freq: + metrics["cpu/frequency"] = cpu_freq.current + if cpu_freq.max > 0: + metrics["cpu/frequency_max"] = cpu_freq.max + except Exception: + pass + + try: + cpu_count_logical = psutil.cpu_count(logical=True) + if cpu_count_logical is not None: + metrics["cpu/count_logical"] = cpu_count_logical + cpu_count_physical = psutil.cpu_count(logical=False) + if cpu_count_physical is not None: + metrics["cpu/count_physical"] = cpu_count_physical + except Exception: + pass + + try: + mem = psutil.virtual_memory() + metrics["memory/used"] = mem.used / (1024**3) + metrics["memory/total"] = mem.total / (1024**3) + metrics["memory/available"] = mem.available / (1024**3) + metrics["memory/percent"] = mem.percent + except Exception: + pass + + try: + swap = psutil.swap_memory() + metrics["swap/used"] = swap.used / (1024**3) + metrics["swap/total"] = swap.total / (1024**3) + metrics["swap/percent"] = swap.percent + except Exception: + pass + + try: + disk = psutil.disk_io_counters() + if disk is not None: + if prev_disk_counters is not None and elapsed and elapsed > 0: + metrics["disk/read_mb_per_sec"] = ( + (disk.read_bytes - prev_disk_counters.read_bytes) + / elapsed + / (1024**2) + ) + metrics["disk/write_mb_per_sec"] = ( + (disk.write_bytes - prev_disk_counters.write_bytes) + / elapsed + / (1024**2) + ) + metrics["disk/read_iops"] = ( + disk.read_count - prev_disk_counters.read_count + ) / elapsed + metrics["disk/write_iops"] = ( + disk.write_count - prev_disk_counters.write_count + ) / elapsed + else: + metrics["disk/read_bytes"] = disk.read_bytes + metrics["disk/write_bytes"] = disk.write_bytes + except Exception: + pass + + try: + net = psutil.net_io_counters() + if net is not None: + if prev_net_counters is not None and elapsed and elapsed > 0: + metrics["network/sent_mb_per_sec"] = ( + (net.bytes_sent - prev_net_counters.bytes_sent) + / elapsed + / (1024**2) + ) + metrics["network/recv_mb_per_sec"] = ( + (net.bytes_recv - prev_net_counters.bytes_recv) + / elapsed + / (1024**2) + ) + else: + metrics["network/sent_bytes"] = net.bytes_sent + metrics["network/recv_bytes"] = net.bytes_recv + except Exception: + pass + + try: + sensors = psutil.sensors_temperatures() + if sensors: + for chip_name, entries in sensors.items(): + for i, entry in enumerate(entries): + label = ( + entry.label.strip() + if entry.label and entry.label.strip() + else f"{chip_name}_{i}" + ) + metrics[f"temp/{label}"] = entry.current + except Exception: + pass + + try: + battery = psutil.sensors_battery() + if battery is not None: + metrics["battery/percent"] = battery.percent + metrics["battery/power_plugged"] = int(battery.power_plugged) + except Exception: + pass + + return metrics + + +class CpuMonitor: + def __init__(self, run: "Run", interval: float = 10.0): + self._run = run + self._interval = interval + self._stop_flag = threading.Event() + self._thread: "threading.Thread | None" = None + self._last_disk_counters: Any = None + self._last_net_counters: Any = None + self._last_time: float | None = None + self._include_static_next = True + + def start(self): + if not PSUTIL_AVAILABLE: + try: + _ensure_psutil() + except ImportError: + warnings.warn( + "auto_log_cpu=True but psutil is not installed. " + "CPU and RAM logging disabled. Install with: pip install psutil" + ) + return + + self._thread = threading.Thread(target=self._monitor_loop, daemon=True) + self._thread.start() + + def stop(self): + self._stop_flag.set() + if self._thread is not None: + self._thread.join(timeout=2.0) + + def _monitor_loop(self): + try: + self._last_disk_counters = psutil.disk_io_counters() + except Exception: + pass + try: + self._last_net_counters = psutil.net_io_counters() + except Exception: + pass + self._last_time = time.monotonic() + + while not self._stop_flag.is_set(): + self._stop_flag.wait(timeout=self._interval) + if self._stop_flag.is_set(): + break + try: + now = time.monotonic() + elapsed = now - self._last_time if self._last_time is not None else None + metrics = collect_cpu_metrics( + prev_disk_counters=self._last_disk_counters, + prev_net_counters=self._last_net_counters, + elapsed=elapsed, + include_static=self._include_static_next, + ) + self._include_static_next = False + try: + self._last_disk_counters = psutil.disk_io_counters() + except Exception: + self._last_disk_counters = None + try: + self._last_net_counters = psutil.net_io_counters() + except Exception: + self._last_net_counters = None + self._last_time = now + if metrics: + self._run.log_system(metrics) + except Exception: + pass + + +def log_cpu(run: "Run | None" = None) -> dict: + """ + Log CPU, RAM, disk, network, and sensor metrics to the current or specified run + as system metrics. + + Args: + run: Optional Run instance. If None, uses current run from context. + + Returns: + dict: The system metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_cpu() + ``` + """ + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_cpu().") + + try: + _ensure_psutil() + except ImportError: + warnings.warn( + "trackio.log_cpu() requires psutil. Install it with: pip install trackio[cpu]" + ) + return {} + + metrics = collect_cpu_metrics() + if metrics: + run.log_system(metrics) + return metrics diff --git a/trackio/deploy.py b/trackio/deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..d463fee1d34a69818f69212ef7a4471ef7fe8516 --- /dev/null +++ b/trackio/deploy.py @@ -0,0 +1,1313 @@ +import importlib.metadata +import io +import json as json_mod +import os +import tempfile +import threading +import time +import warnings +from collections import Counter +from importlib.resources import files +from pathlib import Path + +import httpx +import huggingface_hub +from gradio_client import handle_file +from httpx import ReadTimeout +from huggingface_hub import Volume +from huggingface_hub.errors import ( + BucketNotFoundError, + HfHubHTTPError, + RepositoryNotFoundError, +) + +import trackio +from trackio.bucket_storage import ( + create_bucket_if_not_exists, + export_from_bucket_for_static, + upload_project_to_bucket, + upload_project_to_bucket_for_static, +) +from trackio.cas import PARTIAL_BLOB_GLOB +from trackio.frontend_config import resolve_frontend_dir +from trackio.pending_uploads import replay_pending_uploads +from trackio.remote_client import RemoteClient +from trackio.sqlite_storage import SQLiteStorage +from trackio.utils import ( + get_or_create_project_hash, + on_spaces, + preprocess_space_and_dataset_ids, + project_artifacts_dir, + project_media_dir, +) + +SPACE_HOST_URL = "https://{user_name}-{space_name}.hf.space/" +SPACE_URL = "https://huggingface.co/spaces/{space_id}" +_BOLD_ORANGE = "\033[1m\033[38;5;208m" +_RESET = "\033[0m" + + +def raise_if_space_is_frozen_for_logging(space_id: str) -> None: + try: + info = huggingface_hub.HfApi().space_info(space_id) + except RepositoryNotFoundError: + return + if getattr(info, "sdk", None) == "static": + raise RuntimeError( + f"Cannot log to Hugging Face Space '{space_id}' because it has been frozen " + f"(it uses the static SDK: a read-only dashboard with no live Trackio server).\n\n" + f"Use a different space_id for training, or create a new Gradio Trackio Space. " + f"Freezing converts a live Gradio Space to static after a run; a frozen Space " + f'cannot accept new logs. See trackio.sync(..., sdk="static") in the Trackio docs.' + ) + + +def _readme_linked_hub_yaml(dataset_id: str | None) -> str: + if dataset_id is not None: + return f"datasets:\n - {dataset_id}\n" + return "" + + +_CUSTOM_SPACE_FRONTEND_DIR = "trackio_custom_frontend" + + +def _space_app_py(frontend_dir: str | None = None) -> str: + if frontend_dir is None: + return "import trackio\ntrackio.show()\n" + return f'import trackio\ntrackio.show(frontend_dir="{frontend_dir}")\n' + + +def _upload_frontend_folder( + hf_api: huggingface_hub.HfApi, + *, + repo_id: str, + repo_type: str, + folder_path: str | Path, + path_in_repo: str | None = None, +) -> None: + kwargs = { + "repo_id": repo_id, + "repo_type": repo_type, + "folder_path": str(folder_path), + } + if path_in_repo is not None: + kwargs["path_in_repo"] = path_in_repo + hf_api.upload_folder(**kwargs) + + +def _retry_hf_write(op_name: str, fn, retries: int = 4, initial_delay: float = 1.5): + delay = initial_delay + for attempt in range(1, retries + 1): + try: + return fn() + except ReadTimeout: + if attempt == retries: + raise + print( + f"* {op_name} timed out (attempt {attempt}/{retries}). Retrying in {delay:.1f}s..." + ) + time.sleep(delay) + delay = min(delay * 2, 12) + except HfHubHTTPError as e: + status = e.response.status_code if e.response is not None else None + if status is None or status < 500 or attempt == retries: + raise + print( + f"* {op_name} failed with HTTP {status} (attempt {attempt}/{retries}). Retrying in {delay:.1f}s..." + ) + time.sleep(delay) + delay = min(delay * 2, 12) + + +def _get_space_volumes( + space_id: str, hf_api: huggingface_hub.HfApi | None = None +) -> list[Volume]: + """ + Return mounted volumes for a Space. + + `HfApi.get_space_runtime()` does not always populate `volumes`, even when the + mount exists. Fall back to `space_info().runtime.volumes`, which currently + carries the volume metadata for running Spaces. + """ + hf_api = hf_api or huggingface_hub.HfApi() + runtime = hf_api.get_space_runtime(space_id) + if runtime.volumes: + return list(runtime.volumes) + + info = hf_api.space_info(space_id) + if info.runtime and info.runtime.volumes: + return list(info.runtime.volumes) + + return [] + + +def _get_space_bucket_at_data_mount( + space_id: str, hf_api: huggingface_hub.HfApi | None = None +) -> str | None: + for volume in _get_space_volumes(space_id, hf_api=hf_api): + if volume.type == "bucket" and volume.mount_path == "/data": + return volume.source + return None + + +def _get_existing_space_bucket( + space_id: str, hf_api: huggingface_hub.HfApi | None = None +) -> str | None: + """Return the Trackio bucket for a Space, preferring the canonical /data mount.""" + bucket_at_data = _get_space_bucket_at_data_mount(space_id, hf_api=hf_api) + if bucket_at_data is not None: + return bucket_at_data + + for volume in _get_space_volumes(space_id, hf_api=hf_api): + if volume.type == "bucket": + return volume.source + return None + + +def _get_existing_static_space_bucket( + space_id: str, hf_api: huggingface_hub.HfApi | None = None +) -> str | None: + hf_api = hf_api or huggingface_hub.HfApi() + try: + config_path = hf_api.hf_hub_download( + repo_id=space_id, + repo_type="space", + filename="config.json", + ) + except (FileNotFoundError, HfHubHTTPError, OSError, ValueError): + return None + + try: + with open(config_path, encoding="utf-8") as config_file: + config = json_mod.load(config_file) + except (OSError, ValueError, TypeError): + return None + + bucket_id = config.get("bucket_id") + if isinstance(bucket_id, str) and bucket_id: + return bucket_id + return None + + +def _ensure_bucket_mounted_at_data( + space_id: str, + bucket_id: str, + hf_api: huggingface_hub.HfApi | None = None, +) -> None: + hf_api = hf_api or huggingface_hub.HfApi() + existing = _get_space_volumes(space_id, hf_api=hf_api) + already_mounted = any( + v.type == "bucket" and v.source == bucket_id and v.mount_path == "/data" + for v in existing + ) + if not already_mounted: + preserved = [ + v + for v in existing + if not ( + v.type == "bucket" + and (v.source == bucket_id or v.mount_path == "/data") + ) + ] + hf_api.set_space_volumes( + space_id, + preserved + [Volume(type="bucket", source=bucket_id, mount_path="/data")], + ) + print(f"* Attached bucket {bucket_id} at '/data'") + + existing_variables = hf_api.get_space_variables(space_id) + current_trackio_dir = getattr(existing_variables.get("TRACKIO_DIR"), "value", None) + if current_trackio_dir != "/data/trackio": + huggingface_hub.add_space_variable(space_id, "TRACKIO_DIR", "/data/trackio") + current_bucket_id = getattr( + existing_variables.get("TRACKIO_BUCKET_ID"), "value", None + ) + if current_bucket_id != bucket_id: + huggingface_hub.add_space_variable(space_id, "TRACKIO_BUCKET_ID", bucket_id) + + +def _bucket_exists(bucket_id: str, hf_api: huggingface_hub.HfApi | None = None) -> bool: + hf_api = hf_api or huggingface_hub.HfApi() + try: + hf_api.bucket_info(bucket_id) + return True + except BucketNotFoundError: + return False + + +def _find_available_bucket_id( + preferred_bucket_id: str, hf_api: huggingface_hub.HfApi | None = None +) -> str: + hf_api = hf_api or huggingface_hub.HfApi() + if not _bucket_exists(preferred_bucket_id, hf_api): + return preferred_bucket_id + + suffix = 2 + while True: + candidate = f"{preferred_bucket_id}-{suffix}" + if not _bucket_exists(candidate, hf_api): + return candidate + suffix += 1 + + +def resolve_auto_bucket_id( + space_id: str, + preferred_bucket_id: str, + hf_api: huggingface_hub.HfApi | None = None, +) -> str: + """ + Resolve the bucket to use for an auto-generated bucket ID. + + Rules: + - Existing Space with a bucket mounted at /data -> reuse that bucket. + - Existing static Space with a bucket_id in config.json -> reuse that bucket. + - Otherwise -> use the preferred auto bucket ID if free, or a suffixed variant. + """ + hf_api = hf_api or huggingface_hub.HfApi() + try: + info = hf_api.space_info(space_id) + except RepositoryNotFoundError: + pass + else: + existing_bucket_id = _get_existing_space_bucket(space_id, hf_api=hf_api) + if existing_bucket_id is None and getattr(info, "sdk", None) == "static": + existing_bucket_id = _get_existing_static_space_bucket( + space_id, hf_api=hf_api + ) + if existing_bucket_id is not None: + return existing_bucket_id + + bucket_id = _find_available_bucket_id(preferred_bucket_id, hf_api) + if bucket_id != preferred_bucket_id: + print( + f"* Auto-generated bucket {preferred_bucket_id} already exists; " + f"using {bucket_id} instead" + ) + return bucket_id + + +def _get_source_install_dependencies() -> str: + """Get trackio dependencies from pyproject.toml for source installs.""" + try: + import tomllib # noqa: PLC0415 + except ModuleNotFoundError: + import tomli as tomllib # noqa: PLC0415 + + trackio_path = files("trackio") + pyproject_path = Path(trackio_path).parent / "pyproject.toml" + with open(pyproject_path, "rb") as f: + pyproject = tomllib.load(f) + deps = pyproject["project"]["dependencies"] + spaces_deps = ( + pyproject["project"].get("optional-dependencies", {}).get("spaces", []) + ) + mcp_deps = pyproject["project"].get("optional-dependencies", {}).get("mcp", []) + return "\n".join(deps + spaces_deps + mcp_deps) + + +def _get_space_install_requirement() -> str: + return f"trackio[spaces,mcp]=={trackio.__version__}" + + +def _is_trackio_installed_from_source() -> bool: + """Check if trackio is installed from source/editable install vs PyPI.""" + try: + trackio_file = trackio.__file__ + if "site-packages" not in trackio_file and "dist-packages" not in trackio_file: + return True + + dist = importlib.metadata.distribution("trackio") + if dist.files: + files = list(dist.files) + has_pth = any(".pth" in str(f) for f in files) + if has_pth: + return True + + return False + except ( + AttributeError, + importlib.metadata.PackageNotFoundError, + importlib.metadata.MetadataError, + ValueError, + TypeError, + ): + return True + + +def deploy_as_space( + space_id: str, + space_storage: huggingface_hub.SpaceStorage | None = None, + dataset_id: str | None = None, + bucket_id: str | None = None, + private: bool | None = None, + frontend_dir: str | Path | None = None, +): + if on_spaces(): # in case a repo with this function is uploaded to spaces + return + + if dataset_id is not None and bucket_id is not None: + raise ValueError( + "Cannot use bucket volume options together with dataset_id; use one persistence mode." + ) + + trackio_path = files("trackio") + + hf_api = huggingface_hub.HfApi() + + try: + huggingface_hub.create_repo( + space_id, + private=private, + space_sdk="gradio", + space_storage=space_storage, + repo_type="space", + exist_ok=True, + ) + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: # unauthorized or forbidden + print("Need 'write' access token to create a Spaces repo.") + huggingface_hub.login(add_to_git_credential=False) + huggingface_hub.create_repo( + space_id, + private=private, + space_sdk="gradio", + space_storage=space_storage, + repo_type="space", + exist_ok=True, + ) + else: + raise ValueError(f"Failed to create Space: {e}") + + # We can assume huggingface-hub is available; requirements.txt pins trackio. + # Make sure necessary dependencies are installed by creating a requirements.txt. + is_source_install = _is_trackio_installed_from_source() + resolved_frontend = resolve_frontend_dir(frontend_dir, announce=True) + + if bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=private) + + with open(Path(trackio_path, "README.md"), "r", encoding="utf-8") as f: + readme_content = f.read() + readme_content = readme_content.replace("sdk_version: {GRADIO_VERSION}\n", "") + readme_content = readme_content.replace("{APP_FILE}", "app.py") + readme_content = readme_content.replace( + "{LINKED_HUB_METADATA}", _readme_linked_hub_yaml(dataset_id) + ) + readme_buffer = io.BytesIO(readme_content.encode("utf-8")) + hf_api.upload_file( + path_or_fileobj=readme_buffer, + path_in_repo="README.md", + repo_id=space_id, + repo_type="space", + ) + + if is_source_install: + requirements_content = _get_source_install_dependencies() + else: + requirements_content = _get_space_install_requirement() + + requirements_buffer = io.BytesIO(requirements_content.encode("utf-8")) + hf_api.upload_file( + path_or_fileobj=requirements_buffer, + path_in_repo="requirements.txt", + repo_id=space_id, + repo_type="space", + ) + + huggingface_hub.utils.disable_progress_bars() + + if is_source_install: + dist_index = ( + Path(trackio.__file__).resolve().parent / "frontend" / "dist" / "index.html" + ) + if not dist_index.is_file() and not resolved_frontend.is_custom: + raise ValueError( + "The Trackio frontend build is missing. From the repository root run " + "`cd trackio/frontend && npm ci && npm run build`, then deploy again." + ) + hf_api.upload_folder( + repo_id=space_id, + repo_type="space", + folder_path=trackio_path, + path_in_repo="trackio", + ignore_patterns=[ + "README.md", + "frontend/node_modules/**", + "frontend/src/**", + "frontend/.gitignore", + "frontend/package.json", + "frontend/package-lock.json", + "frontend/vite.config.js", + "frontend/svelte.config.js", + "**/__pycache__/**", + "*.pyc", + ], + ) + + if resolved_frontend.is_custom: + _upload_frontend_folder( + hf_api, + repo_id=space_id, + repo_type="space", + folder_path=resolved_frontend.path, + path_in_repo=_CUSTOM_SPACE_FRONTEND_DIR, + ) + + app_file_content = _space_app_py( + _CUSTOM_SPACE_FRONTEND_DIR if resolved_frontend.is_custom else None + ) + app_file_buffer = io.BytesIO(app_file_content.encode("utf-8")) + hf_api.upload_file( + path_or_fileobj=app_file_buffer, + path_in_repo="app.py", + repo_id=space_id, + repo_type="space", + ) + + if hf_token := huggingface_hub.utils.get_token(): + huggingface_hub.add_space_secret(space_id, "HF_TOKEN", hf_token) + if bucket_id is not None: + _ensure_bucket_mounted_at_data(space_id, bucket_id, hf_api) + elif dataset_id is not None: + huggingface_hub.add_space_variable(space_id, "TRACKIO_DATASET_ID", dataset_id) + if logo_light_url := os.environ.get("TRACKIO_LOGO_LIGHT_URL"): + huggingface_hub.add_space_variable( + space_id, "TRACKIO_LOGO_LIGHT_URL", logo_light_url + ) + if logo_dark_url := os.environ.get("TRACKIO_LOGO_DARK_URL"): + huggingface_hub.add_space_variable( + space_id, "TRACKIO_LOGO_DARK_URL", logo_dark_url + ) + if plot_order := os.environ.get("TRACKIO_PLOT_ORDER"): + huggingface_hub.add_space_variable(space_id, "TRACKIO_PLOT_ORDER", plot_order) + if theme := os.environ.get("TRACKIO_THEME"): + huggingface_hub.add_space_variable(space_id, "TRACKIO_THEME", theme) + huggingface_hub.add_space_variable(space_id, "GRADIO_MCP_SERVER", "True") + + +def create_space_if_not_exists( + space_id: str, + space_storage: huggingface_hub.SpaceStorage | None = None, + dataset_id: str | None = None, + bucket_id: str | None = None, + private: bool | None = None, + frontend_dir: str | Path | None = None, +) -> bool: + """ + Creates a new Hugging Face Space if it does not exist. Returns True if a + new Space was created, False if an existing Space was found. + + Args: + space_id (`str`): + The ID of the Space to create. + space_storage ([`~huggingface_hub.SpaceStorage`], *optional*): + Choice of persistent storage tier for the Space. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + bucket_id (`str`, *optional*): + Full Hub bucket id (`namespace/name`) to attach via the Hub volumes API (platform mount). + Sets `TRACKIO_DIR` to the mount path. + private (`bool`, *optional*): + Whether to make the Space private. If `None` (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + """ + if "/" not in space_id: + raise ValueError( + f"Invalid space ID: {space_id}. Must be in the format: username/reponame or orgname/reponame." + ) + if dataset_id is not None and "/" not in dataset_id: + raise ValueError( + f"Invalid dataset ID: {dataset_id}. Must be in the format: username/datasetname or orgname/datasetname." + ) + if bucket_id is not None and "/" not in bucket_id: + raise ValueError( + f"Invalid bucket ID: {bucket_id}. Must be in the format: username/bucketname or orgname/bucketname." + ) + try: + huggingface_hub.repo_info(space_id, repo_type="space") + print( + f"* Found existing space: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + if bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=private) + _ensure_bucket_mounted_at_data(space_id, bucket_id) + elif dataset_id is not None: + huggingface_hub.add_space_variable( + space_id, "TRACKIO_DATASET_ID", dataset_id + ) + resolved_frontend = resolve_frontend_dir(frontend_dir, announce=False) + if resolved_frontend.is_custom: + deploy_as_space( + space_id, + space_storage, + dataset_id, + bucket_id, + private, + frontend_dir=frontend_dir, + ) + return False + except RepositoryNotFoundError: + pass + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: # unauthorized or forbidden + print("Need 'write' access token to create a Spaces repo.") + huggingface_hub.login(add_to_git_credential=False) + else: + raise ValueError(f"Failed to create Space: {e}") + + print( + f"* Creating new space: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + deploy_as_space( + space_id, + space_storage, + dataset_id, + bucket_id, + private, + frontend_dir=frontend_dir, + ) + threading.Thread( + target=_warn_if_space_build_fails, args=(space_id,), daemon=True + ).start() + return True + + +def space_is_running(space_id: str) -> bool: + try: + info = huggingface_hub.HfApi().space_info(space_id, timeout=30) + return bool(info.runtime) and str(info.runtime.stage) == "RUNNING" + except Exception: + return False + + +def _warn_if_space_build_fails(space_id: str, timeout: int = 600) -> None: + hf_api = huggingface_hub.HfApi() + failure_stages = frozenset( + ("NO_APP_FILE", "CONFIG_ERROR", "BUILD_ERROR", "RUNTIME_ERROR") + ) + start = time.time() + while time.time() - start < timeout: + try: + info = hf_api.space_info(space_id, timeout=30) + if info.runtime: + stage = str(info.runtime.stage) + if stage in failure_stages: + print( + f"\n* WARNING: Space {space_id} failed to build (stage: {stage}). " + f"Logs are being saved to the Bucket and will appear once the Space " + f"is fixed; see the build logs at {SPACE_URL.format(space_id=space_id)}" + ) + return + if stage == "RUNNING": + return + except Exception: + pass + time.sleep(10) + + +def _wait_until_space_running(space_id: str, timeout: int = 300) -> None: + hf_api = huggingface_hub.HfApi() + start = time.time() + delay = 2 + request_timeout = 45.0 + failure_stages = frozenset( + ("NO_APP_FILE", "CONFIG_ERROR", "BUILD_ERROR", "RUNTIME_ERROR") + ) + while time.time() - start < timeout: + try: + info = hf_api.space_info(space_id, timeout=request_timeout) + if info.runtime: + stage = str(info.runtime.stage) + if stage in failure_stages: + raise RuntimeError( + f"Space {space_id} entered terminal stage {stage}. " + "Fix README.md or app files; see build logs on the Hub." + ) + if stage == "RUNNING": + return + except RuntimeError: + raise + except (huggingface_hub.utils.HfHubHTTPError, httpx.RequestError): + pass + time.sleep(delay) + delay = min(delay * 1.5, 15) + raise TimeoutError( + f"Space {space_id} did not reach RUNNING within {timeout}s. " + "Check status and build logs on the Hub." + ) + + +def wait_until_space_exists( + space_id: str, +) -> None: + """ + Blocks the current thread until the Space exists. + + Args: + space_id (`str`): + The ID of the Space to wait for. + + Raises: + `TimeoutError`: If waiting for the Space takes longer than expected. + """ + hf_api = huggingface_hub.HfApi() + delay = 1 + for _ in range(30): + try: + hf_api.space_info(space_id) + return + except (huggingface_hub.utils.HfHubHTTPError, httpx.RequestError): + time.sleep(delay) + delay = min(delay * 2, 60) + raise TimeoutError("Waiting for space to exist took longer than expected") + + +def upload_db_to_space(project: str, space_id: str, force: bool = False) -> None: + """ + Uploads the database of a local Trackio project to a Hugging Face Space. + + This uses the Trackio remote client so newer Trackio Spaces can speak the direct + HTTP API while older Gradio-based Spaces still work through `gradio_client`. + + Args: + project (`str`): + The name of the project to upload. + space_id (`str`): + The ID of the Space to upload to. + force (`bool`, *optional*, defaults to `False`): + If `True`, overwrites the existing database without prompting. If `False`, + prompts for confirmation. + """ + db_path = SQLiteStorage.get_project_db_path(project) + client = RemoteClient( + space_id, + hf_token=huggingface_hub.utils.get_token(), + httpx_kwargs={"timeout": 90}, + ) + + if not force: + try: + existing_projects = client.predict(api_name="/get_all_projects") + if project in existing_projects: + response = input( + f"Database for project '{project}' already exists on Space '{space_id}'. " + f"Overwrite it? (y/N): " + ) + if response.lower() not in ["y", "yes"]: + print("* Upload cancelled.") + return + except Exception as e: + print(f"* Warning: Could not check if project exists on Space: {e}") + print("* Proceeding with upload...") + + client.predict( + api_name="/upload_db_to_space", + project=project, + uploaded_db=handle_file(db_path), + hf_token=huggingface_hub.utils.get_token(), + ) + + +SYNC_BATCH_SIZE = 500 + + +def _replay_pending_uploads( + project: str, + client: "RemoteClient", + hf_token: str | None, +) -> None: + """Replay queued `pending_uploads` rows for `project` via `client` — the + out-of-Run sync path (`trackio sync`); see `replay_pending_uploads` for the + per-kind routing and clearing semantics. + """ + pending_uploads = SQLiteStorage.get_pending_uploads(project) + if not pending_uploads: + return + + def _warn_missing(count: int, sample: str) -> None: + print( + f" Warning: dropping {count} pending upload(s) whose local files " + f"no longer exist (e.g. {sample!r})." + ) + + replay_pending_uploads( + pending_uploads, + project, + predict=client.predict, + hf_token=hf_token, + warn_missing=_warn_missing, + verbose=True, + ) + + +def sync_incremental( + project: str, + space_id: str, + private: bool | None = None, + pending_only: bool = False, + frontend_dir: str | Path | None = None, +) -> None: + """ + Syncs a local Trackio project to a Space via the bulk_log API endpoints + instead of uploading the entire DB file. Supports incremental sync. + + Args: + project: The name of the project to sync. + space_id: The HF Space ID to sync to. + private: Whether to make the Space private if creating. + pending_only: If True, only sync rows tagged with space_id (pending data). + """ + print( + f"* Syncing project '{project}' to: {SPACE_URL.format(space_id=space_id)} (please wait...)" + ) + create_space_if_not_exists(space_id, private=private, frontend_dir=frontend_dir) + wait_until_space_exists(space_id) + hf_token = huggingface_hub.utils.get_token() + expected_run_counts: Counter[str] = Counter() + + client = RemoteClient( + space_id, + hf_token=hf_token, + httpx_kwargs={"timeout": 90}, + ) + + if pending_only: + pending_logs = SQLiteStorage.get_pending_logs(project) + if pending_logs: + logs = pending_logs["logs"] + expected_run_counts.update(log["run"] for log in logs) + for i in range(0, len(logs), SYNC_BATCH_SIZE): + batch = logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing metrics: {min(i + SYNC_BATCH_SIZE, len(logs))}/{len(logs)}..." + ) + client.predict(api_name="/bulk_log", logs=batch, hf_token=hf_token) + SQLiteStorage.clear_pending_logs(project, pending_logs["ids"]) + + pending_sys = SQLiteStorage.get_pending_system_logs(project) + if pending_sys: + logs = pending_sys["logs"] + for i in range(0, len(logs), SYNC_BATCH_SIZE): + batch = logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing system metrics: {min(i + SYNC_BATCH_SIZE, len(logs))}/{len(logs)}..." + ) + client.predict( + api_name="/bulk_log_system", logs=batch, hf_token=hf_token + ) + SQLiteStorage.clear_pending_system_logs(project, pending_sys["ids"]) + + _replay_pending_uploads(project, client, hf_token) + else: + all_logs = SQLiteStorage.get_all_logs_for_sync(project) + if all_logs: + expected_run_counts.update(log["run"] for log in all_logs) + for i in range(0, len(all_logs), SYNC_BATCH_SIZE): + batch = all_logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing metrics: {min(i + SYNC_BATCH_SIZE, len(all_logs))}/{len(all_logs)}..." + ) + client.predict(api_name="/bulk_log", logs=batch, hf_token=hf_token) + + all_sys_logs = SQLiteStorage.get_all_system_logs_for_sync(project) + if all_sys_logs: + for i in range(0, len(all_sys_logs), SYNC_BATCH_SIZE): + batch = all_sys_logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing system metrics: {min(i + SYNC_BATCH_SIZE, len(all_sys_logs))}/{len(all_sys_logs)}..." + ) + client.predict( + api_name="/bulk_log_system", logs=batch, hf_token=hf_token + ) + + _wait_for_remote_sync(client, project, expected_run_counts) + SQLiteStorage.set_project_metadata(project, "space_id", space_id) + print( + f"* Synced successfully to space: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + + +def _build_remote_client_with_retry( + space_id: str, + timeout: int = 360, + verbose: bool = False, +) -> RemoteClient: + deadline = time.time() + timeout + delay = 2 + last_error: Exception | None = None + while time.time() < deadline: + try: + return RemoteClient( + space_id, + hf_token=huggingface_hub.utils.get_token(), + verbose=verbose, + httpx_kwargs={"timeout": 90}, + ) + except (ValueError, ConnectionError) as e: + last_error = e + time.sleep(delay) + delay = min(delay * 1.5, 15) + raise ConnectionError( + f"Could not connect to Space '{space_id}' within {timeout}s: {last_error}" + ) + + +def _wait_for_remote_sync( + client: RemoteClient, + project: str, + expected_run_counts: Counter[str], + timeout: int = 180, +) -> None: + if not expected_run_counts: + return + + deadline = time.time() + timeout + delay = 2 + last_error: Exception | None = None + pending = dict(expected_run_counts) + + while time.time() < deadline and pending: + completed = [] + for run_name, expected_num_logs in pending.items(): + try: + summary = client.predict( + project=project, run=run_name, api_name="/get_run_summary" + ) + if summary.get("num_logs") == expected_num_logs: + completed.append(run_name) + except Exception as e: + last_error = e + for run_name in completed: + pending.pop(run_name, None) + if pending: + time.sleep(delay) + delay = min(delay * 1.5, 15) + + if pending: + raise TimeoutError( + f"Remote sync for project '{project}' did not become visible for runs " + f"{sorted(pending.items())} within {timeout}s. " + f"Last error: {last_error!r}" + ) + + +def upload_dataset_for_static( + project: str, + dataset_id: str, + private: bool | None = None, +) -> None: + hf_api = huggingface_hub.HfApi() + + try: + huggingface_hub.create_repo( + dataset_id, + private=private, + repo_type="dataset", + exist_ok=True, + ) + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: + print("Need 'write' access token to create a Dataset repo.") + huggingface_hub.login(add_to_git_credential=False) + huggingface_hub.create_repo( + dataset_id, + private=private, + repo_type="dataset", + exist_ok=True, + ) + else: + raise ValueError(f"Failed to create Dataset: {e}") + + def _upload_folder(folder: Path, path_in_repo: str, ignore_patterns=None) -> None: + if not folder.exists(): + return + _retry_hf_write( + f"Dataset {path_in_repo} upload", + lambda: hf_api.upload_folder( + repo_id=dataset_id, + repo_type="dataset", + folder_path=str(folder), + path_in_repo=path_in_repo, + ignore_patterns=ignore_patterns, + ), + ) + + with tempfile.TemporaryDirectory() as tmp_dir: + output_dir = Path(tmp_dir) + SQLiteStorage.export_for_static_space(project, output_dir) + + _upload_folder(project_media_dir(project), "media") + _upload_folder(project_artifacts_dir(project), "artifacts", [PARTIAL_BLOB_GLOB]) + + _retry_hf_write( + "Dataset upload", + lambda: hf_api.upload_folder( + repo_id=dataset_id, + repo_type="dataset", + folder_path=str(output_dir), + ), + ) + + print(f"* Dataset uploaded: https://huggingface.co/datasets/{dataset_id}") + + +def deploy_as_static_space( + space_id: str, + dataset_id: str | None, + project: str, + bucket_id: str | None = None, + private: bool | None = None, + hf_token: str | None = None, + frontend_dir: str | Path | None = None, +) -> None: + if on_spaces(): + return + + if private is True: + raise ValueError( + "private=True is not supported for static Trackio Spaces. Static Spaces " + "run entirely in the browser, so their snapshot data must be public. " + "Use sdk='gradio' for a private dashboard." + ) + hf_api = huggingface_hub.HfApi() + + try: + huggingface_hub.create_repo( + space_id, + private=False, + space_sdk="static", + repo_type="space", + exist_ok=True, + ) + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: + print("Need 'write' access token to create a Spaces repo.") + huggingface_hub.login(add_to_git_credential=False) + huggingface_hub.create_repo( + space_id, + private=False, + space_sdk="static", + repo_type="space", + exist_ok=True, + ) + else: + raise ValueError(f"Failed to create Space: {e}") + + linked = _readme_linked_hub_yaml(dataset_id) + readme_content = ( + f"---\nemoji: 🎯\nsdk: static\npinned: false\ntags:\n - trackio\n{linked}---\n" + ) + _retry_hf_write( + "Static Space README upload", + lambda: hf_api.upload_file( + path_or_fileobj=io.BytesIO(readme_content.encode("utf-8")), + path_in_repo="README.md", + repo_id=space_id, + repo_type="space", + ), + ) + + resolved_frontend = resolve_frontend_dir(frontend_dir, announce=True) + + _retry_hf_write( + "Static Space frontend upload", + lambda: hf_api.upload_folder( + repo_id=space_id, + repo_type="space", + folder_path=str(resolved_frontend.path), + ), + ) + + config = { + "mode": "static", + "project": project, + "private": bool(private), + } + if bucket_id is not None: + config["bucket_id"] = bucket_id + if dataset_id is not None: + config["dataset_id"] = dataset_id + if hf_token is not None: + warnings.warn( + "`hf_token` is ignored by deploy_as_static_space() for static Space " + "deployment and will be removed in a future release.", + DeprecationWarning, + stacklevel=2, + ) + + _retry_hf_write( + "Static Space config upload", + lambda: hf_api.upload_file( + path_or_fileobj=io.BytesIO(json_mod.dumps(config).encode("utf-8")), + path_in_repo="config.json", + repo_id=space_id, + repo_type="space", + ), + ) + + assets_dir = Path(trackio.__file__).resolve().parent / "assets" + if assets_dir.is_dir(): + _retry_hf_write( + "Static Space assets upload", + lambda: hf_api.upload_folder( + repo_id=space_id, + repo_type="space", + folder_path=str(assets_dir), + path_in_repo="static/trackio", + ), + ) + + print( + f"* Static Space deployed: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + + +def sync( + project: str, + space_id: str | None = None, + private: bool | None = None, + force: bool = False, + run_in_background: bool = False, + sdk: str = "gradio", + dataset_id: str | None = None, + bucket_id: str | None = None, + frontend_dir: str | Path | None = None, +) -> str: + """ + Syncs a local Trackio project's database to a Hugging Face Space. + If the Space does not exist, it will be created. Local data is never deleted. + + **Freezing:** Passing ``sdk="static"`` deploys a static Space backed by an HF Bucket + (read-only dashboard, no Gradio server). You can sync the same project again later to + refresh that static Space. If you want a one-time snapshot of an existing Gradio Space, + use ``freeze()`` instead. + + Args: + project (`str`): The name of the project to upload. + space_id (`str`, *optional*): The ID of the Space to upload to (e.g., `"username/space_id"`). + If not provided, checks project metadata first, then generates a random space_id. + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. Not supported with ``sdk="static"`` because + static Trackio dashboards read snapshot data directly from the browser. + force (`bool`, *optional*, defaults to `False`): + If `True`, overwrite the existing database without prompting for confirmation. + If `False`, prompt the user before overwriting an existing database. + run_in_background (`bool`, *optional*, defaults to `False`): + If `True`, the Space creation and database upload will be run in a background thread. + If `False`, all the steps will be run synchronously. + sdk (`str`, *optional*, defaults to `"gradio"`): + The type of Space to deploy. `"gradio"` deploys a Gradio Space with a live + server. `"static"` freezes the Space: deploys a static Space that reads from an HF Bucket + (no server needed). + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + bucket_id (`str`, *optional*): + The ID of the HF Bucket to sync to. By default, a bucket is auto-generated + from the space_id. + Returns: + `str`: The Space ID of the synced project. + """ + if sdk not in ("gradio", "static"): + raise ValueError(f"sdk must be 'gradio' or 'static', got '{sdk}'") + if sdk == "static" and private is True: + raise ValueError( + "private=True is not supported for static Trackio Spaces. Static Spaces " + "run entirely in the browser, so their snapshot data must be public. " + "Use sdk='gradio' for a private dashboard." + ) + bucket_id_was_explicit = bucket_id is not None + + if space_id is None: + space_id = SQLiteStorage.get_space_id(project) + if space_id is None: + space_id = f"{project}-{get_or_create_project_hash(project)}" + space_id, dataset_id, bucket_id = preprocess_space_and_dataset_ids( + space_id, dataset_id, bucket_id + ) + if dataset_id is None and bucket_id is not None and not bucket_id_was_explicit: + bucket_id = resolve_auto_bucket_id(space_id, bucket_id) + + def _do_sync(): + try: + info = huggingface_hub.HfApi().space_info(space_id) + existing_sdk = info.sdk + if existing_sdk and existing_sdk != sdk: + raise ValueError( + f"Space '{space_id}' is a '{existing_sdk}' Space but sdk='{sdk}' was requested. " + f"The sdk must match the existing Space type." + ) + except RepositoryNotFoundError: + pass + + if sdk == "static": + if dataset_id is not None: + upload_dataset_for_static(project, dataset_id, private=False) + deploy_as_static_space( + space_id, + dataset_id, + project, + private=False, + frontend_dir=frontend_dir, + ) + elif bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=False) + upload_project_to_bucket_for_static(project, bucket_id) + print( + f"* Project data uploaded to bucket: https://huggingface.co/buckets/{bucket_id}" + ) + deploy_as_static_space( + space_id, + None, + project, + bucket_id=bucket_id, + private=False, + frontend_dir=frontend_dir, + ) + else: + if bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=private) + upload_project_to_bucket(project, bucket_id) + print( + f"* Project data uploaded to bucket: https://huggingface.co/buckets/{bucket_id}" + ) + create_space_if_not_exists( + space_id, + bucket_id=bucket_id, + private=private, + frontend_dir=frontend_dir, + ) + _wait_until_space_running(space_id) + _wait_for_remote_sync( + _build_remote_client_with_retry(space_id), + project, + Counter( + log["run"] + for log in SQLiteStorage.get_all_logs_for_sync(project) + ), + ) + else: + sync_incremental( + project, + space_id, + private=private, + pending_only=False, + frontend_dir=frontend_dir, + ) + SQLiteStorage.set_project_metadata(project, "space_id", space_id) + + if run_in_background: + threading.Thread(target=_do_sync).start() + else: + _do_sync() + return space_id + + +def _get_source_bucket(space_id: str) -> str: + bucket_id = _get_existing_space_bucket(space_id) + if bucket_id is not None: + _ensure_bucket_mounted_at_data(space_id, bucket_id) + return bucket_id + raise ValueError( + f"Space '{space_id}' has no bucket mounted at '/data'. " + f"freeze() requires the source Space to use bucket storage." + ) + + +def freeze( + space_id: str, + project: str, + new_space_id: str | None = None, + private: bool | None = None, + bucket_id: str | None = None, + frontend_dir: str | Path | None = None, +) -> str: + """ + Creates a new static Hugging Face Space containing a read-only snapshot of + the data for the specified project from the source Gradio Space. The data is + read from the bucket attached to the source Space at freeze time. The original + Space is not modified, and the new static Space does not automatically reflect + metrics uploaded to the original Gradio Space after the freeze completes. + + Args: + space_id (`str`): + The ID of the source Gradio Space (e.g., `"username/my-space"` or a + short repo name with the logged-in namespace inferred, like `init()`). + Must be a Gradio Space with a bucket mounted at `/data`. + project (`str`): + The name of the project whose data to include in the frozen Space. + new_space_id (`str`, *optional*): + The ID for the new static Space. If not provided, defaults to + `"{space_id}_static"`. + private (`bool`, *optional*): + Not supported. Frozen static dashboards read snapshot data directly + from the browser, so the destination snapshot must be public. + bucket_id (`str`, *optional*): + The ID of the HF Bucket for the new static Space's data storage. + If not provided, one is auto-generated from the new Space ID. + + Returns: + `str`: The Space ID of the newly created static Space. + """ + if private is True: + raise ValueError( + "private=True is not supported for frozen static Trackio Spaces. Static " + "Spaces run entirely in the browser, so their snapshot data must be " + "public. Use a Gradio Space if the frozen dashboard must stay private." + ) + space_id, _, _ = preprocess_space_and_dataset_ids(space_id, None, None) + + try: + info = huggingface_hub.HfApi().space_info(space_id) + if info.sdk != "gradio": + raise ValueError( + f"Space '{space_id}' is not a Gradio Space (sdk='{info.sdk}'). " + f"freeze() requires a Gradio Space as the source." + ) + except RepositoryNotFoundError: + raise ValueError( + f"Space '{space_id}' not found. Provide an existing Gradio Space ID." + ) + + source_bucket_id = _get_source_bucket(space_id) + print(f"* Reading project data from bucket: {source_bucket_id}") + + bucket_id_was_explicit = bucket_id is not None + + if new_space_id is None: + new_space_id = f"{space_id}_static" + new_space_id, _dataset_id, bucket_id = preprocess_space_and_dataset_ids( + new_space_id, None, bucket_id + ) + if bucket_id is not None and not bucket_id_was_explicit: + bucket_id = resolve_auto_bucket_id(new_space_id, bucket_id) + + hf_api = huggingface_hub.HfApi() + try: + dest_info = hf_api.space_info(new_space_id) + tags = dest_info.tags or [] + if dest_info.sdk != "static" or "trackio" not in tags: + raise ValueError( + f"Space '{new_space_id}' already exists and is not a Trackio static Space " + f"(sdk='{dest_info.sdk}', tags={tags}). Choose a different new_space_id " + f"or delete the existing Space first." + ) + except RepositoryNotFoundError: + pass + + create_bucket_if_not_exists(bucket_id, private=False) + export_from_bucket_for_static(source_bucket_id, bucket_id, project) + print( + f"* Project data uploaded to bucket: https://huggingface.co/buckets/{bucket_id}" + ) + deploy_as_static_space( + new_space_id, + None, + project, + bucket_id=bucket_id, + private=False, + frontend_dir=frontend_dir, + ) + return new_space_id diff --git a/trackio/dummy_commit_scheduler.py b/trackio/dummy_commit_scheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..6068fe8a36b8647ade92dd300af0855f4338826f --- /dev/null +++ b/trackio/dummy_commit_scheduler.py @@ -0,0 +1,19 @@ +from concurrent.futures import Future + + +class DummyCommitSchedulerLock: + def __enter__(self): + return None + + def __exit__(self, exception_type, exception_value, exception_traceback): + pass + + +class DummyCommitScheduler: + def __init__(self): + self.lock = DummyCommitSchedulerLock() + + def trigger(self) -> Future: + fut: Future = Future() + fut.set_result(None) + return fut diff --git a/trackio/exceptions.py b/trackio/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..189f56d718245b65790ff43e14005b846aad2402 --- /dev/null +++ b/trackio/exceptions.py @@ -0,0 +1,2 @@ +class TrackioAPIError(Exception): + pass diff --git a/trackio/fragments.py b/trackio/fragments.py new file mode 100644 index 0000000000000000000000000000000000000000..4e70507516ace65cb1e4221482f384853001ffa2 --- /dev/null +++ b/trackio/fragments.py @@ -0,0 +1,368 @@ +"""Append-only JSONL fragments used as a durable fallback for metric logging. + +Fragments are immutable JSONL files, one writer (process) per subdirectory, so +concurrent training processes never contend on a shared file. They are written +either to a Hugging Face Bucket inbox (when a Space is unreachable) or to a +local inbox directory (when SQLite is unsafe, e.g. on network filesystems), and +are later imported into the project SQLite database by the process that owns it +(the Space or the dashboard server). Records carry the same ``log_id``/ +``alert_id`` UUIDs as the HTTP logging endpoints, and imports use +``INSERT OR IGNORE``, so importing a fragment is idempotent: fragments are +deleted only after a successful import, and re-importing after a crash is +harmless. +""" + +import tempfile +import threading +import uuid +from collections.abc import Callable +from pathlib import Path +from typing import Any + +import huggingface_hub +import orjson + +from trackio import utils +from trackio.typehints import AlertEntry, LogEntry, SystemLogEntry + +FRAGMENT_VERSION = 1 +INBOX_DIR_NAME = "inbox" +BUCKET_INBOX_PREFIX = "trackio/inbox" +BUCKET_MEDIA_PREFIX = "trackio/media" + +METRIC_KIND = "metric" +SYSTEM_METRIC_KIND = "system_metric" +ALERT_KIND = "alert" +KINDS = {METRIC_KIND, SYSTEM_METRIC_KIND, ALERT_KIND} + + +def local_inbox_dir() -> Path: + return utils.TRACKIO_DIR / INBOX_DIR_NAME + + +def metric_record(entry: LogEntry | dict) -> dict: + return { + "v": FRAGMENT_VERSION, + "kind": METRIC_KIND, + "project": entry["project"], + "run": entry["run"], + "run_id": entry.get("run_id"), + "metrics": utils.serialize_values(entry.get("metrics") or {}), + "step": entry.get("step"), + "timestamp": entry.get("timestamp"), + "config": utils.serialize_values(entry.get("config")) + if entry.get("config") + else None, + "log_id": entry.get("log_id"), + } + + +def system_metric_record(entry: SystemLogEntry | dict) -> dict: + return { + "v": FRAGMENT_VERSION, + "kind": SYSTEM_METRIC_KIND, + "project": entry["project"], + "run": entry["run"], + "run_id": entry.get("run_id"), + "metrics": utils.serialize_values(entry.get("metrics") or {}), + "timestamp": entry.get("timestamp"), + "log_id": entry.get("log_id"), + } + + +def alert_record(entry: AlertEntry | dict) -> dict: + return { + "v": FRAGMENT_VERSION, + "kind": ALERT_KIND, + "project": entry["project"], + "run": entry["run"], + "run_id": entry.get("run_id"), + "title": entry["title"], + "text": entry.get("text"), + "level": entry.get("level"), + "step": entry.get("step"), + "timestamp": entry.get("timestamp"), + "alert_id": entry.get("alert_id"), + } + + +def bucket_media_path( + project: str, + run: str | None, + step: int | None, + relative_path: str | None, + filename: str, +) -> str: + parts = [BUCKET_MEDIA_PREFIX, utils.canonical_project_name(project)] + if run: + parts.append(run) + if step is not None: + parts.append(str(step)) + else: + parts.append("files") + if relative_path: + parts.append(str(relative_path)) + parts.append(filename) + return "/".join(parts) + + +class FragmentWriter: + """Writes immutable JSONL fragments for a single writer (process).""" + + def __init__(self, writer_id: str | None = None): + self.writer_id = writer_id or uuid.uuid4().hex[:16] + self._seq = 0 + self._lock = threading.Lock() + + def _next_fragment_name(self) -> str: + with self._lock: + name = f"{self._seq:08d}.jsonl" + self._seq += 1 + return name + + @staticmethod + def serialize_records(records: list[dict]) -> bytes: + return b"".join(orjson.dumps(record) + b"\n" for record in records) + + def write_local( + self, records: list[dict], inbox_dir: Path | None = None + ) -> Path | None: + if not records: + return None + inbox = inbox_dir or local_inbox_dir() + writer_dir = inbox / self.writer_id + fragment_path = writer_dir / self._next_fragment_name() + data = self.serialize_records(records) + for attempt in range(3): + writer_dir.mkdir(parents=True, exist_ok=True) + try: + with tempfile.NamedTemporaryFile( + mode="wb", dir=writer_dir, suffix=".tmp", delete=False + ) as tmp: + tmp.write(data) + tmp_path = Path(tmp.name) + tmp_path.replace(fragment_path) + return fragment_path + except FileNotFoundError: + if attempt == 2 or writer_dir.exists(): + raise + + def write_to_bucket(self, records: list[dict], bucket_id: str) -> str | None: + if not records: + return None + remote_path = ( + f"{BUCKET_INBOX_PREFIX}/{self.writer_id}/{self._next_fragment_name()}" + ) + huggingface_hub.batch_bucket_files( + bucket_id, + add=[(self.serialize_records(records), remote_path)], + token=huggingface_hub.utils.get_token(), + ) + return remote_path + + +def parse_fragment_bytes(data: bytes) -> list[dict]: + records = [] + for line in data.splitlines(): + line = line.strip() + if not line: + continue + try: + record = orjson.loads(line) + except orjson.JSONDecodeError: + continue + if isinstance(record, dict) and record.get("kind") in KINDS: + records.append(record) + return records + + +def _group_by_run(records: list[dict]) -> dict[tuple, list[dict]]: + grouped: dict[tuple, list[dict]] = {} + for record in records: + key = (record.get("project"), record.get("run"), record.get("run_id")) + grouped.setdefault(key, []).append(record) + return grouped + + +def import_records(records: list[dict]) -> int: + from trackio.sqlite_storage import SQLiteStorage # noqa: PLC0415 + + metric_records = [r for r in records if r.get("kind") == METRIC_KIND] + system_records = [r for r in records if r.get("kind") == SYSTEM_METRIC_KIND] + alert_records = [r for r in records if r.get("kind") == ALERT_KIND] + imported = 0 + + for (project, run, run_id), group in _group_by_run(metric_records).items(): + if not project or not run: + continue + config = next((r["config"] for r in group if r.get("config")), None) + has_timestamps = all(r.get("timestamp") for r in group) + SQLiteStorage.bulk_log( + project=project, + run=run, + run_id=run_id, + metrics_list=[r.get("metrics") or {} for r in group], + steps=[r.get("step") for r in group], + timestamps=[r["timestamp"] for r in group] if has_timestamps else None, + config=config, + log_ids=[r.get("log_id") for r in group], + ) + imported += len(group) + + for (project, run, run_id), group in _group_by_run(system_records).items(): + if not project or not run: + continue + has_timestamps = all(r.get("timestamp") for r in group) + SQLiteStorage.bulk_log_system( + project=project, + run=run, + run_id=run_id, + metrics_list=[r.get("metrics") or {} for r in group], + timestamps=[r["timestamp"] for r in group] if has_timestamps else None, + log_ids=[r.get("log_id") for r in group], + ) + imported += len(group) + + for (project, run, run_id), group in _group_by_run(alert_records).items(): + if not project or not run: + continue + has_timestamps = all(r.get("timestamp") for r in group) + SQLiteStorage.bulk_alert( + project=project, + run=run, + run_id=run_id, + titles=[r.get("title") or "" for r in group], + texts=[r.get("text") for r in group], + levels=[r.get("level") or "WARN" for r in group], + steps=[r.get("step") for r in group], + timestamps=[r["timestamp"] for r in group] if has_timestamps else None, + alert_ids=[r.get("alert_id") for r in group], + ) + imported += len(group) + + return imported + + +def import_inbox_dir(inbox_dir: Path | None = None) -> int: + inbox = inbox_dir or local_inbox_dir() + if not inbox.exists(): + return 0 + imported = 0 + for fragment_path in sorted(inbox.rglob("*.jsonl")): + try: + data = fragment_path.read_bytes() + except OSError: + continue + records = parse_fragment_bytes(data) + if records: + imported += import_records(records) + try: + fragment_path.unlink() + except OSError: + pass + for writer_dir in inbox.glob("*"): + if writer_dir.is_dir(): + try: + writer_dir.rmdir() + except OSError: + pass + return imported + + +def list_bucket_inbox_paths(bucket_id: str) -> list[str]: + try: + items = huggingface_hub.list_bucket_tree( + bucket_id, + prefix=BUCKET_INBOX_PREFIX, + recursive=True, + token=huggingface_hub.utils.get_token(), + ) + except Exception: + return [] + return sorted( + item.path + for item in items + if getattr(item, "type", None) == "file" + and getattr(item, "path", "").endswith(".jsonl") + ) + + +def import_inbox_from_bucket(bucket_id: str) -> int: + paths = list_bucket_inbox_paths(bucket_id) + if not paths: + return 0 + imported = 0 + consumed: list[str] = [] + with tempfile.TemporaryDirectory() as tmp_dir: + for i, remote_path in enumerate(paths): + local_path = Path(tmp_dir) / f"{i}.jsonl" + try: + huggingface_hub.download_bucket_files( + bucket_id, + files=[(remote_path, str(local_path))], + token=huggingface_hub.utils.get_token(), + ) + records = parse_fragment_bytes(local_path.read_bytes()) + except Exception: + continue + if records: + imported += import_records(records) + consumed.append(remote_path) + if consumed: + try: + huggingface_hub.batch_bucket_files( + bucket_id, + delete=consumed, + token=huggingface_hub.utils.get_token(), + ) + except Exception: + pass + return imported + + +def _add_files_to_bucket(bucket_id: str, additions: list[tuple[str, str]]) -> None: + if additions: + huggingface_hub.batch_bucket_files( + bucket_id, + add=additions, + token=huggingface_hub.utils.get_token(), + ) + + +def _upload_files_to_bucket( + bucket_id: str, + uploads: list[dict[str, Any]], + remote_path: Callable[[dict[str, Any], Path], str], +) -> None: + _add_files_to_bucket( + bucket_id, + [ + (str(p), remote_path(upload, p)) + for upload in uploads + if (p := Path(upload["file_path"])).exists() + ], + ) + + +def upload_media_files_to_bucket(bucket_id: str, uploads: list[dict[str, Any]]) -> None: + _upload_files_to_bucket( + bucket_id, + uploads, + lambda upload, p: bucket_media_path( + project=upload["project"], + run=upload.get("run"), + step=upload.get("step"), + relative_path=upload.get("relative_path"), + filename=p.name, + ), + ) + + +def upload_artifact_blobs_to_bucket( + bucket_id: str, uploads: list[dict[str, Any]] +) -> None: + _upload_files_to_bucket( + bucket_id, + uploads, + lambda upload, p: f"trackio/{p.relative_to(utils.TRACKIO_DIR).as_posix()}", + ) diff --git a/trackio/frontend/dist/assets/index-m3jgYXoS.css b/trackio/frontend/dist/assets/index-m3jgYXoS.css new file mode 100644 index 0000000000000000000000000000000000000000..833885e1b452f5e0d430ccfaeb379a59a6f7e6c9 --- /dev/null +++ b/trackio/frontend/dist/assets/index-m3jgYXoS.css @@ -0,0 +1 @@ +:root{--primary-50: #fff7ed;--primary-100: #ffedd5;--primary-200: #fed7aa;--primary-300: #fdba74;--primary-400: #fb923c;--primary-500: #f97316;--primary-600: #ea580c;--primary-700: #c2410c;--primary-800: #9a3412;--primary-900: #7c2d12;--primary-950: #6c2e12;--secondary-50: #eff6ff;--secondary-100: #dbeafe;--secondary-200: #bfdbfe;--secondary-300: #93c5fd;--secondary-400: #60a5fa;--secondary-500: #3b82f6;--secondary-600: #2563eb;--secondary-700: #1d4ed8;--secondary-800: #1e40af;--secondary-900: #1e3a8a;--secondary-950: #1d3660;--neutral-50: #f9fafb;--neutral-100: #f3f4f6;--neutral-200: #e5e7eb;--neutral-300: #d1d5db;--neutral-400: #9ca3af;--neutral-500: #6b7280;--neutral-600: #4b5563;--neutral-700: #374151;--neutral-800: #1f2937;--neutral-900: #111827;--neutral-950: #0b0f19;--size-0-5: 2px;--size-1: 4px;--size-2: 8px;--size-3: 12px;--size-4: 16px;--size-5: 20px;--size-6: 24px;--size-8: 32px;--size-14: 56px;--size-16: 64px;--size-28: 112px;--size-full: 100%;--spacing-xxs: 1px;--spacing-xs: 2px;--spacing-sm: 4px;--spacing-md: 6px;--spacing-lg: 8px;--spacing-xl: 10px;--spacing-xxl: 16px;--radius-xxs: 1px;--radius-xs: 2px;--radius-sm: 3px;--radius-md: 4px;--radius-lg: 5px;--radius-xl: 8px;--radius-xxl: 12px;--text-xxs: 9px;--text-xs: 10px;--text-sm: 12px;--text-md: 14px;--text-lg: 16px;--text-xl: 22px;--text-xxl: 26px;--line-sm: 1.4;--background-fill-primary: white;--background-fill-secondary: var(--neutral-50);--body-text-color: var(--neutral-900);--body-text-color-subdued: var(--neutral-600);--border-color-primary: var(--neutral-200);--color-accent: var(--primary-500);--color-accent-soft: var(--primary-50);--shadow-drop: rgba(0, 0, 0, .05) 0px 1px 2px 0px;--shadow-drop-lg: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--shadow-inset: rgba(0, 0, 0, .05) 0px 2px 4px 0px inset;--shadow-spread: 3px;--block-title-text-color: var(--neutral-500);--block-title-text-size: var(--text-md);--block-title-text-weight: 400;--block-info-text-color: var(--body-text-color-subdued);--block-info-text-size: var(--text-sm);--input-background-fill: white;--input-background-fill-focus: var(--primary-500);--input-border-color: var(--border-color-primary);--input-border-color-focus: var(--primary-300);--input-border-width: 1px;--input-padding: var(--spacing-xl);--input-placeholder-color: var(--neutral-400);--input-radius: var(--radius-lg);--input-shadow: 0 0 0 var(--shadow-spread) transparent, var(--shadow-inset);--input-shadow-focus: 0 0 0 var(--shadow-spread) var(--primary-50), var(--shadow-inset);--input-text-size: var(--text-md);--checkbox-background-color: var(--background-fill-primary);--checkbox-background-color-focus: var(--checkbox-background-color);--checkbox-background-color-hover: var(--checkbox-background-color);--checkbox-background-color-selected: var(--primary-600);--checkbox-border-color: var(--neutral-300);--checkbox-border-color-focus: var(--primary-500);--checkbox-border-color-hover: var(--neutral-300);--checkbox-border-color-selected: var(--primary-600);--checkbox-border-radius: var(--radius-sm);--checkbox-border-width: var(--input-border-width);--checkbox-label-gap: var(--spacing-lg);--checkbox-label-padding: var(--spacing-md) calc(2 * var(--spacing-md));--checkbox-label-text-size: var(--text-md);--checkbox-shadow: var(--input-shadow);--checkbox-check: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");--slider-color: var(--primary-500);--container-radius: var(--radius-lg);--layer-top: 9999}.navbar.svelte-d8j1hi{display:flex;align-items:stretch;border-bottom:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);padding:0;flex-shrink:0;min-height:44px}.nav-spacer.svelte-d8j1hi{flex:1 1 0;min-width:0}.nav-tabs.svelte-d8j1hi{display:flex;gap:0;flex-shrink:0;padding-right:8px}.nav-link.svelte-d8j1hi{padding:10px 16px;border:none;background:none;color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-md, 14px);cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;transition:color .15s;font-weight:400}.nav-link.empty.svelte-d8j1hi:not(.active){color:var(--body-text-color-subdued, #9ca3af);opacity:.48}.nav-link.svelte-d8j1hi:hover{color:var(--body-text-color, #1f2937);opacity:1}.nav-link.active.svelte-d8j1hi{color:var(--body-text-color, #1f2937);border-bottom-color:var(--body-text-color, #1f2937);font-weight:500}.settings-btn.svelte-d8j1hi{display:flex;align-items:center;gap:6px}.settings-btn.svelte-d8j1hi svg:where(.svelte-d8j1hi){flex-shrink:0}.checkbox-group.svelte-17gmtkf{display:flex;flex-direction:column}.checkbox-item.svelte-17gmtkf{display:flex;align-items:center;gap:8px;padding:3px 0;cursor:pointer;font-size:13px}.checkbox-item.svelte-17gmtkf input[type=checkbox]:where(.svelte-17gmtkf){-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;margin:0;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);box-shadow:var(--checkbox-shadow);cursor:pointer;flex-shrink:0;transition:background-color .15s,border-color .15s}.checkbox-item.svelte-17gmtkf input[type=checkbox]:where(.svelte-17gmtkf):checked{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}.checkbox-item.svelte-17gmtkf input[type=checkbox]:where(.svelte-17gmtkf):hover{border-color:var(--checkbox-border-color-hover, #d1d5db)}.color-dot.svelte-17gmtkf{width:10px;height:10px;border-radius:50%;flex-shrink:0}.run-name.svelte-17gmtkf{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--body-text-color, #1f2937)}.dropdown-container.svelte-kgylqb{width:100%;margin-bottom:4px}.label.svelte-kgylqb{display:block;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);margin-bottom:6px}.info.svelte-kgylqb{display:block;font-size:12px;color:var(--body-text-color-subdued, #9ca3af);margin-bottom:4px}.wrap.svelte-kgylqb{position:relative;border-radius:var(--input-radius, 8px);background:var(--input-background-fill, white);border:1px solid var(--border-color-primary, #e5e7eb);transition:border-color .15s,box-shadow .15s}.wrap.focused.svelte-kgylqb{border-color:var(--input-border-color-focus, #fdba74);box-shadow:0 0 0 2px var(--primary-50, #fff7ed)}.wrap-inner.svelte-kgylqb{display:flex;position:relative;align-items:center;padding:0 10px}.secondary-wrap.svelte-kgylqb{display:flex;flex:1;align-items:center}input.svelte-kgylqb{margin:0;outline:none;border:none;background:inherit;width:100%;color:var(--body-text-color, #1f2937);font-size:13px;font-family:inherit;padding:7px 0}input.svelte-kgylqb::placeholder{color:var(--input-placeholder-color, #9ca3af)}input[readonly].svelte-kgylqb{cursor:pointer}.icon-wrap.svelte-kgylqb{color:var(--body-text-color-subdued, #9ca3af);width:16px;flex-shrink:0;pointer-events:none}.options.svelte-kgylqb{position:fixed;z-index:var(--layer-top, 9999);margin:0;padding:4px 0;box-shadow:0 4px 12px #0000001f;border-radius:var(--input-radius, 8px);border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);min-width:fit-content;overflow:auto;color:var(--body-text-color, #1f2937);list-style:none}.item.svelte-kgylqb{display:flex;cursor:pointer;padding:6px 10px;font-size:13px;word-break:break-word}.item.svelte-kgylqb:hover,.item.active.svelte-kgylqb{background:var(--background-fill-secondary, #f9fafb)}.item.selected.svelte-kgylqb{font-weight:500}.check-mark.svelte-kgylqb{padding-right:6px;min-width:16px;font-size:12px}.check-mark.hide.svelte-kgylqb{visibility:hidden}.section-label.svelte-1kanzy0{font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280)}.locked-project.svelte-1kanzy0{margin-top:4px;font-size:13px;font-weight:500;color:var(--body-text-color, #1f2937);padding:8px 10px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);background:var(--background-fill-secondary, #f9fafb)}.logo-section.svelte-tssf2h{margin-bottom:20px}.logo.svelte-tssf2h{width:80%;max-width:200px}.checkbox-container.svelte-oj84db{display:flex;align-items:center;gap:8px;cursor:pointer;padding:3px 0}.label-text.svelte-oj84db{color:var(--body-text-color, #1f2937);font-size:13px;line-height:1.4}input[type=checkbox].svelte-oj84db{--ring-color: transparent;position:relative;-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;box-shadow:var(--checkbox-shadow);border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);flex-shrink:0;cursor:pointer;transition:background-color .15s,border-color .15s}input[type=checkbox].svelte-oj84db:checked,input[type=checkbox].svelte-oj84db:checked:hover,input[type=checkbox].svelte-oj84db:checked:focus{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}input[type=checkbox].svelte-oj84db:hover{border-color:var(--checkbox-border-color-hover, #d1d5db);background-color:var(--checkbox-background-color-hover, white)}input[type=checkbox].svelte-oj84db:focus{border-color:var(--checkbox-border-color-focus, #f97316);background-color:var(--checkbox-background-color-focus, white);outline:none}.slider-wrap.svelte-wei6ev{display:flex;flex-direction:column;width:100%}.head.svelte-wei6ev{margin-bottom:4px;display:flex;justify-content:space-between;align-items:center;width:100%}.label.svelte-wei6ev{flex:1;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280)}.info.svelte-wei6ev{display:block;font-size:12px;color:var(--body-text-color-subdued, #9ca3af);margin-bottom:4px}.slider-input-container.svelte-wei6ev{display:flex;align-items:center;gap:6px}input[type=range].svelte-wei6ev{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;cursor:pointer;outline:none;border-radius:var(--radius-xl, 12px);min-width:var(--size-28, 112px);background:transparent}input[type=range].svelte-wei6ev::-webkit-slider-runnable-track{height:6px;border-radius:var(--radius-xl, 12px);background:linear-gradient(to right,var(--slider-color, #f97316) var(--range_progress, 50%),var(--neutral-200, #e5e7eb) var(--range_progress, 50%))}input[type=range].svelte-wei6ev::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:16px;width:16px;background-color:var(--slider-color, #f97316);border:2px solid var(--background-fill-primary, white);border-radius:50%;margin-top:-5px;box-shadow:0 0 0 1px var(--border-color-primary, rgba(0, 0, 0, .08)),0 1px 3px #0003}input[type=range].svelte-wei6ev::-moz-range-track{height:6px;background:var(--neutral-200, #e5e7eb);border-radius:var(--radius-xl, 12px)}input[type=range].svelte-wei6ev::-moz-range-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:16px;width:16px;background-color:var(--slider-color, #f97316);border:2px solid var(--background-fill-primary, white);border-radius:50%;box-shadow:0 0 0 1px var(--border-color-primary, rgba(0, 0, 0, .08)),0 1px 3px #0003}input[type=range].svelte-wei6ev::-moz-range-progress{height:6px;background-color:var(--slider-color, #f97316);border-radius:var(--radius-xl, 12px)}.bound.svelte-wei6ev{font-size:11px;color:var(--body-text-color-subdued, #9ca3af);min-width:12px;text-align:center}.textbox-container.svelte-6yncpg{width:100%}.label.svelte-6yncpg{display:block;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);margin-bottom:6px}.info.svelte-6yncpg{display:block;font-size:12px;color:var(--body-text-color-subdued, #9ca3af);margin-bottom:4px}.input-wrap.svelte-6yncpg{border-radius:var(--input-radius, 8px);background:var(--input-background-fill, white);border:1px solid var(--border-color-primary, #e5e7eb);transition:border-color .15s,box-shadow .15s}.input-wrap.svelte-6yncpg:focus-within{border-color:var(--input-border-color-focus, #fdba74);box-shadow:0 0 0 2px var(--primary-50, #fff7ed)}input.svelte-6yncpg{width:100%;padding:7px 10px;outline:none;border:none;background:transparent;color:var(--body-text-color, #1f2937);font-size:13px;font-family:inherit;border-radius:var(--input-radius, 8px)}input.svelte-6yncpg::placeholder{color:var(--input-placeholder-color, #9ca3af)}.sidebar.svelte-181dlmc{width:290px;min-width:290px;background:var(--background-fill-primary, white);border-right:1px solid var(--border-color-primary, #e5e7eb);display:flex;flex-direction:column;position:relative;overflow:hidden;transition:width .2s,min-width .2s}.sidebar.collapsed.svelte-181dlmc{width:40px;min-width:40px}.toggle-btn.svelte-181dlmc{position:absolute;top:12px;right:8px;z-index:10;border:none;background:none;color:var(--body-text-color-subdued, #9ca3af);cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm, 4px);transition:color .15s,background-color .15s}.toggle-btn.svelte-181dlmc:hover{color:var(--body-text-color, #1f2937);background-color:var(--background-fill-secondary, #f9fafb)}.sidebar-content.svelte-181dlmc{padding:16px;flex:1;min-height:0;display:flex;flex-direction:column}.sidebar-scroll.svelte-181dlmc{overflow-y:auto;flex:1;min-height:0}.oauth-footer.svelte-181dlmc{flex-shrink:0;margin-top:12px;padding-top:12px;border-top:1px solid var(--border-color-primary, #e5e7eb)}.readonly-footer.svelte-181dlmc{flex-shrink:0;margin-top:12px;padding-top:12px;border-top:1px solid var(--border-color-primary, #e5e7eb);display:flex;align-items:center;gap:8px;flex-wrap:wrap}.readonly-badge.svelte-181dlmc{display:inline-flex;align-items:center;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:999px;padding:2px 8px;font-size:10px;letter-spacing:.06em;font-weight:600;color:var(--body-text-color-subdued, #6b7280);background:var(--background-fill-secondary, #f9fafb)}.readonly-link.svelte-181dlmc{font-size:12px;color:var(--body-text-color-subdued, #6b7280);text-decoration:none;max-width:100%;overflow-wrap:anywhere}.readonly-link.svelte-181dlmc:hover{color:var(--body-text-color, #1f2937);text-decoration:underline}.oauth-line.svelte-181dlmc{margin:0;font-size:12px;line-height:1.4;color:var(--body-text-color-subdued, #6b7280)}.oauth-warn.svelte-181dlmc{color:var(--body-text-color, #92400e)}.hf-login-btn.svelte-181dlmc{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:8px 12px;font-size:13px;font-weight:600;color:#fff;background:#141c2e;border-radius:var(--radius-lg, 8px);text-decoration:none;border:none;cursor:pointer;box-sizing:border-box}.hf-login-btn.svelte-181dlmc:hover{background:#283042}.hf-logo.svelte-181dlmc{width:20px;height:20px;flex-shrink:0}.oauth-hint.svelte-181dlmc{margin:8px 0 0;font-size:11px;line-height:1.35;color:var(--body-text-color-subdued, #9ca3af)}.oauth-signed-in.svelte-181dlmc{margin:0;font-size:12px;color:var(--body-text-color-subdued, #6b7280)}.oauth-logout.svelte-181dlmc{font-size:12px;color:var(--body-text-color-subdued, #9ca3af);text-decoration:none;cursor:pointer}.oauth-logout.svelte-181dlmc:hover{text-decoration:underline;color:var(--body-text-color, #1f2937)}.section.svelte-181dlmc{margin-top:2px;margin-bottom:18px}.share-tabs.svelte-181dlmc{display:flex;gap:6px;margin-bottom:8px}.share-tab-btn.svelte-181dlmc{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);padding:4px 8px;font-size:12px;color:var(--body-text-color-subdued, #6b7280);background:var(--background-fill-primary, white);cursor:pointer}.share-tab-btn.active.svelte-181dlmc{color:var(--body-text-color, #1f2937);background:var(--background-fill-secondary, #f9fafb)}.share-field.svelte-181dlmc{display:flex;flex-direction:column;gap:6px}.share-input-row.svelte-181dlmc{display:flex;gap:6px;align-items:stretch}.share-input-row.svelte-181dlmc input:where(.svelte-181dlmc),.share-input-row.svelte-181dlmc textarea:where(.svelte-181dlmc){width:100%;min-width:0;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);padding:6px 8px;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:var(--body-text-color, #1f2937);background:var(--background-fill-secondary, #f9fafb);resize:vertical}.copy-btn.svelte-181dlmc{box-sizing:border-box;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);padding:6px 10px;min-width:3.25rem;display:inline-flex;align-items:center;justify-content:center;font-size:12px;line-height:1;color:var(--body-text-color, #1f2937);background:var(--background-fill-primary, white);cursor:pointer;flex-shrink:0}.copy-btn-check.svelte-181dlmc{display:block;color:var(--color-accent, #f97316)}.share-hint.svelte-181dlmc{margin:0;font-size:12px;line-height:1.4;color:var(--body-text-color-subdued, #9ca3af)}.section-label.svelte-181dlmc{font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280)}.runs-header.svelte-181dlmc{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.select-all-label.svelte-181dlmc{display:flex;align-items:center;gap:6px;cursor:pointer}.select-all-cb.svelte-181dlmc{-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);cursor:pointer;flex-shrink:0;position:relative;transition:background-color .15s,border-color .15s}.select-all-cb.svelte-181dlmc:checked{background-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));border-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));background-image:var(--checkbox-check)}.select-all-cb.svelte-181dlmc:indeterminate{background-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));border-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='3' y='7' width='10' height='2' rx='1'/%3E%3C/svg%3E");background-size:12px;background-position:center;background-repeat:no-repeat}.latest-toggle.svelte-181dlmc{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--body-text-color-subdued, #6b7280);cursor:pointer}.latest-toggle.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc){-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;margin:0;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);box-shadow:var(--checkbox-shadow);cursor:pointer;flex-shrink:0;transition:background-color .15s,border-color .15s}.latest-toggle.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc):checked{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}.checkbox-list.svelte-181dlmc{max-height:300px;overflow-y:auto;margin-top:8px}.device-group.svelte-181dlmc{margin-top:14px;padding-top:12px;border-top:1px solid var(--border-color-primary, #e5e7eb)}.section-sublabel.svelte-181dlmc{font-size:12px;font-weight:600;color:var(--body-text-color-subdued, #6b7280)}.checkbox-group.svelte-181dlmc{display:flex;flex-direction:column;margin-top:8px}.checkbox-item.svelte-181dlmc{display:flex;align-items:center;gap:8px;padding:3px 0;cursor:pointer;font-size:13px}.checkbox-item.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc){-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;margin:0;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);box-shadow:var(--checkbox-shadow);cursor:pointer;flex-shrink:0;transition:background-color .15s,border-color .15s}.checkbox-item.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc):checked{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}.checkbox-item.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc):hover{border-color:var(--checkbox-border-color-hover, #d1d5db)}.run-name.svelte-181dlmc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--body-text-color, #1f2937)}.group-by-row.svelte-181dlmc{margin-top:8px}.grouped-runs.svelte-181dlmc{margin-top:8px;display:flex;flex-direction:column;gap:6px}.run-group-section.svelte-181dlmc{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);overflow:hidden}.run-group-header.svelte-181dlmc{display:flex;align-items:center;padding:6px 10px;background:var(--background-fill-secondary, #f9fafb);border-bottom:1px solid var(--border-color-primary, #e5e7eb)}.run-group-label.svelte-181dlmc{font-size:12px;font-weight:600;color:var(--body-text-color, #1f2937);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:160px}.run-group-count.svelte-181dlmc{font-size:11px;color:var(--body-text-color-subdued, #9ca3af);margin-left:4px;flex-shrink:0}.group-checkbox-list.svelte-181dlmc{padding:4px 10px;max-height:none}.alert-panel.svelte-x5aqew{position:fixed;bottom:16px;right:16px;width:380px;max-height:400px;background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);box-shadow:var(--shadow-drop-lg);z-index:1000;overflow:hidden;display:flex;flex-direction:column}.alert-panel.collapsed.svelte-x5aqew{max-height:none}.alert-header.svelte-x5aqew{padding:10px 12px;border:none;border-bottom:1px solid var(--border-color-primary, #e5e7eb);background:none;width:100%;display:flex;align-items:center;justify-content:space-between;cursor:pointer;gap:8px}.alert-panel.collapsed.svelte-x5aqew .alert-header:where(.svelte-x5aqew){border-bottom:none}.collapse-icon.svelte-x5aqew{color:var(--body-text-color-subdued, #9ca3af);flex-shrink:0;transition:transform .15s}.collapse-icon.rotated.svelte-x5aqew{transform:rotate(-90deg)}.alert-title.svelte-x5aqew{font-size:13px;font-weight:600;color:var(--body-text-color, #1f2937)}.filter-pills.svelte-x5aqew{display:flex;gap:4px}.pill.svelte-x5aqew{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-xxl, 22px);padding:2px 8px;font-size:11px;background:var(--background-fill-secondary, #f9fafb);color:var(--body-text-color-subdued, #6b7280);cursor:pointer}.pill.active.svelte-x5aqew{background:var(--color-accent, #f97316);color:#fff;border-color:var(--color-accent, #f97316)}.alert-list.svelte-x5aqew{overflow-y:auto;flex:1}.alert-item.svelte-x5aqew{border-bottom:1px solid var(--neutral-100, #f3f4f6)}.alert-row.svelte-x5aqew{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;font-size:var(--text-sm, 12px)}.alert-row.svelte-x5aqew:hover{background:var(--background-fill-secondary, #f9fafb)}.alert-text.svelte-x5aqew{flex:1;color:var(--body-text-color, #1f2937)}.alert-meta.svelte-x5aqew{font-size:var(--text-xs, 10px);color:var(--body-text-color-subdued, #9ca3af);white-space:nowrap}.alert-detail.svelte-x5aqew{padding:4px 12px 8px 32px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.plot-container.svelte-9thu1j{min-width:350px;flex:1;background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:12px;overflow:hidden;position:relative}.plot-container[draggable=true].svelte-9thu1j{cursor:grab}.plot-container[draggable=true].svelte-9thu1j:active{cursor:grabbing}.hidden-plot.svelte-9thu1j{visibility:hidden;height:0;padding:0;margin:0;border:none;overflow:hidden;pointer-events:none}.drag-handle.svelte-9thu1j{position:absolute;top:8px;left:8px;color:var(--body-text-color-subdued, #9ca3af);opacity:0;transition:opacity .15s;z-index:5}.plot-container.svelte-9thu1j:hover .drag-handle:where(.svelte-9thu1j){opacity:.5}.drag-handle.svelte-9thu1j:hover{opacity:1!important}.plot-toolbar.svelte-9thu1j{position:absolute;top:8px;right:8px;display:flex;gap:4px;z-index:5;opacity:0;transition:opacity .15s}.plot-container.svelte-9thu1j:hover .plot-toolbar:where(.svelte-9thu1j){opacity:1}.toolbar-btn.svelte-9thu1j{border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;padding:4px 6px;border-radius:var(--radius-sm, 4px);display:flex;align-items:center;justify-content:center}.toolbar-btn.svelte-9thu1j:hover{background:var(--neutral-100, #f3f4f6);color:var(--body-text-color, #1f2937)}.plot-chart-wrap.svelte-9thu1j{position:relative;width:100%}.plot-chart-wrap--fs.svelte-9thu1j{flex:1;min-height:0;display:flex;flex-direction:column}.reset-zoom-btn.svelte-9thu1j{position:absolute;bottom:1px;right:1px;z-index:6;display:inline-flex;align-items:center;justify-content:center;margin:0;min-width:52px;padding:5px 12px 5px 10px;border:none;border-radius:4px;background:transparent;color:var(--body-text-color-subdued, #334155);cursor:pointer;opacity:.92;transform:translateY(6px);transition:opacity .15s ease,color .15s ease,background .15s ease;box-shadow:none}.reset-zoom-btn.svelte-9thu1j:hover{opacity:1;color:var(--body-text-color, #0f172a);background:var(--background-fill-secondary, rgba(226, 232, 240, .85));transform:translateY(6px)}.reset-zoom-btn.svelte-9thu1j svg:where(.svelte-9thu1j){display:block;flex-shrink:0;filter:drop-shadow(0 0 .5px rgba(255,255,255,.95))}.plot-title.svelte-9thu1j{font-size:13px;font-weight:600;color:var(--body-text-color, #374151);text-align:center;padding:0 0 6px;word-break:break-word}.plot-title--fs.svelte-9thu1j{flex-shrink:0}.plot.svelte-9thu1j{width:100%}.plot.svelte-9thu1j .vega-embed{width:100%!important}.plot.svelte-9thu1j .vega-embed summary{display:none}.fullscreen-host.svelte-9thu1j{position:fixed;top:0;right:0;bottom:0;left:0;z-index:10000;box-sizing:border-box;display:flex;flex-direction:column;background:var(--background-fill-primary, white);padding:12px;gap:8px;pointer-events:auto}.fullscreen-host.svelte-9thu1j:fullscreen{width:100%;height:100%}.fullscreen-host.svelte-9thu1j:-webkit-full-screen{width:100%;height:100%}.fullscreen-toolbar.svelte-9thu1j{flex-shrink:0;display:flex;justify-content:flex-end;gap:4px;z-index:5}.fullscreen-chart-wrap.svelte-9thu1j{flex:1;min-height:0;display:flex;flex-direction:column}.fullscreen-legend.svelte-9thu1j{flex-shrink:0}.fullscreen-plot.svelte-9thu1j{flex:1;min-height:0;width:100%;overflow:hidden}.fullscreen-plot.svelte-9thu1j .vega-embed{width:100%!important;height:100%!important;min-height:0;display:flex;flex-direction:column}.fullscreen-plot.svelte-9thu1j .vega-embed .vega-view{flex:1;min-height:0}.fullscreen-plot.svelte-9thu1j .vega-embed summary{display:none}.custom-legend.svelte-9thu1j{display:flex;align-items:center;justify-content:center;gap:12px;padding:6px 0 0;flex-wrap:wrap}.legend-title.svelte-9thu1j{font-size:11px;color:var(--body-text-color-subdued, #6b7280);font-weight:600}.legend-item.svelte-9thu1j{display:flex;align-items:center;gap:4px}.legend-dot.svelte-9thu1j{width:10px;height:10px;border-radius:50%;flex-shrink:0}.legend-line-swatch.svelte-9thu1j{width:24px;height:10px;flex-shrink:0;color:var(--body-text-color, #1f2937)}.legend-label.svelte-9thu1j{font-size:11px;color:var(--body-text-color-subdued, #6b7280)}.legend-toggle.svelte-9thu1j{font-size:11px;color:var(--body-text-color-subdued, #6b7280);background:none;border:none;padding:0 4px;cursor:pointer;text-decoration:underline}.legend-toggle.svelte-9thu1j:hover{color:var(--body-text-color, #1f2937)}.plot-container.svelte-1swghqy{min-width:350px;flex:1;background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:12px;overflow:hidden;position:relative}.plot-container[draggable=true].svelte-1swghqy{cursor:grab}.plot-container[draggable=true].svelte-1swghqy:active{cursor:grabbing}.hidden-plot.svelte-1swghqy{visibility:hidden;height:0;padding:0;margin:0;border:none;overflow:hidden;pointer-events:none}.drag-handle.svelte-1swghqy{position:absolute;top:8px;left:8px;color:var(--body-text-color-subdued, #9ca3af);opacity:0;transition:opacity .15s;z-index:5}.plot-container.svelte-1swghqy:hover .drag-handle:where(.svelte-1swghqy){opacity:.5}.drag-handle.svelte-1swghqy:hover{opacity:1!important}.plot-toolbar.svelte-1swghqy{position:absolute;top:8px;right:8px;display:flex;gap:4px;z-index:5;opacity:0;transition:opacity .15s}.plot-container.svelte-1swghqy:hover .plot-toolbar:where(.svelte-1swghqy){opacity:1}.toolbar-btn.svelte-1swghqy{border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;padding:4px 6px;border-radius:var(--radius-sm, 4px);display:flex;align-items:center;justify-content:center}.toolbar-btn.svelte-1swghqy:hover{background:var(--neutral-100, #f3f4f6);color:var(--body-text-color, #1f2937)}.plot-chart-wrap.svelte-1swghqy{position:relative;width:100%}.plot-chart-wrap--fs.svelte-1swghqy{flex:1;min-height:0;display:flex;flex-direction:column}.plot-title.svelte-1swghqy{font-size:13px;font-weight:600;color:var(--body-text-color, #374151);text-align:center;padding:0 0 6px;word-break:break-word}.plot-title--fs.svelte-1swghqy{flex-shrink:0}.plot.svelte-1swghqy{width:100%}.plot.svelte-1swghqy .vega-embed{width:100%!important}.plot.svelte-1swghqy .vega-embed summary{display:none}.fullscreen-host.svelte-1swghqy{position:fixed;top:0;right:0;bottom:0;left:0;z-index:10000;box-sizing:border-box;display:flex;flex-direction:column;background:var(--background-fill-primary, white);padding:12px;gap:8px;pointer-events:auto}.fullscreen-host.svelte-1swghqy:fullscreen{width:100%;height:100%}.fullscreen-host.svelte-1swghqy:-webkit-full-screen{width:100%;height:100%}.fullscreen-toolbar.svelte-1swghqy{flex-shrink:0;display:flex;justify-content:flex-end;gap:4px;z-index:5}.fullscreen-chart-wrap.svelte-1swghqy{flex:1;min-height:0;display:flex;flex-direction:column}.fullscreen-legend.svelte-1swghqy{flex-shrink:0}.fullscreen-plot.svelte-1swghqy{flex:1;min-height:0;width:100%;overflow:hidden}.fullscreen-plot.svelte-1swghqy .vega-embed{width:100%!important;height:100%!important;min-height:0;display:flex;flex-direction:column}.fullscreen-plot.svelte-1swghqy .vega-embed .vega-view{flex:1;min-height:0}.fullscreen-plot.svelte-1swghqy .vega-embed summary{display:none}.custom-legend.svelte-1swghqy{display:flex;align-items:center;justify-content:center;gap:12px;padding:6px 0 0;flex-wrap:wrap}.legend-item.svelte-1swghqy{display:flex;align-items:center;gap:4px}.legend-dot.svelte-1swghqy{width:10px;height:10px;border-radius:50%;flex-shrink:0}.legend-label.svelte-1swghqy{font-size:11px;color:var(--body-text-color-subdued, #6b7280)}.legend-toggle.svelte-1swghqy{font-size:11px;color:var(--body-text-color-subdued, #6b7280);background:none;border:none;padding:0 4px;cursor:pointer;text-decoration:underline}.legend-toggle.svelte-1swghqy:hover{color:var(--body-text-color, #1f2937)}.accordion.svelte-1jep0a{margin-bottom:12px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);background:var(--background-fill-primary, white);overflow:hidden}.accordion-hidden.svelte-1jep0a{margin-bottom:8px}.accordion-header.svelte-1jep0a{display:flex;align-items:center;gap:8px;width:100%;padding:10px 14px;border:none;background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:var(--text-md, 14px);font-weight:600;cursor:pointer;text-align:left}.accordion-header.svelte-1jep0a:hover{background:var(--background-fill-secondary, #f9fafb)}.arrow.svelte-1jep0a{font-size:14px;transition:transform .15s;color:var(--body-text-color, #1f2937);display:inline-block}.arrow.svelte-1jep0a:not(.rotated){transform:rotate(-90deg)}.accordion-body.svelte-1jep0a{padding:0 14px 14px}.trackio-loading.svelte-1kc6b2l{display:flex;align-items:center;justify-content:center;width:100%;min-height:min(70vh,640px);padding:32px 24px;box-sizing:border-box;background:transparent}.logo-stack.svelte-1kc6b2l{position:relative;width:min(100%,200px);max-width:min(92vw,200px);line-height:0;background:transparent;isolation:isolate}.logo-base.svelte-1kc6b2l{display:block;background:transparent}.logo-img.svelte-1kc6b2l{width:100%;height:auto;display:block;background:transparent}.logo-overlay.svelte-1kc6b2l{position:absolute;left:0;top:0;width:100%;animation:svelte-1kc6b2l-trackio-logo-sweep 4s linear infinite;pointer-events:none;background:transparent}.logo-overlay.svelte-1kc6b2l .logo-img:where(.svelte-1kc6b2l){width:100%;height:auto;object-position:left center}.logo-img--gray.svelte-1kc6b2l{filter:grayscale(1)}@keyframes svelte-1kc6b2l-trackio-logo-sweep{0%{clip-path:inset(0 0 0 0)}50%{clip-path:inset(0 0 0 100%)}to{clip-path:inset(0 0 0 0)}}@media(prefers-reduced-motion:reduce){.logo-overlay.svelte-1kc6b2l{display:none}}.sr-only.svelte-1kc6b2l{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.metrics-page.svelte-2bul55{padding:20px 24px;overflow-y:auto;flex:1;min-height:0}.plot-grid.svelte-2bul55{display:flex;flex-wrap:wrap;gap:16px}.subgroup-list.svelte-2bul55{margin-top:16px}.empty-state.svelte-2bul55{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-2bul55 h2:where(.svelte-2bul55){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-2bul55 p:where(.svelte-2bul55){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-2bul55 pre:where(.svelte-2bul55){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-2bul55 code:where(.svelte-2bul55){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-2bul55 pre:where(.svelte-2bul55) code:where(.svelte-2bul55){background:none;padding:0}.traces-page.svelte-1s32ifo{padding:20px 24px;overflow-y:auto;flex:1;background:var(--background-fill-primary, white)}.toolbar.svelte-1s32ifo{display:flex;align-items:center;gap:12px;margin-bottom:16px}.search-wrap.svelte-1s32ifo{flex:1}.search-wrap.svelte-1s32ifo input:where(.svelte-1s32ifo),.filter-wrap.svelte-1s32ifo select:where(.svelte-1s32ifo){width:100%;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:14px;padding:10px 12px;font-family:inherit}.filter-wrap.svelte-1s32ifo{display:flex;align-items:center;gap:8px;color:var(--body-text-color, #1f2937);font-size:14px;white-space:nowrap}.count.svelte-1s32ifo{margin-left:auto;color:var(--body-text-color-subdued, #6b7280);font-size:14px;white-space:nowrap}.traces-table-wrap.svelte-1s32ifo{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);overflow:hidden;transition:opacity .15s ease}.traces-table-wrap.dim.svelte-1s32ifo{opacity:.55}.traces-table.svelte-1s32ifo{width:100%;border-collapse:collapse;font-size:14px;table-layout:fixed}.trace-id-col.svelte-1s32ifo{width:140px}.request-col.svelte-1s32ifo{width:auto}.run-col.svelte-1s32ifo{width:180px}.step-col.svelte-1s32ifo{width:76px}.request-time-col.svelte-1s32ifo{width:150px}.traces-table.svelte-1s32ifo th:where(.svelte-1s32ifo){text-align:left;padding:10px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.05em;background:var(--background-fill-primary, white)}.traces-table.svelte-1s32ifo td:where(.svelte-1s32ifo){padding:10px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937);vertical-align:top}.trace-row.svelte-1s32ifo{cursor:pointer}.trace-row.svelte-1s32ifo:hover{background:var(--background-fill-secondary, #f9fafb)}.trace-id-chip.svelte-1s32ifo{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;color:var(--body-text-color, #1f2937)}.request.svelte-1s32ifo{font-weight:500;margin-bottom:4px}.preview.svelte-1s32ifo{color:var(--body-text-color-subdued, #6b7280);font-size:13px;line-height:1.45;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.expanded-row.svelte-1s32ifo td:where(.svelte-1s32ifo){padding:0;background:var(--background-fill-secondary, #fafafa)}.trace-detail.svelte-1s32ifo{padding:16px 18px 18px}.detail-meta.svelte-1s32ifo{display:flex;gap:16px;flex-wrap:wrap;color:var(--body-text-color-subdued, #6b7280);font-size:13px;margin-bottom:14px}.conversation.svelte-1s32ifo{display:flex;flex-direction:column;gap:12px}.message.svelte-1s32ifo{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);background:var(--background-fill-primary, white);padding:12px}.message-role.svelte-1s32ifo{margin-bottom:8px;color:var(--body-text-color-subdued, #6b7280);font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.message-tag.svelte-1s32ifo{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:999px;padding:2px 8px;font-size:11px;font-weight:500;text-transform:none;letter-spacing:0}.message-content.svelte-1s32ifo,.tool-block.svelte-1s32ifo{margin:0;white-space:pre-wrap;word-break:break-word;font-family:inherit;color:var(--body-text-color, #1f2937);line-height:1.5}.message-details.svelte-1s32ifo summary:where(.svelte-1s32ifo){cursor:pointer;margin-bottom:8px;color:var(--body-text-color-subdued, #6b7280)}.tool-blocks.svelte-1s32ifo{display:flex;flex-direction:column;gap:8px;margin-top:10px}.tool-block.svelte-1s32ifo{background:var(--background-fill-secondary, #f9fafb);border-radius:var(--radius-md, 6px);padding:10px;overflow-x:auto}.message-parts.svelte-1s32ifo{display:flex;flex-direction:column;gap:10px}.trace-image.svelte-1s32ifo{max-width:100%;max-height:360px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px)}.empty-state.svelte-1s32ifo{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1s32ifo h2:where(.svelte-1s32ifo){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1s32ifo p:where(.svelte-1s32ifo){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.pagination.svelte-1s32ifo{display:flex;align-items:center;justify-content:center;gap:12px;padding:16px 0 4px}.pagination.svelte-1s32ifo button:where(.svelte-1s32ifo){border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:14px;padding:8px 14px;cursor:pointer;font-family:inherit}.pagination.svelte-1s32ifo button:where(.svelte-1s32ifo):hover:not(:disabled){background:var(--background-fill-secondary, #f9fafb)}.pagination.svelte-1s32ifo button:where(.svelte-1s32ifo):disabled{opacity:.5;cursor:not-allowed}.page-info.svelte-1s32ifo{color:var(--body-text-color-subdued, #6b7280);font-size:14px;min-width:120px;text-align:center}@media(max-width:1100px){.toolbar.svelte-1s32ifo{flex-wrap:wrap}.count.svelte-1s32ifo{margin-left:0}}.system-page.svelte-nv5os4{padding:20px 24px;overflow-y:auto;flex:1;min-height:0}.plot-grid.svelte-nv5os4{display:flex;flex-wrap:wrap;gap:12px}.subgroup-list.svelte-nv5os4{margin-top:16px}.empty-state.svelte-nv5os4{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-nv5os4 h2:where(.svelte-nv5os4){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-nv5os4 p:where(.svelte-nv5os4){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-nv5os4 pre:where(.svelte-nv5os4){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-nv5os4 ul:where(.svelte-nv5os4){list-style:disc;padding-left:20px;margin:4px 0 0}.empty-state.svelte-nv5os4 li:where(.svelte-nv5os4){margin:4px 0;color:var(--body-text-color, #1f2937)}.empty-state.svelte-nv5os4 code:where(.svelte-nv5os4){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-nv5os4 pre:where(.svelte-nv5os4) code:where(.svelte-nv5os4){background:none;padding:0}.wave-wrap.svelte-19wbodf{--wave-base: var(--body-text-color-subdued, #9ca3af);--wave-played: var(--color-accent, #f97316);display:flex;align-items:center;gap:8px;padding:8px 10px;background:var(--background-fill-secondary, #f9fafb);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);color:var(--body-text-color, #1f2937)}.play-btn.svelte-19wbodf{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;background:var(--color-accent, #f97316);color:#fff;border:none;cursor:pointer;flex-shrink:0;padding:0}.play-btn.svelte-19wbodf:disabled{opacity:.4;cursor:not-allowed}.play-btn.svelte-19wbodf:hover:not(:disabled){filter:brightness(1.1)}.wave.svelte-19wbodf{flex:1;height:32px;min-width:0;cursor:pointer}.time.svelte-19wbodf{font-size:11px;color:var(--body-text-color-subdued, #6b7280);font-variant-numeric:tabular-nums;flex-shrink:0}audio.svelte-19wbodf{display:none}.media-page.svelte-outb32{padding:20px 24px;overflow-y:auto;flex:1}.section.svelte-outb32{margin:16px 0}.section-heading.svelte-outb32,.image-section-controls.svelte-outb32{display:flex;align-items:center;gap:8px}.image-section-summary.svelte-outb32{justify-content:space-between;gap:12px}.image-section-controls.svelte-outb32{flex:1;justify-content:flex-end}.media-control.svelte-outb32{display:flex;align-items:center;gap:8px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.media-control.svelte-outb32 select:where(.svelte-outb32){height:30px;border:1px solid var(--border-color-primary, #d1d5db);border-radius:var(--radius-sm, 4px);background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:var(--text-sm, 12px);padding:0 28px 0 8px}.section-summary.svelte-outb32{display:flex;align-items:center;gap:6px;cursor:pointer;list-style:none;-webkit-user-select:none;user-select:none;padding:4px 0;margin-bottom:8px}.section-summary.svelte-outb32::-webkit-details-marker{display:none}.chevron.svelte-outb32{color:var(--body-text-color-subdued, #6b7280);transform:rotate(-90deg);transition:transform .15s ease;flex-shrink:0}details[open].svelte-outb32>.section-summary:where(.svelte-outb32) .chevron:where(.svelte-outb32){transform:rotate(0)}.section-title.svelte-outb32{font-size:var(--text-lg, 16px);font-weight:600;color:var(--body-text-color, #1f2937)}.media-label.svelte-outb32{font-size:var(--text-sm, 12px);font-weight:500;color:var(--body-text-color, #1f2937);word-break:break-word}.meta.svelte-outb32{display:flex;align-items:center;gap:3px;font-size:var(--text-xs, 11px);color:var(--body-text-color-subdued, #9ca3af);font-variant-numeric:tabular-nums}.meta.svelte-outb32 .run-dot:where(.svelte-outb32){width:8px;height:8px;border-radius:50%;flex-shrink:0;margin:0 2px}.meta-text.svelte-outb32{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.table-header.svelte-outb32{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:6px}.runs-table.svelte-outb32{width:100%;border-collapse:collapse;font-size:var(--text-md, 14px)}.runs-table.svelte-outb32 th:where(.svelte-outb32){text-align:left;padding:8px 12px;border-bottom:2px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);font-weight:600;font-size:var(--text-sm, 12px);text-transform:uppercase;letter-spacing:.05em}.runs-table.svelte-outb32 td:where(.svelte-outb32){padding:8px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.runs-table.svelte-outb32 tbody:where(.svelte-outb32) tr:where(.svelte-outb32):nth-child(odd){background:var(--table-odd-background-fill, var(--background-fill-primary, white))}.runs-table.svelte-outb32 tbody:where(.svelte-outb32) tr:where(.svelte-outb32):nth-child(2n){background:var(--table-even-background-fill, var(--background-fill-secondary, #f9fafb))}.runs-table.svelte-outb32 tr:where(.svelte-outb32):hover{background:var(--background-fill-secondary, #f3f4f6)}.table-image-frame.svelte-outb32{position:relative;display:inline-flex;width:120px;height:80px;align-items:center;justify-content:center;overflow:hidden;border:0;border-radius:var(--radius-sm, 4px);background:var(--background-fill-secondary, #f3f4f6);color:var(--body-text-color-subdued, #6b7280);cursor:zoom-in;font:inherit;padding:0;text-decoration:none;vertical-align:top}.table-image-placeholder.svelte-outb32{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;font-size:var(--text-xs, 11px)}.table-image-frame.svelte-outb32.image-loaded .table-image-placeholder:where(.svelte-outb32){display:none}.table-image-frame.svelte-outb32.image-failed .table-image-placeholder:where(.svelte-outb32){color:var(--error-text-color, #b91c1c)}.table-image.svelte-outb32{position:relative;z-index:1;max-height:80px;max-width:120px;border-radius:var(--radius-sm, 4px);display:block;object-fit:contain}.table-image-list.svelte-outb32{display:flex;flex-wrap:wrap;gap:4px}.gallery.svelte-outb32{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.gallery-item.svelte-outb32{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);background:var(--background-fill-secondary, #f9fafb);overflow:hidden}.image-frame.svelte-outb32{position:relative;display:block;width:100%;aspect-ratio:4 / 3;overflow:hidden;border:0;border-radius:var(--radius-sm, 4px);background:var(--background-fill-primary, #f3f4f6);color:var(--body-text-color-subdued, #6b7280);cursor:zoom-in;font:inherit;padding:0;text-decoration:none}.image-placeholder.svelte-outb32{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;font-size:var(--text-sm, 12px)}.image-frame.svelte-outb32.image-loaded .image-placeholder:where(.svelte-outb32){display:none}.image-frame.svelte-outb32.image-failed .image-placeholder:where(.svelte-outb32){color:var(--error-text-color, #b91c1c)}.image-frame.svelte-outb32 img:where(.svelte-outb32){position:relative;z-index:1;width:100%;height:100%;display:block;object-fit:contain}.gallery-item.svelte-outb32 video:where(.svelte-outb32){width:100%;display:block;border-radius:var(--radius-sm, 4px)}.audio-gallery-item.svelte-outb32{justify-content:space-between}.caption.svelte-outb32{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #9ca3af)}.image-filter.svelte-outb32{width:min(320px,100%)}.image-filter.svelte-outb32 input:where(.svelte-outb32){width:100%;padding:7px 10px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--input-radius, 8px);background:var(--input-background-fill, white);color:var(--body-text-color, #1f2937);font-family:inherit;font-size:13px;outline:none;transition:border-color .15s,box-shadow .15s}.image-filter.svelte-outb32 input:where(.svelte-outb32):focus{border-color:var(--input-border-color-focus, #fdba74);box-shadow:0 0 0 2px var(--primary-50, #fff7ed)}.image-filter.svelte-outb32 input:where(.svelte-outb32)::placeholder{color:var(--input-placeholder-color, #9ca3af)}.empty-filter-state.svelte-outb32{padding:16px 0;color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px)}.image-modal-backdrop.svelte-outb32{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:32px;background:#000000bf}.image-modal.svelte-outb32{position:relative;display:flex;max-width:min(92vw,1200px);max-height:92vh;flex-direction:column;overflow:hidden;border-radius:var(--radius-lg, 8px);background:var(--background-fill-primary, white);box-shadow:0 20px 60px #00000059}.image-modal-close.svelte-outb32{position:absolute;top:8px;right:8px;z-index:2;width:32px;height:32px;border:0;border-radius:999px;background:#0000008c;color:#fff;cursor:pointer;font-size:24px;line-height:1}.image-modal-nav.svelte-outb32{position:absolute;top:50%;z-index:2;width:48px;height:48px;border:0;border-radius:999px;background:#00000059;color:#fff;cursor:pointer;font-size:40px;line-height:1;transform:translateY(-50%)}.image-modal-nav.svelte-outb32:hover{background:#0000008c}.image-modal-prev.svelte-outb32{left:12px}.image-modal-next.svelte-outb32{right:12px}.modal-image-frame.svelte-outb32{position:relative;display:grid;min-width:min(70vw,720px);min-height:min(65vh,520px);place-items:center;overflow:hidden;background:var(--background-fill-secondary, #f3f4f6);color:var(--body-text-color-subdued, #6b7280)}.modal-image-placeholder.svelte-outb32{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-items:center;font-size:var(--text-sm, 12px)}.modal-image-frame.svelte-outb32.image-loaded .modal-image-placeholder:where(.svelte-outb32){display:none}.modal-image-frame.svelte-outb32.image-failed .modal-image-placeholder:where(.svelte-outb32){color:var(--error-text-color, #b91c1c)}.modal-image-frame.svelte-outb32 img:where(.svelte-outb32){position:relative;z-index:1;max-width:100%;max-height:calc(92vh - 96px);object-fit:contain}.image-modal-info.svelte-outb32{display:flex;flex-direction:column;gap:4px;padding:10px 14px 12px;text-align:center}.image-modal-title.svelte-outb32{font-size:var(--text-md, 14px);font-weight:600;color:var(--body-text-color, #1f2937)}.image-modal-caption.svelte-outb32{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.image-modal-meta.svelte-outb32{justify-content:center}.image-modal-count.svelte-outb32{margin-left:8px}.table-section.svelte-outb32{margin-bottom:16px;overflow-x:auto}.pagination-row.svelte-outb32{display:flex;justify-content:center;align-items:center;gap:12px;margin-top:12px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.load-more-button.svelte-outb32{height:30px;border:1px solid var(--border-color-primary, #d1d5db);border-radius:var(--radius-sm, 4px);background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:var(--text-sm, 12px);font-weight:500;padding:0 10px;cursor:pointer}.load-more-button.svelte-outb32:hover{background:var(--background-fill-secondary, #f9fafb)}.empty-state.svelte-outb32{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-outb32 h2:where(.svelte-outb32){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-outb32 p:where(.svelte-outb32){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-outb32 pre:where(.svelte-outb32){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-outb32 code:where(.svelte-outb32){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-outb32 pre:where(.svelte-outb32) code:where(.svelte-outb32){background:none;padding:0}.reports-page.svelte-iufsej{padding:20px 24px;overflow-y:auto;flex:1}.controls.svelte-iufsej{display:flex;gap:16px;margin-bottom:16px;flex-wrap:wrap;align-items:flex-end}.control.svelte-iufsej{min-width:200px}.filter-pills.svelte-iufsej{display:flex;gap:4px}.pill.svelte-iufsej{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-xxl, 22px);padding:4px 12px;font-size:var(--text-sm, 12px);background:var(--background-fill-secondary, #f9fafb);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;transition:background-color .15s,color .15s}.pill.svelte-iufsej:hover{background:var(--neutral-100, #f3f4f6)}.pill.active.svelte-iufsej{background:var(--color-accent, #f97316);color:#fff;border-color:var(--color-accent, #f97316)}.empty-state.svelte-iufsej{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-iufsej h2:where(.svelte-iufsej){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-iufsej p:where(.svelte-iufsej){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-iufsej pre:where(.svelte-iufsej){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-iufsej code:where(.svelte-iufsej){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-iufsej pre:where(.svelte-iufsej) code:where(.svelte-iufsej){background:none;padding:0}.alerts-table.svelte-iufsej{width:100%;border-collapse:collapse;font-size:var(--text-md, 14px)}.alerts-table.svelte-iufsej th:where(.svelte-iufsej){text-align:left;padding:8px 12px;border-bottom:2px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);font-weight:600;font-size:var(--text-sm, 12px);text-transform:uppercase;letter-spacing:.05em}.alerts-table.svelte-iufsej td:where(.svelte-iufsej){padding:8px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.alerts-table.svelte-iufsej tbody:where(.svelte-iufsej) tr:where(.svelte-iufsej):nth-child(odd){background:var(--table-odd-background-fill, var(--background-fill-primary, white))}.alerts-table.svelte-iufsej tbody:where(.svelte-iufsej) tr:where(.svelte-iufsej):nth-child(2n){background:var(--table-even-background-fill, var(--background-fill-secondary, #f9fafb))}.alerts-table.svelte-iufsej tr:where(.svelte-iufsej):hover{background:var(--background-fill-secondary, #f3f4f6)}.section-title.svelte-iufsej{font-size:16px;font-weight:700;margin:0 0 12px;color:var(--body-text-color, #1f2937)}.reports-section.svelte-iufsej,.alerts-section.svelte-iufsej{margin-bottom:32px}.report-card.svelte-iufsej{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:16px 20px;margin-bottom:12px;background:var(--background-fill-primary, white)}.report-meta.svelte-iufsej{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);margin-bottom:8px}.report-content.svelte-iufsej{font-size:var(--text-md, 14px);color:var(--body-text-color, #1f2937);line-height:1.6}.report-content.svelte-iufsej h2{font-size:18px;font-weight:700;margin:0 0 8px}.report-content.svelte-iufsej h3{font-size:16px;font-weight:600;margin:12px 0 6px}.report-content.svelte-iufsej h4{font-size:14px;font-weight:600;margin:10px 0 4px}.report-content.svelte-iufsej code{background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.report-content.svelte-iufsej ul{margin:4px 0;padding-left:20px}.report-content.svelte-iufsej li{margin:2px 0}.report-content.svelte-iufsej p{margin:6px 0}.filter-empty.svelte-iufsej{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-md, 14px)}.runs-page.svelte-1yb6d54{padding:20px 24px;overflow-y:auto;flex:1}.empty-state.svelte-1yb6d54{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1yb6d54 h2:where(.svelte-1yb6d54){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1yb6d54 p:where(.svelte-1yb6d54){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1yb6d54 pre:where(.svelte-1yb6d54){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-1yb6d54 code:where(.svelte-1yb6d54){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-1yb6d54 pre:where(.svelte-1yb6d54) code:where(.svelte-1yb6d54){background:none;padding:0}.filter-count-row.svelte-1yb6d54{margin-bottom:12px}.filter-count.svelte-1yb6d54{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.runs-table.svelte-1yb6d54{width:100%;border-collapse:collapse;font-size:var(--text-md, 14px)}.runs-table.svelte-1yb6d54 th:where(.svelte-1yb6d54){text-align:left;padding:8px 12px;border-bottom:2px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);font-weight:600;font-size:var(--text-sm, 12px);text-transform:uppercase;letter-spacing:.05em}.runs-table.svelte-1yb6d54 td:where(.svelte-1yb6d54){padding:8px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.runs-table.svelte-1yb6d54 tbody:where(.svelte-1yb6d54) tr:where(.svelte-1yb6d54):nth-child(odd){background:var(--table-odd-background-fill, var(--background-fill-primary, white))}.runs-table.svelte-1yb6d54 tbody:where(.svelte-1yb6d54) tr:where(.svelte-1yb6d54):nth-child(2n){background:var(--table-even-background-fill, var(--background-fill-secondary, #f9fafb))}.runs-table.svelte-1yb6d54 tr:where(.svelte-1yb6d54):hover{background:var(--background-fill-secondary, #f3f4f6)}.run-name-cell.svelte-1yb6d54{font-weight:500}.run-name-with-dot.svelte-1yb6d54{display:inline-flex;align-items:center;gap:8px;max-width:100%}.run-dot.svelte-1yb6d54{width:10px;height:10px;border-radius:50%;flex-shrink:0}.link-btn.svelte-1yb6d54{background:none;border:none;color:var(--color-accent, #f97316);cursor:pointer;font:inherit;font-weight:500;padding:0;text-align:left}.link-btn.svelte-1yb6d54:hover{text-decoration:underline}.rename-input.svelte-1yb6d54{font:inherit;padding:2px 6px;border:1px solid var(--color-accent, #f97316);border-radius:var(--radius-sm, 4px);outline:none;width:100%}.actions-wrap.svelte-1yb6d54{display:flex;gap:4px;align-items:center}.action-btn.svelte-1yb6d54{background:none;border:1px solid transparent;color:var(--body-text-color-subdued, #6b7280);cursor:pointer;padding:4px;border-radius:var(--radius-sm, 4px);display:flex;align-items:center}.action-btn.svelte-1yb6d54:hover{background:var(--background-fill-secondary, #f9fafb);border-color:var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.delete-btn.svelte-1yb6d54:hover{color:#dc2626;border-color:#fecaca;background:#fef2f2}.action-btn.svelte-1yb6d54:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.artifact-counts.svelte-1yb6d54{display:inline-flex;gap:6px}.art-count.svelte-1yb6d54{display:inline-flex;align-items:center;gap:3px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);background:transparent;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:9px;padding:1px 8px;white-space:nowrap}.art-none.svelte-1yb6d54{color:var(--body-text-color-subdued, #9ca3af)}.indent.svelte-1l68cu5{display:flex;align-self:stretch;flex-shrink:0}.indent-guide.svelte-1l68cu5{width:16px;align-self:stretch;position:relative}.indent-guide.svelte-1l68cu5:before{content:"";position:absolute;left:6px;top:0;bottom:0;border-left:1px solid var(--border-color-primary, #e5e7eb)}.version-detail.svelte-pa6cr{border-top:1px solid var(--border-color-primary, #e5e7eb);padding:10px 14px 12px;background:var(--background-fill-secondary, #f9fafb)}.panel.svelte-pa6cr{padding:4px 4px 24px}.panel-header.svelte-pa6cr{border-bottom:1px solid var(--border-color-primary, #e5e7eb);padding-bottom:14px;margin-bottom:16px}.title-row.svelte-pa6cr{display:flex;align-items:center;flex-wrap:wrap;gap:8px}.art-name.svelte-pa6cr{font-size:18px;font-weight:700;color:var(--body-text-color, #1f2937);margin:0;word-break:break-word}.ver-badge.svelte-pa6cr{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--text-sm, 12px);font-weight:600;color:var(--body-text-color-subdued, #6b7280);background:var(--background-fill-secondary, #f3f4f6);border-radius:var(--radius-sm, 4px);padding:2px 7px}.fact-row.svelte-pa6cr{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-top:8px}.fact.svelte-pa6cr{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.type-chip.svelte-pa6cr{text-transform:uppercase;letter-spacing:.04em;font-weight:600}.dot.svelte-pa6cr{color:var(--body-text-color-subdued, #9ca3af)}.use-snippet.svelte-pa6cr{display:flex;align-items:center;gap:8px;margin-top:12px;background:var(--background-fill-secondary, #f9fafb);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);padding:6px 6px 6px 10px;width:fit-content;max-width:min(480px,100%);overflow:hidden}.use-snippet.svelte-pa6cr code:where(.svelte-pa6cr){font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--text-sm, 12px);color:var(--body-text-color, #1f2937);white-space:nowrap;overflow-x:auto;flex:1 1 auto}.tok-mod.svelte-pa6cr{color:var(--body-text-color, #1f2937)}.tok-fn.svelte-pa6cr{color:#8957e5}.tok-str.svelte-pa6cr{color:#1a7f37}.tok-punc.svelte-pa6cr{color:var(--body-text-color-subdued, #6b7280)}.copy-btn.svelte-pa6cr{flex-shrink:0;border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, #fff);color:var(--body-text-color, #374151);border-radius:var(--radius-sm, 4px);padding:3px 10px;font-size:var(--text-xs, 11px);cursor:pointer}.copy-btn.svelte-pa6cr:hover{border-color:var(--color-accent, #f97316);color:var(--color-accent, #f97316)}.copy-btn.small.svelte-pa6cr{padding:1px 8px}.detail-grid.svelte-pa6cr{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin-bottom:10px;align-items:start}.detail-key.svelte-pa6cr{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.detail-val.svelte-pa6cr{font-size:var(--text-sm, 12px);color:var(--body-text-color, #1f2937);word-break:break-word}.digest-val.svelte-pa6cr{display:flex;align-items:center;gap:8px}.digest-text.svelte-pa6cr{word-break:break-all}.mono.svelte-pa6cr{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.run-link.svelte-pa6cr{background:none;border:none;padding:0;font-size:var(--text-sm, 12px);color:var(--color-accent, #f97316);cursor:pointer;text-align:left}.run-link.svelte-pa6cr:hover{text-decoration:underline}.meta-grid.svelte-pa6cr{display:grid;grid-template-columns:max-content 1fr;column-gap:16px;row-gap:0;align-items:stretch}.meta-key-cell.svelte-pa6cr{display:flex;align-items:stretch;min-width:0}.meta-grid.svelte-pa6cr .detail-val:where(.svelte-pa6cr){align-self:center;padding:3px 0}.meta-chevron-spacer.svelte-pa6cr{display:inline-block;width:16px;flex-shrink:0;align-self:center}.meta-leaf-key.svelte-pa6cr{align-self:center;padding:3px 0}.meta-key-row.svelte-pa6cr{display:inline-flex;align-items:center;align-self:center;background:none;border:none;padding:3px 0;margin:0;cursor:pointer;font:inherit;color:var(--body-text-color, #1f2937);text-align:left}.meta-chevron.svelte-pa6cr{display:inline-flex;align-items:center;justify-content:center;width:12px;height:12px;margin-right:4px;flex-shrink:0;color:var(--body-text-color-subdued, #9ca3af);transition:transform .15s}.meta-chevron.open.svelte-pa6cr{transform:rotate(90deg)}.meta-key-label.svelte-pa6cr{font-weight:400;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.meta-key-row.svelte-pa6cr:hover .meta-key-label:where(.svelte-pa6cr){color:var(--color-accent, #f97316)}.meta-node-count.svelte-pa6cr{margin-left:8px;font-size:var(--text-xs, 10px);font-weight:500;color:var(--body-text-color-subdued, #9ca3af)}.meta-preview.svelte-pa6cr{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--text-xs, 11px);color:var(--body-text-color-subdued, #9ca3af);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-table.svelte-pa6cr{display:flex;flex-direction:column}.file-entry.svelte-pa6cr{display:flex;align-items:center;gap:12px;padding:6px 8px;margin:0 -8px;border-radius:var(--radius-sm, 4px);border-top:1px solid var(--border-color-primary, #e5e7eb);color:inherit;text-decoration:none;cursor:pointer}.file-entry.svelte-pa6cr:first-child{border-top:none}.file-entry.svelte-pa6cr:hover{background:var(--background-fill-secondary, #f9fafb);border-top-color:transparent}.spacer.svelte-pa6cr{flex:1 1 auto}.file-path.svelte-pa6cr{font-size:var(--text-sm, 12px);color:var(--body-text-color, #1f2937);word-break:break-all}.file-digest.svelte-pa6cr{font-size:var(--text-xs, 11px);color:var(--body-text-color-subdued, #9ca3af);white-space:nowrap;flex-shrink:0;text-align:right;min-width:88px}.file-size.svelte-pa6cr{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);white-space:nowrap;flex-shrink:0;text-align:right;min-width:56px}.download-icon.svelte-pa6cr{display:flex;align-items:center;justify-content:center;width:20px;height:20px;flex-shrink:0;color:var(--body-text-color-subdued, #9ca3af);transition:color .15s}.file-entry.svelte-pa6cr:hover .download-icon:where(.svelte-pa6cr){color:var(--color-accent, #f97316)}.status.svelte-pa6cr{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);padding:4px 0}.alias-pill.svelte-pa6cr{font-size:var(--text-xs, 11px);padding:1px 7px;border-radius:9px;border:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);background:var(--background-fill-secondary, #f3f4f6);white-space:nowrap}.alias-pill.latest.svelte-pa6cr{color:var(--color-accent, #f97316);border-color:var(--color-accent, #f97316);background:transparent}.run-detail-page.svelte-1bpgsx2{padding:20px 24px;overflow-y:auto;flex:1}.back-link.svelte-1bpgsx2{display:inline-flex;align-items:center;gap:6px;margin:0 0 12px;padding:0;border:0;background:none;color:var(--body-text-color-subdued, #6b7280);font:inherit;font-size:var(--text-sm, 12px);font-weight:500;cursor:pointer}.back-link.svelte-1bpgsx2:hover{color:var(--body-text-color, #1f2937);text-decoration:underline}.detail-card.svelte-1bpgsx2{background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:24px;max-width:800px}.detail-card.svelte-1bpgsx2 h2:where(.svelte-1bpgsx2){color:var(--body-text-color, #1f2937);margin:0 0 16px;font-size:var(--text-xl, 22px)}.detail-card.svelte-1bpgsx2 h3:where(.svelte-1bpgsx2){color:var(--body-text-color, #1f2937);margin:20px 0 8px;font-size:var(--text-lg, 16px)}.detail-grid.svelte-1bpgsx2{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.detail-item.svelte-1bpgsx2{display:flex;flex-direction:column;gap:2px}.detail-label.svelte-1bpgsx2{font-size:var(--text-xs, 10px);font-weight:600;color:var(--body-text-color-subdued, #9ca3af);text-transform:uppercase}.detail-value.svelte-1bpgsx2{font-size:var(--text-md, 14px);color:var(--body-text-color, #1f2937)}.config-block.svelte-1bpgsx2{background:var(--background-fill-secondary, #f9fafb);padding:12px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:var(--text-sm, 12px);color:var(--body-text-color, #1f2937);overflow-x:auto}.artifact-links.svelte-1bpgsx2{display:flex;flex-direction:column;gap:4px}.artifact-entry.svelte-1bpgsx2{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);overflow:hidden}.artifact-row.svelte-1bpgsx2{display:flex;align-items:center}.row-toggle.svelte-1bpgsx2{display:flex;align-items:center;gap:12px;flex:1;min-width:0;text-align:left;background:none;border:none;padding:8px 12px;cursor:pointer}.row-toggle.svelte-1bpgsx2:hover{background:var(--background-fill-secondary, #f9fafb)}.open-btn.svelte-1bpgsx2{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:30px;height:30px;margin-right:6px;border:none;background:none;color:var(--body-text-color-subdued, #9ca3af);border-radius:var(--radius-sm, 4px);cursor:pointer;transition:color .15s,background-color .15s}.open-btn.svelte-1bpgsx2:hover{color:var(--color-accent, #f97316);background:var(--background-fill-secondary, #f9fafb)}.chevron.svelte-1bpgsx2{flex-shrink:0;display:inline-block;color:var(--body-text-color, #1f2937);font-size:14px;transition:transform .15s;transform:rotate(-90deg)}.chevron.open.svelte-1bpgsx2{transform:none}.art-name.svelte-1bpgsx2{font-weight:600;color:var(--body-text-color, #1f2937);font-size:var(--text-md, 14px)}.art-ver.svelte-1bpgsx2{font-weight:400;color:var(--body-text-color-subdued, #6b7280);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.art-type.svelte-1bpgsx2{font-size:var(--text-xs, 11px);text-transform:uppercase;letter-spacing:.04em;color:var(--body-text-color-subdued, #6b7280);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:9px;padding:1px 8px}.art-size.svelte-1bpgsx2{margin-left:auto;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1bpgsx2{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1bpgsx2 h2:where(.svelte-1bpgsx2){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1bpgsx2 p:where(.svelte-1bpgsx2){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1bpgsx2 pre:where(.svelte-1bpgsx2){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-1bpgsx2 code:where(.svelte-1bpgsx2){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-1bpgsx2 pre:where(.svelte-1bpgsx2) code:where(.svelte-1bpgsx2){background:none;padding:0}.files-page.svelte-1xvfk9n{padding:20px 24px;overflow-y:auto;flex:1}.page-title.svelte-1xvfk9n{color:var(--body-text-color, #1f2937);font-size:16px;font-weight:700;margin:0 0 4px}.page-subtitle.svelte-1xvfk9n{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px);margin:0 0 16px}.file-list.svelte-1xvfk9n{display:flex;flex-direction:column;gap:4px}.file-item.svelte-1xvfk9n{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);background:var(--background-fill-primary, white);overflow:hidden}.file-item.expanded.svelte-1xvfk9n{border-color:var(--color-accent, #f97316)}.file-row.svelte-1xvfk9n{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;gap:12px}.file-name.svelte-1xvfk9n{display:flex;align-items:center;gap:8px;background:none;border:none;padding:0;font-size:var(--text-md, 14px);color:var(--body-text-color, #1f2937);cursor:pointer;text-align:left}.file-name.svelte-1xvfk9n:hover{color:var(--color-accent, #f97316)}.file-icon.svelte-1xvfk9n{font-size:14px;flex-shrink:0}.file-actions.svelte-1xvfk9n{display:flex;align-items:center;gap:12px;flex-shrink:0}.file-size.svelte-1xvfk9n{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);white-space:nowrap}.download-btn.svelte-1xvfk9n{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:var(--radius-md, 6px);color:var(--body-text-color-subdued, #6b7280);transition:background-color .15s,color .15s}.download-btn.svelte-1xvfk9n:hover{background:var(--background-fill-secondary, #f3f4f6);color:var(--body-text-color, #1f2937)}.file-preview.svelte-1xvfk9n{border-top:1px solid var(--border-color-primary, #e5e7eb);padding:12px 14px;background:var(--background-fill-secondary, #f9fafb)}.preview-code.svelte-1xvfk9n{margin:0;font-size:12px;line-height:1.5;max-height:400px;overflow:auto;white-space:pre-wrap;word-break:break-all;color:var(--body-text-color, #1f2937)}.preview-loading.svelte-1xvfk9n,.preview-unavailable.svelte-1xvfk9n{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px);padding:8px 0}.preview-unavailable.svelte-1xvfk9n a:where(.svelte-1xvfk9n){color:var(--color-accent, #f97316);text-decoration:none}.preview-unavailable.svelte-1xvfk9n a:where(.svelte-1xvfk9n):hover{text-decoration:underline}.empty-state.svelte-1xvfk9n{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1xvfk9n h2:where(.svelte-1xvfk9n){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1xvfk9n p:where(.svelte-1xvfk9n){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1xvfk9n pre:where(.svelte-1xvfk9n){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-1xvfk9n code:where(.svelte-1xvfk9n){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-1xvfk9n pre:where(.svelte-1xvfk9n) code:where(.svelte-1xvfk9n){background:none;padding:0}.artifacts-sidebar.svelte-coehlr{width:300px;flex-shrink:0;display:flex;flex-direction:column;border-right:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, #fff);overflow:hidden}.tree-header.svelte-coehlr{padding:16px 16px 10px;flex-shrink:0}.tree-search.svelte-coehlr{margin-top:14px}.search-label.svelte-coehlr{display:block;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);margin-bottom:6px}.search-box.svelte-coehlr{position:relative;display:flex;align-items:center}.search-icon.svelte-coehlr{position:absolute;left:10px;color:var(--body-text-color-subdued, #9ca3af);pointer-events:none}.search-box.svelte-coehlr input:where(.svelte-coehlr){width:100%;padding:6px 26px 6px 30px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);background:var(--background-fill-secondary, #f9fafb);color:var(--body-text-color, #1f2937);font-size:var(--text-sm, 13px);outline:none}.search-box.svelte-coehlr input:where(.svelte-coehlr):focus{border-color:var(--color-accent, #f97316)}.clear-search.svelte-coehlr{position:absolute;right:8px;border:none;background:none;color:var(--body-text-color-subdued, #9ca3af);font-size:18px;line-height:1;cursor:pointer;padding:0 2px}.clear-search.svelte-coehlr:hover{color:var(--body-text-color, #1f2937)}.tree.svelte-coehlr{flex:1;overflow-y:auto;padding:6px 0 12px}.tree-empty.svelte-coehlr{padding:16px 14px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.tree-row.svelte-coehlr{display:flex;align-items:center;width:100%;min-height:30px;background:none;border:none;cursor:pointer;text-align:left;color:var(--body-text-color, #1f2937);font-size:var(--text-sm, 13px);padding:0 12px;border-radius:0}.tree-row.svelte-coehlr:hover{background:var(--background-fill-secondary, #f3f4f6)}.tree-chevron-spacer.svelte-coehlr{display:inline-block;width:12px;margin-right:6px;flex-shrink:0}.chevron.svelte-coehlr{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;margin-right:6px;color:var(--body-text-color-subdued, #6b7280);width:12px;height:12px;transition:transform .15s}.chevron.open.svelte-coehlr{transform:rotate(90deg)}.type-label.svelte-coehlr{text-transform:uppercase;letter-spacing:.04em;font-size:var(--text-xs, 11px);font-weight:700;color:var(--body-text-color-subdued, #6b7280)}.artifact-label.svelte-coehlr{font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.version-label.svelte-coehlr{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:600;flex-shrink:0}.version-row.svelte-coehlr .alias-pill:where(.svelte-coehlr){margin-left:6px}.spacer.svelte-coehlr{flex:1 1 auto}.node-count.svelte-coehlr{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--background-fill-secondary, #f3f4f6);color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-xs, 10px);flex-shrink:0}.version-row.selected.svelte-coehlr{background:var(--background-fill-secondary, #f3f4f6);box-shadow:inset 3px 0 0 var(--color-accent, #f97316)}.version-row.selected.svelte-coehlr .version-label:where(.svelte-coehlr){color:var(--color-accent, #f97316)}.alias-pill.svelte-coehlr{font-size:var(--text-xs, 10px);padding:0 6px;border-radius:9px;border:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);background:var(--background-fill-secondary, #f3f4f6);white-space:nowrap;line-height:16px}.alias-pill.latest.svelte-coehlr{color:var(--color-accent, #f97316);border-color:var(--color-accent, #f97316);background:transparent}.detail-pane.svelte-q8gppg{flex:1;min-width:0;overflow-y:auto;padding:20px 28px}.detail-empty.svelte-q8gppg{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 13px);padding:12px 0}.empty-state.svelte-q8gppg{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-q8gppg h2:where(.svelte-q8gppg){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-q8gppg p:where(.svelte-q8gppg){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-q8gppg pre:where(.svelte-q8gppg){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-q8gppg code:where(.svelte-q8gppg){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-q8gppg pre:where(.svelte-q8gppg) code:where(.svelte-q8gppg){background:none;padding:0}.settings-page.svelte-1ozf5k3{padding:24px 32px;overflow-y:auto;flex:1}.page-title.svelte-1ozf5k3{color:var(--body-text-color, #1f2937);font-size:18px;font-weight:700;margin:0 0 24px}.two-col.svelte-1ozf5k3{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:32px;align-items:start}@media(max-width:900px){.two-col.svelte-1ozf5k3{grid-template-columns:1fr}}.settings-section.svelte-1ozf5k3{margin-bottom:32px}.section-title.svelte-1ozf5k3{color:var(--body-text-color, #1f2937);font-size:15px;font-weight:600;margin:0 0 4px}.section-desc.svelte-1ozf5k3{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px);margin:0 0 12px;line-height:1.5}.section-desc.svelte-1ozf5k3 code:where(.svelte-1ozf5k3){background:var(--background-fill-secondary, #f3f4f6);padding:1px 5px;border-radius:var(--radius-sm, 3px);font-size:11px}.section-desc.svelte-1ozf5k3 strong:where(.svelte-1ozf5k3){color:var(--color-accent, #f97316)}.theme-switcher.svelte-1ozf5k3{display:inline-flex;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);overflow:hidden}.theme-option.svelte-1ozf5k3{display:inline-flex;align-items:center;gap:6px;padding:8px 20px;border:none;background:var(--background-fill-primary, white);color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-md, 14px);cursor:pointer;transition:all .15s;border-right:1px solid var(--border-color-primary, #e5e7eb)}.theme-option.svelte-1ozf5k3:last-child{border-right:none}.theme-option.svelte-1ozf5k3:hover{color:var(--body-text-color, #1f2937);background:var(--background-fill-secondary, #f9fafb)}.theme-option.selected.svelte-1ozf5k3{background:var(--color-accent, #f97316);color:#fff;font-weight:500}.project-selector.svelte-1ozf5k3{display:flex;align-items:center;gap:10px;margin-bottom:12px}.selector-label.svelte-1ozf5k3{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);flex-shrink:0}.selector-select.svelte-1ozf5k3{padding:6px 10px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 4px);background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:var(--text-sm, 12px);min-width:160px;cursor:pointer}.selector-select.svelte-1ozf5k3:focus{outline:none;border-color:var(--color-accent, #f97316)}.commands-table.svelte-1ozf5k3{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);overflow:hidden}.command-row.svelte-1ozf5k3{display:flex;align-items:center;gap:16px;padding:10px 14px;border-bottom:1px solid var(--border-color-primary, #e5e7eb)}.command-row.svelte-1ozf5k3:last-child{border-bottom:none}.command-label.svelte-1ozf5k3{width:180px;flex-shrink:0;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.command-value.svelte-1ozf5k3{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.command-value.svelte-1ozf5k3 code:where(.svelte-1ozf5k3){flex:1;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;color:var(--body-text-color, #1f2937);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.copy-btn.svelte-1ozf5k3{display:flex;align-items:center;justify-content:center;width:26px;height:26px;flex-shrink:0;border:none;background:none;border-radius:var(--radius-md, 4px);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;transition:background-color .15s,color .15s}.copy-btn.svelte-1ozf5k3:hover{background:var(--background-fill-secondary, #f3f4f6);color:var(--body-text-color, #1f2937)}.copy-btn.copied.svelte-1ozf5k3{color:var(--color-accent, #f97316)}.agent-tabs.svelte-1ozf5k3{display:flex;border-bottom:1px solid var(--border-color-primary, #e5e7eb);gap:0;margin-bottom:0}.agent-tab.svelte-1ozf5k3{padding:8px 16px;border:none;background:none;color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px);cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;white-space:nowrap}.agent-tab.svelte-1ozf5k3:hover{color:var(--body-text-color, #1f2937)}.agent-tab.active.svelte-1ozf5k3{color:var(--color-accent, #f97316);border-bottom-color:var(--color-accent, #f97316);font-weight:500}.agent-panel.svelte-1ozf5k3{border:1px solid var(--border-color-primary, #e5e7eb);border-top:none;border-radius:0 0 var(--radius-lg, 8px) var(--radius-lg, 8px);padding:16px}.install-block.svelte-1ozf5k3{margin-bottom:16px}.install-label.svelte-1ozf5k3{display:block;font-size:11px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);text-transform:uppercase;letter-spacing:.04em;margin-bottom:6px}.install-cmd.svelte-1ozf5k3{display:flex;align-items:center;gap:8px;background:var(--background-fill-secondary, #f3f4f6);border-radius:var(--radius-md, 4px);padding:8px 10px}.install-cmd.svelte-1ozf5k3 code:where(.svelte-1ozf5k3){flex:1;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;color:var(--body-text-color, #1f2937);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.example-block.svelte-1ozf5k3{background:var(--background-fill-secondary, #f9fafb);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 4px);padding:12px}.example-header.svelte-1ozf5k3{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.example-label.svelte-1ozf5k3{font-size:11px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);text-transform:uppercase;letter-spacing:.04em}.example-text.svelte-1ozf5k3{margin:0;font-size:var(--text-sm, 12px);color:var(--body-text-color, #1f2937);line-height:1.6;font-style:italic}*{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;background:var(--background-fill-primary, #fff);color:var(--body-text-color, #1f2937);font-size:var(--text-md, 14px);-webkit-font-smoothing:antialiased}.app.svelte-1n46o8q{display:flex;height:100vh;overflow:hidden}.main.svelte-1n46o8q{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}.page-content.svelte-1n46o8q{flex:1;overflow:hidden;display:flex;background:var(--bg-primary)} diff --git a/trackio/frontend/dist/assets/index-nILgi7uv.js b/trackio/frontend/dist/assets/index-nILgi7uv.js new file mode 100644 index 0000000000000000000000000000000000000000..21abb678b53c10f47c949c1ad07b4fc36d8e1f16 --- /dev/null +++ b/trackio/frontend/dist/assets/index-nILgi7uv.js @@ -0,0 +1,256 @@ +var jW=Object.defineProperty;var sF=e=>{throw TypeError(e)};var UW=(e,t,n)=>t in e?jW(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Ws=(e,t,n)=>UW(e,typeof t!="symbol"?t+"":t,n),a_=(e,t,n)=>t.has(e)||sF("Cannot "+n);var pe=(e,t,n)=>(a_(e,t,"read from private field"),n?n.call(e):t.get(e)),Wt=(e,t,n)=>t.has(e)?sF("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),Pt=(e,t,n,r)=>(a_(e,t,"write to private field"),r?r.call(e,n):t.set(e,n),n),Jn=(e,t,n)=>(a_(e,t,"access private method"),n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const a of s.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&r(a)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();const qW="5";var BT;typeof window<"u"&&((BT=window.__svelte??(window.__svelte={})).v??(BT.v=new Set)).add(qW);const WW=1,HW=2,qT=4,GW=8,YW=16,VW=1,XW=2,KW=4,ZW=8,JW=16,QW=1,eH=2,Sr=Symbol(),WT="http://www.w3.org/1999/xhtml",tH="http://www.w3.org/2000/svg",nH="http://www.w3.org/1998/Math/MathML",rH=!1;var ok=Array.isArray,iH=Array.prototype.indexOf,Sd=Array.prototype.includes,Oy=Array.from,sH=Object.defineProperty,id=Object.getOwnPropertyDescriptor,HT=Object.getOwnPropertyDescriptors,aH=Object.prototype,oH=Array.prototype,lk=Object.getPrototypeOf,aF=Object.isExtensible;const bc=()=>{};function lH(e){return e()}function dw(e){for(var t=0;t{e=r,t=i});return{promise:n,resolve:e,reject:t}}function pg(e,t){if(Array.isArray(e))return e;if(!(Symbol.iterator in e))return Array.from(e);const n=[];for(const r of e)if(n.push(r),n.length===t)break;return n}const wr=2,Cd=4,t0=8,YT=1<<24,bu=16,ca=32,Nc=64,hw=128,Cs=512,pr=1024,Ir=2048,fa=4096,is=8192,$s=16384,ff=32768,pw=1<<25,Oc=65536,oF=1<<17,uH=1<<18,hh=1<<19,VT=1<<20,Ya=1<<25,Lc=65536,gw=1<<21,uk=1<<22,Gl=1<<23,Xo=Symbol("$state"),cH=Symbol("legacy props"),fH=Symbol(""),Oo=new class extends Error{constructor(){super(...arguments);Ws(this,"name","StaleReactionError");Ws(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};var zT;const dH=!!((zT=globalThis.document)!=null&&zT.contentType)&&globalThis.document.contentType.includes("xml");function hH(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function pH(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function gH(e,t,n){throw new Error("https://svelte.dev/e/each_key_duplicate")}function mH(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function vH(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function yH(e){throw new Error("https://svelte.dev/e/effect_orphan")}function bH(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function _H(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function xH(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function wH(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function EH(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function AH(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}function kH(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function SH(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function XT(e){return e===this.v}function KT(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function ZT(e){return!KT(e,this.v)}let ph=!1,CH=!1;function $H(){ph=!0}let Bn=null;function $d(e){Bn=e}function ln(e,t=!1,n){Bn={p:Bn,i:!1,c:null,e:null,s:e,x:null,r:Ht,l:ph&&!t?{s:null,u:null,$:[]}:null}}function un(e){var t=Bn,n=t.e;if(n!==null){t.e=null;for(var r of n)yR(r)}return t.i=!0,Bn=t.p,{}}function gh(){return!ph||Bn!==null&&Bn.l===null}let uc=[];function JT(){var e=uc;uc=[],dw(e)}function Yl(e){if(uc.length===0&&!Xp){var t=uc;queueMicrotask(()=>{t===uc&&JT()})}uc.push(e)}function FH(){for(;uc.length>0;)JT()}function QT(e){var t=Ht;if(t===null)return zt.f|=Gl,e;if((t.f&ff)===0&&(t.f&Cd)===0)throw e;Ll(e,t)}function Ll(e,t){for(;t!==null;){if((t.f&hw)!==0){if((t.f&ff)===0)throw e;try{t.b.error(e);return}catch(n){e=n}}t=t.parent}throw e}const DH=-7169;function Yn(e,t){e.f=e.f&DH|t}function ck(e){(e.f&Cs)!==0||e.deps===null?Yn(e,pr):Yn(e,fa)}function eR(e){if(e!==null)for(const t of e)(t.f&wr)===0||(t.f&Lc)===0||(t.f^=Lc,eR(t.deps))}function tR(e,t,n){(e.f&Ir)!==0?t.add(e):(e.f&fa)!==0&&n.add(e),eR(e.deps),Yn(e,pr)}let om=!1;function MH(e){var t=om;try{return om=!1,[e(),om]}finally{om=t}}const Vh=new Set;let Ft=null,$r=null,mw=null,Xp=!1,o_=!1,Kf=null,o1=null;var lF=0;let TH=1;var vd,yd,bd,_d,Jg,ys,xd,Nl,Ba,wd,ni,vw,yw,bw,_w,nR;const Ty=class Ty{constructor(){Wt(this,ni);Ws(this,"id",TH++);Ws(this,"current",new Map);Ws(this,"previous",new Map);Wt(this,vd,new Set);Wt(this,yd,new Set);Wt(this,bd,0);Wt(this,_d,0);Wt(this,Jg,null);Wt(this,ys,[]);Wt(this,xd,new Set);Wt(this,Nl,new Set);Wt(this,Ba,new Map);Ws(this,"is_fork",!1);Wt(this,wd,!1)}skip_effect(t){pe(this,Ba).has(t)||pe(this,Ba).set(t,{d:[],m:[]})}unskip_effect(t){var n=pe(this,Ba).get(t);if(n){pe(this,Ba).delete(t);for(var r of n.d)Yn(r,Ir),this.schedule(r);for(r of n.m)Yn(r,fa),this.schedule(r)}}capture(t,n){n!==Sr&&!this.previous.has(t)&&this.previous.set(t,n),(t.f&Gl)===0&&(this.current.set(t,t.v),$r==null||$r.set(t,t.v))}activate(){Ft=this}deactivate(){Ft=null,$r=null}flush(){try{if(o_=!0,Ft=this,!Jn(this,ni,vw).call(this)){for(const t of pe(this,xd))pe(this,Nl).delete(t),Yn(t,Ir),this.schedule(t);for(const t of pe(this,Nl))Yn(t,fa),this.schedule(t)}Jn(this,ni,yw).call(this)}finally{lF=0,mw=null,Kf=null,o1=null,o_=!1,Ft=null,$r=null,Vl.clear()}}discard(){for(const t of pe(this,yd))t(this);pe(this,yd).clear()}increment(t){Pt(this,bd,pe(this,bd)+1),t&&Pt(this,_d,pe(this,_d)+1)}decrement(t,n){Pt(this,bd,pe(this,bd)-1),t&&Pt(this,_d,pe(this,_d)-1),!(pe(this,wd)||n)&&(Pt(this,wd,!0),Yl(()=>{Pt(this,wd,!1),this.flush()}))}oncommit(t){pe(this,vd).add(t)}ondiscard(t){pe(this,yd).add(t)}settled(){return(pe(this,Jg)??Pt(this,Jg,GT())).promise}static ensure(){if(Ft===null){const t=Ft=new Ty;o_||(Vh.add(Ft),Xp||Yl(()=>{Ft===t&&t.flush()}))}return Ft}apply(){}schedule(t){var i;if(mw=t,(i=t.b)!=null&&i.is_pending&&(t.f&(Cd|t0|YT))!==0&&(t.f&ff)===0){t.b.defer_effect(t);return}for(var n=t;n.parent!==null;){n=n.parent;var r=n.f;if(Kf!==null&&n===Ht&&(zt===null||(zt.f&wr)===0))return;if((r&(Nc|ca))!==0){if((r&pr)===0)return;n.f^=pr}}pe(this,ys).push(n)}};vd=new WeakMap,yd=new WeakMap,bd=new WeakMap,_d=new WeakMap,Jg=new WeakMap,ys=new WeakMap,xd=new WeakMap,Nl=new WeakMap,Ba=new WeakMap,wd=new WeakMap,ni=new WeakSet,vw=function(){return this.is_fork||pe(this,_d)>0},yw=function(){var o,l;lF++>1e3&&NH();const t=pe(this,ys);Pt(this,ys,[]),this.apply();var n=Kf=[],r=[],i=o1=[];for(const u of t)Jn(this,ni,bw).call(this,u,n,r);if(Ft=null,i.length>0){var s=Ty.ensure();for(const u of i)s.schedule(u)}if(Kf=null,o1=null,Jn(this,ni,vw).call(this)){Jn(this,ni,_w).call(this,r),Jn(this,ni,_w).call(this,n);for(const[u,c]of pe(this,Ba))sR(u,c)}else{pe(this,xd).clear(),pe(this,Nl).clear();for(const u of pe(this,vd))u(this);pe(this,vd).clear(),uF(r),uF(n),pe(this,bd)===0&&Jn(this,ni,nR).call(this),(o=pe(this,Jg))==null||o.resolve()}var a=Ft;if(pe(this,ys).length>0){const u=a??(a=this);pe(u,ys).push(...pe(this,ys).filter(c=>!pe(u,ys).includes(c)))}a!==null&&(Vh.add(a),Jn(l=a,ni,yw).call(l))},bw=function(t,n,r){t.f^=pr;for(var i=t.first;i!==null;){var s=i.f,a=(s&(ca|Nc))!==0,o=a&&(s&pr)!==0,l=o||(s&is)!==0||pe(this,Ba).has(i);if(!l&&i.fn!==null){a?i.f^=pr:(s&Cd)!==0?n.push(i):a0(i)&&((s&bu)!==0&&pe(this,Nl).add(i),Md(i));var u=i.first;if(u!==null){i=u;continue}}for(;i!==null;){var c=i.next;if(c!==null){i=c;break}i=i.parent}}},_w=function(t){for(var n=0;n1){this.previous.clear();var t=Ft,n=$r,r=!0;for(const s of Vh){if(s===this){r=!1;continue}const a=[];for(const[l,u]of this.current){if(s.current.has(l))if(r&&u!==s.current.get(l))s.current.set(l,u);else continue;a.push(l)}if(a.length===0)continue;const o=[...s.current.keys()].filter(l=>!this.current.has(l));if(o.length>0){s.activate();const l=new Set,u=new Map;for(const c of a)rR(c,o,l,u);if(pe(s,ys).length>0){s.apply();for(const c of pe(s,ys))Jn(i=s,ni,bw).call(i,c,[],[])}s.deactivate()}}Ft=t,$r=n}pe(this,Ba).clear(),Vh.delete(this)};let Ic=Ty;function RH(e){var t=Xp;Xp=!0;try{for(var n;;){if(FH(),Ft===null)return n;Ft.flush()}}finally{Xp=t}}function NH(){try{bH()}catch(e){Ll(e,mw)}}let Vs=null;function uF(e){var t=e.length;if(t!==0){for(var n=0;n0)){Vl.clear();for(const i of Vs){if((i.f&($s|is))!==0)continue;const s=[i];let a=i.parent;for(;a!==null;)Vs.has(a)&&(Vs.delete(a),s.push(a)),a=a.parent;for(let o=s.length-1;o>=0;o--){const l=s[o];(l.f&($s|is))===0&&Md(l)}}Vs.clear()}}Vs=null}}function rR(e,t,n,r){if(!n.has(e)&&(n.add(e),e.reactions!==null))for(const i of e.reactions){const s=i.f;(s&wr)!==0?rR(i,t,n,r):(s&(uk|bu))!==0&&(s&Ir)===0&&iR(i,t,r)&&(Yn(i,Ir),fk(i))}}function iR(e,t,n){const r=n.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const i of e.deps){if(Sd.call(t,i))return!0;if((i.f&wr)!==0&&iR(i,t,n))return n.set(i,!0),!0}return n.set(e,!1),!1}function fk(e){Ft.schedule(e)}function sR(e,t){if(!((e.f&ca)!==0&&(e.f&pr)!==0)){(e.f&Ir)!==0?t.d.push(e):(e.f&fa)!==0&&t.m.push(e),Yn(e,pr);for(var n=e.first;n!==null;)sR(n,t),n=n.next}}function OH(e){let t=0,n=Pc(0),r;return()=>{gk()&&(m(n),i0(()=>(t===0&&(r=_u(()=>e(()=>Kp(n)))),t+=1,()=>{Yl(()=>{t-=1,t===0&&(r==null||r(),r=void 0,Kp(n))})})))}}var LH=Oc|hh;function IH(e,t,n,r){new PH(e,t,n,r)}var bs,ak,za,mc,Si,ja,Xi,Xs,Bo,vc,Ol,Ed,Ad,kd,zo,Ry,ar,BH,zH,jH,xw,l1,u1,ww;class PH{constructor(t,n,r,i){Wt(this,ar);Ws(this,"parent");Ws(this,"is_pending",!1);Ws(this,"transform_error");Wt(this,bs);Wt(this,ak,null);Wt(this,za);Wt(this,mc);Wt(this,Si);Wt(this,ja,null);Wt(this,Xi,null);Wt(this,Xs,null);Wt(this,Bo,null);Wt(this,vc,0);Wt(this,Ol,0);Wt(this,Ed,!1);Wt(this,Ad,new Set);Wt(this,kd,new Set);Wt(this,zo,null);Wt(this,Ry,OH(()=>(Pt(this,zo,Pc(pe(this,vc))),()=>{Pt(this,zo,null)})));var s;Pt(this,bs,t),Pt(this,za,n),Pt(this,mc,a=>{var o=Ht;o.b=this,o.f|=hw,r(a)}),this.parent=Ht.b,this.transform_error=i??((s=this.parent)==null?void 0:s.transform_error)??(a=>a),Pt(this,Si,s0(()=>{Jn(this,ar,xw).call(this)},LH))}defer_effect(t){tR(t,pe(this,Ad),pe(this,kd))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!pe(this,za).pending}update_pending_count(t,n){Jn(this,ar,ww).call(this,t,n),Pt(this,vc,pe(this,vc)+t),!(!pe(this,zo)||pe(this,Ed))&&(Pt(this,Ed,!0),Yl(()=>{Pt(this,Ed,!1),pe(this,zo)&&Fd(pe(this,zo),pe(this,vc))}))}get_effect_pending(){return pe(this,Ry).call(this),m(pe(this,zo))}error(t){var n=pe(this,za).onerror;let r=pe(this,za).failed;if(!n&&!r)throw t;pe(this,ja)&&(Oi(pe(this,ja)),Pt(this,ja,null)),pe(this,Xi)&&(Oi(pe(this,Xi)),Pt(this,Xi,null)),pe(this,Xs)&&(Oi(pe(this,Xs)),Pt(this,Xs,null));var i=!1,s=!1;const a=()=>{if(i){SH();return}i=!0,s&&AH(),pe(this,Xs)!==null&&_c(pe(this,Xs),()=>{Pt(this,Xs,null)}),Jn(this,ar,u1).call(this,()=>{Jn(this,ar,xw).call(this)})},o=l=>{try{s=!0,n==null||n(l,a),s=!1}catch(u){Ll(u,pe(this,Si)&&pe(this,Si).parent)}r&&Pt(this,Xs,Jn(this,ar,u1).call(this,()=>{try{return _s(()=>{var u=Ht;u.b=this,u.f|=hw,r(pe(this,bs),()=>l,()=>a)})}catch(u){return Ll(u,pe(this,Si).parent),null}}))};Yl(()=>{var l;try{l=this.transform_error(t)}catch(u){Ll(u,pe(this,Si)&&pe(this,Si).parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(o,u=>Ll(u,pe(this,Si)&&pe(this,Si).parent)):o(l)})}}bs=new WeakMap,ak=new WeakMap,za=new WeakMap,mc=new WeakMap,Si=new WeakMap,ja=new WeakMap,Xi=new WeakMap,Xs=new WeakMap,Bo=new WeakMap,vc=new WeakMap,Ol=new WeakMap,Ed=new WeakMap,Ad=new WeakMap,kd=new WeakMap,zo=new WeakMap,Ry=new WeakMap,ar=new WeakSet,BH=function(){try{Pt(this,ja,_s(()=>pe(this,mc).call(this,pe(this,bs))))}catch(t){this.error(t)}},zH=function(t){const n=pe(this,za).failed;n&&Pt(this,Xs,_s(()=>{n(pe(this,bs),()=>t,()=>()=>{})}))},jH=function(){const t=pe(this,za).pending;if(t){this.is_pending=!0,Pt(this,Xi,_s(()=>t(pe(this,bs))));var n=Ft;Yl(()=>{var r=Pt(this,Bo,document.createDocumentFragment()),i=Ko();r.append(i),Pt(this,ja,Jn(this,ar,u1).call(this,()=>_s(()=>pe(this,mc).call(this,i)))),pe(this,Ol)===0&&(pe(this,bs).before(r),Pt(this,Bo,null),_c(pe(this,Xi),()=>{Pt(this,Xi,null)}),Jn(this,ar,l1).call(this,n))})}},xw=function(){var t=Ft;try{if(this.is_pending=this.has_pending_snippet(),Pt(this,Ol,0),Pt(this,vc,0),Pt(this,ja,_s(()=>{pe(this,mc).call(this,pe(this,bs))})),pe(this,Ol)>0){var n=Pt(this,Bo,document.createDocumentFragment());_k(pe(this,ja),n);const r=pe(this,za).pending;Pt(this,Xi,_s(()=>r(pe(this,bs))))}else Jn(this,ar,l1).call(this,t)}catch(r){this.error(r)}},l1=function(t){this.is_pending=!1;for(const n of pe(this,Ad))Yn(n,Ir),t.schedule(n);for(const n of pe(this,kd))Yn(n,fa),t.schedule(n);pe(this,Ad).clear(),pe(this,kd).clear()},u1=function(t){var n=Ht,r=zt,i=Bn;ro(pe(this,Si)),Rs(pe(this,Si)),$d(pe(this,Si).ctx);try{return Ic.ensure(),t()}catch(s){return QT(s),null}finally{ro(n),Rs(r),$d(i)}},ww=function(t,n){var r;if(!this.has_pending_snippet()){this.parent&&Jn(r=this.parent,ar,ww).call(r,t,n);return}Pt(this,Ol,pe(this,Ol)+t),pe(this,Ol)===0&&(Jn(this,ar,l1).call(this,n),pe(this,Xi)&&_c(pe(this,Xi),()=>{Pt(this,Xi,null)}),pe(this,Bo)&&(pe(this,bs).before(pe(this,Bo)),Pt(this,Bo,null)))};function UH(e,t,n,r){const i=gh()?n0:dk;var s=e.filter(d=>!d.settled);if(n.length===0&&s.length===0){r(t.map(i));return}var a=Ht,o=qH(),l=s.length===1?s[0].promise:s.length>1?Promise.all(s.map(d=>d.promise)):null;function u(d){o();try{r(d)}catch(h){(a.f&$s)===0&&Ll(h,a)}U1()}if(n.length===0){l.then(()=>u(t.map(i)));return}var c=aR();function f(){Promise.all(n.map(d=>WH(d))).then(d=>u([...t.map(i),...d])).catch(d=>Ll(d,a)).finally(()=>c())}l?l.then(()=>{o(),f(),U1()}):f()}function qH(){var e=Ht,t=zt,n=Bn,r=Ft;return function(s=!0){ro(e),Rs(t),$d(n),s&&(e.f&$s)===0&&(r==null||r.activate(),r==null||r.apply())}}function U1(e=!0){ro(null),Rs(null),$d(null),e&&(Ft==null||Ft.deactivate())}function aR(){var e=Ht.b,t=Ft,n=e.is_rendered();return e.update_pending_count(1,t),t.increment(n),(r=!1)=>{e.update_pending_count(-1,t),t.decrement(n,r)}}function n0(e){var t=wr|Ir,n=zt!==null&&(zt.f&wr)!==0?zt:null;return Ht!==null&&(Ht.f|=hh),{ctx:Bn,deps:null,effects:null,equals:XT,f:t,fn:e,reactions:null,rv:0,v:Sr,wv:0,parent:n??Ht,ac:null}}function WH(e,t,n){let r=Ht;r===null&&pH();var i=void 0,s=Pc(Sr),a=!zt,o=new Map;return rG(()=>{var h;var l=Ht,u=GT();i=u.promise;try{Promise.resolve(e()).then(u.resolve,u.reject).finally(U1)}catch(p){u.reject(p),U1()}var c=Ft;if(a){if((l.f&ff)!==0)var f=aR();if(r.b.is_rendered())(h=o.get(c))==null||h.reject(Oo),o.delete(c);else{for(const p of o.values())p.reject(Oo);o.clear()}o.set(c,u)}const d=(p,g=void 0)=>{if(f){var v=g===Oo;f(v)}if(!(g===Oo||(l.f&$s)!==0)){if(c.activate(),g)s.f|=Gl,Fd(s,g);else{(s.f&Gl)!==0&&(s.f^=Gl),Fd(s,p);for(const[y,b]of o){if(o.delete(y),y===c)break;b.reject(Oo)}}c.deactivate()}};u.promise.then(d,p=>d(null,p||"unknown"))}),mk(()=>{for(const l of o.values())l.reject(Oo)}),new Promise(l=>{function u(c){function f(){c===i?l(s):u(i)}c.then(f,f)}u(i)})}function ke(e){const t=n0(e);return AR(t),t}function dk(e){const t=n0(e);return t.equals=ZT,t}function HH(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n0&&!uR&&XH()}return t}function XH(){uR=!1;for(const e of Ew)(e.f&pr)!==0&&Yn(e,fa),a0(e)&&Md(e);Ew.clear()}function cR(e,t=1){var n=m(e),r=t===1?n++:n--;return F(e,n),r}function Kp(e){F(e,e.v+1)}function fR(e,t,n){var r=e.reactions;if(r!==null)for(var i=gh(),s=r.length,a=0;a{if(xc===s)return o();var l=zt,u=xc;Rs(null),hF(s);var c=o();return Rs(l),hF(u),c};return r&&n.set("length",ie(e.length)),new Proxy(e,{defineProperty(o,l,u){(!("value"in u)||u.configurable===!1||u.enumerable===!1||u.writable===!1)&&xH();var c=n.get(l);return c===void 0?a(()=>{var f=ie(u.value);return n.set(l,f),f}):F(c,u.value,!0),!0},deleteProperty(o,l){var u=n.get(l);if(u===void 0){if(l in o){const c=a(()=>ie(Sr));n.set(l,c),Kp(i)}}else F(u,Sr),Kp(i);return!0},get(o,l,u){var h;if(l===Xo)return e;var c=n.get(l),f=l in o;if(c===void 0&&(!f||(h=id(o,l))!=null&&h.writable)&&(c=a(()=>{var p=yt(f?o[l]:Sr),g=ie(p);return g}),n.set(l,c)),c!==void 0){var d=m(c);return d===Sr?void 0:d}return Reflect.get(o,l,u)},getOwnPropertyDescriptor(o,l){var u=Reflect.getOwnPropertyDescriptor(o,l);if(u&&"value"in u){var c=n.get(l);c&&(u.value=m(c))}else if(u===void 0){var f=n.get(l),d=f==null?void 0:f.v;if(f!==void 0&&d!==Sr)return{enumerable:!0,configurable:!0,value:d,writable:!0}}return u},has(o,l){var d;if(l===Xo)return!0;var u=n.get(l),c=u!==void 0&&u.v!==Sr||Reflect.has(o,l);if(u!==void 0||Ht!==null&&(!c||(d=id(o,l))!=null&&d.writable)){u===void 0&&(u=a(()=>{var h=c?yt(o[l]):Sr,p=ie(h);return p}),n.set(l,u));var f=m(u);if(f===Sr)return!1}return c},set(o,l,u,c){var _;var f=n.get(l),d=l in o;if(r&&l==="length")for(var h=u;hie(Sr)),n.set(h+"",p))}if(f===void 0)(!d||(_=id(o,l))!=null&&_.writable)&&(f=a(()=>ie(void 0)),F(f,yt(u)),n.set(l,f));else{d=f.v!==Sr;var g=a(()=>yt(u));F(f,g)}var v=Reflect.getOwnPropertyDescriptor(o,l);if(v!=null&&v.set&&v.set.call(c,u),!d){if(r&&typeof l=="string"){var y=n.get("length"),b=Number(l);Number.isInteger(b)&&b>=y.v&&F(y,b+1)}Kp(i)}return!0},ownKeys(o){m(i);var l=Reflect.ownKeys(o).filter(f=>{var d=n.get(f);return d===void 0||d.v!==Sr});for(var[u,c]of n)c.v!==Sr&&!(u in o)&&l.push(u);return l},setPrototypeOf(){wH()}})}function cF(e){try{if(e!==null&&typeof e=="object"&&Xo in e)return e[Xo]}catch{}return e}function KH(e,t){return Object.is(cF(e),cF(t))}var Dd,dR,hR,pR;function ZH(){if(Dd===void 0){Dd=window,dR=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;hR=id(t,"firstChild").get,pR=id(t,"nextSibling").get,aF(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),aF(n)&&(n.__t=void 0)}}function Ko(e=""){return document.createTextNode(e)}function Va(e){return hR.call(e)}function r0(e){return pR.call(e)}function S(e,t){return Va(e)}function ct(e,t=!1){{var n=Va(e);return n instanceof Comment&&n.data===""?r0(n):n}}function D(e,t=1,n=!1){let r=e;for(;t--;)r=r0(r);return r}function JH(e){e.textContent=""}function gR(){return!1}function mR(e,t,n){return document.createElementNS(t??WT,e,void 0)}let fF=!1;function QH(){fF||(fF=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var t;if(!e.defaultPrevented)for(const n of e.target.elements)(t=n.__on_r)==null||t.call(n)})},{capture:!0}))}function Ly(e){var t=zt,n=Ht;Rs(null),ro(null);try{return e()}finally{Rs(t),ro(n)}}function pk(e,t,n,r=n){e.addEventListener(t,()=>Ly(n));const i=e.__on_r;i?e.__on_r=()=>{i(),r(!0)}:e.__on_r=()=>r(!0),QH()}function vR(e){Ht===null&&(zt===null&&yH(),vH()),nu&&mH()}function eG(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function po(e,t){var n=Ht;n!==null&&(n.f&is)!==0&&(e|=is);var r={ctx:Bn,deps:null,nodes:null,f:e|Ir|Cs,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null},i=r;if((e&Cd)!==0)Kf!==null?Kf.push(r):Ic.ensure().schedule(r);else if(t!==null){try{Md(r)}catch(a){throw Oi(r),a}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&(i.f&hh)===0&&(i=i.first,(e&bu)!==0&&(e&Oc)!==0&&i!==null&&(i.f|=Oc))}if(i!==null&&(i.parent=n,n!==null&&eG(i,n),zt!==null&&(zt.f&wr)!==0&&(e&Nc)===0)){var s=zt;(s.effects??(s.effects=[])).push(i)}return r}function gk(){return zt!==null&&!ra}function mk(e){const t=po(t0,null);return Yn(t,pr),t.teardown=e,t}function Lt(e){vR();var t=Ht.f,n=!zt&&(t&ca)!==0&&(t&ff)===0;if(n){var r=Bn;(r.e??(r.e=[])).push(e)}else return yR(e)}function yR(e){return po(Cd|VT,e)}function tG(e){return vR(),po(t0|VT,e)}function nG(e){Ic.ensure();const t=po(Nc|hh,e);return(n={})=>new Promise(r=>{n.outro?_c(t,()=>{Oi(t),r(void 0)}):(Oi(t),r(void 0))})}function vk(e){return po(Cd,e)}function rG(e){return po(uk|hh,e)}function i0(e,t=0){return po(t0|t,e)}function me(e,t=[],n=[],r=[]){UH(r,t,n,i=>{po(t0,()=>e(...i.map(m)))})}function s0(e,t=0){var n=po(bu|t,e);return n}function _s(e){return po(ca|hh,e)}function bR(e){var t=e.teardown;if(t!==null){const n=nu,r=zt;dF(!0),Rs(null);try{t.call(null)}finally{dF(n),Rs(r)}}}function yk(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){const i=n.ac;i!==null&&Ly(()=>{i.abort(Oo)});var r=n.next;(n.f&Nc)!==0?n.parent=null:Oi(n,t),n=r}}function iG(e){for(var t=e.first;t!==null;){var n=t.next;(t.f&ca)===0&&Oi(t),t=n}}function Oi(e,t=!0){var n=!1;(t||(e.f&uH)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(_R(e.nodes.start,e.nodes.end),n=!0),Yn(e,pw),yk(e,t&&!n),gg(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(const s of r)s.stop();bR(e),e.f^=pw,e.f|=$s;var i=e.parent;i!==null&&i.first!==null&&xR(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function _R(e,t){for(;e!==null;){var n=e===t?null:r0(e);e.remove(),e=n}}function xR(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function _c(e,t,n=!0){var r=[];wR(e,r,!0);var i=()=>{n&&Oi(e),t&&t()},s=r.length;if(s>0){var a=()=>--s||i();for(var o of r)o.out(a)}else i()}function wR(e,t,n){if((e.f&is)===0){e.f^=is;var r=e.nodes&&e.nodes.t;if(r!==null)for(const o of r)(o.is_global||n)&&t.push(o);for(var i=e.first;i!==null;){var s=i.next,a=(i.f&Oc)!==0||(i.f&ca)!==0&&(e.f&bu)!==0;wR(i,t,a?n:!1),i=s}}}function bk(e){ER(e,!0)}function ER(e,t){if((e.f&is)!==0){e.f^=is,(e.f&pr)===0&&(Yn(e,Ir),Ic.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=(n.f&Oc)!==0||(n.f&ca)!==0;ER(n,i?t:!1),n=r}var s=e.nodes&&e.nodes.t;if(s!==null)for(const a of s)(a.is_global||t)&&a.in()}}function _k(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:r0(n);t.append(n),n=i}}let c1=!1,nu=!1;function dF(e){nu=e}let zt=null,ra=!1;function Rs(e){zt=e}let Ht=null;function ro(e){Ht=e}let Fs=null;function AR(e){zt!==null&&(Fs===null?Fs=[e]:Fs.push(e))}let Ci=null,Yi=0,vs=null;function sG(e){vs=e}let kR=1,cc=0,xc=cc;function hF(e){xc=e}function SR(){return++kR}function a0(e){var t=e.f;if((t&Ir)!==0)return!0;if(t&wr&&(e.f&=~Lc),(t&fa)!==0){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}(t&Cs)!==0&&$r===null&&Yn(e,pr)}return!1}function CR(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Fs!==null&&Sd.call(Fs,e)))for(var i=0;i{e.ac.abort(Oo)}),e.ac=null);try{e.f|=gw;var c=e.fn,f=c();e.f|=ff;var d=e.deps,h=Ft==null?void 0:Ft.is_fork;if(Ci!==null){var p;if(h||gg(e,Yi),d!==null&&Yi>0)for(d.length=Yi+Ci.length,p=0;pn==null?void 0:n.call(this,s))}return e.startsWith("pointer")||e.startsWith("touch")||e==="wheel"?Yl(()=>{t.addEventListener(e,i,r)}):t.addEventListener(e,i,r),i}function _n(e,t,n,r,i){var s={capture:r,passive:i},a=oG(e,t,n,s);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&mk(()=>{t.removeEventListener(e,a,s)})}function Ne(e,t,n){(t[fc]??(t[fc]={}))[e]=n}function or(e){for(var t=0;t{throw b});throw d}}finally{e[fc]=t,delete e.currentTarget,Rs(c),ro(f)}}}var jT;const l_=((jT=globalThis==null?void 0:globalThis.window)==null?void 0:jT.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function lG(e){return(l_==null?void 0:l_.createHTML(e))??e}function RR(e){var t=mR("template");return t.innerHTML=lG(e.replaceAll("","")),t.content}function Bc(e,t){var n=Ht;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function z(e,t){var n=(t&QW)!==0,r=(t&eH)!==0,i,s=!e.startsWith("");return()=>{i===void 0&&(i=RR(s?e:""+e),n||(i=Va(i)));var a=r||dR?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=Va(a),l=a.lastChild;Bc(o,l)}else Bc(a,a);return a}}function uG(e,t,n="svg"){var r=!e.startsWith(""),i=`<${n}>${r?e:""+e}`,s;return()=>{if(!s){var a=RR(i),o=Va(a);s=Va(o)}var l=s.cloneNode(!0);return Bc(l,l),l}}function ri(e,t){return uG(e,t,"svg")}function Cw(e=""){{var t=Ko(e+"");return Bc(t,t),t}}function Mn(){var e=document.createDocumentFragment(),t=document.createComment(""),n=Ko();return e.append(t,n),Bc(t,n),e}function R(e,t){e!==null&&e.before(t)}const cG=["touchstart","touchmove"];function fG(e){return cG.includes(e)}function ae(e,t){var n=t==null?"":typeof t=="object"?`${t}`:t;n!==(e.__t??(e.__t=e.nodeValue))&&(e.__t=n,e.nodeValue=`${n}`)}function dG(e,t){return hG(e,t)}const lm=new Map;function hG(e,{target:t,anchor:n,props:r={},events:i,context:s,intro:a=!0,transformError:o}){ZH();var l=void 0,u=nG(()=>{var c=n??t.appendChild(Ko());IH(c,{pending:()=>{}},h=>{ln({});var p=Bn;s&&(p.c=s),i&&(r.$$events=i),l=e(h,r)||{},un()},o);var f=new Set,d=h=>{for(var p=0;p{var v;for(var h of f)for(const y of[t,document]){var p=lm.get(y),g=p.get(h);--g==0?(y.removeEventListener(h,Sw),p.delete(h),p.size===0&&lm.delete(y)):p.set(h,g)}kw.delete(d),c!==n&&((v=c.parentNode)==null||v.removeChild(c))}});return pG.set(l,u),l}let pG=new WeakMap;var Ks,Ua,Ki,yc,Qg,e0,Ny;class xk{constructor(t,n=!0){Ws(this,"anchor");Wt(this,Ks,new Map);Wt(this,Ua,new Map);Wt(this,Ki,new Map);Wt(this,yc,new Set);Wt(this,Qg,!0);Wt(this,e0,t=>{if(pe(this,Ks).has(t)){var n=pe(this,Ks).get(t),r=pe(this,Ua).get(n);if(r)bk(r),pe(this,yc).delete(n);else{var i=pe(this,Ki).get(n);i&&(pe(this,Ua).set(n,i.effect),pe(this,Ki).delete(n),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),r=i.effect)}for(const[s,a]of pe(this,Ks)){if(pe(this,Ks).delete(s),s===t)break;const o=pe(this,Ki).get(a);o&&(Oi(o.effect),pe(this,Ki).delete(a))}for(const[s,a]of pe(this,Ua)){if(s===n||pe(this,yc).has(s))continue;const o=()=>{if(Array.from(pe(this,Ks).values()).includes(s)){var u=document.createDocumentFragment();_k(a,u),u.append(Ko()),pe(this,Ki).set(s,{effect:a,fragment:u})}else Oi(a);pe(this,yc).delete(s),pe(this,Ua).delete(s)};pe(this,Qg)||!r?(pe(this,yc).add(s),_c(a,o,!1)):o()}}});Wt(this,Ny,t=>{pe(this,Ks).delete(t);const n=Array.from(pe(this,Ks).values());for(const[r,i]of pe(this,Ki))n.includes(r)||(Oi(i.effect),pe(this,Ki).delete(r))});this.anchor=t,Pt(this,Qg,n)}ensure(t,n){var r=Ft,i=gR();if(n&&!pe(this,Ua).has(t)&&!pe(this,Ki).has(t))if(i){var s=document.createDocumentFragment(),a=Ko();s.append(a),pe(this,Ki).set(t,{effect:_s(()=>n(a)),fragment:s})}else pe(this,Ua).set(t,_s(()=>n(this.anchor)));if(pe(this,Ks).set(r,t),i){for(const[o,l]of pe(this,Ua))o===t?r.unskip_effect(l):r.skip_effect(l);for(const[o,l]of pe(this,Ki))o===t?r.unskip_effect(l.effect):r.skip_effect(l.effect);r.oncommit(pe(this,e0)),r.ondiscard(pe(this,Ny))}else pe(this,e0).call(this,r)}}Ks=new WeakMap,Ua=new WeakMap,Ki=new WeakMap,yc=new WeakMap,Qg=new WeakMap,e0=new WeakMap,Ny=new WeakMap;function gF(e,t,...n){var r=new xk(e);s0(()=>{const i=t()??null;r.ensure(i,i&&(s=>i(s,...n)))},Oc)}function mh(e){Bn===null&&hH(),ph&&Bn.l!==null?gG(Bn).m.push(e):Lt(()=>{const t=_u(e);if(typeof t=="function")return t})}function gG(e){var t=e.l;return t.u??(t.u={a:[],b:[],m:[]})}function ue(e,t,n=!1){var r=new xk(e),i=n?Oc:0;function s(a,o){r.ensure(a,o)}s0(()=>{var a=!1;t((o,l=0)=>{a=!0,s(l,o)}),a||s(-1,null)},i)}const mG=Symbol("NaN");function vG(e,t,n){var r=new xk(e),i=!gh();s0(()=>{var s=t();s!==s&&(s=mG),i&&s!==null&&typeof s=="object"&&(s={}),r.ensure(s,n)})}function bt(e,t){return t}function yG(e,t,n){for(var r=[],i=t.length,s,a=t.length,o=0;o{if(s){if(s.pending.delete(f),s.done.add(f),s.pending.size===0){var d=e.outrogroups;$w(e,Oy(s.done)),d.delete(s),d.size===0&&(e.outrogroups=null)}}else a-=1},!1)}if(a===0){var l=r.length===0&&n!==null;if(l){var u=n,c=u.parentNode;JH(c),c.append(u),e.items.clear()}$w(e,t,!l)}else s={pending:new Set(t),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(s)}function $w(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(const a of e.pending.values())for(const o of a)r.add(e.items.get(o).e)}for(var i=0;i{var _=n();return ok(_)?_:_==null?[]:Oy(_)}),d,h=new Map,p=!0;function g(_){(b.effect.f&$s)===0&&(b.pending.delete(_),b.fallback=c,bG(b,d,a,t,r),c!==null&&(d.length===0?(c.f&Ya)===0?bk(c):(c.f^=Ya,xp(c,null,a)):_c(c,()=>{c=null})))}function v(_){b.pending.delete(_)}var y=s0(()=>{d=m(f);for(var _=d.length,x=new Set,w=Ft,A=gR(),E=0;E<_;E+=1){var k=d[E],C=r(k,E),M=p?null:o.get(C);M?(M.v&&Fd(M.v,k),M.i&&Fd(M.i,E),A&&w.unskip_effect(M.e)):(M=_G(o,p?a:mF??(mF=Ko()),k,C,E,i,t,n),p||(M.e.f|=Ya),o.set(C,M)),x.add(C)}if(_===0&&s&&!c&&(p?c=_s(()=>s(a)):(c=_s(()=>s(mF??(mF=Ko()))),c.f|=Ya)),_>x.size&&gH(),!p)if(h.set(w,x),A){for(const[N,P]of o)x.has(N)||w.skip_effect(P.e);w.oncommit(g),w.ondiscard(v)}else g(w);m(f)}),b={effect:y,items:o,pending:h,outrogroups:null,fallback:c};p=!1}function Xh(e){for(;e!==null&&(e.f&ca)===0;)e=e.next;return e}function bG(e,t,n,r,i){var M,N,P,I,T,$,L,W,U;var s=(r&GW)!==0,a=t.length,o=e.items,l=Xh(e.effect.first),u,c=null,f,d=[],h=[],p,g,v,y;if(s)for(y=0;y0){var C=(r&qT)!==0&&a===0?n:null;if(s){for(y=0;y{var O,H;if(f!==void 0)for(v of f)(H=(O=v.nodes)==null?void 0:O.a)==null||H.apply()})}function _G(e,t,n,r,i,s,a,o){var l=(a&WW)!==0?(a&YW)===0?VH(n,!1,!1):Pc(n):null,u=(a&HW)!==0?Pc(i):null;return{v:l,i:u,e:_s(()=>(s(t,l??n,u??i,o),()=>{e.delete(r)}))}}function xp(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,s=t&&(t.f&Ya)===0?t.nodes.start:n;r!==null;){var a=r0(r);if(s.before(r),r===i)return;r=a}}function El(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function xG(e,t,n=!1,r=!1,i=!1,s=!1){var a=e,o="";if(n)var l=e;me(()=>{var u=Ht;if(o!==(o=t()??"")){if(n){u.nodes=null,l.innerHTML=o,o!==""&&Bc(Va(l),l.lastChild);return}if(u.nodes!==null&&(_R(u.nodes.start,u.nodes.end),u.nodes=null),o!==""){var c=r?tH:i?nH:void 0,f=mR(r?"svg":i?"math":"template",c);f.innerHTML=o;var d=r||i?f:f.content;if(Bc(Va(d),d.lastChild),r||i)for(;Va(d);)a.before(Va(d));else a.before(d)}}})}function u_(e,t,n){vk(()=>{var r=_u(()=>t(e,n==null?void 0:n())||{});if(n&&(r!=null&&r.update)){var i=!1,s={};i0(()=>{var a=n();MR(a),i&&KT(s,a)&&(s=a,r.update(a))}),i=!0}if(r!=null&&r.destroy)return()=>r.destroy()})}function NR(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+=e;else if(typeof e=="object")if(Array.isArray(e)){var i=e.length;for(t=0;t=0;){var o=a+s;(a===0||vF.includes(r[a-1]))&&(o===r.length||vF.includes(r[o]))?r=(a===0?"":r.substring(0,a))+r.substring(o+1):a=o}}return r===""?null:r}function yF(e,t=!1){var n=t?" !important;":";",r="";for(var i of Object.keys(e)){var s=e[i];s!=null&&s!==""&&(r+=" "+i+": "+s+n)}return r}function c_(e){return e[0]!=="-"||e[1]!=="-"?e.toLowerCase():e}function kG(e,t){if(t){var n="",r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var s=!1,a=0,o=!1,l=[];r&&l.push(...Object.keys(r).map(c_)),i&&l.push(...Object.keys(i).map(c_));var u=0,c=-1;const g=e.length;for(var f=0;f{OR(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),mk(()=>{t.disconnect()})}function q1(e,t,n=t){var r=new WeakSet,i=!0;pk(e,"change",s=>{var a=s?"[selected]":":checked",o;if(e.multiple)o=[].map.call(e.querySelectorAll(a),Zp);else{var l=e.querySelector(a)??e.querySelector("option:not([disabled])");o=l&&Zp(l)}n(o),Ft!==null&&r.add(Ft)}),vk(()=>{var s=t();if(e===document.activeElement){var a=Ft;if(r.has(a))return}if(OR(e,s,i),i&&s===void 0){var o=e.querySelector(":checked");o!==null&&(s=Zp(o),n(s))}e.__value=s,i=!1}),SG(e)}function Zp(e){return"__value"in e?e.__value:e.value}const CG=Symbol("is custom element"),$G=Symbol("is html"),FG=dH?"progress":"PROGRESS";function bF(e,t){var n=wk(e);n.value===(n.value=t??void 0)||e.value===t&&(t!==0||e.nodeName!==FG)||(e.value=t??"")}function Gf(e,t){var n=wk(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function pt(e,t,n,r){var i=wk(e);i[t]!==(i[t]=n)&&(t==="loading"&&(e[fH]=n),n==null?e.removeAttribute(t):typeof n!="string"&&DG(e).includes(t)?e[t]=n:e.setAttribute(t,n))}function wk(e){return e.__attributes??(e.__attributes={[CG]:e.nodeName.includes("-"),[$G]:e.namespaceURI===WT})}var _F=new Map;function DG(e){var t=e.getAttribute("is")||e.nodeName,n=_F.get(t);if(n)return n;_F.set(t,n=[]);for(var r,i=e,s=Element.prototype;s!==i;){r=HT(i);for(var a in r)r[a].set&&n.push(a);i=lk(i)}return n}function df(e,t,n=t){var r=new WeakSet;pk(e,"input",async i=>{var s=i?e.defaultValue:e.value;if(s=d_(e)?h_(s):s,n(s),Ft!==null&&r.add(Ft),await Mi(),s!==(s=t())){var a=e.selectionStart,o=e.selectionEnd,l=e.value.length;if(e.value=s??"",o!==null){var u=e.value.length;a===o&&o===l&&u>l?(e.selectionStart=u,e.selectionEnd=u):(e.selectionStart=a,e.selectionEnd=Math.min(o,u))}}}),_u(t)==null&&e.value&&(n(d_(e)?h_(e.value):e.value),Ft!==null&&r.add(Ft)),i0(()=>{var i=t();if(e===document.activeElement){var s=Ft;if(r.has(s))return}d_(e)&&i===h_(e.value)||e.type==="date"&&!i&&!e.value||i!==e.value&&(e.value=i??"")})}function MG(e,t,n=t){pk(e,"change",r=>{var i=r?e.defaultChecked:e.checked;n(i)}),_u(t)==null&&n(e.checked),i0(()=>{var r=t();e.checked=!!r})}function d_(e){var t=e.type;return t==="number"||t==="range"}function h_(e){return e===""?null:+e}function xF(e,t){return e===t||(e==null?void 0:e[Xo])===t}function es(e={},t,n,r){var i=Bn.r,s=Ht;return vk(()=>{var a,o;return i0(()=>{a=o,o=[],_u(()=>{e!==n(...o)&&(t(e,...o),a&&xF(n(...a),e)&&t(null,...a))})}),()=>{let l=s;for(;l!==i&&l.parent!==null&&l.parent.f&pw;)l=l.parent;const u=()=>{o&&xF(n(...o),e)&&t(null,...o)},c=l.teardown;l.teardown=()=>{u(),c==null||c()}}}),e}function TG(e=!1){const t=Bn,n=t.l.u;if(!n)return;let r=()=>MR(t.s);if(e){let i=0,s={};const a=n0(()=>{let o=!1;const l=t.s;for(const u in l)l[u]!==s[u]&&(s[u]=l[u],o=!0);return o&&i++,i});r=()=>m(a)}n.b.length&&tG(()=>{wF(t,r),dw(n.b)}),Lt(()=>{const i=_u(()=>n.m.map(lH));return()=>{for(const s of i)typeof s=="function"&&s()}}),n.a.length&&Lt(()=>{wF(t,r),dw(n.a)})}function wF(e,t){if(e.l.s)for(const n of e.l.s)m(n);t()}function se(e,t,n,r){var _;var i=!ph||(n&XW)!==0,s=(n&ZW)!==0,a=(n&JW)!==0,o=r,l=!0,u=()=>(l&&(l=!1,o=a?_u(r):r),o);let c;if(s){var f=Xo in e||cH in e;c=((_=id(e,t))==null?void 0:_.set)??(f&&t in e?x=>e[t]=x:void 0)}var d,h=!1;s?[d,h]=MH(()=>e[t]):d=e[t],d===void 0&&r!==void 0&&(d=u(),c&&(i&&_H(),c(d)));var p;if(i?p=()=>{var x=e[t];return x===void 0?u():(l=!0,x)}:p=()=>{var x=e[t];return x!==void 0&&(o=void 0),x===void 0?o:x},i&&(n&KW)===0)return p;if(c){var g=e.$$legacy;return(function(x,w){return arguments.length>0?((!i||!w||g||h)&&c(w?p():x),x):p()})}var v=!1,y=((n&VW)!==0?n0:dk)(()=>(v=!1,p()));s&&m(y);var b=Ht;return(function(x,w){if(arguments.length>0){const A=w?m(y):i&&s?yt(x):x;return F(y,A),v=!0,o!==void 0&&(o=A),x}return nu&&v||(b.f&$s)!==0?y.v:m(y)})}var RG=z(""),NG=z('');function OG(e,t){ln(t,!0);let n=se(t,"currentPage",3,"metrics"),r=se(t,"tabAvailability",19,()=>({})),i=se(t,"optionalEmptyTabs",19,()=>new Set),s=se(t,"hideEmptyTabs",3,!1);const a=[{id:"metrics",label:"Metrics"},{id:"system",label:"System Metrics"},{id:"traces",label:"Traces"},{id:"media",label:"Media & Tables"},{id:"reports",label:"Alerts & Reports"},{id:"runs",label:"Runs"},{id:"files",label:"Files"},{id:"artifacts",label:"Artifacts"}];function o(v){var y;(y=t.onNavigate)==null||y.call(t,v)}function l(v){return i().has(v)&&r()[v]===!1}function u(v){return n()===v||v==="runs"&&n()==="run-detail"}let c=ke(()=>s()?a.filter(v=>v.id===n()||!l(v.id)):a);var f=NG(),d=D(S(f),2),h=S(d);gt(h,17,()=>m(c),bt,(v,y)=>{var b=RG();let _;var x=S(b);me((w,A)=>{_=qt(b,1,"nav-link svelte-d8j1hi",null,_,w),pt(b,"title",A),ae(x,m(y).label)},[()=>({active:u(m(y).id),empty:l(m(y).id)}),()=>l(m(y).id)?`${m(y).label} is empty for this project`:m(y).label]),Ne("click",b,()=>o(m(y).id)),R(v,b)});var p=D(h,2);let g;me(()=>g=qt(p,1,"nav-link settings-btn svelte-d8j1hi",null,g,{active:n()==="settings"})),Ne("click",p,()=>o("settings")),R(e,f),un()}or(["click"]);var LG=z(''),IG=z('
');function EF(e,t){ln(t,!0);let n=se(t,"choices",19,()=>[]),r=se(t,"selected",31,()=>yt([])),i=se(t,"colors",19,()=>[]),s=se(t,"ontoggle",3,null),a=se(t,"getKey",3,c=>c),o=se(t,"getLabel",3,c=>c);function l(c){var d;const f=a()(c);r().includes(f)?r(r().filter(h=>h!==f)):r([...r(),f]),(d=s())==null||d()}var u=IG();gt(u,21,n,bt,(c,f,d)=>{var h=LG(),p=S(h),g=D(p,2),v=D(g,2),y=S(v);me((b,_,x)=>{Gf(p,b),al(g,`background: ${(i()[d]||"#999")??""}`),pt(v,"title",_),ae(y,x)},[()=>r().includes(a()(m(f))),()=>o()(m(f)),()=>o()(m(f))]),Ne("change",p,()=>l(m(f))),R(c,h)}),R(e,u),un()}or(["change"]);var PG=z(' '),BG=z(' '),zG=z('
  • '),jG=z('
      '),UG=z('');function Fw(e,t){ln(t,!0);let n=se(t,"label",3,"Dropdown"),r=se(t,"info",3,""),i=se(t,"value",15,null),s=se(t,"choices",19,()=>[]),a=se(t,"filterable",3,!0),o=se(t,"showLabel",3,!0),l,u=ie(!1),c=ie(""),f=ie(null),d=ie(yt([])),h=ie(0),p=ie(null),g=ie(null),v=ie(300),y=ke(()=>s().map(G=>typeof G=="object"&&G!==null?G:{label:String(G),value:G})),b=ke(()=>i()!==null?m(y).findIndex(G=>G.value===i()):-1);Lt(()=>{if(m(u))return;const G=m(y).findIndex(J=>J.value===i());i()!==null&&G>=0?F(c,m(y)[G].label,!0):F(c,"")}),Lt(()=>{F(d,m(u)?_(m(c)):m(y).map((G,J)=>J),!0)});function _(G){if(!G)return m(y).map((ce,xe)=>xe);const J=G.toLowerCase();return m(y).map((ce,xe)=>ce.label.toLowerCase().includes(J)?xe:-1).filter(ce=>ce>=0)}function x(){var G;if(F(c,""),F(d,m(y).map((J,ce)=>ce),!0),F(u,!0),l){const J=(G=l.closest(".wrap"))==null?void 0:G.getBoundingClientRect();if(J){F(h,J.width,!0);const ce=window.innerHeight-J.bottom,xe=J.top;ce>=200||ce>xe?(F(p,`${J.bottom}px`),F(g,null),F(v,ce-16)):(F(g,`${window.innerHeight-J.top}px`),F(p,null),F(v,xe-16))}}}function w(G){m(u)&&(G.preventDefault(),l==null||l.blur())}function A(){const G=m(y).findIndex(J=>J.label===m(c));if(G>=0)i(m(y)[G].value);else if(i()!==null){const J=m(y).findIndex(ce=>ce.value===i());F(c,J>=0?m(y)[J].label:"",!0)}else F(c,"");F(u,!1),F(f,null),F(d,m(y).map((J,ce)=>ce),!0)}function E(G){const J=parseInt(G);isNaN(J)||(i(m(y)[J].value),F(c,m(y)[J].label,!0),F(u,!1),F(f,null),l==null||l.blur())}async function k(G){if(await Mi(),F(d,_(m(c)),!0),m(d).length>0&&m(f)===null&&F(f,m(d)[0],!0),G.key==="ArrowDown")if(G.preventDefault(),m(f)===null)F(f,m(d)[0]??null,!0);else{const J=m(d).indexOf(m(f));J0&&F(f,m(d)[J-1],!0)}}else G.key==="Enter"?m(f)!==null&&E(m(f)):G.key==="Escape"&&(F(u,!1),l==null||l.blur())}var C=UG(),M=S(C);{var N=G=>{var J=PG(),ce=S(J);me(()=>ae(ce,n())),R(G,J)};ue(M,G=>{o()&&G(N)})}var P=D(M,2);{var I=G=>{var J=BG(),ce=S(J);me(()=>ae(ce,r())),R(G,J)};ue(P,G=>{r()&&G(I)})}var T=D(P,2);let $;var L=S(T),W=S(L),U=S(W);es(U,G=>l=G,()=>l);var O=D(T,2);{var H=G=>{var J=jG(),ce=S(J);let xe;gt(ce,21,()=>m(d),bt,(be,Le)=>{var tt=zG();let he;var Y=S(tt);let Ce;var le=D(Y);me(()=>{he=qt(tt,1,"item svelte-kgylqb",null,he,{selected:m(Le)===m(b),active:m(Le)===m(f)}),pt(tt,"data-index",m(Le)),pt(tt,"aria-selected",m(Le)===m(b)),Ce=qt(Y,1,"check-mark svelte-kgylqb",null,Ce,{hide:m(Le)!==m(b)}),ae(le,` ${m(y)[m(Le)].label??""}`)}),R(be,tt)}),me(()=>xe=al(ce,"",xe,{top:m(p),bottom:m(g),"max-height":`${m(v)??""}px`,width:`${m(h)??""}px`})),Ne("mousedown",ce,be=>{var tt;be.preventDefault();const Le=(tt=be.target.closest("li"))==null?void 0:tt.dataset.index;Le!==void 0&&E(Le)}),R(G,J)};ue(O,G=>{m(u)&&G(H)})}me(()=>{$=qt(T,1,"wrap svelte-kgylqb",null,$,{focused:m(u)}),pt(U,"aria-label",n()),U.readOnly=!a(),pt(U,"placeholder",i()===null?"Select...":"")}),Ne("mousedown",U,w),Ne("keydown",U,k),_n("blur",U,A),_n("focus",U,x),df(U,()=>m(c),G=>F(c,G)),R(e,C),un()}or(["mousedown","keydown"]);var qG=z('
      ',1);function LR(e,t){ln(t,!0);let n=se(t,"projects",19,()=>[]),r=se(t,"selectedProject",15,null),i=se(t,"projectLocked",3,!1);var s=Mn(),a=ct(s);{var o=u=>{var c=qG(),f=D(ct(c),2),d=S(f);me(()=>ae(d,r()??"—")),R(u,c)},l=u=>{Fw(u,{label:"Project",get choices(){return n()},filterable:!0,get value(){return r()},set value(c){r(c)}})};ue(a,u=>{i()?u(o):u(l,-1)})}R(e,s),un()}const IR={light:"/static/trackio/trackio_logo_type_light_transparent.png",dark:"/static/trackio/trackio_logo_type_dark_transparent.png"};var WG=z('
      ');function PR(e,t){ln(t,!0);let n=se(t,"logoUrls",3,IR),r=se(t,"darkMode",3,!1);var i=WG(),s=S(i);me(()=>pt(s,"src",r()?n().dark:n().light)),R(e,i),un()}var HG=z(' '),GG=z('');function um(e,t){ln(t,!0);let n=se(t,"label",3,""),r=se(t,"checked",15,!1),i=se(t,"showLabel",3,!0);function s(c){r(c.currentTarget.checked)}var a=GG(),o=S(a),l=D(o,2);{var u=c=>{var f=HG(),d=S(f);me(()=>ae(d,n())),R(c,f)};ue(l,c=>{i()&&n()&&c(u)})}Ne("input",o,s),MG(o,r),R(e,a),un()}or(["input"]);var YG=z(' '),VG=z(' '),XG=z('
      ');function KG(e,t){ln(t,!0);let n=se(t,"label",3,"Slider"),r=se(t,"info",3,""),i=se(t,"value",15,0),s=se(t,"min",3,0),a=se(t,"max",3,100),o=se(t,"step",3,1),l=se(t,"showLabel",3,!0),u,c=ke(()=>i()>a()?100:i(){u&&u.style.setProperty("--range_progress",`${m(c)}%`)});var f=XG(),d=S(f),h=S(d);{var p=E=>{var k=YG(),C=S(k);me(()=>ae(C,n())),R(E,k)};ue(h,E=>{l()&&E(p)})}var g=D(d,2);{var v=E=>{var k=VG(),C=S(k);me(()=>ae(C,r())),R(E,k)};ue(g,E=>{r()&&E(v)})}var y=D(g,2),b=S(y),_=S(b),x=D(b,2);es(x,E=>u=E,()=>u);var w=D(x,2),A=S(w);me(()=>{ae(_,s()),pt(x,"min",s()),pt(x,"max",a()),pt(x,"step",o()),ae(A,a())}),df(x,i),R(e,f),un()}var ZG=z(' '),JG=z(' '),QG=z('
      ');function p_(e,t){ln(t,!0);let n=se(t,"label",3,""),r=se(t,"info",3,""),i=se(t,"value",15,""),s=se(t,"placeholder",3,""),a=se(t,"showLabel",3,!0);var o=QG(),l=S(o);{var u=p=>{var g=ZG(),v=S(g);me(()=>ae(v,n())),R(p,g)};ue(l,p=>{a()&&n()&&p(u)})}var c=D(l,2);{var f=p=>{var g=JG(),v=S(g);me(()=>ae(v,r())),R(p,g)};ue(c,p=>{r()&&p(f)})}var d=D(c,2),h=S(d);me(()=>pt(h,"placeholder",s())),df(h,i),R(e,o),un()}const eY=["#A8769B","#E89957","#3B82F6","#10B981","#EF4444","#8B5CF6","#14B8A6","#F59E0B","#EC4899","#06B6D4"];let Dw=eY;function tY(e){Array.isArray(e)&&e.length>0&&(Dw=e)}function Mw(e){return Dw[e%Dw.length]}function o0(e){const t={};return e.forEach((n,r)=>{const i=typeof n=="string"?n:(n==null?void 0:n.id)??(n==null?void 0:n.name)??String(r);t[i]=Mw(r)}),t}function AF(e){return!e||e.length===0?[]:[e[0]]}function nY(e,t,n){const r=e??[],i=t??[],s=n??[],a=new Set(i),o=r.filter(u=>a.has(u));if(r.length===0||o.length===0)return[...i];if(s.length>0&&r.length===s.length){const u=new Set(o),c=i.filter(f=>!u.has(f));return[...o,...c]}return o}const BR=["project","run","timestamp","step","time","metrics"];function rY(e,t,n,r,i,s){if(!e||e.length===0)return null;let a=e.map(d=>({...d}));Object.hasOwn(a[0],"step")||a.forEach((d,h)=>d.step=h);let o="step";if(r==="time"&&Object.hasOwn(a[0],"timestamp")){const d=new Date(a[0].timestamp).getTime();a.forEach(h=>{h.time=(new Date(h.timestamp).getTime()-d)/1e3}),o="time"}else r!=="step"&&a.some(d=>typeof d[r]=="number"&&isFinite(d[r]))&&(o=r);i&&a.forEach(d=>{if(d[o]!=null){const h=d[o];d[o]=h<=0?Math.log10(Math.max(h,0)+1):Math.log10(h)}});const u=zR(a).filter(d=>!BR.includes(d)&&d!==o);s&&a.forEach(d=>{u.forEach(h=>{if(d[h]!=null&&typeof d[h]=="number"){const p=d[h];d[h]=p<=0?Math.log10(Math.max(p,0)+1):Math.log10(p)}})});const c=typeof t=="string"?t:(t==null?void 0:t.id)??(t==null?void 0:t.name),f=typeof t=="string"?t:(t==null?void 0:t.name)??(t==null?void 0:t.id);if(n>0){const d=a.map(p=>({...p,run:f,run_id:c,series_key:c,data_type:"original"})),h=iY(a,u,n).map(p=>({...p,run:f,run_id:c,series_key:c,data_type:"smoothed"}));return{rows:[...d,...h],xColumn:o}}return{rows:a.map(d=>({...d,run:f,run_id:c,series_key:c,data_type:"original"})),xColumn:o}}function iY(e,t,n){const r=Math.max(3,Math.min(n,e.length)),i=Math.floor(r/2);return e.map((s,a)=>{const o={...s};return t.forEach(l=>{if(s[l]==null||typeof s[l]!="number")return;const u=Math.max(0,a-i),c=Math.min(e.length,a+i+1);let f=0,d=0;for(let h=u;h0?f/d:s[l]}),o})}function zR(e){if(!e||e.length===0)return[];const t=new Set;return e.forEach(n=>{Object.keys(n).forEach(r=>{typeof n[r]=="number"&&isFinite(n[r])&&t.add(r)})}),Array.from(t)}function sY(e){return zR(e).filter(t=>!BR.includes(t))}function Tw(e,t,n,r){let i=e.filter(o=>o[n]!=null&&o[n]!==void 0);if(r){const o=new Map;for(const u of i){const c=`${u.series_key||u.run||""}\0${u.data_type||"original"}`;o.has(c)||o.set(c,[]),o.get(c).push(u)}const l=[];for(const[,u]of o){u.sort((d,h)=>d[t]-h[t]);let c=0,f=u.length-1;for(;c=0&&u[f][t]>r[1];)f--;c=Math.max(0,c-1),f=Math.min(u.length-1,f+1),l.push(...u.slice(c,f+1))}i=l}const s=i.filter(o=>o.data_type==="original"||!o.data_type);let a;if(s.length>0){let o=1/0,l=-1/0;for(const u of s){const c=u[n];c!=null&&(cl&&(l=c))}o!==1/0&&(a=[o,l])}return{data:jR(i,t,n,"series_key",r,["run","series_key"]).data,yExtent:a}}function kF(e,t,n,r,i,s=[]){const a=[t,n];r&&Object.hasOwn(e[0],r)&&a.push(r),a.push(...s);let o=e.map(p=>{const g={};return[...new Set(a)].forEach(v=>g[v]=p[v]),p.data_type&&(g.data_type=p.data_type),p.run&&(g.run=p.run),g});const l=Math.min(...o.map(p=>p[t]).filter(p=>p!=null)),u=Math.max(...o.map(p=>p[t]).filter(p=>p!=null));let c=i;if(i){const[p,g]=[i[0]??l,i[1]??u];c=[p,g]}const f={};r?o.forEach(p=>{const g=p[r]||"__default";f[g]||(f[g]=[]),f[g].push(p)}):f.__default=o;const d=[],h=100;return Object.values(f).forEach(p=>{if(p.sort((_,x)=>(_[t]||0)-(x[t]||0)),p.length<500){d.push(...p);return}const g=c?c[0]:l,v=c?c[1]:u;if(g===v){d.push(...p);return}const y=(v-g)/h,b=new Map;p.forEach(_=>{const x=_[t];if(x==null)return;const w=Math.min(Math.floor((x-g)/y),h-1);b.has(w)||b.set(w,[]),b.get(w).push(_)}),b.forEach(_=>{if(_.length===0)return;let x=_[0],w=_[0];_.forEach(A=>{A[n]w[n]&&(w=A)}),d.push(x),x!==w&&d.push(w)})}),d.sort((p,g)=>(p[t]||0)-(g[t]||0)),{data:d,xLim:c}}function jR(e,t,n,r,i,s=[]){if(!e||e.length===0)return{data:e,xLim:i};if(e.some(o=>o.data_type)&&r&&e[0]&&Object.hasOwn(e[0],r)){const o=new Map;for(const c of e){const f=`${c[r]??"__default"}\0${c.data_type??"original"}`;o.has(f)||o.set(f,[]),o.get(f).push(c)}const l=[];let u=i;for(const c of o.values()){const f=kF(c,t,n,r,i,s);l.push(...f.data),u=f.xLim}return l.sort((c,f)=>(c[t]||0)-(f[t]||0)),{data:l,xLim:u}}return kF(e,t,n,r,i,s)}function UR(e,t=[]){const n=[],r={};e.forEach(u=>{if(u.includes("/")){const c=u.split("/"),f=c[0];if(r[f]||(r[f]={direct:[],subgroups:{}}),c.length===2)r[f].direct.push(u);else{const d=c[1];r[f].subgroups[d]||(r[f].subgroups[d]=[]),r[f].subgroups[d].push(u)}}else n.push(u)});function i(u){if(!t||t.length===0)return u.sort();const c=[],f=[...u];for(const d of t)for(let h=f.length-1;h>=0;h--)s(f[h],d)&&(c.push(f[h]),f.splice(h,1));return f.sort(),[...c,...f]}function s(u,c){return c===u||c.endsWith("/*")&&u.startsWith(c.slice(0,-1))?!0:c.includes("*")?new RegExp("^"+c.replace(/\*/g,".*")+"$").test(u):!1}function a(u){if(!t||t.length===0)return 1/0;for(let c=0;c0&&(o.charts={direct:i(n),subgroups:{}});const l=Object.keys(r);if(l.sort((u,c)=>{const f=a(u),d=a(c);return f!==d?f-d:u.localeCompare(c)}),l.forEach(u=>{const c=r[u];c.direct=i(c.direct),Object.keys(c.subgroups).forEach(f=>{c.subgroups[f]=i(c.subgroups[f])}),o[u]=c}),"charts"in o){const u=a("charts");if(u<1/0){const c=Object.entries(o);c.sort(([d],[h])=>{const p=d==="charts"?u:a(d),g=h==="charts"?u:a(h);return p!==g?p-g:d.localeCompare(h)});const f={};return c.forEach(([d,h])=>{f[d]=h}),f}}return o}function qR(e,t,n){if(!t||!e||e.length===0)return"";const r=new Set,i=[];for(const s of e){const a=s[t];a&&!r.has(a)&&(r.add(a),i.push(`${a}:${n[a]??"#999"}`))}return i.sort(),i.join("|")}function SF(e){if(!e)return null;const t=typeof e.step=="number"?e.step:null,n=e.timestamp??null;return{step:t,ts:n}}function WR(e,t){if(!e||!t)return!!t;if(t.length!==e.length)return!0;if(t.length===0)return!1;const n=SF(e[e.length-1]),r=SF(t[t.length-1]);return!n||!r?!0:n.step!==r.step||n.ts!==r.ts}function Iy(e,t){if(!t||!t.trim())return e;try{const n=new RegExp(t,"i");return e.filter(r=>n.test(r))}catch{return e.filter(n=>n.toLowerCase().includes(t.toLowerCase()))}}const W1=Object.freeze({_Group:"Group",_Username:"Username"});function aY(e){return e.startsWith("_")&&!Object.hasOwn(W1,e)}function oY(e){return W1[e]??e}function lY(e,t){const n=new Set;for(const r of Object.values(e??{})){if(!r||typeof r!="object")continue;const i=r[t],s=i==null?"(unset)":String(i);if(n.add(s),n.size>=2)return!0}return!1}function uY(e){const t=Object.keys(W1).filter(a=>lY(e,a)).map(a=>({label:oY(a),value:a})),n=new Set(t.map(a=>a.label)),r=new Set,i=new Set;for(const a of Object.values(e??{}))if(!(!a||typeof a!="object"))for(const o of Object.keys(a))a[o]===null||a[o]===void 0||aY(o)||Object.hasOwn(W1,o)||n.has(o)||(typeof a[o]=="object"?i.add(o):r.add(o));for(const a of i)r.delete(a);const s=[...r].sort().map(a=>({label:a,value:a}));return[{label:"None",value:null},...t,...s]}function cY(e,t,n){if(!n)return null;const r=new Map;for(const i of e){const a=((t??{})[i.id]??(t??{})[i.name]??{})[n],o=a==null?"(unset)":String(a);r.has(o)||r.set(o,[]),r.get(o).push(i)}return r}var fY=ri(''),dY=ri(''),hY=z('
      '),pY=ri(''),gY=z(''),mY=z(''),vY=z(''),yY=ri(''),bY=z(''),_Y=z(''),xY=z(''),wY=z('
      '),EY=z('
      '),AY=z('
      '),kY=z('
      '),SY=z(''),CY=z('
      '),$Y=z('
      ',1),FY=z('
      ',1),DY=z(''),MY=z('

      Signed in, but this account does not have write access to this Space.

      '),TY=z('

      Required to delete or rename runs (Space owner or collaborator with write access).

      ',1),RY=z(''),NY=z(''),OY=z(''),LY=z('
      ');function IY(e,t){ln(t,!0);let n=se(t,"open",15,!0),r=se(t,"variant",3,"full"),i=se(t,"currentPage",3,"metrics"),s=se(t,"projects",19,()=>[]),a=se(t,"selectedProject",15,null),o=se(t,"runs",19,()=>[]),l=se(t,"selectedRuns",31,()=>yt([])),u=se(t,"availableSystemDevices",19,()=>[]),c=se(t,"selectedSystemDevices",31,()=>yt([])),f=se(t,"smoothing",15,10),d=se(t,"xAxis",15,"step"),h=se(t,"logScaleX",15,!1),p=se(t,"logScaleY",15,!1),g=se(t,"metricFilter",15,""),v=se(t,"realtimeEnabled",15,!0),y=se(t,"showHeaders",15,!0),b=se(t,"filterText",15,""),_=se(t,"runConfigs",19,()=>({})),x=se(t,"metricColumns",19,()=>[]),w=se(t,"spacesMode",3,!1),A=se(t,"runMutationAllowed",3,!0),E=se(t,"mutationAuth",3,"local"),k=se(t,"readOnlySource",3,null),C=se(t,"projectLocked",3,!1),M=se(t,"spaceId",3,null),N=se(t,"logoUrls",3,void 0),P=se(t,"darkMode",3,!1),I=ie(0),T=null;mh(()=>{const ee=()=>{cR(I)};return window.addEventListener("popstate",ee),()=>{window.removeEventListener("popstate",ee),T&&(clearTimeout(T),T=null)}});let $=ke(()=>(m(I),`${window.location.origin}${window.__trackio_base||""}/oauth/hf/start`)),L=ke(()=>["step","time",...x()]);function W(){n(!n())}function U(ee,ge){return ee.indeterminate=ge,{update(ve){ee.indeterminate=ve}}}let O=ke(()=>{if(!b()||!b().trim())return o();const ee=new Set(Iy(o().map(ge=>ge.name),b()));return o().filter(ge=>ee.has(ge.name))}),H=ke(()=>o0(o())),G=ke(()=>m(O).map(ee=>ee.id??ee.name)),J=ie(null);Lt(()=>{a(),F(J,null)}),Lt(()=>{m(ce).some(ee=>ee.value===m(J))||F(J,null)});let ce=ke(()=>uY(_())),xe=ke(()=>cY(m(O),_(),m(J))),be=ie(!1),Le=ie("share"),tt=ie(null);function he(){F(be,!m(be)),m(be)&&m(O).length>0?l(AF(m(G))):m(be)||l([...m(G)])}Lt(()=>{if(!m(be)||m(G).length===0)return;const ee=AF(m(G));(l().length!==ee.length||l()[0]!==ee[0])&&l(ee)});function Y(ee){c().includes(ee)?c(c().filter(ge=>ge!==ee)):c([...c(),ee])}function Ce(ee){if(!ee||!ee.includes("/"))return"";const[ge,ve]=ee.split("/",2);return!ge||!ve?"":`${ge}-${ve}.hf.space`}function le(){const ee=Ce(M());if(ee)return`https://${ee}`;const ge=window.__trackio_base||"/",ve=new URL(ge,window.location.origin);let $e=ve.href;return $e.endsWith("/")&&($e=$e.slice(0,-1)),$e||ve.origin}function V(ee,ge){const ve=new Set(ge.map($e=>$e.id??$e.name));return ee.filter($e=>ve.has($e))}let q=ke(()=>{var Xe;if(m(I),i()!=="metrics"||!w()||!a())return"";const ee=new URLSearchParams;ee.set("project",a()),(Xe=g())!=null&&Xe.trim()&&ee.set("metric_filter",g().trim());const ge=V(l(),o());ge.length&&ee.set("run_ids",ge.join(",")),f()!=null&&f()!==10&&ee.set("smoothing",f().toString()),y()||ee.set("accordion","hidden"),ee.set("sidebar","hidden"),ee.set("navbar","hidden");const ve=le(),$e=ee.toString();return $e?`${ve}/?${$e}`:`${ve}/`}),B=ke(()=>m(q)?``:"");async function Q(ee,ge){if(ee){try{await navigator.clipboard.writeText(ee)}catch{const ve=document.createElement("textarea");ve.value=ee,ve.style.position="fixed",ve.style.opacity="0",document.body.appendChild(ve),ve.focus(),ve.select(),document.execCommand("copy"),document.body.removeChild(ve)}F(tt,ge,!0),T&&clearTimeout(T),T=setTimeout(()=>{F(tt,null),T=null},2e3)}}var X=LY();let j;var re=S(X),Me=S(re);{var K=ee=>{var ge=fY();R(ee,ge)},Z=ee=>{var ge=dY();R(ee,ge)};ue(Me,ee=>{n()?ee(K):ee(Z,-1)})}var te=D(re,2);{var _e=ee=>{var ge=OY(),ve=S(ge),$e=S(ve);PR($e,{get logoUrls(){return N()},get darkMode(){return P()}});var Xe=D($e,2),Re=S(Xe);LR(Re,{get projects(){return s()},get projectLocked(){return C()},get selectedProject(){return a()},set selectedProject(fe){a(fe)}});var je=D(Xe,2);{var Ze=fe=>{var Ie=hY(),Je=S(Ie);p_(Je,{label:"Run Filter",info:"Filter runs using regex patterns. Leave empty to show all runs.",placeholder:"e.g., baseline|exp-.*|v2",get value(){return b()},set value(xt){b(xt)}}),R(fe,Ie)};ue(je,fe=>{r()==="compact"&&i()==="runs"&&fe(Ze)})}var Ke=D(je,2);{var Qe=fe=>{var Ie=FY(),Je=ct(Ie);{var xt=rt=>{var at=wY(),Mt=S(at),jn=S(Mt);let yn;var wi=D(jn,2);let Un;var qn=D(Mt,2);{var Zn=cr=>{var ii=vY(),Ai=D(S(ii),2);{var bn=fr=>{var Gi=gY(),Fo=S(Gi),qs=D(Fo,2),Nn=S(qs);{var Yt=dr=>{var ps=pY();R(dr,ps)},$a=dr=>{var ps=Cw("Copy");R(dr,ps)};ue(Nn,dr=>{m(tt)==="share"?dr(Yt):dr($a,-1)})}me(()=>{bF(Fo,m(q)),pt(qs,"aria-label",m(tt)==="share"?"Copied":"Copy share link")}),Ne("click",qs,()=>Q(m(q),"share")),R(fr,Gi)},Bu=fr=>{var Gi=mY();R(fr,Gi)};ue(Ai,fr=>{m(q)?fr(bn):fr(Bu,-1)})}R(cr,ii)},Ei=cr=>{var ii=xY(),Ai=D(S(ii),2);{var bn=fr=>{var Gi=bY(),Fo=S(Gi),qs=D(Fo,2),Nn=S(qs);{var Yt=dr=>{var ps=yY();R(dr,ps)},$a=dr=>{var ps=Cw("Copy");R(dr,ps)};ue(Nn,dr=>{m(tt)==="embed"?dr(Yt):dr($a,-1)})}me(()=>{bF(Fo,m(B)),pt(qs,"aria-label",m(tt)==="embed"?"Copied":"Copy embed code")}),Ne("click",qs,()=>Q(m(B),"embed")),R(fr,Gi)},Bu=fr=>{var Gi=_Y();R(fr,Gi)};ue(Ai,fr=>{m(B)?fr(bn):fr(Bu,-1)})}R(cr,ii)};ue(qn,cr=>{m(Le)==="share"?cr(Zn):cr(Ei,-1)})}me(()=>{yn=qt(jn,1,"share-tab-btn svelte-181dlmc",null,yn,{active:m(Le)==="share"}),Un=qt(wi,1,"share-tab-btn svelte-181dlmc",null,Un,{active:m(Le)==="embed"})}),Ne("click",jn,()=>{F(Le,"share")}),Ne("click",wi,()=>{F(Le,"embed")}),R(rt,at)};ue(Je,rt=>{i()==="metrics"&&w()&&rt(xt)})}var Et=D(Je,2),Ye=S(Et),ut=S(Ye),At=S(ut);u_(At,(rt,at)=>U==null?void 0:U(rt,at),()=>l().length>0&&l().length{var at=AY();gt(at,21,()=>[...m(xe).entries()],bt,(Mt,jn)=>{var yn=ke(()=>pg(m(jn),2));let wi=()=>m(yn)[0],Un=()=>m(yn)[1];const qn=ke(()=>Un().map(Nn=>Nn.id??Nn.name)),Zn=ke(()=>m(qn).filter(Nn=>l().includes(Nn)));var Ei=EY(),cr=S(Ei),ii=S(cr),Ai=S(ii);u_(Ai,(Nn,Yt)=>U==null?void 0:U(Nn,Yt),()=>m(Zn).length>0&&m(Zn).lengthUn().map(Yt=>m(H)[Yt.id??Yt.name]??Mw(Math.max(0,o().indexOf(Yt)))));EF(qs,{get choices(){return Un()},getKey:Yt=>Yt.id??Yt.name,getLabel:Yt=>Yt.name,get colors(){return m(Nn)},ontoggle:()=>{F(be,!1)},get selected(){return l()},set selected(Yt){l(Yt)}})}me(()=>{Gf(Ai,m(Zn).length===m(qn).length&&m(qn).length>0),pt(bn,"title",wi()),ae(Bu,wi()),ae(Gi,`(${Un().length??""})`)}),Ne("change",Ai,()=>{if(m(Zn).length===m(qn).length)l(l().filter(Nn=>!m(qn).includes(Nn)));else{const Nn=m(qn).filter(Yt=>!l().includes(Yt));l([...l(),...Nn])}F(be,!1)}),R(Mt,Ei)}),R(rt,at)},Nt=rt=>{var at=kY(),Mt=S(at);{let jn=ke(()=>m(O).map(yn=>m(H)[yn.id??yn.name]??Mw(Math.max(0,o().indexOf(yn)))));EF(Mt,{get choices(){return m(O)},getKey:yn=>yn.id??yn.name,getLabel:yn=>yn.name,get colors(){return m(jn)},ontoggle:()=>{F(be,!1)},get selected(){return l()},set selected(yn){l(yn)}})}R(rt,at)};ue(vn,rt=>{m(xe)?rt(lt):rt(Nt,-1)})}var ne=D(vn,2);{var Ae=rt=>{var at=CY(),Mt=S(at),jn=S(Mt);u_(jn,(qn,Zn)=>U==null?void 0:U(qn,Zn),()=>c().length>0&&c().length{var Ei=SY(),cr=S(Ei),ii=D(cr,2),Ai=S(ii);me(bn=>{Gf(cr,bn),pt(ii,"title",m(Zn)),ae(Ai,m(Zn))},[()=>c().includes(m(Zn))]),Ne("change",cr,()=>Y(m(Zn))),R(qn,Ei)}),me(()=>{Gf(jn,c().length===u().length&&u().length>0),ae(wi,`Devices (${u().length??""})`)}),Ne("change",jn,()=>{c().length===u().length?c([]):c([...u()])}),R(rt,at)};ue(ne,rt=>{i()==="system"&&u().length>0&&rt(Ae)})}var St=D(Et,2);{var Ot=rt=>{var at=$Y(),Mt=D(ct(at),2),jn=S(Mt);um(jn,{label:"Refresh metrics realtime",get checked(){return v()},set checked(bn){v(bn)}});var yn=D(jn,2);um(yn,{label:"Show section headers",get checked(){return y()},set checked(bn){y(bn)}});var wi=D(Mt,2),Un=S(wi);KG(Un,{label:"Smoothing Factor (0 = no smoothing)",min:0,max:20,step:1,get value(){return f()},set value(bn){f(bn)}});var qn=D(wi,2),Zn=S(qn);Fw(Zn,{label:"X-axis",get choices(){return m(L)},filterable:!1,get value(){return d()},set value(bn){d(bn)}});var Ei=D(Zn,2);um(Ei,{label:"Log scale X-axis",get checked(){return h()},set checked(bn){h(bn)}});var cr=D(Ei,2);um(cr,{label:"Log scale Y-axis",get checked(){return p()},set checked(bn){p(bn)}});var ii=D(qn,2),Ai=S(ii);p_(Ai,{label:"Metric Filter",info:"Filter metrics using regex patterns. Leave empty to show all metrics.",placeholder:"e.g., loss|ndcg@10|gpu",get value(){return g()},set value(bn){g(bn)}}),R(rt,at)};ue(St,rt=>{(i()==="metrics"||i()==="system")&&rt(Ot)})}me(()=>{Gf(At,l().length===m(G).length&&m(G).length>0),ae(et,`Runs (${m(G).length??""})`),Gf(vt,m(be))}),Ne("change",At,()=>{l().length===m(G).length?l([]):l([...m(G)]),F(be,!1)}),Ne("change",vt,he),R(fe,Ie)};ue(Ke,fe=>{r()==="full"&&fe(Qe)})}var nt=D(ve,2);{var Ge=fe=>{var Ie=DY(),Je=D(S(Ie),2),xt=S(Je);me(()=>{pt(Je,"href",k().url),ae(xt,k().url)}),R(fe,Ie)},qe=fe=>{var Ie=RY(),Je=S(Ie);{var xt=Ye=>{var ut=MY();R(Ye,ut)},Et=Ye=>{var ut=TY(),At=ct(ut);me(()=>pt(At,"href",m($))),R(Ye,ut)};ue(Je,Ye=>{E()==="oauth_insufficient"?Ye(xt):Ye(Et,-1)})}R(fe,Ie)},oe=fe=>{var Ie=NY(),Je=D(S(Ie),2);pt(Je,"href",`${window.__trackio_base||""}/oauth/logout`),Ne("click",Je,()=>{sessionStorage.removeItem("trackio_oauth_session")}),R(fe,Ie)};ue(nt,fe=>{k()?fe(Ge):w()&&!A()?fe(qe,1):w()&&A()&&E()==="oauth"&&fe(oe,2)})}R(ee,ge)};ue(te,ee=>{n()&&ee(_e)})}me(()=>j=qt(X,1,"sidebar svelte-181dlmc",null,j,{collapsed:!n()})),Ne("click",re,W),R(e,X),un()}or(["click","change"]);var PY=z('
      '),BY=z('
      '),zY=z('
      '),jY=z('
      '),UY=z('
      ');function qY(e,t){ln(t,!0);let n=se(t,"alerts",19,()=>[]);const r={info:"🔵",warn:"🟡",error:"🔴"};let i=ie(yt({})),s=ie(null),a=ie(!1),o=ke(()=>m(s)?n().filter(d=>d.level===m(s)):n());function l(d){F(i,{...m(i),[d]:!m(i)[d]},!0)}var u=Mn(),c=ct(u);{var f=d=>{var h=UY();let p;var g=S(h),v=S(g),y=S(v),b=D(v,2);{var _=k=>{var C=PY(),M=S(C);let N;var P=D(M,2);let I;var T=D(P,2);let $;var L=D(T,2);let W;me(()=>{N=qt(M,1,"pill svelte-x5aqew",null,N,{active:m(s)===null}),I=qt(P,1,"pill svelte-x5aqew",null,I,{active:m(s)==="info"}),$=qt(T,1,"pill svelte-x5aqew",null,$,{active:m(s)==="warn"}),W=qt(L,1,"pill svelte-x5aqew",null,W,{active:m(s)==="error"})}),Ne("click",M,U=>{U.stopPropagation(),F(s,null)}),Ne("click",P,U=>{U.stopPropagation(),F(s,"info")}),Ne("click",T,U=>{U.stopPropagation(),F(s,"warn")}),Ne("click",L,U=>{U.stopPropagation(),F(s,"error")}),R(k,C)};ue(b,k=>{m(a)||k(_)})}var x=D(b,2);let w;var A=D(g,2);{var E=k=>{var C=jY();gt(C,21,()=>m(o),bt,(M,N,P)=>{var I=zY();let T;var $=S(I),L=S($),W=S(L),U=D(L,2),O=S(U),H=D(U,2),G=S(H),J=D($,2);{var ce=xe=>{var be=BY(),Le=S(be);me(()=>ae(Le,m(N).text)),R(xe,be)};ue(J,xe=>{m(i)[P]&&m(N).text&&xe(ce)})}me(()=>{T=qt(I,1,"alert-item svelte-x5aqew",null,T,{expanded:m(i)[P]}),ae(W,r[m(N).level]||""),ae(O,m(N).title),ae(G,m(N).meta||"")}),Ne("click",$,()=>l(P)),R(M,I)}),R(k,C)};ue(A,k=>{m(a)||k(E)})}me(()=>{p=qt(h,1,"alert-panel svelte-x5aqew",null,p,{collapsed:m(a)}),ae(y,`Alerts (${n().length??""})`),w=qt(x,0,"collapse-icon svelte-x5aqew",null,w,{rotated:m(a)})}),Ne("click",g,()=>F(a,!m(a))),Ne("keydown",g,k=>k.key==="Enter"&&F(a,!m(a))),R(d,h)};ue(c,d=>{n().length>0&&d(f)})}R(e,u),un()}or(["click","keydown"]);function HR(){return window.__trackio_base||""}function WY(e){const t=HR();return t&&e.startsWith(t)?e.slice(t.length)||"/":e}function CF(){const t=WY(window.location.pathname).replace(/\/+$/,"")||"/";switch(t==="/"?"":t.replace(/^\//,"").split("/")[0]){case"":case"metrics":return"metrics";case"system":return"system";case"traces":return"traces";case"media":return"media";case"reports":return"reports";case"runs":return"runs";case"run":return"run-detail";case"files":return"files";case"artifacts":return"artifacts";case"settings":return"settings";default:return"metrics"}}function mg(e){const t=new URLSearchParams(window.location.search),n={metrics:"/",traces:"/traces",system:"/system",media:"/media",reports:"/reports",runs:"/runs","run-detail":"/run",files:"/files",artifacts:"/artifacts",settings:"/settings"},r=HR()+(n[e]||"/"),i=t.toString(),s=i?`${r}?${i}`:r;window.history.pushState({},"",s),window.dispatchEvent(new PopStateEvent("popstate"))}function er(e){return new URLSearchParams(window.location.search).get(e)}function GR(e,t){H1("selected_artifact",e),H1("selected_version",`v${t}`)}function YR(){const e=er("selected_artifact"),t=er("selected_version"),n=t?parseInt(String(t).replace(/^v/i,""),10):NaN;return{name:e,version:Number.isNaN(n)?null:n}}function Rw(e,t){H1("selected_run_id",t),H1("selected_run",e),mg("run-detail")}function H1(e,t){const n=new URLSearchParams(window.location.search);t!=null&&t!==""?n.set(e,t):n.delete(e);const r=n.toString(),i=r?`${window.location.pathname}?${r}`:window.location.pathname;window.history.replaceState({},"",i)}const HY=/("(?:[^\\"]|\\.)*")|[:,]/g;function g_(e,t={}){const n=JSON.stringify([1],void 0,t.indent===void 0?2:t.indent).slice(2,-3),r=n===""?1/0:t.maxLength===void 0?80:t.maxLength;let{replacer:i}=t;return(function s(a,o,l){a&&typeof a.toJSON=="function"&&(a=a.toJSON());const u=JSON.stringify(a,i);if(u===void 0)return u;const c=r-o.length-l;if(u.length<=c){const f=u.replace(HY,(d,h)=>h||`${d} `);if(f.length<=c)return f}if(i!=null&&(a=JSON.parse(u),i=void 0),typeof a=="object"&&a!==null){const f=o+n,d=[];let h=0,p,g;if(Array.isArray(a)){p="[",g="]";const{length:v}=a;for(;h0)return[p,n+d.join(`, +${f}`),g].join(` +${o}`)}return u})(e,"",0)}function Wi(e,t,n){return e.fields=t||[],e.fname=n,e}function zn(e){return e==null?null:e.fname}function Vr(e){return e==null?null:e.fields}function VR(e){return e.length===1?GY(e[0]):YY(e)}const GY=e=>function(t){return t[e]},YY=e=>{const t=e.length;return function(n){for(let r=0;ra?u():a=o+1:l==="["?(o>a&&u(),i=a=o+1):l==="]"&&(i||ye("Access path missing open bracket: "+e),i>0&&u(),i=0,a=o+1)}return i&&ye("Access path missing closing bracket: "+e),r&&ye("Access path missing closing quote: "+e),o>a&&(o++,u()),t}function Ns(e,t,n){const r=go(e);return e=r.length===1?r[0]:e,Wi((n&&n.get||VR)(r),[e],t||e)}const l0=Ns("id"),ei=Wi(e=>e,[],"identity"),Rl=Wi(()=>0,[],"zero"),vh=Wi(()=>1,[],"one"),ls=Wi(()=>!0,[],"true"),kl=Wi(()=>!1,[],"false"),Ek=new Set(Object.getOwnPropertyNames(Object.prototype));function VY(e,t,n){const r=[t].concat([].slice.call(n));console[e].apply(console,r)}const XR=0,Ak=1,kk=2,KR=3,ZR=4;function Sk(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:VY,r=e||XR;return{level(i){return arguments.length?(r=+i,this):r},error(){return r>=Ak&&n(t||"error","ERROR",arguments),this},warn(){return r>=kk&&n(t||"warn","WARN",arguments),this},info(){return r>=KR&&n(t||"log","INFO",arguments),this},debug(){return r>=ZR&&n(t||"log","DEBUG",arguments),this}}}var Se=Array.isArray;function Ue(e){return e===Object(e)}const $F=e=>e!=="__proto__";function yh(){for(var e=arguments.length,t=new Array(e),n=0;n{for(const s in i)if(s==="signals")r.signals=XY(r.signals,i.signals);else{const a=s==="legend"?{layout:1}:s==="style"?!0:null;bh(r,s,i[s],a)}return r},{})}function bh(e,t,n,r){if(!$F(t))return;let i,s;if(Ue(n)&&!Se(n)){s=Ue(e[t])?e[t]:e[t]={};for(i in n)r&&(r===!0||r[i])?bh(s,i,n[i]):$F(i)&&(s[i]=n[i])}else e[t]=n}function XY(e,t){if(e==null)return t;const n={},r=[];function i(s){n[s.name]||(n[s.name]=1,r.push(s))}return t.forEach(i),e.forEach(i),r}function Xt(e){return e[e.length-1]}function Gr(e){return e==null||e===""?null:+e}const JR=e=>t=>e*Math.exp(t),QR=e=>t=>Math.log(e*t),eN=e=>t=>Math.sign(t)*Math.log1p(Math.abs(t/e)),tN=e=>t=>Math.sign(t)*Math.expm1(Math.abs(t))*e,G1=e=>t=>t<0?-Math.pow(-t,e):Math.pow(t,e);function Py(e,t,n,r){const i=n(e[0]),s=n(Xt(e)),a=(s-i)*t;return[r(i-a),r(s-a)]}function nN(e,t){return Py(e,t,Gr,ei)}function rN(e,t){var n=Math.sign(e[0]);return Py(e,t,QR(n),JR(n))}function iN(e,t,n){return Py(e,t,G1(n),G1(1/n))}function sN(e,t,n){return Py(e,t,eN(n),tN(n))}function By(e,t,n,r,i){const s=r(e[0]),a=r(Xt(e)),o=t!=null?r(t):(s+a)/2;return[i(o+(s-o)*n),i(o+(a-o)*n)]}function Ck(e,t,n){return By(e,t,n,Gr,ei)}function $k(e,t,n){const r=Math.sign(e[0]);return By(e,t,n,QR(r),JR(r))}function Y1(e,t,n,r){return By(e,t,n,G1(r),G1(1/r))}function Fk(e,t,n,r){return By(e,t,n,eN(r),tN(r))}function aN(e){return 1+~~(new Date(e).getMonth()/3)}function oN(e){return 1+~~(new Date(e).getUTCMonth()/3)}function He(e){return e!=null?Se(e)?e:[e]:[]}function lN(e,t,n){let r=e[0],i=e[1],s;return i=n-t?[t,n]:[r=Math.min(Math.max(r,t),n-s),r+s]}function Rt(e){return typeof e=="function"}const KY="descending";function Dk(e,t,n){n=n||{},t=He(t)||[];const r=[],i=[],s={},a=n.comparator||ZY;return He(e).forEach((o,l)=>{o!=null&&(r.push(t[l]===KY?-1:1),i.push(o=Rt(o)?o:Ns(o,null,n)),(Vr(o)||[]).forEach(u=>s[u]=1))}),i.length===0?null:Wi(a(i,r),Object.keys(s))}const _h=(e,t)=>(et||t==null)&&e!=null?1:(t=t instanceof Date?+t:t,(e=e instanceof Date?+e:e)!==e&&t===t?-1:t!==t&&e===e?1:0),ZY=(e,t)=>e.length===1?JY(e[0],t[0]):QY(e,t,e.length),JY=(e,t)=>function(n,r){return _h(e(n),e(r))*t},QY=(e,t,n)=>(t.push(0),function(r,i){let s,a=0,o=-1;for(;a===0&&++oe}function Mk(e,t){let n;return r=>{n&&clearTimeout(n),n=setTimeout(()=>(t(r),n=null),e)}}function Tt(e){for(let t,n,r=1,i=arguments.length;ra&&(a=i))}else{for(i=t(e[n]);na&&(a=i))}return[s,a]}function uN(e,t){const n=e.length;let r=-1,i,s,a,o,l;if(t==null){for(;++r=s){i=a=s;break}if(r===n)return[-1,-1];for(o=l=r;++rs&&(i=s,o=r),a=s){i=a=s;break}if(r===n)return[-1,-1];for(o=l=r;++rs&&(i=s,o=r),a{i.set(s,e[s])}),i}function cN(e,t,n,r,i,s){if(!n&&n!==0)return s;const a=+n;let o=e[0],l=Xt(e),u;ls&&(a=i,i=s,s=a),n=n===void 0||n,r=r===void 0||r,(n?i<=e:io.replace(/\\(.)/g,"$1")):He(e));const r=e&&e.length,i=n&&n.get||VR,s=o=>i(t?[o]:go(o));let a;if(!r)a=function(){return""};else if(r===1){const o=s(e[0]);a=function(l){return""+o(l)}}else{const o=e.map(s);a=function(l){let u=""+o[0](l),c=0;for(;++c{t={},n={},r=0},s=(a,o)=>(++r>e&&(n=t,t={},r=1),t[a]=o);return i(),{clear:i,has:a=>Ve(t,a)||Ve(n,a),get:a=>Ve(t,a)?t[a]:Ve(n,a)?s(a,n[a]):void 0,set:(a,o)=>Ve(t,a)?t[a]=o:s(a,o)}}function pN(e,t,n,r){const i=t.length,s=n.length;if(!s)return t;if(!i)return n;const a=r||new t.constructor(i+s);let o=0,l=0,u=0;for(;o0?n[l++]:t[o++];for(;o=0;)n+=e;return n}function gN(e,t,n,r){const i=n||" ",s=e+"",a=t-s.length;return a<=0?s:r==="left"?wp(i,a)+s:r==="center"?wp(i,~~(a/2))+s+wp(i,Math.ceil(a/2)):s+wp(i,a)}function u0(e){return e&&Xt(e)-e[0]||0}function Pe(e){return Se(e)?"["+e.map(Pe)+"]":Ue(e)||We(e)?JSON.stringify(e).replace("\u2028","\\u2028").replace("\u2029","\\u2029"):e}function Nk(e){return e==null||e===""?null:!e||e==="false"||e==="0"?!1:!!e}const tV=e=>Qt(e)||Xl(e)?e:Date.parse(e);function Ok(e,t){return t=t||tV,e==null||e===""?null:t(e)}function Lk(e){return e==null||e===""?null:e+""}function da(e){const t={},n=e.length;for(let r=0;r9999?"+"+ki(e,6):ki(e,4)}function iV(e){var t=e.getUTCHours(),n=e.getUTCMinutes(),r=e.getUTCSeconds(),i=e.getUTCMilliseconds();return isNaN(e)?"Invalid Date":rV(e.getUTCFullYear())+"-"+ki(e.getUTCMonth()+1,2)+"-"+ki(e.getUTCDate(),2)+(i?"T"+ki(t,2)+":"+ki(n,2)+":"+ki(r,2)+"."+ki(i,3)+"Z":r?"T"+ki(t,2)+":"+ki(n,2)+":"+ki(r,2)+"Z":n||t?"T"+ki(t,2)+":"+ki(n,2)+"Z":"")}function sV(e){var t=new RegExp('["'+e+` +\r]`),n=e.charCodeAt(0);function r(f,d){var h,p,g=i(f,function(v,y){if(h)return h(v,y-1);p=v,h=d?nV(v,d):vN(v)});return g.columns=p||[],g}function i(f,d){var h=[],p=f.length,g=0,v=0,y,b=p<=0,_=!1;f.charCodeAt(p-1)===Kh&&--p,f.charCodeAt(p-1)===y_&&--p;function x(){if(b)return m_;if(_)return _=!1,FF;var A,E=g,k;if(f.charCodeAt(E)===v_){for(;g++=p?b=!0:(k=f.charCodeAt(g++))===Kh?_=!0:k===y_&&(_=!0,f.charCodeAt(g)===Kh&&++g),f.slice(E+1,A-1).replace(/""/g,'"')}for(;g1)r=hV(e,t,n);else for(i=0,r=new Array(s=e.arcs.length);it?1:e>=t?0:NaN}function pV(e,t){return e==null||t==null?NaN:te?1:t>=e?0:NaN}function wh(e){let t,n,r;e.length!==2?(t=Zo,n=(o,l)=>Zo(e(o),l),r=(o,l)=>e(o)-l):(t=e===Zo||e===pV?e:gV,n=e,r=e);function i(o,l,u=0,c=o.length){if(u>>1;n(o[f],l)<0?u=f+1:c=f}while(u>>1;n(o[f],l)<=0?u=f+1:c=f}while(uu&&r(o[f-1],l)>-r(o[f],l)?f-1:f}return{left:i,center:a,right:s}}function gV(){return 0}function bN(e){return e===null?NaN:+e}function*mV(e,t){if(t===void 0)for(let n of e)n!=null&&(n=+n)>=n&&(yield n);else{let n=-1;for(let r of e)(r=t(r,++n,e))!=null&&(r=+r)>=r&&(yield r)}}const _N=wh(Zo),ru=_N.right,vV=_N.left;wh(bN).center;function yV(e,t){let n=0,r,i=0,s=0;if(t===void 0)for(let a of e)a!=null&&(a=+a)>=a&&(r=a-i,i+=r/++n,s+=r*(a-i));else{let a=-1;for(let o of e)(o=t(o,++a,e))!=null&&(o=+o)>=o&&(r=o-i,i+=r/++n,s+=r*(o-i))}if(n>1)return s/(n-1)}function bV(e,t){const n=yV(e,t);return n&&Math.sqrt(n)}class gi{constructor(){this._partials=new Float64Array(32),this._n=0}add(t){const n=this._partials;let r=0;for(let i=0;i0){for(a=t[--n];n>0&&(r=a,i=t[--n],a=r+i,s=i-(a-r),!s););n>0&&(s<0&&t[n-1]<0||s>0&&t[n-1]>0)&&(i=s*2,r=a+i,i==r-a&&(a=r))}return a}}class TF extends Map{constructor(t,n=EN){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),t!=null)for(const[r,i]of t)this.set(r,i)}get(t){return super.get(Nw(this,t))}has(t){return super.has(Nw(this,t))}set(t,n){return super.set(xN(this,t),n)}delete(t){return super.delete(wN(this,t))}}class V1 extends Set{constructor(t,n=EN){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),t!=null)for(const r of t)this.add(r)}has(t){return super.has(Nw(this,t))}add(t){return super.add(xN(this,t))}delete(t){return super.delete(wN(this,t))}}function Nw({_intern:e,_key:t},n){const r=t(n);return e.has(r)?e.get(r):n}function xN({_intern:e,_key:t},n){const r=t(n);return e.has(r)?e.get(r):(e.set(r,n),n)}function wN({_intern:e,_key:t},n){const r=t(n);return e.has(r)&&(n=e.get(r),e.delete(r)),n}function EN(e){return e!==null&&typeof e=="object"?e.valueOf():e}function _V(e,t){return Array.from(t,n=>e[n])}function xV(e=Zo){if(e===Zo)return AN;if(typeof e!="function")throw new TypeError("compare is not a function");return(t,n)=>{const r=e(t,n);return r||r===0?r:(e(n,n)===0)-(e(t,t)===0)}}function AN(e,t){return(e==null||!(e>=e))-(t==null||!(t>=t))||(et?1:0)}const wV=Math.sqrt(50),EV=Math.sqrt(10),AV=Math.sqrt(2);function X1(e,t,n){const r=(t-e)/Math.max(0,n),i=Math.floor(Math.log10(r)),s=r/Math.pow(10,i),a=s>=wV?10:s>=EV?5:s>=AV?2:1;let o,l,u;return i<0?(u=Math.pow(10,-i)/a,o=Math.round(e*u),l=Math.round(t*u),o/ut&&--l,u=-u):(u=Math.pow(10,i)*a,o=Math.round(e/u),l=Math.round(t/u),o*ut&&--l),l0))return[];if(e===t)return[e];const r=t=i))return[];const o=s-i+1,l=new Array(o);if(r)if(a<0)for(let u=0;u=r)&&(n=r);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n=i)&&(n=i)}return n}function Iw(e,t){let n;if(t===void 0)for(const r of e)r!=null&&(n>r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function kN(e,t,n=0,r=1/0,i){if(t=Math.floor(t),n=Math.floor(Math.max(0,n)),r=Math.floor(Math.min(e.length-1,r)),!(n<=t&&t<=r))return e;for(i=i===void 0?AN:xV(i);r>n;){if(r-n>600){const l=r-n+1,u=t-n+1,c=Math.log(l),f=.5*Math.exp(2*c/3),d=.5*Math.sqrt(c*f*(l-f)/l)*(u-l/2<0?-1:1),h=Math.max(n,Math.floor(t-u*f/l+d)),p=Math.min(r,Math.floor(t+(l-u)*f/l+d));kN(e,t,h,p,i)}const s=e[t];let a=n,o=r;for(Zh(e,n,t),i(e[r],s)>0&&Zh(e,n,r);a0;)--o}i(e[n],s)===0?Zh(e,n,o):(++o,Zh(e,o,r)),o<=t&&(n=o+1),t<=o&&(r=o-1)}return e}function Zh(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}function Pw(e,t,n){if(e=Float64Array.from(mV(e,n)),!(!(r=e.length)||isNaN(t=+t))){if(t<=0||r<2)return Iw(e);if(t>=1)return wc(e);var r,i=(r-1)*t,s=Math.floor(i),a=wc(kN(e,s).subarray(0,s+1)),o=Iw(e.subarray(s+1));return a+(o-a)*(i-s)}}function SN(e,t,n=bN){if(!(!(r=e.length)||isNaN(t=+t))){if(t<=0||r<2)return+n(e[0],0,e);if(t>=1)return+n(e[r-1],r-1,e);var r,i=(r-1)*t,s=Math.floor(i),a=+n(e[s],s,e),o=+n(e[s+1],s+1,e);return a+(o-a)*(i-s)}}function kV(e,t){let n=0,r=0;if(t===void 0)for(let i of e)i!=null&&(i=+i)>=i&&(++n,r+=i);else{let i=-1;for(let s of e)(s=t(s,++i,e))!=null&&(s=+s)>=s&&(++n,r+=s)}if(n)return r/n}function CN(e,t){return Pw(e,.5,t)}function*SV(e){for(const t of e)yield*t}function $N(e){return Array.from(SV(e))}function ts(e,t,n){e=+e,t=+t,n=(i=arguments.length)<2?(t=e,e=0,1):i<3?1:+n;for(var r=-1,i=Math.max(0,Math.ceil((t-e)/n))|0,s=new Array(i);++r=1e21?e.toLocaleString("en").replace(/,/g,""):e.toString(10)}function K1(e,t){if(!isFinite(e)||e===0)return null;var n=(e=t?e.toExponential(t-1):e.toExponential()).indexOf("e"),r=e.slice(0,n);return[r.length>1?r[0]+r.slice(2):r,+e.slice(n+1)]}function Td(e){return e=K1(Math.abs(e)),e?e[1]:NaN}function MV(e,t){return function(n,r){for(var i=n.length,s=[],a=0,o=e[0],l=0;i>0&&o>0&&(l+o+1>r&&(o=Math.max(1,r-l)),s.push(n.substring(i-=o,i+o)),!((l+=o+1)>r));)o=e[a=(a+1)%e.length];return s.reverse().join(t)}}function TV(e){return function(t){return t.replace(/[0-9]/g,function(n){return e[+n]})}}var RV=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function zc(e){if(!(t=RV.exec(e)))throw new Error("invalid format: "+e);var t;return new Ik({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}zc.prototype=Ik.prototype;function Ik(e){this.fill=e.fill===void 0?" ":e.fill+"",this.align=e.align===void 0?">":e.align+"",this.sign=e.sign===void 0?"-":e.sign+"",this.symbol=e.symbol===void 0?"":e.symbol+"",this.zero=!!e.zero,this.width=e.width===void 0?void 0:+e.width,this.comma=!!e.comma,this.precision=e.precision===void 0?void 0:+e.precision,this.trim=!!e.trim,this.type=e.type===void 0?"":e.type+""}Ik.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function NV(e){e:for(var t=e.length,n=1,r=-1,i;n0&&(r=0);break}return r>0?e.slice(0,r)+e.slice(i+1):e}var Z1;function OV(e,t){var n=K1(e,t);if(!n)return Z1=void 0,e.toPrecision(t);var r=n[0],i=n[1],s=i-(Z1=Math.max(-8,Math.min(8,Math.floor(i/3)))*3)+1,a=r.length;return s===a?r:s>a?r+new Array(s-a+1).join("0"):s>0?r.slice(0,s)+"."+r.slice(s):"0."+new Array(1-s).join("0")+K1(e,Math.max(0,t+s-1))[0]}function RF(e,t){var n=K1(e,t);if(!n)return e+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}const NF={"%":(e,t)=>(e*100).toFixed(t),b:e=>Math.round(e).toString(2),c:e=>e+"",d:DV,e:(e,t)=>e.toExponential(t),f:(e,t)=>e.toFixed(t),g:(e,t)=>e.toPrecision(t),o:e=>Math.round(e).toString(8),p:(e,t)=>RF(e*100,t),r:RF,s:OV,X:e=>Math.round(e).toString(16).toUpperCase(),x:e=>Math.round(e).toString(16)};function OF(e){return e}var LF=Array.prototype.map,IF=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function DN(e){var t=e.grouping===void 0||e.thousands===void 0?OF:MV(LF.call(e.grouping,Number),e.thousands+""),n=e.currency===void 0?"":e.currency[0]+"",r=e.currency===void 0?"":e.currency[1]+"",i=e.decimal===void 0?".":e.decimal+"",s=e.numerals===void 0?OF:TV(LF.call(e.numerals,String)),a=e.percent===void 0?"%":e.percent+"",o=e.minus===void 0?"−":e.minus+"",l=e.nan===void 0?"NaN":e.nan+"";function u(f,d){f=zc(f);var h=f.fill,p=f.align,g=f.sign,v=f.symbol,y=f.zero,b=f.width,_=f.comma,x=f.precision,w=f.trim,A=f.type;A==="n"?(_=!0,A="g"):NF[A]||(x===void 0&&(x=12),w=!0,A="g"),(y||h==="0"&&p==="=")&&(y=!0,h="0",p="=");var E=(d&&d.prefix!==void 0?d.prefix:"")+(v==="$"?n:v==="#"&&/[boxX]/.test(A)?"0"+A.toLowerCase():""),k=(v==="$"?r:/[%p]/.test(A)?a:"")+(d&&d.suffix!==void 0?d.suffix:""),C=NF[A],M=/[defgprs%]/.test(A);x=x===void 0?6:/[gprs]/.test(A)?Math.max(1,Math.min(21,x)):Math.max(0,Math.min(20,x));function N(P){var I=E,T=k,$,L,W;if(A==="c")T=C(P)+T,P="";else{P=+P;var U=P<0||1/P<0;if(P=isNaN(P)?l:C(Math.abs(P),x),w&&(P=NV(P)),U&&+P==0&&g!=="+"&&(U=!1),I=(U?g==="("?g:o:g==="-"||g==="("?"":g)+I,T=(A==="s"&&!isNaN(P)&&Z1!==void 0?IF[8+Z1/3]:"")+T+(U&&g==="("?")":""),M){for($=-1,L=P.length;++$W||W>57){T=(W===46?i+P.slice($+1):P.slice($))+T,P=P.slice(0,$);break}}}_&&!y&&(P=t(P,1/0));var O=I.length+P.length+T.length,H=O>1)+I+P+T+H.slice(O);break;default:P=H+I+P+T;break}return s(P)}return N.toString=function(){return f+""},N}function c(f,d){var h=Math.max(-8,Math.min(8,Math.floor(Td(d)/3)))*3,p=Math.pow(10,-h),g=u((f=zc(f),f.type="f",f),{suffix:IF[8+h/3]});return function(v){return g(p*v)}}return{format:u,formatPrefix:c}}var fm,zy,Pk;LV({thousands:",",grouping:[3],currency:["$",""]});function LV(e){return fm=DN(e),zy=fm.format,Pk=fm.formatPrefix,fm}function MN(e){return Math.max(0,-Td(Math.abs(e)))}function TN(e,t){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(Td(t)/3)))*3-Td(Math.abs(e)))}function RN(e,t){return e=Math.abs(e),t=Math.abs(t)-e,Math.max(0,Td(t)-Td(e))+1}const b_=new Date,__=new Date;function lr(e,t,n,r){function i(s){return e(s=arguments.length===0?new Date:new Date(+s)),s}return i.floor=s=>(e(s=new Date(+s)),s),i.ceil=s=>(e(s=new Date(s-1)),t(s,1),e(s),s),i.round=s=>{const a=i(s),o=i.ceil(s);return s-a(t(s=new Date(+s),a==null?1:Math.floor(a)),s),i.range=(s,a,o)=>{const l=[];if(s=i.ceil(s),o=o==null?1:Math.floor(o),!(s0))return l;let u;do l.push(u=new Date(+s)),t(s,o),e(s);while(ulr(a=>{if(a>=a)for(;e(a),!s(a);)a.setTime(a-1)},(a,o)=>{if(a>=a)if(o<0)for(;++o<=0;)for(;t(a,-1),!s(a););else for(;--o>=0;)for(;t(a,1),!s(a););}),n&&(i.count=(s,a)=>(b_.setTime(+s),__.setTime(+a),e(b_),e(__),Math.floor(n(b_,__))),i.every=s=>(s=Math.floor(s),!isFinite(s)||!(s>0)?null:s>1?i.filter(r?a=>r(a)%s===0:a=>i.count(0,a)%s===0):i)),i}const Rd=lr(()=>{},(e,t)=>{e.setTime(+e+t)},(e,t)=>t-e);Rd.every=e=>(e=Math.floor(e),!isFinite(e)||!(e>0)?null:e>1?lr(t=>{t.setTime(Math.floor(t/e)*e)},(t,n)=>{t.setTime(+t+n*e)},(t,n)=>(n-t)/e):Rd);Rd.range;const qo=1e3,Es=qo*60,Wo=Es*60,ol=Wo*24,Bk=ol*7,PF=ol*30,x_=ol*365,Ho=lr(e=>{e.setTime(e-e.getMilliseconds())},(e,t)=>{e.setTime(+e+t*qo)},(e,t)=>(t-e)/qo,e=>e.getUTCSeconds());Ho.range;const jy=lr(e=>{e.setTime(e-e.getMilliseconds()-e.getSeconds()*qo)},(e,t)=>{e.setTime(+e+t*Es)},(e,t)=>(t-e)/Es,e=>e.getMinutes());jy.range;const Uy=lr(e=>{e.setUTCSeconds(0,0)},(e,t)=>{e.setTime(+e+t*Es)},(e,t)=>(t-e)/Es,e=>e.getUTCMinutes());Uy.range;const qy=lr(e=>{e.setTime(e-e.getMilliseconds()-e.getSeconds()*qo-e.getMinutes()*Es)},(e,t)=>{e.setTime(+e+t*Wo)},(e,t)=>(t-e)/Wo,e=>e.getHours());qy.range;const Wy=lr(e=>{e.setUTCMinutes(0,0,0)},(e,t)=>{e.setTime(+e+t*Wo)},(e,t)=>(t-e)/Wo,e=>e.getUTCHours());Wy.range;const Jo=lr(e=>e.setHours(0,0,0,0),(e,t)=>e.setDate(e.getDate()+t),(e,t)=>(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*Es)/ol,e=>e.getDate()-1);Jo.range;const Kl=lr(e=>{e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCDate(e.getUTCDate()+t)},(e,t)=>(t-e)/ol,e=>e.getUTCDate()-1);Kl.range;const NN=lr(e=>{e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCDate(e.getUTCDate()+t)},(e,t)=>(t-e)/ol,e=>Math.floor(e/ol));NN.range;function hf(e){return lr(t=>{t.setDate(t.getDate()-(t.getDay()+7-e)%7),t.setHours(0,0,0,0)},(t,n)=>{t.setDate(t.getDate()+n*7)},(t,n)=>(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Es)/Bk)}const Eh=hf(0),J1=hf(1),IV=hf(2),PV=hf(3),Nd=hf(4),BV=hf(5),zV=hf(6);Eh.range;J1.range;IV.range;PV.range;Nd.range;BV.range;zV.range;function pf(e){return lr(t=>{t.setUTCDate(t.getUTCDate()-(t.getUTCDay()+7-e)%7),t.setUTCHours(0,0,0,0)},(t,n)=>{t.setUTCDate(t.getUTCDate()+n*7)},(t,n)=>(n-t)/Bk)}const Ah=pf(0),Q1=pf(1),jV=pf(2),UV=pf(3),Od=pf(4),qV=pf(5),WV=pf(6);Ah.range;Q1.range;jV.range;UV.range;Od.range;qV.range;WV.range;const vg=lr(e=>{e.setDate(1),e.setHours(0,0,0,0)},(e,t)=>{e.setMonth(e.getMonth()+t)},(e,t)=>t.getMonth()-e.getMonth()+(t.getFullYear()-e.getFullYear())*12,e=>e.getMonth());vg.range;const yg=lr(e=>{e.setUTCDate(1),e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCMonth(e.getUTCMonth()+t)},(e,t)=>t.getUTCMonth()-e.getUTCMonth()+(t.getUTCFullYear()-e.getUTCFullYear())*12,e=>e.getUTCMonth());yg.range;const so=lr(e=>{e.setMonth(0,1),e.setHours(0,0,0,0)},(e,t)=>{e.setFullYear(e.getFullYear()+t)},(e,t)=>t.getFullYear()-e.getFullYear(),e=>e.getFullYear());so.every=e=>!isFinite(e=Math.floor(e))||!(e>0)?null:lr(t=>{t.setFullYear(Math.floor(t.getFullYear()/e)*e),t.setMonth(0,1),t.setHours(0,0,0,0)},(t,n)=>{t.setFullYear(t.getFullYear()+n*e)});so.range;const ao=lr(e=>{e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCFullYear(e.getUTCFullYear()+t)},(e,t)=>t.getUTCFullYear()-e.getUTCFullYear(),e=>e.getUTCFullYear());ao.every=e=>!isFinite(e=Math.floor(e))||!(e>0)?null:lr(t=>{t.setUTCFullYear(Math.floor(t.getUTCFullYear()/e)*e),t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,n)=>{t.setUTCFullYear(t.getUTCFullYear()+n*e)});ao.range;function ON(e,t,n,r,i,s){const a=[[Ho,1,qo],[Ho,5,5*qo],[Ho,15,15*qo],[Ho,30,30*qo],[s,1,Es],[s,5,5*Es],[s,15,15*Es],[s,30,30*Es],[i,1,Wo],[i,3,3*Wo],[i,6,6*Wo],[i,12,12*Wo],[r,1,ol],[r,2,2*ol],[n,1,Bk],[t,1,PF],[t,3,3*PF],[e,1,x_]];function o(u,c,f){const d=cv).right(a,d);if(h===a.length)return e.every(iu(u/x_,c/x_,f));if(h===0)return Rd.every(Math.max(iu(u,c,f),1));const[p,g]=a[d/a[h-1][2](e[t]=1+n,e),{});function jk(e){const t=He(e).slice(),n={};return t.length||ye("Missing time unit."),t.forEach(i=>{Ve(w_,i)?n[i]=1:ye(`Invalid time unit: ${i}.`)}),(n[rr]||n[Hr]?1:0)+(n[Pi]||n[Xr]||n[Bi]?1:0)+(n[oo]?1:0)>1&&ye(`Incompatible time units: ${e}`),t.sort((i,s)=>w_[i]-w_[s]),t}const XV={[Or]:"%Y ",[Pi]:"Q%q ",[Xr]:"%b ",[Bi]:"%d ",[rr]:"W%U ",[Hr]:"%a ",[oo]:"%j ",[us]:"%H:00",[cs]:"00:%M",[Os]:":%S",[ha]:".%L",[`${Or}-${Xr}`]:"%Y-%m ",[`${Or}-${Xr}-${Bi}`]:"%Y-%m-%d ",[`${us}-${cs}`]:"%H:%M"};function LN(e,t){const n=Tt({},XV,t),r=jk(e),i=r.length;let s="",a=0,o,l;for(a=0;aa;--o)if(l=r.slice(a,o).join("-"),n[l]!=null){s+=n[l],a=o;break}return s.trim()}const rc=new Date;function Uk(e){return rc.setFullYear(e),rc.setMonth(0),rc.setDate(1),rc.setHours(0,0,0,0),rc}function IN(e){return BN(new Date(e))}function PN(e){return Bw(new Date(e))}function BN(e){return Jo.count(Uk(e.getFullYear())-1,e)}function Bw(e){return Eh.count(Uk(e.getFullYear())-1,e)}function zw(e){return Uk(e).getDay()}function KV(e,t,n,r,i,s,a){if(0<=e&&e<100){const o=new Date(-1,t,n,r,i,s,a);return o.setFullYear(e),o}return new Date(e,t,n,r,i,s,a)}function zN(e){return UN(new Date(e))}function jN(e){return jw(new Date(e))}function UN(e){const t=Date.UTC(e.getUTCFullYear(),0,1);return Kl.count(t-1,e)}function jw(e){const t=Date.UTC(e.getUTCFullYear(),0,1);return Ah.count(t-1,e)}function Uw(e){return rc.setTime(Date.UTC(e,0,1)),rc.getUTCDay()}function ZV(e,t,n,r,i,s,a){if(0<=e&&e<100){const o=new Date(Date.UTC(-1,t,n,r,i,s,a));return o.setUTCFullYear(n.y),o}return new Date(Date.UTC(e,t,n,r,i,s,a))}function qN(e,t,n,r,i){const s=t||1,a=Xt(e),o=(y,b,_)=>(_=_||y,JV(n[_],r[_],y===a&&s,b)),l=new Date,u=da(e),c=u[Or]?o(Or):ti(2012),f=u[Xr]?o(Xr):u[Pi]?o(Pi):Rl,d=u[rr]&&u[Hr]?o(Hr,1,rr+Hr):u[rr]?o(rr,1):u[Hr]?o(Hr,1):u[Bi]?o(Bi,1):u[oo]?o(oo,1):vh,h=u[us]?o(us):Rl,p=u[cs]?o(cs):Rl,g=u[Os]?o(Os):Rl,v=u[ha]?o(ha):Rl;return function(y){l.setTime(+y);const b=c(l);return i(b,f(l),d(l,b),h(l),p(l),g(l),v(l))}}function JV(e,t,n,r){const i=n<=1?e:r?(s,a)=>r+n*Math.floor((e(s,a)-r)/n):(s,a)=>n*Math.floor(e(s,a)/n);return t?(s,a)=>t(i(s,a),a):i}function Ld(e,t,n){return t+e*7-(n+6)%7}const QV={[Or]:e=>e.getFullYear(),[Pi]:e=>Math.floor(e.getMonth()/3),[Xr]:e=>e.getMonth(),[Bi]:e=>e.getDate(),[us]:e=>e.getHours(),[cs]:e=>e.getMinutes(),[Os]:e=>e.getSeconds(),[ha]:e=>e.getMilliseconds(),[oo]:e=>BN(e),[rr]:e=>Bw(e),[rr+Hr]:(e,t)=>Ld(Bw(e),e.getDay(),zw(t)),[Hr]:(e,t)=>Ld(1,e.getDay(),zw(t))},eX={[Pi]:e=>3*e,[rr]:(e,t)=>Ld(e,0,zw(t))};function WN(e,t){return qN(e,t||1,QV,eX,KV)}const tX={[Or]:e=>e.getUTCFullYear(),[Pi]:e=>Math.floor(e.getUTCMonth()/3),[Xr]:e=>e.getUTCMonth(),[Bi]:e=>e.getUTCDate(),[us]:e=>e.getUTCHours(),[cs]:e=>e.getUTCMinutes(),[Os]:e=>e.getUTCSeconds(),[ha]:e=>e.getUTCMilliseconds(),[oo]:e=>UN(e),[rr]:e=>jw(e),[Hr]:(e,t)=>Ld(1,e.getUTCDay(),Uw(t)),[rr+Hr]:(e,t)=>Ld(jw(e),e.getUTCDay(),Uw(t))},nX={[Pi]:e=>3*e,[rr]:(e,t)=>Ld(e,0,Uw(t))};function HN(e,t){return qN(e,t||1,tX,nX,ZV)}const rX={[Or]:so,[Pi]:vg.every(3),[Xr]:vg,[rr]:Eh,[Bi]:Jo,[Hr]:Jo,[oo]:Jo,[us]:qy,[cs]:jy,[Os]:Ho,[ha]:Rd},iX={[Or]:ao,[Pi]:yg.every(3),[Xr]:yg,[rr]:Ah,[Bi]:Kl,[Hr]:Kl,[oo]:Kl,[us]:Wy,[cs]:Uy,[Os]:Ho,[ha]:Rd};function kh(e){return rX[e]}function Sh(e){return iX[e]}function GN(e,t,n){return e?e.offset(t,n):void 0}function YN(e,t,n){return GN(kh(e),t,n)}function VN(e,t,n){return GN(Sh(e),t,n)}function XN(e,t,n,r){return e?e.range(t,n,r):void 0}function KN(e,t,n,r){return XN(kh(e),t,n,r)}function ZN(e,t,n,r){return XN(Sh(e),t,n,r)}const Ep=1e3,Ap=Ep*60,kp=Ap*60,Hy=kp*24,sX=Hy*7,BF=Hy*30,qw=Hy*365,JN=[Or,Xr,Bi,us,cs,Os,ha],Sp=JN.slice(0,-1),Cp=Sp.slice(0,-1),$p=Cp.slice(0,-1),aX=$p.slice(0,-1),oX=[Or,rr],zF=[Or,Xr],QN=[Or],Jh=[[Sp,1,Ep],[Sp,5,5*Ep],[Sp,15,15*Ep],[Sp,30,30*Ep],[Cp,1,Ap],[Cp,5,5*Ap],[Cp,15,15*Ap],[Cp,30,30*Ap],[$p,1,kp],[$p,3,3*kp],[$p,6,6*kp],[$p,12,12*kp],[aX,1,Hy],[oX,1,sX],[zF,1,BF],[zF,3,3*BF],[QN,1,qw]];function eO(e){const t=e.extent,n=e.maxbins||40,r=Math.abs(u0(t))/n;let i=wh(o=>o[2]).right(Jh,r),s,a;return i===Jh.length?(s=QN,a=iu(t[0]/qw,t[1]/qw,n)):i?(i=Jh[r/Jh[i-1][2]53)return null;"w"in V||(V.w=1),"Z"in V?(B=A_(Qh(V.y,0,1)),Q=B.getUTCDay(),B=Q>4||Q===0?Q1.ceil(B):Q1(B),B=Kl.offset(B,(V.V-1)*7),V.y=B.getUTCFullYear(),V.m=B.getUTCMonth(),V.d=B.getUTCDate()+(V.w+6)%7):(B=E_(Qh(V.y,0,1)),Q=B.getDay(),B=Q>4||Q===0?J1.ceil(B):J1(B),B=Jo.offset(B,(V.V-1)*7),V.y=B.getFullYear(),V.m=B.getMonth(),V.d=B.getDate()+(V.w+6)%7)}else("W"in V||"U"in V)&&("w"in V||(V.w="u"in V?V.u%7:"W"in V?1:0),Q="Z"in V?A_(Qh(V.y,0,1)).getUTCDay():E_(Qh(V.y,0,1)).getDay(),V.m=0,V.d="W"in V?(V.w+6)%7+V.W*7-(Q+5)%7:V.w+V.U*7-(Q+6)%7);return"Z"in V?(V.H+=V.Z/100|0,V.M+=V.Z%100,A_(V)):E_(V)}}function k(Y,Ce,le,V){for(var q=0,B=Ce.length,Q=le.length,X,j;q=Q)return-1;if(X=Ce.charCodeAt(q++),X===37){if(X=Ce.charAt(q++),j=w[X in jF?Ce.charAt(q++):X],!j||(V=j(Y,le,V))<0)return-1}else if(X!=le.charCodeAt(V++))return-1}return V}function C(Y,Ce,le){var V=u.exec(Ce.slice(le));return V?(Y.p=c.get(V[0].toLowerCase()),le+V[0].length):-1}function M(Y,Ce,le){var V=h.exec(Ce.slice(le));return V?(Y.w=p.get(V[0].toLowerCase()),le+V[0].length):-1}function N(Y,Ce,le){var V=f.exec(Ce.slice(le));return V?(Y.w=d.get(V[0].toLowerCase()),le+V[0].length):-1}function P(Y,Ce,le){var V=y.exec(Ce.slice(le));return V?(Y.m=b.get(V[0].toLowerCase()),le+V[0].length):-1}function I(Y,Ce,le){var V=g.exec(Ce.slice(le));return V?(Y.m=v.get(V[0].toLowerCase()),le+V[0].length):-1}function T(Y,Ce,le){return k(Y,t,Ce,le)}function $(Y,Ce,le){return k(Y,n,Ce,le)}function L(Y,Ce,le){return k(Y,r,Ce,le)}function W(Y){return a[Y.getDay()]}function U(Y){return s[Y.getDay()]}function O(Y){return l[Y.getMonth()]}function H(Y){return o[Y.getMonth()]}function G(Y){return i[+(Y.getHours()>=12)]}function J(Y){return 1+~~(Y.getMonth()/3)}function ce(Y){return a[Y.getUTCDay()]}function xe(Y){return s[Y.getUTCDay()]}function be(Y){return l[Y.getUTCMonth()]}function Le(Y){return o[Y.getUTCMonth()]}function tt(Y){return i[+(Y.getUTCHours()>=12)]}function he(Y){return 1+~~(Y.getUTCMonth()/3)}return{format:function(Y){var Ce=A(Y+="",_);return Ce.toString=function(){return Y},Ce},parse:function(Y){var Ce=E(Y+="",!1);return Ce.toString=function(){return Y},Ce},utcFormat:function(Y){var Ce=A(Y+="",x);return Ce.toString=function(){return Y},Ce},utcParse:function(Y){var Ce=E(Y+="",!0);return Ce.toString=function(){return Y},Ce}}}var jF={"-":"",_:" ",0:"0"},Ar=/^\s*\d+/,lX=/^%/,uX=/[\\^$*+?|[\]().{}]/g;function en(e,t,n){var r=e<0?"-":"",i=(r?-e:e)+"",s=i.length;return r+(s[t.toLowerCase(),n]))}function fX(e,t,n){var r=Ar.exec(t.slice(n,n+1));return r?(e.w=+r[0],n+r[0].length):-1}function dX(e,t,n){var r=Ar.exec(t.slice(n,n+1));return r?(e.u=+r[0],n+r[0].length):-1}function hX(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.U=+r[0],n+r[0].length):-1}function pX(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.V=+r[0],n+r[0].length):-1}function gX(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.W=+r[0],n+r[0].length):-1}function UF(e,t,n){var r=Ar.exec(t.slice(n,n+4));return r?(e.y=+r[0],n+r[0].length):-1}function qF(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function mX(e,t,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(t.slice(n,n+6));return r?(e.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function vX(e,t,n){var r=Ar.exec(t.slice(n,n+1));return r?(e.q=r[0]*3-3,n+r[0].length):-1}function yX(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.m=r[0]-1,n+r[0].length):-1}function WF(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.d=+r[0],n+r[0].length):-1}function bX(e,t,n){var r=Ar.exec(t.slice(n,n+3));return r?(e.m=0,e.d=+r[0],n+r[0].length):-1}function HF(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.H=+r[0],n+r[0].length):-1}function _X(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.M=+r[0],n+r[0].length):-1}function xX(e,t,n){var r=Ar.exec(t.slice(n,n+2));return r?(e.S=+r[0],n+r[0].length):-1}function wX(e,t,n){var r=Ar.exec(t.slice(n,n+3));return r?(e.L=+r[0],n+r[0].length):-1}function EX(e,t,n){var r=Ar.exec(t.slice(n,n+6));return r?(e.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function AX(e,t,n){var r=lX.exec(t.slice(n,n+1));return r?n+r[0].length:-1}function kX(e,t,n){var r=Ar.exec(t.slice(n));return r?(e.Q=+r[0],n+r[0].length):-1}function SX(e,t,n){var r=Ar.exec(t.slice(n));return r?(e.s=+r[0],n+r[0].length):-1}function GF(e,t){return en(e.getDate(),t,2)}function CX(e,t){return en(e.getHours(),t,2)}function $X(e,t){return en(e.getHours()%12||12,t,2)}function FX(e,t){return en(1+Jo.count(so(e),e),t,3)}function nO(e,t){return en(e.getMilliseconds(),t,3)}function DX(e,t){return nO(e,t)+"000"}function MX(e,t){return en(e.getMonth()+1,t,2)}function TX(e,t){return en(e.getMinutes(),t,2)}function RX(e,t){return en(e.getSeconds(),t,2)}function NX(e){var t=e.getDay();return t===0?7:t}function OX(e,t){return en(Eh.count(so(e)-1,e),t,2)}function rO(e){var t=e.getDay();return t>=4||t===0?Nd(e):Nd.ceil(e)}function LX(e,t){return e=rO(e),en(Nd.count(so(e),e)+(so(e).getDay()===4),t,2)}function IX(e){return e.getDay()}function PX(e,t){return en(J1.count(so(e)-1,e),t,2)}function BX(e,t){return en(e.getFullYear()%100,t,2)}function zX(e,t){return e=rO(e),en(e.getFullYear()%100,t,2)}function jX(e,t){return en(e.getFullYear()%1e4,t,4)}function UX(e,t){var n=e.getDay();return e=n>=4||n===0?Nd(e):Nd.ceil(e),en(e.getFullYear()%1e4,t,4)}function qX(e){var t=e.getTimezoneOffset();return(t>0?"-":(t*=-1,"+"))+en(t/60|0,"0",2)+en(t%60,"0",2)}function YF(e,t){return en(e.getUTCDate(),t,2)}function WX(e,t){return en(e.getUTCHours(),t,2)}function HX(e,t){return en(e.getUTCHours()%12||12,t,2)}function GX(e,t){return en(1+Kl.count(ao(e),e),t,3)}function iO(e,t){return en(e.getUTCMilliseconds(),t,3)}function YX(e,t){return iO(e,t)+"000"}function VX(e,t){return en(e.getUTCMonth()+1,t,2)}function XX(e,t){return en(e.getUTCMinutes(),t,2)}function KX(e,t){return en(e.getUTCSeconds(),t,2)}function ZX(e){var t=e.getUTCDay();return t===0?7:t}function JX(e,t){return en(Ah.count(ao(e)-1,e),t,2)}function sO(e){var t=e.getUTCDay();return t>=4||t===0?Od(e):Od.ceil(e)}function QX(e,t){return e=sO(e),en(Od.count(ao(e),e)+(ao(e).getUTCDay()===4),t,2)}function eK(e){return e.getUTCDay()}function tK(e,t){return en(Q1.count(ao(e)-1,e),t,2)}function nK(e,t){return en(e.getUTCFullYear()%100,t,2)}function rK(e,t){return e=sO(e),en(e.getUTCFullYear()%100,t,2)}function iK(e,t){return en(e.getUTCFullYear()%1e4,t,4)}function sK(e,t){var n=e.getUTCDay();return e=n>=4||n===0?Od(e):Od.ceil(e),en(e.getUTCFullYear()%1e4,t,4)}function aK(){return"+0000"}function VF(){return"%"}function XF(e){return+e}function KF(e){return Math.floor(+e/1e3)}var Tf,qk,aO,Wk,oO;oK({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function oK(e){return Tf=tO(e),qk=Tf.format,aO=Tf.parse,Wk=Tf.utcFormat,oO=Tf.utcParse,Tf}function Fp(e){const t={};return n=>t[n]||(t[n]=e(n))}function lK(e,t){return n=>{const r=e(n),i=r.indexOf(t);if(i<0)return r;let s=uK(r,i);const a=si;)if(r[s]!=="0"){++s;break}return r.slice(0,s)+a}}function uK(e,t){let n=e.lastIndexOf("e"),r;if(n>0)return n;for(n=e.length;--n>t;)if(r=e.charCodeAt(n),r>=48&&r<=57)return n+1}function lO(e){const t=Fp(e.format),n=e.formatPrefix;return{format:t,formatPrefix:n,formatFloat(r){const i=zc(r||",");if(i.precision==null){switch(i.precision=12,i.type){case"%":i.precision-=2;break;case"e":i.precision-=1;break}return lK(t(i),t(".1f")(1)[1])}else return t(i)},formatSpan(r,i,s,a){a=zc(a??",f");const o=iu(r,i,s),l=Math.max(Math.abs(r),Math.abs(i));let u;if(a.precision==null)switch(a.type){case"s":return isNaN(u=TN(o,l))||(a.precision=u),n(a,l);case"":case"e":case"g":case"p":case"r":{isNaN(u=RN(o,l))||(a.precision=u-(a.type==="e"));break}case"f":case"%":{isNaN(u=MN(o))||(a.precision=u-(a.type==="%")*2);break}}return t(a)}}}let Ww;uO();function uO(){return Ww=lO({format:zy,formatPrefix:Pk})}function cO(e){return lO(DN(e))}function ev(e){return arguments.length?Ww=cO(e):Ww}function ZF(e,t,n){n=n||{},Ue(n)||ye(`Invalid time multi-format specifier: ${n}`);const r=t(Os),i=t(cs),s=t(us),a=t(Bi),o=t(rr),l=t(Xr),u=t(Pi),c=t(Or),f=e(n[ha]||".%L"),d=e(n[Os]||":%S"),h=e(n[cs]||"%I:%M"),p=e(n[us]||"%I %p"),g=e(n[Bi]||n[Hr]||"%a %d"),v=e(n[rr]||"%b %d"),y=e(n[Xr]||"%B"),b=e(n[Pi]||"%B"),_=e(n[Or]||"%Y");return x=>(r(x)We(r)?t(r):ZF(t,kh,r),utcFormat:r=>We(r)?n(r):ZF(n,Sh,r),timeParse:Fp(e.parse),utcParse:Fp(e.utcParse)}}let Hw;dO();function dO(){return Hw=fO({format:qk,parse:aO,utcFormat:Wk,utcParse:oO})}function hO(e){return fO(tO(e))}function bg(e){return arguments.length?Hw=hO(e):Hw}const Gw=(e,t)=>Tt({},e,t);function pO(e,t){const n=e?cO(e):ev(),r=t?hO(t):bg();return Gw(n,r)}function Hk(e,t){const n=arguments.length;return n&&n!==2&&ye("defaultLocale expects either zero or two arguments."),n?Gw(ev(e),bg(t)):Gw(ev(),bg())}function cK(){return uO(),dO(),Hk()}const fK=/^(data:|([A-Za-z]+:)?\/\/)/,dK=/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|file|data):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,hK=/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g,JF="file://";function pK(e,t){return n=>({options:n||{},sanitize:mK,load:gK,fileAccess:!1,file:vK(),http:bK(e)})}async function gK(e,t){const n=await this.sanitize(e,t),r=n.href;return n.localFile?this.file(r):this.http(r,t)}async function mK(e,t){t=Tt({},this.options,t);const n=this.fileAccess,r={href:null};let i,s,a;const o=dK.test(e.replace(hK,""));(e==null||typeof e!="string"||!o)&&ye("Sanitize failure, invalid URI: "+Pe(e));const l=fK.test(e);return(a=t.baseURL)&&!l&&(!e.startsWith("/")&&!a.endsWith("/")&&(e="/"+e),e=a+e),s=(i=e.startsWith(JF))||t.mode==="file"||t.mode!=="http"&&!l&&n,i?e=e.slice(JF.length):e.startsWith("//")&&(t.defaultProtocol==="file"?(e=e.slice(2),s=!0):e=(t.defaultProtocol||"http")+":"+e),Object.defineProperty(r,"localFile",{value:!!s}),r.href=e,t.target&&(r.target=t.target+""),t.rel&&(r.rel=t.rel+""),t.context==="image"&&t.crossOrigin&&(r.crossOrigin=t.crossOrigin+""),r}function vK(e){return yK}async function yK(){ye("No file system access.")}function bK(e){return e?async function(t,n){const r=Tt({},this.options.http,n),i=n&&n.response,s=await e(t,r);return s.ok?Rt(s[i])?s[i]():s.text():ye(s.status+""+s.statusText)}:_K}async function _K(){ye("No HTTP fetch method available.")}const xK=e=>e!=null&&e===e,wK=e=>e==="true"||e==="false"||e===!0||e===!1,EK=e=>!Number.isNaN(Date.parse(e)),gO=e=>!Number.isNaN(+e)&&!(e instanceof Date),AK=e=>gO(e)&&Number.isInteger(+e),Yw={boolean:Nk,integer:Gr,number:Gr,date:Ok,string:Lk,unknown:ei},dm=[wK,AK,gO,EK],kK=["boolean","integer","number","date"];function mO(e,t){if(!e||!e.length)return"unknown";const n=e.length,r=dm.length,i=dm.map((s,a)=>a+1);for(let s=0,a=0,o,l;ss===0?a:s,0)-1]}function vO(e,t){return t.reduce((n,r)=>(n[r]=mO(e,r),n),{})}function QF(e){const t=function(n,r){const i={delimiter:e};return Gk(n,r?Tt(r,i):i)};return t.responseType="text",t}function Gk(e,t){return t.header&&(e=t.header.map(Pe).join(t.delimiter)+` +`+e),sV(t.delimiter).parse(e+"")}Gk.responseType="text";function SK(e){return typeof Buffer=="function"&&Rt(Buffer.isBuffer)?Buffer.isBuffer(e):!1}function Yk(e,t){const n=t&&t.property?Ns(t.property):ei;return Ue(e)&&!SK(e)?CK(n(e),t):n(JSON.parse(e))}Yk.responseType="json";function CK(e,t){return!Se(e)&&fN(e)&&(e=[...e]),t&&t.copy?JSON.parse(JSON.stringify(e)):e}const $K={interior:(e,t)=>e!==t,exterior:(e,t)=>e===t};function yO(e,t){let n,r,i,s;return e=Yk(e,t),t&&t.feature?(n=uV,i=t.feature):t&&t.mesh?(n=fV,i=t.mesh,s=$K[t.filter]):ye("Missing TopoJSON feature or mesh parameter."),r=(r=e.objects[i])?n(e,r,s):ye("Invalid TopoJSON object: "+i),r&&r.features||[r]}yO.responseType="json";const f1={dsv:Gk,csv:QF(","),tsv:QF(" "),json:Yk,topojson:yO};function Vk(e,t){return arguments.length>1?(f1[e]=t,this):Ve(f1,e)?f1[e]:null}function bO(e){const t=Vk(e);return t&&t.responseType||"text"}function _O(e,t,n,r){t=t||{};const i=Vk(t.type||"json");return i||ye("Unknown data format type: "+t.type),e=i(e,t),t.parse&&FK(e,t.parse,n,r),Ve(e,"columns")&&delete e.columns,e}function FK(e,t,n,r){if(!e.length)return;const i=bg();n=n||i.timeParse,r=r||i.utcParse;let s=e.columns||Object.keys(e[0]),a,o,l,u,c,f;t==="auto"&&(t=vO(e,s)),s=Object.keys(t);const d=s.map(h=>{const p=t[h];let g,v;if(p&&(p.startsWith("date:")||p.startsWith("utc:")))return g=p.split(/:(.+)?/,2),v=g[1],(v[0]==="'"&&v[v.length-1]==="'"||v[0]==='"'&&v[v.length-1]==='"')&&(v=v.slice(1,-1)),(g[0]==="utc"?r:n)(v);if(!Yw[p])throw Error("Illegal format pattern: "+h+":"+p);return Yw[p]});for(l=0,c=e.length,f=s.length;l{const s=t(i);return r[s]||(r[s]=1,n.push(i)),n},n.remove=i=>{const s=t(i);if(r[s]){r[s]=0;const a=n.indexOf(i);a>=0&&n.splice(a,1)}return n},n}async function d1(e,t){try{await t(e)}catch(n){e.error(n)}}const xO=Symbol("vega_id");let DK=1;function Vy(e){return!!(e&&dt(e))}function dt(e){return e[xO]}function wO(e,t){return e[xO]=t,e}function nn(e){const t=e===Object(e)?e:{data:e};return dt(t)?t:wO(t,DK++)}function Xk(e){return Xy(e,nn({}))}function Xy(e,t){for(const n in e)t[n]=e[n];return t}function EO(e,t){return wO(t,dt(e))}function gf(e,t){return e?t?(n,r)=>e(n,r)||dt(t(n))-dt(t(r)):(n,r)=>e(n,r)||dt(n)-dt(r):null}function AO(e){return e&&e.constructor===wu}function wu(){const e=[],t=[],n=[],r=[],i=[];let s=null,a=!1;return{constructor:wu,insert(o){const l=He(o),u=l.length;for(let c=0;c{p(b)&&(u[dt(b)]=-1)});for(f=0,d=e.length;f0&&(y(g,p,h.value),o.modifies(p));for(f=0,d=i.length;f{p(b)&&u[dt(b)]>0&&y(b,h.field,h.value)}),o.modifies(h.field);if(a)o.mod=t.length||r.length?l.filter(b=>u[dt(b)]>0):l.slice();else for(v in c)o.mod.push(c[v]);return(s||s==null&&(t.length||r.length))&&o.clean(!0),o}}}const h1="_:mod:_";function Ky(){Object.defineProperty(this,h1,{writable:!0,value:{}})}Ky.prototype={set(e,t,n,r){const i=this,s=i[e],a=i[h1];return t!=null&&t>=0?(s[t]!==n||r)&&(s[t]=n,a[t+":"+e]=-1,a[e]=-1):(s!==n||r)&&(i[e]=n,a[e]=Se(n)?1+n.length:-1),i},modified(e,t){const n=this[h1];if(arguments.length){if(Se(e)){for(let r=0;r=0?t+1{h instanceof gn?(h!==this&&(t&&h.targets().add(this),s.push(h)),i.push({op:h,name:f,index:d})):r.set(f,d,h)};for(a in e)if(o=e[a],a===TK)He(o).forEach(f=>{f instanceof gn?f!==this&&(f.targets().add(this),s.push(f)):ye("Pulse parameters must be operator instances.")}),this.source=o;else if(Se(o))for(r.set(a,-1,Array(l=o.length)),u=0;u{const n=Date.now();return n-t>e?(t=n,1):0})},debounce(e){const t=Sl();return this.targets().add(Sl(null,null,Mk(e,n=>{const r=n.dataflow;t.receive(n),r&&r.run&&r.run()}))),t},between(e,t){let n=!1;return e.targets().add(Sl(null,null,()=>n=!0)),t.targets().add(Sl(null,null,()=>n=!1)),this.filter(()=>n)},detach(){this._filter=ls,this._targets=null}};function BK(e,t,n,r){const i=this,s=Sl(n,r),a=function(u){u.dataflow=i;try{s.receive(u)}catch(c){i.error(c)}finally{i.run()}};let o;typeof e=="string"&&typeof document<"u"?o=document.querySelectorAll(e):o=He(e);const l=o.length;for(let u=0;ut=r);return n.requests=0,n.done=()=>{--n.requests===0&&(e._pending=null,t(e))},e._pending=n}const HK={skip:!0};function GK(e,t,n,r,i){return(e instanceof gn?VK:YK)(this,e,t,n,r,i),this}function YK(e,t,n,r,i,s){const a=Tt({},s,HK);let o,l;Rt(n)||(n=ti(n)),r===void 0?o=u=>e.touch(n(u)):Rt(r)?(l=new gn(null,r,i,!1),o=u=>{l.evaluate(u);const c=n(u),f=l.value;AO(f)?e.pulse(c,f,s):e.update(c,f,a)}):o=u=>e.update(n(u),r,a),t.apply(o)}function VK(e,t,n,r,i,s){if(r===void 0)t.targets().add(n);else{const a=s||{},o=new gn(null,XK(n,r),i,!1);o.modified(a.force),o.rank=t.rank,t.targets().add(o),n&&(o.skip(!0),o.value=n.value,o.targets().add(n),e.connect(n,[o]))}}function XK(e,t){return t=Rt(t)?t:ti(t),e?function(n,r){const i=t(n,r);return e.skip()||(e.skip(i!==this.value).value=i),i}:t}function KK(e){e.rank=++this._rank}function ZK(e){const t=[e];let n,r,i;for(;t.length;)if(this.rank(n=t.pop()),r=n._targets)for(i=r.length;--i>=0;)t.push(n=r[i]),n===e&&ye("Cycle detected in dataflow graph.")}const tv={},Ia=1,Fl=2,No=4,JK=Ia|Fl,t4=Ia|No,Rf=Ia|Fl|No,n4=8,np=16,r4=32,i4=64;function Zl(e,t,n){this.dataflow=e,this.stamp=t??-1,this.add=[],this.rem=[],this.mod=[],this.fields=null,this.encode=n||null}function k_(e,t){const n=[];return $l(e,t,r=>n.push(r)),n}function s4(e,t){const n={};return e.visit(t,r=>{n[dt(r)]=1}),r=>n[dt(r)]?null:r}function hm(e,t){return e?(n,r)=>e(n,r)&&t(n,r):t}Zl.prototype={StopPropagation:tv,ADD:Ia,REM:Fl,MOD:No,ADD_REM:JK,ADD_MOD:t4,ALL:Rf,REFLOW:n4,SOURCE:np,NO_SOURCE:r4,NO_FIELDS:i4,fork(e){return new Zl(this.dataflow).init(this,e)},clone(){const e=this.fork(Rf);return e.add=e.add.slice(),e.rem=e.rem.slice(),e.mod=e.mod.slice(),e.source&&(e.source=e.source.slice()),e.materialize(Rf|np)},addAll(){let e=this;return!e.source||e.add===e.rem||!e.rem.length&&e.source.length===e.add.length||(e=new Zl(this.dataflow).init(this),e.add=e.source,e.rem=[]),e},init(e,t){const n=this;return n.stamp=e.stamp,n.encode=e.encode,e.fields&&!(t&i4)&&(n.fields=e.fields),t&Ia?(n.addF=e.addF,n.add=e.add):(n.addF=null,n.add=[]),t&Fl?(n.remF=e.remF,n.rem=e.rem):(n.remF=null,n.rem=[]),t&No?(n.modF=e.modF,n.mod=e.mod):(n.modF=null,n.mod=[]),t&r4?(n.srcF=null,n.source=null):(n.srcF=e.srcF,n.source=e.source,e.cleans&&(n.cleans=e.cleans)),n},runAfter(e){this.dataflow.runAfter(e)},changed(e){const t=e||Rf;return t&Ia&&this.add.length||t&Fl&&this.rem.length||t&No&&this.mod.length},reflow(e){if(e)return this.fork(Rf).reflow();const t=this.add.length,n=this.source&&this.source.length;return n&&n!==t&&(this.mod=this.source,t&&this.filter(No,s4(this,Ia))),this},clean(e){return arguments.length?(this.cleans=!!e,this):this.cleans},modifies(e){const t=this.fields||(this.fields={});return Se(e)?e.forEach(n=>t[n]=!0):t[e]=!0,this},modified(e,t){const n=this.fields;return(t||this.mod.length)&&n?arguments.length?Se(e)?e.some(r=>n[r]):n[e]:!!n:!1},filter(e,t){const n=this;return e&Ia&&(n.addF=hm(n.addF,t)),e&Fl&&(n.remF=hm(n.remF,t)),e&No&&(n.modF=hm(n.modF,t)),e&np&&(n.srcF=hm(n.srcF,t)),n},materialize(e){e=e||Rf;const t=this;return e&Ia&&t.addF&&(t.add=k_(t.add,t.addF),t.addF=null),e&Fl&&t.remF&&(t.rem=k_(t.rem,t.remF),t.remF=null),e&No&&t.modF&&(t.mod=k_(t.mod,t.modF),t.modF=null),e&np&&t.srcF&&(t.source=t.source.filter(t.srcF),t.srcF=null),t},visit(e,t){const n=this,r=t;if(e&np)return $l(n.source,n.srcF,r),n;e&Ia&&$l(n.add,n.addF,r),e&Fl&&$l(n.rem,n.remF,r),e&No&&$l(n.mod,n.modF,r);const i=n.source;if(e&n4&&i){const s=n.add.length+n.mod.length;s===i.length||(s?$l(i,s4(n,t4),r):$l(i,n.srcF,r))}return n}};function Kk(e,t,n,r){const i=this;let s=0;this.dataflow=e,this.stamp=t,this.fields=null,this.encode=r||null,this.pulses=n;for(const a of n)if(a.stamp===t){if(a.fields){const o=i.fields||(i.fields={});for(const l in a.fields)o[l]=1}a.changed(i.ADD)&&(s|=i.ADD),a.changed(i.REM)&&(s|=i.REM),a.changed(i.MOD)&&(s|=i.MOD)}this.changes=s}Be(Kk,Zl,{fork(e){const t=new Zl(this.dataflow).init(this,e&this.NO_FIELDS);return e!==void 0&&(e&t.ADD&&this.visit(t.ADD,n=>t.add.push(n)),e&t.REM&&this.visit(t.REM,n=>t.rem.push(n)),e&t.MOD&&this.visit(t.MOD,n=>t.mod.push(n))),t},changed(e){return this.changes&e},modified(e){const t=this,n=t.fields;return n&&t.changes&t.MOD?Se(e)?e.some(r=>n[r]):n[e]:0},filter(){ye("MultiPulse does not support filtering.")},materialize(){ye("MultiPulse does not support materialization.")},visit(e,t){const n=this,r=n.pulses,i=r.length;let s=0;if(e&n.SOURCE)for(;sr._enqueue(c,!0)),r._touched=Yy(l0);let a=0,o,l,u;try{for(;r._heap.size()>0;){if(o=r._heap.pop(),o.rank!==o.qrank){r._enqueue(o,!0);continue}l=o.run(r._getPulse(o,e)),l.then?l=await l:l.async&&(i.push(l.async),l=tv),l!==tv&&o._targets&&o._targets.forEach(c=>r._enqueue(c)),++a}}catch(c){r._heap.clear(),u=c}if(r._input={},r._pulse=null,r.debug(`Pulse ${s}: ${a} operators`),u&&(r._postrun=[],r.error(u)),r._postrun.length){const c=r._postrun.sort((f,d)=>d.priority-f.priority);r._postrun=[];for(let f=0;fr.runAsync(null,()=>{c.forEach(f=>{try{f(r)}catch(d){r.error(d)}})})),r}async function eZ(e,t,n){for(;this._running;)await this._running;const r=()=>this._running=null;return(this._running=this.evaluate(e,t,n)).then(r,r),this._running}function tZ(e,t,n){return this._pulse?kO(this):(this.evaluate(e,t,n),this)}function nZ(e,t,n){if(this._pulse||t)this._postrun.push({priority:n||0,callback:e});else try{e(this)}catch(r){this.error(r)}}function kO(e){return e.error("Dataflow already running. Use runAsync() to chain invocations."),e}function rZ(e,t){const n=e.stampi.pulse),t):this._input[e.id]||sZ(this._pulse,n&&n.pulse)}function sZ(e,t){return t&&t.stamp===e.stamp?t:(e=e.fork(),t&&t!==tv&&(e.source=t.source),e)}const Zk={skip:!1,force:!1};function aZ(e,t){const n=t||Zk;return this._pulse?this._enqueue(e):this._touched.add(e),n.skip&&e.skip(!0),this}function oZ(e,t,n){const r=n||Zk;return(e.set(t)||r.force)&&this.touch(e,r),this}function lZ(e,t,n){this.touch(e,n||Zk);const r=new Zl(this,this._clock+(this._pulse?0:1)),i=e.pulse&&e.pulse.source||[];return r.target=e,this._input[e.id]=t.pulse(r,i),this}function uZ(e){let t=[];return{clear:()=>t=[],size:()=>t.length,peek:()=>t[0],push:n=>(t.push(n),SO(t,0,t.length-1,e)),pop:()=>{const n=t.pop();let r;return t.length?(r=t[0],t[0]=n,cZ(t,0,e)):r=n,r}}}function SO(e,t,n,r){let i,s;const a=e[n];for(;n>t;){if(s=n-1>>1,i=e[s],r(a,i)<0){e[n]=i,n=s;continue}break}return e[n]=a}function cZ(e,t,n){const r=t,i=e.length,s=e[t];let a=(t<<1)+1,o;for(;a=0&&(a=o),e[t]=e[a],t=a,a=(t<<1)+1;return e[t]=s,SO(e,r,t,n)}function sd(){this.logger(Sk()),this.logLevel(Ak),this._clock=0,this._rank=0,this._locale=Hk();try{this._loader=Gy()}catch{}this._touched=Yy(l0),this._input={},this._pulse=null,this._heap=uZ((e,t)=>e.qrank-t.qrank),this._postrun=[]}function rp(e){return function(){return this._log[e].apply(this,arguments)}}sd.prototype={stamp(){return this._clock},loader(e){return arguments.length?(this._loader=e,this):this._loader},locale(e){return arguments.length?(this._locale=e,this):this._locale},logger(e){return arguments.length?(this._log=e,this):this._log},error:rp("error"),warn:rp("warn"),info:rp("info"),debug:rp("debug"),logLevel:rp("level"),cleanThreshold:1e4,add:LK,connect:IK,rank:KK,rerank:ZK,pulse:lZ,touch:aZ,update:oZ,changeset:wu,ingest:jK,parse:zK,preload:qK,request:UK,events:BK,on:GK,evaluate:QK,run:tZ,runAsync:eZ,runAfter:nZ,_enqueue:rZ,_getPulse:iZ};function de(e,t){gn.call(this,e,null,t)}Be(de,gn,{run(e){if(e.stampthis.pulse=n):t!==e.StopPropagation&&(this.pulse=t),t},evaluate(e){const t=this.marshall(e.stamp),n=this.transform(t,e);return t.clear(),n},transform(){}});const Id={};function CO(e){const t=$O(e);return t&&t.Definition||null}function $O(e){return e=e&&e.toLowerCase(),Ve(Id,e)?Id[e]:null}function*FO(e,t){if(t==null)for(let n of e)n!=null&&n!==""&&(n=+n)>=n&&(yield n);else{let n=-1;for(let r of e)r=t(r,++n,e),r!=null&&r!==""&&(r=+r)>=r&&(yield r)}}function Jk(e,t,n){const r=Float64Array.from(FO(e,n));return r.sort(Zo),t.map(i=>SN(r,i))}function Qk(e,t){return Jk(e,[.25,.5,.75],t)}function eS(e,t){const n=e.length,r=bV(e,t),i=Qk(e,t),s=(i[2]-i[0])/1.34;return 1.06*(Math.min(r,s)||r||Math.abs(i[0])||1)*Math.pow(n,-.2)}function DO(e){const t=e.maxbins||20,n=e.base||10,r=Math.log(n),i=e.divide||[5,2];let s=e.extent[0],a=e.extent[1],o,l,u,c,f,d;const h=e.span||a-s||Math.abs(s)||1;if(e.step)o=e.step;else if(e.steps){for(c=h/t,f=0,d=e.steps.length;ft;)o*=n;for(f=0,d=i.length;f=u&&h/c<=t&&(o=c)}c=Math.log(o);const p=c>=0?0:~~(-c/r)+1,g=Math.pow(n,-p-1);return(e.nice||e.nice===void 0)&&(c=Math.floor(s/o+g)*o,s=sd);const i=e.length,s=new Float64Array(i);let a=0,o=1,l=r(e[0]),u=l,c=l+t,f;for(;o=c){for(u=(l+u)/2;a>1);ai;)e[a--]=e[r]}r=i,i=s}return e}function hZ(e){return function(){return e=(1103515245*e+12345)%2147483647,e/2147483647}}function pZ(e,t){t==null&&(t=e,e=0);let n,r,i;const s={min(a){return arguments.length?(n=a||0,i=r-n,s):n},max(a){return arguments.length?(r=a||0,i=r-n,s):r},sample(){return n+Math.floor(i*Ls())},pdf(a){return a===Math.floor(a)&&a>=n&&a=r?1:(o-n+1)/i},icdf(a){return a>=0&&a<=1?n-1+Math.floor(a*i):NaN}};return s.min(e).max(t)}const RO=Math.sqrt(2*Math.PI),gZ=Math.SQRT2;let ip=NaN;function Jy(e,t){e=e||0,t=t??1;let n=0,r=0,i,s;if(ip===ip)n=ip,ip=NaN;else{do n=Ls()*2-1,r=Ls()*2-1,i=n*n+r*r;while(i===0||i>1);s=Math.sqrt(-2*Math.log(i)/i),n*=s,ip=r*s}return e+n*t}function tS(e,t,n){n=n??1;const r=(e-(t||0))/n;return Math.exp(-.5*r*r)/(n*RO)}function Qy(e,t,n){t=t||0,n=n??1;const r=(e-t)/n,i=Math.abs(r);let s;if(i>37)s=0;else{const a=Math.exp(-i*i/2);let o;i<7.07106781186547?(o=.0352624965998911*i+.700383064443688,o=o*i+6.37396220353165,o=o*i+33.912866078383,o=o*i+112.079291497871,o=o*i+221.213596169931,o=o*i+220.206867912376,s=a*o,o=.0883883476483184*i+1.75566716318264,o=o*i+16.064177579207,o=o*i+86.7807322029461,o=o*i+296.564248779674,o=o*i+637.333633378831,o=o*i+793.826512519948,o=o*i+440.413735824752,s=s/o):(o=i+.65,o=i+4/o,o=i+3/o,o=i+2/o,o=i+1/o,s=a/o/2.506628274631)}return r>0?1-s:s}function eb(e,t,n){return e<0||e>1?NaN:(t||0)+(n??1)*gZ*mZ(2*e-1)}function mZ(e){let t=-Math.log((1-e)*(1+e)),n;return t<6.25?(t-=3.125,n=-364441206401782e-35,n=-16850591381820166e-35+n*t,n=128584807152564e-32+n*t,n=11157877678025181e-33+n*t,n=-1333171662854621e-31+n*t,n=20972767875968562e-33+n*t,n=6637638134358324e-30+n*t,n=-4054566272975207e-29+n*t,n=-8151934197605472e-29+n*t,n=26335093153082323e-28+n*t,n=-12975133253453532e-27+n*t,n=-5415412054294628e-26+n*t,n=10512122733215323e-25+n*t,n=-4112633980346984e-24+n*t,n=-29070369957882005e-24+n*t,n=42347877827932404e-23+n*t,n=-13654692000834679e-22+n*t,n=-13882523362786469e-21+n*t,n=.00018673420803405714+n*t,n=-.000740702534166267+n*t,n=-.006033670871430149+n*t,n=.24015818242558962+n*t,n=1.6536545626831027+n*t):t<16?(t=Math.sqrt(t)-3.25,n=22137376921775787e-25,n=9075656193888539e-23+n*t,n=-27517406297064545e-23+n*t,n=18239629214389228e-24+n*t,n=15027403968909828e-22+n*t,n=-4013867526981546e-21+n*t,n=29234449089955446e-22+n*t,n=12475304481671779e-21+n*t,n=-47318229009055734e-21+n*t,n=6828485145957318e-20+n*t,n=24031110387097894e-21+n*t,n=-.0003550375203628475+n*t,n=.0009532893797373805+n*t,n=-.0016882755560235047+n*t,n=.002491442096107851+n*t,n=-.003751208507569241+n*t,n=.005370914553590064+n*t,n=1.0052589676941592+n*t,n=3.0838856104922208+n*t):Number.isFinite(t)?(t=Math.sqrt(t)-5,n=-27109920616438573e-27,n=-2555641816996525e-25+n*t,n=15076572693500548e-25+n*t,n=-3789465440126737e-24+n*t,n=761570120807834e-23+n*t,n=-1496002662714924e-23+n*t,n=2914795345090108e-23+n*t,n=-6771199775845234e-23+n*t,n=22900482228026655e-23+n*t,n=-99298272942317e-20+n*t,n=4526062597223154e-21+n*t,n=-1968177810553167e-20+n*t,n=7599527703001776e-20+n*t,n=-.00021503011930044477+n*t,n=-.00013871931833623122+n*t,n=1.0103004648645344+n*t,n=4.849906401408584+n*t):n=1/0,n*e}function nS(e,t){let n,r;const i={mean(s){return arguments.length?(n=s||0,i):n},stdev(s){return arguments.length?(r=s??1,i):r},sample:()=>Jy(n,r),pdf:s=>tS(s,n,r),cdf:s=>Qy(s,n,r),icdf:s=>eb(s,n,r)};return i.mean(e).stdev(t)}function rS(e,t){const n=nS();let r=0;const i={data(s){return arguments.length?(e=s,r=s?s.length:0,i.bandwidth(t)):e},bandwidth(s){return arguments.length?(t=s,!t&&e&&(t=eS(e)),i):t},sample(){return e[~~(Ls()*r)]+t*n.sample()},pdf(s){let a=0,o=0;for(;oiS(n,r),pdf:s=>sS(s,n,r),cdf:s=>aS(s,n,r),icdf:s=>oS(s,n,r)};return i.mean(e).stdev(t)}function OO(e,t){let n=0,r;function i(a){const o=[];let l=0,u;for(u=0;u=t&&e<=n?1/(n-t):0}function cS(e,t,n){return n==null&&(n=t??1,t=0),en?1:(e-t)/(n-t)}function fS(e,t,n){return n==null&&(n=t??1,t=0),e>=0&&e<=1?t+e*(n-t):NaN}function LO(e,t){let n,r;const i={min(s){return arguments.length?(n=s||0,i):n},max(s){return arguments.length?(r=s??1,i):r},sample:()=>lS(n,r),pdf:s=>uS(s,n,r),cdf:s=>cS(s,n,r),icdf:s=>fS(s,n,r)};return t==null&&(t=e??1,e=0),i.min(e).max(t)}function dS(e,t,n){let r=0,i=0;for(const s of e){const a=n(s);t(s)==null||a==null||isNaN(a)||(r+=(a-r)/++i)}return{coef:[r],predict:()=>r,rSquared:0}}function c0(e,t,n,r){const i=r-e*e,s=Math.abs(i)<1e-24?0:(n-e*t)/i;return[t-s*e,s]}function tb(e,t,n,r){e=e.filter(h=>{let p=t(h),g=n(h);return p!=null&&(p=+p)>=p&&g!=null&&(g=+g)>=g}),r&&e.sort((h,p)=>t(h)-t(p));const i=e.length,s=new Float64Array(i),a=new Float64Array(i);let o=0,l=0,u=0,c,f,d;for(d of e)s[o]=c=+t(d),a[o]=f=+n(d),++o,l+=(c-l)/o,u+=(f-u)/o;for(o=0;o=s&&a!=null&&(a=+a)>=a&&r(s,a,++i)}function Ch(e,t,n,r,i){let s=0,a=0;return f0(e,t,n,(o,l)=>{const u=l-i(o),c=l-r;s+=u*u,a+=c*c}),1-s/a}function hS(e,t,n){let r=0,i=0,s=0,a=0,o=0;f0(e,t,n,(c,f)=>{++o,r+=(c-r)/o,i+=(f-i)/o,s+=(c*f-s)/o,a+=(c*c-a)/o});const l=c0(r,i,s,a),u=c=>l[0]+l[1]*c;return{coef:l,predict:u,rSquared:Ch(e,t,n,i,u)}}function IO(e,t,n){let r=0,i=0,s=0,a=0,o=0;f0(e,t,n,(c,f)=>{++o,c=Math.log(c),r+=(c-r)/o,i+=(f-i)/o,s+=(c*f-s)/o,a+=(c*c-a)/o});const l=c0(r,i,s,a),u=c=>l[0]+l[1]*Math.log(c);return{coef:l,predict:u,rSquared:Ch(e,t,n,i,u)}}function PO(e,t,n){const[r,i,s,a]=tb(e,t,n);let o=0,l=0,u=0,c=0,f=0,d,h,p;f0(e,t,n,(b,_)=>{d=r[f++],h=Math.log(_),p=d*_,o+=(_*h-o)/f,l+=(p-l)/f,u+=(p*h-u)/f,c+=(d*p-c)/f});const[g,v]=c0(l/a,o/a,u/a,c/a),y=b=>Math.exp(g+v*(b-s));return{coef:[Math.exp(g-v*s),v],predict:y,rSquared:Ch(e,t,n,a,y)}}function BO(e,t,n){let r=0,i=0,s=0,a=0,o=0,l=0;f0(e,t,n,(f,d)=>{const h=Math.log(f),p=Math.log(d);++l,r+=(h-r)/l,i+=(p-i)/l,s+=(h*p-s)/l,a+=(h*h-a)/l,o+=(d-o)/l});const u=c0(r,i,s,a),c=f=>u[0]*Math.pow(f,u[1]);return u[0]=Math.exp(u[0]),{coef:u,predict:c,rSquared:Ch(e,t,n,o,c)}}function pS(e,t,n){const[r,i,s,a]=tb(e,t,n),o=r.length;let l=0,u=0,c=0,f=0,d=0,h,p,g,v;for(h=0;h(E=E-s,_*E*E+x*E+w+a);return{coef:[w-x*s+_*s*s+a,x-2*_*s,_],predict:A,rSquared:Ch(e,t,n,a,A)}}function zO(e,t,n,r){if(r===0)return dS(e,t,n);if(r===1)return hS(e,t,n);if(r===2)return pS(e,t,n);const[i,s,a,o]=tb(e,t,n),l=i.length,u=[],c=[],f=r+1;let d,h,p,g,v;for(d=0;d{_-=a;let x=o+y[0]+y[1]*_+y[2]*_*_;for(d=3;d=0;--s)for(o=t[s],l=1,i[s]+=o,a=1;a<=s;++a)l*=(s+1-a)/a,i[s-a]+=o*Math.pow(n,a)*l;return i[0]+=r,i}function yZ(e){const t=e.length-1,n=[];let r,i,s,a,o;for(r=0;rMath.abs(e[r][a])&&(a=i);for(s=r;s=r;s--)e[s][i]-=e[s][r]*e[r][i]/e[r][r]}for(i=t-1;i>=0;--i){for(o=0,s=i+1;si[_]-y?b:_;let w=0,A=0,E=0,k=0,C=0;const M=1/Math.abs(i[x]-y||1);for(let I=b;I<=_;++I){const T=i[I],$=s[I],L=bZ(Math.abs(y-T)*M)*d[I],W=T*L;w+=L,A+=W,E+=$*L,k+=$*W,C+=T*W}const[N,P]=c0(A/w,E/w,k/w,C/w);c[v]=N+P*y,f[v]=Math.abs(s[v]-c[v]),_Z(i,v+1,p)}if(h===a4)break;const g=CN(f);if(Math.abs(g)=1?o4:(b=1-y*y)*b}return xZ(i,c,a,o)}function bZ(e){return(e=1-e*e*e)*e*e}function _Z(e,t,n){const r=e[t];let i=n[0],s=n[1]+1;if(!(s>=e.length))for(;t>i&&e[s]-r<=r-e[i];)n[0]=++i,n[1]=s,++s}function xZ(e,t,n,r){const i=e.length,s=[];let a=0,o=0,l=[],u;for(;a[g,e(g)],s=t[0],a=t[1],o=a-s,l=o/r,u=[i(s)],c=[];if(n===r){for(let g=1;g0;)c.push(i(s+g/n*o))}let f=u[0],d=c[c.length-1];const h=1/o,p=EZ(f[1],c);for(;d;){const g=i((f[0]+d[0])/2);g[0]-f[0]>=l&&AZ(f,g,d,h,p)>wZ?c.push(g):(f=d,u.push(d),c.pop()),d=c[c.length-1]}return u}function EZ(e,t){let n=e,r=e;const i=t.length;for(let s=0;sr&&(r=a)}return 1/(r-n)}function AZ(e,t,n,r,i){const s=Math.atan2(i*(n[1]-e[1]),r*(n[0]-e[0])),a=Math.atan2(i*(t[1]-e[1]),r*(t[0]-e[0]));return Math.abs(s-a)}function kZ(e){return t=>{const n=e.length;let r=1,i=String(e[0](t));for(;r{},SZ={init:S_,add:S_,rem:S_,idx:0},_g={values:{init:e=>e.cell.store=!0,value:e=>e.cell.data.values(),idx:-1},count:{value:e=>e.cell.num},__count__:{value:e=>e.missing+e.valid},missing:{value:e=>e.missing},valid:{value:e=>e.valid},sum:{init:e=>e.sum=0,value:e=>e.valid?e.sum:void 0,add:(e,t)=>e.sum+=+t,rem:(e,t)=>e.sum-=t},product:{init:e=>e.product=1,value:e=>e.valid?e.product:void 0,add:(e,t)=>e.product*=t,rem:(e,t)=>e.product/=t},mean:{init:e=>e.mean=0,value:e=>e.valid?e.mean:void 0,add:(e,t)=>(e.mean_d=t-e.mean,e.mean+=e.mean_d/e.valid),rem:(e,t)=>(e.mean_d=t-e.mean,e.mean-=e.valid?e.mean_d/e.valid:e.mean)},average:{value:e=>e.valid?e.mean:void 0,req:["mean"],idx:1},variance:{init:e=>e.dev=0,value:e=>e.valid>1?e.dev/(e.valid-1):void 0,add:(e,t)=>e.dev+=e.mean_d*(t-e.mean),rem:(e,t)=>e.dev-=e.mean_d*(t-e.mean),req:["mean"],idx:1},variancep:{value:e=>e.valid>1?e.dev/e.valid:void 0,req:["variance"],idx:2},stdev:{value:e=>e.valid>1?Math.sqrt(e.dev/(e.valid-1)):void 0,req:["variance"],idx:2},stdevp:{value:e=>e.valid>1?Math.sqrt(e.dev/e.valid):void 0,req:["variance"],idx:2},stderr:{value:e=>e.valid>1?Math.sqrt(e.dev/(e.valid*(e.valid-1))):void 0,req:["variance"],idx:2},distinct:{value:e=>e.cell.data.distinct(e.get),req:["values"],idx:3},ci0:{value:e=>e.cell.data.ci0(e.get),req:["values"],idx:3},ci1:{value:e=>e.cell.data.ci1(e.get),req:["values"],idx:3},median:{value:e=>e.cell.data.q2(e.get),req:["values"],idx:3},q1:{value:e=>e.cell.data.q1(e.get),req:["values"],idx:3},q3:{value:e=>e.cell.data.q3(e.get),req:["values"],idx:3},min:{init:e=>e.min=void 0,value:e=>e.min=Number.isNaN(e.min)?e.cell.data.min(e.get):e.min,add:(e,t)=>{(t{t<=e.min&&(e.min=NaN)},req:["values"],idx:4},max:{init:e=>e.max=void 0,value:e=>e.max=Number.isNaN(e.max)?e.cell.data.max(e.get):e.max,add:(e,t)=>{(t>e.max||e.max===void 0)&&(e.max=t)},rem:(e,t)=>{t>=e.max&&(e.max=NaN)},req:["values"],idx:4},argmin:{init:e=>e.argmin=void 0,value:e=>e.argmin||e.cell.data.argmin(e.get),add:(e,t,n)=>{t{t<=e.min&&(e.argmin=void 0)},req:["min","values"],idx:3},argmax:{init:e=>e.argmax=void 0,value:e=>e.argmax||e.cell.data.argmax(e.get),add:(e,t,n)=>{t>e.max&&(e.argmax=n)},rem:(e,t)=>{t>=e.max&&(e.argmax=void 0)},req:["max","values"],idx:3},exponential:{init:(e,t)=>{e.exp=0,e.exp_r=t},value:e=>e.valid?e.exp*(1-e.exp_r)/(1-e.exp_r**e.valid):void 0,add:(e,t)=>e.exp=e.exp_r*e.exp+t,rem:(e,t)=>e.exp=(e.exp-t/e.exp_r**(e.valid-1))/e.exp_r},exponentialb:{value:e=>e.valid?e.exp*(1-e.exp_r):void 0,req:["exponential"],idx:1}},d0=Object.keys(_g).filter(e=>e!=="__count__");function CZ(e,t){return(n,r)=>Tt({name:e,aggregate_param:r,out:n||e},SZ,t)}[...d0,"__count__"].forEach(e=>{_g[e]=CZ(e,_g[e])});function qO(e,t,n){return _g[e](n,t)}function WO(e,t){return e.idx-t.idx}function $Z(e){const t={};e.forEach(r=>t[r.name]=r);const n=r=>{r.req&&r.req.forEach(i=>{t[i]||n(t[i]=_g[i]())})};return e.forEach(n),Object.values(t).sort(WO)}function FZ(){this.valid=0,this.missing=0,this._ops.forEach(e=>e.aggregate_param==null?e.init(this):e.init(this,e.aggregate_param))}function DZ(e,t){if(e==null||e===""){++this.missing;return}e===e&&(++this.valid,this._ops.forEach(n=>n.add(this,e,t)))}function MZ(e,t){if(e==null||e===""){--this.missing;return}e===e&&(--this.valid,this._ops.forEach(n=>n.rem(this,e,t)))}function TZ(e){return this._out.forEach(t=>e[t.out]=t.value(this)),e}function HO(e,t){const n=t||ei,r=$Z(e),i=e.slice().sort(WO);function s(a){this._ops=r,this._out=i,this.cell=a,this.init()}return s.prototype.init=FZ,s.prototype.add=DZ,s.prototype.rem=MZ,s.prototype.set=TZ,s.prototype.get=n,s.fields=e.map(a=>a.out),s}function gS(e){this._key=e?Ns(e):dt,this.reset()}const Br=gS.prototype;Br.reset=function(){this._add=[],this._rem=[],this._ext=null,this._get=null,this._q=null};Br.add=function(e){this._add.push(e)};Br.rem=function(e){this._rem.push(e)};Br.values=function(){if(this._get=null,this._rem.length===0)return this._add;const e=this._add,t=this._rem,n=this._key,r=e.length,i=t.length,s=Array(r-i),a={};let o,l,u;for(o=0;o=0;)s=e(t[r])+"",Ve(n,s)||(n[s]=1,++i);return i};Br.extent=function(e){if(this._get!==e||!this._ext){const t=this.values(),n=uN(t,e);this._ext=[t[n[0]],t[n[1]]],this._get=e}return this._ext};Br.argmin=function(e){return this.extent(e)[0]||{}};Br.argmax=function(e){return this.extent(e)[1]||{}};Br.min=function(e){const t=this.extent(e)[0];return t!=null?e(t):void 0};Br.max=function(e){const t=this.extent(e)[1];return t!=null?e(t):void 0};Br.quartile=function(e){return(this._get!==e||!this._q)&&(this._q=Qk(this.values(),e),this._get=e),this._q};Br.q1=function(e){return this.quartile(e)[0]};Br.q2=function(e){return this.quartile(e)[1]};Br.q3=function(e){return this.quartile(e)[2]};Br.ci=function(e){return(this._get!==e||!this._ci)&&(this._ci=MO(this.values(),1e3,.05,e),this._get=e),this._ci};Br.ci0=function(e){return this.ci(e)[0]};Br.ci1=function(e){return this.ci(e)[1]};function su(e){de.call(this,null,e),this._adds=[],this._mods=[],this._alen=0,this._mlen=0,this._drop=!0,this._cross=!1,this._dims=[],this._dnames=[],this._measures=[],this._countOnly=!1,this._counts=null,this._prev=null,this._inputs=null,this._outputs=null}su.Definition={type:"Aggregate",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"ops",type:"enum",array:!0,values:d0},{name:"aggregate_params",type:"number",null:!0,array:!0},{name:"fields",type:"field",null:!0,array:!0},{name:"as",type:"string",null:!0,array:!0},{name:"drop",type:"boolean",default:!0},{name:"cross",type:"boolean",default:!1},{name:"key",type:"field"}]};Be(su,de,{transform(e,t){const n=this,r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=e.modified();return n.stamp=r.stamp,n.value&&(i||t.modified(n._inputs,!0))?(n._prev=n.value,n.value=i?n.init(e):Object.create(null),t.visit(t.SOURCE,s=>n.add(s))):(n.value=n.value||n.init(e),t.visit(t.REM,s=>n.rem(s)),t.visit(t.ADD,s=>n.add(s))),r.modifies(n._outputs),n._drop=e.drop!==!1,e.cross&&n._dims.length>1&&(n._drop=!1,n.cross()),t.clean()&&n._drop&&r.clean(!0).runAfter(()=>this.clean()),n.changes(r)},cross(){const e=this,t=e.value,n=e._dnames,r=n.map(()=>({})),i=n.length;function s(o){let l,u,c,f;for(l in o)for(c=o[l].tuple,u=0;u{const _=zn(b);return i(b),n.push(_),_}),this.cellkey=e.key?e.key:Vw(this._dims),this._countOnly=!0,this._counts=[],this._measures=[];const s=e.fields||[null],a=e.ops||["count"],o=e.aggregate_params||[null],l=e.as||[],u=s.length,c={};let f,d,h,p,g,v,y;for(u!==a.length&&ye("Unmatched number of fields and aggregate ops."),y=0;yHO(b,b.field)),Object.create(null)},cellkey:Vw(),cell(e,t){let n=this.value[e];return n?n.num===0&&this._drop&&n.stamp{const f=r(c);c[o]=f,c[l]=f==null?null:i+s*(1+(f-i)/s)}:c=>c[o]=r(c)),t.modifies(n?a:o)},_bins(e){if(this.value&&!e.modified())return this.value;const t=e.field,n=DO(e),r=n.step;let i=n.start,s=i+Math.ceil((n.stop-i)/r)*r,a,o;(a=e.anchor)!=null&&(o=a-(i+r*Math.floor((a-i)/r)),i+=o,s+=o);const l=function(u){let c=Gr(t(u));return c==null?null:cs?1/0:(c=Math.max(i,Math.min(c,s-r)),i+r*Math.floor(RZ+(c-i)/r))};return l.start=i,l.stop=n.stop,l.step=r,this.value=Wi(l,Vr(t),e.name||"bin_"+zn(t))}});function GO(e,t,n){const r=e;let i=t||[],s=n||[],a={},o=0;return{add:l=>s.push(l),remove:l=>a[r(l)]=++o,size:()=>i.length,data:(l,u)=>(o&&(i=i.filter(c=>!a[r(c)]),a={},o=0),u&&l&&i.sort(l),s.length&&(i=l?pN(l,i,s.sort(l)):i.concat(s),s=[]),i)}}function vS(e){de.call(this,[],e)}vS.Definition={type:"Collect",metadata:{source:!0},params:[{name:"sort",type:"compare"}]};Be(vS,de,{transform(e,t){const n=t.fork(t.ALL),r=GO(dt,this.value,n.materialize(n.ADD).add),i=e.sort,s=t.changed()||i&&(e.modified("sort")||t.modified(i.fields));return n.visit(n.REM,r.remove),this.modified(s),this.value=n.source=r.data(gf(i),s),t.source&&t.source.root&&(this.value.root=t.source.root),n}});function YO(e){gn.call(this,null,NZ,e)}Be(YO,gn);function NZ(e){return this.value&&!e.modified()?this.value:Dk(e.fields,e.orders)}function yS(e){de.call(this,null,e)}yS.Definition={type:"CountPattern",metadata:{generates:!0,changes:!0},params:[{name:"field",type:"field",required:!0},{name:"case",type:"enum",values:["upper","lower","mixed"],default:"mixed"},{name:"pattern",type:"string",default:'[\\w"]+'},{name:"stopwords",type:"string",default:""},{name:"as",type:"string",array:!0,length:2,default:["text","count"]}]};function OZ(e,t,n){switch(t){case"upper":e=e.toUpperCase();break;case"lower":e=e.toLowerCase();break}return e.match(n)}Be(yS,de,{transform(e,t){const n=f=>d=>{for(var h=OZ(o(d),e.case,s)||[],p,g=0,v=h.length;gi[f]=1+(i[f]||0)),c=n(f=>i[f]-=1);return r?t.visit(t.SOURCE,u):(t.visit(t.ADD,u),t.visit(t.REM,c)),this._finish(t,l)},_parameterCheck(e,t){let n=!1;return(e.modified("stopwords")||!this._stop)&&(this._stop=new RegExp("^"+(e.stopwords||"")+"$","i"),n=!0),(e.modified("pattern")||!this._match)&&(this._match=new RegExp(e.pattern||"[\\w']+","g"),n=!0),(e.modified("field")||t.modified(e.field.fields))&&(n=!0),n&&(this._counts={}),n},_finish(e,t){const n=this._counts,r=this._tuples||(this._tuples={}),i=t[0],s=t[1],a=e.fork(e.NO_SOURCE|e.NO_FIELDS);let o,l,u;for(o in n)l=r[o],u=n[o]||0,!l&&u?(r[o]=l=nn({}),l[i]=o,l[s]=u,a.add.push(l)):u===0?(l&&a.rem.push(l),n[o]=null,r[o]=null):l[s]!==u&&(l[s]=u,a.mod.push(l));return a.modifies(t)}});function bS(e){de.call(this,null,e)}bS.Definition={type:"Cross",metadata:{generates:!0},params:[{name:"filter",type:"expr"},{name:"as",type:"string",array:!0,length:2,default:["a","b"]}]};Be(bS,de,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.as||["a","b"],i=r[0],s=r[1],a=!this.value||t.changed(t.ADD_REM)||e.modified("as")||e.modified("filter");let o=this.value;return a?(o&&(n.rem=o),o=t.materialize(t.SOURCE).source,n.add=this.value=LZ(o,i,s,e.filter||ls)):n.mod=o,n.source=this.value,n.modifies(r)}});function LZ(e,t,n,r){for(var i=[],s={},a=e.length,o=0,l,u;oVO(s,t))):typeof r[i]===u4&&r[i](e[i]);return r}function _S(e){de.call(this,null,e)}const XO=[{key:{function:"normal"},params:[{name:"mean",type:"number",default:0},{name:"stdev",type:"number",default:1}]},{key:{function:"lognormal"},params:[{name:"mean",type:"number",default:0},{name:"stdev",type:"number",default:1}]},{key:{function:"uniform"},params:[{name:"min",type:"number",default:0},{name:"max",type:"number",default:1}]},{key:{function:"kde"},params:[{name:"field",type:"field",required:!0},{name:"from",type:"data"},{name:"bandwidth",type:"number",default:0}]}],BZ={key:{function:"mixture"},params:[{name:"distributions",type:"param",array:!0,params:XO},{name:"weights",type:"number",array:!0}]};_S.Definition={type:"Density",metadata:{generates:!0},params:[{name:"extent",type:"number",array:!0,length:2},{name:"steps",type:"number"},{name:"minsteps",type:"number",default:25},{name:"maxsteps",type:"number",default:200},{name:"method",type:"string",default:"pdf",values:["pdf","cdf"]},{name:"distribution",type:"param",params:XO.concat(BZ)},{name:"as",type:"string",array:!0,default:["value","density"]}]};Be(_S,de,{transform(e,t){const n=t.fork(t.NO_SOURCE|t.NO_FIELDS);if(!this.value||t.changed()||e.modified()){const r=VO(e.distribution,zZ(t)),i=e.steps||e.minsteps||25,s=e.steps||e.maxsteps||200;let a=e.method||"pdf";a!=="pdf"&&a!=="cdf"&&ye("Invalid density method: "+a),!e.extent&&!r.data&&ye("Missing density extent parameter."),a=r[a];const o=e.as||["value","density"],l=e.extent||io(r.data()),u=nb(a,l,i,s).map(c=>{const f={};return f[o[0]]=c[0],f[o[1]]=c[1],nn(f)});this.value&&(n.rem=this.value),this.value=n.add=n.source=u}return n}});function zZ(e){return()=>e.materialize(e.SOURCE).source}function KO(e,t){return e?e.map((n,r)=>t[r]||zn(n)):null}function xS(e,t,n){const r=[],i=f=>f(l);let s,a,o,l,u,c;if(t==null)r.push(e.map(n));else for(s={},a=0,o=e.length;au0(io(e,t))/30;Be(wS,de,{transform(e,t){if(this.value&&!(e.modified()||t.changed()))return t;const n=t.materialize(t.SOURCE).source,r=xS(t.source,e.groupby,ei),i=e.smooth||!1,s=e.field,a=e.step||jZ(n,s),o=gf((p,g)=>s(p)-s(g)),l=e.as||ZO,u=r.length;let c=1/0,f=-1/0,d=0,h;for(;df&&(f=g),p[++h][l]=g}return this.value={start:c,stop:f,step:a},t.reflow(!0).modifies(l)}});function JO(e){gn.call(this,null,UZ,e),this.modified(!0)}Be(JO,gn);function UZ(e){const t=e.expr;return this.value&&!e.modified("expr")?this.value:Wi(n=>t(n,e),Vr(t),zn(t))}function ES(e){de.call(this,[void 0,void 0],e)}ES.Definition={type:"Extent",metadata:{},params:[{name:"field",type:"field",required:!0}]};Be(ES,de,{transform(e,t){const n=this.value,r=e.field,i=t.changed()||t.modified(r.fields)||e.modified("field");let s=n[0],a=n[1];if((i||s==null)&&(s=1/0,a=-1/0),t.visit(i?t.SOURCE:t.ADD,o=>{const l=Gr(r(o));l!=null&&(la&&(a=l))}),!Number.isFinite(s)||!Number.isFinite(a)){let o=zn(r);o&&(o=` for field "${o}"`),t.dataflow.warn(`Infinite extent${o}: [${s}, ${a}]`),s=a=void 0}this.value=[s,a]}});function AS(e,t){gn.call(this,e),this.parent=t,this.count=0}Be(AS,gn,{connect(e){return this.detachSubflow=e.detachSubflow,this.targets().add(e),e.source=this},add(e){this.count+=1,this.value.add.push(e)},rem(e){this.count-=1,this.value.rem.push(e)},mod(e){this.value.mod.push(e)},init(e){this.value.init(e,e.NO_SOURCE)},evaluate(){return this.value}});function rb(e){de.call(this,{},e),this._keys=xh();const t=this._targets=[];t.active=0,t.forEach=n=>{for(let r=0,i=t.active;rr&&r.count>0);this.initTargets(n)}},initTargets(e){const t=this._targets,n=t.length,r=e?e.length:0;let i=0;for(;ithis.subflow(l,i,t);return this._group=e.group||{},this.initTargets(),t.visit(t.REM,l=>{const u=dt(l),c=s.get(u);c!==void 0&&(s.delete(u),o(c).rem(l))}),t.visit(t.ADD,l=>{const u=r(l);s.set(dt(l),u),o(u).add(l)}),a||t.modified(r.fields)?t.visit(t.MOD,l=>{const u=dt(l),c=s.get(u),f=r(l);c===f?o(f).mod(l):(s.set(u,f),o(c).rem(l),o(f).add(l))}):t.changed(t.MOD)&&t.visit(t.MOD,l=>{o(s.get(dt(l))).mod(l)}),a&&t.visit(t.REFLOW,l=>{const u=dt(l),c=s.get(u),f=r(l);c!==f&&(s.set(u,f),o(c).rem(l),o(f).add(l))}),t.clean()?n.runAfter(()=>{this.clean(),s.clean()}):s.empty>n.cleanThreshold&&n.runAfter(s.clean),t}});function QO(e){gn.call(this,null,qZ,e)}Be(QO,gn);function qZ(e){return this.value&&!e.modified()?this.value:Se(e.name)?He(e.name).map(t=>Ns(t)):Ns(e.name,e.as)}function kS(e){de.call(this,xh(),e)}kS.Definition={type:"Filter",metadata:{changes:!0},params:[{name:"expr",type:"expr",required:!0}]};Be(kS,de,{transform(e,t){const n=t.dataflow,r=this.value,i=t.fork(),s=i.add,a=i.rem,o=i.mod,l=e.expr;let u=!0;t.visit(t.REM,f=>{const d=dt(f);r.has(d)?r.delete(d):a.push(f)}),t.visit(t.ADD,f=>{l(f,e)?s.push(f):r.set(dt(f),1)});function c(f){const d=dt(f),h=l(f,e),p=r.get(d);h&&p?(r.delete(d),s.push(f)):!h&&!p?(r.set(d,1),a.push(f)):u&&h&&!p&&o.push(f)}return t.visit(t.MOD,c),e.modified()&&(u=!1,t.visit(t.REFLOW,c)),r.empty>n.cleanThreshold&&n.runAfter(r.clean),i}});function SS(e){de.call(this,[],e)}SS.Definition={type:"Flatten",metadata:{generates:!0},params:[{name:"fields",type:"field",array:!0,required:!0},{name:"index",type:"string"},{name:"as",type:"string",array:!0}]};Be(SS,de,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.fields,i=KO(r,e.as||[]),s=e.index||null,a=i.length;return n.rem=this.value,t.visit(t.SOURCE,o=>{const l=r.map(p=>p(o)),u=l.reduce((p,g)=>Math.max(p,g.length),0);let c=0,f,d,h;for(;c{for(let c=0,f;ca[r]=n(a,e))}});function e7(e){de.call(this,[],e)}Be(e7,de,{transform(e,t){const n=t.fork(t.ALL),r=e.generator;let i=this.value,s=e.size-i.length,a,o,l;if(s>0){for(a=[];--s>=0;)a.push(l=nn(r(e))),i.push(l);n.add=n.add.length?n.materialize(n.ADD).add.concat(a):a}else o=i.slice(0,-s),n.rem=n.rem.length?n.materialize(n.REM).rem.concat(o):o,i=i.slice(-s);return n.source=this.value=i,n}});const pm={value:"value",median:CN,mean:kV,min:Iw,max:wc},WZ=[];function FS(e){de.call(this,[],e)}FS.Definition={type:"Impute",metadata:{changes:!0},params:[{name:"field",type:"field",required:!0},{name:"key",type:"field",required:!0},{name:"keyvals",array:!0},{name:"groupby",type:"field",array:!0},{name:"method",type:"enum",default:"value",values:["value","mean","median","max","min"]},{name:"value",default:0}]};function HZ(e){var t=e.method||pm.value,n;if(pm[t]==null)ye("Unrecognized imputation method: "+t);else return t===pm.value?(n=e.value!==void 0?e.value:0,()=>n):pm[t]}function GZ(e){const t=e.field;return n=>n?t(n):NaN}Be(FS,de,{transform(e,t){var n=t.fork(t.ALL),r=HZ(e),i=GZ(e),s=zn(e.field),a=zn(e.key),o=(e.groupby||[]).map(zn),l=YZ(t.source,e.groupby,e.key,e.keyvals),u=[],c=this.value,f=l.domain.length,d,h,p,g,v,y,b,_,x,w;for(v=0,_=l.length;v<_;++v)for(d=l[v],p=d.values,h=NaN,b=0;by(v),s=[],a=r?r.slice():[],o={},l={},u,c,f,d,h,p,g,v;for(a.forEach((y,b)=>o[y]=b+1),d=0,g=e.length;dn.add(s))):(i=n.value=n.value||this.init(e),t.visit(t.REM,s=>n.rem(s)),t.visit(t.ADD,s=>n.add(s))),n.changes(),t.visit(t.SOURCE,s=>{Tt(s,i[n.cellkey(s)].tuple)}),t.reflow(r).modifies(this._outputs)},changes(){const e=this._adds,t=this._mods;let n,r;for(n=0,r=this._alen;n{const p=rS(h,a)[o],g=e.counts?h.length:1,v=c||io(h);nb(p,v,f,d).forEach(y=>{const b={};for(let _=0;_(this._pending=He(i.data),s=>s.touch(this)))}:n.request(e.url,e.format).then(r=>C_(this,t,He(r.data)))}});function XZ(e){return e.modified("async")&&!(e.modified("values")||e.modified("url")||e.modified("format"))}function C_(e,t,n){n.forEach(nn);const r=t.fork(t.NO_FIELDS&t.NO_SOURCE);return r.rem=e.value,e.value=r.source=r.add=n,e._pending=null,r.rem.length&&r.clean(!0),r}function TS(e){de.call(this,{},e)}TS.Definition={type:"Lookup",metadata:{modifies:!0},params:[{name:"index",type:"index",params:[{name:"from",type:"data",required:!0},{name:"key",type:"field",required:!0}]},{name:"values",type:"field",array:!0},{name:"fields",type:"field",array:!0,required:!0},{name:"as",type:"string",array:!0},{name:"default",default:null}]};Be(TS,de,{transform(e,t){const n=e.fields,r=e.index,i=e.values,s=e.default==null?null:e.default,a=e.modified(),o=n.length;let l=a?t.SOURCE:t.ADD,u=t,c=e.as,f,d,h;return i?(d=i.length,o>1&&!c&&ye('Multi-field lookup requires explicit "as" parameter.'),c&&c.length!==o*d&&ye('The "as" parameter has too few output field names.'),c=c||i.map(zn),f=function(p){for(var g=0,v=0,y,b;gt.modified(p.fields)),l|=h?t.MOD:0),t.visit(l,f),u.modifies(c)}});function r7(e){gn.call(this,null,KZ,e)}Be(r7,gn);function KZ(e){if(this.value&&!e.modified())return this.value;const t=e.extents,n=t.length;let r=1/0,i=-1/0,s,a;for(s=0;si&&(i=a[1]);return[r,i]}function i7(e){gn.call(this,null,ZZ,e)}Be(i7,gn);function ZZ(e){return this.value&&!e.modified()?this.value:e.values.reduce((t,n)=>t.concat(n),[])}function s7(e){de.call(this,null,e)}Be(s7,de,{transform(e,t){return this.modified(e.modified()),this.value=e,t.fork(t.NO_SOURCE|t.NO_FIELDS)}});function RS(e){su.call(this,e)}RS.Definition={type:"Pivot",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"field",type:"field",required:!0},{name:"value",type:"field",required:!0},{name:"op",type:"enum",values:d0,default:"sum"},{name:"limit",type:"number",default:0},{name:"key",type:"field"}]};Be(RS,su,{_transform:su.prototype.transform,transform(e,t){return this._transform(JZ(e,t),t)}});function JZ(e,t){const n=e.field,r=e.value,i=(e.op==="count"?"__count__":e.op)||"sum",s=Vr(n).concat(Vr(r)),a=eJ(n,e.limit||0,t);return t.changed()&&e.set("__pivot__",null,null,!0),{key:e.key,groupby:e.groupby,ops:a.map(()=>i),fields:a.map(o=>QZ(o,n,r,s)),as:a.map(o=>o+""),modified:e.modified.bind(e)}}function QZ(e,t,n,r){return Wi(i=>t(i)===e?n(i):NaN,r,e+"")}function eJ(e,t,n){const r={},i=[];return n.visit(n.SOURCE,s=>{const a=e(s);r[a]||(r[a]=1,i.push(a))}),i.sort(_h),t?i.slice(0,t):i}function a7(e){rb.call(this,e)}Be(a7,rb,{transform(e,t){const n=e.subflow,r=e.field,i=s=>this.subflow(dt(s),n,t,s);return(e.modified("field")||r&&t.modified(Vr(r)))&&ye("PreFacet does not support field modification."),this.initTargets(),r?(t.visit(t.MOD,s=>{const a=i(s);r(s).forEach(o=>a.mod(o))}),t.visit(t.ADD,s=>{const a=i(s);r(s).forEach(o=>a.add(nn(o)))}),t.visit(t.REM,s=>{const a=i(s);r(s).forEach(o=>a.rem(o))})):(t.visit(t.MOD,s=>i(s).mod(s)),t.visit(t.ADD,s=>i(s).add(s)),t.visit(t.REM,s=>i(s).rem(s))),t.clean()&&t.runAfter(()=>this.clean()),t}});function NS(e){de.call(this,null,e)}NS.Definition={type:"Project",metadata:{generates:!0,changes:!0},params:[{name:"fields",type:"field",array:!0},{name:"as",type:"string",null:!0,array:!0}]};Be(NS,de,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.fields,i=KO(e.fields,e.as||[]),s=r?(o,l)=>tJ(o,l,r,i):Xy;let a;return this.value?a=this.value:(t=t.addAll(),a=this.value={}),t.visit(t.REM,o=>{const l=dt(o);n.rem.push(a[l]),a[l]=null}),t.visit(t.ADD,o=>{const l=s(o,nn({}));a[dt(o)]=l,n.add.push(l)}),t.visit(t.MOD,o=>{n.mod.push(s(o,a[dt(o)]))}),n}});function tJ(e,t,n,r){for(let i=0,s=n.length;i{const d=Jk(f,u);for(let h=0;h{const s=dt(i);n.rem.push(r[s]),r[s]=null}),t.visit(t.ADD,i=>{const s=Xk(i);r[dt(i)]=s,n.add.push(s)}),t.visit(t.MOD,i=>{const s=r[dt(i)];for(const a in i)s[a]=i[a],n.modifies(a);n.mod.push(s)})),n}});function LS(e){de.call(this,[],e),this.count=0}LS.Definition={type:"Sample",metadata:{},params:[{name:"size",type:"number",default:1e3}]};Be(LS,de,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.modified("size"),i=e.size,s=this.value.reduce((c,f)=>(c[dt(f)]=1,c),{});let a=this.value,o=this.count,l=0;function u(c){let f,d;a.length=l&&(f=a[d],s[dt(f)]&&n.rem.push(f),a[d]=c)),++o}if(t.rem.length&&(t.visit(t.REM,c=>{const f=dt(c);s[f]&&(s[f]=-1,n.rem.push(c)),--o}),a=a.filter(c=>s[dt(c)]!==-1)),(t.rem.length||r)&&a.length{s[dt(c)]||u(c)}),l=-1),r&&a.length>i){const c=a.length-i;for(let f=0;f{s[dt(c)]&&n.mod.push(c)}),t.add.length&&t.visit(t.ADD,u),(t.add.length||l<0)&&(n.add=a.filter(c=>!s[dt(c)])),this.count=o,this.value=n.source=a,n}});function IS(e){de.call(this,null,e)}IS.Definition={type:"Sequence",metadata:{generates:!0,changes:!0},params:[{name:"start",type:"number",required:!0},{name:"stop",type:"number",required:!0},{name:"step",type:"number",default:1},{name:"as",type:"string",default:"data"}]};Be(IS,de,{transform(e,t){if(this.value&&!e.modified())return;const n=t.materialize().fork(t.MOD),r=e.as||"data";return n.rem=this.value?t.rem.concat(this.value):t.rem,this.value=ts(e.start,e.stop,e.step||1).map(i=>{const s={};return s[r]=i,nn(s)}),n.add=t.add.concat(this.value),n}});function u7(e){de.call(this,null,e),this.modified(!0)}Be(u7,de,{transform(e,t){return this.value=t.source,t.changed()?t.fork(t.NO_SOURCE|t.NO_FIELDS):t.StopPropagation}});function PS(e){de.call(this,null,e)}const c7=["unit0","unit1"];PS.Definition={type:"TimeUnit",metadata:{modifies:!0},params:[{name:"field",type:"field",required:!0},{name:"interval",type:"boolean",default:!0},{name:"units",type:"enum",values:zk,array:!0},{name:"step",type:"number",default:1},{name:"maxbins",type:"number",default:40},{name:"extent",type:"date",array:!0},{name:"timezone",type:"enum",default:"local",values:["local","utc"]},{name:"as",type:"string",array:!0,length:2,default:c7}]};Be(PS,de,{transform(e,t){const n=e.field,r=e.interval!==!1,i=e.timezone==="utc",s=this._floor(e,t),a=(i?Sh:kh)(s.unit).offset,o=e.as||c7,l=o[0],u=o[1],c=s.step;let f=s.start||1/0,d=s.stop||-1/0,h=t.ADD;return(e.modified()||t.changed(t.REM)||t.modified(Vr(n)))&&(t=t.reflow(!0),h=t.SOURCE,f=1/0,d=-1/0),t.visit(h,p=>{const g=n(p);let v,y;g==null?(p[l]=null,r&&(p[u]=null)):(p[l]=v=y=s(g),r&&(p[u]=y=a(v,c)),vd&&(d=y))}),s.start=f,s.stop=d,t.modifies(r?o:l)},_floor(e,t){const n=e.timezone==="utc",{units:r,step:i}=e.units?{units:e.units,step:e.step||1}:eO({extent:e.extent||io(t.materialize(t.SOURCE).source,e.field),maxbins:e.maxbins}),s=jk(r),a=this.value||{},o=(n?HN:WN)(s,i);return o.unit=Xt(s),o.units=s,o.step=i,o.start=a.start,o.stop=a.stop,this.value=o}});function f7(e){de.call(this,xh(),e)}Be(f7,de,{transform(e,t){const n=t.dataflow,r=e.field,i=this.value,s=o=>i.set(r(o),o);let a=!0;return e.modified("field")||t.modified(r.fields)?(i.clear(),t.visit(t.SOURCE,s)):t.changed()?(t.visit(t.REM,o=>i.delete(r(o))),t.visit(t.ADD,s)):a=!1,this.modified(a),i.empty>n.cleanThreshold&&n.runAfter(i.clean),t.fork()}});function d7(e){de.call(this,null,e)}Be(d7,de,{transform(e,t){(!this.value||e.modified("field")||e.modified("sort")||t.changed()||e.sort&&t.modified(e.sort.fields))&&(this.value=(e.sort?t.source.slice().sort(gf(e.sort)):t.source).map(e.field))}});function rJ(e,t,n,r){const i=xg[e](t,n);return{init:i.init||Rl,update:function(s,a){a[r]=i.next(s)}}}const xg={row_number:function(){return{next:e=>e.index+1}},rank:function(){let e;return{init:()=>e=1,next:t=>{const n=t.index,r=t.data;return n&&t.compare(r[n-1],r[n])?e=n+1:e}}},dense_rank:function(){let e;return{init:()=>e=1,next:t=>{const n=t.index,r=t.data;return n&&t.compare(r[n-1],r[n])?++e:e}}},percent_rank:function(){const e=xg.rank(),t=e.next;return{init:e.init,next:n=>(t(n)-1)/(n.data.length-1)}},cume_dist:function(){let e;return{init:()=>e=0,next:t=>{const n=t.data,r=t.compare;let i=t.index;if(e0||ye("ntile num must be greater than zero.");const n=xg.cume_dist(),r=n.next;return{init:n.init,next:i=>Math.ceil(t*r(i))}},lag:function(e,t){return t=+t||1,{next:n=>{const r=n.index-t;return r>=0?e(n.data[r]):null}}},lead:function(e,t){return t=+t||1,{next:n=>{const r=n.index+t,i=n.data;return re(t.data[t.i0])}},last_value:function(e){return{next:t=>e(t.data[t.i1-1])}},nth_value:function(e,t){return t=+t,t>0||ye("nth_value nth must be greater than zero."),{next:n=>{const r=n.i0+(t-1);return rt=null,next:n=>{const r=e(n.data[n.index]);return r!=null?t=r:t}}},next_value:function(e){let t,n;return{init:()=>(t=null,n=-1),next:r=>{const i=r.data;return r.index<=n?t:(n=iJ(e,i,r.index))<0?(n=i.length,t=null):t=e(i[n])}}}};function iJ(e,t,n){for(let r=t.length;nl[g]=1)}h(e.sort),t.forEach((p,g)=>{const v=n[g],y=r[g],b=i[g]||null,_=zn(v),x=UO(p,_,s[g]);if(h(v),a.push(x),Ve(xg,p))o.push(rJ(p,v,y,x));else{if(v==null&&p!=="count"&&ye("Null aggregate field specified."),p==="count"){c.push(x);return}d=!1;let w=u[_];w||(w=u[_]=[],w.field=v,f.push(w)),w.push(qO(p,b,x))}}),(c.length||f.length)&&(this.cell=aJ(f,c,d)),this.inputs=Object.keys(l)}const p7=h7.prototype;p7.init=function(){this.windows.forEach(e=>e.init()),this.cell&&this.cell.init()};p7.update=function(e,t){const n=this.cell,r=this.windows,i=e.data,s=r&&r.length;let a;if(n){for(a=e.p0;aHO(l,l.field));const r={num:0,agg:null,store:!1,count:t};if(!n)for(var i=e.length,s=r.agg=Array(i),a=0;athis.group(i(o));let a=this.state;(!a||n)&&(a=this.state=new h7(e)),n||t.modified(a.inputs)?(this.value={},t.visit(t.SOURCE,o=>s(o).add(o))):(t.visit(t.REM,o=>s(o).remove(o)),t.visit(t.ADD,o=>s(o).add(o)));for(let o=0,l=this._mlen;o0&&!i(s[n],s[n-1])&&(e.i0=t.left(s,s[n])),r1?0:e<-1?Pd:Math.acos(e)}function f4(e){return e>=1?nv:e<=-1?-nv:Math.asin(e)}const Xw=Math.PI,Kw=2*Xw,ec=1e-6,hJ=Kw-ec;function m7(e){this._+=e[0];for(let t=1,n=e.length;t=0))throw new Error(`invalid digits: ${e}`);if(t>15)return m7;const n=10**t;return function(r){this._+=r[0];for(let i=1,s=r.length;iec)if(!(Math.abs(f*l-u*c)>ec)||!s)this._append`L${this._x1=t},${this._y1=n}`;else{let h=r-a,p=i-o,g=l*l+u*u,v=h*h+p*p,y=Math.sqrt(g),b=Math.sqrt(d),_=s*Math.tan((Xw-Math.acos((g+d-v)/(2*y*b)))/2),x=_/b,w=_/y;Math.abs(x-1)>ec&&this._append`L${t+x*c},${n+x*f}`,this._append`A${s},${s},0,0,${+(f*h>c*p)},${this._x1=t+w*l},${this._y1=n+w*u}`}}arc(t,n,r,i,s,a){if(t=+t,n=+n,r=+r,a=!!a,r<0)throw new Error(`negative radius: ${r}`);let o=r*Math.cos(i),l=r*Math.sin(i),u=t+o,c=n+l,f=1^a,d=a?i-s:s-i;this._x1===null?this._append`M${u},${c}`:(Math.abs(this._x1-u)>ec||Math.abs(this._y1-c)>ec)&&this._append`L${u},${c}`,r&&(d<0&&(d=d%Kw+Kw),d>hJ?this._append`A${r},${r},0,1,${f},${t-o},${n-l}A${r},${r},0,1,${f},${this._x1=u},${this._y1=c}`:d>ec&&this._append`A${r},${r},0,${+(d>=Xw)},${f},${this._x1=t+r*Math.cos(s)},${this._y1=n+r*Math.sin(s)}`)}rect(t,n,r,i){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${r=+r}v${+i}h${-r}Z`}toString(){return this._}};function ib(){return new zS}ib.prototype=zS.prototype;function sb(e){let t=3;return e.digits=function(n){if(!arguments.length)return t;if(n==null)t=null;else{const r=Math.floor(n);if(!(r>=0))throw new RangeError(`invalid digits: ${n}`);t=r}return e},()=>new zS(t)}function gJ(e){return e.innerRadius}function mJ(e){return e.outerRadius}function vJ(e){return e.startAngle}function yJ(e){return e.endAngle}function bJ(e){return e&&e.padAngle}function _J(e,t,n,r,i,s,a,o){var l=n-e,u=r-t,c=a-i,f=o-s,d=f*l-c*u;if(!(d*dT*T+$*$&&(k=M,C=N),{cx:k,cy:C,x01:-c,y01:-f,x11:k*(i/w-1),y11:C*(i/w-1)}}function xJ(){var e=gJ,t=mJ,n=rn(0),r=null,i=vJ,s=yJ,a=bJ,o=null,l=sb(u);function u(){var c,f,d=+e.apply(this,arguments),h=+t.apply(this,arguments),p=i.apply(this,arguments)-nv,g=s.apply(this,arguments)-nv,v=c4(g-p),y=g>p;if(o||(o=c=l()),hUr))o.moveTo(0,0);else if(v>g7-Ur)o.moveTo(h*qu(p),h*Ma(p)),o.arc(0,0,h,p,g,!y),d>Ur&&(o.moveTo(d*qu(g),d*Ma(g)),o.arc(0,0,d,g,p,y));else{var b=p,_=g,x=p,w=g,A=v,E=v,k=a.apply(this,arguments)/2,C=k>Ur&&(r?+r.apply(this,arguments):dc(d*d+h*h)),M=$_(c4(h-d)/2,+n.apply(this,arguments)),N=M,P=M,I,T;if(C>Ur){var $=f4(C/d*Ma(k)),L=f4(C/h*Ma(k));(A-=$*2)>Ur?($*=y?1:-1,x+=$,w-=$):(A=0,x=w=(p+g)/2),(E-=L*2)>Ur?(L*=y?1:-1,b+=L,_-=L):(E=0,b=_=(p+g)/2)}var W=h*qu(b),U=h*Ma(b),O=d*qu(w),H=d*Ma(w);if(M>Ur){var G=h*qu(_),J=h*Ma(_),ce=d*qu(x),xe=d*Ma(x),be;if(vUr?P>Ur?(I=gm(ce,xe,W,U,h,P,y),T=gm(G,J,O,H,h,P,y),o.moveTo(I.cx+I.x01,I.cy+I.y01),PUr)||!(A>Ur)?o.lineTo(O,H):N>Ur?(I=gm(O,H,G,J,d,-N,y),T=gm(W,U,ce,xe,d,-N,y),o.lineTo(I.cx+I.x01,I.cy+I.y01),N=h;--p)o.point(_[p],x[p]);o.lineEnd(),o.areaEnd()}y&&(_[d]=+e(v,d,f),x[d]=+t(v,d,f),o.point(r?+r(v,d,f):_[d],n?+n(v,d,f):x[d]))}if(b)return o=null,b+""||null}function c(){return x7().defined(i).curve(a).context(s)}return u.x=function(f){return arguments.length?(e=typeof f=="function"?f:rn(+f),r=null,u):e},u.x0=function(f){return arguments.length?(e=typeof f=="function"?f:rn(+f),u):e},u.x1=function(f){return arguments.length?(r=f==null?null:typeof f=="function"?f:rn(+f),u):r},u.y=function(f){return arguments.length?(t=typeof f=="function"?f:rn(+f),n=null,u):t},u.y0=function(f){return arguments.length?(t=typeof f=="function"?f:rn(+f),u):t},u.y1=function(f){return arguments.length?(n=f==null?null:typeof f=="function"?f:rn(+f),u):n},u.lineX0=u.lineY0=function(){return c().x(e).y(t)},u.lineY1=function(){return c().x(e).y(n)},u.lineX1=function(){return c().x(r).y(t)},u.defined=function(f){return arguments.length?(i=typeof f=="function"?f:rn(!!f),u):i},u.curve=function(f){return arguments.length?(a=f,s!=null&&(o=a(s)),u):a},u.context=function(f){return arguments.length?(f==null?s=o=null:o=a(s=f),u):s},u}const wJ={draw(e,t){const n=dc(t/Pd);e.moveTo(n,0),e.arc(0,0,n,0,g7)}};function EJ(e,t){let n=null,r=sb(i);e=typeof e=="function"?e:rn(e||wJ),t=typeof t=="function"?t:rn(t===void 0?64:+t);function i(){let s;if(n||(n=s=r()),e.apply(this,arguments).draw(n,+t.apply(this,arguments)),s)return n=null,s+""||null}return i.type=function(s){return arguments.length?(e=typeof s=="function"?s:rn(s),i):e},i.size=function(s){return arguments.length?(t=typeof s=="function"?s:rn(+s),i):t},i.context=function(s){return arguments.length?(n=s??null,i):n},i}function au(){}function rv(e,t,n){e._context.bezierCurveTo((2*e._x0+e._x1)/3,(2*e._y0+e._y1)/3,(e._x0+2*e._x1)/3,(e._y0+2*e._y1)/3,(e._x0+4*e._x1+t)/6,(e._y0+4*e._y1+n)/6)}function ab(e){this._context=e}ab.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:rv(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:rv(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function AJ(e){return new ab(e)}function E7(e){this._context=e}E7.prototype={areaStart:au,areaEnd:au,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x2,this._y2),this._context.closePath();break}case 2:{this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break}case 3:{this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4);break}}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x2=e,this._y2=t;break;case 1:this._point=2,this._x3=e,this._y3=t;break;case 2:this._point=3,this._x4=e,this._y4=t,this._context.moveTo((this._x0+4*this._x1+e)/6,(this._y0+4*this._y1+t)/6);break;default:rv(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function kJ(e){return new E7(e)}function A7(e){this._context=e}A7.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+e)/6,r=(this._y0+4*this._y1+t)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:rv(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function SJ(e){return new A7(e)}function k7(e,t){this._basis=new ab(e),this._beta=t}k7.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var e=this._x,t=this._y,n=e.length-1;if(n>0)for(var r=e[0],i=t[0],s=e[n]-r,a=t[n]-i,o=-1,l;++o<=n;)l=o/n,this._basis.point(this._beta*e[o]+(1-this._beta)*(r+l*s),this._beta*t[o]+(1-this._beta)*(i+l*a));this._x=this._y=null,this._basis.lineEnd()},point:function(e,t){this._x.push(+e),this._y.push(+t)}};const CJ=(function e(t){function n(r){return t===1?new ab(r):new k7(r,t)}return n.beta=function(r){return e(+r)},n})(.85);function iv(e,t,n){e._context.bezierCurveTo(e._x1+e._k*(e._x2-e._x0),e._y1+e._k*(e._y2-e._y0),e._x2+e._k*(e._x1-t),e._y2+e._k*(e._y1-n),e._x2,e._y2)}function US(e,t){this._context=e,this._k=(1-t)/6}US.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:iv(this,this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2,this._x1=e,this._y1=t;break;case 2:this._point=3;default:iv(this,e,t);break}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const $J=(function e(t){function n(r){return new US(r,t)}return n.tension=function(r){return e(+r)},n})(0);function qS(e,t){this._context=e,this._k=(1-t)/6}qS.prototype={areaStart:au,areaEnd:au,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x3=e,this._y3=t;break;case 1:this._point=2,this._context.moveTo(this._x4=e,this._y4=t);break;case 2:this._point=3,this._x5=e,this._y5=t;break;default:iv(this,e,t);break}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const FJ=(function e(t){function n(r){return new qS(r,t)}return n.tension=function(r){return e(+r)},n})(0);function WS(e,t){this._context=e,this._k=(1-t)/6}WS.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:iv(this,e,t);break}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const DJ=(function e(t){function n(r){return new WS(r,t)}return n.tension=function(r){return e(+r)},n})(0);function HS(e,t,n){var r=e._x1,i=e._y1,s=e._x2,a=e._y2;if(e._l01_a>Ur){var o=2*e._l01_2a+3*e._l01_a*e._l12_a+e._l12_2a,l=3*e._l01_a*(e._l01_a+e._l12_a);r=(r*o-e._x0*e._l12_2a+e._x2*e._l01_2a)/l,i=(i*o-e._y0*e._l12_2a+e._y2*e._l01_2a)/l}if(e._l23_a>Ur){var u=2*e._l23_2a+3*e._l23_a*e._l12_a+e._l12_2a,c=3*e._l23_a*(e._l23_a+e._l12_a);s=(s*u+e._x1*e._l23_2a-t*e._l12_2a)/c,a=(a*u+e._y1*e._l23_2a-n*e._l12_2a)/c}e._context.bezierCurveTo(r,i,s,a,e._x2,e._y2)}function S7(e,t){this._context=e,this._alpha=t}S7.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){if(e=+e,t=+t,this._point){var n=this._x2-e,r=this._y2-t;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3;default:HS(this,e,t);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const MJ=(function e(t){function n(r){return t?new S7(r,t):new US(r,0)}return n.alpha=function(r){return e(+r)},n})(.5);function C7(e,t){this._context=e,this._alpha=t}C7.prototype={areaStart:au,areaEnd:au,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(e,t){if(e=+e,t=+t,this._point){var n=this._x2-e,r=this._y2-t;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=e,this._y3=t;break;case 1:this._point=2,this._context.moveTo(this._x4=e,this._y4=t);break;case 2:this._point=3,this._x5=e,this._y5=t;break;default:HS(this,e,t);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const TJ=(function e(t){function n(r){return t?new C7(r,t):new qS(r,0)}return n.alpha=function(r){return e(+r)},n})(.5);function $7(e,t){this._context=e,this._alpha=t}$7.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){if(e=+e,t=+t,this._point){var n=this._x2-e,r=this._y2-t;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:HS(this,e,t);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const RJ=(function e(t){function n(r){return t?new $7(r,t):new WS(r,0)}return n.alpha=function(r){return e(+r)},n})(.5);function F7(e){this._context=e}F7.prototype={areaStart:au,areaEnd:au,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(e,t){e=+e,t=+t,this._point?this._context.lineTo(e,t):(this._point=1,this._context.moveTo(e,t))}};function NJ(e){return new F7(e)}function d4(e){return e<0?-1:1}function h4(e,t,n){var r=e._x1-e._x0,i=t-e._x1,s=(e._y1-e._y0)/(r||i<0&&-0),a=(n-e._y1)/(i||r<0&&-0),o=(s*i+a*r)/(r+i);return(d4(s)+d4(a))*Math.min(Math.abs(s),Math.abs(a),.5*Math.abs(o))||0}function p4(e,t){var n=e._x1-e._x0;return n?(3*(e._y1-e._y0)/n-t)/2:t}function F_(e,t,n){var r=e._x0,i=e._y0,s=e._x1,a=e._y1,o=(s-r)/3;e._context.bezierCurveTo(r+o,i+o*t,s-o,a-o*n,s,a)}function sv(e){this._context=e}sv.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:F_(this,this._t0,p4(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){var n=NaN;if(e=+e,t=+t,!(e===this._x1&&t===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,F_(this,p4(this,n=h4(this,e,t)),n);break;default:F_(this,this._t0,n=h4(this,e,t));break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t,this._t0=n}}};function D7(e){this._context=new M7(e)}(D7.prototype=Object.create(sv.prototype)).point=function(e,t){sv.prototype.point.call(this,t,e)};function M7(e){this._context=e}M7.prototype={moveTo:function(e,t){this._context.moveTo(t,e)},closePath:function(){this._context.closePath()},lineTo:function(e,t){this._context.lineTo(t,e)},bezierCurveTo:function(e,t,n,r,i,s){this._context.bezierCurveTo(t,e,r,n,s,i)}};function OJ(e){return new sv(e)}function LJ(e){return new D7(e)}function T7(e){this._context=e}T7.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var e=this._x,t=this._y,n=e.length;if(n)if(this._line?this._context.lineTo(e[0],t[0]):this._context.moveTo(e[0],t[0]),n===2)this._context.lineTo(e[1],t[1]);else for(var r=g4(e),i=g4(t),s=0,a=1;a=0;--t)i[t]=(a[t]-i[t+1])/s[t];for(s[n-1]=(e[n]+i[n-1])/2,t=0;t=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:{if(this._t<=0)this._context.lineTo(this._x,t),this._context.lineTo(e,t);else{var n=this._x*(1-this._t)+e*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,t)}break}}this._x=e,this._y=t}};function PJ(e){return new ob(e,.5)}function BJ(e){return new ob(e,0)}function zJ(e){return new ob(e,1)}function Jl(e,t){if(typeof document<"u"&&document.createElement){const n=document.createElement("canvas");if(n&&n.getContext)return n.width=e,n.height=t,n}return null}const jJ=()=>typeof Image<"u"?Image:null;function mo(e,t){switch(arguments.length){case 0:break;case 1:this.range(e);break;default:this.range(t).domain(e);break}return this}function Eu(e,t){switch(arguments.length){case 0:break;case 1:{typeof e=="function"?this.interpolator(e):this.range(e);break}default:{this.domain(e),typeof t=="function"?this.interpolator(t):this.range(t);break}}return this}const Zw=Symbol("implicit");function GS(){var e=new TF,t=[],n=[],r=Zw;function i(s){let a=e.get(s);if(a===void 0){if(r!==Zw)return r;e.set(s,a=t.push(s)-1)}return n[a%n.length]}return i.domain=function(s){if(!arguments.length)return t.slice();t=[],e=new TF;for(const a of s)e.has(a)||e.set(a,t.push(a)-1);return i},i.range=function(s){return arguments.length?(n=Array.from(s),i):n.slice()},i.unknown=function(s){return arguments.length?(r=s,i):r},i.copy=function(){return GS(t,n).unknown(r)},mo.apply(i,arguments),i}function $h(e,t,n){e.prototype=t.prototype=n,n.constructor=e}function h0(e,t){var n=Object.create(e.prototype);for(var r in t)n[r]=t[r];return n}function Au(){}var jc=.7,Bd=1/jc,ad="\\s*([+-]?\\d+)\\s*",wg="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Za="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",UJ=/^#([0-9a-f]{3,8})$/,qJ=new RegExp(`^rgb\\(${ad},${ad},${ad}\\)$`),WJ=new RegExp(`^rgb\\(${Za},${Za},${Za}\\)$`),HJ=new RegExp(`^rgba\\(${ad},${ad},${ad},${wg}\\)$`),GJ=new RegExp(`^rgba\\(${Za},${Za},${Za},${wg}\\)$`),YJ=new RegExp(`^hsl\\(${wg},${Za},${Za}\\)$`),VJ=new RegExp(`^hsla\\(${wg},${Za},${Za},${wg}\\)$`),m4={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};$h(Au,Eg,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:v4,formatHex:v4,formatHex8:XJ,formatHsl:KJ,formatRgb:y4,toString:y4});function v4(){return this.rgb().formatHex()}function XJ(){return this.rgb().formatHex8()}function KJ(){return R7(this).formatHsl()}function y4(){return this.rgb().formatRgb()}function Eg(e){var t,n;return e=(e+"").trim().toLowerCase(),(t=UJ.exec(e))?(n=t[1].length,t=parseInt(t[1],16),n===6?b4(t):n===3?new gr(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?mm(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?mm(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=qJ.exec(e))?new gr(t[1],t[2],t[3],1):(t=WJ.exec(e))?new gr(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=HJ.exec(e))?mm(t[1],t[2],t[3],t[4]):(t=GJ.exec(e))?mm(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=YJ.exec(e))?w4(t[1],t[2]/100,t[3]/100,1):(t=VJ.exec(e))?w4(t[1],t[2]/100,t[3]/100,t[4]):m4.hasOwnProperty(e)?b4(m4[e]):e==="transparent"?new gr(NaN,NaN,NaN,0):null}function b4(e){return new gr(e>>16&255,e>>8&255,e&255,1)}function mm(e,t,n,r){return r<=0&&(e=t=n=NaN),new gr(e,t,n,r)}function YS(e){return e instanceof Au||(e=Eg(e)),e?(e=e.rgb(),new gr(e.r,e.g,e.b,e.opacity)):new gr}function ou(e,t,n,r){return arguments.length===1?YS(e):new gr(e,t,n,r??1)}function gr(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}$h(gr,ou,h0(Au,{brighter(e){return e=e==null?Bd:Math.pow(Bd,e),new gr(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?jc:Math.pow(jc,e),new gr(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new gr(Ec(this.r),Ec(this.g),Ec(this.b),av(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:_4,formatHex:_4,formatHex8:ZJ,formatRgb:x4,toString:x4}));function _4(){return`#${hc(this.r)}${hc(this.g)}${hc(this.b)}`}function ZJ(){return`#${hc(this.r)}${hc(this.g)}${hc(this.b)}${hc((isNaN(this.opacity)?1:this.opacity)*255)}`}function x4(){const e=av(this.opacity);return`${e===1?"rgb(":"rgba("}${Ec(this.r)}, ${Ec(this.g)}, ${Ec(this.b)}${e===1?")":`, ${e})`}`}function av(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function Ec(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function hc(e){return e=Ec(e),(e<16?"0":"")+e.toString(16)}function w4(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new ta(e,t,n,r)}function R7(e){if(e instanceof ta)return new ta(e.h,e.s,e.l,e.opacity);if(e instanceof Au||(e=Eg(e)),!e)return new ta;if(e instanceof ta)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,i=Math.min(t,n,r),s=Math.max(t,n,r),a=NaN,o=s-i,l=(s+i)/2;return o?(t===s?a=(n-r)/o+(n0&&l<1?0:a,new ta(a,o,l,e.opacity)}function ov(e,t,n,r){return arguments.length===1?R7(e):new ta(e,t,n,r??1)}function ta(e,t,n,r){this.h=+e,this.s=+t,this.l=+n,this.opacity=+r}$h(ta,ov,h0(Au,{brighter(e){return e=e==null?Bd:Math.pow(Bd,e),new ta(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?jc:Math.pow(jc,e),new ta(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*t,i=2*n-r;return new gr(D_(e>=240?e-240:e+120,i,r),D_(e,i,r),D_(e<120?e+240:e-120,i,r),this.opacity)},clamp(){return new ta(E4(this.h),vm(this.s),vm(this.l),av(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=av(this.opacity);return`${e===1?"hsl(":"hsla("}${E4(this.h)}, ${vm(this.s)*100}%, ${vm(this.l)*100}%${e===1?")":`, ${e})`}`}}));function E4(e){return e=(e||0)%360,e<0?e+360:e}function vm(e){return Math.max(0,Math.min(1,e||0))}function D_(e,t,n){return(e<60?t+(n-t)*e/60:e<180?n:e<240?t+(n-t)*(240-e)/60:t)*255}const N7=Math.PI/180,O7=180/Math.PI,lv=18,L7=.96422,I7=1,P7=.82521,B7=4/29,od=6/29,z7=3*od*od,JJ=od*od*od;function j7(e){if(e instanceof Ja)return new Ja(e.l,e.a,e.b,e.opacity);if(e instanceof Go)return U7(e);e instanceof gr||(e=YS(e));var t=N_(e.r),n=N_(e.g),r=N_(e.b),i=M_((.2225045*t+.7168786*n+.0606169*r)/I7),s,a;return t===n&&n===r?s=a=i:(s=M_((.4360747*t+.3850649*n+.1430804*r)/L7),a=M_((.0139322*t+.0971045*n+.7141733*r)/P7)),new Ja(116*i-16,500*(s-i),200*(i-a),e.opacity)}function uv(e,t,n,r){return arguments.length===1?j7(e):new Ja(e,t,n,r??1)}function Ja(e,t,n,r){this.l=+e,this.a=+t,this.b=+n,this.opacity=+r}$h(Ja,uv,h0(Au,{brighter(e){return new Ja(this.l+lv*(e??1),this.a,this.b,this.opacity)},darker(e){return new Ja(this.l-lv*(e??1),this.a,this.b,this.opacity)},rgb(){var e=(this.l+16)/116,t=isNaN(this.a)?e:e+this.a/500,n=isNaN(this.b)?e:e-this.b/200;return t=L7*T_(t),e=I7*T_(e),n=P7*T_(n),new gr(R_(3.1338561*t-1.6168667*e-.4906146*n),R_(-.9787684*t+1.9161415*e+.033454*n),R_(.0719453*t-.2289914*e+1.4052427*n),this.opacity)}}));function M_(e){return e>JJ?Math.pow(e,1/3):e/z7+B7}function T_(e){return e>od?e*e*e:z7*(e-B7)}function R_(e){return 255*(e<=.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055)}function N_(e){return(e/=255)<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)}function QJ(e){if(e instanceof Go)return new Go(e.h,e.c,e.l,e.opacity);if(e instanceof Ja||(e=j7(e)),e.a===0&&e.b===0)return new Go(NaN,0=1?(n=1,t-1):Math.floor(n*t),i=e[r],s=e[r+1],a=r>0?e[r-1]:2*i-s,o=r()=>e;function Y7(e,t){return function(n){return e+n*t}}function tQ(e,t,n){return e=Math.pow(e,n),t=Math.pow(t,n)-e,n=1/n,function(r){return Math.pow(e+r*t,n)}}function cb(e,t){var n=t-e;return n?Y7(e,n>180||n<-180?n-360*Math.round(n/360):n):ub(isNaN(e)?t:e)}function nQ(e){return(e=+e)==1?mr:function(t,n){return n-t?tQ(t,n,e):ub(isNaN(t)?n:t)}}function mr(e,t){var n=t-e;return n?Y7(e,n):ub(isNaN(e)?t:e)}const Qw=(function e(t){var n=nQ(t);function r(i,s){var a=n((i=ou(i)).r,(s=ou(s)).r),o=n(i.g,s.g),l=n(i.b,s.b),u=mr(i.opacity,s.opacity);return function(c){return i.r=a(c),i.g=o(c),i.b=l(c),i.opacity=u(c),i+""}}return r.gamma=e,r})(1);function V7(e){return function(t){var n=t.length,r=new Array(n),i=new Array(n),s=new Array(n),a,o;for(a=0;an&&(s=t.slice(n,s),o[a]?o[a]+=s:o[++a]=s),(r=r[0])===(i=i[0])?o[a]?o[a]+=i:o[++a]=i:(o[++a]=null,l.push({i:a,x:Qs(r,i)})),n=O_.lastIndex;return n180?c+=360:c-u>180&&(u+=360),d.push({i:f.push(i(f)+"rotate(",null,r)-2,x:Qs(u,c)})):c&&f.push(i(f)+"rotate("+c+r)}function o(u,c,f,d){u!==c?d.push({i:f.push(i(f)+"skewX(",null,r)-2,x:Qs(u,c)}):c&&f.push(i(f)+"skewX("+c+r)}function l(u,c,f,d,h,p){if(u!==f||c!==d){var g=h.push(i(h)+"scale(",null,",",null,")");p.push({i:g-4,x:Qs(u,f)},{i:g-2,x:Qs(c,d)})}else(f!==1||d!==1)&&h.push(i(h)+"scale("+f+","+d+")")}return function(u,c){var f=[],d=[];return u=e(u),c=e(c),s(u.translateX,u.translateY,c.translateX,c.translateY,f,d),a(u.rotate,c.rotate,f,d),o(u.skewX,c.skewX,f,d),l(u.scaleX,u.scaleY,c.scaleX,c.scaleY,f,d),u=c=null,function(h){for(var p=-1,g=d.length,v;++pt&&(n=e,e=t,t=n),function(r){return Math.max(e,Math.min(t,r))}}function FQ(e,t,n){var r=e[0],i=e[1],s=t[0],a=t[1];return i2?DQ:FQ,l=u=null,f}function f(d){return d==null||isNaN(d=+d)?s:(l||(l=o(e.map(r),t,n)))(r(a(d)))}return f.invert=function(d){return a(i((u||(u=o(t,e.map(r),Qs)))(d)))},f.domain=function(d){return arguments.length?(e=Array.from(d,nE),c()):e.slice()},f.range=function(d){return arguments.length?(t=Array.from(d),c()):t.slice()},f.rangeRound=function(d){return t=Array.from(d),n=p0,c()},f.clamp=function(d){return arguments.length?(a=d?!0:Ni,c()):a!==Ni},f.interpolate=function(d){return arguments.length?(n=d,c()):n},f.unknown=function(d){return arguments.length?(s=d,f):s},function(d,h){return r=d,i=h,c()}}function s9(){return fb()(Ni,Ni)}function a9(e,t,n,r){var i=iu(e,t,n),s;switch(r=zc(r??",f"),r.type){case"s":{var a=Math.max(Math.abs(e),Math.abs(t));return r.precision==null&&!isNaN(s=TN(i,a))&&(r.precision=s),Pk(r,a)}case"":case"e":case"g":case"p":case"r":{r.precision==null&&!isNaN(s=RN(i,Math.max(Math.abs(e),Math.abs(t))))&&(r.precision=s-(r.type==="e"));break}case"f":case"%":{r.precision==null&&!isNaN(s=MN(i))&&(r.precision=s-(r.type==="%")*2);break}}return zy(r)}function mf(e){var t=e.domain;return e.ticks=function(n){var r=t();return Ow(r[0],r[r.length-1],n??10)},e.tickFormat=function(n,r){var i=t();return a9(i[0],i[i.length-1],n??10,r)},e.nice=function(n){n==null&&(n=10);var r=t(),i=0,s=r.length-1,a=r[i],o=r[s],l,u,c=10;for(o0;){if(u=Lw(a,o,n),u===l)return r[i]=a,r[s]=o,t(r);if(u>0)a=Math.floor(a/u)*u,o=Math.ceil(o/u)*u;else if(u<0)a=Math.ceil(a*u)/u,o=Math.floor(o*u)/u;else break;l=u}return e},e}function o9(){var e=s9();return e.copy=function(){return g0(e,o9())},mo.apply(e,arguments),mf(e)}function l9(e){var t;function n(r){return r==null||isNaN(r=+r)?t:r}return n.invert=n,n.domain=n.range=function(r){return arguments.length?(e=Array.from(r,nE),n):e.slice()},n.unknown=function(r){return arguments.length?(t=r,n):t},n.copy=function(){return l9(e).unknown(t)},e=arguments.length?Array.from(e,nE):[0,1],mf(n)}function u9(e,t){e=e.slice();var n=0,r=e.length-1,i=e[n],s=e[r],a;return sMath.pow(e,t)}function OQ(e){return e===Math.E?Math.log:e===10&&Math.log10||e===2&&Math.log2||(e=Math.log(e),t=>Math.log(t)/e)}function T4(e){return(t,n)=>-e(-t,n)}function JS(e){const t=e(D4,M4),n=t.domain;let r=10,i,s;function a(){return i=OQ(r),s=NQ(r),n()[0]<0?(i=T4(i),s=T4(s),e(MQ,TQ)):e(D4,M4),t}return t.base=function(o){return arguments.length?(r=+o,a()):r},t.domain=function(o){return arguments.length?(n(o),a()):n()},t.ticks=o=>{const l=n();let u=l[0],c=l[l.length-1];const f=c0){for(;d<=h;++d)for(p=1;pc)break;y.push(g)}}else for(;d<=h;++d)for(p=r-1;p>=1;--p)if(g=d>0?p/s(-d):p*s(d),!(gc)break;y.push(g)}y.length*2{if(o==null&&(o=10),l==null&&(l=r===10?"s":","),typeof l!="function"&&(!(r%1)&&(l=zc(l)).precision==null&&(l.trim=!0),l=zy(l)),o===1/0)return l;const u=Math.max(1,r*o/t.ticks().length);return c=>{let f=c/s(Math.round(i(c)));return f*rn(u9(n(),{floor:o=>s(Math.floor(i(o))),ceil:o=>s(Math.ceil(i(o)))})),t}function c9(){const e=JS(fb()).domain([1,10]);return e.copy=()=>g0(e,c9()).base(e.base()),mo.apply(e,arguments),e}function R4(e){return function(t){return Math.sign(t)*Math.log1p(Math.abs(t/e))}}function N4(e){return function(t){return Math.sign(t)*Math.expm1(Math.abs(t))*e}}function QS(e){var t=1,n=e(R4(t),N4(t));return n.constant=function(r){return arguments.length?e(R4(t=+r),N4(t)):t},mf(n)}function f9(){var e=QS(fb());return e.copy=function(){return g0(e,f9()).constant(e.constant())},mo.apply(e,arguments)}function O4(e){return function(t){return t<0?-Math.pow(-t,e):Math.pow(t,e)}}function LQ(e){return e<0?-Math.sqrt(-e):Math.sqrt(e)}function IQ(e){return e<0?-e*e:e*e}function e3(e){var t=e(Ni,Ni),n=1;function r(){return n===1?e(Ni,Ni):n===.5?e(LQ,IQ):e(O4(n),O4(1/n))}return t.exponent=function(i){return arguments.length?(n=+i,r()):n},mf(t)}function t3(){var e=e3(fb());return e.copy=function(){return g0(e,t3()).exponent(e.exponent())},mo.apply(e,arguments),e}function PQ(){return t3.apply(null,arguments).exponent(.5)}function d9(){var e=[],t=[],n=[],r;function i(){var a=0,o=Math.max(1,t.length);for(n=new Array(o-1);++a0?n[o-1]:e[0],o=n?[r[n-1],t]:[r[u-1],r[u]]},a.unknown=function(l){return arguments.length&&(s=l),a},a.thresholds=function(){return r.slice()},a.copy=function(){return h9().domain([e,t]).range(i).unknown(s)},mo.apply(mf(a),arguments)}function p9(){var e=[.5],t=[0,1],n,r=1;function i(s){return s!=null&&s<=s?t[ru(e,s,0,r)]:n}return i.domain=function(s){return arguments.length?(e=Array.from(s),r=Math.min(e.length,t.length-1),i):e.slice()},i.range=function(s){return arguments.length?(t=Array.from(s),r=Math.min(e.length,t.length-1),i):t.slice()},i.invertExtent=function(s){var a=t.indexOf(s);return[e[a-1],e[a]]},i.unknown=function(s){return arguments.length?(n=s,i):n},i.copy=function(){return p9().domain(e).range(t).unknown(n)},mo.apply(i,arguments)}function BQ(e){return new Date(e)}function zQ(e){return e instanceof Date?+e:+new Date(+e)}function n3(e,t,n,r,i,s,a,o,l,u){var c=s9(),f=c.invert,d=c.domain,h=u(".%L"),p=u(":%S"),g=u("%I:%M"),v=u("%I %p"),y=u("%a %d"),b=u("%b %d"),_=u("%B"),x=u("%Y");function w(A){return(l(A)0?r:1:0}const tee="identity",zd="linear",ll="log",m0="pow",v0="sqrt",pb="symlog",Uc="time",qc="utc",Qa="sequential",Fh="diverging",jd="quantile",gb="quantize",mb="threshold",o3="ordinal",iE="point",_9="band",l3="bin-ordinal",ur="continuous",y0="discrete",b0="discretizing",zs="interpolating",u3="temporal";function nee(e){return function(t){let n=t[0],r=t[1],i;return r=r&&n[l]<=i&&(s<0&&(s=l),a=l);if(!(s<0))return r=e.invertExtent(n[s]),i=e.invertExtent(n[a]),[r[0]===void 0?r[1]:r[0],i[1]===void 0?i[0]:i[1]]}}function c3(){const e=GS().unknown(void 0),t=e.domain,n=e.range;let r=[0,1],i,s,a=!1,o=0,l=0,u=.5;delete e.unknown;function c(){const f=t().length,d=r[1]g+i*y);return n(d?v.reverse():v)}return e.domain=function(f){return arguments.length?(t(f),c()):t()},e.range=function(f){return arguments.length?(r=[+f[0],+f[1]],c()):r.slice()},e.rangeRound=function(f){return r=[+f[0],+f[1]],a=!0,c()},e.bandwidth=function(){return s},e.step=function(){return i},e.round=function(f){return arguments.length?(a=!!f,c()):a},e.padding=function(f){return arguments.length?(l=Math.max(0,Math.min(1,f)),o=l,c()):o},e.paddingInner=function(f){return arguments.length?(o=Math.max(0,Math.min(1,f)),c()):o},e.paddingOuter=function(f){return arguments.length?(l=Math.max(0,Math.min(1,f)),c()):l},e.align=function(f){return arguments.length?(u=Math.max(0,Math.min(1,f)),c()):u},e.invertRange=function(f){if(f[0]==null||f[1]==null)return;const d=r[1]r[1-d])))return y=Math.max(0,ru(h,g)-1),b=g===v?y:ru(h,v)-1,g-h[y]>s+1e-10&&++y,d&&(_=y,y=p-b,b=p-_),y>b?void 0:t().slice(y,b+1)},e.invert=function(f){const d=e.invertRange([f,f]);return d&&d[0]},e.copy=function(){return c3().domain(t()).range(r).round(a).paddingInner(o).paddingOuter(l).align(u)},c()}function x9(e){const t=e.copy;return e.padding=e.paddingOuter,delete e.paddingInner,e.copy=function(){return x9(t())},e}function iee(){return x9(c3().paddingInner(1))}var see=Array.prototype.map;function aee(e){return see.call(e,Gr)}const oee=Array.prototype.slice;function w9(){let e=[],t=[];function n(r){return r==null||r!==r?void 0:t[(ru(e,r)-1)%t.length]}return n.domain=function(r){return arguments.length?(e=aee(r),n):e.slice()},n.range=function(r){return arguments.length?(t=oee.call(r),n):t.slice()},n.tickFormat=function(r,i){return a9(e[0],Xt(e),r??10,i)},n.copy=function(){return w9().domain(n.domain()).range(n.range())},n}const fv=new Map,E9=Symbol("vega_scale");function A9(e){return e[E9]=!0,e}function L4(e){return e&&e[E9]===!0}function lee(e,t,n){const r=function(){const s=t();return s.invertRange||(s.invertRange=s.invert?nee(s):s.invertExtent?ree(s):void 0),s.type=e,A9(s)};return r.metadata=da(He(n)),r}function tn(e,t,n){return arguments.length>1?(fv.set(e,lee(e,t,n)),this):k9(e)?fv.get(e):void 0}tn(tee,l9);tn(zd,o9,ur);tn(ll,c9,[ur,ll]);tn(m0,t3,ur);tn(v0,PQ,ur);tn(pb,f9,ur);tn(Uc,jQ,[ur,u3]);tn(qc,UQ,[ur,u3]);tn(Qa,r3,[ur,zs]);tn(`${Qa}-${zd}`,r3,[ur,zs]);tn(`${Qa}-${ll}`,g9,[ur,zs,ll]);tn(`${Qa}-${m0}`,i3,[ur,zs]);tn(`${Qa}-${v0}`,qQ,[ur,zs]);tn(`${Qa}-${pb}`,m9,[ur,zs]);tn(`${Fh}-${zd}`,v9,[ur,zs]);tn(`${Fh}-${ll}`,y9,[ur,zs,ll]);tn(`${Fh}-${m0}`,s3,[ur,zs]);tn(`${Fh}-${v0}`,WQ,[ur,zs]);tn(`${Fh}-${pb}`,b9,[ur,zs]);tn(jd,d9,[b0,jd]);tn(gb,h9,b0);tn(mb,p9,b0);tn(l3,w9,[y0,b0]);tn(o3,GS,y0);tn(_9,c3,y0);tn(iE,iee,y0);function k9(e){return fv.has(e)}function vf(e,t){const n=fv.get(e);return n&&n.metadata[t]}function f3(e){return vf(e,ur)}function Ud(e){return vf(e,y0)}function sE(e){return vf(e,b0)}function S9(e){return vf(e,ll)}function uee(e){return vf(e,u3)}function C9(e){return vf(e,zs)}function $9(e){return vf(e,jd)}const cee=["clamp","base","constant","exponent"];function F9(e,t){const n=t[0],r=Xt(t)-n;return function(i){return e(n+i*r)}}function vb(e,t,n){return ZS(d3(t||"rgb",n),e)}function D9(e,t){const n=new Array(t),r=t+1;for(let i=0;ie[o]?a[o](e[o]()):0),a)}function d3(e,t){const n=SQ[fee(e)];return t!=null&&n&&n.gamma?n.gamma(t):n}function fee(e){return"interpolate"+e.toLowerCase().split("-").map(t=>t[0].toUpperCase()+t.slice(1)).join("")}const dee={blues:"cfe1f2bed8eca8cee58fc1de74b2d75ba3cf4592c63181bd206fb2125ca40a4a90",greens:"d3eecdc0e6baabdda594d3917bc77d60ba6c46ab5e329a512089430e7735036429",greys:"e2e2e2d4d4d4c4c4c4b1b1b19d9d9d8888887575756262624d4d4d3535351e1e1e",oranges:"fdd8b3fdc998fdb87bfda55efc9244f87f2cf06b18e4580bd14904b93d029f3303",purples:"e2e1efd4d4e8c4c5e0b4b3d6a3a0cc928ec3827cb97566ae684ea25c3696501f8c",reds:"fdc9b4fcb49afc9e80fc8767fa7051f6573fec3f2fdc2a25c81b1db21218970b13",blueGreen:"d5efedc1e8e0a7ddd18bd2be70c6a958ba9144ad77319c5d2089460e7736036429",bluePurple:"ccddecbad0e4a8c2dd9ab0d4919cc98d85be8b6db28a55a6873c99822287730f71",greenBlue:"d3eecec5e8c3b1e1bb9bd8bb82cec269c2ca51b2cd3c9fc7288abd1675b10b60a1",orangeRed:"fddcaffdcf9bfdc18afdad77fb9562f67d53ee6545e24932d32d1ebf130da70403",purpleBlue:"dbdaebc8cee4b1c3de97b7d87bacd15b9fc93a90c01e7fb70b70ab056199045281",purpleBlueGreen:"dbd8eac8cee4b0c3de93b7d872acd1549fc83892bb1c88a3097f8702736b016353",purpleRed:"dcc9e2d3b3d7ce9eccd186c0da6bb2e14da0e23189d91e6fc61159ab07498f023a",redPurple:"fccfccfcbec0faa9b8f98faff571a5ec539ddb3695c41b8aa908808d0179700174",yellowGreen:"e4f4acd1eca0b9e2949ed68880c97c62bb6e47aa5e3297502083440e723b036034",yellowOrangeBrown:"feeaa1fedd84fecc63feb746fca031f68921eb7215db5e0bc54c05ab3d038f3204",yellowOrangeRed:"fee087fed16ffebd59fea849fd903efc7335f9522bee3423de1b20ca0b22af0225",blueOrange:"134b852f78b35da2cb9dcae1d2e5eff2f0ebfce0bafbbf74e8932fc5690d994a07",brownBlueGreen:"704108a0651ac79548e3c78af3e6c6eef1eac9e9e48ed1c74da79e187a72025147",purpleGreen:"5b1667834792a67fb6c9aed3e6d6e8eff0efd9efd5aedda971bb75368e490e5e29",purpleOrange:"4114696647968f83b7b9b4d6dadbebf3eeeafce0bafbbf74e8932fc5690d994a07",redBlue:"8c0d25bf363adf745ef4ae91fbdbc9f2efeed2e5ef9dcae15da2cb2f78b3134b85",redGrey:"8c0d25bf363adf745ef4ae91fcdccbfaf4f1e2e2e2c0c0c0969696646464343434",yellowGreenBlue:"eff9bddbf1b4bde5b594d5b969c5be45b4c22c9ec02182b82163aa23479c1c3185",redYellowBlue:"a50026d4322cf16e43fcac64fedd90faf8c1dcf1ecabd6e875abd04a74b4313695",redYellowGreen:"a50026d4322cf16e43fcac63fedd8df9f7aed7ee8ea4d86e64bc6122964f006837",pinkYellowGreen:"8e0152c0267edd72adf0b3d6faddedf5f3efe1f2cab6de8780bb474f9125276419",spectral:"9e0142d13c4bf0704afcac63fedd8dfbf8b0e0f3a1a9dda269bda94288b55e4fa2",viridis:"440154470e61481a6c482575472f7d443a834144873d4e8a39568c35608d31688e2d708e2a788e27818e23888e21918d1f988b1fa08822a8842ab07f35b77943bf7154c56866cc5d7ad1518fd744a5db36bcdf27d2e21be9e51afde725",magma:"0000040404130b0924150e3720114b2c11603b0f704a107957157e651a80721f817f24828c29819a2e80a8327db6377ac43c75d1426fde4968e95462f1605df76f5cfa7f5efc8f65fe9f6dfeaf78febf84fece91fddea0fcedaffcfdbf",inferno:"0000040403130c0826170c3b240c4f330a5f420a68500d6c5d126e6b176e781c6d86216b932667a12b62ae305cbb3755c73e4cd24644dd513ae65c30ed6925f3771af8850ffb9506fca50afcb519fac62df6d645f2e661f3f484fcffa4",plasma:"0d088723069033059742039d5002a25d01a66a00a87801a88405a7900da49c179ea72198b12a90ba3488c33d80cb4779d35171da5a69e16462e76e5bed7953f2834cf68f44fa9a3dfca636fdb32ffec029fcce25f9dc24f5ea27f0f921",cividis:"00205100235800265d002961012b65042e670831690d346b11366c16396d1c3c6e213f6e26426e2c456e31476e374a6e3c4d6e42506e47536d4c566d51586e555b6e5a5e6e5e616e62646f66676f6a6a706e6d717270717573727976737c79747f7c75827f758682768985778c8877908b78938e789691789a94789e9778a19b78a59e77a9a177aea575b2a874b6ab73bbaf71c0b26fc5b66dc9b96acebd68d3c065d8c462ddc85fe2cb5ce7cf58ebd355f0d652f3da4ff7de4cfae249fce647",rainbow:"6e40aa883eb1a43db3bf3cafd83fa4ee4395fe4b83ff576eff6659ff7847ff8c38f3a130e2b72fcfcc36bee044aff05b8ff4576ff65b52f6673af27828ea8d1ddfa319d0b81cbecb23abd82f96e03d82e14c6edb5a5dd0664dbf6e40aa",sinebow:"ff4040fc582af47218e78d0bd5a703bfbf00a7d5038de70b72f41858fc2a40ff402afc5818f4720be78d03d5a700bfbf03a7d50b8de71872f42a58fc4040ff582afc7218f48d0be7a703d5bf00bfd503a7e70b8df41872fc2a58ff4040",turbo:"23171b32204a3e2a71453493493eae4b49c54a53d7485ee44569ee4074f53c7ff8378af93295f72e9ff42ba9ef28b3e926bce125c5d925cdcf27d5c629dcbc2de3b232e9a738ee9d3ff39347f68950f9805afc7765fd6e70fe667cfd5e88fc5795fb51a1f84badf545b9f140c5ec3cd0e637dae034e4d931ecd12ef4c92bfac029ffb626ffad24ffa223ff9821ff8d1fff821dff771cfd6c1af76118f05616e84b14df4111d5380fcb2f0dc0260ab61f07ac1805a313029b0f00950c00910b00",browns:"eedbbdecca96e9b97ae4a865dc9856d18954c7784cc0673fb85536ad44339f3632",tealBlues:"bce4d89dd3d181c3cb65b3c245a2b9368fae347da0306a932c5985",teals:"bbdfdfa2d4d58ac9c975bcbb61b0af4da5a43799982b8b8c1e7f7f127273006667",warmGreys:"dcd4d0cec5c1c0b8b4b3aaa7a59c9998908c8b827f7e7673726866665c5a59504e",goldGreen:"f4d166d5ca60b6c35c98bb597cb25760a6564b9c533f8f4f33834a257740146c36",goldOrange:"f4d166f8be5cf8aa4cf5983bf3852aef701be2621fd65322c54923b142239e3a26",goldRed:"f4d166f6be59f9aa51fc964ef6834bee734ae56249db5247cf4244c43141b71d3e",lightGreyRed:"efe9e6e1dad7d5cbc8c8bdb9bbaea9cd967ddc7b43e15f19df4011dc000b",lightGreyTeal:"e4eaead6dcddc8ced2b7c2c7a6b4bc64b0bf22a6c32295c11f85be1876bc",lightMulti:"e0f1f2c4e9d0b0de9fd0e181f6e072f6c053f3993ef77440ef4a3c",lightOrange:"f2e7daf7d5baf9c499fab184fa9c73f68967ef7860e8645bde515bd43d5b",lightTealBlue:"e3e9e0c0dccf9aceca7abfc859afc0389fb9328dad2f7ca0276b95255988",darkBlue:"3232322d46681a5c930074af008cbf05a7ce25c0dd38daed50f3faffffff",darkGold:"3c3c3c584b37725e348c7631ae8b2bcfa424ecc31ef9de30fff184ffffff",darkGreen:"3a3a3a215748006f4d048942489e4276b340a6c63dd2d836ffeb2cffffaa",darkMulti:"3737371f5287197d8c29a86995ce3fffe800ffffff",darkRed:"3434347036339e3c38cc4037e75d1eec8620eeab29f0ce32ffeb2c"},hee={accent:GQ,category10:HQ,category20:"1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5",category20b:"393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6",category20c:"3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9",dark2:YQ,observable10:VQ,paired:XQ,pastel1:KQ,pastel2:ZQ,set1:JQ,set2:QQ,set3:eee,tableau10:"4c78a8f58518e4575672b7b254a24beeca3bb279a2ff9da69d755dbab0ac",tableau20:"4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5"};function T9(e){if(Se(e))return e;const t=e.length/6|0,n=new Array(t);for(let r=0;rvb(T9(e)));function h3(e,t){return e=e&&e.toLowerCase(),arguments.length>1?(I4[e]=t,this):I4[e]}const p1="symbol",pee="discrete",gee="gradient",mee=e=>Se(e)?e.map(t=>String(t)):String(e),vee=(e,t)=>e[1]-t[1],yee=(e,t)=>t[1]-e[1];function p3(e,t,n){let r;return Qt(t)&&(e.bins&&(t=Math.max(t,e.bins.length)),n!=null&&(t=Math.min(t,Math.floor(u0(e.domain())/n||1)+1))),Ue(t)&&(r=t.step,t=t.interval),We(t)&&(t=e.type===Uc?kh(t):e.type==qc?Sh(t):ye("Only time and utc scales accept interval strings."),r&&(t=t.every(r))),t}function N9(e,t,n){let r=e.range(),i=r[0],s=Xt(r),a=vee;if(i>s&&(r=s,s=i,i=r,a=yee),i=Math.floor(i),s=Math.ceil(s),t=t.map(o=>[o,e(o)]).filter(o=>i<=o[1]&&o[1]<=s).sort(a).map(o=>o[0]),n>0&&t.length>1){const o=[t[0],Xt(t)];for(;t.length>n&&t.length>=3;)t=t.filter((l,u)=>!(u%2));t.length<3&&(t=o)}return t}function g3(e,t){return e.bins?N9(e,e.bins,t):e.ticks?e.ticks(t):e.domain()}function O9(e,t,n,r,i,s){const a=t.type;let o=mee;if(a===Uc||i===Uc)o=e.timeFormat(r);else if(a===qc||i===qc)o=e.utcFormat(r);else if(S9(a)){const l=e.formatFloat(r);if(s||t.bins)o=l;else{const u=L9(t,n,!1);o=c=>u(c)?l(c):""}}else if(t.tickFormat){const l=t.domain();o=e.formatSpan(l[0],l[l.length-1],n,r)}else r&&(o=e.format(r));return o}function L9(e,t,n){const r=g3(e,t),i=e.base(),s=Math.log(i),a=Math.max(1,i*t/r.length),o=l=>{let u=l/Math.pow(i,Math.round(Math.log(l)/s));return u*i1?r[1]-r[0]:r[0],a;for(a=1;aaE[e.type]||e.bins;function B9(e,t,n,r,i,s,a){const o=I9[t.type]&&s!==Uc&&s!==qc?bee(e,t,i):O9(e,t,n,i,s,a);return r===p1&&wee(t)?Eee(o):r===pee?Aee(o):kee(o)}const Eee=e=>(t,n,r)=>{const i=P4(r[n+1],P4(r.max,1/0)),s=B4(t,e),a=B4(i,e);return s&&a?s+" – "+a:a?"< "+a:"≥ "+s},P4=(e,t)=>e??t,Aee=e=>(t,n)=>n?e(t):null,kee=e=>t=>e(t),B4=(e,t)=>Number.isFinite(e)?t(e):null;function See(e){const t=e.domain(),n=t.length-1;let r=+t[0],i=+Xt(t),s=i-r;if(e.type===mb){const a=n?s/n:.1;r-=a,i+=a,s=i-r}return a=>(a-r)/s}function Cee(e,t,n,r){const i=r||t.type;return We(n)&&uee(i)&&(n=n.replace(/%a/g,"%A").replace(/%b/g,"%B")),!n&&i===Uc?e.timeFormat("%A, %d %B %Y, %X"):!n&&i===qc?e.utcFormat("%A, %d %B %Y, %X UTC"):B9(e,t,5,null,n,r,!0)}function z9(e,t,n){n=n||{};const r=Math.max(3,n.maxlen||7),i=Cee(e,t,n.format,n.formatType);if(sE(t.type)){const s=P9(t).slice(1).map(i),a=s.length;return`${a} boundar${a===1?"y":"ies"}: ${s.join(", ")}`}else if(Ud(t.type)){const s=t.domain(),a=s.length,o=a>r?s.slice(0,r-2).map(i).join(", ")+", ending with "+s.slice(-1).map(i):s.map(i).join(", ");return`${a} value${a===1?"":"s"}: ${o}`}else{const s=t.domain();return`values from ${i(s[0])} to ${i(Xt(s))}`}}let j9=0;function $ee(){j9=0}const dv="p_";function m3(e){return e&&e.gradient}function U9(e,t,n){const r=e.gradient;let i=e.id,s=r==="radial"?dv:"";return i||(i=e.id="gradient_"+j9++,r==="radial"?(e.x1=Ta(e.x1,.5),e.y1=Ta(e.y1,.5),e.r1=Ta(e.r1,0),e.x2=Ta(e.x2,.5),e.y2=Ta(e.y2,.5),e.r2=Ta(e.r2,.5),s=dv):(e.x1=Ta(e.x1,0),e.y1=Ta(e.y1,0),e.x2=Ta(e.x2,1),e.y2=Ta(e.y2,0))),t[i]=e,"url("+(n||"")+"#"+s+i+")"}function Ta(e,t){return e??t}function q9(e,t){var n=[],r;return r={gradient:"linear",x1:e?e[0]:0,y1:e?e[1]:0,x2:t?t[0]:1,y2:t?t[1]:0,stops:n,stop:function(i,s){return n.push({offset:i,color:s}),r}}}const z4={basis:{curve:AJ},"basis-closed":{curve:kJ},"basis-open":{curve:SJ},bundle:{curve:CJ,tension:"beta",value:.85},cardinal:{curve:$J,tension:"tension",value:0},"cardinal-open":{curve:DJ,tension:"tension",value:0},"cardinal-closed":{curve:FJ,tension:"tension",value:0},"catmull-rom":{curve:MJ,tension:"alpha",value:.5},"catmull-rom-closed":{curve:TJ,tension:"alpha",value:.5},"catmull-rom-open":{curve:RJ,tension:"alpha",value:.5},linear:{curve:jS},"linear-closed":{curve:NJ},monotone:{horizontal:LJ,vertical:OJ},natural:{curve:IJ},step:{curve:PJ},"step-after":{curve:zJ},"step-before":{curve:BJ}};function v3(e,t,n){var r=Ve(z4,e)&&z4[e],i=null;return r&&(i=r.curve||r[t||"vertical"],r.tension&&n!=null&&(i=i[r.tension](n))),i}const Fee={m:2,l:2,h:1,v:1,z:0,c:6,s:4,q:4,t:2,a:7},Dee=/[mlhvzcsqta]([^mlhvzcsqta]+|$)/gi,Mee=/^[+-]?(([0-9]*\.[0-9]+)|([0-9]+\.)|([0-9]+))([eE][+-]?[0-9]+)?/,Tee=/^((\s+,?\s*)|(,\s*))/,Ree=/^[01]/;function qd(e){const t=[];return(e.match(Dee)||[]).forEach(r=>{let i=r[0];const s=i.toLowerCase(),a=Fee[s],o=Nee(s,a,r.slice(1).trim()),l=o.length;if(l1&&(g=Math.sqrt(g),n*=g,r*=g);const v=d/n,y=f/n,b=-f/r,_=d/r,x=v*o+y*l,w=b*o+_*l,A=v*e+y*t,E=b*e+_*t;let C=1/((A-x)*(A-x)+(E-w)*(E-w))-.25;C<0&&(C=0);let M=Math.sqrt(C);s==i&&(M=-M);const N=.5*(x+A)-M*(E-w),P=.5*(w+E)+M*(A-x),I=Math.atan2(w-P,x-N);let $=Math.atan2(E-P,A-N)-I;$<0&&s===1?$+=Wa:$>0&&s===0&&($-=Wa);const L=Math.ceil(Math.abs($/(ic+.001))),W=[];for(let U=0;U+e}function bm(e,t,n){return Math.max(t,Math.min(e,n))}function G9(){var e=zee,t=jee,n=Uee,r=qee,i=Do(0),s=i,a=i,o=i,l=null;function u(c,f,d){var h,p=f??+e.call(this,c),g=d??+t.call(this,c),v=+n.call(this,c),y=+r.call(this,c),b=Math.min(v,y)/2,_=bm(+i.call(this,c),0,b),x=bm(+s.call(this,c),0,b),w=bm(+a.call(this,c),0,b),A=bm(+o.call(this,c),0,b);if(l||(l=h=ib()),_<=0&&x<=0&&w<=0&&A<=0)l.rect(p,g,v,y);else{var E=p+v,k=g+y;l.moveTo(p+_,g),l.lineTo(E-x,g),l.bezierCurveTo(E-Al*x,g,E,g+Al*x,E,g+x),l.lineTo(E,k-A),l.bezierCurveTo(E,k-Al*A,E-Al*A,k,E-A,k),l.lineTo(p+w,k),l.bezierCurveTo(p+Al*w,k,p,k-Al*w,p,k-w),l.lineTo(p,g+_),l.bezierCurveTo(p,g+Al*_,p+Al*_,g,p+_,g),l.closePath()}if(h)return l=null,h+""||null}return u.x=function(c){return arguments.length?(e=Do(c),u):e},u.y=function(c){return arguments.length?(t=Do(c),u):t},u.width=function(c){return arguments.length?(n=Do(c),u):n},u.height=function(c){return arguments.length?(r=Do(c),u):r},u.cornerRadius=function(c,f,d,h){return arguments.length?(i=Do(c),s=f!=null?Do(f):i,o=d!=null?Do(d):i,a=h!=null?Do(h):s,u):i},u.context=function(c){return arguments.length?(l=c??null,u):l},u}function Y9(){var e,t,n,r,i=null,s,a,o,l;function u(f,d,h){const p=h/2;if(s){var g=o-d,v=f-a;if(g||v){var y=Math.hypot(g,v),b=(g/=y)*l,_=(v/=y)*l,x=Math.atan2(v,g);i.moveTo(a-b,o-_),i.lineTo(f-g*p,d-v*p),i.arc(f,d,p,x-Math.PI,x),i.lineTo(a+b,o+_),i.arc(a,o,l,x,x+Math.PI)}else i.arc(f,d,p,0,Wa);i.closePath()}else s=1;a=f,o=d,l=p}function c(f){var d,h=f.length,p,g=!1,v;for(i==null&&(i=v=ib()),d=0;d<=h;++d)!(de.x||0,w0=e=>e.y||0,Wee=e=>e.width||0,Hee=e=>e.height||0,Gee=e=>(e.x||0)+(e.width||0),Yee=e=>(e.y||0)+(e.height||0),Vee=e=>e.startAngle||0,Xee=e=>e.endAngle||0,Kee=e=>e.padAngle||0,Zee=e=>e.innerRadius||0,Jee=e=>e.outerRadius||0,Qee=e=>e.cornerRadius||0,ete=e=>_0(e.cornerRadiusTopLeft,e.cornerRadius)||0,tte=e=>_0(e.cornerRadiusTopRight,e.cornerRadius)||0,nte=e=>_0(e.cornerRadiusBottomRight,e.cornerRadius)||0,rte=e=>_0(e.cornerRadiusBottomLeft,e.cornerRadius)||0,ite=e=>_0(e.size,64),ste=e=>e.size||1,yb=e=>e.defined!==!1,ate=e=>H9(e.shape||"circle"),ote=xJ().startAngle(Vee).endAngle(Xee).padAngle(Kee).innerRadius(Zee).outerRadius(Jee).cornerRadius(Qee),lte=w7().x(x0).y1(w0).y0(Yee).defined(yb),ute=w7().y(w0).x1(x0).x0(Gee).defined(yb),cte=x7().x(x0).y(w0).defined(yb),fte=G9().x(x0).y(w0).width(Wee).height(Hee).cornerRadius(ete,tte,nte,rte),dte=EJ().type(ate).size(ite),hte=Y9().x(x0).y(w0).defined(yb).size(ste);function y3(e){return e.cornerRadius||e.cornerRadiusTopLeft||e.cornerRadiusTopRight||e.cornerRadiusBottomRight||e.cornerRadiusBottomLeft}function pte(e,t){return ote.context(e)(t)}function gte(e,t){const n=t[0],r=n.interpolate||"linear";return(n.orient==="horizontal"?ute:lte).curve(v3(r,n.orient,n.tension)).context(e)(t)}function mte(e,t){const n=t[0],r=n.interpolate||"linear";return cte.curve(v3(r,n.orient,n.tension)).context(e)(t)}function Dh(e,t,n,r){return fte.context(e)(t,n,r)}function vte(e,t){return(t.mark.shape||t.shape).context(e)(t)}function yte(e,t){return dte.context(e)(t)}function bte(e,t){return hte.context(e)(t)}var V9=1;function X9(){V9=1}function b3(e,t,n){var r=t.clip,i=e._defs,s=t.clip_id||(t.clip_id="clip"+V9++),a=i.clipping[s]||(i.clipping[s]={id:s});return Rt(r)?a.path=r(null):y3(n)?a.path=Dh(null,n,0,0):(a.width=n.width||0,a.height=n.height||0),"url(#"+s+")"}function Qn(e){this.clear(),e&&this.union(e)}Qn.prototype={clone(){return new Qn(this)},clear(){return this.x1=+Number.MAX_VALUE,this.y1=+Number.MAX_VALUE,this.x2=-Number.MAX_VALUE,this.y2=-Number.MAX_VALUE,this},empty(){return this.x1===+Number.MAX_VALUE&&this.y1===+Number.MAX_VALUE&&this.x2===-Number.MAX_VALUE&&this.y2===-Number.MAX_VALUE},equals(e){return this.x1===e.x1&&this.y1===e.y1&&this.x2===e.x2&&this.y2===e.y2},set(e,t,n,r){return nthis.x2&&(this.x2=e),t>this.y2&&(this.y2=t),this},expand(e){return this.x1-=e,this.y1-=e,this.x2+=e,this.y2+=e,this},round(){return this.x1=Math.floor(this.x1),this.y1=Math.floor(this.y1),this.x2=Math.ceil(this.x2),this.y2=Math.ceil(this.y2),this},scale(e){return this.x1*=e,this.y1*=e,this.x2*=e,this.y2*=e,this},translate(e,t){return this.x1+=e,this.x2+=e,this.y1+=t,this.y2+=t,this},rotate(e,t,n){const r=this.rotatedPoints(e,t,n);return this.clear().add(r[0],r[1]).add(r[2],r[3]).add(r[4],r[5]).add(r[6],r[7])},rotatedPoints(e,t,n){var{x1:r,y1:i,x2:s,y2:a}=this,o=Math.cos(e),l=Math.sin(e),u=t-t*o+n*l,c=n-t*l-n*o;return[o*r-l*i+u,l*r+o*i+c,o*r-l*a+u,l*r+o*a+c,o*s-l*i+u,l*s+o*i+c,o*s-l*a+u,l*s+o*a+c]},union(e){return e.x1this.x2&&(this.x2=e.x2),e.y2>this.y2&&(this.y2=e.y2),this},intersect(e){return e.x1>this.x1&&(this.x1=e.x1),e.y1>this.y1&&(this.y1=e.y1),e.x2=e.x2&&this.y1<=e.y1&&this.y2>=e.y2},alignsWith(e){return e&&(this.x1==e.x1||this.x2==e.x2||this.y1==e.y1||this.y2==e.y2)},intersects(e){return e&&!(this.x2e.x2||this.y2e.y2)},contains(e,t){return!(ethis.x2||tthis.y2)},width(){return this.x2-this.x1},height(){return this.y2-this.y1}};function bb(e){this.mark=e,this.bounds=this.bounds||new Qn}function _b(e){bb.call(this,e),this.items=this.items||[]}Be(_b,bb);class K9{constructor(t){this._pending=0,this._loader=t||Gy()}pending(){return this._pending}sanitizeURL(t){const n=this;return W4(n),n._loader.sanitize(t,{context:"href"}).then(r=>(sp(n),r)).catch(()=>(sp(n),null))}loadImage(t){const n=this,r=jJ();return W4(n),n._loader.sanitize(t,{context:"image"}).then(i=>{const s=i.href;if(!s||!r)throw{url:s};const a=new r,o=Ve(i,"crossOrigin")?i.crossOrigin:"anonymous";return o!=null&&(a.crossOrigin=o),a.onload=()=>sp(n),a.onerror=()=>sp(n),a.src=s,a}).catch(i=>(sp(n),{complete:!1,width:0,height:0,src:i&&i.url||""}))}ready(){const t=this;return new Promise(n=>{function r(i){t.pending()?setTimeout(()=>{r(!0)},10):n(i)}r(!1)})}}function W4(e){e._pending+=1}function sp(e){e._pending-=1}function hl(e,t,n){if(t.stroke&&t.opacity!==0&&t.strokeOpacity!==0){const r=t.strokeWidth!=null?+t.strokeWidth:1;e.expand(r+(n?_te(t,r):0))}return e}function _te(e,t){return e.strokeJoin&&e.strokeJoin!=="miter"?0:t}const xte=Wa-1e-8;let xb,g1,m1,pc,oE,v1,lE,uE;const Il=(e,t)=>xb.add(e,t),y1=(e,t)=>Il(g1=e,m1=t),H4=e=>Il(e,xb.y1),G4=e=>Il(xb.x1,e),sc=(e,t)=>oE*e+lE*t,ac=(e,t)=>v1*e+uE*t,B_=(e,t)=>Il(sc(e,t),ac(e,t)),z_=(e,t)=>y1(sc(e,t),ac(e,t));function E0(e,t){return xb=e,t?(pc=t*lu,oE=uE=Math.cos(pc),v1=Math.sin(pc),lE=-v1):(oE=uE=1,pc=v1=lE=0),wte}const wte={beginPath(){},closePath(){},moveTo:z_,lineTo:z_,rect(e,t,n,r){pc?(B_(e+n,t),B_(e+n,t+r),B_(e,t+r),z_(e,t)):(Il(e+n,t+r),y1(e,t))},quadraticCurveTo(e,t,n,r){const i=sc(e,t),s=ac(e,t),a=sc(n,r),o=ac(n,r);Y4(g1,i,a,H4),Y4(m1,s,o,G4),y1(a,o)},bezierCurveTo(e,t,n,r,i,s){const a=sc(e,t),o=ac(e,t),l=sc(n,r),u=ac(n,r),c=sc(i,s),f=ac(i,s);V4(g1,a,l,c,H4),V4(m1,o,u,f,G4),y1(c,f)},arc(e,t,n,r,i,s){if(r+=pc,i+=pc,g1=n*Math.cos(i)+e,m1=n*Math.sin(i)+t,Math.abs(i-r)>xte)Il(e-n,t-n),Il(e+n,t+n);else{const a=u=>Il(n*Math.cos(u)+e,n*Math.sin(u)+t);let o,l;if(a(r),a(i),i!==r)if(r=r%Wa,r<0&&(r+=Wa),i=i%Wa,i<0&&(i+=Wa),ii;++l,o-=ic)a(o);else for(o=r-r%ic+ic,l=0;l<4&&oOee?(c=a*a+o*s,c>=0&&(c=Math.sqrt(c),l=(-a+c)/s,u=(-a-c)/s)):l=.5*o/a,0d)return!1;g>f&&(f=g)}else if(h>0){if(g0?(e.globalAlpha=n,e.fillStyle=Q9(e,t,t.fill),!0):!1}var Ate=[];function Hd(e,t,n){var r=(r=t.strokeWidth)!=null?r:1;return r<=0?!1:(n*=t.strokeOpacity==null?1:t.strokeOpacity,n>0?(e.globalAlpha=n,e.strokeStyle=Q9(e,t,t.stroke),e.lineWidth=r,e.lineCap=t.strokeCap||"butt",e.lineJoin=t.strokeJoin||"miter",e.miterLimit=t.strokeMiterLimit||10,e.setLineDash&&(e.setLineDash(t.strokeDash||Ate),e.lineDashOffset=t.strokeDashOffset||0),!0):!1)}function kte(e,t){return e.zindex-t.zindex||e.index-t.index}function w3(e){if(!e.zdirty)return e.zitems;var t=e.items,n=[],r,i,s;for(i=0,s=t.length;i=0;)if(r=t(n[i]))return r;if(n===s){for(n=e.items,i=n.length;--i>=0;)if(!n[i].zindex&&(r=t(n[i])))return r}return null}function E3(e){return function(t,n,r){pa(n,i=>{(!r||r.intersects(i.bounds))&&eL(e,t,i,i)})}}function Ste(e){return function(t,n,r){n.items.length&&(!r||r.intersects(n.bounds))&&eL(e,t,n.items[0],n.items)}}function eL(e,t,n,r){var i=n.opacity==null?1:n.opacity;i!==0&&(e(t,r)||(Wd(t,n),n.fill&&hv(t,n,i)&&t.fill(),n.stroke&&Hd(t,n,i)&&t.stroke()))}function wb(e){return e=e||ls,function(t,n,r,i,s,a){return r*=t.pixelRatio,i*=t.pixelRatio,pv(n,o=>{const l=o.bounds;if(!(l&&!l.contains(s,a)||!l)&&e(t,o,r,i,s,a))return o})}}function A0(e,t){return function(n,r,i,s){var a=Array.isArray(r)?r[0]:r,o=t??a.fill,l=a.stroke&&n.isPointInStroke,u,c;return l&&(u=a.strokeWidth,c=a.strokeCap,n.lineWidth=u??1,n.lineCap=c??"butt"),e(n,r)?!1:o&&n.isPointInPath(i,s)||l&&n.isPointInStroke(i,s)}}function A3(e){return wb(A0(e))}function kc(e,t){return"translate("+e+","+t+")"}function k3(e){return"rotate("+e+")"}function Cte(e,t){return"scale("+e+","+t+")"}function tL(e){return kc(e.x||0,e.y||0)}function $te(e){return kc(e.x||0,e.y||0)+(e.angle?" "+k3(e.angle):"")}function Fte(e){return kc(e.x||0,e.y||0)+(e.angle?" "+k3(e.angle):"")+(e.scaleX||e.scaleY?" "+Cte(e.scaleX||1,e.scaleY||1):"")}function S3(e,t,n){function r(a,o){a("transform",$te(o)),a("d",t(null,o))}function i(a,o){return t(E0(a,o.angle),o),hl(a,o).translate(o.x||0,o.y||0)}function s(a,o){var l=o.x||0,u=o.y||0,c=o.angle||0;a.translate(l,u),c&&a.rotate(c*=lu),a.beginPath(),t(a,o),c&&a.rotate(-c),a.translate(-l,-u)}return{type:e,tag:"path",nested:!1,attr:r,bound:i,draw:E3(s),pick:A3(s),isect:n||_3(s)}}var Dte=S3("arc",pte);function Mte(e,t){for(var n=e[0].orient==="horizontal"?t[1]:t[0],r=e[0].orient==="horizontal"?"y":"x",i=e.length,s=1/0,a,o;--i>=0;)e[i].defined!==!1&&(o=Math.abs(e[i][r]-n),o=0;)if(e[r].defined!==!1&&(i=e[r].x-t[0],s=e[r].y-t[1],a=i*i+s*s,a=0;)if(e[n].defined!==!1&&(r=e[n].x-t[0],i=e[n].y-t[1],s=r*r+i*i,r=e[n].size||1,s.5&&t<1.5?.5-Math.abs(t-1):0}function Lte(e,t){e("transform",tL(t))}function iL(e,t){const n=rL(t);e("d",Dh(null,t,n,n))}function Ite(e,t){e("class","background"),e("aria-hidden",!0),iL(e,t)}function Pte(e,t){e("class","foreground"),e("aria-hidden",!0),t.strokeForeground?iL(e,t):e("d","")}function Bte(e,t,n){const r=t.clip?b3(n,t,t):null;e("clip-path",r)}function zte(e,t){if(!t.clip&&t.items){const n=t.items,r=n.length;for(let i=0;i{const s=i.x||0,a=i.y||0,o=i.strokeForeground,l=i.opacity==null?1:i.opacity;(i.stroke||i.fill)&&l&&(Sg(e,i,s,a),Wd(e,i),i.fill&&hv(e,i,l)&&e.fill(),i.stroke&&!o&&Hd(e,i,l)&&e.stroke()),e.save(),e.translate(s,a),i.clip&&nL(e,i),n&&n.translate(-s,-a),pa(i,u=>{(u.marktype==="group"||r==null||r.includes(u.marktype))&&this.draw(e,u,n,r)}),n&&n.translate(s,a),e.restore(),o&&i.stroke&&l&&(Sg(e,i,s,a),Wd(e,i),Hd(e,i,l)&&e.stroke())})}function Hte(e,t,n,r,i,s){if(t.bounds&&!t.bounds.contains(i,s)||!t.items)return null;const a=n*e.pixelRatio,o=r*e.pixelRatio;return pv(t,l=>{let u,c,f;const d=l.bounds;if(d&&!d.contains(i,s))return;c=l.x||0,f=l.y||0;const h=c+(l.width||0),p=f+(l.height||0),g=l.clip;if(g&&(ih||sp))return;if(e.save(),e.translate(c,f),c=i-c,f=s-f,g&&y3(l)&&!qte(e,l,a,o))return e.restore(),null;const v=l.strokeForeground,y=t.interactive!==!1;return y&&v&&l.stroke&&Ute(e,l,a,o)?(e.restore(),l):(u=pv(l,b=>Gte(b,c,f)?this.pick(b,n,r,c,f):null),!u&&y&&(l.fill||!v&&l.stroke)&&jte(e,l,a,o)&&(u=l),e.restore(),u||null)})}function Gte(e,t,n){return(e.interactive!==!1||e.marktype==="group")&&e.bounds&&e.bounds.contains(t,n)}var Yte={type:"group",tag:"g",nested:!1,attr:Lte,bound:zte,draw:Wte,pick:Hte,isect:Z9,content:Bte,background:Ite,foreground:Pte},Cg={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",version:"1.1"};function $3(e,t){var n=e.image;return(!n||e.url&&e.url!==n.url)&&(n={complete:!1,width:0,height:0},t.loadImage(e.url).then(r=>{e.image=r,e.image.url=e.url})),n}function F3(e,t){return e.width!=null?e.width:!t||!t.width?0:e.aspect!==!1&&e.height?e.height*t.width/t.height:t.width}function D3(e,t){return e.height!=null?e.height:!t||!t.height?0:e.aspect!==!1&&e.width?e.width*t.height/t.width:t.height}function Eb(e,t){return e==="center"?t/2:e==="right"?t:0}function Ab(e,t){return e==="middle"?t/2:e==="bottom"?t:0}function Vte(e,t,n){const r=$3(t,n),i=F3(t,r),s=D3(t,r),a=(t.x||0)-Eb(t.align,i),o=(t.y||0)-Ab(t.baseline,s),l=!r.src&&r.toDataURL?r.toDataURL():r.src||"";e("href",l,Cg["xmlns:xlink"],"xlink:href"),e("transform",kc(a,o)),e("width",i),e("height",s),e("preserveAspectRatio",t.aspect===!1?"none":"xMidYMid")}function Xte(e,t){const n=t.image,r=F3(t,n),i=D3(t,n),s=(t.x||0)-Eb(t.align,r),a=(t.y||0)-Ab(t.baseline,i);return e.set(s,a,s+r,a+i)}function Kte(e,t,n){pa(t,r=>{if(n&&!n.intersects(r.bounds))return;const i=$3(r,this);let s=F3(r,i),a=D3(r,i);if(s===0||a===0)return;let o=(r.x||0)-Eb(r.align,s),l=(r.y||0)-Ab(r.baseline,a),u,c,f,d;r.aspect!==!1&&(c=i.width/i.height,f=r.width/r.height,c===c&&f===f&&c!==f&&(f{if(!(n&&!n.intersects(r.bounds))){var i=r.opacity==null?1:r.opacity;i&&sL(e,r,i)&&(Wd(e,r),e.stroke())}})}function lne(e,t,n,r){return e.isPointInStroke?sL(e,t,1)&&e.isPointInStroke(n,r):!1}var une={type:"rule",tag:"line",nested:!1,attr:sne,bound:ane,draw:one,pick:wb(lne),isect:J9},cne=S3("shape",vte),fne=S3("symbol",yte,x3);const J4=hN();var ss={height:yo,measureWidth:M3,estimateWidth:gv,width:gv,canvas:aL};aL(!0);function aL(e){ss.width=e&&Ql?M3:gv}function gv(e,t){return oL(cu(e,t),yo(e))}function oL(e,t){return~~(.8*e.length*t)}function M3(e,t){return yo(e)<=0||!(t=cu(e,t))?0:lL(t,kb(e))}function lL(e,t){const n=`(${t}) ${e}`;let r=J4.get(n);return r===void 0&&(Ql.font=t,r=Ql.measureText(e).width,J4.set(n,r)),r}function yo(e){return e.fontSize!=null?+e.fontSize||0:11}function uu(e){return e.lineHeight!=null?e.lineHeight:yo(e)+2}function dne(e){return Se(e)?e.length>1?e:e[0]:e}function k0(e){return dne(e.lineBreak&&e.text&&!Se(e.text)?e.text.split(e.lineBreak):e.text)}function T3(e){const t=k0(e);return(Se(t)?t.length-1:0)*uu(e)}function cu(e,t){const n=t==null?"":(t+"").trim();return e.limit>0&&n.length?pne(e,n):n}function hne(e){if(ss.width===M3){const t=kb(e);return n=>lL(n,t)}else if(ss.width===gv){const t=yo(e);return n=>oL(n,t)}else return t=>ss.width(e,t)}function pne(e,t){var n=+e.limit,r=hne(e);if(r(t)>>1,r(t.slice(l))>n?a=l+1:o=l;return i+t.slice(a)}else{for(;a>>1),r(t.slice(0,l))Math.max(d,ss.width(t,h)),0)):f=ss.width(t,c),i==="center"?l-=f/2:i==="right"&&(l-=f),e.set(l+=a,u+=o,l+f,u+r),t.angle&&!n)e.rotate(t.angle*lu,a,o);else if(n===2)return e.rotatedPoints(t.angle*lu,a,o);return e}function vne(e,t,n){pa(t,r=>{var i=r.opacity==null?1:r.opacity,s,a,o,l,u,c,f;if(!(n&&!n.intersects(r.bounds)||i===0||r.fontSize<=0||r.text==null||r.text.length===0)){if(e.font=kb(r),e.textAlign=r.align||"left",s=Sb(r),a=s.x1,o=s.y1,r.angle&&(e.save(),e.translate(a,o),e.rotate(r.angle*lu),a=o=0),a+=r.dx||0,o+=(r.dy||0)+R3(r),c=k0(r),Wd(e,r),Se(c))for(u=uu(r),l=0;lt;)e.removeChild(n[--r]);return e}function pL(e){return"mark-"+e.marktype+(e.role?" role-"+e.role:"")+(e.name?" "+e.name:"")}function Cb(e,t){const n=t.getBoundingClientRect();return[e.clientX-n.left-(t.clientLeft||0),e.clientY-n.top-(t.clientTop||0)]}function Ene(e,t,n,r){var i=e&&e.mark,s,a;if(i&&(s=fs[i.marktype]).tip){for(a=Cb(t,n),a[0]-=r[0],a[1]-=r[1];e=e.mark.group;)a[0]-=e.x||0,a[1]-=e.y||0;e=s.tip(i.items,a)}return e}let L3=class{constructor(t,n){this._active=null,this._handlers={},this._loader=t||Gy(),this._tooltip=n||Ane}initialize(t,n,r){return this._el=t,this._obj=r||null,this.origin(n)}element(){return this._el}canvas(){return this._el&&this._el.firstChild}origin(t){return arguments.length?(this._origin=t||[0,0],this):this._origin.slice()}scene(t){return arguments.length?(this._scene=t,this):this._scene}on(){}off(){}_handlerIndex(t,n,r){for(let i=t?t.length:0;--i>=0;)if(t[i].type===n&&(!r||t[i].handler===r))return i;return-1}handlers(t){const n=this._handlers,r=[];if(t)r.push(...n[this.eventName(t)]);else for(const i in n)r.push(...n[i]);return r}eventName(t){const n=t.indexOf(".");return n<0?t:t.slice(0,n)}handleHref(t,n,r){this._loader.sanitize(r,{context:"href"}).then(i=>{const s=new MouseEvent(t.type,t),a=Pl(null,"a");for(const o in i)a.setAttribute(o,i[o]);a.dispatchEvent(s)}).catch(()=>{})}handleTooltip(t,n,r){if(n&&n.tooltip!=null){n=Ene(n,t,this.canvas(),this._origin);const i=r&&n&&n.tooltip||null;this._tooltip.call(this._obj,this,t,n,i)}}getItemBoundingClientRect(t){const n=this.canvas();if(!n)return;const r=n.getBoundingClientRect(),i=this._origin,s=t.bounds,a=s.width(),o=s.height();let l=s.x1+i[0]+r.left,u=s.y1+i[1]+r.top;for(;t.mark&&(t=t.mark.group);)l+=t.x||0,u+=t.y||0;return{x:l,y:u,width:a,height:o,left:l,top:u,right:l+a,bottom:u+o}}};function Ane(e,t,n,r){e.element().setAttribute("title",r||"")}class C0{constructor(t){this._el=null,this._bgcolor=null,this._loader=new K9(t)}initialize(t,n,r,i,s){return this._el=t,this.resize(n,r,i,s)}element(){return this._el}canvas(){return this._el&&this._el.firstChild}background(t){return arguments.length===0?this._bgcolor:(this._bgcolor=t,this)}resize(t,n,r,i){return this._width=t,this._height=n,this._origin=r||[0,0],this._scale=i||1,this}dirty(){}render(t,n){const r=this;return r._call=function(){r._render(t,n)},r._call(),r._call=null,r}_render(){}renderAsync(t,n){const r=this.render(t,n);return this._ready?this._ready.then(()=>r):Promise.resolve(r)}_load(t,n){var r=this,i=r._loader[t](n);if(!r._ready){const s=r._call;r._ready=r._loader.ready().then(a=>{a&&s(),r._ready=null})}return i}sanitizeURL(t){return this._load("sanitizeURL",t)}loadImage(t){return this._load("loadImage",t)}}const kne="keydown",Sne="keypress",Cne="keyup",gL="dragenter",_1="dragleave",mL="dragover",dE="pointerdown",$ne="pointerup",mv="pointermove",x1="pointerout",vL="pointerover",hE="mousedown",Fne="mouseup",yL="mousemove",vv="mouseout",bL="mouseover",yv="click",Dne="dblclick",Mne="wheel",_L="mousewheel",bv="touchstart",_v="touchmove",xv="touchend",Tne=[kne,Sne,Cne,gL,_1,mL,dE,$ne,mv,x1,vL,hE,Fne,yL,vv,bL,yv,Dne,Mne,_L,bv,_v,xv],pE=mv,Qp=vv,gE=yv;class $0 extends L3{constructor(t,n){super(t,n),this._down=null,this._touch=null,this._first=!0,this._events={},this.events=Tne,this.pointermove=nD([mv,yL],[vL,bL],[x1,vv]),this.dragover=nD([mL],[gL],[_1]),this.pointerout=rD([x1,vv]),this.dragleave=rD([_1])}initialize(t,n,r){return this._canvas=t&&O3(t,"canvas"),[yv,hE,dE,mv,x1,_1].forEach(i=>tD(this,i)),super.initialize(t,n,r)}canvas(){return this._canvas}context(){return this._canvas.getContext("2d")}DOMMouseScroll(t){this.fire(_L,t)}pointerdown(t){this._down=this._active,this.fire(dE,t)}mousedown(t){this._down=this._active,this.fire(hE,t)}click(t){this._down===this._active&&(this.fire(yv,t),this._down=null)}touchstart(t){this._touch=this.pickEvent(t.changedTouches[0]),this._first&&(this._active=this._touch,this._first=!1),this.fire(bv,t,!0)}touchmove(t){this.fire(_v,t,!0)}touchend(t){this.fire(xv,t,!0),this._touch=null}fire(t,n,r){const i=r?this._touch:this._active,s=this._handlers[t];if(n.vegaType=t,t===gE&&i&&i.href?this.handleHref(n,i,i.href):(t===pE||t===Qp)&&this.handleTooltip(n,i,t!==Qp),s)for(let a=0,o=s.length;a=0&&i.splice(s,1),this}pickEvent(t){const n=Cb(t,this._canvas),r=this._origin;return this.pick(this._scene,n[0],n[1],n[0]-r[0],n[1]-r[1])}pick(t,n,r,i,s){const a=this.context();return fs[t.marktype].pick.call(this,a,t,n,r,i,s)}}const Rne=e=>e===bv||e===_v||e===xv?[bv,_v,xv]:[e];function tD(e,t){Rne(t).forEach(n=>Nne(e,n))}function Nne(e,t){const n=e.canvas();n&&!e._events[t]&&(e._events[t]=1,n.addEventListener(t,e[t]?r=>e[t](r):r=>e.fire(t,r)))}function Dp(e,t,n){t.forEach(r=>e.fire(r,n))}function nD(e,t,n){return function(r){const i=this._active,s=this.pickEvent(r);s===i?Dp(this,e,r):((!i||!i.exit)&&Dp(this,n,r),this._active=s,Dp(this,t,r),Dp(this,e,r))}}function rD(e){return function(t){Dp(this,e,t),this._active=null}}function One(){return typeof window<"u"&&window.devicePixelRatio||1}function Lne(e,t,n,r,i,s){const a=typeof HTMLElement<"u"&&e instanceof HTMLElement&&e.parentNode!=null,o=e.getContext("2d"),l=a?One():i;e.width=t*l,e.height=n*l;for(const u in s)o[u]=s[u];return a&&l!==1&&(e.style.width=t+"px",e.style.height=n+"px"),o.pixelRatio=l,o.setTransform(l,0,0,l,l*r[0],l*r[1]),e}class wv extends C0{constructor(t){super(t),this._options={},this._redraw=!1,this._dirty=new Qn,this._tempb=new Qn}initialize(t,n,r,i,s,a){return this._options=a||{},this._canvas=this._options.externalContext?null:Jl(1,1,this._options.type),t&&this._canvas&&(xs(t,0).appendChild(this._canvas),this._canvas.setAttribute("class","marks")),super.initialize(t,n,r,i,s)}resize(t,n,r,i){if(super.resize(t,n,r,i),this._canvas)Lne(this._canvas,this._width,this._height,this._origin,this._scale,this._options.context);else{const s=this._options.externalContext;s||ye("CanvasRenderer is missing a valid canvas or context"),s.scale(this._scale,this._scale),s.translate(this._origin[0],this._origin[1])}return this._redraw=!0,this}canvas(){return this._canvas}context(){return this._options.externalContext||(this._canvas?this._canvas.getContext("2d"):null)}dirty(t){const n=this._tempb.clear().union(t.bounds);let r=t.mark.group;for(;r;)n.translate(r.x||0,r.y||0),r=r.mark.group;this._dirty.union(n)}_render(t,n){const r=this.context(),i=this._origin,s=this._width,a=this._height,o=this._dirty,l=Ine(i,s,a);r.save();const u=this._redraw||o.empty()?(this._redraw=!1,l.expand(1)):Pne(r,l.intersect(o),i);return this.clear(-i[0],-i[1],s,a),this.draw(r,t,u,n),r.restore(),o.clear(),this}draw(t,n,r,i){if(n.marktype!=="group"&&i!=null&&!i.includes(n.marktype))return;const s=fs[n.marktype];n.clip&&Ote(t,n),s.draw.call(this,t,n,r,i),n.clip&&t.restore()}clear(t,n,r,i){const s=this._options,a=this.context();s.type!=="pdf"&&!s.externalContext&&a.clearRect(t,n,r,i),this._bgcolor!=null&&(a.fillStyle=this._bgcolor,a.fillRect(t,n,r,i))}}const Ine=(e,t,n)=>new Qn().set(0,0,t,n).translate(-e[0],-e[1]);function Pne(e,t,n){return t.expand(1).round(),e.pixelRatio%1&&t.scale(e.pixelRatio).round().scale(1/e.pixelRatio),t.translate(-(n[0]%1),-(n[1]%1)),e.beginPath(),e.rect(t.x1,t.y1,t.width(),t.height()),e.clip(),t}class xL extends L3{constructor(t,n){super(t,n);const r=this;r._hrefHandler=j_(r,(i,s)=>{s&&s.href&&r.handleHref(i,s,s.href)}),r._tooltipHandler=j_(r,(i,s)=>{r.handleTooltip(i,s,i.type!==Qp)})}initialize(t,n,r){let i=this._svg;return i&&(i.removeEventListener(gE,this._hrefHandler),i.removeEventListener(pE,this._tooltipHandler),i.removeEventListener(Qp,this._tooltipHandler)),this._svg=i=t&&O3(t,"svg"),i&&(i.addEventListener(gE,this._hrefHandler),i.addEventListener(pE,this._tooltipHandler),i.addEventListener(Qp,this._tooltipHandler)),super.initialize(t,n,r)}canvas(){return this._svg}on(t,n){const r=this.eventName(t),i=this._handlers;if(this._handlerIndex(i[r],t,n)<0){const a={type:t,handler:n,listener:j_(this,n)};(i[r]||(i[r]=[])).push(a),this._svg&&this._svg.addEventListener(r,a.listener)}return this}off(t,n){const r=this.eventName(t),i=this._handlers[r],s=this._handlerIndex(i,t,n);return s>=0&&(this._svg&&this._svg.removeEventListener(r,i[s].listener),i.splice(s,1)),this}}const j_=(e,t)=>n=>{let r=n.target.__data__;r=Array.isArray(r)?r[0]:r,n.vegaType=n.type,t.call(e._obj,n,r)},wL="aria-hidden",I3="aria-label",P3="role",B3="aria-roledescription",EL="graphics-object",z3="graphics-symbol",AL=(e,t,n)=>({[P3]:e,[B3]:t,[I3]:n||void 0}),Bne=da(["axis-domain","axis-grid","axis-label","axis-tick","axis-title","legend-band","legend-entry","legend-gradient","legend-label","legend-title","legend-symbol","title"]),iD={axis:{desc:"axis",caption:Une},legend:{desc:"legend",caption:qne},"title-text":{desc:"title",caption:e=>`Title text '${aD(e)}'`},"title-subtitle":{desc:"subtitle",caption:e=>`Subtitle text '${aD(e)}'`}},sD={ariaRole:P3,ariaRoleDescription:B3,description:I3};function kL(e,t){const n=t.aria===!1;if(e(wL,n||void 0),n||t.description==null)for(const r in sD)e(sD[r],void 0);else{const r=t.mark.marktype;e(I3,t.description),e(P3,t.ariaRole||(r==="group"?EL:z3)),e(B3,t.ariaRoleDescription||`${r} mark`)}}function SL(e){return e.aria===!1?{[wL]:!0}:Bne[e.role]?null:iD[e.role]?jne(e,iD[e.role]):zne(e)}function zne(e){const t=e.marktype,n=t==="group"||t==="text"||e.items.some(r=>r.description!=null&&r.aria!==!1);return AL(n?EL:z3,`${t} mark container`,e.description)}function jne(e,t){try{const n=e.items[0],r=t.caption||(()=>"");return AL(t.role||z3,t.desc,n.description||r(n))}catch{return null}}function aD(e){return He(e.text).join(" ")}function Une(e){const t=e.datum,n=e.orient,r=t.title?CL(e):null,i=e.context,s=i.scales[t.scale].value,a=i.dataflow.locale(),o=s.type;return`${n==="left"||n==="right"?"Y":"X"}-axis`+(r?` titled '${r}'`:"")+` for a ${Ud(o)?"discrete":o} scale with ${z9(a,s,e)}`}function qne(e){const t=e.datum,n=t.title?CL(e):null,r=`${t.type||""} legend`.trim(),i=t.scales,s=Object.keys(i),a=e.context,o=a.scales[i[s[0]]].value,l=a.dataflow.locale();return Hne(r)+(n?` titled '${n}'`:"")+` for ${Wne(s)} with ${z9(l,o,e)}`}function CL(e){try{return He(Xt(e.items).items[0].text).join(" ")}catch{return null}}function Wne(e){return e=e.map(t=>t+(t==="fill"||t==="stroke"?" color":"")),e.length<2?e[0]:e.slice(0,-1).join(", ")+" and "+Xt(e)}function Hne(e){return e.length?e[0].toUpperCase()+e.slice(1):e}const $L=e=>(e+"").replace(/&/g,"&").replace(//g,">"),Gne=e=>$L(e).replace(/"/g,""").replace(/\t/g," ").replace(/\n/g," ").replace(/\r/g," ");function j3(){let e="",t="",n="";const r=[],i=()=>t=n="",s=l=>{t&&(e+=`${t}>${n}`,i()),r.push(l)},a=(l,u)=>(u!=null&&(t+=` ${l}="${Gne(u)}"`),o),o={open(l){s(l),t="<"+l;for(var u=arguments.length,c=new Array(u>1?u-1:0),f=1;f${n}`:"/>"):e+=``,i(),o},attr:a,text:l=>(n+=$L(l),o),toString:()=>e};return o}const FL=e=>DL(j3(),e)+"";function DL(e,t){if(e.open(t.tagName),t.hasAttributes()){const n=t.attributes,r=n.length;for(let i=0;i{c.dirty=n})),!i.zdirty){if(r.exit){a.nested&&i.items.length?(u=i.items[0],u._svg&&this._update(a,u._svg,u)):r._svg&&(u=r._svg.parentNode,u&&u.removeChild(r._svg)),r._svg=null;continue}r=a.nested?i.items[0]:r,r._update!==n&&(!r._svg||!r._svg.ownerSVGElement?(this._dirtyAll=!1,lD(r,n)):this._update(a,r._svg,r),r._update=n)}return!this._dirtyAll}mark(t,n,r,i){if(!this.isDirty(n))return n._svg;const s=this._svg,a=n.marktype,o=fs[a],l=n.interactive===!1?"none":null,u=o.tag==="g",c=uD(n,t,r,"g",s);if(a!=="group"&&i!=null&&!i.includes(a))return xs(c,0),n._svg;c.setAttribute("class",pL(n));const f=SL(n);for(const g in f)oi(c,g,f[g]);u||oi(c,"pointer-events",l),oi(c,"clip-path",n.clip?b3(this,n,n.group):null);let d=null,h=0;const p=g=>{const v=this.isDirty(g),y=uD(g,c,d,o.tag,s);v&&(this._update(o,y,g),u&&Xne(this,y,g,i)),d=y,++h};return o.nested?n.items.length&&p(n.items[0]):pa(n,p),xs(c,h),c}_update(t,n,r){Yo=n,Wr=n.__values__,kL(eg,r),t.attr(eg,r,this);const i=Zne[t.type];i&&i.call(this,t,n,r),Yo&&this.style(Yo,r)}style(t,n){if(n!=null){for(const r in Ev){let i=r==="font"?S0(n):n[r];if(i===Wr[r])continue;const s=Ev[r];i==null?t.removeAttribute(s):(m3(i)&&(i=U9(i,this._defs.gradient,TL())),t.setAttribute(s,i+"")),Wr[r]=i}for(const r in Av)w1(t,Av[r],n[r])}}defs(){const t=this._svg,n=this._defs;let r=n.el,i=0;for(const s in n.gradient)r||(n.el=r=nr(t,ap+1,"defs",tr)),i=Yne(r,n.gradient[s],i);for(const s in n.clipping)r||(n.el=r=nr(t,ap+1,"defs",tr)),i=Vne(r,n.clipping[s],i);r&&(i===0?(t.removeChild(r),n.el=null):xs(r,i))}_clearDefs(){const t=this._defs;t.gradient={},t.clipping={}}}function lD(e,t){for(;e&&e.dirty!==t;e=e.mark.group)if(e.dirty=t,e.mark&&e.mark.dirty!==t)e.mark.dirty=t;else return}function Yne(e,t,n){let r,i,s;if(t.gradient==="radial"){let a=nr(e,n++,"pattern",tr);Bl(a,{id:dv+t.id,viewBox:"0,0,1,1",width:"100%",height:"100%",preserveAspectRatio:"xMidYMid slice"}),a=nr(a,0,"rect",tr),Bl(a,{width:1,height:1,fill:`url(${TL()}#${t.id})`}),e=nr(e,n++,"radialGradient",tr),Bl(e,{id:t.id,fx:t.x1,fy:t.y1,fr:t.r1,cx:t.x2,cy:t.y2,r:t.r2})}else e=nr(e,n++,"linearGradient",tr),Bl(e,{id:t.id,x1:t.x1,x2:t.x2,y1:t.y1,y2:t.y2});for(r=0,i=t.stops.length;r{i=e.mark(t,a,i,r),++s}),xs(t,1+s)}function uD(e,t,n,r,i){let s=e._svg,a;if(!s&&(a=t.ownerDocument,s=Pl(a,r,tr),e._svg=s,e.mark&&(s.__data__=e,s.__values__={fill:"default"},r==="g"))){const o=Pl(a,"path",tr);s.appendChild(o),o.__data__=e;const l=Pl(a,"g",tr);s.appendChild(l),l.__data__=e;const u=Pl(a,"path",tr);s.appendChild(u),u.__data__=e,u.__values__={fill:"default"}}return(s.ownerSVGElement!==i||Kne(s,n))&&t.insertBefore(s,n?n.nextSibling:t.firstChild),s}function Kne(e,t){return e.parentNode&&e.parentNode.childNodes.length>1&&e.previousSibling!=t}let Yo=null,Wr=null;const Zne={group(e,t,n){const r=Yo=t.childNodes[2];Wr=r.__values__,e.foreground(eg,n,this),Wr=t.__values__,Yo=t.childNodes[1],e.content(eg,n,this);const i=Yo=t.childNodes[0];e.background(eg,n,this);const s=n.mark.interactive===!1?"none":null;if(s!==Wr.events&&(oi(r,"pointer-events",s),oi(i,"pointer-events",s),Wr.events=s),n.strokeForeground&&n.stroke){const a=n.fill;oi(r,"display",null),this.style(i,n),oi(i,"stroke",null),a&&(n.fill=null),Wr=r.__values__,this.style(r,n),a&&(n.fill=a),Yo=null}else oi(r,"display","none")},image(e,t,n){n.smooth===!1?(w1(t,"image-rendering","optimizeSpeed"),w1(t,"image-rendering","pixelated")):w1(t,"image-rendering",null)},text(e,t,n){const r=k0(n);let i,s,a,o;Se(r)?(s=r.map(l=>cu(n,l)),i=s.join(` +`),i!==Wr.text&&(xs(t,0),a=t.ownerDocument,o=uu(n),s.forEach((l,u)=>{const c=Pl(a,"tspan",tr);c.__data__=n,c.textContent=l,u&&(c.setAttribute("x",0),c.setAttribute("dy",o)),t.appendChild(c)}),Wr.text=i)):(s=cu(n,r),s!==Wr.text&&(t.textContent=s,Wr.text=s)),oi(t,"font-family",S0(n)),oi(t,"font-size",yo(n)+"px"),oi(t,"font-style",n.fontStyle),oi(t,"font-variant",n.fontVariant),oi(t,"font-weight",n.fontWeight)}};function eg(e,t,n){t!==Wr[e]&&(n?Jne(Yo,e,t,n):oi(Yo,e,t),Wr[e]=t)}function w1(e,t,n){n!==Wr[t]&&(n==null?e.style.removeProperty(t):e.style.setProperty(t,n+""),Wr[t]=n)}function Bl(e,t){for(const n in t)oi(e,n,t[n])}function oi(e,t,n){n!=null?e.setAttribute(t,n):e.removeAttribute(t)}function Jne(e,t,n,r){n!=null?e.setAttributeNS(r,t,n):e.removeAttributeNS(r,t)}function TL(){let e;return typeof window>"u"?"":(e=window.location).hash?e.href.slice(0,-e.hash.length):e.href}class RL extends C0{constructor(t){super(t),this._text=null,this._defs={gradient:{},clipping:{}}}svg(){return this._text}_render(t){const n=j3();n.open("svg",Tt({},Cg,{class:"marks",width:this._width*this._scale,height:this._height*this._scale,viewBox:`0 0 ${this._width} ${this._height}`}));const r=this._bgcolor;return r&&r!=="transparent"&&r!=="none"&&n.open("rect",{width:this._width,height:this._height,fill:r}).close(),n.open("g",ML,{transform:"translate("+this._origin+")"}),this.mark(n,t),n.close(),this.defs(n),this._text=n.close()+"",this}mark(t,n){const r=fs[n.marktype],i=r.tag,s=[kL,r.attr];t.open("g",{class:pL(n),"clip-path":n.clip?b3(this,n,n.group):null},SL(n),{"pointer-events":i!=="g"&&n.interactive===!1?"none":null});const a=o=>{const l=this.href(o);if(l&&t.open("a",l),t.open(i,this.attr(n,o,s,i!=="g"?i:null)),i==="text"){const u=k0(o);if(Se(u)){const c={x:0,dy:uu(o)};for(let f=0;fthis.mark(t,d)),t.close(),u&&f?(c&&(o.fill=null),o.stroke=f,t.open("path",this.attr(n,o,r.foreground,"bgrect")).close(),c&&(o.fill=c)):t.open("path",this.attr(n,o,r.foreground,"bgfore")).close()}t.close(),l&&t.close()};return r.nested?n.items&&n.items.length&&a(n.items[0]):pa(n,a),t.close()}href(t){const n=t.href;let r;if(n){if(r=this._hrefs&&this._hrefs[n])return r;this.sanitizeURL(n).then(i=>{i["xlink:href"]=i.href,i.href=null,(this._hrefs||(this._hrefs={}))[n]=i})}return null}attr(t,n,r,i){const s={},a=(o,l,u,c)=>{s[c||o]=l};return Array.isArray(r)?r.forEach(o=>o(a,n,this)):r(a,n,this),i&&Qne(s,n,t,i,this._defs),s}defs(t){const n=this._defs.gradient,r=this._defs.clipping;if(Object.keys(n).length+Object.keys(r).length!==0){t.open("defs");for(const s in n){const a=n[s],o=a.stops;a.gradient==="radial"?(t.open("pattern",{id:dv+s,viewBox:"0,0,1,1",width:"100%",height:"100%",preserveAspectRatio:"xMidYMid slice"}),t.open("rect",{width:"1",height:"1",fill:"url(#"+s+")"}).close(),t.close(),t.open("radialGradient",{id:s,fx:a.x1,fy:a.y1,fr:a.r1,cx:a.x2,cy:a.y2,r:a.r2})):t.open("linearGradient",{id:s,x1:a.x1,x2:a.x2,y1:a.y1,y2:a.y2});for(let l=0;l!Zs.svgMarkTypes.includes(s));this._svgRenderer.render(t,Zs.svgMarkTypes),this._canvasRenderer.render(t,i)}resize(t,n,r,i){return super.resize(t,n,r,i),this._svgRenderer.resize(t,n,r,i),this._canvasRenderer.resize(t,n,r,i),this}background(t){return Zs.svgOnTop?this._canvasRenderer.background(t):this._svgRenderer.background(t),this}}class NL extends $0{constructor(t,n){super(t,n)}initialize(t,n,r){const i=nr(nr(t,0,"div"),Zs.svgOnTop?0:1,"div");return super.initialize(i,n,r)}}const OL="canvas",LL="hybrid",IL="png",PL="svg",BL="none",zl={Canvas:OL,PNG:IL,SVG:PL,Hybrid:LL,None:BL},Wc={};Wc[OL]=Wc[IL]={renderer:wv,headless:wv,handler:$0};Wc[PL]={renderer:U3,headless:RL,handler:xL};Wc[LL]={renderer:mE,headless:mE,handler:NL};Wc[BL]={};function $b(e,t){return e=String(e||"").toLowerCase(),arguments.length>1?(Wc[e]=t,this):Wc[e]}function zL(e,t,n){const r=[],i=new Qn().union(t),s=e.marktype;return s?jL(e,i,n,r):s==="group"?UL(e,i,n,r):ye("Intersect scene must be mark node or group item.")}function jL(e,t,n,r){if(tre(e,t,n)){const i=e.items,s=e.marktype,a=i.length;let o=0;if(s==="group")for(;o=0;s--)if(n[s]!=r[s])return!1;for(s=n.length-1;s>=0;s--)if(i=n[s],!q3(e[i],t[i],i))return!1;return typeof e==typeof t}function ire(){X9(),$ee()}const Gd="top",na="left",ia="right",fu="bottom",sre="top-left",are="top-right",ore="bottom-left",lre="bottom-right",W3="start",vE="middle",li="end",ure="x",cre="y",Fb="group",H3="axis",G3="title",fre="frame",dre="scope",Y3="legend",GL="row-header",YL="row-footer",VL="row-title",XL="column-header",KL="column-footer",ZL="column-title",hre="padding",pre="symbol",JL="fit",QL="fit-x",eI="fit-y",gre="pad",V3="none",_m="all",yE="each",X3="flush",jl="column",Ul="row";function tI(e){de.call(this,null,e)}Be(tI,de,{transform(e,t){const n=t.dataflow,r=e.mark,i=r.marktype,s=fs[i],a=s.bound;let o=r.bounds,l;if(s.nested)r.items.length&&n.dirty(r.items[0]),o=xm(r,a),r.items.forEach(u=>{u.bounds.clear().union(o)});else if(i===Fb||e.modified())switch(t.visit(t.MOD,u=>n.dirty(u)),o.clear(),r.items.forEach(u=>o.union(xm(u,a))),r.role){case H3:case Y3:case G3:t.reflow()}else l=t.changed(t.REM),t.visit(t.ADD,u=>{o.union(xm(u,a))}),t.visit(t.MOD,u=>{l=l||o.alignsWith(u.bounds),n.dirty(u),o.union(xm(u,a))}),l&&(o.clear(),r.items.forEach(u=>o.union(u.bounds)));return WL(r),t.modifies("bounds")}});function xm(e,t,n){return t(e.bounds.clear(),e,n)}const cD=":vega_identifier:";function K3(e){de.call(this,0,e)}K3.Definition={type:"Identifier",metadata:{modifies:!0},params:[{name:"as",type:"string",required:!0}]};Be(K3,de,{transform(e,t){const n=mre(t.dataflow),r=e.as;let i=n.value;return t.visit(t.ADD,s=>s[r]=s[r]||++i),n.set(this.value=i),t}});function mre(e){return e._signals[cD]||(e._signals[cD]=e.add(0))}function nI(e){de.call(this,null,e)}Be(nI,de,{transform(e,t){let n=this.value;n||(n=t.dataflow.scenegraph().mark(e.markdef,vre(e),e.index),n.group.context=e.context,e.context.group||(e.context.group=n.group),n.source=this.source,n.clip=e.clip,n.interactive=e.interactive,this.value=n);const r=n.marktype===Fb?_b:bb;return t.visit(t.ADD,i=>r.call(i,n)),(e.modified("clip")||e.modified("interactive"))&&(n.clip=e.clip,n.interactive=!!e.interactive,n.zdirty=!0,t.reflow()),n.items=t.source,t}});function vre(e){const t=e.groups,n=e.parent;return t&&t.size===1?t.get(Object.keys(t.object)[0]):t&&n?t.lookup(n):null}function rI(e){de.call(this,null,e)}const fD={parity:e=>e.filter((t,n)=>n%2?t.opacity=0:1),greedy:(e,t)=>{let n;return e.filter((r,i)=>!i||!iI(n.bounds,r.bounds,t)?(n=r,1):r.opacity=0)}},iI=(e,t,n)=>n>Math.max(t.x1-e.x2,e.x1-t.x2,t.y1-e.y2,e.y1-t.y2),dD=(e,t)=>{for(var n=1,r=e.length,i=e[0].bounds,s;n{const t=e.bounds;return t.width()>1&&t.height()>1},bre=(e,t,n)=>{var r=e.range(),i=new Qn;return t===Gd||t===fu?i.set(r[0],-1/0,r[1],1/0):i.set(-1/0,r[0],1/0,r[1]),i.expand(n||1),s=>i.encloses(s.bounds)},hD=e=>(e.forEach(t=>t.opacity=1),e),pD=(e,t)=>e.reflow(t.modified()).modifies("opacity");Be(rI,de,{transform(e,t){const n=fD[e.method]||fD.parity,r=e.separation||0;let i=t.materialize(t.SOURCE).source,s,a;if(!i||!i.length)return;if(!e.method)return e.modified("method")&&(hD(i),t=pD(t,e)),t;if(i=i.filter(yre),!i.length)return;if(e.sort&&(i=i.slice().sort(e.sort)),s=hD(i),t=pD(t,e),s.length>=3&&dD(s,r)){do s=n(s,r);while(s.length>=3&&dD(s,r));s.length<3&&!Xt(i).opacity&&(s.length>1&&(Xt(s).opacity=0),Xt(i).opacity=1)}e.boundScale&&e.boundTolerance>=0&&(a=bre(e.boundScale,e.boundOrient,+e.boundTolerance),i.forEach(l=>{a(l)||(l.opacity=0)}));const o=s[0].mark.bounds.clear();return i.forEach(l=>{l.opacity&&o.union(l.bounds)}),t}});function sI(e){de.call(this,null,e)}Be(sI,de,{transform(e,t){const n=t.dataflow;if(t.visit(t.ALL,r=>n.dirty(r)),t.fields&&t.fields.zindex){const r=t.source&&t.source[0];r&&(r.mark.zdirty=!0)}}});const qr=new Qn;function Qf(e,t,n){return e[t]===n?0:(e[t]=n,1)}function _re(e){var t=e.items[0].orient;return t===na||t===ia}function xre(e){let t=+e.grid;return[e.ticks?t++:-1,e.labels?t++:-1,t+ +e.domain]}function wre(e,t,n,r){var i=t.items[0],s=i.datum,a=i.translate!=null?i.translate:.5,o=i.orient,l=xre(s),u=i.range,c=i.offset,f=i.position,d=i.minExtent,h=i.maxExtent,p=s.title&&i.items[l[2]].items[0],g=i.titlePadding,v=i.bounds,y=p&&T3(p),b=0,_=0,x,w;switch(qr.clear().union(v),v.clear(),(x=l[0])>-1&&v.union(i.items[x].bounds),(x=l[1])>-1&&v.union(i.items[x].bounds),o){case Gd:b=f||0,_=-c,w=Math.max(d,Math.min(h,-v.y1)),v.add(0,-w).add(u,0),p&&wm(e,p,w,g,y,0,-1,v);break;case na:b=-c,_=f||0,w=Math.max(d,Math.min(h,-v.x1)),v.add(-w,0).add(0,u),p&&wm(e,p,w,g,y,1,-1,v);break;case ia:b=n+c,_=f||0,w=Math.max(d,Math.min(h,v.x2)),v.add(0,0).add(w,u),p&&wm(e,p,w,g,y,1,1,v);break;case fu:b=f||0,_=r+c,w=Math.max(d,Math.min(h,v.y2)),v.add(0,0).add(u,w),p&&wm(e,p,w,g,0,0,1,v);break;default:b=i.x,_=i.y}return hl(v.translate(b,_),i),Qf(i,"x",b+a)|Qf(i,"y",_+a)&&(i.bounds=qr,e.dirty(i),i.bounds=v,e.dirty(i)),i.mark.bounds.clear().union(v)}function wm(e,t,n,r,i,s,a,o){const l=t.bounds;if(t.auto){const u=a*(n+i+r);let c=0,f=0;e.dirty(t),s?c=(t.x||0)-(t.x=u):f=(t.y||0)-(t.y=u),t.mark.bounds.clear().union(l.translate(-c,-f)),e.dirty(t)}o.union(l)}const gD=(e,t)=>Math.floor(Math.min(e,t)),mD=(e,t)=>Math.ceil(Math.max(e,t));function Ere(e){var t=e.items,n=t.length,r=0,i,s;const a={marks:[],rowheaders:[],rowfooters:[],colheaders:[],colfooters:[],rowtitle:null,coltitle:null};for(;r1)for(E=0;E0&&(_[E]+=T/2);if(o&&Sn(n.center,Ul)&&c!==1)for(E=0;E0&&(x[E]+=$/2);for(E=0;Ei&&(e.warn("Grid headers exceed limit: "+i),t=t.slice(0,i)),g+=s,b=0,x=t.length;b=0&&(E=n[_])==null;_-=d);o?(k=h==null?E.x:Math.round(E.bounds.x1+h*E.bounds.width()),C=g):(k=g,C=h==null?E.y:Math.round(E.bounds.y1+h*E.bounds.height())),w.union(A.bounds.translate(k-(A.x||0),C-(A.y||0))),A.x=k,A.y=C,e.dirty(A),v=a(v,w[u])}return v}function yD(e,t,n,r,i,s){if(t){e.dirty(t);var a=n,o=n;r?a=Math.round(i.x1+s*i.width()):o=Math.round(i.y1+s*i.height()),t.bounds.translate(a-(t.x||0),o-(t.y||0)),t.mark.bounds.clear().union(t.bounds),t.x=a,t.y=o,e.dirty(t)}}function Fre(e,t){const n=e[t]||{};return(r,i)=>n[r]!=null?n[r]:e[r]!=null?e[r]:i}function Dre(e,t){let n=-1/0;return e.forEach(r=>{r.offset!=null&&(n=Math.max(n,r.offset))}),n>-1/0?n:t}function Mre(e,t,n,r,i,s,a){const o=Fre(n,t),l=Dre(e,o("offset",0)),u=o("anchor",W3),c=u===li?1:u===vE?.5:0,f={align:yE,bounds:o("bounds",X3),columns:o("direction")==="vertical"?1:e.length,padding:o("margin",8),center:o("center"),nodirty:!0};switch(t){case na:f.anchor={x:Math.floor(r.x1)-l,column:li,y:c*(a||r.height()+2*r.y1),row:u};break;case ia:f.anchor={x:Math.ceil(r.x2)+l,y:c*(a||r.height()+2*r.y1),row:u};break;case Gd:f.anchor={y:Math.floor(i.y1)-l,row:li,x:c*(s||i.width()+2*i.x1),column:u};break;case fu:f.anchor={y:Math.ceil(i.y2)+l,x:c*(s||i.width()+2*i.x1),column:u};break;case sre:f.anchor={x:l,y:l};break;case are:f.anchor={x:s-l,y:l,column:li};break;case ore:f.anchor={x:l,y:a-l,row:li};break;case lre:f.anchor={x:s-l,y:a-l,column:li,row:li};break}return f}function Tre(e,t){var n=t.items[0],r=n.datum,i=n.orient,s=n.bounds,a=n.x,o=n.y,l,u;return n._bounds?n._bounds.clear().union(s):n._bounds=s.clone(),s.clear(),Nre(e,n,n.items[0].items[0]),s=Rre(n,s),l=2*n.padding,u=2*n.padding,s.empty()||(l=Math.ceil(s.width()+l),u=Math.ceil(s.height()+u)),r.type===pre&&Ore(n.items[0].items[0].items[0].items),i!==V3&&(n.x=a=0,n.y=o=0),n.width=l,n.height=u,hl(s.set(a,o,a+l,o+u),n),n.mark.bounds.clear().union(s),n}function Rre(e,t){return e.items.forEach(n=>t.union(n.bounds)),t.x1=e.padding,t.y1=e.padding,t}function Nre(e,t,n){var r=t.padding,i=r-n.x,s=r-n.y;if(!t.datum.title)(i||s)&&op(e,n,i,s);else{var a=t.items[1].items[0],o=a.anchor,l=t.titlePadding||0,u=r-a.x,c=r-a.y;switch(a.orient){case na:i+=Math.ceil(a.bounds.width())+l;break;case ia:case fu:break;default:s+=a.bounds.height()+l}switch((i||s)&&op(e,n,i,s),a.orient){case na:c+=Of(t,n,a,o,1,1);break;case ia:u+=Of(t,n,a,li,0,0)+l,c+=Of(t,n,a,o,1,1);break;case fu:u+=Of(t,n,a,o,0,0),c+=Of(t,n,a,li,-1,0,1)+l;break;default:u+=Of(t,n,a,o,0,0)}(u||c)&&op(e,a,u,c),(u=Math.round(a.bounds.x1-r))<0&&(op(e,n,-u,0),op(e,a,-u,0))}}function Of(e,t,n,r,i,s,a){const o=e.datum.type!=="symbol",l=n.datum.vgrad,u=o&&(s||!l)&&!a?t.items[0]:t,c=u.bounds[i?"y2":"x2"]-e.padding,f=l&&s?c:0,d=l&&s?0:c,h=i<=0?0:T3(n);return Math.round(r===W3?f:r===li?d-h:.5*(c-h))}function op(e,t,n,r){t.x+=n,t.y+=r,t.bounds.translate(n,r),t.mark.bounds.translate(n,r),e.dirty(t)}function Ore(e){const t=e.reduce((n,r)=>(n[r.column]=Math.max(r.bounds.x2-r.x,n[r.column]||0),n),{});e.forEach(n=>{n.width=t[n.column],n.height=n.bounds.y2-n.y})}function Lre(e,t,n,r,i){var s=t.items[0],a=s.frame,o=s.orient,l=s.anchor,u=s.offset,c=s.padding,f=s.items[0].items[0],d=s.items[1]&&s.items[1].items[0],h=o===na||o===ia?r:n,p=0,g=0,v=0,y=0,b=0,_;if(a!==Fb?o===na?(p=i.y2,h=i.y1):o===ia?(p=i.y1,h=i.y2):(p=i.x1,h=i.x2):o===na&&(p=r,h=0),_=l===W3?p:l===li?h:(p+h)/2,d&&d.text){switch(o){case Gd:case fu:b=f.bounds.height()+c;break;case na:y=f.bounds.width()+c;break;case ia:y=-f.bounds.width()-c;break}qr.clear().union(d.bounds),qr.translate(y-(d.x||0),b-(d.y||0)),Qf(d,"x",y)|Qf(d,"y",b)&&(e.dirty(d),d.bounds.clear().union(qr),d.mark.bounds.clear().union(qr),e.dirty(d)),qr.clear().union(d.bounds)}else qr.clear();switch(qr.union(f.bounds),o){case Gd:g=_,v=i.y1-qr.height()-u;break;case na:g=i.x1-qr.width()-u,v=_;break;case ia:g=i.x2+qr.width()+u,v=_;break;case fu:g=_,v=i.y2+u;break;default:g=s.x,v=s.y}return Qf(s,"x",g)|Qf(s,"y",v)&&(qr.translate(g,v),e.dirty(s),s.bounds.clear().union(qr),t.bounds.clear().union(qr),e.dirty(s)),s.bounds}function oI(e){de.call(this,null,e)}Be(oI,de,{transform(e,t){const n=t.dataflow;return e.mark.items.forEach(r=>{e.layout&&Sre(n,r,e.layout),Pre(n,r,e)}),Ire(e.mark.group)?t.reflow():t}});function Ire(e){return e&&e.mark.role!=="legend-entry"}function Pre(e,t,n){var r=t.items,i=Math.max(0,t.width||0),s=Math.max(0,t.height||0),a=new Qn().set(0,0,i,s),o=a.clone(),l=a.clone(),u=[],c,f,d,h,p,g;for(p=0,g=r.length;p{d=y.orient||ia,d!==V3&&(v[d]||(v[d]=[])).push(y)});for(const y in v){const b=v[y];aI(e,b,Mre(b,y,n.legends,o,l,i,s))}u.forEach(y=>{const b=y.bounds;if(b.equals(y._bounds)||(y.bounds=y._bounds,e.dirty(y),y.bounds=b,e.dirty(y)),n.autosize&&(n.autosize.type===JL||n.autosize.type===QL||n.autosize.type===eI))switch(y.orient){case na:case ia:a.add(b.x1,0).add(b.x2,0);break;case Gd:case fu:a.add(0,b.y1).add(0,b.y2)}else a.union(b)})}a.union(o).union(l),c&&a.union(Lre(e,c,i,s,a)),t.clip&&a.set(0,0,t.width||0,t.height||0),Bre(e,t,a,n)}function Bre(e,t,n,r){const i=r.autosize||{},s=i.type;if(e._autosize<1||!s)return;let a=e._width,o=e._height,l=Math.max(0,t.width||0),u=Math.max(0,Math.ceil(-n.x1)),c=Math.max(0,t.height||0),f=Math.max(0,Math.ceil(-n.y1));const d=Math.max(0,Math.ceil(n.x2-l)),h=Math.max(0,Math.ceil(n.y2-c));if(i.contains===hre){const p=e.padding();a-=p.left+p.right,o-=p.top+p.bottom}s===V3?(u=0,f=0,l=a,c=o):s===JL?(l=Math.max(0,a-u-d),c=Math.max(0,o-f-h)):s===QL?(l=Math.max(0,a-u-d),o=c+f+h):s===eI?(a=l+u+d,c=Math.max(0,o-f-h)):s===gre&&(a=l+u+d,o=c+f+h),e._resizeView(a,o,l,c,[u,f],i.resize)}const zre=Object.freeze(Object.defineProperty({__proto__:null,bound:tI,identifier:K3,mark:nI,overlap:rI,render:sI,viewlayout:oI},Symbol.toStringTag,{value:"Module"}));function lI(e){de.call(this,null,e)}Be(lI,de,{transform(e,t){if(this.value&&!e.modified())return t.StopPropagation;var n=t.dataflow.locale(),r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=this.value,s=e.scale,a=e.count==null?e.values?e.values.length:10:e.count,o=p3(s,a,e.minstep),l=e.format||O9(n,s,o,e.formatSpecifier,e.formatType,!!e.values),u=e.values?N9(s,e.values,o):g3(s,o);return i&&(r.rem=i),i=u.map((c,f)=>nn({index:f/(u.length-1||1),value:c,label:l(c)})),e.extra&&i.length&&i.push(nn({index:-1,extra:{value:i[0].value},label:""})),r.source=i,r.add=i,this.value=i,r}});function uI(e){de.call(this,null,e)}function jre(){return nn({})}function Ure(e){const t=xh().test(n=>n.exit);return t.lookup=n=>t.get(e(n)),t}Be(uI,de,{transform(e,t){var n=t.dataflow,r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=e.item||jre,s=e.key||dt,a=this.value;return Se(r.encode)&&(r.encode=null),a&&(e.modified("key")||t.modified(s))&&ye("DataJoin does not support modified key function or fields."),a||(t=t.addAll(),this.value=a=Ure(s)),t.visit(t.ADD,o=>{const l=s(o);let u=a.get(l);u?u.exit?(a.empty--,r.add.push(u)):r.mod.push(u):(u=i(o),a.set(l,u),r.add.push(u)),u.datum=o,u.exit=!1}),t.visit(t.MOD,o=>{const l=s(o),u=a.get(l);u&&(u.datum=o,r.mod.push(u))}),t.visit(t.REM,o=>{const l=s(o),u=a.get(l);o===u.datum&&!u.exit&&(r.rem.push(u),u.exit=!0,++a.empty)}),t.changed(t.ADD_MOD)&&r.modifies("datum"),(t.clean()||e.clean&&a.empty>n.cleanThreshold)&&n.runAfter(a.clean),r}});function cI(e){de.call(this,null,e)}Be(cI,de,{transform(e,t){var n=t.fork(t.ADD_REM),r=e.mod||!1,i=e.encoders,s=t.encode;if(Se(s))if(n.changed()||s.every(f=>i[f]))s=s[0],n.encode=null;else return t.StopPropagation;var a=s==="enter",o=i.update||kl,l=i.enter||kl,u=i.exit||kl,c=(s&&!a?i[s]:o)||kl;if(t.changed(t.ADD)&&(t.visit(t.ADD,f=>{l(f,e),o(f,e)}),n.modifies(l.output),n.modifies(o.output),c!==kl&&c!==o&&(t.visit(t.ADD,f=>{c(f,e)}),n.modifies(c.output))),t.changed(t.REM)&&u!==kl&&(t.visit(t.REM,f=>{u(f,e)}),n.modifies(u.output)),a||c!==kl){const f=t.MOD|(e.modified()?t.REFLOW:0);a?(t.visit(f,d=>{const h=l(d,e)||r;(c(d,e)||h)&&n.mod.push(d)}),n.mod.length&&n.modifies(l.output)):t.visit(f,d=>{(c(d,e)||r)&&n.mod.push(d)}),n.mod.length&&n.modifies(c.output)}return n.changed()?n:t.StopPropagation}});function fI(e){de.call(this,[],e)}Be(fI,de,{transform(e,t){if(this.value!=null&&!e.modified())return t.StopPropagation;var n=t.dataflow.locale(),r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=this.value,s=e.type||p1,a=e.scale,o=+e.limit,l=p3(a,e.count==null?5:e.count,e.minstep),u=!!e.values||s===p1,c=e.format||B9(n,a,l,s,e.formatSpecifier,e.formatType,u),f=e.values||P9(a,l),d,h,p,g,v;return i&&(r.rem=i),s===p1?(o&&f.length>o?(t.dataflow.warn("Symbol legend count exceeds limit, filtering items."),i=f.slice(0,o-1),v=!0):i=f,Rt(p=e.size)?(!e.values&&a(i[0])===0&&(i=i.slice(1)),g=i.reduce((y,b)=>Math.max(y,p(b,e)),0)):p=ti(g=p||8),i=i.map((y,b)=>nn({index:b,label:c(y,b,i),value:y,offset:g,size:p(y,e)})),v&&(v=f[i.length],i.push(nn({index:i.length,label:`…${f.length-i.length} entries`,value:v,offset:g,size:p(v,e)})))):s===gee?(d=a.domain(),h=M9(a,d[0],Xt(d)),f.length<3&&!e.values&&d[0]!==Xt(d)&&(f=[d[0],Xt(d)]),i=f.map((y,b)=>nn({index:b,label:c(y,b,f),value:y,perc:h(y)}))):(p=f.length-1,h=See(a),i=f.map((y,b)=>nn({index:b,label:c(y,b,f),value:y,perc:b?h(y):0,perc2:b===p?1:h(f[b+1])}))),r.source=i,r.add=i,this.value=i,r}});const qre=e=>e.source.x,Wre=e=>e.source.y,Hre=e=>e.target.x,Gre=e=>e.target.y;function Z3(e){de.call(this,{},e)}Z3.Definition={type:"LinkPath",metadata:{modifies:!0},params:[{name:"sourceX",type:"field",default:"source.x"},{name:"sourceY",type:"field",default:"source.y"},{name:"targetX",type:"field",default:"target.x"},{name:"targetY",type:"field",default:"target.y"},{name:"orient",type:"enum",default:"vertical",values:["horizontal","vertical","radial"]},{name:"shape",type:"enum",default:"line",values:["line","arc","curve","diagonal","orthogonal"]},{name:"require",type:"signal"},{name:"as",type:"string",default:"path"}]};Be(Z3,de,{transform(e,t){var n=e.sourceX||qre,r=e.sourceY||Wre,i=e.targetX||Hre,s=e.targetY||Gre,a=e.as||"path",o=e.orient||"vertical",l=e.shape||"line",u=bD.get(l+"-"+o)||bD.get(l);return u||ye("LinkPath unsupported type: "+e.shape+(e.orient?"-"+e.orient:"")),t.visit(t.SOURCE,c=>{c[a]=u(n(c),r(c),i(c),s(c))}),t.reflow(e.modified()).modifies(a)}});const dI=(e,t,n,r)=>"M"+e+","+t+"L"+n+","+r,Yre=(e,t,n,r)=>dI(t*Math.cos(e),t*Math.sin(e),r*Math.cos(n),r*Math.sin(n)),hI=(e,t,n,r)=>{var i=n-e,s=r-t,a=Math.hypot(i,s)/2,o=180*Math.atan2(s,i)/Math.PI;return"M"+e+","+t+"A"+a+","+a+" "+o+" 0 1 "+n+","+r},Vre=(e,t,n,r)=>hI(t*Math.cos(e),t*Math.sin(e),r*Math.cos(n),r*Math.sin(n)),pI=(e,t,n,r)=>{const i=n-e,s=r-t,a=.2*(i+s),o=.2*(s-i);return"M"+e+","+t+"C"+(e+a)+","+(t+o)+" "+(n+o)+","+(r-a)+" "+n+","+r},Xre=(e,t,n,r)=>pI(t*Math.cos(e),t*Math.sin(e),r*Math.cos(n),r*Math.sin(n)),Kre=(e,t,n,r)=>"M"+e+","+t+"V"+r+"H"+n,Zre=(e,t,n,r)=>"M"+e+","+t+"H"+n+"V"+r,Jre=(e,t,n,r)=>{const i=Math.cos(e),s=Math.sin(e),a=Math.cos(n),o=Math.sin(n),l=Math.abs(n-e)>Math.PI?n<=e:n>e;return"M"+t*i+","+t*s+"A"+t+","+t+" 0 0,"+(l?1:0)+" "+t*a+","+t*o+"L"+r*a+","+r*o},Qre=(e,t,n,r)=>{const i=(e+n)/2;return"M"+e+","+t+"C"+i+","+t+" "+i+","+r+" "+n+","+r},eie=(e,t,n,r)=>{const i=(t+r)/2;return"M"+e+","+t+"C"+e+","+i+" "+n+","+i+" "+n+","+r},tie=(e,t,n,r)=>{const i=Math.cos(e),s=Math.sin(e),a=Math.cos(n),o=Math.sin(n),l=(t+r)/2;return"M"+t*i+","+t*s+"C"+l*i+","+l*s+" "+l*a+","+l*o+" "+r*a+","+r*o},bD=xh({line:dI,"line-radial":Yre,arc:hI,"arc-radial":Vre,curve:pI,"curve-radial":Xre,"orthogonal-horizontal":Kre,"orthogonal-vertical":Zre,"orthogonal-radial":Jre,"diagonal-horizontal":Qre,"diagonal-vertical":eie,"diagonal-radial":tie});function J3(e){de.call(this,null,e)}J3.Definition={type:"Pie",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"startAngle",type:"number",default:0},{name:"endAngle",type:"number",default:6.283185307179586},{name:"sort",type:"boolean",default:!1},{name:"as",type:"string",array:!0,length:2,default:["startAngle","endAngle"]}]};Be(J3,de,{transform(e,t){var n=e.as||["startAngle","endAngle"],r=n[0],i=n[1],s=e.field||vh,a=e.startAngle||0,o=e.endAngle!=null?e.endAngle:2*Math.PI,l=t.source,u=l.map(s),c=u.length,f=a,d=(o-a)/FN(u),h=ts(c),p,g,v;for(e.sort&&h.sort((y,b)=>u[y]-u[b]),p=0;p-1)return r;var i=t.domain,s=e.type,a=t.zero||t.zero===void 0&&rie(e),o,l;if(!i)return 0;if((a||t.domainMin!=null||t.domainMax!=null||t.domainMid!=null)&&(o=(i=i.slice()).length-1||1,a&&(i[0]>0&&(i[0]=0),i[o]<0&&(i[o]=0)),t.domainMin!=null&&(i[0]=t.domainMin),t.domainMax!=null&&(i[o]=t.domainMax),t.domainMid!=null)){l=t.domainMid;const u=l>i[o]?o+1:li+(s<0?-1:s>0?1:0),0));r!==t.length&&n.warn("Log scale domain includes zero: "+Pe(t))}return t}function cie(e,t,n){let r=t.bins;if(r&&!Se(r)){const i=e.domain(),s=i[0],a=Xt(i),o=r.step;let l=r.start==null?s:r.start,u=r.stop==null?a:r.stop;o||ye("Scale bins parameter missing step property."),la&&(u=o*Math.floor(a/o)),r=ts(l,u+o/2,o)}return r?e.bins=r:e.bins&&delete e.bins,e.type===l3&&(r?!t.domain&&!t.domainRaw&&(e.domain(r),n=r.length):e.bins=e.domain()),n}function fie(e,t,n){var r=e.type,i=t.round||!1,s=t.range;if(t.rangeStep!=null)s=die(r,t,n);else if(t.scheme&&(s=hie(r,t,n),Rt(s))){if(e.interpolator)return e.interpolator(s);ye(`Scale type ${r} does not support interpolating color schemes.`)}if(s&&C9(r))return e.interpolator(vb(bE(s,t.reverse),t.interpolate,t.interpolateGamma));s&&t.interpolate&&e.interpolate?e.interpolate(d3(t.interpolate,t.interpolateGamma)):Rt(e.round)?e.round(i):Rt(e.rangeRound)&&e.interpolate(i?p0:ku),s&&e.range(bE(s,t.reverse))}function die(e,t,n){e!==_9&&e!==iE&&ye("Only band and point scales support rangeStep.");var r=(t.paddingOuter!=null?t.paddingOuter:t.padding)||0,i=e===iE?1:(t.paddingInner!=null?t.paddingInner:t.padding)||0;return[0,t.rangeStep*a3(n,i,r)]}function hie(e,t,n){var r=t.schemeExtent,i,s;return Se(t.scheme)?s=vb(t.scheme,t.interpolate,t.interpolateGamma):(i=t.scheme.toLowerCase(),s=h3(i),s||ye(`Unrecognized scheme name: ${t.scheme}`)),n=e===mb?n+1:e===l3?n-1:e===jd||e===gb?+t.schemeCount||nie:n,C9(e)?_D(s,r,t.reverse):Rt(s)?D9(_D(s,r),n):e===o3?s:s.slice(0,n)}function _D(e,t,n){return Rt(e)&&(t||n)?F9(e,bE(t||[0,1],n)):e}function bE(e,t){return t?e.slice().reverse():e}function yI(e){de.call(this,null,e)}Be(yI,de,{transform(e,t){const n=e.modified("sort")||t.changed(t.ADD)||t.modified(e.sort.fields)||t.modified("datum");return n&&t.source.sort(gf(e.sort)),this.modified(n),t}});const xD="zero",bI="center",_I="normalize",xI=["y0","y1"];function Q3(e){de.call(this,null,e)}Q3.Definition={type:"Stack",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"groupby",type:"field",array:!0},{name:"sort",type:"compare"},{name:"offset",type:"enum",default:xD,values:[xD,bI,_I]},{name:"as",type:"string",array:!0,length:2,default:xI}]};Be(Q3,de,{transform(e,t){var n=e.as||xI,r=n[0],i=n[1],s=gf(e.sort),a=e.field||vh,o=e.offset===bI?pie:e.offset===_I?gie:mie,l,u,c,f;for(l=vie(t.source,e.groupby,s,a),u=0,c=l.length,f=l.max;ug(c),a,o,l,u,c,f,d,h,p;if(t==null)i.push(e.slice());else for(a={},o=0,l=e.length;op&&(p=h),n&&d.sort(n)}return i.max=p,i}const yie=Object.freeze(Object.defineProperty({__proto__:null,axisticks:lI,datajoin:uI,encode:cI,legendentries:fI,linkpath:Z3,pie:J3,scale:mI,sortitems:yI,stack:Q3},Symbol.toStringTag,{value:"Module"}));var _t=1e-6,kv=1e-12,jt=Math.PI,Pn=jt/2,Sv=jt/4,vi=jt*2,Hn=180/jt,Bt=jt/180,Vt=Math.abs,Mh=Math.atan,Is=Math.atan2,wt=Math.cos,Am=Math.ceil,wI=Math.exp,_E=Math.hypot,Cv=Math.log,q_=Math.pow,ht=Math.sin,As=Math.sign||function(e){return e>0?1:e<0?-1:0},yi=Math.sqrt,eC=Math.tan;function EI(e){return e>1?0:e<-1?jt:Math.acos(e)}function zi(e){return e>1?Pn:e<-1?-Pn:Math.asin(e)}function Tr(){}function $v(e,t){e&&ED.hasOwnProperty(e.type)&&ED[e.type](e,t)}var wD={Feature:function(e,t){$v(e.geometry,t)},FeatureCollection:function(e,t){for(var n=e.features,r=-1,i=n.length;++r=0?1:-1,i=r*n,s=wt(t),a=ht(t),o=AE*a,l=EE*s+o*wt(i),u=o*r*ht(i);Fv.add(Is(u,l)),wE=e,EE=s,AE=a}function wie(e){return Dv=new gi,jo(e,lo),Dv*2}function Mv(e){return[Is(e[1],e[0]),zi(e[2])]}function Hc(e){var t=e[0],n=e[1],r=wt(n);return[r*wt(t),r*ht(t),ht(n)]}function km(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]}function Yd(e,t){return[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]]}function W_(e,t){e[0]+=t[0],e[1]+=t[1],e[2]+=t[2]}function Sm(e,t){return[e[0]*t,e[1]*t,e[2]*t]}function Tv(e){var t=yi(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);e[0]/=t,e[1]/=t,e[2]/=t}var Fn,Di,Ln,Ji,tc,CI,$I,ld,tg,Dl,ul,Lo={point:kE,lineStart:kD,lineEnd:SD,polygonStart:function(){Lo.point=DI,Lo.lineStart=Eie,Lo.lineEnd=Aie,tg=new gi,lo.polygonStart()},polygonEnd:function(){lo.polygonEnd(),Lo.point=kE,Lo.lineStart=kD,Lo.lineEnd=SD,Fv<0?(Fn=-(Ln=180),Di=-(Ji=90)):tg>_t?Ji=90:tg<-_t&&(Di=-90),ul[0]=Fn,ul[1]=Ln},sphere:function(){Fn=-(Ln=180),Di=-(Ji=90)}};function kE(e,t){Dl.push(ul=[Fn=e,Ln=e]),tJi&&(Ji=t)}function FI(e,t){var n=Hc([e*Bt,t*Bt]);if(ld){var r=Yd(ld,n),i=[r[1],-r[0],0],s=Yd(i,r);Tv(s),s=Mv(s);var a=e-tc,o=a>0?1:-1,l=s[0]*Hn*o,u,c=Vt(a)>180;c^(o*tcJi&&(Ji=u)):(l=(l+360)%360-180,c^(o*tcJi&&(Ji=t))),c?eZi(Fn,Ln)&&(Ln=e):Zi(e,Ln)>Zi(Fn,Ln)&&(Fn=e):Ln>=Fn?(eLn&&(Ln=e)):e>tc?Zi(Fn,e)>Zi(Fn,Ln)&&(Ln=e):Zi(e,Ln)>Zi(Fn,Ln)&&(Fn=e)}else Dl.push(ul=[Fn=e,Ln=e]);tJi&&(Ji=t),ld=n,tc=e}function kD(){Lo.point=FI}function SD(){ul[0]=Fn,ul[1]=Ln,Lo.point=kE,ld=null}function DI(e,t){if(ld){var n=e-tc;tg.add(Vt(n)>180?n+(n>0?360:-360):n)}else CI=e,$I=t;lo.point(e,t),FI(e,t)}function Eie(){lo.lineStart()}function Aie(){DI(CI,$I),lo.lineEnd(),Vt(tg)>_t&&(Fn=-(Ln=180)),ul[0]=Fn,ul[1]=Ln,ld=null}function Zi(e,t){return(t-=e)<0?t+360:t}function kie(e,t){return e[0]-t[0]}function CD(e,t){return e[0]<=e[1]?e[0]<=t&&t<=e[1]:tZi(r[0],r[1])&&(r[1]=i[1]),Zi(i[0],r[1])>Zi(r[0],r[1])&&(r[0]=i[0])):s.push(r=i);for(a=-1/0,n=s.length-1,t=0,r=s[n];t<=n;r=i,++t)i=s[t],(o=Zi(r[1],i[0]))>a&&(a=o,Fn=i[0],Ln=r[1])}return Dl=ul=null,Fn===1/0||Di===1/0?[[NaN,NaN],[NaN,NaN]]:[[Fn,Di],[Ln,Ji]]}var Mp,Rv,Nv,Ov,Lv,Iv,Pv,Bv,SE,CE,$E,MI,TI,ui,ci,fi,sa={sphere:Tr,point:tC,lineStart:$D,lineEnd:FD,polygonStart:function(){sa.lineStart=Fie,sa.lineEnd=Die},polygonEnd:function(){sa.lineStart=$D,sa.lineEnd=FD}};function tC(e,t){e*=Bt,t*=Bt;var n=wt(t);F0(n*wt(e),n*ht(e),ht(t))}function F0(e,t,n){++Mp,Nv+=(e-Nv)/Mp,Ov+=(t-Ov)/Mp,Lv+=(n-Lv)/Mp}function $D(){sa.point=Cie}function Cie(e,t){e*=Bt,t*=Bt;var n=wt(t);ui=n*wt(e),ci=n*ht(e),fi=ht(t),sa.point=$ie,F0(ui,ci,fi)}function $ie(e,t){e*=Bt,t*=Bt;var n=wt(t),r=n*wt(e),i=n*ht(e),s=ht(t),a=Is(yi((a=ci*s-fi*i)*a+(a=fi*r-ui*s)*a+(a=ui*i-ci*r)*a),ui*r+ci*i+fi*s);Rv+=a,Iv+=a*(ui+(ui=r)),Pv+=a*(ci+(ci=i)),Bv+=a*(fi+(fi=s)),F0(ui,ci,fi)}function FD(){sa.point=tC}function Fie(){sa.point=Mie}function Die(){RI(MI,TI),sa.point=tC}function Mie(e,t){MI=e,TI=t,e*=Bt,t*=Bt,sa.point=RI;var n=wt(t);ui=n*wt(e),ci=n*ht(e),fi=ht(t),F0(ui,ci,fi)}function RI(e,t){e*=Bt,t*=Bt;var n=wt(t),r=n*wt(e),i=n*ht(e),s=ht(t),a=ci*s-fi*i,o=fi*r-ui*s,l=ui*i-ci*r,u=_E(a,o,l),c=zi(u),f=u&&-c/u;SE.add(f*a),CE.add(f*o),$E.add(f*l),Rv+=c,Iv+=c*(ui+(ui=r)),Pv+=c*(ci+(ci=i)),Bv+=c*(fi+(fi=s)),F0(ui,ci,fi)}function Tie(e){Mp=Rv=Nv=Ov=Lv=Iv=Pv=Bv=0,SE=new gi,CE=new gi,$E=new gi,jo(e,sa);var t=+SE,n=+CE,r=+$E,i=_E(t,n,r);return ijt&&(e-=Math.round(e/vi)*vi),[e,t]}DE.invert=DE;function NI(e,t,n){return(e%=vi)?t||n?FE(MD(e),TD(t,n)):MD(e):t||n?TD(t,n):DE}function DD(e){return function(t,n){return t+=e,Vt(t)>jt&&(t-=Math.round(t/vi)*vi),[t,n]}}function MD(e){var t=DD(e);return t.invert=DD(-e),t}function TD(e,t){var n=wt(e),r=ht(e),i=wt(t),s=ht(t);function a(o,l){var u=wt(l),c=wt(o)*u,f=ht(o)*u,d=ht(l),h=d*n+c*r;return[Is(f*i-h*s,c*n-d*r),zi(h*i+f*s)]}return a.invert=function(o,l){var u=wt(l),c=wt(o)*u,f=ht(o)*u,d=ht(l),h=d*i-f*s;return[Is(f*i+d*s,c*n+h*r),zi(h*n-c*r)]},a}function Rie(e){e=NI(e[0]*Bt,e[1]*Bt,e.length>2?e[2]*Bt:0);function t(n){return n=e(n[0]*Bt,n[1]*Bt),n[0]*=Hn,n[1]*=Hn,n}return t.invert=function(n){return n=e.invert(n[0]*Bt,n[1]*Bt),n[0]*=Hn,n[1]*=Hn,n},t}function Nie(e,t,n,r,i,s){if(n){var a=wt(t),o=ht(t),l=r*n;i==null?(i=t+r*vi,s=t-l/2):(i=RD(a,i),s=RD(a,s),(r>0?is)&&(i+=r*vi));for(var u,c=i;r>0?c>s:c1&&e.push(e.pop().concat(e.shift()))},result:function(){var n=e;return e=[],t=null,n}}}function E1(e,t){return Vt(e[0]-t[0])<_t&&Vt(e[1]-t[1])<_t}function Cm(e,t,n,r){this.x=e,this.z=t,this.o=n,this.e=r,this.v=!1,this.n=this.p=null}function LI(e,t,n,r,i){var s=[],a=[],o,l;if(e.forEach(function(p){if(!((g=p.length-1)<=0)){var g,v=p[0],y=p[g],b;if(E1(v,y)){if(!v[2]&&!y[2]){for(i.lineStart(),o=0;o=0;--o)i.point((f=c[o])[0],f[1]);else r(d.x,d.p.x,-1,i);d=d.p}d=d.o,c=d.z,h=!h}while(!d.v);i.lineEnd()}}}function ND(e){if(t=e.length){for(var t,n=0,r=e[0],i;++n=0?1:-1,M=C*k,N=M>jt,P=v*A;if(l.add(Is(P*C*ht(M),y*E+P*wt(M))),a+=N?k+C*vi:k,N^p>=n^x>=n){var I=Yd(Hc(h),Hc(_));Tv(I);var T=Yd(s,I);Tv(T);var $=(N^k>=0?-1:1)*zi(T[2]);(r>$||r===$&&(I[0]||I[1]))&&(o+=N^k>=0?1:-1)}}return(a<-_t||a<_t&&l<-kv)^o&1}function II(e,t,n,r){return function(i){var s=t(i),a=OI(),o=t(a),l=!1,u,c,f,d={point:h,lineStart:g,lineEnd:v,polygonStart:function(){d.point=y,d.lineStart=b,d.lineEnd=_,c=[],u=[]},polygonEnd:function(){d.point=h,d.lineStart=g,d.lineEnd=v,c=$N(c);var x=Oie(u,r);c.length?(l||(i.polygonStart(),l=!0),LI(c,Iie,x,n,i)):x&&(l||(i.polygonStart(),l=!0),i.lineStart(),n(null,null,1,i),i.lineEnd()),l&&(i.polygonEnd(),l=!1),c=u=null},sphere:function(){i.polygonStart(),i.lineStart(),n(null,null,1,i),i.lineEnd(),i.polygonEnd()}};function h(x,w){e(x,w)&&i.point(x,w)}function p(x,w){s.point(x,w)}function g(){d.point=p,s.lineStart()}function v(){d.point=h,s.lineEnd()}function y(x,w){f.push([x,w]),o.point(x,w)}function b(){o.lineStart(),f=[]}function _(){y(f[0][0],f[0][1]),o.lineEnd();var x=o.clean(),w=a.result(),A,E=w.length,k,C,M;if(f.pop(),u.push(f),f=null,!!E){if(x&1){if(C=w[0],(k=C.length-1)>0){for(l||(i.polygonStart(),l=!0),i.lineStart(),A=0;A1&&x&2&&w.push(w.pop().concat(w.shift())),c.push(w.filter(Lie))}}return d}}function Lie(e){return e.length>1}function Iie(e,t){return((e=e.x)[0]<0?e[1]-Pn-_t:Pn-e[1])-((t=t.x)[0]<0?t[1]-Pn-_t:Pn-t[1])}const OD=II(function(){return!0},Pie,zie,[-jt,-Pn]);function Pie(e){var t=NaN,n=NaN,r=NaN,i;return{lineStart:function(){e.lineStart(),i=1},point:function(s,a){var o=s>0?jt:-jt,l=Vt(s-t);Vt(l-jt)<_t?(e.point(t,n=(n+a)/2>0?Pn:-Pn),e.point(r,n),e.lineEnd(),e.lineStart(),e.point(o,n),e.point(s,n),i=0):r!==o&&l>=jt&&(Vt(t-r)<_t&&(t-=r*_t),Vt(s-o)<_t&&(s-=o*_t),n=Bie(t,n,s,a),e.point(r,n),e.lineEnd(),e.lineStart(),e.point(o,n),i=0),e.point(t=s,n=a),r=o},lineEnd:function(){e.lineEnd(),t=n=NaN},clean:function(){return 2-i}}}function Bie(e,t,n,r){var i,s,a=ht(e-n);return Vt(a)>_t?Mh((ht(t)*(s=wt(r))*ht(n)-ht(r)*(i=wt(t))*ht(e))/(i*s*a)):(t+r)/2}function zie(e,t,n,r){var i;if(e==null)i=n*Pn,r.point(-jt,i),r.point(0,i),r.point(jt,i),r.point(jt,0),r.point(jt,-i),r.point(0,-i),r.point(-jt,-i),r.point(-jt,0),r.point(-jt,i);else if(Vt(e[0]-t[0])>_t){var s=e[0]0,i=Vt(t)>_t;function s(c,f,d,h){Nie(h,e,n,d,c,f)}function a(c,f){return wt(c)*wt(f)>t}function o(c){var f,d,h,p,g;return{lineStart:function(){p=h=!1,g=1},point:function(v,y){var b=[v,y],_,x=a(v,y),w=r?x?0:u(v,y):x?u(v+(v<0?jt:-jt),y):0;if(!f&&(p=h=x)&&c.lineStart(),x!==h&&(_=l(f,b),(!_||E1(f,_)||E1(b,_))&&(b[2]=1)),x!==h)g=0,x?(c.lineStart(),_=l(b,f),c.point(_[0],_[1])):(_=l(f,b),c.point(_[0],_[1],2),c.lineEnd()),f=_;else if(i&&f&&r^x){var A;!(w&d)&&(A=l(b,f,!0))&&(g=0,r?(c.lineStart(),c.point(A[0][0],A[0][1]),c.point(A[1][0],A[1][1]),c.lineEnd()):(c.point(A[1][0],A[1][1]),c.lineEnd(),c.lineStart(),c.point(A[0][0],A[0][1],3)))}x&&(!f||!E1(f,b))&&c.point(b[0],b[1]),f=b,h=x,d=w},lineEnd:function(){h&&c.lineEnd(),f=null},clean:function(){return g|(p&&h)<<1}}}function l(c,f,d){var h=Hc(c),p=Hc(f),g=[1,0,0],v=Yd(h,p),y=km(v,v),b=v[0],_=y-b*b;if(!_)return!d&&c;var x=t*y/_,w=-t*b/_,A=Yd(g,v),E=Sm(g,x),k=Sm(v,w);W_(E,k);var C=A,M=km(E,C),N=km(C,C),P=M*M-N*(km(E,E)-1);if(!(P<0)){var I=yi(P),T=Sm(C,(-M-I)/N);if(W_(T,E),T=Mv(T),!d)return T;var $=c[0],L=f[0],W=c[1],U=f[1],O;L<$&&(O=$,$=L,L=O);var H=L-$,G=Vt(H-jt)<_t,J=G||H<_t;if(!G&&U0^T[1]<(Vt(T[0]-$)<_t?W:U):W<=T[1]&&T[1]<=U:H>jt^($<=T[0]&&T[0]<=L)){var ce=Sm(C,(-M+I)/N);return W_(ce,E),[T,Mv(ce)]}}}function u(c,f){var d=r?e:jt-e,h=0;return c<-d?h|=1:c>d&&(h|=2),f<-d?h|=4:f>d&&(h|=8),h}return II(a,o,s,r?[0,-e]:[-jt,e-jt])}function Uie(e,t,n,r,i,s){var a=e[0],o=e[1],l=t[0],u=t[1],c=0,f=1,d=l-a,h=u-o,p;if(p=n-a,!(!d&&p>0)){if(p/=d,d<0){if(p0){if(p>f)return;p>c&&(c=p)}if(p=i-a,!(!d&&p<0)){if(p/=d,d<0){if(p>f)return;p>c&&(c=p)}else if(d>0){if(p0)){if(p/=h,h<0){if(p0){if(p>f)return;p>c&&(c=p)}if(p=s-o,!(!h&&p<0)){if(p/=h,h<0){if(p>f)return;p>c&&(c=p)}else if(h>0){if(p0&&(e[0]=a+c*d,e[1]=o+c*h),f<1&&(t[0]=a+f*d,t[1]=o+f*h),!0}}}}}var Tp=1e9,$m=-Tp;function PI(e,t,n,r){function i(u,c){return e<=u&&u<=n&&t<=c&&c<=r}function s(u,c,f,d){var h=0,p=0;if(u==null||(h=a(u,f))!==(p=a(c,f))||l(u,c)<0^f>0)do d.point(h===0||h===3?e:n,h>1?r:t);while((h=(h+f+4)%4)!==p);else d.point(c[0],c[1])}function a(u,c){return Vt(u[0]-e)<_t?c>0?0:3:Vt(u[0]-n)<_t?c>0?2:1:Vt(u[1]-t)<_t?c>0?1:0:c>0?3:2}function o(u,c){return l(u.x,c.x)}function l(u,c){var f=a(u,1),d=a(c,1);return f!==d?f-d:f===0?c[1]-u[1]:f===1?u[0]-c[0]:f===2?u[1]-c[1]:c[0]-u[0]}return function(u){var c=u,f=OI(),d,h,p,g,v,y,b,_,x,w,A,E={point:k,lineStart:P,lineEnd:I,polygonStart:M,polygonEnd:N};function k($,L){i($,L)&&c.point($,L)}function C(){for(var $=0,L=0,W=h.length;Lr&&(xe-J)*(r-ce)>(be-ce)*(e-J)&&++$:be<=r&&(xe-J)*(r-ce)<(be-ce)*(e-J)&&--$;return $}function M(){c=f,d=[],h=[],A=!0}function N(){var $=C(),L=A&&$,W=(d=$N(d)).length;(L||W)&&(u.polygonStart(),L&&(u.lineStart(),s(null,null,1,u),u.lineEnd()),W&&LI(d,o,$,s,u),u.polygonEnd()),c=u,d=h=p=null}function P(){E.point=T,h&&h.push(p=[]),w=!0,x=!1,b=_=NaN}function I(){d&&(T(g,v),y&&x&&f.rejoin(),d.push(f.result())),E.point=k,x&&c.lineEnd()}function T($,L){var W=i($,L);if(h&&p.push([$,L]),w)g=$,v=L,y=W,w=!1,W&&(c.lineStart(),c.point($,L));else if(W&&x)c.point($,L);else{var U=[b=Math.max($m,Math.min(Tp,b)),_=Math.max($m,Math.min(Tp,_))],O=[$=Math.max($m,Math.min(Tp,$)),L=Math.max($m,Math.min(Tp,L))];Uie(U,O,e,t,n,r)?(x||(c.lineStart(),c.point(U[0],U[1])),c.point(O[0],O[1]),W||c.lineEnd(),A=!1):W&&(c.lineStart(),c.point($,L),A=!1)}b=$,_=L,x=W}return E}}function LD(e,t,n){var r=ts(e,t-_t,n).concat(t);return function(i){return r.map(function(s){return[i,s]})}}function ID(e,t,n){var r=ts(e,t-_t,n).concat(t);return function(i){return r.map(function(s){return[s,i]})}}function qie(){var e,t,n,r,i,s,a,o,l=10,u=l,c=90,f=360,d,h,p,g,v=2.5;function y(){return{type:"MultiLineString",coordinates:b()}}function b(){return ts(Am(r/c)*c,n,c).map(p).concat(ts(Am(o/f)*f,a,f).map(g)).concat(ts(Am(t/l)*l,e,l).filter(function(_){return Vt(_%c)>_t}).map(d)).concat(ts(Am(s/u)*u,i,u).filter(function(_){return Vt(_%f)>_t}).map(h))}return y.lines=function(){return b().map(function(_){return{type:"LineString",coordinates:_}})},y.outline=function(){return{type:"Polygon",coordinates:[p(r).concat(g(a).slice(1),p(n).reverse().slice(1),g(o).reverse().slice(1))]}},y.extent=function(_){return arguments.length?y.extentMajor(_).extentMinor(_):y.extentMinor()},y.extentMajor=function(_){return arguments.length?(r=+_[0][0],n=+_[1][0],o=+_[0][1],a=+_[1][1],r>n&&(_=r,r=n,n=_),o>a&&(_=o,o=a,a=_),y.precision(v)):[[r,o],[n,a]]},y.extentMinor=function(_){return arguments.length?(t=+_[0][0],e=+_[1][0],s=+_[0][1],i=+_[1][1],t>e&&(_=t,t=e,e=_),s>i&&(_=s,s=i,i=_),y.precision(v)):[[t,s],[e,i]]},y.step=function(_){return arguments.length?y.stepMajor(_).stepMinor(_):y.stepMinor()},y.stepMajor=function(_){return arguments.length?(c=+_[0],f=+_[1],y):[c,f]},y.stepMinor=function(_){return arguments.length?(l=+_[0],u=+_[1],y):[l,u]},y.precision=function(_){return arguments.length?(v=+_,d=LD(s,i,90),h=ID(t,e,v),p=LD(o,a,90),g=ID(r,n,v),y):v},y.extentMajor([[-180,-90+_t],[180,90-_t]]).extentMinor([[-180,-80-_t],[180,80+_t]])}const $g=e=>e;var G_=new gi,ME=new gi,BI,zI,TE,RE,Uo={point:Tr,lineStart:Tr,lineEnd:Tr,polygonStart:function(){Uo.lineStart=Wie,Uo.lineEnd=Gie},polygonEnd:function(){Uo.lineStart=Uo.lineEnd=Uo.point=Tr,G_.add(Vt(ME)),ME=new gi},result:function(){var e=G_/2;return G_=new gi,e}};function Wie(){Uo.point=Hie}function Hie(e,t){Uo.point=jI,BI=TE=e,zI=RE=t}function jI(e,t){ME.add(RE*e-TE*t),TE=e,RE=t}function Gie(){jI(BI,zI)}var Vd=1/0,zv=Vd,Fg=-Vd,jv=Fg,Uv={point:Yie,lineStart:Tr,lineEnd:Tr,polygonStart:Tr,polygonEnd:Tr,result:function(){var e=[[Vd,zv],[Fg,jv]];return Fg=jv=-(zv=Vd=1/0),e}};function Yie(e,t){eFg&&(Fg=e),tjv&&(jv=t)}var NE=0,OE=0,Rp=0,qv=0,Wv=0,ed=0,LE=0,IE=0,Np=0,UI,qI,Ha,Ga,ws={point:Gc,lineStart:PD,lineEnd:BD,polygonStart:function(){ws.lineStart=Kie,ws.lineEnd=Zie},polygonEnd:function(){ws.point=Gc,ws.lineStart=PD,ws.lineEnd=BD},result:function(){var e=Np?[LE/Np,IE/Np]:ed?[qv/ed,Wv/ed]:Rp?[NE/Rp,OE/Rp]:[NaN,NaN];return NE=OE=Rp=qv=Wv=ed=LE=IE=Np=0,e}};function Gc(e,t){NE+=e,OE+=t,++Rp}function PD(){ws.point=Vie}function Vie(e,t){ws.point=Xie,Gc(Ha=e,Ga=t)}function Xie(e,t){var n=e-Ha,r=t-Ga,i=yi(n*n+r*r);qv+=i*(Ha+e)/2,Wv+=i*(Ga+t)/2,ed+=i,Gc(Ha=e,Ga=t)}function BD(){ws.point=Gc}function Kie(){ws.point=Jie}function Zie(){WI(UI,qI)}function Jie(e,t){ws.point=WI,Gc(UI=Ha=e,qI=Ga=t)}function WI(e,t){var n=e-Ha,r=t-Ga,i=yi(n*n+r*r);qv+=i*(Ha+e)/2,Wv+=i*(Ga+t)/2,ed+=i,i=Ga*e-Ha*t,LE+=i*(Ha+e),IE+=i*(Ga+t),Np+=i*3,Gc(Ha=e,Ga=t)}function HI(e){this._context=e}HI.prototype={_radius:4.5,pointRadius:function(e){return this._radius=e,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){this._line===0&&this._context.closePath(),this._point=NaN},point:function(e,t){switch(this._point){case 0:{this._context.moveTo(e,t),this._point=1;break}case 1:{this._context.lineTo(e,t);break}default:{this._context.moveTo(e+this._radius,t),this._context.arc(e,t,this._radius,0,vi);break}}},result:Tr};var PE=new gi,Y_,GI,YI,Op,Lp,Dg={point:Tr,lineStart:function(){Dg.point=Qie},lineEnd:function(){Y_&&VI(GI,YI),Dg.point=Tr},polygonStart:function(){Y_=!0},polygonEnd:function(){Y_=null},result:function(){var e=+PE;return PE=new gi,e}};function Qie(e,t){Dg.point=VI,GI=Op=e,YI=Lp=t}function VI(e,t){Op-=e,Lp-=t,PE.add(yi(Op*Op+Lp*Lp)),Op=e,Lp=t}let zD,Hv,jD,UD;class qD{constructor(t){this._append=t==null?XI:ese(t),this._radius=4.5,this._=""}pointRadius(t){return this._radius=+t,this}polygonStart(){this._line=0}polygonEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){this._line===0&&(this._+="Z"),this._point=NaN}point(t,n){switch(this._point){case 0:{this._append`M${t},${n}`,this._point=1;break}case 1:{this._append`L${t},${n}`;break}default:{if(this._append`M${t},${n}`,this._radius!==jD||this._append!==Hv){const r=this._radius,i=this._;this._="",this._append`m0,${r}a${r},${r} 0 1,1 0,${-2*r}a${r},${r} 0 1,1 0,${2*r}z`,jD=r,Hv=this._append,UD=this._,this._=i}this._+=UD;break}}}result(){const t=this._;return this._="",t.length?t:null}}function XI(e){let t=1;this._+=e[0];for(const n=e.length;t=0))throw new RangeError(`invalid digits: ${e}`);if(t>15)return XI;if(t!==zD){const n=10**t;zD=t,Hv=function(i){let s=1;this._+=i[0];for(const a=i.length;s=0))throw new RangeError(`invalid digits: ${o}`);n=l}return t===null&&(s=new qD(n)),a},a.projection(e).digits(n).context(t)}function Db(e){return function(t){var n=new BE;for(var r in e)n[r]=e[r];return n.stream=t,n}}function BE(){}BE.prototype={constructor:BE,point:function(e,t){this.stream.point(e,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};function nC(e,t,n){var r=e.clipExtent&&e.clipExtent();return e.scale(150).translate([0,0]),r!=null&&e.clipExtent(null),jo(n,e.stream(Uv)),t(Uv.result()),r!=null&&e.clipExtent(r),e}function Mb(e,t,n){return nC(e,function(r){var i=t[1][0]-t[0][0],s=t[1][1]-t[0][1],a=Math.min(i/(r[1][0]-r[0][0]),s/(r[1][1]-r[0][1])),o=+t[0][0]+(i-a*(r[1][0]+r[0][0]))/2,l=+t[0][1]+(s-a*(r[1][1]+r[0][1]))/2;e.scale(150*a).translate([o,l])},n)}function rC(e,t,n){return Mb(e,[[0,0],t],n)}function iC(e,t,n){return nC(e,function(r){var i=+t,s=i/(r[1][0]-r[0][0]),a=(i-s*(r[1][0]+r[0][0]))/2,o=-s*r[0][1];e.scale(150*s).translate([a,o])},n)}function sC(e,t,n){return nC(e,function(r){var i=+t,s=i/(r[1][1]-r[0][1]),a=-s*r[0][0],o=(i-s*(r[1][1]+r[0][1]))/2;e.scale(150*s).translate([a,o])},n)}var WD=16,tse=wt(30*Bt);function HD(e,t){return+t?rse(e,t):nse(e)}function nse(e){return Db({point:function(t,n){t=e(t,n),this.stream.point(t[0],t[1])}})}function rse(e,t){function n(r,i,s,a,o,l,u,c,f,d,h,p,g,v){var y=u-r,b=c-i,_=y*y+b*b;if(_>4*t&&g--){var x=a+d,w=o+h,A=l+p,E=yi(x*x+w*w+A*A),k=zi(A/=E),C=Vt(Vt(A)-1)<_t||Vt(s-f)<_t?(s+f)/2:Is(w,x),M=e(C,k),N=M[0],P=M[1],I=N-r,T=P-i,$=b*I-y*T;($*$/_>t||Vt((y*I+b*T)/_-.5)>.3||a*d+o*h+l*p2?$[2]%360*Bt:0,I()):[o*Hn,l*Hn,u*Hn]},N.angle=function($){return arguments.length?(f=$%360*Bt,I()):f*Hn},N.reflectX=function($){return arguments.length?(d=$?-1:1,I()):d<0},N.reflectY=function($){return arguments.length?(h=$?-1:1,I()):h<0},N.precision=function($){return arguments.length?(A=HD(E,w=$*$),T()):yi(w)},N.fitExtent=function($,L){return Mb(N,$,L)},N.fitSize=function($,L){return rC(N,$,L)},N.fitWidth=function($,L){return iC(N,$,L)},N.fitHeight=function($,L){return sC(N,$,L)};function I(){var $=GD(n,0,0,d,h,f).apply(null,t(s,a)),L=GD(n,r-$[0],i-$[1],d,h,f);return c=NI(o,l,u),E=FE(t,L),k=FE(c,E),A=HD(E,w),T()}function T(){return C=M=null,N}return function(){return t=e.apply(this,arguments),N.invert=t.invert&&P,I()}}function aC(e){var t=0,n=jt/3,r=ZI(e),i=r(t,n);return i.parallels=function(s){return arguments.length?r(t=s[0]*Bt,n=s[1]*Bt):[t*Hn,n*Hn]},i}function ose(e){var t=wt(e);function n(r,i){return[r*t,ht(i)/t]}return n.invert=function(r,i){return[r/t,zi(i*t)]},n}function lse(e,t){var n=ht(e),r=(n+ht(t))/2;if(Vt(r)<_t)return ose(e);var i=1+n*(2*r-n),s=yi(i)/r;function a(o,l){var u=yi(i-2*r*ht(l))/r;return[u*ht(o*=r),s-u*wt(o)]}return a.invert=function(o,l){var u=s-l,c=Is(o,Vt(u))*As(u);return u*r<0&&(c-=jt*As(o)*As(u)),[c/r,zi((i-(o*o+u*u)*r*r)/(2*r))]},a}function Gv(){return aC(lse).scale(155.424).center([0,33.6442])}function JI(){return Gv().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])}function use(e){var t=e.length;return{point:function(n,r){for(var i=-1;++i=.12&&v<.234&&g>=-.425&&g<-.214?i:v>=.166&&v<.234&&g>=-.214&&g<-.115?a:n).invert(d)},c.stream=function(d){return e&&t===d?e:e=use([n.stream(t=d),i.stream(d),a.stream(d)])},c.precision=function(d){return arguments.length?(n.precision(d),i.precision(d),a.precision(d),f()):n.precision()},c.scale=function(d){return arguments.length?(n.scale(d),i.scale(d*.35),a.scale(d),c.translate(n.translate())):n.scale()},c.translate=function(d){if(!arguments.length)return n.translate();var h=n.scale(),p=+d[0],g=+d[1];return r=n.translate(d).clipExtent([[p-.455*h,g-.238*h],[p+.455*h,g+.238*h]]).stream(u),s=i.translate([p-.307*h,g+.201*h]).clipExtent([[p-.425*h+_t,g+.12*h+_t],[p-.214*h-_t,g+.234*h-_t]]).stream(u),o=a.translate([p-.205*h,g+.212*h]).clipExtent([[p-.214*h+_t,g+.166*h+_t],[p-.115*h-_t,g+.234*h-_t]]).stream(u),f()},c.fitExtent=function(d,h){return Mb(c,d,h)},c.fitSize=function(d,h){return rC(c,d,h)},c.fitWidth=function(d,h){return iC(c,d,h)},c.fitHeight=function(d,h){return sC(c,d,h)};function f(){return e=t=null,c}return c.scale(1070)}function QI(e){return function(t,n){var r=wt(t),i=wt(n),s=e(r*i);return s===1/0?[2,0]:[s*i*ht(t),s*ht(n)]}}function D0(e){return function(t,n){var r=yi(t*t+n*n),i=e(r),s=ht(i),a=wt(i);return[Is(t*s,r*a),zi(r&&n*s/r)]}}var eP=QI(function(e){return yi(2/(1+e))});eP.invert=D0(function(e){return 2*zi(e/2)});function fse(){return bo(eP).scale(124.75).clipAngle(180-.001)}var tP=QI(function(e){return(e=EI(e))&&e/ht(e)});tP.invert=D0(function(e){return e});function dse(){return bo(tP).scale(79.4188).clipAngle(180-.001)}function Tb(e,t){return[e,Cv(eC((Pn+t)/2))]}Tb.invert=function(e,t){return[e,2*Mh(wI(t))-Pn]};function hse(){return nP(Tb).scale(961/vi)}function nP(e){var t=bo(e),n=t.center,r=t.scale,i=t.translate,s=t.clipExtent,a=null,o,l,u;t.scale=function(f){return arguments.length?(r(f),c()):r()},t.translate=function(f){return arguments.length?(i(f),c()):i()},t.center=function(f){return arguments.length?(n(f),c()):n()},t.clipExtent=function(f){return arguments.length?(f==null?a=o=l=u=null:(a=+f[0][0],o=+f[0][1],l=+f[1][0],u=+f[1][1]),c()):a==null?null:[[a,o],[l,u]]};function c(){var f=jt*r(),d=t(Rie(t.rotate()).invert([0,0]));return s(a==null?[[d[0]-f,d[1]-f],[d[0]+f,d[1]+f]]:e===Tb?[[Math.max(d[0]-f,a),o],[Math.min(d[0]+f,l),u]]:[[a,Math.max(d[1]-f,o)],[l,Math.min(d[1]+f,u)]])}return c()}function Fm(e){return eC((Pn+e)/2)}function pse(e,t){var n=wt(e),r=e===t?ht(e):Cv(n/wt(t))/Cv(Fm(t)/Fm(e)),i=n*q_(Fm(e),r)/r;if(!r)return Tb;function s(a,o){i>0?o<-Pn+_t&&(o=-Pn+_t):o>Pn-_t&&(o=Pn-_t);var l=i/q_(Fm(o),r);return[l*ht(r*a),i-l*wt(r*a)]}return s.invert=function(a,o){var l=i-o,u=As(r)*yi(a*a+l*l),c=Is(a,Vt(l))*As(l);return l*r<0&&(c-=jt*As(a)*As(l)),[c/r,2*Mh(q_(i/u,1/r))-Pn]},s}function gse(){return aC(pse).scale(109.5).parallels([30,30])}function Yv(e,t){return[e,t]}Yv.invert=Yv;function mse(){return bo(Yv).scale(152.63)}function vse(e,t){var n=wt(e),r=e===t?ht(e):(n-wt(t))/(t-e),i=n/r+e;if(Vt(r)<_t)return Yv;function s(a,o){var l=i-o,u=r*a;return[l*ht(u),i-l*wt(u)]}return s.invert=function(a,o){var l=i-o,u=Is(a,Vt(l))*As(l);return l*r<0&&(u-=jt*As(a)*As(l)),[u/r,i-As(r)*yi(a*a+l*l)]},s}function yse(){return aC(vse).scale(131.154).center([0,13.9389])}var ng=1.340264,rg=-.081106,ig=893e-6,sg=.003796,Vv=yi(3)/2,bse=12;function rP(e,t){var n=zi(Vv*ht(t)),r=n*n,i=r*r*r;return[e*wt(n)/(Vv*(ng+3*rg*r+i*(7*ig+9*sg*r))),n*(ng+rg*r+i*(ig+sg*r))]}rP.invert=function(e,t){for(var n=t,r=n*n,i=r*r*r,s=0,a,o,l;s_t&&--r>0);return[e/(.8707+(s=n*n)*(-.131979+s*(-.013791+s*s*s*(.003971-.001529*s)))),n]};function Ese(){return bo(sP).scale(175.295)}function aP(e,t){return[wt(t)*ht(e),ht(t)]}aP.invert=D0(zi);function Ase(){return bo(aP).scale(249.5).clipAngle(90+_t)}function oP(e,t){var n=wt(t),r=1+wt(e)*n;return[n*ht(e)/r,ht(t)/r]}oP.invert=D0(function(e){return 2*Mh(e)});function kse(){return bo(oP).scale(250).clipAngle(142)}function lP(e,t){return[Cv(eC((Pn+t)/2)),-e]}lP.invert=function(e,t){return[-t,2*Mh(wI(e))-Pn]};function Sse(){var e=nP(lP),t=e.center,n=e.rotate;return e.center=function(r){return arguments.length?t([-r[1],r[0]]):(r=t(),[r[1],-r[0]])},e.rotate=function(r){return arguments.length?n([r[0],r[1],r.length>2?r[2]+90:90]):(r=n(),[r[0],r[1],r[2]-90])},n([0,0,90]).scale(159.155)}var Cse=Math.abs,zE=Math.cos,Xv=Math.sin,$se=1e-6,uP=Math.PI,jE=uP/2,YD=Fse(2);function VD(e){return e>1?jE:e<-1?-jE:Math.asin(e)}function Fse(e){return e>0?Math.sqrt(e):0}function Dse(e,t){var n=e*Xv(t),r=30,i;do t-=i=(t+Xv(t)-n)/(1+zE(t));while(Cse(i)>$se&&--r>0);return t/2}function Mse(e,t,n){function r(i,s){return[e*i*zE(s=Dse(n,s)),t*Xv(s)]}return r.invert=function(i,s){return s=VD(s/t),[i/(e*zE(s)),VD((2*s+Xv(2*s))/n)]},r}var Tse=Mse(YD/jE,YD,uP);function Rse(){return bo(Tse).scale(169.529)}const Nse=KI(),UE=["clipAngle","clipExtent","scale","translate","center","rotate","parallels","precision","reflectX","reflectY","coefficient","distance","fraction","lobes","parallel","radius","ratio","spacing","tilt"];function Ose(e,t){return function n(){const r=t();return r.type=e,r.path=KI().projection(r),r.copy=r.copy||function(){const i=n();return UE.forEach(s=>{r[s]&&i[s](r[s]())}),i.path.pointRadius(r.path.pointRadius()),i},A9(r)}}function oC(e,t){if(!e||typeof e!="string")throw new Error("Projection type must be a name string.");return e=e.toLowerCase(),arguments.length>1?(Kv[e]=Ose(e,t),this):Kv[e]||null}function cP(e){return e&&e.path||Nse}const Kv={albers:JI,albersusa:cse,azimuthalequalarea:fse,azimuthalequidistant:dse,conicconformal:gse,conicequalarea:Gv,conicequidistant:yse,equalEarth:_se,equirectangular:mse,gnomonic:xse,identity:wse,mercator:hse,mollweide:Rse,naturalEarth1:Ese,orthographic:Ase,stereographic:kse,transversemercator:Sse};for(const e in Kv)oC(e,Kv[e]);function Lse(){}const Mo=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function fP(){var e=1,t=1,n=o;function r(l,u){return u.map(c=>i(l,c))}function i(l,u){var c=[],f=[];return s(l,u,d=>{n(d,l,u),Ise(d)>0?c.push([d]):f.push(d)}),f.forEach(d=>{for(var h=0,p=c.length,g;h=u,Mo[v<<1].forEach(_);++h=u,Mo[g|v<<1].forEach(_);for(Mo[v<<0].forEach(_);++p=u,y=l[p*e]>=u,Mo[v<<1|y<<2].forEach(_);++h=u,b=y,y=l[p*e+h+1]>=u,Mo[g|v<<1|y<<2|b<<3].forEach(_);Mo[v|y<<3].forEach(_)}for(h=-1,y=l[p*e]>=u,Mo[y<<2].forEach(_);++h=u,Mo[y<<2|b<<3].forEach(_);Mo[y<<3].forEach(_);function _(x){var w=[x[0][0]+h,x[0][1]+p],A=[x[1][0]+h,x[1][1]+p],E=a(w),k=a(A),C,M;(C=d[E])?(M=f[k])?(delete d[C.end],delete f[M.start],C===M?(C.ring.push(A),c(C.ring)):f[C.start]=d[M.end]={start:C.start,end:M.end,ring:C.ring.concat(M.ring)}):(delete d[C.end],C.ring.push(A),d[C.end=k]=C):(C=f[k])?(M=d[E])?(delete f[C.start],delete d[M.end],C===M?(C.ring.push(A),c(C.ring)):f[M.start]=d[C.end]={start:M.start,end:C.end,ring:M.ring.concat(C.ring)}):(delete f[C.start],C.ring.unshift(w),f[C.start=E]=C):f[E]=d[k]={start:E,end:k,ring:[w,A]}}}function a(l){return l[0]*2+l[1]*(e+1)*4}function o(l,u,c){l.forEach(f=>{var d=f[0],h=f[1],p=d|0,g=h|0,v,y=u[g*e+p];d>0&&d0&&h=0&&c>=0||ye("invalid size"),e=u,t=c,r},r.smooth=function(l){return arguments.length?(n=l?o:Lse,r):n===o},r}function Ise(e){for(var t=0,n=e.length,r=e[n-1][1]*e[0][0]-e[n-1][0]*e[0][1];++tr!=h>r&&n<(d-u)*(r-c)/(h-c)+u&&(i=-i)}return i}function zse(e,t,n){var r;return jse(e,t,n)&&Use(e[r=+(e[0]===t[0])],n[r],t[r])}function jse(e,t,n){return(t[0]-e[0])*(n[1]-e[1])===(n[0]-e[0])*(t[1]-e[1])}function Use(e,t,n){return e<=t&&t<=n||n<=t&&t<=e}function dP(e,t,n){return function(r){var i=io(r),s=n?Math.min(i[0],0):i[0],a=i[1],o=a-s,l=t?iu(s,a,e):o/(e+1);return ts(s+l,a,l)}}function lC(e){de.call(this,null,e)}lC.Definition={type:"Isocontour",metadata:{generates:!0},params:[{name:"field",type:"field"},{name:"thresholds",type:"number",array:!0},{name:"levels",type:"number"},{name:"nice",type:"boolean",default:!1},{name:"resolve",type:"enum",values:["shared","independent"],default:"independent"},{name:"zero",type:"boolean",default:!0},{name:"smooth",type:"boolean",default:!0},{name:"scale",type:"number",expr:!0},{name:"translate",type:"number",array:!0,expr:!0},{name:"as",type:"string",null:!0,default:"contour"}]};Be(lC,de,{transform(e,t){if(this.value&&!t.changed()&&!e.modified())return t.StopPropagation;var n=t.fork(t.NO_SOURCE|t.NO_FIELDS),r=t.materialize(t.SOURCE).source,i=e.field||ei,s=fP().smooth(e.smooth!==!1),a=e.thresholds||qse(r,i,e),o=e.as===null?null:e.as||"contour",l=[];return r.forEach(u=>{const c=i(u),f=s.size([c.width,c.height])(c.values,Se(a)?a:a(c.values));Wse(f,c,u,e),f.forEach(d=>{l.push(Xy(u,nn(o!=null?{[o]:d}:d)))})}),this.value&&(n.rem=this.value),this.value=n.source=n.add=l,n}});function qse(e,t,n){const r=dP(n.levels||10,n.nice,n.zero!==!1);return n.resolve!=="shared"?r:r(e.map(i=>wc(t(i).values)))}function Wse(e,t,n,r){let i=r.scale||t.scale,s=r.translate||t.translate;if(Rt(i)&&(i=i(n,r)),Rt(s)&&(s=s(n,r)),(i===1||i==null)&&!s)return;const a=(Qt(i)?i:i[0])||1,o=(Qt(i)?i:i[1])||1,l=s&&s[0]||0,u=s&&s[1]||0;e.forEach(hP(t,a,o,l,u))}function hP(e,t,n,r,i){const s=e.x1||0,a=e.y1||0,o=t*n<0;function l(f){f.forEach(u)}function u(f){o&&f.reverse(),f.forEach(c)}function c(f){f[0]=(f[0]-s)*t+r,f[1]=(f[1]-a)*n+i}return function(f){return f.coordinates.forEach(l),f}}function XD(e,t,n){const r=e>=0?e:eS(t,n);return Math.round((Math.sqrt(4*r*r+1)-1)/2)}function V_(e){return Rt(e)?e:ti(+e)}function pP(){var e=l=>l[0],t=l=>l[1],n=vh,r=[-1,-1],i=960,s=500,a=2;function o(l,u){const c=XD(r[0],l,e)>>a,f=XD(r[1],l,t)>>a,d=c?c+2:0,h=f?f+2:0,p=2*d+(i>>a),g=2*h+(s>>a),v=new Float32Array(p*g),y=new Float32Array(p*g);let b=v;l.forEach(x=>{const w=d+(+e(x)>>a),A=h+(+t(x)>>a);w>=0&&w=0&&A0&&f>0?(Lf(p,g,v,y,c),If(p,g,y,v,f),Lf(p,g,v,y,c),If(p,g,y,v,f),Lf(p,g,v,y,c),If(p,g,y,v,f)):c>0?(Lf(p,g,v,y,c),Lf(p,g,y,v,c),Lf(p,g,v,y,c),b=y):f>0&&(If(p,g,v,y,f),If(p,g,y,v,f),If(p,g,v,y,f),b=y);const _=u?Math.pow(2,-2*a):1/FN(b);for(let x=0,w=p*g;x>a),y2:h+(s>>a)}}return o.x=function(l){return arguments.length?(e=V_(l),o):e},o.y=function(l){return arguments.length?(t=V_(l),o):t},o.weight=function(l){return arguments.length?(n=V_(l),o):n},o.size=function(l){if(!arguments.length)return[i,s];var u=+l[0],c=+l[1];return u>=0&&c>=0||ye("invalid size"),i=u,s=c,o},o.cellSize=function(l){return arguments.length?((l=+l)>=1||ye("invalid cell size"),a=Math.floor(Math.log(l)/Math.LN2),o):1<=i&&(o>=s&&(l-=n[o-s+a*e]),r[o-i+a*e]=l/Math.min(o+1,e-1+s-o,s))}function If(e,t,n,r,i){const s=(i<<1)+1;for(let a=0;a=i&&(o>=s&&(l-=n[a+(o-s)*e]),r[a+(o-i)*e]=l/Math.min(o+1,t-1+s-o,s))}function uC(e){de.call(this,null,e)}uC.Definition={type:"KDE2D",metadata:{generates:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"x",type:"field",required:!0},{name:"y",type:"field",required:!0},{name:"weight",type:"field"},{name:"groupby",type:"field",array:!0},{name:"cellSize",type:"number"},{name:"bandwidth",type:"number",array:!0,length:2},{name:"counts",type:"boolean",default:!1},{name:"as",type:"string",default:"grid"}]};const Hse=["x","y","weight","size","cellSize","bandwidth"];function gP(e,t){return Hse.forEach(n=>t[n]!=null?e[n](t[n]):0),e}Be(uC,de,{transform(e,t){if(this.value&&!t.changed()&&!e.modified())return t.StopPropagation;var n=t.fork(t.NO_SOURCE|t.NO_FIELDS),r=t.materialize(t.SOURCE).source,i=Gse(r,e.groupby),s=(e.groupby||[]).map(zn),a=gP(pP(),e),o=e.as||"grid",l=[];function u(c,f){for(let d=0;dnn(u({[o]:a(c,e.counts)},c.dims))),this.value&&(n.rem=this.value),this.value=n.source=n.add=l,n}});function Gse(e,t){var n=[],r=c=>c(o),i,s,a,o,l,u;if(t==null)n.push(e);else for(i={},s=0,a=e.length;sn.push(o(c))),s&&a&&(t.visit(l,c=>{var f=s(c),d=a(c);f!=null&&d!=null&&(f=+f)===f&&(d=+d)===d&&r.push([f,d])}),n=n.concat({type:qE,geometry:{type:Yse,coordinates:r}})),this.value={type:fC,features:n}}});function hC(e){de.call(this,null,e)}hC.Definition={type:"GeoPath",metadata:{modifies:!0},params:[{name:"projection",type:"projection"},{name:"field",type:"field"},{name:"pointRadius",type:"number",expr:!0},{name:"as",type:"string",default:"path"}]};Be(hC,de,{transform(e,t){var n=t.fork(t.ALL),r=this.value,i=e.field||ei,s=e.as||"path",a=n.SOURCE;!r||e.modified()?(this.value=r=cP(e.projection),n.materialize().reflow()):a=i===ei||t.modified(i.fields)?n.ADD_MOD:n.ADD;const o=Vse(r,e.pointRadius);return n.visit(a,l=>l[s]=r(i(l))),r.pointRadius(o),n.modifies(s)}});function Vse(e,t){const n=e.pointRadius();return e.context(null),t!=null&&e.pointRadius(t),n}function pC(e){de.call(this,null,e)}pC.Definition={type:"GeoPoint",metadata:{modifies:!0},params:[{name:"projection",type:"projection",required:!0},{name:"fields",type:"field",array:!0,required:!0,length:2},{name:"as",type:"string",array:!0,length:2,default:["x","y"]}]};Be(pC,de,{transform(e,t){var n=e.projection,r=e.fields[0],i=e.fields[1],s=e.as||["x","y"],a=s[0],o=s[1],l;function u(c){const f=n([r(c),i(c)]);f?(c[a]=f[0],c[o]=f[1]):(c[a]=void 0,c[o]=void 0)}return e.modified()?t=t.materialize().reflow(!0).visit(t.SOURCE,u):(l=t.modified(r.fields)||t.modified(i.fields),t.visit(l?t.ADD_MOD:t.ADD,u)),t.modifies(s)}});function gC(e){de.call(this,null,e)}gC.Definition={type:"GeoShape",metadata:{modifies:!0,nomod:!0},params:[{name:"projection",type:"projection"},{name:"field",type:"field",default:"datum"},{name:"pointRadius",type:"number",expr:!0},{name:"as",type:"string",default:"shape"}]};Be(gC,de,{transform(e,t){var n=t.fork(t.ALL),r=this.value,i=e.as||"shape",s=n.ADD;return(!r||e.modified())&&(this.value=r=Xse(cP(e.projection),e.field||Ns("datum"),e.pointRadius),n.materialize().reflow(),s=n.SOURCE),n.visit(s,a=>a[i]=r),n.modifies(i)}});function Xse(e,t,n){const r=n==null?i=>e(t(i)):i=>{var s=e.pointRadius(),a=e.pointRadius(n)(t(i));return e.pointRadius(s),a};return r.context=i=>(e.context(i),r),r}function mC(e){de.call(this,[],e),this.generator=qie()}mC.Definition={type:"Graticule",metadata:{changes:!0,generates:!0},params:[{name:"extent",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"extentMajor",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"extentMinor",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"step",type:"number",array:!0,length:2},{name:"stepMajor",type:"number",array:!0,length:2,default:[90,360]},{name:"stepMinor",type:"number",array:!0,length:2,default:[10,10]},{name:"precision",type:"number",default:2.5}]};Be(mC,de,{transform(e,t){var n=this.value,r=this.generator,i;if(!n.length||e.modified())for(const s in e)Rt(r[s])&&r[s](e[s]);return i=r(),n.length?t.mod.push(EO(n[0],i)):t.add.push(nn(i)),n[0]=i,t}});function vC(e){de.call(this,null,e)}vC.Definition={type:"heatmap",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"color",type:"string",expr:!0},{name:"opacity",type:"number",expr:!0},{name:"resolve",type:"enum",values:["shared","independent"],default:"independent"},{name:"as",type:"string",default:"image"}]};Be(vC,de,{transform(e,t){if(!t.changed()&&!e.modified())return t.StopPropagation;var n=t.materialize(t.SOURCE).source,r=e.resolve==="shared",i=e.field||ei,s=Zse(e.opacity,e),a=Kse(e.color,e),o=e.as||"image",l={$x:0,$y:0,$value:0,$max:r?wc(n.map(u=>wc(i(u).values))):0};return n.forEach(u=>{const c=i(u),f=Tt({},u,l);r||(f.$max=wc(c.values||[])),u[o]=Jse(c,f,a.dep?a:ti(a(f)),s.dep?s:ti(s(f)))}),t.reflow(!0).modifies(o)}});function Kse(e,t){let n;return Rt(e)?(n=r=>ou(e(r,t)),n.dep=mP(e)):n=ti(ou(e||"#888")),n}function Zse(e,t){let n;return Rt(e)?(n=r=>e(r,t),n.dep=mP(e)):e?n=ti(e):(n=r=>r.$value/r.$max||0,n.dep=!0),n}function mP(e){if(!Rt(e))return!1;const t=da(Vr(e));return t.$x||t.$y||t.$value||t.$max}function Jse(e,t,n,r){const i=e.width,s=e.height,a=e.x1||0,o=e.y1||0,l=e.x2||i,u=e.y2||s,c=e.values,f=c?v=>c[v]:Rl,d=Jl(l-a,u-o),h=d.getContext("2d"),p=h.getImageData(0,0,l-a,u-o),g=p.data;for(let v=o,y=0;v{e[r]!=null&&KD(n,r,e[r])})):UE.forEach(r=>{e.modified(r)&&KD(n,r,e[r])}),e.pointRadius!=null&&n.path.pointRadius(e.pointRadius),e.fit&&Qse(n,e),t.fork(t.NO_SOURCE|t.NO_FIELDS)}});function Qse(e,t){const n=tae(t.fit);t.extent?e.fitExtent(t.extent,n):t.size&&e.fitSize(t.size,n)}function eae(e){const t=oC((e||"mercator").toLowerCase());return t||ye("Unrecognized projection type: "+e),t()}function KD(e,t,n){Rt(e[t])&&e[t](n)}function tae(e){return e=He(e),e.length===1?e[0]:{type:fC,features:e.reduce((t,n)=>t.concat(nae(n)),[])}}function nae(e){return e.type===fC?e.features:He(e).filter(t=>t!=null).map(t=>t.type===qE?t:{type:qE,geometry:t})}const rae=Object.freeze(Object.defineProperty({__proto__:null,contour:cC,geojson:dC,geopath:hC,geopoint:pC,geoshape:gC,graticule:mC,heatmap:vC,isocontour:lC,kde2d:uC,projection:vP},Symbol.toStringTag,{value:"Module"}));function iae(e,t){var n,r=1;e==null&&(e=0),t==null&&(t=0);function i(){var s,a=n.length,o,l=0,u=0;for(s=0;s=(f=(o+u)/2))?o=f:u=f,(v=n>=(d=(l+c)/2))?l=d:c=d,i=s,!(s=s[y=v<<1|g]))return i[y]=a,e;if(h=+e._x.call(null,s.data),p=+e._y.call(null,s.data),t===h&&n===p)return a.next=s,i?i[y]=a:e._root=a,e;do i=i?i[y]=new Array(4):e._root=new Array(4),(g=t>=(f=(o+u)/2))?o=f:u=f,(v=n>=(d=(l+c)/2))?l=d:c=d;while((y=v<<1|g)===(b=(p>=d)<<1|h>=f));return i[b]=s,i[y]=a,e}function aae(e){var t,n,r=e.length,i,s,a=new Array(r),o=new Array(r),l=1/0,u=1/0,c=-1/0,f=-1/0;for(n=0;nc&&(c=i),sf&&(f=s));if(l>c||u>f)return this;for(this.cover(l,u).cover(c,f),n=0;ne||e>=i||r>t||t>=s;)switch(u=(tc||(o=p.y0)>f||(l=p.x1)=y)<<1|e>=v)&&(p=d[d.length-1],d[d.length-1]=d[d.length-1-g],d[d.length-1-g]=p)}else{var b=e-+this._x.call(null,h.data),_=t-+this._y.call(null,h.data),x=b*b+_*_;if(x=(d=(a+l)/2))?a=d:l=d,(g=f>=(h=(o+u)/2))?o=h:u=h,t=n,!(n=n[v=g<<1|p]))return this;if(!n.length)break;(t[v+1&3]||t[v+2&3]||t[v+3&3])&&(r=t,y=v)}for(;n.data!==e;)if(i=n,!(n=n.next))return this;return(s=n.next)&&delete n.next,i?(s?i.next=s:delete i.next,this):t?(s?t[v]=s:delete t[v],(n=t[0]||t[1]||t[2]||t[3])&&n===(t[3]||t[2]||t[1]||t[0])&&!n.length&&(r?r[y]=n:this._root=n),this):(this._root=s,this)}function dae(e){for(var t=0,n=e.length;td.index){var N=h-k.x-k.vx,P=p-k.y-k.vy,I=N*N+P*P;Ih+M||Ap+M||Eu.r&&(u.r=u[c].r)}function l(){if(t){var u,c=t.length,f;for(n=new Array(c),u=0;u[t(w,A,a),w])),x;for(v=0,o=new Array(y);v{}};function bP(){for(var e=0,t=arguments.length,n={},r;e=0&&(r=n.slice(i+1),n=n.slice(0,i)),n&&!t.hasOwnProperty(n))throw new Error("unknown type: "+n);return{type:n,name:r}})}A1.prototype=bP.prototype={constructor:A1,on:function(e,t){var n=this._,r=Cae(e+"",n),i,s=-1,a=r.length;if(arguments.length<2){for(;++s0)for(var n=new Array(i),r=0,i,s;r=0&&e._call.call(void 0,t),e=e._next;--Xd}function eM(){Yc=(Jv=Mg.now())+Rb,Xd=Ip=0;try{Dae()}finally{Xd=0,Tae(),Yc=0}}function Mae(){var e=Mg.now(),t=e-Jv;t>_P&&(Rb-=t,Jv=e)}function Tae(){for(var e,t=Zv,n,r=1/0;t;)t._call?(r>t._time&&(r=t._time),e=t,t=t._next):(n=t._next,t._next=null,t=e?e._next=n:Zv=n);Pp=e,WE(r)}function WE(e){if(!Xd){Ip&&(Ip=clearTimeout(Ip));var t=e-Yc;t>24?(e<1/0&&(Ip=setTimeout(eM,e-Mg.now()-Rb)),lp&&(lp=clearInterval(lp))):(lp||(Jv=Mg.now(),lp=setInterval(Mae,_P)),Xd=1,xP(eM))}}function Rae(e,t,n){var r=new Qv,i=t;return t==null?(r.restart(e,t,n),r):(r._restart=r.restart,r.restart=function(s,a,o){a=+a,o=o==null?_C():+o,r._restart(function l(u){u+=i,r._restart(l,i+=a,o),s(u)},a,o)},r.restart(e,t,n),r)}const Nae=1664525,Oae=1013904223,tM=4294967296;function Lae(){let e=1;return()=>(e=(Nae*e+Oae)%tM)/tM}function Iae(e){return e.x}function Pae(e){return e.y}var Bae=10,zae=Math.PI*(3-Math.sqrt(5));function jae(e){var t,n=1,r=.001,i=1-Math.pow(r,1/300),s=0,a=.6,o=new Map,l=wP(f),u=bP("tick","end"),c=Lae();e==null&&(e=[]);function f(){d(),u.call("tick",t),n1?(v==null?o.delete(g):o.set(g,p(v)),t):o.get(g)},find:function(g,v,y){var b=0,_=e.length,x,w,A,E,k;for(y==null?y=1/0:y*=y,b=0;b<_;++b)E=e[b],x=g-E.x,w=v-E.y,A=x*x+w*w,A1?(u.on(g,v),t):u.on(g)}}}function Uae(){var e,t,n,r,i=hi(-30),s,a=1,o=1/0,l=.81;function u(h){var p,g=e.length,v=yC(e,Iae,Pae).visitAfter(f);for(r=h,p=0;p=o)return;(h.data!==t||h.next)&&(y===0&&(y=ql(n),x+=y*y),b===0&&(b=ql(n),x+=b*b),x=0;)n.tick();else if(n.stopped()&&n.restart(),!r)return t.StopPropagation}return this.finish(e,t)},finish(e,t){const n=t.dataflow;for(let o=this._argops,l=0,u=o.length,c;le.touch(t).run()}function Yae(e,t){const n=jae(e),r=n.stop,i=n.restart;let s=!1;return n.stopped=()=>s,n.restart=()=>(s=!1,i()),n.stop=()=>(s=!0,r()),AP(n,t,!0).on("end",()=>s=!0)}function AP(e,t,n,r){var i=He(t.forces),s,a,o,l;for(s=0,a=HE.length;st(r,n):t)}const Zae=Object.freeze(Object.defineProperty({__proto__:null,force:xC},Symbol.toStringTag,{value:"Module"}));function Jae(e,t){return e.parent===t.parent?1:2}function Qae(e){return e.reduce(eoe,0)/e.length}function eoe(e,t){return e+t.x}function toe(e){return 1+e.reduce(noe,0)}function noe(e,t){return Math.max(e,t.y)}function roe(e){for(var t;t=e.children;)e=t[0];return e}function ioe(e){for(var t;t=e.children;)e=t[t.length-1];return e}function soe(){var e=Jae,t=1,n=1,r=!1;function i(s){var a,o=0;s.eachAfter(function(d){var h=d.children;h?(d.x=Qae(h),d.y=toe(h)):(d.x=a?o+=e(d,a):0,d.y=0,a=d)});var l=roe(s),u=ioe(s),c=l.x-e(l,u)/2,f=u.x+e(u,l)/2;return s.eachAfter(r?function(d){d.x=(d.x-s.x)*t,d.y=(s.y-d.y)*n}:function(d){d.x=(d.x-c)/(f-c)*t,d.y=(1-(s.y?d.y/s.y:1))*n})}return i.separation=function(s){return arguments.length?(e=s,i):e},i.size=function(s){return arguments.length?(r=!1,t=+s[0],n=+s[1],i):r?null:[t,n]},i.nodeSize=function(s){return arguments.length?(r=!0,t=+s[0],n=+s[1],i):r?[t,n]:null},i}function aoe(e){var t=0,n=e.children,r=n&&n.length;if(!r)t=1;else for(;--r>=0;)t+=n[r].value;e.value=t}function ooe(){return this.eachAfter(aoe)}function loe(e,t){let n=-1;for(const r of this)e.call(t,r,++n,this);return this}function uoe(e,t){for(var n=this,r=[n],i,s,a=-1;n=r.pop();)if(e.call(t,n,++a,this),i=n.children)for(s=i.length-1;s>=0;--s)r.push(i[s]);return this}function coe(e,t){for(var n=this,r=[n],i=[],s,a,o,l=-1;n=r.pop();)if(i.push(n),s=n.children)for(a=0,o=s.length;a=0;)n+=r[i].value;t.value=n})}function hoe(e){return this.eachBefore(function(t){t.children&&t.children.sort(e)})}function poe(e){for(var t=this,n=goe(t,e),r=[t];t!==n;)t=t.parent,r.push(t);for(var i=r.length;e!==n;)r.splice(i,0,e),e=e.parent;return r}function goe(e,t){if(e===t)return e;var n=e.ancestors(),r=t.ancestors(),i=null;for(e=n.pop(),t=r.pop();e===t;)i=e,e=n.pop(),t=r.pop();return i}function moe(){for(var e=this,t=[e];e=e.parent;)t.push(e);return t}function voe(){return Array.from(this)}function yoe(){var e=[];return this.eachBefore(function(t){t.children||e.push(t)}),e}function boe(){var e=this,t=[];return e.each(function(n){n!==e&&t.push({source:n.parent,target:n})}),t}function*_oe(){var e=this,t,n=[e],r,i,s;do for(t=n.reverse(),n=[];e=t.pop();)if(yield e,r=e.children)for(i=0,s=r.length;i=0;--o)i.push(s=a[o]=new Kd(a[o])),s.parent=r,s.depth=r.depth+1;return n.eachBefore(kP)}function xoe(){return wC(this).eachBefore(Aoe)}function woe(e){return e.children}function Eoe(e){return Array.isArray(e)?e[1]:null}function Aoe(e){e.data.value!==void 0&&(e.value=e.data.value),e.data=e.data.data}function kP(e){var t=0;do e.height=t;while((e=e.parent)&&e.height<++t)}function Kd(e){this.data=e,this.depth=this.height=0,this.parent=null}Kd.prototype=wC.prototype={constructor:Kd,count:ooe,each:loe,eachAfter:coe,eachBefore:uoe,find:foe,sum:doe,sort:hoe,path:poe,ancestors:moe,descendants:voe,leaves:yoe,links:boe,copy:xoe,[Symbol.iterator]:_oe};function k1(e){return e==null?null:SP(e)}function SP(e){if(typeof e!="function")throw new Error;return e}function oc(){return 0}function Yf(e){return function(){return e}}const koe=1664525,Soe=1013904223,rM=4294967296;function Coe(){let e=1;return()=>(e=(koe*e+Soe)%rM)/rM}function $oe(e){return typeof e=="object"&&"length"in e?e:Array.from(e)}function Foe(e,t){let n=e.length,r,i;for(;n;)i=t()*n--|0,r=e[n],e[n]=e[i],e[i]=r;return e}function Doe(e,t){for(var n=0,r=(e=Foe(Array.from(e),t)).length,i=[],s,a;n0&&n*n>r*r+i*i}function X_(e,t){for(var n=0;n1e-6?(N+Math.sqrt(N*N-4*M*P))/(2*M):P/N);return{x:r+A+E*I,y:i+k+C*I,r:I}}function iM(e,t,n){var r=e.x-t.x,i,s,a=e.y-t.y,o,l,u=r*r+a*a;u?(s=t.r+n.r,s*=s,l=e.r+n.r,l*=l,s>l?(i=(u+l-s)/(2*u),o=Math.sqrt(Math.max(0,l/u-i*i)),n.x=e.x-i*r-o*a,n.y=e.y-i*a+o*r):(i=(u+s-l)/(2*u),o=Math.sqrt(Math.max(0,s/u-i*i)),n.x=t.x+i*r-o*a,n.y=t.y+i*a+o*r)):(n.x=t.x+n.r,n.y=t.y)}function sM(e,t){var n=e.r+t.r-1e-6,r=t.x-e.x,i=t.y-e.y;return n>0&&n*n>r*r+i*i}function aM(e){var t=e._,n=e.next._,r=t.r+n.r,i=(t.x*n.r+n.x*t.r)/r,s=(t.y*n.r+n.y*t.r)/r;return i*i+s*s}function Mm(e){this._=e,this.next=null,this.previous=null}function Noe(e,t){if(!(s=(e=$oe(e)).length))return 0;var n,r,i,s,a,o,l,u,c,f,d;if(n=e[0],n.x=0,n.y=0,!(s>1))return n.r;if(r=e[1],n.x=-r.r,r.x=n.r,r.y=0,!(s>2))return n.r+r.r;iM(r,n,i=e[2]),n=new Mm(n),r=new Mm(r),i=new Mm(i),n.next=i.previous=r,r.next=n.previous=i,i.next=r.previous=n;e:for(l=3;ljoe(n(x,w,i))),b=y.map(fM),_=new Set(y).add("");for(const x of b)_.has(x)||(_.add(x),y.push(x),b.push(fM(x)),s.push(Z_));a=(x,w)=>y[w],o=(x,w)=>b[w]}for(c=0,l=s.length;c=0&&(h=s[y],h.data===Z_);--y)h.data=null}if(f.parent=Poe,f.eachBefore(function(y){y.depth=y.parent.depth+1,--l}).eachBefore(kP),f.parent=null,l>0)throw new Error("cycle");return f}return r.id=function(i){return arguments.length?(e=k1(i),r):e},r.parentId=function(i){return arguments.length?(t=k1(i),r):t},r.path=function(i){return arguments.length?(n=k1(i),r):n},r}function joe(e){e=`${e}`;let t=e.length;return GE(e,t-1)&&!GE(e,t-2)&&(e=e.slice(0,-1)),e[0]==="/"?e:`/${e}`}function fM(e){let t=e.length;if(t<2)return"";for(;--t>1&&!GE(e,t););return e.slice(0,t)}function GE(e,t){if(e[t]==="/"){let n=0;for(;t>0&&e[--t]==="\\";)++n;if((n&1)===0)return!0}return!1}function Uoe(e,t){return e.parent===t.parent?1:2}function J_(e){var t=e.children;return t?t[0]:e.t}function Q_(e){var t=e.children;return t?t[t.length-1]:e.t}function qoe(e,t,n){var r=n/(t.i-e.i);t.c-=r,t.s+=n,e.c+=r,t.z+=n,t.m+=n}function Woe(e){for(var t=0,n=0,r=e.children,i=r.length,s;--i>=0;)s=r[i],s.z+=t,s.m+=t,t+=s.s+(n+=s.c)}function Hoe(e,t,n){return e.a.parent===t.parent?e.a:n}function S1(e,t){this._=e,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=t}S1.prototype=Object.create(Kd.prototype);function Goe(e){for(var t=new S1(e,0),n,r=[t],i,s,a,o;n=r.pop();)if(s=n._.children)for(n.children=new Array(o=s.length),a=o-1;a>=0;--a)r.push(i=n.children[a]=new S1(s[a],a)),i.parent=n;return(t.parent=new S1(null,0)).children=[t],t}function Yoe(){var e=Uoe,t=1,n=1,r=null;function i(u){var c=Goe(u);if(c.eachAfter(s),c.parent.m=-c.z,c.eachBefore(a),r)u.eachBefore(l);else{var f=u,d=u,h=u;u.eachBefore(function(b){b.xd.x&&(d=b),b.depth>h.depth&&(h=b)});var p=f===d?1:e(f,d)/2,g=p-f.x,v=t/(d.x+p+g),y=n/(h.depth||1);u.eachBefore(function(b){b.x=(b.x+g)*v,b.y=b.depth*y})}return u}function s(u){var c=u.children,f=u.parent.children,d=u.i?f[u.i-1]:null;if(c){Woe(u);var h=(c[0].z+c[c.length-1].z)/2;d?(u.z=d.z+e(u._,d._),u.m=u.z-h):u.z=h}else d&&(u.z=d.z+e(u._,d._));u.parent.A=o(u,d,u.parent.A||f[0])}function a(u){u._.x=u.z+u.parent.m,u.m+=u.parent.m}function o(u,c,f){if(c){for(var d=u,h=u,p=c,g=d.parent.children[0],v=d.m,y=h.m,b=p.m,_=g.m,x;p=Q_(p),d=J_(d),p&&d;)g=J_(g),h=Q_(h),h.a=u,x=p.z+b-d.z-v+e(p._,d._),x>0&&(qoe(Hoe(p,u,f),u,x),v+=x,y+=x),b+=p.m,v+=d.m,_+=g.m,y+=h.m;p&&!Q_(h)&&(h.t=p,h.m+=b-y),d&&!J_(g)&&(g.t=d,g.m+=v-_,f=u)}return f}function l(u){u.x*=t,u.y=u.depth*n}return i.separation=function(u){return arguments.length?(e=u,i):e},i.size=function(u){return arguments.length?(r=!1,t=+u[0],n=+u[1],i):r?null:[t,n]},i.nodeSize=function(u){return arguments.length?(r=!0,t=+u[0],n=+u[1],i):r?[t,n]:null},i}function Nb(e,t,n,r,i){for(var s=e.children,a,o=-1,l=s.length,u=e.value&&(i-n)/e.value;++ob&&(b=u),A=v*v*w,_=Math.max(b/A,A/y),_>x){v-=u;break}x=_}a.push(l={value:v,dice:h1?r:1)},n})(DP);function Voe(){var e=TP,t=!1,n=1,r=1,i=[0],s=oc,a=oc,o=oc,l=oc,u=oc;function c(d){return d.x0=d.y0=0,d.x1=n,d.y1=r,d.eachBefore(f),i=[0],t&&d.eachBefore(FP),d}function f(d){var h=i[d.depth],p=d.x0+h,g=d.y0+h,v=d.x1-h,y=d.y1-h;v=d-1){var b=s[f];b.x0=p,b.y0=g,b.x1=v,b.y1=y;return}for(var _=u[f],x=h/2+_,w=f+1,A=d-1;w>>1;u[E]y-g){var M=h?(p*C+v*k)/h:v;c(f,w,k,p,g,M,y),c(w,d,C,M,g,v,y)}else{var N=h?(g*C+y*k)/h:y;c(f,w,k,p,g,v,N),c(w,d,C,p,N,v,y)}}}function Koe(e,t,n,r,i){(e.depth&1?Nb:M0)(e,t,n,r,i)}const Zoe=(function e(t){function n(r,i,s,a,o){if((l=r._squarify)&&l.ratio===t)for(var l,u,c,f,d=-1,h,p=l.length,g=r.value;++d1?r:1)},n})(DP);function YE(e,t,n){const r={};return e.each(i=>{const s=i.data;n(s)&&(r[t(s)]=i)}),e.lookup=r,e}function EC(e){de.call(this,null,e)}EC.Definition={type:"Nest",metadata:{treesource:!0,changes:!0},params:[{name:"keys",type:"field",array:!0},{name:"generate",type:"boolean"}]};const Joe=e=>e.values;Be(EC,de,{transform(e,t){t.source||ye("Nest transform requires an upstream data source.");var n=e.generate,r=e.modified(),i=t.clone(),s=this.value;return(!s||r||t.changed())&&(s&&s.each(a=>{a.children&&Vy(a.data)&&i.rem.push(a.data)}),this.value=s=wC({values:He(e.keys).reduce((a,o)=>(a.key(o),a),Qoe()).entries(i.source)},Joe),n&&s.each(a=>{a.children&&(a=nn(a.data),i.add.push(a),i.source.push(a))}),YE(s,dt,dt)),i.source.root=s,i}});function Qoe(){const e=[],t={entries:i=>r(n(i,0),0),key:i=>(e.push(i),t)};function n(i,s){if(s>=e.length)return i;const a=i.length,o=e[s++],l={},u={};let c=-1,f,d,h;for(;++ce.length)return i;const a=[];for(const o in i)a.push({key:o,values:r(i[o],s)});return a}return t}function pl(e){de.call(this,null,e)}const ele=(e,t)=>e.parent===t.parent?1:2;Be(pl,de,{transform(e,t){(!t.source||!t.source.root)&&ye(this.constructor.name+" transform requires a backing tree data source.");const n=this.layout(e.method),r=this.fields,i=t.source.root,s=e.as||r;e.field?i.sum(e.field):i.count(),e.sort&&i.sort(gf(e.sort,a=>a.data)),tle(n,this.params,e),n.separation&&n.separation(e.separation!==!1?ele:vh);try{this.value=n(i)}catch(a){ye(a)}return i.each(a=>nle(a,r,s)),t.reflow(e.modified()).modifies(s).modifies("leaf")}});function tle(e,t,n){for(let r,i=0,s=t.length;is[dt(a)]=1),r.each(a=>{const o=a.data,l=a.parent&&a.parent.data;l&&s[dt(o)]&&s[dt(l)]&&i.add.push(nn({source:l,target:o}))}),this.value=i.add):t.changed(t.MOD)&&(t.visit(t.MOD,a=>s[dt(a)]=1),n.forEach(a=>{(s[dt(a.source)]||s[dt(a.target)])&&i.mod.push(a)})),i}});const hM={binary:Xoe,dice:M0,slice:Nb,slicedice:Koe,squarify:TP,resquarify:Zoe},ZE=["x0","y0","x1","y1","depth","children"];function FC(e){pl.call(this,e)}FC.Definition={type:"Treemap",metadata:{tree:!0,modifies:!0},params:[{name:"field",type:"field"},{name:"sort",type:"compare"},{name:"method",type:"enum",default:"squarify",values:["squarify","resquarify","binary","dice","slice","slicedice"]},{name:"padding",type:"number",default:0},{name:"paddingInner",type:"number",default:0},{name:"paddingOuter",type:"number",default:0},{name:"paddingTop",type:"number",default:0},{name:"paddingRight",type:"number",default:0},{name:"paddingBottom",type:"number",default:0},{name:"paddingLeft",type:"number",default:0},{name:"ratio",type:"number",default:1.618033988749895},{name:"round",type:"boolean",default:!1},{name:"size",type:"number",array:!0,length:2},{name:"as",type:"string",array:!0,length:ZE.length,default:ZE}]};Be(FC,pl,{layout(){const e=Voe();return e.ratio=t=>{const n=e.tile();n.ratio&&e.tile(n.ratio(t))},e.method=t=>{Ve(hM,t)?e.tile(hM[t]):ye("Unrecognized Treemap layout method: "+t)},e},params:["method","ratio","size","round","padding","paddingInner","paddingOuter","paddingTop","paddingRight","paddingBottom","paddingLeft"],fields:ZE});const rle=Object.freeze(Object.defineProperty({__proto__:null,nest:EC,pack:AC,partition:kC,stratify:SC,tree:CC,treelinks:$C,treemap:FC},Symbol.toStringTag,{value:"Module"})),ex=4278190080;function ile(e,t){const n=e.bitmap();return(t||[]).forEach(r=>n.set(e(r.boundary[0]),e(r.boundary[3]))),[n,void 0]}function sle(e,t,n,r,i){const s=e.width,a=e.height,o=r||i,l=Jl(s,a).getContext("2d"),u=Jl(s,a).getContext("2d"),c=o&&Jl(s,a).getContext("2d");n.forEach(k=>C1(l,k,!1)),C1(u,t,!1),o&&C1(c,t,!0);const f=tx(l,s,a),d=tx(u,s,a),h=o&&tx(c,s,a),p=e.bitmap(),g=o&&e.bitmap();let v,y,b,_,x,w,A,E;for(y=0;y{i.items.forEach(s=>C1(e,s.items,n))}):fs[r].draw(e,{items:n?t.map(ale):t})}function ale(e){const t=Xy(e,{});return t.stroke&&t.strokeOpacity!==0||t.fill&&t.fillOpacity!==0?{...t,strokeOpacity:1,stroke:"#000",fillOpacity:0}:t}const To=5,si=31,Tg=32,Ml=new Uint32Array(Tg+1),ea=new Uint32Array(Tg+1);ea[0]=0;Ml[0]=~ea[0];for(let e=1;e<=Tg;++e)ea[e]=ea[e-1]<<1|1,Ml[e]=~ea[e];function ole(e,t){const n=new Uint32Array(~~((e*t+Tg)/Tg));function r(s,a){n[s]|=a}function i(s,a){n[s]&=a}return{array:n,get:(s,a)=>{const o=a*e+s;return n[o>>>To]&1<<(o&si)},set:(s,a)=>{const o=a*e+s;r(o>>>To,1<<(o&si))},clear:(s,a)=>{const o=a*e+s;i(o>>>To,~(1<<(o&si)))},getRange:(s,a,o,l)=>{let u=l,c,f,d,h;for(;u>=a;--u)if(c=u*e+s,f=u*e+o,d=c>>>To,h=f>>>To,d===h){if(n[d]&Ml[c&si]&ea[(f&si)+1])return!0}else{if(n[d]&Ml[c&si]||n[h]&ea[(f&si)+1])return!0;for(let p=d+1;p{let u,c,f,d,h;for(;a<=l;++a)if(u=a*e+s,c=a*e+o,f=u>>>To,d=c>>>To,f===d)r(f,Ml[u&si]&ea[(c&si)+1]);else for(r(f,Ml[u&si]),r(d,ea[(c&si)+1]),h=f+1;h{let u,c,f,d,h;for(;a<=l;++a)if(u=a*e+s,c=a*e+o,f=u>>>To,d=c>>>To,f===d)i(f,ea[u&si]|Ml[(c&si)+1]);else for(i(f,ea[u&si]),i(d,Ml[(c&si)+1]),h=f+1;hs<0||a<0||l>=t||o>=e}}function lle(e,t,n){const r=Math.max(1,Math.sqrt(e*t/1e6)),i=~~((e+2*n+r)/r),s=~~((t+2*n+r)/r),a=o=>~~((o+n)/r);return a.invert=o=>o*r-n,a.bitmap=()=>ole(i,s),a.ratio=r,a.padding=n,a.width=e,a.height=t,a}function ule(e,t,n,r){const i=e.width,s=e.height;return function(a){const o=a.datum.datum.items[r].items,l=o.length,u=a.datum.fontSize,c=ss.width(a.datum,a.datum.text);let f=0,d,h,p,g,v,y,b;for(let _=0;_=f&&(f=b,a.x=v,a.y=y);return v=c/2,y=u/2,d=a.x-v,h=a.x+v,p=a.y-y,g=a.y+y,a.align="center",d<0&&h<=i?a.align="left":0<=d&&ii||t-(a=r/2)<0||t+a>s}function Wl(e,t,n,r,i,s,a,o){const l=i*s/(r*2),u=e(t-l),c=e(t+l),f=e(n-(s=s/2)),d=e(n+s);return a.outOfBounds(u,f,c,d)||a.getRange(u,f,c,d)||o&&o.getRange(u,f,c,d)}function cle(e,t,n,r){const i=e.width,s=e.height,a=t[0],o=t[1];function l(u,c,f,d,h){const p=e.invert(u),g=e.invert(c);let v=f,y=s,b;if(!ey(p,g,d,h,i,s)&&!Wl(e,p,g,h,d,v,a,o)&&!Wl(e,p,g,h,d,h,a,null)){for(;y-v>=1;)b=(v+y)/2,Wl(e,p,g,h,d,b,a,o)?y=b:v=b;if(v>f)return[p,g,v,!0]}}return function(u){const c=u.datum.datum.items[r].items,f=c.length,d=u.datum.fontSize,h=ss.width(u.datum,u.datum.text);let p=n?d:0,g=!1,v=!1,y=0,b,_,x,w,A,E,k,C,M,N,P,I,T,$,L,W,U;for(let O=0;O_&&(U=b,b=_,_=U),x>w&&(U=x,x=w,w=U),M=e(b),P=e(_),N=~~((M+P)/2),I=e(x),$=e(w),T=~~((I+$)/2),k=N;k>=M;--k)for(C=T;C>=I;--C)W=l(k,C,p,h,d),W&&([u.x,u.y,p,g]=W);for(k=N;k<=P;++k)for(C=T;C<=$;++C)W=l(k,C,p,h,d),W&&([u.x,u.y,p,g]=W);!g&&!n&&(L=Math.abs(_-b+w-x),A=(b+_)/2,E=(x+w)/2,L>=y&&!ey(A,E,h,d,i,s)&&!Wl(e,A,E,d,h,d,a,null)&&(y=L,u.x=A,u.y=E,v=!0))}return g||v?(A=h/2,E=d/2,a.setRange(e(u.x-A),e(u.y-E),e(u.x+A),e(u.y+E)),u.align="center",u.baseline="middle",!0):!1}}const fle=[-1,-1,1,1],dle=[-1,1,-1,1];function hle(e,t,n,r){const i=e.width,s=e.height,a=t[0],o=t[1],l=e.bitmap();return function(u){const c=u.datum.datum.items[r].items,f=c.length,d=u.datum.fontSize,h=ss.width(u.datum,u.datum.text),p=[];let g=n?d:0,v=!1,y=!1,b=0,_,x,w,A,E,k,C,M,N,P,I,T;for(let $=0;$=1;)I=(N+P)/2,Wl(e,E,k,d,h,I,a,o)?P=I:N=I;N>g&&(u.x=E,u.y=k,g=N,v=!0)}}!v&&!n&&(T=Math.abs(x-_+A-w),E=(_+x)/2,k=(w+A)/2,T>=b&&!ey(E,k,h,d,i,s)&&!Wl(e,E,k,d,h,d,a,null)&&(b=T,u.x=E,u.y=k,y=!0))}return v||y?(E=h/2,k=d/2,a.setRange(e(u.x-E),e(u.y-k),e(u.x+E),e(u.y+k)),u.align="center",u.baseline="middle",!0):!1}}const ple=["right","center","left"],gle=["bottom","middle","top"];function mle(e,t,n,r){const i=e.width,s=e.height,a=t[0],o=t[1],l=r.length;return function(u){const c=u.boundary,f=u.datum.fontSize;if(c[2]<0||c[5]<0||c[0]>i||c[3]>s)return!1;let d=u.textWidth??0,h,p,g,v,y,b,_,x,w,A,E,k,C,M,N;for(let P=0;P>>2&3)-1,g=h===0&&p===0||r[P]<0,v=h&&p?Math.SQRT1_2:1,y=r[P]<0?-1:1,b=c[1+h]+r[P]*h*v,E=c[4+p]+y*f*p/2+r[P]*p*v,x=E-f/2,w=E+f/2,k=e(b),M=e(x),N=e(w),!d)if(pM(k,k,M,N,a,o,b,b,x,w,c,g))d=ss.width(u.datum,u.datum.text);else continue;if(A=b+y*d*h/2,b=A-d/2,_=A+d/2,k=e(b),C=e(_),pM(k,C,M,N,a,o,b,_,x,w,c,g))return u.x=h?h*y<0?_:b:A,u.y=p?p*y<0?w:x:E,u.align=ple[h*y+1],u.baseline=gle[p*y+1],a.setRange(k,M,C,N),!0}return!1}}function pM(e,t,n,r,i,s,a,o,l,u,c,f){return!(i.outOfBounds(e,n,t,r)||(f&&s||i).getRange(e,n,t,r))}const nx=0,rx=4,ix=8,sx=0,ax=1,ox=2,vle={"top-left":nx+sx,top:nx+ax,"top-right":nx+ox,left:rx+sx,middle:rx+ax,right:rx+ox,"bottom-left":ix+sx,bottom:ix+ax,"bottom-right":ix+ox},yle={naive:ule,"reduced-search":cle,floodfill:hle};function ble(e,t,n,r,i,s,a,o,l,u,c){if(!e.length)return e;const f=Math.max(r.length,i.length),d=_le(r,f),h=xle(i,f),p=wle(e[0].datum),g=p==="group"&&e[0].datum.items[l].marktype,v=g==="area",y=Ele(p,g,o,l),b=u===null||u===1/0,_=v&&c==="naive";let x=-1,w=-1;const A=e.map(M=>{const N=b?ss.width(M,M.text):void 0;return x=Math.max(x,N),w=Math.max(w,M.fontSize),{datum:M,opacity:0,x:void 0,y:void 0,align:void 0,baseline:void 0,boundary:y(M),textWidth:N}});u=u===null||u===1/0?Math.max(x,w)+Math.max(...r):u;const E=lle(t[0],t[1],u);let k;if(!_){n&&A.sort((P,I)=>n(P.datum,I.datum));let M=!1;for(let P=0;PP.datum);k=s.length||N?sle(E,N||[],s,M,v):ile(E,a&&A)}const C=v?yle[c](E,k,a,l):mle(E,k,h,d);return A.forEach(M=>M.opacity=+C(M)),A}function _le(e,t){const n=new Float64Array(t),r=e.length;for(let i=0;i[s.x,s.x,s.x,s.y,s.y,s.y];return e?e==="line"||e==="area"?s=>i(s.datum):t==="line"?s=>{const a=s.datum.items[r].items;return i(a.length?a[n==="start"?0:a.length-1]:{x:NaN,y:NaN})}:s=>{const a=s.datum.bounds;return[a.x1,(a.x1+a.x2)/2,a.x2,a.y1,(a.y1+a.y2)/2,a.y2]}:i}const JE=["x","y","opacity","align","baseline"],RP=["top-left","left","bottom-left","top","bottom","top-right","right","bottom-right"];function DC(e){de.call(this,null,e)}DC.Definition={type:"Label",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"sort",type:"compare"},{name:"anchor",type:"string",array:!0,default:RP},{name:"offset",type:"number",array:!0,default:[1]},{name:"padding",type:"number",default:0,null:!0},{name:"lineAnchor",type:"string",values:["start","end"],default:"end"},{name:"markIndex",type:"number",default:0},{name:"avoidBaseMark",type:"boolean",default:!0},{name:"avoidMarks",type:"data",array:!0},{name:"method",type:"string",default:"naive"},{name:"as",type:"string",array:!0,length:JE.length,default:JE}]};Be(DC,de,{transform(e,t){function n(s){const a=e[s];return Rt(a)&&t.modified(a.fields)}const r=e.modified();if(!(r||t.changed(t.ADD_REM)||n("sort")))return;(!e.size||e.size.length!==2)&&ye("Size parameter should be specified as a [width, height] array.");const i=e.as||JE;return ble(t.materialize(t.SOURCE).source||[],e.size,e.sort,He(e.offset==null?1:e.offset),He(e.anchor||RP),e.avoidMarks||[],e.avoidBaseMark!==!1,e.lineAnchor||"end",e.markIndex||0,e.padding===void 0?0:e.padding,e.method||"naive").forEach(s=>{const a=s.datum;a[i[0]]=s.x,a[i[1]]=s.y,a[i[2]]=s.opacity,a[i[3]]=s.align,a[i[4]]=s.baseline}),t.reflow(r).modifies(i)}});const Ale=Object.freeze(Object.defineProperty({__proto__:null,label:DC},Symbol.toStringTag,{value:"Module"}));function NP(e,t){var n=[],r=function(c){return c(o)},i,s,a,o,l,u;if(t==null)n.push(e);else for(i={},s=0,a=e.length;s{jO(u,e.x,e.y,e.bandwidth||.3).forEach(c=>{const f={};for(let d=0;de==="poly"?t:e==="quad"?2:1;function TC(e){de.call(this,null,e)}TC.Definition={type:"Regression",metadata:{generates:!0},params:[{name:"x",type:"field",required:!0},{name:"y",type:"field",required:!0},{name:"groupby",type:"field",array:!0},{name:"method",type:"string",default:"linear",values:Object.keys(QE)},{name:"order",type:"number",default:3},{name:"extent",type:"number",array:!0,length:2},{name:"params",type:"boolean",default:!1},{name:"as",type:"string",array:!0}]};Be(TC,de,{transform(e,t){const n=t.fork(t.NO_SOURCE|t.NO_FIELDS);if(!this.value||t.changed()||e.modified()){const r=t.materialize(t.SOURCE).source,i=NP(r,e.groupby),s=(e.groupby||[]).map(zn),a=e.method||"linear",o=e.order==null?3:e.order,l=kle(a,o),u=e.as||[zn(e.x),zn(e.y)],c=QE[a],f=[];let d=e.extent;Ve(QE,a)||ye("Invalid regression method: "+a),d!=null&&a==="log"&&d[0]<=0&&(t.dataflow.warn("Ignoring extent with values <= 0 for log regression."),d=null),i.forEach(h=>{if(h.length<=l){t.dataflow.warn("Skipping regression with more parameters than data points.");return}const g=c(h,e.x,e.y,o);if(e.params){f.push(nn({keys:h.dims,coef:g.coef,rSquared:g.rSquared}));return}const v=d||io(h,e.x),y=b=>{const _={};for(let x=0;xy([b,g.predict(b)])):nb(g.predict,v,25,200).forEach(y)}),this.value&&(n.rem=this.value),this.value=n.add=n.source=f}return n}});const Sle=Object.freeze(Object.defineProperty({__proto__:null,loess:MC,regression:TC},Symbol.toStringTag,{value:"Module"})),Qo=11102230246251565e-32,jr=134217729,Cle=(3+8*Qo)*Qo;function lx(e,t,n,r,i){let s,a,o,l,u=t[0],c=r[0],f=0,d=0;c>u==c>-u?(s=u,u=t[++f]):(s=c,c=r[++d]);let h=0;if(fu==c>-u?(a=u+s,o=s-(a-u),u=t[++f]):(a=c+s,o=s-(a-c),c=r[++d]),s=a,o!==0&&(i[h++]=o);fu==c>-u?(a=s+u,l=a-s,o=s-(a-l)+(u-l),u=t[++f]):(a=s+c,l=a-s,o=s-(a-l)+(c-l),c=r[++d]),s=a,o!==0&&(i[h++]=o);for(;f=T||-I>=T||(f=e-C,o=e-(C+f)+(f-i),f=n-M,u=n-(M+f)+(f-i),f=t-N,l=t-(N+f)+(f-s),f=r-P,c=r-(P+f)+(f-s),o===0&&l===0&&u===0&&c===0)||(T=Mle*a+Cle*Math.abs(I),I+=C*c+P*o-(N*u+M*l),I>=T||-I>=T))return I;x=o*P,d=jr*o,h=d-(d-o),p=o-h,d=jr*P,g=d-(d-P),v=P-g,w=p*v-(x-h*g-p*g-h*v),A=l*M,d=jr*l,h=d-(d-l),p=l-h,d=jr*M,g=d-(d-M),v=M-g,E=p*v-(A-h*g-p*g-h*v),y=w-E,f=w-y,ai[0]=w-(y+f)+(f-E),b=x+y,f=b-x,_=x-(b-f)+(y-f),y=_-A,f=_-y,ai[1]=_-(y+f)+(f-A),k=b+y,f=k-b,ai[2]=b-(k-f)+(y-f),ai[3]=k;const $=lx(4,Pf,4,ai,gM);x=C*c,d=jr*C,h=d-(d-C),p=C-h,d=jr*c,g=d-(d-c),v=c-g,w=p*v-(x-h*g-p*g-h*v),A=N*u,d=jr*N,h=d-(d-N),p=N-h,d=jr*u,g=d-(d-u),v=u-g,E=p*v-(A-h*g-p*g-h*v),y=w-E,f=w-y,ai[0]=w-(y+f)+(f-E),b=x+y,f=b-x,_=x-(b-f)+(y-f),y=_-A,f=_-y,ai[1]=_-(y+f)+(f-A),k=b+y,f=k-b,ai[2]=b-(k-f)+(y-f),ai[3]=k;const L=lx($,gM,4,ai,mM);x=o*c,d=jr*o,h=d-(d-o),p=o-h,d=jr*c,g=d-(d-c),v=c-g,w=p*v-(x-h*g-p*g-h*v),A=l*u,d=jr*l,h=d-(d-l),p=l-h,d=jr*u,g=d-(d-u),v=u-g,E=p*v-(A-h*g-p*g-h*v),y=w-E,f=w-y,ai[0]=w-(y+f)+(f-E),b=x+y,f=b-x,_=x-(b-f)+(y-f),y=_-A,f=_-y,ai[1]=_-(y+f)+(f-A),k=b+y,f=k-b,ai[2]=b-(k-f)+(y-f),ai[3]=k;const W=lx(L,mM,4,ai,vM);return vM[W-1]}function Tm(e,t,n,r,i,s){const a=(t-s)*(n-i),o=(e-i)*(r-s),l=a-o,u=Math.abs(a+o);return Math.abs(l)>=Fle*u?l:-Tle(e,t,n,r,i,s,u)}const yM=Math.pow(2,-52),Rm=new Uint32Array(512);class ty{static from(t,n=Ile,r=Ple){const i=t.length,s=new Float64Array(i*2);for(let a=0;a>1;if(n>0&&typeof t[0]!="number")throw new Error("Expected coords to contain numbers.");this.coords=t;const r=Math.max(2*n-5,0);this._triangles=new Uint32Array(r*3),this._halfedges=new Int32Array(r*3),this._hashSize=Math.ceil(Math.sqrt(n)),this._hullPrev=new Uint32Array(n),this._hullNext=new Uint32Array(n),this._hullTri=new Uint32Array(n),this._hullHash=new Int32Array(this._hashSize),this._ids=new Uint32Array(n),this._dists=new Float64Array(n),this.update()}update(){const{coords:t,_hullPrev:n,_hullNext:r,_hullTri:i,_hullHash:s}=this,a=t.length>>1;let o=1/0,l=1/0,u=-1/0,c=-1/0;for(let C=0;Cu&&(u=M),N>c&&(c=N),this._ids[C]=C}const f=(o+u)/2,d=(l+c)/2;let h,p,g;for(let C=0,M=1/0;C0&&(p=C,M=N)}let b=t[2*p],_=t[2*p+1],x=1/0;for(let C=0;CP&&(C[M++]=I,P=T)}this.hull=C.subarray(0,M),this.triangles=new Uint32Array(0),this.halfedges=new Uint32Array(0);return}if(Tm(v,y,b,_,w,A)<0){const C=p,M=b,N=_;p=g,b=w,_=A,g=C,w=M,A=N}const E=Lle(v,y,b,_,w,A);this._cx=E.x,this._cy=E.y;for(let C=0;C0&&Math.abs(I-M)<=yM&&Math.abs(T-N)<=yM||(M=I,N=T,P===h||P===p||P===g))continue;let $=0;for(let H=0,G=this._hashKey(I,T);H=0;)if(L=W,L===$){L=-1;break}if(L===-1)continue;let U=this._addTriangle(L,P,r[L],-1,-1,i[L]);i[P]=this._legalize(U+2),i[L]=U,k++;let O=r[L];for(;W=r[O],Tm(I,T,t[2*O],t[2*O+1],t[2*W],t[2*W+1])<0;)U=this._addTriangle(O,P,W,i[P],-1,i[O]),i[P]=this._legalize(U+2),r[O]=O,k--,O=W;if(L===$)for(;W=n[L],Tm(I,T,t[2*W],t[2*W+1],t[2*L],t[2*L+1])<0;)U=this._addTriangle(W,P,L,-1,i[L],i[W]),this._legalize(U+2),i[W]=U,r[L]=L,k--,L=W;this._hullStart=n[P]=L,r[L]=n[O]=P,r[P]=O,s[this._hashKey(I,T)]=P,s[this._hashKey(t[2*L],t[2*L+1])]=L}this.hull=new Uint32Array(k);for(let C=0,M=this._hullStart;C0?3-n:1+n)/4}function ux(e,t,n,r){const i=e-n,s=t-r;return i*i+s*s}function Nle(e,t,n,r,i,s,a,o){const l=e-a,u=t-o,c=n-a,f=r-o,d=i-a,h=s-o,p=l*l+u*u,g=c*c+f*f,v=d*d+h*h;return l*(f*v-g*h)-u*(c*v-g*d)+p*(c*h-f*d)<0}function Ole(e,t,n,r,i,s){const a=n-e,o=r-t,l=i-e,u=s-t,c=a*a+o*o,f=l*l+u*u,d=.5/(a*u-o*l),h=(u*c-o*f)*d,p=(a*f-l*c)*d;return h*h+p*p}function Lle(e,t,n,r,i,s){const a=n-e,o=r-t,l=i-e,u=s-t,c=a*a+o*o,f=l*l+u*u,d=.5/(a*u-o*l),h=e+(u*c-o*f)*d,p=t+(a*f-l*c)*d;return{x:h,y:p}}function td(e,t,n,r){if(r-n<=20)for(let i=n+1;i<=r;i++){const s=e[i],a=t[s];let o=i-1;for(;o>=n&&t[e[o]]>a;)e[o+1]=e[o--];e[o+1]=s}else{const i=n+r>>1;let s=n+1,a=r;up(e,i,s),t[e[n]]>t[e[r]]&&up(e,n,r),t[e[s]]>t[e[r]]&&up(e,s,r),t[e[n]]>t[e[s]]&&up(e,n,s);const o=e[s],l=t[o];for(;;){do s++;while(t[e[s]]l);if(a=a-n?(td(e,t,s,r),td(e,t,n,a-1)):(td(e,t,n,a-1),td(e,t,s,r))}}function up(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}function Ile(e){return e[0]}function Ple(e){return e[1]}const bM=1e-6;class gc{constructor(){this._x0=this._y0=this._x1=this._y1=null,this._=""}moveTo(t,n){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}`}closePath(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")}lineTo(t,n){this._+=`L${this._x1=+t},${this._y1=+n}`}arc(t,n,r){t=+t,n=+n,r=+r;const i=t+r,s=n;if(r<0)throw new Error("negative radius");this._x1===null?this._+=`M${i},${s}`:(Math.abs(this._x1-i)>bM||Math.abs(this._y1-s)>bM)&&(this._+="L"+i+","+s),r&&(this._+=`A${r},${r},0,1,1,${t-r},${n}A${r},${r},0,1,1,${this._x1=i},${this._y1=s}`)}rect(t,n,r,i){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${+r}v${+i}h${-r}Z`}value(){return this._||null}}class eA{constructor(){this._=[]}moveTo(t,n){this._.push([t,n])}closePath(){this._.push(this._[0].slice())}lineTo(t,n){this._.push([t,n])}value(){return this._.length?this._:null}}let Ble=class{constructor(t,[n,r,i,s]=[0,0,960,500]){if(!((i=+i)>=(n=+n))||!((s=+s)>=(r=+r)))throw new Error("invalid bounds");this.delaunay=t,this._circumcenters=new Float64Array(t.points.length*2),this.vectors=new Float64Array(t.points.length*2),this.xmax=i,this.xmin=n,this.ymax=s,this.ymin=r,this._init()}update(){return this.delaunay.update(),this._init(),this}_init(){const{delaunay:{points:t,hull:n,triangles:r},vectors:i}=this;let s,a;const o=this.circumcenters=this._circumcenters.subarray(0,r.length/3*2);for(let g=0,v=0,y=r.length,b,_;g1;)s-=2;for(let a=2;a0){if(n>=this.ymax)return null;(a=(this.ymax-n)/i)0){if(t>=this.xmax)return null;(a=(this.xmax-t)/r)this.xmax?2:0)|(nthis.ymax?8:0)}_simplify(t){if(t&&t.length>4){for(let n=0;n1e-10)return!1}return!0}function Wle(e,t,n){return[e+Math.sin(e+t)*n,t+Math.cos(e-t)*n]}class RC{static from(t,n=jle,r=Ule,i){return new RC("length"in t?Hle(t,n,r,i):Float64Array.from(Gle(t,n,r,i)))}constructor(t){this._delaunator=new ty(t),this.inedges=new Int32Array(t.length/2),this._hullIndex=new Int32Array(t.length/2),this.points=this._delaunator.coords,this._init()}update(){return this._delaunator.update(),this._init(),this}_init(){const t=this._delaunator,n=this.points;if(t.hull&&t.hull.length>2&&qle(t)){this.collinear=Int32Array.from({length:n.length/2},(d,h)=>h).sort((d,h)=>n[2*d]-n[2*h]||n[2*d+1]-n[2*h+1]);const l=this.collinear[0],u=this.collinear[this.collinear.length-1],c=[n[2*l],n[2*l+1],n[2*u],n[2*u+1]],f=1e-8*Math.hypot(c[3]-c[1],c[2]-c[0]);for(let d=0,h=n.length/2;d0&&(this.triangles=new Int32Array(3).fill(-1),this.halfedges=new Int32Array(3).fill(-1),this.triangles[0]=i[0],a[i[0]]=1,i.length===2&&(a[i[1]]=0,this.triangles[1]=i[1],this.triangles[2]=i[1]))}voronoi(t){return new Ble(this,t)}*neighbors(t){const{inedges:n,hull:r,_hullIndex:i,halfedges:s,triangles:a,collinear:o}=this;if(o){const f=o.indexOf(t);f>0&&(yield o[f-1]),f=0&&s!==r&&s!==i;)r=s;return s}_step(t,n,r){const{inedges:i,hull:s,_hullIndex:a,halfedges:o,triangles:l,points:u}=this;if(i[t]===-1||!u.length)return(t+1)%(u.length>>1);let c=t,f=Bf(n-u[t*2],2)+Bf(r-u[t*2+1],2);const d=i[t];let h=d;do{let p=l[h];const g=Bf(n-u[p*2],2)+Bf(r-u[p*2+1],2);if(g>5)*e[1]),v=null,y=u.length,b=-1,_=[],x=u.map(A=>({text:t(A),font:n(A),style:i(A),weight:s(A),rotate:a(A),size:~~(r(A)+1e-14),padding:o(A),xoff:0,yoff:0,x1:0,y1:0,x0:0,y0:0,hasText:!1,sprite:null,datum:A})).sort((A,E)=>E.size-A.size);++b>1,w.y=e[1]*(c()+.5)>>1,Jle(p,w,x,b),w.hasText&&h(g,w,v)&&(_.push(w),v?eue(v,w):v=[{x:w.x+w.x0,y:w.y+w.y0},{x:w.x+w.x1,y:w.y+w.y1}],w.x-=e[0]>>1,w.y-=e[1]>>1)}return _};function d(p){p.width=p.height=1;var g=Math.sqrt(p.getContext("2d").getImageData(0,0,1,1).data.length>>2);p.width=(jp<<5)/g,p.height=$1/g;var v=p.getContext("2d");return v.fillStyle=v.strokeStyle="red",v.textAlign="center",{context:v,ratio:g}}function h(p,g,v){for(var y=g.x,b=g.y,_=Math.hypot(e[0],e[1]),x=l(e),w=c()<.5?1:-1,A=-w,E,k,C;(E=x(A+=w))&&(k=~~E[0],C=~~E[1],!(Math.min(Math.abs(k),Math.abs(C))>=_));)if(g.x=y+k,g.y=b+C,!(g.x+g.x0<0||g.y+g.y0<0||g.x+g.x1>e[0]||g.y+g.y1>e[1])&&(!v||!Qle(g,p,e[0]))&&(!v||tue(g,v))){for(var M=g.sprite,N=g.width>>5,P=e[0]>>5,I=g.x-(N<<4),T=I&127,$=32-T,L=g.y1-g.y0,W=(g.y+g.y0)*P+(I>>5),U,O=0;O>>T:0);W+=P}return g.sprite=null,!0}return!1}return f.words=function(p){return arguments.length?(u=p,f):u},f.size=function(p){return arguments.length?(e=[+p[0],+p[1]],f):e},f.font=function(p){return arguments.length?(n=Wu(p),f):n},f.fontStyle=function(p){return arguments.length?(i=Wu(p),f):i},f.fontWeight=function(p){return arguments.length?(s=Wu(p),f):s},f.rotate=function(p){return arguments.length?(a=Wu(p),f):a},f.text=function(p){return arguments.length?(t=Wu(p),f):t},f.spiral=function(p){return arguments.length?(l=iue[p]||p,f):l},f.fontSize=function(p){return arguments.length?(r=Wu(p),f):r},f.padding=function(p){return arguments.length?(o=Wu(p),f):o},f.random=function(p){return arguments.length?(c=p,f):c},f}function Jle(e,t,n,r){if(!t.sprite){var i=e.context,s=e.ratio;i.clearRect(0,0,(jp<<5)/s,$1/s);var a=0,o=0,l=0,u=n.length,c,f,d,h,p;for(--r;++r>5<<5,d=~~Math.max(Math.abs(b+_),Math.abs(b-_))}else c=c+31>>5<<5;if(d>l&&(l=d),a+c>=jp<<5&&(a=0,o+=l,l=0),o+d>=$1)break;i.translate((a+(c>>1))/s,(o+(d>>1))/s),t.rotate&&i.rotate(t.rotate*cx),i.fillText(t.text,0,0),t.padding&&(i.lineWidth=2*t.padding,i.strokeText(t.text,0,0)),i.restore(),t.width=c,t.height=d,t.xoff=a,t.yoff=o,t.x1=c>>1,t.y1=d>>1,t.x0=-t.x1,t.y0=-t.y1,t.hasText=!0,a+=c}for(var w=i.getImageData(0,0,(jp<<5)/s,$1/s).data,A=[];--r>=0;)if(t=n[r],!!t.hasText){for(c=t.width,f=c>>5,d=t.y1-t.y0,h=0;h>5),M=w[(o+p)*(jp<<5)+(a+h)<<2]?1<<31-h%32:0;A[C]|=M,E|=M}E?k=p:(t.y0++,d--,p--,o++)}t.y1=t.y0+k,t.sprite=A.slice(0,(t.y1-t.y0)*f)}}}function Qle(e,t,n){n>>=5;for(var r=e.sprite,i=e.width>>5,s=e.x-(i<<4),a=s&127,o=32-a,l=e.y1-e.y0,u=(e.y+e.y0)*n+(s>>5),c,f=0;f>>a:0))&t[u+d])return!0;u+=n}return!1}function eue(e,t){var n=e[0],r=e[1];t.x+t.x0r.x&&(r.x=t.x+t.x1),t.y+t.y1>r.y&&(r.y=t.y+t.y1)}function tue(e,t){return e.x+e.x1>t[0].x&&e.x+e.x0t[0].y&&e.y+e.y0g(p(v))}i.forEach(p=>{p[a[0]]=NaN,p[a[1]]=NaN,p[a[3]]=0});const u=s.words(i).text(e.text).size(e.size||[500,500]).padding(e.padding||1).spiral(e.spiral||"archimedean").rotate(e.rotate||0).font(e.font||"sans-serif").fontStyle(e.fontStyle||"normal").fontWeight(e.fontWeight||"normal").fontSize(o).random(Ls).layout(),c=s.size(),f=c[0]>>1,d=c[1]>>1,h=u.length;for(let p=0,g,v;pnew Uint8Array(e),lue=e=>new Uint16Array(e),ag=e=>new Uint32Array(e);function uue(){let e=8,t=[],n=ag(0),r=Nm(0,e),i=Nm(0,e);return{data:()=>t,seen:()=>n=cue(n,t.length),add(s){for(let a=0,o=t.length,l=s.length,u;at.length,curr:()=>r,prev:()=>i,reset:s=>i[s]=r[s],all:()=>e<257?255:e<65537?65535:4294967295,set(s,a){r[s]|=a},clear(s,a){r[s]&=~a},resize(s,a){const o=r.length;(s>o||a>e)&&(e=Math.max(a,e),r=Nm(s,e,r),i=Nm(s,e))}}}function cue(e,t,n){return e.length>=t?e:(n=n||new e.constructor(t),n.set(e),n)}function Nm(e,t,n){const r=(t<257?oue:t<65537?lue:ag)(e);return n&&r.set(n),r}function _M(e,t,n){const r=1<0)for(v=0;ve,size:()=>n}}function fue(e,t){return e.sort.call(t,(n,r)=>{const i=e[n],s=e[r];return is?1:0}),_V(e,t)}function due(e,t,n,r,i,s,a,o,l){let u=0,c=0,f;for(f=0;ut.modified(r.fields));return n?this.reinit(e,t):this.eval(e,t)}else return this.init(e,t)},init(e,t){const n=e.fields,r=e.query,i=this._indices={},s=this._dims=[],a=r.length;let o=0,l,u;for(;o{const s=i.remove(t,n);for(const a in r)r[a].reindex(s)})},update(e,t,n){const r=this._dims,i=e.query,s=t.stamp,a=r.length;let o=0,l,u;for(n.filters=0,u=0;uh)for(v=h,y=Math.min(f,p);vp)for(v=Math.max(f,p),y=d;vf)for(p=f,g=Math.min(u,d);pd)for(p=Math.max(u,d),g=c;po[c]&n?null:a[c];return s.filter(s.MOD,u),i&i-1?(s.filter(s.ADD,c=>{const f=o[c]&n;return!f&&f^l[c]&n?a[c]:null}),s.filter(s.REM,c=>{const f=o[c]&n;return f&&!(f^(f^l[c]&n))?a[c]:null})):(s.filter(s.ADD,u),s.filter(s.REM,c=>(o[c]&n)===i?a[c]:null)),s.filter(s.SOURCE,c=>u(c._index))}});const hue=Object.freeze(Object.defineProperty({__proto__:null,crossfilter:LC,resolvefilter:IC},Symbol.toStringTag,{value:"Module"})),pue="RawCode",Vc="Literal",gue="Property",mue="Identifier",vue="ArrayExpression",yue="BinaryExpression",IP="CallExpression",bue="ConditionalExpression",_ue="LogicalExpression",xue="MemberExpression",wue="ObjectExpression",Eue="UnaryExpression";function ba(e){this.type=e}ba.prototype.visit=function(e){let t,n,r;if(e(this))return 1;for(t=Aue(this),n=0,r=t.length;n";_o[Xc]="Identifier";_o[Cu]="Keyword";_o[Lb]="Null";_o[yf]="Numeric";_o[$i]="Punctuator";_o[N0]="String";_o[kue]="RegularExpression";var Sue="ArrayExpression",Cue="BinaryExpression",$ue="CallExpression",Fue="ConditionalExpression",PP="Identifier",Due="Literal",Mue="LogicalExpression",Tue="MemberExpression",Rue="ObjectExpression",Nue="Property",Oue="UnaryExpression",vr="Unexpected token %0",Lue="Unexpected number",Iue="Unexpected string",Pue="Unexpected identifier",Bue="Unexpected reserved word",zue="Unexpected end of input",tA="Invalid regular expression",fx="Invalid regular expression: missing /",BP="Octal literals are not allowed in strict mode.",jue="Duplicate data property in object literal not allowed in strict mode",Rr="ILLEGAL",Rg="Disabled.",Uue=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),que=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]");function Ib(e,t){if(!e)throw new Error("ASSERT: "+t)}function Io(e){return e>=48&&e<=57}function PC(e){return"0123456789abcdefABCDEF".includes(e)}function og(e){return"01234567".includes(e)}function Wue(e){return e===32||e===9||e===11||e===12||e===160||e>=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].includes(e)}function Ng(e){return e===10||e===13||e===8232||e===8233}function O0(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e===92||e>=128&&Uue.test(String.fromCharCode(e))}function ny(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e>=48&&e<=57||e===92||e>=128&&que.test(String.fromCharCode(e))}const Hue={if:1,in:1,do:1,var:1,for:1,new:1,try:1,let:1,this:1,else:1,case:1,void:1,with:1,enum:1,while:1,break:1,catch:1,throw:1,const:1,yield:1,class:1,super:1,return:1,typeof:1,delete:1,switch:1,export:1,import:1,public:1,static:1,default:1,finally:1,extends:1,package:1,private:1,function:1,continue:1,debugger:1,interface:1,protected:1,instanceof:1,implements:1};function zP(){for(;we1114111||e!=="}")&&Zt({},vr,Rr),t<=65535?String.fromCharCode(t):(n=(t-65536>>10)+55296,r=(t-65536&1023)+56320,String.fromCharCode(n,r))}function jP(){var e,t;for(e=it.charCodeAt(we++),t=String.fromCharCode(e),e===92&&(it.charCodeAt(we)!==117&&Zt({},vr,Rr),++we,e=nA("u"),(!e||e==="\\"||!O0(e.charCodeAt(0)))&&Zt({},vr,Rr),t=e);we>>=")return we+=4,{type:$i,value:a,start:e,end:we};if(s=a.substr(0,3),s===">>>"||s==="<<="||s===">>=")return we+=3,{type:$i,value:s,start:e,end:we};if(i=s.substr(0,2),r===i[1]&&"+-<>&|".includes(r)||i==="=>")return we+=2,{type:$i,value:i,start:e,end:we};if(i==="//"&&Zt({},vr,Rr),"<>=!+-*%&|^/".includes(r))return++we,{type:$i,value:r,start:e,end:we};Zt({},vr,Rr)}function Xue(e){let t="";for(;we{if(parseInt(i,16)<=1114111)return"x";Zt({},tA)}).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"x"));try{new RegExp(n)}catch{Zt({},tA)}try{return new RegExp(e,t)}catch{return null}}function Que(){var e,t,n,r,i;for(e=it[we],Ib(e==="/","Regular expression literal must start with a slash"),t=it[we++],n=!1,r=!1;we=0&&Zt({},tA,n),{value:n,literal:t}}function tce(){var e,t,n,r;return an=null,zP(),e=we,t=Que(),n=ece(),r=Jue(t.value,n.value),{literal:t.literal+n.literal,value:r,regex:{pattern:t.value,flags:n.value},start:e,end:we}}function nce(e){return e.type===Xc||e.type===Cu||e.type===Ob||e.type===Lb}function UP(){if(zP(),we>=Kr)return{type:R0,start:we,end:we};const e=it.charCodeAt(we);return O0(e)?Vue():e===40||e===41||e===59?dx():e===39||e===34?Zue():e===46?Io(it.charCodeAt(we+1))?wM():dx():Io(e)?wM():dx()}function Ti(){const e=an;return we=e.end,an=UP(),we=e.end,e}function qP(){const e=we;an=UP(),we=e}function rce(e){const t=new ba(Sue);return t.elements=e,t}function EM(e,t,n){const r=new ba(e==="||"||e==="&&"?Mue:Cue);return r.operator=e,r.left=t,r.right=n,r}function ice(e,t){const n=new ba($ue);return n.callee=e,n.arguments=t,n}function sce(e,t,n){const r=new ba(Fue);return r.test=e,r.consequent=t,r.alternate=n,r}function BC(e){const t=new ba(PP);return t.name=e,t}function Up(e){const t=new ba(Due);return t.value=e.value,t.raw=it.slice(e.start,e.end),e.regex&&(t.raw==="//"&&(t.raw="/(?:)/"),t.regex=e.regex),t}function AM(e,t,n){const r=new ba(Tue);return r.computed=e==="[",r.object=t,r.property=n,r.computed||(n.member=!0),r}function ace(e){const t=new ba(Rue);return t.properties=e,t}function kM(e,t,n){const r=new ba(Nue);return r.key=t,r.value=n,r.kind=e,r}function oce(e,t){const n=new ba(Oue);return n.operator=e,n.argument=t,n.prefix=!0,n}function Zt(e,t){var n,r=Array.prototype.slice.call(arguments,2),i=t.replace(/%(\d)/g,(s,a)=>(Ib(a":case"<=":case">=":case"instanceof":case"in":t=7;break;case"<<":case">>":case">>>":t=8;break;case"+":case"-":t=9;break;case"*":case"/":case"%":t=11;break}return t}function bce(){var e,t,n,r,i,s,a,o,l,u;if(e=an,l=F1(),r=an,i=$M(r),i===0)return l;for(r.prec=i,Ti(),t=[e,an],a=F1(),s=[l,r,a];(i=$M(an))>0;){for(;s.length>2&&i<=s[s.length-2].prec;)a=s.pop(),o=s.pop().value,l=s.pop(),t.pop(),n=EM(o,l,a),s.push(n);r=Ti(),r.prec=i,s.push(r),t.push(an),n=F1(),s.push(n)}for(u=s.length-1,n=s[u],t.pop();u>1;)t.pop(),n=EM(s[u-1].value,s[u-2],n),u-=2;return n}function Kc(){var e,t,n;return e=bce(),wn("?")&&(Ti(),t=Kc(),Zr(":"),n=Kc(),e=sce(e,t,n)),e}function zC(){const e=Kc();if(wn(","))throw new Error(Rg);return e}function WP(e){it=e,we=0,Kr=it.length,an=null,qP();const t=zC();if(an.type!==R0)throw new Error("Unexpect token after expression.");return t}var HP={NaN:"NaN",E:"Math.E",LN2:"Math.LN2",LN10:"Math.LN10",LOG2E:"Math.LOG2E",LOG10E:"Math.LOG10E",PI:"Math.PI",SQRT1_2:"Math.SQRT1_2",SQRT2:"Math.SQRT2",MIN_VALUE:"Number.MIN_VALUE",MAX_VALUE:"Number.MAX_VALUE"};function GP(e){function t(a,o,l,u){let c=e(o[0]);return l&&(c=l+"("+c+")",l.lastIndexOf("new ",0)===0&&(c="("+c+")")),c+"."+a+(u<0?"":u===0?"()":"("+o.slice(1).map(e).join(",")+")")}function n(a,o,l){return u=>t(a,u,o,l)}const r="new Date",i="String",s="RegExp";return{isNaN:"Number.isNaN",isFinite:"Number.isFinite",abs:"Math.abs",acos:"Math.acos",asin:"Math.asin",atan:"Math.atan",atan2:"Math.atan2",ceil:"Math.ceil",cos:"Math.cos",exp:"Math.exp",floor:"Math.floor",hypot:"Math.hypot",log:"Math.log",max:"Math.max",min:"Math.min",pow:"Math.pow",random:"Math.random",round:"Math.round",sin:"Math.sin",sqrt:"Math.sqrt",tan:"Math.tan",clamp:function(a){a.length<3&&ye("Missing arguments to clamp function."),a.length>3&&ye("Too many arguments to clamp function.");const o=a.map(e);return"Math.max("+o[1]+", Math.min("+o[2]+","+o[0]+"))"},now:"Date.now",utc:"Date.UTC",datetime:r,date:n("getDate",r,0),day:n("getDay",r,0),year:n("getFullYear",r,0),month:n("getMonth",r,0),hours:n("getHours",r,0),minutes:n("getMinutes",r,0),seconds:n("getSeconds",r,0),milliseconds:n("getMilliseconds",r,0),time:n("getTime",r,0),timezoneoffset:n("getTimezoneOffset",r,0),utcdate:n("getUTCDate",r,0),utcday:n("getUTCDay",r,0),utcyear:n("getUTCFullYear",r,0),utcmonth:n("getUTCMonth",r,0),utchours:n("getUTCHours",r,0),utcminutes:n("getUTCMinutes",r,0),utcseconds:n("getUTCSeconds",r,0),utcmilliseconds:n("getUTCMilliseconds",r,0),length:n("length",null,-1),parseFloat:"parseFloat",parseInt:"parseInt",upper:n("toUpperCase",i,0),lower:n("toLowerCase",i,0),substring:n("substring",i),split:n("split",i),trim:n("trim",i,0),btoa:"btoa",atob:"atob",regexp:s,test:n("test",s),if:function(a){a.length<3&&ye("Missing arguments to if function."),a.length>3&&ye("Too many arguments to if function.");const o=a.map(e);return"("+o[0]+"?"+o[1]+":"+o[2]+")"}}}function _ce(e){const t=e&&e.length-1;return t&&(e[0]==='"'&&e[t]==='"'||e[0]==="'"&&e[t]==="'")?e.slice(1,-1):e}function YP(e){e=e||{};const t=e.allowed?da(e.allowed):{},n=e.forbidden?da(e.forbidden):{},r=e.constants||HP,i=(e.functions||GP)(f),s=e.globalvar,a=e.fieldvar,o=Rt(s)?s:p=>`${s}["${p}"]`;let l={},u={},c=0;function f(p){if(We(p))return p;const g=d[p.type];return g==null&&ye("Unsupported type: "+p.type),g(p)}const d={Literal:p=>p.raw,Identifier:p=>{const g=p.name;return c>0?g:Ve(n,g)?ye("Illegal identifier: "+g):Ve(r,g)?r[g]:Ve(t,g)?g:(l[g]=1,o(g))},MemberExpression:p=>{const g=!p.computed,v=f(p.object);g&&(c+=1);const y=f(p.property);return v===a&&(u[_ce(y)]=1),g&&(c-=1),v+(g?"."+y:"["+y+"]")},CallExpression:p=>{p.callee.type!=="Identifier"&&ye("Illegal callee type: "+p.callee.type);const g=p.callee.name,v=p.arguments,y=Ve(i,g)&&i[g];return y||ye("Unrecognized function: "+g),Rt(y)?y(v):y+"("+v.map(f).join(",")+")"},ArrayExpression:p=>"["+p.elements.map(f).join(",")+"]",BinaryExpression:p=>"("+f(p.left)+" "+p.operator+" "+f(p.right)+")",UnaryExpression:p=>"("+p.operator+f(p.argument)+")",ConditionalExpression:p=>"("+f(p.test)+"?"+f(p.consequent)+":"+f(p.alternate)+")",LogicalExpression:p=>"("+f(p.left)+p.operator+f(p.right)+")",ObjectExpression:p=>{for(const g of p.properties){const v=g.key.name;Ek.has(v)&&ye("Illegal property: "+v)}return"{"+p.properties.map(f).join(",")+"}"},Property:p=>{c+=1;const g=f(p.key);return c-=1,g+":"+f(p.value)}};function h(p){const g={code:f(p),globals:Object.keys(l),fields:Object.keys(u)};return l={},u={},g}return h.functions=i,h.constants=r,h}const FM=Symbol("vega_selection_getter");function VP(e){return(!e.getter||!e.getter[FM])&&(e.getter=Ns(e.field),e.getter[FM]=!0),e.getter}const jC="intersect",DM="union",xce="vlMulti",wce="vlPoint",MM="or",Ece="and",qa="_vgsid_",Og=Ns(qa),Ace="E",kce="R",Sce="R-E",Cce="R-LE",$ce="R-RE",Fce="E-LT",Dce="E-LTE",Mce="E-GT",Tce="E-GTE",Rce="E-VALID",Nce="E-ONE",ry="index:unit";function TM(e,t){for(var n=t.fields,r=t.values,i=n.length,s=0,a,o;s=r[s])return!1}else if(o.type===Dce){if(a>r[s])return!1}else if(o.type===Mce){if(a<=r[s])return!1}else if(o.type===Tce){if(aTt(t.fields?{values:t.fields.map(r=>VP(r)(n.datum))}:{[qa]:Og(n.datum)},t))}function zce(e,t,n,r){for(var i=this.context.data[e],s=i?i.values.value:[],a={},o={},l={},u,c,f,d,h,p,g,v,y,b,_=s.length,x=0,w,A;x<_;++x)if(u=s[x],d=u.unit,c=u.fields,f=u.values,c&&f){for(w=0,A=c.length;w(E[c[C].field]=k,E),{})))}else h=qa,p=Og(u),g=a[h]||(a[h]={}),v=g[d]||(g[d]=[]),v.push(p),n&&(v=o[d]||(o[d]=[]),v.push({[qa]:p}));if(t=t||DM,a[qa]?a[qa]=px[`${qa}_${t}`](...Object.values(a[qa])):Object.keys(a).forEach(E=>{a[E]=Object.keys(a[E]).map(k=>a[E][k]).reduce((k,C)=>k===void 0?C:px[`${l[E]}_${t}`](k,C))}),s=Object.keys(o),n&&s.length){const E=r?wce:xce;a[E]=t===DM?{[MM]:s.reduce((k,C)=>(k.push(...o[C]),k),[])}:{[Ece]:s.map(k=>({[MM]:o[k]}))}}return a}var px={[`${qa}_union`]:FV,[`${qa}_intersect`]:CV,E_union:function(e,t){if(!e.length)return t;for(var n=0,r=t.length;nt.includes(n)):t},R_union:function(e,t){var n=Gr(t[0]),r=Gr(t[1]);return n>r&&(n=t[1],r=t[0]),e.length?(e[0]>n&&(e[0]=n),e[1]r&&(n=t[1],r=t[0]),e.length?rr&&(e[1]=r),e):[n,r]}};const jce=":",Uce="@";function UC(e,t,n,r){t[0].type!==Vc&&ye("First argument to selection functions must be a string literal.");const i=t[0].value,s=t.length>=2&&Xt(t).value,a="unit",o=Uce+a,l=jce+i;s===jC&&!Ve(r,o)&&(r[o]=n.getData(i).indataRef(n,a)),Ve(r,l)||(r[l]=n.getData(i).tuplesRef())}function KP(e){const t=this.context.data[e];return t?t.values.value:[]}function qce(e,t,n){const r=this.context.data[e]["index:"+t],i=r?r.value.get(n):void 0;return i&&i.count}function Wce(e,t){const n=this.context.dataflow,r=this.context.data[e],i=r.input;return n.pulse(i,n.changeset().remove(ls).insert(t)),1}function Hce(e,t,n){if(e){const r=this.context.dataflow,i=e.mark.source;r.pulse(i,r.changeset().encode(e,t))}return n!==void 0?n:e}const L0=e=>function(t,n){const r=this.context.dataflow.locale();return t===null?"null":r[e](n)(t)},Gce=L0("format"),ZP=L0("timeFormat"),Yce=L0("utcFormat"),Vce=L0("timeParse"),Xce=L0("utcParse"),Om=new Date(2e3,0,1);function Bb(e,t,n){return!Number.isInteger(e)||!Number.isInteger(t)?"":(Om.setYear(2e3),Om.setMonth(e),Om.setDate(t),ZP.call(this,Om,n))}function Kce(e){return Bb.call(this,e,1,"%B")}function Zce(e){return Bb.call(this,e,1,"%b")}function Jce(e){return Bb.call(this,0,2+e,"%A")}function Qce(e){return Bb.call(this,0,2+e,"%a")}const efe=":",tfe="@",rA="%",JP="$";function qC(e,t,n,r){t[0].type!==Vc&&ye("First argument to data functions must be a string literal.");const i=t[0].value,s=efe+i;if(!Ve(s,r))try{r[s]=n.getData(i).tuplesRef()}catch{}}function nfe(e,t,n,r){t[0].type!==Vc&&ye("First argument to indata must be a string literal."),t[1].type!==Vc&&ye("Second argument to indata must be a string literal.");const i=t[0].value,s=t[1].value,a=tfe+s;Ve(a,r)||(r[a]=n.getData(i).indataRef(n,s))}function mi(e,t,n,r){if(t[0].type===Vc)RM(n,r,t[0].value);else for(e in n.scales)RM(n,r,e)}function RM(e,t,n){const r=rA+n;if(!Ve(t,r))try{t[r]=e.scaleRef(n)}catch{}}function xo(e,t){if(We(e)){const n=t.scales[e];return n&&L4(n.value)?n.value:void 0}else if(Rt(e))return L4(e)?e:void 0}function rfe(e,t,n){t.__bandwidth=i=>i&&i.bandwidth?i.bandwidth():0,n._bandwidth=mi,n._range=mi,n._scale=mi;const r=i=>"_["+(i.type===Vc?Pe(rA+i.value):Pe(rA)+"+"+e(i))+"]";return{_bandwidth:i=>`this.__bandwidth(${r(i[0])})`,_range:i=>`${r(i[0])}.range()`,_scale:i=>`${r(i[0])}(${e(i[1])})`}}function WC(e,t){return function(n,r,i){if(n){const s=xo(n,(i||this).context);return s&&s.path[e](r)}else return t(r)}}const ife=WC("area",wie),sfe=WC("bounds",Sie),afe=WC("centroid",Tie);function ofe(e,t){const n=xo(e,(t||this).context);return n&&n.scale()}function lfe(e){const t=this.context.group;let n=!1;if(t)for(;e;){if(e===t){n=!0;break}e=e.mark.group}return n}function HC(e,t,n){try{e[t].apply(e,["EXPRESSION"].concat([].slice.call(n)))}catch(r){e.warn(r)}return n[n.length-1]}function ufe(){return HC(this.context.dataflow,"warn",arguments)}function cfe(){return HC(this.context.dataflow,"info",arguments)}function ffe(){return HC(this.context.dataflow,"debug",arguments)}function gx(e){const t=e/255;return t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)}function iA(e){const t=ou(e),n=gx(t.r),r=gx(t.g),i=gx(t.b);return .2126*n+.7152*r+.0722*i}function dfe(e,t){const n=iA(e),r=iA(t),i=Math.max(n,r),s=Math.min(n,r);return(i+.05)/(s+.05)}function hfe(){const e=[].slice.call(arguments);return e.unshift({}),Tt(...e)}function QP(e,t){return e===t||e!==e&&t!==t?!0:Se(e)?Se(t)&&e.length===t.length?pfe(e,t):!1:Ue(e)&&Ue(t)?eB(e,t):!1}function pfe(e,t){for(let n=0,r=e.length;neB(e,t)}function gfe(e,t,n,r,i,s){const a=this.context.dataflow,o=this.context.data[e],l=o.input,u=a.stamp();let c=o.changes,f,d;if(a._trigger===!1||!(l.value.length||t||r))return 0;if((!c||c.stamp{o.modified=!0,a.pulse(l,c).run()},!0,1)),n&&(f=n===!0?ls:Se(n)||Vy(n)?n:NM(n),c.remove(f)),t&&c.insert(t),r&&(f=NM(r),l.value.some(f)?c.remove(f):c.insert(r)),i)for(d in s)c.modify(i,d,s[d]);return 1}function mfe(e){const t=e.touches,n=t[0].clientX-t[1].clientX,r=t[0].clientY-t[1].clientY;return Math.hypot(n,r)}function vfe(e){const t=e.touches;return Math.atan2(t[0].clientY-t[1].clientY,t[0].clientX-t[1].clientX)}const OM={};function yfe(e,t){const n=OM[t]||(OM[t]=Ns(t));return Se(e)?e.map(n):n(e)}function zb(e){return Se(e)||ArrayBuffer.isView(e)?e:null}function GC(e){return zb(e)||(We(e)?e:null)}function bfe(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;rs.stop(u(c),e(c))),s}function Nfe(e,t,n){const r=xo(e,(n||this).context);return function(i){return r?r.path.context(i)(t):""}}function Ofe(e){let t=null;return function(n){return n?kg(n,t=t||qd(e)):e}}const tB=e=>e.data;function nB(e,t){const n=KP.call(t,e);return n.root&&n.root.lookup||{}}function Lfe(e,t,n){const r=nB(e,this),i=r[t],s=r[n];return i&&s?i.path(s).map(tB):void 0}function Ife(e,t){const n=nB(e,this)[t];return n?n.ancestors().map(tB):void 0}const rB=()=>typeof window<"u"&&window||null;function Pfe(){const e=rB();return e?e.screen:{}}function Bfe(){const e=rB();return e?[e.innerWidth,e.innerHeight]:[void 0,void 0]}function zfe(){const e=this.context.dataflow,t=e.container&&e.container();return t?[t.clientWidth,t.clientHeight]:[void 0,void 0]}function iB(e,t,n){if(!e)return[];const[r,i]=e,s=new Qn().set(r[0],r[1],i[0],i[1]),a=n||this.context.dataflow.scenegraph().root;return zL(a,s,jfe(t))}function jfe(e){let t=null;if(e){const n=He(e.marktype),r=He(e.markname);t=i=>(!n.length||n.some(s=>i.marktype===s))&&(!r.length||r.some(s=>i.name===s))}return t}function Ufe(e,t,n){let r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:5;e=He(e);const i=e[e.length-1];return i===void 0||Math.hypot(i[0]-t,i[1]-n)>r?[...e,[t,n]]:e}function qfe(e){return He(e).reduce((t,n,r)=>{let[i,s]=n;return t+=r==0?`M ${i},${s} `:r===e.length-1?" Z":`L ${i},${s} `},"")}function Wfe(e,t,n){const{x:r,y:i,mark:s}=n,a=new Qn().set(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER,Number.MIN_SAFE_INTEGER);for(const[l,u]of t)la.x2&&(a.x2=l),ua.y2&&(a.y2=u);return a.translate(r,i),iB([[a.x1,a.y1],[a.x2,a.y2]],e,s).filter(l=>Hfe(l.x,l.y,t))}function Hfe(e,t,n){let r=0;for(let i=0,s=n.length-1;it!=o>t&&e<(a-l)*(t-u)/(o-u)+l&&r++}return r&1}const Lg={random(){return Ls()},cumulativeNormal:Qy,cumulativeLogNormal:aS,cumulativeUniform:cS,densityNormal:tS,densityLogNormal:sS,densityUniform:uS,quantileNormal:eb,quantileLogNormal:oS,quantileUniform:fS,sampleNormal:Jy,sampleLogNormal:iS,sampleUniform:lS,isArray:Se,isBoolean:xu,isDate:Xl,isDefined(e){return e!==void 0},isNumber:Qt,isObject:Ue,isRegExp:Tk,isString:We,isTuple:Vy,isValid(e){return e!=null&&e===e},toBoolean:Nk,toDate(e){return Ok(e)},toNumber:Gr,toString:Lk,indexof:_fe,join:bfe,lastindexof:xfe,replace:Efe,reverse:Afe,sort:kfe,slice:wfe,flush:cN,lerp:dN,merge:hfe,pad:gN,peek:Xt,pluck:yfe,span:u0,inrange:Zf,truncate:mN,rgb:ou,lab:uv,hcl:cv,hsl:ov,luminance:iA,contrast:dfe,sequence:ts,format:Gce,utcFormat:Yce,utcParse:Xce,utcOffset:VN,utcSequence:ZN,timeFormat:ZP,timeParse:Vce,timeOffset:YN,timeSequence:KN,timeUnitSpecifier:LN,monthFormat:Kce,monthAbbrevFormat:Zce,dayFormat:Jce,dayAbbrevFormat:Qce,quarter:aN,utcquarter:oN,week:PN,utcweek:jN,dayofyear:IN,utcdayofyear:zN,warn:ufe,info:cfe,debug:ffe,extent(e){return io(e)},inScope:lfe,intersect:iB,clampRange:lN,pinchDistance:mfe,pinchAngle:vfe,screen:Pfe,containerSize:zfe,windowSize:Bfe,bandspace:Sfe,setdata:Wce,pathShape:Ofe,panLinear:nN,panLog:rN,panPow:iN,panSymlog:sN,zoomLinear:Ck,zoomLog:$k,zoomPow:Y1,zoomSymlog:Fk,encode:Hce,modify:gfe,lassoAppend:Ufe,lassoPath:qfe,intersectLasso:Wfe},Gfe=["view","item","group","xy","x","y"],Yfe="event.vega.",sB="this.",YC={},aB={forbidden:["_"],allowed:["datum","event","item"],fieldvar:"datum",globalvar:e=>`_[${Pe(JP+e)}]`,functions:Vfe,constants:HP,visitors:YC},sA=YP(aB);function Vfe(e){const t=GP(e);Gfe.forEach(n=>t[n]=Yfe+n);for(const n in Lg)t[n]=sB+n;return Tt(t,rfe(e,Lg,YC)),t}function Kn(e,t,n){return arguments.length===1?Lg[e]:(Lg[e]=t,n&&(YC[e]=n),sA&&(sA.functions[e]=sB+e),this)}Kn("bandwidth",Cfe,mi);Kn("copy",$fe,mi);Kn("domain",Ffe,mi);Kn("range",Mfe,mi);Kn("invert",Dfe,mi);Kn("scale",Tfe,mi);Kn("gradient",Rfe,mi);Kn("geoArea",ife,mi);Kn("geoBounds",sfe,mi);Kn("geoCentroid",afe,mi);Kn("geoShape",Nfe,mi);Kn("geoScale",ofe,mi);Kn("indata",qce,nfe);Kn("data",KP,qC);Kn("treePath",Lfe,qC);Kn("treeAncestors",Ife,qC);Kn("vlSelectionTest",Oce,UC);Kn("vlSelectionIdTest",Pce,UC);Kn("vlSelectionResolve",zce,UC);Kn("vlSelectionTuples",Bce);function uo(e,t){const n={};let r;try{e=We(e)?e:Pe(e)+"",r=WP(e)}catch{ye("Expression parse error: "+e)}r.visit(s=>{if(s.type!==IP)return;const a=s.callee.name,o=aB.visitors[a];o&&o(a,s.arguments,t,n)});const i=sA(r);return i.globals.forEach(s=>{const a=JP+s;!Ve(n,a)&&t.getSignal(s)&&(n[a]=t.signalRef(s))}),{$expr:Tt({code:i.code},t.options.ast?{ast:r}:null),$fields:i.fields,$params:n}}function Xfe(e){const t=this,n=e.operators||[];return e.background&&(t.background=e.background),e.eventConfig&&(t.eventConfig=e.eventConfig),e.locale&&(t.locale=e.locale),n.forEach(r=>t.parseOperator(r)),n.forEach(r=>t.parseOperatorParameters(r)),(e.streams||[]).forEach(r=>t.parseStream(r)),(e.updates||[]).forEach(r=>t.parseUpdate(r)),t.resolve()}const Kfe=da(["rule"]),LM=da(["group","image","rect"]);function Zfe(e,t){let n="";return Kfe[t]||(e.x2&&(e.x?(LM[t]&&(n+="if(o.x>o.x2)$=o.x,o.x=o.x2,o.x2=$;"),n+="o.width=o.x2-o.x;"):n+="o.x=o.x2-(o.width||0);"),e.xc&&(n+="o.x=o.xc-(o.width||0)/2;"),e.y2&&(e.y?(LM[t]&&(n+="if(o.y>o.y2)$=o.y,o.y=o.y2,o.y2=$;"),n+="o.height=o.y2-o.y;"):n+="o.y=o.y2-(o.height||0);"),e.yc&&(n+="o.y=o.yc-(o.height||0)/2;")),n}function VC(e){return(e+"").toLowerCase()}function Jfe(e){return VC(e)==="operator"}function Qfe(e){return VC(e)==="collect"}function cp(e,t,n){n.endsWith(";")||(n="return("+n+");");const r=Function(...t.concat(n));return e&&e.functions?r.bind(e.functions):r}function ede(e,t,n,r){return`((u = ${e}) < (v = ${t}) || u == null) && v != null ? ${n} + : (u > v || v == null) && u != null ? ${r} + : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? ${n} + : v !== v && u === u ? ${r} : `}var tde={operator:(e,t)=>cp(e,["_"],t.code),parameter:(e,t)=>cp(e,["datum","_"],t.code),event:(e,t)=>cp(e,["event"],t.code),handler:(e,t)=>{const n=`var datum=event.item&&event.item.datum;return ${t.code};`;return cp(e,["_","event"],n)},encode:(e,t)=>{const{marktype:n,channels:r}=t;let i="var o=item,datum=o.datum,m=0,$;";for(const s in r){const a="o["+Pe(s)+"]";i+=`$=${r[s].code};if(${a}!==$)${a}=$,m=1;`}return i+=Zfe(r,n),i+="return m;",cp(e,["item","_"],i)},codegen:{get(e){const t=`[${e.map(Pe).join("][")}]`,n=Function("_",`return _${t};`);return n.path=t,n},comparator(e,t){let n;const r=(s,a)=>{const o=t[a];let l,u;return s.path?(l=`a${s.path}`,u=`b${s.path}`):((n=n||{})["f"+a]=s,l=`this.f${a}(a)`,u=`this.f${a}(b)`),ede(l,u,-o,o)},i=Function("a","b","var u, v; return "+e.map(r).join("")+"0;");return n?i.bind(n):i}}};function nde(e){const t=this;Jfe(e.type)||!e.type?t.operator(e,e.update?t.operatorExpression(e.update):null):t.transform(e,e.type)}function rde(e){const t=this;if(e.params){const n=t.get(e.id);n||ye("Invalid operator id: "+e.id),t.dataflow.connect(n,n.parameters(t.parseParameters(e.params),e.react,e.initonly))}}function ide(e,t){t=t||{};const n=this;for(const r in e){const i=e[r];t[r]=Se(i)?i.map(s=>IM(s,n,t)):IM(i,n,t)}return t}function IM(e,t,n){if(!e||!Ue(e))return e;for(let r=0,i=PM.length,s;ri&&i.$tupleid?dt:i);return t.fn[n]||(t.fn[n]=Dk(r,e.$order,t.expr.codegen))}function cde(e,t){const n=e.$encode,r={};for(const i in n){const s=n[i];r[i]=Wi(t.encodeExpression(s.$expr),s.$fields),r[i].output=s.$output}return r}function fde(e,t){return t}function dde(e,t){const n=e.$subflow;return function(r,i,s){const a=t.fork().parse(n),o=a.get(n.operators[0].id),l=a.signals.parent;return l&&l.set(s),o.detachSubflow=()=>t.detach(a),o}}function hde(){return dt}function pde(e){var t=this,n=e.filter!=null?t.eventExpression(e.filter):void 0,r=e.stream!=null?t.get(e.stream):void 0,i;e.source?r=t.events(e.source,e.type,n):e.merge&&(i=e.merge.map(s=>t.get(s)),r=i[0].merge.apply(i[0],i.slice(1))),e.between&&(i=e.between.map(s=>t.get(s)),r=r.between(i[0],i[1])),e.filter&&(r=r.filter(n)),e.throttle!=null&&(r=r.throttle(+e.throttle)),e.debounce!=null&&(r=r.debounce(+e.debounce)),r==null&&ye("Invalid stream definition: "+JSON.stringify(e)),e.consume&&r.consume(!0),t.stream(e,r)}function gde(e){var t=this,n=Ue(n=e.source)?n.$ref:n,r=t.get(n),i=null,s=e.update,a=void 0;r||ye("Source not defined: "+e.source),i=e.target&&e.target.$expr?t.eventExpression(e.target.$expr):t.get(e.target),s&&s.$expr&&(s.$params&&(a=t.parseParameters(s.$params)),s=t.handlerExpression(s.$expr)),t.update(e,r,i,s,a)}const mde={skip:!0};function vde(e){var t=this,n={};if(e.signals){var r=n.signals={};Object.keys(t.signals).forEach(s=>{const a=t.signals[s];e.signals(s,a)&&(r[s]=a.value)})}if(e.data){var i=n.data={};Object.keys(t.data).forEach(s=>{const a=t.data[s];e.data(s,a)&&(i[s]=a.input.value)})}return t.subcontext&&e.recurse!==!1&&(n.subcontext=t.subcontext.map(s=>s.getState(e))),n}function yde(e){var t=this,n=t.dataflow,r=e.data,i=e.signals;Object.keys(i||{}).forEach(s=>{n.update(t.signals[s],i[s],mde)}),Object.keys(r||{}).forEach(s=>{n.pulse(t.data[s].input,n.changeset().remove(ls).insert(r[s]))}),(e.subcontext||[]).forEach((s,a)=>{const o=t.subcontext[a];o&&o.setState(s)})}function oB(e,t,n,r){return new lB(e,t,n,r)}function lB(e,t,n,r){this.dataflow=e,this.transforms=t,this.events=e.events.bind(e),this.expr=r||tde,this.signals={},this.scales={},this.nodes={},this.data={},this.fn={},n&&(this.functions=Object.create(n),this.functions.context=this)}function BM(e){this.dataflow=e.dataflow,this.transforms=e.transforms,this.events=e.events,this.expr=e.expr,this.signals=Object.create(e.signals),this.scales=Object.create(e.scales),this.nodes=Object.create(e.nodes),this.data=Object.create(e.data),this.fn=Object.create(e.fn),e.functions&&(this.functions=Object.create(e.functions),this.functions.context=this)}lB.prototype=BM.prototype={fork(){const e=new BM(this);return(this.subcontext||(this.subcontext=[])).push(e),e},detach(e){this.subcontext=this.subcontext.filter(n=>n!==e);const t=Object.keys(e.nodes);for(const n of t)e.nodes[n]._targets=null;for(const n of t)e.nodes[n].detach();e.nodes=null},get(e){return this.nodes[e]},set(e,t){return this.nodes[e]=t},add(e,t){const n=this,r=n.dataflow,i=e.value;if(n.set(e.id,t),Qfe(e.type)&&i&&(i.$ingest?r.ingest(t,i.$ingest,i.$format):i.$request?r.preload(t,i.$request,i.$format):r.pulse(t,r.changeset().insert(i))),e.root&&(n.root=t),e.parent){let s=n.get(e.parent.$ref);s?(r.connect(s,[t]),t.targets().add(s)):(n.unresolved=n.unresolved||[]).push(()=>{s=n.get(e.parent.$ref),r.connect(s,[t]),t.targets().add(s)})}if(e.signal&&(n.signals[e.signal]=t),e.scale&&(n.scales[e.scale]=t),e.data)for(const s in e.data){const a=n.data[s]||(n.data[s]={});e.data[s].forEach(o=>a[o]=t)}},resolve(){return(this.unresolved||[]).forEach(e=>e()),delete this.unresolved,this},operator(e,t){this.add(e,this.dataflow.add(e.value,t))},transform(e,t){this.add(e,this.dataflow.add(this.transforms[VC(t)]))},stream(e,t){this.set(e.id,t)},update(e,t,n,r,i){this.dataflow.on(t,n,r,i,e.options)},operatorExpression(e){return this.expr.operator(this,e)},parameterExpression(e){return this.expr.parameter(this,e)},eventExpression(e){return this.expr.event(this,e)},handlerExpression(e){return this.expr.handler(this,e)},encodeExpression(e){return this.expr.encode(this,e)},parse:Xfe,parseOperator:nde,parseOperatorParameters:rde,parseParameters:ide,parseStream:pde,parseUpdate:gde,getState:vde,setState:yde};function bde(e){const t=e.container();t&&(t.setAttribute("role","graphics-document"),t.setAttribute("aria-roleDescription","visualization"),uB(t,e.description()))}function uB(e,t){e&&(t==null?e.removeAttribute("aria-label"):e.setAttribute("aria-label",t))}function _de(e){e.add(null,t=>(e._background=t.bg,e._resize=1,t.bg),{bg:e._signals.background})}const mx="default";function xde(e){const t=e._signals.cursor||(e._signals.cursor=e.add({user:mx,item:null}));e.on(e.events("view","pointermove"),t,(n,r)=>{const i=t.value,s=i?We(i)?i:i.user:mx,a=r.item&&r.item.cursor||null;return i&&s===i.user&&a==i.item?i:{user:s,item:a}}),e.add(null,function(n){let r=n.cursor,i=this.value;return We(r)||(i=r.item,r=r.user),aA(e,r&&r!==mx?r:i||r),i},{cursor:t})}function aA(e,t){const n=e.globalCursor()?typeof document<"u"&&document.body:e.container();if(n)return t==null?n.style.removeProperty("cursor"):n.style.cursor=t}function iy(e,t){var n=e._runtime.data;return Ve(n,t)||ye("Unrecognized data set: "+t),n[t]}function wde(e,t){return arguments.length<2?iy(this,e).values.value:jb.call(this,e,wu().remove(ls).insert(t))}function jb(e,t){AO(t)||ye("Second argument to changes must be a changeset.");const n=iy(this,e);return n.modified=!0,this.pulse(n.input,t)}function Ede(e,t){return jb.call(this,e,wu().insert(t))}function Ade(e,t){return jb.call(this,e,wu().remove(t))}function cB(e){var t=e.padding();return Math.max(0,e._viewWidth+t.left+t.right)}function fB(e){var t=e.padding();return Math.max(0,e._viewHeight+t.top+t.bottom)}function Ub(e){var t=e.padding(),n=e._origin;return[t.left+n[0],t.top+n[1]]}function kde(e){var t=Ub(e),n=cB(e),r=fB(e);e._renderer.background(e.background()),e._renderer.resize(n,r,t),e._handler.origin(t),e._resizeListeners.forEach(i=>{try{i(n,r)}catch(s){e.error(s)}})}function Sde(e,t,n){var r=e._renderer,i=r&&r.canvas(),s,a,o;return i&&(o=Ub(e),a=t.changedTouches?t.changedTouches[0]:t,s=Cb(a,i),s[0]-=o[0],s[1]-=o[1]),t.dataflow=e,t.item=n,t.vega=Cde(e,n,s),t}function Cde(e,t,n){const r=t?t.mark.marktype==="group"?t:t.mark.group:null;function i(a){var o=r,l;if(a){for(l=t;l;l=l.mark.group)if(l.mark.name===a){o=l;break}}return o&&o.mark&&o.mark.interactive?o:{}}function s(a){if(!a)return n;We(a)&&(a=i(a));const o=n.slice();for(;a;)o[0]-=a.x||0,o[1]-=a.y||0,a=a.mark&&a.mark.group;return o}return{view:ti(e),item:ti(t||{}),group:i,xy:s,x:a=>s(a)[0],y:a=>s(a)[1]}}const zM="view",$de="timer",Fde="window",Dde={trap:!1};function Mde(e){const t=Tt({defaults:{}},e),n=(r,i)=>{i.forEach(s=>{Se(r[s])&&(r[s]=da(r[s]))})};return n(t.defaults,["prevent","allow"]),n(t,["view","window","selector"]),t}function dB(e,t,n,r){e._eventListeners.push({type:n,sources:He(t),handler:r})}function Tde(e,t){var n=e._eventConfig.defaults,r=n.prevent,i=n.allow;return r===!1||i===!0?!1:r===!0||i===!1?!0:r?r[t]:i?!i[t]:e.preventDefault()}function Lm(e,t,n){const r=e._eventConfig&&e._eventConfig[t];return r===!1||Ue(r)&&!r[n]?(e.warn(`Blocked ${t} ${n} event listener.`),!1):!0}function Rde(e,t,n){var r=this,i=new Zy(n),s=function(u,c){r.runAsync(null,()=>{e===zM&&Tde(r,t)&&u.preventDefault(),i.receive(Sde(r,u,c))})},a;if(e===$de)Lm(r,"timer",t)&&r.timer(s,t);else if(e===zM)Lm(r,"view",t)&&r.addEventListener(t,s,Dde);else if(e===Fde?Lm(r,"window",t)&&typeof window<"u"&&(a=[window]):typeof document<"u"&&Lm(r,"selector",t)&&(a=Array.from(document.querySelectorAll(e))),!a)r.warn("Can not resolve event source: "+e);else{for(var o=0,l=a.length;o=0;)t[i].stop();for(i=r.length;--i>=0;)for(a=r[i],s=a.sources.length;--s>=0;)a.sources[s].removeEventListener(a.type,a.handler);for(e&&e.call(this,this._handler,null,null,null),i=n.length;--i>=0;)l=n[i].type,o=n[i].handler,this._handler.off(l,o);return this}function as(e,t,n){const r=document.createElement(e);for(const i in t)r.setAttribute(i,t[i]);return n!=null&&(r.textContent=n),r}const Lde="vega-bind",Ide="vega-bind-name",Pde="vega-bind-radio";function Bde(e,t,n){if(!t)return;const r=n.param;let i=n.state;return i||(i=n.state={elements:null,active:!1,set:null,update:a=>{a!=e.signal(r.signal)&&e.runAsync(null,()=>{i.source=!0,e.signal(r.signal,a)})}},r.debounce&&(i.update=Mk(r.debounce,i.update))),(r.input==null&&r.element?zde:Ude)(i,t,r,e),i.active||(e.on(e._signals[r.signal],null,()=>{i.source?i.source=!1:i.set(e.signal(r.signal))}),i.active=!0),i}function zde(e,t,n,r){const i=n.event||"input",s=()=>e.update(t.value);r.signal(n.signal,t.value),t.addEventListener(i,s),dB(r,t,i,s),e.set=a=>{t.value=a,t.dispatchEvent(jde(i))}}function jde(e){return typeof Event<"u"?new Event(e):{type:e}}function Ude(e,t,n,r){const i=r.signal(n.signal),s=as("div",{class:Lde}),a=n.input==="radio"?s:s.appendChild(as("label"));a.appendChild(as("span",{class:Ide},n.name||n.signal)),t.appendChild(s);let o=qde;switch(n.input){case"checkbox":o=Wde;break;case"select":o=Hde;break;case"radio":o=Gde;break;case"range":o=Yde;break}o(e,a,n,i)}function qde(e,t,n,r){const i=as("input");for(const s in n)s!=="signal"&&s!=="element"&&i.setAttribute(s==="input"?"type":s,n[s]);i.setAttribute("name",n.signal),i.value=r,t.appendChild(i),i.addEventListener("input",()=>e.update(i.value)),e.elements=[i],e.set=s=>i.value=s}function Wde(e,t,n,r){const i={type:"checkbox",name:n.signal};r&&(i.checked=!0);const s=as("input",i);t.appendChild(s),s.addEventListener("change",()=>e.update(s.checked)),e.elements=[s],e.set=a=>s.checked=!!a||null}function Hde(e,t,n,r){const i=as("select",{name:n.signal}),s=n.labels||[];n.options.forEach((a,o)=>{const l={value:a};sy(a,r)&&(l.selected=!0),i.appendChild(as("option",l,(s[o]||a)+""))}),t.appendChild(i),i.addEventListener("change",()=>{e.update(n.options[i.selectedIndex])}),e.elements=[i],e.set=a=>{for(let o=0,l=n.options.length;o{const l={type:"radio",name:n.signal,value:a};sy(a,r)&&(l.checked=!0);const u=as("input",l);u.addEventListener("change",()=>e.update(a));const c=as("label",{},(s[o]||a)+"");return c.prepend(u),i.appendChild(c),u}),e.set=a=>{const o=e.elements,l=o.length;for(let u=0;u{l.textContent=o.value,e.update(+o.value)};o.addEventListener("input",u),o.addEventListener("change",u),e.elements=[o],e.set=c=>{o.value=c,l.textContent=c}}function sy(e,t){return e===t||e+""==t+""}function hB(e,t,n,r,i,s){return t=t||new r(e.loader()),t.initialize(n,cB(e),fB(e),Ub(e),i,s).background(e.background())}function XC(e,t){return t?function(){try{t.apply(this,arguments)}catch(n){e.error(n)}}:null}function Vde(e,t,n,r){const i=new r(e.loader(),XC(e,e.tooltip())).scene(e.scenegraph().root).initialize(n,Ub(e),e);return t&&t.handlers().forEach(s=>{i.on(s.type,s.handler)}),i}function Xde(e,t){const n=this,r=n._renderType,i=n._eventConfig.bind,s=$b(r);e=n._el=e?vx(n,e,!0):null,bde(n),s||n.error("Unrecognized renderer type: "+r);const a=s.handler||$0,o=e?s.renderer:s.headless;return n._renderer=o?hB(n,n._renderer,e,o):null,n._handler=Vde(n,n._handler,e,a),n._redraw=!0,e&&i!=="none"&&(t=t?n._elBind=vx(n,t,!0):e.appendChild(as("form",{class:"vega-bindings"})),n._bind.forEach(l=>{l.param.element&&i!=="container"&&(l.element=vx(n,l.param.element,!!l.param.input))}),n._bind.forEach(l=>{Bde(n,l.element||t,l)})),n}function vx(e,t,n){if(typeof t=="string")if(typeof document<"u"){if(t=document.querySelector(t),!t)return e.error("Signal bind element not found: "+t),null}else return e.error("DOM document instance not found."),null;if(t&&n)try{t.textContent=""}catch(r){t=null,e.error(r)}return t}const fp=e=>+e||0,Kde=e=>({top:e,bottom:e,left:e,right:e});function WM(e){return Ue(e)?{top:fp(e.top),bottom:fp(e.bottom),left:fp(e.left),right:fp(e.right)}:Kde(fp(e))}async function KC(e,t,n,r){const i=$b(t),s=i&&i.headless;return s||ye("Unrecognized renderer type: "+t),await e.runAsync(),hB(e,null,null,s,n,r).renderAsync(e._scenegraph.root)}async function Zde(e,t){e!==zl.Canvas&&e!==zl.SVG&&e!==zl.PNG&&ye("Unrecognized image type: "+e);const n=await KC(this,e,t);return e===zl.SVG?Jde(n.svg(),"image/svg+xml"):n.canvas().toDataURL("image/png")}function Jde(e,t){const n=new Blob([e],{type:t});return window.URL.createObjectURL(n)}async function Qde(e,t){return(await KC(this,zl.Canvas,e,t)).canvas()}async function ehe(e){return(await KC(this,zl.SVG,e)).svg()}function the(e,t,n){return oB(e,Id,Lg,n).parse(t)}function nhe(e){var t=this._runtime.scales;return Ve(t,e)||ye("Unrecognized scale or projection: "+e),t[e].value}var pB="width",gB="height",ZC="padding",HM={skip:!0};function mB(e,t){var n=e.autosize(),r=e.padding();return t-(n&&n.contains===ZC?r.left+r.right:0)}function vB(e,t){var n=e.autosize(),r=e.padding();return t-(n&&n.contains===ZC?r.top+r.bottom:0)}function rhe(e){var t=e._signals,n=t[pB],r=t[gB],i=t[ZC];function s(){e._autosize=e._resize=1}e._resizeWidth=e.add(null,o=>{e._width=o.size,e._viewWidth=mB(e,o.size),s()},{size:n}),e._resizeHeight=e.add(null,o=>{e._height=o.size,e._viewHeight=vB(e,o.size),s()},{size:r});const a=e.add(null,s,{pad:i});e._resizeWidth.rank=n.rank+1,e._resizeHeight.rank=r.rank+1,a.rank=i.rank+1}function ihe(e,t,n,r,i,s){this.runAfter(a=>{let o=0;a._autosize=0,a.width()!==n&&(o=1,a.signal(pB,n,HM),a._resizeWidth.skip(!0)),a.height()!==r&&(o=1,a.signal(gB,r,HM),a._resizeHeight.skip(!0)),a._viewWidth!==e&&(a._resize=1,a._viewWidth=e),a._viewHeight!==t&&(a._resize=1,a._viewHeight=t),(a._origin[0]!==i[0]||a._origin[1]!==i[1])&&(a._resize=1,a._origin=i),o&&a.run("enter"),s&&a.runAfter(l=>l.resize())},!1,1)}function she(e){return this._runtime.getState(e||{data:ahe,signals:ohe,recurse:!0})}function ahe(e,t){return t.modified&&Se(t.input.value)&&!e.startsWith("_:vega:_")}function ohe(e,t){return!(e==="parent"||t instanceof Id.proxy)}function lhe(e){return this.runAsync(null,t=>{t._trigger=!1,t._runtime.setState(e)},t=>{t._trigger=!0}),this}function uhe(e,t){function n(r){e({timestamp:Date.now(),elapsed:r})}this._timers.push(Rae(n,t))}function che(e,t,n,r){const i=e.element();i&&i.setAttribute("title",fhe(r))}function fhe(e){return e==null?"":Se(e)?yB(e):Ue(e)&&!Xl(e)?dhe(e):e+""}function dhe(e){return Object.keys(e).map(t=>{const n=e[t];return t+": "+(Se(n)?yB(n):bB(n))}).join(` +`)}function yB(e){return"["+e.map(bB).join(", ")+"]"}function bB(e){return Se(e)?"[…]":Ue(e)&&!Xl(e)?"{…}":e}function hhe(){if(this.renderer()==="canvas"&&this._renderer._canvas){let e=null;const t=()=>{e!=null&&e();const n=matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);n.addEventListener("change",t),e=()=>{n.removeEventListener("change",t)},this._renderer._canvas.getContext("2d").pixelRatio=window.devicePixelRatio||1,this._redraw=!0,this._resize=1,this.resize().runAsync()};t()}}function _B(e,t){const n=this;if(t=t||{},sd.call(n),t.loader&&n.loader(t.loader),t.logger&&n.logger(t.logger),t.logLevel!=null&&n.logLevel(t.logLevel),t.locale||e.locale){const s=Tt({},e.locale,t.locale);n.locale(pO(s.number,s.time))}n._el=null,n._elBind=null,n._renderType=t.renderer||zl.Canvas,n._scenegraph=new hL;const r=n._scenegraph.root;n._renderer=null,n._tooltip=t.tooltip||che,n._redraw=!0,n._handler=new $0().scene(r),n._globalCursor=!1,n._preventDefault=!1,n._timers=[],n._eventListeners=[],n._resizeListeners=[],n._eventConfig=Mde(e.eventConfig),n.globalCursor(n._eventConfig.globalCursor);const i=the(n,e,t.expr);n._runtime=i,n._signals=i.signals,n._bind=(e.bindings||[]).map(s=>({state:null,param:Tt({},s)})),i.root&&i.root.set(r),r.source=i.data.root.input,n.pulse(i.data.root.input,n.changeset().insert(r.items)),n._width=n.width(),n._height=n.height(),n._viewWidth=mB(n,n._width),n._viewHeight=vB(n,n._height),n._origin=[0,0],n._resize=0,n._autosize=1,rhe(n),_de(n),xde(n),n.description(e.description),t.hover&&n.hover(),t.container&&n.initialize(t.container,t.bind),t.watchPixelRatio&&n._watchPixelRatio()}function Im(e,t){return Ve(e._signals,t)?e._signals[t]:ye("Unrecognized signal name: "+Pe(t))}function xB(e,t){const n=(e._targets||[]).filter(r=>r._update&&r._update.handler===t);return n.length?n[0]:null}function GM(e,t,n,r){let i=xB(n,r);return i||(i=XC(e,()=>r(t,n.value)),i.handler=r,e.on(n,null,i)),e}function YM(e,t,n){const r=xB(t,n);return r&&t._targets.remove(r),e}Be(_B,sd,{async evaluate(e,t,n){if(await sd.prototype.evaluate.call(this,e,t),this._redraw||this._resize)try{this._renderer&&(this._resize&&(this._resize=0,kde(this)),await this._renderer.renderAsync(this._scenegraph.root)),this._redraw=!1}catch(r){this.error(r)}return n&&d1(this,n),this},dirty(e){this._redraw=!0,this._renderer&&this._renderer.dirty(e)},description(e){if(arguments.length){const t=e!=null?e+"":null;return t!==this._desc&&uB(this._el,this._desc=t),this}return this._desc},container(){return this._el},scenegraph(){return this._scenegraph},origin(){return this._origin.slice()},signal(e,t,n){const r=Im(this,e);return arguments.length===1?r.value:this.update(r,t,n)},width(e){return arguments.length?this.signal("width",e):this.signal("width")},height(e){return arguments.length?this.signal("height",e):this.signal("height")},padding(e){return arguments.length?this.signal("padding",WM(e)):WM(this.signal("padding"))},autosize(e){return arguments.length?this.signal("autosize",e):this.signal("autosize")},background(e){return arguments.length?this.signal("background",e):this.signal("background")},renderer(e){return arguments.length?($b(e)||ye("Unrecognized renderer type: "+e),e!==this._renderType&&(this._renderType=e,this._resetRenderer()),this):this._renderType},tooltip(e){return arguments.length?(e!==this._tooltip&&(this._tooltip=e,this._resetRenderer()),this):this._tooltip},loader(e){return arguments.length?(e!==this._loader&&(sd.prototype.loader.call(this,e),this._resetRenderer()),this):this._loader},resize(){return this._autosize=1,this.touch(Im(this,"autosize"))},_resetRenderer(){this._renderer&&(this._renderer=null,this.initialize(this._el,this._elBind))},_resizeView:ihe,addEventListener(e,t,n){let r=t;return n&&n.trap===!1||(r=XC(this,t),r.raw=t),this._handler.on(e,r),this},removeEventListener(e,t){for(var n=this._handler.handlers(e),r=n.length,i,s;--r>=0;)if(s=n[r].type,i=n[r].handler,e===s&&(t===i||t===i.raw)){this._handler.off(s,i);break}return this},addResizeListener(e){const t=this._resizeListeners;return t.includes(e)||t.push(e),this},removeResizeListener(e){var t=this._resizeListeners,n=t.indexOf(e);return n>=0&&t.splice(n,1),this},addSignalListener(e,t){return GM(this,e,Im(this,e),t)},removeSignalListener(e,t){return YM(this,Im(this,e),t)},addDataListener(e,t){return GM(this,e,iy(this,e).values,t)},removeDataListener(e,t){return YM(this,iy(this,e).values,t)},globalCursor(e){if(arguments.length){if(this._globalCursor!==!!e){const t=aA(this,null);this._globalCursor=!!e,t&&aA(this,t)}return this}else return this._globalCursor},preventDefault(e){return arguments.length?(this._preventDefault=e,this):this._preventDefault},timer:uhe,events:Rde,finalize:Ode,hover:Nde,data:wde,change:jb,insert:Ede,remove:Ade,scale:nhe,initialize:Xde,toImageURL:Zde,toCanvas:Qde,toSVG:ehe,getState:she,setState:lhe,_watchPixelRatio:hhe});const phe="view",ay="[",oy="]",wB="{",EB="}",ghe=":",AB=",",mhe="@",vhe=">",yhe=/[[\]{}]/,bhe={"*":1,arc:1,area:1,group:1,image:1,line:1,path:1,rect:1,rule:1,shape:1,symbol:1,text:1,trail:1};let kB,SB;function $u(e,t,n){return kB=t||phe,SB=n||bhe,CB(e.trim()).map(oA)}function _he(e){return SB[e]}function lg(e,t,n,r,i){const s=e.length;let a=0,o;for(;t=0?--a:r&&r.indexOf(o)>=0&&++a}return t}function CB(e){const t=[],n=e.length;let r=0,i=0;for(;i' after between selector: "+e;r=r.map(oA);const i=oA(e.slice(1).trim());return i.between?{between:r,stream:i}:(i.between=r,i)}function whe(e){const t={source:kB},n=[];let r=[0,0],i=0,s=0,a=e.length,o=0,l,u;if(e[a-1]===EB){if(o=e.lastIndexOf(wB),o>=0){try{r=Ehe(e.substring(o+1,a-1))}catch{throw"Invalid throttle specification: "+e}e=e.slice(0,o).trim(),a=e.length}else throw"Unmatched right brace: "+e;o=0}if(!a)throw e;if(e[0]===mhe&&(i=++o),l=lg(e,o,ghe),l1?(t.type=n[1],i?t.markname=n[0].slice(1):_he(n[0])?t.marktype=n[0]:t.source=n[0]):t.type=n[0],t.type.slice(-1)==="!"&&(t.consume=!0,t.type=t.type.slice(0,-1)),u!=null&&(t.filter=u),r[0]&&(t.throttle=r[0]),r[1]&&(t.debounce=r[1]),t}function Ehe(e){const t=e.split(AB);if(!e.length||t.length>2)throw e;return t.map(n=>{const r=+n;if(r!==r)throw e;return r})}function Ahe(e){return Ue(e)?e:{type:e||"pad"}}const dp=e=>+e||0,khe=e=>({top:e,bottom:e,left:e,right:e});function She(e){return Ue(e)?e.signal?e:{top:dp(e.top),bottom:dp(e.bottom),left:dp(e.left),right:dp(e.right)}:khe(dp(e))}const yr=e=>Ue(e)&&!Se(e)?Tt({},e):{value:e};function VM(e,t,n,r){return n!=null?(Ue(n)&&!Se(n)||Se(n)&&n.length&&Ue(n[0])?e.update[t]=n:e[r||"enter"][t]={value:n},1):0}function Pr(e,t,n){for(const r in t)VM(e,r,t[r]);for(const r in n)VM(e,r,n[r],"update")}function Th(e,t,n){for(const r in t)n&&Ve(n,r)||(e[r]=Tt(e[r]||{},t[r]));return e}function Vf(e,t){return t&&(t.enter&&t.enter[e]||t.update&&t.update[e])}const JC="mark",QC="frame",e$="scope",Che="axis",$he="axis-domain",Fhe="axis-grid",Dhe="axis-label",Mhe="axis-tick",The="axis-title",Rhe="legend",Nhe="legend-band",Ohe="legend-entry",Lhe="legend-gradient",$B="legend-label",Ihe="legend-symbol",Phe="legend-title",Bhe="title",zhe="title-text",jhe="title-subtitle";function Uhe(e,t,n,r,i){const s={},a={};let o,l,u,c;l="lineBreak",t==="text"&&i[l]!=null&&!Vf(l,e)&&yx(s,l,i[l]),(n=="legend"||String(n).startsWith("axis"))&&(n=null),c=n===QC?i.group:n===JC?Tt({},i.mark,i[t]):null;for(l in c)u=Vf(l,e)||(l==="fill"||l==="stroke")&&(Vf("fill",e)||Vf("stroke",e)),u||yx(s,l,c[l]);He(r).forEach(f=>{const d=i.style&&i.style[f];for(const h in d)Vf(h,e)||yx(s,h,d[h])}),e=Tt({},e);for(l in s)c=s[l],c.signal?(o=o||{})[l]=c:a[l]=c;return e.enter=Tt(a,e.enter),o&&(e.update=Tt(o,e.update)),e}function yx(e,t,n){e[t]=n&&n.signal?{signal:n.signal}:{value:n}}const FB=e=>We(e)?Pe(e):e.signal?`(${e.signal})`:DB(e);function qb(e){if(e.gradient!=null)return Whe(e);let t=e.signal?`(${e.signal})`:e.color?qhe(e.color):e.field!=null?DB(e.field):e.value!==void 0?Pe(e.value):void 0;return e.scale!=null&&(t=Hhe(e,t)),t===void 0&&(t=null),e.exponent!=null&&(t=`pow(${t},${D1(e.exponent)})`),e.mult!=null&&(t+=`*${D1(e.mult)}`),e.offset!=null&&(t+=`+${D1(e.offset)}`),e.round&&(t=`round(${t})`),t}const Pm=(e,t,n,r)=>`(${e}(${[t,n,r].map(qb).join(",")})+'')`;function qhe(e){return e.c?Pm("hcl",e.h,e.c,e.l):e.h||e.s?Pm("hsl",e.h,e.s,e.l):e.l||e.a?Pm("lab",e.l,e.a,e.b):e.r||e.g||e.b?Pm("rgb",e.r,e.g,e.b):null}function Whe(e){const t=[e.start,e.stop,e.count].map(n=>n==null?null:Pe(n));for(;t.length&&Xt(t)==null;)t.pop();return t.unshift(FB(e.gradient)),`gradient(${t.join(",")})`}function D1(e){return Ue(e)?"("+qb(e)+")":e}function DB(e){return MB(Ue(e)?e:{datum:e})}function MB(e){let t,n,r;if(e.signal)t="datum",r=e.signal;else if(e.group||e.parent){for(n=Math.max(1,e.level||1),t="item";n-- >0;)t+=".mark.group";e.parent?(r=e.parent,t+=".datum"):r=e.group}else e.datum?(t="datum",r=e.datum):ye("Invalid field reference: "+Pe(e));return e.signal||(r=We(r)?go(r).map(Pe).join("]["):MB(r)),t+"["+r+"]"}function Hhe(e,t){const n=FB(e.scale);return e.range!=null?t=`lerp(_range(${n}), ${+e.range})`:(t!==void 0&&(t=`_scale(${n}, ${t})`),e.band&&(t=(t?t+"+":"")+`_bandwidth(${n})`+(+e.band==1?"":"*"+D1(e.band)),e.extra&&(t=`(datum.extra ? _scale(${n}, datum.extra.value) : ${t})`)),t==null&&(t="0")),t}function Ghe(e){let t="";return e.forEach(n=>{const r=qb(n);t+=n.test?`(${n.test})?${r}:`:r}),Xt(t)===":"&&(t+="null"),t}function TB(e,t,n,r,i,s){const a={};s=s||{},s.encoders={$encode:a},e=Uhe(e,t,n,r,i.config);for(const o in e)a[o]=Yhe(e[o],t,s,i);return s}function Yhe(e,t,n,r){const i={},s={};for(const a in e)e[a]!=null&&(i[a]=Xhe(Vhe(e[a]),r,n,s));return{$expr:{marktype:t,channels:i},$fields:Object.keys(s),$output:Object.keys(e)}}function Vhe(e){return Se(e)?Ghe(e):qb(e)}function Xhe(e,t,n,r){const i=uo(e,t);return i.$fields.forEach(s=>r[s]=1),Tt(n,i.$params),i.$expr}const Khe="outer",Zhe=["value","update","init","react","bind"];function XM(e,t){ye(e+' for "outer" push: '+Pe(t))}function RB(e,t){const n=e.name;if(e.push===Khe)t.signals[n]||XM("No prior signal definition",n),Zhe.forEach(r=>{e[r]!==void 0&&XM("Invalid property ",r)});else{const r=t.addSignal(n,e.value);e.react===!1&&(r.react=!1),e.bind&&t.addBinding(n,e.bind)}}function lA(e,t,n,r){this.id=-1,this.type=e,this.value=t,this.params=n,r&&(this.parent=r)}function Wb(e,t,n,r){return new lA(e,t,n,r)}function ly(e,t){return Wb("operator",e,t)}function ft(e){const t={$ref:e.id};return e.id<0&&(e.refs=e.refs||[]).push(t),t}function Ig(e,t){return t?{$field:e,$name:t}:{$field:e}}const uA=Ig("key");function KM(e,t){return{$compare:e,$order:t}}function Jhe(e,t){const n={$key:e};return t&&(n.$flat=!0),n}const Qhe="ascending",epe="descending";function tpe(e){return Ue(e)?(e.order===epe?"-":"+")+Hb(e.op,e.field):""}function Hb(e,t){return(e&&e.signal?"$"+e.signal:e||"")+(e&&t?"_":"")+(t&&t.signal?"$"+t.signal:t||"")}const t$="scope",cA="view";function sr(e){return e&&e.signal}function npe(e){return e&&e.expr}function M1(e){if(sr(e))return!0;if(Ue(e)){for(const t in e)if(M1(e[t]))return!0}return!1}function Js(e,t){return e??t}function Sc(e){return e&&e.signal||e}const ZM="timer";function Pg(e,t){return(e.merge?ipe:e.stream?spe:e.type?ape:ye("Invalid stream specification: "+Pe(e)))(e,t)}function rpe(e){return e===t$?cA:e||cA}function ipe(e,t){const n=e.merge.map(i=>Pg(i,t)),r=n$({merge:n},e,t);return t.addStream(r).id}function spe(e,t){const n=Pg(e.stream,t),r=n$({stream:n},e,t);return t.addStream(r).id}function ape(e,t){let n;e.type===ZM?(n=t.event(ZM,e.throttle),e={between:e.between,filter:e.filter}):n=t.event(rpe(e.source),e.type);const r=n$({stream:n},e,t);return Object.keys(r).length===1?n:t.addStream(r).id}function n$(e,t,n){let r=t.between;return r&&(r.length!==2&&ye('Stream "between" parameter must have 2 entries: '+Pe(t)),e.between=[Pg(r[0],n),Pg(r[1],n)]),r=t.filter?[].concat(t.filter):[],(t.marktype||t.markname||t.markrole)&&r.push(ope(t.marktype,t.markname,t.markrole)),t.source===t$&&r.push("inScope(event.item)"),r.length&&(e.filter=uo("("+r.join(")&&(")+")",n).$expr),(r=t.throttle)!=null&&(e.throttle=+r),(r=t.debounce)!=null&&(e.debounce=+r),t.consume&&(e.consume=!0),e}function ope(e,t,n){const r="event.item";return r+(e&&e!=="*"?"&&"+r+".mark.marktype==='"+e+"'":"")+(n?"&&"+r+".mark.role==='"+n+"'":"")+(t?"&&"+r+".mark.name==='"+t+"'":"")}const lpe={code:"_.$value",ast:{type:"Identifier",value:"value"}};function upe(e,t,n){const r=e.encode,i={target:n};let s=e.events,a=e.update,o=[];s||ye("Signal update missing events specification."),We(s)&&(s=$u(s,t.isSubscope()?t$:cA)),s=He(s).filter(l=>l.signal||l.scale?(o.push(l),0):1),o.length>1&&(o=[fpe(o)]),s.length&&o.push(s.length>1?{merge:s}:s[0]),r!=null&&(a&&ye("Signal encode and update are mutually exclusive."),a="encode(item(),"+Pe(r)+")"),i.update=We(a)?uo(a,t):a.expr!=null?uo(a.expr,t):a.value!=null?a.value:a.signal!=null?{$expr:lpe,$params:{$value:t.signalRef(a.signal)}}:ye("Invalid signal update specification."),e.force&&(i.options={force:!0}),o.forEach(l=>t.addUpdate(Tt(cpe(l,t),i)))}function cpe(e,t){return{source:e.signal?t.signalRef(e.signal):e.scale?t.scaleRef(e.scale):Pg(e,t)}}function fpe(e){return{signal:"["+e.map(t=>t.scale?'scale("'+t.scale+'")':t.signal)+"]"}}function dpe(e,t){const n=t.getSignal(e.name);let r=e.update;e.init&&(r?ye("Signals can not include both init and update expressions."):(r=e.init,n.initonly=!0)),r&&(r=uo(r,t),n.update=r.$expr,n.params=r.$params),e.on&&e.on.forEach(i=>upe(i,t,n.id))}const pn=e=>(t,n,r)=>Wb(e,n,t||void 0,r),NB=pn("aggregate"),hpe=pn("axisticks"),OB=pn("bound"),_a=pn("collect"),JM=pn("compare"),ppe=pn("datajoin"),LB=pn("encode"),gpe=pn("expression"),mpe=pn("facet"),vpe=pn("field"),ype=pn("key"),bpe=pn("legendentries"),_pe=pn("load"),xpe=pn("mark"),wpe=pn("multiextent"),Epe=pn("multivalues"),Ape=pn("overlap"),kpe=pn("params"),IB=pn("prefacet"),Spe=pn("projection"),Cpe=pn("proxy"),$pe=pn("relay"),PB=pn("render"),Fpe=pn("scale"),bf=pn("sieve"),Dpe=pn("sortitems"),BB=pn("viewlayout"),Mpe=pn("values");let Tpe=0;const zB={min:"min",max:"max",count:"sum"};function Rpe(e,t){const n=e.type||"linear";k9(n)||ye("Unrecognized scale type: "+Pe(n)),t.addScale(e.name,{type:n,domain:void 0})}function Npe(e,t){const n=t.getScale(e.name).params;let r;n.domain=jB(e.domain,e,t),e.range!=null&&(n.range=qB(e,t,n)),e.interpolate!=null&&Wpe(e.interpolate,n),e.nice!=null&&(n.nice=qpe(e.nice,t)),e.bins!=null&&(n.bins=Upe(e.bins,t));for(r in e)Ve(n,r)||r==="name"||(n[r]=ks(e[r],t))}function ks(e,t){return Ue(e)?e.signal?t.signalRef(e.signal):ye("Unsupported object: "+Pe(e)):e}function T1(e,t){return e.signal?t.signalRef(e.signal):e.map(n=>ks(n,t))}function Gb(e){ye("Can not find data set: "+Pe(e))}function jB(e,t,n){if(!e){(t.domainMin!=null||t.domainMax!=null)&&ye("No scale domain defined for domainMin/domainMax to override.");return}return e.signal?n.signalRef(e.signal):(Se(e)?Ope:e.fields?Ipe:Lpe)(e,t,n)}function Ope(e,t,n){return e.map(r=>ks(r,n))}function Lpe(e,t,n){const r=n.getData(e.data);return r||Gb(e.data),Ud(t.type)?r.valuesRef(n,e.field,UB(e.sort,!1)):$9(t.type)?r.domainRef(n,e.field):r.extentRef(n,e.field)}function Ipe(e,t,n){const r=e.data,i=e.fields.reduce((s,a)=>(a=We(a)?{data:r,field:a}:Se(a)||a.signal?Ppe(a,n):a,s.push(a),s),[]);return(Ud(t.type)?Bpe:$9(t.type)?zpe:jpe)(e,n,i)}function Ppe(e,t){const n="_:vega:_"+Tpe++,r=_a({});if(Se(e))r.value={$ingest:e};else if(e.signal){const i="setdata("+Pe(n)+","+e.signal+")";r.params.input=t.signalRef(i)}return t.addDataPipeline(n,[r,bf({})]),{data:n,field:"data"}}function Bpe(e,t,n){const r=UB(e.sort,!0);let i,s;const a=n.map(u=>{const c=t.getData(u.data);return c||Gb(u.data),c.countsRef(t,u.field,r)}),o={groupby:uA,pulse:a};r&&(i=r.op||"count",s=r.field?Hb(i,r.field):"count",o.ops=[zB[i]],o.fields=[t.fieldRef(s)],o.as=[s]),i=t.add(NB(o));const l=t.add(_a({pulse:ft(i)}));return s=t.add(Mpe({field:uA,sort:t.sortRef(r),pulse:ft(l)})),ft(s)}function UB(e,t){return e&&(!e.field&&!e.op?Ue(e)?e.field="key":e={field:"key"}:!e.field&&e.op!=="count"?ye("No field provided for sort aggregate op: "+e.op):t&&e.field&&e.op&&!zB[e.op]&&ye("Multiple domain scales can not be sorted using "+e.op)),e}function zpe(e,t,n){const r=n.map(i=>{const s=t.getData(i.data);return s||Gb(i.data),s.domainRef(t,i.field)});return ft(t.add(Epe({values:r})))}function jpe(e,t,n){const r=n.map(i=>{const s=t.getData(i.data);return s||Gb(i.data),s.extentRef(t,i.field)});return ft(t.add(wpe({extents:r})))}function Upe(e,t){return e.signal||Se(e)?T1(e,t):t.objectProperty(e)}function qpe(e,t){return e.signal?t.signalRef(e.signal):Ue(e)?{interval:ks(e.interval),step:ks(e.step)}:ks(e)}function Wpe(e,t){t.interpolate=ks(e.type||e),e.gamma!=null&&(t.interpolateGamma=ks(e.gamma))}function qB(e,t,n){const r=t.config.range;let i=e.range;if(i.signal)return t.signalRef(i.signal);if(We(i)){if(r&&Ve(r,i))return e=Tt({},e,{range:r[i]}),qB(e,t,n);i==="width"?i=[0,{signal:"width"}]:i==="height"?i=Ud(e.type)?[0,{signal:"height"}]:[{signal:"height"},0]:ye("Unrecognized scale range value: "+Pe(i))}else if(i.scheme){n.scheme=Se(i.scheme)?T1(i.scheme,t):ks(i.scheme,t),i.extent&&(n.schemeExtent=T1(i.extent,t)),i.count&&(n.schemeCount=ks(i.count,t));return}else if(i.step){n.rangeStep=ks(i.step,t);return}else{if(Ud(e.type)&&!Se(i))return jB(i,e,t);Se(i)||ye("Unsupported range type: "+Pe(i))}return i.map(s=>(Se(s)?T1:ks)(s,t))}function Hpe(e,t){const n=t.config.projection||{},r={};for(const i in e)i!=="name"&&(r[i]=fA(e[i],i,t));for(const i in n)r[i]==null&&(r[i]=fA(n[i],i,t));t.addProjection(e.name,r)}function fA(e,t,n){return Se(e)?e.map(r=>fA(r,t,n)):Ue(e)?e.signal?n.signalRef(e.signal):t==="fit"?e:ye("Unsupported parameter object: "+Pe(e)):e}const xa="top",Rh="left",Nh="right",du="bottom",WB="center",Gpe="vertical",Ype="start",Vpe="middle",Xpe="end",dA="index",r$="label",Kpe="offset",Zd="perc",Zpe="perc2",Ds="value",I0="guide-label",i$="guide-title",Jpe="group-title",Qpe="group-subtitle",QM="symbol",R1="gradient",hA="discrete",pA="size",ege="shape",tge="fill",nge="stroke",rge="strokeWidth",ige="strokeDash",sge="opacity",s$=[pA,ege,tge,nge,rge,ige,sge],P0={name:1,style:1,interactive:1},Kt={value:0},Ms={value:1},Yb="group",HB="rect",a$="rule",age="symbol",_f="text";function Bg(e){return e.type=Yb,e.interactive=e.interactive||!1,e}function Hi(e,t){const n=(r,i)=>Js(e[r],Js(t[r],i));return n.isVertical=r=>Gpe===Js(e.direction,t.direction||(r?t.symbolDirection:t.gradientDirection)),n.gradientLength=()=>Js(e.gradientLength,t.gradientLength||t.gradientWidth),n.gradientThickness=()=>Js(e.gradientThickness,t.gradientThickness||t.gradientHeight),n.entryColumns=()=>Js(e.columns,Js(t.columns,+n.isVertical(!0))),n}function GB(e,t){const n=t&&(t.update&&t.update[e]||t.enter&&t.enter[e]);return n&&n.signal?n:n?n.value:null}function oge(e,t,n){const r=t.config.style[n];return r&&r[e]}function Vb(e,t,n){return`item.anchor === '${Ype}' ? ${e} : item.anchor === '${Xpe}' ? ${t} : ${n}`}const o$=Vb(Pe(Rh),Pe(Nh),Pe(WB));function lge(e){const t=e("tickBand");let n=e("tickOffset"),r,i;return t?t.signal?(r={signal:`(${t.signal}) === 'extent' ? 1 : 0.5`},i={signal:`(${t.signal}) === 'extent'`},Ue(n)||(n={signal:`(${t.signal}) === 'extent' ? 0 : ${n}`})):t==="extent"?(r=1,i=!0,n=0):(r=.5,i=!1):(r=e("bandPosition"),i=e("tickExtra")),{extra:i,band:r,offset:n}}function YB(e,t){return t?e?Ue(e)?Object.assign({},e,{offset:YB(e.offset,t)}):{value:e,offset:t}:t:e}function ds(e,t){return t?(e.name=t.name,e.style=t.style||e.style,e.interactive=!!t.interactive,e.encode=Th(e.encode,t,P0)):e.interactive=!1,e}function uge(e,t,n,r){const i=Hi(e,n),s=i.isVertical(),a=i.gradientThickness(),o=i.gradientLength();let l,u,c,f,d;s?(u=[0,1],c=[0,0],f=a,d=o):(u=[0,0],c=[1,0],f=o,d=a);const h={enter:l={opacity:Kt,x:Kt,y:Kt,width:yr(f),height:yr(d)},update:Tt({},l,{opacity:Ms,fill:{gradient:t,start:u,stop:c}}),exit:{opacity:Kt}};return Pr(h,{stroke:i("gradientStrokeColor"),strokeWidth:i("gradientStrokeWidth")},{opacity:i("gradientOpacity")}),ds({type:HB,role:Lhe,encode:h},r)}function cge(e,t,n,r,i){const s=Hi(e,n),a=s.isVertical(),o=s.gradientThickness(),l=s.gradientLength();let u,c,f,d,h="";a?(u="y",f="y2",c="x",d="width",h="1-"):(u="x",f="x2",c="y",d="height");const p={opacity:Kt,fill:{scale:t,field:Ds}};p[u]={signal:h+"datum."+Zd,mult:l},p[c]=Kt,p[f]={signal:h+"datum."+Zpe,mult:l},p[d]=yr(o);const g={enter:p,update:Tt({},p,{opacity:Ms}),exit:{opacity:Kt}};return Pr(g,{stroke:s("gradientStrokeColor"),strokeWidth:s("gradientStrokeWidth")},{opacity:s("gradientOpacity")}),ds({type:HB,role:Nhe,key:Ds,from:i,encode:g},r)}const fge=`datum.${Zd}<=0?"${Rh}":datum.${Zd}>=1?"${Nh}":"${WB}"`,dge=`datum.${Zd}<=0?"${du}":datum.${Zd}>=1?"${xa}":"${Vpe}"`;function e6(e,t,n,r){const i=Hi(e,t),s=i.isVertical(),a=yr(i.gradientThickness()),o=i.gradientLength();let l=i("labelOverlap"),u,c,f,d,h="";const p={enter:u={opacity:Kt},update:c={opacity:Ms,text:{field:r$}},exit:{opacity:Kt}};return Pr(p,{fill:i("labelColor"),fillOpacity:i("labelOpacity"),font:i("labelFont"),fontSize:i("labelFontSize"),fontStyle:i("labelFontStyle"),fontWeight:i("labelFontWeight"),limit:Js(e.labelLimit,t.gradientLabelLimit)}),s?(u.align={value:"left"},u.baseline=c.baseline={signal:dge},f="y",d="x",h="1-"):(u.align=c.align={signal:fge},u.baseline={value:"top"},f="x",d="y"),u[f]=c[f]={signal:h+"datum."+Zd,mult:o},u[d]=c[d]=a,a.offset=Js(e.labelOffset,t.gradientLabelOffset)||0,l=l?{separation:i("labelSeparation"),method:l,order:"datum."+dA}:void 0,ds({type:_f,role:$B,style:I0,key:Ds,from:r,encode:p,overlap:l},n)}function hge(e,t,n,r,i){const s=Hi(e,t),a=n.entries,o=!!(a&&a.interactive),l=a?a.name:void 0,u=s("clipHeight"),c=s("symbolOffset"),f={data:"value"},d=`(${i}) ? datum.${Kpe} : datum.${pA}`,h=u?yr(u):{field:pA},p=`datum.${dA}`,g=`max(1, ${i})`;let v,y,b,_,x;h.mult=.5,v={enter:y={opacity:Kt,x:{signal:d,mult:.5,offset:c},y:h},update:b={opacity:Ms,x:y.x,y:y.y},exit:{opacity:Kt}};let w=null,A=null;e.fill||(w=t.symbolBaseFillColor,A=t.symbolBaseStrokeColor),Pr(v,{fill:s("symbolFillColor",w),shape:s("symbolType"),size:s("symbolSize"),stroke:s("symbolStrokeColor",A),strokeDash:s("symbolDash"),strokeDashOffset:s("symbolDashOffset"),strokeWidth:s("symbolStrokeWidth")},{opacity:s("symbolOpacity")}),s$.forEach(M=>{e[M]&&(b[M]=y[M]={scale:e[M],field:Ds})});const E=ds({type:age,role:Ihe,key:Ds,from:f,clip:u?!0:void 0,encode:v},n.symbols),k=yr(c);k.offset=s("labelOffset"),v={enter:y={opacity:Kt,x:{signal:d,offset:k},y:h},update:b={opacity:Ms,text:{field:r$},x:y.x,y:y.y},exit:{opacity:Kt}},Pr(v,{align:s("labelAlign"),baseline:s("labelBaseline"),fill:s("labelColor"),fillOpacity:s("labelOpacity"),font:s("labelFont"),fontSize:s("labelFontSize"),fontStyle:s("labelFontStyle"),fontWeight:s("labelFontWeight"),limit:s("labelLimit")});const C=ds({type:_f,role:$B,style:I0,key:Ds,from:f,encode:v},n.labels);return v={enter:{noBound:{value:!u},width:Kt,height:u?yr(u):Kt,opacity:Kt},exit:{opacity:Kt},update:b={opacity:Ms,row:{signal:null},column:{signal:null}}},s.isVertical(!0)?(_=`ceil(item.mark.items.length / ${g})`,b.row.signal=`${p}%${_}`,b.column.signal=`floor(${p} / ${_})`,x={field:["row",p]}):(b.row.signal=`floor(${p} / ${g})`,b.column.signal=`${p} % ${g}`,x={field:p}),b.column.signal=`(${i})?${b.column.signal}:${p}`,r={facet:{data:r,name:"value",groupby:dA}},Bg({role:e$,from:r,encode:Th(v,a,P0),marks:[E,C],name:l,interactive:o,sort:x})}function pge(e,t){const n=Hi(e,t);return{align:n("gridAlign"),columns:n.entryColumns(),center:{row:!0,column:!1},padding:{row:n("rowPadding"),column:n("columnPadding")}}}const l$='item.orient === "left"',u$='item.orient === "right"',Xb=`(${l$} || ${u$})`,gge=`datum.vgrad && ${Xb}`,mge=Vb('"top"','"bottom"','"middle"'),vge=Vb('"right"','"left"','"center"'),yge=`datum.vgrad && ${u$} ? (${vge}) : (${Xb} && !(datum.vgrad && ${l$})) ? "left" : ${o$}`,bge=`item._anchor || (${Xb} ? "middle" : "start")`,_ge=`${gge} ? (${l$} ? -90 : 90) : 0`,xge=`${Xb} ? (datum.vgrad ? (${u$} ? "bottom" : "top") : ${mge}) : "top"`;function wge(e,t,n,r){const i=Hi(e,t),s={enter:{opacity:Kt},update:{opacity:Ms,x:{field:{group:"padding"}},y:{field:{group:"padding"}}},exit:{opacity:Kt}};return Pr(s,{orient:i("titleOrient"),_anchor:i("titleAnchor"),anchor:{signal:bge},angle:{signal:_ge},align:{signal:yge},baseline:{signal:xge},text:e.title,fill:i("titleColor"),fillOpacity:i("titleOpacity"),font:i("titleFont"),fontSize:i("titleFontSize"),fontStyle:i("titleFontStyle"),fontWeight:i("titleFontWeight"),limit:i("titleLimit"),lineHeight:i("titleLineHeight")},{align:i("titleAlign"),baseline:i("titleBaseline")}),ds({type:_f,role:Phe,style:i$,from:r,encode:s},n)}function Ege(e,t){let n;return Ue(e)&&(e.signal?n=e.signal:e.path?n="pathShape("+t6(e.path)+")":e.sphere&&(n="geoShape("+t6(e.sphere)+', {type: "Sphere"})')),n?t.signalRef(n):!!e}function t6(e){return Ue(e)&&e.signal?e.signal:Pe(e)}function VB(e){const t=e.role||"";return t.startsWith("axis")||t.startsWith("legend")||t.startsWith("title")?t:e.type===Yb?e$:t||JC}function Age(e){return{marktype:e.type,name:e.name||void 0,role:e.role||VB(e),zindex:+e.zindex||void 0,aria:e.aria,description:e.description}}function kge(e,t){return e&&e.signal?t.signalRef(e.signal):e!==!1}function c$(e,t){const n=CO(e.type);n||ye("Unrecognized transform type: "+Pe(e.type));const r=Wb(n.type.toLowerCase(),null,XB(n,e,t));return e.signal&&t.addSignal(e.signal,t.proxy(r)),r.metadata=n.metadata||{},r}function XB(e,t,n){const r={},i=e.params.length;for(let s=0;sn6(e,s,n)):n6(e,i,n)}function n6(e,t,n){const r=e.type;if(sr(t))return i6(r)?ye("Expression references can not be signals."):bx(r)?n.fieldRef(t):s6(r)?n.compareRef(t):n.signalRef(t.signal);{const i=e.expr||bx(r);return i&&Fge(t)?n.exprRef(t.expr,t.as):i&&Dge(t)?Ig(t.field,t.as):i6(r)?uo(t,n):Mge(r)?ft(n.getData(t).values):bx(r)?Ig(t):s6(r)?n.compareRef(t):t}}function Cge(e,t,n){return We(t.from)||ye('Lookup "from" parameter must be a string literal.'),n.getData(t.from).lookupRef(n,t.key)}function $ge(e,t,n){const r=t[e.name];return e.array?(Se(r)||ye("Expected an array of sub-parameters. Instead: "+Pe(r)),r.map(i=>r6(e,i,n))):r6(e,r,n)}function r6(e,t,n){const r=e.params.length;let i;for(let a=0;ae&&e.expr,Dge=e=>e&&e.field,Mge=e=>e==="data",i6=e=>e==="expr",bx=e=>e==="field",s6=e=>e==="compare";function Tge(e,t,n){let r,i,s,a,o;return e?(r=e.facet)&&(t||ye("Only group marks can be faceted."),r.field!=null?a=o=N1(r,n):(e.data?o=ft(n.getData(e.data).aggregate):(s=c$(Tt({type:"aggregate",groupby:He(r.groupby)},r.aggregate),n),s.params.key=n.keyRef(r.groupby),s.params.pulse=N1(r,n),a=o=ft(n.add(s))),i=n.keyRef(r.groupby,!0))):a=ft(n.add(_a(null,[{}]))),a||(a=N1(e,n)),{key:i,pulse:a,parent:o}}function N1(e,t){return e.$ref?e:e.data&&e.data.$ref?e.data:ft(t.getData(e.data).output)}function Zc(e,t,n,r,i){this.scope=e,this.input=t,this.output=n,this.values=r,this.aggregate=i,this.index={}}Zc.fromEntries=function(e,t){const n=t.length,r=t[n-1],i=t[n-2];let s=t[0],a=null,o=1;for(s&&s.type==="load"&&(s=t[1]),e.add(t[0]);of??"null").join(",")+"),0)",c=uo(u,t);l.update=c.$expr,l.params=c.$params}function Kb(e,t){const n=VB(e),r=e.type===Yb,i=e.from&&e.from.facet,s=e.overlap;let a=e.layout||n===e$||n===QC,o,l,u,c,f,d,h;const p=n===JC||a||i,g=Tge(e.from,r,t);l=t.add(ppe({key:g.key||(e.key?Ig(e.key):void 0),pulse:g.pulse,clean:!r}));const v=ft(l);l=u=t.add(_a({pulse:v})),l=t.add(xpe({markdef:Age(e),interactive:kge(e.interactive,t),clip:Ege(e.clip,t),context:{$context:!0},groups:t.lookup(),parent:t.signals.parent?t.signalRef("parent"):null,index:t.markpath(),pulse:ft(l)}));const y=ft(l);l=c=t.add(LB(TB(e.encode,e.type,n,e.style,t,{mod:!1,pulse:y}))),l.params.parent=t.encode(),e.transform&&e.transform.forEach(A=>{const E=c$(A,t),k=E.metadata;(k.generates||k.changes)&&ye("Mark transforms should not generate new data."),k.nomod||(c.params.mod=!0),E.params.pulse=ft(l),t.add(l=E)}),e.sort&&(l=t.add(Dpe({sort:t.compareRef(e.sort),pulse:ft(l)})));const b=ft(l);(i||a)&&(a=t.add(BB({layout:t.objectProperty(e.layout),legends:t.legends,mark:y,pulse:b})),d=ft(a));const _=t.add(OB({mark:y,pulse:d||b}));h=ft(_),r&&(p&&(o=t.operators,o.pop(),a&&o.pop()),t.pushState(b,d||h,v),i?Rge(e,t,g):p?Nge(e,t,g):t.parse(e),t.popState(),p&&(a&&o.push(a),o.push(_))),s&&(h=Oge(s,h,t));const x=t.add(PB({pulse:h})),w=t.add(bf({pulse:ft(x)},void 0,t.parent()));e.name!=null&&(f=e.name,t.addData(f,new Zc(t,u,x,w)),e.on&&e.on.forEach(A=>{(A.insert||A.remove||A.toggle)&&ye("Marks only support modify triggers."),ZB(A,t,f)}))}function Oge(e,t,n){const r=e.method,i=e.bound,s=e.separation,a={separation:sr(s)?n.signalRef(s.signal):s,method:sr(r)?n.signalRef(r.signal):r,pulse:t};if(e.order&&(a.sort=n.compareRef({field:e.order})),i){const o=i.tolerance;a.boundTolerance=sr(o)?n.signalRef(o.signal):+o,a.boundScale=n.scaleRef(i.scale),a.boundOrient=i.orient}return ft(n.add(Ape(a)))}function Lge(e,t){const n=t.config.legend,r=e.encode||{},i=Hi(e,n),s=r.legend||{},a=s.name||void 0,o=s.interactive,l=s.style,u={};let c=0,f,d,h;s$.forEach(_=>e[_]?(u[_]=e[_],c=c||e[_]):0),c||ye("Missing valid scale for legend.");const p=Ige(e,t.scaleType(c)),g={title:e.title!=null,scales:u,type:p,vgrad:p!=="symbol"&&i.isVertical()},v=ft(t.add(_a(null,[g]))),y={enter:{x:{value:0},y:{value:0}}},b=ft(t.add(bpe(d={type:p,scale:t.scaleRef(c),count:t.objectProperty(i("tickCount")),limit:t.property(i("symbolLimit")),values:t.objectProperty(e.values),minstep:t.property(e.tickMinStep),formatType:t.property(e.formatType),formatSpecifier:t.property(e.format)})));return p===R1?(h=[uge(e,c,n,r.gradient),e6(e,n,r.labels,b)],d.count=d.count||t.signalRef(`max(2,2*floor((${Sc(i.gradientLength())})/100))`)):p===hA?h=[cge(e,c,n,r.gradient,b),e6(e,n,r.labels,b)]:(f=pge(e,n),h=[hge(e,n,r,b,Sc(f.columns))],d.size=zge(e,t,h[0].marks)),h=[Bg({role:Ohe,from:v,encode:y,marks:h,layout:f,interactive:o})],g.title&&h.push(wge(e,n,r.title,v)),Kb(Bg({role:Rhe,from:v,encode:Th(Bge(i,e,n),s,P0),marks:h,aria:i("aria"),description:i("description"),zindex:i("zindex"),name:a,interactive:o,style:l}),t)}function Ige(e,t){let n=e.type||QM;return!e.type&&Pge(e)===1&&(e.fill||e.stroke)&&(n=f3(t)?R1:sE(t)?hA:QM),n!==R1?n:sE(t)?hA:R1}function Pge(e){return s$.reduce((t,n)=>t+(e[n]?1:0),0)}function Bge(e,t,n){const r={enter:{},update:{}};return Pr(r,{orient:e("orient"),offset:e("offset"),padding:e("padding"),titlePadding:e("titlePadding"),cornerRadius:e("cornerRadius"),fill:e("fillColor"),stroke:e("strokeColor"),strokeWidth:n.strokeWidth,strokeDash:n.strokeDash,x:e("legendX"),y:e("legendY"),format:t.format,formatType:t.formatType}),r}function zge(e,t,n){const r=Sc(o6("size",e,n)),i=Sc(o6("strokeWidth",e,n)),s=Sc(jge(n[1].encode,t,I0));return uo(`max(ceil(sqrt(${r})+${i}),${s})`,t)}function o6(e,t,n){return t[e]?`scale("${t[e]}",datum)`:GB(e,n[0].encode)}function jge(e,t,n){return GB("fontSize",e)||oge("fontSize",t,n)}const Uge=`item.orient==="${Rh}"?-90:item.orient==="${Nh}"?90:0`;function qge(e,t){e=We(e)?{text:e}:e;const n=Hi(e,t.config.title),r=e.encode||{},i=r.group||{},s=i.name||void 0,a=i.interactive,o=i.style,l=[],u={},c=ft(t.add(_a(null,[u])));return l.push(Gge(e,n,Wge(e),c)),e.subtitle&&l.push(Yge(e,n,r.subtitle,c)),Kb(Bg({role:Bhe,from:c,encode:Hge(n,i),marks:l,aria:n("aria"),description:n("description"),zindex:n("zindex"),name:s,interactive:a,style:o}),t)}function Wge(e){const t=e.encode;return t&&t.title||Tt({name:e.name,interactive:e.interactive,style:e.style},t)}function Hge(e,t){const n={enter:{},update:{}};return Pr(n,{orient:e("orient"),anchor:e("anchor"),align:{signal:o$},angle:{signal:Uge},limit:e("limit"),frame:e("frame"),offset:e("offset")||0,padding:e("subtitlePadding")}),Th(n,t,P0)}function Gge(e,t,n,r){const i={value:0},s=e.text,a={enter:{opacity:i},update:{opacity:{value:1}},exit:{opacity:i}};return Pr(a,{text:s,align:{signal:"item.mark.group.align"},angle:{signal:"item.mark.group.angle"},limit:{signal:"item.mark.group.limit"},baseline:"top",dx:t("dx"),dy:t("dy"),fill:t("color"),font:t("font"),fontSize:t("fontSize"),fontStyle:t("fontStyle"),fontWeight:t("fontWeight"),lineHeight:t("lineHeight")},{align:t("align"),angle:t("angle"),baseline:t("baseline")}),ds({type:_f,role:zhe,style:Jpe,from:r,encode:a},n)}function Yge(e,t,n,r){const i={value:0},s=e.subtitle,a={enter:{opacity:i},update:{opacity:{value:1}},exit:{opacity:i}};return Pr(a,{text:s,align:{signal:"item.mark.group.align"},angle:{signal:"item.mark.group.angle"},limit:{signal:"item.mark.group.limit"},baseline:"top",dx:t("dx"),dy:t("dy"),fill:t("subtitleColor"),font:t("subtitleFont"),fontSize:t("subtitleFontSize"),fontStyle:t("subtitleFontStyle"),fontWeight:t("subtitleFontWeight"),lineHeight:t("subtitleLineHeight")},{align:t("align"),angle:t("angle"),baseline:t("baseline")}),ds({type:_f,role:jhe,style:Qpe,from:r,encode:a},n)}function Vge(e,t){const n=[];e.transform&&e.transform.forEach(r=>{n.push(c$(r,t))}),e.on&&e.on.forEach(r=>{ZB(r,t,e.name)}),t.addDataPipeline(e.name,Xge(e,t,n))}function Xge(e,t,n){const r=[];let i=null,s=!1,a=!1,o,l,u,c,f;for(e.values?sr(e.values)||M1(e.format)?(r.push(l6(t,e)),r.push(i=Hu())):r.push(i=Hu({$ingest:e.values,$format:e.format})):e.url?M1(e.url)||M1(e.format)?(r.push(l6(t,e)),r.push(i=Hu())):r.push(i=Hu({$request:e.url,$format:e.format})):e.source&&(i=o=He(e.source).map(d=>ft(t.getData(d).output)),r.push(null)),l=0,u=n.length;le===du||e===xa,Zb=(e,t,n)=>sr(e)?Qge(e.signal,t,n):e===Rh||e===xa?t:n,br=(e,t,n)=>sr(e)?Zge(e.signal,t,n):JB(e)?t:n,la=(e,t,n)=>sr(e)?Jge(e.signal,t,n):JB(e)?n:t,QB=(e,t,n)=>sr(e)?e0e(e.signal,t,n):e===xa?{value:t}:{value:n},Kge=(e,t,n)=>sr(e)?t0e(e.signal,t,n):e===Nh?{value:t}:{value:n},Zge=(e,t,n)=>ez(`${e} === '${xa}' || ${e} === '${du}'`,t,n),Jge=(e,t,n)=>ez(`${e} !== '${xa}' && ${e} !== '${du}'`,t,n),Qge=(e,t,n)=>f$(`${e} === '${Rh}' || ${e} === '${xa}'`,t,n),e0e=(e,t,n)=>f$(`${e} === '${xa}'`,t,n),t0e=(e,t,n)=>f$(`${e} === '${Nh}'`,t,n),ez=(e,t,n)=>(t=t!=null?yr(t):t,n=n!=null?yr(n):n,u6(t)&&u6(n)?(t=t?t.signal||Pe(t.value):null,n=n?n.signal||Pe(n.value):null,{signal:`${e} ? (${t}) : (${n})`}):[Tt({test:e},t)].concat(n||[])),u6=e=>e==null||Object.keys(e).length===1,f$=(e,t,n)=>({signal:`${e} ? (${nd(t)}) : (${nd(n)})`}),n0e=(e,t,n,r,i)=>({signal:(r!=null?`${e} === '${Rh}' ? (${nd(r)}) : `:"")+(n!=null?`${e} === '${du}' ? (${nd(n)}) : `:"")+(i!=null?`${e} === '${Nh}' ? (${nd(i)}) : `:"")+(t!=null?`${e} === '${xa}' ? (${nd(t)}) : `:"")+"(null)"}),nd=e=>sr(e)?e.signal:e==null?null:Pe(e),r0e=(e,t)=>t===0?0:sr(e)?{signal:`(${e.signal}) * ${t}`}:{value:e*t},ud=(e,t)=>{const n=e.signal;return n&&n.endsWith("(null)")?{signal:n.slice(0,-6)+t.signal}:e};function zf(e,t,n,r){let i;if(t&&Ve(t,e))return t[e];if(Ve(n,e))return n[e];if(e.startsWith("title")){switch(e){case"titleColor":i="fill";break;case"titleFont":case"titleFontSize":case"titleFontWeight":i=e[5].toLowerCase()+e.slice(6)}return r[i$][i]}else if(e.startsWith("label")){switch(e){case"labelColor":i="fill";break;case"labelFont":case"labelFontSize":i=e[5].toLowerCase()+e.slice(6)}return r[I0][i]}return null}function c6(e){const t={};for(const n of e)if(n)for(const r in n)t[r]=1;return Object.keys(t)}function i0e(e,t){var n=t.config,r=n.style,i=n.axis,s=t.scaleType(e.scale)==="band"&&n.axisBand,a=e.orient,o,l,u;if(sr(a)){const f=c6([n.axisX,n.axisY]),d=c6([n.axisTop,n.axisBottom,n.axisLeft,n.axisRight]);o={};for(u of f)o[u]=br(a,zf(u,n.axisX,i,r),zf(u,n.axisY,i,r));l={};for(u of d)l[u]=n0e(a.signal,zf(u,n.axisTop,i,r),zf(u,n.axisBottom,i,r),zf(u,n.axisLeft,i,r),zf(u,n.axisRight,i,r))}else o=a===xa||a===du?n.axisX:n.axisY,l=n["axis"+a[0].toUpperCase()+a.slice(1)];return o||l||s?Tt({},i,o,l,s):i}function s0e(e,t,n,r){const i=Hi(e,t),s=e.orient;let a,o;const l={enter:a={opacity:Kt},update:o={opacity:Ms},exit:{opacity:Kt}};Pr(l,{stroke:i("domainColor"),strokeCap:i("domainCap"),strokeDash:i("domainDash"),strokeDashOffset:i("domainDashOffset"),strokeWidth:i("domainWidth"),strokeOpacity:i("domainOpacity")});const u=f6(e,0),c=f6(e,1);return a.x=o.x=br(s,u,Kt),a.x2=o.x2=br(s,c),a.y=o.y=la(s,u,Kt),a.y2=o.y2=la(s,c),ds({type:a$,role:$he,from:r,encode:l},n)}function f6(e,t){return{scale:e.scale,range:t}}function a0e(e,t,n,r,i){const s=Hi(e,t),a=e.orient,o=e.gridScale,l=Zb(a,1,-1),u=o0e(e.offset,l);let c,f,d;const h={enter:c={opacity:Kt},update:d={opacity:Ms},exit:f={opacity:Kt}};Pr(h,{stroke:s("gridColor"),strokeCap:s("gridCap"),strokeDash:s("gridDash"),strokeDashOffset:s("gridDashOffset"),strokeOpacity:s("gridOpacity"),strokeWidth:s("gridWidth")});const p={scale:e.scale,field:Ds,band:i.band,extra:i.extra,offset:i.offset,round:s("tickRound")},g=br(a,{signal:"height"},{signal:"width"}),v=o?{scale:o,range:0,mult:l,offset:u}:{value:0,offset:u},y=o?{scale:o,range:1,mult:l,offset:u}:Tt(g,{mult:l,offset:u});return c.x=d.x=br(a,p,v),c.y=d.y=la(a,p,v),c.x2=d.x2=la(a,y),c.y2=d.y2=br(a,y),f.x=br(a,p),f.y=la(a,p),ds({type:a$,role:Fhe,key:Ds,from:r,encode:h},n)}function o0e(e,t){if(t!==1)if(!Ue(e))e=sr(t)?{signal:`(${t.signal}) * (${e||0})`}:t*(e||0);else{let n=e=Tt({},e);for(;n.mult!=null;)if(Ue(n.mult))n=n.mult=Tt({},n.mult);else return n.mult=sr(t)?{signal:`(${n.mult}) * (${t.signal})`}:n.mult*t,e;n.mult=t}return e}function l0e(e,t,n,r,i,s){const a=Hi(e,t),o=e.orient,l=Zb(o,-1,1);let u,c,f;const d={enter:u={opacity:Kt},update:f={opacity:Ms},exit:c={opacity:Kt}};Pr(d,{stroke:a("tickColor"),strokeCap:a("tickCap"),strokeDash:a("tickDash"),strokeDashOffset:a("tickDashOffset"),strokeOpacity:a("tickOpacity"),strokeWidth:a("tickWidth")});const h=yr(i);h.mult=l;const p={scale:e.scale,field:Ds,band:s.band,extra:s.extra,offset:s.offset,round:a("tickRound")};return f.y=u.y=br(o,Kt,p),f.y2=u.y2=br(o,h),c.x=br(o,p),f.x=u.x=la(o,Kt,p),f.x2=u.x2=la(o,h),c.y=la(o,p),ds({type:a$,role:Mhe,key:Ds,from:r,encode:d},n)}function _x(e,t,n,r,i){return{signal:'flush(range("'+e+'"), scale("'+e+'", datum.value), '+t+","+n+","+r+","+i+")"}}function u0e(e,t,n,r,i,s){const a=Hi(e,t),o=e.orient,l=e.scale,u=Zb(o,-1,1),c=Sc(a("labelFlush")),f=Sc(a("labelFlushOffset")),d=a("labelAlign"),h=a("labelBaseline");let p=c===0||!!c,g;const v=yr(i);v.mult=u,v.offset=yr(a("labelPadding")||0),v.offset.mult=u;const y={scale:l,field:Ds,band:.5,offset:YB(s.offset,a("labelOffset"))},b=br(o,p?_x(l,c,'"left"','"right"','"center"'):{value:"center"},Kge(o,"left","right")),_=br(o,QB(o,"bottom","top"),p?_x(l,c,'"top"','"bottom"','"middle"'):{value:"middle"}),x=_x(l,c,`-(${f})`,f,0);p=p&&f;const w={opacity:Kt,x:br(o,y,v),y:la(o,y,v)},A={enter:w,update:g={opacity:Ms,text:{field:r$},x:w.x,y:w.y,align:b,baseline:_},exit:{opacity:Kt,x:w.x,y:w.y}};Pr(A,{dx:!d&&p?br(o,x):null,dy:!h&&p?la(o,x):null}),Pr(A,{angle:a("labelAngle"),fill:a("labelColor"),fillOpacity:a("labelOpacity"),font:a("labelFont"),fontSize:a("labelFontSize"),fontWeight:a("labelFontWeight"),fontStyle:a("labelFontStyle"),limit:a("labelLimit"),lineHeight:a("labelLineHeight")},{align:d,baseline:h});const E=a("labelBound");let k=a("labelOverlap");return k=k||E?{separation:a("labelSeparation"),method:k,order:"datum.index",bound:E?{scale:l,orient:o,tolerance:E}:null}:void 0,g.align!==b&&(g.align=ud(g.align,b)),g.baseline!==_&&(g.baseline=ud(g.baseline,_)),ds({type:_f,role:Dhe,style:I0,key:Ds,from:r,encode:A,overlap:k},n)}function c0e(e,t,n,r){const i=Hi(e,t),s=e.orient,a=Zb(s,-1,1);let o,l;const u={enter:o={opacity:Kt,anchor:yr(i("titleAnchor",null)),align:{signal:o$}},update:l=Tt({},o,{opacity:Ms,text:yr(e.title)}),exit:{opacity:Kt}},c={signal:`lerp(range("${e.scale}"), ${Vb(0,1,.5)})`};return l.x=br(s,c),l.y=la(s,c),o.angle=br(s,Kt,r0e(a,90)),o.baseline=br(s,QB(s,du,xa),{value:du}),l.angle=o.angle,l.baseline=o.baseline,Pr(u,{fill:i("titleColor"),fillOpacity:i("titleOpacity"),font:i("titleFont"),fontSize:i("titleFontSize"),fontStyle:i("titleFontStyle"),fontWeight:i("titleFontWeight"),limit:i("titleLimit"),lineHeight:i("titleLineHeight")},{align:i("titleAlign"),angle:i("titleAngle"),baseline:i("titleBaseline")}),f0e(i,s,u,n),u.update.align=ud(u.update.align,o.align),u.update.angle=ud(u.update.angle,o.angle),u.update.baseline=ud(u.update.baseline,o.baseline),ds({type:_f,role:The,style:i$,from:r,encode:u},n)}function f0e(e,t,n,r){const i=(o,l)=>o!=null?(n.update[l]=ud(yr(o),n.update[l]),!1):!Vf(l,r),s=i(e("titleX"),"x"),a=i(e("titleY"),"y");n.enter.auto=a===s?yr(a):br(t,yr(a),yr(s))}function d0e(e,t){const n=i0e(e,t),r=e.encode||{},i=r.axis||{},s=i.name||void 0,a=i.interactive,o=i.style,l=Hi(e,n),u=lge(l),c={scale:e.scale,ticks:!!l("ticks"),labels:!!l("labels"),grid:!!l("grid"),domain:!!l("domain"),title:e.title!=null},f=ft(t.add(_a({},[c]))),d=ft(t.add(hpe({scale:t.scaleRef(e.scale),extra:t.property(u.extra),count:t.objectProperty(e.tickCount),values:t.objectProperty(e.values),minstep:t.property(e.tickMinStep),formatType:t.property(e.formatType),formatSpecifier:t.property(e.format)}))),h=[];let p;return c.grid&&h.push(a0e(e,n,r.grid,d,u)),c.ticks&&(p=l("tickSize"),h.push(l0e(e,n,r.ticks,d,p,u))),c.labels&&(p=c.ticks?p:0,h.push(u0e(e,n,r.labels,d,p,u))),c.domain&&h.push(s0e(e,n,r.domain,f)),c.title&&h.push(c0e(e,n,r.title,f)),Kb(Bg({role:Che,from:f,encode:Th(h0e(l,e),i,P0),marks:h,aria:l("aria"),description:l("description"),zindex:l("zindex"),name:s,interactive:a,style:o}),t)}function h0e(e,t){const n={enter:{},update:{}};return Pr(n,{orient:e("orient"),offset:e("offset")||0,position:Js(t.position,0),titlePadding:e("titlePadding"),minExtent:e("minExtent"),maxExtent:e("maxExtent"),range:{signal:`abs(span(range("${t.scale}")))`},translate:e("translate"),format:t.format,formatType:t.formatType}),n}function tz(e,t,n){const r=He(e.signals),i=He(e.scales);return n||r.forEach(s=>RB(s,t)),He(e.projections).forEach(s=>Hpe(s,t)),i.forEach(s=>Rpe(s,t)),He(e.data).forEach(s=>Vge(s,t)),i.forEach(s=>Npe(s,t)),(n||r).forEach(s=>dpe(s,t)),He(e.axes).forEach(s=>d0e(s,t)),He(e.marks).forEach(s=>Kb(s,t)),He(e.legends).forEach(s=>Lge(s,t)),e.title&&qge(e.title,t),t.parseLambdas(),t}const p0e=e=>Th({enter:{x:{value:0},y:{value:0}},update:{width:{signal:"width"},height:{signal:"height"}}},e);function g0e(e,t){const n=t.config,r=ft(t.root=t.add(ly())),i=m0e(e,n);i.forEach(u=>RB(u,t)),t.description=e.description||n.description,t.eventConfig=n.events,t.legends=t.objectProperty(n.legend&&n.legend.layout),t.locale=n.locale;const s=t.add(_a()),a=t.add(LB(TB(p0e(e.encode),Yb,QC,e.style,t,{pulse:ft(s)}))),o=t.add(BB({layout:t.objectProperty(e.layout),legends:t.legends,autosize:t.signalRef("autosize"),mark:r,pulse:ft(a)}));t.operators.pop(),t.pushState(ft(a),ft(o),null),tz(e,t,i),t.operators.push(o);let l=t.add(OB({mark:r,pulse:ft(o)}));return l=t.add(PB({pulse:ft(l)})),l=t.add(bf({pulse:ft(l)})),t.addData("root",new Zc(t,s,s,l)),t}function pp(e,t){return t&&t.signal?{name:e,update:t.signal}:{name:e,value:t}}function m0e(e,t){const n=a=>Js(e[a],t[a]),r=[pp("background",n("background")),pp("autosize",Ahe(n("autosize"))),pp("padding",She(n("padding"))),pp("width",n("width")||0),pp("height",n("height")||0)],i=r.reduce((a,o)=>(a[o.name]=o,a),{}),s={};return He(e.signals).forEach(a=>{Ve(i,a.name)?a=Tt(i[a.name],a):r.push(a),s[a.name]=a}),He(t.signals).forEach(a=>{!Ve(s,a.name)&&!Ve(i,a.name)&&r.push(a)}),r}function nz(e,t){this.config=e||{},this.options=t||{},this.bindings=[],this.field={},this.signals={},this.lambdas={},this.scales={},this.events={},this.data={},this.streams=[],this.updates=[],this.operators=[],this.eventConfig=null,this.locale=null,this._id=0,this._subid=0,this._nextsub=[0],this._parent=[],this._encode=[],this._lookup=[],this._markpath=[]}function d6(e){this.config=e.config,this.options=e.options,this.legends=e.legends,this.field=Object.create(e.field),this.signals=Object.create(e.signals),this.lambdas=Object.create(e.lambdas),this.scales=Object.create(e.scales),this.events=Object.create(e.events),this.data=Object.create(e.data),this.streams=[],this.updates=[],this.operators=[],this._id=0,this._subid=++e._nextsub[0],this._nextsub=e._nextsub,this._parent=e._parent.slice(),this._encode=e._encode.slice(),this._lookup=e._lookup.slice(),this._markpath=e._markpath}nz.prototype=d6.prototype={parse(e){return tz(e,this)},fork(){return new d6(this)},isSubscope(){return this._subid>0},toRuntime(){return this.finish(),{description:this.description,operators:this.operators,streams:this.streams,updates:this.updates,bindings:this.bindings,eventConfig:this.eventConfig,locale:this.locale}},id(){return(this._subid?this._subid+":":0)+this._id++},add(e){return this.operators.push(e),e.id=this.id(),e.refs&&(e.refs.forEach(t=>{t.$ref=e.id}),e.refs=null),e},proxy(e){const t=e instanceof lA?ft(e):e;return this.add(Cpe({value:t}))},addStream(e){return this.streams.push(e),e.id=this.id(),e},addUpdate(e){return this.updates.push(e),e},finish(){let e,t;this.root&&(this.root.root=!0);for(e in this.signals)this.signals[e].signal=e;for(e in this.scales)this.scales[e].scale=e;function n(r,i,s){let a,o;r&&(a=r.data||(r.data={}),o=a[i]||(a[i]=[]),o.push(s))}for(e in this.data){t=this.data[e],n(t.input,e,"input"),n(t.output,e,"output"),n(t.values,e,"values");for(const r in t.index)n(t.index[r],e,"index:"+r)}return this},pushState(e,t,n){this._encode.push(ft(this.add(bf({pulse:e})))),this._parent.push(t),this._lookup.push(n?ft(this.proxy(n)):null),this._markpath.push(-1)},popState(){this._encode.pop(),this._parent.pop(),this._lookup.pop(),this._markpath.pop()},parent(){return Xt(this._parent)},encode(){return Xt(this._encode)},lookup(){return Xt(this._lookup)},markpath(){const e=this._markpath;return++e[e.length-1]},fieldRef(e,t){if(We(e))return Ig(e,t);e.signal||ye("Unsupported field reference: "+Pe(e));const n=e.signal;let r=this.field[n];if(!r){const i={name:this.signalRef(n)};t&&(i.as=t),this.field[n]=r=ft(this.add(vpe(i)))}return r},compareRef(e){let t=!1;const n=s=>sr(s)?(t=!0,this.signalRef(s.signal)):npe(s)?(t=!0,this.exprRef(s.expr)):s,r=He(e.field).map(n),i=He(e.order).map(n);return t?ft(this.add(JM({fields:r,orders:i}))):KM(r,i)},keyRef(e,t){let n=!1;const r=s=>sr(s)?(n=!0,ft(i[s.signal])):s,i=this.signals;return e=He(e).map(r),n?ft(this.add(ype({fields:e,flat:t}))):Jhe(e,t)},sortRef(e){if(!e)return e;const t=Hb(e.op,e.field),n=e.order||Qhe;return n.signal?ft(this.add(JM({fields:t,orders:this.signalRef(n.signal)}))):KM(t,n)},event(e,t){const n=e+":"+t;if(!this.events[n]){const r=this.id();this.streams.push({id:r,source:e,type:t}),this.events[n]=r}return this.events[n]},hasOwnSignal(e){return Ve(this.signals,e)},addSignal(e,t){this.hasOwnSignal(e)&&ye("Duplicate signal name: "+Pe(e));const n=t instanceof lA?t:this.add(ly(t));return this.signals[e]=n},getSignal(e){return this.signals[e]||ye("Unrecognized signal name: "+Pe(e)),this.signals[e]},signalRef(e){return this.signals[e]?ft(this.signals[e]):(Ve(this.lambdas,e)||(this.lambdas[e]=this.add(ly(null))),ft(this.lambdas[e]))},parseLambdas(){const e=Object.keys(this.lambdas);for(let t=0,n=e.length;t0?",":"")+(Ue(i)?i.signal||d$(i):Pe(i))}return n+"]"}function y0e(e){let t="{",n=0,r,i;for(r in e)i=e[r],t+=(++n>1?",":"")+Pe(r)+":"+(Ue(i)?i.signal||d$(i):Pe(i));return t+"}"}function b0e(){const e="sans-serif",r="#4c78a8",i="#000",s="#888",a="#ddd";return{description:"Vega visualization",padding:0,autosize:"pad",background:null,events:{defaults:{allow:["wheel"]}},group:null,mark:null,arc:{fill:r},area:{fill:r},image:null,line:{stroke:r,strokeWidth:2},path:{stroke:r},rect:{fill:r},rule:{stroke:i},shape:{stroke:r},symbol:{fill:r,size:64},text:{fill:i,font:e,fontSize:11},trail:{fill:r,size:2},style:{"guide-label":{fill:i,font:e,fontSize:10},"guide-title":{fill:i,font:e,fontSize:11,fontWeight:"bold"},"group-title":{fill:i,font:e,fontSize:13,fontWeight:"bold"},"group-subtitle":{fill:i,font:e,fontSize:12},point:{size:30,strokeWidth:2,shape:"circle"},circle:{size:30,strokeWidth:2},square:{size:30,strokeWidth:2,shape:"square"},cell:{fill:"transparent",stroke:a},view:{fill:"transparent"}},title:{orient:"top",anchor:"middle",offset:4,subtitlePadding:3},axis:{minExtent:0,maxExtent:200,bandPosition:.5,domain:!0,domainWidth:1,domainColor:s,grid:!1,gridWidth:1,gridColor:a,labels:!0,labelAngle:0,labelLimit:180,labelOffset:0,labelPadding:2,ticks:!0,tickColor:s,tickOffset:0,tickRound:!0,tickSize:5,tickWidth:1,titlePadding:4},axisBand:{tickOffset:-.5},projection:{type:"mercator"},legend:{orient:"right",padding:0,gridAlign:"each",columnPadding:10,rowPadding:2,symbolDirection:"vertical",gradientDirection:"vertical",gradientLength:200,gradientThickness:16,gradientStrokeColor:a,gradientStrokeWidth:0,gradientLabelOffset:2,labelAlign:"left",labelBaseline:"middle",labelLimit:160,labelOffset:4,labelOverlap:!0,symbolLimit:30,symbolType:"circle",symbolSize:100,symbolOffset:0,symbolStrokeWidth:1.5,symbolBaseFillColor:"transparent",symbolBaseStrokeColor:s,titleLimit:180,titleOrient:"top",titlePadding:5,layout:{offset:18,direction:"horizontal",left:{direction:"vertical"},right:{direction:"vertical"}}},range:{category:{scheme:"tableau10"},ordinal:{scheme:"blues"},heatmap:{scheme:"yellowgreenblue"},ramp:{scheme:"blues"},diverging:{scheme:"blueorange",extent:[1,0]},symbol:["circle","square","triangle-up","cross","diamond","triangle-right","triangle-down","triangle-left"]}}}function _0e(e,t,n){return Ue(e)||ye("Input Vega specification must be an object."),t=yh(b0e(),t,e.config),g0e(e,new nz(t,n)).toRuntime()}var x0e="5.33.1";Tt(Id,cJ,zre,yie,rae,Zae,Ale,rle,Sle,Kle,aue,hue);const w0e=Object.freeze(Object.defineProperty({__proto__:null,Bounds:Qn,CanvasHandler:$0,CanvasRenderer:wv,DATE:Bi,DAY:Hr,DAYOFYEAR:oo,Dataflow:sd,Debug:ZR,DisallowedObjectProperties:Ek,Error:Ak,EventStream:Zy,Gradient:q9,GroupItem:_b,HOURS:us,Handler:L3,HybridHandler:NL,HybridRenderer:mE,Info:KR,Item:bb,MILLISECONDS:ha,MINUTES:cs,MONTH:Xr,Marks:fs,MultiPulse:Kk,None:XR,Operator:gn,Parameters:Ky,Pulse:Zl,QUARTER:Pi,RenderType:zl,Renderer:C0,ResourceLoader:K9,SECONDS:Os,SVGHandler:xL,SVGRenderer:U3,SVGStringRenderer:RL,Scenegraph:hL,TIME_UNITS:zk,Transform:de,View:_B,WEEK:rr,Warn:kk,YEAR:Or,accessor:Wi,accessorFields:Vr,accessorName:zn,array:He,ascending:_h,bandwidthNRD:eS,bin:DO,bootstrapCI:MO,boundClip:WL,boundContext:E0,boundItem:fE,boundMark:uL,boundStroke:hl,changeset:wu,clampRange:lN,codegenExpression:YP,compare:Dk,constant:ti,cumulativeLogNormal:aS,cumulativeNormal:Qy,cumulativeUniform:cS,dayofyear:IN,debounce:Mk,defaultLocale:Hk,definition:CO,densityLogNormal:sS,densityNormal:tS,densityUniform:uS,domChild:nr,domClear:xs,domCreate:Pl,domFind:O3,dotbin:TO,error:ye,expressionFunction:Kn,extend:Tt,extent:io,extentIndex:uN,falsy:kl,fastmap:xh,field:Ns,flush:cN,font:kb,fontFamily:S0,fontSize:yo,format:f1,formatLocale:ev,formats:Vk,hasOwnProperty:Ve,id:l0,identity:ei,inferType:mO,inferTypes:vO,ingest:nn,inherits:Be,inrange:Zf,interpolate:d3,interpolateColors:vb,interpolateRange:F9,intersect:zL,intersectBoxLine:Jf,intersectPath:_3,intersectPoint:x3,intersectRule:J9,isArray:Se,isBoolean:xu,isDate:Xl,isFunction:Rt,isIterable:fN,isNumber:Qt,isObject:Ue,isRegExp:Tk,isString:We,isTuple:Vy,key:Rk,lerp:dN,lineHeight:uu,loader:Gy,locale:pO,logger:Sk,lruCache:hN,markup:j3,merge:pN,mergeConfig:yh,multiLineOffset:T3,one:vh,pad:gN,panLinear:nN,panLog:rN,panPow:iN,panSymlog:sN,parse:_0e,parseExpression:WP,parseSelector:$u,path:ib,pathCurves:v3,pathEqual:HL,pathParse:qd,pathRectangle:G9,pathRender:kg,pathSymbols:H9,pathTrail:Y9,peek:Xt,point:Cb,projection:oC,quantileLogNormal:oS,quantileNormal:eb,quantileUniform:fS,quantiles:Jk,quantizeInterpolator:D9,quarter:aN,quartiles:Qk,get random(){return Ls},randomInteger:pZ,randomKDE:rS,randomLCG:hZ,randomLogNormal:NO,randomMixture:OO,randomNormal:nS,randomUniform:LO,read:_O,regressionConstant:dS,regressionExp:PO,regressionLinear:hS,regressionLoess:jO,regressionLog:IO,regressionPoly:zO,regressionPow:BO,regressionQuad:pS,renderModule:$b,repeat:wp,resetDefaultLocale:cK,resetSVGClipId:X9,resetSVGDefIds:ire,responseType:bO,runtimeContext:oB,sampleCurve:nb,sampleLogNormal:iS,sampleNormal:Jy,sampleUniform:lS,scale:tn,sceneEqual:q3,sceneFromJSON:fL,scenePickVisit:pv,sceneToJSON:cL,sceneVisit:pa,sceneZOrder:w3,scheme:h3,serializeXML:FL,setHybridRendererOptions:ere,setRandom:fZ,span:u0,splitAccessPath:go,stringValue:Pe,textMetrics:ss,timeBin:eO,timeFloor:WN,timeFormatLocale:bg,timeInterval:kh,timeOffset:YN,timeSequence:KN,timeUnitSpecifier:LN,timeUnits:jk,toBoolean:Nk,toDate:Ok,toNumber:Gr,toSet:da,toString:Lk,transform:$O,transforms:Id,truncate:mN,truthy:ls,tupleid:dt,typeParsers:Yw,utcFloor:HN,utcInterval:Sh,utcOffset:VN,utcSequence:ZN,utcdayofyear:zN,utcquarter:oN,utcweek:jN,version:x0e,visitArray:$l,week:PN,writeConfig:bh,zero:Rl,zoomLinear:Ck,zoomLog:$k,zoomPow:Y1,zoomSymlog:Fk},Symbol.toStringTag,{value:"Module"}));function E0e(e,t,n){let r;t.x2&&(t.x?(n&&e.x>e.x2&&(r=e.x,e.x=e.x2,e.x2=r),e.width=e.x2-e.x):e.x=e.x2-(e.width||0)),t.xc&&(e.x=e.xc-(e.width||0)/2),t.y2&&(t.y?(n&&e.y>e.y2&&(r=e.y,e.y=e.y2,e.y2=r),e.height=e.y2-e.y):e.y=e.y2-(e.height||0)),t.yc&&(e.y=e.yc-(e.height||0)/2)}var A0e={NaN:NaN,E:Math.E,LN2:Math.LN2,LN10:Math.LN10,LOG2E:Math.LOG2E,LOG10E:Math.LOG10E,PI:Math.PI,SQRT1_2:Math.SQRT1_2,SQRT2:Math.SQRT2,MIN_VALUE:Number.MIN_VALUE,MAX_VALUE:Number.MAX_VALUE},k0e={"*":(e,t)=>e*t,"+":(e,t)=>e+t,"-":(e,t)=>e-t,"/":(e,t)=>e/t,"%":(e,t)=>e%t,">":(e,t)=>e>t,"<":(e,t)=>ee<=t,">=":(e,t)=>e>=t,"==":(e,t)=>e==t,"!=":(e,t)=>e!=t,"===":(e,t)=>e===t,"!==":(e,t)=>e!==t,"&":(e,t)=>e&t,"|":(e,t)=>e|t,"^":(e,t)=>e^t,"<<":(e,t)=>e<>":(e,t)=>e>>t,">>>":(e,t)=>e>>>t},S0e={"+":e=>+e,"-":e=>-e,"~":e=>~e,"!":e=>!e};const C0e=Array.prototype.slice,Gu=(e,t,n)=>{const r=n?n(t[0]):t[0];return r[e].apply(r,C0e.call(t,1))},$0e=(e,t,n,r,i,s,a)=>new Date(e,t||0,n??1,r||0,i||0,s||0,a||0);var F0e={isNaN:Number.isNaN,isFinite:Number.isFinite,abs:Math.abs,acos:Math.acos,asin:Math.asin,atan:Math.atan,atan2:Math.atan2,ceil:Math.ceil,cos:Math.cos,exp:Math.exp,floor:Math.floor,log:Math.log,max:Math.max,min:Math.min,pow:Math.pow,random:Math.random,round:Math.round,sin:Math.sin,sqrt:Math.sqrt,tan:Math.tan,clamp:(e,t,n)=>Math.max(t,Math.min(n,e)),now:Date.now,utc:Date.UTC,datetime:$0e,date:e=>new Date(e).getDate(),day:e=>new Date(e).getDay(),year:e=>new Date(e).getFullYear(),month:e=>new Date(e).getMonth(),hours:e=>new Date(e).getHours(),minutes:e=>new Date(e).getMinutes(),seconds:e=>new Date(e).getSeconds(),milliseconds:e=>new Date(e).getMilliseconds(),time:e=>new Date(e).getTime(),timezoneoffset:e=>new Date(e).getTimezoneOffset(),utcdate:e=>new Date(e).getUTCDate(),utcday:e=>new Date(e).getUTCDay(),utcyear:e=>new Date(e).getUTCFullYear(),utcmonth:e=>new Date(e).getUTCMonth(),utchours:e=>new Date(e).getUTCHours(),utcminutes:e=>new Date(e).getUTCMinutes(),utcseconds:e=>new Date(e).getUTCSeconds(),utcmilliseconds:e=>new Date(e).getUTCMilliseconds(),length:e=>e.length,join:function(){return Gu("join",arguments)},indexof:function(){return Gu("indexOf",arguments)},lastindexof:function(){return Gu("lastIndexOf",arguments)},slice:function(){return Gu("slice",arguments)},reverse:e=>e.slice().reverse(),sort:e=>e.slice().sort(_h),parseFloat,parseInt,upper:e=>String(e).toUpperCase(),lower:e=>String(e).toLowerCase(),substring:function(){return Gu("substring",arguments,String)},split:function(){return Gu("split",arguments,String)},replace:function(){return Gu("replace",arguments,String)},trim:e=>String(e).trim(),btoa:e=>btoa(e),atob:e=>atob(e),regexp:RegExp,test:(e,t)=>RegExp(e).test(t)};const D0e=["view","item","group","xy","x","y"],gA=new Set([Function,eval,setTimeout,setInterval]);typeof setImmediate=="function"&&gA.add(setImmediate);const M0e={Literal:(e,t)=>t.value,Identifier:(e,t)=>{const n=t.name;return e.memberDepth>0?n:n==="datum"?e.datum:n==="event"?e.event:n==="item"?e.item:A0e[n]||e.params["$"+n]},MemberExpression:(e,t)=>{const n=!t.computed,r=e(t.object);n&&(e.memberDepth+=1);const i=e(t.property);if(n&&(e.memberDepth-=1),gA.has(r[i])){console.error(`Prevented interpretation of member "${i}" which could lead to insecure code execution`);return}return r[i]},CallExpression:(e,t)=>{const n=t.arguments;let r=t.callee.name;return r.startsWith("_")&&(r=r.slice(1)),r==="if"?e(n[0])?e(n[1]):e(n[2]):(e.fn[r]||F0e[r]).apply(e.fn,n.map(e))},ArrayExpression:(e,t)=>t.elements.map(e),BinaryExpression:(e,t)=>k0e[t.operator](e(t.left),e(t.right)),UnaryExpression:(e,t)=>S0e[t.operator](e(t.argument)),ConditionalExpression:(e,t)=>e(t.test)?e(t.consequent):e(t.alternate),LogicalExpression:(e,t)=>t.operator==="&&"?e(t.left)&&e(t.right):e(t.left)||e(t.right),ObjectExpression:(e,t)=>t.properties.reduce((n,r)=>{e.memberDepth+=1;const i=e(r.key);e.memberDepth-=1;const s=e(r.value);return Ek.has(i)?console.error(`Prevented interpretation of property "${i}" which could lead to insecure code execution`):gA.has(s)?console.error(`Prevented interpretation of method "${s}" which could lead to insecure code execution`):n[i]=s,n},{})};function gp(e,t,n,r,i,s){const a=o=>M0e[o.type](a,o);return a.memberDepth=0,a.fn=Object.create(t),a.params=n,a.datum=r,a.event=i,a.item=s,D0e.forEach(o=>a.fn[o]=function(){return i.vega[o](...arguments)}),a(e)}var T0e={operator(e,t){const n=t.ast,r=e.functions;return i=>gp(n,r,i)},parameter(e,t){const n=t.ast,r=e.functions;return(i,s)=>gp(n,r,s,i)},event(e,t){const n=t.ast,r=e.functions;return i=>gp(n,r,void 0,void 0,i)},handler(e,t){const n=t.ast,r=e.functions;return(i,s)=>{const a=s.item&&s.item.datum;return gp(n,r,i,a,s)}},encode(e,t){const{marktype:n,channels:r}=t,i=e.functions,s=n==="group"||n==="image"||n==="rect";return(a,o)=>{const l=a.datum;let u=0,c;for(const f in r)c=gp(r[f].ast,i,o,l,void 0,a),a[f]!==c&&(a[f]=c,u=1);return n!=="rule"&&E0e(a,r,s),u}}};const R0e="5.23.0",N0e={version:R0e};function h$(e){return De(e,"or")}function p$(e){return De(e,"and")}function g$(e){return De(e,"not")}function O1(e,t){if(g$(e))O1(e.not,t);else if(p$(e))for(const n of e.and)O1(n,t);else if(h$(e))for(const n of e.or)O1(n,t);else t(e)}function cd(e,t){return g$(e)?{not:cd(e.not,t)}:p$(e)?{and:e.and.map(n=>cd(n,t))}:h$(e)?{or:e.or.map(n=>cd(n,t))}:t(e)}const Ct=structuredClone;function rz(e){throw new Error(e)}function Jd(e,t){const n={};for(const r of t)Ve(e,r)&&(n[r]=e[r]);return n}function Li(e,t){const n={...e};for(const r of t)delete n[r];return n}Set.prototype.toJSON=function(){return`Set(${[...this].map(e=>hn(e)).join(",")})`};function Gt(e){if(Qt(e))return e;const t=We(e)?e:hn(e);if(t.length<250)return t;let n=0;for(let r=0;ro===0?a:`[${a}]`),s=i.map((a,o)=>i.slice(0,o+1).join(""));for(const a of s)t.add(a)}return t}function y$(e,t){return e===void 0||t===void 0?!0:v$(vA(e),vA(t))}function dn(e){return Fe(e).length===0}const Fe=Object.keys,Lr=Object.values,hu=Object.entries;function zg(e){return e===!0||e===!1}function Cn(e){const t=e.replace(/\W/g,"_");return(e.match(/^\d+/)?"_":"")+t}function ug(e,t){return g$(e)?`!(${ug(e.not,t)})`:p$(e)?`(${e.and.map(n=>ug(n,t)).join(") && (")})`:h$(e)?`(${e.or.map(n=>ug(n,t)).join(") || (")})`:t(e)}function uy(e,t){if(t.length===0)return!0;const n=t.shift();return n in e&&uy(e[n],t)&&delete e[n],dn(e)}function B0(e){return e.charAt(0).toUpperCase()+e.substr(1)}function b$(e,t="datum"){const n=go(e),r=[];for(let i=1;i<=n.length;i++){const s=`[${n.slice(0,i).map(Pe).join("][")}]`;r.push(`${t}${s}`)}return r.join(" && ")}function az(e,t="datum"){return`${t}[${Pe(go(e).join("."))}]`}function sn(e){return`datum['${e.replaceAll("'","\\'")}']`}function I0e(e){return e.replace(/(\[|\]|\.|'|")/g,"\\$1")}function Ps(e){return`${go(e).map(I0e).join("\\.")}`}function Jc(e,t,n){return e.replace(new RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"g"),n)}function Oh(e){return`${go(e).join(".")}`}function eh(e){return e?go(e).length:0}function Vn(...e){return e.find(t=>t!==void 0)}let oz=42;function lz(e){const t=++oz;return e?String(e)+t:t}function P0e(){oz=42}function uz(e){return cz(e)?e:`__${e}`}function cz(e){return e.startsWith("__")}function jg(e){if(e!==void 0)return(e%360+360)%360}function Jb(e){return Qt(e)?!0:!isNaN(e)&&!isNaN(parseFloat(e))}const h6=Object.getPrototypeOf(structuredClone({}));function ns(e,t){if(e===t)return!0;if(e&&t&&typeof e=="object"&&typeof t=="object"){if(e.constructor.name!==t.constructor.name)return!1;let n,r;if(Array.isArray(e)){if(n=e.length,n!=t.length)return!1;for(r=n;r--!==0;)if(!ns(e[r],t[r]))return!1;return!0}if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const s of e.entries())if(!t.has(s[0]))return!1;for(const s of e.entries())if(!ns(s[1],t.get(s[0])))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const s of e.entries())if(!t.has(s[0]))return!1;return!0}if(ArrayBuffer.isView(e)&&ArrayBuffer.isView(t)){if(n=e.length,n!=t.length)return!1;for(r=n;r--!==0;)if(e[r]!==t[r])return!1;return!0}if(e.constructor===RegExp)return e.source===t.source&&e.flags===t.flags;if(e.valueOf!==Object.prototype.valueOf&&e.valueOf!==h6.valueOf)return e.valueOf()===t.valueOf();if(e.toString!==Object.prototype.toString&&e.toString!==h6.toString)return e.toString()===t.toString();const i=Object.keys(e);if(n=i.length,n!==Object.keys(t).length)return!1;for(r=n;r--!==0;)if(!Object.prototype.hasOwnProperty.call(t,i[r]))return!1;for(r=n;r--!==0;){const s=i[r];if(!ns(e[s],t[s]))return!1}return!0}return e!==e&&t!==t}function hn(e){const t=[];return(function n(r){if(r&&r.toJSON&&typeof r.toJSON=="function"&&(r=r.toJSON()),r===void 0)return;if(typeof r=="number")return isFinite(r)?""+r:"null";if(typeof r!="object")return JSON.stringify(r);let i,s;if(Array.isArray(r)){for(s="[",i=0;ia2(e[t])?Cn(`_${t}_${hu(e[t])}`):Cn(`_${t}_${e[t]}`)).join("")}function xn(e){return e===!0||Ef(e)&&!e.binned}function Cr(e){return e==="binned"||Ef(e)&&e.binned===!0}function Ef(e){return Ue(e)}function a2(e){return De(e,"param")}function p6(e){switch(e){case el:case tl:case vl:case ji:case Eo:case Ao:case Ru:case yl:case Mu:case Tu:case Ui:return 6;case Nu:return 4;default:return 10}}function q0(e){return De(e,"expr")}function Fr(e,{level:t}={level:0}){const n=Fe(e||{}),r={};for(const i of n)r[i]=t===0?Qi(e[i]):Fr(e[i],{level:t-1});return r}function Az(e){const{anchor:t,frame:n,offset:r,orient:i,angle:s,limit:a,color:o,subtitleColor:l,subtitleFont:u,subtitleFontSize:c,subtitleFontStyle:f,subtitleFontWeight:d,subtitleLineHeight:h,subtitlePadding:p,...g}=e,v={...g,...o?{fill:o}:{}},y={...t?{anchor:t}:{},...n?{frame:n}:{},...r?{offset:r}:{},...i?{orient:i}:{},...s!==void 0?{angle:s}:{},...a!==void 0?{limit:a}:{}},b={...l?{subtitleColor:l}:{},...u?{subtitleFont:u}:{},...c?{subtitleFontSize:c}:{},...f?{subtitleFontStyle:f}:{},...d?{subtitleFontWeight:d}:{},...h?{subtitleLineHeight:h}:{},...p?{subtitlePadding:p}:{}},_=Jd(e,["align","baseline","dx","dy","limit"]);return{titleMarkConfig:v,subtitleMarkConfig:_,nonMarkTitleProperties:y,subtitle:b}}function Tl(e){return We(e)||Se(e)&&We(e[0])}function ot(e){return De(e,"signal")}function Af(e){return De(e,"step")}function ume(e){return Se(e)?!1:De(e,"fields")&&!De(e,"data")}function cme(e){return Se(e)?!1:De(e,"fields")&&De(e,"data")}function Vo(e){return Se(e)?!1:De(e,"field")&&De(e,"data")}const fme={aria:1,description:1,ariaRole:1,ariaRoleDescription:1,blend:1,opacity:1,fill:1,fillOpacity:1,stroke:1,strokeCap:1,strokeWidth:1,strokeOpacity:1,strokeDash:1,strokeDashOffset:1,strokeJoin:1,strokeOffset:1,strokeMiterLimit:1,startAngle:1,endAngle:1,padAngle:1,innerRadius:1,outerRadius:1,size:1,shape:1,interpolate:1,tension:1,orient:1,align:1,baseline:1,text:1,dir:1,dx:1,dy:1,ellipsis:1,limit:1,radius:1,theta:1,angle:1,font:1,fontSize:1,fontWeight:1,fontStyle:1,lineBreak:1,lineHeight:1,cursor:1,href:1,tooltip:1,cornerRadius:1,cornerRadiusTopLeft:1,cornerRadiusTopRight:1,cornerRadiusBottomLeft:1,cornerRadiusBottomRight:1,aspect:1,width:1,height:1,url:1,smooth:1},dme=Fe(fme),hme={arc:1,area:1,group:1,image:1,line:1,path:1,rect:1,rule:1,shape:1,symbol:1,text:1,trail:1},yA=["cornerRadius","cornerRadiusTopLeft","cornerRadiusTopRight","cornerRadiusBottomLeft","cornerRadiusBottomRight"];function kz(e){const t=Se(e.condition)?e.condition.map(g6):g6(e.condition);return{...Qi(e),condition:t}}function Qi(e){if(q0(e)){const{expr:t,...n}=e;return{signal:t,...n}}return e}function g6(e){if(q0(e)){const{expr:t,...n}=e;return{signal:t,...n}}return e}function En(e){if(q0(e)){const{expr:t,...n}=e;return{signal:t,...n}}return ot(e)?e:e!==void 0?{value:e}:void 0}function pme(e){return ot(e)?e.signal:Pe(e)}function m6(e){return ot(e)?e.signal:Pe(e.value)}function aa(e){return ot(e)?e.signal:e==null?null:Pe(e)}function gme(e,t,n){for(const r of n){const i=co(r,t.markDef,t.config);i!==void 0&&(e[r]=En(i))}return e}function Sz(e){return[].concat(e.type,e.style??[])}function fn(e,t,n,r={}){const{vgChannel:i,ignoreVgConfig:s}=r;return i&&De(t,i)?t[i]:t[e]!==void 0?t[e]:s&&(!i||i===e)?void 0:co(e,t,n,r)}function co(e,t,n,{vgChannel:r}={}){const i=bA(e,t,n.style);return Vn(r?i:void 0,i,r?n[t.type][r]:void 0,n[t.type][e],r?n.mark[r]:n.mark[e])}function bA(e,t,n){return Cz(e,Sz(t),n)}function Cz(e,t,n){t=He(t);let r;for(const i of t){const s=n[i];De(s,e)&&(r=s[e])}return r}function $z(e,t){return He(e).reduce((n,r)=>(n.field.push(ze(r,t)),n.order.push(r.sort??"ascending"),n),{field:[],order:[]})}function Fz(e,t){const n=[...e];return t.forEach(r=>{for(const i of n)if(ns(i,r))return;n.push(r)}),n}function Dz(e,t){return ns(e,t)||!t?e:e?[...He(e),...He(t)].join(", "):t}function Mz(e,t){const n=e.value,r=t.value;if(n==null||r===null)return{explicit:e.explicit,value:null};if((Tl(n)||ot(n))&&(Tl(r)||ot(r)))return{explicit:e.explicit,value:Dz(n,r)};if(Tl(n)||ot(n))return{explicit:e.explicit,value:n};if(Tl(r)||ot(r))return{explicit:e.explicit,value:r};if(!Tl(n)&&!ot(n)&&!Tl(r)&&!ot(r))return{explicit:e.explicit,value:Fz(n,r)};throw new Error("It should never reach here")}function F$(e){return`Invalid specification ${hn(e)}. Make sure the specification includes at least one of the following properties: "mark", "layer", "facet", "hconcat", "vconcat", "concat", or "repeat".`}const mme='Autosize "fit" only works for single views and layered views.';function v6(e){return`${e=="width"?"Width":"Height"} "container" only works for single views and layered views.`}function y6(e){const t=e=="width"?"Width":"Height",n=e=="width"?"x":"y";return`${t} "container" only works well with autosize "fit" or "fit-${n}".`}function b6(e){return e?`Dropping "fit-${e}" because spec has discrete ${qi(e)}.`:'Dropping "fit" because spec has discrete size.'}function D$(e){return`Unknown field for ${e}. Cannot calculate view size.`}function _6(e){return`Cannot project a selection on encoding channel "${e}", which has no field.`}function vme(e,t){return`Cannot project a selection on encoding channel "${e}" as it uses an aggregate function ("${t}").`}function yme(e){return`The "nearest" transform is not supported for ${e} marks.`}function Tz(e){return`Selection not supported for ${e} yet.`}function bme(e){return`Cannot find a selection named "${e}".`}const _me="Scale bindings are currently only supported for scales with unbinned, continuous domains.",xme="Sequntial scales are deprecated. The available quantitative scale type values are linear, log, pow, sqrt, symlog, time and utc",wme="Legend bindings are only supported for selections over an individual field or encoding channel.";function Eme(e){return`Lookups can only be performed on selection parameters. "${e}" is a variable parameter.`}function Ame(e){return`Cannot define and lookup the "${e}" selection in the same view. Try moving the lookup into a second, layered view?`}const kme="The same selection must be used to override scale domains in a layered view.",Sme='Interval selections should be initialized using "x", "y", "longitude", or "latitude" keys.';function Cme(e){return`Unknown repeated value "${e}".`}function x6(e){return`The "columns" property cannot be used when "${e}" has nested row/column.`}const $me="Multiple timer selections in one unit spec are not supported. Ignoring all but the first.",M$="Animation involving facet, layer, or concat is currently unsupported.";function Fme(e){return`A "field" or "encoding" must be specified when using a selection as a scale domain. Using "field": ${Pe(e)}.`}function Dme(e,t,n,r){return(e.length?"Multiple ":"No ")+`matching ${Pe(t)} encoding found for selection ${Pe(n.param)}. Using "field": ${Pe(r)}.`}const Mme="Axes cannot be shared in concatenated or repeated views yet (https://github.com/vega/vega-lite/issues/2415).";function Tme(e){return`Unrecognized parse "${e}".`}function w6(e,t,n){return`An ancestor parsed field "${e}" as ${n} but a child wants to parse the field as ${t}.`}const Rme="Attempt to add the same child twice.";function Nme(e){return`Ignoring an invalid transform: ${hn(e)}.`}const Ome='If "from.fields" is not specified, "as" has to be a string that specifies the key to be used for the data from the secondary source.';function E6(e){return`Config.customFormatTypes is not true, thus custom format type and format for channel ${e} are dropped.`}function Lme(e){const{parentProjection:t,projection:n}=e;return`Layer's shared projection ${hn(t)} is overridden by a child projection ${hn(n)}.`}const Ime="Arc marks uses theta channel rather than angle, replacing angle with theta.";function Pme(e){return`${e}Offset dropped because ${e} is continuous`}function Bme(e,t,n){return`Channel ${e} is a ${t}. Converted to {value: ${hn(n)}}.`}function Rz(e){return`Invalid field type "${e}".`}function zme(e,t){return`Invalid field type "${e}" for aggregate: "${t}", using "quantitative" instead.`}function jme(e){return`Invalid aggregation operator "${e}".`}function Nz(e,t){const{fill:n,stroke:r}=t;return`Dropping color ${e} as the plot also has ${n&&r?"fill and stroke":n?"fill":"stroke"}.`}function Ume(e){return`Position range does not support relative band size for ${e}.`}function _A(e,t){return`Dropping ${hn(e)} from channel "${t}" since it does not contain any data field, datum, value, or signal.`}const qme="Line marks cannot encode size with a non-groupby field. You may want to use trail marks instead.";function o2(e,t,n){return`${e} dropped as it is incompatible with "${t}".`}function Wme(e){return`${e}-encoding is dropped as ${e} is not a valid encoding channel.`}function Hme(e){return`${e} encoding should be discrete (ordinal / nominal / binned).`}function Gme(e){return`${e} encoding should be discrete (ordinal / nominal / binned) or use a discretizing scale (e.g. threshold).`}function Yme(e){return`Facet encoding dropped as ${e.join(" and ")} ${e.length>1?"are":"is"} also specified.`}function Ex(e,t){return`Using discrete channel "${e}" to encode "${t}" field can be misleading as it does not encode ${t==="ordinal"?"order":"magnitude"}.`}function Vme(e){return`The ${e} for range marks cannot be an expression`}function Xme(e,t){return`Line mark is for continuous lines and thus cannot be used with ${e&&t?"x2 and y2":e?"x2":"y2"}. We will use the rule mark (line segments) instead.`}function Kme(e,t){return`Specified orient "${e}" overridden with "${t}".`}function Zme(e){return`Cannot use the scale property "${e}" with non-color channel.`}function Jme(e){return`Cannot use the relative band size with ${e} scale.`}function Qme(e){return`Using unaggregated domain with raw field has no effect (${hn(e)}).`}function e1e(e){return`Unaggregated domain not applicable for "${e}" since it produces values outside the origin domain of the source data.`}function t1e(e){return`Unaggregated domain is currently unsupported for log scale (${hn(e)}).`}function n1e(e){return`Cannot apply size to non-oriented mark "${e}".`}function r1e(e,t,n){return`Channel "${e}" does not work with "${t}" scale. We are using "${n}" scale instead.`}function i1e(e,t){return`FieldDef does not work with "${e}" scale. We are using "${t}" scale instead.`}function Oz(e,t,n){return`${n}-scale's "${t}" is dropped as it does not work with ${e} scale.`}function Lz(e){return`The step for "${e}" is dropped because the ${e==="width"?"x":"y"} is continuous.`}function s1e(e,t,n,r){return`Conflicting ${t.toString()} property "${e.toString()}" (${hn(n)} and ${hn(r)}). Using ${hn(n)}.`}function a1e(e,t,n,r){return`Conflicting ${t.toString()} property "${e.toString()}" (${hn(n)} and ${hn(r)}). Using the union of the two domains.`}function o1e(e){return`Setting the scale to be independent for "${e}" means we also have to set the guide (axis or legend) to be independent.`}function l1e(e){return`Dropping sort property ${hn(e)} as unioned domains only support boolean or op "count", "min", and "max".`}const A6="Domains that should be unioned has conflicting sort properties. Sort will be set to true.",u1e="Detected faceted independent scales that union domain of multiple fields from different data sources. We will use the first field. The result view size may be incorrect.",c1e="Detected faceted independent scales that union domain of the same fields from different source. We will assume that this is the same field from a different fork of the same data source. However, if this is not the case, the result view size may be incorrect.",f1e="Detected faceted independent scales that union domain of multiple fields from the same data source. We will use the first field. The result view size may be incorrect.";function d1e(e){return`Cannot stack "${e}" if there is already "${e}2".`}function h1e(e){return`Stack is applied to a non-linear scale (${e}).`}function p1e(e){return`Stacking is applied even though the aggregate function is non-summative ("${e}").`}function cy(e,t){return`Invalid ${e}: ${hn(t)}.`}function g1e(e){return`Dropping day from datetime ${hn(e)} as day cannot be combined with other units.`}function m1e(e,t){return`${t?"extent ":""}${t&&e?"and ":""}${e?"center ":""}${t&&e?"are ":"is "}not needed when data are aggregated.`}function v1e(e,t,n){return`${e} is not usually used with ${t} for ${n}.`}function y1e(e,t){return`Continuous axis should not have customized aggregation function ${e}; ${t} already agregates the axis.`}function k6(e){return`1D error band does not support ${e}.`}function Iz(e){return`Channel ${e} is required for "binned" bin.`}function b1e(e){return`Channel ${e} should not be used with "binned" bin.`}function _1e(e){return`Domain for ${e} is required for threshold scale.`}const Pz=Sk(kk);let ef=Pz;function x1e(e){return ef=e,ef}function w1e(){return ef=Pz,ef}function T$(...e){ef.error(...e)}function Te(...e){ef.warn(...e)}function E1e(...e){ef.debug(...e)}function kf(e){if(e&&Ue(e)){for(const t of N$)if(De(e,t))return!0}return!1}const Bz=["january","february","march","april","may","june","july","august","september","october","november","december"],A1e=Bz.map(e=>e.substr(0,3)),zz=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],k1e=zz.map(e=>e.substr(0,3));function S1e(e){if(Jb(e)&&(e=+e),Qt(e))return e>4&&Te(cy("quarter",e)),e-1;throw new Error(cy("quarter",e))}function C1e(e){if(Jb(e)&&(e=+e),Qt(e))return e-1;{const t=e.toLowerCase(),n=Bz.indexOf(t);if(n!==-1)return n;const r=t.substr(0,3),i=A1e.indexOf(r);if(i!==-1)return i;throw new Error(cy("month",e))}}function $1e(e){if(Jb(e)&&(e=+e),Qt(e))return e%7;{const t=e.toLowerCase(),n=zz.indexOf(t);if(n!==-1)return n;const r=t.substr(0,3),i=k1e.indexOf(r);if(i!==-1)return i;throw new Error(cy("day",e))}}function R$(e,t){const n=[];if(t&&e.day!==void 0&&Fe(e).length>1&&(Te(g1e(e)),e=Ct(e),delete e.day),e.year!==void 0?n.push(e.year):n.push(2012),e.month!==void 0){const r=t?C1e(e.month):e.month;n.push(r)}else if(e.quarter!==void 0){const r=t?S1e(e.quarter):e.quarter;n.push(Qt(r)?r*3:`${r}*3`)}else n.push(0);if(e.date!==void 0)n.push(e.date);else if(e.day!==void 0){const r=t?$1e(e.day):e.day;n.push(Qt(r)?r+1:`${r}+1`)}else n.push(1);for(const r of["hours","minutes","seconds","milliseconds"]){const i=e[r];n.push(typeof i>"u"?0:i)}return n}function tf(e){const n=R$(e,!0).join(", ");return e.utc?`utc(${n})`:`datetime(${n})`}function F1e(e){const n=R$(e,!1).join(", ");return e.utc?`utc(${n})`:`datetime(${n})`}function D1e(e){const t=R$(e,!0);return e.utc?+new Date(Date.UTC(...t)):+new Date(...t)}const jz={year:1,quarter:1,month:1,week:1,day:1,dayofyear:1,date:1,hours:1,minutes:1,seconds:1,milliseconds:1},N$=Fe(jz);function M1e(e){return Ve(jz,e)}function Sf(e){return Ue(e)?e.binned:Uz(e)}function Uz(e){return e&&e.startsWith("binned")}function O$(e){return e.startsWith("utc")}function T1e(e){return e.substring(3)}const R1e={"year-month":"%b %Y ","year-month-date":"%b %d, %Y "};function l2(e){return N$.filter(t=>Wz(e,t))}function qz(e){const t=l2(e);return t[t.length-1]}function Wz(e,t){const n=e.indexOf(t);return!(n<0||n>0&&t==="seconds"&&e.charAt(n-1)==="i"||e.length>n+3&&t==="day"&&e.charAt(n+3)==="o"||n>0&&t==="year"&&e.charAt(n-1)==="f")}function N1e(e,t,{end:n}={end:!1}){const r=b$(t),i=O$(e)?"utc":"";function s(l){return l==="quarter"?`(${i}quarter(${r})-1)`:`${i}${l}(${r})`}let a;const o={};for(const l of N$)Wz(e,l)&&(o[l]=s(l),a=l);return n&&(o[a]+="+1"),F1e(o)}function Hz(e){if(!e)return;const t=l2(e);return`timeUnitSpecifier(${hn(t)}, ${hn(R1e)})`}function O1e(e,t,n){if(!e)return;const r=Hz(e);return`${n||O$(e)?"utc":"time"}Format(${t}, ${r})`}function xr(e){if(!e)return;let t;return We(e)?Uz(e)?t={unit:e.substring(6),binned:!0}:t={unit:e}:Ue(e)&&(t={...e,...e.unit?{unit:e.unit}:{}}),O$(t.unit)&&(t.utc=!0,t.unit=T1e(t.unit)),t}function L1e(e){const{utc:t,...n}=xr(e);return n.unit?(t?"utc":"")+Fe(n).map(r=>Cn(`${r==="unit"?"":`_${r}_`}${n[r]}`)).join(""):(t?"utc":"")+"timeunit"+Fe(n).map(r=>Cn(`_${r}_${n[r]}`)).join("")}function Gz(e,t=n=>n){const n=xr(e),r=qz(n.unit);if(r&&r!=="day"){const i={year:2001,month:1,date:1,hours:0,minutes:0,seconds:0,milliseconds:0},{step:s,part:a}=Yz(r,n.step),o={...i,[a]:+i[a]+s};return`${t(tf(o))} - ${t(tf(i))}`}}const I1e={year:1,month:1,date:1,hours:1,minutes:1,seconds:1,milliseconds:1};function P1e(e){return Ve(I1e,e)}function Yz(e,t=1){if(P1e(e))return{part:e,step:t};switch(e){case"day":case"dayofyear":return{part:"date",step:t};case"quarter":return{part:"month",step:t*3};case"week":return{part:"date",step:t*7}}}function B1e(e){return De(e,"param")}function L$(e){return!!(e!=null&&e.field)&&e.equal!==void 0}function I$(e){return!!(e!=null&&e.field)&&e.lt!==void 0}function P$(e){return!!(e!=null&&e.field)&&e.lte!==void 0}function B$(e){return!!(e!=null&&e.field)&&e.gt!==void 0}function z$(e){return!!(e!=null&&e.field)&&e.gte!==void 0}function j$(e){if(e!=null&&e.field){if(Se(e.range)&&e.range.length===2)return!0;if(ot(e.range))return!0}return!1}function U$(e){return!!(e!=null&&e.field)&&(Se(e.oneOf)||Se(e.in))}function z1e(e){return!!(e!=null&&e.field)&&e.valid!==void 0}function Vz(e){return U$(e)||L$(e)||j$(e)||I$(e)||B$(e)||P$(e)||z$(e)}function Na(e,t){return y2(e,{timeUnit:t,wrapTime:!0})}function j1e(e,t){return e.map(n=>Na(n,t))}function Xz(e,t=!0){const{field:n}=e,r=xr(e.timeUnit),{unit:i,binned:s}=r||{},a=ze(e,{expr:"datum"}),o=i?`time(${s?a:N1e(i,n)})`:a;if(L$(e))return`${o}===${Na(e.equal,i)}`;if(I$(e)){const l=e.lt;return`${o}<${Na(l,i)}`}else if(B$(e)){const l=e.gt;return`${o}>${Na(l,i)}`}else if(P$(e)){const l=e.lte;return`${o}<=${Na(l,i)}`}else if(z$(e)){const l=e.gte;return`${o}>=${Na(l,i)}`}else{if(U$(e))return`indexof([${j1e(e.oneOf,i).join(",")}], ${o}) !== -1`;if(z1e(e))return u2(o,e.valid);if(j$(e)){const{range:l}=Fr(e),u=ot(l)?{signal:`${l.signal}[0]`}:l[0],c=ot(l)?{signal:`${l.signal}[1]`}:l[1];if(u!==null&&c!==null&&t)return"inrange("+o+", ["+Na(u,i)+", "+Na(c,i)+"])";const f=[];return u!==null&&f.push(`${o} >= ${Na(u,i)}`),c!==null&&f.push(`${o} <= ${Na(c,i)}`),f.length>0?f.join(" && "):"true"}}throw new Error(`Invalid field predicate: ${hn(e)}`)}function u2(e,t=!0){return t?`isValid(${e}) && isFinite(+${e})`:`!isValid(${e}) || !isFinite(+${e})`}function U1e(e){return Vz(e)&&e.timeUnit?{...e,timeUnit:xr(e.timeUnit)}:e}const W0={quantitative:"quantitative",ordinal:"ordinal",temporal:"temporal",nominal:"nominal",geojson:"geojson"};function q1e(e){return e==="quantitative"||e==="temporal"}function Kz(e){return e==="ordinal"||e==="nominal"}const nf=W0.quantitative,q$=W0.ordinal,nh=W0.temporal,W$=W0.nominal,Ih=W0.geojson;function W1e(e){if(e)switch(e=e.toLowerCase(),e){case"q":case nf:return"quantitative";case"t":case nh:return"temporal";case"o":case q$:return"ordinal";case"n":case W$:return"nominal";case Ih:return"geojson"}}const Dr={LINEAR:"linear",LOG:"log",POW:"pow",SQRT:"sqrt",TIME:"time",UTC:"utc",POINT:"point",BAND:"band"},xA={linear:"numeric",log:"numeric",pow:"numeric",sqrt:"numeric",symlog:"numeric",identity:"numeric",sequential:"numeric",time:"time",utc:"time",ordinal:"ordinal","bin-ordinal":"bin-ordinal",point:"ordinal-position",band:"ordinal-position",quantile:"discretizing",quantize:"discretizing",threshold:"discretizing"};function H1e(e,t){const n=xA[e],r=xA[t];return n===r||n==="ordinal-position"&&r==="time"||r==="ordinal-position"&&n==="time"}const G1e={linear:0,log:1,pow:1,sqrt:1,symlog:1,identity:1,sequential:1,time:0,utc:0,point:10,band:11,ordinal:0,"bin-ordinal":0,quantile:0,quantize:0,threshold:0};function S6(e){return G1e[e]}const Zz=new Set(["linear","log","pow","sqrt","symlog"]),Jz=new Set([...Zz,"time","utc"]);function Qz(e){return Zz.has(e)}const ej=new Set(["quantile","quantize","threshold"]),Y1e=new Set([...Jz,...ej,"sequential","identity"]),V1e=new Set(["ordinal","bin-ordinal","point","band"]);function Er(e){return V1e.has(e)}function ga(e){return Y1e.has(e)}function Ka(e){return Jz.has(e)}function rh(e){return ej.has(e)}const X1e={pointPadding:.5,barBandPaddingInner:.1,rectBandPaddingInner:0,tickBandPaddingInner:.25,bandWithNestedOffsetPaddingInner:.2,bandWithNestedOffsetPaddingOuter:.2,minBandSize:2,minFontSize:8,maxFontSize:40,minOpacity:.3,maxOpacity:.8,minSize:4,minStrokeWidth:1,maxStrokeWidth:4,quantileCount:4,quantizeCount:4,zero:!0,framesPerSecond:2,animationDuration:5};function K1e(e){return!We(e)&&De(e,"name")}function tj(e){return De(e,"param")}function Z1e(e){return De(e,"unionWith")}function J1e(e){return Ue(e)&&"field"in e}const Q1e={type:1,domain:1,domainMax:1,domainMin:1,domainMid:1,domainRaw:1,align:1,range:1,rangeMax:1,rangeMin:1,scheme:1,bins:1,reverse:1,round:1,clamp:1,nice:1,base:1,exponent:1,constant:1,interpolate:1,zero:1,padding:1,paddingInner:1,paddingOuter:1},{type:jFe,domain:UFe,range:qFe,rangeMax:WFe,rangeMin:HFe,scheme:GFe,...eve}=Q1e,tve=Fe(eve);function wA(e,t){switch(t){case"type":case"domain":case"reverse":case"range":return!0;case"scheme":case"interpolate":return!["point","band","identity"].includes(e);case"bins":return!["point","band","identity","ordinal"].includes(e);case"round":return Ka(e)||e==="band"||e==="point";case"padding":case"rangeMin":case"rangeMax":return Ka(e)||["point","band"].includes(e);case"paddingOuter":case"align":return["point","band"].includes(e);case"paddingInner":return e==="band";case"domainMax":case"domainMid":case"domainMin":case"domainRaw":case"clamp":return Ka(e);case"nice":return Ka(e)||e==="quantize"||e==="threshold";case"exponent":return e==="pow";case"base":return e==="log";case"constant":return e==="symlog";case"zero":return ga(e)&&!Ut(["log","time","utc","threshold","quantile"],e)}}function nj(e,t){switch(t){case"interpolate":case"scheme":case"domainMid":return fd(e)?void 0:Zme(t);case"align":case"type":case"bins":case"domain":case"domainMax":case"domainMin":case"domainRaw":case"range":case"base":case"exponent":case"constant":case"nice":case"padding":case"paddingInner":case"paddingOuter":case"rangeMax":case"rangeMin":case"reverse":case"round":case"clamp":case"zero":return}}function nve(e,t){return Ut([q$,W$],t)?e===void 0||Er(e):t===nh?Ut([Dr.TIME,Dr.UTC,void 0],e):t===nf?Qz(e)||rh(e)||e===void 0:!0}function rve(e,t,n=!1){if(!So(e))return!1;switch(e){case $n:case kr:case Fu:case Lh:case js:case Ea:return Ka(t)||t==="band"?!0:t==="point"?!n:!1;case Du:return Ut(["linear","band"],t);case vl:case Ru:case yl:case Mu:case Tu:case xf:return Ka(t)||rh(t)||Ut(["band","point","ordinal"],t);case ji:case Eo:case Ao:return t!=="band";case Nu:case Ui:return t==="ordinal"||rh(t)}}function ive(e){return Ue(e)&&"value"in e}const xi={arc:"arc",area:"area",bar:"bar",image:"image",line:"line",point:"point",rect:"rect",rule:"rule",text:"text",tick:"tick",trail:"trail",circle:"circle",square:"square",geoshape:"geoshape"},rj=xi.arc,c2=xi.area,f2=xi.bar,sve=xi.image,d2=xi.line,h2=xi.point,ave=xi.rect,fy=xi.rule,ij=xi.text,H$=xi.tick,ove=xi.trail,G$=xi.circle,Y$=xi.square,sj=xi.geoshape;function Lu(e){return["line","area","trail"].includes(e)}function Ug(e){return["rect","bar","image","arc","tick"].includes(e)}const lve=new Set(Fe(xi));function fo(e){return De(e,"type")}const uve=["stroke","strokeWidth","strokeDash","strokeDashOffset","strokeOpacity","strokeJoin","strokeMiterLimit"],cve=["fill","fillOpacity"],fve=[...uve,...cve],dve={color:1,filled:1,invalid:1,order:1,radius2:1,theta2:1,timeUnitBandSize:1,timeUnitBandPosition:1},C6=Fe(dve),Ax=["binSpacing","continuousBandSize","discreteBandSize","minBandSize"],hve={area:["line","point"],bar:Ax,rect:Ax,line:["point"],tick:["bandSize","thickness",...Ax]},pve={color:"#4c78a8",invalid:"break-paths-show-path-domains",timeUnitBandSize:1},gve={mark:1,arc:1,area:1,bar:1,circle:1,image:1,line:1,point:1,rect:1,rule:1,square:1,text:1,tick:1,trail:1,geoshape:1},aj=Fe(gve);function rf(e){return De(e,"band")}const mve={horizontal:["cornerRadiusTopRight","cornerRadiusBottomRight"],vertical:["cornerRadiusTopLeft","cornerRadiusTopRight"]},vve=5,V$={binSpacing:0,continuousBandSize:vve,minBandSize:.25,timeUnitBandPosition:.5},yve={...V$,binSpacing:1},bve={...V$,thickness:1};function _ve(e){return fo(e)?e.type:e}function oj(e,{isPath:t}){return e===void 0||e==="break-paths-show-path-domains"?t?"break-paths-show-domains":"filter":e===null?"show":e}function X$({markDef:e,config:t,scaleChannel:n,scaleType:r,isCountAggregate:i}){var o,l;if(!r||!ga(r)||i)return"always-valid";const s=oj(fn("invalid",e,t),{isPath:Lu(e.type)});return((l=(o=t.scale)==null?void 0:o.invalid)==null?void 0:l[n])!==void 0?"show":s}function xve(e){return e==="break-paths-filter-domains"||e==="break-paths-show-domains"}function lj({scaleName:e,scale:t,mode:n}){const r=`domain('${e}')`;if(!t||!e)return;const i=`${r}[0]`,s=`peek(${r})`,a=t.domainHasZero();return a==="definitely"?{scale:e,value:0}:a==="maybe"?{signal:`scale('${e}', inrange(0, ${r}) ? 0 : ${n==="zeroOrMin"?i:s})`}:{signal:`scale('${e}', ${n==="zeroOrMin"?i:s})`}}function uj({scaleChannel:e,channelDef:t,scale:n,scaleName:r,markDef:i,config:s}){var c;const a=n==null?void 0:n.get("type"),o=va(t),l=s2(o==null?void 0:o.aggregate),u=X$({scaleChannel:e,markDef:i,config:s,scaleType:a,isCountAggregate:l});if(o&&u==="show"){const f=((c=s.scale.invalid)==null?void 0:c[e])??"zero-or-min";return{test:u2(ze(o,{expr:"datum"}),!1),...wve(f,n,r)}}}function wve(e,t,n){if(ive(e)){const{value:r}=e;return ot(r)?{signal:r.signal}:{value:r}}return lj({scale:t,scaleName:n,mode:"zeroOrMin"})}function K$(e){const{channel:t,channelDef:n,markDef:r,scale:i,scaleName:s,config:a}=e,o=wf(t),l=Z$(e),u=uj({scaleChannel:o,channelDef:n,scale:i,scaleName:s,markDef:r,config:a});return u!==void 0?[u,l]:l}function Eve(e){const{datum:t}=e;return kf(t)?tf(t):`${hn(t)}`}function Cc(e,t,n,r){const i={};if(t&&(i.scale=t),Co(e)){const{datum:s}=e;kf(s)?i.signal=tf(s):ot(s)?i.signal=s.signal:q0(s)?i.signal=s.expr:i.value=s}else i.field=ze(e,n);if(r){const{offset:s,band:a}=r;s&&(i.offset=s),a&&(i.band=a)}return i}function dy({scaleName:e,fieldOrDatumDef:t,fieldOrDatumDef2:n,offset:r,startSuffix:i,endSuffix:s="end",bandPosition:a=.5}){const o=!ot(a)&&0{switch(t.fieldTitle){case"plain":return e.field;case"functional":return Pve(e);default:return Ive(e,t)}};let wj=xj;function Ej(e){wj=e}function Bve(){Ej(xj)}function dd(e,t,{allowDisabling:n,includeDefault:r=!0}){var o;const i=(o=t5(e))==null?void 0:o.title;if(!Oe(e))return i??e.title;const s=e,a=r?n5(s,t):void 0;return n?Vn(i,s.title,a):i??s.title??a}function t5(e){if(sh(e)&&e.axis)return e.axis;if(bj(e)&&e.legend)return e.legend;if(Q$(e)&&e.header)return e.header}function n5(e,t){return wj(e,t)}function gy(e){if(_j(e)){const{format:t,formatType:n}=e;return{format:t,formatType:n}}else{const t=t5(e)??{},{format:n,formatType:r}=t;return{format:n,formatType:r}}}function zve(e,t){var s;switch(t){case"latitude":case"longitude":return"quantitative";case"row":case"column":case"facet":case"shape":case"strokeDash":return"nominal";case"order":return"ordinal"}if(e5(e)&&Se(e.sort))return"ordinal";const{aggregate:n,bin:r,timeUnit:i}=e;if(i)return"temporal";if(r||n&&!Ou(n)&&!cl(n))return"quantitative";if(Cf(e)&&((s=e.scale)!=null&&s.type))switch(xA[e.scale.type]){case"numeric":case"discretizing":return"quantitative";case"time":return"temporal"}return"nominal"}function va(e){if(Oe(e))return e;if(m2(e))return e.condition}function ir(e){if($t(e))return e;if(V0(e))return e.condition}function Aj(e,t,n,r={}){if(We(e)||Qt(e)||xu(e)){const i=We(e)?"string":Qt(e)?"number":"boolean";return Te(Bme(t,i,e)),{value:e}}return $t(e)?my(e,t,n,r):V0(e)?{...e,condition:my(e.condition,t,n,r)}:e}function my(e,t,n,r){if(_j(e)){const{format:i,formatType:s,...a}=e;if(sf(s)&&!n.customFormatTypes)return Te(E6(t)),my(a,t,n,r)}else{const i=sh(e)?"axis":bj(e)?"legend":Q$(e)?"header":null;if(i&&e[i]){const{format:s,formatType:a,...o}=e[i];if(sf(a)&&!n.customFormatTypes)return Te(E6(t)),my({...e,[i]:o},t,n,r)}}return Oe(e)?r5(e,t,r):jve(e)}function jve(e){let t=e.type;if(t)return e;const{datum:n}=e;return t=Qt(n)?"quantitative":We(n)?"nominal":kf(n)?"temporal":void 0,{...e,type:t}}function r5(e,t,{compositeMark:n=!1}={}){const{aggregate:r,timeUnit:i,bin:s,field:a}=e,o={...e};if(!n&&r&&!$$(r)&&!Ou(r)&&!cl(r)&&(Te(jme(r)),delete o.aggregate),i&&(o.timeUnit=xr(i)),a&&(o.field=`${a}`),xn(s)&&(o.bin=v2(s,t)),Cr(s)&&!Xn(t)&&Te(b1e(t)),bi(o)){const{type:l}=o,u=W1e(l);l!==u&&(o.type=u),l!=="quantitative"&&s2(r)&&(Te(zme(l,r)),o.type="quantitative")}else if(!vz(t)){const l=zve(o,t);o.type=l}if(bi(o)){const{compatible:l,warning:u}=Uve(o,t)||{};l===!1&&Te(u)}if(e5(o)&&We(o.sort)){const{sort:l}=o;if(F6(l))return{...o,sort:{encoding:l}};const u=l.substring(1);if(l.charAt(0)==="-"&&F6(u))return{...o,sort:{encoding:u,order:"descending"}}}if(Q$(o)){const{header:l}=o;if(l){const{orient:u,...c}=l;if(u)return{...o,header:{...c,labelOrient:l.labelOrient||u,titleOrient:l.titleOrient||u}}}}return o}function v2(e,t){return xu(e)?{maxbins:p6(t)}:e==="binned"?{binned:!0}:!e.maxbins&&!e.step?{...e,maxbins:p6(t)}:e}const jf={compatible:!0};function Uve(e,t){const n=e.type;if(n==="geojson"&&t!=="shape")return{compatible:!1,warning:`Channel ${t} should not be used with a geojson data.`};switch(t){case el:case tl:case Qb:return py(e)?jf:{compatible:!1,warning:Hme(t)};case $n:case kr:case Fu:case Lh:case ji:case Eo:case Ao:case z0:case j0:case e2:case Qc:case t2:case n2:case xf:case js:case Ea:case r2:return jf;case ka:case Bs:case Aa:case Sa:return n!==nf?{compatible:!1,warning:`Channel ${t} should be used with a quantitative field only, not ${e.type} field.`}:jf;case yl:case Mu:case Tu:case Ru:case vl:case ml:case gl:case wa:case wo:case Du:return n==="nominal"&&!e.sort?{compatible:!1,warning:`Channel ${t} should not be used with an unsorted discrete field.`}:jf;case Ui:case Nu:return!py(e)&&!Ove(e)?{compatible:!1,warning:Gme(t)}:jf;case th:return e.type==="nominal"&&!("sort"in e)?{compatible:!1,warning:"Channel order is inappropriate for nominal field, which has no inherent order."}:jf}}function ah(e){const{formatType:t}=gy(e);return t==="time"||!t&&qve(e)}function qve(e){return e&&(e.type==="temporal"||Oe(e)&&!!e.timeUnit)}function y2(e,{timeUnit:t,type:n,wrapTime:r,undefinedIfExprNotRequired:i}){var l;const s=t&&((l=xr(t))==null?void 0:l.unit);let a=s||n==="temporal",o;return q0(e)?o=e.expr:ot(e)?o=e.signal:kf(e)?(a=!0,o=tf(e)):(We(e)||Qt(e))&&a&&(o=`datetime(${hn(e)})`,M1e(s)&&(Qt(e)&&e<1e4||We(e)&&isNaN(Date.parse(e)))&&(o=tf({[s]:e}))),o?r&&a?`time(${o})`:o:i?void 0:hn(e)}function kj(e,t){const{type:n}=e;return t.map(r=>{const i=Oe(e)&&!Sf(e.timeUnit)?e.timeUnit:void 0,s=y2(r,{timeUnit:i,type:n,undefinedIfExprNotRequired:!0});return s!==void 0?{signal:s}:r})}function X0(e,t){return xn(e.bin)?So(t)&&["ordinal","nominal"].includes(e.type):(console.warn("Only call this method for binned field defs."),!1)}const T6={labelAlign:{part:"labels",vgProp:"align"},labelBaseline:{part:"labels",vgProp:"baseline"},labelColor:{part:"labels",vgProp:"fill"},labelFont:{part:"labels",vgProp:"font"},labelFontSize:{part:"labels",vgProp:"fontSize"},labelFontStyle:{part:"labels",vgProp:"fontStyle"},labelFontWeight:{part:"labels",vgProp:"fontWeight"},labelOpacity:{part:"labels",vgProp:"opacity"},labelOffset:null,labelPadding:null,gridColor:{part:"grid",vgProp:"stroke"},gridDash:{part:"grid",vgProp:"strokeDash"},gridDashOffset:{part:"grid",vgProp:"strokeDashOffset"},gridOpacity:{part:"grid",vgProp:"opacity"},gridWidth:{part:"grid",vgProp:"strokeWidth"},tickColor:{part:"ticks",vgProp:"stroke"},tickDash:{part:"ticks",vgProp:"strokeDash"},tickDashOffset:{part:"ticks",vgProp:"strokeDashOffset"},tickOpacity:{part:"ticks",vgProp:"opacity"},tickSize:null,tickWidth:{part:"ticks",vgProp:"strokeWidth"}};function K0(e){return e==null?void 0:e.condition}const Sj=["domain","grid","labels","ticks","title"],Wve={grid:"grid",gridCap:"grid",gridColor:"grid",gridDash:"grid",gridDashOffset:"grid",gridOpacity:"grid",gridScale:"grid",gridWidth:"grid",orient:"main",bandPosition:"both",aria:"main",description:"main",domain:"main",domainCap:"main",domainColor:"main",domainDash:"main",domainDashOffset:"main",domainOpacity:"main",domainWidth:"main",format:"main",formatType:"main",labelAlign:"main",labelAngle:"main",labelBaseline:"main",labelBound:"main",labelColor:"main",labelFlush:"main",labelFlushOffset:"main",labelFont:"main",labelFontSize:"main",labelFontStyle:"main",labelFontWeight:"main",labelLimit:"main",labelLineHeight:"main",labelOffset:"main",labelOpacity:"main",labelOverlap:"main",labelPadding:"main",labels:"main",labelSeparation:"main",maxExtent:"main",minExtent:"main",offset:"both",position:"main",tickCap:"main",tickColor:"main",tickDash:"main",tickDashOffset:"main",tickMinStep:"both",tickOffset:"both",tickOpacity:"main",tickRound:"both",ticks:"main",tickSize:"main",tickWidth:"both",title:"main",titleAlign:"main",titleAnchor:"main",titleAngle:"main",titleBaseline:"main",titleColor:"main",titleFont:"main",titleFontSize:"main",titleFontStyle:"main",titleFontWeight:"main",titleLimit:"main",titleLineHeight:"main",titleOpacity:"main",titlePadding:"main",titleX:"main",titleY:"main",encode:"both",scale:"both",tickBand:"both",tickCount:"both",tickExtra:"both",translate:"both",values:"both",zindex:"both"},Cj={orient:1,aria:1,bandPosition:1,description:1,domain:1,domainCap:1,domainColor:1,domainDash:1,domainDashOffset:1,domainOpacity:1,domainWidth:1,format:1,formatType:1,grid:1,gridCap:1,gridColor:1,gridDash:1,gridDashOffset:1,gridOpacity:1,gridWidth:1,labelAlign:1,labelAngle:1,labelBaseline:1,labelBound:1,labelColor:1,labelFlush:1,labelFlushOffset:1,labelFont:1,labelFontSize:1,labelFontStyle:1,labelFontWeight:1,labelLimit:1,labelLineHeight:1,labelOffset:1,labelOpacity:1,labelOverlap:1,labelPadding:1,labels:1,labelSeparation:1,maxExtent:1,minExtent:1,offset:1,position:1,tickBand:1,tickCap:1,tickColor:1,tickCount:1,tickDash:1,tickDashOffset:1,tickExtra:1,tickMinStep:1,tickOffset:1,tickOpacity:1,tickRound:1,ticks:1,tickSize:1,tickWidth:1,title:1,titleAlign:1,titleAnchor:1,titleAngle:1,titleBaseline:1,titleColor:1,titleFont:1,titleFontSize:1,titleFontStyle:1,titleFontWeight:1,titleLimit:1,titleLineHeight:1,titleOpacity:1,titlePadding:1,titleX:1,titleY:1,translate:1,values:1,zindex:1},Hve={...Cj,style:1,labelExpr:1,encoding:1};function R6(e){return Ve(Hve,e)}const Gve={axis:1,axisBand:1,axisBottom:1,axisDiscrete:1,axisLeft:1,axisPoint:1,axisQuantitative:1,axisRight:1,axisTemporal:1,axisTop:1,axisX:1,axisXBand:1,axisXDiscrete:1,axisXPoint:1,axisXQuantitative:1,axisXTemporal:1,axisY:1,axisYBand:1,axisYDiscrete:1,axisYPoint:1,axisYQuantitative:1,axisYTemporal:1},$j=Fe(Gve);function _l(e){return De(e,"mark")}class b2{constructor(t,n){this.name=t,this.run=n}hasMatchingType(t){return _l(t)?_ve(t.mark)===this.name:!1}}function $c(e,t){const n=e&&e[t];return n?Se(n)?Qd(n,r=>!!r.field):Oe(n)||m2(n):!1}function Fj(e,t){const n=e&&e[t];return n?Se(n)?Qd(n,r=>!!r.field):Oe(n)||Co(n)||V0(n):!1}function Dj(e,t){if(Xn(t)){const n=e[t];if((Oe(n)||Co(n))&&(Kz(n.type)||Oe(n)&&n.timeUnit)){const r=E$(t);return Fj(e,r)}}return!1}function Mj(e){return Qd(j0e,t=>{if($c(e,t)){const n=e[t];if(Se(n))return Qd(n,r=>!!r.aggregate);{const r=va(n);return r&&!!r.aggregate}}return!1})}function Tj(e,t){const n=[],r=[],i=[],s=[],a={};return i5(e,(o,l)=>{if(Oe(o)){const{field:u,aggregate:c,bin:f,timeUnit:d,...h}=o;if(c||d||f){const p=t5(o),g=p==null?void 0:p.title;let v=ze(o,{forAs:!0});const y={...g?[]:{title:dd(o,t,{allowDisabling:!0})},...h,field:v};if(c){let b;if(Ou(c)?(b="argmax",v=ze({op:"argmax",field:c.argmax},{forAs:!0}),y.field=`${v}.${u}`):cl(c)?(b="argmin",v=ze({op:"argmin",field:c.argmin},{forAs:!0}),y.field=`${v}.${u}`):c!=="boxplot"&&c!=="errorbar"&&c!=="errorband"&&(b=c),b){const _={op:b,as:v};u&&(_.field=u),s.push(_)}}else if(n.push(v),bi(o)&&xn(f)){if(r.push({bin:f,field:u,as:v}),n.push(ze(o,{binSuffix:"end"})),X0(o,l)&&n.push(ze(o,{binSuffix:"range"})),Xn(l)){const b={field:`${v}_end`};a[`${l}2`]=b}y.bin="binned",vz(l)||(y.type=nf)}else if(d&&!Sf(d)){i.push({timeUnit:d,field:u,as:v});const b=bi(o)&&o.type!==nh&&"time";b&&(l===z0||l===Qc?y.formatType=b:J0e(l)?y.legend={formatType:b,...y.legend}:Xn(l)&&(y.axis={formatType:b,...y.axis}))}a[l]=y}else n.push(u),a[l]=e[l]}else a[l]=e[l]}),{bins:r,timeUnits:i,aggregate:s,groupby:n,encoding:a}}function Yve(e,t,n){const r=eme(t,n);if(r){if(r==="binned"){const i=e[t===wa?$n:kr];return!!(Oe(i)&&Oe(e[t])&&Cr(i.bin))}}else return!1;return!0}function Vve(e,t,n,r){const i={};for(const s of Fe(e))mz(s)||Te(Wme(s));for(let s of Y0e){if(!e[s])continue;const a=e[s];if(U0(s)){const o=G0e(s),l=i[o];if(Oe(l)&&q1e(l.type)&&Oe(a)&&!l.timeUnit){Te(Pme(o));continue}}if(s==="angle"&&t==="arc"&&!e.theta&&(Te(Ime),s=js),!Yve(e,s,t)){Te(o2(s,t));continue}if(s===vl&&t==="line"){const o=va(e[s]);if(o!=null&&o.aggregate){Te(qme);continue}}if(s===ji&&(n?"fill"in e:"stroke"in e)){Te(Nz("encoding",{fill:"fill"in e,stroke:"stroke"in e}));continue}if(s===j0||s===th&&!Se(a)&&!ma(a)||s===Qc&&Se(a)){if(a){if(s===th){const o=e[s];if(yj(o)){i[s]=o;continue}}i[s]=He(a).reduce((o,l)=>(Oe(l)?o.push(r5(l,s)):Te(_A(l,s)),o),[])}}else{if(s===Qc&&a===null)i[s]=null;else if(!Oe(a)&&!Co(a)&&!ma(a)&&!Y0(a)&&!ot(a)){Te(_A(a,s));continue}i[s]=Aj(a,s,r)}}return i}function _2(e,t){const n={};for(const r of Fe(e)){const i=Aj(e[r],r,t,{compositeMark:!0});n[r]=i}return n}function Xve(e){const t=[];for(const n of Fe(e))if($c(e,n)){const r=e[n],i=He(r);for(const s of i)Oe(s)?t.push(s):m2(s)&&t.push(s.condition)}return t}function i5(e,t,n){if(e)for(const r of Fe(e)){const i=e[r];if(Se(i))for(const s of i)t.call(n,s,r);else t.call(n,i,r)}}function Kve(e,t,n,r){return e?Fe(e).reduce((i,s)=>{const a=e[s];return Se(a)?a.reduce((o,l)=>t.call(r,o,l,s),i):t.call(r,i,a,s)},n):n}function Rj(e,t){return Fe(t).reduce((n,r)=>{switch(r){case $n:case kr:case t2:case r2:case n2:case wa:case wo:case Fu:case Lh:case js:case ml:case Ea:case gl:case Du:case Aa:case ka:case Sa:case Bs:case z0:case Ui:case xf:case Qc:return n;case th:if(e==="line"||e==="trail")return n;case j0:case e2:{const i=t[r];if(Se(i)||Oe(i))for(const s of He(i))s.aggregate||n.push(ze(s,{}));return n}case vl:if(e==="trail")return n;case ji:case Eo:case Ao:case yl:case Mu:case Tu:case Nu:case Ru:{const i=va(t[r]);return i&&!i.aggregate&&n.push(ze(i,{})),n}}},[])}function Zve(e){const{tooltip:t,...n}=e;if(!t)return{filteredEncoding:n};let r,i;if(Se(t)){for(const s of t)s.aggregate?(r||(r=[]),r.push(s)):(i||(i=[]),i.push(s));r&&(n.tooltip=r)}else t.aggregate?n.tooltip=t:i=t;return Se(i)&&i.length===1&&(i=i[0]),{customTooltipWithoutAggregatedField:i,filteredEncoding:n}}function AA(e,t,n,r=!0){if("tooltip"in n)return{tooltip:n.tooltip};const i=e.map(({fieldPrefix:a,titlePrefix:o})=>{const l=r?` of ${s5(t)}`:"";return{field:a+t.field,type:t.type,title:ot(o)?{signal:`${o}"${escape(l)}"`}:o+l}}),s=Xve(n).map(Rve);return{tooltip:[...i,...Xa(s,Gt)]}}function s5(e){const{title:t,field:n}=e;return Vn(t,n)}function a5(e,t,n,r,i){const{scale:s,axis:a}=n;return({partName:o,mark:l,positionPrefix:u,endPositionPrefix:c=void 0,extraEncoding:f={}})=>{const d=s5(n);return Nj(e,o,i,{mark:l,encoding:{[t]:{field:`${u}_${n.field}`,type:n.type,...d!==void 0?{title:d}:{},...s!==void 0?{scale:s}:{},...a!==void 0?{axis:a}:{}},...We(c)?{[`${t}2`]:{field:`${c}_${n.field}`}}:{},...r,...f}})}}function Nj(e,t,n,r){const{clip:i,color:s,opacity:a}=e,o=e.type;return e[t]||e[t]===void 0&&n[t]?[{...r,mark:{...n[t],...i?{clip:i}:{},...s?{color:s}:{},...a?{opacity:a}:{},...fo(r.mark)?r.mark:{type:r.mark},style:`${o}-${String(t)}`,...xu(e[t])?{}:e[t]}}]:[]}function Oj(e,t,n){const{encoding:r}=e,i=t==="vertical"?"y":"x",s=r[i],a=r[`${i}2`],o=r[`${i}Error`],l=r[`${i}Error2`];return{continuousAxisChannelDef:Bm(s,n),continuousAxisChannelDef2:Bm(a,n),continuousAxisChannelDefError:Bm(o,n),continuousAxisChannelDefError2:Bm(l,n),continuousAxis:i}}function Bm(e,t){if(e!=null&&e.aggregate){const{aggregate:n,...r}=e;return n!==t&&Te(y1e(n,t)),r}else return e}function Lj(e,t){const{mark:n,encoding:r}=e,{x:i,y:s}=r;if(fo(n)&&n.orient)return n.orient;if(Hl(i)){if(Hl(s)){const a=Oe(i)&&i.aggregate,o=Oe(s)&&s.aggregate;if(!a&&o===t)return"vertical";if(!o&&a===t)return"horizontal";if(a===t&&o===t)throw new Error("Both x and y cannot have aggregate");return ah(s)&&!ah(i)?"horizontal":"vertical"}return"horizontal"}else{if(Hl(s))return"vertical";throw new Error(`Need a valid continuous axis for ${t}s`)}}const vy="boxplot",Jve=["box","median","outliers","rule","ticks"],Qve=new b2(vy,Pj);function Ij(e){return Qt(e)?"tukey":e}function Pj(e,{config:t}){e={...e,encoding:_2(e.encoding,t)};const{mark:n,encoding:r,params:i,projection:s,...a}=e,o=fo(n)?n:{type:n};i&&Te(Tz("boxplot"));const l=o.extent??t.boxplot.extent,u=fn("size",o,t),c=o.invalid,f=Ij(l),{bins:d,timeUnits:h,transform:p,continuousAxisChannelDef:g,continuousAxis:v,groupby:y,aggregate:b,encodingWithoutContinuousAxis:_,ticksOrient:x,boxOrient:w,customTooltipWithoutAggregatedField:A}=eye(e,l,t),E=Oh(g.field),{color:k,size:C,...M}=_,N=re=>a5(o,v,g,re,t.boxplot),P=N(M),I=N(_),T=(Ue(t.boxplot.box)?t.boxplot.box.color:t.mark.color)||"#4c78a8",$=N({...M,...C?{size:C}:{},color:{condition:{test:`${sn(`lower_box_${g.field}`)} >= ${sn(`upper_box_${g.field}`)}`,...k||{value:T}}}}),L=AA([{fieldPrefix:f==="min-max"?"upper_whisker_":"max_",titlePrefix:"Max"},{fieldPrefix:"upper_box_",titlePrefix:"Q3"},{fieldPrefix:"mid_box_",titlePrefix:"Median"},{fieldPrefix:"lower_box_",titlePrefix:"Q1"},{fieldPrefix:f==="min-max"?"lower_whisker_":"min_",titlePrefix:"Min"}],g,_),W={type:"tick",color:"black",opacity:1,orient:x,invalid:c,aria:!1},U=f==="min-max"?L:AA([{fieldPrefix:"upper_whisker_",titlePrefix:"Upper Whisker"},{fieldPrefix:"lower_whisker_",titlePrefix:"Lower Whisker"}],g,_),O=[...P({partName:"rule",mark:{type:"rule",invalid:c,aria:!1},positionPrefix:"lower_whisker",endPositionPrefix:"lower_box",extraEncoding:U}),...P({partName:"rule",mark:{type:"rule",invalid:c,aria:!1},positionPrefix:"upper_box",endPositionPrefix:"upper_whisker",extraEncoding:U}),...P({partName:"ticks",mark:W,positionPrefix:"lower_whisker",extraEncoding:U}),...P({partName:"ticks",mark:W,positionPrefix:"upper_whisker",extraEncoding:U})],H=[...f!=="tukey"?O:[],...I({partName:"box",mark:{type:"bar",...u?{size:u}:{},orient:w,invalid:c,ariaRoleDescription:"box"},positionPrefix:"lower_box",endPositionPrefix:"upper_box",extraEncoding:L}),...$({partName:"median",mark:{type:"tick",invalid:c,...Ue(t.boxplot.median)&&t.boxplot.median.color?{color:t.boxplot.median.color}:{},...u?{size:u}:{},orient:x,aria:!1},positionPrefix:"mid_box",extraEncoding:L})];if(f==="min-max")return{...a,transform:(a.transform??[]).concat(p),layer:H};const G=sn(`lower_box_${g.field}`),J=sn(`upper_box_${g.field}`),ce=`(${J} - ${G})`,xe=`${G} - ${l} * ${ce}`,be=`${J} + ${l} * ${ce}`,Le=sn(g.field),tt={joinaggregate:Bj(g.field),groupby:y},he={transform:[{filter:`(${xe} <= ${Le}) && (${Le} <= ${be})`},{aggregate:[{op:"min",field:g.field,as:`lower_whisker_${E}`},{op:"max",field:g.field,as:`upper_whisker_${E}`},{op:"min",field:`lower_box_${g.field}`,as:`lower_box_${E}`},{op:"max",field:`upper_box_${g.field}`,as:`upper_box_${E}`},...b],groupby:y}],layer:O},{tooltip:Y,...Ce}=M,{scale:le,axis:V}=g,q=s5(g),B=Li(V,["title"]),Q=Nj(o,"outliers",t.boxplot,{transform:[{filter:`(${Le} < ${xe}) || (${Le} > ${be})`}],mark:"point",encoding:{[v]:{field:g.field,type:g.type,...q!==void 0?{title:q}:{},...le!==void 0?{scale:le}:{},...dn(B)?{}:{axis:B}},...Ce,...k?{color:k}:{},...A?{tooltip:A}:{}}})[0];let X;const j=[...d,...h,tt];return Q?X={transform:j,layer:[Q,he]}:(X=he,X.transform.unshift(...j)),{...a,layer:[X,{transform:p,layer:H}]}}function Bj(e){const t=Oh(e);return[{op:"q1",field:e,as:`lower_box_${t}`},{op:"q3",field:e,as:`upper_box_${t}`}]}function eye(e,t,n){const r=Lj(e,vy),{continuousAxisChannelDef:i,continuousAxis:s}=Oj(e,r,vy),a=i.field,o=Oh(a),l=Ij(t),u=[...Bj(a),{op:"median",field:a,as:`mid_box_${o}`},{op:"min",field:a,as:(l==="min-max"?"lower_whisker_":"min_")+o},{op:"max",field:a,as:(l==="min-max"?"upper_whisker_":"max_")+o}],c=l==="min-max"||l==="tukey"?[]:[{calculate:`${sn(`upper_box_${o}`)} - ${sn(`lower_box_${o}`)}`,as:`iqr_${o}`},{calculate:`min(${sn(`upper_box_${o}`)} + ${sn(`iqr_${o}`)} * ${t}, ${sn(`max_${o}`)})`,as:`upper_whisker_${o}`},{calculate:`max(${sn(`lower_box_${o}`)} - ${sn(`iqr_${o}`)} * ${t}, ${sn(`min_${o}`)})`,as:`lower_whisker_${o}`}],{[s]:f,...d}=e.encoding,{customTooltipWithoutAggregatedField:h,filteredEncoding:p}=Zve(d),{bins:g,timeUnits:v,aggregate:y,groupby:b,encoding:_}=Tj(p,n),x=r==="vertical"?"horizontal":"vertical",w=r,A=[...g,...v,{aggregate:[...y,...u],groupby:b},...c];return{bins:g,timeUnits:v,transform:A,groupby:b,aggregate:y,continuousAxisChannelDef:i,continuousAxis:s,encodingWithoutContinuousAxis:_,ticksOrient:x,boxOrient:w,customTooltipWithoutAggregatedField:h}}const o5="errorbar",tye=["ticks","rule"],nye=new b2(o5,zj);function zj(e,{config:t}){e={...e,encoding:_2(e.encoding,t)};const{transform:n,continuousAxisChannelDef:r,continuousAxis:i,encodingWithoutContinuousAxis:s,ticksOrient:a,markDef:o,outerSpec:l,tooltipEncoding:u}=jj(e,o5,t);delete s.size;const c=a5(o,i,r,s,t.errorbar),f=o.thickness,d=o.size,h={type:"tick",orient:a,aria:!1,...f!==void 0?{thickness:f}:{},...d!==void 0?{size:d}:{}},p=[...c({partName:"ticks",mark:h,positionPrefix:"lower",extraEncoding:u}),...c({partName:"ticks",mark:h,positionPrefix:"upper",extraEncoding:u}),...c({partName:"rule",mark:{type:"rule",ariaRoleDescription:"errorbar",...f!==void 0?{size:f}:{}},positionPrefix:"lower",endPositionPrefix:"upper",extraEncoding:u})];return{...l,transform:n,...p.length>1?{layer:p}:{...p[0]}}}function rye(e,t){const{encoding:n}=e;if(iye(n))return{orient:Lj(e,t),inputType:"raw"};const r=sye(n),i=aye(n),s=n.x,a=n.y;if(r){if(i)throw new Error(`${t} cannot be both type aggregated-upper-lower and aggregated-error`);const o=n.x2,l=n.y2;if($t(o)&&$t(l))throw new Error(`${t} cannot have both x2 and y2`);if($t(o)){if(Hl(s))return{orient:"horizontal",inputType:"aggregated-upper-lower"};throw new Error(`Both x and x2 have to be quantitative in ${t}`)}else if($t(l)){if(Hl(a))return{orient:"vertical",inputType:"aggregated-upper-lower"};throw new Error(`Both y and y2 have to be quantitative in ${t}`)}throw new Error("No ranged axis")}else{const o=n.xError,l=n.xError2,u=n.yError,c=n.yError2;if($t(l)&&!$t(o))throw new Error(`${t} cannot have xError2 without xError`);if($t(c)&&!$t(u))throw new Error(`${t} cannot have yError2 without yError`);if($t(o)&&$t(u))throw new Error(`${t} cannot have both xError and yError with both are quantiative`);if($t(o)){if(Hl(s))return{orient:"horizontal",inputType:"aggregated-error"};throw new Error("All x, xError, and xError2 (if exist) have to be quantitative")}else if($t(u)){if(Hl(a))return{orient:"vertical",inputType:"aggregated-error"};throw new Error("All y, yError, and yError2 (if exist) have to be quantitative")}throw new Error("No ranged axis")}}function iye(e){return($t(e.x)||$t(e.y))&&!$t(e.x2)&&!$t(e.y2)&&!$t(e.xError)&&!$t(e.xError2)&&!$t(e.yError)&&!$t(e.yError2)}function sye(e){return $t(e.x2)||$t(e.y2)}function aye(e){return $t(e.xError)||$t(e.xError2)||$t(e.yError)||$t(e.yError2)}function jj(e,t,n){const{mark:r,encoding:i,params:s,projection:a,...o}=e,l=fo(r)?r:{type:r};s&&Te(Tz(t));const{orient:u,inputType:c}=rye(e,t),{continuousAxisChannelDef:f,continuousAxisChannelDef2:d,continuousAxisChannelDefError:h,continuousAxisChannelDefError2:p,continuousAxis:g}=Oj(e,u,t),{errorBarSpecificAggregate:v,postAggregateCalculates:y,tooltipSummary:b,tooltipTitleWithFieldName:_}=oye(l,f,d,h,p,c,t,n),{[g]:x,[g==="x"?"x2":"y2"]:w,[g==="x"?"xError":"yError"]:A,[g==="x"?"xError2":"yError2"]:E,...k}=i,{bins:C,timeUnits:M,aggregate:N,groupby:P,encoding:I}=Tj(k,n),T=[...N,...v],$=c!=="raw"?[]:P,L=AA(b,f,I,_);return{transform:[...o.transform??[],...C,...M,...T.length===0?[]:[{aggregate:T,groupby:$}],...y],groupby:$,continuousAxisChannelDef:f,continuousAxis:g,encodingWithoutContinuousAxis:I,ticksOrient:u==="vertical"?"horizontal":"vertical",markDef:l,outerSpec:o,tooltipEncoding:L}}function oye(e,t,n,r,i,s,a,o){let l=[],u=[];const c=t.field;let f,d=!1;if(s==="raw"){const h=e.center?e.center:e.extent?e.extent==="iqr"?"median":"mean":o.errorbar.center,p=e.extent?e.extent:h==="mean"?"stderr":"iqr";if(h==="median"!=(p==="iqr")&&Te(v1e(h,p,a)),p==="stderr"||p==="stdev")l=[{op:p,field:c,as:`extent_${c}`},{op:h,field:c,as:`center_${c}`}],u=[{calculate:`${sn(`center_${c}`)} + ${sn(`extent_${c}`)}`,as:`upper_${c}`},{calculate:`${sn(`center_${c}`)} - ${sn(`extent_${c}`)}`,as:`lower_${c}`}],f=[{fieldPrefix:"center_",titlePrefix:B0(h)},{fieldPrefix:"upper_",titlePrefix:N6(h,p,"+")},{fieldPrefix:"lower_",titlePrefix:N6(h,p,"-")}],d=!0;else{let g,v,y;p==="ci"?(g="mean",v="ci0",y="ci1"):(g="median",v="q1",y="q3"),l=[{op:v,field:c,as:`lower_${c}`},{op:y,field:c,as:`upper_${c}`},{op:g,field:c,as:`center_${c}`}],f=[{fieldPrefix:"upper_",titlePrefix:dd({field:c,aggregate:y,type:"quantitative"},o,{allowDisabling:!1})},{fieldPrefix:"lower_",titlePrefix:dd({field:c,aggregate:v,type:"quantitative"},o,{allowDisabling:!1})},{fieldPrefix:"center_",titlePrefix:dd({field:c,aggregate:g,type:"quantitative"},o,{allowDisabling:!1})}]}}else{(e.center||e.extent)&&Te(m1e(e.center,e.extent)),s==="aggregated-upper-lower"?(f=[],u=[{calculate:sn(n.field),as:`upper_${c}`},{calculate:sn(c),as:`lower_${c}`}]):s==="aggregated-error"&&(f=[{fieldPrefix:"",titlePrefix:c}],u=[{calculate:`${sn(c)} + ${sn(r.field)}`,as:`upper_${c}`}],i?u.push({calculate:`${sn(c)} + ${sn(i.field)}`,as:`lower_${c}`}):u.push({calculate:`${sn(c)} - ${sn(r.field)}`,as:`lower_${c}`}));for(const h of u)f.push({fieldPrefix:h.as.substring(0,6),titlePrefix:Jc(Jc(h.calculate,"datum['",""),"']","")})}return{postAggregateCalculates:u,errorBarSpecificAggregate:l,tooltipSummary:f,tooltipTitleWithFieldName:d}}function N6(e,t,n){return`${B0(e)} ${n} ${t}`}const l5="errorband",lye=["band","borders"],uye=new b2(l5,Uj);function Uj(e,{config:t}){e={...e,encoding:_2(e.encoding,t)};const{transform:n,continuousAxisChannelDef:r,continuousAxis:i,encodingWithoutContinuousAxis:s,markDef:a,outerSpec:o,tooltipEncoding:l}=jj(e,l5,t),u=a,c=a5(u,i,r,s,t.errorband),f=e.encoding.x!==void 0&&e.encoding.y!==void 0;let d={type:f?"area":"rect"},h={type:f?"line":"rule"};const p={...u.interpolate?{interpolate:u.interpolate}:{},...u.tension&&u.interpolate?{tension:u.tension}:{}};return f?(d={...d,...p,ariaRoleDescription:"errorband"},h={...h,...p,aria:!1}):u.interpolate?Te(k6("interpolate")):u.tension&&Te(k6("tension")),{...o,transform:n,layer:[...c({partName:"band",mark:d,positionPrefix:"lower",endPositionPrefix:"upper",extraEncoding:l}),...c({partName:"borders",mark:h,positionPrefix:"lower",extraEncoding:l}),...c({partName:"borders",mark:h,positionPrefix:"upper",extraEncoding:l})]}}const qj={};function u5(e,t,n){const r=new b2(e,t);qj[e]={normalizer:r,parts:n}}function cye(){return Fe(qj)}u5(vy,Pj,Jve);u5(o5,zj,tye);u5(l5,Uj,lye);const fye=["gradientHorizontalMaxLength","gradientHorizontalMinLength","gradientVerticalMaxLength","gradientVerticalMinLength","unselectedOpacity"],Wj={titleAlign:"align",titleAnchor:"anchor",titleAngle:"angle",titleBaseline:"baseline",titleColor:"color",titleFont:"font",titleFontSize:"fontSize",titleFontStyle:"fontStyle",titleFontWeight:"fontWeight",titleLimit:"limit",titleLineHeight:"lineHeight",titleOrient:"orient",titlePadding:"offset"},Hj={labelAlign:"align",labelAnchor:"anchor",labelAngle:"angle",labelBaseline:"baseline",labelColor:"color",labelFont:"font",labelFontSize:"fontSize",labelFontStyle:"fontStyle",labelFontWeight:"fontWeight",labelLimit:"limit",labelLineHeight:"lineHeight",labelOrient:"orient",labelPadding:"offset"},dye=Fe(Wj),hye=Fe(Hj),pye={header:1,headerRow:1,headerColumn:1,headerFacet:1},Gj=Fe(pye),Yj=["size","shape","fill","stroke","strokeDash","strokeWidth","opacity"],gye={gradientHorizontalMaxLength:200,gradientHorizontalMinLength:100,gradientVerticalMaxLength:200,gradientVerticalMinLength:64,unselectedOpacity:.35},mye={aria:1,clipHeight:1,columnPadding:1,columns:1,cornerRadius:1,description:1,direction:1,fillColor:1,format:1,formatType:1,gradientLength:1,gradientOpacity:1,gradientStrokeColor:1,gradientStrokeWidth:1,gradientThickness:1,gridAlign:1,labelAlign:1,labelBaseline:1,labelColor:1,labelFont:1,labelFontSize:1,labelFontStyle:1,labelFontWeight:1,labelLimit:1,labelOffset:1,labelOpacity:1,labelOverlap:1,labelPadding:1,labelSeparation:1,legendX:1,legendY:1,offset:1,orient:1,padding:1,rowPadding:1,strokeColor:1,symbolDash:1,symbolDashOffset:1,symbolFillColor:1,symbolLimit:1,symbolOffset:1,symbolOpacity:1,symbolSize:1,symbolStrokeColor:1,symbolStrokeWidth:1,symbolType:1,tickCount:1,tickMinStep:1,title:1,titleAlign:1,titleAnchor:1,titleBaseline:1,titleColor:1,titleFont:1,titleFontSize:1,titleFontStyle:1,titleFontWeight:1,titleLimit:1,titleLineHeight:1,titleOpacity:1,titleOrient:1,titlePadding:1,type:1,values:1,zindex:1},ya="_vgsid_",vye={point:{on:"click",fields:[ya],toggle:"event.shiftKey",resolve:"global",clear:"dblclick"},interval:{on:"[pointerdown, window:pointerup] > window:pointermove!",encodings:["x","y"],translate:"[pointerdown, window:pointerup] > window:pointermove!",zoom:"wheel!",mark:{fill:"#333",fillOpacity:.125,stroke:"white"},resolve:"global",clear:"dblclick"}};function c5(e){return e==="legend"||!!(e!=null&&e.legend)}function kx(e){return c5(e)&&Ue(e)}function f5(e){return!!(e!=null&&e.select)}function Vj(e){const t=[];for(const n of e||[]){if(f5(n))continue;const{expr:r,bind:i,...s}=n;if(i&&r){const a={...s,bind:i,init:r};t.push(a)}else{const a={...s,...r?{update:r}:{},...i?{bind:i}:{}};t.push(a)}}return t}function yye(e){return x2(e)||h5(e)||d5(e)}function d5(e){return De(e,"concat")}function x2(e){return De(e,"vconcat")}function h5(e){return De(e,"hconcat")}function Xj({step:e,offsetIsDiscrete:t}){return t?e.for??"offset":"position"}function ho(e){return De(e,"step")}function O6(e){return De(e,"view")||De(e,"width")||De(e,"height")}const L6=20,bye={align:1,bounds:1,center:1,columns:1,spacing:1},_ye=Fe(bye);function xye(e,t,n){const r=n[t],i={},{spacing:s,columns:a}=r;s!==void 0&&(i.spacing=s),a!==void 0&&(g2(e)&&!G0(e.facet)||d5(e))&&(i.columns=a),x2(e)&&(i.columns=1);for(const o of _ye)if(e[o]!==void 0)if(o==="spacing"){const l=e[o];i[o]=Qt(l)?l:{row:l.row??s,column:l.column??s}}else i[o]=e[o];return i}function kA(e,t){return e[t]??e[t==="width"?"continuousWidth":"continuousHeight"]}function SA(e,t){const n=yy(e,t);return ho(n)?n.step:Kj}function yy(e,t){const n=e[t]??e[t==="width"?"discreteWidth":"discreteHeight"];return Vn(n,{step:e.step})}const Kj=20,wye={continuousWidth:200,continuousHeight:200,step:Kj},Eye={background:"white",padding:5,timeFormat:"%b %d, %Y",countTitle:"Count of Records",view:wye,mark:pve,arc:{},area:{},bar:yve,circle:{},geoshape:{},image:{},line:{},point:{},rect:V$,rule:{color:"black"},square:{},text:{color:"black"},tick:bve,trail:{},boxplot:{size:14,extent:1.5,box:{},median:{color:"white"},outliers:{},rule:{},ticks:null},errorbar:{center:"mean",rule:!0,ticks:!1},errorband:{band:{opacity:.3},borders:!1},scale:X1e,projection:{},legend:gye,header:{titlePadding:10,labelPadding:10},headerColumn:{},headerRow:{},headerFacet:{},selection:vye,style:{},title:{},facet:{spacing:L6},concat:{spacing:L6},normalizedNumberFormat:".0%"},Ro=["#4c78a8","#f58518","#e45756","#72b7b2","#54a24b","#eeca3b","#b279a2","#ff9da6","#9d755d","#bab0ac"],I6={text:11,guideLabel:10,guideTitle:11,groupTitle:13,groupSubtitle:12},P6={blue:Ro[0],orange:Ro[1],red:Ro[2],teal:Ro[3],green:Ro[4],yellow:Ro[5],purple:Ro[6],pink:Ro[7],brown:Ro[8],gray0:"#000",gray1:"#111",gray2:"#222",gray3:"#333",gray4:"#444",gray5:"#555",gray6:"#666",gray7:"#777",gray8:"#888",gray9:"#999",gray10:"#aaa",gray11:"#bbb",gray12:"#ccc",gray13:"#ddd",gray14:"#eee",gray15:"#fff"};function Aye(e={}){return{signals:[{name:"color",value:Ue(e)?{...P6,...e}:P6}],mark:{color:{signal:"color.blue"}},rule:{color:{signal:"color.gray0"}},text:{color:{signal:"color.gray0"}},style:{"guide-label":{fill:{signal:"color.gray0"}},"guide-title":{fill:{signal:"color.gray0"}},"group-title":{fill:{signal:"color.gray0"}},"group-subtitle":{fill:{signal:"color.gray0"}},cell:{stroke:{signal:"color.gray8"}}},axis:{domainColor:{signal:"color.gray13"},gridColor:{signal:"color.gray8"},tickColor:{signal:"color.gray13"}},range:{category:[{signal:"color.blue"},{signal:"color.orange"},{signal:"color.red"},{signal:"color.teal"},{signal:"color.green"},{signal:"color.yellow"},{signal:"color.purple"},{signal:"color.pink"},{signal:"color.brown"},{signal:"color.grey8"}]}}}function kye(e){return{signals:[{name:"fontSize",value:Ue(e)?{...I6,...e}:I6}],text:{fontSize:{signal:"fontSize.text"}},style:{"guide-label":{fontSize:{signal:"fontSize.guideLabel"}},"guide-title":{fontSize:{signal:"fontSize.guideTitle"}},"group-title":{fontSize:{signal:"fontSize.groupTitle"}},"group-subtitle":{fontSize:{signal:"fontSize.groupSubtitle"}}}}}function Sye(e){return{text:{font:e},style:{"guide-label":{font:e},"guide-title":{font:e},"group-title":{font:e},"group-subtitle":{font:e}}}}function Zj(e){const t=Fe(e||{}),n={};for(const r of t){const i=e[r];n[r]=K0(i)?kz(i):Qi(i)}return n}function Cye(e){const t=Fe(e),n={};for(const r of t)n[r]=Zj(e[r]);return n}const $ye=[...aj,...$j,...Gj,"background","padding","legend","lineBreak","scale","style","title","view"];function Jj(e={}){const{color:t,font:n,fontSize:r,selection:i,...s}=e,a=yh({},Ct(Eye),n?Sye(n):{},t?Aye(t):{},r?kye(r):{},s||{});i&&bh(a,"selection",i,!0);const o=Li(a,$ye);for(const l of["background","lineBreak","padding"])a[l]&&(o[l]=Qi(a[l]));for(const l of aj)a[l]&&(o[l]=Fr(a[l]));for(const l of $j)a[l]&&(o[l]=Zj(a[l]));for(const l of Gj)a[l]&&(o[l]=Fr(a[l]));if(a.legend&&(o.legend=Fr(a.legend)),a.scale){const{invalid:l,...u}=a.scale,c=Fr(l,{level:1});o.scale={...Fr(u),...Fe(c).length>0?{invalid:c}:{}}}return a.style&&(o.style=Cye(a.style)),a.title&&(o.title=Fr(a.title)),a.view&&(o.view=Fr(a.view)),o}const Fye=new Set(["view",...lve]),Dye=["color","fontSize","background","padding","facet","concat","numberFormat","numberFormatType","normalizedNumberFormat","normalizedNumberFormatType","timeFormat","countTitle","header","axisQuantitative","axisTemporal","axisDiscrete","axisPoint","axisXBand","axisXPoint","axisXDiscrete","axisXQuantitative","axisXTemporal","axisYBand","axisYPoint","axisYDiscrete","axisYQuantitative","axisYTemporal","scale","selection","overlay"],Mye={view:["continuousWidth","continuousHeight","discreteWidth","discreteHeight","step"],...hve};function Tye(e){e=Ct(e);for(const t of Dye)delete e[t];if(e.axis)for(const t in e.axis)K0(e.axis[t])&&delete e.axis[t];if(e.legend)for(const t of fye)delete e.legend[t];if(e.mark){for(const t of C6)delete e.mark[t];e.mark.tooltip&&Ue(e.mark.tooltip)&&delete e.mark.tooltip}e.params&&(e.signals=(e.signals||[]).concat(Vj(e.params)),delete e.params);for(const t of Fye){for(const r of C6)delete e[t][r];const n=Mye[t];if(n)for(const r of n)delete e[t][r];Nye(e,t)}for(const t of cye())delete e[t];Rye(e);for(const t in e)Ue(e[t])&&dn(e[t])&&delete e[t];return dn(e)?void 0:e}function Rye(e){const{titleMarkConfig:t,subtitleMarkConfig:n,subtitle:r}=Az(e.title);dn(t)||(e.style["group-title"]={...e.style["group-title"],...t}),dn(n)||(e.style["group-subtitle"]={...e.style["group-subtitle"],...n}),dn(r)?delete e.title:e.title=r}function Nye(e,t,n,r){const i=e[t];t==="view"&&(n="cell");const s={...i,...e.style[n??t]};dn(s)||(e.style[n??t]=s),delete e[t]}function w2(e){return De(e,"layer")}function Oye(e){return De(e,"repeat")}function Lye(e){return!Se(e.repeat)&&De(e.repeat,"layer")}class p5{map(t,n){return g2(t)?this.mapFacet(t,n):Oye(t)?this.mapRepeat(t,n):h5(t)?this.mapHConcat(t,n):x2(t)?this.mapVConcat(t,n):d5(t)?this.mapConcat(t,n):this.mapLayerOrUnit(t,n)}mapLayerOrUnit(t,n){if(w2(t))return this.mapLayer(t,n);if(_l(t))return this.mapUnit(t,n);throw new Error(F$(t))}mapLayer(t,n){return{...t,layer:t.layer.map(r=>this.mapLayerOrUnit(r,n))}}mapHConcat(t,n){return{...t,hconcat:t.hconcat.map(r=>this.map(r,n))}}mapVConcat(t,n){return{...t,vconcat:t.vconcat.map(r=>this.map(r,n))}}mapConcat(t,n){const{concat:r,...i}=t;return{...i,concat:r.map(s=>this.map(s,n))}}mapFacet(t,n){return{...t,spec:this.map(t.spec,n)}}mapRepeat(t,n){return{...t,spec:this.map(t.spec,n)}}}const Iye={zero:1,center:1,normalize:1};function Pye(e){return Ve(Iye,e)}const Bye=new Set([rj,f2,c2,fy,h2,G$,Y$,d2,ij,H$]),zye=new Set([f2,c2,rj]);function Uf(e){return Oe(e)&&ih(e)==="quantitative"&&!e.bin}function B6(e,t,{orient:n,type:r}){const i=t==="x"?"y":"radius",s=t==="x"&&["bar","area"].includes(r),a=e[t],o=e[i];if(Oe(a)&&Oe(o))if(Uf(a)&&Uf(o)){if(a.stack)return t;if(o.stack)return i;const l=Oe(a)&&!!a.aggregate,u=Oe(o)&&!!o.aggregate;if(l!==u)return l?t:i;if(s){if(n==="vertical")return i;if(n==="horizontal")return t}}else{if(Uf(a))return t;if(Uf(o))return i}else{if(Uf(a))return s&&n==="vertical"?void 0:t;if(Uf(o))return s&&n==="horizontal"?void 0:i}}function jye(e){switch(e){case"x":return"y";case"y":return"x";case"theta":return"radius";case"radius":return"theta"}}function Qj(e,t){var g,v;const n=fo(e)?e:{type:e},r=n.type;if(!Bye.has(r))return null;const i=B6(t,"x",n)||B6(t,"theta",n);if(!i)return null;const s=t[i],a=Oe(s)?ze(s,{}):void 0,o=jye(i),l=[],u=new Set;if(t[o]){const y=t[o],b=Oe(y)?ze(y,{}):void 0;b&&b!==a&&(l.push(o),u.add(b))}const c=o==="x"?"xOffset":"yOffset",f=t[c],d=Oe(f)?ze(f,{}):void 0;d&&d!==a&&(l.push(c),u.add(d));const h=V0e.reduce((y,b)=>{if(b!=="tooltip"&&$c(t,b)){const _=t[b];for(const x of He(_)){const w=va(x);if(w.aggregate)continue;const A=ze(w,{});(!A||!u.has(A))&&y.push({channel:b,fieldDef:w})}}return y},[]);let p;return s.stack!==void 0?xu(s.stack)?p=s.stack?"zero":null:p=s.stack:zye.has(r)&&(p="zero"),!p||!Pye(p)||Mj(t)&&h.length===0?null:((g=s==null?void 0:s.scale)!=null&&g.type&&((v=s==null?void 0:s.scale)==null?void 0:v.type)!==Dr.LINEAR&&s!=null&&s.stack&&Te(h1e(s.scale.type)),$t(t[ko(i)])?(s.stack!==void 0&&Te(d1e(i)),null):(Oe(s)&&s.aggregate&&!ome.has(s.aggregate)&&Te(p1e(s.aggregate)),{groupbyChannels:l,groupbyFields:u,fieldChannel:i,impute:s.impute===null?!1:Lu(r),stackBy:h,offset:p}))}function eU(e,t,n){const r=Fr(e),i=fn("orient",r,n);if(r.orient=Hye(r.type,t,i),i!==void 0&&i!==r.orient&&Te(Kme(r.orient,i)),r.type==="bar"&&r.orient){const l=fn("cornerRadiusEnd",r,n);if(l!==void 0){const u=r.orient==="horizontal"&&t.x2||r.orient==="vertical"&&t.y2?["cornerRadius"]:mve[r.orient];for(const c of u)r[c]=l;r.cornerRadiusEnd!==void 0&&delete r.cornerRadiusEnd}}const s=fn("opacity",r,n),a=fn("fillOpacity",r,n);return s===void 0&&a===void 0&&(r.opacity=qye(r.type,t)),fn("cursor",r,n)===void 0&&(r.cursor=Uye(r,t,n)),r}function Uye(e,t,n){return t.href||e.href||fn("href",e,n)?"pointer":e.cursor}function qye(e,t){if(Ut([h2,H$,G$,Y$],e)&&!Mj(t))return .7}function Wye(e,t,{graticule:n}){if(n)return!1;const r=co("filled",e,t),i=e.type;return Vn(r,i!==h2&&i!==d2&&i!==fy)}function Hye(e,t,n){switch(e){case h2:case G$:case Y$:case ij:case ave:case sve:return}const{x:r,y:i,x2:s,y2:a}=t;switch(e){case f2:if(Oe(r)&&(Cr(r.bin)||Oe(i)&&i.aggregate&&!r.aggregate))return"vertical";if(Oe(i)&&(Cr(i.bin)||Oe(r)&&r.aggregate&&!i.aggregate))return"horizontal";if(a||s){if(n)return n;if(!s)return(Oe(r)&&r.type===nf&&!xn(r.bin)||hy(r))&&Oe(i)&&Cr(i.bin)?"horizontal":"vertical";if(!a)return(Oe(i)&&i.type===nf&&!xn(i.bin)||hy(i))&&Oe(r)&&Cr(r.bin)?"vertical":"horizontal"}case fy:if(s&&!(Oe(r)&&Cr(r.bin))&&a&&!(Oe(i)&&Cr(i.bin)))return;case c2:if(a)return Oe(i)&&Cr(i.bin)?"horizontal":"vertical";if(s)return Oe(r)&&Cr(r.bin)?"vertical":"horizontal";if(e===fy){if(r&&!i)return"vertical";if(i&&!r)return"horizontal"}case d2:case H$:{const o=M6(r),l=M6(i);if(n)return n;if(o&&!l)return e!=="tick"?"horizontal":"vertical";if(!o&&l)return e!=="tick"?"vertical":"horizontal";if(o&&l)return"vertical";{const u=bi(r)&&r.type===nh,c=bi(i)&&i.type===nh;if(u&&!c)return"vertical";if(!u&&c)return"horizontal"}return}}return"vertical"}function Gye(e){const{point:t,line:n,...r}=e;return Fe(r).length>1?r:r.type}function Yye(e){for(const t of["line","area","rule","trail"])e[t]&&(e={...e,[t]:Li(e[t],["point","line"])});return e}function Sx(e,t={},n){return e.point==="transparent"?{opacity:0}:e.point?Ue(e.point)?e.point:{}:e.point!==void 0?null:t.point||n.shape?Ue(t.point)?t.point:{}:void 0}function z6(e,t={}){return e.line?e.line===!0?{}:e.line:e.line!==void 0?null:t.line?t.line===!0?{}:t.line:void 0}class Vye{constructor(){this.name="path-overlay"}hasMatchingType(t,n){if(_l(t)){const{mark:r,encoding:i}=t,s=fo(r)?r:{type:r};switch(s.type){case"line":case"rule":case"trail":return!!Sx(s,n[s.type],i);case"area":return!!Sx(s,n[s.type],i)||!!z6(s,n[s.type])}}return!1}run(t,n,r){const{config:i}=n,{params:s,projection:a,mark:o,name:l,encoding:u,...c}=t,f=_2(u,i),d=fo(o)?o:{type:o},h=Sx(d,i[d.type],f),p=d.type==="area"&&z6(d,i[d.type]),g=[{name:l,...s?{params:s}:{},mark:Gye({...d.type==="area"&&d.opacity===void 0&&d.fillOpacity===void 0?{opacity:.7}:{},...d}),encoding:Li(f,["shape"])}],v=Qj(eU(d,f,i),f);let y=f;if(v){const{fieldChannel:b,offset:_}=v;y={...f,[b]:{...f[b],..._?{stack:_}:{}}}}return y=Li(y,["y2","x2"]),p&&g.push({...a?{projection:a}:{},mark:{type:"line",...Jd(d,["clip","interpolate","tension","tooltip"]),...p},encoding:y}),h&&g.push({...a?{projection:a}:{},mark:{type:"point",opacity:1,filled:!0,...Jd(d,["clip","tooltip"]),...h},encoding:y}),r({...c,layer:g},{...n,config:Yye(i)})}}function Xye(e,t){return t?G0(e)?nU(e,t):tU(e,t):e}function Cx(e,t){return t?nU(e,t):e}function CA(e,t,n){const r=t[e];if(Mve(r)){if(r.repeat in n)return{...t,[e]:n[r.repeat]};Te(Cme(r.repeat));return}return t}function tU(e,t){if(e=CA("field",e,t),e!==void 0){if(e===null)return null;if(e5(e)&&nl(e.sort)){const n=CA("field",e.sort,t);e={...e,...n?{sort:n}:{}}}return e}}function j6(e,t){if(Oe(e))return tU(e,t);{const n=CA("datum",e,t);return n!==e&&!n.type&&(n.type="nominal"),n}}function U6(e,t){if($t(e)){const n=j6(e,t);if(n)return n;if(Y0(e))return{condition:e.condition}}else{if(V0(e)){const n=j6(e.condition,t);if(n)return{...e,condition:n};{const{condition:r,...i}=e;return i}}return e}}function nU(e,t){const n={};for(const r in e)if(De(e,r)){const i=e[r];if(Se(i))n[r]=i.map(s=>U6(s,t)).filter(s=>s);else{const s=U6(i,t);s!==void 0&&(n[r]=s)}}return n}class Kye{constructor(){this.name="RuleForRangedLine"}hasMatchingType(t){if(_l(t)){const{encoding:n,mark:r}=t;if(r==="line"||fo(r)&&r.type==="line")for(const i of H0e){const s=wf(i),a=n[s];if(n[i]&&(Oe(a)&&!Cr(a.bin)||Co(a)))return!0}}return!1}run(t,n,r){const{encoding:i,mark:s}=t;return Te(Xme(!!i.x2,!!i.y2)),r({...t,mark:Ue(s)?{...s,type:"rule"}:"rule"},n)}}class Zye extends p5{constructor(){super(...arguments),this.nonFacetUnitNormalizers=[Qve,nye,uye,new Vye,new Kye]}map(t,n){if(_l(t)){const r=$c(t.encoding,el),i=$c(t.encoding,tl),s=$c(t.encoding,Qb);if(r||i||s)return this.mapFacetedUnit(t,n)}return super.map(t,n)}mapUnit(t,n){const{parentEncoding:r,parentProjection:i}=n,s=Cx(t.encoding,n.repeater),a={...t,...t.name?{name:[n.repeaterPrefix,t.name].filter(l=>l).join("_")}:{},...s?{encoding:s}:{}};if(r||i)return this.mapUnitWithParentEncodingOrProjection(a,n);const o=this.mapLayerOrUnit.bind(this);for(const l of this.nonFacetUnitNormalizers)if(l.hasMatchingType(a,n.config))return l.run(a,n,o);return a}mapRepeat(t,n){return Lye(t)?this.mapLayerRepeat(t,n):this.mapNonLayerRepeat(t,n)}mapLayerRepeat(t,n){const{repeat:r,spec:i,...s}=t,{row:a,column:o,layer:l}=r,{repeater:u={},repeaterPrefix:c=""}=n;return a||o?this.mapRepeat({...t,repeat:{...a?{row:a}:{},...o?{column:o}:{}},spec:{repeat:{layer:l},spec:i}},n):{...s,layer:l.map(f=>{const d={...u,layer:f},h=`${(i.name?`${i.name}_`:"")+c}child__layer_${Cn(f)}`,p=this.mapLayerOrUnit(i,{...n,repeater:d,repeaterPrefix:h});return p.name=h,p})}}mapNonLayerRepeat(t,n){const{repeat:r,spec:i,data:s,...a}=t;!Se(r)&&t.columns&&(t=Li(t,["columns"]),Te(x6("repeat")));const o=[],{repeater:l={},repeaterPrefix:u=""}=n,c=!Se(r)&&r.row||[l?l.row:null],f=!Se(r)&&r.column||[l?l.column:null],d=Se(r)&&r||[l?l.repeat:null];for(const p of d)for(const g of c)for(const v of f){const y={repeat:p,row:g,column:v,layer:l.layer},b=(i.name?`${i.name}_`:"")+u+"child__"+(Se(r)?`${Cn(p)}`:(r.row?`row_${Cn(g)}`:"")+(r.column?`column_${Cn(v)}`:"")),_=this.map(i,{...n,repeater:y,repeaterPrefix:b});_.name=b,o.push(Li(_,["data"]))}const h=Se(r)?t.columns:r.column?r.column.length:1;return{data:i.data??s,align:"all",...a,columns:h,concat:o}}mapFacet(t,n){const{facet:r}=t;return G0(r)&&t.columns&&(t=Li(t,["columns"]),Te(x6("facet"))),super.mapFacet(t,n)}mapUnitWithParentEncodingOrProjection(t,n){const{encoding:r,projection:i}=t,{parentEncoding:s,parentProjection:a,config:o}=n,l=W6({parentProjection:a,projection:i}),u=q6({parentEncoding:s,encoding:Cx(r,n.repeater)});return this.mapUnit({...t,...l?{projection:l}:{},...u?{encoding:u}:{}},{config:o})}mapFacetedUnit(t,n){const{row:r,column:i,facet:s,...a}=t.encoding,{mark:o,width:l,projection:u,height:c,view:f,params:d,encoding:h,...p}=t,{facetMapping:g,layout:v}=this.getFacetMappingAndLayout({row:r,column:i,facet:s},n),y=Cx(a,n.repeater);return this.mapFacet({...p,...v,facet:g,spec:{...l?{width:l}:{},...c?{height:c}:{},...f?{view:f}:{},...u?{projection:u}:{},mark:o,encoding:y,...d?{params:d}:{}}},n)}getFacetMappingAndLayout(t,n){const{row:r,column:i,facet:s}=t;if(r||i){s&&Te(Yme([...r?[el]:[],...i?[tl]:[]]));const a={},o={};for(const l of[el,tl]){const u=t[l];if(u){const{align:c,center:f,spacing:d,columns:h,...p}=u;a[l]=p;for(const g of["align","center","spacing"])u[g]!==void 0&&(o[g]??(o[g]={}),o[g][l]=u[g])}}return{facetMapping:a,layout:o}}else{const{align:a,center:o,spacing:l,columns:u,...c}=s;return{facetMapping:Xye(c,n.repeater),layout:{...a?{align:a}:{},...o?{center:o}:{},...l?{spacing:l}:{},...u?{columns:u}:{}}}}}mapLayer(t,{parentEncoding:n,parentProjection:r,...i}){const{encoding:s,projection:a,...o}=t,l={...i,parentEncoding:q6({parentEncoding:n,encoding:s,layer:!0}),parentProjection:W6({parentProjection:r,projection:a})};return super.mapLayer({...o,...t.name?{name:[l.repeaterPrefix,t.name].filter(u=>u).join("_")}:{}},l)}}function q6({parentEncoding:e,encoding:t={},layer:n}){let r={};if(e){const i=new Set([...Fe(e),...Fe(t)]);for(const s of i){const a=t[s],o=e[s];if($t(a)){const l={...o,...a};r[s]=l}else V0(a)?r[s]={...a,condition:{...o,...a.condition}}:a||a===null?r[s]=a:(n||ma(o)||ot(o)||$t(o)||Se(o))&&(r[s]=o)}}else r=t;return!r||dn(r)?void 0:r}function W6(e){const{parentProjection:t,projection:n}=e;return t&&n&&Te(Lme({parentProjection:t,projection:n})),n??t}function g5(e){return De(e,"filter")}function Jye(e){return De(e,"stop")}function rU(e){return De(e,"lookup")}function Qye(e){return De(e,"data")}function ebe(e){return De(e,"param")}function tbe(e){return De(e,"pivot")}function nbe(e){return De(e,"density")}function rbe(e){return De(e,"quantile")}function ibe(e){return De(e,"regression")}function sbe(e){return De(e,"loess")}function abe(e){return De(e,"sample")}function obe(e){return De(e,"window")}function lbe(e){return De(e,"joinaggregate")}function ube(e){return De(e,"flatten")}function cbe(e){return De(e,"calculate")}function iU(e){return De(e,"bin")}function fbe(e){return De(e,"impute")}function dbe(e){return De(e,"timeUnit")}function hbe(e){return De(e,"aggregate")}function pbe(e){return De(e,"stack")}function gbe(e){return De(e,"fold")}function mbe(e){return De(e,"extent")&&!De(e,"density")&&!De(e,"regression")}function vbe(e){return e.map(t=>g5(t)?{filter:cd(t.filter,U1e)}:t)}class ybe extends p5{map(t,n){return n.emptySelections??(n.emptySelections={}),n.selectionPredicates??(n.selectionPredicates={}),t=H6(t,n),super.map(t,n)}mapLayerOrUnit(t,n){if(t=H6(t,n),t.encoding){const r={};for(const[i,s]of hu(t.encoding))r[i]=sU(s,n);t={...t,encoding:r}}return super.mapLayerOrUnit(t,n)}mapUnit(t,n){const{selection:r,...i}=t;return r?{...i,params:hu(r).map(([s,a])=>{const{init:o,bind:l,empty:u,...c}=a;c.type==="single"?(c.type="point",c.toggle=!1):c.type==="multi"&&(c.type="point"),n.emptySelections[s]=u!=="none";for(const f of Lr(n.selectionPredicates[s]??{}))f.empty=u!=="none";return{name:s,value:o,select:c,bind:l}})}:t}}function H6(e,t){const{transform:n,...r}=e;if(n){const i=n.map(s=>{if(g5(s))return{filter:$A(s,t)};if(iU(s)&&Ef(s.bin))return{...s,bin:aU(s.bin)};if(rU(s)){const{selection:a,...o}=s.from;return a?{...s,from:{param:a,...o}}:s}return s});return{...r,transform:i}}return e}function sU(e,t){var r,i;const n=Ct(e);if(Oe(n)&&Ef(n.bin)&&(n.bin=aU(n.bin)),Cf(n)&&((i=(r=n.scale)==null?void 0:r.domain)!=null&&i.selection)){const{selection:s,...a}=n.scale.domain;n.scale.domain={...a,...s?{param:s}:{}}}if(Y0(n))if(Se(n.condition))n.condition=n.condition.map(s=>{const{selection:a,param:o,test:l,...u}=s;return o?s:{...u,test:$A(s,t)}});else{const{selection:s,param:a,test:o,...l}=sU(n.condition,t);n.condition=a?n.condition:{...l,test:$A(n.condition,t)}}return n}function aU(e){const t=e.extent;if(t!=null&&t.selection){const{selection:n,...r}=t;return{...e,extent:{...r,param:n}}}return e}function $A(e,t){const n=r=>cd(r,i=>{var s;const a=t.emptySelections[i]??!0,o={param:i,empty:a};return(s=t.selectionPredicates)[i]??(s[i]=[]),t.selectionPredicates[i].push(o),o});return e.selection?n(e.selection):cd(e.test||e.filter,r=>r.selection?n(r.selection):r)}class FA extends p5{map(t,n){const r=n.selections??[];if(t.params&&!_l(t)){const i=[];for(const s of t.params)f5(s)?r.push(s):i.push(s);t.params=i}return n.selections=r,super.map(t,n)}mapUnit(t,n){const r=n.selections;if(!r||!r.length)return t;const i=(n.path??[]).concat(t.name),s=[];for(const a of r)if(!a.views||!a.views.length)s.push(a);else for(const o of a.views)(We(o)&&(o===t.name||i.includes(o))||Se(o)&&o.map(l=>i.indexOf(l)).every((l,u,c)=>l!==-1&&(u===0||l>c[u-1])))&&s.push(a);return s.length&&(t.params=s),t}}for(const e of["mapFacet","mapRepeat","mapHConcat","mapVConcat","mapLayer"]){const t=FA.prototype[e];FA.prototype[e]=function(n,r){return t.call(this,n,bbe(n,r))}}function bbe(e,t){return e.name?{...t,path:(t.path??[]).concat(e.name)}:t}function oU(e,t){t===void 0&&(t=Jj(e.config));const n=Ebe(e,t),{width:r,height:i}=e,s=Abe(n,{width:r,height:i,autosize:e.autosize},t);return{...n,...s?{autosize:s}:{}}}const _be=new Zye,xbe=new ybe,wbe=new FA;function Ebe(e,t={}){const n={config:t};return wbe.map(_be.map(xbe.map(e,n),n),n)}function G6(e){return We(e)?{type:e}:e??{}}function Abe(e,t,n){let{width:r,height:i}=t;const s=_l(e)||w2(e),a={};s?r=="container"&&i=="container"?(a.type="fit",a.contains="padding"):r=="container"?(a.type="fit-x",a.contains="padding"):i=="container"&&(a.type="fit-y",a.contains="padding"):(r=="container"&&(Te(v6("width")),r=void 0),i=="container"&&(Te(v6("height")),i=void 0));const o={type:"pad",...a,...n?G6(n.autosize):{},...G6(e.autosize)};if(o.type==="fit"&&!s&&(Te(mme),o.type="pad"),r=="container"&&!(o.type=="fit"||o.type=="fit-x")&&Te(y6("width")),i=="container"&&!(o.type=="fit"||o.type=="fit-y")&&Te(y6("height")),!ns(o,{type:"pad"}))return o}function kbe(e){return["fit","fit-x","fit-y"].includes(e)}function Sbe(e){return e?`fit-${i2(e)}`:"fit"}const Cbe=["background","padding"];function Y6(e,t){const n={};for(const r of Cbe)e&&e[r]!==void 0&&(n[r]=Qi(e[r]));return t&&(n.params=e.params),n}class xl{constructor(t={},n={}){this.explicit=t,this.implicit=n}clone(){return new xl(Ct(this.explicit),Ct(this.implicit))}combine(){return{...this.explicit,...this.implicit}}get(t){return Vn(this.explicit[t],this.implicit[t])}getWithExplicit(t){return this.explicit[t]!==void 0?{explicit:!0,value:this.explicit[t]}:this.implicit[t]!==void 0?{explicit:!1,value:this.implicit[t]}:{explicit:!1,value:void 0}}setWithExplicit(t,{value:n,explicit:r}){n!==void 0&&this.set(t,n,r)}set(t,n,r){return delete this[r?"implicit":"explicit"][t],this[r?"explicit":"implicit"][t]=n,this}copyKeyFromSplit(t,{explicit:n,implicit:r}){n[t]!==void 0?this.set(t,n[t],!0):r[t]!==void 0&&this.set(t,r[t],!1)}copyKeyFromObject(t,n){n[t]!==void 0&&this.set(t,n[t],!0)}copyAll(t){for(const n of Fe(t.combine())){const r=t.getWithExplicit(n);this.setWithExplicit(n,r)}}}function Pa(e){return{explicit:!0,value:e}}function Vi(e){return{explicit:!1,value:e}}function lU(e){return(t,n,r,i)=>{const s=e(t.value,n.value);return s>0?t:s<0?n:E2(t,n,r,i)}}function E2(e,t,n,r){return e.explicit&&t.explicit&&Te(s1e(n,r,e.value,t.value)),e}function mu(e,t,n,r,i=E2){return e===void 0||e.value===void 0?t:e.explicit&&!t.explicit?e:t.explicit&&!e.explicit?t:ns(e.value,t.value)?e:i(e,t,n,r)}class $be extends xl{constructor(t={},n={},r=!1){super(t,n),this.explicit=t,this.implicit=n,this.parseNothing=r}clone(){const t=super.clone();return t.parseNothing=this.parseNothing,t}}function oh(e){return De(e,"url")}function qg(e){return De(e,"values")}function uU(e){return De(e,"name")&&!oh(e)&&!qg(e)&&!eu(e)}function eu(e){return e&&(cU(e)||fU(e)||m5(e))}function cU(e){return De(e,"sequence")}function fU(e){return De(e,"sphere")}function m5(e){return De(e,"graticule")}var Tn;(function(e){e[e.Raw=0]="Raw",e[e.Main=1]="Main",e[e.Row=2]="Row",e[e.Column=3]="Column",e[e.Lookup=4]="Lookup",e[e.PreFilterInvalid=5]="PreFilterInvalid",e[e.PostFilterInvalid=6]="PostFilterInvalid"})(Tn||(Tn={}));function dU({invalid:e,isPath:t}){switch(oj(e,{isPath:t})){case"filter":return{marks:"exclude-invalid-values",scales:"exclude-invalid-values"};case"break-paths-show-domains":return{marks:t?"include-invalid-values":"exclude-invalid-values",scales:"include-invalid-values"};case"break-paths-filter-domains":return{marks:t?"include-invalid-values":"exclude-invalid-values",scales:"exclude-invalid-values"};case"show":return{marks:"include-invalid-values",scales:"include-invalid-values"}}}function Fbe(e){const{marks:t,scales:n}=dU(e);return t===n?Tn.Main:n==="include-invalid-values"?Tn.PreFilterInvalid:Tn.PostFilterInvalid}class cn{constructor(t,n){this.debugName=n,this._children=[],this._parent=null,t&&(this.parent=t)}clone(){throw new Error("Cannot clone node")}get parent(){return this._parent}set parent(t){this._parent=t,t&&t.addChild(this)}get children(){return this._children}numChildren(){return this._children.length}addChild(t,n){if(this._children.includes(t)){Te(Rme);return}n!==void 0?this._children.splice(n,0,t):this._children.push(t)}removeChild(t){const n=this._children.indexOf(t);return this._children.splice(n,1),n}remove(){let t=this._parent.removeChild(this);for(const n of this._children)n._parent=this._parent,this._parent.addChild(n,t++)}insertAsParentOf(t){const n=t.parent;n.removeChild(this),this.parent=n,t.parent=this}swapWithParent(){const t=this._parent,n=t.parent;for(const i of this._children)i.parent=t;this._children=[],t.removeChild(this);const r=t.parent.removeChild(t);this._parent=n,n.addChild(this,r),t.parent=this}}class Ii extends cn{clone(){const t=new this.constructor;return t.debugName=`clone_${this.debugName}`,t._source=this._source,t._name=`clone_${this._name}`,t.type=this.type,t.refCounts=this.refCounts,t.refCounts[t._name]=0,t}constructor(t,n,r,i){super(t,n),this.type=r,this.refCounts=i,this._source=this._name=n,this.refCounts&&!(this._name in this.refCounts)&&(this.refCounts[this._name]=0)}dependentFields(){return new Set}producedFields(){return new Set}hash(){return this._hash===void 0&&(this._hash=`Output ${lz()}`),this._hash}getSource(){return this.refCounts[this._name]++,this._source}isRequired(){return!!this.refCounts[this._name]}setSource(t){this._source=t}}function $x(e){return e.as!==void 0}function V6(e){return`${e}_end`}class eo extends cn{clone(){return new eo(null,Ct(this.timeUnits))}constructor(t,n){super(t),this.timeUnits=n}static makeFromEncoding(t,n){const r=n.reduceFieldDef((i,s,a)=>{const{field:o,timeUnit:l}=s;if(l){let u;if(Sf(l)){if(Dn(n)){const{mark:c,markDef:f,config:d}=n,h=gu({fieldDef:s,markDef:f,config:d});(Ug(c)||h)&&(u={timeUnit:xr(l),field:o})}}else u={as:ze(s,{forAs:!0}),field:o,timeUnit:l};if(Dn(n)){const{mark:c,markDef:f,config:d}=n,h=gu({fieldDef:s,markDef:f,config:d});Ug(c)&&Xn(a)&&h!==.5&&(u.rectBandPosition=h)}u&&(i[Gt(u)]=u)}return i},{});return dn(r)?null:new eo(t,r)}static makeFromTransform(t,n){const{timeUnit:r,...i}={...n},s=xr(r),a={...i,timeUnit:s};return new eo(t,{[Gt(a)]:a})}merge(t){this.timeUnits={...this.timeUnits};for(const n in t.timeUnits)this.timeUnits[n]||(this.timeUnits[n]=t.timeUnits[n]);for(const n of t.children)t.removeChild(n),n.parent=this;t.remove()}removeFormulas(t){const n={};for(const[r,i]of hu(this.timeUnits)){const s=$x(i)?i.as:`${i.field}_end`;t.has(s)||(n[r]=i)}this.timeUnits=n}producedFields(){return new Set(Lr(this.timeUnits).map(t=>$x(t)?t.as:V6(t.field)))}dependentFields(){return new Set(Lr(this.timeUnits).map(t=>t.field))}hash(){return`TimeUnit ${Gt(this.timeUnits)}`}assemble(){const t=[];for(const n of Lr(this.timeUnits)){const{rectBandPosition:r}=n,i=xr(n.timeUnit);if($x(n)){const{field:s,as:a}=n,{unit:o,utc:l,...u}=i,c=[a,`${a}_end`];t.push({field:Ps(s),type:"timeunit",...o?{units:l2(o)}:{},...l?{timezone:"utc"}:{},...u,as:c}),t.push(...X6(c,r,i))}else if(n){const{field:s}=n,a=s.replaceAll("\\.","."),o=hU({timeUnit:i,field:a}),l=V6(a);t.push({type:"formula",expr:o,as:l}),t.push(...X6([a,l],r,i))}}return t}}const A2="offsetted_rect_start",k2="offsetted_rect_end";function hU({timeUnit:e,field:t,reverse:n}){const{unit:r,utc:i}=e,s=qz(r),{part:a,step:o}=Yz(s,e.step);return`${i?"utcOffset":"timeOffset"}('${a}', ${sn(t)}, ${n?-o:o})`}function X6([e,t],n,r){if(n!==void 0&&n!==.5){const i=sn(e),s=sn(t);return[{type:"formula",expr:K6([hU({timeUnit:r,field:e,reverse:!0}),i],n+.5),as:`${e}_${A2}`},{type:"formula",expr:K6([i,s],n+.5),as:`${e}_${k2}`}]}return[]}function K6([e,t],n){return`${1-n} * ${e} + ${n} * ${t}`}const Z0="_tuple_fields";class Dbe{constructor(...t){this.items=t,this.hasChannel={},this.hasField={},this.hasSelectionId=!1}}const Mbe={defined:()=>!0,parse:(e,t,n)=>{const r=t.name,i=t.project??(t.project=new Dbe),s={},a={},o=new Set,l=(p,g)=>{const v=g==="visual"?p.channel:p.field;let y=Cn(`${r}_${v}`);for(let b=1;o.has(y);b++)y=Cn(`${r}_${v}_${b}`);return o.add(y),{[g]:y}},u=t.type,c=e.config.selection[u],f=n.value!==void 0?He(n.value):null;let{fields:d,encodings:h}=Ue(n.select)?n.select:{};if(!d&&!h&&f){for(const p of f)if(Ue(p))for(const g of Fe(p))W0e(g)?(h||(h=[])).push(g):u==="interval"?(Te(Sme),h=c.encodings):(d??(d=[])).push(g)}!d&&!h&&(h=c.encodings,"fields"in c&&(d=c.fields));for(const p of h??[]){const g=e.fieldDef(p);if(g){let v=g.field;if(g.aggregate){Te(vme(p,g.aggregate));continue}else if(!v){Te(_6(p));continue}if(g.timeUnit&&!Sf(g.timeUnit)){v=e.vgField(p);const y={timeUnit:g.timeUnit,as:v,field:g.field};a[Gt(y)]=y}if(!s[v]){const y=u==="interval"&&So(p)&&ga(e.getScaleComponent(p).get("type"))?"R":g.bin?"R-RE":"E",b={field:v,channel:p,type:y,index:i.items.length};b.signals={...l(b,"data"),...l(b,"visual")},i.items.push(s[v]=b),i.hasField[v]=s[v],i.hasSelectionId=i.hasSelectionId||v===ya,pz(p)?(b.geoChannel=p,b.channel=hz(p),i.hasChannel[b.channel]=s[v]):i.hasChannel[p]=s[v]}}else Te(_6(p))}for(const p of d??[]){if(i.hasField[p])continue;const g={type:"E",field:p,index:i.items.length};g.signals={...l(g,"data")},i.items.push(g),i.hasField[p]=g,i.hasSelectionId=i.hasSelectionId||p===ya}f&&(t.init=f.map(p=>i.items.map(g=>Ue(p)?p[g.geoChannel||g.channel]!==void 0?p[g.geoChannel||g.channel]:p[g.field]:p))),dn(a)||(i.timeUnit=new eo(null,a))},signals:(e,t,n)=>{const r=t.name+Z0;return n.filter(s=>s.name===r).length>0||t.project.hasSelectionId?n:n.concat({name:r,value:t.project.items.map(vU)})}},pU="_curr",L1="anim_value",Xf="anim_clock",DA="eased_anim_clock",gU="min_extent",mU="max_range_extent",Fx="last_tick_at",Dx="is_playing",Tbe=1/60*1e3,Rbe=(e,t)=>[{name:DA,update:Xf},{name:`${e}_domain`,init:`domain('${t}')`},{name:gU,init:`extent(${e}_domain)[0]`},{name:mU,init:`extent(range('${t}'))[1]`},{name:L1,update:`invert('${t}', ${DA})`}],Nbe={defined:e=>e.type==="point",topLevelSignals:(e,t,n)=>(to(t)&&(n=n.concat([{name:Xf,init:"0",on:[{events:{type:"timer",throttle:Tbe},update:`${Dx} ? (${Xf} + (now() - ${Fx}) > ${mU} ? 0 : ${Xf} + (now() - ${Fx})) : ${Xf}`}]},{name:Fx,init:"now()",on:[{events:[{signal:Xf},{signal:Dx}],update:"now()"}]},{name:Dx,init:"true"}])),n),signals:(e,t,n)=>{const r=t.name,i=r+Z0,s=t.project,a="(item().isVoronoi ? datum.datum : datum)",o=Lr(e.component.selection??{}).reduce((c,f)=>f.type==="interval"?c.concat(f.name+hd):c,[]).map(c=>`indexof(item().mark.name, '${c}') < 0`).join(" && "),l=`datum && item().mark.marktype !== 'group' && indexof(item().mark.role, 'legend') < 0${o?` && ${o}`:""}`;let u=`unit: ${Fc(e)}, `;if(t.project.hasSelectionId)u+=`${ya}: ${a}[${Pe(ya)}]`;else if(to(t))u+=`fields: ${i}, values: [${L1} ? ${L1} : ${gU}]`;else{const c=s.items.map(f=>{const d=e.fieldDef(f.channel);return d!=null&&d.bin?`[${a}[${Pe(e.vgField(f.channel,{}))}], ${a}[${Pe(e.vgField(f.channel,{binSuffix:"end"}))}]]`:`${a}[${Pe(f.field)}]`}).join(", ");u+=`fields: ${i}, values: [${c}]`}if(to(t))return n.concat(Rbe(t.name,e.scaleName(Du)),[{name:r+dl,on:[{events:[{signal:DA},{signal:L1}],update:`{${u}}`,force:!0}]}]);{const c=t.events;return n.concat([{name:r+dl,on:c?[{events:c,update:`${l} ? {${u}} : null`,force:!0}]:[]}])}}};function vU(e){const{signals:t,hasLegend:n,index:r,...i}=e;return i.field=Ps(i.field),i}function af(e,t=!0,n=ei){if(Se(e)){const r=e.map(i=>af(i,t,n));return t?`[${r.join(", ")}]`:r}else if(kf(e))return n(t?tf(e):D1e(e));return t?n(hn(e)):e}function Obe(e,t){for(const n of Lr(e.component.selection??{})){const r=n.name;let i=`${r}${dl}, ${n.resolve==="global"?"true":`{unit: ${Fc(e)}}`}`;for(const s of C2)s.defined(n)&&(s.signals&&(t=s.signals(e,n,t)),s.modifyExpr&&(i=s.modifyExpr(e,n,i)));t.push({name:r+l2e,on:[{events:{signal:n.name+dl},update:`modify(${Pe(n.name+of)}, ${i})`}]})}return v5(t)}function Lbe(e,t){if(e.component.selection&&Fe(e.component.selection).length){const n=Pe(e.getName("cell"));t.unshift({name:"facet",value:{},on:[{events:$u("pointermove","scope"),update:`isTuple(facet) ? facet : group(${n}).datum`}]})}return v5(t)}function Ibe(e,t){let n=!1;for(const r of Lr(e.component.selection??{})){const i=r.name,s=Pe(i+of);if(t.filter(o=>o.name===i).length===0){const o=r.resolve==="global"?"union":r.resolve,l=r.type==="point"?", true, true)":")";t.push({name:r.name,update:`${NU}(${s}, ${Pe(o)}${l}`})}n=!0;for(const o of C2)o.defined(r)&&o.topLevelSignals&&(t=o.topLevelSignals(e,r,t))}return n&&t.filter(i=>i.name==="unit").length===0&&t.unshift({name:"unit",value:{},on:[{events:"pointermove",update:"isTuple(group()) ? group() : unit"}]}),v5(t)}function Pbe(e,t){const n=[],r=[],i=Fc(e,{escape:!1});for(const s of Lr(e.component.selection??{})){const a={name:s.name+of};if(s.project.hasSelectionId&&(a.transform=[{type:"collect",sort:{field:ya}}]),s.init){const l=s.project.items.map(vU);a.values=s.project.hasSelectionId?s.init.map(u=>({unit:i,[ya]:af(u,!1)[0]})):s.init.map(u=>({unit:i,fields:l,values:af(u,!1)}))}if([...n,...t].filter(l=>l.name===s.name+of).length||n.push(a),to(s)&&t.length){const l=e.lookupDataSource(e.getDataName(Tn.Main)),u=t.find(f=>f.name===l),c=u.transform.find(f=>f.type==="filter"&&f.expr.includes("vlSelectionTest"));if(c){u.transform=u.transform.filter(d=>d!==c);const f={name:u.name+pU,source:u.name,transform:[c]};r.push(f)}}}return n.concat(t,r)}function yU(e,t){for(const n of Lr(e.component.selection??{}))for(const r of C2)r.defined(n)&&r.marks&&(t=r.marks(e,n,t));return t}function Bbe(e,t){for(const n of e.children)Dn(n)&&(t=yU(n,t));return t}function zbe(e,t,n,r){const i=HU(e,t.param,t);return{signal:ga(n.get("type"))&&Se(r)&&r[0]>r[1]?`isValid(${i}) && reverse(${i})`:i}}function v5(e){return e.map(t=>(t.on&&!t.on.length&&delete t.on,t))}const rl={defined:e=>e.type==="interval"&&e.resolve==="global"&&e.bind&&e.bind==="scales",parse:(e,t)=>{const n=t.scales=[];for(const r of t.project.items){const i=r.channel;if(!So(i))continue;const s=e.getScaleComponent(i),a=s?s.get("type"):void 0;if(a=="sequential"&&Te(xme),!s||!ga(a)){Te(_me);continue}s.set("selectionExtent",{param:t.name,field:r.field},!0),n.push(r)}},topLevelSignals:(e,t,n)=>{const r=t.scales.filter(a=>n.filter(o=>o.name===a.signals.data).length===0);if(!e.parent||TA(e)||r.length===0)return n;const i=n.find(a=>a.name===t.name);let s=i.update;if(s.includes(NU))i.update=`{${r.map(a=>`${Pe(Ps(a.field))}: ${a.signals.data}`).join(", ")}}`;else{for(const a of r){const o=`${Pe(Ps(a.field))}: ${a.signals.data}`;s.includes(o)||(s=`${s.substring(0,s.length-1)}, ${o}}`)}i.update=s}return n.concat(r.map(a=>({name:a.signals.data})))},signals:(e,t,n)=>{if(e.parent&&!TA(e))for(const r of t.scales){const i=n.find(s=>s.name===r.signals.data);i.push="outer",delete i.value,delete i.update}return n}};function MA(e,t){return`domain(${Pe(e.scaleName(t))})`}function TA(e){return e.parent&&Uh(e.parent)&&(!e.parent.parent||TA(e.parent.parent))}const hd="_brush",bU="_scale_trigger",mp="geo_interval_init_tick",_U="_init",jbe="_center",Ube={defined:e=>e.type==="interval",parse:(e,t,n)=>{var r;if(e.hasProjection){const i={...Ue(n.select)?n.select:{}};i.fields=[ya],i.encodings||(i.encodings=n.value?Fe(n.value):[ka,Aa]),n.select={type:"interval",...i}}if(t.translate&&!rl.defined(t)){const i=`!event.item || event.item.mark.name !== ${Pe(t.name+hd)}`;for(const s of t.events){if(!s.between){Te(`${s} is not an ordered event stream for interval selections.`);continue}const a=He((r=s.between[0]).filter??(r.filter=[]));a.includes(i)||a.push(i)}}},signals:(e,t,n)=>{const r=t.name,i=r+dl,s=Lr(t.project.hasChannel).filter(o=>o.channel===$n||o.channel===kr),a=t.init?t.init[0]:null;if(n.push(...s.reduce((o,l)=>o.concat(qbe(e,t,l,a&&a[l.index])),[])),e.hasProjection){const o=Pe(e.projectionName()),l=e.projectionName()+jbe,{x:u,y:c}=t.project.hasChannel,f=u&&u.signals.visual,d=c&&c.signals.visual,h=u?a&&a[u.index]:`${l}[0]`,p=c?a&&a[c.index]:`${l}[1]`,g=w=>e.getSizeSignalRef(w).signal,v=`[[${f?f+"[0]":"0"}, ${d?d+"[0]":"0"}],[${f?f+"[1]":g("width")}, ${d?d+"[1]":g("height")}]]`;a&&(n.unshift({name:r+_U,init:`[scale(${o}, [${u?h[0]:h}, ${c?p[0]:p}]), scale(${o}, [${u?h[1]:h}, ${c?p[1]:p}])]`}),(!u||!c)&&(n.find(A=>A.name===l)||n.unshift({name:l,update:`invert(${o}, [${g("width")}/2, ${g("height")}/2])`})));const y=`intersect(${v}, {markname: ${Pe(e.getName("marks"))}}, unit.mark)`,b=`{unit: ${Fc(e)}}`,_=`vlSelectionTuples(${y}, ${b})`,x=s.map(w=>w.signals.visual);return n.concat({name:i,on:[{events:[...x.length?[{signal:x.join(" || ")}]:[],...a?[{signal:mp}]:[]],update:_}]})}else{if(!rl.defined(t)){const u=r+bU,c=s.map(f=>{const d=f.channel,{data:h,visual:p}=f.signals,g=Pe(e.scaleName(d)),v=e.getScaleComponent(d).get("type"),y=ga(v)?"+":"";return`(!isArray(${h}) || (${y}invert(${g}, ${p})[0] === ${y}${h}[0] && ${y}invert(${g}, ${p})[1] === ${y}${h}[1]))`});c.length&&n.push({name:u,value:{},on:[{events:s.map(f=>({scale:e.scaleName(f.channel)})),update:c.join(" && ")+` ? ${u} : {}`}]})}const o=s.map(u=>u.signals.data),l=`unit: ${Fc(e)}, fields: ${r+Z0}, values`;return n.concat({name:i,...a?{init:`{${l}: ${af(a)}}`}:{},...o.length?{on:[{events:[{signal:o.join(" || ")}],update:`${o.join(" && ")} ? {${l}: [${o}]} : null`}]}:{}})}},topLevelSignals:(e,t,n)=>(Dn(e)&&e.hasProjection&&t.init&&(n.filter(i=>i.name===mp).length||n.unshift({name:mp,value:null,on:[{events:"timer{1}",update:`${mp} === null ? {} : ${mp}`}]})),n),marks:(e,t,n)=>{const r=t.name,{x:i,y:s}=t.project.hasChannel,a=i==null?void 0:i.signals.visual,o=s==null?void 0:s.signals.visual,l=`data(${Pe(t.name+of)})`;if(rl.defined(t)||!i&&!s)return n;const u={x:i!==void 0?{signal:`${a}[0]`}:{value:0},y:s!==void 0?{signal:`${o}[0]`}:{value:0},x2:i!==void 0?{signal:`${a}[1]`}:{field:{group:"width"}},y2:s!==void 0?{signal:`${o}[1]`}:{field:{group:"height"}}};if(t.resolve==="global")for(const v of Fe(u))u[v]=[{test:`${l}.length && ${l}[0].unit === ${Fc(e)}`,...u[v]},{value:0}];const{fill:c,fillOpacity:f,cursor:d,...h}=t.mark,p=Fe(h).reduce((v,y)=>(v[y]=[{test:[i!==void 0&&`${a}[0] !== ${a}[1]`,s!==void 0&&`${o}[0] !== ${o}[1]`].filter(b=>b).join(" && "),value:h[y]},{value:null}],v),{}),g=d??(t.translate?"move":null);return[{name:`${r+hd}_bg`,type:"rect",clip:!0,encode:{enter:{fill:{value:c},fillOpacity:{value:f}},update:u}},...n,{name:r+hd,type:"rect",clip:!0,encode:{enter:{...g?{cursor:{value:g}}:{},fill:{value:"transparent"}},update:{...u,...p}}}]}};function qbe(e,t,n,r){const i=!e.hasProjection,s=n.channel,a=n.signals.visual,o=Pe(i?e.scaleName(s):e.projectionName()),l=d=>`scale(${o}, ${d})`,u=e.getSizeSignalRef(s===$n?"width":"height").signal,c=`${s}(unit)`,f=t.events.reduce((d,h)=>[...d,{events:h.between[0],update:`[${c}, ${c}]`},{events:h,update:`[${a}[0], clamp(${c}, 0, ${u})]`}],[]);if(i){const d=n.signals.data,h=rl.defined(t),p=e.getScaleComponent(s),g=p?p.get("type"):void 0,v=r?{init:af(r,!0,l)}:{value:[]};return f.push({events:{signal:t.name+bU},update:ga(g)?`[${l(`${d}[0]`)}, ${l(`${d}[1]`)}]`:"[0, 0]"}),h?[{name:d,on:[]}]:[{name:a,...v,on:f},{name:d,...r?{init:af(r)}:{},on:[{events:{signal:a},update:`${a}[0] === ${a}[1] ? null : invert(${o}, ${a})`}]}]}else{const d=s===$n?0:1,h=t.name+_U,p=r?{init:`[${h}[0][${d}], ${h}[1][${d}]]`}:{value:[]};return[{name:a,...p,on:f}]}}function Ph({model:e,channelDef:t,vgChannel:n,invalidValueRef:r,mainRefFn:i}){const s=Y0(t)&&t.condition;let a=[];s&&(a=He(s).map(u=>{const c=i(u);if(Dve(u)){const{param:f,empty:d}=u;return{test:WU(e,{param:f,empty:d}),...c}}else return{test:wy(e,u.test),...c}})),r!==void 0&&a.push(r);const o=i(t);return o!==void 0&&a.push(o),a.length>1||a.length===1&&a[0].test?{[n]:a}:a.length===1?{[n]:a[0]}:{}}function y5(e,t="text"){const n=e.encoding[t];return Ph({model:e,channelDef:n,vgChannel:t,mainRefFn:r=>S2(r,e.config),invalidValueRef:void 0})}function S2(e,t,n="datum"){if(e){if(ma(e))return En(e.value);if($t(e)){const{format:r,formatType:i}=gy(e);return J$({fieldOrDatumDef:e,format:r,formatType:i,expr:n,config:t})}}}function xU(e,t={}){const{encoding:n,markDef:r,config:i,stack:s}=e,a=n.tooltip;if(Se(a))return{tooltip:Z6({tooltip:a},s,i,t)};{const o=t.reactiveGeom?"datum.datum":"datum";return Ph({model:e,channelDef:a,vgChannel:"tooltip",mainRefFn:u=>{const c=S2(u,i,o);if(c)return c;if(u===null)return;let f=fn("tooltip",r,i);if(f===!0&&(f={content:"encoding"}),We(f))return{value:f};if(Ue(f))return ot(f)?f:f.content==="encoding"?Z6(n,s,i,t):{signal:o}},invalidValueRef:void 0})}}function wU(e,t,n,{reactiveGeom:r}={}){const i={...n,...n.tooltipFormat},s=new Set,a=r?"datum.datum":"datum",o=[];function l(c,f){const d=wf(f),h=bi(c)?c:{...c,type:e[d].type},p=h.title||n5(h,i),g=He(p).join(", ").replaceAll(/"/g,'\\"');let v;if(Xn(f)){const y=f==="x"?"x2":"y2",b=va(e[y]);if(Cr(h.bin)&&b){const _=ze(h,{expr:a}),x=ze(b,{expr:a}),{format:w,formatType:A}=gy(h);v=H0(_,x,w,A,i),s.add(y)}}if((Xn(f)||f===js||f===Ea)&&t&&t.fieldChannel===f&&t.offset==="normalize"){const{format:y,formatType:b}=gy(h);v=J$({fieldOrDatumDef:h,format:y,formatType:b,expr:a,config:i,normalizeStack:!0}).signal}v??(v=S2(h,i,a).signal),o.push({channel:f,key:g,value:v})}i5(e,(c,f)=>{Oe(c)?l(c,f):m2(c)&&l(c.condition,f)});const u={};for(const{channel:c,key:f,value:d}of o)!s.has(c)&&!u[f]&&(u[f]=d);return u}function Z6(e,t,n,{reactiveGeom:r}={}){const i=wU(e,t,n,{reactiveGeom:r}),s=hu(i).map(([a,o])=>`"${a}": ${o}`);return s.length>0?{signal:`{${s.join(", ")}}`}:void 0}function Wbe(e){const{markDef:t,config:n}=e,r=fn("aria",t,n);return r===!1?{}:{...r?{aria:r}:{},...Hbe(e),...Gbe(e)}}function Hbe(e){const{mark:t,markDef:n,config:r}=e;if(r.aria===!1)return{};const i=fn("ariaRoleDescription",n,r);return i!=null?{ariaRoleDescription:{value:i}}:Ve(hme,t)?{}:{ariaRoleDescription:{value:t}}}function Gbe(e){const{encoding:t,markDef:n,config:r,stack:i}=e,s=t.description;if(s)return Ph({model:e,channelDef:s,vgChannel:"description",mainRefFn:l=>S2(l,e.config),invalidValueRef:void 0});const a=fn("description",n,r);if(a!=null)return{description:En(a)};if(r.aria===!1)return{};const o=wU(t,i,r);if(!dn(o))return{description:{signal:hu(o).map(([l,u],c)=>`"${c>0?"; ":""}${l}: " + (${u})`).join(" + ")}}}function Mr(e,t,n={}){const{markDef:r,encoding:i,config:s}=t,{vgChannel:a}=n;let{defaultRef:o,defaultValue:l}=n;const u=i[e];o===void 0&&(l??(l=fn(e,r,s,{vgChannel:a,ignoreVgConfig:!Y0(u)})),l!==void 0&&(o=En(l)));const c={markDef:r,config:s,scaleName:t.scaleName(e),scale:t.getScaleComponent(e)},f=uj({...c,scaleChannel:e,channelDef:u});return Ph({model:t,channelDef:u,vgChannel:a??e,invalidValueRef:f,mainRefFn:h=>Z$({...c,channel:e,channelDef:h,stack:null,defaultRef:o})})}function EU(e,t={filled:void 0}){const{markDef:n,encoding:r,config:i}=e,{type:s}=n,a=t.filled??fn("filled",n,i),o=Ut(["bar","point","circle","square","geoshape"],s)?"transparent":void 0,l=fn(a===!0?"color":void 0,n,i,{vgChannel:"fill"})??i.mark[a===!0&&"color"]??o,u=fn(a===!1?"color":void 0,n,i,{vgChannel:"stroke"})??i.mark[a===!1&&"color"],c=a?"fill":"stroke",f={...l?{fill:En(l)}:{},...u?{stroke:En(u)}:{}};return n.color&&(a?n.fill:n.stroke)&&Te(Nz("property",{fill:"fill"in n,stroke:"stroke"in n})),{...f,...Mr("color",e,{vgChannel:c,defaultValue:a?l:u}),...Mr("fill",e,{defaultValue:r.fill?l:void 0}),...Mr("stroke",e,{defaultValue:r.stroke?u:void 0})}}function Ybe(e){const{encoding:t,mark:n}=e,r=t.order;return!Lu(n)&&ma(r)?Ph({model:e,channelDef:r,vgChannel:"zindex",mainRefFn:i=>En(i.value),invalidValueRef:void 0}):{}}function lh({channel:e,markDef:t,encoding:n={},model:r,bandPosition:i}){const s=`${e}Offset`,a=t[s],o=n[s];if((s==="xOffset"||s==="yOffset")&&o)return{offsetType:"encoding",offset:Z$({channel:s,channelDef:o,markDef:t,config:r==null?void 0:r.config,scaleName:r.scaleName(s),scale:r.getScaleComponent(s),stack:null,defaultRef:En(a),bandPosition:i})};const l=t[s];return l?{offsetType:"visual",offset:l}:{}}function pi(e,t,{defaultPos:n,vgChannel:r}){const{encoding:i,markDef:s,config:a,stack:o}=t,l=i[e],u=i[ko(e)],c=t.scaleName(e),f=t.getScaleComponent(e),{offset:d,offsetType:h}=lh({channel:e,markDef:s,encoding:i,model:t,bandPosition:.5}),p=b5({model:t,defaultPos:n,channel:e,scaleName:c,scale:f}),g=!l&&Xn(e)&&(i.latitude||i.longitude)?{field:t.getName(e)}:Vbe({channel:e,channelDef:l,channel2Def:u,markDef:s,config:a,scaleName:c,scale:f,stack:o,offset:d,defaultRef:p,bandPosition:h==="encoding"?0:void 0});return g?{[r||e]:g}:void 0}function Vbe(e){const{channel:t,channelDef:n,scaleName:r,stack:i,offset:s,markDef:a}=e;if($t(n)&&i&&t===i.fieldChannel){if(Oe(n)){let o=n.bandPosition;if(o===void 0&&a.type==="text"&&(t==="radius"||t==="theta")&&(o=.5),o!==void 0)return dy({scaleName:r,fieldOrDatumDef:n,startSuffix:"start",bandPosition:o,offset:s})}return Cc(n,r,{suffix:"end"},{offset:s})}return K$(e)}function b5({model:e,defaultPos:t,channel:n,scaleName:r,scale:i}){const{markDef:s,config:a}=e;return()=>{const o=wf(n),l=pu(n),u=fn(n,s,a,{vgChannel:l});if(u!==void 0)return cg(n,u);switch(t){case"zeroOrMin":return J6({scaleName:r,scale:i,mode:"zeroOrMin",mainChannel:o,config:a});case"zeroOrMax":return J6({scaleName:r,scale:i,mode:{zeroOrMax:{widthSignal:e.width.signal,heightSignal:e.height.signal}},mainChannel:o,config:a});case"mid":return{...e[qi(n)],mult:.5}}}}function J6({mainChannel:e,config:t,...n}){const r=lj(n),{mode:i}=n;if(r)return r;switch(e){case"radius":{if(i==="zeroOrMin")return{value:0};const{widthSignal:s,heightSignal:a}=i.zeroOrMax;return{signal:`min(${s},${a})/2`}}case"theta":return i==="zeroOrMin"?{value:0}:{signal:"2*PI"};case"x":return i==="zeroOrMin"?{value:0}:{field:{group:"width"}};case"y":return i==="zeroOrMin"?{field:{group:"height"}}:{value:0}}}const Xbe={left:"x",center:"xc",right:"x2"},Kbe={top:"y",middle:"yc",bottom:"y2"};function AU(e,t,n,r="middle"){if(e==="radius"||e==="theta")return pu(e);const i=e==="x"?"align":"baseline",s=fn(i,t,n);let a;return ot(s)?(Te(Vme(i)),a=void 0):a=s,e==="x"?Xbe[a||(r==="top"?"left":"center")]:Kbe[a||r]}function by(e,t,{defaultPos:n,defaultPos2:r,range:i}){return i?kU(e,t,{defaultPos:n,defaultPos2:r}):pi(e,t,{defaultPos:n})}function kU(e,t,{defaultPos:n,defaultPos2:r}){const{markDef:i,config:s}=t,a=ko(e),o=qi(e),l=Zbe(t,r,a),u=l[o]?AU(e,i,s):pu(e);return{...pi(e,t,{defaultPos:n,vgChannel:u}),...l}}function Zbe(e,t,n){const{encoding:r,mark:i,markDef:s,stack:a,config:o}=e,l=wf(n),u=qi(n),c=pu(n),f=r[l],d=e.scaleName(l),h=e.getScaleComponent(l),{offset:p}=n in r||n in s?lh({channel:n,markDef:s,encoding:r,model:e}):lh({channel:l,markDef:s,encoding:r,model:e});if(!f&&(n==="x2"||n==="y2")&&(r.latitude||r.longitude)){const v=qi(n),y=e.markDef[v];return y!=null?{[v]:{value:y}}:{[c]:{field:e.getName(n)}}}const g=Jbe({channel:n,channelDef:f,channel2Def:r[n],markDef:s,config:o,scaleName:d,scale:h,stack:a,offset:p,defaultRef:void 0});return g!==void 0?{[c]:g}:zm(n,s)||zm(n,{[n]:bA(n,s,o.style),[u]:bA(u,s,o.style)})||zm(n,o[i])||zm(n,o.mark)||{[c]:b5({model:e,defaultPos:t,channel:n,scaleName:d,scale:h})()}}function Jbe({channel:e,channelDef:t,channel2Def:n,markDef:r,config:i,scaleName:s,scale:a,stack:o,offset:l,defaultRef:u}){return $t(t)&&o&&e.charAt(0)===o.fieldChannel.charAt(0)?Cc(t,s,{suffix:"start"},{offset:l}):K$({channel:e,channelDef:n,scaleName:s,scale:a,stack:o,markDef:r,config:i,offset:l,defaultRef:u})}function zm(e,t){const n=qi(e),r=pu(e);if(t[r]!==void 0)return{[r]:cg(e,t[r])};if(t[e]!==void 0)return{[r]:cg(e,t[e])};if(t[n]){const i=t[n];if(rf(i))Te(Ume(n));else return{[n]:cg(e,i)}}}function fl(e,t){const{config:n,encoding:r,markDef:i}=e,s=i.type,a=ko(t),o=qi(t),l=r[t],u=r[a],c=e.getScaleComponent(t),f=c?c.get("type"):void 0,d=i.orient,h=r[o]??r.size??fn("size",i,n,{vgChannel:o}),p=yz(t),g=s==="bar"&&(t==="x"?d==="vertical":d==="horizontal")||s==="tick"&&(t==="y"?d==="vertical":d==="horizontal");return Oe(l)&&(xn(l.bin)||Cr(l.bin)||l.timeUnit&&!u)&&!(h&&!rf(h))&&!r[p]&&!Er(f)?t2e({fieldDef:l,fieldDef2:u,channel:t,model:e}):($t(l)&&Er(f)||g)&&!u?e2e(l,t,e):kU(t,e,{defaultPos:"zeroOrMax",defaultPos2:"zeroOrMin"})}function Qbe(e,t,n,r,i,s,a){if(rf(i))if(n){const l=n.get("type");if(l==="band"){let u=`bandwidth('${t}')`;i.band!==1&&(u=`${i.band} * ${u}`);const c=co("minBandSize",{type:a},r);return{signal:c?`max(${aa(c)}, ${u})`:u}}else i.band!==1&&(Te(Jme(l)),i=void 0)}else return{mult:i.band,field:{group:e}};else{if(ot(i))return i;if(i)return{value:i}}if(n){const l=n.get("range");if(Af(l)&&Qt(l.step))return{value:l.step-2}}if(!s){const{bandPaddingInner:l,barBandPaddingInner:u,rectBandPaddingInner:c,tickBandPaddingInner:f}=r.scale,d=Vn(l,a==="tick"?f:a==="bar"?u:c);if(ot(d))return{signal:`(1 - (${d.signal})) * ${e}`};if(Qt(d))return{signal:`${1-d} * ${e}`}}return{value:SA(r.view,e)-2}}function e2e(e,t,n){var C,M;const{markDef:r,encoding:i,config:s,stack:a}=n,o=r.orient,l=n.scaleName(t),u=n.getScaleComponent(t),c=qi(t),f=ko(t),d=yz(t),h=n.scaleName(d),p=n.getScaleComponent(E$(t)),g=r.type==="tick"||o==="horizontal"&&t==="y"||o==="vertical"&&t==="x";let v;(i.size||r.size)&&(g?v=Mr("size",n,{vgChannel:c,defaultRef:En(r.size)}):Te(n1e(r.type)));const y=!!v,b=mj({channel:t,fieldDef:e,markDef:r,config:s,scaleType:(C=u||p)==null?void 0:C.get("type"),useVlSizeChannel:g});v=v||{[c]:Qbe(c,h||l,p||u,s,b,!!e,r.type)};const _=((M=u||p)==null?void 0:M.get("type"))==="band"&&rf(b)&&!y?"top":"middle",x=AU(t,r,s,_),w=x==="xc"||x==="yc",{offset:A,offsetType:E}=lh({channel:t,markDef:r,encoding:i,model:n,bandPosition:w?.5:0}),k=K$({channel:t,channelDef:e,markDef:r,config:s,scaleName:l,scale:u,stack:a,offset:A,defaultRef:b5({model:n,defaultPos:"mid",channel:t,scaleName:l,scale:u}),bandPosition:w?E==="encoding"?0:.5:ot(b)?{signal:`(1-${b})/2`}:rf(b)?(1-b.band)/2:0});if(c)return{[x]:k,...v};{const N=pu(f),P=v[c],I=A?{...P,offset:A}:P;return{[x]:k,[N]:Se(k)?[k[0],{...k[1],offset:I}]:{...k,offset:I}}}}function Q6(e,t,n,r,i,s,a){if(dz(e))return 0;const o=e==="x"||e==="y2",l=o?-t/2:t/2;if(ot(n)||ot(i)||ot(r)||s){const u=aa(n),c=aa(i),f=aa(r),d=aa(s),p=s?`(${a} < ${d} ? ${o?"":"-"}0.5 * (${d} - (${a})) : ${l})`:l,g=f?`${f} + `:"",v=u?`(${u} ? -1 : 1) * `:"",y=c?`(${c} + ${p})`:p;return{signal:g+v+y}}else return i=i||0,r+(n?-i-l:+i+l)}function t2e({fieldDef:e,fieldDef2:t,channel:n,model:r}){var M;const{config:i,markDef:s,encoding:a}=r,o=r.getScaleComponent(n),l=r.scaleName(n),u=o?o.get("type"):void 0,c=o.get("reverse"),f=mj({channel:n,fieldDef:e,markDef:s,config:i,scaleType:u}),d=(M=r.component.axes[n])==null?void 0:M[0],h=(d==null?void 0:d.get("translate"))??.5,p=Xn(n)?fn("binSpacing",s,i)??0:0,g=ko(n),v=pu(n),y=pu(g),b=co("minBandSize",s,i),{offset:_}=lh({channel:n,markDef:s,encoding:a,model:r,bandPosition:0}),{offset:x}=lh({channel:g,markDef:s,encoding:a,model:r,bandPosition:0}),w=Ave({fieldDef:e,scaleName:l}),A=Q6(n,p,c,h,_,b,w),E=Q6(g,p,c,h,x??_,b,w),k=ot(f)?{signal:`(1-${f.signal})/2`}:rf(f)?(1-f.band)/2:.5,C=gu({fieldDef:e,fieldDef2:t,markDef:s,config:i});if(xn(e.bin)||e.timeUnit){const N=e.timeUnit&&C!==.5;return{[y]:e8({fieldDef:e,scaleName:l,bandPosition:k,offset:E,useRectOffsetField:N}),[v]:e8({fieldDef:e,scaleName:l,bandPosition:ot(k)?{signal:`1-${k.signal}`}:1-k,offset:A,useRectOffsetField:N})}}else if(Cr(e.bin)){const N=Cc(e,l,{},{offset:E});if(Oe(t))return{[y]:N,[v]:Cc(t,l,{},{offset:A})};if(Ef(e.bin)&&e.bin.step)return{[y]:N,[v]:{signal:`scale("${l}", ${ze(e,{expr:"datum"})} + ${e.bin.step})`,offset:A}}}Te(Iz(g))}function e8({fieldDef:e,scaleName:t,bandPosition:n,offset:r,useRectOffsetField:i}){return dy({scaleName:t,fieldOrDatumDef:e,bandPosition:n,offset:r,...i?{startSuffix:A2,endSuffix:k2}:{}})}const n2e=new Set(["aria","width","height"]);function Us(e,t){const{fill:n=void 0,stroke:r=void 0}=t.color==="include"?EU(e):{};return{...r2e(e.markDef,t),...t8("fill",n),...t8("stroke",r),...Mr("opacity",e),...Mr("fillOpacity",e),...Mr("strokeOpacity",e),...Mr("strokeWidth",e),...Mr("strokeDash",e),...Ybe(e),...xU(e),...y5(e,"href"),...Wbe(e)}}function t8(e,t){return t?{[e]:t}:{}}function r2e(e,t){return dme.reduce((n,r)=>(!n2e.has(r)&&De(e,r)&&t[r]!=="ignore"&&(n[r]=En(e[r])),n),{})}function _5(e){const{config:t,markDef:n}=e,r=new Set;if(e.forEachFieldDef((i,s)=>{var u;let a;if(!So(s)||!(a=e.getScaleType(s)))return;const o=s2(i.aggregate),l=X$({scaleChannel:s,markDef:n,config:t,scaleType:a,isCountAggregate:o});if(xve(l)){const c=e.vgField(s,{expr:"datum",binSuffix:(u=e.stack)!=null&&u.impute?"mid":void 0});c&&r.add(c)}}),r.size>0)return{defined:{signal:[...r].map(s=>u2(s,!0)).join(" && ")}}}function n8(e,t){if(t!==void 0)return{[e]:En(t)}}const Mx="voronoi",SU={defined:e=>e.type==="point"&&e.nearest,parse:(e,t)=>{if(t.events)for(const n of t.events)n.markname=e.getName(Mx)},marks:(e,t,n)=>{const{x:r,y:i}=t.project.hasChannel,s=e.mark;if(Lu(s))return Te(yme(s)),n;const a={name:e.getName(Mx),type:"path",interactive:!0,from:{data:e.getName("marks")},encode:{update:{fill:{value:"transparent"},strokeWidth:{value:.35},stroke:{value:"transparent"},isVoronoi:{value:!0},...xU(e,{reactiveGeom:!0})}},transform:[{type:"voronoi",x:{expr:r||!i?"datum.datum.x || 0":"0"},y:{expr:i||!r?"datum.datum.y || 0":"0"},size:[e.getSizeSignalRef("width"),e.getSizeSignalRef("height")]}]};let o=0,l=!1;return n.forEach((u,c)=>{const f=u.name??"";f===e.component.mark[0].name?o=c:f.includes(Mx)&&(l=!0)}),l||n.splice(o+1,0,a),n}},CU={defined:e=>e.type==="point"&&e.resolve==="global"&&e.bind&&e.bind!=="scales"&&!c5(e.bind),parse:(e,t,n)=>OU(t,n),topLevelSignals:(e,t,n)=>{const r=t.name,i=t.project,s=t.bind,a=t.init&&t.init[0],o=SU.defined(t)?"(item().isVoronoi ? datum.datum : datum)":"datum";return i.items.forEach((l,u)=>{const c=Cn(`${r}_${l.field}`);n.filter(d=>d.name===c).length||n.unshift({name:c,...a?{init:af(a[u])}:{value:null},on:t.events?[{events:t.events,update:`datum && item().mark.marktype !== 'group' ? ${o}[${Pe(l.field)}] : null`}]:[],bind:s[l.field]??s[l.channel]??s})}),n},signals:(e,t,n)=>{const r=t.name,i=t.project,s=n.find(u=>u.name===r+dl),a=r+Z0,o=i.items.map(u=>Cn(`${r}_${u.field}`)),l=o.map(u=>`${u} !== null`).join(" && ");return o.length&&(s.update=`${l} ? {fields: ${a}, values: [${o.join(", ")}]} : null`),delete s.value,delete s.on,n}},_y="_toggle",$U={defined:e=>e.type==="point"&&!to(e)&&!!e.toggle,signals:(e,t,n)=>n.concat({name:t.name+_y,value:!1,on:[{events:t.events,update:t.toggle}]}),modifyExpr:(e,t)=>{const n=t.name+dl,r=t.name+_y;return`${r} ? null : ${n}, `+(t.resolve==="global"?`${r} ? null : true, `:`${r} ? null : {unit: ${Fc(e)}}, `)+`${r} ? ${n} : null`}},i2e={defined:e=>e.clear!==void 0&&e.clear!==!1&&!to(e),parse:(e,t)=>{t.clear&&(t.clear=We(t.clear)?$u(t.clear,"view"):t.clear)},topLevelSignals:(e,t,n)=>{if(CU.defined(t))for(const r of t.project.items){const i=n.findIndex(s=>s.name===Cn(`${t.name}_${r.field}`));i!==-1&&n[i].on.push({events:t.clear,update:"null"})}return n},signals:(e,t,n)=>{function r(i,s){i!==-1&&n[i].on&&n[i].on.push({events:t.clear,update:s})}if(t.type==="interval")for(const i of t.project.items){const s=n.findIndex(a=>a.name===i.signals.visual);if(r(s,"[0, 0]"),s===-1){const a=n.findIndex(o=>o.name===i.signals.data);r(a,"null")}}else{let i=n.findIndex(s=>s.name===t.name+dl);r(i,"null"),$U.defined(t)&&(i=n.findIndex(s=>s.name===t.name+_y),r(i,"false"))}return n}},FU={defined:e=>{const t=e.resolve==="global"&&e.bind&&c5(e.bind),n=e.project.items.length===1&&e.project.items[0].field!==ya;return t&&!n&&Te(wme),t&&n},parse:(e,t,n)=>{const r=Ct(n);if(r.select=We(r.select)?{type:r.select,toggle:t.toggle}:{...r.select,toggle:t.toggle},OU(t,r),Ue(n.select)&&(n.select.on||n.select.clear)){const a='event.item && indexof(event.item.mark.role, "legend") < 0';for(const o of t.events)o.filter=He(o.filter??[]),o.filter.includes(a)||o.filter.push(a)}const i=kx(t.bind)?t.bind.legend:"click",s=We(i)?$u(i,"view"):He(i);t.bind={legend:{merge:s}}},topLevelSignals:(e,t,n)=>{const r=t.name,i=kx(t.bind)&&t.bind.legend,s=a=>o=>{const l=Ct(o);return l.markname=a,l};for(const a of t.project.items){if(!a.hasLegend)continue;const o=`${Cn(a.field)}_legend`,l=`${r}_${o}`;if(n.filter(c=>c.name===l).length===0){const c=i.merge.map(s(`${o}_symbols`)).concat(i.merge.map(s(`${o}_labels`))).concat(i.merge.map(s(`${o}_entries`)));n.unshift({name:l,...t.init?{}:{value:null},on:[{events:c,update:"isDefined(datum.value) ? datum.value : item().items[0].items[0].datum.value",force:!0},{events:i.merge,update:`!event.item || !datum ? null : ${l}`,force:!0}]})}}return n},signals:(e,t,n)=>{const r=t.name,i=t.project,s=n.find(d=>d.name===r+dl),a=r+Z0,o=i.items.filter(d=>d.hasLegend).map(d=>Cn(`${r}_${Cn(d.field)}_legend`)),u=`${o.map(d=>`${d} !== null`).join(" && ")} ? {fields: ${a}, values: [${o.join(", ")}]} : null`;t.events&&o.length>0?s.on.push({events:o.map(d=>({signal:d})),update:u}):o.length>0&&(s.update=u,delete s.value,delete s.on);const c=n.find(d=>d.name===r+_y),f=kx(t.bind)&&t.bind.legend;return c&&(t.events?c.on.push({...c.on[0],events:f}):c.on[0].events=f),n}};function s2e(e,t,n){var i;const r=(i=e.fieldDef(t))==null?void 0:i.field;for(const s of Lr(e.component.selection??{})){const a=s.project.hasField[r]??s.project.hasChannel[t];if(a&&FU.defined(s)){const o=n.get("selections")??[];o.push(s.name),n.set("selections",o,!1),a.hasLegend=!0}}}const DU="_translate_anchor",MU="_translate_delta",a2e={defined:e=>e.type==="interval"&&e.translate,signals:(e,t,n)=>{const r=t.name,i=rl.defined(t),s=r+DU,{x:a,y:o}=t.project.hasChannel;let l=$u(t.translate,"scope");return i||(l=l.map(u=>(u.between[0].markname=r+hd,u))),n.push({name:s,value:{},on:[{events:l.map(u=>u.between[0]),update:"{x: x(unit), y: y(unit)"+(a!==void 0?`, extent_x: ${i?MA(e,$n):`slice(${a.signals.visual})`}`:"")+(o!==void 0?`, extent_y: ${i?MA(e,kr):`slice(${o.signals.visual})`}`:"")+"}"}]},{name:r+MU,value:{},on:[{events:l,update:`{x: ${s}.x - x(unit), y: ${s}.y - y(unit)}`}]}),a!==void 0&&r8(e,t,a,"width",n),o!==void 0&&r8(e,t,o,"height",n),n}};function r8(e,t,n,r,i){const s=t.name,a=s+DU,o=s+MU,l=n.channel,u=rl.defined(t),c=i.find(w=>w.name===n.signals[u?"data":"visual"]),f=e.getSizeSignalRef(r).signal,d=e.getScaleComponent(l),h=d&&d.get("type"),p=d&&d.get("reverse"),g=u?l===$n?p?"":"-":p?"-":"":"",v=`${a}.extent_${l}`,y=`${g}${o}.${l} / ${u?`${f}`:`span(${v})`}`,b=!u||!d?"panLinear":h==="log"?"panLog":h==="symlog"?"panSymlog":h==="pow"?"panPow":"panLinear",_=u?h==="pow"?`, ${d.get("exponent")??1}`:h==="symlog"?`, ${d.get("constant")??1}`:"":"",x=`${b}(${v}, ${y}${_})`;c.on.push({events:{signal:o},update:u?x:`clampRange(${x}, 0, ${f})`})}const TU="_zoom_anchor",RU="_zoom_delta",o2e={defined:e=>e.type==="interval"&&e.zoom,signals:(e,t,n)=>{const r=t.name,i=rl.defined(t),s=r+RU,{x:a,y:o}=t.project.hasChannel,l=Pe(e.scaleName($n)),u=Pe(e.scaleName(kr));let c=$u(t.zoom,"scope");return i||(c=c.map(f=>(f.markname=r+hd,f))),n.push({name:r+TU,on:[{events:c,update:i?"{"+[l?`x: invert(${l}, x(unit))`:"",u?`y: invert(${u}, y(unit))`:""].filter(f=>f).join(", ")+"}":"{x: x(unit), y: y(unit)}"}]},{name:s,on:[{events:c,force:!0,update:"pow(1.001, event.deltaY * pow(16, event.deltaMode))"}]}),a!==void 0&&i8(e,t,a,"width",n),o!==void 0&&i8(e,t,o,"height",n),n}};function i8(e,t,n,r,i){const s=t.name,a=n.channel,o=rl.defined(t),l=i.find(b=>b.name===n.signals[o?"data":"visual"]),u=e.getSizeSignalRef(r).signal,c=e.getScaleComponent(a),f=c&&c.get("type"),d=o?MA(e,a):l.name,h=s+RU,p=`${s}${TU}.${a}`,g=!o||!c?"zoomLinear":f==="log"?"zoomLog":f==="symlog"?"zoomSymlog":f==="pow"?"zoomPow":"zoomLinear",v=o?f==="pow"?`, ${c.get("exponent")??1}`:f==="symlog"?`, ${c.get("constant")??1}`:"":"",y=`${g}(${d}, ${p}, ${h}${v})`;l.on.push({events:{signal:h},update:o?y:`clampRange(${y}, 0, ${u})`})}const of="_store",dl="_tuple",l2e="_modify",NU="vlSelectionResolve",C2=[Nbe,Ube,Mbe,$U,CU,rl,FU,i2e,a2e,o2e,SU];function u2e(e){let t=e.parent;for(;t&&!os(t);)t=t.parent;return t}function Fc(e,{escape:t}={escape:!0}){let n=t?Pe(e.name):e.name;const r=u2e(e);if(r){const{facet:i}=r;for(const s of Ss)i[s]&&(n+=` + '__facet_${s}_' + (facet[${Pe(r.vgField(s))}])`)}return n}function x5(e){return Lr(e.component.selection??{}).reduce((t,n)=>t||n.project.hasSelectionId,!1)}function OU(e,t){(We(t.select)||!t.select.on)&&delete e.events,(We(t.select)||!t.select.clear)&&delete e.clear,(We(t.select)||!t.select.toggle)&&delete e.toggle}function to(e){var t;return(t=e.events)==null?void 0:t.find(n=>"type"in n&&n.type==="timer")}const c2e="RawCode",f2e="Literal",d2e="Property",h2e="Identifier",p2e="ArrayExpression",g2e="BinaryExpression",m2e="CallExpression",v2e="ConditionalExpression",y2e="LogicalExpression",b2e="MemberExpression",_2e="ObjectExpression",x2e="UnaryExpression";function Ca(e){this.type=e}Ca.prototype.visit=function(e){let t,n,r;if(e(this))return 1;for(t=w2e(this),n=0,r=t.length;n";$o[lf]="Identifier";$o[Iu]="Keyword";$o[F2]="Null";$o[$f]="Numeric";$o[Fi]="Punctuator";$o[Q0]="String";$o[E2e]="RegularExpression";var A2e="ArrayExpression",k2e="BinaryExpression",S2e="CallExpression",C2e="ConditionalExpression",LU="Identifier",$2e="Literal",F2e="LogicalExpression",D2e="MemberExpression",M2e="ObjectExpression",T2e="Property",R2e="UnaryExpression",_r="Unexpected token %0",N2e="Unexpected number",O2e="Unexpected string",L2e="Unexpected identifier",I2e="Unexpected reserved word",P2e="Unexpected end of input",RA="Invalid regular expression",Tx="Invalid regular expression: missing /",IU="Octal literals are not allowed in strict mode.",B2e="Duplicate data property in object literal not allowed in strict mode",Nr="ILLEGAL",Wg="Disabled.",z2e=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),j2e=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]");function D2(e,t){if(!e)throw new Error("ASSERT: "+t)}function Po(e){return e>=48&&e<=57}function w5(e){return"0123456789abcdefABCDEF".includes(e)}function fg(e){return"01234567".includes(e)}function U2e(e){return e===32||e===9||e===11||e===12||e===160||e>=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].includes(e)}function Hg(e){return e===10||e===13||e===8232||e===8233}function em(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e===92||e>=128&&z2e.test(String.fromCharCode(e))}function xy(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e>=48&&e<=57||e===92||e>=128&&j2e.test(String.fromCharCode(e))}const q2e={if:1,in:1,do:1,var:1,for:1,new:1,try:1,let:1,this:1,else:1,case:1,void:1,with:1,enum:1,while:1,break:1,catch:1,throw:1,const:1,yield:1,class:1,super:1,return:1,typeof:1,delete:1,switch:1,export:1,import:1,public:1,static:1,default:1,finally:1,extends:1,package:1,private:1,function:1,continue:1,debugger:1,interface:1,protected:1,instanceof:1,implements:1};function PU(){for(;Ee1114111||e!=="}")&&Jt({},_r,Nr),t<=65535?String.fromCharCode(t):(n=(t-65536>>10)+55296,r=(t-65536&1023)+56320,String.fromCharCode(n,r))}function BU(){var e,t;for(e=st.charCodeAt(Ee++),t=String.fromCharCode(e),e===92&&(st.charCodeAt(Ee)!==117&&Jt({},_r,Nr),++Ee,e=NA("u"),(!e||e==="\\"||!em(e.charCodeAt(0)))&&Jt({},_r,Nr),t=e);Ee>>=")return Ee+=4,{type:Fi,value:a,start:e,end:Ee};if(s=a.substr(0,3),s===">>>"||s==="<<="||s===">>=")return Ee+=3,{type:Fi,value:s,start:e,end:Ee};if(i=s.substr(0,2),r===i[1]&&"+-<>&|".includes(r)||i==="=>")return Ee+=2,{type:Fi,value:i,start:e,end:Ee};if(i==="//"&&Jt({},_r,Nr),"<>=!+-*%&|^/".includes(r))return++Ee,{type:Fi,value:r,start:e,end:Ee};Jt({},_r,Nr)}function Y2e(e){let t="";for(;Ee{if(parseInt(i,16)<=1114111)return"x";Jt({},RA)}).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"x"));try{new RegExp(n)}catch{Jt({},RA)}try{return new RegExp(e,t)}catch{return null}}function Z2e(){var e,t,n,r,i;for(e=st[Ee],D2(e==="/","Regular expression literal must start with a slash"),t=st[Ee++],n=!1,r=!1;Ee=0&&Jt({},RA,n),{value:n,literal:t}}function Q2e(){var e,t,n,r;return on=null,PU(),e=Ee,t=Z2e(),n=J2e(),r=K2e(t.value,n.value),{literal:t.literal+n.literal,value:r,regex:{pattern:t.value,flags:n.value},start:e,end:Ee}}function e_e(e){return e.type===lf||e.type===Iu||e.type===$2||e.type===F2}function zU(){if(PU(),Ee>=Jr)return{type:J0,start:Ee,end:Ee};const e=st.charCodeAt(Ee);return em(e)?G2e():e===40||e===41||e===59?Rx():e===39||e===34?X2e():e===46?Po(st.charCodeAt(Ee+1))?s8():Rx():Po(e)?s8():Rx()}function Ri(){const e=on;return Ee=e.end,on=zU(),Ee=e.end,e}function jU(){const e=Ee;on=zU(),Ee=e}function t_e(e){const t=new Ca(A2e);return t.elements=e,t}function a8(e,t,n){const r=new Ca(e==="||"||e==="&&"?F2e:k2e);return r.operator=e,r.left=t,r.right=n,r}function n_e(e,t){const n=new Ca(S2e);return n.callee=e,n.arguments=t,n}function r_e(e,t,n){const r=new Ca(C2e);return r.test=e,r.consequent=t,r.alternate=n,r}function E5(e){const t=new Ca(LU);return t.name=e,t}function qp(e){const t=new Ca($2e);return t.value=e.value,t.raw=st.slice(e.start,e.end),e.regex&&(t.raw==="//"&&(t.raw="/(?:)/"),t.regex=e.regex),t}function o8(e,t,n){const r=new Ca(D2e);return r.computed=e==="[",r.object=t,r.property=n,r.computed||(n.member=!0),r}function i_e(e){const t=new Ca(M2e);return t.properties=e,t}function l8(e,t,n){const r=new Ca(T2e);return r.key=t,r.value=n,r.kind=e,r}function s_e(e,t){const n=new Ca(R2e);return n.operator=e,n.argument=t,n.prefix=!0,n}function Jt(e,t){var n,r=Array.prototype.slice.call(arguments,2),i=t.replace(/%(\d)/g,(s,a)=>(D2(a":case"<=":case">=":case"instanceof":case"in":t=7;break;case"<<":case">>":case">>>":t=8;break;case"+":case"-":t=9;break;case"*":case"/":case"%":t=11;break}return t}function v_e(){var e,t,n,r,i,s,a,o,l,u;if(e=on,l=I1(),r=on,i=f8(r),i===0)return l;for(r.prec=i,Ri(),t=[e,on],a=I1(),s=[l,r,a];(i=f8(on))>0;){for(;s.length>2&&i<=s[s.length-2].prec;)a=s.pop(),o=s.pop().value,l=s.pop(),t.pop(),n=a8(o,l,a),s.push(n);r=Ri(),r.prec=i,s.push(r),t.push(on),n=I1(),s.push(n)}for(u=s.length-1,n=s[u],t.pop();u>1;)t.pop(),n=a8(s[u-1].value,s[u-2],n),u-=2;return n}function uf(){var e,t,n;return e=v_e(),An("?")&&(Ri(),t=uf(),Qr(":"),n=uf(),e=r_e(e,t,n)),e}function A5(){const e=uf();if(An(","))throw new Error(Wg);return e}function y_e(e){st=e,Ee=0,Jr=st.length,on=null,jU();const t=A5();if(on.type!==J0)throw new Error("Unexpect token after expression.");return t}function OA(e){const t=[];return e.type==="Identifier"?[e.name]:e.type==="Literal"?[e.value]:(e.type==="MemberExpression"&&(t.push(...OA(e.object)),t.push(...OA(e.property))),t)}function UU(e){return e.object.type==="MemberExpression"?UU(e.object):e.object.name==="datum"}function qU(e){const t=y_e(e),n=new Set;return t.visit(r=>{r.type==="MemberExpression"&&UU(r)&&n.add(OA(r).slice(1).join("."))}),n}class Bh extends cn{clone(){return new Bh(null,this.model,Ct(this.filter))}constructor(t,n,r){super(t),this.model=n,this.filter=r,this.expr=wy(this.model,this.filter,this),this._dependentFields=qU(this.expr)}dependentFields(){return this._dependentFields}producedFields(){return new Set}assemble(){return{type:"filter",expr:this.expr}}hash(){return`Filter ${this.expr}`}}function b_e(e,t){const n={},r=e.config.selection;if(!t||!t.length)return n;let i=0;for(const s of t){const a=Cn(s.name),o=s.select,l=We(o)?o:o.type,u=Ue(o)?Ct(o):{type:l},c=r[l];for(const h in c)h==="fields"||h==="encodings"||(h==="mark"&&(u.mark={...c.mark,...u.mark}),(u[h]===void 0||u[h]===!0)&&(u[h]=Ct(c[h]??u[h])));const f=n[a]={...u,name:a,type:l,init:s.value,bind:s.bind,events:We(u.on)?$u(u.on,"scope"):He(Ct(u.on))};if(to(f)&&(i++,i>1)){delete n[a];continue}const d=Ct(s);for(const h of C2)h.defined(f)&&h.parse&&h.parse(e,f,d)}return i>1&&Te($me),n}function WU(e,t,n,r="datum"){const i=We(t)?t:t.param,s=Cn(i),a=Pe(s+of);let o;try{o=e.getSelectionComponent(s,i)}catch{return`!!${s}`}if(o.project.timeUnit){const d=n??e.component.data.raw,h=o.project.timeUnit.clone();d.parent?h.insertAsParentOf(d):d.parent=h}const l=o.project.hasSelectionId?"vlSelectionIdTest(":"vlSelectionTest(",u=o.resolve==="global"?")":`, ${Pe(o.resolve)})`,c=`${l}${a}, ${r}${u}`,f=`length(data(${a}))`;return t.empty===!1?`${f} && ${c}`:`!${f} || ${c}`}function HU(e,t,n){const r=Cn(t),i=n.encoding;let s=n.field,a;try{a=e.getSelectionComponent(r,t)}catch{return r}if(!i&&!s)s=a.project.items[0].field,a.project.items.length>1&&Te(Fme(s));else if(i&&!s){const o=a.project.items.filter(l=>l.channel===i);!o.length||o.length>1?(s=a.project.items[0].field,Te(Dme(o,i,n,s))):s=o[0].field}return`${a.name}[${Pe(Ps(s))}]`}function __e(e,t){for(const[n,r]of hu(e.component.selection??{})){const i=e.getName(`lookup_${n}`);e.component.data.outputNodes[i]=r.materialized=new Ii(new Bh(t,e,{param:n}),i,Tn.Lookup,e.component.data.outputNodeRefCounts)}}function wy(e,t,n){return ug(t,r=>We(r)?r:B1e(r)?WU(e,r,n):Xz(r))}function x_e(e,t){if(e)return Se(e)&&!Tl(e)?e.map(n=>n5(n,t)).join(", "):e}function Ox(e,t,n,r){var i,s;e.encode??(e.encode={}),(i=e.encode)[t]??(i[t]={}),(s=e.encode[t]).update??(s.update={}),e.encode[t].update[n]=r}function Wp(e,t,n,r={header:!1}){var f,d;const{disable:i,orient:s,scale:a,labelExpr:o,title:l,zindex:u,...c}=e.combine();if(!i){for(const h in c){const p=h,g=Wve[p],v=c[p];if(g&&g!==t&&g!=="both")delete c[p];else if(K0(v)){const{condition:y,...b}=v,_=He(y),x=T6[p];if(x){const{vgProp:w,part:A}=x,E=[..._.map(k=>{const{test:C,...M}=k;return{test:wy(null,C),...M}}),b];Ox(c,A,w,E),delete c[p]}else if(x===null){const w={signal:_.map(A=>{const{test:E,...k}=A;return`${wy(null,E)} ? ${m6(k)} : `}).join("")+m6(b)};c[p]=w}}else if(ot(v)){const y=T6[p];if(y){const{vgProp:b,part:_}=y;Ox(c,_,b,v),delete c[p]}}Ut(["labelAlign","labelBaseline"],p)&&c[p]===null&&delete c[p]}if(t==="grid"){if(!c.grid)return;if(c.encode){const{grid:h}=c.encode;c.encode={...h?{grid:h}:{}},dn(c.encode)&&delete c.encode}return{scale:a,orient:s,...c,domain:!1,labels:!1,aria:!1,maxExtent:0,minExtent:0,ticks:!1,zindex:Vn(u,0)}}else{if(!r.header&&e.mainExtracted)return;if(o!==void 0){let p=o;(d=(f=c.encode)==null?void 0:f.labels)!=null&&d.update&&ot(c.encode.labels.update.text)&&(p=Jc(o,"datum.label",c.encode.labels.update.text.signal)),Ox(c,"labels","text",{signal:p})}if(c.labelAlign===null&&delete c.labelAlign,c.encode){for(const p of Sj)e.hasAxisPart(p)||delete c.encode[p];dn(c.encode)&&delete c.encode}const h=x_e(l,n);return{scale:a,orient:s,grid:!1,...h?{title:h}:{},...c,...n.aria===!1?{aria:!1}:{},zindex:Vn(u,0)}}}}function GU(e){const{axes:t}=e.component,n=[];for(const r of bl)if(t[r]){for(const i of t[r])if(!i.get("disable")&&!i.get("gridScale")){const s=r==="x"?"height":"width",a=e.getSizeSignalRef(s).signal;s!==a&&n.push({name:s,update:a})}}return n}function w_e(e,t){const{x:n=[],y:r=[]}=e;return[...n.map(i=>Wp(i,"grid",t)),...r.map(i=>Wp(i,"grid",t)),...n.map(i=>Wp(i,"main",t)),...r.map(i=>Wp(i,"main",t))].filter(i=>i)}function d8(e,t,n,r){return Object.assign.apply(null,[{},...e.map(i=>{if(i==="axisOrient"){const s=n==="x"?"bottom":"left",a=t[n==="x"?"axisBottom":"axisLeft"]||{},o=t[n==="x"?"axisTop":"axisRight"]||{},l=new Set([...Fe(a),...Fe(o)]),u={};for(const c of l.values())u[c]={signal:`${r.signal} === "${s}" ? ${aa(a[c])} : ${aa(o[c])}`};return u}return t[i]})])}function E_e(e,t,n,r){const i=t==="band"?["axisDiscrete","axisBand"]:t==="point"?["axisDiscrete","axisPoint"]:Qz(t)?["axisQuantitative"]:t==="time"||t==="utc"?["axisTemporal"]:[],s=e==="x"?"axisX":"axisY",a=ot(n)?"axisOrient":`axis${B0(n)}`,o=[...i,...i.map(u=>s+u.substr(4))],l=["axis",a,s];return{vlOnlyAxisConfig:d8(o,r,e,n),vgAxisConfig:d8(l,r,e,n),axisConfigStyle:A_e([...l,...o],r)}}function A_e(e,t){var r;const n=[{}];for(const i of e){let s=(r=t[i])==null?void 0:r.style;if(s){s=He(s);for(const a of s)n.push(t.style[a])}}return Object.assign.apply(null,n)}function LA(e,t,n,r={}){var s;const i=Cz(e,n,t);if(i!==void 0)return{configFrom:"style",configValue:i};for(const a of["vlOnlyAxisConfig","vgAxisConfig","axisConfigStyle"])if(((s=r[a])==null?void 0:s[e])!==void 0)return{configFrom:a,configValue:r[a][e]};return{}}const h8={scale:({model:e,channel:t})=>e.scaleName(t),format:({format:e})=>e,formatType:({formatType:e})=>e,grid:({fieldOrDatumDef:e,axis:t,scaleType:n})=>t.grid??k_e(n,e),gridScale:({model:e,channel:t})=>S_e(e,t),labelAlign:({axis:e,labelAngle:t,orient:n,channel:r})=>e.labelAlign||VU(t,n,r),labelAngle:({labelAngle:e})=>e,labelBaseline:({axis:e,labelAngle:t,orient:n,channel:r})=>e.labelBaseline||YU(t,n,r),labelFlush:({axis:e,fieldOrDatumDef:t,channel:n})=>e.labelFlush??$_e(t.type,n),labelOverlap:({axis:e,fieldOrDatumDef:t,scaleType:n})=>e.labelOverlap??F_e(t.type,n,Oe(t)&&!!t.timeUnit,Oe(t)?t.sort:void 0),orient:({orient:e})=>e,tickCount:({channel:e,model:t,axis:n,fieldOrDatumDef:r,scaleType:i})=>{const s=e==="x"?"width":e==="y"?"height":void 0,a=s?t.getSizeSignalRef(s):void 0;return n.tickCount??M_e({fieldOrDatumDef:r,scaleType:i,size:a,values:n.values})},tickMinStep:T_e,title:({axis:e,model:t,channel:n})=>{if(e.title!==void 0)return e.title;const r=XU(t,n);if(r!==void 0)return r;const i=t.typedFieldDef(n),s=n==="x"?"x2":"y2",a=t.fieldDef(s);return Fz(i?[D6(i)]:[],Oe(a)?[D6(a)]:[])},values:({axis:e,fieldOrDatumDef:t})=>R_e(e,t),zindex:({axis:e,fieldOrDatumDef:t,mark:n})=>e.zindex??N_e(n,t)};function k_e(e,t){return!Er(e)&&Oe(t)&&!xn(t==null?void 0:t.bin)&&!Cr(t==null?void 0:t.bin)}function S_e(e,t){const n=t==="x"?"y":"x";if(e.getScaleComponent(n))return e.scaleName(n)}function C_e(e,t,n,r,i){const s=t==null?void 0:t.labelAngle;if(s!==void 0)return ot(s)?s:jg(s);{const{configValue:a}=LA("labelAngle",r,t==null?void 0:t.style,i);return a!==void 0?jg(a):n===$n&&Ut([W$,q$],e.type)&&!(Oe(e)&&e.timeUnit)?270:void 0}}function IA(e){return`(((${e.signal} % 360) + 360) % 360)`}function YU(e,t,n,r){if(e!==void 0)if(n==="x"){if(ot(e)){const i=IA(e),s=ot(t)?`(${t.signal} === "top")`:t==="top";return{signal:`(45 < ${i} && ${i} < 135) || (225 < ${i} && ${i} < 315) ? "middle" :(${i} <= 45 || 315 <= ${i}) === ${s} ? "bottom" : "top"`}}if(45{if(Cf(r)&&gj(r.sort)){const{field:s,timeUnit:a}=r,o=r.sort,l=o.map((u,c)=>`${Xz({field:s,timeUnit:a,equal:u})} ? ${c} : `).join("")+o.length;t=new uh(t,{calculate:l,as:ch(r,i,{forAs:!0})})}}),t}producedFields(){return new Set([this.transform.as])}dependentFields(){return this._dependentFields}assemble(){return{type:"formula",expr:this.transform.calculate,as:this.transform.as}}hash(){return`Calculate ${Gt(this.transform)}`}}function ch(e,t,n){return ze(e,{prefix:t,suffix:"sort_index",...n})}function T2(e,t){return Ut(["top","bottom"],t)?"column":Ut(["left","right"],t)||e==="row"?"row":"column"}function fh(e,t,n,r){const i=r==="row"?n.headerRow:r==="column"?n.headerColumn:n.headerFacet;return Vn((t||{})[e],i[e],n.header[e])}function R2(e,t,n,r){const i={};for(const s of e){const a=fh(s,t||{},n,r);a!==void 0&&(i[s]=a)}return i}const k5=["row","column"],S5=["header","footer"];function O_e(e,t){const n=e.component.layoutHeaders[t].title,r=e.config?e.config:void 0,i=e.component.layoutHeaders[t].facetFieldDef?e.component.layoutHeaders[t].facetFieldDef:void 0,{titleAnchor:s,titleAngle:a,titleOrient:o}=R2(["titleAnchor","titleAngle","titleOrient"],i.header,r,t),l=T2(t,o),u=jg(a);return{name:`${t}-title`,type:"group",role:`${l}-title`,title:{text:n,...t==="row"?{orient:"left"}:{},style:"guide-title",...ZU(u,l),...KU(l,u,s),...JU(r,i,t,dye,Wj)}}}function KU(e,t,n="middle"){switch(n){case"start":return{align:"left"};case"end":return{align:"right"}}const r=VU(t,e==="row"?"left":"top",e==="row"?"y":"x");return r?{align:r}:{}}function ZU(e,t){const n=YU(e,t==="row"?"left":"top",t==="row"?"y":"x",!0);return n?{baseline:n}:{}}function L_e(e,t){const n=e.component.layoutHeaders[t],r=[];for(const i of S5)if(n[i])for(const s of n[i]){const a=P_e(e,t,i,n,s);a!=null&&r.push(a)}return r}function I_e(e,t){const{sort:n}=e;return nl(n)?{field:ze(n,{expr:"datum"}),order:n.order??"ascending"}:Se(n)?{field:ch(e,t,{expr:"datum"}),order:"ascending"}:{field:ze(e,{expr:"datum"}),order:n??"ascending"}}function PA(e,t,n){const{format:r,formatType:i,labelAngle:s,labelAnchor:a,labelOrient:o,labelExpr:l}=R2(["format","formatType","labelAngle","labelAnchor","labelOrient","labelExpr"],e.header,n,t),u=J$({fieldOrDatumDef:e,format:r,formatType:i,expr:"parent",config:n}).signal,c=T2(t,o);return{text:{signal:l?Jc(Jc(l,"datum.label",u),"datum.value",ze(e,{expr:"parent"})):u},...t==="row"?{orient:"left"}:{},style:"guide-label",frame:"group",...ZU(s,c),...KU(c,s,a),...JU(n,e,t,hye,Hj)}}function P_e(e,t,n,r,i){if(i){let s=null;const{facetFieldDef:a}=r,o=e.config?e.config:void 0;if(a&&i.labels){const{labelOrient:f}=R2(["labelOrient"],a.header,o,t);(t==="row"&&!Ut(["top","bottom"],f)||t==="column"&&!Ut(["left","right"],f))&&(s=PA(a,t,o))}const l=os(e)&&!G0(e.facet),u=i.axes,c=(u==null?void 0:u.length)>0;if(s||c){const f=t==="row"?"height":"width";return{name:e.getName(`${t}_${n}`),type:"group",role:`${t}-${n}`,...r.facetFieldDef?{from:{data:e.getName(`${t}_domain`)},sort:I_e(a,t)}:{},...c&&l?{from:{data:e.getName(`facet_domain_${t}`)}}:{},...s?{title:s}:{},...i.sizeSignal?{encode:{update:{[f]:i.sizeSignal}}}:{},...c?{axes:u}:{}}}}return null}const B_e={column:{start:0,end:1},row:{start:1,end:0}};function z_e(e,t){return B_e[t][e]}function j_e(e,t){const n={};for(const r of Ss){const i=e[r];if(i!=null&&i.facetFieldDef){const{titleAnchor:s,titleOrient:a}=R2(["titleAnchor","titleOrient"],i.facetFieldDef.header,t,r),o=T2(r,a),l=z_e(s,o);l!==void 0&&(n[o]=l)}}return dn(n)?void 0:n}function JU(e,t,n,r,i){const s={};for(const a of r){if(!i[a])continue;const o=fh(a,t==null?void 0:t.header,e,n);o!==void 0&&(s[i[a]]=o)}return s}function C5(e){return[...jm(e,"width"),...jm(e,"height"),...jm(e,"childWidth"),...jm(e,"childHeight")]}function jm(e,t){const n=t==="width"?"x":"y",r=e.component.layoutSize.get(t);if(!r||r==="merged")return[];const i=e.getSizeSignalRef(t).signal;if(r==="step"){const s=e.getScaleComponent(n);if(s){const a=s.get("type"),o=s.get("range");if(Er(a)&&Af(o)){const l=e.scaleName(n);return os(e.parent)&&e.parent.component.resolve.scale[n]==="independent"?[p8(l,o)]:[p8(l,o),{name:i,update:QU(l,s,`domain('${l}').length`)}]}}throw new Error("layout size is step although width/height is not step.")}else if(r=="container"){const s=i.endsWith("width"),a=s?"containerSize()[0]":"containerSize()[1]",o=kA(e.config.view,s?"width":"height"),l=`isFinite(${a}) ? ${a} : ${o}`;return[{name:i,init:l,on:[{update:l,events:"window:resize"}]}]}else return[{name:i,value:r}]}function p8(e,t){const n=`${e}_step`;return ot(t.step)?{name:n,update:t.step.signal}:{name:n,value:t.step}}function QU(e,t,n){const r=t.get("type"),i=t.get("padding"),s=Vn(t.get("paddingOuter"),i);let a=t.get("paddingInner");return a=r==="band"?a!==void 0?a:i:1,`bandspace(${n}, ${aa(a)}, ${aa(s)}) * ${e}_step`}function eq(e){return e==="childWidth"?"width":e==="childHeight"?"height":e}function tq(e,t){return Fe(e).reduce((n,r)=>({...n,...Ph({model:t,channelDef:e[r],vgChannel:r,mainRefFn:i=>En(i.value),invalidValueRef:void 0})}),{})}function nq(e,t){if(os(t))return e==="theta"?"independent":"shared";if(Uh(t))return"shared";if(N5(t))return Xn(e)||e==="theta"||e==="radius"?"independent":"shared";throw new Error("invalid model type for resolve")}function $5(e,t){const n=e.scale[t],r=Xn(t)?"axis":"legend";return n==="independent"?(e[r][t]==="shared"&&Te(o1e(t)),"independent"):e[r][t]||"shared"}const U_e={...mye,disable:1,labelExpr:1,selections:1,opacity:1,shape:1,stroke:1,fill:1,size:1,strokeWidth:1,strokeDash:1,encode:1},rq=Fe(U_e);class q_e extends xl{}const g8={symbols:W_e,gradient:H_e,labels:G_e,entries:Y_e};function W_e(e,{fieldOrDatumDef:t,model:n,channel:r,legendCmpt:i,legendType:s}){if(s!=="symbol")return;const{markDef:a,encoding:o,config:l,mark:u}=n,c=a.filled&&u!=="trail";let f={...gme({},n,fve),...EU(n,{filled:c})};const d=i.get("symbolOpacity")??l.legend.symbolOpacity,h=i.get("symbolFillColor")??l.legend.symbolFillColor,p=i.get("symbolStrokeColor")??l.legend.symbolStrokeColor,g=d===void 0?iq(o.opacity)??a.opacity:void 0;if(f.fill){if(r==="fill"||c&&r===ji)delete f.fill;else if(De(f.fill,"field"))h?delete f.fill:(f.fill=En(l.legend.symbolBaseFillColor??"black"),f.fillOpacity=En(g??1));else if(Se(f.fill)){const v=BA(o.fill??o.color)??a.fill??(c&&a.color);v&&(f.fill=En(v))}}if(f.stroke){if(r==="stroke"||!c&&r===ji)delete f.stroke;else if(De(f.stroke,"field")||p)delete f.stroke;else if(Se(f.stroke)){const v=Vn(BA(o.stroke||o.color),a.stroke,c?a.color:void 0);v&&(f.stroke={value:v})}}if(r!==yl){const v=Oe(t)&&aq(n,i,t);v?f.opacity=[{test:v,...En(g??1)},En(l.legend.unselectedOpacity)]:g&&(f.opacity=En(g))}return f={...f,...e},dn(f)?void 0:f}function H_e(e,{model:t,legendType:n,legendCmpt:r}){if(n!=="gradient")return;const{config:i,markDef:s,encoding:a}=t;let o={};const u=(r.get("gradientOpacity")??i.legend.gradientOpacity)===void 0?iq(a.opacity)||s.opacity:void 0;return u&&(o.opacity=En(u)),o={...o,...e},dn(o)?void 0:o}function G_e(e,{fieldOrDatumDef:t,model:n,channel:r,legendCmpt:i}){const s=n.legend(r)||{},a=n.config,o=Oe(t)?aq(n,i,t):void 0,l=o?[{test:o,value:1},{value:a.legend.unselectedOpacity}]:void 0,{format:u,formatType:c}=s;let f;sf(c)?f=oa({fieldOrDatumDef:t,field:"datum.value",format:u,formatType:c,config:a}):u===void 0&&c===void 0&&a.customFormatTypes&&(t.type==="quantitative"&&a.numberFormatType?f=oa({fieldOrDatumDef:t,field:"datum.value",format:a.numberFormat,formatType:a.numberFormatType,config:a}):t.type==="temporal"&&a.timeFormatType&&Oe(t)&&t.timeUnit===void 0&&(f=oa({fieldOrDatumDef:t,field:"datum.value",format:a.timeFormat,formatType:a.timeFormatType,config:a})));const d={...l?{opacity:l}:{},...f?{text:f}:{},...e};return dn(d)?void 0:d}function Y_e(e,{legendCmpt:t}){const n=t.get("selections");return n!=null&&n.length?{...e,fill:{value:"transparent"}}:e}function iq(e){return sq(e,(t,n)=>Math.max(t,n.value))}function BA(e){return sq(e,(t,n)=>Vn(t,n.value))}function sq(e,t){if(Tve(e))return He(e.condition).reduce(t,e.value);if(ma(e))return e.value}function aq(e,t,n){const r=t.get("selections");if(!(r!=null&&r.length))return;const i=Pe(n.field);return r.map(s=>`(!length(data(${Pe(Cn(s)+of)})) || (${s}[${i}] && indexof(${s}[${i}], datum.value) >= 0))`).join(" || ")}const m8={direction:({direction:e})=>e,format:({fieldOrDatumDef:e,legend:t,config:n})=>{const{format:r,formatType:i}=t;return dj(e,e.type,r,i,n,!1)},formatType:({legend:e,fieldOrDatumDef:t,scaleType:n})=>{const{formatType:r}=e;return hj(r,t,n)},gradientLength:e=>{const{legend:t,legendConfig:n}=e;return t.gradientLength??n.gradientLength??exe(e)},labelOverlap:({legend:e,legendConfig:t,scaleType:n})=>e.labelOverlap??t.labelOverlap??txe(n),symbolType:({legend:e,markDef:t,channel:n,encoding:r})=>e.symbolType??X_e(t.type,n,r.shape,t.shape),title:({fieldOrDatumDef:e,config:t})=>dd(e,t,{allowDisabling:!0}),type:({legendType:e,scaleType:t,channel:n})=>{if(fd(n)&&Ka(t)){if(e==="gradient")return}else if(e==="symbol")return;return e},values:({fieldOrDatumDef:e,legend:t})=>V_e(t,e)};function V_e(e,t){const n=e.values;if(Se(n))return kj(t,n);if(ot(n))return n}function X_e(e,t,n,r){if(t!=="shape"){const i=BA(n)??r;if(i)return i}switch(e){case"bar":case"rect":case"image":case"square":return"square";case"line":case"trail":case"rule":return"stroke";case"arc":case"point":case"circle":case"tick":case"geoshape":case"area":case"text":return"circle"}}function K_e(e){const{legend:t}=e;return Vn(t.type,Z_e(e))}function Z_e({channel:e,timeUnit:t,scaleType:n}){if(fd(e)){if(Ut(["quarter","month","day"],t))return"symbol";if(Ka(n))return"gradient"}return"symbol"}function J_e({legendConfig:e,legendType:t,orient:n,legend:r}){return r.direction??e[t?"gradientDirection":"symbolDirection"]??Q_e(n,t)}function Q_e(e,t){switch(e){case"top":case"bottom":return"horizontal";case"left":case"right":case"none":case void 0:return;default:return t==="gradient"?"horizontal":void 0}}function exe({legendConfig:e,model:t,direction:n,orient:r,scaleType:i}){const{gradientHorizontalMaxLength:s,gradientHorizontalMinLength:a,gradientVerticalMaxLength:o,gradientVerticalMinLength:l}=e;if(Ka(i))return n==="horizontal"?r==="top"||r==="bottom"?v8(t,"width",a,s):a:v8(t,"height",l,o)}function v8(e,t,n,r){return{signal:`clamp(${e.getSizeSignalRef(t).signal}, ${n}, ${r})`}}function txe(e){if(Ut(["quantile","threshold","log","symlog"],e))return"greedy"}function oq(e){const t=Dn(e)?nxe(e):axe(e);return e.component.legends=t,t}function nxe(e){const{encoding:t}=e,n={};for(const r of[ji,...Yj]){const i=ir(t[r]);!i||!e.getScaleComponent(r)||r===Ui&&Oe(i)&&i.type===Ih||(n[r]=sxe(e,r))}return n}function rxe(e,t){const n=e.scaleName(t);if(e.mark==="trail"){if(t==="color")return{stroke:n};if(t==="size")return{strokeWidth:n}}return t==="color"?e.markDef.filled?{fill:n}:{stroke:n}:{[t]:n}}function ixe(e,t,n,r){switch(t){case"disable":return n!==void 0;case"values":return!!(n!=null&&n.values);case"title":if(t==="title"&&e===(r==null?void 0:r.title))return!0}return e===(n||{})[t]}function sxe(e,t){var x;let n=e.legend(t);const{markDef:r,encoding:i,config:s}=e,a=s.legend,o=new q_e({},rxe(e,t));s2e(e,t,o);const l=n!==void 0?!n:a.disable;if(o.set("disable",l,n!==void 0),l)return o;n=n||{};const u=e.getScaleComponent(t).get("type"),c=ir(i[t]),f=Oe(c)?(x=xr(c.timeUnit))==null?void 0:x.unit:void 0,d=n.orient||s.legend.orient||"right",h=K_e({legend:n,channel:t,timeUnit:f,scaleType:u}),p=J_e({legend:n,legendType:h,orient:d,legendConfig:a}),g={legend:n,channel:t,model:e,markDef:r,encoding:i,fieldOrDatumDef:c,legendConfig:a,config:s,scaleType:u,orient:d,legendType:h,direction:p};for(const w of rq){if(h==="gradient"&&w.startsWith("symbol")||h==="symbol"&&w.startsWith("gradient"))continue;const A=w in m8?m8[w](g):n[w];if(A!==void 0){const E=ixe(A,w,n,e.fieldDef(t));(E||s.legend[w]===void 0)&&o.set(w,A,E)}}const v=(n==null?void 0:n.encoding)??{},y=o.get("selections"),b={},_={fieldOrDatumDef:c,model:e,channel:t,legendCmpt:o,legendType:h};for(const w of["labels","legend","title","symbols","gradient","entries"]){const A=tq(v[w]??{},e),E=w in g8?g8[w](A,_):A;E!==void 0&&!dn(E)&&(b[w]={...y!=null&&y.length&&Oe(c)?{name:`${Cn(c.field)}_legend_${w}`}:{},...y!=null&&y.length?{interactive:!!y}:{},update:E})}return dn(b)||o.set("encode",b,!!(n!=null&&n.encoding)),o}function axe(e){const{legends:t,resolve:n}=e.component;for(const r of e.children){oq(r);for(const i of Fe(r.component.legends))n.legend[i]=$5(e.component.resolve,i),n.legend[i]==="shared"&&(t[i]=lq(t[i],r.component.legends[i]),t[i]||(n.legend[i]="independent",delete t[i]))}for(const r of Fe(t))for(const i of e.children)i.component.legends[r]&&n.legend[r]==="shared"&&delete i.component.legends[r];return t}function lq(e,t){var s,a,o,l;if(!e)return t.clone();const n=e.getWithExplicit("orient"),r=t.getWithExplicit("orient");if(n.explicit&&r.explicit&&n.value!==r.value)return;let i=!1;for(const u of rq){const c=mu(e.getWithExplicit(u),t.getWithExplicit(u),u,"legend",(f,d)=>{switch(u){case"symbolType":return oxe(f,d);case"title":return Mz(f,d);case"type":return i=!0,Vi("symbol")}return E2(f,d,u,"legend")});e.setWithExplicit(u,c)}return i&&((a=(s=e.implicit)==null?void 0:s.encode)!=null&&a.gradient&&uy(e.implicit,["encode","gradient"]),(l=(o=e.explicit)==null?void 0:o.encode)!=null&&l.gradient&&uy(e.explicit,["encode","gradient"])),e}function oxe(e,t){return t.value==="circle"?t:e}function lxe(e,t,n,r){var i,s;e.encode??(e.encode={}),(i=e.encode)[t]??(i[t]={}),(s=e.encode[t]).update??(s.update={}),e.encode[t].update[n]=r}function uq(e){const t=e.component.legends,n={};for(const i of Fe(t)){const s=e.getScaleComponent(i),a=hn(s.get("domains"));if(n[a])for(const o of n[a])lq(o,t[i])||n[a].push(t[i]);else n[a]=[t[i].clone()]}return Lr(n).flat().map(i=>uxe(i,e.config)).filter(i=>i!==void 0)}function uxe(e,t){var a,o,l;const{disable:n,labelExpr:r,selections:i,...s}=e.combine();if(!n){if(t.aria===!1&&s.aria==null&&(s.aria=!1),(a=s.encode)!=null&&a.symbols){const u=s.encode.symbols.update;u.fill&&u.fill.value!=="transparent"&&!u.stroke&&!s.stroke&&(u.stroke={value:"transparent"});for(const c of Yj)s[c]&&delete u[c]}if(s.title||delete s.title,r!==void 0){let u=r;(l=(o=s.encode)==null?void 0:o.labels)!=null&&l.update&&ot(s.encode.labels.update.text)&&(u=Jc(r,"datum.label",s.encode.labels.update.text.signal)),lxe(s,"labels","text",{signal:u})}return s}}function cxe(e){return Uh(e)||N5(e)?fxe(e):cq(e)}function fxe(e){return e.children.reduce((t,n)=>t.concat(n.assembleProjections()),cq(e))}function cq(e){const t=e.component.projection;if(!t||t.merged)return[];const n=t.combine(),{name:r}=n;if(t.data){const i={signal:`[${t.size.map(a=>a.signal).join(", ")}]`},s=t.data.reduce((a,o)=>{const l=ot(o)?o.signal:`data('${e.lookupDataSource(o)}')`;return Ut(a,l)||a.push(l),a},[]);if(s.length<=0)throw new Error("Projection's fit didn't find any data sources");return[{name:r,size:i,fit:{signal:s.length>1?`[${s.join(", ")}]`:s[0]},...n}]}else return[{name:r,translate:{signal:"[width / 2, height / 2]"},...n}]}const dxe=["type","clipAngle","clipExtent","center","rotate","precision","reflectX","reflectY","coefficient","distance","fraction","lobes","parallel","radius","ratio","spacing","tilt"];class fq extends xl{constructor(t,n,r,i){super({...n},{name:t}),this.specifiedProjection=n,this.size=r,this.data=i,this.merged=!1}get isFit(){return!!this.data}}function dq(e){e.component.projection=Dn(e)?hxe(e):mxe(e)}function hxe(e){if(e.hasProjection){const t=Fr(e.specifiedProjection),n=!(t&&(t.scale!=null||t.translate!=null)),r=n?[e.getSizeSignalRef("width"),e.getSizeSignalRef("height")]:void 0,i=n?pxe(e):void 0,s=new fq(e.projectionName(!0),{...Fr(e.config.projection),...t},r,i);return s.get("type")||s.set("type","equalEarth",!1),s}}function pxe(e){const t=[],{encoding:n}=e;for(const r of[[ka,Aa],[Bs,Sa]])(ir(n[r[0]])||ir(n[r[1]]))&&t.push({signal:e.getName(`geojson_${t.length}`)});return e.channelHasField(Ui)&&e.typedFieldDef(Ui).type===Ih&&t.push({signal:e.getName(`geojson_${t.length}`)}),t.length===0&&t.push(e.requestDataName(Tn.Main)),t}function gxe(e,t){const n=m$(dxe,i=>!!(!Ve(e.explicit,i)&&!Ve(t.explicit,i)||Ve(e.explicit,i)&&Ve(t.explicit,i)&&ns(e.get(i),t.get(i))));if(ns(e.size,t.size)){if(n)return e;if(ns(e.explicit,{}))return t;if(ns(t.explicit,{}))return e}return null}function mxe(e){if(e.children.length===0)return;let t;for(const r of e.children)dq(r);const n=m$(e.children,r=>{const i=r.component.projection;if(i)if(t){const s=gxe(t,i);return s&&(t=s),!!s}else return t=i,!0;else return!0});if(t&&n){const r=e.projectionName(!0),i=new fq(r,t.specifiedProjection,t.size,Ct(t.data));for(const s of e.children){const a=s.component.projection;a&&(a.isFit&&i.data.push(...s.component.projection.data),s.renameProjection(a.get("name"),r),a.merged=!0)}return i}}function vxe(e,t,n,r){if(X0(t,n)){const i=Dn(e)?e.axis(n)??e.legend(n)??{}:{},s=ze(t,{expr:"datum"}),a=ze(t,{expr:"datum",binSuffix:"end"});return{formulaAs:ze(t,{binSuffix:"range",forAs:!0}),formula:H0(s,a,i.format,i.formatType,r)}}return{}}function hq(e,t){return`${Ez(e)}_${t}`}function yxe(e,t){return{signal:e.getName(`${t}_bins`),extentSignal:e.getName(`${t}_extent`)}}function F5(e,t,n){const r=v2(n,void 0)??{},i=hq(r,t);return e.getName(`${i}_bins`)}function bxe(e){return"as"in e}function y8(e,t,n){let r,i;bxe(e)?r=We(e.as)?[e.as,`${e.as}_end`]:[e.as[0],e.as[1]]:r=[ze(e,{forAs:!0}),ze(e,{binSuffix:"end",forAs:!0})];const s={...v2(t,void 0)},a=hq(s,e.field),{signal:o,extentSignal:l}=yxe(n,a);if(a2(s.extent)){const c=s.extent;i=HU(n,c.param,c),delete s.extent}const u={bin:s,field:e.field,as:[r],...o?{signal:o}:{},...l?{extentSignal:l}:{},...i?{span:i}:{}};return{key:a,binComponent:u}}class no extends cn{clone(){return new no(null,Ct(this.bins))}constructor(t,n){super(t),this.bins=n}static makeFromEncoding(t,n){const r=n.reduceFieldDef((i,s,a)=>{if(bi(s)&&xn(s.bin)){const{key:o,binComponent:l}=y8(s,s.bin,n);i[o]={...l,...i[o],...vxe(n,s,a,n.config)}}return i},{});return dn(r)?null:new no(t,r)}static makeFromTransform(t,n,r){const{key:i,binComponent:s}=y8(n,n.bin,r);return new no(t,{[i]:s})}merge(t,n){for(const r of Fe(t.bins))r in this.bins?(n(t.bins[r].signal,this.bins[r].signal),this.bins[r].as=Xa([...this.bins[r].as,...t.bins[r].as],Gt)):this.bins[r]=t.bins[r];for(const r of t.children)t.removeChild(r),r.parent=this;t.remove()}producedFields(){return new Set(Lr(this.bins).map(t=>t.as).flat(2))}dependentFields(){return new Set(Lr(this.bins).map(t=>t.field))}hash(){return`Bin ${Gt(this.bins)}`}assemble(){return Lr(this.bins).flatMap(t=>{const n=[],[r,...i]=t.as,{extent:s,...a}=t.bin,o={type:"bin",field:Ps(t.field),as:r,signal:t.signal,...a2(s)?{extent:null}:{extent:s},...t.span?{span:{signal:`span(${t.span})`}}:{},...a};!s&&t.extentSignal&&(n.push({type:"extent",field:Ps(t.field),signal:t.extentSignal}),o.extent={signal:t.extentSignal}),n.push(o);for(const l of i)for(let u=0;u<2;u++)n.push({type:"formula",expr:ze({field:r[u]},{expr:"datum"}),as:l[u]});return t.formula&&n.push({type:"formula",expr:t.formula,as:t.formulaAs}),n})}}function _xe(e,t,n,r){var s;const i=Dn(r)?r.encoding[ko(t)]:void 0;if(bi(n)&&Dn(r)&&vj(n,i,r.markDef,r.config)){e.add(ze(n,{})),e.add(ze(n,{suffix:"end"}));const{mark:a,markDef:o,config:l}=r,u=gu({fieldDef:n,markDef:o,config:l});Ug(a)&&u!==.5&&Xn(t)&&(e.add(ze(n,{suffix:A2})),e.add(ze(n,{suffix:k2}))),n.bin&&X0(n,t)&&e.add(ze(n,{binSuffix:"range"}))}else if(pz(t)){const a=hz(t);e.add(r.getName(a))}else e.add(ze(n));return Cf(n)&&J1e((s=n.scale)==null?void 0:s.range)&&e.add(n.scale.range.field),e}function xxe(e,t){for(const n of Fe(t)){const r=t[n];for(const i of Fe(r))n in e?e[n][i]=new Set([...e[n][i]??[],...r[i]]):e[n]={[i]:r[i]}}}class ua extends cn{clone(){return new ua(null,new Set(this.dimensions),Ct(this.measures))}constructor(t,n,r){super(t),this.dimensions=n,this.measures=r}get groupBy(){return this.dimensions}static makeFromEncoding(t,n){let r=!1;n.forEachFieldDef(a=>{a.aggregate&&(r=!0)});const i={},s=new Set;return!r||(n.forEachFieldDef((a,o)=>{const{aggregate:l,field:u}=a;if(l)if(l==="count")i["*"]??(i["*"]={}),i["*"].count=new Set([ze(a,{forAs:!0})]);else{if(cl(l)||Ou(l)){const c=cl(l)?"argmin":"argmax",f=l[c];i[f]??(i[f]={}),i[f][c]=new Set([ze({op:c,field:f},{forAs:!0})])}else i[u]??(i[u]={}),i[u][l]=new Set([ze(a,{forAs:!0})]);So(o)&&n.scaleDomain(o)==="unaggregated"&&(i[u]??(i[u]={}),i[u].min=new Set([ze({field:u,aggregate:"min"},{forAs:!0})]),i[u].max=new Set([ze({field:u,aggregate:"max"},{forAs:!0})]))}else _xe(s,o,a,n)}),s.size+Fe(i).length===0)?null:new ua(t,s,i)}static makeFromTransform(t,n){var r;const i=new Set,s={};for(const a of n.aggregate){const{op:o,field:l,as:u}=a;o&&(o==="count"?(s["*"]??(s["*"]={}),s["*"].count=new Set([u||ze(a,{forAs:!0})])):(s[l]??(s[l]={}),(r=s[l])[o]??(r[o]=new Set),s[l][o].add(u||ze(a,{forAs:!0}))))}for(const a of n.groupby??[])i.add(a);return i.size+Fe(s).length===0?null:new ua(t,i,s)}merge(t){return sz(this.dimensions,t.dimensions)?(xxe(this.measures,t.measures),!0):(E1e("different dimensions, cannot merge"),!1)}addDimensions(t){t.forEach(this.dimensions.add,this.dimensions)}dependentFields(){return new Set([...this.dimensions,...Fe(this.measures)])}producedFields(){const t=new Set;for(const n of Fe(this.measures))for(const r of Fe(this.measures[n])){const i=this.measures[n][r];i.size===0?t.add(`${r}_${n}`):i.forEach(t.add,t)}return t}hash(){return`Aggregate ${Gt({dimensions:this.dimensions,measures:this.measures})}`}assemble(){const t=[],n=[],r=[];for(const s of Fe(this.measures))for(const a of Fe(this.measures[s]))for(const o of this.measures[s][a])r.push(o),t.push(a),n.push(s==="*"?null:Ps(s));return{type:"aggregate",groupby:[...this.dimensions].map(Ps),ops:t,fields:n,as:r}}}class zh extends cn{constructor(t,n,r,i){super(t),this.model=n,this.name=r,this.data=i;for(const s of Ss){const a=n.facet[s];if(a){const{bin:o,sort:l}=a;this[s]={name:n.getName(`${s}_domain`),fields:[ze(a),...xn(o)?[ze(a,{binSuffix:"end"})]:[]],...nl(l)?{sortField:l}:Se(l)?{sortIndexField:ch(a,s)}:{}}}}this.childModel=n.child}hash(){let t="Facet";for(const n of Ss)this[n]&&(t+=` ${n.charAt(0)}:${Gt(this[n])}`);return t}get fields(){var n;const t=[];for(const r of Ss)(n=this[r])!=null&&n.fields&&t.push(...this[r].fields);return t}dependentFields(){const t=new Set(this.fields);for(const n of Ss)this[n]&&(this[n].sortField&&t.add(this[n].sortField.field),this[n].sortIndexField&&t.add(this[n].sortIndexField));return t}producedFields(){return new Set}getSource(){return this.name}getChildIndependentFieldsWithStep(){const t={};for(const n of bl){const r=this.childModel.component.scales[n];if(r&&!r.merged){const i=r.get("type"),s=r.get("range");if(Er(i)&&Af(s)){const a=N2(this.childModel,n),o=R5(a);o?t[n]=o:Te(D$(n))}}}return t}assembleRowColumnHeaderData(t,n,r){const i={row:"y",column:"x",facet:void 0}[t],s=[],a=[],o=[];i&&r&&r[i]&&(n?(s.push(`distinct_${r[i]}`),a.push("max")):(s.push(r[i]),a.push("distinct")),o.push(`distinct_${r[i]}`));const{sortField:l,sortIndexField:u}=this[t];if(l){const{op:c=p2,field:f}=l;s.push(f),a.push(c),o.push(ze(l,{forAs:!0}))}else u&&(s.push(u),a.push("max"),o.push(u));return{name:this[t].name,source:n??this.data,transform:[{type:"aggregate",groupby:this[t].fields,...s.length?{fields:s,ops:a,as:o}:{}}]}}assembleFacetHeaderData(t){var l;const{columns:n}=this.model.layout,{layoutHeaders:r}=this.model.component,i=[],s={};for(const u of k5){for(const c of S5){const f=(r[u]&&r[u][c])??[];for(const d of f)if(((l=d.axes)==null?void 0:l.length)>0){s[u]=!0;break}}if(s[u]){const c=`length(data("${this.facet.name}"))`,f=u==="row"?n?{signal:`ceil(${c} / ${n})`}:1:n?{signal:`min(${c}, ${n})`}:{signal:c};i.push({name:`${this.facet.name}_${u}`,transform:[{type:"sequence",start:0,stop:f}]})}}const{row:a,column:o}=s;return(a||o)&&i.unshift(this.assembleRowColumnHeaderData("facet",null,t)),i}assemble(){const t=[];let n=null;const r=this.getChildIndependentFieldsWithStep(),{column:i,row:s,facet:a}=this;if(i&&s&&(r.x||r.y)){n=`cross_${this.column.name}_${this.row.name}`;const o=[].concat(r.x??[],r.y??[]),l=o.map(()=>"distinct");t.push({name:n,source:this.data,transform:[{type:"aggregate",groupby:this.fields,fields:o,ops:l}]})}for(const o of[tl,el])this[o]&&t.push(this.assembleRowColumnHeaderData(o,n,r));if(a){const o=this.assembleFacetHeaderData(r);o&&t.push(...o)}return t}}function b8(e){return e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e}function wxe(e,t){const n=b$(e);if(t==="number")return`toNumber(${n})`;if(t==="boolean")return`toBoolean(${n})`;if(t==="string")return`toString(${n})`;if(t==="date")return`toDate(${n})`;if(t==="flatten")return n;if(t.startsWith("date:")){const r=b8(t.slice(5,t.length));return`timeParse(${n},'${r}')`}else if(t.startsWith("utc:")){const r=b8(t.slice(4,t.length));return`utcParse(${n},'${r}')`}else return Te(Tme(t)),null}function Exe(e){const t={};return O1(e.filter,n=>{if(Vz(n)){let r=null;L$(n)?r=Qi(n.equal):P$(n)?r=Qi(n.lte):I$(n)?r=Qi(n.lt):B$(n)?r=Qi(n.gt):z$(n)?r=Qi(n.gte):j$(n)?r=n.range[0]:U$(n)&&(r=(n.oneOf??n.in)[0]),r&&(kf(r)?t[n.field]="date":Qt(r)?t[n.field]="number":We(r)&&(t[n.field]="string")),n.timeUnit&&(t[n.field]="date")}}),t}function Axe(e){const t={};function n(r){ah(r)?t[r.field]="date":r.type==="quantitative"&&ame(r.aggregate)?t[r.field]="number":eh(r.field)>1?r.field in t||(t[r.field]="flatten"):Cf(r)&&nl(r.sort)&&eh(r.sort.field)>1&&(r.sort.field in t||(t[r.sort.field]="flatten"))}if((Dn(e)||os(e))&&e.forEachFieldDef((r,i)=>{if(bi(r))n(r);else{const s=wf(i),a=e.fieldDef(s);n({...r,type:a.type})}}),Dn(e)){const{mark:r,markDef:i,encoding:s}=e;if(Lu(r)&&!e.encoding.order){const a=i.orient==="horizontal"?"y":"x",o=s[a];Oe(o)&&o.type==="quantitative"&&!(o.field in t)&&(t[o.field]="number")}}return t}function kxe(e){const t={};if(Dn(e)&&e.component.selection)for(const n of Fe(e.component.selection)){const r=e.component.selection[n];for(const i of r.project.items)!i.channel&&eh(i.field)>1&&(t[i.field]="flatten")}return t}class Yr extends cn{clone(){return new Yr(null,Ct(this._parse))}constructor(t,n){super(t),this._parse=n}hash(){return`Parse ${Gt(this._parse)}`}static makeExplicit(t,n,r){var a;let i={};const s=n.data;return!eu(s)&&((a=s==null?void 0:s.format)!=null&&a.parse)&&(i=s.format.parse),this.makeWithAncestors(t,i,{},r)}static makeWithAncestors(t,n,r,i){for(const o of Fe(r)){const l=i.getWithExplicit(o);l.value!==void 0&&(l.explicit||l.value===r[o]||l.value==="derived"||r[o]==="flatten"?delete r[o]:Te(w6(o,r[o],l.value)))}for(const o of Fe(n)){const l=i.get(o);l!==void 0&&(l===n[o]?delete n[o]:Te(w6(o,n[o],l)))}const s=new xl(n,r);i.copyAll(s);const a={};for(const o of Fe(s.combine())){const l=s.get(o);l!==null&&(a[o]=l)}return Fe(a).length===0||i.parseNothing?null:new Yr(t,a)}get parse(){return this._parse}merge(t){this._parse={...this._parse,...t.parse},t.remove()}assembleFormatParse(){const t={};for(const n of Fe(this._parse)){const r=this._parse[n];eh(n)===1&&(t[n]=r)}return t}producedFields(){return new Set(Fe(this._parse))}dependentFields(){return new Set(Fe(this._parse))}assembleTransforms(t=!1){return Fe(this._parse).filter(n=>t?eh(n)>1:!0).map(n=>{const r=wxe(n,this._parse[n]);return r?{type:"formula",expr:r,as:Oh(n)}:null}).filter(n=>n!==null)}}class vu extends cn{clone(){return new vu(null)}constructor(t){super(t)}dependentFields(){return new Set}producedFields(){return new Set([ya])}hash(){return"Identifier"}assemble(){return{type:"identifier",as:ya}}}class tm extends cn{clone(){return new tm(null,this.params)}constructor(t,n){super(t),this.params=n}dependentFields(){return new Set}producedFields(){}hash(){return`Graticule ${Gt(this.params)}`}assemble(){return{type:"graticule",...this.params===!0?{}:this.params}}}class nm extends cn{clone(){return new nm(null,this.params)}constructor(t,n){super(t),this.params=n}dependentFields(){return new Set}producedFields(){return new Set([this.params.as??"data"])}hash(){return`Hash ${Gt(this.params)}`}assemble(){return{type:"sequence",...this.params}}}class cf extends cn{constructor(t){super(null),t??(t={name:"source"});let n;if(eu(t)||(n=t.format?{...Li(t.format,["parse"])}:{}),qg(t))this._data={values:t.values};else if(oh(t)){if(this._data={url:t.url},!n.type){let r=/(?:\.([^.]+))?$/.exec(t.url)[1];Ut(["json","csv","tsv","dsv","topojson"],r)||(r="json"),n.type=r}}else fU(t)?this._data={values:[{type:"Sphere"}]}:(uU(t)||eu(t))&&(this._data={});this._generator=eu(t),t.name&&(this._name=t.name),n&&!dn(n)&&(this._data.format=n)}dependentFields(){return new Set}producedFields(){}get data(){return this._data}hasName(){return!!this._name}get isGenerator(){return this._generator}get dataName(){return this._name}set dataName(t){this._name=t}set parent(t){throw new Error("Source nodes have to be roots.")}remove(){throw new Error("Source nodes are roots and cannot be removed.")}hash(){throw new Error("Cannot hash sources")}assemble(){return{name:this._name,...this._data,transform:[]}}}var _8=function(e,t,n,r,i){if(r==="m")throw new TypeError("Private method is not writable");if(r==="a"&&!i)throw new TypeError("Private accessor was defined without a setter");if(typeof t=="function"?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return r==="a"?i.call(e,n):i?i.value=n:t.set(e,n),n},Sxe=function(e,t,n,r){if(n==="a"&&!r)throw new TypeError("Private accessor was defined without a getter");if(typeof t=="function"?e!==t||!r:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return n==="m"?r:n==="a"?r.call(e):r?r.value:t.get(e)},Hp;function D5(e){return e instanceof cf||e instanceof tm||e instanceof nm}class M5{constructor(){Hp.set(this,void 0),_8(this,Hp,!1,"f")}setModified(){_8(this,Hp,!0,"f")}get modifiedFlag(){return Sxe(this,Hp,"f")}}Hp=new WeakMap;class Ff extends M5{getNodeDepths(t,n,r){r.set(t,n);for(const i of t.children)this.getNodeDepths(i,n+1,r);return r}optimize(t){const r=[...this.getNodeDepths(t,0,new Map).entries()].sort((i,s)=>s[1]-i[1]);for(const i of r)this.run(i[0]);return this.modifiedFlag}}class T5 extends M5{optimize(t){this.run(t);for(const n of t.children)this.optimize(n);return this.modifiedFlag}}class Cxe extends T5{mergeNodes(t,n){const r=n.shift();for(const i of n)t.removeChild(i),i.parent=r,i.remove()}run(t){const n=t.children.map(i=>i.hash()),r={};for(let i=0;i1&&(this.setModified(),this.mergeNodes(t,r[i]))}}class $xe extends T5{constructor(t){super(),this.requiresSelectionId=t&&x5(t)}run(t){t instanceof vu&&(this.requiresSelectionId&&(D5(t.parent)||t.parent instanceof ua||t.parent instanceof Yr)||(this.setModified(),t.remove()))}}class Fxe extends M5{optimize(t){return this.run(t,new Set),this.modifiedFlag}run(t,n){let r=new Set;t instanceof eo&&(r=t.producedFields(),v$(r,n)&&(this.setModified(),t.removeFormulas(n),t.producedFields.length===0&&t.remove()));for(const i of t.children)this.run(i,new Set([...n,...r]))}}class Dxe extends T5{constructor(){super()}run(t){t instanceof Ii&&!t.isRequired()&&(this.setModified(),t.remove())}}class Mxe extends Ff{run(t){if(!D5(t)&&!(t.numChildren()>1)){for(const n of t.children)if(n instanceof Yr)if(t instanceof Yr)this.setModified(),t.merge(n);else{if(y$(t.producedFields(),n.dependentFields()))continue;this.setModified(),n.swapWithParent()}}}}class Txe extends Ff{run(t){const n=[...t.children],r=t.children.filter(i=>i instanceof Yr);if(t.numChildren()>1&&r.length>=1){const i={},s=new Set;for(const a of r){const o=a.parse;for(const l of Fe(o))l in i?i[l]!==o[l]&&s.add(l):i[l]=o[l]}for(const a of s)delete i[a];if(!dn(i)){this.setModified();const a=new Yr(t,i);for(const o of n){if(o instanceof Yr)for(const l of Fe(i))delete o.parse[l];t.removeChild(o),o.parent=a,o instanceof Yr&&Fe(o.parse).length===0&&o.remove()}}}}}class Rxe extends Ff{run(t){t instanceof Ii||t.numChildren()>0||t instanceof zh||t instanceof cf||(this.setModified(),t.remove())}}class Nxe extends Ff{run(t){const n=t.children.filter(i=>i instanceof eo),r=n.pop();for(const i of n)this.setModified(),r.merge(i)}}class Oxe extends Ff{run(t){const n=t.children.filter(i=>i instanceof ua),r={};for(const i of n){const s=Gt(i.groupBy);s in r||(r[s]=[]),r[s].push(i)}for(const i of Fe(r)){const s=r[i];if(s.length>1){const a=s.pop();for(const o of s)a.merge(o)&&(t.removeChild(o),o.parent=a,o.remove(),this.setModified())}}}}class Lxe extends Ff{constructor(t){super(),this.model=t}run(t){const n=!(D5(t)||t instanceof Bh||t instanceof Yr||t instanceof vu),r=[],i=[];for(const s of t.children)s instanceof no&&(n&&!y$(t.producedFields(),s.dependentFields())?r.push(s):i.push(s));if(r.length>0){const s=r.pop();for(const a of r)s.merge(a,this.model.renameSignal.bind(this.model));this.setModified(),t instanceof no?t.merge(s,this.model.renameSignal.bind(this.model)):s.swapWithParent()}if(i.length>1){const s=i.pop();for(const a of i)s.merge(a,this.model.renameSignal.bind(this.model));this.setModified()}}}class Ixe extends Ff{run(t){const n=[...t.children];if(!Qd(n,a=>a instanceof Ii)||t.numChildren()<=1)return;const i=[];let s;for(const a of n)if(a instanceof Ii){let o=a;for(;o.numChildren()===1;){const[l]=o.children;if(l instanceof Ii)o=l;else break}i.push(...o.children),s?(t.removeChild(a),a.parent=s.parent,s.parent.removeChild(s),s.parent=o,this.setModified()):s=o}else i.push(a);if(i.length){this.setModified();for(const a of i)a.parent.removeChild(a),a.parent=s}}}class Df extends cn{clone(){return new Df(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n}addDimensions(t){this.transform.groupby=Xa(this.transform.groupby.concat(t),n=>n)}dependentFields(){const t=new Set;return this.transform.groupby&&this.transform.groupby.forEach(t.add,t),this.transform.joinaggregate.map(n=>n.field).filter(n=>n!==void 0).forEach(t.add,t),t}producedFields(){return new Set(this.transform.joinaggregate.map(this.getDefaultName))}getDefaultName(t){return t.as??ze(t)}hash(){return`JoinAggregateTransform ${Gt(this.transform)}`}assemble(){const t=[],n=[],r=[];for(const s of this.transform.joinaggregate)n.push(s.op),r.push(this.getDefaultName(s)),t.push(s.field===void 0?null:s.field);const i=this.transform.groupby;return{type:"joinaggregate",as:r,ops:n,fields:t,...i!==void 0?{groupby:i}:{}}}}class dh extends cn{clone(){return new dh(null,{...this.filter})}constructor(t,n){super(t),this.filter=n}static make(t,n,r){const{config:i,markDef:s}=n,{marks:a,scales:o}=r;if(a==="include-invalid-values"&&o==="include-invalid-values")return null;const l=n.reduceFieldDef((u,c,f)=>{const d=So(f)&&n.getScaleComponent(f);if(d){const h=d.get("type"),{aggregate:p}=c,g=X$({scaleChannel:f,markDef:s,config:i,scaleType:h,isCountAggregate:s2(p)});g!=="show"&&g!=="always-valid"&&(u[c.field]=c)}return u},{});return Fe(l).length?new dh(t,l):null}dependentFields(){return new Set(Fe(this.filter))}producedFields(){return new Set}hash(){return`FilterInvalid ${Gt(this.filter)}`}assemble(){const t=Fe(this.filter).reduce((n,r)=>{const i=this.filter[r],s=ze(i,{expr:"datum"});return i!==null&&(i.type==="temporal"?n.push(`(isDate(${s}) || (${zA(s)}))`):i.type==="quantitative"&&n.push(zA(s))),n},[]);return t.length>0?{type:"filter",expr:t.join(" && ")}:null}}function zA(e){return`isValid(${e}) && isFinite(+${e})`}function Pxe(e){return e.stack.stackBy.reduce((t,n)=>{const r=n.fieldDef,i=ze(r);return i&&t.push(i),t},[])}function Bxe(e){return Se(e)&&e.every(t=>We(t))&&e.length>1}class il extends cn{clone(){return new il(null,Ct(this._stack))}constructor(t,n){super(t),this._stack=n}static makeFromTransform(t,n){const{stack:r,groupby:i,as:s,offset:a="zero"}=n,o=[],l=[];if(n.sort!==void 0)for(const f of n.sort)o.push(f.field),l.push(Vn(f.order,"ascending"));const u={field:o,order:l};let c;return Bxe(s)?c=s:We(s)?c=[s,`${s}_end`]:c=[`${n.stack}_start`,`${n.stack}_end`],new il(t,{dimensionFieldDefs:[],stackField:r,groupby:i,offset:a,sort:u,facetby:[],as:c})}static makeFromEncoding(t,n){const r=n.stack,{encoding:i}=n;if(!r)return null;const{groupbyChannels:s,fieldChannel:a,offset:o,impute:l}=r,u=s.map(h=>{const p=i[h];return va(p)}).filter(h=>!!h),c=Pxe(n),f=n.encoding.order;let d;if(Se(f)||Oe(f))d=$z(f);else{const h=yj(f)?f.sort:a==="y"?"descending":"ascending";d=c.reduce((p,g)=>(p.field.includes(g)||(p.field.push(g),p.order.push(h)),p),{field:[],order:[]})}return new il(t,{dimensionFieldDefs:u,stackField:n.vgField(a),facetby:[],stackby:c,sort:d,offset:o,impute:l,as:[n.vgField(a,{suffix:"start",forAs:!0}),n.vgField(a,{suffix:"end",forAs:!0})]})}get stack(){return this._stack}addDimensions(t){this._stack.facetby.push(...t)}dependentFields(){const t=new Set;return t.add(this._stack.stackField),this.getGroupbyFields().forEach(t.add,t),this._stack.facetby.forEach(t.add,t),this._stack.sort.field.forEach(t.add,t),t}producedFields(){return new Set(this._stack.as)}hash(){return`Stack ${Gt(this._stack)}`}getGroupbyFields(){const{dimensionFieldDefs:t,impute:n,groupby:r}=this._stack;return t.length>0?t.map(i=>i.bin?n?[ze(i,{binSuffix:"mid"})]:[ze(i,{}),ze(i,{binSuffix:"end"})]:[ze(i)]).flat():r??[]}assemble(){const t=[],{facetby:n,dimensionFieldDefs:r,stackField:i,stackby:s,sort:a,offset:o,impute:l,as:u}=this._stack;if(l)for(const c of r){const{bandPosition:f=.5,bin:d}=c;if(d){const h=ze(c,{expr:"datum"}),p=ze(c,{expr:"datum",binSuffix:"end"});t.push({type:"formula",expr:`${zA(h)} ? ${f}*${h}+${1-f}*${p} : ${h}`,as:ze(c,{binSuffix:"mid",forAs:!0})})}t.push({type:"impute",field:i,groupby:[...s,...n],key:ze(c,{binSuffix:"mid"}),method:"value",value:0})}return t.push({type:"stack",groupby:[...this.getGroupbyFields(),...n],field:i,sort:a,as:u,offset:o}),t}}class jh extends cn{clone(){return new jh(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n}addDimensions(t){this.transform.groupby=Xa(this.transform.groupby.concat(t),n=>n)}dependentFields(){const t=new Set;return(this.transform.groupby??[]).forEach(t.add,t),(this.transform.sort??[]).forEach(n=>t.add(n.field)),this.transform.window.map(n=>n.field).filter(n=>n!==void 0).forEach(t.add,t),t}producedFields(){return new Set(this.transform.window.map(this.getDefaultName))}getDefaultName(t){return t.as??ze(t)}hash(){return`WindowTransform ${Gt(this.transform)}`}assemble(){const t=[],n=[],r=[],i=[];for(const f of this.transform.window)n.push(f.op),r.push(this.getDefaultName(f)),i.push(f.param===void 0?null:f.param),t.push(f.field===void 0?null:f.field);const s=this.transform.frame,a=this.transform.groupby;if(s&&s[0]===null&&s[1]===null&&n.every(f=>$$(f)))return{type:"joinaggregate",as:r,ops:n,fields:t,...a!==void 0?{groupby:a}:{}};const o=[],l=[];if(this.transform.sort!==void 0)for(const f of this.transform.sort)o.push(f.field),l.push(f.order??"ascending");const u={field:o,order:l},c=this.transform.ignorePeers;return{type:"window",params:i,as:r,ops:n,fields:t,sort:u,...c!==void 0?{ignorePeers:c}:{},...a!==void 0?{groupby:a}:{},...s!==void 0?{frame:s}:{}}}}function zxe(e){function t(n){if(!(n instanceof zh)){const r=n.clone();if(r instanceof Ii){const i=UA+r.getSource();r.setSource(i),e.model.component.data.outputNodes[i]=r}else(r instanceof ua||r instanceof il||r instanceof jh||r instanceof Df)&&r.addDimensions(e.fields);for(const i of n.children.flatMap(t))i.parent=r;return[r]}return n.children.flatMap(t)}return t}function jA(e){if(e instanceof zh)if(e.numChildren()===1&&!(e.children[0]instanceof Ii)){const t=e.children[0];(t instanceof ua||t instanceof il||t instanceof jh||t instanceof Df)&&t.addDimensions(e.fields),t.swapWithParent(),jA(e)}else{const t=e.model.component.data.main;pq(t);const n=zxe(e),r=e.children.map(n).flat();for(const i of r)i.parent=t}else e.children.map(jA)}function pq(e){if(e instanceof Ii&&e.type===Tn.Main&&e.numChildren()===1){const t=e.children[0];t instanceof zh||(t.swapWithParent(),pq(e))}}const UA="scale_",Um=5;function qA(e){for(const t of e){for(const n of t.children)if(n.parent!==t)return!1;if(!qA(t.children))return!1}return!0}function Hs(e,t){let n=!1;for(const r of t)n=e.optimize(r)||n;return n}function x8(e,t,n){let r=e.sources,i=!1;return i=Hs(new Dxe,r)||i,i=Hs(new $xe(t),r)||i,r=r.filter(s=>s.numChildren()>0),i=Hs(new Rxe,r)||i,r=r.filter(s=>s.numChildren()>0),n||(i=Hs(new Mxe,r)||i,i=Hs(new Lxe(t),r)||i,i=Hs(new Fxe,r)||i,i=Hs(new Txe,r)||i,i=Hs(new Oxe,r)||i,i=Hs(new Nxe,r)||i,i=Hs(new Cxe,r)||i,i=Hs(new Ixe,r)||i),e.sources=r,i}function jxe(e,t){qA(e.sources);let n=0,r=0;for(let i=0;it(n))}}function gq(e){Dn(e)?Uxe(e):qxe(e)}function Uxe(e){const t=e.component.scales;for(const n of Fe(t)){const r=Hxe(e,n);if(t[n].setWithExplicit("domains",r),Yxe(e,n),e.component.data.isFaceted){let s=e;for(;!os(s)&&s.parent;)s=s.parent;if(s.component.resolve.scale[n]==="shared")for(const o of r.value)Vo(o)&&(o.data=UA+o.data.replace(UA,""))}}}function qxe(e){for(const n of e.children)gq(n);const t=e.component.scales;for(const n of Fe(t)){let r,i=null;for(const s of e.children){const a=s.component.scales[n];if(a){r===void 0?r=a.getWithExplicit("domains"):r=mu(r,a.getWithExplicit("domains"),"domains","scale",WA);const o=a.get("selectionExtent");i&&o&&i.param!==o.param&&Te(kme),i=o}}t[n].setWithExplicit("domains",r),i&&t[n].set("selectionExtent",i,!0)}}function Wxe(e,t,n,r){if(e==="unaggregated"){const{valid:i,reason:s}=w8(t,n);if(!i){Te(s);return}}else if(e===void 0&&r.useUnaggregatedDomain){const{valid:i}=w8(t,n);if(i)return"unaggregated"}return e}function Hxe(e,t){const n=e.getScaleComponent(t).get("type"),{encoding:r}=e,i=Wxe(e.scaleDomain(t),e.typedFieldDef(t),n,e.config.scale);return i!==e.scaleDomain(t)&&(e.specifiedScales[t]={...e.specifiedScales[t],domain:i}),t==="x"&&ir(r.x2)?ir(r.x)?mu(Cl(n,i,e,"x"),Cl(n,i,e,"x2"),"domain","scale",WA):Cl(n,i,e,"x2"):t==="y"&&ir(r.y2)?ir(r.y)?mu(Cl(n,i,e,"y"),Cl(n,i,e,"y2"),"domain","scale",WA):Cl(n,i,e,"y2"):Cl(n,i,e,t)}function Gxe(e,t,n){return e.map(r=>({signal:`{data: ${y2(r,{timeUnit:n,type:t})}}`}))}function Lx(e,t,n){var i;const r=(i=xr(n))==null?void 0:i.unit;return t==="temporal"||r?Gxe(e,t,r):[e]}function Cl(e,t,n,r){const{encoding:i,markDef:s,mark:a,config:o,stack:l}=n,u=ir(i[r]),{type:c}=u,f=u.timeUnit,d=Fbe({invalid:co("invalid",s,o),isPath:Lu(a)});if(Z1e(t)){const g=Cl(e,void 0,n,r),v=Lx(t.unionWith,c,f);return Pa([...v,...g.value])}else{if(ot(t))return Pa([t]);if(t&&t!=="unaggregated"&&!tj(t))return Pa(Lx(t,c,f))}if(l&&r===l.fieldChannel){if(l.offset==="normalize")return Vi([[0,1]]);const g=n.requestDataName(d);return Vi([{data:g,field:n.vgField(r,{suffix:"start"})},{data:g,field:n.vgField(r,{suffix:"end"})}])}const h=So(r)&&Oe(u)?Vxe(n,r,e):void 0;if(Co(u)){const g=Lx([u.datum],c,f);return Vi(g)}const p=u;if(t==="unaggregated"){const{field:g}=u;return Vi([{data:n.requestDataName(d),field:ze({field:g,aggregate:"min"})},{data:n.requestDataName(d),field:ze({field:g,aggregate:"max"})}])}else if(xn(p.bin)){if(Er(e))return Vi(e==="bin-ordinal"?[]:[{data:zg(h)?n.requestDataName(d):n.requestDataName(Tn.Raw),field:n.vgField(r,X0(p,r)?{binSuffix:"range"}:{}),sort:h===!0||!Ue(h)?{field:n.vgField(r,{}),op:"min"}:h}]);{const{bin:g}=p;if(xn(g)){const v=F5(n,p.field,g);return Vi([new hr(()=>{const y=n.getSignalName(v);return`[${y}.start, ${y}.stop]`})])}else return Vi([{data:n.requestDataName(d),field:n.vgField(r,{})}])}}else if(p.timeUnit&&Ut(["time","utc"],e)){const g=i[ko(r)];if(vj(p,g,s,o)){const v=n.requestDataName(d),y=gu({fieldDef:p,fieldDef2:g,markDef:s,config:o}),b=Ug(a)&&y!==.5&&Xn(r);return Vi([{data:v,field:n.vgField(r,b?{suffix:A2}:{})},{data:v,field:n.vgField(r,{suffix:b?k2:"end"})}])}}return Vi(h?[{data:zg(h)?n.requestDataName(d):n.requestDataName(Tn.Raw),field:n.vgField(r),sort:h}]:[{data:n.requestDataName(d),field:n.vgField(r)}])}function Ix(e,t){const{op:n,field:r,order:i}=e;return{op:n??(t?"sum":p2),...r?{field:Ps(r)}:{},...i?{order:i}:{}}}function Yxe(e,t){var o;const n=e.component.scales[t],r=e.specifiedScales[t].domain,i=(o=e.fieldDef(t))==null?void 0:o.bin,s=tj(r)?r:void 0,a=Ef(i)&&a2(i.extent)?i.extent:void 0;(s||a)&&n.set("selectionExtent",s??a,!0)}function Vxe(e,t,n){if(!Er(n))return;const r=e.fieldDef(t),i=r.sort;if(gj(i))return{op:"min",field:ch(r,t),order:"ascending"};const{stack:s}=e,a=s?new Set([...s.groupbyFields,...s.stackBy.map(o=>o.fieldDef.field)]):void 0;if(nl(i)){const o=s&&!a.has(i.field);return Ix(i,o)}else if(Fve(i)){const{encoding:o,order:l}=i,u=e.fieldDef(o),{aggregate:c,field:f}=u,d=s&&!a.has(f);if(cl(c)||Ou(c))return Ix({field:ze(u),order:l},d);if($$(c)||!c)return Ix({op:c,field:f,order:l},d)}else{if(i==="descending")return{op:"min",field:e.vgField(t),order:"descending"};if(Ut(["ascending",void 0],i))return!0}}function w8(e,t){const{aggregate:n,type:r}=e;return n?We(n)&&!lme.has(n)?{valid:!1,reason:e1e(n)}:r==="quantitative"&&t==="log"?{valid:!1,reason:t1e(e)}:{valid:!0}:{valid:!1,reason:Qme(e)}}function WA(e,t,n,r){return e.explicit&&t.explicit&&Te(a1e(n,r,e.value,t.value)),{explicit:e.explicit,value:[...e.value,...t.value]}}function Xxe(e){const t=Xa(e.map(a=>{if(Vo(a)){const{sort:o,...l}=a;return l}return a}),Gt),n=Xa(e.map(a=>{if(Vo(a)){const o=a.sort;return o!==void 0&&!zg(o)&&("op"in o&&o.op==="count"&&delete o.field,o.order==="ascending"&&delete o.order),o}}).filter(a=>a!==void 0),Gt);if(t.length===0)return;if(t.length===1){const a=e[0];if(Vo(a)&&n.length>0){let o=n[0];if(n.length>1){Te(A6);const l=n.filter(u=>Ue(u)&&"op"in u&&u.op!=="min");n.every(u=>Ue(u)&&"op"in u)&&l.length===1?o=l[0]:o=!0}else if(Ue(o)&&"field"in o){const l=o.field;a.field===l&&(o=o.order?{order:o.order}:!0)}return{...a,sort:o}}return a}const r=Xa(n.map(a=>zg(a)||!("op"in a)||We(a.op)&&Ve(ime,a.op)?a:(Te(l1e(a)),!0)),Gt);let i;r.length===1?i=r[0]:r.length>1&&(Te(A6),i=!0);const s=Xa(e.map(a=>Vo(a)?a.data:null),a=>a);return s.length===1&&s[0]!==null?{data:s[0],fields:t.map(o=>o.field),...i?{sort:i}:{}}:{fields:t,...i?{sort:i}:{}}}function R5(e){if(Vo(e)&&We(e.field))return e.field;if(ume(e)){let t;for(const n of e.fields)if(Vo(n)&&We(n.field)){if(!t)t=n.field;else if(t!==n.field)return Te(u1e),t}return Te(c1e),t}else if(cme(e)){Te(f1e);const t=e.fields[0];return We(t)?t:void 0}}function N2(e,t){const r=e.component.scales[t].get("domains").map(i=>(Vo(i)&&(i.data=e.lookupDataSource(i.data)),i));return Xxe(r)}function mq(e){return Uh(e)||N5(e)?e.children.reduce((t,n)=>t.concat(mq(n)),E8(e)):E8(e)}function E8(e){return Fe(e.component.scales).reduce((t,n)=>{const r=e.component.scales[n];if(r.merged)return t;const i=r.combine(),{name:s,type:a,selectionExtent:o,domains:l,range:u,reverse:c,...f}=i,d=Kxe(i.range,s,n,e),h=N2(e,n),p=o?zbe(e,o,r,h):null;return t.push({name:s,type:a,...h?{domain:h}:{},...p?{domainRaw:p}:{},range:d,...c!==void 0?{reverse:c}:{},...f}),t},[])}function Kxe(e,t,n,r){if(Xn(n)){if(Af(e))return{step:{signal:`${t}_step`}}}else if(Ue(e)&&Vo(e))return{...e,data:r.lookupDataSource(e.data)};return e}class vq extends xl{constructor(t,n){super({},{name:t}),this.merged=!1,this.setWithExplicit("type",n)}domainHasZero(){const t=this.get("type");if(Ut([Dr.LOG,Dr.TIME,Dr.UTC],t))return"definitely-not";const n=this.get("zero");if(n===!0||n===void 0&&Ut([Dr.LINEAR,Dr.SQRT,Dr.POW],t))return"definitely";const r=this.get("domains");if(r.length>0){let i=!1,s=!1,a=!1;for(const o of r){if(Se(o)){const l=o[0],u=o[o.length-1];if(Qt(l)&&Qt(u))if(l<=0&&u>=0){i=!0;continue}else{s=!0;continue}}a=!0}if(i)return"definitely";if(s&&!a)return"definitely-not"}return"maybe"}}const Zxe=["range","scheme"];function Jxe(e){const t=e.component.scales;for(const n of C$){const r=t[n];if(!r)continue;const i=Qxe(n,e);r.setWithExplicit("range",i)}}function A8(e,t){const n=e.fieldDef(t);if(n!=null&&n.bin){const{bin:r,field:i}=n,s=qi(t),a=e.getName(s);if(Ue(r)&&r.binned&&r.step!==void 0)return new hr(()=>{const o=e.scaleName(t),l=`(domain("${o}")[1] - domain("${o}")[0]) / ${r.step}`;return`${e.getSignalName(a)} / (${l})`});if(xn(r)){const o=F5(e,i,r);return new hr(()=>{const l=e.getSignalName(o),u=`(${l}.stop - ${l}.start) / ${l}.step`;return`${e.getSignalName(a)} / (${u})`})}}}function Qxe(e,t){const n=t.specifiedScales[e],{size:r}=t,s=t.getScaleComponent(e).get("type");for(const f of Zxe)if(n[f]!==void 0){const d=wA(s,f),h=nj(e,f);if(!d)Te(Oz(s,f,e));else if(h)Te(h);else switch(f){case"range":{const p=n.range;if(Se(p)){if(Xn(e))return Pa(p.map(g=>{if(g==="width"||g==="height"){const v=t.getName(g),y=t.getSignalName.bind(t);return hr.fromName(y,v)}return g}))}else if(Ue(p))return Pa({data:t.requestDataName(Tn.Main),field:p.field,sort:{op:"min",field:t.vgField(e)}});return Pa(p)}case"scheme":return Pa(ewe(n[f]))}}const a=e===$n||e==="xOffset"?"width":"height",o=r[a];if(ho(o)){if(Xn(e))if(Er(s)){const f=bq(o,t,e);if(f)return Pa({step:f})}else Te(Lz(a));else if(U0(e)){const f=e===Fu?"x":"y";if(t.getScaleComponent(f).get("type")==="band"){const p=_q(o,s);if(p)return Pa(p)}}}const{rangeMin:l,rangeMax:u}=n,c=twe(e,t);return(l!==void 0||u!==void 0)&&wA(s,"rangeMin")&&Se(c)&&c.length===2?Pa([l??c[0],u??c[1]]):Vi(c)}function ewe(e){return K1e(e)?{scheme:e.name,...Li(e,["name"])}:{scheme:e}}function yq(e,t,n,{center:r}={}){const i=qi(e),s=t.getName(i),a=t.getSignalName.bind(t);return e===kr&&ga(n)?r?[hr.fromName(o=>`${a(o)}/2`,s),hr.fromName(o=>`-${a(o)}/2`,s)]:[hr.fromName(a,s),0]:r?[hr.fromName(o=>`-${a(o)}/2`,s),hr.fromName(o=>`${a(o)}/2`,s)]:[0,hr.fromName(a,s)]}function twe(e,t){const{size:n,config:r,mark:i,encoding:s}=t,{type:a}=ir(s[e]),l=t.getScaleComponent(e).get("type"),{domain:u,domainMid:c}=t.specifiedScales[e];switch(e){case $n:case kr:{if(Ut(["point","band"],l)){const f=xq(e,n,r.view);if(ho(f))return{step:bq(f,t,e)}}return yq(e,t,l)}case Fu:case Lh:return nwe(e,t,l);case vl:{const f=swe(i,r),d=awe(i,n,t,r);return rh(l)?iwe(f,d,rwe(l,r,u,e)):[f,d]}case js:return[0,Math.PI*2];case xf:return[0,360];case Ea:return[0,new hr(()=>{const f=t.getSignalName(os(t.parent)?"child_width":"width"),d=t.getSignalName(os(t.parent)?"child_height":"height");return`min(${f},${d})/2`})];case Du:return{step:1e3/r.scale.framesPerSecond};case Ru:return[r.scale.minStrokeWidth,r.scale.maxStrokeWidth];case Nu:return[[1,0],[4,2],[2,1],[1,1],[1,2,4,2]];case Ui:return"symbol";case ji:case Eo:case Ao:return l==="ordinal"?a==="nominal"?"category":"ordinal":c!==void 0?"diverging":i==="rect"||i==="geoshape"?"heatmap":"ramp";case yl:case Mu:case Tu:return[r.scale.minOpacity,r.scale.maxOpacity]}}function bq(e,t,n){const{encoding:r}=t,i=t.getScaleComponent(n),s=E$(n),a=r[s];if(Xj({step:e,offsetIsDiscrete:$t(a)&&Kz(a.type)})==="offset"&&Fj(r,s)){const l=t.getScaleComponent(s);let c=`domain('${t.scaleName(s)}').length`;if(l.get("type")==="band"){const d=l.get("paddingInner")??l.get("padding")??0,h=l.get("paddingOuter")??l.get("padding")??0;c=`bandspace(${c}, ${d}, ${h})`}const f=i.get("paddingInner")??i.get("padding");return{signal:`${e.step} * ${c} / (1-${pme(f)})`}}else return e.step}function _q(e,t){if(Xj({step:e,offsetIsDiscrete:Er(t)})==="offset")return{step:e.step}}function nwe(e,t,n){const r=e===Fu?"x":"y",i=t.getScaleComponent(r);if(!i)return yq(r,t,n,{center:!0});const s=i.get("type"),a=t.scaleName(r),{markDef:o,config:l}=t;if(s==="band"){const u=xq(r,t.size,t.config.view);if(ho(u)){const c=_q(u,n);if(c)return c}return[0,{signal:`bandwidth('${a}')`}]}else{const u=t.encoding[r];if(Oe(u)&&u.timeUnit){const c=Gz(u.timeUnit,p=>`scale('${a}', ${p})`),f=t.config.scale.bandWithNestedOffsetPaddingInner,d=gu({fieldDef:u,markDef:o,config:l})-.5,h=d!==0?` + ${d}`:"";if(f){const p=ot(f)?`${f.signal}/2`+h:`${f/2+d}`,g=ot(f)?`(1 - ${f.signal}/2)`+h:`${1-f/2+d}`;return[{signal:`${p} * (${c})`},{signal:`${g} * (${c})`}]}return[0,{signal:c}]}return rz(`Cannot use ${e} scale if ${r} scale is not discrete.`)}}function xq(e,t,n){const r=e===$n?"width":"height",i=t[r];return i||yy(n,r)}function rwe(e,t,n,r){switch(e){case"quantile":return t.scale.quantileCount;case"quantize":return t.scale.quantizeCount;case"threshold":return n!==void 0&&Se(n)?n.length+1:(Te(_1e(r)),3)}}function iwe(e,t,n){const r=()=>{const i=aa(t),s=aa(e),a=`(${i} - ${s}) / (${n} - 1)`;return`sequence(${s}, ${i} + ${a}, ${a})`};return ot(t)?new hr(r):{signal:r()}}function swe(e,t){switch(e){case"bar":case"tick":return t.scale.minBandSize;case"line":case"trail":case"rule":return t.scale.minStrokeWidth;case"text":return t.scale.minFontSize;case"point":case"square":case"circle":return t.scale.minSize}throw new Error(o2("size",e))}const k8=.95;function awe(e,t,n,r){const i={x:A8(n,"x"),y:A8(n,"y")};switch(e){case"bar":case"tick":{if(r.scale.maxBandSize!==void 0)return r.scale.maxBandSize;const s=S8(t,i,r.view);return Qt(s)?s-1:new hr(()=>`${s.signal} - 1`)}case"line":case"trail":case"rule":return r.scale.maxStrokeWidth;case"text":return r.scale.maxFontSize;case"point":case"square":case"circle":{if(r.scale.maxSize)return r.scale.maxSize;const s=S8(t,i,r.view);return Qt(s)?Math.pow(k8*s,2):new hr(()=>`pow(${k8} * ${s.signal}, 2)`)}}throw new Error(o2("size",e))}function S8(e,t,n){const r=ho(e.width)?e.width.step:SA(n,"width"),i=ho(e.height)?e.height.step:SA(n,"height");return t.x||t.y?new hr(()=>`min(${[t.x?t.x.signal:r,t.y?t.y.signal:i].join(", ")})`):Math.min(r,i)}function wq(e,t){Dn(e)?owe(e,t):Aq(e,t)}function owe(e,t){const n=e.component.scales,{config:r,encoding:i,markDef:s,specifiedScales:a}=e;for(const o of Fe(n)){const l=a[o],u=n[o],c=e.getScaleComponent(o),f=ir(i[o]),d=l[t],h=c.get("type"),p=c.get("padding"),g=c.get("paddingInner"),v=wA(h,t),y=nj(o,t);if(d!==void 0&&(v?y&&Te(y):Te(Oz(h,t,o))),v&&y===void 0)if(d!==void 0){const b=f.timeUnit,_=f.type;switch(t){case"domainMax":case"domainMin":kf(l[t])||_==="temporal"||b?u.set(t,{signal:y2(l[t],{type:_,timeUnit:b})},!0):u.set(t,l[t],!0);break;default:u.copyKeyFromObject(t,l)}}else{const b=De(C8,t)?C8[t]({model:e,channel:o,fieldOrDatumDef:f,scaleType:h,scalePadding:p,scalePaddingInner:g,domain:l.domain,domainMin:l.domainMin,domainMax:l.domainMax,markDef:s,config:r,hasNestedOffsetScale:Dj(i,o),hasSecondaryRangeChannel:!!i[ko(o)]}):r.scale[t];b!==void 0&&u.set(t,b,!1)}}}const C8={bins:({model:e,fieldOrDatumDef:t})=>Oe(t)?lwe(e,t):void 0,interpolate:({channel:e,fieldOrDatumDef:t})=>uwe(e,t.type),nice:({scaleType:e,channel:t,domain:n,domainMin:r,domainMax:i,fieldOrDatumDef:s})=>cwe(e,t,n,r,i,s),padding:({channel:e,scaleType:t,fieldOrDatumDef:n,markDef:r,config:i})=>fwe(e,t,i.scale,n,r,i.bar),paddingInner:({scalePadding:e,channel:t,markDef:n,scaleType:r,config:i,hasNestedOffsetScale:s})=>dwe(e,t,n.type,r,i.scale,s),paddingOuter:({scalePadding:e,channel:t,scaleType:n,scalePaddingInner:r,config:i,hasNestedOffsetScale:s})=>hwe(e,t,n,r,i.scale,s),reverse:({fieldOrDatumDef:e,scaleType:t,channel:n,config:r})=>{const i=Oe(e)?e.sort:void 0;return pwe(t,i,n,r.scale)},zero:({channel:e,fieldOrDatumDef:t,domain:n,markDef:r,scaleType:i,config:s,hasSecondaryRangeChannel:a})=>gwe(e,t,n,r,i,s.scale,a)};function Eq(e){Dn(e)?Jxe(e):Aq(e,"range")}function Aq(e,t){const n=e.component.scales;for(const r of e.children)t==="range"?Eq(r):wq(r,t);for(const r of Fe(n)){let i;for(const s of e.children){const a=s.component.scales[r];if(a){const o=a.getWithExplicit(t);i=mu(i,o,t,"scale",lU((l,u)=>{switch(t){case"range":return l.step&&u.step?l.step-u.step:0}return 0}))}}n[r].setWithExplicit(t,i)}}function lwe(e,t){const n=t.bin;if(xn(n)){const r=F5(e,t.field,n);return new hr(()=>e.getSignalName(r))}else if(Cr(n)&&Ef(n)&&n.step!==void 0)return{step:n.step}}function uwe(e,t){if(Ut([ji,Eo,Ao],e)&&t!=="nominal")return"hcl"}function cwe(e,t,n,r,i,s){var a;if(!((a=va(s))!=null&&a.bin||Se(n)||i!=null||r!=null||Ut([Dr.TIME,Dr.UTC],e)))return Xn(t)?!0:void 0}function fwe(e,t,n,r,i,s){if(Xn(e)){if(Ka(t)){if(n.continuousPadding!==void 0)return n.continuousPadding;const{type:a,orient:o}=i;if(a==="bar"&&!(Oe(r)&&(r.bin||r.timeUnit))&&(o==="vertical"&&e==="x"||o==="horizontal"&&e==="y"))return s.continuousBandSize}if(t===Dr.POINT)return n.pointPadding}}function dwe(e,t,n,r,i,s=!1){if(e===void 0){if(Xn(t)){const{bandPaddingInner:a,barBandPaddingInner:o,rectBandPaddingInner:l,tickBandPaddingInner:u,bandWithNestedOffsetPaddingInner:c}=i;return s?c:Vn(a,n==="bar"?o:n==="tick"?u:l)}else if(U0(t)&&r===Dr.BAND)return i.offsetBandPaddingInner}}function hwe(e,t,n,r,i,s=!1){if(e===void 0){if(Xn(t)){const{bandPaddingOuter:a,bandWithNestedOffsetPaddingOuter:o}=i;if(s)return o;if(n===Dr.BAND)return Vn(a,ot(r)?{signal:`${r.signal}/2`}:r/2)}else if(U0(t)){if(n===Dr.POINT)return .5;if(n===Dr.BAND)return i.offsetBandPaddingOuter}}}function pwe(e,t,n,r){if(n==="x"&&r.xReverse!==void 0)return ga(e)&&t==="descending"?ot(r.xReverse)?{signal:`!${r.xReverse.signal}`}:!r.xReverse:r.xReverse;if(ga(e)&&t==="descending")return!0}function gwe(e,t,n,r,i,s,a){if(!!n&&n!=="unaggregated"&&ga(i)){if(Se(n)){const l=n[0],u=n[n.length-1];if(Qt(l)&&l<=0&&Qt(u)&&u>=0)return!0}return!1}if(e==="size"&&t.type==="quantitative"&&!rh(i))return!0;if(!(Oe(t)&&t.bin)&&Ut([...bl,...X0e],e)){const{orient:l,type:u}=r;return Ut(["bar","area","line","trail"],u)&&(l==="horizontal"&&e==="y"||l==="vertical"&&e==="x")?!1:Ut(["bar","area"],u)&&!a?!0:s==null?void 0:s.zero}return!1}function mwe(e,t,n,r,i=!1){const s=vwe(t,n,r,i),{type:a}=e;return So(t)?a!==void 0?rve(t,a)?Oe(n)&&!nve(a,n.type)?(Te(i1e(a,s)),s):a:(Te(r1e(t,a,s)),s):s:null}function vwe(e,t,n,r){var i;switch(t.type){case"nominal":case"ordinal":{if(fd(e)||wx(e)==="discrete")return e==="shape"&&t.type==="ordinal"&&Te(Ex(e,"ordinal")),"ordinal";if(xx(e))return"band";if(Xn(e)||U0(e)){if(Ut(["rect","bar","image","rule","tick"],n.type)||r)return"band"}else if(n.type==="arc"&&e in S$)return"band";const s=n[qi(e)];return rf(s)||sh(t)&&((i=t.axis)!=null&&i.tickBand)?"band":"point"}case"temporal":return fd(e)?"time":wx(e)==="discrete"?(Te(Ex(e,"temporal")),"ordinal"):Oe(t)&&t.timeUnit&&xr(t.timeUnit).utc?"utc":xx(e)?"band":"time";case"quantitative":return fd(e)?Oe(t)&&xn(t.bin)?"bin-ordinal":"linear":wx(e)==="discrete"?(Te(Ex(e,"quantitative")),"ordinal"):xx(e)?"band":"linear";case"geojson":return}throw new Error(Rz(t.type))}function ywe(e,{ignoreRange:t}={}){kq(e),gq(e);for(const n of tve)wq(e,n);t||Eq(e)}function kq(e){Dn(e)?e.component.scales=bwe(e):e.component.scales=xwe(e)}function bwe(e){const{encoding:t,mark:n,markDef:r}=e,i={};for(const s of C$){const a=ir(t[s]);if(a&&n===sj&&s===Ui&&a.type===Ih)continue;let o=a&&a.scale;if(a&&o!==null&&o!==!1){o??(o={});const l=Dj(t,s),u=mwe(o,s,a,r,l);i[s]=new vq(e.scaleName(`${s}`,!0),{value:u,explicit:o.type===u})}}return i}const _we=lU((e,t)=>S6(e)-S6(t));function xwe(e){var t;const n=e.component.scales={},r={},i=e.component.resolve;for(const s of e.children){kq(s);for(const a of Fe(s.component.scales))if((t=i.scale)[a]??(t[a]=nq(a,e)),i.scale[a]==="shared"){const o=r[a],l=s.component.scales[a].getWithExplicit("type");o?H1e(o.value,l.value)?r[a]=mu(o,l,"type","scale",_we):(i.scale[a]="independent",delete r[a]):r[a]=l}}for(const s of Fe(r)){const a=e.scaleName(s,!0),o=r[s];n[s]=new vq(a,o);for(const l of e.children){const u=l.component.scales[s];u&&(l.renameScale(u.get("name"),a),u.merged=!0)}}return n}class Px{constructor(){this.nameMap={}}rename(t,n){this.nameMap[t]=n}has(t){return this.nameMap[t]!==void 0}get(t){for(;this.nameMap[t]&&t!==this.nameMap[t];)t=this.nameMap[t];return t}}function Dn(e){return(e==null?void 0:e.type)==="unit"}function os(e){return(e==null?void 0:e.type)==="facet"}function N5(e){return(e==null?void 0:e.type)==="concat"}function Uh(e){return(e==null?void 0:e.type)==="layer"}class O5{constructor(t,n,r,i,s,a,o){this.type=n,this.parent=r,this.config=s,this.parent=r,this.config=s,this.view=Fr(o),this.name=t.name??i,this.title=Tl(t.title)?{text:t.title}:t.title?Fr(t.title):void 0,this.scaleNameMap=r?r.scaleNameMap:new Px,this.projectionNameMap=r?r.projectionNameMap:new Px,this.signalNameMap=r?r.signalNameMap:new Px,this.data=t.data,this.description=t.description,this.transforms=vbe(t.transform??[]),this.layout=n==="layer"||n==="unit"?{}:xye(t,n,s),this.component={data:{sources:r?r.component.data.sources:[],outputNodes:r?r.component.data.outputNodes:{},outputNodeRefCounts:r?r.component.data.outputNodeRefCounts:{},isFaceted:g2(t)||(r==null?void 0:r.component.data.isFaceted)&&t.data===void 0},layoutSize:new xl,layoutHeaders:{row:{},column:{},facet:{}},mark:null,resolve:{scale:{},axis:{},legend:{},...a?Ct(a):{}},selection:null,scales:null,projection:null,axes:{},legends:{}}}get width(){return this.getSizeSignalRef("width")}get height(){return this.getSizeSignalRef("height")}parse(){this.parseScale(),this.parseLayoutSize(),this.renameTopLevelLayoutSizeSignal(),this.parseSelections(),this.parseProjection(),this.parseData(),this.parseAxesAndHeaders(),this.parseLegends(),this.parseMarkGroup()}parseScale(){ywe(this)}parseProjection(){dq(this)}renameTopLevelLayoutSizeSignal(){this.getName("width")!=="width"&&this.renameSignal(this.getName("width"),"width"),this.getName("height")!=="height"&&this.renameSignal(this.getName("height"),"height")}parseLegends(){oq(this)}assembleEncodeFromView(t){const{style:n,...r}=t,i={};for(const s of Fe(r)){const a=r[s];a!==void 0&&(i[s]=En(a))}return i}assembleGroupEncodeEntry(t){let n={};return this.view&&(n=this.assembleEncodeFromView(this.view)),!t&&(this.description&&(n.description=En(this.description)),this.type==="unit"||this.type==="layer")?{width:this.getSizeSignalRef("width"),height:this.getSizeSignalRef("height"),...n}:dn(n)?void 0:n}assembleLayout(){if(!this.layout)return;const{spacing:t,...n}=this.layout,{component:r,config:i}=this,s=j_e(r.layoutHeaders,i);return{padding:t,...this.assembleDefaultLayout(),...n,...s?{titleBand:s}:{}}}assembleDefaultLayout(){return{}}assembleHeaderMarks(){const{layoutHeaders:t}=this.component;let n=[];for(const r of Ss)t[r].title&&n.push(O_e(this,r));for(const r of k5)n=n.concat(L_e(this,r));return n}assembleAxes(){return w_e(this.component.axes,this.config)}assembleLegends(){return uq(this)}assembleProjections(){return cxe(this)}assembleTitle(){const{encoding:t,...n}=this.title??{},r={...Az(this.config.title).nonMarkTitleProperties,...n,...t?{encode:{update:t}}:{}};if(r.text)return Ut(["unit","layer"],this.type)?Ut(["middle",void 0],r.anchor)&&(r.frame??(r.frame="group")):r.anchor??(r.anchor="start"),dn(r)?void 0:r}assembleGroup(t=[]){const n={};t=t.concat(this.assembleSignals()),t.length>0&&(n.signals=t);const r=this.assembleLayout();r&&(n.layout=r),n.marks=[].concat(this.assembleHeaderMarks(),this.assembleMarks());const i=!this.parent||os(this.parent)?mq(this):[];i.length>0&&(n.scales=i);const s=this.assembleAxes();s.length>0&&(n.axes=s);const a=this.assembleLegends();return a.length>0&&(n.legends=a),n}getName(t){return Cn((this.name?`${this.name}_`:"")+t)}getDataName(t){return this.getName(Tn[t].toLowerCase())}requestDataName(t){const n=this.getDataName(t),r=this.component.data.outputNodeRefCounts;return r[n]=(r[n]||0)+1,n}getSizeSignalRef(t){if(os(this.parent)){const n=eq(t),r=i2(n),i=this.component.scales[r];if(i&&!i.merged){const s=i.get("type"),a=i.get("range");if(Er(s)&&Af(a)){const o=i.get("name"),l=N2(this,r),u=R5(l);if(u){const c=ze({aggregate:"distinct",field:u},{expr:"datum"});return{signal:QU(o,i,c)}}else return Te(D$(r)),null}}}return{signal:this.signalNameMap.get(this.getName(t))}}lookupDataSource(t){const n=this.component.data.outputNodes[t];return n?n.getSource():t}getSignalName(t){return this.signalNameMap.get(t)}renameSignal(t,n){this.signalNameMap.rename(t,n)}renameScale(t,n){this.scaleNameMap.rename(t,n)}renameProjection(t,n){this.projectionNameMap.rename(t,n)}scaleName(t,n){if(n)return this.getName(t);if(mz(t)&&So(t)&&this.component.scales[t]||this.scaleNameMap.has(this.getName(t)))return this.scaleNameMap.get(this.getName(t))}projectionName(t){if(t)return this.getName("projection");if(this.component.projection&&!this.component.projection.merged||this.projectionNameMap.has(this.getName("projection")))return this.projectionNameMap.get(this.getName("projection"))}getScaleComponent(t){if(!this.component.scales)throw new Error("getScaleComponent cannot be called before parseScale(). Make sure you have called parseScale or use parseUnitModelWithScale().");const n=this.component.scales[t];return n&&!n.merged?n:this.parent?this.parent.getScaleComponent(t):void 0}getScaleType(t){const n=this.getScaleComponent(t);return n?n.get("type"):void 0}getSelectionComponent(t,n){let r=this.component.selection[t];if(!r&&this.parent&&(r=this.parent.getSelectionComponent(t,n)),!r)throw new Error(bme(n));return r}hasAxisOrientSignalRef(){var t,n;return((t=this.component.axes.x)==null?void 0:t.some(r=>r.hasOrientSignalRef()))||((n=this.component.axes.y)==null?void 0:n.some(r=>r.hasOrientSignalRef()))}}class Sq extends O5{vgField(t,n={}){const r=this.fieldDef(t);if(r)return ze(r,n)}reduceFieldDef(t,n){return Kve(this.getMapping(),(r,i,s)=>{const a=va(i);return a?t(r,a,s):r},n)}forEachFieldDef(t,n){i5(this.getMapping(),(r,i)=>{const s=va(r);s&&t(s,i)},n)}}class O2 extends cn{clone(){return new O2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??"value",r[1]??"density"];const i=this.transform.resolve??"shared";this.transform.resolve=i}dependentFields(){return new Set([this.transform.density,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`DensityTransform ${Gt(this.transform)}`}assemble(){const{density:t,...n}=this.transform,r={type:"kde",field:t,...n};return r.resolve=this.transform.resolve,r}}class L2 extends cn{clone(){return new L2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n)}dependentFields(){return new Set([this.transform.extent])}producedFields(){return new Set([])}hash(){return`ExtentTransform ${Gt(this.transform)}`}assemble(){const{extent:t,param:n}=this.transform;return{type:"extent",field:t,signal:n}}}class I2 extends cn{clone(){return new I2(this.parent,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n);const{flatten:r,as:i=[]}=this.transform;this.transform.as=r.map((s,a)=>i[a]??s)}dependentFields(){return new Set(this.transform.flatten)}producedFields(){return new Set(this.transform.as)}hash(){return`FlattenTransform ${Gt(this.transform)}`}assemble(){const{flatten:t,as:n}=this.transform;return{type:"flatten",fields:t,as:n}}}class P2 extends cn{clone(){return new P2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??"key",r[1]??"value"]}dependentFields(){return new Set(this.transform.fold)}producedFields(){return new Set(this.transform.as)}hash(){return`FoldTransform ${Gt(this.transform)}`}assemble(){const{fold:t,as:n}=this.transform;return{type:"fold",fields:t,as:n}}}class pd extends cn{clone(){return new pd(null,Ct(this.fields),this.geojson,this.signal)}static parseAll(t,n){if(n.component.projection&&!n.component.projection.isFit)return t;let r=0;for(const i of[[ka,Aa],[Bs,Sa]]){const s=i.map(a=>{const o=ir(n.encoding[a]);return Oe(o)?o.field:Co(o)?{expr:`${o.datum}`}:ma(o)?{expr:`${o.value}`}:void 0});(s[0]||s[1])&&(t=new pd(t,s,null,n.getName(`geojson_${r++}`)))}if(n.channelHasField(Ui)){const i=n.typedFieldDef(Ui);i.type===Ih&&(t=new pd(t,null,i.field,n.getName(`geojson_${r++}`)))}return t}constructor(t,n,r,i){super(t),this.fields=n,this.geojson=r,this.signal=i}dependentFields(){const t=(this.fields??[]).filter(We);return new Set([...this.geojson?[this.geojson]:[],...t])}producedFields(){return new Set}hash(){return`GeoJSON ${this.geojson} ${this.signal} ${Gt(this.fields)}`}assemble(){return[...this.geojson?[{type:"filter",expr:`isValid(datum["${this.geojson}"])`}]:[],{type:"geojson",...this.fields?{fields:this.fields}:{},...this.geojson?{geojson:this.geojson}:{},signal:this.signal}]}}class Gg extends cn{clone(){return new Gg(null,this.projection,Ct(this.fields),Ct(this.as))}constructor(t,n,r,i){super(t),this.projection=n,this.fields=r,this.as=i}static parseAll(t,n){if(!n.projectionName())return t;for(const r of[[ka,Aa],[Bs,Sa]]){const i=r.map(a=>{const o=ir(n.encoding[a]);return Oe(o)?o.field:Co(o)?{expr:`${o.datum}`}:ma(o)?{expr:`${o.value}`}:void 0}),s=r[0]===Bs?"2":"";(i[0]||i[1])&&(t=new Gg(t,n.projectionName(),i,[n.getName(`x${s}`),n.getName(`y${s}`)]))}return t}dependentFields(){return new Set(this.fields.filter(We))}producedFields(){return new Set(this.as)}hash(){return`Geopoint ${this.projection} ${Gt(this.fields)} ${Gt(this.as)}`}assemble(){return{type:"geopoint",projection:this.projection,fields:this.fields,as:this.as}}}class Dc extends cn{clone(){return new Dc(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n}dependentFields(){return new Set([this.transform.impute,this.transform.key,...this.transform.groupby??[]])}producedFields(){return new Set([this.transform.impute])}processSequence(t){const{start:n=0,stop:r,step:i}=t;return{signal:`sequence(${[n,r,...i?[i]:[]].join(",")})`}}static makeFromTransform(t,n){return new Dc(t,n)}static makeFromEncoding(t,n){const r=n.encoding,i=r.x,s=r.y;if(Oe(i)&&Oe(s)){const a=i.impute?i:s.impute?s:void 0;if(a===void 0)return;const o=i.impute?s:s.impute?i:void 0,{method:l,value:u,frame:c,keyvals:f}=a.impute,d=Rj(n.mark,r);return new Dc(t,{impute:a.field,key:o.field,...l?{method:l}:{},...u!==void 0?{value:u}:{},...c?{frame:c}:{},...f!==void 0?{keyvals:f}:{},...d.length?{groupby:d}:{}})}return null}hash(){return`Impute ${Gt(this.transform)}`}assemble(){const{impute:t,key:n,keyvals:r,method:i,groupby:s,value:a,frame:o=[null,null]}=this.transform,l={type:"impute",field:t,key:n,...r?{keyvals:Jye(r)?this.processSequence(r):r}:{},method:"value",...s?{groupby:s}:{},value:!i||i==="value"?a:null};if(i&&i!=="value"){const u={type:"window",as:[`imputed_${t}_value`],ops:[i],fields:[t],frame:o,ignorePeers:!1,...s?{groupby:s}:{}},c={type:"formula",expr:`datum.${t} === null ? datum.imputed_${t}_value : datum.${t}`,as:t};return[l,u,c]}else return[l]}}class B2 extends cn{clone(){return new B2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??n.on,r[1]??n.loess]}dependentFields(){return new Set([this.transform.loess,this.transform.on,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`LoessTransform ${Gt(this.transform)}`}assemble(){const{loess:t,on:n,...r}=this.transform;return{type:"loess",x:n,y:t,...r}}}class Yg extends cn{clone(){return new Yg(null,Ct(this.transform),this.secondary)}constructor(t,n,r){super(t),this.transform=n,this.secondary=r}static make(t,n,r,i){const s=n.component.data.sources,{from:a}=r;let o=null;if(Qye(a)){let l=Fq(a.data,s);l||(l=new cf(a.data),s.push(l));const u=n.getName(`lookup_${i}`);o=new Ii(l,u,Tn.Lookup,n.component.data.outputNodeRefCounts),n.component.data.outputNodes[u]=o}else if(ebe(a)){const l=a.param;r={as:l,...r};let u;try{u=n.getSelectionComponent(Cn(l),l)}catch{throw new Error(Eme(l))}if(o=u.materialized,!o)throw new Error(Ame(l))}return new Yg(t,r,o.getSource())}dependentFields(){return new Set([this.transform.lookup])}producedFields(){return new Set(this.transform.as?He(this.transform.as):this.transform.from.fields)}hash(){return`Lookup ${Gt({transform:this.transform,secondary:this.secondary})}`}assemble(){let t;if(this.transform.from.fields)t={values:this.transform.from.fields,...this.transform.as?{as:He(this.transform.as)}:{}};else{let n=this.transform.as;We(n)||(Te(Ome),n="_lookup"),t={as:[n]}}return{type:"lookup",from:this.secondary,key:this.transform.from.key,fields:[this.transform.lookup],...t,...this.transform.default?{default:this.transform.default}:{}}}}class z2 extends cn{clone(){return new z2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??"prob",r[1]??"value"]}dependentFields(){return new Set([this.transform.quantile,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`QuantileTransform ${Gt(this.transform)}`}assemble(){const{quantile:t,...n}=this.transform;return{type:"quantile",field:t,...n}}}class j2 extends cn{clone(){return new j2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Ct(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??n.on,r[1]??n.regression]}dependentFields(){return new Set([this.transform.regression,this.transform.on,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`RegressionTransform ${Gt(this.transform)}`}assemble(){const{regression:t,on:n,...r}=this.transform;return{type:"regression",x:n,y:t,...r}}}class U2 extends cn{clone(){return new U2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n}addDimensions(t){this.transform.groupby=Xa((this.transform.groupby??[]).concat(t),n=>n)}producedFields(){}dependentFields(){return new Set([this.transform.pivot,this.transform.value,...this.transform.groupby??[]])}hash(){return`PivotTransform ${Gt(this.transform)}`}assemble(){const{pivot:t,value:n,groupby:r,limit:i,op:s}=this.transform;return{type:"pivot",field:t,value:n,...i!==void 0?{limit:i}:{},...s!==void 0?{op:s}:{},...r!==void 0?{groupby:r}:{}}}}class q2 extends cn{clone(){return new q2(null,Ct(this.transform))}constructor(t,n){super(t),this.transform=n}dependentFields(){return new Set}producedFields(){return new Set}hash(){return`SampleTransform ${Gt(this.transform)}`}assemble(){return{type:"sample",size:this.transform.sample}}}function Cq(e){let t=0;function n(r,i){if(r instanceof cf&&!r.isGenerator&&!oh(r.data)&&(e.push(i),i={name:null,source:i.name,transform:[]}),r instanceof Yr&&(r.parent instanceof cf&&!i.source?(i.format={...i.format,parse:r.assembleFormatParse()},i.transform.push(...r.assembleTransforms(!0))):i.transform.push(...r.assembleTransforms())),r instanceof zh){i.name||(i.name=`data_${t++}`),!i.source||i.transform.length>0?(e.push(i),r.data=i.name):r.data=i.source,e.push(...r.assemble());return}switch((r instanceof tm||r instanceof nm||r instanceof dh||r instanceof Bh||r instanceof uh||r instanceof Gg||r instanceof ua||r instanceof Yg||r instanceof jh||r instanceof Df||r instanceof P2||r instanceof I2||r instanceof O2||r instanceof B2||r instanceof z2||r instanceof j2||r instanceof vu||r instanceof q2||r instanceof U2||r instanceof L2)&&i.transform.push(r.assemble()),(r instanceof no||r instanceof eo||r instanceof Dc||r instanceof il||r instanceof pd)&&i.transform.push(...r.assemble()),r instanceof Ii&&(i.source&&i.transform.length===0?r.setSource(i.source):r.parent instanceof Ii?r.setSource(i.name):(i.name||(i.name=`data_${t++}`),r.setSource(i.name),r.numChildren()===1&&(e.push(i),i={name:null,source:i.name,transform:[]}))),r.numChildren()){case 0:r instanceof Ii&&(!i.source||i.transform.length>0)&&e.push(i);break;case 1:n(r.children[0],i);break;default:{i.name||(i.name=`data_${t++}`);let s=i.name;!i.source||i.transform.length>0?e.push(i):s=i.source;for(const a of r.children)n(a,{name:null,source:s,transform:[]});break}}}return n}function wwe(e){const t=[],n=Cq(t);for(const r of e.children)n(r,{source:e.name,name:null,transform:[]});return t}function Ewe(e,t){const n=[],r=Cq(n);let i=0;for(const a of e.sources){a.hasName()||(a.dataName=`source_${i++}`);const o=a.assemble();r(a,o)}for(const a of n)a.transform.length===0&&delete a.transform;let s=0;for(const[a,o]of n.entries())(o.transform??[]).length===0&&!o.source&&n.splice(s++,0,n.splice(a,1)[0]);for(const a of n)for(const o of a.transform??[])o.type==="lookup"&&(o.from=e.outputNodes[o.from].getSource());for(const a of n)a.name in t&&(a.values=t[a.name]);return n}function Awe(e){return e==="top"||e==="left"||ot(e)?"header":"footer"}function kwe(e){for(const t of Ss)Swe(e,t);$8(e,"x"),$8(e,"y")}function Swe(e,t){var a;const{facet:n,config:r,child:i,component:s}=e;if(e.channelHasField(t)){const o=n[t],l=fh("title",null,r,t);let u=dd(o,r,{allowDisabling:!0,includeDefault:l===void 0||!!l});i.component.layoutHeaders[t].title&&(u=Se(u)?u.join(", "):u,u+=` / ${i.component.layoutHeaders[t].title}`,i.component.layoutHeaders[t].title=null);const c=fh("labelOrient",o.header,r,t),f=o.header!==null?Vn((a=o.header)==null?void 0:a.labels,r.header.labels,!0):!1,d=Ut(["bottom","right"],c)?"footer":"header";s.layoutHeaders[t]={title:o.header!==null?u:null,facetFieldDef:o,[d]:t==="facet"?[]:[$q(e,t,f)]}}}function $q(e,t,n){const r=t==="row"?"height":"width";return{labels:n,sizeSignal:e.child.component.layoutSize.get(r)?e.child.getSizeSignalRef(r):void 0,axes:[]}}function $8(e,t){const{child:n}=e;if(n.component.axes[t]){const{layoutHeaders:r,resolve:i}=e.component;if(i.axis[t]=$5(i,t),i.axis[t]==="shared"){const s=t==="x"?"column":"row",a=r[s];for(const o of n.component.axes[t]){const l=Awe(o.get("orient"));a[l]??(a[l]=[$q(e,s,!1)]);const u=Wp(o,"main",e.config,{header:!0});u&&a[l][0].axes.push(u),o.mainExtracted=!0}}}}function Cwe(e){L5(e),Ey(e,"width"),Ey(e,"height")}function $we(e){L5(e);const t=e.layout.columns===1?"width":"childWidth",n=e.layout.columns===void 0?"height":"childHeight";Ey(e,t),Ey(e,n)}function L5(e){for(const t of e.children)t.parseLayoutSize()}function Ey(e,t){const n=eq(t),r=i2(n),i=e.component.resolve,s=e.component.layoutSize;let a;for(const o of e.children){const l=o.component.layoutSize.getWithExplicit(n),u=i.scale[r]??nq(r,e);if(u==="independent"&&l.value==="step"){a=void 0;break}if(a){if(u==="independent"&&a.value!==l.value){a=void 0;break}a=mu(a,l,n,"")}else a=l}if(a){for(const o of e.children)e.renameSignal(o.getName(n),e.getName(t)),o.component.layoutSize.set(n,"merged",!1);s.setWithExplicit(t,a)}else s.setWithExplicit(t,{explicit:!1,value:void 0})}function Fwe(e){const{size:t,component:n}=e;for(const r of bl){const i=qi(r);if(t[i]){const s=t[i];n.layoutSize.set(i,ho(s)?"step":s,!0)}else{const s=Dwe(e,i);n.layoutSize.set(i,s,!1)}}}function Dwe(e,t){const n=t==="width"?"x":"y",r=e.config,i=e.getScaleComponent(n);if(i){const s=i.get("type"),a=i.get("range");if(Er(s)){const o=yy(r.view,t);return Af(a)||ho(o)?"step":o}else return kA(r.view,t)}else{if(e.hasProjection||e.mark==="arc")return kA(r.view,t);{const s=yy(r.view,t);return ho(s)?s.step:s}}}function HA(e,t,n){return ze(t,{suffix:`by_${ze(e)}`,...n})}class dg extends Sq{constructor(t,n,r,i){super(t,"facet",n,r,i,t.resolve),this.child=j5(t.spec,this,this.getName("child"),void 0,i),this.children=[this.child],this.facet=this.initFacet(t.facet)}initFacet(t){if(!G0(t))return{facet:this.initFacetFieldDef(t,"facet")};const n=Fe(t),r={};for(const i of n){if(![el,tl].includes(i)){Te(o2(i,"facet"));break}const s=t[i];if(s.field===void 0){Te(_A(s,i));break}r[i]=this.initFacetFieldDef(s,i)}return r}initFacetFieldDef(t,n){const r=r5(t,n);return r.header?r.header=Fr(r.header):r.header===null&&(r.header=null),r}channelHasField(t){return De(this.facet,t)}fieldDef(t){return this.facet[t]}parseData(){this.component.data=W2(this),this.child.parseData()}parseLayoutSize(){L5(this)}parseSelections(){this.child.parseSelections(),this.component.selection=this.child.component.selection,Object.values(this.component.selection).some(t=>to(t))&&T$(M$)}parseMarkGroup(){this.child.parseMarkGroup()}parseAxesAndHeaders(){this.child.parseAxesAndHeaders(),kwe(this)}assembleSelectionTopLevelSignals(t){return this.child.assembleSelectionTopLevelSignals(t)}assembleSignals(){return this.child.assembleSignals(),[]}assembleSelectionData(t){return this.child.assembleSelectionData(t)}getHeaderLayoutMixins(){const t={};for(const n of Ss)for(const r of S5){const i=this.component.layoutHeaders[n],s=i[r],{facetFieldDef:a}=i;if(a){const o=fh("titleOrient",a.header,this.config,n);if(["right","bottom"].includes(o)){const l=T2(n,o);t.titleAnchor??(t.titleAnchor={}),t.titleAnchor[l]="end"}}if(s!=null&&s[0]){const o=n==="row"?"height":"width",l=r==="header"?"headerBand":"footerBand";n!=="facet"&&!this.child.component.layoutSize.get(o)&&(t[l]??(t[l]={}),t[l][n]=.5),i.title&&(t.offset??(t.offset={}),t.offset[n==="row"?"rowTitle":"columnTitle"]=10)}}return t}assembleDefaultLayout(){const{column:t,row:n}=this.facet,r=t?this.columnDistinctSignal():n?1:void 0;let i="all";return(!n&&this.component.resolve.scale.x==="independent"||!t&&this.component.resolve.scale.y==="independent")&&(i="none"),{...this.getHeaderLayoutMixins(),...r?{columns:r}:{},bounds:"full",align:i}}assembleLayoutSignals(){return this.child.assembleLayoutSignals()}columnDistinctSignal(){if(!(this.parent&&this.parent instanceof dg))return{signal:`length(data('${this.getName("column_domain")}'))`}}assembleGroupStyle(){}assembleGroup(t){return this.parent&&this.parent instanceof dg?{...this.channelHasField("column")?{encode:{update:{columns:{field:ze(this.facet.column,{prefix:"distinct"})}}}}:{},...super.assembleGroup(t)}:super.assembleGroup(t)}getCardinalityAggregateForChild(){const t=[],n=[],r=[];if(this.child instanceof dg){if(this.child.channelHasField("column")){const i=ze(this.child.facet.column);t.push(i),n.push("distinct"),r.push(`distinct_${i}`)}}else for(const i of bl){const s=this.child.component.scales[i];if(s&&!s.merged){const a=s.get("type"),o=s.get("range");if(Er(a)&&Af(o)){const l=N2(this.child,i),u=R5(l);u?(t.push(u),n.push("distinct"),r.push(`distinct_${u}`)):Te(D$(i))}}}return{fields:t,ops:n,as:r}}assembleFacet(){const{name:t,data:n}=this.component.data.facetRoot,{row:r,column:i}=this.facet,{fields:s,ops:a,as:o}=this.getCardinalityAggregateForChild(),l=[];for(const c of Ss){const f=this.facet[c];if(f){l.push(ze(f));const{bin:d,sort:h}=f;if(xn(d)&&l.push(ze(f,{binSuffix:"end"})),nl(h)){const{field:p,op:g=p2}=h,v=HA(f,h);r&&i?(s.push(v),a.push("max"),o.push(v)):(s.push(p),a.push(g),o.push(v))}else if(Se(h)){const p=ch(f,c);s.push(p),a.push("max"),o.push(p)}}}const u=!!r&&!!i;return{name:t,data:n,groupby:l,...u||s.length>0?{aggregate:{...u?{cross:u}:{},...s.length?{fields:s,ops:a,as:o}:{}}}:{}}}facetSortFields(t){const{facet:n}=this,r=n[t];return r?nl(r.sort)?[HA(r,r.sort,{expr:"datum"})]:Se(r.sort)?[ch(r,t,{expr:"datum"})]:[ze(r,{expr:"datum"})]:[]}facetSortOrder(t){const{facet:n}=this,r=n[t];if(r){const{sort:i}=r;return[(nl(i)?i.order:!Se(i)&&i)||"ascending"]}return[]}assembleLabelTitle(){var i;const{facet:t,config:n}=this;if(t.facet)return PA(t.facet,"facet",n);const r={row:["top","bottom"],column:["left","right"]};for(const s of k5)if(t[s]){const a=fh("labelOrient",(i=t[s])==null?void 0:i.header,n,s);if(r[s].includes(a))return PA(t[s],s,n)}}assembleMarks(){const{child:t}=this,n=this.component.data.facetRoot,r=wwe(n),i=t.assembleGroupEncodeEntry(!1),s=this.assembleLabelTitle()||t.assembleTitle(),a=t.assembleGroupStyle();return[{name:this.getName("cell"),type:"group",...s?{title:s}:{},...a?{style:a}:{},from:{facet:this.assembleFacet()},sort:{field:Ss.map(l=>this.facetSortFields(l)).flat(),order:Ss.map(l=>this.facetSortOrder(l)).flat()},...r.length>0?{data:r}:{},...i?{encode:{update:i}}:{},...t.assembleGroup(Lbe(this,[]))}]}getMapping(){return this.facet}}function Mwe(e,t){const{row:n,column:r}=t;if(n&&r){let i=null;for(const s of[n,r])if(nl(s.sort)){const{field:a,op:o=p2}=s.sort;e=i=new Df(e,{joinaggregate:[{op:o,field:a,as:HA(s,s.sort,{forAs:!0})}],groupby:[ze(s)]})}return i}return null}function Fq(e,t){var n,r,i,s;for(const a of t){const o=a.data;if(e.name&&a.hasName()&&e.name!==a.dataName)continue;const l=(n=e.format)==null?void 0:n.mesh,u=(r=o.format)==null?void 0:r.feature;if(l&&u)continue;const c=(i=e.format)==null?void 0:i.feature;if((c||u)&&c!==u)continue;const f=(s=o.format)==null?void 0:s.mesh;if(!((l||f)&&l!==f)){if(qg(e)&&qg(o)){if(ns(e.values,o.values))return a}else if(oh(e)&&oh(o)){if(e.url===o.url)return a}else if(uU(e)&&e.name===a.dataName)return a}}return null}function Twe(e,t){if(e.data||!e.parent){if(e.data===null){const r=new cf({values:[]});return t.push(r),r}const n=Fq(e.data,t);if(n)return eu(e.data)||(n.data.format=iz({},e.data.format,n.data.format)),!n.hasName()&&e.data.name&&(n.dataName=e.data.name),n;{const r=new cf(e.data);return t.push(r),r}}else return e.parent.component.data.facetRoot?e.parent.component.data.facetRoot:e.parent.component.data.main}function Rwe(e,t,n){let r=0;for(const i of t.transforms){let s,a;if(cbe(i))a=e=new uh(e,i),s="derived";else if(g5(i)){const o=Exe(i);a=e=Yr.makeWithAncestors(e,{},o,n)??e,e=new Bh(e,t,i.filter)}else if(iU(i))a=e=no.makeFromTransform(e,i,t),s="number";else if(dbe(i))s="date",n.getWithExplicit(i.field).value===void 0&&(e=new Yr(e,{[i.field]:s}),n.set(i.field,s,!1)),a=e=eo.makeFromTransform(e,i);else if(hbe(i))a=e=ua.makeFromTransform(e,i),s="number",x5(t)&&(e=new vu(e));else if(rU(i))a=e=Yg.make(e,t,i,r++),s="derived";else if(obe(i))a=e=new jh(e,i),s="number";else if(lbe(i))a=e=new Df(e,i),s="number";else if(pbe(i))a=e=il.makeFromTransform(e,i),s="derived";else if(gbe(i))a=e=new P2(e,i),s="derived";else if(mbe(i))a=e=new L2(e,i),s="derived";else if(ube(i))a=e=new I2(e,i),s="derived";else if(tbe(i))a=e=new U2(e,i),s="derived";else if(abe(i))e=new q2(e,i);else if(fbe(i))a=e=Dc.makeFromTransform(e,i),s="derived";else if(nbe(i))a=e=new O2(e,i),s="derived";else if(rbe(i))a=e=new z2(e,i),s="derived";else if(ibe(i))a=e=new j2(e,i),s="derived";else if(sbe(i))a=e=new B2(e,i),s="derived";else{Te(Nme(i));continue}if(a&&s!==void 0)for(const o of a.producedFields()??[])n.set(o,s,!1)}return e}function W2(e){var v;let t=Twe(e,e.component.data.sources);const{outputNodes:n,outputNodeRefCounts:r}=e.component.data,i=e.data,a=!(i&&(eu(i)||oh(i)||qg(i)))&&e.parent?e.parent.component.data.ancestorParse.clone():new $be;eu(i)?(cU(i)?t=new nm(t,i.sequence):m5(i)&&(t=new tm(t,i.graticule)),a.parseNothing=!0):((v=i==null?void 0:i.format)==null?void 0:v.parse)===null&&(a.parseNothing=!0),t=Yr.makeExplicit(t,e,a)??t,t=new vu(t);const o=e.parent&&Uh(e.parent);(Dn(e)||os(e))&&o&&(t=no.makeFromEncoding(t,e)??t),e.transforms.length>0&&(t=Rwe(t,e,a));const l=kxe(e),u=Axe(e);t=Yr.makeWithAncestors(t,{},{...l,...u},a)??t,Dn(e)&&(t=pd.parseAll(t,e),t=Gg.parseAll(t,e)),(Dn(e)||os(e))&&(o||(t=no.makeFromEncoding(t,e)??t),t=eo.makeFromEncoding(t,e)??t,t=uh.parseAllForSortIndex(t,e));const c=t=qm(Tn.Raw,e,t);if(Dn(e)){const y=ua.makeFromEncoding(t,e);y&&(t=y,x5(e)&&(t=new vu(t))),t=Dc.makeFromEncoding(t,e)??t,t=il.makeFromEncoding(t,e)??t}let f,d;if(Dn(e)){const{markDef:y,mark:b,config:_}=e,x=fn("invalid",y,_),{marks:w,scales:A}=d=dU({invalid:x,isPath:Lu(b)});w!==A&&A==="include-invalid-values"&&(f=t=qm(Tn.PreFilterInvalid,e,t)),w==="exclude-invalid-values"&&(t=dh.make(t,e,d)??t)}const h=t=qm(Tn.Main,e,t);let p;if(Dn(e)&&d){const{marks:y,scales:b}=d;y==="include-invalid-values"&&b==="exclude-invalid-values"&&(t=dh.make(t,e,d)??t,p=t=qm(Tn.PostFilterInvalid,e,t))}Dn(e)&&__e(e,h);let g=null;if(os(e)){const y=e.getName("facet");t=Mwe(t,e.facet)??t,g=new zh(t,e,y,h.getSource()),n[y]=g}return{...e.component.data,outputNodes:n,outputNodeRefCounts:r,raw:c,main:h,facetRoot:g,ancestorParse:a,preFilterInvalid:f,postFilterInvalid:p}}function qm(e,t,n){const{outputNodes:r,outputNodeRefCounts:i}=t.component.data,s=t.getDataName(e),a=new Ii(n,s,e,i);return r[s]=a,a}class Nwe extends O5{constructor(t,n,r,i){var s,a,o,l;super(t,"concat",n,r,i,t.resolve),(((a=(s=t.resolve)==null?void 0:s.axis)==null?void 0:a.x)==="shared"||((l=(o=t.resolve)==null?void 0:o.axis)==null?void 0:l.y)==="shared")&&Te(Mme),this.children=this.getChildren(t).map((u,c)=>j5(u,this,this.getName(`concat_${c}`),void 0,i))}parseData(){this.component.data=W2(this);for(const t of this.children)t.parseData()}parseSelections(){this.component.selection={};for(const t of this.children){t.parseSelections();for(const n of Fe(t.component.selection))this.component.selection[n]=t.component.selection[n]}Object.values(this.component.selection).some(t=>to(t))&&T$(M$)}parseMarkGroup(){for(const t of this.children)t.parseMarkGroup()}parseAxesAndHeaders(){for(const t of this.children)t.parseAxesAndHeaders()}getChildren(t){return x2(t)?t.vconcat:h5(t)?t.hconcat:t.concat}parseLayoutSize(){$we(this)}parseAxisGroup(){return null}assembleSelectionTopLevelSignals(t){return this.children.reduce((n,r)=>r.assembleSelectionTopLevelSignals(n),t)}assembleSignals(){return this.children.forEach(t=>t.assembleSignals()),[]}assembleLayoutSignals(){const t=C5(this);for(const n of this.children)t.push(...n.assembleLayoutSignals());return t}assembleSelectionData(t){return this.children.reduce((n,r)=>r.assembleSelectionData(n),t)}assembleMarks(){return this.children.map(t=>{const n=t.assembleTitle(),r=t.assembleGroupStyle(),i=t.assembleGroupEncodeEntry(!1);return{type:"group",name:t.getName("group"),...n?{title:n}:{},...r?{style:r}:{},...i?{encode:{update:i}}:{},...t.assembleGroup()}})}assembleGroupStyle(){}assembleDefaultLayout(){const t=this.layout.columns;return{...t!=null?{columns:t}:{},bounds:"full",align:"each"}}}function Owe(e){return e===!1||e===null}const Lwe={disable:1,gridScale:1,scale:1,...Cj,labelExpr:1,encode:1},Dq=Fe(Lwe);class I5 extends xl{constructor(t={},n={},r=!1){super(),this.explicit=t,this.implicit=n,this.mainExtracted=r}clone(){return new I5(Ct(this.explicit),Ct(this.implicit),this.mainExtracted)}hasAxisPart(t){return t==="axis"?!0:t==="grid"||t==="title"?!!this.get(t):!Owe(this.get(t))}hasOrientSignalRef(){return ot(this.explicit.orient)}}function Iwe(e,t,n){const{encoding:r,config:i}=e,s=ir(r[t])??ir(r[ko(t)]),a=e.axis(t)||{},{format:o,formatType:l}=a;if(sf(l))return{text:oa({fieldOrDatumDef:s,field:"datum.value",format:o,formatType:l,config:i}),...n};if(o===void 0&&l===void 0&&i.customFormatTypes){if(ih(s)==="quantitative"){if(sh(s)&&s.stack==="normalize"&&i.normalizedNumberFormatType)return{text:oa({fieldOrDatumDef:s,field:"datum.value",format:i.normalizedNumberFormat,formatType:i.normalizedNumberFormatType,config:i}),...n};if(i.numberFormatType)return{text:oa({fieldOrDatumDef:s,field:"datum.value",format:i.numberFormat,formatType:i.numberFormatType,config:i}),...n}}if(ih(s)==="temporal"&&i.timeFormatType&&Oe(s)&&!s.timeUnit)return{text:oa({fieldOrDatumDef:s,field:"datum.value",format:i.timeFormat,formatType:i.timeFormatType,config:i}),...n}}return n}function Pwe(e){return bl.reduce((t,n)=>(e.component.scales[n]&&(t[n]=[Hwe(n,e)]),t),{})}const Bwe={bottom:"top",top:"bottom",left:"right",right:"left"};function zwe(e){const{axes:t,resolve:n}=e.component,r={top:0,bottom:0,right:0,left:0};for(const i of e.children){i.parseAxesAndHeaders();for(const s of Fe(i.component.axes))n.axis[s]=$5(e.component.resolve,s),n.axis[s]==="shared"&&(t[s]=jwe(t[s],i.component.axes[s]),t[s]||(n.axis[s]="independent",delete t[s]))}for(const i of bl){for(const s of e.children)if(s.component.axes[i]){if(n.axis[i]==="independent"){t[i]=(t[i]??[]).concat(s.component.axes[i]);for(const a of s.component.axes[i]){const{value:o,explicit:l}=a.getWithExplicit("orient");if(!ot(o)){if(r[o]>0&&!l){const u=Bwe[o];r[o]>r[u]&&a.set("orient",u,!1)}r[o]++}}}delete s.component.axes[i]}if(n.axis[i]==="independent"&&t[i]&&t[i].length>1)for(const[s,a]of(t[i]||[]).entries())s>0&&a.get("grid")&&!a.explicit.grid&&(a.implicit.grid=!1)}}function jwe(e,t){if(e){if(e.length!==t.length)return;const n=e.length;for(let r=0;rn.clone());return e}function Uwe(e,t){for(const n of Dq){const r=mu(e.getWithExplicit(n),t.getWithExplicit(n),n,"axis",(i,s)=>{switch(n){case"title":return Mz(i,s);case"gridScale":return{explicit:i.explicit,value:Vn(i.value,s.value)}}return E2(i,s,n,"axis")});e.setWithExplicit(n,r)}return e}function qwe(e,t,n,r,i){if(t==="disable")return n!==void 0;switch(n=n||{},t){case"titleAngle":case"labelAngle":return e===(ot(n.labelAngle)?n.labelAngle:jg(n.labelAngle));case"values":return!!n.values;case"encode":return!!n.encoding||!!n.labelAngle;case"title":if(e===XU(r,i))return!0}return e===n[t]}const Wwe=new Set(["grid","translate","format","formatType","orient","labelExpr","tickCount","position","tickMinStep"]);function Hwe(e,t){var y,b;let n=t.axis(e);const r=new I5,i=ir(t.encoding[e]),{mark:s,config:a}=t,o=(n==null?void 0:n.orient)||((y=a[e==="x"?"axisX":"axisY"])==null?void 0:y.orient)||((b=a.axis)==null?void 0:b.orient)||D_e(e),l=t.getScaleComponent(e).get("type"),u=E_e(e,l,o,t.config),c=n!==void 0?!n:LA("disable",a.style,n==null?void 0:n.style,u).configValue;if(r.set("disable",c,n!==void 0),c)return r;n=n||{};const f=C_e(i,n,e,a.style,u),d=hj(n.formatType,i,l),h=dj(i,i.type,n.format,n.formatType,a,!0),p={fieldOrDatumDef:i,axis:n,channel:e,model:t,scaleType:l,orient:o,labelAngle:f,format:h,formatType:d,mark:s,config:a};for(const _ of Dq){const x=_ in h8?h8[_](p):R6(_)?n[_]:void 0,w=x!==void 0,A=qwe(x,_,n,t,e);if(w&&A)r.set(_,x,A);else{const{configValue:E=void 0,configFrom:k=void 0}=R6(_)&&_!=="values"?LA(_,a.style,n.style,u):{},C=E!==void 0;w&&!C?r.set(_,x,A):(k!=="vgAxisConfig"||Wwe.has(_)&&C||K0(E)||ot(E))&&r.set(_,E,!1)}}const g=n.encoding??{},v=Sj.reduce((_,x)=>{if(!r.hasAxisPart(x))return _;const w=tq(g[x]??{},t),A=x==="labels"?Iwe(t,e,w):w;return A!==void 0&&!dn(A)&&(_[x]={update:A}),_},{});return dn(v)||r.set("encode",v,!!n.encoding||n.labelAngle!==void 0),r}function Gwe({encoding:e,size:t}){for(const n of bl){const r=qi(n);ho(t[r])&&Hl(e[n])&&(delete t[r],Te(Lz(r)))}return t}const Ywe={vgMark:"arc",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"}),...pi("x",e,{defaultPos:"mid"}),...pi("y",e,{defaultPos:"mid"}),...fl(e,"radius"),...fl(e,"theta")})},Vwe={vgMark:"area",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",orient:"include",size:"ignore",theta:"ignore"}),...by("x",e,{defaultPos:"zeroOrMin",defaultPos2:"zeroOrMin",range:e.markDef.orient==="horizontal"}),...by("y",e,{defaultPos:"zeroOrMin",defaultPos2:"zeroOrMin",range:e.markDef.orient==="vertical"}),..._5(e)})},Xwe={vgMark:"rect",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...fl(e,"x"),...fl(e,"y")})},Kwe={vgMark:"shape",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"})}),postEncodingTransform:e=>{const{encoding:t}=e,n=t.shape;return[{type:"geoshape",projection:e.projectionName(),...n&&Oe(n)&&n.type===Ih?{field:ze(n,{expr:"datum"})}:{}}]}},Zwe={vgMark:"image",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"ignore",orient:"ignore",size:"ignore",theta:"ignore"}),...fl(e,"x"),...fl(e,"y"),...y5(e,"url")})},Jwe={vgMark:"line",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"}),...pi("x",e,{defaultPos:"mid"}),...pi("y",e,{defaultPos:"mid"}),...Mr("size",e,{vgChannel:"strokeWidth"}),..._5(e)})},Qwe={vgMark:"trail",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",size:"include",orient:"ignore",theta:"ignore"}),...pi("x",e,{defaultPos:"mid"}),...pi("y",e,{defaultPos:"mid"}),...Mr("size",e),..._5(e)})};function P5(e,t){const{config:n}=e;return{...Us(e,{align:"ignore",baseline:"ignore",color:"include",size:"include",orient:"ignore",theta:"ignore"}),...pi("x",e,{defaultPos:"mid"}),...pi("y",e,{defaultPos:"mid"}),...Mr("size",e),...Mr("angle",e),...eEe(e,n,t)}}function eEe(e,t,n){return n?{shape:{value:n}}:Mr("shape",e)}const tEe={vgMark:"symbol",encodeEntry:e=>P5(e)},nEe={vgMark:"symbol",encodeEntry:e=>P5(e,"circle")},rEe={vgMark:"symbol",encodeEntry:e=>P5(e,"square")},iEe={vgMark:"rect",encodeEntry:e=>({...Us(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...fl(e,"x"),...fl(e,"y")})},sEe={vgMark:"rule",encodeEntry:e=>{const{markDef:t}=e,n=t.orient;return!e.encoding.x&&!e.encoding.y&&!e.encoding.latitude&&!e.encoding.longitude?{}:{...Us(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...by("x",e,{defaultPos:n==="horizontal"?"zeroOrMax":"mid",defaultPos2:"zeroOrMin",range:n!=="vertical"}),...by("y",e,{defaultPos:n==="vertical"?"zeroOrMax":"mid",defaultPos2:"zeroOrMin",range:n!=="horizontal"}),...Mr("size",e,{vgChannel:"strokeWidth"})}}},aEe={vgMark:"text",encodeEntry:e=>{const{config:t,encoding:n}=e;return{...Us(e,{align:"include",baseline:"include",color:"include",size:"ignore",orient:"ignore",theta:"include"}),...pi("x",e,{defaultPos:"mid"}),...pi("y",e,{defaultPos:"mid"}),...y5(e),...Mr("size",e,{vgChannel:"fontSize"}),...Mr("angle",e),...n8("align",oEe(e.markDef,n,t)),...n8("baseline",lEe(e.markDef,n,t)),...pi("radius",e,{defaultPos:null}),...pi("theta",e,{defaultPos:null})}}};function oEe(e,t,n){if(fn("align",e,n)===void 0)return"center"}function lEe(e,t,n){if(fn("baseline",e,n)===void 0)return"middle"}const uEe={vgMark:"rect",encodeEntry:e=>{const{config:t,markDef:n}=e,r=n.orient,i=r==="horizontal"?"x":"y",s=r==="horizontal"?"y":"x",a=r==="horizontal"?"height":"width";return{...Us(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...fl(e,i),...pi(s,e,{defaultPos:"mid",vgChannel:s==="y"?"yc":"xc"}),[a]:En(fn("thickness",n,t))}}},Wm={arc:Ywe,area:Vwe,bar:Xwe,circle:nEe,geoshape:Kwe,image:Zwe,line:Jwe,point:tEe,rect:iEe,rule:sEe,square:rEe,text:aEe,tick:uEe,trail:Qwe};function cEe(e){if(Ut([d2,c2,ove],e.mark)){const t=Rj(e.mark,e.encoding);if(t.length>0)return fEe(e,t)}else if(e.mark===f2){const t=yA.some(n=>fn(n,e.markDef,e.config));if(e.stack&&!e.fieldDef("size")&&t)return dEe(e)}return B5(e)}const F8="faceted_path_";function fEe(e,t){return[{name:e.getName("pathgroup"),type:"group",from:{facet:{name:F8+e.requestDataName(Tn.Main),data:e.requestDataName(Tn.Main),groupby:t}},encode:{update:{width:{field:{group:"width"}},height:{field:{group:"height"}}}},marks:B5(e,{fromPrefix:F8})}]}const D8="stack_group_";function dEe(e){var u;const[t]=B5(e,{fromPrefix:D8}),n=e.scaleName(e.stack.fieldChannel),r=(c={})=>e.vgField(e.stack.fieldChannel,c),i=(c,f)=>{const d=[r({prefix:"min",suffix:"start",expr:f}),r({prefix:"max",suffix:"start",expr:f}),r({prefix:"min",suffix:"end",expr:f}),r({prefix:"max",suffix:"end",expr:f})];return`${c}(${d.map(h=>`scale('${n}',${h})`).join(",")})`};let s,a;e.stack.fieldChannel==="x"?(s={...Jd(t.encode.update,["y","yc","y2","height",...yA]),x:{signal:i("min","datum")},x2:{signal:i("max","datum")},clip:{value:!0}},a={x:{field:{group:"x"},mult:-1},height:{field:{group:"height"}}},t.encode.update={...Li(t.encode.update,["y","yc","y2"]),height:{field:{group:"height"}}}):(s={...Jd(t.encode.update,["x","xc","x2","width"]),y:{signal:i("min","datum")},y2:{signal:i("max","datum")},clip:{value:!0}},a={y:{field:{group:"y"},mult:-1},width:{field:{group:"width"}}},t.encode.update={...Li(t.encode.update,["x","xc","x2"]),width:{field:{group:"width"}}});for(const c of yA){const f=co(c,e.markDef,e.config);t.encode.update[c]?(s[c]=t.encode.update[c],delete t.encode.update[c]):f&&(s[c]=En(f)),f&&(t.encode.update[c]={value:0})}const o=[];if(((u=e.stack.groupbyChannels)==null?void 0:u.length)>0)for(const c of e.stack.groupbyChannels){const f=e.fieldDef(c),d=ze(f);d&&o.push(d),(f!=null&&f.bin||f!=null&&f.timeUnit)&&o.push(ze(f,{binSuffix:"end"}))}return s=["stroke","strokeWidth","strokeJoin","strokeCap","strokeDash","strokeDashOffset","strokeMiterLimit","strokeOpacity"].reduce((c,f)=>{if(t.encode.update[f])return{...c,[f]:t.encode.update[f]};{const d=co(f,e.markDef,e.config);return d!==void 0?{...c,[f]:En(d)}:c}},s),s.stroke&&(s.strokeForeground={value:!0},s.strokeOffset={value:0}),[{type:"group",from:{facet:{data:e.requestDataName(Tn.Main),name:D8+e.requestDataName(Tn.Main),groupby:o,aggregate:{fields:[r({suffix:"start"}),r({suffix:"start"}),r({suffix:"end"}),r({suffix:"end"})],ops:["min","max","min","max"]}}},encode:{update:s},marks:[{type:"group",encode:{update:a},marks:[t]}]}]}function hEe(e){const{encoding:t,stack:n,mark:r,markDef:i,config:s}=e,a=t.order;if(!(!Se(a)&&ma(a)&&mA(a.value)||!a&&mA(fn("order",i,s)))){if((Se(a)||Oe(a))&&!n)return $z(a,{expr:"datum"});if(Lu(r)){const o=i.orient==="horizontal"?"y":"x",l=t[o];if(Oe(l))return{field:o}}}}function B5(e,t={fromPrefix:""}){const{mark:n,markDef:r,encoding:i,config:s}=e,a=Vn(r.clip,pEe(e),gEe(e)),o=Sz(r),l=i.key,u=hEe(e),c=mEe(e),f=fn("aria",r,s),d=Wm[n].postEncodingTransform?Wm[n].postEncodingTransform(e):null;return[{name:e.getName("marks"),type:Wm[n].vgMark,...a?{clip:a}:{},...o?{style:o}:{},...l?{key:l.field}:{},...u?{sort:u}:{},...c||{},...f===!1?{aria:f}:{},from:{data:t.fromPrefix+e.requestDataName(Tn.Main)},encode:{update:Wm[n].encodeEntry(e)},...d?{transform:d}:{}}]}function pEe(e){const t=e.getScaleComponent("x"),n=e.getScaleComponent("y");return t!=null&&t.get("selectionExtent")||n!=null&&n.get("selectionExtent")?!0:void 0}function gEe(e){const t=e.component.projection;return t&&!t.isFit?!0:void 0}function mEe(e){if(!e.component.selection)return null;const t=Fe(e.component.selection).length;let n=t,r=e.parent;for(;r&&n===0;)n=Fe(r.component.selection).length,r=r.parent;return n?{interactive:t>0||e.mark==="geoshape"||!!e.encoding.tooltip||!!e.markDef.tooltip}:null}class Mq extends Sq{constructor(t,n,r,i={},s){super(t,"unit",n,r,s,void 0,O6(t)?t.view:void 0),this.specifiedScales={},this.specifiedAxes={},this.specifiedLegends={},this.specifiedProjection={},this.selection=[],this.children=[],this.correctDataNames=u=>{var c,f,d;return(c=u.from)!=null&&c.data&&(u.from.data=this.lookupDataSource(u.from.data),"time"in this.encoding&&(u.from.data=u.from.data+pU)),(d=(f=u.from)==null?void 0:f.facet)!=null&&d.data&&(u.from.facet.data=this.lookupDataSource(u.from.facet.data)),u};const a=fo(t.mark)?{...t.mark}:{type:t.mark},o=a.type;a.filled===void 0&&(a.filled=Wye(a,s,{graticule:t.data&&m5(t.data)}));const l=this.encoding=Vve(t.encoding||{},o,a.filled,s);this.markDef=eU(a,l,s),this.size=Gwe({encoding:l,size:O6(t)?{...i,...t.width?{width:t.width}:{},...t.height?{height:t.height}:{}}:i}),this.stack=Qj(this.markDef,l),this.specifiedScales=this.initScales(o,l),this.specifiedAxes=this.initAxes(l),this.specifiedLegends=this.initLegends(l),this.specifiedProjection=t.projection,this.selection=(t.params??[]).filter(u=>f5(u))}get hasProjection(){const{encoding:t}=this,n=this.mark===sj,r=t&&z0e.some(i=>$t(t[i]));return n||r}scaleDomain(t){const n=this.specifiedScales[t];return n?n.domain:void 0}axis(t){return this.specifiedAxes[t]}legend(t){return this.specifiedLegends[t]}initScales(t,n){return C$.reduce((r,i)=>{const s=ir(n[i]);return s&&(r[i]=this.initScale(s.scale??{})),r},{})}initScale(t){const{domain:n,range:r}=t,i=Fr(t);return Se(n)&&(i.domain=n.map(Qi)),Se(r)&&(i.range=r.map(Qi)),i}initAxes(t){return bl.reduce((n,r)=>{const i=t[r];if($t(i)||r===$n&&$t(t.x2)||r===kr&&$t(t.y2)){const s=$t(i)?i.axis:void 0;n[r]=s&&this.initAxis({...s})}return n},{})}initAxis(t){const n=Fe(t),r={};for(const i of n){const s=t[i];r[i]=K0(s)?kz(s):Qi(s)}return r}initLegends(t){return Z0e.reduce((n,r)=>{const i=ir(t[r]);if(i&&Q0e(r)){const s=i.legend;n[r]=s&&Fr(s)}return n},{})}parseData(){this.component.data=W2(this)}parseLayoutSize(){Fwe(this)}parseSelections(){this.component.selection=b_e(this,this.selection)}parseMarkGroup(){this.component.mark=cEe(this)}parseAxesAndHeaders(){this.component.axes=Pwe(this)}assembleSelectionTopLevelSignals(t){return Ibe(this,t)}assembleSignals(){return[...GU(this),...Obe(this,[])]}assembleSelectionData(t){return Pbe(this,t)}assembleLayout(){return null}assembleLayoutSignals(){return C5(this)}assembleMarks(){let t=this.component.mark??[];return(!this.parent||!Uh(this.parent))&&(t=yU(this,t)),t.map(this.correctDataNames)}assembleGroupStyle(){const{style:t}=this.view||{};return t!==void 0?t:this.encoding.x||this.encoding.y?"cell":"view"}getMapping(){return this.encoding}get mark(){return this.markDef.type}channelHasField(t){return $c(this.encoding,t)}fieldDef(t){const n=this.encoding[t];return va(n)}typedFieldDef(t){const n=this.fieldDef(t);return bi(n)?n:null}}class z5 extends O5{constructor(t,n,r,i,s){super(t,"layer",n,r,s,t.resolve,t.view);const a={...i,...t.width?{width:t.width}:{},...t.height?{height:t.height}:{}};this.children=t.layer.map((o,l)=>{if(w2(o))return new z5(o,this,this.getName(`layer_${l}`),a,s);if(_l(o))return new Mq(o,this,this.getName(`layer_${l}`),a,s);throw new Error(F$(o))})}parseData(){this.component.data=W2(this);for(const t of this.children)t.parseData()}parseLayoutSize(){Cwe(this)}parseSelections(){this.component.selection={};for(const t of this.children){t.parseSelections();for(const n of Fe(t.component.selection))this.component.selection[n]=t.component.selection[n]}Object.values(this.component.selection).some(t=>to(t))&&T$(M$)}parseMarkGroup(){for(const t of this.children)t.parseMarkGroup()}parseAxesAndHeaders(){zwe(this)}assembleSelectionTopLevelSignals(t){return this.children.reduce((n,r)=>r.assembleSelectionTopLevelSignals(n),t)}assembleSignals(){return this.children.reduce((t,n)=>t.concat(n.assembleSignals()),GU(this))}assembleLayoutSignals(){return this.children.reduce((t,n)=>t.concat(n.assembleLayoutSignals()),C5(this))}assembleSelectionData(t){return this.children.reduce((n,r)=>r.assembleSelectionData(n),t)}assembleGroupStyle(){const t=new Set;for(const r of this.children)for(const i of He(r.assembleGroupStyle()))t.add(i);const n=Array.from(t);return n.length>1?n:n.length===1?n[0]:void 0}assembleTitle(){let t=super.assembleTitle();if(t)return t;for(const n of this.children)if(t=n.assembleTitle(),t)return t}assembleLayout(){return null}assembleMarks(){return Bbe(this,this.children.flatMap(t=>t.assembleMarks()))}assembleLegends(){return this.children.reduce((t,n)=>t.concat(n.assembleLegends()),uq(this))}}function j5(e,t,n,r,i){if(g2(e))return new dg(e,t,n,i);if(w2(e))return new z5(e,t,n,r,i);if(_l(e))return new Mq(e,t,n,r,i);if(yye(e))return new Nwe(e,t,n,i);throw new Error(F$(e))}function vEe(e,t={}){t.logger&&x1e(t.logger),t.fieldTitle&&Ej(t.fieldTitle);try{const n=Jj(yh(t.config,e.config)),r=oU(e,n),i=j5(r,null,"",void 0,n);return i.parse(),jxe(i.component.data,i),{spec:bEe(i,yEe(e,r.autosize,n,i),e.datasets,e.usermeta),normalized:r}}finally{t.logger&&w1e(),t.fieldTitle&&Bve()}}function yEe(e,t,n,r){const i=r.component.layoutSize.get("width"),s=r.component.layoutSize.get("height");if(t===void 0?(t={type:"pad"},r.hasAxisOrientSignalRef()&&(t.resize=!0)):We(t)&&(t={type:t}),i&&s&&kbe(t.type)){if(i==="step"&&s==="step")Te(b6()),t.type="pad";else if(i==="step"||s==="step"){const a=i==="step"?"width":"height";Te(b6(i2(a)));const o=a==="width"?"height":"width";t.type=Sbe(o)}}return{...Fe(t).length===1&&t.type?t.type==="pad"?{}:{autosize:t.type}:{autosize:t},...Y6(n,!1),...Y6(e,!0)}}function bEe(e,t,n={},r){const i=e.config?Tye(e.config):void 0,s=Ewe(e.component.data,n),a=e.assembleSelectionData(s),o=e.assembleProjections(),l=e.assembleTitle(),u=e.assembleGroupStyle(),c=e.assembleGroupEncodeEntry(!0);let f=e.assembleLayoutSignals();f=f.filter(p=>(p.name==="width"||p.name==="height")&&p.value!==void 0?(t[p.name]=+p.value,!1):!0);const{params:d,...h}=t;return{$schema:"https://vega.github.io/schema/vega/v5.json",...e.description?{description:e.description}:{},...h,...l?{title:l}:{},...u?{style:u}:{},...c?{encode:{update:c}}:{},data:a,...o.length>0?{projections:o}:{},...e.assembleGroup([...f,...e.assembleSelectionTopLevelSignals([]),...Vj(d)]),...i?{config:i}:{},...r?{usermeta:r}:{}}}const _Ee=N0e.version,xEe=Object.freeze(Object.defineProperty({__proto__:null,accessPathDepth:eh,accessPathWithDatum:b$,accessWithDatumToUnescapedPath:sn,compile:vEe,contains:Ut,deepEqual:ns,deleteNestedProperty:uy,duplicate:Ct,entries:hu,every:m$,fieldIntersection:y$,flatAccessWithDatum:az,getFirstDefined:Vn,hasIntersection:v$,hasProperty:De,hash:Gt,internalField:uz,isBoolean:zg,isEmpty:dn,isEqual:L0e,isInternalField:cz,isNullOrFalse:mA,isNumeric:Jb,keys:Fe,logicalExpr:ug,mergeDeep:iz,never:rz,normalize:oU,normalizeAngle:jg,omit:Li,pick:Jd,prefixGenerator:vA,removePathFromField:Oh,replaceAll:Jc,replacePathInField:Ps,resetIdCounter:P0e,setEqual:sz,some:Qd,stringify:hn,titleCase:B0,unique:Xa,uniqueId:lz,vals:Lr,varName:Cn,version:_Ee},Symbol.toStringTag,{value:"Module"}));function Tq(e){const[t,n]=/schema\/([\w-]+)\/([\w\.\-]+)\.json$/g.exec(e).slice(1,3);return{library:t,version:n}}var wEe="2.15.0",EEe={version:wEe};const qf="#fff",M8="#888",AEe={background:"#333",view:{stroke:M8},title:{color:qf,subtitleColor:qf},style:{"guide-label":{fill:qf},"guide-title":{fill:qf}},axis:{domainColor:qf,gridColor:M8,tickColor:qf}},Yu="#4572a7",kEe={background:"#fff",arc:{fill:Yu},area:{fill:Yu},line:{stroke:Yu,strokeWidth:2},path:{stroke:Yu},rect:{fill:Yu},shape:{stroke:Yu},symbol:{fill:Yu,strokeWidth:1.5,size:50},axis:{bandPosition:.5,grid:!0,gridColor:"#000000",gridOpacity:1,gridWidth:.5,labelPadding:10,tickSize:5,tickWidth:.5},axisBand:{grid:!1,tickExtra:!0},legend:{labelBaseline:"middle",labelFontSize:11,symbolSize:50,symbolType:"square"},range:{category:["#4572a7","#aa4643","#8aa453","#71598e","#4598ae","#d98445","#94aace","#d09393","#b9cc98","#a99cbc"]}},Vu="#30a2da",Bx="#cbcbcb",SEe="#999",CEe="#333",T8="#f0f0f0",R8="#333",$Ee={arc:{fill:Vu},area:{fill:Vu},axis:{domainColor:Bx,grid:!0,gridColor:Bx,gridWidth:1,labelColor:SEe,labelFontSize:10,titleColor:CEe,tickColor:Bx,tickSize:10,titleFontSize:14,titlePadding:10,labelPadding:4},axisBand:{grid:!1},background:T8,group:{fill:T8},legend:{labelColor:R8,labelFontSize:11,padding:1,symbolSize:30,symbolType:"square",titleColor:R8,titleFontSize:14,titlePadding:10},line:{stroke:Vu,strokeWidth:2},path:{stroke:Vu,strokeWidth:.5},rect:{fill:Vu},range:{category:["#30a2da","#fc4f30","#e5ae38","#6d904f","#8b8b8b","#b96db8","#ff9e27","#56cc60","#52d2ca","#52689e","#545454","#9fe4f8"],diverging:["#cc0020","#e77866","#f6e7e1","#d6e8ed","#91bfd9","#1d78b5"],heatmap:["#d6e8ed","#cee0e5","#91bfd9","#549cc6","#1d78b5"]},point:{filled:!0,shape:"circle"},shape:{stroke:Vu},bar:{binSpacing:2,fill:Vu,stroke:null},title:{anchor:"start",fontSize:24,fontWeight:600,offset:20}},Xu="#000",FEe={group:{fill:"#e5e5e5"},arc:{fill:Xu},area:{fill:Xu},line:{stroke:Xu},path:{stroke:Xu},rect:{fill:Xu},shape:{stroke:Xu},symbol:{fill:Xu,size:40},axis:{domain:!1,grid:!0,gridColor:"#FFFFFF",gridOpacity:1,labelColor:"#7F7F7F",labelPadding:4,tickColor:"#7F7F7F",tickSize:5.67,titleFontSize:16,titleFontWeight:"normal"},legend:{labelBaseline:"middle",labelFontSize:11,symbolSize:40},range:{category:["#000000","#7F7F7F","#1A1A1A","#999999","#333333","#B0B0B0","#4D4D4D","#C9C9C9","#666666","#DCDCDC"]}},DEe=22,MEe="normal",N8="Benton Gothic, sans-serif",O8=11.5,TEe="normal",Ku="#82c6df",zx="Benton Gothic Bold, sans-serif",L8="normal",I8=13,vp={"category-6":["#ec8431","#829eb1","#c89d29","#3580b1","#adc839","#ab7fb4"],"fire-7":["#fbf2c7","#f9e39c","#f8d36e","#f4bb6a","#e68a4f","#d15a40","#ab4232"],"fireandice-6":["#e68a4f","#f4bb6a","#f9e39c","#dadfe2","#a6b7c6","#849eae"]},REe={background:"#ffffff",title:{anchor:"start",color:"#000000",font:zx,fontSize:DEe,fontWeight:MEe},arc:{fill:Ku},area:{fill:Ku},line:{stroke:Ku,strokeWidth:2},path:{stroke:Ku},rect:{fill:Ku},shape:{stroke:Ku},symbol:{fill:Ku,size:30},axis:{labelFont:N8,labelFontSize:O8,labelFontWeight:TEe,titleFont:zx,titleFontSize:I8,titleFontWeight:L8},axisX:{labelAngle:0,labelPadding:4,tickSize:3},axisY:{labelBaseline:"middle",maxExtent:45,minExtent:45,tickSize:2,titleAlign:"left",titleAngle:0,titleX:-45,titleY:-11},legend:{labelFont:N8,labelFontSize:O8,symbolType:"square",titleFont:zx,titleFontSize:I8,titleFontWeight:L8},range:{category:vp["category-6"],diverging:vp["fireandice-6"],heatmap:vp["fire-7"],ordinal:vp["fire-7"],ramp:vp["fire-7"]}},Zu="#ab5787",Hm="#979797",NEe={background:"#f9f9f9",arc:{fill:Zu},area:{fill:Zu},line:{stroke:Zu},path:{stroke:Zu},rect:{fill:Zu},shape:{stroke:Zu},symbol:{fill:Zu,size:30},axis:{domainColor:Hm,domainWidth:.5,gridWidth:.2,labelColor:Hm,tickColor:Hm,tickWidth:.2,titleColor:Hm},axisBand:{grid:!1},axisX:{grid:!0,tickSize:10},axisY:{domain:!1,grid:!0,tickSize:0},legend:{labelFontSize:11,padding:1,symbolSize:30,symbolType:"square"},range:{category:["#ab5787","#51b2e5","#703c5c","#168dd9","#d190b6","#00609f","#d365ba","#154866","#666666","#c4c4c4"]}},Ju="#3e5c69",OEe={background:"#fff",arc:{fill:Ju},area:{fill:Ju},line:{stroke:Ju},path:{stroke:Ju},rect:{fill:Ju},shape:{stroke:Ju},symbol:{fill:Ju},axis:{domainWidth:.5,grid:!0,labelPadding:2,tickSize:5,tickWidth:.5,titleFontWeight:"normal"},axisBand:{grid:!1},axisX:{gridWidth:.2},axisY:{gridDash:[3],gridWidth:.4},legend:{labelFontSize:11,padding:1,symbolType:"square"},range:{category:["#3e5c69","#6793a6","#182429","#0570b0","#3690c0","#74a9cf","#a6bddb","#e2ddf2"]}},ms="#1696d2",P8="#000000",LEe="#FFFFFF",Gm="Lato",jx="Lato",IEe="Lato",PEe="#DEDDDD",BEe=18,yp={"shades-blue":["#CFE8F3","#A2D4EC","#73BFE2","#46ABDB","#1696D2","#12719E","#0A4C6A","#062635"],"six-groups-cat-1":["#1696d2","#ec008b","#fdbf11","#000000","#d2d2d2","#55b748"],"six-groups-seq":["#cfe8f3","#a2d4ec","#73bfe2","#46abdb","#1696d2","#12719e"],"diverging-colors":["#ca5800","#fdbf11","#fdd870","#fff2cf","#cfe8f3","#73bfe2","#1696d2","#0a4c6a"]},zEe={background:LEe,title:{anchor:"start",fontSize:BEe,font:Gm},axisX:{domain:!0,domainColor:P8,domainWidth:1,grid:!1,labelFontSize:12,labelFont:jx,labelAngle:0,tickColor:P8,tickSize:5,titleFontSize:12,titlePadding:10,titleFont:Gm},axisY:{domain:!1,domainWidth:1,grid:!0,gridColor:PEe,gridWidth:1,labelFontSize:12,labelFont:jx,labelPadding:8,ticks:!1,titleFontSize:12,titlePadding:10,titleFont:Gm,titleAngle:0,titleY:-10,titleX:18},legend:{labelFontSize:12,labelFont:jx,symbolSize:100,titleFontSize:12,titlePadding:10,titleFont:Gm,orient:"right",offset:10},view:{stroke:"transparent"},range:{category:yp["six-groups-cat-1"],diverging:yp["diverging-colors"],heatmap:yp["diverging-colors"],ordinal:yp["six-groups-seq"],ramp:yp["shades-blue"]},area:{fill:ms},rect:{fill:ms},line:{color:ms,stroke:ms,strokeWidth:5},trail:{color:ms,stroke:ms,strokeWidth:0,size:1},path:{stroke:ms,strokeWidth:.5},point:{filled:!0},text:{font:IEe,color:ms,fontSize:11,align:"center",fontWeight:400,size:11},style:{bar:{fill:ms,stroke:null}},arc:{fill:ms},shape:{stroke:ms},symbol:{fill:ms,size:30}},Qu="#3366CC",B8="#ccc",Ym="Arial, sans-serif",jEe={arc:{fill:Qu},area:{fill:Qu},path:{stroke:Qu},rect:{fill:Qu},shape:{stroke:Qu},symbol:{stroke:Qu},circle:{fill:Qu},background:"#fff",padding:{top:10,right:10,bottom:10,left:10},style:{"guide-label":{font:Ym,fontSize:12},"guide-title":{font:Ym,fontSize:12},"group-title":{font:Ym,fontSize:12}},title:{font:Ym,fontSize:14,fontWeight:"bold",dy:-3,anchor:"start"},axis:{gridColor:B8,tickColor:B8,domain:!1,grid:!0},range:{category:["#4285F4","#DB4437","#F4B400","#0F9D58","#AB47BC","#00ACC1","#FF7043","#9E9D24","#5C6BC0","#F06292","#00796B","#C2185B"],heatmap:["#c6dafc","#5e97f6","#2a56c6"]}},U5=e=>e*(1/3+1),z8=U5(9),j8=U5(10),U8=U5(12),bp="Segoe UI",q8="wf_standard-font, helvetica, arial, sans-serif",W8="#252423",_p="#605E5C",H8="transparent",UEe="#C8C6C4",Ys="#118DFF",qEe="#12239E",WEe="#E66C37",HEe="#6B007B",GEe="#E044A7",YEe="#744EC2",VEe="#D9B300",XEe="#D64550",Rq=Ys,Nq="#DEEFFF",G8=[Nq,Rq],KEe=[Nq,"#c7e4ff","#b0d9ff","#9aceff","#83c3ff","#6cb9ff","#55aeff","#3fa3ff","#2898ff",Rq],ZEe={view:{stroke:H8},background:H8,font:bp,header:{titleFont:q8,titleFontSize:U8,titleColor:W8,labelFont:bp,labelFontSize:j8,labelColor:_p},axis:{ticks:!1,grid:!1,domain:!1,labelColor:_p,labelFontSize:z8,titleFont:q8,titleColor:W8,titleFontSize:U8,titleFontWeight:"normal"},axisQuantitative:{tickCount:3,grid:!0,gridColor:UEe,gridDash:[1,5],labelFlush:!1},axisBand:{tickExtra:!0},axisX:{labelPadding:5},axisY:{labelPadding:10},bar:{fill:Ys},line:{stroke:Ys,strokeWidth:3,strokeCap:"round",strokeJoin:"round"},text:{font:bp,fontSize:z8,fill:_p},arc:{fill:Ys},area:{fill:Ys,line:!0,opacity:.6},path:{stroke:Ys},rect:{fill:Ys},point:{fill:Ys,filled:!0,size:75},shape:{stroke:Ys},symbol:{fill:Ys,strokeWidth:1.5,size:50},legend:{titleFont:bp,titleFontWeight:"bold",titleColor:_p,labelFont:bp,labelFontSize:j8,labelColor:_p,symbolType:"circle",symbolSize:75},range:{category:[Ys,qEe,WEe,HEe,GEe,YEe,VEe,XEe],diverging:G8,heatmap:G8,ordinal:KEe}},Ux='IBM Plex Sans,system-ui,-apple-system,BlinkMacSystemFont,".sfnstext-regular",sans-serif',JEe='IBM Plex Sans Condensed, system-ui, -apple-system, BlinkMacSystemFont, ".SFNSText-Regular", sans-serif',qx=400,Vm={textPrimary:{g90:"#f4f4f4",g100:"#f4f4f4",white:"#161616",g10:"#161616"},textSecondary:{g90:"#c6c6c6",g100:"#c6c6c6",white:"#525252",g10:"#525252"},layerAccent01:{white:"#e0e0e0",g10:"#e0e0e0",g90:"#525252",g100:"#393939"},gridBg:{white:"#ffffff",g10:"#ffffff",g90:"#161616",g100:"#161616"}},QEe=["#8a3ffc","#33b1ff","#007d79","#ff7eb6","#fa4d56","#fff1f1","#6fdc8c","#4589ff","#d12771","#d2a106","#08bdba","#bae6ff","#ba4e00","#d4bbff"],eAe=["#6929c4","#1192e8","#005d5d","#9f1853","#fa4d56","#570408","#198038","#002d9c","#ee538b","#b28600","#009d9a","#012749","#8a3800","#a56eff"];function H2({theme:e,background:t}){const n=["white","g10"].includes(e)?"light":"dark",r=Vm.gridBg[e],i=Vm.textPrimary[e],s=Vm.textSecondary[e],a=n==="dark"?QEe:eAe,o=n==="dark"?"#d4bbff":"#6929c4";return{background:t,arc:{fill:o},area:{fill:o},path:{stroke:o},rect:{fill:o},shape:{stroke:o},symbol:{stroke:o},circle:{fill:o},view:{fill:r,stroke:r},group:{fill:r},title:{color:i,anchor:"start",dy:-15,fontSize:16,font:Ux,fontWeight:600},axis:{labelColor:s,labelFontSize:12,labelFont:JEe,labelFontWeight:qx,titleColor:i,titleFontWeight:600,titleFontSize:12,grid:!0,gridColor:Vm.layerAccent01[e],labelAngle:0},axisX:{titlePadding:10},axisY:{titlePadding:2.5},style:{"guide-label":{font:Ux,fill:s,fontWeight:qx},"guide-title":{font:Ux,fill:s,fontWeight:qx}},range:{category:a,diverging:["#750e13","#a2191f","#da1e28","#fa4d56","#ff8389","#ffb3b8","#ffd7d9","#fff1f1","#e5f6ff","#bae6ff","#82cfff","#33b1ff","#1192e8","#0072c3","#00539a","#003a6d"],heatmap:["#f6f2ff","#e8daff","#d4bbff","#be95ff","#a56eff","#8a3ffc","#6929c4","#491d8b","#31135e","#1c0f30"]}}}const tAe=H2({theme:"white",background:"#ffffff"}),nAe=H2({theme:"g10",background:"#f4f4f4"}),rAe=H2({theme:"g90",background:"#262626"}),iAe=H2({theme:"g100",background:"#161616"}),sAe=EEe.version,aAe=Object.freeze(Object.defineProperty({__proto__:null,carbong10:nAe,carbong100:iAe,carbong90:rAe,carbonwhite:tAe,dark:AEe,excel:kEe,fivethirtyeight:$Ee,ggplot2:FEe,googlecharts:jEe,latimes:REe,powerbi:ZEe,quartz:NEe,urbaninstitute:zEe,version:sAe,vox:OEe},Symbol.toStringTag,{value:"Module"}));function oAe(e,t,n,r){if(Se(e))return`[${e.map(i=>t(We(i)?i:Y8(i,n))).join(", ")}]`;if(Ue(e)){let i="";const{title:s,image:a,...o}=e;s&&(i+=`

      ${t(s)}

      `),a&&(i+=``);const l=Object.keys(o);if(l.length>0){i+="";for(const u of l){let c=o[u];c!==void 0&&(Ue(c)&&(c=Y8(c,n)),i+=``)}i+="
      ${t(u)}${t(c)}
      "}return i||"{}"}return t(e)}function lAe(e){const t=[];return function(n,r){if(typeof r!="object"||r===null)return r;const i=t.indexOf(this)+1;return t.length=i,t.length>e?"[Object]":t.indexOf(r)>=0?"[Circular]":(t.push(r),r)}}function Y8(e,t){return JSON.stringify(e,lAe(t))}var uAe=`#vg-tooltip-element { + visibility: hidden; + padding: 8px; + position: fixed; + z-index: 1000; + font-family: sans-serif; + font-size: 11px; + border-radius: 3px; + box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); + /* The default theme is the light theme. */ + background-color: rgba(255, 255, 255, 0.95); + border: 1px solid #d9d9d9; + color: black; +} +#vg-tooltip-element.visible { + visibility: visible; +} +#vg-tooltip-element h2 { + margin-top: 0; + margin-bottom: 10px; + font-size: 13px; +} +#vg-tooltip-element table { + border-spacing: 0; +} +#vg-tooltip-element table tr { + border: none; +} +#vg-tooltip-element table tr td { + overflow: hidden; + text-overflow: ellipsis; + padding-top: 2px; + padding-bottom: 2px; +} +#vg-tooltip-element table tr td.key { + color: #808080; + max-width: 150px; + text-align: right; + padding-right: 4px; +} +#vg-tooltip-element table tr td.value { + display: block; + max-width: 300px; + max-height: 7em; + text-align: left; +} +#vg-tooltip-element.dark-theme { + background-color: rgba(32, 32, 32, 0.9); + border: 1px solid #f5f5f5; + color: white; +} +#vg-tooltip-element.dark-theme td.key { + color: #bfbfbf; +} +`;const Oq="vg-tooltip-element",cAe={offsetX:10,offsetY:10,id:Oq,styleId:"vega-tooltip-style",theme:"light",disableDefaultStyle:!1,sanitize:fAe,maxDepth:2,formatTooltip:oAe,baseURL:"",anchor:"cursor",position:["top","bottom","left","right","top-left","top-right","bottom-left","bottom-right"]};function fAe(e){return String(e).replace(/&/g,"&").replace(/=0&&e.y>=0&&e.x+t.width<=window.innerWidth&&e.y+t.height<=window.innerHeight}function gAe(e,t,n){return e.clientX>=t.x&&e.clientX<=t.x+n.width&&e.clientY>=t.y&&e.clientY<=t.y+n.height}class mAe{constructor(t){this.options={...cAe,...t};const n=this.options.id;if(this.el=null,this.call=this.tooltipHandler.bind(this),!this.options.disableDefaultStyle&&!document.getElementById(this.options.styleId)){const r=document.createElement("style");r.setAttribute("id",this.options.styleId),r.innerHTML=dAe(n);const i=document.head;i.childNodes.length>0?i.insertBefore(r,i.childNodes[0]):i.appendChild(r)}}tooltipHandler(t,n,r,i){if(this.el=document.getElementById(this.options.id),this.el||(this.el=document.createElement("div"),this.el.setAttribute("id",this.options.id),this.el.classList.add("vg-tooltip"),(document.fullscreenElement??document.body).appendChild(this.el)),i==null||i===""){this.el.classList.remove("visible",`${this.options.theme}-theme`);return}this.el.innerHTML=this.options.formatTooltip(i,this.options.sanitize,this.options.maxDepth,this.options.baseURL),this.el.classList.add("visible",`${this.options.theme}-theme`);const{x:s,y:a}=this.options.anchor==="mark"?hAe(t,n,r,this.el.getBoundingClientRect(),this.options):Lq(n,this.el.getBoundingClientRect(),this.options);this.el.style.top=`${a}px`,this.el.style.left=`${s}px`}}var Wx={};/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017-2022 Joachim Wester + * MIT licensed + */var vAe=(function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,i){r.__proto__=i}||function(r,i){for(var s in i)i.hasOwnProperty(s)&&(r[s]=i[s])},e(t,n)};return function(t,n){e(t,n);function r(){this.constructor=t}t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}})(),yAe=Object.prototype.hasOwnProperty;function GA(e,t){return yAe.call(e,t)}function YA(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&r<=57){t++;continue}return!1}return!0}function nc(e){return e.indexOf("/")===-1&&e.indexOf("~")===-1?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function Bq(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function XA(e){if(e===void 0)return!0;if(e){if(Array.isArray(e)){for(var t=0,n=e.length;t0&&l[c-1]=="constructor"))throw new TypeError("JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&d===void 0&&(u[h]===void 0?d=l.slice(0,c).join("/"):c==f-1&&(d=t.path),d!==void 0&&p(t,0,e,d)),c++,Array.isArray(u)){if(h==="-")h=u.length;else{if(n&&!VA(h))throw new In("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",s,t,e);VA(h)&&(h=~~h)}if(c>=f){if(n&&t.op==="add"&&h>u.length)throw new In("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",s,t,e);var a=_Ae[t.op].call(t,u,h,e);if(a.test===!1)throw new In("Test operation failed","TEST_OPERATION_FAILED",s,t,e);return a}}else if(c>=f){var a=rd[t.op].call(t,u,h,e);if(a.test===!1)throw new In("Test operation failed","TEST_OPERATION_FAILED",s,t,e);return a}if(u=u[h],n&&c0)throw new In('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if((e.op==="move"||e.op==="copy")&&typeof e.from!="string")throw new In("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if((e.op==="add"||e.op==="replace"||e.op==="test")&&e.value===void 0)throw new In("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if((e.op==="add"||e.op==="replace"||e.op==="test")&&XA(e.value))throw new In("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",t,e,n);if(n){if(e.op=="add"){var i=e.path.split("/").length,s=r.split("/").length;if(i!==s+1&&i!==s)throw new In("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",t,e,n)}else if(e.op==="replace"||e.op==="remove"||e.op==="_get"){if(e.path!==r)throw new In("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",t,e,n)}else if(e.op==="move"||e.op==="copy"){var a={op:"_get",path:e.from,value:void 0},o=jq([a],n);if(o&&o.name==="OPERATION_PATH_UNRESOLVABLE")throw new In("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",t,e,n)}}}else throw new In("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",t,e,n)}function jq(e,t,n){try{if(!Array.isArray(e))throw new In("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)G2(rs(t),rs(e),n||!0);else{n=n||ky;for(var r=0;r0&&(e.patches=[],e.callback&&e.callback(r)),r}function W5(e,t,n,r,i){if(t!==e){typeof t.toJSON=="function"&&(t=t.toJSON());for(var s=YA(t),a=YA(e),o=!1,l=a.length-1;l>=0;l--){var u=a[l],c=e[u];if(GA(t,u)&&!(t[u]===void 0&&c!==void 0&&Array.isArray(t)===!1)){var f=t[u];typeof c=="object"&&c!=null&&typeof f=="object"&&f!=null&&Array.isArray(c)===Array.isArray(f)?W5(c,f,n,r+"/"+nc(u),i):c!==f&&(i&&n.push({op:"test",path:r+"/"+nc(u),value:rs(c)}),n.push({op:"replace",path:r+"/"+nc(u),value:rs(f)}))}else Array.isArray(e)===Array.isArray(t)?(i&&n.push({op:"test",path:r+"/"+nc(u),value:rs(c)}),n.push({op:"remove",path:r+"/"+nc(u)}),o=!0):(i&&n.push({op:"test",path:r,value:e}),n.push({op:"replace",path:r,value:t}))}if(!(!o&&s.length==a.length))for(var l=0;l=this.max){const s=this.map.keys().next().value;this.delete(s)}this.map.set(n,r)}return this}}return Hx=e,Hx}var Gx,K8;function H5(){if(K8)return Gx;K8=1;const e=Object.freeze({loose:!0}),t=Object.freeze({});return Gx=r=>r?typeof r!="object"?e:r:t,Gx}var Xm={exports:{}},Yx,Z8;function G5(){if(Z8)return Yx;Z8=1;const e="2.0.0",t=256,n=Number.MAX_SAFE_INTEGER||9007199254740991,r=16,i=t-6;return Yx={MAX_LENGTH:t,MAX_SAFE_COMPONENT_LENGTH:r,MAX_SAFE_BUILD_LENGTH:i,MAX_SAFE_INTEGER:n,RELEASE_TYPES:["major","premajor","minor","preminor","patch","prepatch","prerelease"],SEMVER_SPEC_VERSION:e,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2},Yx}var Vx,J8;function Y2(){return J8||(J8=1,Vx=typeof process=="object"&&Wx&&Wx.NODE_DEBUG&&/\bsemver\b/i.test(Wx.NODE_DEBUG)?(...t)=>console.error("SEMVER",...t):()=>{}),Vx}var Q8;function Y5(){return Q8||(Q8=1,(function(e,t){const{MAX_SAFE_COMPONENT_LENGTH:n,MAX_SAFE_BUILD_LENGTH:r,MAX_LENGTH:i}=G5(),s=Y2();t=e.exports={};const a=t.re=[],o=t.safeRe=[],l=t.src=[],u=t.t={};let c=0;const f="[a-zA-Z0-9-]",d=[["\\s",1],["\\d",i],[f,r]],h=g=>{for(const[v,y]of d)g=g.split(`${v}*`).join(`${v}{0,${y}}`).split(`${v}+`).join(`${v}{1,${y}}`);return g},p=(g,v,y)=>{const b=h(v),_=c++;s(g,_,v),u[g]=_,l[_]=v,a[_]=new RegExp(v,y?"g":void 0),o[_]=new RegExp(b,y?"g":void 0)};p("NUMERICIDENTIFIER","0|[1-9]\\d*"),p("NUMERICIDENTIFIERLOOSE","\\d+"),p("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${f}*`),p("MAINVERSION",`(${l[u.NUMERICIDENTIFIER]})\\.(${l[u.NUMERICIDENTIFIER]})\\.(${l[u.NUMERICIDENTIFIER]})`),p("MAINVERSIONLOOSE",`(${l[u.NUMERICIDENTIFIERLOOSE]})\\.(${l[u.NUMERICIDENTIFIERLOOSE]})\\.(${l[u.NUMERICIDENTIFIERLOOSE]})`),p("PRERELEASEIDENTIFIER",`(?:${l[u.NUMERICIDENTIFIER]}|${l[u.NONNUMERICIDENTIFIER]})`),p("PRERELEASEIDENTIFIERLOOSE",`(?:${l[u.NUMERICIDENTIFIERLOOSE]}|${l[u.NONNUMERICIDENTIFIER]})`),p("PRERELEASE",`(?:-(${l[u.PRERELEASEIDENTIFIER]}(?:\\.${l[u.PRERELEASEIDENTIFIER]})*))`),p("PRERELEASELOOSE",`(?:-?(${l[u.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${l[u.PRERELEASEIDENTIFIERLOOSE]})*))`),p("BUILDIDENTIFIER",`${f}+`),p("BUILD",`(?:\\+(${l[u.BUILDIDENTIFIER]}(?:\\.${l[u.BUILDIDENTIFIER]})*))`),p("FULLPLAIN",`v?${l[u.MAINVERSION]}${l[u.PRERELEASE]}?${l[u.BUILD]}?`),p("FULL",`^${l[u.FULLPLAIN]}$`),p("LOOSEPLAIN",`[v=\\s]*${l[u.MAINVERSIONLOOSE]}${l[u.PRERELEASELOOSE]}?${l[u.BUILD]}?`),p("LOOSE",`^${l[u.LOOSEPLAIN]}$`),p("GTLT","((?:<|>)?=?)"),p("XRANGEIDENTIFIERLOOSE",`${l[u.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`),p("XRANGEIDENTIFIER",`${l[u.NUMERICIDENTIFIER]}|x|X|\\*`),p("XRANGEPLAIN",`[v=\\s]*(${l[u.XRANGEIDENTIFIER]})(?:\\.(${l[u.XRANGEIDENTIFIER]})(?:\\.(${l[u.XRANGEIDENTIFIER]})(?:${l[u.PRERELEASE]})?${l[u.BUILD]}?)?)?`),p("XRANGEPLAINLOOSE",`[v=\\s]*(${l[u.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[u.XRANGEIDENTIFIERLOOSE]})(?:\\.(${l[u.XRANGEIDENTIFIERLOOSE]})(?:${l[u.PRERELEASELOOSE]})?${l[u.BUILD]}?)?)?`),p("XRANGE",`^${l[u.GTLT]}\\s*${l[u.XRANGEPLAIN]}$`),p("XRANGELOOSE",`^${l[u.GTLT]}\\s*${l[u.XRANGEPLAINLOOSE]}$`),p("COERCEPLAIN",`(^|[^\\d])(\\d{1,${n}})(?:\\.(\\d{1,${n}}))?(?:\\.(\\d{1,${n}}))?`),p("COERCE",`${l[u.COERCEPLAIN]}(?:$|[^\\d])`),p("COERCEFULL",l[u.COERCEPLAIN]+`(?:${l[u.PRERELEASE]})?(?:${l[u.BUILD]})?(?:$|[^\\d])`),p("COERCERTL",l[u.COERCE],!0),p("COERCERTLFULL",l[u.COERCEFULL],!0),p("LONETILDE","(?:~>?)"),p("TILDETRIM",`(\\s*)${l[u.LONETILDE]}\\s+`,!0),t.tildeTrimReplace="$1~",p("TILDE",`^${l[u.LONETILDE]}${l[u.XRANGEPLAIN]}$`),p("TILDELOOSE",`^${l[u.LONETILDE]}${l[u.XRANGEPLAINLOOSE]}$`),p("LONECARET","(?:\\^)"),p("CARETTRIM",`(\\s*)${l[u.LONECARET]}\\s+`,!0),t.caretTrimReplace="$1^",p("CARET",`^${l[u.LONECARET]}${l[u.XRANGEPLAIN]}$`),p("CARETLOOSE",`^${l[u.LONECARET]}${l[u.XRANGEPLAINLOOSE]}$`),p("COMPARATORLOOSE",`^${l[u.GTLT]}\\s*(${l[u.LOOSEPLAIN]})$|^$`),p("COMPARATOR",`^${l[u.GTLT]}\\s*(${l[u.FULLPLAIN]})$|^$`),p("COMPARATORTRIM",`(\\s*)${l[u.GTLT]}\\s*(${l[u.LOOSEPLAIN]}|${l[u.XRANGEPLAIN]})`,!0),t.comparatorTrimReplace="$1$2$3",p("HYPHENRANGE",`^\\s*(${l[u.XRANGEPLAIN]})\\s+-\\s+(${l[u.XRANGEPLAIN]})\\s*$`),p("HYPHENRANGELOOSE",`^\\s*(${l[u.XRANGEPLAINLOOSE]})\\s+-\\s+(${l[u.XRANGEPLAINLOOSE]})\\s*$`),p("STAR","(<|>)?=?\\s*\\*"),p("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),p("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")})(Xm,Xm.exports)),Xm.exports}var Xx,eT;function NAe(){if(eT)return Xx;eT=1;const e=/^[0-9]+$/,t=(r,i)=>{const s=e.test(r),a=e.test(i);return s&&a&&(r=+r,i=+i),r===i?0:s&&!a?-1:a&&!s?1:rt(i,r)},Xx}var Kx,tT;function V5(){if(tT)return Kx;tT=1;const e=Y2(),{MAX_LENGTH:t,MAX_SAFE_INTEGER:n}=G5(),{safeRe:r,t:i}=Y5(),s=H5(),{compareIdentifiers:a}=NAe();class o{constructor(u,c){if(c=s(c),u instanceof o){if(u.loose===!!c.loose&&u.includePrerelease===!!c.includePrerelease)return u;u=u.version}else if(typeof u!="string")throw new TypeError(`Invalid version. Must be a string. Got type "${typeof u}".`);if(u.length>t)throw new TypeError(`version is longer than ${t} characters`);e("SemVer",u,c),this.options=c,this.loose=!!c.loose,this.includePrerelease=!!c.includePrerelease;const f=u.trim().match(c.loose?r[i.LOOSE]:r[i.FULL]);if(!f)throw new TypeError(`Invalid Version: ${u}`);if(this.raw=u,this.major=+f[1],this.minor=+f[2],this.patch=+f[3],this.major>n||this.major<0)throw new TypeError("Invalid major version");if(this.minor>n||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>n||this.patch<0)throw new TypeError("Invalid patch version");f[4]?this.prerelease=f[4].split(".").map(d=>{if(/^[0-9]+$/.test(d)){const h=+d;if(h>=0&&h=0;)typeof this.prerelease[h]=="number"&&(this.prerelease[h]++,h=-2);if(h===-1){if(c===this.prerelease.join(".")&&f===!1)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(d)}}if(c){let h=[c,d];f===!1&&(h=[c]),a(this.prerelease[0],c)===0?isNaN(this.prerelease[1])&&(this.prerelease=h):this.prerelease=h}break}default:throw new Error(`invalid increment argument: ${u}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}}return Kx=o,Kx}var Zx,nT;function qh(){if(nT)return Zx;nT=1;const e=V5();return Zx=(n,r,i)=>new e(n,i).compare(new e(r,i)),Zx}var Jx,rT;function OAe(){if(rT)return Jx;rT=1;const e=qh();return Jx=(n,r,i)=>e(n,r,i)===0,Jx}var Qx,iT;function LAe(){if(iT)return Qx;iT=1;const e=qh();return Qx=(n,r,i)=>e(n,r,i)!==0,Qx}var ew,sT;function IAe(){if(sT)return ew;sT=1;const e=qh();return ew=(n,r,i)=>e(n,r,i)>0,ew}var tw,aT;function PAe(){if(aT)return tw;aT=1;const e=qh();return tw=(n,r,i)=>e(n,r,i)>=0,tw}var nw,oT;function BAe(){if(oT)return nw;oT=1;const e=qh();return nw=(n,r,i)=>e(n,r,i)<0,nw}var rw,lT;function zAe(){if(lT)return rw;lT=1;const e=qh();return rw=(n,r,i)=>e(n,r,i)<=0,rw}var iw,uT;function jAe(){if(uT)return iw;uT=1;const e=OAe(),t=LAe(),n=IAe(),r=PAe(),i=BAe(),s=zAe();return iw=(o,l,u,c)=>{switch(l){case"===":return typeof o=="object"&&(o=o.version),typeof u=="object"&&(u=u.version),o===u;case"!==":return typeof o=="object"&&(o=o.version),typeof u=="object"&&(u=u.version),o!==u;case"":case"=":case"==":return e(o,u,c);case"!=":return t(o,u,c);case">":return n(o,u,c);case">=":return r(o,u,c);case"<":return i(o,u,c);case"<=":return s(o,u,c);default:throw new TypeError(`Invalid operator: ${l}`)}},iw}var sw,cT;function UAe(){if(cT)return sw;cT=1;const e=Symbol("SemVer ANY");class t{static get ANY(){return e}constructor(c,f){if(f=n(f),c instanceof t){if(c.loose===!!f.loose)return c;c=c.value}c=c.trim().split(/\s+/).join(" "),a("comparator",c,f),this.options=f,this.loose=!!f.loose,this.parse(c),this.semver===e?this.value="":this.value=this.operator+this.semver.version,a("comp",this)}parse(c){const f=this.options.loose?r[i.COMPARATORLOOSE]:r[i.COMPARATOR],d=c.match(f);if(!d)throw new TypeError(`Invalid comparator: ${c}`);this.operator=d[1]!==void 0?d[1]:"",this.operator==="="&&(this.operator=""),d[2]?this.semver=new o(d[2],this.options.loose):this.semver=e}toString(){return this.value}test(c){if(a("Comparator.test",c,this.options.loose),this.semver===e||c===e)return!0;if(typeof c=="string")try{c=new o(c,this.options)}catch{return!1}return s(c,this.operator,this.semver,this.options)}intersects(c,f){if(!(c instanceof t))throw new TypeError("a Comparator is required");return this.operator===""?this.value===""?!0:new l(c.value,f).test(this.value):c.operator===""?c.value===""?!0:new l(this.value,f).test(c.semver):(f=n(f),f.includePrerelease&&(this.value==="<0.0.0-0"||c.value==="<0.0.0-0")||!f.includePrerelease&&(this.value.startsWith("<0.0.0")||c.value.startsWith("<0.0.0"))?!1:!!(this.operator.startsWith(">")&&c.operator.startsWith(">")||this.operator.startsWith("<")&&c.operator.startsWith("<")||this.semver.version===c.semver.version&&this.operator.includes("=")&&c.operator.includes("=")||s(this.semver,"<",c.semver,f)&&this.operator.startsWith(">")&&c.operator.startsWith("<")||s(this.semver,">",c.semver,f)&&this.operator.startsWith("<")&&c.operator.startsWith(">")))}}sw=t;const n=H5(),{safeRe:r,t:i}=Y5(),s=jAe(),a=Y2(),o=V5(),l=Uq();return sw}var aw,fT;function Uq(){if(fT)return aw;fT=1;const e=/\s+/g;class t{constructor($,L){if(L=i(L),$ instanceof t)return $.loose===!!L.loose&&$.includePrerelease===!!L.includePrerelease?$:new t($.raw,L);if($ instanceof s)return this.raw=$.value,this.set=[[$]],this.formatted=void 0,this;if(this.options=L,this.loose=!!L.loose,this.includePrerelease=!!L.includePrerelease,this.raw=$.trim().replace(e," "),this.set=this.raw.split("||").map(W=>this.parseRange(W.trim())).filter(W=>W.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){const W=this.set[0];if(this.set=this.set.filter(U=>!g(U[0])),this.set.length===0)this.set=[W];else if(this.set.length>1){for(const U of this.set)if(U.length===1&&v(U[0])){this.set=[U];break}}}this.formatted=void 0}get range(){if(this.formatted===void 0){this.formatted="";for(let $=0;$0&&(this.formatted+="||");const L=this.set[$];for(let W=0;W0&&(this.formatted+=" "),this.formatted+=L[W].toString().trim()}}return this.formatted}format(){return this.range}toString(){return this.range}parseRange($){const W=((this.options.includePrerelease&&h)|(this.options.loose&&p))+":"+$,U=r.get(W);if(U)return U;const O=this.options.loose,H=O?l[u.HYPHENRANGELOOSE]:l[u.HYPHENRANGE];$=$.replace(H,P(this.options.includePrerelease)),a("hyphen replace",$),$=$.replace(l[u.COMPARATORTRIM],c),a("comparator trim",$),$=$.replace(l[u.TILDETRIM],f),a("tilde trim",$),$=$.replace(l[u.CARETTRIM],d),a("caret trim",$);let G=$.split(" ").map(be=>b(be,this.options)).join(" ").split(/\s+/).map(be=>N(be,this.options));O&&(G=G.filter(be=>(a("loose invalid filter",be,this.options),!!be.match(l[u.COMPARATORLOOSE])))),a("range list",G);const J=new Map,ce=G.map(be=>new s(be,this.options));for(const be of ce){if(g(be))return[be];J.set(be.value,be)}J.size>1&&J.has("")&&J.delete("");const xe=[...J.values()];return r.set(W,xe),xe}intersects($,L){if(!($ instanceof t))throw new TypeError("a Range is required");return this.set.some(W=>y(W,L)&&$.set.some(U=>y(U,L)&&W.every(O=>U.every(H=>O.intersects(H,L)))))}test($){if(!$)return!1;if(typeof $=="string")try{$=new o($,this.options)}catch{return!1}for(let L=0;LT.value==="<0.0.0-0",v=T=>T.value==="",y=(T,$)=>{let L=!0;const W=T.slice();let U=W.pop();for(;L&&W.length;)L=W.every(O=>U.intersects(O,$)),U=W.pop();return L},b=(T,$)=>(a("comp",T,$),T=A(T,$),a("caret",T),T=x(T,$),a("tildes",T),T=k(T,$),a("xrange",T),T=M(T,$),a("stars",T),T),_=T=>!T||T.toLowerCase()==="x"||T==="*",x=(T,$)=>T.trim().split(/\s+/).map(L=>w(L,$)).join(" "),w=(T,$)=>{const L=$.loose?l[u.TILDELOOSE]:l[u.TILDE];return T.replace(L,(W,U,O,H,G)=>{a("tilde",T,W,U,O,H,G);let J;return _(U)?J="":_(O)?J=`>=${U}.0.0 <${+U+1}.0.0-0`:_(H)?J=`>=${U}.${O}.0 <${U}.${+O+1}.0-0`:G?(a("replaceTilde pr",G),J=`>=${U}.${O}.${H}-${G} <${U}.${+O+1}.0-0`):J=`>=${U}.${O}.${H} <${U}.${+O+1}.0-0`,a("tilde return",J),J})},A=(T,$)=>T.trim().split(/\s+/).map(L=>E(L,$)).join(" "),E=(T,$)=>{a("caret",T,$);const L=$.loose?l[u.CARETLOOSE]:l[u.CARET],W=$.includePrerelease?"-0":"";return T.replace(L,(U,O,H,G,J)=>{a("caret",T,U,O,H,G,J);let ce;return _(O)?ce="":_(H)?ce=`>=${O}.0.0${W} <${+O+1}.0.0-0`:_(G)?O==="0"?ce=`>=${O}.${H}.0${W} <${O}.${+H+1}.0-0`:ce=`>=${O}.${H}.0${W} <${+O+1}.0.0-0`:J?(a("replaceCaret pr",J),O==="0"?H==="0"?ce=`>=${O}.${H}.${G}-${J} <${O}.${H}.${+G+1}-0`:ce=`>=${O}.${H}.${G}-${J} <${O}.${+H+1}.0-0`:ce=`>=${O}.${H}.${G}-${J} <${+O+1}.0.0-0`):(a("no pr"),O==="0"?H==="0"?ce=`>=${O}.${H}.${G}${W} <${O}.${H}.${+G+1}-0`:ce=`>=${O}.${H}.${G}${W} <${O}.${+H+1}.0-0`:ce=`>=${O}.${H}.${G} <${+O+1}.0.0-0`),a("caret return",ce),ce})},k=(T,$)=>(a("replaceXRanges",T,$),T.split(/\s+/).map(L=>C(L,$)).join(" ")),C=(T,$)=>{T=T.trim();const L=$.loose?l[u.XRANGELOOSE]:l[u.XRANGE];return T.replace(L,(W,U,O,H,G,J)=>{a("xRange",T,W,U,O,H,G,J);const ce=_(O),xe=ce||_(H),be=xe||_(G),Le=be;return U==="="&&Le&&(U=""),J=$.includePrerelease?"-0":"",ce?U===">"||U==="<"?W="<0.0.0-0":W="*":U&&Le?(xe&&(H=0),G=0,U===">"?(U=">=",xe?(O=+O+1,H=0,G=0):(H=+H+1,G=0)):U==="<="&&(U="<",xe?O=+O+1:H=+H+1),U==="<"&&(J="-0"),W=`${U+O}.${H}.${G}${J}`):xe?W=`>=${O}.0.0${J} <${+O+1}.0.0-0`:be&&(W=`>=${O}.${H}.0${J} <${O}.${+H+1}.0-0`),a("xRange return",W),W})},M=(T,$)=>(a("replaceStars",T,$),T.trim().replace(l[u.STAR],"")),N=(T,$)=>(a("replaceGTE0",T,$),T.trim().replace(l[$.includePrerelease?u.GTE0PRE:u.GTE0],"")),P=T=>($,L,W,U,O,H,G,J,ce,xe,be,Le)=>(_(W)?L="":_(U)?L=`>=${W}.0.0${T?"-0":""}`:_(O)?L=`>=${W}.${U}.0${T?"-0":""}`:H?L=`>=${L}`:L=`>=${L}${T?"-0":""}`,_(ce)?J="":_(xe)?J=`<${+ce+1}.0.0-0`:_(be)?J=`<${ce}.${+xe+1}.0-0`:Le?J=`<=${ce}.${xe}.${be}-${Le}`:T?J=`<${ce}.${xe}.${+be+1}-0`:J=`<=${J}`,`${L} ${J}`.trim()),I=(T,$,L)=>{for(let W=0;W0){const U=T[W].semver;if(U.major===$.major&&U.minor===$.minor&&U.patch===$.patch)return!0}return!1}return!0};return aw}var ow,dT;function qAe(){if(dT)return ow;dT=1;const e=Uq();return ow=(n,r,i)=>{try{r=new e(r,i)}catch{return!1}return r.test(n)},ow}var WAe=qAe(),qq=TAe(WAe);function HAe(e,t,n){const r=e.open(t),i=250,{origin:s}=new URL(t);let a=40;function o(u){u.source===r&&(a=0,e.removeEventListener("message",o,!1))}e.addEventListener("message",o,!1);function l(){a<=0||(r.postMessage(n,s),setTimeout(l,i),a-=1)}setTimeout(l,i)}var GAe=`.vega-embed { + position: relative; + display: inline-block; + box-sizing: border-box; +} +.vega-embed.has-actions { + padding-right: 38px; +} +.vega-embed details:not([open]) > :not(summary) { + display: none !important; +} +.vega-embed summary { + list-style: none; + position: absolute; + top: 0; + right: 0; + padding: 6px; + z-index: 1000; + background: white; + box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1); + color: #1b1e23; + border: 1px solid #aaa; + border-radius: 999px; + opacity: 0.2; + transition: opacity 0.4s ease-in; + cursor: pointer; + line-height: 0px; +} +.vega-embed summary::-webkit-details-marker { + display: none; +} +.vega-embed summary:active { + box-shadow: #aaa 0px 0px 0px 1px inset; +} +.vega-embed summary svg { + width: 14px; + height: 14px; +} +.vega-embed details[open] summary { + opacity: 0.7; +} +.vega-embed:hover summary, .vega-embed:focus-within summary { + opacity: 1 !important; + transition: opacity 0.2s ease; +} +.vega-embed .vega-actions { + position: absolute; + z-index: 1001; + top: 35px; + right: -9px; + display: flex; + flex-direction: column; + padding-bottom: 8px; + padding-top: 8px; + border-radius: 4px; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2); + border: 1px solid #d9d9d9; + background: white; + animation-duration: 0.15s; + animation-name: scale-in; + animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1.5); + text-align: left; +} +.vega-embed .vega-actions a { + padding: 8px 16px; + font-family: sans-serif; + font-size: 14px; + font-weight: 600; + white-space: nowrap; + color: #434a56; + text-decoration: none; +} +.vega-embed .vega-actions a:hover, .vega-embed .vega-actions a:focus { + background-color: #f7f7f9; + color: black; +} +.vega-embed .vega-actions::before, .vega-embed .vega-actions::after { + content: ""; + display: inline-block; + position: absolute; +} +.vega-embed .vega-actions::before { + left: auto; + right: 14px; + top: -16px; + border: 8px solid rgba(0, 0, 0, 0); + border-bottom-color: #d9d9d9; +} +.vega-embed .vega-actions::after { + left: auto; + right: 15px; + top: -14px; + border: 7px solid rgba(0, 0, 0, 0); + border-bottom-color: #fff; +} +.vega-embed .chart-wrapper.fit-x { + width: 100%; +} +.vega-embed .chart-wrapper.fit-y { + height: 100%; +} + +.vega-embed-wrapper { + max-width: 100%; + overflow: auto; + padding-right: 14px; +} + +@keyframes scale-in { + from { + opacity: 0; + transform: scale(0.6); + } + to { + opacity: 1; + transform: scale(1); + } +} +`;function Wq(e,...t){for(const n of t)YAe(e,n);return e}function YAe(e,t){for(const n of Object.keys(t))bh(e,n,t[n],!0)}const Oa=w0e;let Xg=xEe;const Km=typeof window<"u"?window:void 0;var UT;Xg===void 0&&((UT=Km==null?void 0:Km.vl)!=null&&UT.compile)&&(Xg=Km.vl);const VAe={export:{svg:!0,png:!0},source:!0,compiled:!0,editor:!0},XAe={CLICK_TO_VIEW_ACTIONS:"Click to view actions",COMPILED_ACTION:"View Compiled Vega",EDITOR_ACTION:"Open in Vega Editor",PNG_ACTION:"Save as PNG",SOURCE_ACTION:"View Source",SVG_ACTION:"Save as SVG"},Gp={vega:"Vega","vega-lite":"Vega-Lite"},Sy={vega:Oa.version,"vega-lite":Xg?Xg.version:"not available"},KAe={vega:e=>e,"vega-lite":(e,t)=>Xg.compile(e,{config:t}).spec},ZAe=` + + + + +`,JAe="chart-wrapper";function QAe(e){return typeof e=="function"}function hT(e,t,n,r){const i=`${t}
      `,s=`
      ${n}`,a=window.open("");a.document.write(i+e+s),a.document.title=`${Gp[r]} JSON Source`}function eke(e,t){if(e.$schema){const n=Tq(e.$schema);t&&t!==n.library&&console.warn(`The given visualization spec is written in ${Gp[n.library]}, but mode argument sets ${Gp[t]??t}.`);const r=n.library;return qq(Sy[r],`^${n.version.slice(1)}`)||console.warn(`The input spec uses ${Gp[r]} ${n.version}, but the current version of ${Gp[r]} is v${Sy[r]}.`),r}return"mark"in e||"encoding"in e||"layer"in e||"hconcat"in e||"vconcat"in e||"facet"in e||"repeat"in e?"vega-lite":"marks"in e||"signals"in e||"scales"in e||"axes"in e?"vega":t??"vega"}function Hq(e){return!!(e&&"load"in e)}function pT(e){return Hq(e)?e:Oa.loader(e)}function tke(e){var n;const t=((n=e.usermeta)==null?void 0:n.embedOptions)??{};return We(t.defaultStyle)&&(t.defaultStyle=!1),t}async function Gq(e,t,n={}){let r,i;We(t)?(i=pT(n.loader),r=JSON.parse(await i.load(t))):r=t;const s=tke(r),a=s.loader;(!i||a)&&(i=pT(n.loader??a));const o=await gT(s,i),l=await gT(n,i),u={...Wq(l,o),config:yh(l.config??{},o.config??{})};return await rke(e,r,u,i)}async function gT(e,t){const n=We(e.config)?JSON.parse(await t.load(e.config)):e.config??{},r=We(e.patch)?JSON.parse(await t.load(e.patch)):e.patch;return{...e,...r?{patch:r}:{},...n?{config:n}:{}}}function nke(e){const t=e.getRootNode?e.getRootNode():document;return t instanceof ShadowRoot?{root:t,rootContainer:t}:{root:document,rootContainer:document.head??document.body}}async function rke(e,t,n={},r){const i=n.theme?yh(aAe[n.theme],n.config??{}):n.config,s=xu(n.actions)?n.actions:Wq({},VAe,n.actions??{}),a={...XAe,...n.i18n},o=n.renderer??"canvas",l=n.logLevel??Oa.Warn,u=n.downloadFileName??"visualization",c=typeof e=="string"?document.querySelector(e):e;if(!c)throw new Error(`${e} does not exist`);if(n.defaultStyle!==!1){const w="vega-embed-style",{root:A,rootContainer:E}=nke(c);if(!A.getElementById(w)){const k=document.createElement("style");k.id=w,k.innerHTML=n.defaultStyle===void 0||n.defaultStyle===!0?GAe.toString():n.defaultStyle,E.appendChild(k)}}const f=eke(t,n.mode);let d=KAe[f](t,i);if(f==="vega-lite"&&d.$schema){const w=Tq(d.$schema);qq(Sy.vega,`^${w.version.slice(1)}`)||console.warn(`The compiled spec uses Vega ${w.version}, but current version is v${Sy.vega}.`)}c.classList.add("vega-embed"),s&&c.classList.add("has-actions"),c.innerHTML="";let h=c;if(s){const w=document.createElement("div");w.classList.add(JAe),c.appendChild(w),h=w}const p=n.patch;if(p&&(d=p instanceof Function?p(d):G2(d,p,!0,!1).newDocument),n.formatLocale&&Oa.formatLocale(n.formatLocale),n.timeFormatLocale&&Oa.timeFormatLocale(n.timeFormatLocale),n.expressionFunctions)for(const w in n.expressionFunctions){const A=n.expressionFunctions[w];"fn"in A?Oa.expressionFunction(w,A.fn,A.visitor):A instanceof Function&&Oa.expressionFunction(w,A)}const{ast:g}=n,v=Oa.parse(d,f==="vega-lite"?{}:i,{ast:g}),y=new(n.viewClass||Oa.View)(v,{loader:r,logLevel:l,renderer:o,...g?{expr:Oa.expressionInterpreter??n.expr??T0e}:{}});if(y.addSignalListener("autosize",(w,A)=>{const{type:E}=A;E=="fit-x"?(h.classList.add("fit-x"),h.classList.remove("fit-y")):E=="fit-y"?(h.classList.remove("fit-x"),h.classList.add("fit-y")):E=="fit"?h.classList.add("fit-x","fit-y"):h.classList.remove("fit-x","fit-y")}),n.tooltip!==!1){const{loader:w,tooltip:A}=n,E=w&&!Hq(w)?w==null?void 0:w.baseURL:void 0,k=QAe(A)?A:new mAe({baseURL:E,...A===!0?{}:A}).call;y.tooltip(k)}let{hover:b}=n;if(b===void 0&&(b=f==="vega"),b){const{hoverSet:w,updateSet:A}=typeof b=="boolean"?{}:b;y.hover(w,A)}n&&(n.width!=null&&y.width(n.width),n.height!=null&&y.height(n.height),n.padding!=null&&y.padding(n.padding)),await y.initialize(h,n.bind).runAsync();let _;if(s!==!1){let w=c;if(n.defaultStyle!==!1||n.forceActionsMenu){const E=document.createElement("details");E.title=a.CLICK_TO_VIEW_ACTIONS,c.append(E),w=E;const k=document.createElement("summary");k.innerHTML=ZAe,E.append(k),_=C=>{E.contains(C.target)||E.removeAttribute("open")},document.addEventListener("click",_)}const A=document.createElement("div");if(w.append(A),A.classList.add("vega-actions"),s===!0||s.export!==!1){for(const E of["svg","png"])if(s===!0||s.export===!0||s.export[E]){const k=a[`${E.toUpperCase()}_ACTION`],C=document.createElement("a"),M=Ue(n.scaleFactor)?n.scaleFactor[E]:n.scaleFactor;C.text=k,C.href="#",C.target="_blank",C.download=`${u}.${E}`,C.addEventListener("mousedown",async function(N){N.preventDefault();const P=await y.toImageURL(E,M);this.href=P}),A.append(C)}}if(s===!0||s.source!==!1){const E=document.createElement("a");E.text=a.SOURCE_ACTION,E.href="#",E.addEventListener("click",function(k){hT(g_(t),n.sourceHeader??"",n.sourceFooter??"",f),k.preventDefault()}),A.append(E)}if(f==="vega-lite"&&(s===!0||s.compiled!==!1)){const E=document.createElement("a");E.text=a.COMPILED_ACTION,E.href="#",E.addEventListener("click",function(k){hT(g_(d),n.sourceHeader??"",n.sourceFooter??"","vega"),k.preventDefault()}),A.append(E)}if(s===!0||s.editor!==!1){const E=n.editorUrl??"https://vega.github.io/editor/",k=document.createElement("a");k.text=a.EDITOR_ACTION,k.href="#",k.addEventListener("click",function(C){HAe(window,E,{config:i,mode:p?"vega":f,renderer:o,spec:g_(p?d:t)}),C.preventDefault()}),A.append(k)}}function x(){_&&document.removeEventListener("click",_),y.finalize()}return{view:y,spec:t,vgSpec:d,finalize:x,embedOptions:n}}function mT(e,t,n){return!e||e.length===0?[]:t||e.length<=n?e:e.slice(0,n)}var ike=z('
      '),ske=z('
      '),ake=z(''),oke=z(' '),lke=z(''),uke=z('
      '),cke=z(' '),fke=z('
      '),dke=z('
      ',1),hke=z('
      '),pke=z(''),gke=z(' '),mke=z(''),vke=z('
      '),yke=z(' '),bke=z('
      '),_ke=z('
      '),xke=z('
      ',1);function Cy(e,t){ln(t,!0);let n=se(t,"data",19,()=>[]),r=se(t,"x",3,"step"),i=se(t,"y",3,""),s=se(t,"colorField",3,"run"),a=se(t,"colorDisplayField",3,""),o=se(t,"colorLabel",3,""),l=se(t,"dashField",3,""),u=se(t,"dashLabel",3,""),c=se(t,"yLabel",3,""),f=se(t,"colorMap",19,()=>({})),d=se(t,"title",3,""),h=se(t,"xLim",3,null),p=se(t,"yExtent",3,void 0),g=se(t,"onSelect",3,null),v=se(t,"onResetZoom",3,null),y=se(t,"draggable",3,!1),b=se(t,"ondragstart",3,null),_=se(t,"ondragover",3,null),x=se(t,"ondrop",3,null),w=ie(null),A=ie(null),E=ie(null),k=ie(null),C=ie(!1),M=null,N=!1,P=ke(()=>o()||s()),I=ke(()=>u()||l()),T=ke(()=>c()||(i().includes("/")?i().split("/").pop():i())),$=ke(()=>{if(!s()||!n()||n().length===0)return[];const oe=new Set,fe=[];for(const Ie of n()){const Je=Ie[s()];Je&&!oe.has(Je)&&(oe.add(Je),fe.push({key:Je,name:Ie[a()]||Je,color:f()[Je]||"#999"}))}return fe}),L=ke(()=>qR(n(),s(),f()));const W=6;let U=ie(!1),O=ie(!1),H=ke(()=>mT(m($),m(U),W)),G=ke(()=>mT(m($),m(O),W)),J=ke(()=>{if(!l()||!n()||n().length===0)return[];const oe=new Set,fe=[],Ie=[[1,0],[12,4],[3,2],[10,3,2,3],[2,2],[14,4,2,4],[6,4,1,4],[16,5],[4,2,1,2],[2,1]];for(const Je of n()){const xt=Je[l()];xt&&!oe.has(xt)&&(oe.add(xt),fe.push({name:xt,pattern:Ie[fe.length%Ie.length]}))}return fe}),ce=ke(()=>{if(!l()||!n()||n().length===0)return"";const oe=m(J).map(fe=>`${fe.name}:${fe.pattern.join(",")}`);return oe.sort(),oe.join("|")});function xe(oe,fe){return getComputedStyle(document.documentElement).getPropertyValue(oe).trim()||fe}function be(){const oe=n().filter(Ie=>Ie.data_type==="original"||!Ie.data_type),fe=n().filter(Ie=>Ie.data_type==="smoothed");return{originalData:oe,smoothedData:fe,hasSmoothed:fe.length>0}}function Le(oe){const fe=oe.map(Ie=>Ie[r()]).filter(Ie=>Ie!=null);if(h())return[h()[0],h()[1]];if(fe.length>0)return[Math.min(...fe),Math.max(...fe)]}function tt(){const oe=s()&&n().length>0&&Object.hasOwn(n()[0],s()),fe=l()&&n().length>0&&Object.hasOwn(n()[0],l()),Ie=oe?[...new Set(n().map(Ae=>Ae[s()]))]:[],Je=[...new Set(Ie)],xt=Je,Et=Je.map(Ae=>f()[Ae]||"#999"),{originalData:Ye,smoothedData:ut,hasSmoothed:At}=be();N=At;const It=Le(Ye),et={field:r(),type:"quantitative",scale:{zero:!1,...It?{domain:It}:{}}},mt={field:i(),type:"quantitative",...p()?{scale:{domain:p()}}:{}},vt=oe?{color:{field:s(),type:"nominal",scale:{domain:xt,range:Et},legend:null}}:{},Dt=fe?{strokeDash:{field:l(),type:"nominal",scale:{domain:m(J).map(Ae=>Ae.name),range:m(J).map(Ae=>Ae.pattern)},legend:null}}:{},kt=[],mn=(Ae={})=>({type:"line",clip:!0,strokeWidth:2.25,...Ae}),vn=m(T),lt=[];oe&<.push({field:a()||s(),type:"nominal",title:m(P)}),fe&<.push({field:l(),type:"nominal",title:m(I)}),lt.push({field:r(),type:"quantitative",title:r()},{field:i(),type:"quantitative",title:vn});const Nt=[{name:"hover",select:{type:"point",on:"pointerover",nearest:!0,clear:"pointerout"}}],ne=(Ae,St)=>({...Ae,mark:{type:"circle",clip:!0,size:60,opacity:0},encoding:{x:et,y:mt,...vt,tooltip:lt,opacity:{condition:{param:"hover",empty:!1,value:1},value:0}},params:Nt,name:St});return At?(kt.push({data:{name:"data_original",values:Ye},mark:mn({strokeWidth:1,opacity:.3}),encoding:{x:et,y:mt,...vt,...Dt},name:"original"}),kt.push({data:{name:"data_smoothed",values:ut},mark:mn(),encoding:{x:et,y:mt,...vt,...Dt},name:"plot"}),kt.push(ne({data:{name:"data_smoothed",values:ut}},"hover_points"))):(kt.push({data:{name:"data_plot",values:n()},mark:mn(),encoding:{x:et,y:mt,...vt,...Dt},name:"plot"}),kt.push(ne({data:{name:"data_plot",values:n()}},"hover_points"))),{$schema:"https://vega.github.io/schema/vega-lite/v5.json",width:"container",height:m(C)?"container":250,autosize:{type:"fit",contains:"padding"},layer:kt,...g()?{params:[{name:"brush",select:{type:"interval",encodings:["x"],mark:{fill:"gray",fillOpacity:.3,stroke:"none"}},views:["plot"]}]}:{},config:{background:"transparent",axis:{labelColor:xe("--body-text-color-subdued","#6b7280"),titleColor:xe("--body-text-color","#374151"),gridColor:xe("--border-color-primary","#f3f4f6")},view:{stroke:"transparent"},mark:{cursor:g()?"crosshair":void 0}},encoding:{y:{title:vn}}}}function he(){const{originalData:oe}=be(),fe=Le(oe),Ie=fe?`${fe[0]},${fe[1]}`:"auto",Je=p()?`${p()[0]},${p()[1]}`:"auto";return`${i()}\0${r()}\0${m(L)}\0${m(ce)}\0${d()}\0${m(C)}\0${!!g()}\0${Ie}\0${Je}`}function Y(oe,fe,Ie){const Je=wu().remove(ls).insert(Ie);oe.change(fe,Je)}function Ce(){if(!m(k))return!1;const{originalData:oe,smoothedData:fe,hasSmoothed:Ie}=be();if(Ie!==N)return!1;try{return Ie?(Y(m(k),"data_original",oe),Y(m(k),"data_smoothed",fe)):Y(m(k),"data_plot",n()),m(k).run(),N=Ie,!0}catch{return!1}}async function le(){if(await Mi(),!m(w)||!n()||n().length===0||!i())return;const oe=tt();try{m(k)&&(m(k).finalize(),F(k,null));const fe=await Gq(m(w),oe,{actions:!1,renderer:"canvas"});if(F(k,fe.view,!0),M=he(),requestAnimationFrame(()=>{fe.view.resize()}),g()){let Ie=0,Je=null;fe.view.addSignalListener("brush",(xt,Et)=>{if(Date.now()-Ie<1e3||!Et||Object.keys(Et).length===0)return;clearTimeout(Je);const Ye=Et[Object.keys(Et)[0]];!Ye||Ye.length!==2||(Je=setTimeout(()=>{Ie=Date.now(),g()(Ye)},250))})}}catch(fe){console.error("Vega render error:",fe)}}async function V(){if(!m(w)||!n()||n().length===0||!i())return;const oe=he();m(k)&&oe===M&&Ce()||await le()}function q(){if(!n()||n().length===0)return;const oe=n().filter(At=>At.data_type==="original"||!At.data_type);if(oe.length===0)return;const fe=Object.keys(oe[0]).filter(At=>At!=="data_type"),Ie=fe.map(At=>/[,"]/.test(At)?`"${At.replace(/"/g,'""')}"`:At).join(","),Je=oe.map(At=>fe.map(It=>{const et=At[It];return et==null?"":typeof et=="string"&&(et.includes(",")||et.includes('"'))?`"${et.replace(/"/g,'""')}"`:et}).join(",")),xt=[Ie,...Je].join(` +`),Et=new Blob([xt],{type:"text/csv"}),Ye=URL.createObjectURL(Et),ut=document.createElement("a");ut.href=Ye,ut.download=`${(i()||"data").replace(/\//g,"_")}.csv`,document.body.appendChild(ut),ut.click(),document.body.removeChild(ut),URL.revokeObjectURL(Ye)}async function B(){if(m(k))try{const oe=await m(k).toImageURL("png",4),fe=document.createElement("a");fe.href=oe,fe.download=`${(i()||"chart").replace(/\//g,"_")}.png`,document.body.appendChild(fe),fe.click(),document.body.removeChild(fe)}catch(oe){console.error("Failed to export image:",oe)}}function Q(oe){if(!oe)return Promise.reject(new Error("no element"));const fe=oe.requestFullscreen||oe.webkitRequestFullscreen||oe.mozRequestFullScreen||oe.msRequestFullscreen;return fe?fe.call(oe):Promise.reject(new Error("no fullscreen"))}function X(){const oe=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen||document.msExitFullscreen;return oe?oe.call(document):Promise.resolve()}function j(oe){const fe=document.getElementById("vg-tooltip-element");fe&&oe&&fe.parentElement!==oe&&oe.appendChild(fe)}async function re(){var oe;F(C,!0),document.body.style.overflow="hidden",await Mi(),await Mi();try{await Q(m(E)),await Mi(),j(m(E)),(oe=m(k))==null||oe.resize()}catch{document.body.style.overflow="",F(C,!1)}}async function Me(){try{await X()}catch{}document.body.style.overflow="",F(C,!1),j(document.body)}async function K(){m(C)?await Me():await re()}function Z(){const oe=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;!oe&&m(C)&&(document.body.style.overflow="",F(C,!1),j(document.body)),oe&&m(C)&&Mi().then(()=>{var fe;return(fe=m(k))==null?void 0:fe.resize()})}function te(oe){oe.key==="Escape"&&m(C)&&Me()}Lt(()=>{n(),i(),r(),m(L),m(ce),h(),p(),d(),m(C),m(w),V()}),Lt(()=>{if(!m(w))return;const oe=new ResizeObserver(()=>{queueMicrotask(()=>{var fe;(fe=m(k))==null||fe.resize()})});return oe.observe(m(w)),()=>oe.disconnect()}),mh(()=>(document.addEventListener("fullscreenchange",Z),document.addEventListener("webkitfullscreenchange",Z),document.addEventListener("mozfullscreenchange",Z),document.addEventListener("MSFullscreenChange",Z),()=>{document.removeEventListener("fullscreenchange",Z),document.removeEventListener("webkitfullscreenchange",Z),document.removeEventListener("mozfullscreenchange",Z),document.removeEventListener("MSFullscreenChange",Z),m(k)&&m(k).finalize(),document.body.style.overflow=""}));function _e(oe){b()&&b()(oe)}var ee=xke();_n("keydown",Dd,te);var ge=ct(ee);let ve;var $e=S(ge),Xe=S($e),Re=D(Xe,2),je=D(Re,2),Ze=D($e,2);{var Ke=oe=>{var fe=ike();R(oe,fe)};ue(Ze,oe=>{y()&&oe(Ke)})}var Qe=D(Ze,2);{var nt=oe=>{var fe=dke(),Ie=ct(fe);{var Je=vt=>{var Dt=ske(),kt=S(Dt);me(()=>ae(kt,d())),R(vt,Dt)};ue(Ie,vt=>{d()&&vt(Je)})}var xt=D(Ie,2),Et=S(xt);es(Et,vt=>F(w,vt),()=>m(w));var Ye=D(Et,2);{var ut=vt=>{var Dt=ake();Ne("click",Dt,kt=>{kt.stopPropagation(),v()()}),R(vt,Dt)};ue(Ye,vt=>{h()&&v()&&vt(ut)})}var At=D(xt,2);{var It=vt=>{var Dt=uke(),kt=S(Dt);gt(kt,17,()=>m(H),bt,(lt,Nt)=>{var ne=oke(),Ae=S(ne),St=D(Ae,2),Ot=S(St);me(()=>{al(Ae,`background: ${m(Nt).color??""}`),ae(Ot,m(Nt).name)}),R(lt,ne)});var mn=D(kt,2);{var vn=lt=>{var Nt=lke(),ne=S(Nt);me(()=>ae(ne,m(U)?"Show less":`+${m($).length-W} more`)),Ne("click",Nt,Ae=>{Ae.stopPropagation(),F(U,!m(U))}),R(lt,Nt)};ue(mn,lt=>{m($).length>W&<(vn)})}R(vt,Dt)};ue(At,vt=>{m($).length>0&&vt(It)})}var et=D(At,2);{var mt=vt=>{var Dt=fke(),kt=S(Dt),mn=S(kt),vn=D(kt,2);gt(vn,17,()=>m(J),bt,(lt,Nt)=>{var ne=cke(),Ae=S(ne),St=S(Ae),Ot=D(Ae,2),rt=S(Ot);me(at=>{pt(St,"stroke-dasharray",at),ae(rt,m(Nt).name)},[()=>m(Nt).pattern.join(" ")]),R(lt,ne)}),me(()=>ae(mn,m(I))),R(vt,Dt)};ue(et,vt=>{m(J).length>0&&vt(mt)})}R(oe,fe)};ue(Qe,oe=>{m(C)||oe(nt)})}es(ge,oe=>F(A,oe),()=>m(A));var Ge=D(ge,2);{var qe=oe=>{var fe=_ke(),Ie=S(fe),Je=S(Ie),xt=D(Je,2),Et=D(xt,2),Ye=D(Ie,2);{var ut=lt=>{var Nt=hke(),ne=S(Nt);me(()=>ae(ne,d())),R(lt,Nt)};ue(Ye,lt=>{d()&<(ut)})}var At=D(Ye,2),It=S(At),et=S(It);es(et,lt=>F(w,lt),()=>m(w));var mt=D(et,2);{var vt=lt=>{var Nt=pke();Ne("click",Nt,ne=>{ne.stopPropagation(),v()()}),R(lt,Nt)};ue(mt,lt=>{h()&&v()&<(vt)})}var Dt=D(At,2);{var kt=lt=>{var Nt=vke(),ne=S(Nt);gt(ne,17,()=>m(G),bt,(Ot,rt)=>{var at=gke(),Mt=S(at),jn=D(Mt,2),yn=S(jn);me(()=>{al(Mt,`background: ${m(rt).color??""}`),ae(yn,m(rt).name)}),R(Ot,at)});var Ae=D(ne,2);{var St=Ot=>{var rt=mke(),at=S(rt);me(()=>ae(at,m(O)?"Show less":`+${m($).length-W} more`)),Ne("click",rt,Mt=>{Mt.stopPropagation(),F(O,!m(O))}),R(Ot,rt)};ue(Ae,Ot=>{m($).length>W&&Ot(St)})}R(lt,Nt)};ue(Dt,lt=>{m($).length>0&<(kt)})}var mn=D(Dt,2);{var vn=lt=>{var Nt=bke(),ne=S(Nt),Ae=S(ne),St=D(ne,2);gt(St,17,()=>m(J),bt,(Ot,rt)=>{var at=yke(),Mt=S(at),jn=S(Mt),yn=D(Mt,2),wi=S(yn);me(Un=>{pt(jn,"stroke-dasharray",Un),ae(wi,m(rt).name)},[()=>m(rt).pattern.join(" ")]),R(Ot,at)}),me(()=>ae(Ae,m(I))),R(lt,Nt)};ue(mn,lt=>{m(J).length>0&<(vn)})}es(fe,lt=>F(E,lt),()=>m(E)),Ne("click",Je,q),Ne("click",xt,B),Ne("click",Et,()=>Me()),R(oe,fe)};ue(Ge,oe=>{m(C)&&oe(qe)})}me(()=>{ve=qt(ge,1,"plot-container svelte-9thu1j",null,ve,{"hidden-plot":m(C)}),pt(ge,"draggable",y()?"true":void 0)}),_n("dragstart",ge,function(...oe){var fe;(fe=y()?_e:void 0)==null||fe.apply(this,oe)}),_n("dragover",ge,function(...oe){var fe;(fe=y()?_():void 0)==null||fe.apply(this,oe)}),_n("drop",ge,function(...oe){var fe;(fe=y()?x():void 0)==null||fe.apply(this,oe)}),Ne("click",Xe,q),Ne("click",Re,B),Ne("click",je,K),R(e,ee),un()}or(["click"]);var wke=z('
      '),Eke=z('
      '),Ake=z(' '),kke=z(''),Ske=z('
      '),Cke=z('
      ',1),$ke=z('
      '),Fke=z(' '),Dke=z(''),Mke=z('
      '),Tke=z(`
      `),Rke=z(`
      `,1);function vT(e,t){ln(t,!0);let n=se(t,"data",19,()=>[]),r=se(t,"y",3,""),i=se(t,"colorField",3,"run"),s=se(t,"colorDisplayField",3,""),a=se(t,"colorMap",19,()=>({})),o=se(t,"title",3,""),l=se(t,"draggable",3,!1),u=se(t,"ondragstart",3,null),c=se(t,"ondragover",3,null),f=se(t,"ondrop",3,null),d=ie(null),h=ie(null),p=ie(null),g=ie(null),v=ie(!1),y=ke(()=>{if(!i()||!n()||n().length===0)return[];const X=new Set,j=[];for(const re of n()){const Me=re[i()];Me&&!X.has(Me)&&(X.add(Me),j.push({key:Me,name:re[s()]||Me,color:a()[Me]||"#999"}))}return j}),b=ke(()=>qR(n(),i(),a()));const _=6;let x=ie(!1),w=ie(!1),A=ke(()=>m(x)||m(y).length<=_?m(y):m(y).slice(0,_)),E=ke(()=>m(w)||m(y).length<=_?m(y):m(y).slice(0,_));function k(){const X=new Map;for(const j of n()){if(j.data_type==="smoothed")continue;const re=j[i()];re&&j[r()]!=null&&X.set(re,{key:re,label:j[s()]||re,value:j[r()]})}return Array.from(X.values())}function C(X,j){return getComputedStyle(document.documentElement).getPropertyValue(X).trim()||j}function M(X){const j=X.map(Z=>Z.key),re=j.map(Z=>a()[Z]||"#999"),Me=Object.fromEntries(X.map(Z=>[Z.key,Z.label])),K=r().includes("/")?r().split("/").pop():r();return{$schema:"https://vega.github.io/schema/vega-lite/v5.json",width:"container",height:m(v)?"container":250,autosize:{type:"fit",contains:"padding"},data:{values:X},mark:{type:"bar",cornerRadiusTopLeft:3,cornerRadiusTopRight:3},encoding:{x:{field:"key",type:"nominal",sort:j,axis:{labelAngle:j.length>4?-45:0,labelLimit:120,labelExpr:`${JSON.stringify(Me)}[datum.value] || datum.value`},title:null},y:{field:"value",type:"quantitative",title:K,scale:{zero:!0}},color:{field:"key",type:"nominal",scale:{domain:j,range:re},legend:null},tooltip:[{field:"label",type:"nominal",title:"Run"},{field:"value",type:"quantitative",title:K}]},config:{background:"transparent",axis:{labelColor:C("--body-text-color-subdued","#6b7280"),titleColor:C("--body-text-color","#374151"),gridColor:C("--border-color-primary","#f3f4f6")},view:{stroke:"transparent"}}}}async function N(){if(await Mi(),!m(d)||!n()||n().length===0||!r())return;const X=k();if(X.length===0)return;const j=M(X);try{m(g)&&(m(g).finalize(),F(g,null));const re=await Gq(m(d),j,{actions:!1,renderer:"canvas"});F(g,re.view,!0),requestAnimationFrame(()=>{re.view.resize()})}catch(re){console.error("Vega render error:",re)}}function P(){const X=k();if(X.length===0)return;const re="run,"+(/[,"]/.test(r())?`"${r().replace(/"/g,'""')}"`:r()),Me=X.map(ee=>`${typeof ee.label=="string"&&(ee.label.includes(",")||ee.label.includes('"'))?`"${ee.label.replace(/"/g,'""')}"`:ee.label},${ee.value}`),K=[re,...Me].join(` +`),Z=new Blob([K],{type:"text/csv"}),te=URL.createObjectURL(Z),_e=document.createElement("a");_e.href=te,_e.download=`${(r()||"data").replace(/\//g,"_")}.csv`,document.body.appendChild(_e),_e.click(),document.body.removeChild(_e),URL.revokeObjectURL(te)}async function I(){if(m(g))try{const X=await m(g).toImageURL("png",4),j=document.createElement("a");j.href=X,j.download=`${(r()||"chart").replace(/\//g,"_")}.png`,document.body.appendChild(j),j.click(),document.body.removeChild(j)}catch(X){console.error("Failed to export image:",X)}}function T(X){if(!X)return Promise.reject(new Error("no element"));const j=X.requestFullscreen||X.webkitRequestFullscreen||X.mozRequestFullScreen||X.msRequestFullscreen;return j?j.call(X):Promise.reject(new Error("no fullscreen"))}function $(){const X=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen||document.msExitFullscreen;return X?X.call(document):Promise.resolve()}function L(X){const j=document.getElementById("vg-tooltip-element");j&&X&&j.parentElement!==X&&X.appendChild(j)}async function W(){var X;F(v,!0),document.body.style.overflow="hidden",await Mi(),await Mi();try{await T(m(p)),await Mi(),L(m(p)),(X=m(g))==null||X.resize()}catch{document.body.style.overflow="",F(v,!1)}}async function U(){try{await $()}catch{}document.body.style.overflow="",F(v,!1),L(document.body)}async function O(){m(v)?await U():await W()}function H(){const X=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;!X&&m(v)&&(document.body.style.overflow="",F(v,!1),L(document.body)),X&&m(v)&&Mi().then(()=>{var j;return(j=m(g))==null?void 0:j.resize()})}function G(X){X.key==="Escape"&&m(v)&&U()}Lt(()=>{n(),r(),m(b),o(),m(v),m(d),N()}),Lt(()=>{if(!m(d))return;const X=new ResizeObserver(()=>{queueMicrotask(()=>{var j;(j=m(g))==null||j.resize()})});return X.observe(m(d)),()=>X.disconnect()}),mh(()=>(document.addEventListener("fullscreenchange",H),document.addEventListener("webkitfullscreenchange",H),document.addEventListener("mozfullscreenchange",H),document.addEventListener("MSFullscreenChange",H),()=>{document.removeEventListener("fullscreenchange",H),document.removeEventListener("webkitfullscreenchange",H),document.removeEventListener("mozfullscreenchange",H),document.removeEventListener("MSFullscreenChange",H),m(g)&&m(g).finalize(),document.body.style.overflow=""}));function J(X){u()&&u()(X)}var ce=Rke();_n("keydown",Dd,G);var xe=ct(ce);let be;var Le=S(xe),tt=S(Le),he=D(tt,2),Y=D(he,2),Ce=D(Le,2);{var le=X=>{var j=wke();R(X,j)};ue(Ce,X=>{l()&&X(le)})}var V=D(Ce,2);{var q=X=>{var j=Cke(),re=ct(j);{var Me=ee=>{var ge=Eke(),ve=S(ge);me(()=>ae(ve,o())),R(ee,ge)};ue(re,ee=>{o()&&ee(Me)})}var K=D(re,2),Z=S(K);es(Z,ee=>F(d,ee),()=>m(d));var te=D(K,2);{var _e=ee=>{var ge=Ske(),ve=S(ge);gt(ve,17,()=>m(A),bt,(Re,je)=>{var Ze=Ake(),Ke=S(Ze),Qe=D(Ke,2),nt=S(Qe);me(()=>{al(Ke,`background: ${m(je).color??""}`),ae(nt,m(je).name)}),R(Re,Ze)});var $e=D(ve,2);{var Xe=Re=>{var je=kke(),Ze=S(je);me(()=>ae(Ze,m(x)?"Show less":`+${m(y).length-_} more`)),Ne("click",je,Ke=>{Ke.stopPropagation(),F(x,!m(x))}),R(Re,je)};ue($e,Re=>{m(y).length>_&&Re(Xe)})}R(ee,ge)};ue(te,ee=>{m(y).length>0&&ee(_e)})}R(X,j)};ue(V,X=>{m(v)||X(q)})}es(xe,X=>F(h,X),()=>m(h));var B=D(xe,2);{var Q=X=>{var j=Tke(),re=S(j),Me=S(re),K=D(Me,2),Z=D(K,2),te=D(re,2);{var _e=Re=>{var je=$ke(),Ze=S(je);me(()=>ae(Ze,o())),R(Re,je)};ue(te,Re=>{o()&&Re(_e)})}var ee=D(te,2),ge=S(ee),ve=S(ge);es(ve,Re=>F(d,Re),()=>m(d));var $e=D(ee,2);{var Xe=Re=>{var je=Mke(),Ze=S(je);gt(Ze,17,()=>m(E),bt,(nt,Ge)=>{var qe=Fke(),oe=S(qe),fe=D(oe,2),Ie=S(fe);me(()=>{al(oe,`background: ${m(Ge).color??""}`),ae(Ie,m(Ge).name)}),R(nt,qe)});var Ke=D(Ze,2);{var Qe=nt=>{var Ge=Dke(),qe=S(Ge);me(()=>ae(qe,m(w)?"Show less":`+${m(y).length-_} more`)),Ne("click",Ge,oe=>{oe.stopPropagation(),F(w,!m(w))}),R(nt,Ge)};ue(Ke,nt=>{m(y).length>_&&nt(Qe)})}R(Re,je)};ue($e,Re=>{m(y).length>0&&Re(Xe)})}es(j,Re=>F(p,Re),()=>m(p)),Ne("click",Me,P),Ne("click",K,I),Ne("click",Z,()=>U()),R(X,j)};ue(B,X=>{m(v)&&X(Q)})}me(()=>{be=qt(xe,1,"plot-container bar-plot svelte-1swghqy",null,be,{"hidden-plot":m(v)}),pt(xe,"draggable",l()?"true":void 0)}),_n("dragstart",xe,function(...X){var j;(j=l()?J:void 0)==null||j.apply(this,X)}),_n("dragover",xe,function(...X){var j;(j=l()?c():void 0)==null||j.apply(this,X)}),_n("drop",xe,function(...X){var j;(j=l()?f():void 0)==null||j.apply(this,X)}),Ne("click",tt,P),Ne("click",he,I),Ne("click",Y,O),R(e,ce),un()}or(["click"]);var Nke=z('
      '),Oke=z('
      '),Lke=z('
      ');function gd(e,t){ln(t,!0);let n=se(t,"label",3,""),r=se(t,"open",15,!0),i=se(t,"hidden",3,!1);function s(){r(!r())}var a=Mn(),o=ct(a);{var l=c=>{var f=Nke(),d=S(f);{var h=p=>{var g=Mn(),v=ct(g);gF(v,()=>t.children),R(p,g)};ue(d,p=>{t.children&&p(h)})}R(c,f)},u=c=>{var f=Lke(),d=S(f),h=S(d);let p;var g=D(h,2),v=S(g),y=D(d,2);{var b=_=>{var x=Oke(),w=S(x);{var A=E=>{var k=Mn(),C=ct(k);gF(C,()=>t.children),R(E,k)};ue(w,E=>{t.children&&E(A)})}R(_,x)};ue(y,_=>{r()&&_(b)})}me(()=>{p=qt(h,1,"arrow svelte-1jep0a",null,p,{rotated:r()}),ae(v,n())}),Ne("click",d,s),R(c,f)};ue(o,c=>{i()?c(l):c(u,-1)})}R(e,a),un()}or(["click"]);$H();const Yq="trackio_theme_preference";let P1=[];function Ike(e){return P1.push(e),()=>{P1=P1.filter(t=>t!==e)}}function Pke(){const e=X5();P1.forEach(t=>t(e))}const yT={"--neutral-50":"#fafafa","--neutral-100":"#f4f4f5","--neutral-200":"#e4e4e7","--neutral-300":"#d4d4d8","--neutral-400":"#bbbbc2","--neutral-500":"#71717a","--neutral-600":"#52525b","--neutral-700":"#3f3f46","--neutral-800":"#27272a","--neutral-900":"#18181b","--neutral-950":"#0f0f11","--background-fill-primary":"#0f0f11","--background-fill-secondary":"#18181b","--body-text-color":"#f4f4f5","--body-text-color-subdued":"#bbbbc2","--border-color-primary":"#3f3f46","--color-accent":"#f97316","--color-accent-soft":"#3f3f46","--input-background-fill":"#27272a","--input-background-fill-focus":"#f97316","--input-border-color":"#3f3f46","--input-border-color-focus":"#3f3f46","--input-placeholder-color":"#71717a","--input-shadow":"none","--input-shadow-focus":"none","--checkbox-background-color":"#27272a","--checkbox-background-color-focus":"#27272a","--checkbox-background-color-hover":"#27272a","--checkbox-background-color-selected":"#f97316","--checkbox-border-color":"#3f3f46","--checkbox-border-color-focus":"#f97316","--checkbox-border-color-hover":"#52525b","--checkbox-border-color-selected":"#f97316","--table-even-background-fill":"#0f0f11","--table-odd-background-fill":"#18181b","--slider-color":"#f97316","--shadow-drop":"rgba(0,0,0,0.15) 0px 1px 2px 0px","--shadow-drop-lg":"0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.2)","--shadow-inset":"rgba(0,0,0,0.15) 0px 2px 4px 0px inset","--block-title-text-color":"#bbbbc2","--block-info-text-color":"#71717a","--primary-50":"#3f3f46"};function hg(e){const t=document.documentElement;e==="dark"?(t.dataset.theme="dark",Object.entries(yT).forEach(([n,r])=>{t.style.setProperty(n,r)})):(delete t.dataset.theme,Object.keys(yT).forEach(n=>{t.style.removeProperty(n)})),Pke()}function X5(){return document.documentElement.dataset.theme==="dark"}function K5(){return window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"default"}function Z5(){return localStorage.getItem(Yq)||"system"}function Bke(e){localStorage.setItem(Yq,e),Vq(e),Xq(e==="system")}function Vq(e){hg(e==="system"?K5():e==="dark"?"dark":"default")}let Zm=!1;function bT(){Z5()==="system"&&hg(K5())}function Xq(e){const t=window.matchMedia("(prefers-color-scheme: dark)");e&&!Zm?(t.addEventListener("change",bT),Zm=!0):!e&&Zm&&(t.removeEventListener("change",bT),Zm=!1)}function zke(){const e=new URLSearchParams(window.location.search).get("__theme");if(e){hg(e);return}const t=Z5();Vq(t),Xq(t==="system")}var jke=z('
      Loading
      ');function Pu(e,t){ln(t,!1);const r=X5()||new URLSearchParams(window.location.search).get("__theme")==="dark"||K5()==="dark"?"/static/trackio/trackio_logo_dark.png":"/static/trackio/trackio_logo_light.png";TG();var i=jke(),s=S(i),a=S(s),o=S(a),l=D(a,2),u=S(l);me(()=>{pt(o,"src",r),pt(u,"src",r)}),R(e,i),un()}const _T=["BOOLEAN","INT32","INT64","INT96","FLOAT","DOUBLE","BYTE_ARRAY","FIXED_LEN_BYTE_ARRAY"],lc=["PLAIN","GROUP_VAR_INT","PLAIN_DICTIONARY","RLE","BIT_PACKED","DELTA_BINARY_PACKED","DELTA_LENGTH_BYTE_ARRAY","DELTA_BYTE_ARRAY","RLE_DICTIONARY","BYTE_STREAM_SPLIT"],Uke=["REQUIRED","OPTIONAL","REPEATED"],qke=["UTF8","MAP","MAP_KEY_VALUE","LIST","ENUM","DECIMAL","DATE","TIME_MILLIS","TIME_MICROS","TIMESTAMP_MILLIS","TIMESTAMP_MICROS","UINT_8","UINT_16","UINT_32","UINT_64","INT_8","INT_16","INT_32","INT_64","JSON","BSON","INTERVAL"],Wke=["UNCOMPRESSED","SNAPPY","GZIP","LZO","BROTLI","LZ4","ZSTD","LZ4_RAW"],Kq=["DATA_PAGE","INDEX_PAGE","DICTIONARY_PAGE","DATA_PAGE_V2"],Hke=["SPHERICAL","VINCENTY","THOMAS","ANDOYER","KARNEY"];function ZA(e){const t=Jm(e);if(t.type===1)return{type:"Point",coordinates:JA(e,t)};if(t.type===2)return{type:"LineString",coordinates:QA(e,t)};if(t.type===3)return{type:"Polygon",coordinates:xT(e,t)};if(t.type===4){const n=[];for(let r=0;r1&&i<=7&&(a=t.getUint32(e.offset,n),e.offset+=4);let o=2;return s&&o++,s===3&&o++,{littleEndian:n,type:i,dim:o,count:a}}function JA(e,t){const n=[];for(let r=0;r{var d;return((d=f.element.logical_type)==null?void 0:d.type)==="VARIANT"}))&&a==="BYTE_ARRAY"&&o!=="UTF8"&&(l==null?void 0:l.type)!=="STRING")return e;if(o==="DECIMAL"){const d=10**-(n.scale||0),h=new Array(e.length);for(let p=0;pr.timestampFromNanoseconds(Gke(f)));if(o==="DATE")return Array.from(e).map(f=>r.dateFromDays(f));if(o==="TIMESTAMP_MILLIS")return Array.from(e).map(f=>r.timestampFromMilliseconds(f));if(o==="TIMESTAMP_MICROS")return Array.from(e).map(f=>r.timestampFromMicroseconds(f));if(o==="JSON")return e.map(f=>JSON.parse(Zq.decode(f)));if(o==="BSON")throw new Error("parquet bson not supported");if(o==="INTERVAL")throw new Error("parquet interval not supported");if((l==null?void 0:l.type)==="GEOMETRY")return e.map(f=>r.geometryFromBytes(f));if((l==null?void 0:l.type)==="GEOGRAPHY")return e.map(f=>r.geographyFromBytes(f));if(o==="UTF8"||(l==null?void 0:l.type)==="STRING"||i&&a==="BYTE_ARRAY")return e.map(f=>r.stringFromBytes(f));if(o==="UINT_64"||(l==null?void 0:l.type)==="INTEGER"&&l.bitWidth===64&&!l.isSigned){if(e instanceof BigInt64Array)return new BigUint64Array(e.buffer,e.byteOffset,e.length);const f=u?new Array(e.length):new BigUint64Array(e.length);for(let d=0;d=2n**BigInt(n-1)&&(t-=2n**BigInt(n)),Number(t)}function Gke(e){const t=(e>>64n)-2440588n,n=e&0xffffffffffffffffn;return t*86400000000000n+n}function eW(e){if(!e)return;const t=e[1]<<8|e[0],n=t>>15?-1:1,r=t>>10&31,i=t&1023;return r===0?n*2**-14*(i/1024):r===31?i?NaN:n*(1/0):n*2**(r-15)*(1+i/1024)}function tW(e,t,n){const r=e[t],i=[];let s=1;if(r.num_children)for(;i.lengtha.element.name===i);if(!s)throw new Error(`parquet schema element not found: ${t}`);r.push(s),n=s}return r}function Yke(e){const t=[];function n(r){if(r.children.length)for(const i of r.children)n(i);else t.push(r.path.join("."))}return n(e),t}function rW(e){let t=0;for(const{element:n}of e)n.repetition_type==="REPEATED"&&t++;return t}function J5(e){let t=0;for(const{element:n}of e.slice(1))n.repetition_type!=="REQUIRED"&&t++;return t}function Vke(e){if(!e||e.element.converted_type!=="LIST"||e.children.length>1)return!1;const t=e.children[0];return!(t.children.length>1||t.element.repetition_type!=="REPEATED")}function Xke(e){if(!e||e.element.converted_type!=="MAP"||e.children.length>1)return!1;const t=e.children[0];if(t.children.length!==2||t.element.repetition_type!=="REPEATED")return!1;const n=t.children.find(i=>i.element.name==="key");if((n==null?void 0:n.element.repetition_type)==="REPEATED")return!1;const r=t.children.find(i=>i.element.name==="value");return(r==null?void 0:r.element.repetition_type)!=="REPEATED"}function iW(e){if(e.length!==2)return!1;const[,t]=e;return!(t.element.repetition_type==="REPEATED"||t.children.length)}const Kke=0,ET=1,AT=2,kT=3,Zke=4,Jke=5,Qke=6,eSe=7,tSe=8,nSe=9,rSe=12;function X2(e){const t={};let n=0;for(;e.offset>4;n=s?n+s:sW(e),t[`field_${n}`]=ek(e,i)}return t}function ek(e,t){switch(t){case ET:return!0;case AT:return!1;case kT:return e.view.getInt8(e.offset++);case Zke:case Jke:return sW(e);case Qke:return tk(e);case eSe:{const n=e.view.getFloat64(e.offset,!0);return e.offset+=8,n}case tSe:{const n=Tc(e),r=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,n);return e.offset+=n,r}case nSe:{const n=e.view.getUint8(e.offset++),r=n&15;let i=n>>4;i===15&&(i=Tc(e));const s=r===ET||r===AT,a=new Array(i);for(let o=0;o>>1^-(t&1)}function tk(e){const t=iSe(e);return t>>1n^-(t&1n)}function sSe(e,t){var s,a,o,l,u;const n=new Map,r=(s=t==null?void 0:t.find(({key:c})=>c==="geo"))==null?void 0:s.value,i=(r&&((a=JSON.parse(r))==null?void 0:a.columns))??{};for(const[c,f]of Object.entries(i)){if(f.encoding!=="WKB")continue;const d=f.edges==="spherical"?"GEOGRAPHY":"GEOMETRY",h=((o=f.crs)==null?void 0:o.id)??((u=(l=f.crs)==null?void 0:l.ids)==null?void 0:u[0]),p=h?`${h.authority}:${h.code.toString()}`:void 0;n.set(c,{type:d,crs:p})}for(let c=1;c=0))throw new Error("parquet expected AsyncBuffer");const i=Math.max(0,e.byteLength-n),s=await e.slice(i,e.byteLength),a=new DataView(s);if(a.getUint32(s.byteLength-4,!0)!==827474256)throw new Error("parquet file invalid (footer != PAR1)");const o=a.getUint32(s.byteLength-8,!0);if(o>e.byteLength-8)throw new Error(`parquet metadata length ${o} exceeds available buffer ${e.byteLength-8}`);if(o+8>n){const l=e.byteLength-o-8,u=await e.slice(l,i),c=new ArrayBuffer(o+8),f=new Uint8Array(c);return f.set(new Uint8Array(u)),f.set(new Uint8Array(s),i-l),ST(c,{parsers:t,geoparquet:r})}else return ST(s,{parsers:t,geoparquet:r})}function ST(e,{parsers:t,geoparquet:n=!0}={}){var v;if(!(e instanceof ArrayBuffer))throw new Error("parquet expected ArrayBuffer");const r=new DataView(e);if(t={...V2,...t},r.byteLength<8)throw new Error("parquet file is too short");if(r.getUint32(r.byteLength-4,!0)!==827474256)throw new Error("parquet file invalid (footer != PAR1)");const i=r.byteLength-8,s=r.getUint32(i,!0);if(s>r.byteLength-8)throw new Error(`parquet metadata length ${s} exceeds available buffer ${r.byteLength-8}`);const a=i-s,l=X2({view:r,offset:a}),u=l.field_1,c=l.field_2.map(y=>({type:_T[y.field_1],type_length:y.field_2,repetition_type:Uke[y.field_3],name:La(y.field_4),num_children:y.field_5,converted_type:qke[y.field_6],scale:y.field_7,precision:y.field_8,field_id:y.field_9,logical_type:uSe(y.field_10)})),f=c.filter(y=>y.type),d=l.field_3,h=l.field_4.map(y=>{var b;return{columns:y.field_1.map((_,x)=>{var w,A,E;return{file_path:La(_.field_1),file_offset:_.field_2,meta_data:_.field_3&&{type:_T[_.field_3.field_1],encodings:(w=_.field_3.field_2)==null?void 0:w.map(k=>lc[k]),path_in_schema:_.field_3.field_3.map(La),codec:Wke[_.field_3.field_4],num_values:_.field_3.field_5,total_uncompressed_size:_.field_3.field_6,total_compressed_size:_.field_3.field_7,key_value_metadata:(A=_.field_3.field_8)==null?void 0:A.map(k=>({key:La(k.field_1),value:La(k.field_2)})),data_page_offset:_.field_3.field_9,index_page_offset:_.field_3.field_10,dictionary_page_offset:_.field_3.field_11,statistics:cSe(_.field_3.field_12,f[x],t),encoding_stats:(E=_.field_3.field_13)==null?void 0:E.map(k=>({page_type:Kq[k.field_1],encoding:lc[k.field_2],count:k.field_3})),bloom_filter_offset:_.field_3.field_14,bloom_filter_length:_.field_3.field_15,size_statistics:_.field_3.field_16&&{unencoded_byte_array_data_bytes:_.field_3.field_16.field_1,repetition_level_histogram:_.field_3.field_16.field_2,definition_level_histogram:_.field_3.field_16.field_3},geospatial_statistics:_.field_3.field_17&&{bbox:_.field_3.field_17.field_1&&{xmin:_.field_3.field_17.field_1.field_1,xmax:_.field_3.field_17.field_1.field_2,ymin:_.field_3.field_17.field_1.field_3,ymax:_.field_3.field_17.field_1.field_4,zmin:_.field_3.field_17.field_1.field_5,zmax:_.field_3.field_17.field_1.field_6,mmin:_.field_3.field_17.field_1.field_7,mmax:_.field_3.field_17.field_1.field_8},geospatial_types:_.field_3.field_17.field_2}},offset_index_offset:_.field_4,offset_index_length:_.field_5,column_index_offset:_.field_6,column_index_length:_.field_7,crypto_metadata:_.field_8,encrypted_column_metadata:_.field_9}}),total_byte_size:y.field_2,num_rows:y.field_3,sorting_columns:(b=y.field_4)==null?void 0:b.map(_=>({column_idx:_.field_1,descending:_.field_2,nulls_first:_.field_3})),file_offset:y.field_5,total_compressed_size:y.field_6,ordinal:y.field_7}}),p=(v=l.field_5)==null?void 0:v.map(y=>({key:La(y.field_1),value:La(y.field_2)})),g=La(l.field_6);return n&&sSe(c,p),{version:u,schema:c,num_rows:d,row_groups:h,key_value_metadata:p,created_by:g,metadata_length:s}}function nk({schema:e}){return nW(e,[])[0]}function uSe(e){return e!=null&&e.field_1?{type:"STRING"}:e!=null&&e.field_2?{type:"MAP"}:e!=null&&e.field_3?{type:"LIST"}:e!=null&&e.field_4?{type:"ENUM"}:e!=null&&e.field_5?{type:"DECIMAL",scale:e.field_5.field_1,precision:e.field_5.field_2}:e!=null&&e.field_6?{type:"DATE"}:e!=null&&e.field_7?{type:"TIME",isAdjustedToUTC:e.field_7.field_1,unit:CT(e.field_7.field_2)}:e!=null&&e.field_8?{type:"TIMESTAMP",isAdjustedToUTC:e.field_8.field_1,unit:CT(e.field_8.field_2)}:e!=null&&e.field_10?{type:"INTEGER",bitWidth:e.field_10.field_1,isSigned:e.field_10.field_2}:e!=null&&e.field_11?{type:"NULL"}:e!=null&&e.field_12?{type:"JSON"}:e!=null&&e.field_13?{type:"BSON"}:e!=null&&e.field_14?{type:"UUID"}:e!=null&&e.field_15?{type:"FLOAT16"}:e!=null&&e.field_16?{type:"VARIANT",specification_version:e.field_16.field_1}:e!=null&&e.field_17?{type:"GEOMETRY",crs:La(e.field_17.field_1)}:e!=null&&e.field_18?{type:"GEOGRAPHY",crs:La(e.field_18.field_1),algorithm:Hke[e.field_18.field_2]}:e}function CT(e){if(e.field_1)return"MILLIS";if(e.field_2)return"MICROS";if(e.field_3)return"NANOS";throw new Error("parquet time unit required")}function cSe(e,t,n){return e&&{max:Qm(e.field_1,t,n),min:Qm(e.field_2,t,n),null_count:e.field_3,distinct_count:e.field_4,max_value:Qm(e.field_5,t,n),min_value:Qm(e.field_6,t,n),is_max_value_exact:e.field_7,is_min_value_exact:e.field_8}}function Qm(e,t,n){const{type:r,converted_type:i,logical_type:s}=t;if(e===void 0)return e;if(r==="BOOLEAN")return e[0]===1;if(r==="BYTE_ARRAY")return n.stringFromBytes(e);const a=new DataView(e.buffer,e.byteOffset,e.byteLength);return r==="FLOAT"&&a.byteLength===4?a.getFloat32(0,!0):r==="DOUBLE"&&a.byteLength===8?a.getFloat64(0,!0):r==="INT32"&&i==="DATE"?n.dateFromDays(a.getInt32(0,!0)):r==="INT64"&&i==="TIMESTAMP_MILLIS"?n.timestampFromMilliseconds(a.getBigInt64(0,!0)):r==="INT64"&&i==="TIMESTAMP_MICROS"?n.timestampFromMicroseconds(a.getBigInt64(0,!0)):r==="INT64"&&(s==null?void 0:s.type)==="TIMESTAMP"&&(s==null?void 0:s.unit)==="NANOS"?n.timestampFromNanoseconds(a.getBigInt64(0,!0)):r==="INT64"&&(s==null?void 0:s.type)==="TIMESTAMP"&&(s==null?void 0:s.unit)==="MICROS"?n.timestampFromMicroseconds(a.getBigInt64(0,!0)):r==="INT64"&&(s==null?void 0:s.type)==="TIMESTAMP"?n.timestampFromMilliseconds(a.getBigInt64(0,!0)):r==="INT32"&&a.byteLength===4?a.getInt32(0,!0):r==="INT64"&&a.byteLength===8?a.getBigInt64(0,!0):i==="DECIMAL"?Qq(e)*10**-(t.scale||0):(s==null?void 0:s.type)==="FLOAT16"?eW(e):e}function fSe(e){const t=X2(e);return{page_locations:t.field_1.map(dSe),unencoded_byte_array_data_bytes:t.field_2}}function dSe(e){return{offset:e.field_1,compressed_page_size:e.field_2,first_row_index:e.field_3}}function aW(e,t){for(let r=0;rn.split(".")[0])),[...new Set(t)]}function Yp(e,t,n=!0){return"$and"in t&&Array.isArray(t.$and)?t.$and.every(r=>Yp(e,r,n)):"$or"in t&&Array.isArray(t.$or)?t.$or.some(r=>Yp(e,r,n)):"$nor"in t&&Array.isArray(t.$nor)?!t.$nor.some(r=>Yp(e,r,n)):Object.entries(t).every(([r,i])=>{const s=hSe(e,r);return typeof i!="object"||i===null||Array.isArray(i)?sl(s,i,n):Object.entries(i||{}).every(([a,o])=>a==="$gt"?s>o:a==="$gte"?s>=o:a==="$lt"?srk({rowGroup:e,physicalColumns:t,filter:s,strict:r}));if("$or"in n&&Array.isArray(n.$or))return n.$or.every(s=>rk({rowGroup:e,physicalColumns:t,filter:s,strict:r}));if("$nor"in n&&Array.isArray(n.$nor))return!1;for(const[s,a]of Object.entries(n)){const o=t.indexOf(s);if(o===-1)continue;const l=(i=e.columns[o].meta_data)==null?void 0:i.statistics;if(!l)continue;const{min:u,max:c,min_value:f,max_value:d}=l,h=f!==void 0?f:u,p=d!==void 0?d:c;if(!(h===void 0||p===void 0)){for(const[g,v]of Object.entries(a||{}))if(g==="$gt"&&p<=v||g==="$gte"&&p=v||g==="$lte"&&h>v||g==="$eq"&&(vp)||g==="$ne"&&sl(h,p,r)&&sl(h,v,r)||g==="$in"&&Array.isArray(v)&&v.every(y=>yp)||g==="$nin"&&Array.isArray(v)&&sl(h,p,r)&&v.includes(h))return!0}}return!1}function hSe(e,t){let n=e;for(const r of t.split("."))n=n==null?void 0:n[r];return n}const pSe=1<<21;function gSe({metadata:e,rowStart:t=0,rowEnd:n=1/0,columns:r,filter:i,filterStrict:s=!0,useOffsetIndex:a=!1}){if(!e)throw new Error("parquetPlan requires metadata");const o=[],l=[],u=[],c=Yke(nk(e));let f=0;for(const d of e.row_groups){const h=Number(d.num_rows),p=f+h;if(h>0&&p>t&&fe.slice(r,i));return{byteLength:e.byteLength,slice(r,i=e.byteLength){const s=t.findIndex(({startByte:a,endByte:o})=>a<=r&&i<=o);if(s<0)return e.slice(r,i);if(t[s].startByte!==r||t[s].endByte!==i){const a=r-t[s].startByte,o=i-t[s].startByte;return n[s]instanceof Promise?n[s].then(l=>l.slice(a,o)):n[s].slice(a,o)}else return n[s]}}}const Q5=new TextDecoder,$T=new WeakMap;function lW(e,t=V2){if(Array.isArray(e))return e.map(n=>lW(n,t));if(typeof e!="object")return e;if("metadata"in e){const n=vSe(e.metadata),r=e.typed_value&&z1(e.typed_value,n,t),i=e.value&&Kg($y(e.value),n,t);return r&&i?{...i,...r}:r??i}return e}function z1(e,t,n){if(e&&typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Uint8Array)){if("typed_value"in e)return z1(e.typed_value,t,n);if("value"in e&&e.value instanceof Uint8Array)return Kg($y(e.value),t,n);const r={};for(const[i,s]of Object.entries(e))r[i]=z1(s,t,n);return r}return e instanceof Uint8Array?Kg($y(e),t,n):Array.isArray(e)?e.map(r=>z1(r,t,n)):e}function $y(e){return{view:new DataView(e.buffer,e.byteOffset,e.byteLength),offset:0}}function vSe(e){let t=$T.get(e.buffer);t||(t=new Map,$T.set(e.buffer,t));const n=`${e.byteOffset}:${e.byteLength}`,r=t.get(n);if(r)return r;const i=$y(e),s=i.view.getUint8(i.offset++),a=s&15;if(a!==1)throw new Error(`parquet unsupported variant metadata version: ${a}`);const o=(s>>4&1)===1,l=(s>>6&3)+1,u=Rc(i,l),c=new Array(u+1);for(let p=0;p>2;if(i===0)return ySe(e,s,n);if(i===2)return bSe(e,s,t,n);if(i===3)return _Se(e,s,t,n);const a=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,s);return e.offset+=s,Q5.decode(a)}function ySe(e,t,n){switch(t){case 0:return null;case 1:return!0;case 2:return!1;case 3:{const r=e.view.getInt8(e.offset);return e.offset+=1,r}case 4:{const r=e.view.getInt16(e.offset,!0);return e.offset+=2,r}case 5:{const r=e.view.getInt32(e.offset,!0);return e.offset+=4,r}case 6:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,r}case 7:{const r=e.view.getFloat64(e.offset,!0);return e.offset+=8,r}case 8:return lw(e,4);case 9:return lw(e,8);case 10:return lw(e,16);case 11:{const r=e.view.getInt32(e.offset,!0);return e.offset+=4,n.dateFromDays(r)}case 12:case 13:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,n.timestampFromMicroseconds(r)}case 14:{const r=e.view.getFloat32(e.offset,!0);return e.offset+=4,r}case 15:return FT(e);case 16:{const r=FT(e);return Q5.decode(r)}case 17:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,r}case 18:case 19:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,n.timestampFromNanoseconds(r)}case 20:{const r=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,16);e.offset+=16;const i=Array.from(r,s=>s.toString(16).padStart(2,"0")).join("");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20)}`}default:throw new Error(`parquet unsupported variant primitive type: ${t}`)}}function bSe(e,t,n,r){const i=(t&3)+1,s=(t>>2&3)+1,o=t>>4&1?Rc(e,4):e.view.getUint8(e.offset++),l=new Array(o);for(let f=0;f>2&1,a=i+1,o=Rc(e,s?4:1),l=new Array(o+1);for(let f=0;fp.repetition_type);let l=0;const u=[e];let c=e,f=0,d=0,h=0;if(n[0])for(;f>h&g;for(h+=d;h>=8;)h-=8n,e.offset++,h&&(v|=BigInt(e.view.getUint8(e.offset))<>>1;wSe(e,o,t,n,s),s+=o}}e.offset=i+r}function wSe(e,t,n,r,i){const s=n+7>>3;let a=0;for(let o=0;o>1<<3;const a=(1<8?(u-=8,l-=8,o>>>=8):l-u>u&a),s--,u+=n);return i}function dW(e,t,n,r){const i=ASe(n,r),s=new Uint8Array(t*i);for(let a=0;a=n)throw new Error("invalid snappy length header");for(;i=n)throw new Error("missing eof marker");if((a&3)===0){let l=(a>>>2)+1;if(l>60){if(i+3>=n)throw new Error("snappy error literal pos + 3 >= inputLength");const u=l-60;l=e[i]+(e[i+1]<<8)+(e[i+2]<<16)+(e[i+3]<<24),l=(l&RSe[u])+1,i+=u}if(i+l>n)throw new Error("snappy error literal exceeds input length");MT(e,i,t,s,l),i+=l,s+=l}else{let l=0;switch(a&3){case 1:o=(a>>>2&7)+4,l=e[i]+(a>>>5<<8),i++;break;case 2:if(n<=i+1)throw new Error("snappy error end of input");o=(a>>>2)+1,l=e[i]+(e[i+1]<<8),i+=2;break;case 3:if(n<=i+3)throw new Error("snappy error end of input");o=(a>>>2)+1,l=e[i]+(e[i+1]<<8)+(e[i+2]<<16)+(e[i+3]<<24),i+=4;break}if(l===0||isNaN(l))throw new Error(`invalid offset ${l} pos ${i} inputLength ${n}`);if(l>s)throw new Error("cannot copy from before start of buffer");MT(t,s-l,t,s,o),s+=o}}if(s!==r)throw new Error("premature end of input")}function OSe(e,t,{type:n,element:r,schemaPath:i}){const s=new DataView(e.buffer,e.byteOffset,e.byteLength),a={view:s,offset:0};let o;const l=LSe(a,t,i),{definitionLevels:u,numNulls:c}=ISe(a,t,i),f=t.num_values-c;if(t.encoding==="PLAIN")o=eF(a,n,f,r.type_length);else if(t.encoding==="PLAIN_DICTIONARY"||t.encoding==="RLE_DICTIONARY"||t.encoding==="RLE"){const d=n==="BOOLEAN"?1:s.getUint8(a.offset++);d?(o=new Array(f),n==="BOOLEAN"?(yu(a,d,o),o=o.map(h=>!!h)):yu(a,d,o,s.byteLength-a.offset)):o=new Uint8Array(f)}else if(t.encoding==="BYTE_STREAM_SPLIT")o=dW(a,f,n,r.type_length);else if(t.encoding==="DELTA_BINARY_PACKED")o=n==="INT32"?new Int32Array(f):new BigInt64Array(f),Zg(a,f,o);else if(t.encoding==="DELTA_LENGTH_BYTE_ARRAY")o=new Array(f),fW(a,f,o);else throw new Error(`parquet unsupported encoding: ${t.encoding}`);return{definitionLevels:u,repetitionLevels:l,dataPage:o}}function LSe(e,t,n){if(n.length>1){const r=rW(n);if(r){const i=new Array(t.num_values);return yu(e,K2(r),i),i}}return[]}function ISe(e,t,n){const r=J5(n);if(!r)return{definitionLevels:[],numNulls:0};const i=new Array(t.num_values);yu(e,K2(r),i);let s=t.num_values;for(const a of i)a===r&&s--;return s===0&&(i.length=0),{definitionLevels:i,numNulls:s}}function ik(e,t,n,r){let i;const s=r==null?void 0:r[n];if(n==="UNCOMPRESSED")i=e;else if(s)i=s(e,t);else if(n==="SNAPPY")i=new Uint8Array(t),NSe(e,i);else throw new Error(`parquet unsupported compression codec: ${n}`);if((i==null?void 0:i.length)!==t)throw new Error(`parquet decompressed page length ${i==null?void 0:i.length} does not match header ${t}`);return i}function PSe(e,t,n){const i={view:new DataView(e.buffer,e.byteOffset,e.byteLength),offset:0},{type:s,element:a,schemaPath:o,codec:l,compressors:u}=n,c=t.data_page_header_v2;if(!c)throw new Error("parquet data page header v2 is undefined");const f=BSe(i,c,o);i.offset=c.repetition_levels_byte_length;const d=zSe(i,c,o),h=t.uncompressed_page_size-c.definition_levels_byte_length-c.repetition_levels_byte_length;let p=e.subarray(i.offset);c.is_compressed!==!1&&(p=ik(p,h,l,u));const g=new DataView(p.buffer,p.byteOffset,p.byteLength),v={view:g,offset:0};let y;const b=c.num_values-c.num_nulls;if(c.encoding==="PLAIN")y=eF(v,s,b,a.type_length);else if(c.encoding==="RLE")y=new Array(b),yu(v,1,y),y=y.map(_=>!!_);else if(c.encoding==="PLAIN_DICTIONARY"||c.encoding==="RLE_DICTIONARY"){const _=g.getUint8(v.offset++);y=new Array(b),yu(v,_,y,h-1)}else if(c.encoding==="DELTA_BINARY_PACKED")y=s==="INT32"?new Int32Array(b):new BigInt64Array(b),Zg(v,b,y);else if(c.encoding==="DELTA_LENGTH_BYTE_ARRAY")y=new Array(b),fW(v,b,y);else if(c.encoding==="DELTA_BYTE_ARRAY")y=new Array(b),xSe(v,b,y);else if(c.encoding==="BYTE_STREAM_SPLIT")y=dW(v,b,s,a.type_length);else throw new Error(`parquet unsupported encoding: ${c.encoding}`);return{definitionLevels:d,repetitionLevels:f,dataPage:y}}function BSe(e,t,n){const r=rW(n);if(!r)return[];const i=new Array(t.num_values);return yu(e,K2(r),i,t.repetition_levels_byte_length),i}function zSe(e,t,n){const r=J5(n);if(r){const i=new Array(t.num_values);return yu(e,K2(r),i,t.definition_levels_byte_length),i}}function TT(e,{groupStart:t,selectStart:n,selectEnd:r},i,s){const{pathInSchema:a,schemaPath:o}=i,l=iW(o),u=[];let c,f,d=0,h=0;const p=s&&(()=>{f&&s({pathInSchema:a,columnData:f,rowStart:t+d-f.length,rowEnd:t+d})});for(;(l?d=e.view.byteLength-1);){const g=jSe(e);if(g.type==="DICTIONARY_PAGE"){const{data:v}=RT(e,g,i,c,void 0,0);v&&(c=Jq(v,i))}else{const v=(f==null?void 0:f.length)||0,y=RT(e,g,i,c,f,n-d);y.skipped?(u.length||(h+=y.skipped),d+=y.skipped):y.data&&f===y.data?d+=y.data.length-v:y.data&&y.data.length&&(p==null||p(),u.push(y.data),d+=y.data.length,f=y.data)}}return p==null||p(),{data:u,skipped:h}}function RT(e,t,n,r,i,s){const{type:a,element:o,schemaPath:l,codec:u,compressors:c}=n,f=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,t.compressed_page_size);if(e.offset+=t.compressed_page_size,t.type==="DATA_PAGE"){const d=t.data_page_header;if(!d)throw new Error("parquet data page header is undefined");if(s>d.num_values&&iW(l))return{skipped:d.num_values};const h=ik(f,Number(t.uncompressed_page_size),u,c),{definitionLevels:p,repetitionLevels:g,dataPage:v}=OSe(h,d,n),y=wT(v,r,d.encoding,n),b=Array.isArray(i)?i:[];return{skipped:0,data:DT(b,p,g,y,l)}}else if(t.type==="DATA_PAGE_V2"){const d=t.data_page_header_v2;if(!d)throw new Error("parquet data page header v2 is undefined");if(s>d.num_rows)return{skipped:d.num_values};const{definitionLevels:h,repetitionLevels:p,dataPage:g}=PSe(f,t,n),v=wT(g,r,d.encoding,n),y=Array.isArray(i)?i:[];return{skipped:0,data:DT(y,h,p,v,l)}}else if(t.type==="DICTIONARY_PAGE"){const d=t.dictionary_page_header;if(!d)throw new Error("parquet dictionary page header is undefined");const h=ik(f,Number(t.uncompressed_page_size),u,c),p={view:new DataView(h.buffer,h.byteOffset,h.byteLength),offset:0};return{skipped:0,data:eF(p,a,d.num_values,o.type_length)}}else throw new Error(`parquet unsupported page type: ${t.type}`)}function jSe(e){const t=X2(e),n=Kq[t.field_1],r=t.field_2,i=t.field_3,s=t.field_4,a=t.field_5&&{num_values:t.field_5.field_1,encoding:lc[t.field_5.field_2],definition_level_encoding:lc[t.field_5.field_3],repetition_level_encoding:lc[t.field_5.field_4],statistics:t.field_5.field_5&&{max:t.field_5.field_5.field_1,min:t.field_5.field_5.field_2,null_count:t.field_5.field_5.field_3,distinct_count:t.field_5.field_5.field_4,max_value:t.field_5.field_5.field_5,min_value:t.field_5.field_5.field_6}},o=t.field_6,l=t.field_7&&{num_values:t.field_7.field_1,encoding:lc[t.field_7.field_2],is_sorted:t.field_7.field_3},u=t.field_8&&{num_values:t.field_8.field_1,num_nulls:t.field_8.field_2,num_rows:t.field_8.field_3,encoding:lc[t.field_8.field_4],definition_levels_byte_length:t.field_8.field_5,repetition_levels_byte_length:t.field_8.field_6,is_compressed:t.field_8.field_7===void 0?!0:t.field_8.field_7,statistics:t.field_8.field_8};return{type:n,uncompressed_page_size:r,compressed_page_size:i,crc:s,data_page_header:a,index_page_header:o,dictionary_page_header:l,data_page_header_v2:u}}function USe(e,{metadata:t},n){const{file:r,compressors:i,utf8:s}=e,a=[],o={...V2,...e.parsers};for(const l of n.chunks){const{columnMetadata:u}=l,c=nW(t.schema,u.path_in_schema),f={pathInSchema:u.path_in_schema,type:u.type,element:c[c.length-1].element,schemaPath:c,codec:u.codec,parsers:o,compressors:i,utf8:s};if(!("offsetIndex"in l)){a.push({pathInSchema:u.path_in_schema,data:Promise.resolve(r.slice(l.range.startByte,l.range.endByte)).then(d=>{const h={view:new DataView(d),offset:0};return TT(h,n,f,e.onPage)})});continue}a.push({pathInSchema:u.path_in_schema,data:Promise.resolve(r.slice(l.offsetIndex.startByte,l.offsetIndex.endByte)).then(async d=>{const h=fSe({view:new DataView(d),offset:0}),{selectStart:p,selectEnd:g}=n,v=h.page_locations;let y=NaN,b=NaN,_=0;for(let C=0;Cp&&(Number.isNaN(y)&&(y=Number(M.offset),_=N),b=Number(M.offset)+M.compressed_page_size)}const x=await r.slice(y,b),w={view:new DataView(x),offset:0},A=_?{...n,groupStart:n.groupStart+_,selectStart:n.selectStart-_,selectEnd:n.selectEnd-_}:n,{data:E,skipped:k}=TT(w,A,f,e.onPage);return{data:E,skipped:_+k}})})}return{groupStart:n.groupStart,groupRows:n.groupRows,asyncColumns:a}}async function NT({asyncColumns:e},t,n,r,i){const s=await Promise.all(e.map(async({data:f})=>{const d=await f;return{...d,data:oW(d.data)}})),a=e.map(f=>f.pathInSchema[0]).filter(f=>!r||r.includes(f)),o=r??a,l=o.map(f=>e.findIndex(d=>d.pathInSchema[0]===f)),u=n-t;if(i==="object"){const f=Array(u);for(let d=0;d=0){const{data:v,skipped:y}=s[g];h[p]=v[d-y]}}c[f]=h}return c}function qSe(e,t,n){const{asyncColumns:r}=e;n={...V2,...n};const i=[];for(const s of t.children)if(s.children.length){const a=r.filter(u=>u.pathInSchema[0]===s.element.name);if(!a.length)continue;const o=new Map,l=Promise.all(a.map(u=>u.data.then(({data:c})=>{o.set(u.pathInSchema.join("."),oW(c))}))).then(()=>{Vp(o,s,n);const u=o.get(s.path.join("."));if(!u)throw new Error("parquet column data not assembled");return{data:[u],skipped:0}});i.push({pathInSchema:s.path,data:l})}else{const a=r.find(o=>o.pathInSchema[0]===s.element.name);a&&i.push(a)}return{...e,asyncColumns:i}}async function WSe(e){e.metadata??(e.metadata=await lSe(e.file,e));const{rowStart:t=0,rowEnd:n,columns:r,onChunk:i,onComplete:s,rowFormat:a,filter:o,filterStrict:l=!0}=e;if(o&&a!=="object")throw new Error('parquet filter requires rowFormat: "object"');const u=B1(o);if(u.length){const v=nk(e.metadata).children.map(b=>b.element.name),y=u.filter(b=>!v.includes(b));if(y.length)throw new Error(`parquet filter columns not found: ${y.join(", ")}`)}let c=r,f=!1;if(r&&o){const v=u.filter(y=>!r.includes(y));v.length&&(c=[...r,...v],f=!0)}const d=c!==r?{...e,columns:c}:e,h=HSe(d);if(!s&&!i){for(const{asyncColumns:v}of h)for(const{data:y}of v)await y;return}const p=nk(e.metadata),g=h.map(v=>qSe(v,p,e.parsers));if(i)for(const v of g)for(const y of v.asyncColumns)y.data.then(({data:b,skipped:_})=>{let x=v.groupStart+_;for(const w of b)i({columnName:y.pathInSchema[0],columnData:w,rowStart:x,rowEnd:x+w.length}),x+=w.length});if(s){const v=[];for(const y of g){const b=Math.max(t-y.groupStart,0),_=Math.min((n??1/0)-y.groupStart,y.groupRows),x=a==="object"?await NT(y,b,_,c,"object"):await NT(y,b,_,r,"array");if(o){for(const w of x)if(Yp(w,o,l)){if(f&&r)for(const A of u)r.includes(A)||delete w[A];v.push(w)}}else aW(v,x)}s(v)}else for(const{asyncColumns:v}of g)for(const{data:y}of v)await y}function HSe(e){if(!e.metadata)throw new Error("parquet requires metadata");const t=gSe(e);return e.file=mSe(e.file,t),t.groups.map(n=>USe(e,t,n))}const e1=new Map;function GSe(e){const t={};for(const n in e){const r=e[n];t[n]=typeof r=="bigint"?Number(r):r}return t}async function tu(e,t={}){if(e1.has(e))return e1.get(e);const n=await fetch(e,{headers:t});if(!n.ok){if(n.status===404)return e1.set(e,[]),[];throw new Error(`Failed to fetch ${e}: ${n.status}`)}const r=await n.arrayBuffer();let i=[];return await WSe({file:r,rowFormat:"object",onComplete:s=>{i=s.map(GSe)}}),e1.set(e,i),i}let Gn=null,t1=null,n1=null,r1=null,i1=null,Wf=null,Hf=null,Ra=null,s1=null;function Ts(e){return Gn.bucket_id?`https://huggingface.co/buckets/${Gn.bucket_id}/resolve/${e}`:`https://huggingface.co/datasets/${Gn.dataset_id}/resolve/main/${e}`}async function YSe(e){Gn=e}function VSe(){return!Gn||Gn.mode!=="static"?null:Gn.bucket_id?{url:`https://huggingface.co/buckets/${Gn.bucket_id}`}:Gn.dataset_id?{url:`https://huggingface.co/datasets/${Gn.dataset_id}`}:null}async function tF(){return t1||(t1=await tu(Ts("metrics.parquet")),t1)}async function hW(){return n1||(n1=await tu(Ts("aux/system_metrics.parquet")),n1)}async function pW(){return r1||(r1=await tu(Ts("aux/configs.parquet")),r1)}async function nF(){return i1||(i1=await tu(Ts("aux/traces.parquet")),i1)}async function J2(){if(Wf)return Wf;const e=await fetch(Ts("runs.json"));return e.ok?(Wf=await e.json(),Wf):(Wf=[],Wf)}let uw=null;function gW(){return uw||(uw=tu(Ts("aux/artifact_versions.parquet")).catch(()=>[])),uw}async function rm(){if(s1)return s1;const[e,t,n,r]=await Promise.all([tu(Ts("aux/artifacts.parquet")).catch(()=>[]),gW(),tu(Ts("aux/artifact_aliases.parquet")).catch(()=>[]),tu(Ts("aux/run_artifact_links.parquet")).catch(()=>[])]);return s1={artifacts:e,versions:t,aliases:n,links:r},s1}async function XSe(){if(Hf)return Hf;const e=await fetch(Ts("settings.json"));return e.ok?(Hf=await e.json(),Hf):(Hf={},Hf)}const im=new Set(["id","run_id","run_name","timestamp","step","log_id","space_id","created_at"]);function sm(e){return!e||e.length===0?{rows:[],columns:[]}:{rows:e,columns:Object.keys(e[0])}}function Q2(e){return e==null?{name:null,id:null}:typeof e=="string"?{name:e,id:null}:{name:e.name??null,id:e.id??null}}function Wh(e,t){const n=Q2(t);return n.id!=null&&e.run_id!=null?e.run_id===n.id:n.name==null?!0:e.run_name===n.name}async function KSe(){return[Gn.project]}async function ZSe(){return(await J2()).map(t=>({id:t.id??t.run_id??t.name,name:t.name,created_at:t.created_at??null,last_step:t.last_step??null,log_count:t.log_count??0}))}async function JSe(e,t){const n=await tF(),{rows:r,columns:i}=sm(n),s=i.filter(l=>!im.has(l)),a=r.filter(l=>Wh(l,t)),o=new Set;for(const l of a)for(const u of s)l[u]!==null&&l[u]!==void 0&&o.add(u);return[...o]}function mW(e){return typeof e=="number"&&Number.isFinite(e)}async function vW(e,t,n={}){const r=await tF(),{rows:i}=sm(r),s=i.filter(o=>Wh(o,t)),a=n.scalar_only===!0;return s.map(o=>{const l={};for(const[u,c]of Object.entries(o))if(!im.has(u)&&c!=null){if(a){mW(c)&&(l[u]=c);continue}if(typeof c=="string"&&c.startsWith("{")&&c.includes("_type"))try{l[u]=JSON.parse(c)}catch{l[u]=c}else l[u]=c}return l.timestamp=o.timestamp,l.step=o.step,l})}function QSe(e){const t=[];function n(r){if(r!=null){if(Array.isArray(r)){r.forEach(n);return}if(typeof r=="object"){Object.values(r).forEach(n);return}t.push(String(r))}}return n(e.messages||[]),n(e.metadata||{}),t.join(" ").toLowerCase()}function e3e(e,t){switch(t){case"step_asc":return[...e].sort((n,r)=>(n.step??0)-(r.step??0));case"step_desc":return[...e].sort((n,r)=>(r.step??0)-(n.step??0));case"request_time_asc":return[...e].sort((n,r)=>String(n.timestamp||"").localeCompare(String(r.timestamp||"")));case"request_time_desc":default:return[...e].sort((n,r)=>String(r.timestamp||"").localeCompare(String(n.timestamp||"")))}}function Fy(e,t){if(e==null)return t;if(typeof e=="string"){if(!e)return t;try{return JSON.parse(e)}catch{return t}}if(typeof e=="object"&&!ArrayBuffer.isView(e)&&!(e instanceof ArrayBuffer))return e;let n;try{const r=e instanceof ArrayBuffer?new Uint8Array(e):new Uint8Array(e.buffer||e);n=new TextDecoder("utf-8").decode(r)}catch{return t}if(!n)return t;try{return JSON.parse(n)}catch{return t}}async function t3e(e,t){const n=await nF(),r=new Map;for(const a of n){if(!Wh(a,t))continue;const o=a.step;r.set(o,(r.get(o)||0)+1)}const i=[...r.entries()].map(([a,o])=>({step:a,count:o})).sort((a,o)=>(a.step??0)-(o.step??0));return{total:i.reduce((a,o)=>a+o.count,0),steps:i}}async function n3e(e,t,n={}){const r=Q2(t);let a=(await nF()).filter(o=>Wh(o,t)).map(o=>{const l={id:o.id,key:o.key,index:o.trace_index,run:o.run_name||r.name,run_id:o.run_id||r.id,step:o.step,timestamp:o.timestamp,messages:Fy(o.messages,[]),metadata:Fy(o.metadata,{})};return l._search_text=(o.search_text||`${l.id} ${l.key} ${QSe(l)}`).toLowerCase(),l});if(n.step!=null&&(a=a.filter(o=>o.step===n.step)),n.search&&n.search.trim()){const o=n.search.trim().toLowerCase();a=a.filter(l=>l._search_text.includes(o))}return a=e3e(a,n.sort||"request_time_desc"),n.offset&&(a=a.slice(n.offset)),n.limit!=null&&(a=a.slice(0,n.limit)),a.map(({_search_text:o,...l})=>l)}async function r3e(){const e=await J2(),t=e.map(n=>n.last_step||0);return{project:Gn.project,num_runs:e.length,runs:e.map(n=>({id:n.id??n.run_id??n.name,name:n.name,created_at:n.created_at??null,last_step:n.last_step??null,log_count:n.log_count??0})),last_activity:t.length?Math.max(...t):null}}async function i3e(e,t){const n=await J2(),r=Q2(t),i=n.find(c=>r.id!=null&&(c.id??c.run_id??c.name)!=null?(c.id??c.run_id??c.name)===r.id:c.name===r.name);if(!i)return{project:Gn.project,run:r.name,run_id:r.id,num_logs:0,metrics:[],config:null,last_step:null};const s=await JSe(Gn.project,t);let a=null;const o=await pW(),{rows:l}=sm(o),u=l.find(c=>r.id!=null&&c.run_id!=null?c.run_id===r.id:c.run_name===r.name);if(u){a={};for(const[c,f]of Object.entries(u))c!=="id"&&c!=="run_name"&&c!=="created_at"&&(a[c]=f)}return{project:Gn.project,run:i.name,run_id:i.id??i.run_id??i.name,num_logs:i.log_count||0,metrics:s,config:a,last_step:i.last_step}}async function s3e(){return[]}async function yW(e,t){const n=await hW(),{rows:r}=sm(n);return r.filter(s=>Wh(s,t)).map(s=>{const a={};for(const[o,l]of Object.entries(s))im.has(o)||l!=null&&(a[o]=l);return a.timestamp=s.timestamp,a})}async function a3e(){const e=await XSe();return{logo_urls:{light:"/static/trackio/trackio_logo_type_light_transparent.png",dark:"/static/trackio/trackio_logo_type_dark_transparent.png"},color_palette:e.color_palette||[],plot_order:e.plot_order||[],table_truncate_length:250}}let a1=null;const o3e=new Set(["trackio.image","trackio.video","trackio.audio","trackio.table"]),l3e=new Set(["trackio.markdown"]);function u3e(e){for(const[t,n]of Object.entries(e))if(!im.has(t)&&n!=null&&mW(n))return!0;return!1}function OT(e,t){for(const[n,r]of Object.entries(e)){if(im.has(n)||r==null)continue;let i=r;if(typeof i=="string"&&i.startsWith("{")&&i.includes("_type"))try{i=JSON.parse(i)}catch{continue}if(i&&typeof i=="object"&&t.has(i._type))return!0}return!1}async function c3e(){if(a1)return a1;const[e,t,n,r,i]=await Promise.all([tF().catch(()=>[]),hW().catch(()=>[]),nF().catch(()=>[]),EW().catch(()=>[]),gW()]),s=e||[];let a=!1,o=!1,l=!1;for(const u of s)if(!a&&u3e(u)&&(a=!0),!o&&OT(u,o3e)&&(o=!0),!l&&OT(u,l3e)&&(l=!0),a&&o&&l)break;return a1={metrics:a,media:o,reports:l,system:(t||[]).length>0,traces:(n||[]).length>0,files:(r||[]).length>0,artifacts:(i||[]).length>0},a1}const f3e=/^v(\d+)$/;function bW(e){const t=new Map;for(const n of e){const r=Number(n.artifact_version_id);t.has(r)||t.set(r,[]),t.get(r).push(n.alias)}return t}function _W(e,t){return String(e.created_at||"").localeCompare(String(t.created_at||""))}async function d3e(){const{artifacts:e,versions:t,aliases:n}=await rm(),r=bW(n),i=new Map;for(const s of t){const a=Number(s.artifact_id);i.has(a)||i.set(a,[]),i.get(a).push({version_id:Number(s.id),version:Number(s.version),aliases:r.get(Number(s.id))||[],size_bytes:Number(s.size_bytes),created_at:s.created_at})}for(const s of i.values())s.sort((a,o)=>o.version-a.version);return[...e].sort((s,a)=>s.type!==a.type?s.type{const a=i.get(Number(s.id))||[];return{name:s.name,type:s.type,description:s.description??null,created_at:s.created_at,num_versions:a.length,latest_version:a.length?a[0].version:null,versions:a}})}async function h3e(e,t,n){const{artifacts:r,versions:i,aliases:s}=await rm(),a=r.find(h=>h.name===t);if(!a)return null;const o=Number(a.id),l=i.filter(h=>Number(h.artifact_id)===o),u=n||"latest",c=f3e.exec(u);let f=null;if(c){const h=Number(c[1]);f=l.find(p=>Number(p.version)===h)||null}else{const h=s.find(p=>Number(p.artifact_id)===o&&p.alias===u);h&&(f=l.find(p=>Number(p.id)===Number(h.artifact_version_id))||null)}if(!f)return null;const d=bW(s);return{artifact_id:o,version_id:Number(f.id),version:Number(f.version),name:a.name,type:a.type,description:a.description??null,manifest:Fy(f.manifest,[]),manifest_digest:f.manifest_digest,metadata:Fy(f.metadata,null),size_bytes:Number(f.size_bytes),producer_run_id:f.producer_run_id??null,producer_run_name:f.producer_run_name??null,created_at:f.created_at,aliases:d.get(Number(f.id))||[]}}async function xW(){const e=await J2(),t=new Set,n=new Map;for(const r of e){const i=r.id??r.run_id??r.name??null;if(i==null)continue;t.add(i);const s=r.name??null;s!=null&&(n.has(s)||n.set(s,new Set),n.get(s).add(i))}return{recordIds:t,ownersByName:n}}function wW(e,{recordIds:t,ownersByName:n}){const r=e.run_id??null;if(r!=null&&t.has(r))return r;const i=n.get(e.run_name??null);return i&&i.size===1?i.values().next().value:null}async function p3e(e,t){const n={input:[],output:[]},r=Q2(t);if(r.name==null&&r.id==null)return n;const{artifacts:i,versions:s,links:a}=await rm(),o=await xW(),l=new Map(s.map(d=>[Number(d.id),d])),u=new Map(i.map(d=>[Number(d.id),d])),c=a.filter(d=>r.id!=null?wW(d,o)===r.id:Wh(d,t)).sort(_W),f=new Set;for(const d of c){const h=l.get(Number(d.artifact_version_id));if(!h)continue;const p=u.get(Number(h.artifact_id));if(!p||!n[d.direction])continue;const g=`${d.direction}:${Number(h.id)}`;f.has(g)||(f.add(g),n[d.direction].push({version_id:Number(h.id),name:p.name,type:p.type,version:Number(h.version),size_bytes:Number(h.size_bytes),created_at:d.created_at}))}return n}async function g3e(){const{links:e}=await rm(),t=await xW(),n=new Map,r=new Map;for(const i of e){const s=wW(i,t),a=i.run_name??null,o=JSON.stringify([s,a]);n.has(o)||(n.set(o,{run_id:s,run_name:a,input:0,output:0}),r.set(o,new Set));const l=r.get(o),u=`${i.direction}:${Number(i.artifact_version_id)}`;if(l.has(u))continue;l.add(u);const c=n.get(o);(i.direction==="input"||i.direction==="output")&&(c[i.direction]+=1)}return[...n.values()]}async function m3e(e,t){const{links:n}=await rm();return n.filter(r=>r.direction==="input"&&Number(r.artifact_version_id)===Number(t)).sort(_W).map(r=>({run_name:r.run_name??null,run_id:r.run_id??null,created_at:r.created_at}))}function v3e(e,t){return Ts(`artifacts/blobs/sha256/${t.slice(0,2)}/${t}`)}async function EW(){if(Ra)return Ra;if(Gn.bucket_id){const r=await fetch(`https://huggingface.co/api/buckets/${Gn.bucket_id}/tree?prefix=media/files/&recursive=true`);if(!r.ok)return Ra=[],Ra;const i=await r.json();return Ra=(Array.isArray(i)?i:[]).filter(s=>s.type==="file").map(s=>({name:s.path.split("/").at(-1)??s.path,path:s.path.slice(6)})),Ra}const e=await fetch(`https://huggingface.co/api/datasets/${Gn.dataset_id}`);if(!e.ok)return Ra=[],Ra;const t=await e.json();return Ra=(Array.isArray(t==null?void 0:t.siblings)?t.siblings:[]).map(r=>r==null?void 0:r.rfilename).filter(r=>typeof r=="string"&&r.startsWith("media/files/")).map(r=>({name:r.split("/").at(-1)??r,path:r.slice(6)})),Ra}async function y3e(){const e=new Set(["id","run_id","run_name","created_at"]),t=await pW().catch(()=>null);if(!t)return{};const{rows:n}=sm(t),r={};for(const i of n){const s=i.run_name;if(!s)continue;const a={};for(const[o,l]of Object.entries(i))e.has(o)||l!=null&&(a[o]=l);r[i.run_id??s]=a}return r}async function b3e(){return{allowed:!1}}async function _3e(){throw new Error("Not supported in static mode")}async function x3e(){throw new Error("Not supported in static mode")}function w3e(e){return Gn.project&&e.startsWith(Gn.project+"/")?e.slice(Gn.project.length+1):e}function AW(e){const t=w3e(e);return Ts(`media/${t}`)}let sk=0;function kW(){return typeof window>"u"?!1:(window.location.hostname||"").toLowerCase().endsWith(".hf.space")}function E3e(){const e=Date.now()+12e3;sk=Math.max(sk,e)}function e_(){return Date.now()(md=e,e))),cw)}function k3e(){const e=sessionStorage.getItem("trackio_oauth_session");return e?{"x-trackio-oauth-session":e}:{}}async function Rn(e,t={}){const n=e.startsWith("/")?e.slice(1):e,r=`${am}/api/${n}`,i=await fetch(r,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...k3e()},body:JSON.stringify(t)});if(i.status===429&&E3e(),!i.ok)throw new Error(`API call ${e} failed: ${i.status}`);const s=await i.json();if(s.error)throw new Error(s.error);return s.data}async function S3e(){return await kn()?KSe():await Rn("/get_all_projects")}async function C3e(e){return await kn()?ZSe():await Rn("/get_runs_for_project",{project:e})}async function $3e(e){return await kn()?y3e():await Rn("/get_run_configs",{project:e})}function hs(e){return e==null?{run:null,run_id:null}:typeof e=="string"?{run:e,run_id:null}:{run:e.name??null,run_id:e.id??null}}async function FW(e,t,n={}){const r={project:e,...hs(t),...n};return await kn()?vW(e,t,n):await Rn("/get_logs",r)}async function F3e(e,t,n={}){if(await kn()){const i=[];for(const s of t){const a=await vW(e,s,n);i.push({...hs(s),logs:a})}return i}const r={project:e,runs:t.map(i=>hs(i)),...n};return await Rn("/get_logs_batch",r)}async function D3e(e,t,n={}){const r={project:e,...hs(t),...n};return await kn()?n3e(e,t,n):await Rn("/get_traces",r)}async function M3e(e,t){const n={project:e,...hs(t)};return await kn()?t3e(e,t):await Rn("/get_trace_steps",n)}async function T3e(e){return await kn()?r3e():await Rn("/get_project_summary",{project:e})}async function DW(e,t){const n={project:e,...hs(t)};return await kn()?i3e(e,t):await Rn("/get_run_summary",n)}async function MW(e,t,n,r){const i={project:e,...hs(t),level:n,since:r};return await kn()?s3e():await Rn("/get_alerts",i)}async function R3e(e,t){const n={project:e,...hs(t)};return await kn()?yW(e,t):await Rn("/get_system_logs",n)}async function LT(e,t){if(await kn()){const n=[];for(const r of t){const i=await yW(e,r);n.push({...hs(r),logs:i})}return n}return await Rn("/get_system_logs_batch",{project:e,runs:t.map(n=>hs(n))})}async function N3e(){return await kn()?a3e():await Rn("/get_settings")}async function O3e(e){return await kn()?EW():await Rn("/get_project_files",{project:e})}async function IT(e){return await kn()?d3e():await Rn("/list_artifacts",{project:e})}async function L3e(e,t,n){return await kn()?h3e(e,t,n):await Rn("/get_artifact_manifest",{project:e,name:t,spec:n})}async function I3e(e,t){const n={project:e,...hs(t)};return await kn()?p3e(e,t):await Rn("/get_run_artifacts",n)}async function P3e(e){return await kn()?g3e():await Rn("/get_run_artifact_counts",{project:e})}async function B3e(e,t){return await kn()?m3e(e,t):await Rn("/get_artifact_consumers",{project:e,version_id:t})}function z3e(e,t){return md?v3e(e,t):`${am}/artifact_blob/${encodeURIComponent(e)}/${encodeURIComponent(t)}`}async function j3e(e){return await kn()?c3e():await Rn("/get_tab_availability",{project:e})}async function U3e(){return await kn()?b3e():await Rn("/get_run_mutation_status",{})}async function q3e(e,t){const n={project:e,...hs(t)};return await kn()?_3e():await Rn("/delete_run",n)}async function W3e(e,t,n){const r=hs(t);return await kn()?x3e():await Rn("/rename_run",{project:e,old_name:r.run,run_id:r.run_id,new_name:n})}function H3e(e){$W=e?e+"/":""}function TW(e){return md?AW(e):`${am}/file?path=${encodeURIComponent(`${$W}${e}`)}`}function fw(e){return md?AW(e):`${am}/file?path=${encodeURIComponent(e)}`}async function G3e(){return await kn()?VSe():null}var Y3e=z('

      No projects

      Create a project by calling trackio.init(project="…") in your training script.

      '),V3e=z('

      No run selected

      Select one or more runs in the sidebar.

      '),X3e=z('

      Start logging with Trackio

      You can create a new project by calling trackio.init():

      Then call trackio.log() to log metrics:

      Finally, call trackio.finish() to finish the run:

      '),K3e=z('
      '),Z3e=z('
      '),J3e=z('
      ',1),Q3e=z('
      ');function eCe(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"selectedRuns",19,()=>[]),i=se(t,"allRuns",19,()=>[]),s=se(t,"smoothing",3,10),a=se(t,"xAxis",3,"step"),o=se(t,"logScaleX",3,!1),l=se(t,"logScaleY",3,!1),u=se(t,"metricFilter",3,""),c=se(t,"showHeaders",3,!0),f=se(t,"appBootstrapReady",3,!1),d=se(t,"plotOrder",19,()=>[]),h=se(t,"realtimeEnabled",3,!0),p=se(t,"metricColumns",31,()=>yt([])),g=ie(yt([])),v=ie("step"),y=ie(yt([])),b=ie(yt(new Set)),_=ie(null),x=ie(!1),w=ie(yt({})),A=ie(yt({group:null,index:-1})),E=new Map,k=null;const C=64;let M=ke(()=>o0(i())),N=ke(()=>{let le=u()?Iy(m(y),u()):m(y);return UR(le,d())}),P=ke(()=>Object.keys(m(N)));function I(le){return Tw(m(g),m(v),le,m(_))}function T(le,V){const q=m(w)[le];if(!q)return V;const B=[];for(const Q of q)V.includes(Q)&&B.push(Q);for(const Q of V)B.includes(Q)||B.push(Q);return B}function $(le,V,q){F(A,{group:le,index:V},!0),q.dataTransfer.effectAllowed="move",q.dataTransfer.setData("text/plain","")}function L(le,V,q){m(A).group===le&&(q.preventDefault(),q.dataTransfer.dropEffect="move")}function W(le,V,q,B){if(B.preventDefault(),m(A).group!==le||m(A).index===V){F(A,{group:null,index:-1},!0);return}const Q=[...q],[X]=Q.splice(m(A).index,1);Q.splice(V,0,X),F(w,{...m(w),[le]:Q},!0),F(A,{group:null,index:-1},!0)}function U(){if(!n()||r().length===0){F(g,[],!0),F(y,[],!0);return}const le=[];for(const j of r()){const re=E.get(j.id??j.name);if(!re)continue;const Me=rY(re,j,s(),a(),o(),l());Me&&(le.push(...Me.rows),F(v,Me.xColumn,!0))}F(g,le,!0);const V=le.filter(j=>j.data_type==="original"||!j.data_type),q=sY(V).filter(j=>j!=="run"&&j!=="data_type"&&j!=="x_axis"),B=q.filter(j=>j!==m(v));F(y,B,!0),p(q);const Q=new Map;for(const j of V){const re=j.series_key;for(const Me of B){if(j[Me]==null)continue;const K=`${Me}\0${re}`;Q.set(K,(Q.get(K)||0)+1)}}const X=new Set(B);for(const[j,re]of Q)re>1&&X.delete(j.split("\0")[0]);F(b,X,!0)}async function O(le){const V=[];for(let q=0;q{const B=q.id??q.name;return!E.has(B)});let V=!1;if(le.length>0)try{const q=await O(le);for(const B of q){const Q=B.run_id??B.run;E.set(Q,B.logs),V=!0}}catch(q){console.error("Failed to load metric logs:",q)}(V||!m(x))&&U(),F(x,!0)}async function G(){if(h()&&!(!n()||r().length===0)&&!t_()&&!e_())try{const le=await O(r());let V=!1;for(const q of le){const B=q.run_id??q.run,Q=q.logs,X=E.get(B);(!X||WR(X,Q))&&(E.set(B,Q),V=!0)}V&&U()}catch(le){console.error("Failed to refresh metric logs:",le)}}Lt(()=>{n(),r(),f(),E=n()?E:new Map,H()}),Lt(()=>{s(),a(),o(),l(),m(x)&&U()}),mh(()=>{const le=er("xmin"),V=er("xmax");if(le!=null&&le!==""&&V!=null&&V!==""){const q=parseFloat(le),B=parseFloat(V);!Number.isNaN(q)&&!Number.isNaN(B)&&q{k&&clearInterval(k)}});function J(le){le&&le.length===2&&F(_,le,!0)}function ce(){F(_,null)}var xe=Q3e(),be=S(xe);{var Le=le=>{Pu(le,{})},tt=le=>{var V=Y3e();R(le,V)},he=le=>{var V=V3e();R(le,V)},Y=le=>{var V=X3e(),q=D(S(V),4),B=S(q);B.textContent=`import trackio +trackio.init(project="my-project")`;var Q=D(q,4),X=S(Q);X.textContent=`for i in range(10): + trackio.log({"loss": 1/(i+1)})`;var j=D(Q,4),re=S(j);re.textContent="trackio.finish()",R(le,V)},Ce=le=>{var V=Mn(),q=ct(V);gt(q,17,()=>m(P),bt,(B,Q)=>{const X=ke(()=>m(N)[m(Q)]),j=ke(()=>`${m(Q)}:direct`),re=ke(()=>T(m(j),m(X).direct)),Me=ke(()=>m(X).direct.length),K=ke(()=>Object.values(m(X).subgroups).reduce((te,_e)=>te+_e.length,0)),Z=ke(()=>m(Me)+m(K));{let te=ke(()=>!c());gd(B,{get label(){return`${m(Q)??""} (${m(Z)??""})`},open:!0,get hidden(){return m(te)},children:(_e,ee)=>{var ge=J3e(),ve=ct(ge);{var $e=Re=>{var je=K3e();gt(je,21,()=>m(re),bt,(Ze,Ke,Qe)=>{const nt=ke(()=>I(m(Ke))),Ge=ke(()=>m(nt).data),qe=ke(()=>m(nt).yExtent),oe=ke(()=>m(b).has(m(Ke))),fe=ke(()=>c()&&m(Ke).split("/").slice(1).join("/")||m(Ke));var Ie=Mn(),Je=ct(Ie);{var xt=Et=>{var Ye=Mn(),ut=ct(Ye);{var At=et=>{vT(et,{get data(){return m(Ge)},get y(){return m(Ke)},get title(){return m(fe)},colorField:"series_key",colorDisplayField:"run",get colorMap(){return m(M)},draggable:!0,ondragstart:mt=>$(m(j),Qe,mt),ondragover:mt=>L(m(j),Qe,mt),ondrop:mt=>W(m(j),Qe,m(re),mt)})},It=et=>{Cy(et,{get data(){return m(Ge)},get x(){return m(v)},get y(){return m(Ke)},get title(){return m(fe)},colorField:"series_key",colorDisplayField:"run",get colorMap(){return m(M)},get xLim(){return m(_)},get yExtent(){return m(qe)},onSelect:J,onResetZoom:ce,draggable:!0,ondragstart:mt=>$(m(j),Qe,mt),ondragover:mt=>L(m(j),Qe,mt),ondrop:mt=>W(m(j),Qe,m(re),mt)})};ue(ut,et=>{m(oe)?et(At):et(It,-1)})}R(Et,Ye)};ue(Je,Et=>{m(Ge).length>0&&Et(xt)})}R(Ze,Ie)}),R(Re,je)};ue(ve,Re=>{m(re).length>0&&Re($e)})}var Xe=D(ve,2);gt(Xe,21,()=>Object.entries(m(X).subgroups),bt,(Re,je)=>{var Ze=ke(()=>pg(m(je),2));let Ke=()=>m(Ze)[0],Qe=()=>m(Ze)[1];const nt=ke(()=>`${m(Q)}:${Ke()}`),Ge=ke(()=>T(m(nt),Qe()));{let qe=ke(()=>!c());gd(Re,{get label(){return`${Ke()??""} (${Qe().length??""})`},open:!0,get hidden(){return m(qe)},children:(oe,fe)=>{var Ie=Z3e();gt(Ie,21,()=>m(Ge),bt,(Je,xt,Et)=>{const Ye=ke(()=>I(m(xt))),ut=ke(()=>m(Ye).data),At=ke(()=>m(Ye).yExtent),It=ke(()=>m(b).has(m(xt))),et=ke(()=>c()&&m(xt).split("/").slice(2).join("/")||m(xt));var mt=Mn(),vt=ct(mt);{var Dt=kt=>{var mn=Mn(),vn=ct(mn);{var lt=ne=>{vT(ne,{get data(){return m(ut)},get y(){return m(xt)},get title(){return m(et)},colorField:"series_key",colorDisplayField:"run",get colorMap(){return m(M)},draggable:!0,ondragstart:Ae=>$(m(nt),Et,Ae),ondragover:Ae=>L(m(nt),Et,Ae),ondrop:Ae=>W(m(nt),Et,m(Ge),Ae)})},Nt=ne=>{Cy(ne,{get data(){return m(ut)},get x(){return m(v)},get y(){return m(xt)},get title(){return m(et)},colorField:"series_key",colorDisplayField:"run",get colorMap(){return m(M)},get xLim(){return m(_)},get yExtent(){return m(At)},onSelect:J,onResetZoom:ce,draggable:!0,ondragstart:Ae=>$(m(nt),Et,Ae),ondragover:Ae=>L(m(nt),Et,Ae),ondrop:Ae=>W(m(nt),Et,m(Ge),Ae)})};ue(vn,ne=>{m(It)?ne(lt):ne(Nt,-1)})}R(kt,mn)};ue(vt,kt=>{m(ut).length>0&&kt(Dt)})}R(Je,mt)}),R(oe,Ie)},$$slots:{default:!0}})}}),R(_e,ge)},$$slots:{default:!0}})}}),R(le,V)};ue(be,le=>{!f()||!m(x)?le(Le):n()?r().length===0?le(he,2):m(g).length===0?le(Y,3):le(Ce,-1):le(tt,1)})}R(e,xe),un()}var tCe=z('

      Select a project

      Pick a project to browse trace logs.

      '),nCe=z('

      No runs selected

      Select one or more runs in the sidebar to browse traces.

      '),rCe=z(""),iCe=z('

      No traces match the current filters

      Try a different search query, step, or run selection.

      '),sCe=z(" "),aCe=z('tool calls'),oCe=z('function call'),lCe=z('
      Expand content
       
      '),uCe=z('
       
      '),cCe=z(''),fCe=z('
       
      '),dCe=z('
      '),hCe=z('
       
      '),pCe=z('
      '),gCe=z('
       
      '),mCe=z('
      '),vCe=z('
      '),yCe=z('
      ',1),bCe=z('
      Trace IDRequestRunStepRequest time
      ',1),_Ce=z('
      ',1),xCe=z('
      ');function wCe(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"selectedRuns",19,()=>[]);const i=50;let s=ie(!1),a=ie(""),o=ie("request_time_desc"),l=ie("all"),u=ie(0),c=ie(null),f=ie(yt([])),d=ie(yt([])),h=ie(0),p=0,g=0;function v(q){return q.map(B=>`${B.id||""}:${B.name||""}`).join("|")}function y(q){return typeof q=="string"?q:Array.isArray(q)?q.map(B=>typeof B=="string"?B:typeof(B==null?void 0:B.text)=="string"?B.text:typeof(B==null?void 0:B.content)=="string"?B.content:(B==null?void 0:B._type)==="trackio.image"||(B==null?void 0:B.type)==="image"?"[image]":"").filter(Boolean).join(" "):typeof(q==null?void 0:q.text)=="string"?q.text:""}function b(q,B){const Q=Array.isArray(q.messages)?q.messages:[],X=Q.find(re=>(re==null?void 0:re.role)==="user"),j=Q.find(re=>(re==null?void 0:re.role)==="assistant");return{...q,run:q.run||B,request:y(X==null?void 0:X.content)||"(no user message)",preview:y(j==null?void 0:j.content)||"(no assistant response)"}}function _(q,B){return[...q].sort((Q,X)=>{switch(B){case"step_asc":return(Q.step??0)-(X.step??0);case"step_desc":return(X.step??0)-(Q.step??0);case"request_time_asc":return String(Q.timestamp||"").localeCompare(String(X.timestamp||""));case"request_time_desc":default:return String(X.timestamp||"").localeCompare(String(Q.timestamp||""))}})}async function x(){const q=++g;if(!n()||r().length===0){F(d,[],!0),F(h,0);return}try{const B=await Promise.all(r().map(j=>M3e(n(),j)));if(q!==g)return;const Q=new Map;let X=0;for(const j of B){X+=(j==null?void 0:j.total)||0;for(const re of(j==null?void 0:j.steps)||[])Q.set(re.step,(Q.get(re.step)||0)+re.count)}F(d,[...Q.entries()].map(([j,re])=>({step:j,count:re})).sort((j,re)=>(j.step??0)-(re.step??0)),!0),F(h,X,!0)}catch(B){if(q!==g)return;console.error("Failed to load trace summary:",B),F(d,[],!0),F(h,0)}}async function w(q,B,Q,X){const j=++p;if(!n()||r().length===0){F(f,[],!0),F(c,null);return}F(s,!0);try{const re=Q==="all"?null:Number(Q),Me=X*i,K=r().length===1,Z=K?i:Me+i,te=K?Me:0,_e=await Promise.all(r().map(async ge=>(await D3e(n(),ge,{search:q,sort:B,step:re,limit:Z,offset:te})).map($e=>b($e,ge.name))));if(j!==p)return;let ee=_(_e.flat(),B);K||(ee=ee.slice(Me,Me+i)),F(f,ee,!0),m(f).find(ge=>ge.id===m(c))||F(c,null)}catch(re){if(j!==p)return;console.error("Failed to load traces:",re),F(f,[],!0)}finally{j===p&&F(s,!1)}}let A="",E="",k="",C="all";Lt(()=>{const q=`${n()||""}::${v(r())}`;q!==A&&(A=q,F(u,0),F(l,"all"),F(c,null),F(f,[],!0),x())}),Lt(()=>{n(),v(r());const q=m(a).trim();(q!==E||m(o)!==k||m(l)!==C)&&((E!==""||q!==""||m(o)!==k||m(l)!==C)&&F(u,0),E=q,k=m(o),C=m(l));const B=setTimeout(()=>{w(q,m(o),m(l),m(u))},150);return()=>clearTimeout(B)});function M(q){F(c,m(c)===q?null:q,!0)}function N(q,B){(q.key==="Enter"||q.key===" ")&&(q.preventDefault(),M(B))}function P(q){if(!q)return"—";const B=new Date(q);if(Number.isNaN(B.getTime()))return q;const X=new Date().getTime()-B.getTime(),j=Math.max(0,Math.round(X/1e3));if(j<5)return"just now";if(j<60)return`${j} sec ago`;const re=Math.round(j/60);if(re<60)return`${re} min ago`;const Me=Math.round(re/60);if(Me<24)return`${Me} hr ago`;const K=Math.round(Me/24);if(K<7)return`${K} day${K===1?"":"s"} ago`;const Z=Math.round(K/7);if(Z<5)return`${Z} wk ago`;const te=Math.round(K/30);return te<12?`${te} mo ago`:`${Math.round(K/365)} yr ago`}function I(q){const B=q==null?void 0:q.content;return typeof B=="string"||B==null?[]:Array.isArray(B)?B:[B]}function T(q){return I(q).length>0}function $(q){return(q==null?void 0:q._type)==="trackio.image"||(q==null?void 0:q.type)==="image"||(q==null?void 0:q.type)==="input_image"||(q==null?void 0:q.type)==="image_url"}function L(q){var B;return q!=null&&q.file_path?TW(q.file_path):(B=q==null?void 0:q.image_url)!=null&&B.url?q.image_url.url:typeof(q==null?void 0:q.url)=="string"?q.url:""}function W(q){return(q==null?void 0:q.caption)||(q==null?void 0:q.alt)||"Trace image"}function U(q){return typeof q=="string"&&q.length>500}function O(q){if(!q)return"";const B=String(q).split(":");if(B.length>=4){const Q=B[1],X=B[B.length-1];return X!==""&&!Number.isNaN(Number(X))?`${Q}:${X}`:Q}return String(q)}function H(q){if(!q)return"";const B=String(q).split(":"),Q=B.length>=4?B[1]||B[0]:String(q);return Q.replace(/[^a-zA-Z0-9]/g,"").slice(0,7)||Q.slice(0,7)}function G(q){if(!q)return null;const B=String(q).split(":");if(B.length>=4){const Q=B[B.length-1];if(Q!==""&&!Number.isNaN(Number(Q)))return Q}return null}function J(q){if(q==null)return"—";if(typeof q=="string")return q;if(typeof q=="number"||typeof q=="boolean")return String(q);try{return JSON.stringify(q)}catch{return String(q)}}function ce(q){return Object.entries(q.metadata||{})}let xe=ke(()=>{if(m(l)==="all")return m(h);const q=Number(m(l)),B=m(d).find(Q=>Q.step===q);return B?B.count*Math.max(1,r().length):0}),be=ke(()=>Math.max(1,Math.ceil(m(xe)/i)));function Le(){m(u)>0&&F(u,m(u)-1)}function tt(){m(u){var B=tCe();R(q,B)},le=q=>{var B=nCe();R(q,B)},V=q=>{var B=_Ce(),Q=ct(B),X=S(Q),j=S(X),re=D(X,2),Me=D(S(re),2),K=S(Me),Z=S(K);K.value=K.__value="all";var te=D(K);gt(te,17,()=>m(d),bt,(Ge,qe)=>{var oe=rCe(),fe=S(oe),Ie={};me(Je=>{ae(fe,`Step ${m(qe).step??""} (${m(qe).count??""})`),Ie!==(Ie=Je)&&(oe.value=(oe.__value=Je)??"")},[()=>String(m(qe).step)]),R(Ge,oe)});var _e=D(re,2),ee=D(S(_e),2),ge=S(ee);ge.value=ge.__value="request_time_desc";var ve=D(ge);ve.value=ve.__value="request_time_asc";var $e=D(ve);$e.value=$e.__value="step_desc";var Xe=D($e);Xe.value=Xe.__value="step_asc";var Re=D(_e,2),je=S(Re),Ze=D(Q,2);{var Ke=Ge=>{Pu(Ge,{})},Qe=Ge=>{var qe=iCe();R(Ge,qe)},nt=Ge=>{var qe=bCe(),oe=ct(qe);let fe;var Ie=S(oe),Je=D(S(Ie),2);gt(Je,21,()=>m(f),It=>It.id,(It,et)=>{var mt=yCe(),vt=ct(mt),Dt=S(vt),kt=S(Dt),mn=S(kt),vn=D(Dt),lt=S(vn),Nt=S(lt),ne=D(lt,2),Ae=S(ne),St=D(vn),Ot=S(St),rt=D(St),at=S(rt),Mt=D(rt),jn=S(Mt),yn=D(vt,2);{var wi=Un=>{var qn=vCe(),Zn=S(qn),Ei=S(Zn),cr=S(Ei),ii=S(cr),Ai=S(ii),bn=D(ii,2),Bu=S(bn),fr=D(bn,2),Gi=S(fr),Fo=D(fr,2);gt(Fo,17,()=>ce(m(et)),bt,(Nn,Yt)=>{var $a=ke(()=>pg(m(Yt),2));let dr=()=>m($a)[0],ps=()=>m($a)[1];var Hh=sCe(),n_=S(Hh);me(r_=>ae(n_,`${dr()??""}: ${r_??""}`),[()=>J(ps())]),R(Nn,Hh)});var qs=D(cr,2);gt(qs,21,()=>m(et).messages,bt,(Nn,Yt)=>{var $a=mCe(),dr=S($a),ps=S(dr),Hh=D(ps);{var n_=On=>{var Wn=aCe();R(On,Wn)};ue(Hh,On=>{var Wn;(Wn=m(Yt).tool_calls)!=null&&Wn.length&&On(n_)})}var r_=D(Hh,2);{var NW=On=>{var Wn=oCe();R(On,Wn)};ue(r_,On=>{m(Yt).function_call&&On(NW)})}var rF=D(dr,2);{var OW=On=>{var Wn=Mn(),zu=ct(Wn);{var Fa=Da=>{var Uu=lCe(),Yh=D(S(Uu),2),wl=S(Yh);me(()=>ae(wl,m(Yt).content)),R(Da,Uu)},ju=ke(()=>U(m(Yt).content)),Gh=Da=>{var Uu=uCe(),Yh=S(Uu);me(()=>ae(Yh,m(Yt).content)),R(Da,Uu)};ue(zu,Da=>{m(ju)?Da(Fa):Da(Gh,-1)})}R(On,Wn)},LW=On=>{var Wn=dCe();gt(Wn,21,()=>I(m(Yt)),bt,(zu,Fa)=>{var ju=Mn(),Gh=ct(ju);{var Da=wl=>{var Mf=cCe();me((i_,s_)=>{pt(Mf,"src",i_),pt(Mf,"alt",s_)},[()=>L(m(Fa)),()=>W(m(Fa))]),R(wl,Mf)},Uu=ke(()=>$(m(Fa))),Yh=wl=>{var Mf=fCe(),i_=S(Mf);me(s_=>ae(i_,s_),[()=>JSON.stringify(m(Fa),null,2)]),R(wl,Mf)};ue(Gh,wl=>{m(Uu)?wl(Da):wl(Yh,-1)})}R(zu,ju)}),R(On,Wn)},IW=ke(()=>T(m(Yt)));ue(rF,On=>{typeof m(Yt).content=="string"?On(OW):m(IW)&&On(LW,1)})}var iF=D(rF,2);{var PW=On=>{var Wn=pCe();gt(Wn,21,()=>m(Yt).tool_calls,bt,(zu,Fa)=>{var ju=hCe(),Gh=S(ju);me(Da=>ae(Gh,Da),[()=>JSON.stringify(m(Fa),null,2)]),R(zu,ju)}),R(On,Wn)};ue(iF,On=>{var Wn;(Wn=m(Yt).tool_calls)!=null&&Wn.length&&On(PW)})}var BW=D(iF,2);{var zW=On=>{var Wn=gCe(),zu=S(Wn);me(Fa=>ae(zu,Fa),[()=>JSON.stringify(m(Yt).function_call,null,2)]),R(On,Wn)};ue(BW,On=>{m(Yt).function_call&&On(zW)})}me(()=>{pt($a,"data-role",m(Yt).role||"unknown"),ae(ps,`${(m(Yt).role||"message")??""} `)}),R(Nn,$a)}),me(Nn=>{ae(Ai,`Trace ID: ${Nn??""}`),ae(Bu,`Logged as: ${m(et).key??""}`),ae(Gi,`Timestamp: ${(m(et).timestamp||"—")??""}`)},[()=>O(m(et).id)]),R(Un,qn)};ue(yn,Un=>{m(c)===m(et).id&&Un(wi)})}me((Un,qn,Zn,Ei)=>{pt(vt,"aria-expanded",m(c)===m(et).id),pt(kt,"title",Un),ae(mn,`${qn??""}${Zn??""}`),ae(Nt,m(et).request),ae(Ae,m(et).preview),ae(Ot,m(et).run||"—"),ae(at,m(et).step??"—"),ae(jn,Ei)},[()=>O(m(et).id),()=>H(m(et).id),()=>G(m(et).id)!==null?`:${G(m(et).id)}`:"",()=>P(m(et).timestamp)]),Ne("click",vt,()=>M(m(et).id)),Ne("keydown",vt,Un=>N(Un,m(et).id)),R(It,mt)});var xt=D(oe,2),Et=S(xt),Ye=D(Et,2),ut=S(Ye),At=D(Ye,2);me(()=>{fe=qt(oe,1,"traces-table-wrap svelte-1s32ifo",null,fe,{dim:m(s)}),Et.disabled=m(u)===0||m(s),ae(ut,`Page ${m(u)+1} of ${m(be)??""}`),At.disabled=m(u)>=m(be)-1||m(s)}),Ne("click",Et,Le),Ne("click",At,tt),R(Ge,qe)};ue(Ze,Ge=>{m(s)&&m(f).length===0?Ge(Ke):m(f).length===0?Ge(Qe,1):Ge(nt,-1)})}me(()=>{ae(Z,`All steps (${m(h)??""})`),ae(je,`${m(xe)??""} trace${m(xe)===1?"":"s"}`)}),df(j,()=>m(a),Ge=>F(a,Ge)),q1(Me,()=>m(l),Ge=>F(l,Ge)),q1(ee,()=>m(o),Ge=>F(o,Ge)),R(q,B)};ue(Y,q=>{n()?r().length===0?q(le,1):q(V,-1):q(Ce)})}R(e,he),un()}or(["click","keydown"]);var ECe=z('

      Unable to load system metrics

      '),ACe=z('

      No projects

      Create a project by calling trackio.init(project="…") in your training script.

      '),kCe=z('

      No run selected

      Select one or more runs in the sidebar.

      '),SCe=z('

      No System Metrics Available

      System metrics will appear here once logged. To enable automatic logging:

      Setup:

      • CPU/system metrics: pip install trackio[cpu] (requires psutil)
      • NVIDIA GPU: pip install trackio[gpu] (requires nvidia-ml-py)
      • Apple Silicon: pip install trackio[apple-gpu] (requires psutil)
      '),CCe=z('
      '),$Ce=z('
      '),FCe=z(" ",1),DCe=z('
      ');function MCe(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"selectedRuns",19,()=>[]),i=se(t,"allRuns",19,()=>[]),s=se(t,"smoothing",3,5),a=se(t,"appBootstrapReady",3,!1),o=se(t,"realtimeEnabled",3,!0),l=se(t,"availableDevices",31,()=>yt([])),u=se(t,"selectedDevices",31,()=>yt([])),c=ie(yt([])),f=ie(yt([])),d=ie(null),h=ie(!1),p=ie(null),g=!0,v=ie(yt({})),y=ie(yt({group:null,index:-1}));const b=64;let _=new Map,x=null,w=ke(()=>o0(i().length?i():r())),A=ke(()=>UR(m(f))),E=ke(()=>Object.keys(m(A))),k=ke(()=>{const K=new Map,Z=m(d);for(const te of Object.values(m(A))){for(const _e of te.direct)K.has(_e)||K.set(_e,Tw(m(c),"time",_e,Z));for(const _e of Object.values(te.subgroups))for(const ee of _e)K.has(ee)||K.set(ee,Tw(m(c),"time",ee,Z))}return K}),C=ke(()=>{const K=[];for(const[Z,te]of Object.entries(m(A)))for(const _e of L(Object.keys(te.subgroups)))K.push(he(Z,_e));return[...new Set(K)]}),M=ke(()=>{const K=new Map;for(const[Z,te]of Object.entries(m(A)))K.set(Z,Ce(Z,te.subgroups));return K}),N=ke(()=>{const K=new Map,Z=m(d);for(const[te,_e]of m(M).entries())for(const[ee,ge]of Object.entries(_e)){const ve=`sys:${te}:compare:${ee}`;K.set(ve,le(m(c),"time",ge,Z))}return K});function P(K,Z){const te=m(v)[K];if(!te)return Z;const _e=[];for(const ee of te)Z.includes(ee)&&_e.push(ee);for(const ee of Z)_e.includes(ee)||_e.push(ee);return _e}function I(K,Z,te){F(y,{group:K,index:Z},!0),te.dataTransfer.effectAllowed="move",te.dataTransfer.setData("text/plain","")}function T(K,Z,te){m(y).group===K&&(te.preventDefault(),te.dataTransfer.dropEffect="move")}function $(K,Z,te,_e){if(_e.preventDefault(),m(y).group!==K||m(y).index===Z){F(y,{group:null,index:-1},!0);return}const ee=[...te],[ge]=ee.splice(m(y).index,1);ee.splice(Z,0,ge),F(v,{...m(v),[K]:ee},!0),F(y,{group:null,index:-1},!0)}function L(K){return[...K].sort((Z,te)=>{const _e=Number(Z),ee=Number(te);return!Number.isNaN(_e)&&!Number.isNaN(ee)?_e-ee:Z.localeCompare(te)})}function W(K,Z){return K.length!==Z.length?!1:K.every((te,_e)=>te===Z[_e])}function U(){if(!n()||r().length===0){F(c,[],!0),F(f,[],!0);return}const K=[],Z=new Set;for(const te of r()){const _e=te.id??te.name,ee=_.get(_e);if(!ee||ee.length===0)continue;const ge=new Date(ee[0].timestamp).getTime();ee.forEach(ve=>{const $e=(new Date(ve.timestamp).getTime()-ge)/1e3;Object.keys(ve).forEach(Xe=>{typeof ve[Xe]=="number"&&Xe!=="step"&&Xe!=="time"&&Z.add(Xe)}),K.push({...ve,time:$e,run:te.name,run_id:_e,series_key:_e,data_type:"original"})})}F(f,Array.from(Z).sort(),!0),F(c,K,!0)}function O(K){const Z=K&&K.message?String(K.message):"";return/\b(404|405|501)\b/.test(Z)}async function H(K){if(g&&K.length<=b)try{return await LT(n(),K)}catch(te){if(!O(te))throw te;g=!1}if(g){const te=[];for(let _e=0;_e{const _e=te.id??te.name;return!_.has(_e)});let Z=!1;if(K.length>0)try{const te=await H(K);for(const _e of te){const ee=_e.run_id??_e.run;_.set(ee,_e.logs),Z=!0}F(p,null)}catch(te){if(console.error("Failed to load system metric logs:",te),!m(h)){F(p,te&&te.message?te.message:"Failed to load system metrics",!0);return}}(Z||!m(h))&&U(),F(p,null),F(h,!0)}async function J(){if(o()&&!(!n()||r().length===0)&&!t_()&&!e_())try{const K=await H(r());let Z=!1;for(const te of K){const _e=te.run_id??te.run,ee=te.logs,ge=_.get(_e);(!ge||WR(ge,ee))&&(_.set(_e,ee),Z=!0)}Z&&U()}catch(K){console.error("Failed to refresh system metric logs:",K)}}Lt(()=>{n(),r(),a(),_=n()?_:new Map,G()}),Lt(()=>{s(),m(h)&&U()}),Lt(()=>{const K=l(),Z=m(C),te=u().filter(_e=>Z.includes(_e));if(W(l(),Z)||l(Z),Z.length===0){u().length>0&&u([]);return}if(K.length===0&&u().length===0){W(u(),Z)||u([...Z]);return}if(u().length>0&&te.length!==u().length){const _e=te.length>0?te:[...Z];W(u(),_e)||u(_e)}}),mh(()=>(x=setInterval(J,CW()),()=>{x&&clearInterval(x)}));function ce(K){K&&K.length===2&&F(d,K,!0)}function xe(){F(d,null)}const be={utilization:"%",mean_utilization:"%",allocated_memory:"GiB",total_allocated_memory:"GiB",power:"W",total_power:"W",temp:"°C",max_temp:"°C"};function Le(K){const Z=K.split("/").pop(),te=be[Z];return te?`${K} (${te})`:K}function tt(K,Z=1){const te=K.split("/").slice(Z).join("/")||K;return Le(te)}function he(K,Z){return K==="gpu"?`GPU ${Z}`:`${K.toUpperCase()} ${Z}`}function Y(K,Z){return he(K,Z)}function Ce(K,Z){const te={},_e=L(Object.keys(Z)).filter(ge=>{const ve=Y(K,ge);return u().length===0||u().includes(ve)});for(const ge of _e)for(const ve of Z[ge]??[]){const $e=ve.split("/").slice(2).join("/");$e&&(te[$e]||(te[$e]=[]),te[$e].push(ve))}const ee={};return Object.keys(te).sort().forEach(ge=>{ee[ge]=te[ge]}),ee}function le(K,Z,te,_e){if(!te||te.length===0)return{data:[],yExtent:void 0};let ee=[];for(const $e of te){const[Xe,Re]=$e.split("/");for(const je of K){const Ze=je[$e];Ze!=null&&ee.push({[Z]:je[Z],value:Ze,seriesKey:`${je.series_key}\0${Xe}\0${Re}`,run:je.run,series_key:je.series_key,device:Y(Xe,Re),data_type:je.data_type})}}if(_e){const $e=new Map;for(const Re of ee){const je=`${Re.seriesKey}\0${Re.data_type||"original"}`;$e.has(je)||$e.set(je,[]),$e.get(je).push(Re)}const Xe=[];for(const Re of $e.values()){Re.sort((Ke,Qe)=>Ke[Z]-Qe[Z]);let je=0,Ze=Re.length-1;for(;je=0&&Re[Ze][Z]>_e[1];)Ze--;je=Math.max(0,je-1),Ze=Math.min(Re.length-1,Ze+1),Xe.push(...Re.slice(je,Ze+1))}ee=Xe}const ge=ee.filter($e=>$e.data_type==="original"||!$e.data_type);let ve;if(ge.length>0){let $e=1/0,Xe=-1/0;for(const Re of ge)Re.value<$e&&($e=Re.value),Re.value>Xe&&(Xe=Re.value);$e!==1/0&&(ve=[$e,Xe])}return{data:jR(ee,Z,"value","seriesKey",_e,["seriesKey","run","series_key","device"]).data,yExtent:ve}}var V=DCe(),q=S(V);{var B=K=>{Pu(K,{})},Q=K=>{var Z=ECe(),te=D(S(Z),2),_e=S(te);me(()=>ae(_e,m(p))),R(K,Z)},X=K=>{var Z=ACe();R(K,Z)},j=K=>{var Z=kCe();R(K,Z)},re=K=>{var Z=SCe(),te=D(S(Z),4),_e=S(te);_e.textContent=`import trackio + +# CPU/system metrics auto-enable when psutil is installed: +run = trackio.init(project="my-project") + +# Or explicitly enable/disable them: +run = trackio.init(project="my-project", auto_log_cpu=True) + +# Manually log at any time: +trackio.log_cpu() +trackio.log_gpu()`,R(K,Z)},Me=K=>{var Z=Mn(),te=ct(Z);gt(te,17,()=>m(E),bt,(_e,ee)=>{const ge=ke(()=>m(A)[m(ee)]),ve=ke(()=>`sys:${m(ee)}`),$e=ke(()=>`sys:${m(ee)}:compare`),Xe=ke(()=>P(m(ve),m(ge).direct)),Re=ke(()=>m(M).get(m(ee))??{}),je=ke(()=>P(m($e),Object.keys(m(Re))));gd(_e,{get label(){return m(ee)},open:!0,children:(Ze,Ke)=>{var Qe=FCe(),nt=ct(Qe);{var Ge=fe=>{var Ie=CCe();gt(Ie,21,()=>m(Xe),bt,(Je,xt,Et)=>{const Ye=ke(()=>m(k).get(m(xt))??{data:[],yExtent:void 0}),ut=ke(()=>m(Ye).data),At=ke(()=>m(Ye).yExtent);var It=Mn(),et=ct(It);{var mt=vt=>{{let Dt=ke(()=>tt(m(xt),1));Cy(vt,{get data(){return m(ut)},x:"time",get y(){return m(xt)},get title(){return m(Dt)},get colorMap(){return m(w)},colorField:"series_key",colorDisplayField:"run",get xLim(){return m(d)},get yExtent(){return m(At)},onSelect:ce,onResetZoom:xe,draggable:!0,ondragstart:kt=>I(m(ve),Et,kt),ondragover:kt=>T(m(ve),Et,kt),ondrop:kt=>$(m(ve),Et,m(Xe),kt)})}};ue(et,vt=>{m(ut).length>0&&vt(mt)})}R(Je,It)}),R(fe,Ie)};ue(nt,fe=>{m(Xe).length>0&&fe(Ge)})}var qe=D(nt,2);{var oe=fe=>{var Ie=$Ce(),Je=S(Ie);gt(Je,21,()=>m(je),bt,(xt,Et,Ye)=>{const ut=ke(()=>`sys:${m(ee)}:compare:${m(Et)}`),At=ke(()=>m(N).get(m(ut))??{data:[],yExtent:void 0}),It=ke(()=>m(At).data),et=ke(()=>m(At).yExtent);var mt=Mn(),vt=ct(mt);{var Dt=kt=>{{let mn=ke(()=>Le(m(Et))),vn=ke(()=>Le(m(Et)));Cy(kt,{get data(){return m(It)},x:"time",y:"value",get yLabel(){return m(mn)},get title(){return m(vn)},colorField:"series_key",colorDisplayField:"run",colorLabel:"Run",get colorMap(){return m(w)},dashField:"device",dashLabel:"Device",get xLim(){return m(d)},get yExtent(){return m(et)},onSelect:ce,onResetZoom:xe,draggable:!0,ondragstart:lt=>I(m($e),Ye,lt),ondragover:lt=>T(m($e),Ye,lt),ondrop:lt=>$(m($e),Ye,m(je),lt)})}};ue(vt,kt=>{m(It).length>0&&kt(Dt)})}R(xt,mt)}),R(fe,Ie)};ue(qe,fe=>{m(je).length>0&&fe(oe)})}R(Ze,Qe)},$$slots:{default:!0}})}),R(K,Z)};ue(q,K=>{!a()||!m(h)&&!m(p)?K(B):m(p)&&!m(h)?K(Q,1):n()?r().length===0?K(j,3):m(c).length===0?K(re,4):K(Me,-1):K(X,2)})}R(e,V),un()}var TCe=ri(''),RCe=ri(''),NCe=z('
      ');function OCe(e,t){ln(t,!0);let n=se(t,"src",3,"");const r=72;let i,s,a=ie(yt([])),o=ie(0),l=ie(0),u=ie(!1),c=ie(!1);function f(C){if(!Number.isFinite(C)||C<0)return"0:00";const M=Math.floor(C/60),N=Math.floor(C%60);return`${M}:${N.toString().padStart(2,"0")}`}async function d(){var C;if(n()){F(c,!1);try{const N=await(await fetch(n())).arrayBuffer(),P=window.AudioContext||window.webkitAudioContext,I=new P,T=await I.decodeAudioData(N);F(o,T.duration,!0);const $=T.getChannelData(0),L=Math.max(1,Math.floor($.length/r)),W=new Array(r);for(let O=0;OO/U),!0),(C=I.close)==null||C.call(I)}catch{F(c,!0)}}}function h(){if(!i||m(a).length===0)return;const C=window.devicePixelRatio||1,M=i.getBoundingClientRect();if(M.width===0)return;i.width=M.width*C,i.height=M.height*C;const N=i.getContext("2d");N.setTransform(C,0,0,C,0,0),N.clearRect(0,0,M.width,M.height);const P=getComputedStyle(i),I=(P.getPropertyValue("--wave-played")||"#f97316").trim(),T=(P.getPropertyValue("--wave-base")||"#9ca3af").trim(),$=m(o)>0?m(l)/m(o):0,L=M.width/m(a).length,W=M.height/2;for(let U=0;U{}):s.pause())}function g(C){if(!s||!m(o))return;const M=i.getBoundingClientRect(),N=C.clientX-M.left,P=Math.max(0,Math.min(m(o),N/M.width*m(o)));s.currentTime=P,F(l,P,!0)}Lt(()=>{n(),F(a,[],!0),F(l,0),F(o,0),F(u,!1),d()}),Lt(()=>{m(a),m(l),m(o),h()});var v=NCe();_n("resize",Dd,h);var y=S(v),b=S(y);{var _=C=>{var M=TCe();R(C,M)},x=C=>{var M=RCe();R(C,M)};ue(b,C=>{m(u)?C(_):C(x,-1)})}var w=D(y,2);es(w,C=>i=C,()=>i);var A=D(w,2),E=S(A),k=D(A,2);es(k,C=>s=C,()=>s),me((C,M)=>{pt(y,"aria-label",m(u)?"Pause":"Play"),y.disabled=m(c),ae(E,`${C??""} / ${M??""}`),pt(k,"src",n())},[()=>f(m(l)),()=>f(m(o))]),Ne("click",y,p),Ne("click",w,g),_n("timeupdate",k,()=>F(l,s.currentTime,!0)),_n("loadedmetadata",k,()=>F(o,s.duration,!0)),_n("play",k,()=>F(u,!0)),_n("pause",k,()=>F(u,!1)),_n("ended",k,()=>{F(u,!1),F(l,0)}),R(e,v),un()}or(["click"]);var LCe=z('

      Select a project

      Pick a project in the sidebar to browse media and tables for a run.

      ',1),ICe=z('

      No runs selected

      Select runs in the sidebar to browse media and tables.

      ',1),PCe=z('

      No media or tables in this run

      Log images, video, audio, and tables by passing Trackio objects to trackio.log():

      Each type appears in its own section here once logged.

      ',1),BCe=z('
      '),zCe=z('
      '),jCe=z('
      '),UCe=z(''),qCe=z('
      No images match this filter.
      '),WCe=z('
      '),HCe=z('
      Sort
      '),GCe=z('',2),YCe=z('
      '),VCe=z('
      '),XCe=z(''),KCe=z('
      '),ZCe=z('
      '),JCe=z(' '),QCe=z(''),e$e=z(''),t$e=z('
      '),n$e=z(''),r$e=z(''),i$e=z('
      '),s$e=z('
      '),a$e=z('
      '),o$e=z(" ",1),l$e=z(''),u$e=z(''),c$e=z('
      '),f$e=z('
      '),d$e=z(' '),h$e=z(''),p$e=z('
      ',1);function g$e(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"selectedRuns",19,()=>[]),i=se(t,"allRuns",19,()=>[]),s=se(t,"tableTruncateLength",3,250),a=ke(()=>o0(i().length?i():r()));function o(B){return m(a)[B._runId]??m(a)[B._run]??"#9ca3af"}const l=48,u={images:[],videos:[],audios:[],tables:[]};let c=ie(yt(u)),f=ie("newest"),d=ie(""),h=ie(yt(b())),p=ie(null),g=ie(yt([])),v=ie(null),y=ie(!1);function b(){return{images:l,videos:l,audios:l,tables:l}}function _(){F(h,b(),!0)}function x(B,Q){const X=Number.isFinite(B.step)?B.step:0,j=Number.isFinite(Q.step)?Q.step:0,re=m(f)==="newest"?j-X:X-j;if(re!==0)return re;const Me=Number.isFinite(B._index)?B._index:0,K=Number.isFinite(Q._index)?Q._index:0;return m(f)==="newest"?K-Me:Me-K}function w(B){return[...B].sort(x)}function A(B){return Array.isArray(B._value)&&B._value.length>0}let E=ke(()=>({images:w(m(c).images),videos:w(m(c).videos),audios:w(m(c).audios),tables:w(m(c).tables.filter(A))}));function k(B){return B.caption?`${B.key} ${B.caption}`:B.key}let C=ke(()=>{if(!m(d).trim())return m(E).images;const B=new Set(Iy(m(E).images.map(Q=>k(Q)),m(d)));return m(E).images.filter(Q=>B.has(k(Q)))}),M=ke(()=>({images:m(C).slice(0,m(h).images),videos:m(E).videos.slice(0,m(h).videos),audios:m(E).audios.slice(0,m(h).audios),tables:m(E).tables.slice(0,m(h).tables)})),N=ke(()=>m(E).images.length>0||m(E).videos.length>0||m(E).audios.length>0||m(E).tables.length>0);function P(B){m(h)[B]+=l}Lt(()=>{m(f),m(d),m(c),_()});async function I(){if(!n()||r().length===0){F(c,u,!0);return}F(y,!0);try{const B=r(),Q=[];for(const te of B){const _e=await FW(n(),te);_e&&Q.push(..._e.map(ee=>({...ee,_run:te.name,_runId:te.id??te.name})))}const X=Q,j=[],re=[],Me=[],K=[];let Z=0;X&&X.forEach((te,_e)=>{Object.entries(te).forEach(([ee,ge])=>{if(ge&&typeof ge=="object"&&ge._type){const ve={key:ee,step:te.step??_e,_index:Z++,_run:te._run,_runId:te._runId,...ge};switch(ge._type){case"trackio.image":j.push(ve);break;case"trackio.video":re.push(ve);break;case"trackio.audio":Me.push(ve);break;case"trackio.table":K.push(ve);break}}})}),F(c,{images:j,videos:re,audios:Me,tables:K},!0)}catch(B){console.error("Failed to load media:",B)}finally{F(y,!1)}}Lt(()=>{n(),r(),I()});function T(B){return B._resolvedUrl?B._resolvedUrl:B.file_path?TW(B.file_path):""}function $(B){return B&&typeof B=="object"&&!Array.isArray(B)&&B._type==="trackio.image"}function L(B){return Array.isArray(B)&&B.length>0&&B.every(Q=>Q&&typeof Q=="object"&&Q._type==="trackio.image")}function W(B){var Q;(Q=B.currentTarget.parentElement)==null||Q.classList.add("image-loaded")}function U(B){var Q;(Q=B.currentTarget.parentElement)==null||Q.classList.add("image-failed")}function O(B,Q=null){return{...B,key:B.key??(Q==null?void 0:Q.key),step:B.step??(Q==null?void 0:Q.step),_run:B._run??(Q==null?void 0:Q._run),_runId:B._runId??(Q==null?void 0:Q._runId),caption:B.caption??(Q==null?void 0:Q.caption)}}function H(B,Q=null,X=[],j=null){F(p,O(B,Q),!0),F(g,X,!0),F(v,j,!0)}function G(){F(p,null),F(g,[],!0),F(v,null)}function J(B){B<0||B>=m(g).length||(F(p,O(m(g)[B]),!0),F(v,B,!0))}function ce(){m(v)===null||m(g).length<=1||J((m(v)-1+m(g).length)%m(g).length)}function xe(){m(v)===null||m(g).length<=1||J((m(v)+1)%m(g).length)}function be(B){m(p)&&(B.key==="Escape"&&G(),B.key==="ArrowLeft"&&ce(),B.key==="ArrowRight"&&xe())}var Le=p$e();_n("keydown",Dd,be);var tt=ct(Le),he=S(tt);{var Y=B=>{Pu(B,{})},Ce=B=>{var Q=BCe(),X=S(Q);{var j=K=>{var Z=LCe();R(K,Z)},re=K=>{var Z=ICe(),te=D(ct(Z),4),_e=S(te);_e.textContent=`import trackio +trackio.init(project="my-project") +trackio.log({"loss": 0.5}) +trackio.finish()`,R(K,Z)},Me=K=>{var Z=PCe(),te=D(ct(Z),4),_e=S(te);_e.textContent=`import trackio + +trackio.init(project="my-project") +trackio.log({"plot": trackio.Image("figure.png")}) +trackio.log({"clip": trackio.Video("output.mp4")}) +trackio.log({"audio": trackio.Audio("speech.wav")}) + +import pandas as pd +df = pd.DataFrame({"epoch": [0, 1], "acc": [0.9, 0.95]}) +trackio.log({"samples": trackio.Table(dataframe=df)})`,R(K,Z)};ue(X,K=>{n()?r().length===0?K(re,1):K(Me,-1):K(j)})}R(B,Q)},le=B=>{const Q=(ge,ve=bc)=>{var $e=zCe(),Xe=S($e);let Re;var je=D(Xe,2),Ze=S(je);me(Ke=>{Re=al(Xe,"",Re,Ke),ae(Ze,`Run: ${ve()._run??""}, Step: ${ve().step??""}`)},[()=>({background:o(ve())})]),R(ge,$e)};var X=o$e(),j=ct(X);{var re=ge=>{var ve=HCe(),$e=S(ve),Xe=S($e),Re=D(S(Xe),2),je=S(Re),Ze=D(Xe,2),Ke=S(Ze),Qe=S(Ke),nt=D(Ke,2),Ge=D(S(nt),2),qe=S(Ge);qe.value=qe.__value="newest";var oe=D(qe);oe.value=oe.__value="oldest";var fe=D($e,2);gt(fe,21,()=>m(M).images,bt,(Ye,ut,At)=>{var It=UCe(),et=S(It),mt=S(et),vt=D(et,2),Dt=D(S(vt),2),kt=D(vt,2);{var mn=lt=>{var Nt=jCe(),ne=S(Nt);me(()=>ae(ne,m(ut).caption)),R(lt,Nt)};ue(kt,lt=>{m(ut).caption&<(mn)})}var vn=D(kt,2);Q(vn,()=>m(ut)),me(lt=>{ae(mt,m(ut).key),pt(vt,"aria-label",`Open ${m(ut).caption||m(ut).key}`),pt(Dt,"src",lt),pt(Dt,"alt",m(ut).caption||m(ut).key)},[()=>T(m(ut))]),Ne("click",vt,()=>H(m(ut),null,m(C),At)),_n("load",Dt,W),_n("error",Dt,U),R(Ye,It)});var Ie=D(fe,2);{var Je=Ye=>{var ut=qCe();R(Ye,ut)};ue(Ie,Ye=>{m(C).length===0&&Ye(Je)})}var xt=D(Ie,2);{var Et=Ye=>{var ut=WCe(),At=S(ut),It=S(At),et=D(At,2);me(()=>ae(It,`Showing ${m(M).images.length??""} of ${m(C).length??""}`)),Ne("click",et,()=>P("images")),R(Ye,ut)};ue(xt,Ye=>{m(h).imagesae(je,`Images (${m(C).length??""})`)),Ne("click",Qe,Ye=>Ye.stopPropagation()),Ne("keydown",Qe,Ye=>Ye.stopPropagation()),df(Qe,()=>m(d),Ye=>F(d,Ye)),Ne("click",Ge,Ye=>Ye.stopPropagation()),Ne("keydown",Ge,Ye=>Ye.stopPropagation()),q1(Ge,()=>m(f),Ye=>F(f,Ye)),R(ge,ve)};ue(j,ge=>{m(E).images.length>0&&ge(re)})}var Me=D(j,2);{var K=ge=>{var ve=VCe(),$e=S(ve),Xe=D(S($e),2),Re=S(Xe),je=D($e,2);gt(je,21,()=>m(M).videos,bt,(Qe,nt)=>{var Ge=GCe(),qe=S(Ge),oe=S(qe),fe=D(qe,2),Ie=D(fe,2);Q(Ie,()=>m(nt)),me(Je=>{ae(oe,m(nt).key),pt(fe,"src",Je)},[()=>T(m(nt))]),R(Qe,Ge)});var Ze=D(je,2);{var Ke=Qe=>{var nt=YCe(),Ge=S(nt),qe=S(Ge),oe=D(Ge,2);me(()=>ae(qe,`Showing ${m(M).videos.length??""} of ${m(E).videos.length??""}`)),Ne("click",oe,()=>P("videos")),R(Qe,nt)};ue(Ze,Qe=>{m(h).videosae(Re,`Videos (${m(E).videos.length??""})`)),R(ge,ve)};ue(Me,ge=>{m(E).videos.length>0&&ge(K)})}var Z=D(Me,2);{var te=ge=>{var ve=ZCe(),$e=S(ve),Xe=D(S($e),2),Re=S(Xe),je=D($e,2);gt(je,21,()=>m(M).audios,bt,(Qe,nt)=>{var Ge=XCe(),qe=S(Ge),oe=S(qe),fe=D(qe,2);{let Je=ke(()=>T(m(nt)));OCe(fe,{get src(){return m(Je)}})}var Ie=D(fe,2);Q(Ie,()=>m(nt)),me(()=>ae(oe,m(nt).key)),R(Qe,Ge)});var Ze=D(je,2);{var Ke=Qe=>{var nt=KCe(),Ge=S(nt),qe=S(Ge),oe=D(Ge,2);me(()=>ae(qe,`Showing ${m(M).audios.length??""} of ${m(E).audios.length??""}`)),Ne("click",oe,()=>P("audios")),R(Qe,nt)};ue(Ze,Qe=>{m(h).audiosae(Re,`Audio (${m(E).audios.length??""})`)),R(ge,ve)};ue(Z,ge=>{m(E).audios.length>0&&ge(te)})}var _e=D(Z,2);{var ee=ge=>{var ve=a$e(),$e=S(ve),Xe=D(S($e),2),Re=S(Xe),je=D($e,2);gt(je,17,()=>m(M).tables,bt,(Qe,nt)=>{var Ge=i$e(),qe=S(Ge),oe=S(qe),fe=S(oe),Ie=D(oe,2);Q(Ie,()=>m(nt));var Je=D(qe,2),xt=S(Je),Et=S(xt);gt(Et,21,()=>Object.keys(m(nt)._value[0]),bt,(ut,At)=>{var It=JCe(),et=S(It);me(()=>ae(et,m(At))),R(ut,It)});var Ye=D(xt);gt(Ye,21,()=>m(nt)._value,bt,(ut,At)=>{var It=r$e();gt(It,21,()=>Object.values(m(At)),bt,(et,mt)=>{var vt=n$e(),Dt=S(vt);{var kt=ne=>{var Ae=QCe(),St=D(S(Ae),2);me(Ot=>{pt(St,"src",Ot),pt(St,"alt",m(mt).caption||"")},[()=>T(m(mt))]),Ne("click",Ae,()=>H(m(mt),m(nt))),_n("load",St,W),_n("error",St,U),R(ne,Ae)},mn=ke(()=>$(m(mt))),vn=ne=>{var Ae=t$e();gt(Ae,21,()=>m(mt),bt,(St,Ot)=>{var rt=e$e(),at=D(S(rt),2);me(Mt=>{pt(at,"src",Mt),pt(at,"alt",m(Ot).caption||"")},[()=>T(m(Ot))]),Ne("click",rt,()=>H(m(Ot),m(nt))),_n("load",at,W),_n("error",at,U),R(St,rt)}),R(ne,Ae)},lt=ke(()=>L(m(mt))),Nt=ne=>{var Ae=Cw();me(St=>ae(Ae,St),[()=>typeof m(mt)=="string"&&m(mt).length>s()?m(mt).slice(0,s())+"…":m(mt)??""]),R(ne,Ae)};ue(Dt,ne=>{m(mn)?ne(kt):m(lt)?ne(vn,1):ne(Nt,-1)})}R(et,vt)}),R(ut,It)}),me(()=>ae(fe,m(nt).key)),R(Qe,Ge)});var Ze=D(je,2);{var Ke=Qe=>{var nt=s$e(),Ge=S(nt),qe=S(Ge),oe=D(Ge,2);me(()=>ae(qe,`Showing ${m(M).tables.length??""} of ${m(E).tables.length??""}`)),Ne("click",oe,()=>P("tables")),R(Qe,nt)};ue(Ze,Qe=>{m(h).tablesae(Re,`Tables (${m(E).tables.length??""})`)),R(ge,ve)};ue(_e,ge=>{m(E).tables.length>0&&ge(ee)})}R(B,X)};ue(he,B=>{m(y)?B(Y):m(N)?B(le,-1):B(Ce,1)})}var V=D(tt,2);{var q=B=>{var Q=h$e(),X=S(Q),j=S(X),re=D(j,2);{var Me=qe=>{var oe=l$e();Ne("click",oe,ce),R(qe,oe)};ue(re,qe=>{m(g).length>1&&qe(Me)})}var K=D(re,2),Z=D(S(K),2),te=D(K,2);{var _e=qe=>{var oe=u$e();Ne("click",oe,xe),R(qe,oe)};ue(te,qe=>{m(g).length>1&&qe(_e)})}var ee=D(te,2),ge=S(ee);{var ve=qe=>{var oe=c$e(),fe=S(oe);me(()=>ae(fe,m(p).key)),R(qe,oe)};ue(ge,qe=>{m(p).key&&qe(ve)})}var $e=D(ge,2);{var Xe=qe=>{var oe=f$e(),fe=S(oe);me(()=>ae(fe,m(p).caption)),R(qe,oe)};ue($e,qe=>{m(p).caption&&qe(Xe)})}var Re=D($e,2),je=S(Re);let Ze;var Ke=D(je,2),Qe=S(Ke),nt=D(Ke,2);{var Ge=qe=>{var oe=d$e(),fe=S(oe);me(()=>ae(fe,`${m(v)+1} / ${m(g).length??""}`)),R(qe,oe)};ue(nt,qe=>{m(v)!==null&&m(g).length>1&&qe(Ge)})}me((qe,oe)=>{pt(Z,"src",qe),pt(Z,"alt",m(p).caption||m(p).key||"Image preview"),Ze=al(je,"",Ze,oe),ae(Qe,`Run: ${m(p)._run??""}, Step: ${m(p).step??""}`)},[()=>T(m(p)),()=>({background:o(m(p))})]),Ne("click",Q,G),Ne("click",X,qe=>qe.stopPropagation()),Ne("keydown",X,qe=>qe.stopPropagation()),Ne("click",j,G),_n("load",Z,W),_n("error",Z,U),R(B,Q)};ue(V,B=>{m(p)&&B(q)})}R(e,Le),un()}or(["click","keydown"]);var m$e=z(`

      No alerts or reports yet

      Alerts are recorded when your training script calls trackio.alert(). + Reports are logged as Markdown via trackio.log().

      `),v$e=z('
      '),y$e=z('

      '),b$e=z('

      No alerts for this level.

      '),_$e=z(' '),x$e=z(' '),w$e=z(''),E$e=z('
      '),A$e=z('

      '),k$e=z(" ",1),S$e=z('
      ');function C$e(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"selectedRuns",19,()=>[]),i=ie(yt([])),s=ie(yt([])),a=ie(null),o=ie(!1);const l={info:"🔵",warn:"🟡",error:"🔴"};function u(x){if(!x)return"";let w=x.replace(/&/g,"&").replace(//g,">");return w=w.replace(/^### (.+)$/gm,"

      $1

      "),w=w.replace(/^## (.+)$/gm,"

      $1

      "),w=w.replace(/^# (.+)$/gm,"

      $1

      "),w=w.replace(/\*\*(.+?)\*\*/g,"$1"),w=w.replace(/`([^`]+)`/g,"$1"),w=w.replace(/^- (.+)$/gm,"
    • $1
    • "),w=w.replace(/(
    • .*<\/li>\n?)+/gs,A=>`
        ${A}
      `),w=w.replace(/\n{2,}/g,"

      "),w=`

      ${w}

      `,w=w.replace(/

      \s*()/g,"$1"),w=w.replace(/(<\/h[234]>)\s*<\/p>/g,"$1"),w=w.replace(/

      \s*(

        )/g,"$1"),w=w.replace(/(<\/ul>)\s*<\/p>/g,"$1"),w=w.replace(/

        \s*<\/p>/g,""),w}let c=ke(()=>m(a)?m(i).filter(x=>x.level===m(a)):m(i));async function f(){if(!n()){F(i,[],!0),F(s,[],!0);return}F(o,!0);try{const x=await MW(n(),null,null,null),w=new Set(r().map(k=>k.name));F(i,(x||[]).filter(k=>!k.run||w.has(k.run)),!0);const A=r(),E=[];for(const k of A)try{const C=await FW(n(),k);if(C)for(const M of C)for(const[N,P]of Object.entries(M))P&&typeof P=="object"&&P._type==="trackio.markdown"&&E.push({key:N,run:k.name,step:M.step,content:P._value||""})}catch{}F(s,E,!0)}catch(x){console.error("Failed to load alerts:",x),F(i,[],!0)}finally{F(o,!1)}}Lt(()=>{n(),r(),f()});function d(x){if(!x)return"";try{return new Date(x).toLocaleString()}catch{return x}}let h=["Level","Run","Title","Text","Step","Time"],p=ke(()=>m(c).map(x=>[`${l[x.level]||""} ${x.level}`,x.run||"",x.title,x.text||"",x.step??"",d(x.timestamp)]));var g=S$e(),v=S(g);{var y=x=>{Pu(x,{})},b=x=>{var w=m$e(),A=D(S(w),4),E=S(A);E.textContent=`import trackio +from trackio import AlertLevel + +trackio.init(project="my-project") +trackio.alert("Low validation loss", text="Consider saving a checkpoint.", level=AlertLevel.INFO) +trackio.log({"reports/summary": trackio.Markdown("# My Report\\nResults look good.")})`,R(x,w)},_=x=>{var w=k$e(),A=ct(w);{var E=M=>{var N=y$e(),P=S(N),I=S(P),T=D(P,2);gt(T,17,()=>m(s),bt,($,L)=>{var W=v$e(),U=S(W),O=S(U),H=D(U,2);xG(H,()=>u(m(L).content),!0),me(()=>ae(O,`${m(L).key??""} · ${m(L).run??""} · step ${m(L).step??""}`)),R($,W)}),me(()=>ae(I,`Reports (${m(s).length??""})`)),R(M,N)};ue(A,M=>{m(s).length>0&&M(E)})}var k=D(A,2);{var C=M=>{var N=A$e(),P=S(N),I=S(P),T=D(P,2),$=S(T),L=S($),W=S(L);let U;var O=D(W,2);let H;var G=D(O,2);let J;var ce=D(G,2);let xe;var be=D(T,2);{var Le=he=>{var Y=b$e();R(he,Y)},tt=he=>{var Y=E$e(),Ce=S(Y),le=S(Ce);gt(le,21,()=>h,bt,(q,B)=>{var Q=_$e(),X=S(Q);me(()=>ae(X,m(B))),R(q,Q)});var V=D(Ce);gt(V,21,()=>m(p),bt,(q,B)=>{var Q=w$e();gt(Q,21,()=>m(B),bt,(X,j)=>{var re=x$e(),Me=S(re);me(()=>ae(Me,m(j))),R(X,re)}),R(q,Q)}),R(he,Y)};ue(be,he=>{m(c).length===0?he(Le):he(tt,-1)})}me(()=>{ae(I,`Alerts (${m(i).length??""})`),U=qt(W,1,"pill svelte-iufsej",null,U,{active:m(a)===null}),H=qt(O,1,"pill svelte-iufsej",null,H,{active:m(a)==="info"}),J=qt(G,1,"pill svelte-iufsej",null,J,{active:m(a)==="warn"}),xe=qt(ce,1,"pill svelte-iufsej",null,xe,{active:m(a)==="error"})}),Ne("click",W,()=>F(a,null)),Ne("click",O,()=>F(a,"info")),Ne("click",G,()=>F(a,"warn")),Ne("click",ce,()=>F(a,"error")),R(M,N)};ue(k,M=>{m(i).length>0&&M(C)})}R(x,w)};ue(v,x=>{m(o)?x(y):m(i).length===0&&m(s).length===0?x(b,1):x(_,-1)})}R(e,g),un()}or(["click"]);var $$e=z('

        No runs in this project

        Runs are created when you call trackio.init() and log at least one step. Example:

        Refresh this page or wait for the dashboard to poll; new runs appear in the table with step counts.

        '),F$e=z('
        '),D$e=z('Artifacts'),M$e=z(''),T$e=z('
        '),R$e=z(' '),N$e=z(' '),O$e=z('
        '),L$e=z(''),I$e=z(''),P$e=z('
        '),B$e=z('
        ActionsRun NameStepsLast Step
        ',1),z$e=z('
        ');function j$e(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"runs",19,()=>[]),i=se(t,"filterText",3,""),s=se(t,"onRunsChanged",3,null),a=se(t,"runMutationAllowed",3,!0),o=ke(a),l=ke(()=>o0(r())),u=ie(yt([])),c=ie(!1),f=ie(-1),d=ie(""),h=ie(null),p=ke(()=>{if(!i()||!i().trim())return m(u);const I=new Set(Iy(m(u).map(T=>T.name),i()));return m(u).filter(T=>I.has(T.name))}),g=ke(()=>m(u).some(I=>I.outputs>0||I.inputs>0)),v=0;function y(I){const T=new Map,$=new Map;for(const L of I){const W=L.run_id!=null?T:$,U=L.run_id!=null?L.run_id:L.run_name,O=W.get(U)??{inputs:0,outputs:0};O.inputs+=L.input||0,O.outputs+=L.output||0,W.set(U,O)}return{byId:T,byName:$}}function b(I,T,$){const L=T.id!=null?I.byId.get(T.id):null,W=($.get(T.name)??0)===1,U=T.id==null||W?I.byName.get(T.name):null;return{inputs:((L==null?void 0:L.inputs)??0)+((U==null?void 0:U.inputs)??0),outputs:((L==null?void 0:L.outputs)??0)+((U==null?void 0:U.outputs)??0)}}async function _(){const I=++v;if(!n()){F(u,[],!0),F(c,!1);return}F(c,!0);try{const $=(await T3e(n())).runs||[],[L,W]=await Promise.all([Promise.all($.map(H=>DW(n(),H))),P3e(n()).catch(()=>[])]);if(I!==v)return;const U=y(W),O=new Map;for(const H of $)O.set(H.name,(O.get(H.name)??0)+1);F(u,L.map((H,G)=>({id:$[G].id,name:$[G].name,numSteps:H.num_logs||0,lastStep:H.last_step||0,...b(U,$[G],O)})),!0)}catch(T){I===v&&console.error("Failed to load runs:",T)}finally{I===v&&F(c,!1)}}Lt(()=>{n(),_()});async function x(I){if(m(o)&&confirm(`Delete run "${I.name}"? This cannot be undone.`))try{await q3e(n(),I),await _(),s()&&s()()}catch(T){console.error("Failed to delete run:",T)}}async function w(I,T){var $,L;m(o)&&(F(f,I,!0),F(d,T,!0),await Mi(),($=m(h))==null||$.focus(),(L=m(h))==null||L.select())}async function A(I){if(!m(o))return;const T=m(d).trim();if(!T||T===I.name){F(f,-1);return}try{await W3e(n(),I,T),F(f,-1),await _(),s()&&s()()}catch($){console.error("Failed to rename run:",$)}}function E(I,T){I.key==="Enter"&&A(T),I.key==="Escape"&&F(f,-1)}var k=z$e(),C=S(k);{var M=I=>{Pu(I,{})},N=I=>{var T=$$e(),$=D(S(T),4),L=S($);L.textContent=`import trackio +trackio.init(project="my-project") +for i in range(10): + trackio.log({"loss": 1 / (i + 1)}) +trackio.finish()`,R(I,T)},P=I=>{var T=B$e(),$=ct(T);{var L=ce=>{var xe=F$e(),be=S(xe),Le=S(be);me(()=>ae(Le,`${m(p).length??""} of ${m(u).length??""} runs`)),R(ce,xe)};ue($,ce=>{i()&&ce(L)})}var W=D($,2),U=S(W),O=S(U),H=D(S(O),4);{var G=ce=>{var xe=D$e();R(ce,xe)};ue(H,ce=>{m(g)&&ce(G)})}var J=D(U);gt(J,21,()=>m(p),bt,(ce,xe,be)=>{var Le=P$e(),tt=S(Le),he=S(tt),Y=S(he),Ce=D(Y,2),le=D(tt),V=S(le);{var q=Z=>{var te=M$e();es(te,_e=>F(h,_e),()=>m(h)),Ne("keydown",te,_e=>E(_e,m(xe))),_n("blur",te,()=>A(m(xe))),df(te,()=>m(d),_e=>F(d,_e)),R(Z,te)},B=Z=>{var te=T$e(),_e=S(te);let ee;var ge=D(_e,2),ve=S(ge);me(()=>{ee=al(_e,"",ee,{background:m(l)[m(xe).id??m(xe).name]??"#9ca3af"}),ae(ve,m(xe).name)}),Ne("click",ge,()=>Rw(m(xe).name,m(xe).id)),R(Z,te)};ue(V,Z=>{m(f)===be?Z(q):Z(B,-1)})}var Q=D(le),X=S(Q),j=D(Q),re=S(j),Me=D(j);{var K=Z=>{var te=I$e(),_e=S(te);{var ee=ve=>{var $e=O$e(),Xe=S($e);{var Re=Ke=>{var Qe=R$e(),nt=S(Qe);me(()=>{pt(Qe,"title",`${m(xe).outputs??""} output artifact${m(xe).outputs===1?"":"s"} (produced)`),ae(nt,`↑ ${m(xe).outputs??""}`)}),R(Ke,Qe)};ue(Xe,Ke=>{m(xe).outputs>0&&Ke(Re)})}var je=D(Xe,2);{var Ze=Ke=>{var Qe=N$e(),nt=S(Qe);me(()=>{pt(Qe,"title",`${m(xe).inputs??""} input artifact${m(xe).inputs===1?"":"s"} (consumed)`),ae(nt,`↓ ${m(xe).inputs??""}`)}),R(Ke,Qe)};ue(je,Ke=>{m(xe).inputs>0&&Ke(Ze)})}R(ve,$e)},ge=ve=>{var $e=L$e();R(ve,$e)};ue(_e,ve=>{m(xe).outputs>0||m(xe).inputs>0?ve(ee):ve(ge,-1)})}R(Z,te)};ue(Me,Z=>{m(g)&&Z(K)})}me(()=>{pt(Y,"title",m(o)?"Rename":"Sign in with Hugging Face (write access) to rename runs"),Y.disabled=!m(o),pt(Ce,"title",m(o)?"Delete":"Sign in with Hugging Face (write access) to delete runs"),Ce.disabled=!m(o),ae(X,m(xe).numSteps),ae(re,m(xe).lastStep)}),Ne("click",Y,()=>w(be,m(xe).name)),Ne("click",Ce,()=>x(m(xe))),R(ce,Le)}),R(I,T)};ue(C,I=>{m(c)?I(M):m(u).length===0?I(N,1):I(P,-1)})}R(e,k),un()}or(["click","keydown"]);var U$e=z(''),q$e=z('');function Dy(e,t){let n=se(t,"depth",3,0);var r=Mn(),i=ct(r);{var s=a=>{var o=q$e();gt(o,21,()=>Array.from({length:n()}),bt,(l,u)=>{var c=U$e();R(l,c)}),R(a,o)};ue(i,a=>{n()>0&&a(s)})}R(e,r)}function My(e){return e==null?"":e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:`${(e/(1024*1024*1024)).toFixed(2)} GB`}var W$e=z(' '),H$e=z('
        '),G$e=z('
        ',1),Y$e=z('
        ',1),V$e=z('Produced by ',1),X$e=z(' ',1),K$e=z('Used by ',1),Z$e=z(" ",1),J$e=z('
        Loading…
        '),Q$e=z('
        Failed to load this version.
        '),e5e=z(" "),t5e=z('Description ',1),n5e=z('
        Created Digest
        '),r5e=z('
        '),i5e=z('

        · ·
        trackio.use_artifact( )
        ',1),s5e=z(' ',1),a5e=z('
        Digest
        ',1),o5e=z("
        ");function RW(e,t){ln(t,!0);const n=O=>{var H=H$e();gt(H,21,()=>m(u).manifest||[],bt,(G,J)=>{var ce=W$e(),xe=S(ce),be=S(xe),Le=D(xe,4),tt=S(Le),he=D(Le,2),Y=S(he);me((Ce,le,V)=>{pt(ce,"href",Ce),pt(ce,"download",m(J).path),pt(ce,"title",`Download ${m(J).path??""}`),ae(be,m(J).path),pt(Le,"title",m(J).digest),ae(tt,`${le??""}…`),ae(Y,V)},[()=>z3e(s(),m(J).digest),()=>{var Ce;return(Ce=m(J).digest)==null?void 0:Ce.slice(0,12)},()=>My(m(J).size)]),R(G,ce)}),R(O,H)},r=(O,H=bc,G=bc,J=bc)=>{var ce=Mn(),xe=ct(ce);gt(xe,17,H,bt,(be,Le)=>{var tt=ke(()=>pg(m(Le),2));let he=()=>m(tt)[0],Y=()=>m(tt)[1];var Ce=Mn(),le=ct(Ce);{var V=Q=>{const X=ke(()=>[...J(),he()]),j=ke(()=>k(m(X),Y(),G()));var re=G$e(),Me=ct(re),K=S(Me);Dy(K,{get depth(){return G()}});var Z=D(K,2),te=S(Z);let _e;var ee=D(te,2),ge=S(ee),ve=D(ee,2),$e=S(ve),Xe=D(Me,2),Re=S(Xe),je=D(Xe,2);{var Ze=Ke=>{{let Qe=ke(()=>Object.entries(Y()));r(Ke,()=>m(Qe),()=>G()+1,()=>m(X))}};ue(je,Ke=>{m(j)||Ke(Ze)})}me((Ke,Qe)=>{_e=qt(te,1,"meta-chevron svelte-pa6cr",null,_e,{open:!m(j)}),ae(ge,he()),ae($e,Ke),ae(Re,Qe)},[()=>Object.keys(Y()).length,()=>m(j)?E(Y()):""]),Ne("click",Z,()=>C(m(X),Y(),G())),R(Q,re)},q=ke(()=>_(Y())),B=Q=>{var X=Y$e(),j=ct(X),re=S(j);Dy(re,{get depth(){return G()}});var Me=D(re,4),K=S(Me),Z=D(j,2),te=S(Z);me(_e=>{ae(K,he()),ae(te,_e)},[()=>x(Y())]),R(Q,X)};ue(le,Q=>{m(q)?Q(V):Q(B,-1)})}R(be,Ce)}),R(O,ce)},i=O=>{var H=Z$e(),G=ct(H);{var J=be=>{var Le=V$e(),tt=D(ct(Le),2),he=S(tt),Y=S(he);me(()=>ae(Y,m(u).producer_run_name)),Ne("click",he,()=>Rw(m(u).producer_run_name,m(u).producer_run_id)),R(be,Le)};ue(G,be=>{m(u).producer_run_name&&be(J)})}var ce=D(G,2);{var xe=be=>{var Le=K$e(),tt=D(ct(Le),2);gt(tt,21,()=>m(c),bt,(he,Y,Ce)=>{var le=X$e(),V=ct(le),q=S(V),B=D(V,1,!0);me(()=>{ae(q,m(Y).run_name??m(Y).run_id),ae(B,CeRw(m(Y).run_name,m(Y).run_id)),R(he,le)}),R(be,Le)};ue(ce,be=>{m(c).length&&be(xe)})}R(O,H)};let s=se(t,"project",3,null),a=se(t,"name",3,null),o=se(t,"version",3,null),l=se(t,"variant",3,"inline"),u=ie(null),c=ie(yt([])),f=ie(!1),d=ie(!1),h=ie(""),p=null,g=ie(yt({}));function v(O){if(!O)return"";try{return new Date(O).toLocaleString(void 0,{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return O}}function y(O){return O!==null&&typeof O=="object"&&!Array.isArray(O)}function b(O){return Array.isArray(O)&&O.every(H=>H===null||typeof H!="object")}function _(O){return y(O)||Array.isArray(O)&&!b(O)}function x(O){return b(O)?JSON.stringify(O):O===null?"null":String(O)}function w(O){return JSON.stringify(O)}function A(O,H){return H>=2||Object.keys(O).length>12}function E(O){const H=JSON.stringify(O);return H.length>80?H.slice(0,80)+"…":H}function k(O,H,G){return m(g)[w(O)]??A(H,G)}function C(O,H,G){m(g)[w(O)]=!k(O,H,G)}async function M(O,H){if(O){try{await navigator.clipboard.writeText(O)}catch{return}F(h,H,!0),p&&clearTimeout(p),p=setTimeout(()=>{m(h)===H&&F(h,"")},1500)}}let N=ke(()=>m(u)?`trackio.use_artifact("${m(u).name}:v${m(u).version}")`:"");async function P(){if(F(u,null),F(c,[],!0),F(d,!1),F(g,{},!0),!(!s()||!a()||o()==null)){F(f,!0);try{const O=await L3e(s(),a(),`v${o()}`);F(u,O,!0),(O==null?void 0:O.version_id)!=null&&F(c,await B3e(s(),O.version_id)||[],!0)}catch{F(d,!0)}finally{F(f,!1)}}}Lt(()=>{s(),a(),o(),P()});var I=o5e(),T=S(I);{var $=O=>{var H=J$e();R(O,H)},L=O=>{var H=Q$e();R(O,H)},W=O=>{var H=i5e(),G=ct(H),J=S(G),ce=S(J),xe=S(ce),be=D(ce,2),Le=S(be),tt=D(be,2);gt(tt,17,()=>m(u).aliases,bt,(ve,$e)=>{var Xe=e5e();let Re;var je=S(Xe);me(()=>{Re=qt(Xe,1,"alias-pill svelte-pa6cr",null,Re,{latest:m($e)==="latest"}),ae(je,m($e))}),R(ve,Xe)});var he=D(J,2),Y=S(he),Ce=S(Y),le=D(Y,4),V=S(le),q=D(le,4),B=S(q),Q=D(he,2),X=S(Q),j=D(S(X),4),re=S(j),Me=D(X,2),K=S(Me),Z=D(G,2);gd(Z,{label:"Overview",children:(ve,$e)=>{var Xe=n5e(),Re=S(Xe);{var je=Ie=>{var Je=t5e(),xt=D(ct(Je),2),Et=S(xt);me(()=>ae(Et,m(u).description)),R(Ie,Je)};ue(Re,Ie=>{m(u).description&&Ie(je)})}var Ze=D(Re,2);i(Ze);var Ke=D(Ze,4),Qe=S(Ke),nt=D(Ke,4),Ge=S(nt),qe=S(Ge),oe=D(Ge,2),fe=S(oe);me((Ie,Je)=>{ae(Qe,Ie),pt(Ge,"title",m(u).manifest_digest),ae(qe,`${Je??""}…`),ae(fe,m(h)==="digest"?"Copied":"Copy")},[()=>v(m(u).created_at),()=>{var Ie;return(Ie=m(u).manifest_digest)==null?void 0:Ie.slice(0,16)}]),Ne("click",oe,()=>M(m(u).manifest_digest,"digest")),R(ve,Xe)},$$slots:{default:!0}});var te=D(Z,2);{var _e=ve=>{{let $e=ke(()=>Object.keys(m(u).metadata).length);gd(ve,{get label(){return`Metadata (${m($e)??""})`},children:(Xe,Re)=>{var je=r5e(),Ze=S(je);{let Ke=ke(()=>Object.entries(m(u).metadata));r(Ze,()=>m(Ke),()=>0,()=>[])}R(Xe,je)},$$slots:{default:!0}})}},ee=ke(()=>m(u).metadata&&Object.keys(m(u).metadata).length);ue(te,ve=>{m(ee)&&ve(_e)})}var ge=D(te,2);gd(ge,{get label(){return`Files (${(m(u).manifest||[]).length??""})`},children:(ve,$e)=>{n(ve)},$$slots:{default:!0}}),me(ve=>{ae(xe,m(u).name),ae(Le,`v${m(u).version??""}`),ae(Ce,m(u).type),ae(V,`${(m(u).manifest||[]).length??""} + ${(m(u).manifest||[]).length===1?"file":"files"}`),ae(B,ve),ae(re,`"${m(u).name??""}:v${m(u).version??""}"`),ae(K,m(h)==="use"?"Copied":"Copy")},[()=>My(m(u).size_bytes)]),Ne("click",Me,()=>M(m(N),"use")),R(O,H)},U=O=>{var H=a5e(),G=ct(H),J=S(G);i(J);var ce=D(J,4),xe=S(ce),be=D(ce,2);{var Le=Y=>{var Ce=Mn(),le=ct(Ce);gt(le,17,()=>Object.entries(m(u).metadata),bt,(V,q)=>{var B=ke(()=>pg(m(q),2));let Q=()=>m(B)[0],X=()=>m(B)[1];var j=s5e(),re=ct(j),Me=S(re),K=D(re,2),Z=S(K);me(te=>{ae(Me,Q()),ae(Z,te)},[()=>typeof X()=="object"?JSON.stringify(X()):String(X())]),R(V,j)}),R(Y,Ce)},tt=ke(()=>m(u).metadata&&Object.keys(m(u).metadata).length);ue(be,Y=>{m(tt)&&Y(Le)})}var he=D(G,2);n(he),me(Y=>ae(xe,`${Y??""}…`),[()=>{var Y;return(Y=m(u).manifest_digest)==null?void 0:Y.slice(0,16)}]),R(O,H)};ue(T,O=>{m(f)?O($):m(d)||!m(u)?O(L,1):l()==="panel"?O(W,2):O(U,-1)})}me(()=>qt(I,1,EG(l()==="panel"?"panel":"version-detail"),"svelte-pa6cr")),R(e,I),un()}or(["click"]);var l5e=z('
        '),u5e=z(`

        Open a run

        Choose a run from the Runs page or follow a run name from the sidebar. This view shows the + project name, log count, last step, metric keys, and any logged config.

        Config passed to trackio.init() appears under Configuration when present.

        `),c5e=z('

        Configuration

         
        ',1),f5e=z('

        Output artifacts

        ',1),d5e=z('

        Input artifacts

        ',1),h5e=z('

        Project
        Total Logs
        Last Step
        Metrics
        '),p5e=z('
        ');function g5e(e,t){ln(t,!0);const n=(w,A=bc,E=bc)=>{const k=ke(()=>`${E()}:${A().name}@v${A().version}`);var C=l5e(),M=S(C),N=S(M),P=S(N);let I;var T=D(P,2),$=S(T),L=D($),W=S(L),U=D(T,2),O=S(U),H=D(U,2),G=S(H),J=D(N,2),ce=D(M,2);{var xe=be=>{RW(be,{get project(){return r()},get name(){return A().name},get version(){return A().version}})};ue(ce,be=>{m(u)[m(k)]&&be(xe)})}me(be=>{I=qt(P,1,"chevron svelte-1bpgsx2",null,I,{open:m(u)[m(k)]}),ae($,A().name),ae(W,`:v${A().version??""}`),ae(O,A().type),ae(G,be),pt(J,"aria-label",`Open ${A().name??""} v${A().version??""} in the Artifacts tab`)},[()=>My(A().size_bytes)]),Ne("click",N,()=>c(m(k))),Ne("click",J,()=>f(A().name,A().version)),R(w,C)};let r=se(t,"project",3,null),i=ie(null),s=ie(null),a=ie(null),o=ie(!1),l=ie(yt({input:[],output:[]})),u=ie(yt({}));function c(w){m(u)[w]=!m(u)[w]}function f(w,A){GR(w,A),mg("artifacts")}let d=0;function h(){F(s,er("selected_run_id"),!0),F(i,er("selected_run"),!0)}Lt(()=>(h(),window.addEventListener("popstate",h),()=>window.removeEventListener("popstate",h)));async function p(){const w=++d;if(F(u,{},!0),!r()||!m(i)&&!m(s)){F(a,null),F(l,{input:[],output:[]},!0),F(o,!1);return}F(o,!0);const A=m(s)?{id:m(s),name:m(i)}:m(i),E=I3e(r(),A).catch(()=>({input:[],output:[]}));try{const C=await DW(r(),A);if(w!==d)return;F(a,C,!0),C!=null&&C.run&&F(i,C.run,!0)}catch(C){w===d&&console.error("Failed to load run detail:",C)}finally{w===d&&F(o,!1)}const k=await E;w===d&&F(l,k,!0)}Lt(()=>{r(),m(i),m(s),p()});var g=p5e(),v=S(g),y=D(v,2);{var b=w=>{Pu(w,{})},_=w=>{var A=u5e(),E=D(S(A),4),k=S(E);k.textContent=`import trackio +trackio.init(project="my-project", config={"lr": 1e-3}) +trackio.log({"loss": 0.5}) +trackio.finish()`,R(w,A)},x=w=>{var A=h5e(),E=S(A),k=S(E),C=D(E,2),M=S(C),N=D(S(M),2),P=S(N),I=D(M,2),T=D(S(I),2),$=S(T),L=D(I,2),W=D(S(L),2),U=S(W),O=D(L,2),H=D(S(O),2),G=S(H),J=D(C,2);{var ce=he=>{var Y=c5e(),Ce=D(ct(Y),2),le=S(Ce);me(V=>ae(le,V),[()=>JSON.stringify(m(a).config,null,2)]),R(he,Y)};ue(J,he=>{m(a).config&&he(ce)})}var xe=D(J,2);{var be=he=>{var Y=f5e(),Ce=D(ct(Y),2);gt(Ce,21,()=>m(l).output,bt,(le,V)=>{n(le,()=>m(V),()=>"out")}),R(he,Y)};ue(xe,he=>{m(l).output.length>0&&he(be)})}var Le=D(xe,2);{var tt=he=>{var Y=d5e(),Ce=D(ct(Y),2);gt(Ce,21,()=>m(l).input,bt,(le,V)=>{n(le,()=>m(V),()=>"in")}),R(he,Y)};ue(Le,he=>{m(l).input.length>0&&he(tt)})}me(he=>{ae(k,m(a).run),ae(P,m(a).project),ae($,m(a).num_logs),ae(U,m(a).last_step??"N/A"),ae(G,he)},[()=>m(a).metrics&&m(a).metrics.length?m(a).metrics.join(", "):"N/A"]),R(w,A)};ue(y,w=>{m(o)?w(b):m(a)?w(x,-1):w(_,1)})}Ne("click",v,()=>mg("runs")),R(e,g),un()}or(["click"]);var m5e=z('

        No project files yet

        Files are stored at the project level (not tied to a single run). After trackio.init(), copy artifacts into the project with trackio.save():

        Paths can be a single file or a glob. Saved files will list here for download.

        '),v5e=z(' '),y5e=z('
        Loading preview...
        '),b5e=z('
         
        '),_5e=z('
        Preview not available. Download the file instead.
        '),x5e=z('
        '),w5e=z('
        '),E5e=z('

        Files

        Showing files saved across all runs in this project.

        ',1),A5e=z('
        ');function k5e(e,t){ln(t,!0);let n=se(t,"project",3,null),r=ie(yt([])),i=ie(!1),s=ie(null),a=ie(null),o=ie(!1);const l=new Set(["txt","md","json","yml","yaml","toml","ini","cfg","csv","tsv","xml","html","css","js","py","sh","log","conf","env","gitignore","dockerfile"]);function u(y){const b=y.split(".").pop().toLowerCase();return l.has(b)}async function c(y){if(m(s)===y.name){F(s,null),F(a,null);return}if(F(s,y.name,!0),!u(y.name)){F(a,null);return}F(o,!0);try{const b=fw(y.path),_=await fetch(b);if(!_.ok)throw new Error("fetch failed");const x=await _.text();F(a,x.length>5e4?x.slice(0,5e4)+` + +… (truncated)`:x,!0)}catch{F(a,null)}finally{F(o,!1)}}async function f(){if(!n()){F(r,[],!0);return}F(i,!0);try{F(r,await O3e(n()),!0)}catch{F(r,[],!0)}finally{F(i,!1)}}Lt(()=>{n(),f()});var d=A5e(),h=S(d);{var p=y=>{Pu(y,{})},g=y=>{var b=m5e(),_=D(S(b),4),x=S(_);x.textContent=`import trackio + +trackio.init(project="my-project") +trackio.save("config.yaml") +trackio.save("checkpoints/*.pt")`,R(y,b)},v=y=>{var b=E5e(),_=D(ct(b),4);gt(_,21,()=>m(r),bt,(x,w)=>{var A=w5e();let E;var k=S(A),C=S(k),M=S(C),N=S(M),P=D(M),I=D(C,2),T=S(I);{var $=O=>{var H=v5e(),G=S(H);me(J=>ae(G,J),[()=>My(m(w).size)]),R(O,H)};ue(T,O=>{m(w).size!=null&&O($)})}var L=D(T,2),W=D(k,2);{var U=O=>{var H=x5e(),G=S(H);{var J=be=>{var Le=y5e();R(be,Le)},ce=be=>{var Le=b5e(),tt=S(Le);me(()=>ae(tt,m(a))),R(be,Le)},xe=be=>{var Le=_5e(),tt=D(S(Le));me(he=>pt(tt,"href",he),[()=>fw(m(w).path)]),R(be,Le)};ue(G,be=>{m(o)?be(J):m(a)!=null?be(ce,1):be(xe,-1)})}R(O,H)};ue(W,O=>{m(s)===m(w).name&&O(U)})}me((O,H)=>{E=qt(A,1,"file-item svelte-1xvfk9n",null,E,{expanded:m(s)===m(w).name}),ae(N,O),ae(P,` ${m(w).name??""}`),pt(L,"href",H)},[()=>u(m(w).name)?"📄":"📦",()=>fw(m(w).path)]),Ne("click",C,()=>c(m(w))),R(x,A)}),R(y,b)};ue(h,y=>{m(i)?y(p):m(r).length===0?y(g,1):y(v,-1)})}R(e,d),un()}or(["click"]);const PT=e=>{var t=S5e();R(e,t)};var S5e=ri(''),C5e=z(''),$5e=z('
        Loading…
        '),F5e=z(`
        Couldn't load artifacts.
        `),D5e=z('
        No artifacts in this project.
        '),M5e=z('
        '),T5e=z(" "),R5e=z(''),N5e=z('
        '),O5e=z('
        '),L5e=z('');function I5e(e,t){ln(t,!0);let n=se(t,"project",15,null),r=se(t,"projects",19,()=>[]),i=se(t,"projectLocked",3,!1),s=se(t,"logoUrls",3,void 0),a=se(t,"darkMode",3,!1),o=se(t,"selection",15,null),l=se(t,"empty",15,!1),u=ie(yt([])),c=ie(!1),f=ie(!1),d=ie(""),h=ie(yt({})),p=ie(yt({}));function g(he,Y){return`${he}@v${Y}`}let v=ke(()=>{const he=m(d).trim().toLowerCase(),Y=new Map;for(const Ce of m(u))he&&!Ce.name.toLowerCase().includes(he)&&!Ce.type.toLowerCase().includes(he)||(Y.has(Ce.type)||Y.set(Ce.type,[]),Y.get(Ce.type).push(Ce));return[...Y.entries()].map(([Ce,le])=>({type:Ce,artifacts:le}))}),y=ke(()=>m(d).trim().length>0);function b(he){return m(y)||m(h)[he]!==!1}function _(he){return m(y)||!!m(p)[he]}function x(he){m(y)||(m(h)[he]=!b(he))}function w(he){m(y)||(m(p)[he]=!m(p)[he])}function A(he,Y){o({name:he.name,version:Y.version}),GR(he.name,Y.version)}function E(he,Y){return o()&&o().name===he&&o().version===Y}async function k(){var le;const he=YR();let Y=he.name?m(u).find(V=>V.name===he.name):null;if(Y||(Y=m(u)[0]),!Y||!Y.versions.length)return;let Ce=he.version!=null?Y.versions.find(V=>V.version===he.version):null;Ce||(Ce=Y.versions[0]),m(p)[Y.name]=!0,A(Y,Ce),await Mi(),(le=document.getElementById("tree-"+g(Y.name,Ce.version)))==null||le.scrollIntoView({block:"nearest"})}let C=0;async function M(){const he=++C;if(F(h,{},!0),F(p,{},!0),o(null),l(!1),F(f,!1),!n()){F(u,[],!0),F(c,!1);return}F(c,!0);try{const Y=await IT(n());if(he!==C)return;F(u,Y,!0)}catch{if(he!==C)return;F(u,[],!0),F(f,!0)}finally{he===C&&F(c,!1)}l(!m(f)&&m(u).length===0),!m(f)&&m(u).length&&await k()}async function N(){if(!n()||m(c))return;const he=++C,Y=await IT(n()).catch(()=>null);Y==null||he!==C||(JSON.stringify(Y)!==JSON.stringify(m(u))&&F(u,Y,!0),F(f,!1),l(m(u).length===0),!o()&&m(u).length&&await k())}Lt(()=>{n(),M()}),Lt(()=>{const he=setInterval(()=>{t_()||e_()||N()},SW());return()=>clearInterval(he)});var P=L5e(),I=S(P),T=S(I);PR(T,{get logoUrls(){return s()},get darkMode(){return a()}});var $=D(T,2);LR($,{get projects(){return r()},get projectLocked(){return i()},get selectedProject(){return n()},set selectedProject(he){n(he)}});var L=D($,2),W=D(S(L),2),U=D(S(W),2),O=D(U,2);{var H=he=>{var Y=C5e();Ne("click",Y,()=>F(d,"")),R(he,Y)};ue(O,he=>{m(d)&&he(H)})}var G=D(I,2),J=S(G);{var ce=he=>{var Y=$5e();R(he,Y)},xe=he=>{var Y=F5e();R(he,Y)},be=he=>{var Y=D5e();R(he,Y)},Le=he=>{var Y=M5e(),Ce=S(Y);me(()=>ae(Ce,`No artifacts match “${m(d)??""}”.`)),R(he,Y)},tt=he=>{var Y=Mn(),Ce=ct(Y);gt(Ce,17,()=>m(v),bt,(le,V)=>{var q=O5e(),B=S(q),Q=S(B);let X;var j=S(Q);PT(j);var re=D(Q,2),Me=S(re),K=D(re,4),Z=S(K),te=D(B,2);{var _e=ge=>{var ve=Mn(),$e=ct(ve);gt($e,17,()=>m(V).artifacts,bt,(Xe,Re)=>{var je=N5e(),Ze=S(je),Ke=S(Ze);Dy(Ke,{depth:1});var Qe=D(Ke,2);let nt;var Ge=S(Qe);PT(Ge);var qe=D(Qe,2),oe=S(qe),fe=D(qe,4),Ie=S(fe),Je=D(Ze,2);{var xt=Ye=>{var ut=Mn(),At=ct(ut);gt(At,17,()=>m(Re).versions,bt,(It,et)=>{var mt=R5e();let vt;var Dt=S(mt);Dy(Dt,{depth:2});var kt=D(Dt,4),mn=S(kt),vn=D(kt,2);gt(vn,17,()=>m(et).aliases,bt,(lt,Nt)=>{var ne=T5e();let Ae;var St=S(ne);me(()=>{Ae=qt(ne,1,"alias-pill svelte-coehlr",null,Ae,{latest:m(Nt)==="latest"}),ae(St,m(Nt))}),R(lt,ne)}),me((lt,Nt)=>{pt(mt,"id",lt),vt=qt(mt,1,"tree-row version-row svelte-coehlr",null,vt,Nt),ae(mn,`v${m(et).version??""}`)},[()=>"tree-"+g(m(Re).name,m(et).version),()=>({selected:E(m(Re).name,m(et).version)})]),Ne("click",mt,()=>A(m(Re),m(et))),R(It,mt)}),R(Ye,ut)},Et=ke(()=>_(m(Re).name));ue(Je,Ye=>{m(Et)&&Ye(xt)})}me(Ye=>{nt=qt(Qe,1,"chevron svelte-coehlr",null,nt,Ye),pt(qe,"title",m(Re).name),ae(oe,m(Re).name),ae(Ie,m(Re).num_versions)},[()=>({open:_(m(Re).name)})]),Ne("click",Ze,()=>w(m(Re).name)),R(Xe,je)}),R(ge,ve)},ee=ke(()=>b(m(V).type));ue(te,ge=>{m(ee)&&ge(_e)})}me(ge=>{X=qt(Q,1,"chevron svelte-coehlr",null,X,ge),ae(Me,m(V).type),ae(Z,m(V).artifacts.length)},[()=>({open:b(m(V).type)})]),Ne("click",B,()=>x(m(V).type)),R(le,q)}),R(he,Y)};ue(J,he=>{m(c)?he(ce):m(f)?he(xe,1):m(u).length===0?he(be,2):m(v).length===0?he(Le,3):he(tt,-1)})}df(U,()=>m(d),he=>F(d,he)),R(e,P),un()}or(["click"]);var P5e=z(`

        No artifacts in this project

        Artifacts are versioned, content-addressed files (models, datasets, …) + logged from a run. After trackio.init(), log one with trackio.log_artifact():

        You can also build a multi-file artifact with add_file()/add_dir(). Logged artifacts list + here, grouped by type, with their versions and files.

        `),B5e=z('
        Select an artifact version to view its details.
        '),z5e=z('
        ');function j5e(e,t){ln(t,!0);let n=se(t,"project",3,null),r=se(t,"selection",3,null),i=se(t,"empty",3,!1);var s=z5e(),a=S(s);{var o=c=>{var f=Mn(),d=ct(f);vG(d,()=>`${r().name}@v${r().version}`,h=>{RW(h,{variant:"panel",get project(){return n()},get name(){return r().name},get version(){return r().version}})}),R(c,f)},l=c=>{var f=P5e(),d=D(S(f),4),h=S(d);h.textContent=`import trackio + +trackio.init(project="my-project") +trackio.log_artifact("model.pt", name="my-model", type="model")`,R(c,f)},u=c=>{var f=B5e();R(c,f)};ue(a,c=>{r()?c(o):i()?c(l,1):c(u,-1)})}R(e,s),un()}var U5e=ri(''),q5e=ri(''),W5e=ri(''),H5e=z(""),G5e=z('Connected to — remote commands include --space automatically.',1),Y5e=z(""),V5e=z('
        '),X5e=ri(''),K5e=ri(''),Z5e=z('
        '),J5e=z(""),Q5e=ri(''),eFe=ri(''),tFe=ri(''),nFe=ri(''),rFe=z('

        Settings

        Appearance

        Choose how the dashboard looks to you.

        CLI Reference

        Common Trackio CLI commands.

        Agent Skills

        Install Trackio as a skill in your AI coding agent to query experiments with natural language.

        Run in Terminal to Install:
        Example prompt

        ');function iFe(e,t){ln(t,!0);let n=se(t,"spaceId",3,null),r=se(t,"selectedProject",3,null),i=se(t,"projects",19,()=>[]),s=ie(yt(Z5())),a=ie(null),o=ie(null),l=ie("claude"),u=ie(!1),c=ie(!1);const f=[{id:"claude",label:"Claude Code",flag:"--claude"},{id:"codex",label:"Codex",flag:"--codex"},{id:"cursor",label:"Cursor",flag:"--cursor"},{id:"opencode",label:"OpenCode",flag:"--opencode"}];let d=ke(()=>{var j;return`trackio skills add ${(j=f.find(re=>re.id===m(l)))==null?void 0:j.flag}`}),h=ke(()=>{const j=m(o)||"";return{claude:`Use the trackio skill to look at the runs in project "${j}" and find at which step the loss started diverging. Summarize what happened.`,codex:`Use the trackio skill to pull the latest metrics for project "${j}" and tell me which run has the best final eval accuracy.`,cursor:`Use the trackio skill to compare the last two runs in project "${j}" and explain why the learning rate change affected convergence.`,opencode:`Use the trackio skill to get a summary of project "${j}" and flag any runs where the loss spiked unexpectedly.`}[m(l)]});Lt(()=>{if(i(),r(),!(m(o)&&i().includes(m(o)))){if(r()&&i().includes(r())){F(o,r());return}F(o,i()[0]??r()??null,!0)}});function p(j){F(s,j,!0),Bke(j)}function g(){return n()?` --space ${n()}`:""}let v=ke(()=>{const j=g(),re=m(o)||"";return[{title:"Launch dashboard",cmd:"trackio show"},{title:"Launch dashboard (project)",cmd:`trackio show --project "${re}"`},{title:"List projects",cmd:`trackio${j} list projects`},{title:"List runs",cmd:`trackio${j} list runs --project "${re}"`},{title:"List metrics",cmd:`trackio${j} list metrics --project "${re}" --run `},{title:"Project summary",cmd:`trackio${j} get project --project "${re}"`},{title:"Run summary",cmd:`trackio${j} get run --project "${re}" --run `},{title:"Sync to HF Space",cmd:`trackio sync${j} --project "${re}"`},{title:"Check sync status",cmd:"trackio status"}]});async function y(j,re){try{await navigator.clipboard.writeText(j),F(a,re,!0),setTimeout(()=>{m(a)===re&&F(a,null)},1500)}catch{}}async function b(j,re){try{await navigator.clipboard.writeText(j),re==="agent"?(F(u,!0),setTimeout(()=>{F(u,!1)},1500)):(F(c,!0),setTimeout(()=>{F(c,!1)},1500))}catch{}}var _=rFe(),x=D(S(_),2),w=S(x),A=S(w),E=D(S(A),4);gt(E,20,()=>[{value:"system",label:"System"},{value:"light",label:"Light"},{value:"dark",label:"Dark"}],bt,(j,re)=>{var Me=H5e();let K;var Z=S(Me);{var te=ve=>{var $e=U5e();R(ve,$e)},_e=ve=>{var $e=q5e();R(ve,$e)},ee=ve=>{var $e=W5e();R(ve,$e)};ue(Z,ve=>{re.value==="system"?ve(te):re.value==="light"?ve(_e,1):ve(ee,-1)})}var ge=D(Z);me(()=>{K=qt(Me,1,"theme-option svelte-1ozf5k3",null,K,{selected:m(s)===re.value}),ae(ge,` ${re.label??""}`)}),Ne("click",Me,()=>p(re.value)),R(j,Me)});var k=D(A,2),C=D(S(k),2),M=D(S(C));{var N=j=>{var re=G5e(),Me=D(ct(re)),K=S(Me);me(()=>ae(K,n())),R(j,re)};ue(M,j=>{n()&&j(N)})}var P=D(C,2);{var I=j=>{var re=V5e(),Me=D(S(re),2);gt(Me,21,i,bt,(K,Z)=>{var te=Y5e(),_e=S(te),ee={};me(()=>{ae(_e,m(Z)),ee!==(ee=m(Z))&&(te.value=(te.__value=m(Z))??"")}),R(K,te)}),q1(Me,()=>m(o),K=>F(o,K)),R(j,re)};ue(P,j=>{i().length>0&&j(I)})}var T=D(P,2);gt(T,21,()=>m(v),bt,(j,re,Me)=>{var K=Z5e(),Z=S(K),te=S(Z),_e=D(Z,2),ee=S(_e),ge=S(ee),ve=D(ee,2);let $e;var Xe=S(ve);{var Re=Ze=>{var Ke=X5e();R(Ze,Ke)},je=Ze=>{var Ke=K5e();R(Ze,Ke)};ue(Xe,Ze=>{m(a)===Me?Ze(Re):Ze(je,-1)})}me(()=>{ae(te,m(re).title),ae(ge,m(re).cmd),$e=qt(ve,1,"copy-btn svelte-1ozf5k3",null,$e,{copied:m(a)===Me})}),Ne("click",ve,()=>y(m(re).cmd,Me)),R(j,K)});var $=D(w,2),L=S($),W=D(S(L),4);gt(W,21,()=>f,bt,(j,re)=>{var Me=J5e();let K;var Z=S(Me);me(()=>{K=qt(Me,1,"agent-tab svelte-1ozf5k3",null,K,{active:m(l)===m(re).id}),ae(Z,m(re).label)}),Ne("click",Me,()=>{F(l,m(re).id,!0)}),R(j,Me)});var U=D(W,2),O=S(U),H=D(S(O),2),G=S(H),J=S(G),ce=D(G,2);let xe;var be=S(ce);{var Le=j=>{var re=Q5e();R(j,re)},tt=j=>{var re=eFe();R(j,re)};ue(be,j=>{m(u)?j(Le):j(tt,-1)})}var he=D(O,2),Y=S(he),Ce=D(S(Y),2);let le;var V=S(Ce);{var q=j=>{var re=tFe();R(j,re)},B=j=>{var re=nFe();R(j,re)};ue(V,j=>{m(c)?j(q):j(B,-1)})}var Q=D(Y,2),X=S(Q);me(()=>{ae(J,m(d)),xe=qt(ce,1,"copy-btn svelte-1ozf5k3",null,xe,{copied:m(u)}),le=qt(Ce,1,"copy-btn svelte-1ozf5k3",null,le,{copied:m(c)}),ae(X,m(h))}),Ne("click",ce,()=>b(m(d),"agent")),Ne("click",Ce,()=>b(m(h),"example")),R(e,_),un()}or(["click"]);var sFe=z('
        ');function aFe(e,t){ln(t,!0);function n(ne){if(!ne)return"";const Ae=ne.trim(),St=Ae.split(",").map(rt=>rt.trim()).filter(Boolean);if(St.length===0)return"";const Ot=rt=>/^[\w./-]+$/.test(rt);return St.every(Ot)?St.map(rt=>`^${rt.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}$`).join("|"):Ae}function r(){return er("x_axis")||er("x-axis")}zke();let i=ie(yt(X5()));Ike(ne=>{F(i,ne,!0)});let s=ie("metrics"),a=ie(yt([])),o=ie(null),l=ie(yt([])),u=ie(yt([])),c=ie(10),f=ie("step"),d=ie(!1),h=ie(!1),p=ie(""),g=ie(!0),v=ie(!0),y=ie(""),b=ie(yt([])),_=ie(null),x=ie(!1),w=ie(!0),A=ie(!1),E=ie(!1),k=ie(!1),C=ie(0),M=ie(yt([])),N=ie(null),P=ie(yt({spaces:!1,allowed:!0,auth:"local"})),I=ie(null),T=ie(!1),$=ie(yt(IR)),L=ie(yt([])),W=ie(250),U=ie(null),O=ie(null),H=ie(yt([])),G=ie(yt([])),J=ie(yt({})),ce=0,xe=0,be=!1,Le=!1;const tt=15e3,he=new Set(["system","traces","media","reports","files","artifacts"]),Y=["metrics","system","traces","media","reports","runs","files","artifacts"];let Ce=ie(yt({})),le=ie(null),V=ie(null),q=ie(!1);function B(ne){return(ne==null?void 0:ne.id)??(ne==null?void 0:ne.name)}function Q(ne){return ne==="step"||ne==="time"||m(b).includes(ne)}let X=ke(()=>m(l).filter(ne=>m(u).includes(B(ne))));function j(ne){Le=!0,F(s,ne,!0),mg(ne)}function re(){const ne=window.__trackio_base||"";let Ae=window.location.pathname;return ne&&Ae.startsWith(ne)&&(Ae=Ae.slice(ne.length)||"/"),Ae=Ae.replace(/\/+$/,"")||"/",Ae==="/"}function Me(){return er("project")||er("selected_project")}function K(){const ne=Me();ne&&m(a).includes(ne)&&F(o,ne,!0)}async function Z(){try{const ne=await S3e();if(F(a,ne||[],!0),m(a).length>0&&!m(o)){const Ae=Me();F(o,Ae&&m(a).includes(Ae)?Ae:m(a)[0],!0)}K()}catch(ne){console.error("Failed to load projects:",ne)}}async function te(){await _e(),await Re()}async function _e(){const ne=m(o);if(!ne){F(l,[],!0),F(u,[],!0),F(H,[],!0),F(G,[],!0),F(Ce,{},!0),F(le,null);return}ne!==m(le)&&F(Ce,{},!0);try{const[Ae,St]=await Promise.all([C3e(ne),$3e(ne).catch(()=>null)]);if(m(o)!==ne)return;const Ot=[...Ae||[]].reverse();if(JSON.stringify(m(l))!==JSON.stringify(Ot)){const rt=m(u),at=m(l).map(B);F(l,Ot,!0),F(u,nY(rt,Ot.map(B),at),!0)}St!=null&&(F(Ce,St,!0),F(le,ne,!0))}catch(Ae){console.error("Failed to load runs:",Ae)}}async function ee(){if(m(o))try{const ne=await MW(m(o),null,null,null);F(M,(ne||[]).slice(-20),!0)}catch{}}function ge(){return{metrics:!1,system:!1,traces:!1,media:!1,reports:!1,runs:!1,files:!1,artifacts:!1}}async function ve({force:ne=!1}={}){const Ae=Date.now();if(!ne&&Ae-xe0};if(F(J,rt,!0),be&&!Le&&re()){const at=Y.find(Mt=>rt[Mt]);at&&at!==m(s)&&(F(s,at,!0),mg(at)),Le=!0}}catch(Ot){if(St!==ce)return;console.error("Failed to load tab availability:",Ot),F(J,ge(),!0)}}function $e(){m(N)&&clearInterval(m(N)),F(N,setInterval(async()=>{m(g)&&(t_()||e_()||(await Z(),await _e(),await ee(),await ve()))},SW()),!0)}function Xe(){const ne=new URLSearchParams(window.location.search);let Ae=!1;const St=ne.get("write_token");St&&(document.cookie=`trackio_write_token=${encodeURIComponent(St)}; path=/; max-age=604800; SameSite=Lax`,ne.delete("write_token"),Ae=!0);const Ot=ne.get("oauth_session");if(Ot&&(sessionStorage.setItem("trackio_oauth_session",Ot),ne.delete("oauth_session"),Ae=!0),Ae){const rt=ne.toString(),at=window.location.pathname+(rt?`?${rt}`:"");window.history.replaceState({},"",at)}}async function Re(){try{const ne=await U3e();F(P,{spaces:!!ne.spaces,allowed:!!ne.allowed,auth:ne.auth??"none"},!0)}catch{F(P,{spaces:!1,allowed:!0,auth:"local"},!0)}}function je(){m(I)&&clearInterval(m(I)),F(I,setInterval(()=>{Re()},12e4),!0)}Lt(()=>{m(o),F(H,[],!0),F(G,[],!0),_e()}),Lt(()=>{m(C),F(E,er("navbar")==="hidden")}),Lt(()=>{if(m(C),m(s)!=="artifacts"||!m(A))return;const{name:ne,version:Ae}=YR();!ne||Ae==null||F(V,{name:ne,version:Ae},!0)}),mh(()=>{const ne=er("sidebar");ne==="hidden"?(F(A,!0),F(w,!1)):ne==="collapsed"?(F(A,!1),F(w,!1)):F(A,!1);const Ae=er("smoothing");if(Ae){const at=parseInt(Ae,10);Number.isNaN(at)||F(c,at,!0)}const St=r();St&&St.trim()?(F(_,St.trim(),!0),F(f,m(_),!0)):F(x,!0);const Ot=er("metric_filter"),rt=er("metrics");return Ot?F(p,Ot,!0):rt&&F(p,n(rt),!0),er("accordion")==="hidden"&&F(v,!1),F(k,er("hide_empty_tabs")==="true"),be=re(),F(s,CF(),!0),window.addEventListener("popstate",()=>{F(s,CF(),!0),cR(C),K()}),Xe(),(async()=>{const at=await kn();at?(F(g,!1),F(P,{spaces:!1,allowed:!1,auth:"static"},!0),F(U,await G3e(),!0)):(Re(),je(),window.addEventListener("focus",Re));try{try{const Mt=await N3e();Mt&&(Mt.logo_urls&&F($,Mt.logo_urls,!0),Mt.color_palette&&tY(Mt.color_palette),Mt.plot_order&&F(L,Mt.plot_order,!0),Mt.table_truncate_length&&F(W,Mt.table_truncate_length,!0),Mt.media_dir&&H3e(Mt.media_dir),Mt.space_id&&F(O,Mt.space_id,!0))}catch{}await Z(),await _e(),await ee(),await ve({force:!0})}catch(Mt){console.error("Failed to load projects:",Mt)}finally{F(T,!0)}at||$e()})(),()=>{m(N)&&clearInterval(m(N)),m(I)&&clearInterval(m(I)),window.removeEventListener("focus",Re)}});let Ze=ke(()=>{m(C);const ne=Me();return!!(ne&&m(a).includes(ne))});Lt(()=>{m(a),m(C),m(Ze)&&K()}),Lt(()=>{m(o),m(l),m(T)&&ve({force:!0})}),Lt(()=>{m(x)||!m(_)||(Q(m(_))?(F(f,m(_),!0),F(x,!0)):m(b).length>0&&(F(f,"step"),F(x,!0)))});let Ke=ie(!1);Lt(()=>{if(m(Ke)||!m(T)||!m(o))return;const ne=er("run_ids"),Ae=er("runs");if(!ne&&!Ae){F(Ke,!0);return}if(!m(l).length){F(Ke,!0);return}let St;if(ne){const Ot=ne.split(",").map(at=>at.trim()).filter(Boolean),rt=new Set(m(l).map(at=>B(at)));St=Ot.filter(at=>rt.has(at))}else{const Ot=Ae.split(",").map(at=>at.trim()).filter(Boolean),rt=new Set(Ot);St=m(l).filter(at=>rt.has(at.name)).map(at=>B(at))}St.length&&F(u,St,!0),F(Ke,!0)});let Qe=ke(()=>m(s)==="metrics"||m(s)==="traces"||m(s)==="system"||m(s)==="media"||m(s)==="reports"||m(s)==="runs"||m(s)==="run-detail"||m(s)==="files"),nt=ke(()=>m(s)==="runs"||m(s)==="files"?"compact":"full");var Ge=sFe(),qe=S(Ge);{var oe=ne=>{IY(ne,{get variant(){return m(nt)},get currentPage(){return m(s)},get spacesMode(){return m(P).spaces},get runMutationAllowed(){return m(P).allowed},get mutationAuth(){return m(P).auth},get readOnlySource(){return m(U)},get projects(){return m(a)},get projectLocked(){return m(Ze)},get runs(){return m(l)},get runConfigs(){return m(Ce)},get metricColumns(){return m(b)},get availableSystemDevices(){return m(H)},get spaceId(){return m(O)},get logoUrls(){return m($)},get darkMode(){return m(i)},get open(){return m(w)},set open(Ae){F(w,Ae,!0)},get selectedProject(){return m(o)},set selectedProject(Ae){F(o,Ae,!0)},get selectedRuns(){return m(u)},set selectedRuns(Ae){F(u,Ae,!0)},get smoothing(){return m(c)},set smoothing(Ae){F(c,Ae,!0)},get xAxis(){return m(f)},set xAxis(Ae){F(f,Ae,!0)},get logScaleX(){return m(d)},set logScaleX(Ae){F(d,Ae,!0)},get logScaleY(){return m(h)},set logScaleY(Ae){F(h,Ae,!0)},get metricFilter(){return m(p)},set metricFilter(Ae){F(p,Ae,!0)},get realtimeEnabled(){return m(g)},set realtimeEnabled(Ae){F(g,Ae,!0)},get showHeaders(){return m(v)},set showHeaders(Ae){F(v,Ae,!0)},get filterText(){return m(y)},set filterText(Ae){F(y,Ae,!0)},get selectedSystemDevices(){return m(G)},set selectedSystemDevices(Ae){F(G,Ae,!0)}})};ue(qe,ne=>{m(Qe)&&!m(A)&&ne(oe)})}var fe=D(qe,2);{var Ie=ne=>{I5e(ne,{get projects(){return m(a)},get projectLocked(){return m(Ze)},get logoUrls(){return m($)},get darkMode(){return m(i)},get project(){return m(o)},set project(Ae){F(o,Ae,!0)},get selection(){return m(V)},set selection(Ae){F(V,Ae,!0)},get empty(){return m(q)},set empty(Ae){F(q,Ae,!0)}})};ue(fe,ne=>{m(s)==="artifacts"&&!m(A)&&ne(Ie)})}var Je=D(fe,2),xt=S(Je);{var Et=ne=>{OG(ne,{get currentPage(){return m(s)},get tabAvailability(){return m(J)},get optionalEmptyTabs(){return he},get hideEmptyTabs(){return m(k)},onNavigate:j})};ue(xt,ne=>{m(E)||ne(Et)})}var Ye=D(xt,2),ut=S(Ye);{var At=ne=>{eCe(ne,{get project(){return m(o)},get selectedRuns(){return m(X)},get allRuns(){return m(l)},get smoothing(){return m(c)},get xAxis(){return m(f)},get logScaleX(){return m(d)},get logScaleY(){return m(h)},get metricFilter(){return m(p)},get showHeaders(){return m(v)},get appBootstrapReady(){return m(T)},get plotOrder(){return m(L)},get realtimeEnabled(){return m(g)},get metricColumns(){return m(b)},set metricColumns(Ae){F(b,Ae,!0)}})},It=ne=>{wCe(ne,{get project(){return m(o)},get selectedRuns(){return m(X)}})},et=ne=>{MCe(ne,{get project(){return m(o)},get selectedRuns(){return m(X)},get allRuns(){return m(l)},get smoothing(){return m(c)},get appBootstrapReady(){return m(T)},get realtimeEnabled(){return m(g)},get availableDevices(){return m(H)},set availableDevices(Ae){F(H,Ae,!0)},get selectedDevices(){return m(G)},set selectedDevices(Ae){F(G,Ae,!0)}})},mt=ne=>{g$e(ne,{get project(){return m(o)},get selectedRuns(){return m(X)},get allRuns(){return m(l)},get tableTruncateLength(){return m(W)}})},vt=ne=>{C$e(ne,{get project(){return m(o)},get selectedRuns(){return m(X)}})},Dt=ne=>{j$e(ne,{get project(){return m(o)},get runs(){return m(l)},get filterText(){return m(y)},onRunsChanged:te,get runMutationAllowed(){return m(P).allowed}})},kt=ne=>{g5e(ne,{get project(){return m(o)}})},mn=ne=>{k5e(ne,{get project(){return m(o)}})},vn=ne=>{j5e(ne,{get project(){return m(o)},get selection(){return m(V)},get empty(){return m(q)}})},lt=ne=>{iFe(ne,{get spaceId(){return m(O)},get selectedProject(){return m(o)},get projects(){return m(a)}})};ue(ut,ne=>{m(s)==="metrics"?ne(At):m(s)==="traces"?ne(It,1):m(s)==="system"?ne(et,2):m(s)==="media"?ne(mt,3):m(s)==="reports"?ne(vt,4):m(s)==="runs"?ne(Dt,5):m(s)==="run-detail"?ne(kt,6):m(s)==="files"?ne(mn,7):m(s)==="artifacts"?ne(vn,8):m(s)==="settings"&&ne(lt,9)})}var Nt=D(Je,2);qY(Nt,{get alerts(){return m(M)}}),R(e,Ge),un()}dG(aFe,{target:document.getElementById("app")}); diff --git a/trackio/frontend/dist/index.html b/trackio/frontend/dist/index.html new file mode 100644 index 0000000000000000000000000000000000000000..ebd950e2d3999433f80453c544dd7008539c869a --- /dev/null +++ b/trackio/frontend/dist/index.html @@ -0,0 +1,14 @@ + + + + + + Trackio Dashboard + + + + + +
        + + diff --git a/trackio/frontend/eslint.config.js b/trackio/frontend/eslint.config.js new file mode 100644 index 0000000000000000000000000000000000000000..c0bd968851d9ee35d98943b9c2b04b91af245322 --- /dev/null +++ b/trackio/frontend/eslint.config.js @@ -0,0 +1,42 @@ +import js from "@eslint/js"; +import svelte from "eslint-plugin-svelte"; +import svelteParser from "svelte-eslint-parser"; +import globals from "globals"; + +export default [ + { ignores: ["dist/**", "node_modules/**"] }, + { + files: ["**/*.js"], + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2021, + $state: "readonly", + $derived: "readonly", + $effect: "readonly", + $props: "readonly", + $bindable: "readonly", + $inspect: "readonly", + }, + }, + rules: { + ...js.configs.recommended.rules, + "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + "no-empty": "off", + }, + }, + { + files: ["**/*.svelte"], + languageOptions: { + parser: svelteParser, + globals: { ...globals.browser, ...globals.es2021 }, + }, + plugins: { svelte }, + rules: { + ...js.configs.recommended.rules, + ...svelte.configs.recommended.rules, + "no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^\\$" }], + "no-empty": "off", + }, + }, +]; diff --git a/trackio/frontend/index.html b/trackio/frontend/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c3d5e2df6bb7db117ed1d554ea7d8d180b076799 --- /dev/null +++ b/trackio/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + Trackio Dashboard + + + +
        + + + diff --git a/trackio/frontend_config.py b/trackio/frontend_config.py new file mode 100644 index 0000000000000000000000000000000000000000..cd40a82e907f7d88dbf9335dc341f999f206f5f0 --- /dev/null +++ b/trackio/frontend_config.py @@ -0,0 +1,175 @@ +import json +import os +import shutil +from dataclasses import dataclass +from pathlib import Path + +from huggingface_hub.constants import HF_HOME + +TRACKIO_USER_HOME = Path(HF_HOME) / "trackio" +TRACKIO_CONFIG_PATH = TRACKIO_USER_HOME / "config.json" +BUNDLED_FRONTEND_DIR = Path(__file__).parent / "frontend" / "dist" +STARTER_FRONTEND_DIR = Path(__file__).parent / "frontend_templates" / "starter" + + +@dataclass(frozen=True) +class ResolvedFrontend: + path: Path + source: str + is_custom: bool + used_fallback: bool = False + requested_path: Path | None = None + + +def _normalize_frontend_path(path: str | Path) -> Path: + return Path(path).expanduser().resolve() + + +def is_valid_frontend_dir(path: str | Path | None) -> bool: + if path is None: + return False + frontend_dir = _normalize_frontend_path(path) + return frontend_dir.is_dir() and (frontend_dir / "index.html").is_file() + + +def _is_empty_directory(path: Path) -> bool: + return path.is_dir() and not any(path.iterdir()) + + +def _copy_starter_template(destination: Path) -> None: + destination.mkdir(parents=True, exist_ok=True) + for child in STARTER_FRONTEND_DIR.iterdir(): + target = destination / child.name + if child.is_dir(): + shutil.copytree(child, target, dirs_exist_ok=True) + else: + shutil.copy2(child, target) + + +def _materialize_argument_frontend_dir(candidate: Path) -> bool: + existed_before = candidate.exists() + if existed_before and not _is_empty_directory(candidate): + return False + + _copy_starter_template(candidate) + state = "did not exist" if not existed_before else "was empty" + print( + f"* Trackio frontend directory from argument {state}: {candidate}. " + "Copied the starter template into it and serving that directory." + ) + return True + + +def load_trackio_config() -> dict: + if not TRACKIO_CONFIG_PATH.is_file(): + return {} + try: + data = json.loads(TRACKIO_CONFIG_PATH.read_text()) + except (json.JSONDecodeError, OSError): + return {} + return data if isinstance(data, dict) else {} + + +def save_trackio_config(config: dict) -> None: + TRACKIO_USER_HOME.mkdir(parents=True, exist_ok=True) + TRACKIO_CONFIG_PATH.write_text(json.dumps(config, indent=2, sort_keys=True) + "\n") + + +def get_persisted_frontend_dir() -> Path | None: + frontend_dir = load_trackio_config().get("frontend_dir") + if not frontend_dir: + return None + return _normalize_frontend_path(frontend_dir) + + +def set_persisted_frontend_dir(path: str | Path) -> Path: + frontend_dir = _normalize_frontend_path(path) + if not is_valid_frontend_dir(frontend_dir): + raise ValueError( + f"Invalid frontend directory: {frontend_dir}. Expected a directory containing index.html." + ) + config = load_trackio_config() + config["frontend_dir"] = str(frontend_dir) + save_trackio_config(config) + return frontend_dir + + +def unset_persisted_frontend_dir() -> bool: + config = load_trackio_config() + if "frontend_dir" not in config: + return False + del config["frontend_dir"] + if config: + save_trackio_config(config) + elif TRACKIO_CONFIG_PATH.exists(): + TRACKIO_CONFIG_PATH.unlink() + return True + + +def _configured_frontend_candidates( + frontend_dir: str | Path | None, +) -> list[tuple[str, Path]]: + candidates: list[tuple[str, Path]] = [] + if frontend_dir is not None: + candidates.append(("argument", _normalize_frontend_path(frontend_dir))) + env_dir = os.environ.get("TRACKIO_FRONTEND_DIR") + if env_dir: + candidates.append(("env", _normalize_frontend_path(env_dir))) + persisted_dir = get_persisted_frontend_dir() + if persisted_dir is not None: + candidates.append(("config", persisted_dir)) + return candidates + + +def _announce_config_frontend(frontend_dir: Path) -> None: + print( + f"* Using Trackio custom frontend from config: {frontend_dir}\n" + " Reset with `trackio config unset frontend`." + ) + + +def resolve_frontend_dir( + frontend_dir: str | Path | None = None, + *, + announce: bool = False, +) -> ResolvedFrontend: + for source, candidate in _configured_frontend_candidates(frontend_dir): + if source == "argument": + if not candidate.exists() or _is_empty_directory(candidate): + _materialize_argument_frontend_dir(candidate) + + if is_valid_frontend_dir(candidate): + if source == "config" and announce: + _announce_config_frontend(candidate) + return ResolvedFrontend( + path=candidate, + source=source, + is_custom=True, + ) + if source == "argument": + print( + f"* Trackio frontend from {source} is invalid: {candidate}. " + f"Falling back to starter template at {STARTER_FRONTEND_DIR}." + ) + return ResolvedFrontend( + path=STARTER_FRONTEND_DIR, + source="starter", + is_custom=True, + used_fallback=True, + requested_path=candidate, + ) + print(f"* Trackio frontend from {source} is invalid: {candidate}. Ignoring it.") + + if is_valid_frontend_dir(BUNDLED_FRONTEND_DIR): + return ResolvedFrontend( + path=BUNDLED_FRONTEND_DIR, + source="bundled", + is_custom=False, + ) + + return ResolvedFrontend( + path=STARTER_FRONTEND_DIR, + source="starter", + is_custom=True, + used_fallback=True, + ) diff --git a/trackio/frontend_server.py b/trackio/frontend_server.py new file mode 100644 index 0000000000000000000000000000000000000000..2e2dcd0d84a9852e389c4072ea1b8eecb73b6639 --- /dev/null +++ b/trackio/frontend_server.py @@ -0,0 +1,175 @@ +"""Serves a static frontend alongside the Trackio HTTP API.""" + +import hashlib +import json +import logging +import re +from pathlib import Path + +from starlette.middleware.base import BaseHTTPMiddleware +from starlette.responses import FileResponse, HTMLResponse, JSONResponse +from starlette.routing import Mount, Route, get_route_path +from starlette.staticfiles import StaticFiles + +ASSETS_DIR = Path(__file__).parent / "assets" + +_logger = logging.getLogger(__name__) + +_ABSOLUTE_REF_RE = re.compile(r'(href|src)="(/(?:assets|static/trackio)/[^"]+)"') + +_LIVE_RELOAD_SCRIPT = """ + +""".strip() + + +def _frontend_version(frontend_root: Path) -> str: + digest = hashlib.sha256() + for path in sorted(frontend_root.rglob("*")): + if not path.is_file(): + continue + relative = path.relative_to(frontend_root) + digest.update(str(relative).encode("utf-8")) + stat = path.stat() + digest.update(str(stat.st_mtime_ns).encode("utf-8")) + digest.update(str(stat.st_size).encode("utf-8")) + return digest.hexdigest() + + +def _inject_live_reload(html: str, root_path: str) -> str: + if "/__trackio/frontend_version" in html: + return html + script = _LIVE_RELOAD_SCRIPT.replace("__TRACKIO_ROOT_PATH__", root_path) + if "" in html: + return html.replace("", f"{script}\n ") + return html + script + + +def _prefix_absolute_refs(html: str, root_path: str) -> str: + if not root_path: + return html + return _ABSOLUTE_REF_RE.sub( + lambda m: f'{m.group(1)}="{root_path}{m.group(2)}"', html + ) + + +def _inject_base_script(html: str, root_path: str) -> str: + if not root_path: + return html + script = f"" + if "" in html: + return html.replace("", f"\n {script}", 1) + return script + html + + +def _render_index_html(path: Path, root_path: str = "") -> str: + html = path.read_text(encoding="utf-8") + html = _prefix_absolute_refs(html, root_path) + html = _inject_base_script(html, root_path) + return _inject_live_reload(html, root_path) + + +def _html_response(path: Path, root_path: str = "") -> HTMLResponse: + return HTMLResponse(_render_index_html(path, root_path)) + + +class FrontendMiddleware(BaseHTTPMiddleware): + def __init__(self, app, frontend_root: Path, index_html_path: Path): + super().__init__(app) + self.frontend_root = frontend_root + self.index_html_path = index_html_path + self.reserved_prefixes = ( + "/api/", + "/file", + "/version", + "/artifact_blob/", + "/static/trackio", + "/__trackio/frontend_version", + "/oauth/", + "/login/", + "/mcp", + ) + self.reserved_exact = { + "/api", + "/oauth", + "/login", + } + + async def dispatch(self, request, call_next): + if request.method not in {"GET", "HEAD"}: + return await call_next(request) + + path = get_route_path(request.scope) + if path in self.reserved_exact or path.startswith(self.reserved_prefixes): + return await call_next(request) + + root_path = request.scope.get("root_path", "") + relative_path = path.lstrip("/") + requested_path = (self.frontend_root / relative_path).resolve() + if ( + relative_path + and requested_path.is_file() + and requested_path.is_relative_to(self.frontend_root) + ): + if requested_path.suffix.lower() == ".html": + return _html_response(requested_path, root_path) + return FileResponse(requested_path) + + return _html_response(self.index_html_path, root_path) + + +def mount_frontend(app, frontend_dir: str | Path): + frontend_root = Path(frontend_dir).resolve() + if not frontend_root.exists(): + _logger.warning( + "Trackio dashboard UI was not mounted: %s is missing. " + "Build the frontend or provide a custom frontend directory.", + frontend_root, + ) + return + + index_html_path = frontend_root / "index.html" + if not index_html_path.exists(): + _logger.warning( + "Trackio dashboard UI was not mounted: %s is missing.", + index_html_path, + ) + return + + async def frontend_version(_request): + return JSONResponse({"version": _frontend_version(frontend_root)}) + + static_assets = StaticFiles(directory=str(ASSETS_DIR)) + + app.add_middleware( + FrontendMiddleware, + frontend_root=frontend_root, + index_html_path=index_html_path, + ) + app.routes.append(Mount("/static/trackio", app=static_assets)) + app.routes.append( + Route("/__trackio/frontend_version", frontend_version, methods=["GET"]) + ) diff --git a/trackio/frontend_templates/logbook/bucket-icon.svg b/trackio/frontend_templates/logbook/bucket-icon.svg new file mode 100644 index 0000000000000000000000000000000000000000..b7ce1dac0d70d7ca8e392aff3a534b756041708d --- /dev/null +++ b/trackio/frontend_templates/logbook/bucket-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/trackio/frontend_templates/logbook/index.html b/trackio/frontend_templates/logbook/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f386be9033f4b4367329ef2e99b6866a3f98f26a --- /dev/null +++ b/trackio/frontend_templates/logbook/index.html @@ -0,0 +1,54 @@ + + + + + + Trackio Logbook + + + +
        + +
        +
        +
        +
        + + + + + + diff --git a/trackio/frontend_templates/logbook/logbook.css b/trackio/frontend_templates/logbook/logbook.css new file mode 100644 index 0000000000000000000000000000000000000000..2a9f174dac3117978fa2279dacebce2185fe6694 --- /dev/null +++ b/trackio/frontend_templates/logbook/logbook.css @@ -0,0 +1,1602 @@ +:root { + --bg: #ffffff; + --paper: #fdfcf9; + --panel: #ffffff; + --ink: #1f2937; + --muted: #6b7280; + --line: #e5e7eb; + --accent: #f97316; + --accent-strong: #ea580c; + --accent-soft: #fff7ed; + --accent-line: rgba(249, 115, 22, 0.16); + --grid-line: rgba(31, 41, 55, 0.045); + --code-bg: #f3f4f6; + --radius: 12px; + --serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Georgia, serif; + --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, + sans-serif; + --mono: "SFMono-Regular", "Cascadia Mono", "JetBrains Mono", Menlo, Consolas, + ui-monospace, monospace; +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; +} + +body { + background: var(--bg); + color: var(--ink); + font-family: var(--sans); + font-size: 13px; + line-height: 1.65; + -webkit-font-smoothing: antialiased; +} + +#app { + display: flex; + min-height: 100vh; +} + +/* ---- sidebar (composition-book cover) ---- */ +#sidebar { + width: 280px; + flex: 0 0 280px; + background: #17181c; + color: #e7e7ea; + position: sticky; + top: 0; + height: 100vh; + overflow-y: auto; + padding: 22px 16px; + display: flex; + flex-direction: column; +} + +#book-head { + display: flex; + align-items: center; + gap: 10px; + padding: 8px; + margin-bottom: 12px; + border-radius: 10px; + cursor: pointer; + transition: background 0.12s; +} +#book-head:hover { + background: rgba(255, 255, 255, 0.05); +} +#book-wordmark { + width: 154px; + height: auto; + object-fit: contain; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +#tree { + flex: 1; + padding-top: 8px; +} + +#tree a { + display: block; + padding: 6px 10px; + border-radius: 8px; + color: #c3c4cb; + text-decoration: none; + font-size: 14px; + transition: background 0.12s, color 0.12s; +} + +#tree a:hover { + background: rgba(255, 255, 255, 0.06); + color: #ffffff; +} + +#tree a.active { + background: rgba(249, 115, 22, 0.16); + color: #fdba74; + font-weight: 600; +} + +#tree a .tree-mark { + color: #6b6d76; +} + +#tree a:hover .tree-mark, +#tree a.active .tree-mark { + color: inherit; + opacity: 0.6; +} + +#tree .depth-1 { + padding-left: 22px; +} +#tree .depth-2 { + padding-left: 34px; +} +#tree .depth-3 { + padding-left: 46px; +} + + +/* ---- content ---- */ +#content { + flex: 1; + min-width: 0; + padding: 48px 40px 120px; + background-color: var(--paper); + background-image: + linear-gradient(var(--grid-line) 1px, transparent 1px), + linear-gradient(90deg, var(--grid-line) 1px, transparent 1px); + background-size: 26px 26px; + background-position: center top; +} + +#page { + width: 100%; + min-width: 0; + max-width: 1052px; + margin: 0 auto; +} + +.page-section { + scroll-margin-top: 40px; + padding: 0 0 35px; + margin: 0 0 32px; +} + +.page-section:last-child { + margin-bottom: 0; +} + +.page-layout { + display: grid; + grid-template-columns: minmax(0, 760px) 248px; + gap: 44px; + align-items: start; +} + +.page-body { + min-width: 0; +} + +.resource-anchor { + display: block; + height: 0; + overflow: hidden; +} + +/* ---- pinned notes ---- */ +.pinned-notes { + margin: 30px 0 0; +} +.pinned-notes-list .cell { + margin: 0; + border-color: rgba(249, 115, 22, 0.55); +} +.pinned-notes-list .cell + .cell { + margin-top: 12px; +} +.cell.pinned-source { + border-color: rgba(249, 115, 22, 0.55); +} +.book-intro.has-pinned-notes { + border-bottom: none; + padding-bottom: 22px; + margin-bottom: 30px; +} +.book-intro.book-intro-tight { + border-bottom: none; + padding-bottom: 4px; + margin-bottom: 20px; +} + +#page h1 { + font-family: var(--serif); + font-size: 34px; + line-height: 1.15; + letter-spacing: -0.02em; + margin: 0 0 8px; + overflow-wrap: anywhere; +} + +#page .page-section:not(.book-intro) h1 { + font-size: 26px; +} + +#page h2 { + font-family: var(--serif); + font-size: 24px; + margin: 36px 0 10px; +} + +#page h3 { + font-size: 17px; + font-weight: 700; + margin: 26px 0 2px; + letter-spacing: -0.01em; +} + +#page h3::before { + content: ""; + display: inline-block; + width: 7px; + height: 7px; + border-radius: 2px; + background: var(--accent); + margin-right: 10px; + vertical-align: middle; + transform: translateY(-1px); +} + +#page p { + margin: 10px 0; +} + +#page blockquote { + margin: 14px 0; + padding: 2px 16px; + border-left: 3px solid #fdba74; + color: var(--muted); +} + +#page hr { + display: none; +} + +#page code { + font-family: var(--mono); + font-size: 0.86em; + background: var(--code-bg); + padding: 2px 6px; + border-radius: 6px; +} + +#page pre { + max-width: 100%; + background: var(--code-bg); + border: 1px solid var(--line); + border-radius: var(--radius); + padding: 14px 16px; + overflow-x: auto; +} +#page pre code { + background: none; + padding: 0; + font-size: 11.5px; +} + +/* ---- code blocks + collapsible accordion ---- */ +#page pre.hl { + background: #17181c; + border: none; + color: #e7e7ea; + font-size: 13px; + line-height: 1.58; +} +#page pre.hl code { + color: inherit; + font-family: var(--mono); +} +.code-accordion { + border: 1px solid rgba(249, 115, 22, 0.2); + border-radius: 8px; + overflow: hidden; + margin: 12px 0; + background: #17181c; +} +.code-accordion summary { + list-style: none; + cursor: pointer; + display: flex; + align-items: center; + gap: 9px; + padding: 9px 12px; + font-family: var(--mono); + font-size: 11.5px; + font-weight: 700; + color: #e7e7ea; + background: #1e2027; + user-select: none; + overflow-wrap: anywhere; +} +.code-accordion summary::-webkit-details-marker { + display: none; +} +.code-accordion summary::after { + content: "▸"; + margin-left: auto; + color: var(--accent); + transition: transform 0.12s; + transform: rotate(180deg); +} +.code-accordion[open] summary::after { + transform: rotate(90deg); +} +.code-accordion .code-ico { + color: var(--accent); + font-weight: 700; +} +.code-accordion pre.hl { + margin: 0; + border-radius: 0; + border: none; + border-top: 1px solid rgba(249, 115, 22, 0.16); +} +.tok-comment { + color: #7a7d87; + font-style: italic; +} +.tok-string { + color: #a5d6a7; +} +.tok-keyword { + color: #fdba74; +} +.tok-number { + color: #7fd0e0; +} + +#page a { + color: var(--accent); +} + +#page ul { + padding-left: 20px; +} + +.ts { + font-family: var(--mono); + font-size: 12px; + color: var(--muted); + background: none; + padding: 0; +} + +/* ---- notebook-style cells ---- */ +.cell { + max-width: 100%; + border: 1px solid var(--line); + border-radius: 10px; + background: rgba(255, 255, 255, 0.86); + margin: 18px 0; + overflow: hidden; + box-shadow: 0 2px 10px rgba(31, 41, 55, 0.035); +} +.cell-head { + display: flex; + justify-content: space-between; + gap: 16px; + align-items: center; + padding: 14px 18px; + background: rgba(255, 255, 255, 0.92); + border-bottom: 1px solid var(--line); +} +.cell-head.no-title { + justify-content: flex-end; + padding-top: 10px; + padding-bottom: 10px; +} +.cell-title { + flex: 1; + min-width: 0; + font-size: 13px; + font-weight: 650; + color: var(--ink); + line-height: 1.35; + overflow-wrap: anywhere; +} +.cell-meta { + flex: 0 0 auto; + display: flex; + align-items: center; + gap: 10px; + font-family: var(--sans); + font-size: 13px; + color: var(--muted); +} +.cell-open { + flex: 0 0 auto; + font-family: var(--mono); + font-size: 12px; + color: var(--accent); + text-decoration: none; +} +.cell-open:hover { + color: var(--accent-strong); +} +.cell-body { + min-width: 0; + padding: 14px 18px 18px; +} +.cell.dashboard .cell-body { + padding: 0; +} +#page .cell-body h1, +#page .cell-body h2 { + font-family: var(--sans); + font-size: 17px; + font-weight: 700; + letter-spacing: -0.01em; + line-height: 1.35; + margin: 22px 0 6px; +} +#page .cell-body > :first-child { + margin-top: 0; +} +#page .cell-body > :last-child { + margin-bottom: 0; +} +.cell.code .cell-head { + background: #fbfbfc; +} +.figure-fit { + position: relative; + overflow: hidden; + min-height: 160px; + border: 1px solid var(--line); + border-radius: 8px; + background: #fff; +} +.figure-fit[hidden] { + display: none; +} +.figure-fit:fullscreen, +.figure-fit:-webkit-full-screen { + width: 100%; + height: 100%; + border: none; + border-radius: 0; +} +.figure-frame { + display: block; + width: 100%; + min-height: 160px; + border: none; + background: #fff; +} +.figure-frame[hidden], +.figure-raw[hidden] { + display: none; +} +.fig-switch { + position: relative; + display: inline-flex; + flex: 0 0 auto; + border: 1px solid var(--line); + border-radius: 999px; + background: var(--code-bg); + padding: 2px; +} +.fig-switch button { + position: relative; + z-index: 1; + flex: 1; + min-width: 62px; + border: none; + background: none; + font-family: var(--sans); + font-size: 12px; + font-weight: 600; + color: var(--muted); + padding: 3px 12px; + border-radius: 999px; + cursor: pointer; + transition: color 0.15s; +} +.fig-switch button.active { + color: var(--accent-strong); +} +.fig-switch-thumb { + position: absolute; + top: 2px; + bottom: 2px; + left: 2px; + width: calc(50% - 2px); + border-radius: 999px; + background: var(--panel); + border: 1px solid rgba(249, 115, 22, 0.35); + box-shadow: 0 1px 4px rgba(31, 41, 55, 0.08); + transition: transform 0.18s ease; +} +.fig-switch.raw .fig-switch-thumb { + transform: translateX(100%); +} +#page .figure-raw pre { + margin: 0; + max-height: 420px; + overflow: auto; + font-family: var(--mono); + font-size: 13px; + line-height: 1.55; + background: var(--code-bg); + border: 1px solid var(--line); + border-radius: 8px; + padding: 12px 14px; +} +/* ---- figure fullscreen ---- */ +.cell-fullscreen { + position: relative; + display: inline-flex; + flex: 0 0 auto; +} +.cell-fullscreen-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + padding: 0; + border: 1px solid var(--line); + border-radius: 999px; + background: var(--code-bg); + color: var(--muted); + cursor: pointer; + transition: color 0.15s, border-color 0.15s, background 0.15s; +} +.cell-fullscreen-btn:hover { + color: var(--accent-strong); + border-color: rgba(249, 115, 22, 0.35); + background: var(--accent-soft); +} +.cell-fullscreen-btn svg { + width: 14px; + height: 14px; +} +/* ---- copyable snippets ---- */ +.snippet { + position: relative; +} +.copy-snippet { + position: absolute; + top: 7px; + right: 8px; + width: 24px; + height: 24px; + border: none; + border-radius: 6px; + background: rgba(255, 255, 255, 0.08); + color: #9a9da8; + font-size: 12px; + line-height: 1; + cursor: pointer; + opacity: 0; + transition: opacity 0.12s, color 0.12s, background 0.12s; +} +.snippet:hover .copy-snippet, +.jp-out:hover .copy-snippet, +.figure-raw:hover .copy-snippet, +.code-accordion summary:hover .copy-snippet { + opacity: 1; +} +.copy-snippet:hover { + color: #ffffff; + background: rgba(255, 255, 255, 0.16); +} +.copy-snippet.copied { + color: #52d08a; + opacity: 1; +} +.code-accordion .code-name { + user-select: text; + cursor: text; +} +.jp-out, +.figure-raw { + position: relative; +} +.jp-out .copy-snippet, +.figure-raw .copy-snippet { + background: var(--code-bg); + color: var(--muted); + border: 1px solid var(--line); +} +.jp-out .copy-snippet:hover, +.figure-raw .copy-snippet:hover { + color: var(--accent-strong); + background: var(--panel); +} + +/* ---- jupyter-style code cells ---- */ +.jp { + border: 1px solid var(--line); + border-radius: 10px; + overflow: hidden; + margin: 12px 0; + background: var(--panel); +} +.jp-gutter { + flex: 0 0 46px; + padding: 13px 0 0 13px; + font-family: var(--mono); + font-size: 10.5px; + letter-spacing: 0.07em; + text-transform: uppercase; + font-weight: 600; + user-select: none; +} +.jp-in { + display: flex; + background: #17181c; +} +.jp-in .jp-gutter { + color: #6f727d; +} +.jp-in-body { + flex: 1; + min-width: 0; +} +#page .jp-in-body pre.hl { + margin: 0; + border: none; + border-radius: 0; + background: none; + padding: 12px 16px 12px 0; +} +.jp-in-body .code-accordion { + margin: 0; + border: none; + border-top: 1px solid rgba(255, 255, 255, 0.09); + border-radius: 0; + background: none; +} +.jp-in-body .code-accordion summary { + background: none; + padding: 9px 16px 9px 0; +} +.jp-in-body .code-accordion pre.hl { + border-top: 1px solid rgba(255, 255, 255, 0.09); +} +.jp-meta { + padding: 5px 14px; + font-family: var(--mono); + font-size: 11.5px; + color: var(--muted); + background: #fbfbfc; + border-top: 1px solid var(--line); +} +.jp-out { + display: flex; + border-top: 1px solid var(--line); + background: var(--panel); +} +.jp-out .jp-gutter { + color: var(--accent-strong); +} +.jp-out-body { + flex: 1; + min-width: 0; +} +#page .jp-out-pre { + min-width: 0; + margin: 0; + border: none; + border-radius: 0; + background: none; + color: var(--ink); + font-family: var(--mono); + font-size: 13px; + line-height: 1.55; + padding: 12px 16px 12px 0; + white-space: pre; + overflow-x: auto; + overflow-y: auto; + max-height: 26em; +} +.jp-artifacts { + display: flex; + flex-direction: column; +} +.jp-out-body .jp-out-pre + .jp-artifacts { + border-top: 1px solid var(--line); +} +.out-artifact { + display: flex; + align-items: baseline; + gap: 8px; + padding: 9px 16px 9px 0; + text-decoration: none; + color: inherit; +} +.out-artifact + .out-artifact { + border-top: 1px solid var(--line); +} +a.out-artifact:hover .out-artifact-name { + color: var(--accent-strong); +} +.out-artifact-ico { + flex: 0 0 auto; + font-size: 13px; +} +.out-artifact-name { + font-family: var(--mono); + font-size: 12.5px; + font-weight: 600; + color: var(--ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.out-artifact-meta { + flex: 0 0 auto; + margin-left: auto; + padding-left: 12px; + font-size: 12px; + color: var(--muted); + white-space: nowrap; +} +.out-artifact-state.open { + color: var(--accent); + font-weight: 600; +} +.trackio-embed { + border: 1px solid var(--line); + border-radius: var(--radius); + overflow: hidden; + background: var(--panel); +} +.trackio-cell-meta { + display: flex; + gap: 6px; + flex-wrap: wrap; + justify-content: flex-end; +} + +/* ---- unfurl cards ---- */ +.unfurl { + display: block; + border: 1px solid var(--line); + border-radius: var(--radius); + background: var(--panel); + margin: 12px 0; + overflow: hidden; + text-decoration: none; + color: inherit; + transition: border-color 0.14s, box-shadow 0.14s; +} +.unfurl:hover { + border-color: #cfcbe6; + box-shadow: 0 4px 18px rgba(30, 20, 80, 0.06); +} + +.unfurl-body { + padding: 13px 16px; + display: flex; + gap: 12px; + align-items: flex-start; +} + +.unfurl-ico { + font-size: 20px; + line-height: 1.3; + flex: 0 0 auto; +} + +.unfurl-main { + min-width: 0; + flex: 1; +} + +.unfurl-kind { + font-family: var(--mono); + font-size: 10.5px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--accent); + font-weight: 600; +} + +.unfurl-title { + font-weight: 650; + font-size: 15px; + margin: 1px 0 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.unfurl-desc { + color: var(--muted); + font-size: 13.5px; + line-height: 1.45; +} + +.unfurl-meta { + margin-top: 6px; + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.chip { + font-size: 11.5px; + background: var(--code-bg); + border-radius: 999px; + padding: 2px 9px; + color: var(--muted); + font-family: var(--mono); +} + +.unfurl-raw { + font-family: var(--mono); + font-size: 11px; + color: var(--muted); + border-top: 1px solid var(--line); + padding: 7px 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.unfurl.embed { + padding: 0; + overflow: hidden; +} +.embed-head { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 14px; + border-bottom: 1px solid var(--line); +} +.embed-head .unfurl-kind { + flex: 0 0 auto; +} +.embed-title { + flex: 1; + min-width: 0; + font-weight: 650; + font-size: 14px; + color: var(--ink); + text-decoration: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.embed-title:hover { + color: var(--accent); +} +.embed-open { + flex: 0 0 auto; + font-family: var(--mono); + font-size: 12px; + color: var(--accent); + text-decoration: none; +} +.embed-frame { + display: block; + width: 100%; + height: 560px; + border: 0; + background: var(--code-bg); +} + +.dashboard-shell { + display: block; +} +.dashboard-shell .dashboard-frame { + display: block; + width: 100%; + height: 900px; + border: 0; + background: var(--code-bg); +} + +.unfurl.image { + padding: 0; +} +.unfurl.image img { + display: block; + width: 100%; + height: auto; + max-height: 460px; + object-fit: contain; + background: var(--code-bg); +} + +.artifact-chip { + border: 1px solid var(--line); + background: var(--panel); + border-radius: var(--radius); + padding: 10px 14px; + margin: 8px 0; + font-size: 14px; +} +.cell.dashboard .artifact-chip { + margin: 14px 18px 18px; +} +.artifact-chip code { + color: var(--accent); +} + +/* ---- task board ---- */ +.board-wrap { + overflow-x: auto; + border: 1px solid var(--line); + border-radius: var(--radius); + margin: 12px 0 20px; + background: var(--panel); +} +table.board { + border-collapse: collapse; + width: 100%; + font-size: 14px; +} +table.board th, +table.board td { + text-align: left; + padding: 9px 14px; + border-bottom: 1px solid var(--line); + vertical-align: top; +} +table.board thead th { + background: var(--accent-soft); + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.05em; + color: #9a4a12; + font-weight: 600; + border-bottom: 1px solid var(--line); +} +table.board tbody tr:last-child td { + border-bottom: none; +} +table.board .col-check { + text-align: center; + width: 92px; + white-space: nowrap; +} +table.board tr.section-row td { + background: var(--accent-soft); + text-align: center; + font-weight: 700; + font-size: 13px; + color: var(--accent-strong); + padding: 7px 14px; + letter-spacing: 0.02em; +} +.box { + display: inline-flex; + align-items: center; + justify-content: center; + width: 18px; + height: 18px; + border: 1.5px solid #cfcbe0; + border-radius: 5px; + font-size: 12px; + color: #fff; + line-height: 1; +} +.box.on { + background: var(--accent); + border-color: var(--accent); +} +.who-chip { + display: inline-block; + padding: 3px 12px; + border-radius: 999px; + font-size: 12.5px; + font-weight: 600; + white-space: nowrap; +} +.who-chip.muted { + background: var(--code-bg); + color: var(--muted); + font-weight: 500; +} + +/* ---- status badges + clickable rows ---- */ +table.board .col-status { + width: 130px; + white-space: nowrap; +} +.badge { + display: inline-block; + padding: 3px 11px; + border-radius: 999px; + font-size: 12px; + font-weight: 600; + letter-spacing: 0.01em; +} +.badge.gray { + background: var(--code-bg); + color: var(--muted); +} +.badge.amber { + background: var(--accent-soft); + color: #b45309; +} +.badge.green { + background: #e6f7ee; + color: #1a8a55; +} +.badge.red { + background: #fde8ec; + color: #c62a4b; +} +table.board tr.linked-row { + cursor: pointer; +} +table.board tr.linked-row:hover td { + background: var(--accent-soft); +} +table.board tr.linked-row a { + color: var(--ink); + font-weight: 600; + text-decoration: none; +} +table.board tr.linked-row:hover a { + color: var(--accent-strong); +} + +/* ---- agent read hint ---- */ +.agent-hint { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 8px; + margin: 4px 0 22px; + font-size: 12.5px; + color: var(--muted); +} +#page .agent-hint code { + background: var(--code-bg); + padding: 2px 9px; + border-radius: 6px; + font-family: var(--mono); + font-size: 12px; + font-weight: 500; + color: var(--ink); +} +.agent-hint .copy { + flex: 0 0 auto; + background: none; + color: var(--muted); + border: 1px solid var(--line); + border-radius: 6px; + width: 22px; + height: 22px; + font-size: 11px; + line-height: 1; + cursor: pointer; + transition: color 0.12s, border-color 0.12s; +} +.agent-hint .copy:hover { + color: var(--accent-strong); + border-color: var(--accent); +} +.agent-hint .copy.copied { + color: #1a8a55; + border-color: #1a8a55; +} +.agent-hint-note { + margin-left: auto; + font-size: 12px; + color: var(--muted); +} + +/* ---- logbook summary stats ---- */ +.logbook-stats { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin: 0 0 28px; +} +.stat-tile { + position: relative; + display: inline-flex; + align-items: center; + gap: 11px; + border: 1px solid var(--line); + background: var(--panel); + border-radius: var(--radius); + padding: 12px 23px; + font: inherit; + text-align: left; + cursor: pointer; + transition: border-color 0.12s, box-shadow 0.12s; +} +.stat-tile:hover:not([disabled]) { + border-color: rgba(249, 115, 22, 0.45); + box-shadow: 0 3px 12px rgba(31, 41, 55, 0.06); +} +.stat-tile:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} +.stat-tile[disabled] { + cursor: default; + opacity: 0.7; +} +.stat-tile.open { + border-color: rgba(249, 115, 22, 0.6); + box-shadow: 0 3px 12px rgba(31, 41, 55, 0.08); +} +.stat-icon { + width: 24px; + height: 24px; + flex: 0 0 24px; + object-fit: contain; + align-self: center; +} +.stat-text { + display: flex; + align-items: baseline; + gap: 8px; + white-space: nowrap; + line-height: 1; +} +.stat-num { + font-family: var(--mono); + font-size: 20px; + font-weight: 600; + line-height: 1; + color: var(--accent-strong); +} +.stat-label { + font-size: 15px; + line-height: 1; + color: var(--muted); +} +.stat-caret { + margin-left: 2px; + font-size: 10px; + color: var(--muted); + align-self: center; + transition: transform 0.12s; +} +.stat-tile.open .stat-caret { + transform: rotate(180deg); +} +.stat-popover { + position: absolute; + top: 100%; + left: 0; + margin-top: 6px; + min-width: 300px; + max-width: min(460px, 92vw); + max-height: 340px; + overflow-y: auto; + z-index: 20; + background: var(--panel); + border: 1px solid var(--line); + border-radius: var(--radius); + box-shadow: 0 8px 28px rgba(31, 41, 55, 0.12); + padding: 6px; +} +.stat-popover[hidden] { + display: none; +} +.stat-pop-head { + padding: 6px 10px 8px; + font-size: 11.5px; + font-weight: 700; + letter-spacing: 0.03em; + text-transform: uppercase; + color: var(--muted); +} +.stat-row { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 9px 11px; + border-radius: 9px; + border: 1px solid transparent; + text-decoration: none; + color: inherit; + cursor: pointer; +} +.stat-row:hover { + border-color: rgba(249, 115, 22, 0.4); + background: var(--accent-soft); +} +.stat-row-ico { + font-size: 15px; + line-height: 1.3; + flex: 0 0 auto; +} +.stat-row-main { + min-width: 0; + flex: 1; +} +.stat-row-title { + font-family: var(--mono); + font-size: 12.5px; + font-weight: 600; + color: var(--ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.stat-row-meta { + margin-top: 2px; + font-size: 12px; + color: var(--muted); +} +.stat-row-state.open { + color: var(--accent); + font-weight: 600; + border-radius: 5px; + padding: 1px 5px; + margin: -1px -2px; +} +.stat-row-state.open:hover { + background: rgba(249, 115, 22, 0.14); + text-decoration: underline; +} +.art-ico { + width: 1em; + height: 1em; + object-fit: contain; + vertical-align: -0.15em; +} + +/* ---- scroll-to-resource highlight ---- */ +.res-flash { + animation: res-flash 1.5s ease; + border-radius: 8px; +} +@keyframes res-flash { + 0%, + 25% { + box-shadow: 0 0 0 3px var(--accent); + } + 100% { + box-shadow: 0 0 0 3px rgba(249, 115, 22, 0); + } +} + +/* ---- inline resource chips ---- */ +#page .res-chip { + display: inline-flex; + align-items: center; + gap: 5px; + max-width: 100%; + padding: 0 9px 0 6px; + margin: 0 1px; + border: 1px solid var(--line); + border-radius: 999px; + background: var(--panel); + font-family: var(--mono); + font-size: 0.78em; + font-weight: 600; + color: var(--ink); + text-decoration: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: middle; + line-height: 1.65; + transform: translateY(-0.08em); + transition: border-color 0.12s, background 0.12s, color 0.12s; +} +.res-chip-ico { + font-size: 1.05em; + line-height: 1; +} +#page .res-chip:hover, +#page .res-chip.res-hl { + border-color: var(--accent); + background: var(--accent-soft); + color: var(--accent-strong); +} +#page a.res-link.res-hl { + background: var(--accent-soft); + border-radius: 4px; +} +.rail-item.res-hl { + border-color: var(--accent); + background: var(--accent-soft); + box-shadow: 0 3px 12px rgba(249, 115, 22, 0.14); +} +.rail-item.res-hl .rail-title { + color: var(--accent-strong); +} +.rail-item.rail-local { + cursor: default; +} +.artifact-chip.res-hl { + border-color: var(--accent); + background: var(--accent-soft); +} + +/* ---- contextual resources rail ---- */ +.context-rail { + position: relative; + width: 248px; +} +.context-rail[hidden] { + display: none; +} +.rail-kind { + display: flex; + align-items: center; + gap: 5px; + font-family: var(--mono); + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.08em; + font-weight: 600; + color: var(--accent); + margin-bottom: 4px; +} +.rail-item { + position: absolute; + left: 0; + right: 0; + display: block; + border: 1px solid var(--line); + border-radius: 10px; + background: var(--panel); + padding: 9px 12px; + margin-bottom: 8px; + text-decoration: none; + color: inherit; + transition: border-color 0.14s, box-shadow 0.14s; +} +.rail-item:hover { + border-color: rgba(249, 115, 22, 0.45); + box-shadow: 0 3px 12px rgba(31, 41, 55, 0.06); +} +.rail-title { + font-family: var(--mono); + font-size: 12.5px; + font-weight: 600; + color: var(--ink); + overflow-wrap: anywhere; + line-height: 1.4; +} +.rail-item:hover .rail-title { + color: var(--accent-strong); +} +.rail-meta { + font-size: 11.5px; + color: var(--muted); + margin-top: 2px; +} + +@media (max-width: 1400px) { + .page-layout { + display: block; + } + .context-rail { + width: 100%; + margin-top: 28px; + position: static; + min-height: 0 !important; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 10px; + } + .context-rail[hidden] { + display: none; + } + .context-rail .rail-item { + position: static; + margin-bottom: 0; + } +} + +/* ---- connect footer + modal ---- */ +#sidebar-foot { + margin-top: auto; + padding-top: 14px; + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +#connect-btn { + width: 100%; + display: flex; + align-items: center; + gap: 8px; + background: rgba(255, 255, 255, 0.05); + color: #c3c4cb; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 9px; + padding: 9px 12px; + font-size: 13.5px; + font-family: var(--sans); + cursor: pointer; + transition: background 0.12s, color 0.12s, border-color 0.12s; +} +#connect-btn:hover { + background: rgba(249, 115, 22, 0.14); + border-color: rgba(249, 115, 22, 0.4); + color: #fdba74; +} +#connect-btn .ico { + font-size: 15px; +} + +#modal[hidden] { + display: none; +} +#modal { + position: fixed; + inset: 0; + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + padding: 24px; +} +.modal-backdrop { + position: absolute; + inset: 0; + background: rgba(20, 18, 30, 0.5); + backdrop-filter: blur(2px); +} +.modal-card { + position: relative; + background: var(--panel); + border-radius: 16px; + width: 100%; + max-width: 620px; + max-height: 85vh; + overflow-y: auto; + box-shadow: 0 24px 70px rgba(20, 15, 50, 0.28); +} +.modal-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 18px 22px; + border-bottom: 1px solid var(--line); + position: sticky; + top: 0; + background: var(--panel); +} +.modal-title { + display: flex; + align-items: center; + gap: 10px; + font-family: var(--serif); + font-size: 21px; + letter-spacing: -0.01em; +} +.modal-logo { + width: 26px; + height: 26px; + object-fit: contain; +} +.modal-actions { + display: flex; + align-items: center; + gap: 8px; +} +.btn { + font-family: var(--sans); + font-size: 13.5px; + font-weight: 600; + border: 1px solid var(--line); + background: var(--panel); + color: var(--ink); + border-radius: 9px; + padding: 8px 13px; + cursor: pointer; + transition: background 0.12s, border-color 0.12s, color 0.12s; +} +.btn:hover { + border-color: var(--accent); + color: var(--accent-strong); +} +.btn.copied { + border-color: #1a8a55; + color: #1a8a55; +} +.btn.icon { + font-size: 18px; + line-height: 1; + padding: 6px 11px; + font-weight: 400; +} +.modal-body { + padding: 20px 22px 26px; +} +.modal-intro { + margin: 0 0 20px; + color: var(--muted); + line-height: 1.55; +} +#connect-steps { + list-style: none; + margin: 0; + padding: 0; +} +#connect-steps li { + margin-bottom: 18px; +} +.step-title { + font-weight: 600; + font-size: 14.5px; + margin-bottom: 8px; +} +.codeblock { + display: flex; + align-items: center; + gap: 8px; + background: #17181c; + border-radius: 10px; + padding: 11px 12px 11px 15px; +} +.codeblock code { + flex: 1; + min-width: 0; + overflow-x: auto; + white-space: nowrap; + font-family: var(--mono); + font-size: 13px; + color: #f0efff; + background: none; + padding: 0; +} +.codeblock .copy { + flex: 0 0 auto; + background: rgba(255, 255, 255, 0.08); + color: #c3c4cb; + border: 1px solid rgba(255, 255, 255, 0.14); + border-radius: 7px; + width: 30px; + height: 30px; + font-size: 14px; + cursor: pointer; + transition: background 0.12s, color 0.12s; +} +.codeblock .copy:hover { + background: rgba(249, 115, 22, 0.2); + color: #fdba74; +} +.codeblock .copy.copied { + color: #52d08a; +} + +@media (max-width: 720px) { + #app { + flex-direction: column; + } + #sidebar { + width: 100%; + flex: none; + height: auto; + position: static; + } + #content { + display: block; + width: 100%; + padding: 28px 20px 80px; + overflow-x: hidden; + } + #page { + width: 100%; + max-width: 100%; + } + #page h1 { + font-size: 30px; + } + .cell-head { + align-items: flex-start; + flex-direction: column; + gap: 4px; + } +} diff --git a/trackio/frontend_templates/logbook/logbook.js b/trackio/frontend_templates/logbook/logbook.js new file mode 100644 index 0000000000000000000000000000000000000000..8493abfc9d816bf6c220cca35233ca89bab143e6 --- /dev/null +++ b/trackio/frontend_templates/logbook/logbook.js @@ -0,0 +1,2275 @@ +(function () { + "use strict"; + + let MANIFEST = null; + const PAGE_CACHE = {}; + const UNFURL_CACHE = {}; + const LIVE_RELOAD_MS = 1500; + const FIGURE_FRAME_WINDOWS = new Set(); + let FIGURE_NAVIGATION_READY = false; + + function esc(s) { + return String(s) + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } + + function flattenTree(node, depth, acc) { + acc.push({ node: node, depth: depth }); + (node.children || []).forEach((c) => flattenTree(c, depth + 1, acc)); + return acc; + } + + function findNode(node, slug) { + if (node.slug === slug) return node; + for (const c of node.children || []) { + const hit = findNode(c, slug); + if (hit) return hit; + } + return null; + } + + /* -------------------- minimal markdown -------------------- */ + + function inline(text) { + let t = esc(text); + t = t.replace(/`([^`]+)`/g, (_, c) => `${c}`); + t = t.replace(/\*\*([^*]+)\*\*/g, (_, c) => `${c}`); + t = t.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, txt, url) => { + const safe = esc(url); + const attrs = /^https?:/.test(url) ? ' target="_blank" rel="noopener"' : ""; + const item = /^https?:/.test(url) ? classifyResource(url) : null; + const data = item + ? ` class="res-link" data-res-url="${esc(item.url)}"` + : ""; + return `${txt}`; + }); + t = t.replace(/(^|[\s(])(https?:\/\/[^\s<>)"'`]+)/g, (m, pre, url) => { + let rest = ""; + const cut = url.search(/"|'|<|>/); + if (cut !== -1) { + rest = url.slice(cut); + url = url.slice(0, cut); + } + const trailing = (url.match(/[.,;:!?`]+$/) || [""])[0]; + const clean = trailing ? url.slice(0, -trailing.length) : url; + if (!clean) return m; + const item = classifyResource(clean); + if (item) return `${pre}${resChipHtml(item)}${trailing}${rest}`; + return `${pre}${clean}${trailing}${rest}`; + }); + return t; + } + + function resChipHtml(item) { + return ( + `` + + `${RESOURCE_ICONS[item.kind]}` + + `${esc(item.id)}` + ); + } + + const URL_ONLY = /^(https?:\/\/[^\s]+)$/; + const DETECTED_URL = + /(https?:\/\/[^\s<>)\]"'`]+|trackio-local-dashboard:\/\/[^\s<>)\]"'`]+|trackio-artifact:\/\/[^\s<>)\]"'`]+|trackio-local-path:\/\/[^\s<>)\]"'`]+)/g; + + function renderMarkdown(md, container) { + const cellRe = /(^|\n)---\n\n([\s\S]*?)(?=\n---\n/g, "").split("\n"); + let i = 0; + let para = []; + + function flushPara() { + if (!para.length) return; + const joined = para.join(" ").trim(); + para = []; + if (!joined) return; + if (/^trackio-artifact:\/\/\S+$/.test(joined)) return; + if (/^trackio-local-path:\/\/\S+$/.test(joined)) return; + if (joined.indexOf("📦 Artifact") !== -1) { + const div = document.createElement("div"); + div.className = "artifact-chip"; + div.innerHTML = ARTIFACT_ICON_IMG + inline(joined.replace(/📦\s*/, "")); + container.appendChild(div); + return; + } + if (URL_ONLY.test(joined) || IMG_PATH.test(joined)) { + const el = renderStandaloneUrl(joined); + if (el) container.appendChild(el); + return; + } + const p = document.createElement("p"); + p.innerHTML = inline(joined); + container.appendChild(p); + } + + while (i < lines.length) { + const line = lines[i]; + const trimmed = line.trim(); + + if (trimmed === "") { + flushPara(); + i++; + continue; + } + const fence = trimmed.match(/^(`{3,}|~{3,})(.*)$/); + if (fence) { + flushPara(); + const marker = fence[1][0]; + const closeRe = new RegExp("^" + marker + "{" + fence[1].length + ",}\\s*$"); + const info = fence[2].trim(); + const buf = []; + i++; + while (i < lines.length && !closeRe.test(lines[i].trim())) { + buf.push(lines[i]); + i++; + } + i++; + const lang = (info.split(/\s+/)[0] || "").toLowerCase(); + const tm = info.match(/title=(\S+)/); + container.appendChild( + renderCode(buf.join("\n"), lang, tm ? tm[1] : null) + ); + continue; + } + if (trimmed === "---") { + flushPara(); + container.appendChild(document.createElement("hr")); + i++; + continue; + } + const h = trimmed.match(/^(#{1,4})\s+(.*)$/); + if (h) { + flushPara(); + const el = document.createElement("h" + h[1].length); + el.innerHTML = inline(h[2]); + container.appendChild(el); + i++; + continue; + } + if ( + trimmed.startsWith("|") && + i + 1 < lines.length && + /^\|?[\s:|-]*-{2,}[\s:|-]*\|?$/.test(lines[i + 1].trim()) + ) { + flushPara(); + const rows = []; + while (i < lines.length && lines[i].trim().startsWith("|")) { + rows.push(parseRow(lines[i].trim())); + i++; + } + renderTable(rows, container); + continue; + } + if (trimmed.startsWith("> ")) { + flushPara(); + const bq = document.createElement("blockquote"); + bq.innerHTML = inline(trimmed.slice(2)); + container.appendChild(bq); + i++; + continue; + } + if (/^`[^`]+`$/.test(trimmed)) { + flushPara(); + const el = document.createElement("div"); + el.className = "ts"; + el.textContent = trimmed.replace(/`/g, ""); + container.appendChild(el); + i++; + continue; + } + if (trimmed.startsWith("- ")) { + flushPara(); + const items = []; + while (i < lines.length && lines[i].trim().startsWith("- ")) { + items.push(lines[i].trim().slice(2).trim()); + i++; + } + renderList(items, container); + continue; + } + para.push(trimmed); + i++; + } + flushPara(); + } + + function renderCell(meta, body, container, artifacts) { + const cell = document.createElement("section"); + cell.className = `cell ${meta.type || "markdown"}`; + if (meta.id) cell.dataset.cellId = meta.id; + if (isPinned(meta)) cell.classList.add("pinned-source"); + + const head = document.createElement("div"); + head.className = "cell-head"; + const rawTitle = (meta.title || "").trim(); + const title = rawTitle && rawTitle.toLowerCase() !== "untitled" ? esc(rawTitle) : ""; + const when = meta.created_at ? `${esc(formatTime(meta.created_at))}` : ""; + head.innerHTML = + (title ? `
        ${title}
        ` : "") + + `
        ${when}
        `; + if (!title) head.classList.add("no-title"); + cell.appendChild(head); + + const bodyEl = document.createElement("div"); + bodyEl.className = "cell-body"; + if (meta.type === "code") { + renderCodeCell(body, bodyEl, artifacts); + } else if (meta.type === "figure") { + cell.dataset.resUrl = `trackio-figure://${(meta.title || "Figure").trim()}`; + renderFigureCell(body, bodyEl, head); + } else if (meta.type === "artifact") { + renderMarkdownPlain(body, bodyEl); + const chip = bodyEl.querySelector(".artifact-chip"); + const uri = body.match( + /(trackio-artifact:\/\/\S+|trackio-local-path:\/\/\S+|https:\/\/huggingface\.co\/buckets\/[^\s<)]+#\S+)/ + ); + if (chip && uri) chip.dataset.resUrl = uri[1]; + } else if (meta.type === "dashboard") { + const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/); + cell.dataset.resUrl = sp + ? sp[0] + : `trackio-local-dashboard://${(meta.dashboard_project || "").trim()}`; + renderDashboardCell(meta, body, bodyEl, head); + } else { + const cleaned = stripDuplicateTitle(body, meta.title); + renderMarkdownPlain(cleaned, bodyEl); + renderDetectedEmbeds(cleaned, bodyEl); + } + cell.appendChild(bodyEl); + container.appendChild(cell); + return cell; + } + + function isPinned(meta) { + return Boolean(meta && (meta.pinned === true || meta.pinned === "true")); + } + + function stripDuplicateTitle(body, title) { + if (!title) return body; + const m = body.match(/^\s*#{1,6}\s+([^\n]+)\n?/); + if (!m) return body; + const norm = (s) => + s + .toLowerCase() + .replace(/[*_`#]/g, "") + .replace(/\s+/g, " ") + .trim(); + return norm(m[1]) === norm(title) ? body.slice(m[0].length) : body; + } + + function formatTime(iso) { + const d = new Date(iso); + if (Number.isNaN(d.getTime())) return iso; + return d.toLocaleString(undefined, { + month: "short", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + }); + } + + function parseFences(text) { + const fenceRe = /(`{3,4}|~{3,4})([^\n]*)\n([\s\S]*?)\n\1/g; + const parts = []; + let pos = 0; + let match; + while ((match = fenceRe.exec(text))) { + if (match.index > pos) { + parts.push({ kind: "text", text: text.slice(pos, match.index) }); + } + const info = match[2].trim(); + const lang = (info.split(/\s+/)[0] || "").toLowerCase(); + const titleMatch = info.match(/title=(\S+)/); + parts.push({ + kind: lang === "result" || lang === "output" ? "output" : "code", + lang, + title: titleMatch ? titleMatch[1] : null, + text: match[3], + }); + pos = match.index + match[0].length; + } + if (pos < text.length) parts.push({ kind: "text", text: text.slice(pos) }); + return parts; + } + + function fitFigureFrame(frame, wrap) { + let doc; + try { + doc = frame.contentDocument; + } catch (e) { + return; + } + if (!doc || !doc.body) return; + frame.style.transform = "none"; + frame.style.width = "100%"; + frame.style.height = "auto"; + frame.style.position = ""; + frame.style.left = ""; + frame.style.top = ""; + const avail = wrap.clientWidth; + const isFullscreen = + document.fullscreenElement === wrap || + document.webkitFullscreenElement === wrap; + const availHeight = isFullscreen ? wrap.clientHeight : Infinity; + const cw = Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth, 1); + const ch = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight, 1); + const scale = Math.min(avail / cw, availHeight / ch); + if (avail && scale < 1 - 1e-3) { + frame.style.width = `${cw}px`; + frame.style.height = `${ch}px`; + frame.style.transformOrigin = "top left"; + frame.style.transform = `scale(${scale})`; + if (isFullscreen) { + frame.style.position = "absolute"; + frame.style.left = `${Math.max(0, (avail - cw * scale) / 2)}px`; + frame.style.top = `${Math.max(0, (availHeight - ch * scale) / 2)}px`; + wrap.style.height = "100%"; + } else { + wrap.style.height = `${Math.ceil(ch * scale)}px`; + } + } else { + frame.style.width = "100%"; + frame.style.height = `${ch}px`; + wrap.style.height = isFullscreen ? "100%" : `${ch}px`; + } + } + + function attachFigureFit(frame, wrap) { + const refit = () => fitFigureFrame(frame, wrap); + frame.addEventListener("load", refit); + if (window.ResizeObserver) { + const ro = new ResizeObserver(() => refit()); + ro.observe(wrap); + } + } + + function renderFigureCell(text, container, head) { + const parts = parseFences(text); + const htmlPart = parts.find((part) => part.lang === "html"); + const rawPart = parts.find((part) => part.lang === "raw"); + if (!htmlPart || !htmlPart.text.trim()) { + const empty = document.createElement("p"); + empty.className = "muted"; + empty.textContent = "No figure HTML."; + container.appendChild(empty); + return; + } + const frame = document.createElement("iframe"); + frame.className = "figure-frame"; + frame.sandbox = "allow-scripts allow-same-origin"; + frame.loading = "lazy"; + frame.srcdoc = htmlPart.text; + registerFigureNavigation(frame); + const figWrap = document.createElement("div"); + figWrap.className = "figure-fit"; + figWrap.appendChild(frame); + attachFigureFit(frame, figWrap); + if (head) { + const metaEl = head.querySelector(".cell-meta"); + if (metaEl) + metaEl.insertBefore(buildFullscreenControl(figWrap, frame), metaEl.firstChild); + } + if (!rawPart || !rawPart.text.trim()) { + container.appendChild(figWrap); + return; + } + const sw = document.createElement("div"); + sw.className = "fig-switch"; + const thumb = document.createElement("span"); + thumb.className = "fig-switch-thumb"; + const figBtn = document.createElement("button"); + figBtn.type = "button"; + figBtn.className = "active"; + figBtn.textContent = "Figure"; + const rawBtn = document.createElement("button"); + rawBtn.type = "button"; + rawBtn.textContent = "Raw"; + sw.appendChild(thumb); + sw.appendChild(figBtn); + sw.appendChild(rawBtn); + const rawView = document.createElement("div"); + rawView.className = "figure-raw"; + rawView.hidden = true; + const pre = document.createElement("pre"); + const code = document.createElement("code"); + code.textContent = rawPart.text; + pre.appendChild(code); + rawView.appendChild(pre); + rawView.appendChild(copySnippetBtn(rawPart.text)); + const select = (showRaw) => { + sw.classList.toggle("raw", showRaw); + figBtn.classList.toggle("active", !showRaw); + rawBtn.classList.toggle("active", showRaw); + figWrap.hidden = showRaw; + rawView.hidden = !showRaw; + }; + figBtn.addEventListener("click", () => select(false)); + rawBtn.addEventListener("click", () => select(true)); + if (head) { + head.insertBefore(sw, head.querySelector(".cell-meta")); + } else { + container.appendChild(sw); + } + container.appendChild(figWrap); + container.appendChild(rawView); + } + + // Poster embeds can send `{ type: "trackio-logbook:navigate", target: "..." }` + // from their iframe. Only accept messages from figure frames we created, and + // only route to pages that are present in this logbook's manifest. + function registerFigureNavigation(frame) { + const registerFrameWindow = () => { + if (frame.contentWindow) FIGURE_FRAME_WINDOWS.add(frame.contentWindow); + }; + // `srcdoc` replaces the initial about:blank document. Register after that + // navigation as well, so messages come from the live figure document. + frame.addEventListener("load", registerFrameWindow); + registerFrameWindow(); + if (FIGURE_NAVIGATION_READY) return; + FIGURE_NAVIGATION_READY = true; + window.addEventListener("message", (event) => { + if (!FIGURE_FRAME_WINDOWS.has(event.source)) return; + const message = event.data; + if (!message || message.type !== "trackio-logbook:navigate") return; + const target = String(message.target || "").replace(/^#?\//, ""); + if (!target || !MANIFEST || !findNode(MANIFEST.root, target)) return; + const hash = "#/" + target; + if (location.hash === hash) scrollToHash(); + else location.hash = hash; + }); + } + + const FULLSCREEN_ICON = + ''; + + // Figures are rendered in same-origin iframes, so fullscreen the fitted + // wrapper rather than the iframe document. This uses the browser's native + // fullscreen UI and preserves the figure's existing responsive sizing. + function buildFullscreenControl(figWrap, frame) { + const wrap = document.createElement("span"); + wrap.className = "cell-fullscreen"; + const btn = document.createElement("button"); + btn.type = "button"; + btn.className = "cell-fullscreen-btn"; + btn.setAttribute("aria-label", "Open figure in fullscreen"); + btn.title = "Open figure in fullscreen"; + btn.innerHTML = FULLSCREEN_ICON; + wrap.appendChild(btn); + + btn.addEventListener("click", async () => { + const request = figWrap.requestFullscreen || figWrap.webkitRequestFullscreen; + if (!request) return; + try { + await request.call(figWrap); + } catch (_) { + // Fullscreen can be disabled by the embedding browser or policy. + } + }); + document.addEventListener("fullscreenchange", () => { + if (document.fullscreenElement === figWrap) fitFigureFrame(frame, figWrap); + }); + return wrap; + } + + function extractUrls(text) { + const seen = new Set(); + const urls = []; + let match; + while ((match = DETECTED_URL.exec(text))) { + const url = match[1].replace(/[.,;:!?'"`]+$/, ""); + if (!seen.has(url)) { + seen.add(url); + urls.push(url); + } + } + DETECTED_URL.lastIndex = 0; + return urls; + } + + const IMG_URL = /(\.(png|jpe?g|gif|svg|webp)(\?|$)|\/artifact_blob\/)/i; + + function renderDetectedEmbeds(text, container) { + extractUrls(text).forEach((url) => { + if (url.startsWith("trackio-local-dashboard://")) { + const div = document.createElement("div"); + div.className = "artifact-chip"; + div.dataset.resUrl = url; + div.innerHTML = + "🎯 Local Trackio dashboard — publish the logbook to share it"; + container.appendChild(div); + } else if (IMG_URL.test(url)) { + container.appendChild(renderImage(url)); + } else if (/huggingface\.co\/spaces\//.test(url)) { + maybeEmbedTrackioSpace(url, container); + } + }); + } + + function renderStandaloneUrl(url) { + if (IMG_URL.test(url) || IMG_PATH.test(url)) return renderImage(url); + const item = classifyResource(url); + if (item) { + const marker = document.createElement("span"); + marker.className = "resource-anchor"; + marker.dataset.resUrl = item.url; + marker.setAttribute("aria-hidden", "true"); + return marker; + } + const p = document.createElement("p"); + p.innerHTML = inline(url); + return p; + } + + function renderImage(url) { + const a = document.createElement("a"); + a.className = "unfurl image"; + a.href = url; + a.target = "_blank"; + a.rel = "noopener"; + const img = document.createElement("img"); + img.loading = "lazy"; + img.src = url; + img.alt = "artifact image"; + a.appendChild(img); + return a; + } + + function maybeEmbedTrackioSpace(url, container) { + const id = url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, ""); + const holder = document.createElement("div"); + container.appendChild(holder); + getJSON(`https://huggingface.co/api/spaces/${id}`).then((d) => { + const tags = (d && d.tags) || []; + if (tags.some((t) => String(t).toLowerCase() === "trackio")) { + renderTrackioSpaceEmbed(holder, url, id); + } else { + holder.remove(); + } + }); + } + + function jpGutter(label) { + const g = document.createElement("div"); + g.className = "jp-gutter"; + g.textContent = label; + return g; + } + + function renderOutArtifact(info) { + const remote = !info.local && !!info.url; + const el = document.createElement(remote ? "a" : "div"); + el.className = "out-artifact"; + if (remote) { + el.href = info.url; + el.target = "_blank"; + el.rel = "noopener"; + } + el.dataset.resUrl = info.resUrl; + const parts = [info.type, info.size].filter(Boolean).map(esc); + const state = remote + ? `Open ↗` + : `publish to share`; + const meta = parts.length ? `${parts.join(" · ")} · ${state}` : state; + el.innerHTML = + `${ARTIFACT_ICON_IMG}` + + `${esc(info.name)}` + + `${meta}`; + return el; + } + + function renderCodeCell(body, container, artifacts) { + const parts = parseFences(body); + const block = document.createElement("div"); + block.className = "jp"; + const input = document.createElement("div"); + input.className = "jp-in"; + const inputBody = document.createElement("div"); + inputBody.className = "jp-in-body"; + input.appendChild(jpGutter("In")); + input.appendChild(inputBody); + let metaEl = null; + let outputEl = null; + let outBody = null; + const ensureOut = () => { + if (outputEl) return; + outputEl = document.createElement("div"); + outputEl.className = "jp-out"; + outputEl.appendChild(jpGutter("Out")); + outBody = document.createElement("div"); + outBody.className = "jp-out-body"; + outputEl.appendChild(outBody); + }; + const embedTexts = []; + parts.forEach((part) => { + if (part.kind === "text") { + const text = part.text.trim(); + if (!text) return; + if (/^exit\s+\S+(\s|·)/.test(text)) { + metaEl = document.createElement("div"); + metaEl.className = "jp-meta"; + metaEl.textContent = text.replace( + /\s*·\s*[A-Z][a-z]{2} \d{1,2}, \d{4}.*$/, + "" + ); + } else { + renderMarkdownPlain(text, container); + embedTexts.push(text); + } + return; + } + if (part.kind === "output") { + ensureOut(); + const pre = document.createElement("pre"); + pre.className = "jp-out-pre"; + const c = document.createElement("code"); + c.textContent = part.text; + pre.appendChild(c); + outBody.appendChild(pre); + outputEl.appendChild(copySnippetBtn(part.text)); + embedTexts.push(part.text); + return; + } + inputBody.appendChild(renderCode(part.text, part.lang, part.title)); + }); + if (artifacts && artifacts.length) { + ensureOut(); + const artWrap = document.createElement("div"); + artWrap.className = "jp-artifacts"; + artifacts.forEach((a) => { + artWrap.appendChild( + renderOutArtifact(artifactInfoFromCell(a.meta, a.body)) + ); + }); + outBody.appendChild(artWrap); + } + if (inputBody.childNodes.length > 0) block.appendChild(input); + if (metaEl) block.appendChild(metaEl); + if (outputEl) block.appendChild(outputEl); + if (block.childNodes.length) container.appendChild(block); + embedTexts.forEach((text) => renderDetectedEmbeds(text, container)); + } + + function parseRow(line) { + let s = line.trim(); + if (s.startsWith("|")) s = s.slice(1); + if (s.endsWith("|")) s = s.slice(0, -1); + return s.split(/(? c.replace(/\\\|/g, "|").trim()); + } + + const TRUTHY = ["x", "✓", "✔", "yes", "done", "true", "[x]"]; + const CHIP_COLORS = [ + ["#e7f0ff", "#2158d0"], + ["#fde8ec", "#c62a4b"], + ["#e6f7ee", "#1a8a55"], + ["#fdf0e0", "#b26a12"], + ["#efe9ff", "#5b3bd6"], + ["#e6f6f8", "#127b88"], + ]; + + function chipColor(name) { + let h = 0; + for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0; + return CHIP_COLORS[h % CHIP_COLORS.length]; + } + + const STATUS_MAP = { + "": ["Planned", "gray"], + planned: ["Planned", "gray"], + todo: ["Planned", "gray"], + "to do": ["Planned", "gray"], + backlog: ["Planned", "gray"], + "in progress": ["In progress", "amber"], + "in-progress": ["In progress", "amber"], + wip: ["In progress", "amber"], + running: ["In progress", "amber"], + active: ["In progress", "amber"], + done: ["Done", "green"], + complete: ["Done", "green"], + completed: ["Done", "green"], + blocked: ["Blocked", "red"], + failed: ["Failed", "red"], + abandoned: ["Abandoned", "gray"], + }; + + function statusBadge(val) { + const [label, tone] = STATUS_MAP[val.toLowerCase()] || [val || "—", "gray"]; + return `${esc(label)}`; + } + + function renderTable(rows, container) { + if (rows.length < 2) return; + const header = rows[0]; + const body = rows.slice(2); + const roles = header.map((h) => { + const t = h.toLowerCase(); + if (t.includes("status") || t.includes("state")) return "status"; + if (t.includes("progress") || t.includes("complete") || t.includes("done")) + return "check"; + if (t === "who" || t.includes("assign") || t.includes("owner")) return "who"; + return "text"; + }); + const table = document.createElement("table"); + table.className = "board"; + const thead = document.createElement("thead"); + const htr = document.createElement("tr"); + header.forEach((h, c) => { + const th = document.createElement("th"); + th.textContent = h; + if (roles[c] === "check") th.className = "col-check"; + htr.appendChild(th); + }); + thead.appendChild(htr); + table.appendChild(thead); + const tbody = document.createElement("tbody"); + body.forEach((cells) => { + const nonEmpty = cells.filter((x) => x !== "").length; + if (header.length > 1 && nonEmpty === 1 && cells[0]) { + const tr = document.createElement("tr"); + tr.className = "section-row"; + const td = document.createElement("td"); + td.colSpan = header.length; + td.innerHTML = inline(cells[0]); + tr.appendChild(td); + tbody.appendChild(tr); + return; + } + const tr = document.createElement("tr"); + header.forEach((_, c) => { + const td = document.createElement("td"); + const val = (cells[c] || "").trim(); + if (roles[c] === "status") { + td.className = "col-status"; + td.innerHTML = statusBadge(val); + } else if (roles[c] === "check") { + td.className = "col-check"; + const on = TRUTHY.indexOf(val.toLowerCase()) !== -1; + td.innerHTML = `${on ? "✓" : ""}`; + } else if (roles[c] === "who") { + if (!val || /^to assign$/i.test(val)) { + td.innerHTML = `${esc(val || "—")}`; + } else { + const [bg, fg] = chipColor(val); + td.innerHTML = `${esc(val)}`; + } + } else { + td.innerHTML = inline(val); + } + tr.appendChild(td); + }); + const link = tr.querySelector('a[href^="#/"]'); + if (link) { + tr.classList.add("linked-row"); + tr.addEventListener("click", (e) => { + if (e.target.tagName !== "A") location.hash = link.getAttribute("href"); + }); + } + tbody.appendChild(tr); + }); + table.appendChild(tbody); + const wrap = document.createElement("div"); + wrap.className = "board-wrap"; + wrap.appendChild(table); + container.appendChild(wrap); + } + + const HL_RULES = { + python: [ + ["comment", /#[^\n]*/], + ["string", /'''[\s\S]*?'''|"""[\s\S]*?"""|'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/], + [ + "keyword", + /\b(?:def|class|return|if|elif|else|for|while|import|from|as|with|try|except|finally|raise|in|not|and|or|is|None|True|False|lambda|yield|global|nonlocal|assert|pass|break|continue|async|await|print)\b/, + ], + ["number", /\b\d[\d_.eE+-]*\b/], + ], + bash: [ + ["comment", /#[^\n]*/], + ["string", /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/], + ["keyword", /\b(?:if|then|else|fi|for|in|do|done|while|case|esac|function|export|source|echo|cd|return|local)\b/], + ["number", /(?<=\s)-{1,2}[a-zA-Z][\w-]*/], + ], + json: [ + ["string", /"(?:\\.|[^"\\])*"/], + ["keyword", /\b(?:true|false|null)\b/], + ["number", /-?\b\d[\d.eE+-]*\b/], + ], + yaml: [ + ["comment", /#[^\n]*/], + ["string", /'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"/], + ["keyword", /\b(?:true|false|null|yes|no)\b/], + ["number", /-?\b\d[\d.eE+-]*\b/], + ], + }; + HL_RULES.javascript = HL_RULES.python; + HL_RULES.typescript = HL_RULES.python; + HL_RULES.sql = [ + ["comment", /--[^\n]*/], + ["string", /'(?:\\.|[^'\\])*'/], + [ + "keyword", + /\b(?:SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|OUTER|ON|GROUP|BY|ORDER|LIMIT|INSERT|INTO|VALUES|UPDATE|SET|DELETE|CREATE|TABLE|AS|AND|OR|NOT|NULL|COUNT|DISTINCT|IN)\b/i, + ], + ["number", /\b\d[\d.]*\b/], + ]; + + function highlightCode(code, lang) { + const rules = HL_RULES[lang]; + if (!rules) return esc(code); + const combined = new RegExp(rules.map((r) => "(" + r[1].source + ")").join("|"), "g"); + let out = ""; + let last = 0; + let m; + while ((m = combined.exec(code))) { + if (m[0] === "") { + combined.lastIndex++; + continue; + } + out += esc(code.slice(last, m.index)); + let gi = 1; + while (gi < m.length && m[gi] === undefined) gi++; + out += `${esc(m[0])}`; + last = m.index + m[0].length; + } + out += esc(code.slice(last)); + return out; + } + + function copySnippetBtn(text) { + const btn = document.createElement("button"); + btn.type = "button"; + btn.className = "copy-snippet"; + btn.title = "Copy"; + btn.textContent = "⧉"; + btn.addEventListener("click", (e) => { + e.preventDefault(); + e.stopPropagation(); + copyText(text, btn, "⧉"); + }); + return btn; + } + + function renderCode(code, lang, title) { + const pre = document.createElement("pre"); + pre.className = "hl"; + const c = document.createElement("code"); + c.innerHTML = highlightCode(code, lang); + pre.appendChild(c); + if (!title) { + const wrap = document.createElement("div"); + wrap.className = "snippet"; + wrap.appendChild(pre); + wrap.appendChild(copySnippetBtn(code)); + return wrap; + } + const det = document.createElement("details"); + det.className = "code-accordion"; + det.dataset.resUrl = `trackio-script://${title}`; + const sum = document.createElement("summary"); + sum.innerHTML = + `</>` + + `${esc(title)}`; + sum + .querySelector(".code-name") + .addEventListener("click", (e) => e.preventDefault()); + det.appendChild(sum); + const wrap = document.createElement("div"); + wrap.className = "snippet"; + wrap.appendChild(pre); + wrap.appendChild(copySnippetBtn(code)); + det.appendChild(wrap); + return det; + } + + const IMG_PATH = /^[^\s]+\.(png|jpe?g|gif|svg|webp)$/i; + + function renderList(items, container) { + let ul = null; + items.forEach((item) => { + if (URL_ONLY.test(item) || IMG_PATH.test(item)) { + const el = renderStandaloneUrl(item); + if (el) { + ul = null; + container.appendChild(el); + } + } else if (item.indexOf("📦 Artifact") !== -1) { + ul = null; + const div = document.createElement("div"); + div.className = "artifact-chip"; + div.innerHTML = inline(item.replace("📦", "🪣")); + container.appendChild(div); + } else if (item.indexOf("trackio-local-dashboard://") !== -1) { + ul = null; + const uri = item.match(/trackio-local-dashboard:\/\/\S+/)?.[0] || ""; + const div = document.createElement("div"); + div.className = "artifact-chip"; + if (uri) div.dataset.resUrl = uri; + div.innerHTML = + "🎯 Local dashboard — publish the logbook to share it"; + container.appendChild(div); + } else { + if (!ul) { + ul = document.createElement("ul"); + container.appendChild(ul); + } + const li = document.createElement("li"); + li.innerHTML = inline(item); + ul.appendChild(li); + } + }); + } + + /* -------------------- resources rail -------------------- */ + + function fmt(n) { + if (n == null) return null; + if (n >= 1e6) return (n / 1e6).toFixed(1) + "M"; + if (n >= 1e3) return (n / 1e3).toFixed(1) + "k"; + return String(n); + } + + const RESOURCE_SECTIONS = [ + ["dashboard", "Dashboards", "🎯"], + ["model", "Models", "🤗"], + ["dataset", "Datasets", "📊"], + ["space", "Spaces", "🚀"], + ["artifact", "Artifacts", "🪣"], + ["paper", "Papers", "📄"], + ["repo", "Code", "🐙"], + ["job", "Jobs", "⚙️"], + ["bucket", "Buckets", "🪣"], + ]; + + const RESOURCE_ICONS = Object.fromEntries( + RESOURCE_SECTIONS.map(([kind, , icon]) => [kind, icon]) + ); + + const ARTIFACT_ICON_IMG = ``; + const DASHBOARD_ICON_IMG = ``; + + const RESOURCE_DESC = { + dashboard: "Dashboard", + model: "Model", + dataset: "Dataset", + space: "Space", + artifact: "Artifact — in Bucket", + paper: "Paper", + repo: "Repository", + job: "Job — status & logs", + bucket: "Bucket — artifacts & data", + }; + + const HF_NON_MODEL_PREFIX = + /^(datasets|spaces|jobs|buckets|papers|blog|docs|api|posts|collections|organizations|settings|new|join|login|pricing|tasks|learn|chat|models)(\/|$)/; + + function hfId(url, marker) { + return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, ""); + } + + function classifyResource(url) { + if (IMG_URL.test(url)) { + return null; + } + let m; + if (url.startsWith("trackio-local-dashboard://")) { + return { + kind: "dashboard", + id: url.slice("trackio-local-dashboard://".length), + url, + local: true, + }; + } + if (url.startsWith("trackio-artifact://")) { + return { + kind: "artifact", + id: url.slice("trackio-artifact://".length), + url, + local: true, + }; + } + if (url.startsWith("trackio-local-path://")) { + return { + kind: "artifact", + id: url.slice("trackio-local-path://".length), + url, + local: true, + }; + } + if ((m = url.match(/huggingface\.co\/buckets\/[^#\s]+#(.+)/))) { + return { kind: "artifact", id: decodeURIComponent(m[1]), url }; + } + if (/huggingface\.co\/datasets\/[^/]+\/[^/]+/.test(url)) { + return { kind: "dataset", id: hfId(url, "/datasets/"), url }; + } + if (/huggingface\.co\/spaces\/[^/]+\/[^/]+/.test(url)) { + return { kind: "space", id: hfId(url, "/spaces/"), url }; + } + if (/huggingface\.co\/jobs\//.test(url)) { + const parts = hfId(url, "/jobs/").split("/"); + const jid = parts[1] || ""; + return { + kind: "job", + id: parts[0] + (jid ? ` · ${jid.slice(0, 12)}${jid.length > 12 ? "…" : ""}` : ""), + url, + }; + } + if (/huggingface\.co\/buckets\//.test(url)) { + return { kind: "bucket", id: hfId(url, "/buckets/"), url }; + } + if (/huggingface\.co\/papers\//.test(url)) { + return { kind: "paper", id: `Paper ${hfId(url, "/papers/")}`, url }; + } + if ((m = url.match(/arxiv\.org\/(?:abs|pdf)\/([^?#\s]+)/))) { + return { kind: "paper", id: `arXiv:${m[1].replace(/\.pdf$/, "")}`, url }; + } + if ((m = url.match(/github\.com\/([^/?#]+\/[^/?#]+)/))) { + return { kind: "repo", id: m[1], url }; + } + if ((m = url.match(/huggingface\.co\/([^?#]+)/))) { + const rest = m[1].replace(/\/$/, ""); + if (/^[^/]+\/[^/]+$/.test(rest) && !HF_NON_MODEL_PREFIX.test(rest)) { + return { kind: "model", id: rest, url }; + } + } + return null; + } + + async function fillRailMeta(item, el) { + if (item.local) return; + const meta = el.querySelector(".rail-meta"); + const set = (parts) => { + const text = parts.filter(Boolean).join(" · "); + if (text) meta.textContent = text; + }; + if (item.kind === "model") { + const d = await getJSON(`https://huggingface.co/api/models/${item.id}`); + if (d) set([d.pipeline_tag, `↓ ${fmt(d.downloads)}`, `♥ ${fmt(d.likes)}`]); + } else if (item.kind === "dataset") { + const d = await getJSON(`https://huggingface.co/api/datasets/${item.id}`); + if (d) set([`↓ ${fmt(d.downloads)}`, `♥ ${fmt(d.likes)}`]); + } else if (item.kind === "space" || item.kind === "dashboard") { + const d = await getJSON(`https://huggingface.co/api/spaces/${item.id}`); + if (d) set([d.sdk, `♥ ${fmt(d.likes)}`]); + } else if (item.kind === "repo") { + const d = await getJSON(`https://api.github.com/repos/${item.id}`); + if (d) set([`★ ${fmt(d.stargazers_count)}`, d.language]); + } else if (item.kind === "paper") { + const m = item.id.match(/^(?:arXiv:|Paper )(.+)$/); + if (!m) return; + const arxivId = m[1].replace(/v\d+$/, ""); + const d = await getJSON(`https://huggingface.co/api/papers/${arxivId}`); + if (d && d.id) { + if (el.href) el.href = `https://huggingface.co/papers/${d.id}`; + const title = + d.title && d.title.length > 70 ? `${d.title.slice(0, 69)}…` : d.title; + set([title, d.upvotes ? `▲ ${fmt(d.upvotes)}` : null]); + } + } + } + + const BARE_ID_SKIP_DIRS = new Set([ + "scripts", + "configs", + "config", + "results", + "figures", + "data", + "datasets", + "src", + "tests", + "test", + "examples", + "pages", + "assets", + "docs", + "outputs", + "output", + "checkpoints", + "models", + "utils", + "lib", + "bin", + "tmp", + "node_modules", + "dist", + "build", + ]); + const FILE_EXT_RE = + /\.(py|pyc|js|ts|jsx|tsx|json|jsonl|yaml|yml|csv|tsv|md|txt|sh|bash|html|css|png|jpe?g|svg|gif|webp|ipynb|toml|cfg|ini|lock|pdf|whl|gz|zip|tar|pt|pth|bin|safetensors|db|sqlite)$/i; + + async function detectBareModelIds(text, groups) { + const stripped = text.replace(DETECTED_URL, " "); + DETECTED_URL.lastIndex = 0; + const seen = new Set(); + const candidates = []; + const re = /(^|[\s"'`(=[])([A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*)/g; + let m; + while ((m = re.exec(stripped)) && candidates.length < 15) { + const id = m[2].replace(/[.:,]+$/, ""); + if (seen.has(id)) continue; + seen.add(id); + if (FILE_EXT_RE.test(id)) continue; + if (BARE_ID_SKIP_DIRS.has(id.split("/")[0].toLowerCase())) continue; + candidates.push(id); + } + const results = await Promise.all( + candidates.map((id) => getJSON(`https://huggingface.co/api/models/${id}`)) + ); + let added = false; + const confirmed = []; + results.forEach((d, i) => { + if (!d || !d.id) return; + const id = candidates[i]; + confirmed.push(id); + const url = `https://huggingface.co/${id}`; + if (!groups.has("model")) groups.set("model", new Map()); + if (!groups.get("model").has(url)) { + groups.get("model").set(url, { kind: "model", id, url }); + added = true; + } + }); + return { added, confirmed }; + } + + function chipifyBareIds(ids, container) { + if (!ids.length) return; + const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")); + const pattern = new RegExp("(" + escaped.join("|") + ")"); + const splitter = new RegExp(pattern.source, "g"); + container + .querySelectorAll(".cell.markdown .cell-body") + .forEach((body) => { + const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, { + acceptNode(node) { + if (!pattern.test(node.nodeValue)) return NodeFilter.FILTER_REJECT; + for ( + let el = node.parentElement; + el && el !== body; + el = el.parentElement + ) { + if (["A", "CODE", "PRE", "BUTTON"].indexOf(el.tagName) !== -1) { + return NodeFilter.FILTER_REJECT; + } + } + return NodeFilter.FILTER_ACCEPT; + }, + }); + const nodes = []; + while (walker.nextNode()) nodes.push(walker.currentNode); + nodes.forEach((node) => { + const frag = document.createDocumentFragment(); + node.nodeValue.split(splitter).forEach((part) => { + if (ids.indexOf(part) !== -1) { + const holder = document.createElement("span"); + holder.innerHTML = resChipHtml({ + kind: "model", + id: part, + url: `https://huggingface.co/${part}`, + }); + frag.appendChild(holder.firstChild); + } else if (part) { + frag.appendChild(document.createTextNode(part)); + } + }); + node.parentNode.replaceChild(frag, node); + }); + }); + } + + let RAIL_TOKEN = 0; + const RAIL_EXCLUDE_KINDS = new Set(["paper", "repo", "artifact", "dashboard"]); + + function railDashboardItem(it) { + return { + kind: "dashboard", + id: it.id, + url: it.local ? it.resUrl : it.url || it.resUrl, + local: it.local, + railLabel: "Dashboard", + }; + } + + function promoteTrackioSpacesInRail(groups, dashResUrls, body, rail, token) { + const spaceGroup = groups.get("space"); + if (!spaceGroup || !spaceGroup.size) return; + spaceGroup.forEach((item, url) => { + getJSON(`https://huggingface.co/api/spaces/${item.id}`) + .then((d) => { + if (rail.dataset.renderToken !== token) return; + const tags = (d && d.tags) || []; + if (!tags.some((t) => String(t).toLowerCase() === "trackio")) return; + if (dashResUrls.has(url)) return; + spaceGroup.delete(url); + if (!spaceGroup.size) groups.delete("space"); + if (!groups.has("dashboard")) groups.set("dashboard", new Map()); + groups.get("dashboard").set(url, { + kind: "dashboard", + id: item.id, + url: item.url, + local: false, + railLabel: "Dashboard", + }); + dashResUrls.add(url); + paintRail(groups, body, rail); + }) + .catch(() => {}); + }); + } + + function renderRail(md, body, rail) { + const token = String(++RAIL_TOKEN); + rail.dataset.renderToken = token; + const scanText = md.replace( + /(`{3,4}|~{3,4})(html|raw)[^\n]*\n[\s\S]*?\n\1/g, + " " + ); + const groups = new Map(); + const dashMap = new Map(); + const dashResUrls = new Set(); + cellDashboardItems(md).forEach((it) => { + if (dashMap.has(it.resUrl)) return; + dashMap.set(it.resUrl, railDashboardItem(it)); + dashResUrls.add(it.resUrl); + }); + if (dashMap.size) groups.set("dashboard", dashMap); + extractUrls(scanText).forEach((url) => { + const item = classifyResource(url); + if (!item) return; + if (RAIL_EXCLUDE_KINDS.has(item.kind)) return; + if (dashResUrls.has(url)) return; + if (!groups.has(item.kind)) groups.set(item.kind, new Map()); + groups.get(item.kind).set(item.url, item); + }); + const artMap = new Map(); + cellArtifactItems(md).forEach((it) => { + if (artMap.has(it.resUrl)) return; + const label = it.type + ? it.type.charAt(0).toUpperCase() + it.type.slice(1) + : "Artifact"; + artMap.set(it.resUrl, { + kind: "artifact", + id: it.name, + url: it.local ? it.resUrl : it.url || it.resUrl, + local: it.local, + railLabel: label, + size: it.size, + }); + }); + if (artMap.size) groups.set("artifact", artMap); + paintRail(groups, body, rail); + promoteTrackioSpacesInRail(groups, dashResUrls, body, rail, token); + detectBareModelIds(scanText, groups) + .then((result) => { + if (rail.dataset.renderToken !== token) return; + chipifyBareIds(result.confirmed, body); + if (result.added) paintRail(groups, body, rail); + }) + .catch(() => {}); + } + + function paintRail(groups, body, rail) { + rail.innerHTML = ""; + RESOURCE_SECTIONS.forEach(([kind, label, icon]) => { + const group = groups.get(kind); + if (!group || !group.size) return; + group.forEach((item) => { + const el = document.createElement(item.local ? "div" : "a"); + el.className = item.local ? "rail-item rail-local" : "rail-item"; + if (!item.local) { + el.href = item.url; + el.target = "_blank"; + el.rel = "noopener"; + } + el.dataset.resUrl = item.url; + let desc; + if (kind === "artifact") { + const state = item.local ? "publish to share" : "Open ↗"; + desc = item.size ? `${item.size} · ${state}` : state; + } else if (kind === "dashboard") { + desc = item.local ? "publish to share" : "Open ↗"; + } else { + desc = item.local ? "publish to share" : RESOURCE_DESC[kind]; + } + const kindLabel = item.railLabel || label.replace(/s$/, ""); + const iconHtml = + kind === "artifact" + ? ARTIFACT_ICON_IMG + : kind === "dashboard" + ? DASHBOARD_ICON_IMG + : `${icon}`; + el.innerHTML = + `
        ${iconHtml}${esc(kindLabel)}
        ` + + `
        ${esc(item.id)}
        ` + + `
        ${esc(desc)}
        `; + rail.appendChild(el); + fillRailMeta(item, el) + .catch(() => {}) + .finally(() => scheduleRailPosition(body, rail)); + }); + }); + rail.hidden = !rail.childElementCount; + scheduleRailPosition(body, rail); + } + + function resourceAnchor(body, url) { + return body.querySelector(`[data-res-url="${CSS.escape(url)}"]`); + } + + function positionRail(body, rail) { + if (rail.hidden || !rail.isConnected) return; + const bodyRect = body.getBoundingClientRect(); + const items = Array.from(rail.querySelectorAll(".rail-item")).map((el, index) => { + const anchor = resourceAnchor(body, el.dataset.resUrl); + return { + el, + index, + desired: anchor + ? Math.max(0, anchor.getBoundingClientRect().top - bodyRect.top) + : 0, + }; + }); + items.sort((a, b) => a.desired - b.desired || a.index - b.index); + let cursor = 0; + items.forEach(({ el, desired }) => { + const top = Math.max(desired, cursor); + el.style.top = `${top}px`; + cursor = top + el.offsetHeight + 10; + }); + rail.style.minHeight = `${Math.max(body.offsetHeight, cursor)}px`; + } + + function scheduleRailPosition(body, rail) { + cancelAnimationFrame(Number(rail.dataset.positionFrame || 0)); + rail.dataset.positionFrame = String( + requestAnimationFrame(() => positionRail(body, rail)) + ); + } + + function dashboardSubdomainFromUrl(url) { + return spaceIdFromUrl(url).toLowerCase().replace(/[^a-z0-9-]/g, "-"); + } + + function dashboardOpenLink(head, url) { + if (!head || !url) return; + const meta = head.querySelector(".cell-meta"); + if (!meta) return; + let link = meta.querySelector(".cell-open"); + if (!link) { + link = document.createElement("a"); + link.className = "cell-open"; + link.target = "_blank"; + link.rel = "noopener"; + meta.insertBefore(link, meta.firstChild); + } + link.href = url; + link.textContent = "Open ↗"; + } + + function dashboardFrame(src) { + const iframe = document.createElement("iframe"); + iframe.className = "dashboard-frame"; + iframe.src = src; + iframe.loading = "lazy"; + iframe.allow = "clipboard-read; clipboard-write; fullscreen"; + return iframe; + } + + function renderDashboardCell(meta, body, container, head) { + const project = meta.dashboard_project || ""; + const holder = document.createElement("div"); + holder.className = "dashboard-shell"; + container.appendChild(holder); + const space = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/); + if (space) { + const url = space[0]; + dashboardOpenLink(head, url); + holder.appendChild( + dashboardFrame( + `https://${dashboardSubdomainFromUrl(url)}.hf.space/?sidebar=hidden&hide_empty_tabs=true` + ) + ); + return; + } + if (!isLocalPreview()) { + holder.className = "artifact-chip"; + holder.dataset.resUrl = `trackio-local-dashboard://${project}`; + holder.innerHTML = + "🎯 Local Trackio dashboard — publish the logbook to share it"; + return; + } + const open = "/dashboard/?project=" + encodeURIComponent(project); + dashboardOpenLink(head, open); + holder.appendChild( + dashboardFrame(open + "&sidebar=hidden&hide_empty_tabs=true"), + ); + } + + const CACHE_PREFIX = "trackio-logbook:"; + const CACHE_TTL_MS = 24 * 60 * 60 * 1000; + const CACHE_MISS_TTL_MS = 60 * 60 * 1000; + + function cacheGet(url) { + try { + const raw = localStorage.getItem(CACHE_PREFIX + url); + if (!raw) return undefined; + const entry = JSON.parse(raw); + const ttl = entry.d === null ? CACHE_MISS_TTL_MS : CACHE_TTL_MS; + if (Date.now() - entry.t > ttl) { + localStorage.removeItem(CACHE_PREFIX + url); + return undefined; + } + return entry.d; + } catch (e) { + return undefined; + } + } + + function cacheSet(url, data) { + try { + localStorage.setItem( + CACHE_PREFIX + url, + JSON.stringify({ t: Date.now(), d: data }) + ); + } catch (e) {} + } + + async function getJSON(url) { + if (UNFURL_CACHE[url] !== undefined) return UNFURL_CACHE[url]; + const cached = cacheGet(url); + if (cached !== undefined) { + UNFURL_CACHE[url] = cached; + return cached; + } + try { + const r = await fetch(url); + if (!r.ok) throw new Error(r.status); + const j = await r.json(); + UNFURL_CACHE[url] = j; + cacheSet(url, j); + return j; + } catch (e) { + UNFURL_CACHE[url] = null; + cacheSet(url, null); + return null; + } + } + + /* -------------------- routing / render -------------------- */ + + function buildTree() { + const tree = document.getElementById("tree"); + tree.innerHTML = ""; + const nodes = []; + (MANIFEST.root.children || []).forEach((c) => flattenTree(c, 0, nodes)); + nodes.forEach(({ node, depth }) => { + const a = document.createElement("a"); + a.href = "#/" + node.slug; + a.className = "depth-" + depth; + a.dataset.slug = node.slug; + const mark = document.createElement("span"); + mark.className = "tree-mark"; + mark.textContent = "§"; + a.appendChild(mark); + a.appendChild(document.createTextNode(" " + node.title)); + tree.appendChild(a); + }); + } + + function highlight(slug) { + document + .querySelectorAll("#tree a") + .forEach((a) => a.classList.toggle("active", a.dataset.slug === slug)); + document + .getElementById("book-head") + .classList.toggle("active", slug === MANIFEST.root.slug); + } + + function clearPageCache() { + Object.keys(PAGE_CACHE).forEach((key) => { + delete PAGE_CACHE[key]; + }); + } + + function isLocalPreview() { + return ["localhost", "127.0.0.1", "::1"].includes(location.hostname); + } + + async function fetchManifest() { + const suffix = isLocalPreview() ? `?t=${Date.now()}` : ""; + return await (await fetch("./logbook.json" + suffix, { cache: "no-store" })).json(); + } + + async function fetchPage(node) { + if (PAGE_CACHE[node.file]) return PAGE_CACHE[node.file]; + try { + const suffix = isLocalPreview() + ? `?rev=${encodeURIComponent(MANIFEST.revision || "")}` + : ""; + const r = await fetch("./" + node.file + suffix, { cache: "no-store" }); + PAGE_CACHE[node.file] = await r.text(); + } catch (e) { + PAGE_CACHE[node.file] = "# " + node.title + "\n\n_Could not load section._"; + } + return PAGE_CACHE[node.file]; + } + + function allNodes() { + const nodes = []; + flattenTree(MANIFEST.root, 0, nodes); + return nodes.map(({ node }) => node); + } + + function collectPinnedCells(markdown, nodes) { + const cells = []; + markdown.forEach((text, index) => { + const cellRe = /(^|\n)---\n\n([\s\S]*?)(?=\n---\n\n([\s\S]*?)(?=\n---\n + + + +
        + +
        +
        + +
        + +
        + + + + + + + + + + + +
        Trace IDRequestRunStepRequest time
        +
        +
        + + + + + + + + diff --git a/trackio/frontend_templates/starter/styles.css b/trackio/frontend_templates/starter/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..51058b424f66a5bacc736f1c7fbc9e4f0290dd74 --- /dev/null +++ b/trackio/frontend_templates/starter/styles.css @@ -0,0 +1,467 @@ +:root { + color-scheme: light; + --background-fill-primary: #ffffff; + --background-fill-secondary: #f9fafb; + --background-fill-tertiary: #f3f4f6; + --border-color-primary: #e5e7eb; + --border-color-accent: #d1d5db; + --body-text-color: #111827; + --body-text-color-subdued: #6b7280; + --body-text-color-soft: #9ca3af; + --accent: #1d4ed8; + --shadow-soft: 0 1px 2px rgba(16, 24, 40, 0.04); +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + min-height: 100%; + background: var(--background-fill-secondary); + color: var(--body-text-color); + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + sans-serif; +} + +button, +input, +select, +table { + font: inherit; +} + +.app-shell { + display: grid; + grid-template-columns: 320px minmax(0, 1fr); + min-height: 100vh; +} + +.sidebar { + border-right: 1px solid var(--border-color-primary); + background: var(--background-fill-primary); +} + +.sidebar-scroll { + height: 100vh; + overflow-y: auto; + padding: 18px 16px 28px; +} + +.logo-section { + padding: 10px 10px 18px; + border-bottom: 1px solid var(--border-color-primary); +} + +.logo { + display: block; + width: 138px; + max-width: 100%; +} + +.sidebar-section { + padding: 18px 10px 0; +} + +.section-label, +.eyebrow { + margin: 0 0 10px; + color: var(--body-text-color-subdued); + font-size: 12px; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.run-list { + display: grid; + gap: 8px; +} + +.dropdown-wrap { + position: relative; +} + +.project-select { + width: 100%; + padding: 10px 40px 10px 12px; + border: 1px solid var(--border-color-primary); + border-radius: 10px; + background: var(--background-fill-primary); + color: var(--body-text-color); + appearance: none; + -webkit-appearance: none; +} + +.project-select:focus { + outline: none; + border-color: var(--border-color-accent); + box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.08); +} + +.dropdown-icon { + position: absolute; + top: 50%; + right: 12px; + transform: translateY(-50%); + color: var(--body-text-color-subdued); + pointer-events: none; +} + +.run-option { + display: grid; + grid-template-columns: 18px 10px minmax(0, 1fr); + gap: 10px; + align-items: start; + padding: 10px 12px; + border: 1px solid var(--border-color-primary); + border-radius: 10px; + background: var(--background-fill-primary); + cursor: pointer; +} + +.run-option input { + margin: 2px 0 0; + accent-color: var(--accent); +} + +.run-color-dot { + width: 10px; + height: 10px; + margin-top: 5px; + border-radius: 999px; + background: var(--accent); +} + +.run-option-text strong, +.run-option-text span { + display: block; +} + +.run-option-text strong { + color: var(--body-text-color); + font-size: 14px; + font-weight: 600; +} + +.run-option-text span, +.sidebar-note, +.sidebar-empty { + color: var(--body-text-color-subdued); + font-size: 13px; + line-height: 1.5; +} + +.main-shell { + display: flex; + flex-direction: column; + min-width: 0; +} + +.navbar { + display: flex; + align-items: stretch; + min-height: 44px; + border-bottom: 1px solid var(--border-color-primary); + background: var(--background-fill-primary); +} + +.nav-spacer { + flex: 1 1 0; +} + +.nav-tabs { + display: flex; + padding-right: 8px; +} + +.nav-link { + padding: 10px 16px; + border: none; + border-bottom: 2px solid transparent; + background: none; + color: var(--body-text-color-subdued); + cursor: pointer; +} + +.nav-link.active { + border-bottom-color: var(--body-text-color); + color: var(--body-text-color); + font-weight: 500; +} + +.page { + display: none; + min-width: 0; + padding: 24px 28px 36px; +} + +.page.active { + display: block; +} + +.page-header { + margin-bottom: 22px; +} + +.page-header h1 { + margin: 0; + font-size: 32px; + line-height: 1.1; +} + +.page-subtitle { + margin: 8px 0 0; + color: var(--body-text-color-subdued); + font-size: 15px; +} + +.metrics-grid { + display: grid; + gap: 18px; +} + +.metric-card { + padding: 18px; + border: 1px solid var(--border-color-primary); + border-radius: 14px; + background: var(--background-fill-primary); + box-shadow: var(--shadow-soft); +} + +.metric-card-head { + display: flex; + align-items: start; + justify-content: space-between; + gap: 16px; +} + +.metric-card h3 { + margin: 0; + font-size: 18px; +} + +.metric-run, +.metric-meta, +.metric-empty, +.metric-latest { + color: var(--body-text-color-subdued); + font-size: 13px; +} + +.metric-latest { + color: var(--body-text-color); + max-width: 50%; + font-size: 13px; + font-weight: 600; + text-align: right; +} + +.plot-shell { + margin-top: 14px; + padding: 10px 12px; + border: 1px solid var(--border-color-primary); + border-radius: 12px; + background: linear-gradient(180deg, #ffffff, #f9fafb); +} + +.plot-shell svg { + display: block; + width: 100%; + height: auto; +} + +.plot-axis { + stroke: var(--border-color-accent); + stroke-width: 1.2; +} + +.plot-line { + fill: none; + stroke-width: 2.25; + stroke-linecap: round; + stroke-linejoin: round; +} + +.plot-marker { + fill: var(--background-fill-primary); + stroke: var(--body-text-color); + stroke-width: 1.5; +} + +.metric-legend { + display: flex; + flex-wrap: wrap; + gap: 10px 14px; + margin-top: 12px; +} + +.metric-legend-item { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--body-text-color-subdued); + font-size: 13px; +} + +.metric-legend-dot { + width: 10px; + height: 10px; + border-radius: 999px; +} + +.traces-table-wrap { + overflow: auto; + border: 1px solid var(--border-color-primary); + border-radius: 14px; + background: var(--background-fill-primary); + box-shadow: var(--shadow-soft); +} + +.traces-table { + width: 100%; + border-collapse: collapse; +} + +.traces-table thead { + background: var(--background-fill-secondary); +} + +.traces-table th, +.traces-table td { + padding: 14px 16px; + border-bottom: 1px solid var(--border-color-primary); + text-align: left; + vertical-align: top; + font-size: 14px; +} + +.traces-table th { + color: var(--body-text-color-subdued); + font-size: 12px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.trace-summary-row { + cursor: pointer; +} + +.trace-summary-row:hover { + background: var(--background-fill-secondary); +} + +.trace-summary-row.expanded { + background: var(--background-fill-secondary); +} + +.trace-id { + color: var(--body-text-color); + font-family: + ui-monospace, + SFMono-Regular, + Menlo, + monospace; + font-size: 12px; +} + +.trace-request { + max-width: 520px; + color: var(--body-text-color); +} + +.trace-detail-row td { + padding: 0; + background: var(--background-fill-secondary); +} + +.trace-detail-shell { + padding: 18px 20px; + border-top: 1px solid var(--border-color-primary); +} + +.trace-detail-head strong { + display: block; + color: var(--body-text-color); + font-size: 14px; +} + +.trace-detail-meta { + margin-top: 4px; + color: var(--body-text-color-subdued); + font-size: 12px; +} + +.trace-message-list { + display: grid; + gap: 12px; + margin-top: 16px; +} + +.trace-message { + padding: 12px 14px; + border: 1px solid var(--border-color-primary); + border-radius: 12px; + background: var(--background-fill-primary); +} + +.trace-message-role { + margin-bottom: 8px; + color: var(--body-text-color-subdued); + font-size: 12px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.trace-message-text { + color: var(--body-text-color); + font-size: 14px; + line-height: 1.55; + white-space: pre-wrap; + overflow-wrap: anywhere; +} + +.trace-message-muted { + color: var(--body-text-color-subdued); +} + +.empty-row, +.empty-panel { + color: var(--body-text-color-subdued); + text-align: center; +} + +.empty-panel { + padding: 48px 20px; + border: 1px dashed var(--border-color-accent); + border-radius: 14px; + background: var(--background-fill-primary); +} + +@media (max-width: 960px) { + .app-shell { + grid-template-columns: 1fr; + } + + .sidebar { + border-right: none; + border-bottom: 1px solid var(--border-color-primary); + } + + .sidebar-scroll { + height: auto; + } + + .page { + padding: 18px; + } +} diff --git a/trackio/gpu.py b/trackio/gpu.py new file mode 100644 index 0000000000000000000000000000000000000000..a84d903884069e1133532629aa1c63d22c3c792a --- /dev/null +++ b/trackio/gpu.py @@ -0,0 +1,381 @@ +import os +import threading +import warnings +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from trackio.run import Run + +pynvml: Any = None +PYNVML_AVAILABLE = False +_nvml_initialized = False +_nvml_lock = threading.Lock() +_energy_baseline: dict[int, float] = {} + + +def _ensure_pynvml(): + global PYNVML_AVAILABLE, pynvml + if PYNVML_AVAILABLE: + return pynvml + try: + import pynvml as _pynvml + + pynvml = _pynvml + PYNVML_AVAILABLE = True + return pynvml + except ImportError: + raise ImportError( + "nvidia-ml-py is required for GPU monitoring. " + "Install it with: pip install nvidia-ml-py" + ) + + +def _init_nvml() -> bool: + global _nvml_initialized + with _nvml_lock: + if _nvml_initialized: + return True + try: + nvml = _ensure_pynvml() + nvml.nvmlInit() + _nvml_initialized = True + return True + except Exception: + return False + + +def get_gpu_count() -> tuple[int, list[int]]: + """ + Get the number of GPUs visible to this process and their physical indices. + Respects CUDA_VISIBLE_DEVICES environment variable. + + Returns: + Tuple of (count, physical_indices) where: + - count: Number of visible GPUs + - physical_indices: List mapping logical index to physical GPU index. + e.g., if CUDA_VISIBLE_DEVICES=2,3 returns (2, [2, 3]) + meaning logical GPU 0 = physical GPU 2, logical GPU 1 = physical GPU 3 + """ + if not _init_nvml(): + return 0, [] + + cuda_visible = os.environ.get("CUDA_VISIBLE_DEVICES") + if cuda_visible is not None and cuda_visible.strip(): + try: + indices = [int(x.strip()) for x in cuda_visible.split(",") if x.strip()] + return len(indices), indices + except ValueError: + pass + + try: + total = pynvml.nvmlDeviceGetCount() + return total, list(range(total)) + except Exception: + return 0, [] + + +def get_all_gpu_count() -> tuple[int, list[int]]: + """ + Get the total number of physical GPUs on the machine, ignoring CUDA_VISIBLE_DEVICES. + + Returns: + Tuple of (count, physical_indices) for ALL GPUs on the machine. + e.g., on a 4-GPU machine returns (4, [0, 1, 2, 3]) regardless of + CUDA_VISIBLE_DEVICES setting. + """ + if not _init_nvml(): + return 0, [] + + try: + total = pynvml.nvmlDeviceGetCount() + return total, list(range(total)) + except Exception: + return 0, [] + + +def gpu_available() -> bool: + """ + Check if GPU monitoring is available. + + Returns True if nvidia-ml-py is installed and at least one NVIDIA GPU is detected. + This is used for auto-detection of GPU logging. + """ + try: + _ensure_pynvml() + count, _ = get_gpu_count() + return count > 0 + except ImportError: + return False + except Exception: + return False + + +def reset_energy_baseline(): + """Reset the energy baseline for all GPUs. Called when a new run starts.""" + global _energy_baseline + _energy_baseline = {} + + +def collect_gpu_metrics(device: int | None = None, all_gpus: bool = False) -> dict: + """ + Collect GPU metrics for visible GPUs. + + Args: + device: CUDA device index to collect metrics from. If None, collects + from all GPUs visible to this process (respects CUDA_VISIBLE_DEVICES). + The device index is the logical CUDA index (0, 1, 2...), not the + physical GPU index. + all_gpus: If True and device is None, collect metrics for ALL physical GPUs + on the machine, ignoring CUDA_VISIBLE_DEVICES. Used by GpuMonitor + to report system-wide GPU metrics in distributed training. + + Returns: + Dictionary of GPU metrics. Keys use device indices (gpu/0/, gpu/1/, etc.). + """ + if not _init_nvml(): + return {} + + if all_gpus and device is None: + gpu_count, visible_gpus = get_all_gpu_count() + else: + gpu_count, visible_gpus = get_gpu_count() + if gpu_count == 0: + return {} + + if device is not None: + if device < 0 or device >= gpu_count: + return {} + gpu_indices = [(device, visible_gpus[device])] + else: + gpu_indices = list(enumerate(visible_gpus)) + + metrics = {} + total_util = 0.0 + total_mem_used_gib = 0.0 + total_power = 0.0 + max_temp = 0.0 + valid_util_count = 0 + + for logical_idx, physical_idx in gpu_indices: + prefix = f"gpu/{logical_idx}" + try: + handle = pynvml.nvmlDeviceGetHandleByIndex(physical_idx) + + try: + util = pynvml.nvmlDeviceGetUtilizationRates(handle) + metrics[f"{prefix}/utilization"] = util.gpu + metrics[f"{prefix}/memory_utilization"] = util.memory + total_util += util.gpu + valid_util_count += 1 + except Exception: + pass + + try: + mem = pynvml.nvmlDeviceGetMemoryInfo(handle) + mem_used_gib = mem.used / (1024**3) + mem_total_gib = mem.total / (1024**3) + metrics[f"{prefix}/allocated_memory"] = mem_used_gib + metrics[f"{prefix}/total_memory"] = mem_total_gib + if mem.total > 0: + metrics[f"{prefix}/memory_usage"] = mem.used / mem.total + total_mem_used_gib += mem_used_gib + except Exception: + pass + + try: + power_mw = pynvml.nvmlDeviceGetPowerUsage(handle) + power_w = power_mw / 1000.0 + metrics[f"{prefix}/power"] = power_w + total_power += power_w + except Exception: + pass + + try: + power_limit_mw = pynvml.nvmlDeviceGetPowerManagementLimit(handle) + power_limit_w = power_limit_mw / 1000.0 + metrics[f"{prefix}/power_limit"] = power_limit_w + if power_limit_w > 0 and f"{prefix}/power" in metrics: + metrics[f"{prefix}/power_percent"] = ( + metrics[f"{prefix}/power"] / power_limit_w + ) * 100 + except Exception: + pass + + try: + temp = pynvml.nvmlDeviceGetTemperature( + handle, pynvml.NVML_TEMPERATURE_GPU + ) + metrics[f"{prefix}/temp"] = temp + max_temp = max(max_temp, temp) + except Exception: + pass + + try: + sm_clock = pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_SM) + metrics[f"{prefix}/sm_clock"] = sm_clock + except Exception: + pass + + try: + mem_clock = pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_MEM) + metrics[f"{prefix}/memory_clock"] = mem_clock + except Exception: + pass + + try: + fan_speed = pynvml.nvmlDeviceGetFanSpeed(handle) + metrics[f"{prefix}/fan_speed"] = fan_speed + except Exception: + pass + + try: + pstate = pynvml.nvmlDeviceGetPerformanceState(handle) + metrics[f"{prefix}/performance_state"] = pstate + except Exception: + pass + + try: + energy_mj = pynvml.nvmlDeviceGetTotalEnergyConsumption(handle) + if physical_idx not in _energy_baseline: + _energy_baseline[physical_idx] = energy_mj + energy_consumed_mj = energy_mj - _energy_baseline[physical_idx] + metrics[f"{prefix}/energy_consumed"] = energy_consumed_mj / 1000.0 + except Exception: + pass + + try: + pcie_tx = pynvml.nvmlDeviceGetPcieThroughput( + handle, pynvml.NVML_PCIE_UTIL_TX_BYTES + ) + pcie_rx = pynvml.nvmlDeviceGetPcieThroughput( + handle, pynvml.NVML_PCIE_UTIL_RX_BYTES + ) + metrics[f"{prefix}/pcie_tx"] = pcie_tx / 1024.0 + metrics[f"{prefix}/pcie_rx"] = pcie_rx / 1024.0 + except Exception: + pass + + try: + throttle = pynvml.nvmlDeviceGetCurrentClocksThrottleReasons(handle) + metrics[f"{prefix}/throttle_thermal"] = int( + bool(throttle & pynvml.nvmlClocksThrottleReasonSwThermalSlowdown) + ) + metrics[f"{prefix}/throttle_power"] = int( + bool(throttle & pynvml.nvmlClocksThrottleReasonSwPowerCap) + ) + metrics[f"{prefix}/throttle_hw_slowdown"] = int( + bool(throttle & pynvml.nvmlClocksThrottleReasonHwSlowdown) + ) + metrics[f"{prefix}/throttle_apps"] = int( + bool( + throttle + & pynvml.nvmlClocksThrottleReasonApplicationsClocksSetting + ) + ) + except Exception: + pass + + try: + ecc_corrected = pynvml.nvmlDeviceGetTotalEccErrors( + handle, + pynvml.NVML_MEMORY_ERROR_TYPE_CORRECTED, + pynvml.NVML_VOLATILE_ECC, + ) + metrics[f"{prefix}/corrected_memory_errors"] = ecc_corrected + except Exception: + pass + + try: + ecc_uncorrected = pynvml.nvmlDeviceGetTotalEccErrors( + handle, + pynvml.NVML_MEMORY_ERROR_TYPE_UNCORRECTED, + pynvml.NVML_VOLATILE_ECC, + ) + metrics[f"{prefix}/uncorrected_memory_errors"] = ecc_uncorrected + except Exception: + pass + + except Exception: + continue + + if valid_util_count > 0: + metrics["gpu/mean_utilization"] = total_util / valid_util_count + if total_mem_used_gib > 0: + metrics["gpu/total_allocated_memory"] = total_mem_used_gib + if total_power > 0: + metrics["gpu/total_power"] = total_power + if max_temp > 0: + metrics["gpu/max_temp"] = max_temp + + return metrics + + +class GpuMonitor: + def __init__(self, run: "Run", interval: float = 10.0): + self._run = run + self._interval = interval + self._stop_flag = threading.Event() + self._thread: "threading.Thread | None" = None + + def start(self): + count, _ = get_all_gpu_count() + if count == 0: + warnings.warn( + "auto_log_gpu=True but no NVIDIA GPUs detected. GPU logging disabled." + ) + return + + reset_energy_baseline() + self._thread = threading.Thread(target=self._monitor_loop, daemon=True) + self._thread.start() + + def stop(self): + self._stop_flag.set() + if self._thread is not None: + self._thread.join(timeout=2.0) + + def _monitor_loop(self): + while not self._stop_flag.is_set(): + try: + metrics = collect_gpu_metrics(all_gpus=True) + if metrics: + self._run.log_system(metrics) + except Exception: + pass + + self._stop_flag.wait(timeout=self._interval) + + +def log_gpu(run: "Run | None" = None, device: int | None = None) -> dict: + """ + Log GPU metrics to the current or specified run as system metrics. + + Args: + run: Optional Run instance. If None, uses current run from context. + device: CUDA device index to collect metrics from. If None, collects + from all GPUs visible to this process (respects CUDA_VISIBLE_DEVICES). + + Returns: + dict: The GPU metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_gpu() # logs all visible GPUs + trackio.log_gpu(device=0) # logs only CUDA device 0 + ``` + """ + from trackio import context_vars + + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_gpu().") + + metrics = collect_gpu_metrics(device=device) + if metrics: + run.log_system(metrics) + return metrics diff --git a/trackio/histogram.py b/trackio/histogram.py new file mode 100644 index 0000000000000000000000000000000000000000..1e00477907d55f7f5dcc1bf2bff05029d43b3ac1 --- /dev/null +++ b/trackio/histogram.py @@ -0,0 +1,71 @@ +from typing import Sequence + +import numpy as np + + +class Histogram: + """ + Histogram data type for Trackio, compatible with wandb.Histogram. + + Args: + sequence (`np.ndarray` or `Sequence[float]` or `Sequence[int]`, *optional*): + Sequence of values to create the histogram from. + np_histogram (`tuple`, *optional*): + Pre-computed NumPy histogram as a `(hist, bins)` tuple. + num_bins (`int`, *optional*, defaults to `64`): + Number of bins for the histogram (maximum `512`). + + Example: + ```python + import trackio + import numpy as np + + # Create histogram from sequence + data = np.random.randn(1000) + trackio.log({"distribution": trackio.Histogram(data)}) + + # Create histogram from numpy histogram + hist, bins = np.histogram(data, bins=30) + trackio.log({"distribution": trackio.Histogram(np_histogram=(hist, bins))}) + + # Specify custom number of bins + trackio.log({"distribution": trackio.Histogram(data, num_bins=50)}) + ``` + """ + + TYPE = "trackio.histogram" + + def __init__( + self, + sequence: np.ndarray | Sequence[float] | Sequence[int] | None = None, + np_histogram: tuple | None = None, + num_bins: int = 64, + ): + if sequence is None and np_histogram is None: + raise ValueError("Must provide either sequence or np_histogram") + + if sequence is not None and np_histogram is not None: + raise ValueError("Cannot provide both sequence and np_histogram") + + num_bins = min(num_bins, 512) + + if np_histogram is not None: + self.histogram, self.bins = np_histogram + self.histogram = np.asarray(self.histogram) + self.bins = np.asarray(self.bins) + else: + data = np.asarray(sequence).flatten() + data = data[np.isfinite(data)] + if len(data) == 0: + self.histogram = np.array([]) + self.bins = np.array([]) + else: + self.histogram, self.bins = np.histogram(data, bins=num_bins) + + def _to_dict(self) -> dict: + """Convert histogram to dictionary for storage.""" + return { + "_type": self.TYPE, + "bins": self.bins.tolist(), + "values": self.histogram.tolist(), + } diff --git a/trackio/imports.py b/trackio/imports.py new file mode 100644 index 0000000000000000000000000000000000000000..37516dbdc409b91f643ba3b0070c80379bb2252b --- /dev/null +++ b/trackio/imports.py @@ -0,0 +1,305 @@ +import csv +import os +from pathlib import Path + +from trackio import deploy, utils +from trackio.sqlite_storage import SQLiteStorage + + +def import_csv( + csv_path: str | Path, + project: str, + name: str | None = None, + space_id: str | None = None, + dataset_id: str | None = None, + private: bool | None = None, + force: bool = False, +) -> None: + """ + Imports a CSV file into a Trackio project. The CSV file must contain a `"step"` + column, may optionally contain a `"timestamp"` column, and any other columns will be + treated as metrics. It should also include a header row with the column names. + + TODO: call init() and return a Run object so that the user can continue to log metrics to it. + + Args: + csv_path (`str` or `Path`): + The str or Path to the CSV file to import. + project (`str`): + The name of the project to import the CSV file into. Must not be an existing + project. + name (`str`, *optional*): + The name of the Run to import the CSV file into. If not provided, a default + name will be generated. + name (`str`, *optional*): + The name of the run (if not provided, a default name will be generated). + space_id (`str`, *optional*): + If provided, the project will be logged to a Hugging Face Space instead of a + local directory. Should be a complete Space name like `"username/reponame"` + or `"orgname/reponame"`, or just `"reponame"` in which case the Space will + be created in the currently-logged-in Hugging Face user's namespace. If the + Space does not exist, it will be created. If the Space already exists, the + project will be logged to it. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + """ + if SQLiteStorage.get_runs(project): + raise ValueError( + f"Project '{project}' already exists. Cannot import CSV into existing project." + ) + + csv_path = Path(csv_path) + if not csv_path.exists(): + raise FileNotFoundError(f"CSV file not found: {csv_path}") + + with csv_path.open(newline="", encoding="utf-8") as csv_file: + reader = csv.DictReader(csv_file) + source_columns = reader.fieldnames or [] + rows = list(reader) + + if not rows: + raise ValueError("CSV file is empty") + + column_mapping = utils.simplify_column_names(source_columns) + normalized_rows = [ + {column_mapping[key]: value for key, value in row.items()} for row in rows + ] + columns = list(normalized_rows[0].keys()) + + step_column = None + for col in columns: + if col.lower() == "step": + step_column = col + break + + if step_column is None: + raise ValueError("CSV file must contain a 'step' or 'Step' column") + + if name is None: + name = csv_path.stem + + metrics_list = [] + steps = [] + timestamps = [] + + numeric_columns = [] + for column in columns: + if column == step_column: + continue + if column == "timestamp": + continue + + try: + for row in normalized_rows: + value = row[column] + if value in ("", None): + continue + float(value) + except (ValueError, TypeError): + continue + numeric_columns.append(column) + + for row in normalized_rows: + metrics = {} + for column in numeric_columns: + value = row[column] + if value not in ("", None): + metrics[column] = float(value) + + if metrics: + metrics_list.append(metrics) + steps.append(int(float(row[step_column]))) + + if "timestamp" in row and row["timestamp"] not in ("", None): + timestamps.append(str(row["timestamp"])) + else: + timestamps.append("") + + if not metrics_list: + raise ValueError( + f"No numeric metric data found in CSV file: {csv_path}. Columns other " + "than 'step' and 'timestamp' must contain numeric values." + ) + + SQLiteStorage.bulk_log( + project=project, + run=name, + metrics_list=metrics_list, + steps=steps, + timestamps=timestamps, + ) + + print( + f"* Imported {len(metrics_list)} rows from {csv_path} into project '{project}' as run '{name}'" + ) + print(f"* Metrics found: {', '.join(metrics_list[0].keys())}") + + space_id, dataset_id, _ = utils.preprocess_space_and_dataset_ids( + space_id, dataset_id + ) + if dataset_id is not None: + os.environ["TRACKIO_DATASET_ID"] = dataset_id + print(f"* Trackio metrics will be synced to Hugging Face Dataset: {dataset_id}") + + if space_id is None: + utils.print_dashboard_instructions(project) + else: + deploy.create_space_if_not_exists( + space_id=space_id, dataset_id=dataset_id, private=private + ) + deploy.wait_until_space_exists(space_id=space_id) + deploy.upload_db_to_space(project=project, space_id=space_id, force=force) + print( + f"* View dashboard by going to: {deploy.SPACE_URL.format(space_id=space_id)}" + ) + + +def import_tf_events( + log_dir: str | Path, + project: str, + name: str | None = None, + space_id: str | None = None, + dataset_id: str | None = None, + private: bool | None = None, + force: bool = False, +) -> None: + """ + Imports TensorFlow Events files from a directory into a Trackio project. Each + subdirectory in the log directory will be imported as a separate run. + + Args: + log_dir (`str` or `Path`): + The str or Path to the directory containing TensorFlow Events files. + project (`str`): + The name of the project to import the TensorFlow Events files into. Must not + be an existing project. + name (`str`, *optional*): + The name prefix for runs (if not provided, will use directory names). Each + subdirectory will create a separate run. + space_id (`str`, *optional*): + If provided, the project will be logged to a Hugging Face Space instead of a + local directory. Should be a complete Space name like `"username/reponame"` + or `"orgname/reponame"`, or just `"reponame"` in which case the Space will + be created in the currently-logged-in Hugging Face user's namespace. If the + Space does not exist, it will be created. If the Space already exists, the + project will be logged to it. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + """ + try: + from tbparse import SummaryReader + except ImportError: + raise ImportError( + "The `tbparse` package is not installed but is required for `import_tf_events`. Please install trackio with the `tensorboard` extra: `pip install trackio[tensorboard]`." + ) + + if SQLiteStorage.get_runs(project): + raise ValueError( + f"Project '{project}' already exists. Cannot import TF events into existing project." + ) + + path = Path(log_dir) + if not path.exists(): + raise FileNotFoundError(f"TF events directory not found: {path}") + + # Use tbparse to read all tfevents files in the directory structure + reader = SummaryReader(str(path), extra_columns={"dir_name"}) + df = reader.scalars + + if df.empty: + raise ValueError(f"No TensorFlow events data found in {path}") + + total_imported = 0 + imported_runs = [] + + # Group by dir_name to create separate runs + for dir_name, group_df in df.groupby("dir_name"): + try: + # Determine run name based on directory name + if dir_name == "": + run_name = "main" # For files in the root directory + else: + run_name = dir_name # Use directory name + + if name: + run_name = f"{name}_{run_name}" + + if group_df.empty: + print(f"* Skipping directory {dir_name}: no scalar data found") + continue + + metrics_list = [] + steps = [] + timestamps = [] + + for _, row in group_df.iterrows(): + # Convert row values to appropriate types + tag = str(row["tag"]) + value = float(row["value"]) + step = int(row["step"]) + + metrics = {tag: value} + metrics_list.append(metrics) + steps.append(step) + + # Use wall_time if present, else fallback + if "wall_time" in group_df.columns and not utils.is_missing_value( + row["wall_time"] + ): + timestamps.append(str(row["wall_time"])) + else: + timestamps.append("") + + if metrics_list: + SQLiteStorage.bulk_log( + project=project, + run=str(run_name), + metrics_list=metrics_list, + steps=steps, + timestamps=timestamps, + ) + + total_imported += len(metrics_list) + imported_runs.append(run_name) + + print( + f"* Imported {len(metrics_list)} scalar events from directory '{dir_name}' as run '{run_name}'" + ) + print(f"* Metrics in this run: {', '.join(set(group_df['tag']))}") + + except Exception as e: + print(f"* Error processing directory {dir_name}: {e}") + continue + + if not imported_runs: + raise ValueError("No valid TensorFlow events data could be imported") + + print(f"* Total imported events: {total_imported}") + print(f"* Created runs: {', '.join(imported_runs)}") + + space_id, dataset_id, _ = utils.preprocess_space_and_dataset_ids( + space_id, dataset_id + ) + if dataset_id is not None: + os.environ["TRACKIO_DATASET_ID"] = dataset_id + print(f"* Trackio metrics will be synced to Hugging Face Dataset: {dataset_id}") + + if space_id is None: + utils.print_dashboard_instructions(project) + else: + deploy.create_space_if_not_exists( + space_id, dataset_id=dataset_id, private=private + ) + deploy.wait_until_space_exists(space_id) + deploy.upload_db_to_space(project, space_id, force=force) + print( + f"* View dashboard by going to: {deploy.SPACE_URL.format(space_id=space_id)}" + ) diff --git a/trackio/launch.py b/trackio/launch.py new file mode 100644 index 0000000000000000000000000000000000000000..9fe4843dceb64c7c6ee74f95cbc22e5447a273c6 --- /dev/null +++ b/trackio/launch.py @@ -0,0 +1,202 @@ +from __future__ import annotations + +import os +import secrets +import socket +import threading +import time +import warnings +from pathlib import Path +from typing import Any + +import httpx +import uvicorn +from uvicorn.config import Config + +from trackio._vendor.gradio_exceptions import ChecksumMismatchError +from trackio._vendor.networking import normalize_share_url, setup_tunnel, url_ok +from trackio._vendor.tunneling import BINARY_PATH +from trackio.launch_utils import colab_check, is_hosted_notebook + +INITIAL_PORT_VALUE = int(os.getenv("GRADIO_SERVER_PORT", "7860")) +TRY_NUM_PORTS = int(os.getenv("GRADIO_NUM_PORTS", "100")) +LOCALHOST_NAME = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1") + + +class _UvicornServer(uvicorn.Server): + def install_signal_handlers(self) -> None: + pass + + def run_in_thread(self) -> None: + self.thread = threading.Thread(target=self.run, daemon=True) + self.thread.start() + start = time.time() + while not self.started: + time.sleep(1e-3) + if time.time() - start > 60: + raise RuntimeError( + "Server failed to start. Please check that the port is available." + ) + + +def _bind_host(server_name: str) -> str: + if server_name.startswith("[") and server_name.endswith("]"): + return server_name[1:-1] + return server_name + + +def start_server( + app: Any, + server_name: str | None = None, + server_port: int | None = None, + ssl_keyfile: str | None = None, + ssl_certfile: str | None = None, + ssl_keyfile_password: str | None = None, +) -> tuple[str, int, str, _UvicornServer]: + server_name = server_name or LOCALHOST_NAME + url_host_name = "localhost" if server_name == "0.0.0.0" else server_name + + host = _bind_host(server_name) + + server_ports = ( + [server_port] + if server_port is not None + else range(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS) + ) + + port_used = None + server = None + for port in server_ports: + try: + socket_family = socket.AF_INET6 if ":" in host else socket.AF_INET + with socket.socket(socket_family, socket.SOCK_STREAM) as s: + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind((host, port)) + config = Config( + app=app, + port=port, + host=host, + log_level="warning", + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ) + server = _UvicornServer(config=config) + server.run_in_thread() + port_used = port + break + except (OSError, RuntimeError): + continue + else: + raise OSError( + f"Cannot find empty port in range: {min(server_ports)}-{max(server_ports)}. " + "Set GRADIO_SERVER_PORT or pass server_port to trackio.show()." + ) + + assert port_used is not None and server is not None + + if ssl_keyfile is not None: + path_to_local_server = f"https://{url_host_name}:{port_used}/" + else: + path_to_local_server = f"http://{url_host_name}:{port_used}/" + + return server_name, port_used, path_to_local_server, server + + +def launch_trackio_dashboard( + starlette_app: Any, + *, + server_name: str | None = None, + server_port: int | None = None, + share: bool | None = None, + share_server_address: str | None = None, + share_server_protocol: str | None = None, + share_server_tls_certificate: str | None = None, + mcp_server: bool = False, + ssl_verify: bool = True, + quiet: bool = False, +) -> tuple[str | None, str | None, str | None, Any]: + is_colab = colab_check() + is_hosted_nb = is_hosted_notebook() + space_id = os.getenv("SPACE_ID") + + if share is None: + if is_colab or is_hosted_nb: + if not quiet: + print( + "It looks like you are running Trackio on a hosted Jupyter notebook, which requires " + "`share=True`. Automatically setting `share=True` " + "(set `share=False` in `show()` to disable).\n" + ) + share = True + else: + share = os.getenv("GRADIO_SHARE", "").lower() == "true" + + sn = server_name + if sn is None and os.getenv("SYSTEM") == "spaces": + sn = "0.0.0.0" + elif sn is None: + sn = LOCALHOST_NAME + + server_name_r, server_port_r, local_url, uv_server = start_server( + starlette_app, + server_name=sn, + server_port=server_port, + ) + + local_api_url = f"{local_url.rstrip('/')}/api/" + try: + httpx.get(f"{local_url.rstrip('/')}/version", verify=ssl_verify, timeout=10) + except Exception as e: + raise RuntimeError( + f"Could not reach Trackio server at {local_url.rstrip('/')}/version: {e}" + ) from e + + if share and space_id: + warnings.warn("Setting share=True is not supported on Hugging Face Spaces") + share = False + + share_url: str | None = None + if share: + try: + share_tok = secrets.token_urlsafe(32) + proto = share_server_protocol or ( + "http" if share_server_address is not None else "https" + ) + raw = setup_tunnel( + local_host=server_name_r, + local_port=server_port_r, + share_token=share_tok, + share_server_address=share_server_address, + share_server_tls_certificate=share_server_tls_certificate, + ) + share_url = normalize_share_url(raw, proto) + if not quiet: + print(f"* Running on public URL: {share_url}") + print( + "\nThis share link expires in 1 week. For permanent hosting, deploy to Hugging Face Spaces." + ) + except Exception as e: + share_url = None + if not quiet: + if isinstance(e, ChecksumMismatchError): + print( + "\nCould not create share link. Checksum mismatch for frpc binary." + ) + elif Path(BINARY_PATH).exists(): + print( + "\nCould not create share link. Check your internet connection or https://status.gradio.app." + ) + else: + print( + f"\nCould not create share link. Missing frpc at {BINARY_PATH}. {e}" + ) + + if not share_url and not quiet: + print("* To create a public link, set `share=True` in `trackio.show()`.") + + return local_url, share_url, local_api_url, uv_server + + +def url_ok_local(local_url: str) -> bool: + return url_ok(local_url) diff --git a/trackio/launch_utils.py b/trackio/launch_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..4215f7564472ad42441be63ecec13d5d385a20fb --- /dev/null +++ b/trackio/launch_utils.py @@ -0,0 +1,33 @@ +import os + + +def colab_check() -> bool: + is_colab = False + try: + from IPython.core.getipython import get_ipython # noqa: PLC0415 + + from_ipynb = get_ipython() + if "google.colab" in str(from_ipynb): + is_colab = True + except (ImportError, NameError): + pass + return is_colab + + +def is_hosted_notebook() -> bool: + return bool( + os.environ.get("KAGGLE_KERNEL_RUN_TYPE") + or os.path.exists("/home/ec2-user/SageMaker") + ) + + +def ipython_check() -> bool: + is_ipython = False + try: + from IPython.core.getipython import get_ipython # noqa: PLC0415 + + if get_ipython() is not None: + is_ipython = True + except (ImportError, NameError): + pass + return is_ipython diff --git a/trackio/logbook.py b/trackio/logbook.py new file mode 100644 index 0000000000000000000000000000000000000000..b5c74547e7e3993c79112ffbf17d3e5e647dfe26 --- /dev/null +++ b/trackio/logbook.py @@ -0,0 +1,2189 @@ +from __future__ import annotations + +import base64 +import html +import json +import os +import re +import shlex +import shutil +import subprocess +import sys +import time +import uuid +from datetime import datetime, timezone +from pathlib import Path + +PROJECT_DIR_NAME = ".trackio" +LOGBOOK_SUBDIR = "logbook" +METADATA_FILE = "metadata.json" +SCHEMA_VERSION = 1 +ROOT_SLUG = "index" +VIEWER_DIR = Path(__file__).parent / "frontend_templates" / "logbook" +VIEWER_FILES = [ + "index.html", + "logbook.css", + "logbook.js", + "trackio-logo.png", + "trackio-logo-light.png", + "trackio-wordmark-dark.png", + "bucket-icon.svg", +] + +TOC_HEADING = "## Pages" +TOC_HEADER = "| Page |" +TOC_SEP = "| --- |" +TOC_PLACEHOLDER_TOKENS = ("logbook note", "logbook cell markdown", "logbook page") +STATUS_COL_RE = re.compile(r"\b(status|state)\b", re.I) +LINK_COL_RE = re.compile(r"\b(page|experiment|name|title)\b", re.I) +CELL_TYPES = {"markdown", "code", "figure", "artifact", "dashboard"} +ARTIFACT_URI_PREFIX = "trackio-artifact://" +PATH_ARTIFACT_URI_PREFIX = "trackio-local-path://" +LOCAL_DASHBOARD_PREFIX = "trackio-local-dashboard://" +SPACE_URL_RE = re.compile(r"https://huggingface\.co/spaces/[^\s<>)\"'`]+") +BUCKET_URL_RE = re.compile(r"https://huggingface\.co/buckets/[^\s<>)\"'`]+") +DEFAULT_HEAD = 3 +DEFAULT_TAIL = 3 +DEFAULT_RAW_LIMIT = 500 +FENCE_RE = re.compile(r"(`{3,4}|~{3,4})([^\n]*)\n([\s\S]*?)\n\1") +RUN_OUTPUT_LIMIT = 20_000 +RUN_OUTPUT_HEAD = 2_000 +RUN_OUTPUT_TAIL = RUN_OUTPUT_LIMIT - RUN_OUTPUT_HEAD +TRY_NUM_PORTS = int(os.getenv("GRADIO_NUM_PORTS", "100")) +CELL_RE = re.compile( + r"(^|\n)---\n\n([\s\S]*?)(?=\n---\n" + ) + return f"{m.group(1)}---\n{marker}\n{m.group(3)}" + + new_text = CELL_RE.sub(_repl, text) + if state["hit"]: + path.write_text(new_text, encoding="utf-8") + write_site_files(proj) + return { + "page": node["slug"], + "page_title": node["title"], + "title": state["title"], + "pinned": pinned, + } + raise LogbookError(f"No cell with id '{cell_id}' in this logbook.") + + +# ---- auto-note (called from trackio.finish / log_artifact) ---- + + +def _autonote_enabled() -> bool: + return os.environ.get("TRACKIO_LOGBOOK_AUTONOTE", "1").lower() not in ( + "0", + "false", + "no", + "off", + ) + + +def _new_cell_id() -> str: + return f"cell_{uuid.uuid4().hex[:12]}" + + +def _cell_marker(cell_type: str, title: str | None = None, **metadata) -> str: + if cell_type not in CELL_TYPES: + raise LogbookError(f"Unsupported logbook cell type: {cell_type}") + title = (title or "").strip() or "Untitled" + payload = { + "type": cell_type, + "id": metadata.pop("id", _new_cell_id()), + "created_at": metadata.pop("created_at", _now_iso()), + "title": title, + } + payload.update({k: v for k, v in metadata.items() if v not in (None, "", [])}) + return "" + + +def _shorten(text: str, limit: int = 80) -> str: + text = re.sub(r"\s+", " ", text).strip() + if len(text) <= limit: + return text + return text[: limit - 1].rstrip() + "…" + + +def _strip_markdown_title(text: str) -> str: + text = re.sub(r"!\[([^\]]*)\]\([^)]+\)", r"\1", text) + text = re.sub(r"\[([^\]]+)\]\([^)]+\)", r"\1", text) + text = re.sub(r"[*_`>#]+", "", text) + return text.strip(" -:\t") + + +def _default_cell_title(cell_type: str, body: str, metadata: dict) -> str: + command = metadata.get("command") + if command: + try: + return _shorten(f"Run: {shlex.join(command)}") + except TypeError: + return "Run" + if cell_type == "code": + titled = re.search(r"^````\w*\s+title=([^\n]+)", body, re.M) + if titled: + return _shorten(f"Code: {titled.group(1).strip()}") + return "Code cell" + if cell_type == "figure": + return "Figure" + for line in body.splitlines(): + line = line.strip() + if not line or line.startswith("````") or line.startswith("