zumly 0.92.6 → 0.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -18
- package/dist/zumly.cjs +2 -2
- package/dist/zumly.css +15 -0
- package/dist/zumly.js +2 -2
- package/dist/zumly.min.css +1 -1
- package/dist/zumly.mjs +2 -2
- package/package.json +9 -5
- package/src/drivers/anime-transition.js +5 -5
- package/src/drivers/driver-helpers.js +8 -3
- package/src/drivers/motion-transition.js +5 -5
- package/src/drivers/transform-matrix.js +34 -0
- package/src/view-lifecycle.js +70 -0
- package/src/view-visibility.js +43 -0
- package/types/zumly.d.ts +13 -10
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
## Status
|
|
25
25
|
|
|
26
|
-
Zumly is under active development.
|
|
26
|
+
Zumly is under active development. It supports depth and lateral navigation, pluggable transition drivers (CSS, WAAPI, none, Anime.js, GSAP, Motion, custom), separate depth and lateral navigation controls, a view resolver and prefetch cache, an optional **plugin** API (<code>.use()</code>), and the **hash router** plugin. View sources include HTML strings, URLs, async functions, objects with <code>render()</code>, DOM nodes, and web component tags.
|
|
27
27
|
|
|
28
28
|
Zoom-out geometry uses batched DOM reads plus pure math where possible to cut layout thrash before animations (see [Geometry optimization](docs/geometry-optimization.md)).
|
|
29
29
|
|
|
@@ -251,12 +251,13 @@ Each entry in `views` is a **view source**. The resolver detects the type and re
|
|
|
251
251
|
| **Async function** | `(ctx) => fetch(...).then(r => r.text())` or return `HTMLElement` | No |
|
|
252
252
|
| **Object with `render()`** | `{ render(ctx) { return '<div>…</div>' }, mounted?() }` | No |
|
|
253
253
|
| **Web component** | `'my-view'` (string with hyphen, not a key in `views`) | No |
|
|
254
|
+
| **DOM element** | `document.createElement('div')` | No; cloned on resolution |
|
|
254
255
|
|
|
255
|
-
**View pipeline:** Resolve → normalize `.z-view` → insert into canvas → call `mounted()` (if present). Static/URL views are cloned
|
|
256
|
+
**View pipeline:** Resolve → normalize `.z-view` → insert into canvas → call `mounted()` (if present). Static/URL views are cloned on every retrieval, including simultaneous requests. DOM element sources are also cloned; listeners attached directly to the original element are not copied.
|
|
256
257
|
|
|
257
258
|
### Framework integration
|
|
258
259
|
|
|
259
|
-
|
|
260
|
+
Use **function views** or **object views** to mount framework components. Register their teardown with `onCleanup()` so the framework releases its resources when the view is discarded:
|
|
260
261
|
|
|
261
262
|
**React**
|
|
262
263
|
|
|
@@ -269,8 +270,9 @@ const app = new Zumly({
|
|
|
269
270
|
initialView: 'home',
|
|
270
271
|
views: {
|
|
271
272
|
home: '<div class="z-view"><div class="zoom-me" data-to="dashboard" data-id="42">Open</div></div>',
|
|
272
|
-
dashboard: ({ target, props }) => {
|
|
273
|
+
dashboard: ({ target, props, onCleanup }) => {
|
|
273
274
|
const root = createRoot(target)
|
|
275
|
+
onCleanup(() => root.unmount())
|
|
274
276
|
root.render(<Dashboard id={props.id} />)
|
|
275
277
|
}
|
|
276
278
|
}
|
|
@@ -284,8 +286,10 @@ import { createApp } from 'vue'
|
|
|
284
286
|
import Dashboard from './Dashboard.vue'
|
|
285
287
|
|
|
286
288
|
views: {
|
|
287
|
-
dashboard: ({ target, props }) => {
|
|
288
|
-
createApp(Dashboard, { id: props.id })
|
|
289
|
+
dashboard: ({ target, props, onCleanup }) => {
|
|
290
|
+
const component = createApp(Dashboard, { id: props.id })
|
|
291
|
+
onCleanup(() => component.unmount())
|
|
292
|
+
component.mount(target)
|
|
289
293
|
}
|
|
290
294
|
}
|
|
291
295
|
```
|
|
@@ -296,8 +300,9 @@ views: {
|
|
|
296
300
|
import Dashboard from './Dashboard.svelte'
|
|
297
301
|
|
|
298
302
|
views: {
|
|
299
|
-
dashboard: ({ target, props }) => {
|
|
300
|
-
new Dashboard({ target, props: { id: props.id } })
|
|
303
|
+
dashboard: ({ target, props, onCleanup }) => {
|
|
304
|
+
const component = new Dashboard({ target, props: { id: props.id } })
|
|
305
|
+
onCleanup(() => component.$destroy())
|
|
301
306
|
}
|
|
302
307
|
}
|
|
303
308
|
```
|
|
@@ -306,8 +311,9 @@ views: {
|
|
|
306
311
|
|
|
307
312
|
```ts
|
|
308
313
|
views: {
|
|
309
|
-
dashboard: ({ target, props }) => {
|
|
314
|
+
dashboard: ({ target, props, onCleanup }) => {
|
|
310
315
|
const compRef = viewContainerRef.createComponent(DashboardComponent)
|
|
316
|
+
onCleanup(() => compRef.destroy())
|
|
311
317
|
compRef.instance.id = props.id
|
|
312
318
|
target.appendChild(compRef.location.nativeElement)
|
|
313
319
|
}
|
|
@@ -316,19 +322,40 @@ views: {
|
|
|
316
322
|
|
|
317
323
|
**Key points:**
|
|
318
324
|
|
|
319
|
-
- The `target` parameter is a fresh `<div>` created by Zumly
|
|
325
|
+
- The `target` parameter is a fresh `<div>` created by Zumly. When a function mounts into it and returns nothing, Zumly preserves that container and all its children. It defaults to the canvas width and height; set `target.style.width` and `target.style.height` for a smaller view.
|
|
320
326
|
- `props` contains data attributes from the trigger element (`data-id="42"` → `props.id`).
|
|
321
327
|
- `componentContext` (constructor option) is passed as `context` to all function/object views — use it for shared state (router, store, API client).
|
|
322
|
-
- Function views are **never cached** — they
|
|
328
|
+
- Function/object views are **never cached or prefetched** — they render only when requested by navigation. Initial views receive the same context contract, with empty `props`.
|
|
329
|
+
- Call `onCleanup(fn)` to register unmount, unsubscribe, or timer cleanup. Callbacks run once when the view is permanently removed, rendering fails, an abandoned async result arrives, or the instance is destroyed. Temporarily detached depth views and kept-alive lateral views retain their resources until discarded. Async callbacks are started without waiting for them.
|
|
323
330
|
- Use `mounted()` (object views) for post-insertion setup — it runs after the node is in the DOM.
|
|
324
|
-
-
|
|
331
|
+
- Returning an `HTMLElement` from a function or `render()` transfers that resolved view instance to Zumly; prefer `onCleanup()` over relying on DOM removal to unmount framework components.
|
|
325
332
|
|
|
326
333
|
### Preload and prefetch
|
|
327
334
|
|
|
328
|
-
- **Eager preload:** `preload: ['viewA', 'viewB']` —
|
|
335
|
+
- **Eager preload:** `preload: ['viewA', 'viewB']` — static HTML and URL views are resolved and cached during `init()`; dynamic views and custom elements are skipped.
|
|
329
336
|
- **Hover prefetch:** `mouseover` on a `.zoom-me[data-to]` trigger prefetches its target in the background.
|
|
330
337
|
- **Focus prefetch:** `focusin` on a `.zoom-me[data-to]` also prefetches (for keyboard/accessibility).
|
|
331
|
-
- **Scan prefetch:** When a view becomes current,
|
|
338
|
+
- **Scan prefetch:** When a view becomes current, its unique `.zoom-me[data-to]` targets enter a background queue. This works on touch devices where hover is unavailable. The queue keeps up to 32 pending targets and starts at most two resolutions concurrently, yielding between starts.
|
|
339
|
+
|
|
340
|
+
All prefetch strategies skip functions, objects, and custom elements to avoid rendering components speculatively.
|
|
341
|
+
|
|
342
|
+
Prefetch warms a template without cloning it. Navigation gets an independent clone when it needs the view. New speculative work pauses during navigation and resumes after completion; a requested view can load immediately without waiting for a queue slot. Already-running requests may still finish. Explicit `preload` remains eager.
|
|
343
|
+
|
|
344
|
+
The template cache holds up to 64 entries, evicts the least recently used, and expires URL responses after five minutes. Eviction only affects reusable templates: mounted views, form values, history, and `keepAlive` nodes stay intact. An evicted or unprefetched target resolves normally when visited.
|
|
345
|
+
|
|
346
|
+
### Navigation completion and accessibility
|
|
347
|
+
|
|
348
|
+
`zoomTo()`, `zoomIn()`, `goTo()`, `zoomOut()`, and `back()` return promises that settle after the transition and its completion hooks. Await each call when navigating through several views:
|
|
349
|
+
|
|
350
|
+
```js
|
|
351
|
+
await app.zoomTo('detail')
|
|
352
|
+
await app.zoomTo('deep')
|
|
353
|
+
await app.back()
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Calls made while another view is loading or animating are ignored. Failed navigation resolves after recovery and reports the error through Zumly's diagnostics. `init()` is idempotent, and `destroy()` releases pending navigation promises and discards late view results.
|
|
357
|
+
|
|
358
|
+
Generic `.zoom-me` triggers receive keyboard focus and support Enter/Space. Native buttons and links retain their semantics; navigation controls also support keyboard activation. Arrow navigation ignores text inputs and editable controls. Background views become `inert` and hidden from assistive technology until active again. Focus moves to the first usable control in the current view, or to the view itself. Zumly uses instant transitions when `prefers-reduced-motion: reduce` is active.
|
|
332
359
|
|
|
333
360
|
### Plugins
|
|
334
361
|
|
|
@@ -388,7 +415,7 @@ The UMD/IIFE bundle attaches the same plugin as `Zumly.Router`. There is no sepa
|
|
|
388
415
|
|
|
389
416
|
### Requirements
|
|
390
417
|
|
|
391
|
-
- Node.js >= 18
|
|
418
|
+
- Use Node.js 22+ for development. The distributed package entry points support Node.js >= 18; constructing a Zumly instance requires a browser DOM.
|
|
392
419
|
|
|
393
420
|
### Commands
|
|
394
421
|
|
|
@@ -403,6 +430,12 @@ npm run dev
|
|
|
403
430
|
npm run test:install-browsers
|
|
404
431
|
npm run test
|
|
405
432
|
|
|
433
|
+
# Run the suite in Chromium, Firefox, and WebKit
|
|
434
|
+
npm run test:browsers
|
|
435
|
+
|
|
436
|
+
# Compile and verify the installed npm tarball's public exports
|
|
437
|
+
npm run test:pack
|
|
438
|
+
|
|
406
439
|
# Run tests with coverage
|
|
407
440
|
npm run test:coverage
|
|
408
441
|
|
|
@@ -410,7 +443,7 @@ npm run test:coverage
|
|
|
410
443
|
npm run build
|
|
411
444
|
```
|
|
412
445
|
|
|
413
|
-
Tests use [Vitest](https://vitest.dev/) with the browser provider ([Playwright](https://playwright.dev/))
|
|
446
|
+
Tests use [Vitest](https://vitest.dev/) with the browser provider ([Playwright](https://playwright.dev/)). Run `npm run test:install-browsers` once (or after upgrading Playwright) to install Chromium, Firefox, and WebKit. `npm test` defaults to Chromium; `BROWSER=firefox` or `BROWSER=webkit` selects an individual engine. Run `npm run test:browsers` and `npm run test:pack` locally to check all three engines and the package exports.
|
|
414
447
|
|
|
415
448
|
### Building
|
|
416
449
|
|
|
@@ -420,6 +453,8 @@ npm run compile
|
|
|
420
453
|
|
|
421
454
|
Output is in the `dist/` folder.
|
|
422
455
|
|
|
456
|
+
`npm run build` compiles via `prepack` and creates a local tarball. It does not commit, push, or publish.
|
|
457
|
+
|
|
423
458
|
## Changelog
|
|
424
459
|
|
|
425
460
|
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|
@@ -435,10 +470,12 @@ See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|
|
435
470
|
- Resize correction (translate/origin scaling; deferred while transitioning)
|
|
436
471
|
- Pluggable drivers (CSS, WAAPI, none, Anime.js, GSAP, Motion, custom)
|
|
437
472
|
- Batched zoom-out reads + math helpers to reduce reflow (see [geometry-optimization.md](docs/geometry-optimization.md))
|
|
473
|
+
- Keyboard trigger activation, focus management, inactive-view isolation, and reduced-motion support
|
|
474
|
+
- Per-view resource cleanup with `ViewContext.onCleanup()`
|
|
438
475
|
|
|
439
476
|
**Planned:**
|
|
440
477
|
- Router deep-linking (open a multi-level hash cold)
|
|
441
|
-
-
|
|
478
|
+
- Further accessibility testing with assistive technologies
|
|
442
479
|
|
|
443
480
|
Details and more topics: [docs/roadMap.md](docs/roadMap.md). Driver contract and helpers: [docs/DRIVER_API.md](docs/DRIVER_API.md).
|
|
444
481
|
|
|
@@ -448,7 +485,7 @@ Details and more topics: [docs/roadMap.md](docs/roadMap.md). Driver contract and
|
|
|
448
485
|
|
|
449
486
|
## Origin
|
|
450
487
|
|
|
451
|
-
Zumly is a reimagined, framework-agnostic zoom engine inspired by [Zircle UI](https://github.com/zircleUI/zircleUI). Part of the [Zumerlab](https://github.com/zumerlab) ecosystem — use it with [Orbit](https://github.com/zumerlab/orbit) for radial layouts and [SnapDOM](https://github.com/zumerlab/snapdom) for
|
|
488
|
+
Zumly is a reimagined, framework-agnostic zoom engine inspired by [Zircle UI](https://github.com/zircleUI/zircleUI). Part of the [Zumerlab](https://github.com/zumerlab) ecosystem — use it with [Orbit](https://github.com/zumerlab/orbit) for radial layouts and [SnapDOM](https://github.com/zumerlab/snapdom) for DOM-to-image capture. Use [SnapDIFF](https://github.com/zumerlab/snapdiff) to compare captures for visual regression testing.
|
|
452
489
|
|
|
453
490
|
## License
|
|
454
491
|
|
package/dist/zumly.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* zumly
|
|
3
|
-
* v.0.
|
|
3
|
+
* v.0.97.0
|
|
4
4
|
* Author Juan Martin Muda - Zumerlab
|
|
5
5
|
* License MIT
|
|
6
6
|
*/
|
|
7
|
-
var Tt=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var ze=Object.getOwnPropertyNames;var ke=Object.prototype.hasOwnProperty;var Ce=(r,t)=>{for(var e in t)Tt(r,e,{get:t[e],enumerable:!0})},Oe=(r,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ze(t))!ke.call(r,n)&&n!==e&&Tt(r,n,{get:()=>t[n],enumerable:!(s=Le(t,n))||s.enumerable});return r};var Ae=r=>Oe(Tt({},"__esModule",{value:!0}),r);var ts={};Ce(ts,{Zumly:()=>tt,ZumlyRouter:()=>Ot,default:()=>Je});module.exports=Ae(ts);var ft=class{#t={};constructor(t={}){this.#t=t}#e(t){return typeof t=="function"?"function":t instanceof HTMLElement?"element":typeof t=="object"&&t!==null&&typeof t.render=="function"?"object":typeof t!="string"?"unknown":/^https?:\/\/|^\/|\.html$|\.php$/i.test(t)?"url":t.includes("<")?"html":t.includes("-")?"webcomponent":"unknown"}async resolve(t,e=null){if(typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.#t,t)){let n=this.#t[t];return this.resolve(n,e)}switch(this.#e(t)){case"html":{let n=document.createElement("div");n.innerHTML=t.trim();let o=n.firstElementChild;if(!o)throw new Error("Zumly: view produced no element (html)");return o}case"url":{let n=new AbortController,o=setTimeout(()=>n.abort(),1e4),i;try{i=await fetch(t,{signal:n.signal})}finally{clearTimeout(o)}if(!i.ok)throw new Error(`Zumly: fetch failed for "${t}" (${i.status})`);let a=await i.text(),l=document.createElement("div");l.innerHTML=a.trim();let c=l.firstElementChild;if(!c)throw new Error("Zumly: view produced no element (url)");return c}case"function":{let n=e&&e.target||document.createElement("div"),o=await t({...e,target:n});if(typeof o=="string")return this.resolve(o,e);if(o instanceof HTMLElement)return o;let i=n.firstElementChild||n;return i.classList.contains("z-view")||i.classList.add("z-view"),i}case"object":{let n=await t.render(e);if(typeof n!="string")throw new Error("Zumly: view render() must return string");return this.resolve(n,e)}case"element":return t.cloneNode(!0);case"webcomponent":return await customElements.whenDefined(t),document.createElement(t);default:throw new Error("Zumly: unknown view type for source")}}};async function st(r,t,e,s,n,o){if(!r||!r.classList){let i=document.createElement("div");i.classList.add("z-view"),r&&i.appendChild(r),r=i}else r.classList.contains("z-view")||r.classList.add("z-view");return r.dataset.viewName=t,r.getAttribute("aria-label")||r.setAttribute("aria-label",`View: ${t}`),r.style.transformOrigin="0 0",r.style.position="absolute",s?r.classList.add("is-current-view"):r.classList.add("is-new-current-view","has-no-events","hide"),e.append(r),typeof n[t]=="object"&&typeof n[t].mounted=="function"&&await n[t].mounted(),r}function L(r,t,e){t&&e==="welcome"&&console.info(`%c Zumly %c ${t}`,"background: #424085; color: white; border-radius: 3px;","color: #424085"),t&&r&&(e==="info"||e===void 0)&&console.info(`%c Zumly %c ${t}`,"background: #6679A3; color: #304157; border-radius: 3px;","color: #6679A3"),t&&e==="warn"&&console.warn(`%c Zumly %c ${t}`,"background: #DCBF53; color: #424085; border-radius: 3px;","color: #424085"),t&&e==="error"&&console.error(`%c Zumly %c ${t}`,"background: #BE4747; color: white; border-radius: 3px;","color: #424085")}function Ht(r,t){if(t.isValid=!1,!r||typeof r!="object"){L(!1,"'options' object has to be provided when instance is defined","error");return}if(typeof r.mount!="string"){L(!1,"'mount' must be a string selector","error");return}if(t.mount=r.mount,typeof r.initialView!="string"){L(!1,"'initialView' must be a string","error");return}if(t.initialView=r.initialView,!r.views||typeof r.views!="object"){L(!1,"'views' must be an object","error");return}t.views=r.views,t.isValid=!0,t.preload=Array.isArray(r.preload)?r.preload:[],t.debug=typeof r.debug=="boolean"?r.debug:!1,t.componentContext=r.componentContext&&typeof r.componentContext=="object"?r.componentContext:new Map;let e=r.transitions&&typeof r.transitions=="object"?r.transitions:null,s=e&&e.cover,n=typeof s=="string"?s.toLowerCase():null,o=n==="width"||n==="height";t.cover=o?n:"width",!o&&e&&s!==void 0&&L(!1,`'transitions.cover' must be either "width" or "height". Falling back to "width".`,"warn"),t.duration=e&&typeof e.duration=="string"?e.duration:"1s",t.ease=e&&typeof e.ease=="string"?e.ease:"ease-in-out",t.deferred=typeof r.deferred=="boolean"?r.deferred:!1;let i=e&&e.hideTrigger;i===!0||i==="fade"?t.hideTrigger=i:(t.hideTrigger=!1,i!=null&&i!==!1&&L(!1,`'transitions.hideTrigger' must be true or "fade". Falling back to false.`,"warn"));let a=e&&e.effects;Array.isArray(a)&&a.length>=2&&typeof a[0]=="string"&&typeof a[1]=="string"?t.effects=[a[0],a[1]]:Array.isArray(a)&&a.length===1&&typeof a[0]=="string"?t.effects=[a[0],a[0]]:(t.effects=["none","none"],a!=null&&L(!1,`'transitions.effects' must be an array of 1-2 CSS filter strings (e.g. ["blur(3px)", "blur(8px) saturate(0)"]). Falling back to no effects.`,"warn"));let l=e&&e.driver,c=typeof l=="string"?l.toLowerCase():null,f=typeof l=="function"?l:null;if(c!==null){let d=["css","waapi","none","anime","gsap","motion"];t.transitionDriver=d.includes(c)?c:"css",d.includes(c)||L(!1,`'transitions.driver' must be "css", "waapi", "none", "anime", "gsap", "motion", or a function. Got "${l}". Falling back to "css".`,"warn")}else f!==null?t.transitionDriver=f:t.transitionDriver="css";let u=e&&e.stagger;typeof u=="number"&&u>0?t.stagger=u:(t.stagger=0,u!=null&&u!==0&&L(!1,"'transitions.stagger' must be a positive number (ms). Falling back to 0 (disabled).","warn")),t.parallax=0;let h=r.lateralNav;if(h===!1)t.lateralNav=!1;else if(h&&typeof h=="object"){let d=typeof h.mode=="string"?h.mode.toLowerCase():null,g=d==="auto"||d==="always";d&&!g&&L(!1,`'lateralNav.mode' must be "auto" or "always". Falling back to "auto".`,"warn");let v=null;if(Array.isArray(h.siblings))v=h.siblings.filter(w=>typeof w=="string"&&w),v.length<2&&(L(!1,"'lateralNav.siblings' needs at least 2 view names. Ignoring.","warn"),v=null);else if(h.siblings&&typeof h.siblings=="object"){v={};for(let[w,b]of Object.entries(h.siblings))if(Array.isArray(b)){let _=b.filter(S=>typeof S=="string"&&S);_.length>=2&&(v[w]=_)}Object.keys(v).length===0&&(v=null)}else h.siblings!==void 0&&L(!1,"'lateralNav.siblings' must be an array of view names or a { parentView: [...] } map. Ignoring.","warn");t.lateralNav={mode:g?d:"auto",arrows:typeof h.arrows=="boolean"?h.arrows:!0,dots:typeof h.dots=="boolean"?h.dots:!0,keepAlive:h.keepAlive===!0||h.keepAlive==="visible"?h.keepAlive:!1,siblings:v}}else t.lateralNav={mode:"auto",arrows:!0,dots:!0,keepAlive:!1,siblings:null};let m=r.depthNav;if(m===!1)t.depthNav=!1;else if(m&&typeof m=="object"){let d=typeof m.position=="string"?m.position.toLowerCase():null,g=d==="bottom-left"||d==="top-left";d&&!g&&L(!1,`'depthNav.position' must be "bottom-left" or "top-left". Falling back to "bottom-left".`,"warn"),t.depthNav={position:g?d:"bottom-left"}}else t.depthNav={position:"bottom-left"};let y=r.lateralNav&&typeof r.lateralNav=="object"?r.lateralNav.position:void 0;if(t.lateralNav&&typeof t.lateralNav=="object"){let d=y==="bottom-center"||y==="top-center";y&&!d&&L(!1,`'lateralNav.position' must be "bottom-center" or "top-center". Falling back to "bottom-center".`,"warn"),t.lateralNav.position=d?y:"bottom-center"}let p=r.inputs;p&&typeof p=="object"?t.inputs={wheel:typeof p.wheel=="boolean"?p.wheel:!0,keyboard:typeof p.keyboard=="boolean"?p.keyboard:!0,click:typeof p.click=="boolean"?p.click:!0,touch:typeof p.touch=="boolean"?p.touch:!0}:t.inputs={wheel:!0,keyboard:!0,click:!0,touch:!0}}function jt(r,t,e,s,n){let o=e/r,i=s/t;return n==="height"?{scale:i,scaleInv:1/i}:{scale:o,scaleInv:1/o}}function Rt(r,t,e,s){let n=t.left,o=t.top,i=r.x-n+(r.width-e.width*s)/2,a=r.y-o+(r.height-e.height*s)/2;return`translate(${i}px, ${a}px) scale(${s})`}function qt(r,t,e){let s=t.left,n=t.top,o=r.x-s+(r.width-e.width)/2,i=r.y-n+(r.height-e.height)/2;return`translate(${o}px, ${i}px)`}function Bt(r,t){let e=r.x+r.width/2-t.x,s=r.y+r.height/2-t.y;return`${e}px ${s}px`}function Vt(r,t,e,s,n=0){let o=r.width/2-t.width/2-t.x+e.x,i=r.height/2-t.height/2-t.y+e.y,a=1-n,l=o*a,c=i*a;return{x:o,y:i,transform:`translate(${l}px, ${c}px) scale(${s})`}}function Xt({canvasRect:r,canvasOffset:t,triggerRect:e,previousViewRectAtBaseTransform:s,lastViewZoomedElementRect:n,previousViewRectWithPreviousAtEndTransform:o,scale:i,preScale:a,parallax:l=0}){let c=t.left,f=t.top,u=r.width/2-e.width/2-e.x,h=r.height/2-e.height/2-e.y,m=u+(s.x-n.x)+o.x-c+(o.width-n.width)/2,y=h+(s.y-n.y)+o.y-f+(o.height-n.height)/2,p=1-Math.min(l*2,.9);return`translate(${m*p}px, ${y*p}px) scale(${i*a})`}function Yt(r,t,e,s,n){return`translate(${r-e.left}px, ${t-e.top}px) scale(${s*n})`}function ut(r){let t=r.split(/\s+/);return{x:parseFloat(t[0])||0,y:parseFloat(t[1])||0}}function rt(r){let t=typeof r=="string"?r:"",e=t.match(/translate\s*\(\s*([-+\d.eE]+)px\s*,\s*([-+\d.eE]+)px\s*\)/);if(!e)return{tx:0,ty:0,rest:t.trim(),matched:!1};let s=t.replace(/translate\s*\([^)]+\)\s*/,"").trim();return{tx:parseFloat(e[1]),ty:parseFloat(e[2]),rest:s,matched:!0}}function nt(r){let t=rt(r),e=r.match(/scale\s*\(\s*([-+\d.eE]+)\s*\)/);return{tx:t.matched?t.tx:0,ty:t.matched?t.ty:0,scale:e?parseFloat(e[1]):1}}function ht(r,t,e,s,n,o,i,a,l,c){let f=t.x-e.x*(1-o)-s,u=t.y-e.y*(1-o)-n,h=t.width/o,m=t.height/o,y=f+e.x+(r.x-f-e.x-s)/o,p=u+e.y+(r.y-u-e.y-n)/o,d=r.width/o,g=r.height/o,v=f+i.x+a+c*(y-f-i.x),w=u+i.y+l+c*(p-u-i.y),b=d*c,_=g*c;return{x:v,y:w,width:b,height:_,left:v,top:w,right:v+b,bottom:w+_}}function ot(r,t,e){return{viewName:r,backwardState:t,forwardState:e}}function Ut(r){return{detachedNode:r}}function Wt(r,t,e,s,n){let o=[];return t!==null&&o.push(t),e!==null&&o.push(e),s!==null&&o.push(s),n!==null&&o.push(n),{zoomLevel:r,views:o}}function Kt(r){let t=r.views?.[3];if(!(!t||!(t.detachedNode instanceof Node)))return t.detachedNode}var dt=class{#t=new Map;set(t,e,s=null){this.#t.set(t,{node:e,expires:s?Date.now()+s:null})}get(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>e.expires?(this.#t.delete(t),null):e.node.cloneNode(!0):null}has(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>e.expires?(this.#t.delete(t),!1):!0:!1}invalidate(t){this.#t.delete(t)}clear(){this.#t.clear()}};var Pe=300*1e3,Ie=/^https?:\/\/|^\/|\.html$|\.php$/i,mt=class{#t;#e;#r;#s=new Map;constructor(t={}){this.#r=t,this.#t=new ft(t),this.#e=new dt}#n(t){return typeof this.#r[t]=="string"}#o(t){return Ie.test(t)?Pe:null}async get(t,e=null){if(this.#n(t)){let s=this.#e.get(t);if(s)return s;if(this.#s.has(t))return this.#s.get(t);let n=(async()=>{try{let o=await this.#t.resolve(t,e),i=this.#r[t],a=this.#o(i);return this.#e.set(t,o,a),o}finally{this.#s.delete(t)}})();return this.#s.set(t,n),n}return this.#t.resolve(t,e)}async preloadEager(t,e=null){!Array.isArray(t)||t.length===0||await Promise.all(t.map(s=>this.get(s,e)))}prefetch(t,e=null){this.get(t,e).catch(()=>{})}prefetchOnHover(t,e=null){this.prefetch(t,e)}scanAndPrefetch(t,e=null){if(!t||!t.querySelectorAll)return;t.querySelectorAll(".zoom-me[data-to]").forEach(n=>{let o=n.dataset.to;o&&(n.hasAttribute("role")||n.setAttribute("role","button"),n.hasAttribute("aria-label")||n.setAttribute("aria-label",`Zoom to ${o}`),this.prefetch(o,e))})}};function K(r){r&&(r.style.contentVisibility="hidden")}function X(r){r&&(r.style.contentVisibility="visible")}function F(r){if(typeof r=="number"&&!Number.isNaN(r))return Math.max(0,r);let t=String(r).trim(),e=t.match(/^(\d*\.?\d+)\s*(ms|s)?$/i);if(!e)return typeof console<"u"&&console.warn(`[zumly] Could not parse duration "${t}" \u2014 falling back to 500ms.`),500;let s=parseFloat(e[1]);return(e[2]||"s").toLowerCase()==="ms"?Math.max(0,s):Math.max(0,s*1e3)}function pt(r){return F(r)/1e3}function T(r,t){if(r.classList.contains("is-new-current-view")){let e=t.views[0].forwardState;r.classList.replace("is-new-current-view","is-current-view"),r.classList.remove("zoom-current-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-previous-view")){let e=t.views[1].forwardState;r.classList.remove("zoom-previous-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-last-view")){let e=t.views[2].forwardState;r.classList.remove("zoom-last-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform}}function N(r,t){r.classList.remove("zoom-previous-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin="0 0",r.style.transform=t.transform}function $(r,t){r.classList.remove("zoom-last-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin=t.origin,r.style.transform=t.transform}function C(r,t){try{t&&t.removeChild(r)}catch{try{r.parentElement&&t.removeChild(r.parentElement)}catch{}}}function z(...r){for(let t of r)t&&(t.classList.remove("hide"),X(t))}function H(r,t){let{currentView:e,previousView:s,backView:n,backViewState:o,lastView:i,lastViewState:a,incomingTransformEnd:l,currentStage:c,canvas:f}=r,u=c.views[0];z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=u.forwardState.origin,e.style.transform=l||u.forwardState.transform,n&&o&&(n.style.transform=o.transformEnd),i&&a&&(i.style.transform=a.transformEnd),r.keepAlive||C(s,f),t()}var j=150;function R(r,t){let e=!1,s=setTimeout(()=>{e||(e=!0,r())},t);return{finish(){e||(e=!0,clearTimeout(s),r())},extend(n){e||(clearTimeout(s),s=setTimeout(()=>{e||(e=!0,r())},n))},safetyTimer:s}}function Gt(){return{a:1,b:0,c:0,d:1,e:0,f:0}}function Ne(r){if(!r||r==="none")return Gt();let t=String(r).match(/matrix\(([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+)\)/);return t?{a:parseFloat(t[1])||1,b:parseFloat(t[2])||0,c:parseFloat(t[3])||0,d:parseFloat(t[4])||1,e:parseFloat(t[5])||0,f:parseFloat(t[6])||0}:Gt()}function Q(r){return`matrix(${r.a}, ${r.b}, ${r.c}, ${r.d}, ${r.e}, ${r.f})`}function G(r,t,e){return r+(t-r)*e}function J(r,t,e){let s=Math.max(0,Math.min(1,e));return{a:G(r.a,t.a,s),b:G(r.b,t.b,s),c:G(r.c,t.c,s),d:G(r.d,t.d,s),e:G(r.e,t.e,s),f:G(r.f,t.f,s)}}function Z(r,t,e){r.style.transformOrigin=t,r.style.transform=e;try{r.getBoundingClientRect()}catch{}return Ne(getComputedStyle(r).transform)}function Jt(r,t){let{type:e,currentView:s,previousView:n,lastView:o,currentStage:i,duration:a,ease:l,canvas:c}=r;if(!s||!n||!i){t();return}e==="lateral"?$e(r,t):e==="zoomIn"?Ze(s,n,o,i,a,l,t):e==="zoomOut"?Me(s,n,o,i,a,l,c,t):t()}function $e(r,t){let{currentView:e,previousView:s,backView:n,backViewState:o,lastView:i,lastViewState:a,incomingTransformStart:l,incomingTransformEnd:c,outgoingTransform:f,outgoingTransformEnd:u,currentStage:h,duration:m,ease:y,canvas:p}=r,d=F(m),g=h.views[0];z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=g.forwardState.origin,n&&o&&(M(n,m,y,{"--lateral-from":o.transformStart,"--lateral-to":o.transformEnd}),n.classList.add("zoom-lateral-back")),i&&a&&(M(i,m,y,{"--lateral-from":a.transformStart,"--lateral-to":a.transformEnd}),i.classList.add("zoom-lateral-back")),r.keepAlive!=="visible"&&(M(s,m,y,{"--lateral-out-from":f,"--lateral-out-to":u}),s.classList.add("zoom-lateral-out")),M(e,m,y,{"--lateral-in-from":l,"--lateral-in-to":c}),e.classList.add("zoom-lateral-in");let v=r.keepAlive==="visible"?[e]:[s,e];n&&o&&v.push(n),i&&a&&v.push(i);let w=v.length,b=d+j,_=new Set(["zoom-lateral-in","zoom-lateral-out","zoom-lateral-back"]),{finish:S,extend:O}=R(()=>{Et(v,I,P),r.keepAlive?(s.classList.remove("zoom-lateral-out"),s.style.opacity=""):C(s,p),n&&(n.classList.remove("zoom-lateral-back"),n.style.transform=o?.transformEnd||n.style.transform),i&&(i.classList.remove("zoom-lateral-back"),i.style.transform=a?.transformEnd||i.style.transform),e.classList.remove("zoom-lateral-in"),e.style.transform=c,t()},b);function P(x){x.target!==x.currentTarget||!_.has(x.animationName)||O(b)}function I(x){if(x.target!==x.currentTarget||!_.has(x.animationName))return;let q=x.currentTarget;q.removeEventListener("animationend",I),q.removeEventListener("animationstart",P),w--,w<=0&&S()}v.forEach(x=>{x.addEventListener("animationstart",P),x.addEventListener("animationend",I)})}function Ze(r,t,e,s,n,o,i){z(r,t,e);let a=s.stagger||0;M(r,n,o,{"--current-view-transform-start":s.views[0].backwardState.transform,"--current-view-transform-end":s.views[0].forwardState.transform}),a>0&&r.style.setProperty("animation-delay","0ms"),M(t,n,o,{"--previous-view-transform-start":s.views[1].backwardState.transform,"--previous-view-transform-end":s.views[1].forwardState.transform}),a>0&&t.style.setProperty("animation-delay",`${a}ms`),e&&(M(e,n,o,{"--last-view-transform-start":s.views[2].backwardState.transform,"--last-view-transform-end":s.views[2].forwardState.transform}),a>0&&e.style.setProperty("animation-delay",`${a*2}ms`)),r.classList.add("zoom-current-view"),t.classList.add("zoom-previous-view"),e&&e.classList.add("zoom-last-view");let l=e?[r,t,e]:[r,t],c=l.length,f=F(n),u=e?a*2:a,h=f+u+j,m=new Set(["zoom-current-view","zoom-previous-view","zoom-last-view"]),{finish:y,extend:p}=R(()=>{Et(l,g,d),l.forEach(v=>v.style.removeProperty("animation-delay")),l.forEach(v=>{if(v?.isConnected)try{T(v,s)}catch{}}),i()},h);function d(v){v.target!==v.currentTarget||!m.has(v.animationName)||p(h)}function g(v){if(v.target!==v.currentTarget||!m.has(v.animationName))return;let w=v.currentTarget;if(w.removeEventListener("animationend",g),w.removeEventListener("animationstart",d),w.isConnected)try{T(w,s)}catch{}c--,c<=0&&y()}l.forEach(v=>{v.addEventListener("animationstart",d),v.addEventListener("animationend",g)})}function Me(r,t,e,s,n,o,i,a){let l=s.views[0],c=s.views[1],f=e&&s.views[2]?s.views[2]:null,u=s.stagger||0;M(r,n,o,{"--current-view-transform-start":l.backwardState.transform,"--current-view-transform-end":l.forwardState.transform}),u>0&&r.style.setProperty("animation-delay","0ms"),M(t,n,o,{"--previous-view-transform-start":c.backwardState.transform,"--previous-view-transform-end":c.forwardState.transform}),u>0&&t.style.setProperty("animation-delay",`${u}ms`),e&&f&&(M(e,n,o,{"--last-view-transform-start":f.backwardState.transform,"--last-view-transform-end":f.forwardState.transform}),u>0&&e.style.setProperty("animation-delay",`${u*2}ms`)),r.classList.add("zoom-current-view-reverse"),t.classList.add("zoom-previous-view-reverse"),e&&e.classList.add("zoom-last-view-reverse");let h=e?[r,t,e]:[r,t],m=h.length,y=F(n),p=e?u*2:u,d=y+p+j,g=new Set(["zoom-current-view-reverse","zoom-previous-view-reverse","zoom-last-view-reverse"]),{finish:v,extend:w}=R(()=>{Et(h,_,b),h.forEach(S=>S.style.removeProperty("animation-delay")),h.forEach(S=>{if(S?.isConnected)try{Qt(S,s,i)}catch{}}),a()},d);function b(S){S.target!==S.currentTarget||!g.has(S.animationName)||w(d)}function _(S){if(S.target!==S.currentTarget||!g.has(S.animationName))return;let O=S.currentTarget;if(O.removeEventListener("animationend",_),O.removeEventListener("animationstart",b),O.isConnected)try{Qt(O,s,i)}catch{}m--,m<=0&&v()}h.forEach(S=>{S.addEventListener("animationstart",b),S.addEventListener("animationend",_)})}function Qt(r,t,e){if(r.classList.contains("zoom-current-view-reverse")){C(r,e);return}if(r.classList.contains("zoom-previous-view-reverse")){N(r,t.views[1].backwardState);return}r.classList.contains("zoom-last-view-reverse")&&$(r,t.views[2].backwardState)}function M(r,t,e,s){r.style.setProperty("--zoom-duration",t),r.style.setProperty("--zoom-ease",e);for(let[n,o]of Object.entries(s))r.style.setProperty(n,o)}function Et(r,t,e){for(let s of r)s?.removeEventListener&&(s.removeEventListener("animationend",t),s.removeEventListener("animationstart",e))}function te(r,t){let{type:e,currentView:s,previousView:n,lastView:o,currentStage:i,canvas:a}=r;if(!s||!n||!i){t();return}if(e==="lateral"){H(r,t);return}if(e==="zoomIn"){z(s,n,o),T(s,i),T(n,i),o&&T(o,i),t();return}if(e==="zoomOut"){C(s,a),z(n,o),N(n,i.views[1].backwardState),o&&$(o,i.views[2].backwardState),t();return}t()}function ee(r,t){let{type:e,currentView:s,previousView:n,lastView:o,currentStage:i,duration:a,ease:l,canvas:c}=r;if(!s||!n||!i){t();return}let f=F(a);if(e==="lateral"){He(r,f,l,t);return}if(e==="zoomIn"){De(s,n,o,i,f,l,t);return}if(e==="zoomOut"){Fe(s,n,o,i,f,l,c,t);return}t()}function De(r,t,e,s,n,o,i){z(r,t,e);let a=s.views[0],l=s.views[1],c=e&&s.views[2]?s.views[2]:null;r.style.transformOrigin=a.backwardState.origin,r.style.transform=a.backwardState.transform,t.style.transformOrigin=l.backwardState.origin,t.style.transform=l.backwardState.transform,c&&(e.style.transformOrigin=c.backwardState.origin,e.style.transform=c.backwardState.transform);let f=s.stagger||0,u=[];u.push(r.animate([{transform:a.backwardState.transform},{transform:a.forwardState.transform}],{duration:n,easing:o,fill:"forwards"})),u.push(t.animate([{transform:l.backwardState.transform},{transform:l.forwardState.transform}],{duration:n,delay:f,easing:o,fill:"forwards"})),c&&u.push(e.animate([{transform:c.backwardState.transform},{transform:c.forwardState.transform}],{duration:n,delay:f*2,easing:o,fill:"forwards"}));let h=c?f*2:f,{finish:m}=R(()=>{xt(u);try{T(r,s),T(t,s),e&&T(e,s)}catch{}i()},n+h+j);Promise.all(u.map(y=>y.finished)).then(m).catch(m)}function Fe(r,t,e,s,n,o,i,a){let l=s.views[0],c=s.views[1],f=e&&s.views[2]?s.views[2]:null,u=c.backwardState,h=f?f.backwardState:null;r.style.transformOrigin=l.forwardState.origin,r.style.transform=l.forwardState.transform,requestAnimationFrame(()=>{requestAnimationFrame(()=>{t.style.transformOrigin=c.forwardState.origin,e&&f&&(e.style.transformOrigin=f.forwardState.origin);let m=t.style.transform||getComputedStyle(t).transform||c.forwardState.transform,y=e&&f?e.style.transform||getComputedStyle(e).transform||f.forwardState.transform:null,p=s.stagger||0,d=[];d.push(r.animate([{transform:l.forwardState.transform},{transform:l.backwardState.transform}],{duration:n,easing:o,fill:"forwards"})),d.push(t.animate([{transform:m},{transform:u.transform}],{duration:n,delay:p,easing:o,fill:"both"})),e&&h&&d.push(e.animate([{transform:y},{transform:h.transform}],{duration:n,delay:p*2,easing:o,fill:"both"})),t.style.removeProperty("transform"),e&&e.style.removeProperty("transform");let g=e&&h?p*2:p,{finish:v}=R(()=>{xt(d);try{C(r,i),N(t,u),e&&h&&$(e,h)}catch{}a()},n+g+j);Promise.all(d.map(w=>w.finished)).then(v).catch(v)})})}function He(r,t,e,s){let{currentView:n,previousView:o,backView:i,backViewState:a,lastView:l,lastViewState:c,incomingTransformStart:f,incomingTransformEnd:u,outgoingTransform:h,outgoingTransformEnd:m,currentStage:y,canvas:p}=r,d=y.views[0];z(n),n.classList.replace("is-new-current-view","is-current-view"),n.classList.remove("zoom-current-view","has-no-events"),n.style.transformOrigin=d.forwardState.origin;let g=[];g.push(n.animate([{transform:f,opacity:0},{transform:u,opacity:1}],{duration:t,easing:e,fill:"forwards"})),r.keepAlive!=="visible"&&g.push(o.animate([{transform:h,opacity:1},{transform:m,opacity:0}],{duration:t,easing:e,fill:"forwards"})),i&&a&&g.push(i.animate([{transform:a.transformStart},{transform:a.transformEnd}],{duration:t,easing:e,fill:"forwards"})),l&&c&&g.push(l.animate([{transform:c.transformStart},{transform:c.transformEnd}],{duration:t,easing:e,fill:"forwards"}));let{finish:v}=R(()=>{xt(g),n.style.transform=u||d.forwardState.transform,i&&a&&(i.style.transform=a.transformEnd),l&&c&&(l.style.transform=c.transformEnd),r.keepAlive?(o.style.opacity="",o.style.transform=m):C(o,p),s()},t+j);Promise.all(g.map(w=>w.finished)).then(v).catch(v)}function xt(r){for(let t of r)try{t.cancel()}catch{}}function se(r,t){let e=typeof globalThis<"u"&&globalThis.anime;if(!e||typeof e!="function"){console.warn('Zumly anime driver: Anime.js not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.2/anime.min.js"><\/script>'),t();return}let{type:s,currentView:n,previousView:o,lastView:i,currentStage:a,duration:l,ease:c,canvas:f}=r;if(!n||!o||!a){t();return}let u=F(l);s==="lateral"?H(r,t):s==="zoomIn"?je(e,n,o,i,a,u,c,t):s==="zoomOut"?Re(e,n,o,i,a,u,c,f,t):t()}function je(r,t,e,s,n,o,i,a){z(t,e,s);let l=n.views[0],c=n.views[1],f=s&&n.views[2]?n.views[2]:null,u=re([{el:t,backward:l.backwardState,forward:l.forwardState},{el:e,backward:c.backwardState,forward:c.forwardState},...f?[{el:s,backward:f.backwardState,forward:f.forwardState}]:[]],"forward");ne(u,0);let h=n.stagger||0,m=o+(f?h*2:h),y={value:0};r({targets:y,value:1,duration:m,easing:ie(i),update:()=>{let p=y.value*m;oe(u,p,o,h)},complete:()=>{T(t,n),T(e,n),s&&T(s,n),a()}})}function Re(r,t,e,s,n,o,i,a,l){let c=n.views[0],f=n.views[1],u=s&&n.views[2]?n.views[2]:null,h=f.backwardState,m=u?u.backwardState:null,y=re([{el:t,backward:c.backwardState,forward:c.forwardState},{el:e,backward:f.backwardState,forward:f.forwardState},...u?[{el:s,backward:u.backwardState,forward:u.forwardState}]:[]],"backward");ne(y,0);let p=n.stagger||0,d=o+(u?p*2:p),g={value:0};r({targets:g,value:1,duration:d,easing:ie(i),update:()=>{let v=g.value*d;oe(y,v,o,p)},complete:()=>{C(t,a),N(e,h),s&&m&&$(s,m),l()}})}function re(r,t){return r.map(({el:e,backward:s,forward:n})=>{if(t==="forward"){let o=Z(e,s.origin,s.transform),i=Z(e,s.origin,n.transform);return{el:e,from:o,to:i}}else{let o=Z(e,n.origin,n.transform),i=Z(e,n.origin,s.transform);return{el:e,from:o,to:i}}})}function ne(r,t){for(let{el:e,from:s,to:n}of r)e.style.transform=Q(J(s,n,t))}function oe(r,t,e,s){for(let n=0;n<r.length;n++){let{el:o,from:i,to:a}=r[n],l=n*s,c=Math.max(0,t-l),f=e>0?Math.min(1,c/e):1;o.style.transform=Q(J(i,a,f))}}function ie(r){if(typeof r!="string")return"easeInOutQuad";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOutQuad":t.includes("ease-in")?"easeInQuad":t.includes("ease-out")?"easeOutQuad":t}function ae(r,t){let e=typeof globalThis<"u"&&globalThis.gsap;if(!e||typeof e.to!="function"){console.warn('Zumly GSAP driver: GSAP not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"><\/script>'),t();return}let{type:s,currentView:n,previousView:o,lastView:i,currentStage:a,duration:l,ease:c,canvas:f}=r;if(!n||!o||!a){t();return}let u=pt(l);s==="lateral"?H(r,t):s==="zoomIn"?qe(e,n,o,i,a,u,c,t):s==="zoomOut"?Be(e,n,o,i,a,u,c,f,t):t()}function qe(r,t,e,s,n,o,i,a){z(t,e,s);let l=n.views[0],c=n.views[1],f=s&&n.views[2]?n.views[2]:null;vt(t,l.backwardState),vt(e,c.backwardState),f&&vt(s,f.backwardState);let u=r.timeline({onComplete:()=>{T(t,n),T(e,n),s&&T(s,n),a()}}),h=le(i),m=(n.stagger||0)/1e3;u.to(t,{transform:l.forwardState.transform,duration:o,ease:h},0),u.to(e,{transform:c.forwardState.transform,duration:o,ease:h},m),f&&u.to(s,{transform:f.forwardState.transform,duration:o,ease:h},m*2)}function Be(r,t,e,s,n,o,i,a,l){let c=n.views[0],f=n.views[1],u=s&&n.views[2]?n.views[2]:null,h=f.backwardState,m=u?u.backwardState:null;vt(t,c.forwardState);let y=e.style.transform||getComputedStyle(e).transform||f.forwardState.transform,p=s&&u?s.style.transform||getComputedStyle(s).transform||u.forwardState.transform:null;e.style.transformOrigin=f.forwardState.origin,s&&u&&(s.style.transformOrigin=u.forwardState.origin);let d=le(i),g=r.timeline({onComplete:()=>{C(t,a),N(e,h),s&&m&&$(s,m),l()}}),v=(n.stagger||0)/1e3;r.set(e,{transform:y}),s&&p&&r.set(s,{transform:p}),g.fromTo(t,{transform:c.forwardState.transform},{transform:c.backwardState.transform,duration:o,ease:d},0),g.fromTo(e,{transform:y},{transform:h.transform,duration:o,ease:d},v),s&&m&&g.fromTo(s,{transform:p},{transform:m.transform,duration:o,ease:d},v*2)}function vt(r,t){r.style.transformOrigin=t.origin,r.style.transform=t.transform}function le(r){if(typeof r!="string")return"power2.inOut";let t=r.toLowerCase();return t==="linear"?"none":t.includes("ease-in-out")?"power2.inOut":t.includes("ease-in")?"power2.in":t.includes("ease-out")?"power2.out":t}function ce(r,t){let e=Ye();if(!e||typeof e!="function"){console.warn('Zumly Motion driver: Motion not loaded. Add <script src="https://cdn.jsdelivr.net/npm/motion@11/dist/motion.min.js"><\/script>'),t();return}let{type:s,currentView:n,previousView:o,lastView:i,currentStage:a,duration:l,ease:c,canvas:f}=r;if(!n||!o||!a){t();return}let u=pt(l);s==="lateral"?H(r,t):s==="zoomIn"?Ve(e,n,o,i,a,u,c,t):s==="zoomOut"?Xe(e,n,o,i,a,u,c,f,t):t()}function Ve(r,t,e,s,n,o,i,a){z(t,e,s);let l=fe(t,e,s,n,"forward");ue(l,0);let c=n.stagger||0,f=c/1e3,u=o*1e3,h=o+(l.length>2?f*2:f);r(0,1,{duration:h,ease:de(i),onUpdate:y=>{let p=y*h*1e3;he(l,p,u,c)}}).then(()=>{T(t,n),T(e,n),s&&T(s,n),a()}).catch(()=>a())}function Xe(r,t,e,s,n,o,i,a,l){let c=n.views[1],f=s&&n.views[2]?n.views[2]:null,u=c.backwardState,h=f?f.backwardState:null,m=fe(t,e,s,n,"backward");ue(m,0);let y=n.stagger||0,p=y/1e3,d=o*1e3,g=o+(m.length>2?p*2:p);r(0,1,{duration:g,ease:de(i),onUpdate:w=>{let b=w*g*1e3;he(m,b,d,y)}}).then(()=>{C(t,a),N(e,u),s&&h&&$(s,h),l()}).catch(()=>l())}function fe(r,t,e,s,n){let o=s.views[0],i=s.views[1],a=e&&s.views[2]?s.views[2]:null,l=[{el:r,backward:o.backwardState,forward:o.forwardState},{el:t,backward:i.backwardState,forward:i.forwardState}];return a&&l.push({el:e,backward:a.backwardState,forward:a.forwardState}),l.map(({el:c,backward:f,forward:u})=>n==="forward"?{el:c,from:Z(c,f.origin,f.transform),to:Z(c,f.origin,u.transform)}:{el:c,from:Z(c,u.origin,u.transform),to:Z(c,u.origin,f.transform)})}function ue(r,t){for(let{el:e,from:s,to:n}of r)e.style.transform=Q(J(s,n,t))}function he(r,t,e,s){for(let n=0;n<r.length;n++){let{el:o,from:i,to:a}=r[n],l=n*s,c=Math.max(0,t-l),f=e>0?Math.min(1,c/e):1;o.style.transform=Q(J(i,a,f))}}function Ye(){let r=typeof globalThis<"u"?globalThis:typeof window<"u"?window:{};return r.motion?.animate||r.Motion?.animate||r.animate}function de(r){if(typeof r!="string")return"easeInOut";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOut":t.includes("ease-in")?"easeIn":t.includes("ease-out")?"easeOut":r}var me={css:Jt,waapi:ee,none:te,anime:se,gsap:ae,motion:ce};function pe(r){if(typeof r=="function")return{runTransition(s,n){r(s,n)}};let t=typeof r=="string"?r.toLowerCase():"css";return{runTransition:me[t]||me.css}}function Ue(r){if(typeof r!="string"||r.trim()==="")return{tx:0,ty:0,rest:""};let t=rt(r);return t.matched?{tx:t.tx,ty:t.ty,rest:t.rest}:null}function Lt(r,t,e){let s=Ue(r);if(s===null)return r;let n=s.tx*t,o=s.ty*e,i=s.rest?` ${s.rest}`:"";return`translate(${n}px, ${o}px)${i}`.trim()}function We(r){if(typeof r!="string"||!r.trim())return null;let t=r.trim().match(/^([-\d.eE]+)px\s+([-\d.eE]+)px$/);return t?{x:parseFloat(t[1]),y:parseFloat(t[2])}:null}function zt(r,t,e){let s=We(r);return s===null?r:`${s.x*t}px ${s.y*e}px`}function kt(r,t,e,s,n){if(!r.storedViews?.length||!r.canvas||t<=0||e<=0)return;let o=s/t,i=n/e;for(let m of r.storedViews){let y=m.views;if(Array.isArray(y))for(let p=0;p<y.length;p++){let d=y[p];!d||d.detachedNode||(d.backwardState&&(d.backwardState.transform=Lt(d.backwardState.transform,o,i),d.backwardState.origin!=null&&(d.backwardState.origin=zt(d.backwardState.origin,o,i))),d.forwardState&&(d.forwardState.transform=Lt(d.forwardState.transform,o,i),d.forwardState.origin!=null&&(d.forwardState.origin=zt(d.forwardState.origin,o,i))))}}let a=r.canvas,l=a.querySelector(".is-current-view"),c=a.querySelector(".is-previous-view"),f=a.querySelector(".is-last-view"),u=a.querySelector(".is-new-current-view"),h=[l,c,f,u].filter(Boolean);for(let m of h){if(!m.style)continue;let y=m.style.transform;y!=null&&y!==""&&(m.style.transform=Lt(y,o,i));let p=m.style.transformOrigin;p!=null&&p!==""&&(m.style.transformOrigin=zt(p,o,i))}}var Ke=8e3,tt=class{constructor(t){if(this.storedViews=[],this.currentStage=null,this.debug=!1,this.trace=[],this.blockEvents=!1,this._blockEventsSafetyTimer=null,this.touchstartX=0,this.touchstartY=0,this.touchendX=0,this.touchendY=0,this.touching=!1,this.lateralHistory=[],this._lastCanvasWidth=0,this._lastCanvasHeight=0,this._pendingResizeCorrection=!1,this._destroyed=!1,this._trackedTimers=new Set,this._pendingTransitionComplete=null,this._hooks={},this._plugins=[],Ht(t,this),!this.isValid){this.notify("is unable to start: invalid or missing required options (mount, initialView, views).","error");return}if(this.canvas=document.querySelector(this.mount),!this.canvas){this.notify(`mount selector "${this.mount}" did not match any element.`,"error"),this.isValid=!1;return}this.transitionDriver=pe(this.transitionDriver),this._onZoom=this.onZoom.bind(this),this._onTouchStart=this.onTouchStart.bind(this),this._onTouchEnd=this.onTouchEnd.bind(this),this._onTouchCancel=()=>{this.touching=!1},this._onKeyUp=this.onKeyUp.bind(this),this._onWheel=this.onWheel.bind(this),this._wheelCooldown=!1,this._onPrefetchTrigger=e=>{e.target.classList.contains("zoom-me")&&e.target.dataset.to&&this.prefetcher.prefetch(e.target.dataset.to,{trigger:e.target,...e.target.dataset})},this._onResize=this._handleResize.bind(this),this._resizeDebounceTimer=null,this._RESIZE_DEBOUNCE_MS=80,this.prefetcher=new mt(this.views),this._bindEvents()}_bindEvents(){let t=this.canvas;t&&(t.setAttribute("tabindex","0"),t.setAttribute("role","application"),t.setAttribute("aria-roledescription","zoomable interface"),t.setAttribute("aria-live","polite"),t.addEventListener("mouseup",this._onZoom,!1),t.addEventListener("touchend",this._onZoom,!1),t.addEventListener("touchstart",this._onTouchStart,{passive:!0}),t.addEventListener("touchend",this._onTouchEnd,!1),t.addEventListener("touchcancel",this._onTouchCancel,{passive:!0}),t.addEventListener("keyup",this._onKeyUp,!1),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("mouseover",this._onPrefetchTrigger,{passive:!0}),t.addEventListener("focusin",this._onPrefetchTrigger,{passive:!0}),window.addEventListener("resize",this._onResize,{passive:!0}),typeof ResizeObserver<"u"&&(this._resizeObserver=new ResizeObserver(()=>this._handleResize()),this._resizeObserver.observe(t)))}_unbindEvents(){let t=this.canvas;t&&(t.removeEventListener("mouseup",this._onZoom,!1),t.removeEventListener("touchend",this._onZoom,!1),t.removeEventListener("touchstart",this._onTouchStart),t.removeEventListener("touchend",this._onTouchEnd,!1),t.removeEventListener("touchcancel",this._onTouchCancel),t.removeEventListener("keyup",this._onKeyUp,!1),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("mouseover",this._onPrefetchTrigger),t.removeEventListener("focusin",this._onPrefetchTrigger)),window.removeEventListener("resize",this._onResize),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null)}_resetCanvasScroll(t){if(t&&((t.scrollLeft!==0||t.scrollTop!==0)&&(this.notify(`canvas had a residual scroll (${t.scrollLeft}, ${t.scrollTop}) \u2014 resetting. Something scrolled the canvas mid-transition.`,"warn"),t.scrollLeft=0,t.scrollTop=0),!this._warnedScrolledAncestor)){for(let e=t.parentElement;e&&e!==document.body;e=e.parentElement)if(e.scrollLeft!==0||e.scrollTop!==0){let s=e.className?`.${String(e.className).trim().split(/\s+/).join(".")}`:e.tagName.toLowerCase();this.notify(`an ancestor of the canvas (${s}) is scrolled (${e.scrollLeft}, ${e.scrollTop}): all zooms will land displaced. Use 'overflow: clip' (not 'hidden') on containers around the canvas.`,"warn"),this._warnedScrolledAncestor=!0;break}}}_setBlockEvents(){this.blockEvents=!0,this._clearBlockEventsSafety(),this._blockEventsSafetyTimer=setTimeout(()=>{if(this.blockEvents&&!this._destroyed){this.notify("blockEvents safety timeout: driver did not call onComplete. Force-resetting.","warn"),this.blockEvents=!1;let t=this._pendingTransitionComplete;t?t():this._onTransitionComplete()}},Ke)}_clearBlockEventsSafety(){this._blockEventsSafetyTimer!==null&&(clearTimeout(this._blockEventsSafetyTimer),this._blockEventsSafetyTimer=null)}_setTrackedTimeout(t,e){let s=setTimeout(()=>{this._trackedTimers.delete(s),!this._destroyed&&t()},e);return this._trackedTimers.add(s),s}_clearTrackedTimeouts(){for(let t of this._trackedTimers)clearTimeout(t);this._trackedTimers.clear()}storeViews(t){this.tracing("storedViews()"),this.storedViews.push(t),this.debug&&console.debug("Zumly storedViews",t)}tracing(t){if(this.debug)if(t==="ended"){let e=this.trace.map((s,n)=>`${n===0?`Instance ${this.mount}: ${s}`:`${s}`}`).join(" > ");this.notify(e),this.trace=[]}else this.trace.push(t)}notify(t,e){return L(this.debug,t,e)}_recordCanvasSize(){if(!this.canvas)return;let t=this.canvas.getBoundingClientRect();this._lastCanvasWidth=t.width,this._lastCanvasHeight=t.height}_handleResize(){this._destroyed||(this._resizeDebounceTimer&&clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=setTimeout(()=>{if(this._resizeDebounceTimer=null,!this.isValid||!this.canvas||this._lastCanvasWidth===0)return;let t=this.canvas.getBoundingClientRect(),e=t.width,s=t.height;if(!(e===this._lastCanvasWidth&&s===this._lastCanvasHeight)){if(this.blockEvents){this._pendingResizeCorrection=!0;return}kt(this,this._lastCanvasWidth,this._lastCanvasHeight,e,s),this._lastCanvasWidth=e,this._lastCanvasHeight=s}},this._RESIZE_DEBOUNCE_MS))}_onTransitionComplete(){if(this._clearBlockEventsSafety(),this._pendingResizeCorrection&&!this.blockEvents){this._pendingResizeCorrection=!1;let t=this.canvas?.getBoundingClientRect();if(t&&this._lastCanvasWidth>0){let e=t.width,s=t.height;(e!==this._lastCanvasWidth||s!==this._lastCanvasHeight)&&kt(this,this._lastCanvasWidth,this._lastCanvasHeight,e,s),this._lastCanvasWidth=e,this._lastCanvasHeight=s}}else this._recordCanvasSize();this._manageFocus()}_manageFocus(){if(!this.canvas)return;let t=this.canvas.querySelector(".is-current-view");if(!t)return;let e=t.querySelector('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');e?e.focus({preventScroll:!0}):(t.setAttribute("tabindex","-1"),t.focus({preventScroll:!0}))}_resolveEffects(t){let e=t?.dataset?.withEffects;if(e&&typeof e=="string"){let s=e.split("|").map(n=>n.trim());return[s[0]||"none",s[1]||s[0]||"none"]}return this.effects}_applyEffects(t,e,s,n,o){!s||s[0]==="none"&&s[1]==="none"||(t&&s[0]!=="none"&&(t.style.setProperty("--z-effect-filter",s[0]),t.style.setProperty("--zoom-duration",n),t.style.setProperty("--zoom-ease",o),t.classList.add("has-effect")),e&&s[1]!=="none"&&(e.style.setProperty("--z-effect-filter",s[1]),e.style.setProperty("--zoom-duration",n),e.style.setProperty("--zoom-ease",o),e.classList.add("has-effect")))}_removeEffect(t){if(!t||!t.classList.contains("has-effect"))return;t.classList.remove("has-effect"),t.classList.add("has-effect-reverse");let e=()=>{t.classList.remove("has-effect-reverse"),t.style.removeProperty("--z-effect-filter"),t.removeEventListener("transitionend",e)};t.addEventListener("transitionend",e,{once:!0});let s=t.style.getPropertyValue("--zoom-duration");this._setTrackedTimeout(e,s?parseFloat(s)*(s.includes("ms")?1:1e3)+100:1100)}_resolveHideTrigger(t){return t?.dataset?.hideTrigger!==void 0?t.dataset.hideTrigger==="fade"?"fade":!0:this.hideTrigger}_applyHideTrigger(t,e,s,n,o){!s||!t||(s==="fade"?(t.style.setProperty("--zoom-duration",n),t.style.setProperty("--zoom-ease",o),t.classList.add("z-trigger-fade"),e.style.setProperty("--zoom-duration",n),e.style.setProperty("--zoom-ease",o),e.classList.add("z-view-fade-in"),e.offsetHeight,e.classList.remove("hide")):t.classList.add("z-trigger-hidden"))}_restoreHideTrigger(t,e,s,n){if(!(!e||!t))if(e==="fade"){t.classList.remove("z-trigger-fade"),t.style.setProperty("--zoom-duration",s),t.style.setProperty("--zoom-ease",n),t.classList.add("z-trigger-fade-reverse");let o=()=>{t.classList.remove("z-trigger-fade-reverse"),t.style.removeProperty("--zoom-duration"),t.style.removeProperty("--zoom-ease"),t.removeEventListener("transitionend",o)};t.addEventListener("transitionend",o,{once:!0}),this._setTrackedTimeout(o,parseFloat(s)*(s.includes("ms")?1:1e3)+100)}else t.classList.remove("z-trigger-hidden")}on(t,e){return typeof e!="function"?this:((this._hooks[t]||=[]).push(e),this)}use(t,e){if(!t)return this;let s={plugin:t,options:e};return this._plugins.push(s),this._initialized&&this._installPlugin(s),this}_installPlugin(t){let{plugin:e,options:s}=t;try{typeof e=="function"?e(this,s):typeof e.install=="function"&&e.install(this,s)}catch(n){this.notify(`plugin install error: ${n.message}`,"error")}}off(t,e){return e?this._hooks[t]&&(this._hooks[t]=this._hooks[t].filter(s=>s!==e)):delete this._hooks[t],this}_emit(t,e={}){let s=this._hooks[t];if(!(!s||s.length===0))for(let n of s)try{n(e)}catch(o){this.debug&&console.error(`Zumly hook "${t}" threw:`,o)}}zoomLevel(){return this.storedViews.length}getZoomLevel(){return this.zoomLevel()}getCurrentViewName(){return!this.storedViews||this.storedViews.length===0?null:this.storedViews[this.storedViews.length-1]?.views?.[0]?.viewName??null}back(){if(!this._destroyed){if(this.blockEvents){this.notify("back ignored: a transition is already running.","warn");return}if(this.lateralHistory&&this.lateralHistory.length>0){let t=this.lateralHistory.pop(),e=t&&typeof t=="object"?t.name:t,s=t&&typeof t=="object"?t.entry:void 0,n=t&&typeof t=="object"?t.node:void 0;return this._doLateral(e,!0,{savedEntry:s,keepAliveNode:n})}this.zoomOut()}}async goTo(t,e={}){return this._destroyed?void 0:(e.mode==="lateral"?"lateral":"depth")==="depth"?this.zoomTo(t,e):this._doLateral(t,!1,e)}async zoomTo(t,e={}){if(this._destroyed)return;if(!this.isValid||!this.canvas){this.notify("zoomTo() cannot run: instance is invalid or canvas not found.","error");return}if(typeof t!="string"||!t){this.notify("zoomTo() requires a non-empty view name.","warn");return}if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`zoomTo("${t}"): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}if(this.getCurrentViewName()===t)return;let n=this.canvas.getBoundingClientRect(),o=Math.max(40,n.width*.1),i=Math.max(40,n.height*.1),l={rect:{x:n.left+(n.width-o)/2,y:n.top+(n.height-i)/2,width:o,height:i},duration:e.duration??this.duration,ease:e.ease??this.ease,props:e.props??{}};await this._doZoomIn(t,l)}async init(){if(this._destroyed)return;if(!this.isValid||!this.canvas){this.notify("init() cannot run: instance is invalid or canvas element was not found.","error");return}this.tracing("init()"),this.preload&&this.preload.length&&await this.prefetcher.preloadEager(this.preload,null).catch(e=>{this.notify(`preload failed: ${e.message}`,"warn")});let t;try{let e=await this.prefetcher.get(this.initialView,null);t=await st(e,this.initialView,this.canvas,!0,this.views,this.componentContext)}catch(e){this.notify(`init() failed to resolve initial view "${this.initialView}": ${e.message}`,"error");return}this._emit("viewMounted",{viewName:this.initialView,node:t}),this.prefetcher.scanAndPrefetch(t,null),this.storeViews({zoomLevel:this.storedViews.length,scale:1,views:[{viewName:this.initialView,backwardState:{origin:"0 0",transform:""}}]}),this.currentStage=this.storedViews[this.storedViews.length-1],this._recordCanvasSize(),this._initialized=!0;for(let e of this._plugins)this._installPlugin(e)}destroy(){this._destroyed||(this._emit("destroy"),this._destroyed=!0,this._clearBlockEventsSafety(),this._clearTrackedTimeouts(),this._pendingTransitionComplete=null,this._resizeDebounceTimer&&(clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=null),this._unbindEvents(),this._removeNav(),this._cleanupLateralKeepAlive(),this.blockEvents=!1,this.storedViews=[],this.currentStage=null,this.lateralHistory=[],this.trace=[],this._hooks={},this.prefetcher=null,this.transitionDriver=null,this.canvas&&(this.canvas.removeAttribute("tabindex"),this.canvas.removeAttribute("role"),this.canvas.removeAttribute("aria-roledescription"),this.canvas.removeAttribute("aria-live")),this.isValid=!1)}async _doZoomIn(t,e){if(this._destroyed)return;if(this.blockEvents){this.notify("zoomIn ignored: a transition is already running.","warn");return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],this._emit("beforeZoomIn",{viewName:t}),this.tracing("zoomIn()");let s=this.canvas,n=e.el;this._resetCanvasScroll(s);let o=s.getBoundingClientRect(),i=o.left,a=o.top,c=(this.storedViews.length>0?this.storedViews[this.storedViews.length-1]:null)?.scale??1;this.tracing("getView()");let f=n?{trigger:n,target:document.createElement("div"),context:this.componentContext,props:Object.assign({},n.dataset)}:{target:document.createElement("div"),context:this.componentContext,props:e.props??{}},u=n?.dataset?.deferred!==void 0?!0:this.deferred,h,m=null;try{if(u){let E=await this.prefetcher.get(t,f);if(this._destroyed)return;for(m=document.createDocumentFragment();E.firstChild;)m.appendChild(E.firstChild);h=await st(E,t,s,!1,{},this.componentContext)}else{let E=await this.prefetcher.get(t,f);if(this._destroyed)return;this.prefetcher.scanAndPrefetch(E,f),h=await st(E,t,s,!1,this.views,this.componentContext)}}catch(E){this.notify(`zoomIn aborted: failed to resolve view "${t}": ${E.message}`,"error");return}if(!h)return;u||this._emit("viewMounted",{viewName:t,node:h}),n&&n.classList.add("zoomed");let y=n?(()=>{let E=n.getBoundingClientRect();return{x:E.x,y:E.y,width:E.width,height:E.height}})():e.rect,p=n?n.dataset.withDuration||this.duration:e.duration??this.duration,d=n?n.dataset.withEase||this.ease:e.ease??this.ease,g=n?n.dataset.withCover||this.cover:e.cover??this.cover,v=n?parseInt(n.dataset.withStagger,10)||this.stagger:e.stagger??this.stagger,w=s.querySelector(".is-current-view"),b=s.querySelector(".is-previous-view"),_=s.querySelector(".is-last-view");if(!w){this.notify("zoomIn aborted: no current view found in canvas. Call init() before navigating and keep Zumly view classes intact.","error"),n&&n.classList.remove("zoomed");try{s.removeChild(h)}catch{}return}K(h),K(w),K(b),_&&(K(_),s.removeChild(_));let S,O,P,I,x,q,B,et=w.style.transform,k=w.style.transformOrigin,D=b?b.style.transform:null,A=b?b.style.transformOrigin:null;try{w.classList.replace("is-current-view","is-previous-view"),b&&b.classList.replace("is-previous-view","is-last-view");let E=h.getBoundingClientRect(),V=w.getBoundingClientRect(),bt=null,At=null,lt=null;b&&(bt=b.getBoundingClientRect(),lt=b.querySelector(".zoomed"),At=lt&<.getBoundingClientRect?lt.getBoundingClientRect():bt);let ct={left:i,top:a},Pt={width:o.width,height:o.height},It={width:E.width,height:E.height},Nt=jt(y.width,y.height,E.width,E.height,g);B=Nt.scale;let Se=Nt.scaleInv;S=Rt(y,ct,It,Se),P=w.style.transform;let $t=Bt(y,V);I=Vt(Pt,y,V,B,this.parallax);let Zt=ut(k||"0 0"),U=nt(P||""),Mt=ut($t),W=nt(I.transform),Dt=y;if(n&&(Dt=ht(y,V,Zt,U.tx,U.ty,U.scale,Mt,W.tx,W.ty,W.scale)),O=qt(Dt,ct,It),b){x=b.style.transform;let Te=ht(V,V,Zt,U.tx,U.ty,U.scale,Mt,W.tx,W.ty,W.scale),Ee=Yt(I.x,I.y,ct,B,c),Ft=ut(A||"0 0"),_t=nt(x||""),St=nt(Ee),xe=ht(At,bt,Ft,_t.tx,_t.ty,_t.scale,Ft,St.tx,St.ty,St.scale);q=Xt({canvasRect:Pt,canvasOffset:ct,triggerRect:y,previousViewRectAtBaseTransform:V,lastViewZoomedElementRect:xe,previousViewRectWithPreviousAtEndTransform:Te,scale:B,preScale:c,parallax:this.parallax})}h.style.transform=S,w.style.transformOrigin=$t}catch(E){this.notify(`zoomIn geometry computation failed: ${E.message}. Aborting zoom.`,"error"),this.debug&&console.error("Zumly _doZoomIn error:",E),w.style.transform=et,w.style.transformOrigin=k,w.classList.contains("is-previous-view")&&w.classList.replace("is-previous-view","is-current-view"),b&&(b.style.transform=D,b.style.transformOrigin=A,b.classList.contains("is-last-view")&&b.classList.replace("is-last-view","is-previous-view"));try{s.removeChild(h)}catch{}n&&n.classList.remove("zoomed"),X(w),X(b);return}let Y=ot(h.dataset.viewName,{origin:h.style.transformOrigin,duration:p,ease:d,transform:S},{origin:h.style.transformOrigin,duration:p,ease:d,transform:O}),ye=ot(w.dataset.viewName,{origin:w.style.transformOrigin,duration:p,ease:d,transform:P},{origin:w.style.transformOrigin,duration:p,ease:d,transform:I.transform}),we=b?ot(b.dataset.viewName,{origin:b.style.transformOrigin,duration:p,ease:d,transform:x},{origin:b.style.transformOrigin,duration:p,ease:d,transform:q}):null,ge=_?Ut(_):null,at=Wt(this.storedViews.length,Y,ye,we,ge);at.scale=B,at.stagger=v||0,this.storeViews(at),this.currentStage=this.storedViews[this.storedViews.length-1],this.tracing("setCSSVariables()");let be=this._resolveEffects(n);this._applyEffects(w,b,be,p,d);let wt=this._resolveHideTrigger(n);this._applyHideTrigger(n,h,wt,p,d),wt&&(at.hideTriggerMode=wt),this._setBlockEvents();let _e={type:"zoomIn",currentView:h,previousView:w,lastView:b,currentStage:this.currentStage,duration:p,ease:d},gt=async()=>{this._pendingTransitionComplete===gt&&(this._pendingTransitionComplete=null,!this._destroyed&&(u&&m&&h&&(h.appendChild(m),this.prefetcher.scanAndPrefetch(h,f),typeof this.views[t]=="object"&&typeof this.views[t].mounted=="function"&&await this.views[t].mounted(),this._emit("viewMounted",{viewName:t,node:h})),this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterZoomIn",{viewName:t,zoomLevel:this.zoomLevel()}),this.tracing("ended")))};this._pendingTransitionComplete=gt,this.transitionDriver.runTransition(_e,gt)}async zoomIn(t){this._destroyed||t?.dataset?.to&&await this._doZoomIn(t.dataset.to,{el:t})}async _doLateral(t,e=!1,s={}){if(this._destroyed)return;if(this.blockEvents){this.notify("lateral navigation ignored: a transition is already running.","warn");return}if(!this.isValid||!this.canvas)return;if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`goTo("${t}", { mode: 'lateral' }): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}let n=this.canvas.querySelector(".is-current-view");if(!n)return;let o=n.dataset?.viewName;if(o===t)return;this._emit("beforeLateral",{viewName:t,from:o,isBack:e});let i=this.lateralNav&&this.lateralNav.keepAlive,a=null;if(!e){this.lateralHistory=this.lateralHistory||[];let k=this.storedViews[this.storedViews.length-1];a={name:o,entry:k.views[0],node:i?n:null}}this.tracing("lateral()");let l=s.duration??this.duration,c=s.ease??this.ease,f=this.canvas.querySelector(".is-previous-view"),u=this.canvas.querySelector(".is-last-view"),h=0,m=0,y=this._declaredSiblings(),p=y?y.indexOf(o):-1,d=y?y.indexOf(t):-1;if(p!==-1&&d!==-1){let k=this.canvas.getBoundingClientRect();h=(p-d)*k.width*.15}else if(f){let k=f.querySelector(`.zoom-me[data-to="${o}"]`),D=f.querySelector(`.zoom-me[data-to="${t}"]`);if(k&&D){let A=k.getBoundingClientRect(),Y=D.getBoundingClientRect();h=A.left+A.width/2-(Y.left+Y.width/2),m=A.top+A.height/2-(Y.top+Y.height/2)}else h=this.canvas.getBoundingClientRect().width*.15}let g=null,v=null;if(i&&(e&&s.keepAliveNode?v=s.keepAliveNode:v=this.canvas.querySelector(`.is-lateral-hidden[data-view-name="${t}"]`)),v){if(v.style.display="",v.style.opacity="",v.classList.remove("is-lateral-hidden","zoom-lateral-out"),v.classList.add("is-new-current-view","has-no-events"),g=v,!e&&this.lateralHistory){let k=this.lateralHistory.findIndex(D=>D.node===v);k!==-1&&this.lateralHistory.splice(k,1)}}else{let k=()=>{e&&this.lateralHistory.push({name:t,entry:s.savedEntry,node:s.keepAliveNode??null})},D={target:document.createElement("div"),context:this.componentContext,props:s.props??{}};try{let A=await this.prefetcher.get(t,D);if(this._destroyed)return;this.prefetcher.scanAndPrefetch(A,D),g=await st(A,t,this.canvas,!1,this.views,this.componentContext)}catch(A){this.notify(`lateral navigation aborted: failed to resolve view "${t}": ${A.message}`,"error"),k();return}if(!g){k();return}this._emit("viewMounted",{viewName:t,node:g})}a&&this.lateralHistory.push(a),K(g);let w=n.style.transform||"",b=n.style.transformOrigin||"0 0";g.style.transform=w,g.style.transformOrigin=b;let _=this.storedViews[this.storedViews.length-1],S=e&&s.savedEntry?{...s.savedEntry,viewName:t}:ot(t,{origin:b,duration:l,ease:c,transform:w},{origin:b,duration:l,ease:c,transform:w});_.views[0]=S,this.currentStage=_;let O=f?{transformStart:f.style.transform||"",transformEnd:this._computeLateralBackTransform(f.style.transform||"",h,m)}:null,P=u&&_.views[2]?{transformStart:u.style.transform||"",transformEnd:this._computeLateralBackTransform(u.style.transform||"",h*.7,m*.7)}:null;O&&_.views[1]&&(_.views[1].forwardState={..._.views[1].forwardState,transform:O.transformEnd}),P&&_.views[2]&&(_.views[2].forwardState={..._.views[2].forwardState,transform:P.transformEnd});let I=w,x=this._computeLateralBackTransform(I,-h,-m),q=this._computeLateralBackTransform(w,h,m);this._setBlockEvents();let B={type:"lateral",currentView:g,previousView:n,lastView:u||null,backView:f||null,backViewState:O,lastViewState:P,incomingTransformStart:x,incomingTransformEnd:I,outgoingTransform:w,outgoingTransformEnd:q,currentStage:this.currentStage,duration:l,ease:c,canvas:this.canvas,slideDeltaX:h,slideDeltaY:m,keepAlive:i&&!e?i:!1},et=()=>{this._pendingTransitionComplete===et&&(this._pendingTransitionComplete=null,!this._destroyed&&(i&&!e&&(n.classList.remove("is-current-view","is-new-current-view","has-no-events"),n.classList.add("is-lateral-hidden"),i!=="visible"?n.style.display="none":(n.style.transform=w,n.style.opacity="")),this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterLateral",{viewName:t,from:o,isBack:e}),this.tracing("ended")))};this._pendingTransitionComplete=et,this.transitionDriver.runTransition(B,et)}_computeLateralBackTransform(t,e,s){let n=rt(t);return n.matched?`translate(${n.tx+e}px, ${n.ty+s}px) ${n.rest}`.trim():`translate(${e}px, ${s}px) ${t}`.trim()}zoomOut(){if(this._destroyed)return;if(this.blockEvents){this.notify("zoomOut ignored: a transition is already running.","warn");return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],this._emit("beforeZoomOut",{zoomLevel:this.zoomLevel()}),this.tracing("zoomOut()");let t=this.canvas;this._resetCanvasScroll(t);let e=t.querySelector(".is-current-view"),s=t.querySelector(".is-previous-view");if(!e||!s){this.notify("zoomOut: current or previous view not found (animation may still be running)","warn");return}this._setBlockEvents(),this.currentStage=this.storedViews[this.storedViews.length-1];let n=t.querySelector(".is-last-view");this.tracing("setCSSVariables()");let o=this.currentStage.views[0]?.forwardState?.duration??this.duration,i=this.currentStage.views[0]?.forwardState?.ease??this.ease,a=s.querySelector(".zoomed");a&&a.classList.remove("zoomed");let l=this.currentStage.hideTriggerMode;l&&a&&this._restoreHideTrigger(a,l,o,i),l==="fade"?(e.classList.remove("z-view-fade-in"),e.style.setProperty("--zoom-duration",o),e.style.setProperty("--zoom-ease",i),e.classList.add("z-view-fade-out")):(e.classList.remove("z-view-fade-in"),e.style.removeProperty("opacity")),this._removeEffect(s),s.classList.replace("is-previous-view","is-current-view"),n!==null&&(n.classList.contains("has-effect")&&this.effects[0]!=="none"&&n.style.setProperty("--z-effect-filter",this.effects[0]),n.classList.replace("is-last-view","is-previous-view"),n.classList.remove("hide"),X(n));let c=Kt(this.currentStage);if(c){t.prepend(c);let h=t.querySelector(".z-view:first-child");h&&(X(h),h.classList.add("hide"))}let f={type:"zoomOut",currentView:e,previousView:s,lastView:n,currentStage:this.currentStage,duration:o,ease:i,canvas:t},u=()=>{this._pendingTransitionComplete===u&&(this._pendingTransitionComplete=null,!this._destroyed&&(this.blockEvents=!1,this._onTransitionComplete(),this.storedViews.pop(),this._updateNav(),this._emit("afterZoomOut",{zoomLevel:this.zoomLevel()}),this.tracing("ended")))};this._pendingTransitionComplete=u,this.transitionDriver.runTransition(f,u)}onZoom(t){if(this._destroyed||t.type==="mouseup"&&!this.inputs.click||t.type==="touchend"&&!this.inputs.touch)return;let e=t.target;if(e.closest(".z-depth-nav")||e.closest(".z-lateral-nav"))return;let s=e.classList.contains("zoom-me")||e.closest(".zoom-me");if(!this.blockEvents&&s&&!this.touching){this.tracing("onZoom() \u2192 zoomIn"),t.stopPropagation();let n=e.classList.contains("zoom-me")?e:e.closest(".zoom-me");this.zoomIn(n);return}if(this.storedViews.length>1&&!this.blockEvents&&!s&&!this.touching){let n=this.canvas.querySelector(".is-current-view");if(n&&n.contains(e))return;let o=this._findSiblingTriggerAtPoint(t.clientX,t.clientY);if(o){this.tracing("onZoom() \u2192 lateral"),t.stopPropagation(),this._doLateral(o.dataset.to);return}this.tracing("onZoom() \u2192 zoomOut"),t.stopPropagation(),this.zoomOut()}}_findSiblingTriggerAtPoint(t,e){let s=this.canvas.querySelector(".is-previous-view");if(!s)return null;let o=this.canvas.querySelector(".is-current-view")?.dataset?.viewName;if(!o)return null;let i=s.querySelectorAll(".zoom-me[data-to]");for(let a of i){if(a.dataset.to===o)continue;let l=a.getBoundingClientRect();if(t>=l.left&&t<=l.right&&e>=l.top&&e<=l.bottom)return a}return null}_getSiblings(){let e=this.canvas.querySelector(".is-current-view")?.dataset?.viewName,s=this._declaredSiblings();if(s&&s.indexOf(e)!==-1)return{siblings:s,currentIndex:s.indexOf(e)};let n=this.canvas.querySelector(".is-previous-view");if(!n)return{siblings:[],currentIndex:-1};let o=n.querySelectorAll(".zoom-me[data-to]"),i=[];for(let l of o)l.dataset.to&&i.push(l.dataset.to);let a=i.indexOf(e);return{siblings:i,currentIndex:a}}_declaredSiblings(){let t=this.lateralNav&&typeof this.lateralNav=="object"?this.lateralNav.siblings:null;if(!t)return null;if(Array.isArray(t))return t;let e=this.canvas.querySelector(".is-previous-view")?.dataset?.viewName;return e&&Array.isArray(t[e])?t[e]:null}_updateNav(){this._destroyed||(this._removeNav(),this._updateDepthNav(),this._updateLateralNav())}_updateDepthNav(){if(!this.depthNav||this.storedViews.length-1<1)return;let e=this.canvas.querySelector(".z-view.is-current-view");if(e&&e.querySelector(".z-depth-nav"))return;let s=this.depthNav.position||"bottom-left",n=document.createElement("div");n.className="z-depth-nav z-depth-nav--"+s;let o=document.createElement("button");o.className="z-nav-back",o.setAttribute("aria-label","Zoom out (go back)"),o.innerHTML="‹",o.addEventListener("mouseup",i=>{i.stopPropagation(),!this.blockEvents&&this.storedViews.length>1&&this.zoomOut()}),n.appendChild(o),this.canvas.appendChild(n)}_updateLateralNav(){if(!this.lateralNav)return;let t=this.storedViews.length-1,e=this._getSiblings();if(e.siblings.length<2)return;if(this.lateralNav.mode==="auto"&&t>=1){let a=this.canvas.querySelector(".z-view.is-current-view");if(a&&a.offsetWidth>=this.canvas.offsetWidth&&a.offsetHeight>=this.canvas.offsetHeight)return}let{siblings:s,currentIndex:n}=e,o=this.lateralNav.position||"bottom-center",i=document.createElement("div");if(i.className="z-lateral-nav z-lateral-nav--"+o,this.lateralNav.arrows){let a=document.createElement("button");a.className="z-nav-arrow z-nav-prev",a.setAttribute("aria-label","Previous sibling view"),a.innerHTML="‹",a.disabled=n<=0,a.addEventListener("mouseup",l=>{l.stopPropagation(),n>0&&this._doLateral(s[n-1])}),i.appendChild(a)}if(this.lateralNav.dots){let a=document.createElement("div");a.className="z-nav-lateral-dots";for(let l=0;l<s.length;l++){let c=document.createElement("button");c.className="z-nav-dot z-nav-lat-dot"+(l===n?" is-active":""),c.setAttribute("aria-label",`Go to ${s[l]}`),c.dataset.to=s[l],c.addEventListener("mouseup",(f=>u=>{u.stopPropagation(),f!==n&&this._doLateral(s[f])})(l)),a.appendChild(c)}i.appendChild(a)}if(this.lateralNav.arrows){let a=document.createElement("button");a.className="z-nav-arrow z-nav-next",a.setAttribute("aria-label","Next sibling view"),a.innerHTML="›",a.disabled=n>=s.length-1,a.addEventListener("mouseup",l=>{l.stopPropagation(),n<s.length-1&&this._doLateral(s[n+1])}),i.appendChild(a)}this.canvas.appendChild(i)}_removeNav(){this.canvas&&this.canvas.querySelectorAll(".z-depth-nav, .z-lateral-nav").forEach(t=>t.remove())}_cleanupLateralKeepAlive(){if(!this.canvas)return;let t=this.canvas.querySelectorAll(".is-lateral-hidden");for(let e of t)e.remove()}onKeyUp(t){this._destroyed||this.inputs.keyboard&&(this.tracing("onKeyUp()"),(t.key==="ArrowLeft"||t.key==="ArrowDown")&&(t.preventDefault(),this.storedViews.length>1&&!this.blockEvents?this.zoomOut():this.notify(`is on level zero. Can't zoom out. Trigger: ${t.key}`,"warn")),(t.key==="ArrowRight"||t.key==="ArrowUp")&&(t.preventDefault(),this.notify(t.key+" has no actions defined")))}onWheel(t){this._destroyed||this.inputs.wheel&&(this._isInsideScrollable(t.target,t.deltaY)||(t.preventDefault(),!(this.blockEvents||this._wheelCooldown)&&t.deltaY>0&&this.storedViews.length>1&&(this.tracing("onWheel() \u2192 zoomOut"),this._wheelCooldown=!0,this._setTrackedTimeout(()=>{this._wheelCooldown=!1},500),this.zoomOut())))}_isInsideScrollable(t,e){let s=t,n=this.canvas.querySelector(".is-current-view");for(;s&&s!==this.canvas;){if(s===n||n&&n.contains(s)){let{overflowY:o}=window.getComputedStyle(s);if((o==="auto"||o==="scroll")&&(e>0?s.scrollTop+s.clientHeight<s.scrollHeight-1:s.scrollTop>0))return!0}s=s.parentElement}return!1}onTouchStart(t){this._destroyed||this.inputs.touch&&(this.tracing("onTouchStart()"),this.touching=!0,this.touchstartX=t.changedTouches[0].screenX,this.touchstartY=t.changedTouches[0].screenY)}onTouchEnd(t){this._destroyed||this.inputs.touch&&(this.blockEvents||(this.tracing("onTouchEnd()"),this.touchendX=t.changedTouches[0].screenX,this.touchendY=t.changedTouches[0].screenY,this.handleGesture(t)),this.touching=!1)}handleGesture(t){t.stopPropagation(),this.tracing("handleGesture()");let e=this.touchendX-this.touchstartX,s=this.touchendY-this.touchstartY,n=Math.abs(e)<10&&Math.abs(s)<10;e<-30&&(this.storedViews.length>1&&!this.blockEvents?(this.tracing("swipe left"),this.zoomOut()):this.notify("is on level zero. Can't zoom out. Trigger: Swipe left","warn"));let o=t.target.classList.contains("zoom-me")?t.target:t.target.closest(".zoom-me");n&&!this.blockEvents&&o&&this.touching&&(this.touching=!1,this.tracing("tap"),t.preventDefault(),this.zoomIn(o)),n&&this.storedViews.length>1&&!this.blockEvents&&!o&&t.target.closest(".is-current-view")===null&&this.touching&&(this.touching=!1,this.tracing("tap"),this.zoomOut())}};var Ge={separator:"/",prefix:"/"};function ve(r,t){let e=[];for(let s of r.storedViews){let n=s.views&&s.views[0];n&&n.viewName&&e.push(n.viewName)}return e.join(t)}function Qe(r,t){let e=window.location.hash.slice(1);return e.startsWith(r)&&(e=e.slice(r.length)),e?e.split(t).filter(Boolean):[]}var Ot={install(r,t){let e=Object.assign({},Ge,t),s=e.separator,n=e.prefix,o=!1;function i(f){if(o)return;let u=ve(r,s),h="#"+n+u;window.location.hash!==h&&(o=!0,window.history[f](null,"",h),o=!1)}function a(){i("pushState")}function l(){i("replaceState")}r.on("afterZoomIn",a),r.on("afterLateral",a),r.on("afterZoomOut",l);function c(){if(o)return;o=!0;let f=Qe(n,s),u=ve(r,s).split(s).filter(Boolean);if(f.join(s)===u.join(s)){o=!1;return}if(f.length<u.length){let h=u.length-f.length;for(let m=0;m<h;m++)r.zoomOut()}else if(f.length===u.length&&f.length>0){let h=f[f.length-1];h!==u[u.length-1]&&r.goTo(h,{mode:"lateral"})}else f.length>u.length&&window.history.back();o=!1}window.addEventListener("popstate",c),l(),r.on("destroy",function(){r.off("afterZoomIn",a),r.off("afterLateral",a),r.off("afterZoomOut",l),window.removeEventListener("popstate",c)})}};tt.Router=Ot;var Je=tt;
|
|
7
|
+
var Dt=Object.defineProperty;var je=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var qe=(r,t)=>{for(var e in t)Dt(r,e,{get:t[e],enumerable:!0})},We=(r,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Be(t))!Re.call(r,i)&&i!==e&&Dt(r,i,{get:()=>t[i],enumerable:!(s=je(t,i))||s.enumerable});return r};var Xe=r=>We(Dt({},"__esModule",{value:!0}),r);var ws={};qe(ws,{Zumly:()=>ft,ZumlyRouter:()=>Xt,default:()=>gs});module.exports=Xe(ws);var it=Symbol.for("zumly.viewLifecycles");function re(r){try{let t=r();t&&typeof t.then=="function"&&t.catch(e=>console.error("Zumly: view cleanup failed:",e))}catch(t){console.error("Zumly: view cleanup failed:",t)}}function ie(){let r=!1,t=[],e={onCleanup(s){if(typeof s!="function")throw new TypeError("Zumly: onCleanup expects a function");r?re(s):t.push(s)},attach(s){let i=s[it];i||(i=new Set,Object.defineProperty(s,it,{value:i,configurable:!0})),i.add(e)},dispose(){if(!r){r=!0;for(let s of t.splice(0).reverse())re(s)}}};return e}function C(r){if(!r)return;let t=[];r[it]&&t.push(r);let s=(r.ownerDocument||r).createTreeWalker(r,1),i;for(;i=s.nextNode();)i[it]&&t.push(i);for(let n=t.length-1;n>=0;n--){let o=t[n],a=o[it];if(a){for(let c of a)c.dispose();delete o[it]}}}var Ye=1e4,xt=class{#t={};constructor(t={}){this.#t=t}#e(t){return typeof t=="function"?"function":t instanceof HTMLElement?"element":typeof t=="object"&&t!==null&&typeof t.render=="function"?"object":typeof t!="string"?"unknown":/^https?:\/\/|^\/|\.(?:html|php)(?:[?#].*)?$/i.test(t)?"url":t.includes("<")?"html":t.includes("-")?"webcomponent":"unknown"}async resolve(t,e=null){let s=new Set;for(;typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.#t,t);){if(s.has(t))throw new Error(`Zumly: circular view alias "${t}"`);s.add(t),t=this.#t[t]}let i=this.#e(t);switch(i){case"html":{let n=document.createElement("div");n.innerHTML=t.trim();let o=n.firstElementChild;if(!o)throw new Error("Zumly: view produced no element (html)");return o}case"url":{let n=new AbortController,o=setTimeout(()=>n.abort(),Ye),a;try{let f=await fetch(t,{signal:n.signal});if(!f.ok)throw new Error(`Zumly: fetch failed for "${t}" (${f.status})`);a=await f.text()}finally{clearTimeout(o)}let c=document.createElement("div");c.innerHTML=a.trim();let l=c.firstElementChild;if(!l)throw new Error("Zumly: view produced no element (url)");return l}case"function":case"object":{let n=ie(),o=e?.target||document.createElement("div");n.attach(o);let a={...e,target:o,props:e?.props||{},context:e?.context||new Map,onCleanup:n.onCleanup};try{let c=await(i==="function"?t(a):t.render(a)),l;if(typeof c=="string")l=await this.resolve(c,a);else if(c instanceof HTMLElement)l=c;else if(i==="function")l=o,o.classList.length||(o.style.width||(o.style.width="100%"),o.style.height||(o.style.height="100%"));else throw new Error("Zumly: view render() must return a string or HTMLElement");return n.attach(l),l}catch(c){throw n.dispose(),c}}case"element":return t.cloneNode(!0);case"webcomponent":return await customElements.whenDefined(t),document.createElement(t);default:throw new Error("Zumly: unknown view type for source")}}};async function dt(r,t,e,s,i,n){if(!r||!r.classList){let o=document.createElement("div");o.classList.add("z-view"),r&&o.appendChild(r),r=o}else r.classList.contains("z-view")||r.classList.add("z-view");r.dataset.viewName=t,r.getAttribute("aria-label")||r.setAttribute("aria-label",`View: ${t}`),r.style.transformOrigin="0 0",r.style.position="absolute",s?r.classList.add("is-current-view"):r.classList.add("is-new-current-view","has-no-events","hide"),e.append(r);try{i[t]&&typeof i[t]=="object"&&typeof i[t].mounted=="function"&&await i[t].mounted()}catch(o){throw C(r),r.remove(),o}return r}function $(r,t,e){t&&e==="welcome"&&console.info(`%c Zumly %c ${t}`,"background: #424085; color: white; border-radius: 3px;","color: #424085"),t&&r&&(e==="info"||e===void 0)&&console.info(`%c Zumly %c ${t}`,"background: #6679A3; color: #304157; border-radius: 3px;","color: #6679A3"),t&&e==="warn"&&console.warn(`%c Zumly %c ${t}`,"background: #DCBF53; color: #424085; border-radius: 3px;","color: #424085"),t&&e==="error"&&console.error(`%c Zumly %c ${t}`,"background: #BE4747; color: white; border-radius: 3px;","color: #424085")}function ne(r,t){if(t.isValid=!1,!r||typeof r!="object"){$(!1,"'options' object has to be provided when instance is defined","error");return}if(typeof r.mount!="string"){$(!1,"'mount' must be a string selector","error");return}if(t.mount=r.mount,typeof r.initialView!="string"){$(!1,"'initialView' must be a string","error");return}if(t.initialView=r.initialView,!r.views||typeof r.views!="object"){$(!1,"'views' must be an object","error");return}t.views=r.views,t.isValid=!0,t.preload=Array.isArray(r.preload)?r.preload:[],t.debug=typeof r.debug=="boolean"?r.debug:!1,t.componentContext=r.componentContext&&typeof r.componentContext=="object"?r.componentContext:new Map;let e=r.transitions&&typeof r.transitions=="object"?r.transitions:null,s=e&&e.cover,i=typeof s=="string"?s.toLowerCase():null,n=i==="width"||i==="height";t.cover=n?i:"width",!n&&e&&s!==void 0&&$(!1,`'transitions.cover' must be either "width" or "height". Falling back to "width".`,"warn"),t.duration=e&&typeof e.duration=="string"?e.duration:"1s",t.ease=e&&typeof e.ease=="string"?e.ease:"ease-in-out",t.deferred=typeof r.deferred=="boolean"?r.deferred:!1;let o=e&&e.hideTrigger;o===!0||o==="fade"?t.hideTrigger=o:(t.hideTrigger=!1,o!=null&&o!==!1&&$(!1,`'transitions.hideTrigger' must be true or "fade". Falling back to false.`,"warn"));let a=e&&e.effects;Array.isArray(a)&&a.length>=2&&typeof a[0]=="string"&&typeof a[1]=="string"?t.effects=[a[0],a[1]]:Array.isArray(a)&&a.length===1&&typeof a[0]=="string"?t.effects=[a[0],a[0]]:(t.effects=["none","none"],a!=null&&$(!1,`'transitions.effects' must be an array of 1-2 CSS filter strings (e.g. ["blur(3px)", "blur(8px) saturate(0)"]). Falling back to no effects.`,"warn"));let c=e&&e.driver,l=typeof c=="string"?c.toLowerCase():null,f=typeof c=="function"?c:null;if(l!==null){let p=["css","waapi","none","anime","gsap","motion"];t.transitionDriver=p.includes(l)?l:"css",p.includes(l)||$(!1,`'transitions.driver' must be "css", "waapi", "none", "anime", "gsap", "motion", or a function. Got "${c}". Falling back to "css".`,"warn")}else f!==null?t.transitionDriver=f:t.transitionDriver="css";let h=e&&e.stagger;typeof h=="number"&&h>0?t.stagger=h:(t.stagger=0,h!=null&&h!==0&&$(!1,"'transitions.stagger' must be a positive number (ms). Falling back to 0 (disabled).","warn")),t.parallax=0;let u=r.lateralNav;if(u===!1)t.lateralNav=!1;else if(u&&typeof u=="object"){let p=typeof u.mode=="string"?u.mode.toLowerCase():null,y=p==="auto"||p==="always";p&&!y&&$(!1,`'lateralNav.mode' must be "auto" or "always". Falling back to "auto".`,"warn");let g=null;if(Array.isArray(u.siblings))g=u.siblings.filter(x=>typeof x=="string"&&x),g.length<2&&($(!1,"'lateralNav.siblings' needs at least 2 view names. Ignoring.","warn"),g=null);else if(u.siblings&&typeof u.siblings=="object"){g={};for(let[x,b]of Object.entries(u.siblings))if(Array.isArray(b)){let _=b.filter(S=>typeof S=="string"&&S);_.length>=2&&(g[x]=_)}Object.keys(g).length===0&&(g=null)}else u.siblings!==void 0&&$(!1,"'lateralNav.siblings' must be an array of view names or a { parentView: [...] } map. Ignoring.","warn");t.lateralNav={mode:y?p:"auto",arrows:typeof u.arrows=="boolean"?u.arrows:!0,dots:typeof u.dots=="boolean"?u.dots:!0,keepAlive:u.keepAlive===!0||u.keepAlive==="visible"?u.keepAlive:!1,siblings:g}}else t.lateralNav={mode:"auto",arrows:!0,dots:!0,keepAlive:!1,siblings:null};let d=r.depthNav;if(d===!1)t.depthNav=!1;else if(d&&typeof d=="object"){let p=typeof d.position=="string"?d.position.toLowerCase():null,y=p==="bottom-left"||p==="top-left";p&&!y&&$(!1,`'depthNav.position' must be "bottom-left" or "top-left". Falling back to "bottom-left".`,"warn"),t.depthNav={position:y?p:"bottom-left"}}else t.depthNav={position:"bottom-left"};let v=r.lateralNav&&typeof r.lateralNav=="object"?r.lateralNav.position:void 0;if(t.lateralNav&&typeof t.lateralNav=="object"){let p=v==="bottom-center"||v==="top-center";v&&!p&&$(!1,`'lateralNav.position' must be "bottom-center" or "top-center". Falling back to "bottom-center".`,"warn"),t.lateralNav.position=p?v:"bottom-center"}let m=r.inputs;m===!1?t.inputs={wheel:!1,keyboard:!1,click:!1,touch:!1}:m&&typeof m=="object"?t.inputs={wheel:typeof m.wheel=="boolean"?m.wheel:!0,keyboard:typeof m.keyboard=="boolean"?m.keyboard:!0,click:typeof m.click=="boolean"?m.click:!0,touch:typeof m.touch=="boolean"?m.touch:!0}:t.inputs={wheel:!0,keyboard:!0,click:!0,touch:!0}}function St(r,t,e,s,i){let n=e/r,o=s/t;return i==="height"?{scale:o,scaleInv:1/o}:{scale:n,scaleInv:1/n}}function Ft(r,t,e,s){let i=t.left,n=t.top,o=r.x-i+(r.width-e.width*s)/2,a=r.y-n+(r.height-e.height*s)/2;return`translate(${o}px, ${a}px) scale(${s})`}function oe(r,t,e){let s=t.left,i=t.top,n=r.x-s+(r.width-e.width)/2,o=r.y-i+(r.height-e.height)/2;return`translate(${n}px, ${o}px)`}function ae(r,t){let e=r.x+r.width/2-t.x,s=r.y+r.height/2-t.y;return`${e}px ${s}px`}function le(r,t,e,s,i=0){let n=r.width/2-t.width/2-t.x+e.x,o=r.height/2-t.height/2-t.y+e.y,a=1-i,c=n*a,l=o*a;return{x:n,y:o,transform:`translate(${c}px, ${l}px) scale(${s})`}}function ce({canvasRect:r,canvasOffset:t,triggerRect:e,previousViewRectAtBaseTransform:s,lastViewZoomedElementRect:i,previousViewRectWithPreviousAtEndTransform:n,scale:o,preScale:a,parallax:c=0}){let l=t.left,f=t.top,h=r.width/2-e.width/2-e.x,u=r.height/2-e.height/2-e.y,d=h+(s.x-i.x)+n.x-l+(n.width-i.width)/2,v=u+(s.y-i.y)+n.y-f+(n.height-i.height)/2,m=1-Math.min(c*2,.9);return`translate(${d*m}px, ${v*m}px) scale(${o*a})`}function fe(r,t,e,s,i){return`translate(${r-e.left}px, ${t-e.top}px) scale(${s*i})`}function nt(r){let t=r.split(/\s+/);return{x:parseFloat(t[0])||0,y:parseFloat(t[1])||0}}function et(r){let t=typeof r=="string"?r:"",e=t.match(/translate\s*\(\s*([-+\d.eE]+)px\s*,\s*([-+\d.eE]+)px\s*\)/);if(!e)return{tx:0,ty:0,rest:t.trim(),matched:!1};let s=t.replace(/translate\s*\([^)]+\)\s*/,"").trim();return{tx:parseFloat(e[1]),ty:parseFloat(e[2]),rest:s,matched:!0}}function Y(r){let t=et(r),e=r.match(/scale\s*\(\s*([-+\d.eE]+)\s*\)/);return{tx:t.matched?t.tx:0,ty:t.matched?t.ty:0,scale:e?parseFloat(e[1]):1}}function mt(r,t,e,s,i,n,o,a,c,l){let f=t.x-e.x*(1-n)-s,h=t.y-e.y*(1-n)-i,u=t.width/n,d=t.height/n,v=f+e.x+(r.x-f-e.x-s)/n,m=h+e.y+(r.y-h-e.y-i)/n,p=r.width/n,y=r.height/n,g=f+o.x+a+l*(v-f-o.x),x=h+o.y+c+l*(m-h-o.y),b=p*l,_=y*l;return{x:g,y:x,width:b,height:_,left:g,top:x,right:g+b,bottom:x+_}}function pt(r,t,e){return{viewName:r,backwardState:t,forwardState:e}}function he(r){return{detachedNode:r}}function ue(r,t,e,s,i){let n=[];return t!==null&&n.push(t),e!==null&&n.push(e),s!==null&&n.push(s),i!==null&&n.push(i),{zoomLevel:r,views:n}}function Vt(r){let t=r.views?.[3];if(!(!t||!(t.detachedNode instanceof Node)))return t.detachedNode}var Tt=class{#t=new Map;#e;constructor({maxEntries:t=64}={}){this.#e=Number.isInteger(t)&&t>=0?t:64}set(t,e,s=null){this.#e!==0&&this.adopt(t,e.cloneNode(!0),s)}adopt(t,e,s=null){let i=Date.now();for(let[n,o]of this.#t)o.expires!==null&&i>=o.expires&&this.#t.delete(n);if(this.#e!==0)for(this.#t.delete(t),this.#t.set(t,{node:e,expires:s===null?null:i+s});this.#t.size>this.#e;)this.#t.delete(this.#t.keys().next().value)}get(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>=e.expires?(this.#t.delete(t),null):(this.#t.delete(t),this.#t.set(t,e),e.node.cloneNode(!0)):null}has(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>=e.expires?(this.#t.delete(t),!1):!0:!1}invalidate(t){this.#t.delete(t)}clear(){this.#t.clear()}};var Ke="button, input, select, textarea, a[href], summary";function kt(r){return r?.matches?.(Ke)||!1}function jt(r){return!!r?.closest?.('input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"], [role="combobox"], [role="slider"], [role="spinbutton"]')}function de(r){let t=r.querySelectorAll(".zoom-me[data-to]");return t.forEach(e=>{kt(e)||(e.hasAttribute("role")||e.setAttribute("role","button"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0")),!e.hasAttribute("aria-label")&&!e.hasAttribute("aria-labelledby")&&!e.textContent.trim()&&e.setAttribute("aria-label",`Zoom to ${e.dataset.to}`)}),t}var Et=class{constructor(){this.backgrounds=new Map}sync(t){for(let e of t.children)e.classList.contains("z-view")&&(e.classList.contains("is-current-view")?this.restore(e):(this.backgrounds.has(e)||this.backgrounds.set(e,{inert:e.inert,hidden:e.getAttribute("aria-hidden")}),e.inert=!0,e.setAttribute("aria-hidden","true")));for(let e of this.backgrounds.keys())t.contains(e)||this.restore(e)}restore(t){let e=this.backgrounds.get(t);e&&(t.inert=e.inert,e.hidden===null?t.removeAttribute("aria-hidden"):t.setAttribute("aria-hidden",e.hidden),this.backgrounds.delete(t))}destroy(){for(let t of this.backgrounds.keys())this.restore(t)}};var Ue=300*1e3,me=/^https?:\/\/|^\/|\.(?:html|php)(?:[?#].*)?$/i,zt=class{#t;#e;#l;#n=new Map;#s=new Map;#r=null;#c=0;#d;#f;#i=!1;#o=!1;constructor(t={},{maxCacheEntries:e=64,prefetchConcurrency:s=2,maxPendingPrefetch:i=32}={}){this.#l=t,this.#t=new xt(t),this.#e=new Tt({maxEntries:e}),this.#d=Number.isInteger(s)&&s>0?s:2,this.#f=Number.isInteger(i)&&i>=0?i:32}#h(t){let e=new Set;for(;typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.#l,t);){if(e.has(t))return null;e.add(t),t=this.#l[t]}return typeof t=="string"&&(t.includes("<")||me.test(t))?t:null}#v(t){return me.test(t)?Ue:null}async get(t,e=null){if(this.#i)throw new Error("Zumly: view prefetcher has been destroyed");this.#s.delete(t);let s=this.#h(t);if(s!==null){let i=this.#e.get(t);return i||(await this.#m(t,s,e)).cloneNode(!0)}return this.#t.resolve(t,e)}#m(t,e,s){if(this.#n.has(t))return this.#n.get(t);let i=(async()=>{try{let n=await this.#t.resolve(t,s);return this.#i||this.#e.adopt(t,n,this.#v(e)),n}finally{this.#n.delete(t)}})();return this.#n.set(t,i),i}async#u(t,e){if(this.#i)return;this.#s.delete(t);let s=this.#h(t);s===null||this.#e.has(t)||await this.#m(t,s,e)}async preloadEager(t,e=null){!Array.isArray(t)||t.length===0||await Promise.all([...new Set(t)].map(s=>this.#u(s,e)))}prefetch(t,e=null){if(this.#o){this.#p(t,e);return}this.#u(t,e).catch(()=>{})}prefetchOnHover(t,e=null){this.prefetch(t,e)}scanAndPrefetch(t,e=null){if(this.#i||!t||!t.querySelectorAll)return;let s=de(t);this.#s.clear();let i=new Set;for(let n of s){let o=n.dataset.to;if(!(!o||i.has(o))){if(i.add(o),this.#s.size>=this.#f)break;this.#p(o,e)}}this.#a()}#p(t,e){this.#i||this.#s.size>=this.#f||this.#s.has(t)||this.#h(t)===null||this.#e.has(t)||this.#n.has(t)||this.#s.set(t,e)}#a(){this.#i||this.#o||this.#r!==null||this.#s.size===0||this.#c>=this.#d||(this.#r=setTimeout(()=>{if(this.#r=null,this.#i||this.#s.size===0)return;let[t,e]=this.#s.entries().next().value;this.#s.delete(t),this.#c++,this.#u(t,e).catch(()=>{}).finally(()=>{this.#c--,this.#a()}),this.#a()},0))}pause(){this.#o=!0,this.#r!==null&&clearTimeout(this.#r),this.#r=null}resume(){this.#o=!1,this.#a()}destroy(){this.#i=!0,this.#r!==null&&clearTimeout(this.#r),this.#r=null,this.#s.clear(),this.#e.clear()}};var Lt=Symbol.for("zumly.viewVisibility");function pe(r){r[Lt]||Object.defineProperty(r,Lt,{configurable:!0,value:{value:r.style.getPropertyValue("content-visibility"),priority:r.style.getPropertyPriority("content-visibility")}})}function Ct(r){r&&(pe(r),r.style.contentVisibility="hidden")}function vt(r){r&&(pe(r),r.style.contentVisibility="visible")}function yt(r){let t=r?.[Lt];t&&(t.value?r.style.setProperty("content-visibility",t.value,t.priority):r.style.removeProperty("content-visibility"),delete r[Lt])}function K(r){if(typeof r=="number"&&!Number.isNaN(r))return Math.max(0,r);let t=String(r).trim(),e=t.match(/^(\d*\.?\d+)\s*(ms|s)?$/i);if(!e)return typeof console<"u"&&console.warn(`[zumly] Could not parse duration "${t}" \u2014 falling back to 500ms.`),500;let s=parseFloat(e[1]);return(e[2]||"s").toLowerCase()==="ms"?Math.max(0,s):Math.max(0,s*1e3)}function Nt(r){return K(r)/1e3}function k(r,t){if(r.classList.contains("is-new-current-view")){let e=t.views[0].forwardState;r.classList.replace("is-new-current-view","is-current-view"),r.classList.remove("zoom-current-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-previous-view")){let e=t.views[1].forwardState;r.classList.remove("zoom-previous-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-last-view")){let e=t.views[2].forwardState;r.classList.remove("zoom-last-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform}}function V(r,t){r.classList.remove("zoom-previous-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin="0 0",r.style.transform=t.transform}function j(r,t){r.classList.remove("zoom-last-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin=t.origin,r.style.transform=t.transform}function H(r,t){C(r);try{t&&t.removeChild(r)}catch{try{r?.parentElement&&t&&(C(r.parentElement),t.removeChild(r.parentElement))}catch{}}}function Z(...r){for(let t of r)t&&(t.classList.remove("hide"),vt(t))}function G(r,t){let{currentView:e,previousView:s,backView:i,backViewState:n,lastView:o,lastViewState:a,incomingTransformEnd:c,currentStage:l,canvas:f}=r,h=l.views[0];Z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=h.forwardState.origin,e.style.transform=c||h.forwardState.transform,i&&n&&(i.style.transform=n.transformEnd),o&&a&&(o.style.transform=a.transformEnd),r.keepAlive||H(s,f),t()}var Q=150;function J(r,t){let e=!1,s=setTimeout(()=>{e||(e=!0,r())},t);return{finish(){e||(e=!0,clearTimeout(s),r())},extend(i){e||(clearTimeout(s),s=setTimeout(()=>{e||(e=!0,r())},i))},safetyTimer:s}}function Ot(){return{a:1,b:0,c:0,d:1,e:0,f:0}}function Ge(r){if(!r||r==="none")return Ot();let t=String(r).match(/matrix\(([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+)\)/);return t?{a:parseFloat(t[1]),b:parseFloat(t[2])||0,c:parseFloat(t[3])||0,d:parseFloat(t[4]),e:parseFloat(t[5])||0,f:parseFloat(t[6])||0}:Ot()}function at(r){return`matrix(${r.a}, ${r.b}, ${r.c}, ${r.d}, ${r.e}, ${r.f})`}function ot(r,t,e){return r+(t-r)*e}function lt(r,t,e){let s=Math.max(0,Math.min(1,e));return{a:ot(r.a,t.a,s),b:ot(r.b,t.b,s),c:ot(r.c,t.c,s),d:ot(r.d,t.d,s),e:ot(r.e,t.e,s),f:ot(r.f,t.f,s)}}function ve(r,t,e){r.style.transformOrigin=t,r.style.transform=e;try{r.getBoundingClientRect()}catch{}return Ge(getComputedStyle(r).transform)}function ge(r,t){let{type:e,currentView:s,previousView:i,lastView:n,currentStage:o,duration:a,ease:c,canvas:l}=r;if(!s||!i||!o){t();return}e==="lateral"?Qe(r,t):e==="zoomIn"?Je(s,i,n,o,a,c,t):e==="zoomOut"?ts(s,i,n,o,a,c,l,t):t()}function Qe(r,t){let{currentView:e,previousView:s,backView:i,backViewState:n,lastView:o,lastViewState:a,incomingTransformStart:c,incomingTransformEnd:l,outgoingTransform:f,outgoingTransformEnd:h,currentStage:u,duration:d,ease:v,canvas:m}=r,p=K(d),y=u.views[0];Z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=y.forwardState.origin,i&&n&&(R(i,d,v,{"--lateral-from":n.transformStart,"--lateral-to":n.transformEnd}),i.classList.add("zoom-lateral-back")),o&&a&&(R(o,d,v,{"--lateral-from":a.transformStart,"--lateral-to":a.transformEnd}),o.classList.add("zoom-lateral-back")),r.keepAlive!=="visible"&&(R(s,d,v,{"--lateral-out-from":f,"--lateral-out-to":h}),s.classList.add("zoom-lateral-out")),R(e,d,v,{"--lateral-in-from":c,"--lateral-in-to":l}),e.classList.add("zoom-lateral-in");let g=r.keepAlive==="visible"?[e]:[s,e];i&&n&&g.push(i),o&&a&&g.push(o);let x=g.length,b=p+Q,_=new Set(["zoom-lateral-in","zoom-lateral-out","zoom-lateral-back"]),{finish:S,extend:O}=J(()=>{Bt(g,E,A),r.keepAlive?(s.classList.remove("zoom-lateral-out"),s.style.opacity=""):H(s,m),i&&(i.classList.remove("zoom-lateral-back"),i.style.transform=n?.transformEnd||i.style.transform),o&&(o.classList.remove("zoom-lateral-back"),o.style.transform=a?.transformEnd||o.style.transform),e.classList.remove("zoom-lateral-in"),e.style.transform=l,t()},b);function A(T){T.target!==T.currentTarget||!_.has(T.animationName)||O(b)}function E(T){if(T.target!==T.currentTarget||!_.has(T.animationName))return;let P=T.currentTarget;P.removeEventListener("animationend",E),P.removeEventListener("animationstart",A),x--,x<=0&&S()}g.forEach(T=>{T.addEventListener("animationstart",A),T.addEventListener("animationend",E)})}function Je(r,t,e,s,i,n,o){Z(r,t,e);let a=s.stagger||0;R(r,i,n,{"--current-view-transform-start":s.views[0].backwardState.transform,"--current-view-transform-end":s.views[0].forwardState.transform}),a>0&&r.style.setProperty("animation-delay","0ms"),R(t,i,n,{"--previous-view-transform-start":s.views[1].backwardState.transform,"--previous-view-transform-end":s.views[1].forwardState.transform}),a>0&&t.style.setProperty("animation-delay",`${a}ms`),e&&(R(e,i,n,{"--last-view-transform-start":s.views[2].backwardState.transform,"--last-view-transform-end":s.views[2].forwardState.transform}),a>0&&e.style.setProperty("animation-delay",`${a*2}ms`)),r.classList.add("zoom-current-view"),t.classList.add("zoom-previous-view"),e&&e.classList.add("zoom-last-view");let c=e?[r,t,e]:[r,t],l=c.length,f=K(i),h=e?a*2:a,u=f+h+Q,d=new Set(["zoom-current-view","zoom-previous-view","zoom-last-view"]),{finish:v,extend:m}=J(()=>{Bt(c,y,p),c.forEach(g=>g.style.removeProperty("animation-delay")),c.forEach(g=>{if(g?.isConnected)try{k(g,s)}catch{}}),o()},u);function p(g){g.target!==g.currentTarget||!d.has(g.animationName)||m(u)}function y(g){if(g.target!==g.currentTarget||!d.has(g.animationName))return;let x=g.currentTarget;if(x.removeEventListener("animationend",y),x.removeEventListener("animationstart",p),x.isConnected)try{k(x,s)}catch{}l--,l<=0&&v()}c.forEach(g=>{g.addEventListener("animationstart",p),g.addEventListener("animationend",y)})}function ts(r,t,e,s,i,n,o,a){let c=s.views[0],l=s.views[1],f=e&&s.views[2]?s.views[2]:null,h=s.stagger||0;R(r,i,n,{"--current-view-transform-start":c.backwardState.transform,"--current-view-transform-end":c.forwardState.transform}),h>0&&r.style.setProperty("animation-delay","0ms"),R(t,i,n,{"--previous-view-transform-start":l.backwardState.transform,"--previous-view-transform-end":l.forwardState.transform}),h>0&&t.style.setProperty("animation-delay",`${h}ms`),e&&f&&(R(e,i,n,{"--last-view-transform-start":f.backwardState.transform,"--last-view-transform-end":f.forwardState.transform}),h>0&&e.style.setProperty("animation-delay",`${h*2}ms`)),r.classList.add("zoom-current-view-reverse"),t.classList.add("zoom-previous-view-reverse"),e&&e.classList.add("zoom-last-view-reverse");let u=e?[r,t,e]:[r,t],d=u.length,v=K(i),m=e?h*2:h,p=v+m+Q,y=new Set(["zoom-current-view-reverse","zoom-previous-view-reverse","zoom-last-view-reverse"]),{finish:g,extend:x}=J(()=>{Bt(u,_,b),u.forEach(S=>S.style.removeProperty("animation-delay")),u.forEach(S=>{if(S?.isConnected)try{ye(S,s,o)}catch{}}),a()},p);function b(S){S.target!==S.currentTarget||!y.has(S.animationName)||x(p)}function _(S){if(S.target!==S.currentTarget||!y.has(S.animationName))return;let O=S.currentTarget;if(O.removeEventListener("animationend",_),O.removeEventListener("animationstart",b),O.isConnected)try{ye(O,s,o)}catch{}d--,d<=0&&g()}u.forEach(S=>{S.addEventListener("animationstart",b),S.addEventListener("animationend",_)})}function ye(r,t,e){if(r.classList.contains("zoom-current-view-reverse")){H(r,e);return}if(r.classList.contains("zoom-previous-view-reverse")){V(r,t.views[1].backwardState);return}r.classList.contains("zoom-last-view-reverse")&&j(r,t.views[2].backwardState)}function R(r,t,e,s){r.style.setProperty("--zoom-duration",t),r.style.setProperty("--zoom-ease",e);for(let[i,n]of Object.entries(s))r.style.setProperty(i,n)}function Bt(r,t,e){for(let s of r)s?.removeEventListener&&(s.removeEventListener("animationend",t),s.removeEventListener("animationstart",e))}function we(r,t){let{type:e,currentView:s,previousView:i,lastView:n,currentStage:o,canvas:a}=r;if(!s||!i||!o){t();return}if(e==="lateral"){G(r,t);return}if(e==="zoomIn"){Z(s,i,n),k(s,o),k(i,o),n&&k(n,o),t();return}if(e==="zoomOut"){H(s,a),Z(i,n),V(i,o.views[1].backwardState),n&&j(n,o.views[2].backwardState),t();return}t()}function be(r,t){let{type:e,currentView:s,previousView:i,lastView:n,currentStage:o,duration:a,ease:c,canvas:l}=r;if(!s||!i||!o){t();return}let f=K(a);if(e==="lateral"){rs(r,f,c,t);return}if(e==="zoomIn"){es(s,i,n,o,f,c,t);return}if(e==="zoomOut"){ss(s,i,n,o,f,c,l,t);return}t()}function es(r,t,e,s,i,n,o){Z(r,t,e);let a=s.views[0],c=s.views[1],l=e&&s.views[2]?s.views[2]:null;r.style.transformOrigin=a.backwardState.origin,r.style.transform=a.backwardState.transform,t.style.transformOrigin=c.backwardState.origin,t.style.transform=c.backwardState.transform,l&&(e.style.transformOrigin=l.backwardState.origin,e.style.transform=l.backwardState.transform);let f=s.stagger||0,h=[];h.push(r.animate([{transform:a.backwardState.transform},{transform:a.forwardState.transform}],{duration:i,easing:n,fill:"forwards"})),h.push(t.animate([{transform:c.backwardState.transform},{transform:c.forwardState.transform}],{duration:i,delay:f,easing:n,fill:"forwards"})),l&&h.push(e.animate([{transform:l.backwardState.transform},{transform:l.forwardState.transform}],{duration:i,delay:f*2,easing:n,fill:"forwards"}));let u=l?f*2:f,{finish:d}=J(()=>{Rt(h);try{k(r,s),k(t,s),e&&k(e,s)}catch{}o()},i+u+Q);Promise.all(h.map(v=>v.finished)).then(d).catch(d)}function ss(r,t,e,s,i,n,o,a){let c=s.views[0],l=s.views[1],f=e&&s.views[2]?s.views[2]:null,h=l.backwardState,u=f?f.backwardState:null;r.style.transformOrigin=c.forwardState.origin,r.style.transform=c.forwardState.transform,requestAnimationFrame(()=>{requestAnimationFrame(()=>{t.style.transformOrigin=l.forwardState.origin,e&&f&&(e.style.transformOrigin=f.forwardState.origin);let d=t.style.transform||getComputedStyle(t).transform||l.forwardState.transform,v=e&&f?e.style.transform||getComputedStyle(e).transform||f.forwardState.transform:null,m=s.stagger||0,p=[];p.push(r.animate([{transform:c.forwardState.transform},{transform:c.backwardState.transform}],{duration:i,easing:n,fill:"forwards"})),p.push(t.animate([{transform:d},{transform:h.transform}],{duration:i,delay:m,easing:n,fill:"both"})),e&&u&&p.push(e.animate([{transform:v},{transform:u.transform}],{duration:i,delay:m*2,easing:n,fill:"both"})),t.style.removeProperty("transform"),e&&e.style.removeProperty("transform");let y=e&&u?m*2:m,{finish:g}=J(()=>{Rt(p);try{H(r,o),V(t,h),e&&u&&j(e,u)}catch{}a()},i+y+Q);Promise.all(p.map(x=>x.finished)).then(g).catch(g)})})}function rs(r,t,e,s){let{currentView:i,previousView:n,backView:o,backViewState:a,lastView:c,lastViewState:l,incomingTransformStart:f,incomingTransformEnd:h,outgoingTransform:u,outgoingTransformEnd:d,currentStage:v,canvas:m}=r,p=v.views[0];Z(i),i.classList.replace("is-new-current-view","is-current-view"),i.classList.remove("zoom-current-view","has-no-events"),i.style.transformOrigin=p.forwardState.origin;let y=[];y.push(i.animate([{transform:f,opacity:0},{transform:h,opacity:1}],{duration:t,easing:e,fill:"forwards"})),r.keepAlive!=="visible"&&y.push(n.animate([{transform:u,opacity:1},{transform:d,opacity:0}],{duration:t,easing:e,fill:"forwards"})),o&&a&&y.push(o.animate([{transform:a.transformStart},{transform:a.transformEnd}],{duration:t,easing:e,fill:"forwards"})),c&&l&&y.push(c.animate([{transform:l.transformStart},{transform:l.transformEnd}],{duration:t,easing:e,fill:"forwards"}));let{finish:g}=J(()=>{Rt(y),i.style.transform=h||p.forwardState.transform,o&&a&&(o.style.transform=a.transformEnd),c&&l&&(c.style.transform=l.transformEnd),r.keepAlive?(n.style.opacity="",n.style.transform=d):H(n,m),s()},t+Q);Promise.all(y.map(x=>x.finished)).then(g).catch(g)}function Rt(r){for(let t of r)try{t.cancel()}catch{}}var xe="[-+]?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?",_e=`(${xe})(px)?`,is=new RegExp(`^(?:translate\\(\\s*${_e}\\s*,\\s*${_e}\\s*\\)\\s*)?(?:scale\\(\\s*(${xe})\\s*\\))?$`);function ns(r){if(typeof r!="string")return null;let t=r.trim();if(t==="none")return Ot();if(!t)return null;let e=t.match(is);if(!e)return null;let s=Number(e[1]??0),i=Number(e[3]??0),n=Number(e[5]??1);return s!==0&&!e[2]||i!==0&&!e[4]||![s,i,n].every(Number.isFinite)?null:{a:n,b:0,c:0,d:n,e:s,f:i}}function q(r,t,e){let s=ns(e);return s?(r.style.transformOrigin=t,r.style.transform=e,s):ve(r,t,e)}function Se(r,t){let e=typeof globalThis<"u"&&globalThis.anime;if(!e||typeof e!="function"){console.warn('Zumly anime driver: Anime.js not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.2/anime.min.js"><\/script>'),t();return}let{type:s,currentView:i,previousView:n,lastView:o,currentStage:a,duration:c,ease:l,canvas:f}=r;if(!i||!n||!a){t();return}let h=K(c);s==="lateral"?G(r,t):s==="zoomIn"?os(e,i,n,o,a,h,l,t):s==="zoomOut"?as(e,i,n,o,a,h,l,f,t):t()}function os(r,t,e,s,i,n,o,a){Z(t,e,s);let c=i.views[0],l=i.views[1],f=s&&i.views[2]?i.views[2]:null,h=Te([{el:t,backward:c.backwardState,forward:c.forwardState},{el:e,backward:l.backwardState,forward:l.forwardState},...f?[{el:s,backward:f.backwardState,forward:f.forwardState}]:[]],"forward");Ee(h,0);let u=i.stagger||0,d=n+(f?u*2:u),v={value:0};r({targets:v,value:1,duration:d,easing:ze(o),update:()=>{let m=v.value*d;ke(h,m,n,u)},complete:()=>{k(t,i),k(e,i),s&&k(s,i),a()}})}function as(r,t,e,s,i,n,o,a,c){let l=i.views[0],f=i.views[1],h=s&&i.views[2]?i.views[2]:null,u=f.backwardState,d=h?h.backwardState:null,v=Te([{el:t,backward:l.backwardState,forward:l.forwardState},{el:e,backward:f.backwardState,forward:f.forwardState},...h?[{el:s,backward:h.backwardState,forward:h.forwardState}]:[]],"backward");Ee(v,0);let m=i.stagger||0,p=n+(h?m*2:m),y={value:0};r({targets:y,value:1,duration:p,easing:ze(o),update:()=>{let g=y.value*p;ke(v,g,n,m)},complete:()=>{H(t,a),V(e,u),s&&d&&j(s,d),c()}})}function Te(r,t){return r.map(({el:e,backward:s,forward:i})=>{if(t==="forward"){let n=q(e,s.origin,s.transform),o=q(e,s.origin,i.transform);return{el:e,from:n,to:o}}else{let n=q(e,i.origin,i.transform),o=q(e,i.origin,s.transform);return{el:e,from:n,to:o}}})}function Ee(r,t){for(let{el:e,from:s,to:i}of r)e.style.transform=at(lt(s,i,t))}function ke(r,t,e,s){for(let i=0;i<r.length;i++){let{el:n,from:o,to:a}=r[i],c=i*s,l=Math.max(0,t-c),f=e>0?Math.min(1,l/e):1;n.style.transform=at(lt(o,a,f))}}function ze(r){if(typeof r!="string")return"easeInOutQuad";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOutQuad":t.includes("ease-in")?"easeInQuad":t.includes("ease-out")?"easeOutQuad":t}function Le(r,t){let e=typeof globalThis<"u"&&globalThis.gsap;if(!e||typeof e.to!="function"){console.warn('Zumly GSAP driver: GSAP not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"><\/script>'),t();return}let{type:s,currentView:i,previousView:n,lastView:o,currentStage:a,duration:c,ease:l,canvas:f}=r;if(!i||!n||!a){t();return}let h=Nt(c);s==="lateral"?G(r,t):s==="zoomIn"?ls(e,i,n,o,a,h,l,t):s==="zoomOut"?cs(e,i,n,o,a,h,l,f,t):t()}function ls(r,t,e,s,i,n,o,a){Z(t,e,s);let c=i.views[0],l=i.views[1],f=s&&i.views[2]?i.views[2]:null;At(t,c.backwardState),At(e,l.backwardState),f&&At(s,f.backwardState);let h=r.timeline({onComplete:()=>{k(t,i),k(e,i),s&&k(s,i),a()}}),u=Ce(o),d=(i.stagger||0)/1e3;h.to(t,{transform:c.forwardState.transform,duration:n,ease:u},0),h.to(e,{transform:l.forwardState.transform,duration:n,ease:u},d),f&&h.to(s,{transform:f.forwardState.transform,duration:n,ease:u},d*2)}function cs(r,t,e,s,i,n,o,a,c){let l=i.views[0],f=i.views[1],h=s&&i.views[2]?i.views[2]:null,u=f.backwardState,d=h?h.backwardState:null;At(t,l.forwardState);let v=e.style.transform||getComputedStyle(e).transform||f.forwardState.transform,m=s&&h?s.style.transform||getComputedStyle(s).transform||h.forwardState.transform:null;e.style.transformOrigin=f.forwardState.origin,s&&h&&(s.style.transformOrigin=h.forwardState.origin);let p=Ce(o),y=r.timeline({onComplete:()=>{H(t,a),V(e,u),s&&d&&j(s,d),c()}}),g=(i.stagger||0)/1e3;r.set(e,{transform:v}),s&&m&&r.set(s,{transform:m}),y.fromTo(t,{transform:l.forwardState.transform},{transform:l.backwardState.transform,duration:n,ease:p},0),y.fromTo(e,{transform:v},{transform:u.transform,duration:n,ease:p},g),s&&d&&y.fromTo(s,{transform:m},{transform:d.transform,duration:n,ease:p},g*2)}function At(r,t){r.style.transformOrigin=t.origin,r.style.transform=t.transform}function Ce(r){if(typeof r!="string")return"power2.inOut";let t=r.toLowerCase();return t==="linear"?"none":t.includes("ease-in-out")?"power2.inOut":t.includes("ease-in")?"power2.in":t.includes("ease-out")?"power2.out":t}function Oe(r,t){let e=us();if(!e||typeof e!="function"){console.warn('Zumly Motion driver: Motion not loaded. Add <script src="https://cdn.jsdelivr.net/npm/motion@11/dist/motion.min.js"><\/script>'),t();return}let{type:s,currentView:i,previousView:n,lastView:o,currentStage:a,duration:c,ease:l,canvas:f}=r;if(!i||!n||!a){t();return}let h=Nt(c);s==="lateral"?G(r,t):s==="zoomIn"?fs(e,i,n,o,a,h,l,t):s==="zoomOut"?hs(e,i,n,o,a,h,l,f,t):t()}function fs(r,t,e,s,i,n,o,a){Z(t,e,s);let c=Ne(t,e,s,i,"forward");Ae(c,0);let l=i.stagger||0,f=l/1e3,h=n*1e3,u=n+(c.length>2?f*2:f);r(0,1,{duration:u,ease:Ie(o),onUpdate:v=>{let m=v*u*1e3;Pe(c,m,h,l)}}).then(()=>{k(t,i),k(e,i),s&&k(s,i),a()}).catch(()=>a())}function hs(r,t,e,s,i,n,o,a,c){let l=i.views[1],f=s&&i.views[2]?i.views[2]:null,h=l.backwardState,u=f?f.backwardState:null,d=Ne(t,e,s,i,"backward");Ae(d,0);let v=i.stagger||0,m=v/1e3,p=n*1e3,y=n+(d.length>2?m*2:m);r(0,1,{duration:y,ease:Ie(o),onUpdate:x=>{let b=x*y*1e3;Pe(d,b,p,v)}}).then(()=>{H(t,a),V(e,h),s&&u&&j(s,u),c()}).catch(()=>c())}function Ne(r,t,e,s,i){let n=s.views[0],o=s.views[1],a=e&&s.views[2]?s.views[2]:null,c=[{el:r,backward:n.backwardState,forward:n.forwardState},{el:t,backward:o.backwardState,forward:o.forwardState}];return a&&c.push({el:e,backward:a.backwardState,forward:a.forwardState}),c.map(({el:l,backward:f,forward:h})=>i==="forward"?{el:l,from:q(l,f.origin,f.transform),to:q(l,f.origin,h.transform)}:{el:l,from:q(l,h.origin,h.transform),to:q(l,h.origin,f.transform)})}function Ae(r,t){for(let{el:e,from:s,to:i}of r)e.style.transform=at(lt(s,i,t))}function Pe(r,t,e,s){for(let i=0;i<r.length;i++){let{el:n,from:o,to:a}=r[i],c=i*s,l=Math.max(0,t-c),f=e>0?Math.min(1,l/e):1;n.style.transform=at(lt(o,a,f))}}function us(){let r=typeof globalThis<"u"?globalThis:typeof window<"u"?window:{};return r.motion?.animate||r.Motion?.animate||r.animate}function Ie(r){if(typeof r!="string")return"easeInOut";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOut":t.includes("ease-in")?"easeIn":t.includes("ease-out")?"easeOut":r}var $e={css:ge,waapi:be,none:we,anime:Se,gsap:Le,motion:Oe};function Pt(r){if(typeof r=="function")return{runTransition(s,i){r(s,i)}};let t=typeof r=="string"?r.toLowerCase():"css";return{runTransition:$e[t]||$e.css}}function ds(r){if(typeof r!="string"||r.trim()==="")return{tx:0,ty:0,rest:""};let t=et(r);return t.matched?{tx:t.tx,ty:t.ty,rest:t.rest}:null}function Ze(r,t,e){let s=ds(r);if(s===null)return r;let i=s.tx*t,n=s.ty*e,o=s.rest?` ${s.rest}`:"";return`translate(${i}px, ${n}px)${o}`.trim()}function ms(r){if(typeof r!="string"||!r.trim())return null;let t=r.trim().match(/^([-\d.eE]+)px\s+([-\d.eE]+)px$/);return t?{x:parseFloat(t[1]),y:parseFloat(t[2])}:null}function Me(r,t,e){let s=ms(r);return s===null?r:`${s.x*t}px ${s.y*e}px`}function qt(r,t,e,s,i){if(!r.storedViews?.length||!r.canvas||t<=0||e<=0)return;let n=s/t,o=i/e,a=new Set,c=p=>{if(!(!p||p.detachedNode))for(let y of[p.backwardState,p.forwardState])!y||a.has(y)||(a.add(y),y.transform=Ze(y.transform,n,o),y.origin!=null&&(y.origin=Me(y.origin,n,o)))},l=[...r.storedViews];for(let p of r.lateralHistory||[])p.stage&&l.push(p.stage),c(p.entry);for(let p of l)Array.isArray(p.views)&&p.views.forEach(c);let f=r.canvas,h=f.querySelector(".is-current-view"),u=f.querySelector(".is-previous-view"),d=f.querySelector(".is-last-view"),v=f.querySelector(".is-new-current-view"),m=[h,u,d,v].filter(Boolean);for(let p of m){if(!p.style)continue;let y=p.style.transform;y!=null&&y!==""&&(p.style.transform=Ze(y,n,o));let g=p.style.transformOrigin;g!=null&&g!==""&&(p.style.transformOrigin=Me(g,n,o))}}var ps=8e3,ft=class{constructor(t){if(this.storedViews=[],this.currentStage=null,this.debug=!1,this.trace=[],this.blockEvents=!1,this._blockEventsSafetyTimer=null,this.touchstartX=0,this.touchstartY=0,this.touchendX=0,this.touchendY=0,this.touching=!1,this.lateralHistory=[],this._lastCanvasWidth=0,this._lastCanvasHeight=0,this._pendingResizeCorrection=!1,this._destroyed=!1,this._trackedTimers=new Set,this._pendingTransitionComplete=null,this._navigationTask=null,this._initPromise=null,this._accessibility=new Et,this._hooks={},this._plugins=[],ne(t,this),!this.isValid){this.notify("is unable to start: invalid or missing required options (mount, initialView, views).","error");return}if(this.canvas=document.querySelector(this.mount),!this.canvas){this.notify(`mount selector "${this.mount}" did not match any element.`,"error"),this.isValid=!1;return}this.transitionDriver=Pt(this.transitionDriver),this._onZoom=this.onZoom.bind(this),this._onTouchStart=this.onTouchStart.bind(this),this._onTouchEnd=this.onTouchEnd.bind(this),this._onTouchCancel=()=>{this.touching=!1},this._onKeyUp=this.onKeyUp.bind(this),this._onKeyDown=this.onKeyDown.bind(this),this._onKeyboardClick=e=>{e.target.closest?.(".zoom-me[data-to]")&&((e.detail===0?!this.inputs.keyboard:!this.inputs.click)||(e.preventDefault(),e.detail===0&&this.onZoom(e)))},this._onWheel=this.onWheel.bind(this),this._wheelCooldown=!1,this._onPrefetchTrigger=e=>{let s=e.target.closest?.(".zoom-me[data-to]");!this._destroyed&&s&&this.canvas.contains(s)&&this.prefetcher.prefetch(s.dataset.to,{trigger:s,context:this.componentContext,props:{...s.dataset}})},this._onResize=this._handleResize.bind(this),this._resizeDebounceTimer=null,this._RESIZE_DEBOUNCE_MS=80,this.prefetcher=new zt(this.views),this._bindEvents()}_bindEvents(){let t=this.canvas;t&&(this._canvasAttributes=new Map(["tabindex","role","aria-roledescription","aria-live"].map(e=>[e,t.getAttribute(e)])),t.setAttribute("tabindex","0"),t.setAttribute("role","application"),t.setAttribute("aria-roledescription","zoomable interface"),t.setAttribute("aria-live","polite"),t.addEventListener("mouseup",this._onZoom,!1),t.addEventListener("touchend",this._onZoom,!1),t.addEventListener("touchstart",this._onTouchStart,{passive:!0}),t.addEventListener("touchend",this._onTouchEnd,!1),t.addEventListener("touchcancel",this._onTouchCancel,{passive:!0}),t.addEventListener("keyup",this._onKeyUp,!1),t.addEventListener("keydown",this._onKeyDown,!1),t.addEventListener("click",this._onKeyboardClick,!1),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("mouseover",this._onPrefetchTrigger,{passive:!0}),t.addEventListener("focusin",this._onPrefetchTrigger,{passive:!0}),window.addEventListener("resize",this._onResize,{passive:!0}),typeof ResizeObserver<"u"&&(this._resizeObserver=new ResizeObserver(()=>this._handleResize()),this._resizeObserver.observe(t)))}_unbindEvents(){let t=this.canvas;t&&(t.removeEventListener("mouseup",this._onZoom,!1),t.removeEventListener("touchend",this._onZoom,!1),t.removeEventListener("touchstart",this._onTouchStart),t.removeEventListener("touchend",this._onTouchEnd,!1),t.removeEventListener("touchcancel",this._onTouchCancel),t.removeEventListener("keyup",this._onKeyUp,!1),t.removeEventListener("keydown",this._onKeyDown,!1),t.removeEventListener("click",this._onKeyboardClick,!1),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("mouseover",this._onPrefetchTrigger),t.removeEventListener("focusin",this._onPrefetchTrigger)),window.removeEventListener("resize",this._onResize),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null)}_resetCanvasScroll(t){if(t&&((t.scrollLeft!==0||t.scrollTop!==0)&&(this.notify(`canvas had a residual scroll (${t.scrollLeft}, ${t.scrollTop}) \u2014 resetting. Something scrolled the canvas mid-transition.`,"warn"),t.scrollLeft=0,t.scrollTop=0),!this._warnedScrolledAncestor)){for(let e=t.parentElement;e&&e!==document.body;e=e.parentElement)if(e.scrollLeft!==0||e.scrollTop!==0){let s=e.className?`.${String(e.className).trim().split(/\s+/).join(".")}`:e.tagName.toLowerCase();this.notify(`an ancestor of the canvas (${s}) is scrolled (${e.scrollLeft}, ${e.scrollTop}): all zooms will land displaced. Use 'overflow: clip' (not 'hidden') on containers around the canvas.`,"warn"),this._warnedScrolledAncestor=!0;break}}}_setBlockEvents(){this.blockEvents=!0,this._clearBlockEventsSafety(),this._blockEventsSafetyTimer=setTimeout(()=>{if(this.blockEvents&&!this._destroyed){this.notify("blockEvents safety timeout: driver did not call onComplete. Force-resetting.","warn"),this.blockEvents=!1;let t=this._pendingTransitionComplete;t?t():this._onTransitionComplete()}},ps)}_clearBlockEventsSafety(){this._blockEventsSafetyTimer!==null&&(clearTimeout(this._blockEventsSafetyTimer),this._blockEventsSafetyTimer=null)}_setTrackedTimeout(t,e){let s=setTimeout(()=>{this._trackedTimers.delete(s),!this._destroyed&&t()},e);return this._trackedTimers.add(s),s}_clearTrackedTimeouts(){for(let t of this._trackedTimers)clearTimeout(t);this._trackedTimers.clear()}storeViews(t){this.tracing("storedViews()"),this.storedViews.push(t),this.debug&&console.debug("Zumly storedViews",t)}tracing(t){if(this.debug)if(t==="ended"){let e=this.trace.map((s,i)=>`${i===0?`Instance ${this.mount}: ${s}`:`${s}`}`).join(" > ");this.notify(e),this.trace=[]}else this.trace.push(t)}notify(t,e){return $(this.debug,t,e)}_recordCanvasSize(){this.canvas&&(this._lastCanvasWidth=this.canvas.offsetWidth,this._lastCanvasHeight=this.canvas.offsetHeight)}_handleResize(){this._destroyed||(this._resizeDebounceTimer&&clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=setTimeout(()=>{if(this._resizeDebounceTimer=null,!this.isValid||!this.canvas||this._lastCanvasWidth===0)return;let t=this.canvas.offsetWidth,e=this.canvas.offsetHeight;if(!(t===this._lastCanvasWidth&&e===this._lastCanvasHeight)){if(this.blockEvents){this._pendingResizeCorrection=!0;return}qt(this,this._lastCanvasWidth,this._lastCanvasHeight,t,e),this._lastCanvasWidth=t,this._lastCanvasHeight=e}},this._RESIZE_DEBOUNCE_MS))}_onTransitionComplete(){if(this._clearBlockEventsSafety(),this._pendingResizeCorrection&&!this.blockEvents){if(this._pendingResizeCorrection=!1,this.canvas&&this._lastCanvasWidth>0){let e=this.canvas.offsetWidth,s=this.canvas.offsetHeight;(e!==this._lastCanvasWidth||s!==this._lastCanvasHeight)&&qt(this,this._lastCanvasWidth,this._lastCanvasHeight,e,s),this._lastCanvasWidth=e,this._lastCanvasHeight=s}}else this._recordCanvasSize();for(let e of this.canvas?.children||[])e.classList.contains("z-view")&&yt(e);let t=this.canvas?.querySelector(".is-current-view");t&&this._accessibility.restore(t),this._manageFocus(),this.canvas&&this._accessibility.sync(this.canvas)}_manageFocus(){if(!this.canvas)return;let t=this.canvas.querySelector(".is-current-view");if(!t)return;let e='a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',s=n=>!n||n.closest("[inert], [hidden]")?!1:(n.focus({preventScroll:!0}),document.activeElement===n||n.contains(document.activeElement)),i=t.querySelector(e);if(!s(i)){for(let n of t.querySelectorAll(e))if(n!==i&&s(n))return;t.setAttribute("tabindex","-1"),t.focus({preventScroll:!0})}}_prefersReducedMotion(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}_resolveEffects(t){if(this._prefersReducedMotion())return["none","none"];let e=t?.dataset?.withEffects;if(e&&typeof e=="string"){let s=e.split("|").map(i=>i.trim());return[s[0]||"none",s[1]||s[0]||"none"]}return this.effects}_applyEffects(t,e,s,i,n){!s||s[0]==="none"&&s[1]==="none"||(t&&s[0]!=="none"&&(t.style.setProperty("--z-effect-filter",s[0]),t.style.setProperty("--zoom-duration",i),t.style.setProperty("--zoom-ease",n),t.classList.add("has-effect")),e&&s[1]!=="none"&&(e.style.setProperty("--z-effect-filter",s[1]),e.style.setProperty("--zoom-duration",i),e.style.setProperty("--zoom-ease",n),e.classList.add("has-effect")))}_removeEffect(t){if(!t||!t.classList.contains("has-effect"))return;t.classList.remove("has-effect"),t.classList.add("has-effect-reverse");let e=()=>{t.classList.remove("has-effect-reverse"),t.style.removeProperty("--z-effect-filter"),t.removeEventListener("transitionend",e)};t.addEventListener("transitionend",e,{once:!0});let s=t.style.getPropertyValue("--zoom-duration");this._setTrackedTimeout(e,s?parseFloat(s)*(s.includes("ms")?1:1e3)+100:1100)}_resolveHideTrigger(t){return t?.dataset?.hideTrigger!==void 0?t.dataset.hideTrigger==="fade"?"fade":!0:this.hideTrigger}_applyHideTrigger(t,e,s,i,n,o=!0){if(!(!s||!t))if(s==="fade"){if(t.style.setProperty("--zoom-duration",i),t.style.setProperty("--zoom-ease",n),t.classList.add("z-trigger-fade"),!o)return;e.style.setProperty("--zoom-duration",i),e.style.setProperty("--zoom-ease",n),e.classList.add("z-view-fade-in"),e.offsetHeight,e.classList.remove("hide")}else t.classList.add("z-trigger-hidden")}_restoreHideTrigger(t,e,s,i){if(!(!e||!t))if(e==="fade"){t.classList.remove("z-trigger-fade"),t.style.setProperty("--zoom-duration",s),t.style.setProperty("--zoom-ease",i),t.classList.add("z-trigger-fade-reverse");let n=()=>{t.classList.remove("z-trigger-fade-reverse"),t.style.removeProperty("--zoom-duration"),t.style.removeProperty("--zoom-ease"),t.removeEventListener("transitionend",n)};t.addEventListener("transitionend",n,{once:!0}),this._setTrackedTimeout(n,parseFloat(s)*(s.includes("ms")?1:1e3)+100)}else t.classList.remove("z-trigger-hidden")}on(t,e){return typeof e!="function"?this:((this._hooks[t]||=[]).push(e),this)}use(t,e){if(!t)return this;let s={plugin:t,options:e};return this._plugins.push(s),this._initialized&&this._installPlugin(s),this}_installPlugin(t){let{plugin:e,options:s}=t;try{typeof e=="function"?e(this,s):typeof e.install=="function"&&e.install(this,s)}catch(i){this.notify(`plugin install error: ${i.message}`,"error")}}off(t,e){return e?this._hooks[t]&&(this._hooks[t]=this._hooks[t].filter(s=>s!==e)):delete this._hooks[t],this}_emit(t,e={}){let s=this._hooks[t];if(!(!s||s.length===0))for(let i of s)try{i(e)}catch(n){this.debug&&console.error(`Zumly hook "${t}" threw:`,n)}}_runNavigation(t){if(this._destroyed||this.blockEvents)return Promise.resolve();let e={pendingViews:new Set};e.promise=new Promise(i=>{e.resolve=i}),this._navigationTask=e,this.blockEvents=!0,this.prefetcher?.pause();let s=()=>{this._navigationTask===e&&(this._navigationTask=null,this.blockEvents=!1,this._clearBlockEventsSafety(),this.prefetcher?.resume()),e.resolve()};try{Promise.resolve(t()).then(s,i=>{this.notify(`navigation aborted: ${i.message}`,"error"),s()})}catch(i){this.notify(`navigation aborted: ${i.message}`,"error"),s()}return e.promise}_cancelNavigation(){let t=this._navigationTask;if(this._navigationTask=null,this._pendingTransitionComplete=null,this._clearBlockEventsSafety(),this.blockEvents=!1,t){for(let e of t.pendingViews)C(e);t.pendingViews.clear(),t.releaseTransition?.(),t.resolve()}}_createViewContext(t={},e){let s={target:document.createElement("div"),context:this.componentContext,props:t};return e&&(s.trigger=e),this._navigationTask?.pendingViews.add(s.target),s}_runNavigationTransition(t,e){if(this._destroyed)return Promise.resolve();let s=this._navigationTask;return new Promise(i=>{s&&(s.releaseTransition=i);let n=()=>{if(this._pendingTransitionComplete===n){if(this._pendingTransitionComplete=null,this._destroyed){i();return}try{Promise.resolve(e()).then(i,l=>{this.notify(`transition completion failed: ${l.message}`,"error"),i()})}catch(l){this.notify(`transition completion failed: ${l.message}`,"error"),i()}}};this._setBlockEvents(),this._pendingTransitionComplete=n;let o=this._prefersReducedMotion?.(),a=o?Pt("none"):this.transitionDriver,c=o?{...t,duration:"0s",currentStage:{...t.currentStage,stagger:0}}:t;try{a.runTransition(c,n)}catch(l){this.notify(`transition driver failed: ${l.message}. Finishing without animation.`,"error");try{Pt("none").runTransition(c,n)}catch{n()}}})}zoomLevel(){return this.storedViews.length}getZoomLevel(){return this.zoomLevel()}getCurrentViewName(){return!this.storedViews||this.storedViews.length===0?null:this.storedViews[this.storedViews.length-1]?.views?.[0]?.viewName??null}async back(){if(!this._destroyed){if(this.blockEvents){this.notify("back ignored: a transition is already running.","warn");return}if(this.lateralHistory&&this.lateralHistory.length>0){let t=this.lateralHistory.pop(),e=t&&typeof t=="object"?t.name:t,s=t&&typeof t=="object"?t.entry:void 0,i=t&&typeof t=="object"?t.node:void 0;return this._doLateral(e,!0,{savedEntry:s,keepAliveNode:i,savedStage:t?.stage})}return this.zoomOut()}}async goTo(t,e={}){return this._destroyed?void 0:(e.mode==="lateral"?"lateral":"depth")==="depth"?this.zoomTo(t,e):this._doLateral(t,!1,e)}async zoomTo(t,e={}){if(this._destroyed)return;if(!this.isValid||!this.canvas){this.notify("zoomTo() cannot run: instance is invalid or canvas not found.","error");return}if(typeof t!="string"||!t){this.notify("zoomTo() requires a non-empty view name.","warn");return}if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`zoomTo("${t}"): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}if(this.getCurrentViewName()===t)return;let i=this.canvas.getBoundingClientRect(),n=Math.max(40,i.width*.1),o=Math.max(40,i.height*.1),c={rect:{x:i.left+(i.width-n)/2,y:i.top+(i.height-o)/2,width:n,height:o},duration:e.duration??this.duration,ease:e.ease??this.ease,props:e.props??{}};await this._doZoomIn(t,c)}init(){return this._destroyed||this._initialized?Promise.resolve():this._initPromise?this._initPromise:!this.isValid||!this.canvas?(this.notify("init() cannot run: instance is invalid or canvas element was not found.","error"),Promise.resolve()):(this._initPromise=this._runNavigation(()=>this._initialize()).finally(()=>{this._initPromise=null}),this._initPromise)}async _initialize(){this.tracing("init()");let t=this.prefetcher,e=this._createViewContext();if(this.preload&&this.preload.length&&(await t.preloadEager(this.preload,null).catch(i=>{this.notify(`preload failed: ${i.message}`,"warn")}),this._destroyed))return;let s;try{let i=await t.get(this.initialView,e);if(this._destroyed){C(i);return}if(s=await dt(i,this.initialView,this.canvas,!0,this.views,this.componentContext),this._destroyed){C(s),s.remove();return}}catch(i){this.notify(`init() failed to resolve initial view "${this.initialView}": ${i.message}`,"error");return}if(this._emit("viewMounted",{viewName:this.initialView,node:s}),!this._destroyed){t.scanAndPrefetch(s,e),this.storeViews({zoomLevel:this.storedViews.length,scale:1,views:[{viewName:this.initialView,backwardState:{origin:"0 0",transform:""}}]}),this.currentStage=this.storedViews[this.storedViews.length-1],this._recordCanvasSize(),this._accessibility.sync(this.canvas),this._initialized=!0;for(let i of this._plugins)this._installPlugin(i)}}destroy(){if(!this._destroyed){this._destroyed=!0,this._emit("destroy"),this._cancelNavigation(),this._clearBlockEventsSafety(),this._clearTrackedTimeouts(),this._pendingTransitionComplete=null,this._resizeDebounceTimer&&(clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=null),this._unbindEvents(),this._removeNav(),this._cleanupLateralKeepAlive(),this._accessibility.destroy(),this.canvas&&C(this.canvas);for(let t of this.storedViews){let e=Vt(t);e&&C(e)}if(this.blockEvents=!1,this.storedViews=[],this.currentStage=null,this.lateralHistory=[],this.trace=[],this._hooks={},this.prefetcher?.destroy(),this.prefetcher=null,this.transitionDriver=null,this.canvas)for(let[t,e]of this._canvasAttributes||[])e===null?this.canvas.removeAttribute(t):this.canvas.setAttribute(t,e);this.isValid=!1}}async _doZoomIn(t,e){return this._runNavigation(()=>this._performZoomIn(t,e))}async _performZoomIn(t,e){if(this._emit("beforeZoomIn",{viewName:t}),this._destroyed)return;this.tracing("zoomIn()");let s=this.canvas,i=e.el;this._resetCanvasScroll(s);let o=(this.storedViews.length>0?this.storedViews[this.storedViews.length-1]:null)?.scale??1;this.tracing("getView()");let a=this._createViewContext(i?{...i.dataset}:e.props??{},i),c=i?.dataset?.deferred!==void 0?!0:this.deferred,l,f=null,h=()=>{C(f),C(l),l?.remove()};try{if(c){let w=await this.prefetcher.get(t,a);if(this._destroyed){C(w);return}for(f=document.createDocumentFragment();w.firstChild;)f.appendChild(w.firstChild);l=await dt(w,t,s,!1,{},this.componentContext)}else{let w=await this.prefetcher.get(t,a);if(this._destroyed){C(w);return}this.prefetcher.scanAndPrefetch(w,a),l=await dt(w,t,s,!1,this.views,this.componentContext)}}catch(w){h(),this.notify(`zoomIn aborted: failed to resolve view "${t}": ${w.message}`,"error");return}if(!l){h();return}if(this._destroyed){h();return}if(c||this._emit("viewMounted",{viewName:t,node:l}),this._destroyed)return;i&&i.classList.add("zoomed");let u=s.getBoundingClientRect(),d=u.left,v=u.top,m=i?(()=>{let w=i.getBoundingClientRect();return{x:w.x,y:w.y,width:w.width,height:w.height}})():e.rect,p=i?i.dataset.withDuration||this.duration:e.duration??this.duration,y=i?i.dataset.withEase||this.ease:e.ease??this.ease,g=i?i.dataset.withCover||this.cover:e.cover??this.cover,x=i?parseInt(i.dataset.withStagger,10)||this.stagger:e.stagger??this.stagger,b=s.querySelector(".is-current-view"),_=s.querySelector(".is-previous-view"),S=s.querySelector(".is-last-view");if(!b){this.notify("zoomIn aborted: no current view found in canvas. Call init() before navigating and keep Zumly view classes intact.","error"),i&&i.classList.remove("zoomed"),h();return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],Ct(l),S&&(Ct(S),s.removeChild(S));let O,A,E,T,P,B,z,D=b.style.transform,N=b.style.transformOrigin,I=_?_.style.transform:null,F=_?_.style.transformOrigin:null;try{b.classList.replace("is-current-view","is-previous-view"),_&&_.classList.replace("is-previous-view","is-last-view");let w=l.getBoundingClientRect(),L=b.getBoundingClientRect(),X=null,Yt=null,bt=null;_&&(X=_.getBoundingClientRect(),bt=_.querySelector(".zoomed"),Yt=bt&&bt.getBoundingClientRect?bt.getBoundingClientRect():X);let _t={left:d,top:v},Kt={width:u.width,height:u.height},Ut={width:w.width,height:w.height},Gt=St(m.width,m.height,w.width,w.height,g);z=Gt.scale;let He=Gt.scaleInv;O=Ft(m,_t,Ut,He),E=b.style.transform;let Qt=ae(m,L);T=le(Kt,m,L,z,this.parallax);let Jt=nt(N||"0 0"),st=Y(E||""),te=nt(Qt),rt=Y(T.transform),ee=m;if(i&&(ee=mt(m,L,Jt,st.tx,st.ty,st.scale,te,rt.tx,rt.ty,rt.scale)),A=oe(ee,_t,Ut),_){P=_.style.transform;let De=mt(L,L,Jt,st.tx,st.ty,st.scale,te,rt.tx,rt.ty,rt.scale),Fe=fe(T.x,T.y,_t,z,o),se=nt(F||"0 0"),Mt=Y(P||""),Ht=Y(Fe),Ve=mt(Yt,X,se,Mt.tx,Mt.ty,Mt.scale,se,Ht.tx,Ht.ty,Ht.scale);B=ce({canvasRect:Kt,canvasOffset:_t,triggerRect:m,previousViewRectAtBaseTransform:L,lastViewZoomedElementRect:Ve,previousViewRectWithPreviousAtEndTransform:De,scale:z,preScale:o,parallax:this.parallax})}l.style.transform=O,b.style.transformOrigin=Qt}catch(w){this.notify(`zoomIn geometry computation failed: ${w.message}. Aborting zoom.`,"error"),this.debug&&console.error("Zumly _doZoomIn error:",w),b.style.transform=D,b.style.transformOrigin=N,b.classList.contains("is-previous-view")&&b.classList.replace("is-previous-view","is-current-view"),_&&(_.style.transform=I,_.style.transformOrigin=F,_.classList.contains("is-last-view")&&_.classList.replace("is-last-view","is-previous-view")),h(),S&&s.prepend(S),i&&i.classList.remove("zoomed"),yt(b),yt(_),yt(S);return}let M=pt(l.dataset.viewName,{origin:l.style.transformOrigin,duration:p,ease:y,transform:O},{origin:l.style.transformOrigin,duration:p,ease:y,transform:A}),wt=pt(b.dataset.viewName,{origin:b.style.transformOrigin,duration:p,ease:y,transform:E},{origin:b.style.transformOrigin,duration:p,ease:y,transform:T.transform}),ht=_?pt(_.dataset.viewName,{origin:_.style.transformOrigin,duration:p,ease:y,transform:P},{origin:_.style.transformOrigin,duration:p,ease:y,transform:B}):null,U=S?he(S):null,W=ue(this.storedViews.length,M,wt,ht,U);W.scale=z,W.stagger=x||0,this.storeViews(W),this.currentStage=this.storedViews[this.storedViews.length-1],this.tracing("setCSSVariables()");let It=this._resolveEffects(i);this._applyEffects(b,_,It,p,y);let ut=this._resolveHideTrigger(i);this._applyHideTrigger(i,l,ut,p,y),ut&&(W.hideTriggerMode=ut);let $t={type:"zoomIn",currentView:l,previousView:b,lastView:_,currentStage:this.currentStage,duration:p,ease:y},Zt=async()=>{if(c&&f&&l){if(l.appendChild(f),this.prefetcher.scanAndPrefetch(l,a),typeof this.views[t]=="object"&&typeof this.views[t].mounted=="function")try{await this.views[t].mounted()}catch(w){this.notify(`deferred view mounted() failed: ${w.message}`,"error")}if(this._destroyed)return;this._emit("viewMounted",{viewName:t,node:l})}this._destroyed||(this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterZoomIn",{viewName:t,zoomLevel:this.zoomLevel()}),this.tracing("ended"))};await this._runNavigationTransition($t,Zt),this._destroyed&&f&&C(f)}async zoomIn(t){this._destroyed||t?.dataset?.to&&await this._doZoomIn(t.dataset.to,{el:t})}async _doLateral(t,e=!1,s={}){return this._runNavigation(()=>this._performLateral(t,e,s))}async _performLateral(t,e=!1,s={}){if(!this.isValid||!this.canvas)return;if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`goTo("${t}", { mode: 'lateral' }): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}let i=this.canvas.querySelector(".is-current-view");if(!i)return;let n=i.dataset?.viewName;if(n===t||(this._emit("beforeLateral",{viewName:t,from:n,isBack:e}),this._destroyed))return;let o=this.lateralNav&&this.lateralNav.keepAlive,a=null;if(!e){this.lateralHistory=this.lateralHistory||[];let w=this.storedViews[this.storedViews.length-1];a={name:n,stage:this._copyLateralStage(w),node:o?i:null},a.entry=a.stage.views[0]}this.tracing("lateral()");let c=s.duration??this.duration,l=s.ease??this.ease,f=this.canvas.querySelector(".is-previous-view"),h=this.canvas.querySelector(".is-last-view"),u=null,d=null;if(o&&(e&&s.keepAliveNode?d=s.keepAliveNode:d=this.canvas.querySelector(`.is-lateral-hidden[data-view-name="${t}"]`)),d){if(d.style.display="",d.style.opacity="",d.classList.remove("is-lateral-hidden","zoom-lateral-out"),d.classList.add("is-new-current-view","has-no-events"),u=d,!e&&this.lateralHistory){let w=this.lateralHistory.findIndex(L=>L.node===d);w!==-1&&this.lateralHistory.splice(w,1)}}else{let w=()=>{e&&this.lateralHistory.push({name:t,entry:s.savedEntry,stage:s.savedStage,node:s.keepAliveNode??null})},L=this._createViewContext(s.props??{});try{let X=await this.prefetcher.get(t,L);if(this._destroyed){C(X);return}this.prefetcher.scanAndPrefetch(X,L),u=await dt(X,t,this.canvas,!1,this.views,this.componentContext)}catch(X){this.notify(`lateral navigation aborted: failed to resolve view "${t}": ${X.message}`,"error"),w();return}if(!u){w();return}if(this._destroyed){C(u),u.remove();return}if(this._emit("viewMounted",{viewName:t,node:u}),this._destroyed)return}let v=i.style.transform||"",m=this.storedViews[this.storedViews.length-1];u.style.transform="",u.style.transformOrigin="0 0";let p=new Map,y=w=>(p.has(w)||p.set(w,w.getBoundingClientRect()),p.get(w)),g=y(u),x=y(i),b=y(this.canvas),_=b.width/this.canvas.offsetWidth||1,S=b.height/this.canvas.offsetHeight||1,O=f?f.querySelectorAll(".zoom-me[data-to]"):[],A,E;for(let w of O)if(!A&&w.dataset.to===n&&(A=w),!E&&w.dataset.to===t&&(E=w),A&&E)break;let T=0,P=0,B=this._declaredSiblings(),z=B?B.indexOf(n):-1,D=B?B.indexOf(t):-1;if(z!==-1&&D!==-1)T=(z-D)*b.width*.15;else if(f)if(A&&E){let w=y(A),L=y(E);T=w.left+w.width/2-(L.left+L.width/2),P=w.top+w.height/2-(L.top+L.height/2)}else T=b.width*.15;let N=f?{transformStart:f.style.transform||"",transformEnd:this._computeLateralBackTransform(f.style.transform||"",T,P)}:null,I=h&&m.views[2]?{transformStart:h.style.transform||"",transformEnd:this._computeLateralBackTransform(h.style.transform||"",T*.7,P*.7)}:null,F=m.views[0],M=this._computeLateralBackTransform("",(x.x-g.x+(x.width-g.width)/2)/_,(x.y-g.y+(x.height-g.height)/2)/S),wt=Y(F.backwardState.transform||"").scale,ht=this._computeLateralBackTransform(F.backwardState.transform||"",(x.width-g.width)*wt/(2*_),(x.height-g.height)*wt/(2*S)),U=f?.querySelector(".zoomed");if(E&&N&&!(e&&s.savedStage)){let w=this._lateralTargetGeometry(u,E,f,h,m,{measure:y,outgoingView:i,canvasRect:b,sx:_,sy:S});w&&(M=w.currentEnd,ht=w.currentBack,N.transformEnd=w.previousEnd,I&&w.lastEnd&&(I.transformEnd=w.lastEnd),m.scale=w.scale)}if(e&&s.savedStage){Object.assign(m,this._copyLateralStage(s.savedStage)),M=m.views[0].forwardState?.transform||"",ht=m.views[0].backwardState.transform,N&&(N.transformEnd=m.views[1].forwardState.transform),I&&(I.transformEnd=m.views[2].forwardState.transform);let w=et(N?.transformStart||v),L=et(N?.transformEnd||M);T=L.tx-w.tx,P=L.ty-w.ty}else m.views[0]=pt(t,{origin:"0 0",duration:c,ease:l,transform:ht},{origin:"0 0",duration:c,ease:l,transform:M});this.currentStage=m,a&&this.lateralHistory.push(a),U?.classList.remove("zoomed");let W=E?this._resolveHideTrigger(E):!1;m.hideTriggerMode=W,E&&(E.classList.add("zoomed"),this._applyHideTrigger(E,u,W,c,l,!1),W&&E.classList.add("z-trigger-hidden")),Ct(u),N&&m.views[1]&&(m.views[1].forwardState={...m.views[1].forwardState,transform:N.transformEnd}),I&&m.views[2]&&(m.views[2].forwardState={...m.views[2].forwardState,transform:I.transformEnd});let It=this._computeLateralBackTransform(M,-T,-P),ut=this._computeLateralBackTransform(v,T,P),$t={type:"lateral",currentView:u,previousView:i,lastView:h||null,backView:f||null,backViewState:N,lastViewState:I,incomingTransformStart:It,incomingTransformEnd:M,outgoingTransform:v,outgoingTransformEnd:ut,currentStage:this.currentStage,duration:c,ease:l,canvas:this.canvas,slideDeltaX:T,slideDeltaY:P,keepAlive:o&&!e?o:!1},Zt=()=>{U&&U!==E&&(U.classList.remove("z-trigger-hidden","z-trigger-fade","z-trigger-fade-reverse"),U.style.removeProperty("--zoom-duration"),U.style.removeProperty("--zoom-ease")),W==="fade"&&E.classList.remove("z-trigger-hidden"),o&&!e&&(i.classList.remove("is-current-view","is-new-current-view","has-no-events"),i.classList.add("is-lateral-hidden"),o!=="visible"?i.style.display="none":(i.style.transform=v,i.style.opacity="")),this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterLateral",{viewName:t,from:n,isBack:e}),this.tracing("ended")};return this._runNavigationTransition($t,Zt)}_copyLateralStage(t){return{...t,views:t.views.map(e=>({...e,...e.backwardState&&{backwardState:{...e.backwardState}},...(e.forwardState||e.backwardState)&&{forwardState:{...e.forwardState||e.backwardState}}}))}}_lateralTargetGeometry(t,e,s,i,n,o){let{measure:a,outgoingView:c,canvasRect:l,sx:f,sy:h}=o,u=z=>{let D=a(z);return{x:(D.x-l.x)/f,y:(D.y-l.y)/h,width:D.width/f,height:D.height/h}},d=u(t),v=u(c),m=u(s),p=u(e);if(!d.width||!d.height||!p.width||!p.height)return null;let y=Y(s.style.transform||""),g=nt(s.style.transformOrigin||"0 0"),x=e.dataset.withCover||this.cover,b=St(p.width,p.height,d.width,d.height,x).scale,_=y.scale*b,S=(z,D,N,I,F,M)=>mt(z,D,N,I.tx,I.ty,I.scale,F,M.tx,M.ty,M.scale),O=S(p,m,g,y,g,{...y,scale:_}),A={tx:y.tx+v.x+v.width/2-O.x-O.width/2,ty:y.ty+v.y+v.height/2-O.y-O.height/2,scale:_},E=z=>`translate(${z.tx}px, ${z.ty}px) scale(${z.scale})`,T=S(p,m,g,y,{x:0,y:0},Y(n.views[1].backwardState.transform||"")),P=St(T.width,T.height,d.width,d.height,x).scaleInv,B={currentEnd:`translate(${v.x-d.x+(v.width-d.width)/2}px, ${v.y-d.y+(v.height-d.height)/2}px)`,currentBack:Ft(T,{left:d.x,top:d.y},d,P),previousEnd:E(A),scale:_};if(i&&n.views[2]){let z=u(i),D=nt(i.style.transformOrigin||"0 0"),N=Y(i.style.transform||""),I=S(m,m,g,y,g,A),F={...N,scale:N.scale*b},M=S(z,z,D,N,D,F);F.tx+=I.x+b*(z.x-m.x)-M.x,F.ty+=I.y+b*(z.y-m.y)-M.y,B.lastEnd=E(F)}return B}_computeLateralBackTransform(t,e,s){let i=et(t);return i.matched?`translate(${i.tx+e}px, ${i.ty+s}px) ${i.rest}`.trim():`translate(${e}px, ${s}px) ${t}`.trim()}zoomOut(){return this._runNavigation(()=>this._performZoomOut())}_performZoomOut(){if(this._emit("beforeZoomOut",{zoomLevel:this.zoomLevel()}),this._destroyed)return;this.tracing("zoomOut()");let t=this.canvas;this._resetCanvasScroll(t);let e=t.querySelector(".is-current-view"),s=t.querySelector(".is-previous-view");if(!e||!s){this.notify("zoomOut: current or previous view not found (animation may still be running)","warn");return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],this.currentStage=this.storedViews[this.storedViews.length-1];let i=t.querySelector(".is-last-view");this.tracing("setCSSVariables()");let n=this.currentStage.views[0]?.forwardState?.duration??this.duration,o=this.currentStage.views[0]?.forwardState?.ease??this.ease,a=s.querySelector(".zoomed");a&&a.classList.remove("zoomed");let c=this.currentStage.hideTriggerMode;c&&a&&this._restoreHideTrigger(a,c,n,o),c==="fade"?(e.classList.remove("z-view-fade-in"),e.style.setProperty("--zoom-duration",n),e.style.setProperty("--zoom-ease",o),e.classList.add("z-view-fade-out")):(e.classList.remove("z-view-fade-in"),e.style.removeProperty("opacity")),this._removeEffect(s),s.classList.replace("is-previous-view","is-current-view"),i!==null&&(i.classList.contains("has-effect")&&this.effects[0]!=="none"&&i.style.setProperty("--z-effect-filter",this.effects[0]),i.classList.replace("is-last-view","is-previous-view"),i.classList.remove("hide"),vt(i));let l=Vt(this.currentStage);if(l){t.prepend(l);let u=t.querySelector(".z-view:first-child");u&&(vt(u),u.classList.add("hide"))}let f={type:"zoomOut",currentView:e,previousView:s,lastView:i,currentStage:this.currentStage,duration:n,ease:o,canvas:t},h=()=>{this.blockEvents=!1,this._onTransitionComplete(),this.storedViews.pop(),this._updateNav(),this._emit("afterZoomOut",{zoomLevel:this.zoomLevel()}),this.tracing("ended")};return this._runNavigationTransition(f,h)}onZoom(t){if(this._destroyed||t.type==="mouseup"&&t.button!==0||t.type==="click"&&!this.inputs.keyboard||t.type==="mouseup"&&!this.inputs.click||t.type==="touchend"&&!this.inputs.touch)return;let e=t.target;if(e.closest?.("[inert]")||e.closest(".z-depth-nav")||e.closest(".z-lateral-nav"))return;let s=e.classList.contains("zoom-me")||e.closest(".zoom-me");if(!this.blockEvents&&s&&!this.touching){this.tracing("onZoom() \u2192 zoomIn"),t.preventDefault(),t.stopPropagation();let i=e.classList.contains("zoom-me")?e:e.closest(".zoom-me");this.zoomIn(i);return}if(this.storedViews.length>1&&!this.blockEvents&&!s&&!this.touching){let i=this.canvas.querySelector(".is-current-view");if(i&&i.contains(e))return;let n=this._findSiblingTriggerAtPoint(t.clientX,t.clientY);if(n){this.tracing("onZoom() \u2192 lateral"),t.stopPropagation(),this._doLateral(n.dataset.to);return}this.tracing("onZoom() \u2192 zoomOut"),t.stopPropagation(),this.zoomOut()}}_findSiblingTriggerAtPoint(t,e){let s=this.canvas.querySelector(".is-previous-view");if(!s)return null;let n=this.canvas.querySelector(".is-current-view")?.dataset?.viewName;if(!n)return null;let o=s.querySelectorAll(".zoom-me[data-to]");for(let a of o){if(a.dataset.to===n)continue;let c=a.getBoundingClientRect();if(t>=c.left&&t<=c.right&&e>=c.top&&e<=c.bottom)return a}return null}_getSiblings(){let e=this.canvas.querySelector(".is-current-view")?.dataset?.viewName,s=this._declaredSiblings();if(s&&s.indexOf(e)!==-1)return{siblings:s,currentIndex:s.indexOf(e)};let i=this.canvas.querySelector(".is-previous-view");if(!i)return{siblings:[],currentIndex:-1};let n=i.querySelectorAll(".zoom-me[data-to]"),o=[];for(let c of n)c.dataset.to&&o.push(c.dataset.to);let a=o.indexOf(e);return{siblings:o,currentIndex:a}}_declaredSiblings(){let t=this.lateralNav&&typeof this.lateralNav=="object"?this.lateralNav.siblings:null;if(!t)return null;if(Array.isArray(t))return t;let e=this.canvas.querySelector(".is-previous-view")?.dataset?.viewName;return e&&Array.isArray(t[e])?t[e]:null}_updateNav(){if(this._destroyed)return;let t=this.storedViews.length-1,e=this.canvas.querySelector(":scope > .z-view.is-current-view"),s=!!this.depthNav&&t>=1&&!e?.querySelector(".z-depth-nav"),i=this.lateralNav?this._getSiblings():null;i?.siblings.length<2&&(i=null),i&&this.lateralNav.mode==="auto"&&t>=1&&e&&e.offsetWidth>=this.canvas.offsetWidth&&e.offsetHeight>=this.canvas.offsetHeight&&(i=null),this._updateDepthNav(s),this._updateLateralNav(i)}_updateDepthNav(t){if(t===void 0){let n=this.canvas.querySelector(":scope > .z-view.is-current-view");t=!!this.depthNav&&this.storedViews.length>1&&!n?.querySelector(".z-depth-nav")}if(!t){this._depthNavElement?.remove();return}let e=this.depthNav.position||"bottom-left",s=this._depthNavElement;if(!s){s=document.createElement("div");let n=document.createElement("button");n.className="z-nav-back",n.setAttribute("aria-label","Zoom out (go back)"),n.innerHTML="‹",n.type="button",n.addEventListener("click",o=>{o.stopPropagation(),!this._destroyed&&s.parentNode===this.canvas&&!this.blockEvents&&this.storedViews.length>1&&this.zoomOut()}),s.appendChild(n),this._depthNavElement=s}let i="z-depth-nav z-depth-nav--"+e;s.className!==i&&(s.className=i),s.parentNode!==this.canvas&&this.canvas.appendChild(s)}_updateLateralNav(t){if(t===void 0&&(t=this.lateralNav?this._getSiblings():null,t?.siblings.length<2&&(t=null),t&&this.lateralNav.mode==="auto"&&this.storedViews.length>1)){let l=this.canvas.querySelector(":scope > .z-view.is-current-view");l&&l.offsetWidth>=this.canvas.offsetWidth&&l.offsetHeight>=this.canvas.offsetHeight&&(t=null)}if(!t){this._lateralNavState?.element.remove();return}let{siblings:e,currentIndex:s}=t,i=this.lateralNav.position||"bottom-center",n=!!this.lateralNav.arrows,o=!!this.lateralNav.dots,a=this._lateralNavState;if(!a||a.arrows!==n||a.dots!==o||a.siblings.length!==e.length||a.siblings.some((l,f)=>l!==e[f])){a?.element.remove();let l=document.createElement("div");a={element:l,siblings:[...e],currentIndex:-1,arrows:n,dots:o,dotButtons:[]};let f=(h,u,d)=>{let v=document.createElement("button");return v.className="z-nav-arrow z-nav-"+h,v.setAttribute("aria-label",u),v.innerHTML=d,v.type="button",v};if(n&&(a.prevButton=f("prev","Previous sibling view","‹"),l.appendChild(a.prevButton)),o){let h=document.createElement("div");h.className="z-nav-lateral-dots";for(let u of e){let d=document.createElement("button");d.className="z-nav-dot z-nav-lat-dot",d.setAttribute("aria-label",`Go to ${u}`),d.dataset.to=u,d.type="button",a.dotButtons.push(d),h.appendChild(d)}l.appendChild(h)}n&&(a.nextButton=f("next","Next sibling view","›"),l.appendChild(a.nextButton)),l.addEventListener("click",h=>{let u=h.target.closest?.("button");if(!u||!l.contains(u))return;h.stopPropagation();let d=this._lateralNavState;if(this._destroyed||this.blockEvents||d?.element!==l||l.parentNode!==this.canvas)return;let v=u===d.prevButton?d.currentIndex-1:u===d.nextButton?d.currentIndex+1:d.dotButtons.indexOf(u);v>=0&&v<d.siblings.length&&v!==d.currentIndex&&this._doLateral(d.siblings[v])}),this._lateralNavState=a}if(a.currentIndex!==s){let l=a.dotButtons[a.currentIndex];l?.classList.remove("is-active"),l?.removeAttribute("aria-current");let f=a.dotButtons[s];f?.classList.add("is-active"),f?.setAttribute("aria-current","true"),a.currentIndex=s}a.prevButton&&a.prevButton.disabled!==s<=0&&(a.prevButton.disabled=s<=0),a.nextButton&&a.nextButton.disabled!==s>=e.length-1&&(a.nextButton.disabled=s>=e.length-1);let c="z-lateral-nav z-lateral-nav--"+i;a.element.className!==c&&(a.element.className=c),a.element.parentNode!==this.canvas&&this.canvas.appendChild(a.element)}_removeNav(){this._depthNavElement?.remove(),this._lateralNavState?.element.remove(),this._depthNavElement=null,this._lateralNavState=null}_cleanupLateralKeepAlive(){if(!this.canvas)return;let t=this.canvas.querySelectorAll(".is-lateral-hidden");for(let e of t)this._accessibility.restore(e),C(e),e.remove()}onKeyDown(t){if(this._destroyed||!this.inputs.keyboard||t.defaultPrevented||jt(t.target))return;let e=t.target.closest?.(".zoom-me[data-to]");!e||kt(e)||e.closest("[inert]")||(t.key===" "||t.key==="Enter")&&(t.preventDefault(),t.key==="Enter"&&!t.repeat&&!this.blockEvents&&this.zoomIn(e))}onKeyUp(t){if(this._destroyed||!this.inputs.keyboard||t.defaultPrevented||jt(t.target)||t.target.closest?.("[inert]"))return;let e=t.target.closest?.(".zoom-me[data-to]");if(t.key===" "&&e&&!kt(e)){t.preventDefault(),this.blockEvents||this.zoomIn(e);return}this.tracing("onKeyUp()"),(t.key==="ArrowLeft"||t.key==="ArrowDown")&&(t.preventDefault(),this.storedViews.length>1&&!this.blockEvents?this.zoomOut():this.notify(`is on level zero. Can't zoom out. Trigger: ${t.key}`,"warn"))}onWheel(t){this._destroyed||this.inputs.wheel&&(this._isInsideScrollable(t.target,t.deltaY)||(t.preventDefault(),!(this.blockEvents||this._wheelCooldown)&&t.deltaY>0&&this.storedViews.length>1&&(this.tracing("onWheel() \u2192 zoomOut"),this._wheelCooldown=!0,this._setTrackedTimeout(()=>{this._wheelCooldown=!1},500),this.zoomOut())))}_isInsideScrollable(t,e){let s=t,i=this.canvas.querySelector(".is-current-view");for(;s&&s!==this.canvas;){if(s===i||i&&i.contains(s)){let{overflowY:n}=window.getComputedStyle(s);if((n==="auto"||n==="scroll")&&(e>0?s.scrollTop+s.clientHeight<s.scrollHeight-1:s.scrollTop>0))return!0}s=s.parentElement}return!1}onTouchStart(t){this._destroyed||this.inputs.touch&&(this.tracing("onTouchStart()"),this.touching=!0,this.touchstartX=t.changedTouches[0].screenX,this.touchstartY=t.changedTouches[0].screenY)}onTouchEnd(t){this._destroyed||this.inputs.touch&&(this.blockEvents||(this.tracing("onTouchEnd()"),this.touchendX=t.changedTouches[0].screenX,this.touchendY=t.changedTouches[0].screenY,this.handleGesture(t)),this.touching=!1)}handleGesture(t){if(t.target.closest?.(".z-depth-nav, .z-lateral-nav"))return;t.stopPropagation(),this.tracing("handleGesture()");let e=this.touchendX-this.touchstartX,s=this.touchendY-this.touchstartY,i=Math.abs(e)<10&&Math.abs(s)<10;e<-30&&(this.storedViews.length>1&&!this.blockEvents?(this.tracing("swipe left"),this.zoomOut()):this.notify("is on level zero. Can't zoom out. Trigger: Swipe left","warn"));let n=t.target.classList.contains("zoom-me")?t.target:t.target.closest(".zoom-me");i&&!this.blockEvents&&n&&this.touching&&(this.touching=!1,this.tracing("tap"),t.preventDefault(),this.zoomIn(n)),i&&this.storedViews.length>1&&!this.blockEvents&&!n&&t.target.closest(".is-current-view")===null&&this.touching&&(this.touching=!1,this.tracing("tap"),this.zoomOut())}};var vs={separator:"/",prefix:"/"};function Wt(r,t){let e=[];for(let s of r.storedViews){let i=s.views&&s.views[0];i&&i.viewName&&e.push(i.viewName)}return e.join(t)}function ys(r,t){let e=window.location.hash.slice(1);return e.startsWith(r)&&(e=e.slice(r.length)),e?e.split(t).filter(Boolean):[]}var Xt={install(r,t){let e=Object.assign({},vs,t),s=e.separator,i=e.prefix,n=!1,o=!1,a=null,c=!1;function l(v){if(n)return;let m=Wt(r,s),p="#"+i+m;window.location.hash!==p&&(n=!0,window.history[v](null,"",p),n=!1)}function f(){l("pushState")}function h(){l("replaceState")}r.on("afterZoomIn",f),r.on("afterLateral",f),r.on("afterZoomOut",h);async function u(){if(!(o||c)){o=!0,n=!0;try{for(;a&&!c;){let v=a;if(a=null,await r._navigationTask?.promise,c)return;if(a)continue;let m=Wt(r,s).split(s).filter(Boolean);if(v.join(s)!==m.join(s)){if(v.length>m.length){window.history.back();continue}for(;m.length>v.length&&m.length>1;){let p=m.length;if(await r.zoomOut(),c)return;if(m=Wt(r,s).split(s).filter(Boolean),a||m.length>=p)break}if(!a&&v.length===m.length&&v.length>0){let p=v[v.length-1];if(p!==m[m.length-1]){let y=r.lateralHistory||[],g=b=>typeof b=="object"?b?.name:b,x=y.map(g).lastIndexOf(p);if(x!==-1)for(;r.lateralHistory.length>x;){let b=r.lateralHistory.length;if(await r.back(),c||a||r.lateralHistory.length>=b)break}else await r.goTo(p,{mode:"lateral"})}}}}}finally{n=!1,o=!1}}}function d(){c||(a=ys(i,s),u())}window.addEventListener("popstate",d),h(),r.on("destroy",function(){c=!0,a=null,r.off("afterZoomIn",f),r.off("afterLateral",f),r.off("afterZoomOut",h),window.removeEventListener("popstate",d)})}};ft.Router=Xt;var gs=ft;
|
package/dist/zumly.css
CHANGED
|
@@ -14,6 +14,20 @@
|
|
|
14
14
|
.zumly-canvas:focus {
|
|
15
15
|
outline: none;
|
|
16
16
|
}
|
|
17
|
+
.zumly-canvas:focus-visible,
|
|
18
|
+
.zumly-canvas .zoom-me:focus-visible {
|
|
19
|
+
outline: 2px solid currentColor;
|
|
20
|
+
outline-offset: 3px;
|
|
21
|
+
}
|
|
22
|
+
@media (prefers-reduced-motion: reduce) {
|
|
23
|
+
.zumly-canvas .z-view,
|
|
24
|
+
.zumly-canvas .zoom-me,
|
|
25
|
+
.zumly-canvas .z-nav-dot {
|
|
26
|
+
transition-duration: 0s !important;
|
|
27
|
+
animation-duration: 0s !important;
|
|
28
|
+
animation-delay: 0s !important;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
17
31
|
.z-view {
|
|
18
32
|
position: absolute;
|
|
19
33
|
contain: strict;
|
|
@@ -21,6 +35,7 @@
|
|
|
21
35
|
}
|
|
22
36
|
.z-view.is-current-view {
|
|
23
37
|
cursor: default;
|
|
38
|
+
content-visibility: visible;
|
|
24
39
|
}
|
|
25
40
|
.z-view.is-previous-view,
|
|
26
41
|
.z-view.is-last-view,
|