// source --> https://htlbid.com/v3/thyblackman.com/htlbid.js 
/*HTLv3*/!function(e){e.ADITUDE_WRAPPER_CONFIG={SITE_DOMAIN:"thyblackman.com",HTLBID_GLOBAL:"htl",BID_MODIFIERS:{},PREBID_ALIASES:[],GPT_SET_CENTERING:!0,PREBID_CONFIG:{minBidCacheTTL:0,eventHistoryTTL:30,enableTIDs:!0,useBidCache:!0,priceGranularity:"high",v3Settings:{gdpr:{timeout:8e3,defaultGdprScope:!0},gpp:{cmpApi:!0,timeout:8e3}},floors:{}},PREBID_GLOBAL:"pbjs",SLOT_PREFIX:"",ALL_AD_UNITS:[{slot:".htlad-adhesion",code:"/11462305847/thyblackman/adhesion",targeting:{},interstitial:!1,oop:!1,mediaTypes:{banner:{sizes:[{sizes:[[320,100],[320,50]],viewport:[0,0]},{sizes:[[728,90]],viewport:[728,0]},{sizes:[[728,90]],viewport:[1024,0]}]}},bids:[{viewport:[0,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820579"}},{bidder:"sovrn",params:{tagid:"1035307"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673327"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_adhesion-mobile"}},{bidder:"yieldmo",params:{placementId:"3919218697629017051"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]},{viewport:[728,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820579"}},{bidder:"sovrn",params:{tagid:"1035303"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673319"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_adhesion-tablet"}},{bidder:"yieldmo",params:{placementId:"3919218697788400604"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]},{viewport:[1024,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820579"}},{bidder:"sovrn",params:{tagid:"1035303"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673325"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_adhesion-desktop"}},{bidder:"yieldmo",params:{placementId:"3919218697956172765"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]}]},{slot:".htlad-in_content",code:"/11462305847/thyblackman/in_content",targeting:{},interstitial:!1,oop:!1,mediaTypes:{banner:{sizes:[{sizes:[[300,250],[320,100],[320,50],[300,600]],viewport:[0,0]},{sizes:[[728,90],[300,250]],viewport:[728,0]},{sizes:[[728,90]],viewport:[1024,0]}]}},bids:[{viewport:[0,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820580"}},{bidder:"sovrn",params:{tagid:"1035304"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673324"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_in_content-mobile"}},{bidder:"yieldmo",params:{placementId:"3919218698098779102"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]},{viewport:[728,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820580"}},{bidder:"sovrn",params:{tagid:"1035300"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673321"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_in_content-tablet"}},{bidder:"yieldmo",params:{placementId:"3919218698258162655"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]},{viewport:[1024,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820580"}},{bidder:"sovrn",params:{tagid:"1035300"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673322"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_in_content-desktop"}},{bidder:"yieldmo",params:{placementId:"3919218698409157600"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]}]},{slot:".htlad-leaderboard",code:"/11462305847/thyblackman/leaderboard",targeting:{},interstitial:!1,oop:!1,mediaTypes:{banner:{sizes:[{sizes:[[320,100],[320,50]],viewport:[0,0]},{sizes:[[728,90]],viewport:[728,0]},{sizes:[[970,250],[728,90]],viewport:[1024,0]}]}},bids:[{viewport:[0,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820576"}},{bidder:"sovrn",params:{tagid:"1035305"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673323"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_leaderboard-mobile"}},{bidder:"yieldmo",params:{placementId:"3919218698560152545"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]},{viewport:[728,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820576"}},{bidder:"sovrn",params:{tagid:"1035301"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673328"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_leaderboard-tablet"}},{bidder:"yieldmo",params:{placementId:"3919218698702758882"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]},{viewport:[1024,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820576"}},{bidder:"sovrn",params:{tagid:"1035301"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673320"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_leaderboard-desktop"}},{bidder:"yieldmo",params:{placementId:"3919218698828588003"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]}]},{slot:".htlad-out_of_page",code:"/11462305847/thyblackman/out_of_page",targeting:{},interstitial:!1,oop:!0,mediaTypes:{banner:{sizes:[{sizes:[],viewport:[0,0]}]}},bids:[{viewport:[0,0],bids:[]}]},{slot:".htlad-right_rail",code:"/11462305847/thyblackman/rightrail",targeting:{},interstitial:!1,oop:!1,mediaTypes:{banner:{sizes:[{sizes:[],viewport:[0,0]},{sizes:[],viewport:[728,0]},{sizes:[[300,600],[300,250]],viewport:[1024,0]}]}},bids:[{viewport:[0,0],bids:[]},{viewport:[728,0],bids:[]},{viewport:[1024,0],bids:[[{bidder:"openx",params:{delDomain:"blavity-d.openx.net",unit:"562021787"}},{bidder:"ix",params:{siteId:"820578"}},{bidder:"sovrn",params:{tagid:"1035302"}},{bidder:"pubmatic",params:{publisherId:"160224"}},{bidder:"pulsepoint",params:{cp:"563029",ct:"753639"}},{bidder:"nativo",params:{placementId:"1673326"}},{bidder:"triplelift",params:{inventoryCode:"thyblackman_right_rail-desktop"}},{bidder:"yieldmo",params:{placementId:"3919218698987971556"}},{bidder:"adgrid",params:{domainId:1683,placement:"l2dd5yhd"}}]]}]}],COMPONENTS:[{name:"double-verify",config:{clientCode:"24192157",settingsCode:"DV684348"}},{name:"creative-timed-refresh",config:{includeBaseDivIds:[".htlad-adhesion",".htlad-in_content",".htlad-leaderboard",".htlad-right_rail"],fallbackRefreshTime:30,refreshTimes:{prebid:30,amazon:30},viewableOnly:!0}},{name:"htl-traffic-shaping",config:{rules:[{bidder:"triplelift",operator:"BLOCK",conditions:{countries:["CN"]},uuid:"ce8b2581-dd3e-4e56-a3a4-58a641276ccf"}]}},{name:"htl-injector",config:{autoStartLayouts:!1,htlbidGlobal:"htl",pageviewUrl:"//ams-pageview-public.s3.amazonaws.com/1x1-pixel.png?id=e9fff6978977",selectors:[{selector:".htlad-adhesion",forceRender:!0,sticky:{closable:!1},interstitial:!1,oop:!1},{selector:".htlad-in_content",forceRender:!1,sticky:!1,interstitial:!1,oop:!1},{selector:".htlad-leaderboard",forceRender:!0,sticky:!1,interstitial:!1,oop:!1},{selector:".htlad-out_of_page",forceRender:!0,sticky:!1,interstitial:!1,oop:!0},{selector:".htlad-right_rail",forceRender:!1,sticky:!1,interstitial:!1,oop:!1}],slots:[{name:"adhesion",interstitial:!1,tiles:[{viewport:[0,0],config:{sizes:[[320,100],[320,50]],prebid:{groups:["adhesion-mobile"]}}},{viewport:[728,0],config:{sizes:[[728,90]],prebid:{groups:["adhesion-tablet"]}}},{viewport:[1024,0],config:{sizes:[[728,90]],prebid:{groups:["adhesion-desktop"]}}}],gpt:{targeting:{},outOfPage:!1,adUnit:"thyblackman/adhesion"},lockRefreshSize:!1,refresh:{interval:30,max:500},sticky:{closeable:!1,closeHours:0},prebidGroups:[{viewport:[0,0],groups:["adhesion-mobile"]},{viewport:[728,0],groups:["adhesion-tablet"]},{viewport:[1024,0],groups:["adhesion-desktop"]}]},{name:"in_content",interstitial:!1,tiles:[{viewport:[0,0],config:{sizes:[[300,250],[320,100],[320,50],[300,600]],prebid:{groups:["in_content-mobile"]}}},{viewport:[728,0],config:{sizes:[[728,90],[300,250]],prebid:{groups:["in_content-tablet"]}}},{viewport:[1024,0],config:{sizes:[[728,90]],prebid:{groups:["in_content-desktop"]}}}],gpt:{targeting:{},outOfPage:!1,adUnit:"thyblackman/in_content"},lazyLoad:{enabled:!0,pixels:600},lazyFetch:{},lockRefreshSize:!1,refresh:{interval:30,max:500},prebidGroups:[{viewport:[0,0],groups:["in_content-mobile"]},{viewport:[728,0],groups:["in_content-tablet"]},{viewport:[1024,0],groups:["in_content-desktop"]}]},{name:"leaderboard",interstitial:!1,tiles:[{viewport:[0,0],config:{sizes:[[320,100],[320,50]],prebid:{groups:["leaderboard-mobile"]}}},{viewport:[728,0],config:{sizes:[[728,90]],prebid:{groups:["leaderboard-tablet"]}}},{viewport:[1024,0],config:{sizes:[[970,250],[728,90]],prebid:{groups:["leaderboard-desktop"]}}}],gpt:{targeting:{},outOfPage:!1,adUnit:"thyblackman/leaderboard"},refresh:{interval:30,max:500},prebidGroups:[{viewport:[0,0],groups:["leaderboard-mobile"]},{viewport:[728,0],groups:["leaderboard-tablet"]},{viewport:[1024,0],groups:["leaderboard-desktop"]}]},{name:"out_of_page",interstitial:!1,tiles:[{viewport:[0,0],config:{sizes:[]}}],gpt:{targeting:{},outOfPage:!0,adUnit:"thyblackman/out_of_page"},lockRefreshSize:!1,prebidGroups:[{viewport:[0,0],groups:[]}]},{name:"right_rail",interstitial:!1,tiles:[{viewport:[0,0],config:{sizes:[]}},{viewport:[728,0],config:{sizes:[]}},{viewport:[1024,0],config:{sizes:[[300,600],[300,250]],prebid:{groups:["right_rail-desktop"]}}}],gpt:{targeting:{},outOfPage:!1,adUnit:"thyblackman/rightrail"},lazyLoad:{enabled:!0,pixels:600},lazyFetch:{},lockRefreshSize:!1,refresh:{interval:30,max:500},prebidGroups:[{viewport:[0,0],groups:[]},{viewport:[728,0],groups:[]},{viewport:[1024,0],groups:["right_rail-desktop"]}]}]}},{name:"throttle-refresh",config:{throttleMs:5e3}}],DIV_CUSTOMIZATIONS:[{baseDivId:".htlad-adhesion",observerConfig:{rootMargin:"0px 0px 0px 0px",threshold:[.25]}},{baseDivId:".htlad-in_content",observerConfig:{rootMargin:"600px 0px 600px 0px",threshold:[.25]}},{baseDivId:".htlad-leaderboard",observerConfig:{rootMargin:"0px 0px 0px 0px",threshold:[.25]}},{baseDivId:".htlad-out_of_page",observerConfig:{rootMargin:"0px 0px 0px 0px",threshold:[.25]}},{baseDivId:".htlad-right_rail",observerConfig:{rootMargin:"600px 0px 600px 0px",threshold:[.25]}}],PREBID_TIMEOUT:2e3,PBJS_BUILD:{version:"9.44.1",modules:["openxBidAdapter","ixBidAdapter","sovrnBidAdapter","pubmaticBidAdapter","pulsepointBidAdapter","nativoBidAdapter","tripleliftBidAdapter","yieldmoBidAdapter","adgridBidAdapter","gptPreAuction","sharedIdSystem","33acrossIdSystem","fabrickIdSystem","id5IdSystem","criteoIdSystem","pubProvidedIdSystem","unifiedIdSystem","consentManagement","consentManagementGpp","consentManagementUsp"]},THIRD_PARTY_SCRIPTS:[{name:"bouncex",appendTo:"head",url:"https://tag.bounceexchange.com/5892/i.js",async:!0},{name:"confiant",appendTo:"head",url:"https://cdn.confiant-integrations.net/z26h_gytFypnwX8JIyGJ5UIodkY/gpt_and_prebid/config.js",async:!0}],COMPONENTS_CONFIG_ENABLED:!0,CUSTOM_JS:"//InMobi CMP\n(function() {\n  var host = 'www.blavity.com';\n  var element = document.createElement('script');\n  var firstScript = document.getElementsByTagName('script')[0];\n  var url = 'https://cmp.inmobi.com'\n    .concat('/choice/', 'GANCBjEfRH5Fe', '/', host, '/choice.js?tag_version=V3');\n  var uspTries = 0;\n  var uspTriesLimit = 3;\n  element.async = true;\n  element.type = 'text/javascript';\n  element.src = url;\n\n  firstScript.parentNode.insertBefore(element, firstScript);\n\n  function makeStub() {\n    var TCF_LOCATOR_NAME = '__tcfapiLocator';\n    var queue = [];\n    var win = window;\n    var cmpFrame;\n\n    function addFrame() {\n      var doc = win.document;\n      var otherCMP = !!(win.frames[TCF_LOCATOR_NAME]);\n\n      if (!otherCMP) {\n        if (doc.body) {\n          var iframe = doc.createElement('iframe');\n\n          iframe.style.cssText = 'display:none';\n          iframe.name = TCF_LOCATOR_NAME;\n          doc.body.appendChild(iframe);\n        } else {\n          setTimeout(addFrame, 5);\n        }\n      }\n      return !otherCMP;\n    }\n\n    function tcfAPIHandler() {\n      var gdprApplies;\n      var args = arguments;\n\n      if (!args.length) {\n        return queue;\n      } else if (args[0] === 'setGdprApplies') {\n        if (\n          args.length > 3 &&\n          args[2] === 2 &&\n          typeof args[3] === 'boolean'\n        ) {\n          gdprApplies = args[3];\n          if (typeof args[2] === 'function') {\n            args[2]('set', true);\n          }\n        }\n      } else if (args[0] === 'ping') {\n        var retr = {\n          gdprApplies: gdprApplies,\n          cmpLoaded: false,\n          cmpStatus: 'stub'\n        };\n\n        if (typeof args[2] === 'function') {\n          args[2](retr);\n        }\n      } else {\n        if(args[0] === 'init' && typeof args[3] === 'object') {\n          args[3] = Object.assign(args[3], { tag_version: 'V3' });\n        }\n        queue.push(args);\n      }\n    }\n\n    function postMessageEventHandler(event) {\n      var msgIsString = typeof event.data === 'string';\n      var json = {};\n\n      try {\n        if (msgIsString) {\n          json = JSON.parse(event.data);\n        } else {\n          json = event.data;\n        }\n      } catch (ignore) {}\n\n      var payload = json.__tcfapiCall;\n\n      if (payload) {\n        window.__tcfapi(\n          payload.command,\n          payload.version,\n          function(retValue, success) {\n            var returnMsg = {\n              __tcfapiReturn: {\n                returnValue: retValue,\n                success: success,\n                callId: payload.callId\n              }\n            };\n            if (msgIsString) {\n              returnMsg = JSON.stringify(returnMsg);\n            }\n            if (event && event.source && event.source.postMessage) {\n              event.source.postMessage(returnMsg, '*');\n            }\n          },\n          payload.parameter\n        );\n      }\n    }\n\n    while (win) {\n      try {\n        if (win.frames[TCF_LOCATOR_NAME]) {\n          cmpFrame = win;\n          break;\n        }\n      } catch (ignore) {}\n\n      if (win === window.top) {\n        break;\n      }\n      win = win.parent;\n    }\n    if (!cmpFrame) {\n      addFrame();\n      win.__tcfapi = tcfAPIHandler;\n      win.addEventListener('message', postMessageEventHandler, false);\n    }\n  };\n\n  makeStub();\n\n  var uspStubFunction = function() {\n    var arg = arguments;\n    if (typeof window.__uspapi !== uspStubFunction) {\n      setTimeout(function() {\n        if (typeof window.__uspapi !== 'undefined') {\n          window.__uspapi.apply(window.__uspapi, arg);\n        }\n      }, 500);\n    }\n  };\n\n  var checkIfUspIsReady = function() {\n    uspTries++;\n    if (window.__uspapi === uspStubFunction && uspTries < uspTriesLimit) {\n      console.warn('USP is not accessible');\n    } else {\n      clearInterval(uspInterval);\n    }\n  };\n\n  if (typeof window.__uspapi === 'undefined') {\n    window.__uspapi = uspStubFunction;\n    var uspInterval = setInterval(checkIfUspIsReady, 6000);\n  }\n})();\n//End Inmobi CMP\n\n//add UTM KVPs that persist through user's session\n(function() {\n  // Define whitelisted targeting keys to persist\n  const whitelistedKeys = ['utm_source', 'utm_medium'];\n  \n  // Local storage key\n  const localStorageKey = 'htlPersistedKvs';\n  \n  // Function to get current page targeting values\n  function getPageTargeting() {\n    const targeting = {};\n    \n    // Check URL parameters first\n    const urlParams = new URLSearchParams(window.location.search);\n    whitelistedKeys.forEach(key => {\n      if (urlParams.has(key)) {\n        targeting[key] = urlParams.get(key);\n      }\n    });\n    \n    // Then check if GPT is defined and has pubads\n    if (window.googletag && googletag.pubads) {\n      const pubads = googletag.pubads();\n      \n      // Get targeting values for whitelisted keys\n      whitelistedKeys.forEach(key => {\n        // Skip if already found in URL\n        if (targeting[key]) return;\n        \n        const values = pubads.getTargeting(key);\n        if (values && values.length > 0) {\n          targeting[key] = values[0];\n        }\n      });\n    }\n    \n    return targeting;\n  }\n  \n  // Function to persist targeting values\n  function persistTargeting() {\n    // Get existing persisted values\n    let persistedValues = {};\n    try {\n      const stored = localStorage.getItem(localStorageKey);\n      if (stored) {\n        persistedValues = JSON.parse(stored);\n      }\n    } catch (e) {\n      console.error('Error reading persisted targeting:', e);\n    }\n    \n    // Get current page targeting\n    const currentTargeting = getPageTargeting();\n    \n    // Merge current with persisted (current takes precedence)\n    let hasChanges = false;\n    whitelistedKeys.forEach(key => {\n      if (currentTargeting[key] && persistedValues[key] !== currentTargeting[key]) {\n        persistedValues[key] = currentTargeting[key];\n        hasChanges = true;\n      }\n    });\n    \n    // Save back to localStorage if changes were made\n    if (hasChanges) {\n      localStorage.setItem(localStorageKey, JSON.stringify(persistedValues));\n    }\n    \n    // Apply persisted values to page targeting\n    if (window.googletag && googletag.pubads) {\n      const pubads = googletag.pubads();\n      Object.keys(persistedValues).forEach(key => {\n        if (whitelistedKeys.includes(key) && persistedValues[key]) {\n          pubads.setTargeting(key, persistedValues[key]);\n        }\n      });\n    }\n  }\n  \n  // Initialize\n  function initialize() {\n    // Apply any persisted values and check for new ones\n    persistTargeting();\n    \n    // Set up slot rendering event listener\n    if (window.googletag && googletag.cmd) {\n      googletag.cmd.push(function() {\n        googletag.pubads().addEventListener('slotRenderEnded', persistTargeting);\n      });\n    }\n  }\n  \n  // Run initialization\n  if (window.googletag && googletag.cmd) {\n    googletag.cmd.push(initialize);\n  } else {\n    window.addEventListener('DOMContentLoaded', function() {\n      if (window.googletag && googletag.cmd) {\n        googletag.cmd.push(initialize);\n      } else {\n        // Simple fallback - just run without GPT\n        initialize();\n      }\n    });\n  }\n})();\n\n\n/* eslint-disable no-unused-vars */\n/* eslint-disable no-multiple-empty-lines */\n/* eslint-disable no-empty */\n/* eslint-disable no-multi-spaces */\n/* eslint-disable no-console */\n\n/* DO NOT TOUCH THIS - HELPER CONSTS START */\n\nclass InjectionQueue {\n  constructor() {\n    this.queue = []\n    this.processing = false\n  }\n\n  addTask(task, delay = 50, maxRetries = 10) {\n    this.queue.push({ task, delay, retries: 0, maxRetries })\n    this.processQueue()\n  }\n\n  async processQueue() {\n    if (this.processing) return\n    this.processing = true\n\n    while (this.queue.length > 0) {\n      let { task, delay, retries, maxRetries } = this.queue[0] // Peek at the first task\n\n      try {\n        const success = await task() // Task should return true on success, false on failure\n        if (success) {\n          this.queue.shift() // Remove successful task\n        } else if (retries < maxRetries) {\n          this.queue[0].retries++ // Increment retry count\n          await new Promise(resolve => setTimeout(resolve, delay)) // Wait before retrying\n          continue // Retry without removing from queue\n        } else {\n          console.warn('Max retries reached, removing task.')\n          this.queue.shift() // Remove failed task\n        }\n      } catch (error) {\n        console.error('Task execution error:', error)\n        this.queue.shift() // Remove task if an unexpected error occurs\n      }\n    }\n\n    this.processing = false\n  }\n}\n\nconst injectionQueue = new InjectionQueue()\n\nfunction isHomePage() {\n  return window.location.pathname === '/' || window.location.pathname === ''\n}\n\n/* DO NOT TOUCH THIS - HELPER CONSTS END */\n\n\n\n/* AD OPS SECTION START */\n\n/* ALL PAGES START */\n\n/*\n  CSS FOR PAGE\n*/\n\ninjectCSS(`\n  .injected-container {\n    margin: 16px;\n    text-align: center;\n    flex: auto;\n  }\n  .pattern-injection {\n    min-height: 1px;\n  }\n`)\n\n/* ALL PAGES END */\n\nfunction runAdInjection() {\n  const isMobile = window.innerWidth <= 768\n  const onHomePage = isHomePage()\n  const isBlocked = isBlockedPage()\n\n  // Add logging for blocked pages\n  if (isBlocked) {\n    console.log('Ad injection skipped: Page is in blocked list')\n    return\n  }\n\n  if (!onHomePage) {\n    if (isMobile) {\n      /* MOBILE INJECTION START */\n      queueInsertAfterWordCount({\n        parentSelector: '.entry-content',\n        itemSelector: 'p',\n        adUnits: ['in_content'], // If more placements than units, units will cycle ie 1-2-3-1-2-3\n        wordsThreshold: 200,\n        position: 'afterend', // Place the ads after the words\n      })\n      /* MOBILE INJECTION END */\n    } else {\n      /* DESKTOP INJECTION START */\n      queueInsertAfterWordCount({\n        parentSelector: '.entry-content',\n        itemSelector: 'p',\n        adUnits: ['in_content'], // If more placements than units, units will cycle ie 1-2-3-1-2-3\n        wordsThreshold: 300,\n        position: 'afterend', // Place the ads after the words\n      })\n      /* DESKTOP INJECTION END */\n    }\n  }\n\n  console.log('Injection finishing.')\n  console.log({\n    isMobile,\n    onHomePage,\n  })\n}\n\nconst debouncedRunAdInjection = debounce(runAdInjection, 1000)\n\n// Run once on initial load\ndebouncedRunAdInjection()\n\n// Always listen for page changes and re-run ad injection logic\nonPageChange(runAdInjection, 1000)\n\n/* AD OPS SECTION END */\n\n/*\n  * ------------------------------------- *\n  *****************************************\n  * DO NOT TOUCH ANYTHING BELOW THIS LINE *\n  * DO NOT TOUCH ANYTHING BELOW THIS LINE *\n  * DO NOT TOUCH ANYTHING BELOW THIS LINE *\n  * ***************************************\n  * ------------------------------------- *\n*/\n\nconst BLOCKED_PAGES = [\n  'thyblackman.com/2012/06/01/how-to-tell-if-your-girl-is-possibly-a-ho/',\n  'thyblackman.com/2023/01/23/african-americans-how-to-know-the-difference-between-a-man-and-a-nger/',\n  'thyblackman.com/2023/06/03/black-women-bitch-will-always-be-an-insult/'\n]\n\n// Function to check if current page is in the blocked list\nfunction isBlockedPage() {\n  const currentUrl = window.location.href.toLowerCase()\n\n  // Check if current URL contains any of the blocked page paths\n  return BLOCKED_PAGES.some(blockedPath => {\n    // Strip protocol to make matching more reliable\n    return currentUrl.includes(blockedPath.toLowerCase())\n  })\n}\n\n\nfunction debounce(fn, delay) {\n  let timeout\n  return function (...args) {\n    clearTimeout(timeout)\n    timeout = setTimeout(() => fn.apply(this, args), delay)\n  }\n}\n\nfunction onPageChange(callback, timeout = 500) {\n  let currentPathname = window.location.pathname\n\n  function handleChange() {\n    setTimeout(() => {\n      if (currentPathname !== window.location.pathname) {\n        currentPathname = window.location.pathname\n        callback(currentPathname)\n      }\n    }, timeout)\n  }\n\n  // Listen for history state changes (back/forward navigation)\n  window.addEventListener('popstate', handleChange)\n\n  // Monkey-patch pushState & replaceState to detect route changes\n  const originalPushState = history.pushState\n  history.pushState = function (...args) {\n    originalPushState.apply(this, args)\n    handleChange()\n  }\n\n  const originalReplaceState = history.replaceState\n  history.replaceState = function (...args) {\n    originalReplaceState.apply(this, args)\n    handleChange()\n  }\n}\n\nfunction createWrappedDiv(parentClass = 'injected-container', adUnit) {\n  const parentDiv = document.createElement('div')\n  parentDiv.className = parentClass\n\n  const childDiv = document.createElement('div')\n  childDiv.className = `htlad-${adUnit.trim()}`\n\n  parentDiv.appendChild(childDiv)\n  return parentDiv\n}\n\n// Function to inject CSS into the page (only once)\nfunction injectCSS(css, styleId = 'custom-style-injector') {\n  if (!css) return\n\n  if (!document.getElementById(styleId)) {\n    const style = document.createElement('style')\n    style.textContent = css\n    document.head.appendChild(style)\n  }\n}\n\nfunction waitForElement(selector, maxRetries = 10, delay = 100) {\n  return new Promise((resolve, reject) => {\n    let attempts = 0\n\n    function check() {\n      const element = document.querySelector(selector)\n      if (element) {\n        resolve(element)\n      } else if (attempts < maxRetries) {\n        attempts++\n        setTimeout(check, delay)\n      } else {\n        reject(new Error(`Element ${selector} not found after ${maxRetries} retries`))\n      }\n    }\n\n    check()\n  })\n}\n\n// Function to insert the wrapped div at the specified position\nfunction insertWrappedDiv({\n  parentClass = 'injected-container',\n  adUnit,\n  targetSelector, // Optional if targetElement is provided\n  targetElement,  // Allows direct DOM reference\n  position = 'afterbegin',\n  levelsUp = 0,\n}) {\n  let target = targetElement || document.querySelector(targetSelector)\n\n  console.log('Injection appending: ', { adUnit, target, date: Date.now() })\n\n  if (!target) {\n    console.warn('No valid target found.')\n    return false // Signals retry\n  }\n\n  // Traverse up if levelsUp is specified\n  if (levelsUp > 0) {\n    target = getParentElement(target, levelsUp)\n  }\n\n  if (!target) {\n    console.warn(`No valid parent found after traversing ${levelsUp} levels`)\n    return false // Signals retry\n  }\n\n  const wrappedDiv = createWrappedDiv(parentClass, adUnit)\n  target.insertAdjacentElement(position, wrappedDiv)\n\n  return true // Successful insertion\n}\n\n// Function to traverse up a specified number of parent levels safely\nfunction getParentElement(element, levelsUp = 1) {\n  for (let i = 0; i < levelsUp; i++) {\n    if (!element.parentElement) {\n      console.warn(\n        `Reached the top of the DOM before reaching ${levelsUp} levels up`\n      )\n      return element // Returns the last valid parent found\n    }\n    element = element.parentElement\n  }\n  return element\n}\n\nfunction getFilteredContentElements(parentSelector, { startSelector, endSelector, excludeSelectors = [] } = {}) {\n  const parent = document.querySelector(parentSelector)\n  if (!parent) return []\n\n  let children = Array.from(parent.children)\n\n  // Find the starting element (if specified)\n  let startIndex = 0\n  if (startSelector) {\n    const startEl = parent.querySelector(startSelector)\n    if (startEl > 0) {\n      startIndex = children.indexOf(startEl)\n    }\n  }\n\n  // Find the ending element (if specified)\n  let endIndex = children.length\n  if (endSelector) {\n    const endEl = parent.querySelector(endSelector)\n    if (endEl > 0) {\n      endIndex = children.indexOf(endEl)\n    }\n  }\n\n  // Slice content within start and end range\n  children = children.slice(startIndex, endIndex + 1)\n\n  // Remove excluded elements\n  if (excludeSelectors.length > 0) {\n    children = children.filter((el) => !excludeSelectors.some((sel) => el.matches(sel)))\n  }\n\n  return children\n}\n\nfunction findValidContentElement(element, {\n  validSelectors = ['p', 'img', 'blockquote'],\n  wrapperSelectors = ['span', 'div'], // Allow customization of potential wrappers\n  contentWrapperSelector,\n  excludedSelector\n} = {}) {\n  if (!element) return null\n\n  // If the element matches a valid selector, return it directly\n  if (validSelectors.some((sel) => element.matches(sel))) {\n    return element\n  }\n\n  // If it's an excluded element (like an inline ad), return null\n  if (excludedSelector && element.matches(excludedSelector)) {\n    return null\n  }\n\n  // If it's a known wrapper type, look inside for a content wrapper\n  if (wrapperSelectors.some((sel) => element.matches(sel))) {\n    const contentContainer = contentWrapperSelector\n      ? element.querySelector(contentWrapperSelector)\n      : element\n\n    if (contentContainer) {\n      // Find first valid content element inside the wrapper\n      return contentContainer.querySelector(validSelectors.join(','))\n    }\n  }\n\n  return null // If nothing valid is found, return null\n}\n\nfunction generateAdUnitNames(baseName = 'AdUnit', existingAdsCount = 0, countNeeded = 3, startIndex = null) {\n  let startingNumber = startIndex !== null ? startIndex : existingAdsCount + 1\n  return Array.from({ length: countNeeded }, (_, i) => `${baseName}${startingNumber + i}`)\n}\n\nfunction insertAfterPattern({\n  parentSelector,\n  itemSelector,\n  adUnits,\n  firstInsertAfter = 2,\n  insertEvery = 5,\n  parentClass = 'injected-container',\n  position = 'afterend',\n}) {\n  const parent = document.querySelector(parentSelector)\n  if (!parent) {\n    console.warn(`No parent found for selector: '${parentSelector}'`)\n    return false // Retry needed\n  }\n\n  const items = parent.querySelectorAll(itemSelector)\n  if (items.length === 0) {\n    console.warn(`No elements found for selector: '${itemSelector}' inside '${parentSelector}'`)\n    return false // Retry needed\n  }\n\n  let adIndex = 0 // Track which ad unit to use next\n  let insertCount = 0\n\n  items.forEach((item, index) => {\n    if (index + 1 === firstInsertAfter || (index + 1 - firstInsertAfter) % insertEvery === 0) {\n      const adUnit = adUnits[adIndex % adUnits.length] // Rotate through ad units\n\n      injectionQueue.addTask(() => {\n        return insertWrappedDiv({\n          adUnit,\n          parentClass,\n          targetElement: item, // Pass the actual element reference\n          position,\n          levelsUp: 0,\n        })\n      })\n\n      adIndex++ // Move to the next ad unit in rotation\n      insertCount++\n    }\n  })\n\n  if (insertCount === 0) {\n    console.warn('No ads were inserted. Check firstInsertAfter and insertEvery values.')\n    return false // Retry if necessary\n  }\n\n  return true // Successfully scheduled\n}\n\nasync function queueInsertAfterWordCount({\n  parentSelector,\n  itemSelector,\n  adUnits,\n  wordsThreshold = 300, // Insert ad after this many words\n  resetBetweenItems = false,\n  parentClass = 'injected-container',\n  position = 'afterend',\n}) {\n  const parent = await waitForElement(parentSelector, 50, 100)\n  if (!parent) {\n    console.warn(`No parent found for selector: '${parentSelector}'`)\n    return false // Retry needed\n  }\n\n  const items = parent.querySelectorAll(itemSelector)\n  if (items.length === 0) {\n    console.warn(`No elements found for selector: '${itemSelector}' inside '${parentSelector}'`)\n    return false // Retry needed\n  }\n\n  /* Prevent Duplication */\n  const existingAds = parent.querySelectorAll(`.${parentClass}`)\n  existingAds.forEach((ad) => {\n    console.log('Injection removing dupe: ', ad)\n    ad.remove()\n  })\n\n  let wordCount = 0\n  let adIndex = 0\n  let insertCount = 0\n\n  items.forEach((item) => {\n    const text = item.innerText.trim() // Extract text content\n    const words = text.split(/\\s+/).length // Count words (split by spaces)\n    wordCount += words\n\n    if (wordCount >= wordsThreshold) {\n      const adUnit = adUnits[adIndex % adUnits.length] // Rotate ad units\n\n      injectionQueue.addTask(() => {\n        return insertWrappedDiv({\n          adUnit,\n          parentClass,\n          targetElement: item, // Insert ad after this element\n          position,\n          levelsUp: 0,\n        })\n      })\n\n      adIndex++\n      insertCount++\n      wordCount = resetBetweenItems ? 0 : wordCount - wordsThreshold // Reset word count after injection\n    }\n  })\n\n  if (insertCount === 0) {\n    console.warn('No ads were inserted. Check wordsThreshold value.')\n    return false // Retry if necessary\n  }\n\n  return true // Successfully scheduled\n}\n\n\nfunction createAdDiv(id) {\n  const div = document.createElement('div')\n  div.id = id\n  return div\n}\n\nfunction makeAnchor({\n  target = 'body',\n  adUnit = 'dt-sticky',\n  divId = 'anchor',\n  addDesktopPadding = true,\n  closeButton = false,\n  css = {\n    bottom: 0,\n    left: 0,\n    position: 'fixed',\n    textAlign: 'center',\n    width: '100%',\n    zIndex: 999,\n  }\n}) {\n  if (!document.getElementById(`${divId}--wrapper`)) {\n    adUnit = `htlad-${adUnit.trim()}`\n    const wrapperDiv = createAdDiv(`${divId}--wrapper`)\n    const innerDiv = createAdDiv(`${divId}--wrapper-inner`)\n    const adDiv = createAdDiv(divId)\n    const targetDiv = document.querySelector(target)\n    wrapperDiv.classList.add('div-wrapper')\n    wrapperDiv.classList.add('anchor-wrapper-outer')\n    innerDiv.classList.add('anchor-wrapper-inner')\n    adDiv.classList.add(adUnit)\n    innerDiv.appendChild(adDiv)\n    wrapperDiv.appendChild(innerDiv)\n\n    Object.keys(css).forEach((attr) => {\n      wrapperDiv.style[attr] = css[attr]\n    })\n\n    if (closeButton) {\n      const closeButton = document.createElement('div')\n      closeButton.classList.add('anchor-close-button')\n      closeButton.onclick = () => wrapperDiv.remove()\n      innerDiv.appendChild(closeButton)\n    }\n\n    targetDiv.appendChild(wrapperDiv)\n\n    if (addDesktopPadding) {\n      if (document.body) {\n        document.body.style.paddingBottom = '90px'\n      }\n    }\n  }\n}\n\nfunction insertAfterNthChild({\n  containerSelector,        // Selector for the parent container\n  requiredAttributes = [],  // Optional attributes the container must have\n  childSelector,            // Selector for direct child elements\n  nth = 2,                  // Insert after the nth direct child (1-based index)\n  adUnit,                   // ID or class for the injected ad unit\n  parentClass = 'injected-container', // Class for the wrapper div\n  position = 'afterend',    // Where to insert relative to the target element\n}) {\n  // Build the full container selector with required attributes\n  const attributeSelector = requiredAttributes.map(attr => `[${attr}]`).join('')\n  const container = document.querySelector(`${containerSelector}${attributeSelector}`)\n\n  if (!container) {\n    console.warn(`No container found for selector: '${containerSelector}' with attributes: '${requiredAttributes.join(', ')}'`)\n    return\n  }\n\n  // Get only direct children and filter by the childSelector\n  const children = Array.from(container.children).filter(child => child.matches(childSelector))\n\n  // Ensure the requested nth element exists\n  const targetChild = children.length >= nth ? children[nth - 1] : null\n\n  if (!targetChild) {\n    console.warn(`No direct child element found at index ${nth} using selector '${childSelector}' inside '${containerSelector}'`)\n    return\n  }\n\n  // Inject the wrapped div\n  queueInsertWrappedDiv({\n    adUnit,\n    parentClass,\n    targetElement: targetChild,\n    position,\n  })\n}\n\nfunction insertAfterHeightThreshold({\n  postSelector,\n  adUnits,\n  heightThreshold = 2000,\n  parentClass = 'injected-container',\n  position = 'afterend',\n}) {\n  console.log('Post injection starting...')\n  const post = document.querySelector(postSelector)\n  if (!post) {\n    console.warn(`No element found for selector: '${postSelector}'`)\n    return\n  }\n\n  console.log('Post: ', post)\n\n  const directChildren = Array.from(post.children) // Get only direct children\n  let cumulativeHeight = 0\n  let adIndex = 0\n\n  console.log('Children: ', directChildren)\n\n  directChildren.forEach((child) => {\n    const childHeight = child.offsetHeight // Get element height\n    cumulativeHeight += childHeight\n\n    if (cumulativeHeight >= heightThreshold) {\n      // Select ad unit in rotation\n      const adUnit = adUnits[adIndex % adUnits.length]\n\n      queueInsertWrappedDiv({\n        adUnit,\n        parentClass,\n        targetElement: child,\n        position,\n        levelsUp: 0,\n      })\n\n      cumulativeHeight = 0 // Reset height tracker\n      adIndex++ // Move to next ad unit\n    }\n  })\n}\n\nfunction insertSupplementalAds({\n  parentSelector,\n  targetElement,\n  adUnits,\n  existingAdSelector = '[class^=\"htlad-\"]',\n  maxInsertions = 3,\n  allowedSelectors = ['p', 'img', 'blockquote'],\n  parentClass = 'injected-container',\n  position = 'afterend',\n  minGapDistance = window.innerHeight / 3,\n  filterContent = null, // Custom function to filter content elements\n  validateElement = null, // Custom function to check if an element is valid\n}) {\n  let parent = targetElement || document.querySelector(parentSelector)\n  if (!parent) {\n    console.warn(`No parent found for selector: '${parentSelector}'`)\n    return false\n  }\n\n  let children = filterContent ? filterContent(parentSelector) : Array.from(parent.children)\n  let existingAds = Array.from(parent.querySelectorAll(existingAdSelector))\n\n  if (children.length < 2 && existingAds.length === 0) {\n    console.warn(`Not enough content or ads inside '${parentSelector}' to calculate gaps.`)\n    return false\n  }\n\n  let allElements = [...children, ...existingAds].sort(\n    (a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top\n  )\n\n  let gaps = []\n  const parentRect = parent.getBoundingClientRect()\n  let lastAdBottom = parentRect.top\n\n  existingAds.forEach((ad) => {\n    const rect = ad.getBoundingClientRect()\n    const gap = rect.top - lastAdBottom\n\n    if (gap >= minGapDistance) {\n      gaps.push({ gapSize: gap, midpointY: lastAdBottom + gap / 2 })\n    }\n\n    lastAdBottom = rect.bottom\n  })\n\n  const contentBottomGap = parentRect.bottom - lastAdBottom\n  if (contentBottomGap >= minGapDistance) {\n    gaps.push({ gapSize: contentBottomGap, midpointY: lastAdBottom + contentBottomGap / 2 })\n  }\n\n  gaps.sort((a, b) => b.gapSize - a.gapSize)\n  const topGaps = gaps.slice(0, maxInsertions)\n\n  let insertCount = 0\n  let adIndex = 0\n\n  topGaps.forEach(({ midpointY }) => {\n    let closestElement = null\n    let closestDistance = Infinity\n\n    allElements.forEach((element) => {\n      const rect = element.getBoundingClientRect()\n\n      if (rect.top >= midpointY) {\n        let validElement = validateElement ? validateElement(element) : element\n\n        if (validElement && allowedSelectors.some((sel) => validElement.matches(sel))) {\n          const distance = rect.top - midpointY\n          if (distance < closestDistance) {\n            closestDistance = distance\n            closestElement = validElement\n          }\n        }\n      }\n    })\n\n    if (closestElement) {\n      const adUnit = adUnits[adIndex % adUnits.length]\n\n      injectionQueue.addTask(() => {\n        return insertWrappedDiv({\n          adUnit,\n          parentClass,\n          targetElement: closestElement,\n          position,\n          levelsUp: 0,\n        })\n      })\n\n      adIndex++\n      insertCount++\n    }\n  })\n\n  if (insertCount === 0) {\n    console.warn('No valid spots found for supplemental ads.')\n    return false\n  }\n\n  return true\n}\n\nfunction insertAdsAtCadence({\n  parentSelector, // The main content wrapper\n  adUnits, // Array of ad unit names\n  adsPerScreenHeight = 0.5, // How many ads per screen height (e.g., 0.5 = 1 ad every 2 screen heights)\n  allowedSelectors = ['p', 'li', 'div.article-row'], // Where ads can go\n  blockedSelectors = ['h1', 'h2', 'h3', 'h4', 'table', '.no-dynamic-units'], // Where ads CAN’T go\n  parentClass = 'injected-ad-container', // Wrapper class for injected ads\n  position = 'afterend', // Default insertion position\n}) {\n  const parent = document.querySelector(parentSelector)\n  if (!parent) {\n    console.warn(`No parent found for selector: '${parentSelector}'`)\n    return false\n  }\n\n  const allElements = Array.from(parent.querySelectorAll(allowedSelectors.join(',')))\n  if (!allElements.length) {\n    console.warn(`No valid content elements found for ad placement inside '${parentSelector}'`)\n    return false\n  }\n\n  const blockedElements = new Set([...parent.querySelectorAll(blockedSelectors.join(','))])\n\n  const screenHeight = window.innerHeight\n  const targetGap = screenHeight / adsPerScreenHeight // Correctly calculate spacing\n\n  let insertCount = 0\n  let lastInsertedY = parent.getBoundingClientRect().top // Start from top of content\n  let adIndex = 0\n\n  for (let element of allElements) {\n    const rect = element.getBoundingClientRect()\n    if (blockedElements.has(element)) continue // Skip blocked elements\n\n    const gap = rect.top - lastInsertedY\n    if (gap >= targetGap) {\n      const adUnit = adUnits[adIndex % adUnits.length] // Rotate ad units\n\n      injectionQueue.addTask(() => {\n        return insertWrappedDiv({\n          adUnit,\n          parentClass,\n          targetElement: element,\n          position,\n          levelsUp: 0,\n        })\n      })\n\n      insertCount++\n      adIndex++\n      lastInsertedY = rect.bottom // Update last insertion point\n    }\n  }\n\n  if (insertCount === 0) {\n    console.warn('No valid spots found for cadence-based ad insertion.')\n    return false\n  }\n\n  return true // Successfully scheduled\n}\n\nfunction observeMutations({ targetSelector, config, filter, contentSelector, callback }) {\n  const targetNode = document.querySelector(targetSelector)\n  if (!targetNode) {\n    console.warn(`⚠️ Target selector not found: ${targetSelector}`)\n    return\n  }\n\n  const observer = new MutationObserver((mutationsList) => {\n    mutationsList.forEach((mutation) => {\n      mutation.addedNodes.forEach((node) => {\n        if (node.nodeType === 1 && filter(node)) {\n          console.log('🆕 Detected new parent node:', node)\n\n          // If a contentSelector is provided, find the inner content\n          const contentNode = contentSelector ? node.querySelector(contentSelector) : node\n\n          if (!contentNode) {\n            console.warn('⚠️ No matching content inside:', node)\n            return\n          }\n\n          callback(contentNode) // Now passing the correct inner content\n        }\n      })\n    })\n  })\n\n  observer.observe(targetNode, config)\n}\n\nfunction queueInsertWrappedDiv(options) {\n  injectionQueue.addTask(() => {\n    const success = insertWrappedDiv(options)\n    return success !== false // Ensure it returns a boolean for retry logic\n  })\n}\n\nfunction queueInsertAfterPattern(options) {\n  injectionQueue.addTask(() => insertAfterPattern(options), 500)\n}\n"};const n=function(){if(document.currentScript.src)return document.currentScript.src;const e=document.getElementsByTagName("script");for(const n of e)if(n.src.includes("/thyblackman.com/htlbid.js"))return n.src;return console.warn("Unable to determine the original script URL for Aditude Loader"),""}();function t(){if(!n)return void console.error("Unable to determine URL for fallback script.");console.warn("Loading bridge-htlbid.js.");const t=e.document.createElement("script");t.src=n.replace(/htlbid.js/,"bridge-htlbid.js"),t.async=!0,t.onerror=()=>{console.error("Unable to load the htlbid wrapper.")},t.src===n?console.error("Unable to determine URL for htlbid wrapper."):e.document.head.appendChild(t)}if(Object.keys(e.ADITUDE_WRAPPER_CONFIG).length>0){["https://dn0qt3r0xannq.cloudfront.net/blavity-XA2LDeQSQU/blavity.com/prebid-load.js","https://dn0qt3r0xannq.cloudfront.net/blavity-XA2LDeQSQU/blavity.com/prebid-wrapper.js"].forEach((n=>{const t=e.document.createElement("link");t.setAttribute("rel","preload"),t.setAttribute("as","script"),t.setAttribute("href",n),e.document.head.appendChild(t)})),function(){const n="https://dn0qt3r0xannq.cloudfront.net/blavity-XA2LDeQSQU/blavity.com/prebid-load.js";if(Array.from(document.scripts).some((e=>{try{return new URL(e.src).href===new URL(n,document.baseURI).href}catch{return!1}})))return void console.warn("Aditude Loader - attempted to load file multiple times, skipping:",n);const r=e.document.createElement("script");r.src=n,r.async=!0,r.onload=function(){console.log("prebid-load.js loaded successfully."),e.tude=e.tude||{},e.tude.cmd=e.tude.cmd||[],e.tude.cmd.push((function(){e.tude.customJs((({main:n,events:t,domContentLoaded:r,loadScript:i,useAditudePrebidFloors:a})=>{try{(()=>{var n=document.createElement("script"),t=document.getElementsByTagName("script")[0],r="https://cmp.inmobi.com".concat("/choice/","GANCBjEfRH5Fe","/","www.blavity.com","/choice.js?tag_version=V3"),i=0;n.async=!0,n.type="text/javascript",n.src=r,t.parentNode.insertBefore(n,t),(()=>{for(var n,t="__tcfapiLocator",r=[],i=e;i;){try{if(i.frames[t]){n=i;break}}catch(e){}if(i===e.top)break;i=i.parent}n||(function e(){var n=i.document,r=!!i.frames[t];if(!r)if(n.body){var a=n.createElement("iframe");a.style.cssText="display:none",a.name=t,n.body.appendChild(a)}else setTimeout(e,5);return!r}(),i.__tcfapi=function(){var e,n=arguments;if(!n.length)return r;if("setGdprApplies"===n[0])n.length>3&&2===n[2]&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0));else if("ping"===n[0]){var t={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof n[2]&&n[2](t)}else"init"===n[0]&&"object"==typeof n[3]&&(n[3]=Object.assign(n[3],{tag_version:"V3"})),r.push(n)},i.addEventListener("message",(n=>{var t="string"==typeof n.data,r={};try{r=t?JSON.parse(n.data):n.data}catch(e){}var i=r.__tcfapiCall;i&&e.__tcfapi(i.command,i.version,((e,r)=>{var a={__tcfapiReturn:{returnValue:e,success:r,callId:i.callId}};t&&(a=JSON.stringify(a)),n&&n.source&&n.source.postMessage&&n.source.postMessage(a,"*")}),i.parameter)}),!1))})();var a=function(){var n=arguments;typeof e.__uspapi!==a&&setTimeout((()=>{void 0!==e.__uspapi&&e.__uspapi.apply(e.__uspapi,n)}),500)};if(void 0===e.__uspapi){e.__uspapi=a;var o=setInterval((()=>{i++,e.__uspapi===a&&i<3?console.warn("USP is not accessible"):clearInterval(o)}),6e3)}})(),(()=>{const n=["utm_source","utm_medium"],t="htlPersistedKvs";function r(){let r={};try{const e=localStorage.getItem(t);e&&(r=JSON.parse(e))}catch(e){console.error("Error reading persisted targeting:",e)}const i=(()=>{const t={},r=new URLSearchParams(e.location.search);if(n.forEach((e=>{r.has(e)&&(t[e]=r.get(e))})),e.googletag&&googletag.pubads){const e=googletag.pubads();n.forEach((n=>{if(t[n])return;const r=e.getTargeting(n);r&&r.length>0&&(t[n]=r[0])}))}return t})();let a=!1;if(n.forEach((e=>{i[e]&&r[e]!==i[e]&&(r[e]=i[e],a=!0)})),a&&localStorage.setItem(t,JSON.stringify(r)),e.googletag&&googletag.pubads){const e=googletag.pubads();Object.keys(r).forEach((t=>{n.includes(t)&&r[t]&&e.setTargeting(t,r[t])}))}}function i(){r(),e.googletag&&googletag.cmd&&googletag.cmd.push((()=>{googletag.pubads().addEventListener("slotRenderEnded",r)}))}e.googletag&&googletag.cmd?googletag.cmd.push(i):e.addEventListener("DOMContentLoaded",(()=>{e.googletag&&googletag.cmd?googletag.cmd.push(i):i()}))})();class l{constructor(){this.queue=[],this.processing=!1}addTask(e,n=50,t=10){this.queue.push({task:e,delay:n,retries:0,maxRetries:t}),this.processQueue()}async processQueue(){if(!this.processing){for(this.processing=!0;this.queue.length>0;){let{task:e,delay:n,retries:t,maxRetries:r}=this.queue[0];try{if(await e())this.queue.shift();else{if(t<r){this.queue[0].retries++,await new Promise((e=>setTimeout(e,n)));continue}console.warn("Max retries reached, removing task."),this.queue.shift()}}catch(e){console.error("Task execution error:",e),this.queue.shift()}}this.processing=!1}}}const c=new l;function o(){const n=e.innerWidth<=768,t="/"===e.location.pathname||""===e.location.pathname;(()=>{const n=e.location.href.toLowerCase();return p.some((e=>n.includes(e.toLowerCase())))})()?console.log("Ad injection skipped: Page is in blocked list"):(t||d(n?{parentSelector:".entry-content",itemSelector:"p",adUnits:["in_content"],wordsThreshold:200,position:"afterend"}:{parentSelector:".entry-content",itemSelector:"p",adUnits:["in_content"],wordsThreshold:300,position:"afterend"}),console.log("Injection finishing."),console.log({isMobile:n,onHomePage:t}))}((e,n="custom-style-injector")=>{if(e&&!document.getElementById(n)){const n=document.createElement("style");n.textContent=e,document.head.appendChild(n)}})("\n  .injected-container {\n    margin: 16px;\n    text-align: center;\n    flex: auto;\n  }\n  .pattern-injection {\n    min-height: 1px;\n  }\n"),function(e,n){let t;return function(...r){clearTimeout(t),t=setTimeout((()=>e.apply(this,r)),n)}}(o,1e3)(),function(n,t=500){let r=e.location.pathname;function i(){setTimeout((()=>{r!==e.location.pathname&&(r=e.location.pathname,n(r))}),t)}e.addEventListener("popstate",i);const a=history.pushState;history.pushState=function(...e){a.apply(this,e),i()};const o=history.replaceState;history.replaceState=function(...e){o.apply(this,e),i()}}(o,1e3);const p=["thyblackman.com/2012/06/01/how-to-tell-if-your-girl-is-possibly-a-ho/","thyblackman.com/2023/01/23/african-americans-how-to-know-the-difference-between-a-man-and-a-nger/","thyblackman.com/2023/06/03/black-women-bitch-will-always-be-an-insult/"];function s({parentClass:e="injected-container",adUnit:n,targetSelector:t,targetElement:r,position:i="afterbegin",levelsUp:a=0}){let o=r||document.querySelector(t);if(console.log("Injection appending: ",{adUnit:n,target:o,date:Date.now()}),!o)return console.warn("No valid target found."),!1;if(a>0&&(o=((e,n=1)=>{for(let t=0;t<n;t++){if(!e.parentElement)return console.warn(`Reached the top of the DOM before reaching ${n} levels up`),e;e=e.parentElement}return e})(o,a)),!o)return console.warn(`No valid parent found after traversing ${a} levels`),!1;const s=((e="injected-container",n)=>{const t=document.createElement("div");t.className=e;const r=document.createElement("div");return r.className=`htlad-${n.trim()}`,t.appendChild(r),t})(e,n);return o.insertAdjacentElement(i,s),!0}async function d({parentSelector:e,itemSelector:n,adUnits:t,wordsThreshold:r=300,resetBetweenItems:i=!1,parentClass:a="injected-container",position:o="afterend"}){const d=await((e,n=10,t=100)=>new Promise(((r,i)=>{let a=0;!function o(){const s=document.querySelector(e);s?r(s):a<n?(a++,setTimeout(o,t)):i(new Error(`Element ${e} not found after ${n} retries`))}()})))(e,50,100);if(!d)return console.warn(`No parent found for selector: '${e}'`),!1;const l=d.querySelectorAll(n);if(0===l.length)return console.warn(`No elements found for selector: '${n}' inside '${e}'`),!1;d.querySelectorAll(`.${a}`).forEach((e=>{console.log("Injection removing dupe: ",e),e.remove()}));let p=0,u=0,m=0;return l.forEach((e=>{const n=e.innerText.trim().split(/\s+/).length;if(p+=n,p>=r){const n=t[u%t.length];c.addTask((()=>s({adUnit:n,parentClass:a,targetElement:e,position:o,levelsUp:0}))),u++,m++,p=i?0:p-r}})),0!==m||(console.warn("No ads were inserted. Check wordsThreshold value."),!1)}}catch(u){console.error("Custom JS error:",u)}}))}))},r.onerror=()=>{console.warn("Failed to load prebid-load.js, loading fallback script."),t()},e.document.head.appendChild(r)}()}else t()}(window);