=== MantaWeb Consent Shield - Cookie Consent Banner & Real Cookie Blocker (GDPR, CCPA, Tikun 13) ===
Contributors: mantaweb
Tags: cookie consent, gdpr, ccpa, privacy, cookie banner
Requires at least: 6.2
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 5.0.13
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Cookie consent banner + real server-side cookie blocker. GDPR, CCPA and Israeli Tikun 13 ready. No SaaS: consent data never leaves your server.

== Description ==

**MantaWeb Consent Shield** is a privacy consent management plugin for WordPress built by **MantaWeb**. It combines a configurable consent banner with an active script and cookie blocker, a full audit log, and a compliance checklist - all without sending any data to external servers.

= Who it is for =

Any WordPress site that needs to comply with:

* **Israeli Privacy Law Amendment 13** (Tikun 13, in force August 2025)
* **GDPR** + ePrivacy Directive (EU / UK)
* **CCPA** "Do Not Sell My Personal Information" (California)

= How it works =

When a visitor lands on your site, Consent Shield shows a consent banner before any third-party scripts run. Scripts are blocked server-side using an output-buffer HTML rewriter - not just via the WordPress `wp_enqueue_script` filter. This means inline scripts (Google Tag Manager, Meta Pixel, GA4 config calls), iframes (YouTube, Vimeo, Google Maps), and tracking pixels are all held until the visitor gives consent, even when the page is served from a Cloudflare cache or WP-Rocket.

After consent, the plugin stores the record in a local database table with an INSERT-only write path (a stored record is never rewritten) and fires Google Consent Mode v2 signals automatically for GA4 and Google Ads. Records leave the table only through the retention policy you configure, or an explicit "Clear Log".

= Key features - Free =

**4-category consent banner**
* Necessary, Functional, Analytics, Marketing categories
* 1-button, 2-button, and 3-button layouts (configurable in the wizard)
* Fully customizable text - edit every word the visitor sees from the admin UI
* Floating privacy pill for post-consent withdrawal (required by Tikun 13)
* `[mantacs_dsar_button]` shortcode: adds a "Request my data" button that opens the visitor's mail client with a pre-filled DSAR email addressed to your DPO

**Real script and cookie blocker**
* Output-buffer HTML rewriter - blocks scripts and iframes that bypass `wp_enqueue_script`
* Click-to-load placeholders for YouTube, Vimeo, and Google Maps embeds
* Cookie Sweeper removes cookies not belonging to consented categories on consent change
* Works behind Cloudflare cache, WP-Rocket, and other full-page caching systems
* ~50 built-in service definitions including Israeli payment gateways (Tranzila, Cardcom, Bit, iCount, ActiveTrail, Smoove)

**Compliance tools**
* Google Consent Mode v2 automatic wiring for GA4
* IP anonymization - IPv4 masked to /24, IPv6 to /48 (default ON)
* Tikun 13 compliance checklist with automatic checks and manual-check guidance
* Policy versioning - one click forces re-consent from all visitors
* Bot detection - hides the popup from search engine crawlers

**Audit and data management**
* INSERT-only consent log: a stored record is never rewritten, so the log is an audit trail for as long as your retention policy keeps it (default 365 days / 20,000 records, both adjustable, and "keep forever" is an option)
* CSV export from the admin UI
* Admin activity log tracks every settings change
* WP-CLI commands: `wp pcm status`, `wp pcm consents export`, `wp pcm policy bump`, `wp pcm tikun13 check`, `wp pcm wizard reset`, `wp pcm cache flush`

**Accessible consent banner**
* Built to meet WCAG 2.1 AA for the consent interface - keyboard and screen-reader accessible, EAA-aware
* Proper dialog semantics: `role="dialog"` + `aria-modal` for the overlay banner, a labelled `role="region"` for the quiet inline banner
* Focus is moved into the banner on open, kept inside it while it is open, and restored on close - and it is never pre-placed on "Accept"
* Real `<button>` and `<input type="checkbox">` controls with visible focus indicators, not clickable `<div>`s
* Live contrast badges in the admin colour picker warn you before you ship a low-contrast palette
* `prefers-reduced-motion` honoured in both CSS and the JS fade helpers

**Setup**
* 5-step guided setup wizard (~3 minutes)
* All banner texts editable from the admin "Custom Texts" tab
* Light/dark mode support via CSS custom properties

= What makes it different =

**Real blocker, not just an enqueue filter.** Most consent plugins only hook into `wp_enqueue_script`. Consent Shield rewrites the HTML output server-side, so GTM's `dataLayer` push, inline `fbq()` calls, and hardcoded `<script>` tags are all blocked before the visitor even downloads the page - including scripts injected by Elementor custom code, WPCode, or Insert Headers and Footers, not only those loaded via `wp_enqueue_script`.

**Cloudflare-safe architecture.** Because the HTML is identical for all visitors (scripts disabled by default), cached pages work correctly. The client-side bootstrap JS reads the consent cookie and re-enables the right scripts in real time - no PHP run required.

**100% self-hosted - a privacy tool that respects privacy.** Many popular consent solutions are SaaS platforms: every consent event, and with it your visitors' data, flows through a third-party cloud. Consent Shield sends nothing anywhere - no telemetry, no phone-home, no external consent management platform. Consent records live in your own database, under your control.

**Tikun 13-first.** Built from scratch for Israeli Privacy Law compliance, not retrofitted from a GDPR-only plugin.

**Accessible by design.** The banner is the first thing every visitor meets, so it is built to meet WCAG 2.1 AA for the consent interface: dialog semantics, managed focus, labelled native controls, visible focus rings and reduced-motion support. Many consent banners still ship with no dialog role and no focus management at all, which means a keyboard or screen-reader user can be stuck at the front door. This is not an accessibility certification and it does not make a whole site conformant - overall conformance and your own colour choices are still yours - but it is one less obstacle under the European Accessibility Act and IS 5568.

= Fully functional, no locked features =

Every feature described above is included and fully functional. Nothing is crippled, time-limited or held back: no license keys, no trials, no feature that stops working after 14 days, and no upsell standing between you and a compliant banner.

One honest exception, so you are not surprised by it: the Design tab ends with an "Effects" group (backdrop blur, background opacity, border width, corner radius) shown as a clearly-labelled, disabled preview of the Pro controls, with the real default values in place. It is a preview of what Pro adds, not a switched-off part of this plugin. Nothing else in the interface is disabled, and no feature listed above depends on it.

= Consent Shield Pro (separate full version) =

A separate, paid Pro version (distributed by MantaWeb, not hosted on WordPress.org) contains everything in this plugin plus geo-routed banner text (GDPR/CCPA variants by visitor country), per-language versions of the banner texts and of the Privacy Policy link for multilingual sites, a visual banner-layout picker, per-button colors with gradients and hover effects, embedded Hebrew web fonts, and an auto-detect scanner. Installing Pro replaces this plugin; all settings and consent data carry over automatically. Full feature comparison: [manta-web.co.il/consent-shield/en](https://manta-web.co.il/consent-shield/en/)

MantaWeb also offers a separate, paid Tikun 13 implementation service (privacy-policy drafting and site setup); details are on the "MantaWeb Services" screen inside the plugin.

== Installation ==

1. In WP Admin go to **Plugins > Add New > Upload Plugin**, upload the ZIP, and activate.
2. A yellow admin notice will appear: "Consent Shield: You have not configured the plugin yet." Click **Launch Setup Wizard**.
3. Complete the 5-step wizard:
   * Step 1 - DPO email address and company / site name
   * Step 2 - Select your Privacy Policy page
   * Step 3 - Banner layout (1, 2, or 3 buttons) and floating privacy pill position
   * Step 4 - Compliance toggles (IP anonymization, Google Consent Mode v2, advanced blocker, bot hiding)
   * Step 5 - Summary and finish
4. If you use Cloudflare, WP-Rocket, or another caching system, purge the cache once after activation.
5. Optionally check the **Tikun 13 Compliance** page for an automated checklist and manual guidance.

== Frequently Asked Questions ==

= Does it block scripts before the visitor gives consent? =

Yes. Consent Shield uses a PHP output-buffer rewriter that intercepts the HTML before it is sent to the browser. Scripts are replaced with inert placeholders (`type="text/plain" data-pcm-src="..."`). A lightweight bootstrap JS file activates only the scripts belonging to categories the visitor has consented to. This happens even when PHP is not involved in serving a cached page.

= Does it block scripts added by Elementor, WPCode or header/footer plugins? =

Yes. Because the blocker rewrites the page's final HTML instead of relying on WordPress's `wp_enqueue_script` system, it does not matter how a tracker got onto the page: Elementor custom code, a WPCode or "Insert Headers and Footers" snippet, Google Tag Manager code pasted into the theme, or a tag another plugin adds - all are held until the visitor consents. Two edge cases: a rare inline script with no known signature, and a tag that a tag manager injects at runtime (handled by blocking the parent tag manager plus Google Consent Mode v2).

= Does it work with Cloudflare / WP-Rocket / other caching systems? =

Yes. The HTML served to all visitors is identical - scripts are disabled in the static HTML. The client-side JS reads the visitor's consent cookie and re-enables scripts in real time. Caching systems serve the same cached HTML to everyone; the per-visitor decision is made in the browser.

= Is it GDPR compliant? =

Yes for the plugin's scope. Consent Shield provides: prior consent before non-essential scripts run, granular category selection, a clear withdrawal mechanism, an INSERT-only consent log with IP anonymization (records are never rewritten, and are removed only by the retention policy you configure), and a policy versioning mechanism. Your legal counsel should review your overall compliance posture including your privacy policy content.

= Is it CCPA compliant? =

Basic CCPA support is included: a "Do Not Sell" flow via the consent banner. Geo-targeted CCPA-specific banner text for US visitors is available in the separate Consent Shield Pro add-on.

= Is it Tikun 13 (Israeli Privacy Law Amendment 13) compliant? =

Yes within the plugin's scope. Consent Shield covers: informed consent before non-essential data collection, granular category choices, visitor withdrawal rights (floating pill + DSAR shortcode), and an INSERT-only consent log kept for the retention period you set. The remaining Tikun 13 obligations - legal privacy policy text, consent checkboxes across forms, and DPO registration - require external work. See the Tikun 13 Compliance page inside the plugin for a checklist.

= Does it phone home or send data to external servers? =

No. Every consent record, admin log entry, and configuration option is stored in your WordPress database. Nothing is sent to MantaWeb or any other external service.

= How are consent records stored? =

In a dedicated `pcm_consents` database table. Writes are INSERT-only: a stored record is never rewritten, so what you read back is exactly what the visitor chose at that moment.

Records are removed only in two ways, both under your control:

* **The retention policy you configure.** A daily cleanup permanently deletes records older than "Log retention (days)" (default 365) and, once the table passes "Maximum records to store" (default 20,000), the oldest records above that limit. Both fields are in **Settings > Compliance & logs**. Set retention to 0 to keep records indefinitely, and raise the maximum if your traffic needs it.
* **The "Clear Log" button** in the Visitor Activity Log, which empties the table immediately.

Because this log is the evidence you would rely on to demonstrate consent, review both limits against your own retention obligations, and export to CSV from the admin UI before anything ages out.

= How do I customize the banner text? =

Go to **Privacy Management > Privacy Settings**, then click the **Custom Texts** tab. Every string the visitor sees - banner message, button labels, category names and descriptions, privacy policy link text, and the floating pill label - can be overridden per-field. Leave a field blank to use the default (shown as placeholder).

= How do I add a "Withdraw consent" or "My privacy choices" link? =

Two options:
1. The floating privacy pill appears automatically in the position you configured in the wizard. Clicking it reopens the consent banner.
2. Add `[mantacs_dsar_button]` to any page to place a "Request my data" button that opens the visitor's mail client with a pre-filled DSAR email to your DPO.

= How do I export consent records for an audit? =

Go to **Privacy Management > Visitor Activity Log** and click **Export CSV**. The export is logged in the Admin Activity Log with the username that performed it.

= What happens if something on my site breaks after activation? =

Add `define('MANTACS_DISABLE_OB', true);` to your `wp-config.php`. This switches off the output-buffer rewriter, so the plugin stops touching your page's HTML.

Be precise about what is left running. The client-side layer stays active: Google Consent Mode v2, the click-to-load placeholders, the cookie sweeper, and the runtime catcher for tags injected by JavaScript. What stops is all server-side neutralising, and the constant on its own does **not** switch the enqueue-only blocking on: that is the "Basic" blocking mode, which you have to select in **Settings > Blocking**. Until you do, nothing is blocked before the page reaches the browser.

Remove the constant once you have identified the conflict.

= What exactly does the "Basic" blocking mode turn off? =

"Basic" blocks only scripts registered through `wp_enqueue_script` that match the Handle or URL-pattern lists in the Blocking tab. Compared with "Full" it also turns off three things that ship with the output-buffer rewriter:

* the cookie sweeper, so cookies belonging to a category the visitor refused are no longer deleted;
* the click-to-load placeholders for YouTube, Vimeo and Google Maps embeds;
* the runtime catcher that neutralises `<script>` / `<iframe>` / `<img>` tags injected by JavaScript after the page loads.

Google Consent Mode v2 is independent of the blocking mode: if it is enabled it fires in Full, Basic and Off alike.

= Is there a Pro version? =

Yes. Consent Shield Pro is a separate full version, distributed by MantaWeb (not hosted on WordPress.org). On top of everything in this free plugin it adds geo-routed banner text (GDPR / CCPA variants by visitor country), a separate set of banner texts and a separate Privacy Policy page for each language on a multilingual site (it follows the WordPress locale, so it works alongside Polylang, WPML or TranslatePress, and with a bilingual theme that has no multilingual plugin at all), a visual banner-layout picker, per-button colors with gradients and hover effects, embedded Hebrew web fonts, and an auto-detect tracker scanner. Installing Pro replaces this plugin; every setting and consent record carries over automatically. See the full feature comparison at [manta-web.co.il/consent-shield/en](https://manta-web.co.il/consent-shield/en/).

== Screenshots ==

1. The consent banner - Accept All / Essential Only / Decline, plus a "Customize" option, shown over a live site.
2. Granular per-category consent. Visitors toggle Functional, Analytics and Marketing independently; Essential is always on.
3. Real script blocking. Third-party embeds (YouTube, Maps, etc.) are replaced with a click-to-load placeholder and never load until allowed. The floating privacy button (bottom-left) lets visitors change their choice at any time.
4. The guided 5-step Setup Wizard, including the plugin-language selector.
5. The Israeli Privacy Law (Tikun 13) compliance checklist - an automatic score against the core requirements.
6. The Design tab - colours, typography, position and effects in collapsible groups. Each colour has a hex field, an eyedropper and a live WCAG contrast score, and the banner preview docked at the bottom updates as you edit.

== External services ==

This plugin does NOT connect to, call, or send any data to any external or third-party service. It makes no outbound HTTP requests. Every consent record, log entry and setting is stored only in your own WordPress database. No telemetry, no phone-home, no remote fonts, no remote analytics, and no license or activation checks.

Please note about the code: the plugin contains a built-in list of third-party tracker domain names (for example googletagmanager.com, connect.facebook.net, embed.tawk.to, widget.intercom.io). These strings are NOT services the plugin contacts. They are the plugin's blocklist: the trackers the plugin looks for in your page's HTML and BLOCKS (neutralizes) until the visitor consents. The plugin never loads or requests any of these domains itself; it only prevents your own theme/other plugins from loading them before consent.

The MantaWeb Services admin page contains plain HTML links to the MantaWeb website and to WhatsApp. Nothing is sent when the page loads; a link only opens the target site in a new tab if you click it.

== Changelog ==

= 5.0.13 =
* Fixed: on some sites the plugin sent you to the Setup Wizard automatically after installing, landed on "Sorry, you are not allowed to access this page", and left no way back. This happened when another plugin owned Consent Shield's menu for that request. The plugin no longer redirects anywhere on its own, and the links to the wizard are hidden whenever that screen is not available.
* Fixed: "skip the wizard" now also stops the setup notice, instead of only the redirect that no longer exists.

= 5.0.9 =
* Fixed: the "You have not configured the plugin yet" setup notice no longer appears on Consent Shield's own screens. It was meant to be hidden there and never was.
* Fixed: removed an unused internal address from the data the plugin adds to your pages. It pointed at a feature that was taken out in 4.3.0 and did nothing.
* Translations: the Hebrew, Arabic and Spanish catalogues now cover every screen. Seventeen labels were still showing in English, including the column headings in the consent-log CSV export and the two text-size fields on the Design tab.

= 5.0.8 =
* Fixed: clicking "Add" on a service in the Blocking tab could fail with a fatal error. Two files were missing from the 5.0.7 download, so the code that adds the service was never installed. Both are included again.
* Fixed: Google Consent Mode v2 was not sent on sites running with the advanced blocker turned off, for the same reason.
* Internal: new extension points so add-ons can supply the banner message, the Privacy Policy link target and extra rows on the Texts tab. The banner and the settings screens render exactly as in 5.0.7.
* Internal: the live banner preview in the admin can now have its admin-typed strings supplied by an add-on too, so a preview and the front end cannot drift apart. With no add-on installed the preview behaves exactly as in 5.0.7.

= 5.0.7 =
* The screenshot gallery now shows only screens you get in this plugin. A screenshot of a Pro-only screen was removed.

= 5.0.6 =
* The Design tab is now organised so that Pro controls appear inside the group they belong to (Colours, Typography, Position and size, Effects) instead of all landing in one place.
* The locked "Effects" preview now shows the real default values, so the sliders you see match what you get after upgrading.
* Groundwork for the Pro effects (backdrop blur, background opacity, borders, corner radius). The free banner renders exactly as before.

= 5.0.5 =
* New: the settings screen was reorganized into five focused tabs - Banner and buttons, Design, Texts, Blocking, Compliance and logs. After saving you return to the tab you were on.
* New: rebuilt Design tab - a proper colour picker with a curated palette, hex field and eyedropper, a live WCAG contrast check on your colour combinations, and a one-click reset to the default design.
* New: the live banner preview now floats at the bottom of the settings screen and follows you across the Banner, Design and Texts tabs, updating as you type (including custom button texts). It can be hidden with one click.
* New: the "delay before showing" field now has friendly presets (Immediately / 2s / 5s...) instead of raw milliseconds.
* New: an optional "Powered by MantaWeb" credit link on the banner (off by default).
* Fixed: on phones, the centered banner box could slide halfway off the screen; it now docks neatly to the bottom at full width.
* Fixed: on phones, opening "Customize" inside the banner could push the category toggles and Save button below the screen; the banner now scrolls inside itself with a single scroll.
* Fixed: saving the main settings screen no longer disables Google Consent Mode v2. The wizard-set value (and other options without a control on that screen) are now preserved instead of being reset on save.
* Fixed: the banner button-layout default is now consistent everywhere, so saving no longer switches an unset layout to two-button mode.
* Fixed: admin styles and scripts now refresh automatically after an update - no more hard refresh to see the current settings screen.
* Improved: banner accessibility hardening - better keyboard navigation and screen-reader labels.
* Improved: the legacy blocking-level section was folded into one clear blocking mode setting.
* Added an "Upgrade to Pro" link on the plugins list.
* Typography: replaced em dashes with regular hyphens across the interface and the bundled translations.
* Removed a leftover internal font flag from v4.1.0 (no change to how fonts render).

= 5.0.4 =
* Sanitization polish: the numeric settings (page IDs, retention, delay, log limit, font sizes) now go through absint().

= 5.0.3 =
* Fixed: the admin CSS/JS were not loaded on the main settings screen (the hook test did not match the menu slug), so the live popup preview only refreshed after saving. All plugin screens now load their assets and the preview updates as you type.
* Fixed the remaining Plugin Check errors: escaped the font-size field output and prepared every direct database read with the %i identifier placeholder.

= 5.0.2 =
* WordPress.org review compliance pass (round 3). Removed the artificial caps: log-retention days, maximum stored records and font sizes are now fully adjustable in this free plugin (no companion-plugin unlock hooks remain). Renamed the internal code prefix from "pcm" to the unique 4+ character prefix "mantacs" across defines, class, namespaces, options, hooks, AJAX actions, script handles, page slugs and the DSAR shortcode; existing installs migrate their saved settings automatically. Wrapped the CSV export headers in translation functions. Switched all direct database reads to $wpdb->prepare() with the %i identifier placeholder (requires WordPress 6.2+).

= 5.0.1 =
* WordPress.org review compliance pass. Removed every remaining tier-gated code path so the plugin contains only free, fully-functional features (per-button colours, numeric font sizes, custom fonts, and larger retention/log limits were removed entirely from this plugin; they exist only in the separate paid Pro version, which is not hosted here). Hardened input sanitization for all $_SERVER / $_COOKIE / $_GET reads. Paired the output-buffer rewriter with an explicit close on shutdown. Clarified in this readme that the plugin makes no external calls and that the tracker domain names in the code are a blocklist, not services it contacts. Fixed the Plugin URI.

= 5.0.0 =
* Renamed to "MantaWeb Consent Shield" (new slug: mantaweb-consent-shield).
* Removed all locked/tier-gated functionality from this plugin. Everything it ships is fully functional; premium capabilities (geo-routed banner text, per-button colors, Hebrew web fonts and numeric sizes, extended retention/log limits, auto-detect scanner) moved to the separate Consent Shield Pro add-on, which is distributed by MantaWeb and hooks into this plugin's public filters and actions.
* Removed the Pro-waitlist email form. The plugin now makes no external calls of any kind.
* Moved the last inline admin script into the enqueued admin JavaScript.

= 4.4.13 =
* Cleared the last Plugin Check errors: added translator comments and output escaping to the remaining placeholder strings, and annotated the output-buffer script rewriter. The plugin now passes Plugin Check with no errors.

= 4.4.12 =
* WordPress.org Plugin Check compliance pass: escaped all admin-page output, added translator comments to strings with placeholders, moved inline `<style>` blocks into the stylesheet, switched the inline blocker script to `wp_print_inline_script_tag()`, replaced `date()`/`parse_url()` with `gmdate()`/`wp_parse_url()`, and limited the readme to 5 tags. No functional or visual changes.

= 4.4.11 =
* Banner buttons now align with the start of the reading direction (left in English/LTR, right in Hebrew/Arabic) so they line up under the message text instead of being pushed to the opposite side.

= 4.4.10 =
* **Fixed: the "Plugin Language" override did nothing.** Selecting English (or any language) left the admin screens and the visitor banner in the site language. WordPress loads a plugin's translation "just in time" on the first string, and that path ignored the `plugin_locale` filter the override relied on - so the site-language `.mo` was already loaded and, since English is the source language, there was no English `.mo` to replace it. The override now works via the `load_textdomain_mofile` filter, which every load path honours, and forces English by leaving the text domain unloaded.
* **Fixed: forcing an LTR language on an RTL site (or vice-versa) now flips text direction correctly.** Banner, wizard and settings preview follow the forced language's direction instead of the site locale, so an English banner on a Hebrew site reads left-to-right.

= 4.4.9 =
* **Fixed: the "Customize" category panel rendered right-to-left on English (and other LTR) sites.** Panel alignment and the on/off toggle animation were hardcoded to RTL geometry. Direction is now derived from the site locale - LTR by default, RTL for Hebrew/Arabic - and the popup carries an explicit direction so it no longer depends on the theme setting `dir` on the `<html>` element. Also applies to the click-to-load placeholder and the footer privacy link.

= 4.4.8 =
* **Critical fix: all popup buttons were dead when reopening via the Privacy Pill.** The click handlers (Accept All / Essential Only / Decline / Customize / Save Choices) were only wired for visitors WITHOUT existing consent - the initializer returned early for returning visitors, so the popup the pill reopened had no event listeners at all. Handlers are now wired unconditionally. This latent bug existed since the pill was introduced and surfaced once 4.4.6/4.4.7 made the pill reopen work reliably.

= 4.4.7 =
Full-codebase review release - 10 fixes, 2 of them critical consent-integrity bugs:

* **Fixed: scripts blocked via handles/URL patterns were never re-enabled after consent.** Two combined defects: the server-side consent check still compared the cookie against the plain string `accept` (the cookie has been JSON since 4.4.1), and the legacy-blocked `<script>` tags carried no `data-pcm-category`, which the restore logic requires. Both sides fixed; already-cached pages are healed by a client-side category fallback.
* **Fixed: the category toggles showed everything OFF after "Accept All".** The panel prefill did not understand the 4.4.1 wrapped-choice cookie format - reopening via the privacy pill displayed all optional categories unchecked, and re-saving from that state silently downgraded the visitor's consent to necessary-only.
* **Fixed: the AJAX endpoint set the consent cookie in the pre-4.4.1 plain-string format.** With `COOKIE_DOMAIN` defined this created a second, stale cookie the client JS never overwrote - causing an endless re-consent loop after a policy bump. The server now writes the exact JSON shape the client writes.
* **Fixed: crawler requests could poison full-page caches with bannerless HTML.** The bot check ran server-side, so a crawler priming Cloudflare/WP Rocket cache produced pages with no consent banner for every visitor. Bot hiding now happens client-side; the markup (hidden by default CSS) is always rendered.
* **Fixed: "Bump policy version" was ignored when the Advanced Blocker was disabled** (the policy version was only exposed through the blocker bootstrap). It is now passed to the popup script directly.
* **Performance: table-schema checks (dbDelta) no longer run on every request** - they are gated behind a stored schema version and run only on install/upgrade.
* **Privacy: removed the visitor UUID from the inline blocker payload.** It was baked into cached HTML, exposing the cache-priming visitor's identifier to everyone.
* Retention cron now compares timestamps in UTC (matching how consent records are stored).
* Setup Wizard: the privacy-policy dropdown now lists up to 500 pages, sorted by title.
* Internal: normalized newline-splitting regexes in the settings save handler.

= 4.4.6 =
* **Fixed: Floating Privacy Pill click did nothing in the first 5 seconds after page load.** A defensive `MutationObserver` installed when a visitor already had consent was force-hiding the popup whenever its `style.display` changed - including the intentional change triggered by clicking the pill. Result: visitors saw the pill, clicked it, and the pill disappeared without the preferences modal ever opening. The observer is now disconnected as soon as a pill click occurs.
* **Fixed: Wizard navigation arrows displayed on the wrong visual side in Hebrew RTL.** Source order was being flipped for RTL on top of the browser's own bidi re-ordering, producing a double-flip. The same string order now works for both directions; only the arrow glyph (← vs →) varies.

= 4.4.5 =
* Removed duplicated arrows in Hebrew/Spanish wizard buttons (translation strings no longer ship with baked-in arrow glyphs).
* Renamed top-level admin menu from "Privacy Management" to "Consent Shield" for brand consistency.

= 4.4.4 =
* Added a visible "Notice: clicking this button sends your email to the plugin author" disclosure above the Pro waitlist form (Alex security audit MEDIUM-2).
* Disclosed the `wp_mail` to `gabi@manta-web.co.il` in the readme "External services" section (Alex MEDIUM-1).

= 4.4.3 =
* Removed redundant arrow from the wizard "Skip" link.
* Expanded Hebrew and Arabic translations from ~77 to ~470 strings (full UI coverage).
* Added Spanish (es_ES) translation.

= 4.4.2 =
* New: "Plugin Language" admin option - override the WP site locale for the consent UI (auto / English / Hebrew / Arabic / Spanish).
* Direction-aware wizard navigation arrows.

= 4.4.1 =
* **Critical fix: consent persistence broke on sites whose admin had ever pressed "Bump policy version".** Plain-string cookie values (`accept` / `essential` / `decline`) were treated as `policy_version=0` by `hasConsent()`, which made every page load re-show the banner. All consent values are now wrapped in JSON with the current `policy_version`.

= 4.4.0 =
* **Full internationalization (i18n)**: Default language switched from Hebrew to English. All 380+ user-facing strings are now translatable via the standard WordPress `__()` / `esc_html__()` system with text domain `consent-shield`. Ships with Hebrew (he_IL) and Arabic (ar) starter translations. Additional languages available via translate.wordpress.org.
* **RTL direction is now conditional** on site locale (`is_rtl()`). Was previously hardcoded to `direction:rtl` in three CSS blocks and one inline style, forcing RTL even on LTR sites.
* **Plugin header Description rewritten to English** for correct wp.org indexing.
* **Services page prices removed** - replaced with "Contact us for pricing" and a landing-page CTA.
* **`load_plugin_textdomain`** wired on `init`; `Domain Path: /languages` added to plugin header.
* `readme.txt` rewritten to English-primary for wp.org submission compliance.

= 4.3.5 =
* Fixed: WP Rocket admin notice still showed on the services page after v4.3.4 because `remove_all_actions('admin_notices')` ran too late. Moved suppression to the `current_screen` hook.
* Fixed: Hero font rendered with cramped Hebrew glyphs on Windows (Segoe UI at weight 800). Switched to Hebrew-first font stack and dropped `font-weight` from 800 to 700 with `letter-spacing` reset to 0.

= 4.3.4 =
* Services page: 8 UX fixes from live review - font inheritance, admin-notice suppression, RTL workflow-step number overlap, copy corrections, CTA replaced from mailto to web-form link.

= 4.3.3 =
* Fixed: Click-to-load placeholders did not unwrap after "Accept All".
* Fixed: Category toggles showed pre-consent state after reopening via the floating pill.

= 4.3.2 =
* Free/Pro UI lockdown: Hebrew web fonts, per-button colors, custom font sizes, extended retention, and auto-detect buttons are now gated behind Pro badges. Server-side clamps enforce limits on save.

= 4.3.1 =
* DSAR cleanup: removed three orphan references to automated DSAR emails that no longer exist in the Free plugin.
* New `[consent_shield_dsar_button]` shortcode for manual DSAR contact channel.

= 4.3.0 =
* Free/Pro tier split. Auto-scanner, DSAR REST API, WPML adapter, WooCommerce integration, and geo-routing moved to consent-shield-pro. Service catalog trimmed from 115 to ~50 entries.
* Pro waitlist now sends a `wp_mail()` notification to MantaWeb on signup.

= 4.2.1 =
* New MantaWeb Services page replacing the speculative "Upgrade to Pro" template. Shows real service offering (Tikun 13 compliance package) with WhatsApp and web-form CTAs.

= 4.2.0 =
* Rebrand: Privacy Consent Manager → Consent Shield by MantaWeb. Plugin slug updated to `consent-shield`. No data loss on upgrade - internal identifiers (`pcm_options`, `pcm_consents`, `PCM_*` constants) kept stable.

= 4.1.0 =
* Typography overhaul with Hebrew-aware font stack and discoverable font controls.
* Custom-font field collapses unless the "Other" option is selected.

= 4.0.0 =
* Initial public release of Consent Shield. Real output-buffer script blocker, 4-category consent banner, Google Consent Mode v2, 5-step setup wizard, Tikun 13 compliance checklist, IP anonymization, floating privacy pill, WP-CLI commands.

== Upgrade Notice ==

= 4.4.13 =
Stability and standards release: reliable consent persistence, working per-visitor language override, correct RTL/LTR direction, and a clean WordPress.org Plugin Check pass. No data migration required.
