var SizeWiseTracker = (() => {
  var __defProp = Object.defineProperty;
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  var __getOwnPropNames = Object.getOwnPropertyNames;
  var __hasOwnProp = Object.prototype.hasOwnProperty;
  var __esm = (fn, res) => function __init() {
    return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
  };
  var __export = (target, all) => {
    for (var name in all)
      __defProp(target, name, { get: all[name], enumerable: true });
  };
  var __copyProps = (to, from, except, desc) => {
    if (from && typeof from === "object" || typeof from === "function") {
      for (let key of __getOwnPropNames(from))
        if (!__hasOwnProp.call(to, key) && key !== except)
          __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
    }
    return to;
  };
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

  // src/config.js
  var config_exports = {};
  __export(config_exports, {
    configPresets: () => configPresets,
    defaultConfig: () => defaultConfig,
    mergeConfig: () => mergeConfig,
    validateConfig: () => validateConfig
  });
  function validateConfig(config) {
    const errors = [];
    if (!config.apiEndpoint) {
      errors.push("API endpoint is required");
    }
    if (config.clickTracking) {
      const ct = config.clickTracking;
      if (!["all", "active-only", "selective"].includes(ct.mode)) {
        errors.push('Click tracking mode must be "all", "active-only", or "selective"');
      }
      if (ct.mode === "selective" && (!ct.selective || !ct.selective.selectors)) {
        errors.push("Selective mode requires selectors configuration");
      }
      if (ct.performance) {
        const perf = ct.performance;
        if (perf.debounceDelay < 0) {
          errors.push("Debounce delay must be >= 0");
        }
        if (perf.throttleDelay < 0) {
          errors.push("Throttle delay must be >= 0");
        }
        if (perf.maxClicksPerBatch < 1) {
          errors.push("Max clicks per batch must be >= 1");
        }
        if (perf.batchTimeout < 100) {
          errors.push("Batch timeout must be >= 100ms");
        }
        if (perf.minClickInterval < 0) {
          errors.push("Min click interval must be >= 0");
        }
      }
    }
    return errors;
  }
  function mergeConfig(baseConfig, userConfig) {
    return {
      ...baseConfig,
      ...userConfig,
      auth: {
        ...baseConfig.auth,
        ...userConfig.auth
      },
      clickTracking: {
        ...baseConfig.clickTracking,
        ...userConfig.clickTracking,
        activeElements: {
          ...baseConfig.clickTracking.activeElements,
          ...userConfig.clickTracking?.activeElements
        },
        performance: {
          ...baseConfig.clickTracking.performance,
          ...userConfig.clickTracking?.performance
        },
        selective: {
          ...baseConfig.clickTracking.selective,
          ...userConfig.clickTracking?.selective
        }
      }
    };
  }
  var defaultConfig, configPresets;
  var init_config = __esm({
    "src/config.js"() {
      defaultConfig = {
        // Base endpoint for API calls
        apiEndpoint: "https://dev-api.sizewize.net",
        environment: "development",
        // SizeWise iframe domains configuration
        sizewiseIframeDomains: ["app-dev.sizewize.net", "app.sizewise.cloud"],
        // Authentication settings
        auth: {
          anonymousLoginEndpoint: "/auth/app/login/anonymous",
          eventsEndpoint: "/events/analyze",
          tokenCookieName: "sizewise_auth_token",
          userStorageKey: "sizewise_user_data"
        },
        // Fingerprint configuration (new endpoint)
        fingerprint: {
          apiKey: "sk_test_550e8400-e29b-41d4-a716-446655440000",
          endpoint: "/fingerprint/generate"
        },
        // Click tracking configuration
        clickTracking: {
          // Tracking modes:
          // - 'all': Track all clicks (original behavior)
          // - 'active-only': Track only clicks on active/interactive elements
          // - 'selective': Track only clicks matching specific selectors
          mode: "active-only",
          // Active element detection settings (used when mode = 'active-only')
          activeElements: {
            // Native interactive HTML elements
            nativeElements: [
              "button",
              'input[type="submit"]',
              'input[type="button"]',
              'input[type="reset"]',
              'input[type="image"]',
              'input[type="file"]',
              "a[href]",
              "select",
              "textarea"
            ],
            // Elements with JavaScript event handlers
            withEvents: [
              "onclick",
              "onchange",
              "onsubmit",
              "onfocus",
              "onblur",
              "onmouseover",
              "onmouseout",
              "onkeydown",
              "onkeyup"
            ],
            // Elements with interactive ARIA roles
            withRoles: [
              "button",
              "link",
              "menuitem",
              "tab",
              "checkbox",
              "radio",
              "switch",
              "slider",
              "combobox"
            ],
            // Elements with action-related data attributes
            withDataAttributes: [
              "data-track",
              "data-analytics",
              "data-action",
              "data-click",
              "data-event"
            ],
            // CSS classes that indicate interactivity
            withClasses: [
              ".btn",
              ".button",
              ".cta",
              ".action",
              ".clickable",
              ".interactive",
              ".clickable-element"
            ],
            // Elements with pointer cursor (CSS)
            withPointerCursor: true,
            // Check if element is child of an active element
            checkParentElements: false
          },
          // Performance optimization settings
          performance: {
            debounceDelay: 100,
            // Debounce delay for rapid clicks (ms)
            throttleDelay: 50,
            // Throttle delay for performance (ms)
            maxClicksPerBatch: 10,
            // Maximum clicks to process in one batch
            batchTimeout: 2e3,
            // Timeout for batch processing (ms)
            minClickInterval: 50
            // Minimum time between clicks to track (ms)
          },
          // Elements to ignore (regardless of mode)
          ignoreElements: [
            "script",
            "style",
            "meta",
            "link",
            "noscript",
            "[data-no-track]",
            "[data-sizewise-ignore]"
          ],
          // Selective mode settings (used when mode = 'selective')
          selective: {
            // Only track elements matching these CSS selectors
            selectors: [
              '[data-track="click"]',
              ".analytics-track",
              "button[data-action]",
              "a[data-event]"
            ],
            // Track all clicks within these container elements
            containers: [
              ".tracking-zone",
              "[data-analytics-zone]",
              ".main-content"
            ]
          }
        }
      };
      configPresets = {
        // Development preset - track active elements with faster processing
        development: {
          clickTracking: {
            mode: "active-only",
            performance: {
              debounceDelay: 50,
              throttleDelay: 25,
              maxClicksPerBatch: 5,
              batchTimeout: 1e3,
              minClickInterval: 25
            }
          }
        },
        // Production preset - only active elements, optimized performance
        production: {
          clickTracking: {
            mode: "active-only",
            performance: {
              debounceDelay: 150,
              throttleDelay: 75,
              maxClicksPerBatch: 15,
              batchTimeout: 3e3,
              minClickInterval: 75
            }
          }
        },
        // E-commerce preset - focus on conversion events
        ecommerce: {
          clickTracking: {
            mode: "selective",
            selective: {
              selectors: [
                '[data-track="click"]',
                ".add-to-cart",
                ".buy-now",
                ".checkout",
                ".product-link",
                "form[data-checkout]",
                "[data-product-id]"
              ],
              containers: [
                ".product-grid",
                ".shopping-cart",
                ".checkout-form"
              ]
            }
          }
        },
        // Minimal preset - only essential tracking
        minimal: {
          clickTracking: {
            mode: "selective",
            selective: {
              selectors: [
                "[data-analytics]",
                ".cta-button",
                'form button[type="submit"]'
              ]
            },
            performance: {
              debounceDelay: 200,
              throttleDelay: 100,
              maxClicksPerBatch: 20,
              batchTimeout: 5e3,
              minClickInterval: 100
            }
          }
        }
      };
    }
  });

  // src/index.js
  var index_exports = {};
  __export(index_exports, {
    default: () => index_default
  });

  // src/logger.js
  function log(message, type = "info") {
    const prefix = "[SizeWise Tracker]";
    if (type === "error") {
      console.error(prefix, message);
    } else if (type === "warn") {
      console.warn(prefix, message);
    } else {
      console.log(prefix, message);
    }
  }

  // src/services/FingerprintService.js
  init_config();
  var FingerprintService = class {
    constructor() {
      this.config = {
        ...defaultConfig.fingerprint
      };
    }
    // Main method that replaces FingerprintJS.get()
    async getFingerprint() {
      try {
        const signals = this.collectSignals();
        const response = await this.callFingerprintAPI({ signals });
        return {
          visitorId: response.visitorId,
          confidence: response.confidence,
          generatedAt: response.generatedAt,
          // Additional fields for compatibility
          requestId: response.visitorId,
          // For compatibility
          components: this.transformSignalsToComponents(signals)
        };
      } catch (_error) {
        log(`Failed to generate fingerprint: ${_error.message}`, "error");
        return null;
      }
    }
    // Call fingerprint API with API key
    async callFingerprintAPI(data) {
      const config = await Promise.resolve().then(() => (init_config(), config_exports)).then((m) => m.defaultConfig);
      const url = `${config.apiEndpoint}${this.config.endpoint}`;
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-API-Key": this.config.apiKey
        },
        body: JSON.stringify(data)
      });
      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(`Fingerprint API failed: ${response.status} ${response.statusText} - ${errorData.message || ""}`);
      }
      return await response.json();
    }
    // Collect device signals
    collectSignals() {
      return {
        userAgent: this.getUserAgent(),
        screen: {
          width: screen.width,
          height: screen.height,
          availWidth: screen.availWidth,
          availHeight: screen.availHeight,
          colorDepth: screen.colorDepth
        },
        timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
        language: navigator.language,
        platform: this.getPlatform(),
        hardwareConcurrency: this.getHardwareConcurrency(),
        deviceMemory: this.getDeviceMemory(),
        maxTouchPoints: navigator.maxTouchPoints || 0,
        canvas: this.generateCanvasFingerprint(),
        webgl: this.generateWebGLFingerprint()
      };
    }
    // Generate canvas fingerprint
    generateCanvasFingerprint() {
      try {
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        canvas.width = 200;
        canvas.height = 50;
        ctx.textBaseline = "top";
        ctx.font = "14px Arial";
        ctx.fillStyle = "#000000";
        ctx.fillText("SizeWise Fingerprint \u{1F3AF}", 2, 2);
        ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
        ctx.fillRect(100, 5, 60, 20);
        ctx.strokeStyle = "#FF0000";
        ctx.lineWidth = 2;
        ctx.strokeRect(10, 25, 80, 15);
        const gradient = ctx.createLinearGradient(0, 0, 200, 0);
        gradient.addColorStop(0, "rgba(0,0,255,0.5)");
        gradient.addColorStop(1, "rgba(255,0,255,0.5)");
        ctx.fillStyle = gradient;
        ctx.fillRect(150, 10, 40, 30);
        return canvas.toDataURL();
      } catch (_error) {
        log(`Failed to generate canvas fingerprint: ${_error.message}`, "warn");
        return null;
      }
    }
    // Generate WebGL fingerprint
    generateWebGLFingerprint() {
      try {
        const canvas = document.createElement("canvas");
        const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
        if (!gl) return null;
        return {
          vendor: gl.getParameter(gl.VENDOR),
          renderer: gl.getParameter(gl.RENDERER),
          version: gl.getParameter(gl.VERSION),
          shadingLanguageVersion: gl.getParameter(gl.SHADING_LANGUAGE_VERSION)
        };
      } catch (_error) {
        log(`Failed to generate WebGL fingerprint: ${_error.message}`, "warn");
        return null;
      }
    }
    // Transform signals to components format (for compatibility)
    transformSignalsToComponents(signals) {
      return {
        userAgent: { value: signals.userAgent },
        screen: { value: signals.screen },
        timezone: { value: signals.timezone },
        language: { value: signals.language },
        platform: { value: signals.platform },
        hardwareConcurrency: { value: signals.hardwareConcurrency },
        deviceMemory: { value: signals.deviceMemory },
        maxTouchPoints: { value: signals.maxTouchPoints },
        canvas: { value: signals.canvas },
        webgl: { value: signals.webgl }
      };
    }
    // Get user agent information (with fallback for deprecated navigator.userAgent)
    getUserAgent() {
      try {
        if (navigator.userAgentData) {
          const uaData = navigator.userAgentData;
          const platform = uaData.platform || "Unknown";
          const brand = uaData.brands?.[0]?.brand || "Unknown";
          const version = uaData.brands?.[0]?.version || "Unknown";
          return `${brand}/${version} (${platform})`;
        }
        if (navigator.userAgent) {
          return navigator.userAgent;
        }
        return "Unknown";
      } catch (_error) {
        log(`Failed to get user agent: ${_error.message}`, "warn");
        return "Unknown";
      }
    }
    // Get hardware concurrency (with fallback for deprecated navigator.hardwareConcurrency)
    getHardwareConcurrency() {
      try {
        if (navigator.hardwareConcurrency !== void 0) {
          return navigator.hardwareConcurrency;
        }
        const userAgent = this.getUserAgent();
        if (userAgent.includes("Mobile") || userAgent.includes("Android") || userAgent.includes("iPhone")) {
          return 4;
        }
        return 8;
      } catch (_error) {
        log(`Failed to get hardware concurrency: ${_error.message}`, "warn");
        return 4;
      }
    }
    // Get device memory (with fallback for deprecated navigator.deviceMemory)
    getDeviceMemory() {
      try {
        if (navigator.deviceMemory !== void 0) {
          return navigator.deviceMemory;
        }
        const userAgent = this.getUserAgent();
        if (userAgent.includes("Mobile") || userAgent.includes("Android") || userAgent.includes("iPhone")) {
          return 4;
        }
        return 8;
      } catch (_error) {
        log(`Failed to get device memory: ${_error.message}`, "warn");
        return 4;
      }
    }
    // Get platform information (with fallback for deprecated navigator.platform)
    getPlatform() {
      try {
        if (navigator.userAgentData && navigator.userAgentData.platform) {
          return navigator.userAgentData.platform;
        }
        if (navigator.platform) {
          return navigator.platform;
        }
        const userAgent = navigator.userAgent;
        if (userAgent.includes("Windows")) return "Windows";
        if (userAgent.includes("Mac")) return "macOS";
        if (userAgent.includes("Linux")) return "Linux";
        if (userAgent.includes("Android")) return "Android";
        if (userAgent.includes("iPhone") || userAgent.includes("iPad")) return "iOS";
        return "Unknown";
      } catch (_error) {
        log(`Failed to get platform: ${_error.message}`, "warn");
        return "Unknown";
      }
    }
    // Compatibility methods
    getConfig() {
      return { ...this.config };
    }
    async isReady() {
      return true;
    }
  };

  // src/fingerprint.js
  var newFingerprintService = new FingerprintService();
  var FingerprintService2 = {
    // Get full fingerprint result (using new service)
    getFingerprint: async () => {
      try {
        const result = await newFingerprintService.getFingerprint();
        return result;
      } catch (_error) {
        log(`[FINGERPRINT] Failed to get fingerprint: ${_error.message}`, "error");
        return null;
      }
    },
    // Get configuration (using new service)
    getConfig: () => {
      return newFingerprintService.getConfig();
    },
    // Check if FingerprintJS is ready (always true for new service)
    isReady: async () => {
      return await newFingerprintService.isReady();
    }
  };
  var fingerprintConfig = newFingerprintService.getConfig();

  // src/utils.js
  function generateUUID() {
    if (typeof crypto !== "undefined" && crypto.randomUUID) {
      return crypto.randomUUID();
    }
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
      const r = Math.random() * 16 | 0;
      const v = c === "x" ? r : r & 3 | 8;
      return v.toString(16);
    });
  }
  var CookieUtils = {
    // Set a cookie
    set: (name, value, days = 30) => {
      const expires = /* @__PURE__ */ new Date();
      expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1e3);
      document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/;SameSite=Lax`;
    },
    // Get a cookie value
    get: (name) => {
      const nameEQ = `${name}=`;
      const ca = document.cookie.split(";");
      for (let i = 0; i < ca.length; i++) {
        let c = ca[i];
        while (c.charAt(0) === " ") {
          c = c.substring(1, c.length);
        }
        if (c.indexOf(nameEQ) === 0) {
          return c.substring(nameEQ.length, c.length);
        }
      }
      return null;
    },
    // Delete a cookie
    delete: (name) => {
      document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;
    },
    // Check if a cookie exists
    exists: (name) => {
      return CookieUtils.get(name) !== null;
    }
  };
  var TokenUtils = {
    // Decode JWT token (without verification)
    decode: (token) => {
      try {
        const [, base64Url] = token.split(".");
        const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
        const jsonPayload = decodeURIComponent(atob(base64).split("").map((c) => {
          return `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`;
        }).join(""));
        return JSON.parse(jsonPayload);
      } catch (_error) {
        return null;
      }
    },
    // Check if token is expired
    isExpired: (token) => {
      const decoded = TokenUtils.decode(token);
      if (!decoded || !decoded.exp) {
        return true;
      }
      const currentTime = Math.floor(Date.now() / 1e3);
      return decoded.exp < currentTime;
    },
    // Get token expiration time
    getExpirationTime: (token) => {
      const decoded = TokenUtils.decode(token);
      return decoded ? decoded.exp * 1e3 : null;
    }
  };
  var ApiUtils = {
    // Make authenticated API call
    call: async (endpoint, options = {}) => {
      const config = await Promise.resolve().then(() => (init_config(), config_exports)).then((m) => m.defaultConfig);
      const token = CookieUtils.get(config.auth.tokenCookieName);
      const defaultOptions = {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          ...token && { "Authorization": `Bearer ${token}` }
        }
      };
      const finalOptions = {
        ...defaultOptions,
        ...options,
        headers: {
          ...defaultOptions.headers,
          ...options.headers
        }
      };
      const url = `${config.apiEndpoint}${endpoint}`;
      const response = await fetch(url, finalOptions);
      if (!response.ok) {
        throw new Error(`API call failed: ${response.status} ${response.statusText}`);
      }
      return await response.json();
    },
    // Make POST request
    post: (endpoint, data) => {
      return ApiUtils.call(endpoint, {
        method: "POST",
        body: JSON.stringify(data)
      });
    }
  };

  // src/storage/StorageManager.js
  var Storage = class {
    // Fingerprint data storage
    static save(data) {
      try {
        localStorage.setItem("SizeWiseFingerprint", JSON.stringify(data));
      } catch (_error) {
        log(`Failed to save to localStorage: ${_error.message}`, "error");
      }
    }
    static get() {
      try {
        const data = localStorage.getItem("SizeWiseFingerprint");
        return data ? JSON.parse(data) : null;
      } catch (_error) {
        log(`Failed to get from localStorage: ${_error.message}`, "error");
        return null;
      }
    }
    static clear() {
      try {
        localStorage.removeItem("SizeWiseFingerprint");
      } catch (_error) {
        log(`Failed to clear localStorage: ${_error.message}`, "error");
      }
    }
    // User data storage
    static saveUser(userData) {
      try {
        localStorage.setItem("SizeWiseUser", JSON.stringify(userData));
      } catch (_error) {
        log(`Failed to save user data to localStorage: ${_error.message}`, "error");
      }
    }
    static getUser() {
      try {
        const data = localStorage.getItem("SizeWiseUser");
        return data ? JSON.parse(data) : null;
      } catch (_error) {
        log(`Failed to get user data from localStorage: ${_error.message}`, "error");
        return null;
      }
    }
    static clearUser() {
      try {
        localStorage.removeItem("SizeWiseUser");
      } catch (_error) {
        log(`Failed to clear user data from localStorage: ${_error.message}`, "error");
      }
    }
    // Get app user data (for backward compatibility)
    static getAppUser() {
      const userData = this.getUser();
      return userData?.appUser || userData;
    }
    // Get customer info
    static getCustomer() {
      const userData = this.getUser();
      return userData?.customer || null;
    }
    // Clicks data storage
    static saveClicks(clicksData) {
      try {
        localStorage.setItem("SizeWiseClicks", JSON.stringify(clicksData));
      } catch (_error) {
        log(`Failed to save clicks data to localStorage: ${_error.message}`, "error");
      }
    }
    static getClicks() {
      try {
        const data = localStorage.getItem("SizeWiseClicks");
        return data ? JSON.parse(data) : [];
      } catch (_error) {
        log(`Failed to get clicks data from localStorage: ${_error.message}`, "error");
        return [];
      }
    }
    static addClick(clickData) {
      try {
        const clicks = this.getClicks();
        clicks.push({
          ...clickData,
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        });
        if (clicks.length > 100) {
          clicks.splice(0, clicks.length - 100);
        }
        this.saveClicks(clicks);
      } catch (_error) {
        log(`Failed to add click data: ${_error.message}`, "error");
      }
    }
    static removeClick(clickData) {
      try {
        const clicks = this.getClicks();
        const index = clicks.findIndex(
          (click) => click.timestamp === clickData.timestamp && click.element?.tagName === clickData.element?.tagName
        );
        if (index > -1) {
          clicks.splice(index, 1);
          this.saveClicks(clicks);
        }
      } catch (_error) {
        log(`Failed to remove click data: ${_error.message}`, "error");
      }
    }
    static clearClicks() {
      try {
        localStorage.removeItem("SizeWiseClicks");
      } catch (_error) {
        log(`Failed to clear clicks data from localStorage: ${_error.message}`, "error");
      }
    }
    // Domain data storage
    static saveDomain(domainData) {
      try {
        localStorage.setItem("SizeWiseDomain", JSON.stringify(domainData));
      } catch (_error) {
        log(`Failed to save domain to localStorage: ${_error.message}`, "error");
      }
    }
    static getDomain() {
      try {
        const data = localStorage.getItem("SizeWiseDomain");
        return data ? JSON.parse(data) : null;
      } catch (_error) {
        log(`Failed to get domain from localStorage: ${_error.message}`, "error");
        return null;
      }
    }
    static clearDomain() {
      try {
        localStorage.removeItem("SizeWiseDomain");
      } catch (_error) {
        log(`Failed to clear domain from localStorage: ${_error.message}`, "error");
      }
    }
    // Navigation data storage
    static saveNavigations(navigationsData) {
      try {
        localStorage.setItem("SizeWiseNavigations", JSON.stringify(navigationsData));
      } catch (_error) {
        log(`Failed to save navigations data to localStorage: ${_error.message}`, "error");
      }
    }
    static getNavigations() {
      try {
        const data = localStorage.getItem("SizeWiseNavigations");
        return data ? JSON.parse(data) : [];
      } catch (_error) {
        log(`Failed to get navigations data from localStorage: ${_error.message}`, "error");
        return [];
      }
    }
    static addNavigation(navigationData) {
      try {
        const navigations = this.getNavigations();
        navigations.push({
          ...navigationData,
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        });
        if (navigations.length > 50) {
          navigations.splice(0, navigations.length - 50);
        }
        this.saveNavigations(navigations);
      } catch (_error) {
        log(`Failed to add navigation data: ${_error.message}`, "error");
      }
    }
    static removeNavigation(navigationData) {
      try {
        const navigations = this.getNavigations();
        const index = navigations.findIndex(
          (nav) => nav.timestamp === navigationData.timestamp && nav.pageInfo?.url === navigationData.pageInfo?.url
        );
        if (index > -1) {
          navigations.splice(index, 1);
          this.saveNavigations(navigations);
        }
      } catch (_error) {
        log(`Failed to remove navigation data: ${_error.message}`, "error");
      }
    }
    static clearNavigations() {
      try {
        localStorage.removeItem("SizeWiseNavigations");
      } catch (_error) {
        log(`Failed to clear navigations data from localStorage: ${_error.message}`, "error");
      }
    }
    // Tracker ID generation and storage
    static getTrackerId() {
      let trackerId = localStorage.getItem("SizeWiseTrackerId");
      if (!trackerId) {
        trackerId = this.generateTrackerId();
        localStorage.setItem("SizeWiseTrackerId", trackerId);
      }
      return trackerId;
    }
    static generateTrackerId() {
      return "sw_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9);
    }
    // Session ID generation and storage (UUID format for API compatibility)
    // Uses sessionStorage so each browser tab/window gets a new session
    static getSessionId() {
      let sessionId = sessionStorage.getItem("SizeWiseSessionId");
      if (!sessionId) {
        sessionId = generateUUID();
        sessionStorage.setItem("SizeWiseSessionId", sessionId);
      }
      return sessionId;
    }
    static generateSessionId() {
      const sessionId = generateUUID();
      sessionStorage.setItem("SizeWiseSessionId", sessionId);
      return sessionId;
    }
    // Data validation
    static isValid(data) {
      if (!data) return false;
      if (typeof data === "object" && data.visitorId) {
        return true;
      }
      return false;
    }
    // Clear all tracker data
    static clearAll() {
      try {
        localStorage.removeItem("SizeWiseFingerprint");
        localStorage.removeItem("SizeWiseUser");
        localStorage.removeItem("SizeWiseClicks");
        localStorage.removeItem("SizeWiseDomain");
        localStorage.removeItem("SizeWiseNavigations");
        localStorage.removeItem("SizeWiseTrackerId");
      } catch (_error) {
        log(`Failed to clear all data: ${_error.message}`, "error");
      }
    }
  };

  // src/services/AuthService.js
  init_config();
  var AuthService = class {
    constructor() {
      this.config = defaultConfig.auth;
    }
    // Perform anonymous login
    async anonymousLogin(visitorId) {
      const domainData = Storage.getDomain();
      if (!domainData || !domainData.domain) {
        throw new Error("Domain not available for authentication");
      }
      const response = await ApiUtils.post(this.config.anonymousLoginEndpoint, {
        visitorId,
        domain: domainData.domain
      });
      if (response && response.token && response.appUser) {
        CookieUtils.set(this.config.tokenCookieName, response.token);
        const userData = {
          appUser: response.appUser,
          customer: response.customer
        };
        Storage.saveUser(userData);
        return response;
      }
      throw new Error("Invalid response from anonymous login");
    }
    // Check if we have valid authentication
    isAuthenticated() {
      const token = CookieUtils.get(this.config.tokenCookieName);
      const userData = Storage.getUser();
      if (!token || !userData) {
        return false;
      }
      if (TokenUtils.isExpired(token)) {
        this.clearAuth();
        return false;
      }
      return true;
    }
    // Clear authentication data
    clearAuth() {
      CookieUtils.delete(this.config.tokenCookieName);
      Storage.clearUser();
    }
    // Get current user data
    getUser() {
      return Storage.getUser();
    }
    // Get current app user data (for backward compatibility)
    getAppUser() {
      return Storage.getAppUser();
    }
    // Get current customer data
    getCustomer() {
      return Storage.getCustomer();
    }
    // Get current token
    getToken() {
      return CookieUtils.get(this.config.tokenCookieName);
    }
  };
  var authService = new AuthService();

  // src/services/ClickTrackingService.js
  init_config();

  // src/services/CartService.js
  var CartService = class {
    constructor() {
      this.userData = null;
    }
    // Get cart_saved based on customer platform
    getCartData() {
      try {
        const userData = authService.getUser();
        const customer = userData?.customer;
        const platform = customer?.platform?.toLowerCase();
        if (platform === "shopify") {
          return this.getShopifyCart();
        }
        return {};
      } catch (_error) {
        log(`Failed to get cart data: ${_error.message}`, "warn");
        return {};
      }
    }
    // For Shopify: use chAeSavedToCart
    getShopifyCart() {
      try {
        const cartData = localStorage.getItem("chAeSavedToCart");
        if (cartData) {
          return JSON.parse(cartData);
        }
        return {};
      } catch (_error) {
        log(`Failed to parse Shopify cart data: ${_error.message}`, "warn");
        return {};
      }
    }
  };
  var cartService = new CartService();

  // src/services/ClickTrackingService.js
  var ClickTrackingService = class {
    constructor() {
      this.config = {
        ...defaultConfig.clickTracking,
        eventsEndpoint: defaultConfig.apiEndpoint + defaultConfig.auth.eventsEndpoint
      };
      this.state = {
        isTracking: false,
        isProcessingQueue: false
      };
      this.queueProcessingInterval = null;
    }
    // Initialize with configuration
    init(config = {}) {
      this.config = {
        ...this.config,
        ...config
      };
      this.retryQueue();
    }
    // Start click tracking
    start() {
      if (this.state.isTracking) return;
      if (window !== window.parent) return;
      try {
        document.addEventListener("click", this.handleClick.bind(this), { passive: true, capture: true });
        this.state.isTracking = true;
        this.startQueueProcessing();
        this.setupConnectivityListeners();
      } catch (_error) {
        log(`Failed to start click tracking: ${_error.message}`, "error");
      }
    }
    // Stop click tracking
    stop() {
      if (!this.state.isTracking) return;
      try {
        document.removeEventListener("click", this.handleClick.bind(this), { capture: true });
        this.state.isTracking = false;
        this.stopQueueProcessing();
        this.removeConnectivityListeners();
      } catch (_error) {
        log(`Failed to stop click tracking: ${_error.message}`, "error");
      }
    }
    // Handle click event
    handleClick(event) {
      try {
        const path = event.composedPath ? event.composedPath() : [];
        if (path.length === 0) {
          log("No path found in event", "warn");
          return;
        }
        const interactiveElement = this.findInteractiveElement(path);
        if (!interactiveElement) {
          return;
        }
        const clickData = this.extractClickData(interactiveElement, event);
        this.sendToAPI(clickData);
      } catch (_error) {
        log(`Failed to handle click: ${_error.message}`, "error");
      }
    }
    // Find interactive element in path
    findInteractiveElement(path) {
      const { mode, selective } = this.config;
      const selectorString = this.buildSelectorString();
      for (const node of path) {
        if (!(node instanceof Element)) continue;
        if (this.shouldIgnoreElement(node)) {
          continue;
        }
        if (mode === "selective" && selective?.containers) {
          for (const containerSelector of selective.containers) {
            if (node.closest(containerSelector)) {
              return node;
            }
          }
        }
        if (node.matches && node.matches(selectorString)) {
          return node;
        }
      }
      return null;
    }
    // Check if element should be ignored
    shouldIgnoreElement(element) {
      const { ignoreElements } = this.config;
      if (!ignoreElements) return false;
      for (const selector of ignoreElements) {
        if (element.matches && element.matches(selector)) {
          return true;
        }
      }
      return false;
    }
    // Build selector string from configuration
    buildSelectorString() {
      const { activeElements, mode, selective } = this.config;
      const selectors = [];
      if (mode === "all") {
        return "*";
      }
      if (mode === "selective" && selective?.selectors) {
        return selective.selectors.join(", ");
      }
      if (activeElements) {
        if (activeElements.nativeElements) {
          selectors.push(...activeElements.nativeElements);
        }
        if (activeElements.withDataAttributes) {
          activeElements.withDataAttributes.forEach((attr) => {
            selectors.push(`[${attr}]`);
          });
        }
        if (activeElements.withClasses) {
          activeElements.withClasses.forEach((className) => {
            const cleanClass = className.startsWith(".") ? className : `.${className}`;
            selectors.push(cleanClass);
          });
        }
        if (activeElements.withRoles) {
          activeElements.withRoles.forEach((role) => {
            selectors.push(`[role="${role}"]`);
          });
        }
      }
      return selectors.join(", ");
    }
    // Extract click data
    extractClickData(element, event) {
      const userData = authService.getUser()?.appUser || authService.getUser();
      const sessionId = Storage.getSessionId();
      const path = this.generateElementPath(element);
      const trackingRule = this.determineTrackingRule(element);
      const rect = element.getBoundingClientRect();
      const position = {
        x: Math.round(event.clientX - rect.left),
        y: Math.round(event.clientY - rect.top)
      };
      const size = {
        width: Math.round(rect.width),
        height: Math.round(rect.height)
      };
      const classNameObj = {};
      if (element.className) {
        element.className.split(" ").forEach((cls) => {
          if (cls.trim()) classNameObj[cls.trim()] = true;
        });
      }
      return {
        eventType: "click",
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        element: {
          tagName: element.tagName.toLowerCase(),
          className: classNameObj,
          id: element.id || "",
          href: element.href || "",
          type: element.type || "",
          text: element.textContent?.trim().substring(0, 100) || "",
          position,
          size,
          attributes: this.getRelevantAttributes(element)
        },
        elementHTML: element.outerHTML,
        path,
        pageInfo: {
          url: window.location.href,
          title: document.title,
          referrer: document.referrer
        },
        domain: window.location.hostname,
        trackingRule,
        userId: userData?.id || "",
        sessionId,
        cart_saved: cartService.getCartData()
      };
    }
    // Get relevant attributes
    getRelevantAttributes(element) {
      const relevant = {};
      const attributes = element.attributes;
      for (let i = 0; i < attributes.length; i++) {
        const attr = attributes[i];
        if (["class", "id", "href", "src", "data-"].some((prefix) => attr.name.startsWith(prefix))) {
          relevant[attr.name] = attr.value;
        }
      }
      return relevant;
    }
    // Send to API with queue fallback
    async sendToAPI(clickData) {
      try {
        await ApiUtils.post(defaultConfig.auth.eventsEndpoint, clickData);
        Storage.removeClick(clickData);
      } catch (_error) {
        log(`Failed to send click to API: ${_error.message}`, "warn");
        this.addToQueue(clickData);
      }
    }
    // Add to queue
    addToQueue(clickData) {
      Storage.addClick(clickData);
    }
    // Retry failed requests with queue management
    async retryQueue() {
      if (this.state.isProcessingQueue) {
        log("Queue processing already in progress, skipping", "warn");
        return;
      }
      this.state.isProcessingQueue = true;
      try {
        const clicks = Storage.getClicks();
        if (clicks.length === 0) {
          this.state.isProcessingQueue = false;
          return;
        }
        log(`Processing ${clicks.length} clicks from queue`, "info");
        for (let i = clicks.length - 1; i >= 0; i--) {
          const clickData = clicks[i];
          try {
            await this.sendToAPI(clickData);
            Storage.removeClick(clickData);
            log("Successfully processed and removed click from queue", "info");
          } catch (_error) {
            log(`Failed to process click from queue: ${_error.message}`, "warn");
          }
        }
        const remainingClicks = Storage.getClicks().length;
        if (remainingClicks > 0) {
          log(`${remainingClicks} clicks remaining in queue`, "info");
        } else {
          log("Queue processing completed, all clicks sent successfully", "info");
        }
      } catch (_error) {
        log(`Queue processing failed: ${_error.message}`, "error");
      } finally {
        this.state.isProcessingQueue = false;
      }
    }
    // Start queue processing with interval
    startQueueProcessing() {
      if (this.queueProcessingInterval) {
        clearInterval(this.queueProcessingInterval);
      }
      this.queueProcessingInterval = setInterval(() => {
        this.retryQueue();
      }, 3e4);
      log("Queue processing started (30s interval)", "info");
    }
    // Stop queue processing
    stopQueueProcessing() {
      if (this.queueProcessingInterval) {
        clearInterval(this.queueProcessingInterval);
        this.queueProcessingInterval = null;
        log("Queue processing stopped", "info");
      }
    }
    // Setup connectivity listeners
    setupConnectivityListeners() {
      window.addEventListener("online", this.handleOnline.bind(this));
      document.addEventListener("visibilitychange", this.handleVisibilityChange.bind(this));
    }
    // Remove connectivity listeners
    removeConnectivityListeners() {
      window.removeEventListener("online", this.handleOnline.bind(this));
      document.removeEventListener("visibilitychange", this.handleVisibilityChange.bind(this));
    }
    // Handle online event
    handleOnline() {
      log("Connection restored, processing queue", "info");
      this.retryQueue();
    }
    // Handle visibility change
    handleVisibilityChange() {
      if (!document.hidden) {
        log("Page became visible, processing queue", "info");
        this.retryQueue();
      }
    }
    // Get queue status
    getQueueStatus() {
      return {
        isTracking: this.state.isTracking,
        isProcessingQueue: this.state.isProcessingQueue,
        queueLength: Storage.getClicks().length,
        queueProcessingInterval: !!this.queueProcessingInterval
      };
    }
    // Generate CSS path as array
    generateElementPath(element) {
      const path = [];
      let current = element;
      while (current && current !== document.body) {
        let selector = current.tagName.toLowerCase();
        if (current.id) {
          selector += `#${current.id}`;
        } else if (current.className) {
          const classes = current.className.split(" ").filter((cls) => cls.trim());
          if (classes.length > 0) {
            selector += `.${classes[0]}`;
          }
        }
        path.unshift(selector);
        current = current.parentElement;
      }
      return path;
    }
    // Determine tracking rule that matched
    determineTrackingRule(element) {
      const { mode, activeElements, selective } = this.config;
      if (mode === "all") {
        return "all_elements";
      }
      if (mode === "selective" && selective?.selectors) {
        for (const selector of selective.selectors) {
          if (element.matches && element.matches(selector)) {
            return `selective_${selector}`;
          }
        }
      }
      if (activeElements) {
        if (activeElements.nativeElements) {
          for (const selector of activeElements.nativeElements) {
            if (element.matches && element.matches(selector)) {
              return `native_${selector}`;
            }
          }
        }
        if (activeElements.withDataAttributes) {
          for (const attr of activeElements.withDataAttributes) {
            if (element.hasAttribute(attr)) {
              return `data_attribute_${attr}`;
            }
          }
        }
        if (activeElements.withClasses) {
          for (const className of activeElements.withClasses) {
            const cleanClass = className.startsWith(".") ? className.substring(1) : className;
            if (element.classList && element.classList.contains(cleanClass)) {
              return `class_${cleanClass}`;
            }
          }
        }
        if (activeElements.withRoles) {
          for (const role of activeElements.withRoles) {
            if (element.getAttribute("role") === role) {
              return `role_${role}`;
            }
          }
        }
        if (activeElements.withPointerCursor) {
          const computedStyle = window.getComputedStyle(element);
          if (computedStyle.cursor === "pointer") {
            return "pointer_cursor";
          }
        }
      }
      return "unknown";
    }
  };
  var clickTrackingService = new ClickTrackingService();

  // src/navigation.js
  init_config();
  var NavigationTrackingService = class {
    constructor() {
      this.isTracking = false;
      this.history = [];
      this.maxHistorySize = 100;
      this.state = {
        isProcessingQueue: false
      };
      this.queueProcessingInterval = null;
    }
    // Find heading element from page
    findHeadingElement() {
      try {
        const h1 = document.querySelector("h1");
        if (h1 && h1.textContent.trim()) {
          return h1;
        }
        const title = document.title;
        if (title && title !== "") {
          return this.createVirtualTitleElement();
        }
        const h2 = document.querySelector("h2");
        if (h2 && h2.textContent.trim()) {
          return h2;
        }
        const h3 = document.querySelector("h3");
        if (h3 && h3.textContent.trim()) {
          return h3;
        }
        return this.createVirtualTitleElement();
      } catch (_error) {
        log(`Failed to find heading element: ${_error.message}`, "error");
        return this.createVirtualTitleElement();
      }
    }
    // Create virtual title element for fallback
    createVirtualTitleElement() {
      const virtualElement = {
        tagName: "title",
        className: {},
        id: "",
        textContent: document.title || "Page without heading",
        outerHTML: `<title>${document.title || "Page without heading"}</title>`,
        getBoundingClientRect: () => ({ left: 0, top: 0, width: 0, height: 0 }),
        attributes: []
      };
      return virtualElement;
    }
    // Extract element data similar to ClickTrackingService
    extractElementData(element) {
      try {
        const rect = element.getBoundingClientRect ? element.getBoundingClientRect() : { left: 0, top: 0, width: 0, height: 0 };
        const position = {
          x: Math.round(rect.left),
          y: Math.round(rect.top)
        };
        const size = {
          width: Math.round(rect.width),
          height: Math.round(rect.height)
        };
        const classNameObj = {};
        if (element.className && typeof element.className === "string") {
          element.className.split(" ").forEach((cls) => {
            if (cls.trim()) classNameObj[cls.trim()] = true;
          });
        }
        const attributes = {};
        if (element.attributes) {
          for (let i = 0; i < element.attributes.length; i++) {
            const attr = element.attributes[i];
            if (["class", "id", "data-"].some((prefix) => attr.name.startsWith(prefix))) {
              attributes[attr.name] = attr.value;
            }
          }
        }
        return {
          tagName: element.tagName?.toLowerCase() || "title",
          className: classNameObj,
          id: element.id || "",
          text: element.textContent?.trim().substring(0, 100) || "",
          position,
          size,
          attributes
        };
      } catch (_error) {
        log(`Failed to extract element data: ${_error.message}`, "error");
        return {
          tagName: "title",
          className: {},
          id: "",
          text: "Error extracting element data",
          position: { x: 0, y: 0 },
          size: { width: 0, height: 0 },
          attributes: {}
        };
      }
    }
    // Generate CSS path as array (similar to ClickTrackingService)
    generateElementPath(element) {
      try {
        const path = [];
        let current = element;
        if (element.tagName === "title" && !element.parentElement) {
          return ["html", "head", "title"];
        }
        while (current && current !== document.body) {
          let selector = current.tagName?.toLowerCase() || "unknown";
          if (current.id) {
            selector += `#${current.id}`;
          } else if (current.className && typeof current.className === "string") {
            const classes = current.className.split(" ").filter((cls) => cls.trim());
            if (classes.length > 0) {
              selector += `.${classes[0]}`;
            }
          }
          path.unshift(selector);
          current = current.parentElement;
        }
        return path;
      } catch (_error) {
        log(`Failed to generate element path: ${_error.message}`, "error");
        return ["html", "body"];
      }
    }
    // Create navigation event (similar to click events)
    createNavigationEvent(type, fromUrl = null) {
      const headingElement = this.findHeadingElement();
      const userData = authService.getUser()?.appUser || authService.getUser();
      const event = {
        eventType: "page_view",
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        element: this.extractElementData(headingElement),
        elementHTML: headingElement?.outerHTML || "<html>...</html>",
        path: this.generateElementPath(headingElement),
        pageInfo: {
          url: window.location.href,
          title: document.title,
          referrer: fromUrl || document.referrer
        },
        domain: window.location.hostname,
        trackingRule: "page_view",
        userId: userData?.id || "",
        sessionId: Storage.getSessionId(),
        cart_saved: cartService.getCartData()
      };
      return event;
    }
    // Save navigation event
    saveNavigationEvent(event) {
      try {
        this.history.push(event);
        if (this.history.length > this.maxHistorySize) {
          this.history = this.history.slice(-this.maxHistorySize);
        }
        Storage.addNavigation(event);
      } catch (_error) {
        log(`Failed to save navigation event: ${_error.message}`, "error");
      }
    }
    // Handle navigation event
    handleNavigation(type, fromUrl = null) {
      const event = this.createNavigationEvent(type, fromUrl);
      this.saveNavigationEvent(event);
      this.sendToAPI(event);
    }
    // Initialize navigation tracking
    init() {
      if (this.isTracking) {
        return;
      }
      try {
        this.history = Storage.getNavigations();
        if ("navigation" in window) {
        } else {
        }
        this.isTracking = true;
        this.retryQueue();
      } catch (_error) {
        log(`Failed to initialize navigation tracking: ${_error.message}`, "error");
      }
    }
    // Start navigation tracking
    start() {
      if (!this.isTracking) {
        this.init();
      }
      this.handleNavigation("page_load");
      this.startQueueProcessing();
      this.setupConnectivityListeners();
    }
    // Stop navigation tracking
    stop() {
      this.isTracking = false;
      this.stopQueueProcessing();
      this.removeConnectivityListeners();
    }
    // Get navigation history
    getHistory() {
      return [...this.history];
    }
    // Clear navigation history
    clearHistory() {
      this.history = [];
      Storage.clearNavigations();
    }
    // Send to API with queue fallback
    async sendToAPI(navigationData) {
      try {
        await ApiUtils.post(defaultConfig.auth.eventsEndpoint, navigationData);
        Storage.removeNavigation(navigationData);
      } catch (_error) {
        log(`Failed to send navigation to API: ${_error.message}`, "warn");
        this.addToQueue(navigationData);
      }
    }
    // Add to queue
    addToQueue(navigationData) {
      Storage.addNavigation(navigationData);
    }
    // Retry failed requests with queue management
    async retryQueue() {
      if (this.state.isProcessingQueue) {
        log("Navigation queue processing already in progress, skipping", "warn");
        return;
      }
      this.state.isProcessingQueue = true;
      try {
        const navigations = Storage.getNavigations();
        if (navigations.length === 0) {
          this.state.isProcessingQueue = false;
          return;
        }
        log(`Processing ${navigations.length} navigations from queue`, "info");
        for (let i = navigations.length - 1; i >= 0; i--) {
          const navigationData = navigations[i];
          try {
            await this.sendToAPI(navigationData);
            Storage.removeNavigation(navigationData);
            log("Successfully processed and removed navigation from queue", "info");
          } catch (_error) {
            log(`Failed to process navigation from queue: ${_error.message}`, "warn");
          }
        }
        const remainingNavigations = Storage.getNavigations().length;
        if (remainingNavigations > 0) {
          log(`${remainingNavigations} navigations remaining in queue`, "info");
        } else {
          log("Navigation queue processing completed, all navigations sent successfully", "info");
        }
      } catch (_error) {
        log(`Navigation queue processing failed: ${_error.message}`, "error");
      } finally {
        this.state.isProcessingQueue = false;
      }
    }
    // Start queue processing with interval
    startQueueProcessing() {
      if (this.queueProcessingInterval) {
        clearInterval(this.queueProcessingInterval);
      }
      this.queueProcessingInterval = setInterval(() => {
        this.retryQueue();
      }, 3e4);
      log("Navigation queue processing started (30s interval)", "info");
    }
    // Stop queue processing
    stopQueueProcessing() {
      if (this.queueProcessingInterval) {
        clearInterval(this.queueProcessingInterval);
        this.queueProcessingInterval = null;
        log("Navigation queue processing stopped", "info");
      }
    }
    // Setup connectivity listeners
    setupConnectivityListeners() {
      window.addEventListener("online", this.handleOnline.bind(this));
      document.addEventListener("visibilitychange", this.handleVisibilityChange.bind(this));
    }
    // Remove connectivity listeners
    removeConnectivityListeners() {
      window.removeEventListener("online", this.handleOnline.bind(this));
      document.removeEventListener("visibilitychange", this.handleVisibilityChange.bind(this));
    }
    // Handle online event
    handleOnline() {
      log("Connection restored, processing navigation queue", "info");
      this.retryQueue();
    }
    // Handle visibility change
    handleVisibilityChange() {
      if (!document.hidden) {
        log("Page became visible, processing navigation queue", "info");
        this.retryQueue();
      }
    }
    // Get navigation status
    getStatus() {
      return {
        isTracking: this.isTracking,
        historySize: this.history.length,
        maxHistorySize: this.maxHistorySize,
        isProcessingQueue: this.state.isProcessingQueue,
        queueLength: Storage.getNavigations().length,
        queueProcessingInterval: !!this.queueProcessingInterval
      };
    }
  };
  var navigationTrackingService = new NavigationTrackingService();

  // src/utils/ConfigUtils.js
  init_config();
  var ConfigUtils = class {
    // Apply configuration preset
    static applyConfigPreset(presetName) {
      if (configPresets[presetName]) {
        window.__pendingConfigPreset = configPresets[presetName].clickTracking;
        return true;
      }
      return false;
    }
    // Get available presets
    static getAvailablePresets() {
      return Object.keys(configPresets);
    }
    // Auto-detect environment and apply appropriate configuration
    static autoConfigureTracker() {
      const isDevelopment = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname.includes("dev") || window.location.hostname.includes("staging");
      if (isDevelopment) {
        this.applyConfigPreset("development");
      } else {
        this.applyConfigPreset("production");
      }
      const trackerScript = document.querySelector('script[src*="sw-tracker"]');
      if (trackerScript) {
        const mode = trackerScript.getAttribute("data-mode");
        if (mode && ["all", "active-only", "selective"].includes(mode)) {
          window.__pendingCustomMode = mode;
        }
      }
    }
    // Validate configuration object
    static validateConfig(config) {
      const errors = [];
      if (!config.apiEndpoint) {
        errors.push("API endpoint is required");
      }
      if (config.clickTracking) {
        const ct = config.clickTracking;
        if (!["all", "active-only", "selective"].includes(ct.mode)) {
          errors.push('Click tracking mode must be "all", "active-only", or "selective"');
        }
        if (ct.mode === "selective" && (!ct.selective || !ct.selective.selectors)) {
          errors.push("Selective mode requires selectors configuration");
        }
        if (ct.performance) {
          const perf = ct.performance;
          if (perf.debounceDelay < 0) {
            errors.push("Debounce delay must be >= 0");
          }
          if (perf.throttleDelay < 0) {
            errors.push("Throttle delay must be >= 0");
          }
          if (perf.maxClicksPerBatch < 1) {
            errors.push("Max clicks per batch must be >= 1");
          }
          if (perf.batchTimeout < 100) {
            errors.push("Batch timeout must be >= 100ms");
          }
          if (perf.minClickInterval < 0) {
            errors.push("Min click interval must be >= 0");
          }
        }
      }
      return errors;
    }
    // Merge configurations
    static mergeConfig(baseConfig, userConfig) {
      return {
        ...baseConfig,
        ...userConfig,
        auth: {
          ...baseConfig.auth,
          ...userConfig.auth
        },
        clickTracking: {
          ...baseConfig.clickTracking,
          ...userConfig.clickTracking,
          activeElements: {
            ...baseConfig.clickTracking.activeElements,
            ...userConfig.clickTracking?.activeElements
          },
          performance: {
            ...baseConfig.clickTracking.performance,
            ...userConfig.clickTracking?.performance
          },
          selective: {
            ...baseConfig.clickTracking.selective,
            ...userConfig.clickTracking?.selective
          }
        }
      };
    }
  };

  // src/index.js
  init_config();
  var SizeWiseTracker = class {
    constructor() {
      this.mode = null;
      this.isInitialized = false;
      this.isInitializing = false;
      this.isReady = false;
      this.fingerprintData = null;
      this.userData = null;
      this.instanceId = Math.random().toString(36).substr(2, 9);
      if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", () => this.init());
      } else {
        this.init();
      }
    }
    // Detect tracker mode based on context
    detectMode() {
      const currentHostname = window.location.hostname;
      const isSizeWiseIframe = defaultConfig.sizewiseIframeDomains.includes(currentHostname);
      const isInIframe = window !== window.parent;
      if (isSizeWiseIframe && isInIframe) {
        return "SIZEWISE_IFRAME";
      }
      if (isSizeWiseIframe && !isInIframe) {
        return "INDEPENDENT";
      }
      return "NORMAL";
    }
    // Initialize tracker
    async init() {
      if (this.isInitializing) {
        while (this.isInitializing) {
          await new Promise((resolve) => setTimeout(resolve, 100));
        }
        return;
      }
      if (this.isInitialized) {
        return;
      }
      this.isInitializing = true;
      try {
        this.mode = this.detectMode();
        switch (this.mode) {
          case "NORMAL":
            await this.initNormalMode();
            break;
          case "SIZEWISE_IFRAME":
            await this.initIframeMode();
            break;
          case "INDEPENDENT":
            this.initIndependentMode();
            break;
          default:
            break;
        }
        this.isInitialized = true;
      } catch (_error) {
        log(`Failed to initialize tracker: ${_error.message}`, "error");
      } finally {
        this.isInitializing = false;
      }
    }
    // Initialize normal mode (original behavior)
    async initNormalMode() {
      this.initializeDomain();
      ConfigUtils.autoConfigureTracker();
      const storedData = Storage.get();
      if (Storage.isValid(storedData)) {
        this.fingerprintData = storedData;
      } else {
        await this.refreshFingerprint();
      }
      await this.handleAuthentication();
      clickTrackingService.init();
      clickTrackingService.start();
      navigationTrackingService.init();
      navigationTrackingService.start();
      this.setupIframeDetection();
      this.isReady = true;
    }
    // Initialize iframe mode (SizeWise iframe)
    async initIframeMode() {
      await this.waitForParentData();
      clickTrackingService.init();
      this.setupIframeNavigationListener();
      this.isReady = true;
    }
    // Initialize independent mode (SizeWise domain but not in iframe)
    initIndependentMode() {
    }
    // Initialize domain data
    initializeDomain() {
      try {
        const storedDomain = Storage.getDomain();
        if (storedDomain && storedDomain.domain) {
          return;
        }
        const currentDomain = window.location.hostname;
        const domainData = {
          domain: currentDomain,
          protocol: window.location.protocol,
          port: window.location.port || null
        };
        Storage.saveDomain(domainData);
      } catch (_error) {
        log(`Failed to initialize domain: ${_error.message}`, "error");
      }
    }
    // Handle authentication flow
    async handleAuthentication() {
      try {
        if (authService.isAuthenticated()) {
          this.userData = authService.getAppUser();
          return;
        }
        const visitorId = this._getVisitorIdInternal();
        if (!visitorId) {
          return;
        }
        const authResponse = await authService.anonymousLogin(visitorId);
        this.userData = authResponse.appUser;
      } catch (_error) {
        log(`Authentication failed: ${_error.message}`, "error");
      }
    }
    // Get fresh fingerprint data
    async refreshFingerprint() {
      try {
        const result = await FingerprintService2.getFingerprint();
        if (result) {
          this.fingerprintData = result;
          Storage.save(result);
          return result;
        }
        throw new Error("Failed to get fingerprint result");
      } catch (_error) {
        log(`Failed to refresh fingerprint: ${_error.message}`, "error");
        return null;
      }
    }
    // Get visitor ID
    async getVisitorId() {
      if (!this.isInitialized) {
        await this.init();
      }
      return this._getVisitorIdInternal();
    }
    // Internal method to get visitor ID (avoids initialization loop)
    _getVisitorIdInternal() {
      if (!this.fingerprintData) {
        return null;
      }
      return this.fingerprintData.visitorId;
    }
    // Get fingerprint data
    async getFingerprint() {
      if (!this.isInitialized) {
        await this.init();
      }
      return this.fingerprintData;
    }
    // Get user data
    async getUser() {
      if (!this.isInitialized) {
        await this.init();
      }
      return this.userData;
    }
    // Get authentication status
    async getAuthStatus() {
      if (!this.isInitialized) {
        await this.init();
      }
      return {
        isAuthenticated: authService.isAuthenticated(),
        user: this.userData,
        token: authService.getToken()
      };
    }
    // Refresh authentication (useful when token expires)
    async refreshAuth() {
      try {
        await this.handleAuthentication();
        return this.userData;
      } catch (_error) {
        log(`Failed to refresh authentication: ${_error.message}`, "error");
        return null;
      }
    }
    // Clear all data
    clearData() {
      this.fingerprintData = null;
      this.userData = null;
      this.isInitialized = false;
      if (this.iframeMessageListener) {
        window.removeEventListener("message", this.iframeMessageListener);
        this.iframeMessageListener = null;
      }
      Storage.clearAll();
      authService.clearAuth();
    }
    // Get tracker status
    getStatus() {
      return {
        isInitialized: this.isInitialized,
        mode: this.mode,
        hasData: !!this.fingerprintData,
        hasUser: !!this.userData,
        isAuthenticated: authService.isAuthenticated(),
        trackerId: Storage.getTrackerId(),
        config: FingerprintService2.getConfig()
      };
    }
    // Get all captured clicks
    getClicks() {
      return Storage.getClicks();
    }
    // Clear all clicks
    clearClicks() {
      Storage.clearClicks();
    }
    // Get clicks count
    getClicksCount() {
      return Storage.getClicks().length;
    }
    // Navigation tracking methods
    getNavigationHistory() {
      return navigationTrackingService.getHistory();
    }
    clearNavigationHistory() {
      navigationTrackingService.clearHistory();
    }
    getNavigationStatus() {
      return navigationTrackingService.getStatus();
    }
    // Get click tracking configuration
    getClickTrackingConfig() {
      return clickTrackingService.getConfig();
    }
    // Update click tracking configuration
    updateClickTrackingConfig(newConfig) {
      clickTrackingService.updateConfig(newConfig);
    }
    // Get click tracking status
    getClickTrackingStatus() {
      return clickTrackingService.getQueueStatus();
    }
    // Get warnings for debugging
    getWarnings() {
      return clickTrackingService.getWarnings();
    }
    // Clear warnings
    clearWarnings() {
      clickTrackingService.clearWarnings();
    }
    // Get API responses for debugging
    getApiResponses() {
      return clickTrackingService.getApiResponses();
    }
    // Clear API responses
    clearApiResponses() {
      clickTrackingService.clearApiResponses();
    }
    // Setup iframe detection
    setupIframeDetection() {
      this.detectExistingIframes();
      this.observeNewIframes();
      this.setupIframeCommunication();
    }
    // Setup communication with iframes
    setupIframeCommunication() {
      this.iframeMessageListener = (event) => {
        if (event.source === window) {
          return;
        }
        if (!event.data || event.data.type !== "USER_PROFILES_FROM_IFRAME") {
          return;
        }
        this.handleUserProfilesFromIframe(event.data.data);
      };
      window.addEventListener("message", this.iframeMessageListener);
    }
    // Handle UserProfiles received from iframe
    handleUserProfilesFromIframe(data) {
      try {
        const userProfiles = data.userProfiles;
        localStorage.setItem("UserProfilesFromIframe", JSON.stringify(userProfiles));
      } catch (_error) {
        log(`Failed to handle UserProfiles from iframe: ${_error.message}`, "error");
      }
    }
    // Detect existing iframes
    detectExistingIframes() {
      const iframes = document.querySelectorAll("iframe");
      iframes.forEach((iframe) => this.handleIframe(iframe));
    }
    // Observe new iframes being added
    observeNewIframes() {
      const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
          mutation.addedNodes.forEach((node) => {
            if (node.tagName === "IFRAME") {
              this.handleIframe(node);
            }
          });
        });
      });
      observer.observe(document.body, { childList: true, subtree: true });
    }
    // Handle individual iframe
    handleIframe(iframe) {
      const src = iframe.src || "";
      const sizewiseDomains = ["app-dev.sizewize.net", "app.sizewise.cloud"];
      const isSizeWiseIframe = sizewiseDomains.some(
        (domain) => src.includes(domain)
      );
      if (isSizeWiseIframe) {
        iframe.addEventListener("load", () => {
          this.sendDataToIframe(iframe.contentWindow);
        });
      }
    }
    // Send tracker data to iframe
    sendDataToIframe(target) {
      const data = {
        type: "TRACKER_DATA_FROM_PARENT",
        data: {
          visitorId: this.fingerprintData?.visitorId,
          userId: this.userData?.id,
          sessionId: Storage.getSessionId()
        }
      };
      target.postMessage(data, "*");
    }
    // Wait for data from parent with timeout
    async waitForParentData() {
      return new Promise((resolve) => {
        const timeout = setTimeout(() => {
          resolve();
        }, 5e3);
        const handler = (event) => {
          if (event.source !== window.parent) {
            return;
          }
          if (!event.data || event.data.type !== "TRACKER_DATA_FROM_PARENT") {
            return;
          }
          clearTimeout(timeout);
          window.removeEventListener("message", handler);
          this.handleParentData(event.data.data);
          resolve();
        };
        window.addEventListener("message", handler);
      });
    }
    // Handle data received from parent
    handleParentData(data) {
      this.visitorId = data.visitorId;
      this.userId = data.userId;
      this.sessionId = data.sessionId;
      const essentialData = {
        visitorId: this.visitorId,
        userId: this.userId,
        sessionId: this.sessionId
      };
      localStorage.setItem("SizeWiseTrackerData", JSON.stringify(essentialData));
      this.sendUserProfilesToParent();
    }
    // Send UserProfiles to parent
    sendUserProfilesToParent() {
      let userProfiles;
      try {
        userProfiles = window.UserProfiles || JSON.parse(localStorage.getItem("UserProfiles"));
      } catch (_e) {
        userProfiles = null;
      }
      if (!userProfiles) {
        window.parent.postMessage({
          type: "USER_PROFILES_FROM_IFRAME",
          data: { error: "NO_USER_PROFILES" }
        }, "*");
        return;
      }
      const summary = userProfiles.map((profile) => {
        const { nickName, age, gender, scans } = profile;
        let scanSummary = null;
        if (Array.isArray(scans) && scans.length > 0) {
          const lastScan = scans[scans.length - 1];
          const {
            scanId,
            tenantId,
            left_foot,
            right_foot,
            scanResults
          } = lastScan || {};
          const inputDataRaw = scanResults?.input_data || {};
          const inputData = {
            id: inputDataRaw.id,
            gender: inputDataRaw.gender,
            tenant_id: inputDataRaw.tenant_id
          };
          const brandsRaw = scanResults?.recommended_size?.brands || [];
          const brands = brandsRaw.filter((b) => b.brand !== "STANDARD").map((b) => {
            const bothFeet = b.both_feet || {};
            const filteredScales = {};
            for (const [scaleKey, scaleObj] of Object.entries(bothFeet)) {
              if (scaleObj && typeof scaleObj === "object" && scaleObj.size) {
                filteredScales[scaleKey] = {
                  size: scaleObj.size,
                  confidence: scaleObj.confidence || null
                };
              }
            }
            return {
              brand: b.brand,
              scales: filteredScales
            };
          });
          scanSummary = {
            scanId,
            tenantId,
            left_foot,
            right_foot,
            inputData,
            brands
          };
        }
        return {
          nickName,
          age,
          gender,
          scanSummary
        };
      });
      window.parent.postMessage({
        type: "USER_PROFILES_FROM_IFRAME",
        data: { userProfiles: summary }
      }, "*");
    }
    // Setup iframe navigation listener
    setupIframeNavigationListener() {
      window.addEventListener("popstate", () => {
        const currentUrl = window.location.href;
        const navigationData = {
          type: "iframe_navigation",
          url: currentUrl,
          timestamp: (/* @__PURE__ */ new Date()).toISOString(),
          sessionId: this.sessionId || Storage.getSessionId()
        };
        window.parent.postMessage({
          type: "IFRAME_NAVIGATION",
          data: navigationData
        }, "*");
      });
    }
  };
  var tracker = new SizeWiseTracker();
  window.SizeWiseTracker = tracker;
  var index_default = tracker;
  return __toCommonJS(index_exports);
})();
