@font-face {
	font-weight: normal;
	font-style: normal;
	font-family: "woodmart-font";
	src: url("//pngheaven.com/wp-content/themes/woodmart/fonts/woodmart-font-3-400.woff2?v=8.3.8") format("woff2");
}

@font-face {
	font-family: "star";
	font-weight: 400;
	font-style: normal;
	src: url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/star.eot?#iefix") format("embedded-opentype"), url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/star.woff") format("woff"), url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/star.ttf") format("truetype"), url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/star.svg#star") format("svg");
}

@font-face {
	font-family: "WooCommerce";
	font-weight: 400;
	font-style: normal;
	src: url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/WooCommerce.eot?#iefix") format("embedded-opentype"), url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/WooCommerce.woff") format("woff"), url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/WooCommerce.ttf") format("truetype"), url("//pngheaven.com/wp-content/plugins/woocommerce/assets/fonts/WooCommerce.svg#WooCommerce") format("svg");
}

:root {
	--wd-text-font: "Manrope", Arial, Helvetica, sans-serif;
	--wd-text-font-weight: 400;
	--wd-text-color: #777777;
	--wd-text-font-size: 15px;
	--wd-title-font: "Manrope", Arial, Helvetica, sans-serif;
	--wd-title-font-weight: 700;
	--wd-title-color: #242424;
	--wd-entities-title-font: "Manrope", Arial, Helvetica, sans-serif;
	--wd-entities-title-font-weight: 600;
	--wd-entities-title-color: #333333;
	--wd-entities-title-color-hover: rgb(51 51 51 / 65%);
	--wd-alternative-font: "Lato", Arial, Helvetica, sans-serif;
	--wd-widget-title-font: "Manrope", Arial, Helvetica, sans-serif;
	--wd-widget-title-font-weight: 700;
	--wd-widget-title-transform: capitalize;
	--wd-widget-title-color: #333;
	--wd-widget-title-font-size: 16px;
	--wd-header-el-font: "Manrope", Arial, Helvetica, sans-serif;
	--wd-header-el-font-weight: 600;
	--wd-header-el-transform: capitalize;
	--wd-header-el-font-size: 14px;
	--wd-brd-radius: 10px;
	--wd-otl-style: dotted;
	--wd-otl-width: 2px;
	--wd-primary-color: rgb(140,188,103);
	--wd-alternative-color: #fbbc34;
	--btn-default-bgcolor: #f7f7f7;
	--btn-default-bgcolor-hover: #efefef;
	--btn-accented-bgcolor: rgb(140,188,103);
	--btn-accented-bgcolor-hover: rgb(128,171,94);
	--btn-transform: capitalize;
	--wd-form-brd-width: 1px;
	--notices-success-bg: #459647;
	--notices-success-color: #fff;
	--notices-warning-bg: #E0B252;
	--notices-warning-color: #fff;
	--wd-link-color: #333333;
	--wd-link-color-hover: #242424;
	--wd-sticky-btn-height: 95px;
}
.wd-age-verify-wrap {
	--wd-popup-width: 500px;
}
.wd-popup.wd-promo-popup {
	background-color: #111111;
	background-image: none;
	background-repeat: no-repeat;
	background-size: contain;
	background-position: left center;
}
.wd-promo-popup-wrap {
	--wd-popup-width: 800px;
}
:is(.woodmart-archive-shop .wd-builder-off,.wd-wishlist-content,.related-and-upsells,.cart-collaterals,.wd-shop-product,.wd-fbt) .wd-products-with-bg, :is(.woodmart-archive-shop .wd-builder-off,.wd-wishlist-content,.related-and-upsells,.cart-collaterals,.wd-shop-product,.wd-fbt) .wd-products-with-bg :is(.wd-product,.wd-cat) {
	--wd-prod-bg:rgb(255,255,255);
	--wd-bordered-bg:rgb(255,255,255);
}
:is(.woodmart-woocommerce-layered-nav, .wd-product-category-filter) .wd-scroll-content {
	max-height: 223px;
}
.wd-page-title .wd-page-title-bg img {
	object-fit: cover;
	object-position: center center;
}
.wd-footer {
	background-color: rgb(140,188,103);
	background-image: none;
}
html .wd-nav-mobile > li > a {
	text-transform: capitalize;
}
html .wd-checkout-steps li {
	text-transform: capitalize;
}
html .page-title > .container > .title, html .page-title .wd-title-wrapp > .title {
	font-size: 32px;
}
html table th {
	text-transform: capitalize;
}
.page .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
.woodmart-archive-shop:not(.single-product) .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
.single-product .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
.woodmart-archive-blog .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
.single-post .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
.woodmart-archive-portfolio .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
.single-portfolio .wd-page-content {
	background-color: rgb(250,248,245);
	background-image: none;
}
html .widget_price_filter [class*="price_slider_amount"] .button {
	color: rgb(255,255,255);
	background: rgb(140,188,103);
}
html .widget_price_filter [class*="price_slider_amount"] .button:hover {
	color: rgb(255,255,255);
	background: rgb(128,171,94);
}
body, [class*=color-scheme-light], [class*=color-scheme-dark], .wd-search-form[class*="wd-header-search-form"] form.searchform, .wd-el-search .searchform {
	--wd-form-bg: rgb(255,255,255);
}
.wd-nav-arrows.wd-pos-sep:not(:where(.wd-custom-style)) {
	--wd-arrow-size: 40px;
	--wd-arrow-icon-size: 16px;
	--wd-arrow-offset-h: 20px;
	--wd-arrow-color: rgb(51,51,51);
	--wd-arrow-color-hover: rgb(255,255,255);
	--wd-arrow-color-dis: rgba(51,51,51,0.8);
	--wd-arrow-bg: rgb(255,255,255);
	--wd-arrow-bg-hover: rgb(140,188,103);
	--wd-arrow-bg-dis: rgb(255,255,255);
	--wd-arrow-radius: 10px;
	--wd-arrow-shadow: 0px 0px 0px 0px rgba(255,255,255,0);
}
.wd-nav-scroll {
	--wd-nscroll-height: 3px;
	--wd-nscroll-drag-bg: rgb(140,188,103);
	--wd-nscroll-drag-bg-hover: rgb(128,171,94);
}
.product-labels .product-label.new {
	background-color: rgb(244,229,12);
	color: rgba(191,59,19,0.97);
}
.mfp-wrap.wd-popup-quick-view-wrap {
	--wd-popup-width: 920px;
}

@media (max-width: 1024px) {
	:root {
		--wd-sticky-btn-height: 95px;
	}
	html .page-title > .container > .title, html .page-title .wd-title-wrapp > .title {
		font-size: 28px;
	}
	[class*="thumbs-grid-bottom"] .woocommerce-product-gallery__wrapper.wd-grid {
		--wd-col: 1;
	}

}

@media (max-width: 768.98px) {
	:root {
		--wd-sticky-btn-height: 42px;
	}
	[class*="thumbs-grid-bottom"] .woocommerce-product-gallery__wrapper.wd-grid {
		--wd-col: 1;
	}

}
:root{
--wd-container-w: 1480px;
--wd-form-brd-radius: 5px;
--btn-default-color: #333;
--btn-default-color-hover: #333;
--btn-accented-color: #fff;
--btn-accented-color-hover: #fff;
--btn-default-brd-radius: 5px;
--btn-default-box-shadow: none;
--btn-default-box-shadow-hover: none;
--btn-accented-brd-radius: 5px;
--btn-accented-box-shadow: none;
--btn-accented-box-shadow-hover: none;
}

@media (min-width: 1480px) {
section.elementor-section.wd-section-stretch > .elementor-container {
margin-left: auto;
margin-right: auto;
}
}


.wd-page-title {
background-color: rgb(250,248,245);
}

/**
 * PNG Heaven Daily Free — 이 스니펫만으로 동작.
 * 다른 daily-free 스니펫과 함수명이 겹치지 않게 phdf_ 접두어만 쓴다.
 *
 * Code Snippets:
 * - 첫 줄 <?php 빼고 붙여 넣기
 * - Run everywhere / 모든 곳에서 실행
 */

if (!defined('ABSPATH')) {
    exit;
}

if (defined('PHDF_LOADED')) {
    return;
}
define('PHDF_LOADED', true);

function phdf_cfg() {
    return array(
        'turnstile_site_key' => '0x4AAAAAAEq_JOECAYQwlQmg',
        'turnstile_secret'   => '0x4AAAAAAEq_JBYzxAYYGtnn2UlSGU_etQM',
        'hourly_limit'       => 5,
        'daily_limit'        => 20,
        'token_ttl'          => 300,
        's3_bucket'          => 'png-heaven-storage',
        's3_region'          => 'ap-southeast-2',
        's3_access_key'      => 'AKIAQMBVP3RZFVDYJXJY',
        's3_secret_key'      => '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',
        's3_key_template'    => 'wp-content/uploads/daily-free/{number}.png',
        'preview_base'       => 'https://pngheaven.com/daily-free/',
    );
}

function phdf_number() {
    $total        = 1100;
    $start_number = 7;
    $tz           = new DateTimeZone('Asia/Seoul');
    $start        = new DateTime('2026-09-02', $tz);
    $today        = new DateTime('today', $tz);
    $days         = (int) $start->diff($today)->format('%r%a');
    $number       = (($days + $start_number - 1) % $total) + 1;
    if ($number <= 0) {
        $number += $total;
    }
    return str_pad((string) $number, 4, '0', STR_PAD_LEFT);
}

function phdf_ip() {
    if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
        return sanitize_text_field(wp_unslash($_SERVER['HTTP_CF_CONNECTING_IP']));
    }
    if (!empty($_SERVER['REMOTE_ADDR'])) {
        return sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR']));
    }
    return '0.0.0.0';
}

function phdf_s3_public_url($number) {
    $cfg = phdf_cfg();
    $key = ltrim(str_replace('{number}', $number, $cfg['s3_key_template']), '/');
    return 'https://' . $cfg['s3_bucket'] . '.s3.' . $cfg['s3_region'] . '.amazonaws.com/' . $key;
}

function phdf_http_get_body($url) {
    $ua   = 'Mozilla/5.0 (compatible; PNGHeavenDailyFree/2.2)';
    $args = array(
        'timeout'     => 90,
        'redirection' => 5,
        'sslverify'   => true,
        'headers'     => array('User-Agent' => $ua),
    );

    $res = wp_remote_get($url, $args);
    if (!is_wp_error($res) && (int) wp_remote_retrieve_response_code($res) === 200) {
        $body = wp_remote_retrieve_body($res);
        if (is_string($body) && $body !== '') {
            return $body;
        }
    }

    $args['sslverify'] = false;
    $res = wp_remote_get($url, $args);
    if (!is_wp_error($res) && (int) wp_remote_retrieve_response_code($res) === 200) {
        $body = wp_remote_retrieve_body($res);
        if (is_string($body) && $body !== '') {
            return $body;
        }
    }

    if (function_exists('curl_init')) {
        $tries = array(true, false);
        foreach ($tries as $verify) {
            $ch = curl_init($url);
            curl_setopt_array($ch, array(
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS      => 5,
                CURLOPT_TIMEOUT        => 90,
                CURLOPT_SSL_VERIFYPEER => $verify,
                CURLOPT_SSL_VERIFYHOST => $verify ? 2 : 0,
                CURLOPT_USERAGENT      => $ua,
            ));
            $body = curl_exec($ch);
            $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            if ($code === 200 && is_string($body) && $body !== '') {
                return $body;
            }
        }
    }

    return false;
}

function phdf_s3_fetch($number) {
    $public = phdf_s3_public_url($number);
    $body   = phdf_http_get_body($public);
    if (is_string($body) && strncmp($body, "\x89PNG", 4) === 0) {
        return $body;
    }
    return new WP_Error('missing_file', 'Today\'s file is not available yet.', array('status' => 503));
}

function phdf_rate_keys() {
    $tz   = new DateTimeZone('Asia/Seoul');
    $now  = new DateTime('now', $tz);
    $hash = hash('sha256', phdf_ip() . wp_salt('auth'));
    return array(
        'hour'     => 'phdf_h_' . $hash . '_' . $now->format('YmdH'),
        'day'      => 'phdf_d_' . $hash . '_' . $now->format('Ymd'),
        'hour_ttl' => 3600,
        'day_ttl'  => max(60, (new DateTime('tomorrow', $tz))->getTimestamp() - time()),
    );
}

function phdf_rate_count($key) {
    $n = get_transient($key);
    return is_numeric($n) ? (int) $n : 0;
}

function phdf_rate_check() {
    $cfg  = phdf_cfg();
    $keys = phdf_rate_keys();
    if (phdf_rate_count($keys['hour']) >= $cfg['hourly_limit']) {
        return new WP_Error('rate_limited', 'Hourly download limit reached. Try again later.', array('status' => 429));
    }
    if (phdf_rate_count($keys['day']) >= $cfg['daily_limit']) {
        return new WP_Error('rate_limited', 'Daily download limit reached. Come back tomorrow.', array('status' => 429));
    }
    return true;
}

function phdf_json_error($error) {
    $data   = $error->get_error_data();
    $status = (is_array($data) && !empty($data['status'])) ? (int) $data['status'] : 403;
    status_header($status);
    nocache_headers();
    header('Content-Type: application/json; charset=utf-8');
    echo wp_json_encode(array(
        'code'    => $error->get_error_code(),
        'message' => $error->get_error_message(),
    ));
    exit;
}

function phdf_verify_turnstile($token) {
    $cfg = phdf_cfg();
    if ($cfg['turnstile_secret'] === '') {
        return new WP_Error('not_configured', 'Turnstile is not configured.', array('status' => 503));
    }
    if (!is_string($token) || $token === '') {
        return new WP_Error('bad_token', 'Verification required.', array('status' => 400));
    }
    $response = wp_remote_post(
        'https://challenges.cloudflare.com/turnstile/v0/siteverify',
        array(
            'timeout' => 12,
            'body'    => array(
                'secret'   => $cfg['turnstile_secret'],
                'response' => $token,
                'remoteip' => phdf_ip(),
            ),
        )
    );
    if (is_wp_error($response)) {
        return new WP_Error('turnstile_error', 'Verification failed. Try again.', array('status' => 502));
    }
    $body = json_decode(wp_remote_retrieve_body($response), true);
    if (empty($body['success'])) {
        return new WP_Error('turnstile_denied', 'Verification failed. Try again.', array('status' => 403));
    }
    return true;
}

function phdf_issue_token($turnstile) {
    $limited = phdf_rate_check();
    if (is_wp_error($limited)) {
        return $limited;
    }
    $ok = phdf_verify_turnstile($turnstile);
    if (is_wp_error($ok)) {
        return $ok;
    }
    $cfg   = phdf_cfg();
    $nonce = bin2hex(random_bytes(32));
    set_transient(
        'phdf_dl_' . $nonce,
        array(
            'exp' => time() + (int) $cfg['token_ttl'],
            'ip'  => phdf_ip(),
        ),
        (int) $cfg['token_ttl']
    );
    $page = wp_get_referer();
    if (!$page) {
        $page = home_url('/');
    }
    return array(
        'url' => add_query_arg(
            array(
                'phdf_dl' => '1',
                't'       => $nonce,
            ),
            $page
        ),
    );
}

function phdf_stream($nonce) {
    $nonce = sanitize_text_field((string) $nonce);
    if ($nonce === '' || !preg_match('/^[a-f0-9]{64}$/', $nonce)) {
        return new WP_Error('bad_request', 'Invalid download link.', array('status' => 400));
    }
    $data = get_transient('phdf_dl_' . $nonce);
    if (!is_array($data) || empty($data['exp']) || time() > (int) $data['exp']) {
        delete_transient('phdf_dl_' . $nonce);
        return new WP_Error('expired', 'This download link has expired.', array('status' => 403));
    }
    if (!empty($data['ip']) && $data['ip'] !== phdf_ip()) {
        return new WP_Error('denied', 'This download link is not valid here.', array('status' => 403));
    }
    $limited = phdf_rate_check();
    if (is_wp_error($limited)) {
        return $limited;
    }
    delete_transient('phdf_dl_' . $nonce);
    $keys = phdf_rate_keys();
    set_transient($keys['hour'], phdf_rate_count($keys['hour']) + 1, $keys['hour_ttl']);
    set_transient($keys['day'], phdf_rate_count($keys['day']) + 1, $keys['day_ttl']);

    $today    = new DateTime('today', new DateTimeZone('Asia/Seoul'));
    $filename = 'pngheaven-free-' . $today->format('Y-m-d') . '.png';
    $body     = phdf_s3_fetch(phdf_number());
    if (is_wp_error($body)) {
        return $body;
    }

    nocache_headers();
    header('Content-Type: image/png');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('X-Content-Type-Options: nosniff');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    while (ob_get_level()) {
        ob_end_clean();
    }
    echo $body;
    exit;
}

if (!empty($_POST['phdf_token'])) {
    $token  = isset($_POST['turnstile']) ? wp_unslash($_POST['turnstile']) : '';
    $result = phdf_issue_token($token);
    if (is_wp_error($result)) {
        phdf_json_error($result);
    }
    nocache_headers();
    header('Content-Type: application/json; charset=utf-8');
    echo wp_json_encode($result);
    exit;
}

if (!empty($_GET['phdf_dl'])) {
    $result = phdf_stream(isset($_GET['t']) ? wp_unslash($_GET['t']) : '');
    if (is_wp_error($result)) {
        phdf_json_error($result);
    }
}

function phdf_img($suffix) {
    $cfg = phdf_cfg();
    return $cfg['preview_base'] . 'daily-free-' . phdf_number() . '-' . $suffix . '.jpg';
}

function phdf_sc_a() {
    return '<div class="phdf-home-a">'
        . '<img class="pngheaven-daily-free-image" src="' . esc_url(phdf_img('a')) . '" alt="Free PNG of the Day">'
        . '</div>';
}

function phdf_sc_b() {
    return '<img class="pngheaven-daily-free-image" src="' . esc_url(phdf_img('b')) . '" alt="Free PNG of the Day Preview" loading="lazy" style="display:block;width:100%;height:auto;margin:0;padding:0;">';
}
function phdf_sc_number() {
    return esc_html(phdf_number());
}
function phdf_sc_date() {
    $today = new DateTime('today', new DateTimeZone('Asia/Seoul'));
    return esc_html($today->format('l, F j, Y'));
}
function phdf_sc_download() {
    return '<div class="pngheaven-daily-download" data-phdf-download data-phdf-ver="2.2.0">'
        . '<button type="button" class="pngheaven-daily-download__btn">Download Free PNG</button>'
        . '<div class="pngheaven-daily-download__panel" hidden>'
        . '<p class="pngheaven-daily-download__hint">Quick check so this stays free for humans — no account needed.</p>'
        . '<div class="pngheaven-daily-download__widget"></div>'
        . '<p class="pngheaven-daily-download__status" hidden></p>'
        . '</div></div>';
}

add_shortcode('daily_free_a', 'phdf_sc_a');
add_shortcode('daily_free_b', 'phdf_sc_b');
add_shortcode('daily_free_number', 'phdf_sc_number');
add_shortcode('daily_free_date', 'phdf_sc_date');
add_shortcode('daily_free_download', 'phdf_sc_download');

function phdf_expand($content) {
    if (!is_string($content) || strpos($content, '[daily_free') === false) {
        return $content;
    }
    return do_shortcode($content);
}
add_filter('widget_text', 'phdf_expand');
add_filter('woocommerce_short_description', 'phdf_expand');
add_filter('elementor/widget/render_content', 'phdf_expand');
add_filter('elementor/frontend/the_content', 'phdf_expand');

function phdf_needs_assets() {
    if (!is_singular()) {
        return false;
    }
    $post = get_post();
    if (!$post) {
        return false;
    }
    if (strpos($post->post_content, '[daily_free') !== false) {
        return true;
    }
    $elementor = get_post_meta($post->ID, '_elementor_data', true);
    return is_string($elementor) && strpos($elementor, 'daily_free') !== false;
}

function phdf_enqueue() {
    if (!phdf_needs_assets()) {
        return;
    }
    $cfg = phdf_cfg();

    $css = <<<'CSS'

    /* Home - Daily Free Promo Banner */
    
    .phdf-home-a {
    
      display: block !important;
    
      width: 100% !important;
    
      max-width: none !important;
    
      margin: 0 !important;
    
      padding: 0 !important;
    
      line-height: 0 !important;
    
    }
    
    .phdf-home-a .pngheaven-daily-free-image {
    
      display: block !important;
    
      width: 100% !important;
    
      max-width: none !important;
    
      height: auto !important;
    
      margin: 0 !important;
    
      padding: 0 !important;
    
    }
    
    /* WoodMart Promo Banner content wrapper 안의 기본 여백 제거 */
    
    .wd-banner:has(.phdf-home-a) .wrapper-content-banner,
    
    .wd-banner:has(.phdf-home-a) .banner-inner,
    
    .wd-banner:has(.phdf-home-a) .banner-content {
    
      padding: 0 !important;
    
      margin: 0 !important;
    
    }
    
    .ph-daily-hero { position: relative; }
    
    .pngheaven-daily-download {
  position: absolute;
  top: 28px;
  right: 28px;
  z-index: 5;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
.pngheaven-daily-download__btn {
  display: block !important;
  background: #6b7f5a !important;
  color: #fff !important;
  border: 0 !important;
  border-radius: 10px !important;
  padding: 14px 20px !important;
  font-size: 14px !important;
  font-weight: 800 !important;
  cursor: pointer !important;
  box-shadow: 0 8px 20px rgba(0,0,0,.18) !important;
  min-width: 190px !important;
  min-height: 46px !important;
}
.pngheaven-daily-download__btn:hover,
.pngheaven-daily-download__btn:focus {
  background: #5d704e !important;
  color: #fff !important;
}
.pngheaven-daily-download__panel {
  padding: 14px 16px;
  background: #fff;
  border: 1px solid #e6e0d4;
  border-radius: 12px;
  width: min(320px, calc(100vw - 64px));
  box-shadow: 0 10px 28px rgba(0,0,0,.16);
}
.pngheaven-daily-download__hint {
  margin: 0 0 12px;
  font-size: 13px;
  color: #555;
}
.pngheaven-daily-download__status { margin: 12px 0 0; font-size: 13px; color: #444; }
.pngheaven-daily-download__status.is-error { color: #a94442; }
@media (max-width: 768px) {
  .pngheaven-daily-download { top: 16px; right: 16px; left: 16px; align-items: stretch; }
  .pngheaven-daily-download__btn { width: 100%; }
  .pngheaven-daily-download__panel { width: 100%; }
}
CSS;

    $js = <<<'JS'
(function () {
  var cfg = window.phdfDaily || {};
  var root = document.querySelector('[data-phdf-download]');
  if (!root || root.getAttribute('data-phdf-bound')) return;
  root.setAttribute('data-phdf-bound', '1');

  var btn = root.querySelector('.pngheaven-daily-download__btn');
  var panel = root.querySelector('.pngheaven-daily-download__panel');
  var widget = root.querySelector('.pngheaven-daily-download__widget');
  var status = root.querySelector('.pngheaven-daily-download__status');
  var widgetId = null;
  var busy = false;
  var locked = false;

  function setStatus(message, isError) {
    if (!status) return;
    status.hidden = !message;
    status.textContent = message || '';
    status.classList.toggle('is-error', !!isError);
  }

  function stopTurnstile() {
    if (window.turnstile && widgetId !== null) {
      try { window.turnstile.remove(widgetId); } catch (e) {}
      widgetId = null;
    }
    if (widget) widget.innerHTML = '';
  }

  function fail(message) {
    busy = false;
    btn.disabled = false;
    stopTurnstile();
    setStatus(message, true);
  }

  function saveBlob(blob, filename) {
    var objectUrl = URL.createObjectURL(blob);
    var a = document.createElement('a');
    a.href = objectUrl;
    a.download = filename || 'pngheaven-free.png';
    document.body.appendChild(a);
    a.click();
    a.remove();
    setTimeout(function () { URL.revokeObjectURL(objectUrl); }, 1000);
  }

  function requestDownload(token) {
    if (busy) return;
    busy = true;
    locked = true;
    btn.disabled = true;
    setStatus('Preparing your download…', false);

    fetch(window.location.href, {
      method: 'POST',
      credentials: 'same-origin',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
      body: 'phdf_token=1&turnstile=' + encodeURIComponent(token)
    })
      .then(function (res) {
        return res.json().then(function (body) { return { ok: res.ok, body: body }; });
      })
      .then(function (result) {
        if (!result.ok || !result.body || !result.body.url) {
          throw new Error((result.body && result.body.message) || 'Download could not start. Try again.');
        }
        setStatus('Download starting…', false);
        return fetch(result.body.url, { credentials: 'same-origin' });
      })
      .then(function (res) {
        if (!res.ok) {
          return res.json().catch(function () { return {}; }).then(function (body) {
            throw new Error((body && body.message) || 'Download could not start. Try again.');
          });
        }
        var type = (res.headers.get('Content-Type') || '').toLowerCase();
        if (type.indexOf('image/png') === -1) {
          throw new Error('Download could not start. Try again.');
        }
        var match = (res.headers.get('Content-Disposition') || '').match(/filename="?([^"]+)"?/i);
        var filename = match ? match[1] : 'pngheaven-free.png';
        return res.blob().then(function (blob) {
          saveBlob(blob, filename);
          stopTurnstile();
          if (panel) panel.hidden = true;
          setStatus('Download started.', false);
          busy = false;
          btn.disabled = false;
        });
      })
      .catch(function (err) {
        fail(err.message || 'Download could not start. Try again.');
      });
  }

  function onToken(token) {
    if (!token || busy || locked) return;
    requestDownload(token);
  }

  btn.addEventListener('click', function () {
    if (busy) return;
    locked = false;
    if (!cfg.siteKey) {
      setStatus('Download is not configured yet.', true);
      if (panel) panel.hidden = false;
      return;
    }
    if (panel) panel.hidden = false;
    setStatus('', false);
    if (!window.turnstile) {
      setStatus('Security check failed to load. Refresh and try again.', true);
      return;
    }
    stopTurnstile();
    widgetId = window.turnstile.render(widget, {
      sitekey: cfg.siteKey,
      appearance: 'interaction-only',
      callback: onToken,
      'error-callback': function () {
        fail('Security check failed. Try again.');
      }
    });
  });
})();
JS;

    wp_register_style('phdf-download', false, array(), '2.2.0');
    wp_enqueue_style('phdf-download');
    wp_add_inline_style('phdf-download', $css);

    wp_enqueue_script(
        'cloudflare-turnstile',
        'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit',
        array(),
        null,
        true
    );

    wp_register_script('phdf-download', false, array('cloudflare-turnstile'), '2.2.0', true);
    wp_enqueue_script('phdf-download');
    wp_add_inline_script(
        'phdf-download',
        'window.phdfDaily = ' . wp_json_encode(array(
            'siteKey' => $cfg['turnstile_site_key'],
        )) . ';',
        'before'
    );
    wp_add_inline_script('phdf-download', $js);
}
add_action('wp_enqueue_scripts', 'phdf_enqueue', 20);