== Changelog ==

= 3.23.5 =
* Security: web Google/Apple sign-in now requires a provider-verified email address before linking or creating an account (prevents account takeover via an unverified provider email).
* Security: the loyalty-progress REST endpoint now identifies the customer from the WordPress auth cookie and only ever returns the logged-in customer's own progress (no more lookups by arbitrary email).
* Security: the mobile-app promo validation endpoint is now per-IP throttled against code enumeration.
* Fix: rate-limiter transients can no longer be stored with a zero/negative expiration.

= 3.23.4 =
* Security: the web Sign in with Apple flow now cryptographically verifies the Apple ID token (RS256 signature against Apple's JWKS) before signing the user in — previously only iss/aud/exp claims were checked.
* Security: public loyalty-progress REST lookups are now IP rate-limited.
* Review feedback: every inline <script>/<style> is now delivered through wp_add_inline_script()/wp_add_inline_style()/wp_print_inline_script_tag(); JSON-LD output no longer uses JSON_UNESCAPED_SLASHES; transient keys are consistently unbsb_-prefixed; the placeholder image URL uses UNBSB_PLUGIN_URL instead of a hardcoded wp-content path.
* The "Powered by" credit under the booking form is now opt-in (Settings toggle, off by default).
* Updated bundled libraries: Chart.js 4.5.1, intl-tel-input 29.2.3 (bundled utils, webp flag sprites).
* readme: documented every external service (Google/Apple sign-in, reCAPTCHA, hCaptcha, GA4, Meta Pixel/CAPI, NetGSM) with data-flow details and working terms/privacy links.
* Removed bundled .po/.mo translation files (translate.wordpress.org handles translations) and the load_plugin_textdomain() call.

= 3.23.3 =
* Security: public booking and promo-code AJAX endpoints are now IP rate-limited (5/min for booking creation) — they are deliberately nonce-free for cache compatibility and previously relied on the honeypot/CAPTCHA only.
* Hardening: remaining unsanitized/unslashed inputs fixed, OAuth redirects use wp_safe_redirect with an allowed-hosts filter, debug logging gated behind WP_DEBUG.

= 3.23.2 =
* WordPress.org readiness: removed the self-hosted update checker (WordPress.org is now the update channel), FullCalendar is bundled locally instead of loaded from a CDN, the optional GA4 loader is enqueued through the WordPress script API, and every Plugin Check error was resolved (SQL prepare, output escaping, translator comments).
* Fix: Customer View "Wallet" payment badge queried the wrong table name and never showed.

= 3.23.1 =
* New: Conditional email-template blocks {if_cancel}, {if_reschedule}, {if_manage} — cancel/reschedule wording is dropped automatically when the feature is disabled.

= 3.23.0 =
* New: Soft delete for services, staff and categories with a "Deleted items" list and Restore.
* New: Edit Booking supports full multi-service editing (Bookings list + Calendar).
* Fix: Conflict check now runs against the new end time when a booking's services change.

= 3.22.x =
* New: Whole admin installable as a PWA (role-aware manifest, install prompt, offline page).
* Fix: Service Worker no longer cache-firsts third-party wp-admin assets.
* Fix: Mobile modal overflow, missing app-bar spacing, pinch-zoom on plugin screens, missing Card payment icon.

= 3.21.0 =
* New: Mobile app shell (top bar, drawer, bottom tabs, bottom-sheet modals) on every plugin admin screen.

= 3.20.0 =
* New: Reports page — P&L over any date range with a month-by-month breakdown.

= 3.19.x =
* New: Inventory module — items, per-location stock, movement ledger, stock counts, staff order requests, low-stock alerts.
* New: Staff portal read-only colleague calendars; customer birthday list/filters; dashboard Net Profit section.
* Fix: Staff could complete another staff member's booking via AJAX.

= 3.18.x =
* New: Birthday collection + marketing consent, birthday greeting email with auto gift coupon, editable birthday template.

= 3.17.x =
* New: Team commission split memory, commission recalculation, per-row earnings delete, Staff View metric cards, bookings-list badges (new / visits / no-show / cancellations / lifetime value), quick date filters, admin team bookings, New Booking mobile UX.
* Fix: Export/Import now covers all plugin tables; settings import keeps serialized options intact.

= 3.16.x =
* New: Team services — a service can require N staff at the same time (slot intersection, auto-assignment, commission split).
* New: Manual per-staff commission split on booking completion.

= 3.15.2 =
* New: Themes can now ship an optional `script.js` (declared in `theme.json`), enqueued in the footer only when the theme is active — for self-contained progressive enhancement. Documented in the theming standard.
* New: Gaia theme — a live "running selection" summary inside the sticky action bar: the chosen service and price, then the staff and time as you advance, shown right above the Continue button (like premium booking apps).
* New: Gaia theme — on the Date & Time step the first available day is auto-selected so its times load immediately, instead of an empty "Select a date first" panel.
* New: Gaia theme — restyled service selection as a two-column tile gallery (one column on phones) with a category-colour spine and a prominent price, plus a refined category-filter pill rail. Stronger text contrast throughout for readability.
* Fix: Gaia — the Back and Continue buttons no longer stack on top of each other in the bottom bar on phones; they sit side by side (compact Back, filling Continue).
* New: Gaia — clearer discounts (terracotta sale price + solid badge), refined motion (service/list entrance, selected-state polish, completed-step checkmarks, calendar paging fade), a taupe luxe confirmation screen, and a stronger mobile-app feel.

= 3.15.1 =
* New: "Sable" bundled theme — a warm taupe (#c2b09c) luxury look: sand-stone canvas, espresso serif ink, bronze hairlines, with editorial Services and Team layouts (template overrides). A calm, expensive alternative to the dark themes.
* New: "Gaia" bundled theme — soft cosmetic-clinic luxe: airy cream canvas, warm taupe accents, light Montserrat type and generously rounded, pill-soft shapes (rounded cards, pill buttons). Editorial Services and Team layouts included.
* Fix: The "Customize active theme" colors are now opt-in (a new "Override theme colors" toggle, off by default). Previously a saved appearance color silently overrode every theme's primary/accent/radius/font, so picking a theme didn't take full effect. Now the chosen theme controls the look unless you explicitly enable the override.

= 3.15.0 =
* New: Modular frontend theming system for the booking shortcodes. Pick an active theme in Settings → Appearance → Theme; a theme can change design tokens (colors/radius/fonts), ship its own CSS, and override shortcode templates — each layer optional and granular so themes survive plugin updates.
* New: Three bundled themes — Default (the classic look), Minimal (flat/monochrome), Midnight (dark mode).
* New: Themes are discoverable from three sources — the plugin's themes/ folder, a child-theme's /unbsb-themes/ folder (auto-discovered, no code), and the `unbsb_register_themes` filter (for other plugins). The standard (theme.json manifest, token vocabulary, template contract) is documented in docs/THEMING.md.
* New: Per-shortcode override — [unbsb_booking_form theme="midnight"] themes a single shortcode.
* New: Hooks — `unbsb_register_themes`, `unbsb_active_theme`, `unbsb_theme_tokens`, `unbsb_locate_partial`, and `unbsb_before_partial_{name}` / `unbsb_after_partial_{name}`.
* Improvement: The public stylesheet's design tokens are now hoisted to :root and reach every section (auth modal, welcome banner, affiliate, account) — previously several sections were hardcoded and ignored theming. The legacy Appearance colors remain as a per-site "customize active theme" override layer.

= 3.14.0 =
* New: Mobile REST API for a native (React Native) customer app — a complete, stateless, token-based surface under `unbsb/v1/app/*`. Member sign-up/login/logout, native Google & Apple sign-in, full booking lifecycle, profile management, vouchers/wallet, loyalty, affiliate and push-device registration. Docs in docs/MOBILE-API.md, docs/openapi.yaml, docs/REACT-NATIVE.md.
* New: JWT auth — short-lived signed access tokens (HS256, dedicated rotatable secret) + opaque refresh tokens stored hashed one-row-per-device and rotated on every use. Per-user token version is a global kill-switch (password change / logout-all instantly invalidates all access tokens). Bearer auth resolved globally so no cookies/nonces are needed.
* New: Auth endpoints — register, login, refresh, social/google, social/apple, password forgot/reset, logout, logout-all. Account — get/update/delete profile (GDPR), change password, resend verification, list sessions. Push devices — register/remove token.
* New: Native social verification — Google ID tokens via Google tokeninfo (issuer + audience checked against web/iOS/Android client ids); Apple identity tokens verified locally against Apple's JWKS (RS256) with from-scratch JWK→PEM + openssl_verify, checking issuer/audience/expiry.
* New: App surface — config bootstrap; catalog (categories/services/staff, salary & PII stripped); availability (slots by service or duration, days, today-by-staff); bookings (create guest-or-auth, list, detail, cancel, reschedule, guest-by-token); promo validate; loyalty; wallet (balance/redeem/transactions); affiliate dashboard.
* New: Settings — General → "Enable Mobile API" toggle. Booking → Social Login gained Google iOS Client ID, Google Android Client ID and Apple App Bundle ID for native sign-in audiences.
* New: Database — adds unbsb_auth_tokens (refresh sessions, hashed) and unbsb_device_tokens (push) on upgrade.
* Security: rate-limited register/login/forgot/redeem/booking and native social endpoints; password-reset stays generic (no email enumeration); booking not-found vs not-owned return identical 404; config endpoint never exposes secrets. Hardening pass: native social login rejects unverified provider emails and refuses to bind a social identity to an admin/staff account; rate-limiter now uses REMOTE_ADDR by default (proxy headers only honored when the new "Trust proxy" option is on); customer-facing booking detail strips staff email/phone and internal notes; the legacy public booking endpoint no longer accepts client-supplied customer_id/force/payment fields; public availability endpoints are throttled and short-cached.

= 3.13.1 =
* New: Booking completion modal now surfaces the wallet-apply prompt and voucher-code input. When a customer has wallet balance > 0, the modal shows it at open; admin/staff tick the checkbox and enter an amount (defaults to min(balance, booking price)), and the wallet is debited first, then the remainder is recorded via the existing cash/card/transfer path.
* New: Voucher code input beside the amount field — paste 8-char code, click Apply, discount is posted to the booking and the Amount Received input is reduced automatically.
* Fix: complete-booking button now carries data-customer-id so the wallet balance lookup works without an extra server round-trip.

= 3.13.0 =
* New: Voucher & Client Wallet system — fixed / service-specific / percentage gift vouchers plus per-customer wallet balance. Admin/staff issue vouchers (cash/card/transfer). Recipients redeem via [unbsb_wallet] shortcode or at checkout. Fixed vouchers load wallet; service/percentage apply as single-use line discount.
* New: Four tables (vouchers, wallet_transactions, voucher_redemptions, voucher_audit_log). Insert-only audit ledger.
* New: 8-char codes (32-char unambiguous alphabet), HMAC-SHA256 hashed at rest, constant-time compare.
* New: Atomic wallet debit with row-lock transaction — double-spend safe.
* New: Non-existent recipient invite flow — placeholder customer + invite email + auto-redeem on registration.
* New: Daily expiry cron + configurable expiring-soon reminder.
* New: Seven lifecycle email templates in English, Turkish, and Bulgarian.
* New: Settings → General → "Vouchers & Wallet" section (enable toggle, expiry days, reminder days).
* New: Admin submenu Bookings → Vouchers with issue modal, filters, and void action.
* New: Public REST endpoint POST /unbsb/v1/wallet/redeem with 10-attempts/15-min rate limit.

= 3.12.15 =
* Fix: Dashboard "Top Services" and "Staff Performance" row rendered as 3 columns with an empty rightmost column. CSS specificity bug — `.unbsb-dashboard-grid` (1fr 1.5fr 1fr) was defined after `.unbsb-dashboard-grid-2` (1fr 1fr) and overrode it. Resolved by scoping the 2-column rule with a compound selector so it wins regardless of source order.

= 3.12.14 =
* New: Admin calendar "Block Time" button — mark a staff member unavailable for an arbitrary time window on a single day (one-off, not recurring). Optional reason field. Blocks appear as gray events on the calendar and are excluded from the customer-facing slot calculator. Click a block to remove it. If any non-cancelled booking overlaps the requested range, admin is prompted with the conflicting bookings and must confirm to proceed (existing bookings are kept; only new bookings are blocked).
* Fix: `is_holiday()` now treats only rows with NULL start/end times as full-day holidays, so partial time-off rows no longer zero out the entire day's slot grid.

= 3.12.13 =
* Fix: Settings > General page — "Pages" section (Account Page / Manage Booking Page dropdowns) was rendered outside the settings card at the bottom because the Staff Earnings toggle used the wrong CSS class (`unbsb-toggle-row` instead of `unbsb-setting-item unbsb-setting-toggle`) plus an extra stray `</div>` closed the section early. Normalised all three toggles (Multiple Services, Staff Earnings, Allow Staff to Record Lower Amounts) to the same structure.

= 3.12.12 =
* New: Settings > General > "Allow Staff to Record Lower Amounts" toggle (default OFF). When OFF, non-admin staff cannot complete a booking with a paid amount less than the service price. Admins always can. Enforced on both the client (HTML5 input min) and server (AJAX handler).

= 3.12.11 =
* Fix: Complete-booking modal blocked downward adjustment — HTML5 `min` attribute was still being set to the booking price in JS, so browsers rejected any lower amount. Admin can now enter any non-negative paid amount (tip upward or agreed discount downward). Commission remains strictly proportional to paid_amount.

= 3.12.10 =
* Security: /my-bookings REST endpoint no longer falls back to email-based customer lookup. Identity is strictly established via customers.user_id. Prior behaviour could link a WP user to any customer row sharing the same email (customers.email is not unique) and exposed booking management tokens of other customers. Severity: High.
* Security: Removed automatic link_user() call on email match — auto-claiming customer rows is now disabled; the link must be set at registration/verification time.
* Security: Removed UNBSB_Booking::get_by_email() fallback inside /my-bookings which returned bookings by the bookings.customer_email free-text column regardless of ownership.

= 3.12.9 =
* Fix: Dashboard monthly revenue included future confirmed bookings — switched to month-to-date; prev-month comparison capped to same day-of-month
* Fix: Profit/Loss on dashboard now uses actual turnover (paid services + product sales) instead of scheduled price
* Fix: Revenue cards + turnover table reconciliation — completed bookings use paid_amount, confirmed use price everywhere
* Fix: Average booking value now subtracts discount (or uses paid_amount when completed)
* Fix: Weekly chart booking count + revenue filter synced (both confirmed/completed)
* Fix: Week start computed deterministically (ISO Mon-Sun), no more `monday this week` locale edge cases
* Fix: Cancellation rate denominator = confirmed+completed+cancelled (orphan pending excluded)
* Fix: Returning customers counted by customer_id (not email)
* Fix: Staff performance + top services use paid_amount (matches turnover table)
* Fix: Product sales queries use indexed range `>= start AND < next-day` instead of DATE() wrapper
* Fix: Month-boundary timezone — current_time() + explicit time bounds
* Fix: Turnover table includes all active staff (LEFT JOIN)
* New: Booking completion accepts any non-negative paid amount — commission strictly proportional to what was actually received. Pays 30 on a 25 booking? Commission on 30. Pays 20? Commission on 20
* Fix: Re-completing a booking with a different paid_amount recalculates commission

= 3.11.9 =
* New: Floating staff menu on frontend — staff members see a FAB button with quick links to portal pages

= 3.11.8 =
* Fix: My Account dropdown hidden behind banner — removed overflow:hidden and decorative pseudo-elements from welcome banner

= 3.11.7 =
* Fix: My Account button not working — replaced link with dropdown menu (user info, account link, logout)
* New: Email verification banner on booking form for unverified users with resend button

= 3.11.6 =
* Fix: Password reset confirm 404 — modal JS used unbsbPublic which is undefined on non-shortcode pages, now uses inline PHP values

= 3.11.5 =
* Fix: Password reset email not sending — missing template in notification ensure_templates_exist
* Fix: Password reset link opening wrong page — added global overlay modal that works on any page
* Update: Login prompt in booking form — shorter text with visible Login/Register button

= 3.11.4 =
* Fix: Theme button pseudo-elements (::before/::after) overriding plugin button styles

= 3.11.3 =
* Fix: Forgot password in booking modal not working — replaced external link with inline reset form

= 3.11.2 =
* Fix: Fatal error on hosts without PHP calendar extension — replaced cal_days_in_month with gmdate
* Fix: Class UNBSB_Expense_Entry not found — missing require_once in core loader

= 3.11.1 =
* Fix: Fatal error on hosts without PHP calendar extension — replaced cal_days_in_month with gmdate

= 3.11.0 =
* New: Monthly expense tracking — define recurring cost items (rent, utilities, etc.)
* New: Expenses admin page — enter actual monthly amounts with month navigation
* New: Expenses settings tab — manage expense categories with default amounts
* New: Dashboard expenses & profit/loss section — daily cost, today's revenue, profit/loss cards with detail table
* New: Forgot password — custom password reset flow with email template on account page
* Database: Added unbsb_expense_categories, unbsb_expense_entries tables

= 3.10.4 =
* Fix: ICS calendar file not attached to booking received email — missing include_ics parameter
* Fix: Multi-service toggle not saving — checkbox was in General tab HTML but registered under Booking tab in save handler
* Fix: Social login session lost on page refresh with LiteSpeed/Cloudflare cache — client-side auth-check detects cached pages

= 3.10.3 =
* Fix: Social login HMAC-signed state — no transients/cookies, works on any hosting
* Fix: Social auth popup Content-Type set to text/html — prevents browser escaping HTML as JSON
* Fix: First-time discount auth on cached pages — cookie validated directly without nonce
* Fix: Social login fatal error — missing constructor parameter for UNBSB_Public

= 3.10.2 =
* Fix: Social login state validation rewritten — HMAC-signed state, no server-side storage dependency

= 3.10.1 =
* Fix: Social login "Invalid request" error — added cookie-based OAuth state fallback for hosts with object caching
* New: First-time service discount now visible in checkout summary with highlighted "Special discount for you" row
* New: First-time discount recorded in booking internal notes for admin tracking

= 3.10.0 =
* New: Affiliate program — single-level referral system with commission tracking
* New: Admin creates affiliates manually, each gets unique referral code
* New: Referral tracking via link (?ref=CODE cookie) and registration form code input
* New: Level system — more referrals = higher level = higher commission percentage
* New: Commission earned on completed bookings within configurable earning window
* New: Wallet system — earnings accumulate, admin records payouts to deduct balance
* New: Affiliate settings tab — enable/disable, cookie days, earning months, dynamic level configuration
* New: Admin Affiliates page — list, create, activate/deactivate, delete, payout recording
* New: [unbsb_affiliate] shortcode — public affiliate dashboard with stats, referral link, level progress, earnings/payout history
* Database: Added unbsb_affiliates, unbsb_referrals, unbsb_affiliate_earnings, unbsb_affiliate_payouts tables

= 3.9.0 =
* New: Email verification system — customers verify email via link after registration
* New: Google/Apple social login users are automatically email-verified
* New: Resend verification email from account page with rate limiting
* New: Marketing consent checkbox on registration forms (booking modal + account page)
* New: First-time service discount — per-service discount for first-time customers
* New: First-time discount admin UI — discount type (percentage/fixed) and value per service
* New: First-time discount eligibility API endpoint for frontend badge display
* New: Golden badge on service cards showing first-time discount for eligible users
* New: Login prompt banner above booking steps for non-logged-in users
* New: Auth modal always available for non-logged-in users (not just when require_login is on)
* Database: Added email_verified, email_verification_token, marketing_consent columns to customers table
* Database: Added first_time_discount_type, first_time_discount_value columns to services table

= 3.7.0 =
* New: Staff portal — confirm bookings with price adjustment from calendar popup
* New: Calendar popup action buttons for staff portal (Confirm, Reject, Complete, Edit)
* New: Confirm Booking modal with editable price field
* New: Email queue system — background email processing via WP Cron with retry logic
* New: Email Queue admin page — monitor pending, sent, and failed emails
* New: Loyalty program — customers earn a free service after N completed bookings
* New: Loyalty progress cards on customer account page with progress bars
* New: Customer profile editing — name and phone update from account page
* New: PWA support for staff portal — install as mobile app with offline capability
* New: Dashboard revenue vs paid amount tracking with month-over-month comparison
* New: Re-booking reminder emails for inactive customers
* New: Mobile responsive staff portal — card layouts, scrollable tables, touch-friendly UI
* New: "Pending" filter button in staff portal bookings
* Fix: Staff users can now access wp-admin (dual role customer/staff no longer blocked)
* Fix: Staff login redirect no longer overridden by customer redirect
* Fix: Admin/staff bypass Minimum Booking Lead Time when creating bookings

= 3.6.0 =
* New: Require Login setting — customers must authenticate before booking
* New: Auth modal in booking form (login/register tabs)
* New: Google Sign In OAuth integration
* New: Apple Sign In OAuth integration
* New: intl-tel-input phone number input with country code selection
* New: Registration fields: first/last name, phone (required), birthday, gender (optional)
* New: Shortcode `require_login` parameter override (`yes`/`no`)
* Database: Added `birthday` and `gender` columns to customers table

= 3.5.3 =
* Fix: Meta CAPI Purchase events no longer sent for bookings created by admin or staff — only customer bookings from the public form are tracked

= 3.5.2 =
* Fix: Booking creation returning 403 on cached pages — removed stale nonce check from booking and promo code endpoints
* Security maintained via honeypot, CAPTCHA, and rate limiting

= 3.5.1 =
* Fix: Public AJAX endpoints (slots, staff, services) returning 403 for visitors on cached pages
* Fix: Removed nonce verification from read-only public endpoints to prevent cache expiry issues
* New: CAPI Queue Status panel in Tracking settings — view pending/sent/failed counts and recent events

= 3.5.0 =
* New: Meta Conversions API (CAPI) integration — send Purchase events server-side for better ad optimization
* New: Asynchronous event queue with WP Cron processing (every 2 minutes, max 3 retries)
* New: Automatic event deduplication between browser Pixel and server CAPI via shared event_id
* New: User data matching — hashed email, phone, and first name sent for higher match rates
* New: Client IP and User Agent captured at booking time for improved attribution
* New: Settings UI for Conversions API — enable/disable toggle and encrypted Access Token field
* New: Auto-cleanup of sent events older than 30 days
* Database: Added unbsb_capi_queue table

= 3.4.1 =
* Fix: Saving settings on one tab was resetting all other tabs' checkbox settings to default values
* Improvement: Settings save is now tab-aware — only the active tab's options are processed

= 3.4.0 =
* New: Loyalty progress shown in booking form — customer sees "3/9 — 6 more for free!" on email blur
* New: Re-booking reminder emails — automatic "we miss you" email after X days of inactivity (configurable)
* New: Customer profile editing — name and phone update from account page
* New: "Log in for faster booking" hint in booking form for non-logged-in users
* New: Re-booking reminder settings in Email tab (enable/disable + days threshold)

= 3.3.0 =
* New: Loyalty progress cards on customer account page — shows progress bars per service
* New: "FREE!" badge when a loyalty reward is available
* New: Visual progress bar with percentage fill for each tracked service
* Style: Loyalty cards with gradient backgrounds, hover effects, and responsive design

= 3.2.0 =
* New: Month-over-month comparison on dashboard — revenue and customer growth with arrows
* New: Comparison percentage badges on stat cards (green up / red down)
* Fix: Admin and staff users bypass Minimum Booking Lead Time when creating bookings
* Fix: Untranslated strings — PWA placeholder, time format labels, email queue errors

= 3.1.0 =
* New: Loyalty program — customers earn a free service after N completed bookings (configurable, default: 9+1)
* New: Loyalty settings tab — enable/disable, set threshold
* New: Per-service tracking — each service has its own loyalty counter
* New: Automatic price discount — 10th booking price set to 0 automatically
* New: REST API endpoint for loyalty progress (`/wp-json/unbsb/v1/loyalty/{email}`)
* New: Loyalty data passed to frontend booking form
* Database: Added unbsb_loyalty table

= 3.0.0 =
* New: PWA support for staff portal — install as phone app with home screen icon
* New: Offline data viewing — cached bookings and schedule available without internet
* New: PWA settings tab — customize app name, icon, and theme color
* New: Offline banner — shows warning when staff is working without internet
* New: Automatic cache versioning — updates clear old cache on plugin update

= 2.9.4 =
* Fix: Staff portal confirm/reject/complete buttons now work on mobile (was showing "An error occurred" despite success)
* Fix: Staff portal "View" button works on mobile cards — reads data from card layout instead of table row
* Fix: Complete booking updates both desktop table row and mobile card status
* Fix: Staff new booking page redirects to staff portal instead of admin bookings page

= 2.9.3 =
* New: "Pending" filter button in staff portal — quickly see only pending bookings
* Fix: List view stays active when clicking filter buttons (no longer jumps back to calendar)
* Style: Pending filter button styled with amber/warning color to stand out

= 2.9.2 =
* Fix: Staff portal fully responsive on mobile — all tables, modals, filters, and calendars now work on phones
* New: Mobile card layout for bookings list — replaces table on small screens with touch-friendly cards
* New: Horizontal scrollable tables for earnings and performance pages on mobile
* New: Full-screen modals on mobile with proper scrolling
* New: Touch-friendly action buttons with labels on mobile booking cards
* Fix: Date filter and period filter buttons scroll horizontally on small screens
* Fix: Stats grid properly stacks on mobile (2-col at 782px, 1-col at 480px)
* Fix: Off day/extra day items stack vertically on mobile
* Style: FullCalendar toolbar and buttons adjusted for mobile viewports

= 2.9.1 =
* Fix: Fatal error — current_user_can() called too early, moved to admin_init hook
* Fix: Staff role auto-recovery on init hook if role was destroyed
* Fix: Staff role preserved on activation — only missing capabilities added

= 2.9.0 =
* Fix: Staff avatar now saves correctly when creating or editing staff
* Fix: Staff email notification for new bookings — template auto-seeds if missing
* Fix: ICS calendar attachments now work correctly with email queue
* Fix: Auto-run DB migrations on plugin update (no deactivate/activate needed)
* Fix: Staff role no longer destroyed on migration — prevents staff login issues
* Fix: Migration only runs for admin users (staff portal unaffected)
* New: Background email queue — emails sent asynchronously via WP Cron (1-min intervals, 3 retry attempts)
* New: Email Queue admin page — monitor pending, sent, and failed emails
* New: Retry failed emails with one click
* New: Manual and automatic cleanup of old queue records (30 days default, daily cron)
* New: REST API endpoint `/wp-json/unbsb/v1/slots/today?service_id={id}` — today's available slots grouped by staff

= 2.6.0 =
* New: Meta Pixel (Facebook) integration with configurable event tracking
* New: Google Analytics 4 integration with configurable event tracking
* New: Tracking tab in settings — Meta Pixel + Google Analytics side by side
* New: "GA already loaded" option — works with Google Site Kit, MonsterInsights, etc. without conflicts
* Meta Pixel events: PageView, ViewContent, AddToCart, Schedule, InitiateCheckout, Purchase
* GA4 events: page_view, view_item, add_to_cart, begin_checkout, add_shipping_info, purchase
* All tracking events individually toggleable from admin settings

= 2.5.0 =
* New: Staff page converted to table list view (name, contact, status, compensation, balance, actions)
* New: Smooth scroll to top of booking form on every step navigation
* Fix: Staff self-booking now loads available time slots correctly
* Fix: Staff self-booking shows only assigned services (was showing all 59, now shows only staff's own)
* Fix: unbsbNewBookingData localization for staff-new-booking page hook

= 2.4.0 =
* New: Staff can edit/reschedule their own bookings (change date, time, add notes)
* New: "Save & Confirm" button — staff can edit and confirm a booking in one action
* New: Edit button on staff booking rows for pending and confirmed bookings
* New: Staff page converted to table list view with columns: name, contact, status, compensation, balance, actions
* New: Conflict detection when staff reschedules a booking

= 2.3.0 =
* New: Admin Staff View page — combined earnings, performance, and payments in one page
* New: "View" button on staff cards for quick access to staff details
* New: Calendar shows unavailable/closed days with stripe pattern (uses available-days API)
* New: Staff card click auto-advances to date/time selection step
* New: Slot click also auto-advances to date/time step
* New: Category headers shown in single-service booking mode
* New: "Powered by Unbelievable Booking System" footer with version
* Fix: Service name no longer overlaps price on mobile (text wraps fully)
* Fix: Service validation uses highlight animation instead of toast message
* Style: Comprehensive mobile responsive improvements — compact cards, better spacing, 380px breakpoint
* Style: Bold duration text, darker powered-by link

= 2.2.0 =
* New: Staff Earnings Dashboard — view commission, salary, and payment history
* New: Staff Performance Metrics — booking stats, cancellation rate, top services, monthly trends
* New: Admin payment recording — track payments to staff with remaining balance
* New: Remaining balance column on staff list cards
* New: Staff self-booking — staff can create bookings for themselves with filtered services and backend enforcement
* Database: Added unbsb_staff_payments table
* 6 new REST API endpoints for earnings, payments, and performance data

= 2.1.0 =
* Reschedule email notification — customers, admin, and staff now receive email when a booking is rescheduled
* New email template: Booking Rescheduled with {old_booking_date} and {old_booking_time} placeholders
* Fix reminder email timezone — now uses WordPress local time instead of UTC
* Fix staff email template missing on fresh installations
* Fix reminder tracking bloating wp_options — now uses transients with 48h auto-expiry

= 2.0.0 =
* Staff extra working days — staff can add extra open days to their schedule
* Admin booking edit — full edit modal with service, staff, date/time, customer, price
* Admin booking search by customer name or email
* Dashboard metrics: revenue summary, popular services, staff performance, cancellation rate
* Customer CSV import/export
* Booking form appearance customizer (colors, border radius, font size)
* FullCalendar event click to edit booking directly
* Fix view booking button in admin bookings list
* Auto-confirm booking option in settings
* Staff avatar upload via WordPress Media Library
* Fix reminder email duplicate sending
* Fix Booking Manager and ICS Generator dependency loading

= 1.7.0 =
* Fixed email notifications not firing
* Staff portal default calendar weekly view
* FullCalendar integration for admin and staff

= 1.6.0 =
* FullCalendar day/week/month views for admin calendar
* Staff portal list/calendar toggle
* Calendar events API endpoint

= 1.5.0 =
* Staff portal with own bookings and schedule management
* Staff WordPress user creation and linking
* Booking completion with payment recording
* Staff salary/commission system
* Email notification fix

= 1.4.0 =
* Admin new booking page with customer search
* Staff custom pricing per service
* Category-grouped services in booking form
* Compact service cards with inline duration
* Scroll indicators for category filter
* Staff availability cards with nearest slots
* Time format (24h/12h) fix
* Staff data leak fix in public API

= 1.3.0 =
* Multi-service category grouping in booking form
* Stylish category filter buttons
* Service search in admin new booking
* Various bug fixes

= 1.2.0 =
* Added full data export/import functionality
* Export all plugin data (categories, services, staff, customers, bookings, settings) as JSON
* Import data with merge or replace modes
* Admin panel export/import page with drag & drop file upload
* Data validation and security checks for import
* Memory limit and file size checks
* Transaction-based import for data integrity

= 1.1.0 – 2026-03-08 =
* Added: Promo code / coupon system with percentage, fixed amount, and "cheapest service free" discount types
* Added: Per-customer usage limits for promo codes with login requirement
* Added: Discounted price field for services
* Added: Redesigned service selection cards – checkbox on the left, prominent price display on the right with discount badge
* Added: Self-hosted update checker (wp-update-sdk)
* Improved: Booking summary now shows discount details when a promo code is applied

= 1.0.2 – 2026-02-09 =
* Fixed: Text domain changed to match WordPress.org plugin slug (easy-salon-booking)
* Fixed: Removed Plugin URI to avoid duplicate URI with Author URI

= 1.0.1 – 2026-02-09 =
* Fixed: Bundle Chart.js locally instead of CDN
* Fixed: Replaced all inline scripts with wp_localize_script and wp_add_inline_script
* Fixed: Moved inline styles to enqueued CSS file
* Fixed: REST API permission_callback for available-slots endpoint
* Fixed: Plugin URI added to plugin header
* Fixed: readme.txt shortcode references and installation path
* Added: External Services section documenting NetGSM SMS API
* Added: Booking management shortcode [unbsb_manage_booking] to readme

= 1.0.0 – 2025-01-25 =
* Initial release
* Service management with categories, custom duration and pricing
* Staff management with individual schedules
* Working hours configuration per staff member
* Break time and holiday management
* Customer database with booking history
* Email notifications (confirmation, reminder, cancellation)
* SMS notifications via NetGSM
* Interactive calendar view
* Responsive booking form shortcode
* Booking management for customers
* Multi-language support (TR, EN, DE, FR, RU, BG)

== Upgrade Notice ==

= 1.1.0 =
New promo code system, discounted prices, redesigned service cards, and self-hosted update checker.

= 1.0.2 =
Text domain corrected to match WordPress.org slug. No functionality changes.

= 1.0.1 =
Security and coding standards improvements. All assets now bundled locally, inline scripts removed.

= 1.0.0 =
Initial release of Unbelievable Salon Booking. Welcome!
