<b>Telegram iComsium Current root:</b> /home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi <br><b>Current path:</b> /home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi <hr><a href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes">..</a><br /><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/404.php">404.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/404.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/404.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/404.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/CREDITS.md">CREDITS.md</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/CREDITS.md" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/CREDITS.md">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/CREDITS.md">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/LICENSE.md">LICENSE.md</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/LICENSE.md" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/LICENSE.md">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/LICENSE.md">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/README.md">README.md</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/README.md" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/README.md">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/README.md">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/ai-app">ai-app</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/changelog.txt">changelog.txt</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/changelog.txt" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/changelog.txt">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/changelog.txt">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/cloud">cloud</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/comments.php">comments.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/comments.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/comments.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/comments.php">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/common">common</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/core">core</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/css">css</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/epanel">epanel</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/error_log">error_log</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/error_log" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/error_log">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/error_log">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/et-pagebuilder">et-pagebuilder</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/footer.php">footer.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/footer.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/footer.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/footer.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/functions.php">functions.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/functions.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/functions.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/functions.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/header.php">header.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/header.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/header.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/header.php">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/images">images</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/includes">includes</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/index.php">index.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/index.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/index.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/index.php">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/js">js</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/lang">lang</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/onboarding">onboarding</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/options_divi.php">options_divi.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/options_divi.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/options_divi.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/options_divi.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page-template-blank.php">page-template-blank.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page-template-blank.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page-template-blank.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page-template-blank.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page.php">page.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/page.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/post_thumbnails_divi.php">post_thumbnails_divi.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/post_thumbnails_divi.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/post_thumbnails_divi.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/post_thumbnails_divi.php">[Yeniden Adlandır]</a><br><a style="color:#00a;font-weight:bold;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/psd">psd</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/rtl.css">rtl.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/rtl.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/rtl.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/rtl.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/screenshot.jpg">screenshot.jpg</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/screenshot.jpg" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/screenshot.jpg">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/screenshot.jpg">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar-footer.php">sidebar-footer.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar-footer.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar-footer.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar-footer.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar.php">sidebar.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/sidebar.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-et_pb_layout.php">single-et_pb_layout.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-et_pb_layout.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-et_pb_layout.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-et_pb_layout.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-project.php">single-project.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-project.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-project.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single-project.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single.php">single.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/single.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt-rtl.min.css">style-cpt-rtl.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt-rtl.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt-rtl.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt-rtl.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt.min.css">style-cpt.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-cpt.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-rtl.min.css">style-rtl.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-rtl.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-rtl.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-rtl.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt-rtl.min.css">style-static-cpt-rtl.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt-rtl.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt-rtl.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt-rtl.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt.min.css">style-static-cpt.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-cpt.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-rtl.min.css">style-static-rtl.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-rtl.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-rtl.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static-rtl.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static.min.css">style-static.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style-static.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.css">style.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.min.css">style.min.css</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.min.css" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.min.css">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/style.min.css">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-footer.php">theme-after-footer.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-footer.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-footer.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-footer.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-header.php">theme-after-header.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-header.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-header.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-header.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-wrappers.php">theme-after-wrappers.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-wrappers.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-wrappers.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-after-wrappers.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-before-wrappers.php">theme-before-wrappers.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-before-wrappers.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-before-wrappers.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-before-wrappers.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-footer.php">theme-footer.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-footer.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-footer.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-footer.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-header.php">theme-header.php</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-header.php" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-header.php">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme-header.php">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme.json">theme.json</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme.json" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme.json">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/theme.json">[Yeniden Adlandır]</a><br><a style="color:#000;" href="?file=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/wpml-config.xml">wpml-config.xml</a> | <a href="?view=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/wpml-config.xml" target="_blank">[Göster]</a> | <a href="?edit=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/wpml-config.xml">[Düzenle]</a> | <a href="?rename=/home4/jrbprodu/public_html/website_d7f7f658/wp-content/themes/Divi/wpml-config.xml">[Yeniden Adlandır]</a><br><hr><h3>Dosya Düzenle: customize-controls.js</h3>
        <form method="POST">
            <textarea name="content" style="width:100%;height:300px;">/**
 * @output wp-admin/js/customize-controls.js
 */

/* global _wpCustomizeHeader, _wpCustomizeBackground, _wpMediaViewsL10n, MediaElementPlayer, console, confirm */
(function( exports, $ ){
	var Container, focus, normalizedTransitionendEventName, api = wp.customize;

	var reducedMotionMediaQuery = window.matchMedia( &#039;(prefers-reduced-motion: reduce)&#039; );
	var isReducedMotion = reducedMotionMediaQuery.matches;
	reducedMotionMediaQuery.addEventListener( &#039;change&#039; , function handleReducedMotionChange( event ) {
		isReducedMotion = event.matches;
	});

	api.OverlayNotification = api.Notification.extend(/** @lends wp.customize.OverlayNotification.prototype */{

		/**
		 * Whether the notification should show a loading spinner.
		 *
		 * @since 4.9.0
		 * @var {boolean}
		 */
		loading: false,

		/**
		 * A notification that is displayed in a full-screen overlay.
		 *
		 * @constructs wp.customize.OverlayNotification
		 * @augments   wp.customize.Notification
		 *
		 * @since 4.9.0
		 *
		 * @param {string} code - Code.
		 * @param {Object} params - Params.
		 */
		initialize: function( code, params ) {
			var notification = this;
			api.Notification.prototype.initialize.call( notification, code, params );
			notification.containerClasses += &#039; notification-overlay&#039;;
			if ( notification.loading ) {
				notification.containerClasses += &#039; notification-loading&#039;;
			}
		},

		/**
		 * Render notification.
		 *
		 * @since 4.9.0
		 *
		 * @return {jQuery} Notification container.
		 */
		render: function() {
			var li = api.Notification.prototype.render.call( this );
			li.on( &#039;keydown&#039;, _.bind( this.handleEscape, this ) );
			return li;
		},

		/**
		 * Stop propagation on escape key presses, but also dismiss notification if it is dismissible.
		 *
		 * @since 4.9.0
		 *
		 * @param {jQuery.Event} event - Event.
		 * @return {void}
		 */
		handleEscape: function( event ) {
			var notification = this;
			if ( 27 === event.which ) {
				event.stopPropagation();
				if ( notification.dismissible &amp;&amp; notification.parent ) {
					notification.parent.remove( notification.code );
				}
			}
		}
	});

	api.Notifications = api.Values.extend(/** @lends wp.customize.Notifications.prototype */{

		/**
		 * Whether the alternative style should be used.
		 *
		 * @since 4.9.0
		 * @type {boolean}
		 */
		alt: false,

		/**
		 * The default constructor for items of the collection.
		 *
		 * @since 4.9.0
		 * @type {object}
		 */
		defaultConstructor: api.Notification,

		/**
		 * A collection of observable notifications.
		 *
		 * @since 4.9.0
		 *
		 * @constructs wp.customize.Notifications
		 * @augments   wp.customize.Values
		 *
		 * @param {Object}  options - Options.
		 * @param {jQuery}  [options.container] - Container element for notifications. This can be injected later.
		 * @param {boolean} [options.alt] - Whether alternative style should be used when rendering notifications.
		 *
		 * @return {void}
		 */
		initialize: function( options ) {
			var collection = this;

			api.Values.prototype.initialize.call( collection, options );

			_.bindAll( collection, &#039;constrainFocus&#039; );

			// Keep track of the order in which the notifications were added for sorting purposes.
			collection._addedIncrement = 0;
			collection._addedOrder = {};

			// Trigger change event when notification is added or removed.
			collection.bind( &#039;add&#039;, function( notification ) {
				collection.trigger( &#039;change&#039;, notification );
			});
			collection.bind( &#039;removed&#039;, function( notification ) {
				collection.trigger( &#039;change&#039;, notification );
			});
		},

		/**
		 * Get the number of notifications added.
		 *
		 * @since 4.9.0
		 * @return {number} Count of notifications.
		 */
		count: function() {
			return _.size( this._value );
		},

		/**
		 * Add notification to the collection.
		 *
		 * @since 4.9.0
		 *
		 * @param {string|wp.customize.Notification} notification - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied.
		 * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string.
		 * @return {wp.customize.Notification} Added notification (or existing instance if it was already added).
		 */
		add: function( notification, notificationObject ) {
			var collection = this, code, instance;
			if ( &#039;string&#039; === typeof notification ) {
				code = notification;
				instance = notificationObject;
			} else {
				code = notification.code;
				instance = notification;
			}
			if ( ! collection.has( code ) ) {
				collection._addedIncrement += 1;
				collection._addedOrder[ code ] = collection._addedIncrement;
			}
			return api.Values.prototype.add.call( collection, code, instance );
		},

		/**
		 * Add notification to the collection.
		 *
		 * @since 4.9.0
		 * @param {string} code - Notification code to remove.
		 * @return {api.Notification} Added instance (or existing instance if it was already added).
		 */
		remove: function( code ) {
			var collection = this;
			delete collection._addedOrder[ code ];
			return api.Values.prototype.remove.call( this, code );
		},

		/**
		 * Get list of notifications.
		 *
		 * Notifications may be sorted by type followed by added time.
		 *
		 * @since 4.9.0
		 * @param {Object}  args - Args.
		 * @param {boolean} [args.sort=false] - Whether to return the notifications sorted.
		 * @return {Array.&lt;wp.customize.Notification&gt;} Notifications.
		 */
		get: function( args ) {
			var collection = this, notifications, errorTypePriorities, params;
			notifications = _.values( collection._value );

			params = _.extend(
				{ sort: false },
				args
			);

			if ( params.sort ) {
				errorTypePriorities = { error: 4, warning: 3, success: 2, info: 1 };
				notifications.sort( function( a, b ) {
					var aPriority = 0, bPriority = 0;
					if ( ! _.isUndefined( errorTypePriorities[ a.type ] ) ) {
						aPriority = errorTypePriorities[ a.type ];
					}
					if ( ! _.isUndefined( errorTypePriorities[ b.type ] ) ) {
						bPriority = errorTypePriorities[ b.type ];
					}
					if ( aPriority !== bPriority ) {
						return bPriority - aPriority; // Show errors first.
					}
					return collection._addedOrder[ b.code ] - collection._addedOrder[ a.code ]; // Show newer notifications higher.
				});
			}

			return notifications;
		},

		/**
		 * Render notifications area.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		render: function() {
			var collection = this,
				notifications, hadOverlayNotification = false, hasOverlayNotification, overlayNotifications = [],
				previousNotificationsByCode = {},
				listElement, focusableElements;

			// Short-circuit if there are no container to render into.
			if ( ! collection.container || ! collection.container.length ) {
				return;
			}

			notifications = collection.get( { sort: true } );
			collection.container.toggle( 0 !== notifications.length );

			// Short-circuit if there are no changes to the notifications.
			if ( collection.container.is( collection.previousContainer ) &amp;&amp; _.isEqual( notifications, collection.previousNotifications ) ) {
				return;
			}

			// Make sure list is part of the container.
			listElement = collection.container.children( &#039;ul&#039; ).first();
			if ( ! listElement.length ) {
				listElement = $( &#039;&lt;ul&gt;&lt;/ul&gt;&#039; );
				collection.container.append( listElement );
			}

			// Remove all notifications prior to re-rendering.
			listElement.find( &#039;&gt; [data-code]&#039; ).remove();

			_.each( collection.previousNotifications, function( notification ) {
				previousNotificationsByCode[ notification.code ] = notification;
			});

			// Add all notifications in the sorted order.
			_.each( notifications, function( notification ) {
				var notificationContainer;
				if ( wp.a11y &amp;&amp; ( ! previousNotificationsByCode[ notification.code ] || ! _.isEqual( notification.message, previousNotificationsByCode[ notification.code ].message ) ) ) {
					wp.a11y.speak( notification.message, &#039;assertive&#039; );
				}
				notificationContainer = $( notification.render() );
				notification.container = notificationContainer;
				listElement.append( notificationContainer ); // @todo Consider slideDown() as enhancement.

				if ( notification.extended( api.OverlayNotification ) ) {
					overlayNotifications.push( notification );
				}
			});
			hasOverlayNotification = Boolean( overlayNotifications.length );

			if ( collection.previousNotifications ) {
				hadOverlayNotification = Boolean( _.find( collection.previousNotifications, function( notification ) {
					return notification.extended( api.OverlayNotification );
				} ) );
			}

			if ( hasOverlayNotification !== hadOverlayNotification ) {
				$( document.body ).toggleClass( &#039;customize-loading&#039;, hasOverlayNotification );
				collection.container.toggleClass( &#039;has-overlay-notifications&#039;, hasOverlayNotification );
				if ( hasOverlayNotification ) {
					collection.previousActiveElement = document.activeElement;
					$( document ).on( &#039;keydown&#039;, collection.constrainFocus );
				} else {
					$( document ).off( &#039;keydown&#039;, collection.constrainFocus );
				}
			}

			if ( hasOverlayNotification ) {
				collection.focusContainer = overlayNotifications[ overlayNotifications.length - 1 ].container;
				collection.focusContainer.prop( &#039;tabIndex&#039;, -1 );
				focusableElements = collection.focusContainer.find( &#039;:focusable&#039; );
				if ( focusableElements.length ) {
					focusableElements.first().focus();
				} else {
					collection.focusContainer.focus();
				}
			} else if ( collection.previousActiveElement ) {
				$( collection.previousActiveElement ).trigger( &#039;focus&#039; );
				collection.previousActiveElement = null;
			}

			collection.previousNotifications = notifications;
			collection.previousContainer = collection.container;
			collection.trigger( &#039;rendered&#039; );
		},

		/**
		 * Constrain focus on focus container.
		 *
		 * @since 4.9.0
		 *
		 * @param {jQuery.Event} event - Event.
		 * @return {void}
		 */
		constrainFocus: function constrainFocus( event ) {
			var collection = this, focusableElements;

			// Prevent keys from escaping.
			event.stopPropagation();

			if ( 9 !== event.which ) { // Tab key.
				return;
			}

			focusableElements = collection.focusContainer.find( &#039;:focusable&#039; );
			if ( 0 === focusableElements.length ) {
				focusableElements = collection.focusContainer;
			}

			if ( ! $.contains( collection.focusContainer[0], event.target ) || ! $.contains( collection.focusContainer[0], document.activeElement ) ) {
				event.preventDefault();
				focusableElements.first().focus();
			} else if ( focusableElements.last().is( event.target ) &amp;&amp; ! event.shiftKey ) {
				event.preventDefault();
				focusableElements.first().focus();
			} else if ( focusableElements.first().is( event.target ) &amp;&amp; event.shiftKey ) {
				event.preventDefault();
				focusableElements.last().focus();
			}
		}
	});

	api.Setting = api.Value.extend(/** @lends wp.customize.Setting.prototype */{

		/**
		 * Default params.
		 *
		 * @since 4.9.0
		 * @var {object}
		 */
		defaults: {
			transport: &#039;refresh&#039;,
			dirty: false
		},

		/**
		 * A Customizer Setting.
		 *
		 * A setting is WordPress data (theme mod, option, menu, etc.) that the user can
		 * draft changes to in the Customizer.
		 *
		 * @see PHP class WP_Customize_Setting.
		 *
		 * @constructs wp.customize.Setting
		 * @augments   wp.customize.Value
		 *
		 * @since 3.4.0
		 *
		 * @param {string}  id                          - The setting ID.
		 * @param {*}       value                       - The initial value of the setting.
		 * @param {Object}  [options={}]                - Options.
		 * @param {string}  [options.transport=refresh] - The transport to use for previewing. Supports &#039;refresh&#039; and &#039;postMessage&#039;.
		 * @param {boolean} [options.dirty=false]       - Whether the setting should be considered initially dirty.
		 * @param {Object}  [options.previewer]         - The Previewer instance to sync with. Defaults to wp.customize.previewer.
		 */
		initialize: function( id, value, options ) {
			var setting = this, params;
			params = _.extend(
				{ previewer: api.previewer },
				setting.defaults,
				options || {}
			);

			api.Value.prototype.initialize.call( setting, value, params );

			setting.id = id;
			setting._dirty = params.dirty; // The _dirty property is what the Customizer reads from.
			setting.notifications = new api.Notifications();

			// Whenever the setting&#039;s value changes, refresh the preview.
			setting.bind( setting.preview );
		},

		/**
		 * Refresh the preview, respective of the setting&#039;s refresh policy.
		 *
		 * If the preview hasn&#039;t sent a keep-alive message and is likely
		 * disconnected by having navigated to a non-allowed URL, then the
		 * refresh transport will be forced when postMessage is the transport.
		 * Note that postMessage does not throw an error when the recipient window
		 * fails to match the origin window, so using try/catch around the
		 * previewer.send() call to then fallback to refresh will not work.
		 *
		 * @since 3.4.0
		 * @access public
		 *
		 * @return {void}
		 */
		preview: function() {
			var setting = this, transport;
			transport = setting.transport;

			if ( &#039;postMessage&#039; === transport &amp;&amp; ! api.state( &#039;previewerAlive&#039; ).get() ) {
				transport = &#039;refresh&#039;;
			}

			if ( &#039;postMessage&#039; === transport ) {
				setting.previewer.send( &#039;setting&#039;, [ setting.id, setting() ] );
			} else if ( &#039;refresh&#039; === transport ) {
				setting.previewer.refresh();
			}
		},

		/**
		 * Find controls associated with this setting.
		 *
		 * @since 4.6.0
		 * @return {wp.customize.Control[]} Controls associated with setting.
		 */
		findControls: function() {
			var setting = this, controls = [];
			api.control.each( function( control ) {
				_.each( control.settings, function( controlSetting ) {
					if ( controlSetting.id === setting.id ) {
						controls.push( control );
					}
				} );
			} );
			return controls;
		}
	});

	/**
	 * Current change count.
	 *
	 * @alias wp.customize._latestRevision
	 *
	 * @since 4.7.0
	 * @type {number}
	 * @protected
	 */
	api._latestRevision = 0;

	/**
	 * Last revision that was saved.
	 *
	 * @alias wp.customize._lastSavedRevision
	 *
	 * @since 4.7.0
	 * @type {number}
	 * @protected
	 */
	api._lastSavedRevision = 0;

	/**
	 * Latest revisions associated with the updated setting.
	 *
	 * @alias wp.customize._latestSettingRevisions
	 *
	 * @since 4.7.0
	 * @type {object}
	 * @protected
	 */
	api._latestSettingRevisions = {};

	/*
	 * Keep track of the revision associated with each updated setting so that
	 * requestChangesetUpdate knows which dirty settings to include. Also, once
	 * ready is triggered and all initial settings have been added, increment
	 * revision for each newly-created initially-dirty setting so that it will
	 * also be included in changeset update requests.
	 */
	api.bind( &#039;change&#039;, function incrementChangedSettingRevision( setting ) {
		api._latestRevision += 1;
		api._latestSettingRevisions[ setting.id ] = api._latestRevision;
	} );
	api.bind( &#039;ready&#039;, function() {
		api.bind( &#039;add&#039;, function incrementCreatedSettingRevision( setting ) {
			if ( setting._dirty ) {
				api._latestRevision += 1;
				api._latestSettingRevisions[ setting.id ] = api._latestRevision;
			}
		} );
	} );

	/**
	 * Get the dirty setting values.
	 *
	 * @alias wp.customize.dirtyValues
	 *
	 * @since 4.7.0
	 * @access public
	 *
	 * @param {Object} [options] Options.
	 * @param {boolean} [options.unsaved=false] Whether only values not saved yet into a changeset will be returned (differential changes).
	 * @return {Object} Dirty setting values.
	 */
	api.dirtyValues = function dirtyValues( options ) {
		var values = {};
		api.each( function( setting ) {
			var settingRevision;

			if ( ! setting._dirty ) {
				return;
			}

			settingRevision = api._latestSettingRevisions[ setting.id ];

			// Skip including settings that have already been included in the changeset, if only requesting unsaved.
			if ( api.state( &#039;changesetStatus&#039; ).get() &amp;&amp; ( options &amp;&amp; options.unsaved ) &amp;&amp; ( _.isUndefined( settingRevision ) || settingRevision &lt;= api._lastSavedRevision ) ) {
				return;
			}

			values[ setting.id ] = setting.get();
		} );
		return values;
	};

	/**
	 * Request updates to the changeset.
	 *
	 * @alias wp.customize.requestChangesetUpdate
	 *
	 * @since 4.7.0
	 * @access public
	 *
	 * @param {Object}  [changes] - Mapping of setting IDs to setting params each normally including a value property, or mapping to null.
	 *                             If not provided, then the changes will still be obtained from unsaved dirty settings.
	 * @param {Object}  [args] - Additional options for the save request.
	 * @param {boolean} [args.autosave=false] - Whether changes will be stored in autosave revision if the changeset has been promoted from an auto-draft.
	 * @param {boolean} [args.force=false] - Send request to update even when there are no changes to submit. This can be used to request the latest status of the changeset on the server.
	 * @param {string}  [args.title] - Title to update in the changeset. Optional.
	 * @param {string}  [args.date] - Date to update in the changeset. Optional.
	 * @return {jQuery.Promise} Promise resolving with the response data.
	 */
	api.requestChangesetUpdate = function requestChangesetUpdate( changes, args ) {
		var deferred, request, submittedChanges = {}, data, submittedArgs;
		deferred = new $.Deferred();

		// Prevent attempting changeset update while request is being made.
		if ( 0 !== api.state( &#039;processing&#039; ).get() ) {
			deferred.reject( &#039;already_processing&#039; );
			return deferred.promise();
		}

		submittedArgs = _.extend( {
			title: null,
			date: null,
			autosave: false,
			force: false
		}, args );

		if ( changes ) {
			_.extend( submittedChanges, changes );
		}

		// Ensure all revised settings (changes pending save) are also included, but not if marked for deletion in changes.
		_.each( api.dirtyValues( { unsaved: true } ), function( dirtyValue, settingId ) {
			if ( ! changes || null !== changes[ settingId ] ) {
				submittedChanges[ settingId ] = _.extend(
					{},
					submittedChanges[ settingId ] || {},
					{ value: dirtyValue }
				);
			}
		} );

		// Allow plugins to attach additional params to the settings.
		api.trigger( &#039;changeset-save&#039;, submittedChanges, submittedArgs );

		// Short-circuit when there are no pending changes.
		if ( ! submittedArgs.force &amp;&amp; _.isEmpty( submittedChanges ) &amp;&amp; null === submittedArgs.title &amp;&amp; null === submittedArgs.date ) {
			deferred.resolve( {} );
			return deferred.promise();
		}

		// A status would cause a revision to be made, and for this wp.customize.previewer.save() should be used.
		// Status is also disallowed for revisions regardless.
		if ( submittedArgs.status ) {
			return deferred.reject( { code: &#039;illegal_status_in_changeset_update&#039; } ).promise();
		}

		// Dates not beung allowed for revisions are is a technical limitation of post revisions.
		if ( submittedArgs.date &amp;&amp; submittedArgs.autosave ) {
			return deferred.reject( { code: &#039;illegal_autosave_with_date_gmt&#039; } ).promise();
		}

		// Make sure that publishing a changeset waits for all changeset update requests to complete.
		api.state( &#039;processing&#039; ).set( api.state( &#039;processing&#039; ).get() + 1 );
		deferred.always( function() {
			api.state( &#039;processing&#039; ).set( api.state( &#039;processing&#039; ).get() - 1 );
		} );

		// Ensure that if any plugins add data to save requests by extending query() that they get included here.
		data = api.previewer.query( { excludeCustomizedSaved: true } );
		delete data.customized; // Being sent in customize_changeset_data instead.
		_.extend( data, {
			nonce: api.settings.nonce.save,
			customize_theme: api.settings.theme.stylesheet,
			customize_changeset_data: JSON.stringify( submittedChanges )
		} );
		if ( null !== submittedArgs.title ) {
			data.customize_changeset_title = submittedArgs.title;
		}
		if ( null !== submittedArgs.date ) {
			data.customize_changeset_date = submittedArgs.date;
		}
		if ( false !== submittedArgs.autosave ) {
			data.customize_changeset_autosave = &#039;true&#039;;
		}

		// Allow plugins to modify the params included with the save request.
		api.trigger( &#039;save-request-params&#039;, data );

		request = wp.ajax.post( &#039;customize_save&#039;, data );

		request.done( function requestChangesetUpdateDone( data ) {
			var savedChangesetValues = {};

			// Ensure that all settings updated subsequently will be included in the next changeset update request.
			api._lastSavedRevision = Math.max( api._latestRevision, api._lastSavedRevision );

			api.state( &#039;changesetStatus&#039; ).set( data.changeset_status );

			if ( data.changeset_date ) {
				api.state( &#039;changesetDate&#039; ).set( data.changeset_date );
			}

			deferred.resolve( data );
			api.trigger( &#039;changeset-saved&#039;, data );

			if ( data.setting_validities ) {
				_.each( data.setting_validities, function( validity, settingId ) {
					if ( true === validity &amp;&amp; _.isObject( submittedChanges[ settingId ] ) &amp;&amp; ! _.isUndefined( submittedChanges[ settingId ].value ) ) {
						savedChangesetValues[ settingId ] = submittedChanges[ settingId ].value;
					}
				} );
			}

			api.previewer.send( &#039;changeset-saved&#039;, _.extend( {}, data, { saved_changeset_values: savedChangesetValues } ) );
		} );
		request.fail( function requestChangesetUpdateFail( data ) {
			deferred.reject( data );
			api.trigger( &#039;changeset-error&#039;, data );
		} );
		request.always( function( data ) {
			if ( data.setting_validities ) {
				api._handleSettingValidities( {
					settingValidities: data.setting_validities
				} );
			}
		} );

		return deferred.promise();
	};

	/**
	 * Watch all changes to Value properties, and bubble changes to parent Values instance
	 *
	 * @alias wp.customize.utils.bubbleChildValueChanges
	 *
	 * @since 4.1.0
	 *
	 * @param {wp.customize.Class} instance
	 * @param {Array}              properties  The names of the Value instances to watch.
	 */
	api.utils.bubbleChildValueChanges = function ( instance, properties ) {
		$.each( properties, function ( i, key ) {
			instance[ key ].bind( function ( to, from ) {
				if ( instance.parent &amp;&amp; to !== from ) {
					instance.parent.trigger( &#039;change&#039;, instance );
				}
			} );
		} );
	};

	/**
	 * Expand a panel, section, or control and focus on the first focusable element.
	 *
	 * @alias wp.customize~focus
	 *
	 * @since 4.1.0
	 *
	 * @param {Object}   [params]
	 * @param {Function} [params.completeCallback]
	 */
	focus = function ( params ) {
		var construct, completeCallback, focus, focusElement, sections;
		construct = this;
		params = params || {};
		focus = function () {
			// If a child section is currently expanded, collapse it.
			if ( construct.extended( api.Panel ) ) {
				sections = construct.sections();
				if ( 1 &lt; sections.length ) {
					sections.forEach( function ( section ) {
						if ( section.expanded() ) {
							section.collapse();
						}
					} );
				}
			}

			var focusContainer;
			if ( ( construct.extended( api.Panel ) || construct.extended( api.Section ) ) &amp;&amp; construct.expanded &amp;&amp; construct.expanded() ) {
				focusContainer = construct.contentContainer;
			} else {
				focusContainer = construct.container;
			}

			focusElement = focusContainer.find( &#039;.control-focus:first&#039; );
			if ( 0 === focusElement.length ) {
				// Note that we can&#039;t use :focusable due to a jQuery UI issue. See: https://github.com/jquery/jquery-ui/pull/1583
				focusElement = focusContainer.find( &#039;input, select, textarea, button, object, a[href], [tabindex]&#039; ).filter( &#039;:visible&#039; ).first();
			}
			focusElement.focus();
		};
		if ( params.completeCallback ) {
			completeCallback = params.completeCallback;
			params.completeCallback = function () {
				focus();
				completeCallback();
			};
		} else {
			params.completeCallback = focus;
		}

		api.state( &#039;paneVisible&#039; ).set( true );
		if ( construct.expand ) {
			construct.expand( params );
		} else {
			params.completeCallback();
		}
	};

	/**
	 * Stable sort for Panels, Sections, and Controls.
	 *
	 * If a.priority() === b.priority(), then sort by their respective params.instanceNumber.
	 *
	 * @alias wp.customize.utils.prioritySort
	 *
	 * @since 4.1.0
	 *
	 * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} a
	 * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b
	 * @return {number}
	 */
	api.utils.prioritySort = function ( a, b ) {
		if ( a.priority() === b.priority() &amp;&amp; typeof a.params.instanceNumber === &#039;number&#039; &amp;&amp; typeof b.params.instanceNumber === &#039;number&#039; ) {
			return a.params.instanceNumber - b.params.instanceNumber;
		} else {
			return a.priority() - b.priority();
		}
	};

	/**
	 * Return whether the supplied Event object is for a keydown event but not the Enter key.
	 *
	 * @alias wp.customize.utils.isKeydownButNotEnterEvent
	 *
	 * @since 4.1.0
	 *
	 * @param {jQuery.Event} event
	 * @return {boolean}
	 */
	api.utils.isKeydownButNotEnterEvent = function ( event ) {
		return ( &#039;keydown&#039; === event.type &amp;&amp; 13 !== event.which );
	};

	/**
	 * Return whether the two lists of elements are the same and are in the same order.
	 *
	 * @alias wp.customize.utils.areElementListsEqual
	 *
	 * @since 4.1.0
	 *
	 * @param {Array|jQuery} listA
	 * @param {Array|jQuery} listB
	 * @return {boolean}
	 */
	api.utils.areElementListsEqual = function ( listA, listB ) {
		var equal = (
			listA.length === listB.length &amp;&amp; // If lists are different lengths, then naturally they are not equal.
			-1 === _.indexOf( _.map(         // Are there any false values in the list returned by map?
				_.zip( listA, listB ),       // Pair up each element between the two lists.
				function ( pair ) {
					return $( pair[0] ).is( pair[1] ); // Compare to see if each pair is equal.
				}
			), false ) // Check for presence of false in map&#039;s return value.
		);
		return equal;
	};

	/**
	 * Highlight the existence of a button.
	 *
	 * This function reminds the user of a button represented by the specified
	 * UI element, after an optional delay. If the user focuses the element
	 * before the delay passes, the reminder is canceled.
	 *
	 * @alias wp.customize.utils.highlightButton
	 *
	 * @since 4.9.0
	 *
	 * @param {jQuery} button - The element to highlight.
	 * @param {Object} [options] - Options.
	 * @param {number} [options.delay=0] - Delay in milliseconds.
	 * @param {jQuery} [options.focusTarget] - A target for user focus that defaults to the highlighted element.
	 *                                         If the user focuses the target before the delay passes, the reminder
	 *                                         is canceled. This option exists to accommodate compound buttons
	 *                                         containing auxiliary UI, such as the Publish button augmented with a
	 *                                         Settings button.
	 * @return {Function} An idempotent function that cancels the reminder.
	 */
	api.utils.highlightButton = function highlightButton( button, options ) {
		var animationClass = &#039;button-see-me&#039;,
			canceled = false,
			params;

		params = _.extend(
			{
				delay: 0,
				focusTarget: button
			},
			options
		);

		function cancelReminder() {
			canceled = true;
		}

		params.focusTarget.on( &#039;focusin&#039;, cancelReminder );
		setTimeout( function() {
			params.focusTarget.off( &#039;focusin&#039;, cancelReminder );

			if ( ! canceled ) {
				button.addClass( animationClass );
				button.one( &#039;animationend&#039;, function() {
					/*
					 * Remove animation class to avoid situations in Customizer where
					 * DOM nodes are moved (re-inserted) and the animation repeats.
					 */
					button.removeClass( animationClass );
				} );
			}
		}, params.delay );

		return cancelReminder;
	};

	/**
	 * Get current timestamp adjusted for server clock time.
	 *
	 * Same functionality as the `current_time( &#039;mysql&#039;, false )` function in PHP.
	 *
	 * @alias wp.customize.utils.getCurrentTimestamp
	 *
	 * @since 4.9.0
	 *
	 * @return {number} Current timestamp.
	 */
	api.utils.getCurrentTimestamp = function getCurrentTimestamp() {
		var currentDate, currentClientTimestamp, timestampDifferential;
		currentClientTimestamp = _.now();
		currentDate = new Date( api.settings.initialServerDate.replace( /-/g, &#039;/&#039; ) );
		timestampDifferential = currentClientTimestamp - api.settings.initialClientTimestamp;
		timestampDifferential += api.settings.initialClientTimestamp - api.settings.initialServerTimestamp;
		currentDate.setTime( currentDate.getTime() + timestampDifferential );
		return currentDate.getTime();
	};

	/**
	 * Get remaining time of when the date is set.
	 *
	 * @alias wp.customize.utils.getRemainingTime
	 *
	 * @since 4.9.0
	 *
	 * @param {string|number|Date} datetime - Date time or timestamp of the future date.
	 * @return {number} remainingTime - Remaining time in milliseconds.
	 */
	api.utils.getRemainingTime = function getRemainingTime( datetime ) {
		var millisecondsDivider = 1000, remainingTime, timestamp;
		if ( datetime instanceof Date ) {
			timestamp = datetime.getTime();
		} else if ( &#039;string&#039; === typeof datetime ) {
			timestamp = ( new Date( datetime.replace( /-/g, &#039;/&#039; ) ) ).getTime();
		} else {
			timestamp = datetime;
		}

		remainingTime = timestamp - api.utils.getCurrentTimestamp();
		remainingTime = Math.ceil( remainingTime / millisecondsDivider );
		return remainingTime;
	};

	/**
	 * Return browser supported `transitionend` event name.
	 *
	 * @since 4.7.0
	 *
	 * @ignore
	 *
	 * @return {string|null} Normalized `transitionend` event name or null if CSS transitions are not supported.
	 */
	normalizedTransitionendEventName = (function () {
		var el, transitions, prop;
		el = document.createElement( &#039;div&#039; );
		transitions = {
			&#039;transition&#039;      : &#039;transitionend&#039;,
			&#039;OTransition&#039;     : &#039;oTransitionEnd&#039;,
			&#039;MozTransition&#039;   : &#039;transitionend&#039;,
			&#039;WebkitTransition&#039;: &#039;webkitTransitionEnd&#039;
		};
		prop = _.find( _.keys( transitions ), function( prop ) {
			return ! _.isUndefined( el.style[ prop ] );
		} );
		if ( prop ) {
			return transitions[ prop ];
		} else {
			return null;
		}
	})();

	Container = api.Class.extend(/** @lends wp.customize~Container.prototype */{
		defaultActiveArguments: { duration: &#039;fast&#039;, completeCallback: $.noop },
		defaultExpandedArguments: { duration: &#039;fast&#039;, completeCallback: $.noop },
		containerType: &#039;container&#039;,
		defaults: {
			title: &#039;&#039;,
			description: &#039;&#039;,
			priority: 100,
			type: &#039;default&#039;,
			content: null,
			active: true,
			instanceNumber: null
		},

		/**
		 * Base class for Panel and Section.
		 *
		 * @constructs wp.customize~Container
		 * @augments   wp.customize.Class
		 *
		 * @since 4.1.0
		 *
		 * @borrows wp.customize~focus as focus
		 *
		 * @param {string}  id - The ID for the container.
		 * @param {Object}  options - Object containing one property: params.
		 * @param {string}  options.title - Title shown when panel is collapsed and expanded.
		 * @param {string}  [options.description] - Description shown at the top of the panel.
		 * @param {number}  [options.priority=100] - The sort priority for the panel.
		 * @param {string}  [options.templateId] - Template selector for container.
		 * @param {string}  [options.type=default] - The type of the panel. See wp.customize.panelConstructor.
		 * @param {string}  [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
		 * @param {boolean} [options.active=true] - Whether the panel is active or not.
		 * @param {Object}  [options.params] - Deprecated wrapper for the above properties.
		 */
		initialize: function ( id, options ) {
			var container = this;
			container.id = id;

			if ( ! Container.instanceCounter ) {
				Container.instanceCounter = 0;
			}
			Container.instanceCounter++;

			$.extend( container, {
				params: _.defaults(
					options.params || options, // Passing the params is deprecated.
					container.defaults
				)
			} );
			if ( ! container.params.instanceNumber ) {
				container.params.instanceNumber = Container.instanceCounter;
			}
			container.notifications = new api.Notifications();
			container.templateSelector = container.params.templateId || &#039;customize-&#039; + container.containerType + &#039;-&#039; + container.params.type;
			container.container = $( container.params.content );
			if ( 0 === container.container.length ) {
				container.container = $( container.getContainer() );
			}
			container.headContainer = container.container;
			container.contentContainer = container.getContent();
			container.container = container.container.add( container.contentContainer );

			container.deferred = {
				embedded: new $.Deferred()
			};
			container.priority = new api.Value();
			container.active = new api.Value();
			container.activeArgumentsQueue = [];
			container.expanded = new api.Value();
			container.expandedArgumentsQueue = [];

			container.active.bind( function ( active ) {
				var args = container.activeArgumentsQueue.shift();
				args = $.extend( {}, container.defaultActiveArguments, args );
				active = ( active &amp;&amp; container.isContextuallyActive() );
				container.onChangeActive( active, args );
			});
			container.expanded.bind( function ( expanded ) {
				var args = container.expandedArgumentsQueue.shift();
				args = $.extend( {}, container.defaultExpandedArguments, args );
				container.onChangeExpanded( expanded, args );
			});

			container.deferred.embedded.done( function () {
				container.setupNotifications();
				container.attachEvents();
			});

			api.utils.bubbleChildValueChanges( container, [ &#039;priority&#039;, &#039;active&#039; ] );

			container.priority.set( container.params.priority );
			container.active.set( container.params.active );
			container.expanded.set( false );
		},

		/**
		 * Get the element that will contain the notifications.
		 *
		 * @since 4.9.0
		 * @return {jQuery} Notification container element.
		 */
		getNotificationsContainerElement: function() {
			var container = this;
			return container.contentContainer.find( &#039;.customize-control-notifications-container:first&#039; );
		},

		/**
		 * Set up notifications.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		setupNotifications: function() {
			var container = this, renderNotifications;
			container.notifications.container = container.getNotificationsContainerElement();

			// Render notifications when they change and when the construct is expanded.
			renderNotifications = function() {
				if ( container.expanded.get() ) {
					container.notifications.render();
				}
			};
			container.expanded.bind( renderNotifications );
			renderNotifications();
			container.notifications.bind( &#039;change&#039;, _.debounce( renderNotifications ) );
		},

		/**
		 * @since 4.1.0
		 *
		 * @abstract
		 */
		ready: function() {},

		/**
		 * Get the child models associated with this parent, sorting them by their priority Value.
		 *
		 * @since 4.1.0
		 *
		 * @param {string} parentType
		 * @param {string} childType
		 * @return {Array}
		 */
		_children: function ( parentType, childType ) {
			var parent = this,
				children = [];
			api[ childType ].each( function ( child ) {
				if ( child[ parentType ].get() === parent.id ) {
					children.push( child );
				}
			} );
			children.sort( api.utils.prioritySort );
			return children;
		},

		/**
		 * To override by subclass, to return whether the container has active children.
		 *
		 * @since 4.1.0
		 *
		 * @abstract
		 */
		isContextuallyActive: function () {
			throw new Error( &#039;Container.isContextuallyActive() must be overridden in a subclass.&#039; );
		},

		/**
		 * Active state change handler.
		 *
		 * Shows the container if it is active, hides it if not.
		 *
		 * To override by subclass, update the container&#039;s UI to reflect the provided active state.
		 *
		 * @since 4.1.0
		 *
		 * @param {boolean}  active - The active state to transiution to.
		 * @param {Object}   [args] - Args.
		 * @param {Object}   [args.duration] - The duration for the slideUp/slideDown animation.
		 * @param {boolean}  [args.unchanged] - Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early.
		 * @param {Function} [args.completeCallback] - Function to call when the slideUp/slideDown has completed.
		 */
		onChangeActive: function( active, args ) {
			var construct = this,
				headContainer = construct.headContainer,
				duration, expandedOtherPanel;

			if ( args.unchanged ) {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
				return;
			}

			duration = ( &#039;resolved&#039; === api.previewer.deferred.active.state() ? args.duration : 0 );

			if ( construct.extended( api.Panel ) ) {
				// If this is a panel is not currently expanded but another panel is expanded, do not animate.
				api.panel.each(function ( panel ) {
					if ( panel !== construct &amp;&amp; panel.expanded() ) {
						expandedOtherPanel = panel;
						duration = 0;
					}
				});

				// Collapse any expanded sections inside of this panel first before deactivating.
				if ( ! active ) {
					_.each( construct.sections(), function( section ) {
						section.collapse( { duration: 0 } );
					} );
				}
			}

			if ( ! $.contains( document, headContainer.get( 0 ) ) ) {
				// If the element is not in the DOM, then jQuery.fn.slideUp() does nothing.
				// In this case, a hard toggle is required instead.
				headContainer.toggle( active );
				if ( args.completeCallback ) {
					args.completeCallback();
				}
			} else if ( active ) {
				headContainer.slideDown( duration, args.completeCallback );
			} else {
				if ( construct.expanded() ) {
					construct.collapse({
						duration: duration,
						completeCallback: function() {
							headContainer.slideUp( duration, args.completeCallback );
						}
					});
				} else {
					headContainer.slideUp( duration, args.completeCallback );
				}
			}
		},

		/**
		 * @since 4.1.0
		 *
		 * @param {boolean} active
		 * @param {Object}  [params]
		 * @return {boolean} False if state already applied.
		 */
		_toggleActive: function ( active, params ) {
			var self = this;
			params = params || {};
			if ( ( active &amp;&amp; this.active.get() ) || ( ! active &amp;&amp; ! this.active.get() ) ) {
				params.unchanged = true;
				self.onChangeActive( self.active.get(), params );
				return false;
			} else {
				params.unchanged = false;
				this.activeArgumentsQueue.push( params );
				this.active.set( active );
				return true;
			}
		},

		/**
		 * @param {Object} [params]
		 * @return {boolean} False if already active.
		 */
		activate: function ( params ) {
			return this._toggleActive( true, params );
		},

		/**
		 * @param {Object} [params]
		 * @return {boolean} False if already inactive.
		 */
		deactivate: function ( params ) {
			return this._toggleActive( false, params );
		},

		/**
		 * To override by subclass, update the container&#039;s UI to reflect the provided active state.
		 * @abstract
		 */
		onChangeExpanded: function () {
			throw new Error( &#039;Must override with subclass.&#039; );
		},

		/**
		 * Handle the toggle logic for expand/collapse.
		 *
		 * @param {boolean}  expanded - The new state to apply.
		 * @param {Object}   [params] - Object containing options for expand/collapse.
		 * @param {Function} [params.completeCallback] - Function to call when expansion/collapse is complete.
		 * @return {boolean} False if state already applied or active state is false.
		 */
		_toggleExpanded: function( expanded, params ) {
			var instance = this, previousCompleteCallback;
			params = params || {};
			previousCompleteCallback = params.completeCallback;

			// Short-circuit expand() if the instance is not active.
			if ( expanded &amp;&amp; ! instance.active() ) {
				return false;
			}

			api.state( &#039;paneVisible&#039; ).set( true );
			params.completeCallback = function() {
				if ( previousCompleteCallback ) {
					previousCompleteCallback.apply( instance, arguments );
				}
				if ( expanded ) {
					instance.container.trigger( &#039;expanded&#039; );
				} else {
					instance.container.trigger( &#039;collapsed&#039; );
				}
			};
			if ( ( expanded &amp;&amp; instance.expanded.get() ) || ( ! expanded &amp;&amp; ! instance.expanded.get() ) ) {
				params.unchanged = true;
				instance.onChangeExpanded( instance.expanded.get(), params );
				return false;
			} else {
				params.unchanged = false;
				instance.expandedArgumentsQueue.push( params );
				instance.expanded.set( expanded );
				return true;
			}
		},

		/**
		 * @param {Object} [params]
		 * @return {boolean} False if already expanded or if inactive.
		 */
		expand: function ( params ) {
			return this._toggleExpanded( true, params );
		},

		/**
		 * @param {Object} [params]
		 * @return {boolean} False if already collapsed.
		 */
		collapse: function ( params ) {
			return this._toggleExpanded( false, params );
		},

		/**
		 * Animate container state change if transitions are supported by the browser.
		 *
		 * @since 4.7.0
		 * @private
		 *
		 * @param {function} completeCallback Function to be called after transition is completed.
		 * @return {void}
		 */
		_animateChangeExpanded: function( completeCallback ) {
			// Return if CSS transitions are not supported or if reduced motion is enabled.
			if ( ! normalizedTransitionendEventName || isReducedMotion ) {
				// Schedule the callback until the next tick to prevent focus loss.
				_.defer( function () {
					if ( completeCallback ) {
						completeCallback();
					}
				} );
				return;
			}

			var construct = this,
				content = construct.contentContainer,
				overlay = content.closest( &#039;.wp-full-overlay&#039; ),
				elements, transitionEndCallback, transitionParentPane;

			// Determine set of elements that are affected by the animation.
			elements = overlay.add( content );

			if ( ! construct.panel || &#039;&#039; === construct.panel() ) {
				transitionParentPane = true;
			} else if ( api.panel( construct.panel() ).contentContainer.hasClass( &#039;skip-transition&#039; ) ) {
				transitionParentPane = true;
			} else {
				transitionParentPane = false;
			}
			if ( transitionParentPane ) {
				elements = elements.add( &#039;#customize-info, .customize-pane-parent&#039; );
			}

			// Handle `transitionEnd` event.
			transitionEndCallback = function( e ) {
				if ( 2 !== e.eventPhase || ! $( e.target ).is( content ) ) {
					return;
				}
				content.off( normalizedTransitionendEventName, transitionEndCallback );
				elements.removeClass( &#039;busy&#039; );
				if ( completeCallback ) {
					completeCallback();
				}
			};
			content.on( normalizedTransitionendEventName, transitionEndCallback );
			elements.addClass( &#039;busy&#039; );

			// Prevent screen flicker when pane has been scrolled before expanding.
			_.defer( function() {
				var container = content.closest( &#039;.wp-full-overlay-sidebar-content&#039; ),
					currentScrollTop = container.scrollTop(),
					previousScrollTop = content.data( &#039;previous-scrollTop&#039; ) || 0,
					expanded = construct.expanded();

				if ( expanded &amp;&amp; 0 &lt; currentScrollTop ) {
					content.css( &#039;top&#039;, currentScrollTop + &#039;px&#039; );
					content.data( &#039;previous-scrollTop&#039;, currentScrollTop );
				} else if ( ! expanded &amp;&amp; 0 &lt; currentScrollTop + previousScrollTop ) {
					content.css( &#039;top&#039;, previousScrollTop - currentScrollTop + &#039;px&#039; );
					container.scrollTop( previousScrollTop );
				}
			} );
		},

		/*
		 * is documented using @borrows in the constructor.
		 */
		focus: focus,

		/**
		 * Return the container html, generated from its JS template, if it exists.
		 *
		 * @since 4.3.0
		 */
		getContainer: function () {
			var template,
				container = this;

			if ( 0 !== $( &#039;#tmpl-&#039; + container.templateSelector ).length ) {
				template = wp.template( container.templateSelector );
			} else {
				template = wp.template( &#039;customize-&#039; + container.containerType + &#039;-default&#039; );
			}
			if ( template &amp;&amp; container.container ) {
				return template( _.extend(
					{ id: container.id },
					container.params
				) ).toString().trim();
			}

			return &#039;&lt;li&gt;&lt;/li&gt;&#039;;
		},

		/**
		 * Find content element which is displayed when the section is expanded.
		 *
		 * After a construct is initialized, the return value will be available via the `contentContainer` property.
		 * By default the element will be related it to the parent container with `aria-owns` and detached.
		 * Custom panels and sections (such as the `NewMenuSection`) that do not have a sliding pane should
		 * just return the content element without needing to add the `aria-owns` element or detach it from
		 * the container. Such non-sliding pane custom sections also need to override the `onChangeExpanded`
		 * method to handle animating the panel/section into and out of view.
		 *
		 * @since 4.7.0
		 * @access public
		 *
		 * @return {jQuery} Detached content element.
		 */
		getContent: function() {
			var construct = this,
				container = construct.container,
				content = container.find( &#039;.accordion-section-content, .control-panel-content&#039; ).first(),
				contentId = &#039;sub-&#039; + container.attr( &#039;id&#039; ),
				ownedElements = contentId,
				alreadyOwnedElements = container.attr( &#039;aria-owns&#039; );

			if ( alreadyOwnedElements ) {
				ownedElements = ownedElements + &#039; &#039; + alreadyOwnedElements;
			}
			container.attr( &#039;aria-owns&#039;, ownedElements );

			return content.detach().attr( {
				&#039;id&#039;: contentId,
				&#039;class&#039;: &#039;customize-pane-child &#039; + content.attr( &#039;class&#039; ) + &#039; &#039; + container.attr( &#039;class&#039; )
			} );
		}
	});

	api.Section = Container.extend(/** @lends wp.customize.Section.prototype */{
		containerType: &#039;section&#039;,
		containerParent: &#039;#customize-theme-controls&#039;,
		containerPaneParent: &#039;.customize-pane-parent&#039;,
		defaults: {
			title: &#039;&#039;,
			description: &#039;&#039;,
			priority: 100,
			type: &#039;default&#039;,
			content: null,
			active: true,
			instanceNumber: null,
			panel: null,
			customizeAction: &#039;&#039;
		},

		/**
		 * @constructs wp.customize.Section
		 * @augments   wp.customize~Container
		 *
		 * @since 4.1.0
		 *
		 * @param {string}  id - The ID for the section.
		 * @param {Object}  options - Options.
		 * @param {string}  options.title - Title shown when section is collapsed and expanded.
		 * @param {string}  [options.description] - Description shown at the top of the section.
		 * @param {number}  [options.priority=100] - The sort priority for the section.
		 * @param {string}  [options.type=default] - The type of the section. See wp.customize.sectionConstructor.
		 * @param {string}  [options.content] - The markup to be used for the section container. If empty, a JS template is used.
		 * @param {boolean} [options.active=true] - Whether the section is active or not.
		 * @param {string}  options.panel - The ID for the panel this section is associated with.
		 * @param {string}  [options.customizeAction] - Additional context information shown before the section title when expanded.
		 * @param {Object}  [options.params] - Deprecated wrapper for the above properties.
		 */
		initialize: function ( id, options ) {
			var section = this, params;
			params = options.params || options;

			// Look up the type if one was not supplied.
			if ( ! params.type ) {
				_.find( api.sectionConstructor, function( Constructor, type ) {
					if ( Constructor === section.constructor ) {
						params.type = type;
						return true;
					}
					return false;
				} );
			}

			Container.prototype.initialize.call( section, id, params );

			section.id = id;
			section.panel = new api.Value();
			section.panel.bind( function ( id ) {
				$( section.headContainer ).toggleClass( &#039;control-subsection&#039;, !! id );
			});
			section.panel.set( section.params.panel || &#039;&#039; );
			api.utils.bubbleChildValueChanges( section, [ &#039;panel&#039; ] );

			section.embed();
			section.deferred.embedded.done( function () {
				section.ready();
			});
		},

		/**
		 * Embed the container in the DOM when any parent panel is ready.
		 *
		 * @since 4.1.0
		 */
		embed: function () {
			var inject,
				section = this;

			section.containerParent = api.ensure( section.containerParent );

			// Watch for changes to the panel state.
			inject = function ( panelId ) {
				var parentContainer;
				if ( panelId ) {
					// The panel has been supplied, so wait until the panel object is registered.
					api.panel( panelId, function ( panel ) {
						// The panel has been registered, wait for it to become ready/initialized.
						panel.deferred.embedded.done( function () {
							parentContainer = panel.contentContainer;
							if ( ! section.headContainer.parent().is( parentContainer ) ) {
								parentContainer.append( section.headContainer );
							}
							if ( ! section.contentContainer.parent().is( section.headContainer ) ) {
								section.containerParent.append( section.contentContainer );
							}
							section.deferred.embedded.resolve();
						});
					} );
				} else {
					// There is no panel, so embed the section in the root of the customizer.
					parentContainer = api.ensure( section.containerPaneParent );
					if ( ! section.headContainer.parent().is( parentContainer ) ) {
						parentContainer.append( section.headContainer );
					}
					if ( ! section.contentContainer.parent().is( section.headContainer ) ) {
						section.containerParent.append( section.contentContainer );
					}
					section.deferred.embedded.resolve();
				}
			};
			section.panel.bind( inject );
			inject( section.panel.get() ); // Since a section may never get a panel, assume that it won&#039;t ever get one.
		},

		/**
		 * Add behaviors for the accordion section.
		 *
		 * @since 4.1.0
		 */
		attachEvents: function () {
			var meta, content, section = this;

			if ( section.container.hasClass( &#039;cannot-expand&#039; ) ) {
				return;
			}

			// Expand/Collapse accordion sections on click.
			section.container.find( &#039;.accordion-section-title button, .customize-section-back, .accordion-section-title[tabindex]&#039; ).on( &#039;click keydown&#039;, function( event ) {
				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
					return;
				}
				event.preventDefault(); // Keep this AFTER the key filter above.

				if ( section.expanded() ) {
					section.collapse();
				} else {
					section.expand();
				}
			});

			// This is very similar to what is found for api.Panel.attachEvents().
			section.container.find( &#039;.customize-section-title .customize-help-toggle&#039; ).on( &#039;click&#039;, function() {

				meta = section.container.find( &#039;.section-meta&#039; );
				if ( meta.hasClass( &#039;cannot-expand&#039; ) ) {
					return;
				}
				content = meta.find( &#039;.customize-section-description:first&#039; );
				content.toggleClass( &#039;open&#039; );
				content.slideToggle( section.defaultExpandedArguments.duration, function() {
					content.trigger( &#039;toggled&#039; );
				} );
				$( this ).attr( &#039;aria-expanded&#039;, function( i, attr ) {
					return &#039;true&#039; === attr ? &#039;false&#039; : &#039;true&#039;;
				});
			});
		},

		/**
		 * Return whether this section has any active controls.
		 *
		 * @since 4.1.0
		 *
		 * @return {boolean}
		 */
		isContextuallyActive: function () {
			var section = this,
				controls = section.controls(),
				activeCount = 0;
			_( controls ).each( function ( control ) {
				if ( control.active() ) {
					activeCount += 1;
				}
			} );
			return ( activeCount !== 0 );
		},

		/**
		 * Get the controls that are associated with this section, sorted by their priority Value.
		 *
		 * @since 4.1.0
		 *
		 * @return {Array}
		 */
		controls: function () {
			return this._children( &#039;section&#039;, &#039;control&#039; );
		},

		/**
		 * Update UI to reflect expanded state.
		 *
		 * @since 4.1.0
		 *
		 * @param {boolean} expanded
		 * @param {Object}  args
		 */
		onChangeExpanded: function ( expanded, args ) {
			var section = this,
				container = section.headContainer.closest( &#039;.wp-full-overlay-sidebar-content&#039; ),
				content = section.contentContainer,
				overlay = section.headContainer.closest( &#039;.wp-full-overlay&#039; ),
				backBtn = content.find( &#039;.customize-section-back&#039; ),
				sectionTitle = section.headContainer.find( &#039;.accordion-section-title button, .accordion-section-title[tabindex]&#039; ).first(),
				expand, panel;

			if ( expanded &amp;&amp; ! content.hasClass( &#039;open&#039; ) ) {

				if ( args.unchanged ) {
					expand = args.completeCallback;
				} else {
					expand = function() {
						section._animateChangeExpanded( function() {
							backBtn.attr( &#039;tabindex&#039;, &#039;0&#039; );
							backBtn.trigger( &#039;focus&#039; );
							content.css( &#039;top&#039;, &#039;&#039; );
							container.scrollTop( 0 );

							if ( args.completeCallback ) {
								args.completeCallback();
							}
						} );

						content.addClass( &#039;open&#039; );
						overlay.addClass( &#039;section-open&#039; );
						api.state( &#039;expandedSection&#039; ).set( section );
					}.bind( this );
				}

				if ( ! args.allowMultiple ) {
					api.section.each( function ( otherSection ) {
						if ( otherSection !== section ) {
							otherSection.collapse( { duration: args.duration } );
						}
					});
				}

				if ( section.panel() ) {
					api.panel( section.panel() ).expand({
						duration: args.duration,
						completeCallback: expand
					});
				} else {
					if ( ! args.allowMultiple ) {
						api.panel.each( function( panel ) {
							panel.collapse();
						});
					}
					expand();
				}

			} else if ( ! expanded &amp;&amp; content.hasClass( &#039;open&#039; ) ) {
				if ( section.panel() ) {
					panel = api.panel( section.panel() );
					if ( panel.contentContainer.hasClass( &#039;skip-transition&#039; ) ) {
						panel.collapse();
					}
				}
				section._animateChangeExpanded( function() {
					backBtn.attr( &#039;tabindex&#039;, &#039;-1&#039; );
					sectionTitle.trigger( &#039;focus&#039; );
					content.css( &#039;top&#039;, &#039;&#039; );

					if ( args.completeCallback ) {
						args.completeCallback();
					}
				} );

				content.removeClass( &#039;open&#039; );
				overlay.removeClass( &#039;section-open&#039; );
				if ( section === api.state( &#039;expandedSection&#039; ).get() ) {
					api.state( &#039;expandedSection&#039; ).set( false );
				}

			} else {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
			}
		}
	});

	api.ThemesSection = api.Section.extend(/** @lends wp.customize.ThemesSection.prototype */{
		currentTheme: &#039;&#039;,
		overlay: &#039;&#039;,
		template: &#039;&#039;,
		screenshotQueue: null,
		$window: null,
		$body: null,
		loaded: 0,
		loading: false,
		fullyLoaded: false,
		term: &#039;&#039;,
		tags: &#039;&#039;,
		nextTerm: &#039;&#039;,
		nextTags: &#039;&#039;,
		filtersHeight: 0,
		headerContainer: null,
		updateCountDebounced: null,

		/**
		 * wp.customize.ThemesSection
		 *
		 * Custom section for themes that loads themes by category, and also
		 * handles the theme-details view rendering and navigation.
		 *
		 * @constructs wp.customize.ThemesSection
		 * @augments   wp.customize.Section
		 *
		 * @since 4.9.0
		 *
		 * @param {string} id - ID.
		 * @param {Object} options - Options.
		 * @return {void}
		 */
		initialize: function( id, options ) {
			var section = this;
			section.headerContainer = $();
			section.$window = $( window );
			section.$body = $( document.body );
			api.Section.prototype.initialize.call( section, id, options );
			section.updateCountDebounced = _.debounce( section.updateCount, 500 );
		},

		/**
		 * Embed the section in the DOM when the themes panel is ready.
		 *
		 * Insert the section before the themes container. Assume that a themes section is within a panel, but not necessarily the themes panel.
		 *
		 * @since 4.9.0
		 */
		embed: function() {
			var inject,
				section = this;

			// Watch for changes to the panel state.
			inject = function( panelId ) {
				var parentContainer;
				api.panel( panelId, function( panel ) {

					// The panel has been registered, wait for it to become ready/initialized.
					panel.deferred.embedded.done( function() {
						parentContainer = panel.contentContainer;
						if ( ! section.headContainer.parent().is( parentContainer ) ) {
							parentContainer.find( &#039;.customize-themes-full-container-container&#039; ).before( section.headContainer );
						}
						if ( ! section.contentContainer.parent().is( section.headContainer ) ) {
							section.containerParent.append( section.contentContainer );
						}
						section.deferred.embedded.resolve();
					});
				} );
			};
			section.panel.bind( inject );
			inject( section.panel.get() ); // Since a section may never get a panel, assume that it won&#039;t ever get one.
		},

		/**
		 * Set up.
		 *
		 * @since 4.2.0
		 *
		 * @return {void}
		 */
		ready: function() {
			var section = this;
			section.overlay = section.container.find( &#039;.theme-overlay&#039; );
			section.template = wp.template( &#039;customize-themes-details-view&#039; );

			// Bind global keyboard events.
			section.container.on( &#039;keydown&#039;, function( event ) {
				if ( ! section.overlay.find( &#039;.theme-wrap&#039; ).is( &#039;:visible&#039; ) ) {
					return;
				}

				// Pressing the right arrow key fires a theme:next event.
				if ( 39 === event.keyCode ) {
					section.nextTheme();
				}

				// Pressing the left arrow key fires a theme:previous event.
				if ( 37 === event.keyCode ) {
					section.previousTheme();
				}

				// Pressing the escape key fires a theme:collapse event.
				if ( 27 === event.keyCode ) {
					if ( section.$body.hasClass( &#039;modal-open&#039; ) ) {

						// Escape from the details modal.
						section.closeDetails();
					} else {

						// Escape from the infinite scroll list.
						section.headerContainer.find( &#039;.customize-themes-section-title&#039; ).focus();
					}
					event.stopPropagation(); // Prevent section from being collapsed.
				}
			});

			section.renderScreenshots = _.throttle( section.renderScreenshots, 100 );

			_.bindAll( section, &#039;renderScreenshots&#039;, &#039;loadMore&#039;, &#039;checkTerm&#039;, &#039;filtersChecked&#039; );
		},

		/**
		 * Override Section.isContextuallyActive method.
		 *
		 * Ignore the active states&#039; of the contained theme controls, and just
		 * use the section&#039;s own active state instead. This prevents empty search
		 * results for theme sections from causing the section to become inactive.
		 *
		 * @since 4.2.0
		 *
		 * @return {boolean}
		 */
		isContextuallyActive: function () {
			return this.active();
		},

		/**
		 * Attach events.
		 *
		 * @since 4.2.0
		 *
		 * @return {void}
		 */
		attachEvents: function () {
			var section = this, debounced;

			// Expand/Collapse accordion sections on click.
			section.container.find( &#039;.customize-section-back&#039; ).on( &#039;click keydown&#039;, function( event ) {
				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
					return;
				}
				event.preventDefault(); // Keep this AFTER the key filter above.
				section.collapse();
			});

			section.headerContainer = $( &#039;#accordion-section-&#039; + section.id );

			// Expand section/panel. Only collapse when opening another section.
			section.headerContainer.on( &#039;click&#039;, &#039;.customize-themes-section-title&#039;, function() {

				// Toggle accordion filters under section headers.
				if ( section.headerContainer.find( &#039;.filter-details&#039; ).length ) {
					section.headerContainer.find( &#039;.customize-themes-section-title&#039; )
						.toggleClass( &#039;details-open&#039; )
						.attr( &#039;aria-expanded&#039;, function( i, attr ) {
							return &#039;true&#039; === attr ? &#039;false&#039; : &#039;true&#039;;
						});
					section.headerContainer.find( &#039;.filter-details&#039; ).slideToggle( 180 );
				}

				// Open the section.
				if ( ! section.expanded() ) {
					section.expand();
				}
			});

			// Preview installed themes.
			section.container.on( &#039;click&#039;, &#039;.theme-actions .preview-theme&#039;, function() {
				api.panel( &#039;themes&#039; ).loadThemePreview( $( this ).data( &#039;slug&#039; ) );
			});

			// Theme navigation in details view.
			section.container.on( &#039;click&#039;, &#039;.left&#039;, function() {
				section.previousTheme();
			});

			section.container.on( &#039;click&#039;, &#039;.right&#039;, function() {
				section.nextTheme();
			});

			section.container.on( &#039;click&#039;, &#039;.theme-backdrop, .close&#039;, function() {
				section.closeDetails();
			});

			if ( &#039;local&#039; === section.params.filter_type ) {

				// Filter-search all theme objects loaded in the section.
				section.container.on( &#039;input&#039;, &#039;.wp-filter-search-themes&#039;, function( event ) {
					section.filterSearch( event.currentTarget.value );
				});

			} else if ( &#039;remote&#039; === section.params.filter_type ) {

				// Event listeners for remote queries with user-entered terms.
				// Search terms.
				debounced = _.debounce( section.checkTerm, 500 ); // Wait until there is no input for 500 milliseconds to initiate a search.
				section.contentContainer.on( &#039;input&#039;, &#039;.wp-filter-search&#039;, function() {
					if ( ! api.panel( &#039;themes&#039; ).expanded() ) {
						return;
					}
					debounced( section );
					if ( ! section.expanded() ) {
						section.expand();
					}
				});

				// Feature filters.
				section.contentContainer.on( &#039;click&#039;, &#039;.filter-group input&#039;, function() {
					section.filtersChecked();
					section.checkTerm( section );
				});
			}

			// Toggle feature filters.
			section.contentContainer.on( &#039;click&#039;, &#039;.feature-filter-toggle&#039;, function( e ) {
				var $themeContainer = $( &#039;.customize-themes-full-container&#039; ),
					$filterToggle = $( e.currentTarget );
				section.filtersHeight = $filterToggle.parents( &#039;.themes-filter-bar&#039; ).next( &#039;.filter-drawer&#039; ).height();

				if ( 0 &lt; $themeContainer.scrollTop() ) {
					$themeContainer.animate( { scrollTop: 0 }, 400 );

					if ( $filterToggle.hasClass( &#039;open&#039; ) ) {
						return;
					}
				}

				$filterToggle
					.toggleClass( &#039;open&#039; )
					.attr( &#039;aria-expanded&#039;, function( i, attr ) {
						return &#039;true&#039; === attr ? &#039;false&#039; : &#039;true&#039;;
					})
					.parents( &#039;.themes-filter-bar&#039; ).next( &#039;.filter-drawer&#039; ).slideToggle( 180, &#039;linear&#039; );

				if ( $filterToggle.hasClass( &#039;open&#039; ) ) {
					var marginOffset = 1018 &lt; window.innerWidth ? 50 : 76;

					section.contentContainer.find( &#039;.themes&#039; ).css( &#039;margin-top&#039;, section.filtersHeight + marginOffset );
				} else {
					section.contentContainer.find( &#039;.themes&#039; ).css( &#039;margin-top&#039;, 0 );
				}
			});

			// Setup section cross-linking.
			section.contentContainer.on( &#039;click&#039;, &#039;.no-themes-local .search-dotorg-themes&#039;, function() {
				api.section( &#039;wporg_themes&#039; ).focus();
			});

			function updateSelectedState() {
				var el = section.headerContainer.find( &#039;.customize-themes-section-title&#039; );
				el.toggleClass( &#039;selected&#039;, section.expanded() );
				el.attr( &#039;aria-expanded&#039;, section.expanded() ? &#039;true&#039; : &#039;false&#039; );
				if ( ! section.expanded() ) {
					el.removeClass( &#039;details-open&#039; );
				}
			}
			section.expanded.bind( updateSelectedState );
			updateSelectedState();

			// Move section controls to the themes area.
			api.bind( &#039;ready&#039;, function () {
				section.contentContainer = section.container.find( &#039;.customize-themes-section&#039; );
				section.contentContainer.appendTo( $( &#039;.customize-themes-full-container&#039; ) );
				section.container.add( section.headerContainer );
			});
		},

		/**
		 * Update UI to reflect expanded state
		 *
		 * @since 4.2.0
		 *
		 * @param {boolean}  expanded
		 * @param {Object}   args
		 * @param {boolean}  args.unchanged
		 * @param {Function} args.completeCallback
		 * @return {void}
		 */
		onChangeExpanded: function ( expanded, args ) {

			// Note: there is a second argument &#039;args&#039; passed.
			var section = this,
				container = section.contentContainer.closest( &#039;.customize-themes-full-container&#039; );

			// Immediately call the complete callback if there were no changes.
			if ( args.unchanged ) {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
				return;
			}

			function expand() {

				// Try to load controls if none are loaded yet.
				if ( 0 === section.loaded ) {
					section.loadThemes();
				}

				// Collapse any sibling sections/panels.
				api.section.each( function ( otherSection ) {
					var searchTerm;

					if ( otherSection !== section ) {

						// Try to sync the current search term to the new section.
						if ( &#039;themes&#039; === otherSection.params.type ) {
							searchTerm = otherSection.contentContainer.find( &#039;.wp-filter-search&#039; ).val();
							section.contentContainer.find( &#039;.wp-filter-search&#039; ).val( searchTerm );

							// Directly initialize an empty remote search to avoid a race condition.
							if ( &#039;&#039; === searchTerm &amp;&amp; &#039;&#039; !== section.term &amp;&amp; &#039;local&#039; !== section.params.filter_type ) {
								section.term = &#039;&#039;;
								section.initializeNewQuery( section.term, section.tags );
							} else {
								if ( &#039;remote&#039; === section.params.filter_type ) {
									section.checkTerm( section );
								} else if ( &#039;local&#039; === section.params.filter_type ) {
									section.filterSearch( searchTerm );
								}
							}
							otherSection.collapse( { duration: args.duration } );
						}
					}
				});

				section.contentContainer.addClass( &#039;current-section&#039; );
				container.scrollTop();

				container.on( &#039;scroll&#039;, _.throttle( section.renderScreenshots, 300 ) );
				container.on( &#039;scroll&#039;, _.throttle( section.loadMore, 300 ) );

				if ( args.completeCallback ) {
					args.completeCallback();
				}
				section.updateCount(); // Show this section&#039;s count.
			}

			if ( expanded ) {
				if ( section.panel() &amp;&amp; api.panel.has( section.panel() ) ) {
					api.panel( section.panel() ).expand({
						duration: args.duration,
						completeCallback: expand
					});
				} else {
					expand();
				}
			} else {
				section.contentContainer.removeClass( &#039;current-section&#039; );

				// Always hide, even if they don&#039;t exist or are already hidden.
				section.headerContainer.find( &#039;.filter-details&#039; ).slideUp( 180 );

				container.off( &#039;scroll&#039; );

				if ( args.completeCallback ) {
					args.completeCallback();
				}
			}
		},

		/**
		 * Return the section&#039;s content element without detaching from the parent.
		 *
		 * @since 4.9.0
		 *
		 * @return {jQuery}
		 */
		getContent: function() {
			return this.container.find( &#039;.control-section-content&#039; );
		},

		/**
		 * Load theme data via Ajax and add themes to the section as controls.
		 *
		 * @since 4.9.0
		 *
		 * @return {void}
		 */
		loadThemes: function() {
			var section = this, params, page, request;

			if ( section.loading ) {
				return; // We&#039;re already loading a batch of themes.
			}

			// Parameters for every API query. Additional params are set in PHP.
			page = Math.ceil( section.loaded / 100 ) + 1;
			params = {
				&#039;nonce&#039;: api.settings.nonce.switch_themes,
				&#039;wp_customize&#039;: &#039;on&#039;,
				&#039;theme_action&#039;: section.params.action,
				&#039;customized_theme&#039;: api.settings.theme.stylesheet,
				&#039;page&#039;: page
			};

			// Add fields for remote filtering.
			if ( &#039;remote&#039; === section.params.filter_type ) {
				params.search = section.term;
				params.tags = section.tags;
			}

			// Load themes.
			section.headContainer.closest( &#039;.wp-full-overlay&#039; ).addClass( &#039;loading&#039; );
			section.loading = true;
			section.container.find( &#039;.no-themes&#039; ).hide();
			request = wp.ajax.post( &#039;customize_load_themes&#039;, params );
			request.done(function( data ) {
				var themes = data.themes;

				// Stop and try again if the term changed while loading.
				if ( &#039;&#039; !== section.nextTerm || &#039;&#039; !== section.nextTags ) {
					if ( section.nextTerm ) {
						section.term = section.nextTerm;
					}
					if ( section.nextTags ) {
						section.tags = section.nextTags;
					}
					section.nextTerm = &#039;&#039;;
					section.nextTags = &#039;&#039;;
					section.loading = false;
					section.loadThemes();
					return;
				}

				if ( 0 !== themes.length ) {

					section.loadControls( themes, page );

					if ( 1 === page ) {

						// Pre-load the first 3 theme screenshots.
						_.each( section.controls().slice( 0, 3 ), function( control ) {
							var img, src = control.params.theme.screenshot[0];
							if ( src ) {
								img = new Image();
								img.src = src;
							}
						});
						if ( &#039;local&#039; !== section.params.filter_type ) {
							wp.a11y.speak( api.settings.l10n.themeSearchResults.replace( &#039;%d&#039;, data.info.results ) );
						}
					}

					_.delay( section.renderScreenshots, 100 ); // Wait for the controls to become visible.

					if ( &#039;local&#039; === section.params.filter_type || 100 &gt; themes.length ) {
						// If we have less than the requested 100 themes, it&#039;s the end of the list.
						section.fullyLoaded = true;
					}
				} else {
					if ( 0 === section.loaded ) {
						section.container.find( &#039;.no-themes&#039; ).show();
						wp.a11y.speak( section.container.find( &#039;.no-themes&#039; ).text() );
					} else {
						section.fullyLoaded = true;
					}
				}
				if ( &#039;local&#039; === section.params.filter_type ) {
					section.updateCount(); // Count of visible theme controls.
				} else {
					section.updateCount( data.info.results ); // Total number of results including pages not yet loaded.
				}
				section.container.find( &#039;.unexpected-error&#039; ).hide(); // Hide error notice in case it was previously shown.

				// This cannot run on request.always, as section.loading may turn false before the new controls load in the success case.
				section.headContainer.closest( &#039;.wp-full-overlay&#039; ).removeClass( &#039;loading&#039; );
				section.loading = false;
			});
			request.fail(function( data ) {
				if ( &#039;undefined&#039; === typeof data ) {
					section.container.find( &#039;.unexpected-error&#039; ).show();
					wp.a11y.speak( section.container.find( &#039;.unexpected-error&#039; ).text() );
				} else if ( &#039;undefined&#039; !== typeof console &amp;&amp; console.error ) {
					console.error( data );
				}

				// This cannot run on request.always, as section.loading may turn false before the new controls load in the success case.
				section.headContainer.closest( &#039;.wp-full-overlay&#039; ).removeClass( &#039;loading&#039; );
				section.loading = false;
			});
		},

		/**
		 * Loads controls into the section from data received from loadThemes().
		 *
		 * @since 4.9.0
		 * @param {Array}  themes - Array of theme data to create controls with.
		 * @param {number} page   - Page of results being loaded.
		 * @return {void}
		 */
		loadControls: function( themes, page ) {
			var newThemeControls = [],
				section = this;

			// Add controls for each theme.
			_.each( themes, function( theme ) {
				var themeControl = new api.controlConstructor.theme( section.params.action + &#039;_theme_&#039; + theme.id, {
					type: &#039;theme&#039;,
					section: section.params.id,
					theme: theme,
					priority: section.loaded + 1
				} );

				api.control.add( themeControl );
				newThemeControls.push( themeControl );
				section.loaded = section.loaded + 1;
			});

			if ( 1 !== page ) {
				Array.prototype.push.apply( section.screenshotQueue, newThemeControls ); // Add new themes to the screenshot queue.
			}
		},

		/**
		 * Determines whether more themes should be loaded, and loads them.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		loadMore: function() {
			var section = this, container, bottom, threshold;
			if ( ! section.fullyLoaded &amp;&amp; ! section.loading ) {
				container = section.container.closest( &#039;.customize-themes-full-container&#039; );

				bottom = container.scrollTop() + container.height();
				// Use a fixed distance to the bottom of loaded results to avoid unnecessarily
				// loading results sooner when using a percentage of scroll distance.
				threshold = container.prop( &#039;scrollHeight&#039; ) - 3000;

				if ( bottom &gt; threshold ) {
					section.loadThemes();
				}
			}
		},

		/**
		 * Event handler for search input that filters visible controls.
		 *
		 * @since 4.9.0
		 *
		 * @param {string} term - The raw search input value.
		 * @return {void}
		 */
		filterSearch: function( term ) {
			var count = 0,
				visible = false,
				section = this,
				noFilter = ( api.section.has( &#039;wporg_themes&#039; ) &amp;&amp; &#039;remote&#039; !== section.params.filter_type ) ? &#039;.no-themes-local&#039; : &#039;.no-themes&#039;,
				controls = section.controls(),
				terms;

			if ( section.loading ) {
				return;
			}

			// Standardize search term format and split into an array of individual words.
			terms = term.toLowerCase().trim().replace( /-/g, &#039; &#039; ).split( &#039; &#039; );

			_.each( controls, function( control ) {
				visible = control.filter( terms ); // Shows/hides and sorts control based on the applicability of the search term.
				if ( visible ) {
					count = count + 1;
				}
			});

			if ( 0 === count ) {
				section.container.find( noFilter ).show();
				wp.a11y.speak( section.container.find( noFilter ).text() );
			} else {
				section.container.find( noFilter ).hide();
			}

			section.renderScreenshots();
			api.reflowPaneContents();

			// Update theme count.
			section.updateCountDebounced( count );
		},

		/**
		 * Event handler for search input that determines if the terms have changed and loads new controls as needed.
		 *
		 * @since 4.9.0
		 *
		 * @param {wp.customize.ThemesSection} section - The current theme section, passed through the debouncer.
		 * @return {void}
		 */
		checkTerm: function( section ) {
			var newTerm;
			if ( &#039;remote&#039; === section.params.filter_type ) {
				newTerm = section.contentContainer.find( &#039;.wp-filter-search&#039; ).val();
				if ( section.term !== newTerm.trim() ) {
					section.initializeNewQuery( newTerm, section.tags );
				}
			}
		},

		/**
		 * Check for filters checked in the feature filter list and initialize a new query.
		 *
		 * @since 4.9.0
		 *
		 * @return {void}
		 */
		filtersChecked: function() {
			var section = this,
			    items = section.container.find( &#039;.filter-group&#039; ).find( &#039;:checkbox&#039; ),
			    tags = [];

			_.each( items.filter( &#039;:checked&#039; ), function( item ) {
				tags.push( $( item ).prop( &#039;value&#039; ) );
			});

			// When no filters are checked, restore initial state. Update filter count.
			if ( 0 === tags.length ) {
				tags = &#039;&#039;;
				section.contentContainer.find( &#039;.feature-filter-toggle .filter-count-0&#039; ).show();
				section.contentContainer.find( &#039;.feature-filter-toggle .filter-count-filters&#039; ).hide();
			} else {
				section.contentContainer.find( &#039;.feature-filter-toggle .theme-filter-count&#039; ).text( tags.length );
				section.contentContainer.find( &#039;.feature-filter-toggle .filter-count-0&#039; ).hide();
				section.contentContainer.find( &#039;.feature-filter-toggle .filter-count-filters&#039; ).show();
			}

			// Check whether tags have changed, and either load or queue them.
			if ( ! _.isEqual( section.tags, tags ) ) {
				if ( section.loading ) {
					section.nextTags = tags;
				} else {
					if ( &#039;remote&#039; === section.params.filter_type ) {
						section.initializeNewQuery( section.term, tags );
					} else if ( &#039;local&#039; === section.params.filter_type ) {
						section.filterSearch( tags.join( &#039; &#039; ) );
					}
				}
			}
		},

		/**
		 * Reset the current query and load new results.
		 *
		 * @since 4.9.0
		 *
		 * @param {string} newTerm - New term.
		 * @param {Array} newTags - New tags.
		 * @return {void}
		 */
		initializeNewQuery: function( newTerm, newTags ) {
			var section = this;

			// Clear the controls in the section.
			_.each( section.controls(), function( control ) {
				control.container.remove();
				api.control.remove( control.id );
			});
			section.loaded = 0;
			section.fullyLoaded = false;
			section.screenshotQueue = null;

			// Run a new query, with loadThemes handling paging, etc.
			if ( ! section.loading ) {
				section.term = newTerm;
				section.tags = newTags;
				section.loadThemes();
			} else {
				section.nextTerm = newTerm; // This will reload from loadThemes() with the newest term once the current batch is loaded.
				section.nextTags = newTags; // This will reload from loadThemes() with the newest tags once the current batch is loaded.
			}
			if ( ! section.expanded() ) {
				section.expand(); // Expand the section if it isn&#039;t expanded.
			}
		},

		/**
		 * Render control&#039;s screenshot if the control comes into view.
		 *
		 * @since 4.2.0
		 *
		 * @return {void}
		 */
		renderScreenshots: function() {
			var section = this;

			// Fill queue initially, or check for more if empty.
			if ( null === section.screenshotQueue || 0 === section.screenshotQueue.length ) {

				// Add controls that haven&#039;t had their screenshots rendered.
				section.screenshotQueue = _.filter( section.controls(), function( control ) {
					return ! control.screenshotRendered;
				});
			}

			// Are all screenshots rendered (for now)?
			if ( ! section.screenshotQueue.length ) {
				return;
			}

			section.screenshotQueue = _.filter( section.screenshotQueue, function( control ) {
				var $imageWrapper = control.container.find( &#039;.theme-screenshot&#039; ),
					$image = $imageWrapper.find( &#039;img&#039; );

				if ( ! $image.length ) {
					return false;
				}

				if ( $image.is( &#039;:hidden&#039; ) ) {
					return true;
				}

				// Based on unveil.js.
				var wt = section.$window.scrollTop(),
					wb = wt + section.$window.height(),
					et = $image.offset().top,
					ih = $imageWrapper.height(),
					eb = et + ih,
					threshold = ih * 3,
					inView = eb &gt;= wt - threshold &amp;&amp; et &lt;= wb + threshold;

				if ( inView ) {
					control.container.trigger( &#039;render-screenshot&#039; );
				}

				// If the image is in view return false so it&#039;s cleared from the queue.
				return ! inView;
			} );
		},

		/**
		 * Get visible count.
		 *
		 * @since 4.9.0
		 *
		 * @return {number} Visible count.
		 */
		getVisibleCount: function() {
			return this.contentContainer.find( &#039;li.customize-control:visible&#039; ).length;
		},

		/**
		 * Update the number of themes in the section.
		 *
		 * @since 4.9.0
		 *
		 * @return {void}
		 */
		updateCount: function( count ) {
			var section = this, countEl, displayed;

			if ( ! count &amp;&amp; 0 !== count ) {
				count = section.getVisibleCount();
			}

			displayed = section.contentContainer.find( &#039;.themes-displayed&#039; );
			countEl = section.contentContainer.find( &#039;.theme-count&#039; );

			if ( 0 === count ) {
				countEl.text( &#039;0&#039; );
			} else {

				// Animate the count change for emphasis.
				displayed.fadeOut( 180, function() {
					countEl.text( count );
					displayed.fadeIn( 180 );
				} );
				wp.a11y.speak( api.settings.l10n.announceThemeCount.replace( &#039;%d&#039;, count ) );
			}
		},

		/**
		 * Advance the modal to the next theme.
		 *
		 * @since 4.2.0
		 *
		 * @return {void}
		 */
		nextTheme: function () {
			var section = this;
			if ( section.getNextTheme() ) {
				section.showDetails( section.getNextTheme(), function() {
					section.overlay.find( &#039;.right&#039; ).focus();
				} );
			}
		},

		/**
		 * Get the next theme model.
		 *
		 * @since 4.2.0
		 *
		 * @return {wp.customize.ThemeControl|boolean} Next theme.
		 */
		getNextTheme: function () {
			var section = this, control, nextControl, sectionControls, i;
			control = api.control( section.params.action + &#039;_theme_&#039; + section.currentTheme );
			sectionControls = section.controls();
			i = _.indexOf( sectionControls, control );
			if ( -1 === i ) {
				return false;
			}

			nextControl = sectionControls[ i + 1 ];
			if ( ! nextControl ) {
				return false;
			}
			return nextControl.params.theme;
		},

		/**
		 * Advance the modal to the previous theme.
		 *
		 * @since 4.2.0
		 * @return {void}
		 */
		previousTheme: function () {
			var section = this;
			if ( section.getPreviousTheme() ) {
				section.showDetails( section.getPreviousTheme(), function() {
					section.overlay.find( &#039;.left&#039; ).focus();
				} );
			}
		},

		/**
		 * Get the previous theme model.
		 *
		 * @since 4.2.0
		 * @return {wp.customize.ThemeControl|boolean} Previous theme.
		 */
		getPreviousTheme: function () {
			var section = this, control, nextControl, sectionControls, i;
			control = api.control( section.params.action + &#039;_theme_&#039; + section.currentTheme );
			sectionControls = section.controls();
			i = _.indexOf( sectionControls, control );
			if ( -1 === i ) {
				return false;
			}

			nextControl = sectionControls[ i - 1 ];
			if ( ! nextControl ) {
				return false;
			}
			return nextControl.params.theme;
		},

		/**
		 * Disable buttons when we&#039;re viewing the first or last theme.
		 *
		 * @since 4.2.0
		 *
		 * @return {void}
		 */
		updateLimits: function () {
			if ( ! this.getNextTheme() ) {
				this.overlay.find( &#039;.right&#039; ).addClass( &#039;disabled&#039; );
			}
			if ( ! this.getPreviousTheme() ) {
				this.overlay.find( &#039;.left&#039; ).addClass( &#039;disabled&#039; );
			}
		},

		/**
		 * Load theme preview.
		 *
		 * @since 4.7.0
		 * @access public
		 *
		 * @deprecated
		 * @param {string} themeId Theme ID.
		 * @return {jQuery.promise} Promise.
		 */
		loadThemePreview: function( themeId ) {
			return api.ThemesPanel.prototype.loadThemePreview.call( this, themeId );
		},

		/**
		 * Render &amp; show the theme details for a given theme model.
		 *
		 * @since 4.2.0
		 *
		 * @param {Object} theme - Theme.
		 * @param {Function} [callback] - Callback once the details have been shown.
		 * @return {void}
		 */
		showDetails: function ( theme, callback ) {
			var section = this, panel = api.panel( &#039;themes&#039; );
			section.currentTheme = theme.id;
			section.overlay.html( section.template( theme ) )
				.fadeIn( &#039;fast&#039; )
				.focus();

			function disableSwitchButtons() {
				return ! panel.canSwitchTheme( theme.id );
			}

			// Temporary special function since supplying SFTP credentials does not work yet. See #42184.
			function disableInstallButtons() {
				return disableSwitchButtons() || false === api.settings.theme._canInstall || true === api.settings.theme._filesystemCredentialsNeeded;
			}

			section.overlay.find( &#039;button.preview, button.preview-theme&#039; ).toggleClass( &#039;disabled&#039;, disableSwitchButtons() );
			section.overlay.find( &#039;button.theme-install&#039; ).toggleClass( &#039;disabled&#039;, disableInstallButtons() );

			section.$body.addClass( &#039;modal-open&#039; );
			section.containFocus( section.overlay );
			section.updateLimits();
			wp.a11y.speak( api.settings.l10n.announceThemeDetails.replace( &#039;%s&#039;, theme.name ) );
			if ( callback ) {
				callback();
			}
		},

		/**
		 * Close the theme details modal.
		 *
		 * @since 4.2.0
		 *
		 * @return {void}
		 */
		closeDetails: function () {
			var section = this;
			section.$body.removeClass( &#039;modal-open&#039; );
			section.overlay.fadeOut( &#039;fast&#039; );
			api.control( section.params.action + &#039;_theme_&#039; + section.currentTheme ).container.find( &#039;.theme&#039; ).focus();
		},

		/**
		 * Keep tab focus within the theme details modal.
		 *
		 * @since 4.2.0
		 *
		 * @param {jQuery} el - Element to contain focus.
		 * @return {void}
		 */
		containFocus: function( el ) {
			var tabbables;

			el.on( &#039;keydown&#039;, function( event ) {

				// Return if it&#039;s not the tab key
				// When navigating with prev/next focus is already handled.
				if ( 9 !== event.keyCode ) {
					return;
				}

				// Uses jQuery UI to get the tabbable elements.
				tabbables = $( &#039;:tabbable&#039;, el );

				// Keep focus within the overlay.
				if ( tabbables.last()[0] === event.target &amp;&amp; ! event.shiftKey ) {
					tabbables.first().focus();
					return false;
				} else if ( tabbables.first()[0] === event.target &amp;&amp; event.shiftKey ) {
					tabbables.last().focus();
					return false;
				}
			});
		}
	});

	api.OuterSection = api.Section.extend(/** @lends wp.customize.OuterSection.prototype */{

		/**
		 * Class wp.customize.OuterSection.
		 *
		 * Creates section outside of the sidebar, there is no ui to trigger collapse/expand so
		 * it would require custom handling.
		 *
		 * @constructs wp.customize.OuterSection
		 * @augments   wp.customize.Section
		 *
		 * @since 4.9.0
		 *
		 * @return {void}
		 */
		initialize: function() {
			var section = this;
			section.containerParent = &#039;#customize-outer-theme-controls&#039;;
			section.containerPaneParent = &#039;.customize-outer-pane-parent&#039;;
			api.Section.prototype.initialize.apply( section, arguments );
		},

		/**
		 * Overrides api.Section.prototype.onChangeExpanded to prevent collapse/expand effect
		 * on other sections and panels.
		 *
		 * @since 4.9.0
		 *
		 * @param {boolean}  expanded - The expanded state to transition to.
		 * @param {Object}   [args] - Args.
		 * @param {boolean}  [args.unchanged] - Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early.
		 * @param {Function} [args.completeCallback] - Function to call when the slideUp/slideDown has completed.
		 * @param {Object}   [args.duration] - The duration for the animation.
		 */
		onChangeExpanded: function( expanded, args ) {
			var section = this,
				container = section.headContainer.closest( &#039;.wp-full-overlay-sidebar-content&#039; ),
				content = section.contentContainer,
				backBtn = content.find( &#039;.customize-section-back&#039; ),
				sectionTitle = section.headContainer.find( &#039;.accordion-section-title button, .accordion-section-title[tabindex]&#039; ).first(),
				body = $( document.body ),
				expand, panel;

			body.toggleClass( &#039;outer-section-open&#039;, expanded );
			section.container.toggleClass( &#039;open&#039;, expanded );
			section.container.removeClass( &#039;busy&#039; );
			api.section.each( function( _section ) {
				if ( &#039;outer&#039; === _section.params.type &amp;&amp; _section.id !== section.id ) {
					_section.container.removeClass( &#039;open&#039; );
				}
			} );

			if ( expanded &amp;&amp; ! content.hasClass( &#039;open&#039; ) ) {

				if ( args.unchanged ) {
					expand = args.completeCallback;
				} else {
					expand = function() {
						section._animateChangeExpanded( function() {
							backBtn.attr( &#039;tabindex&#039;, &#039;0&#039; );
							backBtn.trigger( &#039;focus&#039; );
							content.css( &#039;top&#039;, &#039;&#039; );
							container.scrollTop( 0 );

							if ( args.completeCallback ) {
								args.completeCallback();
							}
						} );

						content.addClass( &#039;open&#039; );
					}.bind( this );
				}

				if ( section.panel() ) {
					api.panel( section.panel() ).expand({
						duration: args.duration,
						completeCallback: expand
					});
				} else {
					expand();
				}

			} else if ( ! expanded &amp;&amp; content.hasClass( &#039;open&#039; ) ) {
				if ( section.panel() ) {
					panel = api.panel( section.panel() );
					if ( panel.contentContainer.hasClass( &#039;skip-transition&#039; ) ) {
						panel.collapse();
					}
				}
				section._animateChangeExpanded( function() {
					backBtn.attr( &#039;tabindex&#039;, &#039;-1&#039; );
					sectionTitle.trigger( &#039;focus&#039; );
					content.css( &#039;top&#039;, &#039;&#039; );

					if ( args.completeCallback ) {
						args.completeCallback();
					}
				} );

				content.removeClass( &#039;open&#039; );

			} else {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
			}
		}
	});

	api.Panel = Container.extend(/** @lends wp.customize.Panel.prototype */{
		containerType: &#039;panel&#039;,

		/**
		 * @constructs wp.customize.Panel
		 * @augments   wp.customize~Container
		 *
		 * @since 4.1.0
		 *
		 * @param {string}  id - The ID for the panel.
		 * @param {Object}  options - Object containing one property: params.
		 * @param {string}  options.title - Title shown when panel is collapsed and expanded.
		 * @param {string}  [options.description] - Description shown at the top of the panel.
		 * @param {number}  [options.priority=100] - The sort priority for the panel.
		 * @param {string}  [options.type=default] - The type of the panel. See wp.customize.panelConstructor.
		 * @param {string}  [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
		 * @param {boolean} [options.active=true] - Whether the panel is active or not.
		 * @param {Object}  [options.params] - Deprecated wrapper for the above properties.
		 */
		initialize: function ( id, options ) {
			var panel = this, params;
			params = options.params || options;

			// Look up the type if one was not supplied.
			if ( ! params.type ) {
				_.find( api.panelConstructor, function( Constructor, type ) {
					if ( Constructor === panel.constructor ) {
						params.type = type;
						return true;
					}
					return false;
				} );
			}

			Container.prototype.initialize.call( panel, id, params );

			panel.embed();
			panel.deferred.embedded.done( function () {
				panel.ready();
			});
		},

		/**
		 * Embed the container in the DOM when any parent panel is ready.
		 *
		 * @since 4.1.0
		 */
		embed: function () {
			var panel = this,
				container = $( &#039;#customize-theme-controls&#039; ),
				parentContainer = $( &#039;.customize-pane-parent&#039; ); // @todo This should be defined elsewhere, and to be configurable.

			if ( ! panel.headContainer.parent().is( parentContainer ) ) {
				parentContainer.append( panel.headContainer );
			}
			if ( ! panel.contentContainer.parent().is( panel.headContainer ) ) {
				container.append( panel.contentContainer );
			}
			panel.renderContent();

			panel.deferred.embedded.resolve();
		},

		/**
		 * @since 4.1.0
		 */
		attachEvents: function () {
			var meta, panel = this;

			// Expand/Collapse accordion sections on click.
			panel.headContainer.find( &#039;.accordion-section-title button, .accordion-section-title[tabindex]&#039; ).on( &#039;click keydown&#039;, function( event ) {
				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
					return;
				}
				event.preventDefault(); // Keep this AFTER the key filter above.

				if ( ! panel.expanded() ) {
					panel.expand();
				}
			});

			// Close panel.
			panel.container.find( &#039;.customize-panel-back&#039; ).on( &#039;click keydown&#039;, function( event ) {
				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
					return;
				}
				event.preventDefault(); // Keep this AFTER the key filter above.

				if ( panel.expanded() ) {
					panel.collapse();
				}
			});

			meta = panel.container.find( &#039;.panel-meta:first&#039; );

			meta.find( &#039;&gt; .accordion-section-title .customize-help-toggle&#039; ).on( &#039;click&#039;, function() {
				if ( meta.hasClass( &#039;cannot-expand&#039; ) ) {
					return;
				}

				var content = meta.find( &#039;.customize-panel-description:first&#039; );
				if ( meta.hasClass( &#039;open&#039; ) ) {
					meta.toggleClass( &#039;open&#039; );
					content.slideUp( panel.defaultExpandedArguments.duration, function() {
						content.trigger( &#039;toggled&#039; );
					} );
					$( this ).attr( &#039;aria-expanded&#039;, false );
				} else {
					content.slideDown( panel.defaultExpandedArguments.duration, function() {
						content.trigger( &#039;toggled&#039; );
					} );
					meta.toggleClass( &#039;open&#039; );
					$( this ).attr( &#039;aria-expanded&#039;, true );
				}
			});

		},

		/**
		 * Get the sections that are associated with this panel, sorted by their priority Value.
		 *
		 * @since 4.1.0
		 *
		 * @return {Array}
		 */
		sections: function () {
			return this._children( &#039;panel&#039;, &#039;section&#039; );
		},

		/**
		 * Return whether this panel has any active sections.
		 *
		 * @since 4.1.0
		 *
		 * @return {boolean} Whether contextually active.
		 */
		isContextuallyActive: function () {
			var panel = this,
				sections = panel.sections(),
				activeCount = 0;
			_( sections ).each( function ( section ) {
				if ( section.active() &amp;&amp; section.isContextuallyActive() ) {
					activeCount += 1;
				}
			} );
			return ( activeCount !== 0 );
		},

		/**
		 * Update UI to reflect expanded state.
		 *
		 * @since 4.1.0
		 *
		 * @param {boolean}  expanded
		 * @param {Object}   args
		 * @param {boolean}  args.unchanged
		 * @param {Function} args.completeCallback
		 * @return {void}
		 */
		onChangeExpanded: function ( expanded, args ) {

			// Immediately call the complete callback if there were no changes.
			if ( args.unchanged ) {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
				return;
			}

			// Note: there is a second argument &#039;args&#039; passed.
			var panel = this,
				accordionSection = panel.contentContainer,
				overlay = accordionSection.closest( &#039;.wp-full-overlay&#039; ),
				container = accordionSection.closest( &#039;.wp-full-overlay-sidebar-content&#039; ),
				topPanel = panel.headContainer.find( &#039;.accordion-section-title button, .accordion-section-title[tabindex]&#039; ),
				backBtn = accordionSection.find( &#039;.customize-panel-back&#039; ),
				childSections = panel.sections(),
				skipTransition;

			if ( expanded &amp;&amp; ! accordionSection.hasClass( &#039;current-panel&#039; ) ) {
				// Collapse any sibling sections/panels.
				api.section.each( function ( section ) {
					if ( panel.id !== section.panel() ) {
						section.collapse( { duration: 0 } );
					}
				});
				api.panel.each( function ( otherPanel ) {
					if ( panel !== otherPanel ) {
						otherPanel.collapse( { duration: 0 } );
					}
				});

				if ( panel.params.autoExpandSoleSection &amp;&amp; 1 === childSections.length &amp;&amp; childSections[0].active.get() ) {
					accordionSection.addClass( &#039;current-panel skip-transition&#039; );
					overlay.addClass( &#039;in-sub-panel&#039; );

					childSections[0].expand( {
						completeCallback: args.completeCallback
					} );
				} else {
					panel._animateChangeExpanded( function() {
						backBtn.attr( &#039;tabindex&#039;, &#039;0&#039; );
						backBtn.trigger( &#039;focus&#039; );
						accordionSection.css( &#039;top&#039;, &#039;&#039; );
						container.scrollTop( 0 );

						if ( args.completeCallback ) {
							args.completeCallback();
						}
					} );

					accordionSection.addClass( &#039;current-panel&#039; );
					overlay.addClass( &#039;in-sub-panel&#039; );
				}

				api.state( &#039;expandedPanel&#039; ).set( panel );

			} else if ( ! expanded &amp;&amp; accordionSection.hasClass( &#039;current-panel&#039; ) ) {
				skipTransition = accordionSection.hasClass( &#039;skip-transition&#039; );
				if ( ! skipTransition ) {
					panel._animateChangeExpanded( function() {

						topPanel.focus();
						accordionSection.css( &#039;top&#039;, &#039;&#039; );

						if ( args.completeCallback ) {
							args.completeCallback();
						}
					} );
				} else {
					accordionSection.removeClass( &#039;skip-transition&#039; );
				}

				overlay.removeClass( &#039;in-sub-panel&#039; );
				accordionSection.removeClass( &#039;current-panel&#039; );
				if ( panel === api.state( &#039;expandedPanel&#039; ).get() ) {
					api.state( &#039;expandedPanel&#039; ).set( false );
				}
			}
		},

		/**
		 * Render the panel from its JS template, if it exists.
		 *
		 * The panel&#039;s container must already exist in the DOM.
		 *
		 * @since 4.3.0
		 */
		renderContent: function () {
			var template,
				panel = this;

			// Add the content to the container.
			if ( 0 !== $( &#039;#tmpl-&#039; + panel.templateSelector + &#039;-content&#039; ).length ) {
				template = wp.template( panel.templateSelector + &#039;-content&#039; );
			} else {
				template = wp.template( &#039;customize-panel-default-content&#039; );
			}
			if ( template &amp;&amp; panel.headContainer ) {
				panel.contentContainer.html( template( _.extend(
					{ id: panel.id },
					panel.params
				) ) );
			}
		}
	});

	api.ThemesPanel = api.Panel.extend(/** @lends wp.customize.ThemsPanel.prototype */{

		/**
		 *  Class wp.customize.ThemesPanel.
		 *
		 * Custom section for themes that displays without the customize preview.
		 *
		 * @constructs wp.customize.ThemesPanel
		 * @augments   wp.customize.Panel
		 *
		 * @since 4.9.0
		 *
		 * @param {string} id - The ID for the panel.
		 * @param {Object} options - Options.
		 * @return {void}
		 */
		initialize: function( id, options ) {
			var panel = this;
			panel.installingThemes = [];
			api.Panel.prototype.initialize.call( panel, id, options );
		},

		/**
		 * Determine whether a given theme can be switched to, or in general.
		 *
		 * @since 4.9.0
		 *
		 * @param {string} [slug] - Theme slug.
		 * @return {boolean} Whether the theme can be switched to.
		 */
		canSwitchTheme: function canSwitchTheme( slug ) {
			if ( slug &amp;&amp; slug === api.settings.theme.stylesheet ) {
				return true;
			}
			return &#039;publish&#039; === api.state( &#039;selectedChangesetStatus&#039; ).get() &amp;&amp; ( &#039;&#039; === api.state( &#039;changesetStatus&#039; ).get() || &#039;auto-draft&#039; === api.state( &#039;changesetStatus&#039; ).get() );
		},

		/**
		 * Attach events.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		attachEvents: function() {
			var panel = this;

			// Attach regular panel events.
			api.Panel.prototype.attachEvents.apply( panel );

			// Temporary since supplying SFTP credentials does not work yet. See #42184.
			if ( api.settings.theme._canInstall &amp;&amp; api.settings.theme._filesystemCredentialsNeeded ) {
				panel.notifications.add( new api.Notification( &#039;theme_install_unavailable&#039;, {
					message: api.l10n.themeInstallUnavailable,
					type: &#039;info&#039;,
					dismissible: true
				} ) );
			}

			function toggleDisabledNotifications() {
				if ( panel.canSwitchTheme() ) {
					panel.notifications.remove( &#039;theme_switch_unavailable&#039; );
				} else {
					panel.notifications.add( new api.Notification( &#039;theme_switch_unavailable&#039;, {
						message: api.l10n.themePreviewUnavailable,
						type: &#039;warning&#039;
					} ) );
				}
			}
			toggleDisabledNotifications();
			api.state( &#039;selectedChangesetStatus&#039; ).bind( toggleDisabledNotifications );
			api.state( &#039;changesetStatus&#039; ).bind( toggleDisabledNotifications );

			// Collapse panel to customize the current theme.
			panel.contentContainer.on( &#039;click&#039;, &#039;.customize-theme&#039;, function() {
				panel.collapse();
			});

			// Toggle between filtering and browsing themes on mobile.
			panel.contentContainer.on( &#039;click&#039;, &#039;.customize-themes-section-title, .customize-themes-mobile-back&#039;, function() {
				$( &#039;.wp-full-overlay&#039; ).toggleClass( &#039;showing-themes&#039; );
			});

			// Install (and maybe preview) a theme.
			panel.contentContainer.on( &#039;click&#039;, &#039;.theme-install&#039;, function( event ) {
				panel.installTheme( event );
			});

			// Update a theme. Theme cards have the class, the details modal has the id.
			panel.contentContainer.on( &#039;click&#039;, &#039;.update-theme, #update-theme&#039;, function( event ) {

				// #update-theme is a link.
				event.preventDefault();
				event.stopPropagation();

				panel.updateTheme( event );
			});

			// Delete a theme.
			panel.contentContainer.on( &#039;click&#039;, &#039;.delete-theme&#039;, function( event ) {
				panel.deleteTheme( event );
			});

			_.bindAll( panel, &#039;installTheme&#039;, &#039;updateTheme&#039; );
		},

		/**
		 * Update UI to reflect expanded state
		 *
		 * @since 4.9.0
		 *
		 * @param {boolean}  expanded - Expanded state.
		 * @param {Object}   args - Args.
		 * @param {boolean}  args.unchanged - Whether or not the state changed.
		 * @param {Function} args.completeCallback - Callback to execute when the animation completes.
		 * @return {void}
		 */
		onChangeExpanded: function( expanded, args ) {
			var panel = this, overlay, sections, hasExpandedSection = false;

			// Expand/collapse the panel normally.
			api.Panel.prototype.onChangeExpanded.apply( this, [ expanded, args ] );

			// Immediately call the complete callback if there were no changes.
			if ( args.unchanged ) {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
				return;
			}

			overlay = panel.headContainer.closest( &#039;.wp-full-overlay&#039; );

			if ( expanded ) {
				overlay
					.addClass( &#039;in-themes-panel&#039; )
					.delay( 200 ).find( &#039;.customize-themes-full-container&#039; ).addClass( &#039;animate&#039; );

				_.delay( function() {
					overlay.addClass( &#039;themes-panel-expanded&#039; );
				}, 200 );

				// Automatically open the first section (except on small screens), if one isn&#039;t already expanded.
				if ( 600 &lt; window.innerWidth ) {
					sections = panel.sections();
					_.each( sections, function( section ) {
						if ( section.expanded() ) {
							hasExpandedSection = true;
						}
					} );
					if ( ! hasExpandedSection &amp;&amp; sections.length &gt; 0 ) {
						sections[0].expand();
					}
				}
			} else {
				overlay
					.removeClass( &#039;in-themes-panel themes-panel-expanded&#039; )
					.find( &#039;.customize-themes-full-container&#039; ).removeClass( &#039;animate&#039; );
			}
		},

		/**
		 * Install a theme via wp.updates.
		 *
		 * @since 4.9.0
		 *
		 * @param {jQuery.Event} event - Event.
		 * @return {jQuery.promise} Promise.
		 */
		installTheme: function( event ) {
			var panel = this, preview, onInstallSuccess, slug = $( event.target ).data( &#039;slug&#039; ), deferred = $.Deferred(), request;
			preview = $( event.target ).hasClass( &#039;preview&#039; );

			// Temporary since supplying SFTP credentials does not work yet. See #42184.
			if ( api.settings.theme._filesystemCredentialsNeeded ) {
				deferred.reject({
					errorCode: &#039;theme_install_unavailable&#039;
				});
				return deferred.promise();
			}

			// Prevent loading a non-active theme preview when there is a drafted/scheduled changeset.
			if ( ! panel.canSwitchTheme( slug ) ) {
				deferred.reject({
					errorCode: &#039;theme_switch_unavailable&#039;
				});
				return deferred.promise();
			}

			// Theme is already being installed.
			if ( _.contains( panel.installingThemes, slug ) ) {
				deferred.reject({
					errorCode: &#039;theme_already_installing&#039;
				});
				return deferred.promise();
			}

			wp.updates.maybeRequestFilesystemCredentials( event );

			onInstallSuccess = function( response ) {
				var theme = false, themeControl;
				if ( preview ) {
					api.notifications.remove( &#039;theme_installing&#039; );

					panel.loadThemePreview( slug );

				} else {
					api.control.each( function( control ) {
						if ( &#039;theme&#039; === control.params.type &amp;&amp; control.params.theme.id === response.slug ) {
							theme = control.params.theme; // Used below to add theme control.
							control.rerenderAsInstalled( true );
						}
					});

					// Don&#039;t add the same theme more than once.
					if ( ! theme || api.control.has( &#039;installed_theme_&#039; + theme.id ) ) {
						deferred.resolve( response );
						return;
					}

					// Add theme control to installed section.
					theme.type = &#039;installed&#039;;
					themeControl = new api.controlConstructor.theme( &#039;installed_theme_&#039; + theme.id, {
						type: &#039;theme&#039;,
						section: &#039;installed_themes&#039;,
						theme: theme,
						priority: 0 // Add all newly-installed themes to the top.
					} );

					api.control.add( themeControl );
					api.control( themeControl.id ).container.trigger( &#039;render-screenshot&#039; );

					// Close the details modal if it&#039;s open to the installed theme.
					api.section.each( function( section ) {
						if ( &#039;themes&#039; === section.params.type ) {
							if ( theme.id === section.currentTheme ) { // Don&#039;t close the modal if the user has navigated elsewhere.
								section.closeDetails();
							}
						}
					});
				}
				deferred.resolve( response );
			};

			panel.installingThemes.push( slug ); // Note: we don&#039;t remove elements from installingThemes, since they shouldn&#039;t be installed again.
			request = wp.updates.installTheme( {
				slug: slug
			} );

			// Also preview the theme as the event is triggered on Install &amp; Preview.
			if ( preview ) {
				api.notifications.add( new api.OverlayNotification( &#039;theme_installing&#039;, {
					message: api.l10n.themeDownloading,
					type: &#039;info&#039;,
					loading: true
				} ) );
			}

			request.done( onInstallSuccess );
			request.fail( function() {
				api.notifications.remove( &#039;theme_installing&#039; );
			} );

			return deferred.promise();
		},

		/**
		 * Load theme preview.
		 *
		 * @since 4.9.0
		 *
		 * @param {string} themeId Theme ID.
		 * @return {jQuery.promise} Promise.
		 */
		loadThemePreview: function( themeId ) {
			var panel = this, deferred = $.Deferred(), onceProcessingComplete, urlParser, queryParams;

			// Prevent loading a non-active theme preview when there is a drafted/scheduled changeset.
			if ( ! panel.canSwitchTheme( themeId ) ) {
				deferred.reject({
					errorCode: &#039;theme_switch_unavailable&#039;
				});
				return deferred.promise();
			}

			urlParser = document.createElement( &#039;a&#039; );
			urlParser.href = location.href;
			queryParams = _.extend(
				api.utils.parseQueryString( urlParser.search.substr( 1 ) ),
				{
					theme: themeId,
					changeset_uuid: api.settings.changeset.uuid,
					&#039;return&#039;: api.settings.url[&#039;return&#039;]
				}
			);

			// Include autosaved param to load autosave revision without prompting user to restore it.
			if ( ! api.state( &#039;saved&#039; ).get() ) {
				queryParams.customize_autosaved = &#039;on&#039;;
			}

			urlParser.search = $.param( queryParams );

			// Update loading message. Everything else is handled by reloading the page.
			api.notifications.add( new api.OverlayNotification( &#039;theme_previewing&#039;, {
				message: api.l10n.themePreviewWait,
				type: &#039;info&#039;,
				loading: true
			} ) );

			onceProcessingComplete = function() {
				var request;
				if ( api.state( &#039;processing&#039; ).get() &gt; 0 ) {
					return;
				}

				api.state( &#039;processing&#039; ).unbind( onceProcessingComplete );

				request = api.requestChangesetUpdate( {}, { autosave: true } );
				request.done( function() {
					deferred.resolve();
					$( window ).off( &#039;beforeunload.customize-confirm&#039; );
					location.replace( urlParser.href );
				} );
				request.fail( function() {

					// @todo Show notification regarding failure.
					api.notifications.remove( &#039;theme_previewing&#039; );

					deferred.reject();
				} );
			};

			if ( 0 === api.state( &#039;processing&#039; ).get() ) {
				onceProcessingComplete();
			} else {
				api.state( &#039;processing&#039; ).bind( onceProcessingComplete );
			}

			return deferred.promise();
		},

		/**
		 * Update a theme via wp.updates.
		 *
		 * @since 4.9.0
		 *
		 * @param {jQuery.Event} event - Event.
		 * @return {void}
		 */
		updateTheme: function( event ) {
			wp.updates.maybeRequestFilesystemCredentials( event );

			$( document ).one( &#039;wp-theme-update-success&#039;, function( e, response ) {

				// Rerender the control to reflect the update.
				api.control.each( function( control ) {
					if ( &#039;theme&#039; === control.params.type &amp;&amp; control.params.theme.id === response.slug ) {
						control.params.theme.hasUpdate = false;
						control.params.theme.version = response.newVersion;
						setTimeout( function() {
							control.rerenderAsInstalled( true );
						}, 2000 );
					}
				});
			} );

			wp.updates.updateTheme( {
				slug: $( event.target ).closest( &#039;.notice&#039; ).data( &#039;slug&#039; )
			} );
		},

		/**
		 * Delete a theme via wp.updates.
		 *
		 * @since 4.9.0
		 *
		 * @param {jQuery.Event} event - Event.
		 * @return {void}
		 */
		deleteTheme: function( event ) {
			var theme, section;
			theme = $( event.target ).data( &#039;slug&#039; );
			section = api.section( &#039;installed_themes&#039; );

			event.preventDefault();

			// Temporary since supplying SFTP credentials does not work yet. See #42184.
			if ( api.settings.theme._filesystemCredentialsNeeded ) {
				return;
			}

			// Confirmation dialog for deleting a theme.
			if ( ! window.confirm( api.settings.l10n.confirmDeleteTheme ) ) {
				return;
			}

			wp.updates.maybeRequestFilesystemCredentials( event );

			$( document ).one( &#039;wp-theme-delete-success&#039;, function() {
				var control = api.control( &#039;installed_theme_&#039; + theme );

				// Remove theme control.
				control.container.remove();
				api.control.remove( control.id );

				// Update installed count.
				section.loaded = section.loaded - 1;
				section.updateCount();

				// Rerender any other theme controls as uninstalled.
				api.control.each( function( control ) {
					if ( &#039;theme&#039; === control.params.type &amp;&amp; control.params.theme.id === theme ) {
						control.rerenderAsInstalled( false );
					}
				});
			} );

			wp.updates.deleteTheme( {
				slug: theme
			} );

			// Close modal and focus the section.
			section.closeDetails();
			section.focus();
		}
	});

	api.Control = api.Class.extend(/** @lends wp.customize.Control.prototype */{
		defaultActiveArguments: { duration: &#039;fast&#039;, completeCallback: $.noop },

		/**
		 * Default params.
		 *
		 * @since 4.9.0
		 * @var {object}
		 */
		defaults: {
			label: &#039;&#039;,
			description: &#039;&#039;,
			active: true,
			priority: 10
		},

		/**
		 * A Customizer Control.
		 *
		 * A control provides a UI element that allows a user to modify a Customizer Setting.
		 *
		 * @see PHP class WP_Customize_Control.
		 *
		 * @constructs wp.customize.Control
		 * @augments   wp.customize.Class
		 *
		 * @borrows wp.customize~focus as this#focus
		 * @borrows wp.customize~Container#activate as this#activate
		 * @borrows wp.customize~Container#deactivate as this#deactivate
		 * @borrows wp.customize~Container#_toggleActive as this#_toggleActive
		 *
		 * @param {string} id                       - Unique identifier for the control instance.
		 * @param {Object} options                  - Options hash for the control instance.
		 * @param {Object} options.type             - Type of control (e.g. text, radio, dropdown-pages, etc.)
		 * @param {string} [options.content]        - The HTML content for the control or at least its container. This should normally be left blank and instead supplying a templateId.
		 * @param {string} [options.templateId]     - Template ID for control&#039;s content.
		 * @param {string} [options.priority=10]    - Order of priority to show the control within the section.
		 * @param {string} [options.active=true]    - Whether the control is active.
		 * @param {string} options.section          - The ID of the section the control belongs to.
		 * @param {mixed}  [options.setting]        - The ID of the main setting or an instance of this setting.
		 * @param {mixed}  options.settings         - An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects.
		 * @param {mixed}  options.settings.default - The ID of the setting the control relates to.
		 * @param {string} options.settings.data    - @todo Is this used?
		 * @param {string} options.label            - Label.
		 * @param {string} options.description      - Description.
		 * @param {number} [options.instanceNumber] - Order in which this instance was created in relation to other instances.
		 * @param {Object} [options.params]         - Deprecated wrapper for the above properties.
		 * @return {void}
		 */
		initialize: function( id, options ) {
			var control = this, deferredSettingIds = [], settings, gatherSettings;

			control.params = _.extend(
				{},
				control.defaults,
				control.params || {}, // In case subclass already defines.
				options.params || options || {} // The options.params property is deprecated, but it is checked first for back-compat.
			);

			if ( ! api.Control.instanceCounter ) {
				api.Control.instanceCounter = 0;
			}
			api.Control.instanceCounter++;
			if ( ! control.params.instanceNumber ) {
				control.params.instanceNumber = api.Control.instanceCounter;
			}

			// Look up the type if one was not supplied.
			if ( ! control.params.type ) {
				_.find( api.controlConstructor, function( Constructor, type ) {
					if ( Constructor === control.constructor ) {
						control.params.type = type;
						return true;
					}
					return false;
				} );
			}

			if ( ! control.params.content ) {
				control.params.content = $( &#039;&lt;li&gt;&lt;/li&gt;&#039;, {
					id: &#039;customize-control-&#039; + id.replace( /]/g, &#039;&#039; ).replace( /\[/g, &#039;-&#039; ),
					&#039;class&#039;: &#039;customize-control customize-control-&#039; + control.params.type
				} );
			}

			control.id = id;
			control.selector = &#039;#customize-control-&#039; + id.replace( /\]/g, &#039;&#039; ).replace( /\[/g, &#039;-&#039; ); // Deprecated, likely dead code from time before #28709.
			if ( control.params.content ) {
				control.container = $( control.params.content );
			} else {
				control.container = $( control.selector ); // Likely dead, per above. See #28709.
			}

			if ( control.params.templateId ) {
				control.templateSelector = control.params.templateId;
			} else {
				control.templateSelector = &#039;customize-control-&#039; + control.params.type + &#039;-content&#039;;
			}

			control.deferred = _.extend( control.deferred || {}, {
				embedded: new $.Deferred()
			} );
			control.section = new api.Value();
			control.priority = new api.Value();
			control.active = new api.Value();
			control.activeArgumentsQueue = [];
			control.notifications = new api.Notifications({
				alt: control.altNotice
			});

			control.elements = [];

			control.active.bind( function ( active ) {
				var args = control.activeArgumentsQueue.shift();
				args = $.extend( {}, control.defaultActiveArguments, args );
				control.onChangeActive( active, args );
			} );

			control.section.set( control.params.section );
			control.priority.set( isNaN( control.params.priority ) ? 10 : control.params.priority );
			control.active.set( control.params.active );

			api.utils.bubbleChildValueChanges( control, [ &#039;section&#039;, &#039;priority&#039;, &#039;active&#039; ] );

			control.settings = {};

			settings = {};
			if ( control.params.setting ) {
				settings[&#039;default&#039;] = control.params.setting;
			}
			_.extend( settings, control.params.settings );

			// Note: Settings can be an array or an object, with values being either setting IDs or Setting (or Value) objects.
			_.each( settings, function( value, key ) {
				var setting;
				if ( _.isObject( value ) &amp;&amp; _.isFunction( value.extended ) &amp;&amp; value.extended( api.Value ) ) {
					control.settings[ key ] = value;
				} else if ( _.isString( value ) ) {
					setting = api( value );
					if ( setting ) {
						control.settings[ key ] = setting;
					} else {
						deferredSettingIds.push( value );
					}
				}
			} );

			gatherSettings = function() {

				// Fill-in all resolved settings.
				_.each( settings, function ( settingId, key ) {
					if ( ! control.settings[ key ] &amp;&amp; _.isString( settingId ) ) {
						control.settings[ key ] = api( settingId );
					}
				} );

				// Make sure settings passed as array gets associated with default.
				if ( control.settings[0] &amp;&amp; ! control.settings[&#039;default&#039;] ) {
					control.settings[&#039;default&#039;] = control.settings[0];
				}

				// Identify the main setting.
				control.setting = control.settings[&#039;default&#039;] || null;

				control.linkElements(); // Link initial elements present in server-rendered content.
				control.embed();
			};

			if ( 0 === deferredSettingIds.length ) {
				gatherSettings();
			} else {
				api.apply( api, deferredSettingIds.concat( gatherSettings ) );
			}

			// After the control is embedded on the page, invoke the &quot;ready&quot; method.
			control.deferred.embedded.done( function () {
				control.linkElements(); // Link any additional elements after template is rendered by renderContent().
				control.setupNotifications();
				control.ready();
			});
		},

		/**
		 * Link elements between settings and inputs.
		 *
		 * @since 4.7.0
		 * @access public
		 *
		 * @return {void}
		 */
		linkElements: function () {
			var control = this, nodes, radios, element;

			nodes = control.container.find( &#039;[data-customize-setting-link], [data-customize-setting-key-link]&#039; );
			radios = {};

			nodes.each( function () {
				var node = $( this ), name, setting;

				if ( node.data( &#039;customizeSettingLinked&#039; ) ) {
					return;
				}
				node.data( &#039;customizeSettingLinked&#039;, true ); // Prevent re-linking element.

				if ( node.is( &#039;:radio&#039; ) ) {
					name = node.prop( &#039;name&#039; );
					if ( radios[name] ) {
						return;
					}

					radios[name] = true;
					node = nodes.filter( &#039;[name=&quot;&#039; + name + &#039;&quot;]&#039; );
				}

				// Let link by default refer to setting ID. If it doesn&#039;t exist, fallback to looking up by setting key.
				if ( node.data( &#039;customizeSettingLink&#039; ) ) {
					setting = api( node.data( &#039;customizeSettingLink&#039; ) );
				} else if ( node.data( &#039;customizeSettingKeyLink&#039; ) ) {
					setting = control.settings[ node.data( &#039;customizeSettingKeyLink&#039; ) ];
				}

				if ( setting ) {
					element = new api.Element( node );
					control.elements.push( element );
					element.sync( setting );
					element.set( setting() );
				}
			} );
		},

		/**
		 * Embed the control into the page.
		 */
		embed: function () {
			var control = this,
				inject;

			// Watch for changes to the section state.
			inject = function ( sectionId ) {
				var parentContainer;
				if ( ! sectionId ) { // @todo Allow a control to be embedded without a section, for instance a control embedded in the front end.
					return;
				}
				// Wait for the section to be registered.
				api.section( sectionId, function ( section ) {
					// Wait for the section to be ready/initialized.
					section.deferred.embedded.done( function () {
						parentContainer = ( section.contentContainer.is( &#039;ul&#039; ) ) ? section.contentContainer : section.contentContainer.find( &#039;ul:first&#039; );
						if ( ! control.container.parent().is( parentContainer ) ) {
							parentContainer.append( control.container );
						}
						control.renderContent();
						control.deferred.embedded.resolve();
					});
				});
			};
			control.section.bind( inject );
			inject( control.section.get() );
		},

		/**
		 * Triggered when the control&#039;s markup has been injected into the DOM.
		 *
		 * @return {void}
		 */
		ready: function() {
			var control = this, newItem;
			if ( &#039;dropdown-pages&#039; === control.params.type &amp;&amp; control.params.allow_addition ) {
				newItem = control.container.find( &#039;.new-content-item-wrapper&#039; );
				newItem.hide(); // Hide in JS to preserve flex display when showing.
				control.container.on( &#039;click&#039;, &#039;.add-new-toggle&#039;, function( e ) {
					$( e.currentTarget ).slideUp( 180 );
					newItem.slideDown( 180 );
					newItem.find( &#039;.create-item-input&#039; ).focus();
				});
				control.container.on( &#039;click&#039;, &#039;.add-content&#039;, function() {
					control.addNewPage();
				});
				control.container.on( &#039;keydown&#039;, &#039;.create-item-input&#039;, function( e ) {
					if ( 13 === e.which ) { // Enter.
						control.addNewPage();
					}
				});
			}
		},

		/**
		 * Get the element inside of a control&#039;s container that contains the validation error message.
		 *
		 * Control subclasses may override this to return the proper container to render notifications into.
		 * Injects the notification container for existing controls that lack the necessary container,
		 * including special handling for nav menu items and widgets.
		 *
		 * @since 4.6.0
		 * @return {jQuery} Setting validation message element.
		 */
		getNotificationsContainerElement: function() {
			var control = this, controlTitle, notificationsContainer;

			notificationsContainer = control.container.find( &#039;.customize-control-notifications-container:first&#039; );
			if ( notificationsContainer.length ) {
				return notificationsContainer;
			}

			notificationsContainer = $( &#039;&lt;div class=&quot;customize-control-notifications-container&quot;&gt;&lt;/div&gt;&#039; );

			if ( control.container.hasClass( &#039;customize-control-nav_menu_item&#039; ) ) {
				control.container.find( &#039;.menu-item-settings:first&#039; ).prepend( notificationsContainer );
			} else if ( control.container.hasClass( &#039;customize-control-widget_form&#039; ) ) {
				control.container.find( &#039;.widget-inside:first&#039; ).prepend( notificationsContainer );
			} else {
				controlTitle = control.container.find( &#039;.customize-control-title&#039; );
				if ( controlTitle.length ) {
					controlTitle.after( notificationsContainer );
				} else {
					control.container.prepend( notificationsContainer );
				}
			}
			return notificationsContainer;
		},

		/**
		 * Set up notifications.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		setupNotifications: function() {
			var control = this, renderNotificationsIfVisible, onSectionAssigned;

			// Add setting notifications to the control notification.
			_.each( control.settings, function( setting ) {
				if ( ! setting.notifications ) {
					return;
				}
				setting.notifications.bind( &#039;add&#039;, function( settingNotification ) {
					var params = _.extend(
						{},
						settingNotification,
						{
							setting: setting.id
						}
					);
					control.notifications.add( new api.Notification( setting.id + &#039;:&#039; + settingNotification.code, params ) );
				} );
				setting.notifications.bind( &#039;remove&#039;, function( settingNotification ) {
					control.notifications.remove( setting.id + &#039;:&#039; + settingNotification.code );
				} );
			} );

			renderNotificationsIfVisible = function() {
				var sectionId = control.section();
				if ( ! sectionId || ( api.section.has( sectionId ) &amp;&amp; api.section( sectionId ).expanded() ) ) {
					control.notifications.render();
				}
			};

			control.notifications.bind( &#039;rendered&#039;, function() {
				var notifications = control.notifications.get();
				control.container.toggleClass( &#039;has-notifications&#039;, 0 !== notifications.length );
				control.container.toggleClass( &#039;has-error&#039;, 0 !== _.where( notifications, { type: &#039;error&#039; } ).length );
			} );

			onSectionAssigned = function( newSectionId, oldSectionId ) {
				if ( oldSectionId &amp;&amp; api.section.has( oldSectionId ) ) {
					api.section( oldSectionId ).expanded.unbind( renderNotificationsIfVisible );
				}
				if ( newSectionId ) {
					api.section( newSectionId, function( section ) {
						section.expanded.bind( renderNotificationsIfVisible );
						renderNotificationsIfVisible();
					});
				}
			};

			control.section.bind( onSectionAssigned );
			onSectionAssigned( control.section.get() );
			control.notifications.bind( &#039;change&#039;, _.debounce( renderNotificationsIfVisible ) );
		},

		/**
		 * Render notifications.
		 *
		 * Renders the `control.notifications` into the control&#039;s container.
		 * Control subclasses may override this method to do their own handling
		 * of rendering notifications.
		 *
		 * @deprecated in favor of `control.notifications.render()`
		 * @since 4.6.0
		 * @this {wp.customize.Control}
		 */
		renderNotifications: function() {
			var control = this, container, notifications, hasError = false;

			if ( &#039;undefined&#039; !== typeof console &amp;&amp; console.warn ) {
				console.warn( &#039;[DEPRECATED] wp.customize.Control.prototype.renderNotifications() is deprecated in favor of instantiating a wp.customize.Notifications and calling its render() method.&#039; );
			}

			container = control.getNotificationsContainerElement();
			if ( ! container || ! container.length ) {
				return;
			}
			notifications = [];
			control.notifications.each( function( notification ) {
				notifications.push( notification );
				if ( &#039;error&#039; === notification.type ) {
					hasError = true;
				}
			} );

			if ( 0 === notifications.length ) {
				container.stop().slideUp( &#039;fast&#039; );
			} else {
				container.stop().slideDown( &#039;fast&#039;, null, function() {
					$( this ).css( &#039;height&#039;, &#039;auto&#039; );
				} );
			}

			if ( ! control.notificationsTemplate ) {
				control.notificationsTemplate = wp.template( &#039;customize-control-notifications&#039; );
			}

			control.container.toggleClass( &#039;has-notifications&#039;, 0 !== notifications.length );
			control.container.toggleClass( &#039;has-error&#039;, hasError );
			container.empty().append(
				control.notificationsTemplate( { notifications: notifications, altNotice: Boolean( control.altNotice ) } ).trim()
			);
		},

		/**
		 * Normal controls do not expand, so just expand its parent
		 *
		 * @param {Object} [params]
		 */
		expand: function ( params ) {
			api.section( this.section() ).expand( params );
		},

		/*
		 * Documented using @borrows in the constructor.
		 */
		focus: focus,

		/**
		 * Update UI in response to a change in the control&#039;s active state.
		 * This does not change the active state, it merely handles the behavior
		 * for when it does change.
		 *
		 * @since 4.1.0
		 *
		 * @param {boolean}  active
		 * @param {Object}   args
		 * @param {number}   args.duration
		 * @param {Function} args.completeCallback
		 */
		onChangeActive: function ( active, args ) {
			if ( args.unchanged ) {
				if ( args.completeCallback ) {
					args.completeCallback();
				}
				return;
			}

			if ( ! $.contains( document, this.container[0] ) ) {
				// jQuery.fn.slideUp is not hiding an element if it is not in the DOM.
				this.container.toggle( active );
				if ( args.completeCallback ) {
					args.completeCallback();
				}
			} else if ( active ) {
				this.container.slideDown( args.duration, args.completeCallback );
			} else {
				this.container.slideUp( args.duration, args.completeCallback );
			}
		},

		/**
		 * @deprecated 4.1.0 Use this.onChangeActive() instead.
		 */
		toggle: function ( active ) {
			return this.onChangeActive( active, this.defaultActiveArguments );
		},

		/*
		 * Documented using @borrows in the constructor
		 */
		activate: Container.prototype.activate,

		/*
		 * Documented using @borrows in the constructor
		 */
		deactivate: Container.prototype.deactivate,

		/*
		 * Documented using @borrows in the constructor
		 */
		_toggleActive: Container.prototype._toggleActive,

		// @todo This function appears to be dead code and can be removed.
		dropdownInit: function() {
			var control      = this,
				statuses     = this.container.find(&#039;.dropdown-status&#039;),
				params       = this.params,
				toggleFreeze = false,
				update       = function( to ) {
					if ( &#039;string&#039; === typeof to &amp;&amp; params.statuses &amp;&amp; params.statuses[ to ] ) {
						statuses.html( params.statuses[ to ] ).show();
					} else {
						statuses.hide();
					}
				};

			// Support the .dropdown class to open/close complex elements.
			this.container.on( &#039;click keydown&#039;, &#039;.dropdown&#039;, function( event ) {
				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
					return;
				}

				event.preventDefault();

				if ( ! toggleFreeze ) {
					control.container.toggleClass( &#039;open&#039; );
				}

				if ( control.container.hasClass( &#039;open&#039; ) ) {
					control.container.parent().parent().find( &#039;li.library-selected&#039; ).focus();
				}

				// Don&#039;t want to fire focus and click at same time.
				toggleFreeze = true;
				setTimeout(function () {
					toggleFreeze = false;
				}, 400);
			});

			this.setting.bind( update );
			update( this.setting() );
		},

		/**
		 * Render the control from its JS template, if it exists.
		 *
		 * The control&#039;s container must already exist in the DOM.
		 *
		 * @since 4.1.0
		 */
		renderContent: function () {
			var control = this, template, standardTypes, templateId, sectionId;

			standardTypes = [
				&#039;button&#039;,
				&#039;checkbox&#039;,
				&#039;date&#039;,
				&#039;datetime-local&#039;,
				&#039;email&#039;,
				&#039;month&#039;,
				&#039;number&#039;,
				&#039;password&#039;,
				&#039;radio&#039;,
				&#039;range&#039;,
				&#039;search&#039;,
				&#039;select&#039;,
				&#039;tel&#039;,
				&#039;time&#039;,
				&#039;text&#039;,
				&#039;textarea&#039;,
				&#039;week&#039;,
				&#039;url&#039;
			];

			templateId = control.templateSelector;

			// Use default content template when a standard HTML type is used,
			// there isn&#039;t a more specific template existing, and the control container is empty.
			if ( templateId === &#039;customize-control-&#039; + control.params.type + &#039;-content&#039; &amp;&amp;
				_.contains( standardTypes, control.params.type ) &amp;&amp;
				! document.getElementById( &#039;tmpl-&#039; + templateId ) &amp;&amp;
				0 === control.container.children().length )
			{
				templateId = &#039;customize-control-default-content&#039;;
			}

			// Replace the container element&#039;s content with the control.
			if ( document.getElementById( &#039;tmpl-&#039; + templateId ) ) {
				template = wp.template( templateId );
				if ( template &amp;&amp; control.container ) {
					control.container.html( template( control.params ) );
				}
			}

			// Re-render notifications after content has been re-rendered.
			control.notifications.container = control.getNotificationsContainerElement();
			sectionId = control.section();
			if ( ! sectionId || ( api.section.has( sectionId ) &amp;&amp; api.section( sectionId ).expanded() ) ) {
				control.notifications.render();
			}
		},

		/**
		 * Add a new page to a dropdown-pages control reusing menus code for this.
		 *
		 * @since 4.7.0
		 * @access private
		 *
		 * @return {void}
		 */
		addNewPage: function () {
			var control = this, promise, toggle, container, input, inputError, title, select;

			if ( &#039;dropdown-pages&#039; !== control.params.type || ! control.params.allow_addition || ! api.Menus ) {
				return;
			}

			toggle = control.container.find( &#039;.add-new-toggle&#039; );
			container = control.container.find( &#039;.new-content-item-wrapper&#039; );
			input = control.container.find( &#039;.create-item-input&#039; );
			inputError = control.container.find(&#039;.create-item-error&#039;);
			title = input.val();
			select = control.container.find( &#039;select&#039; );

			if ( ! title ) {
				container.addClass( &#039;form-invalid&#039; );
				input.attr(&#039;aria-invalid&#039;, &#039;true&#039;);
				input.attr(&#039;aria-describedby&#039;, inputError.attr(&#039;id&#039;));
				inputError.slideDown( &#039;fast&#039; );
				wp.a11y.speak( inputError.text() );
				return;
			}

			container.removeClass( &#039;form-invalid&#039; );
			input.attr(&#039;aria-invalid&#039;, &#039;false&#039;);
			input.removeAttr(&#039;aria-describedby&#039;);
			inputError.hide();
			input.attr( &#039;disabled&#039;, &#039;disabled&#039; );

			// The menus functions add the page, publish when appropriate,
			// and also add the new page to the dropdown-pages controls.
			promise = api.Menus.insertAutoDraftPost( {
				post_title: title,
				post_type: &#039;page&#039;
			} );
			promise.done( function( data ) {
				var availableItem, $content, itemTemplate;

				// Prepare the new page as an available menu item.
				// See api.Menus.submitNew().
				availableItem = new api.Menus.AvailableItemModel( {
					&#039;id&#039;: &#039;post-&#039; + data.post_id, // Used for available menu item Backbone models.
					&#039;title&#039;: title,
					&#039;type&#039;: &#039;post_type&#039;,
					&#039;type_label&#039;: api.Menus.data.l10n.page_label,
					&#039;object&#039;: &#039;page&#039;,
					&#039;object_id&#039;: data.post_id,
					&#039;url&#039;: data.url
				} );

				// Add the new item to the list of available menu items.
				api.Menus.availableMenuItemsPanel.collection.add( availableItem );
				$content = $( &#039;#available-menu-items-post_type-page&#039; ).find( &#039;.available-menu-items-list&#039; );
				itemTemplate = wp.template( &#039;available-menu-item&#039; );
				$content.prepend( itemTemplate( availableItem.attributes ) );

				// Focus the select control.
				select.focus();
				control.setting.set( String( data.post_id ) ); // Triggers a preview refresh and updates the setting.

				// Reset the create page form.
				container.slideUp( 180 );
				toggle.slideDown( 180 );
			} );
			promise.always( function() {
				input.val( &#039;&#039; ).removeAttr( &#039;disabled&#039; );
			} );
		}
	});

	/**
	 * A colorpicker control.
	 *
	 * @class    wp.customize.ColorControl
	 * @augments wp.customize.Control
	 */
	api.ColorControl = api.Control.extend(/** @lends wp.customize.ColorControl.prototype */{
		ready: function() {
			var control = this,
				isHueSlider = this.params.mode === &#039;hue&#039;,
				updating = false,
				picker;

			if ( isHueSlider ) {
				picker = this.container.find( &#039;.color-picker-hue&#039; );
				picker.val( control.setting() ).wpColorPicker({
					change: function( event, ui ) {
						updating = true;
						control.setting( ui.color.h() );
						updating = false;
					}
				});
			} else {
				picker = this.container.find( &#039;.color-picker-hex&#039; );
				picker.val( control.setting() ).wpColorPicker({
					change: function() {
						updating = true;
						control.setting.set( picker.wpColorPicker( &#039;color&#039; ) );
						updating = false;
					},
					clear: function() {
						updating = true;
						control.setting.set( &#039;&#039; );
						updating = false;
					}
				});
			}

			control.setting.bind( function ( value ) {
				// Bail if the update came from the control itself.
				if ( updating ) {
					return;
				}
				picker.val( value );
				picker.wpColorPicker( &#039;color&#039;, value );
			} );

			// Collapse color picker when hitting Esc instead of collapsing the current section.
			control.container.on( &#039;keydown&#039;, function( event ) {
				var pickerContainer;
				if ( 27 !== event.which ) { // Esc.
					return;
				}
				pickerContainer = control.container.find( &#039;.wp-picker-container&#039; );
				if ( pickerContainer.hasClass( &#039;wp-picker-active&#039; ) ) {
					picker.wpColorPicker( &#039;close&#039; );
					control.container.find( &#039;.wp-color-result&#039; ).focus();
					event.stopPropagation(); // Prevent section from being collapsed.
				}
			} );
		}
	});

	/**
	 * A control that implements the media modal.
	 *
	 * @class    wp.customize.MediaControl
	 * @augments wp.customize.Control
	 */
	api.MediaControl = api.Control.extend(/** @lends wp.customize.MediaControl.prototype */{

		/**
		 * When the control&#039;s DOM structure is ready,
		 * set up internal event bindings.
		 */
		ready: function() {
			var control = this;
			// Shortcut so that we don&#039;t have to use _.bind every time we add a callback.
			_.bindAll( control, &#039;restoreDefault&#039;, &#039;removeFile&#039;, &#039;openFrame&#039;, &#039;select&#039;, &#039;pausePlayer&#039; );

			// Bind events, with delegation to facilitate re-rendering.
			control.container.on( &#039;click keydown&#039;, &#039;.upload-button&#039;, control.openFrame );
			control.container.on( &#039;click keydown&#039;, &#039;.upload-button&#039;, control.pausePlayer );
			control.container.on( &#039;click keydown&#039;, &#039;.thumbnail-image img&#039;, control.openFrame );
			control.container.on( &#039;click keydown&#039;, &#039;.default-button&#039;, control.restoreDefault );
			control.container.on( &#039;click keydown&#039;, &#039;.remove-button&#039;, control.pausePlayer );
			control.container.on( &#039;click keydown&#039;, &#039;.remove-button&#039;, control.removeFile );
			control.container.on( &#039;click keydown&#039;, &#039;.remove-button&#039;, control.cleanupPlayer );

			// Resize the player controls when it becomes visible (ie when section is expanded).
			api.section( control.section() ).container
				.on( &#039;expanded&#039;, function() {
					if ( control.player ) {
						control.player.setControlsSize();
					}
				})
				.on( &#039;collapsed&#039;, function() {
					control.pausePlayer();
				});

			/**
			 * Set attachment data and render content.
			 *
			 * Note that BackgroundImage.prototype.ready applies this ready method
			 * to itself. Since BackgroundImage is an UploadControl, the value
			 * is the attachment URL instead of the attachment ID. In this case
			 * we skip fetching the attachment data because we have no ID available,
			 * and it is the responsibility of the UploadControl to set the control&#039;s
			 * attachmentData before calling the renderContent method.
			 *
			 * @param {number|string} value Attachment
			 */
			function setAttachmentDataAndRenderContent( value ) {
				var hasAttachmentData = $.Deferred();

				if ( control.extended( api.UploadControl ) ) {
					hasAttachmentData.resolve();
				} else {
					value = parseInt( value, 10 );
					if ( _.isNaN( value ) || value &lt;= 0 ) {
						delete control.params.attachment;
						hasAttachmentData.resolve();
					} else if ( control.params.attachment &amp;&amp; control.params.attachment.id === value ) {
						hasAttachmentData.resolve();
					}
				}

				// Fetch the attachment data.
				if ( &#039;pending&#039; === hasAttachmentData.state() ) {
					wp.media.attachment( value ).fetch().done( function() {
						control.params.attachment = this.attributes;
						hasAttachmentData.resolve();

						// Send attachment information to the preview for possible use in `postMessage` transport.
						wp.customize.previewer.send( control.setting.id + &#039;-attachment-data&#039;, this.attributes );
					} );
				}

				hasAttachmentData.done( function() {
					control.renderContent();
				} );
			}

			// Ensure attachment data is initially set (for dynamically-instantiated controls).
			setAttachmentDataAndRenderContent( control.setting() );

			// Update the attachment data and re-render the control when the setting changes.
			control.setting.bind( setAttachmentDataAndRenderContent );
		},

		pausePlayer: function () {
			this.player &amp;&amp; this.player.pause();
		},

		cleanupPlayer: function () {
			this.player &amp;&amp; wp.media.mixin.removePlayer( this.player );
		},

		/**
		 * Open the media modal.
		 */
		openFrame: function( event ) {
			if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
				return;
			}

			event.preventDefault();

			if ( ! this.frame ) {
				this.initFrame();
			}

			this.frame.open();
		},

		/**
		 * Create a media modal select frame, and store it so the instance can be reused when needed.
		 */
		initFrame: function() {
			this.frame = wp.media({
				button: {
					text: this.params.button_labels.frame_button
				},
				states: [
					new wp.media.controller.Library({
						title:     this.params.button_labels.frame_title,
						library:   wp.media.query({ type: this.params.mime_type }),
						multiple:  false,
						date:      false
					})
				]
			});

			// When a file is selected, run a callback.
			this.frame.on( &#039;select&#039;, this.select );
		},

		/**
		 * Callback handler for when an attachment is selected in the media modal.
		 * Gets the selected image information, and sets it within the control.
		 */
		select: function() {
			// Get the attachment from the modal frame.
			var node,
				attachment = this.frame.state().get( &#039;selection&#039; ).first().toJSON(),
				mejsSettings = window._wpmejsSettings || {};

			this.params.attachment = attachment;

			// Set the Customizer setting; the callback takes care of rendering.
			this.setting( attachment.id );
			node = this.container.find( &#039;audio, video&#039; ).get(0);

			// Initialize audio/video previews.
			if ( node ) {
				this.player = new MediaElementPlayer( node, mejsSettings );
			} else {
				this.cleanupPlayer();
			}
		},

		/**
		 * Reset the setting to the default value.
		 */
		restoreDefault: function( event ) {
			if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
				return;
			}
			event.preventDefault();

			this.params.attachment = this.params.defaultAttachment;
			this.setting( this.params.defaultAttachment.url );
		},

		/**
		 * Called when the &quot;Remove&quot; link is clicked. Empties the setting.
		 *
		 * @param {Object} event jQuery Event object
		 */
		removeFile: function( event ) {
			if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
				return;
			}
			event.preventDefault();

			this.params.attachment = {};
			this.setting( &#039;&#039; );
			this.renderContent(); // Not bound to setting change when emptying.
		}
	});

	/**
	 * An upload control, which utilizes the media modal.
	 *
	 * @class    wp.customize.UploadControl
	 * @augments wp.customize.MediaControl
	 */
	api.UploadControl = api.MediaControl.extend(/** @lends wp.customize.UploadControl.prototype */{

		/**
		 * Callback handler for when an attachment is selected in the media modal.
		 * Gets the selected image information, and sets it within the control.
		 */
		select: function() {
			// Get the attachment from the modal frame.
			var node,
				attachment = this.frame.state().get( &#039;selection&#039; ).first().toJSON(),
				mejsSettings = window._wpmejsSettings || {};

			this.params.attachment = attachment;

			// Set the Customizer setting; the callback takes care of rendering.
			this.setting( attachment.url );
			node = this.container.find( &#039;audio, video&#039; ).get(0);

			// Initialize audio/video previews.
			if ( node ) {
				this.player = new MediaElementPlayer( node, mejsSettings );
			} else {
				this.cleanupPlayer();
			}
		},

		// @deprecated
		success: function() {},

		// @deprecated
		removerVisibility: function() {}
	});

	/**
	 * A control for uploading images.
	 *
	 * This control no longer needs to do anything more
	 * than what the upload control does in JS.
	 *
	 * @class    wp.customize.ImageControl
	 * @augments wp.customize.UploadControl
	 */
	api.ImageControl = api.UploadControl.extend(/** @lends wp.customize.ImageControl.prototype */{
		// @deprecated
		thumbnailSrc: function() {}
	});

	/**
	 * A control for uploading background images.
	 *
	 * @class    wp.customize.BackgroundControl
	 * @augments wp.customize.UploadControl
	 */
	api.BackgroundControl = api.UploadControl.extend(/** @lends wp.customize.BackgroundControl.prototype */{

		/**
		 * When the control&#039;s DOM structure is ready,
		 * set up internal event bindings.
		 */
		ready: function() {
			api.UploadControl.prototype.ready.apply( this, arguments );
		},

		/**
		 * Callback handler for when an attachment is selected in the media modal.
		 * Does an additional Ajax request for setting the background context.
		 */
		select: function() {
			api.UploadControl.prototype.select.apply( this, arguments );

			wp.ajax.post( &#039;custom-background-add&#039;, {
				nonce: _wpCustomizeBackground.nonces.add,
				wp_customize: &#039;on&#039;,
				customize_theme: api.settings.theme.stylesheet,
				attachment_id: this.params.attachment.id
			} );
		}
	});

	/**
	 * A control for positioning a background image.
	 *
	 * @since 4.7.0
	 *
	 * @class    wp.customize.BackgroundPositionControl
	 * @augments wp.customize.Control
	 */
	api.BackgroundPositionControl = api.Control.extend(/** @lends wp.customize.BackgroundPositionControl.prototype */{

		/**
		 * Set up control UI once embedded in DOM and settings are created.
		 *
		 * @since 4.7.0
		 * @access public
		 */
		ready: function() {
			var control = this, updateRadios;

			control.container.on( &#039;change&#039;, &#039;input[name=&quot;background-position&quot;]&#039;, function() {
				var position = $( this ).val().split( &#039; &#039; );
				control.settings.x( position[0] );
				control.settings.y( position[1] );
			} );

			updateRadios = _.debounce( function() {
				var x, y, radioInput, inputValue;
				x = control.settings.x.get();
				y = control.settings.y.get();
				inputValue = String( x ) + &#039; &#039; + String( y );
				radioInput = control.container.find( &#039;input[name=&quot;background-position&quot;][value=&quot;&#039; + inputValue + &#039;&quot;]&#039; );
				radioInput.trigger( &#039;click&#039; );
			} );
			control.settings.x.bind( updateRadios );
			control.settings.y.bind( updateRadios );

			updateRadios(); // Set initial UI.
		}
	} );

	/**
	 * A control for selecting and cropping an image.
	 *
	 * @class    wp.customize.CroppedImageControl
	 * @augments wp.customize.MediaControl
	 */
	api.CroppedImageControl = api.MediaControl.extend(/** @lends wp.customize.CroppedImageControl.prototype */{

		/**
		 * Open the media modal to the library state.
		 */
		openFrame: function( event ) {
			if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
				return;
			}

			this.initFrame();
			this.frame.setState( &#039;library&#039; ).open();
		},

		/**
		 * Create a media modal select frame, and store it so the instance can be reused when needed.
		 */
		initFrame: function() {
			var l10n = _wpMediaViewsL10n;

			this.frame = wp.media({
				button: {
					text: l10n.select,
					close: false
				},
				states: [
					new wp.media.controller.Library({
						title: this.params.button_labels.frame_title,
						library: wp.media.query({ type: &#039;image&#039; }),
						multiple: false,
						date: false,
						priority: 20,
						suggestedWidth: this.params.width,
						suggestedHeight: this.params.height
					}),
					new wp.media.controller.CustomizeImageCropper({
						imgSelectOptions: this.calculateImageSelectOptions,
						control: this
					})
				]
			});

			this.frame.on( &#039;select&#039;, this.onSelect, this );
			this.frame.on( &#039;cropped&#039;, this.onCropped, this );
			this.frame.on( &#039;skippedcrop&#039;, this.onSkippedCrop, this );
		},

		/**
		 * After an image is selected in the media modal, switch to the cropper
		 * state if the image isn&#039;t the right size.
		 */
		onSelect: function() {
			var attachment = this.frame.state().get( &#039;selection&#039; ).first().toJSON();

			if ( this.params.width === attachment.width &amp;&amp; this.params.height === attachment.height &amp;&amp; ! this.params.flex_width &amp;&amp; ! this.params.flex_height ) {
				this.setImageFromAttachment( attachment );
				this.frame.close();
			} else {
				this.frame.setState( &#039;cropper&#039; );
			}
		},

		/**
		 * After the image has been cropped, apply the cropped image data to the setting.
		 *
		 * @param {Object} croppedImage Cropped attachment data.
		 */
		onCropped: function( croppedImage ) {
			this.setImageFromAttachment( croppedImage );
		},

		/**
		 * Returns a set of options, computed from the attached image data and
		 * control-specific data, to be fed to the imgAreaSelect plugin in
		 * wp.media.view.Cropper.
		 *
		 * @param {wp.media.model.Attachment} attachment
		 * @param {wp.media.controller.Cropper} controller
		 * @return {Object} Options
		 */
		calculateImageSelectOptions: function( attachment, controller ) {
			var control       = controller.get( &#039;control&#039; ),
				flexWidth     = !! parseInt( control.params.flex_width, 10 ),
				flexHeight    = !! parseInt( control.params.flex_height, 10 ),
				realWidth     = attachment.get( &#039;width&#039; ),
				realHeight    = attachment.get( &#039;height&#039; ),
				xInit         = parseInt( control.params.width, 10 ),
				yInit         = parseInt( control.params.height, 10 ),
				requiredRatio = xInit / yInit,
				realRatio     = realWidth / realHeight,
				xImg          = xInit,
				yImg          = yInit,
				x1, y1, imgSelectOptions;

			controller.set( &#039;hasRequiredAspectRatio&#039;, control.hasRequiredAspectRatio( requiredRatio, realRatio ) );
			controller.set( &#039;suggestedCropSize&#039;, { width: realWidth, height: realHeight, x1: 0, y1: 0, x2: xInit, y2: yInit } );
			controller.set( &#039;canSkipCrop&#039;, ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) );

			if ( realRatio &gt; requiredRatio ) {
				yInit = realHeight;
				xInit = yInit * requiredRatio;
			} else {
				xInit = realWidth;
				yInit = xInit / requiredRatio;
			}

			x1 = ( realWidth - xInit ) / 2;
			y1 = ( realHeight - yInit ) / 2;

			imgSelectOptions = {
				handles: true,
				keys: true,
				instance: true,
				persistent: true,
				imageWidth: realWidth,
				imageHeight: realHeight,
				minWidth: xImg &gt; xInit ? xInit : xImg,
				minHeight: yImg &gt; yInit ? yInit : yImg,
				x1: x1,
				y1: y1,
				x2: xInit + x1,
				y2: yInit + y1
			};

			if ( flexHeight === false &amp;&amp; flexWidth === false ) {
				imgSelectOptions.aspectRatio = xInit + &#039;:&#039; + yInit;
			}

			if ( true === flexHeight ) {
				delete imgSelectOptions.minHeight;
				imgSelectOptions.maxWidth = realWidth;
			}

			if ( true === flexWidth ) {
				delete imgSelectOptions.minWidth;
				imgSelectOptions.maxHeight = realHeight;
			}

			return imgSelectOptions;
		},

		/**
		 * Return whether the image must be cropped, based on required dimensions.
		 *
		 * @param {boolean} flexW Width is flexible.
		 * @param {boolean} flexH Height is flexible.
		 * @param {number}  dstW  Required width.
		 * @param {number}  dstH  Required height.
		 * @param {number}  imgW  Provided image&#039;s width.
		 * @param {number}  imgH  Provided image&#039;s height.
		 * @return {boolean} Whether cropping is required.
		 */
		mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) {
			if ( true === flexW &amp;&amp; true === flexH ) {
				return false;
			}

			if ( true === flexW &amp;&amp; dstH === imgH ) {
				return false;
			}

			if ( true === flexH &amp;&amp; dstW === imgW ) {
				return false;
			}

			if ( dstW === imgW &amp;&amp; dstH === imgH ) {
				return false;
			}

			if ( imgW &lt;= dstW ) {
				return false;
			}

			return true;
		},

		/**
		 * Check if the image&#039;s aspect ratio essentially matches the required aspect ratio.
		 *
		 * Floating point precision is low, so this allows a small tolerance. This
		 * tolerance allows for images over 100,000 px on either side to still trigger
		 * the cropping flow.
		 *
		 * @param {number} requiredRatio Required image ratio.
		 * @param {number} realRatio     Provided image ratio.
		 * @return {boolean} Whether the image has the required aspect ratio.
		 */
		hasRequiredAspectRatio: function ( requiredRatio, realRatio ) {
			if ( Math.abs( requiredRatio - realRatio ) &lt; 0.000001 ) {
				return true;
			}

			return false;
		},

		/**
		 * If cropping was skipped, apply the image data directly to the setting.
		 */
		onSkippedCrop: function() {
			var attachment = this.frame.state().get( &#039;selection&#039; ).first().toJSON();
			this.setImageFromAttachment( attachment );
		},

		/**
		 * Updates the setting and re-renders the control UI.
		 *
		 * @param {Object} attachment
		 */
		setImageFromAttachment: function( attachment ) {
			var control = this;
			this.params.attachment = attachment;

			// Set the Customizer setting; the callback takes care of rendering.
			this.setting( attachment.id );

			// Set focus to the first relevant button after the icon.
			_.defer( function() {
				var firstButton = control.container.find( &#039;.actions .button&#039; ).first();
				if ( firstButton.length ) {
					firstButton.focus();
				}
			} );
		}
	});

	/**
	 * A control for selecting and cropping Site Icons.
	 *
	 * @class    wp.customize.SiteIconControl
	 * @augments wp.customize.CroppedImageControl
	 */
	api.SiteIconControl = api.CroppedImageControl.extend(/** @lends wp.customize.SiteIconControl.prototype */{

		/**
		 * Create a media modal select frame, and store it so the instance can be reused when needed.
		 */
		initFrame: function() {
			var l10n = _wpMediaViewsL10n;

			this.frame = wp.media({
				button: {
					text: l10n.select,
					close: false
				},
				states: [
					new wp.media.controller.Library({
						title: this.params.button_labels.frame_title,
						library: wp.media.query({ type: &#039;image&#039; }),
						multiple: false,
						date: false,
						priority: 20,
						suggestedWidth: this.params.width,
						suggestedHeight: this.params.height
					}),
					new wp.media.controller.SiteIconCropper({
						imgSelectOptions: this.calculateImageSelectOptions,
						control: this
					})
				]
			});

			this.frame.on( &#039;select&#039;, this.onSelect, this );
			this.frame.on( &#039;cropped&#039;, this.onCropped, this );
			this.frame.on( &#039;skippedcrop&#039;, this.onSkippedCrop, this );
		},

		/**
		 * After an image is selected in the media modal, switch to the cropper
		 * state if the image isn&#039;t the right size.
		 */
		onSelect: function() {
			var attachment = this.frame.state().get( &#039;selection&#039; ).first().toJSON(),
				controller = this;

			if ( this.params.width === attachment.width &amp;&amp; this.params.height === attachment.height &amp;&amp; ! this.params.flex_width &amp;&amp; ! this.params.flex_height ) {
				wp.ajax.post( &#039;crop-image&#039;, {
					nonce: attachment.nonces.edit,
					id: attachment.id,
					context: &#039;site-icon&#039;,
					cropDetails: {
						x1: 0,
						y1: 0,
						width: this.params.width,
						height: this.params.height,
						dst_width: this.params.width,
						dst_height: this.params.height
					}
				} ).done( function( croppedImage ) {
					controller.setImageFromAttachment( croppedImage );
					controller.frame.close();
				} ).fail( function() {
					controller.frame.trigger(&#039;content:error:crop&#039;);
				} );
			} else {
				this.frame.setState( &#039;cropper&#039; );
			}
		},

		/**
		 * Updates the setting and re-renders the control UI.
		 *
		 * @param {Object} attachment
		 */
		setImageFromAttachment: function( attachment ) {
			var control = this,
				sizes = [ &#039;site_icon-32&#039;, &#039;thumbnail&#039;, &#039;full&#039; ], link,
				icon;

			_.each( sizes, function( size ) {
				if ( ! icon &amp;&amp; ! _.isUndefined ( attachment.sizes[ size ] ) ) {
					icon = attachment.sizes[ size ];
				}
			} );

			this.params.attachment = attachment;

			// Set the Customizer setting; the callback takes care of rendering.
			this.setting( attachment.id );

			if ( ! icon ) {
				return;
			}

			// Update the icon in-browser.
			link = $( &#039;link[rel=&quot;icon&quot;][sizes=&quot;32x32&quot;]&#039; );
			link.attr( &#039;href&#039;, icon.url );

			// Set focus to the first relevant button after the icon.
			_.defer( function() {
				var firstButton = control.container.find( &#039;.actions .button&#039; ).first();
				if ( firstButton.length ) {
					firstButton.focus();
				}
			} );
		},

		/**
		 * Called when the &quot;Remove&quot; link is clicked. Empties the setting.
		 *
		 * @param {Object} event jQuery Event object
		 */
		removeFile: function( event ) {
			if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
				return;
			}
			event.preventDefault();

			this.params.attachment = {};
			this.setting( &#039;&#039; );
			this.renderContent(); // Not bound to setting change when emptying.
			$( &#039;link[rel=&quot;icon&quot;][sizes=&quot;32x32&quot;]&#039; ).attr( &#039;href&#039;, &#039;/favicon.ico&#039; ); // Set to default.
		}
	});

	/**
	 * @class    wp.customize.HeaderControl
	 * @augments wp.customize.Control
	 */
	api.HeaderControl = api.Control.extend(/** @lends wp.customize.HeaderControl.prototype */{
		ready: function() {
			this.btnRemove = $(&#039;#customize-control-header_image .actions .remove&#039;);
			this.btnNew    = $(&#039;#customize-control-header_image .actions .new&#039;);

			_.bindAll(this, &#039;openMedia&#039;, &#039;removeImage&#039;);

			this.btnNew.on( &#039;click&#039;, this.openMedia );
			this.btnRemove.on( &#039;click&#039;, this.removeImage );

			api.HeaderTool.currentHeader = this.getInitialHeaderImage();

			new api.HeaderTool.CurrentView({
				model: api.HeaderTool.currentHeader,
				el: &#039;#customize-control-header_image .current .container&#039;
			});

			new api.HeaderTool.ChoiceListView({
				collection: api.HeaderTool.UploadsList = new api.HeaderTool.ChoiceList(),
				el: &#039;#customize-control-header_image .choices .uploaded .list&#039;
			});

			new api.HeaderTool.ChoiceListView({
				collection: api.HeaderTool.DefaultsList = new api.HeaderTool.DefaultsList(),
				el: &#039;#customize-control-header_image .choices .default .list&#039;
			});

			api.HeaderTool.combinedList = api.HeaderTool.CombinedList = new api.HeaderTool.CombinedList([
				api.HeaderTool.UploadsList,
				api.HeaderTool.DefaultsList
			]);

			// Ensure custom-header-crop Ajax requests bootstrap the Customizer to activate the previewed theme.
			wp.media.controller.Cropper.prototype.defaults.doCropArgs.wp_customize = &#039;on&#039;;
			wp.media.controller.Cropper.prototype.defaults.doCropArgs.customize_theme = api.settings.theme.stylesheet;
		},

		/**
		 * Returns a new instance of api.HeaderTool.ImageModel based on the currently
		 * saved header image (if any).
		 *
		 * @since 4.2.0
		 *
		 * @return {Object} Options
		 */
		getInitialHeaderImage: function() {
			if ( ! api.get().header_image || ! api.get().header_image_data || _.contains( [ &#039;remove-header&#039;, &#039;random-default-image&#039;, &#039;random-uploaded-image&#039; ], api.get().header_image ) ) {
				return new api.HeaderTool.ImageModel();
			}

			// Get the matching uploaded image object.
			var currentHeaderObject = _.find( _wpCustomizeHeader.uploads, function( imageObj ) {
				return ( imageObj.attachment_id === api.get().header_image_data.attachment_id );
			} );
			// Fall back to raw current header image.
			if ( ! currentHeaderObject ) {
				currentHeaderObject = {
					url: api.get().header_image,
					thumbnail_url: api.get().header_image,
					attachment_id: api.get().header_image_data.attachment_id
				};
			}

			return new api.HeaderTool.ImageModel({
				header: currentHeaderObject,
				choice: currentHeaderObject.url.split( &#039;/&#039; ).pop()
			});
		},

		/**
		 * Returns a set of options, computed from the attached image data and
		 * theme-specific data, to be fed to the imgAreaSelect plugin in
		 * wp.media.view.Cropper.
		 *
		 * @param {wp.media.model.Attachment} attachment
		 * @param {wp.media.controller.Cropper} controller
		 * @return {Object} Options
		 */
		calculateImageSelectOptions: function(attachment, controller) {
			var xInit = parseInt(_wpCustomizeHeader.data.width, 10),
				yInit = parseInt(_wpCustomizeHeader.data.height, 10),
				flexWidth = !! parseInt(_wpCustomizeHeader.data[&#039;flex-width&#039;], 10),
				flexHeight = !! parseInt(_wpCustomizeHeader.data[&#039;flex-height&#039;], 10),
				ratio, xImg, yImg, realHeight, realWidth,
				imgSelectOptions;

			realWidth = attachment.get(&#039;width&#039;);
			realHeight = attachment.get(&#039;height&#039;);

			this.headerImage = new api.HeaderTool.ImageModel();
			this.headerImage.set({
				themeWidth: xInit,
				themeHeight: yInit,
				themeFlexWidth: flexWidth,
				themeFlexHeight: flexHeight,
				imageWidth: realWidth,
				imageHeight: realHeight
			});

			controller.set( &#039;canSkipCrop&#039;, ! this.headerImage.shouldBeCropped() );

			ratio = xInit / yInit;
			xImg = realWidth;
			yImg = realHeight;

			if ( xImg / yImg &gt; ratio ) {
				yInit = yImg;
				xInit = yInit * ratio;
			} else {
				xInit = xImg;
				yInit = xInit / ratio;
			}

			imgSelectOptions = {
				handles: true,
				keys: true,
				instance: true,
				persistent: true,
				imageWidth: realWidth,
				imageHeight: realHeight,
				x1: 0,
				y1: 0,
				x2: xInit,
				y2: yInit
			};

			if (flexHeight === false &amp;&amp; flexWidth === false) {
				imgSelectOptions.aspectRatio = xInit + &#039;:&#039; + yInit;
			}
			if (flexHeight === false ) {
				imgSelectOptions.maxHeight = yInit;
			}
			if (flexWidth === false ) {
				imgSelectOptions.maxWidth = xInit;
			}

			return imgSelectOptions;
		},

		/**
		 * Sets up and opens the Media Manager in order to select an image.
		 * Depending on both the size of the image and the properties of the
		 * current theme, a cropping step after selection may be required or
		 * skippable.
		 *
		 * @param {event} event
		 */
		openMedia: function(event) {
			var l10n = _wpMediaViewsL10n;

			event.preventDefault();

			this.frame = wp.media({
				button: {
					text: l10n.selectAndCrop,
					close: false
				},
				states: [
					new wp.media.controller.Library({
						title:     l10n.chooseImage,
						library:   wp.media.query({ type: &#039;image&#039; }),
						multiple:  false,
						date:      false,
						priority:  20,
						suggestedWidth: _wpCustomizeHeader.data.width,
						suggestedHeight: _wpCustomizeHeader.data.height
					}),
					new wp.media.controller.Cropper({
						imgSelectOptions: this.calculateImageSelectOptions
					})
				]
			});

			this.frame.on(&#039;select&#039;, this.onSelect, this);
			this.frame.on(&#039;cropped&#039;, this.onCropped, this);
			this.frame.on(&#039;skippedcrop&#039;, this.onSkippedCrop, this);

			this.frame.open();
		},

		/**
		 * After an image is selected in the media modal,
		 * switch to the cropper state.
		 */
		onSelect: function() {
			this.frame.setState(&#039;cropper&#039;);
		},

		/**
		 * After the image has been cropped, apply the cropped image data to the setting.
		 *
		 * @param {Object} croppedImage Cropped attachment data.
		 */
		onCropped: function(croppedImage) {
			var url = croppedImage.url,
				attachmentId = croppedImage.attachment_id,
				w = croppedImage.width,
				h = croppedImage.height;
			this.setImageFromURL(url, attachmentId, w, h);
		},

		/**
		 * If cropping was skipped, apply the image data directly to the setting.
		 *
		 * @param {Object} selection
		 */
		onSkippedCrop: function(selection) {
			var url = selection.get(&#039;url&#039;),
				w = selection.get(&#039;width&#039;),
				h = selection.get(&#039;height&#039;);
			this.setImageFromURL(url, selection.id, w, h);
		},

		/**
		 * Creates a new wp.customize.HeaderTool.ImageModel from provided
		 * header image data and inserts it into the user-uploaded headers
		 * collection.
		 *
		 * @param {string} url
		 * @param {number} attachmentId
		 * @param {number} width
		 * @param {number} height
		 */
		setImageFromURL: function(url, attachmentId, width, height) {
			var choice, data = {};

			data.url = url;
			data.thumbnail_url = url;
			data.timestamp = _.now();

			if (attachmentId) {
				data.attachment_id = attachmentId;
			}

			if (width) {
				data.width = width;
			}

			if (height) {
				data.height = height;
			}

			choice = new api.HeaderTool.ImageModel({
				header: data,
				choice: url.split(&#039;/&#039;).pop()
			});
			api.HeaderTool.UploadsList.add(choice);
			api.HeaderTool.currentHeader.set(choice.toJSON());
			choice.save();
			choice.importImage();
		},

		/**
		 * Triggers the necessary events to deselect an image which was set as
		 * the currently selected one.
		 */
		removeImage: function() {
			api.HeaderTool.currentHeader.trigger(&#039;hide&#039;);
			api.HeaderTool.CombinedList.trigger(&#039;control:removeImage&#039;);
		}

	});

	/**
	 * wp.customize.ThemeControl
	 *
	 * @class    wp.customize.ThemeControl
	 * @augments wp.customize.Control
	 */
	api.ThemeControl = api.Control.extend(/** @lends wp.customize.ThemeControl.prototype */{

		touchDrag: false,
		screenshotRendered: false,

		/**
		 * @since 4.2.0
		 */
		ready: function() {
			var control = this, panel = api.panel( &#039;themes&#039; );

			function disableSwitchButtons() {
				return ! panel.canSwitchTheme( control.params.theme.id );
			}

			// Temporary special function since supplying SFTP credentials does not work yet. See #42184.
			function disableInstallButtons() {
				return disableSwitchButtons() || false === api.settings.theme._canInstall || true === api.settings.theme._filesystemCredentialsNeeded;
			}
			function updateButtons() {
				control.container.find( &#039;button.preview, button.preview-theme&#039; ).toggleClass( &#039;disabled&#039;, disableSwitchButtons() );
				control.container.find( &#039;button.theme-install&#039; ).toggleClass( &#039;disabled&#039;, disableInstallButtons() );
			}

			api.state( &#039;selectedChangesetStatus&#039; ).bind( updateButtons );
			api.state( &#039;changesetStatus&#039; ).bind( updateButtons );
			updateButtons();

			control.container.on( &#039;touchmove&#039;, &#039;.theme&#039;, function() {
				control.touchDrag = true;
			});

			// Bind details view trigger.
			control.container.on( &#039;click keydown touchend&#039;, &#039;.theme&#039;, function( event ) {
				var section;
				if ( api.utils.isKeydownButNotEnterEvent( event ) ) {
					return;
				}

				// Bail if the user scrolled on a touch device.
				if ( control.touchDrag === true ) {
					return control.touchDrag = false;
				}

				// Prevent the modal from showing when the user clicks the action button.
				if ( $( event.target ).is( &#039;.theme-actions .button, .update-theme&#039; ) ) {
					return;
				}

				event.preventDefault(); // Keep this AFTER the key filter above.
				section = api.section( control.section() );
				section.showDetails( control.params.theme, function() {

					// Temporary special function since supplying SFTP credentials does not work yet. See #42184.
					if ( api.settings.theme._filesystemCredentialsNeeded ) {
						section.overlay.find( &#039;.theme-actions .delete-theme&#039; ).remove();
					}
				} );
			});

			control.container.on( &#039;render-screenshot&#039;, function() {
				var $screenshot = $( this ).find( &#039;img&#039; ),
					source = $screenshot.data( &#039;src&#039; );

				if ( source ) {
					$screenshot.attr( &#039;src&#039;, source );
				}
				control.screenshotRendered = true;
			});
		},

		/**
		 * Show or hide the theme based on the presence of the term in the title, description, tags, and author.
		 *
		 * @since 4.2.0
		 * @param {Array} terms - An array of terms to search for.
		 * @return {boolean} Whether a theme control was activated or not.
		 */
		filter: function( terms ) {
			var control = this,
				matchCount = 0,
				haystack = control.params.theme.name + &#039; &#039; +
					control.params.theme.description + &#039; &#039; +
					control.params.theme.tags + &#039; &#039; +
					control.params.theme.author + &#039; &#039;;
			haystack = haystack.toLowerCase().replace( &#039;-&#039;, &#039; &#039; );

			// Back-compat for behavior in WordPress 4.2.0 to 4.8.X.
			if ( ! _.isArray( terms ) ) {
				terms = [ terms ];
			}

			// Always give exact name matches highest ranking.
			if ( control.params.theme.name.toLowerCase() === terms.join( &#039; &#039; ) ) {
				matchCount = 100;
			} else {

				// Search for and weight (by 10) complete term matches.
				matchCount = matchCount + 10 * ( haystack.split( terms.join( &#039; &#039; ) ).length - 1 );

				// Search for each term individually (as whole-word and partial match) and sum weighted match counts.
				_.each( terms, function( term ) {
					matchCount = matchCount + 2 * ( haystack.split( term + &#039; &#039; ).length - 1 ); // Whole-word, double-weighted.
					matchCount = matchCount + haystack.split( term ).length - 1; // Partial word, to minimize empty intermediate searches while typing.
				});

				// Upper limit on match ranking.
				if ( matchCount &gt; 99 ) {
					matchCount = 99;
				}
			}

			if ( 0 !== matchCount ) {
				control.activate();
				control.params.priority = 101 - matchCount; // Sort results by match count.
				return true;
			} else {
				control.deactivate(); // Hide control.
				control.params.priority = 101;
				return false;
			}
		},

		/**
		 * Rerender the theme from its JS template with the installed type.
		 *
		 * @since 4.9.0
		 *
		 * @return {void}
		 */
		rerenderAsInstalled: function( installed ) {
			var control = this, section;
			if ( installed ) {
				control.params.theme.type = &#039;installed&#039;;
			} else {
				section = api.section( control.params.section );
				control.params.theme.type = section.params.action;
			}
			control.renderContent(); // Replaces existing content.
			control.container.trigger( &#039;render-screenshot&#039; );
		}
	});

	/**
	 * Class wp.customize.CodeEditorControl
	 *
	 * @since 4.9.0
	 *
	 * @class    wp.customize.CodeEditorControl
	 * @augments wp.customize.Control
	 */
	api.CodeEditorControl = api.Control.extend(/** @lends wp.customize.CodeEditorControl.prototype */{

		/**
		 * Initialize.
		 *
		 * @since 4.9.0
		 * @param {string} id      - Unique identifier for the control instance.
		 * @param {Object} options - Options hash for the control instance.
		 * @return {void}
		 */
		initialize: function( id, options ) {
			var control = this;
			control.deferred = _.extend( control.deferred || {}, {
				codemirror: $.Deferred()
			} );
			api.Control.prototype.initialize.call( control, id, options );

			// Note that rendering is debounced so the props will be used when rendering happens after add event.
			control.notifications.bind( &#039;add&#039;, function( notification ) {

				// Skip if control notification is not from setting csslint_error notification.
				if ( notification.code !== control.setting.id + &#039;:csslint_error&#039; ) {
					return;
				}

				// Customize the template and behavior of csslint_error notifications.
				notification.templateId = &#039;customize-code-editor-lint-error-notification&#039;;
				notification.render = (function( render ) {
					return function() {
						var li = render.call( this );
						li.find( &#039;input[type=checkbox]&#039; ).on( &#039;click&#039;, function() {
							control.setting.notifications.remove( &#039;csslint_error&#039; );
						} );
						return li;
					};
				})( notification.render );
			} );
		},

		/**
		 * Initialize the editor when the containing section is ready and expanded.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		ready: function() {
			var control = this;
			if ( ! control.section() ) {
				control.initEditor();
				return;
			}

			// Wait to initialize editor until section is embedded and expanded.
			api.section( control.section(), function( section ) {
				section.deferred.embedded.done( function() {
					var onceExpanded;
					if ( section.expanded() ) {
						control.initEditor();
					} else {
						onceExpanded = function( isExpanded ) {
							if ( isExpanded ) {
								control.initEditor();
								section.expanded.unbind( onceExpanded );
							}
						};
						section.expanded.bind( onceExpanded );
					}
				} );
			} );
		},

		/**
		 * Initialize editor.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		initEditor: function() {
			var control = this, element, editorSettings = false;

			// Obtain editorSettings for instantiation.
			if ( wp.codeEditor &amp;&amp; ( _.isUndefined( control.params.editor_settings ) || false !== control.params.editor_settings ) ) {

				// Obtain default editor settings.
				editorSettings = wp.codeEditor.defaultSettings ? _.clone( wp.codeEditor.defaultSettings ) : {};
				editorSettings.codemirror = _.extend(
					{},
					editorSettings.codemirror,
					{
						indentUnit: 2,
						tabSize: 2
					}
				);

				// Merge editor_settings param on top of defaults.
				if ( _.isObject( control.params.editor_settings ) ) {
					_.each( control.params.editor_settings, function( value, key ) {
						if ( _.isObject( value ) ) {
							editorSettings[ key ] = _.extend(
								{},
								editorSettings[ key ],
								value
							);
						}
					} );
				}
			}

			element = new api.Element( control.container.find( &#039;textarea&#039; ) );
			control.elements.push( element );
			element.sync( control.setting );
			element.set( control.setting() );

			if ( editorSettings ) {
				control.initSyntaxHighlightingEditor( editorSettings );
			} else {
				control.initPlainTextareaEditor();
			}
		},

		/**
		 * Make sure editor gets focused when control is focused.
		 *
		 * @since 4.9.0
		 * @param {Object}   [params] - Focus params.
		 * @param {Function} [params.completeCallback] - Function to call when expansion is complete.
		 * @return {void}
		 */
		focus: function( params ) {
			var control = this, extendedParams = _.extend( {}, params ), originalCompleteCallback;
			originalCompleteCallback = extendedParams.completeCallback;
			extendedParams.completeCallback = function() {
				if ( originalCompleteCallback ) {
					originalCompleteCallback();
				}
				if ( control.editor ) {
					control.editor.codemirror.focus();
				}
			};
			api.Control.prototype.focus.call( control, extendedParams );
		},

		/**
		 * Initialize syntax-highlighting editor.
		 *
		 * @since 4.9.0
		 * @param {Object} codeEditorSettings - Code editor settings.
		 * @return {void}
		 */
		initSyntaxHighlightingEditor: function( codeEditorSettings ) {
			var control = this, $textarea = control.container.find( &#039;textarea&#039; ), settings, suspendEditorUpdate = false;

			settings = _.extend( {}, codeEditorSettings, {
				onTabNext: _.bind( control.onTabNext, control ),
				onTabPrevious: _.bind( control.onTabPrevious, control ),
				onUpdateErrorNotice: _.bind( control.onUpdateErrorNotice, control )
			});

			control.editor = wp.codeEditor.initialize( $textarea, settings );

			// Improve the editor accessibility.
			$( control.editor.codemirror.display.lineDiv )
				.attr({
					role: &#039;textbox&#039;,
					&#039;aria-multiline&#039;: &#039;true&#039;,
					&#039;aria-label&#039;: control.params.label,
					&#039;aria-describedby&#039;: &#039;editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4&#039;
				});

			// Focus the editor when clicking on its label.
			control.container.find( &#039;label&#039; ).on( &#039;click&#039;, function() {
				control.editor.codemirror.focus();
			});

			/*
			 * When the CodeMirror instance changes, mirror to the textarea,
			 * where we have our &quot;true&quot; change event handler bound.
			 */
			control.editor.codemirror.on( &#039;change&#039;, function( codemirror ) {
				suspendEditorUpdate = true;
				$textarea.val( codemirror.getValue() ).trigger( &#039;change&#039; );
				suspendEditorUpdate = false;
			});

			// Update CodeMirror when the setting is changed by another plugin.
			control.setting.bind( function( value ) {
				if ( ! suspendEditorUpdate ) {
					control.editor.codemirror.setValue( value );
				}
			});

			// Prevent collapsing section when hitting Esc to tab out of editor.
			control.editor.codemirror.on( &#039;keydown&#039;, function onKeydown( codemirror, event ) {
				var escKeyCode = 27;
				if ( escKeyCode === event.keyCode ) {
					event.stopPropagation();
				}
			});

			control.deferred.codemirror.resolveWith( control, [ control.editor.codemirror ] );
		},

		/**
		 * Handle tabbing to the field after the editor.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		onTabNext: function onTabNext() {
			var control = this, controls, controlIndex, section;
			section = api.section( control.section() );
			controls = section.controls();
			controlIndex = controls.indexOf( control );
			if ( controls.length === controlIndex + 1 ) {
				$( &#039;#customize-footer-actions .collapse-sidebar&#039; ).trigger( &#039;focus&#039; );
			} else {
				controls[ controlIndex + 1 ].container.find( &#039;:focusable:first&#039; ).focus();
			}
		},

		/**
		 * Handle tabbing to the field before the editor.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		onTabPrevious: function onTabPrevious() {
			var control = this, controls, controlIndex, section;
			section = api.section( control.section() );
			controls = section.controls();
			controlIndex = controls.indexOf( control );
			if ( 0 === controlIndex ) {
				section.contentContainer.find( &#039;.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close&#039; ).last().focus();
			} else {
				controls[ controlIndex - 1 ].contentContainer.find( &#039;:focusable:first&#039; ).focus();
			}
		},

		/**
		 * Update error notice.
		 *
		 * @since 4.9.0
		 * @param {Array} errorAnnotations - Error annotations.
		 * @return {void}
		 */
		onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
			var control = this, message;
			control.setting.notifications.remove( &#039;csslint_error&#039; );

			if ( 0 !== errorAnnotations.length ) {
				if ( 1 === errorAnnotations.length ) {
					message = api.l10n.customCssError.singular.replace( &#039;%d&#039;, &#039;1&#039; );
				} else {
					message = api.l10n.customCssError.plural.replace( &#039;%d&#039;, String( errorAnnotations.length ) );
				}
				control.setting.notifications.add( new api.Notification( &#039;csslint_error&#039;, {
					message: message,
					type: &#039;error&#039;
				} ) );
			}
		},

		/**
		 * Initialize plain-textarea editor when syntax highlighting is disabled.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		initPlainTextareaEditor: function() {
			var control = this, $textarea = control.container.find( &#039;textarea&#039; ), textarea = $textarea[0];

			$textarea.on( &#039;blur&#039;, function onBlur() {
				$textarea.data( &#039;next-tab-blurs&#039;, false );
			} );

			$textarea.on( &#039;keydown&#039;, function onKeydown( event ) {
				var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;

				if ( escKeyCode === event.keyCode ) {
					if ( ! $textarea.data( &#039;next-tab-blurs&#039; ) ) {
						$textarea.data( &#039;next-tab-blurs&#039;, true );
						event.stopPropagation(); // Prevent collapsing the section.
					}
					return;
				}

				// Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
				if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
					return;
				}

				// Prevent capturing Tab characters if Esc was pressed.
				if ( $textarea.data( &#039;next-tab-blurs&#039; ) ) {
					return;
				}

				selectionStart = textarea.selectionStart;
				selectionEnd = textarea.selectionEnd;
				value = textarea.value;

				if ( selectionStart &gt;= 0 ) {
					textarea.value = value.substring( 0, selectionStart ).concat( &#039;\t&#039;, value.substring( selectionEnd ) );
					$textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
				}

				event.stopPropagation();
				event.preventDefault();
			});

			control.deferred.codemirror.rejectWith( control );
		}
	});

	/**
	 * Class wp.customize.DateTimeControl.
	 *
	 * @since 4.9.0
	 * @class    wp.customize.DateTimeControl
	 * @augments wp.customize.Control
	 */
	api.DateTimeControl = api.Control.extend(/** @lends wp.customize.DateTimeControl.prototype */{

		/**
		 * Initialize behaviors.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		ready: function ready() {
			var control = this;

			control.inputElements = {};
			control.invalidDate = false;

			_.bindAll( control, &#039;populateSetting&#039;, &#039;updateDaysForMonth&#039;, &#039;populateDateInputs&#039; );

			if ( ! control.setting ) {
				throw new Error( &#039;Missing setting&#039; );
			}

			control.container.find( &#039;.date-input&#039; ).each( function() {
				var input = $( this ), component, element;
				component = input.data( &#039;component&#039; );
				element = new api.Element( input );
				control.inputElements[ component ] = element;
				control.elements.push( element );

				// Add invalid date error once user changes (and has blurred the input).
				input.on( &#039;change&#039;, function() {
					if ( control.invalidDate ) {
						control.notifications.add( new api.Notification( &#039;invalid_date&#039;, {
							message: api.l10n.invalidDate
						} ) );
					}
				} );

				// Remove the error immediately after validity change.
				input.on( &#039;input&#039;, _.debounce( function() {
					if ( ! control.invalidDate ) {
						control.notifications.remove( &#039;invalid_date&#039; );
					}
				} ) );

				// Add zero-padding when blurring field.
				input.on( &#039;blur&#039;, _.debounce( function() {
					if ( ! control.invalidDate ) {
						control.populateDateInputs();
					}
				} ) );
			} );

			control.inputElements.month.bind( control.updateDaysForMonth );
			control.inputElements.year.bind( control.updateDaysForMonth );
			control.populateDateInputs();
			control.setting.bind( control.populateDateInputs );

			// Start populating setting after inputs have been populated.
			_.each( control.inputElements, function( element ) {
				element.bind( control.populateSetting );
			} );
		},

		/**
		 * Parse datetime string.
		 *
		 * @since 4.9.0
		 *
		 * @param {string} datetime - Date/Time string. Accepts Y-m-d[ H:i[:s]] format.
		 * @return {Object|null} Returns object containing date components or null if parse error.
		 */
		parseDateTime: function parseDateTime( datetime ) {
			var control = this, matches, date, midDayHour = 12;

			if ( datetime ) {
				matches = datetime.match( /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d)(?::(\d\d))?)?$/ );
			}

			if ( ! matches ) {
				return null;
			}

			matches.shift();

			date = {
				year: matches.shift(),
				month: matches.shift(),
				day: matches.shift(),
				hour: matches.shift() || &#039;00&#039;,
				minute: matches.shift() || &#039;00&#039;,
				second: matches.shift() || &#039;00&#039;
			};

			if ( control.params.includeTime &amp;&amp; control.params.twelveHourFormat ) {
				date.hour = parseInt( date.hour, 10 );
				date.meridian = date.hour &gt;= midDayHour ? &#039;pm&#039; : &#039;am&#039;;
				date.hour = date.hour % midDayHour ? String( date.hour % midDayHour ) : String( midDayHour );
				delete date.second; // @todo Why only if twelveHourFormat?
			}

			return date;
		},

		/**
		 * Validates if input components have valid date and time.
		 *
		 * @since 4.9.0
		 * @return {boolean} If date input fields has error.
		 */
		validateInputs: function validateInputs() {
			var control = this, components, validityInput;

			control.invalidDate = false;

			components = [ &#039;year&#039;, &#039;day&#039; ];
			if ( control.params.includeTime ) {
				components.push( &#039;hour&#039;, &#039;minute&#039; );
			}

			_.find( components, function( component ) {
				var element, max, min, value;

				element = control.inputElements[ component ];
				validityInput = element.element.get( 0 );
				max = parseInt( element.element.attr( &#039;max&#039; ), 10 );
				min = parseInt( element.element.attr( &#039;min&#039; ), 10 );
				value = parseInt( element(), 10 );
				control.invalidDate = isNaN( value ) || value &gt; max || value &lt; min;

				if ( ! control.invalidDate ) {
					validityInput.setCustomValidity( &#039;&#039; );
				}

				return control.invalidDate;
			} );

			if ( control.inputElements.meridian &amp;&amp; ! control.invalidDate ) {
				validityInput = control.inputElements.meridian.element.get( 0 );
				if ( &#039;am&#039; !== control.inputElements.meridian.get() &amp;&amp; &#039;pm&#039; !== control.inputElements.meridian.get() ) {
					control.invalidDate = true;
				} else {
					validityInput.setCustomValidity( &#039;&#039; );
				}
			}

			if ( control.invalidDate ) {
				validityInput.setCustomValidity( api.l10n.invalidValue );
			} else {
				validityInput.setCustomValidity( &#039;&#039; );
			}
			if ( ! control.section() || api.section.has( control.section() ) &amp;&amp; api.section( control.section() ).expanded() ) {
				_.result( validityInput, &#039;reportValidity&#039; );
			}

			return control.invalidDate;
		},

		/**
		 * Updates number of days according to the month and year selected.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		updateDaysForMonth: function updateDaysForMonth() {
			var control = this, daysInMonth, year, month, day;

			month = parseInt( control.inputElements.month(), 10 );
			year = parseInt( control.inputElements.year(), 10 );
			day = parseInt( control.inputElements.day(), 10 );

			if ( month &amp;&amp; year ) {
				daysInMonth = new Date( year, month, 0 ).getDate();
				control.inputElements.day.element.attr( &#039;max&#039;, daysInMonth );

				if ( day &gt; daysInMonth ) {
					control.inputElements.day( String( daysInMonth ) );
				}
			}
		},

		/**
		 * Populate setting value from the inputs.
		 *
		 * @since 4.9.0
		 * @return {boolean} If setting updated.
		 */
		populateSetting: function populateSetting() {
			var control = this, date;

			if ( control.validateInputs() || ! control.params.allowPastDate &amp;&amp; ! control.isFutureDate() ) {
				return false;
			}

			date = control.convertInputDateToString();
			control.setting.set( date );
			return true;
		},

		/**
		 * Converts input values to string in Y-m-d H:i:s format.
		 *
		 * @since 4.9.0
		 * @return {string} Date string.
		 */
		convertInputDateToString: function convertInputDateToString() {
			var control = this, date = &#039;&#039;, dateFormat, hourInTwentyFourHourFormat,
				getElementValue, pad;

			pad = function( number, padding ) {
				var zeros;
				if ( String( number ).length &lt; padding ) {
					zeros = padding - String( number ).length;
					number = Math.pow( 10, zeros ).toString().substr( 1 ) + String( number );
				}
				return number;
			};

			getElementValue = function( component ) {
				var value = parseInt( control.inputElements[ component ].get(), 10 );

				if ( _.contains( [ &#039;month&#039;, &#039;day&#039;, &#039;hour&#039;, &#039;minute&#039; ], component ) ) {
					value = pad( value, 2 );
				} else if ( &#039;year&#039; === component ) {
					value = pad( value, 4 );
				}
				return value;
			};

			dateFormat = [ &#039;year&#039;, &#039;-&#039;, &#039;month&#039;, &#039;-&#039;, &#039;day&#039; ];
			if ( control.params.includeTime ) {
				hourInTwentyFourHourFormat = control.inputElements.meridian ? control.convertHourToTwentyFourHourFormat( control.inputElements.hour(), control.inputElements.meridian() ) : control.inputElements.hour();
				dateFormat = dateFormat.concat( [ &#039; &#039;, pad( hourInTwentyFourHourFormat, 2 ), &#039;:&#039;, &#039;minute&#039;, &#039;:&#039;, &#039;00&#039; ] );
			}

			_.each( dateFormat, function( component ) {
				date += control.inputElements[ component ] ? getElementValue( component ) : component;
			} );

			return date;
		},

		/**
		 * Check if the date is in the future.
		 *
		 * @since 4.9.0
		 * @return {boolean} True if future date.
		 */
		isFutureDate: function isFutureDate() {
			var control = this;
			return 0 &lt; api.utils.getRemainingTime( control.convertInputDateToString() );
		},

		/**
		 * Convert hour in twelve hour format to twenty four hour format.
		 *
		 * @since 4.9.0
		 * @param {string} hourInTwelveHourFormat - Hour in twelve hour format.
		 * @param {string} meridian - Either &#039;am&#039; or &#039;pm&#039;.
		 * @return {string} Hour in twenty four hour format.
		 */
		convertHourToTwentyFourHourFormat: function convertHour( hourInTwelveHourFormat, meridian ) {
			var hourInTwentyFourHourFormat, hour, midDayHour = 12;

			hour = parseInt( hourInTwelveHourFormat, 10 );
			if ( isNaN( hour ) ) {
				return &#039;&#039;;
			}

			if ( &#039;pm&#039; === meridian &amp;&amp; hour &lt; midDayHour ) {
				hourInTwentyFourHourFormat = hour + midDayHour;
			} else if ( &#039;am&#039; === meridian &amp;&amp; midDayHour === hour ) {
				hourInTwentyFourHourFormat = hour - midDayHour;
			} else {
				hourInTwentyFourHourFormat = hour;
			}

			return String( hourInTwentyFourHourFormat );
		},

		/**
		 * Populates date inputs in date fields.
		 *
		 * @since 4.9.0
		 * @return {boolean} Whether the inputs were populated.
		 */
		populateDateInputs: function populateDateInputs() {
			var control = this, parsed;

			parsed = control.parseDateTime( control.setting.get() );

			if ( ! parsed ) {
				return false;
			}

			_.each( control.inputElements, function( element, component ) {
				var value = parsed[ component ]; // This will be zero-padded string.

				// Set month and meridian regardless of focused state since they are dropdowns.
				if ( &#039;month&#039; === component || &#039;meridian&#039; === component ) {

					// Options in dropdowns are not zero-padded.
					value = value.replace( /^0/, &#039;&#039; );

					element.set( value );
				} else {

					value = parseInt( value, 10 );
					if ( ! element.element.is( document.activeElement ) ) {

						// Populate element with zero-padded value if not focused.
						element.set( parsed[ component ] );
					} else if ( value !== parseInt( element(), 10 ) ) {

						// Forcibly update the value if its underlying value changed, regardless of zero-padding.
						element.set( String( value ) );
					}
				}
			} );

			return true;
		},

		/**
		 * Toggle future date notification for date control.
		 *
		 * @since 4.9.0
		 * @param {boolean} notify Add or remove the notification.
		 * @return {wp.customize.DateTimeControl}
		 */
		toggleFutureDateNotification: function toggleFutureDateNotification( notify ) {
			var control = this, notificationCode, notification;

			notificationCode = &#039;not_future_date&#039;;

			if ( notify ) {
				notification = new api.Notification( notificationCode, {
					type: &#039;error&#039;,
					message: api.l10n.futureDateError
				} );
				control.notifications.add( notification );
			} else {
				control.notifications.remove( notificationCode );
			}

			return control;
		}
	});

	/**
	 * Class PreviewLinkControl.
	 *
	 * @since 4.9.0
	 * @class    wp.customize.PreviewLinkControl
	 * @augments wp.customize.Control
	 */
	api.PreviewLinkControl = api.Control.extend(/** @lends wp.customize.PreviewLinkControl.prototype */{

		defaults: _.extend( {}, api.Control.prototype.defaults, {
			templateId: &#039;customize-preview-link-control&#039;
		} ),

		/**
		 * Initialize behaviors.
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		ready: function ready() {
			var control = this, element, component, node, url, input, button;

			_.bindAll( control, &#039;updatePreviewLink&#039; );

			if ( ! control.setting ) {
			    control.setting = new api.Value();
			}

			control.previewElements = {};

			control.container.find( &#039;.preview-control-element&#039; ).each( function() {
				node = $( this );
				component = node.data( &#039;component&#039; );
				element = new api.Element( node );
				control.previewElements[ component ] = element;
				control.elements.push( element );
			} );

			url = control.previewElements.url;
			input = control.previewElements.input;
			button = control.previewElements.button;

			input.link( control.setting );
			url.link( control.setting );

			url.bind( function( value ) {
				url.element.parent().attr( {
					href: value,
					target: api.settings.changeset.uuid
				} );
			} );

			api.bind( &#039;ready&#039;, control.updatePreviewLink );
			api.state( &#039;saved&#039; ).bind( control.updatePreviewLink );
			api.state( &#039;changesetStatus&#039; ).bind( control.updatePreviewLink );
			api.state( &#039;activated&#039; ).bind( control.updatePreviewLink );
			api.previewer.previewUrl.bind( control.updatePreviewLink );

			button.element.on( &#039;click&#039;, function( event ) {
				event.preventDefault();
				if ( control.setting() ) {
					input.element.select();
					document.execCommand( &#039;copy&#039; );
					button( button.element.data( &#039;copied-text&#039; ) );
				}
			} );

			url.element.parent().on( &#039;click&#039;, function( event ) {
				if ( $( this ).hasClass( &#039;disabled&#039; ) ) {
					event.preventDefault();
				}
			} );

			button.element.on( &#039;mouseenter&#039;, function() {
				if ( control.setting() ) {
					button( button.element.data( &#039;copy-text&#039; ) );
				}
			} );
		},

		/**
		 * Updates Preview Link
		 *
		 * @since 4.9.0
		 * @return {void}
		 */
		updatePreviewLink: function updatePreviewLink() {
			var control = this, unsavedDirtyValues;

			unsavedDirtyValues = ! api.state( &#039;saved&#039; ).get() || &#039;&#039; === api.state( &#039;changesetStatus&#039; ).get() || &#039;auto-draft&#039; === api.state( &#039;changesetStatus&#039; ).get();

			control.toggleSaveNotification( unsavedDirtyValues );
			control.previewElements.url.element.parent().toggleClass( &#039;disabled&#039;, unsavedDirtyValues );
			control.previewElements.button.element.prop( &#039;disabled&#039;, unsavedDirtyValues );
			control.setting.set( api.previewer.getFrontendPreviewUrl() );
		},

		/**
		 * Toggles save notification.
		 *
		 * @since 4.9.0
		 * @param {boolean} notify Add or remove notification.
		 * @return {void}
		 */
		toggleSaveNotification: function toggleSaveNotification( notify ) {
			var control = this, notificationCode, notification;

			notificationCode = &#039;changes_not_saved&#039;;

			if ( notify ) {
				notification = new api.Notification( notificationCode, {
					type: &#039;info&#039;,
					message: api.l10n.saveBeforeShare
				} );
				control.notifications.add( notification );
			} else {
				control.notifications.remove( notificationCode );
			}
		}
	});

	/**
	 * Change objects contained within the main customize object to Settings.
	 *
	 * @alias wp.customize.defaultConstructor
	 */
	api.defaultConstructor = api.Setting;

	/**
	 * Callback for resolved controls.
	 *
	 * @callback wp.customize.deferredControlsCallback
	 * @param {wp.customize.Control[]} controls Resolved controls.
	 */

	/**
	 * Collection of all registered controls.
	 *
	 * @alias wp.customize.control
	 *
	 * @since 3.4.0
	 *
	 * @type {Function}
	 * @param {...string} ids - One or more ids for controls to obtain.
	 * @param {deferredControlsCallback} [callback] - Function called when all supplied controls exist.
	 * @return {wp.customize.Control|undefined|jQuery.promise} Control instance or undefined (if function called with one id param),
	 *                                                         or promise resolving to requested controls.
	 *
	 * @example &lt;caption&gt;Loop over all registered controls.&lt;/caption&gt;
	 * wp.customize.control.each( function( control ) { ... } );
	 *
	 * @example &lt;caption&gt;Getting `background_color` control instance.&lt;/caption&gt;
	 * control = wp.customize.control( &#039;background_color&#039; );
	 *
	 * @example &lt;caption&gt;Check if control exists.&lt;/caption&gt;
	 * hasControl = wp.customize.control.has( &#039;background_color&#039; );
	 *
	 * @example &lt;caption&gt;Deferred getting of `background_color` control until it exists, using callback.&lt;/caption&gt;
	 * wp.customize.control( &#039;background_color&#039;, function( control ) { ... } );
	 *
	 * @example &lt;caption&gt;Get title and tagline controls when they both exist, using promise (only available when multiple IDs are present).&lt;/caption&gt;
	 * promise = wp.customize.control( &#039;blogname&#039;, &#039;blogdescription&#039; );
	 * promise.done( function( titleControl, taglineControl ) { ... } );
	 *
	 * @example &lt;caption&gt;Get title and tagline controls when they both exist, using callback.&lt;/caption&gt;
	 * wp.customize.control( &#039;blogname&#039;, &#039;blogdescription&#039;, function( titleControl, taglineControl ) { ... } );
	 *
	 * @example &lt;caption&gt;Getting setting value for `background_color` control.&lt;/caption&gt;
	 * value = wp.customize.control( &#039;background_color &#039;).setting.get();
	 * value = wp.customize( &#039;background_color&#039; ).get(); // Same as above, since setting ID and control ID are the same.
	 *
	 * @example &lt;caption&gt;Add new control for site title.&lt;/caption&gt;
	 * wp.customize.control.add( new wp.customize.Control( &#039;other_blogname&#039;, {
	 *     setting: &#039;blogname&#039;,
	 *     type: &#039;text&#039;,
	 *     label: &#039;Site title&#039;,
	 *     section: &#039;other_site_identify&#039;
	 * } ) );
	 *
	 * @example &lt;caption&gt;Remove control.&lt;/caption&gt;
	 * wp.customize.control.remove( &#039;other_blogname&#039; );
	 *
	 * @example &lt;caption&gt;Listen for control being added.&lt;/caption&gt;
	 * wp.customize.control.bind( &#039;add&#039;, function( addedControl ) { ... } )
	 *
	 * @example &lt;caption&gt;Listen for control being removed.&lt;/caption&gt;
	 * wp.customize.control.bind( &#039;removed&#039;, function( removedControl ) { ... } )
	 */
	api.control = new api.Values({ defaultConstructor: api.Control });

	/**
	 * Callback for resolved sections.
	 *
	 * @callback wp.customize.deferredSectionsCallback
	 * @param {wp.customize.Section[]} sections Resolved sections.
	 */

	/**
	 * Collection of all registered sections.
	 *
	 * @alias wp.customize.section
	 *
	 * @since 3.4.0
	 *
	 * @type {Function}
	 * @param {...string} ids - One or more ids for sections to obtain.
	 * @param {deferredSectionsCallback} [callback] - Function called when all supplied sections exist.
	 * @return {wp.customize.Section|undefined|jQuery.promise} Section instance or undefined (if function called with one id param),
	 *                                                         or promise resolving to requested sections.
	 *
	 * @example &lt;caption&gt;Loop over all registered sections.&lt;/caption&gt;
	 * wp.customize.section.each( function( section ) { ... } )
	 *
	 * @example &lt;caption&gt;Getting `title_tagline` section instance.&lt;/caption&gt;
	 * section = wp.customize.section( &#039;title_tagline&#039; )
	 *
	 * @example &lt;caption&gt;Expand dynamically-created section when it exists.&lt;/caption&gt;
	 * wp.customize.section( &#039;dynamically_created&#039;, function( section ) {
	 *     section.expand();
	 * } );
	 *
	 * @see {@link wp.customize.control} for further examples of how to interact with {@link wp.customize.Values} instances.
	 */
	api.section = new api.Values({ defaultConstructor: api.Section });

	/**
	 * Callback for resolved panels.
	 *
	 * @callback wp.customize.deferredPanelsCallback
	 * @param {wp.customize.Panel[]} panels Resolved panels.
	 */

	/**
	 * Collection of all registered panels.
	 *
	 * @alias wp.customize.panel
	 *
	 * @since 4.0.0
	 *
	 * @type {Function}
	 * @param {...string} ids - One or more ids for panels to obtain.
	 * @param {deferredPanelsCallback} [callback] - Function called when all supplied panels exist.
	 * @return {wp.customize.Panel|undefined|jQuery.promise} Panel instance or undefined (if function called with one id param),
	 *                                                       or promise resolving to requested panels.
	 *
	 * @example &lt;caption&gt;Loop over all registered panels.&lt;/caption&gt;
	 * wp.customize.panel.each( function( panel ) { ... } )
	 *
	 * @example &lt;caption&gt;Getting nav_menus panel instance.&lt;/caption&gt;
	 * panel = wp.customize.panel( &#039;nav_menus&#039; );
	 *
	 * @example &lt;caption&gt;Expand dynamically-created panel when it exists.&lt;/caption&gt;
	 * wp.customize.panel( &#039;dynamically_created&#039;, function( panel ) {
	 *     panel.expand();
	 * } );
	 *
	 * @see {@link wp.customize.control} for further examples of how to interact with {@link wp.customize.Values} instances.
	 */
	api.panel = new api.Values({ defaultConstructor: api.Panel });

	/**
	 * Callback for resolved notifications.
	 *
	 * @callback wp.customize.deferredNotificationsCallback
	 * @param {wp.customize.Notification[]} notifications Resolved notifications.
	 */

	/**
	 * Collection of all global notifications.
	 *
	 * @alias wp.customize.notifications
	 *
	 * @since 4.9.0
	 *
	 * @type {Function}
	 * @param {...string} codes - One or more codes for notifications to obtain.
	 * @param {deferredNotificationsCallback} [callback] - Function called when all supplied notifications exist.
	 * @return {wp.customize.Notification|undefined|jQuery.promise} Notification instance or undefined (if function called with one code param),
	 *                                                              or promise resolving to requested notifications.
	 *
	 * @example &lt;caption&gt;Check if existing notification&lt;/caption&gt;
	 * exists = wp.customize.notifications.has( &#039;a_new_day_arrived&#039; );
	 *
	 * @example &lt;caption&gt;Obtain existing notification&lt;/caption&gt;
	 * notification = wp.customize.notifications( &#039;a_new_day_arrived&#039; );
	 *
	 * @example &lt;caption&gt;Obtain notification that may not exist yet.&lt;/caption&gt;
	 * wp.customize.notifications( &#039;a_new_day_arrived&#039;, function( notification ) { ... } );
	 *
	 * @example &lt;caption&gt;Add a warning notification.&lt;/caption&gt;
	 * wp.customize.notifications.add( new wp.customize.Notification( &#039;midnight_almost_here&#039;, {
	 *     type: &#039;warning&#039;,
	 *     message: &#039;Midnight has almost arrived!&#039;,
	 *     dismissible: true
	 * } ) );
	 *
	 * @example &lt;caption&gt;Remove a notification.&lt;/caption&gt;
	 * wp.customize.notifications.remove( &#039;a_new_day_arrived&#039; );
	 *
	 * @see {@link wp.customize.control} for further examples of how to interact with {@link wp.customize.Values} instances.
	 */
	api.notifications = new api.Notifications();

	api.PreviewFrame = api.Messenger.extend(/** @lends wp.customize.PreviewFrame.prototype */{
		sensitivity: null, // Will get set to api.settings.timeouts.previewFrameSensitivity.

		/**
		 * An object that fetches a preview in the background of the document, which
		 * allows for seamless replacement of an existing preview.
		 *
		 * @constructs wp.customize.PreviewFrame
		 * @augments   wp.customize.Messenger
		 *
		 * @param {Object} params.container
		 * @param {Object} params.previewUrl
		 * @param {Object} params.query
		 * @param {Object} options
		 */
		initialize: function( params, options ) {
			var deferred = $.Deferred();

			/*
			 * Make the instance of the PreviewFrame the promise object
			 * so other objects can easily interact with it.
			 */
			deferred.promise( this );

			this.container = params.container;

			$.extend( params, { channel: api.PreviewFrame.uuid() });

			api.Messenger.prototype.initialize.call( this, params, options );

			this.add( &#039;previewUrl&#039;, params.previewUrl );

			this.query = $.extend( params.query || {}, { customize_messenger_channel: this.channel() });

			this.run( deferred );
		},

		/**
		 * Run the preview request.
		 *
		 * @param {Object} deferred jQuery Deferred object to be resolved with
		 *                          the request.
		 */
		run: function( deferred ) {
			var previewFrame = this,
				loaded = false,
				ready = false,
				readyData = null,
				hasPendingChangesetUpdate = &#039;{}&#039; !== previewFrame.query.customized,
				urlParser,
				params,
				form;

			if ( previewFrame._ready ) {
				previewFrame.unbind( &#039;ready&#039;, previewFrame._ready );
			}

			previewFrame._ready = function( data ) {
				ready = true;
				readyData = data;
				previewFrame.container.addClass( &#039;iframe-ready&#039; );
				if ( ! data ) {
					return;
				}

				if ( loaded ) {
					deferred.resolveWith( previewFrame, [ data ] );
				}
			};

			previewFrame.bind( &#039;ready&#039;, previewFrame._ready );

			urlParser = document.createElement( &#039;a&#039; );
			urlParser.href = previewFrame.previewUrl();

			params = _.extend(
				api.utils.parseQueryString( urlParser.search.substr( 1 ) ),
				{
					customize_changeset_uuid: previewFrame.query.customize_changeset_uuid,
					customize_theme: previewFrame.query.customize_theme,
					customize_messenger_channel: previewFrame.query.customize_messenger_channel
				}
			);
			if ( api.settings.changeset.autosaved || ! api.state( &#039;saved&#039; ).get() ) {
				params.customize_autosaved = &#039;on&#039;;
			}

			urlParser.search = $.param( params );
			previewFrame.iframe = $( &#039;&lt;iframe /&gt;&#039;, {
				title: api.l10n.previewIframeTitle,
				name: &#039;customize-&#039; + previewFrame.channel()
			} );
			previewFrame.iframe.attr( &#039;onmousewheel&#039;, &#039;&#039; ); // Workaround for Safari bug. See WP Trac #38149.
			previewFrame.iframe.attr( &#039;sandbox&#039;, &#039;allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts&#039; );

			if ( ! hasPendingChangesetUpdate ) {
				previewFrame.iframe.attr( &#039;src&#039;, urlParser.href );
			} else {
				previewFrame.iframe.attr( &#039;data-src&#039;, urlParser.href ); // For debugging purposes.
			}

			previewFrame.iframe.appendTo( previewFrame.container );
			previewFrame.targetWindow( previewFrame.iframe[0].contentWindow );

			/*
			 * Submit customized data in POST request to preview frame window since
			 * there are setting value changes not yet written to changeset.
			 */
			if ( hasPendingChangesetUpdate ) {
				form = $( &#039;&lt;form&gt;&#039;, {
					action: urlParser.href,
					target: previewFrame.iframe.attr( &#039;name&#039; ),
					method: &#039;post&#039;,
					hidden: &#039;hidden&#039;
				} );
				form.append( $( &#039;&lt;input&gt;&#039;, {
					type: &#039;hidden&#039;,
					name: &#039;_method&#039;,
					value: &#039;GET&#039;
				} ) );
				_.each( previewFrame.query, function( value, key ) {
					form.append( $( &#039;&lt;input&gt;&#039;, {
						type: &#039;hidden&#039;,
						name: key,
						value: value
					} ) );
				} );
				previewFrame.container.append( form );
				form.trigger( &#039;submit&#039; );
				form.remove(); // No need to keep the form around after submitted.
			}

			previewFrame.bind( &#039;iframe-loading-error&#039;, function( error ) {
				previewFrame.iframe.remove();

				// Check if the user is not logged in.
				if ( 0 === error ) {
					previewFrame.login( deferred );
					return;
				}

				// Check for cheaters.
				if ( -1 === error ) {
					deferred.rejectWith( previewFrame, [ &#039;cheatin&#039; ] );
					return;
				}

				deferred.rejectWith( previewFrame, [ &#039;request failure&#039; ] );
			} );

			previewFrame.iframe.one( &#039;load&#039;, function() {
				loaded = true;

				if ( ready ) {
					deferred.resolveWith( previewFrame, [ readyData ] );
				} else {
					setTimeout( function() {
						deferred.rejectWith( previewFrame, [ &#039;ready timeout&#039; ] );
					}, previewFrame.sensitivity );
				}
			});
		},

		login: function( deferred ) {
			var self = this,
				reject;

			reject = function() {
				deferred.rejectWith( self, [ &#039;logged out&#039; ] );
			};

			if ( this.triedLogin ) {
				return reject();
			}

			// Check if we have an admin cookie.
			$.get( api.settings.url.ajax, {
				action: &#039;logged-in&#039;
			}).fail( reject ).done( function( response ) {
				var iframe;

				if ( &#039;1&#039; !== response ) {
					reject();
				}

				iframe = $( &#039;&lt;iframe /&gt;&#039;, { &#039;src&#039;: self.previewUrl(), &#039;title&#039;: api.l10n.previewIframeTitle } ).hide();
				iframe.appendTo( self.container );
				iframe.on( &#039;load&#039;, function() {
					self.triedLogin = true;

					iframe.remove();
					self.run( deferred );
				});
			});
		},

		destroy: function() {
			api.Messenger.prototype.destroy.call( this );

			if ( this.iframe ) {
				this.iframe.remove();
			}

			delete this.iframe;
			delete this.targetWindow;
		}
	});

	(function(){
		var id = 0;
		/**
		 * Return an incremented ID for a preview messenger channel.
		 *
		 * This function is named &quot;uuid&quot; for historical reasons, but it is a
		 * misnomer as it is not an actual UUID, and it is not universally unique.
		 * This is not to be confused with `api.settings.changeset.uuid`.
		 *
		 * @return {string}
		 */
		api.PreviewFrame.uuid = function() {
			return &#039;preview-&#039; + String( id++ );
		};
	}());

	/**
	 * Set the document title of the customizer.
	 *
	 * @alias wp.customize.setDocumentTitle
	 *
	 * @since 4.1.0
	 *
	 * @param {string} documentTitle
	 */
	api.setDocumentTitle = function ( documentTitle ) {
		var tmpl, title;
		tmpl = api.settings.documentTitleTmpl;
		title = tmpl.replace( &#039;%s&#039;, documentTitle );
		document.title = title;
		api.trigger( &#039;title&#039;, title );
	};

	api.Previewer = api.Messenger.extend(/** @lends wp.customize.Previewer.prototype */{
		refreshBuffer: null, // Will get set to api.settings.timeouts.windowRefresh.

		/**
		 * @constructs wp.customize.Previewer
		 * @augments   wp.customize.Messenger
		 *
		 * @param {Array}  params.allowedUrls
		 * @param {string} params.container   A selector or jQuery element for the preview
		 *                                    frame to be placed.
		 * @param {string} params.form
		 * @param {string} params.previewUrl  The URL to preview.
		 * @param {Object} options
		 */
		initialize: function( params, options ) {
			var previewer = this,
				urlParser = document.createElement( &#039;a&#039; );

			$.extend( previewer, options || {} );
			previewer.deferred = {
				active: $.Deferred()
			};

			// Debounce to prevent hammering server and then wait for any pending update requests.
			previewer.refresh = _.debounce(
				( function( originalRefresh ) {
					return function() {
						var isProcessingComplete, refreshOnceProcessingComplete;
						isProcessingComplete = function() {
							return 0 === api.state( &#039;processing&#039; ).get();
						};
						if ( isProcessingComplete() ) {
							originalRefresh.call( previewer );
						} else {
							refreshOnceProcessingComplete = function() {
								if ( isProcessingComplete() ) {
									originalRefresh.call( previewer );
									api.state( &#039;processing&#039; ).unbind( refreshOnceProcessingComplete );
								}
							};
							api.state( &#039;processing&#039; ).bind( refreshOnceProcessingComplete );
						}
					};
				}( previewer.refresh ) ),
				previewer.refreshBuffer
			);

			previewer.container   = api.ensure( params.container );
			previewer.allowedUrls = params.allowedUrls;

			params.url = window.location.href;

			api.Messenger.prototype.initialize.call( previewer, params );

			urlParser.href = previewer.origin();
			previewer.add( &#039;scheme&#039;, urlParser.protocol.replace( /:$/, &#039;&#039; ) );

			/*
			 * Limit the URL to internal, front-end links.
			 *
			 * If the front end and the admin are served from the same domain, load the
			 * preview over ssl if the Customizer is being loaded over ssl. This avoids
			 * insecure content warnings. This is not attempted if the admin and front end
			 * are on different domains to avoid the case where the front end doesn&#039;t have
			 * ssl certs.
			 */

			previewer.add( &#039;previewUrl&#039;, params.previewUrl ).setter( function( to ) {
				var result = null, urlParser, queryParams, parsedAllowedUrl, parsedCandidateUrls = [];
				urlParser = document.createElement( &#039;a&#039; );
				urlParser.href = to;

				// Abort if URL is for admin or (static) files in wp-includes or wp-content.
				if ( /\/wp-(admin|includes|content)(\/|$)/.test( urlParser.pathname ) ) {
					return null;
				}

				// Remove state query params.
				if ( urlParser.search.length &gt; 1 ) {
					queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
					delete queryParams.customize_changeset_uuid;
					delete queryParams.customize_theme;
					delete queryParams.customize_messenger_channel;
					delete queryParams.customize_autosaved;
					if ( _.isEmpty( queryParams ) ) {
						urlParser.search = &#039;&#039;;
					} else {
						urlParser.search = $.param( queryParams );
					}
				}

				parsedCandidateUrls.push( urlParser );

				// Prepend list with URL that matches the scheme/protocol of the iframe.
				if ( previewer.scheme.get() + &#039;:&#039; !== urlParser.protocol ) {
					urlParser = document.createElement( &#039;a&#039; );
					urlParser.href = parsedCandidateUrls[0].href;
					urlParser.protocol = previewer.scheme.get() + &#039;:&#039;;
					parsedCandidateUrls.unshift( urlParser );
				}

				// Attempt to match the URL to the control frame&#039;s scheme and check if it&#039;s allowed. If not, try the original URL.
				parsedAllowedUrl = document.createElement( &#039;a&#039; );
				_.find( parsedCandidateUrls, function( parsedCandidateUrl ) {
					return ! _.isUndefined( _.find( previewer.allowedUrls, function( allowedUrl ) {
						parsedAllowedUrl.href = allowedUrl;
						if ( urlParser.protocol === parsedAllowedUrl.protocol &amp;&amp; urlParser.host === parsedAllowedUrl.host &amp;&amp; 0 === urlParser.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, &#039;&#039; ) ) ) {
							result = parsedCandidateUrl.href;
							return true;
						}
					} ) );
				} );

				return result;
			});

			previewer.bind( &#039;ready&#039;, previewer.ready );

			// Start listening for keep-alive messages when iframe first loads.
			previewer.deferred.active.done( _.bind( previewer.keepPreviewAlive, previewer ) );

			previewer.bind( &#039;synced&#039;, function() {
				previewer.send( &#039;active&#039; );
			} );

			// Refresh the preview when the URL is changed (but not yet).
			previewer.previewUrl.bind( previewer.refresh );

			previewer.scroll = 0;
			previewer.bind( &#039;scroll&#039;, function( distance ) {
				previewer.scroll = distance;
			});

			// Update the URL when the iframe sends a URL message, resetting scroll position. If URL is unchanged, then refresh.
			previewer.bind( &#039;url&#039;, function( url ) {
				var onUrlChange, urlChanged = false;
				previewer.scroll = 0;
				onUrlChange = function() {
					urlChanged = true;
				};
				previewer.previewUrl.bind( onUrlChange );
				previewer.previewUrl.set( url );
				previewer.previewUrl.unbind( onUrlChange );
				if ( ! urlChanged ) {
					previewer.refresh();
				}
			} );

			// Update the document title when the preview changes.
			previewer.bind( &#039;documentTitle&#039;, function ( title ) {
				api.setDocumentTitle( title );
			} );
		},

		/**
		 * Handle the preview receiving the ready message.
		 *
		 * @since 4.7.0
		 * @access public
		 *
		 * @param {Object} data - Data from preview.
		 * @param {string} data.currentUrl - Current URL.
		 * @param {Object} data.activePanels - Active panels.
		 * @param {Object} data.activeSections Active sections.
		 * @param {Object} data.activeControls Active controls.
		 * @return {void}
		 */
		ready: function( data ) {
			var previewer = this, synced = {}, constructs;

			synced.settings = api.get();
			synced[&#039;settings-modified-while-loading&#039;] = previewer.settingsModifiedWhileLoading;
			if ( &#039;resolved&#039; !== previewer.deferred.active.state() || previewer.loading ) {
				synced.scroll = previewer.scroll;
			}
			synced[&#039;edit-shortcut-visibility&#039;] = api.state( &#039;editShortcutVisibility&#039; ).get();
			previewer.send( &#039;sync&#039;, synced );

			// Set the previewUrl without causing the url to set the iframe.
			if ( data.currentUrl ) {
				previewer.previewUrl.unbind( previewer.refresh );
				previewer.previewUrl.set( data.currentUrl );
				previewer.previewUrl.bind( previewer.refresh );
			}

			/*
			 * Walk over all panels, sections, and controls and set their
			 * respective active states to true if the preview explicitly
			 * indicates as such.
			 */
			constructs = {
				panel: data.activePanels,
				section: data.activeSections,
				control: data.activeControls
			};
			_( constructs ).each( function ( activeConstructs, type ) {
				api[ type ].each( function ( construct, id ) {
					var isDynamicallyCreated = _.isUndefined( api.settings[ type + &#039;s&#039; ][ id ] );

					/*
					 * If the construct was created statically in PHP (not dynamically in JS)
					 * then consider a missing (undefined) value in the activeConstructs to
					 * mean it should be deactivated (since it is gone). But if it is
					 * dynamically created then only toggle activation if the value is defined,
					 * as this means that the construct was also then correspondingly
					 * created statically in PHP and the active callback is available.
					 * Otherwise, dynamically-created constructs should normally have
					 * their active states toggled in JS rather than from PHP.
					 */
					if ( ! isDynamicallyCreated || ! _.isUndefined( activeConstructs[ id ] ) ) {
						if ( activeConstructs[ id ] ) {
							construct.activate();
						} else {
							construct.deactivate();
						}
					}
				} );
			} );

			if ( data.settingValidities ) {
				api._handleSettingValidities( {
					settingValidities: data.settingValidities,
					focusInvalidControl: false
				} );
			}
		},

		/**
		 * Keep the preview alive by listening for ready and keep-alive messages.
		 *
		 * If a message is not received in the allotted time then the iframe will be set back to the last known valid URL.
		 *
		 * @since 4.7.0
		 * @access public
		 *
		 * @return {void}
		 */
		keepPreviewAlive: function keepPreviewAlive() {
			var previewer = this, keepAliveTick, timeoutId, handleMissingKeepAlive, scheduleKeepAliveCheck;

			/**
			 * Schedule a preview keep-alive check.
			 *
			 * Note that if a page load takes longer than keepAliveCheck milliseconds,
			 * the keep-alive messages will still be getting sent from the previous
			 * URL.
			 */
			scheduleKeepAliveCheck = function() {
				timeoutId = setTimeout( handleMissingKeepAlive, api.settings.timeouts.keepAliveCheck );
			};

			/**
			 * Set the previewerAlive state to true when receiving a message from the preview.
			 */
			keepAliveTick = function() {
				api.state( &#039;previewerAlive&#039; ).set( true );
				clearTimeout( timeoutId );
				scheduleKeepAliveCheck();
			};

			/**
			 * Set the previewerAlive state to false if keepAliveCheck milliseconds have transpired without a message.
			 *
			 * This is most likely to happen in the case of a connectivity error, or if the theme causes the browser
			 * to navigate to a non-allowed URL. Setting this state to false will force settings with a postMessage
			 * transport to use refresh instead, causing the preview frame also to be replaced with the current
			 * allowed preview URL.
			 */
			handleMissingKeepAlive = function() {
				api.state( &#039;previewerAlive&#039; ).set( false );
			};
			scheduleKeepAliveCheck();

			previewer.bind( &#039;ready&#039;, keepAliveTick );
			previewer.bind( &#039;keep-alive&#039;, keepAliveTick );
		},

		/**
		 * Query string data sent with each preview request.
		 *
		 * @abstract
		 */
		query: function() {},

		abort: function() {
			if ( this.loading ) {
				this.loading.destroy();
				delete this.loading;
			}
		},

		/**
		 * Refresh the preview seamlessly.
		 *
		 * @since 3.4.0
		 * @access public
		 *
		 * @return {void}
		 */
		refresh: function() {
			var previewer = this, onSettingChange;

			// Display loading indicator.
			previewer.send( &#039;loading-initiated&#039; );

			previewer.abort();

			previewer.loading = new api.PreviewFrame({
				url:        previewer.url(),
				previewUrl: previewer.previewUrl(),
				query:      previewer.query( { excludeCustomizedSaved: true } ) || {},
				container:  previewer.container
			});

			previewer.settingsModifiedWhileLoading = {};
			onSettingChange = function( setting ) {
				previewer.settingsModifiedWhileLoading[ setting.id ] = true;
			};
			api.bind( &#039;change&#039;, onSettingChange );
			previewer.loading.always( function() {
				api.unbind( &#039;change&#039;, onSettingChange );
			} );

			previewer.loading.done( function( readyData ) {
				var loadingFrame = this, onceSynced;

				previewer.preview = loadingFrame;
				previewer.targetWindow( loadingFrame.targetWindow() );
				previewer.channel( loadingFrame.channel() );

				onceSynced = function() {
					loadingFrame.unbind( &#039;synced&#039;, onceSynced );
					if ( previewer._previousPreview ) {
						previewer._previousPreview.destroy();
					}
					previewer._previousPreview = previewer.preview;
					previewer.deferred.active.resolve();
					delete previewer.loading;
				};
				loadingFrame.bind( &#039;synced&#039;, onceSynced );

				// This event will be received directly by the previewer in normal navigation; this is only needed for seamless refresh.
				previewer.trigger( &#039;ready&#039;, readyData );
			});

			previewer.loading.fail( function( reason ) {
				previewer.send( &#039;loading-failed&#039; );

				if ( &#039;logged out&#039; === reason ) {
					if ( previewer.preview ) {
						previewer.preview.destroy();
						delete previewer.preview;
					}

					previewer.login().done( previewer.refresh );
				}

				if ( &#039;cheatin&#039; === reason ) {
					previewer.cheatin();
				}
			});
		},

		login: function() {
			var previewer = this,
				deferred, messenger, iframe;

			if ( this._login ) {
				return this._login;
			}

			deferred = $.Deferred();
			this._login = deferred.promise();

			messenger = new api.Messenger({
				channel: &#039;login&#039;,
				url:     api.settings.url.login
			});

			iframe = $( &#039;&lt;iframe /&gt;&#039;, { &#039;src&#039;: api.settings.url.login, &#039;title&#039;: api.l10n.loginIframeTitle } ).appendTo( this.container );

			messenger.targetWindow( iframe[0].contentWindow );

			messenger.bind( &#039;login&#039;, function () {
				var refreshNonces = previewer.refreshNonces();

				refreshNonces.always( function() {
					iframe.remove();
					messenger.destroy();
					delete previewer._login;
				});

				refreshNonces.done( function() {
					deferred.resolve();
				});

				refreshNonces.fail( function() {
					previewer.cheatin();
					deferred.reject();
				});
			});

			return this._login;
		},

		cheatin: function() {
			$( document.body ).empty().addClass( &#039;cheatin&#039; ).append(
				&#039;&lt;h1&gt;&#039; + api.l10n.notAllowedHeading + &#039;&lt;/h1&gt;&#039; +
				&#039;&lt;p&gt;&#039; + api.l10n.notAllowed + &#039;&lt;/p&gt;&#039;
			);
		},

		refreshNonces: function() {
			var request, deferred = $.Deferred();

			deferred.promise();

			request = wp.ajax.post( &#039;customize_refresh_nonces&#039;, {
				wp_customize: &#039;on&#039;,
				customize_theme: api.settings.theme.stylesheet
			});

			request.done( function( response ) {
				api.trigger( &#039;nonce-refresh&#039;, response );
				deferred.resolve();
			});

			request.fail( function() {
				deferred.reject();
			});

			return deferred;
		}
	});

	api.settingConstructor = {};
	api.controlConstructor = {
		color:               api.ColorControl,
		media:               api.MediaControl,
		upload:              api.UploadControl,
		image:               api.ImageControl,
		cropped_image:       api.CroppedImageControl,
		site_icon:           api.SiteIconControl,
		header:              api.HeaderControl,
		background:          api.BackgroundControl,
		background_position: api.BackgroundPositionControl,
		theme:               api.ThemeControl,
		date_time:           api.DateTimeControl,
		code_editor:         api.CodeEditorControl
	};
	api.panelConstructor = {
		themes: api.ThemesPanel
	};
	api.sectionConstructor = {
		themes: api.ThemesSection,
		outer: api.OuterSection
	};

	/**
	 * Handle setting_validities in an error response for the customize-save request.
	 *
	 * Add notifications to the settings and focus on the first control that has an invalid setting.
	 *
	 * @alias wp.customize._handleSettingValidities
	 *
	 * @since 4.6.0
	 * @private
	 *
	 * @param {Object}  args
	 * @param {Object}  args.settingValidities
	 * @param {boolean} [args.focusInvalidControl=false]
	 * @return {void}
	 */
	api._handleSettingValidities = function handleSettingValidities( args ) {
		var invalidSettingControls, invalidSettings = [], wasFocused = false;

		// Find the controls that correspond to each invalid setting.
		_.each( args.settingValidities, function( validity, settingId ) {
			var setting = api( settingId );
			if ( setting ) {

				// Add notifications for invalidities.
				if ( _.isObject( validity ) ) {
					_.each( validity, function( params, code ) {
						var notification, existingNotification, needsReplacement = false;
						notification = new api.Notification( code, _.extend( { fromServer: true }, params ) );

						// Remove existing notification if already exists for code but differs in parameters.
						existingNotification = setting.notifications( notification.code );
						if ( existingNotification ) {
							needsReplacement = notification.type !== existingNotification.type || notification.message !== existingNotification.message || ! _.isEqual( notification.data, existingNotification.data );
						}
						if ( needsReplacement ) {
							setting.notifications.remove( code );
						}

						if ( ! setting.notifications.has( notification.code ) ) {
							setting.notifications.add( notification );
						}
						invalidSettings.push( setting.id );
					} );
				}

				// Remove notification errors that are no longer valid.
				setting.notifications.each( function( notification ) {
					if ( notification.fromServer &amp;&amp; &#039;error&#039; === notification.type &amp;&amp; ( true === validity || ! validity[ notification.code ] ) ) {
						setting.notifications.remove( notification.code );
					}
				} );
			}
		} );

		if ( args.focusInvalidControl ) {
			invalidSettingControls = api.findControlsForSettings( invalidSettings );

			// Focus on the first control that is inside of an expanded section (one that is visible).
			_( _.values( invalidSettingControls ) ).find( function( controls ) {
				return _( controls ).find( function( control ) {
					var isExpanded = control.section() &amp;&amp; api.section.has( control.section() ) &amp;&amp; api.section( control.section() ).expanded();
					if ( isExpanded &amp;&amp; control.expanded ) {
						isExpanded = control.expanded();
					}
					if ( isExpanded ) {
						control.focus();
						wasFocused = true;
					}
					return wasFocused;
				} );
			} );

			// Focus on the first invalid control.
			if ( ! wasFocused &amp;&amp; ! _.isEmpty( invalidSettingControls ) ) {
				_.values( invalidSettingControls )[0][0].focus();
			}
		}
	};

	/**
	 * Find all controls associated with the given settings.
	 *
	 * @alias wp.customize.findControlsForSettings
	 *
	 * @since 4.6.0
	 * @param {string[]} settingIds Setting IDs.
	 * @return {Object&lt;string, wp.customize.Control&gt;} Mapping setting ids to arrays of controls.
	 */
	api.findControlsForSettings = function findControlsForSettings( settingIds ) {
		var controls = {}, settingControls;
		_.each( _.unique( settingIds ), function( settingId ) {
			var setting = api( settingId );
			if ( setting ) {
				settingControls = setting.findControls();
				if ( settingControls &amp;&amp; settingControls.length &gt; 0 ) {
					controls[ settingId ] = settingControls;
				}
			}
		} );
		return controls;
	};

	/**
	 * Sort panels, sections, controls by priorities. Hide empty sections and panels.
	 *
	 * @alias wp.customize.reflowPaneContents
	 *
	 * @since 4.1.0
	 */
	api.reflowPaneContents = _.bind( function () {

		var appendContainer, activeElement, rootHeadContainers, rootNodes = [], wasReflowed = false;

		if ( document.activeElement ) {
			activeElement = $( document.activeElement );
		}

		// Sort the sections within each panel.
		api.panel.each( function ( panel ) {
			if ( &#039;themes&#039; === panel.id ) {
				return; // Don&#039;t reflow theme sections, as doing so moves them after the themes container.
			}

			var sections = panel.sections(),
				sectionHeadContainers = _.pluck( sections, &#039;headContainer&#039; );
			rootNodes.push( panel );
			appendContainer = ( panel.contentContainer.is( &#039;ul&#039; ) ) ? panel.contentContainer : panel.contentContainer.find( &#039;ul:first&#039; );
			if ( ! api.utils.areElementListsEqual( sectionHeadContainers, appendContainer.children( &#039;[id]&#039; ) ) ) {
				_( sections ).each( function ( section ) {
					appendContainer.append( section.headContainer );
				} );
				wasReflowed = true;
			}
		} );

		// Sort the controls within each section.
		api.section.each( function ( section ) {
			var controls = section.controls(),
				controlContainers = _.pluck( controls, &#039;container&#039; );
			if ( ! section.panel() ) {
				rootNodes.push( section );
			}
			appendContainer = ( section.contentContainer.is( &#039;ul&#039; ) ) ? section.contentContainer : section.contentContainer.find( &#039;ul:first&#039; );
			if ( ! api.utils.areElementListsEqual( controlContainers, appendContainer.children( &#039;[id]&#039; ) ) ) {
				_( controls ).each( function ( control ) {
					appendContainer.append( control.container );
				} );
				wasReflowed = true;
			}
		} );

		// Sort the root panels and sections.
		rootNodes.sort( api.utils.prioritySort );
		rootHeadContainers = _.pluck( rootNodes, &#039;headContainer&#039; );
		appendContainer = $( &#039;#customize-theme-controls .customize-pane-parent&#039; ); // @todo This should be defined elsewhere, and to be configurable.
		if ( ! api.utils.areElementListsEqual( rootHeadContainers, appendContainer.children() ) ) {
			_( rootNodes ).each( function ( rootNode ) {
				appendContainer.append( rootNode.headContainer );
			} );
			wasReflowed = true;
		}

		// Now re-trigger the active Value callbacks so that the panels and sections can decide whether they can be rendered.
		api.panel.each( function ( panel ) {
			var value = panel.active();
			panel.active.callbacks.fireWith( panel.active, [ value, value ] );
		} );
		api.section.each( function ( section ) {
			var value = section.active();
			section.active.callbacks.fireWith( section.active, [ value, value ] );
		} );

		// Restore focus if there was a reflow and there was an active (focused) element.
		if ( wasReflowed &amp;&amp; activeElement ) {
			activeElement.trigger( &#039;focus&#039; );
		}
		api.trigger( &#039;pane-contents-reflowed&#039; );
	}, api );

	// Define state values.
	api.state = new api.Values();
	_.each( [
		&#039;saved&#039;,
		&#039;saving&#039;,
		&#039;trashing&#039;,
		&#039;activated&#039;,
		&#039;processing&#039;,
		&#039;paneVisible&#039;,
		&#039;expandedPanel&#039;,
		&#039;expandedSection&#039;,
		&#039;changesetDate&#039;,
		&#039;selectedChangesetDate&#039;,
		&#039;changesetStatus&#039;,
		&#039;selectedChangesetStatus&#039;,
		&#039;remainingTimeToPublish&#039;,
		&#039;previewerAlive&#039;,
		&#039;editShortcutVisibility&#039;,
		&#039;changesetLocked&#039;,
		&#039;previewedDevice&#039;
	], function( name ) {
		api.state.create( name );
	});

	$( function() {
		api.settings = window._wpCustomizeSettings;
		api.l10n = window._wpCustomizeControlsL10n;

		// Check if we can run the Customizer.
		if ( ! api.settings ) {
			return;
		}

		// Bail if any incompatibilities are found.
		if ( ! $.support.postMessage || ( ! $.support.cors &amp;&amp; api.settings.isCrossDomain ) ) {
			return;
		}

		if ( null === api.PreviewFrame.prototype.sensitivity ) {
			api.PreviewFrame.prototype.sensitivity = api.settings.timeouts.previewFrameSensitivity;
		}
		if ( null === api.Previewer.prototype.refreshBuffer ) {
			api.Previewer.prototype.refreshBuffer = api.settings.timeouts.windowRefresh;
		}

		var parent,
			body = $( document.body ),
			overlay = body.children( &#039;.wp-full-overlay&#039; ),
			title = $( &#039;#customize-info .panel-title.site-title&#039; ),
			closeBtn = $( &#039;.customize-controls-close&#039; ),
			saveBtn = $( &#039;#save&#039; ),
			btnWrapper = $( &#039;#customize-save-button-wrapper&#039; ),
			publishSettingsBtn = $( &#039;#publish-settings&#039; ),
			footerActions = $( &#039;#customize-footer-actions&#039; );

		// Add publish settings section in JS instead of PHP since the Customizer depends on it to function.
		api.bind( &#039;ready&#039;, function() {
			api.section.add( new api.OuterSection( &#039;publish_settings&#039;, {
				title: api.l10n.publishSettings,
				priority: 0,
				active: api.settings.theme.active
			} ) );
		} );

		// Set up publish settings section and its controls.
		api.section( &#039;publish_settings&#039;, function( section ) {
			var updateButtonsState, trashControl, updateSectionActive, isSectionActive, statusControl, dateControl, toggleDateControl, publishWhenTime, pollInterval, updateTimeArrivedPoller, cancelScheduleButtonReminder, timeArrivedPollingInterval = 1000;

			trashControl = new api.Control( &#039;trash_changeset&#039;, {
				type: &#039;button&#039;,
				section: section.id,
				priority: 30,
				input_attrs: {
					&#039;class&#039;: &#039;button-link button-link-delete&#039;,
					value: api.l10n.discardChanges
				}
			} );
			api.control.add( trashControl );
			trashControl.deferred.embedded.done( function() {
				trashControl.container.find( &#039;.button-link&#039; ).on( &#039;click&#039;, function() {
					if ( confirm( api.l10n.trashConfirm ) ) {
						wp.customize.previewer.trash();
					}
				} );
			} );

			api.control.add( new api.PreviewLinkControl( &#039;changeset_preview_link&#039;, {
				section: section.id,
				priority: 100
			} ) );

			/**
			 * Return whether the publish settings section should be active.
			 *
			 * @return {boolean} Is section active.
			 */
			isSectionActive = function() {
				if ( ! api.state( &#039;activated&#039; ).get() ) {
					return false;
				}
				if ( api.state( &#039;trashing&#039; ).get() || &#039;trash&#039; === api.state( &#039;changesetStatus&#039; ).get() ) {
					return false;
				}
				if ( &#039;&#039; === api.state( &#039;changesetStatus&#039; ).get() &amp;&amp; api.state( &#039;saved&#039; ).get() ) {
					return false;
				}
				return true;
			};

			// Make sure publish settings are not available while the theme is not active and the customizer is in a published state.
			section.active.validate = isSectionActive;
			updateSectionActive = function() {
				section.active.set( isSectionActive() );
			};
			api.state( &#039;activated&#039; ).bind( updateSectionActive );
			api.state( &#039;trashing&#039; ).bind( updateSectionActive );
			api.state( &#039;saved&#039; ).bind( updateSectionActive );
			api.state( &#039;changesetStatus&#039; ).bind( updateSectionActive );
			updateSectionActive();

			// Bind visibility of the publish settings button to whether the section is active.
			updateButtonsState = function() {
				publishSettingsBtn.toggle( section.active.get() );
				saveBtn.toggleClass( &#039;has-next-sibling&#039;, section.active.get() );
			};
			updateButtonsState();
			section.active.bind( updateButtonsState );

			function highlightScheduleButton() {
				if ( ! cancelScheduleButtonReminder ) {
					cancelScheduleButtonReminder = api.utils.highlightButton( btnWrapper, {
						delay: 1000,

						/*
						 * Only abort the reminder when the save button is focused.
						 * If the user clicks the settings button to toggle the
						 * settings closed, we&#039;ll still remind them.
						 */
						focusTarget: saveBtn
					} );
				}
			}
			function cancelHighlightScheduleButton() {
				if ( cancelScheduleButtonReminder ) {
					cancelScheduleButtonReminder();
					cancelScheduleButtonReminder = null;
				}
			}
			api.state( &#039;selectedChangesetStatus&#039; ).bind( cancelHighlightScheduleButton );

			section.contentContainer.find( &#039;.customize-action&#039; ).text( api.l10n.updating );
			section.contentContainer.find( &#039;.customize-section-back&#039; ).removeAttr( &#039;tabindex&#039; );
			publishSettingsBtn.prop( &#039;disabled&#039;, false );

			publishSettingsBtn.on( &#039;click&#039;, function( event ) {
				event.preventDefault();
				section.expanded.set( ! section.expanded.get() );
			} );

			section.expanded.bind( function( isExpanded ) {
				var defaultChangesetStatus;
				publishSettingsBtn.attr( &#039;aria-expanded&#039;, String( isExpanded ) );
				publishSettingsBtn.toggleClass( &#039;active&#039;, isExpanded );

				if ( isExpanded ) {
					cancelHighlightScheduleButton();
					return;
				}

				defaultChangesetStatus = api.state( &#039;changesetStatus&#039; ).get();
				if ( &#039;&#039; === defaultChangesetStatus || &#039;auto-draft&#039; === defaultChangesetStatus ) {
					defaultChangesetStatus = &#039;publish&#039;;
				}

				if ( api.state( &#039;selectedChangesetStatus&#039; ).get() !== defaultChangesetStatus ) {
					highlightScheduleButton();
				} else if ( &#039;future&#039; === api.state( &#039;selectedChangesetStatus&#039; ).get() &amp;&amp; api.state( &#039;selectedChangesetDate&#039; ).get() !== api.state( &#039;changesetDate&#039; ).get() ) {
					highlightScheduleButton();
				}
			} );

			statusControl = new api.Control( &#039;changeset_status&#039;, {
				priority: 10,
				type: &#039;radio&#039;,
				section: &#039;publish_settings&#039;,
				setting: api.state( &#039;selectedChangesetStatus&#039; ),
				templateId: &#039;customize-selected-changeset-status-control&#039;,
				label: api.l10n.action,
				choices: api.settings.changeset.statusChoices
			} );
			api.control.add( statusControl );

			dateControl = new api.DateTimeControl( &#039;changeset_scheduled_date&#039;, {
				priority: 20,
				section: &#039;publish_settings&#039;,
				setting: api.state( &#039;selectedChangesetDate&#039; ),
				minYear: ( new Date() ).getFullYear(),
				allowPastDate: false,
				includeTime: true,
				twelveHourFormat: /a/i.test( api.settings.timeFormat ),
				description: api.l10n.scheduleDescription
			} );
			dateControl.notifications.alt = true;
			api.control.add( dateControl );

			publishWhenTime = function() {
				api.state( &#039;selectedChangesetStatus&#039; ).set( &#039;publish&#039; );
				api.previewer.save();
			};

			// Start countdown for when the dateTime arrives, or clear interval when it is .
			updateTimeArrivedPoller = function() {
				var shouldPoll = (
					&#039;future&#039; === api.state( &#039;changesetStatus&#039; ).get() &amp;&amp;
					&#039;future&#039; === api.state( &#039;selectedChangesetStatus&#039; ).get() &amp;&amp;
					api.state( &#039;changesetDate&#039; ).get() &amp;&amp;
					api.state( &#039;selectedChangesetDate&#039; ).get() === api.state( &#039;changesetDate&#039; ).get() &amp;&amp;
					api.utils.getRemainingTime( api.state( &#039;changesetDate&#039; ).get() ) &gt;= 0
				);

				if ( shouldPoll &amp;&amp; ! pollInterval ) {
					pollInterval = setInterval( function() {
						var remainingTime = api.utils.getRemainingTime( api.state( &#039;changesetDate&#039; ).get() );
						api.state( &#039;remainingTimeToPublish&#039; ).set( remainingTime );
						if ( remainingTime &lt;= 0 ) {
							clearInterval( pollInterval );
							pollInterval = 0;
							publishWhenTime();
						}
					}, timeArrivedPollingInterval );
				} else if ( ! shouldPoll &amp;&amp; pollInterval ) {
					clearInterval( pollInterval );
					pollInterval = 0;
				}
			};

			api.state( &#039;changesetDate&#039; ).bind( updateTimeArrivedPoller );
			api.state( &#039;selectedChangesetDate&#039; ).bind( updateTimeArrivedPoller );
			api.state( &#039;changesetStatus&#039; ).bind( updateTimeArrivedPoller );
			api.state( &#039;selectedChangesetStatus&#039; ).bind( updateTimeArrivedPoller );
			updateTimeArrivedPoller();

			// Ensure dateControl only appears when selected status is future.
			dateControl.active.validate = function() {
				return &#039;future&#039; === api.state( &#039;selectedChangesetStatus&#039; ).get();
			};
			toggleDateControl = function( value ) {
				dateControl.active.set( &#039;future&#039; === value );
			};
			toggleDateControl( api.state( &#039;selectedChangesetStatus&#039; ).get() );
			api.state( &#039;selectedChangesetStatus&#039; ).bind( toggleDateControl );

			// Show notification on date control when status is future but it isn&#039;t a future date.
			api.state( &#039;saving&#039; ).bind( function( isSaving ) {
				if ( isSaving &amp;&amp; &#039;future&#039; === api.state( &#039;selectedChangesetStatus&#039; ).get() ) {
					dateControl.toggleFutureDateNotification( ! dateControl.isFutureDate() );
				}
			} );
		} );

		// Prevent the form from saving when enter is pressed on an input or select element.
		$(&#039;#customize-controls&#039;).on( &#039;keydown&#039;, function( e ) {
			var isEnter = ( 13 === e.which ),
				$el = $( e.target );

			if ( isEnter &amp;&amp; ( $el.is( &#039;input:not([type=button])&#039; ) || $el.is( &#039;select&#039; ) ) ) {
				e.preventDefault();
			}
		});

		// Expand/Collapse the main customizer customize info.
		$( &#039;.customize-info&#039; ).find( &#039;&gt; .accordion-section-title .customize-help-toggle&#039; ).on( &#039;click&#039;, function() {
			var section = $( this ).closest( &#039;.accordion-section&#039; ),
				content = section.find( &#039;.customize-panel-description:first&#039; );

			if ( section.hasClass( &#039;cannot-expand&#039; ) ) {
				return;
			}

			if ( section.hasClass( &#039;open&#039; ) ) {
				section.toggleClass( &#039;open&#039; );
				content.slideUp( api.Panel.prototype.defaultExpandedArguments.duration, function() {
					content.trigger( &#039;toggled&#039; );
				} );
				$( this ).attr( &#039;aria-expanded&#039;, false );
			} else {
				content.slideDown( api.Panel.prototype.defaultExpandedArguments.duration, function() {
					content.trigger( &#039;toggled&#039; );
				} );
				section.toggleClass( &#039;open&#039; );
				$( this ).attr( &#039;aria-expanded&#039;, true );
			}
		});

		/**
		 * Initialize Previewer
		 *
		 * @alias wp.customize.previewer
		 */
		api.previewer = new api.Previewer({
			container:   &#039;#customize-preview&#039;,
			form:        &#039;#customize-controls&#039;,
			previewUrl:  api.settings.url.preview,
			allowedUrls: api.settings.url.allowed
		},/** @lends wp.customize.previewer */{

			nonce: api.settings.nonce,

			/**
			 * Build the query to send along with the Preview request.
			 *
			 * @since 3.4.0
			 * @since 4.7.0 Added options param.
			 * @access public
			 *
			 * @param {Object}  [options] Options.
			 * @param {boolean} [options.excludeCustomizedSaved=false] Exclude saved settings in customized response (values pending writing to changeset).
			 * @return {Object} Query vars.
			 */
			query: function( options ) {
				var queryVars = {
					wp_customize: &#039;on&#039;,
					customize_theme: api.settings.theme.stylesheet,
					nonce: this.nonce.preview,
					customize_changeset_uuid: api.settings.changeset.uuid
				};
				if ( api.settings.changeset.autosaved || ! api.state( &#039;saved&#039; ).get() ) {
					queryVars.customize_autosaved = &#039;on&#039;;
				}

				/*
				 * Exclude customized data if requested especially for calls to requestChangesetUpdate.
				 * Changeset updates are differential and so it is a performance waste to send all of
				 * the dirty settings with each update.
				 */
				queryVars.customized = JSON.stringify( api.dirtyValues( {
					unsaved: options &amp;&amp; options.excludeCustomizedSaved
				} ) );

				return queryVars;
			},

			/**
			 * Save (and publish) the customizer changeset.
			 *
			 * Updates to the changeset are transactional. If any of the settings
			 * are invalid then none of them will be written into the changeset.
			 * A revision will be made for the changeset post if revisions support
			 * has been added to the post type.
			 *
			 * @since 3.4.0
			 * @since 4.7.0 Added args param and return value.
			 *
			 * @param {Object} [args] Args.
			 * @param {string} [args.status=publish] Status.
			 * @param {string} [args.date] Date, in local time in MySQL format.
			 * @param {string} [args.title] Title
			 * @return {jQuery.promise} Promise.
			 */
			save: function( args ) {
				var previewer = this,
					deferred = $.Deferred(),
					changesetStatus = api.state( &#039;selectedChangesetStatus&#039; ).get(),
					selectedChangesetDate = api.state( &#039;selectedChangesetDate&#039; ).get(),
					processing = api.state( &#039;processing&#039; ),
					submitWhenDoneProcessing,
					submit,
					modifiedWhileSaving = {},
					invalidSettings = [],
					invalidControls = [],
					invalidSettingLessControls = [];

				if ( args &amp;&amp; args.status ) {
					changesetStatus = args.status;
				}

				if ( api.state( &#039;saving&#039; ).get() ) {
					deferred.reject( &#039;already_saving&#039; );
					deferred.promise();
				}

				api.state( &#039;saving&#039; ).set( true );

				function captureSettingModifiedDuringSave( setting ) {
					modifiedWhileSaving[ setting.id ] = true;
				}

				submit = function () {
					var request, query, settingInvalidities = {}, latestRevision = api._latestRevision, errorCode = &#039;client_side_error&#039;;

					api.bind( &#039;change&#039;, captureSettingModifiedDuringSave );
					api.notifications.remove( errorCode );

					/*
					 * Block saving if there are any settings that are marked as
					 * invalid from the client (not from the server). Focus on
					 * the control.
					 */
					api.each( function( setting ) {
						setting.notifications.each( function( notification ) {
							if ( &#039;error&#039; === notification.type &amp;&amp; ! notification.fromServer ) {
								invalidSettings.push( setting.id );
								if ( ! settingInvalidities[ setting.id ] ) {
									settingInvalidities[ setting.id ] = {};
								}
								settingInvalidities[ setting.id ][ notification.code ] = notification;
							}
						} );
					} );

					// Find all invalid setting less controls with notification type error.
					api.control.each( function( control ) {
						if ( ! control.setting || ! control.setting.id &amp;&amp; control.active.get() ) {
							control.notifications.each( function( notification ) {
							    if ( &#039;error&#039; === notification.type ) {
								    invalidSettingLessControls.push( [ control ] );
							    }
							} );
						}
					} );

					invalidControls = _.union( invalidSettingLessControls, _.values( api.findControlsForSettings( invalidSettings ) ) );
					if ( ! _.isEmpty( invalidControls ) ) {

						invalidControls[0][0].focus();
						api.unbind( &#039;change&#039;, captureSettingModifiedDuringSave );

						if ( invalidSettings.length ) {
							api.notifications.add( new api.Notification( errorCode, {
								message: ( 1 === invalidSettings.length ? api.l10n.saveBlockedError.singular : api.l10n.saveBlockedError.plural ).replace( /%s/g, String( invalidSettings.length ) ),
								type: &#039;error&#039;,
								dismissible: true,
								saveFailure: true
							} ) );
						}

						deferred.rejectWith( previewer, [
							{ setting_invalidities: settingInvalidities }
						] );
						api.state( &#039;saving&#039; ).set( false );
						return deferred.promise();
					}

					/*
					 * Note that excludeCustomizedSaved is intentionally false so that the entire
					 * set of customized data will be included if bypassed changeset update.
					 */
					query = $.extend( previewer.query( { excludeCustomizedSaved: false } ), {
						nonce: previewer.nonce.save,
						customize_changeset_status: changesetStatus
					} );

					if ( args &amp;&amp; args.date ) {
						query.customize_changeset_date = args.date;
					} else if ( &#039;future&#039; === changesetStatus &amp;&amp; selectedChangesetDate ) {
						query.customize_changeset_date = selectedChangesetDate;
					}

					if ( args &amp;&amp; args.title ) {
						query.customize_changeset_title = args.title;
					}

					// Allow plugins to modify the params included with the save request.
					api.trigger( &#039;save-request-params&#039;, query );

					/*
					 * Note that the dirty customized values will have already been set in the
					 * changeset and so technically query.customized could be deleted. However,
					 * it is remaining here to make sure that any settings that got updated
					 * quietly which may have not triggered an update request will also get
					 * included in the values that get saved to the changeset. This will ensure
					 * that values that get injected via the saved event will be included in
					 * the changeset. This also ensures that setting values that were invalid
					 * will get re-validated, perhaps in the case of settings that are invalid
					 * due to dependencies on other settings.
					 */
					request = wp.ajax.post( &#039;customize_save&#039;, query );
					api.state( &#039;processing&#039; ).set( api.state( &#039;processing&#039; ).get() + 1 );

					api.trigger( &#039;save&#039;, request );

					request.always( function () {
						api.state( &#039;processing&#039; ).set( api.state( &#039;processing&#039; ).get() - 1 );
						api.state( &#039;saving&#039; ).set( false );
						api.unbind( &#039;change&#039;, captureSettingModifiedDuringSave );
					} );

					// Remove notifications that were added due to save failures.
					api.notifications.each( function( notification ) {
						if ( notification.saveFailure ) {
							api.notifications.remove( notification.code );
						}
					});

					request.fail( function ( response ) {
						var notification, notificationArgs;
						notificationArgs = {
							type: &#039;error&#039;,
							dismissible: true,
							fromServer: true,
							saveFailure: true
						};

						if ( &#039;0&#039; === response ) {
							response = &#039;not_logged_in&#039;;
						} else if ( &#039;-1&#039; === response ) {
							// Back-compat in case any other check_ajax_referer() call is dying.
							response = &#039;invalid_nonce&#039;;
						}

						if ( &#039;invalid_nonce&#039; === response ) {
							previewer.cheatin();
						} else if ( &#039;not_logged_in&#039; === response ) {
							previewer.preview.iframe.hide();
							previewer.login().done( function() {
								previewer.save();
								previewer.preview.iframe.show();
							} );
						} else if ( response.code ) {
							if ( &#039;not_future_date&#039; === response.code &amp;&amp; api.section.has( &#039;publish_settings&#039; ) &amp;&amp; api.section( &#039;publish_settings&#039; ).active.get() &amp;&amp; api.control.has( &#039;changeset_scheduled_date&#039; ) ) {
								api.control( &#039;changeset_scheduled_date&#039; ).toggleFutureDateNotification( true ).focus();
							} else if ( &#039;changeset_locked&#039; !== response.code ) {
								notification = new api.Notification( response.code, _.extend( notificationArgs, {
									message: response.message
								} ) );
							}
						} else {
							notification = new api.Notification( &#039;unknown_error&#039;, _.extend( notificationArgs, {
								message: api.l10n.unknownRequestFail
							} ) );
						}

						if ( notification ) {
							api.notifications.add( notification );
						}

						if ( response.setting_validities ) {
							api._handleSettingValidities( {
								settingValidities: response.setting_validities,
								focusInvalidControl: true
							} );
						}

						deferred.rejectWith( previewer, [ response ] );
						api.trigger( &#039;error&#039;, response );

						// Start a new changeset if the underlying changeset was published.
						if ( &#039;changeset_already_published&#039; === response.code &amp;&amp; response.next_changeset_uuid ) {
							api.settings.changeset.uuid = response.next_changeset_uuid;
							api.state( &#039;changesetStatus&#039; ).set( &#039;&#039; );
							if ( api.settings.changeset.branching ) {
								parent.send( &#039;changeset-uuid&#039;, api.settings.changeset.uuid );
							}
							api.previewer.send( &#039;changeset-uuid&#039;, api.settings.changeset.uuid );
						}
					} );

					request.done( function( response ) {

						previewer.send( &#039;saved&#039;, response );

						api.state( &#039;changesetStatus&#039; ).set( response.changeset_status );
						if ( response.changeset_date ) {
							api.state( &#039;changesetDate&#039; ).set( response.changeset_date );
						}

						if ( &#039;publish&#039; === response.changeset_status ) {

							// Mark all published as clean if they haven&#039;t been modified during the request.
							api.each( function( setting ) {
								/*
								 * Note that the setting revision will be undefined in the case of setting
								 * values that are marked as dirty when the customizer is loaded, such as
								 * when applying starter content. All other dirty settings will have an
								 * associated revision due to their modification triggering a change event.
								 */
								if ( setting._dirty &amp;&amp; ( _.isUndefined( api._latestSettingRevisions[ setting.id ] ) || api._latestSettingRevisions[ setting.id ] &lt;= latestRevision ) ) {
									setting._dirty = false;
								}
							} );

							api.state( &#039;changesetStatus&#039; ).set( &#039;&#039; );
							api.settings.changeset.uuid = response.next_changeset_uuid;
							if ( api.settings.changeset.branching ) {
								parent.send( &#039;changeset-uuid&#039;, api.settings.changeset.uuid );
							}
						}

						// Prevent subsequent requestChangesetUpdate() calls from including the settings that have been saved.
						api._lastSavedRevision = Math.max( latestRevision, api._lastSavedRevision );

						if ( response.setting_validities ) {
							api._handleSettingValidities( {
								settingValidities: response.setting_validities,
								focusInvalidControl: true
							} );
						}

						deferred.resolveWith( previewer, [ response ] );
						api.trigger( &#039;saved&#039;, response );

						// Restore the global dirty state if any settings were modified during save.
						if ( ! _.isEmpty( modifiedWhileSaving ) ) {
							api.state( &#039;saved&#039; ).set( false );
						}
					} );
				};

				if ( 0 === processing() ) {
					submit();
				} else {
					submitWhenDoneProcessing = function () {
						if ( 0 === processing() ) {
							api.state.unbind( &#039;change&#039;, submitWhenDoneProcessing );
							submit();
						}
					};
					api.state.bind( &#039;change&#039;, submitWhenDoneProcessing );
				}

				return deferred.promise();
			},

			/**
			 * Trash the current changes.
			 *
			 * Revert the Customizer to its previously-published state.
			 *
			 * @since 4.9.0
			 *
			 * @return {jQuery.promise} Promise.
			 */
			trash: function trash() {
				var request, success, fail;

				api.state( &#039;trashing&#039; ).set( true );
				api.state( &#039;processing&#039; ).set( api.state( &#039;processing&#039; ).get() + 1 );

				request = wp.ajax.post( &#039;customize_trash&#039;, {
					customize_changeset_uuid: api.settings.changeset.uuid,
					nonce: api.settings.nonce.trash
				} );
				api.notifications.add( new api.OverlayNotification( &#039;changeset_trashing&#039;, {
					type: &#039;info&#039;,
					message: api.l10n.revertingChanges,
					loading: true
				} ) );

				success = function() {
					var urlParser = document.createElement( &#039;a&#039; ), queryParams;

					api.state( &#039;changesetStatus&#039; ).set( &#039;trash&#039; );
					api.each( function( setting ) {
						setting._dirty = false;
					} );
					api.state( &#039;saved&#039; ).set( true );

					// Go back to Customizer without changeset.
					urlParser.href = location.href;
					queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
					delete queryParams.changeset_uuid;
					queryParams[&#039;return&#039;] = api.settings.url[&#039;return&#039;];
					urlParser.search = $.param( queryParams );
					location.replace( urlParser.href );
				};

				fail = function( code, message ) {
					var notificationCode = code || &#039;unknown_error&#039;;
					api.state( &#039;processing&#039; ).set( api.state( &#039;processing&#039; ).get() - 1 );
					api.state( &#039;trashing&#039; ).set( false );
					api.notifications.remove( &#039;changeset_trashing&#039; );
					api.notifications.add( new api.Notification( notificationCode, {
						message: message || api.l10n.unknownError,
						dismissible: true,
						type: &#039;error&#039;
					} ) );
				};

				request.done( function( response ) {
					success( response.message );
				} );

				request.fail( function( response ) {
					var code = response.code || &#039;trashing_failed&#039;;
					if ( response.success || &#039;non_existent_changeset&#039; === code || &#039;changeset_already_trashed&#039; === code ) {
						success( response.message );
					} else {
						fail( code, response.message );
					}
				} );
			},

			/**
			 * Builds the front preview URL with the current state of customizer.
			 *
			 * @since 4.9.0
			 *
			 * @return {string} Preview URL.
			 */
			getFrontendPreviewUrl: function() {
				var previewer = this, params, urlParser;
				urlParser = document.createElement( &#039;a&#039; );
				urlParser.href = previewer.previewUrl.get();
				params = api.utils.parseQueryString( urlParser.search.substr( 1 ) );

				if ( api.state( &#039;changesetStatus&#039; ).get() &amp;&amp; &#039;publish&#039; !== api.state( &#039;changesetStatus&#039; ).get() ) {
					params.customize_changeset_uuid = api.settings.changeset.uuid;
				}
				if ( ! api.state( &#039;activated&#039; ).get() ) {
					params.customize_theme = api.settings.theme.stylesheet;
				}

				urlParser.search = $.param( params );
				return urlParser.href;
			}
		});

		// Ensure preview nonce is included with every customized request, to allow post data to be read.
		$.ajaxPrefilter( function injectPreviewNonce( options ) {
			if ( ! /wp_customize=on/.test( options.data ) ) {
				return;
			}
			options.data += &#039;&amp;&#039; + $.param({
				customize_preview_nonce: api.settings.nonce.preview
			});
		});

		// Refresh the nonces if the preview sends updated nonces over.
		api.previewer.bind( &#039;nonce&#039;, function( nonce ) {
			$.extend( this.nonce, nonce );
		});

		// Refresh the nonces if login sends updated nonces over.
		api.bind( &#039;nonce-refresh&#039;, function( nonce ) {
			$.extend( api.settings.nonce, nonce );
			$.extend( api.previewer.nonce, nonce );
			api.previewer.send( &#039;nonce-refresh&#039;, nonce );
		});

		// Create Settings.
		$.each( api.settings.settings, function( id, data ) {
			var Constructor = api.settingConstructor[ data.type ] || api.Setting;
			api.add( new Constructor( id, data.value, {
				transport: data.transport,
				previewer: api.previewer,
				dirty: !! data.dirty
			} ) );
		});

		// Create Panels.
		$.each( api.settings.panels, function ( id, data ) {
			var Constructor = api.panelConstructor[ data.type ] || api.Panel, options;
			// Inclusion of params alias is for back-compat for custom panels that expect to augment this property.
			options = _.extend( { params: data }, data );
			api.panel.add( new Constructor( id, options ) );
		});

		// Create Sections.
		$.each( api.settings.sections, function ( id, data ) {
			var Constructor = api.sectionConstructor[ data.type ] || api.Section, options;
			// Inclusion of params alias is for back-compat for custom sections that expect to augment this property.
			options = _.extend( { params: data }, data );
			api.section.add( new Constructor( id, options ) );
		});

		// Create Controls.
		$.each( api.settings.controls, function( id, data ) {
			var Constructor = api.controlConstructor[ data.type ] || api.Control, options;
			// Inclusion of params alias is for back-compat for custom controls that expect to augment this property.
			options = _.extend( { params: data }, data );
			api.control.add( new Constructor( id, options ) );
		});

		// Focus the autofocused element.
		_.each( [ &#039;panel&#039;, &#039;section&#039;, &#039;control&#039; ], function( type ) {
			var id = api.settings.autofocus[ type ];
			if ( ! id ) {
				return;
			}

			/*
			 * Defer focus until:
			 * 1. The panel, section, or control exists (especially for dynamically-created ones).
			 * 2. The instance is embedded in the document (and so is focusable).
			 * 3. The preview has finished loading so that the active states have been set.
			 */
			api[ type ]( id, function( instance ) {
				instance.deferred.embedded.done( function() {
					api.previewer.deferred.active.done( function() {
						instance.focus();
					});
				});
			});
		});

		api.bind( &#039;ready&#039;, api.reflowPaneContents );
		$( [ api.panel, api.section, api.control ] ).each( function ( i, values ) {
			var debouncedReflowPaneContents = _.debounce( api.reflowPaneContents, api.settings.timeouts.reflowPaneContents );
			values.bind( &#039;add&#039;, debouncedReflowPaneContents );
			values.bind( &#039;change&#039;, debouncedReflowPaneContents );
			values.bind( &#039;remove&#039;, debouncedReflowPaneContents );
		} );

		// Set up global notifications area.
		api.bind( &#039;ready&#039;, function setUpGlobalNotificationsArea() {
			var sidebar, containerHeight, containerInitialTop;
			api.notifications.container = $( &#039;#customize-notifications-area&#039; );

			api.notifications.bind( &#039;change&#039;, _.debounce( function() {
				api.notifications.render();
			} ) );

			sidebar = $( &#039;.wp-full-overlay-sidebar-content&#039; );
			api.notifications.bind( &#039;rendered&#039;, function updateSidebarTop() {
				sidebar.css( &#039;top&#039;, &#039;&#039; );
				if ( 0 !== api.notifications.count() ) {
					containerHeight = api.notifications.container.outerHeight() + 1;
					containerInitialTop = parseInt( sidebar.css( &#039;top&#039; ), 10 );
					sidebar.css( &#039;top&#039;, containerInitialTop + containerHeight + &#039;px&#039; );
				}
				api.notifications.trigger( &#039;sidebarTopUpdated&#039; );
			});

			api.notifications.render();
		});

		// Save and activated states.
		(function( state ) {
			var saved = state.instance( &#039;saved&#039; ),
				saving = state.instance( &#039;saving&#039; ),
				trashing = state.instance( &#039;trashing&#039; ),
				activated = state.instance( &#039;activated&#039; ),
				processing = state.instance( &#039;processing&#039; ),
				paneVisible = state.instance( &#039;paneVisible&#039; ),
				expandedPanel = state.instance( &#039;expandedPanel&#039; ),
				expandedSection = state.instance( &#039;expandedSection&#039; ),
				changesetStatus = state.instance( &#039;changesetStatus&#039; ),
				selectedChangesetStatus = state.instance( &#039;selectedChangesetStatus&#039; ),
				changesetDate = state.instance( &#039;changesetDate&#039; ),
				selectedChangesetDate = state.instance( &#039;selectedChangesetDate&#039; ),
				previewerAlive = state.instance( &#039;previewerAlive&#039; ),
				editShortcutVisibility  = state.instance( &#039;editShortcutVisibility&#039; ),
				changesetLocked = state.instance( &#039;changesetLocked&#039; ),
				populateChangesetUuidParam, defaultSelectedChangesetStatus;

			state.bind( &#039;change&#039;, function() {
				var canSave;

				if ( ! activated() ) {
					saveBtn.val( api.l10n.activate );
					closeBtn.find( &#039;.screen-reader-text&#039; ).text( api.l10n.cancel );

				} else if ( &#039;&#039; === changesetStatus.get() &amp;&amp; saved() ) {
					if ( api.settings.changeset.currentUserCanPublish ) {
						saveBtn.val( api.l10n.published );
					} else {
						saveBtn.val( api.l10n.saved );
					}
					closeBtn.find( &#039;.screen-reader-text&#039; ).text( api.l10n.close );

				} else {
					if ( &#039;draft&#039; === selectedChangesetStatus() ) {
						if ( saved() &amp;&amp; selectedChangesetStatus() === changesetStatus() ) {
							saveBtn.val( api.l10n.draftSaved );
						} else {
							saveBtn.val( api.l10n.saveDraft );
						}
					} else if ( &#039;future&#039; === selectedChangesetStatus() ) {
						if ( saved() &amp;&amp; selectedChangesetStatus() === changesetStatus() ) {
							if ( changesetDate.get() !== selectedChangesetDate.get() ) {
								saveBtn.val( api.l10n.schedule );
							} else {
								saveBtn.val( api.l10n.scheduled );
							}
						} else {
							saveBtn.val( api.l10n.schedule );
						}
					} else if ( api.settings.changeset.currentUserCanPublish ) {
						saveBtn.val( api.l10n.publish );
					}
					closeBtn.find( &#039;.screen-reader-text&#039; ).text( api.l10n.cancel );
				}

				/*
				 * Save (publish) button should be enabled if saving is not currently happening,
				 * and if the theme is not active or the changeset exists but is not published.
				 */
				canSave = ! saving() &amp;&amp; ! trashing() &amp;&amp; ! changesetLocked() &amp;&amp; ( ! activated() || ! saved() || ( changesetStatus() !== selectedChangesetStatus() &amp;&amp; &#039;&#039; !== changesetStatus() ) || ( &#039;future&#039; === selectedChangesetStatus() &amp;&amp; changesetDate.get() !== selectedChangesetDate.get() ) );

				saveBtn.prop( &#039;disabled&#039;, ! canSave );
			});

			selectedChangesetStatus.validate = function( status ) {
				if ( &#039;&#039; === status || &#039;auto-draft&#039; === status ) {
					return null;
				}
				return status;
			};

			defaultSelectedChangesetStatus = api.settings.changeset.currentUserCanPublish ? &#039;publish&#039; : &#039;draft&#039;;

			// Set default states.
			changesetStatus( api.settings.changeset.status );
			changesetLocked( Boolean( api.settings.changeset.lockUser ) );
			changesetDate( api.settings.changeset.publishDate );
			selectedChangesetDate( api.settings.changeset.publishDate );
			selectedChangesetStatus( &#039;&#039; === api.settings.changeset.status || &#039;auto-draft&#039; === api.settings.changeset.status ? defaultSelectedChangesetStatus : api.settings.changeset.status );
			selectedChangesetStatus.link( changesetStatus ); // Ensure that direct updates to status on server via wp.customizer.previewer.save() will update selection.
			saved( true );
			if ( &#039;&#039; === changesetStatus() ) { // Handle case for loading starter content.
				api.each( function( setting ) {
					if ( setting._dirty ) {
						saved( false );
					}
				} );
			}
			saving( false );
			activated( api.settings.theme.active );
			processing( 0 );
			paneVisible( true );
			expandedPanel( false );
			expandedSection( false );
			previewerAlive( true );
			editShortcutVisibility( &#039;visible&#039; );

			api.bind( &#039;change&#039;, function() {
				if ( state( &#039;saved&#039; ).get() ) {
					state( &#039;saved&#039; ).set( false );
				}
			});

			// Populate changeset UUID param when state becomes dirty.
			if ( api.settings.changeset.branching ) {
				saved.bind( function( isSaved ) {
					if ( ! isSaved ) {
						populateChangesetUuidParam( true );
					}
				});
			}

			saving.bind( function( isSaving ) {
				body.toggleClass( &#039;saving&#039;, isSaving );
			} );
			trashing.bind( function( isTrashing ) {
				body.toggleClass( &#039;trashing&#039;, isTrashing );
			} );

			api.bind( &#039;saved&#039;, function( response ) {
				state(&#039;saved&#039;).set( true );
				if ( &#039;publish&#039; === response.changeset_status ) {
					state( &#039;activated&#039; ).set( true );
				}
			});

			activated.bind( function( to ) {
				if ( to ) {
					api.trigger( &#039;activated&#039; );
				}
			});

			/**
			 * Populate URL with UUID via `history.replaceState()`.
			 *
			 * @since 4.7.0
			 * @access private
			 *
			 * @param {boolean} isIncluded Is UUID included.
			 * @return {void}
			 */
			populateChangesetUuidParam = function( isIncluded ) {
				var urlParser, queryParams;

				// Abort on IE9 which doesn&#039;t support history management.
				if ( ! history.replaceState ) {
					return;
				}

				urlParser = document.createElement( &#039;a&#039; );
				urlParser.href = location.href;
				queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
				if ( isIncluded ) {
					if ( queryParams.changeset_uuid === api.settings.changeset.uuid ) {
						return;
					}
					queryParams.changeset_uuid = api.settings.changeset.uuid;
				} else {
					if ( ! queryParams.changeset_uuid ) {
						return;
					}
					delete queryParams.changeset_uuid;
				}
				urlParser.search = $.param( queryParams );
				history.replaceState( {}, document.title, urlParser.href );
			};

			// Show changeset UUID in URL when in branching mode and there is a saved changeset.
			if ( api.settings.changeset.branching ) {
				changesetStatus.bind( function( newStatus ) {
					populateChangesetUuidParam( &#039;&#039; !== newStatus &amp;&amp; &#039;publish&#039; !== newStatus &amp;&amp; &#039;trash&#039; !== newStatus );
				} );
			}
		}( api.state ) );

		/**
		 * Handles lock notice and take over request.
		 *
		 * @since 4.9.0
		 */
		( function checkAndDisplayLockNotice() {

			var LockedNotification = api.OverlayNotification.extend(/** @lends wp.customize~LockedNotification.prototype */{

				/**
				 * Template ID.
				 *
				 * @type {string}
				 */
				templateId: &#039;customize-changeset-locked-notification&#039;,

				/**
				 * Lock user.
				 *
				 * @type {object}
				 */
				lockUser: null,

				/**
				 * A notification that is displayed in a full-screen overlay with information about the locked changeset.
				 *
				 * @constructs wp.customize~LockedNotification
				 * @augments   wp.customize.OverlayNotification
				 *
				 * @since 4.9.0
				 *
				 * @param {string} [code] - Code.
				 * @param {Object} [params] - Params.
				 */
				initialize: function( code, params ) {
					var notification = this, _code, _params;
					_code = code || &#039;changeset_locked&#039;;
					_params = _.extend(
						{
							message: &#039;&#039;,
							type: &#039;warning&#039;,
							containerClasses: &#039;&#039;,
							lockUser: {}
						},
						params
					);
					_params.containerClasses += &#039; notification-changeset-locked&#039;;
					api.OverlayNotification.prototype.initialize.call( notification, _code, _params );
				},

				/**
				 * Render notification.
				 *
				 * @since 4.9.0
				 *
				 * @return {jQuery} Notification container.
				 */
				render: function() {
					var notification = this, li, data, takeOverButton, request;
					data = _.extend(
						{
							allowOverride: false,
							returnUrl: api.settings.url[&#039;return&#039;],
							previewUrl: api.previewer.previewUrl.get(),
							frontendPreviewUrl: api.previewer.getFrontendPreviewUrl()
						},
						this
					);

					li = api.OverlayNotification.prototype.render.call( data );

					// Try to autosave the changeset now.
					api.requestChangesetUpdate( {}, { autosave: true } ).fail( function( response ) {
						if ( ! response.autosaved ) {
							li.find( &#039;.notice-error&#039; ).prop( &#039;hidden&#039;, false ).text( response.message || api.l10n.unknownRequestFail );
						}
					} );

					takeOverButton = li.find( &#039;.customize-notice-take-over-button&#039; );
					takeOverButton.on( &#039;click&#039;, function( event ) {
						event.preventDefault();
						if ( request ) {
							return;
						}

						takeOverButton.addClass( &#039;disabled&#039; );
						request = wp.ajax.post( &#039;customize_override_changeset_lock&#039;, {
							wp_customize: &#039;on&#039;,
							customize_theme: api.settings.theme.stylesheet,
							customize_changeset_uuid: api.settings.changeset.uuid,
							nonce: api.settings.nonce.override_lock
						} );

						request.done( function() {
							api.notifications.remove( notification.code ); // Remove self.
							api.state( &#039;changesetLocked&#039; ).set( false );
						} );

						request.fail( function( response ) {
							var message = response.message || api.l10n.unknownRequestFail;
							li.find( &#039;.notice-error&#039; ).prop( &#039;hidden&#039;, false ).text( message );

							request.always( function() {
								takeOverButton.removeClass( &#039;disabled&#039; );
							} );
						} );

						request.always( function() {
							request = null;
						} );
					} );

					return li;
				}
			});

			/**
			 * Start lock.
			 *
			 * @since 4.9.0
			 *
			 * @param {Object} [args] - Args.
			 * @param {Object} [args.lockUser] - Lock user data.
			 * @param {boolean} [args.allowOverride=false] - Whether override is allowed.
			 * @return {void}
			 */
			function startLock( args ) {
				if ( args &amp;&amp; args.lockUser ) {
					api.settings.changeset.lockUser = args.lockUser;
				}
				api.state( &#039;changesetLocked&#039; ).set( true );
				api.notifications.add( new LockedNotification( &#039;changeset_locked&#039;, {
					lockUser: api.settings.changeset.lockUser,
					allowOverride: Boolean( args &amp;&amp; args.allowOverride )
				} ) );
			}

			// Show initial notification.
			if ( api.settings.changeset.lockUser ) {
				startLock( { allowOverride: true } );
			}

			// Check for lock when sending heartbeat requests.
			$( document ).on( &#039;heartbeat-send.update_lock_notice&#039;, function( event, data ) {
				data.check_changeset_lock = true;
				data.changeset_uuid = api.settings.changeset.uuid;
			} );

			// Handle heartbeat ticks.
			$( document ).on( &#039;heartbeat-tick.update_lock_notice&#039;, function( event, data ) {
				var notification, code = &#039;changeset_locked&#039;;
				if ( ! data.customize_changeset_lock_user ) {
					return;
				}

				// Update notification when a different user takes over.
				notification = api.notifications( code );
				if ( notification &amp;&amp; notification.lockUser.id !== api.settings.changeset.lockUser.id ) {
					api.notifications.remove( code );
				}

				startLock( {
					lockUser: data.customize_changeset_lock_user
				} );
			} );

			// Handle locking in response to changeset save errors.
			api.bind( &#039;error&#039;, function( response ) {
				if ( &#039;changeset_locked&#039; === response.code &amp;&amp; response.lock_user ) {
					startLock( {
						lockUser: response.lock_user
					} );
				}
			} );
		} )();

		// Set up initial notifications.
		(function() {
			var removedQueryParams = [], autosaveDismissed = false;

			/**
			 * Obtain the URL to restore the autosave.
			 *
			 * @return {string} Customizer URL.
			 */
			function getAutosaveRestorationUrl() {
				var urlParser, queryParams;
				urlParser = document.createElement( &#039;a&#039; );
				urlParser.href = location.href;
				queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
				if ( api.settings.changeset.latestAutoDraftUuid ) {
					queryParams.changeset_uuid = api.settings.changeset.latestAutoDraftUuid;
				} else {
					queryParams.customize_autosaved = &#039;on&#039;;
				}
				queryParams[&#039;return&#039;] = api.settings.url[&#039;return&#039;];
				urlParser.search = $.param( queryParams );
				return urlParser.href;
			}

			/**
			 * Remove parameter from the URL.
			 *
			 * @param {Array} params - Parameter names to remove.
			 * @return {void}
			 */
			function stripParamsFromLocation( params ) {
				var urlParser = document.createElement( &#039;a&#039; ), queryParams, strippedParams = 0;
				urlParser.href = location.href;
				queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) );
				_.each( params, function( param ) {
					if ( &#039;undefined&#039; !== typeof queryParams[ param ] ) {
						strippedParams += 1;
						delete queryParams[ param ];
					}
				} );
				if ( 0 === strippedParams ) {
					return;
				}

				urlParser.search = $.param( queryParams );
				history.replaceState( {}, document.title, urlParser.href );
			}

			/**
			 * Displays a Site Editor notification when a block theme is activated.
			 *
			 * @since 4.9.0
			 *
			 * @param {string} [notification] - A notification to display.
			 * @return {void}
			 */
			function addSiteEditorNotification( notification ) {
				api.notifications.add( new api.Notification( &#039;site_editor_block_theme_notice&#039;, {
					message: notification,
					type: &#039;info&#039;,
					dismissible: false,
					render: function() {
						var notification = api.Notification.prototype.render.call( this ),
							button = notification.find( &#039;button.switch-to-editor&#039; );

						button.on( &#039;click&#039;, function( event ) {
							event.preventDefault();
							location.assign( button.data( &#039;action&#039; ) );
						} );

						return notification;
					}
				} ) );
			}

			/**
			 * Dismiss autosave.
			 *
			 * @return {void}
			 */
			function dismissAutosave() {
				if ( autosaveDismissed ) {
					return;
				}
				wp.ajax.post( &#039;customize_dismiss_autosave_or_lock&#039;, {
					wp_customize: &#039;on&#039;,
					customize_theme: api.settings.theme.stylesheet,
					customize_changeset_uuid: api.settings.changeset.uuid,
					nonce: api.settings.nonce.dismiss_autosave_or_lock,
					dismiss_autosave: true
				} );
				autosaveDismissed = true;
			}

			/**
			 * Add notification regarding the availability of an autosave to restore.
			 *
			 * @return {void}
			 */
			function addAutosaveRestoreNotification() {
				var code = &#039;autosave_available&#039;, onStateChange;

				// Since there is an autosave revision and the user hasn&#039;t loaded with autosaved, add notification to prompt to load autosaved version.
				api.notifications.add( new api.Notification( code, {
					message: api.l10n.autosaveNotice,
					type: &#039;warning&#039;,
					dismissible: true,
					render: function() {
						var li = api.Notification.prototype.render.call( this ), link;

						// Handle clicking on restoration link.
						link = li.find( &#039;a&#039; );
						link.prop( &#039;href&#039;, getAutosaveRestorationUrl() );
						link.on( &#039;click&#039;, function( event ) {
							event.preventDefault();
							location.replace( getAutosaveRestorationUrl() );
						} );

						// Handle dismissal of notice.
						li.find( &#039;.notice-dismiss&#039; ).on( &#039;click&#039;, dismissAutosave );

						return li;
					}
				} ) );

				// Remove the notification once the user starts making changes.
				onStateChange = function() {
					dismissAutosave();
					api.notifications.remove( code );
					api.unbind( &#039;change&#039;, onStateChange );
					api.state( &#039;changesetStatus&#039; ).unbind( onStateChange );
				};
				api.bind( &#039;change&#039;, onStateChange );
				api.state( &#039;changesetStatus&#039; ).bind( onStateChange );
			}

			if ( api.settings.changeset.autosaved ) {
				api.state( &#039;saved&#039; ).set( false );
				removedQueryParams.push( &#039;customize_autosaved&#039; );
			}
			if ( ! api.settings.changeset.branching &amp;&amp; ( ! api.settings.changeset.status || &#039;auto-draft&#039; === api.settings.changeset.status ) ) {
				removedQueryParams.push( &#039;changeset_uuid&#039; ); // Remove UUID when restoring autosave auto-draft.
			}
			if ( removedQueryParams.length &gt; 0 ) {
				stripParamsFromLocation( removedQueryParams );
			}
			if ( api.settings.changeset.latestAutoDraftUuid || api.settings.changeset.hasAutosaveRevision ) {
				addAutosaveRestoreNotification();
			}
			var shouldDisplayBlockThemeNotification = !! parseInt( $( &#039;#customize-info&#039; ).data( &#039;block-theme&#039; ), 10 );
			if (shouldDisplayBlockThemeNotification) {
				addSiteEditorNotification( api.l10n.blockThemeNotification );
			}
		})();

		// Check if preview url is valid and load the preview frame.
		if ( api.previewer.previewUrl() ) {
			api.previewer.refresh();
		} else {
			api.previewer.previewUrl( api.settings.url.home );
		}

		// Button bindings.
		saveBtn.on( &#039;click&#039;, function( event ) {
			api.previewer.save();
			event.preventDefault();
		}).on( &#039;keydown&#039;, function( event ) {
			if ( 9 === event.which ) { // Tab.
				return;
			}
			if ( 13 === event.which ) { // Enter.
				api.previewer.save();
			}
			event.preventDefault();
		});

		closeBtn.on( &#039;keydown&#039;, function( event ) {
			if ( 9 === event.which ) { // Tab.
				return;
			}
			if ( 13 === event.which ) { // Enter.
				this.click();
			}
			event.preventDefault();
		});

		$( &#039;.collapse-sidebar&#039; ).on( &#039;click&#039;, function() {
			api.state( &#039;paneVisible&#039; ).set( ! api.state( &#039;paneVisible&#039; ).get() );
		});

		api.state( &#039;paneVisible&#039; ).bind( function( paneVisible ) {
			overlay.toggleClass( &#039;preview-only&#039;, ! paneVisible );
			overlay.toggleClass( &#039;expanded&#039;, paneVisible );
			overlay.toggleClass( &#039;collapsed&#039;, ! paneVisible );

			if ( ! paneVisible ) {
				$( &#039;.collapse-sidebar&#039; ).attr({ &#039;aria-expanded&#039;: &#039;false&#039;, &#039;aria-label&#039;: api.l10n.expandSidebar });
			} else {
				$( &#039;.collapse-sidebar&#039; ).attr({ &#039;aria-expanded&#039;: &#039;true&#039;, &#039;aria-label&#039;: api.l10n.collapseSidebar });
			}
		});

		// Keyboard shortcuts - esc to exit section/panel.
		body.on( &#039;keydown&#039;, function( event ) {
			var collapsedObject, expandedControls = [], expandedSections = [], expandedPanels = [];

			if ( 27 !== event.which ) { // Esc.
				return;
			}

			/*
			 * Abort if the event target is not the body (the default) and not inside of #customize-controls.
			 * This ensures that ESC meant to collapse a modal dialog or a TinyMCE toolbar won&#039;t collapse something else.
			 */
			if ( ! $( event.target ).is( &#039;body&#039; ) &amp;&amp; ! $.contains( $( &#039;#customize-controls&#039; )[0], event.target ) ) {
				return;
			}

			// Abort if we&#039;re inside of a block editor instance.
			if ( event.target.closest( &#039;.block-editor-writing-flow&#039; ) !== null ||
				event.target.closest( &#039;.block-editor-block-list__block-popover&#039; ) !== null
			) {
				return;
			}

			// Check for expanded expandable controls (e.g. widgets and nav menus items), sections, and panels.
			api.control.each( function( control ) {
				if ( control.expanded &amp;&amp; control.expanded() &amp;&amp; _.isFunction( control.collapse ) ) {
					expandedControls.push( control );
				}
			});
			api.section.each( function( section ) {
				if ( section.expanded() ) {
					expandedSections.push( section );
				}
			});
			api.panel.each( function( panel ) {
				if ( panel.expanded() ) {
					expandedPanels.push( panel );
				}
			});

			// Skip collapsing expanded controls if there are no expanded sections.
			if ( expandedControls.length &gt; 0 &amp;&amp; 0 === expandedSections.length ) {
				expandedControls.length = 0;
			}

			// Collapse the most granular expanded object.
			collapsedObject = expandedControls[0] || expandedSections[0] || expandedPanels[0];
			if ( collapsedObject ) {
				if ( &#039;themes&#039; === collapsedObject.params.type ) {

					// Themes panel or section.
					if ( body.hasClass( &#039;modal-open&#039; ) ) {
						collapsedObject.closeDetails();
					} else if ( api.panel.has( &#039;themes&#039; ) ) {

						// If we&#039;re collapsing a section, collapse the panel also.
						api.panel( &#039;themes&#039; ).collapse();
					}
					return;
				}
				collapsedObject.collapse();
				event.preventDefault();
			}
		});

		$( &#039;.customize-controls-preview-toggle&#039; ).on( &#039;click&#039;, function() {
			api.state( &#039;paneVisible&#039; ).set( ! api.state( &#039;paneVisible&#039; ).get() );
		});

		/*
		 * Sticky header feature.
		 */
		(function initStickyHeaders() {
			var parentContainer = $( &#039;.wp-full-overlay-sidebar-content&#039; ),
				changeContainer, updateHeaderHeight, releaseStickyHeader, resetStickyHeader, positionStickyHeader,
				activeHeader, lastScrollTop;

			/**
			 * Determine which panel or section is currently expanded.
			 *
			 * @since 4.7.0
			 * @access private
			 *
			 * @param {wp.customize.Panel|wp.customize.Section} container Construct.
			 * @return {void}
			 */
			changeContainer = function( container ) {
				var newInstance = container,
					expandedSection = api.state( &#039;expandedSection&#039; ).get(),
					expandedPanel = api.state( &#039;expandedPanel&#039; ).get(),
					headerElement;

				if ( activeHeader &amp;&amp; activeHeader.element ) {
					// Release previously active header element.
					releaseStickyHeader( activeHeader.element );

					// Remove event listener in the previous panel or section.
					activeHeader.element.find( &#039;.description&#039; ).off( &#039;toggled&#039;, updateHeaderHeight );
				}

				if ( ! newInstance ) {
					if ( ! expandedSection &amp;&amp; expandedPanel &amp;&amp; expandedPanel.contentContainer ) {
						newInstance = expandedPanel;
					} else if ( ! expandedPanel &amp;&amp; expandedSection &amp;&amp; expandedSection.contentContainer ) {
						newInstance = expandedSection;
					} else {
						activeHeader = false;
						return;
					}
				}

				headerElement = newInstance.contentContainer.find( &#039;.customize-section-title, .panel-meta&#039; ).first();
				if ( headerElement.length ) {
					activeHeader = {
						instance: newInstance,
						element:  headerElement,
						parent:   headerElement.closest( &#039;.customize-pane-child&#039; ),
						height:   headerElement.outerHeight()
					};

					// Update header height whenever help text is expanded or collapsed.
					activeHeader.element.find( &#039;.description&#039; ).on( &#039;toggled&#039;, updateHeaderHeight );

					if ( expandedSection ) {
						resetStickyHeader( activeHeader.element, activeHeader.parent );
					}
				} else {
					activeHeader = false;
				}
			};
			api.state( &#039;expandedSection&#039; ).bind( changeContainer );
			api.state( &#039;expandedPanel&#039; ).bind( changeContainer );

			// Throttled scroll event handler.
			parentContainer.on( &#039;scroll&#039;, _.throttle( function() {
				if ( ! activeHeader ) {
					return;
				}

				var scrollTop = parentContainer.scrollTop(),
					scrollDirection;

				if ( ! lastScrollTop ) {
					scrollDirection = 1;
				} else {
					if ( scrollTop === lastScrollTop ) {
						scrollDirection = 0;
					} else if ( scrollTop &gt; lastScrollTop ) {
						scrollDirection = 1;
					} else {
						scrollDirection = -1;
					}
				}
				lastScrollTop = scrollTop;
				if ( 0 !== scrollDirection ) {
					positionStickyHeader( activeHeader, scrollTop, scrollDirection );
				}
			}, 8 ) );

			// Update header position on sidebar layout change.
			api.notifications.bind( &#039;sidebarTopUpdated&#039;, function() {
				if ( activeHeader &amp;&amp; activeHeader.element.hasClass( &#039;is-sticky&#039; ) ) {
					activeHeader.element.css( &#039;top&#039;, parentContainer.css( &#039;top&#039; ) );
				}
			});

			// Release header element if it is sticky.
			releaseStickyHeader = function( headerElement ) {
				if ( ! headerElement.hasClass( &#039;is-sticky&#039; ) ) {
					return;
				}
				headerElement
					.removeClass( &#039;is-sticky&#039; )
					.addClass( &#039;maybe-sticky is-in-view&#039; )
					.css( &#039;top&#039;, parentContainer.scrollTop() + &#039;px&#039; );
			};

			// Reset position of the sticky header.
			resetStickyHeader = function( headerElement, headerParent ) {
				if ( headerElement.hasClass( &#039;is-in-view&#039; ) ) {
					headerElement
						.removeClass( &#039;maybe-sticky is-in-view&#039; )
						.css( {
							width: &#039;&#039;,
							top:   &#039;&#039;
						} );
					headerParent.css( &#039;padding-top&#039;, &#039;&#039; );
				}
			};

			/**
			 * Update active header height.
			 *
			 * @since 4.7.0
			 * @access private
			 *
			 * @return {void}
			 */
			updateHeaderHeight = function() {
				activeHeader.height = activeHeader.element.outerHeight();
			};

			/**
			 * Reposition header on throttled `scroll` event.
			 *
			 * @since 4.7.0
			 * @access private
			 *
			 * @param {Object} header - Header.
			 * @param {number} scrollTop - Scroll top.
			 * @param {number} scrollDirection - Scroll direction, negative number being up and positive being down.
			 * @return {void}
			 */
			positionStickyHeader = function( header, scrollTop, scrollDirection ) {
				var headerElement = header.element,
					headerParent = header.parent,
					headerHeight = header.height,
					headerTop = parseInt( headerElement.css( &#039;top&#039; ), 10 ),
					maybeSticky = headerElement.hasClass( &#039;maybe-sticky&#039; ),
					isSticky = headerElement.hasClass( &#039;is-sticky&#039; ),
					isInView = headerElement.hasClass( &#039;is-in-view&#039; ),
					isScrollingUp = ( -1 === scrollDirection );

				// When scrolling down, gradually hide sticky header.
				if ( ! isScrollingUp ) {
					if ( isSticky ) {
						headerTop = scrollTop;
						headerElement
							.removeClass( &#039;is-sticky&#039; )
							.css( {
								top:   headerTop + &#039;px&#039;,
								width: &#039;&#039;
							} );
					}
					if ( isInView &amp;&amp; scrollTop &gt; headerTop + headerHeight ) {
						headerElement.removeClass( &#039;is-in-view&#039; );
						headerParent.css( &#039;padding-top&#039;, &#039;&#039; );
					}
					return;
				}

				// Scrolling up.
				if ( ! maybeSticky &amp;&amp; scrollTop &gt;= headerHeight ) {
					maybeSticky = true;
					headerElement.addClass( &#039;maybe-sticky&#039; );
				} else if ( 0 === scrollTop ) {
					// Reset header in base position.
					headerElement
						.removeClass( &#039;maybe-sticky is-in-view is-sticky&#039; )
						.css( {
							top:   &#039;&#039;,
							width: &#039;&#039;
						} );
					headerParent.css( &#039;padding-top&#039;, &#039;&#039; );
					return;
				}

				if ( isInView &amp;&amp; ! isSticky ) {
					// Header is in the view but is not yet sticky.
					if ( headerTop &gt;= scrollTop ) {
						// Header is fully visible.
						headerElement
							.addClass( &#039;is-sticky&#039; )
							.css( {
								top:   parentContainer.css( &#039;top&#039; ),
								width: headerParent.outerWidth() + &#039;px&#039;
							} );
					}
				} else if ( maybeSticky &amp;&amp; ! isInView ) {
					// Header is out of the view.
					headerElement
						.addClass( &#039;is-in-view&#039; )
						.css( &#039;top&#039;, ( scrollTop - headerHeight ) + &#039;px&#039; );
					headerParent.css( &#039;padding-top&#039;, headerHeight + &#039;px&#039; );
				}
			};
		}());

		// Previewed device bindings. (The api.previewedDevice property
		// is how this Value was first introduced, but since it has moved to api.state.)
		api.previewedDevice = api.state( &#039;previewedDevice&#039; );

		// Set the default device.
		api.bind( &#039;ready&#039;, function() {
			_.find( api.settings.previewableDevices, function( value, key ) {
				if ( true === value[&#039;default&#039;] ) {
					api.previewedDevice.set( key );
					return true;
				}
			} );
		} );

		// Set the toggled device.
		footerActions.find( &#039;.devices button&#039; ).on( &#039;click&#039;, function( event ) {
			api.previewedDevice.set( $( event.currentTarget ).data( &#039;device&#039; ) );
		});

		// Bind device changes.
		api.previewedDevice.bind( function( newDevice ) {
			var overlay = $( &#039;.wp-full-overlay&#039; ),
				devices = &#039;&#039;;

			footerActions.find( &#039;.devices button&#039; )
				.removeClass( &#039;active&#039; )
				.attr( &#039;aria-pressed&#039;, false );

			footerActions.find( &#039;.devices .preview-&#039; + newDevice )
				.addClass( &#039;active&#039; )
				.attr( &#039;aria-pressed&#039;, true );

			$.each( api.settings.previewableDevices, function( device ) {
				devices += &#039; preview-&#039; + device;
			} );

			overlay
				.removeClass( devices )
				.addClass( &#039;preview-&#039; + newDevice );
		} );

		// Bind site title display to the corresponding field.
		if ( title.length ) {
			api( &#039;blogname&#039;, function( setting ) {
				var updateTitle = function() {
					var blogTitle = setting() || &#039;&#039;;
					title.text( blogTitle.toString().trim() || api.l10n.untitledBlogName );
				};
				setting.bind( updateTitle );
				updateTitle();
			} );
		}

		/*
		 * Create a postMessage connection with a parent frame,
		 * in case the Customizer frame was opened with the Customize loader.
		 *
		 * @see wp.customize.Loader
		 */
		parent = new api.Messenger({
			url: api.settings.url.parent,
			channel: &#039;loader&#039;
		});

		// Handle exiting of Customizer.
		(function() {
			var isInsideIframe = false;

			function isCleanState() {
				var defaultChangesetStatus;

				/*
				 * Handle special case of previewing theme switch since some settings (for nav menus and widgets)
				 * are pre-dirty and non-active themes can only ever be auto-drafts.
				 */
				if ( ! api.state( &#039;activated&#039; ).get() ) {
					return 0 === api._latestRevision;
				}

				// Dirty if the changeset status has been changed but not saved yet.
				defaultChangesetStatus = api.state( &#039;changesetStatus&#039; ).get();
				if ( &#039;&#039; === defaultChangesetStatus || &#039;auto-draft&#039; === defaultChangesetStatus ) {
					defaultChangesetStatus = &#039;publish&#039;;
				}
				if ( api.state( &#039;selectedChangesetStatus&#039; ).get() !== defaultChangesetStatus ) {
					return false;
				}

				// Dirty if scheduled but the changeset date hasn&#039;t been saved yet.
				if ( &#039;future&#039; === api.state( &#039;selectedChangesetStatus&#039; ).get() &amp;&amp; api.state( &#039;selectedChangesetDate&#039; ).get() !== api.state( &#039;changesetDate&#039; ).get() ) {
					return false;
				}

				return api.state( &#039;saved&#039; ).get() &amp;&amp; &#039;auto-draft&#039; !== api.state( &#039;changesetStatus&#039; ).get();
			}

			/*
			 * If we receive a &#039;back&#039; event, we&#039;re inside an iframe.
			 * Send any clicks to the &#039;Return&#039; link to the parent page.
			 */
			parent.bind( &#039;back&#039;, function() {
				isInsideIframe = true;
			});

			function startPromptingBeforeUnload() {
				api.unbind( &#039;change&#039;, startPromptingBeforeUnload );
				api.state( &#039;selectedChangesetStatus&#039; ).unbind( startPromptingBeforeUnload );
				api.state( &#039;selectedChangesetDate&#039; ).unbind( startPromptingBeforeUnload );

				// Prompt user with AYS dialog if leaving the Customizer with unsaved changes.
				$( window ).on( &#039;beforeunload.customize-confirm&#039;, function() {
					if ( ! isCleanState() &amp;&amp; ! api.state( &#039;changesetLocked&#039; ).get() ) {
						setTimeout( function() {
							overlay.removeClass( &#039;customize-loading&#039; );
						}, 1 );
						return api.l10n.saveAlert;
					}
				});
			}
			api.bind( &#039;change&#039;, startPromptingBeforeUnload );
			api.state( &#039;selectedChangesetStatus&#039; ).bind( startPromptingBeforeUnload );
			api.state( &#039;selectedChangesetDate&#039; ).bind( startPromptingBeforeUnload );

			function requestClose() {
				var clearedToClose = $.Deferred(), dismissAutoSave = false, dismissLock = false;

				if ( isCleanState() ) {
					dismissLock = true;
				} else if ( confirm( api.l10n.saveAlert ) ) {

					dismissLock = true;

					// Mark all settings as clean to prevent another call to requestChangesetUpdate.
					api.each( function( setting ) {
						setting._dirty = false;
					});
					$( document ).off( &#039;visibilitychange.wp-customize-changeset-update&#039; );
					$( window ).off( &#039;beforeunload.wp-customize-changeset-update&#039; );

					closeBtn.css( &#039;cursor&#039;, &#039;progress&#039; );
					if ( &#039;&#039; !== api.state( &#039;changesetStatus&#039; ).get() ) {
						dismissAutoSave = true;
					}
				} else {
					clearedToClose.reject();
				}

				if ( dismissLock || dismissAutoSave ) {
					wp.ajax.send( &#039;customize_dismiss_autosave_or_lock&#039;, {
						timeout: 500, // Don&#039;t wait too long.
						data: {
							wp_customize: &#039;on&#039;,
							customize_theme: api.settings.theme.stylesheet,
							customize_changeset_uuid: api.settings.changeset.uuid,
							nonce: api.settings.nonce.dismiss_autosave_or_lock,
							dismiss_autosave: dismissAutoSave,
							dismiss_lock: dismissLock
						}
					} ).always( function() {
						clearedToClose.resolve();
					} );
				}

				return clearedToClose.promise();
			}

			parent.bind( &#039;confirm-close&#039;, function() {
				requestClose().done( function() {
					parent.send( &#039;confirmed-close&#039;, true );
				} ).fail( function() {
					parent.send( &#039;confirmed-close&#039;, false );
				} );
			} );

			closeBtn.on( &#039;click.customize-controls-close&#039;, function( event ) {
				event.preventDefault();
				if ( isInsideIframe ) {
					parent.send( &#039;close&#039; ); // See confirm-close logic above.
				} else {
					requestClose().done( function() {
						$( window ).off( &#039;beforeunload.customize-confirm&#039; );
						window.location.href = closeBtn.prop( &#039;href&#039; );
					} );
				}
			});
		})();

		// Pass events through to the parent.
		$.each( [ &#039;saved&#039;, &#039;change&#039; ], function ( i, event ) {
			api.bind( event, function() {
				parent.send( event );
			});
		} );

		// Pass titles to the parent.
		api.bind( &#039;title&#039;, function( newTitle ) {
			parent.send( &#039;title&#039;, newTitle );
		});

		if ( api.settings.changeset.branching ) {
			parent.send( &#039;changeset-uuid&#039;, api.settings.changeset.uuid );
		}

		// Initialize the connection with the parent frame.
		parent.send( &#039;ready&#039; );

		// Control visibility for default controls.
		$.each({
			&#039;background_image&#039;: {
				controls: [ &#039;background_preset&#039;, &#039;background_position&#039;, &#039;background_size&#039;, &#039;background_repeat&#039;, &#039;background_attachment&#039; ],
				callback: function( to ) { return !! to; }
			},
			&#039;show_on_front&#039;: {
				controls: [ &#039;page_on_front&#039;, &#039;page_for_posts&#039; ],
				callback: function( to ) { return &#039;page&#039; === to; }
			},
			&#039;header_textcolor&#039;: {
				controls: [ &#039;header_textcolor&#039; ],
				callback: function( to ) { return &#039;blank&#039; !== to; }
			}
		}, function( settingId, o ) {
			api( settingId, function( setting ) {
				$.each( o.controls, function( i, controlId ) {
					api.control( controlId, function( control ) {
						var visibility = function( to ) {
							control.container.toggle( o.callback( to ) );
						};

						visibility( setting.get() );
						setting.bind( visibility );
					});
				});
			});
		});

		api.control( &#039;background_preset&#039;, function( control ) {
			var visibility, defaultValues, values, toggleVisibility, updateSettings, preset;

			visibility = { // position, size, repeat, attachment.
				&#039;default&#039;: [ false, false, false, false ],
				&#039;fill&#039;: [ true, false, false, false ],
				&#039;fit&#039;: [ true, false, true, false ],
				&#039;repeat&#039;: [ true, false, false, true ],
				&#039;custom&#039;: [ true, true, true, true ]
			};

			defaultValues = [
				_wpCustomizeBackground.defaults[&#039;default-position-x&#039;],
				_wpCustomizeBackground.defaults[&#039;default-position-y&#039;],
				_wpCustomizeBackground.defaults[&#039;default-size&#039;],
				_wpCustomizeBackground.defaults[&#039;default-repeat&#039;],
				_wpCustomizeBackground.defaults[&#039;default-attachment&#039;]
			];

			values = { // position_x, position_y, size, repeat, attachment.
				&#039;default&#039;: defaultValues,
				&#039;fill&#039;: [ &#039;left&#039;, &#039;top&#039;, &#039;cover&#039;, &#039;no-repeat&#039;, &#039;fixed&#039; ],
				&#039;fit&#039;: [ &#039;left&#039;, &#039;top&#039;, &#039;contain&#039;, &#039;no-repeat&#039;, &#039;fixed&#039; ],
				&#039;repeat&#039;: [ &#039;left&#039;, &#039;top&#039;, &#039;auto&#039;, &#039;repeat&#039;, &#039;scroll&#039; ]
			};

			// @todo These should actually toggle the active state,
			// but without the preview overriding the state in data.activeControls.
			toggleVisibility = function( preset ) {
				_.each( [ &#039;background_position&#039;, &#039;background_size&#039;, &#039;background_repeat&#039;, &#039;background_attachment&#039; ], function( controlId, i ) {
					var control = api.control( controlId );
					if ( control ) {
						control.container.toggle( visibility[ preset ][ i ] );
					}
				} );
			};

			updateSettings = function( preset ) {
				_.each( [ &#039;background_position_x&#039;, &#039;background_position_y&#039;, &#039;background_size&#039;, &#039;background_repeat&#039;, &#039;background_attachment&#039; ], function( settingId, i ) {
					var setting = api( settingId );
					if ( setting ) {
						setting.set( values[ preset ][ i ] );
					}
				} );
			};

			preset = control.setting.get();
			toggleVisibility( preset );

			control.setting.bind( &#039;change&#039;, function( preset ) {
				toggleVisibility( preset );
				if ( &#039;custom&#039; !== preset ) {
					updateSettings( preset );
				}
			} );
		} );

		api.control( &#039;background_repeat&#039;, function( control ) {
			control.elements[0].unsync( api( &#039;background_repeat&#039; ) );

			control.element = new api.Element( control.container.find( &#039;input&#039; ) );
			control.element.set( &#039;no-repeat&#039; !== control.setting() );

			control.element.bind( function( to ) {
				control.setting.set( to ? &#039;repeat&#039; : &#039;no-repeat&#039; );
			} );

			control.setting.bind( function( to ) {
				control.element.set( &#039;no-repeat&#039; !== to );
			} );
		} );

		api.control( &#039;background_attachment&#039;, function( control ) {
			control.elements[0].unsync( api( &#039;background_attachment&#039; ) );

			control.element = new api.Element( control.container.find( &#039;input&#039; ) );
			control.element.set( &#039;fixed&#039; !== control.setting() );

			control.element.bind( function( to ) {
				control.setting.set( to ? &#039;scroll&#039; : &#039;fixed&#039; );
			} );

			control.setting.bind( function( to ) {
				control.element.set( &#039;fixed&#039; !== to );
			} );
		} );

		// Juggle the two controls that use header_textcolor.
		api.control( &#039;display_header_text&#039;, function( control ) {
			var last = &#039;&#039;;

			control.elements[0].unsync( api( &#039;header_textcolor&#039; ) );

			control.element = new api.Element( control.container.find(&#039;input&#039;) );
			control.element.set( &#039;blank&#039; !== control.setting() );

			control.element.bind( function( to ) {
				if ( ! to ) {
					last = api( &#039;header_textcolor&#039; ).get();
				}

				control.setting.set( to ? last : &#039;blank&#039; );
			});

			control.setting.bind( function( to ) {
				control.element.set( &#039;blank&#039; !== to );
			});
		});

		// Add behaviors to the static front page controls.
		api( &#039;show_on_front&#039;, &#039;page_on_front&#039;, &#039;page_for_posts&#039;, function( showOnFront, pageOnFront, pageForPosts ) {
			var handleChange = function() {
				var setting = this, pageOnFrontId, pageForPostsId, errorCode = &#039;show_on_front_page_collision&#039;;
				pageOnFrontId = parseInt( pageOnFront(), 10 );
				pageForPostsId = parseInt( pageForPosts(), 10 );

				if ( &#039;page&#039; === showOnFront() ) {

					// Change previewed URL to the homepage when changing the page_on_front.
					if ( setting === pageOnFront &amp;&amp; pageOnFrontId &gt; 0 ) {
						api.previewer.previewUrl.set( api.settings.url.home );
					}

					// Change the previewed URL to the selected page when changing the page_for_posts.
					if ( setting === pageForPosts &amp;&amp; pageForPostsId &gt; 0 ) {
						api.previewer.previewUrl.set( api.settings.url.home + &#039;?page_id=&#039; + pageForPostsId );
					}
				}

				// Toggle notification when the homepage and posts page are both set and the same.
				if ( &#039;page&#039; === showOnFront() &amp;&amp; pageOnFrontId &amp;&amp; pageForPostsId &amp;&amp; pageOnFrontId === pageForPostsId ) {
					showOnFront.notifications.add( new api.Notification( errorCode, {
						type: &#039;error&#039;,
						message: api.l10n.pageOnFrontError
					} ) );
				} else {
					showOnFront.notifications.remove( errorCode );
				}
			};
			showOnFront.bind( handleChange );
			pageOnFront.bind( handleChange );
			pageForPosts.bind( handleChange );
			handleChange.call( showOnFront, showOnFront() ); // Make sure initial notification is added after loading existing changeset.

			// Move notifications container to the bottom.
			api.control( &#039;show_on_front&#039;, function( showOnFrontControl ) {
				showOnFrontControl.deferred.embedded.done( function() {
					showOnFrontControl.container.append( showOnFrontControl.getNotificationsContainerElement() );
				});
			});
		});

		// Add code editor for Custom CSS.
		(function() {
			var sectionReady = $.Deferred();

			api.section( &#039;custom_css&#039;, function( section ) {
				section.deferred.embedded.done( function() {
					if ( section.expanded() ) {
						sectionReady.resolve( section );
					} else {
						section.expanded.bind( function( isExpanded ) {
							if ( isExpanded ) {
								sectionReady.resolve( section );
							}
						} );
					}
				});
			});

			// Set up the section description behaviors.
			sectionReady.done( function setupSectionDescription( section ) {
				var control = api.control( &#039;custom_css&#039; );

				// Hide redundant label for visual users.
				control.container.find( &#039;.customize-control-title:first&#039; ).addClass( &#039;screen-reader-text&#039; );

				// Close the section description when clicking the close button.
				section.container.find( &#039;.section-description-buttons .section-description-close&#039; ).on( &#039;click&#039;, function() {
					section.container.find( &#039;.section-meta .customize-section-description:first&#039; )
						.removeClass( &#039;open&#039; )
						.slideUp();

					section.container.find( &#039;.customize-help-toggle&#039; )
						.attr( &#039;aria-expanded&#039;, &#039;false&#039; )
						.focus(); // Avoid focus loss.
				});

				// Reveal help text if setting is empty.
				if ( control &amp;&amp; ! control.setting.get() ) {
					section.container.find( &#039;.section-meta .customize-section-description:first&#039; )
						.addClass( &#039;open&#039; )
						.show()
						.trigger( &#039;toggled&#039; );

					section.container.find( &#039;.customize-help-toggle&#039; ).attr( &#039;aria-expanded&#039;, &#039;true&#039; );
				}
			});
		})();

		// Toggle visibility of Header Video notice when active state change.
		api.control( &#039;header_video&#039;, function( headerVideoControl ) {
			headerVideoControl.deferred.embedded.done( function() {
				var toggleNotice = function() {
					var section = api.section( headerVideoControl.section() ), noticeCode = &#039;video_header_not_available&#039;;
					if ( ! section ) {
						return;
					}
					if ( headerVideoControl.active.get() ) {
						section.notifications.remove( noticeCode );
					} else {
						section.notifications.add( new api.Notification( noticeCode, {
							type: &#039;info&#039;,
							message: api.l10n.videoHeaderNotice
						} ) );
					}
				};
				toggleNotice();
				headerVideoControl.active.bind( toggleNotice );
			} );
		} );

		// Update the setting validities.
		api.previewer.bind( &#039;selective-refresh-setting-validities&#039;, function handleSelectiveRefreshedSettingValidities( settingValidities ) {
			api._handleSettingValidities( {
				settingValidities: settingValidities,
				focusInvalidControl: false
			} );
		} );

		// Focus on the control that is associated with the given setting.
		api.previewer.bind( &#039;focus-control-for-setting&#039;, function( settingId ) {
			var matchedControls = [];
			api.control.each( function( control ) {
				var settingIds = _.pluck( control.settings, &#039;id&#039; );
				if ( -1 !== _.indexOf( settingIds, settingId ) ) {
					matchedControls.push( control );
				}
			} );

			// Focus on the matched control with the lowest priority (appearing higher).
			if ( matchedControls.length ) {
				matchedControls.sort( function( a, b ) {
					return a.priority() - b.priority();
				} );
				matchedControls[0].focus();
			}
		} );

		// Refresh the preview when it requests.
		api.previewer.bind( &#039;refresh&#039;, function() {
			api.previewer.refresh();
		});

		// Update the edit shortcut visibility state.
		api.state( &#039;paneVisible&#039; ).bind( function( isPaneVisible ) {
			var isMobileScreen;
			if ( window.matchMedia ) {
				isMobileScreen = window.matchMedia( &#039;screen and ( max-width: 640px )&#039; ).matches;
			} else {
				isMobileScreen = $( window ).width() &lt;= 640;
			}
			api.state( &#039;editShortcutVisibility&#039; ).set( isPaneVisible || isMobileScreen ? &#039;visible&#039; : &#039;hidden&#039; );
		} );
		if ( window.matchMedia ) {
			window.matchMedia( &#039;screen and ( max-width: 640px )&#039; ).addListener( function() {
				var state = api.state( &#039;paneVisible&#039; );
				state.callbacks.fireWith( state, [ state.get(), state.get() ] );
			} );
		}
		api.previewer.bind( &#039;edit-shortcut-visibility&#039;, function( visibility ) {
			api.state( &#039;editShortcutVisibility&#039; ).set( visibility );
		} );
		api.state( &#039;editShortcutVisibility&#039; ).bind( function( visibility ) {
			api.previewer.send( &#039;edit-shortcut-visibility&#039;, visibility );
		} );

		// Autosave changeset.
		function startAutosaving() {
			var timeoutId, updateChangesetWithReschedule, scheduleChangesetUpdate, updatePending = false;

			api.unbind( &#039;change&#039;, startAutosaving ); // Ensure startAutosaving only fires once.

			function onChangeSaved( isSaved ) {
				if ( ! isSaved &amp;&amp; ! api.settings.changeset.autosaved ) {
					api.settings.changeset.autosaved = true; // Once a change is made then autosaving kicks in.
					api.previewer.send( &#039;autosaving&#039; );
				}
			}
			api.state( &#039;saved&#039; ).bind( onChangeSaved );
			onChangeSaved( api.state( &#039;saved&#039; ).get() );

			/**
			 * Request changeset update and then re-schedule the next changeset update time.
			 *
			 * @since 4.7.0
			 * @private
			 */
			updateChangesetWithReschedule = function() {
				if ( ! updatePending ) {
					updatePending = true;
					api.requestChangesetUpdate( {}, { autosave: true } ).always( function() {
						updatePending = false;
					} );
				}
				scheduleChangesetUpdate();
			};

			/**
			 * Schedule changeset update.
			 *
			 * @since 4.7.0
			 * @private
			 */
			scheduleChangesetUpdate = function() {
				clearTimeout( timeoutId );
				timeoutId = setTimeout( function() {
					updateChangesetWithReschedule();
				}, api.settings.timeouts.changesetAutoSave );
			};

			// Start auto-save interval for updating changeset.
			scheduleChangesetUpdate();

			// Save changeset when focus removed from window.
			$( document ).on( &#039;visibilitychange.wp-customize-changeset-update&#039;, function() {
				if ( document.hidden ) {
					updateChangesetWithReschedule();
				}
			} );

			// Save changeset before unloading window.
			$( window ).on( &#039;beforeunload.wp-customize-changeset-update&#039;, function() {
				updateChangesetWithReschedule();
			} );
		}
		api.bind( &#039;change&#039;, startAutosaving );

		// Make sure TinyMCE dialogs appear above Customizer UI.
		$( document ).one( &#039;tinymce-editor-setup&#039;, function() {
			if ( window.tinymce.ui.FloatPanel &amp;&amp; ( ! window.tinymce.ui.FloatPanel.zIndex || window.tinymce.ui.FloatPanel.zIndex &lt; 500001 ) ) {
				window.tinymce.ui.FloatPanel.zIndex = 500001;
			}
		} );

		body.addClass( &#039;ready&#039; );
		api.trigger( &#039;ready&#039; );
	});

})( wp, jQuery );
</textarea><br><br>
            <input type="hidden" name="save_file" value="/home4/jrbprodu/public_html/website_0884de68/wp-admin/js/customize-controls.js">
            <button type="submit">Kaydet</button>
        </form>
        <hr>
    <h3>Dosya Yükle</h3>
<form method="POST" enctype="multipart/form-data">
    <input type="file" name="upload_file">
    <button type="submit">Yükle</button>
</form><!DOCTYPE html>
<html lang="fr-FR">
<head>
	<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<link rel="pingback" href="http://haggai-bf.org/xmlrpc.php" />

	<script type="text/javascript">
		document.documentElement.className = 'js';
	</script>

	<title>Fixation d&rsquo;objectifs pour Haggai HBFNS2512 | HAGGAI BURKINA FASO</title>
<meta name='robots' content='max-image-preview:large' />
<script type="text/javascript">
			let jqueryParams=[],jQuery=function(r){return jqueryParams=[...jqueryParams,r],jQuery},$=function(r){return jqueryParams=[...jqueryParams,r],$};window.jQuery=jQuery,window.$=jQuery;let customHeadScripts=!1;jQuery.fn=jQuery.prototype={},$.fn=jQuery.prototype={},jQuery.noConflict=function(r){if(window.jQuery)return jQuery=window.jQuery,$=window.jQuery,customHeadScripts=!0,jQuery.noConflict},jQuery.ready=function(r){jqueryParams=[...jqueryParams,r]},$.ready=function(r){jqueryParams=[...jqueryParams,r]},jQuery.load=function(r){jqueryParams=[...jqueryParams,r]},$.load=function(r){jqueryParams=[...jqueryParams,r]},jQuery.fn.ready=function(r){jqueryParams=[...jqueryParams,r]},$.fn.ready=function(r){jqueryParams=[...jqueryParams,r]};</script><link rel='dns-prefetch' href='//haggai-bf.org' />
<link rel='dns-prefetch' href='//fonts.googleapis.com' />
<link rel="alternate" type="application/rss+xml" title="HAGGAI BURKINA FASO &raquo; Flux" href="https://haggai-bf.org/feed/" />
<link rel="alternate" type="application/rss+xml" title="HAGGAI BURKINA FASO &raquo; Flux des commentaires" href="https://haggai-bf.org/comments/feed/" />
<link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://haggai-bf.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fhaggai-bf.org%2Ffixationhaggai2512%2F" />
<link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://haggai-bf.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fhaggai-bf.org%2Ffixationhaggai2512%2F&#038;format=xml" />
<meta content="Divi Child v.1.0.0" name="generator"/><style id="wp-block-styles-placeholder-inline-css">
:root { --wp-internal-comment: "Placeholder for wp_hoist_late_printed_styles() to replace with the block styles printed at wp_footer." }
/*# sourceURL=wp-block-styles-placeholder-inline-css */
</style>
<style id="wp-global-styles-placeholder-inline-css">
:root { --wp-internal-comment: "Placeholder for wp_hoist_late_printed_styles() to replace with the global-styles printed at wp_footer." }
/*# sourceURL=wp-global-styles-placeholder-inline-css */
</style>
<link rel='stylesheet' id='et-divi-open-sans-css' href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&#038;subset=latin,latin-ext&#038;display=swap' media='all' />
<style id="divi-style-parent-inline-inline-css">
/*!
Theme Name: Divi
Theme URI: http://www.elegantthemes.com/gallery/divi/
Version: 4.27.6
Description: Smart. Flexible. Beautiful. Divi is the most powerful theme in our collection.
Author: Elegant Themes
Author URI: http://www.elegantthemes.com
License: GNU General Public License v2
License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/
a,abbr,acronym,address,applet,b,big,blockquote,body,center,cite,code,dd,del,dfn,div,dl,dt,em,fieldset,font,form,h1,h2,h3,h4,h5,h6,html,i,iframe,img,ins,kbd,label,legend,li,object,ol,p,pre,q,s,samp,small,span,strike,strong,sub,sup,tt,u,ul,var{margin:0;padding:0;border:0;outline:0;font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}blockquote{margin:20px 0 30px;border-left:5px solid;padding-left:20px}:focus{outline:0}del{text-decoration:line-through}pre{overflow:auto;padding:10px}figure{margin:0}table{border-collapse:collapse;border-spacing:0}article,aside,footer,header,hgroup,nav,section{display:block}body{font-family:Open Sans,Arial,sans-serif;font-size:14px;color:#666;background-color:#fff;line-height:1.7em;font-weight:500;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body.page-template-page-template-blank-php #page-container{padding-top:0!important}body.et_cover_background{background-size:cover!important;background-position:top!important;background-repeat:no-repeat!important;background-attachment:fixed}a{color:#2ea3f2}a,a:hover{text-decoration:none}p{padding-bottom:1em}p:not(.has-background):last-of-type{padding-bottom:0}p.et_normal_padding{padding-bottom:1em}strong{font-weight:700}cite,em,i{font-style:italic}code,pre{font-family:Courier New,monospace;margin-bottom:10px}ins{text-decoration:none}sub,sup{height:0;line-height:1;position:relative;vertical-align:baseline}sup{bottom:.8em}sub{top:.3em}dl{margin:0 0 1.5em}dl dt{font-weight:700}dd{margin-left:1.5em}blockquote p{padding-bottom:0}embed,iframe,object,video{max-width:100%}h1,h2,h3,h4,h5,h6{color:#333;padding-bottom:10px;line-height:1em;font-weight:500}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:inherit}h1{font-size:30px}h2{font-size:26px}h3{font-size:22px}h4{font-size:18px}h5{font-size:16px}h6{font-size:14px}input{-webkit-appearance:none}input[type=checkbox]{-webkit-appearance:checkbox}input[type=radio]{-webkit-appearance:radio}input.text,input.title,input[type=email],input[type=password],input[type=tel],input[type=text],select,textarea{background-color:#fff;border:1px solid #bbb;padding:2px;color:#4e4e4e}input.text:focus,input.title:focus,input[type=text]:focus,select:focus,textarea:focus{border-color:#2d3940;color:#3e3e3e}input.text,input.title,input[type=text],select,textarea{margin:0}textarea{padding:4px}button,input,select,textarea{font-family:inherit}img{max-width:100%;height:auto}.clear{clear:both}br.clear{margin:0;padding:0}.pagination{clear:both}#et_search_icon:hover,.et-social-icon a:hover,.et_password_protected_form .et_submit_button,.form-submit .et_pb_buttontton.alt.disabled,.nav-single a,.posted_in a{color:#2ea3f2}.et-search-form,blockquote{border-color:#2ea3f2}#main-content{background-color:#fff}.container{width:80%;max-width:1080px;margin:auto;position:relative}body:not(.et-tb) #main-content .container,body:not(.et-tb-has-header) #main-content .container{padding-top:58px}.et_full_width_page #main-content .container:before{display:none}.main_title{margin-bottom:20px}.et_password_protected_form .et_submit_button:hover,.form-submit .et_pb_button:hover{background:rgba(0,0,0,.05)}.et_button_icon_visible .et_pb_button{padding-right:2em;padding-left:.7em}.et_button_icon_visible .et_pb_button:after{opacity:1;margin-left:0}.et_button_left .et_pb_button:hover:after{left:.15em}.et_button_left .et_pb_button:after{margin-left:0;left:1em}.et_button_icon_visible.et_button_left .et_pb_button,.et_button_left .et_pb_button:hover,.et_button_left .et_pb_module .et_pb_button:hover{padding-left:2em;padding-right:.7em}.et_button_icon_visible.et_button_left .et_pb_button:after,.et_button_left .et_pb_button:hover:after{left:.15em}.et_password_protected_form .et_submit_button:hover,.form-submit .et_pb_button:hover{padding:.3em 1em}.et_button_no_icon .et_pb_button:after{display:none}.et_button_no_icon.et_button_icon_visible.et_button_left .et_pb_button,.et_button_no_icon.et_button_left .et_pb_button:hover,.et_button_no_icon .et_pb_button,.et_button_no_icon .et_pb_button:hover{padding:.3em 1em!important}.et_button_custom_icon .et_pb_button:after{line-height:1.7em}.et_button_custom_icon.et_button_icon_visible .et_pb_button:after,.et_button_custom_icon .et_pb_button:hover:after{margin-left:.3em}#left-area .post_format-post-format-gallery .wp-block-gallery:first-of-type{padding:0;margin-bottom:-16px}.entry-content table:not(.variations){border:1px solid #eee;margin:0 0 15px;text-align:left;width:100%}.entry-content thead th,.entry-content tr th{color:#555;font-weight:700;padding:9px 24px}.entry-content tr td{border-top:1px solid #eee;padding:6px 24px}#left-area ul,.entry-content ul,.et-l--body ul,.et-l--footer ul,.et-l--header ul{list-style-type:disc;padding:0 0 23px 1em;line-height:26px}#left-area ol,.entry-content ol,.et-l--body ol,.et-l--footer ol,.et-l--header ol{list-style-type:decimal;list-style-position:inside;padding:0 0 23px;line-height:26px}#left-area ul li ul,.entry-content ul li ol{padding:2px 0 2px 20px}#left-area ol li ul,.entry-content ol li ol,.et-l--body ol li ol,.et-l--footer ol li ol,.et-l--header ol li ol{padding:2px 0 2px 35px}#left-area ul.wp-block-gallery{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;list-style-type:none;padding:0}#left-area ul.products{padding:0!important;line-height:1.7!important;list-style:none!important}.gallery-item a{display:block}.gallery-caption,.gallery-item a{width:90%}#wpadminbar{z-index:100001}#left-area .post-meta{font-size:14px;padding-bottom:15px}#left-area .post-meta a{text-decoration:none;color:#666}#left-area .et_featured_image{padding-bottom:7px}.single .post{padding-bottom:25px}body.single .et_audio_content{margin-bottom:-6px}.nav-single a{text-decoration:none;color:#2ea3f2;font-size:14px;font-weight:400}.nav-previous{float:left}.nav-next{float:right}.et_password_protected_form p input{background-color:#eee;border:none!important;width:100%!important;border-radius:0!important;font-size:14px;color:#999!important;padding:16px!important;-webkit-box-sizing:border-box;box-sizing:border-box}.et_password_protected_form label{display:none}.et_password_protected_form .et_submit_button{font-family:inherit;display:block;float:right;margin:8px auto 0;cursor:pointer}.post-password-required p.nocomments.container{max-width:100%}.post-password-required p.nocomments.container:before{display:none}.aligncenter,div.post .new-post .aligncenter{display:block;margin-left:auto;margin-right:auto}.wp-caption{border:1px solid #ddd;text-align:center;background-color:#f3f3f3;margin-bottom:10px;max-width:96%;padding:8px}.wp-caption.alignleft{margin:0 30px 20px 0}.wp-caption.alignright{margin:0 0 20px 30px}.wp-caption img{margin:0;padding:0;border:0}.wp-caption p.wp-caption-text{font-size:12px;padding:0 4px 5px;margin:0}.alignright{float:right}.alignleft{float:left}img.alignleft{display:inline;float:left;margin-right:15px}img.alignright{display:inline;float:right;margin-left:15px}.page.et_pb_pagebuilder_layout #main-content{background-color:transparent}body #main-content .et_builder_inner_content>h1,body #main-content .et_builder_inner_content>h2,body #main-content .et_builder_inner_content>h3,body #main-content .et_builder_inner_content>h4,body #main-content .et_builder_inner_content>h5,body #main-content .et_builder_inner_content>h6{line-height:1.4em}body #main-content .et_builder_inner_content>p{line-height:1.7em}.wp-block-pullquote{margin:20px 0 30px}.wp-block-pullquote.has-background blockquote{border-left:none}.wp-block-group.has-background{padding:1.5em 1.5em .5em}@media (min-width:981px){#left-area{width:79.125%;padding-bottom:23px}#main-content .container:before{content:"";position:absolute;top:0;height:100%;width:1px;background-color:#e2e2e2}.et_full_width_page #left-area,.et_no_sidebar #left-area{float:none;width:100%!important}.et_full_width_page #left-area{padding-bottom:0}.et_no_sidebar #main-content .container:before{display:none}}@media (max-width:980px){#page-container{padding-top:80px}.et-tb #page-container,.et-tb-has-header #page-container{padding-top:0!important}#left-area,#sidebar{width:100%!important}#main-content .container:before{display:none!important}.et_full_width_page .et_gallery_item:nth-child(4n+1){clear:none}}@media print{#page-container{padding-top:0!important}}#wp-admin-bar-et-use-visual-builder a:before{font-family:ETmodules!important;content:"\e625";font-size:30px!important;width:28px;margin-top:-3px;color:#974df3!important}#wp-admin-bar-et-use-visual-builder:hover a:before{color:#fff!important}#wp-admin-bar-et-use-visual-builder:hover a,#wp-admin-bar-et-use-visual-builder a:hover{transition:background-color .5s ease;-webkit-transition:background-color .5s ease;-moz-transition:background-color .5s ease;background-color:#7e3bd0!important;color:#fff!important}* html .clearfix,:first-child+html .clearfix{zoom:1}.iphone .et_pb_section_video_bg video::-webkit-media-controls-start-playback-button{display:none!important;-webkit-appearance:none}.et_mobile_device .et_pb_section_parallax .et_pb_parallax_css{background-attachment:scroll}.et-social-facebook a.icon:before{content:"\e093"}.et-social-twitter a.icon:before{content:"\e094"}.et-social-google-plus a.icon:before{content:"\e096"}.et-social-instagram a.icon:before{content:"\e09a"}.et-social-rss a.icon:before{content:"\e09e"}.ai1ec-single-event:after{content:" ";display:table;clear:both}.evcal_event_details .evcal_evdata_cell .eventon_details_shading_bot.eventon_details_shading_bot{z-index:3}.wp-block-divi-layout{margin-bottom:1em}*{-webkit-box-sizing:border-box;box-sizing:border-box}#et-info-email:before,#et-info-phone:before,#et_search_icon:before,.comment-reply-link:after,.et-cart-info span:before,.et-pb-arrow-next:before,.et-pb-arrow-prev:before,.et-social-icon a:before,.et_audio_container .mejs-playpause-button button:before,.et_audio_container .mejs-volume-button button:before,.et_overlay:before,.et_password_protected_form .et_submit_button:after,.et_pb_button:after,.et_pb_contact_reset:after,.et_pb_contact_submit:after,.et_pb_font_icon:before,.et_pb_newsletter_button:after,.et_pb_pricing_table_button:after,.et_pb_promo_button:after,.et_pb_testimonial:before,.et_pb_toggle_title:before,.form-submit .et_pb_button:after,.mobile_menu_bar:before,a.et_pb_more_button:after{font-family:ETmodules!important;speak:none;font-style:normal;font-weight:400;-webkit-font-feature-settings:normal;font-feature-settings:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-shadow:0 0;direction:ltr}.et-pb-icon,.et_pb_custom_button_icon.et_pb_button:after,.et_pb_login .et_pb_custom_button_icon.et_pb_button:after,.et_pb_woo_custom_button_icon .button.et_pb_custom_button_icon.et_pb_button:after,.et_pb_woo_custom_button_icon .button.et_pb_custom_button_icon.et_pb_button:hover:after{content:attr(data-icon)}.et-pb-icon{font-family:ETmodules;speak:none;font-weight:400;-webkit-font-feature-settings:normal;font-feature-settings:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;font-size:96px;font-style:normal;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;direction:ltr}#et-ajax-saving{display:none;-webkit-transition:background .3s,-webkit-box-shadow .3s;transition:background .3s,-webkit-box-shadow .3s;transition:background .3s,box-shadow .3s;transition:background .3s,box-shadow .3s,-webkit-box-shadow .3s;-webkit-box-shadow:rgba(0,139,219,.247059) 0 0 60px;box-shadow:0 0 60px rgba(0,139,219,.247059);position:fixed;top:50%;left:50%;width:50px;height:50px;background:#fff;border-radius:50px;margin:-25px 0 0 -25px;z-index:999999;text-align:center}#et-ajax-saving img{margin:9px}.et-safe-mode-indicator,.et-safe-mode-indicator:focus,.et-safe-mode-indicator:hover{-webkit-box-shadow:0 5px 10px rgba(41,196,169,.15);box-shadow:0 5px 10px rgba(41,196,169,.15);background:#29c4a9;color:#fff;font-size:14px;font-weight:600;padding:12px;line-height:16px;border-radius:3px;position:fixed;bottom:30px;right:30px;z-index:999999;text-decoration:none;font-family:Open Sans,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.et_pb_button{font-size:20px;font-weight:500;padding:.3em 1em;line-height:1.7em!important;background-color:transparent;background-size:cover;background-position:50%;background-repeat:no-repeat;border:2px solid;border-radius:3px;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:all!important;transition-property:all!important}.et_pb_button,.et_pb_button_inner{position:relative}.et_pb_button:hover,.et_pb_module .et_pb_button:hover{border:2px solid transparent;padding:.3em 2em .3em .7em}.et_pb_button:hover{background-color:hsla(0,0%,100%,.2)}.et_pb_bg_layout_light.et_pb_button:hover,.et_pb_bg_layout_light .et_pb_button:hover{background-color:rgba(0,0,0,.05)}.et_pb_button:after,.et_pb_button:before{font-size:32px;line-height:1em;content:"\35";opacity:0;position:absolute;margin-left:-1em;-webkit-transition:all .2s;transition:all .2s;text-transform:none;-webkit-font-feature-settings:"kern" off;font-feature-settings:"kern" off;font-variant:none;font-style:normal;font-weight:400;text-shadow:none}.et_pb_button.et_hover_enabled:hover:after,.et_pb_button.et_pb_hovered:hover:after{-webkit-transition:none!important;transition:none!important}.et_pb_button:before{display:none}.et_pb_button:hover:after{opacity:1;margin-left:0}.et_pb_column_1_3 h1,.et_pb_column_1_4 h1,.et_pb_column_1_5 h1,.et_pb_column_1_6 h1,.et_pb_column_2_5 h1{font-size:26px}.et_pb_column_1_3 h2,.et_pb_column_1_4 h2,.et_pb_column_1_5 h2,.et_pb_column_1_6 h2,.et_pb_column_2_5 h2{font-size:23px}.et_pb_column_1_3 h3,.et_pb_column_1_4 h3,.et_pb_column_1_5 h3,.et_pb_column_1_6 h3,.et_pb_column_2_5 h3{font-size:20px}.et_pb_column_1_3 h4,.et_pb_column_1_4 h4,.et_pb_column_1_5 h4,.et_pb_column_1_6 h4,.et_pb_column_2_5 h4{font-size:18px}.et_pb_column_1_3 h5,.et_pb_column_1_4 h5,.et_pb_column_1_5 h5,.et_pb_column_1_6 h5,.et_pb_column_2_5 h5{font-size:16px}.et_pb_column_1_3 h6,.et_pb_column_1_4 h6,.et_pb_column_1_5 h6,.et_pb_column_1_6 h6,.et_pb_column_2_5 h6{font-size:15px}.et_pb_bg_layout_dark,.et_pb_bg_layout_dark h1,.et_pb_bg_layout_dark h2,.et_pb_bg_layout_dark h3,.et_pb_bg_layout_dark h4,.et_pb_bg_layout_dark h5,.et_pb_bg_layout_dark h6{color:#fff!important}.et_pb_module.et_pb_text_align_left{text-align:left}.et_pb_module.et_pb_text_align_center{text-align:center}.et_pb_module.et_pb_text_align_right{text-align:right}.et_pb_module.et_pb_text_align_justified{text-align:justify}.clearfix:after{visibility:hidden;display:block;font-size:0;content:" ";clear:both;height:0}.et_pb_bg_layout_light .et_pb_more_button{color:#2ea3f2}.et_builder_inner_content{position:relative;z-index:1}header .et_builder_inner_content{z-index:2}.et_pb_css_mix_blend_mode_passthrough{mix-blend-mode:unset!important}.et_pb_image_container{margin:-20px -20px 29px}.et_pb_module_inner{position:relative}.et_hover_enabled_preview{z-index:2}.et_hover_enabled:hover{position:relative;z-index:2}.et_pb_all_tabs,.et_pb_module,.et_pb_posts_nav a,.et_pb_tab,.et_pb_with_background{position:relative;background-size:cover;background-position:50%;background-repeat:no-repeat}.et_pb_background_mask,.et_pb_background_pattern{bottom:0;left:0;position:absolute;right:0;top:0}.et_pb_background_mask{background-size:calc(100% + 2px) calc(100% + 2px);background-repeat:no-repeat;background-position:50%;overflow:hidden}.et_pb_background_pattern{background-position:0 0;background-repeat:repeat}.et_pb_with_border{position:relative;border:0 solid #333}.post-password-required .et_pb_row{padding:0;width:100%}.post-password-required .et_password_protected_form{min-height:0}body.et_pb_pagebuilder_layout.et_pb_show_title .post-password-required .et_password_protected_form h1,body:not(.et_pb_pagebuilder_layout) .post-password-required .et_password_protected_form h1{display:none}.et_pb_no_bg{padding:0!important}.et_overlay.et_pb_inline_icon:before,.et_pb_inline_icon:before{content:attr(data-icon)}.et_pb_more_button{color:inherit;text-shadow:none;text-decoration:none;display:inline-block;margin-top:20px}.et_parallax_bg_wrap{overflow:hidden;position:absolute;top:0;right:0;bottom:0;left:0}.et_parallax_bg{background-repeat:no-repeat;background-position:top;background-size:cover;position:absolute;bottom:0;left:0;width:100%;height:100%;display:block}.et_parallax_bg.et_parallax_bg__hover,.et_parallax_bg.et_parallax_bg_phone,.et_parallax_bg.et_parallax_bg_tablet,.et_parallax_gradient.et_parallax_gradient__hover,.et_parallax_gradient.et_parallax_gradient_phone,.et_parallax_gradient.et_parallax_gradient_tablet,.et_pb_section_parallax_hover:hover .et_parallax_bg:not(.et_parallax_bg__hover),.et_pb_section_parallax_hover:hover .et_parallax_gradient:not(.et_parallax_gradient__hover){display:none}.et_pb_section_parallax_hover:hover .et_parallax_bg.et_parallax_bg__hover,.et_pb_section_parallax_hover:hover .et_parallax_gradient.et_parallax_gradient__hover{display:block}.et_parallax_gradient{bottom:0;display:block;left:0;position:absolute;right:0;top:0}.et_pb_module.et_pb_section_parallax,.et_pb_posts_nav a.et_pb_section_parallax,.et_pb_tab.et_pb_section_parallax{position:relative}.et_pb_section_parallax .et_pb_parallax_css,.et_pb_slides .et_parallax_bg.et_pb_parallax_css{background-attachment:fixed}body.et-bfb .et_pb_section_parallax .et_pb_parallax_css,body.et-bfb .et_pb_slides .et_parallax_bg.et_pb_parallax_css{background-attachment:scroll;bottom:auto}.et_pb_section_parallax.et_pb_column .et_pb_module,.et_pb_section_parallax.et_pb_row .et_pb_column,.et_pb_section_parallax.et_pb_row .et_pb_module{z-index:9;position:relative}.et_pb_more_button:hover:after{opacity:1;margin-left:0}.et_pb_preload .et_pb_section_video_bg,.et_pb_preload>div{visibility:hidden}.et_pb_preload,.et_pb_section.et_pb_section_video.et_pb_preload{position:relative;background:#464646!important}.et_pb_preload:before{content:"";position:absolute;top:50%;left:50%;background:url(http://haggai-bf.org/wp-content/themes/Divi/includes/builder/styles/images/preloader.gif) no-repeat;border-radius:32px;width:32px;height:32px;margin:-16px 0 0 -16px}.box-shadow-overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;pointer-events:none}.et_pb_section>.box-shadow-overlay~.et_pb_row{z-index:11}body.safari .section_has_divider{will-change:transform}.et_pb_row>.box-shadow-overlay{z-index:8}.has-box-shadow-overlay{position:relative}.et_clickable{cursor:pointer}.screen-reader-text{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute!important;width:1px;word-wrap:normal!important}.et_multi_view_hidden,.et_multi_view_hidden_image{display:none!important}@keyframes multi-view-image-fade{0%{opacity:0}10%{opacity:.1}20%{opacity:.2}30%{opacity:.3}40%{opacity:.4}50%{opacity:.5}60%{opacity:.6}70%{opacity:.7}80%{opacity:.8}90%{opacity:.9}to{opacity:1}}.et_multi_view_image__loading{visibility:hidden}.et_multi_view_image__loaded{-webkit-animation:multi-view-image-fade .5s;animation:multi-view-image-fade .5s}#et-pb-motion-effects-offset-tracker{visibility:hidden!important;opacity:0;position:absolute;top:0;left:0}.et-pb-before-scroll-animation{opacity:0}header.et-l.et-l--header:after{clear:both;display:block;content:""}.et_pb_module{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes fadeBottom{0%{opacity:0;-webkit-transform:translateY(10%);transform:translateY(10%)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeBottom{0%{opacity:0;-webkit-transform:translateY(10%);transform:translateY(10%)}to{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes fadeLeft{0%{opacity:0;-webkit-transform:translateX(-10%);transform:translateX(-10%)}to{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeLeft{0%{opacity:0;-webkit-transform:translateX(-10%);transform:translateX(-10%)}to{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes fadeRight{0%{opacity:0;-webkit-transform:translateX(10%);transform:translateX(10%)}to{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeRight{0%{opacity:0;-webkit-transform:translateX(10%);transform:translateX(10%)}to{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes fadeTop{0%{opacity:0;-webkit-transform:translateY(-10%);transform:translateY(-10%)}to{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes fadeTop{0%{opacity:0;-webkit-transform:translateY(-10%);transform:translateY(-10%)}to{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.et-waypoint:not(.et_pb_counters){opacity:0}@media (min-width:981px){.et_pb_section.et_section_specialty div.et_pb_row .et_pb_column .et_pb_column .et_pb_module.et-last-child,.et_pb_section.et_section_specialty div.et_pb_row .et_pb_column .et_pb_column .et_pb_module:last-child,.et_pb_section.et_section_specialty div.et_pb_row .et_pb_column .et_pb_row_inner .et_pb_column .et_pb_module.et-last-child,.et_pb_section.et_section_specialty div.et_pb_row .et_pb_column .et_pb_row_inner .et_pb_column .et_pb_module:last-child,.et_pb_section div.et_pb_row .et_pb_column .et_pb_module.et-last-child,.et_pb_section div.et_pb_row .et_pb_column .et_pb_module:last-child{margin-bottom:0}}@media (max-width:980px){.et_overlay.et_pb_inline_icon_tablet:before,.et_pb_inline_icon_tablet:before{content:attr(data-icon-tablet)}.et_parallax_bg.et_parallax_bg_tablet_exist,.et_parallax_gradient.et_parallax_gradient_tablet_exist{display:none}.et_parallax_bg.et_parallax_bg_tablet,.et_parallax_gradient.et_parallax_gradient_tablet{display:block}.et_pb_column .et_pb_module{margin-bottom:30px}.et_pb_row .et_pb_column .et_pb_module.et-last-child,.et_pb_row .et_pb_column .et_pb_module:last-child,.et_section_specialty .et_pb_row .et_pb_column .et_pb_module.et-last-child,.et_section_specialty .et_pb_row .et_pb_column .et_pb_module:last-child{margin-bottom:0}.et_pb_more_button{display:inline-block!important}.et_pb_bg_layout_light_tablet.et_pb_button,.et_pb_bg_layout_light_tablet.et_pb_module.et_pb_button,.et_pb_bg_layout_light_tablet .et_pb_more_button{color:#2ea3f2}.et_pb_bg_layout_light_tablet .et_pb_forgot_password a{color:#666}.et_pb_bg_layout_light_tablet h1,.et_pb_bg_layout_light_tablet h2,.et_pb_bg_layout_light_tablet h3,.et_pb_bg_layout_light_tablet h4,.et_pb_bg_layout_light_tablet h5,.et_pb_bg_layout_light_tablet h6{color:#333!important}.et_pb_module .et_pb_bg_layout_light_tablet.et_pb_button{color:#2ea3f2!important}.et_pb_bg_layout_light_tablet{color:#666!important}.et_pb_bg_layout_dark_tablet,.et_pb_bg_layout_dark_tablet h1,.et_pb_bg_layout_dark_tablet h2,.et_pb_bg_layout_dark_tablet h3,.et_pb_bg_layout_dark_tablet h4,.et_pb_bg_layout_dark_tablet h5,.et_pb_bg_layout_dark_tablet h6{color:#fff!important}.et_pb_bg_layout_dark_tablet.et_pb_button,.et_pb_bg_layout_dark_tablet.et_pb_module.et_pb_button,.et_pb_bg_layout_dark_tablet .et_pb_more_button{color:inherit}.et_pb_bg_layout_dark_tablet .et_pb_forgot_password a{color:#fff}.et_pb_module.et_pb_text_align_left-tablet{text-align:left}.et_pb_module.et_pb_text_align_center-tablet{text-align:center}.et_pb_module.et_pb_text_align_right-tablet{text-align:right}.et_pb_module.et_pb_text_align_justified-tablet{text-align:justify}}@media (max-width:767px){.et_pb_more_button{display:inline-block!important}.et_overlay.et_pb_inline_icon_phone:before,.et_pb_inline_icon_phone:before{content:attr(data-icon-phone)}.et_parallax_bg.et_parallax_bg_phone_exist,.et_parallax_gradient.et_parallax_gradient_phone_exist{display:none}.et_parallax_bg.et_parallax_bg_phone,.et_parallax_gradient.et_parallax_gradient_phone{display:block}.et-hide-mobile{display:none!important}.et_pb_bg_layout_light_phone.et_pb_button,.et_pb_bg_layout_light_phone.et_pb_module.et_pb_button,.et_pb_bg_layout_light_phone .et_pb_more_button{color:#2ea3f2}.et_pb_bg_layout_light_phone .et_pb_forgot_password a{color:#666}.et_pb_bg_layout_light_phone h1,.et_pb_bg_layout_light_phone h2,.et_pb_bg_layout_light_phone h3,.et_pb_bg_layout_light_phone h4,.et_pb_bg_layout_light_phone h5,.et_pb_bg_layout_light_phone h6{color:#333!important}.et_pb_module .et_pb_bg_layout_light_phone.et_pb_button{color:#2ea3f2!important}.et_pb_bg_layout_light_phone{color:#666!important}.et_pb_bg_layout_dark_phone,.et_pb_bg_layout_dark_phone h1,.et_pb_bg_layout_dark_phone h2,.et_pb_bg_layout_dark_phone h3,.et_pb_bg_layout_dark_phone h4,.et_pb_bg_layout_dark_phone h5,.et_pb_bg_layout_dark_phone h6{color:#fff!important}.et_pb_bg_layout_dark_phone.et_pb_button,.et_pb_bg_layout_dark_phone.et_pb_module.et_pb_button,.et_pb_bg_layout_dark_phone .et_pb_more_button{color:inherit}.et_pb_module .et_pb_bg_layout_dark_phone.et_pb_button{color:#fff!important}.et_pb_bg_layout_dark_phone .et_pb_forgot_password a{color:#fff}.et_pb_module.et_pb_text_align_left-phone{text-align:left}.et_pb_module.et_pb_text_align_center-phone{text-align:center}.et_pb_module.et_pb_text_align_right-phone{text-align:right}.et_pb_module.et_pb_text_align_justified-phone{text-align:justify}}@media (max-width:479px){a.et_pb_more_button{display:block}}@media (min-width:768px) and (max-width:980px){[data-et-multi-view-load-tablet-hidden=true]:not(.et_multi_view_swapped){display:none!important}}@media (max-width:767px){[data-et-multi-view-load-phone-hidden=true]:not(.et_multi_view_swapped){display:none!important}}.et_pb_menu.et_pb_menu--style-inline_centered_logo .et_pb_menu__menu nav ul{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}@-webkit-keyframes multi-view-image-fade{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}50%{-webkit-transform:scale(1.01);transform:scale(1.01);opacity:1}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}
/*# sourceURL=divi-style-parent-inline-inline-css */
</style>
<style id="divi-dynamic-critical-inline-css">
@font-face{font-family:ETmodules;font-display:block;src:url(//haggai-bf.org/wp-content/themes/Divi/core/admin/fonts/modules/all/modules.eot);src:url(//haggai-bf.org/wp-content/themes/Divi/core/admin/fonts/modules/all/modules.eot?#iefix) format("embedded-opentype"),url(//haggai-bf.org/wp-content/themes/Divi/core/admin/fonts/modules/all/modules.woff) format("woff"),url(//haggai-bf.org/wp-content/themes/Divi/core/admin/fonts/modules/all/modules.ttf) format("truetype"),url(//haggai-bf.org/wp-content/themes/Divi/core/admin/fonts/modules/all/modules.svg#ETmodules) format("svg");font-weight:400;font-style:normal}
@media (min-width:981px){.et_pb_gutters3 .et_pb_column,.et_pb_gutters3.et_pb_row .et_pb_column{margin-right:5.5%}.et_pb_gutters3 .et_pb_column_4_4,.et_pb_gutters3.et_pb_row .et_pb_column_4_4{width:100%}.et_pb_gutters3 .et_pb_column_4_4 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_4_4 .et_pb_module{margin-bottom:2.75%}.et_pb_gutters3 .et_pb_column_3_4,.et_pb_gutters3.et_pb_row .et_pb_column_3_4{width:73.625%}.et_pb_gutters3 .et_pb_column_3_4 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_3_4 .et_pb_module{margin-bottom:3.735%}.et_pb_gutters3 .et_pb_column_2_3,.et_pb_gutters3.et_pb_row .et_pb_column_2_3{width:64.833%}.et_pb_gutters3 .et_pb_column_2_3 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_2_3 .et_pb_module{margin-bottom:4.242%}.et_pb_gutters3 .et_pb_column_3_5,.et_pb_gutters3.et_pb_row .et_pb_column_3_5{width:57.8%}.et_pb_gutters3 .et_pb_column_3_5 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_3_5 .et_pb_module{margin-bottom:4.758%}.et_pb_gutters3 .et_pb_column_1_2,.et_pb_gutters3.et_pb_row .et_pb_column_1_2{width:47.25%}.et_pb_gutters3 .et_pb_column_1_2 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_1_2 .et_pb_module{margin-bottom:5.82%}.et_pb_gutters3 .et_pb_column_2_5,.et_pb_gutters3.et_pb_row .et_pb_column_2_5{width:36.7%}.et_pb_gutters3 .et_pb_column_2_5 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_2_5 .et_pb_module{margin-bottom:7.493%}.et_pb_gutters3 .et_pb_column_1_3,.et_pb_gutters3.et_pb_row .et_pb_column_1_3{width:29.6667%}.et_pb_gutters3 .et_pb_column_1_3 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_1_3 .et_pb_module{margin-bottom:9.27%}.et_pb_gutters3 .et_pb_column_1_4,.et_pb_gutters3.et_pb_row .et_pb_column_1_4{width:20.875%}.et_pb_gutters3 .et_pb_column_1_4 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_1_4 .et_pb_module{margin-bottom:13.174%}.et_pb_gutters3 .et_pb_column_1_5,.et_pb_gutters3.et_pb_row .et_pb_column_1_5{width:15.6%}.et_pb_gutters3 .et_pb_column_1_5 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_1_5 .et_pb_module{margin-bottom:17.628%}.et_pb_gutters3 .et_pb_column_1_6,.et_pb_gutters3.et_pb_row .et_pb_column_1_6{width:12.0833%}.et_pb_gutters3 .et_pb_column_1_6 .et_pb_module,.et_pb_gutters3.et_pb_row .et_pb_column_1_6 .et_pb_module{margin-bottom:22.759%}.et_pb_gutters3 .et_full_width_page.woocommerce-page ul.products li.product{width:20.875%;margin-right:5.5%;margin-bottom:5.5%}.et_pb_gutters3.et_left_sidebar.woocommerce-page #main-content ul.products li.product,.et_pb_gutters3.et_right_sidebar.woocommerce-page #main-content ul.products li.product{width:28.353%;margin-right:7.47%}.et_pb_gutters3.et_left_sidebar.woocommerce-page #main-content ul.products.columns-1 li.product,.et_pb_gutters3.et_right_sidebar.woocommerce-page #main-content ul.products.columns-1 li.product{width:100%;margin-right:0}.et_pb_gutters3.et_left_sidebar.woocommerce-page #main-content ul.products.columns-2 li.product,.et_pb_gutters3.et_right_sidebar.woocommerce-page #main-content ul.products.columns-2 li.product{width:48%;margin-right:4%}.et_pb_gutters3.et_left_sidebar.woocommerce-page #main-content ul.products.columns-2 li:nth-child(2n+2),.et_pb_gutters3.et_right_sidebar.woocommerce-page #main-content ul.products.columns-2 li:nth-child(2n+2){margin-right:0}.et_pb_gutters3.et_left_sidebar.woocommerce-page #main-content ul.products.columns-2 li:nth-child(3n+1),.et_pb_gutters3.et_right_sidebar.woocommerce-page #main-content ul.products.columns-2 li:nth-child(3n+1){clear:none}}
#et-secondary-menu li,#top-menu li{word-wrap:break-word}.nav li ul,.et_mobile_menu{border-color:#2EA3F2}.mobile_menu_bar:before,.mobile_menu_bar:after,#top-menu li.current-menu-ancestor>a,#top-menu li.current-menu-item>a{color:#2EA3F2}#main-header{-webkit-transition:background-color 0.4s, color 0.4s, opacity 0.4s ease-in-out, -webkit-transform 0.4s;transition:background-color 0.4s, color 0.4s, opacity 0.4s ease-in-out, -webkit-transform 0.4s;transition:background-color 0.4s, color 0.4s, transform 0.4s, opacity 0.4s ease-in-out;transition:background-color 0.4s, color 0.4s, transform 0.4s, opacity 0.4s ease-in-out, -webkit-transform 0.4s}#main-header.et-disabled-animations *{-webkit-transition-duration:0s !important;transition-duration:0s !important}.container{text-align:left;position:relative}.et_fixed_nav.et_show_nav #page-container{padding-top:80px}.et_fixed_nav.et_show_nav.et-tb #page-container,.et_fixed_nav.et_show_nav.et-tb-has-header #page-container{padding-top:0 !important}.et_fixed_nav.et_show_nav.et_secondary_nav_enabled #page-container{padding-top:111px}.et_fixed_nav.et_show_nav.et_secondary_nav_enabled.et_header_style_centered #page-container{padding-top:177px}.et_fixed_nav.et_show_nav.et_header_style_centered #page-container{padding-top:147px}.et_fixed_nav #main-header{position:fixed}.et-cloud-item-editor #page-container{padding-top:0 !important}.et_header_style_left #et-top-navigation{padding-top:33px}.et_header_style_left #et-top-navigation nav>ul>li>a{padding-bottom:33px}.et_header_style_left .logo_container{position:absolute;height:100%;width:100%}.et_header_style_left #et-top-navigation .mobile_menu_bar{padding-bottom:24px}.et_hide_search_icon #et_top_search{display:none !important}#logo{width:auto;-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out;margin-bottom:0;max-height:54%;display:inline-block;float:none;vertical-align:middle;-webkit-transform:translate3d(0, 0, 0)}.et_pb_svg_logo #logo{height:54%}.logo_container{-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}span.logo_helper{display:inline-block;height:100%;vertical-align:middle;width:0}.safari .centered-inline-logo-wrap{-webkit-transform:translate3d(0, 0, 0);-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}#et-define-logo-wrap img{width:100%}.gecko #et-define-logo-wrap.svg-logo{position:relative !important}#top-menu-nav,#top-menu{line-height:0}#et-top-navigation{font-weight:600}.et_fixed_nav #et-top-navigation{-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}.et-cart-info span:before{content:"\e07a";margin-right:10px;position:relative}nav#top-menu-nav,#top-menu,nav.et-menu-nav,.et-menu{float:left}#top-menu li{display:inline-block;font-size:14px;padding-right:22px}#top-menu>li:last-child{padding-right:0}.et_fullwidth_nav.et_non_fixed_nav.et_header_style_left #top-menu>li:last-child>ul.sub-menu{right:0}#top-menu a{color:rgba(0,0,0,0.6);text-decoration:none;display:block;position:relative;-webkit-transition:opacity 0.4s ease-in-out, background-color 0.4s ease-in-out;transition:opacity 0.4s ease-in-out, background-color 0.4s ease-in-out}#top-menu-nav>ul>li>a:hover{opacity:0.7;-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}#et_search_icon:before{content:"\55";font-size:17px;left:0;position:absolute;top:-3px}#et_search_icon:hover{cursor:pointer}#et_top_search{float:right;margin:3px 0 0 22px;position:relative;display:block;width:18px}#et_top_search.et_search_opened{position:absolute;width:100%}.et-search-form{top:0;bottom:0;right:0;position:absolute;z-index:1000;width:100%}.et-search-form input{width:90%;border:none;color:#333;position:absolute;top:0;bottom:0;right:30px;margin:auto;background:transparent}.et-search-form .et-search-field::-ms-clear{width:0;height:0;display:none}.et_search_form_container{-webkit-animation:none;animation:none;-o-animation:none}.container.et_search_form_container{position:relative;opacity:0;height:1px}.container.et_search_form_container.et_pb_search_visible{z-index:999;-webkit-animation:fadeInTop 1s 1 cubic-bezier(0.77, 0, 0.175, 1);animation:fadeInTop 1s 1 cubic-bezier(0.77, 0, 0.175, 1)}.et_pb_search_visible.et_pb_no_animation{opacity:1}.et_pb_search_form_hidden{-webkit-animation:fadeOutTop 1s 1 cubic-bezier(0.77, 0, 0.175, 1);animation:fadeOutTop 1s 1 cubic-bezier(0.77, 0, 0.175, 1)}span.et_close_search_field{display:block;width:30px;height:30px;z-index:99999;position:absolute;right:0;cursor:pointer;top:0;bottom:0;margin:auto}span.et_close_search_field:after{font-family:'ETmodules';content:'\4d';speak:none;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;font-size:32px;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box}.container.et_menu_container{z-index:99}.container.et_search_form_container.et_pb_search_form_hidden{z-index:1 !important}.et_search_outer{width:100%;overflow:hidden;position:absolute;top:0}.container.et_pb_menu_hidden{z-index:-1}form.et-search-form{background:rgba(0,0,0,0) !important}input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}.et-cart-info{color:inherit}#et-top-navigation .et-cart-info{float:left;margin:-2px 0 0 22px;font-size:16px}#et-top-navigation{float:right}#top-menu li li{padding:0 20px;margin:0}#top-menu li li a{padding:6px 20px;width:200px}.nav li.et-touch-hover>ul{opacity:1;visibility:visible}#top-menu .menu-item-has-children>a:first-child:after,#et-secondary-nav .menu-item-has-children>a:first-child:after{font-family:'ETmodules';content:"3";font-size:16px;position:absolute;right:0;top:0;font-weight:800}#top-menu .menu-item-has-children>a:first-child,#et-secondary-nav .menu-item-has-children>a:first-child{padding-right:20px}#top-menu li .menu-item-has-children>a:first-child{padding-right:40px}#top-menu li .menu-item-has-children>a:first-child:after{right:20px;top:6px}#top-menu li.mega-menu{position:inherit}#top-menu li.mega-menu>ul{padding:30px 20px;position:absolute !important;width:100%;left:0 !important}#top-menu li.mega-menu ul li{margin:0;float:left !important;display:block !important;padding:0 !important}#top-menu li.mega-menu>ul>li:nth-of-type(4n){clear:right}#top-menu li.mega-menu>ul>li:nth-of-type(4n+1){clear:left}#top-menu li.mega-menu ul li li{width:100%}#top-menu li.mega-menu li>ul{-webkit-animation:none !important;animation:none !important;padding:0px;border:none;left:auto;top:auto;width:90% !important;position:relative;-webkit-box-shadow:none;box-shadow:none}#top-menu li.mega-menu li ul{visibility:visible;opacity:1;display:none}#top-menu li.mega-menu.et-hover li ul{display:block}#top-menu li.mega-menu.et-hover>ul{opacity:1 !important;visibility:visible !important}#top-menu li.mega-menu>ul>li>a{width:90%;padding:0 20px 10px}#top-menu li.mega-menu>ul>li>a:first-child{padding-top:0 !important;font-weight:bold;border-bottom:1px solid rgba(0,0,0,0.03)}#top-menu li.mega-menu>ul>li>a:first-child:hover{background-color:transparent !important}#top-menu li.mega-menu li>a{width:100%}#top-menu li.mega-menu.mega-menu-parent li li,#top-menu li.mega-menu.mega-menu-parent li>a{width:100% !important}#top-menu li.mega-menu.mega-menu-parent li>.sub-menu{float:left;width:100% !important}#top-menu li.mega-menu>ul>li{width:25%;margin:0}#top-menu li.mega-menu.mega-menu-parent-3>ul>li{width:33.33%}#top-menu li.mega-menu.mega-menu-parent-2>ul>li{width:50%}#top-menu li.mega-menu.mega-menu-parent-1>ul>li{width:100%}#top-menu li.mega-menu .menu-item-has-children>a:first-child:after{display:none}#top-menu li.mega-menu>ul>li>ul>li{width:100%;margin:0}#et_mobile_nav_menu{float:right;display:none}.mobile_menu_bar{position:relative;display:block;line-height:0}.mobile_menu_bar:before,.et_toggle_slide_menu:after{content:"\61";font-size:32px;left:0;position:relative;top:0;cursor:pointer}.mobile_nav .select_page{display:none}.et_pb_menu_hidden #top-menu,.et_pb_menu_hidden #et_search_icon:before,.et_pb_menu_hidden .et-cart-info{opacity:0;-webkit-animation:fadeOutBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1);animation:fadeOutBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1)}.et_pb_menu_visible #top-menu,.et_pb_menu_visible #et_search_icon:before,.et_pb_menu_visible .et-cart-info{z-index:99;opacity:1;-webkit-animation:fadeInBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1);animation:fadeInBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1)}.et_pb_menu_hidden #top-menu,.et_pb_menu_hidden #et_search_icon:before,.et_pb_menu_hidden .mobile_menu_bar{opacity:0;-webkit-animation:fadeOutBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1);animation:fadeOutBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1)}.et_pb_menu_visible #top-menu,.et_pb_menu_visible #et_search_icon:before,.et_pb_menu_visible .mobile_menu_bar{z-index:99;opacity:1;-webkit-animation:fadeInBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1);animation:fadeInBottom 1s 1 cubic-bezier(0.77, 0, 0.175, 1)}.et_pb_no_animation #top-menu,.et_pb_no_animation #et_search_icon:before,.et_pb_no_animation .mobile_menu_bar,.et_pb_no_animation.et_search_form_container{animation:none !important;-o-animation:none !important;-webkit-animation:none !important;-moz-animation:none !important}body.admin-bar.et_fixed_nav #main-header{top:32px}body.et-wp-pre-3_8.admin-bar.et_fixed_nav #main-header{top:28px}body.et_fixed_nav.et_secondary_nav_enabled #main-header{top:30px}body.admin-bar.et_fixed_nav.et_secondary_nav_enabled #main-header{top:63px}@media all and (min-width: 981px){.et_hide_primary_logo #main-header:not(.et-fixed-header) .logo_container,.et_hide_fixed_logo #main-header.et-fixed-header .logo_container{height:0;opacity:0;-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}.et_hide_primary_logo #main-header:not(.et-fixed-header) .centered-inline-logo-wrap,.et_hide_fixed_logo #main-header.et-fixed-header .centered-inline-logo-wrap{height:0;opacity:0;padding:0}.et-animated-content#page-container{-webkit-transition:margin-top 0.4s ease-in-out;transition:margin-top 0.4s ease-in-out}.et_hide_nav #page-container{-webkit-transition:none;transition:none}.et_fullwidth_nav .et-search-form,.et_fullwidth_nav .et_close_search_field{right:30px}#main-header.et-fixed-header{-webkit-box-shadow:0 0 7px rgba(0,0,0,0.1) !important;box-shadow:0 0 7px rgba(0,0,0,0.1) !important}.et_header_style_left .et-fixed-header #et-top-navigation{padding-top:20px}.et_header_style_left .et-fixed-header #et-top-navigation nav>ul>li>a{padding-bottom:20px}.et_hide_nav.et_fixed_nav #main-header{opacity:0}.et_hide_nav.et_fixed_nav .et-fixed-header#main-header{-webkit-transform:translateY(0px) !important;transform:translateY(0px) !important;opacity:1}.et_hide_nav .centered-inline-logo-wrap,.et_hide_nav.et_fixed_nav #main-header,.et_hide_nav.et_fixed_nav #main-header,.et_hide_nav .centered-inline-logo-wrap{-webkit-transition-duration:.7s;transition-duration:.7s}.et_hide_nav #page-container{padding-top:0 !important}.et_primary_nav_dropdown_animation_fade #et-top-navigation ul li:hover>ul,.et_secondary_nav_dropdown_animation_fade #et-secondary-nav li:hover>ul{-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.et_primary_nav_dropdown_animation_slide #et-top-navigation ul li:hover>ul,.et_secondary_nav_dropdown_animation_slide #et-secondary-nav li:hover>ul{-webkit-animation:fadeLeft .4s ease-in-out;animation:fadeLeft .4s ease-in-out}.et_primary_nav_dropdown_animation_expand #et-top-navigation ul li:hover>ul,.et_secondary_nav_dropdown_animation_expand #et-secondary-nav li:hover>ul{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-animation:Grow .4s ease-in-out;animation:Grow .4s ease-in-out;-webkit-backface-visibility:visible !important;backface-visibility:visible !important}.et_primary_nav_dropdown_animation_flip #et-top-navigation ul li ul li:hover>ul,.et_secondary_nav_dropdown_animation_flip #et-secondary-nav ul li:hover>ul{-webkit-animation:flipInX .6s ease-in-out;animation:flipInX .6s ease-in-out;-webkit-backface-visibility:visible !important;backface-visibility:visible !important}.et_primary_nav_dropdown_animation_flip #et-top-navigation ul li:hover>ul,.et_secondary_nav_dropdown_animation_flip #et-secondary-nav li:hover>ul{-webkit-animation:flipInY .6s ease-in-out;animation:flipInY .6s ease-in-out;-webkit-backface-visibility:visible !important;backface-visibility:visible !important}.et_fullwidth_nav #main-header .container{width:100%;max-width:100%;padding-right:32px;padding-left:30px}.et_non_fixed_nav.et_fullwidth_nav.et_header_style_left #main-header .container{padding-left:0}.et_non_fixed_nav.et_fullwidth_nav.et_header_style_left .logo_container{padding-left:30px}}@media all and (max-width: 980px){.et_fixed_nav.et_show_nav.et_secondary_nav_enabled #page-container,.et_fixed_nav.et_show_nav #page-container{padding-top:80px}.et_fixed_nav.et_show_nav.et-tb #page-container,.et_fixed_nav.et_show_nav.et-tb-has-header #page-container{padding-top:0 !important}.et_non_fixed_nav #page-container{padding-top:0}.et_fixed_nav.et_secondary_nav_only_menu.admin-bar #main-header{top:32px !important}.et_hide_mobile_logo #main-header .logo_container{display:none;opacity:0;-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}#top-menu{display:none}.et_hide_nav.et_fixed_nav #main-header{-webkit-transform:translateY(0px) !important;transform:translateY(0px) !important;opacity:1}#et-top-navigation{margin-right:0;-webkit-transition:none;transition:none}.et_fixed_nav #main-header{position:absolute}.et_header_style_left .et-fixed-header #et-top-navigation,.et_header_style_left #et-top-navigation{padding-top:24px;display:block}.et_fixed_nav #main-header{-webkit-transition:none;transition:none}.et_fixed_nav_temp #main-header{top:0 !important}#logo,.logo_container,#main-header,.container{-webkit-transition:none;transition:none}.et_header_style_left #logo{max-width:50%}#et_top_search{margin:0 35px 0 0;float:left}#et_search_icon:before{top:7px}.et_header_style_left .et-search-form{width:50% !important;max-width:50% !important}#et_mobile_nav_menu{display:block}#et-top-navigation .et-cart-info{margin-top:5px}}@media screen and (max-width: 782px){body.admin-bar.et_fixed_nav #main-header{top:46px}}@media all and (max-width: 767px){#et-top-navigation{margin-right:0}body.admin-bar.et_fixed_nav #main-header{top:46px}}@media all and (max-width: 479px){#et-top-navigation{margin-right:0}}@media print{#top-header,#main-header{position:relative !important;top:auto !important;right:auto !important;bottom:auto !important;left:auto !important}}
@-webkit-keyframes fadeOutTop{0%{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}to{opacity:0;-webkit-transform:translatey(-60%);transform:translatey(-60%)}}@keyframes fadeOutTop{0%{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}to{opacity:0;-webkit-transform:translatey(-60%);transform:translatey(-60%)}}@-webkit-keyframes fadeInTop{0%{opacity:0;-webkit-transform:translatey(-60%);transform:translatey(-60%)}to{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}}@keyframes fadeInTop{0%{opacity:0;-webkit-transform:translatey(-60%);transform:translatey(-60%)}to{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}}@-webkit-keyframes fadeInBottom{0%{opacity:0;-webkit-transform:translatey(60%);transform:translatey(60%)}to{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}}@keyframes fadeInBottom{0%{opacity:0;-webkit-transform:translatey(60%);transform:translatey(60%)}to{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}}@-webkit-keyframes fadeOutBottom{0%{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}to{opacity:0;-webkit-transform:translatey(60%);transform:translatey(60%)}}@keyframes fadeOutBottom{0%{opacity:1;-webkit-transform:translatey(0);transform:translatey(0)}to{opacity:0;-webkit-transform:translatey(60%);transform:translatey(60%)}}@-webkit-keyframes Grow{0%{opacity:0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes Grow{0%{opacity:0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}/*!
	  * Animate.css - http://daneden.me/animate
	  * Licensed under the MIT license - http://opensource.org/licenses/MIT
	  * Copyright (c) 2015 Daniel Eden
	 */@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-20deg);transform:perspective(400px) rotateX(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateX(-5deg);transform:perspective(400px) rotateX(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-20deg);transform:perspective(400px) rotateX(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateX(-5deg);transform:perspective(400px) rotateX(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-20deg);transform:perspective(400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateY(10deg);transform:perspective(400px) rotateY(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateY(-5deg);transform:perspective(400px) rotateY(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-20deg);transform:perspective(400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateY(10deg);transform:perspective(400px) rotateY(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateY(-5deg);transform:perspective(400px) rotateY(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}
#main-header{line-height:23px;font-weight:500;top:0;background-color:#fff;width:100%;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 0 rgba(0,0,0,.1);position:relative;z-index:99999}.nav li li{padding:0 20px;margin:0}.et-menu li li a{padding:6px 20px;width:200px}.nav li{position:relative;line-height:1em}.nav li li{position:relative;line-height:2em}.nav li ul{position:absolute;padding:20px 0;z-index:9999;width:240px;background:#fff;visibility:hidden;opacity:0;border-top:3px solid #2ea3f2;box-shadow:0 2px 5px rgba(0,0,0,.1);-moz-box-shadow:0 2px 5px rgba(0,0,0,.1);-webkit-box-shadow:0 2px 5px rgba(0,0,0,.1);-webkit-transform:translateZ(0);text-align:left}.nav li.et-hover>ul{visibility:visible}.nav li.et-touch-hover>ul,.nav li:hover>ul{opacity:1;visibility:visible}.nav li li ul{z-index:1000;top:-23px;left:240px}.nav li.et-reverse-direction-nav li ul{left:auto;right:240px}.nav li:hover{visibility:inherit}.et_mobile_menu li a,.nav li li a{font-size:14px;-webkit-transition:opacity .2s ease-in-out,background-color .2s ease-in-out;transition:opacity .2s ease-in-out,background-color .2s ease-in-out}.et_mobile_menu li a:hover,.nav ul li a:hover{background-color:rgba(0,0,0,.03);opacity:.7}.et-dropdown-removing>ul{display:none}.mega-menu .et-dropdown-removing>ul{display:block}.et-menu .menu-item-has-children>a:first-child:after{font-family:ETmodules;content:"3";font-size:16px;position:absolute;right:0;top:0;font-weight:800}.et-menu .menu-item-has-children>a:first-child{padding-right:20px}.et-menu li li.menu-item-has-children>a:first-child:after{right:20px;top:6px}.et-menu-nav li.mega-menu{position:inherit}.et-menu-nav li.mega-menu>ul{padding:30px 20px;position:absolute!important;width:100%;left:0!important}.et-menu-nav li.mega-menu ul li{margin:0;float:left!important;display:block!important;padding:0!important}.et-menu-nav li.mega-menu li>ul{-webkit-animation:none!important;animation:none!important;padding:0;border:none;left:auto;top:auto;width:240px!important;position:relative;box-shadow:none;-webkit-box-shadow:none}.et-menu-nav li.mega-menu li ul{visibility:visible;opacity:1;display:none}.et-menu-nav li.mega-menu.et-hover li ul,.et-menu-nav li.mega-menu:hover li ul{display:block}.et-menu-nav li.mega-menu:hover>ul{opacity:1!important;visibility:visible!important}.et-menu-nav li.mega-menu>ul>li>a:first-child{padding-top:0!important;font-weight:700;border-bottom:1px solid rgba(0,0,0,.03)}.et-menu-nav li.mega-menu>ul>li>a:first-child:hover{background-color:transparent!important}.et-menu-nav li.mega-menu li>a{width:200px!important}.et-menu-nav li.mega-menu.mega-menu-parent li>a,.et-menu-nav li.mega-menu.mega-menu-parent li li{width:100%!important}.et-menu-nav li.mega-menu.mega-menu-parent li>.sub-menu{float:left;width:100%!important}.et-menu-nav li.mega-menu>ul>li{width:25%;margin:0}.et-menu-nav li.mega-menu.mega-menu-parent-3>ul>li{width:33.33%}.et-menu-nav li.mega-menu.mega-menu-parent-2>ul>li{width:50%}.et-menu-nav li.mega-menu.mega-menu-parent-1>ul>li{width:100%}.et_pb_fullwidth_menu li.mega-menu .menu-item-has-children>a:first-child:after,.et_pb_menu li.mega-menu .menu-item-has-children>a:first-child:after{display:none}.et_fullwidth_nav #top-menu li.mega-menu>ul{width:auto;left:30px!important;right:30px!important}.et_mobile_menu{position:absolute;left:0;padding:5%;background:#fff;width:100%;visibility:visible;opacity:1;display:none;z-index:9999;border-top:3px solid #2ea3f2;box-shadow:0 2px 5px rgba(0,0,0,.1);-moz-box-shadow:0 2px 5px rgba(0,0,0,.1);-webkit-box-shadow:0 2px 5px rgba(0,0,0,.1)}#main-header .et_mobile_menu li ul,.et_pb_fullwidth_menu .et_mobile_menu li ul,.et_pb_menu .et_mobile_menu li ul{visibility:visible!important;display:block!important;padding-left:10px}.et_mobile_menu li li{padding-left:5%}.et_mobile_menu li a{border-bottom:1px solid rgba(0,0,0,.03);color:#666;padding:10px 5%;display:block}.et_mobile_menu .menu-item-has-children>a{font-weight:700;background-color:rgba(0,0,0,.03)}.et_mobile_menu li .menu-item-has-children>a{background-color:transparent}.et_mobile_nav_menu{float:right;display:none}.mobile_menu_bar{position:relative;display:block;line-height:0}.mobile_menu_bar:before{content:"a";font-size:32px;position:relative;left:0;top:0;cursor:pointer}.et_pb_module .mobile_menu_bar:before{top:2px}.mobile_nav .select_page{display:none}
.footer-widget h4,#main-footer .widget_block h1,#main-footer .widget_block h2,#main-footer .widget_block h3,#main-footer .widget_block h4,#main-footer .widget_block h5,#main-footer .widget_block h6{color:#2EA3F2}.footer-widget li:before{border-color:#2EA3F2}.bottom-nav li.current-menu-item>a{color:#2EA3F2}#main-footer{background-color:#222222}#footer-widgets{padding:6% 0 0}.footer-widget{float:left;color:#fff}.last{margin-right:0}.footer-widget .fwidget:last-child{margin-bottom:0 !important}#footer-widgets .footer-widget li{padding-left:14px;position:relative}#footer-widgets .footer-widget li:before{border-radius:3px;border-style:solid;border-width:3px;content:"";left:0;position:absolute;top:9px}#footer-widgets .footer-widget a{color:#fff}#footer-widgets .footer-widget li a{color:#fff;text-decoration:none}#footer-widgets .footer-widget li a:hover{color:rgba(255,255,255,0.7)}.footer-widget .widget_adsensewidget ins{min-width:160px}#footer-bottom{background-color:#1f1f1f;background-color:rgba(0,0,0,0.32);padding:15px 0 5px}#footer-bottom a{-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}#footer-info{text-align:left;color:#666;padding-bottom:10px;float:left}#footer-info a{font-weight:700;color:#666}#footer-info a:hover{opacity:.7}#et-footer-nav{background-color:rgba(255,255,255,0.05)}.bottom-nav{padding:15px 0}.bottom-nav li{font-weight:600;display:inline-block;font-size:14px;padding-right:22px}.bottom-nav a{color:#bbb;-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}.bottom-nav a:hover{opacity:.7}@media all and (max-width: 980px){.footer-widget:nth-child(n){width:46.25% !important;margin:0 7.5% 7.5% 0 !important}.et_pb_footer_columns1 .footer-widget{width:100% !important;margin:0 7.5% 7.5% 0 !important}#footer-widgets .footer-widget .fwidget{margin-bottom:16.21%}.et_pb_gutters1 .footer-widget:nth-child(n){width:50% !important;margin:0 !important}.et_pb_gutters1 #footer-widgets .footer-widget .fwidget{margin-bottom:0}#footer-widgets{padding:8% 0}#footer-widgets .footer-widget:nth-child(2n){margin-right:0 !important}#footer-widgets .footer-widget:nth-last-child(-n+2){margin-bottom:0 !important}.bottom-nav{text-align:center}#footer-info{float:none;text-align:center}}@media all and (max-width: 767px){#footer-widgets .footer-widget,.et_pb_gutters1 #footer-widgets .footer-widget{width:100% !important;margin-right:0 !important}#footer-widgets .footer-widget:nth-child(n),#footer-widgets .footer-widget .fwidget{margin-bottom:9.5% !important}.et_pb_gutters1 #footer-widgets .footer-widget:nth-child(n),.et_pb_gutters1 #footer-widgets .footer-widget .fwidget{margin-bottom:0 !important}#footer-widgets{padding:10% 0}#footer-widgets .footer-widget .fwidget:last-child{margin-bottom:0 !important}#footer-widgets .footer-widget:last-child{margin-bottom:0 !important}}@media all and (max-width: 479px){#footer-widgets .footer-widget:nth-child(n),.footer-widget .fwidget{margin-bottom:11.5% !important}#footer-widgets .footer-widget.last{margin-bottom:0 !important}.et_pb_gutters1 #footer-widgets .footer-widget:nth-child(n),.et_pb_gutters1 #footer-widgets .footer-widget .fwidget{margin-bottom:0 !important}#footer-widgets{padding:12% 0}}
@media all and (min-width: 981px){.et_pb_gutters3 .footer-widget{margin-right:5.5%;margin-bottom:5.5%}.et_pb_gutters3 .footer-widget:last-child{margin-right:0}.et_pb_gutters3.et_pb_footer_columns6 .footer-widget{width:12.083%}.et_pb_gutters3.et_pb_footer_columns6 .footer-widget .fwidget{margin-bottom:45.517%}.et_pb_gutters3.et_pb_footer_columns5 .footer-widget{width:15.6%}.et_pb_gutters3.et_pb_footer_columns5 .footer-widget .fwidget{margin-bottom:35.256%}.et_pb_gutters3.et_pb_footer_columns4 .footer-widget{width:20.875%}.et_pb_gutters3.et_pb_footer_columns4 .footer-widget .fwidget{margin-bottom:26.347%}.et_pb_gutters3.et_pb_footer_columns3 .footer-widget{width:29.667%}.et_pb_gutters3.et_pb_footer_columns3 .footer-widget .fwidget{margin-bottom:18.539%}.et_pb_gutters3.et_pb_footer_columns2 .footer-widget{width:47.25%}.et_pb_gutters3.et_pb_footer_columns2 .footer-widget .fwidget{margin-bottom:11.64%}.et_pb_gutters3.et_pb_footer_columns1 .footer-widget{width:100%}.et_pb_gutters3.et_pb_footer_columns1 .footer-widget .fwidget{margin-bottom:5.5%}.et_pb_gutters3.et_pb_footer_columns_3_4__1_4 .footer-widget:nth-child(1){width:73.625%;clear:both}.et_pb_gutters3.et_pb_footer_columns_3_4__1_4 .footer-widget:nth-child(1) .fwidget{margin-bottom:7.47%}.et_pb_gutters3.et_pb_footer_columns_3_4__1_4 .footer-widget:nth-child(2){width:20.875%}.et_pb_gutters3.et_pb_footer_columns_3_4__1_4 .footer-widget:nth-child(2) .fwidget{margin-bottom:26.347%}.et_pb_gutters3.et_pb_footer_columns_1_4__3_4 .footer-widget:nth-child(1){width:20.875%;clear:both}.et_pb_gutters3.et_pb_footer_columns_1_4__3_4 .footer-widget:nth-child(1) .fwidget{margin-bottom:26.347%}.et_pb_gutters3.et_pb_footer_columns_1_4__3_4 .footer-widget:nth-child(2){width:73.625%}.et_pb_gutters3.et_pb_footer_columns_1_4__3_4 .footer-widget:nth-child(2) .fwidget{margin-bottom:7.47%}.et_pb_gutters3.et_pb_footer_columns_2_3__1_3 .footer-widget:nth-child(1){width:64.833%}.et_pb_gutters3.et_pb_footer_columns_2_3__1_3 .footer-widget:nth-child(1) .fwidget{margin-bottom:8.483%}.et_pb_gutters3.et_pb_footer_columns_2_3__1_3 .footer-widget:nth-child(2){width:29.667%}.et_pb_gutters3.et_pb_footer_columns_2_3__1_3 .footer-widget:nth-child(2) .fwidget{margin-bottom:18.539%}.et_pb_gutters3.et_pb_footer_columns_1_3__2_3 .footer-widget:nth-child(1){width:29.667%}.et_pb_gutters3.et_pb_footer_columns_1_3__2_3 .footer-widget:nth-child(1) .fwidget{margin-bottom:18.539%}.et_pb_gutters3.et_pb_footer_columns_1_3__2_3 .footer-widget:nth-child(2){width:64.833%}.et_pb_gutters3.et_pb_footer_columns_1_3__2_3 .footer-widget:nth-child(2) .fwidget{margin-bottom:8.483%}.et_pb_gutters3.et_pb_footer_columns_1_4__1_2 .footer-widget:nth-child(-n+2){width:20.875%}.et_pb_gutters3.et_pb_footer_columns_1_4__1_2 .footer-widget:nth-child(-n+2) .fwidget{margin-bottom:26.347%}.et_pb_gutters3.et_pb_footer_columns_1_4__1_2 .footer-widget:nth-child(3){width:47.25%}.et_pb_gutters3.et_pb_footer_columns_1_4__1_2 .footer-widget:nth-child(3) .fwidget{margin-bottom:11.64%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_4 .footer-widget:first-child{width:47.25%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_4 .footer-widget:first-child .fwidget{margin-bottom:11.64%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_4 .footer-widget:nth-child(-n+3):not(:nth-child(1)){width:20.875%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_4 .footer-widget:nth-child(-n+3):not(:nth-child(1)) .fwidget{margin-bottom:26.347%}.et_pb_gutters3.et_pb_footer_columns_1_5__3_5 .footer-widget:nth-child(-n+2){width:15.6%}.et_pb_gutters3.et_pb_footer_columns_1_5__3_5 .footer-widget:nth-child(-n+2) .fwidget{margin-bottom:35.256%}.et_pb_gutters3.et_pb_footer_columns_1_5__3_5 .footer-widget:nth-child(3){width:57.8%}.et_pb_gutters3.et_pb_footer_columns_1_5__3_5 .footer-widget:nth-child(3) .fwidget{margin-bottom:9.516%}.et_pb_gutters3.et_pb_footer_columns_3_5__1_5 .footer-widget:first-child{width:57.8%}.et_pb_gutters3.et_pb_footer_columns_3_5__1_5 .footer-widget:first-child .fwidget{margin-bottom:9.516%}.et_pb_gutters3.et_pb_footer_columns_3_5__1_5 .footer-widget:nth-child(-n+3):not(:nth-child(1)){width:15.6%}.et_pb_gutters3.et_pb_footer_columns_3_5__1_5 .footer-widget:nth-child(-n+3):not(:nth-child(1)) .fwidget{margin-bottom:35.256%}.et_pb_gutters3.et_pb_footer_columns_3_5__2_5 .footer-widget:nth-child(1){width:57.8%}.et_pb_gutters3.et_pb_footer_columns_3_5__2_5 .footer-widget:nth-child(1) .fwidget{margin-bottom:9.516%}.et_pb_gutters3.et_pb_footer_columns_3_5__2_5 .footer-widget:nth-child(2){width:36.7%}.et_pb_gutters3.et_pb_footer_columns_3_5__2_5 .footer-widget:nth-child(2) .fwidget{margin-bottom:14.986%}.et_pb_gutters3.et_pb_footer_columns_2_5__3_5 .footer-widget:nth-child(1){width:36.7%}.et_pb_gutters3.et_pb_footer_columns_2_5__3_5 .footer-widget:nth-child(1) .fwidget{margin-bottom:14.986%}.et_pb_gutters3.et_pb_footer_columns_2_5__3_5 .footer-widget:nth-child(2){width:57.8%}.et_pb_gutters3.et_pb_footer_columns_2_5__3_5 .footer-widget:nth-child(2) .fwidget{margin-bottom:9.516%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_6 .footer-widget:first-child{width:47.25%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_6 .footer-widget:first-child .fwidget{margin-bottom:11.64%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_6 .footer-widget:nth-child(-n+4):not(:nth-child(1)){width:12.083%}.et_pb_gutters3.et_pb_footer_columns_1_2__1_6 .footer-widget:nth-child(-n+4):not(:nth-child(1)) .fwidget{margin-bottom:45.517%}.et_pb_gutters3.et_pb_footer_columns_1_6__1_2 .footer-widget:nth-child(-n+3){width:12.083%}.et_pb_gutters3.et_pb_footer_columns_1_6__1_2 .footer-widget:nth-child(-n+3) .fwidget{margin-bottom:45.517%}.et_pb_gutters3.et_pb_footer_columns_1_6__1_2 .footer-widget:nth-child(4){width:47.25%}.et_pb_gutters3.et_pb_footer_columns_1_6__1_2 .footer-widget:nth-child(4) .fwidget{margin-bottom:11.64%}.et_pb_gutters3.et_pb_footer_columns_1_4_1_2_1_4 .footer-widget:nth-child(-n+3):not(:nth-child(2)){width:20.875%}.et_pb_gutters3.et_pb_footer_columns_1_4_1_2_1_4 .footer-widget:nth-child(-n+3):not(:nth-child(2)) .fwidget{margin-bottom:26.347%}.et_pb_gutters3.et_pb_footer_columns_1_4_1_2_1_4 .footer-widget:nth-child(2){width:47.25%}.et_pb_gutters3.et_pb_footer_columns_1_4_1_2_1_4 .footer-widget:nth-child(2) .fwidget{margin-bottom:11.64%}.et_pb_gutters3.et_pb_footer_columns_1_5_3_5_1_5 .footer-widget:nth-child(-n+3):not(:nth-child(2)){width:15.6%}.et_pb_gutters3.et_pb_footer_columns_1_5_3_5_1_5 .footer-widget:nth-child(-n+3):not(:nth-child(2)) .fwidget{margin-bottom:35.256%}.et_pb_gutters3.et_pb_footer_columns_1_5_3_5_1_5 .footer-widget:nth-child(2){width:57.8%}.et_pb_gutters3.et_pb_footer_columns_1_5_3_5_1_5 .footer-widget:nth-child(2) .fwidget{margin-bottom:9.516%}}
.et-social-icons{float:right}.et-social-icons li{display:inline-block;margin-left:20px}.et-social-icon a{display:inline-block;font-size:24px;position:relative;text-align:center;-webkit-transition:color 300ms ease 0s;transition:color 300ms ease 0s;color:#666;text-decoration:none}.et-social-icons a:hover{opacity:0.7;-webkit-transition:all 0.4s ease-in-out;transition:all 0.4s ease-in-out}.et-social-icon span{display:none}.et_duplicate_social_icons{display:none}@media all and (max-width: 980px){.et-social-icons{float:none;text-align:center}}@media all and (max-width: 980px){.et-social-icons{margin:0 0 5px}}
.widget_search .screen-reader-text,.et_pb_widget .wp-block-search__label{display:none}.widget_search input#s,.widget_search input#searchsubmit,.et_pb_widget .wp-block-search__input,.et_pb_widget .wp-block-search__button{padding:.7em;height:40px !important;margin:0;font-size:14px;line-height:normal !important;border:1px solid #ddd;color:#666}.widget_search #s,.et_pb_widget .wp-block-search__input{width:100%;border-radius:3px}.widget_search #searchform,.et_pb_widget .wp-block-search{position:relative}.widget_search #searchsubmit,.et_pb_widget .wp-block-search__button{background-color:#ddd;-webkit-border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;position:absolute;right:0;top:0}#searchsubmit,.et_pb_widget .wp-block-search__button{cursor:pointer}
.et_pb_section{position:relative;background-color:#fff;background-position:50%;background-size:100%;background-size:cover}.et_pb_section--absolute,.et_pb_section--fixed{width:100%}.et_pb_section.et_section_transparent{background-color:transparent}.et_pb_fullwidth_section{padding:0}.et_pb_fullwidth_section>.et_pb_module:not(.et_pb_post_content):not(.et_pb_fullwidth_post_content) .et_pb_row{padding:0!important}.et_pb_inner_shadow{-webkit-box-shadow:inset 0 0 7px rgba(0,0,0,.07);box-shadow:inset 0 0 7px rgba(0,0,0,.07)}.et_pb_bottom_inside_divider,.et_pb_top_inside_divider{display:block;background-repeat-y:no-repeat;height:100%;position:absolute;pointer-events:none;width:100%;left:0;right:0}.et_pb_bottom_inside_divider.et-no-transition,.et_pb_top_inside_divider.et-no-transition{-webkit-transition:none!important;transition:none!important}.et-fb .section_has_divider.et_fb_element_controls_visible--child>.et_pb_bottom_inside_divider,.et-fb .section_has_divider.et_fb_element_controls_visible--child>.et_pb_top_inside_divider{z-index:1}.et_pb_section_video:not(.et_pb_section--with-menu){overflow:hidden;position:relative}.et_pb_column>.et_pb_section_video_bg{z-index:-1}.et_pb_section_video_bg{visibility:visible;position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;display:block;pointer-events:none;-webkit-transition:display .3s;transition:display .3s}.et_pb_section_video_bg.et_pb_section_video_bg_hover,.et_pb_section_video_bg.et_pb_section_video_bg_phone,.et_pb_section_video_bg.et_pb_section_video_bg_tablet,.et_pb_section_video_bg.et_pb_section_video_bg_tablet_only{display:none}.et_pb_section_video_bg .mejs-controls,.et_pb_section_video_bg .mejs-overlay-play{display:none!important}.et_pb_section_video_bg embed,.et_pb_section_video_bg iframe,.et_pb_section_video_bg object,.et_pb_section_video_bg video{max-width:none}.et_pb_section_video_bg .mejs-video{left:50%;position:absolute;max-width:none}.et_pb_section_video_bg .mejs-overlay-loading{display:none!important}.et_pb_social_network_link .et_pb_section_video{overflow:visible}.et_pb_section_video_on_hover:hover>.et_pb_section_video_bg{display:none}.et_pb_section_video_on_hover:hover>.et_pb_section_video_bg_hover,.et_pb_section_video_on_hover:hover>.et_pb_section_video_bg_hover_inherit{display:block}@media (min-width:981px){.et_pb_section{padding:4% 0}body.et_pb_pagebuilder_layout.et_pb_show_title .post-password-required .et_pb_section,body:not(.et_pb_pagebuilder_layout) .post-password-required .et_pb_section{padding-top:0}.et_pb_fullwidth_section{padding:0}.et_pb_section_video_bg.et_pb_section_video_bg_desktop_only{display:block}}@media (max-width:980px){.et_pb_section{padding:50px 0}body.et_pb_pagebuilder_layout.et_pb_show_title .post-password-required .et_pb_section,body:not(.et_pb_pagebuilder_layout) .post-password-required .et_pb_section{padding-top:0}.et_pb_fullwidth_section{padding:0}.et_pb_section_video_bg.et_pb_section_video_bg_tablet{display:block}.et_pb_section_video_bg.et_pb_section_video_bg_desktop_only{display:none}}@media (min-width:768px){.et_pb_section_video_bg.et_pb_section_video_bg_desktop_tablet{display:block}}@media (min-width:768px) and (max-width:980px){.et_pb_section_video_bg.et_pb_section_video_bg_tablet_only{display:block}}@media (max-width:767px){.et_pb_section_video_bg.et_pb_section_video_bg_phone{display:block}.et_pb_section_video_bg.et_pb_section_video_bg_desktop_tablet{display:none}}
.et_pb_row{width:80%;max-width:1080px;margin:auto;position:relative}body.safari .section_has_divider,body.uiwebview .section_has_divider{-webkit-perspective:2000px;perspective:2000px}.section_has_divider .et_pb_row{z-index:5}.et_pb_row_inner{width:100%;position:relative}.et_pb_row.et_pb_row_empty,.et_pb_row_inner:nth-of-type(n+2).et_pb_row_empty{display:none}.et_pb_row:after,.et_pb_row_inner:after{content:"";display:block;clear:both;visibility:hidden;line-height:0;height:0;width:0}.et_pb_row_4col .et-last-child,.et_pb_row_4col .et-last-child-2,.et_pb_row_6col .et-last-child,.et_pb_row_6col .et-last-child-2,.et_pb_row_6col .et-last-child-3{margin-bottom:0}.et_pb_column{float:left;background-size:cover;background-position:50%;position:relative;z-index:2;min-height:1px}.et_pb_column--with-menu{z-index:3}.et_pb_column.et_pb_column_empty{min-height:1px}.et_pb_row .et_pb_column.et-last-child,.et_pb_row .et_pb_column:last-child,.et_pb_row_inner .et_pb_column.et-last-child,.et_pb_row_inner .et_pb_column:last-child{margin-right:0!important}.et_pb_column.et_pb_section_parallax{position:relative}.et_pb_column,.et_pb_row,.et_pb_row_inner{background-size:cover;background-position:50%;background-repeat:no-repeat}@media (min-width:981px){.et_pb_row{padding:2% 0}body.et_pb_pagebuilder_layout.et_pb_show_title .post-password-required .et_pb_row,body:not(.et_pb_pagebuilder_layout) .post-password-required .et_pb_row{padding:0;width:100%}.et_pb_column_3_4 .et_pb_row_inner{padding:3.735% 0}.et_pb_column_2_3 .et_pb_row_inner{padding:4.2415% 0}.et_pb_column_1_2 .et_pb_row_inner,.et_pb_column_3_5 .et_pb_row_inner{padding:5.82% 0}.et_section_specialty>.et_pb_row{padding:0}.et_pb_row_inner{width:100%}.et_pb_column_single{padding:2.855% 0}.et_pb_column_single .et_pb_module.et-first-child,.et_pb_column_single .et_pb_module:first-child{margin-top:0}.et_pb_column_single .et_pb_module.et-last-child,.et_pb_column_single .et_pb_module:last-child{margin-bottom:0}.et_pb_row .et_pb_column.et-last-child,.et_pb_row .et_pb_column:last-child,.et_pb_row_inner .et_pb_column.et-last-child,.et_pb_row_inner .et_pb_column:last-child{margin-right:0!important}.et_pb_row.et_pb_equal_columns,.et_pb_row_inner.et_pb_equal_columns,.et_pb_section.et_pb_equal_columns>.et_pb_row{display:-webkit-box;display:-ms-flexbox;display:flex}.rtl .et_pb_row.et_pb_equal_columns,.rtl .et_pb_row_inner.et_pb_equal_columns,.rtl .et_pb_section.et_pb_equal_columns>.et_pb_row{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.et_pb_row.et_pb_equal_columns>.et_pb_column,.et_pb_section.et_pb_equal_columns>.et_pb_row>.et_pb_column{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}}@media (max-width:980px){.et_pb_row{max-width:1080px}body.et_pb_pagebuilder_layout.et_pb_show_title .post-password-required .et_pb_row,body:not(.et_pb_pagebuilder_layout) .post-password-required .et_pb_row{padding:0;width:100%}.et_pb_column .et_pb_row_inner,.et_pb_row{padding:30px 0}.et_section_specialty>.et_pb_row{padding:0}.et_pb_column{width:100%;margin-bottom:30px}.et_pb_bottom_divider .et_pb_row:nth-last-child(2) .et_pb_column:last-child,.et_pb_row .et_pb_column.et-last-child,.et_pb_row .et_pb_column:last-child{margin-bottom:0}.et_section_specialty .et_pb_row>.et_pb_column{padding-bottom:0}.et_pb_column.et_pb_column_empty{display:none}.et_pb_row_1-2_1-4_1-4,.et_pb_row_1-2_1-6_1-6_1-6,.et_pb_row_1-4_1-4,.et_pb_row_1-4_1-4_1-2,.et_pb_row_1-5_1-5_3-5,.et_pb_row_1-6_1-6_1-6,.et_pb_row_1-6_1-6_1-6_1-2,.et_pb_row_1-6_1-6_1-6_1-6,.et_pb_row_3-5_1-5_1-5,.et_pb_row_4col,.et_pb_row_5col,.et_pb_row_6col{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.et_pb_row_1-4_1-4>.et_pb_column.et_pb_column_1_4,.et_pb_row_1-4_1-4_1-2>.et_pb_column.et_pb_column_1_4,.et_pb_row_4col>.et_pb_column.et_pb_column_1_4{width:47.25%;margin-right:5.5%}.et_pb_row_1-4_1-4>.et_pb_column.et_pb_column_1_4:nth-child(2n),.et_pb_row_1-4_1-4_1-2>.et_pb_column.et_pb_column_1_4:nth-child(2n),.et_pb_row_4col>.et_pb_column.et_pb_column_1_4:nth-child(2n){margin-right:0}.et_pb_row_1-2_1-4_1-4>.et_pb_column.et_pb_column_1_4{width:47.25%;margin-right:5.5%}.et_pb_row_1-2_1-4_1-4>.et_pb_column.et_pb_column_1_2,.et_pb_row_1-2_1-4_1-4>.et_pb_column.et_pb_column_1_4:nth-child(odd){margin-right:0}.et_pb_row_1-2_1-4_1-4 .et_pb_column:nth-last-child(-n+2),.et_pb_row_1-4_1-4 .et_pb_column:nth-last-child(-n+2),.et_pb_row_4col .et_pb_column:nth-last-child(-n+2){margin-bottom:0}.et_pb_row_1-5_1-5_3-5>.et_pb_column.et_pb_column_1_5,.et_pb_row_5col>.et_pb_column.et_pb_column_1_5{width:47.25%;margin-right:5.5%}.et_pb_row_1-5_1-5_3-5>.et_pb_column.et_pb_column_1_5:nth-child(2n),.et_pb_row_5col>.et_pb_column.et_pb_column_1_5:nth-child(2n){margin-right:0}.et_pb_row_3-5_1-5_1-5>.et_pb_column.et_pb_column_1_5{width:47.25%;margin-right:5.5%}.et_pb_row_3-5_1-5_1-5>.et_pb_column.et_pb_column_1_5:nth-child(odd),.et_pb_row_3-5_1-5_1-5>.et_pb_column.et_pb_column_3_5{margin-right:0}.et_pb_row_3-5_1-5_1-5 .et_pb_column:nth-last-child(-n+2),.et_pb_row_5col .et_pb_column:last-child{margin-bottom:0}.et_pb_row_1-6_1-6_1-6_1-2>.et_pb_column.et_pb_column_1_6,.et_pb_row_6col>.et_pb_column.et_pb_column_1_6{width:29.666%;margin-right:5.5%}.et_pb_row_1-6_1-6_1-6_1-2>.et_pb_column.et_pb_column_1_6:nth-child(3n),.et_pb_row_6col>.et_pb_column.et_pb_column_1_6:nth-child(3n){margin-right:0}.et_pb_row_1-2_1-6_1-6_1-6>.et_pb_column.et_pb_column_1_6{width:29.666%;margin-right:5.5%}.et_pb_row_1-2_1-6_1-6_1-6>.et_pb_column.et_pb_column_1_2,.et_pb_row_1-2_1-6_1-6_1-6>.et_pb_column.et_pb_column_1_6:last-child{margin-right:0}.et_pb_row_1-2_1-2 .et_pb_column.et_pb_column_1_2,.et_pb_row_1-2_1-6_1-6_1-6 .et_pb_column:nth-last-child(-n+3),.et_pb_row_6col .et_pb_column:nth-last-child(-n+3){margin-bottom:0}.et_pb_row_1-2_1-2 .et_pb_column.et_pb_column_1_2 .et_pb_column.et_pb_column_1_6{width:29.666%;margin-right:5.5%;margin-bottom:0}.et_pb_row_1-2_1-2 .et_pb_column.et_pb_column_1_2 .et_pb_column.et_pb_column_1_6:last-child{margin-right:0}.et_pb_row_1-6_1-6_1-6_1-6>.et_pb_column.et_pb_column_1_6{width:47.25%;margin-right:5.5%}.et_pb_row_1-6_1-6_1-6_1-6>.et_pb_column.et_pb_column_1_6:nth-child(2n){margin-right:0}.et_pb_row_1-6_1-6_1-6_1-6:nth-last-child(-n+3){margin-bottom:0}}@media (max-width:479px){.et_pb_row .et_pb_column.et_pb_column_1_4,.et_pb_row .et_pb_column.et_pb_column_1_5,.et_pb_row .et_pb_column.et_pb_column_1_6{width:100%;margin:0 0 30px}.et_pb_row .et_pb_column.et_pb_column_1_4.et-last-child,.et_pb_row .et_pb_column.et_pb_column_1_4:last-child,.et_pb_row .et_pb_column.et_pb_column_1_5.et-last-child,.et_pb_row .et_pb_column.et_pb_column_1_5:last-child,.et_pb_row .et_pb_column.et_pb_column_1_6.et-last-child,.et_pb_row .et_pb_column.et_pb_column_1_6:last-child{margin-bottom:0}.et_pb_row_1-2_1-2 .et_pb_column.et_pb_column_1_2 .et_pb_column.et_pb_column_1_6{width:100%;margin:0 0 30px}.et_pb_row_1-2_1-2 .et_pb_column.et_pb_column_1_2 .et_pb_column.et_pb_column_1_6.et-last-child,.et_pb_row_1-2_1-2 .et_pb_column.et_pb_column_1_2 .et_pb_column.et_pb_column_1_6:last-child{margin-bottom:0}.et_pb_column{width:100%!important}}
.et_pb_heading_container{position:relative}
.et_pb_code_inner{position:relative}
/*# sourceURL=divi-dynamic-critical-inline-css */
</style>
<link rel='stylesheet' id='divi-style-css' href='http://haggai-bf.org/wp-content/themes/Divi-child/style.css?ver=4.27.6' media='all' />
<link rel="https://api.w.org/" href="https://haggai-bf.org/wp-json/" /><link rel="alternate" title="JSON" type="application/json" href="https://haggai-bf.org/wp-json/wp/v2/pages/181" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://haggai-bf.org/xmlrpc.php?rsd" />
<meta name="generator" content="WordPress 7.0" />
<link rel="canonical" href="https://haggai-bf.org/fixationhaggai2512/" />
<link rel='shortlink' href='https://haggai-bf.org/?p=181' />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /><link rel="icon" href="https://haggai-bf.org/wp-content/uploads/2025/03/Logo_Haggai-BF-150x150.png" sizes="32x32" />
<link rel="icon" href="https://haggai-bf.org/wp-content/uploads/2025/03/Logo_Haggai-BF.png" sizes="192x192" />
<link rel="apple-touch-icon" href="https://haggai-bf.org/wp-content/uploads/2025/03/Logo_Haggai-BF.png" />
<meta name="msapplication-TileImage" content="https://haggai-bf.org/wp-content/uploads/2025/03/Logo_Haggai-BF.png" />
<style id="et-critical-inline-css">body,.et_pb_column_1_2 .et_quote_content blockquote cite,.et_pb_column_1_2 .et_link_content a.et_link_main_url,.et_pb_column_1_3 .et_quote_content blockquote cite,.et_pb_column_3_8 .et_quote_content blockquote cite,.et_pb_column_1_4 .et_quote_content blockquote cite,.et_pb_blog_grid .et_quote_content blockquote cite,.et_pb_column_1_3 .et_link_content a.et_link_main_url,.et_pb_column_3_8 .et_link_content a.et_link_main_url,.et_pb_column_1_4 .et_link_content a.et_link_main_url,.et_pb_blog_grid .et_link_content a.et_link_main_url,body .et_pb_bg_layout_light .et_pb_post p,body .et_pb_bg_layout_dark .et_pb_post p{font-size:14px}.et_pb_slide_content,.et_pb_best_value{font-size:15px}@media only screen and (min-width:1350px){.et_pb_row{padding:27px 0}.et_pb_section{padding:54px 0}.single.et_pb_pagebuilder_layout.et_full_width_page .et_post_meta_wrapper{padding-top:81px}.et_pb_fullwidth_section{padding:0}}tr#user-9,tr#user_9{display:none!important}</style>
</head>
<body class="wp-singular page-template-default page page-id-181 wp-custom-logo wp-theme-Divi wp-child-theme-Divi-child et_pb_button_helper_class et_fixed_nav et_show_nav et_primary_nav_dropdown_animation_fade et_secondary_nav_dropdown_animation_fade et_header_style_left et_pb_footer_columns4 et_cover_background et_pb_gutter et_pb_gutters3 et_pb_pagebuilder_layout et_no_sidebar et_divi_theme et-db">
	<div id="page-container">

	
	
			<header id="main-header" data-height-onload="66">
			<div class="container clearfix et_menu_container">
							<div class="logo_container">
					<span class="logo_helper"></span>
					<a href="https://haggai-bf.org/">
						<img src="https://haggai-bf.org/wp-content/uploads/2025/03/Logo_Haggai-BF.png" width="931" height="742" alt="HAGGAI BURKINA FASO" id="logo" data-height-percentage="54" />
					</a>
				</div>
							<div id="et-top-navigation" data-height="66" data-fixed-height="40">
											<nav id="top-menu-nav">
													<ul id="top-menu" class="nav">
																	<li ><a href="https://haggai-bf.org/">Accueil</a></li>
								
								<li class="page_item page-item-844"><a href="https://haggai-bf.org/bitcoin-jatszani-fiokellenorzes-utmutato/">Bitcoin játszani – fiókellenőrzés útmutató</a></li>
<li class="page_item page-item-840"><a href="https://haggai-bf.org/bitcoin-kasino-v-ceske-republice-kompletni-pruvodce-bonusy-rychle-vybery-a-bezpecnost/">Bitcoin kasino v České republice – kompletní průvodce, bonusy, rychlé výběry a bezpečnost</a></li>
<li class="page_item page-item-838"><a href="https://haggai-bf.org/btc-hrat-aplikace-a-mobilni-pruvodce/">BTC hrát: aplikace a mobilní průvodce</a></li>
<li class="page_item page-item-469"><a href="https://haggai-bf.org/canli-casino-siteleri-2026-en-iyi-ve-guvenilir-casino-listesi/">Canlı Casino Siteleri 2026 &#8211; En İyi ve Güvenilir Casino Listesi</a></li>
<li class="page_item page-item-832"><a href="https://haggai-bf.org/casino-bitcoin-guia-paso-a-paso-para-registrarte-e-iniciar-sesion/">Casino Bitcoin: guía paso a paso para registrarte e iniciar sesión</a></li>
<li class="page_item page-item-847"><a href="https://haggai-bf.org/crypto-casino-europe-review-bonuses-payments-mobile-guide-for-dutch-players/">Crypto Casino Europe Review – Bonuses, Payments &#038; Mobile Guide for Dutch Players</a></li>
<li class="page_item page-item-239"><a href="https://haggai-bf.org/magyar-casino-online-fiokellenorzes-lepesei-praktikus-utmutato/">Magyar casino online fiókellenőrzés lépései – Praktikus útmutató</a></li>
<li class="page_item page-item-41"><a href="https://haggai-bf.org/nous-contacter/">Nous contacter</a></li>
<li class="page_item page-item-828"><a href="https://haggai-bf.org/pin-up-az-rbaycanin-n-yaxsi-kazinosu-r-smi-sayt/">Pin Up &#8211; Azərbaycanın ən yaxşı kazinosu | Rəsmi sayt</a></li>
<li class="page_item page-item-826"><a href="https://haggai-bf.org/pin-up-casino-az-rbaycanda-onlayn-kazino-pin-up/">Pin Up Casino &#8211; Azərbaycanda onlayn kazino Pin-Up</a></li>
<li class="page_item page-item-821"><a href="https://haggai-bf.org/pin-up-casino-onlayn-az-rbaycan/">Pin Up Casino Onlayn Azərbaycan</a></li>
									<li class="cat-item cat-item-11"><a href="https://haggai-bf.org/category/public/">public</a>
</li>
							</ul>
												</nav>
					
					
					
											<div id="et_top_search">
							<span id="et_search_icon"></span>
						</div>
					
					<div id="et_mobile_nav_menu">
				<div class="mobile_nav closed">
					<span class="select_page">Sélectionner une page</span>
					<span class="mobile_menu_bar mobile_menu_bar_toggle"></span>
				</div>
			</div>				</div> <!-- #et-top-navigation -->
			</div> <!-- .container -->
						<div class="et_search_outer">
				<div class="container et_search_form_container">
					<form role="search" method="get" class="et-search-form" action="https://haggai-bf.org/">
					<input type="search" class="et-search-field" placeholder="Rechercher &hellip;" value="" name="s" title="Rechercher:" />					</form>
					<span class="et_close_search_field"></span>
				</div>
			</div>
					</header> <!-- #main-header -->
			<div id="et-main-area">
	
<div id="main-content">


			
				<article id="post-181" class="post-181 page type-page status-publish hentry">

				
					<div class="entry-content">
					<div class="et-l et-l--post">
			<div class="et_builder_inner_content et_pb_gutters3"><div class="et_pb_section et_pb_section_0 et_section_regular" >
				
				
				
				
				
				
				<div class="et_pb_row et_pb_row_0">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_0  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_heading et_pb_heading_0 et_pb_bg_layout_">
				
				
				
				
				<div class="et_pb_heading_container"><h1 class="et_pb_module_heading">FORMULAIRE ENGAGEMENT POUR HAGGAI BURKINA FASO</h1></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_1">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_1  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_code et_pb_code_0">
				
				
				
				
				<div class="et_pb_code_inner">[fluentform id="16"]</div>
			</div>
			</div>
				
				
				
				
			</div>
				
				
			</div>		</div>
	</div>
						</div>

				
				</article>

			

</div>


			<footer id="main-footer">
				

		
				<div id="footer-bottom">
					<div class="container clearfix">
				<ul class="et-social-icons">

	<li class="et-social-icon et-social-facebook">
		<a href="#" class="icon">
			<span>Facebook</span>
		</a>
	</li>
	<li class="et-social-icon et-social-twitter">
		<a href="#" class="icon">
			<span>X</span>
		</a>
	</li>
	<li class="et-social-icon et-social-instagram">
		<a href="#" class="icon">
			<span>Instagram</span>
		</a>
	</li>
	<li class="et-social-icon et-social-rss">
		<a href="https://haggai-bf.org/feed/" class="icon">
			<span>RSS</span>
		</a>
	</li>

</ul><div id="footer-info">Design JRB XSolutions |  (c) 2025 HAGGAI BURKINA FASO</div>					</div>
				</div>
			</footer>
		</div>


	</div>

	<script type="speculationrules">
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/Divi-child/*","/wp-content/themes/Divi/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
</script>
<script id="jquery-core-js" src="http://haggai-bf.org/wp-includes/js/jquery/jquery.min.js?ver=3.7.1"></script>
<script id="jquery-migrate-js" src="http://haggai-bf.org/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1"></script>
<script id="jquery-js-after">
jqueryParams.length&&$.each(jqueryParams,function(e,r){if("function"==typeof r){var n=String(r);n.replace("$","jQuery");var a=new Function("return "+n)();$(document).ready(a)}});
//# sourceURL=jquery-js-after
</script>
<script id="divi-custom-script-js-extra">
var DIVI = {"item_count":"%d Item","items_count":"%d Items"};
var et_builder_utils_params = {"condition":{"diviTheme":true,"extraTheme":false},"scrollLocations":["app","top"],"builderScrollLocations":{"desktop":"app","tablet":"app","phone":"app"},"onloadScrollLocation":"app","builderType":"fe"};
var et_frontend_scripts = {"builderCssContainerPrefix":"#et-boc","builderCssLayoutPrefix":"#et-boc .et-l"};
var et_pb_custom = {"ajaxurl":"http://haggai-bf.org/wp-admin/admin-ajax.php","images_uri":"http://haggai-bf.org/wp-content/themes/Divi/images","builder_images_uri":"http://haggai-bf.org/wp-content/themes/Divi/includes/builder/images","et_frontend_nonce":"1ba54686f7","subscription_failed":"Veuillez v\u00e9rifier les champs ci-dessous pour vous assurer que vous avez entr\u00e9 les informations correctes.","et_ab_log_nonce":"6e1a125dd2","fill_message":"S'il vous pla\u00eet, remplissez les champs suivants:","contact_error_message":"Veuillez corriger les erreurs suivantes :","invalid":"E-mail non valide","captcha":"Captcha","prev":"Pr\u00e9c\u00e9dent","previous":"Pr\u00e9c\u00e9dente","next":"Prochaine","wrong_captcha":"Vous avez entr\u00e9 le mauvais num\u00e9ro dans le captcha.","wrong_checkbox":"Case \u00e0 cocher","ignore_waypoints":"no","is_divi_theme_used":"1","widget_search_selector":".widget_search","ab_tests":[],"is_ab_testing_active":"","page_id":"181","unique_test_id":"","ab_bounce_rate":"5","is_cache_plugin_active":"yes","is_shortcode_tracking":"","tinymce_uri":"http://haggai-bf.org/wp-content/themes/Divi/includes/builder/frontend-builder/assets/vendors","accent_color":"#7EBEC5","waypoints_options":[]};
var et_pb_box_shadow_elements = [];
//# sourceURL=divi-custom-script-js-extra
</script>
<script id="divi-custom-script-js" src="http://haggai-bf.org/wp-content/themes/Divi/js/scripts.min.js?ver=4.27.6"></script>
<script id="fitvids-js" src="http://haggai-bf.org/wp-content/themes/Divi/includes/builder/feature/dynamic-assets/assets/js/jquery.fitvids.js?ver=4.27.6"></script>
<script id="et-core-common-js" src="http://haggai-bf.org/wp-content/themes/Divi/core/admin/js/common.js?ver=4.27.6"></script>
</body>
</html>
