// @bun
var{defineProperty:L,getOwnPropertyNames:R,getOwnPropertyDescriptor:T}=Object,U=Object.prototype.hasOwnProperty;function W(q){return this[q]}var X=(q)=>{var j=(M??=new WeakMap).get(q),D;if(j)return j;if(j=L({},"__esModule",{value:!0}),q&&typeof q==="object"||typeof q==="function"){for(var E of R(q))if(!U.call(j,E))L(j,E,{get:W.bind(q,E),enumerable:!(D=T(q,E))||D.enumerable})}return M.set(q,j),j},M;var Z=(q)=>q;function _(q,j){this[q]=Z.bind(null,j)}var Y=(q,j)=>{for(var D in j)L(q,D,{get:j[D],enumerable:!0,configurable:!0,set:_.bind(j,D)})};var $=(q,j)=>()=>(q&&(j=q(q=0)),j);var b=import.meta.require;function N(q){let j=q.heatmap;if(!j?.enabled)return"";let D={...k,...j};return`
<!-- stx Heatmap - Privacy-Compliant Tracking -->
<script>
(function() {
  'use strict';

  // Configuration
  var config = ${JSON.stringify({trackMouse:D.trackMouse,trackClicks:D.trackClicks,trackScroll:D.trackScroll,samplingRate:D.samplingRate,honorDnt:D.honorDnt,endpoint:D.endpoint,batchSize:D.batchSize,maxDataPoints:D.maxDataPoints,sessionTimeout:D.sessionTimeout,persistData:D.persistData,storagePrefix:D.storagePrefix,captureAttributes:D.captureAttributes,ignoreSelectors:D.ignoreSelectors,zones:D.zones,debugOverlay:D.debugOverlay,minViewportWidth:D.minViewportWidth,maxViewportWidth:D.maxViewportWidth})};

  // Check Do Not Track
  if (config.honorDnt && navigator.doNotTrack === '1') {
    return;
  }

  // Check viewport constraints
  var vw = window.innerWidth;
  if (config.minViewportWidth && vw < config.minViewportWidth) return;
  if (config.maxViewportWidth && vw > config.maxViewportWidth) return;

  // Session management (anonymous, no cookies)
  var session = {
    sid: Math.random().toString(36).slice(2) + Date.now().toString(36),
    page: location.pathname,
    vw: window.innerWidth,
    vh: window.innerHeight,
    points: [],
    started: Date.now(),
    lastActivity: Date.now()
  };

  // Throttle helper
  var lastMove = 0;
  function throttle(fn, wait) {
    return function() {
      var now = Date.now();
      if (now - lastMove >= wait) {
        lastMove = now;
        fn.apply(this, arguments);
      }
    };
  }

  // Get relative coordinates (percentage)
  function getRelativeCoords(e) {
    return {
      x: Math.round((e.clientX / window.innerWidth) * 10000) / 100,
      y: Math.round((e.clientY / window.innerHeight) * 10000) / 100
    };
  }

  // Check if element should be ignored
  function shouldIgnore(el) {
    if (!el || !config.ignoreSelectors) return false;
    for (var i = 0; i < config.ignoreSelectors.length; i++) {
      if (el.matches && el.matches(config.ignoreSelectors[i])) return true;
      if (el.closest && el.closest(config.ignoreSelectors[i])) return true;
    }
    return false;
  }

  // Get element selector (simplified, no IDs to preserve privacy)
  function getSelector(el) {
    if (!el || !el.tagName) return null;
    var tag = el.tagName.toLowerCase();
    var classes = el.className && typeof el.className === 'string'
      ? '.' + el.className.trim().split(/\\s+/).slice(0, 2).join('.')
      : '';
    return tag + classes;
  }

  // Find zone for element
  function findZone(el) {
    if (!config.zones || !el) return null;
    for (var i = 0; i < config.zones.length; i++) {
      var zone = config.zones[i];
      if (el.closest && el.closest(zone.selector)) {
        return zone.id;
      }
    }
    return null;
  }

  // Capture custom attributes
  function captureAttributes(el) {
    if (!config.captureAttributes || !el) return null;
    var attrs = {};
    var hasAttrs = false;
    for (var i = 0; i < config.captureAttributes.length; i++) {
      var attr = config.captureAttributes[i];
      var value = el.getAttribute && el.getAttribute(attr);
      if (value) {
        attrs[attr] = value;
        hasAttrs = true;
      }
    }
    return hasAttrs ? attrs : null;
  }

  // Add data point
  function addPoint(point) {
    session.lastActivity = Date.now();
    if (session.points.length >= config.maxDataPoints) {
      session.points.shift();
    }
    session.points.push(point);

    // Send batch if threshold reached
    if (config.endpoint && session.points.length >= config.batchSize) {
      sendData();
    }
  }

  // Send data to endpoint
  function sendData() {
    if (!config.endpoint || session.points.length === 0) return;

    var data = {
      sid: session.sid,
      page: session.page,
      vw: session.vw,
      vh: session.vh,
      points: session.points.splice(0, config.batchSize)
    };

    // Use sendBeacon for reliability
    if (navigator.sendBeacon) {
      navigator.sendBeacon(config.endpoint, JSON.stringify(data));
    }
else {
      var xhr = new XMLHttpRequest();
      xhr.open('POST', config.endpoint, true);
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.send(JSON.stringify(data));
    }
  }

  // Mouse move handler
  if (config.trackMouse) {
    document.addEventListener('mousemove', throttle(function(e) {
      if (shouldIgnore(e.target)) return;
      var coords = getRelativeCoords(e);
      addPoint({
        x: coords.x,
        y: coords.y,
        type: 'move',
        t: Date.now(),
        zone: findZone(e.target)
      });
    }, config.samplingRate), { passive: true });
  }

  // Click handler
  if (config.trackClicks) {
    document.addEventListener('click', function(e) {
      if (shouldIgnore(e.target)) return;
      var coords = getRelativeCoords(e);
      var point = {
        x: coords.x,
        y: coords.y,
        type: 'click',
        t: Date.now(),
        el: getSelector(e.target),
        zone: findZone(e.target)
      };
      var attrs = captureAttributes(e.target);
      if (attrs) point.attrs = attrs;
      addPoint(point);
    }, { passive: true });
  }

  // Scroll handler
  if (config.trackScroll) {
    var lastScrollDepth = 0;
    document.addEventListener('scroll', throttle(function() {
      var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
      var scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
      var depth = scrollHeight > 0 ? Math.round((scrollTop / scrollHeight) * 100) : 0;

      // Only track significant scroll changes (every 10%)
      if (Math.abs(depth - lastScrollDepth) >= 10) {
        lastScrollDepth = depth;
        addPoint({
          x: 50,
          y: depth,
          type: 'scroll',
          t: Date.now(),
          depth: depth
        });
      }
    }, config.samplingRate * 2), { passive: true });
  }

  // Send remaining data on page unload
  window.addEventListener('beforeunload', sendData);
  window.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'hidden') {
      sendData();
    }
  });

  // Persist data to localStorage if enabled
  if (config.persistData) {
    var storageKey = config.storagePrefix + '_' + session.page.replace(/\\//g, '_');

    // Load existing data
    try {
      var stored = localStorage.getItem(storageKey);
      if (stored) {
        var parsed = JSON.parse(stored);
        if (Date.now() - parsed.lastActivity < config.sessionTimeout * 60000) {
          session.points = parsed.points || [];
        }
      }
    }
catch (e) {}

    // Save periodically
    setInterval(function() {
      try {
        localStorage.setItem(storageKey, JSON.stringify({
          points: session.points,
          lastActivity: session.lastActivity
        }));
      }
catch (e) {}
    }, 5000);
  }

  // Debug overlay
  if (config.debugOverlay) {
    var overlay = document.createElement('div');
    overlay.id = 'stx-heatmap-overlay';
    overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:999999;';
    document.body.appendChild(overlay);

    var canvas = document.createElement('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.cssText = 'width:100%;height:100%;';
    overlay.appendChild(canvas);
    var ctx = canvas.getContext('2d');

    function renderOverlay() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      session.points.forEach(function(p) {
        var x = (p.x / 100) * canvas.width;
        var y = (p.y / 100) * canvas.height;
        ctx.beginPath();
        ctx.arc(x, y, p.type === 'click' ? 8 : 3, 0, Math.PI * 2);
        ctx.fillStyle = p.type === 'click' ? 'rgba(255,0,0,0.5)' : 'rgba(0,0,255,0.2)';
        ctx.fill();
      });
      requestAnimationFrame(renderOverlay);
    }
    renderOverlay();

    window.addEventListener('resize', function() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    });
  }

  // Expose API for manual tracking and data export
  window.stxHeatmap = {
    // Get current session data
    getData: function() {
      return {
        sid: session.sid,
        page: session.page,
        vw: session.vw,
        vh: session.vh,
        points: session.points.slice(),
        started: session.started,
        lastActivity: session.lastActivity
      };
    },
    // Export data as JSON
    exportJSON: function() {
      return JSON.stringify(this.getData(), null, 2);
    },
    // Export data as CSV
    exportCSV: function() {
      var data = this.getData();
      var lines = ['x,y,type,timestamp,element,zone,depth'];
      data.points.forEach(function(p) {
        lines.push([p.x, p.y, p.type, p.t, p.el || '', p.zone || '', p.depth || ''].join(','));
      });
      return lines.join('\\n');
    },
    // Manual data send
    flush: function() {
      sendData();
    },
    // Clear data
    clear: function() {
      session.points = [];
      if (config.persistData) {
        var storageKey = config.storagePrefix + '_' + session.page.replace(/\\//g, '_');
        try { localStorage.removeItem(storageKey); }
catch (e) {}
      }
    },
    // Add custom event
    track: function(type, data) {
      addPoint({
        x: data && data.x || 0,
        y: data && data.y || 0,
        type: type,
        t: Date.now(),
        attrs: data
      });
    },
    // Generate heatmap visualization
    visualize: function(options) {
      options = options || {};
      var data = this.getData();
      var width = options.width || data.vw;
      var height = options.height || data.vh;
      var radius = options.radius || 20;
      var blur = options.blur || 15;
      var maxOpacity = options.maxOpacity || 0.6;

      var canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext('2d');

      // Create heat points
      data.points.forEach(function(p) {
        var x = (p.x / 100) * width;
        var y = (p.y / 100) * height;
        var intensity = p.type === 'click' ? 1 : 0.3;

        var gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
        gradient.addColorStop(0, 'rgba(255,0,0,' + intensity + ')');
        gradient.addColorStop(1, 'rgba(255,0,0,0)');
        ctx.fillStyle = gradient;
        ctx.fillRect(x - radius, y - radius, radius * 2, radius * 2);
      });

      // Apply blur
      ctx.filter = 'blur(' + blur + 'px)';
      ctx.drawImage(canvas, 0, 0);
      ctx.filter = 'none';

      // Colorize
      var imageData = ctx.getImageData(0, 0, width, height);
      var pixels = imageData.data;
      for (var i = 0; i < pixels.length; i += 4) {
        var alpha = pixels[i + 3];
        if (alpha > 0) {
          var ratio = alpha / 255;
          // Gradient: blue -> cyan -> green -> yellow -> red
          if (ratio < 0.25) {
            pixels[i] = 0;
            pixels[i + 1] = Math.round(ratio * 4 * 255);
            pixels[i + 2] = 255;
          }
else if (ratio < 0.5) {
            pixels[i] = 0;
            pixels[i + 1] = 255;
            pixels[i + 2] = Math.round((1 - (ratio - 0.25) * 4) * 255);
          }
else if (ratio < 0.75) {
            pixels[i] = Math.round((ratio - 0.5) * 4 * 255);
            pixels[i + 1] = 255;
            pixels[i + 2] = 0;
          }
else {
            pixels[i] = 255;
            pixels[i + 1] = Math.round((1 - (ratio - 0.75) * 4) * 255);
            pixels[i + 2] = 0;
          }
          pixels[i + 3] = Math.round(alpha * maxOpacity);
        }
      }
      ctx.putImageData(imageData, 0, 0);

      return canvas;
    }
  };
})();
</script>
`}function w(q,j){let D=N(j);if(!D)return q;let E=q.lastIndexOf("</body>");if(E!==-1)return q.slice(0,E)+D+q.slice(E);return q+D}function v(q){let j={},D=q.match(/(\w+)=["']?([^"'\s]+)["']?/g)||[];for(let E of D){let[F,J]=E.split("="),G=J?.replace(/["']/g,"");switch(F){case"endpoint":j.endpoint=G;break;case"samplingRate":j.samplingRate=Number.parseInt(G,10);break;case"batchSize":j.batchSize=Number.parseInt(G,10);break;case"trackMouse":j.trackMouse=G==="true";break;case"trackClicks":j.trackClicks=G==="true";break;case"trackScroll":j.trackScroll=G==="true";break;case"honorDnt":j.honorDnt=G==="true";break;case"debugOverlay":j.debugOverlay=G==="true";break}}return j}class O{sessions=new Map;addSession(q){let j=this.sessions.get(q.sid);if(j)j.points.push(...q.points),j.lastActivity=Math.max(j.lastActivity,q.lastActivity);else this.sessions.set(q.sid,q)}getPageData(q){let j=[];for(let D of this.sessions.values())if(D.page===q)j.push(...D.points);return j}getClickData(q){return this.getPageData(q).filter((j)=>j.type==="click")}getMovementData(q){return this.getPageData(q).filter((j)=>j.type==="move")}getScrollData(q){let j=this.getPageData(q).filter((E)=>E.type==="scroll"),D=new Map;for(let E of j)if(E.depth!==void 0)D.set(E.depth,(D.get(E.depth)||0)+1);return Array.from(D.entries()).map(([E,F])=>({depth:E,count:F})).sort((E,F)=>E.depth-F.depth)}getZoneStats(q){let j=new Map,D=this.getPageData(q);for(let E of D)if(E.zone){let F=j.get(E.zone)||{clicks:0,hovers:0};if(E.type==="click")F.clicks++;else if(E.type==="move")F.hovers++;j.set(E.zone,F)}return j}generateGridData(q,j=20){let D=this.getPageData(q),E=[];for(let J=0;J<j;J++){E[J]=[];for(let G=0;G<j;G++)E[J][G]=0}for(let J of D){let G=Math.min(Math.floor(J.x/100*j),j-1),K=Math.min(Math.floor(J.y/100*j),j-1);E[K][G]+=J.type==="click"?3:1}let F=0;for(let J of E)for(let G of J)F=Math.max(F,G);return E.map((J,G)=>J.map((K,Q)=>({x:Q,y:G,intensity:F>0?K/F:0})))}exportJSON(){return JSON.stringify({sessions:Array.from(this.sessions.values()),exportedAt:new Date().toISOString()},null,2)}clear(){this.sessions.clear()}get sessionCount(){return this.sessions.size}get totalPoints(){let q=0;for(let j of this.sessions.values())q+=j.points.length;return q}}function I(){return new O}var k,B;var P=$(()=>{k={enabled:!1,trackMouse:!0,trackClicks:!0,trackScroll:!0,samplingRate:100,honorDnt:!0,batchSize:50,maxDataPoints:1000,sessionTimeout:30,persistData:!1,storagePrefix:"stx_heatmap",captureAttributes:["data-heatmap-id","data-track"],ignoreSelectors:["[data-heatmap-ignore]",".heatmap-ignore"],debugOverlay:!1};B={name:"heatmap",hasEndTag:!1,description:"Inject privacy-compliant heatmap tracking script",handler:async(q,j,D,E)=>{let F=D.__stx_config||{};if(j.length>0){let J=v(j.join(" "));F.heatmap={...F.heatmap,...J,enabled:!0}}return N(F)}}});P();export{w as injectHeatmap,B as heatmapDirective,N as generateHeatmapScript,k as defaultHeatmapConfig,I as createHeatmapAggregator,O as HeatmapAggregator};
