Changeset 3777386
- Timestamp:
- 10/31/2026 09:47:24 PM (4 hours ago)
- Location:
- awesome-car-rental
- Files:
-
- 356 added
- 1 deleted
- 23 edited
-
tags/1.2.1 (added)
-
tags/1.2.1/admin (added)
-
tags/1.2.1/admin/bookings (added)
-
tags/1.2.1/admin/bookings.php (added)
-
tags/1.2.1/admin/bookings/bookings-edit.php (added)
-
tags/1.2.1/admin/bookings/bookings-list.php (added)
-
tags/1.2.1/admin/bookings/bookings-print.php (added)
-
tags/1.2.1/admin/bookings/bookings-view.php (added)
-
tags/1.2.1/admin/calendar.php (added)
-
tags/1.2.1/admin/cars (added)
-
tags/1.2.1/admin/cars.php (added)
-
tags/1.2.1/admin/cars/cars-add-edit.php (added)
-
tags/1.2.1/admin/cars/cars-delete.php (added)
-
tags/1.2.1/admin/cars/cars-list.php (added)
-
tags/1.2.1/admin/cars/cars-tabs.php (added)
-
tags/1.2.1/admin/cars/cars-view.php (added)
-
tags/1.2.1/admin/categories (added)
-
tags/1.2.1/admin/categories.php (added)
-
tags/1.2.1/admin/categories/categories-add-edit.php (added)
-
tags/1.2.1/admin/categories/categories-delete.php (added)
-
tags/1.2.1/admin/categories/categories-list.php (added)
-
tags/1.2.1/admin/categories/categories-tabs.php (added)
-
tags/1.2.1/admin/categories/categories-view.php (added)
-
tags/1.2.1/admin/customers.php (added)
-
tags/1.2.1/admin/dashboard.php (added)
-
tags/1.2.1/admin/extras.php (added)
-
tags/1.2.1/admin/income-expense (added)
-
tags/1.2.1/admin/income-expense.php (added)
-
tags/1.2.1/admin/income-expense/income-expense-add-edit.php (added)
-
tags/1.2.1/admin/income-expense/income-expense-delete.php (added)
-
tags/1.2.1/admin/income-expense/income-expense-list.php (added)
-
tags/1.2.1/admin/income-expense/income-expense-tab.php (added)
-
tags/1.2.1/admin/income-expense/income-expense-view.php (added)
-
tags/1.2.1/admin/inspections (added)
-
tags/1.2.1/admin/inspections.php (added)
-
tags/1.2.1/admin/inspections/inspections-add-edit.php (added)
-
tags/1.2.1/admin/inspections/inspections-delete.php (added)
-
tags/1.2.1/admin/inspections/inspections-list.php (added)
-
tags/1.2.1/admin/inspections/inspections-view.php (added)
-
tags/1.2.1/admin/maintenance (added)
-
tags/1.2.1/admin/maintenance.php (added)
-
tags/1.2.1/admin/maintenance/maintenance-add-edit.php (added)
-
tags/1.2.1/admin/maintenance/maintenance-delete.php (added)
-
tags/1.2.1/admin/maintenance/maintenance-list.php (added)
-
tags/1.2.1/admin/maintenance/maintenance-tab.php (added)
-
tags/1.2.1/admin/maintenance/maintenance-view.php (added)
-
tags/1.2.1/admin/promos (added)
-
tags/1.2.1/admin/promos.php (added)
-
tags/1.2.1/admin/promos/promos-add-edit.php (added)
-
tags/1.2.1/admin/promos/promos-delete.php (added)
-
tags/1.2.1/admin/promos/promos-list.php (added)
-
tags/1.2.1/admin/report.php (added)
-
tags/1.2.1/admin/seo.php (added)
-
tags/1.2.1/admin/settings (added)
-
tags/1.2.1/admin/settings.php (added)
-
tags/1.2.1/admin/settings/settings-emails.php (added)
-
tags/1.2.1/admin/settings/settings-general.php (added)
-
tags/1.2.1/admin/settings/settings-payments.php (added)
-
tags/1.2.1/admin/settings/settings-tab.php (added)
-
tags/1.2.1/admin/shortcode.php (added)
-
tags/1.2.1/admin/staff (added)
-
tags/1.2.1/admin/staff.php (added)
-
tags/1.2.1/admin/staff/staff-add-edit.php (added)
-
tags/1.2.1/admin/staff/staff-delete.php (added)
-
tags/1.2.1/admin/staff/staff-list.php (added)
-
tags/1.2.1/admin/staff/staff-tab.php (added)
-
tags/1.2.1/admin/staff/staff-view.php (added)
-
tags/1.2.1/admin/style.php (added)
-
tags/1.2.1/assets (added)
-
tags/1.2.1/assets/css (added)
-
tags/1.2.1/assets/css/admin (added)
-
tags/1.2.1/assets/css/admin/admin-booking.css (added)
-
tags/1.2.1/assets/css/admin/admin-calendar.css (added)
-
tags/1.2.1/assets/css/admin/admin-cars.css (added)
-
tags/1.2.1/assets/css/admin/admin-categories.css (added)
-
tags/1.2.1/assets/css/admin/admin-dashboard.css (added)
-
tags/1.2.1/assets/css/admin/admin-extra.css (added)
-
tags/1.2.1/assets/css/admin/admin-income-expense.css (added)
-
tags/1.2.1/assets/css/admin/admin-inspections.css (added)
-
tags/1.2.1/assets/css/admin/admin-main.css (added)
-
tags/1.2.1/assets/css/admin/admin-maintenance.css (added)
-
tags/1.2.1/assets/css/admin/admin-promo.css (added)
-
tags/1.2.1/assets/css/admin/admin-seo.css (added)
-
tags/1.2.1/assets/css/admin/admin-settings.css (added)
-
tags/1.2.1/assets/css/admin/admin-shortcode.css (added)
-
tags/1.2.1/assets/css/admin/admin-staff.css (added)
-
tags/1.2.1/assets/css/admin/admin-style.css (added)
-
tags/1.2.1/assets/css/frontend (added)
-
tags/1.2.1/assets/css/frontend/account.css (added)
-
tags/1.2.1/assets/css/frontend/cars.css (added)
-
tags/1.2.1/assets/css/frontend/checkout.css (added)
-
tags/1.2.1/assets/css/frontend/header-auth.css (added)
-
tags/1.2.1/assets/css/frontend/login.css (added)
-
tags/1.2.1/assets/css/frontend/register.css (added)
-
tags/1.2.1/assets/css/frontend/search.css (added)
-
tags/1.2.1/assets/css/frontend/single-car.css (added)
-
tags/1.2.1/assets/css/frontend/thanks.css (added)
-
tags/1.2.1/assets/css/jquery.dataTables.min.css (added)
-
tags/1.2.1/assets/js (added)
-
tags/1.2.1/assets/js/admin-script.js (added)
-
tags/1.2.1/assets/js/frontend-script.js (added)
-
tags/1.2.1/assets/js/jquery.dataTables.min.js (added)
-
tags/1.2.1/awesome-car-rental.php (added)
-
tags/1.2.1/freemius (added)
-
tags/1.2.1/freemius/LICENSE.txt (added)
-
tags/1.2.1/freemius/README.md (added)
-
tags/1.2.1/freemius/assets (added)
-
tags/1.2.1/freemius/assets/css (added)
-
tags/1.2.1/freemius/assets/css/admin (added)
-
tags/1.2.1/freemius/assets/css/admin/account.css (added)
-
tags/1.2.1/freemius/assets/css/admin/add-ons.css (added)
-
tags/1.2.1/freemius/assets/css/admin/affiliation.css (added)
-
tags/1.2.1/freemius/assets/css/admin/checkout.css (added)
-
tags/1.2.1/freemius/assets/css/admin/clone-resolution.css (added)
-
tags/1.2.1/freemius/assets/css/admin/common.css (added)
-
tags/1.2.1/freemius/assets/css/admin/connect.css (added)
-
tags/1.2.1/freemius/assets/css/admin/debug.css (added)
-
tags/1.2.1/freemius/assets/css/admin/dialog-boxes.css (added)
-
tags/1.2.1/freemius/assets/css/admin/gdpr-optin-notice.css (added)
-
tags/1.2.1/freemius/assets/css/admin/index.php (added)
-
tags/1.2.1/freemius/assets/css/admin/optout.css (added)
-
tags/1.2.1/freemius/assets/css/admin/plugins.css (added)
-
tags/1.2.1/freemius/assets/css/customizer.css (added)
-
tags/1.2.1/freemius/assets/css/index.php (added)
-
tags/1.2.1/freemius/assets/img (added)
-
tags/1.2.1/freemius/assets/img/awesome-car-rental.png (added)
-
tags/1.2.1/freemius/assets/img/index.php (added)
-
tags/1.2.1/freemius/assets/img/plugin-icon.png (added)
-
tags/1.2.1/freemius/assets/img/theme-icon.png (added)
-
tags/1.2.1/freemius/assets/index.php (added)
-
tags/1.2.1/freemius/assets/js (added)
-
tags/1.2.1/freemius/assets/js/index.php (added)
-
tags/1.2.1/freemius/assets/js/jquery.form.js (added)
-
tags/1.2.1/freemius/assets/js/nojquery.ba-postmessage.js (added)
-
tags/1.2.1/freemius/assets/js/postmessage.js (added)
-
tags/1.2.1/freemius/assets/js/pricing (added)
-
tags/1.2.1/freemius/assets/js/pricing/14fb1bd5b7c41648488b06147f50a0dc.svg (added)
-
tags/1.2.1/freemius/assets/js/pricing/178afa6030e76635dbe835e111d2c507.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/27b5a722a5553d9de0170325267fccec.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/4375c4a3ddc6f637c2ab9a2d7220f91e.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/45da596e2b512ffc3bb638baaf0fdc4e.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/a34e046aee1702a5690679750a7f4d0f.svg (added)
-
tags/1.2.1/freemius/assets/js/pricing/b09d0b38b627c2fa564d050f79f2f064.svg (added)
-
tags/1.2.1/freemius/assets/js/pricing/c03f665db27af43971565560adfba594.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/cb5fc4f6ec7ada72e986f6e7dde365bf.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/d65812c447b4523b42d59018e1c0bb53.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/f3aac72a8e63997d6bb888f816457e9b.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/fde48e4609a6ddc11d639fc2421f2afd.png (added)
-
tags/1.2.1/freemius/assets/js/pricing/freemius-pricing.js (added)
-
tags/1.2.1/freemius/assets/js/pricing/freemius-pricing.js.LICENSE.txt (added)
-
tags/1.2.1/freemius/composer.json (added)
-
tags/1.2.1/freemius/config.php (added)
-
tags/1.2.1/freemius/includes (added)
-
tags/1.2.1/freemius/includes/class-freemius-abstract.php (added)
-
tags/1.2.1/freemius/includes/class-freemius.php (added)
-
tags/1.2.1/freemius/includes/class-fs-admin-notices.php (added)
-
tags/1.2.1/freemius/includes/class-fs-api.php (added)
-
tags/1.2.1/freemius/includes/class-fs-garbage-collector.php (added)
-
tags/1.2.1/freemius/includes/class-fs-hook-snapshot.php (added)
-
tags/1.2.1/freemius/includes/class-fs-lock.php (added)
-
tags/1.2.1/freemius/includes/class-fs-logger.php (added)
-
tags/1.2.1/freemius/includes/class-fs-options.php (added)
-
tags/1.2.1/freemius/includes/class-fs-plugin-updater.php (added)
-
tags/1.2.1/freemius/includes/class-fs-security.php (added)
-
tags/1.2.1/freemius/includes/class-fs-storage.php (added)
-
tags/1.2.1/freemius/includes/class-fs-user-lock.php (added)
-
tags/1.2.1/freemius/includes/customizer (added)
-
tags/1.2.1/freemius/includes/customizer/class-fs-customizer-support-section.php (added)
-
tags/1.2.1/freemius/includes/customizer/class-fs-customizer-upsell-control.php (added)
-
tags/1.2.1/freemius/includes/customizer/index.php (added)
-
tags/1.2.1/freemius/includes/debug (added)
-
tags/1.2.1/freemius/includes/debug/class-fs-debug-bar-panel.php (added)
-
tags/1.2.1/freemius/includes/debug/debug-bar-start.php (added)
-
tags/1.2.1/freemius/includes/debug/index.php (added)
-
tags/1.2.1/freemius/includes/entities (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-affiliate-terms.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-affiliate.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-billing.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-entity.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-payment.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-plugin-info.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-plugin-license.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-plugin-plan.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-plugin-tag.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-plugin.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-pricing.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-scope-entity.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-site.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-subscription.php (added)
-
tags/1.2.1/freemius/includes/entities/class-fs-user.php (added)
-
tags/1.2.1/freemius/includes/entities/index.php (added)
-
tags/1.2.1/freemius/includes/fs-core-functions.php (added)
-
tags/1.2.1/freemius/includes/fs-essential-functions.php (added)
-
tags/1.2.1/freemius/includes/fs-html-escaping-functions.php (added)
-
tags/1.2.1/freemius/includes/fs-plugin-info-dialog.php (added)
-
tags/1.2.1/freemius/includes/index.php (added)
-
tags/1.2.1/freemius/includes/l10n.php (added)
-
tags/1.2.1/freemius/includes/managers (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-admin-menu-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-admin-notice-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-cache-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-checkout-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-clone-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-contact-form-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-debug-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-gdpr-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-key-value-storage.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-license-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-option-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-permission-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-plan-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/class-fs-plugin-manager.php (added)
-
tags/1.2.1/freemius/includes/managers/index.php (added)
-
tags/1.2.1/freemius/includes/sdk (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions/ArgumentNotExistException.php (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions/EmptyArgumentException.php (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions/Exception.php (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions/InvalidArgumentException.php (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions/OAuthException.php (added)
-
tags/1.2.1/freemius/includes/sdk/Exceptions/index.php (added)
-
tags/1.2.1/freemius/includes/sdk/FreemiusBase.php (added)
-
tags/1.2.1/freemius/includes/sdk/FreemiusWordPress.php (added)
-
tags/1.2.1/freemius/includes/sdk/LICENSE.txt (added)
-
tags/1.2.1/freemius/includes/sdk/index.php (added)
-
tags/1.2.1/freemius/includes/supplements (added)
-
tags/1.2.1/freemius/includes/supplements/fs-essential-functions-1.1.7.1.php (added)
-
tags/1.2.1/freemius/includes/supplements/fs-essential-functions-2.2.1.php (added)
-
tags/1.2.1/freemius/includes/supplements/fs-migration-2.5.1.php (added)
-
tags/1.2.1/freemius/includes/supplements/index.php (added)
-
tags/1.2.1/freemius/index.php (added)
-
tags/1.2.1/freemius/languages (added)
-
tags/1.2.1/freemius/languages/freemius-cs_CZ.mo (added)
-
tags/1.2.1/freemius/languages/freemius-da_DK.mo (added)
-
tags/1.2.1/freemius/languages/freemius-de_DE.mo (added)
-
tags/1.2.1/freemius/languages/freemius-es_ES.mo (added)
-
tags/1.2.1/freemius/languages/freemius-fr_FR.mo (added)
-
tags/1.2.1/freemius/languages/freemius-he_IL.mo (added)
-
tags/1.2.1/freemius/languages/freemius-hu_HU.mo (added)
-
tags/1.2.1/freemius/languages/freemius-it_IT.mo (added)
-
tags/1.2.1/freemius/languages/freemius-ja.mo (added)
-
tags/1.2.1/freemius/languages/freemius-nl_NL.mo (added)
-
tags/1.2.1/freemius/languages/freemius-ru_RU.mo (added)
-
tags/1.2.1/freemius/languages/freemius-ta.mo (added)
-
tags/1.2.1/freemius/languages/freemius-zh_CN.mo (added)
-
tags/1.2.1/freemius/languages/freemius.pot (added)
-
tags/1.2.1/freemius/languages/index.php (added)
-
tags/1.2.1/freemius/require.php (added)
-
tags/1.2.1/freemius/start.php (added)
-
tags/1.2.1/freemius/templates (added)
-
tags/1.2.1/freemius/templates/account (added)
-
tags/1.2.1/freemius/templates/account.php (added)
-
tags/1.2.1/freemius/templates/account/billing.php (added)
-
tags/1.2.1/freemius/templates/account/index.php (added)
-
tags/1.2.1/freemius/templates/account/partials (added)
-
tags/1.2.1/freemius/templates/account/partials/activate-license-button.php (added)
-
tags/1.2.1/freemius/templates/account/partials/addon.php (added)
-
tags/1.2.1/freemius/templates/account/partials/deactivate-license-button.php (added)
-
tags/1.2.1/freemius/templates/account/partials/disconnect-button.php (added)
-
tags/1.2.1/freemius/templates/account/partials/index.php (added)
-
tags/1.2.1/freemius/templates/account/partials/site.php (added)
-
tags/1.2.1/freemius/templates/account/payments.php (added)
-
tags/1.2.1/freemius/templates/add-ons.php (added)
-
tags/1.2.1/freemius/templates/add-trial-to-pricing.php (added)
-
tags/1.2.1/freemius/templates/admin-notice.php (added)
-
tags/1.2.1/freemius/templates/ajax-loader.php (added)
-
tags/1.2.1/freemius/templates/api-connectivity-message-js.php (added)
-
tags/1.2.1/freemius/templates/auto-installation.php (added)
-
tags/1.2.1/freemius/templates/checkout (added)
-
tags/1.2.1/freemius/templates/checkout.php (added)
-
tags/1.2.1/freemius/templates/checkout/frame.php (added)
-
tags/1.2.1/freemius/templates/checkout/process-redirect.php (added)
-
tags/1.2.1/freemius/templates/checkout/redirect.php (added)
-
tags/1.2.1/freemius/templates/clone-resolution-js.php (added)
-
tags/1.2.1/freemius/templates/connect (added)
-
tags/1.2.1/freemius/templates/connect.php (added)
-
tags/1.2.1/freemius/templates/connect/index.php (added)
-
tags/1.2.1/freemius/templates/connect/permission.php (added)
-
tags/1.2.1/freemius/templates/connect/permissions-group.php (added)
-
tags/1.2.1/freemius/templates/contact.php (added)
-
tags/1.2.1/freemius/templates/debug (added)
-
tags/1.2.1/freemius/templates/debug.php (added)
-
tags/1.2.1/freemius/templates/debug/api-calls.php (added)
-
tags/1.2.1/freemius/templates/debug/index.php (added)
-
tags/1.2.1/freemius/templates/debug/logger.php (added)
-
tags/1.2.1/freemius/templates/debug/plugins-themes-sync.php (added)
-
tags/1.2.1/freemius/templates/debug/scheduled-crons.php (added)
-
tags/1.2.1/freemius/templates/email.php (added)
-
tags/1.2.1/freemius/templates/forms (added)
-
tags/1.2.1/freemius/templates/forms/affiliation.php (added)
-
tags/1.2.1/freemius/templates/forms/data-debug-mode.php (added)
-
tags/1.2.1/freemius/templates/forms/deactivation (added)
-
tags/1.2.1/freemius/templates/forms/deactivation/contact.php (added)
-
tags/1.2.1/freemius/templates/forms/deactivation/form.php (added)
-
tags/1.2.1/freemius/templates/forms/deactivation/index.php (added)
-
tags/1.2.1/freemius/templates/forms/deactivation/retry-skip.php (added)
-
tags/1.2.1/freemius/templates/forms/email-address-update.php (added)
-
tags/1.2.1/freemius/templates/forms/index.php (added)
-
tags/1.2.1/freemius/templates/forms/license-activation.php (added)
-
tags/1.2.1/freemius/templates/forms/optout.php (added)
-
tags/1.2.1/freemius/templates/forms/premium-versions-upgrade-handler.php (added)
-
tags/1.2.1/freemius/templates/forms/premium-versions-upgrade-metadata.php (added)
-
tags/1.2.1/freemius/templates/forms/resend-key.php (added)
-
tags/1.2.1/freemius/templates/forms/subscription-cancellation.php (added)
-
tags/1.2.1/freemius/templates/forms/trial-start.php (added)
-
tags/1.2.1/freemius/templates/forms/user-change.php (added)
-
tags/1.2.1/freemius/templates/gdpr-optin-js.php (added)
-
tags/1.2.1/freemius/templates/index.php (added)
-
tags/1.2.1/freemius/templates/js (added)
-
tags/1.2.1/freemius/templates/js/index.php (added)
-
tags/1.2.1/freemius/templates/js/jquery.content-change.php (added)
-
tags/1.2.1/freemius/templates/js/open-license-activation.php (added)
-
tags/1.2.1/freemius/templates/js/permissions.php (added)
-
tags/1.2.1/freemius/templates/js/style-premium-theme.php (added)
-
tags/1.2.1/freemius/templates/partials (added)
-
tags/1.2.1/freemius/templates/partials/index.php (added)
-
tags/1.2.1/freemius/templates/partials/network-activation.php (added)
-
tags/1.2.1/freemius/templates/plugin-icon.php (added)
-
tags/1.2.1/freemius/templates/plugin-info (added)
-
tags/1.2.1/freemius/templates/plugin-info/description.php (added)
-
tags/1.2.1/freemius/templates/plugin-info/features.php (added)
-
tags/1.2.1/freemius/templates/plugin-info/index.php (added)
-
tags/1.2.1/freemius/templates/plugin-info/screenshots.php (added)
-
tags/1.2.1/freemius/templates/pricing.php (added)
-
tags/1.2.1/freemius/templates/secure-https-header.php (added)
-
tags/1.2.1/freemius/templates/sticky-admin-notice-js.php (added)
-
tags/1.2.1/freemius/templates/tabs-capture-js.php (added)
-
tags/1.2.1/freemius/templates/tabs.php (added)
-
tags/1.2.1/frontend (added)
-
tags/1.2.1/frontend/account (added)
-
tags/1.2.1/frontend/account/acrb-frontned-account.php (added)
-
tags/1.2.1/frontend/auth (added)
-
tags/1.2.1/frontend/auth/acrb-frontend-auth.php (added)
-
tags/1.2.1/frontend/cars (added)
-
tags/1.2.1/frontend/cars/acrb-frontend-cars-grid.php (added)
-
tags/1.2.1/frontend/cars/acrb-frontend-cars.php (added)
-
tags/1.2.1/frontend/checkout (added)
-
tags/1.2.1/frontend/checkout/acrb-frontned-checkout.php (added)
-
tags/1.2.1/frontend/frontend.php (added)
-
tags/1.2.1/frontend/login (added)
-
tags/1.2.1/frontend/login/acrb-frontend-login.php (added)
-
tags/1.2.1/frontend/registration (added)
-
tags/1.2.1/frontend/registration/acrb-frontend-register.php (added)
-
tags/1.2.1/frontend/search (added)
-
tags/1.2.1/frontend/search/acrb-frontend-search-form.php (added)
-
tags/1.2.1/frontend/single (added)
-
tags/1.2.1/frontend/single/acrb-frontned-car-single.php (added)
-
tags/1.2.1/frontend/thanks (added)
-
tags/1.2.1/frontend/thanks/acrb-frontned-thanks.php (added)
-
tags/1.2.1/includes (added)
-
tags/1.2.1/includes/assets.php (added)
-
tags/1.2.1/includes/database.php (added)
-
tags/1.2.1/includes/menus.php (added)
-
tags/1.2.1/readme.txt (added)
-
trunk/assets/css/admin-main.css (deleted)
-
trunk/assets/css/admin/admin-main.css (added)
-
trunk/assets/css/frontend/account.css (modified) (28 diffs)
-
trunk/assets/css/frontend/cars.css (modified) (13 diffs)
-
trunk/assets/css/frontend/checkout.css (modified) (16 diffs)
-
trunk/assets/css/frontend/header-auth.css (modified) (12 diffs)
-
trunk/assets/css/frontend/login.css (modified) (16 diffs)
-
trunk/assets/css/frontend/register.css (modified) (15 diffs)
-
trunk/assets/css/frontend/search.css (modified) (13 diffs)
-
trunk/assets/css/frontend/single-car.css (modified) (23 diffs)
-
trunk/assets/css/frontend/thanks.css (modified) (30 diffs)
-
trunk/awesome-car-rental.php (modified) (1 diff)
-
trunk/frontend/account/acrb-frontned-account.php (modified) (19 diffs)
-
trunk/frontend/auth/acrb-frontend-auth.php (modified) (5 diffs)
-
trunk/frontend/cars/acrb-frontend-cars-grid.php (added)
-
trunk/frontend/cars/acrb-frontend-cars.php (modified) (25 diffs)
-
trunk/frontend/checkout/acrb-frontned-checkout.php (modified) (26 diffs)
-
trunk/frontend/frontend.php (modified) (1 diff)
-
trunk/frontend/login/acrb-frontend-login.php (modified) (9 diffs)
-
trunk/frontend/registration/acrb-frontend-register.php (modified) (6 diffs)
-
trunk/frontend/search/acrb-frontend-search-form.php (modified) (9 diffs)
-
trunk/frontend/single/acrb-frontned-car-single.php (modified) (38 diffs)
-
trunk/frontend/thanks/acrb-frontned-thanks.php (modified) (7 diffs)
-
trunk/includes/assets.php (modified) (1 diff)
-
trunk/includes/database.php (modified) (7 diffs)
-
trunk/readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
awesome-car-rental/trunk/assets/css/frontend/account.css
r3775773 r3777386 1 1 /* ========================================================================== 2 ACRB CUSTOMER ACCOUNT PORTAL (SCOPED TO COMPONENTS - NO :ROOT) 2 ACRB CUSTOMER ACCOUNT PORTAL (SCOPED TO COMPONENTS - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/account.css 3 4 ========================================================================== */ 4 5 … … 7 8 .acrb-auth-locked, 8 9 #acrb-receipt-modal { 9 --acrb-primary: #4f46e5; 10 --acrb-secondary: #64748b; 11 --acrb-text: #0f172a; 12 --acrb-accent: #059669; 10 --acrb-portal-primary: #4f46e5; 11 --acrb-portal-secondary: #64748b; 12 --acrb-portal-text: #0f172a; 13 --acrb-portal-accent: #059669; 14 --acrb-portal-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 13 15 --acrb-btn-bg: #4f46e5; 14 16 --acrb-btn-hover: #4338ca; 15 --acrb-font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 16 --acrb-portal-primary: var(--acrb-primary); 17 --acrb-portal-secondary: var(--acrb-secondary); 18 --acrb-portal-text: var(--acrb-text); 19 --acrb-portal-accent: var(--acrb-accent); 20 --acrb-portal-font: var(--acrb-font-family); 21 22 font-family: var(--acrb-portal-font); 23 color: var(--acrb-portal-text); 24 } 25 26 /* Base resets & icon styling */ 27 .acrb-acc-wrapper, 17 18 font-family: var(--acrb-portal-font, sans-serif); 19 color: var(--acrb-portal-text, #0f172a); 20 box-sizing: border-box; 21 } 22 28 23 .acrb-acc-wrapper *, 29 24 .acrb-acc-wrapper *::before, 30 25 .acrb-acc-wrapper *::after, 31 .acrb-auth-locked,32 26 .acrb-auth-locked *, 33 27 .acrb-auth-locked *::before, 34 28 .acrb-auth-locked *::after, 35 #acrb-receipt-modal,36 29 #acrb-receipt-modal *, 37 30 #acrb-receipt-modal *::before, 38 31 #acrb-receipt-modal *::after { 39 box-sizing: border-box; 40 } 41 32 box-sizing: inherit; 33 } 34 35 /* Universal SVG Icon Standards */ 42 36 .acrb-icon { 43 37 display: inline-block; … … 54 48 55 49 /* -------------------------------------------------------------------------- 56 Auth Lock Screen (Logged Out )50 Auth Lock Screen (Logged Out State) 57 51 -------------------------------------------------------------------------- */ 58 52 .acrb-auth-locked { 59 max-width: 440px;53 max-width: 520px; 60 54 margin: 60px auto; 61 padding: 44px 32px; 55 text-align: center; 56 background: #ffffff; 57 border: 1px solid #e2e8f0; 58 border-radius: 20px; 59 padding: 40px 30px; 60 box-shadow: 0 10px 30px -10px rgba(15, 23, 42, 0.08); 61 } 62 63 .acrb-auth-locked-icon { 64 width: 60px; 65 height: 60px; 66 background: #f1f5f9; 67 border-radius: 50%; 68 display: flex; 69 align-items: center; 70 justify-content: center; 71 margin: 0 auto 20px auto; 72 color: var(--acrb-portal-primary, #4f46e5); 73 } 74 75 .acrb-auth-locked-icon svg { 76 width: 28px; 77 height: 28px; 78 } 79 80 .acrb-auth-locked h2 { 81 font-size: 1.5rem; 82 font-weight: 800; 83 margin: 0 0 10px 0; 84 color: var(--acrb-portal-text, #0f172a); 85 } 86 87 .acrb-auth-locked p { 88 color: var(--acrb-portal-secondary, #64748b); 89 font-size: 0.95rem; 90 line-height: 1.6; 91 margin: 0 0 24px 0; 92 } 93 94 .acrb-auth-btn-primary { 95 display: inline-flex; 96 align-items: center; 97 justify-content: center; 98 gap: 8px; 99 background: var(--acrb-btn-bg, #4f46e5); 100 color: #ffffff !important; 101 text-decoration: none !important; 102 padding: 12px 24px; 103 border-radius: 10px; 104 font-weight: 700; 105 font-size: 0.92rem; 106 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 107 transition: background-color 0.2s ease, transform 0.15s ease, opacity 0.15s ease; 108 } 109 110 .acrb-auth-btn-primary:hover { 111 background: var(--acrb-btn-hover, #4338ca); 112 transform: translateY(-1px); 113 opacity: 0.94; 114 } 115 116 /* -------------------------------------------------------------------------- 117 Account Portal Wrapper Layout 118 -------------------------------------------------------------------------- */ 119 .acrb-acc-wrapper { 120 display: flex; 121 gap: 30px; 122 align-items: flex-start; 123 max-width: 1280px; 124 margin: 0 auto; 125 padding: 30px 16px 60px 16px; 126 } 127 128 .acrb-acc-nav { 129 width: 280px; 130 flex-shrink: 0; 62 131 background: #ffffff; 63 132 border: 1px solid #e2e8f0; 64 133 border-radius: 16px; 65 text-align: center; 66 box-shadow: 0 10px 25px -5px rgba(15, 23, 42, 0.05); 67 } 68 69 .acrb-auth-locked-icon { 70 width: 60px; 71 height: 60px; 72 margin: 0 auto 18px; 73 background: #f1f5f9; 74 color: var(--acrb-portal-primary); 75 border-radius: 50%; 76 display: flex; 77 align-items: center; 78 justify-content: center; 79 } 80 81 .acrb-auth-locked-icon svg { 82 width: 28px; 83 height: 28px; 84 } 85 86 .acrb-auth-locked h2 { 87 margin: 0 0 8px; 88 font-size: 20px; 89 font-weight: 800; 90 color: var(--acrb-portal-text); 91 } 92 93 .acrb-auth-locked p { 94 color: var(--acrb-portal-secondary); 95 font-size: 13.5px; 96 line-height: 1.5; 97 margin: 0 0 24px; 98 } 99 100 .acrb-auth-btn-primary { 101 background: var(--acrb-btn-bg); 102 color: #ffffff !important; 103 text-decoration: none; 104 padding: 12px 24px; 105 border-radius: 8px; 106 font-weight: 700; 107 font-size: 13.5px; 108 display: inline-flex; 109 align-items: center; 110 gap: 8px; 111 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 112 transition: background-color 0.2s ease, opacity 0.15s ease, transform 0.15s ease; 113 } 114 115 .acrb-auth-btn-primary:hover { 116 background: var(--acrb-btn-hover); 117 opacity: 0.94; 118 transform: translateY(-1px); 119 } 120 121 /* -------------------------------------------------------------------------- 122 Account Wrapper Layout 123 -------------------------------------------------------------------------- */ 124 .acrb-acc-wrapper { 125 display: flex; 126 gap: 28px; 127 margin: 30px auto; 128 max-width: 1200px; 129 } 130 131 .acrb-acc-nav { 132 width: 280px; 133 flex-shrink: 0; 134 } 135 136 .acrb-acc-content { 137 flex: 1; 138 min-width: 0; 139 } 140 141 /* -------------------------------------------------------------------------- 142 Navigation Sidebar 143 -------------------------------------------------------------------------- */ 134 padding: 24px; 135 box-shadow: 0 4px 20px -4px rgba(15, 23, 42, 0.05); 136 } 137 144 138 .acrb-nav-user { 145 139 display: flex; 146 140 align-items: center; 147 gap: 14px; 148 margin-bottom: 20px; 149 padding: 18px 20px; 150 background: #ffffff; 151 border: 1px solid #e2e8f0; 152 border-radius: 14px; 153 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03); 141 gap: 12px; 142 padding-bottom: 20px; 143 margin-bottom: 18px; 144 border-bottom: 1px solid #f1f5f9; 154 145 } 155 146 156 147 .acrb-nav-avatar img { 157 148 border-radius: 50%; 149 width: 46px; 150 height: 46px; 158 151 object-fit: cover; 159 152 display: block; … … 162 155 .acrb-nav-info strong { 163 156 display: block; 164 color: var(--acrb-portal-text); 165 font-size: 14.5px; 157 font-size: 0.95rem; 166 158 font-weight: 800; 167 line-height: 1.25;159 color: var(--acrb-portal-text, #0f172a); 168 160 } 169 161 170 162 .acrb-nav-info span { 171 font-size: 11px; 172 color: var(--acrb-portal-primary); 173 font-weight: 700; 174 text-transform: uppercase; 175 letter-spacing: 0.04em; 163 font-size: 0.78rem; 164 color: var(--acrb-portal-secondary, #64748b); 176 165 } 177 166 … … 180 169 padding: 0; 181 170 margin: 0; 182 background: #ffffff; 183 border: 1px solid #e2e8f0; 184 border-radius: 14px; 185 overflow: hidden; 186 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03); 171 display: flex; 172 flex-direction: column; 173 gap: 6px; 187 174 } 188 175 … … 190 177 display: flex; 191 178 align-items: center; 192 gap: 12px; 193 padding: 14px 20px; 194 text-decoration: none; 195 color: var(--acrb-portal-secondary); 196 font-size: 13.5px; 179 gap: 10px; 180 padding: 10px 14px; 181 border-radius: 10px; 182 color: var(--acrb-portal-secondary, #64748b); 197 183 font-weight: 600; 184 font-size: 0.9rem; 198 185 cursor: pointer; 199 transition: all 0.15s ease; 186 text-decoration: none !important; 187 transition: all 0.2s ease; 200 188 border-left: 3px solid transparent; 201 189 } 202 190 203 #acrb-nav-list li a .acrb-icon{204 color: var(--acrb-portal-secondary);205 transition: color 0.15s ease;191 #acrb-nav-list li a:hover { 192 background: #f8fafc; 193 color: var(--acrb-portal-primary, #4f46e5); 206 194 } 207 195 208 196 #acrb-nav-list li.active a { 209 background: #eff6ff; 210 color: var(--acrb-portal-primary) !important; 211 border-left-color: var(--acrb-portal-primary) !important; 212 } 213 214 #acrb-nav-list li.active a .acrb-icon { 215 color: var(--acrb-portal-primary) !important; 216 } 217 218 #acrb-nav-list li a:hover:not(.active) { 219 background: #f8fafc; 220 color: var(--acrb-portal-text); 221 } 222 223 .acrb-nav-logout a { 197 background: #eef2ff; 198 color: var(--acrb-portal-primary, #4f46e5); 199 border-left-color: var(--acrb-portal-primary, #4f46e5); 200 font-weight: 700; 201 } 202 203 #acrb-nav-list li.acrb-nav-logout { 204 margin-top: 10px; 205 padding-top: 10px; 206 border-top: 1px dashed #e2e8f0; 207 } 208 209 #acrb-nav-list li.acrb-nav-logout a { 224 210 color: #dc2626 !important; 225 border-top: 1px solid #f1f5f9; 226 } 227 228 .acrb-nav-logout a:hover { 211 } 212 213 #acrb-nav-list li.acrb-nav-logout a:hover { 229 214 background: #fef2f2 !important; 230 215 } 231 216 232 .acrb-nav-logout a .acrb-icon {233 color: #dc2626 !important;234 }235 236 217 /* -------------------------------------------------------------------------- 237 Tabs & Header (Solid Minimalist, No Gradients)218 Main Content Panels 238 219 -------------------------------------------------------------------------- */ 220 .acrb-acc-content { 221 flex: 1; 222 min-width: 0; 223 } 224 239 225 .acrb-tab-panel { 240 226 display: none; … … 258 244 259 245 .acrb-panel-title { 260 font-size: 1 7px;246 font-size: 1.45rem; 261 247 font-weight: 800; 262 color: var(--acrb-portal-text);263 margin: 0 0 18px;264 letter-spacing: -0.01em;248 margin: 0 0 20px 0; 249 letter-spacing: -0.02em; 250 color: var(--acrb-portal-text, #0f172a); 265 251 } 266 252 … … 268 254 background: #ffffff; 269 255 border: 1px solid #e2e8f0; 270 border-left: 4px solid var(--acrb-portal-primary );256 border-left: 4px solid var(--acrb-portal-primary, #4f46e5); 271 257 border-radius: 14px; 272 258 padding: 22px 26px; … … 276 262 277 263 .acrb-dash-header h2 { 278 margin: 0 0 4px; 279 font-size: 20px; 264 font-size: 1.55rem; 280 265 font-weight: 800; 281 color: var(--acrb-portal-text);266 margin: 0 0 6px 0; 282 267 letter-spacing: -0.02em; 268 color: var(--acrb-portal-text, #0f172a); 283 269 } 284 270 285 271 .acrb-dash-header p { 272 color: var(--acrb-portal-secondary, #64748b); 286 273 margin: 0; 287 color: var(--acrb-portal-secondary); 288 font-size: 13.5px; 274 font-size: 0.92rem; 289 275 } 290 276 … … 293 279 grid-template-columns: repeat(2, 1fr); 294 280 gap: 18px; 295 margin-bottom: 2 2px;281 margin-bottom: 24px; 296 282 } 297 283 … … 299 285 background: #ffffff; 300 286 border: 1px solid #e2e8f0; 287 border-radius: 16px; 301 288 padding: 22px; 302 border-radius: 14px; 303 text-align: center; 304 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03); 289 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.03); 305 290 display: flex; 306 291 flex-direction: column; 307 align-items: center; 308 gap: 6px; 292 align-items: flex-start; 309 293 } 310 294 … … 312 296 width: 44px; 313 297 height: 44px; 314 background: #f1f5f9;315 color: var(--acrb-portal-primary);316 298 border-radius: 12px; 299 background: #eef2ff; 300 color: var(--acrb-portal-primary, #4f46e5); 317 301 display: flex; 318 302 align-items: center; 319 303 justify-content: center; 320 } 321 322 .acrb-stat-icon .acrb-icon { 323 width: 22px; 324 height: 22px; 304 margin-bottom: 12px; 325 305 } 326 306 327 307 .acrb-stat-val { 328 font-size: 24px;308 font-size: 1.7rem; 329 309 font-weight: 800; 330 color: var(--acrb-portal-text); 331 letter-spacing: -0.02em; 310 color: var(--acrb-portal-text, #0f172a); 311 line-height: 1.1; 312 margin-bottom: 4px; 332 313 } 333 314 334 315 .acrb-stat-label { 335 font-size: 11.5px; 336 color: var(--acrb-portal-secondary); 337 font-weight: 700; 338 text-transform: uppercase; 339 letter-spacing: 0.04em; 316 font-size: 0.8rem; 317 color: var(--acrb-portal-secondary, #64748b); 318 font-weight: 600; 340 319 } 341 320 342 321 .acrb-promo-banner { 343 background: var(--acrb-portal- primary);322 background: var(--acrb-portal-text, #0f172a); 344 323 color: #ffffff; 345 border-radius: 1 4px;324 border-radius: 16px; 346 325 padding: 24px 28px; 347 326 display: flex; 348 327 justify-content: space-between; 349 328 align-items: center; 350 box-shadow: 0 4px 20px -2px rgba(15, 23, 42, 0.15); 351 gap: 16px; 329 gap: 20px; 352 330 } 353 331 354 332 .acrb-promo-content h3 { 355 margin: 0 0 4px; 356 font-size: 17px; 333 margin: 0 0 6px 0; 334 font-size: 1.15rem; 335 color: #ffffff; 357 336 font-weight: 800; 358 color: #ffffff;359 337 } 360 338 361 339 .acrb-promo-content p { 362 340 margin: 0; 363 font-size: 13.5px; 364 opacity: 0.9; 365 color: #ffffff; 341 font-size: 0.85rem; 342 color: #94a3b8; 366 343 } 367 344 368 345 .acrb-btn-white { 369 346 background: #ffffff; 370 color: var(--acrb-portal-primary) !important; 371 text-decoration: none; 372 padding: 10px 20px; 373 border-radius: 8px; 374 font-weight: 700; 375 font-size: 13px; 376 transition: all 0.15s ease; 377 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08); 347 color: #0f172a !important; 348 padding: 10px 18px; 349 border-radius: 10px; 350 font-weight: 700; 351 font-size: 0.85rem; 352 text-decoration: none !important; 378 353 display: inline-flex; 379 354 align-items: center; 380 355 gap: 6px; 381 356 white-space: nowrap; 357 transition: background 0.2s ease, transform 0.15s ease; 382 358 } 383 359 384 360 .acrb-btn-white:hover { 385 background: #f 8fafc;361 background: #f1f5f9; 386 362 transform: translateY(-1px); 387 363 } 388 364 389 365 /* -------------------------------------------------------------------------- 390 Bookings & Rental History 366 Bookings & Rental History List 391 367 -------------------------------------------------------------------------- */ 392 368 .acrb-booking-card { 393 369 background: #ffffff; 394 370 border: 1px solid #e2e8f0; 395 border-radius: 14px; 371 border-radius: 16px; 372 padding: 20px 24px; 396 373 margin-bottom: 16px; 397 overflow: hidden; 398 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03); 374 box-shadow: 0 2px 10px rgba(15, 23, 42, 0.03); 399 375 transition: border-color 0.15s ease, box-shadow 0.15s ease; 400 376 } … … 407 383 .acrb-card-main { 408 384 display: flex; 409 gap: 1 8px;410 padding: 20px 22px;411 align-items: center;385 gap: 16px; 386 align-items: center; 387 margin-bottom: 16px; 412 388 } 413 389 414 390 .acrb-car-icon { 415 background: #f8fafc;416 color: var(--acrb-portal-primary);417 391 width: 48px; 418 392 height: 48px; 419 393 min-width: 48px; 420 394 border-radius: 12px; 395 background: #f8fafc; 421 396 border: 1px solid #e2e8f0; 422 397 display: flex; 423 398 align-items: center; 424 399 justify-content: center; 425 } 426 427 .acrb-car-icon .acrb-icon { 428 width: 24px; 429 height: 24px; 400 color: var(--acrb-portal-primary, #4f46e5); 401 flex-shrink: 0; 430 402 } 431 403 432 404 .acrb-booking-details { 433 405 flex: 1; 406 min-width: 0; 434 407 } 435 408 … … 443 416 .acrb-car-name { 444 417 margin: 0; 445 font-size: 1 6px;418 font-size: 1.05rem; 446 419 font-weight: 800; 447 color: var(--acrb-portal-text );420 color: var(--acrb-portal-text, #0f172a); 448 421 } 449 422 450 423 .acrb-status-pill { 451 font-size: 11px; 424 font-size: 0.74rem; 425 font-weight: 700; 452 426 padding: 3px 10px; 453 427 border-radius: 9999px; 454 font-weight: 700; 455 text-transform: uppercase; 456 letter-spacing: 0.04em; 428 text-transform: capitalize; 457 429 display: inline-block; 458 430 } 459 431 432 .status-confirmed, 460 433 .status-completed, 461 .status-confirmed, 462 .status-active, 434 .status-active { 435 background: #dcfce7; 436 color: #15803d; 437 border: 1px solid #a7f3d0; 438 } 439 463 440 .status-pending { 464 background: # ecfdf5;465 color: var(--acrb-portal-accent);466 border: 1px solid # a7f3d0;441 background: #fef3c7; 442 color: #b45309; 443 border: 1px solid #fde68a; 467 444 } 468 445 469 446 .status-cancelled { 470 background: #fe f2f2;471 color: # dc2626;447 background: #fee2e2; 448 color: #b91c1c; 472 449 border: 1px solid #fecaca; 473 450 } … … 476 453 display: flex; 477 454 gap: 16px; 478 font-size: 12.5px; 479 color: var(--acrb-portal-secondary); 480 font-weight: 500; 455 font-size: 0.8rem; 456 color: var(--acrb-portal-secondary, #64748b); 481 457 flex-wrap: wrap; 482 458 } … … 488 464 } 489 465 490 .acrb-meta-item .acrb-icon {491 width: 14px;492 height: 14px;493 color: var(--acrb-portal-secondary);494 }495 496 466 .acrb-card-footer { 497 background: #f8fafc;498 padding: 14px 22px;499 border-top: 1px solid #f1f5f9;500 467 display: flex; 501 468 justify-content: space-between; 502 469 align-items: center; 470 padding-top: 14px; 471 border-top: 1px dashed #e2e8f0; 503 472 } 504 473 … … 509 478 510 479 .acrb-price-label { 511 font-size: 11px; 512 color: var(--acrb-portal-secondary); 513 font-weight: 700; 480 font-size: 0.72rem; 514 481 text-transform: uppercase; 515 letter-spacing: 0.04em; 482 color: var(--acrb-portal-secondary, #64748b); 483 font-weight: 700; 516 484 } 517 485 518 486 .acrb-price-amount { 487 font-size: 1.15rem; 519 488 font-weight: 800; 520 color: var(--acrb-portal-accent) !important; 521 font-size: 18px; 522 letter-spacing: -0.01em; 523 } 524 489 color: var(--acrb-portal-accent, #059669); 490 } 491 492 button.acrb-btn-outline, 525 493 .acrb-btn-outline { 526 494 background: #ffffff; 527 color: var(--acrb-portal-text);528 495 border: 1px solid #cbd5e1; 529 padding: 8px 16px; 496 color: var(--acrb-portal-text, #0f172a); 497 padding: 8px 14px; 530 498 border-radius: 8px; 531 499 font-weight: 700; 532 font-size: 12.5px;500 font-size: 0.82rem; 533 501 cursor: pointer; 534 502 display: inline-flex; 535 503 align-items: center; 536 504 gap: 6px; 537 transition: all 0.15s ease; 538 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02); 505 transition: all 0.2s ease; 539 506 font-family: inherit; 540 507 } 541 508 509 button.acrb-btn-outline:hover, 542 510 .acrb-btn-outline:hover { 543 background: #f1f5f9; 544 border-color: #94a3b8; 545 } 546 547 .acrb-btn-outline .acrb-icon { 548 width: 14px; 549 height: 14px; 550 color: var(--acrb-portal-secondary); 511 border-color: var(--acrb-portal-primary, #4f46e5); 512 color: var(--acrb-portal-primary, #4f46e5); 513 background: #f8fafc; 551 514 } 552 515 553 516 .acrb-empty-box { 517 text-align: center; 554 518 padding: 48px 20px; 555 text-align: center;556 519 background: #ffffff; 557 border: 1px solid #e2e8f0; 558 border-radius: 14px; 559 color: var(--acrb-portal-secondary); 560 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03); 520 border: 1px dashed #cbd5e1; 521 border-radius: 16px; 522 color: var(--acrb-portal-secondary, #64748b); 561 523 } 562 524 … … 564 526 width: 42px; 565 527 height: 42px; 528 margin-bottom: 10px; 566 529 color: #cbd5e1; 567 margin-bottom: 10px;568 530 } 569 531 … … 575 537 576 538 /* -------------------------------------------------------------------------- 577 Forms & Controls539 Settings Forms & Controls 578 540 -------------------------------------------------------------------------- */ 579 541 .acrb-settings-form { 580 542 background: #ffffff; 581 543 border: 1px solid #e2e8f0; 582 border-radius: 1 4px;583 padding: 2 8px;584 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03);544 border-radius: 16px; 545 padding: 24px; 546 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.03); 585 547 } 586 548 587 549 .acrb-form-row { 588 display: grid;589 g rid-template-columns: 1fr 1fr;590 gap: 18px;550 display: flex; 551 gap: 16px; 552 margin-bottom: 16px; 591 553 } 592 554 593 555 .acrb-form-group { 594 margin-bottom: 18px; 595 display: flex; 596 flex-direction: column; 556 flex: 1; 597 557 } 598 558 599 559 .acrb-form-group label { 600 font-size: 13px; 601 font-weight: 700; 560 display: block; 561 font-size: 0.78rem; 562 font-weight: 700; 563 text-transform: uppercase; 564 letter-spacing: 0.04em; 565 color: #475569; 602 566 margin-bottom: 6px; 603 color: var(--acrb-portal-text);604 567 } 605 568 … … 611 574 padding: 0 14px !important; 612 575 font-size: 13.5px !important; 613 color: var(--acrb-portal-text ) !important;576 color: var(--acrb-portal-text, #0f172a) !important; 614 577 background: #f8fafc !important; 615 578 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important; … … 638 601 .acrb-textarea:focus { 639 602 background: #ffffff !important; 640 border-color: var(--acrb-portal-primary ) !important;641 box-shadow: 0 0 0 3px rgba( 15, 23, 42, 0.08) !important;603 border-color: var(--acrb-portal-primary, #4f46e5) !important; 604 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.12) !important; 642 605 outline: none !important; 643 606 } … … 645 608 .acrb-readonly { 646 609 background: #f1f5f9 !important; 647 color: var(--acrb-portal-secondary ) !important;610 color: var(--acrb-portal-secondary, #64748b) !important; 648 611 cursor: not-allowed !important; 649 612 border-color: #e2e8f0 !important; 650 613 } 651 614 652 .acrb-btn-submit { 653 background-color: var(--acrb-btn-bg) !important; 654 border-color: var(--acrb-btn-bg) !important; 615 button.acrb-btn-submit { 616 display: inline-flex; 617 align-items: center; 618 justify-content: center; 619 gap: 8px; 620 background: var(--acrb-btn-bg, #4f46e5) !important; 655 621 color: #ffffff !important; 656 622 border: none; 657 padding: 11px 24px;658 border-radius: 8px;659 font- weight: 700;660 font- size: 13.5px;623 border-radius: 10px; 624 padding: 10px 20px; 625 font-size: 0.9rem; 626 font-weight: 700; 661 627 cursor: pointer; 662 628 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 663 629 transition: background-color 0.2s ease, transform 0.15s ease; 664 display: inline-flex;665 align-items: center;666 justify-content: center;667 gap: 8px;668 630 font-family: inherit; 669 631 } 670 632 671 .acrb-btn-submit:hover { 672 background-color: var(--acrb-btn-hover) !important; 673 border-color: var(--acrb-btn-hover) !important; 633 button.acrb-btn-submit:hover { 634 background: var(--acrb-btn-hover, #4338ca) !important; 674 635 transform: translateY(-1px); 675 636 } … … 680 641 } 681 642 682 /* -------------------------------------------------------------------------- 683 Alerts & Notifications 684 -------------------------------------------------------------------------- */ 643 /* Alerts */ 685 644 .acrb-alert { 686 645 padding: 12px 16px; 687 border-radius: 8px;646 border-radius: 10px; 688 647 margin-bottom: 20px; 689 font-size: 13px;648 font-size: 0.88rem; 690 649 font-weight: 600; 691 display: flex;692 align-items: center;693 gap: 8px;694 650 } 695 651 696 652 .acrb-alert.success { 697 background: # ecfdf5;698 color: #065f46;699 border: 1px solid #a7f3d0;653 background: #f0fdf4; 654 border: 1px solid #bbf7d0; 655 color: #15803d; 700 656 } 701 657 702 658 .acrb-alert.error { 703 659 background: #fef2f2; 704 color: #991b1b;705 660 border: 1px solid #fecaca; 661 color: #b91c1c; 662 } 663 664 /* -------------------------------------------------------------------------- 665 Password Strength & Real-Time Confirmation 666 -------------------------------------------------------------------------- */ 667 .acrb-password-meter-wrap { 668 margin-top: 6px; 669 display: flex; 670 flex-direction: column; 671 gap: 4px; 672 } 673 674 .acrb-password-meter-bar { 675 width: 100%; 676 height: 4px; 677 background: #e2e8f0; 678 border-radius: 999px; 679 overflow: hidden; 680 position: relative; 681 } 682 683 .acrb-password-meter-fill { 684 height: 100%; 685 width: 0%; 686 transition: width 0.25s ease, background-color 0.25s ease; 687 } 688 689 .acrb-password-meter-label { 690 font-size: 0.72rem; 691 font-weight: 600; 692 color: #64748b; 693 } 694 695 .acrb-field-feedback { 696 display: flex; 697 align-items: center; 698 gap: 4px; 699 font-size: 0.75rem; 700 margin-top: 5px; 701 font-weight: 500; 702 } 703 704 .acrb-field-feedback.is-match { 705 color: #059669; 706 } 707 708 .acrb-field-feedback.is-mismatch { 709 color: #dc2626; 710 } 711 712 .acrb-field-feedback svg { 713 width: 13px; 714 height: 13px; 715 flex-shrink: 0; 716 } 717 718 .acrb-input.match-valid { 719 border-color: #059669 !important; 720 background-color: #f0fdf4 !important; 721 } 722 723 .acrb-input.match-invalid { 724 border-color: #dc2626 !important; 725 background-color: #fef2f2 !important; 706 726 } 707 727 … … 710 730 -------------------------------------------------------------------------- */ 711 731 .acrb-modal { 732 position: fixed !important; 733 top: 0 !important; 734 left: 0 !important; 735 right: 0 !important; 736 bottom: 0 !important; 737 width: 100% !important; 738 height: 100% !important; 739 background-color: rgba(15, 23, 42, 0.65) !important; 740 backdrop-filter: blur(4px); 741 z-index: 999999 !important; 742 overflow-x: hidden !important; 743 overflow-y: auto !important; 744 -webkit-overflow-scrolling: touch; 745 padding: 24px 14px !important; 746 box-sizing: border-box !important; 712 747 display: none; 713 position: fixed;714 z-index: 99999;715 left: 0;716 top: 0;717 width: 100%;718 height: 100%;719 background: rgba(15, 23, 42, 0.6);720 backdrop-filter: blur(4px);721 748 } 722 749 723 750 .acrb-modal-content { 724 background: #ffffff; 725 margin: 4% auto; 726 padding: 32px; 727 border-radius: 16px; 728 width: 480px; 729 max-width: 90%; 730 position: relative; 731 box-shadow: 0 25px 35px -10px rgba(0, 0, 0, 0.15); 751 position: relative !important; 752 background: #ffffff !important; 753 border-radius: 14px !important; 754 max-width: 640px !important; 755 width: 100% !important; 756 margin: 20px auto !important; 757 padding: 24px 26px !important; 758 box-sizing: border-box !important; 759 box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.25) !important; 732 760 border: 1px solid #e2e8f0; 733 font-family: var(--acrb-portal-font);734 761 } 735 762 736 763 .acrb-modal-close { 737 position: absolute; 738 right: 20px; 739 top: 18px; 740 font-size: 22px; 764 position: absolute !important; 765 top: 16px !important; 766 right: 18px !important; 741 767 cursor: pointer; 768 font-size: 1.5rem; 769 line-height: 1; 742 770 color: #94a3b8; 743 771 transition: color 0.15s ease; 744 line-height: 1;772 z-index: 5; 745 773 } 746 774 … … 750 778 751 779 .acrb-receipt-header { 752 text-align: center; 753 margin-bottom: 22px; 780 display: flex; 781 align-items: center; 782 gap: 12px; 783 margin-bottom: 12px; 784 } 785 786 .acrb-receipt-icon-wrap { 787 width: 38px; 788 height: 38px; 789 border-radius: 8px; 790 background: #eef2ff; 791 color: var(--acrb-portal-primary, #4f46e5); 792 display: flex; 793 align-items: center; 794 justify-content: center; 795 flex-shrink: 0; 796 } 797 798 .acrb-receipt-icon-wrap svg { 799 width: 20px; 800 height: 20px; 801 } 802 803 .acrb-receipt-title-wrap h3 { 804 margin: 0; 805 font-size: 1.15rem; 806 font-weight: 800; 807 color: var(--acrb-portal-text, #0f172a); 808 } 809 810 .acrb-m-id { 811 font-size: 0.8rem; 812 color: var(--acrb-portal-secondary, #64748b); 813 font-weight: 700; 814 } 815 816 .acrb-receipt-meta-box { 817 background: #f8fafc; 818 border: 1px solid #e2e8f0; 819 border-radius: 10px; 820 padding: 12px 16px; 821 margin: 14px 0 16px 0; 822 display: flex; 823 flex-direction: column; 824 gap: 8px; 825 } 826 827 .acrb-receipt-meta-box .acrb-r-item { 828 display: flex; 829 justify-content: space-between; 830 align-items: center; 831 font-size: 0.875rem; 832 } 833 834 .acrb-label { 835 color: #64748b; 836 font-weight: 500; 837 } 838 839 .acrb-val { 840 color: #0f172a; 841 font-weight: 600; 842 display: flex; 843 align-items: center; 844 gap: 6px; 845 } 846 847 .acrb-payment-badge { 848 display: inline-block; 849 padding: 2px 8px; 850 border-radius: 4px; 851 background: #e2e8f0; 852 color: #334155; 853 font-size: 0.75rem; 854 font-weight: 600; 855 } 856 857 /* Schedule Card */ 858 .acrb-schedule-card { 859 background: #ffffff; 860 border: 1px solid #e2e8f0; 861 border-radius: 10px; 862 padding: 14px 16px; 863 margin-bottom: 16px; 864 box-shadow: 0 1px 3px rgba(15, 23, 42, 0.03); 865 } 866 867 .acrb-schedule-header { 868 display: flex; 869 justify-content: space-between; 870 align-items: center; 871 padding-bottom: 10px; 872 margin-bottom: 12px; 754 873 border-bottom: 1px solid #f1f5f9; 755 padding-bottom: 18px; 756 } 757 758 .acrb-receipt-icon-wrap { 759 width: 52px; 760 height: 52px; 761 background: #f1f5f9; 762 color: var(--acrb-portal-primary); 763 border-radius: 50%; 874 } 875 876 .acrb-schedule-title { 877 font-size: 0.75rem; 878 font-weight: 700; 879 text-transform: uppercase; 880 letter-spacing: 0.06em; 881 color: #64748b; 882 } 883 884 .acrb-duration-pill { 885 display: inline-flex; 886 align-items: center; 887 gap: 4px; 888 background: #eff6ff; 889 color: #1d4ed8; 890 font-size: 0.75rem; 891 font-weight: 700; 892 padding: 3px 9px; 893 border-radius: 9999px; 894 border: 1px solid #dbeafe; 895 } 896 897 .acrb-window-grid { 898 display: grid; 899 grid-template-columns: 1fr auto 1fr; 900 align-items: center; 901 gap: 12px; 902 } 903 904 .acrb-window-point { 905 display: flex; 906 flex-direction: column; 907 gap: 4px; 908 } 909 910 .acrb-point-badge { 911 display: inline-block; 912 font-size: 0.65rem; 913 font-weight: 700; 914 text-transform: uppercase; 915 letter-spacing: 0.06em; 916 padding: 2px 6px; 917 border-radius: 4px; 918 width: fit-content; 919 } 920 921 .acrb-point-badge.pickup { 922 background: #dcfce7; 923 color: #15803d; 924 } 925 926 .acrb-point-badge.return { 927 background: #fee2e2; 928 color: #b91c1c; 929 } 930 931 .acrb-point-date { 932 font-size: 0.9rem; 933 font-weight: 700; 934 color: #0f172a; 935 } 936 937 .acrb-point-loc { 938 font-size: 0.78rem; 939 color: #64748b; 940 display: flex; 941 align-items: center; 942 gap: 4px; 943 } 944 945 .acrb-window-arrow { 764 946 display: flex; 765 947 align-items: center; 766 948 justify-content: center; 767 margin: 0 auto 10px; 768 } 769 770 .acrb-receipt-icon-wrap svg { 771 width: 24px; 772 height: 24px; 773 } 774 775 .acrb-receipt-header h3 { 776 margin: 0 0 4px; 777 font-size: 18px; 778 font-weight: 800; 779 color: var(--acrb-portal-text); 780 } 781 782 .acrb-m-id { 783 color: var(--acrb-portal-secondary); 784 font-size: 12px; 785 font-weight: 700; 786 } 787 788 .acrb-receipt-list { 949 color: #94a3b8; 950 } 951 952 .acrb-window-arrow svg { 953 width: 22px; 954 height: 22px; 955 } 956 957 /* Itemized Fee Breakdown */ 958 .acrb-breakdown-container { 959 background: #ffffff; 960 border: 1px solid #e2e8f0; 961 border-radius: 10px; 962 padding: 14px 16px; 963 margin-bottom: 16px; 964 } 965 966 .acrb-section-subheading { 967 font-size: 0.75rem; 968 text-transform: uppercase; 969 letter-spacing: 0.06em; 970 color: #94a3b8; 971 margin: 0 0 10px 0; 972 font-weight: 700; 973 } 974 975 .acrb-fee-list { 789 976 display: flex; 790 977 flex-direction: column; 791 978 gap: 10px; 792 margin-bottom: 20px; 793 } 794 795 .acrb-r-item { 979 } 980 981 .acrb-fee-row { 796 982 display: flex; 797 983 justify-content: space-between; 798 font-size: 13.5px; 799 color: var(--acrb-portal-secondary); 800 font-weight: 500; 801 } 802 803 .acrb-m-car { 804 color: var(--acrb-portal-text); 805 } 806 807 .acrb-m-date, 808 .acrb-m-method { 809 color: var(--acrb-portal-secondary); 810 } 811 812 .acrb-m-method { 813 font-weight: 700; 814 } 815 816 .acrb-m-ins, 817 .acrb-m-border { 818 color: var(--acrb-portal-primary); 819 font-weight: 700; 820 } 821 822 .acrb-m-promo, 823 .acrb-m-total { 824 color: var(--acrb-portal-accent); 825 } 826 827 .acrb-m-promo { 828 font-weight: 700; 829 } 830 831 .acrb-row-collapsed { 832 display: none; 833 } 834 835 .acrb-r-total { 836 display: flex; 984 align-items: flex-start; 985 padding-bottom: 10px; 986 border-bottom: 1px dashed #e2e8f0; 987 font-size: 0.875rem; 988 } 989 990 .acrb-fee-row:last-child { 991 border-bottom: none; 992 padding-bottom: 0; 993 } 994 995 .acrb-fee-info { 996 display: flex; 997 flex-direction: column; 998 gap: 2px; 999 } 1000 1001 .acrb-fee-title { 1002 font-weight: 600; 1003 color: #0f172a; 1004 } 1005 1006 .acrb-fee-sub { 1007 font-size: 0.75rem; 1008 color: #64748b; 1009 } 1010 1011 .acrb-fee-amount { 1012 font-weight: 700; 1013 color: #0f172a; 1014 white-space: nowrap; 1015 } 1016 1017 .acrb-fee-discount, 1018 .acrb-fee-discount .acrb-fee-title { 1019 color: #059669 !important; 1020 } 1021 1022 .acrb-badge-tag { 1023 display: inline-block; 1024 background: #dcfce7; 1025 color: #15803d; 1026 font-size: 0.7rem; 1027 padding: 1px 6px; 1028 border-radius: 4px; 1029 font-weight: 600; 1030 margin-left: 6px; 1031 } 1032 1033 /* Settled Amount Box */ 1034 .acrb-settled-box { 1035 display: flex !important; 837 1036 justify-content: space-between; 838 border-top: 2px dashed #e2e8f0; 839 padding-top: 16px; 1037 align-items: center; 1038 padding: 16px 18px; 1039 background: #f8fafc; 1040 border: 1px solid #cbd5e1; 1041 border-radius: 10px; 1042 margin-bottom: 18px; 1043 } 1044 1045 .acrb-settled-info strong { 1046 display: block; 1047 font-size: 0.95rem; 1048 color: #0f172a; 1049 font-weight: 700; 1050 } 1051 1052 .acrb-settled-info small { 1053 display: block; 1054 font-size: 0.75rem; 1055 color: #64748b; 1056 margin-top: 2px; 1057 } 1058 1059 .acrb-settled-val { 1060 font-size: 1.45rem; 840 1061 font-weight: 800; 841 font-size: 17px;842 color: var(--acrb-portal-text);843 } 844 845 .acrb-btn-print {1062 color: var(--acrb-portal-primary, #4f46e5); 1063 letter-spacing: -0.02em; 1064 } 1065 1066 button.acrb-btn-print { 846 1067 width: 100%; 847 margin-top: 20px; 848 height: 42px; 849 background: var(--acrb-portal-text); 1068 height: 44px; 1069 background: var(--acrb-btn-bg, #4f46e5); 850 1070 color: #ffffff; 851 border-radius: 8px;852 1071 border: none; 853 font-weight: 700; 854 font-size: 13px; 1072 border-radius: 10px; 1073 font-weight: 700; 1074 font-size: 0.9rem; 855 1075 cursor: pointer; 856 transition: opacity 0.15s ease;857 1076 display: inline-flex; 858 1077 align-items: center; 859 1078 justify-content: center; 860 1079 gap: 8px; 1080 transition: background-color 0.2s ease; 861 1081 font-family: inherit; 862 1082 } 863 1083 864 .acrb-btn-print:hover {865 opacity: 0.88;1084 button.acrb-btn-print:hover { 1085 background: var(--acrb-btn-hover, #4338ca); 866 1086 } 867 1087 868 1088 /* -------------------------------------------------------------------------- 869 Responsive & Print Styles1089 Responsive & Print Rules 870 1090 -------------------------------------------------------------------------- */ 871 @media (max-width: 860px) {1091 @media (max-width: 900px) { 872 1092 .acrb-acc-wrapper { 873 1093 flex-direction: column; … … 875 1095 .acrb-acc-nav { 876 1096 width: 100%; 877 }878 .acrb-form-row {879 grid-template-columns: 1fr;880 1097 } 881 1098 .acrb-stats-grid { … … 888 1105 } 889 1106 1107 @media (max-width: 640px) { 1108 .acrb-form-row { 1109 flex-direction: column; 1110 gap: 12px; 1111 } 1112 .acrb-window-grid { 1113 grid-template-columns: 1fr; 1114 gap: 8px; 1115 } 1116 .acrb-window-arrow { 1117 transform: rotate(90deg); 1118 margin: 4px 0; 1119 } 1120 } 1121 890 1122 @media print { 891 1123 body * { … … 897 1129 } 898 1130 #acrb-receipt-modal { 899 position: absolute; 900 left: 0; 901 top: 0; 902 width: 100%; 903 height: 100%; 904 background: #ffffff; 905 backdrop-filter: none; 1131 position: absolute !important; 1132 left: 0 !important; 1133 top: 0 !important; 1134 width: 100% !important; 1135 height: auto !important; 1136 background: #ffffff !important; 1137 backdrop-filter: none !important; 1138 padding: 0 !important; 906 1139 } 907 1140 .acrb-modal-content { 908 box-shadow: none; 909 border: 1px solid #ccc; 910 margin: 0 auto; 911 width: 100%; 1141 box-shadow: none !important; 1142 border: 1px solid #cbd5e1 !important; 1143 margin: 0 auto !important; 1144 max-width: 100% !important; 1145 width: 100% !important; 1146 padding: 20px !important; 912 1147 } 913 1148 .acrb-modal-close, -
awesome-car-rental/trunk/assets/css/frontend/cars.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB FLEET ARCHIVE (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/all-cars.css 3 4 ========================================================================== */ 4 5 … … 14 15 --acrb-grid-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 15 16 16 font-family: var(--acrb-grid-font );17 color: var(--acrb-grid-text );18 } 19 20 .acrb-grid-wrapper, 17 font-family: var(--acrb-grid-font, sans-serif); 18 color: var(--acrb-grid-text, #0f172a); 19 box-sizing: border-box; 20 } 21 21 22 .acrb-grid-wrapper *, 22 23 .acrb-grid-wrapper *::before, 23 24 .acrb-grid-wrapper *::after, 24 .acrb-empty,25 25 .acrb-empty *, 26 26 .acrb-empty *::before, 27 27 .acrb-empty *::after { 28 box-sizing: border-box;28 box-sizing: inherit; 29 29 } 30 30 … … 34 34 padding: 60px 20px; 35 35 font-size: 14.5px; 36 color: var(--acrb-grid-secondary );36 color: var(--acrb-grid-secondary, #64748b); 37 37 } 38 38 … … 40 40 .acrb-grid-wrapper { 41 41 padding: 30px 0; 42 max-width: 1 200px;42 max-width: 1400px; 43 43 margin: 0 auto; 44 width: 100%; 45 background: transparent; 44 46 } 45 47 46 48 .acrb-layout-container { 47 49 display: flex; 48 gap: 30px;49 50 align-items: flex-start; 51 gap: 32px; 52 position: relative; 50 53 } 51 54 … … 65 68 66 69 /* -------------------------------------------------------------------------- 70 Mobile Collapsible Header Bar 71 -------------------------------------------------------------------------- */ 72 .acrb-mobile-filter-bar { 73 display: none; 74 width: 100%; 75 margin-bottom: 20px; 76 } 77 78 .acrb-mobile-toggle-btn { 79 width: 100%; 80 display: flex; 81 align-items: center; 82 justify-content: space-between; 83 padding: 14px 20px; 84 background: #ffffff; 85 border: 1px solid #e2e8f0; 86 border-radius: 14px; 87 font-size: 0.95rem; 88 font-weight: 700; 89 color: #0f172a; 90 cursor: pointer; 91 box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04); 92 transition: all 0.2s ease; 93 font-family: inherit; 94 } 95 96 .acrb-mobile-toggle-btn:hover { 97 border-color: var(--acrb-grid-primary, #4f46e5); 98 } 99 100 /* -------------------------------------------------------------------------- 67 101 Filter Sidebar 68 102 -------------------------------------------------------------------------- */ 69 103 .acrb-filter-sidebar { 70 width: 280px;104 width: 320px; 71 105 flex-shrink: 0; 72 106 background: #ffffff; 73 107 border: 1px solid #e2e8f0; 74 border-radius: 16px; 75 padding: 24px; 76 box-shadow: 0 4px 20px -4px rgba(15, 23, 42, 0.03); 108 border-radius: 20px; 109 padding: 26px; 110 box-shadow: 0 10px 35px -10px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.03); 111 position: sticky; 112 top: 24px; 113 box-sizing: border-box; 114 transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1); 115 } 116 117 .acrb-sidebar-header { 118 display: flex; 119 align-items: center; 120 justify-content: space-between; 121 padding-bottom: 18px; 122 margin-bottom: 22px; 123 border-bottom: 1px solid #f1f5f9; 124 } 125 126 .acrb-sidebar-title-group { 127 display: flex; 128 align-items: center; 129 gap: 10px; 130 } 131 132 .acrb-sidebar-title-group svg { 133 color: var(--acrb-grid-primary, #4f46e5); 134 flex-shrink: 0; 135 } 136 137 .acrb-sidebar-title-group h4 { 138 margin: 0; 139 font-size: 1.1rem; 140 font-weight: 800; 141 color: #0f172a; 142 letter-spacing: -0.01em; 143 } 144 145 button.acrb-btn-clear { 146 background: none; 147 border: none; 148 font-size: 0.8rem; 149 font-weight: 700; 150 color: #64748b; 151 cursor: pointer; 152 padding: 5px 10px; 153 border-radius: 8px; 154 transition: all 0.2s ease; 155 font-family: inherit; 156 } 157 158 button.acrb-btn-clear:hover { 159 color: var(--acrb-grid-primary, #4f46e5); 160 background: #f1f5f9; 77 161 } 78 162 79 163 .acrb-filter-section { 80 margin-bottom: 22px; 81 padding-bottom: 20px; 82 border-bottom: 1px solid #f1f5f9; 164 margin-bottom: 24px; 83 165 } 84 166 85 167 .acrb-filter-section:last-child { 86 168 margin-bottom: 0; 87 padding-bottom: 0; 88 border-bottom: none; 89 } 90 91 .acrb-filter-section h4 { 92 font-size: 11.5px;169 } 170 171 .acrb-filter-label, 172 .acrb-filter-subheading { 173 display: block; 174 font-size: 0.78rem; 93 175 text-transform: uppercase; 94 letter-spacing: 0.05em;95 color: var(--acrb-grid-secondary);96 margin: 0 0 12px 0;97 176 font-weight: 800; 177 letter-spacing: 0.06em; 178 color: #475569; 179 margin-bottom: 12px; 98 180 } 99 181 100 182 .acrb-search-box { 101 183 position: relative; 184 display: flex; 185 align-items: center; 186 } 187 188 .acrb-search-box svg { 189 position: absolute; 190 left: 14px; 191 color: #94a3b8; 192 pointer-events: none; 193 transition: color 0.2s ease; 194 flex-shrink: 0; 102 195 } 103 196 104 197 .acrb-search-box input { 105 198 width: 100% !important; 106 height: 4 0px !important;107 padding: 0 14px 0 38px !important;108 border: 1px solid # cbd5e1!important;109 border-radius: 8px !important;110 font-size: 13px!important;199 height: 44px !important; 200 padding: 8px 14px 8px 42px !important; 201 border: 1px solid #e2e8f0 !important; 202 border-radius: 12px !important; 203 font-size: 0.9rem !important; 111 204 background: #f8fafc !important; 112 color: var(--acrb-grid-text ) !important;205 color: var(--acrb-grid-text, #0f172a) !important; 113 206 outline: none !important; 114 207 box-shadow: none !important; 115 transition: border-color 0.15s ease, background-color 0.15s ease; 208 transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease; 209 font-family: inherit !important; 116 210 } 117 211 118 212 .acrb-search-box input:focus { 119 213 background: #ffffff !important; 120 border-color: var(--acrb-grid-primary) !important; 121 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important; 122 } 123 124 .acrb-search-box .acrb-grid-icon { 125 position: absolute; 126 left: 12px; 127 top: 50%; 128 transform: translateY(-50%); 214 border-color: var(--acrb-grid-primary, #4f46e5) !important; 215 box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.1) !important; 216 } 217 218 /* Budget Slider */ 219 .acrb-price-header { 220 display: flex; 221 justify-content: space-between; 222 align-items: center; 223 margin-bottom: 12px; 224 } 225 226 .acrb-price-badge { 227 background: #eef2ff; 228 color: var(--acrb-grid-primary, #4f46e5); 229 font-size: 0.88rem; 230 font-weight: 800; 231 padding: 3px 12px; 232 border-radius: 10px; 233 border: 1px solid #e0e7ff; 234 } 235 236 .acrb-range-slider { 237 -webkit-appearance: none; 238 width: 100%; 239 height: 6px; 240 border-radius: 999px; 241 background: #e2e8f0; 242 outline: none; 243 margin: 10px 0 6px 0; 244 cursor: pointer; 245 } 246 247 .acrb-range-slider::-webkit-slider-thumb { 248 -webkit-appearance: none; 249 width: 22px; 250 height: 22px; 251 border-radius: 50%; 252 background: var(--acrb-grid-primary, #4f46e5); 253 border: 3px solid #ffffff; 254 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.28); 255 cursor: pointer; 256 transition: transform 0.15s ease; 257 } 258 259 .acrb-range-slider::-webkit-slider-thumb:hover { 260 transform: scale(1.15); 261 } 262 263 .acrb-slider-bounds { 264 display: flex; 265 justify-content: space-between; 266 font-size: 0.74rem; 129 267 color: #94a3b8; 130 } 131 268 font-weight: 600; 269 } 270 271 /* Category Item List */ 132 272 .acrb-filter-list { 133 273 list-style: none; 274 margin: 0; 134 275 padding: 0; 135 margin: 0;136 276 display: flex; 137 277 flex-direction: column; 278 gap: 6px; 279 } 280 281 .acrb-filter-item label { 282 display: flex; 283 align-items: center; 284 justify-content: space-between; 285 width: 100%; 286 padding: 8px 12px; 287 border-radius: 10px; 288 cursor: pointer; 289 transition: all 0.2s ease; 290 box-sizing: border-box; 291 } 292 293 .acrb-filter-item label:hover { 294 background: #f8fafc; 295 } 296 297 .acrb-item-left { 298 display: flex; 299 align-items: center; 300 gap: 10px; 301 font-size: 0.9rem; 302 font-weight: 600; 303 color: #334155; 304 } 305 306 .acrb-custom-check { 307 width: 18px; 308 height: 18px; 309 border: 2px solid #cbd5e1; 310 border-radius: 6px; 311 display: flex; 312 align-items: center; 313 justify-content: center; 314 transition: all 0.15s ease; 315 flex-shrink: 0; 316 } 317 318 .acrb-custom-check svg { 319 display: none; 320 color: #ffffff; 321 } 322 323 .acrb-cat-filter { 324 display: none; 325 } 326 327 .acrb-cat-filter:checked + .acrb-custom-check { 328 background: var(--acrb-grid-primary, #4f46e5); 329 border-color: var(--acrb-grid-primary, #4f46e5); 330 } 331 332 .acrb-cat-filter:checked + .acrb-custom-check svg { 333 display: block; 334 } 335 336 .acrb-cat-filter:checked ~ span { 337 font-weight: 700; 338 color: #0f172a; 339 } 340 341 .acrb-count-badge { 342 font-size: 0.74rem; 343 font-weight: 700; 344 color: #64748b; 345 background: #f1f5f9; 346 padding: 3px 8px; 347 border-radius: 8px; 348 } 349 350 /* Segmented Button Chips for Specs */ 351 .acrb-chip-grid { 352 display: grid; 353 grid-template-columns: repeat(2, 1fr); 138 354 gap: 8px; 139 355 } 140 356 141 .acrb-filter-item { 142 display: flex; 143 justify-content: space-between; 144 align-items: center; 145 } 146 147 .acrb-filter-item label { 148 display: flex; 149 align-items: center; 150 gap: 10px; 151 font-size: 13.5px; 152 color: #334155; 357 .acrb-chip-btn { 358 display: flex; 359 align-items: center; 360 justify-content: center; 361 gap: 6px; 362 padding: 10px 12px; 363 background: #f8fafc; 364 border: 1px solid #e2e8f0; 365 border-radius: 12px; 366 font-size: 0.82rem; 153 367 font-weight: 600; 154 cursor: pointer; 155 } 156 157 .acrb-filter-item input[type="checkbox"] { 158 width: 16px; 159 height: 16px; 160 accent-color: var(--acrb-grid-primary); 161 cursor: pointer; 162 border-radius: 4px; 163 } 164 165 .acrb-count-badge { 368 color: #475569; 369 cursor: pointer; 370 transition: all 0.2s ease; 371 user-select: none; 372 } 373 374 .acrb-chip-btn input { 375 display: none; 376 } 377 378 .acrb-chip-btn svg { 379 color: #94a3b8; 380 transition: color 0.2s ease; 381 flex-shrink: 0; 382 } 383 384 .acrb-chip-btn:hover { 385 border-color: #cbd5e1; 166 386 background: #f1f5f9; 167 color: var(--acrb-grid-secondary); 168 font-size: 11px; 169 font-weight: 700; 170 padding: 2px 8px; 171 border-radius: 99px; 387 } 388 389 .acrb-chip-btn:has(input:checked) { 390 background: #eef2ff; 391 border-color: var(--acrb-grid-primary, #4f46e5); 392 color: var(--acrb-grid-primary, #4f46e5); 393 font-weight: 700; 394 box-shadow: 0 2px 8px rgba(79, 70, 229, 0.12); 395 } 396 397 .acrb-chip-btn:has(input:checked) svg { 398 color: var(--acrb-grid-primary, #4f46e5); 172 399 } 173 400 174 401 /* -------------------------------------------------------------------------- 175 Content Header & ViewToolbar402 Right Content Container & Top Toolbar 176 403 -------------------------------------------------------------------------- */ 177 404 .acrb-right-content { 178 405 flex: 1; 406 width: 100%; 179 407 min-width: 0; 180 408 } … … 182 410 .acrb-content-header { 183 411 display: flex; 412 align-items: center; 184 413 justify-content: space-between; 185 align-items: center;186 414 background: #ffffff; 187 415 border: 1px solid #e2e8f0; 188 border-radius: 1 4px;189 padding: 1 6px 20px;416 border-radius: 18px; 417 padding: 14px 22px; 190 418 margin-bottom: 24px; 191 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03); 419 box-shadow: 0 4px 15px rgba(15, 23, 42, 0.03); 420 gap: 16px; 421 flex-wrap: wrap; 192 422 } 193 423 194 424 .acrb-result-count { 195 font-size: 13.5px; 196 color: var(--acrb-grid-secondary); 425 font-size: 0.95rem; 426 font-weight: 700; 427 color: #1e293b; 428 } 429 430 .acrb-toolbar-actions { 431 display: flex; 432 align-items: center; 433 gap: 12px; 434 flex-wrap: wrap; 435 } 436 437 /* Per-Page & Sort Dropdowns */ 438 .acrb-select-group { 439 display: flex; 440 align-items: center; 441 gap: 6px; 442 } 443 444 .acrb-select-label { 445 font-size: 0.78rem; 446 font-weight: 700; 447 color: #64748b; 448 text-transform: uppercase; 449 } 450 451 .acrb-select-field { 452 height: 38px; 453 padding: 0 32px 0 12px; 454 background: #f8fafc url('data:image/svg+xml;utf8,<svg fill="none" stroke="%2364748b" stroke-width="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"></path></svg>') no-repeat right 10px center; 455 background-size: 14px; 456 border: 1px solid #e2e8f0; 457 border-radius: 10px; 458 font-size: 0.85rem; 197 459 font-weight: 600; 198 } 199 460 color: #0f172a; 461 cursor: pointer; 462 appearance: none; 463 outline: none; 464 transition: all 0.2s ease; 465 font-family: inherit; 466 } 467 468 .acrb-select-field:focus { 469 border-color: var(--acrb-grid-primary, #4f46e5); 470 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); 471 } 472 473 /* View Mode Buttons */ 200 474 .acrb-view-toolbar { 201 475 display: flex; 202 align-items: center; 203 gap: 8px; 476 background: #f1f5f9; 477 padding: 3px; 478 border-radius: 10px; 479 gap: 2px; 204 480 } 205 481 206 482 button.acrb-view-btn { 207 background: #f8fafc; 208 border: 1px solid #cbd5e1; 483 background: transparent; 484 border: none; 485 padding: 6px 10px; 486 border-radius: 8px; 487 cursor: pointer; 209 488 color: #64748b; 210 width: 36px;211 height: 36px;212 border-radius: 8px;213 489 display: flex; 214 490 align-items: center; 215 491 justify-content: center; 216 cursor: pointer; 217 transition: all 0.15s ease; 218 } 219 220 button.acrb-view-btn:hover, 492 transition: all 0.2s ease; 493 } 494 495 button.acrb-view-btn:hover { 496 color: #0f172a; 497 } 498 221 499 button.acrb-view-btn.active { 222 background: var(--acrb-grid-primary);223 border-color: var(--acrb-grid-primary);224 color: #ffffff;500 background: #ffffff; 501 color: var(--acrb-grid-primary, #4f46e5); 502 box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08); 225 503 } 226 504 … … 230 508 .acrb-car-grid { 231 509 display: grid; 232 grid-template-columns: repeat(auto-fill, minmax( 300px, 1fr));510 grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); 233 511 gap: 24px; 512 margin-bottom: 36px; 234 513 } 235 514 236 515 .acrb-car-card { 237 516 background: #ffffff; 238 border-radius: 16px; 517 border: 1px solid #e2e8f0; 518 border-radius: 20px; 239 519 overflow: hidden; 240 box-shadow: 0 4px 20px -4px rgba(15, 23, 42, 0.05);241 transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.25s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease;242 520 display: flex; 243 521 flex-direction: column; 244 border: 1px solid #e2e8f0;522 transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease; 245 523 position: relative; 246 524 } … … 248 526 .acrb-car-card:hover { 249 527 transform: translateY(-4px); 250 box-shadow: 0 16px 30px -8px rgba(15, 23, 42, 0.1);251 528 border-color: #cbd5e1; 529 box-shadow: 0 18px 38px -12px rgba(15, 23, 42, 0.12); 252 530 } 253 531 254 532 .acrb-img-container { 255 533 position: relative; 256 aspect-ratio: 16 / 10; 534 width: 100%; 535 height: 200px; 536 background: #f8fafc; 257 537 overflow: hidden; 258 background: #f8fafc;259 538 } 260 539 … … 269 548 height: 100%; 270 549 object-fit: cover; 550 transition: transform 0.4s ease; 271 551 display: block; 272 transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);273 552 } 274 553 275 554 .acrb-car-card:hover .acrb-img-container img { 276 transform: scale(1.06); 555 transform: scale(1.05); 556 } 557 558 .acrb-no-thumb { 559 width: 100%; 560 height: 100%; 561 display: flex; 562 align-items: center; 563 justify-content: center; 564 color: #94a3b8; 565 background: #f1f5f9; 277 566 } 278 567 … … 285 574 -webkit-backdrop-filter: blur(8px); 286 575 color: #ffffff; 287 padding: 4px 12px; 288 border-radius: 9999px; 289 font-size: 11px; 290 font-weight: 700; 576 font-size: 0.72rem; 577 font-weight: 700; 578 padding: 4px 10px; 579 border-radius: 999px; 580 letter-spacing: 0.03em; 291 581 text-transform: uppercase; 292 letter-spacing: 0.04em;293 582 z-index: 2; 294 border: 1px solid rgba(255, 255, 255, 0.18);295 583 } 296 584 297 585 .acrb-card-body { 298 padding: 22px; 586 padding: 20px; 587 display: flex; 588 flex-direction: column; 299 589 flex-grow: 1; 300 display: flex; 301 flex-direction: column; 302 } 303 304 .acrb-card-main-info { 305 display: flex; 306 flex-direction: column; 307 width: 100%; 590 justify-content: space-between; 591 gap: 16px; 308 592 } 309 593 310 594 .acrb-card-title { 311 font-size: 17px; 595 margin: 0 0 14px 0; 596 font-size: 1.12rem; 312 597 font-weight: 800; 313 margin: 0 0 14px 0; 314 line-height: 1.3; 315 letter-spacing: -0.01em; 598 line-height: 1.35; 316 599 } 317 600 318 601 .acrb-card-title a { 319 text-decoration: none !important;320 color: var(--acrb-grid-text);602 color: #0f172a; 603 text-decoration: none; 321 604 transition: color 0.15s ease; 322 605 } 323 606 324 607 .acrb-card-title a:hover { 325 color: var(--acrb-grid-primary );608 color: var(--acrb-grid-primary, #4f46e5); 326 609 } 327 610 … … 329 612 display: grid; 330 613 grid-template-columns: repeat(2, 1fr); 331 gap: 8px; 332 margin-bottom: 20px; 614 gap: 10px; 615 background: #f8fafc; 616 border: 1px solid #f1f5f9; 617 padding: 12px; 618 border-radius: 14px; 619 } 620 621 .acrb-spec-item { 622 display: flex; 623 align-items: center; 624 gap: 7px; 625 font-size: 0.78rem; 626 font-weight: 600; 627 color: #475569; 628 } 629 630 .acrb-spec-item svg { 631 color: var(--acrb-grid-primary, #4f46e5); 632 flex-shrink: 0; 633 } 634 635 .acrb-card-footer { 636 display: flex; 637 align-items: center; 638 justify-content: space-between; 333 639 padding-top: 14px; 334 640 border-top: 1px solid #f1f5f9; 335 641 } 336 642 337 .acrb-spec-item { 338 display: flex; 339 align-items: center; 340 gap: 7px; 341 color: var(--acrb-grid-secondary); 342 font-size: 12.5px; 643 .acrb-price-block { 644 display: flex; 645 align-items: baseline; 646 gap: 4px; 647 } 648 649 .acrb-price-val { 650 font-size: 1.35rem; 651 font-weight: 800; 652 color: #0f172a; 653 letter-spacing: -0.02em; 654 } 655 656 .acrb-price-unit { 657 font-size: 0.78rem; 658 color: #64748b; 343 659 font-weight: 600; 660 } 661 662 .acrb-btn-book { 663 display: inline-flex; 664 align-items: center; 665 gap: 6px; 666 padding: 10px 18px; 667 background: var(--acrb-grid-btn-bg, #4f46e5); 668 color: #ffffff; 669 font-size: 0.85rem; 670 font-weight: 700; 671 border-radius: 12px; 672 text-decoration: none; 673 transition: all 0.2s ease; 674 box-shadow: 0 4px 12px rgba(79, 70, 229, 0.22); 675 } 676 677 .acrb-btn-book:hover { 678 background: var(--acrb-grid-btn-hover, #4338ca); 679 transform: translateY(-1px); 680 box-shadow: 0 6px 16px rgba(79, 70, 229, 0.32); 681 color: #ffffff; 682 } 683 684 /* List View Mode Styling */ 685 .acrb-car-grid.list-view { 686 grid-template-columns: 1fr; 687 } 688 689 .acrb-car-grid.list-view .acrb-car-card { 690 flex-direction: row; 691 } 692 693 .acrb-car-grid.list-view .acrb-img-container { 694 width: 320px; 695 height: auto; 696 flex-shrink: 0; 697 } 698 699 .acrb-car-grid.list-view .acrb-card-body { 700 padding: 24px; 701 } 702 703 /* -------------------------------------------------------------------------- 704 Numbered Pagination Controls 705 -------------------------------------------------------------------------- */ 706 .acrb-pagination-container { 707 display: flex; 708 align-items: center; 709 justify-content: center; 710 gap: 8px; 711 margin-top: 16px; 712 user-select: none; 713 } 714 715 .acrb-page-btn { 716 min-width: 42px; 717 height: 42px; 718 padding: 0 8px; 719 border-radius: 12px; 720 border: 1px solid #e2e8f0; 721 background: #ffffff; 722 color: #334155; 723 font-size: 0.9rem; 724 font-weight: 700; 725 display: inline-flex; 726 align-items: center; 727 justify-content: center; 728 cursor: pointer; 729 transition: all 0.2s ease; 730 box-shadow: 0 2px 4px rgba(15, 23, 42, 0.04); 731 font-family: inherit; 732 } 733 734 .acrb-page-btn:hover:not(:disabled) { 735 border-color: var(--acrb-grid-primary, #4f46e5); 736 color: var(--acrb-grid-primary, #4f46e5); 344 737 background: #f8fafc; 345 padding: 8px 10px; 346 border-radius: 8px; 347 border: 1px solid #f1f5f9; 348 overflow: hidden; 349 white-space: nowrap; 350 text-overflow: ellipsis; 351 } 352 353 .acrb-spec-item .acrb-grid-icon { 354 color: var(--acrb-grid-primary); 355 } 356 357 .acrb-spec-item span { 358 overflow: hidden; 359 text-overflow: ellipsis; 360 white-space: nowrap; 361 } 362 363 .acrb-card-footer { 364 margin-top: auto; 365 display: flex; 366 justify-content: space-between; 367 align-items: center; 368 padding-top: 16px; 369 border-top: 1px solid #f1f5f9; 370 gap: 12px; 371 } 372 373 .acrb-price-block { 374 display: flex; 375 align-items: baseline; 376 gap: 3px; 377 } 378 379 .acrb-price-val { 380 font-size: 20px; 381 font-weight: 900; 382 color: var(--acrb-grid-text); 383 letter-spacing: -0.02em; 384 } 385 386 .acrb-price-unit { 387 font-size: 12px; 388 color: var(--acrb-grid-secondary); 389 font-weight: 600; 390 } 391 392 /* Call to Action Button with Customizer Hook Support */ 393 .acrb-btn-book { 394 background: var(--acrb-grid-btn-bg); 395 border: 1px solid var(--acrb-grid-btn-bg); 396 color: #ffffff !important; 397 padding: 10px 18px; 398 border-radius: 8px; 399 text-decoration: none !important; 400 font-weight: 700; 401 font-size: 12.5px; 402 transition: all 0.15s ease; 403 box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08); 738 transform: translateY(-1px); 739 } 740 741 .acrb-page-btn.active { 742 background: var(--acrb-grid-primary, #4f46e5); 743 border-color: var(--acrb-grid-primary, #4f46e5); 744 color: #ffffff; 745 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.3); 746 } 747 748 .acrb-page-btn:disabled { 749 opacity: 0.4; 750 cursor: not-allowed; 751 box-shadow: none; 752 } 753 754 .acrb-page-ellipsis { 404 755 display: inline-flex; 405 756 align-items: center; 406 gap: 6px;407 white-space: nowrap;408 }409 410 .acrb-btn-book:hover {411 background: var(--acrb-grid-btn-hover);412 border-color: var(--acrb-grid-btn-hover);413 opacity: 0.94;414 transform: translateY(-1px);415 box-shadow: 0 4px 12px rgba(15, 23, 42, 0.14);416 }417 418 .acrb-btn-book .acrb-grid-icon {419 width: 14px;420 height: 14px;421 transition: transform 0.15s ease;422 }423 424 .acrb-btn-book:hover .acrb-grid-icon {425 transform: translateX(2px);426 }427 428 /* Fallback Thumbnail */429 .acrb-no-thumb {430 width: 100%;431 height: 100%;432 display: flex;433 align-items: center;434 757 justify-content: center; 435 color: #cbd5e1; 436 background: #f8fafc; 437 } 438 439 .acrb-no-thumb svg { 440 width: 52px; 441 height: 52px; 442 } 443 444 /* Empty Search Results Message */ 758 width: 32px; 759 height: 42px; 760 font-size: 1rem; 761 font-weight: 800; 762 color: #94a3b8; 763 } 764 765 /* Empty State */ 445 766 .acrb-no-cars-msg { 446 display: none;447 grid-column: 1 / -1;448 767 text-align: center; 449 768 padding: 60px 20px; 450 color: var(--acrb-grid-secondary); 769 background: #ffffff; 770 border: 1px dashed #cbd5e1; 771 border-radius: 20px; 772 grid-column: 1 / -1; 451 773 } 452 774 453 775 .acrb-no-cars-icon { 454 width: 48px; 455 height: 48px; 456 color: #cbd5e1; 457 margin-bottom: 12px; 776 margin: 0 auto 16px auto; 777 color: #94a3b8; 778 display: block; 458 779 } 459 780 460 781 .acrb-no-cars-title { 461 margin: 0 0 6px 0; 462 font-size: 18px; 463 color: var(--acrb-grid-text); 782 margin: 0 0 8px 0; 783 font-size: 1.25rem; 784 font-weight: 800; 785 color: #0f172a; 464 786 } 465 787 466 788 .acrb-no-cars-desc { 467 margin: 0; 468 font-size: 14px; 469 } 470 471 /* -------------------------------------------------------------------------- 472 List View Switcher Layout 473 -------------------------------------------------------------------------- */ 474 .acrb-car-grid.list-view { 475 grid-template-columns: 1fr !important; 476 gap: 16px; 477 } 478 479 .acrb-car-grid.list-view .acrb-car-card { 480 flex-direction: row; 481 align-items: stretch; 482 } 483 484 .acrb-car-grid.list-view .acrb-img-container { 485 width: 320px; 486 flex-shrink: 0; 487 aspect-ratio: auto; 488 height: 100%; 489 } 490 491 .acrb-car-grid.list-view .acrb-card-body { 492 flex-direction: column; 493 justify-content: space-between; 494 padding: 24px; 495 } 496 497 .acrb-car-grid.list-view .acrb-card-main-info { 498 display: flex; 499 flex-direction: column; 500 width: 100%; 501 } 502 503 .acrb-car-grid.list-view .acrb-card-title { 504 margin: 0 0 12px 0; 505 font-size: 18px; 506 } 507 508 .acrb-car-grid.list-view .acrb-spec-grid { 509 border-top: none; 510 padding-top: 0; 511 margin-bottom: 20px; 512 display: flex; 513 gap: 10px; 514 } 515 516 .acrb-car-grid.list-view .acrb-card-footer { 517 border-top: 1px solid #f1f5f9; 518 padding-top: 16px; 519 margin-top: auto; 520 flex-direction: row; 521 justify-content: flex-end; 522 align-items: center; 523 gap: 16px; 524 width: 100%; 789 margin: 0 0 20px 0; 790 color: #64748b; 791 font-size: 0.95rem; 792 } 793 794 .acrb-btn-clear-empty { 795 padding: 10px 22px; 796 background: var(--acrb-grid-primary, #4f46e5); 797 color: #ffffff; 798 font-size: 0.88rem; 799 font-weight: 700; 800 border: none; 801 border-radius: 12px; 802 cursor: pointer; 803 transition: all 0.2s ease; 804 font-family: inherit; 525 805 } 526 806 … … 528 808 Responsive Breakpoints 529 809 -------------------------------------------------------------------------- */ 530 @media (max-width: 9 60px) {810 @media (max-width: 980px) { 531 811 .acrb-layout-container { 532 812 flex-direction: column; 533 813 } 814 .acrb-mobile-filter-bar { 815 display: block; 816 } 534 817 .acrb-filter-sidebar { 535 818 width: 100%; 819 position: static; 820 display: none; 821 margin-bottom: 24px; 822 } 823 .acrb-filter-sidebar.is-open { 824 display: block; 536 825 } 537 826 .acrb-car-grid.list-view .acrb-car-card { … … 540 829 .acrb-car-grid.list-view .acrb-img-container { 541 830 width: 100%; 542 aspect-ratio: 16 / 10;831 height: 200px; 543 832 } 544 .acrb-car-grid.list-view .acrb-card-footer { 545 flex-direction: row; 546 justify-content: space-between; 547 align-items: center; 548 } 549 } 833 } -
awesome-car-rental/trunk/assets/css/frontend/checkout.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB CHECKOUT COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/checkout.css 3 4 ========================================================================== */ 4 5 … … 15 16 --acrb-checkout-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 16 17 17 font-family: var(--acrb-checkout-font );18 color: var(--acrb-checkout-text );19 } 20 21 .acrb-checkout-wrapper, 18 font-family: var(--acrb-checkout-font, sans-serif); 19 color: var(--acrb-checkout-text, #0f172a); 20 box-sizing: border-box; 21 } 22 22 23 .acrb-checkout-wrapper *, 23 24 .acrb-checkout-wrapper *::before, 24 25 .acrb-checkout-wrapper *::after, 25 .acrb-redirect-notice,26 26 .acrb-redirect-notice *, 27 27 .acrb-redirect-notice *::before, 28 28 .acrb-redirect-notice *::after, 29 .acrb-checkout-error,30 29 .acrb-checkout-error *, 31 30 .acrb-checkout-error *::before, 32 31 .acrb-checkout-error *::after { 33 box-sizing: border-box;32 box-sizing: inherit; 34 33 } 35 34 … … 41 40 text-align: center; 42 41 font-size: 15px; 43 color: var(--acrb-checkout-secondary );42 color: var(--acrb-checkout-secondary, #64748b); 44 43 } 45 44 46 45 .acrb-checkout-error { 47 max-width: 580px;46 max-width: 600px; 48 47 margin: 80px auto; 49 padding: 50px 40px;48 text-align: center; 50 49 background: #ffffff; 51 50 border: 1px solid #e2e8f0; 52 51 border-radius: 20px; 53 text-align: center;54 box-shadow: 0 1 0px 25px -5px rgba(15, 23, 42, 0.05);52 padding: 48px; 53 box-shadow: 0 15px 30px -10px rgba(15, 23, 42, 0.08); 55 54 } 56 55 57 56 .acrb-checkout-error h3 { 58 color: var(--acrb-checkout-text );57 color: var(--acrb-checkout-text, #0f172a); 59 58 margin-top: 0; 60 font-size: 22px;59 font-size: 1.5rem; 61 60 font-weight: 900; 62 61 letter-spacing: -0.02em; … … 64 63 65 64 .acrb-checkout-error p { 66 color: var(--acrb-checkout-secondary );65 color: var(--acrb-checkout-secondary, #64748b); 67 66 font-size: 14px; 68 margin: 8px 0 2 8px 0;69 line-height: 1. 6;67 margin: 8px 0 24px 0; 68 line-height: 1.5; 70 69 } 71 70 72 71 .acrb-checkout-error a { 73 background: var(--acrb-checkout- btn-bg);74 border: 1px solid var(--acrb-checkout- btn-bg);72 background: var(--acrb-checkout-primary, #4f46e5); 73 border: 1px solid var(--acrb-checkout-primary, #4f46e5); 75 74 color: #ffffff !important; 76 padding: 12px 2 6px;75 padding: 12px 24px; 77 76 border-radius: 10px; 78 77 text-decoration: none; 79 78 font-weight: 700; 80 79 font-size: 14px; 81 display: inline-block; 82 transition: background-color 0.15s ease, border-color 0.15s ease; 80 display: inline-flex; 81 align-items: center; 82 transition: background 0.2s ease, border-color 0.15s ease; 83 83 } 84 84 85 85 .acrb-checkout-error a:hover { 86 background: var(--acrb-checkout-btn-hover );87 border-color: var(--acrb-checkout-btn-hover );86 background: var(--acrb-checkout-btn-hover, #4338ca); 87 border-color: var(--acrb-checkout-btn-hover, #4338ca); 88 88 } 89 89 90 90 /* -------------------------------------------------------------------------- 91 Checkout Core Layout 91 Checkout Core Layout & Progress Steps 92 92 -------------------------------------------------------------------------- */ 93 93 .acrb-checkout-wrapper { 94 max-width: 1200px; 95 margin: 50px auto; 94 max-width: 1240px; 95 margin: 0 auto; 96 padding: 30px 16px 80px 16px; 96 97 } 97 98 … … 100 101 width: 18px; 101 102 height: 18px; 102 stroke-width: 2 ;103 stroke-width: 2.2; 103 104 stroke: currentColor; 104 105 fill: none; … … 109 110 } 110 111 111 /* Progress Steps */112 112 .acrb-checkout-steps { 113 113 display: flex; 114 justify-content: space-between; 115 align-items: center; 116 margin-bottom: 36px; 114 align-items: center; 115 justify-content: center; 116 gap: 12px; 117 margin-bottom: 32px; 118 flex-wrap: wrap; 117 119 background: #ffffff; 118 120 border: 1px solid #e2e8f0; 119 121 border-radius: 16px; 120 padding: 20px 36px;121 box-shadow: 0 4px 1 6px -2px rgba(15, 23, 42, 0.03);122 padding: 16px 24px; 123 box-shadow: 0 4px 15px rgba(15, 23, 42, 0.03); 122 124 } 123 125 … … 125 127 display: flex; 126 128 align-items: center; 127 gap: 1 2px;128 font-size: 14px;129 gap: 10px; 130 font-size: 0.88rem; 129 131 font-weight: 700; 130 color: var(--acrb-checkout-secondary); 132 color: #94a3b8; 133 position: relative; 134 } 135 136 .acrb-step-item:not(:last-child):after { 137 content: ''; 138 display: inline-block; 139 width: 24px; 140 height: 1px; 141 background: #e2e8f0; 142 margin-left: 12px; 131 143 } 132 144 133 145 .acrb-step-item.active { 134 color: var(--acrb-checkout-text); 146 color: var(--acrb-checkout-primary, #4f46e5); 147 } 148 149 .acrb-step-item.completed { 150 color: #059669; 135 151 } 136 152 137 153 .acrb-step-num { 138 width: 3 2px;139 height: 3 2px;154 width: 30px; 155 height: 30px; 140 156 border-radius: 50%; 141 157 background: #f1f5f9; 142 color: var(--acrb-checkout-secondary);158 color: #64748b; 143 159 display: flex; 144 160 align-items: center; 145 161 justify-content: center; 146 font-size: 13px; 147 font-weight: 800; 162 font-size: 0.82rem; 163 font-weight: 800; 164 flex-shrink: 0; 148 165 } 149 166 150 167 .acrb-step-item.active .acrb-step-num { 151 background: var(--acrb-checkout-primary );168 background: var(--acrb-checkout-primary, #4f46e5); 152 169 color: #ffffff; 170 box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3); 171 } 172 173 .acrb-step-item.completed .acrb-step-num { 174 background: #dcfce7; 175 color: #059669; 153 176 } 154 177 … … 156 179 .acrb-checkout-grid { 157 180 display: grid; 158 grid-template-columns: 1fr 4 80px;159 gap: 3 6px;181 grid-template-columns: 1fr 440px; 182 gap: 32px; 160 183 align-items: flex-start; 161 184 } … … 164 187 background: #ffffff; 165 188 border: 1px solid #e2e8f0; 166 border-radius: 16px;167 padding: 32px;168 box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03);169 margin-bottom: 28px;189 border-radius: 20px; 190 padding: 24px; 191 margin-bottom: 24px; 192 box-shadow: 0 4px 20px -4px rgba(15, 23, 42, 0.05); 170 193 } 171 194 172 195 .acrb-checkout-title { 173 font-size: 17.5px; 174 font-weight: 900; 175 color: var(--acrb-checkout-text); 176 margin: 0 0 20px 0; 177 letter-spacing: -0.02em; 178 display: flex; 179 align-items: center; 180 gap: 12px; 181 border-bottom: 1px solid #f1f5f9; 182 padding-bottom: 14px; 183 } 184 185 /* Vehicle Review Card */ 196 margin: 0 0 18px 0; 197 font-size: 1.15rem; 198 font-weight: 800; 199 color: var(--acrb-checkout-text, #0f172a); 200 display: flex; 201 align-items: center; 202 gap: 10px; 203 } 204 205 /* Vehicle Review Card & Itinerary */ 186 206 .acrb-review-box { 187 207 background: #f8fafc; 188 208 border: 1px solid #e2e8f0; 189 border-radius: 1 2px;190 padding: 20px;209 border-radius: 14px; 210 padding: 18px; 191 211 } 192 212 193 213 .acrb-review-vehicle { 194 214 display: flex; 195 gap: 20px; 196 align-items: center; 215 align-items: center; 216 gap: 16px; 217 margin-bottom: 16px; 218 padding-bottom: 16px; 219 border-bottom: 1px dashed #cbd5e1; 197 220 } 198 221 199 222 .acrb-review-thumb { 200 width: 140px;201 height: 95px;223 width: 90px; 224 height: 65px; 202 225 border-radius: 10px; 203 226 overflow: hidden; 204 border: 1px solid #cbd5e1;205 227 background: #ffffff; 228 border: 1px solid #e2e8f0; 206 229 flex-shrink: 0; 207 230 } … … 215 238 216 239 .acrb-review-info h4 { 217 margin: 0 0 6px 0;218 font-size: 1 9px;219 font-weight: 900;220 color: var(--acrb-checkout-text );240 margin: 0 0 4px 0; 241 font-size: 1.05rem; 242 font-weight: 800; 243 color: var(--acrb-checkout-text, #0f172a); 221 244 } 222 245 223 246 .acrb-review-meta { 224 font-size: 13px;225 color: var(--acrb-checkout-secondary );247 font-size: 0.8rem; 248 color: var(--acrb-checkout-secondary, #64748b); 226 249 } 227 250 228 251 .acrb-review-meta strong { 229 color: var(--acrb-checkout-text );252 color: var(--acrb-checkout-text, #0f172a); 230 253 } 231 254 232 255 .acrb-itinerary-grid { 233 256 display: grid; 234 grid-template-columns: repeat(2, 1fr); 235 gap: 12px; 236 margin-top: 18px; 237 padding-top: 18px; 238 border-top: 1px solid #e2e8f0; 257 grid-template-columns: 1fr 1fr; 258 gap: 14px; 239 259 } 240 260 … … 242 262 background: #ffffff; 243 263 border: 1px solid #e2e8f0; 244 padding: 12px 16px; 245 border-radius: 10px; 246 font-size: 12px; 247 color: var(--acrb-checkout-secondary); 248 font-weight: 600; 264 border-radius: 14px; 265 padding: 16px; 249 266 display: flex; 250 267 flex-direction: column; 251 gap: 4px; 252 } 253 254 .acrb-itinerary-pill strong { 255 color: var(--acrb-checkout-text); 256 font-size: 13.5px; 257 font-weight: 800; 258 } 259 260 .acrb-itinerary-schedule-title { 261 color: var(--acrb-checkout-primary); 268 gap: 6px; 269 box-shadow: 0 2px 6px rgba(15, 23, 42, 0.02); 270 position: relative; 271 overflow: hidden; 272 } 273 274 .acrb-itinerary-pill::before { 275 content: ''; 276 position: absolute; 277 top: 0; 278 left: 0; 279 width: 4px; 280 height: 100%; 281 } 282 283 .acrb-itinerary-pill.pickup::before { 284 background: #059669; 285 } 286 287 .acrb-itinerary-pill.return::before { 288 background: var(--acrb-checkout-primary, #4f46e5); 289 } 290 291 .acrb-itinerary-header { 292 display: flex; 293 align-items: center; 294 gap: 6px; 295 font-size: 0.72rem; 296 text-transform: uppercase; 297 font-weight: 800; 298 letter-spacing: 0.06em; 299 color: var(--acrb-checkout-secondary, #64748b); 300 } 301 302 .acrb-itinerary-header svg { 303 width: 14px; 304 height: 14px; 305 stroke-width: 2.2; 306 } 307 308 .acrb-itinerary-pill.pickup .acrb-itinerary-header svg { 309 color: #059669; 310 } 311 312 .acrb-itinerary-pill.return .acrb-itinerary-header svg { 313 color: var(--acrb-checkout-primary, #4f46e5); 314 } 315 316 .acrb-itinerary-date { 317 font-size: 0.95rem; 318 font-weight: 800; 319 color: var(--acrb-checkout-text, #0f172a); 320 display: flex; 321 align-items: center; 322 gap: 6px; 323 } 324 325 .acrb-itinerary-date svg { 326 width: 15px; 327 height: 15px; 328 color: #94a3b8; 329 stroke-width: 2; 330 flex-shrink: 0; 262 331 } 263 332 264 333 .acrb-itinerary-location { 265 font-size: 11px; 334 font-size: 0.8rem; 335 color: #475569; 266 336 font-weight: 500; 267 color: var(--acrb-checkout-secondary); 268 } 269 270 /* Form Fields */ 337 display: flex; 338 align-items: center; 339 gap: 5px; 340 } 341 342 .acrb-itinerary-location svg { 343 width: 13px; 344 height: 13px; 345 color: #94a3b8; 346 flex-shrink: 0; 347 } 348 349 /* Form Fields & Inputs */ 271 350 .acrb-checkout-field { 272 margin-bottom: 18px; 273 } 274 275 .acrb-checkout-field-last { 276 margin-bottom: 0; 351 margin-bottom: 14px; 277 352 } 278 353 279 354 .acrb-checkout-field label { 280 355 display: block; 281 font-size: 13px; 282 font-weight: 800; 283 color: var(--acrb-checkout-text); 284 margin-bottom: 8px; 356 font-size: 0.75rem; 357 text-transform: uppercase; 358 font-weight: 700; 359 color: #475569; 360 margin-bottom: 6px; 361 letter-spacing: 0.04em; 285 362 } 286 363 287 364 .acrb-checkout-input { 288 width: 100% !important; 289 height: 46px !important; 290 padding: 0 16px !important; 291 border: 1px solid #cbd5e1 !important; 292 border-radius: 8px !important; 293 font-size: 14px !important; 294 color: var(--acrb-checkout-text) !important; 295 background: #f8fafc !important; 296 font-family: inherit !important; 297 line-height: 44px !important; 298 box-shadow: none !important; 299 outline: none !important; 300 transition: border-color 0.15s ease, background-color 0.15s ease; 365 width: 100% !important; 366 height: 44px; 367 padding: 8px 14px !important; 368 background: #f8fafc !important; 369 border: 1px solid #e2e8f0 !important; 370 border-radius: 10px !important; 371 font-size: 0.9rem; 372 font-weight: 600; 373 color: var(--acrb-checkout-text, #0f172a) !important; 374 outline: none; 375 transition: border-color 0.15s ease; 376 font-family: inherit; 301 377 } 302 378 303 379 .acrb-checkout-input:focus { 304 border-color: var(--acrb-checkout-primary) !important; 305 background: #ffffff !important; 380 border-color: var(--acrb-checkout-primary, #4f46e5); 381 background: #ffffff; 382 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.12); 306 383 } 307 384 308 385 .acrb-checkout-input:read-only { 309 background: #f1f5f9 !important;310 color: var(--acrb-checkout-secondary) !important;386 background: #f1f5f9; 387 color: #475569; 311 388 cursor: not-allowed; 312 389 } 313 390 314 .acrb-input-compact { 315 height: 42px !important; 316 line-height: 40px !important; 391 /* Payment Options */ 392 .acrb-pay-list { 393 display: flex; 394 flex-direction: column; 395 gap: 10px; 396 } 397 398 .acrb-pay-option { 399 display: flex; 400 align-items: center; 401 gap: 12px; 402 padding: 14px 16px; 403 background: #f8fafc; 404 border: 1.5px solid #e2e8f0; 405 border-radius: 12px; 406 cursor: pointer; 407 font-size: 0.92rem; 408 font-weight: 700; 409 color: var(--acrb-checkout-text, #0f172a); 410 transition: all 0.2s ease; 411 } 412 413 .acrb-pay-option:hover { 414 border-color: #cbd5e1; 415 background: #f1f5f9; 416 } 417 418 .acrb-pay-option.selected { 419 border-color: var(--acrb-checkout-primary, #4f46e5); 420 background: #eef2ff; 421 } 422 423 .acrb-pay-option input { 424 accent-color: var(--acrb-checkout-primary, #4f46e5); 425 width: 16px; 426 height: 16px; 427 cursor: pointer; 317 428 } 318 429 … … 320 431 .acrb-coupon-wrap { 321 432 display: flex; 322 gap: 10px; 433 gap: 8px; 434 } 435 436 .acrb-input-compact { 437 flex: 1; 323 438 } 324 439 325 440 button.acrb-coupon-btn { 326 background: var(--acrb-checkout-btn-bg);441 background: #0f172a; 327 442 color: #ffffff; 328 443 border: none; 329 padding: 0 22px;330 border-radius:8px;331 font- weight: 800;332 font- size: 13.5px;444 border-radius: 10px; 445 padding: 0 18px; 446 font-size: 0.88rem; 447 font-weight: 700; 333 448 cursor: pointer; 334 white-space: nowrap;335 transition: background-color 0.15s ease, opacity 0.15s ease;449 transition: background 0.2s ease; 450 font-family: inherit; 336 451 } 337 452 338 453 button.acrb-coupon-btn:hover { 339 background: var(--acrb-checkout-btn-hover); 340 opacity: 0.94; 454 background: var(--acrb-checkout-primary, #4f46e5); 341 455 } 342 456 343 457 .acrb-coupon-msg { 344 font-size: 12.5px; 345 font-weight: 700; 458 display: none; 459 font-size: 0.8rem; 460 font-weight: 600; 346 461 margin-top: 8px; 347 display: none; 348 } 349 350 /* Payment Radios */ 351 .acrb-pay-list { 352 margin-bottom: 0; 353 } 354 355 .acrb-pay-option { 356 display: flex; 357 align-items: center; 358 cursor: pointer; 359 padding: 15px 20px; 360 border: 1.5px solid #e2e8f0; 361 border-radius: 10px; 362 font-size: 14px; 363 font-weight: 700; 364 color: #334155; 365 background: #ffffff; 366 transition: all 0.15s ease; 367 margin-bottom: 12px; 368 } 369 370 .acrb-pay-option.selected { 371 border-color: var(--acrb-checkout-primary); 372 background: #eef2ff; 373 } 374 375 .acrb-pay-option input[type="radio"] { 376 accent-color: var(--acrb-checkout-primary); 377 width: 18px; 378 height: 18px; 379 margin-right: 14px; 380 cursor: pointer; 381 } 382 383 /* Price Breakdown Summary */ 462 } 463 464 /* Summary Breakdown */ 384 465 .acrb-breakdown-card { 385 466 background: #f8fafc; 386 467 border: 1px solid #e2e8f0; 387 border-radius: 12px; 388 padding: 20px; 389 display: flex; 390 flex-direction: column; 391 gap: 14px; 468 border-radius: 14px; 469 padding: 16px; 470 margin-bottom: 20px; 392 471 } 393 472 … … 395 474 display: flex; 396 475 justify-content: space-between; 397 align-items: flex-start; 398 font-size: 14px; 399 color: #334155; 400 padding-bottom: 12px; 401 border-bottom: 1px solid #e2e8f0; 402 } 403 404 .acrb-bd-item:last-child { 405 border-bottom: none; 406 padding-bottom: 0; 476 align-items: center; 477 margin-bottom: 12px; 478 font-size: 0.88rem; 479 } 480 481 .acrb-bd-label span { 482 display: block; 483 font-weight: 700; 484 color: var(--acrb-checkout-text, #0f172a); 485 } 486 487 .acrb-bd-sub { 488 font-size: 0.74rem; 489 color: var(--acrb-checkout-secondary, #64748b); 490 font-weight: 500; 491 } 492 493 .acrb-bd-val { 494 font-weight: 800; 495 color: var(--acrb-checkout-text, #0f172a); 496 white-space: nowrap; 407 497 } 408 498 409 499 .acrb-bd-discount { 410 500 display: none; 411 color: var(--acrb-checkout-accent); 412 } 413 414 .acrb-bd-label-discount { 415 color: var(--acrb-checkout-accent); 416 } 417 418 .acrb-bd-sub { 419 display: block; 420 font-size: 11.5px; 421 color: var(--acrb-checkout-secondary); 422 margin-top: 3px; 423 font-weight: 500; 424 } 425 426 .acrb-bd-val { 427 font-weight: 800; 428 color: var(--acrb-checkout-text); 501 color: var(--acrb-checkout-accent, #059669) !important; 502 } 503 504 .acrb-bd-discount .acrb-bd-val, 505 .acrb-bd-discount span { 506 color: var(--acrb-checkout-accent, #059669) !important; 429 507 } 430 508 … … 432 510 display: flex; 433 511 justify-content: space-between; 434 align-items: center; 435 border-top: 2px dashed #cbd5e1; 436 padding-top: 18px; 437 margin-top: 4px; 512 align-items: baseline; 513 padding: 16px 0; 514 border-top: 1px dashed #cbd5e1; 515 margin-bottom: 18px; 516 font-size: 1.05rem; 517 font-weight: 800; 518 color: var(--acrb-checkout-text, #0f172a); 519 } 520 521 .acrb-total-accent { 522 font-size: 1.7rem; 438 523 font-weight: 900; 439 color: var(--acrb-checkout-text); 440 font-size: 20px; 441 } 442 443 .acrb-total-accent { 444 color: var(--acrb-checkout-primary); 445 } 446 447 /* Terms Checkbox */ 524 color: var(--acrb-checkout-primary, #4f46e5); 525 letter-spacing: -0.02em; 526 } 527 528 /* Terms & Confirmation Button */ 448 529 .acrb-terms-wrap { 449 margin : 20px 0 14px 0;530 margin-bottom: 20px; 450 531 } 451 532 … … 454 535 align-items: flex-start; 455 536 gap: 10px; 537 font-size: 0.82rem; 538 color: #475569; 456 539 cursor: pointer; 457 font-size: 13px; 458 color: var(--acrb-checkout-secondary); 459 font-weight: 700; 540 line-height: 1.4; 460 541 } 461 542 462 543 .acrb-terms-check { 463 margin-top: 3px; 544 margin-top: 2px; 545 accent-color: var(--acrb-checkout-primary, #4f46e5); 464 546 width: 16px; 465 547 height: 16px; 466 accent-color: var(--acrb-checkout-primary); 467 } 468 469 /* Submit Reservation Button */ 548 cursor: pointer; 549 } 550 470 551 button.acrb-btn-confirm { 471 552 width: 100%; 472 height: 50px; 473 background: var(--acrb-checkout-btn-bg); 474 border: 1px solid var(--acrb-checkout-btn-bg); 553 height: 52px; 554 background: var(--acrb-checkout-btn-bg, #4f46e5); 475 555 color: #ffffff; 476 border-radius: 10px; 477 font-weight: 800; 478 font-size: 15px; 556 border: none; 557 border-radius: 12px; 558 font-size: 1rem; 559 font-weight: 800; 560 display: flex; 561 align-items: center; 562 justify-content: center; 563 gap: 8px; 479 564 cursor: pointer; 480 display: inline-flex; 481 align-items: center; 482 justify-content: center; 483 gap: 10px; 565 transition: all 0.2s ease; 566 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.25); 484 567 font-family: inherit; 485 transition: all 0.15s ease;486 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.25);487 568 } 488 569 489 570 button.acrb-btn-confirm:hover { 490 background: var(--acrb-checkout-btn-hover); 491 border-color: var(--acrb-checkout-btn-hover); 492 opacity: 0.94; 571 background: var(--acrb-checkout-btn-hover, #4338ca); 493 572 transform: translateY(-1px); 494 box-shadow: 0 6px 18px rgba(79, 70, 229, 0.35);495 } 496 497 .acrb-btn-confirm .acrb-checkout-icon{573 box-shadow: 0 6px 20px rgba(79, 70, 229, 0.35); 574 } 575 576 .acrb-btn-confirm svg { 498 577 width: 18px; 499 578 height: 18px; … … 501 580 502 581 /* -------------------------------------------------------------------------- 503 Responsive Rules582 Responsive Breakpoints 504 583 -------------------------------------------------------------------------- */ 505 @media (max-width: 9 00px) {584 @media (max-width: 980px) { 506 585 .acrb-checkout-grid { 507 586 grid-template-columns: 1fr; 508 587 } 588 } 589 590 @media (max-width: 600px) { 591 .acrb-itinerary-grid { 592 grid-template-columns: 1fr; 593 } 509 594 .acrb-checkout-steps { 595 flex-direction: column; 596 align-items: flex-start; 597 padding: 16px; 598 } 599 .acrb-step-item:not(:last-child):after { 510 600 display: none; 511 601 } -
awesome-car-rental/trunk/assets/css/frontend/header-auth.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB HEADER AUTH WIDGET (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/header-auth.css 3 4 ========================================================================== */ 4 5 … … 12 13 --acrb-auth-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 13 14 14 font-family: var(--acrb-auth-font );15 font-family: var(--acrb-auth-font, sans-serif); 15 16 display: inline-flex; 16 17 align-items: center; 18 position: relative; 17 19 box-sizing: border-box; 18 color: var(--acrb-auth-text );20 color: var(--acrb-auth-text, #0f172a); 19 21 } 20 22 21 .acrb-header-auth,22 23 .acrb-header-auth *, 23 24 .acrb-header-auth *::before, 24 25 .acrb-header-auth *::after { 25 box-sizing: border-box;26 box-sizing: inherit; 26 27 } 27 28 … … 29 30 .acrb-header-auth .acrb-auth-svg { 30 31 display: inline-block; 31 width: 16px; 32 height: 16px; 33 stroke-width: 2; 32 width: 15px; 33 height: 15px; 34 34 stroke: currentColor; 35 35 fill: none; 36 stroke-width: 2.2; 36 37 stroke-linecap: round; 37 38 stroke-linejoin: round; … … 53 54 border: 1px solid #e2e8f0; 54 55 box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04); 55 transition: border-color 0. 15s ease, box-shadow 0.15s ease, transform 0.15s ease;56 transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease; 56 57 } 57 58 58 59 .acrb-header-auth .acrb-user-wrapper:hover { 59 border-color: #cbd5e1; 60 border-color: var(--acrb-auth-primary, #4f46e5); 61 background: #ffffff; 60 62 box-shadow: 0 4px 12px -2px rgba(15, 23, 42, 0.08); 61 63 transform: translateY(-1px); … … 74 76 align-items: center; 75 77 justify-content: center; 78 flex-shrink: 0; 76 79 } 77 80 … … 92 95 .acrb-header-auth .acrb-user-greeting { 93 96 font-size: 10px; 94 color: var(--acrb-auth-secondary );97 color: var(--acrb-auth-secondary, #64748b); 95 98 font-weight: 700; 96 99 text-transform: uppercase; … … 101 104 font-size: 13px; 102 105 font-weight: 800; 103 color: var(--acrb-auth-text );104 max-width: 1 20px;106 color: var(--acrb-auth-text, #0f172a); 107 max-width: 130px; 105 108 overflow: hidden; 106 109 text-overflow: ellipsis; … … 109 112 110 113 .acrb-header-auth .acrb-user-chevron { 111 color: var(--acrb-auth-secondary);114 color: #94a3b8; 112 115 margin-left: 2px; 113 transition: transform 0. 15s ease, color 0.15s ease;116 transition: transform 0.2s ease, color 0.2s ease; 114 117 } 115 118 116 119 .acrb-header-auth .acrb-user-wrapper:hover .acrb-user-chevron { 117 120 transform: translateX(2px); 118 color: var(--acrb-auth-primary );121 color: var(--acrb-auth-primary, #4f46e5); 119 122 } 120 123 … … 132 135 align-items: center; 133 136 justify-content: center; 134 gap: 7px;137 gap: 6px; 135 138 text-decoration: none !important; 136 139 font-size: 13px; … … 139 142 border-radius: 8px; 140 143 height: 38px; 144 line-height: 1; 141 145 transition: all 0.15s ease; 142 box-sizing: border-box;143 146 white-space: nowrap; 147 font-family: inherit; 144 148 } 145 149 146 150 /* Login Button */ 147 151 .acrb-header-auth .acrb-h-login { 148 background: #f fffff;149 color: var(--acrb-auth-text ) !important;152 background: #f8fafc; 153 color: var(--acrb-auth-text, #0f172a) !important; 150 154 border: 1px solid #cbd5e1; 151 155 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.03); … … 153 157 154 158 .acrb-header-auth .acrb-h-login .acrb-auth-svg { 155 color: var(--acrb-auth-secondary );159 color: var(--acrb-auth-secondary, #64748b); 156 160 transition: color 0.15s ease; 157 161 } 158 162 159 163 .acrb-header-auth .acrb-h-login:hover { 160 background: #f 8fafc;164 background: #f1f5f9; 161 165 border-color: #94a3b8; 162 color: var(--acrb-auth-text ) !important;166 color: var(--acrb-auth-text, #0f172a) !important; 163 167 transform: translateY(-1px); 164 168 } 165 169 166 170 .acrb-header-auth .acrb-h-login:hover .acrb-auth-svg { 167 color: var(--acrb-auth-primary );171 color: var(--acrb-auth-primary, #4f46e5); 168 172 } 169 173 170 /* Register Button (Uses Customizer Button Colors)*/174 /* Register Button */ 171 175 .acrb-header-auth .acrb-h-reg { 172 background: var(--acrb-auth-btn-bg );176 background: var(--acrb-auth-btn-bg, #4f46e5); 173 177 color: #ffffff !important; 174 border: 1px solid var(--acrb-auth-btn-bg );175 box-shadow: 0 2px 6px rgba( 15, 23, 42, 0.12);178 border: 1px solid var(--acrb-auth-btn-bg, #4f46e5); 179 box-shadow: 0 2px 6px rgba(79, 70, 229, 0.18); 176 180 } 177 181 … … 181 185 182 186 .acrb-header-auth .acrb-h-reg:hover { 183 background: var(--acrb-auth-btn-hover );184 border-color: var(--acrb-auth-btn-hover );187 background: var(--acrb-auth-btn-hover, #4338ca); 188 border-color: var(--acrb-auth-btn-hover, #4338ca); 185 189 opacity: 0.94; 186 190 transform: translateY(-1px); 187 box-shadow: 0 4px 12px rgba( 15, 23, 42, 0.16);191 box-shadow: 0 4px 12px rgba(79, 70, 229, 0.28); 188 192 color: #ffffff !important; 189 193 } -
awesome-car-rental/trunk/assets/css/frontend/login.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB LOGIN COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/login.css 3 4 ========================================================================== */ 4 5 5 6 /* Scoped Variable Fallbacks & Font/Text Colors */ 6 .acrb-auth-page-wrapper { 7 .acrb-auth-page-wrapper, 8 .acrb-auth-solo-wrapper { 7 9 --acrb-login-primary: #4f46e5; 8 10 --acrb-login-secondary: #64748b; … … 13 15 --acrb-login-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 14 16 15 font-family: var(--acrb-login-font); 16 color: var(--acrb-login-text); 17 max-width: 980px; 18 margin: 40px auto; 19 display: flex; 20 background: #ffffff; 21 border-radius: 20px; 22 overflow: hidden; 23 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.08); 24 border: 1px solid #e2e8f0; 17 font-family: var(--acrb-login-font, sans-serif); 18 color: var(--acrb-login-text, #0f172a); 25 19 box-sizing: border-box; 26 20 } 27 21 28 .acrb-auth-page-wrapper,29 22 .acrb-auth-page-wrapper *, 30 23 .acrb-auth-page-wrapper *::before, 31 .acrb-auth-page-wrapper *::after { 32 box-sizing: border-box; 24 .acrb-auth-page-wrapper *::after, 25 .acrb-auth-solo-wrapper *, 26 .acrb-auth-solo-wrapper *::before, 27 .acrb-auth-solo-wrapper *::after { 28 box-sizing: inherit; 33 29 } 34 30 … … 36 32 SVG Icon Standards 37 33 -------------------------------------------------------------------------- */ 38 .acrb- auth-page-wrapper .acrb-login-icon {34 .acrb-login-icon { 39 35 display: inline-block; 40 36 width: 18px; … … 50 46 51 47 /* -------------------------------------------------------------------------- 48 Wrapper Layouts (Solo vs Split Container) 49 -------------------------------------------------------------------------- */ 50 .acrb-auth-solo-wrapper { 51 display: flex; 52 align-items: center; 53 justify-content: center; 54 min-height: 80vh; 55 padding: 24px 16px; 56 } 57 58 .acrb-auth-page-wrapper { 59 max-width: 980px; 60 margin: 40px auto; 61 display: flex; 62 background: #ffffff; 63 border-radius: 20px; 64 overflow: hidden; 65 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.08); 66 border: 1px solid #e2e8f0; 67 } 68 69 /* -------------------------------------------------------------------------- 52 70 Side Info Panel (Solid Dark Theme - No Gradients) 53 71 -------------------------------------------------------------------------- */ 54 .acrb-auth- page-wrapper .acrb-auth-side-info {72 .acrb-auth-side-info { 55 73 flex: 1; 56 background: var(--acrb-login-text );74 background: var(--acrb-login-text, #0f172a); 57 75 padding: 50px 40px; 58 76 color: #ffffff; … … 63 81 } 64 82 65 .acrb-auth- page-wrapper .acrb-auth-side-info h2 {83 .acrb-auth-side-info h2 { 66 84 color: #ffffff !important; 67 85 font-size: 28px; … … 72 90 } 73 91 74 .acrb-auth- page-wrapper .acrb-auth-side-info p {92 .acrb-auth-side-info p { 75 93 color: #94a3b8; 76 94 line-height: 1.55; … … 79 97 } 80 98 81 .acrb-auth- page-wrapper .acrb-auth-security-badge {99 .acrb-auth-security-badge { 82 100 margin-top: 28px; 83 101 display: flex; … … 90 108 } 91 109 92 .acrb- auth-page-wrapper .acrb-badge-icon {110 .acrb-badge-icon { 93 111 color: #60a5fa; 94 112 width: 22px; 95 113 height: 22px; 96 } 97 98 .acrb-auth-page-wrapper .acrb-badge-text { 114 flex-shrink: 0; 115 } 116 117 .acrb-badge-text { 99 118 font-size: 12.5px; 100 119 color: #cbd5e1; … … 105 124 Form Card & Controls 106 125 -------------------------------------------------------------------------- */ 126 .acrb-auth-card { 127 background: #ffffff; 128 border: 1px solid #e2e8f0; 129 border-radius: 24px; 130 padding: 36px 40px; 131 width: 100%; 132 max-width: 440px; 133 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.08); 134 } 135 107 136 .acrb-auth-page-wrapper .acrb-auth-card { 108 137 flex: 1.2; 109 138 padding: 50px 40px; 110 background: #ffffff; 139 border: none; 140 max-width: none; 141 box-shadow: none; 111 142 display: flex; 112 143 flex-direction: column; 113 144 justify-content: center; 145 } 146 147 .acrb-auth-title { 148 margin: 0 0 6px 0; 149 font-size: 1.75rem; 150 font-weight: 900; 151 color: var(--acrb-login-text, #0f172a); 152 letter-spacing: -0.02em; 114 153 } 115 154 … … 117 156 font-size: 24px; 118 157 font-weight: 800; 119 color: var(--acrb-login-text); 120 margin: 0 0 4px 0; 121 letter-spacing: -0.02em; 158 } 159 160 .acrb-auth-subtitle { 161 margin: 0 0 24px 0; 162 font-size: 0.9rem; 163 color: var(--acrb-login-secondary, #64748b); 122 164 } 123 165 124 166 .acrb-auth-page-wrapper .acrb-auth-subtitle { 125 color: var(--acrb-login-secondary);167 margin-bottom: 28px; 126 168 font-size: 13.5px; 127 margin: 0 0 28px 0; 169 } 170 171 .acrb-login-field { 172 margin-bottom: 18px; 128 173 } 129 174 … … 136 181 } 137 182 138 .acrb-auth-page-wrapper .acrb-password-header { 183 .acrb-login-field label { 184 display: block; 185 font-size: 0.75rem; 186 text-transform: uppercase; 187 font-weight: 700; 188 color: #475569; 189 margin-bottom: 6px; 190 letter-spacing: 0.04em; 191 } 192 193 .acrb-auth-page-wrapper .acrb-login-field label { 194 font-size: 13px; 195 color: var(--acrb-login-text, #0f172a); 196 } 197 198 .acrb-login-field input { 199 width: 100% !important; 200 height: 46px !important; 201 padding: 8px 14px !important; 202 background: #f8fafc !important; 203 border: 1px solid #e2e8f0 !important; 204 border-radius: 12px !important; 205 font-size: 0.92rem !important; 206 font-weight: 600 !important; 207 color: var(--acrb-login-text, #0f172a) !important; 208 transition: all 0.2s ease !important; 209 font-family: inherit !important; 210 outline: none !important; 211 } 212 213 .acrb-auth-page-wrapper .acrb-login-field input { 214 height: 42px !important; 215 padding: 0 14px !important; 216 border-color: #cbd5e1 !important; 217 border-radius: 8px !important; 218 font-size: 13.5px !important; 219 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important; 220 } 221 222 .acrb-login-field input:hover { 223 border-color: #94a3b8 !important; 224 background: #ffffff !important; 225 } 226 227 .acrb-login-field input:focus { 228 background: #ffffff !important; 229 border-color: var(--acrb-login-primary, #4f46e5) !important; 230 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.12) !important; 231 } 232 233 .acrb-auth-page-wrapper .acrb-login-field input:focus { 234 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.08) !important; 235 } 236 237 .acrb-password-header { 139 238 display: flex; 140 239 justify-content: space-between; … … 143 242 } 144 243 145 .acrb-auth-page-wrapper .acrb-password-header label { 146 margin-bottom: 0; 244 .acrb-password-header label { 245 margin-bottom: 0 !important; 246 } 247 248 .acrb-forgot-link { 249 font-size: 0.78rem; 250 font-weight: 700; 251 color: var(--acrb-login-primary, #4f46e5); 252 text-decoration: none; 253 transition: opacity 0.15s ease; 147 254 } 148 255 149 256 .acrb-auth-page-wrapper .acrb-forgot-link { 150 257 font-size: 12px; 151 color: var(--acrb-login-primary); 152 font-weight: 700; 153 text-decoration: none; 154 transition: opacity 0.15s ease; 155 } 156 157 .acrb-auth-page-wrapper .acrb-forgot-link:hover { 258 } 259 260 .acrb-forgot-link:hover { 158 261 text-decoration: underline; 159 262 opacity: 0.9; 160 263 } 161 264 162 .acrb-auth-page-wrapper .acrb-login-field label {163 display: block;164 font-size: 13px;165 font-weight: 700;166 color: var(--acrb-login-text);167 margin-bottom: 6px;168 }169 170 .acrb-auth-page-wrapper .acrb-login-field input {171 width: 100% !important;172 height: 42px !important;173 padding: 0 14px !important;174 border: 1px solid #cbd5e1 !important;175 border-radius: 8px !important;176 font-size: 13.5px !important;177 color: var(--acrb-login-text) !important;178 background: #f8fafc !important;179 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important;180 outline: none !important;181 font-family: inherit !important;182 transition: border-color 0.15s ease, background-color 0.15s ease !important;183 }184 185 .acrb-auth-page-wrapper .acrb-login-field input:hover {186 border-color: #94a3b8 !important;187 background: #ffffff !important;188 }189 190 .acrb-auth-page-wrapper .acrb-login-field input:focus {191 background: #ffffff !important;192 border-color: var(--acrb-login-primary) !important;193 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.08) !important;194 }195 196 265 /* -------------------------------------------------------------------------- 197 266 Buttons & Status Messages 198 267 -------------------------------------------------------------------------- */ 199 .acrb- auth-page-wrapper .acrb-login-btn {268 .acrb-login-btn { 200 269 width: 100%; 201 height: 44px; 202 background: var(--acrb-login-btn-bg); 203 border: 1px solid var(--acrb-login-btn-bg); 270 height: 48px; 271 background: var(--acrb-login-btn-bg, #4f46e5); 204 272 color: #ffffff !important; 205 border-radius: 8px; 206 font-weight: 700; 207 font-size: 13.5px; 208 cursor: pointer; 209 margin-top: 6px; 210 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 211 transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease, transform 0.15s ease; 212 display: inline-flex; 273 border: none; 274 border-radius: 12px; 275 font-size: 0.95rem; 276 font-weight: 800; 277 display: flex; 213 278 align-items: center; 214 279 justify-content: center; 215 280 gap: 8px; 281 cursor: pointer; 282 transition: all 0.2s ease; 283 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.25); 284 margin-top: 24px; 216 285 font-family: inherit; 217 286 } 218 287 219 .acrb-auth-page-wrapper .acrb-login-btn:hover { 220 background: var(--acrb-login-btn-hover); 221 border-color: var(--acrb-login-btn-hover); 288 .acrb-auth-page-wrapper .acrb-login-btn { 289 height: 44px; 290 border-radius: 8px; 291 font-size: 13.5px; 292 margin-top: 6px; 293 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 294 } 295 296 .acrb-login-btn:hover { 297 background: var(--acrb-login-btn-hover, #4338ca); 298 transform: translateY(-1px); 299 box-shadow: 0 6px 18px rgba(79, 70, 229, 0.35); 222 300 opacity: 0.94; 223 transform: translateY(-1px); 301 } 302 303 .acrb-login-btn:disabled { 304 opacity: 0.7; 305 cursor: not-allowed; 306 transform: none !important; 307 box-shadow: none !important; 224 308 } 225 309 … … 227 311 background: #94a3b8 !important; 228 312 border-color: #94a3b8 !important; 229 cursor: not-allowed; 230 box-shadow: none !important; 231 transform: none !important; 232 opacity: 0.7; 233 } 234 235 .acrb-auth-page-wrapper .acrb-auth-footer { 313 } 314 315 #acrb-login-status { 316 margin-top: 14px; 317 font-size: 0.85rem; 236 318 text-align: center; 237 margin-top: 24px; 319 font-weight: 600; 320 min-height: 22px; 321 } 322 323 .acrb-auth-page-wrapper #acrb-login-status { 238 324 font-size: 13px; 239 color: var(--acrb-login-secondary); 240 } 241 242 .acrb-auth-page-wrapper .acrb-auth-footer a { 243 color: var(--acrb-login-primary); 244 font-weight: 700; 245 text-decoration: none; 246 } 247 248 .acrb-auth-page-wrapper .acrb-auth-footer a:hover { 249 text-decoration: underline; 250 } 251 252 .acrb-auth-page-wrapper #acrb-login-status { 253 margin-top: 14px; 254 font-size: 13px; 255 text-align: center; 256 min-height: 22px; 257 font-weight: 600; 325 } 326 327 .status-loading { 328 color: #64748b; 329 } 330 331 .acrb-auth-page-wrapper .status-loading { 332 color: var(--acrb-login-primary, #4f46e5); 333 } 334 335 .status-success { 336 color: #059669; 337 } 338 339 .acrb-auth-page-wrapper .status-success { 340 color: var(--acrb-login-accent, #059669); 341 } 342 343 .status-error { 344 color: #dc2626; 345 background: #fef2f2; 346 border: 1px solid #fecaca; 347 padding: 8px 12px; 348 border-radius: 8px; 258 349 } 259 350 … … 261 352 color: #991b1b; 262 353 padding: 10px 14px; 263 background: #fef2f2; 264 border-radius: 8px; 265 border: 1px solid #fecaca; 266 } 267 268 .acrb-auth-page-wrapper .status-loading { 269 color: var(--acrb-login-primary); 270 font-weight: 600; 271 } 272 273 .acrb-auth-page-wrapper .status-success { 274 color: var(--acrb-login-accent); 275 font-weight: 600; 354 } 355 356 .acrb-auth-footer { 357 text-align: center; 358 margin-top: 24px; 359 font-size: 0.85rem; 360 color: var(--acrb-login-secondary, #64748b); 361 } 362 363 .acrb-auth-page-wrapper .acrb-auth-footer { 364 font-size: 13px; 365 } 366 367 .acrb-auth-footer a { 368 color: var(--acrb-login-primary, #4f46e5); 369 font-weight: 700; 370 text-decoration: none; 371 } 372 373 .acrb-auth-footer a:hover { 374 text-decoration: underline; 276 375 } 277 376 … … 284 383 margin: 20px; 285 384 } 286 .acrb-auth- page-wrapper .acrb-auth-side-info {385 .acrb-auth-side-info { 287 386 padding: 32px 24px; 288 387 } … … 291 390 } 292 391 } 392 393 @media (max-width: 480px) { 394 .acrb-auth-card { 395 padding: 24px 20px; 396 border: none; 397 box-shadow: none; 398 background: transparent; 399 } 400 .acrb-auth-solo-wrapper { 401 padding: 0; 402 } 403 } -
awesome-car-rental/trunk/assets/css/frontend/register.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB REGISTRATION COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/register.css 3 4 ========================================================================== */ 4 5 5 6 /* Scoped Variable Fallbacks & Font/Text Colors */ 6 .acrb-reg-container { 7 .acrb-reg-container, 8 .acrb-reg-solo-wrapper { 7 9 --acrb-reg-primary: #4f46e5; 8 10 --acrb-reg-secondary: #64748b; … … 13 15 --acrb-reg-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 14 16 15 font-family: var(--acrb-reg-font); 16 color: var(--acrb-reg-text); 17 max-width: 980px; 18 margin: 40px auto; 19 display: flex; 20 background: #ffffff; 21 border-radius: 20px; 22 overflow: hidden; 23 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.08); 24 border: 1px solid #e2e8f0; 17 font-family: var(--acrb-reg-font, sans-serif); 18 color: var(--acrb-reg-text, #0f172a); 25 19 box-sizing: border-box; 26 20 } 27 21 28 .acrb-reg-container,29 22 .acrb-reg-container *, 30 23 .acrb-reg-container *::before, 31 .acrb-reg-container *::after { 32 box-sizing: border-box; 24 .acrb-reg-container *::after, 25 .acrb-reg-solo-wrapper *, 26 .acrb-reg-solo-wrapper *::before, 27 .acrb-reg-solo-wrapper *::after { 28 box-sizing: inherit; 33 29 } 34 30 … … 36 32 SVG Icon Standards 37 33 -------------------------------------------------------------------------- */ 38 .acrb-reg- container .acrb-reg-icon {34 .acrb-reg-icon { 39 35 display: inline-block; 40 36 width: 18px; … … 50 46 51 47 /* -------------------------------------------------------------------------- 48 Wrapper Layouts (Solo vs Split Container) 49 -------------------------------------------------------------------------- */ 50 .acrb-reg-solo-wrapper { 51 display: flex; 52 align-items: center; 53 justify-content: center; 54 min-height: 85vh; 55 padding: 24px 16px; 56 } 57 58 .acrb-reg-container { 59 max-width: 980px; 60 margin: 40px auto; 61 display: flex; 62 background: #ffffff; 63 border-radius: 20px; 64 overflow: hidden; 65 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.08); 66 border: 1px solid #e2e8f0; 67 } 68 69 /* -------------------------------------------------------------------------- 52 70 Side Info Panel (Solid Dark Surface - No Gradients) 53 71 -------------------------------------------------------------------------- */ 54 .acrb-reg- container .acrb-reg-info {72 .acrb-reg-info { 55 73 flex: 1; 56 background: var(--acrb-reg-text );74 background: var(--acrb-reg-text, #0f172a); 57 75 padding: 50px 40px; 58 76 color: #ffffff; … … 62 80 } 63 81 64 .acrb-reg- container .acrb-reg-info h2 {82 .acrb-reg-info h2 { 65 83 color: #ffffff !important; 66 84 font-size: 28px; … … 71 89 } 72 90 73 .acrb-reg- container .acrb-reg-info p {91 .acrb-reg-info p { 74 92 color: #94a3b8; 75 93 line-height: 1.55; … … 78 96 } 79 97 80 .acrb- reg-container .acrb-info-list {98 .acrb-info-list { 81 99 list-style: none; 82 100 padding: 0; … … 84 102 } 85 103 86 .acrb- reg-container .acrb-info-list li {104 .acrb-info-list li { 87 105 display: flex; 88 106 align-items: center; … … 94 112 } 95 113 96 .acrb- reg-container .acrb-info-list .acrb-reg-icon {97 color: var(--acrb-reg-primary );98 } 99 100 .acrb-reg-co ntainer .acrb-reg-copyright {114 .acrb-info-list .acrb-reg-icon { 115 color: var(--acrb-reg-primary, #4f46e5); 116 } 117 118 .acrb-reg-copyright { 101 119 font-size: 11.5px; 102 120 color: rgba(255, 255, 255, 0.6); … … 108 126 Registration Form Card & Grid Inputs 109 127 -------------------------------------------------------------------------- */ 128 .acrb-reg-card { 129 background: #ffffff; 130 border: 1px solid #e2e8f0; 131 border-radius: 24px; 132 padding: 36px 40px; 133 width: 100%; 134 max-width: 520px; 135 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.08); 136 } 137 110 138 .acrb-reg-container .acrb-reg-card { 111 139 flex: 1.4; 112 140 padding: 50px 40px; 113 background: #ffffff; 141 border: none; 142 max-width: none; 143 box-shadow: none; 114 144 display: flex; 115 145 flex-direction: column; 116 146 justify-content: center; 147 } 148 149 .acrb-reg-title { 150 margin: 0 0 6px 0; 151 font-size: 1.75rem; 152 font-weight: 900; 153 color: var(--acrb-reg-text, #0f172a); 154 letter-spacing: -0.02em; 117 155 } 118 156 … … 120 158 font-size: 24px; 121 159 font-weight: 800; 122 color: var(--acrb-reg-text); 123 margin: 0 0 4px 0; 124 letter-spacing: -0.02em; 125 } 126 127 .acrb-reg-container .acrb-reg-subtitle { 128 color: var(--acrb-reg-secondary); 129 font-size: 13.5px; 160 } 161 162 .acrb-reg-subtitle { 130 163 margin: 0 0 24px 0; 131 } 132 133 .acrb-reg-container .acrb-reg-grid { 164 font-size: 0.9rem; 165 color: var(--acrb-reg-secondary, #64748b); 166 } 167 168 .acrb-reg-grid { 134 169 display: grid; 135 170 grid-template-columns: 1fr 1fr; 136 171 gap: 16px; 137 } 138 172 margin-bottom: 16px; 173 } 174 175 .acrb-reg-field { 176 display: flex; 177 flex-direction: column; 178 gap: 6px; 179 } 180 181 .acrb-reg-field.full-width, 139 182 .acrb-reg-container .acrb-reg-full { 140 grid-column: span 2; 183 grid-column: 1 / -1; 184 } 185 186 .acrb-reg-field label { 187 font-size: 0.75rem; 188 text-transform: uppercase; 189 font-weight: 700; 190 color: #475569; 191 letter-spacing: 0.04em; 141 192 } 142 193 143 194 .acrb-reg-container .acrb-reg-field label { 144 display: block;145 195 font-size: 13px; 146 font-weight: 700; 147 color: var(--acrb-reg-text); 148 margin-bottom: 6px; 149 } 150 196 color: var(--acrb-reg-text, #0f172a); 197 } 198 199 .acrb-reg-field input, 151 200 .acrb-reg-container .acrb-reg-field input { 152 201 width: 100% !important; 202 height: 44px !important; 203 padding: 8px 14px !important; 204 background: #f8fafc !important; 205 border: 1px solid #e2e8f0 !important; 206 border-radius: 12px !important; 207 font-size: 0.9rem !important; 208 font-weight: 600 !important; 209 color: var(--acrb-reg-text, #0f172a) !important; 210 transition: all 0.2s ease !important; 211 font-family: inherit !important; 212 outline: none !important; 213 } 214 215 .acrb-reg-container .acrb-reg-field input { 153 216 height: 42px !important; 154 217 padding: 0 14px !important; 155 border : 1px solid#cbd5e1 !important;218 border-color: #cbd5e1 !important; 156 219 border-radius: 8px !important; 157 220 font-size: 13.5px !important; 158 color: var(--acrb-reg-text) !important;159 background: #f8fafc !important;160 221 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important; 161 font-family: inherit !important;162 222 line-height: 40px !important; 163 outline: none !important; 164 transition: border-color 0.15s ease, background-color 0.15s ease !important; 165 } 166 167 .acrb-reg-container .acrb-reg-field input:hover { 223 } 224 225 .acrb-reg-field input:hover { 168 226 border-color: #94a3b8 !important; 169 227 background: #ffffff !important; 170 228 } 171 229 172 .acrb-reg- container .acrb-reg-field input:focus {230 .acrb-reg-field input:focus { 173 231 background: #ffffff !important; 174 border-color: var(--acrb-reg-primary) !important; 175 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.08) !important; 232 border-color: var(--acrb-reg-primary, #4f46e5) !important; 233 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.12) !important; 234 } 235 236 /* Password Strength & Match Feedback */ 237 .acrb-password-meter-wrap { 238 margin-top: 4px; 239 display: flex; 240 flex-direction: column; 241 gap: 4px; 242 } 243 244 .acrb-password-meter-bar { 245 width: 100%; 246 height: 4px; 247 background: #e2e8f0; 248 border-radius: 999px; 249 overflow: hidden; 250 } 251 252 .acrb-password-meter-fill { 253 height: 100%; 254 width: 0%; 255 transition: width 0.25s ease, background-color 0.25s ease; 256 } 257 258 .acrb-password-meter-label { 259 font-size: 0.72rem; 260 font-weight: 600; 261 color: #64748b; 262 } 263 264 .acrb-field-feedback { 265 display: flex; 266 align-items: center; 267 gap: 4px; 268 font-size: 0.75rem; 269 margin-top: 4px; 270 font-weight: 500; 271 } 272 273 .acrb-field-feedback.is-match { 274 color: #059669; 275 } 276 277 .acrb-field-feedback.is-mismatch { 278 color: #dc2626; 279 } 280 281 .acrb-field-feedback svg { 282 width: 13px; 283 height: 13px; 284 flex-shrink: 0; 176 285 } 177 286 … … 179 288 Submit Button & Status Feedback 180 289 -------------------------------------------------------------------------- */ 181 .acrb-reg- container .acrb-reg-btn {290 .acrb-reg-btn { 182 291 width: 100%; 183 height: 44px; 184 background: var(--acrb-reg-btn-bg); 185 border: 1px solid var(--acrb-reg-btn-bg); 292 height: 48px; 293 background: var(--acrb-reg-btn-bg, #4f46e5); 186 294 color: #ffffff !important; 187 border-radius: 8px; 188 font-weight: 700; 189 font-size: 13.5px; 190 cursor: pointer; 191 margin-top: 20px; 192 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 193 transition: background-color 0.15s ease, border-color 0.15s ease, opacity 0.15s ease, transform 0.15s ease; 194 display: inline-flex; 295 border: none; 296 border-radius: 12px; 297 font-size: 0.95rem; 298 font-weight: 800; 299 display: flex; 195 300 align-items: center; 196 301 justify-content: center; 197 302 gap: 8px; 303 cursor: pointer; 304 transition: all 0.2s ease; 305 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.25); 306 margin-top: 20px; 198 307 font-family: inherit; 199 308 } 200 309 201 .acrb-reg-container .acrb-reg-btn:hover { 202 background: var(--acrb-reg-btn-hover); 203 border-color: var(--acrb-reg-btn-hover); 310 .acrb-reg-container .acrb-reg-btn { 311 height: 44px; 312 border-radius: 8px; 313 font-size: 13.5px; 314 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12); 315 } 316 317 .acrb-reg-btn:hover { 318 background: var(--acrb-reg-btn-hover, #4338ca); 319 transform: translateY(-1px); 320 box-shadow: 0 6px 18px rgba(79, 70, 229, 0.35); 204 321 opacity: 0.94; 205 transform: translateY(-1px); 322 } 323 324 .acrb-reg-btn:disabled { 325 opacity: 0.6; 326 cursor: not-allowed; 327 transform: none !important; 328 box-shadow: none !important; 206 329 } 207 330 … … 209 332 background: #94a3b8 !important; 210 333 border-color: #94a3b8 !important; 211 cursor: not-allowed; 212 box-shadow: none !important; 213 transform: none !important; 214 opacity: 0.7; 215 } 216 217 .acrb-reg-container .acrb-reg-footer { 334 } 335 336 #acrb-reg-msg { 337 margin-top: 14px; 338 font-size: 0.85rem; 218 339 text-align: center; 219 margin-top: 22px; 220 font-size: 13px; 221 color: var(--acrb-reg-secondary); 222 } 223 224 .acrb-reg-container .acrb-reg-footer a { 225 color: var(--acrb-reg-primary); 226 font-weight: 700; 227 text-decoration: none; 228 } 229 230 .acrb-reg-container .acrb-reg-footer a:hover { 231 text-decoration: underline; 340 font-weight: 600; 341 } 342 343 .status-loading { 344 color: #64748b; 345 } 346 347 .status-success { 348 color: #059669; 349 } 350 351 .status-error { 352 color: #dc2626; 353 background: #fef2f2; 354 border: 1px solid #fecaca; 355 padding: 8px 12px; 356 border-radius: 8px; 357 text-align: left; 232 358 } 233 359 … … 256 382 } 257 383 384 .acrb-reg-footer { 385 text-align: center; 386 margin-top: 24px; 387 font-size: 0.85rem; 388 color: var(--acrb-reg-secondary, #64748b); 389 } 390 391 .acrb-reg-container .acrb-reg-footer { 392 margin-top: 22px; 393 font-size: 13px; 394 } 395 396 .acrb-reg-footer a { 397 color: var(--acrb-reg-primary, #4f46e5); 398 font-weight: 700; 399 text-decoration: none; 400 } 401 402 .acrb-reg-footer a:hover { 403 text-decoration: underline; 404 } 405 258 406 /* -------------------------------------------------------------------------- 259 407 Responsive Breakpoints … … 277 425 } 278 426 } 427 428 @media (max-width: 640px) { 429 .acrb-reg-grid { 430 grid-template-columns: 1fr; 431 } 432 .acrb-reg-card { 433 padding: 24px 20px; 434 border: none; 435 box-shadow: none; 436 background: transparent; 437 } 438 .acrb-reg-solo-wrapper { 439 padding: 0; 440 } 441 } -
awesome-car-rental/trunk/assets/css/frontend/search.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB SEARCH BAR (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/search-form.css 3 4 ========================================================================== */ 4 5 … … 15 16 max-width: 1200px; 16 17 margin: 0 auto; 17 font-family: var(--acrb-search-font );18 color: var(--acrb-search-text );18 font-family: var(--acrb-search-font, sans-serif); 19 color: var(--acrb-search-text, #0f172a); 19 20 box-sizing: border-box; 20 21 } 21 22 22 .acrb-search-wrapper,23 23 .acrb-search-wrapper *, 24 24 .acrb-search-wrapper *::before, 25 25 .acrb-search-wrapper *::after { 26 box-sizing: border-box;26 box-sizing: inherit; 27 27 } 28 28 … … 46 46 .acrb-search-wrapper .acrb-search-form { 47 47 background: #ffffff; 48 border: 1px solid #e2e8f0;48 border: 1px solid rgba(226, 232, 240, 0.8); 49 49 border-radius: 16px; 50 50 padding: 26px 30px; … … 54 54 .acrb-search-wrapper .acrb-search-main { 55 55 display: grid; 56 grid-template-columns: 1fr 1fr 1fr 1frauto;56 grid-template-columns: repeat(4, 1fr) auto; 57 57 gap: 18px; 58 58 align-items: flex-end; … … 62 62 display: flex; 63 63 flex-direction: column; 64 gap: 0.5rem; 64 65 } 65 66 … … 70 71 font-size: 13px; 71 72 font-weight: 700; 72 color: var(--acrb-search- text);73 margin-bottom: 6px;73 color: var(--acrb-search-secondary, #64748b); 74 margin-bottom: 2px; 74 75 } 75 76 76 77 .acrb-search-wrapper .acrb-search-field label .acrb-search-icon { 77 color: var(--acrb-search-primary );78 color: var(--acrb-search-primary, #4f46e5); 78 79 } 79 80 … … 87 88 border-radius: 8px !important; 88 89 font-size: 13.5px !important; 89 color: var(--acrb-search-text ) !important;90 color: var(--acrb-search-text, #0f172a) !important; 90 91 background: #f8fafc !important; 91 92 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important; 92 transition: border-color 0.15s ease, background-color 0.15s ease !important;93 transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease !important; 93 94 font-family: inherit !important; 94 95 line-height: 40px !important; … … 99 100 appearance: none; 100 101 -webkit-appearance: none; 101 background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%3E%3Cpath%20fill%3D%22%2364748b%22%20d%3D%22M5.23%207.21a.75.75%200%20011.06.02L10%2011.168l3.71-3.938a.75.75%200%20111.08%201.04l-4.25%204.5a.75.75%200%2001-1.08%200l-4.25-4.5a.75.75%200%2001.02-1.06z%22%2F%3E%3C%2Fsvg%3E") ;102 background-repeat: no-repeat ;103 background-position: right 12px center ;104 background-size: 18px ;102 background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%3E%3Cpath%20fill%3D%22%2364748b%22%20d%3D%22M5.23%207.21a.75.75%200%20011.06.02L10%2011.168l3.71-3.938a.75.75%200%20111.08%201.04l-4.25%204.5a.75.75%200%2001-1.08%200l-4.25-4.5a.75.75%200%2001.02-1.06z%22%2F%3E%3C%2Fsvg%3E") !important; 103 background-repeat: no-repeat !important; 104 background-position: right 12px center !important; 105 background-size: 18px !important; 105 106 padding-right: 38px !important; 106 107 cursor: pointer; … … 116 117 .acrb-search-wrapper .acrb-search-input:focus { 117 118 background: #ffffff !important; 118 border-color: var(--acrb-search-primary ) !important;119 box-shadow: 0 0 0 3px rgba( 15, 23, 42, 0.08) !important;119 border-color: var(--acrb-search-primary, #4f46e5) !important; 120 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.12) !important; 120 121 } 121 122 … … 123 124 .acrb-search-wrapper .acrb-search-submit { 124 125 height: 42px; 125 background: var(--acrb-search-btn-bg );126 border: 1px solid var(--acrb-search-btn-bg );126 background: var(--acrb-search-btn-bg, #4f46e5); 127 border: 1px solid var(--acrb-search-btn-bg, #4f46e5); 127 128 color: #ffffff !important; 128 129 border-radius: 8px; … … 142 143 143 144 .acrb-search-wrapper .acrb-search-submit:hover { 144 background: var(--acrb-search-btn-hover); 145 border-color: var(--acrb-search-btn-hover); 146 opacity: 0.94; 145 background: var(--acrb-search-btn-hover, #4338ca); 146 border-color: var(--acrb-search-btn-hover, #4338ca); 147 147 transform: translateY(-1px); 148 } 149 150 .acrb-search-wrapper .acrb-search-submit:active { 151 transform: translateY(0); 148 152 } 149 153 … … 151 155 width: 15px; 152 156 height: 15px; 157 color: #ffffff; 153 158 } 154 159 … … 158 163 @media (max-width: 1024px) { 159 164 .acrb-search-wrapper .acrb-search-main { 160 grid-template-columns: 1fr 1fr;165 grid-template-columns: repeat(2, 1fr); 161 166 } 162 167 .acrb-search-wrapper .acrb-search-submit { -
awesome-car-rental/trunk/assets/css/frontend/single-car.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB SINGLE CAR DETAILS (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/single-car.css 3 4 ========================================================================== */ 4 5 … … 15 16 --acrb-single-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 16 17 17 font-family: var(--acrb-single-font );18 color: var(--acrb-single-text );18 font-family: var(--acrb-single-font, sans-serif); 19 color: var(--acrb-single-text, #0f172a); 19 20 box-sizing: border-box; 20 21 } 21 22 22 .acrb-main-container,23 23 .acrb-main-container *, 24 24 .acrb-main-container *::before, 25 25 .acrb-main-container *::after, 26 .acrb-redirect-notice,27 26 .acrb-redirect-notice *, 28 27 .acrb-redirect-notice *::before, 29 28 .acrb-redirect-notice *::after, 30 .acrb-alert-error,31 29 .acrb-alert-error *, 32 30 .acrb-alert-error *::before, 33 31 .acrb-alert-error *::after { 34 box-sizing: border-box;32 box-sizing: inherit; 35 33 } 36 34 … … 42 40 text-align: center; 43 41 font-size: 15px; 44 color: var(--acrb-single-secondary );42 color: var(--acrb-single-secondary, #64748b); 45 43 } 46 44 … … 61 59 -------------------------------------------------------------------------- */ 62 60 .acrb-main-container { 63 max-width: 1200px; 64 margin: 40px auto; 61 max-width: 1320px; 62 margin: 0 auto; 63 padding: 24px 16px 60px 16px; 65 64 } 66 65 … … 80 79 .acrb-flex-grid { 81 80 display: flex; 82 flex-wrap: wrap;81 align-items: flex-start; 83 82 gap: 36px; 84 align-items: flex-start;85 83 } 86 84 87 85 .acrb-content-left { 88 86 flex: 1; 89 min-width: 320px; 87 min-width: 0; 88 } 89 90 .acrb-sidebar-right { 91 width: 440px; 92 flex-shrink: 0; 93 position: sticky; 94 top: 24px; 90 95 } 91 96 … … 94 99 -------------------------------------------------------------------------- */ 95 100 .acrb-gallery-stage { 96 border-radius: 16px; 101 background: #ffffff; 102 border: 1px solid #e2e8f0; 103 border-radius: 20px; 97 104 overflow: hidden; 98 background: #f8fafc; 99 border: 1px solid #e2e8f0; 100 box-shadow: 0 10px 30px -5px rgba(15, 23, 42, 0.05); 105 box-shadow: 0 10px 30px -10px rgba(15, 23, 42, 0.08); 106 margin-bottom: 24px; 107 aspect-ratio: 16 / 10; 108 position: relative; 101 109 } 102 110 103 111 .acrb-gallery-stage img { 104 112 width: 100%; 105 height: 440px;113 height: 100%; 106 114 object-fit: cover; 107 115 display: block; 108 } 109 116 transition: opacity 0.25s ease; 117 } 118 119 .acrb-hero-placeholder { 120 width: 100%; 121 height: 100%; 122 display: flex; 123 flex-direction: column; 124 align-items: center; 125 justify-content: center; 126 background: #f8fafc; 127 color: #94a3b8; 128 gap: 8px; 129 } 130 131 .acrb-hero-placeholder svg { 132 width: 52px; 133 height: 52px; 134 } 135 136 /* Vehicle Header Block */ 110 137 .acrb-header-box { 111 margin- top: 24px;138 margin-bottom: 24px; 112 139 } 113 140 114 141 .acrb-vin-badge { 115 background: #eff6ff;116 display: inline-block;117 padding: 5px 14px;118 b order-radius: 9999px;119 font-size: 11.5px;120 font- weight: 800;121 color: var(--acrb-single-primary);122 margin-bottom: 12px;142 display: inline-flex; 143 align-items: center; 144 gap: 4px; 145 background: #f1f5f9; 146 color: #475569; 147 font-size: 0.75rem; 148 font-weight: 700; 149 letter-spacing: 0.05em; 123 150 text-transform: uppercase; 124 letter-spacing: 0.04em; 125 border: 1px solid #dbeafe; 151 padding: 4px 10px; 152 border-radius: 6px; 153 margin-bottom: 10px; 126 154 } 127 155 128 156 .acrb-car-title { 129 157 margin: 0; 130 font-size: 2 8px;131 font-weight: 900;132 color: var(--acrb-single-text);158 font-size: 2.2rem; 159 font-weight: 800; 160 line-height: 1.25; 133 161 letter-spacing: -0.02em; 162 color: var(--acrb-single-text, #0f172a); 134 163 } 135 164 … … 140 169 display: flex; 141 170 gap: 8px; 142 margin-top: 32px; 143 border-bottom: 1px solid #e2e8f0; 144 padding-bottom: 12px; 171 border-bottom: 2px solid #f1f5f9; 172 margin-bottom: 24px; 145 173 overflow-x: auto; 174 scrollbar-width: none; 175 } 176 177 .acrb-tabs-nav::-webkit-scrollbar { 178 display: none; 146 179 } 147 180 148 181 button.acrb-tab-btn { 149 background: #ffffff; 150 border: 1px solid #cbd5e1; 151 padding: 11px 20px; 182 background: transparent; 183 border: none; 184 padding: 12px 18px; 185 font-size: 0.95rem; 152 186 font-weight: 700; 153 font-size: 13.5px; 154 color: var(--acrb-single-secondary); 187 color: var(--acrb-single-secondary, #64748b); 155 188 cursor: pointer; 156 border-radius: 10px; 157 transition: all 0.15s ease; 189 border-bottom: 2px solid transparent; 190 margin-bottom: -2px; 191 transition: all 0.2s ease; 158 192 white-space: nowrap; 159 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02);160 193 font-family: inherit; 161 194 } 162 195 163 196 button.acrb-tab-btn:hover { 164 background: #f8fafc; 165 color: var(--acrb-single-text); 166 border-color: #94a3b8; 197 color: var(--acrb-single-primary, #4f46e5); 167 198 } 168 199 169 200 button.acrb-tab-btn.active { 170 background: #eff6ff; 171 color: var(--acrb-single-primary); 172 border-color: var(--acrb-single-primary); 173 box-shadow: 0 2px 6px rgba(79, 70, 229, 0.12); 201 color: var(--acrb-single-primary, #4f46e5); 202 border-bottom-color: var(--acrb-single-primary, #4f46e5); 174 203 } 175 204 176 205 .acrb-tab-pane { 177 206 display: none; 178 padding: 28px 0;207 animation: acrbFadeIn 0.2s ease-in-out; 179 208 } 180 209 181 210 .acrb-tab-pane.active { 182 211 display: block; 183 animation: acrbFade 0.25s ease; 184 } 185 186 @keyframes acrbFade { 187 from { 188 opacity: 0; 189 transform: translateY(4px); 190 } 191 to { 192 opacity: 1; 193 transform: translateY(0); 194 } 212 } 213 214 @keyframes acrbFadeIn { 215 from { opacity: 0; transform: translateY(4px); } 216 to { opacity: 1; transform: translateY(0); } 195 217 } 196 218 197 219 .acrb-description { 198 color: var(--acrb-single-secondary); 199 font-size: 15px; 220 font-size: 1rem; 200 221 line-height: 1.7; 201 } 202 222 color: #334155; 223 } 224 225 .acrb-description p { 226 margin-top: 0; 227 } 228 229 /* Specs Grid */ 203 230 .acrb-specs-heading { 231 font-size: 1.15rem; 232 font-weight: 800; 204 233 margin: 0 0 16px 0; 205 font-size: 12px; 206 font-weight: 900; 207 color: var(--acrb-single-secondary); 234 color: var(--acrb-single-secondary, #64748b); 208 235 text-transform: uppercase; 209 236 letter-spacing: 0.04em; 210 237 } 211 238 212 /* Specifications Grid */213 239 .acrb-spec-wrap { 214 240 display: grid; 215 grid-template-columns: repeat(auto-fi t, minmax(160px, 1fr));216 gap: 1 6px;241 grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); 242 gap: 14px; 217 243 margin-bottom: 32px; 218 244 } 219 245 220 246 .acrb-spec-node { 221 padding: 18px;222 247 background: #ffffff; 223 248 border: 1px solid #e2e8f0; 224 249 border-radius: 14px; 225 box-shadow: 0 2px 6px rgba(15, 23, 42, 0.02); 250 padding: 14px 16px; 251 display: flex; 252 flex-direction: column; 253 gap: 4px; 254 box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04); 226 255 } 227 256 228 257 .acrb-spec-icon-wrap { 229 color: var(--acrb-single-primary); 230 margin-bottom: 10px; 231 width: 38px; 232 height: 38px; 233 display: inline-flex; 258 width: 32px; 259 height: 32px; 260 border-radius: 8px; 261 background: #eef2ff; 262 color: var(--acrb-single-primary, #4f46e5); 263 display: flex; 234 264 align-items: center; 235 265 justify-content: center; 236 background: #eef2ff;237 border-radius: 10px; 238 } 239 240 .acrb-spec-icon-wrap .acrb-single-icon { 241 width: 18px;242 height: 18px;266 margin-bottom: 6px; 267 } 268 269 .acrb-spec-icon-wrap svg { 270 width: 16px; 271 height: 16px; 272 stroke-width: 2.2; 243 273 } 244 274 245 275 .acrb-spec-node-lbl { 246 font-size: 11px; 247 color: var(--acrb-single-secondary); 276 font-size: 0.74rem; 248 277 text-transform: uppercase; 249 font-weight: 800;250 letter-spacing: 0.04em;251 margin-bottom: 4px;278 font-weight: 700; 279 color: var(--acrb-single-secondary, #64748b); 280 letter-spacing: 0.05em; 252 281 } 253 282 254 283 .acrb-spec-node-val { 255 font-weight: 900; 256 color: var(--acrb-single-text); 257 font-size: 14px; 258 text-transform: capitalize; 284 font-size: 0.95rem; 285 font-weight: 700; 286 color: var(--acrb-single-text, #0f172a); 259 287 } 260 288 … … 262 290 .acrb-gallery-grid { 263 291 display: grid; 264 grid-template-columns: repeat(auto-fill, minmax(1 60px, 1fr));265 gap: 1 6px;292 grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); 293 gap: 12px; 266 294 } 267 295 268 296 .acrb-gallery-thumb-wrap { 297 aspect-ratio: 4 / 3; 269 298 border-radius: 12px; 270 299 overflow: hidden; 271 border: 1px solid #e2e8f0; 272 background: #f8fafc; 273 aspect-ratio: 16 / 10; 274 } 275 300 border: 2px solid #e2e8f0; 301 cursor: pointer; 302 transition: all 0.2s ease; 303 } 304 305 .acrb-gallery-thumb-wrap.is-active, 306 .acrb-gallery-thumb-wrap:hover { 307 border-color: var(--acrb-single-primary, #4f46e5); 308 transform: scale(1.03); 309 } 310 311 .acrb-gallery-thumb-wrap img, 276 312 .acrb-gallery-item { 277 313 width: 100%; 278 314 height: 100%; 279 315 object-fit: cover; 280 cursor: pointer;281 316 display: block; 282 transition: transform 0.2s ease; 283 } 284 285 .acrb-gallery-item:hover { 286 transform: scale(1.05); 287 } 288 289 /* Video Responsive Container */ 317 } 318 290 319 .acrb-video-container { 291 320 position: relative; … … 293 322 height: 0; 294 323 overflow: hidden; 295 border-radius: 14px; 296 background: #0f172a; 297 border: 1px solid #e2e8f0; 324 border-radius: 16px; 298 325 } 299 326 … … 313 340 background: #f8fafc; 314 341 border-radius: 14px; 315 color: var(--acrb-single-secondary );342 color: var(--acrb-single-secondary, #64748b); 316 343 border: 1px dashed #cbd5e1; 317 344 } 318 345 319 .acrb-hero-placeholder {320 height: 440px;321 display: flex;322 flex-direction: column;323 align-items: center;324 justify-content: center;325 }326 327 .acrb-empty-box .acrb-single-icon {328 width: 40px;329 height: 40px;330 color: #94a3b8;331 margin-bottom: 12px;332 }333 334 346 .acrb-empty-msg { 335 color: var(--acrb-single-secondary );347 color: var(--acrb-single-secondary, #64748b); 336 348 font-style: italic; 337 349 } … … 340 352 Booking Sidebar Card & Forms 341 353 -------------------------------------------------------------------------- */ 342 .acrb-sidebar-right {343 width: 440px;344 min-width: 320px;345 }346 347 354 .acrb-booking-card { 348 padding: 32px;355 background: #ffffff; 349 356 border: 1px solid #e2e8f0; 350 border-radius: 2 0px;351 background: #ffffff;352 box-shadow: 0 10px 30px -5px rgba(15, 23, 42, 0.06);357 border-radius: 24px; 358 padding: 28px; 359 box-shadow: 0 20px 40px -15px rgba(15, 23, 42, 0.1), 0 1px 3px rgba(15, 23, 42, 0.04); 353 360 } 354 361 355 362 .acrb-price-hero { 356 margin-bottom: 24px; 363 display: flex; 364 align-items: baseline; 365 gap: 4px; 366 margin-bottom: 22px; 367 padding-bottom: 18px; 357 368 border-bottom: 1px solid #f1f5f9; 358 padding-bottom: 18px;359 display: flex;360 align-items: baseline;361 gap: 6px;362 369 } 363 370 364 371 .acrb-price-amount { 365 font-size: 32px;372 font-size: 2.1rem; 366 373 font-weight: 900; 367 color: var(--acrb-single-text );374 color: var(--acrb-single-text, #0f172a); 368 375 letter-spacing: -0.02em; 369 376 } 370 377 371 378 .acrb-price-unit { 372 color: var(--acrb-single-secondary); 373 font-size: 13.5px; 374 font-weight: 700; 375 } 376 379 font-size: 0.95rem; 380 font-weight: 600; 381 color: var(--acrb-single-secondary, #64748b); 382 } 383 384 /* Inputs & Form Rows */ 377 385 .acrb-form-row { 378 386 display: flex; 379 gap: 1 0px;380 margin-bottom: 1 6px;387 gap: 12px; 388 margin-bottom: 14px; 381 389 } 382 390 … … 389 397 } 390 398 399 .acrb-locations-row { 400 display: flex; 401 gap: 12px; 402 margin-bottom: 18px; 403 } 404 391 405 .acrb-form-col-half { 392 406 flex: 1; 393 407 } 394 408 395 .acrb-locations-row {396 display: flex;397 gap: 12px;398 margin-bottom: 16px;399 }400 401 409 .acrb-label { 402 410 display: block; 411 font-size: 0.75rem; 412 text-transform: uppercase; 413 font-weight: 700; 414 letter-spacing: 0.05em; 415 color: var(--acrb-single-text, #0f172a); 403 416 margin-bottom: 6px; 404 font-size: 13px;405 font-weight: 800;406 color: var(--acrb-single-text);407 417 } 408 418 409 419 .acrb-input { 410 420 width: 100% !important; 411 height: 44px !important; 412 padding: 0 14px !important; 413 border: 1.5px solid #cbd5e1 !important; 421 height: 42px !important; 422 padding: 8px 12px !important; 423 background: #f8fafc !important; 424 border: 1px solid #e2e8f0 !important; 414 425 border-radius: 10px !important; 415 font-size: 13.5px !important; 416 color: var(--acrb-single-text) !important; 417 background: #f8fafc !important; 418 box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important; 419 transition: border-color 0.15s ease, background-color 0.15s ease !important; 426 font-size: 0.88rem !important; 427 font-weight: 600 !important; 428 color: var(--acrb-single-text, #0f172a) !important; 429 transition: all 0.2s ease !important; 420 430 font-family: inherit !important; 421 line-height: 42px !important;422 431 outline: none !important; 423 432 } … … 430 439 .acrb-input:focus { 431 440 background: #ffffff !important; 432 border-color: var(--acrb-single-primary ) !important;433 box-shadow: 0 0 0 3px rgba( 15, 23, 42, 0.08) !important;441 border-color: var(--acrb-single-primary, #4f46e5) !important; 442 box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.12) !important; 434 443 } 435 444 … … 439 448 background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%3E%3Cpath%20fill%3D%22%2364748b%22%20d%3D%22M5.23%207.21a.75.75%200%20011.06.02L10%2011.168l3.71-3.938a.75.75%200%20111.08%201.04l-4.25%204.5a.75.75%200%2001-1.08%200l-4.25-4.5a.75.75%200%2001.02-1.06z%22%2F%3E%3C%2Fsvg%3E"); 440 449 background-repeat: no-repeat; 441 background-position: right 1 4px center;450 background-position: right 12px center; 442 451 background-size: 18px; 443 padding-right: 40px !important;452 padding-right: 38px !important; 444 453 cursor: pointer; 445 454 } … … 449 458 -------------------------------------------------------------------------- */ 450 459 .acrb-luxury-options-group { 451 margin : 22px 0;460 margin-bottom: 18px; 452 461 } 453 462 454 463 .acrb-group-title { 455 font-size: 11.5px; 456 font-weight: 900; 457 color: var(--acrb-single-secondary); 464 font-size: 0.78rem; 465 font-weight: 800; 458 466 text-transform: uppercase; 459 letter-spacing: 0.06em; 467 letter-spacing: 0.05em; 468 color: var(--acrb-single-secondary, #64748b); 460 469 margin-bottom: 10px; 461 470 } … … 465 474 align-items: center; 466 475 justify-content: space-between; 467 padding: 14px 16px;476 background: #f8fafc; 468 477 border: 1.5px solid #e2e8f0; 469 478 border-radius: 12px; 470 background: #ffffff; 479 padding: 10px 14px; 480 margin-bottom: 8px; 471 481 cursor: pointer; 472 transition: all 0.15s ease; 473 margin-bottom: 8px; 482 transition: all 0.2s ease; 474 483 } 475 484 476 485 .acrb-luxury-card:hover { 477 border-color: # 94a3b8;478 background: #f 8fafc;486 border-color: #cbd5e1; 487 background: #f1f5f9; 479 488 } 480 489 481 490 .acrb-luxury-card.selected { 482 border-color: var(--acrb-single-primary);483 491 background: #eef2ff; 492 border-color: var(--acrb-single-primary, #4f46e5); 484 493 } 485 494 … … 487 496 display: flex; 488 497 align-items: center; 489 gap: 1 2px;490 font-size: 13.5px;491 font-weight: 700;492 color: # 334155;498 gap: 10px; 499 font-size: 0.85rem; 500 font-weight: 600; 501 color: #0f172a; 493 502 } 494 503 495 504 .acrb-luxury-card input[type="radio"] { 496 accent-color: var(--acrb-single-primary );505 accent-color: var(--acrb-single-primary, #4f46e5); 497 506 width: 17px; 498 507 height: 17px; … … 501 510 502 511 .acrb-luxury-price { 503 font-size: 13px;504 font-weight: 900;505 color: var(--acrb-single-primary );512 font-size: 0.82rem; 513 font-weight: 800; 514 color: var(--acrb-single-primary, #4f46e5); 506 515 } 507 516 … … 511 520 .acrb-breakdown-card { 512 521 background: #f8fafc; 513 border: 1.5px solid #e2e8f0; 514 border-radius: 16px; 515 padding: 24px; 516 margin: 24px 0; 517 display: flex; 518 flex-direction: column; 519 gap: 14px; 522 border: 1px solid #e2e8f0; 523 border-radius: 14px; 524 padding: 16px; 525 margin-bottom: 20px; 520 526 box-shadow: 0 4px 16px -4px rgba(15, 23, 42, 0.04); 521 527 } 522 528 523 529 .acrb-breakdown-header { 524 font-size: 12px; 525 font-weight: 900; 526 color: var(--acrb-single-secondary); 530 display: flex; 531 align-items: center; 532 gap: 8px; 533 font-size: 0.82rem; 534 font-weight: 800; 527 535 text-transform: uppercase; 528 letter-spacing: 0.06em; 536 letter-spacing: 0.05em; 537 color: var(--acrb-single-secondary, #64748b); 538 padding-bottom: 10px; 539 margin-bottom: 12px; 529 540 border-bottom: 1px solid #e2e8f0; 530 padding-bottom: 10px; 531 display: flex; 532 align-items: center; 533 gap: 8px; 534 } 535 536 .acrb-breakdown-header .acrb-single-icon { 537 color: var(--acrb-single-primary); 541 } 542 543 .acrb-breakdown-header svg { 538 544 width: 16px; 539 545 height: 16px; 546 color: var(--acrb-single-primary, #4f46e5); 540 547 } 541 548 … … 543 550 display: flex; 544 551 justify-content: space-between; 545 align-items: flex-start; 546 font-size: 13.5px; 552 align-items: center; 553 margin-bottom: 10px; 554 font-size: 0.88rem; 547 555 color: #334155; 548 556 padding-bottom: 10px; … … 561 569 .acrb-bd-label { 562 570 display: flex; 563 align-items: flex-start;564 gap: 10px;565 font-weight: 700;571 align-items: center; 572 gap: 8px; 573 font-weight: 600; 566 574 } 567 575 … … 571 579 border-radius: 8px; 572 580 background: #eef2ff; 573 color: var(--acrb-single-primary );581 color: var(--acrb-single-primary, #4f46e5); 574 582 display: flex; 575 583 align-items: center; 576 584 justify-content: center; 585 font-size: 1rem; 577 586 flex-shrink: 0; 578 font-size: 14px; 587 } 588 589 .acrb-bd-label span { 590 display: block; 591 font-weight: 600; 592 color: #0f172a; 593 line-height: 1.2; 579 594 } 580 595 581 596 .acrb-bd-sub { 582 display: block; 583 font-size: 11.5px; 584 color: var(--acrb-single-secondary); 585 font-weight: 500; 586 margin-top: 2px; 597 font-size: 0.74rem; 598 color: var(--acrb-single-secondary, #64748b); 599 font-weight: normal; 587 600 } 588 601 589 602 .acrb-bd-val { 603 font-weight: 800; 604 color: var(--acrb-single-text, #0f172a); 605 white-space: nowrap; 606 } 607 608 .acrb-breakdown-total { 609 display: flex; 610 justify-content: space-between; 611 align-items: baseline; 612 padding-top: 12px; 613 margin-top: 10px; 614 border-top: 1px dashed #cbd5e1; 615 font-weight: 800; 616 font-size: 1rem; 617 color: var(--acrb-single-text, #0f172a); 618 } 619 620 .acrb-total-accent { 621 font-size: 1.4rem; 590 622 font-weight: 900; 591 color: var(--acrb-single-text); 592 } 593 594 .acrb-breakdown-total { 595 display: flex; 596 justify-content: space-between; 597 align-items: center; 598 border-top: 2px dashed #cbd5e1; 599 padding-top: 16px; 600 margin-top: 6px; 601 font-weight: 900; 602 color: var(--acrb-single-text); 603 font-size: 19px; 604 } 605 606 .acrb-total-accent { 607 color: var(--acrb-single-primary); 608 } 609 610 /* Submit Action Button */ 611 button.acrb-submit-btn { 623 color: var(--acrb-single-primary, #4f46e5); 624 } 625 626 /* Error notification */ 627 .acrb-calc-error { 628 display: none; 629 background: #fef2f2; 630 border: 1px solid #fecaca; 631 color: #dc2626; 632 font-size: 0.8rem; 633 font-weight: 600; 634 border-radius: 8px; 635 padding: 8px 12px; 636 margin-bottom: 12px; 637 } 638 639 /* Submit Button */ 640 button.acrb-submit-btn, 641 .acrb-submit-btn { 612 642 width: 100%; 613 height: 50px; 614 background: var(--acrb-single-btn-bg); 615 border: 1px solid var(--acrb-single-btn-bg); 643 height: 48px; 644 background: var(--acrb-single-btn-bg, #4f46e5); 616 645 color: #ffffff; 617 border-radius: 10px; 646 border: none; 647 border-radius: 12px; 648 font-size: 0.95rem; 618 649 font-weight: 800; 619 font-size: 14.5px; 650 display: flex; 651 align-items: center; 652 justify-content: center; 653 gap: 8px; 620 654 cursor: pointer; 621 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.3); 622 transition: all 0.15s ease; 623 display: inline-flex; 624 align-items: center; 625 justify-content: center; 626 gap: 10px; 655 transition: all 0.2s ease; 656 box-shadow: 0 4px 14px rgba(79, 70, 229, 0.25); 627 657 font-family: inherit; 628 658 } 629 659 630 button.acrb-submit-btn:hover { 631 background: var(--acrb-single-btn-hover); 632 border-color: var(--acrb-single-btn-hover); 633 opacity: 0.94; 660 button.acrb-submit-btn:hover, 661 .acrb-submit-btn:hover { 662 background: var(--acrb-single-btn-hover, #4338ca); 634 663 transform: translateY(-1px); 635 } 636 637 button.acrb-submit-icon { 664 box-shadow: 0 6px 18px rgba(79, 70, 229, 0.35); 665 } 666 667 button.acrb-submit-btn:disabled, 668 .acrb-submit-btn:disabled { 669 opacity: 0.5; 670 cursor: not-allowed; 671 transform: none !important; 672 box-shadow: none !important; 673 } 674 675 .acrb-submit-icon { 638 676 width: 18px; 639 677 height: 18px; 678 stroke-width: 2.2; 640 679 } 641 680 … … 643 682 Responsive Breakpoints 644 683 -------------------------------------------------------------------------- */ 645 @media (max-width: 900px) { 646 .acrb-sidebar-right, 647 .acrb-content-left { 648 width: 100% !important; 649 min-width: 100% !important; 684 @media (max-width: 1080px) { 685 .acrb-flex-grid { 686 flex-direction: column; 650 687 } 651 } 688 .acrb-sidebar-right { 689 width: 100%; 690 position: static; 691 } 692 } 693 694 @media (max-width: 640px) { 695 .acrb-form-row, 696 .acrb-locations-row { 697 flex-direction: column; 698 gap: 10px; 699 } 700 .acrb-car-title { 701 font-size: 1.7rem; 702 } 703 } -
awesome-car-rental/trunk/assets/css/frontend/thanks.css
r3775773 r3777386 1 1 /* ========================================================================== 2 2 ACRB THANK YOU & CONFIRMATION COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS) 3 Location: assets/css/frontend/thanks.css 3 4 ========================================================================== */ 4 5 … … 14 15 --acrb-thanks-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif; 15 16 16 font-family: var(--acrb-thanks-font );17 color: var(--acrb-thanks-text );17 font-family: var(--acrb-thanks-font, sans-serif); 18 color: var(--acrb-thanks-text, #0f172a); 18 19 box-sizing: border-box; 19 20 } 20 21 21 .acrb-thanks-wrapper,22 22 .acrb-thanks-wrapper *, 23 23 .acrb-thanks-wrapper *::before, 24 24 .acrb-thanks-wrapper *::after, 25 .acrb-error-container,26 25 .acrb-error-container *, 27 26 .acrb-error-container *::before, 28 27 .acrb-error-container *::after { 29 box-sizing: border-box;28 box-sizing: inherit; 30 29 } 31 30 … … 45 44 46 45 .acrb-error-container h3 { 47 color: var(--acrb-thanks-text );46 color: var(--acrb-thanks-text, #0f172a); 48 47 font-size: 24px; 49 48 font-weight: 900; … … 53 52 54 53 .acrb-error-container p { 55 color: var(--acrb-thanks-secondary );54 color: var(--acrb-thanks-secondary, #64748b); 56 55 font-size: 14.5px; 57 56 margin: 0 0 32px; … … 59 58 } 60 59 61 .acrb- btn-home {60 .acrb-error-container .acrb-btn-home { 62 61 display: inline-flex; 63 62 align-items: center; 64 63 gap: 10px; 65 64 text-decoration: none !important; 66 background: var(--acrb-thanks-btn-bg );67 border: 1px solid var(--acrb-thanks-btn-bg );65 background: var(--acrb-thanks-btn-bg, #4f46e5); 66 border: 1px solid var(--acrb-thanks-btn-bg, #4f46e5); 68 67 color: #ffffff !important; 69 68 padding: 14px 28px; … … 75 74 } 76 75 77 .acrb- btn-home:hover {78 background: var(--acrb-thanks-btn-hover );79 border-color: var(--acrb-thanks-btn-hover );76 .acrb-error-container .acrb-btn-home:hover { 77 background: var(--acrb-thanks-btn-hover, #4338ca); 78 border-color: var(--acrb-thanks-btn-hover, #4338ca); 80 79 opacity: 0.94; 81 80 transform: translateY(-1px); … … 83 82 84 83 /* -------------------------------------------------------------------------- 85 Confirmation Main C ard84 Confirmation Main Container & Stepper 86 85 -------------------------------------------------------------------------- */ 87 86 .acrb-thanks-wrapper { 88 87 max-width: 860px; 89 margin: 60px auto; 90 } 91 88 margin: 40px auto 80px auto; 89 padding: 0 16px; 90 } 91 92 .acrb-checkout-steps { 93 display: flex; 94 align-items: center; 95 justify-content: center; 96 gap: 12px; 97 margin-bottom: 32px; 98 flex-wrap: wrap; 99 background: #ffffff; 100 border: 1px solid #e2e8f0; 101 border-radius: 16px; 102 padding: 16px 24px; 103 box-shadow: 0 4px 15px rgba(15, 23, 42, 0.03); 104 } 105 106 .acrb-step-item { 107 display: flex; 108 align-items: center; 109 gap: 10px; 110 font-size: 0.88rem; 111 font-weight: 700; 112 color: #94a3b8; 113 position: relative; 114 } 115 116 .acrb-step-item:not(:last-child):after { 117 content: ''; 118 display: inline-block; 119 width: 24px; 120 height: 1px; 121 background: #e2e8f0; 122 margin-left: 12px; 123 } 124 125 .acrb-step-item.active { 126 color: var(--acrb-thanks-primary, #4f46e5); 127 } 128 129 .acrb-step-item.completed { 130 color: #059669; 131 } 132 133 .acrb-step-num { 134 width: 30px; 135 height: 30px; 136 border-radius: 50%; 137 background: #f1f5f9; 138 color: #64748b; 139 display: flex; 140 align-items: center; 141 justify-content: center; 142 font-size: 0.82rem; 143 font-weight: 800; 144 flex-shrink: 0; 145 } 146 147 .acrb-step-item.active .acrb-step-num { 148 background: var(--acrb-thanks-primary, #4f46e5); 149 color: #ffffff; 150 box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3); 151 } 152 153 .acrb-step-item.completed .acrb-step-num { 154 background: #dcfce7; 155 color: #059669; 156 } 157 158 /* -------------------------------------------------------------------------- 159 Confirmation Main Card & Header 160 -------------------------------------------------------------------------- */ 92 161 .acrb-thanks-card { 93 padding: 56px;162 padding: 48px 56px; 94 163 border: 1px solid #e2e8f0; 95 164 border-radius: 24px; … … 98 167 } 99 168 169 .acrb-thanks-header { 170 text-align: center; 171 margin-bottom: 40px; 172 } 173 174 .acrb-success-icon { 175 width: 80px; 176 height: 80px; 177 border-radius: 50%; 178 background: #ecfdf5; 179 color: var(--acrb-thanks-accent, #059669); 180 display: flex; 181 align-items: center; 182 justify-content: center; 183 margin: 0 auto 20px auto; 184 border: 1px solid #a7f3d0; 185 box-shadow: 0 8px 24px rgba(5, 150, 105, 0.12); 186 } 187 100 188 .acrb-thanks-icon { 101 189 display: inline-block; 102 width: 18px;103 height: 18px;190 width: 32px; 191 height: 32px; 104 192 stroke-width: 2.2; 105 193 stroke: currentColor; … … 111 199 } 112 200 113 .acrb-thanks-header {114 text-align: center;115 margin-bottom: 40px;116 }117 118 .acrb-success-icon {119 color: var(--acrb-thanks-accent);120 margin-bottom: 20px;121 display: inline-flex;122 align-items: center;123 justify-content: center;124 width: 80px;125 height: 80px;126 background: #ecfdf5;127 border-radius: 50%;128 border: 1px solid #a7f3d0;129 box-shadow: 0 8px 24px rgba(5, 150, 105, 0.12);130 }131 132 201 .acrb-success-icon .acrb-thanks-icon { 133 202 width: 40px; … … 138 207 font-size: 32px; 139 208 font-weight: 900; 140 color: var(--acrb-thanks-text );209 color: var(--acrb-thanks-text, #0f172a); 141 210 margin: 0 0 10px 0; 142 211 letter-spacing: -0.03em; … … 144 213 145 214 .acrb-thanks-sub { 146 color: var(--acrb-thanks-secondary );215 color: var(--acrb-thanks-secondary, #64748b); 147 216 font-size: 15px; 148 margin: 0 ;217 margin: 0 0 14px 0; 149 218 line-height: 1.6; 150 219 } 151 220 152 221 .acrb-thanks-sub strong { 153 color: var(--acrb-thanks-text );222 color: var(--acrb-thanks-text, #0f172a); 154 223 } 155 224 … … 158 227 align-items: center; 159 228 gap: 8px; 160 margin-top: 20px;229 margin-top: 4px; 161 230 padding: 8px 16px; 162 231 background: #fffbeb; … … 175 244 .acrb-summary-box { 176 245 background: #f8fafc; 246 border: 1px solid #e2e8f0; 247 border-radius: 18px; 177 248 padding: 32px; 178 border-radius: 18px;179 249 margin-bottom: 28px; 180 border: 1px solid #e2e8f0;181 250 } 182 251 … … 185 254 font-size: 12.5px; 186 255 font-weight: 900; 187 color: var(--acrb-thanks-secondary);188 256 text-transform: uppercase; 189 257 letter-spacing: 0.06em; 258 color: var(--acrb-thanks-secondary, #64748b); 190 259 border-bottom: 1px solid #e2e8f0; 191 260 padding-bottom: 12px; … … 214 283 font-size: 11px; 215 284 font-weight: 800; 216 color: var(--acrb-thanks-secondary);217 285 text-transform: uppercase; 218 286 letter-spacing: 0.04em; 287 color: var(--acrb-thanks-secondary, #64748b); 219 288 } 220 289 … … 222 291 font-size: 14.5px; 223 292 font-weight: 900; 224 color: var(--acrb-thanks-text );293 color: var(--acrb-thanks-text, #0f172a); 225 294 } 226 295 227 296 .acrb-val-primary { 228 color: var(--acrb-thanks-primary); 297 color: var(--acrb-thanks-primary, #4f46e5); 298 font-size: 1.1rem; 229 299 } 230 300 231 301 .acrb-val-contact { 232 302 font-size: 13px; 303 line-height: 1.4; 233 304 } 234 305 235 306 .acrb-val-contact-sub { 236 color: var(--acrb-thanks-secondary); 307 font-size: 11.5px; 308 color: var(--acrb-thanks-secondary, #64748b); 237 309 font-weight: 600; 310 display: inline-block; 311 margin-top: 2px; 238 312 } 239 313 … … 242 316 } 243 317 318 .acrb-item-sub { 319 display: block; 320 font-size: 11.5px; 321 color: var(--acrb-thanks-secondary, #64748b); 322 font-weight: 500; 323 margin-top: 3px; 324 } 325 244 326 /* -------------------------------------------------------------------------- 245 327 Financial Breakdown Table 246 328 -------------------------------------------------------------------------- */ 247 329 .acrb-table-container { 330 width: 100%; 331 overflow-x: auto; 248 332 background: #ffffff; 249 333 border: 1px solid #e2e8f0; 250 334 border-radius: 14px; 251 overflow: hidden;335 margin-bottom: 20px; 252 336 box-shadow: 0 2px 8px rgba(15, 23, 42, 0.02); 253 337 } … … 256 340 width: 100%; 257 341 border-collapse: collapse; 258 } 259 260 .acrb-breakdown-table thead th { 342 text-align: left; 343 } 344 345 .acrb-breakdown-table th { 261 346 background: #f1f5f9; 262 color: var(--acrb-thanks-secondary );347 color: var(--acrb-thanks-secondary, #64748b); 263 348 font-size: 11px; 264 349 font-weight: 900; … … 266 351 letter-spacing: 0.05em; 267 352 padding: 12px 18px; 268 text-align: left;269 } 270 271 .acrb-breakdown-table th ead th:last-child {353 border-bottom: 1px solid #e2e8f0; 354 } 355 356 .acrb-breakdown-table th:last-child { 272 357 text-align: right; 273 358 } 274 359 275 .acrb-breakdown-table t r td {360 .acrb-breakdown-table td { 276 361 padding: 16px 18px; 277 362 border-bottom: 1px solid #f1f5f9; 363 vertical-align: middle; 364 color: #334155; 278 365 font-size: 13.5px; 279 color: #334155;280 366 font-weight: 600; 281 vertical-align: middle; 282 } 283 284 .acrb-breakdown-table tr:last-child td { 367 } 368 369 .acrb-breakdown-table tbody tr:last-child td { 285 370 border-bottom: none; 286 371 } 287 372 288 .acrb-breakdown-table t r td:last-child {373 .acrb-breakdown-table td:last-child { 289 374 text-align: right; 290 375 font-weight: 900; 291 color: var(--acrb-thanks-text );376 color: var(--acrb-thanks-text, #0f172a); 292 377 } 293 378 … … 295 380 display: flex; 296 381 align-items: center; 297 gap: 1 0px;382 gap: 12px; 298 383 } 299 384 300 385 .acrb-table-item-badge { 301 width: 28px;302 height: 28px;303 border-radius: 8px;386 width: 32px; 387 height: 32px; 388 border-radius: 10px; 304 389 background: #eef2ff; 305 color: var(--acrb-thanks-primary );390 color: var(--acrb-thanks-primary, #4f46e5); 306 391 display: flex; 307 392 align-items: center; 308 393 justify-content: center; 309 font-size: 1 3px;394 font-size: 14px; 310 395 flex-shrink: 0; 311 396 } … … 313 398 .acrb-table-item-badge.promo-badge { 314 399 background: #ecfdf5; 315 color: #059669;400 color: var(--acrb-thanks-accent, #059669); 316 401 } 317 402 318 403 .acrb-item-name { 319 font-weight: 800; 320 color: var(--acrb-thanks-text); 321 } 322 404 display: block; 405 font-weight: 800; 406 color: var(--acrb-thanks-text, #0f172a); 407 } 408 409 .promo-title, 323 410 .acrb-item-name.promo-title { 324 color: var(--acrb-thanks-accent); 325 } 326 327 .acrb-item-sub { 328 display: block; 329 font-size: 11.5px; 330 color: var(--acrb-thanks-secondary); 331 font-weight: 500; 332 margin-top: 3px; 411 color: var(--acrb-thanks-accent, #059669); 333 412 } 334 413 335 414 .acrb-val-included { 336 color: var(--acrb-thanks-primary); 415 color: var(--acrb-thanks-primary, #4f46e5) !important; 416 font-weight: 700; 337 417 } 338 418 339 419 .acrb-val-applied { 340 color: var(--acrb-thanks-accent );341 font-weight: 900; 342 } 343 344 /* Total Bar */420 color: var(--acrb-thanks-accent, #059669) !important; 421 font-weight: 900; 422 } 423 424 /* Receipt Total Bar */ 345 425 .acrb-receipt-total-bar { 426 display: flex; 427 justify-content: space-between; 428 align-items: center; 346 429 background: #ffffff; 347 430 border: 1.5px solid #cbd5e1; 431 border-radius: 14px; 348 432 padding: 20px 24px; 349 border-radius: 14px;350 display: flex;351 justify-content: space-between;352 align-items: center;353 margin-top: 20px;354 433 box-shadow: 0 4px 12px rgba(15, 23, 42, 0.02); 355 434 } … … 358 437 display: flex; 359 438 align-items: center; 360 gap: 1 0px;439 gap: 12px; 361 440 } 362 441 … … 364 443 font-size: 16px; 365 444 font-weight: 900; 366 color: var(--acrb-thanks-text );445 color: var(--acrb-thanks-text, #0f172a); 367 446 } 368 447 … … 370 449 font-size: 12px; 371 450 font-weight: 800; 372 color: var(--acrb-thanks-secondary );451 color: var(--acrb-thanks-secondary, #64748b); 373 452 background: #f1f5f9; 374 453 padding: 4px 10px; … … 380 459 font-size: 26px; 381 460 font-weight: 900; 382 color: var(--acrb-thanks-primary );461 color: var(--acrb-thanks-primary, #4f46e5); 383 462 letter-spacing: -0.02em; 384 463 } … … 389 468 .acrb-thanks-footer { 390 469 text-align: center; 470 margin-top: 40px; 391 471 } 392 472 393 473 .acrb-footer-desc { 394 474 font-size: 13.5px; 395 color: var(--acrb-thanks-secondary); 396 margin: 0 0 24px 0; 475 color: var(--acrb-thanks-secondary, #64748b); 476 max-width: 650px; 477 margin: 0 auto 24px auto; 397 478 line-height: 1.6; 398 479 } … … 403 484 gap: 14px; 404 485 flex-wrap: wrap; 405 } 406 407 button.acrb-btn-action { 408 cursor: pointer; 486 margin-bottom: 16px; 487 } 488 489 button.acrb-btn-action, 490 .acrb-btn-action { 491 display: inline-flex; 492 align-items: center; 493 gap: 8px; 409 494 background: #ffffff; 410 495 border: 1.5px solid #cbd5e1; 411 color: var(--acrb-thanks-text );496 color: var(--acrb-thanks-text, #0f172a); 412 497 padding: 12px 24px; 413 498 border-radius: 12px; 414 font-weight: 800;415 499 font-size: 13.5px; 416 display: inline-flex;417 align-items: center;418 gap: 8px;500 font-weight: 800; 501 cursor: pointer; 502 text-decoration: none !important; 419 503 transition: all 0.15s ease; 420 text-decoration: none !important;421 504 font-family: inherit; 422 505 } 423 506 424 button.acrb-btn-action:hover { 507 button.acrb-btn-action:hover, 508 .acrb-btn-action:hover { 425 509 background: #f8fafc; 426 border-color: var(--acrb-thanks-primary );427 color: var(--acrb-thanks-primary );510 border-color: var(--acrb-thanks-primary, #4f46e5); 511 color: var(--acrb-thanks-primary, #4f46e5); 428 512 transform: translateY(-1px); 429 513 } 430 514 431 515 .acrb-btn-action.primary { 432 background: var(--acrb-thanks-btn-bg );433 border-color: var(--acrb-thanks-btn-bg );516 background: var(--acrb-thanks-btn-bg, #4f46e5); 517 border-color: var(--acrb-thanks-btn-bg, #4f46e5); 434 518 color: #ffffff !important; 435 519 box-shadow: 0 8px 20px -4px rgba(79, 70, 229, 0.35); … … 437 521 438 522 .acrb-btn-action.primary:hover { 439 background: var(--acrb-thanks-btn-hover );440 border-color: var(--acrb-thanks-btn-hover );523 background: var(--acrb-thanks-btn-hover, #4338ca); 524 border-color: var(--acrb-thanks-btn-hover, #4338ca); 441 525 opacity: 0.94; 442 526 transform: translateY(-1px); 527 color: #ffffff !important; 443 528 } 444 529 445 530 .acrb-support-link { 446 margin-top: 24px;447 531 font-size: 13px; 448 color: var(--acrb-thanks-secondary );532 color: var(--acrb-thanks-secondary, #64748b); 449 533 font-weight: 600; 534 margin: 0; 450 535 } 451 536 452 537 .acrb-support-link a { 453 color: var(--acrb-thanks-primary); 538 color: var(--acrb-thanks-primary, #4f46e5); 539 font-weight: 800; 454 540 text-decoration: none; 455 font-weight: 800;456 541 } 457 542 … … 463 548 Responsive Breakpoints 464 549 -------------------------------------------------------------------------- */ 465 @media (max-width: 640px) {550 @media (max-width: 768px) { 466 551 .acrb-thanks-wrapper { 467 margin: 20px; 552 margin: 20px auto; 553 } 554 .acrb-receipt-grid { 555 grid-template-columns: 1fr; 468 556 } 469 557 .acrb-thanks-card { 470 558 padding: 32px 20px; 471 559 } 472 .acrb-receipt-grid { 473 grid-template-columns: 1fr; 474 } 475 } 476 477 /* -------------------------------------------------------------------------- 478 Print Stylesheet 560 .acrb-receipt-total-bar { 561 flex-direction: column; 562 align-items: flex-start; 563 gap: 12px; 564 } 565 .acrb-receipt-total-val { 566 font-size: 1.8rem; 567 } 568 } 569 570 /* -------------------------------------------------------------------------- 571 Print Styling 479 572 -------------------------------------------------------------------------- */ 480 573 @media print { … … 492 585 width: 100%; 493 586 margin: 0; 587 padding: 0; 494 588 } 495 589 .acrb-thanks-card { 496 box-shadow: none; 497 border: none; 498 padding: 20px; 499 } 590 border: none !important; 591 box-shadow: none !important; 592 padding: 20px !important; 593 } 594 .acrb-checkout-steps, 500 595 .acrb-action-buttons, 501 .acrb-support-link { 596 .acrb-support-link, 597 header, 598 footer { 502 599 display: none !important; 503 600 } -
awesome-car-rental/trunk/awesome-car-rental.php
r3775773 r3777386 3 3 * Plugin Name: Awesome Car Rental & Booking 4 4 * Description: Core functionality for the Car Rental System (Custom Database Architecture, Admin UI, and Logic). 5 * Version: 1.2 5 * Version: 1.2.1 6 6 * Author: Abdullah Nahian 7 7 * Author URI: https://devnahian.com -
awesome-car-rental/trunk/frontend/account/acrb-frontned-account.php
r3775773 r3777386 39 39 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 40 40 41 // Scoped CSS property string injected directly into container style attributes (No :root needed) 42 $scoped_styles = sprintf( 43 '--acrb-portal-primary:%s;--acrb-portal-secondary:%s;--acrb-portal-text:%s;--acrb-portal-accent:%s;--acrb-portal-font:%s;--acrb-btn-bg:%s;--acrb-btn-hover:%s;', 41 // Inject dynamic CSS custom properties via wp_add_inline_style 42 $custom_css = sprintf( 43 '.acrb-acc-wrapper, .acrb-auth-locked, #acrb-receipt-modal { 44 --acrb-portal-primary: %s; 45 --acrb-portal-secondary: %s; 46 --acrb-portal-text: %s; 47 --acrb-portal-accent: %s; 48 --acrb-portal-font: %s; 49 --acrb-btn-bg: %s; 50 --acrb-btn-hover: %s; 51 }', 44 52 esc_attr( $primary_color ), 45 53 esc_attr( $secondary_color ), … … 50 58 esc_attr( $btn_hover_color ) 51 59 ); 60 wp_add_inline_style( 'acrb-account-style', $custom_css ); 52 61 53 62 // 3. Auth Check & Lock Screen … … 56 65 ob_start(); 57 66 ?> 58 <div class="acrb-auth-locked" style="<?php echo esc_attr( $scoped_styles ); ?>">67 <div class="acrb-auth-locked"> 59 68 <div class="acrb-auth-locked-icon"> 60 69 <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> … … 80 89 81 90 // 4. Currency Configuration 82 $currency_symbol = get_option( 'acrb_currency', '£' );83 $currency_pos = get_option( 'acrb_currency_pos', 'left' );91 $currency_symbol = (string) get_option( 'acrb_currency', '£' ); 92 $currency_pos = (string) get_option( 'acrb_currency_pos', 'left' ); 84 93 $update_msg = ''; 85 94 … … 89 98 }; 90 99 91 // 5. Handle Account Profile & PasswordUpdates100 // 5. Handle Account Profile & Security Updates 92 101 if ( isset( $_POST['acrb_update_account'], $_POST['acrb_acc_nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['acrb_acc_nonce'] ) ), 'acrb_save_details' ) ) { 93 $fname = isset( $_POST['fname'] ) ? sanitize_text_field( wp_unslash( $_POST['fname'] ) ) : ''; 94 $lname = isset( $_POST['lname'] ) ? sanitize_text_field( wp_unslash( $_POST['lname'] ) ) : ''; 95 $phone = isset( $_POST['phone'] ) ? sanitize_text_field( wp_unslash( $_POST['phone'] ) ) : ''; 96 $address = isset( $_POST['address'] ) ? sanitize_textarea_field( wp_unslash( $_POST['address'] ) ) : ''; 97 98 update_user_meta( $user_id, 'first_name', $fname ); 99 update_user_meta( $user_id, 'last_name', $lname ); 100 update_user_meta( $user_id, 'billing_phone', $phone ); 101 update_user_meta( $user_id, 'acrb_address', $address ); 102 103 $new_pass = ! empty( $_POST['new_pass'] ) ? (string) wp_unslash( $_POST['new_pass'] ) : ''; 104 $conf_pass = ! empty( $_POST['conf_pass'] ) ? (string) wp_unslash( $_POST['conf_pass'] ) : ''; 105 106 if ( ! empty( $new_pass ) ) { 107 if ( $new_pass === $conf_pass ) { 102 $form_source = isset( $_POST['acrb_form_source'] ) ? sanitize_key( wp_unslash( $_POST['acrb_form_source'] ) ) : ''; 103 104 if ( 'profile' === $form_source ) { 105 $fname = isset( $_POST['fname'] ) ? sanitize_text_field( wp_unslash( $_POST['fname'] ) ) : ''; 106 $lname = isset( $_POST['lname'] ) ? sanitize_text_field( wp_unslash( $_POST['lname'] ) ) : ''; 107 $phone = isset( $_POST['phone'] ) ? sanitize_text_field( wp_unslash( $_POST['phone'] ) ) : ''; 108 109 update_user_meta( $user_id, 'first_name', $fname ); 110 update_user_meta( $user_id, 'last_name', $lname ); 111 update_user_meta( $user_id, 'billing_phone', $phone ); 112 113 $update_msg = '<div class="acrb-alert success">' . esc_html__( 'Profile details saved and updated successfully.', 'awesome-car-rental' ) . '</div>'; 114 } elseif ( 'security' === $form_source ) { 115 $new_pass = ! empty( $_POST['new_pass'] ) ? (string) wp_unslash( $_POST['new_pass'] ) : ''; 116 $conf_pass = ! empty( $_POST['conf_pass'] ) ? (string) wp_unslash( $_POST['conf_pass'] ) : ''; 117 118 if ( empty( $new_pass ) ) { 119 $update_msg = '<div class="acrb-alert error">' . esc_html__( 'Please enter a valid new password.', 'awesome-car-rental' ) . '</div>'; 120 } elseif ( strlen( $new_pass ) < 6 ) { 121 $update_msg = '<div class="acrb-alert error">' . esc_html__( 'Password must be at least 6 characters long.', 'awesome-car-rental' ) . '</div>'; 122 } elseif ( $new_pass !== $conf_pass ) { 123 $update_msg = '<div class="acrb-alert error">' . esc_html__( 'The new passwords provided do not match.', 'awesome-car-rental' ) . '</div>'; 124 } else { 108 125 wp_set_password( $new_pass, $user_id ); 109 $update_msg = '<div class="acrb-alert success">' . esc_html__( 'Password updated successfully. Please log in again.', 'awesome-car-rental' ) . '</div>'; 110 } else { 111 $update_msg = '<div class="acrb-alert error">' . esc_html__( 'The new passwords provided do not match.', 'awesome-car-rental' ) . '</div>'; 126 $update_msg = '<div class="acrb-alert success">' . esc_html__( 'Password updated successfully. Please log in again with your new credentials.', 'awesome-car-rental' ) . '</div>'; 112 127 } 113 } else {114 $update_msg = '<div class="acrb-alert success">' . esc_html__( 'Profile details saved and updated successfully.', 'awesome-car-rental' ) . '</div>';115 128 } 116 129 } … … 137 150 foreach ( $db_bookings as $dbb ) { 138 151 $b_id = absint( $dbb['id'] ); 152 153 // Compute rental duration in days 154 $pickup_raw = ! empty( $dbb['pickup_date'] ) ? (string) $dbb['pickup_date'] : ''; 155 $return_raw = ! empty( $dbb['return_date'] ) ? (string) $dbb['return_date'] : ''; 156 $pickup_time = ! empty( $pickup_raw ) ? strtotime( $pickup_raw ) : 0; 157 $return_time = ! empty( $return_raw ) ? strtotime( $return_raw ) : 0; 158 159 $rental_days = ( $pickup_time && $return_time && $return_time > $pickup_time ) 160 ? max( 1, (int) round( ( $return_time - $pickup_time ) / DAY_IN_SECONDS ) ) 161 : 1; 162 163 // Monetary fields with defensive arithmetic fallback 164 $total_amt = floatval( $dbb['total_amount'] ?? 0 ); 165 $discount_amt = floatval( $dbb['discount_amount'] ?? 0 ); 166 $tax_amt = floatval( $dbb['tax_amount'] ?? 0 ); 167 $insurance_fee = floatval( $dbb['insurance_amount'] ?? 0 ); 168 $border_fee = floatval( $dbb['border_amount'] ?? 0 ); 169 170 // Derive subtotal if not explicitly available 171 $subtotal = isset( $dbb['base_subtotal'] ) 172 ? floatval( $dbb['base_subtotal'] ) 173 : ( $total_amt - $tax_amt - $insurance_fee - $border_fee + $discount_amt ); 174 175 if ( $subtotal <= 0 ) { 176 $subtotal = $total_amt; 177 } 178 179 $rate_per_day = $rental_days > 0 ? ( $subtotal / $rental_days ) : $subtotal; 180 139 181 $normalized_bookings[] = array( 140 182 'id' => $b_id, 141 183 'code' => ! empty( $dbb['booking_code'] ) ? $dbb['booking_code'] : 'ACR-' . $b_id, 142 184 'car_name' => ! empty( $dbb['car_name'] ) ? $dbb['car_name'] : __( 'Fleet Vehicle', 'awesome-car-rental' ), 143 'pickup_date' => ! empty( $ dbb['pickup_date'] ) ? $dbb['pickup_date']: '—',144 'return_date' => ! empty( $ dbb['return_date'] ) ? $dbb['return_date']: '—',185 'pickup_date' => ! empty( $pickup_raw ) ? $pickup_raw : '—', 186 'return_date' => ! empty( $return_raw ) ? $return_raw : '—', 145 187 'pickup_loc' => ! empty( $dbb['pickup_location'] ) ? $dbb['pickup_location'] : __( 'Main Terminal', 'awesome-car-rental' ), 146 188 'return_loc' => ! empty( $dbb['return_location'] ) ? $dbb['return_location'] : __( 'Main Terminal', 'awesome-car-rental' ), 189 'rental_days' => $rental_days, 190 'rate_per_day' => $rate_per_day, 191 'subtotal' => $subtotal, 147 192 'insurance_plan' => ! empty( $dbb['insurance_plan'] ) ? $dbb['insurance_plan'] : '', 193 'insurance_fee' => $insurance_fee, 148 194 'border_permit' => ! empty( $dbb['border_permit'] ) ? $dbb['border_permit'] : '', 195 'border_fee' => $border_fee, 149 196 'promo_code' => ! empty( $dbb['promo_code'] ) ? $dbb['promo_code'] : '', 197 'discount_amt' => $discount_amt, 198 'tax_amt' => $tax_amt, 150 199 'payment_method' => ! empty( $dbb['payment_method'] ) ? $dbb['payment_method'] : 'pay_later', 151 'total_amt' => floatval( $dbb['total_amount'] ?? 0 ),200 'total_amt' => $total_amt, 152 201 'status' => sanitize_key( (string) ( $dbb['booking_status'] ?? 'pending' ) ), 153 202 ); … … 161 210 ob_start(); 162 211 ?> 163 <div class="acrb-acc-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>">212 <div class="acrb-acc-wrapper"> 164 213 <!-- Sidebar Navigation --> 165 214 <aside class="acrb-acc-nav"> … … 292 341 $b_price_disp = $format_price( $booking['total_amt'] ); 293 342 $status_class = 'status-' . sanitize_html_class( $booking['status'] ); 294 $b_insurance = esc_attr( $booking['insurance_plan'] );295 $b_border = esc_attr( $booking['border_permit'] );296 $b_promo = esc_attr( $booking['promo_code'] );297 $b_method = esc_attr( ucwords( str_replace( '_', ' ', $booking['payment_method'] ) ) );298 343 ?> 299 344 <div class="acrb-booking-card"> … … 339 384 </div> 340 385 <button type="button" class="acrb-btn-outline open-receipt" 341 data-id="<?php echo esc_attr( $b_code ); ?>" 342 data-car="<?php echo esc_attr( $b_car ); ?>" 343 data-total="<?php echo esc_attr( $b_price_disp ); ?>" 344 data-date="<?php echo esc_attr( $b_date ); ?>" 345 data-status="<?php echo esc_attr( ucfirst( $b_status ) ); ?>" 346 data-insurance="<?php echo esc_attr( $b_insurance ); ?>" 347 data-border="<?php echo esc_attr( $b_border ); ?>" 348 data-promo="<?php echo esc_attr( $b_promo ); ?>" 349 data-method="<?php echo esc_attr( $b_method ); ?>"> 386 data-id="<?php echo esc_attr( $booking['code'] ); ?>" 387 data-car="<?php echo esc_attr( $booking['car_name'] ); ?>" 388 data-pickup-date="<?php echo esc_attr( $booking['pickup_date'] ); ?>" 389 data-return-date="<?php echo esc_attr( $booking['return_date'] ); ?>" 390 data-pickup-loc="<?php echo esc_attr( $booking['pickup_loc'] ); ?>" 391 data-return-loc="<?php echo esc_attr( $booking['return_loc'] ); ?>" 392 data-days="<?php echo esc_attr( (string) $booking['rental_days'] ); ?>" 393 data-daily-rate="<?php echo esc_attr( $format_price( $booking['rate_per_day'] ) ); ?>" 394 data-subtotal="<?php echo esc_attr( $format_price( $booking['subtotal'] ) ); ?>" 395 data-insurance="<?php echo esc_attr( $booking['insurance_plan'] ); ?>" 396 data-insurance-fee="<?php echo esc_attr( $booking['insurance_fee'] > 0 ? $format_price( $booking['insurance_fee'] ) : '' ); ?>" 397 data-border="<?php echo esc_attr( $booking['border_permit'] ); ?>" 398 data-border-fee="<?php echo esc_attr( $booking['border_fee'] > 0 ? $format_price( $booking['border_fee'] ) : '' ); ?>" 399 data-promo="<?php echo esc_attr( $booking['promo_code'] ); ?>" 400 data-discount="<?php echo esc_attr( $booking['discount_amt'] > 0 ? '- ' . $format_price( $booking['discount_amt'] ) : '' ); ?>" 401 data-tax="<?php echo esc_attr( $booking['tax_amt'] > 0 ? $format_price( $booking['tax_amt'] ) : '' ); ?>" 402 data-total="<?php echo esc_attr( $format_price( $booking['total_amt'] ) ); ?>" 403 data-total-raw="<?php echo esc_attr( (string) $booking['total_amt'] ); ?>" 404 data-status="<?php echo esc_attr( ucfirst( $booking['status'] ) ); ?>" 405 data-method="<?php echo esc_attr( ucwords( str_replace( '_', ' ', $booking['payment_method'] ) ) ); ?>"> 350 406 <svg class="acrb-icon" viewBox="0 0 24 24"> 351 407 <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"></path> … … 376 432 <form method="post" class="acrb-settings-form"> 377 433 <?php wp_nonce_field( 'acrb_save_details', 'acrb_acc_nonce' ); ?> 434 <input type="hidden" name="acrb_form_source" value="profile"> 435 378 436 <div class="acrb-form-row"> 379 437 <div class="acrb-form-group"> … … 395 453 <input type="text" id="acrb_email" value="<?php echo esc_attr( $user->user_email ); ?>" disabled class="acrb-input acrb-readonly"> 396 454 </div> 397 </div>398 <div class="acrb-form-group">399 <label for="acrb_address"><?php esc_html_e( 'Residential / Billing Address', 'awesome-car-rental' ); ?></label>400 <textarea id="acrb_address" name="address" rows="3" class="acrb-textarea"><?php echo esc_textarea( (string) get_user_meta( $user_id, 'acrb_address', true ) ); ?></textarea>401 455 </div> 402 456 <div> … … 416 470 <div id="acrb-security-form" class="acrb-tab-panel"> 417 471 <h2 class="acrb-panel-title"><?php esc_html_e( 'Security & Password', 'awesome-car-rental' ); ?></h2> 418 <form method="post" class="acrb-settings-form">472 <form method="post" id="acrb-password-change-form" class="acrb-settings-form"> 419 473 <?php wp_nonce_field( 'acrb_save_details', 'acrb_acc_nonce' ); ?> 474 <input type="hidden" name="acrb_form_source" value="security"> 475 420 476 <div class="acrb-form-row"> 421 477 <div class="acrb-form-group"> 422 478 <label for="acrb_new_pass"><?php esc_html_e( 'New Password', 'awesome-car-rental' ); ?></label> 423 <input type="password" id="acrb_new_pass" name="new_pass" placeholder="••••••••" class="acrb-input" autocomplete="new-password"> 424 </div> 479 <input type="password" id="acrb_new_pass" name="new_pass" placeholder="••••••••" class="acrb-input" autocomplete="new-password" required> 480 481 <!-- Real-time Strength Meter --> 482 <div class="acrb-password-meter-wrap" id="acrb-meter-container" style="display: none;"> 483 <div class="acrb-password-meter-bar"> 484 <div class="acrb-password-meter-fill" id="acrb-meter-fill"></div> 485 </div> 486 <span class="acrb-password-meter-label" id="acrb-meter-label"></span> 487 </div> 488 </div> 489 425 490 <div class="acrb-form-group"> 426 491 <label for="acrb_conf_pass"><?php esc_html_e( 'Confirm New Password', 'awesome-car-rental' ); ?></label> 427 <input type="password" id="acrb_conf_pass" name="conf_pass" placeholder="••••••••" class="acrb-input" autocomplete="new-password"> 492 <input type="password" id="acrb_conf_pass" name="conf_pass" placeholder="••••••••" class="acrb-input" autocomplete="new-password" required> 493 494 <!-- Real-time Match Indicator --> 495 <div class="acrb-field-feedback" id="acrb-match-msg" style="display: none;"></div> 428 496 </div> 429 497 </div> 430 498 <div> 431 <button type="submit" name="acrb_update_account" class="acrb-btn-submit">499 <button type="submit" id="acrb-pass-submit-btn" name="acrb_update_account" class="acrb-btn-submit"> 432 500 <svg class="acrb-icon acrb-submit-icon" viewBox="0 0 24 24"> 433 501 <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect> … … 442 510 </div> 443 511 444 <!-- Booking Details Modal -->445 <div id="acrb-receipt-modal" class="acrb-modal" role="dialog" aria-modal="true" aria-hidden="true" style="<?php echo esc_attr( $scoped_styles ); ?>">512 <!-- Booking Details Breakdown Modal --> 513 <div id="acrb-receipt-modal" class="acrb-modal" role="dialog" aria-modal="true" aria-hidden="true"> 446 514 <div class="acrb-modal-content"> 447 515 <span class="acrb-modal-close" aria-label="<?php esc_attr_e( 'Close', 'awesome-car-rental' ); ?>">×</span> 516 448 517 <div class="acrb-receipt-header"> 449 518 <div class="acrb-receipt-icon-wrap"> … … 452 521 </svg> 453 522 </div> 454 <h3><?php esc_html_e( 'Rental Voucher & Invoice', 'awesome-car-rental' ); ?></h3> 455 <span id="acrb-m-id" class="acrb-m-id"></span> 456 </div> 457 <div class="acrb-receipt-list"> 523 <div class="acrb-receipt-title-wrap"> 524 <h3><?php esc_html_e( 'Rental Voucher & Invoice', 'awesome-car-rental' ); ?></h3> 525 <span id="acrb-m-id" class="acrb-m-id"></span> 526 </div> 527 </div> 528 529 <!-- Vehicle & Status Overview --> 530 <div class="acrb-receipt-meta-box"> 458 531 <div class="acrb-r-item"> 459 <span ><?php esc_html_e( 'Vehicle Model:', 'awesome-car-rental' ); ?></span>460 <strong id="acrb-m-car" class="acrb- m-car"></strong>532 <span class="acrb-label"><?php esc_html_e( 'Vehicle Model', 'awesome-car-rental' ); ?></span> 533 <strong id="acrb-m-car" class="acrb-val"></strong> 461 534 </div> 462 535 <div class="acrb-r-item"> 463 <span><?php esc_html_e( 'Rental Window:', 'awesome-car-rental' ); ?></span> 464 <span id="acrb-m-date" class="acrb-m-date"></span> 465 </div> 466 <div class="acrb-r-item acrb-row-collapsed" id="acrb-m-ins-row"> 467 <span><?php esc_html_e( 'Protection Plan:', 'awesome-car-rental' ); ?></span> 468 <span id="acrb-m-ins" class="acrb-m-ins"></span> 469 </div> 470 <div class="acrb-r-item acrb-row-collapsed" id="acrb-m-border-row"> 471 <span><?php esc_html_e( 'Border Permit:', 'awesome-car-rental' ); ?></span> 472 <span id="acrb-m-border" class="acrb-m-border"></span> 473 </div> 474 <div class="acrb-r-item acrb-row-collapsed" id="acrb-m-promo-row"> 475 <span><?php esc_html_e( 'Promo Voucher:', 'awesome-car-rental' ); ?></span> 476 <span id="acrb-m-promo" class="acrb-m-promo"></span> 477 </div> 478 <div class="acrb-r-item"> 479 <span><?php esc_html_e( 'Payment Method:', 'awesome-car-rental' ); ?></span> 480 <span id="acrb-m-method" class="acrb-m-method"></span> 481 </div> 482 <div class="acrb-r-item"> 483 <span><?php esc_html_e( 'Booking Status:', 'awesome-car-rental' ); ?></span> 484 <span id="acrb-m-status" class="acrb-status-pill status-confirmed"></span> 485 </div> 486 </div> 487 <div class="acrb-r-total"> 488 <span><?php esc_html_e( 'Settled Amount:', 'awesome-car-rental' ); ?></span> 489 <span id="acrb-m-total" class="acrb-m-total"></span> 490 </div> 536 <span class="acrb-label"><?php esc_html_e( 'Payment & Booking Status', 'awesome-car-rental' ); ?></span> 537 <span class="acrb-val"> 538 <span id="acrb-m-status" class="acrb-status-pill status-confirmed"></span> 539 <span id="acrb-m-method" class="acrb-payment-badge"></span> 540 </span> 541 </div> 542 </div> 543 544 <!-- Detailed Rental Window Card --> 545 <div class="acrb-schedule-card"> 546 <div class="acrb-schedule-header"> 547 <span class="acrb-schedule-title"><?php esc_html_e( 'Rental Window & Schedule', 'awesome-car-rental' ); ?></span> 548 <span class="acrb-duration-pill"> 549 <svg width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 550 <circle cx="12" cy="12" r="10"></circle> 551 <polyline points="12 6 12 12 16 14"></polyline> 552 </svg> 553 <span id="acrb-m-days-badge">1 Day</span> 554 </span> 555 </div> 556 <div class="acrb-window-grid"> 557 <div class="acrb-window-point"> 558 <span class="acrb-point-badge pickup"><?php esc_html_e( 'Pick-up', 'awesome-car-rental' ); ?></span> 559 <span id="acrb-m-pickup-date" class="acrb-point-date">—</span> 560 <span class="acrb-point-loc"> 561 <svg width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 562 <path d="M12 21s-6-5.333-6-10a6 6 0 0 1 12 0c0 4.667-6 10-6 10z"></path> 563 <circle cx="12" cy="11" r="2"></circle> 564 </svg> 565 <span id="acrb-m-pickup-loc">—</span> 566 </span> 567 </div> 568 <div class="acrb-window-arrow"> 569 <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 570 <path stroke-linecap="round" stroke-linejoin="round" d="M17 8l4 4m0 0l-4 4m4-4H3"></path> 571 </svg> 572 </div> 573 <div class="acrb-window-point"> 574 <span class="acrb-point-badge return"><?php esc_html_e( 'Return', 'awesome-car-rental' ); ?></span> 575 <span id="acrb-m-return-date" class="acrb-point-date">—</span> 576 <span class="acrb-point-loc"> 577 <svg width="12" height="12" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> 578 <path d="M12 21s-6-5.333-6-10a6 6 0 0 1 12 0c0 4.667-6 10-6 10z"></path> 579 <circle cx="12" cy="11" r="2"></circle> 580 </svg> 581 <span id="acrb-m-return-loc">—</span> 582 </span> 583 </div> 584 </div> 585 </div> 586 587 <!-- Itemized Fee Breakdown Layout --> 588 <div class="acrb-breakdown-container"> 589 <h4 class="acrb-section-subheading"><?php esc_html_e( 'Itemized Fee Breakdown', 'awesome-car-rental' ); ?></h4> 590 <div class="acrb-fee-list"> 591 <!-- Base Daily Charge --> 592 <div class="acrb-fee-row" id="acrb-row-base"> 593 <div class="acrb-fee-info"> 594 <span class="acrb-fee-title"><?php esc_html_e( 'Base Vehicle Hire', 'awesome-car-rental' ); ?></span> 595 <span class="acrb-fee-sub" id="acrb-m-rate-calc">—</span> 596 </div> 597 <span class="acrb-fee-amount" id="acrb-m-subtotal">—</span> 598 </div> 599 600 <!-- Protection Plan --> 601 <div class="acrb-fee-row" id="acrb-row-insurance" style="display: none;"> 602 <div class="acrb-fee-info"> 603 <span class="acrb-fee-title" id="acrb-m-ins-name"><?php esc_html_e( 'Protection Plan', 'awesome-car-rental' ); ?></span> 604 <span class="acrb-fee-sub"><?php esc_html_e( 'Full collision and theft protection package', 'awesome-car-rental' ); ?></span> 605 </div> 606 <span class="acrb-fee-amount" id="acrb-m-ins-fee">—</span> 607 </div> 608 609 <!-- Border Permit --> 610 <div class="acrb-fee-row" id="acrb-row-border" style="display: none;"> 611 <div class="acrb-fee-info"> 612 <span class="acrb-fee-title"><?php esc_html_e( 'Cross-Border Travel Permit', 'awesome-car-rental' ); ?></span> 613 <span class="acrb-fee-sub" id="acrb-m-border-name">—</span> 614 </div> 615 <span class="acrb-fee-amount" id="acrb-m-border-fee">—</span> 616 </div> 617 618 <!-- Taxes & Charges --> 619 <div class="acrb-fee-row" id="acrb-row-tax" style="display: none;"> 620 <div class="acrb-fee-info"> 621 <span class="acrb-fee-title"><?php esc_html_e( 'Taxes & Regulatory Surcharges', 'awesome-car-rental' ); ?></span> 622 <span class="acrb-fee-sub"><?php esc_html_e( 'Local road tax, VAT and airport facilities fees', 'awesome-car-rental' ); ?></span> 623 </div> 624 <span class="acrb-fee-amount" id="acrb-m-tax-val">—</span> 625 </div> 626 627 <!-- Promo Voucher Discount --> 628 <div class="acrb-fee-row acrb-fee-discount" id="acrb-row-promo" style="display: none;"> 629 <div class="acrb-fee-info"> 630 <div> 631 <span class="acrb-fee-title"><?php esc_html_e( 'Promotional Discount', 'awesome-car-rental' ); ?></span> 632 <span class="acrb-badge-tag" id="acrb-m-promo-badge">PROMO</span> 633 </div> 634 <span class="acrb-fee-sub" id="acrb-m-promo-name">—</span> 635 </div> 636 <span class="acrb-fee-amount acrb-fee-discount" id="acrb-m-discount-fee">—</span> 637 </div> 638 </div> 639 </div> 640 641 <!-- Settled Amount Box --> 642 <div class="acrb-settled-box"> 643 <div class="acrb-settled-info"> 644 <strong><?php esc_html_e( 'Settled Total Amount', 'awesome-car-rental' ); ?></strong> 645 <small><?php esc_html_e( 'All fees, taxes, and coverage included', 'awesome-car-rental' ); ?></small> 646 </div> 647 <div class="acrb-settled-val" id="acrb-m-total">—</div> 648 </div> 649 491 650 <button type="button" onclick="window.print()" class="acrb-btn-print"> 492 651 <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> … … 502 661 <script> 503 662 document.addEventListener('DOMContentLoaded', function() { 663 // Tab Navigation 504 664 const triggers = document.querySelectorAll('.acrb-tab-trigger'); 505 665 triggers.forEach(function(t) { … … 521 681 }); 522 682 523 const modal = document.getElementById('acrb-receipt-modal'); 524 const detailBtns = document.querySelectorAll('.open-receipt'); 525 const closeBtn = document.querySelector('.acrb-modal-close'); 683 // ========================================================================== 684 // Password Strength & Real-Time Confirmation Logic 685 // ========================================================================== 686 const newPassInput = document.getElementById('acrb_new_pass'); 687 const confPassInput = document.getElementById('acrb_conf_pass'); 688 const meterContainer = document.getElementById('acrb-meter-container'); 689 const meterFill = document.getElementById('acrb-meter-fill'); 690 const meterLabel = document.getElementById('acrb-meter-label'); 691 const matchMsg = document.getElementById('acrb-match-msg'); 692 const passSubmitBtn = document.getElementById('acrb-pass-submit-btn'); 693 const passForm = document.getElementById('acrb-password-change-form'); 694 695 function evaluatePasswordStrength(val) { 696 let score = 0; 697 if (!val) return 0; 698 699 if (val.length >= 6) score += 1; 700 if (val.length >= 10) score += 1; 701 if (/[a-z]/.test(val) && /[A-Z]/.test(val)) score += 1; 702 if (/\d/.test(val)) score += 1; 703 if (/[^a-zA-Z\d]/.test(val)) score += 1; 704 705 return Math.min(score, 4); 706 } 707 708 function updateStrengthUI() { 709 if (!newPassInput || !meterContainer) return; 710 711 const val = newPassInput.value; 712 if (!val) { 713 meterContainer.style.display = 'none'; 714 return; 715 } 716 717 meterContainer.style.display = 'flex'; 718 const score = evaluatePasswordStrength(val); 719 720 const configs = [ 721 { width: '25%', color: '#ef4444', text: '<?php echo esc_js( __( 'Weak', 'awesome-car-rental' ) ); ?>' }, 722 { width: '50%', color: '#f97316', text: '<?php echo esc_js( __( 'Fair', 'awesome-car-rental' ) ); ?>' }, 723 { width: '75%', color: '#eab308', text: '<?php echo esc_js( __( 'Good', 'awesome-car-rental' ) ); ?>' }, 724 { width: '100%', color: '#10b981', text: '<?php echo esc_js( __( 'Very Strong', 'awesome-car-rental' ) ); ?>' } 725 ]; 726 727 const active = configs[Math.max(0, score - 1)] || configs[0]; 728 meterFill.style.width = active.width; 729 meterFill.style.backgroundColor = active.color; 730 meterLabel.textContent = active.text; 731 meterLabel.style.color = active.color; 732 } 733 734 function validateMatch() { 735 if (!newPassInput || !confPassInput || !matchMsg) return; 736 737 const newPass = newPassInput.value; 738 const confPass = confPassInput.value; 739 740 if (!confPass) { 741 matchMsg.style.display = 'none'; 742 confPassInput.classList.remove('match-valid', 'match-invalid'); 743 return; 744 } 745 746 matchMsg.style.display = 'flex'; 747 748 if (newPass === confPass) { 749 matchMsg.className = 'acrb-field-feedback is-match'; 750 matchMsg.innerHTML = '<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"></polyline></svg> <span><?php echo esc_js( __( 'Passwords match perfectly', 'awesome-car-rental' ) ); ?></span>'; 751 confPassInput.classList.add('match-valid'); 752 confPassInput.classList.remove('match-invalid'); 753 } else { 754 matchMsg.className = 'acrb-field-feedback is-mismatch'; 755 matchMsg.innerHTML = '<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line></svg> <span><?php echo esc_js( __( 'Passwords do not match', 'awesome-car-rental' ) ); ?></span>'; 756 confPassInput.classList.add('match-invalid'); 757 confPassInput.classList.remove('match-valid'); 758 } 759 } 760 761 if (newPassInput && confPassInput) { 762 newPassInput.addEventListener('input', function() { 763 updateStrengthUI(); 764 validateMatch(); 765 }); 766 767 confPassInput.addEventListener('input', validateMatch); 768 } 769 770 if (passForm) { 771 passForm.addEventListener('submit', function(e) { 772 const newPass = newPassInput.value; 773 const confPass = confPassInput.value; 774 775 if (newPass.length < 6) { 776 e.preventDefault(); 777 alert('<?php echo esc_js( __( 'Password must be at least 6 characters long.', 'awesome-car-rental' ) ); ?>'); 778 newPassInput.focus(); 779 return; 780 } 781 782 if (newPass !== confPass) { 783 e.preventDefault(); 784 alert('<?php echo esc_js( __( 'Passwords do not match. Please ensure both fields are identical.', 'awesome-car-rental' ) ); ?>'); 785 confPassInput.focus(); 786 } 787 }); 788 } 789 790 // ========================================================================== 791 // Receipt Modal Handlers 792 // ========================================================================== 793 const modal = document.getElementById('acrb-receipt-modal'); 794 const detailBtns = document.querySelectorAll('.open-receipt'); 795 const closeBtn = document.querySelector('.acrb-modal-close'); 796 const currencySym = '<?php echo esc_js( $currency_symbol ); ?>'; 797 const currencyPos = '<?php echo esc_js( $currency_pos ); ?>'; 798 799 function formatJsPrice(val) { 800 const num = parseFloat(val) || 0; 801 const formatted = num.toFixed(2); 802 return currencyPos === 'left' ? currencySym + formatted : formatted + currencySym; 803 } 804 805 function closeModal() { 806 if (!modal) return; 807 modal.style.display = 'none'; 808 modal.setAttribute('aria-hidden', 'true'); 809 document.body.style.overflow = ''; 810 } 526 811 527 812 if (modal && detailBtns.length > 0) { 528 813 detailBtns.forEach(function(btn) { 529 814 btn.addEventListener('click', function() { 530 document.getElementById('acrb-m-id').textContent = '#' + this.getAttribute('data-id'); 531 document.getElementById('acrb-m-car').textContent = this.getAttribute('data-car'); 532 document.getElementById('acrb-m-date').textContent = this.getAttribute('data-date'); 533 document.getElementById('acrb-m-total').textContent = this.getAttribute('data-total'); 534 document.getElementById('acrb-m-method').textContent = this.getAttribute('data-method'); 815 const bookingCode = this.getAttribute('data-id') || ''; 816 const carModel = this.getAttribute('data-car') || ''; 817 const payMethod = this.getAttribute('data-method') || ''; 818 const statusText = this.getAttribute('data-status') || ''; 819 const rawTotal = this.getAttribute('data-total-raw') || this.getAttribute('data-total') || '0'; 820 821 document.getElementById('acrb-m-id').textContent = '#' + bookingCode; 822 document.getElementById('acrb-m-car').textContent = carModel; 823 document.getElementById('acrb-m-method').textContent = payMethod; 535 824 536 825 const statusElem = document.getElementById('acrb-m-status'); 537 826 if (statusElem) { 538 statusElem.textContent = this.getAttribute('data-status');827 statusElem.textContent = statusText; 539 828 } 540 829 541 // Insurance 542 const insVal = this.getAttribute('data-insurance'); 543 const insRow = document.getElementById('acrb-m-ins-row'); 544 if (insVal) { 545 document.getElementById('acrb-m-ins').textContent = insVal; 830 const totalElem = document.getElementById('acrb-m-total'); 831 if (totalElem) { 832 totalElem.textContent = formatJsPrice(rawTotal); 833 } 834 835 const daysVal = this.getAttribute('data-days') || '1'; 836 const pickupDateVal = this.getAttribute('data-pickup-date') || '—'; 837 const returnDateVal = this.getAttribute('data-return-date') || '—'; 838 const pickupLocVal = this.getAttribute('data-pickup-loc') || '—'; 839 const returnLocVal = this.getAttribute('data-return-loc') || '—'; 840 841 document.getElementById('acrb-m-days-badge').textContent = daysVal + (daysVal === '1' ? ' Day Rental' : ' Days Rental'); 842 document.getElementById('acrb-m-pickup-date').textContent = pickupDateVal; 843 document.getElementById('acrb-m-return-date').textContent = returnDateVal; 844 document.getElementById('acrb-m-pickup-loc').textContent = pickupLocVal; 845 document.getElementById('acrb-m-return-loc').textContent = returnLocVal; 846 847 const dailyRate = this.getAttribute('data-daily-rate') || ''; 848 const subtotal = this.getAttribute('data-subtotal') || formatJsPrice(rawTotal); 849 850 document.getElementById('acrb-m-rate-calc').textContent = daysVal + (daysVal === '1' ? ' day' : ' days') + (dailyRate ? ' × ' + dailyRate + ' / day' : ''); 851 document.getElementById('acrb-m-subtotal').textContent = subtotal; 852 853 const insName = this.getAttribute('data-insurance'); 854 const insFee = this.getAttribute('data-insurance-fee'); 855 const insRow = document.getElementById('acrb-row-insurance'); 856 if (insName && insName.trim() !== '') { 857 document.getElementById('acrb-m-ins-name').textContent = insName; 858 document.getElementById('acrb-m-ins-fee').textContent = insFee ? insFee : '<?php echo esc_js( __( 'Included', 'awesome-car-rental' ) ); ?>'; 546 859 insRow.style.display = 'flex'; 547 860 } else { … … 549 862 } 550 863 551 // Border552 864 const borderVal = this.getAttribute('data-border'); 553 const borderRow = document.getElementById('acrb-m-border-row'); 554 if (borderVal) { 555 document.getElementById('acrb-m-border').textContent = borderVal + ' Permit'; 865 const borderFee = this.getAttribute('data-border-fee'); 866 const borderRow = document.getElementById('acrb-row-border'); 867 if (borderVal && borderVal.trim() !== '') { 868 document.getElementById('acrb-m-border-name').textContent = borderVal + ' <?php echo esc_js( __( 'Pass', 'awesome-car-rental' ) ); ?>'; 869 document.getElementById('acrb-m-border-fee').textContent = borderFee ? borderFee : '<?php echo esc_js( __( 'Included', 'awesome-car-rental' ) ); ?>'; 556 870 borderRow.style.display = 'flex'; 557 871 } else { … … 559 873 } 560 874 561 // Promo 562 const promoVal = this.getAttribute('data-promo'); 563 const promoRow = document.getElementById('acrb-m-promo-row'); 564 if (promoVal) { 565 document.getElementById('acrb-m-promo').textContent = promoVal; 875 const taxVal = this.getAttribute('data-tax'); 876 const taxRow = document.getElementById('acrb-row-tax'); 877 if (taxVal && taxVal.trim() !== '') { 878 document.getElementById('acrb-m-tax-val').textContent = taxVal; 879 taxRow.style.display = 'flex'; 880 } else { 881 taxRow.style.display = 'none'; 882 } 883 884 const promoVal = this.getAttribute('data-promo'); 885 const discVal = this.getAttribute('data-discount'); 886 const promoRow = document.getElementById('acrb-row-promo'); 887 const badgeElem = document.getElementById('acrb-m-promo-badge'); 888 if ((promoVal && promoVal.trim() !== '') || (discVal && discVal.trim() !== '')) { 889 if (promoVal && promoVal.trim() !== '') { 890 badgeElem.textContent = promoVal; 891 badgeElem.style.display = 'inline-block'; 892 document.getElementById('acrb-m-promo-name').textContent = '<?php echo esc_js( __( 'Voucher code activated', 'awesome-car-rental' ) ); ?>'; 893 } else { 894 badgeElem.style.display = 'none'; 895 document.getElementById('acrb-m-promo-name').textContent = '<?php echo esc_js( __( 'Special promotional discount', 'awesome-car-rental' ) ); ?>'; 896 } 897 document.getElementById('acrb-m-discount-fee').textContent = discVal ? discVal : '<?php echo esc_js( __( 'Applied', 'awesome-car-rental' ) ); ?>'; 566 898 promoRow.style.display = 'flex'; 567 899 } else { … … 571 903 modal.style.display = 'block'; 572 904 modal.setAttribute('aria-hidden', 'false'); 905 modal.scrollTop = 0; 906 document.body.style.overflow = 'hidden'; 573 907 }); 574 908 }); 575 909 576 910 if (closeBtn) { 577 closeBtn.addEventListener('click', function() { 578 modal.style.display = 'none'; 579 modal.setAttribute('aria-hidden', 'true'); 580 }); 911 closeBtn.addEventListener('click', closeModal); 581 912 } 582 913 583 914 window.addEventListener('click', function(e) { 584 915 if (e.target === modal) { 585 modal.style.display = 'none'; 586 modal.setAttribute('aria-hidden', 'true'); 916 closeModal(); 917 } 918 }); 919 920 document.addEventListener('keydown', function(e) { 921 if (e.key === 'Escape' && modal.style.display === 'block') { 922 closeModal(); 587 923 } 588 924 }); -
awesome-car-rental/trunk/frontend/auth/acrb-frontend-auth.php
r3775773 r3777386 2 2 /** 3 3 * [acrb_header_auth] 4 * Ultra-Modern Elite SaaS Header Auth Widget 4 * Ultra-Modern Elite SaaS Header Auth Widget with Dropdown & Redirection Support 5 5 * Location: templates/shortcodes/header-auth.php 6 6 * … … 13 13 if ( ! defined( 'ABSPATH' ) ) { 14 14 exit; 15 }16 17 add_action( 'wp_enqueue_scripts', 'acrb_enqueue_header_auth_assets' );18 19 function acrb_enqueue_header_auth_assets(): void {20 wp_register_style(21 'acrb-header-auth-style',22 ACRB_URL . 'assets/css/frontend/header-auth.css',23 array(),24 ACRB_VERSION25 );26 15 } 27 16 … … 50 39 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 51 40 52 // Scoped CSS property string injected directly into widget wrapper (no :root) 53 $scoped_styles = sprintf( 54 '--acrb-auth-primary:%s;--acrb-auth-secondary:%s;--acrb-auth-text:%s;--acrb-auth-accent:%s;--acrb-auth-btn-bg:%s;--acrb-auth-btn-hover:%s;--acrb-auth-font:%s;', 41 // Inject dynamic CSS custom properties via wp_add_inline_style 42 $custom_css = sprintf( 43 '.acrb-header-auth { 44 --acrb-auth-primary: %s; 45 --acrb-auth-secondary: %s; 46 --acrb-auth-text: %s; 47 --acrb-auth-accent: %s; 48 --acrb-auth-btn-bg: %s; 49 --acrb-auth-btn-hover: %s; 50 --acrb-auth-font: %s; 51 }', 55 52 esc_attr( $primary_color ), 56 53 esc_attr( $secondary_color ), … … 61 58 esc_attr( $selected_font ) 62 59 ); 60 wp_add_inline_style( 'acrb-header-auth-style', $custom_css ); 61 62 // Current URI for intelligent redirect post-login 63 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 64 $current_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; 65 $current_url = home_url( $current_uri ); 63 66 64 67 ob_start(); 65 68 ?> 66 <div class="acrb-header-auth" style="<?php echo esc_attr( $scoped_styles ); ?>">69 <div class="acrb-header-auth"> 67 70 <?php if ( is_user_logged_in() ) : 68 71 $user = wp_get_current_user(); … … 85 88 86 89 <?php else : 87 $login_url = site_url( '/acrb-login/');88 $reg_url = site_url( '/acrb-registration/');90 $login_url = add_query_arg( 'redirect_to', rawurlencode( $current_url ), site_url( '/acrb-login/' ) ); 91 $reg_url = add_query_arg( 'redirect_to', rawurlencode( $current_url ), site_url( '/acrb-registration/' ) ); 89 92 ?> 90 93 <div class="acrb-auth-group"> -
awesome-car-rental/trunk/frontend/cars/acrb-frontend-cars.php
r3775773 r3777386 2 2 /** 3 3 * [acrb_all_cars] 4 * Ultra-Modern Elite SaaS Fleet Archive with Live Filtering & Professional List/Grid Toggles4 * Ultra-Modern Elite SaaS Fleet Archive with Live Filtering & Numbered Pagination 5 5 * Location: templates/shortcodes/all-cars.php 6 6 * … … 19 19 function acrb_render_all_cars_archive_shortcode(): string { 20 20 global $wpdb; 21 $table_cars = $wpdb->prefix . 'dev_nahian_cars';21 $table_cars = $wpdb->prefix . 'dev_nahian_cars'; 22 22 $table_categories = $wpdb->prefix . 'dev_nahian_categories'; 23 23 … … 43 43 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 44 44 45 // Scoped CSS Custom Properties (Zero :root, pure encapsulation) 46 $scoped_styles = sprintf( 47 '--acrb-grid-primary:%s;--acrb-grid-secondary:%s;--acrb-grid-text:%s;--acrb-grid-accent:%s;--acrb-grid-btn-bg:%s;--acrb-grid-btn-hover:%s;--acrb-grid-font:%s;', 45 // Inject dynamic CSS custom properties via wp_add_inline_style 46 $custom_css = sprintf( 47 '.acrb-grid-wrapper, .acrb-empty { 48 --acrb-grid-primary: %s; 49 --acrb-grid-secondary: %s; 50 --acrb-grid-text: %s; 51 --acrb-grid-accent: %s; 52 --acrb-grid-btn-bg: %s; 53 --acrb-grid-btn-hover: %s; 54 --acrb-grid-font: %s; 55 }', 48 56 esc_attr( $primary_color ), 49 57 esc_attr( $secondary_color ), … … 54 62 esc_attr( $selected_font ) 55 63 ); 64 wp_add_inline_style( 'acrb-all-cars-style', $custom_css ); 56 65 57 66 // 3. Currency & Billing Unit Settings 58 $currency_symbol = get_option( 'acrb_currency', '£' ); 59 $currency_pos = get_option( 'acrb_currency_pos', 'left' ); 60 $rental_unit = get_option( 'acrb_rental_unit', 'day' ); 67 $currency_symbol = (string) get_option( 'acrb_currency', '£' ); 68 $currency_code = (string) get_option( 'acrb_currency_code', 'GBP' ); 69 $currency_pos = (string) get_option( 'acrb_currency_pos', 'left' ); 70 $rental_unit = (string) get_option( 'acrb_rental_unit', 'day' ); 61 71 62 72 $format_price = static function( float $val ) use ( $currency_symbol, $currency_pos ): string { … … 70 80 71 81 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 72 $cars = $wpdb->get_results( "SELECT * FROM {$table_cars} WHERE status != 'draft' AND status != 'retired' ORDER BY id DESC", ARRAY_A ); 73 74 // Category vehicle count indexing 75 $cat_counts = array(); 82 $cars = $wpdb->get_results( "SELECT * FROM {$table_cars} WHERE status NOT IN ('draft', 'retired') ORDER BY id DESC", ARRAY_A ); 83 84 // Index Facet Counts & Max Price 85 $cat_counts = array(); 86 $trans_counts = array( 'automatic' => 0, 'manual' => 0 ); 87 $fuel_counts = array( 'petrol' => 0, 'diesel' => 0, 'electric' => 0, 'hybrid' => 0 ); 88 $max_car_price = 0.0; 89 76 90 if ( ! empty( $cars ) ) { 77 91 foreach ( $cars as $car_item ) { … … 80 94 $cat_counts[ $c_cat ] = ( $cat_counts[ $c_cat ] ?? 0 ) + 1; 81 95 } 96 97 $t_slug = strtolower( trim( (string) ( $car_item['transmission'] ?? 'automatic' ) ) ); 98 if ( isset( $trans_counts[ $t_slug ] ) ) { 99 $trans_counts[ $t_slug ]++; 100 } 101 102 $f_slug = strtolower( trim( (string) ( $car_item['fuel'] ?? 'petrol' ) ) ); 103 if ( isset( $fuel_counts[ $f_slug ] ) ) { 104 $fuel_counts[ $f_slug ]++; 105 } 106 107 $car_p = floatval( $car_item['price'] ?? 0 ); 108 if ( $car_p > $max_car_price ) { 109 $max_car_price = $car_p; 110 } 82 111 } 83 112 } 113 114 $max_car_price = ceil( $max_car_price > 0 ? $max_car_price : 500 ); 84 115 85 116 if ( empty( $cars ) ) { 86 117 ob_start(); 87 118 ?> 88 <div class="acrb-empty" style="<?php echo esc_attr( $scoped_styles ); ?>">89 < ?php esc_html_e( 'No fleet vehicles found matching your criteria.', 'awesome-car-rental' ); ?>119 <div class="acrb-empty"> 120 <p><?php esc_html_e( 'No fleet vehicles found matching your criteria.', 'awesome-car-rental' ); ?></p> 90 121 </div> 91 122 <?php … … 95 126 ob_start(); 96 127 ?> 97 <div class="acrb-grid-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>"> 128 <div class="acrb-grid-wrapper"> 129 <!-- Mobile Trigger Bar --> 130 <div class="acrb-mobile-filter-bar"> 131 <button type="button" class="acrb-mobile-toggle-btn" id="acrb-mobile-filter-toggle"> 132 <span style="display:flex;align-items:center;gap:10px;"> 133 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"> 134 <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon> 135 </svg> 136 <span><?php esc_html_e( 'Filter Fleet Models', 'awesome-car-rental' ); ?></span> 137 </span> 138 <span id="acrb-mobile-filter-badge" class="acrb-count-badge" style="display:none;">0</span> 139 </button> 140 </div> 141 98 142 <div class="acrb-layout-container"> 99 143 <!-- Left Side Filter Sidebar --> 100 <aside class="acrb-filter-sidebar"> 144 <aside class="acrb-filter-sidebar" id="acrb-filter-sidebar"> 145 <div class="acrb-sidebar-header"> 146 <div class="acrb-sidebar-title-group"> 147 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"> 148 <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon> 149 </svg> 150 <h4><?php esc_html_e( 'Filter Fleet', 'awesome-car-rental' ); ?></h4> 151 </div> 152 <button type="button" id="acrb-reset-filters-btn" class="acrb-btn-clear"> 153 <?php esc_html_e( 'Reset All', 'awesome-car-rental' ); ?> 154 </button> 155 </div> 156 157 <!-- 1. Search Fleet --> 101 158 <div class="acrb-filter-section"> 102 < h4><?php esc_html_e( 'Search Fleet', 'awesome-car-rental' ); ?></h4>159 <label for="acrb-filter-search" class="acrb-filter-label"><?php esc_html_e( 'Quick Search', 'awesome-car-rental' ); ?></label> 103 160 <div class="acrb-search-box"> 104 <svg class="acrb-grid-icon" viewBox="0 0 24 24"> 161 <input type="text" id="acrb-filter-search" placeholder="<?php esc_attr_e( 'Model, brand or tag...', 'awesome-car-rental' ); ?>"> 162 <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 105 163 <circle cx="11" cy="11" r="8"></circle> 106 164 <line x1="21" y1="21" x2="16.65" y2="16.65"></line> 107 165 </svg> 108 <input type="text" id="acrb-filter-search" placeholder="<?php esc_attr_e( 'Search model or brand...', 'awesome-car-rental' ); ?>">109 166 </div> 110 167 </div> 111 168 169 <!-- 2. Budget Slider --> 170 <div class="acrb-filter-section"> 171 <div class="acrb-price-header"> 172 <label for="acrb-price-range" class="acrb-filter-label" style="margin:0;"><?php esc_html_e( 'Max Daily Budget', 'awesome-car-rental' ); ?></label> 173 <span id="acrb-price-display" class="acrb-price-badge"><?php echo esc_html( $format_price( (float) $max_car_price ) ); ?></span> 174 </div> 175 <input type="range" id="acrb-price-range" min="0" max="<?php echo esc_attr( (string) $max_car_price ); ?>" step="5" value="<?php echo esc_attr( (string) $max_car_price ); ?>" class="acrb-range-slider"> 176 <div class="acrb-slider-bounds"> 177 <span><?php echo esc_html( $format_price( 0.00 ) ); ?></span> 178 <span><?php echo esc_html( $format_price( (float) $max_car_price ) ); ?></span> 179 </div> 180 </div> 181 182 <!-- 3. Category Group --> 112 183 <?php if ( ! empty( $categories ) ) : ?> 113 184 <div class="acrb-filter-section"> 114 <h 4><?php esc_html_e( 'Categories', 'awesome-car-rental' ); ?></h4>185 <h5 class="acrb-filter-subheading"><?php esc_html_e( 'Vehicle Category', 'awesome-car-rental' ); ?></h5> 115 186 <ul class="acrb-filter-list"> 116 187 <?php foreach ( $categories as $cat ) : 117 188 $c_name = esc_html( $cat['name'] ); 118 189 $c_slug = sanitize_title( $cat['slug'] ?? $c_name ); 119 $c_count = absint( $cat_counts[ $c _name] ?? 0 );190 $c_count = absint( $cat_counts[ $cat['name'] ] ?? 0 ); 120 191 ?> 121 192 <li class="acrb-filter-item"> 122 <label> 123 <input type="checkbox" class="acrb-cat-filter" value="<?php echo esc_attr( $c_slug ); ?>"> 124 <span><?php echo esc_html( $c_name ); ?></span> 125 </label> 126 <span class="acrb-count-badge"><?php echo esc_html( (string) $c_count ); ?></span> 127 </li> 193 <label> 194 <div class="acrb-item-left"> 195 <input type="checkbox" class="acrb-cat-filter" value="<?php echo esc_attr( $c_slug ); ?>"> 196 <span class="acrb-custom-check"> 197 <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"> 198 <polyline points="20 6 9 17 4 12"></polyline> 199 </svg> 200 </span> 201 <span><?php echo esc_html( $c_name ); ?></span> 202 </div> 203 <span class="acrb-count-badge"><?php echo esc_html( (string) $c_count ); ?></span> 204 </label> 205 </li> 128 206 <?php endforeach; ?> 129 207 </ul> … … 131 209 <?php endif; ?> 132 210 211 <!-- 4. Transmission Chips --> 133 212 <div class="acrb-filter-section"> 134 <h4><?php esc_html_e( 'Transmission', 'awesome-car-rental' ); ?></h4> 135 <ul class="acrb-filter-list"> 136 <li class="acrb-filter-item"> 137 <label><input type="checkbox" class="acrb-spec-filter" value="automatic"> <span><?php esc_html_e( 'Automatic', 'awesome-car-rental' ); ?></span></label> 138 </li> 139 <li class="acrb-filter-item"> 140 <label><input type="checkbox" class="acrb-spec-filter" value="manual"> <span><?php esc_html_e( 'Manual', 'awesome-car-rental' ); ?></span></label> 141 </li> 142 </ul> 213 <h5 class="acrb-filter-subheading"><?php esc_html_e( 'Transmission', 'awesome-car-rental' ); ?></h5> 214 <div class="acrb-chip-grid"> 215 <label class="acrb-chip-btn"> 216 <input type="checkbox" class="acrb-trans-filter" value="automatic"> 217 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 218 <circle cx="12" cy="12" r="9"></circle> 219 <path d="M12 7v5l3 3"></path> 220 </svg> 221 <span><?php esc_html_e( 'Auto', 'awesome-car-rental' ); ?></span> 222 </label> 223 <label class="acrb-chip-btn"> 224 <input type="checkbox" class="acrb-trans-filter" value="manual"> 225 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 226 <path d="M6 4v16m12-16v16M6 12h12"></path> 227 </svg> 228 <span><?php esc_html_e( 'Manual', 'awesome-car-rental' ); ?></span> 229 </label> 230 </div> 143 231 </div> 144 232 233 <!-- 5. Fuel Type Chips --> 145 234 <div class="acrb-filter-section"> 146 <h4><?php esc_html_e( 'Fuel Type', 'awesome-car-rental' ); ?></h4> 147 <ul class="acrb-filter-list"> 148 <li class="acrb-filter-item"> 149 <label><input type="checkbox" class="acrb-spec-filter" value="petrol"> <span><?php esc_html_e( 'Petrol', 'awesome-car-rental' ); ?></span></label> 150 </li> 151 <li class="acrb-filter-item"> 152 <label><input type="checkbox" class="acrb-spec-filter" value="diesel"> <span><?php esc_html_e( 'Diesel', 'awesome-car-rental' ); ?></span></label> 153 </li> 154 <li class="acrb-filter-item"> 155 <label><input type="checkbox" class="acrb-spec-filter" value="electric"> <span><?php esc_html_e( 'Electric', 'awesome-car-rental' ); ?></span></label> 156 </li> 157 <li class="acrb-filter-item"> 158 <label><input type="checkbox" class="acrb-spec-filter" value="hybrid"> <span><?php esc_html_e( 'Hybrid', 'awesome-car-rental' ); ?></span></label> 159 </li> 160 </ul> 235 <h5 class="acrb-filter-subheading"><?php esc_html_e( 'Fuel / Power', 'awesome-car-rental' ); ?></h5> 236 <div class="acrb-chip-grid"> 237 <label class="acrb-chip-btn"> 238 <input type="checkbox" class="acrb-fuel-filter" value="petrol"> 239 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 240 <path d="M3 22V5a2 2 0 012-2h8a2 2 0 012 2v17"></path> 241 <path d="M15 9h2a2 2 0 012 2v2a2 2 0 002 2 2 2 0 002-2V9.5"></path> 242 </svg> 243 <span><?php esc_html_e( 'Petrol', 'awesome-car-rental' ); ?></span> 244 </label> 245 <label class="acrb-chip-btn"> 246 <input type="checkbox" class="acrb-fuel-filter" value="diesel"> 247 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 248 <path d="M12 2v20M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"></path> 249 </svg> 250 <span><?php esc_html_e( 'Diesel', 'awesome-car-rental' ); ?></span> 251 </label> 252 <label class="acrb-chip-btn"> 253 <input type="checkbox" class="acrb-fuel-filter" value="electric"> 254 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 255 <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon> 256 </svg> 257 <span><?php esc_html_e( 'Electric', 'awesome-car-rental' ); ?></span> 258 </label> 259 <label class="acrb-chip-btn"> 260 <input type="checkbox" class="acrb-fuel-filter" value="hybrid"> 261 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 262 <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> 263 </svg> 264 <span><?php esc_html_e( 'Hybrid', 'awesome-car-rental' ); ?></span> 265 </label> 266 </div> 161 267 </div> 162 268 </aside> … … 164 270 <!-- Right Side Content Area --> 165 271 <div class="acrb-right-content"> 166 <!-- Header Toolbar with View Mode Switches -->272 <!-- Header Toolbar with Count, Per Page, Sorter & View Mode Switches --> 167 273 <div class="acrb-content-header"> 168 274 <span class="acrb-result-count" id="acrb-result-count"> … … 172 278 ?> 173 279 </span> 174 <div class="acrb-view-toolbar"> 175 <button type="button" class="acrb-view-btn active" id="acrb-btn-grid" title="<?php esc_attr_e( 'Grid View', 'awesome-car-rental' ); ?>"> 176 <svg class="acrb-grid-icon" viewBox="0 0 24 24"> 177 <rect x="3" y="3" width="7" height="7"></rect> 178 <rect x="14" y="3" width="7" height="7"></rect> 179 <rect x="14" y="14" width="7" height="7"></rect> 180 <rect x="3" y="14" width="7" height="7"></rect> 181 </svg> 182 </button> 183 <button type="button" class="acrb-view-btn" id="acrb-btn-list" title="<?php esc_attr_e( 'List View', 'awesome-car-rental' ); ?>"> 184 <svg class="acrb-grid-icon" viewBox="0 0 24 24"> 185 <line x1="8" y1="6" x2="21" y2="6"></line> 186 <line x1="8" y1="12" x2="21" y2="12"></line> 187 <line x1="8" y1="18" x2="21" y2="18"></line> 188 <line x1="3" y1="6" x2="3.01" y2="6"></line> 189 <line x1="3" y1="12" x2="3.01" y2="12"></line> 190 <line x1="3" y1="18" x2="3.01" y2="18"></line> 191 </svg> 192 </button> 280 281 <div class="acrb-toolbar-actions"> 282 <!-- Per-Page Selector --> 283 <div class="acrb-select-group"> 284 <label for="acrb-per-page-select" class="acrb-select-label"><?php esc_html_e( 'Show:', 'awesome-car-rental' ); ?></label> 285 <select id="acrb-per-page-select" class="acrb-select-field" aria-label="<?php esc_attr_e( 'Items per page', 'awesome-car-rental' ); ?>"> 286 <option value="6">6</option> 287 <option value="9" selected>9</option> 288 <option value="12">12</option> 289 <option value="24">24</option> 290 <option value="all"><?php esc_html_e( 'All', 'awesome-car-rental' ); ?></option> 291 </select> 292 </div> 293 294 <!-- Sort Select --> 295 <div class="acrb-select-group"> 296 <select id="acrb-sort-select" class="acrb-select-field" aria-label="<?php esc_attr_e( 'Sort Vehicles', 'awesome-car-rental' ); ?>"> 297 <option value="default"><?php esc_html_e( 'Default Order', 'awesome-car-rental' ); ?></option> 298 <option value="price-asc"><?php esc_html_e( 'Price: Low to High', 'awesome-car-rental' ); ?></option> 299 <option value="price-desc"><?php esc_html_e( 'Price: High to Low', 'awesome-car-rental' ); ?></option> 300 <option value="title-asc"><?php esc_html_e( 'Name: A to Z', 'awesome-car-rental' ); ?></option> 301 </select> 302 </div> 303 304 <!-- Grid/List Switch --> 305 <div class="acrb-view-toolbar"> 306 <button type="button" class="acrb-view-btn active" id="acrb-btn-grid" aria-label="<?php esc_attr_e( 'Grid View', 'awesome-car-rental' ); ?>" title="<?php esc_attr_e( 'Grid View', 'awesome-car-rental' ); ?>"> 307 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2"> 308 <rect x="3" y="3" width="7" height="7" rx="1"></rect> 309 <rect x="14" y="3" width="7" height="7" rx="1"></rect> 310 <rect x="14" y="14" width="7" height="7" rx="1"></rect> 311 <rect x="3" y="14" width="7" height="7" rx="1"></rect> 312 </svg> 313 </button> 314 <button type="button" class="acrb-view-btn" id="acrb-btn-list" aria-label="<?php esc_attr_e( 'List View', 'awesome-car-rental' ); ?>" title="<?php esc_attr_e( 'List View', 'awesome-car-rental' ); ?>"> 315 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2"> 316 <line x1="8" y1="6" x2="21" y2="6"></line> 317 <line x1="8" y1="12" x2="21" y2="12"></line> 318 <line x1="8" y1="18" x2="21" y2="18"></line> 319 <line x1="3" y1="6" x2="3.01" y2="6"></line> 320 <line x1="3" y1="12" x2="3.01" y2="12"></line> 321 <line x1="3" y1="18" x2="3.01" y2="18"></line> 322 </svg> 323 </button> 324 </div> 193 325 </div> 194 326 </div> … … 197 329 <div class="acrb-car-grid" id="acrb-fleet-grid"> 198 330 <?php 331 $single_car_page_id = (int) get_option( 'acrb_single_car_page' ); 332 199 333 foreach ( $cars as $car ) : 200 334 $car_id = absint( $car['id'] ); … … 203 337 $car_year = absint( $car['year'] ?? 2026 ); 204 338 $full_title = trim( ( $car_brand ? $car_brand . ' ' : '' ) . $car_name . ( $car_year ? ' (' . $car_year . ')' : '' ) ); 205 206 339 $price_val = floatval( $car['price'] ?? 0.00 ); 207 340 … … 209 342 $cat_slug = sanitize_title( $category_name ); 210 343 211 $trans = (string) ( $car['transmission'] ?: 'Automatic' );212 $seats = absint( $car['seats'] ?: 5 );213 $fuel = (string) ( $car['fuel'] ?: 'Petrol' );214 $baggage = absint( $car['bags'] ?: 2 );215 216 $raw_img = (string) ( $car['image'] ?? '' );217 $thumb_url = '';344 $trans = (string) ( ! empty( $car['transmission'] ) ? $car['transmission'] : 'Automatic' ); 345 $seats = absint( ! empty( $car['seats'] ) ? $car['seats'] : 5 ); 346 $fuel = (string) ( ! empty( $car['fuel'] ) ? $car['fuel'] : 'Petrol' ); 347 $baggage = absint( ! empty( $car['bags'] ) ? $car['bags'] : 2 ); 348 349 $raw_img = (string) ( $car['image'] ?? '' ); 350 $thumb_url = ''; 218 351 if ( is_numeric( $raw_img ) && absint( $raw_img ) > 0 ) { 219 352 $thumb_url = wp_get_attachment_image_url( absint( $raw_img ), 'medium_large' ) ?: ''; … … 222 355 } 223 356 224 $single_car_page_id = get_option( 'acrb_single_car_page' );225 357 $link = $single_car_page_id 226 ? add_query_arg( 'car_id', $car_id, get_permalink( (int)$single_car_page_id ) )358 ? add_query_arg( 'car_id', $car_id, get_permalink( $single_car_page_id ) ) 227 359 : add_query_arg( array( 'sub' => 'view', 'car_id' => $car_id ), admin_url( 'admin.php?page=awesome_car_rental&tab=cars' ) ); 228 360 229 $searchable_text = strtolower( $full_title . ' ' . $trans . ' ' . $fuel . ' ' . $category_name );361 $searchable_text = strtolower( $full_title . ' ' . $trans . ' ' . $fuel . ' ' . $category_name . ' ' . $car_brand ); 230 362 ?> 231 363 <!-- Schema.org Structured Data --> … … 248 380 "@type": "Offer", 249 381 "price": "<?php echo esc_js( number_format( $price_val, 2, '.', '' ) ); ?>", 250 "priceCurrency": " GBP",382 "priceCurrency": "<?php echo esc_js( $currency_code ); ?>", 251 383 "eligibleQuantity": { 252 384 "@type": "QuantitativeValue", 253 385 "unitCode": "DAY", 254 "unitText": "Per Day"386 "unitText": "Per <?php echo esc_js( ucfirst( $rental_unit ) ); ?>" 255 387 } 256 388 } … … 259 391 260 392 <article class="acrb-car-card <?php echo esc_attr( $cat_slug ); ?>" 393 data-id="<?php echo esc_attr( (string) $car_id ); ?>" 261 394 data-search="<?php echo esc_attr( $searchable_text ); ?>" 395 data-title="<?php echo esc_attr( strtolower( $full_title ) ); ?>" 262 396 data-category="<?php echo esc_attr( $cat_slug ); ?>" 263 397 data-trans="<?php echo esc_attr( strtolower( $trans ) ); ?>" 264 data-fuel="<?php echo esc_attr( strtolower( $fuel ) ); ?>"> 398 data-fuel="<?php echo esc_attr( strtolower( $fuel ) ); ?>" 399 data-price="<?php echo esc_attr( (string) $price_val ); ?>"> 265 400 266 401 <!-- Media Header --> … … 268 403 <a href="<?php echo esc_url( $link ); ?>" title="<?php echo esc_attr( $full_title ); ?>"> 269 404 <?php if ( ! empty( $thumb_url ) ) : ?> 270 <img src="<?php echo esc_url( $thumb_url ); ?>" alt="<?php echo esc_attr( $full_title ); ?>" >405 <img src="<?php echo esc_url( $thumb_url ); ?>" alt="<?php echo esc_attr( $full_title ); ?>" loading="lazy"> 271 406 <?php else : ?> 272 407 <div class="acrb-no-thumb"> 273 <svg fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24" >408 <svg fill="none" stroke="currentColor" stroke-width="1.75" viewBox="0 0 24 24" width="38" height="38"> 274 409 <path d="M5 17h14v-5l-2-6H7l-2 6v5z"></path> 275 410 <circle cx="7.5" cy="17.5" r="2.5"></circle> … … 295 430 <div class="acrb-spec-grid"> 296 431 <div class="acrb-spec-item" title="<?php esc_attr_e( 'Transmission', 'awesome-car-rental' ); ?>"> 297 <svg class="acrb-grid-icon" viewBox="0 0 24 24" >432 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 298 433 <circle cx="12" cy="12" r="9"></circle> 299 434 <path d="M12 7v5l3 3"></path> … … 303 438 304 439 <div class="acrb-spec-item" title="<?php esc_attr_e( 'Seating Capacity', 'awesome-car-rental' ); ?>"> 305 <svg class="acrb-grid-icon" viewBox="0 0 24 24" >440 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 306 441 <path d="M16 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"></path> 307 442 <circle cx="12" cy="7" r="4"></circle> … … 311 446 312 447 <div class="acrb-spec-item" title="<?php esc_attr_e( 'Fuel Type', 'awesome-car-rental' ); ?>"> 313 <svg class="acrb-grid-icon" viewBox="0 0 24 24" >448 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 314 449 <path d="M3 22V5a2 2 0 012-2h8a2 2 0 012 2v17"></path> 315 450 <path d="M15 9h2a2 2 0 012 2v2a2 2 0 002 2 2 2 0 002-2V9.5"></path> … … 320 455 321 456 <div class="acrb-spec-item" title="<?php esc_attr_e( 'Luggage Allowance', 'awesome-car-rental' ); ?>"> 322 <svg class="acrb-grid-icon" viewBox="0 0 24 24" >457 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 323 458 <rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect> 324 459 <path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16"></path> … … 338 473 <a href="<?php echo esc_url( $link ); ?>" class="acrb-btn-book"> 339 474 <span><?php esc_html_e( 'Rent Now', 'awesome-car-rental' ); ?></span> 340 <svg class="acrb-grid-icon" viewBox="0 0 24 24" >475 <svg class="acrb-grid-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 341 476 <path d="M5 12h14m-7-7l7 7-7 7"></path> 342 477 </svg> … … 347 482 <?php endforeach; ?> 348 483 349 <div id="acrb-no-cars-msg" class="acrb-no-cars-msg" >350 <svg class="acrb-grid-icon acrb-no-cars-icon" viewBox="0 0 24 24" >484 <div id="acrb-no-cars-msg" class="acrb-no-cars-msg" style="display: none;"> 485 <svg class="acrb-grid-icon acrb-no-cars-icon" viewBox="0 0 24 24" width="52" height="52" fill="none" stroke="currentColor" stroke-width="1.5"> 351 486 <circle cx="11" cy="11" r="8"></circle> 352 487 <line x1="21" y1="21" x2="16.65" y2="16.65"></line> 353 488 </svg> 354 489 <h3 class="acrb-no-cars-title"><?php esc_html_e( 'No vehicles found', 'awesome-car-rental' ); ?></h3> 355 <p class="acrb-no-cars-desc"><?php esc_html_e( 'Try clearing your filters or search query.', 'awesome-car-rental' ); ?></p> 490 <p class="acrb-no-cars-desc"><?php esc_html_e( 'Try clearing your filters or search query to see available fleet options.', 'awesome-car-rental' ); ?></p> 491 <button type="button" class="acrb-btn-clear-empty" id="acrb-empty-reset-btn"><?php esc_html_e( 'Reset All Filters', 'awesome-car-rental' ); ?></button> 356 492 </div> 357 493 </div> 494 495 <!-- Numbered Pagination Controls --> 496 <div class="acrb-pagination-container" id="acrb-pagination-container"></div> 358 497 </div> 359 498 </div> … … 362 501 <script> 363 502 document.addEventListener('DOMContentLoaded', function() { 364 const searchInput = document.getElementById('acrb-filter-search'); 365 const catCheckboxes = document.querySelectorAll('.acrb-cat-filter'); 366 const specCheckboxes = document.querySelectorAll('.acrb-spec-filter'); 367 const cards = document.querySelectorAll('.acrb-car-card'); 368 const countDisplay = document.getElementById('acrb-result-count'); 369 const noCarsMsg = document.getElementById('acrb-no-cars-msg'); 370 371 const btnGrid = document.getElementById('acrb-btn-grid'); 372 const btnList = document.getElementById('acrb-btn-list'); 373 const fleetGrid = document.getElementById('acrb-fleet-grid'); 503 const searchInput = document.getElementById('acrb-filter-search'); 504 const catCheckboxes = document.querySelectorAll('.acrb-cat-filter'); 505 const transCheckboxes = document.querySelectorAll('.acrb-trans-filter'); 506 const fuelCheckboxes = document.querySelectorAll('.acrb-fuel-filter'); 507 const priceSlider = document.getElementById('acrb-price-range'); 508 const priceDisplay = document.getElementById('acrb-price-display'); 509 const sortSelect = document.getElementById('acrb-sort-select'); 510 const perPageSelect = document.getElementById('acrb-per-page-select'); 511 const countDisplay = document.getElementById('acrb-result-count'); 512 const noCarsMsg = document.getElementById('acrb-no-cars-msg'); 513 const resetBtn = document.getElementById('acrb-reset-filters-btn'); 514 const emptyResetBtn = document.getElementById('acrb-empty-reset-btn'); 515 516 const btnGrid = document.getElementById('acrb-btn-grid'); 517 const btnList = document.getElementById('acrb-btn-list'); 518 const fleetGrid = document.getElementById('acrb-fleet-grid'); 519 const pagination = document.getElementById('acrb-pagination-container'); 520 521 const mobileToggleBtn = document.getElementById('acrb-mobile-filter-toggle'); 522 const sidebar = document.getElementById('acrb-filter-sidebar'); 523 const mobileBadge = document.getElementById('acrb-mobile-filter-badge'); 524 525 const currencySymbol = <?php echo wp_json_encode( $currency_symbol ); ?>; 526 const currencyPos = <?php echo wp_json_encode( $currency_pos ); ?>; 527 528 let currentPage = 1; 529 let matchedCards = []; 530 531 function formatCurrency(val) { 532 const formatted = parseFloat(val).toFixed(2); 533 return currencyPos === 'left' ? currencySymbol + formatted : formatted + currencySymbol; 534 } 535 536 // Mobile Filter Drawer Toggle 537 if (mobileToggleBtn && sidebar) { 538 mobileToggleBtn.addEventListener('click', function() { 539 sidebar.classList.toggle('is-open'); 540 }); 541 } 374 542 375 543 // View Mode Switcher … … 387 555 } 388 556 389 function applyFilters() { 390 const query = searchInput ? searchInput.value.toLowerCase().trim() : ''; 391 const selectedCats = Array.from(catCheckboxes).filter(i => i.checked).map(i => i.value); 392 const selectedSpecs = Array.from(specCheckboxes).filter(i => i.checked).map(i => i.value); 393 394 let visible = 0; 395 396 cards.forEach(card => { 397 const text = card.getAttribute('data-search') || ''; 398 const cat = card.getAttribute('data-category') || ''; 399 const trans = card.getAttribute('data-trans') || ''; 400 const fuel = card.getAttribute('data-fuel') || ''; 401 402 const matchesSearch = !query || text.includes(query); 403 const matchesCat = selectedCats.length === 0 || selectedCats.includes(cat); 404 405 let matchesSpec = true; 406 if (selectedSpecs.length > 0) { 407 matchesSpec = selectedSpecs.every(spec => { 408 return trans.includes(spec) || fuel.includes(spec); 409 }); 410 } 411 412 if (matchesSearch && matchesCat && matchesSpec) { 413 card.style.display = 'flex'; 414 visible++; 557 // Price Slider Live Counter & Track Gradient 558 if (priceSlider && priceDisplay) { 559 function updateSliderTrack() { 560 const max = parseFloat(priceSlider.max) || 100; 561 const val = parseFloat(priceSlider.value) || 0; 562 const percentage = (val / max) * 100; 563 priceSlider.style.background = `linear-gradient(to right, var(--acrb-grid-primary, #4f46e5) 0%, var(--acrb-grid-primary, #4f46e5) ${percentage}%, #e2e8f0 ${percentage}%, #e2e8f0 100%)`; 564 priceDisplay.textContent = formatCurrency(priceSlider.value); 565 } 566 567 priceSlider.addEventListener('input', updateSliderTrack); 568 updateSliderTrack(); 569 } 570 571 // Card Sorter 572 function sortCards() { 573 if (!sortSelect || !fleetGrid) return; 574 575 const mode = sortSelect.value; 576 const cardArray = Array.from(fleetGrid.querySelectorAll('.acrb-car-card')); 577 578 cardArray.sort(function(a, b) { 579 if (mode === 'price-asc') { 580 return parseFloat(a.getAttribute('data-price') || 0) - parseFloat(b.getAttribute('data-price') || 0); 581 } else if (mode === 'price-desc') { 582 return parseFloat(b.getAttribute('data-price') || 0) - parseFloat(a.getAttribute('data-price') || 0); 583 } else if (mode === 'title-asc') { 584 return (a.getAttribute('data-title') || '').localeCompare(b.getAttribute('data-title') || ''); 415 585 } else { 416 card.style.display = 'none';586 return parseInt(b.getAttribute('data-id') || 0, 10) - parseInt(a.getAttribute('data-id') || 0, 10); 417 587 } 418 588 }); 419 589 590 cardArray.forEach(function(card) { 591 fleetGrid.appendChild(card); 592 }); 593 } 594 595 // Render Cards with Pagination Page Chunking 596 function renderPagination() { 597 const allCards = fleetGrid.querySelectorAll('.acrb-car-card'); 598 const perPageVal = perPageSelect ? perPageSelect.value : '9'; 599 const perPage = perPageVal === 'all' ? matchedCards.length : parseInt(perPageVal, 10); 600 const totalMatched = matchedCards.length; 601 const totalPages = perPage > 0 ? Math.ceil(totalMatched / perPage) : 1; 602 603 if (currentPage > totalPages) { 604 currentPage = Math.max(1, totalPages); 605 } 606 607 // Hide all first 608 allCards.forEach(c => c.style.display = 'none'); 609 610 // Show current page items 611 if (perPageVal === 'all') { 612 matchedCards.forEach(c => c.style.display = ''); 613 } else { 614 const start = (currentPage - 1) * perPage; 615 const end = start + perPage; 616 matchedCards.slice(start, end).forEach(c => c.style.display = ''); 617 } 618 619 // Build Pagination Buttons 620 if (!pagination) return; 621 pagination.innerHTML = ''; 622 623 if (totalPages <= 1 || perPageVal === 'all') { 624 pagination.style.display = 'none'; 625 return; 626 } 627 628 pagination.style.display = 'flex'; 629 630 // Previous Button 631 const prevBtn = document.createElement('button'); 632 prevBtn.className = 'acrb-page-btn'; 633 prevBtn.innerHTML = '‹'; 634 prevBtn.disabled = currentPage === 1; 635 prevBtn.addEventListener('click', function() { 636 if (currentPage > 1) { 637 currentPage--; 638 renderPagination(); 639 scrollToTop(); 640 } 641 }); 642 pagination.appendChild(prevBtn); 643 644 // Generate Number Range with Smart Ellipses 645 const delta = 1; 646 const range = []; 647 for (let i = 1; i <= totalPages; i++) { 648 if (i === 1 || i === totalPages || (i >= currentPage - delta && i <= currentPage + delta)) { 649 range.push(i); 650 } 651 } 652 653 let l; 654 for (let i of range) { 655 if (l) { 656 if (i - l === 2) { 657 const numBtn = createPageBtn(l + 1); 658 pagination.appendChild(numBtn); 659 } else if (i - l !== 1) { 660 const span = document.createElement('span'); 661 span.className = 'acrb-page-ellipsis'; 662 span.textContent = '...'; 663 pagination.appendChild(span); 664 } 665 } 666 pagination.appendChild(createPageBtn(i)); 667 l = i; 668 } 669 670 // Next Button 671 const nextBtn = document.createElement('button'); 672 nextBtn.className = 'acrb-page-btn'; 673 nextBtn.innerHTML = '›'; 674 nextBtn.disabled = currentPage === totalPages; 675 nextBtn.addEventListener('click', function() { 676 if (currentPage < totalPages) { 677 currentPage++; 678 renderPagination(); 679 scrollToTop(); 680 } 681 }); 682 pagination.appendChild(nextBtn); 683 } 684 685 function createPageBtn(pageNum) { 686 const btn = document.createElement('button'); 687 btn.className = 'acrb-page-btn' + (pageNum === currentPage ? ' active' : ''); 688 btn.textContent = pageNum; 689 btn.addEventListener('click', function() { 690 currentPage = pageNum; 691 renderPagination(); 692 scrollToTop(); 693 }); 694 return btn; 695 } 696 697 function scrollToTop() { 698 fleetGrid.scrollIntoView({ behavior: 'smooth', block: 'start' }); 699 } 700 701 // Apply Search & Taxonomy Filters 702 function applyFilters(resetPage = true) { 703 if (resetPage) { 704 currentPage = 1; 705 } 706 707 const cards = fleetGrid.querySelectorAll('.acrb-car-card'); 708 const query = searchInput ? searchInput.value.toLowerCase().trim() : ''; 709 const selectedCats = Array.from(catCheckboxes).filter(i => i.checked).map(i => i.value); 710 const selectedTrans = Array.from(transCheckboxes).filter(i => i.checked).map(i => i.value); 711 const selectedFuel = Array.from(fuelCheckboxes).filter(i => i.checked).map(i => i.value); 712 const maxPrice = priceSlider ? parseFloat(priceSlider.value) : Infinity; 713 714 const activeFilterCount = (query ? 1 : 0) + selectedCats.length + selectedTrans.length + selectedFuel.length + (priceSlider && priceSlider.value < priceSlider.max ? 1 : 0); 715 716 if (mobileBadge) { 717 if (activeFilterCount > 0) { 718 mobileBadge.textContent = activeFilterCount; 719 mobileBadge.style.display = 'inline-block'; 720 } else { 721 mobileBadge.style.display = 'none'; 722 } 723 } 724 725 matchedCards = []; 726 727 cards.forEach(function(card) { 728 const text = card.getAttribute('data-search') || ''; 729 const cat = card.getAttribute('data-category') || ''; 730 const trans = card.getAttribute('data-trans') || ''; 731 const fuel = card.getAttribute('data-fuel') || ''; 732 const price = parseFloat(card.getAttribute('data-price') || 0); 733 734 const matchesSearch = !query || text.includes(query); 735 const matchesCat = selectedCats.length === 0 || selectedCats.includes(cat); 736 const matchesTrans = selectedTrans.length === 0 || selectedTrans.includes(trans); 737 const matchesFuel = selectedFuel.length === 0 || selectedFuel.includes(fuel); 738 const matchesPrice = price <= maxPrice; 739 740 if (matchesSearch && matchesCat && matchesTrans && matchesFuel && matchesPrice) { 741 matchedCards.push(card); 742 } 743 }); 744 420 745 if (countDisplay) { 421 countDisplay.textContent = "<?php esc_html_e( 'Showing', 'awesome-car-rental' ); ?> " + visible + " <?php esc_html_e( 'of', 'awesome-car-rental' ); ?> " + cards.length + " <?php esc_html_e( 'vehicles', 'awesome-car-rental' ); ?>"; 422 } 746 countDisplay.textContent = "<?php esc_html_e( 'Showing', 'awesome-car-rental' ); ?> " + matchedCards.length + " <?php esc_html_e( 'of', 'awesome-car-rental' ); ?> " + cards.length + " <?php esc_html_e( 'vehicles', 'awesome-car-rental' ); ?>"; 747 } 748 423 749 if (noCarsMsg) { 424 noCarsMsg.style.display = visible === 0 ? 'block' : 'none'; 425 } 426 } 427 428 if (searchInput) searchInput.addEventListener('input', applyFilters); 429 catCheckboxes.forEach(cb => cb.addEventListener('change', applyFilters)); 430 specCheckboxes.forEach(cb => cb.addEventListener('change', applyFilters)); 750 noCarsMsg.style.display = matchedCards.length === 0 ? 'block' : 'none'; 751 } 752 753 renderPagination(); 754 } 755 756 function resetAllFilters() { 757 if (searchInput) searchInput.value = ''; 758 catCheckboxes.forEach(cb => cb.checked = false); 759 transCheckboxes.forEach(cb => cb.checked = false); 760 fuelCheckboxes.forEach(cb => cb.checked = false); 761 762 if (priceSlider && priceDisplay) { 763 priceSlider.value = priceSlider.max; 764 priceSlider.style.background = `linear-gradient(to right, var(--acrb-grid-primary, #4f46e5) 0%, var(--acrb-grid-primary, #4f46e5) 100%, #e2e8f0 100%, #e2e8f0 100%)`; 765 priceDisplay.textContent = formatCurrency(priceSlider.max); 766 } 767 if (sortSelect) { 768 sortSelect.value = 'default'; 769 } 770 if (perPageSelect) { 771 perPageSelect.value = '9'; 772 } 773 774 sortCards(); 775 applyFilters(true); 776 } 777 778 // Event Listeners 779 if (searchInput) searchInput.addEventListener('input', () => applyFilters(true)); 780 if (priceSlider) priceSlider.addEventListener('change', () => applyFilters(true)); 781 if (sortSelect) sortSelect.addEventListener('change', function() { 782 sortCards(); 783 applyFilters(false); 784 }); 785 if (perPageSelect) perPageSelect.addEventListener('change', () => applyFilters(true)); 786 787 catCheckboxes.forEach(cb => cb.addEventListener('change', () => applyFilters(true))); 788 transCheckboxes.forEach(cb => cb.addEventListener('change', () => applyFilters(true))); 789 fuelCheckboxes.forEach(cb => cb.addEventListener('change', () => applyFilters(true))); 790 791 if (resetBtn) resetBtn.addEventListener('click', resetAllFilters); 792 if (emptyResetBtn) emptyResetBtn.addEventListener('click', resetAllFilters); 793 794 // Initial Run 795 applyFilters(true); 431 796 }); 432 797 </script> -
awesome-car-rental/trunk/frontend/checkout/acrb-frontned-checkout.php
r3775773 r3777386 30 30 $table_bookings = $wpdb->prefix . 'dev_nahian_bookings'; 31 31 $table_cars = $wpdb->prefix . 'dev_nahian_cars'; 32 $table_promos = $wpdb->prefix . 'dev_nahian_promo_codes'; 32 33 33 34 $acrb_car_id = isset( $_POST['car_id'] ) ? absint( wp_unslash( $_POST['car_id'] ) ) : 0; … … 39 40 $acrb_pickup_date = isset( $_POST['pickup_date'] ) ? sanitize_text_field( wp_unslash( $_POST['pickup_date'] ) ) : gmdate( 'Y-m-d H:i' ); 40 41 $acrb_return_date = isset( $_POST['return_date'] ) ? sanitize_text_field( wp_unslash( $_POST['return_date'] ) ) : gmdate( 'Y-m-d H:i', strtotime( '+3 days' ) ); 41 $acrb_total = isset( $_POST['order_total'] ) ? floatval( wp_unslash( $_POST['order_total'] ) ) : 0.0;42 42 $acrb_method = isset( $_POST['payment_method'] ) ? sanitize_text_field( wp_unslash( $_POST['payment_method'] ) ) : 'pay_later'; 43 43 44 44 $acrb_insurance = isset( $_POST['insurance_plan'] ) ? sanitize_text_field( wp_unslash( $_POST['insurance_plan'] ) ) : ''; 45 45 $acrb_border = isset( $_POST['border_permit'] ) ? sanitize_text_field( wp_unslash( $_POST['border_permit'] ) ) : ''; 46 $acrb_promo = isset( $_POST['promo_code'] ) ? s anitize_text_field( wp_unslash( $_POST['promo_code']) ) : '';46 $acrb_promo = isset( $_POST['promo_code'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_POST['promo_code'] ) ) ) : ''; 47 47 48 48 if ( $acrb_car_id > 0 && ! empty( $acrb_pickup_date ) && ! empty( $acrb_return_date ) ) { 49 49 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 50 $car_record = $wpdb->get_row( $wpdb->prepare( "SELECT name, brand FROM {$table_cars} WHERE id = %d", $acrb_car_id ), ARRAY_A ); 51 $car_title = $car_record ? trim( ( $car_record['brand'] ?? '' ) . ' ' . $car_record['name'] ) : __( 'Fleet Vehicle', 'awesome-car-rental' ); 52 53 $booking_code = 'BK-' . gmdate( 'Y' ) . '-' . wp_rand( 1000, 9999 ); 50 $car = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_cars} WHERE id = %d", $acrb_car_id ), ARRAY_A ); 51 $car_title = $car ? trim( ( $car['brand'] ?? '' ) . ' ' . $car['name'] ) : __( 'Fleet Vehicle', 'awesome-car-rental' ); 52 53 // Calculate verified dates & rental duration (Fixed multiplication syntax) 54 $start_time = strtotime( $acrb_pickup_date ); 55 $end_time = strtotime( $acrb_return_date ); 56 $diff_hrs = ( $end_time && $start_time && $end_time > $start_time ) ? ( $end_time - $start_time ) / 3600 : 24; 57 $min_days = max( 1, absint( $car['min_days'] ?? 1 ) ); 58 $acrb_days = max( $min_days, (int) ceil( $diff_hrs / 24 ) ); 59 60 $daily_rate = floatval( $car['price'] ?? 0.0 ); 61 $base_subtotal = $acrb_days * $daily_rate; 62 $security_deposit = floatval( $car['security_deposit'] ?? 0.0 ); 63 $insurance_fee = floatval( $car['insurance_fee'] ?? 0.0 ); 64 65 // Addon Insurance 66 $ins_cost = 0.0; 67 $car_insurance_json = ! empty( $car['insurance_plans'] ) ? json_decode( (string) $car['insurance_plans'], true ) : array(); 68 if ( ! empty( $acrb_insurance ) && is_array( $car_insurance_json ) ) { 69 foreach ( $car_insurance_json as $ins ) { 70 if ( ( $ins['name'] ?? '' ) === $acrb_insurance ) { 71 $p = floatval( $ins['price'] ?? 0 ); 72 $t = $ins['type'] ?? 'day'; 73 $ins_cost = ( 'day' === $t ) ? ( $p * $acrb_days ) : $p; 74 break; 75 } 76 } 77 } 78 79 // Addon Border 80 $border_cost = 0.0; 81 $car_border_json = ! empty( $car['border_crossing'] ) ? json_decode( (string) $car['border_crossing'], true ) : array(); 82 if ( ! empty( $acrb_border ) && is_array( $car_border_json ) ) { 83 foreach ( $car_border_json as $b ) { 84 if ( ( $b['country'] ?? '' ) === $acrb_border ) { 85 $f = floatval( $b['fee'] ?? 0 ); 86 $t = $b['type'] ?? 'flat'; 87 $border_cost = ( 'day' === $t ) ? ( $f * $acrb_days ) : $f; 88 break; 89 } 90 } 91 } 92 93 $applicable_subtotal = $base_subtotal + $ins_cost + $border_cost; 94 $discount_amt = 0.0; 95 96 // Verify promo code server-side 97 if ( ! empty( $acrb_promo ) ) { 98 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 99 $db_promo = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_promos} WHERE code = %s AND status = 'active'", $acrb_promo ), ARRAY_A ); 100 if ( $db_promo ) { 101 $today = gmdate( 'Y-m-d' ); 102 $p_expiry = (string) ( $db_promo['expiry_date'] ?? '' ); 103 $min_spend = floatval( $db_promo['min_spend'] ?? 0 ); 104 105 if ( ( empty( $p_expiry ) || $p_expiry >= $today ) && $applicable_subtotal >= $min_spend ) { 106 $p_val = floatval( $db_promo['discount_value'] ?? 0 ); 107 $p_type = $db_promo['discount_type'] ?? 'fixed'; 108 if ( 'percentage' === $p_type ) { 109 $discount_amt = $applicable_subtotal * ( $p_val / 100 ); 110 } else { 111 $discount_amt = $p_val; 112 } 113 $discount_amt = min( $discount_amt, $applicable_subtotal ); 114 } 115 } 116 } 117 118 $computed_grand_total = ( $applicable_subtotal - $discount_amt ) + $security_deposit + $insurance_fee; 119 $booking_code = 'BK-' . gmdate( 'Y' ) . '-' . wp_rand( 1000, 9999 ); 54 120 55 121 // Insert complete data directly into custom database table … … 58 124 $table_bookings, 59 125 array( 60 'booking_code' => $booking_code, 61 'car_id' => absint( $acrb_car_id ), 62 'car_name' => $car_title, 63 'customer_name' => $acrb_cus_name, 64 'customer_email' => $acrb_cus_email, 65 'customer_phone' => $acrb_cus_phone, 66 'pickup_location' => $acrb_pickup_loc, 67 'return_location' => $acrb_return_loc, 68 'pickup_date' => $acrb_pickup_date, 69 'return_date' => $acrb_return_date, 70 'insurance_plan' => $acrb_insurance, 71 'border_permit' => $acrb_border, 72 'promo_code' => $acrb_promo, 73 'total_amount' => $acrb_total, 74 'payment_method' => $acrb_method, 75 'booking_status' => 'pending', 76 'created_at' => current_time( 'mysql' ), 126 'booking_code' => $booking_code, 127 'car_id' => absint( $acrb_car_id ), 128 'car_name' => $car_title, 129 'customer_name' => $acrb_cus_name, 130 'customer_email' => $acrb_cus_email, 131 'customer_phone' => $acrb_cus_phone, 132 'pickup_location' => $acrb_pickup_loc, 133 'return_location' => $acrb_return_loc, 134 'pickup_date' => $acrb_pickup_date, 135 'return_date' => $acrb_return_date, 136 'insurance_plan' => $acrb_insurance, 137 'insurance_amount' => $ins_cost, 138 'border_permit' => $acrb_border, 139 'border_amount' => $border_cost, 140 'promo_code' => $acrb_promo, 141 'discount_amount' => $discount_amt, 142 'base_subtotal' => $base_subtotal, 143 'total_amount' => $computed_grand_total, 144 'payment_method' => $acrb_method, 145 'booking_status' => 'pending', 146 'created_at' => current_time( 'mysql' ), 77 147 ), 78 array( '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '% s', '%s', '%f', '%s', '%s', '%s' )148 array( '%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%f', '%s', '%f', '%s', '%f', '%f', '%f', '%s', '%s', '%s' ) 79 149 ); 80 150 … … 83 153 delete_transient( 'acrb_dashboard_revenue' ); 84 154 85 $acrb_redirect_url = home_url( '/acrb-thanks/?booking_id=' . $acrb_booking_id ); 155 $acrb_redirect_url = add_query_arg( 156 array( 157 'booking_id' => $acrb_booking_id, 158 'code' => $booking_code, 159 ), 160 home_url( '/acrb-thanks/' ) 161 ); 162 86 163 wp_safe_redirect( $acrb_redirect_url ); 87 164 exit; … … 117 194 $acrb_selected_font = $acrb_font_stacks[ $acrb_font_slug ] ?? $acrb_font_stacks['jakarta']; 118 195 119 // Scoped CSS properties string without :root 120 $scoped_styles = sprintf( 121 '--acrb-checkout-primary:%s;--acrb-checkout-secondary:%s;--acrb-checkout-text:%s;--acrb-checkout-accent:%s;--acrb-checkout-btn-bg:%s;--acrb-checkout-btn-hover:%s;--acrb-checkout-font:%s;', 196 // Inject dynamic CSS custom properties via wp_add_inline_style 197 $custom_css = sprintf( 198 '.acrb-checkout-wrapper, .acrb-checkout-error { 199 --acrb-checkout-primary: %s; 200 --acrb-checkout-secondary: %s; 201 --acrb-checkout-text: %s; 202 --acrb-checkout-accent: %s; 203 --acrb-checkout-btn-bg: %s; 204 --acrb-checkout-btn-hover: %s; 205 --acrb-checkout-font: %s; 206 }', 122 207 esc_attr( $acrb_primary_color ), 123 208 esc_attr( $acrb_secondary_color ), … … 128 213 esc_attr( $acrb_selected_font ) 129 214 ); 215 wp_add_inline_style( 'acrb-checkout-style', $custom_css ); 130 216 131 217 // 3. User Authentication Gate 132 218 if ( ! is_user_logged_in() ) { 133 219 $acrb_login_page_url = home_url( '/acrb-login/' ); 134 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized135 220 $acrb_request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; 136 221 $acrb_final_url = add_query_arg( 'redirect_to', rawurlencode( home_url( $acrb_request_uri ) ), $acrb_login_page_url ); … … 139 224 ?> 140 225 <script>window.location.href=<?php echo wp_json_encode( esc_url_raw( $acrb_final_url ) ); ?>;</script> 141 <div class="acrb-redirect-notice" style="<?php echo esc_attr( $scoped_styles ); ?>">142 < ?php esc_html_e( 'Redirecting to secure login portal...', 'awesome-car-rental' ); ?>226 <div class="acrb-redirect-notice"> 227 <p><?php esc_html_e( 'Redirecting to secure login portal...', 'awesome-car-rental' ); ?></p> 143 228 </div> 144 229 <?php … … 165 250 166 251 // Retrieve GET parameters from booking flow 167 // phpcs: ignore WordPress.Security.NonceVerification.Recommended252 // phpcs:disable WordPress.Security.NonceVerification.Recommended 168 253 $acrb_car_id = isset( $_GET['car_id'] ) ? absint( wp_unslash( $_GET['car_id'] ) ) : 0; 169 // phpcs:ignore WordPress.Security.NonceVerification.Recommended170 254 $acrb_pickup_date = isset( $_GET['pdate'] ) ? sanitize_text_field( wp_unslash( $_GET['pdate'] ) ) : gmdate( 'Y-m-d' ); 171 // phpcs:ignore WordPress.Security.NonceVerification.Recommended172 255 $acrb_pickup_time = isset( $_GET['ptime'] ) ? sanitize_text_field( wp_unslash( $_GET['ptime'] ) ) : '10:00'; 173 // phpcs:ignore WordPress.Security.NonceVerification.Recommended174 256 $acrb_return_date = isset( $_GET['rdate'] ) ? sanitize_text_field( wp_unslash( $_GET['rdate'] ) ) : gmdate( 'Y-m-d', strtotime( '+3 days' ) ); 175 // phpcs:ignore WordPress.Security.NonceVerification.Recommended176 257 $acrb_return_time = isset( $_GET['rtime'] ) ? sanitize_text_field( wp_unslash( $_GET['rtime'] ) ) : '10:00'; 177 // phpcs:ignore WordPress.Security.NonceVerification.Recommended178 258 $acrb_pickup_loc = isset( $_GET['ploc'] ) ? sanitize_text_field( wp_unslash( $_GET['ploc'] ) ) : __( 'Main Terminal', 'awesome-car-rental' ); 179 // phpcs:ignore WordPress.Security.NonceVerification.Recommended180 259 $acrb_return_loc = isset( $_GET['dloc'] ) ? sanitize_text_field( wp_unslash( $_GET['dloc'] ) ) : $acrb_pickup_loc; 181 // phpcs:ignore WordPress.Security.NonceVerification.Recommended182 260 $acrb_sel_ins = isset( $_GET['acrb_selected_insurance'] ) ? sanitize_text_field( wp_unslash( $_GET['acrb_selected_insurance'] ) ) : ''; 183 // phpcs:ignore WordPress.Security.NonceVerification.Recommended184 261 $acrb_sel_border = isset( $_GET['acrb_selected_border'] ) ? sanitize_text_field( wp_unslash( $_GET['acrb_selected_border'] ) ) : ''; 185 // phpcs:ignore WordPress.Security.NonceVerification.Recommended186 262 $acrb_pass_method = isset( $_GET['pmethod'] ) ? sanitize_text_field( wp_unslash( $_GET['pmethod'] ) ) : key( $acrb_enabled_methods ); 263 // phpcs:enable WordPress.Security.NonceVerification.Recommended 187 264 188 265 if ( ! array_key_exists( $acrb_pass_method, $acrb_enabled_methods ) ) { … … 205 282 ob_start(); 206 283 ?> 207 <div class="acrb-checkout-error" style="<?php echo esc_attr( $scoped_styles ); ?>">284 <div class="acrb-checkout-error"> 208 285 <h3><?php esc_html_e( 'Fleet Inventory Empty', 'awesome-car-rental' ); ?></h3> 209 286 <p><?php esc_html_e( 'No active vehicles found in your database. Please add a car in your admin dashboard first.', 'awesome-car-rental' ); ?></p> … … 223 300 $acrb_insurance_fee = floatval( $car['insurance_fee'] ?? 0.00 ); 224 301 225 $acrb_currency = get_option( 'acrb_currency', '£' ); 226 $acrb_rental_unit = get_option( 'acrb_rental_unit', 'day' ); 227 228 $start_dt = new DateTime( $acrb_pickup_date . ' ' . $acrb_pickup_time ); 229 $end_dt = new DateTime( $acrb_return_date . ' ' . $acrb_return_time ); 230 $diff_hrs = ( $end_dt->getTimestamp() - $start_dt->getTimestamp() ) / 3600; 231 $acrb_days = max( 1, (int) ceil( $diff_hrs / 24 ) ); 302 $acrb_currency = (string) get_option( 'acrb_currency', '£' ); 303 $acrb_rental_unit = (string) get_option( 'acrb_rental_unit', 'day' ); 304 305 $start_dt = new DateTime( $acrb_pickup_date . ' ' . $acrb_pickup_time ); 306 $end_dt = new DateTime( $acrb_return_date . ' ' . $acrb_return_time ); 307 $diff_hrs = ( $end_dt->getTimestamp() - $start_dt->getTimestamp() ) / 3600; 232 308 233 // Calculate rental subtotal 309 $min_rental_days = max( 1, absint( $car['min_days'] ?? 1 ) ); 310 $acrb_days = max( $min_rental_days, (int) ceil( $diff_hrs / 24 ) ); 311 312 // Calculate rental subtotal (Fixed multiplication syntax) 234 313 $acrb_subtotal = $acrb_days * $acrb_price; 235 314 … … 284 363 'value' => floatval( $p['discount_value'] ), 285 364 'min_spend' => floatval( $p['min_spend'] ), 286 'expiry' => $p['expiry_date'],365 'expiry' => (string) $p['expiry_date'], 287 366 ); 288 367 } … … 291 370 ob_start(); 292 371 ?> 293 <div class="acrb-checkout-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>"> 372 <div class="acrb-checkout-wrapper"> 373 <!-- Stepper Header --> 294 374 <div class="acrb-checkout-steps"> 295 <div class="acrb-step-item"><div class="acrb-step-num">✓</div><span><?php esc_html_e( '1. Select Vehicle', 'awesome-car-rental' ); ?></span></div> 296 <div class="acrb-step-item active"><div class="acrb-step-num">2</div><span><?php esc_html_e( '2. Review & Secure Checkout', 'awesome-car-rental' ); ?></span></div> 297 <div class="acrb-step-item"><div class="acrb-step-num">3</div><span><?php esc_html_e( '3. Instant Handover Confirmation', 'awesome-car-rental' ); ?></span></div> 375 <div class="acrb-step-item completed"> 376 <div class="acrb-step-num"> 377 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"></polyline></svg> 378 </div> 379 <span><?php esc_html_e( '1. Select Vehicle', 'awesome-car-rental' ); ?></span> 380 </div> 381 <div class="acrb-step-item active"> 382 <div class="acrb-step-num">2</div> 383 <span><?php esc_html_e( '2. Review & Secure Checkout', 'awesome-car-rental' ); ?></span> 384 </div> 385 <div class="acrb-step-item"> 386 <div class="acrb-step-num">3</div> 387 <span><?php esc_html_e( '3. Instant Handover Confirmation', 'awesome-car-rental' ); ?></span> 388 </div> 298 389 </div> 299 390 … … 317 408 <!-- Left Column --> 318 409 <div> 410 <!-- Vehicle & Itinerary Review --> 319 411 <div class="acrb-checkout-card"> 320 412 <h2 class="acrb-checkout-title"> 321 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" ><path d="M5 17h14v-5l-2-6H7l-2 6v5z"></path><circle cx="7.5" cy="17.5" r="2.5"></circle><circle cx="16.5" cy="17.5" r="2.5"></circle></svg>413 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M5 17h14v-5l-2-6H7l-2 6v5z"></path><circle cx="7.5" cy="17.5" r="2.5"></circle><circle cx="16.5" cy="17.5" r="2.5"></circle></svg> 322 414 <span><?php esc_html_e( 'Review Vehicle & Itinerary', 'awesome-car-rental' ); ?></span> 323 415 </h2> … … 339 431 340 432 <div class="acrb-itinerary-grid"> 341 <div class="acrb-itinerary-pill"> 342 <span class="acrb-itinerary-schedule-title"><?php esc_html_e( 'Pickup Schedule', 'awesome-car-rental' ); ?></span> 343 <strong><?php echo esc_html( $acrb_pickup_date . ' @ ' . $acrb_pickup_time ); ?></strong> 344 <span class="acrb-itinerary-location">(<?php echo esc_html( $acrb_pickup_loc ); ?>)</span> 345 </div> 346 <div class="acrb-itinerary-pill"> 347 <span class="acrb-itinerary-schedule-title"><?php esc_html_e( 'Return Schedule', 'awesome-car-rental' ); ?></span> 348 <strong><?php echo esc_html( $acrb_return_date . ' @ ' . $acrb_return_time ); ?></strong> 349 <span class="acrb-itinerary-location">(<?php echo esc_html( $acrb_return_loc ); ?>)</span> 433 <!-- Pickup Schedule Pill --> 434 <div class="acrb-itinerary-pill pickup"> 435 <div class="acrb-itinerary-header"> 436 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg> 437 <span><?php esc_html_e( 'Pickup Schedule', 'awesome-car-rental' ); ?></span> 438 </div> 439 <div class="acrb-itinerary-date"> 440 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg> 441 <span><?php echo esc_html( $acrb_pickup_date . ' @ ' . $acrb_pickup_time ); ?></span> 442 </div> 443 <span class="acrb-itinerary-location"> 444 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"></path><circle cx="12" cy="10" r="3"></circle></svg> 445 <span><?php echo esc_html( $acrb_pickup_loc ); ?></span> 446 </span> 447 </div> 448 449 <!-- Return Schedule Pill --> 450 <div class="acrb-itinerary-pill return"> 451 <div class="acrb-itinerary-header"> 452 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 8 10"></polyline></svg> 453 <span><?php esc_html_e( 'Return Schedule', 'awesome-car-rental' ); ?></span> 454 </div> 455 <div class="acrb-itinerary-date"> 456 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg> 457 <span><?php echo esc_html( $acrb_return_date . ' @ ' . $acrb_return_time ); ?></span> 458 </div> 459 <span class="acrb-itinerary-location"> 460 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"></path><circle cx="12" cy="10" r="3"></circle></svg> 461 <span><?php echo esc_html( $acrb_return_loc ); ?></span> 462 </span> 350 463 </div> 351 464 </div> … … 353 466 </div> 354 467 468 <!-- Verified Account Info --> 355 469 <div class="acrb-checkout-card"> 356 470 <h2 class="acrb-checkout-title"> 357 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" ><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>471 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg> 358 472 <span><?php esc_html_e( 'Verified Customer Account', 'awesome-car-rental' ); ?></span> 359 473 </h2> … … 366 480 <input type="email" value="<?php echo esc_attr( $acrb_current_user->user_email ); ?>" readonly class="acrb-checkout-input"> 367 481 </div> 368 <div class="acrb-checkout-field acrb-checkout-field-last">482 <div class="acrb-checkout-field"> 369 483 <label><?php esc_html_e( 'Registered Phone Number', 'awesome-car-rental' ); ?></label> 370 484 <input type="text" value="<?php echo esc_attr( $acrb_display_phone ); ?>" readonly class="acrb-checkout-input"> … … 378 492 <div class="acrb-checkout-card"> 379 493 <h2 class="acrb-checkout-title"> 380 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" ><rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect><line x1="1" y1="10" x2="23" y2="10"></line></svg>494 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect><line x1="1" y1="10" x2="23" y2="10"></line></svg> 381 495 <span><?php esc_html_e( 'Select Payment Method', 'awesome-car-rental' ); ?></span> 382 496 </h2> … … 394 508 <div class="acrb-checkout-card"> 395 509 <h2 class="acrb-checkout-title"> 396 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" ><path d="M20.59 13.41l-7.17 7.17a2 2 0 01-2.83 0L2 12V2h10l8.59 8.59a2 2 0 010 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg>510 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M20.59 13.41l-7.17 7.17a2 2 0 01-2.83 0L2 12V2h10l8.59 8.59a2 2 0 010 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg> 397 511 <span><?php esc_html_e( 'Have a Promo Code?', 'awesome-car-rental' ); ?></span> 398 512 </h2> … … 407 521 <div class="acrb-checkout-card"> 408 522 <h2 class="acrb-checkout-title"> 409 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" ><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg>523 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg> 410 524 <span><?php esc_html_e( 'Price Breakdown Summary', 'awesome-car-rental' ); ?></span> 411 525 </h2> … … 494 608 495 609 <button type="submit" id="acrb_submit_reservation_btn" class="acrb-btn-confirm"> 496 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" ><path d="M5 12h14m-7-7l7 7-7 7"></path></svg>610 <svg class="acrb-checkout-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M5 12h14m-7-7l7 7-7 7"></path></svg> 497 611 <span id="acrb_btn_text"><?php esc_html_e( 'Confirm & Place Secure Reservation', 'awesome-car-rental' ); ?></span> 498 612 </button> … … 506 620 <script> 507 621 document.addEventListener('DOMContentLoaded', function() { 508 const baseSubtotal = <?php echo floatval( $acrb_subtotal ); ?>;509 const insCost = <?php echo floatval( $ins_cost ); ?>;510 const borderCost = <?php echo floatval( $border_cost ); ?>;511 const deposit = <?php echo floatval( $acrb_security_deposit ); ?>;512 const insurance = <?php echo floatval( $acrb_insurance_fee ); ?>;622 const baseSubtotal = <?php echo floatval( $acrb_subtotal ); ?>; 623 const insCost = <?php echo floatval( $ins_cost ); ?>; 624 const borderCost = <?php echo floatval( $border_cost ); ?>; 625 const deposit = <?php echo floatval( $acrb_security_deposit ); ?>; 626 const insurance = <?php echo floatval( $acrb_insurance_fee ); ?>; 513 627 const currencySymbol = '<?php echo esc_js( $acrb_currency ); ?>'; 514 628 515 const sumGrandTotal = document.getElementById('acrb_sum_grand_total');629 const sumGrandTotal = document.getElementById('acrb_sum_grand_total'); 516 630 const finalTotalInput = document.getElementById('acrb_final_total_input'); 517 const hiddenPromo Input= document.getElementById('acrb_hidden_promo_code');631 const hiddenPromo = document.getElementById('acrb_hidden_promo_code'); 518 632 519 const couponBtn = document.getElementById('acrb_apply_coupon');633 const couponBtn = document.getElementById('acrb_apply_coupon'); 520 634 const couponInput = document.getElementById('acrb_coupon_code'); 521 const couponMsg = document.getElementById('acrb_coupon_msg');635 const couponMsg = document.getElementById('acrb_coupon_msg'); 522 636 const discountDiv = document.getElementById('acrb_discount_div'); 523 637 const sumDiscount = document.getElementById('acrb_sum_discount'); … … 534 648 function recalcCheckout() { 535 649 let computedSub = baseSubtotal + insCost + borderCost; 536 let grand = computedSub - appliedDiscountAmt + deposit + insurance; 650 let grand = (computedSub - appliedDiscountAmt) + deposit + insurance; 651 if (grand < 0) grand = 0; 537 652 538 653 if (sumGrandTotal) sumGrandTotal.textContent = grand.toFixed(2); … … 564 679 if (promo.expiry && promo.expiry < currentDate && promo.expiry !== '') { 565 680 appliedDiscountAmt = 0; 566 if (hiddenPromo Input) hiddenPromoInput.value = '';681 if (hiddenPromo) hiddenPromo.value = ''; 567 682 if (discountDiv) discountDiv.style.display = 'none'; 568 683 if (couponMsg) { … … 573 688 } else if (computedSub < promo.min_spend) { 574 689 appliedDiscountAmt = 0; 575 if (hiddenPromo Input) hiddenPromoInput.value = '';690 if (hiddenPromo) hiddenPromo.value = ''; 576 691 if (discountDiv) discountDiv.style.display = 'none'; 577 692 if (couponMsg) { … … 588 703 if (appliedDiscountAmt > computedSub) appliedDiscountAmt = computedSub; 589 704 590 if (hiddenPromo Input) hiddenPromoInput.value = code;705 if (hiddenPromo) hiddenPromo.value = code; 591 706 if (sumDiscount) sumDiscount.textContent = '-' + currencySymbol + appliedDiscountAmt.toFixed(2); 592 707 if (discountDiv) discountDiv.style.display = 'flex'; … … 600 715 } else { 601 716 appliedDiscountAmt = 0; 602 if (hiddenPromo Input) hiddenPromoInput.value = '';717 if (hiddenPromo) hiddenPromo.value = ''; 603 718 if (discountDiv) discountDiv.style.display = 'none'; 604 719 if (couponMsg) { -
awesome-car-rental/trunk/frontend/frontend.php
r3775773 r3777386 21 21 'auth/acrb-frontend-auth.php', 22 22 'cars/acrb-frontend-cars.php', 23 'cars/acrb-frontend-cars-grid.php', 23 24 'login/acrb-frontend-login.php', 24 25 'registration/acrb-frontend-register.php', -
awesome-car-rental/trunk/frontend/login/acrb-frontend-login.php
r3775773 r3777386 1 1 <?php 2 2 /** 3 * [acrb_login] AJAX Login System (Elite SaaS Modernized )4 * Optimized for Security, UI, and Internationalization with Style Customizer Integration.3 * [acrb_login] AJAX Login System (Elite SaaS Modernized for Car Rentals) 4 * Optimized for Security, UI, Email Authentication Fallback, and Redirect Persistence. 5 5 * Location: templates/shortcodes/login.php 6 6 * … … 15 15 } 16 16 17 // 1. BACKEND LOGIC: AJAX Authenticator17 // 2. BACKEND LOGIC: AJAX Authenticator with Email-to-Username Mapping 18 18 add_action( 'wp_ajax_nopriv_acrb_ajax_login', 'acrb_handle_ajax_login' ); 19 19 … … 25 25 } 26 26 27 // B. Validate existence of username and password27 // B. Validate existence of username/email and password 28 28 if ( ! isset( $_POST['username'] ) || ! isset( $_POST['password'] ) ) { 29 29 wp_send_json_error( esc_html__( 'Required fields are missing.', 'awesome-car-rental' ) ); … … 31 31 32 32 // C. Unslash and Sanitize Inputs 33 $ username = sanitize_user( wp_unslash( $_POST['username'] ) );33 $input_login = sanitize_text_field( wp_unslash( $_POST['username'] ) ); 34 34 35 35 // Unslash password without sanitization to preserve special characters 36 36 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 37 37 $password = wp_unslash( $_POST['password'] ); 38 39 // Support logging in with either Username or Email Address seamlessly 40 $username = $input_login; 41 if ( is_email( $input_login ) ) { 42 $user_obj = get_user_by( 'email', $input_login ); 43 if ( $user_obj ) { 44 $username = $user_obj->user_login; 45 } 46 } 38 47 39 48 $creds = array( … … 47 56 48 57 if ( is_wp_error( $user ) ) { 49 wp_send_json_error( esc_html__( 'Invalid email orpassword.', 'awesome-car-rental' ) );58 wp_send_json_error( esc_html__( 'Invalid credentials. Please check your email and password.', 'awesome-car-rental' ) ); 50 59 } else { 51 60 wp_send_json_success(); … … 53 62 } 54 63 55 // 2. UI SHORTCODE64 // 3. UI SHORTCODE 56 65 add_shortcode( 'acrb_login', 'acrb_render_login_shortcode' ); 57 66 58 67 function acrb_render_login_shortcode(): string { 59 // If logged in, redirect to account page 68 // If logged in, redirect to account page or requested redirect URL 60 69 if ( is_user_logged_in() ) { 61 $account_url = esc_url( home_url( '/acrb-account/' ) ); 62 return '<script>window.location.href=' . wp_json_encode( $account_url ) . ';</script>'; 70 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 71 $redirect_to = isset( $_GET['redirect_to'] ) ? esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) : home_url( '/acrb-account/' ); 72 return '<script>window.location.href=' . wp_json_encode( $redirect_to ) . ';</script>'; 63 73 } 64 74 … … 84 94 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 85 95 86 // Scoped CSS properties string without :root 87 $scoped_styles = sprintf( 88 '--acrb-login-primary:%s;--acrb-login-secondary:%s;--acrb-login-text:%s;--acrb-login-accent:%s;--acrb-login-btn-bg:%s;--acrb-login-btn-hover:%s;--acrb-login-font:%s;', 96 // Inject dynamic CSS custom properties via wp_add_inline_style 97 $custom_css = sprintf( 98 '.acrb-auth-solo-wrapper { 99 --acrb-login-primary: %s; 100 --acrb-login-secondary: %s; 101 --acrb-login-text: %s; 102 --acrb-login-accent: %s; 103 --acrb-login-btn-bg: %s; 104 --acrb-login-btn-hover: %s; 105 --acrb-login-font: %s; 106 }', 89 107 esc_attr( $primary_color ), 90 108 esc_attr( $secondary_color ), … … 95 113 esc_attr( $selected_font ) 96 114 ); 115 wp_add_inline_style( 'acrb-login-style', $custom_css ); 97 116 98 117 ob_start(); 99 118 ?> 100 <div class="acrb-auth-page-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>"> 101 <!-- Side Info Panel --> 102 <div class="acrb-auth-side-info"> 103 <h2><?php esc_html_e( 'Fast. Seamless.', 'awesome-car-rental' ); ?><br><?php esc_html_e( 'Secure.', 'awesome-car-rental' ); ?></h2> 104 <p><?php esc_html_e( 'Access your private dashboard to manage your fleet reservations, download settled receipts, and update your account preferences.', 'awesome-car-rental' ); ?></p> 105 <div class="acrb-auth-security-badge"> 106 <svg class="acrb-login-icon acrb-badge-icon" viewBox="0 0 24 24"> 107 <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path> 108 </svg> 109 <span class="acrb-badge-text"><?php esc_html_e( 'Your reservation data is encrypted and secure.', 'awesome-car-rental' ); ?></span> 110 </div> 111 </div> 112 113 <!-- Auth Form Card --> 119 <div class="acrb-auth-solo-wrapper"> 120 <!-- Auth Form Card Only --> 114 121 <div class="acrb-auth-card"> 115 122 <h2 class="acrb-auth-title"><?php esc_html_e( 'Welcome Back', 'awesome-car-rental' ); ?></h2> 116 <p class="acrb-auth-subtitle"><?php esc_html_e( 'Sign in to continue your journey.', 'awesome-car-rental' ); ?></p>123 <p class="acrb-auth-subtitle"><?php esc_html_e( 'Sign in to access your car rental account.', 'awesome-car-rental' ); ?></p> 117 124 118 125 <form id="acrb-login-form"> … … 120 127 121 128 <div class="acrb-login-field"> 122 <label for="acrb_login_email"><?php esc_html_e( 'Email Address ', 'awesome-car-rental' ); ?></label>123 <input type=" email" id="acrb_login_email" placeholder="name@example.com" required autocomplete="email">129 <label for="acrb_login_email"><?php esc_html_e( 'Email Address or Username', 'awesome-car-rental' ); ?></label> 130 <input type="text" id="acrb_login_email" placeholder="name@example.com" required autocomplete="username"> 124 131 </div> 125 132 -
awesome-car-rental/trunk/frontend/registration/acrb-frontend-register.php
r3775773 r3777386 83 83 function acrb_render_register_shortcode(): string { 84 84 if ( is_user_logged_in() ) { 85 $account_url = esc_url( site_url( '/acrb-account/' ) ); 86 return '<script>window.location.href=' . wp_json_encode( $account_url ) . ';</script>'; 85 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 86 $redirect_to = isset( $_GET['redirect_to'] ) ? esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) : site_url( '/acrb-account/' ); 87 return '<script>window.location.href=' . wp_json_encode( $redirect_to ) . ';</script>'; 87 88 } 88 89 … … 108 109 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 109 110 110 // Scoped CSS Custom Properties (Zero :root, component-scoped) 111 $scoped_styles = sprintf( 112 '--acrb-reg-primary:%s;--acrb-reg-secondary:%s;--acrb-reg-text:%s;--acrb-reg-accent:%s;--acrb-reg-btn-bg:%s;--acrb-reg-btn-hover:%s;--acrb-reg-font:%s;', 111 // Inject dynamic CSS custom properties via wp_add_inline_style 112 $custom_css = sprintf( 113 '.acrb-reg-solo-wrapper { 114 --acrb-reg-primary: %s; 115 --acrb-reg-secondary: %s; 116 --acrb-reg-text: %s; 117 --acrb-reg-accent: %s; 118 --acrb-reg-btn-bg: %s; 119 --acrb-reg-btn-hover: %s; 120 --acrb-reg-font: %s; 121 }', 113 122 esc_attr( $primary_color ), 114 123 esc_attr( $secondary_color ), … … 119 128 esc_attr( $selected_font ) 120 129 ); 130 wp_add_inline_style( 'acrb-register-style', $custom_css ); 121 131 122 132 ob_start(); 123 133 ?> 124 <div class="acrb-reg-container" style="<?php echo esc_attr( $scoped_styles ); ?>"> 125 <!-- Side Info Panel --> 126 <div class="acrb-reg-info"> 127 <h2><?php esc_html_e( 'Start Your Journey.', 'awesome-car-rental' ); ?></h2> 128 <p><?php esc_html_e( 'Create a customer account to unlock faster bookings, manage your active rentals, and access exclusive loyalty discounts.', 'awesome-car-rental' ); ?></p> 129 <ul class="acrb-info-list"> 130 <li> 131 <svg class="acrb-reg-icon" viewBox="0 0 24 24"> 132 <polyline points="20 6 9 17 4 12"></polyline> 133 </svg> 134 <span><?php esc_html_e( 'Instant Reservation Confirmation', 'awesome-car-rental' ); ?></span> 135 </li> 136 <li> 137 <svg class="acrb-reg-icon" viewBox="0 0 24 24"> 138 <polyline points="20 6 9 17 4 12"></polyline> 139 </svg> 140 <span><?php esc_html_e( '24/7 Portal & Receipt Management', 'awesome-car-rental' ); ?></span> 141 </li> 142 <li> 143 <svg class="acrb-reg-icon" viewBox="0 0 24 24"> 144 <polyline points="20 6 9 17 4 12"></polyline> 145 </svg> 146 <span><?php esc_html_e( 'Exclusive Member Pricing & Perks', 'awesome-car-rental' ); ?></span> 147 </li> 148 </ul> 149 <div class="acrb-reg-copyright"> 150 © <?php echo esc_html( gmdate( 'Y' ) ); ?> Awesome Car Rental. <?php esc_html_e( 'All rights reserved.', 'awesome-car-rental' ); ?> 151 </div> 152 </div> 153 154 <!-- Registration Form Card --> 134 <div class="acrb-reg-solo-wrapper"> 135 <!-- Registration Form Card Only --> 155 136 <div class="acrb-reg-card"> 156 137 <h2 class="acrb-reg-title"><?php esc_html_e( 'Create Account', 'awesome-car-rental' ); ?></h2> … … 177 158 <input type="email" id="acrb_reg_email" placeholder="john@example.com" required autocomplete="email"> 178 159 </div> 179 <div class="acrb-reg-field ">160 <div class="acrb-reg-field full-width"> 180 161 <label for="acrb_reg_pass"><?php esc_html_e( 'Secure Password (Min. 6 chars)', 'awesome-car-rental' ); ?></label> 181 162 <input type="password" id="acrb_reg_pass" placeholder="••••••••" required minlength="6" autocomplete="new-password"> 182 </div> 183 <div class="acrb-reg-field"> 163 164 <!-- Strength Meter Bar --> 165 <div class="acrb-password-meter-wrap" id="acrb-reg-meter-container" style="display: none;"> 166 <div class="acrb-password-meter-bar"> 167 <div class="acrb-password-meter-fill" id="acrb-reg-meter-fill"></div> 168 </div> 169 <span class="acrb-password-meter-label" id="acrb-reg-meter-label"></span> 170 </div> 171 </div> 172 <div class="acrb-reg-field full-width"> 184 173 <label for="acrb_reg_cpass"><?php esc_html_e( 'Confirm Password', 'awesome-car-rental' ); ?></label> 185 174 <input type="password" id="acrb_reg_cpass" placeholder="••••••••" required minlength="6" autocomplete="new-password"> 175 176 <!-- Live Match Indicator --> 177 <div class="acrb-field-feedback" id="acrb-reg-match-msg" style="display: none;"></div> 186 178 </div> 187 179 </div> … … 197 189 </button> 198 190 199 <div id="acrb-reg-msg" class="acrb-reg-alert"aria-live="polite"></div>191 <div id="acrb-reg-msg" aria-live="polite"></div> 200 192 201 193 <div class="acrb-reg-footer"> 202 194 <?php esc_html_e( 'Already have an account?', 'awesome-car-rental' ); ?> 203 <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php esc_html_e( 'Login here', 'awesome-car-rental' ); ?></a>195 <a href="<?php echo esc_url( home_url( '/acrb-login/' ) ); ?>"><?php esc_html_e( 'Login here', 'awesome-car-rental' ); ?></a> 204 196 </div> 205 197 </form> … … 208 200 209 201 <script> 210 jQuery(document).ready(function($) { 211 $('#acrb-register-form').on('submit', function(e) { 202 document.addEventListener('DOMContentLoaded', function() { 203 const regForm = document.getElementById('acrb-register-form'); 204 const statusDiv = document.getElementById('acrb-reg-msg'); 205 const submitBtn = document.getElementById('acrb-reg-submit'); 206 const passInput = document.getElementById('acrb_reg_pass'); 207 const cpassInput = document.getElementById('acrb_reg_cpass'); 208 const meterContainer = document.getElementById('acrb-reg-meter-container'); 209 const meterFill = document.getElementById('acrb-reg-meter-fill'); 210 const meterLabel = document.getElementById('acrb-reg-meter-label'); 211 const matchMsg = document.getElementById('acrb-reg-match-msg'); 212 213 if (!regForm) return; 214 215 function evaluatePasswordStrength(val) { 216 let score = 0; 217 if (!val) return 0; 218 if (val.length >= 6) score += 1; 219 if (val.length >= 10) score += 1; 220 if (/[a-z]/.test(val) && /[A-Z]/.test(val)) score += 1; 221 if (/\d/.test(val)) score += 1; 222 if (/[^a-zA-Z\d]/.test(val)) score += 1; 223 return Math.min(score, 4); 224 } 225 226 if (passInput) { 227 passInput.addEventListener('input', function() { 228 const val = this.value; 229 if (!val) { 230 meterContainer.style.display = 'none'; 231 return; 232 } 233 meterContainer.style.display = 'flex'; 234 const score = evaluatePasswordStrength(val); 235 const configs = [ 236 { width: '25%', color: '#ef4444', text: '<?php echo esc_js( __( 'Weak', 'awesome-car-rental' ) ); ?>' }, 237 { width: '50%', color: '#f97316', text: '<?php echo esc_js( __( 'Fair', 'awesome-car-rental' ) ); ?>' }, 238 { width: '75%', color: '#eab308', text: '<?php echo esc_js( __( 'Good', 'awesome-car-rental' ) ); ?>' }, 239 { width: '100%', color: '#10b981', text: '<?php echo esc_js( __( 'Very Strong', 'awesome-car-rental' ) ); ?>' } 240 ]; 241 const active = configs[Math.max(0, score - 1)] || configs[0]; 242 meterFill.style.width = active.width; 243 meterFill.style.backgroundColor = active.color; 244 meterLabel.textContent = active.text; 245 meterLabel.style.color = active.color; 246 }); 247 } 248 249 if (cpassInput) { 250 cpassInput.addEventListener('input', function() { 251 const p = passInput.value; 252 const cp = this.value; 253 if (!cp) { 254 matchMsg.style.display = 'none'; 255 return; 256 } 257 matchMsg.style.display = 'flex'; 258 if (p === cp) { 259 matchMsg.className = 'acrb-field-feedback is-match'; 260 matchMsg.innerHTML = '<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"></polyline></svg> <span><?php echo esc_js( __( 'Passwords match perfectly', 'awesome-car-rental' ) ); ?></span>'; 261 } else { 262 matchMsg.className = 'acrb-field-feedback is-mismatch'; 263 matchMsg.innerHTML = '<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line></svg> <span><?php echo esc_js( __( 'Passwords do not match', 'awesome-car-rental' ) ); ?></span>'; 264 } 265 }); 266 } 267 268 regForm.addEventListener('submit', function(e) { 212 269 e.preventDefault(); 213 const btn = $('#acrb-reg-submit');214 const msg = $('#acrb-reg-msg');215 270 216 const pass = $('#acrb_reg_pass').val();217 const cpass = $('#acrb_reg_cpass').val();271 const pass = passInput.value; 272 const cpass = cpassInput.value; 218 273 219 274 if (pass.length < 6) { 220 msg.removeClass('alert-success').addClass('alert-error').text('<?php echo esc_js( __( 'Password must be at least 6 characters long.', 'awesome-car-rental' ) ); ?>').fadeIn();275 statusDiv.innerHTML = '<div class="status-error"><?php echo esc_js( __( 'Password must be at least 6 characters long.', 'awesome-car-rental' ) ); ?></div>'; 221 276 return; 222 277 } 223 278 224 279 if (pass !== cpass) { 225 msg.removeClass('alert-success').addClass('alert-error').text('<?php echo esc_js( __( 'The passwords provided do not match.', 'awesome-car-rental' ) ); ?>').fadeIn();280 statusDiv.innerHTML = '<div class="status-error"><?php echo esc_js( __( 'The passwords provided do not match.', 'awesome-car-rental' ) ); ?></div>'; 226 281 return; 227 282 } 228 229 btn.prop('disabled', true).text('<?php echo esc_js( __( 'Creating Account...', 'awesome-car-rental' ) ); ?>'); 230 msg.hide().removeClass('alert-error alert-success'); 231 232 const data = { 233 action: 'acrb_ajax_register', 234 security: $('#acrb_reg_nonce').val(), 235 username: $('#acrb_reg_user').val(), 236 email: $('#acrb_reg_email').val(), 237 password: pass, 238 cpassword: cpass, 239 full_name: $('#acrb_reg_fullname').val(), 240 phone: $('#acrb_reg_phone').val() 241 }; 242 243 $.post('<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>', data, function(res) { 244 if (res.success) { 245 msg.addClass('alert-success').text(res.data).fadeIn(); 246 setTimeout(() => window.location.href = '<?php echo esc_url( site_url( '/acrb-account/' ) ); ?>', 1800); 283 284 statusDiv.innerHTML = '<span class="status-loading"><?php echo esc_js( __( 'Creating Account...', 'awesome-car-rental' ) ); ?></span>'; 285 submitBtn.disabled = true; 286 287 const formData = new FormData(); 288 formData.append('action', 'acrb_ajax_register'); 289 formData.append('security', document.getElementById('acrb_reg_nonce').value); 290 formData.append('username', document.getElementById('acrb_reg_user').value); 291 formData.append('email', document.getElementById('acrb_reg_email').value); 292 formData.append('password', pass); 293 formData.append('cpassword', cpass); 294 formData.append('full_name', document.getElementById('acrb_reg_fullname').value); 295 formData.append('phone', document.getElementById('acrb_reg_phone').value); 296 297 fetch('<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>', { 298 method: 'POST', 299 body: formData 300 }) 301 .then(response => response.json()) 302 .then(data => { 303 if (data.success) { 304 statusDiv.innerHTML = '<span class="status-success">' + data.data + '</span>'; 305 306 const urlParams = new URLSearchParams(window.location.search); 307 const redirectTo = urlParams.get('redirect_to'); 308 309 setTimeout(() => { 310 window.location.href = redirectTo ? decodeURIComponent(redirectTo) : '<?php echo esc_url( site_url( '/acrb-account/' ) ); ?>'; 311 }, 1500); 247 312 } else { 248 msg.addClass('alert-error').text(res.data).fadeIn();249 btn.prop('disabled', false).text('<?php echo esc_js( __( 'Register Now', 'awesome-car-rental' ) ); ?>');313 statusDiv.innerHTML = '<div class="status-error">' + (data.data || '<?php echo esc_js( __( 'Registration failed.', 'awesome-car-rental' ) ); ?>') + '</div>'; 314 submitBtn.disabled = false; 250 315 } 251 }).fail(function() { 252 msg.addClass('alert-error').text('<?php echo esc_js( __( 'Connection error. Please try again.', 'awesome-car-rental' ) ); ?>').fadeIn(); 253 btn.prop('disabled', false).text('<?php echo esc_js( __( 'Register Now', 'awesome-car-rental' ) ); ?>'); 316 }) 317 .catch(error => { 318 statusDiv.innerHTML = '<div class="status-error"><?php echo esc_js( __( 'Connection error. Please try again.', 'awesome-car-rental' ) ); ?></div>'; 319 submitBtn.disabled = false; 254 320 }); 255 321 }); -
awesome-car-rental/trunk/frontend/search/acrb-frontend-search-form.php
r3775773 r3777386 39 39 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 40 40 41 // Scoped CSS Custom Properties (Zero :root, pure encapsulation) 42 $scoped_styles = sprintf( 43 '--acrb-search-primary:%s;--acrb-search-secondary:%s;--acrb-search-text:%s;--acrb-search-accent:%s;--acrb-search-btn-bg:%s;--acrb-search-btn-hover:%s;--acrb-search-font:%s;', 41 // Inject dynamic CSS custom properties via wp_add_inline_style for clean separation 42 $custom_css = sprintf( 43 '.acrb-search-wrapper { 44 --acrb-search-primary: %s; 45 --acrb-search-secondary: %s; 46 --acrb-search-text: %s; 47 --acrb-search-accent: %s; 48 --acrb-search-btn-bg: %s; 49 --acrb-search-btn-hover: %s; 50 --acrb-search-font: %s; 51 }', 44 52 esc_attr( $primary_color ), 45 53 esc_attr( $secondary_color ), … … 50 58 esc_attr( $selected_font ) 51 59 ); 60 wp_add_inline_style( 'acrb-search-form-style', $custom_css ); 52 61 53 62 // 3. Pull locations from settings 54 63 $locations = get_option( 'acrb_custom_pickup_locations', array() ) ?: get_option( 'acrb_custom_locations', array() ); 55 64 56 // 4. Define Results Page URL 57 $results_page_url = home_url( '/acrb-cars/' ); 65 // 4. Define Results Page URL (Dynamic with fallback) 66 $all_cars_page_id = (int) get_option( 'acrb_all_cars_page' ); 67 $results_page_url = $all_cars_page_id ? get_permalink( $all_cars_page_id ) : home_url( '/acrb-cars/' ); 58 68 59 69 // 5. Get current Search Values (to keep fields filled on results page) 60 // phpcs: ignore WordPress.Security.NonceVerification.Recommended70 // phpcs:disable WordPress.Security.NonceVerification.Recommended 61 71 $current_ploc = isset( $_GET['ploc'] ) ? sanitize_text_field( wp_unslash( $_GET['ploc'] ) ) : ''; 62 // phpcs:ignore WordPress.Security.NonceVerification.Recommended63 72 $current_dloc = isset( $_GET['dloc'] ) ? sanitize_text_field( wp_unslash( $_GET['dloc'] ) ) : ''; 64 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 65 $current_pdate = isset( $_GET['pdate'] ) ? sanitize_text_field( wp_unslash( $_GET['pdate'] ) ) : ''; 66 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 67 $current_rdate = isset( $_GET['rdate'] ) ? sanitize_text_field( wp_unslash( $_GET['rdate'] ) ) : ''; 73 $current_pdate = isset( $_GET['pdate'] ) ? sanitize_text_field( wp_unslash( $_GET['pdate'] ) ) : gmdate( 'Y-m-d' ); 74 $current_rdate = isset( $_GET['rdate'] ) ? sanitize_text_field( wp_unslash( $_GET['rdate'] ) ) : gmdate( 'Y-m-d', strtotime( '+3 days' ) ); 75 // phpcs:enable WordPress.Security.NonceVerification.Recommended 68 76 69 77 ob_start(); 70 78 ?> 71 <div class="acrb-search-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>">79 <div class="acrb-search-wrapper"> 72 80 <form action="<?php echo esc_url( $results_page_url ); ?>" method="GET" class="acrb-search-form"> 73 81 <div class="acrb-search-main"> … … 76 84 <div class="acrb-search-field"> 77 85 <label for="acrb_ploc_in"> 78 <svg class="acrb-search-icon" viewBox="0 0 24 24" >86 <svg class="acrb-search-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 79 87 <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"></path> 80 88 <circle cx="12" cy="10" r="3"></circle> … … 98 106 <div class="acrb-search-field"> 99 107 <label for="acrb_dloc_in"> 100 <svg class="acrb-search-icon" viewBox="0 0 24 24" >108 <svg class="acrb-search-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 101 109 <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"></path> 102 110 <circle cx="12" cy="10" r="3"></circle> … … 120 128 <div class="acrb-search-field"> 121 129 <label for="acrb_pdate_in"> 122 <svg class="acrb-search-icon" viewBox="0 0 24 24" >130 <svg class="acrb-search-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 123 131 <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> 124 132 <line x1="16" y1="2" x2="16" y2="6"></line> … … 140 148 <div class="acrb-search-field"> 141 149 <label for="acrb_rdate_in"> 142 <svg class="acrb-search-icon" viewBox="0 0 24 24" >150 <svg class="acrb-search-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 143 151 <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> 144 152 <line x1="16" y1="2" x2="16" y2="6"></line> … … 153 161 value="<?php echo esc_attr( $current_rdate ); ?>" 154 162 class="acrb-search-input" 155 min="<?php echo $current_pdate ? esc_attr( $current_pdate ) : esc_attr( gmdate( 'Y-m-d' )); ?>"163 min="<?php echo esc_attr( $current_pdate ); ?>" 156 164 required> 157 165 </div> … … 160 168 <button type="submit" class="acrb-search-submit"> 161 169 <span><?php esc_html_e( 'Search Fleet', 'awesome-car-rental' ); ?></span> 162 <svg class="acrb-search-icon" viewBox="0 0 24 24" >170 <svg class="acrb-search-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"> 163 171 <circle cx="11" cy="11" r="8"></circle> 164 172 <line x1="21" y1="21" x2="16.65" y2="16.65"></line> … … 173 181 const pDate = document.getElementById('acrb_pdate_in'); 174 182 const rDate = document.getElementById('acrb_rdate_in'); 175 183 const pLoc = document.getElementById('acrb_ploc_in'); 184 const rLoc = document.getElementById('acrb_dloc_in'); 185 186 // Auto-sync return location if empty 187 if (pLoc && rLoc) { 188 pLoc.addEventListener('change', function() { 189 if (!rLoc.value) { 190 rLoc.value = this.value; 191 } 192 }); 193 } 194 195 // Keep return date valid relative to pickup date 176 196 if (pDate && rDate) { 177 197 pDate.addEventListener('change', function() { -
awesome-car-rental/trunk/frontend/single/acrb-frontned-car-single.php
r3775773 r3777386 39 39 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 40 40 41 // Scoped CSS Custom Properties (Zero :root, component-scoped) 42 $scoped_styles = sprintf( 43 '--acrb-single-primary:%s;--acrb-single-secondary:%s;--acrb-single-text:%s;--acrb-single-accent:%s;--acrb-single-btn-bg:%s;--acrb-single-btn-hover:%s;--acrb-single-font:%s;', 41 // Inject dynamic CSS custom properties via wp_add_inline_style 42 $custom_css = sprintf( 43 '.acrb-main-container, .acrb-redirect-notice, .acrb-alert-error { 44 --acrb-single-primary: %s; 45 --acrb-single-secondary: %s; 46 --acrb-single-text: %s; 47 --acrb-single-accent: %s; 48 --acrb-single-btn-bg: %s; 49 --acrb-single-btn-hover: %s; 50 --acrb-single-font: %s; 51 }', 44 52 esc_attr( $primary_color ), 45 53 esc_attr( $secondary_color ), … … 50 58 esc_attr( $selected_font ) 51 59 ); 60 wp_add_inline_style( 'acrb-single-car-style', $custom_css ); 52 61 53 62 // 3. Auth Check … … 61 70 ?> 62 71 <script>window.location.href=<?php echo wp_json_encode( esc_url_raw( $final_url ) ); ?>;</script> 63 <div class="acrb-redirect-notice" style="<?php echo esc_attr( $scoped_styles ); ?>">64 < ?php esc_html_e( 'Redirecting to secure login portal...', 'awesome-car-rental' ); ?>72 <div class="acrb-redirect-notice"> 73 <p><?php esc_html_e( 'Redirecting to secure login portal...', 'awesome-car-rental' ); ?></p> 65 74 </div> 66 75 <?php … … 78 87 $car = null; 79 88 if ( $car_id > 0 ) { 80 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching81 $car = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE id = %d AND status != 'retired'", $table_cars, $car_id ), ARRAY_A );82 }89 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 90 $car = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_cars} WHERE id = %d AND status != 'retired'", $car_id ), ARRAY_A ); 91 } 83 92 84 93 if ( ! $car ) { … … 93 102 ob_start(); 94 103 ?> 95 <div class="acrb-alert-error" style="<?php echo esc_attr( $scoped_styles ); ?>">96 < ?php esc_html_e( 'Vehicle not found. Please select a car from the fleet grid.', 'awesome-car-rental' ); ?>104 <div class="acrb-alert-error"> 105 <p><?php esc_html_e( 'Vehicle not found. Please select a car from the fleet grid.', 'awesome-car-rental' ); ?></p> 97 106 </div> 98 107 <?php … … 105 114 $insurance_fee = floatval( $car['insurance_fee'] ?? 0.00 ); 106 115 107 $currency =get_option( 'acrb_currency', '£' );108 $rental_unit =get_option( 'acrb_rental_unit', 'day' );109 110 $vehicle_status = (string) ( $car['status'] ?: 'active' );111 $seating_cap = absint( $car['seats'] ?: 5 );112 $baggage_cap = absint( $car['bags'] ?: 2 );113 $transmission = (string) ( $car['transmission'] ?: 'Automatic' );114 $fuel_type = (string) ( $car['fuel'] ?: 'Petrol' );115 $min_rental_days = absint( $car['min_days'] ?: 1);116 $vin = (string) ( $car['vin'] ?:'' );117 $video_url = (string) ( $car['video'] ?:'' );118 $car_name = esc_html( $car['name'] );119 $car_brand = esc_html( $car['brand'] ?? '' );120 $full_title = trim( ( $car_brand ? $car_brand . ' ' : '' ) . $car_name );121 $car_description = (string) ( $car['description'] ?? '' );116 $currency = (string) get_option( 'acrb_currency', '£' ); 117 $rental_unit = (string) get_option( 'acrb_rental_unit', 'day' ); 118 119 $vehicle_status = (string) ( ! empty( $car['status'] ) ? $car['status'] : 'active' ); 120 $seating_cap = absint( ! empty( $car['seats'] ) ? $car['seats'] : 5 ); 121 $baggage_cap = absint( ! empty( $car['bags'] ) ? $car['bags'] : 2 ); 122 $transmission = (string) ( ! empty( $car['transmission'] ) ? $car['transmission'] : 'Automatic' ); 123 $fuel_type = (string) ( ! empty( $car['fuel'] ) ? $car['fuel'] : 'Petrol' ); 124 $min_rental_days = max( 1, absint( ! empty( $car['min_days'] ) ? $car['min_days'] : 1 ) ); 125 $vin = (string) ( $car['vin'] ?? '' ); 126 $video_url = (string) ( $car['video'] ?? '' ); 127 $car_name = esc_html( $car['name'] ); 128 $car_brand = esc_html( $car['brand'] ?? '' ); 129 $full_title = trim( ( $car_brand ? $car_brand . ' ' : '' ) . $car_name ); 130 $car_description = (string) ( $car['description'] ?? '' ); 122 131 123 132 // Resolve Image … … 134 143 $raw_gallery = (string) ( $car['gallery'] ?? '' ); 135 144 if ( ! empty( $raw_gallery ) ) { 136 $gallery_ids = explode( ',', $raw_gallery);145 $gallery_ids = array_filter( array_map( 'trim', explode( ',', $raw_gallery ) ) ); 137 146 } 138 147 … … 148 157 if ( ! empty( $ins['enabled'] ) && ! empty( $ins['name'] ) ) { 149 158 $available_insurance[] = array( 150 'name' => $ins['name'],159 'name' => sanitize_text_field( $ins['name'] ), 151 160 'price' => floatval( $ins['price'] ?? 0 ), 152 'type' => $ins['type'] ?? 'day',161 'type' => sanitize_key( $ins['type'] ?? 'day' ), 153 162 ); 154 163 } … … 161 170 if ( ! empty( $border['enabled'] ) && ! empty( $border['country'] ) ) { 162 171 $available_borders[] = array( 163 'country' => $border['country'],172 'country' => sanitize_text_field( $border['country'] ), 164 173 'fee' => floatval( $border['fee'] ?? 0 ), 165 'type' => $border['type'] ?? 'flat',174 'type' => sanitize_key( $border['type'] ?? 'flat' ), 166 175 ); 167 176 } … … 176 185 foreach ( $db_promos as $p ) { 177 186 $promo_map[ strtoupper( trim( (string) $p['code'] ) ) ] = array( 178 'type' => $p['discount_type'],187 'type' => sanitize_key( $p['discount_type'] ), 179 188 'value' => floatval( $p['discount_value'] ), 180 189 'min_spend' => floatval( $p['min_spend'] ), 181 'expiry' => $p['expiry_date'],190 'expiry' => (string) $p['expiry_date'], 182 191 ); 183 192 } … … 185 194 186 195 // Checkout Page URL 187 $checkout_page_id = get_option( 'acrb_checkout_page' );188 $checkout_page_url = $checkout_page_id ? get_permalink( (int)$checkout_page_id ) : '';196 $checkout_page_id = (int) get_option( 'acrb_checkout_page' ); 197 $checkout_page_url = $checkout_page_id ? get_permalink( $checkout_page_id ) : ''; 189 198 if ( empty( $checkout_page_url ) ) { 190 199 $checkout_page = get_page_by_path( 'acrb-checkout' ); … … 192 201 } 193 202 203 // Default Pre-fill dates from query parameters if passed from catalog 204 // phpcs:disable WordPress.Security.NonceVerification.Recommended 205 $default_pdate = isset( $_GET['pdate'] ) ? sanitize_text_field( wp_unslash( $_GET['pdate'] ) ) : gmdate( 'Y-m-d' ); 206 $default_ptime = isset( $_GET['ptime'] ) ? sanitize_text_field( wp_unslash( $_GET['ptime'] ) ) : '10:00'; 207 $default_rdate = isset( $_GET['rdate'] ) ? sanitize_text_field( wp_unslash( $_GET['rdate'] ) ) : gmdate( 'Y-m-d', strtotime( "+{$min_rental_days} days" ) ); 208 $default_rtime = isset( $_GET['rtime'] ) ? sanitize_text_field( wp_unslash( $_GET['rtime'] ) ) : '10:00'; 209 $default_ploc = isset( $_GET['ploc'] ) ? sanitize_text_field( wp_unslash( $_GET['ploc'] ) ) : ''; 210 $default_rloc = isset( $_GET['dloc'] ) ? sanitize_text_field( wp_unslash( $_GET['dloc'] ) ) : ''; 211 // phpcs:enable WordPress.Security.NonceVerification.Recommended 212 194 213 ob_start(); 195 214 ?> 196 <div class="acrb-main-container" style="<?php echo esc_attr( $scoped_styles ); ?>" data-day-rate="<?php echo esc_attr( (string) $price ); ?>" data-deposit="<?php echo esc_attr( (string) $security_deposit ); ?>" data-insurance="<?php echo esc_attr( (string) $insurance_fee ); ?>" data-currency="<?php echo esc_attr( $currency ); ?>" data-promos="<?php echo esc_attr( wp_json_encode( $promo_map ) ); ?>"> 215 <div class="acrb-main-container" 216 data-day-rate="<?php echo esc_attr( (string) $price ); ?>" 217 data-min-days="<?php echo esc_attr( (string) $min_rental_days ); ?>" 218 data-deposit="<?php echo esc_attr( (string) $security_deposit ); ?>" 219 data-insurance="<?php echo esc_attr( (string) $insurance_fee ); ?>" 220 data-currency="<?php echo esc_attr( $currency ); ?>" 221 data-promos="<?php echo esc_attr( wp_json_encode( $promo_map ) ); ?>"> 222 197 223 <div class="acrb-flex-grid"> 198 224 … … 204 230 <?php else : ?> 205 231 <div class="acrb-empty-box acrb-hero-placeholder"> 206 <svg class="acrb-single-icon" viewBox="0 0 24 24"><path d="M5 17h14v-5l-2-6H7l-2 6v5z"></path><circle cx="7.5" cy="17.5" r="2.5"></circle><circle cx="16.5" cy="17.5" r="2.5"></circle></svg> 232 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 233 <path d="M5 17h14v-5l-2-6H7l-2 6v5z"></path> 234 <circle cx="7.5" cy="17.5" r="2.5"></circle> 235 <circle cx="16.5" cy="17.5" r="2.5"></circle> 236 </svg> 207 237 <p><?php esc_html_e( 'No photo available', 'awesome-car-rental' ); ?></p> 208 238 </div> … … 212 242 <div class="acrb-header-box"> 213 243 <div class="acrb-vin-badge"> 214 <?php esc_html_e( 'VIN Ref:', 'awesome-car-rental' ); ?> #<?php echo esc_html( $vin ?: (string) $car_id ); ?>244 <?php esc_html_e( 'VIN / Reference:', 'awesome-car-rental' ); ?> #<?php echo esc_html( $vin ?: (string) $car_id ); ?> 215 245 </div> 216 246 <h1 class="acrb-car-title"><?php echo esc_html( $full_title ); ?></h1> … … 221 251 <button type="button" class="acrb-tab-btn active" data-tab="overview"><?php esc_html_e( 'Overview', 'awesome-car-rental' ); ?></button> 222 252 <button type="button" class="acrb-tab-btn" data-tab="specs"><?php esc_html_e( 'Specifications', 'awesome-car-rental' ); ?></button> 223 <button type="button" class="acrb-tab-btn" data-tab="gallery"><?php esc_html_e( ' Gallery', 'awesome-car-rental' ); ?></button>253 <button type="button" class="acrb-tab-btn" data-tab="gallery"><?php esc_html_e( 'Photo Gallery', 'awesome-car-rental' ); ?></button> 224 254 <button type="button" class="acrb-tab-btn" data-tab="video"><?php esc_html_e( 'Video Walkaround', 'awesome-car-rental' ); ?></button> 225 255 </div> … … 241 271 <div class="acrb-spec-node"> 242 272 <div class="acrb-spec-icon-wrap"> 243 <svg class="acrb-single-icon" viewBox="0 0 24 24"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>273 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg> 244 274 </div> 245 275 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Status', 'awesome-car-rental' ); ?></div> 246 <div class="acrb-spec-node-val"><?php echo esc_html( $vehicle_status); ?></div>276 <div class="acrb-spec-node-val"><?php echo esc_html( ucfirst( $vehicle_status ) ); ?></div> 247 277 </div> 248 278 <div class="acrb-spec-node"> 249 279 <div class="acrb-spec-icon-wrap"> 250 <svg class="acrb-single-icon" viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 00-3-3.87"></path><path d="M16 3.13a4 4 0 010 7.75"></path></svg>280 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 00-3-3.87"></path><path d="M16 3.13a4 4 0 010 7.75"></path></svg> 251 281 </div> 252 282 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Seating', 'awesome-car-rental' ); ?></div> … … 255 285 <div class="acrb-spec-node"> 256 286 <div class="acrb-spec-icon-wrap"> 257 <svg class="acrb-single-icon" viewBox="0 0 24 24"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect><path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16"></path></svg>287 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect><path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16"></path></svg> 258 288 </div> 259 289 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Baggage', 'awesome-car-rental' ); ?></div> … … 262 292 <div class="acrb-spec-node"> 263 293 <div class="acrb-spec-icon-wrap"> 264 <svg class="acrb-single-icon" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5l3 3"></path></svg>294 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><circle cx="12" cy="12" r="9"></circle><path d="M12 7v5l3 3"></path></svg> 265 295 </div> 266 296 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Transmission', 'awesome-car-rental' ); ?></div> … … 269 299 <div class="acrb-spec-node"> 270 300 <div class="acrb-spec-icon-wrap"> 271 <svg class="acrb-single-icon" viewBox="0 0 24 24"><path d="M3 22V5a2 2 0 012-2h8a2 2 0 012 2v17"></path><path d="M15 9h2a2 2 0 012 2v2a2 2 0 002 2 2 2 0 002-2V9.5"></path></svg>272 </div> 273 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Fuel / Engine', 'awesome-car-rental' ); ?></div>301 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><path d="M3 22V5a2 2 0 012-2h8a2 2 0 012 2v17"></path><path d="M15 9h2a2 2 0 012 2v2a2 2 0 002 2 2 2 0 002-2V9.5"></path></svg> 302 </div> 303 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Fuel Type', 'awesome-car-rental' ); ?></div> 274 304 <div class="acrb-spec-node-val"><?php echo esc_html( $fuel_type ); ?></div> 275 305 </div> 276 306 <div class="acrb-spec-node"> 277 307 <div class="acrb-spec-icon-wrap"> 278 <svg class="acrb-single-icon" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>308 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg> 279 309 </div> 280 310 <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Min Rental', 'awesome-car-rental' ); ?></div> … … 289 319 <div class="acrb-gallery-grid"> 290 320 <?php if ( ! empty( $hero_img ) ) : ?> 291 <div class="acrb-gallery-thumb-wrap ">321 <div class="acrb-gallery-thumb-wrap is-active"> 292 322 <img src="<?php echo esc_url( $hero_img ); ?>" class="acrb-gallery-item" alt="<?php echo esc_attr( $full_title ); ?>"> 293 323 </div> 294 324 <?php endif; ?> 295 325 <?php foreach ( $gallery_ids as $gid ) : 296 $gid = trim( (string) $gid ); 297 if ( ! empty( $gid ) ) : 298 $img_url = ''; 299 if ( is_numeric( $gid ) && absint( $gid ) > 0 ) { 300 $img_url = wp_get_attachment_image_url( absint( $gid ), 'large' ) ?: ''; 301 } elseif ( filter_var( $gid, FILTER_VALIDATE_URL ) ) { 302 $img_url = $gid; 303 } 304 if ( ! empty( $img_url ) ) : 326 $img_url = ''; 327 if ( is_numeric( $gid ) && absint( $gid ) > 0 ) { 328 $img_url = wp_get_attachment_image_url( absint( $gid ), 'large' ) ?: ''; 329 } elseif ( filter_var( $gid, FILTER_VALIDATE_URL ) ) { 330 $img_url = $gid; 331 } 332 if ( ! empty( $img_url ) ) : 305 333 ?> 306 334 <div class="acrb-gallery-thumb-wrap"> 307 335 <img src="<?php echo esc_url( $img_url ); ?>" class="acrb-gallery-item" alt="<?php echo esc_attr( $full_title ); ?>"> 308 336 </div> 309 <?php endif; end if; endforeach; ?>337 <?php endif; endforeach; ?> 310 338 </div> 311 339 <?php else : ?> 312 340 <div class="acrb-empty-box"> 313 <svg class="acrb-single-icon" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg> 314 <p><?php esc_html_e( 'No additional images available.', 'awesome-car-rental' ); ?></p> 341 <p><?php esc_html_e( 'No additional photos uploaded.', 'awesome-car-rental' ); ?></p> 315 342 </div> 316 343 <?php endif; ?> … … 324 351 <div class="acrb-video-container"><?php echo wp_kses_post( $embed ); ?></div> 325 352 <?php else : ?> 326 <p class="acrb-empty-msg"><?php esc_html_e( ' Invalid video URL.', 'awesome-car-rental' ); ?></p>353 <p class="acrb-empty-msg"><?php esc_html_e( 'Unable to load video format.', 'awesome-car-rental' ); ?></p> 327 354 <?php endif; ?> 328 355 <?php else : ?> 329 356 <div class="acrb-empty-box"> 330 <svg class="acrb-single-icon" viewBox="0 0 24 24"><polygon points="23 7 16 12 23 17 23 7"></polygon><rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect></svg> 331 <p><?php esc_html_e( 'No video walkthrough available.', 'awesome-car-rental' ); ?></p> 357 <p><?php esc_html_e( 'No video walkthrough available for this car.', 'awesome-car-rental' ); ?></p> 332 358 </div> 333 359 <?php endif; ?> … … 346 372 <form action="<?php echo esc_url( $checkout_page_url ); ?>" method="GET" id="acrb-booking-form"> 347 373 <input type="hidden" name="car_id" value="<?php echo absint( $car_id ); ?>"> 374 <input type="hidden" name="calculated_days" id="acrb_hidden_days" value="<?php echo absint( $min_rental_days ); ?>"> 375 <input type="hidden" name="subtotal_amount" id="acrb_hidden_subtotal" value="<?php echo esc_attr( (string) ( $price * $min_rental_days ) ); ?>"> 376 <input type="hidden" name="insurance_cost" id="acrb_hidden_ins_cost" value="0"> 377 <input type="hidden" name="border_cost" id="acrb_hidden_border_cost" value="0"> 378 <input type="hidden" name="total_amount" id="acrb_hidden_total" value="0"> 348 379 349 380 <!-- Pickup Date & Time --> … … 351 382 <div class="acrb-form-col-date"> 352 383 <label class="acrb-label" for="p_date"><?php esc_html_e( 'Pickup Date', 'awesome-car-rental' ); ?></label> 353 <input type="date" id="p_date" name="pdate" required min="<?php echo esc_attr( gmdate( 'Y-m-d' ) ); ?>" class="acrb-input">384 <input type="date" id="p_date" name="pdate" value="<?php echo esc_attr( $default_pdate ); ?>" required min="<?php echo esc_attr( gmdate( 'Y-m-d' ) ); ?>" class="acrb-input"> 354 385 </div> 355 386 <div class="acrb-form-col-time"> 356 387 <label class="acrb-label" for="p_time"><?php esc_html_e( 'Time', 'awesome-car-rental' ); ?></label> 357 <input type="time" id="p_time" name="ptime" value=" 10:00" required class="acrb-input">388 <input type="time" id="p_time" name="ptime" value="<?php echo esc_attr( $default_ptime ); ?>" required class="acrb-input"> 358 389 </div> 359 390 </div> … … 363 394 <div class="acrb-form-col-date"> 364 395 <label class="acrb-label" for="r_date"><?php esc_html_e( 'Return Date', 'awesome-car-rental' ); ?></label> 365 <input type="date" id="r_date" name="rdate" required min="<?php echo esc_attr( gmdate( 'Y-m-d' )); ?>" class="acrb-input">396 <input type="date" id="r_date" name="rdate" value="<?php echo esc_attr( $default_rdate ); ?>" required min="<?php echo esc_attr( $default_pdate ); ?>" class="acrb-input"> 366 397 </div> 367 398 <div class="acrb-form-col-time"> 368 399 <label class="acrb-label" for="r_time"><?php esc_html_e( 'Time', 'awesome-car-rental' ); ?></label> 369 <input type="time" id="r_time" name="rtime" value=" 10:00" required class="acrb-input">400 <input type="time" id="r_time" name="rtime" value="<?php echo esc_attr( $default_rtime ); ?>" required class="acrb-input"> 370 401 </div> 371 402 </div> … … 374 405 <div class="acrb-locations-row"> 375 406 <div class="acrb-form-col-half"> 376 <label class="acrb-label" for="acrb_pickup_loc"><?php esc_html_e( 'Pickup Location', 'awesome-car-rental' ); ?></label>407 <label class="acrb-label" for="acrb_pickup_loc"><?php esc_html_e( 'Pickup Hub', 'awesome-car-rental' ); ?></label> 377 408 <select id="acrb_pickup_loc" name="ploc" required class="acrb-input acrb-select"> 378 409 <option value=""><?php esc_html_e( 'Select Hub', 'awesome-car-rental' ); ?></option> … … 381 412 if ( ! empty( $loc_name ) ) : 382 413 ?> 383 <option value="<?php echo esc_attr( $loc_name ); ?>" ><?php echo esc_html( $loc_name ); ?></option>414 <option value="<?php echo esc_attr( $loc_name ); ?>" <?php selected( $default_ploc, $loc_name ); ?>><?php echo esc_html( $loc_name ); ?></option> 384 415 <?php endif; endforeach; ?> 385 416 </select> 386 417 </div> 387 418 <div class="acrb-form-col-half"> 388 <label class="acrb-label" for="acrb_return_loc"><?php esc_html_e( 'Return Location', 'awesome-car-rental' ); ?></label>419 <label class="acrb-label" for="acrb_return_loc"><?php esc_html_e( 'Return Hub', 'awesome-car-rental' ); ?></label> 389 420 <select id="acrb_return_loc" name="dloc" required class="acrb-input acrb-select"> 390 421 <option value=""><?php esc_html_e( 'Select Hub', 'awesome-car-rental' ); ?></option> … … 393 424 if ( ! empty( $loc_name ) ) : 394 425 ?> 395 <option value="<?php echo esc_attr( $loc_name ); ?>" ><?php echo esc_html( $loc_name ); ?></option>426 <option value="<?php echo esc_attr( $loc_name ); ?>" <?php selected( $default_rloc, $loc_name ); ?>><?php echo esc_html( $loc_name ); ?></option> 396 427 <?php endif; endforeach; ?> 397 428 </select> … … 402 433 <?php if ( ! empty( $available_insurance ) ) : ?> 403 434 <div class="acrb-luxury-options-group"> 404 <div class="acrb-group-title">🛡️ <?php esc_html_e( 'Protection & Insurance Plans', 'awesome-car-rental' ); ?></div>435 <div class="acrb-group-title">🛡️ <?php esc_html_e( 'Protection & Coverage', 'awesome-car-rental' ); ?></div> 405 436 <label class="acrb-luxury-card selected"> 406 437 <div class="acrb-luxury-info"> … … 414 445 <div class="acrb-luxury-info"> 415 446 <input type="radio" name="acrb_selected_insurance" value="<?php echo esc_attr( $ins['name'] ); ?>" data-price="<?php echo esc_attr( (string) $ins['price'] ); ?>" data-type="<?php echo esc_attr( $ins['type'] ); ?>" class="acrb-insurance-radio"> 416 <span> 🛡️<?php echo esc_html( $ins['name'] ); ?></span>447 <span><?php echo esc_html( $ins['name'] ); ?></span> 417 448 </div> 418 449 <span class="acrb-luxury-price">+<?php echo esc_html( $currency . number_format( $ins['price'], 2 ) . ( $ins['type'] === 'day' ? '/day' : ' (flat)' ) ); ?></span> … … 429 460 <div class="acrb-luxury-info"> 430 461 <input type="radio" name="acrb_selected_border" value="" data-fee="0" data-type="flat" class="acrb-border-radio" checked> 431 <span><?php esc_html_e( ' No Border Crossing', 'awesome-car-rental' ); ?></span>462 <span><?php esc_html_e( 'Domestic Travel Only', 'awesome-car-rental' ); ?></span> 432 463 </div> 433 464 <span class="acrb-luxury-price"><?php echo esc_html( $currency ); ?>0.00</span> … … 445 476 <?php endif; ?> 446 477 478 <!-- Live Minimum Days / Calculation Alert --> 479 <div class="acrb-calc-error" id="acrb-min-days-alert"></div> 480 447 481 <!-- Price Breakdown Summary Card --> 448 482 <div class="acrb-breakdown-card"> 449 483 <div class="acrb-breakdown-header"> 450 <svg class="acrb-single-icon" viewBox="0 0 24 24"><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg> 484 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> 485 <line x1="18" y1="20" x2="18" y2="10"></line> 486 <line x1="12" y1="20" x2="12" y2="4"></line> 487 <line x1="6" y1="20" x2="6" y2="14"></line> 488 </svg> 451 489 <span><?php esc_html_e( 'Price Breakdown Summary', 'awesome-car-rental' ); ?></span> 452 490 </div> … … 458 496 <div> 459 497 <span><?php esc_html_e( 'Vehicle Rental', 'awesome-car-rental' ); ?></span> 460 <span class="acrb-bd-sub" id="acrb_calc_days"> 0 Daysselected</span>461 </div> 462 </div> 463 <div class="acrb-bd-val" id="acrb_calc_subtotal"><?php echo esc_html( $currency ); ?>0.00</div>498 <span class="acrb-bd-sub" id="acrb_calc_days">1 Day selected</span> 499 </div> 500 </div> 501 <div class="acrb-bd-val" id="acrb_calc_subtotal"><?php echo esc_html( $currency . number_format( $price * $min_rental_days, 2 ) ); ?></div> 464 502 </div> 465 503 … … 523 561 </div> 524 562 525 <button type="submit" class="acrb-submit-btn"> 526 <svg class="acrb-single-icon acrb-submit-icon" viewBox="0 0 24 24"><path d="M5 12h14m-7-7l7 7-7 7"></path></svg> 563 <button type="submit" class="acrb-submit-btn" id="acrb_submit_btn"> 564 <svg class="acrb-single-icon acrb-submit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor"> 565 <path d="M5 12h14m-7-7l7 7-7 7"></path> 566 </svg> 527 567 <span><?php esc_html_e( 'Proceed to Secure Checkout', 'awesome-car-rental' ); ?></span> 528 568 </button> … … 537 577 document.addEventListener('DOMContentLoaded', function() { 538 578 // Tab System 539 const tabBtns = document.querySelectorAll('.acrb-tab-btn');579 const tabBtns = document.querySelectorAll('.acrb-tab-btn'); 540 580 const tabPanes = document.querySelectorAll('.acrb-tab-pane'); 541 581 tabBtns.forEach(btn => { … … 569 609 setupLuxuryCards('input[name="acrb_selected_border"]'); 570 610 571 // Price Breakdown Logic with Dates, Times, Insurance & Border Crossing611 // Form elements 572 612 const pDate = document.getElementById('p_date'); 573 613 const pTime = document.getElementById('p_time'); 574 614 const rDate = document.getElementById('r_date'); 575 615 const rTime = document.getElementById('r_time'); 576 const pLoc = document.getElementById('acrb_pickup_loc');577 const rLoc = document.getElementById('acrb_return_loc');616 const pLoc = document.getElementById('acrb_pickup_loc'); 617 const rLoc = document.getElementById('acrb_return_loc'); 578 618 579 const displayTotal = document.getElementById('acrb_sum_total');580 const displayDays = document.getElementById('acrb_calc_days');619 const displayTotal = document.getElementById('acrb_sum_total'); 620 const displayDays = document.getElementById('acrb_calc_days'); 581 621 const displaySubtotal = document.getElementById('acrb_calc_subtotal'); 622 const minDaysAlert = document.getElementById('acrb-min-days-alert'); 623 const submitBtn = document.getElementById('acrb_submit_btn'); 624 625 const hiddenDays = document.getElementById('acrb_hidden_days'); 626 const hiddenSubtotal = document.getElementById('acrb_hidden_subtotal'); 627 const hiddenInsCost = document.getElementById('acrb_hidden_ins_cost'); 628 const hiddenBorderCost = document.getElementById('acrb_hidden_border_cost'); 629 const hiddenTotal = document.getElementById('acrb_hidden_total'); 582 630 583 631 // Dynamic breakdown rows 584 const insuranceRow = document.getElementById('acrb_bd_insurance_row');632 const insuranceRow = document.getElementById('acrb_bd_insurance_row'); 585 633 const insuranceTitle = document.getElementById('acrb_bd_insurance_title'); 586 const insuranceVal = document.getElementById('acrb_bd_insurance_val');587 588 const borderRow = document.getElementById('acrb_bd_border_row');634 const insuranceVal = document.getElementById('acrb_bd_insurance_val'); 635 636 const borderRow = document.getElementById('acrb_bd_border_row'); 589 637 const borderTitle = document.getElementById('acrb_bd_border_title'); 590 const borderVal = document.getElementById('acrb_bd_border_val'); 591 592 const container = document.querySelector('.acrb-main-container'); 593 const rate = container ? parseFloat(container.dataset.dayRate) : 0; 594 const deposit = container ? parseFloat(container.dataset.deposit) : 0; 638 const borderVal = document.getElementById('acrb_bd_border_val'); 639 640 const container = document.querySelector('.acrb-main-container'); 641 const rate = container ? parseFloat(container.dataset.dayRate) : 0; 642 const minDays = container ? parseInt(container.dataset.minDays, 10) || 1 : 1; 643 const deposit = container ? parseFloat(container.dataset.deposit) : 0; 595 644 const insuranceBase = container ? parseFloat(container.dataset.insurance) : 0; 596 const currency = container ? container.dataset.currency : '$';645 const currency = container ? container.dataset.currency : '$'; 597 646 598 647 // Auto-sync return location with pickup location if empty … … 606 655 if (pDate && rDate && pDate.value && rDate.value && pTime && rTime) { 607 656 const startStr = pDate.value + 'T' + (pTime.value || '10:00'); 608 const endStr = rDate.value + 'T' + (rTime.value || '10:00');657 const endStr = rDate.value + 'T' + (rTime.value || '10:00'); 609 658 610 659 const start = new Date(startStr); 611 const end = new Date(endStr);660 const end = new Date(endStr); 612 661 613 662 const diffHours = (end - start) / (1000 * 60 * 60); 614 663 615 664 if (diffHours > 0) { 616 const days = Math.max(1, Math.ceil(diffHours / 24)); 617 let subtotal = days * rate; 665 const computedDays = Math.ceil(diffHours / 24); 666 667 if (computedDays < minDays) { 668 if (minDaysAlert) { 669 minDaysAlert.textContent = `<?php echo esc_js( __( 'This vehicle requires a minimum rental period of', 'awesome-car-rental' ) ); ?> ${minDays} <?php echo esc_js( __( 'day(s).', 'awesome-car-rental' ) ); ?>`; 670 minDaysAlert.style.display = 'block'; 671 } 672 if (submitBtn) submitBtn.disabled = true; 673 } else { 674 if (minDaysAlert) minDaysAlert.style.display = 'none'; 675 if (submitBtn) submitBtn.disabled = false; 676 } 677 678 const activeDays = Math.max(minDays, computedDays); 679 let subtotal = activeDays * rate; 618 680 let optionsTotal = 0; 619 681 620 // 1. Insurance Calculation & UI Update 682 if (hiddenDays) hiddenDays.value = activeDays; 683 if (hiddenSubtotal) hiddenSubtotal.value = subtotal.toFixed(2); 684 685 // 1. Insurance Calculation 621 686 const selectedIns = document.querySelector('input[name="acrb_selected_insurance"]:checked'); 622 687 let insCost = 0; 623 688 if (selectedIns && selectedIns.value) { 624 689 const price = parseFloat(selectedIns.dataset.price) || 0; 625 const type = selectedIns.dataset.type;626 insCost = (type === 'day' ? price * days : price);690 const type = selectedIns.dataset.type; 691 insCost = (type === 'day' ? price * activeDays : price); 627 692 optionsTotal += insCost; 628 693 694 if (hiddenInsCost) hiddenInsCost.value = insCost.toFixed(2); 629 695 if (insuranceTitle) insuranceTitle.textContent = selectedIns.value; 630 696 if (insuranceVal) insuranceVal.textContent = '+' + currency + insCost.toFixed(2); 631 697 if (insuranceRow) insuranceRow.style.display = 'flex'; 632 698 } else { 699 if (hiddenInsCost) hiddenInsCost.value = '0'; 633 700 if (insuranceRow) insuranceRow.style.display = 'none'; 634 701 } 635 702 636 // 2. Border Crossing Calculation & UI Update703 // 2. Border Crossing Calculation 637 704 const selectedBorder = document.querySelector('input[name="acrb_selected_border"]:checked'); 638 705 let borderCost = 0; 639 706 if (selectedBorder && selectedBorder.value) { 640 const fee = parseFloat(selectedBorder.dataset.fee) || 0;641 const type = selectedBorder.dataset.type;642 borderCost = (type === 'day' ? fee * days : fee);707 const fee = parseFloat(selectedBorder.dataset.fee) || 0; 708 const type = selectedBorder.dataset.type; 709 borderCost = (type === 'day' ? fee * activeDays : fee); 643 710 optionsTotal += borderCost; 644 711 712 if (hiddenBorderCost) hiddenBorderCost.value = borderCost.toFixed(2); 645 713 if (borderTitle) borderTitle.textContent = selectedBorder.value + ' Permit'; 646 714 if (borderVal) borderVal.textContent = '+' + currency + borderCost.toFixed(2); 647 715 if (borderRow) borderRow.style.display = 'flex'; 648 716 } else { 717 if (hiddenBorderCost) hiddenBorderCost.value = '0'; 649 718 if (borderRow) borderRow.style.display = 'none'; 650 719 } … … 652 721 const grandTotal = subtotal + optionsTotal + deposit + insuranceBase; 653 722 654 if (displayDays) displayDays.textContent = days + (days === 1 ? ' Day selected' : ' Days selected'); 723 if (hiddenTotal) hiddenTotal.value = grandTotal.toFixed(2); 724 if (displayDays) displayDays.textContent = activeDays + (activeDays === 1 ? ' Day selected' : ' Days selected'); 655 725 if (displaySubtotal) displaySubtotal.textContent = currency + subtotal.toFixed(2); 656 726 if (displayTotal) displayTotal.textContent = grandTotal.toFixed(2); 657 727 } else { 728 if (minDaysAlert) { 729 minDaysAlert.textContent = '<?php echo esc_js( __( 'Return date and time must be after the pickup date and time.', 'awesome-car-rental' ) ); ?>'; 730 minDaysAlert.style.display = 'block'; 731 } 732 if (submitBtn) submitBtn.disabled = true; 658 733 if (displayDays) displayDays.textContent = '0 Days selected'; 659 734 if (displaySubtotal) displaySubtotal.textContent = currency + '0.00'; … … 681 756 } 682 757 683 // Gallery Hero Switcher 758 // Gallery Hero Switcher with Active Thumb State 684 759 document.querySelectorAll('.acrb-gallery-item').forEach(img => { 685 760 img.addEventListener('click', function() { 686 761 const hero = document.getElementById('acrb-hero-view'); 687 if (hero) hero.src = this.src; 688 window.scrollTo({ top: 0, behavior: 'smooth' }); 762 if (hero) { 763 hero.style.opacity = '0.5'; 764 setTimeout(() => { 765 hero.src = this.src; 766 hero.style.opacity = '1'; 767 }, 120); 768 } 769 document.querySelectorAll('.acrb-gallery-thumb-wrap').forEach(w => w.classList.remove('is-active')); 770 const wrap = this.closest('.acrb-gallery-thumb-wrap'); 771 if (wrap) wrap.classList.add('is-active'); 689 772 }); 690 773 }); 774 775 // Run initial calculation on page load 776 calc(); 691 777 }); 692 778 </script> -
awesome-car-rental/trunk/frontend/thanks/acrb-frontned-thanks.php
r3775773 r3777386 43 43 $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta']; 44 44 45 // Scoped CSS Custom Properties (Zero :root, pure encapsulation) 46 $scoped_styles = sprintf( 47 '--acrb-thanks-primary:%s;--acrb-thanks-secondary:%s;--acrb-thanks-text:%s;--acrb-thanks-accent:%s;--acrb-thanks-btn-bg:%s;--acrb-thanks-btn-hover:%s;--acrb-thanks-font:%s;', 45 // Inject dynamic CSS custom properties via wp_add_inline_style 46 $custom_css = sprintf( 47 '.acrb-thanks-wrapper { 48 --acrb-thanks-primary: %s; 49 --acrb-thanks-secondary: %s; 50 --acrb-thanks-text: %s; 51 --acrb-thanks-accent: %s; 52 --acrb-thanks-btn-bg: %s; 53 --acrb-thanks-btn-hover: %s; 54 --acrb-thanks-font: %s; 55 }', 48 56 esc_attr( $primary_color ), 49 57 esc_attr( $secondary_color ), … … 54 62 esc_attr( $selected_font ) 55 63 ); 64 wp_add_inline_style( 'acrb-thanks-style', $custom_css ); 56 65 57 66 // phpcs:ignore WordPress.Security.NonceVerification.Recommended 58 67 $booking_id = isset( $_GET['booking_id'] ) ? absint( wp_unslash( $_GET['booking_id'] ) ) : 0; 59 68 60 // Validation against Custom Table (Using %i identifier placeholder for table name)69 // Validation against Custom Table 61 70 $booking = null; 62 71 if ( $booking_id > 0 ) { 63 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 64 $booking = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE id = %d", $table_bookings, $booking_id ), ARRAY_A );72 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 73 $booking = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_bookings} WHERE id = %d", $booking_id ), ARRAY_A ); 65 74 } 66 75 … … 68 77 ob_start(); 69 78 ?> 70 <div class="acrb-error-container" style="<?php echo esc_attr( $scoped_styles ); ?>">79 <div class="acrb-error-container"> 71 80 <h3><?php esc_html_e( 'No Active Booking Found', 'awesome-car-rental' ); ?></h3> 72 81 <p><?php esc_html_e( 'It looks like you reached this confirmation page directly without a valid reservation identifier.', 'awesome-car-rental' ); ?></p> … … 109 118 110 119 // Dynamic Currency & Rental Unit 111 $currency = get_option( 'acrb_currency', '£' );112 $rental_unit = get_option( 'acrb_rental_unit', 'day' );120 $currency = (string) get_option( 'acrb_currency', '£' ); 121 $rental_unit = (string) get_option( 'acrb_rental_unit', 'day' ); 113 122 114 123 // Calculate rental duration in days … … 125 134 } 126 135 127 // Lookup Promo details if applied (Using %i identifier placeholder for table name)136 // Lookup Promo details if applied 128 137 $promo_display = ''; 129 138 if ( ! empty( $promo_code ) ) { 130 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 131 $p_record = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE code = %s", $table_promos, $promo_code ), ARRAY_A );139 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared 140 $p_record = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_promos} WHERE code = %s", $promo_code ), ARRAY_A ); 132 141 if ( $p_record ) { 133 142 $p_type = $p_record['discount_type']; … … 141 150 ob_start(); 142 151 ?> 143 <div class="acrb-thanks-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>"> 152 <div class="acrb-thanks-wrapper"> 153 <!-- Stepper Header --> 154 <div class="acrb-checkout-steps"> 155 <div class="acrb-step-item completed"> 156 <div class="acrb-step-num"> 157 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"></polyline></svg> 158 </div> 159 <span><?php esc_html_e( '1. Select Vehicle', 'awesome-car-rental' ); ?></span> 160 </div> 161 <div class="acrb-step-item completed"> 162 <div class="acrb-step-num"> 163 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><polyline points="20 6 9 17 4 12"></polyline></svg> 164 </div> 165 <span><?php esc_html_e( '2. Review & Secure Checkout', 'awesome-car-rental' ); ?></span> 166 </div> 167 <div class="acrb-step-item active"> 168 <div class="acrb-step-num">3</div> 169 <span><?php esc_html_e( '3. Instant Handover Confirmation', 'awesome-car-rental' ); ?></span> 170 </div> 171 </div> 172 144 173 <div class="acrb-thanks-card"> 145 174 <div class="acrb-thanks-header"> … … 297 326 <div class="acrb-action-buttons"> 298 327 <button type="button" onclick="window.print()" class="acrb-btn-action"> 299 <svg class="acrb-thanks-icon" viewBox="0 0 24 24" >328 <svg class="acrb-thanks-icon" viewBox="0 0 24 24" width="18" height="18"> 300 329 <polyline points="6 9 6 2 18 2 18 9"></polyline> 301 330 <path d="M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2"></path> -
awesome-car-rental/trunk/includes/assets.php
r3775773 r3777386 175 175 'acrb-admin-extras-style', 176 176 ACRB_URL . 'assets/css/admin/admin-extra.css', 177 array( 'acrb-admin-main-style' ), 178 ACRB_VERSION 179 ); 180 break; 181 182 case 'settings': 183 wp_enqueue_style( 184 'acrb-admin-settings-style', 185 ACRB_URL . 'assets/css/admin/admin-settings.css', 186 array( 'acrb-admin-main-style' ), 187 ACRB_VERSION 188 ); 189 break; 190 191 case 'staff': 192 wp_enqueue_style( 193 'acrb-admin-staff-style', 194 ACRB_URL . 'assets/css/admin/admin-staff.css', 177 195 array( 'acrb-admin-main-style' ), 178 196 ACRB_VERSION -
awesome-car-rental/trunk/includes/database.php
r3775773 r3777386 11 11 12 12 if ( ! defined( 'ABSPATH' ) ) { 13 exit;13 exit; 14 14 } 15 15 16 16 if ( ! defined( 'ACRB_DB_VERSION' ) ) { 17 define( 'ACRB_DB_VERSION', '1.4.5' );17 define( 'ACRB_DB_VERSION', '1.4.6' ); 18 18 } 19 19 … … 22 22 */ 23 23 function acrb_create_custom_tables(): void { 24 global $wpdb;25 26 $table_cars = $wpdb->prefix . 'dev_nahian_cars';27 $table_bookings = $wpdb->prefix . 'dev_nahian_bookings';28 $table_categories = $wpdb->prefix . 'dev_nahian_categories';29 $table_staff = $wpdb->prefix . 'dev_nahian_staff';30 $table_customers = $wpdb->prefix . 'dev_nahian_customers';31 $table_inspections = $wpdb->prefix . 'dev_nahian_inspections';32 $table_maintenance = $wpdb->prefix . 'dev_nahian_maintenance';33 $table_promo = $wpdb->prefix . 'dev_nahian_promo_codes';34 $table_finance = $wpdb->prefix . 'dev_nahian_income_expense';35 36 $charset_collate = $wpdb->get_charset_collate();37 38 require_once ABSPATH . 'wp-admin/includes/upgrade.php';39 40 // 1. Cars Table Schema41 $sql_cars = "CREATE TABLE {$table_cars} (42 id mediumint(9) NOT NULL AUTO_INCREMENT,43 name varchar(255) NOT NULL,44 brand varchar(255) DEFAULT '',45 year int(4) DEFAULT 2026,46 vin varchar(100) DEFAULT '',47 plate varchar(50) DEFAULT '',48 category varchar(100) DEFAULT '',49 color varchar(50) DEFAULT '',50 status varchar(50) DEFAULT 'active',51 description longtext DEFAULT '',52 pickup_locations longtext DEFAULT '',53 dropoff_locations longtext DEFAULT '',54 insurance_plans longtext DEFAULT '',55 border_crossing longtext DEFAULT '',56 seasonal_rates longtext DEFAULT '',57 transmission varchar(50) DEFAULT 'Automatic',58 fuel varchar(50) DEFAULT 'Petrol',59 seats int(3) DEFAULT 5,60 bags int(3) DEFAULT 2,61 min_days int(3) DEFAULT 1,62 price decimal(10,2) DEFAULT 0.00,63 odometer int(10) DEFAULT 0,64 fuel_level int(3) DEFAULT 100,65 image longtext DEFAULT '',66 gallery longtext DEFAULT '',67 video varchar(255) DEFAULT '',68 notes longtext DEFAULT '',69 created_at datetime DEFAULT CURRENT_TIMESTAMP,70 PRIMARY KEY (id),71 KEY status (status),72 KEY category (category)73 ) {$charset_collate};";74 75 // 2. Bookings Table Schema (Fully Updated with Insurance, Border Permits & Promo Codes)24 global $wpdb; 25 26 $table_cars = $wpdb->prefix . 'dev_nahian_cars'; 27 $table_bookings = $wpdb->prefix . 'dev_nahian_bookings'; 28 $table_categories = $wpdb->prefix . 'dev_nahian_categories'; 29 $table_staff = $wpdb->prefix . 'dev_nahian_staff'; 30 $table_customers = $wpdb->prefix . 'dev_nahian_customers'; 31 $table_inspections = $wpdb->prefix . 'dev_nahian_inspections'; 32 $table_maintenance = $wpdb->prefix . 'dev_nahian_maintenance'; 33 $table_promo = $wpdb->prefix . 'dev_nahian_promo_codes'; 34 $table_finance = $wpdb->prefix . 'dev_nahian_income_expense'; 35 36 $charset_collate = $wpdb->get_charset_collate(); 37 38 require_once ABSPATH . 'wp-admin/includes/upgrade.php'; 39 40 // 1. Cars Table Schema 41 $sql_cars = "CREATE TABLE {$table_cars} ( 42 id mediumint(9) NOT NULL AUTO_INCREMENT, 43 name varchar(255) NOT NULL, 44 brand varchar(255) DEFAULT '', 45 year int(4) DEFAULT 2026, 46 vin varchar(100) DEFAULT '', 47 plate varchar(50) DEFAULT '', 48 category varchar(100) DEFAULT '', 49 color varchar(50) DEFAULT '', 50 status varchar(50) DEFAULT 'active', 51 description longtext DEFAULT '', 52 pickup_locations longtext DEFAULT '', 53 dropoff_locations longtext DEFAULT '', 54 insurance_plans longtext DEFAULT '', 55 border_crossing longtext DEFAULT '', 56 seasonal_rates longtext DEFAULT '', 57 transmission varchar(50) DEFAULT 'Automatic', 58 fuel varchar(50) DEFAULT 'Petrol', 59 seats int(3) DEFAULT 5, 60 bags int(3) DEFAULT 2, 61 min_days int(3) DEFAULT 1, 62 price decimal(10,2) DEFAULT 0.00, 63 odometer int(10) DEFAULT 0, 64 fuel_level int(3) DEFAULT 100, 65 image longtext DEFAULT '', 66 gallery longtext DEFAULT '', 67 video varchar(255) DEFAULT '', 68 notes longtext DEFAULT '', 69 created_at datetime DEFAULT CURRENT_TIMESTAMP, 70 PRIMARY KEY (id), 71 KEY status (status), 72 KEY category (category) 73 ) {$charset_collate};"; 74 75 // 2. Bookings Table Schema (Synchronized with itemized fees, discounts, and subtotals) 76 76 $sql_bookings = "CREATE TABLE {$table_bookings} ( 77 77 id mediumint(9) NOT NULL AUTO_INCREMENT, … … 87 87 return_date datetime DEFAULT NULL, 88 88 insurance_plan varchar(255) DEFAULT '', 89 insurance_amount decimal(10,2) DEFAULT 0.00, 89 90 border_permit varchar(255) DEFAULT '', 91 border_amount decimal(10,2) DEFAULT 0.00, 90 92 promo_code varchar(50) DEFAULT '', 93 discount_amount decimal(10,2) DEFAULT 0.00, 94 base_subtotal decimal(10,2) DEFAULT 0.00, 91 95 total_amount decimal(10,2) DEFAULT 0.00, 92 96 payment_method varchar(50) DEFAULT 'pay_later', … … 96 100 ) {$charset_collate};"; 97 101 98 // 3. Categories Table Schema99 $sql_categories = "CREATE TABLE {$table_categories} (100 id mediumint(9) NOT NULL AUTO_INCREMENT,101 name varchar(255) NOT NULL,102 slug varchar(255) NOT NULL,103 description longtext DEFAULT '',104 image longtext DEFAULT '',105 created_at datetime DEFAULT CURRENT_TIMESTAMP,106 PRIMARY KEY (id),107 UNIQUE KEY slug (slug)108 ) {$charset_collate};";109 110 // 4. Staff Table Schema111 $sql_staff = "CREATE TABLE {$table_staff} (112 id mediumint(9) NOT NULL AUTO_INCREMENT,113 name varchar(255) NOT NULL,114 email varchar(255) DEFAULT '',115 phone varchar(100) DEFAULT '',116 role varchar(100) DEFAULT '',117 status varchar(50) DEFAULT 'active',118 created_at datetime DEFAULT CURRENT_TIMESTAMP,119 PRIMARY KEY (id)120 ) {$charset_collate};";121 122 // 5. Customers Table Schema123 $sql_customers = "CREATE TABLE {$table_customers} (124 id mediumint(9) NOT NULL AUTO_INCREMENT,125 user_id bigint(20) UNSIGNED DEFAULT 0,126 name varchar(255) NOT NULL,127 email varchar(255) DEFAULT '',128 phone varchar(100) DEFAULT '',129 license_number varchar(100) DEFAULT '',130 address longtext DEFAULT '',131 created_at datetime DEFAULT CURRENT_TIMESTAMP,132 PRIMARY KEY (id),133 KEY email (email(191)),134 KEY user_id (user_id)135 ) {$charset_collate};";136 137 // 6. Inspections Table Schema138 $sql_inspections = "CREATE TABLE {$table_inspections} (139 id mediumint(9) NOT NULL AUTO_INCREMENT,140 car_id mediumint(9) NOT NULL,141 car_name varchar(255) DEFAULT '',142 booking_id mediumint(9) DEFAULT 0,143 stage varchar(50) DEFAULT 'Check-Out',144 mileage varchar(100) DEFAULT '',145 fuel_level varchar(50) DEFAULT 'Full (100%)',146 cleanliness varchar(50) DEFAULT 'Clean',147 inspector varchar(255) DEFAULT '',148 damages longtext DEFAULT '',149 inspection_date datetime DEFAULT CURRENT_TIMESTAMP,150 created_at datetime DEFAULT CURRENT_TIMESTAMP,151 PRIMARY KEY (id)152 ) {$charset_collate};";153 154 // 7. Maintenance Table Schema155 $sql_maintenance = "CREATE TABLE {$table_maintenance} (156 id mediumint(9) NOT NULL AUTO_INCREMENT,157 car_name varchar(255) NOT NULL,158 service_type varchar(255) DEFAULT '',159 cost decimal(10,2) DEFAULT 0.00,160 date_in date DEFAULT NULL,161 status varchar(50) DEFAULT 'pending',162 notes longtext DEFAULT '',163 created_at datetime DEFAULT CURRENT_TIMESTAMP,164 PRIMARY KEY (id)165 ) {$charset_collate};";166 167 // 8. Promo Codes Table Schema168 $sql_promo = "CREATE TABLE {$table_promo} (169 id mediumint(9) NOT NULL AUTO_INCREMENT,170 code varchar(100) NOT NULL,171 discount_type varchar(50) DEFAULT 'percentage',172 discount_value decimal(10,2) DEFAULT 0.00,173 min_spend decimal(10,2) DEFAULT 0.00,174 expiry_date date DEFAULT NULL,175 max_uses mediumint(9) DEFAULT 0,176 status varchar(50) DEFAULT 'active',177 created_at datetime DEFAULT CURRENT_TIMESTAMP,178 PRIMARY KEY (id),179 UNIQUE KEY code (code)180 ) {$charset_collate};";181 182 // 9. Financials Table Schema183 $sql_finance = "CREATE TABLE {$table_finance} (184 id mediumint(9) NOT NULL AUTO_INCREMENT,185 type varchar(50) NOT NULL,186 category varchar(100) DEFAULT '',187 amount decimal(10,2) DEFAULT 0.00,188 transaction_date date DEFAULT NULL,189 description longtext DEFAULT '',190 created_at datetime DEFAULT CURRENT_TIMESTAMP,191 PRIMARY KEY (id)192 ) {$charset_collate};";193 194 dbDelta( $sql_cars );195 dbDelta( $sql_bookings );196 dbDelta( $sql_categories );197 dbDelta( $sql_staff );198 dbDelta( $sql_customers );199 dbDelta( $sql_inspections );200 dbDelta( $sql_maintenance );201 dbDelta( $sql_promo );202 dbDelta( $sql_finance );203 204 update_option( 'acrb_db_version', ACRB_DB_VERSION );102 // 3. Categories Table Schema 103 $sql_categories = "CREATE TABLE {$table_categories} ( 104 id mediumint(9) NOT NULL AUTO_INCREMENT, 105 name varchar(255) NOT NULL, 106 slug varchar(255) NOT NULL, 107 description longtext DEFAULT '', 108 image longtext DEFAULT '', 109 created_at datetime DEFAULT CURRENT_TIMESTAMP, 110 PRIMARY KEY (id), 111 UNIQUE KEY slug (slug) 112 ) {$charset_collate};"; 113 114 // 4. Staff Table Schema 115 $sql_staff = "CREATE TABLE {$table_staff} ( 116 id mediumint(9) NOT NULL AUTO_INCREMENT, 117 name varchar(255) NOT NULL, 118 email varchar(255) DEFAULT '', 119 phone varchar(100) DEFAULT '', 120 role varchar(100) DEFAULT '', 121 status varchar(50) DEFAULT 'active', 122 created_at datetime DEFAULT CURRENT_TIMESTAMP, 123 PRIMARY KEY (id) 124 ) {$charset_collate};"; 125 126 // 5. Customers Table Schema 127 $sql_customers = "CREATE TABLE {$table_customers} ( 128 id mediumint(9) NOT NULL AUTO_INCREMENT, 129 user_id bigint(20) UNSIGNED DEFAULT 0, 130 name varchar(255) NOT NULL, 131 email varchar(255) DEFAULT '', 132 phone varchar(100) DEFAULT '', 133 license_number varchar(100) DEFAULT '', 134 address longtext DEFAULT '', 135 created_at datetime DEFAULT CURRENT_TIMESTAMP, 136 PRIMARY KEY (id), 137 KEY email (email(191)), 138 KEY user_id (user_id) 139 ) {$charset_collate};"; 140 141 // 6. Inspections Table Schema 142 $sql_inspections = "CREATE TABLE {$table_inspections} ( 143 id mediumint(9) NOT NULL AUTO_INCREMENT, 144 car_id mediumint(9) NOT NULL, 145 car_name varchar(255) DEFAULT '', 146 booking_id mediumint(9) DEFAULT 0, 147 stage varchar(50) DEFAULT 'Check-Out', 148 mileage varchar(100) DEFAULT '', 149 fuel_level varchar(50) DEFAULT 'Full (100%)', 150 cleanliness varchar(50) DEFAULT 'Clean', 151 inspector varchar(255) DEFAULT '', 152 damages longtext DEFAULT '', 153 inspection_date datetime DEFAULT CURRENT_TIMESTAMP, 154 created_at datetime DEFAULT CURRENT_TIMESTAMP, 155 PRIMARY KEY (id) 156 ) {$charset_collate};"; 157 158 // 7. Maintenance Table Schema 159 $sql_maintenance = "CREATE TABLE {$table_maintenance} ( 160 id mediumint(9) NOT NULL AUTO_INCREMENT, 161 car_name varchar(255) NOT NULL, 162 service_type varchar(255) DEFAULT '', 163 cost decimal(10,2) DEFAULT 0.00, 164 date_in date DEFAULT NULL, 165 status varchar(50) DEFAULT 'pending', 166 notes longtext DEFAULT '', 167 created_at datetime DEFAULT CURRENT_TIMESTAMP, 168 PRIMARY KEY (id) 169 ) {$charset_collate};"; 170 171 // 8. Promo Codes Table Schema 172 $sql_promo = "CREATE TABLE {$table_promo} ( 173 id mediumint(9) NOT NULL AUTO_INCREMENT, 174 code varchar(100) NOT NULL, 175 discount_type varchar(50) DEFAULT 'percentage', 176 discount_value decimal(10,2) DEFAULT 0.00, 177 min_spend decimal(10,2) DEFAULT 0.00, 178 expiry_date date DEFAULT NULL, 179 max_uses mediumint(9) DEFAULT 0, 180 status varchar(50) DEFAULT 'active', 181 created_at datetime DEFAULT CURRENT_TIMESTAMP, 182 PRIMARY KEY (id), 183 UNIQUE KEY code (code) 184 ) {$charset_collate};"; 185 186 // 9. Financials Table Schema 187 $sql_finance = "CREATE TABLE {$table_finance} ( 188 id mediumint(9) NOT NULL AUTO_INCREMENT, 189 type varchar(50) NOT NULL, 190 category varchar(100) DEFAULT '', 191 amount decimal(10,2) DEFAULT 0.00, 192 transaction_date date DEFAULT NULL, 193 description longtext DEFAULT '', 194 created_at datetime DEFAULT CURRENT_TIMESTAMP, 195 PRIMARY KEY (id) 196 ) {$charset_collate};"; 197 198 dbDelta( $sql_cars ); 199 dbDelta( $sql_bookings ); 200 dbDelta( $sql_categories ); 201 dbDelta( $sql_staff ); 202 dbDelta( $sql_customers ); 203 dbDelta( $sql_inspections ); 204 dbDelta( $sql_maintenance ); 205 dbDelta( $sql_promo ); 206 dbDelta( $sql_finance ); 207 208 update_option( 'acrb_db_version', ACRB_DB_VERSION ); 205 209 } 206 210 … … 210 214 */ 211 215 function acrb_activate_plugin_database(): void { 212 acrb_create_custom_tables();213 delete_transient( 'acrb_dashboard_revenue' );216 acrb_create_custom_tables(); 217 delete_transient( 'acrb_dashboard_revenue' ); 214 218 } 215 219 if ( defined( 'ACRB_PLUGIN_FILE' ) ) { 216 register_activation_hook( ACRB_PLUGIN_FILE, 'acrb_activate_plugin_database' );220 register_activation_hook( ACRB_PLUGIN_FILE, 'acrb_activate_plugin_database' ); 217 221 } 218 222 … … 222 226 */ 223 227 function acrb_deactivate_plugin_database(): void { 224 delete_transient( 'acrb_dashboard_revenue' );225 wp_cache_flush();228 delete_transient( 'acrb_dashboard_revenue' ); 229 wp_cache_flush(); 226 230 } 227 231 if ( defined( 'ACRB_PLUGIN_FILE' ) ) { 228 register_deactivation_hook( ACRB_PLUGIN_FILE, 'acrb_deactivate_plugin_database' );232 register_deactivation_hook( ACRB_PLUGIN_FILE, 'acrb_deactivate_plugin_database' ); 229 233 } 230 234 … … 234 238 */ 235 239 function acrb_maybe_create_custom_tables(): void { 236 $current_db_version = get_option( 'acrb_db_version', '0' );237 238 if ( version_compare( (string) $current_db_version, ACRB_DB_VERSION, '<' ) ) {239 acrb_create_custom_tables();240 return;241 }242 243 global $wpdb;244 245 $required_tables = array(246 $wpdb->prefix . 'dev_nahian_cars',247 $wpdb->prefix . 'dev_nahian_bookings',248 $wpdb->prefix . 'dev_nahian_categories',249 $wpdb->prefix . 'dev_nahian_staff',250 $wpdb->prefix . 'dev_nahian_customers',251 $wpdb->prefix . 'dev_nahian_inspections',252 $wpdb->prefix . 'dev_nahian_maintenance',253 $wpdb->prefix . 'dev_nahian_promo_codes',254 $wpdb->prefix . 'dev_nahian_income_expense',255 );256 257 foreach ( $required_tables as $table_name ) {258 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching259 if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) !== $table_name ) {260 acrb_create_custom_tables();261 break;262 }263 }240 $current_db_version = get_option( 'acrb_db_version', '0' ); 241 242 if ( version_compare( (string) $current_db_version, ACRB_DB_VERSION, '<' ) ) { 243 acrb_create_custom_tables(); 244 return; 245 } 246 247 global $wpdb; 248 249 $required_tables = array( 250 $wpdb->prefix . 'dev_nahian_cars', 251 $wpdb->prefix . 'dev_nahian_bookings', 252 $wpdb->prefix . 'dev_nahian_categories', 253 $wpdb->prefix . 'dev_nahian_staff', 254 $wpdb->prefix . 'dev_nahian_customers', 255 $wpdb->prefix . 'dev_nahian_inspections', 256 $wpdb->prefix . 'dev_nahian_maintenance', 257 $wpdb->prefix . 'dev_nahian_promo_codes', 258 $wpdb->prefix . 'dev_nahian_income_expense', 259 ); 260 261 foreach ( $required_tables as $table_name ) { 262 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching 263 if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) ) !== $table_name ) { 264 acrb_create_custom_tables(); 265 break; 266 } 267 } 264 268 } 265 269 add_action( 'admin_init', 'acrb_maybe_create_custom_tables' ); -
awesome-car-rental/trunk/readme.txt
r3775781 r3777386 3 3 Tags: car rental, vehicle booking, rental history, car rental crm, car booking, custom database architecture, checkout engine, seo schema 4 4 Requires at least: 5.8 5 Tested up to: 6.95 Tested up to: 7.1.4 6 6 Requires PHP: 7.4 7 Stable tag: 1.2 7 Stable tag: 1.2.1 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)