Changelog
========

= 1.8.2 =
*   **UI polish — icon and alignment fixes** (`assets/css/admin.css`, `assets/css/wizard.css`, `includes/admin/class-admin.php`): Resolved several visual inconsistencies across the plugin UI. Wizard step-navigation buttons (Next / Back): dashicon arrow was slightly lower than the button text due to the WordPress default button `line-height: 2.15` bleeding through — fixed with `line-height: 1` on `.clicutcl-wizard__btn .dashicons`. Settings page: form-table `th` and `td` cells now use `vertical-align: middle` so toggle switches and their labels sit centered in each row. Card header icon badge and section-header dashicons: added `line-height: 1` and `vertical-align: middle` to prevent glyph offset from dashicons' built-in `vertical-align: top`. Admin sidebar icon: replaced `dashicons-chart-area` with a custom monochrome SVG trail icon — four connected nodes on an upward curve — which renders correctly across all WordPress admin colour schemes via WP's `filter: brightness(0) invert(1)` mechanism.

= 1.8.1 =
*   **Plugin Checker clean pass — PHPCS false positives** (`includes/integrations/class-woocommerce.php`, `includes/class-clicutcl-core.php`): `WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound` warnings on local variables inside class methods (`$normalized`, `$key`, `$value`, `$touch_key` in `normalize_attribution_structure()`; `$term_product_id`, `$terms` in `get_woocommerce_product_categories()`) and a protected class property (`$booted`) are not globals. Silenced with scoped `phpcs:disable/enable` blocks and an inline `phpcs:ignore` respectively. No logic changes.

= 1.8.0 =
*   **GTM Starter Kit lead magnet** (`includes/admin/class-gtm-lead-magnet.php`, `assets/gtm-starter-kit.json`): Adds a dismissible settings-page banner that appears after the first WooCommerce order is tracked (or 3 days after activation, whichever comes first). Submitting an email with explicit opt-in consent subscribes the user to Brevo (fire-and-forget via `wp_remote_post` — failure is logged, never surfaced) and returns a single-use 10-minute signed download link for the pre-built GTM container JSON. The JSON ships 16 Data Layer Variables (full `ecommerce.*` object plus `ft_`/`lt_` attribution series, click IDs, and `event_id` for deduplication), 5 user-configurable Constant Variables (GA4 ID, Ads conversion ID/label, Meta Pixel ID, sGTM endpoint), 7 Custom Event triggers, 11 tags (GA4 Config, Conversion Linker, Meta Pixel base, GA4 purchase/add_to_cart/begin_checkout/view_item/view_item_list, Google Ads purchase, Meta Pixel purchase with `event_id` dedup), and Consent Mode v2 defaults. Brevo credentials configured via `CLICUTCL_BREVO_KEY` and `CLICUTCL_BREVO_LIST` constants.
*   **WooCommerce integration** (`includes/integrations/class-woocommerce.php`): Added `do_action( 'clicutcl_order_attribution_saved', $order )` at the end of `save_order_attribution()` to provide a reliable hook for post-order attribution actions.

= 1.7.9 =
*   **Cross-domain: sibling subdomain passthrough, zero config** (`assets/js/clicutcl-attribution.js`): Link decoration previously only auto-allowed targets that were direct children of the current host (e.g. `site.com` → `checkout.site.com`). Sibling subdomains (`shop.site.com` → `checkout.site.com`) required manually adding the destination to the allowed-domains list. A `getRegistrableDomain` helper now extracts the eTLD+1 from both hosts and compares them — if they share the same registrable domain (including common 2-part TLDs: `.co.uk`, `.com.br`, etc.) decoration fires automatically with no configuration needed.
*   **Checklist: WooCommerce checkout subdomain detection** (`includes/admin/class-admin.php`): When WooCommerce is active and its checkout URL resolves to a different host than `home_url()`, the Cross-domain checklist row now surfaces as `attention` with a message naming the checkout hostname, prompting the user to enable link decoration. Previously showed a silent `neutral` regardless of checkout topology.
*   **Checklist: cross-domain copy fix** (`includes/admin/class-admin.php`): The "decoration will not fire" warning was misleading — decoration fires for all same-registrable-domain targets without an allowed-domains entry. Replaced with accurate copy explaining that subdomains work automatically and the allowed-domains list is only needed for fully separate domains.

= 1.7.8 =
*   **Critical: file truncation hotfix** (`includes/server-side/class-queue.php`, `uninstall.php`): Edit-tool writes during the v1.7.7 release had silently truncated both files, leaving `class-queue.php` missing the `find_event_row()` method and its closing class brace (PHP fatal: unclosed `{` on line 19), and `uninstall.php` missing the final `DROP TABLE` statement for `clicutcl_events` and its closing brace. Both files restored from verified source; brace balance confirmed (58/58 and 8/8 respectively). No logic changes.

= 1.7.7 =
*   **Plugin Checker — zip exclusions** (`Makefile`/build): Previous releases included dev-only files (`.editorconfig`, `.gitignore`, `.mcp.json`, `.phpunit.result.cache`, `phpcs.xml.dist`, `phpunit.xml.dist`, `tools/`, `docs/`, `config/`, `AGENTS.md`, `CLAUDE.md`, `ROADMAP.md`, `RELEASING.md`, `README.*.md`). Zip build now fully honours `.distignore`; all those paths are excluded from the production archive. `.distignore` updated to add `.gitignore`, `.phpunit.result.cache`, and `RELEASING.md`.
*   **Plugin Checker — PHPCS false positive** (`includes/server-side/class-queue.php`): `$table_exists_mem` is a `private static` class property, not a global variable. Added inline `phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound` with explanation to silence the false positive.

= 1.7.6 =
*   **Hotfix — null byte corruption** (`assets/css/admin.css`, `includes/admin/class-admin.php`, `includes/admin/traits/trait-admin-diagnostics-ajax.php`): Trailing null bytes (`0x00`) introduced by the file-editing toolchain caused PHP parse errors (`unexpected character 0x00`) on the live server. Stripped all trailing nulls from all source files. Full PHP/JS/CSS scan confirmed zero null bytes remaining.

= 1.7.5 =
*   **Hotfix — PHP parse error** (`includes/admin/class-admin.php`, line 1254): Three `\$` escape sequences in the cross-domain decoration checklist item were invalid PHP syntax outside a string context (bare `\` token). Corrected to `$link_decor_on` and `$domains_configured`. Plugin was fatal on sites where the cross-domain checklist card loaded.

= 1.7.4 =
*   **CSS audit — token coverage** (`assets/css/admin.css`): Added two new design tokens (`--clicktrail-border-medium: #c3c4c7` for WP medium-weight borders, `--clicktrail-radius-lg: 8px` for code-surface border-radius). Replaced all live hardcoded `#c3c4c7` (×3), `#646970` (×2), and status/notice color values with token references. Zero raw color values remain outside the `:root` block (excluding intentional surface-specific shades with no token equivalent).
*   **CSS audit — cascade fix** (`assets/css/admin.css`): Resolved duplicate `.clicktrail-help-tip` selector. The compact override (15×15 px, tighter margin) is now scoped to `.clicktrail-card__table .clicktrail-help-tip` instead of overriding the base definition globally.
*   **CSS audit — dead code removal** (`assets/css/admin.css`): Deleted orphaned `Setup Wizard (Phase 3)` and `Import/Export Section (Phase 3)` blocks (`clicktrail-wizard`, `clicktrail-wizard-step`, `clicktrail-wizard-progress`, `clicktrail-import-export`). Confirmed zero PHP/HTML references before removal. File reduced from 1174 to 1113 lines.
*   **Consent banner color** (`assets/css/clicutcl-consent.css`): Updated `.ct-btn-primary` from WP 4.x blue (`#0073aa`) to WP 5.7+ blue (`#2271b1`), and hover state from `#005177` to `#135e96`. Consent banner CTA now matches every other branded element in the plugin.

= 1.7.3 =
*   **Action Scheduler support** (`includes/server-side/class-queue.php`): `ensure_schedule()` now detects `as_schedule_recurring_action` at runtime and uses Action Scheduler's recurring action (group `clicktrail-delivery`, 300 s interval) when the library is present (WooCommerce 3.6+ or standalone). Falls back to WP-cron when AS is unavailable. `clear_schedule()` cancels both the AS group and the WP-cron hook so no orphaned entries remain after a scheduler switch.
*   **Uninstall cleanup** (`uninstall.php`): Added guarded `as_unschedule_all_actions` call so AS actions are cancelled on plugin deletion when the library is present.
*   **Syntax fix** (`trait-admin-diagnostics-ajax.php`): Escaped unescaped apostrophe in NitroPack diagnostic detail string that would cause a PHP parse error on sites with strict error reporting.

= 1.7.2 =
*   **NitroPack compatibility** (`includes/integrations/class-nitropack-compat.php` NEW): Detects `NITROPACK_VERSION` and registers two exclusion hooks — `nitropack_js_url_exclude` (URL-based API filter) and `script_loader_tag` (`data-nitropack-exclude="true"` attribute) — to prevent ClickTrail scripts from being postponed until user interaction.
*   **NitroPack diagnostic warning** (`trait-admin-diagnostics-ajax.php`): Added `NITROPACK_VERSION` to `detect_cache_conflict_labels()` and a dedicated `warn` finding in `build_conflict_scan_report()` explaining the JS postpone risk with verification steps.
*   **Core registration** (`class-clicutcl-core.php`): `NitroPack_Compat::register()` wired into `define_public_hooks()` after `Queue::register()`.
*   **pt-BR playbook — Padrão 5 rewrite** (`docs/guides/IMPLEMENTATION-PLAYBOOK.pt-BR.md`): Expanded webhook/CRM section documents the three-layer architecture (script → webhook middleware → CRM), full attribution field table including `gclid`/`fbclid`/`fbc`/`fbp`/`wbraid`/`gbraid`, PipeRun custom field ID requirement, `ct_ready` event pattern, and three common errors.
= 1.7.1 =
*   **Setup Wizard**: Added a 3-step onboarding wizard that fires automatically on first activation. Step 1 auto-detects active form plugins, WooCommerce, CMPs, and caching layers. Step 2 collects the GA4 Measurement ID. Step 3 confirms attribution is active with a quick-test link. All external admin notices are suppressed while the wizard is open. A permanent "Setup Wizard" link is added to the plugin action row on the Plugins screen.
*   **Activation fix**: `Setup_Wizard::init()` now registers before the preflight class check so the activation redirect fires reliably on all environments.
*   **Two-phase consent capture**: UTMs and click IDs are now buffered to `sessionStorage` immediately on page load before any consent banner fires. On consent grant the pending buffer is promoted to the attribution cookie, preserving first-touch even when the user accepts the banner on a later page.
*   **Call tracking MutationObserver skip**: The MutationObserver watching for dynamically inserted links now bails early when every new anchor has a skippable scheme (`tel:`, `mailto:`, `#`). Eliminates wasted debounce cycles from Dynamic Number Insertion tools such as CallRail, CallTrackingMetrics, and WhatConverts.
*   **GF / WPForms attribution field diagnostic**: The Diagnostics conflict scan now checks every active Gravity Forms and WPForms form for `ct_*` hidden fields. Forms without attribution fields surface a warning with a direct edit link. No new AJAX endpoints.
*   **Cross-domain decoration checklist warning**: The setup checklist now shows a `warn` state when link decoration is on but no allowed domains are listed, and an informational note about external payment providers when decoration is correctly configured.
*   **Cross-domain limitations documentation**: Added a "Cross-Domain Limitations" section to the Implementation Playbook and a payment provider table to the Integrations reference covering Stripe, PayPal, Mollie, and Square.
*   **Portuguese (pt-BR) Implementation Playbook**: Added `IMPLEMENTATION-PLAYBOOK.pt-BR.md` covering all rollout patterns including webhook/CRM integrations, the `window.ClickTrail` JS API field reference, and external checkout limitations.
*   **WP.org compliance**: Plugin zip folder renamed from `cth` to `click-trail-handler` to match the WordPress.org plugin slug requirement.
*   **Elementor Forms popup fix**: Attribution data is now injected reliably when an Elementor popup opens and when new form inputs appear in the DOM after initial page load.
*   **CI**: Fixed CodeQL workflow — removed PHP from the language matrix and updated action refs to v4.

= 1.7.0 =
*   **Hardening release**. No user-visible feature changes; addresses ten findings from the 1.6.0 internal code review.
*   Fixed admin QA mode cache-poisoning risk: `adminQaMode` is no longer baked into the localized attribution config where a full-page cache plugin could capture and serve it to anonymous visitors. Now a 1-hour `clicutcl_admin_qa` cookie set only for logged-in `manage_options` users.
*   Fixed minification-exclusion attributes to use the canonical names each tool actually reads: `data-no-optimize`, `data-noptimize`, `data-cfasync`, `data-no-defer`, `data-no-minify`.
*   Replaced `str_replace` script injection with regex-based injection robust to attribute order and whitespace.
*   Refactored `Gravity_Forms_Adapter` from ~660 lines into four focused classes: `Gf_Channel_Resolver`, `Gf_Form_Settings_Tab`, `Gf_Merge_Tags`, `Gf_Minification_Protector`. All public method signatures preserved.
*   Added PHPUnit unit-test suite for `Gf_Channel_Resolver` covering 10 classification rules.
*   Added HOOKS-REFERENCE.md clarifications on `ct_*` entry meta registration and channel label storage.


= 1.5.2 =
*   **Code quality (line endings)**: Normalized mixed line endings in the consent, attribution-token, and privacy handlers so standards checks and packaging behave consistently across environments.
*   **Code quality (PHPCS cleanup)**: Resolved the remaining coding-standards issues in those handlers and documented the intentional exceptions for signed-token Base64URL helpers and the required WordPress privacy eraser callback signature.
*   **Runtime behavior**: No functional changes intended; this patch is a maintenance and standards-compliance release.

= 1.5.1 =
*   **Release metadata**: Bumped the public plugin version to `1.5.1` and aligned the main release surfaces across the plugin header, WordPress readme, product readmes, and technical docs.
*   **Public release notes**: Cleaned up changelog wording to keep public release copy product-focused and competitor-neutral.
*   **Runtime behavior**: No functional runtime changes from `1.5.0`; this patch is a release-metadata and documentation alignment update.

= 1.5.0 =
*   **WooCommerce (HPOS compatibility)**: Declared compatibility with WooCommerce custom order tables during bootstrap and moved purchase dedup state onto Woo order APIs, so the core Woo purchase flow stays aligned with HPOS-capable stores.
*   **WooCommerce (purchase payload enrichment)**: Expanded the Woo purchase payload additively with `subtotal`, `tax_total`, `shipping_total`, `discount_total`, `discount_codes`, `status`, `order_currency`, `item_quantity`, plus richer item fields such as `product_id`, `sku`, `variant`, and `categories`.
*   **WooCommerce (storefront list + cart coverage)**: Added opt-in `woocommerce_storefront_events` support for `view_item`, `view_item_list`, `view_cart`, `add_to_cart`, `remove_from_cart`, and `begin_checkout` through ClickTrail's existing browser event layer, including Woo loop/widget/block heuristics plus `item_list_name` and `item_list_index` context where list attribution is available.
*   **GTM / sGTM compatibility**: Added a dedicated sGTM mode with tagging-server URL support, first-party or custom-loader GTM delivery, and an Events-tab setup wizard with preview probes and destination template hints for GTM-first rollouts.
*   **WooCommerce (post-purchase milestones)**: Added server-side `order_paid`, `order_refunded`, and `order_cancelled` milestone dispatch on top of the existing purchase pipeline. Milestones reuse the purchase payload builder, use deterministic event IDs, persist per-milestone order markers, and stay inside the same dispatcher, dedup, queue, and diagnostics model.
*   **WooCommerce (traceability)**: Persisted stored purchase and milestone trace snapshots on Woo orders and exposed a Diagnostics-only order trace lookup so maintainers can inspect payload snapshots and queue state without depending on a temporary debug window.
*   **Admin UX (readiness + diagnostics)**: Added a read-only setup checklist to the unified settings app and expanded Diagnostics with an interactive conflict scan, privileged backup export/import, and Woo order trace lookup.
*   **Delivery (selective adapter expansion)**: Added Pinterest Conversions API and TikTok Events API as first-class native delivery adapters, with registry-backed adapter labels and destination toggles in the admin experience.
*   **Architecture (feature registry)**: Introduced a shared internal feature registry so adapter choices, destination toggles, diagnostics labels, docs targets, and allowlists stop drifting across the admin, dispatcher, and runtime.
*   **QA / docs (smoke coverage)**: Added a lightweight smoke harness and feature test matrix tied to registry-backed smoke IDs, and updated the canonical admin, integrations, operations, data-model, and event-pipeline docs to reflect the shipped behavior.
*   **Admin UX (Woo guidance)**: Added and expanded the WooCommerce guidance in the unified Events tab so users can see where order attribution is stored, how purchase pushes work, what storefront and milestone events do, and where to verify results.
*   **Extensibility (Woo purchase filter)**: Added `clicutcl_woocommerce_purchase_payload` so integrators can extend the final Woo purchase payload in one place without replacing the integration boundary.
*   **Internationalization**: Extended the `pt_BR` translation coverage to the new settings, diagnostics, Woo trace, backup/restore, and selective-destination admin strings, and regenerated the runtime translation artifacts.
*   **Standards / deployment**: Included the WordPress.org packaging alignment, Plugin Check suppression cleanup, privacy-query hardening, and debug visibility improvements from the recent maintenance pass in the same public release.

= 1.3.9 =
*   **Privacy erasure safety**: Tightened how WordPress privacy export and erasure requests match ClickTrail event records to a person. `LIKE` fragments that include a stored `user_id` are now escaped correctly, which prevents wildcard characters from over-matching unrelated rows during personal-data cleanup.
*   **Privacy erasure performance**: Large privacy erasure requests no longer delete one event row at a time. Matching event IDs are now deleted in batches, which reduces database round-trips and makes privacy cleanup more practical on busy stores and lead-generation sites with larger event tables.
*   **Runtime performance (settings caching)**: Added a lightweight option-cache layer for frequently read plugin settings. Attribution checks, consent checks, attribution-token TTL resolution, tracking settings, and server-side delivery settings now reuse cached values instead of repeatedly calling `get_option()` during the same request.
*   **Runtime performance (conditional assets)**: The frontend consent bridge script now loads only when a page actually needs attribution capture, consent handling, or browser events. Sites that are not using those frontend runtime features avoid one unnecessary script load.
*   **Bootstrap performance**: The autoloader fallback that looks for `CLICUTCL\Core\Context` now remembers the successful file path instead of probing the same candidate locations on every page load.
*   **Debugging (token parsing)**: `base64url_decode()` now logs a diagnostic message to `error_log` when it receives an invalid base64 payload in debug mode, making broken or truncated attribution tokens easier to diagnose instead of failing silently.
*   **Debugging (database errors)**: Privacy erasure now surfaces `$wpdb->last_error` in the erasure response messages when deletion fails and `WP_DEBUG` is enabled, so site owners can see the database-level reason instead of a generic failure.
*   **Code quality (public runtime)**: Extracted consent-bridge config building into `build_consent_bridge_config()` and attribution config building into `build_attribution_config()`, making `enqueue_scripts()` shorter, easier to review, and easier to test.
*   **Code quality (event intake)**: Extracted per-event processing logic into `process_single_event()`, reducing `batch_events()` to a clean dispatch loop and isolating validation, translation, dedup, identity resolution, and delivery into a single-responsibility method.

= 1.3.8 =
*   **Attribution fallback (referrer classification)**: Added per-touch referrer classification for visits without UTMs or click IDs. ClickTrail now derives first-touch and last-touch `source` / `medium` from common search, social, and external referral domains, preserves the raw referrer, ignores internal subdomain hops, and keeps explicit tagged campaign signals as the winner when present.

= 1.3.7 =
*   **Sessions (dedicated SessionManager)**: Decoupled session tracking from attribution signal detection. Sessions are now managed by a standalone `SessionManager` module with a 30-minute inactivity timeout, independent of UTM or click-ID changes. `session_count` inside `runAttribution()` is no longer incremented on attribution signals — session lifecycle is driven purely by user activity.
*   **Sessions (separate storage)**: Session state (`session_id`, `session_number`, `session_started_at`, `last_activity_at`) is persisted in its own `ct_session` cookie and localStorage key, keeping attribution and session concerns fully separated.
*   **Sessions (backward compatibility)**: On first run the SessionManager seeds `session_number` from the existing `session_count` in the attribution payload, then stops writing to attribution storage. `session_count` remains available as an alias of `session_number` in all outward-facing payloads (dataLayer, API, REST, form/purchase dispatch).
*   **Sessions (API surface)**: Added `window.ClickTrail.getSession()` and `window.ClickTrailSession` for client-side access. `Identity.get()` now returns `session_number` alongside `session_id`. The dataLayer `ct_page_view` push includes `session_number`.
*   **Sessions (server-side)**: Added `Attribution_Provider::get_session()` to read the `ct_session` cookie server-side. Form submission and purchase dispatch contexts now include `session_id` in event metadata when available.
*   **Sessions (consent)**: Session state is cleared alongside attribution data when consent is denied or revoked, and the `clearData()` API method clears both stores.

= 1.3.6 =
*   **Forms (Ninja Forms)**: Replaced the speculative Ninja Forms storage path with an explicit submission-extra contract on `extra.clicktrail_attribution`, added normalized payload handling with safe fallback to the current request attribution payload, and surfaced stored attribution in the Ninja Forms submission detail UI through `nf_react_table_extra_value_keys`.
*   **Forms (Elementor Forms)**: Added a native Elementor Pro forms adapter using the official `elementor_pro/forms/new_record` submission hook. ClickTrail now logs Elementor form submissions on the same adapter contract as the other supported form plugins, reads submitted `ct_*` attribution fields when present, and falls back to the current consent-aware attribution payload when explicit hidden fields are not part of the form.
*   **Attribution coverage (modern campaign + browser IDs)**: Expanded the capture schema beyond classic UTMs so ClickTrail now preserves `utm_id`, `utm_source_platform`, `utm_creative_format`, and `utm_marketing_tactic`, plus top-level browser/platform identifiers such as `fbc`, `fbp`, `ttp`, `li_gc`, `ga_client_id`, and `ga_session_id`. The same broader field set now flows through the runtime, browser events, WooCommerce checkout persistence, canonical URL cleanup, and cross-domain attribution token allowlists where appropriate.
*   **Browser events (capability gating)**: Split browser event collection from browser delivery transport. `event_v2` now acts as the single capability gate for loading and booting `clicutcl-events.js`, while REST delivery remains a separate transport concern. Disabling browser event collection now stops browser event listeners and `dataLayer` pushes from the events runtime without affecting attribution capture.
*   **Consent (frontend attribution parity)**: Switched the attribution runtime to the shared consent bridge contract instead of hardcoding the legacy `ct_consent` cookie and banner-only events. Cookiebot, OneTrust, Complianz, GTM, and custom bridge integrations now unblock attribution correctly when consent is granted.
*   **Privacy / retention (client storage)**: Replaced indefinite localStorage attribution persistence with a TTL-bound mirror that honors `cookie_days`, drops legacy no-expiry payloads, and clears client-side attribution state when consent is denied or revoked.
*   **Attribution schema (metadata consistency)**: Standardized attribution metadata on the same `ft_` / `lt_` prefix contract used by the rest of the payload. The runtime and PHP provider now normalize legacy `first_*` / `last_*` metadata aliases back to canonical keys such as `ft_touch_timestamp` and `ft_landing_page`, and the form injector now targets the canonical metadata fields consistently.
*   **Identity enrichment (forms and purchases)**: Added consent-aware identity resolution to form submission and WooCommerce purchase dispatch paths. Server-side form and purchase events now carry the same top-level `identity` payload used by REST intake, with a temporary `meta.identity` mirror kept for backward compatibility with older collectors.
*   **Forms (Fluent Forms — hooks)**: Registered both slash-style (`fluentform/form_element_start`, `fluentform/submission_inserted`) and underscore-style legacy hooks so the adapter fires on Fluent Forms v5+ and on installations still running v4 or below. A static dedup guard in `on_submission` ensures the entry is logged exactly once even if both aliases fire.
*   **Forms (Fluent Forms — meta persistence)**: Implemented the previously commented-out Fluent Forms entry meta write. Attribution values are now inserted into `fluentform_submission_meta` via `wpFluent()` on each submission, making them accessible from the Fluent Forms entry detail view and its API. The insert is wrapped in a try/catch so a table-level error does not block ClickTrail's own event log.
*   **Forms (Gravity Forms — entry meta registration)**: Added `gform_entry_meta` filter registration in the Gravity Forms adapter. Each attribution key (prefixed `ct_`) is now declared as a named meta entry, making attribution values visible in the Gravity Forms entry detail screen, exportable via the CSV/XLSX export tool, and searchable in the entries list — matching the behaviour of first-class Gravity Forms fields.
*   **Admin (Diagnostics — copy)**: Renamed "Recent v2 Intake Events" card to "Recent Event Intake" and updated its description and empty-state text to remove internal "v2" terminology from user-facing diagnostic output.
*   **Admin CSS (settings app utilities)**: Added `.clicktrail-setting-block` (with `.is-disabled` opacity state), `.clicktrail-setting-label` (inline-flex label layout), `.clicktrail-provider-block` (provider row separator), `.clicktrail-ops-links` (action link row), and `.clicktrail-diagnostics-grid--compact` (inset grid variant) to support the unified settings app layout.

= 1.3.5 =
*   **Admin UX (final unified settings app)**: Replaced the split Settings API + separate advanced tracking UI with one modern WordPress-native settings shell for the main ClickTrail settings screen.
*   **Admin IA (capability tabs)**: Reorganized settings into four capability-based tabs -- `Capture`, `Forms`, `Events`, and `Delivery` -- so users can configure ClickTrail by use case instead of internal implementation layers.
*   **Admin copy (humanized language)**: Removed user-facing `Tracking v2` terminology from the main settings flow and translated developer-first labels into product-facing language.
*   **Admin compatibility (legacy URLs)**: Added alias routing for old admin tabs so `general`, `whatsapp`, `trackingv2`, `advanced`, `server`, and `destinations` continue to land in the correct new capability tab.
*   **Admin persistence (grouped save layer)**: Added unified admin AJAX load/save endpoints that group settings by capability in the UI while still writing back to the existing option stores.
*   **Admin UX (delivery summary)**: Added a lightweight Delivery health summary inside Settings with queue backlog, last dispatch, last error, debug state, and direct links to Logs and Diagnostics.
*   **Admin UX (unified identity)**: Replaced `wp.components` Card/CardBody/CardHeader in the Advanced tab React UI with the same `.clicktrail-card` shell used by all PHP-rendered settings tabs — eliminating the two-identity split.
*   **Admin UX (tab consolidation)**: Reduced settings tabs from six to four — Attribution (core capture + JS fallback + cross-domain + WhatsApp), Consent, Destinations, and Advanced — each organized around a clear user intent rather than internal system names.
*   **Admin UX (WhatsApp)**: Moved WhatsApp settings from a standalone tab into a collapsible card on the Attribution tab, where it belongs alongside the other capture settings it shares an option group with.
*   **Admin UX (Destinations tab)**: Destinations tab now presents GTM, server-side delivery, and advertising platform toggles (Meta, Google, LinkedIn, Reddit, Pinterest) as a single unified configuration surface — two PHP forms followed by the React v2 destinations card.
*   **Admin UX (humanized v2 notice)**: Replaced the generic "advanced tracking" notice with a plain-language explanation of why the Advanced tab exists and when it is needed, removing the term "v2" from user-facing copy.
*   **Admin UX (tab icons)**: Updated tab icons to reflect each tab's purpose — chart-area for Attribution, privacy shield for Consent, share for Destinations, admin-tools for Advanced.
*   **Admin JS (React card shell)**: Rewrote `admin-tracking-v2.js` to render cards using our `.clicktrail-card` / `.clicktrail-card__body--react` CSS classes, with icon + title + description in the header matching PHP-rendered cards exactly.
*   **Admin JS (React controls)**: Gave each card a contextual icon, humanized title, and plain-English description. Feature flags card explains each flag inline via `help` text.
*   **Admin CSS**: Added `.clicktrail-card__body--react` padding, row separators, and overrides for `wp.components` ToggleControl, TextControl, and TextareaControl to match our design tokens (border radius, border colour, blue focus ring, toggle pill sizing).

= 1.3.4 =
*   **Admin UX (tab navigation)**: Renamed all settings tabs to plain-English labels — Attribution, Consent, Channels, Destinations, Advanced, Diagnostics — replacing internal developer slugs.
*   **Admin UX (tab consolidation)**: Merged GTM and Server-side tabs into a single Destinations tab, reducing tab count and grouping related delivery settings together.
*   **Admin UX (card layout)**: Replaced flat settings sections with a card-based layout — each card carries an icon, title, and description, with a hairline border and white background matching WP admin conventions.
*   **Admin UX (status bar)**: Added a summary status bar on the Attribution tab showing live pills for Attribution, Consent Mode, JS Capture, Cross-domain, and Server-side states.
*   **Admin UX (sticky save)**: Added a sticky save bar that remains visible at the bottom of the viewport while scrolling through long settings pages.
*   **Admin UX (collapsible cards)**: Advanced sections (Cross-domain, Channels) can be collapsed to reduce visual noise; collapsed state driven by `aria-expanded` and a CSS `is-collapsed` toggle.
*   **Admin UX (conditional dimming)**: Dependent fields dim and disable when their parent toggle is off — JS injection controls mutation observer and field overwrite rows; link decoration controls allowed domains, skip-signed, and cross-domain token; WhatsApp controls the append-attribution row; consent toggle controls all consent sub-fields.
*   **Admin UX (diagnostics)**: Redesigned Diagnostics page with a stats-first grid (Queue Backlog, Last Dispatch, Last Error, Debug Logging) followed by action cards for testing, logging, data management, and telemetry.
*   **Admin UX (field labels)**: Rewrote all settings field labels in plain English throughout Attribution and Consent tabs.
*   **Admin UX (destinations card)**: Tracking v2 Destinations card (Meta, Google, LinkedIn, Reddit, Pinterest) now renders on the Destinations tab in addition to the Advanced tab.
*   **Admin JS**: Added `admin-settings.js` to handle collapsible card toggle behaviour and all conditional field dependency bindings on settings screens.
*   **Admin CSS**: Comprehensive stylesheet additions covering cards, status pills, save bar, diagnostic stat tiles, dimmed rows, field inputs, and responsive breakpoints.

= 1.3.3 =
*   **Admin reliability**: Fixed `clicutcl_attribution_settings` persistence so checkbox/toggle values on the settings page now save correctly alongside scalar fields like `enable_attribution` and `cookie_days`.
*   **Forms integration**: Fixed Fluent Forms hook registration for `fluentform_form_element_start` to accept the documented single argument, preventing fatal errors on form render.
*   **Security (API hardening)**: Added request body-size guards (128KB) on public webhook and lifecycle endpoints to prevent oversized payload abuse (HTTP 413 on overflow).
*   **Security (authz)**: Closed batch endpoint nonce bypass by requiring `manage_options` capability on the wp_rest nonce path.
*   **Security (XSS)**: Replaced consent-banner `innerHTML` rendering with safe DOM API construction to eliminate DOM XSS sinks in active consent UI.
*   **Security (legacy exposure)**: Removed deprecated `assets/js/ct-consent.js` from runtime and added ignore rules to prevent accidental reintroduction.
*   **Security (secrets hygiene)**: Implemented masked admin reads and write-only secret updates for tracking v2 settings (`secret`/`token` fields are no longer exposed back to admin clients).
*   **Security (optional at-rest protection)**: Added optional secret encryption-at-rest for tracking settings (`security.encrypt_secrets_at_rest`) with transparent decrypt-on-read.
*   **Privacy (data minimization)**: Replaced raw WordPress user IDs in dataLayer payloads with salted one-way SHA-256 hashes.
*   **Privacy (WP compliance)**: Added personal data exporter/eraser integration for ClickTrail tracking data via WordPress privacy APIs.
*   **Consent (runtime architecture)**: Added consent bridge layer (`clicutcl-consent-bridge.js`) to normalize consent resolution across built-in banner, CMPs, GTM Consent Mode, and custom implementations.
*   **Consent (event gating)**: Updated event initialization to wait for resolved consent and added dispatch-time guard to block event pushes when consent is denied/unresolved.
*   **Consent (admin controls)**: Added consent source and CMP timeout settings, with sanitization and localized runtime bridge configuration.
*   **GTM behavior**: Preserved unconditional GTM snippet loading while aligning ClickTrail event initialization with resolved consent signals.
*   **Attribution integrity**: Hardened attribution token flows and canonical click-ID normalization (including Snapchat aliases to canonical `sccid` handling).
*   **Attribution coverage**: Aligned click-ID handling across parsing/mapping paths for Google, Meta, TikTok, Microsoft, Twitter/X, LinkedIn, Snapchat aliases, and Pinterest identifiers.
*   **WooCommerce logic**: Fixed fallback attribution path so flat-cookie attribution is normalized into first/last touch before purchase payload flattening.
*   **Forms integration**: Corrected Ninja Forms attribution global usage to `window.ClickTrail` API.
*   **Admin UX**: Replaced dead PII warning CTA with actionable links to diagnostics/settings.
*   **Internationalization**: Replaced hardcoded admin error strings with translatable strings for consistency with WP i18n conventions.
*   **Technical debt (modularization)**: Reduced blast radius by splitting oversized classes into bounded-context traits (admin pages/diagnostics, tracking controller security/debug/token internals, log controller WA/runtime internals).
*   **Technical debt (legacy cleanup)**: Removed deprecated runtime integration class (`includes/integrations/class-form-integrations.php`) and updated ignore policy for archived artifacts.
*   **Standards (boolean coercion fix)**: Fixed toggle sanitization so string values like `"false"` no longer coerce to enabled.
*   **Standards (style consistency)**: Refactored `class-site-health.php` to consistent WordPress/PSR-friendly formatting and safer input handling patterns.
*   **Standards (enforcement)**: Added `phpcs.xml.dist`, typing policy documentation, and QA script to enforce consistent repository typing policy.
*   **Docs hygiene**: Removed duplicated Portuguese section in `README.md` to prevent documentation drift.
*   **Docs truth-alignment**: Updated `readme.txt` claims to match shipped click-ID and consent-mode behavior exactly.

= 1.3.2 =
*   **Security**: Enforced signed-token authorization for WA click ingestion, removed Origin/Referer as a security control, and added trusted-proxy-aware client IP handling.
*   **Security**: Closed WA ingestion bypass paths and aligned authorization checks across endpoints.
*   **Performance**: Removed hot-path option churn for WA diagnostics and moved attempt/dispatch traces to debug-only transient ring buffers.
*   **Performance**: Eliminated per-request schema checks on the WA hot path with DB readiness flags and fail-fast handling when DB is not ready.
*   **Reliability**: Added canonical click-ID normalization boundary (`lt_/ft_` to canonical IDs) before allowlist/signing flow.
*   **Reliability**: Hardened settings sanitization with schema+merge behavior to prevent silent setting loss on partial saves.
*   **Admin UX/Perf**: Scoped admin script loading to relevant screens instead of global wp-admin enqueue.
*   **Polish**: Escaped DB-derived admin table output (`created_at`) and standardized safe output rendering.
*   **Developer Experience**: Added debug-gated JS logging to avoid production console noise by default.
*   **API**: WA endpoint contract now requires a signed `token` for accepted writes.
*   **Internal**: Diagnostics storage now uses transient ring buffers instead of hot-path option-array rewrites.
*   **Internal**: Added hardening config surfaces for token TTL, nonce replay limits, trusted proxies, and diagnostics buffering/throttling.

= 1.3.1 =
*   **Performance**: Implemented conditional loading for `clicutcl-events.js` tracking script—now only loads on the front-end (excluding feeds, robots, and admin) to minimize overhead.
*   **Security (Safety Check)**: Added existence check for `WooCommerce` class before instantiating the integration, preventing potential hooks from loading unnecessarily.
*   **Improvement (Extensibility)**: Introduced `clicutcl_should_load_events_js` filter to allow granular control over when tracking scripts are enqueued.

= 1.3.0 =
*   **Feature (Cache Resurrection)**: Implemented Client-Side Field Injection (`enable_js_injection`) to automatically populate hidden form fields via JavaScript, ensuring accurate attribution even on fully cached pages (WP Rocket, Cloudflare, local caching).
*   **Feature (Cross-Domain)**: Introduced Link Decoration (`enable_link_decoration`) to safely pass attribution parameters to allowed domains, with automatic support for all subdomains of the current site.
*   **Feature (Bot Protection)**: Added advanced bot detection to prevent attribution pollution from crawlers, webdrivers, and headless browsers.
*   **Feature (DX/Insight)**: Integrated with WordPress Site Health to provide proactive diagnostics on caching conflicts and cookie blocking.
*   **Feature (Dashboard)**: Added "ClickTrail Status" dashboard widget for real-time tracking health visibility.
*   **Improvement**: Added JS Fallback for WooCommerce Checkout, ensuring order attribution is captured even when server-side cookies are stripped.
*   **Improvement**: Renamed the primary settings submenu from "ClickTrail" to "Settings" to eliminate duplicate labels and improve UX.
*   **Improvement**: Added official Portuguese (Brazil) translation (`pt_BR`) covering Admin, Consent Banner, and Site Health.
*   **Improvement**: Fully refactored attribution frontend to remove jQuery dependency and expose a modern JS API (`window.ClickTrail`).

= 1.2.3 =
*   **Fix**: Fixed Short Description formatting in readme.txt to comply with WordPress.org plugin guidelines.
*   **Improvement**: Removed deprecated `load_plugin_textdomain()` call—WordPress 4.6+ handles translations automatically for plugins hosted on WordPress.org.
*   **Improvement**: Added PHPCS ignore comment for intentional direct database query on custom plugin table.

= 1.2.2 =
*   **Fix**: Resolved critical autoloading issues on Linux/Unix environments (case-sensitive paths) to prevent Fatal Errors during activation.
*   **Fix**: Implemented strict PHP interface compatibility for all Form Adapters (CF7, WPForms, Gravity Forms, Ninja Forms, Fluent Forms) to resolve fatal errors on PHP 8+.
*   **Fix**: Added robust "preflight" checks in the boot sequence to safely deactivate the plugin if files are corrupted or missing, instead of crashing the site.
*   **Improvement**: Enhanced autoloader performance and added fallback for mixed naming conventions.
*   **Improvement**: Updated plugin metadata and readme for better WordPress.org validation compliance.

= 1.2.1 =
*   **Fix**: Fixed scroll tracking to use GTM's built-in variable names (`gtm.scrollThreshold`, `gtm.scrollUnits`, `gtm.scrollDirection`) instead of custom Data Layer Variables, making GTM setup simpler and more reliable.
*   **Fix**: Fixed scroll percentage calculation bug that prevented scroll events from firing. Changed from string-based property access to direct property access with cross-browser fallbacks for better reliability.
*   **Improvement**: Renamed `time_on_page` event to `user_engagement` with descriptive engagement levels (quick_view, browsing, engaged, interested, highly_engaged) and added detailed parameters (`engagement_time_msec`, `time_label`, `time_threshold`) for better analytics insights.
*   **Fix**: Corrected typo in settings class name (`Attribution_Settings`) for consistency.
*   **Docs**: Updated readme.txt and README.md with benefit-focused messaging emphasizing ROI and business value over technical features.


= 1.2.0 =
*   **Security**: Hardened AJAX handlers with strict WhatsApp URL validation and optimized PII risk logging using nonce verification and state checks.
*   **Feature**: Introduced Custom Database Table (`wp_clicutcl_events`) for scalable event logging, removing reliance on Custom Post Types.
*   **Feature**: Implemented REST API Log Endpoint (`/wp-json/clicutcl/v1/log`) for faster and lighter tracking requests.
*   **Feature**: Added Admin Log Viewer (`ClickTrail > Logs`) to view events from the custom database table.
*   **Feature**: Implemented Automated Database Cleanup (Cron) to keep the events table healthy.
*   **Refactor**: Major architectural improvements including Namespaced Admin class, decoupled AJAX Log Handler, and extracted CPT registration.
*   **Refactor**: Standardized Integrations (WooCommerce & Forms) into namespaced classes (`CLICUTCL\Integrations`), cleaning up the global namespace and dependencies.
*   **Refactor**: Centralized settings logic (`Attribution_Settings`) and Attribution Utilities (`Utils\Attribution`) for better maintainability.
*   **Fix**: Fixed GTM Data Layer variables for Scroll Tracking—now uses GTM's built-in variable names (`gtm.scrollThreshold`, `gtm.scrollUnits`, `gtm.scrollDirection`) plus `percent_scrolled` for GA4 compatibility. No custom Data Layer Variables needed in GTM!
*   **Fix**: Fixed scroll percentage calculation bug that prevented events from firing. Changed from string-based property access to direct property access with cross-browser fallbacks.
*   **Fix**: Improved engagement tracking by renaming `time_on_page` event to `user_engagement` with descriptive engagement levels (quick_view, browsing, engaged, interested, highly_engaged) and added `engagement_time_msec`, `time_label`, and `time_threshold` parameters.
*   **Cleanup**: Removed legacy `clicutcl_wa_click` Custom Post Type and associated AJAX handlers.
*   **Cleanup**: Removed `CLICUTCL\Ajax\Log_Handler` and `CLICUTCL\Post_Types\WhatsApp_Click` classes.

= 1.1.1 =
*   Refreshed readme copy and release guidance to align WordPress.org listing with latest documentation.
*   Prepared for updated screenshots/assets to keep plugin visuals accurate.

= 1.1.0 =
*   Added comprehensive Event Tracking (Searches, Downloads, Scroll Depth, Time on Page).
*   Added Server-side Event Tracking for User Login, Signups, and Comments.
*   Implemented Google Consent Mode v2 support with region-specific defaults.
*   Added manual Google Tag Manager (GTM) Container ID injection.
*   Refactored codebase for better modularity and performance.
*   Enhanced WooCommerce integration with "Source" column and detailed meta box.

= 1.0.0 =
*   Initial release with attribution capture, consent banner, and integrations for WooCommerce, Contact Form 7, Fluent Forms, and WhatsApp.
