(function cookieConsent() {
  const banner = document.getElementById("cookieConsent");
  const accept = document.getElementById("cookieAccept");
  const reject = document.getElementById("cookieReject");
  const storageKey = "adamas_cookie_consent";
  const measurementId = "G-4EEWBQ916D";
  let analyticsLoaded = false;

  if (!banner || !accept || !reject) return;

  function setConsent(value) {
    try {
      window.localStorage.setItem(storageKey, value);
    } catch (_) {}
  }

  function getConsent() {
    try {
      return window.localStorage.getItem(storageKey);
    } catch (_) {
      return null;
    }
  }

  function hideBanner() {
    banner.classList.remove("is-visible");
    document.body.classList.remove("cookie-consent-open");
  }

  function showBanner() {
    banner.classList.add("is-visible");
    document.body.classList.add("cookie-consent-open");
  }

  function loadAnalytics() {
    if (analyticsLoaded) return;
    analyticsLoaded = true;

    window.dataLayer = window.dataLayer || [];
    window.gtag = function gtag() {
      window.dataLayer.push(arguments);
    };

    window.gtag("js", new Date());
    window.gtag("config", measurementId, {
      anonymize_ip: true,
      transport_type: "beacon",
    });

    const script = document.createElement("script");
    script.async = true;
    script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
    document.head.appendChild(script);
  }

  accept.addEventListener("click", () => {
    setConsent("accepted");
    hideBanner();
    loadAnalytics();
  });

  reject.addEventListener("click", () => {
    setConsent("rejected");
    hideBanner();
  });

  const savedConsent = getConsent();
  if (savedConsent === "accepted") {
    loadAnalytics();
    hideBanner();
    return;
  }

  if (savedConsent === "rejected") {
    hideBanner();
    return;
  }

  showBanner();
})();

(function contactForm() {
  const form = document.querySelector("[data-contact-form]");
  if (!form) return;

  const status = form.querySelector("[data-form-status]");
  const recipient = (form.getAttribute("data-mail-recipient") || "").trim();
  const launchText = "Your email app should open now with the enquiry details prefilled. If nothing opens, use the direct email button instead.";
  const configText = "This form still needs a recipient email address configured.";

  function setStatus(message, type) {
    if (!status) return;
    status.textContent = message;
    status.classList.remove("is-success", "is-error");
    if (type) status.classList.add(type);
  }

  form.addEventListener("submit", (event) => {
    event.preventDefault();

    if (!recipient) {
      setStatus(configText, "is-error");
      return;
    }

    if (!form.checkValidity()) {
      form.reportValidity();
      return;
    }

    const formData = new FormData(form);
    if ((formData.get("_gotcha") || "").toString().trim()) return;

    const name = (formData.get("name") || "").toString().trim();
    const company = (formData.get("company") || "").toString().trim();
    const email = (formData.get("email") || "").toString().trim();
    const phone = (formData.get("phone") || "").toString().trim();
    const subject = (formData.get("subject") || "").toString().trim();
    const message = (formData.get("message") || "").toString().trim();

    const lines = [
      "A new enquiry was prepared through the Adamas Aqua website.",
      "",
      `Name: ${name}`,
      `Company: ${company || "Not provided"}`,
      `Email: ${email}`,
      `Phone: ${phone || "Not provided"}`,
      "",
      "Message:",
      message,
    ];

    const mailto = `mailto:${encodeURIComponent(recipient)}?subject=${encodeURIComponent(`[Website Enquiry] ${subject}`)}&body=${encodeURIComponent(lines.join("\n"))}`;
    setStatus(launchText, "is-success");
    window.location.href = mailto;
  });
})();

(function mobileNav() {
  const toggle = document.querySelector(".nav-toggle");
  const nav = document.getElementById("siteNav");
  if (!toggle || !nav) return;

  function closeNav() {
    nav.classList.remove("is-open");
    toggle.setAttribute("aria-expanded", "false");
  }

  toggle.addEventListener("click", () => {
    const isOpen = nav.classList.toggle("is-open");
    toggle.setAttribute("aria-expanded", isOpen ? "true" : "false");
  });

  nav.querySelectorAll("a").forEach((link) => {
    link.addEventListener("click", closeNav);
  });

  document.addEventListener("click", (event) => {
    if (!nav.classList.contains("is-open")) return;
    if (nav.contains(event.target) || toggle.contains(event.target)) return;
    closeNav();
  });

  window.addEventListener("resize", () => {
    if (window.innerWidth > 980) closeNav();
  });
})();

(function faqAccordion() {
  const items = document.querySelectorAll(".faq-item");
  if (!items.length) return;

  items.forEach((item) => {
    item.addEventListener("toggle", () => {
      if (!item.open) return;
      items.forEach((other) => {
        if (other !== item) other.open = false;
      });
    });
  });
})();

(function heroVideoPlayback() {
  const video = document.getElementById("heroVideo");
  if (!video) return;

  const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");

  function tryPlay() {
    video.muted = true;
    const playback = video.play();
    if (playback && typeof playback.catch === "function") {
      playback.catch(() => {});
    }
  }

  function syncPlayback() {
    if (reducedMotion.matches) {
      video.pause();
      return;
    }

    if (document.visibilityState === "visible") {
      tryPlay();
    }
  }

  syncPlayback();

  if (typeof reducedMotion.addEventListener === "function") {
    reducedMotion.addEventListener("change", syncPlayback);
  } else if (typeof reducedMotion.addListener === "function") {
    reducedMotion.addListener(syncPlayback);
  }

  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") {
      syncPlayback();
    } else {
      video.pause();
    }
  });
})();

(function autoScrollPause() {
  const containers = document.querySelectorAll(".hero-banner");
  if (!containers.length) return;

  containers.forEach((container) => {
    const pause = () => container.classList.add("is-paused");
    const resume = () => container.classList.remove("is-paused");

    container.addEventListener("mouseenter", pause);
    container.addEventListener("mouseleave", resume);
    container.addEventListener("focusin", pause);
    container.addEventListener("focusout", resume);
    container.addEventListener("touchstart", pause, { passive: true });
    container.addEventListener("touchend", resume);
    container.addEventListener("touchcancel", resume);
    container.addEventListener("pointerdown", pause);
    container.addEventListener("pointerup", resume);
    container.addEventListener("pointercancel", resume);
  });
})();

(function cardHighlightOnView() {
  const cards = document.querySelectorAll(".proof-card, .info-card, .faq-item, .contact-item, .partner-logo-slot");
  if (!cards.length || !("IntersectionObserver" in window)) return;

  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        entry.target.classList.toggle("is-highlighted", entry.isIntersecting && entry.intersectionRatio > 0.55);
      });
    },
    { threshold: [0.55] }
  );

  cards.forEach((card) => observer.observe(card));
})();

(function optimizeImageLoading() {
  const images = document.querySelectorAll("img");
  if (!images.length) return;

  images.forEach((image) => {
    if (!image.hasAttribute("decoding")) {
      image.setAttribute("decoding", "async");
    }

    if (image.classList.contains("brand-logo")) {
      image.setAttribute("fetchpriority", "high");
      return;
    }

    const rect = image.getBoundingClientRect();
    const aboveFold = rect.top < window.innerHeight * 1.25;

    if (!image.hasAttribute("loading")) {
      image.setAttribute("loading", aboveFold ? "eager" : "lazy");
    }

    if (!image.hasAttribute("fetchpriority")) {
      image.setAttribute("fetchpriority", aboveFold ? "high" : "low");
    }
  });
})();

(function bulletHighlightOnView() {
  const bullets = document.querySelectorAll(".bullet-list li, .bullet-list-light li");
  if (!bullets.length || !("IntersectionObserver" in window)) return;

  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        entry.target.classList.toggle("is-bullet-highlighted", entry.isIntersecting && entry.intersectionRatio > 0.6);
      });
    },
    {
      threshold: [0.6],
      rootMargin: "0px 0px -8% 0px",
    }
  );

  bullets.forEach((bullet) => observer.observe(bullet));
})();

(function moleculeBackground() {
  const canvas = document.getElementById("moleculeBg");
  if (!canvas) return;

  const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
  const ctx = canvas.getContext("2d");
  if (!ctx) return;

  let animationFrame = 0;
  let waterMolecules = [];
  let diamondClusters = [];
  let width = 0;
  let height = 0;
  let dpr = 1;

  function randomBetween(min, max) {
    return min + Math.random() * (max - min);
  }

  function createWaterMolecule() {
    const scale = randomBetween(0.95, 1.4);
    const bond = randomBetween(20, 30) * scale;
    const angle = randomBetween(0, Math.PI * 2);

    return {
      x: randomBetween(0, width),
      y: randomBetween(0, height),
      vx: randomBetween(-0.11, 0.11),
      vy: randomBetween(-0.08, 0.08),
      rotation: angle,
      rotationSpeed: randomBetween(-0.0022, 0.0022),
      bond,
      oxygenRadius: 6.4 * scale,
      hydrogenRadius: 3.6 * scale,
      alpha: randomBetween(0.24, 0.42),
    };
  }

  function createDiamondCluster() {
    return {
      x: randomBetween(0, width),
      y: randomBetween(0, height),
      vx: randomBetween(-0.18, 0.18),
      vy: randomBetween(-0.12, 0.12),
      swayPhase: randomBetween(0, Math.PI * 2),
      swaySpeed: randomBetween(0.018, 0.032),
      bobPhase: randomBetween(0, Math.PI * 2),
      bobSpeed: randomBetween(0.02, 0.034),
      scale: randomBetween(0.62, 0.9),
      alpha: randomBetween(0.22, 0.36),
      // Fixed projected cluster that follows the reference silhouette:
      // 6 lower points, 3 above, 3 above, then a vertical 1 and 1.
      nodes: [
        { x: 0, y: -108, z: 0, r: 4.4 },
        { x: 0, y: -82, z: 0, r: 4.8 },
        { x: -30, y: -52, z: -10, r: 4.5 },
        { x: 0, y: -52, z: 0, r: 4.8 },
        { x: 30, y: -52, z: 10, r: 4.5 },
        { x: -42, y: -16, z: 10, r: 4.6 },
        { x: 0, y: -16, z: 0, r: 5 },
        { x: 42, y: -16, z: -10, r: 4.6 },
        { x: -78, y: 30, z: 14, r: 4.3 },
        { x: -46, y: 30, z: -2, r: 4.2 },
        { x: -14, y: 30, z: 10, r: 4.2 },
        { x: 18, y: 30, z: -10, r: 4.2 },
        { x: 50, y: 30, z: 2, r: 4.2 },
        { x: 82, y: 30, z: -14, r: 4.3 },
      ],
      edges: [
        [0, 1],
        [1, 2], [1, 3], [1, 4],
        [2, 5], [2, 6],
        [3, 5], [3, 6], [3, 7],
        [4, 6], [4, 7],
        [5, 8], [5, 9], [5, 10],
        [6, 9], [6, 10], [6, 11], [6, 12],
        [7, 11], [7, 12], [7, 13],
      ],
    };
  }

  function createDiamondClusters(count) {
    const clusters = [];
    const attempts = count * 30;
    const marginX = Math.max(140, width * 0.12);
    const marginY = Math.max(120, height * 0.14);
    const minSpacing = width < 720 ? 180 : width < 1080 ? 230 : 280;

    for (let i = 0; i < attempts && clusters.length < count; i += 1) {
      const cluster = createDiamondCluster();
      cluster.x = randomBetween(marginX, Math.max(marginX + 1, width - marginX));
      cluster.y = randomBetween(marginY, Math.max(marginY + 1, height - marginY));

      const tooClose = clusters.some((other) => Math.hypot(cluster.x - other.x, cluster.y - other.y) < minSpacing);
      if (!tooClose) clusters.push(cluster);
    }

    while (clusters.length < count) {
      const cluster = createDiamondCluster();
      const slot = clusters.length + 1;
      cluster.x = (width / (count + 1)) * slot;
      cluster.y = height * (0.2 + ((slot % 3) * 0.18));
      clusters.push(cluster);
    }

    return clusters;
  }

  function resize() {
    dpr = Math.min(window.devicePixelRatio || 1, 1.5);
    width = window.innerWidth;
    height = window.innerHeight;
    canvas.width = Math.round(width * dpr);
    canvas.height = Math.round(height * dpr);
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

    const waterCount = width < 720 ? 10 : width < 1080 ? 16 : 22;
    const diamondCount = width < 720 ? 2 : width < 1080 ? 3 : 4;

    waterMolecules = Array.from({ length: waterCount }, createWaterMolecule);
    diamondClusters = createDiamondClusters(diamondCount);
  }

  function wrap(item, margin) {
    if (item.x < -margin) item.x = width + margin;
    if (item.x > width + margin) item.x = -margin;
    if (item.y < -margin) item.y = height + margin;
    if (item.y > height + margin) item.y = -margin;
  }

  function drawWaterMolecule(molecule) {
    const h1x = molecule.x + Math.cos(molecule.rotation - 0.92) * molecule.bond;
    const h1y = molecule.y + Math.sin(molecule.rotation - 0.92) * molecule.bond;
    const h2x = molecule.x + Math.cos(molecule.rotation + 0.92) * molecule.bond;
    const h2y = molecule.y + Math.sin(molecule.rotation + 0.92) * molecule.bond;

    ctx.lineWidth = 1.5;
    ctx.strokeStyle = `rgba(130, 214, 255, ${Math.min(molecule.alpha + 0.08, 0.52)})`;
    ctx.beginPath();
    ctx.moveTo(molecule.x, molecule.y);
    ctx.lineTo(h1x, h1y);
    ctx.moveTo(molecule.x, molecule.y);
    ctx.lineTo(h2x, h2y);
    ctx.stroke();

    ctx.shadowBlur = 18;
    ctx.shadowColor = `rgba(47, 153, 221, ${molecule.alpha * 0.66})`;
    ctx.fillStyle = `rgba(47, 153, 221, ${Math.min(molecule.alpha + 0.16, 0.68)})`;
    ctx.beginPath();
    ctx.arc(molecule.x, molecule.y, molecule.oxygenRadius, 0, Math.PI * 2);
    ctx.fill();

    ctx.shadowBlur = 12;
    ctx.shadowColor = `rgba(227, 180, 93, ${molecule.alpha * 0.42})`;
    ctx.fillStyle = `rgba(227, 180, 93, ${Math.min(molecule.alpha + 0.08, 0.48)})`;
    ctx.beginPath();
    ctx.arc(h1x, h1y, molecule.hydrogenRadius, 0, Math.PI * 2);
    ctx.arc(h2x, h2y, molecule.hydrogenRadius, 0, Math.PI * 2);
    ctx.fill();

    ctx.shadowBlur = 0;
    ctx.strokeStyle = `rgba(255, 255, 255, ${molecule.alpha * 0.24})`;
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.arc(molecule.x, molecule.y, molecule.bond * 1.45, 0, Math.PI * 2);
    ctx.stroke();
  }

  function projectDiamondNode(cluster, node) {
    const tilt = Math.sin(cluster.swayPhase) * 0.32;
    const bob = Math.sin(cluster.bobPhase) * 7;
    const parallaxX = node.x + node.z * tilt;
    const parallaxY = node.y - node.z * 0.22;
    const depthScale = 1 + node.z / 220;

    return {
      x: cluster.x + parallaxX * cluster.scale,
      y: cluster.y + bob + parallaxY * cluster.scale,
      radius: Math.max(2.2, node.r * cluster.scale * depthScale),
      edgeAlpha: cluster.alpha * (0.75 + depthScale * 0.22),
    };
  }

  function drawDiamondBond(start, end, alpha) {
    const gradient = ctx.createLinearGradient(start.x, start.y, end.x, end.y);
    gradient.addColorStop(0, `rgba(244, 250, 255, ${Math.min(alpha + 0.12, 0.7)})`);
    gradient.addColorStop(0.45, `rgba(190, 207, 222, ${Math.min(alpha + 0.06, 0.54)})`);
    gradient.addColorStop(0.55, `rgba(118, 143, 164, ${Math.max(alpha - 0.06, 0.16)})`);
    gradient.addColorStop(1, `rgba(230, 242, 252, ${Math.min(alpha + 0.04, 0.58)})`);

    ctx.lineCap = "round";
    ctx.lineWidth = 3.2;
    ctx.strokeStyle = gradient;
    ctx.shadowBlur = 10;
    ctx.shadowColor = `rgba(130, 214, 255, ${alpha * 0.36})`;
    ctx.beginPath();
    ctx.moveTo(start.x, start.y);
    ctx.lineTo(end.x, end.y);
    ctx.stroke();

    ctx.lineWidth = 1.1;
    ctx.strokeStyle = `rgba(255, 255, 255, ${Math.min(alpha + 0.1, 0.42)})`;
    ctx.shadowBlur = 0;
    ctx.beginPath();
    ctx.moveTo(start.x, start.y);
    ctx.lineTo(end.x, end.y);
    ctx.stroke();
  }

  function drawDiamondNode(node, alpha) {
    const sphere = ctx.createRadialGradient(
      node.x - node.radius * 0.38,
      node.y - node.radius * 0.42,
      node.radius * 0.15,
      node.x,
      node.y,
      node.radius
    );
    sphere.addColorStop(0, `rgba(255, 255, 255, ${Math.min(alpha + 0.32, 0.92)})`);
    sphere.addColorStop(0.28, `rgba(232, 243, 252, ${Math.min(alpha + 0.22, 0.84)})`);
    sphere.addColorStop(0.62, `rgba(164, 183, 201, ${Math.min(alpha + 0.08, 0.58)})`);
    sphere.addColorStop(1, `rgba(96, 120, 144, ${Math.max(alpha - 0.02, 0.2)})`);

    ctx.shadowBlur = 18;
    ctx.shadowColor = `rgba(130, 214, 255, ${alpha * 0.42})`;
    ctx.fillStyle = sphere;
    ctx.beginPath();
    ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
    ctx.fill();

    ctx.shadowBlur = 0;
    ctx.fillStyle = `rgba(255, 255, 255, ${Math.min(alpha + 0.16, 0.72)})`;
    ctx.beginPath();
    ctx.arc(node.x - node.radius * 0.34, node.y - node.radius * 0.36, node.radius * 0.2, 0, Math.PI * 2);
    ctx.fill();

    ctx.strokeStyle = `rgba(55, 77, 96, ${Math.max(alpha - 0.04, 0.16)})`;
    ctx.lineWidth = 0.9;
    ctx.beginPath();
    ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
    ctx.stroke();
  }

  function drawDiamondCluster(cluster) {
    const projected = cluster.nodes.map((node) => projectDiamondNode(cluster, node));

    cluster.edges.forEach(([from, to]) => {
      const start = projected[from];
      const end = projected[to];
      const edgeAlpha = Math.min(start.edgeAlpha, end.edgeAlpha);
      drawDiamondBond(start, end, edgeAlpha);
    });

    projected.forEach((node) => {
      drawDiamondNode(node, cluster.alpha);
    });
  }

  function maintainDiamondSpacing() {
    if (diamondClusters.length < 2) return;

    const minSpacing = width < 720 ? 170 : width < 1080 ? 215 : 250;
    const pushStrength = 0.0028;

    for (let i = 0; i < diamondClusters.length; i += 1) {
      const a = diamondClusters[i];

      for (let j = i + 1; j < diamondClusters.length; j += 1) {
        const b = diamondClusters[j];
        const dx = b.x - a.x;
        const dy = b.y - a.y;
        const distance = Math.hypot(dx, dy) || 0.001;

        if (distance >= minSpacing) continue;

        const overlap = (minSpacing - distance) / minSpacing;
        const offsetX = (dx / distance) * overlap;
        const offsetY = (dy / distance) * overlap;

        a.vx -= offsetX * pushStrength * 22;
        a.vy -= offsetY * pushStrength * 18;
        b.vx += offsetX * pushStrength * 22;
        b.vy += offsetY * pushStrength * 18;
      }
    }

    diamondClusters.forEach((cluster) => {
      cluster.vx *= 0.992;
      cluster.vy *= 0.992;
      cluster.vx = Math.max(-0.24, Math.min(0.24, cluster.vx));
      cluster.vy = Math.max(-0.16, Math.min(0.16, cluster.vy));
    });
  }

  function drawConnections() {
    for (let i = 0; i < waterMolecules.length; i += 1) {
      const a = waterMolecules[i];
      for (let j = i + 1; j < waterMolecules.length; j += 1) {
        const b = waterMolecules[j];
        const dx = a.x - b.x;
        const dy = a.y - b.y;
        const distance = Math.hypot(dx, dy);
        if (distance > 180) continue;

        const alpha = (1 - distance / 180) * 0.12;
        ctx.strokeStyle = `rgba(130, 214, 255, ${alpha})`;
        ctx.lineWidth = 0.8;
        ctx.beginPath();
        ctx.moveTo(a.x, a.y);
        ctx.lineTo(b.x, b.y);
        ctx.stroke();
      }
    }
  }

  function tick() {
    ctx.clearRect(0, 0, width, height);

    maintainDiamondSpacing();

    diamondClusters.forEach((cluster) => {
      cluster.x += cluster.vx;
      cluster.y += cluster.vy;
      cluster.swayPhase += cluster.swaySpeed;
      cluster.bobPhase += cluster.bobSpeed;
      wrap(cluster, 120 * cluster.scale);
      drawDiamondCluster(cluster);
    });

    drawConnections();

    waterMolecules.forEach((molecule) => {
      molecule.x += molecule.vx;
      molecule.y += molecule.vy;
      molecule.rotation += molecule.rotationSpeed;
      wrap(molecule, molecule.bond * 2.6);
      drawWaterMolecule(molecule);
    });

    animationFrame = window.requestAnimationFrame(tick);
  }

  function stop() {
    if (animationFrame) {
      window.cancelAnimationFrame(animationFrame);
      animationFrame = 0;
    }
    ctx.clearRect(0, 0, width, height);
  }

  function start() {
    stop();
    resize();
    if (reducedMotion.matches) return;
    tick();
  }

  start();
  window.addEventListener("resize", start);

  if (typeof reducedMotion.addEventListener === "function") {
    reducedMotion.addEventListener("change", start);
  } else if (typeof reducedMotion.addListener === "function") {
    reducedMotion.addListener(start);
  }

  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") {
      start();
    } else {
      stop();
    }
  });
})();
