UNPKG

zircle

Version:

Zircle's circular components, rebuilt with Orbit and Zumly for the web. No Vue required.

4,376 lines 206 kB
/*! Zircle, Orbit, and Zumly are MIT licensed. See LICENSES.txt for copyright and permission notices. */

// node_modules/@zumer/orbit/dist/orbit.mjs
var STATE = Symbol.for("zumer.orbit.layout.state.v1");
var REGISTRY = Symbol.for("zumer.orbit.layout.registry.v1");
var PROBE = Symbol.for("zumer.orbit.layout.probe.v1");
var VISUALS = "o-arc, o-progress";
var OBSERVE = { subtree: true, childList: true, characterData: true, attributes: true, attributeOldValue: true };
function orbitNumber(element) {
  var _a;
  for (const token of element.classList || []) {
    if (/^orbit-\d+$/.test(token)) return Number(token.slice(6));
  }
  return ((_a = element.classList) == null ? void 0 : _a.contains("orbit")) ? null : void 0;
}
function setLayoutProperty(element, name, value) {
  const text = String(value);
  if (element.style.getPropertyValue(name) !== text) element.style.setProperty(name, text);
}
function cssNumber(element, value, fallback = 0, type = "number") {
  const raw = String(value || "").trim();
  if (!raw) return fallback;
  if (type === "number" && /^[+-]?(?:\d+\.?\d*|\.\d+)$/.test(raw)) return Number(raw);
  const angle = raw.match(/^([+-]?(?:\d+\.?\d*|\.\d+))(deg|rad|grad|turn)?$/);
  if (type === "angle" && angle) {
    return Number(angle[1]) * ({ deg: 1, rad: 180 / Math.PI, grad: 0.9, turn: 360 }[angle[2]] || 1);
  }
  const doc = element.ownerDocument;
  if (!(doc == null ? void 0 : doc.documentElement)) return fallback;
  let probe = doc[PROBE];
  if (!probe) {
    probe = doc.createElement("span");
    probe.setAttribute("data-orbit-measure", "");
    probe.setAttribute("aria-hidden", "true");
    probe.style.cssText = "all:initial!important;position:fixed!important;visibility:hidden!important;pointer-events:none!important;width:0!important;height:0!important;overflow:hidden!important;";
    doc.documentElement.appendChild(probe);
    Object.defineProperty(doc, PROBE, { value: probe, configurable: true });
  }
  const property = type === "angle" ? "rotate" : "scale";
  probe.style.removeProperty(property);
  probe.style.setProperty(property, raw, "important");
  if (!probe.style.getPropertyValue(property)) return fallback;
  const computed = doc.defaultView.getComputedStyle(probe).getPropertyValue(property);
  const resolved = parseFloat(computed);
  return Number.isFinite(resolved) ? resolved : fallback;
}
function group(element) {
  if (element.localName === "o-arc") return "arc";
  for (const name of ["satellite", "vector", "side"]) if (element.classList.contains(name)) return name;
  return null;
}
function layoutRing(ring) {
  const counts = { arc: 0, satellite: 0, vector: 0, side: 0 };
  for (const child of ring.children) {
    const kind = group(child);
    if (kind) setLayoutProperty(child, "--o-layout-index", counts[kind]++ - (kind === "side" ? 1 : 0));
    else if (child.localName === "o-progress") setLayoutProperty(child, "--o-layout-index", 0);
  }
  const count = Math.max(counts.arc, counts.satellite, counts.vector, 1);
  const divisor = counts.side ? String(counts.side) : `max(1, ${count} - var(--o-fit-range, 0))`;
  setLayoutProperty(ring, "--o-layout-angle", `calc(var(--o-range, 360deg) / ${divisor})`);
}
function isScope(root) {
  return (root == null ? void 0 : root.nodeType) === 9 || (root == null ? void 0 : root.nodeType) === 11 && !!root.host;
}
function scopeFor(element) {
  var _a;
  if (isScope(element)) return element;
  const root = (_a = element == null ? void 0 : element.getRootNode) == null ? void 0 : _a.call(element);
  return isScope(root) ? root : null;
}
function composedContains(ancestor, node) {
  var _a, _b;
  for (let current = node; current; current = (_a = current.getRootNode) == null ? void 0 : _a.call(current).host) {
    if (ancestor === current || ((_b = ancestor.contains) == null ? void 0 : _b.call(ancestor, current))) return true;
  }
  return false;
}
function registryFor(doc) {
  if (!doc[REGISTRY]) Object.defineProperty(doc, REGISTRY, {
    value: { states: /* @__PURE__ */ new Set() },
    configurable: true
  });
  return doc[REGISTRY];
}
function dispose(state) {
  if (state.disposed) return;
  state.disposed = true;
  state.view.cancelAnimationFrame(state.frame);
  state.observer.disconnect();
  state.resize.disconnect();
  for (const remove of state.listeners) remove();
  state.rings.clear();
  state.visuals.clear();
  state.dirty.clear();
  state.registry.states.delete(state);
  if (state.scope[STATE] === state) delete state.scope[STATE];
}
function pruneDisconnected(registry) {
  for (const state of registry.states) {
    if (state.scope.host && !state.scope.host.isConnected) dispose(state);
  }
}
function invalidateDescendants(state, target = state.scope) {
  for (const other of state.registry.states) {
    if (other !== state && other.scope.host && composedContains(target, other.scope.host)) {
      other.all = true;
      other.queue();
    }
  }
}
function hasLayoutStructure(node) {
  if (node.nodeType !== 1 || node.hasAttribute("data-orbit-measure")) return false;
  if (orbitNumber(node) !== void 0 || node.matches(".gravity-spot, o-arc, o-progress")) return true;
  return !!node.querySelector(".gravity-spot, .orbit, [data-orbit-ring], o-arc, o-progress");
}
function hasStylesheet(node) {
  return node.nodeType === 1 && (node.matches('style, link[rel~="stylesheet"]') || !!node.querySelector('style, link[rel~="stylesheet"]'));
}
function needsDiscovery(record, state) {
  if (record.type === "childList") {
    return [...record.addedNodes, ...record.removedNodes].some(hasLayoutStructure);
  }
  if (record.attributeName !== "class") return false;
  const element = record.target;
  return state.rings.has(element) || element.classList.contains("gravity-spot") || orbitNumber(element) !== void 0 || (record.oldValue || "").split(/\s+/).some((token) => token === "gravity-spot" || token === "orbit" || /^orbit-\d+$/.test(token));
}
function createState(scope) {
  const doc = scope.nodeType === 9 ? scope : scope.ownerDocument;
  const view = doc.defaultView;
  const registry = registryFor(doc);
  const state = {
    scope,
    doc,
    view,
    registry,
    rings: /* @__PURE__ */ new Set(),
    visuals: /* @__PURE__ */ new Set(),
    dirty: /* @__PURE__ */ new Set(),
    scan: true,
    all: true,
    frame: 0,
    disposed: false,
    listeners: []
  };
  const listen = (target, event, listener, options) => {
    target == null ? void 0 : target.addEventListener(event, listener, options);
    state.listeners.push(() => target == null ? void 0 : target.removeEventListener(event, listener, options));
  };
  const queue = () => {
    if (!state.disposed && !state.frame) state.frame = view.requestAnimationFrame(() => {
      state.frame = 0;
      state.flush();
    });
  };
  state.queue = queue;
  state.flush = () => flush(state);
  state.invalidate = (target = scope, includeDescendants = true) => {
    var _a, _b;
    if (includeDescendants && (target === scope || target === doc.documentElement || target === doc.head)) state.all = true;
    else {
      for (const ring of state.rings) if (ring === target || ring.contains(target) || includeDescendants && ((_a = target.contains) == null ? void 0 : _a.call(target, ring))) state.dirty.add(ring);
      for (const visual of state.visuals) if (visual === target || visual.contains(target) || includeDescendants && ((_b = target.contains) == null ? void 0 : _b.call(target, visual))) state.dirty.add(visual);
    }
    if (state.all || state.dirty.size || state.scan) queue();
  };
  state.observer = new view.MutationObserver((records) => {
    var _a, _b;
    if (records.some((record) => record.type === "childList")) pruneDisconnected(registry);
    if (state.disposed) return;
    for (const record of records) {
      const target = record.target.nodeType === 3 ? record.target.parentElement : record.target;
      if (!target || ((_a = target.hasAttribute) == null ? void 0 : _a.call(target, "data-orbit-measure"))) continue;
      const structural = needsDiscovery(record, state);
      if (structural) state.scan = true;
      const stylesheetChange = record.type === "childList" && [...record.addedNodes, ...record.removedNodes].some(hasStylesheet);
      if (stylesheetChange || ((_b = target.closest) == null ? void 0 : _b.call(target, "head, style")) || target.localName === "link") {
        state.all = true;
        invalidateDescendants(state);
      } else if (record.type === "attributes") invalidateDescendants(state, target);
      state.invalidate(target, record.type === "attributes" || structural);
    }
  });
  state.observer.observe(scope, OBSERVE);
  state.resize = new view.ResizeObserver((entries) => {
    for (const entry of entries) state.dirty.add(entry.target);
    queue();
  });
  const invalidateAll = () => {
    state.all = true;
    invalidateDescendants(state);
    queue();
  };
  if (scope === doc) {
    listen(view, "resize", invalidateAll);
    listen(doc.fonts, "loadingdone", invalidateAll);
  }
  listen(scope, "load", (event) => {
    if (event.target.localName === "link") invalidateAll();
  }, true);
  for (const event of ["pointerover", "pointerout", "focusin", "focusout"]) {
    listen(scope, event, (e) => {
      state.invalidate(e.target);
      invalidateDescendants(state, e.target);
    }, true);
  }
  Object.defineProperty(scope, STATE, { value: state, configurable: true });
  registry.states.add(state);
  queue();
  return state;
}
function ensureState(scope) {
  const doc = scope.nodeType === 9 ? scope : scope.ownerDocument;
  if (!(doc == null ? void 0 : doc.defaultView) || !doc.documentElement || scope.host && !scope.host.isConnected) return null;
  if (scope[STATE] && scope[STATE].doc !== doc) dispose(scope[STATE]);
  if (scope.host) {
    const parent = scopeFor(scope.host);
    if (parent) ensureState(parent);
  }
  return scope[STATE] || createState(scope);
}
function discover(state) {
  const nextRings = /* @__PURE__ */ new Set();
  const automaticCounts = /* @__PURE__ */ new Map();
  for (const ring of state.scope.querySelectorAll(".gravity-spot > *")) {
    const number = orbitNumber(ring);
    if (number === void 0) continue;
    let automatic = automaticCounts.get(ring.parentElement) || 0;
    if (ring.classList.contains("orbit")) automaticCounts.set(ring.parentElement, ++automatic);
    const resolved = number === null ? automatic : number;
    ring.setAttribute("data-orbit-ring", "");
    setLayoutProperty(ring, "--o-layout-number", resolved === 0 ? 1e-5 : resolved);
    nextRings.add(ring);
    state.dirty.add(ring);
    if (!state.rings.has(ring)) state.resize.observe(ring);
  }
  for (const old of state.rings) if (!nextRings.has(old)) {
    state.resize.unobserve(old);
    old.removeAttribute("data-orbit-ring");
    for (const name of ["--o-layout-number", "--o-layout-angle"]) old.style.removeProperty(name);
  }
  state.rings = nextRings;
  const nextVisuals = new Set(state.scope.querySelectorAll(VISUALS));
  for (const old of state.visuals) if (!nextVisuals.has(old)) state.resize.unobserve(old);
  for (const visual of nextVisuals) if (!state.visuals.has(visual)) {
    state.resize.observe(visual);
    state.dirty.add(visual);
  }
  state.visuals = nextVisuals;
  state.scan = false;
}
function flush(state) {
  var _a;
  if (state.disposed) return;
  if (state.scope.host && !state.scope.host.isConnected) {
    dispose(state);
    return;
  }
  state.observer.disconnect();
  try {
    if (state.scan) discover(state);
    const dirty = state.all ? /* @__PURE__ */ new Set([...state.rings, ...state.visuals]) : state.dirty;
    const visuals = /* @__PURE__ */ new Set();
    for (const target of dirty) {
      if (!target.isConnected) continue;
      if (state.rings.has(target)) {
        layoutRing(target);
        for (const visual of target.querySelectorAll(VISUALS)) visuals.add(visual);
      } else if (state.visuals.has(target)) visuals.add(target);
    }
    for (const visual of state.visuals) if (visuals.has(visual)) (_a = visual.update) == null ? void 0 : _a.call(visual);
    state.dirty = /* @__PURE__ */ new Set();
    state.all = false;
  } finally {
    if (!state.disposed) state.observer.observe(state.scope, OBSERVE);
  }
}
function requestLayout(element = globalThis.document) {
  var _a;
  const scope = scopeFor(element);
  if (!scope) return;
  const state = ensureState(scope);
  if (!state) return;
  if (((_a = element == null ? void 0 : element.matches) == null ? void 0 : _a.call(element, VISUALS)) && !state.visuals.has(element)) state.scan = true;
  state.invalidate(element || scope);
}
function refreshLayout(root = globalThis.document) {
  const scope = scopeFor(root);
  if (!scope) return;
  const state = ensureState(scope);
  if (!state) return;
  pruneDisconnected(state.registry);
  for (const current of state.registry.states) {
    if (current !== state && (!current.scope.host || !composedContains(root, current.scope.host))) continue;
    current.scan = true;
    current.all = true;
    current.view.cancelAnimationFrame(current.frame);
    current.frame = 0;
    current.flush();
  }
}
var OrbitBase = class extends (globalThis.HTMLElement || class {
}) {
  constructor() {
    super();
  }
  connectedCallback() {
    requestLayout(this);
  }
  disconnectedCallback() {
    if (this._textFrame) this.ownerDocument.defaultView.cancelAnimationFrame(this._textFrame);
    this._textFrame = 0;
  }
  readNumber(style, name, fallback = 0) {
    return cssNumber(this, style.getPropertyValue(name), fallback);
  }
  readAngle(style, name, fallback = 0) {
    return cssNumber(this, style.getPropertyValue(name), fallback, "angle");
  }
  getCommonAttributes(element) {
    var _a;
    const style = element.ownerDocument.defaultView.getComputedStyle(element);
    const measuredRadius = parseFloat(style.getPropertyValue("r"));
    const orbitRadius = Math.max(0, Number.isFinite(measuredRadius) ? measuredRadius : (((_a = element.parentElement) == null ? void 0 : _a.clientWidth) || 0) / 2);
    const orbitNumber2 = Math.max(1e-5, this.readNumber(style, "--o-orbit-number", 1));
    const size = Math.max(0, this.readNumber(style, "--o-size-ratio", 1));
    const strokeWidth = Math.max(0, this.readNumber(style, "--o-stroke-width", 1));
    const shape = element.getAttribute("shape") || "none";
    const arcHeight = Math.max(0, orbitRadius / orbitNumber2 * size - strokeWidth + 0.3);
    const arcHeightPercentage = orbitRadius > 0 ? Math.min(49.999, arcHeight * 25 / orbitRadius) : 0;
    let innerOuter = 0;
    if (element.classList.contains("outer-orbit")) {
      innerOuter = arcHeightPercentage;
    } else if (element.classList.contains("quarter-outer-orbit")) {
      innerOuter = arcHeightPercentage * -0.5;
    } else if (element.classList.contains("inner-orbit")) {
      innerOuter = arcHeightPercentage * -1;
    } else if (element.classList.contains("quarter-inner-orbit")) {
      innerOuter = arcHeightPercentage * 0.5;
    }
    const realRadius = 50 + innerOuter;
    return {
      orbitRadius,
      arcHeight,
      realRadius,
      arcAngle: 0,
      // Se sobrescribe en cada componente
      shape,
      arcHeightPercentage,
      orbitNumber: orbitNumber2,
      size,
      strokeWidth,
      style
    };
  }
  getProgressAngle(maxAngle, value, maxValue = 100) {
    if (!Number.isFinite(value) || !Number.isFinite(maxValue) || maxValue <= 0) return 0;
    return Math.min(1, Math.max(0, value / maxValue)) * Math.max(0, Math.min(360, maxAngle));
  }
  getControlPoint(x, y, x1, y1, direction = "clockwise") {
    const xm = (x + x1) / 2;
    const ym = (y + y1) / 2;
    const dx = x1 - x;
    const dy = y1 - y;
    if (direction === "clockwise") {
      return {
        xc: xm + dy * 0.4,
        yc: ym - dx * 0.4
      };
    }
    return {
      xc: xm - dy * 0.4,
      yc: ym + dx * 0.4
    };
  }
  arcPoint(radius, angle, radiusAdjustment = 0, angleOffsetDegrees = 0) {
    const adjustedRadius = radius + radiusAdjustment;
    const adjustedAngle = angle + angleOffsetDegrees * Math.PI / 180;
    return {
      x: 50 + adjustedRadius * Math.cos(adjustedAngle),
      y: 50 + adjustedRadius * Math.sin(adjustedAngle)
    };
  }
  calculateCommonArcParameters(arcAngle, radius, arcHeightPercentage, orbitNumber2, shape, strokeWidth, arcHeight, gap = 0) {
    const offset = Math.PI / 2;
    const fangle = Math.max(0, Math.min(359.999999, arcAngle)) * Math.PI / 180;
    const bigRadius = radius + arcHeightPercentage;
    const smallRadius = Math.max(1e-3, radius - arcHeightPercentage);
    const bigGap = Math.min(fangle * 0.49, (gap + strokeWidth * 1.25) / orbitNumber2 / bigRadius);
    const smallGap = Math.min(fangle * 0.49, (gap + strokeWidth * 1.25) / orbitNumber2 / smallRadius);
    const upperAngleStart = bigGap - offset;
    const upperAngleEnd = fangle - bigGap - offset;
    const innerAngleStart = smallGap - offset;
    const innerAngleEnd = fangle - smallGap - offset;
    const upperArcStart = this.arcPoint(bigRadius, upperAngleStart);
    const upperArcEnd = this.arcPoint(bigRadius, upperAngleEnd);
    const innerArcStart = this.arcPoint(smallRadius, innerAngleStart);
    const innerArcEnd = this.arcPoint(smallRadius, innerAngleEnd);
    const upperSweep = upperAngleEnd - upperAngleStart;
    const innerSweep = innerAngleEnd - innerAngleStart;
    const largeArcFlagUpper = upperSweep > Math.PI ? 1 : 0;
    const largeArcFlagInner = innerSweep > Math.PI ? 1 : 0;
    return {
      upperArcStart,
      upperArcEnd,
      innerArcStart,
      innerArcEnd,
      largeArcFlag: largeArcFlagUpper,
      // back-compat alias; prefer the two below
      largeArcFlagUpper,
      largeArcFlagInner,
      bigRadius,
      smallRadius,
      radius,
      upperAngleStart,
      upperAngleEnd,
      innerAngleStart,
      innerAngleEnd
    };
  }
  generatePathData(shape, params, arcHeight, orbitNumber2) {
    let d = "";
    switch (shape) {
      case "rounded":
        d = this.generateRoundedPath(params, arcHeight, orbitNumber2);
        break;
      case "circle":
      case "circle-a":
      case "bullet":
        d = this.generateCirclePath(params, shape);
        break;
      case "circle-b":
        d = this.generateCircleBPath(params, arcHeight, orbitNumber2);
        break;
      case "arrow":
        d = this.generateArrowPath(params, orbitNumber2);
        break;
      case "backslash":
      case "slash":
        d = this.generateSlashPath(params, shape, orbitNumber2);
        break;
      case "zigzag":
        d = this.generateZigzagPath(params, arcHeight, orbitNumber2);
        break;
      default:
        d = this.generateDefaultPath(params);
    }
    return d;
  }
  generateRoundedPath(params, arcHeight, orbitNumber2) {
    const { bigRadius, smallRadius } = params;
    const available = Math.min(params.upperAngleEnd - params.upperAngleStart, params.innerAngleEnd - params.innerAngleStart);
    const curve = Math.min(arcHeight < 5 ? 2.5 : arcHeight < 10 ? 5 : 10, available * 180 / Math.PI * orbitNumber2 * 0.49);
    const capRad = curve / orbitNumber2 * Math.PI / 180;
    const flagU = params.upperAngleEnd - params.upperAngleStart - 2 * capRad > Math.PI ? 1 : 0;
    const flagI = params.innerAngleEnd - params.innerAngleStart - 2 * capRad > Math.PI ? 1 : 0;
    const newUpperStart = this.arcPoint(bigRadius, params.upperAngleStart, 0, curve / orbitNumber2);
    const newUpperEnd = this.arcPoint(bigRadius, params.upperAngleEnd, 0, -curve / orbitNumber2);
    const newInnerStart = this.arcPoint(smallRadius, params.innerAngleStart, 0, curve / orbitNumber2);
    const newInnerEnd = this.arcPoint(smallRadius, params.innerAngleEnd, 0, -curve / orbitNumber2);
    const upperPointStart = this.arcPoint(bigRadius, params.upperAngleStart, -(curve / 2) / orbitNumber2, 0);
    const upperPointEnd = this.arcPoint(bigRadius, params.upperAngleEnd, -(curve / 2) / orbitNumber2, 0);
    const innerPointStart = this.arcPoint(smallRadius, params.innerAngleStart, curve / 2 / orbitNumber2, 0);
    const innerPointEnd = this.arcPoint(smallRadius, params.innerAngleEnd, curve / 2 / orbitNumber2, 0);
    const Q2 = this.getControlPoint(newUpperEnd.x, newUpperEnd.y, upperPointEnd.x, upperPointEnd.y);
    const Q1 = this.getControlPoint(innerPointEnd.x, innerPointEnd.y, newInnerEnd.x, newInnerEnd.y);
    const Q22 = this.getControlPoint(newInnerStart.x, newInnerStart.y, innerPointStart.x, innerPointStart.y);
    const Q3 = this.getControlPoint(upperPointStart.x, upperPointStart.y, newUpperStart.x, newUpperStart.y);
    let d = `M ${newUpperStart.x},${newUpperStart.y} A ${bigRadius},${bigRadius} 0 ${flagU} 1 ${newUpperEnd.x},${newUpperEnd.y}`;
    d += `Q ${Q2.xc},${Q2.yc} ${upperPointEnd.x},${upperPointEnd.y} L ${innerPointEnd.x},${innerPointEnd.y}`;
    d += `Q ${Q1.xc},${Q1.yc} ${newInnerEnd.x},${newInnerEnd.y}`;
    d += `A ${smallRadius},${smallRadius} 0 ${flagI} 0 ${newInnerStart.x},${newInnerStart.y}`;
    d += `Q ${Q22.xc},${Q22.yc} ${innerPointStart.x},${innerPointStart.y} L ${upperPointStart.x},${upperPointStart.y}`;
    d += ` Q ${Q3.xc},${Q3.yc} ${newUpperStart.x},${newUpperStart.y}`;
    d += ` Z`;
    return d;
  }
  // Dentro de la clase OrbitCommon en orbit-common.js
  generateCirclePath(params, shape) {
    const { upperArcStart, upperArcEnd, innerArcStart, innerArcEnd, bigRadius, smallRadius, largeArcFlagUpper, largeArcFlagInner } = params;
    let d = `M ${upperArcStart.x},${upperArcStart.y} A ${bigRadius},${bigRadius} 0 ${largeArcFlagUpper} 1 ${upperArcEnd.x},${upperArcEnd.y}`;
    d += ` A 1,1 0 0 1 ${innerArcEnd.x},${innerArcEnd.y} `;
    d += ` A ${smallRadius},${smallRadius} 0 ${largeArcFlagInner} 0 ${innerArcStart.x},${innerArcStart.y}`;
    d += ` A 1,1 0 0 ${shape === "circle" || shape === "circle-a" ? 1 : 0} ${upperArcStart.x},${upperArcStart.y} `;
    d += ` Z`;
    return d;
  }
  generateCircleBPath(params, arcHeight, orbitNumber2) {
    const { upperAngleStart, upperAngleEnd, innerAngleStart, innerAngleEnd, bigRadius, smallRadius } = params;
    const available = Math.min(upperAngleEnd - upperAngleStart, innerAngleEnd - innerAngleStart);
    const segment = Math.min(arcHeight * 1.36, available * 180 / Math.PI * orbitNumber2 * 0.49);
    const capRad = segment / orbitNumber2 * Math.PI / 180;
    const flagU = upperAngleEnd - upperAngleStart - 2 * capRad > Math.PI ? 1 : 0;
    const flagI = innerAngleEnd - innerAngleStart - 2 * capRad > Math.PI ? 1 : 0;
    const newUpperStart = this.arcPoint(bigRadius, upperAngleStart, 0, segment / orbitNumber2);
    const newUpperEnd = this.arcPoint(bigRadius, upperAngleEnd, 0, -segment / orbitNumber2);
    const newInnerStart = this.arcPoint(smallRadius, innerAngleStart, 0, segment / orbitNumber2);
    const newInnerEnd = this.arcPoint(smallRadius, innerAngleEnd, 0, -segment / orbitNumber2);
    let d = `M ${newUpperStart.x},${newUpperStart.y} A ${bigRadius},${bigRadius} 0 ${flagU} 1 ${newUpperEnd.x},${newUpperEnd.y}`;
    d += ` A 1,1 0 0 1 ${newInnerEnd.x},${newInnerEnd.y} `;
    d += ` A ${smallRadius},${smallRadius} 0 ${flagI} 0 ${newInnerStart.x},${newInnerStart.y}`;
    d += ` A 1,1 0 0 1 ${newUpperStart.x},${newUpperStart.y} `;
    d += ` Z`;
    return d;
  }
  generateArrowPath(params, orbitNumber2) {
    const { upperArcStart, upperArcEnd, innerArcStart, innerArcEnd, bigRadius, smallRadius, largeArcFlagUpper, largeArcFlagInner, radius } = params;
    const middleEnd = this.arcPoint(radius, params.upperAngleEnd, 0, 24 / orbitNumber2 / 2);
    const middleStart = this.arcPoint(radius, params.upperAngleStart, 0, 24 / orbitNumber2 / 2);
    let d = `M ${upperArcStart.x},${upperArcStart.y} A ${bigRadius},${bigRadius} 0 ${largeArcFlagUpper} 1 ${upperArcEnd.x},${upperArcEnd.y}`;
    d += `L ${middleEnd.x} ${middleEnd.y}`;
    d += `L ${innerArcEnd.x} ${innerArcEnd.y}`;
    d += `A ${smallRadius},${smallRadius} 0 ${largeArcFlagInner} 0 ${innerArcStart.x}, ${innerArcStart.y}`;
    d += `L ${middleStart.x} ${middleStart.y}`;
    d += `Z`;
    return d;
  }
  generateSlashPath(params, shape, orbitNumber2) {
    const { upperAngleStart, upperAngleEnd, innerAngleStart, innerAngleEnd, bigRadius, smallRadius, largeArcFlagUpper, largeArcFlagInner } = params;
    const newUpperStart = this.arcPoint(bigRadius, upperAngleStart, 0, shape === "backslash" ? 0 : 24 / orbitNumber2 / 2);
    const newUpperEnd = this.arcPoint(bigRadius, upperAngleEnd, 0, shape === "backslash" ? 0 : 24 / orbitNumber2 / 2);
    const newInnerStart = this.arcPoint(smallRadius, innerAngleStart, 0, shape === "backslash" ? 24 / orbitNumber2 / 2 : 0);
    const newInnerEnd = this.arcPoint(smallRadius, innerAngleEnd, 0, shape === "backslash" ? 24 / orbitNumber2 / 2 : 0);
    let d = `M ${newUpperStart.x},${newUpperStart.y} A ${bigRadius},${bigRadius} 0 ${largeArcFlagUpper} 1 ${newUpperEnd.x},${newUpperEnd.y}`;
    d += `L ${newInnerEnd.x} ${newInnerEnd.y}`;
    d += `A ${smallRadius},${smallRadius} 0 ${largeArcFlagInner} 0 ${newInnerStart.x}, ${newInnerStart.y}`;
    d += `Z`;
    return d;
  }
  generateZigzagPath(params, arcHeight, orbitNumber2) {
    const { upperArcStart, upperArcEnd, innerArcStart, innerArcEnd, bigRadius, smallRadius, largeArcFlagUpper, largeArcFlagInner, radius } = params;
    const h2 = arcHeight / orbitNumber2 / 2;
    const s2 = this.arcPoint(radius, params.upperAngleStart, -h2, 3);
    const s3 = this.arcPoint(radius, params.upperAngleStart, 0, 0);
    const s4 = this.arcPoint(radius, params.upperAngleStart, h2, 3);
    const e2 = this.arcPoint(radius, params.innerAngleEnd, h2, 3);
    const e3 = this.arcPoint(radius, params.innerAngleEnd, 0, 0);
    const e4 = this.arcPoint(radius, params.innerAngleEnd, -h2, 3);
    let d = `M ${upperArcStart.x},${upperArcStart.y} A ${bigRadius},${bigRadius} 0 ${largeArcFlagUpper} 1 ${upperArcEnd.x},${upperArcEnd.y}`;
    d += `L ${e2.x} ${e2.y}`;
    d += `L ${e3.x} ${e3.y}`;
    d += `L ${e4.x} ${e4.y}`;
    d += `L ${innerArcEnd.x} ${innerArcEnd.y}`;
    d += `A ${smallRadius},${smallRadius} 0 ${largeArcFlagInner} 0 ${innerArcStart.x}, ${innerArcStart.y}`;
    d += `L ${s2.x} ${s2.y}`;
    d += `L ${s3.x} ${s3.y}`;
    d += `L ${s4.x} ${s4.y}`;
    d += `Z`;
    return d;
  }
  generateDefaultPath(params) {
    const { upperArcStart, upperArcEnd, innerArcStart, innerArcEnd, bigRadius, smallRadius, largeArcFlagUpper, largeArcFlagInner } = params;
    let d = `M ${upperArcStart.x},${upperArcStart.y} A ${bigRadius},${bigRadius} 0 ${largeArcFlagUpper} 1 ${upperArcEnd.x},${upperArcEnd.y}`;
    d += `L ${innerArcEnd.x} ${innerArcEnd.y}`;
    d += `A ${smallRadius},${smallRadius} 0 ${largeArcFlagInner} 0 ${innerArcStart.x}, ${innerArcStart.y}`;
    d += `Z`;
    return d;
  }
};
var OrbitProgress = class extends OrbitBase {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          --o-fill: var(--o-gray-light);
          --o-stroke: var(--o-fill);
          --o-stroke-width: 1;
          --o-back-fill: transparent;
          --o-back-stroke: none;
          --o-back-stroke-width: 1;
        }
        :host(:hover) {
          --o-fill: var(--o-gray-light);
          --o-stroke: var(--o-fill);
          --o-stroke-width: 1;
          --o-back-fill: transparent;
          --o-back-stroke: none;
          --o-back-stroke-width: 1;
        }
        svg {
          width: 100%;
          height: 100%;
          overflow: visible;
          pointer-events: none;
        }
        /* Display element by default: never steals clicks (see orbit-arc).
           Interaction is opt-in via the "interactive" attribute. */
        svg * {
          pointer-events: none;
        }
        :host([interactive]) svg * {
          pointer-events: visiblePainted;
        }
        :host([interactive]) {
          cursor: pointer;
        }
        .progress-bar {
          fill: var(--o-fill);
          stroke: var(--o-stroke);
          stroke-width: var(--o-stroke-width);
          transition: fill 0.25s, stroke 0.25s;
          stroke-linejoin: round;
        }
        .progress-bg {
          fill: var(--o-back-fill);
          stroke: var(--o-back-stroke);
          stroke-width: var(--o-back-stroke-width);
        }
        /* variant="stroke": the thin, legible gauge (registro "medidor").
           The default band is a FILLED donut wedge, so everyone building a
           thin gauge tripped on --o-fill/--o-back-fill. With this variant the
           paths are open arcs and the data color lives where you expect it:
           --o-stroke for the bar, --o-back-stroke for the track. */
        :host([variant="stroke"]) .progress-bar {
          fill: none;
          stroke: var(--o-stroke);
          stroke-width: var(--o-stroke-width, 2);
          stroke-linecap: round;
        }
        :host([variant="stroke"]) .progress-bg {
          fill: none;
          stroke: var(--o-back-stroke, var(--o-gray-light));
          stroke-width: var(--o-back-stroke-width, 1);
          stroke-linecap: round;
        }
      </style>
      <svg viewBox="0 0 100 100">
        <path class="progress-bg" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
        <path class="progress-bar" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
      </svg>
    `;
  }
  update() {
    const attrs = this.getAttributes();
    const isStroke = this.getAttribute("variant") === "stroke";
    const dBg = isStroke ? this.calculateStrokeArc(attrs, true) : this.calculateArcParameters(attrs, true);
    const dBar = isStroke ? this.calculateStrokeArc(attrs, false) : this.calculateArcParameters(attrs, false);
    this.shadowRoot.querySelector(".progress-bg").setAttribute("d", dBg);
    this.shadowRoot.querySelector(".progress-bar").setAttribute("d", dBar);
  }
  /**
   * variant="stroke": open arc along the orbit radius (no closed band),
   * stroked by CSS. Same progress math as the band variant.
   */
  calculateStrokeArc(attrs, full) {
    const { realRadius } = attrs;
    const arcAngle = Math.max(0, Math.min(this.getProgressAngle(attrs, full), 359.999999));
    if (!(arcAngle > 0) || !(attrs.orbitRadius > 0)) return "";
    const a0 = -90 * (Math.PI / 180);
    const a1 = (-90 + arcAngle) * (Math.PI / 180);
    const x0 = 50 + realRadius * Math.cos(a0);
    const y0 = 50 + realRadius * Math.sin(a0);
    const x1 = 50 + realRadius * Math.cos(a1);
    const y1 = 50 + realRadius * Math.sin(a1);
    const largeArcFlag = arcAngle > 180 ? 1 : 0;
    return `M ${x0},${y0} A ${realRadius},${realRadius} 0 ${largeArcFlag} 1 ${x1},${y1}`;
  }
  getAttributes() {
    const common = super.getCommonAttributes(this);
    const range = Math.max(0, Math.min(360, this.readAngle(common.style, "--o-range", 360)));
    const rawValue = common.style.getPropertyValue("--o-progress").trim();
    const progress = rawValue ? this.readNumber(common.style, "--o-progress", 0) : Number(this.getAttribute("value") || 0);
    const rawMax = this.getAttribute("max");
    const maxValue = rawMax === null ? 100 : Number(rawMax);
    return {
      ...common,
      range,
      progress,
      maxValue
    };
  }
  getProgressAngle(attrs, full) {
    const { range, progress, maxValue } = attrs;
    return full ? range : super.getProgressAngle(range, progress, maxValue);
  }
  calculateArcParameters(attrs, full) {
    const { shape, realRadius, arcHeightPercentage, orbitNumber: orbitNumber2, strokeWidth, arcHeight } = attrs;
    const arcAngle = this.getProgressAngle(attrs, full);
    if (!(arcAngle > 0) || !(attrs.orbitRadius > 0)) return "";
    const params = super.calculateCommonArcParameters(
      arcAngle,
      realRadius,
      arcHeightPercentage,
      orbitNumber2,
      shape,
      strokeWidth,
      arcHeight
    );
    return super.generatePathData(shape, params, arcHeight, orbitNumber2);
  }
};
var template = typeof document === "undefined" ? null : document.createElement("template");
if (template) template.innerHTML = `
  <style>
    :host {
      --o-fill: var(--o-gray-light);
      --o-stroke: var(--o-fill);
      --o-stroke-width: 1;
      --o-color: currentcolor;
    }
    :host(:hover) {
      --o-fill: var(--o-gray-light);
      --o-stroke: var(--o-fill);
      --o-stroke-width: 1;
      --o-color: currentcolor;
    }
    svg {
      width: 100%;
      height: 100%;
      overflow: visible;
      pointer-events: none;
    }
    /* Arcs are display elements by default: they must NOT steal clicks from
       satellites/controls nearby (a painted arc used to capture clicks even
       at opacity 0, and pointer-events:none on the host could not pierce the
       shadow). Interaction is opt-in via the "interactive" attribute. */
    svg * {
      pointer-events: none;
    }
    :host([interactive]) svg * {
      pointer-events: visiblePainted;
    }
    :host([interactive]) {
      cursor: pointer;
    }
    #orbitShape {
      fill: var(--o-fill);
      stroke: var(--o-stroke);
      stroke-width: var(--o-stroke-width);
      transition: fill 0.25s, stroke 0.25s;
    }
    text {
      fill: var(--o-color);
    }
    #orbitPath {
      fill: transparent;
      stroke: none;
      stroke-width: 0;
    }
  </style>
  <svg viewBox="0 0 100 100">
    <path id="orbitShape" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
    <path id="orbitPath" shape-rendering="geometricPrecision" vector-effect="non-scaling-stroke"></path>
    <text>
      <textPath href="#orbitPath" alignment-baseline="middle"></textPath>
    </text>
  </svg>
`;
var OrbitArc = class extends OrbitBase {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }
  update() {
    const attrs = this.getAttributes();
    const { length, fontSize, textAnchor, fitRange } = attrs;
    if (this.hasAttribute("value")) {
      setLayoutProperty(this, "--o-arc-start", `${attrs.stackOffset}deg`);
      setLayoutProperty(this, "--o_stack", attrs.stackOffset + attrs.arcAngle);
    } else {
      this.style.removeProperty("--o-arc-start");
      this.style.removeProperty("--o_stack");
    }
    const orbitPath = this.shadowRoot.querySelector("#orbitPath");
    const orbitShape = this.shadowRoot.querySelector("#orbitShape");
    const textPath = this.shadowRoot.querySelector("textPath");
    orbitShape.setAttribute("d", this.calculateArcParameters(attrs).dShape);
    orbitPath.setAttribute("d", this.calculateTextArcParameters(attrs).dPath);
    if (textAnchor === "start") {
      textPath.setAttribute("startOffset", "0%");
      textPath.setAttribute("text-anchor", "start");
    } else if (textAnchor === "middle") {
      textPath.setAttribute("startOffset", "50%");
      textPath.setAttribute("text-anchor", "middle");
    } else if (textAnchor === "end") {
      textPath.setAttribute("startOffset", "100%");
      textPath.setAttribute("text-anchor", "end");
    }
    if (fitRange) {
      textPath.parentElement.setAttribute("textLength", orbitPath.getTotalLength());
    } else {
      textPath.parentElement.removeAttribute("textLength");
    }
    textPath.parentElement.style.fontSize = `calc(${fontSize} * (100 / (${length}) * (12 / var(--o-orbit-number)))`;
    textPath.textContent = this.textContent;
    this.warnIfTextOverflows(orbitPath, textPath, fitRange);
  }
  /**
   * Curved text has an explicit angular budget: glyphs past the end of the
   * arc path are clipped SILENTLY by SVG. Measure and warn so nobody loses
   * time to invisible truncation (~20 chars in 96° at default sizes).
   * fit-range squeezes the text to the path via textLength, so it never clips.
   */
  warnIfTextOverflows(orbitPath, textPath, fitRange) {
    const raw = (this.textContent || "").trim();
    if (!raw || fitRange || !this.isConnected) return;
    if (this._textFrame) this.ownerDocument.defaultView.cancelAnimationFrame(this._textFrame);
    this._textFrame = this.ownerDocument.defaultView.requestAnimationFrame(() => {
      this._textFrame = 0;
      if (!this.isConnected) return;
      try {
        const pathLen = orbitPath.getTotalLength();
        const textLen = textPath.parentElement.getComputedTextLength();
        if (pathLen > 0 && textLen > pathLen && this._truncWarned !== raw) {
          this._truncWarned = raw;
          console.warn(
            `[orbit] <o-arc> text "${raw.length > 34 ? raw.slice(0, 34) + "\u2026" : raw}" overflows its arc (${Math.round(textLen)} > ${Math.round(pathLen)} units) and will clip. Shorten the text, widen --o-range, or use fit-range to squeeze it.`
          );
        }
      } catch (e) {
      }
    });
  }
  getAttributes() {
    const common = super.getCommonAttributes(this);
    const { style } = common;
    const range = Math.max(0, Math.min(360, this.readAngle(style, "--o-range", 360)));
    const flip = this.hasAttribute("flip") || this.classList.contains("flip");
    const fitRange = this.hasAttribute("fit-range") || this.classList.contains("fit-range");
    const length = common.orbitRadius * 24 / common.orbitNumber || 100;
    const textAnchor = this.getAttribute("text-anchor") || "middle";
    const fontSize = style.fontSize || "16px";
    const gap = Math.max(0, this.readNumber(style, "--o-gap", 1));
    const value = Number(this.getAttribute("value"));
    const rawMax = this.getAttribute("max");
    const max = rawMax === null ? 100 : Number(rawMax);
    const arcAngle = this.hasAttribute("value") ? super.getProgressAngle(range, value, max) : Math.max(0, Math.min(360, this.readAngle(style, "--o-angle", 0)));
    let stackOffset = 0;
    if (this.hasAttribute("value")) {
      for (let prev = this.previousElementSibling; prev; prev = prev.previousElementSibling) {
        if (prev.localName !== "o-arc") continue;
        const previousStyle = this.ownerDocument.defaultView.getComputedStyle(prev);
        if (prev.hasAttribute("value")) {
          const prevMax = prev.hasAttribute("max") ? Number(prev.getAttribute("max")) : 100;
          const prevRange = cssNumber(prev, previousStyle.getPropertyValue("--o-range"), range, "angle");
          stackOffset += super.getProgressAngle(prevRange, Number(prev.getAttribute("value")), prevMax);
        } else stackOffset += cssNumber(prev, previousStyle.getPropertyValue("--o-angle"), 0, "angle");
      }
    }
    return { ...common, gap, arcAngle, stackOffset, flip, fitRange, length, fontSize, textAnchor };
  }
  calculateArcParameters(attrs) {
    const { arcAngle, realRadius, arcHeightPercentage, orbitNumber: orbitNumber2, shape, strokeWidth, arcHeight, gap } = attrs;
    if (!(arcAngle > 0) || !(attrs.orbitRadius > 0)) return { dShape: "" };
    const params = super.calculateCommonArcParameters(
      arcAngle,
      realRadius,
      arcHeightPercentage,
      orbitNumber2,
      shape,
      strokeWidth,
      arcHeight,
      gap
    );
    const dShape = super.generatePathData(shape, params, arcHeight, orbitNumber2);
    return { dShape };
  }
  calculateTextArcParameters(attrs) {
    const { arcAngle, realRadius, gap, flip } = attrs;
    if (!(arcAngle > 0)) return { dPath: "" };
    const adjustedGap = Math.min(gap * 0.5, arcAngle * 0.49);
    const sweepFlag = flip ? 0 : 1;
    const largeArcFlag = arcAngle <= 180 ? 0 : 1;
    let coordX1 = 50 + realRadius * Math.cos((-90 + adjustedGap) * (Math.PI / 180));
    let coordY1 = 50 + realRadius * Math.sin((-90 + adjustedGap) * (Math.PI / 180));
    let coordX2 = 50 + realRadius * Math.cos((arcAngle - 90 - adjustedGap) * Math.PI / 180);
    let coordY2 = 50 + realRadius * Math.sin((arcAngle - 90 - adjustedGap) * Math.PI / 180);
    const [startX, startY, endX, endY] = flip ? [coordX2, coordY2, coordX1, coordY1] : [coordX1, coordY1, coordX2, coordY2];
    const dPath = `M ${startX},${startY} A ${realRadius},${realRadius} 0 ${largeArcFlag} ${sweepFlag} ${endX},${endY}`;
    return { dPath };
  }
  calcularExpresionCSS(cssExpression) {
    return cssNumber(this, cssExpression, 0, "angle");
  }
};
var resizing = /* @__PURE__ */ new WeakMap();
var Orbit = {
  refresh: refreshLayout,
  resize(parentElementSelector) {
    var _a, _b;
    const parent = typeof parentElementSelector === "string" ? (_a = globalThis.document) == null ? void 0 : _a.querySelector(parentElementSelector) : parentElementSelector;
    if (!(parent == null ? void 0 : parent.ownerDocument)) {
      console.error("Orbit.resize: element not found:", parentElementSelector);
      return () => {
      };
    }
    (_b = resizing.get(parent)) == null ? void 0 : _b();
    const view = parent.ownerDocument.defaultView;
    const applyRatio = (width) => {
      if (!(width > 0)) return;
      for (const element of parent.querySelectorAll(".gravity-spot")) {
        const ratio = String(width / 500);
        if (element.style.getPropertyValue("--o-force-ratio") !== ratio) element.style.setProperty("--o-force-ratio", ratio);
      }
      refreshLayout(parent);
    };
    const observer = new view.ResizeObserver((entries) => {
      for (const entry of entries) applyRatio(entry.contentRect.width);
    });
    observer.observe(parent);
    applyRatio(parent.clientWidth || parent.getBoundingClientRect().width);
    const stop = () => {
      observer.disconnect();
      if (resizing.get(parent) === stop) resizing.delete(parent);
    };
    resizing.set(parent, stop);
    return stop;
  }
};
function registerOrbit() {
  if (typeof customElements === "undefined" || typeof document === "undefined") return;
  if (!customElements.get("o-progress")) customElements.define("o-progress", OrbitProgress);
  if (!customElements.get("o-arc")) customElements.define("o-arc", OrbitArc);
  requestLayout(document);
  window.Orbit = Orbit;
}
registerOrbit();

// node_modules/zumly/dist/zumly.mjs
var it = Symbol.for("zumly.viewLifecycles");
function ee(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 se() {
  let r = false, t = [], e = { onCleanup(s) {
    if (typeof s != "function") throw new TypeError("Zumly: onCleanup expects a function");
    r ? ee(s) : t.push(s);
  }, attach(s) {
    let i = s[it];
    i || (i = /* @__PURE__ */ new Set(), Object.defineProperty(s, it, { value: i, configurable: true })), i.add(e);
  }, dispose() {
    if (!r) {
      r = true;
      for (let s of t.splice(0).reverse()) ee(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 Ve = 1e4;
var 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 = /* @__PURE__ */ 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(), Ve), 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 = se(), o = e?.target || document.createElement("div");
        n.attach(o);
        let a = { ...e, target: o, props: e?.props || {}, context: e?.context || /* @__PURE__ */ 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(true);
      case "webcomponent":
        return await customElements.whenDefined(t), document.createElement(t);
      default:
        throw new Error("Zumly: unknown view type for source");
    }
  }
};
async function ut(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 re(r, t) {
  if (t.isValid = false, !r || typeof r != "object") {
    $(false, "'options' object has to be provided when instance is defined", "error");
    return;
  }
  if (typeof r.mount != "string") {
    $(false, "'mount' must be a string selector", "error");
    return;
  }
  if (t.mount = r.mount, typeof r.initialView != "string") {
    $(false, "'initialView' must be a string", "error");
    return;
  }
  if (t.initialView = r.initialView, !r.views || typeof r.views != "object") {
    $(false, "'views' must be an object", "error");
    return;
  }
  t.views = r.views, t.isValid = true, t.preload = Array.isArray(r.preload) ? r.preload : [], t.debug = typeof r.debug == "boolean" ? r.debug : false, t.componentContext = r.componentContext && typeof r.componentContext == "object" ? r.componentContext : /* @__PURE__ */ 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 && $(false, `'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 : false;
  let o = e && e.hideTrigger;
  o === true || o === "fade" ? t.hideTrigger = o : (t.hideTrigger = false, o != null && o !== false && $(false, `'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 && $(false, `'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) || $(false, `'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 && $(false, "'transitions.stagger' must be a positive number (ms). Falling back to 0 (disabled).", "warn")), t.parallax = 0;
  let u = r.lateralNav;
  if (u === false) t.lateralNav = false;
  else if (u && typeof u == "object") {
    let p = typeof u.mode == "string" ? u.mode.toLowerCase() : null, y = p === "auto" || p === "always";
    p && !y && $(false, `'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 && ($(false, "'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 && $(false, "'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 : true, dots: typeof u.dots == "boolean" ? u.dots : true, keepAlive: u.keepAlive === true || u.keepAlive === "visible" ? u.keepAlive : false, siblings: g };
  } else t.lateralNav = { mode: "auto", arrows: true, dots: true, keepAlive: false, siblings: null };
  let d = r.depthNav;
  if (d === false) t.depthNav = false;
  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 && $(false, `'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 && $(false, `'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 === false ? t.inputs = { wheel: false, keyboard: false, click: false, touch: false } : m && typeof m == "object" ? t.inputs = { wheel: typeof m.wheel == "boolean" ? m.wheel : true, keyboard: typeof m.keyboard == "boolean" ? m.keyboard : true, click: typeof m.click == "boolean" ? m.click : true, touch: typeof m.touch == "boolean" ? m.touch : true } : t.inputs = { wheel: true, keyboard: true, click: true, touch: true };
}
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 Dt(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 ie(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 ne(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 oe(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 ae({ 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, 0.9);
  return `translate(${d * m}px, ${v * m}px) scale(${o * a})`;
}
function le(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: false };
  let s = t.replace(/translate\s*\([^)]+\)\s*/, "").trim();
  return { tx: parseFloat(e[1]), ty: parseFloat(e[2]), rest: s, matched: true };
}
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 dt(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 mt(r, t, e) {
  return { viewName: r, backwardState: t, forwardState: e };
}
function ce(r) {
  return { detachedNode: r };
}
function fe(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 Ft(r) {
  let t = r.views?.[3];
  if (!(!t || !(t.detachedNode instanceof Node))) return t.detachedNode;
}
var Tt = class {
  #t = /* @__PURE__ */ 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(true), 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(true)) : null;
  }
  has(t) {
    let e = this.#t.get(t);
    return e ? e.expires !== null && Date.now() >= e.expires ? (this.#t.delete(t), false) : true : false;
  }
  invalidate(t) {
    this.#t.delete(t);
  }
  clear() {
    this.#t.clear();
  }
};
var je = "button, input, select, textarea, a[href], summary";
function kt(r) {
  return r?.matches?.(je) || false;
}
function Vt(r) {
  return !!r?.closest?.('input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"], [role="combobox"], [role="slider"], [role="spinbutton"]');
}
function he(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 = /* @__PURE__ */ 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 = true, 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 Be = 300 * 1e3;
var ue = /^https?:\/\/|^\/|\.(?:html|php)(?:[?#].*)?$/i;
var zt = class {
  #t;
  #e;
  #l;
  #n = /* @__PURE__ */ new Map();
  #s = /* @__PURE__ */ new Map();
  #r = null;
  #c = 0;
  #d;
  #f;
  #i = false;
  #o = false;
  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 = /* @__PURE__ */ 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("<") || ue.test(t)) ? t : null;
  }
  #v(t) {
    return ue.test(t) ? Be : 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(true);
    }
    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 = he(t);
    this.#s.clear();
    let i = /* @__PURE__ */ 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 = true, this.#r !== null && clearTimeout(this.#r), this.#r = null;
  }
  resume() {
    this.#o = false, this.#a();
  }
  destroy() {
    this.#i = true, this.#r !== null && clearTimeout(this.#r), this.#r = null, this.#s.clear(), this.#e.clear();
  }
};
var Lt = Symbol.for("zumly.viewVisibility");
function de(r) {
  r[Lt] || Object.defineProperty(r, Lt, { configurable: true, value: { value: r.style.getPropertyValue("content-visibility"), priority: r.style.getPropertyPriority("content-visibility") } });
}
function Ct(r) {
  r && (de(r), r.style.contentVisibility = "hidden");
}
function pt(r) {
  r && (de(r), r.style.contentVisibility = "visible");
}
function vt(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"), pt(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 = false, s = setTimeout(() => {
    e || (e = true, r());
  }, t);
  return { finish() {
    e || (e = true, clearTimeout(s), r());
  }, extend(i) {
    e || (clearTimeout(s), s = setTimeout(() => {
      e || (e = true, r());
    }, i));
  }, safetyTimer: s };
}
function Ot() {
  return { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
}
function Re(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 me(r, t, e) {
  r.style.transformOrigin = t, r.style.transform = e;
  try {
    r.getBoundingClientRect();
  } catch {
  }
  return Re(getComputedStyle(r).transform);
}
function ve(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" ? We(s, i, n, o, a, c, t) : e === "zoomOut" ? Xe(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, _ = /* @__PURE__ */ new Set(["zoom-lateral-in", "zoom-lateral-out", "zoom-lateral-back"]), { finish: S, extend: O } = J(() => {
    jt(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 We(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 = /* @__PURE__ */ new Set(["zoom-current-view", "zoom-previous-view", "zoom-last-view"]), { finish: v, extend: m } = J(() => {
    jt(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 Xe(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 = /* @__PURE__ */ new Set(["zoom-current-view-reverse", "zoom-previous-view-reverse", "zoom-last-view-reverse"]), { finish: g, extend: x } = J(() => {
    jt(u, _, b), u.forEach((S) => S.style.removeProperty("animation-delay")), u.forEach((S) => {
      if (S?.isConnected) try {
        pe(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 {
      pe(O, s, o);
    } catch {
    }
    d--, d <= 0 && g();
  }
  u.forEach((S) => {
    S.addEventListener("animationstart", b), S.addEventListener("animationend", _);
  });
}
function pe(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 jt(r, t, e) {
  for (let s of r) s?.removeEventListener && (s.removeEventListener("animationend", t), s.removeEventListener("animationstart", e));
}
function ye(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 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;
  }
  let f = K(a);
  if (e === "lateral") {
    Ue(r, f, c, t);
    return;
  }
  if (e === "zoomIn") {
    Ye(s, i, n, o, f, c, t);
    return;
  }
  if (e === "zoomOut") {
    Ke(s, i, n, o, f, c, l, t);
    return;
  }
  t();
}
function Ye(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(() => {
    Bt(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 Ke(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(() => {
        Bt(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 Ue(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(() => {
    Bt(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 Bt(r) {
  for (let t of r) try {
    t.cancel();
  } catch {
  }
}
var be = "[-+]?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?";
var we = `(${be})(px)?`;
var Ge = new RegExp(`^(?:translate\\(\\s*${we}\\s*,\\s*${we}\\s*\\)\\s*)?(?:scale\\(\\s*(${be})\\s*\\))?$`);
function Qe(r) {
  if (typeof r != "string") return null;
  let t = r.trim();
  if (t === "none") return Ot();
  if (!t) return null;
  let e = t.match(Ge);
  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 = Qe(e);
  return s ? (r.style.transformOrigin = t, r.style.transform = e, s) : me(r, t, e);
}
function _e(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" ? Je(e, i, n, o, a, h, l, t) : s === "zoomOut" ? ts(e, i, n, o, a, h, l, f, t) : t();
}
function Je(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 = xe([{ 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");
  Se(h, 0);
  let u = i.stagger || 0, d = n + (f ? u * 2 : u), v = { value: 0 };
  r({ targets: v, value: 1, duration: d, easing: Ee(o), update: () => {
    let m = v.value * d;
    Te(h, m, n, u);
  }, complete: () => {
    k(t, i), k(e, i), s && k(s, i), a();
  } });
}
function ts(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 = xe([{ 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");
  Se(v, 0);
  let m = i.stagger || 0, p = n + (h ? m * 2 : m), y = { value: 0 };
  r({ targets: y, value: 1, duration: p, easing: Ee(o), update: () => {
    let g = y.value * p;
    Te(v, g, n, m);
  }, complete: () => {
    H(t, a), V(e, u), s && d && j(s, d), c();
  } });
}
function xe(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 Se(r, t) {
  for (let { el: e, from: s, to: i } of r) e.style.transform = at(lt(s, i, t));
}
function Te(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 Ee(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 ke(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" ? es(e, i, n, o, a, h, l, t) : s === "zoomOut" ? ss(e, i, n, o, a, h, l, f, t) : t();
}
function es(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 = ze(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 ss(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 = ze(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 ze(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 Le(r, t) {
  let e = ns();
  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" ? rs(e, i, n, o, a, h, l, t) : s === "zoomOut" ? is(e, i, n, o, a, h, l, f, t) : t();
}
function rs(r, t, e, s, i, n, o, a) {
  Z(t, e, s);
  let c = Ce(t, e, s, i, "forward");
  Oe(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: Ae(o), onUpdate: (v) => {
    let m = v * u * 1e3;
    Ne(c, m, h, l);
  } }).then(() => {
    k(t, i), k(e, i), s && k(s, i), a();
  }).catch(() => a());
}
function is(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 = Ce(t, e, s, i, "backward");
  Oe(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: Ae(o), onUpdate: (x) => {
    let b = x * y * 1e3;
    Ne(d, b, p, v);
  } }).then(() => {
    H(t, a), V(e, h), s && u && j(s, u), c();
  }).catch(() => c());
}
function Ce(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 Oe(r, t) {
  for (let { el: e, from: s, to: i } of r) e.style.transform = at(lt(s, i, t));
}
function Ne(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 ns() {
  let r = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : {};
  return r.motion?.animate || r.Motion?.animate || r.animate;
}
function Ae(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 Pe = { css: ve, waapi: ge, none: ye, anime: _e, gsap: ke, motion: Le };
function Pt(r) {
  if (typeof r == "function") return { runTransition(s, i) {
    r(s, i);
  } };
  let t = typeof r == "string" ? r.toLowerCase() : "css";
  return { runTransition: Pe[t] || Pe.css };
}
function os(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 Ie(r, t, e) {
  let s = os(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 as(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 $e(r, t, e) {
  let s = as(r);
  return s === null ? r : `${s.x * t}px ${s.y * e}px`;
}
function Rt(r, t, e, s, i) {
  if (!r.storedViews?.length || !r.canvas || t <= 0 || e <= 0) return;
  let n = s / t, o = i / e, a = /* @__PURE__ */ 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 = Ie(y.transform, n, o), y.origin != null && (y.origin = $e(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 = Ie(y, n, o));
    let g = p.style.transformOrigin;
    g != null && g !== "" && (p.style.transformOrigin = $e(g, n, o));
  }
}
var ls = 8e3;
var gt = class {
  constructor(t) {
    if (this.storedViews = [], this.currentStage = null, this.debug = false, this.trace = [], this.blockEvents = false, this._blockEventsSafetyTimer = null, this.touchstartX = 0, this.touchstartY = 0, this.touchendX = 0, this.touchendY = 0, this.touching = false, this.lateralHistory = [], this._lastCanvasWidth = 0, this._lastCanvasHeight = 0, this._pendingResizeCorrection = false, this._destroyed = false, this._trackedTimers = /* @__PURE__ */ new Set(), this._pendingTransitionComplete = null, this._navigationTask = null, this._initPromise = null, this._accessibility = new Et(), this._hooks = {}, this._plugins = [], re(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 = false;
      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 = false;
    }, 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 = false, 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, false), t.addEventListener("touchend", this._onZoom, false), t.addEventListener("touchstart", this._onTouchStart, { passive: true }), t.addEventListener("touchend", this._onTouchEnd, false), t.addEventListener("touchcancel", this._onTouchCancel, { passive: true }), t.addEventListener("keyup", this._onKeyUp, false), t.addEventListener("keydown", this._onKeyDown, false), t.addEventListener("click", this._onKeyboardClick, false), t.addEventListener("wheel", this._onWheel, { passive: false }), t.addEventListener("mouseover", this._onPrefetchTrigger, { passive: true }), t.addEventListener("focusin", this._onPrefetchTrigger, { passive: true }), window.addEventListener("resize", this._onResize, { passive: true }), typeof ResizeObserver < "u" && (this._resizeObserver = new ResizeObserver(() => this._handleResize()), this._resizeObserver.observe(t)));
  }
  _unbindEvents() {
    let t = this.canvas;
    t && (t.removeEventListener("mouseup", this._onZoom, false), t.removeEventListener("touchend", this._onZoom, false), t.removeEventListener("touchstart", this._onTouchStart), t.removeEventListener("touchend", this._onTouchEnd, false), t.removeEventListener("touchcancel", this._onTouchCancel), t.removeEventListener("keyup", this._onKeyUp, false), t.removeEventListener("keydown", this._onKeyDown, false), t.removeEventListener("click", this._onKeyboardClick, false), 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 = true;
        break;
      }
    }
  }
  _setBlockEvents() {
    this.blockEvents = true, 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 = false;
        let t = this._pendingTransitionComplete;
        t ? t() : this._onTransitionComplete();
      }
    }, ls);
  }
  _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 = true;
          return;
        }
        Rt(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 = false, this.canvas && this._lastCanvasWidth > 0) {
        let e = this.canvas.offsetWidth, s = this.canvas.offsetHeight;
        (e !== this._lastCanvasWidth || s !== this._lastCanvasHeight) && Rt(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") && vt(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]") ? false : (n.focus({ preventScroll: true }), 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: true });
    }
  }
  _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: true });
    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" : true : this.hideTrigger;
  }
  _applyHideTrigger(t, e, s, i, n, o = true) {
    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: true }), 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: /* @__PURE__ */ new Set() };
    e.promise = new Promise((i) => {
      e.resolve = i;
    }), this._navigationTask = e, this.blockEvents = true, this.prefetcher?.pause();
    let s = () => {
      this._navigationTask === e && (this._navigationTask = null, this.blockEvents = false, 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 = false, 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, true, { 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, false, 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 * 0.1), o = Math.max(40, i.height * 0.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 ut(i, this.initialView, this.canvas, true, 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 = true;
      for (let i of this._plugins) this._installPlugin(i);
    }
  }
  destroy() {
    if (!this._destroyed) {
      this._destroyed = true, 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 = Ft(t);
        e && C(e);
      }
      if (this.blockEvents = false, 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 = false;
    }
  }
  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 ? true : 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 ut(w, t, s, false, {}, this.componentContext);
      } else {
        let w = await this.prefetcher.get(t, a);
        if (this._destroyed) {
          C(w);
          return;
        }
        this.prefetcher.scanAndPrefetch(w, a), l = await ut(w, t, s, false, 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, Wt = null, bt = null;
      _ && (X = _.getBoundingClientRect(), bt = _.querySelector(".zoomed"), Wt = bt && bt.getBoundingClientRect ? bt.getBoundingClientRect() : X);
      let _t = { left: d, top: v }, Xt = { width: u.width, height: u.height }, Yt = { width: w.width, height: w.height }, Kt = St(m.width, m.height, w.width, w.height, g);
      z = Kt.scale;
      let Me = Kt.scaleInv;
      O = Dt(m, _t, Yt, Me), E = b.style.transform;
      let Ut = ne(m, L);
      T = oe(Xt, m, L, z, this.parallax);
      let Gt = nt(N || "0 0"), st = Y(E || ""), Qt = nt(Ut), rt = Y(T.transform), Jt = m;
      if (i && (Jt = dt(m, L, Gt, st.tx, st.ty, st.scale, Qt, rt.tx, rt.ty, rt.scale)), A = ie(Jt, _t, Yt), _) {
        P = _.style.transform;
        let He = dt(L, L, Gt, st.tx, st.ty, st.scale, Qt, rt.tx, rt.ty, rt.scale), De = le(T.x, T.y, _t, z, o), te = nt(F || "0 0"), Mt = Y(P || ""), Ht = Y(De), Fe = dt(Wt, X, te, Mt.tx, Mt.ty, Mt.scale, te, Ht.tx, Ht.ty, Ht.scale);
        B = ae({ canvasRect: Xt, canvasOffset: _t, triggerRect: m, previousViewRectAtBaseTransform: L, lastViewZoomedElementRect: Fe, previousViewRectWithPreviousAtEndTransform: He, scale: z, preScale: o, parallax: this.parallax });
      }
      l.style.transform = O, b.style.transformOrigin = Ut;
    } 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"), vt(b), vt(_), vt(S);
      return;
    }
    let M = mt(l.dataset.viewName, { origin: l.style.transformOrigin, duration: p, ease: y, transform: O }, { origin: l.style.transformOrigin, duration: p, ease: y, transform: A }), wt = mt(b.dataset.viewName, { origin: b.style.transformOrigin, duration: p, ease: y, transform: E }, { origin: b.style.transformOrigin, duration: p, ease: y, transform: T.transform }), ft = _ ? mt(_.dataset.viewName, { origin: _.style.transformOrigin, duration: p, ease: y, transform: P }, { origin: _.style.transformOrigin, duration: p, ease: y, transform: B }) : null, U = S ? ce(S) : null, W = fe(this.storedViews.length, M, wt, ft, 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 ht = this._resolveHideTrigger(i);
    this._applyHideTrigger(i, l, ht, p, y), ht && (W.hideTriggerMode = ht);
    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 = false, 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 = false, s = {}) {
    return this._runNavigation(() => this._performLateral(t, e, s));
  }
  async _performLateral(t, e = false, 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 ut(X, t, this.canvas, false, 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 = /* @__PURE__ */ 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 * 0.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 * 0.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 * 0.7, P * 0.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, ft = 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, ft = 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 || "", ft = 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] = mt(t, { origin: "0 0", duration: c, ease: l, transform: ft }, { 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) : false;
    m.hideTriggerMode = W, E && (E.classList.add("zoomed"), this._applyHideTrigger(E, u, W, c, l, false), 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), ht = 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: ht, currentStage: this.currentStage, duration: c, ease: l, canvas: this.canvas, slideDeltaX: T, slideDeltaY: P, keepAlive: o && !e ? o : false }, 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 = false, 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) => dt(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: Dt(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"), pt(i));
    let l = Ft(this.currentStage);
    if (l) {
      t.prepend(l);
      let u = t.querySelector(".z-view:first-child");
      u && (pt(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 = false, 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 = "&#8249;", 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", "&#8249;"), 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", "&#8250;"), 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 || Vt(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 || Vt(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 = true, this._setTrackedTimeout(() => {
      this._wheelCooldown = false;
    }, 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 true;
      }
      s = s.parentElement;
    }
    return false;
  }
  onTouchStart(t) {
    this._destroyed || this.inputs.touch && (this.tracing("onTouchStart()"), this.touching = true, 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 = false);
  }
  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 = false, 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 = false, this.tracing("tap"), this.zoomOut());
  }
};
var cs = { separator: "/", prefix: "/" };
function qt(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 fs(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 Ze = { install(r, t) {
  let e = Object.assign({}, cs, t), s = e.separator, i = e.prefix, n = false, o = false, a = null, c = false;
  function l(v) {
    if (n) return;
    let m = qt(r, s), p = "#" + i + m;
    window.location.hash !== p && (n = true, window.history[v](null, "", p), n = false);
  }
  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 = true, n = true;
      try {
        for (; a && !c; ) {
          let v = a;
          if (a = null, await r._navigationTask?.promise, c) return;
          if (a) continue;
          let m = qt(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 = qt(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 = false, o = false;
      }
    }
  }
  function d() {
    c || (a = fs(i, s), u());
  }
  window.addEventListener("popstate", d), h(), r.on("destroy", function() {
    c = true, a = null, r.off("afterZoomIn", f), r.off("afterLateral", f), r.off("afterZoomOut", h), window.removeEventListener("popstate", d);
  });
} };
gt.Router = Ze;

// src/components/sizes.js
var SIZE_RATIOS = Object.freeze({
  xxl: 1,
  xl: 260 / 420,
  l: 160 / 420,
  m: 100 / 420,
  s: 62 / 420,
  xs: 38 / 420,
  xxs: 16 / 420
});
var SIZES = Object.freeze(Object.keys(SIZE_RATIOS));
var aliases = Object.freeze({
  extralarge: "xl",
  large: "l",
  medium: "m",
  small: "s",
  extrasmall: "xs"
});
function normaliseSize(value, fallback = "m") {
  const key = String(value ?? "").trim().toLowerCase();
  const size = aliases[key] || key;
  return SIZES.includes(size) ? size : SIZES.includes(fallback) ? fallback : "m";
}
function sizeVariable(value, fallback = "m") {
  return `var(--z-size-${normaliseSize(value, fallback)})`;
}

// src/components/surface.js
var HTMLElementBase = globalThis.HTMLElement || class {
};
var own = (node, key) => Object.prototype.hasOwnProperty.call(node, key);
var booleanAttributes = /* @__PURE__ */ new Set(["circle", "square", "button", "disabled", "slider", "knob"]);
var attributes = [
  "size",
  "distance",
  "angle",
  "circle",
  "square",
  "label",
  "label-pos",
  "image-path",
  "to-view",
  "button",
  "disabled",
  "slider",
  "progress",
  "knob",
  "qty",
  "unit",
  "min",
  "max",
  "step",
  "pos"
];
var defaults = { distance: 100, angle: 0, progress: 0, qty: 0, min: 0, max: 100, step: 1 };
var properties = Object.fromEntries(attributes.map((attribute) => [
  attribute.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()),
  attribute
]));
function numberAttribute(element, name, fallback) {
  const text = element.getAttribute(name);
  const value = text === null || text.trim() === "" ? fallback : Number(text);
  return Number.isFinite(value) ? value : fallback;
}
function part(parent, name, tag = "div", className = "") {
  let node = Array.from(parent.children).find((child) => child.dataset.zPart === name);
  if (!node) {
    node = parent.ownerDocument.createElement(tag);
    node.dataset.zPart = name;
    if (className) node.className = className;
    parent.append(node);
  }
  return node;
}
function isDefinition(element) {
  const view = element.localName === "z-view" ? element : element.closest("z-view");
  return view?.hasAttribute("name") && !view.hasAttribute("data-view-name") && view.parentElement?.localName === "z-canvas";
}
function logicalParent(element) {
  return element.parentElement?.closest("z-view, z-spot, z-list") || null;
}
function setAttribute(element, name, value) {
  if (element.getAttribute(name) !== String(value)) element.setAttribute(name, String(value));
}
var ZSurface = class _ZSurface extends HTMLElementBase {
  static get observedAttributes() {
    return attributes;
  }
  constructor() {
    super();
    this._surfaceUpdating = false;
    this._surfaceQueued = false;
    this._surfaceListening = false;
    this._surfaceParts = null;
    this._surfaceObserver = null;
    this._surfaceResizeObserver = null;
    this._onSurfaceAction = (event) => this._handleAction(event);
    this._onSurfaceDisabled = (event) => {
      if (this.hasAttribute("disabled") && event.target.closest?.("z-spot") === this) {
        event.preventDefault();
        event.stopImmediatePropagation();
      }
    };
    this._onSurfaceKey = (event) => this._handleKey(event);
    this._onSurfaceValue = (event) => this._handleValue(event);
    this._onSurfaceScroll = () => this._syncScrollValue();
  }
  connectedCallback() {
    if (isDefinition(this)) return;
    this.refresh();
  }
  disconnectedCallback() {
    queueMicrotask(() => {
      if (this.isConnected) return;
      this._surfaceObserver?.disconnect();
      this._surfaceResizeObserver?.disconnect();
      this._unlisten();
    });
  }
  attributeChangedCallback() {
    if (this.isConnected && !isDefinition(this)) this.refresh();
  }
  get contentElement() {
    return this._surfaceParts?.content || null;
  }
  refresh() {
    if (this._surfaceUpdating || !this.isConnected || isDefinition(this)) return this;
    this._surfaceUpdating = true;
    this._surfaceObserver?.disconnect();
    try {
      for (const property of Object.keys(properties)) {
        if (own(this, property)) {
          const value = this[property];
          delete this[property];
          this[property] = value;
        }
      }
      this.classList.add("z-surface", `z-${this.surfaceType}`);
      if (this.surfaceType === "spot") this.classList.add("satellite");
      const body = part(this, "surface", "div", "z-surface-body");
      this._surfaceParts = {
        body,
        plate: part(this, "plate", "div", "z-plate"),
        image: part(body, "image", "div", "z-image"),
        content: part(body, "content", "div", "z-content"),
        media: part(body, "media", "div", "z-media"),
        extensions: part(this, "extensions", "div", "z-extensions")
      };
      this._adoptContent();
      this._syncAppearance();
      this._syncControls();
      this._syncPosition();
      this._syncScroll();
      this._listen();
    } finally {
      this._surfaceUpdating = false;
      this._observe();
    }
    return this;
  }
  _adoptContent() {
    const slots = this._surfaceParts;
    const authored = [this, slots.content, slots.image, slots.media, slots.extensions].flatMap((holder) => Array.from(holder.childNodes));
    for (const node of authored) {
      if (node.nodeType === 1 && node.hasAttribute("data-z-part")) continue;
      const slot = node.nodeType === 1 ? node.getAttribute("slot") : null;
      const radial = node.nodeType === 1 && node.matches("z-spot, z-list");
      const target = slot === "image" ? slots.image : slot === "media" ? slots.media : slot === "extension" || radial ? slots.extensions : slots.content;
      if (node.parentNode !== target) target.append(node);
    }
    for (const node of Array.from(slots.extensions.children)) {
      if (node.localName === "z-spot") this._adoptSpot(node);
    }
  }
  _adoptSpot(spot) {
    const extensions = this._surfaceParts?.extensions;
    if (!extensions || spot === this) return;
    const layout = part(extensions, "layout", "div", "bigbang z-orbit-layout");
    const gravity = part(layout, "gravity", "div", "gravity-spot");
    let ring = spot.parentElement;
    if (ring?.dataset.zPart !== "spot-orbit" || ring.parentElement !== gravity) {
      ring = this.ownerDocument.createElement("div");
      ring.className = "orbit-12 z-spot-orbit";
      ring.dataset.zPart = "spot-orbit";
      gravity.append(ring);
      ring.append(spot);
    }
    this._sizeSpotOrbit(spot, ring);
  }
  _sizeSpotOrbit(spot, ring) {
    const size = sizeVariable(this.getAttribute("size"), this.defaultSize);
    const distance = numberAttribute(spot, "distance", 100);
    ring.style.setProperty("--o-force", `calc(${size} * ${distance / 100})`);
    ring.style.setProperty("--o-force-ratio", "1");
    ring.style.setProperty("--o-range", "0deg");
  }
  _syncPosition() {
    const size = normaliseSize(this.getAttribute("size"), this.defaultSize);
    this.style.setProperty("--z-diameter", sizeVariable(size));
    this.dataset.zSize = size;
    if (this.surfaceType === "spot") {
      this.style.setProperty("--o-from", `${numberAttribute(this, "angle", 0)}deg`);
      this.style.setProperty("--o-offset", "0deg");
      const parent = logicalParent(this);
      if (parent instanceof _ZSurface) parent._adoptSpot(this);
    }
    const gravity = this._surfaceParts.extensions.querySelector(':scope > [data-z-part="layout"] > [data-z-part="gravity"]');
    if (gravity) {
      for (const ring of gravity.children) {
        if (ring.dataset.zPart !== "spot-orbit") continue;
        const spot = Array.from(ring.children).find((child) => child.localName === "z-spot");
        if (spot) this._sizeSpotOrbit(spot, ring);
        else ring.remove();
      }
    }
  }
  _syncAppearance() {
    const square = this.hasAttribute("square");
    this.classList.toggle("is-square", square);
    this.classList.toggle("is-circle", !square);
    this.classList.toggle("z-button", this.hasAttribute("button"));
    const disabled = this.hasAttribute("disabled");
    this.classList.toggle("is-disabled", disabled);
    const target = this.getAttribute("to-view");
    const navigable = this.surfaceType === "spot" && Boolean(target) && !disabled;
    this.classList.toggle("zoom-me", navigable);
    if (navigable) this.dataset.to = target;
    else delete this.dataset.to;
    if (this.surfaceType === "spot") {
      const button = Boolean(target) || this.hasAttribute("button");
      if (button) {
        setAttribute(this, "role", "button");
        setAttribute(this, "tabindex", disabled ? "-1" : "0");
        setAttribute(this, "aria-disabled", disabled ? "true" : "false");
        this.dataset.zInteractive = "";
      } else if (this.hasAttribute("data-z-interactive")) {
        this.removeAttribute("role");
        this.removeAttribute("tabindex");
        this.removeAttribute("aria-disabled");
        delete this.dataset.zInteractive;
      }
    }
    const image = this._surfaceParts.image;
    let source = Array.from(image.children).find((node) => node.dataset.zPart === "image-source");
    const path = this.getAttribute("image-path");
    if (path) {
      source ||= part(image, "image-source", "img", "z-image-source");
      setAttribute(source, "src", path);
      setAttribute(source, "alt", "");
    } else source?.remove();
    image.hidden = !image.childNodes.length;
    this._surfaceParts.media.hidden = !this._surfaceParts.media.childNodes.length;
    const labelText = this.getAttribute("label") || "";
    const quantityOutside = this.getAttribute("pos") === "outside" && this.hasAttribute("qty") && !this.hasAttribute("knob");
    let label = Array.from(this.children).find((node) => node.dataset.zPart === "label");
    if (labelText || quantityOutside) {
      label ||= part(this, "label", "div", "z-label");
      const position = this.getAttribute("label-pos") || "bottom";
      for (const token of ["top", "bottom", "left", "right", "center"]) label.classList.toggle(token, token === position);
      label.dataset.position = position;
      const inside = part(label, "label-text", "span", "inside");
      if (inside.textContent !== labelText) inside.textContent = labelText;
    } else label?.remove();
    let quantity = this.querySelector(':scope > [data-z-part="label"] > [data-z-part="quantity"], :scope > [data-z-part="surface"] > [data-z-part="content"] > [data-z-part="quantity"]');
    if (this.hasAttribute("qty") && !this.hasAttribute("knob")) {
      const holder = quantityOutside ? label : this._surfaceParts.content;
      if (!quantity) quantity = part(holder, "quantity", "span", "z-quantity");
      else if (quantity.parentElement !== holder) holder.append(quantity);
      const text = `${numberAttribute(this, "qty", 0)}${this.getAttribute("unit") || ""}`;
      if (quantity.textContent !== text) quantity.textContent = text;
    } else quantity?.remove();
  }
  _syncControls() {
    for (const [flag, tag, className, forwarded] of [
      ["slider", "z-slider", "z-surface-slider", ["progress"]],
      ["knob", "z-knob", "z-surface-knob", ["qty", "unit", "min", "max", "step", "disabled"]]
    ]) {
      let control = Array.from(this.children).find((node) => node.dataset.zPart === flag);
      if (this.hasAttribute(flag) && (flag !== "slider" || !this.hasAttribute("square"))) {
        control ||= part(this, flag, tag, className);
        for (const attribute of forwarded) {
          if (this.hasAttribute(attribute)) setAttribute(control, attribute, this.getAttribute(attribute));
          else control.removeAttribute(attribute);
        }
        setAttribute(control, "aria-label", this.getAttribute("aria-label") || this.getAttribute("label") || (flag === "knob" ? "Value" : "Progress"));
      } else control?.remove();
    }
    this._surfaceParts.content.hidden = this.hasAttribute("knob");
  }
  _syncScroll() {
    if (this.surfaceType !== "view") return;
    const content = this._surfaceParts.content;
    const square = this.hasAttribute("square") || !this.hasAttribute("circle") && this.closest("[data-shape]")?.dataset.shape === "square";
    const overflowing = !square && content.clientHeight > 0 && content.scrollHeight > content.clientHeight + 1;
    let control = Array.from(this.children).find((node) => node.dataset.zPart === "scroll");
    if (overflowing) {
      control ||= part(this, "scroll", "z-scroll", "z-surface-scroll");
      setAttribute(control, "aria-label", "Scroll content");
      this._syncScrollValue();
    } else control?.remove();
  }
  _syncScrollValue() {
    const control = Array.from(this.children).find((node) => node.dataset.zPart === "scroll");
    if (!control || !this._surfaceParts) return;
    const content = this._surfaceParts.content;
    const range = content.scrollHeight - content.clientHeight;
    setAttribute(control, "scroll-val", range > 0 ? -45 + 90 * content.scrollTop / range : -45);
  }
  _listen() {
    if (this._surfaceListening) return;
    this._surfaceListening = true;
    for (const type of ["mouseup", "touchend", "click"]) {
      this.addEventListener(type, this._onSurfaceAction);
      this.addEventListener(type, this._onSurfaceDisabled, true);
    }
    this.addEventListener("keydown", this._onSurfaceKey);
    this.addEventListener("input", this._onSurfaceValue, true);
    this.addEventListener("change", this._onSurfaceValue, true);
    this._surfaceParts.content.addEventListener("scroll", this._onSurfaceScroll, { passive: true });
  }
  _unlisten() {
    if (!this._surfaceListening) return;
    this._surfaceListening = false;
    for (const type of ["mouseup", "touchend", "click"]) {
      this.removeEventListener(type, this._onSurfaceAction);
      this.removeEventListener(type, this._onSurfaceDisabled, true);
    }
    this.removeEventListener("keydown", this._onSurfaceKey);
    this.removeEventListener("input", this._onSurfaceValue, true);
    this.removeEventListener("change", this._onSurfaceValue, true);
    this._surfaceParts?.content.removeEventListener("scroll", this._onSurfaceScroll);
  }
  _handleAction(event) {
    if (this.surfaceType !== "spot") return;
    if (event.target.closest?.("z-spot") !== this) return;
    const control = event.target.closest?.("button, a, input, select, textarea, z-knob, z-scroll");
    if (event.type === "click" && !this.getAttribute("to-view") && !this.parentElement?.closest(".zoom-me")) return;
    if (this.hasAttribute("disabled") || !this.getAttribute("to-view") || control && control !== this) {
      event.stopPropagation();
      if (this.hasAttribute("disabled")) event.preventDefault();
    }
  }
  _handleKey(event) {
    if (this.surfaceType !== "spot" || event.target !== this) return;
    if (this.hasAttribute("disabled")) {
      if (event.key === "Enter" || event.key === " ") {
        event.preventDefault();
        event.stopPropagation();
      }
      return;
    }
    if (this.getAttribute("to-view") || !this.hasAttribute("button")) return;
    if ((event.key === "Enter" || event.key === " ") && !event.repeat) {
      event.preventDefault();
      event.stopPropagation();
      this.click();
    }
  }
  _handleValue(event) {
    if (event.target.parentElement === this && event.target.dataset.zPart === "scroll") {
      const value = Number(event.detail?.scrollVal ?? event.detail?.value);
      if (Number.isFinite(value)) {
        const content = this._surfaceParts.content;
        content.scrollTop = (Math.min(45, Math.max(-45, value)) + 45) / 90 * Math.max(0, content.scrollHeight - content.clientHeight);
      }
      event.stopPropagation();
      return;
    }
    if (event.target.parentElement !== this || event.target.dataset.zPart !== "knob") return;
    const qty = event.detail?.qty ?? event.detail?.value;
    if (!Number.isFinite(Number(qty))) return;
    setAttribute(this, "qty", Number(qty));
    event.stopImmediatePropagation();
    this.dispatchEvent(new CustomEvent(event.type, {
      detail: { ...event.detail, qty: Number(qty), value: Number(qty) },
      bubbles: true,
      composed: true
    }));
  }
  _observe() {
    if (!this.isConnected) return;
    this._surfaceObserver ||= new MutationObserver((records) => {
      const holders = [
        this,
        this._surfaceParts?.extensions,
        this._surfaceParts?.content,
        this._surfaceParts?.image,
        this._surfaceParts?.media
      ];
      if (records.some((record) => record.type === "attributes" || holders.includes(record.target) && record.addedNodes.length || this._surfaceParts?.content.contains(record.target))) this._queueRefresh();
    });
    this._surfaceObserver.observe(this, { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: ["slot"] });
    if (this.surfaceType === "view") {
      this._surfaceResizeObserver ||= new ResizeObserver(() => this._syncScroll());
      this._surfaceResizeObserver.disconnect();
      this._surfaceResizeObserver.observe(this._surfaceParts.content);
      for (const child of this._surfaceParts.content.children) this._surfaceResizeObserver.observe(child);
    }
  }
  _queueRefresh() {
    if (this._surfaceQueued) return;
    this._surfaceQueued = true;
    queueMicrotask(() => {
      this._surfaceQueued = false;
      this.refresh();
    });
  }
};
for (const [property, attribute] of Object.entries(properties)) {
  Object.defineProperty(ZSurface.prototype, property, {
    configurable: true,
    get() {
      if (booleanAttributes.has(attribute)) return this.hasAttribute(attribute);
      if (own(defaults, attribute)) return numberAttribute(
        this,
        attribute,
        attribute === "distance" && this.surfaceType === "view" ? 0 : defaults[attribute]
      );
      if (attribute === "size") return normaliseSize(this.getAttribute(attribute), this.defaultSize);
      return this.getAttribute(attribute) ?? "";
    },
    set(value) {
      if (booleanAttributes.has(attribute)) this.toggleAttribute(attribute, Boolean(value));
      else if (value === null || value === void 0) this.removeAttribute(attribute);
      else setAttribute(this, attribute, value);
    }
  });
}
function hydrateSurfaces(root) {
  if (!root) return;
  if (root instanceof ZSurface) root.refresh();
  for (const surface of root.querySelectorAll?.("z-view, z-spot") || []) {
    if (surface instanceof ZSurface) surface.refresh();
  }
}

// src/core.js
var THEMES = Object.freeze(["white", "light-blue", "black", "purple", "orange", "yellow", "blue", "green", "red", "gray"]);
var MODES = Object.freeze(["light", "light-filled", "dark", "dark-filled"]);
var instances = /* @__PURE__ */ new WeakMap();
var sequence = 0;
function choice(value, allowed, label) {
  if (!allowed.includes(value)) throw new TypeError(`Zircle: unknown ${label} "${value}". Use ${allowed.join(", ")}.`);
  return value;
}
async function createZircle(options = {}) {
  if (typeof document === "undefined") throw new Error("Zircle: createZircle() needs a browser. Call it after mounting your component.");
  if (options.signal?.aborted) throw new DOMException("Zircle initialization was cancelled.", "AbortError");
  const mount = typeof options.mount === "string" ? document.querySelector(options.mount) : options.mount;
  if (!(mount instanceof HTMLElement) || !mount.isConnected) throw new Error("Zircle: mount must be a connected HTML element or a matching selector.");
  if (mount.getRootNode() !== document) throw new Error("Zircle: Zumly requires a mount in the document light DOM.");
  if (instances.has(mount)) throw new Error("Zircle: this element already has an instance. Destroy it before mounting again.");
  const views = options.views;
  if (!views || typeof views !== "object" || !Object.keys(views).length) throw new TypeError("Zircle: provide a nonempty views map.");
  const initialView = options.initialView ?? Object.keys(views)[0];
  if (!Object.hasOwn(views, initialView)) throw new Error(`Zircle: initial view "${initialView}" is not registered.`);
  let theme = choice(options.theme ?? "black", THEMES, "theme");
  let mode = choice(options.mode ?? "dark", MODES, "mode");
  let shape = choice(options.shape ?? "circle", ["circle", "square"], "shape");
  let destroyed = false;
  let abortListener;
  const stage = document.createElement("div");
  stage.className = "zircle z-stage";
  const canvas = document.createElement("div");
  canvas.className = "zircle zumly-canvas";
  canvas.dataset.zircleInstance = String(++sequence);
  canvas.setAttribute("aria-label", options.label ?? "Zircle");
  const applyStyle = () => {
    canvas.dataset.theme = theme;
    canvas.dataset.mode = mode;
    canvas.dataset.shape = shape;
    stage.dataset.theme = theme;
    stage.dataset.mode = mode;
    stage.dataset.shape = shape;
  };
  applyStyle();
  const originalPosition = mount.style.position;
  const needsPosition = getComputedStyle(mount).position === "static";
  if (needsPosition) mount.style.position = "relative";
  stage.append(canvas);
  mount.append(stage);
  const resize = () => {
    const { width, height } = mount.getBoundingClientRect();
    const side = Math.max(1, Math.min(840, width, height));
    canvas.style.width = `${side}px`;
    canvas.style.height = `${side}px`;
    canvas.style.left = `${(width - side) / 2}px`;
    canvas.style.top = `${(height - side) / 2}px`;
    const diameter = side * 0.5;
    for (const [size, ratio] of Object.entries({ xxl: 1, xl: 260 / 420, l: 160 / 420, m: 100 / 420, s: 62 / 420, xs: 38 / 420, xxs: 16 / 420 })) {
      canvas.style.setProperty(`--z-size-${size}`, `${diameter * ratio}px`);
    }
    Orbit.refresh(canvas);
  };
  resize();
  const observer = new ResizeObserver(resize);
  observer.observe(mount);
  const app = new gt({
    mount: `[data-zircle-instance="${sequence}"]`,
    initialView,
    views,
    transitions: { driver: "css", duration: "700ms", ease: "ease-in-out", cover: "width", effects: ["blur(1px) opacity(0.35)", "blur(3px) opacity(0.12)"], hideTrigger: false, ...options.transitions },
    depthNav: false,
    lateralNav: false,
    inputs: { click: true, touch: true, keyboard: true, wheel: false, ...options.inputs },
    debug: options.debug ?? false,
    componentContext: options.context ?? /* @__PURE__ */ new Map(),
    preload: options.preload,
    deferred: false
  });
  const events = new EventTarget();
  const emit2 = (type, detail) => {
    events.dispatchEvent(new CustomEvent(type, { detail }));
    mount.dispatchEvent(new CustomEvent(`zircle:${type}`, { detail, bubbles: true }));
  };
  const refresh = () => {
    hydrateSurfaces(canvas);
    resize();
  };
  app.on("viewMounted", ({ node, viewName }) => {
    hydrateSurfaces(node);
    Orbit.refresh(node);
    if (node.classList.contains("is-current-view") && !node.style.transform) {
      node.style.transform = `translate(${(canvas.clientWidth - node.offsetWidth) / 2}px, ${(canvas.clientHeight - node.offsetHeight) / 2}px)`;
    }
    emit2("viewmount", { view: viewName, node });
  });
  const back = document.createElement("button");
  back.type = "button";
  back.className = "z-back z-depth-nav";
  back.textContent = "\u2190";
  back.setAttribute("aria-label", options.backLabel ?? "Go back");
  back.hidden = true;
  back.addEventListener("click", () => api.back());
  const notifyNavigation = () => {
    back.hidden = app.zoomLevel() <= 1;
    if (options.backButton !== false) canvas.append(back);
    emit2("viewchange", { view: app.getCurrentViewName(), depth: Math.max(0, app.zoomLevel() - 1) });
  };
  for (const event of ["afterZoomIn", "afterZoomOut", "afterLateral"]) app.on(event, notifyNavigation);
  if (options.router) app.use(Ze, typeof options.router === "object" ? options.router : void 0);
  const validateTarget = (name) => {
    if (destroyed) throw new Error("Zircle: this instance has been destroyed.");
    if (!Object.hasOwn(views, name)) throw new Error(`Zircle: view "${name}" is not registered.`);
  };
  const api = {
    app,
    canvas,
    mount,
    getCurrentViewName: () => app.getCurrentViewName(),
    getHistory: () => app.storedViews.map((stage2) => stage2.views[0].viewName),
    getHistoryLength: () => app.storedViews.length,
    getTheme: () => theme,
    getMode: () => mode,
    getShape: () => shape,
    setTheme(value) {
      theme = choice(value, THEMES, "theme");
      applyStyle();
      emit2("stylechange", { theme, mode, shape });
      return api;
    },
    setMode(value) {
      mode = choice(value, MODES, "mode");
      applyStyle();
      emit2("stylechange", { theme, mode, shape });
      return api;
    },
    setShape(value) {
      shape = choice(value, ["circle", "square"], "shape");
      applyStyle();
      hydrateSurfaces(canvas);
      emit2("stylechange", { theme, mode, shape });
      return api;
    },
    async goTo(name, opts = {}) {
      validateTarget(name);
      await app.goTo(name, opts);
    },
    async zoomTo(name, opts = {}) {
      validateTarget(name);
      await app.zoomTo(name, opts);
    },
    async setView(target, opts = {}) {
      const name = typeof target === "string" ? target : target?.name;
      validateTarget(name);
      await app.goTo(name, { ...opts, props: typeof target === "object" ? target.params ?? opts.props : opts.props });
    },
    async back() {
      if (!destroyed) await app.back();
    },
    async zoomOut() {
      if (!destroyed) await app.zoomOut();
    },
    goBack() {
      return api.back();
    },
    refresh,
    on(type, handler) {
      events.addEventListener(type, handler);
      return () => events.removeEventListener(type, handler);
    },
    destroy() {
      if (destroyed) return;
      destroyed = true;
      if (abortListener) options.signal.removeEventListener("abort", abortListener);
      observer.disconnect();
      app.destroy();
      stage.remove();
      if (needsPosition && mount.style.position === "relative") mount.style.position = originalPosition;
      instances.delete(mount);
      emit2("destroy", {});
    }
  };
  instances.set(mount, api);
  if (options.signal) {
    abortListener = () => api.destroy();
    options.signal.addEventListener("abort", abortListener, { once: true });
  }
  try {
    await app.init();
    if (options.signal?.aborted) throw new DOMException("Zircle initialization was cancelled.", "AbortError");
    if (!app.isValid || !app.getCurrentViewName()) throw new Error(`Zircle: could not render initial view "${initialView}".`);
    refresh();
    notifyNavigation();
    emit2("ready", { instance: api });
    return api;
  } catch (error) {
    api.destroy();
    throw error;
  }
}

// src/components/z-canvas.js
var HTMLElementBase2 = globalThis.HTMLElement ?? class {
};
var ZCanvas = class extends HTMLElementBase2 {
  static observedAttributes = ["theme", "mode", "shape"];
  connectedCallback() {
    this._upgradeProperty("views");
    this._upgradeProperty("options");
    queueMicrotask(() => {
      if (this.isConnected && !this._ready) this.init();
    });
  }
  disconnectedCallback() {
    queueMicrotask(() => {
      if (!this.isConnected) this.destroy();
    });
  }
  _upgradeProperty(name) {
    if (Object.hasOwn(this, name)) {
      const value = this[name];
      delete this[name];
      this[name] = value;
    }
  }
  get ready() {
    return this._ready ?? this.init();
  }
  get instance() {
    return this._instance ?? null;
  }
  get views() {
    return this._views;
  }
  set views(value) {
    this._views = value;
  }
  get options() {
    return this._options;
  }
  set options(value) {
    this._options = value;
  }
  init() {
    if (this._ready) return this._ready;
    const generation = this._generation = (this._generation ?? 0) + 1;
    this._controller = new AbortController();
    const signal = this._controller.signal;
    const views = { ...this._views };
    let templateError;
    for (const template2 of this.querySelectorAll(":scope > template[data-view]")) {
      const name = template2.dataset.view;
      if (Object.hasOwn(views, name)) {
        templateError = new Error(`Zircle: duplicate view "${name}".`);
        break;
      }
      if (!name.trim() || template2.content.children.length !== 1) {
        templateError = new Error("Zircle: each view template needs a nonempty data-view name and exactly one root element.");
        break;
      }
      views[name] = () => template2.content.firstElementChild.cloneNode(true);
    }
    this._ready = (templateError ? Promise.reject(templateError) : createZircle({
      ...this._options,
      mount: this,
      views,
      signal,
      initialView: this.getAttribute("initial-view") ?? this._options?.initialView ?? Object.keys(views)[0],
      theme: this.getAttribute("theme") ?? this._options?.theme,
      mode: this.getAttribute("mode") ?? this._options?.mode,
      shape: this.getAttribute("shape") ?? this._options?.shape,
      label: this.getAttribute("aria-label") ?? this._options?.label,
      router: this.hasAttribute("router") || this._options?.router
    })).then((instance) => {
      if (generation !== this._generation || !this.isConnected) {
        instance.destroy();
        return null;
      }
      this._instance = instance;
      for (const name of ["theme", "mode", "shape"]) this._applyStyleAttribute(name);
      this.setAttribute("data-ready", "");
      return instance;
    }).catch((error) => {
      if (signal.aborted) return null;
      throw error;
    });
    this._ready.catch((error) => this.dispatchEvent(new CustomEvent("zircle:error", { detail: { error }, bubbles: true })));
    return this._ready;
  }
  attributeChangedCallback(name, oldValue, value) {
    if (oldValue === value || !this._instance) return;
    this._applyStyleAttribute(name);
  }
  _applyStyleAttribute(name) {
    const defaults2 = { theme: "black", mode: "dark", shape: "circle" };
    const value = this.getAttribute(name) ?? this._options?.[name] ?? defaults2[name];
    const suffix = `${name[0].toUpperCase()}${name.slice(1)}`;
    if (this._instance[`get${suffix}`]() !== value) this._instance[`set${suffix}`](value);
  }
  async setView(name, options) {
    return (await this.ready)?.setView(name, options);
  }
  async back() {
    return (await this.ready)?.back();
  }
  destroy() {
    this._generation = (this._generation ?? 0) + 1;
    this._controller?.abort();
    this._controller = null;
    this._instance?.destroy();
    this._instance = null;
    this._ready = null;
    this.removeAttribute("data-ready");
  }
};

// src/components/z-view.js
var ZView = class extends ZSurface {
  get defaultSize() {
    return "xxl";
  }
  get surfaceType() {
    return "view";
  }
};

// src/components/z-spot.js
var ZSpot = class extends ZSurface {
  get defaultSize() {
    return "m";
  }
  get surfaceType() {
    return "spot";
  }
};

// src/components/control-utils.js
var HTMLElementBase3 = globalThis.HTMLElement ?? class {
};
var FULL_RING_RANGE = "359.99deg";
function isViewDefinition(element) {
  const view = element.closest("z-view");
  return view?.hasAttribute("name") && !view.hasAttribute("data-view-name") && view.parentElement?.localName === "z-canvas";
}
function numberAttribute2(element, name, fallback) {
  const raw = element.getAttribute(name);
  const value = raw === null || raw.trim() === "" ? NaN : Number(raw);
  return Number.isFinite(value) ? value : fallback;
}
function reflectNumber(element, name, value) {
  if (value === null || value === void 0) element.removeAttribute(name);
  else if (Number.isFinite(Number(value))) element.setAttribute(name, String(value));
}
function emit(element, type, detail, options = {}) {
  return element.dispatchEvent(new element.ownerDocument.defaultView.CustomEvent(
    type,
    { bubbles: true, composed: true, detail, ...options }
  ));
}
function upgradeProperties(element, names) {
  for (const name of names) {
    if (!Object.prototype.hasOwnProperty.call(element, name)) continue;
    const value = element[name];
    delete element[name];
    element[name] = value;
  }
}
function createRing(element, withHandle = false) {
  const document2 = element.ownerDocument;
  element.classList.add("gravity-spot");
  const orbit = Array.from(element.children).find((node) => node.classList.contains("z-control-orbit")) ?? document2.createElement("div");
  orbit.className = "orbit-12 z-control-orbit";
  orbit.setAttribute("aria-hidden", "true");
  const progress = orbit.querySelector("o-progress") ?? document2.createElement("o-progress");
  progress.className = "z-control-progress";
  progress.setAttribute("variant", "stroke");
  progress.setAttribute("max", "100");
  orbit.append(progress);
  let handle;
  if (withHandle) {
    handle = orbit.querySelector(".z-control-handle") ?? document2.createElement("span");
    handle.className = "satellite z-control-handle";
    handle.style.setProperty("--o-from", "0deg");
    handle.style.setProperty("--o-angle", "0deg");
    orbit.append(handle);
  }
  element.append(orbit);
  return { orbit, progress, handle };
}
var RadialControl = class extends HTMLElementBase3 {
  get step() {
    const value = numberAttribute2(this, "step", 1);
    return value > 0 ? value : 1;
  }
  set step(value) {
    reflectNumber(this, "step", value);
  }
  get unit() {
    return this.getAttribute("unit") ?? "";
  }
  set unit(value) {
    this.setAttribute("unit", value ?? "");
  }
  get disabled() {
    return this.hasAttribute("disabled");
  }
  set disabled(value) {
    this.toggleAttribute("disabled", Boolean(value));
  }
  get value() {
    return this.normalize(numberAttribute2(this, this.valueAttribute, this.min));
  }
  set value(value) {
    reflectNumber(this, this.valueAttribute, this.normalize(Number(value)));
  }
  normalize(value) {
    if (!Number.isFinite(value)) return this.min;
    const bounded = Math.min(this.max, Math.max(this.min, value));
    const stepped = this.min + Math.round((bounded - this.min) / this.step) * this.step;
    return Math.min(this.max, Math.max(this.min, Number(stepped.toFixed(10))));
  }
  upgradeProperties(names) {
    upgradeProperties(this, names);
  }
  connectedCallback() {
    if (isViewDefinition(this)) return;
    if (this._listeners) return;
    this._ring ??= createRing(this, true);
    this._ring.progress.toggleAttribute("interactive", this.controlKind === "scroll");
    if (this.controlKind === "knob" && !this._valueLabel) {
      this._valueLabel = this.querySelector(":scope > .z-knob-value") ?? this.ownerDocument.createElement("span");
      this._valueLabel.className = "z-knob-value";
      this._valueLabel.setAttribute("aria-hidden", "true");
      this._numberLabel = this._valueLabel.querySelector(".z-knob-number") ?? this.ownerDocument.createElement("span");
      this._numberLabel.className = "z-knob-number";
      this._unitLabel = this._valueLabel.querySelector(".z-knob-unit") ?? this.ownerDocument.createElement("span");
      this._unitLabel.className = "z-knob-unit";
      this._valueLabel.append(this._numberLabel, this._unitLabel);
      this.append(this._valueLabel);
    }
    this.classList.add(`z-${this.controlKind}`);
    this.setAttribute("role", "slider");
    if (!this.hasAttribute("aria-label") && !this.hasAttribute("aria-labelledby")) this.setAttribute("aria-label", this.defaultLabel);
    this._listeners = new this.ownerDocument.defaultView.AbortController();
    const options = { signal: this._listeners.signal };
    this.addEventListener("keydown", (event) => this._onKey(event), options);
    this.addEventListener("pointerdown", (event) => this._onPointerDown(event), options);
    this.ownerDocument.addEventListener("pointermove", (event) => this._onPointerMove(event), options);
    this.ownerDocument.addEventListener("pointerup", (event) => this._onPointerEnd(event), options);
    this.ownerDocument.addEventListener("pointercancel", (event) => this._onPointerEnd(event), options);
    this.addEventListener("click", (event) => event.stopPropagation(), options);
    this._render();
  }
  disconnectedCallback() {
    this._releasePointer();
    this._listeners?.abort();
    this._listeners = null;
  }
  attributeChangedCallback() {
    this._render();
  }
  _render() {
    if (!this._ring) return;
    const span = this.max - this.min;
    const progress = span ? (this.value - this.min) / span * 100 : 0;
    const angle = this.startAngle + progress / 100 * this.angleRange;
    this.style.setProperty(`--z-${this.controlKind}-angle`, `${angle}deg`);
    this._ring.progress.setAttribute("value", String(this.controlKind === "scroll" ? 100 : progress));
    this._ring.progress.style.setProperty("--o-range", this.angleRange === 360 ? FULL_RING_RANGE : `${this.angleRange}deg`);
    this._ring.progress.style.setProperty("--o-from", `${this.startAngle + 90}deg`);
    this._ring.handle.style.setProperty("--o-offset", `${angle}deg`);
    if (this._valueLabel) {
      this._numberLabel.textContent = String(this.value);
      this._unitLabel.textContent = this.unit;
      this._unitLabel.hidden = !this.unit;
    }
    this.setAttribute("aria-valuemin", String(this.min));
    this.setAttribute("aria-valuemax", String(this.max));
    this.setAttribute("aria-valuenow", String(this.value));
    this.setAttribute("aria-valuetext", `${this.value}${this.unit ? ` ${this.unit}` : ""}`);
    this.setAttribute("aria-disabled", String(this.disabled));
    if (this.disabled) {
      if (this.tabIndex >= 0) this._enabledTabIndex = this.tabIndex;
      this.tabIndex = -1;
      this._releasePointer();
    } else if (!this.hasAttribute("tabindex") || this.tabIndex === -1) this.tabIndex = this._enabledTabIndex ?? 0;
  }
  valueFromPointer(event) {
    const bounds = this.getBoundingClientRect();
    const angle = (Math.atan2(
      event.clientY - bounds.top - bounds.height / 2,
      event.clientX - bounds.left - bounds.width / 2
    ) * 180 / Math.PI + 360) % 360;
    return this.min + angle / 360 * (this.max - this.min);
  }
  _input(value) {
    const previous = this.value;
    this.value = value;
    if (this.value === previous) return false;
    emit(this, "input", this.eventDetail);
    return true;
  }
  _onKey(event) {
    if (this.disabled || event.altKey || event.ctrlKey || event.metaKey) return;
    const values = {
      ArrowUp: this.value + this.step,
      ArrowRight: this.value + this.step,
      ArrowDown: this.value - this.step,
      ArrowLeft: this.value - this.step,
      PageUp: this.value + this.step * 10,
      PageDown: this.value - this.step * 10,
      Home: this.min,
      End: this.max
    };
    if (!(event.key in values)) return;
    event.preventDefault();
    event.stopPropagation();
    if (this._input(values[event.key])) emit(this, "change", this.eventDetail);
  }
  _onPointerDown(event) {
    if (this.disabled || event.button !== 0 || this._pointerId !== void 0) return;
    event.preventDefault();
    event.stopPropagation();
    this.focus({ preventScroll: true });
    this._pointerId = event.pointerId;
    this._pointerStart = this.value;
    try {
      this.setPointerCapture(event.pointerId);
    } catch {
    }
    this._input(this.valueFromPointer(event));
  }
  _onPointerMove(event) {
    if (this._pointerId === void 0 || event.pointerId !== this._pointerId) return;
    event.preventDefault();
    this._input(this.valueFromPointer(event));
  }
  _onPointerEnd(event) {
    if (this._pointerId === void 0 || event.pointerId !== this._pointerId) return;
    const changed = this.value !== this._pointerStart;
    this._releasePointer();
    if (changed) emit(this, "change", this.eventDetail);
  }
  _releasePointer() {
    if (this._pointerId === void 0) return;
    try {
      this.releasePointerCapture(this._pointerId);
    } catch {
    }
    this._pointerId = void 0;
  }
};

// src/components/z-list.js
var ZList = class extends HTMLElementBase3 {
  static observedAttributes = ["per-page", "page", "size", "square"];
  get perPage() {
    return Math.max(1, Math.floor(numberAttribute2(this, "per-page", 5)));
  }
  set perPage(value) {
    reflectNumber(this, "per-page", value);
  }
  get page() {
    return Math.max(1, Math.min(this.pageCount || 1, Math.floor(numberAttribute2(this, "page", 1))));
  }
  set page(value) {
    reflectNumber(this, "page", value);
  }
  get pageCount() {
    return Math.ceil(this._spots().length / this.perPage);
  }
  get size() {
    return normaliseSize(this.getAttribute("size"), "xxl");
  }
  set size(value) {
    this.setAttribute("size", value);
  }
  get square() {
    return this.hasAttribute("square");
  }
  set square(value) {
    this.toggleAttribute("square", Boolean(value));
  }
  get items() {
    return this._items?.slice() ?? [];
  }
  set items(value) {
    if (!Array.isArray(value)) throw new TypeError("z-list.items must be an array.");
    this._items = value.slice();
    this._itemsDirty = true;
    if (this.isConnected && this._pager) this._render();
  }
  get renderItem() {
    return this._renderItem;
  }
  set renderItem(value) {
    if (value != null && typeof value !== "function") throw new TypeError("z-list.renderItem must be a function.");
    this._renderItem = value;
    this._itemsDirty = true;
    if (this.isConnected && this._pager) this._render();
  }
  connectedCallback() {
    if (isViewDefinition(this)) return;
    upgradeProperties(this, ["items", "renderItem", "page", "perPage", "size", "square"]);
    this.classList.add("z-list", "gravity-spot");
    if (!this._orbit) {
      this._orbit = this.querySelector(":scope > .z-list-orbit") ?? this.ownerDocument.createElement("div");
      this._orbit.className = "orbit-12 z-list-orbit";
      this._orbit.style.setProperty("--o-range", "0deg");
      this._pager = this.querySelector(":scope > .z-list-pagination") ?? this.ownerDocument.createElement("nav");
      this._pager.className = "z-list-pagination orbit-12";
      this._pager.style.setProperty("--o-range", "0deg");
      this._pager.setAttribute("aria-label", "List pages");
      this.append(this._orbit, this._pager);
    }
    if (!this._listeners) {
      this._listeners = new this.ownerDocument.defaultView.AbortController();
      this._pager.addEventListener("click", (event) => {
        const button = event.target.closest("button[data-page]");
        if (!button || button.disabled || !this._pager.contains(button)) return;
        event.stopPropagation();
        this.page = Number(button.dataset.page);
      }, { signal: this._listeners.signal });
    }
    this._observer ??= new this.ownerDocument.defaultView.MutationObserver(() => this._render());
    this._render();
  }
  disconnectedCallback() {
    this._observer?.disconnect();
    this._listeners?.abort();
    this._listeners = null;
  }
  attributeChangedCallback() {
    if (this.isConnected && this._pager) this._render();
  }
  next() {
    this.page += 1;
    return this.page;
  }
  previous() {
    this.page -= 1;
    return this.page;
  }
  _spots() {
    const direct = Array.from(this.children).filter((child) => child.localName === "z-spot");
    return this._orbit ? [...this._orbit.children, ...direct].filter((child) => child.localName === "z-spot") : direct;
  }
  _renderItems() {
    if (!this._itemsDirty || !this._items) return;
    const nodes = this._items.map((item, index) => {
      const rendered = this._renderItem ? this._renderItem(item, index) : typeof item === "object" && item !== null ? item.label ?? item.name ?? String(item) : String(item);
      if (rendered?.nodeType === 1 && rendered.localName === "z-spot") return rendered;
      const spot = this.ownerDocument.createElement("z-spot");
      if (rendered?.nodeType) spot.append(rendered);
      else spot.textContent = rendered == null ? "" : String(rendered);
      return spot;
    });
    for (const node of this._generated ?? []) if (!nodes.includes(node)) node.remove();
    this._generated = nodes;
    this._orbit.append(...nodes);
    this._itemsDirty = false;
  }
  _renderPager(count, page) {
    const first = count > 5 ? Math.max(1, Math.min(page - 2, count - 4)) : 1;
    const pages = Array.from({ length: Math.min(5, count) }, (_, index) => ({
      kind: "page",
      page: first + index,
      text: String(first + index),
      label: `Page ${first + index}`
    }));
    if (count > 5) {
      pages.unshift({ kind: "previous", page: Math.max(1, page - 1), text: "\u2039", label: "Previous page", disabled: page === 1 });
      pages.push({ kind: "next", page: Math.min(count, page + 1), text: "\u203A", label: "Next page", disabled: page === count });
    }
    const signature = pages.map((item) => item.kind === "page" ? item.page : item.kind).join(",");
    let restoreFocus;
    if (signature !== this._pagerSignature) {
      const active = this.ownerDocument.activeElement;
      if (active?.parentElement === this._pager) restoreFocus = { kind: active.dataset.kind, page: active.dataset.page };
      const fragment = this.ownerDocument.createDocumentFragment();
      for (const item of pages) {
        const button = this.ownerDocument.createElement("button");
        button.className = `z-list-page satellite${item.kind === "page" ? "" : ` z-list-${item.kind}`}`;
        button.type = "button";
        fragment.append(button);
      }
      this._pager.replaceChildren(fragment);
      this._pagerSignature = signature;
    }
    this._pager.hidden = count < 2;
    [...this._pager.children].forEach((button, index) => {
      const item = pages[index];
      button.dataset.page = String(item.page);
      button.dataset.kind = item.kind;
      button.textContent = item.text;
      button.setAttribute("aria-label", item.label);
      button.disabled = Boolean(item.disabled);
      button.style.setProperty("--o-offset", `${90 + (pages.length - 1) * 11 - index * 22}deg`);
      button.style.setProperty("--o-from", "0deg");
      button.style.setProperty("--o-angle", "0deg");
      if (item.kind === "page" && item.page === page) button.setAttribute("aria-current", "page");
      else button.removeAttribute("aria-current");
    });
    if (restoreFocus && count > 1) {
      const buttons = [...this._pager.children];
      const target = buttons.find((button) => button.dataset.kind === restoreFocus.kind && (restoreFocus.kind !== "page" || button.dataset.page === restoreFocus.page)) ?? buttons.find((button) => button.getAttribute("aria-current") === "page");
      target?.focus({ preventScroll: true });
    }
  }
  _render() {
    if (!this._pager || this._rendering) return;
    this._rendering = true;
    this._observer?.disconnect();
    try {
      this._renderItems();
      for (const child of Array.from(this.children)) if (child.localName === "z-spot") this._orbit.append(child);
      const spots = this._spots();
      const page = this.page;
      const count = this.pageCount;
      const first = (page - 1) * this.perPage;
      const visible = spots.slice(first, first + this.perPage);
      this._originalDistances ??= /* @__PURE__ */ new WeakMap();
      this._originalAlignments ??= /* @__PURE__ */ new WeakMap();
      for (const spot of this._managedSpots ?? []) {
        if (spots.includes(spot)) continue;
        const alignment = this._originalAlignments.get(spot);
        if (alignment) spot.style.setProperty("--o-aligment", alignment);
        else spot.style.removeProperty("--o-aligment");
        spot.classList.remove("at-center");
        spot.hidden = false;
      }
      this._managedSpots = spots;
      spots.forEach((spot) => {
        spot.hidden = !visible.includes(spot);
        if (!this._originalDistances.has(spot)) {
          const original = spot.hasAttribute("data-z-list-distance") ? spot.getAttribute("data-z-list-distance") || null : spot.getAttribute("distance");
          this._originalDistances.set(spot, original);
          spot.setAttribute("data-z-list-distance", original ?? "");
        }
        if (!this._originalAlignments.has(spot)) this._originalAlignments.set(spot, spot.style.getPropertyValue("--o-aligment"));
      });
      visible.forEach((spot, index) => {
        spot.setAttribute("angle", String(360 / visible.length * index - 90));
        spot.classList.toggle("at-center", visible.length === 1);
        const distance = visible.length === 1 ? "0" : this._originalDistances.get(spot) ?? "100";
        spot.setAttribute("distance", distance);
        spot.style.setProperty("--o-aligment", `calc(var(--o-radius) * ${1 - Math.max(0, numberAttribute2(spot, "distance", 100)) / 100})`);
      });
      this.style.setProperty("--z-list-size", `var(--z-size-${this.size}, var(--z-size-xxl))`);
      this.classList.toggle("is-square", this.hasAttribute("square"));
      this._renderPager(count, page);
      const previousPage = this._lastPage;
      this._lastPage = page;
      if (this.hasAttribute("page") && this.getAttribute("page") !== String(page)) this.setAttribute("page", String(page));
      if (previousPage !== void 0 && previousPage !== page) emit(this, "pagechange", { page, pageCount: count, previousPage });
    } finally {
      this._rendering = false;
      if (this.isConnected) {
        this._observer?.observe(this, { childList: true });
        this._observer?.observe(this._orbit, { childList: true });
      }
    }
  }
};

// src/components/z-dialog.js
var ZDialog = class extends HTMLElementBase3 {
  static observedAttributes = ["open", "visible", "duration", "self-close", "size", "square", "circle", "image-path", "aria-label", "aria-labelledby", "aria-describedby"];
  get open() {
    return this.hasAttribute("open") || this.hasAttribute("visible");
  }
  set open(value) {
    if (value) this.show();
    else this.close();
  }
  get visible() {
    return this.open;
  }
  set visible(value) {
    this.open = value;
  }
  get duration() {
    return Math.max(0, numberAttribute2(this, "duration", this.selfClose ? 1e4 : 0));
  }
  set duration(value) {
    reflectNumber(this, "duration", value);
  }
  get selfClose() {
    return this.hasAttribute("self-close");
  }
  set selfClose(value) {
    this.toggleAttribute("self-close", Boolean(value));
  }
  get size() {
    return normaliseSize(this.getAttribute("size"), "xxl");
  }
  set size(value) {
    this.setAttribute("size", value);
  }
  get square() {
    return this.hasAttribute("square");
  }
  set square(value) {
    this.toggleAttribute("square", Boolean(value));
  }
  get circle() {
    return this.hasAttribute("circle");
  }
  set circle(value) {
    this.toggleAttribute("circle", Boolean(value));
  }
  get imagePath() {
    return this.getAttribute("image-path") ?? "";
  }
  set imagePath(value) {
    if (value) this.setAttribute("image-path", value);
    else this.removeAttribute("image-path");
  }
  get returnValue() {
    return this._panel?.returnValue ?? "";
  }
  connectedCallback() {
    if (isViewDefinition(this)) return;
    upgradeProperties(this, ["open", "visible", "duration", "selfClose", "size", "imagePath", "square", "circle"]);
    this.classList.add("z-dialog");
    if (!this._panel) this._build();
    if (!this._listeners) {
      this._listeners = new this.ownerDocument.defaultView.AbortController();
      const options = { signal: this._listeners.signal };
      this._closeButton.addEventListener("click", () => this.close("", "button"), options);
      this._panel.addEventListener("cancel", (event) => {
        event.preventDefault();
        if (emit(this, "cancel", {}, { cancelable: true })) this.close("", "escape");
      }, options);
      this._panel.addEventListener("close", () => {
        if (this._visible && !this._panel.open) this.close(this._panel.returnValue, "form");
      }, options);
      this._panel.addEventListener("click", (event) => {
        event.stopPropagation();
        if (event.target !== this._panel) return;
        const rect = this._panel.getBoundingClientRect();
        if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) this.close("", "backdrop");
      }, options);
      this._panel.addEventListener("keydown", (event) => this._fallbackKeys(event), options);
      this._content.addEventListener("scroll", () => this._measureScroll(), { ...options, passive: true });
      this._scroll.addEventListener("input", (event) => {
        event.stopPropagation();
        const span = this._content.scrollHeight - this._content.clientHeight;
        if (span > 0) this._content.scrollTop = (event.detail.scrollVal + 45) / 90 * span;
      }, options);
    }
    this._observer ??= new this.ownerDocument.defaultView.MutationObserver(() => this._adoptContent());
    const Resize = this.ownerDocument.defaultView.ResizeObserver;
    if (Resize) this._resize ??= new Resize(() => this._measureScroll());
    this._adoptContent();
    this._observer.observe(this, { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: ["slot"] });
    this._render();
  }
  disconnectedCallback() {
    this._stopTimer();
    this._observer?.disconnect();
    this._resize?.disconnect();
    this._listeners?.abort();
    this._listeners = null;
    if (this._panel?.open) this._panel.close?.();
    this._panel?.removeAttribute("open");
    this._visible = false;
    this._restoreFocus();
  }
  attributeChangedCallback(name, oldValue, newValue) {
    if (oldValue === newValue || !this._panel || this._syncing) return;
    this._render();
    if (this._visible && (name === "duration" || name === "self-close")) this._startTimer();
  }
  show() {
    this.hidden = false;
    this.setAttribute("open", "");
    if (this.isConnected) this._render();
    return this;
  }
  close(returnValue = "", reason = "api") {
    const wasOpen = this._visible;
    this._syncing = true;
    this.removeAttribute("open");
    this.removeAttribute("visible");
    this._syncing = false;
    this._stopTimer();
    this._visible = false;
    if (this._panel) {
      this._panel.returnValue = String(returnValue);
      if (this._panel.open && typeof this._panel.close === "function") this._panel.close(String(returnValue));
      this._panel.removeAttribute("open");
    }
    this._restoreFocus();
    if (wasOpen) emit(this, "close", { returnValue: String(returnValue), reason });
    return this;
  }
  _build() {
    const document2 = this.ownerDocument;
    this._panel = this.querySelector(":scope > .z-dialog-panel") ?? document2.createElement("dialog");
    this._panel.className = "z-dialog-panel";
    this._image = this._panel.querySelector(":scope > img.z-dialog-image");
    this._closeButton = this._panel.querySelector(":scope > .z-dialog-close") ?? document2.createElement("button");
    this._closeButton.type = "button";
    this._closeButton.className = "z-dialog-close";
    this._closeButton.setAttribute("aria-label", "Close dialog");
    this._closeButton.textContent = "\xD7";
    this._content = this._panel.querySelector(":scope > .z-dialog-content") ?? document2.createElement("div");
    this._content.className = "z-dialog-content";
    this._progress = this._panel.querySelector(":scope > .z-dialog-progress") ?? document2.createElement("z-slider");
    this._progress.className = "z-dialog-progress";
    this._progress.setAttribute("aria-label", "Time until dialog closes");
    this._progress.setAttribute("aria-hidden", "true");
    this._scroll = this._panel.querySelector(":scope > .z-dialog-scroll") ?? document2.createElement("z-scroll");
    this._scroll.className = "z-dialog-scroll";
    this._scroll.setAttribute("aria-label", "Scroll dialog content");
    this._scroll.hidden = true;
    this._imageSlot = this._panel.querySelector(":scope > .z-dialog-image-slot") ?? document2.createElement("div");
    this._imageSlot.className = "z-dialog-image-slot";
    this._media = this._panel.querySelector(":scope > .z-dialog-media") ?? document2.createElement("div");
    this._media.className = "z-dialog-media";
    this._extensions = this._panel.querySelector(":scope > .z-dialog-extensions") ?? document2.createElement("div");
    this._extensions.className = "z-dialog-extensions";
    this._panel.append(this._imageSlot, this._content, this._media, this._extensions, this._progress, this._scroll, this._closeButton);
    this.append(this._panel);
  }
  _adoptContent() {
    const nodes = [...this.childNodes, ...this._content.childNodes, ...this._imageSlot.childNodes, ...this._media.childNodes, ...this._extensions.childNodes];
    for (const child of nodes) {
      if (child === this._panel) continue;
      const slot = child.nodeType === 1 ? child.getAttribute("slot") : null;
      const target = slot === "image" ? this._imageSlot : slot === "media" ? this._media : slot === "extension" ? this._extensions : this._content;
      if (child.parentNode !== target) target.append(child);
    }
    this._imageSlot.hidden = !this._imageSlot.childNodes.length || Boolean(this.imagePath);
    this._media.hidden = !this._media.childNodes.length;
    this._extensions.hidden = !this._extensions.childNodes.length;
    this._resize?.disconnect();
    if (this.isConnected) {
      this._resize?.observe(this._content);
      for (const child of this._content.children) this._resize?.observe(child);
    }
    this._measureScroll();
  }
  _render() {
    if (!this._panel) return;
    this.style.setProperty("--z-dialog-size", `var(--z-size-${this.size}, var(--z-size-xxl))`);
    this._panel.classList.toggle("is-square", this.hasAttribute("square"));
    this._panel.classList.toggle("is-circle", !this.hasAttribute("square"));
    for (const name of ["aria-label", "aria-labelledby", "aria-describedby"]) {
      if (this.hasAttribute(name)) this._panel.setAttribute(name, this.getAttribute(name));
      else this._panel.removeAttribute(name);
    }
    if (!this._panel.hasAttribute("aria-label") && !this._panel.hasAttribute("aria-labelledby")) this._panel.setAttribute("aria-label", "Dialog");
    if (this.imagePath) {
      if (!this._image) {
        this._image = this.ownerDocument.createElement("img");
        this._image.className = "z-dialog-image";
        this._image.alt = "";
        this._panel.prepend(this._image);
      }
      this._image.src = this.imagePath;
    } else if (this._image) {
      this._image.remove();
      this._image = null;
    }
    this._imageSlot.hidden = !this._imageSlot.childNodes.length || Boolean(this.imagePath);
    this._progress.hidden = this.duration === 0;
    if (!this.isConnected) return;
    if (this.open && !this._visible) {
      this._returnFocus = this.ownerDocument.activeElement;
      this.hidden = false;
      this._visible = true;
      this._panel.returnValue = "";
      if (typeof this._panel.showModal === "function") {
        this._panel.removeAttribute("open");
        this._panel.showModal();
      } else {
        this._panel.setAttribute("open", "");
        this._panel.setAttribute("role", "dialog");
        this._panel.setAttribute("aria-modal", "true");
        this._closeButton.focus();
      }
      this._startTimer();
      this._measureScroll();
      emit(this, "open", {});
    } else if (!this.open && this._visible) this.close("", "attribute");
  }
  _measureScroll() {
    if (!this._scroll) return;
    const span = this._content.scrollHeight - this._content.clientHeight;
    this._scroll.hidden = !this._visible || span < 2 || this.hasAttribute("square");
    this._scroll.scrollVal = span > 0 ? -45 + this._content.scrollTop / span * 90 : -45;
  }
  _startTimer() {
    this._stopTimer();
    if (!this.duration || !this._visible) return;
    const window2 = this.ownerDocument.defaultView;
    const duration = this.duration;
    const start = window2.performance.now();
    this._progress.progress = 0;
    const tick = () => {
      const elapsed = window2.performance.now() - start;
      this._progress.progress = Math.min(100, elapsed / duration * 100);
      if (this._visible && elapsed < duration) this._timerFrame = window2.requestAnimationFrame(tick);
    };
    this._timerFrame = window2.requestAnimationFrame(tick);
    this._timer = window2.setTimeout(() => {
      this._progress.progress = 100;
      this.close("", "timeout");
      emit(this, "done", { reason: "timeout" });
    }, duration);
  }
  _stopTimer() {
    const window2 = this.ownerDocument.defaultView;
    window2.clearTimeout(this._timer);
    window2.cancelAnimationFrame(this._timerFrame);
    this._timer = this._timerFrame = null;
  }
  _restoreFocus() {
    if (this._returnFocus?.isConnected && typeof this._returnFocus.focus === "function") this._returnFocus.focus({ preventScroll: true });
    this._returnFocus = null;
  }
  _fallbackKeys(event) {
    if (typeof this._panel.showModal === "function") return;
    if (event.key === "Escape") {
      event.preventDefault();
      if (emit(this, "cancel", {}, { cancelable: true })) this.close("", "escape");
    }
    if (event.key !== "Tab") return;
    const focusable = [...this._panel.querySelectorAll("a[href],button,input,select,textarea,[tabindex]")].filter((element) => !element.disabled && element.tabIndex >= 0 && !element.hidden && element.getClientRects().length);
    const first = focusable[0] ?? this._closeButton;
    const last = focusable.at(-1) ?? this._closeButton;
    if (event.shiftKey && this.ownerDocument.activeElement === first) {
      event.preventDefault();
      last.focus();
    } else if (!event.shiftKey && this.ownerDocument.activeElement === last) {
      event.preventDefault();
      first.focus();
    }
  }
};

// src/components/z-knob.js
var ZKnob = class extends RadialControl {
  static observedAttributes = ["qty", "min", "max", "step", "unit", "disabled"];
  get controlKind() {
    return "knob";
  }
  get min() {
    return numberAttribute2(this, "min", 0);
  }
  set min(value) {
    reflectNumber(this, "min", value);
  }
  get max() {
    return Math.max(this.min, numberAttribute2(this, "max", 100));
  }
  set max(value) {
    reflectNumber(this, "max", value);
  }
  get qty() {
    return this.value;
  }
  set qty(value) {
    this.value = value;
  }
  get valueAttribute() {
    return "qty";
  }
  get startAngle() {
    return 0;
  }
  get angleRange() {
    return 360;
  }
  get defaultLabel() {
    return "Value";
  }
  get eventDetail() {
    return { value: this.value, qty: this.value };
  }
  connectedCallback() {
    this.upgradeProperties(["qty", "min", "max", "step", "unit", "value", "disabled"]);
    super.connectedCallback();
  }
};

// src/components/z-slider.js
var ZSlider = class extends HTMLElementBase3 {
  static observedAttributes = ["progress", "unit"];
  get progress() {
    return Math.max(0, Math.min(100, numberAttribute2(this, "progress", 0)));
  }
  set progress(value) {
    reflectNumber(this, "progress", value);
  }
  get value() {
    return this.progress;
  }
  set value(value) {
    this.progress = value;
  }
  get unit() {
    return this.getAttribute("unit") ?? "%";
  }
  set unit(value) {
    this.setAttribute("unit", value ?? "");
  }
  connectedCallback() {
    if (isViewDefinition(this)) return;
    upgradeProperties(this, ["progress", "value", "unit"]);
    this._ring ??= createRing(this);
    this.classList.add("z-slider");
    this.setAttribute("role", "progressbar");
    this.setAttribute("aria-valuemin", "0");
    this.setAttribute("aria-valuemax", "100");
    if (!this.hasAttribute("aria-label") && !this.hasAttribute("aria-labelledby")) this.setAttribute("aria-label", "Progress");
    this._render();
  }
  attributeChangedCallback() {
    this._render();
  }
  _render() {
    if (!this._ring) return;
    this._ring.progress.setAttribute("value", String(this.progress));
    this._ring.progress.style.setProperty("--o-range", FULL_RING_RANGE);
    this._ring.progress.style.setProperty("--o-from", "0deg");
    this.setAttribute("aria-valuenow", String(this.progress));
    this.setAttribute("aria-valuetext", `${this.progress}${this.unit}`);
  }
};

// src/components/z-scroll.js
var ZScroll = class extends RadialControl {
  static observedAttributes = ["scroll-val", "step", "unit", "disabled"];
  get controlKind() {
    return "scroll";
  }
  get min() {
    return -45;
  }
  get max() {
    return 45;
  }
  get scrollVal() {
    return this.value;
  }
  set scrollVal(value) {
    this.value = value;
  }
  get valueAttribute() {
    return "scroll-val";
  }
  get startAngle() {
    return -45;
  }
  get angleRange() {
    return 90;
  }
  get defaultLabel() {
    return "Scroll position";
  }
  get eventDetail() {
    return { value: this.value, scrollVal: this.value };
  }
  connectedCallback() {
    this.upgradeProperties(["scrollVal", "step", "unit", "value", "disabled"]);
    super.connectedCallback();
  }
  valueFromPointer(event) {
    const bounds = this.getBoundingClientRect();
    return this.normalize(Math.atan2(
      event.clientY - bounds.top - bounds.height / 2,
      event.clientX - bounds.left - bounds.width / 2
    ) * 180 / Math.PI);
  }
};

// src/components/z-pagination.js
var ZPagination = class extends HTMLElementBase3 {
  static observedAttributes = ["index", "active", "angle", "distance", "size", "disabled"];
  get index() {
    return Math.max(0, Math.floor(numberAttribute2(this, "index", 0)));
  }
  set index(value) {
    reflectNumber(this, "index", value);
  }
  get active() {
    return Math.max(0, Math.floor(numberAttribute2(this, "active", 0)));
  }
  set active(value) {
    reflectNumber(this, "active", value);
  }
  get angle() {
    return numberAttribute2(this, "angle", 0);
  }
  set angle(value) {
    reflectNumber(this, "angle", value);
  }
  get distance() {
    return Math.max(0, numberAttribute2(this, "distance", 100));
  }
  set distance(value) {
    reflectNumber(this, "distance", value);
  }
  get size() {
    return normaliseSize(this.getAttribute("size"), "xs");
  }
  set size(value) {
    this.setAttribute("size", value);
  }
  get disabled() {
    return this.hasAttribute("disabled");
  }
  set disabled(value) {
    this.toggleAttribute("disabled", Boolean(value));
  }
  connectedCallback() {
    if (isViewDefinition(this)) return;
    upgradeProperties(this, ["index", "active", "angle", "distance", "size", "disabled"]);
    if (!this._button) {
      this._button = this.querySelector(":scope > .z-pagination-button") ?? this.ownerDocument.createElement("button");
      this._button.type = "button";
      this._button.className = "z-pagination-button";
      this.append(this._button);
    }
    this.classList.add("z-pagination", "satellite");
    if (!this._listeners) {
      this._listeners = new this.ownerDocument.defaultView.AbortController();
      this._button.addEventListener("click", (event) => {
        event.stopPropagation();
        if (!this.disabled) emit(this, "change", { index: this.index, page: this.index + 1 });
      }, { signal: this._listeners.signal });
    }
    this._render();
  }
  disconnectedCallback() {
    this._listeners?.abort();
    this._listeners = null;
  }
  attributeChangedCallback() {
    this._render();
  }
  _render() {
    if (!this._button) return;
    this._button.textContent = String(this.index + 1);
    this._button.setAttribute("aria-label", `Page ${this.index + 1}`);
    this._button.disabled = this.disabled;
    this._button.toggleAttribute("data-active", this.index === this.active);
    if (this.index === this.active) this._button.setAttribute("aria-current", "page");
    else this._button.removeAttribute("aria-current");
    this.classList.toggle("active", this.index === this.active);
    this.classList.toggle("deactive", this.index !== this.active);
    this.style.setProperty("--o-from", `${this.angle}deg`);
    this.style.setProperty("--o-offset", "0deg");
    this.style.setProperty("--o-angle", "0deg");
    this.style.setProperty("--z-pagination-distance", String(this.distance / 100));
    this.style.setProperty("--o-aligment", `calc(var(--o-radius) * ${1 - this.distance / 100})`);
    this.style.setProperty("--z-pagination-size", `var(--z-size-${this.size}, var(--z-size-xs))`);
  }
};

// src/components/index.js
function registerElements() {
  if (typeof customElements === "undefined") return;
  registerOrbit();
  const elements = { "z-canvas": ZCanvas, "z-view": ZView, "z-spot": ZSpot, "z-list": ZList, "z-dialog": ZDialog, "z-knob": ZKnob, "z-slider": ZSlider, "z-scroll": ZScroll, "z-pagination": ZPagination };
  for (const [name, ctor] of Object.entries(elements)) {
    if (!customElements.get(name)) customElements.define(name, ctor);
  }
}

// src/zircle.js
if (typeof window !== "undefined") registerElements();
export {
  MODES,
  Orbit,
  THEMES,
  ZCanvas,
  ZDialog,
  ZKnob,
  ZList,
  ZPagination,
  ZScroll,
  ZSlider,
  ZSpot,
  ZView,
  gt as Zumly,
  Ze as ZumlyRouter,
  createZircle,
  createZircle as default,
  registerElements
};
//# sourceMappingURL=zircle.standalone.js.map