[{"command":"settings","settings":{"pluralDelimiter":"\u0003","suppressDeprecationErrors":true,"user":{"uid":0,"permissionsHash":"85d70ff5c59258123846295729decb835a5bed491a3a7e109f48f8ed54760113"}},"merge":true},{"command":"add_css","data":[{"rel":"stylesheet","media":"all","href":"\/sites\/default\/files\/css\/css_s_1GmMDVKilGqTybuDKAE7Jawuom3ouFgrtQF1sZ0q0.css?delta=0\u0026language=en\u0026theme=luv_theme\u0026include=eJzLz4hPzkgsSkwuSS0q1i_LTEnN181JrKrUzclPTMnMSwcA0MIMlQ\u0026exclude=eJxtj1luwzAMRC_kWkcSaImRWUsiQUpx3NPXS5MCQX44nDcAl8CKLmoXyGMkyJxG-IbHEA5eWQtk-sEBuw_MC-EuRTJBDeg-QT-B4sCzh4Q-QUP3bE4o5C7xUCFvjYKdvLfZTWD4MnGrUCgcPsygEBqqOVG-UcYvYenyltlKgvoHm7M-WVCSRlz9SjFhOzJ8SD5eu8Gdla6rnux_guI-9MUvNyPEK237yiWiLe7sqKbBNmtYrhfuhKu5s46FY8_4C1b5i8M"}]},{"command":"add_js","selector":"body","data":[{"src":"\/core\/assets\/vendor\/jquery\/jquery.min.js?v=3.7.1"},{"src":"\/core\/assets\/vendor\/once\/once.min.js?v=1.0.1"},{"src":"\/core\/misc\/drupalSettingsLoader.js?v=10.6.2"},{"src":"\/core\/misc\/drupal.js?v=10.6.2"},{"src":"\/core\/misc\/drupal.init.js?v=10.6.2"},{"src":"\/modules\/custom\/oh_characters\/assets\/video-lazy-loading.c4ea404e.js?v=20260203.135522"}]},{"command":"insert","method":"append","selector":"#images_list","data":"  \u003Cdiv\n    class=\u0022image-item image \u0022\u003E\n          \u003Cimg\n        class=\u0022thumbnail-image\u0022\n        src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_normal_small\/s3\/char-post-images\/1179736754490140448.png?VersionId=KKYTDasvZ8wp4uRwTNjfcdJhj6K8I05k\u0026amp;itok=ckC1vqxW\u0022\n        data-src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_normal\/s3\/char-post-images\/1179736754490140448.png?VersionId=.7eNqcfME0ftziJcnl0lCKMzIETJs186\u0026amp;itok=3w5C7g2s\u0022\n        data-description=\u0022\u0022\n        data-post-description=\u0022Making waves and catching summer rays! \u2600\ufe0f\ud83c\udf0a #BeachDayBliss\u0022\n        data-secured=\u00220\u0022\n        data-character=\u0022100\u0022\n        data-type=\u0022image\u0022\n                  data-video-url=\u0022\u0022                   data-video-id=\u0022610\u0022         data-post=\u00220\u0022\n        data-post-id=\u00227693\u0022\n        data-is-multiple=\u0022\u0022\n        alt=\u0022Making waves and cat\u0022\n        loading=\u0022lazy\u0022\n        onerror=\u0022this.style.display=\u0027none\u0027; this.nextElementSibling.nextElementSibling.style.display=\u0027flex\u0027;\u0022\n      \/\u003E\n      \u003Cdiv class=\u0022image-icon\u0022\u003E\u003C\/div\u003E\n          \u003C\/div\u003E\n  \u003Cdiv\n    class=\u0022image-item image \u0022\u003E\n          \u003Cimg\n        class=\u0022thumbnail-image\u0022\n        src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_normal_small\/s3\/char-post-images\/-3455326768097503909.png?VersionId=zk4x2PgsWE.Yz4oAuNbvsr4BGGP7UJZx\u0026amp;itok=0pmsxMEB\u0022\n        data-src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_normal\/s3\/char-post-images\/-3455326768097503909.png?VersionId=1bKl5CndbTqNPKRhrVHlrXdFOzt0PHJ_\u0026amp;itok=YAbFZLvu\u0022\n        data-description=\u0022\u0022\n        data-post-description=\u0022Caught up in the sunset vibes before my shift. Always dream first \u2728 #SunsetGoals\u0022\n        data-secured=\u00220\u0022\n        data-character=\u0022100\u0022\n        data-type=\u0022image\u0022\n                  data-video-url=\u0022\u0022                   data-video-id=\u0022393\u0022         data-post=\u00221\u0022\n        data-post-id=\u00227456\u0022\n        data-is-multiple=\u0022\u0022\n        alt=\u0022Caught up in the sun\u0022\n        loading=\u0022lazy\u0022\n        onerror=\u0022this.style.display=\u0027none\u0027; this.nextElementSibling.nextElementSibling.style.display=\u0027flex\u0027;\u0022\n      \/\u003E\n      \u003Cdiv class=\u0022image-icon\u0022\u003E\u003C\/div\u003E\n          \u003C\/div\u003E\n  \u003Cdiv\n    class=\u0022image-item image \u0022\u003E\n          \u003Cimg\n        class=\u0022thumbnail-image\u0022\n        src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_normal_small\/s3\/char-post-images\/2900409130008486228.png?VersionId=nP2ALoZBrABelZPRTHkLBHSpCAb_sPyn\u0026amp;itok=VGOtWio0\u0022\n        data-src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_normal\/s3\/char-post-images\/2900409130008486228.png?VersionId=U5LsOtjQC2LpvOxhMjCUepiP7q48XLow\u0026amp;itok=PBb3-hvl\u0022\n        data-description=\u0022\u0022\n        data-post-description=\u0022Sunset vibes and secret thrills \ud83c\udf05\u2728 #SummerAdventures\u0022\n        data-secured=\u00220\u0022\n        data-character=\u0022100\u0022\n        data-type=\u0022image\u0022\n                  data-video-url=\u0022\u0022                   data-video-id=\u0022291\u0022         data-post=\u00222\u0022\n        data-post-id=\u00227354\u0022\n        data-is-multiple=\u0022\u0022\n        alt=\u0022Sunset vibes and sec\u0022\n        loading=\u0022lazy\u0022\n        onerror=\u0022this.style.display=\u0027none\u0027; this.nextElementSibling.nextElementSibling.style.display=\u0027flex\u0027;\u0022\n      \/\u003E\n      \u003Cdiv class=\u0022image-icon\u0022\u003E\u003C\/div\u003E\n          \u003C\/div\u003E\n  \u003Cdiv\n    class=\u0022image-item image blurred-item\u0022\u003E\n          \u003Cimg\n        class=\u0022thumbnail-image\u0022\n        src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_blurred_small\/s3\/char-post-images\/-4170508474206381878.png?VersionId=WznzV2BIjMfiVZ461Y7HUKJCfoKtVd9v\u0026amp;itok=bIGXIqtA\u0022\n        data-src=\u0022https:\/\/d3mpf1svyo6ceu.cloudfront.net\/styles\/profile_blurred\/s3\/char-post-images\/-4170508474206381878.png?VersionId=afFwyUr5H1NhAJFbA8BbqOzC3Aow8bLe\u0026amp;itok=cC5kZBRO\u0022\n        data-description=\u0022\u0022\n        data-post-description=\u0022Feeling fierce in the wild \ud83c\udf3f\ud83d\udc3e #AdventureAwaits\u0022\n        data-secured=\u00221\u0022\n        data-character=\u0022100\u0022\n        data-type=\u0022image\u0022\n                        data-post=\u00223\u0022\n        data-post-id=\u00227280\u0022\n        data-is-multiple=\u0022\u0022\n        alt=\u0022Feeling fierce in th\u0022\n        loading=\u0022lazy\u0022\n        onerror=\u0022this.style.display=\u0027none\u0027; this.nextElementSibling.nextElementSibling.style.display=\u0027flex\u0027;\u0022\n      \/\u003E\n      \u003Cdiv class=\u0022image-icon\u0022\u003E\u003C\/div\u003E\n          \u003C\/div\u003E\n\n\u003Cscript\u003E\n  (function () {\n    \/\/ Auto-play sequence for mobile devices\n    let currentVideoIndex = 0;\n    let videoElements = [];\n    let autoPlayTimer = null;\n    let isAutoPlaying = false;\n\n    \/\/ Check if device is mobile\n    function isMobileDevice() {\n      return \/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini\/i.test(navigator.userAgent);\n    }\n    \n    \/\/ Check if device is iOS\n    function isIOSDevice() {\n      return \/iPad|iPhone|iPod\/.test(navigator.userAgent);\n    }\n\n    \/\/ Initialize video elements\n    function initVideoElements() {\n      videoElements = Array.from(document.querySelectorAll(\u0027.video-wrapper\u0027));\n\n      videoElements.forEach((wrapper, index) =\u003E {\n        const video = wrapper.querySelector(\u0027.video-player\u0027);\n        const thumbnail = wrapper.querySelector(\u0027.video-thumbnail\u0027);\n        const videoIcon = wrapper.querySelector(\u0027.video-icon\u0027);\n\n\n        if (!video) {\n          return;\n        }\n\n        \/\/ iOS-specific: Ensure video is visible and has proper dimensions\n        if (isIOSDevice()) {\n          video.style.display = \u0027block\u0027;\n          video.style.width = \u0027100%\u0027;\n          video.style.height = \u0027auto\u0027;\n          video.style.objectFit = \u0027cover\u0027;\n          \n          \/\/ Force video to show poster or first frame\n          video.addEventListener(\u0027loadstart\u0027, function() {\n            video.style.opacity = \u00271\u0027;\n          });\n          \n          video.addEventListener(\u0027error\u0027, function(e) {\n            \/\/ Show video icon if video fails\n            if (videoIcon) {\n              videoIcon.style.display = \u0027block\u0027;\n            }\n          });\n        }\n\n        \/\/ Add click handler for video icon to start video\n        if (videoIcon) {\n          videoIcon.addEventListener(\u0027click\u0027, function () {\n            currentVideoIndex = index;\n            if (isMobileDevice()) {\n              startAutoPlay();\n            } else {\n              playVideo(index);\n            }\n          });\n        }\n\n        \/\/ For mobile - show play buttons and allow manual start\n        if (isMobileDevice()) {\n          \/\/ Keep play buttons visible for mobile\n          wrapper.style.cursor = \u0027pointer\u0027;\n\n          video.addEventListener(\u0027ended\u0027, function () {\n            showNextVideo();\n          });\n\n          \/\/ Click to start auto-play sequence from any video\n          wrapper.addEventListener(\u0027click\u0027, function () {\n            currentVideoIndex = index;\n            startAutoPlay();\n          });\n        } else {\n          \/\/ Desktop - direct hover to play\/stop without complex state tracking\n          let isVideoPlaying = false;\n\n          wrapper.addEventListener(\u0027mouseenter\u0027, function () {\n            if (!isAutoPlaying \u0026\u0026 !isVideoPlaying) {\n              isVideoPlaying = true;\n              playVideo(index);\n            }\n          });\n\n          wrapper.addEventListener(\u0027mouseleave\u0027, function () {\n            if (!isAutoPlaying \u0026\u0026 isVideoPlaying) {\n              isVideoPlaying = false;\n              stopVideo(index);\n            }\n          });\n\n          \/\/ Click to start auto-play sequence\n          wrapper.addEventListener(\u0027click\u0027, function () {\n            currentVideoIndex = index;\n            startAutoPlay();\n          });\n        }\n      });\n    }\n\n    function playVideo(index) {\n      if (index \u003E= videoElements.length) {\n        return;\n      }\n\n      const wrapper = videoElements[index];\n      const video = wrapper.querySelector(\u0027.video-player\u0027);\n      const thumbnail = wrapper.querySelector(\u0027.video-thumbnail:not(.video-player)\u0027);\n      const videoIcon = wrapper.querySelector(\u0027.video-icon\u0027);\n      const loader = wrapper.querySelector(\u0027.video-loading-indicator\u0027);\n\n\n      if (!video) {\n        return;\n      }\n\n      \/\/ Show loader and fade play button\n      if (loader) {\n        loader.style.display = \u0027block\u0027;\n      }\n      if (videoIcon) {\n        videoIcon.style.opacity = \u00270\u0027;\n        setTimeout(() =\u003E {\n          videoIcon.style.display = \u0027none\u0027;\n        }, 200);\n      }\n\n      \/\/ Load and play video (iOS requires loading on user interaction)\n      const videoUrl = video.dataset.videoUrl;\n      \n      if (!video.src \u0026\u0026 videoUrl) {\n        video.querySelector(\u0027source\u0027).src = videoUrl;\n        video.load();\n      }\n\n      \/\/ Hide thumbnail, show video with smooth transition\n      if (thumbnail) {\n        thumbnail.style.opacity = \u00270\u0027;\n        setTimeout(() =\u003E {\n          thumbnail.style.display = \u0027none\u0027;\n        }, 100);\n      }\n      video.style.display = \u0027block\u0027;\n      video.style.opacity = \u00271\u0027;\n      video.currentTime = 0; \/\/ Reset to start\n\n      \/\/ Add event listeners for iOS video loading\n      video.addEventListener(\u0027loadeddata\u0027, function() {\n        if (loader) {\n          loader.style.display = \u0027none\u0027;\n        }\n        video.play().catch(e =\u003E {\n          showThumbnail(index);\n        });\n      }, { once: true });\n      \n      video.addEventListener(\u0027canplay\u0027, function() {\n        if (loader) {\n          loader.style.display = \u0027none\u0027;\n        }\n      }, { once: true });\n      \n      \/\/ Try to play immediately if already loaded\n      if (video.readyState \u003E= 3) { \/\/ HAVE_FUTURE_DATA\n        if (loader) {\n          loader.style.display = \u0027none\u0027;\n        }\n        video.play().catch(e =\u003E {\n          showThumbnail(index);\n        });\n      }\n    }\n\n    function showThumbnail(index) {\n      if (index \u003E= videoElements.length) {\n        return;\n      }\n\n      const wrapper = videoElements[index];\n      const video = wrapper.querySelector(\u0027.video-player\u0027);\n      const thumbnail = wrapper.querySelector(\u0027.video-thumbnail:not(.video-player)\u0027);\n      const videoIcon = wrapper.querySelector(\u0027.video-icon\u0027);\n      const loader = wrapper.querySelector(\u0027.video-loading-indicator\u0027);\n\n      \/\/ Pause video with smooth transition\n      if (video) {\n        \/\/ video.pause();\n        \/\/ video.style.opacity = \u00270\u0027;\n        setTimeout(() =\u003E {\n          \/\/ video.style.display = \u0027none\u0027;\n        }, 100);\n      }\n\n      \/\/ Show thumbnail and play button with smooth transition\n      if (thumbnail) {\n        thumbnail.style.display = \u0027block\u0027;\n        thumbnail.style.opacity = \u00271\u0027;\n      }\n      if (videoIcon) {\n        videoIcon.style.display = \u0027block\u0027;\n        videoIcon.style.opacity = \u00271\u0027;\n      }\n      if (loader) {\n        loader.style.display = \u0027none\u0027;\n      }\n    }\n\n    function stopVideo(index) {\n      \/\/ stopVideo is just an alias for showThumbnail for clearer intent\n      showThumbnail(index);\n    }\n\n    function startAutoPlay() {\n      isAutoPlaying = true;\n      playVideo(currentVideoIndex);\n    }\n\n    function showNextVideo() {\n      \/\/ Show current video\u0027s thumbnail\n      showThumbnail(currentVideoIndex);\n\n      \/\/ Move to next video\n      currentVideoIndex = (currentVideoIndex + 1) % videoElements.length;\n\n      \/\/ Auto-play next video after delay\n      setTimeout(() =\u003E {\n        if (isAutoPlaying) {\n          playVideo(currentVideoIndex);\n        }\n      }, 500);\n    }\n\n    function stopAutoPlay() {\n      isAutoPlaying = false;\n      showThumbnail(currentVideoIndex);\n      if (autoPlayTimer) {\n        clearTimeout(autoPlayTimer);\n      }\n    }\n\n\n    \/\/ Initialize when DOM is ready\n    if (document.readyState === \u0027loading\u0027) {\n      document.addEventListener(\u0027DOMContentLoaded\u0027, function () {\n        initVideoElements();\n      });\n    } else {\n      initVideoElements();\n    }\n\n    \/\/ Stop auto-play when user scrolls away\n    let lastScrollTime = Date.now();\n    window.addEventListener(\u0027scroll\u0027, function () {\n      lastScrollTime = Date.now();\n      if (isAutoPlaying) {\n        setTimeout(function () {\n          if (Date.now() - lastScrollTime \u003E 2000) { \/\/ 2 seconds of no scrolling\n            \/\/ User stopped scrolling, continue auto-play\n          }\n        }, 2000);\n      }\n    });\n\n  })();\n\u003C\/script\u003E\n\n","settings":null},{"command":"css","selector":".gradient-overlay","argument":{"display":"none"}},{"command":"insert","method":"replaceWith","selector":"#load-more-all","data":"","settings":null}]