=== Site Notice – Announcement & Privacy Bar ===
Contributors: tmd, freemius
Tags: announcement bar, privacy notice, cookie notice, marketing banner, notification bar
Requires at least: 5.8
Tested up to: 6.9
Stable tag: 3.59
License: GPLv2 or later

Lightweight announcement bar and privacy notice for WordPress. Display targeted messages, manage cookie consent, and track engagement.

== Changelog ==

= 3.59 =
* Security: stored URL options (notice link, button, privacy policy and lead-consent privacy links, webhook and custom WhatsApp icon URLs) are now validated on save and restricted to safe schemes (http, https, mailto, tel). Unsafe schemes such as javascript: and data: are rejected.
* Security: the frontend now re-validates every link destination before use, so unsafe URLs saved by an earlier version can no longer become active links.
* Security: the admin Live Preview builds the custom WhatsApp icon as a DOM element instead of raw HTML, preventing a crafted icon URL from injecting script into the settings screen.
* Security: CSV exports (leads and consent log) now neutralise spreadsheet formula injection, so submitted text beginning with =, +, -, @ opens as literal text. Hebrew and English content is unaffected.
* Security: lead-notification recipient and webhook settings now require settings/leads permission, so a delegated user with only privacy permissions can no longer redirect lead notifications.
* Security: client IP detection now uses REMOTE_ADDR by default. Forwarded headers (Cloudflare / reverse proxy) are honoured only when explicitly enabled via the SNT_TRUSTED_PROXY constant or the snt_trust_proxy_headers filter, closing a rate-limit bypass.
* Security: abuse rate limits are no longer keyed on the browser User-Agent, which could be varied to obtain unlimited quota.
* No changes to features, design, layout, saved settings or frontend appearance.

= 3.58 =
* Design tab: fixed the admin mobile layout so compact controls (Theme colors, border width+color) wrap onto a shared row instead of stacking into near-empty full-width rows; tidier spacing on small screens. Desktop layout unchanged.
* Design tab: Background Color and Background Opacity are now shown together on one row (color first) instead of the opacity being hidden inside the collapsed gradient section.
* Live Preview: added Desktop / Mobile preview modes — a viewport toggle that shows the announcement bar at a phone width without leaving the editor.
* Live Preview: added a Desktop Preview modal ("Full Preview") that opens the live preview at true desktop width. It reuses the same live preview (renderer, unsaved updates, notice selector, Active/Draft status, animation/rotation, lead-form and privacy previews) — no separate preview.
* New: Display Layer control for the announcement bar — Auto (unchanged default), Above floating widgets, Below floating widgets, or a Custom z-index — to position the bar relative to chat, WhatsApp, accessibility, and back-to-top widgets. Existing sites are unaffected until changed.
* Navigation Indicators: added decimal border width (finer than the previous whole-number steps).
* Navigation Indicators: added Inner / Outer border position (Outer draws a ring around dots/pills).
* Navigation Indicators: added an explicit Direction control (Auto / LTR / RTL); Auto preserves the existing behavior.
* Navigation Indicators: added a vertical position (offset) control for the indicator row.
* Fix: Classic Dots border now renders on the live site to match the Live Preview (previously a configured border appeared only in the preview).
* All additions are backward compatible — defaults reproduce 3.55 behavior, and no saved settings, option keys, or existing controls were changed.

= 3.55 =
* Changed admin settings save transport to a single JSON payload to avoid server max_input_vars limits on large Premium configurations.

= 3.54.1 =
* Fixed admin settings save failure on large Premium configurations by prioritizing AJAX action/nonce fields and preventing partial saves when requests are truncated.

= 3.54 =
* Added Modern Progress Pills rotation indicator style with smooth CSS-driven active progress, while keeping Classic Dots fully backward compatible.
* Unified the rotation indicators into one design system: Classic Dots and Progress Pills are now two styles of the same indicator, sharing colors, size, spacing, opacity, transition, alignment and hover controls across the frontend and the live preview. Renamed the Design card to "Navigation Indicators" with style-aware controls (glow, pulse, border, active size and hover scale are Classic-only).

= 3.53 =
* Updated bundled Freemius WordPress SDK to 2.13.2.
* Retained the 3.52 Freemius deployment compatibility refactor with a reduced main plugin file size.
* Confirmed the Smart Exposure module loader uses the plugin root path after the modular split.
* No feature behavior changes.

= 3.52 =
* Freemius deployment compatibility improvement.
* Reduced main plugin file size by extracting large internal modules into dedicated include files.
* Preserved existing functionality while reducing preprocessing load during Freemius deployment.
* Accessibility hardening improvements from 3.51 retained.

= 3.51 =
- Accessibility hardening: improved keyboard focus visibility (admin form controls), added table header semantics (scope="col") on admin data tables, and selected accessible labels (help-tip markers). Existing reduced-motion support retained. No changes to features, UI, licensing, Privacy Bar, or frontend behavior.

= 3.50 =
- Internal: extracted the large inline admin settings JavaScript into an external asset (`assets/admin/admin-settings.js`) loaded only on the Site Notice settings screen, reducing the size of the main plugin file. No change to behavior, features, or licensing.

= 3.49 =
- Fixed announcement message whitespace rendering so consecutive spaces entered in the editor are preserved consistently in Live Preview and frontend output.

= 3.48 =
* Compatibility: Freemius integration alignment improvements — moved the Freemius SDK to `vendor/freemius/`, relocated the integration snippet to the top of the plugin file, and hardcoded the product ID and public key per Freemius deployment recommendations. No change to plugin behavior, licensing flows, or Pro gating.
* Version: Plugin promoted to 3.48.

= 3.47 =
* Compatibility: Migrated uninstall handling from `uninstall.php` to a Freemius `after_uninstall` callback, satisfying Freemius deployment packaging requirements.
* Behavior unchanged: uninstall preserves all Site Notice data — settings, leads, analytics, consent logs, exposure logs, roles, and capabilities are not removed. A future "delete data on uninstall" option may be introduced separately.
* Version: Plugin promoted to 3.47.

= 3.46 =
* Improvement: Pro — Freemius pricing screen now displays annual plans as a single yearly price (e.g. "$149/year") instead of a calculated monthly equivalent (e.g. "$12/mo billed annually"), accurately reflecting Site Notice's annual-only billing model.
* Improvement: Freemius licensing and update-flow stability — sync, disconnect, reconnect, and quota enforcement verified across all plan tiers (Starter / Business / Professional).
* Internal: release-readiness and packaging consistency improvements.
* Version: Plugin promoted to 3.46.

= 3.45 =
* Fix: Pro — WhatsApp preset now uses api.whatsapp.com/send instead of the wa.me shortener, preventing emoji corruption on desktop / WhatsApp Web caused by the intermediate redirect step.
* Fix: Pro — WhatsApp prefilled-message fields now apply a list-independent supplementary-plane encoder at save time, guaranteeing 4-byte emoji (e.g. 👋) are stored as safe numeric entities on utf8 / utf8mb3 database tables regardless of the installed WordPress version's emoji list.
* Improvement: Pro — Master Toggle enhanced with a scoped pulse/breathing animation (off = gray, on = active color) and a larger, visually accented helper text; prefers-reduced-motion respected.
* Improvement: Pro — Navigation Dots auto-enable on 2+ active notices with an explanatory modal; manual opt-out respected for the session.
* Improvement: Pro — Live Preview header ⓘ info button opens a lightweight popover with a color-coded draft / active legend.
* Version: Plugin promoted to 3.45.

= 3.44 =
* Fix: WhatsApp prefilled-message emoji (e.g. 👋) now survives correctly on desktop / WhatsApp Web. The plugin now sends visitors to api.whatsapp.com/send instead of wa.me so the intermediate redirect that was corrupting 4-byte emoji is bypassed. Mobile behavior is unchanged.
* Fix: WhatsApp prefilled-message fields now use a list-independent supplementary-plane encoder at save time, guaranteeing emoji are stored as numeric entities regardless of the installed WordPress version's emoji list — prevents silent truncation on utf8 / utf8mb3 database tables.
* Improvement: Pro — Master Toggle area enhanced with scoped breathing/pulse effect (off=gray, on=active-color) and a larger, clearer helper text with a visually accented "must be active" phrase; prefers-reduced-motion respected.
* Improvement: Pro — Navigation Dots label corrected to canonical "הצג נקודות ניווט"; dots are now auto-enabled when 2+ real active notices exist, with an informational modal explaining the behavior; manual opt-out is respected for the current session.
* Improvement: Pro — Live Preview header now includes a small ⓘ info button that opens a lightweight popover explaining preview vs. live-site behavior, including a color legend for draft and active indicators.
* Improvement: Pro — Dots auto-enable modal buttons updated to the plugin's rounded .sna-btn style for visual consistency.
* Version: Plugin promoted to 3.44.

= 3.43 =
* New: Form Builder Visual RTE — Block Title and Block Content fields now display selection-based Bold editing via a contenteditable visual editor; raw ** markers are no longer visible inside the builder editor.
* Improvement: Form Builder alignment synchronization — editor fields now immediately reflect chosen alignment, consistent with Secondary Message behavior.
* Improvement: Form Builder block title default weight — title no longer appears bold by default; bold is applied only when explicitly enabled by the user.
* Improvement: Secondary Message formatting persistence — align and emphasis settings now persist correctly for notice slots 6–10.
* Improvement: Tooltip modernization and cleanup polish — Rules Markdown, Leads filter dropdowns, and additional admin controls migrated to the unified Mini Tooltip system.
* Internal: Various UX and editor consistency improvements across Lead Form and Registration form builders.
* Version: Plugin promoted to 3.43.

= 3.42 =
* Improvement: Tooltip system — completed modernization of all admin UI hint tooltips from native browser title="" to the unified Mini Tooltip (data-sna-tip) system; Rules notice-picker labels now strip Markdown syntax; Leads filter dropdowns, WA country-code input, position grid, visual cards, radius combo, expand/collapse all, lead preset lock, conversion log select-all, users locked row, and notice navigator controls all migrated.
* Version: Plugin promoted to 3.42.

= 3.41 =
* Improvement: Leads mobile toolbar — action row (All Statuses / WA / Export CSV / Bell) visible box edges forced to align with Row 1 (Search / All Alerts / All Time) via final-authority cell-fill and input appearance normalisation; All Statuses end edge, WA start edge, Bell trailing edge, and all inter-control gaps now match Row 1 reference at every mobile viewport (320–480 px), RTL and LTR.
* Improvement: Admin CSS — appended Round 8 override block as the last rule in admin.css to guarantee no earlier content-width or native-input chrome rule can re-introduce visual drift; no layout, span, grid-template, or desktop change.
* Internal: Packaging-only release; no functionality, JS, PHP logic, Smart Exposure, or Leads data changes.
* Version: Plugin promoted to 3.41.

= 3.40 =
* New: Admin Design System Refresh — modernized navigation with Lucide inline SVG icons for every top-level tab (megaphone, git-branch, users, shield-check, palette, sliders-horizontal, bar-chart-3, radar, inbox, crown, zap).
* New: Smart Exposure dedicated top-level tab — relocated from the Behavior tab into its own first-class navigation destination with radar icon; all existing monitor, diagnostics, sources, AJAX, and permission logic preserved byte-for-byte.
* New: Navigation group separators — subtle visual dividers between System Management (Announcements, Rules, Users), Configuration (Privacy, Design, Behavior), Insights (Analytics, Smart Exposure, Inquiries), and Commercial (Pro, Upgrade) tab groups.
* Improvement: Premium active tab pill — enhanced active state with stronger visual contrast, refined hover/focus transitions, and improved keyboard focus rings across the entire tab bar.
* Improvement: Header design system — cohesive design language across navigation, language selector, save button, status badge, and version badge; unified spacing and shadow hierarchy.
* Improvement: Save button — Lucide save icon added alongside label; improved dirty-state transitions and focus styling.
* Improvement: Language selector — refined dropdown trigger with globe icon; improved open/close animation and option row styling.
* Improvement: Mobile touch targets — minimum 44px touch areas on tab buttons and tabbar controls; improved visual hierarchy and spacing at all breakpoints.
* Improvement: RTL/LTR — all new styles use CSS logical properties exclusively; verified Hebrew and English modes.
* Version: Plugin promoted to 3.40.

= 3.39 =
* New: Smart Exposure Monitor — primary admin UI for tracking AI, search, and social crawler access to the announcements REST endpoint.
* New: Bot/User-Agent detection — classifies known crawlers (GPTBot, ChatGPT-User, OAI-SearchBot, ClaudeBot, PerplexityBot, Googlebot, Bingbot, Applebot, FacebookExternalHit, LinkedInBot, WhatsApp, TelegramBot, Bytespider) and generic unknown bots; normal browser traffic is excluded.
* New: Exposure Sources panel — groups detected crawlers by name and type (AI / Search Engine / Social Crawler / Unknown) with per-source counts.
* New: Recent Exposure table — Time, Source, Type, and Notice columns; 50 / 100 / 250 row selector; newest-first; RTL/LTR safe; mobile responsive.
* New: Health panel — six live indicators (REST exposure available, JSON-LD ready, Schema ready, AI ready, Search ready, Robots compatibility).
* New: Smart Exposure Control Card — prominent enable/disable toggle at the top of the Behavior tab with live Enabled/Disabled status badge; replaces the previously buried toggle.
* New: Monitor utility actions — Refresh, Clear Exposure Data, Clear Diagnostics, and Clear All Data (with multi-step confirmation); all admin-only and nonce-protected.
* New: Advanced Diagnostics section — existing Signals diagnostics, system status, and recent activity consolidated under an open-by-default collapsible panel.
* Improvement: Diagnostics history selector upgraded from 10 / 25 / 50 to 50 / 100 / 250 rows; up to 250 entries now embedded per page load.
* Improvement: Smart Exposure Monitor — Phase 1 disclaimer uses precise "Identified by User-Agent (unverified)" wording in English and Hebrew; no unverified identity claims.
* Improvement: Exposure log retention — dedicated sn_exposure_log DB table (250-row cap, daily prune cron, self-healing upgrade path).

= 3.38 =
* Improvement: Signals / Smart Exposure admin — activity history now shows all 50 retained entries with a compact 10 / 25 / 50 row-size selector; helper text accurately reflects the visible count vs. retained total.
* Improvement: Signals / Smart Exposure admin — channel legend added below the activity table explaining Site Page, Site Structure, External Exposure, and Not Exposed in plain language.
* Improvement: Signals / Smart Exposure admin — REST Response Cache status row renamed from "System Cache" and wording clarified; empty-state now shows "מוכן לפעולה" / "Ready" with an explanatory tooltip instead of the alarming "Not yet generated".
* Improvement: Signals / Smart Exposure admin — "Not Exposed" legend description updated to clearer professional wording.

= 3.37 =
* Improvement: Site Signals card — exposure chips now show an inline preview snippet on click, keeping the user in the Behavior tab instead of jumping away.
* Improvement: Exposure chips restyled as circular blue pills matching the existing Jump-to-Notice design language.
* Improvement: Signals status layout — three indicator cards (Exposure Method, REST, Discovery) now share a compact status row; Active Announcements block spans full width to give chips and inline preview breathing room.
* Improvement: Responsive layout — on narrow/mobile viewports the status indicator cards auto-wrap (2+1) while the notices block remains full-width.
* Improvement: Announcement tab label updated to "הודעות" in Hebrew UI.

= 3.36 =
* New: Machine-readable announcement infrastructure with structured visibility support for modern search engines and AI systems.
* New: Site Signals subsystem with REST support, structured announcement output, Yoast SEO integration, and visibility-safe schema handling.

= 3.35 =
* New: Registration Capacity System — per-notice participant limits with configurable counter display (hidden / always / near-full threshold modes) and three counter formats (spots left, spots remaining, X/Y filled).
* New: Automatic waitlist mode — when capacity is full and the waitlist is enabled, the frontend form switches seamlessly to waitlist mode without a page reload; title, subtitle, and button text are all admin-configurable.
* New: Optimistic waitlist conversion — a user who submits just as the last spot is taken is automatically placed on the waitlist instead of receiving a hard error.
* New: Waitlist confirmation email sent immediately on waitlist join (toggle-controlled, bilingual Hebrew/English).
* New: Manual waitlist promotion — admins can promote a waitlisted registration to approved directly from the Leads table with a single click; capacity is re-checked server-side before commit.
* New: Automatic waitlist promotion — when an approved/verified registration is cancelled, expired, or rejected the next waitlisted row is promoted automatically via the snt_registration_status_changed hook.
* New: Promotion notification email sent on both manual and automatic promotion (bilingual).
* New: snt_registration_update_status() — centralised, validated, idempotency-protected status transition helper that fires the snt_registration_status_changed action hook and emits lifecycle analytics events.
* New: snt_capacity_blocking_statuses() filterable registry — defines which statuses consume a capacity slot; extensible via add_filter without code changes.
* New: FIFO waitlist ordering via snt_capacity_next_in_line() with a filterable ORDER BY hook for future priority queue support.
* New: Analytics event accuracy — reg_approved (admin/auto promotion) is now distinct from reg_verified (user-completed email verification flow).
* New: Waitlisted and Approved status badges in the Leads table with distinct colour coding (violet / deep emerald).
* Improvement: Capacity counter never shown when state is full; counter text inherits notice typography (font family, size, direction) without introducing separate styles.
* Improvement: Full-state and waitlist-state overrides respect the notice's configured text alignment and emphasis settings.
* Improvement: Per-notice capacity transient mutex (snt_cap_lock_{N}) prevents last-spot race conditions on concurrent submits.
* Improvement: Auto-promotion transient mutex (snt_cap_auto_{N}) prevents double-promotion on concurrent cancellations.
* Fix: Capacity lock now released immediately for open/near-full submissions instead of leaking a 4-second transient on the dedupe/reuse path.
* Fix: alreadyOnWaitlist server response now shows the contextual waitlist message instead of the generic success copy.
* Fix: snt_capacity_resolve() disabled fast-path counter defaults (format and threshold) aligned with the active code path values.
* Fix: Outdated reg_verified comment in snt_ajax_promote_waitlist() corrected to reg_approved (Phase 3.35-E.1).

= 3.34 =
* New: Lightweight visual inline editor for notice message text. The message textarea is replaced by a restricted contenteditable editor that renders bold formatting in real time. Markdown-lite `**bold**` storage and frontend rendering are unchanged.
* New: Visual bold toggle — the Bold toolbar button wraps the selected text visually inside the editor. Caret-only bold toggles the current line. Bold button highlights when the caret is inside a bold span.
* Improvement: Alignment toolbar now reflects the selected alignment visually inside the editor immediately on click and on page reload.
* Improvement: Clicking the "Message Text" label now correctly focuses the visual editor.
* Fix: Multiline bold selections now serialize and reload correctly; line breaks inside bold spans are preserved across save/reload cycles.
* Fix: Pressing Enter inside a bold span no longer drops the line break on save/reload.
* Fix: Pasting from Microsoft Word, Google Docs, or Outlook no longer leaks CSS or style markup as visible text in the editor.
* Fix: Quick Templates and per-notice Reset now update the visual editor immediately and cannot be overwritten by stale editor content.
* Fix: Toolbar Bold, Align, and Reset actions now correctly trigger the WordPress admin "Save Changes" indicator.
* Fix: Empty bold nodes remaining after deleting text inside a bold span are cleaned up automatically on each sync.

= 3.33 =
* Fix: OTP/email-code verification panel no longer disappears during notice rotation. An in-flight 250 ms rotation animation that started just before the OTP panel mounted would still call applyNoticeContent and tear down the panel; guarded with a rotTimer null-check. Dot navigation is also blocked while OTP verification is pending.
* Fix: OTP email send failures are now surfaced honestly. When the initial verification email cannot be sent (wp_mail returns false), the frontend shows a clear error message instead of opening a fake code-entry panel. The session and code are preserved so the user can re-submit the form and use the resend flow.
* Fix: Resend failures now show a human-readable "couldn't send the verification code" message instead of a generic error.
* Fix: Registration resend endpoint now accepts pending-status rows (rows where the initial send was rate-limited or failed); status is promoted to email_sent on a successful resend.
* Fix: OTP code default validity reduced from 10 minutes to 5 minutes; email copy and countdown now reflect the 5-minute window.
* Fix: Submissions table status metadata for email_sent rows changed to compact "נשלח · DD/MM" format to prevent clipping.

= 3.32 =
* New (Foundation 3.30.1): Registration Foundation — same Lead Form, now with a **Form Mode** dropdown (Off / Lead / Registration) on every per-notice card and a matching **submission_kind** column on the leads table. Picking "Registration" tags new submissions as registrations in the Leads inbox without a second builder, a second JSON, a second admin tab, a second analytics system, or a second table. The submit pipeline, `fields_data`, `_meta` snapshot, `{fields_list}` email/WhatsApp token, webhook payload, CSV export, `tpl_vars`, and analytics surfaces are byte-identical to pre-3.30.1 — only the new DB column differs on the inserted row.
* New (Foundation 3.30.1): Single-source-of-truth registries + predicates for the new abstraction — `snt_submission_kinds()`, `snt_submission_kind_is_valid()`, `snt_form_modes()`, `snt_form_mode_is_active()`, plus the canonical reader `snt_get_form_mode( $notice_id )` (with an automatic legacy fallback to `sn_notice_{N}_lead_enabled` when the new option key is absent, so existing notices behave identically without any migration).
* New (Foundation 3.30.1): Registration lifecycle status vocabulary — `snt_submission_statuses_for_kind('registration')` returns the full 10-value set: `pending`, `email_sent`, `verified`, `expired`, `cancelled`, `rejected` (registration-specific) plus the 4 existing lead statuses (`new`, `in-progress`, `no-answer`, `closed`). Lead rows continue to show the original 4-value set — no schema change, no duplicate registry. Note: email verification, token generation, and the public verification endpoint are not yet implemented; the lifecycle statuses are reserved for the next phase.
* New (Foundation 3.30.1): Registration admin quick-actions — registration rows in the Leads inbox expose three one-click lifecycle buttons: **Mark Verified** (✓), **Cancel** (⊘), and **Reject** (✗). Each prompts a native confirmation dialog, then calls the existing `sn_update_lead_status` endpoint (per-kind server validation) and applies an optimistic DOM update — status dropdown label, colour badge, and "new" row indicator all update without a page reload.
* New (Foundation 3.30.1): Registration status sub-filter — when the Registrations scope is active, a second dropdown lets the admin filter by a specific registration lifecycle status (Pending, Verified, Cancelled, etc.). The filter is additive (`AND lead_status = …` on top of the existing kind filter) and uses the same `snt_submission_statuses_for_kind()` allowlist for server-side validation.
* New (Foundation 3.30.1): Future-ready status registry hook `snt_submission_statuses_for_kind()` that returns the existing lead status vocabulary for both kinds today (no behaviour change). Reserved as the single fork point for Phase 3.31+ lifecycle additions.
* New (Foundation 3.30.1): Registration preset group with three layout-block-aware presets — **Event Registration Basic** (moved into the Registration group), **Workshop Sign-up**, and **Webinar Registration**. Applying any of them flips the Form Mode dropdown to "Registration" automatically; switching Lead ↔ Registration NEVER resets fields, layout blocks, builder JSON, or presets — only the semantic mode changes.
* New (Foundation 3.30.1): Leads inbox segmented filter (All / Leads / Registrations) — additive `WHERE submission_kind = …` extension on the existing leads query, no new admin tab, no analytics changes. A small **Kind** badge column appears only in the All view; the column auto-hides in the Lead/Registration views (where it would be redundant) without touching the underlying DOM, so colspan math, expand-row behaviour, and the existing trash filter stay byte-stable.
* Improvement (Foundation 3.30.1): Backward-compatibility shim keeps `sn_notice_{N}_lead_enabled` and `sn_notice_{N}_form_mode` synchronised in lockstep — the save handler reconciles the legacy toggle from the new mode, and the admin UI mirrors the dropdown ↔ toggle bidirectionally so card show/hide, eligibility predicates, and the public submit endpoint keep behaving exactly as before for every existing notice.
* Hotfix: Lead Form Builder — Layout Blocks active-state save validation. Saving a notice while Active with layout blocks (Text Block / Message Block / Spacer) no longer triggers the spurious "All lead form field labels are required" error. The pre-save validation loop now mirrors the server-side `snt_lf_is_layout()` predicate by short-circuiting on the row's `sna-lf-row--layout` class and `data-element-class="layout"` attribute, so only true data fields are checked for required Labels (existing behaviour preserved byte-for-byte for non-layout rows).
* Hotfix: Lead Form Builder — Message Block + Text Block frontend rendering width. The 12-col `.snt-lead-fields` grid only carried explicit `grid-column: span N` rules for `.snt-lead-input.snt-lf-w*`, so layout blocks (whose root is `.snt-lf-block`, not `.snt-lead-input`) auto-placed into a single 1/12 track and longer content visibly wrapped one-character-per-line. Added byte-parity rules for `.snt-lf-block.snt-lf-w25/33/50/100` (and the centered-flex variant + the ≤320px reflow) so layout blocks honour the same per-element width chooser as data fields. Affects frontend, admin Live Preview, mobile and RTL identically since both consumers share `sntBuildFields()` + `site-notice.css`.
* New: Lead Form Builder — Layout Blocks foundation. Three new element types live alongside the existing data fields inside the same builder, the same ordered list, the same drag/drop, and the same JSON storage: **Text Block** (short informational text or heading), **Message Block** (longer explanatory body with optional title) and **Spacer** (configurable spacing that can optionally render a divider line with thickness / color / opacity). Layout blocks render inside the admin builder, the Live Preview and the real frontend lead form — but are strictly visual-only: they never appear in `fields_data`, the `_meta` snapshot, `fields_data_legacy` / `fields_data_display` / `fields_data_labels`, the `{fields_list}` email/WhatsApp token, the webhook payload (flat keys *and* `fields` companion object), the CSV export (header *or* rows), the admin Leads search, the live `field_meta` map, or any analytics surface. The Phase 2A/2B byte-identical contracts on every lead/CSV/email/webhook are preserved — a form with zero layout blocks behaves exactly like it did on 3.29.
* New: Single-source-of-truth predicates `snt_lf_layout_types()`, `snt_lf_is_layout( $type )` and `snt_lf_is_data( $type )` (mirrors the existing `snt_lf_choice_types()` discipline) used by every loop that distinguishes lead-data from layout-only elements.
* New: Defensive normalization for layout fields at READ time (`snt_lf_normalise_layout_field()`), so legacy or hand-edited JSON always reaches the admin UI and the frontend renderer in a safe shape. Block content is sanitized through `wp_kses_post()` at save time; the frontend renderer uses `createTextNode` + `<br>` so block content can never carry executable HTML even if a future bug bypassed the server-side sanitizer.
* New: Lead Form Builder presets that showcase the new blocks — **Call Me Back** (Full Name + Phone + Preferred Time + spacer) and **Event Registration Basic** (Full Name + Email + Phone with an intro Message Block and section spacers). Pure layout / content presets — they reuse the existing Lead Form storage and the existing submit pipeline.
* Improvement: Spacer element supports both transparent spacing (no visible line) and an optional divider line with adjustable thickness (1–8 px), color and opacity. Height clamped to 0–200 px. All layout uses logical CSS properties so RTL behavior is identical to LTR.

= 3.29 =
* Fix: Pro Announcement/Bars — emojis entered into Notice/Message text and CTA/Button text now persist after Save and reload, and render correctly on the frontend. Values are pre-encoded with `wp_encode_emoji()` on save (same utf8mb4-safe pattern already used for WhatsApp messages and custom emoji), and decoded back at admin/live-preview/frontend display sites. Free Notice 1 behavior is unchanged for plain text; emoji round-trip is now safe on legacy `utf8` (3-byte) `wp_options` tables.

= 3.28 =
* New: User Access & Permissions — connect WordPress users with limited access to SiteNotice only. Free shows a polished locked teaser with feature preview; Pro adds a full Access Control surface with permission presets, granular per-user capabilities, and a side-drawer editor.
* New: Granular Pro capabilities — `snt_view_leads`, `snt_manage_leads`, `snt_view_analytics`, `snt_manage_bars`, `snt_manage_privacy`, `snt_export_csv`, `snt_manage_settings`. Administrators always retain full access; granular caps are enforced server-side on every sensitive AJAX endpoint.
* New: Custom WordPress role `snt_client` ("SiteNotice Client") created idempotently on activation; survives deactivation. Admin role keeps all existing capabilities; only `snt_access` is added.
* Improvement: Tab order — "Users" tab now sits next to "Leads" so it stays inside the main tab group on every viewport.
* Improvement: Premium UX — capability chips, live access summary, slide-in side drawer (bottom sheet on mobile), unified `.sna-btn` system, design-system-matched dropdown for user picking, and full RTL parity.
* Improvement: Revoke Access flow — replaced the native browser confirm with a SiteNotice-styled confirmation dialog that explicitly clarifies "removes SiteNotice access only — the WordPress account remains active". Adds a success toast after revoke and refreshes the table live.
* Safety: Administrator permissions cannot be edited or revoked from the Access Control screen; self-edit is blocked. Pro downgrade does not delete previously assigned capabilities — they simply gate behind Pro again on re-upgrade.

= 2.99 =
* Improved Pro Leads toolbar mobile layout stability and responsive alignment.
* Refined Leads and Not Relevant mobile toolbar spacing, control sizing, and row structure.
* Improved new lead notification UI behavior and refresh action placement.
* Added multiline support for message fields, WhatsApp prepared messages, and lead form messages.
* Improved emoji and Unicode handling for WhatsApp prepared messages.
* Added Pro lead email test delivery flow with clearer feedback.
* Added email delivery health guidance for SMTP/plugin configuration.
* Improved admin UI polish for Leads management.

= 2.98 =
* Improvement: Leads tab — desktop layout now anchors slightly to the reading-edge (right in Hebrew/RTL, left in English/LTR) without centering or changing column structure.
* Improvement: Leads tab — mobile controls reorganised into a compact 4-row layout: Row 1 holds the Leads/Trash toggle plus bulk action and Export CSV (when visible), Row 2 is full-width search, Row 3 splits Notice and Time filters 50/50, and Row 4 keeps the WhatsApp country code (972) compact instead of full-width.
* Polish: Leads toolbar (mobile) — final micro-alignment pass on Row 4. Export CSV now shares the exact baseline of the adjacent Time filter and 972 input (no more ~1-2 px float); horizontal spacing across Date · 972 · CSV is uniform (Date fills col 1 instead of leaving a leftover gap); on iPhone SE-class screens (≤360 px) Date can compress and the column-gap is restored to 8 px so "כל הזמן" and "קידומת 972" no longer overlap. Pure CSS, no layout rebuild, RTL-safe (logical properties only), desktop untouched.
* Improvement: Leads table — header select-all and row checkboxes now share the same 14×14 footprint with the dashicons checkmark recentered, fixing the visible size mismatch.
* Improvement: Leads table — mobile row vertical padding tightened (8 → 6 px) for a more compact list; cell wrapping and column structure unchanged.
* Improvement: Admin toast — on mobile, success/feedback messages (delete, restore, etc.) now appear centered above the sticky Save Changes footer with a subtle fade/slide-up animation, so they're no longer missed behind the bar.
* Improvement: Sticky Save Changes footer — added a subtle top halo on mobile so the bar visually separates from content scrolling beneath it. Toast (above) sits comfortably above the bar.
* Change: Privacy → Re-Access Element — Free version now defaults to Tab (לשונית), the only non-locked type, instead of Handle (ידית). Existing saved choices are preserved untouched; Pro behaviour is unchanged.

= 2.97 =
* Fix: Leads tab — restored loading. The shared `_snI18n()` admin localization helper was scoped to a single IIFE which crashed every later module on first call (Leads, License, Toast, Reset). Hoisted to module scope so all admin code paths share it.
* Fix: Privacy tab — RTL alignment. Removed an `align-items: flex-end` override that, in `flex-direction: column` + `direction: rtl`, resolved to the LEFT physical edge and pushed privacy mode card content off-side in Hebrew mode. Logical `align-items: flex-start` + `text-align: start` now handle both directions correctly.
* New: Admin header — Pro badge / Upgrade CTA. Pro is now a compact uppercase status pill (subtle amber tint, hairline border). Upgrade is a real CTA button with a warm amber gradient, 8 px corners, and proper hover/focus states. Layout no longer shifts on hover.
* New: Upgrade tab — refreshed Free vs Pro comparison. Free now lists the foundation (Announcement Bar, Privacy Bar, Live Preview, basic templates). Pro highlights Lead Forms, Leads management, Lead Form typography, per-notice analytics, Privacy popup, advanced design / glass / blur / radius, advanced typography, multi-notice rotation, advanced behavior & targeting, WhatsApp / CTA templates, and premium templates.
* Pricing: Yearly tiers refreshed — Starter $49 / Business $99 / Agency $179. Lifetime listing removed.
* Localization: Visibility (`All Pages` / `Home Only` / `Selected Pages` / `Exclude Pages`), Display Duration (`Permanent` / `Limited Days`), emoji presets (Fire / Announcement / Delivery / Alert / Launch / etc.), Re-access type cards (Tab / Handle / Icon / Footer + hints), Privacy custom-message placeholders, Behavior subtitle, and Re-access language hints are now fully localized in both Hebrew and English. Saved internal values are unchanged.
* Compliance: Text domain aligned with plugin slug (`site-notice`).

= 2.89 =
* Fix: Design Tab — Button Border toggle now properly reveals/collapses its dependent settings (color/width) without resetting saved values.
* Fix: Design Tab — Submit Button Pulse/Glow color now applies on the real front-end (was working only in Live Preview).
* Fix: Design Tab — Notice Bar Button Pulse/Glow color now applies on the real front-end and stays in sync across multi-notice rotation.
* Improvement: Design Tab — New official defaults for Button Effect Colors — Pulse #57FF78, Glow #36D956. Restore Defaults now resets these values too.
* Improvement: Design Tab — Pulse/Glow color controls show a clearer disabled state with hint text when their style is not selected.

= 2.85 =
* New: Lead Form — Privacy Action selector (PRO). Control how the privacy link behaves per form: Use global setting, Open Privacy Link, or Open Privacy Popup.
* New: Lead Form — Privacy URL field (PRO). When "Open Privacy Link" is selected, a dedicated URL field appears for the form's privacy link.

= 2.40 =
* Fix: Frontend Lead Form privacy row now correctly respects the "Inline With Submit" layout setting — consent row and submit button render on the same row as configured.
* Fix: Preview language now correctly reflects the per-notice language — English notices show English fallback text, Hebrew/RTL notices show Hebrew fallback text.
* Fix: "Inline With Submit" and "Above Last Row" conflict resolved in admin UI — Position control is hidden when Inline With Submit is selected.
* Fix: Admin sticky tabs bar and Save Changes button overlap corrected on desktop.

= 2.31 =
* Fix: RTL input behavior — direction, text-align, and caret position now correctly start from the right for Hebrew/RTL fields (Full Name, Phone, Email visual-only).
* Fix: Form alignment (Auto/Left/Right/Center) no longer reorders fields or breaks grid layout; controls only text direction and alignment.
* Fix: Mobile field width — 25% and 33% fields no longer forced to full width on mobile; grid respects configured widths and only wraps when necessary.
* New: Field Position / Alignment setting (Auto/Right/Center/Left/Full) controls where fields are placed within the form row without affecting text inside inputs.
* Fix: Live Preview now matches Frontend 100% — same RTL logic, same field direction, same field position classes.
* Fix: Agreement row (consent checkbox + text) now renders as a correct inline unit in RTL with checkbox on the right and text to the left.

= 1.97 =
* UX: Pro License section — "Upgrade Plan" now uses Freemius get_upgrade_url() guarded by is_whitelabeled(); "Sync License" and "Change License" buttons added; license key display updated to first-4/last-3 masking format.
* Fix: License activation dialog now injected for both Free and Pro users on the settings page.

= 1.96.1 =
* Fix: Plugin row "Opt out" / Freemius action links completely removed — plugin_action_links filter priority raised to 9999 so it executes after Freemius (priority 10) and returns a clean [Settings, Deactivate]-only array. Also covers network_admin_plugin_action_links_ hook.
* Fix: "Upgrade Plan" / "View Pro Plans" no longer causes "You do not have sufficient permissions" — URL now resolved via menu_page_url('site-notice-pricing') which looks up the actual registered parent (options-general.php vs admin.php), with sn_fs()->get_upgrade_url() as fallback.
* UX: Upgrade Plan and View Pro Plans buttons now open in a new tab so users remain on the plugin settings page.

= 1.96 =
* Fix: Plugin row now shows only "Settings" and "Deactivate" — all Freemius-injected links (opt-in, opt-out, upgrade) removed via full action-links override.
* Fix: "Upgrade Plan" / "View Pro Plans" button no longer causes "You do not have permission" — URL now built via sn_fs()->get_upgrade_url() for correct permission resolution.
* Fix: Sync License button removed from Pro tab to avoid duplicate navigation; Manage License is the single management entry point.
* UX: Manage License button opens in a new tab so users stay inside the plugin settings page.
* UX: Pro tab actions simplified — Free: View Pro Plans + Activate License; Pro: Upgrade Plan + Manage License.
* Security: Additional opt-in notice suppression filters added (fs_show_optin_notice, fs_show_connect_message, fs_show_admin_notice) as belt-and-suspenders alongside anonymous_mode:true.
* New: Plugin version bump to 1.96.

= 1.95 =
* Fix: Freemius opt-in / opt-out prompt fully disabled at SDK level using anonymous_mode:true in fs_dynamic_init — no more banner, popup, or data-sharing modal on install.
* UX: Pro tab State B — expanded license summary: Status, Plan, Expiration/Lifetime, and masked license key (last 4 visible: ••••XXXX).
* UX: License key copy button — one-click clipboard copy with 2s "Copied!" feedback; uses Clipboard API with textarea fallback.
* UX: Pro tab State B — new "Sync License" action button alongside "Upgrade Plan" and "Manage License".
* UX: Expiration row shows "Lifetime" for lifetime licenses or a formatted date for annual/monthly plans.
* New: sn_page() — $snt_fs_license, $snt_fs_license_key_masked, $snt_fs_expiration, $snt_fs_sync_url variables.
* New: .sna-license-key / .sna-license-key__copy CSS component — monospace masked display + accent copy pill.
* New: Plugin version bump to 1.95.

= 1.94 =
* UX: Pro tab — two-state layout (Free / Pro Active) redesigned for cleaner, premium UX.
* UX: State A (free) — removed extra crosslink; two-button layout (View Pro Plans + Activate License) streamlined.
* UX: State B (pro active) — new license summary block shows Status + Plan name from Freemius.
* UX: Pro active buttons — "Upgrade Plan" (primary) + "Manage License" (secondary); Manage License no longer auto-navigates.
* UX: Helper text refined — concise, professional copy in both English and Hebrew.
* Fix: "Manage License" button demoted from primary to secondary so it never outweighs the upgrade CTA.
* New: $snt_fs_plan_title variable retrieves live plan title from Freemius with 'Pro' fallback.
* New: .sna-license-summary component — pill-style summary block for pro license details.
* New: Plugin version bump to 1.94.

= 1.93 =
* UX: Pro tab — complete UI/UX polish pass: cleaner spacing, stronger visual hierarchy, and premium CTA presentation.
* UX: "View Pro Plans" button now uses the full plugin primary-button design system (gradient, shadow, hover lift).
* UX: "Activate License" secondary button height and border-radius now match the primary CTA for a balanced pair.
* UX: Pro tab copy refined — headline, helper text, and sub-hint updated for clarity and professionalism.
* UX: Feature list receives improved per-item spacing and a subtle separator from the CTA area.
* UX: Pro tab inline styles replaced with proper CSS classes (sna-pro-intro, sna-pro-helper, sna-pro-actions, sna-pro-actions-hint, sna-pro-features-sep).
* New: Plugin version bump to 1.93.

= 1.9 =
* Fix: Rotation preview no longer injects dummy "Next Notice" content — animation runs on the current notice only.
* Fix: Privacy glass effect now includes gradient overlay to match top bar visual quality (blur, depth, sheen).
* Fix: Privacy font size now updates live preview instantly for non-Pro users.
* Fix: Design "Restore Defaults" now correctly resets border color field and refreshes the live preview immediately.
* New: Plugin version bump to 1.9.

= 1.88 =
* Fix: Design style presets (Gradient, Glow, Floating) now apply on frontend — sn_adv_style_preset was never saved to database (missing from AJAX str_opts).
* Fix: Privacy default colors — Background #ffffff, Button bg #ffffff, Text #2e2e2e.
* New: Privacy button text color control (sn_priv_btn_text_color), default #2e2e2e.
* Fix: Privacy bold toggle now applies font-weight to admin live preview box.
* Fix: Privacy preview centering — margin:auto on preview box; #snt-root full-width in preview frame.
* Fix: Live preview spacing — 8px padding around privacy preview.

= 1.87 =
* Fix: Design style presets (Gradient, Glow, Floating) now apply correctly on frontend even with scroll trigger or delayed show — uses MutationObserver to detect bar in DOM.
* Fix: Privacy admin preview now stays centered when switching to Privacy mode — #snt-root expands to full width during privacy preview.
* Fix: Privacy admin preview language auto-detection now uses WordPress site locale (document.documentElement.lang) for correct Hebrew/English defaults.
* New: Opacity control for Privacy bar background (default 0.75); applies to both admin preview and frontend.
* New: Opacity control for Advanced Styling updated to default 0.75; Restore Defaults resets to 0.75.
* New: Custom Privacy Link text field — override displayed link label independently of URL.
* New: Custom Accept Button text field — override displayed button label.
* Fix: Mobile Analytics — fixed horizontal overflow; entire layout now fits viewport with no sideways scroll.
* UX: Increased live preview vertical padding for clearer spacing.

= 1.86 =
* Fix: Single mode with multiple notices now loops continuously using instant cut (no fade, no stop).
* Fix: Design style presets (Gradient, Glow, Floating) now render strongly on both admin preview and frontend — restructured to be self-contained per preset.
* New: Glass Effect toggle for Privacy Bar; defaults to ON; Reset restores Glass ON.
* Fix: Privacy admin preview now reflects correct language and real default text (Hebrew when language is set to Hebrew).
* Fix: Privacy preview alignment — no longer shifts to the side when switching to Privacy mode; stays centered.
* Fix: Privacy Reset now fully restores all defaults including Glass ON.
* New: Advanced Styling — Restore Defaults button resets all colors, blur, glass, and preset to original values.
* UX: On mobile, switching to Privacy preview auto-scrolls to the Live Preview panel.
* Fix: Mobile Design tab — typography rows now stack cleanly on small screens.
* Fix: Mobile Analytics tab — table scrolls horizontally; no overflow or broken layout.

= 1.85 =
* Fix: Single mode with multiple notices now advances through them sequentially (one-shot, no loop) instead of freezing on one.
* Fix: Design style presets (Gradient, Glow, Floating) now have clearly distinct appearances in both admin preview and frontend.
* New: Privacy — Reset to Defaults button in Advanced Privacy section restores all colors, text, and settings to their original defaults.
* New: Privacy — separate toggles for Privacy Link and Accept Button; each works independently.
* Fix: Privacy admin preview now updates live as you type or change any privacy setting — no page refresh required.
* Fix: Privacy preview layout — long text now wraps cleanly with no overflow or sideways clipping.

= 1.84 =
* Fix: Single mode now deterministically shows one eligible notice and never behaves like auto-rotate.
* Fix: Design style presets now apply strongly and consistently to the notice container in preview and frontend.
* UX: “Enable Button” toggle moved above Button Text for Notices 2–5.
* Fix: Advanced Privacy PRO settings now apply to the rendered privacy bar and update live in admin preview.
* New: Privacy Live Preview toggle (PRO) inside Advanced Privacy to preview the privacy bar in the existing Live Preview area.

= 1.83 =
* Fix: Notice 2–5 button now previews correctly (matches frontend) without save or refresh.
* Fix: Single mode now consistently shows one notice and does not rely on auto-rotate behavior.
* Fix: Glass effect OFF is now clearly non-glass; ON applies visible blur/transparency/border in preview and frontend.
* Fix: Design styles are now visibly stronger in both preview and frontend.

= 1.82 =
* Fix: Notice 2–5 button enable state now works in admin preview and frontend rendering (matches Notice 1).
* Fix: Preview selector now filters to enabled notices with usable content and updates as you edit/enable notices (no save required).
* Fix: Single mode now consistently shows one valid notice and no longer feels like broken rotation.
* Fix: Glass effect and design styles now have clearly visible differences in preview and frontend.

= 1.81 =
* Fix: Admin live preview now updates instantly for all notice fields and toggles (Notices 1–5) without save/refresh/switching.
* Fix: Preview selector now always includes Notices 1–5 so multi-notice activation is instant in preview.
* Fix: Frontend CTA/link/button rendering now stays correct across notices and rotation, matching preview.
* Fix: Single rotation mode now consistently displays one valid notice and tracks views/clicks correctly.
* Fix: Glass effect and design style presets now apply and clear predictably across preview and frontend.
* Fix: Sticky Save bar positioning avoids admin bar overlap and aligns with plugin content width.

= 1.80 =
* Fix: Multi-notice live preview now updates instantly for all Notice 2–5 fields (text, link, button, CTA) while typing.
* Fix: Frontend CTA rendering for Notice 2–5 now correctly shows links/buttons regardless of Notice 1’s CTA settings.
* Fix: Rotation “Single” mode consistently shows one valid enabled notice when multiple notices exist.
* Fix: Glass Effect and design style presets now apply and clear correctly across preview and frontend.
* UX: Sticky Save bar moved to the top-right of the main content area on desktop; mobile keeps bottom sticky save.

= 1.79 =
* Fix: Multi-notice admin preview now updates instantly for Notices 2–5 when editing text, links, or buttons, without requiring a save or animation replay.
* Fix: Frontend rendering for Notices 2–5 now mirrors the preview exactly, including link and button visibility when enabled.
* Fix: Rotation “Single” mode reliably displays one notice without freezing or skipping enabled notices.
* Fix: Entrance animation applies the advanced background color and glass effect from the first frame, removing the white flash.
* Fix: Glass Effect and design style presets (Gradient, Glow, Floating) now have clearly different appearances in preview and frontend.
* UX: Sticky Save bar remains compact near the preview on desktop and switches to a bottom sticky save button on mobile for easier thumb access.

= 1.78 =
* Fix: Multi-notice preview now stays in sync for Notices 1–5, including message, link, and button state without requiring a save or page refresh.
* Fix: Preview selector reliably shows the currently selected notice and respects unsaved field changes for each notice.
* Fix: CTA behavior for Notices 2–5 now matches Notice 1 across admin preview and frontend (button enable, URLs, and link visibility).
* Fix: Added dedicated analytics for the Privacy bar (views, accepts, CTR) alongside existing global and per-notice announcement analytics.
* Fix: Entrance animation no longer flashes a white bar before custom colors or glass effects are applied.
* UX: Sticky Save bar is now a compact centered pill while remaining fully sticky and using the same buttons.
* UX: Rotation Mode includes a short explanation clarifying Single vs Auto Rotate behavior.
* Pro: Improved glass effect plus new lightweight design presets (Gradient, Glow, Floating) and optional RGBA/alpha support for advanced background colors.

= 1.76 =
* Fix: Preview selector now correctly displays the selected notice content; switching dropdown no longer reverts to Notice 1 on any form change.
* Fix: Frontend opacity now uses rgba() background transparency instead of CSS opacity — text stays fully visible; background is correctly semi-transparent.
* Fix: Advanced styling (rgba background, blur, glass, border-radius) now applied after the entrance animation so it is never overridden.
* Fix: Analytics now counts views and clicks for all users including logged-in admins; the admin bypass in both JS and PHP has been removed.
* New: "Refresh" button added to the global Analytics card for instant data reload without a page reload.
* New: Per-notice "↻" refresh button added to each row of the Per-Notice Analytics table (Pro); refreshes only that notice's data.
* Improvement: sn_get_adv_style() now also returns bgColorRgba (pre-computed rgba string) for direct CSS use in both admin preview and frontend.

= 1.75 =
* Admin: Pro badge now uses pill shape with lighter green (#22c55e) for a cleaner look.
* Admin: Pro active card shows "Site Notice Pro is Active ✅" — no sales text when license is active.
* Admin: Sticky and header Save Changes buttons now use the same AJAX handler as the bottom button.
* Admin: Global analytics reset button renamed to "Reset All Analytics".
* Admin: Per-notice Reset buttons added to Per-Notice Analytics table (PRO only).
* Admin: Advanced Styling preview reflects background color, opacity, blur, glass, border radius in real time.
* Admin: Live Preview shows a notice selector dropdown (PRO) when multiple notices exist.

= 1.74 =
* Admin: Pro badge now uses pill shape with lighter green (#22c55e) for a cleaner look.
* Admin: Pro active card redesigned with green-tinted background, cleaner hierarchy and spacing.
* Admin: Sticky and header Save Changes buttons now use the same AJAX handler as the bottom button (fully reliable in Pro mode).
* Admin: Global analytics reset button renamed to "Reset All Analytics".
* Admin: Per-notice Reset buttons added to Per-Notice Analytics table (PRO); resets only the selected notice via new sn_reset_notice_stats AJAX action.
* Admin: Advanced Styling preview now reflects background color, opacity, blur, glass effect, border radius, text color, and button color in real time.
* Admin: Live Preview shows a notice selector dropdown (PRO) when multiple notices exist; switching updates the preview instantly.

= 1.73 =
* Admin: deactivate flow now uses delete_option (no residual DB state); stale sn_pro_active flag also cleaned with delete_option; "Activate License" button label; Pro License card title.

= 1.72 =
* Admin: Pro license deactivation flow; Free/Pro header badge now reflects real state; sn_is_pro() normalized (stale flag without key falls back to Free).

= 1.71 =
* Admin: final Upgrade plan names, pricing (incl. Agency $129), plan descriptions, and table Sites/Price row copy.

= 1.70 =
* Admin: Sites / License row on Upgrade plans table for tier clarity.

= 1.69 =
* Admin: unified Upgrade plans table (features + pricing); Business column marked Most Popular.

= 1.68 =
* Admin: Pro pricing tiers and introductory note on Upgrade to Pro tab.

= 1.67 =
* Admin: Free vs Pro comparison table on Upgrade to Pro tab.

= 1.66 =
* Admin: richer Upgrade tab feature copy; Activate Pro button uses unified primary styles; cross-links between Upgrade and Pro tabs.

= 1.65 =
* Admin: final Upgrade to Pro microcopy polish (targeting line, feature wording, Advanced Auto Width phrasing).

= 1.64 =
* Admin: improved Upgrade to Pro microcopy (header tagline, benefit-led features, two-line CTA, trust line).

= 1.63 =
* Admin: "Upgrade to Pro" tab moved to last position; refined copy, reinforcement note, and CTA button aligned with plugin primary button styles.

= 1.62 =
* Admin: new "Upgrade to Pro" tab with feature overview and clearer width-mode labels (1.61).

= 1.61 =
* Admin: improved width mode microcopy and explanation block.

