Changeset 3769546
- Timestamp:
- 10/27/2026 09:16:23 PM (4 days ago)
- Location:
- cookieflame
- Files:
-
- 2 added
- 18 edited
- 1 copied
-
tags/5.3.0 (copied) (copied from cookieflame/trunk )
-
tags/5.3.0/assets/css/admin.css (modified) (7 diffs)
-
tags/5.3.0/assets/js/admin.js (modified) (22 diffs)
-
tags/5.3.0/assets/js/cookieconsent-discovery.js (modified) (3 diffs)
-
tags/5.3.0/assets/js/cookieconsent-discovery.min.js (modified) (2 diffs)
-
tags/5.3.0/assets/js/cookieconsent.js (modified) (6 diffs)
-
tags/5.3.0/assets/js/cookieconsent.min.js (modified) (2 diffs)
-
tags/5.3.0/cookieflame.php (modified) (15 diffs)
-
tags/5.3.0/includes/consent-tools.php (added)
-
tags/5.3.0/readme.txt (modified) (3 diffs)
-
tags/5.3.0/uninstall.php (modified) (1 diff)
-
trunk/assets/css/admin.css (modified) (7 diffs)
-
trunk/assets/js/admin.js (modified) (22 diffs)
-
trunk/assets/js/cookieconsent-discovery.js (modified) (3 diffs)
-
trunk/assets/js/cookieconsent-discovery.min.js (modified) (2 diffs)
-
trunk/assets/js/cookieconsent.js (modified) (6 diffs)
-
trunk/assets/js/cookieconsent.min.js (modified) (2 diffs)
-
trunk/cookieflame.php (modified) (15 diffs)
-
trunk/includes/consent-tools.php (added)
-
trunk/readme.txt (modified) (3 diffs)
-
trunk/uninstall.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
cookieflame/tags/5.3.0/assets/css/admin.css
r3766806 r3769546 394 394 } 395 395 396 /* S ource column*/396 /* Status column: one label, then the actions, one per line */ 397 397 .cf-admin-source-cell { 398 398 font-size: 12px; … … 403 403 margin-top: 1px; 404 404 } 405 .cf-admin-status-line + .cf-admin-status-line { 406 margin-top: 3px; 407 } 408 .cf-admin-status-where { 409 color: #646970; 410 line-height: 1.4; 411 } 405 412 .cf-admin-source-link { 406 font-size: 1 1px;407 color: # 646970;413 font-size: 12px; 414 color: #2271b1; 408 415 text-decoration: none; 409 416 cursor: pointer; 410 417 display: inline-block; 411 margin-top: 2px;412 418 transition: color .15s; 413 419 } 414 420 .cf-admin-source-link:hover { 415 color: # 2271b1;421 color: #135e96; 416 422 text-decoration: underline; 423 } 424 .cf-admin-source-link-main { 425 font-weight: 600; 417 426 } 418 427 … … 474 483 align-items: center; 475 484 gap: 4px; 476 font-size: 11px; 477 font-weight: 600; 485 font-size: 12px; 486 font-weight: 600; 487 line-height: 20px; 488 padding: 0 8px; 489 border-radius: 3px; 478 490 } 479 491 .cf-admin-badge-known, 480 492 .cf-admin-badge-ai { 481 color: #00a32a; 493 color: #00701f; 494 background: #e6f4e9; 482 495 } 483 496 .cf-admin-badge-edited { 484 color: #2271b1; 497 color: #135e96; 498 background: #e9f1fa; 485 499 } 486 500 .cf-admin-badge-locked { 487 color: #996800; 501 color: #8a5b00; 502 background: #fcf3e1; 488 503 } 489 504 .cf-admin-badge-unclassified { 490 color: #d63638; 505 color: #8a5b00; 506 background: #fff; 507 box-shadow: inset 0 0 0 1px #dba617; 491 508 } 492 509 … … 859 876 -webkit-user-select: text; 860 877 } 878 .cf-admin-help-list p { 879 margin: 0 0 8px; 880 line-height: 1.5; 881 } 882 .cf-admin-help-list p:last-child { 883 margin-bottom: 0; 884 } 861 885 @keyframes cf-admin-fade-in { 862 886 from { opacity: 0; } … … 1942 1966 } 1943 1967 1944 /* Lock toggle (unstyled button) */ 1945 .cf-admin-lock-toggle { 1946 background: none; 1947 border: none; 1948 cursor: pointer; 1968 /* Lock as correct: a labelled button that fills in when locked */ 1969 .cf-admin-source-cell .button.cf-admin-lock-toggle { 1970 display: inline-flex; 1971 align-items: center; 1972 gap: 3px; 1973 font-size: 12px; 1974 min-height: 24px; 1975 line-height: 22px; 1976 padding: 0 8px 0 6px; 1977 } 1978 .cf-admin-lock-toggle .dashicons { 1949 1979 font-size: 14px; 1950 padding: 0 2px; 1951 vertical-align: middle; 1980 width: 14px; 1981 height: 14px; 1982 } 1983 .cf-admin-source-cell .button.cf-admin-lock-toggle.is-locked { 1984 background: #fcf3e1; 1985 border-color: #dba617; 1986 color: #8a5b00; 1952 1987 } 1953 1988 … … 1999 2034 font-size: 12px; 2000 2035 padding: 8px 12px; 2036 } 2037 2038 /* Remove…: asks why, in a bar under the row */ 2039 .cf-admin-inline-bar-remove { 2040 background: #f6f7f7; 2041 border-left: 3px solid #8c8f94; 2042 font-size: 13px; 2043 padding: 10px 14px; 2044 } 2045 .cf-admin-remove-choices { 2046 display: flex; 2047 flex-wrap: wrap; 2048 align-items: stretch; 2049 gap: 8px; 2050 margin-top: 8px; 2051 } 2052 .cf-admin-remove-choices .button { 2053 display: flex; 2054 flex-direction: column; 2055 align-items: flex-start; 2056 gap: 2px; 2057 max-width: 380px; 2058 height: auto; 2059 padding: 6px 12px; 2060 line-height: 1.4; 2061 text-align: left; 2062 white-space: normal; 2063 } 2064 .cf-admin-remove-choices .button span, 2065 .cf-admin-remove-hint { 2066 font-size: 12px; 2067 color: #646970; 2068 } 2069 .cf-admin-remove-hint { 2070 display: block; 2071 margin-top: 2px; 2072 } 2073 .cf-admin-remove-cancel { 2074 align-self: center; 2075 margin-left: 4px; 2001 2076 } 2002 2077 … … 2053 2128 } 2054 2129 2055 /* Not-active indicator label */2056 .cf-admin-not-active-label {2057 font-size: 11px;2058 color: #646970;2059 display: inline-block;2060 margin-top: 3px;2061 }2062 2063 2130 /* Origin column cell */ 2064 2131 .cf-admin-origin-cell { 2065 2132 font-size: 12px; 2066 }2067 2068 /* Ignore link — muted by default */2069 .cf-admin-ignore-cookie.cf-admin-source-link {2070 color: #888;2071 2133 } 2072 2134 -
cookieflame/tags/5.3.0/assets/js/admin.js
r3766806 r3769546 148 148 * Queue a DELETE for a single cookie via the REST endpoint. 149 149 */ 150 function queueDelete(cookieName, opts, onDone ) {150 function queueDelete(cookieName, opts, onDone, onFail) { 151 151 // opts is optional: queueDelete(name, fn) or queueDelete(name, {dismissed:true}, fn) 152 if (typeof opts === "function") { on Done = opts; opts = {}; }152 if (typeof opts === "function") { onFail = onDone; onDone = opts; opts = {}; } 153 153 opts = opts || {}; 154 154 fetch(cookieflameAdmin.cookieUrl + "/" + encodeURIComponent(cookieName), { … … 164 164 .catch(function (err) { 165 165 cookieflameNotice("Failed to remove \"" + cookieName + "\": " + err.message, "error"); 166 if (onFail) onFail(); 166 167 }); 167 168 } … … 463 464 } 464 465 466 /** 467 * Whether a cookie in the admin's own browser is another consent tool's 468 * cookie when that tool doesn't run on this site (its plugin isn't active 469 * and its script hasn't been seen on the site's pages). Browser extensions 470 * that get around consent banners write these. Same rules as the visitor 471 * check in cookieconsent.js, without the page context. 472 */ 473 function isVisitorOnlyCookie(name) { 474 var rules = cookieflameAdmin && cookieflameAdmin.visitorCookieRules; 475 if (!rules || !rules.tools) return false; 476 if (rules.allow && rules.allow.indexOf(name) !== -1) return false; 477 var domains = cookieflameAdmin.siteScriptDomains || []; 478 for (var t = 0; t < rules.tools.length; t++) { 479 var tool = rules.tools[t], hit = (tool.n || []).indexOf(name) !== -1; 480 for (var p = 0; !hit && p < (tool.p || []).length; p++) { 481 if (name.indexOf(tool.p[p]) === 0) hit = true; 482 } 483 if (!hit) continue; 484 for (var d = 0; d < domains.length; d++) { 485 for (var k = 0; k < (tool.d || []).length; k++) { 486 var host = String(domains[d]).toLowerCase(), dom = tool.d[k]; 487 if (host === dom || host.slice(-dom.length - 1) === "." + dom) return false; 488 } 489 } 490 return true; 491 } 492 return false; 493 } 494 465 495 /* ═══════════════════════════════════════════ 466 496 RENDER SCAN TABLE … … 650 680 var CAT_ORDER = { necessary: 0, preferences: 1, analytics: 2, marketing: 3, unclassified: 4 }; 651 681 682 var ignoredSet = {}; 683 var ignoredList = (cookieflameAdmin && cookieflameAdmin.ignoredCookies) || []; 684 for (var il = 0; il < ignoredList.length; il++) { 685 if (ignoredList[il] && ignoredList[il].name) ignoredSet[ignoredList[il].name] = true; 686 } 687 652 688 // Pre-process: build row data objects for sorting 653 689 var rowData = []; … … 660 696 var custom = findCustom(name); 661 697 var builtin = identifyBuiltIn(name); 698 699 // Cookies you haven't classified stay out of the table when they are on 700 // the Permanently Ignored list, or when only your own browser carries 701 // them and they belong to a consent tool that doesn't run on this site. 702 if (!custom && ignoredSet[name]) continue; 703 if (!custom && !beaconData[name] && !cookieOriginMap[name] && isVisitorOnlyCookie(name)) continue; 662 704 663 705 // Determine source (same logic as before) … … 794 836 divider.innerHTML = '<td colspan="7">' + 795 837 '<span class="cf-admin-cat-dot" style="background:' + (CAT_COLORS[lastCat] || "#a7aaad") + '"></span>' + 796 '<span class="cf-admin-cat-label">' + esc(lastCat .charAt(0).toUpperCase() + lastCat.slice(1)) + '</span>' +838 '<span class="cf-admin-cat-label">' + esc(lastCat === "unclassified" ? "Not identified yet" : lastCat.charAt(0).toUpperCase() + lastCat.slice(1)) + '</span>' + 797 839 '<span class="cf-admin-cat-count">(' + catCount + ')</span>' + 798 840 '</td>'; … … 800 842 } 801 843 802 // Source column content 803 var removeTip = 'Removes this cookie from the Cookie Manager. It will reappear as a new unclassified cookie if a visitor still has it in their browser. Use this if you classified it incorrectly and want to start again.'; 804 var ignoreTip = 'Permanently hides this cookie from the Cookie Manager. Visitor sessions will silently skip it and it will not trigger email notifications. Use this for cookies that are not from your site, such as those set by browser extensions. If you later reinstall the service that set it, Start Cookie Discovery will detect it again and automatically remove it from the ignore list. You can also restore ignored cookies manually from the Ignored Cookies panel at the bottom of this page.'; 805 var removeHtml = '<br><a href="#" class="cf-admin-delete-cookie cf-admin-source-link" data-name="' + esc(rd.name) + '">Remove</a>' + 806 ' <button type="button" class="cf-admin-help-btn cf-admin-help-btn-sm" ' + 807 'data-help-title="Remove cookie" data-help="' + esc(removeTip) + '">?</button>' + 808 '<br><a href="#" class="cf-admin-ignore-cookie cf-admin-source-link" data-name="' + esc(rd.name) + '">Ignore permanently</a>' + 809 ' <button type="button" class="cf-admin-help-btn cf-admin-help-btn-sm" ' + 810 'data-help-title="Ignore permanently" data-help="' + esc(ignoreTip) + '">?</button>'; 811 812 var sourceHtml; 813 814 // Helper: lock badge + toggle for classified sources 815 function _lockBadgeHtml(src, lock, name) { 816 var badge, lockIcon, lockTip, aiLabel, reIdLabel; 817 // Determine badge 818 if (lock === "locked") { 819 badge = '<span class="cf-admin-badge-locked">🔒 Locked</span>'; 820 } else if (lock === "edited") { 821 badge = '<span class="cf-admin-badge-edited">✎ Customised</span>'; 822 } else { 823 // Managed: show original source label 824 if (src === "ai") { aiLabel = "Auto-Identified"; } 825 else if (src === "discovered") { aiLabel = "Classified"; } 826 else if (src === "manual") { aiLabel = "Manual"; } 827 else if (src === "custom") { aiLabel = "Edited"; } 828 else { aiLabel = "Classified"; } 829 badge = '<span class="cf-admin-badge-ai">✓ ' + aiLabel + '</span>'; 830 } 831 // Lock toggle button 832 lockIcon = lock === "locked" ? "🔒" : "🔓"; 833 lockTip = lock === "locked" 834 ? "This cookie is locked. Auto-Identify All will skip it. Click to unlock." 835 : "Click to lock this cookie. Locking prevents Auto-Identify All from changing your classification."; 836 badge += ' <button type="button" class="cf-admin-lock-toggle" data-name="' + esc(name) + '" title="' + esc(lockTip) + '" style="opacity:' + (lock === "locked" ? '1' : '0.4') + ';">' + lockIcon + '</button>'; 837 // Re-identify vs Auto-Identify label 838 reIdLabel = (src === "ai" || lock === "edited") ? "Re-identify" : "Auto-Identify"; 839 if (cookieflameAdmin.isPremium) { 840 var greyStyle = lock === "locked" ? ' style="color:#999;cursor:default;"' : ''; 841 badge += '<br><a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(name) + '"' + greyStyle + '>' + reIdLabel + '</a>'; 842 } 843 return badge; 844 } 845 846 if (rd.source === "custom") { 847 sourceHtml = _lockBadgeHtml("custom", rd.lock, rd.name); 848 sourceHtml += '<br><a href="#" class="cf-admin-revert-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Revert to default</a>'; 849 sourceHtml += removeHtml; 850 } else if (rd.source === "ai") { 851 sourceHtml = _lockBadgeHtml("ai", rd.lock, rd.name); 852 sourceHtml += removeHtml; 853 } else if (rd.source === "manual") { 854 sourceHtml = _lockBadgeHtml("manual", rd.lock, rd.name); 855 sourceHtml += removeHtml; 856 } else if (rd.source === "discovered") { 857 sourceHtml = _lockBadgeHtml("discovered", rd.lock, rd.name); 858 sourceHtml += removeHtml; 859 } else if (rd.source === "builtin") { 860 sourceHtml = '<span class="cf-admin-badge-known">✓ Known</span>'; 861 sourceHtml += '<br><a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Auto-Identify</a>' + proRowPill; 862 sourceHtml += removeHtml; 863 } else if (rd.isBeacon) { 864 sourceHtml = '<span class="cf-admin-badge-unclassified">⚠ Reported</span>'; 865 sourceHtml += '<br><a href="#" class="cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Auto-Identify</a>' + proRowPill; 866 sourceHtml += removeHtml; 867 } else { 868 sourceHtml = '<span class="cf-admin-badge-unclassified">⚠ Unclassified</span>'; 869 sourceHtml += '<br><a href="#" class="cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Auto-Identify</a>' + proRowPill; 870 sourceHtml += removeHtml; 871 } 872 873 // "Not active" label in Source column 874 if (!rd.inBrowser) { 875 var notActiveLabel = rd.isBeacon ? "Reported by visitors" : "Detected, not active"; 876 var notActiveTip = rd.isBeacon 877 ? "This cookie was found by visitors browsing your site. It is not set in your admin browser because marketing and analytics scripts do not run in the admin area. Classify it so CookieFlame manages it correctly when visitors encounter it." 878 : "This cookie was found during a discovery scan on your site but is not set in your browser right now. This is normal. You are viewing the Cookie Manager in the admin area where marketing and analytics scripts do not run. The cookie will be set for visitors on the frontend when they interact with the service or consent to its category. You should still classify it so CookieFlame manages it correctly when visitors encounter it."; 879 sourceHtml += '<br><span class="cf-admin-not-active-label">' + notActiveLabel + 880 ' <button type="button" class="cf-admin-help-btn cf-admin-help-btn-sm" ' + 881 'data-help-title="' + esc(notActiveLabel) + '" data-help="' + esc(notActiveTip) + '">?</button></span>'; 882 } 883 884 // Residual cookie badge (deactivated/removed plugin) 844 // Status column: one label, then the actions (5.3.0). 885 845 var residual = residualMap[rd.name]; 886 if (residual) { 887 sourceHtml += '<br><span class="cf-admin-badge-residual" data-residual-name="' + esc(rd.name) + '">🕑 Residual</span>' + 888 '<span class="cf-admin-residual-from">from ' + esc(residual.plugin) + '</span>'; 889 } 846 var sourceHtml = statusCellHtml(rd, beaconData[rd.name], residual, proRowPill); 890 847 891 848 // Recommended label below category dropdown … … 978 935 } 979 936 980 // Bind remove buttons for manually added cookies 981 // Bind per-row delete buttons (inline confirmation, no confirm() dialog) 982 var delBtns = tbody.querySelectorAll(".cf-admin-delete-cookie"); 983 for (var rb = 0; rb < delBtns.length; rb++) { 984 delBtns[rb].addEventListener("click", function (e) { 985 e.preventDefault(); 986 var link = this; 987 var n = link.getAttribute("data-name"); 988 var tr = link.closest("tr"); 989 990 // If already showing confirmation, ignore 991 if (link.getAttribute("data-confirming")) return; 992 link.setAttribute("data-confirming", "1"); 993 994 // Replace link text with inline confirmation 995 var origHtml = link.innerHTML; 996 link.style.display = "none"; 997 var confirmSpan = document.createElement("span"); 998 confirmSpan.className = "cf-admin-meta-hint"; 999 confirmSpan.innerHTML = 'Remove <strong>' + esc(n) + '</strong>? ' + 1000 '<a href="#" class="cf-admin-confirm-yes cf-admin-link-danger">Yes, remove</a>' + 1001 ' / <a href="#" class="cf-admin-confirm-no cf-admin-link-cancel">Cancel</a>'; 1002 link.parentNode.insertBefore(confirmSpan, link.nextSibling); 1003 1004 confirmSpan.querySelector(".cf-admin-confirm-yes").addEventListener("click", function (ev) { 1005 ev.preventDefault(); 1006 var source = tr ? (tr.getAttribute("data-source") || "") : ""; 1007 // Track as dismissed for builtin cookies (hides from table) 1008 if (source === "builtin" && dismissedCookies.indexOf(n) === -1) { 1009 dismissedCookies.push(n); 1010 } 1011 // Use DELETE endpoint 1012 var delOpts = source === "builtin" ? { dismissed: true } : {}; 1013 queueDelete(n, delOpts, function () { 1014 // Remove residual explanation bar if present 1015 var resBar = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]'); 1016 if (resBar) resBar.remove(); 1017 if (tr) tr.remove(); 1018 cookieflameNotice("\"" + n + "\" removed.", "success"); 1019 }); 1020 }); 1021 1022 confirmSpan.querySelector(".cf-admin-confirm-no").addEventListener("click", function (ev) { 1023 ev.preventDefault(); 1024 confirmSpan.remove(); 1025 link.style.display = ""; 1026 link.removeAttribute("data-confirming"); 1027 }); 1028 }); 937 // Bind each row's Remove… link and Lock as correct button 938 var statusCells = tbody.querySelectorAll("td.cf-admin-source-cell"); 939 for (var cellIdx = 0; cellIdx < statusCells.length; cellIdx++) { 940 bindStatusCell(statusCells[cellIdx], statusCells[cellIdx].closest("tr")); 1029 941 } 1030 942 … … 1035 947 e.preventDefault(); 1036 948 identifySingleWithAi(this); 1037 });1038 }1039 1040 // Bind per-row "Ignore permanently" buttons1041 var ignoreBtns = tbody.querySelectorAll(".cf-admin-ignore-cookie");1042 for (var ig = 0; ig < ignoreBtns.length; ig++) {1043 ignoreBtns[ig].addEventListener("click", function (e) {1044 e.preventDefault();1045 var link = this;1046 var n = link.getAttribute("data-name");1047 var tr = link.closest("tr");1048 1049 if (link.getAttribute("data-confirming")) return;1050 link.setAttribute("data-confirming", "1");1051 1052 // Check beacon context for confidence-aware message.1053 var bc = getBeaconContext(n);1054 var isLikelyExtension = bc && bc.pre_existing;1055 var confirmMsg;1056 if (isLikelyExtension) {1057 confirmMsg = 'This appears to be a browser extension cookie. ' +1058 'It will be permanently hidden from notifications and your cookie declaration.';1059 } else {1060 confirmMsg = 'This cookie and the script that sets it will continue to fire without visitor consent. ' +1061 'It will not appear in your cookie declaration or notifications.';1062 }1063 1064 link.style.display = "none";1065 var confirmSpan = document.createElement("span");1066 confirmSpan.className = "cf-admin-meta-hint";1067 confirmSpan.innerHTML = '<span class="cf-admin-link-warning">' + esc(confirmMsg) + '</span><br>' +1068 '<a href="#" class="cf-admin-ignore-yes cf-admin-link-danger">Yes, ignore permanently</a>' +1069 ' / <a href="#" class="cf-admin-ignore-no cf-admin-link-cancel">Cancel</a>';1070 link.parentNode.insertBefore(confirmSpan, link.nextSibling);1071 1072 confirmSpan.querySelector(".cf-admin-ignore-yes").addEventListener("click", function (ev) {1073 ev.preventDefault();1074 1075 // AJAX call to add to ignored list.1076 fetch(cookieflameAdmin.ignoredCookiesUrl, {1077 method: "POST",1078 headers: { "Content-Type": "application/json", "X-WP-Nonce": cookieflameAdmin.nonce },1079 credentials: "same-origin",1080 body: JSON.stringify({ action: "ignore", name: n })1081 })1082 .then(function (r) { return r.json(); })1083 .then(function (data) {1084 if (data.success) {1085 // Update local state.1086 cookieflameAdmin.ignoredCookies = data.ignored || [];1087 // Remove from in-memory data.1088 savedCustom = savedCustom.filter(function (c) { return c.name !== n; });1089 if (deletedCookies.indexOf(n) === -1) deletedCookies.push(n);1090 if (dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n);1091 // Remove row.1092 var resBarIg = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]');1093 if (resBarIg) resBarIg.remove();1094 if (tr) tr.remove();1095 // Refresh ignored section.1096 renderIgnoredSection();1097 cookieflameNotice("\"" + n + "\" permanently ignored.", "success");1098 }1099 })1100 .catch(function () {1101 cookieflameNotice("Could not ignore cookie. Please try again.", "error");1102 confirmSpan.remove();1103 link.style.display = "";1104 link.removeAttribute("data-confirming");1105 });1106 });1107 1108 confirmSpan.querySelector(".cf-admin-ignore-no").addEventListener("click", function (ev) {1109 ev.preventDefault();1110 confirmSpan.remove();1111 link.style.display = "";1112 link.removeAttribute("data-confirming");1113 });1114 });1115 }1116 1117 // Bind lock toggle buttons (padlock icon on classified cookies)1118 var lockBtns = tbody.querySelectorAll(".cf-admin-lock-toggle");1119 for (var lb = 0; lb < lockBtns.length; lb++) {1120 lockBtns[lb].addEventListener("click", function (e) {1121 e.preventDefault();1122 var cookieName = this.getAttribute("data-name");1123 var tr = this.closest("tr");1124 if (!tr) return;1125 var curLock = tr.getAttribute("data-lock") || "";1126 var newLock = curLock === "locked" ? "" : "locked";1127 tr.setAttribute("data-lock", newLock);1128 1129 // Update button icon, tooltip and opacity1130 this.innerHTML = newLock === "locked" ? "🔒" : "🔓";1131 this.title = newLock === "locked"1132 ? "This cookie is locked. Auto-Identify All will skip it. Click to unlock."1133 : "Click to lock this cookie. Locking prevents Auto-Identify All from changing your classification.";1134 this.style.opacity = newLock === "locked" ? "1" : "0.4";1135 1136 // Update badge1137 var sourceCell = tr.querySelector(".cf-admin-source-cell");1138 if (sourceCell) {1139 var badge = sourceCell.querySelector("[class^='cf-admin-badge']");1140 if (badge) {1141 if (newLock === "locked") {1142 badge.className = "cf-admin-badge-locked";1143 badge.innerHTML = "🔒 Locked";1144 } else {1145 var src = tr.getAttribute("data-source") || "";1146 var label = src === "ai" ? "Auto-Identified" : src === "discovered" ? "Classified" : src === "manual" ? "Manual" : "Edited";1147 badge.className = "cf-admin-badge-ai";1148 badge.innerHTML = "✓ " + label;1149 }1150 }1151 // Update Re-identify link grey state1152 var reIdLink = sourceCell.querySelector(".cf-admin-identify-link");1153 if (reIdLink) {1154 reIdLink.style.color = newLock === "locked" ? "#999" : "";1155 reIdLink.style.cursor = newLock === "locked" ? "default" : "";1156 }1157 }1158 1159 queueSave(cookieName, { lock: newLock });1160 949 }); 1161 950 } … … 1169 958 pluginCount + " CookieFlame, " + 1170 959 thirdPartyCount + " third-party, " + 1171 unknownCount + " unclassified).";960 unknownCount + " not identified yet)."; 1172 961 } 1173 962 … … 1184 973 // Render the permanently ignored cookies section. 1185 974 renderIgnoredSection(); 975 } 976 977 /* ═══════════════════════════════════════════ 978 STATUS COLUMN (5.3.0) 979 One label for where the cookie stands, then its actions: Lock as 980 correct (Pro), Auto-Identify or Re-identify, Revert to default, 981 and one Remove… link that asks why before it removes or ignores 982 the cookie. The explanations live in each link's hover text and 983 the Status column's help. 984 ═══════════════════════════════════════════ */ 985 986 var LOCK_TIP_OFF = "Press this once you've checked the vendor, category and purpose are right. CookieFlame won't change them after that, even when you re-identify."; 987 var LOCK_TIP_ON = "You've checked this cookie. CookieFlame won't change its vendor, category or purpose, even when you re-identify. Click to unlock."; 988 989 function statusLabelHtml(source, lock) { 990 if (source === "unknown") return '<span class="cf-admin-badge-unclassified">Not identified yet</span>'; 991 if (source === "builtin") return '<span class="cf-admin-badge-known">Known</span>'; 992 if (source === "manual") return '<span class="cf-admin-badge-edited">Added by you</span>'; 993 if (source === "custom" || lock === "edited") return '<span class="cf-admin-badge-edited">Changed by you</span>'; 994 if (source === "discovered") return '<span class="cf-admin-badge-known">Classified</span>'; 995 return '<span class="cf-admin-badge-ai">Auto-Identified</span>'; 996 } 997 998 function lockButtonInner(locked) { 999 return '<span class="dashicons dashicons-' + (locked ? "lock" : "unlock") + '" aria-hidden="true"></span>' + 1000 (locked ? "Locked by you" : "Lock as correct"); 1001 } 1002 1003 // Where a cookie nobody has identified yet came from. Pro 1.5.1+ marks 1004 // the cookies its clean scan added with found_by "clean_scan". 1005 function whereFoundText(rd, beacon) { 1006 if (beacon && beacon.found_by === "clean_scan") return "Found by your scan"; 1007 if (beacon) return "Reported by visitors"; 1008 if (rd.inBrowser) return "Seen in your browser"; 1009 return ""; 1010 } 1011 1012 function statusCellHtml(rd, beacon, residual, proPill) { 1013 var name = esc(rd.name); 1014 var classified = ["ai", "manual", "discovered", "custom"].indexOf(rd.source) !== -1; 1015 var line = function (html, cls, hidden) { 1016 return '<div class="cf-admin-status-line' + (cls ? " " + cls : "") + '"' + (hidden ? ' style="display:none;"' : "") + '>' + html + '</div>'; 1017 }; 1018 1019 var html = line(statusLabelHtml(rd.source, rd.lock)); 1020 var where = rd.source === "unknown" ? whereFoundText(rd, beacon) : ""; 1021 if (where) html += line(esc(where), "cf-admin-status-where"); 1022 1023 // Locking only matters to Pro, which is what re-identifies cookies. 1024 if (classified && cookieflameAdmin.isPremium) { 1025 var locked = rd.lock === "locked"; 1026 html += line('<button type="button" class="button button-small cf-admin-lock-toggle' + (locked ? " is-locked" : "") + '" data-name="' + name + '"' + 1027 ' aria-pressed="' + (locked ? "true" : "false") + '" title="' + esc(locked ? LOCK_TIP_ON : LOCK_TIP_OFF) + '">' + lockButtonInner(locked) + '</button>'); 1028 } 1029 1030 if (rd.source === "unknown") { 1031 html += line('<a href="#" class="cf-admin-ai-row-btn cf-admin-source-link cf-admin-source-link-main" data-name="' + name + '" title="Ask CookieFlame\'s service what this cookie is and fill in its details.">Auto-Identify</a>' + proPill); 1032 } else if (rd.source === "builtin") { 1033 html += line('<a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + name + '" title="Ask CookieFlame\'s service what this cookie is.">Auto-Identify</a>' + proPill); 1034 } else if (cookieflameAdmin.isPremium) { 1035 var reLabel = (rd.source === "ai" || rd.lock === "edited") ? "Re-identify" : "Auto-Identify"; 1036 html += line('<a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + name + '" title="Ask CookieFlame\'s service about this cookie again. Your own changes are only ever suggested, never replaced.">' + reLabel + '</a>', 1037 "cf-admin-status-reidentify", rd.lock === "locked"); 1038 } 1039 1040 if (rd.source === "custom") { 1041 html += line('<a href="#" class="cf-admin-revert-btn cf-admin-source-link" data-name="' + name + '" title="Go back to the vendor, category and purpose from CookieFlame\'s built-in list.">Revert to default</a>'); 1042 } 1043 html += line('<a href="#" class="cf-admin-remove-ask cf-admin-source-link" data-name="' + name + '" title="Asks whether your site no longer uses it, or it isn\'t from your site.">Remove…</a>'); 1044 1045 if (residual) { 1046 html += line('<span class="cf-admin-badge-residual" data-residual-name="' + name + '">🕑 Residual</span>' + 1047 '<span class="cf-admin-residual-from">from ' + esc(residual.plugin) + '</span>'); 1048 } 1049 return html; 1050 } 1051 1052 function setLockState(tr, lock) { 1053 var locked = lock === "locked"; 1054 tr.setAttribute("data-lock", lock); 1055 var btn = tr.querySelector(".cf-admin-lock-toggle"); 1056 if (btn) { 1057 btn.classList.toggle("is-locked", locked); 1058 btn.setAttribute("aria-pressed", locked ? "true" : "false"); 1059 btn.title = locked ? LOCK_TIP_ON : LOCK_TIP_OFF; 1060 btn.innerHTML = lockButtonInner(locked); 1061 } 1062 // A locked cookie isn't re-identified, so the link goes while it's locked. 1063 var reId = tr.querySelector(".cf-admin-status-reidentify"); 1064 if (reId) reId.style.display = locked ? "none" : ""; 1065 } 1066 1067 function bindStatusCell(cell, tr) { 1068 if (!cell || !tr) return; 1069 var removeLink = cell.querySelector(".cf-admin-remove-ask"); 1070 if (removeLink) { 1071 removeLink.addEventListener("click", function (e) { 1072 e.preventDefault(); 1073 openRemoveBar(tr); 1074 }); 1075 } 1076 var lockBtn = cell.querySelector(".cf-admin-lock-toggle"); 1077 if (lockBtn) { 1078 lockBtn.addEventListener("click", function (e) { 1079 e.preventDefault(); 1080 var newLock = (tr.getAttribute("data-lock") || "") === "locked" ? "" : "locked"; 1081 setLockState(tr, newLock); 1082 queueSave(tr.getAttribute("data-cookie-name"), { lock: newLock }); 1083 }); 1084 } 1085 } 1086 1087 /** 1088 * Remove… asks why, in a bar under the row. "My site doesn't use it any 1089 * more" removes the cookie, so it comes back if it's seen again. "It's 1090 * not from my site" puts it on the Permanently Ignored list. 1091 */ 1092 function openRemoveBar(tr) { 1093 var n = tr.getAttribute("data-cookie-name"); 1094 var tbody = tr.parentNode; 1095 if (!n || !tbody) return; 1096 var key = CSS.escape(n); 1097 var open = tbody.querySelector('.cf-admin-remove-bar[data-remove-for="' + key + '"]'); 1098 if (open) { open.remove(); return; } 1099 1100 var bc = getBeaconContext(n); 1101 var extHint = (bc && bc.pre_existing) 1102 ? '<em class="cf-admin-remove-hint">This one was already in a visitor\'s browser before your page loaded, which usually means an extension.</em>' 1103 : ""; 1104 1105 var bar = document.createElement("tr"); 1106 bar.className = "cf-admin-remove-bar"; 1107 bar.setAttribute("data-remove-for", n); 1108 bar.innerHTML = '<td colspan="7" class="cf-admin-inline-bar-remove">' + 1109 '<strong>Why are you removing <code>' + esc(n) + '</code>?</strong>' + 1110 '<div class="cf-admin-remove-choices">' + 1111 '<button type="button" class="button cf-admin-remove-unused"><strong>My site doesn\'t use it any more</strong>' + 1112 '<span>Taken off your list. If your site sets it again, it comes back to be identified.</span></button>' + 1113 '<button type="button" class="button cf-admin-remove-notmine"><strong>It\'s not from my site</strong>' + 1114 '<span>From a visitor\'s browser extension or another website. Hidden for good, and CookieFlame stops managing it. You can bring it back from Permanently Ignored at the bottom of this page.</span>' + 1115 extHint + '</button>' + 1116 '<a href="#" class="cf-admin-remove-cancel cf-admin-link-cancel">Cancel</a>' + 1117 '</div></td>'; 1118 tbody.insertBefore(bar, tr.nextSibling); 1119 1120 var buttons = bar.querySelectorAll("button"); 1121 var busy = function (on) { 1122 for (var i = 0; i < buttons.length; i++) buttons[i].disabled = on; 1123 }; 1124 var gone = function (msg) { 1125 var extras = tbody.querySelectorAll('[data-remove-for="' + key + '"], [data-residual-for="' + key + '"], [data-suggestion-for="' + key + '"]'); 1126 for (var i = 0; i < extras.length; i++) extras[i].remove(); 1127 tr.remove(); 1128 cookieflameNotice(msg, "success"); 1129 }; 1130 1131 bar.querySelector(".cf-admin-remove-unused").addEventListener("click", function () { 1132 busy(true); 1133 var source = tr.getAttribute("data-source") || ""; 1134 // A Known cookie still in your browser would show again at once, so it's hidden until seen again. 1135 if (source === "builtin" && dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1136 queueDelete(n, source === "builtin" ? { dismissed: true } : {}, function () { 1137 gone("\"" + esc(n) + "\" removed."); 1138 }, function () { busy(false); }); 1139 }); 1140 1141 bar.querySelector(".cf-admin-remove-notmine").addEventListener("click", function () { 1142 busy(true); 1143 fetch(cookieflameAdmin.ignoredCookiesUrl, { 1144 method: "POST", 1145 headers: { "Content-Type": "application/json", "X-WP-Nonce": cookieflameAdmin.nonce }, 1146 credentials: "same-origin", 1147 body: JSON.stringify({ action: "ignore", name: n }) 1148 }) 1149 .then(function (r) { return r.json(); }) 1150 .then(function (data) { 1151 if (!data || !data.success) throw new Error("not ignored"); 1152 cookieflameAdmin.ignoredCookies = data.ignored || []; 1153 savedCustom = savedCustom.filter(function (c) { return c.name !== n; }); 1154 if (deletedCookies.indexOf(n) === -1) deletedCookies.push(n); 1155 if (dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1156 gone("\"" + esc(n) + "\" moved to Permanently Ignored."); 1157 renderIgnoredSection(); 1158 }) 1159 .catch(function () { 1160 busy(false); 1161 cookieflameNotice("Could not ignore cookie. Please try again.", "error"); 1162 }); 1163 }); 1164 1165 bar.querySelector(".cf-admin-remove-cancel").addEventListener("click", function (e) { 1166 e.preventDefault(); 1167 bar.remove(); 1168 }); 1186 1169 } 1187 1170 … … 1583 1566 } 1584 1567 1568 // It's identified now, so where it came from no longer matters. 1569 var where = sourceCell.querySelector(".cf-admin-status-where"); 1570 if (where) where.remove(); 1571 1585 1572 // Update AI link to "Re-identify" and remove lock toggle if present. 1586 1573 var aiLink = sourceCell.querySelector(".cf-admin-identify-link, .cf-admin-ai-row-btn"); … … 1615 1602 if (aiBtn) aiBtn.addEventListener("click", function (e) { e.preventDefault(); identifySingleWithAi(this); }); 1616 1603 1617 // Delete (Remove) link — inline confirmation flow 1618 var delBtn = cell.querySelector(".cf-admin-delete-cookie"); 1619 if (delBtn) { 1620 delBtn.addEventListener("click", function (e) { 1621 e.preventDefault(); 1622 var link = this; 1623 var n = link.getAttribute("data-name"); 1624 if (link.getAttribute("data-confirming")) return; 1625 link.setAttribute("data-confirming", "1"); 1626 link.style.display = "none"; 1627 var confirmSpan = document.createElement("span"); 1628 confirmSpan.className = "cf-admin-meta-hint"; 1629 confirmSpan.innerHTML = 'Remove <strong>' + esc(n) + '</strong>? ' + 1630 '<a href="#" class="cf-admin-confirm-yes cf-admin-link-danger">Yes, remove</a>' + 1631 ' / <a href="#" class="cf-admin-confirm-no cf-admin-link-cancel">Cancel</a>'; 1632 link.parentNode.insertBefore(confirmSpan, link.nextSibling); 1633 confirmSpan.querySelector(".cf-admin-confirm-yes").addEventListener("click", function (ev) { 1634 ev.preventDefault(); 1635 var source = tr ? (tr.getAttribute("data-source") || "") : ""; 1636 if (source === "builtin" && dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1637 var delOpts = source === "builtin" ? { dismissed: true } : {}; 1638 queueDelete(n, delOpts, function () { 1639 var tbody = tr ? tr.parentNode : null; 1640 if (tbody) { 1641 var resBar = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]'); 1642 if (resBar) resBar.remove(); 1643 } 1644 if (tr) tr.remove(); 1645 cookieflameNotice("\"" + n + "\" removed.", "success"); 1646 }); 1647 }); 1648 confirmSpan.querySelector(".cf-admin-confirm-no").addEventListener("click", function (ev) { 1649 ev.preventDefault(); 1650 confirmSpan.remove(); 1651 link.style.display = ""; 1652 link.removeAttribute("data-confirming"); 1653 }); 1654 }); 1655 } 1656 1657 // Ignore link — inline confirmation flow 1658 var ignoreBtn = cell.querySelector(".cf-admin-ignore-cookie"); 1659 if (ignoreBtn) { 1660 ignoreBtn.addEventListener("click", function (e) { 1661 e.preventDefault(); 1662 var link = this; 1663 var n = link.getAttribute("data-name"); 1664 if (link.getAttribute("data-confirming")) return; 1665 link.setAttribute("data-confirming", "1"); 1666 link.style.display = "none"; 1667 var confirmSpan = document.createElement("span"); 1668 confirmSpan.className = "cf-admin-meta-hint"; 1669 confirmSpan.innerHTML = 'Permanently ignore <strong>' + esc(n) + '</strong>? ' + 1670 '<a href="#" class="cf-admin-ignore-yes cf-admin-link-warning">Yes, ignore permanently</a>' + 1671 ' / <a href="#" class="cf-admin-ignore-no cf-admin-link-cancel">Cancel</a>'; 1672 link.parentNode.insertBefore(confirmSpan, link.nextSibling); 1673 confirmSpan.querySelector(".cf-admin-ignore-yes").addEventListener("click", function (ev) { 1674 ev.preventDefault(); 1675 fetch(cookieflameAdmin.ignoredCookiesUrl, { 1676 method: "POST", 1677 headers: { "Content-Type": "application/json", "X-WP-Nonce": cookieflameAdmin.nonce }, 1678 credentials: "same-origin", 1679 body: JSON.stringify({ action: "ignore", name: n }) 1680 }) 1681 .then(function (r) { return r.json(); }) 1682 .then(function (data) { 1683 if (data.success) { 1684 cookieflameAdmin.ignoredCookies = data.ignored || []; 1685 savedCustom = savedCustom.filter(function (c) { return c.name !== n; }); 1686 if (deletedCookies.indexOf(n) === -1) deletedCookies.push(n); 1687 if (dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1688 var tbody = tr ? tr.parentNode : null; 1689 if (tbody) { 1690 var resBar = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]'); 1691 if (resBar) resBar.remove(); 1692 } 1693 if (tr) tr.remove(); 1694 renderIgnoredSection(); 1695 cookieflameNotice("\"" + n + "\" permanently ignored.", "success"); 1696 } 1697 }) 1698 .catch(function () { 1699 cookieflameNotice("Could not ignore cookie. Please try again.", "error"); 1700 confirmSpan.remove(); 1701 link.style.display = ""; 1702 link.removeAttribute("data-confirming"); 1703 }); 1704 }); 1705 confirmSpan.querySelector(".cf-admin-ignore-no").addEventListener("click", function (ev) { 1706 ev.preventDefault(); 1707 confirmSpan.remove(); 1708 link.style.display = ""; 1709 link.removeAttribute("data-confirming"); 1710 }); 1711 }); 1712 } 1713 1714 // Lock toggle 1715 var lockBtn = cell.querySelector(".cf-admin-lock-toggle"); 1716 if (lockBtn) { 1717 lockBtn.addEventListener("click", function (e) { 1718 e.preventDefault(); 1719 var n = this.getAttribute("data-name"); 1720 var currentLock = tr.getAttribute("data-lock") || ""; 1721 var newLock = currentLock === "locked" ? "" : "locked"; 1722 tr.setAttribute("data-lock", newLock); 1723 this.innerHTML = newLock === "locked" ? "🔒" : "🔓"; 1724 this.title = newLock === "locked" 1725 ? "This cookie is locked. Auto-Identify All will skip it. Click to unlock." 1726 : "Click to lock this cookie. Locking prevents Auto-Identify All from changing your classification."; 1727 this.style.opacity = newLock === "locked" ? "1" : "0.4"; 1728 var badge = cell.querySelector("[class^='cf-admin-badge']"); 1729 if (badge) { 1730 if (newLock === "locked") { 1731 badge.className = "cf-admin-badge-locked"; 1732 badge.innerHTML = "🔒 Locked"; 1733 } else { 1734 var src = tr.getAttribute("data-source") || ""; 1735 var label = src === "ai" ? "Auto-Identified" : src === "discovered" ? "Classified" : src === "manual" ? "Manual" : "Edited"; 1736 badge.className = "cf-admin-badge-ai"; 1737 badge.innerHTML = "✓ " + label; 1738 } 1739 } 1740 var reIdLink = cell.querySelector(".cf-admin-identify-link"); 1741 if (reIdLink) { 1742 reIdLink.style.color = newLock === "locked" ? "#999" : ""; 1743 reIdLink.style.cursor = newLock === "locked" ? "default" : ""; 1744 } 1745 queueSave(n, { lock: newLock }); 1746 }); 1747 } 1604 // Remove… link and Lock as correct button 1605 bindStatusCell(cell, tr); 1748 1606 1749 1607 // Residual badge toggle … … 2048 1906 if (badge) { 2049 1907 badge.className = "cf-admin-badge-ai"; 2050 badge. innerHTML = "✓Auto-Identified";1908 badge.textContent = "Auto-Identified"; 2051 1909 } 2052 1910 // Remove any confirmed tick left over. … … 2088 1946 lockPrompt.setAttribute("data-suggestion-for", n); 2089 1947 lockPrompt.innerHTML = '<td colspan="7" class="cf-admin-inline-bar-lock">' + 2090 'Lock this cookie to prevent future suggestions? ' +1948 'Lock it as correct, so CookieFlame stops suggesting changes? ' + 2091 1949 '<a href="#" class="cf-admin-lock-yes cf-admin-link-cancel" style="margin-left:4px;font-weight:600;">Yes</a>' + 2092 1950 ' / <a href="#" class="cf-admin-lock-no cf-admin-meta-hint" style="margin-left:4px;">No</a>' + … … 2099 1957 lockPrompt.querySelector(".cf-admin-lock-yes").addEventListener("click", function (ev) { 2100 1958 ev.preventDefault(); 2101 cookieRow.setAttribute("data-lock", "locked");1959 setLockState(cookieRow, "locked"); 2102 1960 queueSave(n, { lock: "locked" }); 2103 // Update padlock visuals.2104 var lockBtn = cookieRow.querySelector(".cf-admin-lock-toggle");2105 if (lockBtn) { lockBtn.innerHTML = "🔒"; lockBtn.style.opacity = "1"; }2106 var badge = cookieRow.querySelector("[class^='cf-admin-badge']");2107 if (badge) { badge.className = "cf-admin-badge-locked"; badge.innerHTML = "🔒 Locked"; }2108 var reIdLink = cookieRow.querySelector(".cf-admin-identify-link");2109 if (reIdLink) { reIdLink.style.color = "#999"; reIdLink.style.cursor = "default"; }2110 1961 lockPrompt.remove(); 2111 1962 }); … … 2212 2063 if (badge) { 2213 2064 badge.className = "cf-admin-badge-ai"; 2214 badge. innerHTML = "✓Auto-Identified";2065 badge.textContent = "Auto-Identified"; 2215 2066 } 2216 2067 } … … 2299 2150 2300 2151 if (expanded) { 2301 h += '<p class="cf-admin-ignored-desc">These cookies have been permanently excluded from passive monitoring. They will never trigger notifications or appear in your cookie declaration. C lick Restore to start monitoring a cookie again.</p>';2302 h += '<table class="widefat striped cf-admin-ignored-table"><thead><tr><th>Cookie</th><th> Ignored</th><th></th></tr></thead><tbody>';2152 h += '<p class="cf-admin-ignored-desc">These cookies have been permanently excluded from passive monitoring. They will never trigger notifications or appear in your cookie declaration. Cookies with a reason were ignored automatically because they came with a visitor\'s browser, such as another consent tool\'s cookie written by a browser extension. Click Restore to start monitoring a cookie again.</p>'; 2153 h += '<table class="widefat striped cf-admin-ignored-table"><thead><tr><th>Cookie</th><th>Why</th><th>Ignored</th><th></th></tr></thead><tbody>'; 2303 2154 for (var i = 0; i < ignored.length; i++) { 2304 2155 var ig = ignored[i]; … … 2306 2157 h += '<tr data-ignored-name="' + esc(ig.name) + '">'; 2307 2158 h += '<td><code>' + esc(ig.name) + '</code></td>'; 2159 h += '<td>' + esc(ig.reason || "Ignored by you") + '</td>'; 2308 2160 h += '<td>' + esc(when) + '</td>'; 2309 2161 h += '<td><button type="button" class="button button-small cf-admin-restore-ignored" data-name="' + esc(ig.name) + '">Restore</button></td>'; … … 2344 2196 .then(function (data) { 2345 2197 if (data.success) { 2198 // The server remembers restored automatic entries; mirror that so 2199 // the Cookie Manager shows the cookie again without a reload. 2200 var rules = cookieflameAdmin.visitorCookieRules; 2201 var wasAuto = (cookieflameAdmin.ignoredCookies || []).some(function (ig) { return ig.name === n && ig.auto; }); 2202 if (wasAuto && rules && rules.allow && rules.allow.indexOf(n) === -1) rules.allow.push(n); 2346 2203 cookieflameAdmin.ignoredCookies = data.ignored || []; 2347 2204 renderIgnoredSection(); … … 2712 2569 tr.setAttribute("data-source", "discovered"); 2713 2570 tr.className = ""; 2714 // Update source cell badge + lock icon after save completes2571 // Update the status label; it no longer needs identifying 2715 2572 var srcCell = tr.querySelector(".cf-admin-source-cell"); 2716 2573 if (srcCell) { … … 2718 2575 if (badge) { 2719 2576 badge.className = "cf-admin-badge-known"; 2720 badge. innerHTML = "✓Classified";2577 badge.textContent = "Classified"; 2721 2578 } 2579 var where = srcCell.querySelector(".cf-admin-status-where"); 2580 if (where) where.remove(); 2722 2581 } 2723 2582 } -
cookieflame/tags/5.3.0/assets/js/cookieconsent-discovery.js
r3766806 r3769546 1 1 /** 2 * CookieFlame Discovery Bundle v5. 1.12 * CookieFlame Discovery Bundle v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Admin-only script detection and discovery bar. Loaded … … 287 287 var seen = {}; 288 288 var hasBeforeSnapshot = Object.keys(beforeCookieSet).length > 0; 289 // The Cookie Manager doesn't list cookies that came with the browser 290 // (another consent tool's cookie, or one a browser extension wrote) or 291 // ignored ones, so they aren't counted here either. 292 var visitor = _cc.visitorCookies ? _cc.visitorCookies(current) : {}; 293 var ignoredNames = (window.cookieflameAdmin && window.cookieflameAdmin.ignoredCookieNames) || []; 289 294 for (var i = 0; i < current.length; i++) { 290 295 var name = current[i]; … … 292 297 seen[name] = true; 293 298 if (isSafeForCounter(name)) continue; 299 if (visitor[name] || ignoredNames.indexOf(name) !== -1) continue; 294 300 if (hasBeforeSnapshot && beforeCookieSet[name]) { 295 301 existing.push(name); -
cookieflame/tags/5.3.0/assets/js/cookieconsent-discovery.min.js
r3766806 r3769546 1 1 /** 2 * CookieFlame Discovery Bundle v5. 1.12 * CookieFlame Discovery Bundle v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Admin-only script detection and discovery bar. Loaded … … 13 13 * the core bundle despite the declared WordPress dependency. 14 14 */ 15 !function(){"use strict";var e=window.__ccInternal;if(e){var t=e.scriptLoaded,o=e.scriptLoadedUrls,n=e.hasCookie,i={"Google Analytics":function(){return t("googletagmanager.com/gtag")||t("google-analytics.com")||t("analytics.google.com")||n("_ga")},"Google Ads":function(){return t("googleads.g.doubleclick.net")||t("googleadservices.com")||t("googlesyndication.com")||n("_gcl_au")||n("_gcl_aw")},"Google Tag Manager":function(){return t("googletagmanager.com/gtm.js")||!!window.google_tag_manager},"Microsoft Ads":function(){return t("bat.bing.com")||!!window.uetq||n("_uetsid")||n("_uetvid")},"Meta / Facebook":function(){return t("connect.facebook.net")||!!window.fbq||n("_fbp")||n("_fbc")},"Twitter / X":function(){return t("ads-twitter.com")||t("static.ads-twitter.com")||!!window.twq||n("_twpid")},LinkedIn:function(){return t("snap.licdn.com")||t("ads.linkedin.com")||!!window._linkedin_data_partner_ids||n("li_sugr")||n("bcookie")||n("lidc")},Pinterest:function(){return t("s.pinimg.com/ct")||t("pintrk")||!!window.pintrk||n("_pin_unauth")},Reddit:function(){return t("alb.reddit.com")||t("events.reddit.com")||!!window.rdt||n("_rdt_uuid")},TikTok:function(){return t("analytics.tiktok.com")||!!window.ttq}};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",a):setTimeout(a,100)}function a(){var t=window.__ccDiscovery;if(t&&t.active&&(!document.body||!document.body.classList.contains("wp-admin"))){var n=function(){try{var e=sessionStorage.getItem("cookieflame_discovery_services");return e?JSON.parse(e):{}}catch(e){return{}}}(),a={};try{var r=localStorage.getItem("cookieflame_discovery_before");if(r)for(var c=JSON.parse(r),s=0;s<c.length;s++)a[c[s]]=!0}catch(e){}var d=["wordpress_","wp-settings","wp_lang","PHPSESSID","cc_consent","cc_anon_id","cookieflame_","woocommerce_","wp_woocommerce_"],l=document.createElement("div");l.id="cf-admin-discovery-bar",l.style.cssText="position:fixed;top:0;left:0;right:0;z-index:999999;background:#1d2327;color:#f0f0f1;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;display:flex;align-items:center;justify-content:space-between;padding:10px 20px;box-shadow:0 2px 8px rgba(0,0,0,.3);gap:16px;flex-wrap:wrap;";var m=document.createElement("div");m.style.cssText="display:flex;align-items:center;gap:12px;flex:1;min-width:200px;";var g=document.createElement("span");g.style.cssText="width:10px;height:10px;border-radius:50%;background:#00ba37;display:inline-block;flex-shrink:0;animation:cf-admin-pulse 2s infinite;";var p=document.createElement("span");p.textContent="Cookie Discovery Active",p.style.fontWeight="600";var f=document.createElement("span");f.id="cf-admin-discovery-count",f.style.cssText="background:#2271b1;color:#fff;padding:2px 10px;border-radius:12px;font-size:13px;font-weight:600;cursor:help;",f.textContent="scanning...",m.appendChild(g),m.appendChild(p),m.appendChild(f);var u=document.createElement("span");u.style.cssText="color:#a7aaad;font-size:13px;display:inline-flex;flex-direction:column;gap:2px;";var h=document.createElement("span");h.textContent="All cookies are temporarily accepted. Browse your pages, then click Finish.";var v=document.createElement("span");v.textContent="Tip: Browse by clicking links on the site. Typed URLs may skip discovery.",v.style.cssText="font-size:11px;opacity:0.75;",u.appendChild(h),u.appendChild(v),C(),setTimeout(C,500),setTimeout(C,2e3);var y=document.createElement("button");y.textContent="Finish Discovery",y.style.cssText="background:#00ba37;color:#fff;border:none;padding:8px 20px;border-radius:4px;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;",y.onmouseover=function(){y.style.background="#009929"},y.onmouseout=function(){y.style.background="#00ba37"},l.appendChild(m),l.appendChild(u),l.appendChild(y);var k=document.createElement("style");k.textContent="@keyframes cf-admin-pulse{0%,100%{opacity:1}50%{opacity:.4}}#cf-admin-discovery-bar~*{margin-top:0!important;}body.admin-bar #cf-admin-discovery-bar{top:32px}@media screen and (max-width:782px){body.admin-bar #cf-admin-discovery-bar{top:46px}}",document.head.appendChild(k),document.body.insertBefore(l,document.body.firstChild),document.addEventListener("click",function(e){for(var t=e.target;t&&1===t.nodeType&&"A"!==t.tagName;)t=t.parentNode;if(t&&"A"===t.tagName){var o=t.getAttribute("target");if("_blank"!==o&&"_top"!==o&&"_parent"!==o){var n=t.getAttribute("rel")||"";if(!n||-1===n.split(/\s+/).indexOf("external")){var i=t.getAttribute("href");if(i){var a;try{a=new URL(i,location.href)}catch(e){return}"http:"!==a.protocol&&"https:"!==a.protocol||a.origin===location.origin&&(a.pathname===location.pathname&&a.search===location.search&&a.hash!==location.hash||a.searchParams.has("cookieflame")||(a.searchParams.set("cookieflame","discover"),t.setAttribute("href",a.toString())))}}}}},!0),setTimeout(x,5e3);var w=setInterval(x,3e3);y.addEventListener("click",function(){y.disabled=!0,y.textContent="Finishing...",y.style.opacity="0.7",clearInterval(w),x();var e=n,o=window.__ccConfig||{};try{localStorage.setItem("cookieflame_discovery_results",JSON.stringify(e))}catch(t){var i=encodeURIComponent(JSON.stringify(e)),a=o.cookieDomain?"; domain="+o.cookieDomain:"";document.cookie="cookieflame_discovery_results="+i+"; path=/; max-age=300"+a}fetch(t.finishUrl,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":t.nonce},body:"{}"}).then(function(e){if(403===e.status)throw new Error("Your session has expired. Please reload the page and try again.");return e.json()}).then(function(e){var i=[location.hostname,"."+location.hostname];o.cookieDomain&&i.push(o.cookieDomain);for(var a=0;a<i.length;a++)document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i[a];if(document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",e.restore_dnt){var r=o.cookieDomain?"; domain="+o.cookieDomain:"";document.cookie="cookieflame_dnt=1; path=/; max-age=31536000"+r}try{sessionStorage.removeItem("cookieflame_discovery_services")}catch(e){}for(var c=_(),s=0,d={},m=Object.keys(n),g=0;g<m.length;g++){var p=n[m[g]];if(p.unknown)s++,d[m[g]]=!0;else{var f=p.cookies||[];s+=f.length;for(var u=0;u<f.length;u++)d[f[u]]=!0}}for(var h=c.confirmed.concat(c.existing),v=0;v<h.length;v++)d[h[v]]||s++;l.style.background="#00ba37",l.innerHTML="";var y=document.createElement("span");y.style.cssText="font-weight:600;flex:1;text-align:center;";var k=s+" cookie"+(1!==s?"s":"")+" discovered. Redirecting to Cookie Manager...";y.textContent=k,l.appendChild(y),setTimeout(function(){window.location.href=t.adminUrl},1500)}).catch(function(e){y.disabled=!1,y.textContent="Finish Discovery",y.style.opacity="1",l.style.background="#d63638",u.style.color="#fff",u.textContent="Error: "+e.message})})}function x(){for(var t=function(){var t=[],n=e.getResourceSnapshot();e.setResourceSnapshot(n);for(var a=window.cookieflameAdmin&&window.cookieflameAdmin.serviceDetectors||[],r=[],c=0;c<a.length;c++)for(var s=a[c].scriptDomains||[],d=0;d<s.length;d++)r.push(s[d]);for(var l=0;l<a.length;l++){var m=a[l],g=m.name||"",p=i[g];if(p)try{if(p()){var f=o(g.toLowerCase().replace(/\s+/g,""));if(0===f.length&&-1!==g.indexOf(" "))for(var u=g.toLowerCase().split(" "),h=0;h<u.length&&0===f.length;h++)u[h].length>3&&(f=o(u[h]));t.push({name:g,cookies:m.cookies||[],canonicalDomain:m.canonicalDomain||"",scriptUrls:f})}}catch(e){}}t.pagePlugins=n.pluginScripts;for(var v=["wp.com","wordpress.com","wordpress.org","s.w.org","gravatar.com","cdnjs.cloudflare.com","cdn.jsdelivr.net","unpkg.com","ajax.googleapis.com","fonts.googleapis.com","fonts.gstatic.com","code.jquery.com","stackpath.bootstrapcdn.com","maxcdn.bootstrapcdn.com","www.google.com/recaptcha","www.gstatic.com","apis.google.com","maps.googleapis.com","maps.google.com","challenges.cloudflare.com","static.cloudflareinsights.com","chromium.org","mozilla.org","lazyload","rocket-loader","elementor.com"],y=n.thirdPartyDomains,k=0;k<y.length;k++){for(var w=y[k],x=!1,b=0;b<v.length;b++)if(w===v[b]||-1!==w.indexOf("."+v[b])||-1!==v[b].indexOf(w)){x=!0;break}if(!x){for(var _=!1,C=0;C<r.length;C++)if(-1!==w.indexOf(r[C])||-1!==r[C].indexOf(w)){_=!0;break}_||t.push({name:w,cookies:[],unknown:!0})}}return e.setResourceSnapshot(null),t}(),a=0;a<t.length;a++)n[t[a].name]||(n[t[a].name]=t[a]);if(t.pagePlugins&&t.pagePlugins.length){for(var r=n.__pagePlugins||{},c=0;c<t.pagePlugins.length;c++)r[t.pagePlugins[c].slug]=t.pagePlugins[c].url;n.__pagePlugins=r}!function(e){try{sessionStorage.setItem("cookieflame_discovery_services",JSON.stringify(e))}catch(e){}}(n),function(){var e=document.getElementById("cf-admin-discovery-count");if(e){for(var t=_(),o=(t.confirmed.length,t.existing.length,0),i={},a=Object.keys(n),r=[],c=[],s=0;s<a.length;s++){var d=n[a[s]];if(d.unknown)o++,c.push(a[s]),i[a[s]]=!0;else{r.push(a[s]);var l=d.cookies||[];o+=l.length;for(var m=0;m<l.length;m++)i[l[m]]=!0}}for(var g=t.confirmed.concat(t.existing),p=0;p<g.length;p++)i[g[p]]||o++;if(0===o)e.textContent="no cookies yet",e.title="Browse your site to discover cookies";else{e.textContent=o+" cookie"+(1!==o?"s":"")+" discovered";var f="";r.length>0&&(f+="Services: "+r.sort().join(", ")),c.length>0&&(f&&(f+="\n"),f+="Unknown scripts: "+c.sort().join(", ")),t.confirmed.length>0&&(f&&(f+="\n"),f+="New browser cookies: "+t.confirmed.join(", ")),e.title=f}}}()}function b(e){for(var t=0;t<d.length;t++)if(e===d[t]||0===e.indexOf(d[t]))return!0;return!1}function _(){for(var e=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),t=[],o=[],n={},i=Object.keys(a).length>0,r=0;r<e.length;r++){var c=e[r];n[c]||(n[c]=!0,b(c)||(i&&a[c]?o.push(c):t.push(c)))}return{confirmed:t.sort(),existing:o.sort()}}function C(){var e=document.getElementById("cc-overlay");e&&e.classList.remove("cc-show");var t=document.getElementById("cc-banner");t&&t.classList.remove("cc-show");var o=document.getElementById("cc-ccpa-banner");o&&o.classList.remove("cc-show");var n=document.getElementById("cc-icon");n&&n.classList.remove("cc-show")}}}();15 !function(){"use strict";var e=window.__ccInternal;if(e){var o=e.scriptLoaded,t=e.scriptLoadedUrls,n=e.hasCookie,i={"Google Analytics":function(){return o("googletagmanager.com/gtag")||o("google-analytics.com")||o("analytics.google.com")||n("_ga")},"Google Ads":function(){return o("googleads.g.doubleclick.net")||o("googleadservices.com")||o("googlesyndication.com")||n("_gcl_au")||n("_gcl_aw")},"Google Tag Manager":function(){return o("googletagmanager.com/gtm.js")||!!window.google_tag_manager},"Microsoft Ads":function(){return o("bat.bing.com")||!!window.uetq||n("_uetsid")||n("_uetvid")},"Meta / Facebook":function(){return o("connect.facebook.net")||!!window.fbq||n("_fbp")||n("_fbc")},"Twitter / X":function(){return o("ads-twitter.com")||o("static.ads-twitter.com")||!!window.twq||n("_twpid")},LinkedIn:function(){return o("snap.licdn.com")||o("ads.linkedin.com")||!!window._linkedin_data_partner_ids||n("li_sugr")||n("bcookie")||n("lidc")},Pinterest:function(){return o("s.pinimg.com/ct")||o("pintrk")||!!window.pintrk||n("_pin_unauth")},Reddit:function(){return o("alb.reddit.com")||o("events.reddit.com")||!!window.rdt||n("_rdt_uuid")},TikTok:function(){return o("analytics.tiktok.com")||!!window.ttq}};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",a):setTimeout(a,100)}function a(){var o=window.__ccDiscovery;if(o&&o.active&&(!document.body||!document.body.classList.contains("wp-admin"))){var n=function(){try{var e=sessionStorage.getItem("cookieflame_discovery_services");return e?JSON.parse(e):{}}catch(e){return{}}}(),a={};try{var r=localStorage.getItem("cookieflame_discovery_before");if(r)for(var c=JSON.parse(r),s=0;s<c.length;s++)a[c[s]]=!0}catch(e){}var d=["wordpress_","wp-settings","wp_lang","PHPSESSID","cc_consent","cc_anon_id","cookieflame_","woocommerce_","wp_woocommerce_"],l=document.createElement("div");l.id="cf-admin-discovery-bar",l.style.cssText="position:fixed;top:0;left:0;right:0;z-index:999999;background:#1d2327;color:#f0f0f1;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;display:flex;align-items:center;justify-content:space-between;padding:10px 20px;box-shadow:0 2px 8px rgba(0,0,0,.3);gap:16px;flex-wrap:wrap;";var m=document.createElement("div");m.style.cssText="display:flex;align-items:center;gap:12px;flex:1;min-width:200px;";var g=document.createElement("span");g.style.cssText="width:10px;height:10px;border-radius:50%;background:#00ba37;display:inline-block;flex-shrink:0;animation:cf-admin-pulse 2s infinite;";var p=document.createElement("span");p.textContent="Cookie Discovery Active",p.style.fontWeight="600";var f=document.createElement("span");f.id="cf-admin-discovery-count",f.style.cssText="background:#2271b1;color:#fff;padding:2px 10px;border-radius:12px;font-size:13px;font-weight:600;cursor:help;",f.textContent="scanning...",m.appendChild(g),m.appendChild(p),m.appendChild(f);var u=document.createElement("span");u.style.cssText="color:#a7aaad;font-size:13px;display:inline-flex;flex-direction:column;gap:2px;";var h=document.createElement("span");h.textContent="All cookies are temporarily accepted. Browse your pages, then click Finish.";var v=document.createElement("span");v.textContent="Tip: Browse by clicking links on the site. Typed URLs may skip discovery.",v.style.cssText="font-size:11px;opacity:0.75;",u.appendChild(h),u.appendChild(v),C(),setTimeout(C,500),setTimeout(C,2e3);var y=document.createElement("button");y.textContent="Finish Discovery",y.style.cssText="background:#00ba37;color:#fff;border:none;padding:8px 20px;border-radius:4px;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;",y.onmouseover=function(){y.style.background="#009929"},y.onmouseout=function(){y.style.background="#00ba37"},l.appendChild(m),l.appendChild(u),l.appendChild(y);var k=document.createElement("style");k.textContent="@keyframes cf-admin-pulse{0%,100%{opacity:1}50%{opacity:.4}}#cf-admin-discovery-bar~*{margin-top:0!important;}body.admin-bar #cf-admin-discovery-bar{top:32px}@media screen and (max-width:782px){body.admin-bar #cf-admin-discovery-bar{top:46px}}",document.head.appendChild(k),document.body.insertBefore(l,document.body.firstChild),document.addEventListener("click",function(e){for(var o=e.target;o&&1===o.nodeType&&"A"!==o.tagName;)o=o.parentNode;if(o&&"A"===o.tagName){var t=o.getAttribute("target");if("_blank"!==t&&"_top"!==t&&"_parent"!==t){var n=o.getAttribute("rel")||"";if(!n||-1===n.split(/\s+/).indexOf("external")){var i=o.getAttribute("href");if(i){var a;try{a=new URL(i,location.href)}catch(e){return}"http:"!==a.protocol&&"https:"!==a.protocol||a.origin===location.origin&&(a.pathname===location.pathname&&a.search===location.search&&a.hash!==location.hash||a.searchParams.has("cookieflame")||(a.searchParams.set("cookieflame","discover"),o.setAttribute("href",a.toString())))}}}}},!0),setTimeout(x,5e3);var w=setInterval(x,3e3);y.addEventListener("click",function(){y.disabled=!0,y.textContent="Finishing...",y.style.opacity="0.7",clearInterval(w),x();var e=n,t=window.__ccConfig||{};try{localStorage.setItem("cookieflame_discovery_results",JSON.stringify(e))}catch(o){var i=encodeURIComponent(JSON.stringify(e)),a=t.cookieDomain?"; domain="+t.cookieDomain:"";document.cookie="cookieflame_discovery_results="+i+"; path=/; max-age=300"+a}fetch(o.finishUrl,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":o.nonce},body:"{}"}).then(function(e){if(403===e.status)throw new Error("Your session has expired. Please reload the page and try again.");return e.json()}).then(function(e){var i=[location.hostname,"."+location.hostname];t.cookieDomain&&i.push(t.cookieDomain);for(var a=0;a<i.length;a++)document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i[a];if(document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",e.restore_dnt){var r=t.cookieDomain?"; domain="+t.cookieDomain:"";document.cookie="cookieflame_dnt=1; path=/; max-age=31536000"+r}try{sessionStorage.removeItem("cookieflame_discovery_services")}catch(e){}for(var c=_(),s=0,d={},m=Object.keys(n),g=0;g<m.length;g++){var p=n[m[g]];if(p.unknown)s++,d[m[g]]=!0;else{var f=p.cookies||[];s+=f.length;for(var u=0;u<f.length;u++)d[f[u]]=!0}}for(var h=c.confirmed.concat(c.existing),v=0;v<h.length;v++)d[h[v]]||s++;l.style.background="#00ba37",l.innerHTML="";var y=document.createElement("span");y.style.cssText="font-weight:600;flex:1;text-align:center;";var k=s+" cookie"+(1!==s?"s":"")+" discovered. Redirecting to Cookie Manager...";y.textContent=k,l.appendChild(y),setTimeout(function(){window.location.href=o.adminUrl},1500)}).catch(function(e){y.disabled=!1,y.textContent="Finish Discovery",y.style.opacity="1",l.style.background="#d63638",u.style.color="#fff",u.textContent="Error: "+e.message})})}function x(){for(var o=function(){var o=[],n=e.getResourceSnapshot();e.setResourceSnapshot(n);for(var a=window.cookieflameAdmin&&window.cookieflameAdmin.serviceDetectors||[],r=[],c=0;c<a.length;c++)for(var s=a[c].scriptDomains||[],d=0;d<s.length;d++)r.push(s[d]);for(var l=0;l<a.length;l++){var m=a[l],g=m.name||"",p=i[g];if(p)try{if(p()){var f=t(g.toLowerCase().replace(/\s+/g,""));if(0===f.length&&-1!==g.indexOf(" "))for(var u=g.toLowerCase().split(" "),h=0;h<u.length&&0===f.length;h++)u[h].length>3&&(f=t(u[h]));o.push({name:g,cookies:m.cookies||[],canonicalDomain:m.canonicalDomain||"",scriptUrls:f})}}catch(e){}}o.pagePlugins=n.pluginScripts;for(var v=["wp.com","wordpress.com","wordpress.org","s.w.org","gravatar.com","cdnjs.cloudflare.com","cdn.jsdelivr.net","unpkg.com","ajax.googleapis.com","fonts.googleapis.com","fonts.gstatic.com","code.jquery.com","stackpath.bootstrapcdn.com","maxcdn.bootstrapcdn.com","www.google.com/recaptcha","www.gstatic.com","apis.google.com","maps.googleapis.com","maps.google.com","challenges.cloudflare.com","static.cloudflareinsights.com","chromium.org","mozilla.org","lazyload","rocket-loader","elementor.com"],y=n.thirdPartyDomains,k=0;k<y.length;k++){for(var w=y[k],x=!1,b=0;b<v.length;b++)if(w===v[b]||-1!==w.indexOf("."+v[b])||-1!==v[b].indexOf(w)){x=!0;break}if(!x){for(var _=!1,C=0;C<r.length;C++)if(-1!==w.indexOf(r[C])||-1!==r[C].indexOf(w)){_=!0;break}_||o.push({name:w,cookies:[],unknown:!0})}}return e.setResourceSnapshot(null),o}(),a=0;a<o.length;a++)n[o[a].name]||(n[o[a].name]=o[a]);if(o.pagePlugins&&o.pagePlugins.length){for(var r=n.__pagePlugins||{},c=0;c<o.pagePlugins.length;c++)r[o.pagePlugins[c].slug]=o.pagePlugins[c].url;n.__pagePlugins=r}!function(e){try{sessionStorage.setItem("cookieflame_discovery_services",JSON.stringify(e))}catch(e){}}(n),function(){var e=document.getElementById("cf-admin-discovery-count");if(e){for(var o=_(),t=(o.confirmed.length,o.existing.length,0),i={},a=Object.keys(n),r=[],c=[],s=0;s<a.length;s++){var d=n[a[s]];if(d.unknown)t++,c.push(a[s]),i[a[s]]=!0;else{r.push(a[s]);var l=d.cookies||[];t+=l.length;for(var m=0;m<l.length;m++)i[l[m]]=!0}}for(var g=o.confirmed.concat(o.existing),p=0;p<g.length;p++)i[g[p]]||t++;if(0===t)e.textContent="no cookies yet",e.title="Browse your site to discover cookies";else{e.textContent=t+" cookie"+(1!==t?"s":"")+" discovered";var f="";r.length>0&&(f+="Services: "+r.sort().join(", ")),c.length>0&&(f&&(f+="\n"),f+="Unknown scripts: "+c.sort().join(", ")),o.confirmed.length>0&&(f&&(f+="\n"),f+="New browser cookies: "+o.confirmed.join(", ")),e.title=f}}}()}function b(e){for(var o=0;o<d.length;o++)if(e===d[o]||0===e.indexOf(d[o]))return!0;return!1}function _(){for(var o=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),t=[],n=[],i={},r=Object.keys(a).length>0,c=e.visitorCookies?e.visitorCookies(o):{},s=window.cookieflameAdmin&&window.cookieflameAdmin.ignoredCookieNames||[],d=0;d<o.length;d++){var l=o[d];i[l]||(i[l]=!0,b(l)||c[l]||-1!==s.indexOf(l)||(r&&a[l]?n.push(l):t.push(l)))}return{confirmed:t.sort(),existing:n.sort()}}function C(){var e=document.getElementById("cc-overlay");e&&e.classList.remove("cc-show");var o=document.getElementById("cc-banner");o&&o.classList.remove("cc-show");var t=document.getElementById("cc-ccpa-banner");t&&t.classList.remove("cc-show");var n=document.getElementById("cc-icon");n&&n.classList.remove("cc-show")}}}(); -
cookieflame/tags/5.3.0/assets/js/cookieconsent.js
r3768250 r3769546 1 1 /** 2 * CookieFlame v5. 2.02 * CookieFlame v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Self-hosted cookie consent manager with Google Consent Mode v2, … … 40 40 } catch (e) {} 41 41 42 var PLUGIN_VERSION = "5. 2.0";42 var PLUGIN_VERSION = "5.3.0"; 43 43 44 44 /* ═══════════════════════════════════════════ … … 1400 1400 hasCookiePrefix: hasCookiePrefix, 1401 1401 setResourceSnapshot: function (s) { _resourceSnapshot = s; }, 1402 // Discovery bar (v5.3.0): which of these cookies came with the browser, 1403 // by the same check passive monitoring uses, so its count matches the 1404 // Cookie Manager. 1405 visitorCookies: function (names) { 1406 var domains = getResourceSnapshot().thirdPartyDomains, out = {}; 1407 for (var i = 0; i < names.length; i++) { 1408 if (isVisitorCookie(names[i], domains, cookieSetter(names[i]))) out[names[i]] = true; 1409 } 1410 return out; 1411 }, 1402 1412 // Facade module bridge (v4.41.0+). The facade module reads this to 1403 1413 // access core state it needs for overlay rendering, and registers … … 1898 1908 try { 1899 1909 var url = new URL(String(setters[name]).replace(/:\d+(:\d+)?$/, "")); 1910 if (/^(chrome-extension|moz-extension|safari-web-extension|safari-extension):$/.test(url.protocol)) { 1911 out.set_by = "browser-extension"; 1912 return out; 1913 } 1900 1914 var host = url.hostname; 1901 1915 if (host === location.hostname || host === "www." + location.hostname || "www." + host === location.hostname) { … … 1908 1922 } catch (e) {} 1909 1923 return out; 1924 } 1925 1926 /** 1927 * Whether a cookie came with the visitor's browser rather than this site: 1928 * written by a browser extension, or another consent tool's cookie when 1929 * that tool isn't on the page (rules from window.__ccVisitorCookieRules, 1930 * limited to tools whose WordPress plugin isn't active). Skipping these 1931 * keeps the page's beacon allowance for real cookies; the server makes 1932 * the same check and records them on the ignore list. 1933 */ 1934 function isVisitorCookie(name, domains, setter) { 1935 if (setter.set_by === "browser-extension") return true; 1936 var rules = window.__ccVisitorCookieRules; 1937 if (!rules || !rules.tools) return false; 1938 if (rules.allow && rules.allow.indexOf(name) !== -1) return false; 1939 if (setter.set_by) return false; // A page script wrote it, so the tool runs here. 1940 for (var t = 0; t < rules.tools.length; t++) { 1941 var tool = rules.tools[t], hit = (tool.n || []).indexOf(name) !== -1; 1942 for (var p = 0; !hit && p < (tool.p || []).length; p++) { 1943 if (name.indexOf(tool.p[p]) === 0) hit = true; 1944 } 1945 if (!hit) continue; 1946 for (var d = 0; d < domains.length; d++) { 1947 for (var k = 0; k < (tool.d || []).length; k++) { 1948 var host = String(domains[d]).toLowerCase(), dom = tool.d[k]; 1949 if (host === dom || host.slice(-dom.length - 1) === "." + dom) return false; 1950 } 1951 } 1952 return true; 1953 } 1954 return false; 1910 1955 } 1911 1956 … … 1988 2033 1989 2034 var setter = cookieSetter(name); 2035 // Visitors' browsers don't report these. During Cookie Discovery they 2036 // are reported anyway, so the server records them on the Permanently 2037 // Ignored list with the reason and the admin sees what was set aside. 2038 if (isVisitorCookie(name, scriptDomains, setter) && !(window.__ccDiscovery && window.__ccDiscovery.active)) { 2039 beaconed[name] = true; 2040 continue; 2041 } 1990 2042 1991 2043 var payload = JSON.stringify({ -
cookieflame/tags/5.3.0/assets/js/cookieconsent.min.js
r3768250 r3769546 1 1 /** 2 * CookieFlame v5. 2.02 * CookieFlame v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Self-hosted cookie consent manager with Google Consent Mode v2, … … 17 17 * • Timezone-based geo heuristic with server-side fallback 18 18 */ 19 !function(){"use strict";var e={};try{for(var t=document.cookie.split(";"),n=0;n<t.length;n++){var o=t[n].trim().split("=")[0];o&&(e[o]=!0)}}catch(e){}var c="5. 2.0",r={cookieName:"cc_consent",cookieExpiry:365,privacyUrl:"/privacy-policy",ccpaUrl:"/privacy-policy#do-not-sell",geoApi:"",logEndpoint:"",reconsentDays:365,cspSafe:!1,tcfEnabled:!0,cmpId:1,cmpVersion:1,vendorListVersion:2,storageMethod:"cookie",cookieDomain:"",shareSubdomains:!1,theme:"light",showPoweredBy:!1,iconPosition:"left",consentVersion:"",autoBlockPatterns:[{pattern:"googletagmanager.com/gtag",category:"analytics"},{pattern:"google-analytics.com",category:"analytics"},{pattern:"analytics.google.com",category:"analytics"},{pattern:"hotjar.com",category:"analytics"},{pattern:"mixpanel.com",category:"analytics"},{pattern:"segment.com/analytics",category:"analytics"},{pattern:"segment.io",category:"analytics"},{pattern:"clarity.ms",category:"analytics"},{pattern:"plausible.io",category:"analytics"},{pattern:"js.hs-analytics.net",category:"analytics"},{pattern:"connect.facebook.net",category:"marketing"},{pattern:"snap.licdn.com",category:"marketing"},{pattern:"ads.linkedin.com",category:"marketing"},{pattern:"googleads.g.doubleclick.net",category:"marketing"},{pattern:"googlesyndication.com",category:"marketing"},{pattern:"googleadservices.com",category:"marketing"},{pattern:"ads-twitter.com",category:"marketing"},{pattern:"analytics.tiktok.com",category:"marketing"},{pattern:"pintrk",category:"marketing"},{pattern:"s.pinimg.com/ct",category:"marketing"},{pattern:"widget.intercom.io",category:"preferences"},{pattern:"js.intercomcdn.com",category:"preferences"}],regionRules:{gdpr:["AT","BE","BG","CY","CZ","DE","DK","EE","ES","FI","FR","GR","HR","HU","IE","IT","LT","LU","LV","MT","NL","PL","PT","RO","SE","SI","SK","IS","LI","NO","GB","GG","JE","IM","CH","BR","ZA"],ccpa:["US"]},text:{title:"We value your privacy",description:"We use cookies to improve your experience, analyse traffic and personalise content. You can choose which categories to allow.",acceptAllButton:"Accept All",declineAllButton:"Decline All",saveButton:"Save Preferences",showDetailsButton:"Manage preferences",hideDetailsButton:"Hide preferences",alwaysOnLabel:"(always on)",ccpaTitle:"Your Privacy Choices",ccpaDescription:"We use cookies and similar technologies. Under California law, you have the right to opt out of the sale or sharing of your personal information.",ccpaAcceptButton:"OK",ccpaDnsmpiLink:"Do Not Sell My Personal Information"},cookieTypes:[{id:"necessary",name:"Necessary",description:"Required for the site to function. Cannot be disabled.",required:!0,consentMode:["security_storage","functionality_storage"],tcfPurposes:[1],onAccept:function(){}},{id:"preferences",name:"Preferences",description:"Remember your settings and personalisation choices.",required:!1,defaultValue:!1,consentMode:["functionality_storage","personalization_storage"],tcfPurposes:[2,3],onAccept:function(){},onReject:function(){}},{id:"analytics",name:"Analytics",description:"Help us understand how visitors use the site.",required:!1,defaultValue:!1,consentMode:["analytics_storage"],tcfPurposes:[4,5,6],onAccept:function(){},onReject:function(){}},{id:"marketing",name:"Marketing",description:"Used to deliver relevant ads and track campaigns.",required:!1,defaultValue:!1,consentMode:["ad_storage","ad_user_data","ad_personalization"],tcfPurposes:[7,8,9,10],onAccept:function(){},onReject:function(){}}]};if(window.__ccConfig&&"object"==typeof window.__ccConfig){var a=window.__ccConfig;["cookieName","cookieExpiry","privacyUrl","ccpaUrl","geoApi","logEndpoint","reconsentDays","cspSafe","tcfEnabled","cmpId","cmpVersion","vendorListVersion","storageMethod","cookieDomain","shareSubdomains","theme","showPoweredBy","iconPosition","consentVersion"].forEach(function(e){void 0!==a[e]&&(r[e]=a[e])}),a.text&&"object"==typeof a.text&&Object.keys(a.text).forEach(function(e){r.text[e]=a.text[e]}),Array.isArray(a.cookieTypes)&&(r.cookieTypes=a.cookieTypes),Array.isArray(a.autoBlockPatterns)&&(r.autoBlockPatterns=a.autoBlockPatterns),a.regionRules&&(r.regionRules=a.regionRules)}window.__ccConsentVersion&&(r.consentVersion=window.__ccConsentVersion);var i=!!window.__ccGPC;window.__ccBlockRules&&Array.isArray(window.__ccBlockRules)&&window.__ccBlockRules.length&&(r.autoBlockPatterns=window.__ccBlockRules);var s={cc_consent:{vendor:"CookieFlame",category:"necessary",purpose:"Stores your consent preferences",expiry:"1 year"},cc_anon_id:{vendor:"CookieFlame",category:"necessary",purpose:"Anonymous ID for consent logging",expiry:"1 year"},cookieflame_dnt:{vendor:"CookieFlame",category:"necessary",purpose:"Do-not-track opt-out flag",expiry:"1 year"},PHPSESSID:{vendor:"PHP",category:"necessary",purpose:"Server-side session identifier",expiry:"Session"},wp_settings_:{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-":{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-time-":{vendor:"WordPress",category:"necessary",purpose:"Admin settings timestamp",prefix:!0,expiry:"1 year"},wordpress_logged_in_:{vendor:"WordPress",category:"necessary",purpose:"Login session",prefix:!0,expiry:"Session"},wordpress_sec_:{vendor:"WordPress",category:"necessary",purpose:"Secure login session",prefix:!0,expiry:"Session"},wordpress_test_cookie:{vendor:"WordPress",category:"necessary",purpose:"Checks cookie support",expiry:"Session"},wp_lang:{vendor:"WordPress",category:"necessary",purpose:"Language preference",expiry:"Session"},woocommerce_cart_hash:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping cart contents",expiry:"Session"},woocommerce_items_in_cart:{vendor:"WooCommerce",category:"necessary",purpose:"Cart item count",expiry:"Session"},wp_woocommerce_session_:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping session",prefix:!0,expiry:"2 days"},_ga:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors",expiry:"2 years"},_ga_:{vendor:"Google Analytics",category:"analytics",purpose:"Stores session state",prefix:!0,expiry:"2 years"},_gid:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors (24h)",expiry:"24 hours"},_gat:{vendor:"Google Analytics",category:"analytics",purpose:"Throttles request rate",expiry:"1 minute"},wp_wk_ga_untrack_:{vendor:"Google Analytics",category:"analytics",purpose:"GA opt-out flag",prefix:!0,expiry:"Persistent"},_gcl_au:{vendor:"Google Ads",category:"marketing",purpose:"Conversion linker",expiry:"90 days"},_gcl_aw:{vendor:"Google Ads",category:"marketing",purpose:"Stores ad click info",expiry:"90 days"},_gac_:{vendor:"Google Ads",category:"marketing",purpose:"Campaign information",prefix:!0,expiry:"90 days"},IDE:{vendor:"Google DoubleClick",category:"marketing",purpose:"Ad serving and frequency",expiry:"1 year"},test_cookie:{vendor:"Google DoubleClick",category:"marketing",purpose:"Checks cookie support",expiry:"15 minutes"},NID:{vendor:"Google",category:"preferences",purpose:"Stores preferences",expiry:"6 months"}},d=window.__ccCustomCookies||[];function u(e){for(var t=0;t<d.length;t++){var n=d[t];if("exact"===n.match&&e===n.name)return n;if("prefix"===n.match&&0===e.indexOf(n.name))return n;if("contains"===n.match&&-1!==e.indexOf(n.name))return n}var o=s[e];return o||(Object.keys(s).forEach(function(t){!o&&s[t].prefix&&0===e.indexOf(t)&&(o=s[t])}),o||null)}var l=null,p="none",f=null,m=null,g=!1,y=0;function v(e){return"string"!=typeof e&&(e=String(e)),e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function h(e){if("localStorage"===r.storageMethod)try{return localStorage.getItem(e)}catch(e){return null}var t=document.cookie.match(new RegExp("(?:^|;\\s*)"+e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"=([^;]*)"));if(!t)return null;try{return decodeURIComponent(t[1])}catch(e){return null}}function w(e,t,n){if("localStorage"!==r.storageMethod){var o=new Date;o.setTime(o.getTime()+864e5*n);var c=e+"="+encodeURIComponent(t)+";expires="+o.toUTCString()+";path=/;SameSite=Lax;Secure";r.cookieDomain&&(c+=";domain="+r.cookieDomain),document.cookie=c}else try{localStorage.setItem(e,t)}catch(e){}}function b(){if(m)return m;var e=h("cc_anon_id");return e?(m=e,e):(w("cc_anon_id",m="cc_"+function(){if("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID)try{return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}(),730),m)}function k(){var e={timestamp:l?l.ts:null,complianceMode:p,country:f,gpc:i,consentVersion:r.consentVersion};return r.cookieTypes.forEach(function(t){e[t.id]=l?!!l[t.id]:!!t.required}),e}function _(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t||k()}))}function x(){window.dataLayer=window.dataLayer||[],window.dataLayer.push(arguments)}function E(e){var t={};r.cookieTypes.forEach(function(n){n.consentMode&&n.consentMode.forEach(function(o){t[o]=e[n.id]?"granted":"denied"})}),i&&(t.ad_storage="denied",t.ad_user_data="denied",t.ad_personalization="denied"),x("consent","update",t)}var A=new Map,S=!1;function L(e){var t={};return r.cookieTypes.forEach(function(n){n.tcfPurposes&&n.tcfPurposes.forEach(function(o){t[o]=!!e[n.id]})}),{tcString:"",tcfPolicyVersion:4,cmpId:r.cmpId,cmpVersion:r.cmpVersion,gdprApplies:"gdpr"===p,eventStatus:"useractioncomplete",cmpStatus:"loaded",listenerId:void 0,isServiceSpecific:!0,useNonStandardTexts:!1,publisherCC:"GB",purposeOneTreatment:!1,purpose:{consents:t,legitimateInterests:{}},vendor:{consents:{},legitimateInterests:{}},specialFeatureOptins:{},publisher:{consents:{},legitimateInterests:{},customPurpose:{consents:{},legitimateInterests:{}},restrictions:{}}}}function C(e,t,n,o){if("function"==typeof n)if("addEventListener"===e){var c=++y;if(A.set(c,n),l){var a=L(l);a.listenerId=c,n(a,!0)}}else"removeEventListener"===e?n({listenerId:o},A.delete(o)):"getTCData"===e?n(l?L(l):null,!!l):"ping"===e?n({gdprApplies:"gdpr"===p,cmpLoaded:S,cmpStatus:S?"loaded":"stub",displayStatus:"hidden",apiVersion:"2.2",cmpVersion:r.cmpVersion,cmpId:r.cmpId,gvlVersion:r.vendorListVersion,tcfPolicyVersion:4},!0):n(null,!1)}function B(e){A.forEach(function(t,n){var o=L(e);o.listenerId=n;try{t(o,!0)}catch(e){}})}function I(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<r.autoBlockPatterns.length;n++){var o=r.autoBlockPatterns[n];if(o.pattern instanceof RegExp){if(o.pattern.test(t))return o.category}else if(-1!==t.indexOf(o.pattern.toLowerCase()))return o.category}return null}function T(e){document.querySelectorAll('script[type="text/plain"][data-cc]').forEach(function(t){var n=(t.getAttribute("data-cc")||"").toLowerCase();if(e[n]&&!t.getAttribute("data-cc-activated")){t.setAttribute("data-cc-activated","1");var o=document.createElement("script");o.isWPRocket=!0,Array.from(t.attributes).forEach(function(e){"type"!==e.name&&"data-cc"!==e.name&&"data-cc-activated"!==e.name&&"data-cc-auto"!==e.name&&o.setAttribute(e.name,e.value)}),!t.src&&t.textContent&&(o.textContent=t.textContent),t.parentNode.insertBefore(o,t.nextSibling),t.parentNode.removeChild(t)}}),["img","iframe","link"].forEach(function(t){document.querySelectorAll(t+"[data-cc][data-cc-src]").forEach(function(n){var o=(n.getAttribute("data-cc")||"").toLowerCase();e[o]&&!n.getAttribute("data-cc-activated")&&(n.setAttribute("data-cc-activated","1"),"link"===t?n.href=n.getAttribute("data-cc-src"):n.src=n.getAttribute("data-cc-src"))})})}var O=[{pattern:"youtube.com",category:"marketing"},{pattern:"youtube-nocookie.com",category:"marketing"},{pattern:"youtu.be",category:"marketing"},{pattern:"player.vimeo.com",category:"marketing"},{pattern:"vimeo.com",category:"marketing"},{pattern:"dailymotion.com",category:"marketing"},{pattern:"open.spotify.com",category:"preferences"},{pattern:"soundcloud.com",category:"preferences"},{pattern:"google.com/maps",category:"preferences"},{pattern:"maps.google.com",category:"preferences"},{pattern:"facebook.com/plugins",category:"marketing"},{pattern:"instagram.com",category:"marketing"},{pattern:"tiktok.com/embed",category:"marketing"},{pattern:"twitter.com",category:"marketing"},{pattern:"x.com",category:"marketing"}];function P(){return!(!document.body||!(document.body.classList.contains("elementor-editor-active")||document.body.classList.contains("fl-builder-edit")||document.body.classList.contains("et-fb-root-ancestor")))}var D=[],M=0,R=null,q=!1;function V(){if(R&&D.length){var e=D;D=[];try{R(e)}catch(e){}}}function N(){0!==D.length&&(2!==M?1!==M&&3!==M&&(M=1,function(){var e=window.__ccConfig&&window.__ccConfig.facadesUrl||null;if(!e)return void(M=3);var t=document.createElement("script");t.src=e,t.async=!0,t.onload=function(){M=2,V()},t.onerror=function(){M=3},(document.head||document.documentElement).appendChild(t)}()):V())}function U(e){var t=e.src||e.getAttribute("data-src")||"";if(t&&!e.getAttribute("data-cc-facade")&&!P()){var n=function(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<O.length;n++)if(-1!==t.indexOf(O[n].pattern))return O[n].category;return null}(t);if(n){var o=l||$();o&&o[n]||(e.setAttribute("data-cc-facade","1"),e.setAttribute("data-cc-iframe-cat",n),e.setAttribute("data-cc-original-src",t),e.removeAttribute("src"),e.style.display="none",D.push({type:"iframe",node:e,category:n,src:t}),N())}}}function G(e){if(!e.getAttribute("data-cc-facade")&&!P()){var t=e.getAttribute("data-settings");if(t){var n;try{n=JSON.parse(t)}catch(e){return}var o=n.youtube_url||n.vimeo_url||"";if(o){var c=o.toLowerCase(),r=null;if((-1!==c.indexOf("youtube")||-1!==c.indexOf("youtu.be")||-1!==c.indexOf("vimeo")||-1!==c.indexOf("dailymotion"))&&(r="marketing"),r&&(!l||!l[r])){if(!l){var a=$();if(a&&a[r])return}e.setAttribute("data-cc-facade","1"),q=!0,D.push({type:"elementor",node:e,category:r,url:o}),N()}}}}}function j(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++)U(e[t]);for(var n=document.querySelectorAll(".elementor-widget-video"),o=0;o<n.length;o++)G(n[o]);for(var c=document.querySelectorAll(".wp-block-embed__wrapper iframe[src]"),r=0;r<c.length;r++)U(c[r])}function J(){new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){if("IFRAME"===e.tagName&&U(e),e.querySelectorAll){for(var t=e.querySelectorAll("iframe[src]"),n=0;n<t.length;n++)U(t[n]);for(var o=e.querySelectorAll(".elementor-widget-video"),c=0;c<o.length;c++)G(o[c])}e.classList&&e.classList.contains("elementor-widget-video")&&G(e)}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}function W(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++){var n=e[t];if(!n.getAttribute("data-cc-facade")){var o=n.src||"";if(o)for(var c=0;c<O.length;c++)if(-1!==o.indexOf(O[c].pattern)){n.src=o;break}}}}function H(e,t){r.cookieTypes.forEach(function(n){var o=!!e[n.id];if((t?!!t[n.id]:null)!==o||null===t)if(o&&"function"==typeof n.onAccept)try{n.onAccept()}catch(e){console.warn("[CookieConsent] onAccept error for "+n.id,e)}else if(!o&&"function"==typeof n.onReject)try{n.onReject()}catch(e){console.warn("[CookieConsent] onReject error for "+n.id,e)}})}function F(e,t){var n=l;if(l=e,w(r.cookieName,JSON.stringify(e),r.cookieExpiry),E(e),q&&t)for(var o=document.querySelectorAll(".cc-iframe-facade[data-cc-elementor-widget]"),a=0;a<o.length;a++){var s=o[a].getAttribute("data-cc-iframe-cat");if(s&&e[s])return void window.location.reload()}z(e,n),T(e),function(e){for(var t=document.querySelectorAll(".cc-iframe-facade"),n=0;n<t.length;n++)if(!t[n].getAttribute("data-cc-elementor-widget")&&e[t[n].getAttribute("data-cc-iframe-cat")]){var o=t[n].nextElementSibling;if(o&&"IFRAME"===o.tagName&&o.getAttribute("data-cc-facade")){var c=o.getAttribute("data-cc-original-src");c&&(o.src=c,o.style.display="",o.removeAttribute("data-cc-facade"))}t[n].parentNode.removeChild(t[n])}}(e),t&&"auto_grant_non_eu"!==t&&"ccpa_auto_grant"!==t&&setTimeout(W,300),H(e,n),Z(e),r.tcfEnabled&&B(e),t&&function(e,t){if(r.logEndpoint){var n={};r.cookieTypes.forEach(function(e){n[e.id]=!!t[e.id]});var o={anonymousId:b(),timestamp:(new Date).toISOString(),action:e,consent:n,complianceMode:p,country:f,url:location.href,userAgent:navigator.userAgent,tcfEnabled:r.tcfEnabled,gpc:i,consentVersion:r.consentVersion,version:c};try{var a=JSON.stringify(o);navigator.sendBeacon?navigator.sendBeacon(r.logEndpoint,new Blob([a],{type:"application/json"})):fetch(r.logEndpoint,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0})}catch(e){}}}(t,e)}function Z(e){r.cookieTypes.forEach(function(t){if(!t.required){var n=document.getElementById("cc-cb-"+t.id);n&&(n.checked=!!e[t.id])}});var t=document.getElementById("cc-cats"),n=document.getElementById("cc-details"),o=document.getElementById("cc-pref-buttons");t&&t.classList.remove("cc-open"),n&&(n.textContent=r.text.showDetailsButton),o&&o.classList.remove("cc-open")}function $(){var e=h(r.cookieName);if(!e)return null;try{var t=JSON.parse(e);return!t||"object"!=typeof t||Array.isArray(t)||(!t.ts||isNaN(new Date(t.ts).getTime())||(Date.now()-new Date(t.ts).getTime())/864e5>r.reconsentDays||r.consentVersion&&t.cv!==r.consentVersion)?null:t}catch(e){return null}}function Y(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!0}),e}function K(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!!t.required}),e}function z(e,t){if(t){var n=[];if(r.cookieTypes.forEach(function(o){o.required||t[o.id]&&!e[o.id]&&n.push(o.id)}),n.length)document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean).forEach(function(e){var t=u(e);if(t&&-1!==n.indexOf(t.category)){var o=location.hostname,c="."+o;document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+c,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+o,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; Secure",r.cookieDomain&&(document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain+"; Secure");var a=o.split(".");if(a.length>2){var i="."+a.slice(1).join(".");document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i+"; Secure"}}})}}function Q(e){return(f=e?e.toUpperCase():null)?r.regionRules.gdpr&&-1!==r.regionRules.gdpr.indexOf(f)?"gdpr":r.regionRules.ccpa&&-1!==r.regionRules.ccpa.indexOf(f)?"ccpa":"none":"gdpr"}function X(e){if(window.__ccGeo)return e(Q(window.__ccGeo));r.geoApi?fetch(r.geoApi).then(function(e){return e.json()}).then(function(t){var n=t.country_code||t.country||"";n?e(Q(n)):ee(e)}).catch(function(){ee(e)}):ee(e)}function ee(e){var t="";try{t=Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch(e){}return 0===t.indexOf("Europe/")||"Atlantic/Reykjavik"===t?(f=null,e("gdpr")):0===t.indexOf("US/")||0===t.indexOf("America/")&&["New_York","Chicago","Denver","Los_Angeles","Phoenix","Anchorage","Boise","Detroit","Indianapolis","Louisville","Menominee","Nome","Adak","Juneau","Sitka","Yakutat","Metlakatla","Kentucky","Indiana","North_Dakota"].some(function(e){return-1!==t.indexOf(e)})||"Pacific/Honolulu"===t?(f="US",e("ccpa")):(f=null,void e("gdpr"))}function te(){"dark"===r.theme&&document.documentElement.classList.add("cc-dark"),"right"===r.iconPosition&&document.documentElement.classList.add("cc-icon-right")}function ne(){var e=r.text,t=document.createElement("div");t.id="cc-overlay",document.body.appendChild(t);var n=document.createElement("div");n.id="cc-banner",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-label","Cookie consent"),n.setAttribute("tabindex","-1");var o=r.cookieTypes.map(function(t){var n=t.required?' <span class="cc-always-on">'+v(e.alwaysOnLabel)+"</span>":"";return'<div class="cc-cat"><div><div class="cc-cat-label">'+v(t.name)+n+'</div><div class="cc-cat-desc">'+v(t.description||"")+'</div></div><label class="cc-toggle"><input type="checkbox" id="cc-cb-'+v(t.id)+'" aria-label="'+v(t.name)+'"'+(t.required||t.defaultValue?" checked":"")+(t.required?" disabled":"")+'><span class="cc-slider"></span></label></div>'}).join("");n.innerHTML='<div class="cc-inner"><p class="cc-title">'+v(e.title)+'</p><p class="cc-text">'+v(e.description)+' <a href="'+v(r.privacyUrl)+'">Privacy Policy</a></p><div class="cc-buttons"><button class="cc-btn cc-btn-accept" id="cc-accept">'+v(e.acceptAllButton)+'</button><button class="cc-btn cc-btn-details" id="cc-details" aria-expanded="false">'+v(e.showDetailsButton)+'</button></div><div class="cc-categories" id="cc-cats">'+o+'</div><div class="cc-pref-buttons" id="cc-pref-buttons"><button class="cc-btn cc-btn-save" id="cc-save">'+v(e.saveButton)+'</button><button class="cc-btn cc-btn-decline" id="cc-decline">'+v(e.declineAllButton)+"</button></div></div>"+(r.showPoweredBy?'<div class="cc-powered"><a href="https://www.cookieflame.com" target="_blank" rel="noopener">Powered by CookieFlame</a></div>':""),document.body.appendChild(n);var c=document.createElement("button");c.id="cc-icon",c.setAttribute("aria-label","Cookie settings"),c.innerHTML='<svg width="24" height="24" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19.1 1.16c-.06-.42-.38-.77-.8-.83A11.8 11.8 0 0 0 13.28 1.2L7.5 4.3A11.8 11.8 0 0 0 3.95 7.98L1.09 13.9A11.8 11.8 0 0 0 .38 18.96l1.13 6.47a11.8 11.8 0 0 0 3.53 4.99l4.71 4.56a11.8 11.8 0 0 0 4.59 2.24l6.48.91a11.8 11.8 0 0 0 5.52-.89l5.78-3.09a11.8 11.8 0 0 0 3.55-3.69l2.87-5.9a11.8 11.8 0 0 0 .71-5.08c-.07-.41-.42-.73-.83-.79a14.8 14.8 0 0 1-8.16-7.61c-.14-.59-.63-1.05-1.23-1.14A14.8 14.8 0 0 1 19.1 1.16ZM15.25 10.25a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm-5 15a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0Zm17.5-5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z" fill="currentColor"/></svg>',document.body.appendChild(c),document.getElementById("cc-accept").addEventListener("click",se),document.getElementById("cc-decline").addEventListener("click",de),document.getElementById("cc-save").addEventListener("click",ue),document.getElementById("cc-details").addEventListener("click",le),c.addEventListener("click",function(){re("gdpr")})}var oe=null;function ce(e){if("Tab"===e.key){var t=document.getElementById("cc-banner")||document.getElementById("cc-ccpa-banner");if(t&&t.classList.contains("cc-show")){for(var n=[],o=t.querySelectorAll('button, a[href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])'),c=0;c<o.length;c++){for(var r=o[c],a=!1,i=r.parentElement;i&&i!==t;){if(i.style&&"none"===window.getComputedStyle(i).display){a=!0;break}i=i.parentElement}a||n.push(r)}if(0!==n.length){var s=n[0],d=n[n.length-1];e.shiftKey?document.activeElement===s&&(e.preventDefault(),d.focus()):document.activeElement===d&&(e.preventDefault(),s.focus())}}}}function re(e){"ccpa"!==e?(oe=document.activeElement,requestAnimationFrame(function(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.add("cc-show"),t){t.classList.add("cc-show");var o=t.querySelector(".cc-btn-accept");o&&o.focus(),document.addEventListener("keydown",ce)}n&&n.classList.remove("cc-show")})):requestAnimationFrame(function(){var e=document.getElementById("cc-ccpa-banner");e&&(e.classList.add("cc-show"),oe=document.activeElement,e.focus(),document.addEventListener("keydown",ce))})}function ae(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&"gdpr"===p&&n.classList.add("cc-show"),document.removeEventListener("keydown",ce),oe&&"function"==typeof oe.focus)try{oe.focus()}catch(e){}oe=null}function ie(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&n.classList.remove("cc-show"),document.removeEventListener("keydown",ce)}function se(){F(Y(),"accept_all"),ae(),_("cc:accept-all"),_("cc:update")}function de(){F(K(),"decline_all"),ae(),_("cc:decline-all"),_("cc:update")}function ue(){var e;F((e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f},r.cookieTypes.forEach(function(t){if(t.required)e[t.id]=!0;else{var n=document.getElementById("cc-cb-"+t.id);e[t.id]=!!n&&n.checked}}),e),"save_preferences"),ae(),_("cc:save"),_("cc:update")}function le(){var e=document.getElementById("cc-cats"),t=document.getElementById("cc-details"),n=document.getElementById("cc-pref-buttons"),o=e.classList.toggle("cc-open");t.textContent=o?r.text.hideDetailsButton:r.text.showDetailsButton,t.setAttribute("aria-expanded",o?"true":"false"),n&&(o?n.classList.add("cc-open"):n.classList.remove("cc-open"))}function pe(){var e=document.getElementById("cc-declaration");if(e){for(var t=k(),n={},o=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),c=0;c<o.length;c++){var a=u(o[c]);a&&(n[o[c]]={name:o[c],vendor:a.vendor,category:a.category,purpose:a.purpose,expiry:a.expiry||"",active:!0})}for(var i=0;i<d.length;i++){var s=d[i];s.name&&s.vendor&&s.category&&"unclassified"!==s.category&&!n[s.name]&&(n[s.name]={name:s.name,vendor:s.vendor,category:s.category,purpose:s.purpose||"",expiry:s.expiry||"",active:!1})}for(var l=0;l<o.length;l++)n[o[l]]||(n[o[l]]={name:o[l],vendor:"",category:"unclassified",purpose:"",expiry:"",active:!0});var p=["necessary","preferences","analytics","marketing"],f={};r.cookieTypes.forEach(function(e){f[e.id]=e.name});var m={};p.forEach(function(e){m[e]=[]}),Object.keys(n).forEach(function(e){var t=n[e],o=t.category;m[o]||(m[o]=[]),m[o].push(t)}),p.forEach(function(e){m[e]&&m[e].sort(function(e,t){return e.name.localeCompare(t.name)})});var g="<div>";if(t.timestamp){var y=new Date(t.timestamp);g+="<p>"+v("Your consent was last updated on "+y.toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"})+" at "+y.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})+".")+"</p>"}else g+="<p>"+v("You have not yet made a cookie preference choice on this site.")+"</p>";for(var h=0;h<p.length;h++){var w=p[h],b=m[w];if(b&&b.length){var _,x=f[w]||w,E=r.cookieTypes.filter(function(e){return e.id===w})[0],A=E&&E.description||"";_=!!E&&E.required?"Always active":t[w]?"Active":"Inactive",g+="<div>",g+="<p><b>"+v(x)+"</b> ("+v(_)+")</p>",A&&(g+="<p>"+v(A)+"</p>"),g+="<table><thead><tr>",g+="<th>Name</th><th>Provider</th><th>Purpose</th><th>Expiry</th>",g+="</tr></thead><tbody>";for(var S=0;S<b.length;S++){var L=b[S];g+="<tr>",g+="<td><code>"+v(L.name)+"</code></td>",g+="<td>"+v(L.vendor||"Unknown")+"</td>",g+="<td>"+v(L.purpose||"Not specified")+"</td>",g+="<td>"+v(L.expiry||"—")+"</td>",g+="</tr>"}g+="</tbody></table></div>"}}g+="</div>",e.innerHTML=g}}window.__ccInternal={getResourceSnapshot:ye,scriptLoaded:function(e){for(var t=ge||ye(),n=0;n<t.allUrls.length;n++)if(-1!==t.allUrls[n].indexOf(e))return!0;return!1},scriptLoadedUrls:function(e){for(var t=ge||ye(),n=[],o=0;o<t.allUrls.length;o++)-1!==t.allUrls[o].indexOf(e)&&n.push(t.allUrls[o]);return n},hasCookie:function(e){return document.cookie.split(";").some(function(t){return t.trim().split("=")[0]===e})},hasCookiePrefix:function(e){return document.cookie.split(";").some(function(t){return 0===t.trim().split("=")[0].indexOf(e)})},setResourceSnapshot:function(e){ge=e},facadeBridge:{getConfig:function(){return r},getConsentState:function(){return l},loadConsent:$,saveConsent:function(e,t){F(e,t)},hideAllBanners:ie,registerRenderer:function(e){R=e,M=2,V()}}},window.CookieConsent={getState:k,getConfig:function(){return r},getComplianceMode:function(){return p},getCountry:function(){return f},show:function(){re("gdpr")},acceptAll:se,declineAll:de,getGPC:function(){return i},getConsentVersion:function(){return r.consentVersion},on:function(e,t){window.addEventListener(e,t)},off:function(e,t){window.removeEventListener(e,t)},VERSION:c},window.addEventListener("cc:ready",pe),window.addEventListener("cc:update",pe),function(){if(!window.__ccDefaultsSet){var e={wait_for_update:500};r.cookieTypes.forEach(function(t){t.consentMode&&t.consentMode.forEach(function(n){e[n]=t.required?"granted":"denied"})}),x("consent","default",e)}}(),function(){if(r.tcfEnabled){var e=window.__tcfapi&&window.__tcfapi.queue?window.__tcfapi.queue:[];window.__tcfapi=C,e.forEach(function(e){C.apply(null,e)}),S=!0,window===window.top&&window.addEventListener("message",function(e){var t;try{t="string"==typeof e.data?JSON.parse(e.data):e.data}catch(e){return}if(t&&t.__tcfapiCall){var n=t.__tcfapiCall;C(n.command,n.version,function(t,o){var c={__tcfapiReturn:{returnValue:t,success:o,callId:n.callId}};e.source&&e.source.postMessage("string"==typeof e.data?JSON.stringify(c):c,"*")},n.parameter)}})}}();var fe=$();function me(){var e=window.__ccDiscovery&&window.__ccDiscovery.active;if(!e&&(window.__ccDNT||document.cookie.split(";").some(function(e){return 0===e.trim().indexOf("cookieflame_dnt=")})))return E(l=K()),z(l,Y()),J(),j(),p="dnt",te(),ne(),ie(),Z(l),_("cc:ready"),void pe();if(e){E(l=Y()),T(l),J(),H(l,null),r.tcfEnabled&&B(l),window.dataLayer=window.dataLayer||[];for(var t=["consent_accepted_analytics","consent_accepted_marketing","consent_accepted_preferences","consent_accepted_necessary","consent_update","consent_given","cookie_consent_given","cookie_consent_update","consent_accepted"],n=0;n<t.length;n++)window.dataLayer.push({event:t[n]});return p="discovery",te(),ne(),ie(),_("cc:ready"),_("cc:update"),void pe()}var o=$();if(o)if(i&&(o.marketing=!1),l=o,E(o),T(o),J(),j(),H(o,null),r.tcfEnabled&&B(o),te(),ne(),ie(),Z(o),o.cc){if("gdpr"===(p=Q(o.cc))){var c=document.getElementById("cc-icon");c&&c.classList.add("cc-show")}_("cc:ready"),pe()}else X(function(e){if(p=e,"gdpr"===e){var t=document.getElementById("cc-icon");t&&t.classList.add("cc-show")}_("cc:ready"),pe()});else X(function(e){if(p=e,"none"===e)return J(),F(Y(),"auto_grant_non_eu"),_("cc:ready"),_("cc:update"),void pe();if("ccpa"===e){if(J(),i){var t=Y();t.marketing=!1,F(t,"ccpa_gpc_optout")}else F(Y(),"ccpa_auto_grant");return te(),n=r.text,(o=document.createElement("div")).id="cc-ccpa-banner",o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true"),o.setAttribute("aria-label","Privacy notice"),o.setAttribute("tabindex","-1"),o.innerHTML='<div class="cc-ccpa-inner"><div class="cc-ccpa-text"><p>'+v(n.ccpaDescription)+'</p></div><div class="cc-ccpa-actions"><a href="'+v(r.ccpaUrl)+'" class="cc-ccpa-link">'+v(n.ccpaDnsmpiLink)+'</a><button class="cc-btn cc-btn-accept" id="cc-ccpa-ok">'+v(n.ccpaAcceptButton)+"</button></div></div>",document.body.appendChild(o),document.getElementById("cc-ccpa-ok").addEventListener("click",function(){F(Y(),"ccpa_acknowledge"),o.classList.remove("cc-show"),_("cc:update")}),re("ccpa"),_("cc:ready"),_("cc:update"),void pe()}var n,o;te(),J(),j(),ne(),re("gdpr"),_("cc:ready"),pe()})}fe&&(l=fe,E(fe)),function(){if(!g&&r.autoBlockPatterns&&r.autoBlockPatterns.length){g=!0;var e=document.createElement.bind(document),t=Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src");t&&t.set&&(document.createElement=function(){var n=e.apply(document,arguments);if("script"!==(arguments[0]||"").toLowerCase())return n;function o(e,t){if(t&&"string"==typeof t&&!e.getAttribute("data-cc")&&!e.getAttribute("data-cc-auto")&&-1===t.indexOf("cookieconsent")){var n=I(t);!n||l&&l[n]||(e.type="text/plain",e.setAttribute("data-cc",n),e.setAttribute("data-cc-auto","1"))}}Object.defineProperty(n,"src",{configurable:!0,enumerable:!0,get:function(){return t.get.call(this)},set:function(e){return o(this,e),t.set.call(this,e)}});var c=n.setAttribute.bind(n);return n.setAttribute=function(e,t){return"src"===e.toLowerCase()&&o(n,t),c(e,t)},n}),new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){var t=[];"SCRIPT"===e.tagName&&t.push(e),e.querySelectorAll&&e.querySelectorAll("script[src]").forEach(function(e){t.push(e)}),t.forEach(function(e){if(!(e.getAttribute("data-cc-auto")||e.getAttribute("data-cc")||e.src&&-1!==e.src.indexOf("cookieconsent"))){var t=I(e.src);t&&(l&&l[t]||(e.type="text/plain",e.setAttribute("data-cc",t),e.setAttribute("data-cc-auto","1")))}})}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}}(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",me):me();var ge=null;function ye(){for(var e=[],t=[],n=[],o={},c={},r=document.querySelectorAll("script[src]"),a=0;a<r.length;a++)r[a].src&&e.push(r[a].src);for(var i=document.querySelectorAll("iframe[src]"),s=0;s<i.length;s++)i[s].src&&e.push(i[s].src);if(window.performance&&performance.getEntriesByType)for(var d=performance.getEntriesByType("resource"),u=0;u<d.length;u++){var l=d[u].name||"";if(l){-1===e.indexOf(l)&&e.push(l);var p=d[u].initiatorType||"";if("script"===p||"iframe"===p||"xmlhttprequest"===p||"fetch"===p||-1!==l.indexOf(".js"))try{var f=new URL(l),m=f.hostname;if(m===location.hostname||m==="www."+location.hostname||"www."+m===location.hostname){var g=f.pathname.match(/\/wp-content\/plugins\/([^\/]+)\//);g&&!c[g[1]]&&(c[g[1]]=!0,n.push({slug:g[1],url:l}))}else o[m]||(o[m]=!0,t.push(m))}catch(e){}}}return{allUrls:e,thirdPartyDomains:t,pluginScripts:n}}var ve={};function he(e){var t={set_by:"",set_by_plugin:""},n=window.__ccCookieSetters;if(!n||!Object.prototype.hasOwnProperty.call(n,e)||!n[e])return t;try{var o=new URL(String(n[e]).replace(/:\d+(:\d+)?$/,"")),c=o.hostname;if(c===location.hostname||c==="www."+location.hostname||"www."+c===location.hostname){t.set_by="first-party";var r=o.pathname.match(/\/wp-content\/(?:plugins|themes)\/([^\/]+)\//);r&&(t.set_by_plugin=r[1].toLowerCase())}else t.set_by=c.toLowerCase()}catch(e){}return t}function we(){var t=window.__ccClassified||[],n=window.__ccUnclassified||[],o=window.__ccBeaconUrl;if(o){var c,r={};for(c=0;c<t.length;c++)r[t[c]]=!0;for(c=0;c<n.length;c++)r[n[c]]=!0;var a=Object.keys(ve);for(c=0;c<a.length;c++)r[a[c]]=!0;var i=Object.keys(s);for(c=0;c<i.length;c++)r[i[c]]=!0;var d={},u=[],l=document.cookie.split(";");for(c=0;c<l.length;c++){var p=l[c].indexOf("="),f=(p>-1?l[c].substring(0,p):l[c]).trim(),m=p>-1?l[c].substring(p+1).trim():"";f&&(u.push(f),d[f]=m)}var g=[];for(c=0;c<u.length;c++)if(!r[u[c]]){for(var y=!1,v=Object.keys(s),h=0;h<v.length;h++)if(s[v[h]].prefix&&0===u[c].indexOf(v[h])){y=!0;break}y||g.push(u[c])}if(0!==g.length){for(var w=ye(),b=w.thirdPartyDomains,k=[],_=0;_<w.pluginScripts.length;_++)k.push(w.pluginScripts[_].slug);for(var x=location.pathname,E=0;E<g.length;E++){var A=g[E],S=!!e[A]&&!r[A],L=be(d[A]||""),C=he(A),B=JSON.stringify({cookie_name:A,script_domains:b,plugin_scripts:k,page_path:x,pre_existing:S,value_shape:L,set_by:C.set_by,set_by_plugin:C.set_by_plugin});ve[A]=!0,navigator.sendBeacon&&navigator.sendBeacon(o,new Blob([B],{type:"application/json"}))}}}}function be(e){if(!e||0===e.length)return"empty";if("true"===e||"false"===e||"1"===e||"0"===e)return"boolean";if(/^\d+$/.test(e))return e.length>12?"long-numeric":"numeric";if(/^\d+\.\d+$/.test(e))return"decimal";if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return"uuid";if(/^[A-Za-z0-9+\/]{20,}={0,2}$/.test(e))return"base64";if(/^(GA\d+\.\d+\.\d+\.\d+|G-[A-Z0-9]+)/.test(e))return"ga-id";try{if("object"==typeof JSON.parse(decodeURIComponent(e)))return"json"}catch(e){}return/^[a-f0-9]{24,}$/i.test(e)?"hex-id":/^\d{10,13}$/.test(e)?"timestamp":e.length<=20?"short-string":e.length<=100?"medium-string":"long-string"}setTimeout(we,3e3),setTimeout(we,15e3),setTimeout(we,45e3),window.addEventListener("cc:update",function(){setTimeout(we,3e3)}),window.addEventListener("pagehide",we)}();19 !function(){"use strict";var e={};try{for(var t=document.cookie.split(";"),n=0;n<t.length;n++){var o=t[n].trim().split("=")[0];o&&(e[o]=!0)}}catch(e){}var c="5.3.0",r={cookieName:"cc_consent",cookieExpiry:365,privacyUrl:"/privacy-policy",ccpaUrl:"/privacy-policy#do-not-sell",geoApi:"",logEndpoint:"",reconsentDays:365,cspSafe:!1,tcfEnabled:!0,cmpId:1,cmpVersion:1,vendorListVersion:2,storageMethod:"cookie",cookieDomain:"",shareSubdomains:!1,theme:"light",showPoweredBy:!1,iconPosition:"left",consentVersion:"",autoBlockPatterns:[{pattern:"googletagmanager.com/gtag",category:"analytics"},{pattern:"google-analytics.com",category:"analytics"},{pattern:"analytics.google.com",category:"analytics"},{pattern:"hotjar.com",category:"analytics"},{pattern:"mixpanel.com",category:"analytics"},{pattern:"segment.com/analytics",category:"analytics"},{pattern:"segment.io",category:"analytics"},{pattern:"clarity.ms",category:"analytics"},{pattern:"plausible.io",category:"analytics"},{pattern:"js.hs-analytics.net",category:"analytics"},{pattern:"connect.facebook.net",category:"marketing"},{pattern:"snap.licdn.com",category:"marketing"},{pattern:"ads.linkedin.com",category:"marketing"},{pattern:"googleads.g.doubleclick.net",category:"marketing"},{pattern:"googlesyndication.com",category:"marketing"},{pattern:"googleadservices.com",category:"marketing"},{pattern:"ads-twitter.com",category:"marketing"},{pattern:"analytics.tiktok.com",category:"marketing"},{pattern:"pintrk",category:"marketing"},{pattern:"s.pinimg.com/ct",category:"marketing"},{pattern:"widget.intercom.io",category:"preferences"},{pattern:"js.intercomcdn.com",category:"preferences"}],regionRules:{gdpr:["AT","BE","BG","CY","CZ","DE","DK","EE","ES","FI","FR","GR","HR","HU","IE","IT","LT","LU","LV","MT","NL","PL","PT","RO","SE","SI","SK","IS","LI","NO","GB","GG","JE","IM","CH","BR","ZA"],ccpa:["US"]},text:{title:"We value your privacy",description:"We use cookies to improve your experience, analyse traffic and personalise content. You can choose which categories to allow.",acceptAllButton:"Accept All",declineAllButton:"Decline All",saveButton:"Save Preferences",showDetailsButton:"Manage preferences",hideDetailsButton:"Hide preferences",alwaysOnLabel:"(always on)",ccpaTitle:"Your Privacy Choices",ccpaDescription:"We use cookies and similar technologies. Under California law, you have the right to opt out of the sale or sharing of your personal information.",ccpaAcceptButton:"OK",ccpaDnsmpiLink:"Do Not Sell My Personal Information"},cookieTypes:[{id:"necessary",name:"Necessary",description:"Required for the site to function. Cannot be disabled.",required:!0,consentMode:["security_storage","functionality_storage"],tcfPurposes:[1],onAccept:function(){}},{id:"preferences",name:"Preferences",description:"Remember your settings and personalisation choices.",required:!1,defaultValue:!1,consentMode:["functionality_storage","personalization_storage"],tcfPurposes:[2,3],onAccept:function(){},onReject:function(){}},{id:"analytics",name:"Analytics",description:"Help us understand how visitors use the site.",required:!1,defaultValue:!1,consentMode:["analytics_storage"],tcfPurposes:[4,5,6],onAccept:function(){},onReject:function(){}},{id:"marketing",name:"Marketing",description:"Used to deliver relevant ads and track campaigns.",required:!1,defaultValue:!1,consentMode:["ad_storage","ad_user_data","ad_personalization"],tcfPurposes:[7,8,9,10],onAccept:function(){},onReject:function(){}}]};if(window.__ccConfig&&"object"==typeof window.__ccConfig){var a=window.__ccConfig;["cookieName","cookieExpiry","privacyUrl","ccpaUrl","geoApi","logEndpoint","reconsentDays","cspSafe","tcfEnabled","cmpId","cmpVersion","vendorListVersion","storageMethod","cookieDomain","shareSubdomains","theme","showPoweredBy","iconPosition","consentVersion"].forEach(function(e){void 0!==a[e]&&(r[e]=a[e])}),a.text&&"object"==typeof a.text&&Object.keys(a.text).forEach(function(e){r.text[e]=a.text[e]}),Array.isArray(a.cookieTypes)&&(r.cookieTypes=a.cookieTypes),Array.isArray(a.autoBlockPatterns)&&(r.autoBlockPatterns=a.autoBlockPatterns),a.regionRules&&(r.regionRules=a.regionRules)}window.__ccConsentVersion&&(r.consentVersion=window.__ccConsentVersion);var i=!!window.__ccGPC;window.__ccBlockRules&&Array.isArray(window.__ccBlockRules)&&window.__ccBlockRules.length&&(r.autoBlockPatterns=window.__ccBlockRules);var s={cc_consent:{vendor:"CookieFlame",category:"necessary",purpose:"Stores your consent preferences",expiry:"1 year"},cc_anon_id:{vendor:"CookieFlame",category:"necessary",purpose:"Anonymous ID for consent logging",expiry:"1 year"},cookieflame_dnt:{vendor:"CookieFlame",category:"necessary",purpose:"Do-not-track opt-out flag",expiry:"1 year"},PHPSESSID:{vendor:"PHP",category:"necessary",purpose:"Server-side session identifier",expiry:"Session"},wp_settings_:{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-":{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-time-":{vendor:"WordPress",category:"necessary",purpose:"Admin settings timestamp",prefix:!0,expiry:"1 year"},wordpress_logged_in_:{vendor:"WordPress",category:"necessary",purpose:"Login session",prefix:!0,expiry:"Session"},wordpress_sec_:{vendor:"WordPress",category:"necessary",purpose:"Secure login session",prefix:!0,expiry:"Session"},wordpress_test_cookie:{vendor:"WordPress",category:"necessary",purpose:"Checks cookie support",expiry:"Session"},wp_lang:{vendor:"WordPress",category:"necessary",purpose:"Language preference",expiry:"Session"},woocommerce_cart_hash:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping cart contents",expiry:"Session"},woocommerce_items_in_cart:{vendor:"WooCommerce",category:"necessary",purpose:"Cart item count",expiry:"Session"},wp_woocommerce_session_:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping session",prefix:!0,expiry:"2 days"},_ga:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors",expiry:"2 years"},_ga_:{vendor:"Google Analytics",category:"analytics",purpose:"Stores session state",prefix:!0,expiry:"2 years"},_gid:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors (24h)",expiry:"24 hours"},_gat:{vendor:"Google Analytics",category:"analytics",purpose:"Throttles request rate",expiry:"1 minute"},wp_wk_ga_untrack_:{vendor:"Google Analytics",category:"analytics",purpose:"GA opt-out flag",prefix:!0,expiry:"Persistent"},_gcl_au:{vendor:"Google Ads",category:"marketing",purpose:"Conversion linker",expiry:"90 days"},_gcl_aw:{vendor:"Google Ads",category:"marketing",purpose:"Stores ad click info",expiry:"90 days"},_gac_:{vendor:"Google Ads",category:"marketing",purpose:"Campaign information",prefix:!0,expiry:"90 days"},IDE:{vendor:"Google DoubleClick",category:"marketing",purpose:"Ad serving and frequency",expiry:"1 year"},test_cookie:{vendor:"Google DoubleClick",category:"marketing",purpose:"Checks cookie support",expiry:"15 minutes"},NID:{vendor:"Google",category:"preferences",purpose:"Stores preferences",expiry:"6 months"}},d=window.__ccCustomCookies||[];function u(e){for(var t=0;t<d.length;t++){var n=d[t];if("exact"===n.match&&e===n.name)return n;if("prefix"===n.match&&0===e.indexOf(n.name))return n;if("contains"===n.match&&-1!==e.indexOf(n.name))return n}var o=s[e];return o||(Object.keys(s).forEach(function(t){!o&&s[t].prefix&&0===e.indexOf(t)&&(o=s[t])}),o||null)}var l=null,p="none",f=null,m=null,g=!1,y=0;function v(e){return"string"!=typeof e&&(e=String(e)),e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function h(e){if("localStorage"===r.storageMethod)try{return localStorage.getItem(e)}catch(e){return null}var t=document.cookie.match(new RegExp("(?:^|;\\s*)"+e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"=([^;]*)"));if(!t)return null;try{return decodeURIComponent(t[1])}catch(e){return null}}function w(e,t,n){if("localStorage"!==r.storageMethod){var o=new Date;o.setTime(o.getTime()+864e5*n);var c=e+"="+encodeURIComponent(t)+";expires="+o.toUTCString()+";path=/;SameSite=Lax;Secure";r.cookieDomain&&(c+=";domain="+r.cookieDomain),document.cookie=c}else try{localStorage.setItem(e,t)}catch(e){}}function b(){if(m)return m;var e=h("cc_anon_id");return e?(m=e,e):(w("cc_anon_id",m="cc_"+function(){if("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID)try{return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}(),730),m)}function k(){var e={timestamp:l?l.ts:null,complianceMode:p,country:f,gpc:i,consentVersion:r.consentVersion};return r.cookieTypes.forEach(function(t){e[t.id]=l?!!l[t.id]:!!t.required}),e}function _(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t||k()}))}function x(){window.dataLayer=window.dataLayer||[],window.dataLayer.push(arguments)}function E(e){var t={};r.cookieTypes.forEach(function(n){n.consentMode&&n.consentMode.forEach(function(o){t[o]=e[n.id]?"granted":"denied"})}),i&&(t.ad_storage="denied",t.ad_user_data="denied",t.ad_personalization="denied"),x("consent","update",t)}var A=new Map,S=!1;function L(e){var t={};return r.cookieTypes.forEach(function(n){n.tcfPurposes&&n.tcfPurposes.forEach(function(o){t[o]=!!e[n.id]})}),{tcString:"",tcfPolicyVersion:4,cmpId:r.cmpId,cmpVersion:r.cmpVersion,gdprApplies:"gdpr"===p,eventStatus:"useractioncomplete",cmpStatus:"loaded",listenerId:void 0,isServiceSpecific:!0,useNonStandardTexts:!1,publisherCC:"GB",purposeOneTreatment:!1,purpose:{consents:t,legitimateInterests:{}},vendor:{consents:{},legitimateInterests:{}},specialFeatureOptins:{},publisher:{consents:{},legitimateInterests:{},customPurpose:{consents:{},legitimateInterests:{}},restrictions:{}}}}function C(e,t,n,o){if("function"==typeof n)if("addEventListener"===e){var c=++y;if(A.set(c,n),l){var a=L(l);a.listenerId=c,n(a,!0)}}else"removeEventListener"===e?n({listenerId:o},A.delete(o)):"getTCData"===e?n(l?L(l):null,!!l):"ping"===e?n({gdprApplies:"gdpr"===p,cmpLoaded:S,cmpStatus:S?"loaded":"stub",displayStatus:"hidden",apiVersion:"2.2",cmpVersion:r.cmpVersion,cmpId:r.cmpId,gvlVersion:r.vendorListVersion,tcfPolicyVersion:4},!0):n(null,!1)}function B(e){A.forEach(function(t,n){var o=L(e);o.listenerId=n;try{t(o,!0)}catch(e){}})}function I(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<r.autoBlockPatterns.length;n++){var o=r.autoBlockPatterns[n];if(o.pattern instanceof RegExp){if(o.pattern.test(t))return o.category}else if(-1!==t.indexOf(o.pattern.toLowerCase()))return o.category}return null}function T(e){document.querySelectorAll('script[type="text/plain"][data-cc]').forEach(function(t){var n=(t.getAttribute("data-cc")||"").toLowerCase();if(e[n]&&!t.getAttribute("data-cc-activated")){t.setAttribute("data-cc-activated","1");var o=document.createElement("script");o.isWPRocket=!0,Array.from(t.attributes).forEach(function(e){"type"!==e.name&&"data-cc"!==e.name&&"data-cc-activated"!==e.name&&"data-cc-auto"!==e.name&&o.setAttribute(e.name,e.value)}),!t.src&&t.textContent&&(o.textContent=t.textContent),t.parentNode.insertBefore(o,t.nextSibling),t.parentNode.removeChild(t)}}),["img","iframe","link"].forEach(function(t){document.querySelectorAll(t+"[data-cc][data-cc-src]").forEach(function(n){var o=(n.getAttribute("data-cc")||"").toLowerCase();e[o]&&!n.getAttribute("data-cc-activated")&&(n.setAttribute("data-cc-activated","1"),"link"===t?n.href=n.getAttribute("data-cc-src"):n.src=n.getAttribute("data-cc-src"))})})}var O=[{pattern:"youtube.com",category:"marketing"},{pattern:"youtube-nocookie.com",category:"marketing"},{pattern:"youtu.be",category:"marketing"},{pattern:"player.vimeo.com",category:"marketing"},{pattern:"vimeo.com",category:"marketing"},{pattern:"dailymotion.com",category:"marketing"},{pattern:"open.spotify.com",category:"preferences"},{pattern:"soundcloud.com",category:"preferences"},{pattern:"google.com/maps",category:"preferences"},{pattern:"maps.google.com",category:"preferences"},{pattern:"facebook.com/plugins",category:"marketing"},{pattern:"instagram.com",category:"marketing"},{pattern:"tiktok.com/embed",category:"marketing"},{pattern:"twitter.com",category:"marketing"},{pattern:"x.com",category:"marketing"}];function D(){return!(!document.body||!(document.body.classList.contains("elementor-editor-active")||document.body.classList.contains("fl-builder-edit")||document.body.classList.contains("et-fb-root-ancestor")))}var P=[],M=0,R=null,q=!1;function V(){if(R&&P.length){var e=P;P=[];try{R(e)}catch(e){}}}function N(){0!==P.length&&(2!==M?1!==M&&3!==M&&(M=1,function(){var e=window.__ccConfig&&window.__ccConfig.facadesUrl||null;if(!e)return void(M=3);var t=document.createElement("script");t.src=e,t.async=!0,t.onload=function(){M=2,V()},t.onerror=function(){M=3},(document.head||document.documentElement).appendChild(t)}()):V())}function U(e){var t=e.src||e.getAttribute("data-src")||"";if(t&&!e.getAttribute("data-cc-facade")&&!D()){var n=function(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<O.length;n++)if(-1!==t.indexOf(O[n].pattern))return O[n].category;return null}(t);if(n){var o=l||Z();o&&o[n]||(e.setAttribute("data-cc-facade","1"),e.setAttribute("data-cc-iframe-cat",n),e.setAttribute("data-cc-original-src",t),e.removeAttribute("src"),e.style.display="none",P.push({type:"iframe",node:e,category:n,src:t}),N())}}}function G(e){if(!e.getAttribute("data-cc-facade")&&!D()){var t=e.getAttribute("data-settings");if(t){var n;try{n=JSON.parse(t)}catch(e){return}var o=n.youtube_url||n.vimeo_url||"";if(o){var c=o.toLowerCase(),r=null;if((-1!==c.indexOf("youtube")||-1!==c.indexOf("youtu.be")||-1!==c.indexOf("vimeo")||-1!==c.indexOf("dailymotion"))&&(r="marketing"),r&&(!l||!l[r])){if(!l){var a=Z();if(a&&a[r])return}e.setAttribute("data-cc-facade","1"),q=!0,P.push({type:"elementor",node:e,category:r,url:o}),N()}}}}}function j(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++)U(e[t]);for(var n=document.querySelectorAll(".elementor-widget-video"),o=0;o<n.length;o++)G(n[o]);for(var c=document.querySelectorAll(".wp-block-embed__wrapper iframe[src]"),r=0;r<c.length;r++)U(c[r])}function J(){new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){if("IFRAME"===e.tagName&&U(e),e.querySelectorAll){for(var t=e.querySelectorAll("iframe[src]"),n=0;n<t.length;n++)U(t[n]);for(var o=e.querySelectorAll(".elementor-widget-video"),c=0;c<o.length;c++)G(o[c])}e.classList&&e.classList.contains("elementor-widget-video")&&G(e)}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}function W(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++){var n=e[t];if(!n.getAttribute("data-cc-facade")){var o=n.src||"";if(o)for(var c=0;c<O.length;c++)if(-1!==o.indexOf(O[c].pattern)){n.src=o;break}}}}function H(e,t){r.cookieTypes.forEach(function(n){var o=!!e[n.id];if((t?!!t[n.id]:null)!==o||null===t)if(o&&"function"==typeof n.onAccept)try{n.onAccept()}catch(e){console.warn("[CookieConsent] onAccept error for "+n.id,e)}else if(!o&&"function"==typeof n.onReject)try{n.onReject()}catch(e){console.warn("[CookieConsent] onReject error for "+n.id,e)}})}function F(e,t){var n=l;if(l=e,w(r.cookieName,JSON.stringify(e),r.cookieExpiry),E(e),q&&t)for(var o=document.querySelectorAll(".cc-iframe-facade[data-cc-elementor-widget]"),a=0;a<o.length;a++){var s=o[a].getAttribute("data-cc-iframe-cat");if(s&&e[s])return void window.location.reload()}K(e,n),T(e),function(e){for(var t=document.querySelectorAll(".cc-iframe-facade"),n=0;n<t.length;n++)if(!t[n].getAttribute("data-cc-elementor-widget")&&e[t[n].getAttribute("data-cc-iframe-cat")]){var o=t[n].nextElementSibling;if(o&&"IFRAME"===o.tagName&&o.getAttribute("data-cc-facade")){var c=o.getAttribute("data-cc-original-src");c&&(o.src=c,o.style.display="",o.removeAttribute("data-cc-facade"))}t[n].parentNode.removeChild(t[n])}}(e),t&&"auto_grant_non_eu"!==t&&"ccpa_auto_grant"!==t&&setTimeout(W,300),H(e,n),$(e),r.tcfEnabled&&B(e),t&&function(e,t){if(r.logEndpoint){var n={};r.cookieTypes.forEach(function(e){n[e.id]=!!t[e.id]});var o={anonymousId:b(),timestamp:(new Date).toISOString(),action:e,consent:n,complianceMode:p,country:f,url:location.href,userAgent:navigator.userAgent,tcfEnabled:r.tcfEnabled,gpc:i,consentVersion:r.consentVersion,version:c};try{var a=JSON.stringify(o);navigator.sendBeacon?navigator.sendBeacon(r.logEndpoint,new Blob([a],{type:"application/json"})):fetch(r.logEndpoint,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0})}catch(e){}}}(t,e)}function $(e){r.cookieTypes.forEach(function(t){if(!t.required){var n=document.getElementById("cc-cb-"+t.id);n&&(n.checked=!!e[t.id])}});var t=document.getElementById("cc-cats"),n=document.getElementById("cc-details"),o=document.getElementById("cc-pref-buttons");t&&t.classList.remove("cc-open"),n&&(n.textContent=r.text.showDetailsButton),o&&o.classList.remove("cc-open")}function Z(){var e=h(r.cookieName);if(!e)return null;try{var t=JSON.parse(e);return!t||"object"!=typeof t||Array.isArray(t)||(!t.ts||isNaN(new Date(t.ts).getTime())||(Date.now()-new Date(t.ts).getTime())/864e5>r.reconsentDays||r.consentVersion&&t.cv!==r.consentVersion)?null:t}catch(e){return null}}function Y(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!0}),e}function z(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!!t.required}),e}function K(e,t){if(t){var n=[];if(r.cookieTypes.forEach(function(o){o.required||t[o.id]&&!e[o.id]&&n.push(o.id)}),n.length)document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean).forEach(function(e){var t=u(e);if(t&&-1!==n.indexOf(t.category)){var o=location.hostname,c="."+o;document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+c,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+o,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; Secure",r.cookieDomain&&(document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain+"; Secure");var a=o.split(".");if(a.length>2){var i="."+a.slice(1).join(".");document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i+"; Secure"}}})}}function Q(e){return(f=e?e.toUpperCase():null)?r.regionRules.gdpr&&-1!==r.regionRules.gdpr.indexOf(f)?"gdpr":r.regionRules.ccpa&&-1!==r.regionRules.ccpa.indexOf(f)?"ccpa":"none":"gdpr"}function X(e){if(window.__ccGeo)return e(Q(window.__ccGeo));r.geoApi?fetch(r.geoApi).then(function(e){return e.json()}).then(function(t){var n=t.country_code||t.country||"";n?e(Q(n)):ee(e)}).catch(function(){ee(e)}):ee(e)}function ee(e){var t="";try{t=Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch(e){}return 0===t.indexOf("Europe/")||"Atlantic/Reykjavik"===t?(f=null,e("gdpr")):0===t.indexOf("US/")||0===t.indexOf("America/")&&["New_York","Chicago","Denver","Los_Angeles","Phoenix","Anchorage","Boise","Detroit","Indianapolis","Louisville","Menominee","Nome","Adak","Juneau","Sitka","Yakutat","Metlakatla","Kentucky","Indiana","North_Dakota"].some(function(e){return-1!==t.indexOf(e)})||"Pacific/Honolulu"===t?(f="US",e("ccpa")):(f=null,void e("gdpr"))}function te(){"dark"===r.theme&&document.documentElement.classList.add("cc-dark"),"right"===r.iconPosition&&document.documentElement.classList.add("cc-icon-right")}function ne(){var e=r.text,t=document.createElement("div");t.id="cc-overlay",document.body.appendChild(t);var n=document.createElement("div");n.id="cc-banner",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-label","Cookie consent"),n.setAttribute("tabindex","-1");var o=r.cookieTypes.map(function(t){var n=t.required?' <span class="cc-always-on">'+v(e.alwaysOnLabel)+"</span>":"";return'<div class="cc-cat"><div><div class="cc-cat-label">'+v(t.name)+n+'</div><div class="cc-cat-desc">'+v(t.description||"")+'</div></div><label class="cc-toggle"><input type="checkbox" id="cc-cb-'+v(t.id)+'" aria-label="'+v(t.name)+'"'+(t.required||t.defaultValue?" checked":"")+(t.required?" disabled":"")+'><span class="cc-slider"></span></label></div>'}).join("");n.innerHTML='<div class="cc-inner"><p class="cc-title">'+v(e.title)+'</p><p class="cc-text">'+v(e.description)+' <a href="'+v(r.privacyUrl)+'">Privacy Policy</a></p><div class="cc-buttons"><button class="cc-btn cc-btn-accept" id="cc-accept">'+v(e.acceptAllButton)+'</button><button class="cc-btn cc-btn-details" id="cc-details" aria-expanded="false">'+v(e.showDetailsButton)+'</button></div><div class="cc-categories" id="cc-cats">'+o+'</div><div class="cc-pref-buttons" id="cc-pref-buttons"><button class="cc-btn cc-btn-save" id="cc-save">'+v(e.saveButton)+'</button><button class="cc-btn cc-btn-decline" id="cc-decline">'+v(e.declineAllButton)+"</button></div></div>"+(r.showPoweredBy?'<div class="cc-powered"><a href="https://www.cookieflame.com" target="_blank" rel="noopener">Powered by CookieFlame</a></div>':""),document.body.appendChild(n);var c=document.createElement("button");c.id="cc-icon",c.setAttribute("aria-label","Cookie settings"),c.innerHTML='<svg width="24" height="24" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19.1 1.16c-.06-.42-.38-.77-.8-.83A11.8 11.8 0 0 0 13.28 1.2L7.5 4.3A11.8 11.8 0 0 0 3.95 7.98L1.09 13.9A11.8 11.8 0 0 0 .38 18.96l1.13 6.47a11.8 11.8 0 0 0 3.53 4.99l4.71 4.56a11.8 11.8 0 0 0 4.59 2.24l6.48.91a11.8 11.8 0 0 0 5.52-.89l5.78-3.09a11.8 11.8 0 0 0 3.55-3.69l2.87-5.9a11.8 11.8 0 0 0 .71-5.08c-.07-.41-.42-.73-.83-.79a14.8 14.8 0 0 1-8.16-7.61c-.14-.59-.63-1.05-1.23-1.14A14.8 14.8 0 0 1 19.1 1.16ZM15.25 10.25a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm-5 15a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0Zm17.5-5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z" fill="currentColor"/></svg>',document.body.appendChild(c),document.getElementById("cc-accept").addEventListener("click",se),document.getElementById("cc-decline").addEventListener("click",de),document.getElementById("cc-save").addEventListener("click",ue),document.getElementById("cc-details").addEventListener("click",le),c.addEventListener("click",function(){re("gdpr")})}var oe=null;function ce(e){if("Tab"===e.key){var t=document.getElementById("cc-banner")||document.getElementById("cc-ccpa-banner");if(t&&t.classList.contains("cc-show")){for(var n=[],o=t.querySelectorAll('button, a[href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])'),c=0;c<o.length;c++){for(var r=o[c],a=!1,i=r.parentElement;i&&i!==t;){if(i.style&&"none"===window.getComputedStyle(i).display){a=!0;break}i=i.parentElement}a||n.push(r)}if(0!==n.length){var s=n[0],d=n[n.length-1];e.shiftKey?document.activeElement===s&&(e.preventDefault(),d.focus()):document.activeElement===d&&(e.preventDefault(),s.focus())}}}}function re(e){"ccpa"!==e?(oe=document.activeElement,requestAnimationFrame(function(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.add("cc-show"),t){t.classList.add("cc-show");var o=t.querySelector(".cc-btn-accept");o&&o.focus(),document.addEventListener("keydown",ce)}n&&n.classList.remove("cc-show")})):requestAnimationFrame(function(){var e=document.getElementById("cc-ccpa-banner");e&&(e.classList.add("cc-show"),oe=document.activeElement,e.focus(),document.addEventListener("keydown",ce))})}function ae(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&"gdpr"===p&&n.classList.add("cc-show"),document.removeEventListener("keydown",ce),oe&&"function"==typeof oe.focus)try{oe.focus()}catch(e){}oe=null}function ie(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&n.classList.remove("cc-show"),document.removeEventListener("keydown",ce)}function se(){F(Y(),"accept_all"),ae(),_("cc:accept-all"),_("cc:update")}function de(){F(z(),"decline_all"),ae(),_("cc:decline-all"),_("cc:update")}function ue(){var e;F((e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f},r.cookieTypes.forEach(function(t){if(t.required)e[t.id]=!0;else{var n=document.getElementById("cc-cb-"+t.id);e[t.id]=!!n&&n.checked}}),e),"save_preferences"),ae(),_("cc:save"),_("cc:update")}function le(){var e=document.getElementById("cc-cats"),t=document.getElementById("cc-details"),n=document.getElementById("cc-pref-buttons"),o=e.classList.toggle("cc-open");t.textContent=o?r.text.hideDetailsButton:r.text.showDetailsButton,t.setAttribute("aria-expanded",o?"true":"false"),n&&(o?n.classList.add("cc-open"):n.classList.remove("cc-open"))}function pe(){var e=document.getElementById("cc-declaration");if(e){for(var t=k(),n={},o=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),c=0;c<o.length;c++){var a=u(o[c]);a&&(n[o[c]]={name:o[c],vendor:a.vendor,category:a.category,purpose:a.purpose,expiry:a.expiry||"",active:!0})}for(var i=0;i<d.length;i++){var s=d[i];s.name&&s.vendor&&s.category&&"unclassified"!==s.category&&!n[s.name]&&(n[s.name]={name:s.name,vendor:s.vendor,category:s.category,purpose:s.purpose||"",expiry:s.expiry||"",active:!1})}for(var l=0;l<o.length;l++)n[o[l]]||(n[o[l]]={name:o[l],vendor:"",category:"unclassified",purpose:"",expiry:"",active:!0});var p=["necessary","preferences","analytics","marketing"],f={};r.cookieTypes.forEach(function(e){f[e.id]=e.name});var m={};p.forEach(function(e){m[e]=[]}),Object.keys(n).forEach(function(e){var t=n[e],o=t.category;m[o]||(m[o]=[]),m[o].push(t)}),p.forEach(function(e){m[e]&&m[e].sort(function(e,t){return e.name.localeCompare(t.name)})});var g="<div>";if(t.timestamp){var y=new Date(t.timestamp);g+="<p>"+v("Your consent was last updated on "+y.toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"})+" at "+y.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})+".")+"</p>"}else g+="<p>"+v("You have not yet made a cookie preference choice on this site.")+"</p>";for(var h=0;h<p.length;h++){var w=p[h],b=m[w];if(b&&b.length){var _,x=f[w]||w,E=r.cookieTypes.filter(function(e){return e.id===w})[0],A=E&&E.description||"";_=!!E&&E.required?"Always active":t[w]?"Active":"Inactive",g+="<div>",g+="<p><b>"+v(x)+"</b> ("+v(_)+")</p>",A&&(g+="<p>"+v(A)+"</p>"),g+="<table><thead><tr>",g+="<th>Name</th><th>Provider</th><th>Purpose</th><th>Expiry</th>",g+="</tr></thead><tbody>";for(var S=0;S<b.length;S++){var L=b[S];g+="<tr>",g+="<td><code>"+v(L.name)+"</code></td>",g+="<td>"+v(L.vendor||"Unknown")+"</td>",g+="<td>"+v(L.purpose||"Not specified")+"</td>",g+="<td>"+v(L.expiry||"—")+"</td>",g+="</tr>"}g+="</tbody></table></div>"}}g+="</div>",e.innerHTML=g}}window.__ccInternal={getResourceSnapshot:ye,scriptLoaded:function(e){for(var t=ge||ye(),n=0;n<t.allUrls.length;n++)if(-1!==t.allUrls[n].indexOf(e))return!0;return!1},scriptLoadedUrls:function(e){for(var t=ge||ye(),n=[],o=0;o<t.allUrls.length;o++)-1!==t.allUrls[o].indexOf(e)&&n.push(t.allUrls[o]);return n},hasCookie:function(e){return document.cookie.split(";").some(function(t){return t.trim().split("=")[0]===e})},hasCookiePrefix:function(e){return document.cookie.split(";").some(function(t){return 0===t.trim().split("=")[0].indexOf(e)})},setResourceSnapshot:function(e){ge=e},visitorCookies:function(e){for(var t=ye().thirdPartyDomains,n={},o=0;o<e.length;o++)we(e[o],t,he(e[o]))&&(n[e[o]]=!0);return n},facadeBridge:{getConfig:function(){return r},getConsentState:function(){return l},loadConsent:Z,saveConsent:function(e,t){F(e,t)},hideAllBanners:ie,registerRenderer:function(e){R=e,M=2,V()}}},window.CookieConsent={getState:k,getConfig:function(){return r},getComplianceMode:function(){return p},getCountry:function(){return f},show:function(){re("gdpr")},acceptAll:se,declineAll:de,getGPC:function(){return i},getConsentVersion:function(){return r.consentVersion},on:function(e,t){window.addEventListener(e,t)},off:function(e,t){window.removeEventListener(e,t)},VERSION:c},window.addEventListener("cc:ready",pe),window.addEventListener("cc:update",pe),function(){if(!window.__ccDefaultsSet){var e={wait_for_update:500};r.cookieTypes.forEach(function(t){t.consentMode&&t.consentMode.forEach(function(n){e[n]=t.required?"granted":"denied"})}),x("consent","default",e)}}(),function(){if(r.tcfEnabled){var e=window.__tcfapi&&window.__tcfapi.queue?window.__tcfapi.queue:[];window.__tcfapi=C,e.forEach(function(e){C.apply(null,e)}),S=!0,window===window.top&&window.addEventListener("message",function(e){var t;try{t="string"==typeof e.data?JSON.parse(e.data):e.data}catch(e){return}if(t&&t.__tcfapiCall){var n=t.__tcfapiCall;C(n.command,n.version,function(t,o){var c={__tcfapiReturn:{returnValue:t,success:o,callId:n.callId}};e.source&&e.source.postMessage("string"==typeof e.data?JSON.stringify(c):c,"*")},n.parameter)}})}}();var fe=Z();function me(){var e=window.__ccDiscovery&&window.__ccDiscovery.active;if(!e&&(window.__ccDNT||document.cookie.split(";").some(function(e){return 0===e.trim().indexOf("cookieflame_dnt=")})))return E(l=z()),K(l,Y()),J(),j(),p="dnt",te(),ne(),ie(),$(l),_("cc:ready"),void pe();if(e){E(l=Y()),T(l),J(),H(l,null),r.tcfEnabled&&B(l),window.dataLayer=window.dataLayer||[];for(var t=["consent_accepted_analytics","consent_accepted_marketing","consent_accepted_preferences","consent_accepted_necessary","consent_update","consent_given","cookie_consent_given","cookie_consent_update","consent_accepted"],n=0;n<t.length;n++)window.dataLayer.push({event:t[n]});return p="discovery",te(),ne(),ie(),_("cc:ready"),_("cc:update"),void pe()}var o=Z();if(o)if(i&&(o.marketing=!1),l=o,E(o),T(o),J(),j(),H(o,null),r.tcfEnabled&&B(o),te(),ne(),ie(),$(o),o.cc){if("gdpr"===(p=Q(o.cc))){var c=document.getElementById("cc-icon");c&&c.classList.add("cc-show")}_("cc:ready"),pe()}else X(function(e){if(p=e,"gdpr"===e){var t=document.getElementById("cc-icon");t&&t.classList.add("cc-show")}_("cc:ready"),pe()});else X(function(e){if(p=e,"none"===e)return J(),F(Y(),"auto_grant_non_eu"),_("cc:ready"),_("cc:update"),void pe();if("ccpa"===e){if(J(),i){var t=Y();t.marketing=!1,F(t,"ccpa_gpc_optout")}else F(Y(),"ccpa_auto_grant");return te(),n=r.text,(o=document.createElement("div")).id="cc-ccpa-banner",o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true"),o.setAttribute("aria-label","Privacy notice"),o.setAttribute("tabindex","-1"),o.innerHTML='<div class="cc-ccpa-inner"><div class="cc-ccpa-text"><p>'+v(n.ccpaDescription)+'</p></div><div class="cc-ccpa-actions"><a href="'+v(r.ccpaUrl)+'" class="cc-ccpa-link">'+v(n.ccpaDnsmpiLink)+'</a><button class="cc-btn cc-btn-accept" id="cc-ccpa-ok">'+v(n.ccpaAcceptButton)+"</button></div></div>",document.body.appendChild(o),document.getElementById("cc-ccpa-ok").addEventListener("click",function(){F(Y(),"ccpa_acknowledge"),o.classList.remove("cc-show"),_("cc:update")}),re("ccpa"),_("cc:ready"),_("cc:update"),void pe()}var n,o;te(),J(),j(),ne(),re("gdpr"),_("cc:ready"),pe()})}fe&&(l=fe,E(fe)),function(){if(!g&&r.autoBlockPatterns&&r.autoBlockPatterns.length){g=!0;var e=document.createElement.bind(document),t=Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src");t&&t.set&&(document.createElement=function(){var n=e.apply(document,arguments);if("script"!==(arguments[0]||"").toLowerCase())return n;function o(e,t){if(t&&"string"==typeof t&&!e.getAttribute("data-cc")&&!e.getAttribute("data-cc-auto")&&-1===t.indexOf("cookieconsent")){var n=I(t);!n||l&&l[n]||(e.type="text/plain",e.setAttribute("data-cc",n),e.setAttribute("data-cc-auto","1"))}}Object.defineProperty(n,"src",{configurable:!0,enumerable:!0,get:function(){return t.get.call(this)},set:function(e){return o(this,e),t.set.call(this,e)}});var c=n.setAttribute.bind(n);return n.setAttribute=function(e,t){return"src"===e.toLowerCase()&&o(n,t),c(e,t)},n}),new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){var t=[];"SCRIPT"===e.tagName&&t.push(e),e.querySelectorAll&&e.querySelectorAll("script[src]").forEach(function(e){t.push(e)}),t.forEach(function(e){if(!(e.getAttribute("data-cc-auto")||e.getAttribute("data-cc")||e.src&&-1!==e.src.indexOf("cookieconsent"))){var t=I(e.src);t&&(l&&l[t]||(e.type="text/plain",e.setAttribute("data-cc",t),e.setAttribute("data-cc-auto","1")))}})}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}}(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",me):me();var ge=null;function ye(){for(var e=[],t=[],n=[],o={},c={},r=document.querySelectorAll("script[src]"),a=0;a<r.length;a++)r[a].src&&e.push(r[a].src);for(var i=document.querySelectorAll("iframe[src]"),s=0;s<i.length;s++)i[s].src&&e.push(i[s].src);if(window.performance&&performance.getEntriesByType)for(var d=performance.getEntriesByType("resource"),u=0;u<d.length;u++){var l=d[u].name||"";if(l){-1===e.indexOf(l)&&e.push(l);var p=d[u].initiatorType||"";if("script"===p||"iframe"===p||"xmlhttprequest"===p||"fetch"===p||-1!==l.indexOf(".js"))try{var f=new URL(l),m=f.hostname;if(m===location.hostname||m==="www."+location.hostname||"www."+m===location.hostname){var g=f.pathname.match(/\/wp-content\/plugins\/([^\/]+)\//);g&&!c[g[1]]&&(c[g[1]]=!0,n.push({slug:g[1],url:l}))}else o[m]||(o[m]=!0,t.push(m))}catch(e){}}}return{allUrls:e,thirdPartyDomains:t,pluginScripts:n}}var ve={};function he(e){var t={set_by:"",set_by_plugin:""},n=window.__ccCookieSetters;if(!n||!Object.prototype.hasOwnProperty.call(n,e)||!n[e])return t;try{var o=new URL(String(n[e]).replace(/:\d+(:\d+)?$/,""));if(/^(chrome-extension|moz-extension|safari-web-extension|safari-extension):$/.test(o.protocol))return t.set_by="browser-extension",t;var c=o.hostname;if(c===location.hostname||c==="www."+location.hostname||"www."+c===location.hostname){t.set_by="first-party";var r=o.pathname.match(/\/wp-content\/(?:plugins|themes)\/([^\/]+)\//);r&&(t.set_by_plugin=r[1].toLowerCase())}else t.set_by=c.toLowerCase()}catch(e){}return t}function we(e,t,n){if("browser-extension"===n.set_by)return!0;var o=window.__ccVisitorCookieRules;if(!o||!o.tools)return!1;if(o.allow&&-1!==o.allow.indexOf(e))return!1;if(n.set_by)return!1;for(var c=0;c<o.tools.length;c++){for(var r=o.tools[c],a=-1!==(r.n||[]).indexOf(e),i=0;!a&&i<(r.p||[]).length;i++)0===e.indexOf(r.p[i])&&(a=!0);if(a){for(var s=0;s<t.length;s++)for(var d=0;d<(r.d||[]).length;d++){var u=String(t[s]).toLowerCase(),l=r.d[d];if(u===l||u.slice(-l.length-1)==="."+l)return!1}return!0}}return!1}function be(){var t=window.__ccClassified||[],n=window.__ccUnclassified||[],o=window.__ccBeaconUrl;if(o){var c,r={};for(c=0;c<t.length;c++)r[t[c]]=!0;for(c=0;c<n.length;c++)r[n[c]]=!0;var a=Object.keys(ve);for(c=0;c<a.length;c++)r[a[c]]=!0;var i=Object.keys(s);for(c=0;c<i.length;c++)r[i[c]]=!0;var d={},u=[],l=document.cookie.split(";");for(c=0;c<l.length;c++){var p=l[c].indexOf("="),f=(p>-1?l[c].substring(0,p):l[c]).trim(),m=p>-1?l[c].substring(p+1).trim():"";f&&(u.push(f),d[f]=m)}var g=[];for(c=0;c<u.length;c++)if(!r[u[c]]){for(var y=!1,v=Object.keys(s),h=0;h<v.length;h++)if(s[v[h]].prefix&&0===u[c].indexOf(v[h])){y=!0;break}y||g.push(u[c])}if(0!==g.length){for(var w=ye(),b=w.thirdPartyDomains,k=[],_=0;_<w.pluginScripts.length;_++)k.push(w.pluginScripts[_].slug);for(var x=location.pathname,E=0;E<g.length;E++){var A=g[E],S=!!e[A]&&!r[A],L=ke(d[A]||""),C=he(A);if(!we(A,b,C)||window.__ccDiscovery&&window.__ccDiscovery.active){var B=JSON.stringify({cookie_name:A,script_domains:b,plugin_scripts:k,page_path:x,pre_existing:S,value_shape:L,set_by:C.set_by,set_by_plugin:C.set_by_plugin});ve[A]=!0,navigator.sendBeacon&&navigator.sendBeacon(o,new Blob([B],{type:"application/json"}))}else ve[A]=!0}}}}function ke(e){if(!e||0===e.length)return"empty";if("true"===e||"false"===e||"1"===e||"0"===e)return"boolean";if(/^\d+$/.test(e))return e.length>12?"long-numeric":"numeric";if(/^\d+\.\d+$/.test(e))return"decimal";if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return"uuid";if(/^[A-Za-z0-9+\/]{20,}={0,2}$/.test(e))return"base64";if(/^(GA\d+\.\d+\.\d+\.\d+|G-[A-Z0-9]+)/.test(e))return"ga-id";try{if("object"==typeof JSON.parse(decodeURIComponent(e)))return"json"}catch(e){}return/^[a-f0-9]{24,}$/i.test(e)?"hex-id":/^\d{10,13}$/.test(e)?"timestamp":e.length<=20?"short-string":e.length<=100?"medium-string":"long-string"}setTimeout(be,3e3),setTimeout(be,15e3),setTimeout(be,45e3),window.addEventListener("cc:update",function(){setTimeout(be,3e3)}),window.addEventListener("pagehide",be)}(); -
cookieflame/tags/5.3.0/cookieflame.php
r3768250 r3769546 4 4 * Plugin URI: https://cookieflame.com 5 5 * Description: A lightweight, self-hosted cookie consent manager with Google Consent Mode v2, IAB TCF v2.2, automatic script blocking, multi-region compliance (GDPR/CCPA/LGPD/POPIA), passive cookie monitoring, and server-side geo detection via Cloudflare. 6 * Version: 5. 2.06 * Version: 5.3.0 7 7 * Requires at least: 6.0 8 8 * Requires PHP: 8.0 … … 19 19 } 20 20 21 define( 'COOKIEFLAME_VERSION', '5. 2.0' );21 define( 'COOKIEFLAME_VERSION', '5.3.0' ); 22 22 define( 'COOKIEFLAME_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 23 23 define( 'COOKIEFLAME_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 219 219 // cookieconsent-discovery.js via the cookieflameAdmin global. 220 220 require_once COOKIEFLAME_PLUGIN_DIR . 'includes/service-detectors.php'; 221 require_once COOKIEFLAME_PLUGIN_DIR . 'includes/consent-tools.php'; 221 222 222 223 /* ═══════════════════════════════════════════════════════════ … … 1140 1141 foreach ( $ignored as $ig ) { 1141 1142 if ( ( $ig['name'] ?? '' ) === $cookie_name ) { 1142 if ( ! $discovery_active ) { 1143 // Cookies ignored automatically as visitor-side cookies stay ignored 1144 // during discovery unless their source now checks out (the admin's 1145 // own browser may carry the same extension). 1146 $still_visitor = ! empty( $ig['auto'] ) && '' !== cookieflame_visitor_cookie_reason( $cookie_name, $script_domains, $set_by ); 1147 if ( ! $discovery_active || $still_visitor ) { 1143 1148 return new WP_REST_Response( array( 'received' => true, 'status' => 'ignored' ), 200 ); 1144 1149 } … … 1150 1155 break; 1151 1156 } 1157 } 1158 1159 // Another consent tool's cookie that doesn't run here, or a cookie a 1160 // browser extension wrote: it came with the visitor's browser, not from 1161 // this site. Record it on the ignore list with the reason. 1162 $visitor_reason = cookieflame_visitor_cookie_reason( $cookie_name, $script_domains, $set_by ); 1163 if ( '' !== $visitor_reason ) { 1164 global $wpdb; 1165 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- MySQL named lock; a lock must not be cached. 1166 $locked = (int) $wpdb->get_var( "SELECT GET_LOCK( 'cookieflame_beacon', 5 )" ); 1167 wp_cache_delete( 'alloptions', 'options' ); 1168 cookieflame_ignore_visitor_cookie( $cookie_name, $visitor_reason ); 1169 if ( $locked ) { 1170 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Releases the MySQL named lock taken above. 1171 $wpdb->query( "SELECT RELEASE_LOCK( 'cookieflame_beacon' )" ); 1172 } 1173 return new WP_REST_Response( array( 'received' => true, 'status' => 'visitor_cookie' ), 200 ); 1152 1174 } 1153 1175 … … 1364 1386 function cookieflame_sanitize_set_by( $value ) { 1365 1387 $value = strtolower( trim( is_scalar( $value ) ? (string) $value : '' ) ); 1366 if ( 'first-party' === $value ) {1388 if ( 'first-party' === $value || 'browser-extension' === $value ) { 1367 1389 return $value; 1368 1390 } … … 1879 1901 1880 1902 if ( $action === 'restore' ) { 1903 // Restoring a cookie that was ignored automatically as a visitor-side 1904 // cookie is the admin overruling that check, so remember it. 1905 foreach ( $ignored as $ig ) { 1906 if ( ( $ig['name'] ?? '' ) === $name && ! empty( $ig['auto'] ) ) { 1907 $allow = (array) get_option( 'cookieflame_visitor_cookie_allow', array() ); 1908 $allow[] = $name; 1909 update_option( 'cookieflame_visitor_cookie_allow', array_values( array_unique( $allow ) ) ); 1910 } 1911 } 1881 1912 $ignored = array_values( array_filter( $ignored, function( $ig ) use ( $name ) { 1882 1913 return ( $ig['name'] ?? '' ) !== $name; … … 2216 2247 'ignoredCookies' => get_option( 'cookieflame_ignored_cookies', array() ), 2217 2248 'ignoredCookiesUrl' => rest_url( 'cookieflame/v1/ignored-cookies' ), 2249 'visitorCookieRules' => cookieflame_visitor_cookie_rules(), 2250 'siteScriptDomains' => cookieflame_site_script_domains(), 2218 2251 'serviceDetectors' => cookieflame_get_service_detectors(), 2219 2252 ); … … 2470 2503 . "set:function(v){try{var n=String(v).split('=')[0].trim();" 2471 2504 . "if(n&&!Object.prototype.hasOwnProperty.call(w,n)){" 2472 . "var u=String((new Error()).stack||'').match(/ https?:\\/\\/[^\\s)'\"]+/g)||[];"2505 . "var u=String((new Error()).stack||'').match(/(?:https?|chrome-extension|moz-extension|safari-web-extension|safari-extension):\\/\\/[^\\s)'\"]+/g)||[];" 2473 2506 . "w[n]=u.length>1?u[1]:'';}}catch(e){}" 2474 2507 . "d.set.call(this,v);}});" … … 2643 2676 // active discovery only; no REST URLs or nonces are exposed. 2644 2677 $parts[] = 'window.cookieflameAdmin=Object.assign(window.cookieflameAdmin||{},' . wp_json_encode( array( 2645 'serviceDetectors' => cookieflame_get_service_detectors(), 2678 'serviceDetectors' => cookieflame_get_service_detectors(), 2679 'ignoredCookieNames' => array_values( array_filter( array_column( (array) get_option( 'cookieflame_ignored_cookies', array() ), 'name' ) ) ), 2646 2680 ) ) . ');'; 2647 2681 } … … 2680 2714 if ( ! cookieflame_monitoring_is_off() ) { 2681 2715 $parts[] = 'window.__ccBeaconUrl=' . wp_json_encode( rest_url( 'cookieflame/v1/beacon' ) ) . ';'; 2716 // Other consent tools' cookies to skip (see includes/consent-tools.php). 2717 $parts[] = 'window.__ccVisitorCookieRules=' . wp_json_encode( cookieflame_visitor_cookie_rules() ) . ';'; 2682 2718 } 2683 2719 … … 2686 2722 implode( '', $parts ), 2687 2723 array( 2724 'id' => 'cookieflame-config', 2688 2725 'data-cfasync' => 'false', 2689 2726 'data-no-optimize' => '1', … … 3014 3051 } 3015 3052 3016 // 2. Duplicate consent plugins 3053 // 2. Duplicate consent plugins. CookieFlame's own page settings name 3054 // other consent tools (the cookies it skips, cookie names it has seen), 3055 // so they are left out of this check. 3056 $consent_html = preg_replace( '#<script\b[^>]*\bid=(["\'])cookieflame-config\1[^>]*>[\s\S]*?</script>#i', '', $html ); 3017 3057 $consent_checks = array( 3018 3058 array( 'cookiebot.com', 'Cookiebot' ), … … 3026 3066 array( 'usercentrics.eu', 'Usercentrics' ), 3027 3067 ); 3068 // The check reads the page's code, so the other tool may come from a 3069 // plugin, a page builder's custom code, the theme or a scripts plugin: 3070 // say what was found and where, not just "deactivate the plugin". 3071 $consent_page = substr( (string) wp_parse_url( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '/' ) ), PHP_URL_PATH ), 0, 120 ); 3028 3072 foreach ( $consent_checks as $check ) { 3029 if ( stripos( $html, $check[0] ) !== false ) {3073 if ( stripos( (string) $consent_html, $check[0] ) !== false ) { 3030 3074 $conflicts[] = array( 3031 3075 'type' => 'duplicate_consent', 3032 3076 'severity' => 'critical', 3033 'title' => $check[1] . ' consent plugin detected',3034 'description' => ' Running two cookie consent plugins simultaneously causes unpredictable behaviour. Visitors may see two consent banners, scripts may be blocked or allowed inconsistently, and consent signals can conflict.',3035 'action' => ' Deactivate ' . $check[1] . ' if you intend to use CookieFlame as your consent solution.',3077 'title' => $check[1] . ' found on your pages', 3078 'description' => 'Your pages load ' . $check[1] . '\'s code as well as CookieFlame. Two consent tools on one site can show visitors two banners, block or allow scripts unpredictably, and mix up the choices visitors make. Found on ' . ( in_array( $consent_page, array( '', '/' ), true ) ? 'your home page' : $consent_page ) . '. In that page\'s source, search for "' . $check[0] . '".', 3079 'action' => 'Remove ' . $check[1] . '\'s code if CookieFlame is your consent tool. It isn\'t always a plugin: also check your page builder\'s custom code (for example Elementor > Custom Code), your theme\'s header, and any header and footer scripts plugin. Then visit a page on your site again to update this check.', 3036 3080 ); 3037 3081 } … … 4622 4666 </th> 4623 4667 <th style="width:14%"> 4624 <?php esc_html_e( 'Source', 'cookieflame' ); ?> 4625 <button type="button" class="cf-admin-help-btn" data-help-title="<?php esc_attr_e( 'Source', 'cookieflame' ); ?>" data-help="<?php esc_attr_e( 'How this cookie was identified. Known: recognised from our built-in database. Auto-Identified: classified automatically by the CookieFlame service. Edited: you changed the classification from the default. Reported: discovered by visitors browsing your site. Unclassified: not yet identified.', 'cookieflame' ); ?>">?</button> 4668 <?php esc_html_e( 'Status', 'cookieflame' ); ?> 4669 <?php 4670 $cookieflame_status_help = array( 4671 array( '', __( 'Where each cookie stands, and what you can do with it.', 'cookieflame' ) ), 4672 array( __( 'Not identified yet', 'cookieflame' ), __( 'CookieFlame doesn\'t know this cookie yet, so your banner doesn\'t list it. Red rows were reported by visitors or found by your scan. Yellow rows were only seen in your own browser.', 'cookieflame' ) ), 4673 array( __( 'Known, Auto-Identified, Classified', 'cookieflame' ), __( 'In CookieFlame\'s built-in list, named by the CookieFlame service, or sorted by Cookie Discovery or by you in this table.', 'cookieflame' ) ), 4674 array( __( 'Added by you, Changed by you', 'cookieflame' ), __( 'Your own settings. Re-identify only ever suggests changes to these.', 'cookieflame' ) ), 4675 array( __( 'Lock as correct (Pro)', 'cookieflame' ), __( 'Once you\'ve checked a cookie, CookieFlame won\'t change it, even when you re-identify.', 'cookieflame' ) ), 4676 array( __( 'Auto-Identify, Re-identify (Pro)', 'cookieflame' ), __( 'Ask the CookieFlame service what the cookie is.', 'cookieflame' ) ), 4677 array( __( 'Remove', 'cookieflame' ), __( 'Asks why first. If your site doesn\'t use it any more, it\'s taken off your list and comes back if it\'s seen again. If it isn\'t from your site, it\'s hidden for good on the Permanently Ignored list.', 'cookieflame' ) ), 4678 ); 4679 $cookieflame_status_html = ''; 4680 foreach ( $cookieflame_status_help as $cookieflame_help_item ) { 4681 $cookieflame_status_html .= '<p>' . ( $cookieflame_help_item[0] ? '<strong>' . esc_html( $cookieflame_help_item[0] ) . ':</strong> ' : '' ) . esc_html( $cookieflame_help_item[1] ) . '</p>'; 4682 } 4683 ?> 4684 <button type="button" class="cf-admin-help-btn" data-help-title="<?php esc_attr_e( 'Status', 'cookieflame' ); ?>" data-help-html="<?php echo esc_attr( '<div class="cf-admin-help-list">' . $cookieflame_status_html . '</div>' ); ?>">?</button> 4626 4685 </th> 4627 4686 </tr> -
cookieflame/tags/5.3.0/readme.txt
r3768250 r3769546 5 5 Tested up to: 7.1 6 6 Requires PHP: 8.0 7 Stable tag: 5. 2.07 Stable tag: 5.3.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 195 195 == Changelog == 196 196 197 = 5.3.0 = 198 * Cookie monitoring now ignores cookies that come with a visitor's browser rather than from your site. Some browser extensions write the "already accepted" cookies of other consent tools (such as Complianz, CookieYes, Cookiebot, OneTrust or Didomi) onto every site they visit, and these were being reported as your site's cookies. A consent tool's cookie is now ignored when that tool doesn't run on your site: its plugin isn't active, its script isn't on the page, and no script on the page wrote the cookie. 199 * Cookies written by a browser extension's own code are ignored too. 200 * Cookies ignored this way go on the Permanently Ignored list with the reason, and the list now shows why each cookie was ignored. Restoring one keeps it monitored from then on. 201 * The Cookie Manager and the Cookie Discovery count leave these cookies out too, including ones your own browser extensions add. Cookies that came with your browser during Cookie Discovery go on the Permanently Ignored list with the reason. Cookies on the Permanently Ignored list no longer show in the Cookie Manager just because they are in your own browser. 202 * On update, other consent tools' cookies that were already reported are moved to the Permanently Ignored list. Cookies you classified yourself are left alone. 203 * Fixed: the "consent plugin detected" conflict warning could be set off by CookieFlame's own list of cookie names rather than by another consent plugin on the page. 204 * Cookie Manager: the last column is now "Status". Each cookie shows one label for where it stands (Known, Auto-Identified, Classified, Added by you, Changed by you, or Not identified yet), and cookies that aren't identified yet say where they came from: found by your scan, reported by visitors, or seen in your own browser. 205 * Cookie Manager: Remove and Ignore permanently are now one "Remove…" link that asks why. "My site doesn't use it any more" takes the cookie off your list, and it comes back if it's seen again. "It's not from my site" puts it on the Permanently Ignored list for good. 206 * Cookie Manager: with CookieFlame Pro, the padlock is now a "Lock as correct" button. A locked cookie keeps its vendor, category and purpose, even when you re-identify. 207 * Cookie Manager: the small help buttons beside each link are gone. Each link explains itself when you hover over it, and the Status column's help button explains every label and action. 208 * Improved: when another consent tool's code is on your pages, the warning now says so in plain words ("Cookiebot found on your pages"), names the page and the text to look for, and lists where such code usually lives (plugins, page builder custom code such as Elementor > Custom Code, the theme's header, or a header and footer scripts plugin). It used to say a plugin was installed even when the code came from somewhere else. 209 197 210 = 5.2.0 = 198 211 * Cookie monitoring now records which script first wrote each new cookie: a third-party script's domain, or the WordPress plugin or theme that set it. Previously only the full list of third-party scripts on the page was known. Cookie values are never read or sent. … … 229 242 == Upgrade Notice == 230 243 244 = 5.3.0 = 245 Cookie monitoring now ignores other consent tools' cookies that visitors' browser extensions add, so they no longer appear as your site's cookies. The Cookie Manager's last column is tidier and easier to understand. 246 231 247 = 5.2.0 = 232 248 Better cookie detection: CookieFlame now records which script set each new cookie and keeps checking after consent is given. -
cookieflame/tags/5.3.0/uninstall.php
r3766806 r3769546 31 31 delete_option( 'cookieflame_dismissed_cookies' ); 32 32 delete_option( 'cookieflame_ignored_cookies' ); 33 delete_option( 'cookieflame_visitor_cookie_allow' ); 34 delete_option( 'cookieflame_visitor_cleanup' ); 33 35 delete_option( 'cookieflame_discovery_backup' ); 34 36 delete_option( 'cookieflame_maxmind_last_update' ); -
cookieflame/trunk/assets/css/admin.css
r3766806 r3769546 394 394 } 395 395 396 /* S ource column*/396 /* Status column: one label, then the actions, one per line */ 397 397 .cf-admin-source-cell { 398 398 font-size: 12px; … … 403 403 margin-top: 1px; 404 404 } 405 .cf-admin-status-line + .cf-admin-status-line { 406 margin-top: 3px; 407 } 408 .cf-admin-status-where { 409 color: #646970; 410 line-height: 1.4; 411 } 405 412 .cf-admin-source-link { 406 font-size: 1 1px;407 color: # 646970;413 font-size: 12px; 414 color: #2271b1; 408 415 text-decoration: none; 409 416 cursor: pointer; 410 417 display: inline-block; 411 margin-top: 2px;412 418 transition: color .15s; 413 419 } 414 420 .cf-admin-source-link:hover { 415 color: # 2271b1;421 color: #135e96; 416 422 text-decoration: underline; 423 } 424 .cf-admin-source-link-main { 425 font-weight: 600; 417 426 } 418 427 … … 474 483 align-items: center; 475 484 gap: 4px; 476 font-size: 11px; 477 font-weight: 600; 485 font-size: 12px; 486 font-weight: 600; 487 line-height: 20px; 488 padding: 0 8px; 489 border-radius: 3px; 478 490 } 479 491 .cf-admin-badge-known, 480 492 .cf-admin-badge-ai { 481 color: #00a32a; 493 color: #00701f; 494 background: #e6f4e9; 482 495 } 483 496 .cf-admin-badge-edited { 484 color: #2271b1; 497 color: #135e96; 498 background: #e9f1fa; 485 499 } 486 500 .cf-admin-badge-locked { 487 color: #996800; 501 color: #8a5b00; 502 background: #fcf3e1; 488 503 } 489 504 .cf-admin-badge-unclassified { 490 color: #d63638; 505 color: #8a5b00; 506 background: #fff; 507 box-shadow: inset 0 0 0 1px #dba617; 491 508 } 492 509 … … 859 876 -webkit-user-select: text; 860 877 } 878 .cf-admin-help-list p { 879 margin: 0 0 8px; 880 line-height: 1.5; 881 } 882 .cf-admin-help-list p:last-child { 883 margin-bottom: 0; 884 } 861 885 @keyframes cf-admin-fade-in { 862 886 from { opacity: 0; } … … 1942 1966 } 1943 1967 1944 /* Lock toggle (unstyled button) */ 1945 .cf-admin-lock-toggle { 1946 background: none; 1947 border: none; 1948 cursor: pointer; 1968 /* Lock as correct: a labelled button that fills in when locked */ 1969 .cf-admin-source-cell .button.cf-admin-lock-toggle { 1970 display: inline-flex; 1971 align-items: center; 1972 gap: 3px; 1973 font-size: 12px; 1974 min-height: 24px; 1975 line-height: 22px; 1976 padding: 0 8px 0 6px; 1977 } 1978 .cf-admin-lock-toggle .dashicons { 1949 1979 font-size: 14px; 1950 padding: 0 2px; 1951 vertical-align: middle; 1980 width: 14px; 1981 height: 14px; 1982 } 1983 .cf-admin-source-cell .button.cf-admin-lock-toggle.is-locked { 1984 background: #fcf3e1; 1985 border-color: #dba617; 1986 color: #8a5b00; 1952 1987 } 1953 1988 … … 1999 2034 font-size: 12px; 2000 2035 padding: 8px 12px; 2036 } 2037 2038 /* Remove…: asks why, in a bar under the row */ 2039 .cf-admin-inline-bar-remove { 2040 background: #f6f7f7; 2041 border-left: 3px solid #8c8f94; 2042 font-size: 13px; 2043 padding: 10px 14px; 2044 } 2045 .cf-admin-remove-choices { 2046 display: flex; 2047 flex-wrap: wrap; 2048 align-items: stretch; 2049 gap: 8px; 2050 margin-top: 8px; 2051 } 2052 .cf-admin-remove-choices .button { 2053 display: flex; 2054 flex-direction: column; 2055 align-items: flex-start; 2056 gap: 2px; 2057 max-width: 380px; 2058 height: auto; 2059 padding: 6px 12px; 2060 line-height: 1.4; 2061 text-align: left; 2062 white-space: normal; 2063 } 2064 .cf-admin-remove-choices .button span, 2065 .cf-admin-remove-hint { 2066 font-size: 12px; 2067 color: #646970; 2068 } 2069 .cf-admin-remove-hint { 2070 display: block; 2071 margin-top: 2px; 2072 } 2073 .cf-admin-remove-cancel { 2074 align-self: center; 2075 margin-left: 4px; 2001 2076 } 2002 2077 … … 2053 2128 } 2054 2129 2055 /* Not-active indicator label */2056 .cf-admin-not-active-label {2057 font-size: 11px;2058 color: #646970;2059 display: inline-block;2060 margin-top: 3px;2061 }2062 2063 2130 /* Origin column cell */ 2064 2131 .cf-admin-origin-cell { 2065 2132 font-size: 12px; 2066 }2067 2068 /* Ignore link — muted by default */2069 .cf-admin-ignore-cookie.cf-admin-source-link {2070 color: #888;2071 2133 } 2072 2134 -
cookieflame/trunk/assets/js/admin.js
r3766806 r3769546 148 148 * Queue a DELETE for a single cookie via the REST endpoint. 149 149 */ 150 function queueDelete(cookieName, opts, onDone ) {150 function queueDelete(cookieName, opts, onDone, onFail) { 151 151 // opts is optional: queueDelete(name, fn) or queueDelete(name, {dismissed:true}, fn) 152 if (typeof opts === "function") { on Done = opts; opts = {}; }152 if (typeof opts === "function") { onFail = onDone; onDone = opts; opts = {}; } 153 153 opts = opts || {}; 154 154 fetch(cookieflameAdmin.cookieUrl + "/" + encodeURIComponent(cookieName), { … … 164 164 .catch(function (err) { 165 165 cookieflameNotice("Failed to remove \"" + cookieName + "\": " + err.message, "error"); 166 if (onFail) onFail(); 166 167 }); 167 168 } … … 463 464 } 464 465 466 /** 467 * Whether a cookie in the admin's own browser is another consent tool's 468 * cookie when that tool doesn't run on this site (its plugin isn't active 469 * and its script hasn't been seen on the site's pages). Browser extensions 470 * that get around consent banners write these. Same rules as the visitor 471 * check in cookieconsent.js, without the page context. 472 */ 473 function isVisitorOnlyCookie(name) { 474 var rules = cookieflameAdmin && cookieflameAdmin.visitorCookieRules; 475 if (!rules || !rules.tools) return false; 476 if (rules.allow && rules.allow.indexOf(name) !== -1) return false; 477 var domains = cookieflameAdmin.siteScriptDomains || []; 478 for (var t = 0; t < rules.tools.length; t++) { 479 var tool = rules.tools[t], hit = (tool.n || []).indexOf(name) !== -1; 480 for (var p = 0; !hit && p < (tool.p || []).length; p++) { 481 if (name.indexOf(tool.p[p]) === 0) hit = true; 482 } 483 if (!hit) continue; 484 for (var d = 0; d < domains.length; d++) { 485 for (var k = 0; k < (tool.d || []).length; k++) { 486 var host = String(domains[d]).toLowerCase(), dom = tool.d[k]; 487 if (host === dom || host.slice(-dom.length - 1) === "." + dom) return false; 488 } 489 } 490 return true; 491 } 492 return false; 493 } 494 465 495 /* ═══════════════════════════════════════════ 466 496 RENDER SCAN TABLE … … 650 680 var CAT_ORDER = { necessary: 0, preferences: 1, analytics: 2, marketing: 3, unclassified: 4 }; 651 681 682 var ignoredSet = {}; 683 var ignoredList = (cookieflameAdmin && cookieflameAdmin.ignoredCookies) || []; 684 for (var il = 0; il < ignoredList.length; il++) { 685 if (ignoredList[il] && ignoredList[il].name) ignoredSet[ignoredList[il].name] = true; 686 } 687 652 688 // Pre-process: build row data objects for sorting 653 689 var rowData = []; … … 660 696 var custom = findCustom(name); 661 697 var builtin = identifyBuiltIn(name); 698 699 // Cookies you haven't classified stay out of the table when they are on 700 // the Permanently Ignored list, or when only your own browser carries 701 // them and they belong to a consent tool that doesn't run on this site. 702 if (!custom && ignoredSet[name]) continue; 703 if (!custom && !beaconData[name] && !cookieOriginMap[name] && isVisitorOnlyCookie(name)) continue; 662 704 663 705 // Determine source (same logic as before) … … 794 836 divider.innerHTML = '<td colspan="7">' + 795 837 '<span class="cf-admin-cat-dot" style="background:' + (CAT_COLORS[lastCat] || "#a7aaad") + '"></span>' + 796 '<span class="cf-admin-cat-label">' + esc(lastCat .charAt(0).toUpperCase() + lastCat.slice(1)) + '</span>' +838 '<span class="cf-admin-cat-label">' + esc(lastCat === "unclassified" ? "Not identified yet" : lastCat.charAt(0).toUpperCase() + lastCat.slice(1)) + '</span>' + 797 839 '<span class="cf-admin-cat-count">(' + catCount + ')</span>' + 798 840 '</td>'; … … 800 842 } 801 843 802 // Source column content 803 var removeTip = 'Removes this cookie from the Cookie Manager. It will reappear as a new unclassified cookie if a visitor still has it in their browser. Use this if you classified it incorrectly and want to start again.'; 804 var ignoreTip = 'Permanently hides this cookie from the Cookie Manager. Visitor sessions will silently skip it and it will not trigger email notifications. Use this for cookies that are not from your site, such as those set by browser extensions. If you later reinstall the service that set it, Start Cookie Discovery will detect it again and automatically remove it from the ignore list. You can also restore ignored cookies manually from the Ignored Cookies panel at the bottom of this page.'; 805 var removeHtml = '<br><a href="#" class="cf-admin-delete-cookie cf-admin-source-link" data-name="' + esc(rd.name) + '">Remove</a>' + 806 ' <button type="button" class="cf-admin-help-btn cf-admin-help-btn-sm" ' + 807 'data-help-title="Remove cookie" data-help="' + esc(removeTip) + '">?</button>' + 808 '<br><a href="#" class="cf-admin-ignore-cookie cf-admin-source-link" data-name="' + esc(rd.name) + '">Ignore permanently</a>' + 809 ' <button type="button" class="cf-admin-help-btn cf-admin-help-btn-sm" ' + 810 'data-help-title="Ignore permanently" data-help="' + esc(ignoreTip) + '">?</button>'; 811 812 var sourceHtml; 813 814 // Helper: lock badge + toggle for classified sources 815 function _lockBadgeHtml(src, lock, name) { 816 var badge, lockIcon, lockTip, aiLabel, reIdLabel; 817 // Determine badge 818 if (lock === "locked") { 819 badge = '<span class="cf-admin-badge-locked">🔒 Locked</span>'; 820 } else if (lock === "edited") { 821 badge = '<span class="cf-admin-badge-edited">✎ Customised</span>'; 822 } else { 823 // Managed: show original source label 824 if (src === "ai") { aiLabel = "Auto-Identified"; } 825 else if (src === "discovered") { aiLabel = "Classified"; } 826 else if (src === "manual") { aiLabel = "Manual"; } 827 else if (src === "custom") { aiLabel = "Edited"; } 828 else { aiLabel = "Classified"; } 829 badge = '<span class="cf-admin-badge-ai">✓ ' + aiLabel + '</span>'; 830 } 831 // Lock toggle button 832 lockIcon = lock === "locked" ? "🔒" : "🔓"; 833 lockTip = lock === "locked" 834 ? "This cookie is locked. Auto-Identify All will skip it. Click to unlock." 835 : "Click to lock this cookie. Locking prevents Auto-Identify All from changing your classification."; 836 badge += ' <button type="button" class="cf-admin-lock-toggle" data-name="' + esc(name) + '" title="' + esc(lockTip) + '" style="opacity:' + (lock === "locked" ? '1' : '0.4') + ';">' + lockIcon + '</button>'; 837 // Re-identify vs Auto-Identify label 838 reIdLabel = (src === "ai" || lock === "edited") ? "Re-identify" : "Auto-Identify"; 839 if (cookieflameAdmin.isPremium) { 840 var greyStyle = lock === "locked" ? ' style="color:#999;cursor:default;"' : ''; 841 badge += '<br><a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(name) + '"' + greyStyle + '>' + reIdLabel + '</a>'; 842 } 843 return badge; 844 } 845 846 if (rd.source === "custom") { 847 sourceHtml = _lockBadgeHtml("custom", rd.lock, rd.name); 848 sourceHtml += '<br><a href="#" class="cf-admin-revert-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Revert to default</a>'; 849 sourceHtml += removeHtml; 850 } else if (rd.source === "ai") { 851 sourceHtml = _lockBadgeHtml("ai", rd.lock, rd.name); 852 sourceHtml += removeHtml; 853 } else if (rd.source === "manual") { 854 sourceHtml = _lockBadgeHtml("manual", rd.lock, rd.name); 855 sourceHtml += removeHtml; 856 } else if (rd.source === "discovered") { 857 sourceHtml = _lockBadgeHtml("discovered", rd.lock, rd.name); 858 sourceHtml += removeHtml; 859 } else if (rd.source === "builtin") { 860 sourceHtml = '<span class="cf-admin-badge-known">✓ Known</span>'; 861 sourceHtml += '<br><a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Auto-Identify</a>' + proRowPill; 862 sourceHtml += removeHtml; 863 } else if (rd.isBeacon) { 864 sourceHtml = '<span class="cf-admin-badge-unclassified">⚠ Reported</span>'; 865 sourceHtml += '<br><a href="#" class="cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Auto-Identify</a>' + proRowPill; 866 sourceHtml += removeHtml; 867 } else { 868 sourceHtml = '<span class="cf-admin-badge-unclassified">⚠ Unclassified</span>'; 869 sourceHtml += '<br><a href="#" class="cf-admin-ai-row-btn cf-admin-source-link" data-name="' + esc(rd.name) + '">Auto-Identify</a>' + proRowPill; 870 sourceHtml += removeHtml; 871 } 872 873 // "Not active" label in Source column 874 if (!rd.inBrowser) { 875 var notActiveLabel = rd.isBeacon ? "Reported by visitors" : "Detected, not active"; 876 var notActiveTip = rd.isBeacon 877 ? "This cookie was found by visitors browsing your site. It is not set in your admin browser because marketing and analytics scripts do not run in the admin area. Classify it so CookieFlame manages it correctly when visitors encounter it." 878 : "This cookie was found during a discovery scan on your site but is not set in your browser right now. This is normal. You are viewing the Cookie Manager in the admin area where marketing and analytics scripts do not run. The cookie will be set for visitors on the frontend when they interact with the service or consent to its category. You should still classify it so CookieFlame manages it correctly when visitors encounter it."; 879 sourceHtml += '<br><span class="cf-admin-not-active-label">' + notActiveLabel + 880 ' <button type="button" class="cf-admin-help-btn cf-admin-help-btn-sm" ' + 881 'data-help-title="' + esc(notActiveLabel) + '" data-help="' + esc(notActiveTip) + '">?</button></span>'; 882 } 883 884 // Residual cookie badge (deactivated/removed plugin) 844 // Status column: one label, then the actions (5.3.0). 885 845 var residual = residualMap[rd.name]; 886 if (residual) { 887 sourceHtml += '<br><span class="cf-admin-badge-residual" data-residual-name="' + esc(rd.name) + '">🕑 Residual</span>' + 888 '<span class="cf-admin-residual-from">from ' + esc(residual.plugin) + '</span>'; 889 } 846 var sourceHtml = statusCellHtml(rd, beaconData[rd.name], residual, proRowPill); 890 847 891 848 // Recommended label below category dropdown … … 978 935 } 979 936 980 // Bind remove buttons for manually added cookies 981 // Bind per-row delete buttons (inline confirmation, no confirm() dialog) 982 var delBtns = tbody.querySelectorAll(".cf-admin-delete-cookie"); 983 for (var rb = 0; rb < delBtns.length; rb++) { 984 delBtns[rb].addEventListener("click", function (e) { 985 e.preventDefault(); 986 var link = this; 987 var n = link.getAttribute("data-name"); 988 var tr = link.closest("tr"); 989 990 // If already showing confirmation, ignore 991 if (link.getAttribute("data-confirming")) return; 992 link.setAttribute("data-confirming", "1"); 993 994 // Replace link text with inline confirmation 995 var origHtml = link.innerHTML; 996 link.style.display = "none"; 997 var confirmSpan = document.createElement("span"); 998 confirmSpan.className = "cf-admin-meta-hint"; 999 confirmSpan.innerHTML = 'Remove <strong>' + esc(n) + '</strong>? ' + 1000 '<a href="#" class="cf-admin-confirm-yes cf-admin-link-danger">Yes, remove</a>' + 1001 ' / <a href="#" class="cf-admin-confirm-no cf-admin-link-cancel">Cancel</a>'; 1002 link.parentNode.insertBefore(confirmSpan, link.nextSibling); 1003 1004 confirmSpan.querySelector(".cf-admin-confirm-yes").addEventListener("click", function (ev) { 1005 ev.preventDefault(); 1006 var source = tr ? (tr.getAttribute("data-source") || "") : ""; 1007 // Track as dismissed for builtin cookies (hides from table) 1008 if (source === "builtin" && dismissedCookies.indexOf(n) === -1) { 1009 dismissedCookies.push(n); 1010 } 1011 // Use DELETE endpoint 1012 var delOpts = source === "builtin" ? { dismissed: true } : {}; 1013 queueDelete(n, delOpts, function () { 1014 // Remove residual explanation bar if present 1015 var resBar = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]'); 1016 if (resBar) resBar.remove(); 1017 if (tr) tr.remove(); 1018 cookieflameNotice("\"" + n + "\" removed.", "success"); 1019 }); 1020 }); 1021 1022 confirmSpan.querySelector(".cf-admin-confirm-no").addEventListener("click", function (ev) { 1023 ev.preventDefault(); 1024 confirmSpan.remove(); 1025 link.style.display = ""; 1026 link.removeAttribute("data-confirming"); 1027 }); 1028 }); 937 // Bind each row's Remove… link and Lock as correct button 938 var statusCells = tbody.querySelectorAll("td.cf-admin-source-cell"); 939 for (var cellIdx = 0; cellIdx < statusCells.length; cellIdx++) { 940 bindStatusCell(statusCells[cellIdx], statusCells[cellIdx].closest("tr")); 1029 941 } 1030 942 … … 1035 947 e.preventDefault(); 1036 948 identifySingleWithAi(this); 1037 });1038 }1039 1040 // Bind per-row "Ignore permanently" buttons1041 var ignoreBtns = tbody.querySelectorAll(".cf-admin-ignore-cookie");1042 for (var ig = 0; ig < ignoreBtns.length; ig++) {1043 ignoreBtns[ig].addEventListener("click", function (e) {1044 e.preventDefault();1045 var link = this;1046 var n = link.getAttribute("data-name");1047 var tr = link.closest("tr");1048 1049 if (link.getAttribute("data-confirming")) return;1050 link.setAttribute("data-confirming", "1");1051 1052 // Check beacon context for confidence-aware message.1053 var bc = getBeaconContext(n);1054 var isLikelyExtension = bc && bc.pre_existing;1055 var confirmMsg;1056 if (isLikelyExtension) {1057 confirmMsg = 'This appears to be a browser extension cookie. ' +1058 'It will be permanently hidden from notifications and your cookie declaration.';1059 } else {1060 confirmMsg = 'This cookie and the script that sets it will continue to fire without visitor consent. ' +1061 'It will not appear in your cookie declaration or notifications.';1062 }1063 1064 link.style.display = "none";1065 var confirmSpan = document.createElement("span");1066 confirmSpan.className = "cf-admin-meta-hint";1067 confirmSpan.innerHTML = '<span class="cf-admin-link-warning">' + esc(confirmMsg) + '</span><br>' +1068 '<a href="#" class="cf-admin-ignore-yes cf-admin-link-danger">Yes, ignore permanently</a>' +1069 ' / <a href="#" class="cf-admin-ignore-no cf-admin-link-cancel">Cancel</a>';1070 link.parentNode.insertBefore(confirmSpan, link.nextSibling);1071 1072 confirmSpan.querySelector(".cf-admin-ignore-yes").addEventListener("click", function (ev) {1073 ev.preventDefault();1074 1075 // AJAX call to add to ignored list.1076 fetch(cookieflameAdmin.ignoredCookiesUrl, {1077 method: "POST",1078 headers: { "Content-Type": "application/json", "X-WP-Nonce": cookieflameAdmin.nonce },1079 credentials: "same-origin",1080 body: JSON.stringify({ action: "ignore", name: n })1081 })1082 .then(function (r) { return r.json(); })1083 .then(function (data) {1084 if (data.success) {1085 // Update local state.1086 cookieflameAdmin.ignoredCookies = data.ignored || [];1087 // Remove from in-memory data.1088 savedCustom = savedCustom.filter(function (c) { return c.name !== n; });1089 if (deletedCookies.indexOf(n) === -1) deletedCookies.push(n);1090 if (dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n);1091 // Remove row.1092 var resBarIg = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]');1093 if (resBarIg) resBarIg.remove();1094 if (tr) tr.remove();1095 // Refresh ignored section.1096 renderIgnoredSection();1097 cookieflameNotice("\"" + n + "\" permanently ignored.", "success");1098 }1099 })1100 .catch(function () {1101 cookieflameNotice("Could not ignore cookie. Please try again.", "error");1102 confirmSpan.remove();1103 link.style.display = "";1104 link.removeAttribute("data-confirming");1105 });1106 });1107 1108 confirmSpan.querySelector(".cf-admin-ignore-no").addEventListener("click", function (ev) {1109 ev.preventDefault();1110 confirmSpan.remove();1111 link.style.display = "";1112 link.removeAttribute("data-confirming");1113 });1114 });1115 }1116 1117 // Bind lock toggle buttons (padlock icon on classified cookies)1118 var lockBtns = tbody.querySelectorAll(".cf-admin-lock-toggle");1119 for (var lb = 0; lb < lockBtns.length; lb++) {1120 lockBtns[lb].addEventListener("click", function (e) {1121 e.preventDefault();1122 var cookieName = this.getAttribute("data-name");1123 var tr = this.closest("tr");1124 if (!tr) return;1125 var curLock = tr.getAttribute("data-lock") || "";1126 var newLock = curLock === "locked" ? "" : "locked";1127 tr.setAttribute("data-lock", newLock);1128 1129 // Update button icon, tooltip and opacity1130 this.innerHTML = newLock === "locked" ? "🔒" : "🔓";1131 this.title = newLock === "locked"1132 ? "This cookie is locked. Auto-Identify All will skip it. Click to unlock."1133 : "Click to lock this cookie. Locking prevents Auto-Identify All from changing your classification.";1134 this.style.opacity = newLock === "locked" ? "1" : "0.4";1135 1136 // Update badge1137 var sourceCell = tr.querySelector(".cf-admin-source-cell");1138 if (sourceCell) {1139 var badge = sourceCell.querySelector("[class^='cf-admin-badge']");1140 if (badge) {1141 if (newLock === "locked") {1142 badge.className = "cf-admin-badge-locked";1143 badge.innerHTML = "🔒 Locked";1144 } else {1145 var src = tr.getAttribute("data-source") || "";1146 var label = src === "ai" ? "Auto-Identified" : src === "discovered" ? "Classified" : src === "manual" ? "Manual" : "Edited";1147 badge.className = "cf-admin-badge-ai";1148 badge.innerHTML = "✓ " + label;1149 }1150 }1151 // Update Re-identify link grey state1152 var reIdLink = sourceCell.querySelector(".cf-admin-identify-link");1153 if (reIdLink) {1154 reIdLink.style.color = newLock === "locked" ? "#999" : "";1155 reIdLink.style.cursor = newLock === "locked" ? "default" : "";1156 }1157 }1158 1159 queueSave(cookieName, { lock: newLock });1160 949 }); 1161 950 } … … 1169 958 pluginCount + " CookieFlame, " + 1170 959 thirdPartyCount + " third-party, " + 1171 unknownCount + " unclassified).";960 unknownCount + " not identified yet)."; 1172 961 } 1173 962 … … 1184 973 // Render the permanently ignored cookies section. 1185 974 renderIgnoredSection(); 975 } 976 977 /* ═══════════════════════════════════════════ 978 STATUS COLUMN (5.3.0) 979 One label for where the cookie stands, then its actions: Lock as 980 correct (Pro), Auto-Identify or Re-identify, Revert to default, 981 and one Remove… link that asks why before it removes or ignores 982 the cookie. The explanations live in each link's hover text and 983 the Status column's help. 984 ═══════════════════════════════════════════ */ 985 986 var LOCK_TIP_OFF = "Press this once you've checked the vendor, category and purpose are right. CookieFlame won't change them after that, even when you re-identify."; 987 var LOCK_TIP_ON = "You've checked this cookie. CookieFlame won't change its vendor, category or purpose, even when you re-identify. Click to unlock."; 988 989 function statusLabelHtml(source, lock) { 990 if (source === "unknown") return '<span class="cf-admin-badge-unclassified">Not identified yet</span>'; 991 if (source === "builtin") return '<span class="cf-admin-badge-known">Known</span>'; 992 if (source === "manual") return '<span class="cf-admin-badge-edited">Added by you</span>'; 993 if (source === "custom" || lock === "edited") return '<span class="cf-admin-badge-edited">Changed by you</span>'; 994 if (source === "discovered") return '<span class="cf-admin-badge-known">Classified</span>'; 995 return '<span class="cf-admin-badge-ai">Auto-Identified</span>'; 996 } 997 998 function lockButtonInner(locked) { 999 return '<span class="dashicons dashicons-' + (locked ? "lock" : "unlock") + '" aria-hidden="true"></span>' + 1000 (locked ? "Locked by you" : "Lock as correct"); 1001 } 1002 1003 // Where a cookie nobody has identified yet came from. Pro 1.5.1+ marks 1004 // the cookies its clean scan added with found_by "clean_scan". 1005 function whereFoundText(rd, beacon) { 1006 if (beacon && beacon.found_by === "clean_scan") return "Found by your scan"; 1007 if (beacon) return "Reported by visitors"; 1008 if (rd.inBrowser) return "Seen in your browser"; 1009 return ""; 1010 } 1011 1012 function statusCellHtml(rd, beacon, residual, proPill) { 1013 var name = esc(rd.name); 1014 var classified = ["ai", "manual", "discovered", "custom"].indexOf(rd.source) !== -1; 1015 var line = function (html, cls, hidden) { 1016 return '<div class="cf-admin-status-line' + (cls ? " " + cls : "") + '"' + (hidden ? ' style="display:none;"' : "") + '>' + html + '</div>'; 1017 }; 1018 1019 var html = line(statusLabelHtml(rd.source, rd.lock)); 1020 var where = rd.source === "unknown" ? whereFoundText(rd, beacon) : ""; 1021 if (where) html += line(esc(where), "cf-admin-status-where"); 1022 1023 // Locking only matters to Pro, which is what re-identifies cookies. 1024 if (classified && cookieflameAdmin.isPremium) { 1025 var locked = rd.lock === "locked"; 1026 html += line('<button type="button" class="button button-small cf-admin-lock-toggle' + (locked ? " is-locked" : "") + '" data-name="' + name + '"' + 1027 ' aria-pressed="' + (locked ? "true" : "false") + '" title="' + esc(locked ? LOCK_TIP_ON : LOCK_TIP_OFF) + '">' + lockButtonInner(locked) + '</button>'); 1028 } 1029 1030 if (rd.source === "unknown") { 1031 html += line('<a href="#" class="cf-admin-ai-row-btn cf-admin-source-link cf-admin-source-link-main" data-name="' + name + '" title="Ask CookieFlame\'s service what this cookie is and fill in its details.">Auto-Identify</a>' + proPill); 1032 } else if (rd.source === "builtin") { 1033 html += line('<a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + name + '" title="Ask CookieFlame\'s service what this cookie is.">Auto-Identify</a>' + proPill); 1034 } else if (cookieflameAdmin.isPremium) { 1035 var reLabel = (rd.source === "ai" || rd.lock === "edited") ? "Re-identify" : "Auto-Identify"; 1036 html += line('<a href="#" class="cf-admin-identify-link cf-admin-ai-row-btn cf-admin-source-link" data-name="' + name + '" title="Ask CookieFlame\'s service about this cookie again. Your own changes are only ever suggested, never replaced.">' + reLabel + '</a>', 1037 "cf-admin-status-reidentify", rd.lock === "locked"); 1038 } 1039 1040 if (rd.source === "custom") { 1041 html += line('<a href="#" class="cf-admin-revert-btn cf-admin-source-link" data-name="' + name + '" title="Go back to the vendor, category and purpose from CookieFlame\'s built-in list.">Revert to default</a>'); 1042 } 1043 html += line('<a href="#" class="cf-admin-remove-ask cf-admin-source-link" data-name="' + name + '" title="Asks whether your site no longer uses it, or it isn\'t from your site.">Remove…</a>'); 1044 1045 if (residual) { 1046 html += line('<span class="cf-admin-badge-residual" data-residual-name="' + name + '">🕑 Residual</span>' + 1047 '<span class="cf-admin-residual-from">from ' + esc(residual.plugin) + '</span>'); 1048 } 1049 return html; 1050 } 1051 1052 function setLockState(tr, lock) { 1053 var locked = lock === "locked"; 1054 tr.setAttribute("data-lock", lock); 1055 var btn = tr.querySelector(".cf-admin-lock-toggle"); 1056 if (btn) { 1057 btn.classList.toggle("is-locked", locked); 1058 btn.setAttribute("aria-pressed", locked ? "true" : "false"); 1059 btn.title = locked ? LOCK_TIP_ON : LOCK_TIP_OFF; 1060 btn.innerHTML = lockButtonInner(locked); 1061 } 1062 // A locked cookie isn't re-identified, so the link goes while it's locked. 1063 var reId = tr.querySelector(".cf-admin-status-reidentify"); 1064 if (reId) reId.style.display = locked ? "none" : ""; 1065 } 1066 1067 function bindStatusCell(cell, tr) { 1068 if (!cell || !tr) return; 1069 var removeLink = cell.querySelector(".cf-admin-remove-ask"); 1070 if (removeLink) { 1071 removeLink.addEventListener("click", function (e) { 1072 e.preventDefault(); 1073 openRemoveBar(tr); 1074 }); 1075 } 1076 var lockBtn = cell.querySelector(".cf-admin-lock-toggle"); 1077 if (lockBtn) { 1078 lockBtn.addEventListener("click", function (e) { 1079 e.preventDefault(); 1080 var newLock = (tr.getAttribute("data-lock") || "") === "locked" ? "" : "locked"; 1081 setLockState(tr, newLock); 1082 queueSave(tr.getAttribute("data-cookie-name"), { lock: newLock }); 1083 }); 1084 } 1085 } 1086 1087 /** 1088 * Remove… asks why, in a bar under the row. "My site doesn't use it any 1089 * more" removes the cookie, so it comes back if it's seen again. "It's 1090 * not from my site" puts it on the Permanently Ignored list. 1091 */ 1092 function openRemoveBar(tr) { 1093 var n = tr.getAttribute("data-cookie-name"); 1094 var tbody = tr.parentNode; 1095 if (!n || !tbody) return; 1096 var key = CSS.escape(n); 1097 var open = tbody.querySelector('.cf-admin-remove-bar[data-remove-for="' + key + '"]'); 1098 if (open) { open.remove(); return; } 1099 1100 var bc = getBeaconContext(n); 1101 var extHint = (bc && bc.pre_existing) 1102 ? '<em class="cf-admin-remove-hint">This one was already in a visitor\'s browser before your page loaded, which usually means an extension.</em>' 1103 : ""; 1104 1105 var bar = document.createElement("tr"); 1106 bar.className = "cf-admin-remove-bar"; 1107 bar.setAttribute("data-remove-for", n); 1108 bar.innerHTML = '<td colspan="7" class="cf-admin-inline-bar-remove">' + 1109 '<strong>Why are you removing <code>' + esc(n) + '</code>?</strong>' + 1110 '<div class="cf-admin-remove-choices">' + 1111 '<button type="button" class="button cf-admin-remove-unused"><strong>My site doesn\'t use it any more</strong>' + 1112 '<span>Taken off your list. If your site sets it again, it comes back to be identified.</span></button>' + 1113 '<button type="button" class="button cf-admin-remove-notmine"><strong>It\'s not from my site</strong>' + 1114 '<span>From a visitor\'s browser extension or another website. Hidden for good, and CookieFlame stops managing it. You can bring it back from Permanently Ignored at the bottom of this page.</span>' + 1115 extHint + '</button>' + 1116 '<a href="#" class="cf-admin-remove-cancel cf-admin-link-cancel">Cancel</a>' + 1117 '</div></td>'; 1118 tbody.insertBefore(bar, tr.nextSibling); 1119 1120 var buttons = bar.querySelectorAll("button"); 1121 var busy = function (on) { 1122 for (var i = 0; i < buttons.length; i++) buttons[i].disabled = on; 1123 }; 1124 var gone = function (msg) { 1125 var extras = tbody.querySelectorAll('[data-remove-for="' + key + '"], [data-residual-for="' + key + '"], [data-suggestion-for="' + key + '"]'); 1126 for (var i = 0; i < extras.length; i++) extras[i].remove(); 1127 tr.remove(); 1128 cookieflameNotice(msg, "success"); 1129 }; 1130 1131 bar.querySelector(".cf-admin-remove-unused").addEventListener("click", function () { 1132 busy(true); 1133 var source = tr.getAttribute("data-source") || ""; 1134 // A Known cookie still in your browser would show again at once, so it's hidden until seen again. 1135 if (source === "builtin" && dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1136 queueDelete(n, source === "builtin" ? { dismissed: true } : {}, function () { 1137 gone("\"" + esc(n) + "\" removed."); 1138 }, function () { busy(false); }); 1139 }); 1140 1141 bar.querySelector(".cf-admin-remove-notmine").addEventListener("click", function () { 1142 busy(true); 1143 fetch(cookieflameAdmin.ignoredCookiesUrl, { 1144 method: "POST", 1145 headers: { "Content-Type": "application/json", "X-WP-Nonce": cookieflameAdmin.nonce }, 1146 credentials: "same-origin", 1147 body: JSON.stringify({ action: "ignore", name: n }) 1148 }) 1149 .then(function (r) { return r.json(); }) 1150 .then(function (data) { 1151 if (!data || !data.success) throw new Error("not ignored"); 1152 cookieflameAdmin.ignoredCookies = data.ignored || []; 1153 savedCustom = savedCustom.filter(function (c) { return c.name !== n; }); 1154 if (deletedCookies.indexOf(n) === -1) deletedCookies.push(n); 1155 if (dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1156 gone("\"" + esc(n) + "\" moved to Permanently Ignored."); 1157 renderIgnoredSection(); 1158 }) 1159 .catch(function () { 1160 busy(false); 1161 cookieflameNotice("Could not ignore cookie. Please try again.", "error"); 1162 }); 1163 }); 1164 1165 bar.querySelector(".cf-admin-remove-cancel").addEventListener("click", function (e) { 1166 e.preventDefault(); 1167 bar.remove(); 1168 }); 1186 1169 } 1187 1170 … … 1583 1566 } 1584 1567 1568 // It's identified now, so where it came from no longer matters. 1569 var where = sourceCell.querySelector(".cf-admin-status-where"); 1570 if (where) where.remove(); 1571 1585 1572 // Update AI link to "Re-identify" and remove lock toggle if present. 1586 1573 var aiLink = sourceCell.querySelector(".cf-admin-identify-link, .cf-admin-ai-row-btn"); … … 1615 1602 if (aiBtn) aiBtn.addEventListener("click", function (e) { e.preventDefault(); identifySingleWithAi(this); }); 1616 1603 1617 // Delete (Remove) link — inline confirmation flow 1618 var delBtn = cell.querySelector(".cf-admin-delete-cookie"); 1619 if (delBtn) { 1620 delBtn.addEventListener("click", function (e) { 1621 e.preventDefault(); 1622 var link = this; 1623 var n = link.getAttribute("data-name"); 1624 if (link.getAttribute("data-confirming")) return; 1625 link.setAttribute("data-confirming", "1"); 1626 link.style.display = "none"; 1627 var confirmSpan = document.createElement("span"); 1628 confirmSpan.className = "cf-admin-meta-hint"; 1629 confirmSpan.innerHTML = 'Remove <strong>' + esc(n) + '</strong>? ' + 1630 '<a href="#" class="cf-admin-confirm-yes cf-admin-link-danger">Yes, remove</a>' + 1631 ' / <a href="#" class="cf-admin-confirm-no cf-admin-link-cancel">Cancel</a>'; 1632 link.parentNode.insertBefore(confirmSpan, link.nextSibling); 1633 confirmSpan.querySelector(".cf-admin-confirm-yes").addEventListener("click", function (ev) { 1634 ev.preventDefault(); 1635 var source = tr ? (tr.getAttribute("data-source") || "") : ""; 1636 if (source === "builtin" && dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1637 var delOpts = source === "builtin" ? { dismissed: true } : {}; 1638 queueDelete(n, delOpts, function () { 1639 var tbody = tr ? tr.parentNode : null; 1640 if (tbody) { 1641 var resBar = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]'); 1642 if (resBar) resBar.remove(); 1643 } 1644 if (tr) tr.remove(); 1645 cookieflameNotice("\"" + n + "\" removed.", "success"); 1646 }); 1647 }); 1648 confirmSpan.querySelector(".cf-admin-confirm-no").addEventListener("click", function (ev) { 1649 ev.preventDefault(); 1650 confirmSpan.remove(); 1651 link.style.display = ""; 1652 link.removeAttribute("data-confirming"); 1653 }); 1654 }); 1655 } 1656 1657 // Ignore link — inline confirmation flow 1658 var ignoreBtn = cell.querySelector(".cf-admin-ignore-cookie"); 1659 if (ignoreBtn) { 1660 ignoreBtn.addEventListener("click", function (e) { 1661 e.preventDefault(); 1662 var link = this; 1663 var n = link.getAttribute("data-name"); 1664 if (link.getAttribute("data-confirming")) return; 1665 link.setAttribute("data-confirming", "1"); 1666 link.style.display = "none"; 1667 var confirmSpan = document.createElement("span"); 1668 confirmSpan.className = "cf-admin-meta-hint"; 1669 confirmSpan.innerHTML = 'Permanently ignore <strong>' + esc(n) + '</strong>? ' + 1670 '<a href="#" class="cf-admin-ignore-yes cf-admin-link-warning">Yes, ignore permanently</a>' + 1671 ' / <a href="#" class="cf-admin-ignore-no cf-admin-link-cancel">Cancel</a>'; 1672 link.parentNode.insertBefore(confirmSpan, link.nextSibling); 1673 confirmSpan.querySelector(".cf-admin-ignore-yes").addEventListener("click", function (ev) { 1674 ev.preventDefault(); 1675 fetch(cookieflameAdmin.ignoredCookiesUrl, { 1676 method: "POST", 1677 headers: { "Content-Type": "application/json", "X-WP-Nonce": cookieflameAdmin.nonce }, 1678 credentials: "same-origin", 1679 body: JSON.stringify({ action: "ignore", name: n }) 1680 }) 1681 .then(function (r) { return r.json(); }) 1682 .then(function (data) { 1683 if (data.success) { 1684 cookieflameAdmin.ignoredCookies = data.ignored || []; 1685 savedCustom = savedCustom.filter(function (c) { return c.name !== n; }); 1686 if (deletedCookies.indexOf(n) === -1) deletedCookies.push(n); 1687 if (dismissedCookies.indexOf(n) === -1) dismissedCookies.push(n); 1688 var tbody = tr ? tr.parentNode : null; 1689 if (tbody) { 1690 var resBar = tbody.querySelector('.cf-admin-residual-bar[data-residual-for="' + n + '"]'); 1691 if (resBar) resBar.remove(); 1692 } 1693 if (tr) tr.remove(); 1694 renderIgnoredSection(); 1695 cookieflameNotice("\"" + n + "\" permanently ignored.", "success"); 1696 } 1697 }) 1698 .catch(function () { 1699 cookieflameNotice("Could not ignore cookie. Please try again.", "error"); 1700 confirmSpan.remove(); 1701 link.style.display = ""; 1702 link.removeAttribute("data-confirming"); 1703 }); 1704 }); 1705 confirmSpan.querySelector(".cf-admin-ignore-no").addEventListener("click", function (ev) { 1706 ev.preventDefault(); 1707 confirmSpan.remove(); 1708 link.style.display = ""; 1709 link.removeAttribute("data-confirming"); 1710 }); 1711 }); 1712 } 1713 1714 // Lock toggle 1715 var lockBtn = cell.querySelector(".cf-admin-lock-toggle"); 1716 if (lockBtn) { 1717 lockBtn.addEventListener("click", function (e) { 1718 e.preventDefault(); 1719 var n = this.getAttribute("data-name"); 1720 var currentLock = tr.getAttribute("data-lock") || ""; 1721 var newLock = currentLock === "locked" ? "" : "locked"; 1722 tr.setAttribute("data-lock", newLock); 1723 this.innerHTML = newLock === "locked" ? "🔒" : "🔓"; 1724 this.title = newLock === "locked" 1725 ? "This cookie is locked. Auto-Identify All will skip it. Click to unlock." 1726 : "Click to lock this cookie. Locking prevents Auto-Identify All from changing your classification."; 1727 this.style.opacity = newLock === "locked" ? "1" : "0.4"; 1728 var badge = cell.querySelector("[class^='cf-admin-badge']"); 1729 if (badge) { 1730 if (newLock === "locked") { 1731 badge.className = "cf-admin-badge-locked"; 1732 badge.innerHTML = "🔒 Locked"; 1733 } else { 1734 var src = tr.getAttribute("data-source") || ""; 1735 var label = src === "ai" ? "Auto-Identified" : src === "discovered" ? "Classified" : src === "manual" ? "Manual" : "Edited"; 1736 badge.className = "cf-admin-badge-ai"; 1737 badge.innerHTML = "✓ " + label; 1738 } 1739 } 1740 var reIdLink = cell.querySelector(".cf-admin-identify-link"); 1741 if (reIdLink) { 1742 reIdLink.style.color = newLock === "locked" ? "#999" : ""; 1743 reIdLink.style.cursor = newLock === "locked" ? "default" : ""; 1744 } 1745 queueSave(n, { lock: newLock }); 1746 }); 1747 } 1604 // Remove… link and Lock as correct button 1605 bindStatusCell(cell, tr); 1748 1606 1749 1607 // Residual badge toggle … … 2048 1906 if (badge) { 2049 1907 badge.className = "cf-admin-badge-ai"; 2050 badge. innerHTML = "✓Auto-Identified";1908 badge.textContent = "Auto-Identified"; 2051 1909 } 2052 1910 // Remove any confirmed tick left over. … … 2088 1946 lockPrompt.setAttribute("data-suggestion-for", n); 2089 1947 lockPrompt.innerHTML = '<td colspan="7" class="cf-admin-inline-bar-lock">' + 2090 'Lock this cookie to prevent future suggestions? ' +1948 'Lock it as correct, so CookieFlame stops suggesting changes? ' + 2091 1949 '<a href="#" class="cf-admin-lock-yes cf-admin-link-cancel" style="margin-left:4px;font-weight:600;">Yes</a>' + 2092 1950 ' / <a href="#" class="cf-admin-lock-no cf-admin-meta-hint" style="margin-left:4px;">No</a>' + … … 2099 1957 lockPrompt.querySelector(".cf-admin-lock-yes").addEventListener("click", function (ev) { 2100 1958 ev.preventDefault(); 2101 cookieRow.setAttribute("data-lock", "locked");1959 setLockState(cookieRow, "locked"); 2102 1960 queueSave(n, { lock: "locked" }); 2103 // Update padlock visuals.2104 var lockBtn = cookieRow.querySelector(".cf-admin-lock-toggle");2105 if (lockBtn) { lockBtn.innerHTML = "🔒"; lockBtn.style.opacity = "1"; }2106 var badge = cookieRow.querySelector("[class^='cf-admin-badge']");2107 if (badge) { badge.className = "cf-admin-badge-locked"; badge.innerHTML = "🔒 Locked"; }2108 var reIdLink = cookieRow.querySelector(".cf-admin-identify-link");2109 if (reIdLink) { reIdLink.style.color = "#999"; reIdLink.style.cursor = "default"; }2110 1961 lockPrompt.remove(); 2111 1962 }); … … 2212 2063 if (badge) { 2213 2064 badge.className = "cf-admin-badge-ai"; 2214 badge. innerHTML = "✓Auto-Identified";2065 badge.textContent = "Auto-Identified"; 2215 2066 } 2216 2067 } … … 2299 2150 2300 2151 if (expanded) { 2301 h += '<p class="cf-admin-ignored-desc">These cookies have been permanently excluded from passive monitoring. They will never trigger notifications or appear in your cookie declaration. C lick Restore to start monitoring a cookie again.</p>';2302 h += '<table class="widefat striped cf-admin-ignored-table"><thead><tr><th>Cookie</th><th> Ignored</th><th></th></tr></thead><tbody>';2152 h += '<p class="cf-admin-ignored-desc">These cookies have been permanently excluded from passive monitoring. They will never trigger notifications or appear in your cookie declaration. Cookies with a reason were ignored automatically because they came with a visitor\'s browser, such as another consent tool\'s cookie written by a browser extension. Click Restore to start monitoring a cookie again.</p>'; 2153 h += '<table class="widefat striped cf-admin-ignored-table"><thead><tr><th>Cookie</th><th>Why</th><th>Ignored</th><th></th></tr></thead><tbody>'; 2303 2154 for (var i = 0; i < ignored.length; i++) { 2304 2155 var ig = ignored[i]; … … 2306 2157 h += '<tr data-ignored-name="' + esc(ig.name) + '">'; 2307 2158 h += '<td><code>' + esc(ig.name) + '</code></td>'; 2159 h += '<td>' + esc(ig.reason || "Ignored by you") + '</td>'; 2308 2160 h += '<td>' + esc(when) + '</td>'; 2309 2161 h += '<td><button type="button" class="button button-small cf-admin-restore-ignored" data-name="' + esc(ig.name) + '">Restore</button></td>'; … … 2344 2196 .then(function (data) { 2345 2197 if (data.success) { 2198 // The server remembers restored automatic entries; mirror that so 2199 // the Cookie Manager shows the cookie again without a reload. 2200 var rules = cookieflameAdmin.visitorCookieRules; 2201 var wasAuto = (cookieflameAdmin.ignoredCookies || []).some(function (ig) { return ig.name === n && ig.auto; }); 2202 if (wasAuto && rules && rules.allow && rules.allow.indexOf(n) === -1) rules.allow.push(n); 2346 2203 cookieflameAdmin.ignoredCookies = data.ignored || []; 2347 2204 renderIgnoredSection(); … … 2712 2569 tr.setAttribute("data-source", "discovered"); 2713 2570 tr.className = ""; 2714 // Update source cell badge + lock icon after save completes2571 // Update the status label; it no longer needs identifying 2715 2572 var srcCell = tr.querySelector(".cf-admin-source-cell"); 2716 2573 if (srcCell) { … … 2718 2575 if (badge) { 2719 2576 badge.className = "cf-admin-badge-known"; 2720 badge. innerHTML = "✓Classified";2577 badge.textContent = "Classified"; 2721 2578 } 2579 var where = srcCell.querySelector(".cf-admin-status-where"); 2580 if (where) where.remove(); 2722 2581 } 2723 2582 } -
cookieflame/trunk/assets/js/cookieconsent-discovery.js
r3766806 r3769546 1 1 /** 2 * CookieFlame Discovery Bundle v5. 1.12 * CookieFlame Discovery Bundle v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Admin-only script detection and discovery bar. Loaded … … 287 287 var seen = {}; 288 288 var hasBeforeSnapshot = Object.keys(beforeCookieSet).length > 0; 289 // The Cookie Manager doesn't list cookies that came with the browser 290 // (another consent tool's cookie, or one a browser extension wrote) or 291 // ignored ones, so they aren't counted here either. 292 var visitor = _cc.visitorCookies ? _cc.visitorCookies(current) : {}; 293 var ignoredNames = (window.cookieflameAdmin && window.cookieflameAdmin.ignoredCookieNames) || []; 289 294 for (var i = 0; i < current.length; i++) { 290 295 var name = current[i]; … … 292 297 seen[name] = true; 293 298 if (isSafeForCounter(name)) continue; 299 if (visitor[name] || ignoredNames.indexOf(name) !== -1) continue; 294 300 if (hasBeforeSnapshot && beforeCookieSet[name]) { 295 301 existing.push(name); -
cookieflame/trunk/assets/js/cookieconsent-discovery.min.js
r3766806 r3769546 1 1 /** 2 * CookieFlame Discovery Bundle v5. 1.12 * CookieFlame Discovery Bundle v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Admin-only script detection and discovery bar. Loaded … … 13 13 * the core bundle despite the declared WordPress dependency. 14 14 */ 15 !function(){"use strict";var e=window.__ccInternal;if(e){var t=e.scriptLoaded,o=e.scriptLoadedUrls,n=e.hasCookie,i={"Google Analytics":function(){return t("googletagmanager.com/gtag")||t("google-analytics.com")||t("analytics.google.com")||n("_ga")},"Google Ads":function(){return t("googleads.g.doubleclick.net")||t("googleadservices.com")||t("googlesyndication.com")||n("_gcl_au")||n("_gcl_aw")},"Google Tag Manager":function(){return t("googletagmanager.com/gtm.js")||!!window.google_tag_manager},"Microsoft Ads":function(){return t("bat.bing.com")||!!window.uetq||n("_uetsid")||n("_uetvid")},"Meta / Facebook":function(){return t("connect.facebook.net")||!!window.fbq||n("_fbp")||n("_fbc")},"Twitter / X":function(){return t("ads-twitter.com")||t("static.ads-twitter.com")||!!window.twq||n("_twpid")},LinkedIn:function(){return t("snap.licdn.com")||t("ads.linkedin.com")||!!window._linkedin_data_partner_ids||n("li_sugr")||n("bcookie")||n("lidc")},Pinterest:function(){return t("s.pinimg.com/ct")||t("pintrk")||!!window.pintrk||n("_pin_unauth")},Reddit:function(){return t("alb.reddit.com")||t("events.reddit.com")||!!window.rdt||n("_rdt_uuid")},TikTok:function(){return t("analytics.tiktok.com")||!!window.ttq}};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",a):setTimeout(a,100)}function a(){var t=window.__ccDiscovery;if(t&&t.active&&(!document.body||!document.body.classList.contains("wp-admin"))){var n=function(){try{var e=sessionStorage.getItem("cookieflame_discovery_services");return e?JSON.parse(e):{}}catch(e){return{}}}(),a={};try{var r=localStorage.getItem("cookieflame_discovery_before");if(r)for(var c=JSON.parse(r),s=0;s<c.length;s++)a[c[s]]=!0}catch(e){}var d=["wordpress_","wp-settings","wp_lang","PHPSESSID","cc_consent","cc_anon_id","cookieflame_","woocommerce_","wp_woocommerce_"],l=document.createElement("div");l.id="cf-admin-discovery-bar",l.style.cssText="position:fixed;top:0;left:0;right:0;z-index:999999;background:#1d2327;color:#f0f0f1;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;display:flex;align-items:center;justify-content:space-between;padding:10px 20px;box-shadow:0 2px 8px rgba(0,0,0,.3);gap:16px;flex-wrap:wrap;";var m=document.createElement("div");m.style.cssText="display:flex;align-items:center;gap:12px;flex:1;min-width:200px;";var g=document.createElement("span");g.style.cssText="width:10px;height:10px;border-radius:50%;background:#00ba37;display:inline-block;flex-shrink:0;animation:cf-admin-pulse 2s infinite;";var p=document.createElement("span");p.textContent="Cookie Discovery Active",p.style.fontWeight="600";var f=document.createElement("span");f.id="cf-admin-discovery-count",f.style.cssText="background:#2271b1;color:#fff;padding:2px 10px;border-radius:12px;font-size:13px;font-weight:600;cursor:help;",f.textContent="scanning...",m.appendChild(g),m.appendChild(p),m.appendChild(f);var u=document.createElement("span");u.style.cssText="color:#a7aaad;font-size:13px;display:inline-flex;flex-direction:column;gap:2px;";var h=document.createElement("span");h.textContent="All cookies are temporarily accepted. Browse your pages, then click Finish.";var v=document.createElement("span");v.textContent="Tip: Browse by clicking links on the site. Typed URLs may skip discovery.",v.style.cssText="font-size:11px;opacity:0.75;",u.appendChild(h),u.appendChild(v),C(),setTimeout(C,500),setTimeout(C,2e3);var y=document.createElement("button");y.textContent="Finish Discovery",y.style.cssText="background:#00ba37;color:#fff;border:none;padding:8px 20px;border-radius:4px;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;",y.onmouseover=function(){y.style.background="#009929"},y.onmouseout=function(){y.style.background="#00ba37"},l.appendChild(m),l.appendChild(u),l.appendChild(y);var k=document.createElement("style");k.textContent="@keyframes cf-admin-pulse{0%,100%{opacity:1}50%{opacity:.4}}#cf-admin-discovery-bar~*{margin-top:0!important;}body.admin-bar #cf-admin-discovery-bar{top:32px}@media screen and (max-width:782px){body.admin-bar #cf-admin-discovery-bar{top:46px}}",document.head.appendChild(k),document.body.insertBefore(l,document.body.firstChild),document.addEventListener("click",function(e){for(var t=e.target;t&&1===t.nodeType&&"A"!==t.tagName;)t=t.parentNode;if(t&&"A"===t.tagName){var o=t.getAttribute("target");if("_blank"!==o&&"_top"!==o&&"_parent"!==o){var n=t.getAttribute("rel")||"";if(!n||-1===n.split(/\s+/).indexOf("external")){var i=t.getAttribute("href");if(i){var a;try{a=new URL(i,location.href)}catch(e){return}"http:"!==a.protocol&&"https:"!==a.protocol||a.origin===location.origin&&(a.pathname===location.pathname&&a.search===location.search&&a.hash!==location.hash||a.searchParams.has("cookieflame")||(a.searchParams.set("cookieflame","discover"),t.setAttribute("href",a.toString())))}}}}},!0),setTimeout(x,5e3);var w=setInterval(x,3e3);y.addEventListener("click",function(){y.disabled=!0,y.textContent="Finishing...",y.style.opacity="0.7",clearInterval(w),x();var e=n,o=window.__ccConfig||{};try{localStorage.setItem("cookieflame_discovery_results",JSON.stringify(e))}catch(t){var i=encodeURIComponent(JSON.stringify(e)),a=o.cookieDomain?"; domain="+o.cookieDomain:"";document.cookie="cookieflame_discovery_results="+i+"; path=/; max-age=300"+a}fetch(t.finishUrl,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":t.nonce},body:"{}"}).then(function(e){if(403===e.status)throw new Error("Your session has expired. Please reload the page and try again.");return e.json()}).then(function(e){var i=[location.hostname,"."+location.hostname];o.cookieDomain&&i.push(o.cookieDomain);for(var a=0;a<i.length;a++)document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i[a];if(document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",e.restore_dnt){var r=o.cookieDomain?"; domain="+o.cookieDomain:"";document.cookie="cookieflame_dnt=1; path=/; max-age=31536000"+r}try{sessionStorage.removeItem("cookieflame_discovery_services")}catch(e){}for(var c=_(),s=0,d={},m=Object.keys(n),g=0;g<m.length;g++){var p=n[m[g]];if(p.unknown)s++,d[m[g]]=!0;else{var f=p.cookies||[];s+=f.length;for(var u=0;u<f.length;u++)d[f[u]]=!0}}for(var h=c.confirmed.concat(c.existing),v=0;v<h.length;v++)d[h[v]]||s++;l.style.background="#00ba37",l.innerHTML="";var y=document.createElement("span");y.style.cssText="font-weight:600;flex:1;text-align:center;";var k=s+" cookie"+(1!==s?"s":"")+" discovered. Redirecting to Cookie Manager...";y.textContent=k,l.appendChild(y),setTimeout(function(){window.location.href=t.adminUrl},1500)}).catch(function(e){y.disabled=!1,y.textContent="Finish Discovery",y.style.opacity="1",l.style.background="#d63638",u.style.color="#fff",u.textContent="Error: "+e.message})})}function x(){for(var t=function(){var t=[],n=e.getResourceSnapshot();e.setResourceSnapshot(n);for(var a=window.cookieflameAdmin&&window.cookieflameAdmin.serviceDetectors||[],r=[],c=0;c<a.length;c++)for(var s=a[c].scriptDomains||[],d=0;d<s.length;d++)r.push(s[d]);for(var l=0;l<a.length;l++){var m=a[l],g=m.name||"",p=i[g];if(p)try{if(p()){var f=o(g.toLowerCase().replace(/\s+/g,""));if(0===f.length&&-1!==g.indexOf(" "))for(var u=g.toLowerCase().split(" "),h=0;h<u.length&&0===f.length;h++)u[h].length>3&&(f=o(u[h]));t.push({name:g,cookies:m.cookies||[],canonicalDomain:m.canonicalDomain||"",scriptUrls:f})}}catch(e){}}t.pagePlugins=n.pluginScripts;for(var v=["wp.com","wordpress.com","wordpress.org","s.w.org","gravatar.com","cdnjs.cloudflare.com","cdn.jsdelivr.net","unpkg.com","ajax.googleapis.com","fonts.googleapis.com","fonts.gstatic.com","code.jquery.com","stackpath.bootstrapcdn.com","maxcdn.bootstrapcdn.com","www.google.com/recaptcha","www.gstatic.com","apis.google.com","maps.googleapis.com","maps.google.com","challenges.cloudflare.com","static.cloudflareinsights.com","chromium.org","mozilla.org","lazyload","rocket-loader","elementor.com"],y=n.thirdPartyDomains,k=0;k<y.length;k++){for(var w=y[k],x=!1,b=0;b<v.length;b++)if(w===v[b]||-1!==w.indexOf("."+v[b])||-1!==v[b].indexOf(w)){x=!0;break}if(!x){for(var _=!1,C=0;C<r.length;C++)if(-1!==w.indexOf(r[C])||-1!==r[C].indexOf(w)){_=!0;break}_||t.push({name:w,cookies:[],unknown:!0})}}return e.setResourceSnapshot(null),t}(),a=0;a<t.length;a++)n[t[a].name]||(n[t[a].name]=t[a]);if(t.pagePlugins&&t.pagePlugins.length){for(var r=n.__pagePlugins||{},c=0;c<t.pagePlugins.length;c++)r[t.pagePlugins[c].slug]=t.pagePlugins[c].url;n.__pagePlugins=r}!function(e){try{sessionStorage.setItem("cookieflame_discovery_services",JSON.stringify(e))}catch(e){}}(n),function(){var e=document.getElementById("cf-admin-discovery-count");if(e){for(var t=_(),o=(t.confirmed.length,t.existing.length,0),i={},a=Object.keys(n),r=[],c=[],s=0;s<a.length;s++){var d=n[a[s]];if(d.unknown)o++,c.push(a[s]),i[a[s]]=!0;else{r.push(a[s]);var l=d.cookies||[];o+=l.length;for(var m=0;m<l.length;m++)i[l[m]]=!0}}for(var g=t.confirmed.concat(t.existing),p=0;p<g.length;p++)i[g[p]]||o++;if(0===o)e.textContent="no cookies yet",e.title="Browse your site to discover cookies";else{e.textContent=o+" cookie"+(1!==o?"s":"")+" discovered";var f="";r.length>0&&(f+="Services: "+r.sort().join(", ")),c.length>0&&(f&&(f+="\n"),f+="Unknown scripts: "+c.sort().join(", ")),t.confirmed.length>0&&(f&&(f+="\n"),f+="New browser cookies: "+t.confirmed.join(", ")),e.title=f}}}()}function b(e){for(var t=0;t<d.length;t++)if(e===d[t]||0===e.indexOf(d[t]))return!0;return!1}function _(){for(var e=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),t=[],o=[],n={},i=Object.keys(a).length>0,r=0;r<e.length;r++){var c=e[r];n[c]||(n[c]=!0,b(c)||(i&&a[c]?o.push(c):t.push(c)))}return{confirmed:t.sort(),existing:o.sort()}}function C(){var e=document.getElementById("cc-overlay");e&&e.classList.remove("cc-show");var t=document.getElementById("cc-banner");t&&t.classList.remove("cc-show");var o=document.getElementById("cc-ccpa-banner");o&&o.classList.remove("cc-show");var n=document.getElementById("cc-icon");n&&n.classList.remove("cc-show")}}}();15 !function(){"use strict";var e=window.__ccInternal;if(e){var o=e.scriptLoaded,t=e.scriptLoadedUrls,n=e.hasCookie,i={"Google Analytics":function(){return o("googletagmanager.com/gtag")||o("google-analytics.com")||o("analytics.google.com")||n("_ga")},"Google Ads":function(){return o("googleads.g.doubleclick.net")||o("googleadservices.com")||o("googlesyndication.com")||n("_gcl_au")||n("_gcl_aw")},"Google Tag Manager":function(){return o("googletagmanager.com/gtm.js")||!!window.google_tag_manager},"Microsoft Ads":function(){return o("bat.bing.com")||!!window.uetq||n("_uetsid")||n("_uetvid")},"Meta / Facebook":function(){return o("connect.facebook.net")||!!window.fbq||n("_fbp")||n("_fbc")},"Twitter / X":function(){return o("ads-twitter.com")||o("static.ads-twitter.com")||!!window.twq||n("_twpid")},LinkedIn:function(){return o("snap.licdn.com")||o("ads.linkedin.com")||!!window._linkedin_data_partner_ids||n("li_sugr")||n("bcookie")||n("lidc")},Pinterest:function(){return o("s.pinimg.com/ct")||o("pintrk")||!!window.pintrk||n("_pin_unauth")},Reddit:function(){return o("alb.reddit.com")||o("events.reddit.com")||!!window.rdt||n("_rdt_uuid")},TikTok:function(){return o("analytics.tiktok.com")||!!window.ttq}};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",a):setTimeout(a,100)}function a(){var o=window.__ccDiscovery;if(o&&o.active&&(!document.body||!document.body.classList.contains("wp-admin"))){var n=function(){try{var e=sessionStorage.getItem("cookieflame_discovery_services");return e?JSON.parse(e):{}}catch(e){return{}}}(),a={};try{var r=localStorage.getItem("cookieflame_discovery_before");if(r)for(var c=JSON.parse(r),s=0;s<c.length;s++)a[c[s]]=!0}catch(e){}var d=["wordpress_","wp-settings","wp_lang","PHPSESSID","cc_consent","cc_anon_id","cookieflame_","woocommerce_","wp_woocommerce_"],l=document.createElement("div");l.id="cf-admin-discovery-bar",l.style.cssText="position:fixed;top:0;left:0;right:0;z-index:999999;background:#1d2327;color:#f0f0f1;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;display:flex;align-items:center;justify-content:space-between;padding:10px 20px;box-shadow:0 2px 8px rgba(0,0,0,.3);gap:16px;flex-wrap:wrap;";var m=document.createElement("div");m.style.cssText="display:flex;align-items:center;gap:12px;flex:1;min-width:200px;";var g=document.createElement("span");g.style.cssText="width:10px;height:10px;border-radius:50%;background:#00ba37;display:inline-block;flex-shrink:0;animation:cf-admin-pulse 2s infinite;";var p=document.createElement("span");p.textContent="Cookie Discovery Active",p.style.fontWeight="600";var f=document.createElement("span");f.id="cf-admin-discovery-count",f.style.cssText="background:#2271b1;color:#fff;padding:2px 10px;border-radius:12px;font-size:13px;font-weight:600;cursor:help;",f.textContent="scanning...",m.appendChild(g),m.appendChild(p),m.appendChild(f);var u=document.createElement("span");u.style.cssText="color:#a7aaad;font-size:13px;display:inline-flex;flex-direction:column;gap:2px;";var h=document.createElement("span");h.textContent="All cookies are temporarily accepted. Browse your pages, then click Finish.";var v=document.createElement("span");v.textContent="Tip: Browse by clicking links on the site. Typed URLs may skip discovery.",v.style.cssText="font-size:11px;opacity:0.75;",u.appendChild(h),u.appendChild(v),C(),setTimeout(C,500),setTimeout(C,2e3);var y=document.createElement("button");y.textContent="Finish Discovery",y.style.cssText="background:#00ba37;color:#fff;border:none;padding:8px 20px;border-radius:4px;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;",y.onmouseover=function(){y.style.background="#009929"},y.onmouseout=function(){y.style.background="#00ba37"},l.appendChild(m),l.appendChild(u),l.appendChild(y);var k=document.createElement("style");k.textContent="@keyframes cf-admin-pulse{0%,100%{opacity:1}50%{opacity:.4}}#cf-admin-discovery-bar~*{margin-top:0!important;}body.admin-bar #cf-admin-discovery-bar{top:32px}@media screen and (max-width:782px){body.admin-bar #cf-admin-discovery-bar{top:46px}}",document.head.appendChild(k),document.body.insertBefore(l,document.body.firstChild),document.addEventListener("click",function(e){for(var o=e.target;o&&1===o.nodeType&&"A"!==o.tagName;)o=o.parentNode;if(o&&"A"===o.tagName){var t=o.getAttribute("target");if("_blank"!==t&&"_top"!==t&&"_parent"!==t){var n=o.getAttribute("rel")||"";if(!n||-1===n.split(/\s+/).indexOf("external")){var i=o.getAttribute("href");if(i){var a;try{a=new URL(i,location.href)}catch(e){return}"http:"!==a.protocol&&"https:"!==a.protocol||a.origin===location.origin&&(a.pathname===location.pathname&&a.search===location.search&&a.hash!==location.hash||a.searchParams.has("cookieflame")||(a.searchParams.set("cookieflame","discover"),o.setAttribute("href",a.toString())))}}}}},!0),setTimeout(x,5e3);var w=setInterval(x,3e3);y.addEventListener("click",function(){y.disabled=!0,y.textContent="Finishing...",y.style.opacity="0.7",clearInterval(w),x();var e=n,t=window.__ccConfig||{};try{localStorage.setItem("cookieflame_discovery_results",JSON.stringify(e))}catch(o){var i=encodeURIComponent(JSON.stringify(e)),a=t.cookieDomain?"; domain="+t.cookieDomain:"";document.cookie="cookieflame_discovery_results="+i+"; path=/; max-age=300"+a}fetch(o.finishUrl,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":o.nonce},body:"{}"}).then(function(e){if(403===e.status)throw new Error("Your session has expired. Please reload the page and try again.");return e.json()}).then(function(e){var i=[location.hostname,"."+location.hostname];t.cookieDomain&&i.push(t.cookieDomain);for(var a=0;a<i.length;a++)document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i[a];if(document.cookie="cc_consent=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",e.restore_dnt){var r=t.cookieDomain?"; domain="+t.cookieDomain:"";document.cookie="cookieflame_dnt=1; path=/; max-age=31536000"+r}try{sessionStorage.removeItem("cookieflame_discovery_services")}catch(e){}for(var c=_(),s=0,d={},m=Object.keys(n),g=0;g<m.length;g++){var p=n[m[g]];if(p.unknown)s++,d[m[g]]=!0;else{var f=p.cookies||[];s+=f.length;for(var u=0;u<f.length;u++)d[f[u]]=!0}}for(var h=c.confirmed.concat(c.existing),v=0;v<h.length;v++)d[h[v]]||s++;l.style.background="#00ba37",l.innerHTML="";var y=document.createElement("span");y.style.cssText="font-weight:600;flex:1;text-align:center;";var k=s+" cookie"+(1!==s?"s":"")+" discovered. Redirecting to Cookie Manager...";y.textContent=k,l.appendChild(y),setTimeout(function(){window.location.href=o.adminUrl},1500)}).catch(function(e){y.disabled=!1,y.textContent="Finish Discovery",y.style.opacity="1",l.style.background="#d63638",u.style.color="#fff",u.textContent="Error: "+e.message})})}function x(){for(var o=function(){var o=[],n=e.getResourceSnapshot();e.setResourceSnapshot(n);for(var a=window.cookieflameAdmin&&window.cookieflameAdmin.serviceDetectors||[],r=[],c=0;c<a.length;c++)for(var s=a[c].scriptDomains||[],d=0;d<s.length;d++)r.push(s[d]);for(var l=0;l<a.length;l++){var m=a[l],g=m.name||"",p=i[g];if(p)try{if(p()){var f=t(g.toLowerCase().replace(/\s+/g,""));if(0===f.length&&-1!==g.indexOf(" "))for(var u=g.toLowerCase().split(" "),h=0;h<u.length&&0===f.length;h++)u[h].length>3&&(f=t(u[h]));o.push({name:g,cookies:m.cookies||[],canonicalDomain:m.canonicalDomain||"",scriptUrls:f})}}catch(e){}}o.pagePlugins=n.pluginScripts;for(var v=["wp.com","wordpress.com","wordpress.org","s.w.org","gravatar.com","cdnjs.cloudflare.com","cdn.jsdelivr.net","unpkg.com","ajax.googleapis.com","fonts.googleapis.com","fonts.gstatic.com","code.jquery.com","stackpath.bootstrapcdn.com","maxcdn.bootstrapcdn.com","www.google.com/recaptcha","www.gstatic.com","apis.google.com","maps.googleapis.com","maps.google.com","challenges.cloudflare.com","static.cloudflareinsights.com","chromium.org","mozilla.org","lazyload","rocket-loader","elementor.com"],y=n.thirdPartyDomains,k=0;k<y.length;k++){for(var w=y[k],x=!1,b=0;b<v.length;b++)if(w===v[b]||-1!==w.indexOf("."+v[b])||-1!==v[b].indexOf(w)){x=!0;break}if(!x){for(var _=!1,C=0;C<r.length;C++)if(-1!==w.indexOf(r[C])||-1!==r[C].indexOf(w)){_=!0;break}_||o.push({name:w,cookies:[],unknown:!0})}}return e.setResourceSnapshot(null),o}(),a=0;a<o.length;a++)n[o[a].name]||(n[o[a].name]=o[a]);if(o.pagePlugins&&o.pagePlugins.length){for(var r=n.__pagePlugins||{},c=0;c<o.pagePlugins.length;c++)r[o.pagePlugins[c].slug]=o.pagePlugins[c].url;n.__pagePlugins=r}!function(e){try{sessionStorage.setItem("cookieflame_discovery_services",JSON.stringify(e))}catch(e){}}(n),function(){var e=document.getElementById("cf-admin-discovery-count");if(e){for(var o=_(),t=(o.confirmed.length,o.existing.length,0),i={},a=Object.keys(n),r=[],c=[],s=0;s<a.length;s++){var d=n[a[s]];if(d.unknown)t++,c.push(a[s]),i[a[s]]=!0;else{r.push(a[s]);var l=d.cookies||[];t+=l.length;for(var m=0;m<l.length;m++)i[l[m]]=!0}}for(var g=o.confirmed.concat(o.existing),p=0;p<g.length;p++)i[g[p]]||t++;if(0===t)e.textContent="no cookies yet",e.title="Browse your site to discover cookies";else{e.textContent=t+" cookie"+(1!==t?"s":"")+" discovered";var f="";r.length>0&&(f+="Services: "+r.sort().join(", ")),c.length>0&&(f&&(f+="\n"),f+="Unknown scripts: "+c.sort().join(", ")),o.confirmed.length>0&&(f&&(f+="\n"),f+="New browser cookies: "+o.confirmed.join(", ")),e.title=f}}}()}function b(e){for(var o=0;o<d.length;o++)if(e===d[o]||0===e.indexOf(d[o]))return!0;return!1}function _(){for(var o=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),t=[],n=[],i={},r=Object.keys(a).length>0,c=e.visitorCookies?e.visitorCookies(o):{},s=window.cookieflameAdmin&&window.cookieflameAdmin.ignoredCookieNames||[],d=0;d<o.length;d++){var l=o[d];i[l]||(i[l]=!0,b(l)||c[l]||-1!==s.indexOf(l)||(r&&a[l]?n.push(l):t.push(l)))}return{confirmed:t.sort(),existing:n.sort()}}function C(){var e=document.getElementById("cc-overlay");e&&e.classList.remove("cc-show");var o=document.getElementById("cc-banner");o&&o.classList.remove("cc-show");var t=document.getElementById("cc-ccpa-banner");t&&t.classList.remove("cc-show");var n=document.getElementById("cc-icon");n&&n.classList.remove("cc-show")}}}(); -
cookieflame/trunk/assets/js/cookieconsent.js
r3768250 r3769546 1 1 /** 2 * CookieFlame v5. 2.02 * CookieFlame v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Self-hosted cookie consent manager with Google Consent Mode v2, … … 40 40 } catch (e) {} 41 41 42 var PLUGIN_VERSION = "5. 2.0";42 var PLUGIN_VERSION = "5.3.0"; 43 43 44 44 /* ═══════════════════════════════════════════ … … 1400 1400 hasCookiePrefix: hasCookiePrefix, 1401 1401 setResourceSnapshot: function (s) { _resourceSnapshot = s; }, 1402 // Discovery bar (v5.3.0): which of these cookies came with the browser, 1403 // by the same check passive monitoring uses, so its count matches the 1404 // Cookie Manager. 1405 visitorCookies: function (names) { 1406 var domains = getResourceSnapshot().thirdPartyDomains, out = {}; 1407 for (var i = 0; i < names.length; i++) { 1408 if (isVisitorCookie(names[i], domains, cookieSetter(names[i]))) out[names[i]] = true; 1409 } 1410 return out; 1411 }, 1402 1412 // Facade module bridge (v4.41.0+). The facade module reads this to 1403 1413 // access core state it needs for overlay rendering, and registers … … 1898 1908 try { 1899 1909 var url = new URL(String(setters[name]).replace(/:\d+(:\d+)?$/, "")); 1910 if (/^(chrome-extension|moz-extension|safari-web-extension|safari-extension):$/.test(url.protocol)) { 1911 out.set_by = "browser-extension"; 1912 return out; 1913 } 1900 1914 var host = url.hostname; 1901 1915 if (host === location.hostname || host === "www." + location.hostname || "www." + host === location.hostname) { … … 1908 1922 } catch (e) {} 1909 1923 return out; 1924 } 1925 1926 /** 1927 * Whether a cookie came with the visitor's browser rather than this site: 1928 * written by a browser extension, or another consent tool's cookie when 1929 * that tool isn't on the page (rules from window.__ccVisitorCookieRules, 1930 * limited to tools whose WordPress plugin isn't active). Skipping these 1931 * keeps the page's beacon allowance for real cookies; the server makes 1932 * the same check and records them on the ignore list. 1933 */ 1934 function isVisitorCookie(name, domains, setter) { 1935 if (setter.set_by === "browser-extension") return true; 1936 var rules = window.__ccVisitorCookieRules; 1937 if (!rules || !rules.tools) return false; 1938 if (rules.allow && rules.allow.indexOf(name) !== -1) return false; 1939 if (setter.set_by) return false; // A page script wrote it, so the tool runs here. 1940 for (var t = 0; t < rules.tools.length; t++) { 1941 var tool = rules.tools[t], hit = (tool.n || []).indexOf(name) !== -1; 1942 for (var p = 0; !hit && p < (tool.p || []).length; p++) { 1943 if (name.indexOf(tool.p[p]) === 0) hit = true; 1944 } 1945 if (!hit) continue; 1946 for (var d = 0; d < domains.length; d++) { 1947 for (var k = 0; k < (tool.d || []).length; k++) { 1948 var host = String(domains[d]).toLowerCase(), dom = tool.d[k]; 1949 if (host === dom || host.slice(-dom.length - 1) === "." + dom) return false; 1950 } 1951 } 1952 return true; 1953 } 1954 return false; 1910 1955 } 1911 1956 … … 1988 2033 1989 2034 var setter = cookieSetter(name); 2035 // Visitors' browsers don't report these. During Cookie Discovery they 2036 // are reported anyway, so the server records them on the Permanently 2037 // Ignored list with the reason and the admin sees what was set aside. 2038 if (isVisitorCookie(name, scriptDomains, setter) && !(window.__ccDiscovery && window.__ccDiscovery.active)) { 2039 beaconed[name] = true; 2040 continue; 2041 } 1990 2042 1991 2043 var payload = JSON.stringify({ -
cookieflame/trunk/assets/js/cookieconsent.min.js
r3768250 r3769546 1 1 /** 2 * CookieFlame v5. 2.02 * CookieFlame v5.3.0 3 3 * ───────────────────────────────────────────────────────────── 4 4 * Self-hosted cookie consent manager with Google Consent Mode v2, … … 17 17 * • Timezone-based geo heuristic with server-side fallback 18 18 */ 19 !function(){"use strict";var e={};try{for(var t=document.cookie.split(";"),n=0;n<t.length;n++){var o=t[n].trim().split("=")[0];o&&(e[o]=!0)}}catch(e){}var c="5. 2.0",r={cookieName:"cc_consent",cookieExpiry:365,privacyUrl:"/privacy-policy",ccpaUrl:"/privacy-policy#do-not-sell",geoApi:"",logEndpoint:"",reconsentDays:365,cspSafe:!1,tcfEnabled:!0,cmpId:1,cmpVersion:1,vendorListVersion:2,storageMethod:"cookie",cookieDomain:"",shareSubdomains:!1,theme:"light",showPoweredBy:!1,iconPosition:"left",consentVersion:"",autoBlockPatterns:[{pattern:"googletagmanager.com/gtag",category:"analytics"},{pattern:"google-analytics.com",category:"analytics"},{pattern:"analytics.google.com",category:"analytics"},{pattern:"hotjar.com",category:"analytics"},{pattern:"mixpanel.com",category:"analytics"},{pattern:"segment.com/analytics",category:"analytics"},{pattern:"segment.io",category:"analytics"},{pattern:"clarity.ms",category:"analytics"},{pattern:"plausible.io",category:"analytics"},{pattern:"js.hs-analytics.net",category:"analytics"},{pattern:"connect.facebook.net",category:"marketing"},{pattern:"snap.licdn.com",category:"marketing"},{pattern:"ads.linkedin.com",category:"marketing"},{pattern:"googleads.g.doubleclick.net",category:"marketing"},{pattern:"googlesyndication.com",category:"marketing"},{pattern:"googleadservices.com",category:"marketing"},{pattern:"ads-twitter.com",category:"marketing"},{pattern:"analytics.tiktok.com",category:"marketing"},{pattern:"pintrk",category:"marketing"},{pattern:"s.pinimg.com/ct",category:"marketing"},{pattern:"widget.intercom.io",category:"preferences"},{pattern:"js.intercomcdn.com",category:"preferences"}],regionRules:{gdpr:["AT","BE","BG","CY","CZ","DE","DK","EE","ES","FI","FR","GR","HR","HU","IE","IT","LT","LU","LV","MT","NL","PL","PT","RO","SE","SI","SK","IS","LI","NO","GB","GG","JE","IM","CH","BR","ZA"],ccpa:["US"]},text:{title:"We value your privacy",description:"We use cookies to improve your experience, analyse traffic and personalise content. You can choose which categories to allow.",acceptAllButton:"Accept All",declineAllButton:"Decline All",saveButton:"Save Preferences",showDetailsButton:"Manage preferences",hideDetailsButton:"Hide preferences",alwaysOnLabel:"(always on)",ccpaTitle:"Your Privacy Choices",ccpaDescription:"We use cookies and similar technologies. Under California law, you have the right to opt out of the sale or sharing of your personal information.",ccpaAcceptButton:"OK",ccpaDnsmpiLink:"Do Not Sell My Personal Information"},cookieTypes:[{id:"necessary",name:"Necessary",description:"Required for the site to function. Cannot be disabled.",required:!0,consentMode:["security_storage","functionality_storage"],tcfPurposes:[1],onAccept:function(){}},{id:"preferences",name:"Preferences",description:"Remember your settings and personalisation choices.",required:!1,defaultValue:!1,consentMode:["functionality_storage","personalization_storage"],tcfPurposes:[2,3],onAccept:function(){},onReject:function(){}},{id:"analytics",name:"Analytics",description:"Help us understand how visitors use the site.",required:!1,defaultValue:!1,consentMode:["analytics_storage"],tcfPurposes:[4,5,6],onAccept:function(){},onReject:function(){}},{id:"marketing",name:"Marketing",description:"Used to deliver relevant ads and track campaigns.",required:!1,defaultValue:!1,consentMode:["ad_storage","ad_user_data","ad_personalization"],tcfPurposes:[7,8,9,10],onAccept:function(){},onReject:function(){}}]};if(window.__ccConfig&&"object"==typeof window.__ccConfig){var a=window.__ccConfig;["cookieName","cookieExpiry","privacyUrl","ccpaUrl","geoApi","logEndpoint","reconsentDays","cspSafe","tcfEnabled","cmpId","cmpVersion","vendorListVersion","storageMethod","cookieDomain","shareSubdomains","theme","showPoweredBy","iconPosition","consentVersion"].forEach(function(e){void 0!==a[e]&&(r[e]=a[e])}),a.text&&"object"==typeof a.text&&Object.keys(a.text).forEach(function(e){r.text[e]=a.text[e]}),Array.isArray(a.cookieTypes)&&(r.cookieTypes=a.cookieTypes),Array.isArray(a.autoBlockPatterns)&&(r.autoBlockPatterns=a.autoBlockPatterns),a.regionRules&&(r.regionRules=a.regionRules)}window.__ccConsentVersion&&(r.consentVersion=window.__ccConsentVersion);var i=!!window.__ccGPC;window.__ccBlockRules&&Array.isArray(window.__ccBlockRules)&&window.__ccBlockRules.length&&(r.autoBlockPatterns=window.__ccBlockRules);var s={cc_consent:{vendor:"CookieFlame",category:"necessary",purpose:"Stores your consent preferences",expiry:"1 year"},cc_anon_id:{vendor:"CookieFlame",category:"necessary",purpose:"Anonymous ID for consent logging",expiry:"1 year"},cookieflame_dnt:{vendor:"CookieFlame",category:"necessary",purpose:"Do-not-track opt-out flag",expiry:"1 year"},PHPSESSID:{vendor:"PHP",category:"necessary",purpose:"Server-side session identifier",expiry:"Session"},wp_settings_:{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-":{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-time-":{vendor:"WordPress",category:"necessary",purpose:"Admin settings timestamp",prefix:!0,expiry:"1 year"},wordpress_logged_in_:{vendor:"WordPress",category:"necessary",purpose:"Login session",prefix:!0,expiry:"Session"},wordpress_sec_:{vendor:"WordPress",category:"necessary",purpose:"Secure login session",prefix:!0,expiry:"Session"},wordpress_test_cookie:{vendor:"WordPress",category:"necessary",purpose:"Checks cookie support",expiry:"Session"},wp_lang:{vendor:"WordPress",category:"necessary",purpose:"Language preference",expiry:"Session"},woocommerce_cart_hash:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping cart contents",expiry:"Session"},woocommerce_items_in_cart:{vendor:"WooCommerce",category:"necessary",purpose:"Cart item count",expiry:"Session"},wp_woocommerce_session_:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping session",prefix:!0,expiry:"2 days"},_ga:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors",expiry:"2 years"},_ga_:{vendor:"Google Analytics",category:"analytics",purpose:"Stores session state",prefix:!0,expiry:"2 years"},_gid:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors (24h)",expiry:"24 hours"},_gat:{vendor:"Google Analytics",category:"analytics",purpose:"Throttles request rate",expiry:"1 minute"},wp_wk_ga_untrack_:{vendor:"Google Analytics",category:"analytics",purpose:"GA opt-out flag",prefix:!0,expiry:"Persistent"},_gcl_au:{vendor:"Google Ads",category:"marketing",purpose:"Conversion linker",expiry:"90 days"},_gcl_aw:{vendor:"Google Ads",category:"marketing",purpose:"Stores ad click info",expiry:"90 days"},_gac_:{vendor:"Google Ads",category:"marketing",purpose:"Campaign information",prefix:!0,expiry:"90 days"},IDE:{vendor:"Google DoubleClick",category:"marketing",purpose:"Ad serving and frequency",expiry:"1 year"},test_cookie:{vendor:"Google DoubleClick",category:"marketing",purpose:"Checks cookie support",expiry:"15 minutes"},NID:{vendor:"Google",category:"preferences",purpose:"Stores preferences",expiry:"6 months"}},d=window.__ccCustomCookies||[];function u(e){for(var t=0;t<d.length;t++){var n=d[t];if("exact"===n.match&&e===n.name)return n;if("prefix"===n.match&&0===e.indexOf(n.name))return n;if("contains"===n.match&&-1!==e.indexOf(n.name))return n}var o=s[e];return o||(Object.keys(s).forEach(function(t){!o&&s[t].prefix&&0===e.indexOf(t)&&(o=s[t])}),o||null)}var l=null,p="none",f=null,m=null,g=!1,y=0;function v(e){return"string"!=typeof e&&(e=String(e)),e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function h(e){if("localStorage"===r.storageMethod)try{return localStorage.getItem(e)}catch(e){return null}var t=document.cookie.match(new RegExp("(?:^|;\\s*)"+e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"=([^;]*)"));if(!t)return null;try{return decodeURIComponent(t[1])}catch(e){return null}}function w(e,t,n){if("localStorage"!==r.storageMethod){var o=new Date;o.setTime(o.getTime()+864e5*n);var c=e+"="+encodeURIComponent(t)+";expires="+o.toUTCString()+";path=/;SameSite=Lax;Secure";r.cookieDomain&&(c+=";domain="+r.cookieDomain),document.cookie=c}else try{localStorage.setItem(e,t)}catch(e){}}function b(){if(m)return m;var e=h("cc_anon_id");return e?(m=e,e):(w("cc_anon_id",m="cc_"+function(){if("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID)try{return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}(),730),m)}function k(){var e={timestamp:l?l.ts:null,complianceMode:p,country:f,gpc:i,consentVersion:r.consentVersion};return r.cookieTypes.forEach(function(t){e[t.id]=l?!!l[t.id]:!!t.required}),e}function _(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t||k()}))}function x(){window.dataLayer=window.dataLayer||[],window.dataLayer.push(arguments)}function E(e){var t={};r.cookieTypes.forEach(function(n){n.consentMode&&n.consentMode.forEach(function(o){t[o]=e[n.id]?"granted":"denied"})}),i&&(t.ad_storage="denied",t.ad_user_data="denied",t.ad_personalization="denied"),x("consent","update",t)}var A=new Map,S=!1;function L(e){var t={};return r.cookieTypes.forEach(function(n){n.tcfPurposes&&n.tcfPurposes.forEach(function(o){t[o]=!!e[n.id]})}),{tcString:"",tcfPolicyVersion:4,cmpId:r.cmpId,cmpVersion:r.cmpVersion,gdprApplies:"gdpr"===p,eventStatus:"useractioncomplete",cmpStatus:"loaded",listenerId:void 0,isServiceSpecific:!0,useNonStandardTexts:!1,publisherCC:"GB",purposeOneTreatment:!1,purpose:{consents:t,legitimateInterests:{}},vendor:{consents:{},legitimateInterests:{}},specialFeatureOptins:{},publisher:{consents:{},legitimateInterests:{},customPurpose:{consents:{},legitimateInterests:{}},restrictions:{}}}}function C(e,t,n,o){if("function"==typeof n)if("addEventListener"===e){var c=++y;if(A.set(c,n),l){var a=L(l);a.listenerId=c,n(a,!0)}}else"removeEventListener"===e?n({listenerId:o},A.delete(o)):"getTCData"===e?n(l?L(l):null,!!l):"ping"===e?n({gdprApplies:"gdpr"===p,cmpLoaded:S,cmpStatus:S?"loaded":"stub",displayStatus:"hidden",apiVersion:"2.2",cmpVersion:r.cmpVersion,cmpId:r.cmpId,gvlVersion:r.vendorListVersion,tcfPolicyVersion:4},!0):n(null,!1)}function B(e){A.forEach(function(t,n){var o=L(e);o.listenerId=n;try{t(o,!0)}catch(e){}})}function I(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<r.autoBlockPatterns.length;n++){var o=r.autoBlockPatterns[n];if(o.pattern instanceof RegExp){if(o.pattern.test(t))return o.category}else if(-1!==t.indexOf(o.pattern.toLowerCase()))return o.category}return null}function T(e){document.querySelectorAll('script[type="text/plain"][data-cc]').forEach(function(t){var n=(t.getAttribute("data-cc")||"").toLowerCase();if(e[n]&&!t.getAttribute("data-cc-activated")){t.setAttribute("data-cc-activated","1");var o=document.createElement("script");o.isWPRocket=!0,Array.from(t.attributes).forEach(function(e){"type"!==e.name&&"data-cc"!==e.name&&"data-cc-activated"!==e.name&&"data-cc-auto"!==e.name&&o.setAttribute(e.name,e.value)}),!t.src&&t.textContent&&(o.textContent=t.textContent),t.parentNode.insertBefore(o,t.nextSibling),t.parentNode.removeChild(t)}}),["img","iframe","link"].forEach(function(t){document.querySelectorAll(t+"[data-cc][data-cc-src]").forEach(function(n){var o=(n.getAttribute("data-cc")||"").toLowerCase();e[o]&&!n.getAttribute("data-cc-activated")&&(n.setAttribute("data-cc-activated","1"),"link"===t?n.href=n.getAttribute("data-cc-src"):n.src=n.getAttribute("data-cc-src"))})})}var O=[{pattern:"youtube.com",category:"marketing"},{pattern:"youtube-nocookie.com",category:"marketing"},{pattern:"youtu.be",category:"marketing"},{pattern:"player.vimeo.com",category:"marketing"},{pattern:"vimeo.com",category:"marketing"},{pattern:"dailymotion.com",category:"marketing"},{pattern:"open.spotify.com",category:"preferences"},{pattern:"soundcloud.com",category:"preferences"},{pattern:"google.com/maps",category:"preferences"},{pattern:"maps.google.com",category:"preferences"},{pattern:"facebook.com/plugins",category:"marketing"},{pattern:"instagram.com",category:"marketing"},{pattern:"tiktok.com/embed",category:"marketing"},{pattern:"twitter.com",category:"marketing"},{pattern:"x.com",category:"marketing"}];function P(){return!(!document.body||!(document.body.classList.contains("elementor-editor-active")||document.body.classList.contains("fl-builder-edit")||document.body.classList.contains("et-fb-root-ancestor")))}var D=[],M=0,R=null,q=!1;function V(){if(R&&D.length){var e=D;D=[];try{R(e)}catch(e){}}}function N(){0!==D.length&&(2!==M?1!==M&&3!==M&&(M=1,function(){var e=window.__ccConfig&&window.__ccConfig.facadesUrl||null;if(!e)return void(M=3);var t=document.createElement("script");t.src=e,t.async=!0,t.onload=function(){M=2,V()},t.onerror=function(){M=3},(document.head||document.documentElement).appendChild(t)}()):V())}function U(e){var t=e.src||e.getAttribute("data-src")||"";if(t&&!e.getAttribute("data-cc-facade")&&!P()){var n=function(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<O.length;n++)if(-1!==t.indexOf(O[n].pattern))return O[n].category;return null}(t);if(n){var o=l||$();o&&o[n]||(e.setAttribute("data-cc-facade","1"),e.setAttribute("data-cc-iframe-cat",n),e.setAttribute("data-cc-original-src",t),e.removeAttribute("src"),e.style.display="none",D.push({type:"iframe",node:e,category:n,src:t}),N())}}}function G(e){if(!e.getAttribute("data-cc-facade")&&!P()){var t=e.getAttribute("data-settings");if(t){var n;try{n=JSON.parse(t)}catch(e){return}var o=n.youtube_url||n.vimeo_url||"";if(o){var c=o.toLowerCase(),r=null;if((-1!==c.indexOf("youtube")||-1!==c.indexOf("youtu.be")||-1!==c.indexOf("vimeo")||-1!==c.indexOf("dailymotion"))&&(r="marketing"),r&&(!l||!l[r])){if(!l){var a=$();if(a&&a[r])return}e.setAttribute("data-cc-facade","1"),q=!0,D.push({type:"elementor",node:e,category:r,url:o}),N()}}}}}function j(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++)U(e[t]);for(var n=document.querySelectorAll(".elementor-widget-video"),o=0;o<n.length;o++)G(n[o]);for(var c=document.querySelectorAll(".wp-block-embed__wrapper iframe[src]"),r=0;r<c.length;r++)U(c[r])}function J(){new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){if("IFRAME"===e.tagName&&U(e),e.querySelectorAll){for(var t=e.querySelectorAll("iframe[src]"),n=0;n<t.length;n++)U(t[n]);for(var o=e.querySelectorAll(".elementor-widget-video"),c=0;c<o.length;c++)G(o[c])}e.classList&&e.classList.contains("elementor-widget-video")&&G(e)}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}function W(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++){var n=e[t];if(!n.getAttribute("data-cc-facade")){var o=n.src||"";if(o)for(var c=0;c<O.length;c++)if(-1!==o.indexOf(O[c].pattern)){n.src=o;break}}}}function H(e,t){r.cookieTypes.forEach(function(n){var o=!!e[n.id];if((t?!!t[n.id]:null)!==o||null===t)if(o&&"function"==typeof n.onAccept)try{n.onAccept()}catch(e){console.warn("[CookieConsent] onAccept error for "+n.id,e)}else if(!o&&"function"==typeof n.onReject)try{n.onReject()}catch(e){console.warn("[CookieConsent] onReject error for "+n.id,e)}})}function F(e,t){var n=l;if(l=e,w(r.cookieName,JSON.stringify(e),r.cookieExpiry),E(e),q&&t)for(var o=document.querySelectorAll(".cc-iframe-facade[data-cc-elementor-widget]"),a=0;a<o.length;a++){var s=o[a].getAttribute("data-cc-iframe-cat");if(s&&e[s])return void window.location.reload()}z(e,n),T(e),function(e){for(var t=document.querySelectorAll(".cc-iframe-facade"),n=0;n<t.length;n++)if(!t[n].getAttribute("data-cc-elementor-widget")&&e[t[n].getAttribute("data-cc-iframe-cat")]){var o=t[n].nextElementSibling;if(o&&"IFRAME"===o.tagName&&o.getAttribute("data-cc-facade")){var c=o.getAttribute("data-cc-original-src");c&&(o.src=c,o.style.display="",o.removeAttribute("data-cc-facade"))}t[n].parentNode.removeChild(t[n])}}(e),t&&"auto_grant_non_eu"!==t&&"ccpa_auto_grant"!==t&&setTimeout(W,300),H(e,n),Z(e),r.tcfEnabled&&B(e),t&&function(e,t){if(r.logEndpoint){var n={};r.cookieTypes.forEach(function(e){n[e.id]=!!t[e.id]});var o={anonymousId:b(),timestamp:(new Date).toISOString(),action:e,consent:n,complianceMode:p,country:f,url:location.href,userAgent:navigator.userAgent,tcfEnabled:r.tcfEnabled,gpc:i,consentVersion:r.consentVersion,version:c};try{var a=JSON.stringify(o);navigator.sendBeacon?navigator.sendBeacon(r.logEndpoint,new Blob([a],{type:"application/json"})):fetch(r.logEndpoint,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0})}catch(e){}}}(t,e)}function Z(e){r.cookieTypes.forEach(function(t){if(!t.required){var n=document.getElementById("cc-cb-"+t.id);n&&(n.checked=!!e[t.id])}});var t=document.getElementById("cc-cats"),n=document.getElementById("cc-details"),o=document.getElementById("cc-pref-buttons");t&&t.classList.remove("cc-open"),n&&(n.textContent=r.text.showDetailsButton),o&&o.classList.remove("cc-open")}function $(){var e=h(r.cookieName);if(!e)return null;try{var t=JSON.parse(e);return!t||"object"!=typeof t||Array.isArray(t)||(!t.ts||isNaN(new Date(t.ts).getTime())||(Date.now()-new Date(t.ts).getTime())/864e5>r.reconsentDays||r.consentVersion&&t.cv!==r.consentVersion)?null:t}catch(e){return null}}function Y(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!0}),e}function K(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!!t.required}),e}function z(e,t){if(t){var n=[];if(r.cookieTypes.forEach(function(o){o.required||t[o.id]&&!e[o.id]&&n.push(o.id)}),n.length)document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean).forEach(function(e){var t=u(e);if(t&&-1!==n.indexOf(t.category)){var o=location.hostname,c="."+o;document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+c,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+o,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; Secure",r.cookieDomain&&(document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain+"; Secure");var a=o.split(".");if(a.length>2){var i="."+a.slice(1).join(".");document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i+"; Secure"}}})}}function Q(e){return(f=e?e.toUpperCase():null)?r.regionRules.gdpr&&-1!==r.regionRules.gdpr.indexOf(f)?"gdpr":r.regionRules.ccpa&&-1!==r.regionRules.ccpa.indexOf(f)?"ccpa":"none":"gdpr"}function X(e){if(window.__ccGeo)return e(Q(window.__ccGeo));r.geoApi?fetch(r.geoApi).then(function(e){return e.json()}).then(function(t){var n=t.country_code||t.country||"";n?e(Q(n)):ee(e)}).catch(function(){ee(e)}):ee(e)}function ee(e){var t="";try{t=Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch(e){}return 0===t.indexOf("Europe/")||"Atlantic/Reykjavik"===t?(f=null,e("gdpr")):0===t.indexOf("US/")||0===t.indexOf("America/")&&["New_York","Chicago","Denver","Los_Angeles","Phoenix","Anchorage","Boise","Detroit","Indianapolis","Louisville","Menominee","Nome","Adak","Juneau","Sitka","Yakutat","Metlakatla","Kentucky","Indiana","North_Dakota"].some(function(e){return-1!==t.indexOf(e)})||"Pacific/Honolulu"===t?(f="US",e("ccpa")):(f=null,void e("gdpr"))}function te(){"dark"===r.theme&&document.documentElement.classList.add("cc-dark"),"right"===r.iconPosition&&document.documentElement.classList.add("cc-icon-right")}function ne(){var e=r.text,t=document.createElement("div");t.id="cc-overlay",document.body.appendChild(t);var n=document.createElement("div");n.id="cc-banner",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-label","Cookie consent"),n.setAttribute("tabindex","-1");var o=r.cookieTypes.map(function(t){var n=t.required?' <span class="cc-always-on">'+v(e.alwaysOnLabel)+"</span>":"";return'<div class="cc-cat"><div><div class="cc-cat-label">'+v(t.name)+n+'</div><div class="cc-cat-desc">'+v(t.description||"")+'</div></div><label class="cc-toggle"><input type="checkbox" id="cc-cb-'+v(t.id)+'" aria-label="'+v(t.name)+'"'+(t.required||t.defaultValue?" checked":"")+(t.required?" disabled":"")+'><span class="cc-slider"></span></label></div>'}).join("");n.innerHTML='<div class="cc-inner"><p class="cc-title">'+v(e.title)+'</p><p class="cc-text">'+v(e.description)+' <a href="'+v(r.privacyUrl)+'">Privacy Policy</a></p><div class="cc-buttons"><button class="cc-btn cc-btn-accept" id="cc-accept">'+v(e.acceptAllButton)+'</button><button class="cc-btn cc-btn-details" id="cc-details" aria-expanded="false">'+v(e.showDetailsButton)+'</button></div><div class="cc-categories" id="cc-cats">'+o+'</div><div class="cc-pref-buttons" id="cc-pref-buttons"><button class="cc-btn cc-btn-save" id="cc-save">'+v(e.saveButton)+'</button><button class="cc-btn cc-btn-decline" id="cc-decline">'+v(e.declineAllButton)+"</button></div></div>"+(r.showPoweredBy?'<div class="cc-powered"><a href="https://www.cookieflame.com" target="_blank" rel="noopener">Powered by CookieFlame</a></div>':""),document.body.appendChild(n);var c=document.createElement("button");c.id="cc-icon",c.setAttribute("aria-label","Cookie settings"),c.innerHTML='<svg width="24" height="24" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19.1 1.16c-.06-.42-.38-.77-.8-.83A11.8 11.8 0 0 0 13.28 1.2L7.5 4.3A11.8 11.8 0 0 0 3.95 7.98L1.09 13.9A11.8 11.8 0 0 0 .38 18.96l1.13 6.47a11.8 11.8 0 0 0 3.53 4.99l4.71 4.56a11.8 11.8 0 0 0 4.59 2.24l6.48.91a11.8 11.8 0 0 0 5.52-.89l5.78-3.09a11.8 11.8 0 0 0 3.55-3.69l2.87-5.9a11.8 11.8 0 0 0 .71-5.08c-.07-.41-.42-.73-.83-.79a14.8 14.8 0 0 1-8.16-7.61c-.14-.59-.63-1.05-1.23-1.14A14.8 14.8 0 0 1 19.1 1.16ZM15.25 10.25a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm-5 15a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0Zm17.5-5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z" fill="currentColor"/></svg>',document.body.appendChild(c),document.getElementById("cc-accept").addEventListener("click",se),document.getElementById("cc-decline").addEventListener("click",de),document.getElementById("cc-save").addEventListener("click",ue),document.getElementById("cc-details").addEventListener("click",le),c.addEventListener("click",function(){re("gdpr")})}var oe=null;function ce(e){if("Tab"===e.key){var t=document.getElementById("cc-banner")||document.getElementById("cc-ccpa-banner");if(t&&t.classList.contains("cc-show")){for(var n=[],o=t.querySelectorAll('button, a[href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])'),c=0;c<o.length;c++){for(var r=o[c],a=!1,i=r.parentElement;i&&i!==t;){if(i.style&&"none"===window.getComputedStyle(i).display){a=!0;break}i=i.parentElement}a||n.push(r)}if(0!==n.length){var s=n[0],d=n[n.length-1];e.shiftKey?document.activeElement===s&&(e.preventDefault(),d.focus()):document.activeElement===d&&(e.preventDefault(),s.focus())}}}}function re(e){"ccpa"!==e?(oe=document.activeElement,requestAnimationFrame(function(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.add("cc-show"),t){t.classList.add("cc-show");var o=t.querySelector(".cc-btn-accept");o&&o.focus(),document.addEventListener("keydown",ce)}n&&n.classList.remove("cc-show")})):requestAnimationFrame(function(){var e=document.getElementById("cc-ccpa-banner");e&&(e.classList.add("cc-show"),oe=document.activeElement,e.focus(),document.addEventListener("keydown",ce))})}function ae(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&"gdpr"===p&&n.classList.add("cc-show"),document.removeEventListener("keydown",ce),oe&&"function"==typeof oe.focus)try{oe.focus()}catch(e){}oe=null}function ie(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&n.classList.remove("cc-show"),document.removeEventListener("keydown",ce)}function se(){F(Y(),"accept_all"),ae(),_("cc:accept-all"),_("cc:update")}function de(){F(K(),"decline_all"),ae(),_("cc:decline-all"),_("cc:update")}function ue(){var e;F((e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f},r.cookieTypes.forEach(function(t){if(t.required)e[t.id]=!0;else{var n=document.getElementById("cc-cb-"+t.id);e[t.id]=!!n&&n.checked}}),e),"save_preferences"),ae(),_("cc:save"),_("cc:update")}function le(){var e=document.getElementById("cc-cats"),t=document.getElementById("cc-details"),n=document.getElementById("cc-pref-buttons"),o=e.classList.toggle("cc-open");t.textContent=o?r.text.hideDetailsButton:r.text.showDetailsButton,t.setAttribute("aria-expanded",o?"true":"false"),n&&(o?n.classList.add("cc-open"):n.classList.remove("cc-open"))}function pe(){var e=document.getElementById("cc-declaration");if(e){for(var t=k(),n={},o=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),c=0;c<o.length;c++){var a=u(o[c]);a&&(n[o[c]]={name:o[c],vendor:a.vendor,category:a.category,purpose:a.purpose,expiry:a.expiry||"",active:!0})}for(var i=0;i<d.length;i++){var s=d[i];s.name&&s.vendor&&s.category&&"unclassified"!==s.category&&!n[s.name]&&(n[s.name]={name:s.name,vendor:s.vendor,category:s.category,purpose:s.purpose||"",expiry:s.expiry||"",active:!1})}for(var l=0;l<o.length;l++)n[o[l]]||(n[o[l]]={name:o[l],vendor:"",category:"unclassified",purpose:"",expiry:"",active:!0});var p=["necessary","preferences","analytics","marketing"],f={};r.cookieTypes.forEach(function(e){f[e.id]=e.name});var m={};p.forEach(function(e){m[e]=[]}),Object.keys(n).forEach(function(e){var t=n[e],o=t.category;m[o]||(m[o]=[]),m[o].push(t)}),p.forEach(function(e){m[e]&&m[e].sort(function(e,t){return e.name.localeCompare(t.name)})});var g="<div>";if(t.timestamp){var y=new Date(t.timestamp);g+="<p>"+v("Your consent was last updated on "+y.toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"})+" at "+y.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})+".")+"</p>"}else g+="<p>"+v("You have not yet made a cookie preference choice on this site.")+"</p>";for(var h=0;h<p.length;h++){var w=p[h],b=m[w];if(b&&b.length){var _,x=f[w]||w,E=r.cookieTypes.filter(function(e){return e.id===w})[0],A=E&&E.description||"";_=!!E&&E.required?"Always active":t[w]?"Active":"Inactive",g+="<div>",g+="<p><b>"+v(x)+"</b> ("+v(_)+")</p>",A&&(g+="<p>"+v(A)+"</p>"),g+="<table><thead><tr>",g+="<th>Name</th><th>Provider</th><th>Purpose</th><th>Expiry</th>",g+="</tr></thead><tbody>";for(var S=0;S<b.length;S++){var L=b[S];g+="<tr>",g+="<td><code>"+v(L.name)+"</code></td>",g+="<td>"+v(L.vendor||"Unknown")+"</td>",g+="<td>"+v(L.purpose||"Not specified")+"</td>",g+="<td>"+v(L.expiry||"—")+"</td>",g+="</tr>"}g+="</tbody></table></div>"}}g+="</div>",e.innerHTML=g}}window.__ccInternal={getResourceSnapshot:ye,scriptLoaded:function(e){for(var t=ge||ye(),n=0;n<t.allUrls.length;n++)if(-1!==t.allUrls[n].indexOf(e))return!0;return!1},scriptLoadedUrls:function(e){for(var t=ge||ye(),n=[],o=0;o<t.allUrls.length;o++)-1!==t.allUrls[o].indexOf(e)&&n.push(t.allUrls[o]);return n},hasCookie:function(e){return document.cookie.split(";").some(function(t){return t.trim().split("=")[0]===e})},hasCookiePrefix:function(e){return document.cookie.split(";").some(function(t){return 0===t.trim().split("=")[0].indexOf(e)})},setResourceSnapshot:function(e){ge=e},facadeBridge:{getConfig:function(){return r},getConsentState:function(){return l},loadConsent:$,saveConsent:function(e,t){F(e,t)},hideAllBanners:ie,registerRenderer:function(e){R=e,M=2,V()}}},window.CookieConsent={getState:k,getConfig:function(){return r},getComplianceMode:function(){return p},getCountry:function(){return f},show:function(){re("gdpr")},acceptAll:se,declineAll:de,getGPC:function(){return i},getConsentVersion:function(){return r.consentVersion},on:function(e,t){window.addEventListener(e,t)},off:function(e,t){window.removeEventListener(e,t)},VERSION:c},window.addEventListener("cc:ready",pe),window.addEventListener("cc:update",pe),function(){if(!window.__ccDefaultsSet){var e={wait_for_update:500};r.cookieTypes.forEach(function(t){t.consentMode&&t.consentMode.forEach(function(n){e[n]=t.required?"granted":"denied"})}),x("consent","default",e)}}(),function(){if(r.tcfEnabled){var e=window.__tcfapi&&window.__tcfapi.queue?window.__tcfapi.queue:[];window.__tcfapi=C,e.forEach(function(e){C.apply(null,e)}),S=!0,window===window.top&&window.addEventListener("message",function(e){var t;try{t="string"==typeof e.data?JSON.parse(e.data):e.data}catch(e){return}if(t&&t.__tcfapiCall){var n=t.__tcfapiCall;C(n.command,n.version,function(t,o){var c={__tcfapiReturn:{returnValue:t,success:o,callId:n.callId}};e.source&&e.source.postMessage("string"==typeof e.data?JSON.stringify(c):c,"*")},n.parameter)}})}}();var fe=$();function me(){var e=window.__ccDiscovery&&window.__ccDiscovery.active;if(!e&&(window.__ccDNT||document.cookie.split(";").some(function(e){return 0===e.trim().indexOf("cookieflame_dnt=")})))return E(l=K()),z(l,Y()),J(),j(),p="dnt",te(),ne(),ie(),Z(l),_("cc:ready"),void pe();if(e){E(l=Y()),T(l),J(),H(l,null),r.tcfEnabled&&B(l),window.dataLayer=window.dataLayer||[];for(var t=["consent_accepted_analytics","consent_accepted_marketing","consent_accepted_preferences","consent_accepted_necessary","consent_update","consent_given","cookie_consent_given","cookie_consent_update","consent_accepted"],n=0;n<t.length;n++)window.dataLayer.push({event:t[n]});return p="discovery",te(),ne(),ie(),_("cc:ready"),_("cc:update"),void pe()}var o=$();if(o)if(i&&(o.marketing=!1),l=o,E(o),T(o),J(),j(),H(o,null),r.tcfEnabled&&B(o),te(),ne(),ie(),Z(o),o.cc){if("gdpr"===(p=Q(o.cc))){var c=document.getElementById("cc-icon");c&&c.classList.add("cc-show")}_("cc:ready"),pe()}else X(function(e){if(p=e,"gdpr"===e){var t=document.getElementById("cc-icon");t&&t.classList.add("cc-show")}_("cc:ready"),pe()});else X(function(e){if(p=e,"none"===e)return J(),F(Y(),"auto_grant_non_eu"),_("cc:ready"),_("cc:update"),void pe();if("ccpa"===e){if(J(),i){var t=Y();t.marketing=!1,F(t,"ccpa_gpc_optout")}else F(Y(),"ccpa_auto_grant");return te(),n=r.text,(o=document.createElement("div")).id="cc-ccpa-banner",o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true"),o.setAttribute("aria-label","Privacy notice"),o.setAttribute("tabindex","-1"),o.innerHTML='<div class="cc-ccpa-inner"><div class="cc-ccpa-text"><p>'+v(n.ccpaDescription)+'</p></div><div class="cc-ccpa-actions"><a href="'+v(r.ccpaUrl)+'" class="cc-ccpa-link">'+v(n.ccpaDnsmpiLink)+'</a><button class="cc-btn cc-btn-accept" id="cc-ccpa-ok">'+v(n.ccpaAcceptButton)+"</button></div></div>",document.body.appendChild(o),document.getElementById("cc-ccpa-ok").addEventListener("click",function(){F(Y(),"ccpa_acknowledge"),o.classList.remove("cc-show"),_("cc:update")}),re("ccpa"),_("cc:ready"),_("cc:update"),void pe()}var n,o;te(),J(),j(),ne(),re("gdpr"),_("cc:ready"),pe()})}fe&&(l=fe,E(fe)),function(){if(!g&&r.autoBlockPatterns&&r.autoBlockPatterns.length){g=!0;var e=document.createElement.bind(document),t=Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src");t&&t.set&&(document.createElement=function(){var n=e.apply(document,arguments);if("script"!==(arguments[0]||"").toLowerCase())return n;function o(e,t){if(t&&"string"==typeof t&&!e.getAttribute("data-cc")&&!e.getAttribute("data-cc-auto")&&-1===t.indexOf("cookieconsent")){var n=I(t);!n||l&&l[n]||(e.type="text/plain",e.setAttribute("data-cc",n),e.setAttribute("data-cc-auto","1"))}}Object.defineProperty(n,"src",{configurable:!0,enumerable:!0,get:function(){return t.get.call(this)},set:function(e){return o(this,e),t.set.call(this,e)}});var c=n.setAttribute.bind(n);return n.setAttribute=function(e,t){return"src"===e.toLowerCase()&&o(n,t),c(e,t)},n}),new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){var t=[];"SCRIPT"===e.tagName&&t.push(e),e.querySelectorAll&&e.querySelectorAll("script[src]").forEach(function(e){t.push(e)}),t.forEach(function(e){if(!(e.getAttribute("data-cc-auto")||e.getAttribute("data-cc")||e.src&&-1!==e.src.indexOf("cookieconsent"))){var t=I(e.src);t&&(l&&l[t]||(e.type="text/plain",e.setAttribute("data-cc",t),e.setAttribute("data-cc-auto","1")))}})}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}}(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",me):me();var ge=null;function ye(){for(var e=[],t=[],n=[],o={},c={},r=document.querySelectorAll("script[src]"),a=0;a<r.length;a++)r[a].src&&e.push(r[a].src);for(var i=document.querySelectorAll("iframe[src]"),s=0;s<i.length;s++)i[s].src&&e.push(i[s].src);if(window.performance&&performance.getEntriesByType)for(var d=performance.getEntriesByType("resource"),u=0;u<d.length;u++){var l=d[u].name||"";if(l){-1===e.indexOf(l)&&e.push(l);var p=d[u].initiatorType||"";if("script"===p||"iframe"===p||"xmlhttprequest"===p||"fetch"===p||-1!==l.indexOf(".js"))try{var f=new URL(l),m=f.hostname;if(m===location.hostname||m==="www."+location.hostname||"www."+m===location.hostname){var g=f.pathname.match(/\/wp-content\/plugins\/([^\/]+)\//);g&&!c[g[1]]&&(c[g[1]]=!0,n.push({slug:g[1],url:l}))}else o[m]||(o[m]=!0,t.push(m))}catch(e){}}}return{allUrls:e,thirdPartyDomains:t,pluginScripts:n}}var ve={};function he(e){var t={set_by:"",set_by_plugin:""},n=window.__ccCookieSetters;if(!n||!Object.prototype.hasOwnProperty.call(n,e)||!n[e])return t;try{var o=new URL(String(n[e]).replace(/:\d+(:\d+)?$/,"")),c=o.hostname;if(c===location.hostname||c==="www."+location.hostname||"www."+c===location.hostname){t.set_by="first-party";var r=o.pathname.match(/\/wp-content\/(?:plugins|themes)\/([^\/]+)\//);r&&(t.set_by_plugin=r[1].toLowerCase())}else t.set_by=c.toLowerCase()}catch(e){}return t}function we(){var t=window.__ccClassified||[],n=window.__ccUnclassified||[],o=window.__ccBeaconUrl;if(o){var c,r={};for(c=0;c<t.length;c++)r[t[c]]=!0;for(c=0;c<n.length;c++)r[n[c]]=!0;var a=Object.keys(ve);for(c=0;c<a.length;c++)r[a[c]]=!0;var i=Object.keys(s);for(c=0;c<i.length;c++)r[i[c]]=!0;var d={},u=[],l=document.cookie.split(";");for(c=0;c<l.length;c++){var p=l[c].indexOf("="),f=(p>-1?l[c].substring(0,p):l[c]).trim(),m=p>-1?l[c].substring(p+1).trim():"";f&&(u.push(f),d[f]=m)}var g=[];for(c=0;c<u.length;c++)if(!r[u[c]]){for(var y=!1,v=Object.keys(s),h=0;h<v.length;h++)if(s[v[h]].prefix&&0===u[c].indexOf(v[h])){y=!0;break}y||g.push(u[c])}if(0!==g.length){for(var w=ye(),b=w.thirdPartyDomains,k=[],_=0;_<w.pluginScripts.length;_++)k.push(w.pluginScripts[_].slug);for(var x=location.pathname,E=0;E<g.length;E++){var A=g[E],S=!!e[A]&&!r[A],L=be(d[A]||""),C=he(A),B=JSON.stringify({cookie_name:A,script_domains:b,plugin_scripts:k,page_path:x,pre_existing:S,value_shape:L,set_by:C.set_by,set_by_plugin:C.set_by_plugin});ve[A]=!0,navigator.sendBeacon&&navigator.sendBeacon(o,new Blob([B],{type:"application/json"}))}}}}function be(e){if(!e||0===e.length)return"empty";if("true"===e||"false"===e||"1"===e||"0"===e)return"boolean";if(/^\d+$/.test(e))return e.length>12?"long-numeric":"numeric";if(/^\d+\.\d+$/.test(e))return"decimal";if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return"uuid";if(/^[A-Za-z0-9+\/]{20,}={0,2}$/.test(e))return"base64";if(/^(GA\d+\.\d+\.\d+\.\d+|G-[A-Z0-9]+)/.test(e))return"ga-id";try{if("object"==typeof JSON.parse(decodeURIComponent(e)))return"json"}catch(e){}return/^[a-f0-9]{24,}$/i.test(e)?"hex-id":/^\d{10,13}$/.test(e)?"timestamp":e.length<=20?"short-string":e.length<=100?"medium-string":"long-string"}setTimeout(we,3e3),setTimeout(we,15e3),setTimeout(we,45e3),window.addEventListener("cc:update",function(){setTimeout(we,3e3)}),window.addEventListener("pagehide",we)}();19 !function(){"use strict";var e={};try{for(var t=document.cookie.split(";"),n=0;n<t.length;n++){var o=t[n].trim().split("=")[0];o&&(e[o]=!0)}}catch(e){}var c="5.3.0",r={cookieName:"cc_consent",cookieExpiry:365,privacyUrl:"/privacy-policy",ccpaUrl:"/privacy-policy#do-not-sell",geoApi:"",logEndpoint:"",reconsentDays:365,cspSafe:!1,tcfEnabled:!0,cmpId:1,cmpVersion:1,vendorListVersion:2,storageMethod:"cookie",cookieDomain:"",shareSubdomains:!1,theme:"light",showPoweredBy:!1,iconPosition:"left",consentVersion:"",autoBlockPatterns:[{pattern:"googletagmanager.com/gtag",category:"analytics"},{pattern:"google-analytics.com",category:"analytics"},{pattern:"analytics.google.com",category:"analytics"},{pattern:"hotjar.com",category:"analytics"},{pattern:"mixpanel.com",category:"analytics"},{pattern:"segment.com/analytics",category:"analytics"},{pattern:"segment.io",category:"analytics"},{pattern:"clarity.ms",category:"analytics"},{pattern:"plausible.io",category:"analytics"},{pattern:"js.hs-analytics.net",category:"analytics"},{pattern:"connect.facebook.net",category:"marketing"},{pattern:"snap.licdn.com",category:"marketing"},{pattern:"ads.linkedin.com",category:"marketing"},{pattern:"googleads.g.doubleclick.net",category:"marketing"},{pattern:"googlesyndication.com",category:"marketing"},{pattern:"googleadservices.com",category:"marketing"},{pattern:"ads-twitter.com",category:"marketing"},{pattern:"analytics.tiktok.com",category:"marketing"},{pattern:"pintrk",category:"marketing"},{pattern:"s.pinimg.com/ct",category:"marketing"},{pattern:"widget.intercom.io",category:"preferences"},{pattern:"js.intercomcdn.com",category:"preferences"}],regionRules:{gdpr:["AT","BE","BG","CY","CZ","DE","DK","EE","ES","FI","FR","GR","HR","HU","IE","IT","LT","LU","LV","MT","NL","PL","PT","RO","SE","SI","SK","IS","LI","NO","GB","GG","JE","IM","CH","BR","ZA"],ccpa:["US"]},text:{title:"We value your privacy",description:"We use cookies to improve your experience, analyse traffic and personalise content. You can choose which categories to allow.",acceptAllButton:"Accept All",declineAllButton:"Decline All",saveButton:"Save Preferences",showDetailsButton:"Manage preferences",hideDetailsButton:"Hide preferences",alwaysOnLabel:"(always on)",ccpaTitle:"Your Privacy Choices",ccpaDescription:"We use cookies and similar technologies. Under California law, you have the right to opt out of the sale or sharing of your personal information.",ccpaAcceptButton:"OK",ccpaDnsmpiLink:"Do Not Sell My Personal Information"},cookieTypes:[{id:"necessary",name:"Necessary",description:"Required for the site to function. Cannot be disabled.",required:!0,consentMode:["security_storage","functionality_storage"],tcfPurposes:[1],onAccept:function(){}},{id:"preferences",name:"Preferences",description:"Remember your settings and personalisation choices.",required:!1,defaultValue:!1,consentMode:["functionality_storage","personalization_storage"],tcfPurposes:[2,3],onAccept:function(){},onReject:function(){}},{id:"analytics",name:"Analytics",description:"Help us understand how visitors use the site.",required:!1,defaultValue:!1,consentMode:["analytics_storage"],tcfPurposes:[4,5,6],onAccept:function(){},onReject:function(){}},{id:"marketing",name:"Marketing",description:"Used to deliver relevant ads and track campaigns.",required:!1,defaultValue:!1,consentMode:["ad_storage","ad_user_data","ad_personalization"],tcfPurposes:[7,8,9,10],onAccept:function(){},onReject:function(){}}]};if(window.__ccConfig&&"object"==typeof window.__ccConfig){var a=window.__ccConfig;["cookieName","cookieExpiry","privacyUrl","ccpaUrl","geoApi","logEndpoint","reconsentDays","cspSafe","tcfEnabled","cmpId","cmpVersion","vendorListVersion","storageMethod","cookieDomain","shareSubdomains","theme","showPoweredBy","iconPosition","consentVersion"].forEach(function(e){void 0!==a[e]&&(r[e]=a[e])}),a.text&&"object"==typeof a.text&&Object.keys(a.text).forEach(function(e){r.text[e]=a.text[e]}),Array.isArray(a.cookieTypes)&&(r.cookieTypes=a.cookieTypes),Array.isArray(a.autoBlockPatterns)&&(r.autoBlockPatterns=a.autoBlockPatterns),a.regionRules&&(r.regionRules=a.regionRules)}window.__ccConsentVersion&&(r.consentVersion=window.__ccConsentVersion);var i=!!window.__ccGPC;window.__ccBlockRules&&Array.isArray(window.__ccBlockRules)&&window.__ccBlockRules.length&&(r.autoBlockPatterns=window.__ccBlockRules);var s={cc_consent:{vendor:"CookieFlame",category:"necessary",purpose:"Stores your consent preferences",expiry:"1 year"},cc_anon_id:{vendor:"CookieFlame",category:"necessary",purpose:"Anonymous ID for consent logging",expiry:"1 year"},cookieflame_dnt:{vendor:"CookieFlame",category:"necessary",purpose:"Do-not-track opt-out flag",expiry:"1 year"},PHPSESSID:{vendor:"PHP",category:"necessary",purpose:"Server-side session identifier",expiry:"Session"},wp_settings_:{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-":{vendor:"WordPress",category:"necessary",purpose:"Admin interface preferences",prefix:!0,expiry:"1 year"},"wp-settings-time-":{vendor:"WordPress",category:"necessary",purpose:"Admin settings timestamp",prefix:!0,expiry:"1 year"},wordpress_logged_in_:{vendor:"WordPress",category:"necessary",purpose:"Login session",prefix:!0,expiry:"Session"},wordpress_sec_:{vendor:"WordPress",category:"necessary",purpose:"Secure login session",prefix:!0,expiry:"Session"},wordpress_test_cookie:{vendor:"WordPress",category:"necessary",purpose:"Checks cookie support",expiry:"Session"},wp_lang:{vendor:"WordPress",category:"necessary",purpose:"Language preference",expiry:"Session"},woocommerce_cart_hash:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping cart contents",expiry:"Session"},woocommerce_items_in_cart:{vendor:"WooCommerce",category:"necessary",purpose:"Cart item count",expiry:"Session"},wp_woocommerce_session_:{vendor:"WooCommerce",category:"necessary",purpose:"Shopping session",prefix:!0,expiry:"2 days"},_ga:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors",expiry:"2 years"},_ga_:{vendor:"Google Analytics",category:"analytics",purpose:"Stores session state",prefix:!0,expiry:"2 years"},_gid:{vendor:"Google Analytics",category:"analytics",purpose:"Distinguishes visitors (24h)",expiry:"24 hours"},_gat:{vendor:"Google Analytics",category:"analytics",purpose:"Throttles request rate",expiry:"1 minute"},wp_wk_ga_untrack_:{vendor:"Google Analytics",category:"analytics",purpose:"GA opt-out flag",prefix:!0,expiry:"Persistent"},_gcl_au:{vendor:"Google Ads",category:"marketing",purpose:"Conversion linker",expiry:"90 days"},_gcl_aw:{vendor:"Google Ads",category:"marketing",purpose:"Stores ad click info",expiry:"90 days"},_gac_:{vendor:"Google Ads",category:"marketing",purpose:"Campaign information",prefix:!0,expiry:"90 days"},IDE:{vendor:"Google DoubleClick",category:"marketing",purpose:"Ad serving and frequency",expiry:"1 year"},test_cookie:{vendor:"Google DoubleClick",category:"marketing",purpose:"Checks cookie support",expiry:"15 minutes"},NID:{vendor:"Google",category:"preferences",purpose:"Stores preferences",expiry:"6 months"}},d=window.__ccCustomCookies||[];function u(e){for(var t=0;t<d.length;t++){var n=d[t];if("exact"===n.match&&e===n.name)return n;if("prefix"===n.match&&0===e.indexOf(n.name))return n;if("contains"===n.match&&-1!==e.indexOf(n.name))return n}var o=s[e];return o||(Object.keys(s).forEach(function(t){!o&&s[t].prefix&&0===e.indexOf(t)&&(o=s[t])}),o||null)}var l=null,p="none",f=null,m=null,g=!1,y=0;function v(e){return"string"!=typeof e&&(e=String(e)),e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function h(e){if("localStorage"===r.storageMethod)try{return localStorage.getItem(e)}catch(e){return null}var t=document.cookie.match(new RegExp("(?:^|;\\s*)"+e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"=([^;]*)"));if(!t)return null;try{return decodeURIComponent(t[1])}catch(e){return null}}function w(e,t,n){if("localStorage"!==r.storageMethod){var o=new Date;o.setTime(o.getTime()+864e5*n);var c=e+"="+encodeURIComponent(t)+";expires="+o.toUTCString()+";path=/;SameSite=Lax;Secure";r.cookieDomain&&(c+=";domain="+r.cookieDomain),document.cookie=c}else try{localStorage.setItem(e,t)}catch(e){}}function b(){if(m)return m;var e=h("cc_anon_id");return e?(m=e,e):(w("cc_anon_id",m="cc_"+function(){if("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID)try{return crypto.randomUUID()}catch(e){}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"===e?t:3&t|8).toString(16)})}(),730),m)}function k(){var e={timestamp:l?l.ts:null,complianceMode:p,country:f,gpc:i,consentVersion:r.consentVersion};return r.cookieTypes.forEach(function(t){e[t.id]=l?!!l[t.id]:!!t.required}),e}function _(e,t){window.dispatchEvent(new CustomEvent(e,{detail:t||k()}))}function x(){window.dataLayer=window.dataLayer||[],window.dataLayer.push(arguments)}function E(e){var t={};r.cookieTypes.forEach(function(n){n.consentMode&&n.consentMode.forEach(function(o){t[o]=e[n.id]?"granted":"denied"})}),i&&(t.ad_storage="denied",t.ad_user_data="denied",t.ad_personalization="denied"),x("consent","update",t)}var A=new Map,S=!1;function L(e){var t={};return r.cookieTypes.forEach(function(n){n.tcfPurposes&&n.tcfPurposes.forEach(function(o){t[o]=!!e[n.id]})}),{tcString:"",tcfPolicyVersion:4,cmpId:r.cmpId,cmpVersion:r.cmpVersion,gdprApplies:"gdpr"===p,eventStatus:"useractioncomplete",cmpStatus:"loaded",listenerId:void 0,isServiceSpecific:!0,useNonStandardTexts:!1,publisherCC:"GB",purposeOneTreatment:!1,purpose:{consents:t,legitimateInterests:{}},vendor:{consents:{},legitimateInterests:{}},specialFeatureOptins:{},publisher:{consents:{},legitimateInterests:{},customPurpose:{consents:{},legitimateInterests:{}},restrictions:{}}}}function C(e,t,n,o){if("function"==typeof n)if("addEventListener"===e){var c=++y;if(A.set(c,n),l){var a=L(l);a.listenerId=c,n(a,!0)}}else"removeEventListener"===e?n({listenerId:o},A.delete(o)):"getTCData"===e?n(l?L(l):null,!!l):"ping"===e?n({gdprApplies:"gdpr"===p,cmpLoaded:S,cmpStatus:S?"loaded":"stub",displayStatus:"hidden",apiVersion:"2.2",cmpVersion:r.cmpVersion,cmpId:r.cmpId,gvlVersion:r.vendorListVersion,tcfPolicyVersion:4},!0):n(null,!1)}function B(e){A.forEach(function(t,n){var o=L(e);o.listenerId=n;try{t(o,!0)}catch(e){}})}function I(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<r.autoBlockPatterns.length;n++){var o=r.autoBlockPatterns[n];if(o.pattern instanceof RegExp){if(o.pattern.test(t))return o.category}else if(-1!==t.indexOf(o.pattern.toLowerCase()))return o.category}return null}function T(e){document.querySelectorAll('script[type="text/plain"][data-cc]').forEach(function(t){var n=(t.getAttribute("data-cc")||"").toLowerCase();if(e[n]&&!t.getAttribute("data-cc-activated")){t.setAttribute("data-cc-activated","1");var o=document.createElement("script");o.isWPRocket=!0,Array.from(t.attributes).forEach(function(e){"type"!==e.name&&"data-cc"!==e.name&&"data-cc-activated"!==e.name&&"data-cc-auto"!==e.name&&o.setAttribute(e.name,e.value)}),!t.src&&t.textContent&&(o.textContent=t.textContent),t.parentNode.insertBefore(o,t.nextSibling),t.parentNode.removeChild(t)}}),["img","iframe","link"].forEach(function(t){document.querySelectorAll(t+"[data-cc][data-cc-src]").forEach(function(n){var o=(n.getAttribute("data-cc")||"").toLowerCase();e[o]&&!n.getAttribute("data-cc-activated")&&(n.setAttribute("data-cc-activated","1"),"link"===t?n.href=n.getAttribute("data-cc-src"):n.src=n.getAttribute("data-cc-src"))})})}var O=[{pattern:"youtube.com",category:"marketing"},{pattern:"youtube-nocookie.com",category:"marketing"},{pattern:"youtu.be",category:"marketing"},{pattern:"player.vimeo.com",category:"marketing"},{pattern:"vimeo.com",category:"marketing"},{pattern:"dailymotion.com",category:"marketing"},{pattern:"open.spotify.com",category:"preferences"},{pattern:"soundcloud.com",category:"preferences"},{pattern:"google.com/maps",category:"preferences"},{pattern:"maps.google.com",category:"preferences"},{pattern:"facebook.com/plugins",category:"marketing"},{pattern:"instagram.com",category:"marketing"},{pattern:"tiktok.com/embed",category:"marketing"},{pattern:"twitter.com",category:"marketing"},{pattern:"x.com",category:"marketing"}];function D(){return!(!document.body||!(document.body.classList.contains("elementor-editor-active")||document.body.classList.contains("fl-builder-edit")||document.body.classList.contains("et-fb-root-ancestor")))}var P=[],M=0,R=null,q=!1;function V(){if(R&&P.length){var e=P;P=[];try{R(e)}catch(e){}}}function N(){0!==P.length&&(2!==M?1!==M&&3!==M&&(M=1,function(){var e=window.__ccConfig&&window.__ccConfig.facadesUrl||null;if(!e)return void(M=3);var t=document.createElement("script");t.src=e,t.async=!0,t.onload=function(){M=2,V()},t.onerror=function(){M=3},(document.head||document.documentElement).appendChild(t)}()):V())}function U(e){var t=e.src||e.getAttribute("data-src")||"";if(t&&!e.getAttribute("data-cc-facade")&&!D()){var n=function(e){if(!e)return null;for(var t=e.toLowerCase(),n=0;n<O.length;n++)if(-1!==t.indexOf(O[n].pattern))return O[n].category;return null}(t);if(n){var o=l||Z();o&&o[n]||(e.setAttribute("data-cc-facade","1"),e.setAttribute("data-cc-iframe-cat",n),e.setAttribute("data-cc-original-src",t),e.removeAttribute("src"),e.style.display="none",P.push({type:"iframe",node:e,category:n,src:t}),N())}}}function G(e){if(!e.getAttribute("data-cc-facade")&&!D()){var t=e.getAttribute("data-settings");if(t){var n;try{n=JSON.parse(t)}catch(e){return}var o=n.youtube_url||n.vimeo_url||"";if(o){var c=o.toLowerCase(),r=null;if((-1!==c.indexOf("youtube")||-1!==c.indexOf("youtu.be")||-1!==c.indexOf("vimeo")||-1!==c.indexOf("dailymotion"))&&(r="marketing"),r&&(!l||!l[r])){if(!l){var a=Z();if(a&&a[r])return}e.setAttribute("data-cc-facade","1"),q=!0,P.push({type:"elementor",node:e,category:r,url:o}),N()}}}}}function j(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++)U(e[t]);for(var n=document.querySelectorAll(".elementor-widget-video"),o=0;o<n.length;o++)G(n[o]);for(var c=document.querySelectorAll(".wp-block-embed__wrapper iframe[src]"),r=0;r<c.length;r++)U(c[r])}function J(){new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){if("IFRAME"===e.tagName&&U(e),e.querySelectorAll){for(var t=e.querySelectorAll("iframe[src]"),n=0;n<t.length;n++)U(t[n]);for(var o=e.querySelectorAll(".elementor-widget-video"),c=0;c<o.length;c++)G(o[c])}e.classList&&e.classList.contains("elementor-widget-video")&&G(e)}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}function W(){for(var e=document.querySelectorAll("iframe[src]"),t=0;t<e.length;t++){var n=e[t];if(!n.getAttribute("data-cc-facade")){var o=n.src||"";if(o)for(var c=0;c<O.length;c++)if(-1!==o.indexOf(O[c].pattern)){n.src=o;break}}}}function H(e,t){r.cookieTypes.forEach(function(n){var o=!!e[n.id];if((t?!!t[n.id]:null)!==o||null===t)if(o&&"function"==typeof n.onAccept)try{n.onAccept()}catch(e){console.warn("[CookieConsent] onAccept error for "+n.id,e)}else if(!o&&"function"==typeof n.onReject)try{n.onReject()}catch(e){console.warn("[CookieConsent] onReject error for "+n.id,e)}})}function F(e,t){var n=l;if(l=e,w(r.cookieName,JSON.stringify(e),r.cookieExpiry),E(e),q&&t)for(var o=document.querySelectorAll(".cc-iframe-facade[data-cc-elementor-widget]"),a=0;a<o.length;a++){var s=o[a].getAttribute("data-cc-iframe-cat");if(s&&e[s])return void window.location.reload()}K(e,n),T(e),function(e){for(var t=document.querySelectorAll(".cc-iframe-facade"),n=0;n<t.length;n++)if(!t[n].getAttribute("data-cc-elementor-widget")&&e[t[n].getAttribute("data-cc-iframe-cat")]){var o=t[n].nextElementSibling;if(o&&"IFRAME"===o.tagName&&o.getAttribute("data-cc-facade")){var c=o.getAttribute("data-cc-original-src");c&&(o.src=c,o.style.display="",o.removeAttribute("data-cc-facade"))}t[n].parentNode.removeChild(t[n])}}(e),t&&"auto_grant_non_eu"!==t&&"ccpa_auto_grant"!==t&&setTimeout(W,300),H(e,n),$(e),r.tcfEnabled&&B(e),t&&function(e,t){if(r.logEndpoint){var n={};r.cookieTypes.forEach(function(e){n[e.id]=!!t[e.id]});var o={anonymousId:b(),timestamp:(new Date).toISOString(),action:e,consent:n,complianceMode:p,country:f,url:location.href,userAgent:navigator.userAgent,tcfEnabled:r.tcfEnabled,gpc:i,consentVersion:r.consentVersion,version:c};try{var a=JSON.stringify(o);navigator.sendBeacon?navigator.sendBeacon(r.logEndpoint,new Blob([a],{type:"application/json"})):fetch(r.logEndpoint,{method:"POST",body:a,headers:{"Content-Type":"application/json"},keepalive:!0})}catch(e){}}}(t,e)}function $(e){r.cookieTypes.forEach(function(t){if(!t.required){var n=document.getElementById("cc-cb-"+t.id);n&&(n.checked=!!e[t.id])}});var t=document.getElementById("cc-cats"),n=document.getElementById("cc-details"),o=document.getElementById("cc-pref-buttons");t&&t.classList.remove("cc-open"),n&&(n.textContent=r.text.showDetailsButton),o&&o.classList.remove("cc-open")}function Z(){var e=h(r.cookieName);if(!e)return null;try{var t=JSON.parse(e);return!t||"object"!=typeof t||Array.isArray(t)||(!t.ts||isNaN(new Date(t.ts).getTime())||(Date.now()-new Date(t.ts).getTime())/864e5>r.reconsentDays||r.consentVersion&&t.cv!==r.consentVersion)?null:t}catch(e){return null}}function Y(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!0}),e}function z(){var e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f};return r.cookieTypes.forEach(function(t){e[t.id]=!!t.required}),e}function K(e,t){if(t){var n=[];if(r.cookieTypes.forEach(function(o){o.required||t[o.id]&&!e[o.id]&&n.push(o.id)}),n.length)document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean).forEach(function(e){var t=u(e);if(t&&-1!==n.indexOf(t.category)){var o=location.hostname,c="."+o;document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT",document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+c,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+o,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; Secure",r.cookieDomain&&(document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+r.cookieDomain+"; Secure");var a=o.split(".");if(a.length>2){var i="."+a.slice(1).join(".");document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i,document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain="+i+"; Secure"}}})}}function Q(e){return(f=e?e.toUpperCase():null)?r.regionRules.gdpr&&-1!==r.regionRules.gdpr.indexOf(f)?"gdpr":r.regionRules.ccpa&&-1!==r.regionRules.ccpa.indexOf(f)?"ccpa":"none":"gdpr"}function X(e){if(window.__ccGeo)return e(Q(window.__ccGeo));r.geoApi?fetch(r.geoApi).then(function(e){return e.json()}).then(function(t){var n=t.country_code||t.country||"";n?e(Q(n)):ee(e)}).catch(function(){ee(e)}):ee(e)}function ee(e){var t="";try{t=Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch(e){}return 0===t.indexOf("Europe/")||"Atlantic/Reykjavik"===t?(f=null,e("gdpr")):0===t.indexOf("US/")||0===t.indexOf("America/")&&["New_York","Chicago","Denver","Los_Angeles","Phoenix","Anchorage","Boise","Detroit","Indianapolis","Louisville","Menominee","Nome","Adak","Juneau","Sitka","Yakutat","Metlakatla","Kentucky","Indiana","North_Dakota"].some(function(e){return-1!==t.indexOf(e)})||"Pacific/Honolulu"===t?(f="US",e("ccpa")):(f=null,void e("gdpr"))}function te(){"dark"===r.theme&&document.documentElement.classList.add("cc-dark"),"right"===r.iconPosition&&document.documentElement.classList.add("cc-icon-right")}function ne(){var e=r.text,t=document.createElement("div");t.id="cc-overlay",document.body.appendChild(t);var n=document.createElement("div");n.id="cc-banner",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-label","Cookie consent"),n.setAttribute("tabindex","-1");var o=r.cookieTypes.map(function(t){var n=t.required?' <span class="cc-always-on">'+v(e.alwaysOnLabel)+"</span>":"";return'<div class="cc-cat"><div><div class="cc-cat-label">'+v(t.name)+n+'</div><div class="cc-cat-desc">'+v(t.description||"")+'</div></div><label class="cc-toggle"><input type="checkbox" id="cc-cb-'+v(t.id)+'" aria-label="'+v(t.name)+'"'+(t.required||t.defaultValue?" checked":"")+(t.required?" disabled":"")+'><span class="cc-slider"></span></label></div>'}).join("");n.innerHTML='<div class="cc-inner"><p class="cc-title">'+v(e.title)+'</p><p class="cc-text">'+v(e.description)+' <a href="'+v(r.privacyUrl)+'">Privacy Policy</a></p><div class="cc-buttons"><button class="cc-btn cc-btn-accept" id="cc-accept">'+v(e.acceptAllButton)+'</button><button class="cc-btn cc-btn-details" id="cc-details" aria-expanded="false">'+v(e.showDetailsButton)+'</button></div><div class="cc-categories" id="cc-cats">'+o+'</div><div class="cc-pref-buttons" id="cc-pref-buttons"><button class="cc-btn cc-btn-save" id="cc-save">'+v(e.saveButton)+'</button><button class="cc-btn cc-btn-decline" id="cc-decline">'+v(e.declineAllButton)+"</button></div></div>"+(r.showPoweredBy?'<div class="cc-powered"><a href="https://www.cookieflame.com" target="_blank" rel="noopener">Powered by CookieFlame</a></div>':""),document.body.appendChild(n);var c=document.createElement("button");c.id="cc-icon",c.setAttribute("aria-label","Cookie settings"),c.innerHTML='<svg width="24" height="24" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M19.1 1.16c-.06-.42-.38-.77-.8-.83A11.8 11.8 0 0 0 13.28 1.2L7.5 4.3A11.8 11.8 0 0 0 3.95 7.98L1.09 13.9A11.8 11.8 0 0 0 .38 18.96l1.13 6.47a11.8 11.8 0 0 0 3.53 4.99l4.71 4.56a11.8 11.8 0 0 0 4.59 2.24l6.48.91a11.8 11.8 0 0 0 5.52-.89l5.78-3.09a11.8 11.8 0 0 0 3.55-3.69l2.87-5.9a11.8 11.8 0 0 0 .71-5.08c-.07-.41-.42-.73-.83-.79a14.8 14.8 0 0 1-8.16-7.61c-.14-.59-.63-1.05-1.23-1.14A14.8 14.8 0 0 1 19.1 1.16ZM15.25 10.25a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Zm-5 15a2.5 2.5 0 1 1 5 0 2.5 2.5 0 0 1-5 0Zm17.5-5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z" fill="currentColor"/></svg>',document.body.appendChild(c),document.getElementById("cc-accept").addEventListener("click",se),document.getElementById("cc-decline").addEventListener("click",de),document.getElementById("cc-save").addEventListener("click",ue),document.getElementById("cc-details").addEventListener("click",le),c.addEventListener("click",function(){re("gdpr")})}var oe=null;function ce(e){if("Tab"===e.key){var t=document.getElementById("cc-banner")||document.getElementById("cc-ccpa-banner");if(t&&t.classList.contains("cc-show")){for(var n=[],o=t.querySelectorAll('button, a[href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])'),c=0;c<o.length;c++){for(var r=o[c],a=!1,i=r.parentElement;i&&i!==t;){if(i.style&&"none"===window.getComputedStyle(i).display){a=!0;break}i=i.parentElement}a||n.push(r)}if(0!==n.length){var s=n[0],d=n[n.length-1];e.shiftKey?document.activeElement===s&&(e.preventDefault(),d.focus()):document.activeElement===d&&(e.preventDefault(),s.focus())}}}}function re(e){"ccpa"!==e?(oe=document.activeElement,requestAnimationFrame(function(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.add("cc-show"),t){t.classList.add("cc-show");var o=t.querySelector(".cc-btn-accept");o&&o.focus(),document.addEventListener("keydown",ce)}n&&n.classList.remove("cc-show")})):requestAnimationFrame(function(){var e=document.getElementById("cc-ccpa-banner");e&&(e.classList.add("cc-show"),oe=document.activeElement,e.focus(),document.addEventListener("keydown",ce))})}function ae(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");if(e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&"gdpr"===p&&n.classList.add("cc-show"),document.removeEventListener("keydown",ce),oe&&"function"==typeof oe.focus)try{oe.focus()}catch(e){}oe=null}function ie(){var e=document.getElementById("cc-overlay"),t=document.getElementById("cc-banner"),n=document.getElementById("cc-icon");e&&e.classList.remove("cc-show"),t&&t.classList.remove("cc-show"),n&&n.classList.remove("cc-show"),document.removeEventListener("keydown",ce)}function se(){F(Y(),"accept_all"),ae(),_("cc:accept-all"),_("cc:update")}function de(){F(z(),"decline_all"),ae(),_("cc:decline-all"),_("cc:update")}function ue(){var e;F((e={ts:(new Date).toISOString(),cv:r.consentVersion,cc:f},r.cookieTypes.forEach(function(t){if(t.required)e[t.id]=!0;else{var n=document.getElementById("cc-cb-"+t.id);e[t.id]=!!n&&n.checked}}),e),"save_preferences"),ae(),_("cc:save"),_("cc:update")}function le(){var e=document.getElementById("cc-cats"),t=document.getElementById("cc-details"),n=document.getElementById("cc-pref-buttons"),o=e.classList.toggle("cc-open");t.textContent=o?r.text.hideDetailsButton:r.text.showDetailsButton,t.setAttribute("aria-expanded",o?"true":"false"),n&&(o?n.classList.add("cc-open"):n.classList.remove("cc-open"))}function pe(){var e=document.getElementById("cc-declaration");if(e){for(var t=k(),n={},o=document.cookie.split(";").map(function(e){return e.trim().split("=")[0]}).filter(Boolean),c=0;c<o.length;c++){var a=u(o[c]);a&&(n[o[c]]={name:o[c],vendor:a.vendor,category:a.category,purpose:a.purpose,expiry:a.expiry||"",active:!0})}for(var i=0;i<d.length;i++){var s=d[i];s.name&&s.vendor&&s.category&&"unclassified"!==s.category&&!n[s.name]&&(n[s.name]={name:s.name,vendor:s.vendor,category:s.category,purpose:s.purpose||"",expiry:s.expiry||"",active:!1})}for(var l=0;l<o.length;l++)n[o[l]]||(n[o[l]]={name:o[l],vendor:"",category:"unclassified",purpose:"",expiry:"",active:!0});var p=["necessary","preferences","analytics","marketing"],f={};r.cookieTypes.forEach(function(e){f[e.id]=e.name});var m={};p.forEach(function(e){m[e]=[]}),Object.keys(n).forEach(function(e){var t=n[e],o=t.category;m[o]||(m[o]=[]),m[o].push(t)}),p.forEach(function(e){m[e]&&m[e].sort(function(e,t){return e.name.localeCompare(t.name)})});var g="<div>";if(t.timestamp){var y=new Date(t.timestamp);g+="<p>"+v("Your consent was last updated on "+y.toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"})+" at "+y.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})+".")+"</p>"}else g+="<p>"+v("You have not yet made a cookie preference choice on this site.")+"</p>";for(var h=0;h<p.length;h++){var w=p[h],b=m[w];if(b&&b.length){var _,x=f[w]||w,E=r.cookieTypes.filter(function(e){return e.id===w})[0],A=E&&E.description||"";_=!!E&&E.required?"Always active":t[w]?"Active":"Inactive",g+="<div>",g+="<p><b>"+v(x)+"</b> ("+v(_)+")</p>",A&&(g+="<p>"+v(A)+"</p>"),g+="<table><thead><tr>",g+="<th>Name</th><th>Provider</th><th>Purpose</th><th>Expiry</th>",g+="</tr></thead><tbody>";for(var S=0;S<b.length;S++){var L=b[S];g+="<tr>",g+="<td><code>"+v(L.name)+"</code></td>",g+="<td>"+v(L.vendor||"Unknown")+"</td>",g+="<td>"+v(L.purpose||"Not specified")+"</td>",g+="<td>"+v(L.expiry||"—")+"</td>",g+="</tr>"}g+="</tbody></table></div>"}}g+="</div>",e.innerHTML=g}}window.__ccInternal={getResourceSnapshot:ye,scriptLoaded:function(e){for(var t=ge||ye(),n=0;n<t.allUrls.length;n++)if(-1!==t.allUrls[n].indexOf(e))return!0;return!1},scriptLoadedUrls:function(e){for(var t=ge||ye(),n=[],o=0;o<t.allUrls.length;o++)-1!==t.allUrls[o].indexOf(e)&&n.push(t.allUrls[o]);return n},hasCookie:function(e){return document.cookie.split(";").some(function(t){return t.trim().split("=")[0]===e})},hasCookiePrefix:function(e){return document.cookie.split(";").some(function(t){return 0===t.trim().split("=")[0].indexOf(e)})},setResourceSnapshot:function(e){ge=e},visitorCookies:function(e){for(var t=ye().thirdPartyDomains,n={},o=0;o<e.length;o++)we(e[o],t,he(e[o]))&&(n[e[o]]=!0);return n},facadeBridge:{getConfig:function(){return r},getConsentState:function(){return l},loadConsent:Z,saveConsent:function(e,t){F(e,t)},hideAllBanners:ie,registerRenderer:function(e){R=e,M=2,V()}}},window.CookieConsent={getState:k,getConfig:function(){return r},getComplianceMode:function(){return p},getCountry:function(){return f},show:function(){re("gdpr")},acceptAll:se,declineAll:de,getGPC:function(){return i},getConsentVersion:function(){return r.consentVersion},on:function(e,t){window.addEventListener(e,t)},off:function(e,t){window.removeEventListener(e,t)},VERSION:c},window.addEventListener("cc:ready",pe),window.addEventListener("cc:update",pe),function(){if(!window.__ccDefaultsSet){var e={wait_for_update:500};r.cookieTypes.forEach(function(t){t.consentMode&&t.consentMode.forEach(function(n){e[n]=t.required?"granted":"denied"})}),x("consent","default",e)}}(),function(){if(r.tcfEnabled){var e=window.__tcfapi&&window.__tcfapi.queue?window.__tcfapi.queue:[];window.__tcfapi=C,e.forEach(function(e){C.apply(null,e)}),S=!0,window===window.top&&window.addEventListener("message",function(e){var t;try{t="string"==typeof e.data?JSON.parse(e.data):e.data}catch(e){return}if(t&&t.__tcfapiCall){var n=t.__tcfapiCall;C(n.command,n.version,function(t,o){var c={__tcfapiReturn:{returnValue:t,success:o,callId:n.callId}};e.source&&e.source.postMessage("string"==typeof e.data?JSON.stringify(c):c,"*")},n.parameter)}})}}();var fe=Z();function me(){var e=window.__ccDiscovery&&window.__ccDiscovery.active;if(!e&&(window.__ccDNT||document.cookie.split(";").some(function(e){return 0===e.trim().indexOf("cookieflame_dnt=")})))return E(l=z()),K(l,Y()),J(),j(),p="dnt",te(),ne(),ie(),$(l),_("cc:ready"),void pe();if(e){E(l=Y()),T(l),J(),H(l,null),r.tcfEnabled&&B(l),window.dataLayer=window.dataLayer||[];for(var t=["consent_accepted_analytics","consent_accepted_marketing","consent_accepted_preferences","consent_accepted_necessary","consent_update","consent_given","cookie_consent_given","cookie_consent_update","consent_accepted"],n=0;n<t.length;n++)window.dataLayer.push({event:t[n]});return p="discovery",te(),ne(),ie(),_("cc:ready"),_("cc:update"),void pe()}var o=Z();if(o)if(i&&(o.marketing=!1),l=o,E(o),T(o),J(),j(),H(o,null),r.tcfEnabled&&B(o),te(),ne(),ie(),$(o),o.cc){if("gdpr"===(p=Q(o.cc))){var c=document.getElementById("cc-icon");c&&c.classList.add("cc-show")}_("cc:ready"),pe()}else X(function(e){if(p=e,"gdpr"===e){var t=document.getElementById("cc-icon");t&&t.classList.add("cc-show")}_("cc:ready"),pe()});else X(function(e){if(p=e,"none"===e)return J(),F(Y(),"auto_grant_non_eu"),_("cc:ready"),_("cc:update"),void pe();if("ccpa"===e){if(J(),i){var t=Y();t.marketing=!1,F(t,"ccpa_gpc_optout")}else F(Y(),"ccpa_auto_grant");return te(),n=r.text,(o=document.createElement("div")).id="cc-ccpa-banner",o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true"),o.setAttribute("aria-label","Privacy notice"),o.setAttribute("tabindex","-1"),o.innerHTML='<div class="cc-ccpa-inner"><div class="cc-ccpa-text"><p>'+v(n.ccpaDescription)+'</p></div><div class="cc-ccpa-actions"><a href="'+v(r.ccpaUrl)+'" class="cc-ccpa-link">'+v(n.ccpaDnsmpiLink)+'</a><button class="cc-btn cc-btn-accept" id="cc-ccpa-ok">'+v(n.ccpaAcceptButton)+"</button></div></div>",document.body.appendChild(o),document.getElementById("cc-ccpa-ok").addEventListener("click",function(){F(Y(),"ccpa_acknowledge"),o.classList.remove("cc-show"),_("cc:update")}),re("ccpa"),_("cc:ready"),_("cc:update"),void pe()}var n,o;te(),J(),j(),ne(),re("gdpr"),_("cc:ready"),pe()})}fe&&(l=fe,E(fe)),function(){if(!g&&r.autoBlockPatterns&&r.autoBlockPatterns.length){g=!0;var e=document.createElement.bind(document),t=Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype,"src");t&&t.set&&(document.createElement=function(){var n=e.apply(document,arguments);if("script"!==(arguments[0]||"").toLowerCase())return n;function o(e,t){if(t&&"string"==typeof t&&!e.getAttribute("data-cc")&&!e.getAttribute("data-cc-auto")&&-1===t.indexOf("cookieconsent")){var n=I(t);!n||l&&l[n]||(e.type="text/plain",e.setAttribute("data-cc",n),e.setAttribute("data-cc-auto","1"))}}Object.defineProperty(n,"src",{configurable:!0,enumerable:!0,get:function(){return t.get.call(this)},set:function(e){return o(this,e),t.set.call(this,e)}});var c=n.setAttribute.bind(n);return n.setAttribute=function(e,t){return"src"===e.toLowerCase()&&o(n,t),c(e,t)},n}),new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){if(1===e.nodeType){var t=[];"SCRIPT"===e.tagName&&t.push(e),e.querySelectorAll&&e.querySelectorAll("script[src]").forEach(function(e){t.push(e)}),t.forEach(function(e){if(!(e.getAttribute("data-cc-auto")||e.getAttribute("data-cc")||e.src&&-1!==e.src.indexOf("cookieconsent"))){var t=I(e.src);t&&(l&&l[t]||(e.type="text/plain",e.setAttribute("data-cc",t),e.setAttribute("data-cc-auto","1")))}})}})})}).observe(document.documentElement,{childList:!0,subtree:!0})}}(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",me):me();var ge=null;function ye(){for(var e=[],t=[],n=[],o={},c={},r=document.querySelectorAll("script[src]"),a=0;a<r.length;a++)r[a].src&&e.push(r[a].src);for(var i=document.querySelectorAll("iframe[src]"),s=0;s<i.length;s++)i[s].src&&e.push(i[s].src);if(window.performance&&performance.getEntriesByType)for(var d=performance.getEntriesByType("resource"),u=0;u<d.length;u++){var l=d[u].name||"";if(l){-1===e.indexOf(l)&&e.push(l);var p=d[u].initiatorType||"";if("script"===p||"iframe"===p||"xmlhttprequest"===p||"fetch"===p||-1!==l.indexOf(".js"))try{var f=new URL(l),m=f.hostname;if(m===location.hostname||m==="www."+location.hostname||"www."+m===location.hostname){var g=f.pathname.match(/\/wp-content\/plugins\/([^\/]+)\//);g&&!c[g[1]]&&(c[g[1]]=!0,n.push({slug:g[1],url:l}))}else o[m]||(o[m]=!0,t.push(m))}catch(e){}}}return{allUrls:e,thirdPartyDomains:t,pluginScripts:n}}var ve={};function he(e){var t={set_by:"",set_by_plugin:""},n=window.__ccCookieSetters;if(!n||!Object.prototype.hasOwnProperty.call(n,e)||!n[e])return t;try{var o=new URL(String(n[e]).replace(/:\d+(:\d+)?$/,""));if(/^(chrome-extension|moz-extension|safari-web-extension|safari-extension):$/.test(o.protocol))return t.set_by="browser-extension",t;var c=o.hostname;if(c===location.hostname||c==="www."+location.hostname||"www."+c===location.hostname){t.set_by="first-party";var r=o.pathname.match(/\/wp-content\/(?:plugins|themes)\/([^\/]+)\//);r&&(t.set_by_plugin=r[1].toLowerCase())}else t.set_by=c.toLowerCase()}catch(e){}return t}function we(e,t,n){if("browser-extension"===n.set_by)return!0;var o=window.__ccVisitorCookieRules;if(!o||!o.tools)return!1;if(o.allow&&-1!==o.allow.indexOf(e))return!1;if(n.set_by)return!1;for(var c=0;c<o.tools.length;c++){for(var r=o.tools[c],a=-1!==(r.n||[]).indexOf(e),i=0;!a&&i<(r.p||[]).length;i++)0===e.indexOf(r.p[i])&&(a=!0);if(a){for(var s=0;s<t.length;s++)for(var d=0;d<(r.d||[]).length;d++){var u=String(t[s]).toLowerCase(),l=r.d[d];if(u===l||u.slice(-l.length-1)==="."+l)return!1}return!0}}return!1}function be(){var t=window.__ccClassified||[],n=window.__ccUnclassified||[],o=window.__ccBeaconUrl;if(o){var c,r={};for(c=0;c<t.length;c++)r[t[c]]=!0;for(c=0;c<n.length;c++)r[n[c]]=!0;var a=Object.keys(ve);for(c=0;c<a.length;c++)r[a[c]]=!0;var i=Object.keys(s);for(c=0;c<i.length;c++)r[i[c]]=!0;var d={},u=[],l=document.cookie.split(";");for(c=0;c<l.length;c++){var p=l[c].indexOf("="),f=(p>-1?l[c].substring(0,p):l[c]).trim(),m=p>-1?l[c].substring(p+1).trim():"";f&&(u.push(f),d[f]=m)}var g=[];for(c=0;c<u.length;c++)if(!r[u[c]]){for(var y=!1,v=Object.keys(s),h=0;h<v.length;h++)if(s[v[h]].prefix&&0===u[c].indexOf(v[h])){y=!0;break}y||g.push(u[c])}if(0!==g.length){for(var w=ye(),b=w.thirdPartyDomains,k=[],_=0;_<w.pluginScripts.length;_++)k.push(w.pluginScripts[_].slug);for(var x=location.pathname,E=0;E<g.length;E++){var A=g[E],S=!!e[A]&&!r[A],L=ke(d[A]||""),C=he(A);if(!we(A,b,C)||window.__ccDiscovery&&window.__ccDiscovery.active){var B=JSON.stringify({cookie_name:A,script_domains:b,plugin_scripts:k,page_path:x,pre_existing:S,value_shape:L,set_by:C.set_by,set_by_plugin:C.set_by_plugin});ve[A]=!0,navigator.sendBeacon&&navigator.sendBeacon(o,new Blob([B],{type:"application/json"}))}else ve[A]=!0}}}}function ke(e){if(!e||0===e.length)return"empty";if("true"===e||"false"===e||"1"===e||"0"===e)return"boolean";if(/^\d+$/.test(e))return e.length>12?"long-numeric":"numeric";if(/^\d+\.\d+$/.test(e))return"decimal";if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e))return"uuid";if(/^[A-Za-z0-9+\/]{20,}={0,2}$/.test(e))return"base64";if(/^(GA\d+\.\d+\.\d+\.\d+|G-[A-Z0-9]+)/.test(e))return"ga-id";try{if("object"==typeof JSON.parse(decodeURIComponent(e)))return"json"}catch(e){}return/^[a-f0-9]{24,}$/i.test(e)?"hex-id":/^\d{10,13}$/.test(e)?"timestamp":e.length<=20?"short-string":e.length<=100?"medium-string":"long-string"}setTimeout(be,3e3),setTimeout(be,15e3),setTimeout(be,45e3),window.addEventListener("cc:update",function(){setTimeout(be,3e3)}),window.addEventListener("pagehide",be)}(); -
cookieflame/trunk/cookieflame.php
r3768250 r3769546 4 4 * Plugin URI: https://cookieflame.com 5 5 * Description: A lightweight, self-hosted cookie consent manager with Google Consent Mode v2, IAB TCF v2.2, automatic script blocking, multi-region compliance (GDPR/CCPA/LGPD/POPIA), passive cookie monitoring, and server-side geo detection via Cloudflare. 6 * Version: 5. 2.06 * Version: 5.3.0 7 7 * Requires at least: 6.0 8 8 * Requires PHP: 8.0 … … 19 19 } 20 20 21 define( 'COOKIEFLAME_VERSION', '5. 2.0' );21 define( 'COOKIEFLAME_VERSION', '5.3.0' ); 22 22 define( 'COOKIEFLAME_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 23 23 define( 'COOKIEFLAME_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); … … 219 219 // cookieconsent-discovery.js via the cookieflameAdmin global. 220 220 require_once COOKIEFLAME_PLUGIN_DIR . 'includes/service-detectors.php'; 221 require_once COOKIEFLAME_PLUGIN_DIR . 'includes/consent-tools.php'; 221 222 222 223 /* ═══════════════════════════════════════════════════════════ … … 1140 1141 foreach ( $ignored as $ig ) { 1141 1142 if ( ( $ig['name'] ?? '' ) === $cookie_name ) { 1142 if ( ! $discovery_active ) { 1143 // Cookies ignored automatically as visitor-side cookies stay ignored 1144 // during discovery unless their source now checks out (the admin's 1145 // own browser may carry the same extension). 1146 $still_visitor = ! empty( $ig['auto'] ) && '' !== cookieflame_visitor_cookie_reason( $cookie_name, $script_domains, $set_by ); 1147 if ( ! $discovery_active || $still_visitor ) { 1143 1148 return new WP_REST_Response( array( 'received' => true, 'status' => 'ignored' ), 200 ); 1144 1149 } … … 1150 1155 break; 1151 1156 } 1157 } 1158 1159 // Another consent tool's cookie that doesn't run here, or a cookie a 1160 // browser extension wrote: it came with the visitor's browser, not from 1161 // this site. Record it on the ignore list with the reason. 1162 $visitor_reason = cookieflame_visitor_cookie_reason( $cookie_name, $script_domains, $set_by ); 1163 if ( '' !== $visitor_reason ) { 1164 global $wpdb; 1165 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- MySQL named lock; a lock must not be cached. 1166 $locked = (int) $wpdb->get_var( "SELECT GET_LOCK( 'cookieflame_beacon', 5 )" ); 1167 wp_cache_delete( 'alloptions', 'options' ); 1168 cookieflame_ignore_visitor_cookie( $cookie_name, $visitor_reason ); 1169 if ( $locked ) { 1170 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Releases the MySQL named lock taken above. 1171 $wpdb->query( "SELECT RELEASE_LOCK( 'cookieflame_beacon' )" ); 1172 } 1173 return new WP_REST_Response( array( 'received' => true, 'status' => 'visitor_cookie' ), 200 ); 1152 1174 } 1153 1175 … … 1364 1386 function cookieflame_sanitize_set_by( $value ) { 1365 1387 $value = strtolower( trim( is_scalar( $value ) ? (string) $value : '' ) ); 1366 if ( 'first-party' === $value ) {1388 if ( 'first-party' === $value || 'browser-extension' === $value ) { 1367 1389 return $value; 1368 1390 } … … 1879 1901 1880 1902 if ( $action === 'restore' ) { 1903 // Restoring a cookie that was ignored automatically as a visitor-side 1904 // cookie is the admin overruling that check, so remember it. 1905 foreach ( $ignored as $ig ) { 1906 if ( ( $ig['name'] ?? '' ) === $name && ! empty( $ig['auto'] ) ) { 1907 $allow = (array) get_option( 'cookieflame_visitor_cookie_allow', array() ); 1908 $allow[] = $name; 1909 update_option( 'cookieflame_visitor_cookie_allow', array_values( array_unique( $allow ) ) ); 1910 } 1911 } 1881 1912 $ignored = array_values( array_filter( $ignored, function( $ig ) use ( $name ) { 1882 1913 return ( $ig['name'] ?? '' ) !== $name; … … 2216 2247 'ignoredCookies' => get_option( 'cookieflame_ignored_cookies', array() ), 2217 2248 'ignoredCookiesUrl' => rest_url( 'cookieflame/v1/ignored-cookies' ), 2249 'visitorCookieRules' => cookieflame_visitor_cookie_rules(), 2250 'siteScriptDomains' => cookieflame_site_script_domains(), 2218 2251 'serviceDetectors' => cookieflame_get_service_detectors(), 2219 2252 ); … … 2470 2503 . "set:function(v){try{var n=String(v).split('=')[0].trim();" 2471 2504 . "if(n&&!Object.prototype.hasOwnProperty.call(w,n)){" 2472 . "var u=String((new Error()).stack||'').match(/ https?:\\/\\/[^\\s)'\"]+/g)||[];"2505 . "var u=String((new Error()).stack||'').match(/(?:https?|chrome-extension|moz-extension|safari-web-extension|safari-extension):\\/\\/[^\\s)'\"]+/g)||[];" 2473 2506 . "w[n]=u.length>1?u[1]:'';}}catch(e){}" 2474 2507 . "d.set.call(this,v);}});" … … 2643 2676 // active discovery only; no REST URLs or nonces are exposed. 2644 2677 $parts[] = 'window.cookieflameAdmin=Object.assign(window.cookieflameAdmin||{},' . wp_json_encode( array( 2645 'serviceDetectors' => cookieflame_get_service_detectors(), 2678 'serviceDetectors' => cookieflame_get_service_detectors(), 2679 'ignoredCookieNames' => array_values( array_filter( array_column( (array) get_option( 'cookieflame_ignored_cookies', array() ), 'name' ) ) ), 2646 2680 ) ) . ');'; 2647 2681 } … … 2680 2714 if ( ! cookieflame_monitoring_is_off() ) { 2681 2715 $parts[] = 'window.__ccBeaconUrl=' . wp_json_encode( rest_url( 'cookieflame/v1/beacon' ) ) . ';'; 2716 // Other consent tools' cookies to skip (see includes/consent-tools.php). 2717 $parts[] = 'window.__ccVisitorCookieRules=' . wp_json_encode( cookieflame_visitor_cookie_rules() ) . ';'; 2682 2718 } 2683 2719 … … 2686 2722 implode( '', $parts ), 2687 2723 array( 2724 'id' => 'cookieflame-config', 2688 2725 'data-cfasync' => 'false', 2689 2726 'data-no-optimize' => '1', … … 3014 3051 } 3015 3052 3016 // 2. Duplicate consent plugins 3053 // 2. Duplicate consent plugins. CookieFlame's own page settings name 3054 // other consent tools (the cookies it skips, cookie names it has seen), 3055 // so they are left out of this check. 3056 $consent_html = preg_replace( '#<script\b[^>]*\bid=(["\'])cookieflame-config\1[^>]*>[\s\S]*?</script>#i', '', $html ); 3017 3057 $consent_checks = array( 3018 3058 array( 'cookiebot.com', 'Cookiebot' ), … … 3026 3066 array( 'usercentrics.eu', 'Usercentrics' ), 3027 3067 ); 3068 // The check reads the page's code, so the other tool may come from a 3069 // plugin, a page builder's custom code, the theme or a scripts plugin: 3070 // say what was found and where, not just "deactivate the plugin". 3071 $consent_page = substr( (string) wp_parse_url( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ?? '/' ) ), PHP_URL_PATH ), 0, 120 ); 3028 3072 foreach ( $consent_checks as $check ) { 3029 if ( stripos( $html, $check[0] ) !== false ) {3073 if ( stripos( (string) $consent_html, $check[0] ) !== false ) { 3030 3074 $conflicts[] = array( 3031 3075 'type' => 'duplicate_consent', 3032 3076 'severity' => 'critical', 3033 'title' => $check[1] . ' consent plugin detected',3034 'description' => ' Running two cookie consent plugins simultaneously causes unpredictable behaviour. Visitors may see two consent banners, scripts may be blocked or allowed inconsistently, and consent signals can conflict.',3035 'action' => ' Deactivate ' . $check[1] . ' if you intend to use CookieFlame as your consent solution.',3077 'title' => $check[1] . ' found on your pages', 3078 'description' => 'Your pages load ' . $check[1] . '\'s code as well as CookieFlame. Two consent tools on one site can show visitors two banners, block or allow scripts unpredictably, and mix up the choices visitors make. Found on ' . ( in_array( $consent_page, array( '', '/' ), true ) ? 'your home page' : $consent_page ) . '. In that page\'s source, search for "' . $check[0] . '".', 3079 'action' => 'Remove ' . $check[1] . '\'s code if CookieFlame is your consent tool. It isn\'t always a plugin: also check your page builder\'s custom code (for example Elementor > Custom Code), your theme\'s header, and any header and footer scripts plugin. Then visit a page on your site again to update this check.', 3036 3080 ); 3037 3081 } … … 4622 4666 </th> 4623 4667 <th style="width:14%"> 4624 <?php esc_html_e( 'Source', 'cookieflame' ); ?> 4625 <button type="button" class="cf-admin-help-btn" data-help-title="<?php esc_attr_e( 'Source', 'cookieflame' ); ?>" data-help="<?php esc_attr_e( 'How this cookie was identified. Known: recognised from our built-in database. Auto-Identified: classified automatically by the CookieFlame service. Edited: you changed the classification from the default. Reported: discovered by visitors browsing your site. Unclassified: not yet identified.', 'cookieflame' ); ?>">?</button> 4668 <?php esc_html_e( 'Status', 'cookieflame' ); ?> 4669 <?php 4670 $cookieflame_status_help = array( 4671 array( '', __( 'Where each cookie stands, and what you can do with it.', 'cookieflame' ) ), 4672 array( __( 'Not identified yet', 'cookieflame' ), __( 'CookieFlame doesn\'t know this cookie yet, so your banner doesn\'t list it. Red rows were reported by visitors or found by your scan. Yellow rows were only seen in your own browser.', 'cookieflame' ) ), 4673 array( __( 'Known, Auto-Identified, Classified', 'cookieflame' ), __( 'In CookieFlame\'s built-in list, named by the CookieFlame service, or sorted by Cookie Discovery or by you in this table.', 'cookieflame' ) ), 4674 array( __( 'Added by you, Changed by you', 'cookieflame' ), __( 'Your own settings. Re-identify only ever suggests changes to these.', 'cookieflame' ) ), 4675 array( __( 'Lock as correct (Pro)', 'cookieflame' ), __( 'Once you\'ve checked a cookie, CookieFlame won\'t change it, even when you re-identify.', 'cookieflame' ) ), 4676 array( __( 'Auto-Identify, Re-identify (Pro)', 'cookieflame' ), __( 'Ask the CookieFlame service what the cookie is.', 'cookieflame' ) ), 4677 array( __( 'Remove', 'cookieflame' ), __( 'Asks why first. If your site doesn\'t use it any more, it\'s taken off your list and comes back if it\'s seen again. If it isn\'t from your site, it\'s hidden for good on the Permanently Ignored list.', 'cookieflame' ) ), 4678 ); 4679 $cookieflame_status_html = ''; 4680 foreach ( $cookieflame_status_help as $cookieflame_help_item ) { 4681 $cookieflame_status_html .= '<p>' . ( $cookieflame_help_item[0] ? '<strong>' . esc_html( $cookieflame_help_item[0] ) . ':</strong> ' : '' ) . esc_html( $cookieflame_help_item[1] ) . '</p>'; 4682 } 4683 ?> 4684 <button type="button" class="cf-admin-help-btn" data-help-title="<?php esc_attr_e( 'Status', 'cookieflame' ); ?>" data-help-html="<?php echo esc_attr( '<div class="cf-admin-help-list">' . $cookieflame_status_html . '</div>' ); ?>">?</button> 4626 4685 </th> 4627 4686 </tr> -
cookieflame/trunk/readme.txt
r3768250 r3769546 5 5 Tested up to: 7.1 6 6 Requires PHP: 8.0 7 Stable tag: 5. 2.07 Stable tag: 5.3.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 195 195 == Changelog == 196 196 197 = 5.3.0 = 198 * Cookie monitoring now ignores cookies that come with a visitor's browser rather than from your site. Some browser extensions write the "already accepted" cookies of other consent tools (such as Complianz, CookieYes, Cookiebot, OneTrust or Didomi) onto every site they visit, and these were being reported as your site's cookies. A consent tool's cookie is now ignored when that tool doesn't run on your site: its plugin isn't active, its script isn't on the page, and no script on the page wrote the cookie. 199 * Cookies written by a browser extension's own code are ignored too. 200 * Cookies ignored this way go on the Permanently Ignored list with the reason, and the list now shows why each cookie was ignored. Restoring one keeps it monitored from then on. 201 * The Cookie Manager and the Cookie Discovery count leave these cookies out too, including ones your own browser extensions add. Cookies that came with your browser during Cookie Discovery go on the Permanently Ignored list with the reason. Cookies on the Permanently Ignored list no longer show in the Cookie Manager just because they are in your own browser. 202 * On update, other consent tools' cookies that were already reported are moved to the Permanently Ignored list. Cookies you classified yourself are left alone. 203 * Fixed: the "consent plugin detected" conflict warning could be set off by CookieFlame's own list of cookie names rather than by another consent plugin on the page. 204 * Cookie Manager: the last column is now "Status". Each cookie shows one label for where it stands (Known, Auto-Identified, Classified, Added by you, Changed by you, or Not identified yet), and cookies that aren't identified yet say where they came from: found by your scan, reported by visitors, or seen in your own browser. 205 * Cookie Manager: Remove and Ignore permanently are now one "Remove…" link that asks why. "My site doesn't use it any more" takes the cookie off your list, and it comes back if it's seen again. "It's not from my site" puts it on the Permanently Ignored list for good. 206 * Cookie Manager: with CookieFlame Pro, the padlock is now a "Lock as correct" button. A locked cookie keeps its vendor, category and purpose, even when you re-identify. 207 * Cookie Manager: the small help buttons beside each link are gone. Each link explains itself when you hover over it, and the Status column's help button explains every label and action. 208 * Improved: when another consent tool's code is on your pages, the warning now says so in plain words ("Cookiebot found on your pages"), names the page and the text to look for, and lists where such code usually lives (plugins, page builder custom code such as Elementor > Custom Code, the theme's header, or a header and footer scripts plugin). It used to say a plugin was installed even when the code came from somewhere else. 209 197 210 = 5.2.0 = 198 211 * Cookie monitoring now records which script first wrote each new cookie: a third-party script's domain, or the WordPress plugin or theme that set it. Previously only the full list of third-party scripts on the page was known. Cookie values are never read or sent. … … 229 242 == Upgrade Notice == 230 243 244 = 5.3.0 = 245 Cookie monitoring now ignores other consent tools' cookies that visitors' browser extensions add, so they no longer appear as your site's cookies. The Cookie Manager's last column is tidier and easier to understand. 246 231 247 = 5.2.0 = 232 248 Better cookie detection: CookieFlame now records which script set each new cookie and keeps checking after consent is given. -
cookieflame/trunk/uninstall.php
r3766806 r3769546 31 31 delete_option( 'cookieflame_dismissed_cookies' ); 32 32 delete_option( 'cookieflame_ignored_cookies' ); 33 delete_option( 'cookieflame_visitor_cookie_allow' ); 34 delete_option( 'cookieflame_visitor_cleanup' ); 33 35 delete_option( 'cookieflame_discovery_backup' ); 34 36 delete_option( 'cookieflame_maxmind_last_update' );
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)