(function () {
  "use strict";

  const DEFAULTS = {
    lineColor: "rgba(234, 242, 248, 0.95)",
    bgColor: "#000000",
    targetLineCount: 420,
    lineLength: 18,
    lineWidth: 3,
    easing: 0.12,
    enableConnections: true,
    connectionCount: 58,
    connectionLineWidth: 1.25,
    connectionOpacity: 0.28,
    connectionRefreshMs: 1300,
    connectionFadeMs: 900,
    colorTransitionMs: 820,
    compassNeedleCount: 22,
    compassNeedleBounce: 0.38
  };

  function clamp(value, min, max) {
    return Math.max(min, Math.min(max, value));
  }

  function angleDifference(target, current) {
    let diff = target - current;
    while (diff > Math.PI) diff -= Math.PI * 2;
    while (diff < -Math.PI) diff += Math.PI * 2;
    return diff;
  }

  function easeInOut(t) {
    const x = clamp(t, 0, 1);
    return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
  }

  function parseColor(input) {
    if (typeof input !== "string") return null;
    const value = input.trim();

    const rgba = value.match(/^rgba?\(\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*(?:,\s*([-\d.]+)\s*)?\)$/i);
    if (rgba) {
      return {
        r: clamp(parseFloat(rgba[1]), 0, 255),
        g: clamp(parseFloat(rgba[2]), 0, 255),
        b: clamp(parseFloat(rgba[3]), 0, 255),
        a: clamp(rgba[4] === undefined ? 1 : parseFloat(rgba[4]), 0, 1)
      };
    }

    const hex = value.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
    if (hex) {
      const raw = hex[1];
      if (raw.length === 3) {
        return {
          r: parseInt(raw[0] + raw[0], 16),
          g: parseInt(raw[1] + raw[1], 16),
          b: parseInt(raw[2] + raw[2], 16),
          a: 1
        };
      }
      return {
        r: parseInt(raw.slice(0, 2), 16),
        g: parseInt(raw.slice(2, 4), 16),
        b: parseInt(raw.slice(4, 6), 16),
        a: 1
      };
    }

    return null;
  }

  function mixColor(from, to, t) {
    return {
      r: from.r + (to.r - from.r) * t,
      g: from.g + (to.g - from.g) * t,
      b: from.b + (to.b - from.b) * t,
      a: from.a + (to.a - from.a) * t
    };
  }

  function toRgbaString(color) {
    return "rgba(" +
      Math.round(color.r) + ", " +
      Math.round(color.g) + ", " +
      Math.round(color.b) + ", " +
      clamp(color.a, 0, 1).toFixed(3) +
      ")";
  }

  function initTeamBackground(rootEl, options) {
    if (!rootEl || !rootEl.appendChild) {
      return { destroy: function destroyNoop() {} };
    }

    const config = Object.assign({}, DEFAULTS, options || {});
    const finePointerQuery = window.matchMedia("(hover: hover) and (pointer: fine)");
    const reduceMotionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
    const usesPointer = finePointerQuery.matches && !reduceMotionQuery.matches;

    const hero = rootEl.closest(".team-hero") || document.querySelector(".team-hero") || window;
    const canvas = document.createElement("canvas");
    canvas.setAttribute("aria-hidden", "true");
    canvas.style.position = "absolute";
    canvas.style.inset = "0";
    canvas.style.width = "100%";
    canvas.style.height = "100%";
    canvas.style.display = "block";
    canvas.style.pointerEvents = "none";
    rootEl.innerHTML = "";
    rootEl.style.background = config.bgColor;
    rootEl.appendChild(canvas);

    const context = canvas.getContext("2d");
    if (!context) {
      return { destroy: function destroyNoop() {} };
    }

    let width = 0;
    let height = 0;
    let dpr = 1;
    let rafId = 0;
    let destroyed = false;
    let points = [];
    let neighbors = [];
    let connections = [];
    let connectionEdgeSet = new Set();
    let connectionDegrees = [];
    let nextConnectionRefresh = 0;
    let compassNeedles = [];
    let baseLineColor = parseColor(config.lineColor) || { r: 234, g: 242, b: 248, a: 0.95 };
    let colorFrom = parseColor(config.lineColor) || { r: 234, g: 242, b: 248, a: 0.95 };
    let colorTo = { r: colorFrom.r, g: colorFrom.g, b: colorFrom.b, a: colorFrom.a };
    let colorCurrent = { r: colorFrom.r, g: colorFrom.g, b: colorFrom.b, a: colorFrom.a };
    let colorTransitionStart = 0;
    let colorTransitionDuration = Math.max(1, config.colorTransitionMs);
    let colorInTransition = false;
    let repelActive = false;
    let repelProgress = 0;
    let lastFrameTime = 0;

    const target = { x: 0, y: 0 };
    const drift = {
      t: 0,
      speed: 0.00085,
      ampX: 0.18,
      ampY: 0.14
    };

    function getFieldAngle(px, py) {
      const attractAngle = Math.atan2(target.y - py, target.x - px);
      const repelAngle = Math.atan2(py - target.y, px - target.x);
      return attractAngle + angleDifference(repelAngle, attractAngle) * repelProgress;
    }

    function buildGrid() {
      if (!width || !height) {
        points = [];
        return;
      }

      const aspect = width / height;
      const cols = Math.max(6, Math.round(Math.sqrt(config.targetLineCount * aspect)));
      const rows = Math.max(6, Math.round(config.targetLineCount / cols));
      const xStep = width / (cols + 1);
      const yStep = height / (rows + 1);
      const focalX = width * 0.28;
      const focalY = height * 0.56;
      const jitterAmount = Math.min(xStep, yStep) * 0.05;

      points = [];
      for (let row = 1; row <= rows; row += 1) {
        for (let col = 1; col <= cols; col += 1) {
          const jx = (Math.random() - 0.5) * jitterAmount;
          const jy = (Math.random() - 0.5) * jitterAmount;
          const x = col * xStep + jx;
          const y = row * yStep + jy;
          const baseAngle = Math.atan2(focalY - y, focalX - x);
          points.push({
            id: points.length,
            x: x,
            y: y,
            angle: baseAngle,
            baseAngle: baseAngle
          });
        }
      }

      buildNeighbors();
      rebuildCompassNeedles();
      rebuildConnections();
    }

    function rebuildCompassNeedles() {
      compassNeedles = [];
      if (!points.length || config.compassNeedleCount <= 0) return;

      const count = Math.min(points.length, config.compassNeedleCount);
      const picked = new Set();
      while (picked.size < count) {
        picked.add(Math.floor(Math.random() * points.length));
      }

      picked.forEach(function (index) {
        compassNeedles.push({
          index: index,
          velocity: 0,
          jitterOffset: Math.random() * Math.PI * 2,
          jitterSpeed: 0.001 + Math.random() * 0.0015,
          heading: Math.random() * Math.PI * 2,
          nextHeadingShiftAt: 0,
          stiffness: 0.09 + Math.random() * 0.06,
          damping: 0.8 + Math.random() * 0.08
        });
      });
    }

    function edgeKey(a, b) {
      return a < b ? a + "|" + b : b + "|" + a;
    }

    function buildNeighbors() {
      const total = points.length;
      const maxDistance = config.lineLength * 4.2;
      const maxDistanceSq = maxDistance * maxDistance;
      const minDistance = config.lineLength * 1.25;
      const minDistanceSq = minDistance * minDistance;

      neighbors = Array.from({ length: total }, function () {
        return [];
      });

      for (let i = 0; i < total; i += 1) {
        const a = points[i];
        for (let j = i + 1; j < total; j += 1) {
          const b = points[j];
          const dx = b.x - a.x;
          const dy = b.y - a.y;
          const distSq = dx * dx + dy * dy;
          if (distSq < minDistanceSq || distSq > maxDistanceSq) continue;
          neighbors[i].push({ id: j, distSq: distSq });
          neighbors[j].push({ id: i, distSq: distSq });
        }
      }

      for (let i = 0; i < neighbors.length; i += 1) {
        neighbors[i].sort(function (left, right) {
          return left.distSq - right.distSq;
        });
        if (neighbors[i].length > 12) {
          neighbors[i] = neighbors[i].slice(0, 12);
        }
      }
    }

    function createUnionFind(size) {
      const parent = new Array(size);
      const rank = new Array(size);
      for (let i = 0; i < size; i += 1) {
        parent[i] = i;
        rank[i] = 0;
      }
      return { parent: parent, rank: rank };
    }

    function findRoot(uf, node) {
      let root = node;
      while (uf.parent[root] !== root) {
        root = uf.parent[root];
      }
      while (uf.parent[node] !== node) {
        const next = uf.parent[node];
        uf.parent[node] = root;
        node = next;
      }
      return root;
    }

    function unionNodes(uf, a, b) {
      const rootA = findRoot(uf, a);
      const rootB = findRoot(uf, b);
      if (rootA === rootB) return false;
      if (uf.rank[rootA] < uf.rank[rootB]) {
        uf.parent[rootA] = rootB;
      } else if (uf.rank[rootA] > uf.rank[rootB]) {
        uf.parent[rootB] = rootA;
      } else {
        uf.parent[rootB] = rootA;
        uf.rank[rootA] += 1;
      }
      return true;
    }

    function rebuildGraphStateFromConnections() {
      connectionDegrees = new Array(points.length).fill(0);
      connectionEdgeSet = new Set();
      const uf = createUnionFind(points.length);

      for (let i = 0; i < connections.length; i += 1) {
        const edge = connections[i];
        connectionDegrees[edge.a] += 1;
        connectionDegrees[edge.b] += 1;
        connectionEdgeSet.add(edgeKey(edge.a, edge.b));
        unionNodes(uf, edge.a, edge.b);
      }

      return uf;
    }

    function tryAddConnection(uf, a, b, timestamp) {
      if (a === b) return false;
      if (connectionDegrees[a] >= 3 || connectionDegrees[b] >= 3) return false;

      const key = edgeKey(a, b);
      if (connectionEdgeSet.has(key)) return false;
      if (findRoot(uf, a) === findRoot(uf, b)) return false;

      connectionEdgeSet.add(key);
      connectionDegrees[a] += 1;
      connectionDegrees[b] += 1;
      unionNodes(uf, a, b);
      connections.push({
        a: a,
        b: b,
        pulseOffset: Math.random() * Math.PI * 2,
        phase: "entering",
        progress: 0,
        phaseStartedAt: timestamp
      });
      return true;
    }

    function fillConnections(uf, addTarget, timestamp) {
      let added = 0;
      let attempts = 0;
      const maxAttempts = Math.max(120, addTarget * 40);
      const frontier = [];
      const isInFrontier = new Array(points.length).fill(false);

      for (let i = 0; i < connectionDegrees.length; i += 1) {
        if (connectionDegrees[i] > 0) {
          frontier.push(i);
          isInFrontier[i] = true;
        }
      }

      while (added < addTarget && attempts < maxAttempts) {
        attempts += 1;
        if (!points.length) break;

        // Grow only from anchors that are already part of an existing line graph.
        // If graph is empty, allow a single random seed to start it.
        const from =
          frontier.length > 0
            ? frontier[Math.floor(Math.random() * frontier.length)]
            : Math.floor(Math.random() * points.length);
        const localNeighbors = neighbors[from];
        if (!localNeighbors || localNeighbors.length === 0) continue;

        const pickLimit = Math.min(7, localNeighbors.length);
        const pickedNeighbor = localNeighbors[Math.floor(Math.random() * pickLimit)];
        if (!pickedNeighbor) continue;

        if (tryAddConnection(uf, from, pickedNeighbor.id, timestamp)) {
          if (!isInFrontier[from]) {
            frontier.push(from);
            isInFrontier[from] = true;
          }
          if (!isInFrontier[pickedNeighbor.id]) {
            frontier.push(pickedNeighbor.id);
            isInFrontier[pickedNeighbor.id] = true;
          }
          added += 1;
        }
      }
    }

    function rebuildConnections() {
      connections = [];
      connectionEdgeSet = new Set();
      connectionDegrees = new Array(points.length).fill(0);
      nextConnectionRefresh = 0;

      if (!config.enableConnections || !points.length) return;

      const uf = createUnionFind(points.length);
      const now = typeof performance !== "undefined" ? performance.now() : 0;
      fillConnections(uf, config.connectionCount, now);
    }

    function setLineColor(nextColor, options) {
      const parsed = parseColor(nextColor);
      if (!parsed) return false;

      colorFrom = {
        r: colorCurrent.r,
        g: colorCurrent.g,
        b: colorCurrent.b,
        a: colorCurrent.a
      };
      colorTo = parsed;
      colorTransitionDuration = Math.max(1, (options && options.duration) || config.colorTransitionMs);
      colorTransitionStart = typeof performance !== "undefined" ? performance.now() : 0;
      colorInTransition = true;
      return true;
    }

    function updateLineColor(timestamp) {
      if (!colorInTransition) return;
      const elapsed = Math.max(0, timestamp - colorTransitionStart);
      const t = clamp(elapsed / colorTransitionDuration, 0, 1);
      const eased = easeInOut(t);
      colorCurrent = mixColor(colorFrom, colorTo, eased);
      if (t >= 1) {
        colorCurrent = { r: colorTo.r, g: colorTo.g, b: colorTo.b, a: colorTo.a };
        colorInTransition = false;
      }
    }

    function updateConnectionPhases(timestamp) {
      if (!config.enableConnections || connections.length === 0) return;

      for (let i = connections.length - 1; i >= 0; i -= 1) {
        const edge = connections[i];
        if (!edge) continue;

        if (edge.phase === "active") {
          edge.progress = 1;
          continue;
        }

        const elapsed = Math.max(0, timestamp - (edge.phaseStartedAt || 0));
        const t = clamp(elapsed / Math.max(1, config.connectionFadeMs), 0, 1);

        if (edge.phase === "entering") {
          edge.progress = t;
          if (t >= 1) {
            edge.phase = "active";
            edge.progress = 1;
          }
          continue;
        }

        if (edge.phase === "leaving") {
          edge.progress = 1 - t;
          if (t >= 1 || edge.progress <= 0) {
            connections.splice(i, 1);
          }
        }
      }
    }

    function refreshConnectionSubset(timestamp) {
      if (!config.enableConnections || !points.length) return;
      if (timestamp < nextConnectionRefresh) return;

      nextConnectionRefresh = timestamp + config.connectionRefreshMs;

      if (connections.length === 0) {
        rebuildConnections();
        return;
      }

      const candidates = connections.filter(function (edge) {
        return edge.phase === "active";
      });
      if (candidates.length === 0) return;

      const removeCount = Math.max(1, Math.floor(candidates.length * 0.2));
      for (let i = 0; i < removeCount; i += 1) {
        const pick = candidates[Math.floor(Math.random() * candidates.length)];
        if (!pick || pick.phase !== "active") continue;
        pick.phase = "leaving";
        pick.phaseStartedAt = timestamp;
      }
    }

    function drawConnections(timestamp) {
      if (!config.enableConnections || connections.length === 0) return;

      context.lineWidth = config.lineWidth;
      context.strokeStyle = toRgbaString(colorCurrent);

      for (let i = 0; i < connections.length; i += 1) {
        const edge = connections[i];
        const phaseProgress = easeInOut(edge.progress || 0);
        if (phaseProgress <= 0.001) continue;
        const from = points[edge.a];
        const to = points[edge.b];
        if (!from || !to) continue;

        const dx = to.x - from.x;
        const dy = to.y - from.y;
        const distance = Math.hypot(dx, dy);
        if (distance < 1) continue;

        const dirX = dx / distance;
        const dirY = dy / distance;
        const angleAToB = Math.atan2(dy, dx);
        const angleBToA = angleAToB + Math.PI;
        const magneticA = getFieldAngle(from.x, from.y);
        const magneticB = getFieldAngle(to.x, to.y);

        const pulseA = 0.58 + 0.42 * Math.sin(timestamp * 0.00135 + edge.pulseOffset);
        const pulseB = 0.58 + 0.42 * Math.cos(timestamp * 0.00112 + edge.pulseOffset * 1.17);
        const reachA = clamp(distance * 0.5 * pulseA * phaseProgress, 0, distance * 0.5);
        const reachB = clamp(distance * 0.5 * pulseB * phaseProgress, 0, distance * 0.5);
        const totalReach = Math.min(distance, reachA + reachB);
        if (totalReach <= 0.5) continue;

        const meetRatio = clamp(reachA / totalReach, 0, 1);
        const baseMeetX = from.x + dirX * totalReach * meetRatio;
        const baseMeetY = from.y + dirY * totalReach * meetRatio;
        const normalX = -dirY;
        const normalY = dirX;
        const fieldBias =
          0.5 * Math.sin(angleDifference(magneticA, angleAToB)) -
          0.5 * Math.sin(angleDifference(magneticB, angleBToA));
        const bendOffset = fieldBias * Math.min(config.lineLength * 1.4, distance * 0.18);
        const meetX = baseMeetX + normalX * bendOffset;
        const meetY = baseMeetY + normalY * bendOffset;

        // Fold arm from A: starts at midpoint, bends, then reaches join point.
        const foldA = Math.sin(timestamp * 0.0016 + edge.pulseOffset) * 0.52;
        const fieldBlendA = from.angle + angleDifference(magneticA, from.angle) * 0.4;
        const hingeAAngle = fieldBlendA + angleDifference(angleAToB, fieldBlendA) * 0.55 + foldA;
        const hingeALen = Math.min(reachA * 0.55, Math.max(6, config.lineLength * 0.85));
        const hingeAX = from.x + Math.cos(hingeAAngle) * hingeALen;
        const hingeAY = from.y + Math.sin(hingeAAngle) * hingeALen;

        // Fold arm from B: also bends from its own midpoint.
        const foldB = Math.cos(timestamp * 0.00142 + edge.pulseOffset * 1.21) * 0.52;
        const fieldBlendB = to.angle + angleDifference(magneticB, to.angle) * 0.4;
        const hingeBAngle = fieldBlendB + angleDifference(angleBToA, fieldBlendB) * 0.55 + foldB;
        const hingeBLen = Math.min(reachB * 0.55, Math.max(6, config.lineLength * 0.85));
        const hingeBX = to.x + Math.cos(hingeBAngle) * hingeBLen;
        const hingeBY = to.y + Math.sin(hingeBAngle) * hingeBLen;

        const alpha = clamp(config.connectionOpacity * phaseProgress * (0.65 + 0.35 * (pulseA + pulseB) * 0.5), 0.02, 0.5);
        context.globalAlpha = alpha;

        context.beginPath();
        context.moveTo(from.x, from.y);
        context.lineTo(hingeAX, hingeAY);
        context.lineTo(meetX, meetY);
        context.stroke();

        context.beginPath();
        context.moveTo(to.x, to.y);
        context.lineTo(hingeBX, hingeBY);
        context.lineTo(meetX, meetY);
        context.stroke();
      }

      context.globalAlpha = 1;
    }

    function resize() {
      const rect = rootEl.getBoundingClientRect();
      width = Math.max(1, Math.round(rect.width));
      height = Math.max(1, Math.round(rect.height));
      dpr = clamp(window.devicePixelRatio || 1, 1, 2);
      canvas.width = Math.round(width * dpr);
      canvas.height = Math.round(height * dpr);
      context.setTransform(dpr, 0, 0, dpr, 0, 0);
      buildGrid();

      if (!usesPointer) {
        target.x = width * 0.5;
        target.y = height * 0.5;
      }
    }

    function updateTargetFromPointer(event) {
      const rect = rootEl.getBoundingClientRect();
      target.x = event.clientX - rect.left;
      target.y = event.clientY - rect.top;
    }

    function drawFrame(timestamp) {
      if (destroyed) return;

      if (!lastFrameTime) lastFrameTime = timestamp;
      const dt = Math.max(0, timestamp - lastFrameTime);
      lastFrameTime = timestamp;
      const repelTarget = repelActive ? 1 : 0;
      const blendStep = 1 - Math.exp(-dt / 420);
      repelProgress += (repelTarget - repelProgress) * blendStep;

      updateConnectionPhases(timestamp);
      refreshConnectionSubset(timestamp);
      updateLineColor(timestamp);

      if (config.enableConnections && connections.length < config.connectionCount) {
        const uf = rebuildGraphStateFromConnections();
        fillConnections(uf, config.connectionCount - connections.length, timestamp);
      }

      const baseLineColorString = toRgbaString(baseLineColor);
      const accentLineColorString = toRgbaString(colorCurrent);

      context.clearRect(0, 0, width, height);
      context.fillStyle = config.bgColor;
      context.fillRect(0, 0, width, height);
      context.strokeStyle = baseLineColorString;
      context.lineWidth = config.lineWidth;
      context.lineCap = "round";

      if (!usesPointer) {
        drift.t = timestamp * drift.speed;
        target.x = width * (0.5 + Math.sin(drift.t * 1.18) * drift.ampX);
        target.y = height * (0.5 + Math.cos(drift.t * 0.92) * drift.ampY);
      }

      const influenceX = new Array(points.length).fill(0);
      const influenceY = new Array(points.length).fill(0);
      const influenceWeight = new Array(points.length).fill(0);
      const connectedPoints = new Set();

      if (config.enableConnections && connections.length > 0) {
        for (let i = 0; i < connections.length; i += 1) {
          const edge = connections[i];
          const phaseProgress = easeInOut(edge.progress || 0);
          if (phaseProgress <= 0.001) continue;
          const from = points[edge.a];
          const to = points[edge.b];
          if (!from || !to) continue;
          connectedPoints.add(edge.a);
          connectedPoints.add(edge.b);

          const dx = to.x - from.x;
          const dy = to.y - from.y;
          const distance = Math.hypot(dx, dy);
          if (distance < 1) continue;
          const inv = 1 / distance;
          const nx = dx * inv;
          const ny = dy * inv;
          const strength = (0.42 + 0.58 * (0.5 + 0.5 * Math.sin(timestamp * 0.00125 + edge.pulseOffset))) * phaseProgress;

          influenceX[edge.a] += nx * strength;
          influenceY[edge.a] += ny * strength;
          influenceWeight[edge.a] += strength;

          influenceX[edge.b] -= nx * strength;
          influenceY[edge.b] -= ny * strength;
          influenceWeight[edge.b] += strength;
        }
      }

      const compassByIndex = new Map();
      for (let i = 0; i < compassNeedles.length; i += 1) {
        const needle = compassNeedles[i];
        const point = points[needle.index];
        if (!point) continue;

        if (!needle.nextHeadingShiftAt || timestamp >= needle.nextHeadingShiftAt) {
          needle.heading += (Math.random() * 2 - 1) * Math.PI * 0.9;
          needle.nextHeadingShiftAt = timestamp + 700 + Math.random() * 1500;
        }

        const jitter = Math.sin(timestamp * needle.jitterSpeed + needle.jitterOffset) * config.compassNeedleBounce;
        const desired = needle.heading + jitter;
        const delta = angleDifference(desired, point.angle);

        needle.velocity += delta * needle.stiffness;
        needle.velocity *= needle.damping;
        compassByIndex.set(needle.index, needle.velocity);
      }

      for (let i = 0; i < points.length; i += 1) {
        const point = points[i];
        const magneticAngle = getFieldAngle(point.x, point.y);
        let targetAngle = magneticAngle;
        if (influenceWeight[i] > 0.0001) {
          const pullAngle = Math.atan2(influenceY[i], influenceX[i]);
          const pullMix = clamp(influenceWeight[i] / 2.3, 0.18, 0.55);
          targetAngle = magneticAngle + angleDifference(pullAngle, magneticAngle) * pullMix;
        }

        const nextAngle = point.angle + angleDifference(targetAngle, point.angle) * config.easing;
        const compassKick = compassByIndex.get(i) || 0;
        point.angle = nextAngle + compassKick;

        if (connectedPoints.has(i)) {
          context.beginPath();
          context.arc(point.x, point.y, config.lineWidth * 0.5, 0, Math.PI * 2);
          context.fillStyle = accentLineColorString;
          context.fill();
        } else {
          context.strokeStyle = compassByIndex.has(i) ? accentLineColorString : baseLineColorString;
          const halfLength = config.lineLength * 0.5;
          const cos = Math.cos(point.angle);
          const sin = Math.sin(point.angle);
          const x1 = point.x - cos * halfLength;
          const y1 = point.y - sin * halfLength;
          const x2 = point.x + cos * halfLength;
          const y2 = point.y + sin * halfLength;

          context.beginPath();
          context.moveTo(x1, y1);
          context.lineTo(x2, y2);
          context.stroke();
        }
      }

      drawConnections(timestamp);

      rafId = window.requestAnimationFrame(drawFrame);
    }

    function onPointerLeave() {
      target.x = width * 0.5;
      target.y = height * 0.5;
    }

    function onPointerDown() {
      repelActive = true;
    }

    function onPointerUp() {
      repelActive = false;
    }

    function destroy() {
      if (destroyed) return;
      destroyed = true;
      window.cancelAnimationFrame(rafId);
      window.removeEventListener("resize", resize);
      window.removeEventListener("orientationchange", resize);
      if (usesPointer) {
        hero.removeEventListener("pointermove", updateTargetFromPointer);
        hero.removeEventListener("pointerleave", onPointerLeave);
        hero.removeEventListener("pointerdown", onPointerDown);
        window.removeEventListener("pointerup", onPointerUp);
        window.removeEventListener("pointercancel", onPointerUp);
        window.removeEventListener("blur", onPointerUp);
      }
      if (canvas.parentNode === rootEl) {
        rootEl.removeChild(canvas);
      }
      rootEl.style.background = "";
    }

    resize();
    target.x = width * 0.5;
    target.y = height * 0.5;
    window.addEventListener("resize", resize);
    window.addEventListener("orientationchange", resize);
    if (usesPointer) {
      hero.addEventListener("pointermove", updateTargetFromPointer, { passive: true });
      hero.addEventListener("pointerleave", onPointerLeave);
      hero.addEventListener("pointerdown", onPointerDown);
      window.addEventListener("pointerup", onPointerUp);
      window.addEventListener("pointercancel", onPointerUp);
      window.addEventListener("blur", onPointerUp);
    }
    rafId = window.requestAnimationFrame(drawFrame);

    return {
      destroy: destroy,
      setLineColor: setLineColor
    };
  }

  window.initTeamBackground = initTeamBackground;
})();
