<!doctype html>
<html class="sl-theme-dark">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta content="Comet" property="og:title" />
    <meta
      content="Stremio's fastest torrent/debrid search add-on."
      property="og:description"
    />
    <meta content="https://comet.feels.legal" property="og:url" />
    <meta
      content="https://raw.githubusercontent.com/g0ldyy/comet/refs/heads/main/comet/assets/icon.png"
      property="og:image"
    />
    <meta content="#6b6ef8" data-react-helmet="true" name="theme-color" />

    <title>Comet - Stremio's fastest torrent/debrid search add-on.</title>
    <link
      id="favicon"
      rel="icon"
      type="image/x-icon"
      href="https://raw.githubusercontent.com/g0ldyy/comet/refs/heads/main/comet/assets/icon.png"
    />

    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/dark.css"
    />
    <script
      type="module"
      src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/shoelace-autoloader.js"
    ></script>

    <style>
      :not(:defined) {
        visibility: hidden;
      }

      body {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
        margin: 0;
        background: radial-gradient(
          ellipse at bottom,
          #25292c 0%,
          #0c0d13 100%
        );
        font-family:
          system-ui,
          -apple-system,
          "Segoe UI",
          Roboto,
          "Helvetica Neue",
          "Noto Sans",
          "Liberation Sans",
          Arial,
          sans-serif,
          "Apple Color Emoji",
          "Segoe UI Emoji",
          "Segoe UI Symbol",
          "Noto Color Emoji";
        font-size: 1rem;
        font-weight: 400;
      }

      ::-webkit-scrollbar {
        overflow: hidden;
      }

      .header {
        text-align: center;
        width: 40%;
        margin-bottom: 20px;
        margin-top: 50px;
      }

      .comet-text {
        font-size: calc(1.375rem + 1.5vw);
        font-weight: 500;
        margin-bottom: 0;
      }

      .emoji {
        width: 1em;
        height: 1em;
        vertical-align: middle;
      }

      .form-container {
        background-color: #1a1d20;
        padding: 2rem;
        border-radius: 0.375rem;
        box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
        width: 80vw;
        max-width: 950px;
        margin-bottom: 50px;
      }

      .form-item {
        margin-bottom: 0.75rem;
      }

      sl-details {
        margin-bottom: 0.75rem;
      }

      .centered-item {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-wrap: wrap;
        gap: 10px;
      }

      .stars {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 120%;
        transform: rotate(-45deg);
        z-index: -1;
      }

      .star {
        --star-color: var(--primary-color);
        --star-tail-length: 6em;
        --star-tail-height: 2px;
        --star-width: calc(var(--star-tail-length) / 6);
        --fall-duration: 9s;
        --tail-fade-duration: var(--fall-duration);
        position: absolute;
        top: var(--top-offset);
        left: 0;
        width: var(--star-tail-length);
        height: var(--star-tail-height);
        color: var(--star-color);
        background: linear-gradient(45deg, currentColor, transparent);
        border-radius: 50%;
        filter: drop-shadow(0 0 6px currentColor);
        transform: translate3d(104em, 0, 0);
        animation:
          fall var(--fall-duration) var(--fall-delay) linear infinite,
          tail-fade var(--tail-fade-duration) var(--fall-delay) ease-out
            infinite;
      }

      @media screen and (max-width: 750px) {
        .star {
          animation: fall var(--fall-duration) var(--fall-delay) linear infinite;
        }
      }

      .star::before,
      .star::after {
        position: absolute;
        content: "";
        top: 0;
        left: calc(var(--star-width) / -2);
        width: var(--star-width);
        height: 100%;
        background: linear-gradient(
          45deg,
          transparent,
          currentColor,
          transparent
        );
        border-radius: inherit;
        animation: blink 2s linear infinite;
      }

      .star::before {
        transform: rotate(45deg);
      }

      .star::after {
        transform: rotate(-45deg);
      }

      @keyframes fall {
        to {
          transform: translate3d(-30em, 0, 0);
        }
      }

      @keyframes tail-fade {
        0%,
        50% {
          width: var(--star-tail-length);
          opacity: 1;
        }

        70%,
        80% {
          width: 0;
          opacity: 0.4;
        }

        100% {
          width: 0;
          opacity: 0;
        }
      }

      @keyframes blink {
        50% {
          opacity: 0.6;
        }
      }

      /* Custom Styles */
      .form-item label {
        display: flex;
        align-items: center;
        margin-bottom: 8px;
        font-weight: 500;
      }

      #apiKeyLink,
      #referralLink {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: rgba(255, 255, 255, 0.1);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
        color: white;
        padding: 4px 10px;
        border-radius: 12px;
        text-decoration: none;
        font-size: 0.7rem;
        font-weight: 600;
        margin-left: 8px;
        border: 1px solid rgba(255, 255, 255, 0.25);
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        transition: all 0.3s ease;
        line-height: normal;
        height: auto;
      }

      #apiKeyLink:hover,
      #referralLink:hover {
        background: rgba(255, 255, 255, 0.2);
        border-color: rgba(255, 255, 255, 0.4);
        transform: translateY(-1px);
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
      }

      #apiKeyLink:empty,
      #referralLink:empty {
        display: none;
      }

      .discord-btn::part(base) {
        background-color: #5865f2;
        border-color: #5865f2;
        color: white;
        font-weight: 600;
        display: flex;
        align-items: center;
      }

      .discord-btn::part(base):hover {
        background-color: #4752c4;
        border-color: #4752c4;
      }

      .heart-button {
        position: fixed;
        top: 20px;
        right: 20px;
        z-index: 1000;
        background: rgba(255, 255, 255, 0.1);
        backdrop-filter: blur(10px);
        border: 1px solid rgba(255, 255, 255, 0.2);
        border-radius: 50%;
        width: 45px;
        height: 45px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.3s ease;
        padding: 0;
      }

      .heart-button:hover {
        background: rgba(255, 255, 255, 0.2);
        transform: scale(1.1);
      }

      .heart-button sl-icon {
        color: #ff4757;
        font-size: 1.4rem;
        display: flex;
      }

      @keyframes heartbeat {
        0% {
          transform: scale(1);
        }

        14% {
          transform: scale(1.1);
        }

        28% {
          transform: scale(1);
        }

        42% {
          transform: scale(1.1);
        }

        70% {
          transform: scale(1);
        }
      }
    </style>
  </head>

  <body>
    <div class="stars"></div>

    <script>
      let hasTouchScreen = false;
      if ("maxTouchPoints" in navigator) {
        hasTouchScreen = navigator.maxTouchPoints > 0;
      } else if ("msMaxTouchPoints" in navigator) {
        hasTouchScreen = navigator.msMaxTouchPoints > 0;
      } else {
        const mQ = matchMedia?.("(pointer:coarse)");
        if (mQ?.media === "(pointer:coarse)") {
          hasTouchScreen = !!mQ.matches;
        } else if ("orientation" in window) {
          hasTouchScreen = true;
        } else {
          const UA = navigator.userAgent;
          hasTouchScreen =
            /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(UA) ||
            /\b(Android|Windows Phone|iPad|iPod)\b/i.test(UA);
        }
      }

      if (!hasTouchScreen) {
        document.addEventListener("DOMContentLoaded", function () {
          const starsContainer = document.querySelector(".stars");
          const starCount = 30;

          for (let i = 0; i < starCount; i++) {
            const star = document.createElement("div");
            star.classList.add("star");

            const randomTopOffset = Math.random() * 100;
            const randomLeftOffset = 80 + Math.random() * 40;
            const randomTailLength = 5 + Math.random() * 2.5;
            const randomFallDuration = 6 + Math.random() * 6;

            star.style.setProperty("--top-offset", `${randomTopOffset}vh`);
            star.style.setProperty(
              "--star-tail-length",
              `${randomTailLength}em`,
            );
            star.style.setProperty("--fall-duration", `${randomFallDuration}s`);
            star.style.setProperty("--fall-delay", "0s");
            star.style.transform = `translate3d(${randomLeftOffset}em, 0, 0)`;

            starsContainer.appendChild(star);
          }
        });
      }
    </script>
    <div class="header">
      <div
        style="
          display: flex;
          align-items: center;
          justify-content: center;
          gap: 15px;
          margin-bottom: 10px;
          height: 50px;
        "
      >
        <p
          class="comet-text"
          style="margin: 0; display: flex; align-items: center; line-height: 1"
        >
          <img
            class="emoji"
            src="https://fonts.gstatic.com/s/e/notoemoji/latest/1f4ab/512.gif"
            style="margin-right: 10px"
          />
          Comet
        </p>
        <sl-button
          href="https://discord.com/invite/UJEqpT42nb"
          target="_blank"
          size="small"
          pill
          class="discord-btn"
          style="display: flex; align-items: center"
        >
          <sl-icon
            slot="prefix"
            name="discord"
            style="font-size: 1rem"
          ></sl-icon>
          Discord
        </sl-button>
      </div>
      
    </div>

    <div class="form-container">
      <div class="form-item">
        <sl-select
          id="resolutions"
          multiple
          clearable
          label="Resolutions"
          placeholder="Select resolutions"
        >
          <sl-option value="r2160p">4K UHD - 2160p</sl-option>
          <sl-option value="r1440p">QHD - 1440p</sl-option>
          <sl-option value="r1080p">FHD - 1080p</sl-option>
          <sl-option value="r720p">HD - 720p</sl-option>
          <sl-option value="r576p">SD - 576p</sl-option>
          <sl-option value="r480p">SD - 480p</sl-option>
          <sl-option value="r360p">LD - 360p</sl-option>
          <sl-option value="r240p">LD - 240p</sl-option>
          <sl-option value="unknown">Unknown</sl-option>
        </sl-select>
      </div>

      <div class="form-item">
        <sl-input
          id="maxResultsPerResolution"
          type="number"
          min="0"
          value="0"
          label="Max Results Per Resolution"
          placeholder="Enter max results per resolution"
        ></sl-input>
      </div>

      <div class="form-item">
        <sl-input
          id="maxSize"
          type="number"
          min="0"
          value="0"
          label="Max Size (GB)"
          placeholder="Enter max size in gigabytes"
        ></sl-input>
      </div>

      <div
        class="form-item"
        
      >
        <sl-input
          id="debridStreamProxyPassword"
          label="Debrid Stream Proxy Password"
          placeholder="Enter password"
          help-text="Debrid Stream Proxying allows you to use your Debrid Service from multiple IPs at same time!"
        ></sl-input>
      </div>

      <sl-details id="debridServicesDetails" summary="Debrid Services" open>
        <div id="debridServicesContainer"></div>

        <sl-button
          id="addDebridService"
          variant="default"
          size="small"
          style="margin-bottom: 1rem"
        >
          <sl-icon slot="prefix" name="plus-circle"></sl-icon>
          Add Debrid Service
        </sl-button>

        <sl-divider></sl-divider>

        
        <sl-checkbox
          id="enableTorrent"
          checked
          help-text="Enable direct torrent/magnet links alongside debrid services."
          >Enable Torrent Mode</sl-checkbox
        >
        

        <sl-checkbox
          id="deduplicateStreams"
          help-text="When enabled, shows only one result per torrent (from the first service that has it cached). When disabled, shows results from all services."
          >Deduplicate Streams</sl-checkbox
        >

        <sl-checkbox
          id="scrapeDebridAccountTorrents"
          help-text="Scrape torrents directly from your debrid account library."
          >Scrape Debrid Account Torrents</sl-checkbox
        >
      </sl-details>

      <style>
        .debrid-service-entry {
          display: grid;
          grid-template-columns: 1fr 2fr auto;
          gap: 0.75rem;
          align-items: center;
          padding: 0.75rem;
          background: rgba(255, 255, 255, 0.03);
          border-radius: 0.5rem;
          margin-bottom: 0.5rem;
          border: 1px solid rgba(255, 255, 255, 0.1);
          transition: border-color 0.2s ease;
        }

        .debrid-service-entry:hover {
          border-color: rgba(255, 255, 255, 0.2);
        }

        .debrid-service-entry.dragging {
          opacity: 0.5;
          border-color: var(--sl-color-primary-600);
        }

        .debrid-service-entry .service-links {
          display: flex;
          gap: 0.5rem;
          margin-top: 0.25rem;
        }

        .debrid-service-entry .service-link {
          font-size: 0.7rem;
          color: var(--sl-color-primary-600);
          text-decoration: none;
        }

        .debrid-service-entry .service-link:hover {
          text-decoration: underline;
        }

        .debrid-service-entry .api-key-wrapper {
          display: flex;
          flex-direction: column;
        }

        .debrid-service-entry .remove-btn {
          color: var(--sl-color-danger-600);
        }

        .debrid-service-entry .drag-handle {
          cursor: grab;
          color: var(--sl-color-neutral-400);
          margin-right: 0.5rem;
        }

        .debrid-service-entry .service-header {
          display: flex;
          align-items: center;
        }

        @media (max-width: 600px) {
          .debrid-service-entry {
            grid-template-columns: 1fr;
          }
        }
      </style>

      <script>
        const DEBRID_SERVICES = {
          realdebrid: {
            name: "Real-Debrid",
            apiKeyUrl: "https://real-debrid.com/apitoken",
            referralUrl: "http://real-debrid.com/?id=16161532",
            helpText: "Format: `api-key`"
          },
          torbox: {
            name: "TorBox",
            apiKeyUrl: "https://torbox.app/settings",
            referralUrl: "https://torbox.app/subscription?referral=1ffb2238-1c5f-402e-a2ce-3d7a86c52d02",
            helpText: "Format: `api-key`"
          },
          alldebrid: {
            name: "All-Debrid",
            apiKeyUrl: "https://alldebrid.com/apikeys",
            referralUrl: null,
            helpText: "Format: `api-key`"
          },
          debridlink: {
            name: "Debrid-Link",
            apiKeyUrl: "https://debrid-link.com/webapp/apikey",
            referralUrl: "https://debrid-link.fr/id/G7mli",
            helpText: "Format: `api-key`"
          },
          premiumize: {
            name: "Premiumize",
            apiKeyUrl: "https://premiumize.me/account",
            referralUrl: null,
            helpText: "Format: `api-key`"
          },
          debrider: {
            name: "Debrider",
            apiKeyUrl: "https://debrider.app/dashboard/account",
            referralUrl: null,
            helpText: "Format: `api-key`"
          },
          easydebrid: {
            name: "EasyDebrid",
            apiKeyUrl: "https://paradise-cloud.com/products/easydebrid",
            referralUrl: null,
            helpText: "Format: `api-key`"
          },
          offcloud: {
            name: "Offcloud",
            apiKeyUrl: "https://offcloud.com",
            referralUrl: null,
            helpText: "Format: `email:password`"
          },
          pikpak: {
            name: "PikPak",
            apiKeyUrl: "https://mypikpak.com",
            referralUrl: null,
            helpText: "Format: `email:password`"
          }
        };

        const torrentDisabled = false;
        window.disableTorrentStreams = torrentDisabled;

        let debridServiceCounter = 0;
        let torrentModeAutoDisabled = false;

        function maybeAutoDisableTorrentModeOnFirstDebridService() {
          if (torrentModeAutoDisabled) {
            return;
          }

          const enableTorrentEl = document.getElementById("enableTorrent");
          if (!enableTorrentEl) {
            torrentModeAutoDisabled = true;
            return;
          }

          if (enableTorrentEl.checked) {
            enableTorrentEl.checked = false;
          }

          torrentModeAutoDisabled = true;
        }

        function createDebridServiceEntry(service = "", apiKey = "", applyAutoDisable = true) {
          const container = document.getElementById("debridServicesContainer");
          const hadNoEntries = container.querySelectorAll(".debrid-service-entry").length === 0;
          const entryId = debridServiceCounter++;

          const entry = document.createElement("div");
          entry.className = "debrid-service-entry";
          entry.dataset.entryId = entryId;
          entry.draggable = true;

          // Build service options
          let serviceOptions = Object.entries(DEBRID_SERVICES).map(([key, info]) =>
            `<sl-option value="${key}">${info.name}</sl-option>`
          ).join("");

          entry.innerHTML = `
            <div class="service-header">
              <sl-icon class="drag-handle" name="grip-vertical"></sl-icon>
              <sl-select
                class="debrid-service-select"
                value="${service}"
                placeholder="Select service"
                size="small"
                hoist
              >
                ${serviceOptions}
              </sl-select>
            </div>
            <div class="api-key-wrapper">
              <sl-input
                class="debrid-api-key"
                value="${apiKey}"
                placeholder="Enter API key"
                size="small"
                type="password"
                password-toggle
              ></sl-input>
              <div class="service-links"></div>
            </div>
            <sl-icon-button class="remove-btn" name="trash" label="Remove"></sl-icon-button>
          `;

          // Add event listeners
          const select = entry.querySelector(".debrid-service-select");
          const apiKeyInput = entry.querySelector(".debrid-api-key");
          const linksContainer = entry.querySelector(".service-links");
          const removeBtn = entry.querySelector(".remove-btn");

          select.addEventListener("sl-change", () => {
            updateServiceLinks(select.value, linksContainer, apiKeyInput);
          });

          removeBtn.addEventListener("click", () => {
            entry.remove();
          });

          // Drag and drop
          entry.addEventListener("dragstart", (e) => {
            entry.classList.add("dragging");
            e.dataTransfer.effectAllowed = "move";
          });

          entry.addEventListener("dragend", () => {
            entry.classList.remove("dragging");
          });

          entry.addEventListener("dragover", (e) => {
            e.preventDefault();
            const dragging = container.querySelector(".dragging");
            if (dragging && dragging !== entry) {
              const rect = entry.getBoundingClientRect();
              const midY = rect.top + rect.height / 2;
              if (e.clientY < midY) {
                container.insertBefore(dragging, entry);
              } else {
                container.insertBefore(dragging, entry.nextSibling);
              }
            }
          });

          container.appendChild(entry);

          if (applyAutoDisable && hadNoEntries) {
            maybeAutoDisableTorrentModeOnFirstDebridService();
          }

          // Initialize links if service is pre-selected
          if (service) {
            updateServiceLinks(service, linksContainer, apiKeyInput);
          }

          return entry;
        }

        function updateServiceLinks(service, linksContainer, apiKeyInput) {
          const info = DEBRID_SERVICES[service];
          linksContainer.innerHTML = "";

          if (info) {
            apiKeyInput.helpText = info.helpText;

            if (info.referralUrl) {
              const referralLink = document.createElement("a");
              referralLink.className = "service-link";
              referralLink.href = info.referralUrl;
              referralLink.target = "_blank";
              referralLink.textContent = "Sign up";
              linksContainer.appendChild(referralLink);
            }

            if (info.apiKeyUrl) {
              const apiLink = document.createElement("a");
              apiLink.className = "service-link";
              apiLink.href = info.apiKeyUrl;
              apiLink.target = "_blank";
              apiLink.textContent = "Get API key";
              linksContainer.appendChild(apiLink);
            }
          }
        }

        function getDebridServices() {
          const container = document.getElementById("debridServicesContainer");
          const entries = container.querySelectorAll(".debrid-service-entry");
          const services = [];

          entries.forEach(entry => {
            const service = entry.querySelector(".debrid-service-select").value;
            const apiKey = entry.querySelector(".debrid-api-key").value;

            if (service && apiKey) {
              services.push({ service, apiKey });
            }
          });

          return services;
        }

        function populateDebridServices(services) {
          const container = document.getElementById("debridServicesContainer");
          container.innerHTML = "";
          debridServiceCounter = 0;
          torrentModeAutoDisabled = Boolean(services && services.length > 0);

          if (services && services.length > 0) {
            services.forEach(entry => {
              createDebridServiceEntry(entry.service, entry.apiKey, false);
            });
          }
        }

        // Initialize add button
        const addBtn = document.getElementById("addDebridService");
        addBtn.addEventListener("click", () => {
          createDebridServiceEntry();
        });
      </script>

      <sl-details summary="Language Settings">
        <div class="form-item">
          <sl-select
            id="languages_required"
            multiple
            clearable
            label="Required Languages"
            placeholder="Select required languages"
            help-text="Torrents MUST contain at least one of these languages."
          ></sl-select>
        </div>

        <div class="form-item">
          <sl-select
            id="languages_allowed"
            multiple
            clearable
            label="Allowed Languages"
            placeholder="Select allowed languages"
            help-text="Torrents containing these languages will always be included, even if they contain excluded languages."
          ></sl-select>
        </div>

        <div class="form-item">
          <sl-select
            id="languages_excluded"
            multiple
            clearable
            label="Excluded Languages"
            placeholder="Select excluded languages"
            help-text="Torrents containing these languages will be excluded."
          ></sl-select>
        </div>

        <div class="form-item">
          <sl-select
            id="languages_preferred"
            multiple
            clearable
            label="Preferred Languages"
            placeholder="Select preferred languages"
            help-text="These languages will be prioritized in the results."
          ></sl-select>
        </div>

        <div class="form-item">
          <sl-checkbox
            id="allowEnglishInLanguages"
            help-text="Allows English language torrents to be included even if you excluded English from your language preferences."
            >Allow English in Languages</sl-checkbox
          >
          <sl-checkbox
            id="removeUnknownLanguages"
            help-text="Exclude torrents that don't have a language in the title."
            >Remove Unknown Languages</sl-checkbox
          >
        </div>
      </sl-details>

      <sl-details summary="Advanced Settings">
        <div class="form-item">
          <sl-input
            id="rankThreshold"
            type="number"
            value="-10000000000"
            label="Minimum Rank Threshold"
            placeholder="Enter minimum rank threshold"
            help-text="Torrents ranked below this value will be excluded from results."
          ></sl-input>
          <sl-checkbox
            id="cachedOnly"
            help-text="Show only content that has already been cached."
            >Show Cached Only</sl-checkbox
          >
          <sl-checkbox
            id="sortCachedUncachedTogether"
            help-text="Disable the default behavior of sorting cached results first, and instead mixes cached and uncached results together."
            >Sort Cached and Uncached Together</sl-checkbox
          >
          <sl-checkbox
            checked
            id="removeTrash"
            help-text="Remove all trash from results (if disabled, your filters will not be applied - Adult Content, CAM, Clean Audio, PDTV, R5, Screener, Size, Telecine and Telesync)"
            >Remove Trash</sl-checkbox
          >
          <sl-select
            id="resultFormat"
            multiple
            label="Result Format"
            placeholder="Select what to show in result title"
            hoist
            max-options-visible="10"
          >
          </sl-select>
          <div id="resultFormatPreview" style="
            margin-top: 0.6rem;
            padding: 0.65rem 0.85rem;
            background: rgba(0,0,0,0.35);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 0.4rem;
            font-family: monospace;
            font-size: 0.78rem;
            color: #c8ccd0;
            white-space: pre;
            line-height: 1.65;
          "></div>
        </div>
      </sl-details>

      <div class="centered-item">
        <sl-button id="install" variant="neutral">Install</sl-button>
        <sl-alert id="installAlert" variant="neutral" duration="3000" closable>
          <sl-icon slot="icon" name="clipboard2-check"></sl-icon>
          <strong>Attempting to add the add-on to Stremio...</strong>
        </sl-alert>

        <sl-button id="copy-link" variant="neutral">Copy Link</sl-button>
        <sl-alert id="copyAlert" variant="neutral" duration="3000" closable>
          <sl-icon slot="icon" name="clipboard2-check"></sl-icon>
          <strong
            >The Stremio add-on link has been automatically copied.</strong
          >
        </sl-alert>

        <sl-button id="setup-kodi" variant="neutral">Setup Kodi</sl-button>
        <sl-alert id="kodiAlert" variant="success" duration="3000" closable>
          <sl-icon slot="icon" name="check2-circle"></sl-icon>
          <strong id="kodiAlertText">Kodi setup completed successfully.</strong>
        </sl-alert>
        <sl-alert id="kodiErrorAlert" variant="danger" duration="4000" closable>
          <sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
          <strong id="kodiErrorAlertText">Failed to setup Kodi.</strong>
        </sl-alert>

        <script type="module">
          const languagesEmojis = {
            "multi": "🌎",
            "en": "🇬🇧",  // English
            "ja": "🇯🇵",  // Japanese
            "zh": "🇨🇳",  // Chinese
            "ru": "🇷🇺",  // Russian
            "ar": "🇸🇦",  // Arabic
            "pt": "🇵🇹",  // Portuguese
            "es": "🇪🇸",  // Spanish
            "fr": "🇫🇷",  // French
            "de": "🇩🇪",  // German
            "it": "🇮🇹",  // Italian
            "ko": "🇰🇷",  // Korean
            "hi": "🇮🇳",  // Hindi
            "bn": "🇧🇩",  // Bengali
            "pa": "🇵🇰",  // Punjabi
            "mr": "🇮🇳",  // Marathi
            "gu": "🇮🇳",  // Gujarati
            "ta": "🇮🇳",  // Tamil
            "te": "🇮🇳",  // Telugu
            "kn": "🇮🇳",  // Kannada
            "ml": "🇮🇳",  // Malayalam
            "th": "🇹🇭",  // Thai
            "vi": "🇻🇳",  // Vietnamese
            "id": "🇮🇩",  // Indonesian
            "tr": "🇹🇷",  // Turkish
            "he": "🇮🇱",  // Hebrew
            "fa": "🇮🇷",  // Persian
            "uk": "🇺🇦",  // Ukrainian
            "el": "🇬🇷",  // Greek
            "lt": "🇱🇹",  // Lithuanian
            "lv": "🇱🇻",  // Latvian
            "et": "🇪🇪",  // Estonian
            "pl": "🇵🇱",  // Polish
            "cs": "🇨🇿",  // Czech
            "sk": "🇸🇰",  // Slovak
            "hu": "🇭🇺",  // Hungarian
            "ro": "🇷🇴",  // Romanian
            "bg": "🇧🇬",  // Bulgarian
            "sr": "🇷🇸",  // Serbian
            "hr": "🇭🇷",  // Croatian
            "sl": "🇸🇮",  // Slovenian
            "nl": "🇳🇱",  // Dutch
            "da": "🇩🇰",  // Danish
            "fi": "🇫🇮",  // Finnish
            "sv": "🇸🇪",  // Swedish
            "no": "🇳🇴",  // Norwegian
            "ms": "🇲🇾",  // Malay
            "la": "💃🏻",  // Latino
          };
          let defaultResultFormat = [];
          const ALL_RESOLUTIONS = ["r2160p", "r1440p", "r1080p", "r720p", "r576p", "r480p", "r360p", "r240p", "unknown"];

          (async () => {
            await Promise.allSettled([
              customElements.whenDefined("sl-button"),
              customElements.whenDefined("sl-alert"),
              customElements.whenDefined("sl-select"),
              customElements.whenDefined("sl-input"),
              customElements.whenDefined("sl-option"),
              customElements.whenDefined("sl-icon"),
              customElements.whenDefined("sl-checkbox")
            ]);

            const webConfig = {"resolutions": [9, 7, 6, 5, 4, 3, 2, 1], "resultFormat": ["title", "video_info", "audio_info", "quality_info", "release_group", "seeders", "size", "tracker", "languages"]};


          const resolutionsSelect = document.getElementById("resolutions");
          resolutionsSelect.value = ALL_RESOLUTIONS;

          populateSelect("resultFormat", webConfig.resultFormat);
          defaultResultFormat = webConfig.resultFormat;
          const resultFormatSelect = document.getElementById("resultFormat");
          resultFormatSelect.value = defaultResultFormat;

          // Live preview for result format
          function updateResultFormatPreview() {
            const sel = document.getElementById("resultFormat");
            const raw = sel.value;
            const selected = Array.isArray(raw) ? raw : (raw ? [raw] : []);
            const hasAll = selected.includes("all");
            const S = {
              title:     "📄 Movie.Title.2024.1080p.BluRay.x264-GROUP",
              video:     "📹 H.264 • HDR • 10bit",
              audio:     "🔊 DDP5.1 • Atmos",
              quality:   "⭐ BluRay",
              group:     "🏷️ YTS",
              seeders:   "👤 1234",
              size:      "💾 12.5 GB",
              tracker:   "🔎 Yggrasil",
              languages: "🇬🇧/🇫🇷",
            };
            const c = {};
            if (hasAll || selected.includes("title"))          c.title     = S.title;
            if (hasAll || selected.includes("video_info"))      c.video     = S.video;
            if (hasAll || selected.includes("audio_info"))      c.audio     = S.audio;
            if (hasAll || selected.includes("quality_info"))    c.quality   = S.quality;
            if (hasAll || selected.includes("release_group"))   c.group     = S.group;
            if (hasAll || selected.includes("seeders"))         c.seeders   = S.seeders;
            if (hasAll || selected.includes("size"))            c.size      = S.size;
            if (hasAll || selected.includes("tracker"))         c.tracker   = S.tracker;
            if (hasAll || selected.includes("languages"))       c.languages = S.languages;
            const lines = [];
            if (c.title) lines.push(c.title);
            const va = [c.video, c.audio].filter(Boolean);
            if (va.length) lines.push(va.join(" | "));
            const qg = [c.quality, c.group].filter(Boolean);
            if (qg.length) lines.push(qg.join(" | "));
            const info = [c.seeders, c.size, c.tracker].filter(Boolean);
            if (info.length) lines.push(info.join(" "));
            if (c.languages) lines.push(c.languages);
            document.getElementById("resultFormatPreview").textContent =
              lines.length ? lines.join("\n") : "Empty result format configuration";
          }
          resultFormatSelect.addEventListener("sl-change", updateResultFormatPreview);
          updateResultFormatPreview();

          // try populate the form from previous settings
          try {
            const settings = getSettingsFromUrl();
            if (settings != null) { populateFormFromSettings(settings); }
          } catch (error) {
            console.log("Failed to retrieve or parse settings from URL:", error);
          }

          // Populate language selects
          populateSelect("languages_required", Object.keys(languagesEmojis));
          populateSelect("languages_allowed", Object.keys(languagesEmojis));
          populateSelect("languages_excluded", Object.keys(languagesEmojis));
          populateSelect("languages_preferred", Object.keys(languagesEmojis));

          document.body.classList.add("ready");
          })();

          function populateSelect(selectId, options) {
            const selectElement = document.getElementById(selectId);

            const languageNames = {
              "multi": "Multi",
              "en": "English",
              "ja": "Japanese",
              "zh": "Chinese",
              "ru": "Russian",
              "ar": "Arabic",
              "pt": "Portuguese",
              "es": "Spanish",
              "fr": "French",
              "de": "German",
              "it": "Italian",
              "ko": "Korean",
              "hi": "Hindi",
              "bn": "Bengali",
              "pa": "Punjabi",
              "mr": "Marathi",
              "gu": "Gujarati",
              "ta": "Tamil",
              "te": "Telugu",
              "kn": "Kannada",
              "ml": "Malayalam",
              "th": "Thai",
              "vi": "Vietnamese",
              "id": "Indonesian",
              "tr": "Turkish",
              "he": "Hebrew",
              "fa": "Persian",
              "uk": "Ukrainian",
              "el": "Greek",
              "lt": "Lithuanian",
              "lv": "Latvian",
              "et": "Estonian",
              "pl": "Polish",
              "cs": "Czech",
              "sk": "Slovak",
              "hu": "Hungarian",
              "ro": "Romanian",
              "bg": "Bulgarian",
              "sr": "Serbian",
              "hr": "Croatian",
              "sl": "Slovenian",
              "nl": "Dutch",
              "da": "Danish",
              "fi": "Finnish",
              "sv": "Swedish",
              "no": "Norwegian",
              "ms": "Malay",
              "la": "Latino"
            };

            options.forEach(option => {
              const optionElement = document.createElement("sl-option");
              optionElement.value = option;

              if (selectId.startsWith('languages')) {
                const flag = languagesEmojis[option] || '';
                const fullName = languageNames[option] || option;
                optionElement.textContent = `${flag} ${fullName}`;
              } else {
                optionElement.textContent = option;
              }

              selectElement.appendChild(optionElement);
            });
          }

          const installButton = document.querySelector("#install");
          const installAlert = document.querySelector('#installAlert');
          const copyLinkButton = document.querySelector("#copy-link");
          const copyAlert = document.querySelector('#copyAlert');
          const kodiSetupButton = document.querySelector("#setup-kodi");
          const kodiAlert = document.querySelector("#kodiAlert");
          const kodiAlertText = document.querySelector("#kodiAlertText");
          const stremioApiPrefix = "";

          function getSettings() {
            const languages_required = Array.from(document.getElementById("languages_required").selectedOptions).map(option => option.value);
            const languages_allowed = Array.from(document.getElementById("languages_allowed").selectedOptions).map(option => option.value);
            const languages_excluded = Array.from(document.getElementById("languages_excluded").selectedOptions).map(option => option.value);
            const languages_preferred = Array.from(document.getElementById("languages_preferred").selectedOptions).map(option => option.value);
            const selectedResolutions = Array.from(document.getElementById("resolutions").selectedOptions).map(option => option.value);
            const allResolutions = ALL_RESOLUTIONS;
            const resolutions = allResolutions.reduce((obj, res) => {
              // Only include resolutions that are NOT selected (disabled) as false
              if (!selectedResolutions.includes(res)) {
                obj[res] = false;
              }
              return obj;
            }, {});
            const rankThreshold = document.getElementById("rankThreshold").value;
            const maxResultsPerResolution = document.getElementById("maxResultsPerResolution").value;
            const maxSize = document.getElementById("maxSize").value;
            const cachedOnly = document.getElementById("cachedOnly").checked;
            const sortCachedUncachedTogether = document.getElementById("sortCachedUncachedTogether").checked;
            const removeTrash = document.getElementById("removeTrash").checked;
            const allowEnglishInLanguages = document.getElementById("allowEnglishInLanguages").checked;
            const removeUnknownLanguages = document.getElementById("removeUnknownLanguages").checked;
            const resultFormat = Array.from(document.getElementById("resultFormat").selectedOptions).map(option => option.value);
            const debridStreamProxyPassword = document.getElementById("debridStreamProxyPassword").value;

            const debridServices = getDebridServices();
            const enableTorrentEl = document.getElementById("enableTorrent");
            const enableTorrent = enableTorrentEl ? enableTorrentEl.checked : false;
            const deduplicateStreamsEl = document.getElementById("deduplicateStreams");
            const deduplicateStreams = deduplicateStreamsEl ? deduplicateStreamsEl.checked : false;
            const scrapeDebridAccountTorrentsEl = document.getElementById("scrapeDebridAccountTorrents");
            const scrapeDebridAccountTorrents = scrapeDebridAccountTorrentsEl ? scrapeDebridAccountTorrentsEl.checked : false;

            const selectedResultFormat = resultFormat.length === defaultResultFormat.length && resultFormat.every((val, index) => val === defaultResultFormat[index]) ? ["all"] : resultFormat;

            return {
              maxResultsPerResolution: parseInt(maxResultsPerResolution),
              maxSize: parseFloat(maxSize * 1073741824),
              cachedOnly: cachedOnly,
              sortCachedUncachedTogether: sortCachedUncachedTogether,
              removeTrash: removeTrash,
              resultFormat: selectedResultFormat,
              debridServices: debridServices,
              enableTorrent: enableTorrent,
              deduplicateStreams: deduplicateStreams,
              scrapeDebridAccountTorrents: scrapeDebridAccountTorrents,
              debridStreamProxyPassword: debridStreamProxyPassword,
              languages: {
                required: languages_required,
                allowed: languages_allowed,
                exclude: languages_excluded,
                preferred: languages_preferred
              },
              resolutions: resolutions,
              options: {
                remove_ranks_under: parseFloat(rankThreshold),
                allow_english_in_languages: allowEnglishInLanguages,
                remove_unknown_languages: removeUnknownLanguages
              }
            };
          }

          // Check if config matches all default values
          // If so, use /manifest.json instead of /{b64config}/manifest.json for better CDN caching
          function isDefaultConfig(settings) {
            // For default: no debrid services and torrent mode enabled
            if (settings.debridServices && settings.debridServices.length > 0) {
              return false;
            }

            // enableTorrent must be true for default (torrent-only mode)
            if (settings.enableTorrent !== true) {
              return false;
            }

            // Check all filtering fields match defaults
            // maxResultsPerResolution default is 0
            if (settings.maxResultsPerResolution !== 0) {
              return false;
            }

            // maxSize default is 0
            if (settings.maxSize !== 0) {
              return false;
            }

            // cachedOnly default is false
            if (settings.cachedOnly !== false) {
              return false;
            }

            // sortCachedUncachedTogether default is false
            if (settings.sortCachedUncachedTogether !== false) {
              return false;
            }

            // scrapeDebridAccountTorrents default is false
            if (settings.scrapeDebridAccountTorrents === true) {
              return false;
            }

            // removeTrash default is true
            if (settings.removeTrash !== true) {
              return false;
            }

            // debridStreamProxyPassword default is ""
            if (settings.debridStreamProxyPassword && settings.debridStreamProxyPassword !== "") {
              return false;
            }

            // resultFormat default is ["all"]
            if (!settings.resultFormat ||
                settings.resultFormat.length !== 1 ||
                settings.resultFormat[0] !== "all") {
              return false;
            }

            // resolutions: all should be enabled (no false values in the object)
            // An empty object means all are enabled (default)
            for (const [res, enabled] of Object.entries(settings.resolutions || {})) {
              if (enabled === false) {
                return false;
              }
            }

            // languages: no excludes or preferences (empty arrays)
            if (settings.languages) {
              if (settings.languages.required && settings.languages.required.length > 0) {
                return false;
              }
              if (settings.languages.allowed && settings.languages.allowed.length > 0) {
                return false;
              }
              if (settings.languages.exclude && settings.languages.exclude.length > 0) {
                return false;
              }
              if (settings.languages.preferred && settings.languages.preferred.length > 0) {
                return false;
              }
            }

            // options: check defaults
            if (settings.options) {
              // remove_ranks_under default is -10000000000
              if (settings.options.remove_ranks_under !== -10000000000) {
                return false;
              }
              // allow_english_in_languages default is false
              if (settings.options.allow_english_in_languages !== false) {
                return false;
              }
              // remove_unknown_languages default is false
              if (settings.options.remove_unknown_languages !== false) {
                return false;
              }
            }

            return true;
          }

          // Generate the manifest URL - use /manifest.json for default configs
          function getManifestUrl(settings, forInstall = false) {
            const isDefault = isDefaultConfig(settings);
            const host = window.location.host;

            if (isDefault) {
              // Default config: use public manifest URL (better CDN caching)
              return forInstall
                ? `stremio://${host}${stremioApiPrefix}/manifest.json`
                : `${window.location.origin}${stremioApiPrefix}/manifest.json`;
            } else {
              // Custom config: use b64config in URL
              const settingsString = btoa(JSON.stringify(settings));
              return forInstall
                ? `stremio://${host}${stremioApiPrefix}/${settingsString}/manifest.json`
                : `${window.location.origin}${stremioApiPrefix}/${settingsString}/manifest.json`;
            }
          }

          function getKodiManifestUrl(settings) {
            if (isDefaultConfig(settings)) {
              return `${window.location.origin}${stremioApiPrefix}/manifest.json`;
            }
            const settingsString = btoa(JSON.stringify(settings));
            return `${window.location.origin}${stremioApiPrefix}/${settingsString}/manifest.json`;
          }

          copyLinkButton.addEventListener("click", () => {
            const settings = getSettings();
            const manifestUrl = getManifestUrl(settings, false);

            const textArea = document.createElement("textarea");
            textArea.value = manifestUrl;
            document.body.appendChild(textArea);
            textArea.focus();
            textArea.select();
            document.execCommand("copy");
            document.body.removeChild(textArea);

            console.log(`Copied manifest URL: ${manifestUrl}`);

            copyAlert.toast();
          });

          installButton.addEventListener("click", () => {
            const settings = getSettings();
            const manifestUrl = getManifestUrl(settings, true);
            window.location.href = manifestUrl;
            console.log(`Installing manifest URL: ${manifestUrl}`);
            installAlert.toast();
          });

          async function setupKodiWithCode(rawCode) {
            const code = rawCode.trim().toLowerCase();
            if (!/^[0-9a-f]{6,16}$/.test(code)) {
              showKodiError("Kodi setup code must be a 6–16 character hexadecimal value.");
              return;
            }

            const settings = getSettings();
            const manifestUrl = getKodiManifestUrl(settings);

            const response = await fetch("/kodi/associate_manifest", {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                code: code,
                manifest_url: manifestUrl,
              }),
            });

            if (!response.ok) {
              let errorMessage = "Failed to setup Kodi.";
              try {
                const errorData = await response.json();
                if (errorData.detail) {
                  errorMessage = errorData.detail;
                }
              } catch (error) {
                console.error("Failed to parse Kodi setup error:", error);
              }
              showKodiError(errorMessage);
              return;
            }

            kodiAlertText.textContent = "Kodi setup completed successfully.";
            kodiAlert.toast();
            return true;
          }

          function showKodiError(message) {
            const errorAlert = document.getElementById("kodiErrorAlert");
            const errorText = document.getElementById("kodiErrorAlertText");
            errorText.textContent = message;
            errorAlert.toast();
          }

          const kodiDialog = document.querySelector("#kodi-dialog");
          const kodiConfirmBtn = document.querySelector("#kodi-confirm-btn");
          const kodiCancelBtn = document.querySelector("#kodi-cancel-btn");
          const kodiInput = document.querySelector("#kodi-code-input");

          kodiSetupButton.addEventListener("click", () => {
            const queryParams = new URLSearchParams(window.location.search);
            const suggestedCode = queryParams.get("kodi_code") || "";
            kodiInput.value = suggestedCode;
            kodiDialog.show();
          });

          kodiConfirmBtn.addEventListener("click", async () => {
            const code = kodiInput.value;
            if (code) {
              kodiConfirmBtn.loading = true;
              try {
                const success = await setupKodiWithCode(code);
                if (success) {
                  kodiDialog.hide();
                }
              } catch (error) {
                console.error("Kodi setup error:", error);
                showKodiError("An unexpected error occurred.");
              } finally {
                kodiConfirmBtn.loading = false;
              }
            } else {
              showKodiError("Please enter a setup code.");
            }
          });

          kodiCancelBtn.addEventListener("click", () => kodiDialog.hide());

          kodiInput.addEventListener("keydown", (event) => {
            if (event.key === "Enter") {
              kodiConfirmBtn.click();
            }
          });

          function getSettingsFromUrl() {
            const segments = window.location.pathname.split("/").filter(Boolean);
            const configureIndex = segments.lastIndexOf("configure");
            if (configureIndex <= 0) {
              return null;
            }

            const settingsString = decodeURIComponent(segments[configureIndex - 1]);
            if (!settingsString) {
              return null;
            }

            try {
              return JSON.parse(atob(settingsString));
            } catch (_) {
              return null;
            }
          }

          function populateFormFromSettings(settings) {
            if (settings.cachedOnly !== null)
              document.getElementById("cachedOnly").checked = settings.cachedOnly;
            if (settings.sortCachedUncachedTogether !== undefined && settings.sortCachedUncachedTogether !== null)
              document.getElementById("sortCachedUncachedTogether").checked = settings.sortCachedUncachedTogether;
            if (settings.removeTrash !== null)
              document.getElementById("removeTrash").checked = settings.removeTrash;
            if (settings.maxResultsPerResolution !== null)
              document.getElementById("maxResultsPerResolution").value = settings.maxResultsPerResolution;
            if (settings.maxSize !== null)
              document.getElementById("maxSize").value = settings.maxSize / 1073741824;

            // Handle multi-debrid format
            if (settings.debridServices && settings.debridServices.length > 0) {
              populateDebridServices(settings.debridServices);
            }
            // Handle legacy single-debrid format
            else if (settings.debridService && settings.debridService !== "torrent") {
              populateDebridServices([{
                service: settings.debridService,
                apiKey: settings.debridApiKey || ""
              }]);
            }

            // Handle enableTorrent
            const enableTorrentEl = document.getElementById("enableTorrent");
            if (enableTorrentEl) {
              if (settings.enableTorrent !== undefined) {
                enableTorrentEl.checked = settings.enableTorrent;
              } else if (settings.debridService === "torrent") {
                // Legacy torrent-only mode
                enableTorrentEl.checked = true;
              }
            }

            // Handle deduplicateStreams
            const deduplicateStreamsEl = document.getElementById("deduplicateStreams");
            if (deduplicateStreamsEl && settings.deduplicateStreams !== undefined) {
              deduplicateStreamsEl.checked = settings.deduplicateStreams;
            }

            const scrapeDebridAccountTorrentsEl = document.getElementById("scrapeDebridAccountTorrents");
            if (scrapeDebridAccountTorrentsEl && settings.scrapeDebridAccountTorrents !== undefined) {
              scrapeDebridAccountTorrentsEl.checked = settings.scrapeDebridAccountTorrents;
            }

            if (settings.debridStreamProxyPassword !== null)
              document.getElementById("debridStreamProxyPassword").value = settings.debridStreamProxyPassword;
            if (settings.resultFormat !== null && settings.resultFormat != "all")
              document.getElementById("resultFormat").value = settings.resultFormat;
            updateResultFormatPreview();
            if (settings.languages) {
              if (settings.languages.required)
                document.getElementById("languages_required").value = settings.languages.required;
              if (settings.languages.allowed)
                document.getElementById("languages_allowed").value = settings.languages.allowed;
              if (settings.languages.exclude)
                document.getElementById("languages_excluded").value = settings.languages.exclude;
              if (settings.languages.preferred)
                document.getElementById("languages_preferred").value = settings.languages.preferred;
            }
            if (settings.resolutions) {
              const allResolutions = ALL_RESOLUTIONS;
              const enabledResolutions = allResolutions.filter(res => settings.resolutions[res] !== false);
              document.getElementById("resolutions").value = enabledResolutions;
            }
            if (settings.options?.remove_ranks_under !== undefined)
              document.getElementById("rankThreshold").value = settings.options.remove_ranks_under;
            if (settings.options?.allow_english_in_languages !== undefined)
              document.getElementById("allowEnglishInLanguages").checked = settings.options.allow_english_in_languages;
            if (settings.options?.remove_unknown_languages !== undefined)
              document.getElementById("removeUnknownLanguages").checked = settings.options.remove_unknown_languages;
          }
        </script>
      </div>
    </div>

    <div class="heart-button" id="support-trigger">
      <sl-icon name="heart-fill"></sl-icon>
    </div>

    <sl-dialog label="Setup Kodi" id="kodi-dialog" style="--width: 500px">
      <div
        style="
          display: flex;
          flex-direction: column;
          gap: 1.2rem;
          margin-top: -10px;
        "
      >
        <p
          style="
            margin: 0;
            color: var(--sl-color-neutral-600);
            font-size: 0.95rem;
            line-height: 1.6;
          "
        >
          Kodi is a free and open-source media player that allows you to stream
          and organize your digital content. By setting up Comet on Kodi, you
          can access your favorite torrents and debrid services directly through
          its interface.
        </p>

        <sl-button
          href="https://github.com/g0ldyy/comet/blob/main/kodi/README.md"
          target="_blank"
          variant="default"
          style="width: 100%"
        >
          <sl-icon slot="prefix" name="book"></sl-icon>
          Kodi Setup Guide
        </sl-button>

        <sl-divider></sl-divider>

        <sl-input
          id="kodi-code-input"
          label="Setup Code"
          placeholder="e.g. 1a2b3c"
          help-text="Enter the hexadecimal code displayed in the Comet add-on settings (Configure/Reconfigure)."
          clearable
        ></sl-input>
      </div>
      <sl-button slot="footer" variant="primary" id="kodi-confirm-btn">
        Setup
      </sl-button>
      <sl-button slot="footer" variant="neutral" id="kodi-cancel-btn">
        Cancel
      </sl-button>
    </sl-dialog>

    <sl-dialog label="Support Comet" id="support-dialog" style="--width: 400px">
      <div
        style="
          display: flex;
          flex-direction: column;
          align-items: center;
          text-align: center;
          gap: 0.5rem;
          margin-top: -15px;
        "
      >
        <div
          style="
            font-size: 2.5rem;
            animation: heartbeat 1.5s ease-in-out infinite;
          "
        >
          ❤️
        </div>
        <h3 style="margin: 0">Donate to Me</h3>
        <p
          style="
            color: var(--sl-color-neutral-500);
            margin: 0;
            font-size: 0.9rem;
          "
        >
          Comet is a passion project fueled by late nights and coffee. Your
          support helps keep the lights on and the updates rolling!
        </p>

        <div
          style="
            display: flex;
            flex-direction: column;
            gap: 8px;
            width: 100%;
            margin-top: 10px;
          "
        >
          <sl-button
            href="https://github.com/sponsors/g0ldyy"
            target="_blank"
            outline
            style="width: 100%"
          >
            <sl-icon slot="prefix" name="github"></sl-icon>
            GitHub Sponsors
          </sl-button>
          <sl-button
            href="https://ko-fi.com/g0ldyy"
            target="_blank"
            outline
            style="width: 100%; --sl-color-primary-600: #ff5e5b"
          >
            <sl-icon slot="prefix" name="cup-hot"></sl-icon>
            Ko-fi
          </sl-button>
        </div>
      </div>
    </sl-dialog>

    <script>
      const dialog = document.querySelector("#support-dialog");
      const openButton = document.querySelector("#support-trigger");
      openButton.addEventListener("click", () => dialog.show());
    </script>
  </body>
</html>