(function attachDoesTheDogDieClient(root) {
  "use strict";

  var Common = root.SafeSceneCommon || require("./common.js");

  var MIRROR_PREFIX = "https://r.jina.ai/http://";
  var TOPIC_KEYWORDS = [
    "nudity",
    "sexual",
    "sex ",
    "sex?",
    "bestiality",
    "pedophilia",
    "rape",
    "incest",
    "objectified",
    "minor sexualized"
  ];

  function DoesTheDogDieClient(fetchImpl, options) {
    this.fetchImpl = fetchImpl;
    this.baseUrl = options && options.baseUrl ? options.baseUrl : "https://www.doesthedogdie.com";
    this.timeoutMs = options && options.timeoutMs ? options.timeoutMs : 6000;
    this.searchCacheTtlMs = 6 * 60 * 60 * 1000;
    this.pageCacheTtlMs = 6 * 60 * 60 * 1000;
    this.searchCache = new Map();
    this.pageCache = new Map();
  }

  DoesTheDogDieClient.prototype.getCached = async function getCached(cacheStore, ttlMs, key, loader) {
    var existing = cacheStore.get(key);
    var now = Date.now();

    if (existing && existing.expiresAt > now) {
      return existing.value;
    }

    var value = await loader();
    cacheStore.set(key, {
      value: value,
      expiresAt: now + ttlMs
    });
    return value;
  };

  function decodeMarkdownText(value) {
    return String(value || "")
      .replace(/\[(.*?)\]\((.*?)\)/g, "$1")
      .replace(/!\[(.*?)\]\((.*?)\)/g, "")
      .replace(/\*\*(.*?)\*\*/g, "$1")
      .replace(/\*(.*?)\*/g, "$1")
      .replace(/`(.*?)`/g, "$1")
      .replace(/&amp;/g, "&")
      .replace(/&#x27;/g, "'")
      .replace(/&quot;/g, "\"")
      .replace(/&lt;/g, "<")
      .replace(/&gt;/g, ">")
      .trim();
  }

  function normalizeLineEndings(value) {
    return String(value || "").replace(/\r\n?/g, "\n");
  }

  function unique(values) {
    var seen = new Set();
    return values.filter(function filterValue(value) {
      if (!value || seen.has(value)) {
        return false;
      }

      seen.add(value);
      return true;
    });
  }

  function normalizeSearchQuery(value) {
    return String(value || "")
      .replace(/[^\w\s:'’-]/g, " ")
      .replace(/\s+/g, " ")
      .trim();
  }

  function isRelevantTopic(topicTitle) {
    var normalized = Common.normalizeText(topicTitle);

    if (!normalized) {
      return false;
    }

    return TOPIC_KEYWORDS.some(function hasKeyword(keyword) {
      return normalized.indexOf(Common.normalizeText(keyword)) !== -1;
    });
  }

  function deriveCategoryFromTopic(topicTitle) {
    var normalized = Common.normalizeText(topicTitle);

    if (normalized.indexOf("nudity") !== -1) {
      return "nudity";
    }

    return "sex";
  }

  function buildSourceUrl(baseUrl, mediaId, seasonNumber, episodeNumber) {
    return baseUrl + "/media/" + mediaId + "?index1=" + seasonNumber + "&index2=" + episodeNumber;
  }

  function parseTimeReferences(text) {
    var matches = [];
    var regex = /\b\d{1,2}:\d{2}(?::\d{2})?\b/g;
    var seen = new Set();
    var match = null;

    while ((match = regex.exec(String(text || "")))) {
      var seconds = Common.parseTimecodeToSeconds(match[0]);

      if (!Number.isFinite(seconds) || seen.has(seconds)) {
        continue;
      }

      seen.add(seconds);
      matches.push(seconds);
    }

    return matches.sort(function sortAscending(left, right) {
      return left - right;
    });
  }

  function parseDurationHintSeconds(text) {
    var exactMatch = String(text || "").match(/\bwait\s+(?:about\s+|around\s+)?(\d{1,3})\s*seconds?\b/i);
    if (exactMatch) {
      return Number.parseInt(exactMatch[1], 10);
    }

    var quickMatch = String(text || "").match(/\bover very quickly\b/i);
    return quickMatch ? 10 : null;
  }

  function splitEpisodeSubsections(text) {
    var raw = String(text || "");
    var pattern = /(Episode\s+\d+\s*:?.*?)(?=(?:Episode\s+\d+\s*:)|$)/gis;
    var matches = [];
    var match = null;

    while ((match = pattern.exec(raw))) {
      matches.push(match[1].trim());
    }

    return matches;
  }

  function selectEpisodeScopedComment(text, seasonNumber, episodeNumber) {
    var normalizedText = String(text || "").trim();
    if (!normalizedText) {
      return "";
    }

    var episodeBlocks = splitEpisodeSubsections(normalizedText);
    if (episodeBlocks.length) {
      for (var index = 0; index < episodeBlocks.length; index += 1) {
        if (new RegExp("\\bEpisode\\s+" + episodeNumber + "\\b", "i").test(episodeBlocks[index])) {
          return episodeBlocks[index];
        }
      }
    }

    var seasonEpisodePattern = new RegExp("\\bS\\s*" + seasonNumber + "\\b[\\s\\S]{0,20}\\bE\\s*" + episodeNumber + "\\b", "i");
    if (seasonEpisodePattern.test(normalizedText)) {
      return normalizedText;
    }

    return normalizedText;
  }

  function buildRangeId(prefix, mediaId, seasonNumber, episodeNumber, topicTitle, index) {
    return [
      prefix,
      mediaId,
      seasonNumber,
      episodeNumber,
      Common.normalizeText(topicTitle).replace(/\s+/g, "-") || "scene",
      index
    ].join("-");
  }

  function buildRangeEntry(prefix, mediaId, seasonNumber, episodeNumber, topicTitle, startSeconds, endSeconds, sourceUrl, notes, confidence, index) {
    return {
      id: buildRangeId(prefix, mediaId, seasonNumber, episodeNumber, topicTitle, index),
      category: deriveCategoryFromTopic(topicTitle),
      start: startSeconds,
      end: endSeconds,
      startSeconds: startSeconds,
      endSeconds: endSeconds,
      confidence: confidence,
      notes: notes || null,
      sourceName: "DoesTheDogDie",
      sourceUrl: sourceUrl
    };
  }

  function buildWarningEntry(topicTitle, summary, sourceUrl) {
    return {
      sourceName: "DoesTheDogDie",
      sourceUrl: sourceUrl,
      sceneCount: 1,
      summary: decodeMarkdownText(topicTitle + ": " + summary).replace(/\s+/g, " ").trim(),
      counts: null,
      requiresConnection: false
    };
  }

  function parseSearchMediaIds(markdown) {
    var text = normalizeLineEndings(markdown);
    var regex = /\(https:\/\/www\.doesthedogdie\.com\/media\/(\d+)\)/g;
    var ids = [];
    var match = null;

    while ((match = regex.exec(text))) {
      ids.push(match[1]);
    }

    return unique(ids);
  }

  function parseDuckDuckGoMediaIds(markdown) {
    var text = normalizeLineEndings(markdown);
    var regex = /https:\/\/duckduckgo\.com\/l\/\?uddg=([^&\s)]+)/g;
    var ids = [];
    var match = null;

    while ((match = regex.exec(text))) {
      try {
        var targetUrl = decodeURIComponent(match[1]);
        var mediaMatch = targetUrl.match(/https:\/\/www\.doesthedogdie\.com\/media\/(\d+)/);
        if (mediaMatch) {
          ids.push(mediaMatch[1]);
        }
      } catch (error) {
        continue;
      }
    }

    return unique(ids);
  }

  function parseMediaMetadata(markdown) {
    var text = normalizeLineEndings(markdown);
    var titleMatch = text.match(/\n#\s+([^\n]+)\n\n##\s+([^\n]+)\n/);
    var headerMatch = text.match(/\n##\s+(TV Show|Movie|Book|Video Game|Podcast|Anime|Manga)\s*•\s*(\d{4})/i);
    var title = titleMatch ? decodeMarkdownText(titleMatch[1]) : "";
    var type = headerMatch ? decodeMarkdownText(headerMatch[1]) : "";
    var year = headerMatch ? Number.parseInt(headerMatch[2], 10) : null;

    return {
      title: title,
      type: type,
      year: year
    };
  }

  function parseTimelineBlocks(markdown, options) {
    var normalized = normalizeLineEndings(markdown);
    var exactRanges = [];
    var warnings = [];
    var sourceUrl = options.sourceUrl;
    var timelineBodyMatch = normalized.match(/## Trigger Timeline\n\n([\s\S]*?)(?:\n!\[Image|\nUnlock |$)/i);

    if (!timelineBodyMatch) {
      return {
        exactRanges: exactRanges,
        warnings: warnings
      };
    }

    var blockRegex = /([^\n]+)\n\n(?:CUE\n\n(\d{1,2}:\d{2}(?::\d{2})?)\n\n)?TRIGGER\n\n(\d{1,2}:\d{2}(?::\d{2})?)\n\n([\s\S]*?)(?:\n\nSAFE\n\n(\d{1,2}:\d{2}(?::\d{2})?))?(?=\n\n[^\n]+\n\n(?:CUE\n\n)?TRIGGER|\n\n!\[Image|\n\nUnlock |$)/g;
    var match = null;
    var rangeIndex = 1;

    while ((match = blockRegex.exec(timelineBodyMatch[1]))) {
      var topicTitle = decodeMarkdownText(match[1]);

      if (!isRelevantTopic(topicTitle)) {
        continue;
      }

      var triggerSeconds = Common.parseTimecodeToSeconds(match[3]);
      var safeSeconds = Common.parseTimecodeToSeconds(match[5]);
      var summary = decodeMarkdownText(match[4]);

      if (Number.isFinite(triggerSeconds) && Number.isFinite(safeSeconds) && safeSeconds > triggerSeconds) {
        exactRanges.push(buildRangeEntry(
          "ddd-timeline",
          options.mediaId,
          options.seasonNumber,
          options.episodeNumber,
          topicTitle,
          triggerSeconds,
          safeSeconds,
          sourceUrl,
          summary,
          "scraped-timeline",
          rangeIndex
        ));
        rangeIndex += 1;
      } else if (summary) {
        warnings.push(buildWarningEntry(topicTitle, summary, sourceUrl));
      }
    }

    return {
      exactRanges: exactRanges,
      warnings: warnings
    };
  }

  function parseExpertBlocks(markdown, options) {
    var normalized = normalizeLineEndings(markdown);
    var exactRanges = [];
    var warnings = [];
    var sourceUrl = options.sourceUrl;
    var expertMatch = normalized.match(/### Expert Ratings\n\n([\s\S]*?)\n### Community Ratings/i);

    if (!expertMatch) {
      return {
        exactRanges: exactRanges,
        warnings: warnings
      };
    }

    var blockRegex = /([^\n]+)\n\nYES\n\n\[S(\d+)\s+E(\d+)\]\([^)]+\)\n\nCUE\n\n(\d{1,2}:\d{2}(?::\d{2})?)\n\nTRIGGER\n\n(\d{1,2}:\d{2}(?::\d{2})?)\s*([^\n]*?)\n\nSKIP TO\n\n(\d{1,2}:\d{2}(?::\d{2})?)/g;
    var match = null;
    var rangeIndex = 1;

    while ((match = blockRegex.exec(expertMatch[1]))) {
      var seasonNumber = Number.parseInt(match[2], 10);
      var episodeNumber = Number.parseInt(match[3], 10);
      var topicTitle = decodeMarkdownText(match[1]);

      if (seasonNumber !== options.seasonNumber || episodeNumber !== options.episodeNumber || !isRelevantTopic(topicTitle)) {
        continue;
      }

      var triggerSeconds = Common.parseTimecodeToSeconds(match[5]);
      var skipToSeconds = Common.parseTimecodeToSeconds(match[7]);
      var summary = decodeMarkdownText(match[6] || "");

      if (Number.isFinite(triggerSeconds) && Number.isFinite(skipToSeconds) && skipToSeconds > triggerSeconds) {
        exactRanges.push(buildRangeEntry(
          "ddd-expert",
          options.mediaId,
          seasonNumber,
          episodeNumber,
          topicTitle,
          triggerSeconds,
          skipToSeconds,
          sourceUrl,
          summary,
          "scraped-expert",
          rangeIndex
        ));
        rangeIndex += 1;
      } else {
        warnings.push(buildWarningEntry(
          topicTitle,
          (Number.isFinite(triggerSeconds) ? "Trigger at " + Common.formatSeconds(triggerSeconds) + ". " : "") + summary,
          sourceUrl
        ));
      }
    }

    return {
      exactRanges: exactRanges,
      warnings: warnings
    };
  }

  function parseCommunityBlocks(markdown, options) {
    var normalized = normalizeLineEndings(markdown);
    var exactRanges = [];
    var warnings = [];
    var sourceUrl = options.sourceUrl;
    var rangeIndex = 1;
    var topicRegex = /\[([^\]]+)\]\(https:\/\/www\.doesthedogdie\.com\/[^)]+\)\n([\s\S]*?)(?=\n\[[^\]]+\]\(https:\/\/www\.doesthedogdie\.com\/|\n##### |\n## DDD Pro Guide|$)/g;
    var topicMatch = null;

    while ((topicMatch = topicRegex.exec(normalized))) {
      var topicTitle = decodeMarkdownText(topicMatch[1]);
      var topicBody = topicMatch[2];

      if (!isRelevantTopic(topicTitle)) {
        continue;
      }

      var episodeSpecificRegex = new RegExp("S\\s*" + options.seasonNumber + "\\s*\\n+\\s*E\\s*" + options.episodeNumber + "\\s*\\n+([\\s\\S]*?)(?=\\n+\\s*[A-Za-z0-9_.'’ -]+\\s*\\n+\\s*\\d+\\s+comment|\\n+\\s*\\d+\\s+comments?\\|Add comment|\\n+\\s*Add comment|\\n\\[[^\\]]+\\]\\(https:\\/\\/www\\.doesthedogdie\\.com\\/|\\n##### |$)", "i");
      var scopedMatch = topicBody.match(episodeSpecificRegex);
      var commentText = scopedMatch ? scopedMatch[1] : selectEpisodeScopedComment(topicBody, options.seasonNumber, options.episodeNumber);
      commentText = decodeMarkdownText(commentText).replace(/\s+/g, " ").trim();

      if (!commentText) {
        continue;
      }

      var timeReferences = parseTimeReferences(commentText);
      var durationHintSeconds = parseDurationHintSeconds(commentText);

      if (timeReferences.length >= 2) {
        var startSeconds = timeReferences[0];
        var endSeconds = timeReferences[1];

        if (Number.isFinite(startSeconds) && Number.isFinite(endSeconds) && endSeconds > startSeconds) {
          exactRanges.push(buildRangeEntry(
            "ddd-community",
            options.mediaId,
            options.seasonNumber,
            options.episodeNumber,
            topicTitle,
            startSeconds,
            endSeconds,
            sourceUrl,
            commentText,
            "scraped-community",
            rangeIndex
          ));
          rangeIndex += 1;
          continue;
        }
      }

      if (timeReferences.length === 1 && Number.isFinite(durationHintSeconds) && durationHintSeconds > 0) {
        exactRanges.push(buildRangeEntry(
          "ddd-community",
          options.mediaId,
          options.seasonNumber,
          options.episodeNumber,
          topicTitle,
          timeReferences[0],
          timeReferences[0] + durationHintSeconds,
          sourceUrl,
          commentText,
          "scraped-community-estimate",
          rangeIndex
        ));
        rangeIndex += 1;
        continue;
      }

      warnings.push(buildWarningEntry(topicTitle, commentText, sourceUrl));
    }

    return {
      exactRanges: exactRanges,
      warnings: warnings
    };
  }

  function dedupeRangeEntries(entries) {
    var seen = new Set();
    return entries.filter(function filterEntry(entry) {
      var key = [
        entry.category,
        entry.startSeconds,
        entry.endSeconds,
        entry.sourceUrl
      ].join("|");

      if (seen.has(key)) {
        return false;
      }

      seen.add(key);
      return true;
    });
  }

  function dedupeWarnings(entries) {
    var seen = new Set();
    return entries.filter(function filterEntry(entry) {
      var key = [
        entry.sourceName,
        entry.sourceUrl,
        Common.normalizeText(entry.summary)
      ].join("|");

      if (seen.has(key)) {
        return false;
      }

      seen.add(key);
      return true;
    });
  }

  DoesTheDogDieClient.prototype.requestMarkdownUrl = async function requestMarkdownUrl(targetUrl) {
    var controller = new AbortController();
    var timeoutId = setTimeout(function onTimeout() {
      controller.abort();
    }, this.timeoutMs);

    try {
      var response = await this.fetchImpl(MIRROR_PREFIX + targetUrl, {
        headers: {
          "accept": "text/plain, text/markdown;q=0.9, */*;q=0.1",
          "accept-language": "en-US,en;q=0.9",
          "x-no-cache": "1"
        },
        signal: controller.signal
      });

      if (!response.ok) {
        throw new Error("DoesTheDogDie mirror request failed: " + response.status + " " + targetUrl);
      }

      return response.text();
    } finally {
      clearTimeout(timeoutId);
    }
  };

  DoesTheDogDieClient.prototype.searchMediaIds = async function searchMediaIds(query) {
    var normalizedQuery = normalizeSearchQuery(query);
    var cacheKey = "search|" + normalizedQuery;
    var self = this;

    return this.getCached(this.searchCache, this.searchCacheTtlMs, cacheKey, async function loadSearch() {
      var markdown = await self.requestMarkdownUrl(
        self.baseUrl + "/dddsearch?q=" + encodeURIComponent(normalizedQuery)
      );
      return parseSearchMediaIds(markdown).slice(0, 10);
    });
  };

  DoesTheDogDieClient.prototype.searchDuckDuckGoMediaIds = async function searchDuckDuckGoMediaIds(query) {
    var normalizedQuery = normalizeSearchQuery(query);
    var cacheKey = "duckduckgo-search|" + normalizedQuery;
    var self = this;

    return this.getCached(this.searchCache, this.searchCacheTtlMs, cacheKey, async function loadSearch() {
      var markdown = await self.requestMarkdownUrl(
        "https://html.duckduckgo.com/html/?q=" + encodeURIComponent(normalizedQuery)
      );
      return parseDuckDuckGoMediaIds(markdown).slice(0, 10);
    });
  };

  DoesTheDogDieClient.prototype.fetchEpisodePage = async function fetchEpisodePage(mediaId, seasonNumber, episodeNumber) {
    var cacheKey = ["page", mediaId, seasonNumber, episodeNumber].join("|");
    var self = this;
    return this.getCached(this.pageCache, this.pageCacheTtlMs, cacheKey, async function loadPage() {
      var sourceUrl = buildSourceUrl(self.baseUrl, mediaId, seasonNumber, episodeNumber);
      var markdown = await self.requestMarkdownUrl(sourceUrl);
      return {
        sourceUrl: sourceUrl,
        markdown: markdown,
        metadata: parseMediaMetadata(markdown)
      };
    });
  };

  DoesTheDogDieClient.prototype.fetchTimelinePage = async function fetchTimelinePage(mediaId, seasonNumber, episodeNumber) {
    var cacheKey = ["timeline", mediaId, seasonNumber, episodeNumber].join("|");
    var self = this;
    return this.getCached(this.pageCache, this.pageCacheTtlMs, cacheKey, async function loadTimeline() {
      var sourceUrl = self.baseUrl + "/media/" + mediaId + "/timeline?index1=" + seasonNumber + "&index2=" + episodeNumber;
      var markdown = await self.requestMarkdownUrl(sourceUrl);
      return {
        sourceUrl: sourceUrl,
        markdown: markdown
      };
    });
  };

  function scoreMediaCandidate(metadata, options) {
    var score = Common.scoreTextSimilarity(metadata.title, options.showTitle);

    if (Array.isArray(options.aliases)) {
      options.aliases.forEach(function scoreAlias(alias) {
        score = Math.max(score, Common.scoreTextSimilarity(metadata.title, alias) + 5);
      });
    }

    if (metadata.type && /tv show/i.test(metadata.type)) {
      score += 12;
    }

    if (Number.isFinite(options.releaseYear) && Number.isFinite(metadata.year)) {
      if (metadata.year === options.releaseYear) {
        score += 10;
      } else if (Math.abs(metadata.year - options.releaseYear) <= 1) {
        score += 4;
      }
    }

    return score;
  }

  DoesTheDogDieClient.prototype.findBestEpisodeMatch = async function findBestEpisodeMatch(options) {
    var queries = unique(
      [options.showTitle].concat(Array.isArray(options.aliases) ? options.aliases : [])
        .map(normalizeSearchQuery)
        .filter(Boolean)
    );
    var candidateIds = [];

    for (var queryIndex = 0; queryIndex < queries.length; queryIndex += 1) {
      var duckQueries = [
        "doesthedogdie " + queries[queryIndex] + " tv show",
        Number.isFinite(options.releaseYear)
          ? "doesthedogdie " + queries[queryIndex] + " " + options.releaseYear + " tv show"
          : ""
      ].filter(Boolean);

      for (var duckIndex = 0; duckIndex < duckQueries.length; duckIndex += 1) {
        candidateIds = candidateIds.concat(await this.searchDuckDuckGoMediaIds(duckQueries[duckIndex]));
        if (candidateIds.length >= 4) {
          break;
        }
      }

      if (candidateIds.length < 4) {
        candidateIds = candidateIds.concat(await this.searchMediaIds(queries[queryIndex]));
      }

      if (candidateIds.length >= 4) {
        break;
      }
    }

    candidateIds = unique(candidateIds).slice(0, 4);

    if (!candidateIds.length) {
      return null;
    }

    var bestMatch = null;

    for (var index = 0; index < candidateIds.length; index += 1) {
      var mediaId = candidateIds[index];

      try {
        var page = await this.fetchEpisodePage(mediaId, options.seasonNumber, options.episodeNumber);
        var score = scoreMediaCandidate(page.metadata, options);

        if (!bestMatch || score > bestMatch.score) {
          bestMatch = {
            mediaId: mediaId,
            score: score,
            page: page
          };

          if (bestMatch.score >= 110) {
            break;
          }
        }
      } catch (error) {
        continue;
      }
    }

    return bestMatch && bestMatch.score >= 40 ? bestMatch : null;
  };

  DoesTheDogDieClient.prototype.lookupEpisode = async function lookupEpisode(options) {
    var bestMatch = await this.findBestEpisodeMatch(options);

    if (!bestMatch) {
      return null;
    }

    var timelinePage = null;

    try {
      timelinePage = await this.fetchTimelinePage(bestMatch.mediaId, options.seasonNumber, options.episodeNumber);
    } catch (error) {
      timelinePage = null;
    }

    var parsedExactRanges = [];
    var parsedWarnings = [];

    var expertResult = parseExpertBlocks(bestMatch.page.markdown, {
      mediaId: bestMatch.mediaId,
      seasonNumber: options.seasonNumber,
      episodeNumber: options.episodeNumber,
      sourceUrl: bestMatch.page.sourceUrl
    });
    parsedExactRanges = parsedExactRanges.concat(expertResult.exactRanges);
    parsedWarnings = parsedWarnings.concat(expertResult.warnings);

    var communityResult = parseCommunityBlocks(bestMatch.page.markdown, {
      mediaId: bestMatch.mediaId,
      seasonNumber: options.seasonNumber,
      episodeNumber: options.episodeNumber,
      sourceUrl: bestMatch.page.sourceUrl
    });
    parsedExactRanges = parsedExactRanges.concat(communityResult.exactRanges);
    parsedWarnings = parsedWarnings.concat(communityResult.warnings);

    if (timelinePage) {
      var timelineResult = parseTimelineBlocks(timelinePage.markdown, {
        mediaId: bestMatch.mediaId,
        seasonNumber: options.seasonNumber,
        episodeNumber: options.episodeNumber,
        sourceUrl: timelinePage.sourceUrl
      });
      parsedExactRanges = parsedExactRanges.concat(timelineResult.exactRanges);
      parsedWarnings = parsedWarnings.concat(timelineResult.warnings);
    }

    var exactRanges = dedupeRangeEntries(parsedExactRanges);
    var warningOnly = dedupeWarnings(parsedWarnings);

    if (!exactRanges.length && !warningOnly.length) {
      return null;
    }

    return {
      sourceName: "DoesTheDogDie",
      sourceUrl: bestMatch.page.sourceUrl,
      mediaId: bestMatch.mediaId,
      exactRanges: exactRanges,
      warningOnly: warningOnly,
      matchingSceneCount: exactRanges.length || warningOnly.length
    };
  };

  var api = {
    DoesTheDogDieClient: DoesTheDogDieClient,
    parseSearchMediaIds: parseSearchMediaIds,
    parseDuckDuckGoMediaIds: parseDuckDuckGoMediaIds,
    parseMediaMetadata: parseMediaMetadata,
    parseExpertBlocks: parseExpertBlocks,
    parseCommunityBlocks: parseCommunityBlocks,
    parseTimelineBlocks: parseTimelineBlocks
  };

  root.SafeSceneDoesTheDogDie = api;

  if (typeof module !== "undefined" && module.exports) {
    module.exports = api;
  }
}(typeof globalThis !== "undefined" ? globalThis : this));
