Plugin Directory

Changeset 3777386


Ignore:
Timestamp:
10/31/2026 09:47:24 PM (4 hours ago)
Author:
nahian91
Message:

Version 1.2.1

Location:
awesome-car-rental
Files:
356 added
1 deleted
23 edited

Legend:

Unmodified
Added
Removed
  • awesome-car-rental/trunk/assets/css/frontend/account.css

    r3775773 r3777386  
    11/* ==========================================================================
    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
    34   ========================================================================== */
    45
    … …  
    78.acrb-auth-locked,
    89#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;
    1315  --acrb-btn-bg: #4f46e5;
    1416  --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
    2823.acrb-acc-wrapper *,
    2924.acrb-acc-wrapper *::before,
    3025.acrb-acc-wrapper *::after,
    31 .acrb-auth-locked,
    3226.acrb-auth-locked *,
    3327.acrb-auth-locked *::before,
    3428.acrb-auth-locked *::after,
    35 #acrb-receipt-modal,
    3629#acrb-receipt-modal *,
    3730#acrb-receipt-modal *::before,
    3831#acrb-receipt-modal *::after {
    39   box-sizing: border-box;
    40 }
    41 
     32  box-sizing: inherit;
     33}
     34
     35/* Universal SVG Icon Standards */
    4236.acrb-icon {
    4337  display: inline-block;
    … …  
    5448
    5549/* --------------------------------------------------------------------------
    56    Auth Lock Screen (Logged Out)
     50   Auth Lock Screen (Logged Out State)
    5751   -------------------------------------------------------------------------- */
    5852.acrb-auth-locked {
    59   max-width: 440px;
     53  max-width: 520px;
    6054  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;
    62131  background: #ffffff;
    63132  border: 1px solid #e2e8f0;
    64133  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
    144138.acrb-nav-user {
    145139  display: flex;
    146140  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;
    154145}
    155146
    156147.acrb-nav-avatar img {
    157148  border-radius: 50%;
     149  width: 46px;
     150  height: 46px;
    158151  object-fit: cover;
    159152  display: block;
    … …  
    162155.acrb-nav-info strong {
    163156  display: block;
    164   color: var(--acrb-portal-text);
    165   font-size: 14.5px;
     157  font-size: 0.95rem;
    166158  font-weight: 800;
    167   line-height: 1.25;
     159  color: var(--acrb-portal-text, #0f172a);
    168160}
    169161
    170162.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);
    176165}
    177166
    … …  
    180169  padding: 0;
    181170  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;
    187174}
    188175
    … …  
    190177  display: flex;
    191178  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);
    197183  font-weight: 600;
     184  font-size: 0.9rem;
    198185  cursor: pointer;
    199   transition: all 0.15s ease;
     186  text-decoration: none !important;
     187  transition: all 0.2s ease;
    200188  border-left: 3px solid transparent;
    201189}
    202190
    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);
    206194}
    207195
    208196#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 {
    224210  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 {
    229214  background: #fef2f2 !important;
    230215}
    231216
    232 .acrb-nav-logout a .acrb-icon {
    233   color: #dc2626 !important;
    234 }
    235 
    236217/* --------------------------------------------------------------------------
    237    Tabs & Header (Solid Minimalist, No Gradients)
     218   Main Content Panels
    238219   -------------------------------------------------------------------------- */
     220.acrb-acc-content {
     221  flex: 1;
     222  min-width: 0;
     223}
     224
    239225.acrb-tab-panel {
    240226  display: none;
    … …  
    258244
    259245.acrb-panel-title {
    260   font-size: 17px;
     246  font-size: 1.45rem;
    261247  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);
    265251}
    266252
    … …  
    268254  background: #ffffff;
    269255  border: 1px solid #e2e8f0;
    270   border-left: 4px solid var(--acrb-portal-primary);
     256  border-left: 4px solid var(--acrb-portal-primary, #4f46e5);
    271257  border-radius: 14px;
    272258  padding: 22px 26px;
    … …  
    276262
    277263.acrb-dash-header h2 {
    278   margin: 0 0 4px;
    279   font-size: 20px;
     264  font-size: 1.55rem;
    280265  font-weight: 800;
    281   color: var(--acrb-portal-text);
     266  margin: 0 0 6px 0;
    282267  letter-spacing: -0.02em;
     268  color: var(--acrb-portal-text, #0f172a);
    283269}
    284270
    285271.acrb-dash-header p {
     272  color: var(--acrb-portal-secondary, #64748b);
    286273  margin: 0;
    287   color: var(--acrb-portal-secondary);
    288   font-size: 13.5px;
     274  font-size: 0.92rem;
    289275}
    290276
    … …  
    293279  grid-template-columns: repeat(2, 1fr);
    294280  gap: 18px;
    295   margin-bottom: 22px;
     281  margin-bottom: 24px;
    296282}
    297283
    … …  
    299285  background: #ffffff;
    300286  border: 1px solid #e2e8f0;
     287  border-radius: 16px;
    301288  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);
    305290  display: flex;
    306291  flex-direction: column;
    307   align-items: center;
    308   gap: 6px;
     292  align-items: flex-start;
    309293}
    310294
    … …  
    312296  width: 44px;
    313297  height: 44px;
    314   background: #f1f5f9;
    315   color: var(--acrb-portal-primary);
    316298  border-radius: 12px;
     299  background: #eef2ff;
     300  color: var(--acrb-portal-primary, #4f46e5);
    317301  display: flex;
    318302  align-items: center;
    319303  justify-content: center;
    320 }
    321 
    322 .acrb-stat-icon .acrb-icon {
    323   width: 22px;
    324   height: 22px;
     304  margin-bottom: 12px;
    325305}
    326306
    327307.acrb-stat-val {
    328   font-size: 24px;
     308  font-size: 1.7rem;
    329309  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;
    332313}
    333314
    334315.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;
    340319}
    341320
    342321.acrb-promo-banner {
    343   background: var(--acrb-portal-primary);
     322  background: var(--acrb-portal-text, #0f172a);
    344323  color: #ffffff;
    345   border-radius: 14px;
     324  border-radius: 16px;
    346325  padding: 24px 28px;
    347326  display: flex;
    348327  justify-content: space-between;
    349328  align-items: center;
    350   box-shadow: 0 4px 20px -2px rgba(15, 23, 42, 0.15);
    351   gap: 16px;
     329  gap: 20px;
    352330}
    353331
    354332.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;
    357336  font-weight: 800;
    358   color: #ffffff;
    359337}
    360338
    361339.acrb-promo-content p {
    362340  margin: 0;
    363   font-size: 13.5px;
    364   opacity: 0.9;
    365   color: #ffffff;
     341  font-size: 0.85rem;
     342  color: #94a3b8;
    366343}
    367344
    368345.acrb-btn-white {
    369346  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;
    378353  display: inline-flex;
    379354  align-items: center;
    380355  gap: 6px;
    381356  white-space: nowrap;
     357  transition: background 0.2s ease, transform 0.15s ease;
    382358}
    383359
    384360.acrb-btn-white:hover {
    385   background: #f8fafc;
     361  background: #f1f5f9;
    386362  transform: translateY(-1px);
    387363}
    388364
    389365/* --------------------------------------------------------------------------
    390    Bookings & Rental History
     366   Bookings & Rental History List
    391367   -------------------------------------------------------------------------- */
    392368.acrb-booking-card {
    393369  background: #ffffff;
    394370  border: 1px solid #e2e8f0;
    395   border-radius: 14px;
     371  border-radius: 16px;
     372  padding: 20px 24px;
    396373  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);
    399375  transition: border-color 0.15s ease, box-shadow 0.15s ease;
    400376}
    … …  
    407383.acrb-card-main {
    408384  display: flex;
    409   gap: 18px;
    410   padding: 20px 22px;
    411   align-items: center;
     385  gap: 16px;
     386  align-items: center;
     387  margin-bottom: 16px;
    412388}
    413389
    414390.acrb-car-icon {
    415   background: #f8fafc;
    416   color: var(--acrb-portal-primary);
    417391  width: 48px;
    418392  height: 48px;
    419393  min-width: 48px;
    420394  border-radius: 12px;
     395  background: #f8fafc;
    421396  border: 1px solid #e2e8f0;
    422397  display: flex;
    423398  align-items: center;
    424399  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;
    430402}
    431403
    432404.acrb-booking-details {
    433405  flex: 1;
     406  min-width: 0;
    434407}
    435408
    … …  
    443416.acrb-car-name {
    444417  margin: 0;
    445   font-size: 16px;
     418  font-size: 1.05rem;
    446419  font-weight: 800;
    447   color: var(--acrb-portal-text);
     420  color: var(--acrb-portal-text, #0f172a);
    448421}
    449422
    450423.acrb-status-pill {
    451   font-size: 11px;
     424  font-size: 0.74rem;
     425  font-weight: 700;
    452426  padding: 3px 10px;
    453427  border-radius: 9999px;
    454   font-weight: 700;
    455   text-transform: uppercase;
    456   letter-spacing: 0.04em;
     428  text-transform: capitalize;
    457429  display: inline-block;
    458430}
    459431
     432.status-confirmed,
    460433.status-completed,
    461 .status-confirmed,
    462 .status-active,
     434.status-active {
     435  background: #dcfce7;
     436  color: #15803d;
     437  border: 1px solid #a7f3d0;
     438}
     439
    463440.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;
    467444}
    468445
    469446.status-cancelled {
    470   background: #fef2f2;
    471   color: #dc2626;
     447  background: #fee2e2;
     448  color: #b91c1c;
    472449  border: 1px solid #fecaca;
    473450}
    … …  
    476453  display: flex;
    477454  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);
    481457  flex-wrap: wrap;
    482458}
    … …  
    488464}
    489465
    490 .acrb-meta-item .acrb-icon {
    491   width: 14px;
    492   height: 14px;
    493   color: var(--acrb-portal-secondary);
    494 }
    495 
    496466.acrb-card-footer {
    497   background: #f8fafc;
    498   padding: 14px 22px;
    499   border-top: 1px solid #f1f5f9;
    500467  display: flex;
    501468  justify-content: space-between;
    502469  align-items: center;
     470  padding-top: 14px;
     471  border-top: 1px dashed #e2e8f0;
    503472}
    504473
    … …  
    509478
    510479.acrb-price-label {
    511   font-size: 11px;
    512   color: var(--acrb-portal-secondary);
    513   font-weight: 700;
     480  font-size: 0.72rem;
    514481  text-transform: uppercase;
    515   letter-spacing: 0.04em;
     482  color: var(--acrb-portal-secondary, #64748b);
     483  font-weight: 700;
    516484}
    517485
    518486.acrb-price-amount {
     487  font-size: 1.15rem;
    519488  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
     492button.acrb-btn-outline,
    525493.acrb-btn-outline {
    526494  background: #ffffff;
    527   color: var(--acrb-portal-text);
    528495  border: 1px solid #cbd5e1;
    529   padding: 8px 16px;
     496  color: var(--acrb-portal-text, #0f172a);
     497  padding: 8px 14px;
    530498  border-radius: 8px;
    531499  font-weight: 700;
    532   font-size: 12.5px;
     500  font-size: 0.82rem;
    533501  cursor: pointer;
    534502  display: inline-flex;
    535503  align-items: center;
    536504  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;
    539506  font-family: inherit;
    540507}
    541508
     509button.acrb-btn-outline:hover,
    542510.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;
    551514}
    552515
    553516.acrb-empty-box {
     517  text-align: center;
    554518  padding: 48px 20px;
    555   text-align: center;
    556519  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);
    561523}
    562524
    … …  
    564526  width: 42px;
    565527  height: 42px;
     528  margin-bottom: 10px;
    566529  color: #cbd5e1;
    567   margin-bottom: 10px;
    568530}
    569531
    … …  
    575537
    576538/* --------------------------------------------------------------------------
    577    Forms & Controls
     539   Settings Forms & Controls
    578540   -------------------------------------------------------------------------- */
    579541.acrb-settings-form {
    580542  background: #ffffff;
    581543  border: 1px solid #e2e8f0;
    582   border-radius: 14px;
    583   padding: 28px;
    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);
    585547}
    586548
    587549.acrb-form-row {
    588   display: grid;
    589   grid-template-columns: 1fr 1fr;
    590   gap: 18px;
     550  display: flex;
     551  gap: 16px;
     552  margin-bottom: 16px;
    591553}
    592554
    593555.acrb-form-group {
    594   margin-bottom: 18px;
    595   display: flex;
    596   flex-direction: column;
     556  flex: 1;
    597557}
    598558
    599559.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;
    602566  margin-bottom: 6px;
    603   color: var(--acrb-portal-text);
    604567}
    605568
    … …  
    611574  padding: 0 14px !important;
    612575  font-size: 13.5px !important;
    613   color: var(--acrb-portal-text) !important;
     576  color: var(--acrb-portal-text, #0f172a) !important;
    614577  background: #f8fafc !important;
    615578  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important;
    … …  
    638601.acrb-textarea:focus {
    639602  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;
    642605  outline: none !important;
    643606}
    … …  
    645608.acrb-readonly {
    646609  background: #f1f5f9 !important;
    647   color: var(--acrb-portal-secondary) !important;
     610  color: var(--acrb-portal-secondary, #64748b) !important;
    648611  cursor: not-allowed !important;
    649612  border-color: #e2e8f0 !important;
    650613}
    651614
    652 .acrb-btn-submit {
    653   background-color: var(--acrb-btn-bg) !important;
    654   border-color: var(--acrb-btn-bg) !important;
     615button.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;
    655621  color: #ffffff !important;
    656622  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;
    661627  cursor: pointer;
    662628  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12);
    663629  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;
    668630  font-family: inherit;
    669631}
    670632
    671 .acrb-btn-submit:hover {
    672   background-color: var(--acrb-btn-hover) !important;
    673   border-color: var(--acrb-btn-hover) !important;
     633button.acrb-btn-submit:hover {
     634  background: var(--acrb-btn-hover, #4338ca) !important;
    674635  transform: translateY(-1px);
    675636}
    … …  
    680641}
    681642
    682 /* --------------------------------------------------------------------------
    683    Alerts & Notifications
    684    -------------------------------------------------------------------------- */
     643/* Alerts */
    685644.acrb-alert {
    686645  padding: 12px 16px;
    687   border-radius: 8px;
     646  border-radius: 10px;
    688647  margin-bottom: 20px;
    689   font-size: 13px;
     648  font-size: 0.88rem;
    690649  font-weight: 600;
    691   display: flex;
    692   align-items: center;
    693   gap: 8px;
    694650}
    695651
    696652.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;
    700656}
    701657
    702658.acrb-alert.error {
    703659  background: #fef2f2;
    704   color: #991b1b;
    705660  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;
    706726}
    707727
    … …  
    710730   -------------------------------------------------------------------------- */
    711731.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;
    712747  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);
    721748}
    722749
    723750.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;
    732760  border: 1px solid #e2e8f0;
    733   font-family: var(--acrb-portal-font);
    734761}
    735762
    736763.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;
    741767  cursor: pointer;
     768  font-size: 1.5rem;
     769  line-height: 1;
    742770  color: #94a3b8;
    743771  transition: color 0.15s ease;
    744   line-height: 1;
     772  z-index: 5;
    745773}
    746774
    … …  
    750778
    751779.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;
    754873  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 {
    764946  display: flex;
    765947  align-items: center;
    766948  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 {
    789976  display: flex;
    790977  flex-direction: column;
    791978  gap: 10px;
    792   margin-bottom: 20px;
    793 }
    794 
    795 .acrb-r-item {
     979}
     980
     981.acrb-fee-row {
    796982  display: flex;
    797983  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;
    8371036  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;
    8401061  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
     1066button.acrb-btn-print {
    8461067  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);
    8501070  color: #ffffff;
    851   border-radius: 8px;
    8521071  border: none;
    853   font-weight: 700;
    854   font-size: 13px;
     1072  border-radius: 10px;
     1073  font-weight: 700;
     1074  font-size: 0.9rem;
    8551075  cursor: pointer;
    856   transition: opacity 0.15s ease;
    8571076  display: inline-flex;
    8581077  align-items: center;
    8591078  justify-content: center;
    8601079  gap: 8px;
     1080  transition: background-color 0.2s ease;
    8611081  font-family: inherit;
    8621082}
    8631083
    864 .acrb-btn-print:hover {
    865   opacity: 0.88;
     1084button.acrb-btn-print:hover {
     1085  background: var(--acrb-btn-hover, #4338ca);
    8661086}
    8671087
    8681088/* --------------------------------------------------------------------------
    869    Responsive & Print Styles
     1089   Responsive & Print Rules
    8701090   -------------------------------------------------------------------------- */
    871 @media (max-width: 860px) {
     1091@media (max-width: 900px) {
    8721092  .acrb-acc-wrapper {
    8731093    flex-direction: column;
    … …  
    8751095  .acrb-acc-nav {
    8761096    width: 100%;
    877   }
    878   .acrb-form-row {
    879     grid-template-columns: 1fr;
    8801097  }
    8811098  .acrb-stats-grid {
    … …  
    8881105}
    8891106
     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
    8901122@media print {
    8911123  body * {
    … …  
    8971129  }
    8981130  #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;
    9061139  }
    9071140  .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;
    9121147  }
    9131148  .acrb-modal-close,
  • awesome-car-rental/trunk/assets/css/frontend/cars.css

    r3775773 r3777386  
    11/* ==========================================================================
    22   ACRB FLEET ARCHIVE (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/all-cars.css
    34   ========================================================================== */
    45
    … …  
    1415  --acrb-grid-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1516
    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
    2122.acrb-grid-wrapper *,
    2223.acrb-grid-wrapper *::before,
    2324.acrb-grid-wrapper *::after,
    24 .acrb-empty,
    2525.acrb-empty *,
    2626.acrb-empty *::before,
    2727.acrb-empty *::after {
    28   box-sizing: border-box;
     28  box-sizing: inherit;
    2929}
    3030
    … …  
    3434  padding: 60px 20px;
    3535  font-size: 14.5px;
    36   color: var(--acrb-grid-secondary);
     36  color: var(--acrb-grid-secondary, #64748b);
    3737}
    3838
    … …  
    4040.acrb-grid-wrapper {
    4141  padding: 30px 0;
    42   max-width: 1200px;
     42  max-width: 1400px;
    4343  margin: 0 auto;
     44  width: 100%;
     45  background: transparent;
    4446}
    4547
    4648.acrb-layout-container {
    4749  display: flex;
    48   gap: 30px;
    4950  align-items: flex-start;
     51  gap: 32px;
     52  position: relative;
    5053}
    5154
    … …  
    6568
    6669/* --------------------------------------------------------------------------
     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/* --------------------------------------------------------------------------
    67101   Filter Sidebar
    68102   -------------------------------------------------------------------------- */
    69103.acrb-filter-sidebar {
    70   width: 280px;
     104  width: 320px;
    71105  flex-shrink: 0;
    72106  background: #ffffff;
    73107  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
     145button.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
     158button.acrb-btn-clear:hover {
     159  color: var(--acrb-grid-primary, #4f46e5);
     160  background: #f1f5f9;
    77161}
    78162
    79163.acrb-filter-section {
    80   margin-bottom: 22px;
    81   padding-bottom: 20px;
    82   border-bottom: 1px solid #f1f5f9;
     164  margin-bottom: 24px;
    83165}
    84166
    85167.acrb-filter-section:last-child {
    86168  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;
    93175  text-transform: uppercase;
    94   letter-spacing: 0.05em;
    95   color: var(--acrb-grid-secondary);
    96   margin: 0 0 12px 0;
    97176  font-weight: 800;
     177  letter-spacing: 0.06em;
     178  color: #475569;
     179  margin-bottom: 12px;
    98180}
    99181
    100182.acrb-search-box {
    101183  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;
    102195}
    103196
    104197.acrb-search-box input {
    105198  width: 100% !important;
    106   height: 40px !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;
    111204  background: #f8fafc !important;
    112   color: var(--acrb-grid-text) !important;
     205  color: var(--acrb-grid-text, #0f172a) !important;
    113206  outline: none !important;
    114207  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;
    116210}
    117211
    118212.acrb-search-box input:focus {
    119213  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;
    129267  color: #94a3b8;
    130 }
    131 
     268  font-weight: 600;
     269}
     270
     271/* Category Item List */
    132272.acrb-filter-list {
    133273  list-style: none;
     274  margin: 0;
    134275  padding: 0;
    135   margin: 0;
    136276  display: flex;
    137277  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);
    138354  gap: 8px;
    139355}
    140356
    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;
    153367  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;
    166386  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);
    172399}
    173400
    174401/* --------------------------------------------------------------------------
    175    Content Header & View Toolbar
     402   Right Content Container & Top Toolbar
    176403   -------------------------------------------------------------------------- */
    177404.acrb-right-content {
    178405  flex: 1;
     406  width: 100%;
    179407  min-width: 0;
    180408}
    … …  
    182410.acrb-content-header {
    183411  display: flex;
     412  align-items: center;
    184413  justify-content: space-between;
    185   align-items: center;
    186414  background: #ffffff;
    187415  border: 1px solid #e2e8f0;
    188   border-radius: 14px;
    189   padding: 16px 20px;
     416  border-radius: 18px;
     417  padding: 14px 22px;
    190418  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;
    192422}
    193423
    194424.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;
    197459  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 */
    200474.acrb-view-toolbar {
    201475  display: flex;
    202   align-items: center;
    203   gap: 8px;
     476  background: #f1f5f9;
     477  padding: 3px;
     478  border-radius: 10px;
     479  gap: 2px;
    204480}
    205481
    206482button.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;
    209488  color: #64748b;
    210   width: 36px;
    211   height: 36px;
    212   border-radius: 8px;
    213489  display: flex;
    214490  align-items: center;
    215491  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
     495button.acrb-view-btn:hover {
     496  color: #0f172a;
     497}
     498
    221499button.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);
    225503}
    226504
    … …  
    230508.acrb-car-grid {
    231509  display: grid;
    232   grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
     510  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
    233511  gap: 24px;
     512  margin-bottom: 36px;
    234513}
    235514
    236515.acrb-car-card {
    237516  background: #ffffff;
    238   border-radius: 16px;
     517  border: 1px solid #e2e8f0;
     518  border-radius: 20px;
    239519  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;
    242520  display: flex;
    243521  flex-direction: column;
    244   border: 1px solid #e2e8f0;
     522  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
    245523  position: relative;
    246524}
    … …  
    248526.acrb-car-card:hover {
    249527  transform: translateY(-4px);
    250   box-shadow: 0 16px 30px -8px rgba(15, 23, 42, 0.1);
    251528  border-color: #cbd5e1;
     529  box-shadow: 0 18px 38px -12px rgba(15, 23, 42, 0.12);
    252530}
    253531
    254532.acrb-img-container {
    255533  position: relative;
    256   aspect-ratio: 16 / 10;
     534  width: 100%;
     535  height: 200px;
     536  background: #f8fafc;
    257537  overflow: hidden;
    258   background: #f8fafc;
    259538}
    260539
    … …  
    269548  height: 100%;
    270549  object-fit: cover;
     550  transition: transform 0.4s ease;
    271551  display: block;
    272   transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
    273552}
    274553
    275554.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;
    277566}
    278567
    … …  
    285574  -webkit-backdrop-filter: blur(8px);
    286575  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;
    291581  text-transform: uppercase;
    292   letter-spacing: 0.04em;
    293582  z-index: 2;
    294   border: 1px solid rgba(255, 255, 255, 0.18);
    295583}
    296584
    297585.acrb-card-body {
    298   padding: 22px;
     586  padding: 20px;
     587  display: flex;
     588  flex-direction: column;
    299589  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;
    308592}
    309593
    310594.acrb-card-title {
    311   font-size: 17px;
     595  margin: 0 0 14px 0;
     596  font-size: 1.12rem;
    312597  font-weight: 800;
    313   margin: 0 0 14px 0;
    314   line-height: 1.3;
    315   letter-spacing: -0.01em;
     598  line-height: 1.35;
    316599}
    317600
    318601.acrb-card-title a {
    319   text-decoration: none !important;
    320   color: var(--acrb-grid-text);
     602  color: #0f172a;
     603  text-decoration: none;
    321604  transition: color 0.15s ease;
    322605}
    323606
    324607.acrb-card-title a:hover {
    325   color: var(--acrb-grid-primary);
     608  color: var(--acrb-grid-primary, #4f46e5);
    326609}
    327610
    … …  
    329612  display: grid;
    330613  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;
    333639  padding-top: 14px;
    334640  border-top: 1px solid #f1f5f9;
    335641}
    336642
    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;
    343659  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);
    344737  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 {
    404755  display: inline-flex;
    405756  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;
    434757  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 */
    445766.acrb-no-cars-msg {
    446   display: none;
    447   grid-column: 1 / -1;
    448767  text-align: center;
    449768  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;
    451773}
    452774
    453775.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;
    458779}
    459780
    460781.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;
    464786}
    465787
    466788.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;
    525805}
    526806
    … …  
    528808   Responsive Breakpoints
    529809   -------------------------------------------------------------------------- */
    530 @media (max-width: 960px) {
     810@media (max-width: 980px) {
    531811  .acrb-layout-container {
    532812    flex-direction: column;
    533813  }
     814  .acrb-mobile-filter-bar {
     815    display: block;
     816  }
    534817  .acrb-filter-sidebar {
    535818    width: 100%;
     819    position: static;
     820    display: none;
     821    margin-bottom: 24px;
     822  }
     823  .acrb-filter-sidebar.is-open {
     824    display: block;
    536825  }
    537826  .acrb-car-grid.list-view .acrb-car-card {
    … …  
    540829  .acrb-car-grid.list-view .acrb-img-container {
    541830    width: 100%;
    542     aspect-ratio: 16 / 10;
     831    height: 200px;
    543832  }
    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  
    11/* ==========================================================================
    22   ACRB CHECKOUT COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/checkout.css
    34   ========================================================================== */
    45
    … …  
    1516  --acrb-checkout-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1617
    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
    2223.acrb-checkout-wrapper *,
    2324.acrb-checkout-wrapper *::before,
    2425.acrb-checkout-wrapper *::after,
    25 .acrb-redirect-notice,
    2626.acrb-redirect-notice *,
    2727.acrb-redirect-notice *::before,
    2828.acrb-redirect-notice *::after,
    29 .acrb-checkout-error,
    3029.acrb-checkout-error *,
    3130.acrb-checkout-error *::before,
    3231.acrb-checkout-error *::after {
    33   box-sizing: border-box;
     32  box-sizing: inherit;
    3433}
    3534
    … …  
    4140  text-align: center;
    4241  font-size: 15px;
    43   color: var(--acrb-checkout-secondary);
     42  color: var(--acrb-checkout-secondary, #64748b);
    4443}
    4544
    4645.acrb-checkout-error {
    47   max-width: 580px;
     46  max-width: 600px;
    4847  margin: 80px auto;
    49   padding: 50px 40px;
     48  text-align: center;
    5049  background: #ffffff;
    5150  border: 1px solid #e2e8f0;
    5251  border-radius: 20px;
    53   text-align: center;
    54   box-shadow: 0 10px 25px -5px rgba(15, 23, 42, 0.05);
     52  padding: 48px;
     53  box-shadow: 0 15px 30px -10px rgba(15, 23, 42, 0.08);
    5554}
    5655
    5756.acrb-checkout-error h3 {
    58   color: var(--acrb-checkout-text);
     57  color: var(--acrb-checkout-text, #0f172a);
    5958  margin-top: 0;
    60   font-size: 22px;
     59  font-size: 1.5rem;
    6160  font-weight: 900;
    6261  letter-spacing: -0.02em;
    … …  
    6463
    6564.acrb-checkout-error p {
    66   color: var(--acrb-checkout-secondary);
     65  color: var(--acrb-checkout-secondary, #64748b);
    6766  font-size: 14px;
    68   margin: 8px 0 28px 0;
    69   line-height: 1.6;
     67  margin: 8px 0 24px 0;
     68  line-height: 1.5;
    7069}
    7170
    7271.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);
    7574  color: #ffffff !important;
    76   padding: 12px 26px;
     75  padding: 12px 24px;
    7776  border-radius: 10px;
    7877  text-decoration: none;
    7978  font-weight: 700;
    8079  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;
    8383}
    8484
    8585.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);
    8888}
    8989
    9090/* --------------------------------------------------------------------------
    91    Checkout Core Layout
     91   Checkout Core Layout & Progress Steps
    9292   -------------------------------------------------------------------------- */
    9393.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;
    9697}
    9798
    … …  
    100101  width: 18px;
    101102  height: 18px;
    102   stroke-width: 2;
     103  stroke-width: 2.2;
    103104  stroke: currentColor;
    104105  fill: none;
    … …  
    109110}
    110111
    111 /* Progress Steps */
    112112.acrb-checkout-steps {
    113113  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;
    117119  background: #ffffff;
    118120  border: 1px solid #e2e8f0;
    119121  border-radius: 16px;
    120   padding: 20px 36px;
    121   box-shadow: 0 4px 16px -2px rgba(15, 23, 42, 0.03);
     122  padding: 16px 24px;
     123  box-shadow: 0 4px 15px rgba(15, 23, 42, 0.03);
    122124}
    123125
    … …  
    125127  display: flex;
    126128  align-items: center;
    127   gap: 12px;
    128   font-size: 14px;
     129  gap: 10px;
     130  font-size: 0.88rem;
    129131  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;
    131143}
    132144
    133145.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;
    135151}
    136152
    137153.acrb-step-num {
    138   width: 32px;
    139   height: 32px;
     154  width: 30px;
     155  height: 30px;
    140156  border-radius: 50%;
    141157  background: #f1f5f9;
    142   color: var(--acrb-checkout-secondary);
     158  color: #64748b;
    143159  display: flex;
    144160  align-items: center;
    145161  justify-content: center;
    146   font-size: 13px;
    147   font-weight: 800;
     162  font-size: 0.82rem;
     163  font-weight: 800;
     164  flex-shrink: 0;
    148165}
    149166
    150167.acrb-step-item.active .acrb-step-num {
    151   background: var(--acrb-checkout-primary);
     168  background: var(--acrb-checkout-primary, #4f46e5);
    152169  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;
    153176}
    154177
    … …  
    156179.acrb-checkout-grid {
    157180  display: grid;
    158   grid-template-columns: 1fr 480px;
    159   gap: 36px;
     181  grid-template-columns: 1fr 440px;
     182  gap: 32px;
    160183  align-items: flex-start;
    161184}
    … …  
    164187  background: #ffffff;
    165188  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);
    170193}
    171194
    172195.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 */
    186206.acrb-review-box {
    187207  background: #f8fafc;
    188208  border: 1px solid #e2e8f0;
    189   border-radius: 12px;
    190   padding: 20px;
     209  border-radius: 14px;
     210  padding: 18px;
    191211}
    192212
    193213.acrb-review-vehicle {
    194214  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;
    197220}
    198221
    199222.acrb-review-thumb {
    200   width: 140px;
    201   height: 95px;
     223  width: 90px;
     224  height: 65px;
    202225  border-radius: 10px;
    203226  overflow: hidden;
    204   border: 1px solid #cbd5e1;
    205227  background: #ffffff;
     228  border: 1px solid #e2e8f0;
    206229  flex-shrink: 0;
    207230}
    … …  
    215238
    216239.acrb-review-info h4 {
    217   margin: 0 0 6px 0;
    218   font-size: 19px;
    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);
    221244}
    222245
    223246.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);
    226249}
    227250
    228251.acrb-review-meta strong {
    229   color: var(--acrb-checkout-text);
     252  color: var(--acrb-checkout-text, #0f172a);
    230253}
    231254
    232255.acrb-itinerary-grid {
    233256  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;
    239259}
    240260
    … …  
    242262  background: #ffffff;
    243263  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;
    249266  display: flex;
    250267  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;
    262331}
    263332
    264333.acrb-itinerary-location {
    265   font-size: 11px;
     334  font-size: 0.8rem;
     335  color: #475569;
    266336  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 */
    271350.acrb-checkout-field {
    272   margin-bottom: 18px;
    273 }
    274 
    275 .acrb-checkout-field-last {
    276   margin-bottom: 0;
     351  margin-bottom: 14px;
    277352}
    278353
    279354.acrb-checkout-field label {
    280355  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;
    285362}
    286363
    287364.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;
    301377}
    302378
    303379.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);
    306383}
    307384
    308385.acrb-checkout-input:read-only {
    309   background: #f1f5f9 !important;
    310   color: var(--acrb-checkout-secondary) !important;
     386  background: #f1f5f9;
     387  color: #475569;
    311388  cursor: not-allowed;
    312389}
    313390
    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;
    317428}
    318429
    … …  
    320431.acrb-coupon-wrap {
    321432  display: flex;
    322   gap: 10px;
     433  gap: 8px;
     434}
     435
     436.acrb-input-compact {
     437  flex: 1;
    323438}
    324439
    325440button.acrb-coupon-btn {
    326   background: var(--acrb-checkout-btn-bg);
     441  background: #0f172a;
    327442  color: #ffffff;
    328443  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;
    333448  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;
    336451}
    337452
    338453button.acrb-coupon-btn:hover {
    339   background: var(--acrb-checkout-btn-hover);
    340   opacity: 0.94;
     454  background: var(--acrb-checkout-primary, #4f46e5);
    341455}
    342456
    343457.acrb-coupon-msg {
    344   font-size: 12.5px;
    345   font-weight: 700;
     458  display: none;
     459  font-size: 0.8rem;
     460  font-weight: 600;
    346461  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 */
    384465.acrb-breakdown-card {
    385466  background: #f8fafc;
    386467  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;
    392471}
    393472
    … …  
    395474  display: flex;
    396475  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;
    407497}
    408498
    409499.acrb-bd-discount {
    410500  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;
    429507}
    430508
    … …  
    432510  display: flex;
    433511  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;
    438523  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 */
    448529.acrb-terms-wrap {
    449   margin: 20px 0 14px 0;
     530  margin-bottom: 20px;
    450531}
    451532
    … …  
    454535  align-items: flex-start;
    455536  gap: 10px;
     537  font-size: 0.82rem;
     538  color: #475569;
    456539  cursor: pointer;
    457   font-size: 13px;
    458   color: var(--acrb-checkout-secondary);
    459   font-weight: 700;
     540  line-height: 1.4;
    460541}
    461542
    462543.acrb-terms-check {
    463   margin-top: 3px;
     544  margin-top: 2px;
     545  accent-color: var(--acrb-checkout-primary, #4f46e5);
    464546  width: 16px;
    465547  height: 16px;
    466   accent-color: var(--acrb-checkout-primary);
    467 }
    468 
    469 /* Submit Reservation Button */
     548  cursor: pointer;
     549}
     550
    470551button.acrb-btn-confirm {
    471552  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);
    475555  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;
    479564  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);
    484567  font-family: inherit;
    485   transition: all 0.15s ease;
    486   box-shadow: 0 4px 14px rgba(79, 70, 229, 0.25);
    487568}
    488569
    489570button.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);
    493572  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 {
    498577  width: 18px;
    499578  height: 18px;
    … …  
    501580
    502581/* --------------------------------------------------------------------------
    503    Responsive Rules
     582   Responsive Breakpoints
    504583   -------------------------------------------------------------------------- */
    505 @media (max-width: 900px) {
     584@media (max-width: 980px) {
    506585  .acrb-checkout-grid {
    507586    grid-template-columns: 1fr;
    508587  }
     588}
     589
     590@media (max-width: 600px) {
     591  .acrb-itinerary-grid {
     592    grid-template-columns: 1fr;
     593  }
    509594  .acrb-checkout-steps {
     595    flex-direction: column;
     596    align-items: flex-start;
     597    padding: 16px;
     598  }
     599  .acrb-step-item:not(:last-child):after {
    510600    display: none;
    511601  }
  • awesome-car-rental/trunk/assets/css/frontend/header-auth.css

    r3775773 r3777386  
    11/* ==========================================================================
    22   ACRB HEADER AUTH WIDGET (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/header-auth.css
    34   ========================================================================== */
    45
    … …  
    1213  --acrb-auth-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1314
    14   font-family: var(--acrb-auth-font);
     15  font-family: var(--acrb-auth-font, sans-serif);
    1516  display: inline-flex;
    1617  align-items: center;
     18  position: relative;
    1719  box-sizing: border-box;
    18   color: var(--acrb-auth-text);
     20  color: var(--acrb-auth-text, #0f172a);
    1921}
    2022
    21 .acrb-header-auth,
    2223.acrb-header-auth *,
    2324.acrb-header-auth *::before,
    2425.acrb-header-auth *::after {
    25   box-sizing: border-box;
     26  box-sizing: inherit;
    2627}
    2728
    … …  
    2930.acrb-header-auth .acrb-auth-svg {
    3031  display: inline-block;
    31   width: 16px;
    32   height: 16px;
    33   stroke-width: 2;
     32  width: 15px;
     33  height: 15px;
    3434  stroke: currentColor;
    3535  fill: none;
     36  stroke-width: 2.2;
    3637  stroke-linecap: round;
    3738  stroke-linejoin: round;
    … …  
    5354  border: 1px solid #e2e8f0;
    5455  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;
    5657}
    5758
    5859.acrb-header-auth .acrb-user-wrapper:hover {
    59   border-color: #cbd5e1;
     60  border-color: var(--acrb-auth-primary, #4f46e5);
     61  background: #ffffff;
    6062  box-shadow: 0 4px 12px -2px rgba(15, 23, 42, 0.08);
    6163  transform: translateY(-1px);
    … …  
    7476  align-items: center;
    7577  justify-content: center;
     78  flex-shrink: 0;
    7679}
    7780
    … …  
    9295.acrb-header-auth .acrb-user-greeting {
    9396  font-size: 10px;
    94   color: var(--acrb-auth-secondary);
     97  color: var(--acrb-auth-secondary, #64748b);
    9598  font-weight: 700;
    9699  text-transform: uppercase;
    … …  
    101104  font-size: 13px;
    102105  font-weight: 800;
    103   color: var(--acrb-auth-text);
    104   max-width: 120px;
     106  color: var(--acrb-auth-text, #0f172a);
     107  max-width: 130px;
    105108  overflow: hidden;
    106109  text-overflow: ellipsis;
    … …  
    109112
    110113.acrb-header-auth .acrb-user-chevron {
    111   color: var(--acrb-auth-secondary);
     114  color: #94a3b8;
    112115  margin-left: 2px;
    113   transition: transform 0.15s ease, color 0.15s ease;
     116  transition: transform 0.2s ease, color 0.2s ease;
    114117}
    115118
    116119.acrb-header-auth .acrb-user-wrapper:hover .acrb-user-chevron {
    117120  transform: translateX(2px);
    118   color: var(--acrb-auth-primary);
     121  color: var(--acrb-auth-primary, #4f46e5);
    119122}
    120123
    … …  
    132135  align-items: center;
    133136  justify-content: center;
    134   gap: 7px;
     137  gap: 6px;
    135138  text-decoration: none !important;
    136139  font-size: 13px;
    … …  
    139142  border-radius: 8px;
    140143  height: 38px;
     144  line-height: 1;
    141145  transition: all 0.15s ease;
    142   box-sizing: border-box;
    143146  white-space: nowrap;
     147  font-family: inherit;
    144148}
    145149
    146150/* Login Button */
    147151.acrb-header-auth .acrb-h-login {
    148   background: #ffffff;
    149   color: var(--acrb-auth-text) !important;
     152  background: #f8fafc;
     153  color: var(--acrb-auth-text, #0f172a) !important;
    150154  border: 1px solid #cbd5e1;
    151155  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.03);
    … …  
    153157
    154158.acrb-header-auth .acrb-h-login .acrb-auth-svg {
    155   color: var(--acrb-auth-secondary);
     159  color: var(--acrb-auth-secondary, #64748b);
    156160  transition: color 0.15s ease;
    157161}
    158162
    159163.acrb-header-auth .acrb-h-login:hover {
    160   background: #f8fafc;
     164  background: #f1f5f9;
    161165  border-color: #94a3b8;
    162   color: var(--acrb-auth-text) !important;
     166  color: var(--acrb-auth-text, #0f172a) !important;
    163167  transform: translateY(-1px);
    164168}
    165169
    166170.acrb-header-auth .acrb-h-login:hover .acrb-auth-svg {
    167   color: var(--acrb-auth-primary);
     171  color: var(--acrb-auth-primary, #4f46e5);
    168172}
    169173
    170 /* Register Button (Uses Customizer Button Colors) */
     174/* Register Button */
    171175.acrb-header-auth .acrb-h-reg {
    172   background: var(--acrb-auth-btn-bg);
     176  background: var(--acrb-auth-btn-bg, #4f46e5);
    173177  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);
    176180}
    177181
    … …  
    181185
    182186.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);
    185189  opacity: 0.94;
    186190  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);
    188192  color: #ffffff !important;
    189193}
  • awesome-car-rental/trunk/assets/css/frontend/login.css

    r3775773 r3777386  
    11/* ==========================================================================
    22   ACRB LOGIN COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/login.css
    34   ========================================================================== */
    45
    56/* Scoped Variable Fallbacks & Font/Text Colors */
    6 .acrb-auth-page-wrapper {
     7.acrb-auth-page-wrapper,
     8.acrb-auth-solo-wrapper {
    79  --acrb-login-primary: #4f46e5;
    810  --acrb-login-secondary: #64748b;
    … …  
    1315  --acrb-login-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1416
    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);
    2519  box-sizing: border-box;
    2620}
    2721
    28 .acrb-auth-page-wrapper,
    2922.acrb-auth-page-wrapper *,
    3023.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;
    3329}
    3430
    … …  
    3632   SVG Icon Standards
    3733   -------------------------------------------------------------------------- */
    38 .acrb-auth-page-wrapper .acrb-login-icon {
     34.acrb-login-icon {
    3935  display: inline-block;
    4036  width: 18px;
    … …  
    5046
    5147/* --------------------------------------------------------------------------
     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/* --------------------------------------------------------------------------
    5270   Side Info Panel (Solid Dark Theme - No Gradients)
    5371   -------------------------------------------------------------------------- */
    54 .acrb-auth-page-wrapper .acrb-auth-side-info {
     72.acrb-auth-side-info {
    5573  flex: 1;
    56   background: var(--acrb-login-text);
     74  background: var(--acrb-login-text, #0f172a);
    5775  padding: 50px 40px;
    5876  color: #ffffff;
    … …  
    6381}
    6482
    65 .acrb-auth-page-wrapper .acrb-auth-side-info h2 {
     83.acrb-auth-side-info h2 {
    6684  color: #ffffff !important;
    6785  font-size: 28px;
    … …  
    7290}
    7391
    74 .acrb-auth-page-wrapper .acrb-auth-side-info p {
     92.acrb-auth-side-info p {
    7593  color: #94a3b8;
    7694  line-height: 1.55;
    … …  
    7997}
    8098
    81 .acrb-auth-page-wrapper .acrb-auth-security-badge {
     99.acrb-auth-security-badge {
    82100  margin-top: 28px;
    83101  display: flex;
    … …  
    90108}
    91109
    92 .acrb-auth-page-wrapper .acrb-badge-icon {
     110.acrb-badge-icon {
    93111  color: #60a5fa;
    94112  width: 22px;
    95113  height: 22px;
    96 }
    97 
    98 .acrb-auth-page-wrapper .acrb-badge-text {
     114  flex-shrink: 0;
     115}
     116
     117.acrb-badge-text {
    99118  font-size: 12.5px;
    100119  color: #cbd5e1;
    … …  
    105124   Form Card & Controls
    106125   -------------------------------------------------------------------------- */
     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
    107136.acrb-auth-page-wrapper .acrb-auth-card {
    108137  flex: 1.2;
    109138  padding: 50px 40px;
    110   background: #ffffff;
     139  border: none;
     140  max-width: none;
     141  box-shadow: none;
    111142  display: flex;
    112143  flex-direction: column;
    113144  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;
    114153}
    115154
    … …  
    117156  font-size: 24px;
    118157  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);
    122164}
    123165
    124166.acrb-auth-page-wrapper .acrb-auth-subtitle {
    125   color: var(--acrb-login-secondary);
     167  margin-bottom: 28px;
    126168  font-size: 13.5px;
    127   margin: 0 0 28px 0;
     169}
     170
     171.acrb-login-field {
     172  margin-bottom: 18px;
    128173}
    129174
    … …  
    136181}
    137182
    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 {
    139238  display: flex;
    140239  justify-content: space-between;
    … …  
    143242}
    144243
    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;
    147254}
    148255
    149256.acrb-auth-page-wrapper .acrb-forgot-link {
    150257  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 {
    158261  text-decoration: underline;
    159262  opacity: 0.9;
    160263}
    161264
    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 
    196265/* --------------------------------------------------------------------------
    197266   Buttons & Status Messages
    198267   -------------------------------------------------------------------------- */
    199 .acrb-auth-page-wrapper .acrb-login-btn {
     268.acrb-login-btn {
    200269  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);
    204272  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;
    213278  align-items: center;
    214279  justify-content: center;
    215280  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;
    216285  font-family: inherit;
    217286}
    218287
    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);
    222300  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;
    224308}
    225309
    … …  
    227311  background: #94a3b8 !important;
    228312  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;
    236318  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 {
    238324  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;
    258349}
    259350
    … …  
    261352  color: #991b1b;
    262353  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;
    276375}
    277376
    … …  
    284383    margin: 20px;
    285384  }
    286   .acrb-auth-page-wrapper .acrb-auth-side-info {
     385  .acrb-auth-side-info {
    287386    padding: 32px 24px;
    288387  }
    … …  
    291390  }
    292391}
     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  
    11/* ==========================================================================
    22   ACRB REGISTRATION COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/register.css
    34   ========================================================================== */
    45
    56/* Scoped Variable Fallbacks & Font/Text Colors */
    6 .acrb-reg-container {
     7.acrb-reg-container,
     8.acrb-reg-solo-wrapper {
    79  --acrb-reg-primary: #4f46e5;
    810  --acrb-reg-secondary: #64748b;
    … …  
    1315  --acrb-reg-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1416
    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);
    2519  box-sizing: border-box;
    2620}
    2721
    28 .acrb-reg-container,
    2922.acrb-reg-container *,
    3023.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;
    3329}
    3430
    … …  
    3632   SVG Icon Standards
    3733   -------------------------------------------------------------------------- */
    38 .acrb-reg-container .acrb-reg-icon {
     34.acrb-reg-icon {
    3935  display: inline-block;
    4036  width: 18px;
    … …  
    5046
    5147/* --------------------------------------------------------------------------
     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/* --------------------------------------------------------------------------
    5270   Side Info Panel (Solid Dark Surface - No Gradients)
    5371   -------------------------------------------------------------------------- */
    54 .acrb-reg-container .acrb-reg-info {
     72.acrb-reg-info {
    5573  flex: 1;
    56   background: var(--acrb-reg-text);
     74  background: var(--acrb-reg-text, #0f172a);
    5775  padding: 50px 40px;
    5876  color: #ffffff;
    … …  
    6280}
    6381
    64 .acrb-reg-container .acrb-reg-info h2 {
     82.acrb-reg-info h2 {
    6583  color: #ffffff !important;
    6684  font-size: 28px;
    … …  
    7189}
    7290
    73 .acrb-reg-container .acrb-reg-info p {
     91.acrb-reg-info p {
    7492  color: #94a3b8;
    7593  line-height: 1.55;
    … …  
    7896}
    7997
    80 .acrb-reg-container .acrb-info-list {
     98.acrb-info-list {
    8199  list-style: none;
    82100  padding: 0;
    … …  
    84102}
    85103
    86 .acrb-reg-container .acrb-info-list li {
     104.acrb-info-list li {
    87105  display: flex;
    88106  align-items: center;
    … …  
    94112}
    95113
    96 .acrb-reg-container .acrb-info-list .acrb-reg-icon {
    97   color: var(--acrb-reg-primary);
    98 }
    99 
    100 .acrb-reg-container .acrb-reg-copyright {
     114.acrb-info-list .acrb-reg-icon {
     115  color: var(--acrb-reg-primary, #4f46e5);
     116}
     117
     118.acrb-reg-copyright {
    101119  font-size: 11.5px;
    102120  color: rgba(255, 255, 255, 0.6);
    … …  
    108126   Registration Form Card & Grid Inputs
    109127   -------------------------------------------------------------------------- */
     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
    110138.acrb-reg-container .acrb-reg-card {
    111139  flex: 1.4;
    112140  padding: 50px 40px;
    113   background: #ffffff;
     141  border: none;
     142  max-width: none;
     143  box-shadow: none;
    114144  display: flex;
    115145  flex-direction: column;
    116146  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;
    117155}
    118156
    … …  
    120158  font-size: 24px;
    121159  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 {
    130163  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 {
    134169  display: grid;
    135170  grid-template-columns: 1fr 1fr;
    136171  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,
    139182.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;
    141192}
    142193
    143194.acrb-reg-container .acrb-reg-field label {
    144   display: block;
    145195  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,
    151200.acrb-reg-container .acrb-reg-field input {
    152201  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 {
    153216  height: 42px !important;
    154217  padding: 0 14px !important;
    155   border: 1px solid #cbd5e1 !important;
     218  border-color: #cbd5e1 !important;
    156219  border-radius: 8px !important;
    157220  font-size: 13.5px !important;
    158   color: var(--acrb-reg-text) !important;
    159   background: #f8fafc !important;
    160221  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02) !important;
    161   font-family: inherit !important;
    162222  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 {
    168226  border-color: #94a3b8 !important;
    169227  background: #ffffff !important;
    170228}
    171229
    172 .acrb-reg-container .acrb-reg-field input:focus {
     230.acrb-reg-field input:focus {
    173231  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;
    176285}
    177286
    … …  
    179288   Submit Button & Status Feedback
    180289   -------------------------------------------------------------------------- */
    181 .acrb-reg-container .acrb-reg-btn {
     290.acrb-reg-btn {
    182291  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);
    186294  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;
    195300  align-items: center;
    196301  justify-content: center;
    197302  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;
    198307  font-family: inherit;
    199308}
    200309
    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);
    204321  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;
    206329}
    207330
    … …  
    209332  background: #94a3b8 !important;
    210333  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;
    218339  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;
    232358}
    233359
    … …  
    256382}
    257383
     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
    258406/* --------------------------------------------------------------------------
    259407   Responsive Breakpoints
    … …  
    277425  }
    278426}
     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  
    11/* ==========================================================================
    22   ACRB SEARCH BAR (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/search-form.css
    34   ========================================================================== */
    45
    … …  
    1516  max-width: 1200px;
    1617  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);
    1920  box-sizing: border-box;
    2021}
    2122
    22 .acrb-search-wrapper,
    2323.acrb-search-wrapper *,
    2424.acrb-search-wrapper *::before,
    2525.acrb-search-wrapper *::after {
    26   box-sizing: border-box;
     26  box-sizing: inherit;
    2727}
    2828
    … …  
    4646.acrb-search-wrapper .acrb-search-form {
    4747  background: #ffffff;
    48   border: 1px solid #e2e8f0;
     48  border: 1px solid rgba(226, 232, 240, 0.8);
    4949  border-radius: 16px;
    5050  padding: 26px 30px;
    … …  
    5454.acrb-search-wrapper .acrb-search-main {
    5555  display: grid;
    56   grid-template-columns: 1fr 1fr 1fr 1fr auto;
     56  grid-template-columns: repeat(4, 1fr) auto;
    5757  gap: 18px;
    5858  align-items: flex-end;
    … …  
    6262  display: flex;
    6363  flex-direction: column;
     64  gap: 0.5rem;
    6465}
    6566
    … …  
    7071  font-size: 13px;
    7172  font-weight: 700;
    72   color: var(--acrb-search-text);
    73   margin-bottom: 6px;
     73  color: var(--acrb-search-secondary, #64748b);
     74  margin-bottom: 2px;
    7475}
    7576
    7677.acrb-search-wrapper .acrb-search-field label .acrb-search-icon {
    77   color: var(--acrb-search-primary);
     78  color: var(--acrb-search-primary, #4f46e5);
    7879}
    7980
    … …  
    8788  border-radius: 8px !important;
    8889  font-size: 13.5px !important;
    89   color: var(--acrb-search-text) !important;
     90  color: var(--acrb-search-text, #0f172a) !important;
    9091  background: #f8fafc !important;
    9192  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;
    9394  font-family: inherit !important;
    9495  line-height: 40px !important;
    … …  
    99100  appearance: none;
    100101  -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;
    105106  padding-right: 38px !important;
    106107  cursor: pointer;
    … …  
    116117.acrb-search-wrapper .acrb-search-input:focus {
    117118  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;
    120121}
    121122
    … …  
    123124.acrb-search-wrapper .acrb-search-submit {
    124125  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);
    127128  color: #ffffff !important;
    128129  border-radius: 8px;
    … …  
    142143
    143144.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);
    147147  transform: translateY(-1px);
     148}
     149
     150.acrb-search-wrapper .acrb-search-submit:active {
     151  transform: translateY(0);
    148152}
    149153
    … …  
    151155  width: 15px;
    152156  height: 15px;
     157  color: #ffffff;
    153158}
    154159
    … …  
    158163@media (max-width: 1024px) {
    159164  .acrb-search-wrapper .acrb-search-main {
    160     grid-template-columns: 1fr 1fr;
     165    grid-template-columns: repeat(2, 1fr);
    161166  }
    162167  .acrb-search-wrapper .acrb-search-submit {
  • awesome-car-rental/trunk/assets/css/frontend/single-car.css

    r3775773 r3777386  
    11/* ==========================================================================
    22   ACRB SINGLE CAR DETAILS (SCOPED COMPONENT - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/single-car.css
    34   ========================================================================== */
    45
    … …  
    1516  --acrb-single-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1617
    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);
    1920  box-sizing: border-box;
    2021}
    2122
    22 .acrb-main-container,
    2323.acrb-main-container *,
    2424.acrb-main-container *::before,
    2525.acrb-main-container *::after,
    26 .acrb-redirect-notice,
    2726.acrb-redirect-notice *,
    2827.acrb-redirect-notice *::before,
    2928.acrb-redirect-notice *::after,
    30 .acrb-alert-error,
    3129.acrb-alert-error *,
    3230.acrb-alert-error *::before,
    3331.acrb-alert-error *::after {
    34   box-sizing: border-box;
     32  box-sizing: inherit;
    3533}
    3634
    … …  
    4240  text-align: center;
    4341  font-size: 15px;
    44   color: var(--acrb-single-secondary);
     42  color: var(--acrb-single-secondary, #64748b);
    4543}
    4644
    … …  
    6159   -------------------------------------------------------------------------- */
    6260.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;
    6564}
    6665
    … …  
    8079.acrb-flex-grid {
    8180  display: flex;
    82   flex-wrap: wrap;
     81  align-items: flex-start;
    8382  gap: 36px;
    84   align-items: flex-start;
    8583}
    8684
    8785.acrb-content-left {
    8886  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;
    9095}
    9196
    … …  
    9499   -------------------------------------------------------------------------- */
    95100.acrb-gallery-stage {
    96   border-radius: 16px;
     101  background: #ffffff;
     102  border: 1px solid #e2e8f0;
     103  border-radius: 20px;
    97104  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;
    101109}
    102110
    103111.acrb-gallery-stage img {
    104112  width: 100%;
    105   height: 440px;
     113  height: 100%;
    106114  object-fit: cover;
    107115  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 */
    110137.acrb-header-box {
    111   margin-top: 24px;
     138  margin-bottom: 24px;
    112139}
    113140
    114141.acrb-vin-badge {
    115   background: #eff6ff;
    116   display: inline-block;
    117   padding: 5px 14px;
    118   border-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;
    123150  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;
    126154}
    127155
    128156.acrb-car-title {
    129157  margin: 0;
    130   font-size: 28px;
    131   font-weight: 900;
    132   color: var(--acrb-single-text);
     158  font-size: 2.2rem;
     159  font-weight: 800;
     160  line-height: 1.25;
    133161  letter-spacing: -0.02em;
     162  color: var(--acrb-single-text, #0f172a);
    134163}
    135164
    … …  
    140169  display: flex;
    141170  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;
    145173  overflow-x: auto;
     174  scrollbar-width: none;
     175}
     176
     177.acrb-tabs-nav::-webkit-scrollbar {
     178  display: none;
    146179}
    147180
    148181button.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;
    152186  font-weight: 700;
    153   font-size: 13.5px;
    154   color: var(--acrb-single-secondary);
     187  color: var(--acrb-single-secondary, #64748b);
    155188  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;
    158192  white-space: nowrap;
    159   box-shadow: 0 1px 2px rgba(15, 23, 42, 0.02);
    160193  font-family: inherit;
    161194}
    162195
    163196button.acrb-tab-btn:hover {
    164   background: #f8fafc;
    165   color: var(--acrb-single-text);
    166   border-color: #94a3b8;
     197  color: var(--acrb-single-primary, #4f46e5);
    167198}
    168199
    169200button.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);
    174203}
    175204
    176205.acrb-tab-pane {
    177206  display: none;
    178   padding: 28px 0;
     207  animation: acrbFadeIn 0.2s ease-in-out;
    179208}
    180209
    181210.acrb-tab-pane.active {
    182211  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); }
    195217}
    196218
    197219.acrb-description {
    198   color: var(--acrb-single-secondary);
    199   font-size: 15px;
     220  font-size: 1rem;
    200221  line-height: 1.7;
    201 }
    202 
     222  color: #334155;
     223}
     224
     225.acrb-description p {
     226  margin-top: 0;
     227}
     228
     229/* Specs Grid */
    203230.acrb-specs-heading {
     231  font-size: 1.15rem;
     232  font-weight: 800;
    204233  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);
    208235  text-transform: uppercase;
    209236  letter-spacing: 0.04em;
    210237}
    211238
    212 /* Specifications Grid */
    213239.acrb-spec-wrap {
    214240  display: grid;
    215   grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    216   gap: 16px;
     241  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
     242  gap: 14px;
    217243  margin-bottom: 32px;
    218244}
    219245
    220246.acrb-spec-node {
    221   padding: 18px;
    222247  background: #ffffff;
    223248  border: 1px solid #e2e8f0;
    224249  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);
    226255}
    227256
    228257.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;
    234264  align-items: center;
    235265  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;
    243273}
    244274
    245275.acrb-spec-node-lbl {
    246   font-size: 11px;
    247   color: var(--acrb-single-secondary);
     276  font-size: 0.74rem;
    248277  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;
    252281}
    253282
    254283.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);
    259287}
    260288
    … …  
    262290.acrb-gallery-grid {
    263291  display: grid;
    264   grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    265   gap: 16px;
     292  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
     293  gap: 12px;
    266294}
    267295
    268296.acrb-gallery-thumb-wrap {
     297  aspect-ratio: 4 / 3;
    269298  border-radius: 12px;
    270299  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,
    276312.acrb-gallery-item {
    277313  width: 100%;
    278314  height: 100%;
    279315  object-fit: cover;
    280   cursor: pointer;
    281316  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
    290319.acrb-video-container {
    291320  position: relative;
    … …  
    293322  height: 0;
    294323  overflow: hidden;
    295   border-radius: 14px;
    296   background: #0f172a;
    297   border: 1px solid #e2e8f0;
     324  border-radius: 16px;
    298325}
    299326
    … …  
    313340  background: #f8fafc;
    314341  border-radius: 14px;
    315   color: var(--acrb-single-secondary);
     342  color: var(--acrb-single-secondary, #64748b);
    316343  border: 1px dashed #cbd5e1;
    317344}
    318345
    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 
    334346.acrb-empty-msg {
    335   color: var(--acrb-single-secondary);
     347  color: var(--acrb-single-secondary, #64748b);
    336348  font-style: italic;
    337349}
    … …  
    340352   Booking Sidebar Card & Forms
    341353   -------------------------------------------------------------------------- */
    342 .acrb-sidebar-right {
    343   width: 440px;
    344   min-width: 320px;
    345 }
    346 
    347354.acrb-booking-card {
    348   padding: 32px;
     355  background: #ffffff;
    349356  border: 1px solid #e2e8f0;
    350   border-radius: 20px;
    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);
    353360}
    354361
    355362.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;
    357368  border-bottom: 1px solid #f1f5f9;
    358   padding-bottom: 18px;
    359   display: flex;
    360   align-items: baseline;
    361   gap: 6px;
    362369}
    363370
    364371.acrb-price-amount {
    365   font-size: 32px;
     372  font-size: 2.1rem;
    366373  font-weight: 900;
    367   color: var(--acrb-single-text);
     374  color: var(--acrb-single-text, #0f172a);
    368375  letter-spacing: -0.02em;
    369376}
    370377
    371378.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 */
    377385.acrb-form-row {
    378386  display: flex;
    379   gap: 10px;
    380   margin-bottom: 16px;
     387  gap: 12px;
     388  margin-bottom: 14px;
    381389}
    382390
    … …  
    389397}
    390398
     399.acrb-locations-row {
     400  display: flex;
     401  gap: 12px;
     402  margin-bottom: 18px;
     403}
     404
    391405.acrb-form-col-half {
    392406  flex: 1;
    393407}
    394408
    395 .acrb-locations-row {
    396   display: flex;
    397   gap: 12px;
    398   margin-bottom: 16px;
    399 }
    400 
    401409.acrb-label {
    402410  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);
    403416  margin-bottom: 6px;
    404   font-size: 13px;
    405   font-weight: 800;
    406   color: var(--acrb-single-text);
    407417}
    408418
    409419.acrb-input {
    410420  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;
    414425  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;
    420430  font-family: inherit !important;
    421   line-height: 42px !important;
    422431  outline: none !important;
    423432}
    … …  
    430439.acrb-input:focus {
    431440  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;
    434443}
    435444
    … …  
    439448  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");
    440449  background-repeat: no-repeat;
    441   background-position: right 14px center;
     450  background-position: right 12px center;
    442451  background-size: 18px;
    443   padding-right: 40px !important;
     452  padding-right: 38px !important;
    444453  cursor: pointer;
    445454}
    … …  
    449458   -------------------------------------------------------------------------- */
    450459.acrb-luxury-options-group {
    451   margin: 22px 0;
     460  margin-bottom: 18px;
    452461}
    453462
    454463.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;
    458466  text-transform: uppercase;
    459   letter-spacing: 0.06em;
     467  letter-spacing: 0.05em;
     468  color: var(--acrb-single-secondary, #64748b);
    460469  margin-bottom: 10px;
    461470}
    … …  
    465474  align-items: center;
    466475  justify-content: space-between;
    467   padding: 14px 16px;
     476  background: #f8fafc;
    468477  border: 1.5px solid #e2e8f0;
    469478  border-radius: 12px;
    470   background: #ffffff;
     479  padding: 10px 14px;
     480  margin-bottom: 8px;
    471481  cursor: pointer;
    472   transition: all 0.15s ease;
    473   margin-bottom: 8px;
     482  transition: all 0.2s ease;
    474483}
    475484
    476485.acrb-luxury-card:hover {
    477   border-color: #94a3b8;
    478   background: #f8fafc;
     486  border-color: #cbd5e1;
     487  background: #f1f5f9;
    479488}
    480489
    481490.acrb-luxury-card.selected {
    482   border-color: var(--acrb-single-primary);
    483491  background: #eef2ff;
     492  border-color: var(--acrb-single-primary, #4f46e5);
    484493}
    485494
    … …  
    487496  display: flex;
    488497  align-items: center;
    489   gap: 12px;
    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;
    493502}
    494503
    495504.acrb-luxury-card input[type="radio"] {
    496   accent-color: var(--acrb-single-primary);
     505  accent-color: var(--acrb-single-primary, #4f46e5);
    497506  width: 17px;
    498507  height: 17px;
    … …  
    501510
    502511.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);
    506515}
    507516
    … …  
    511520.acrb-breakdown-card {
    512521  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;
    520526  box-shadow: 0 4px 16px -4px rgba(15, 23, 42, 0.04);
    521527}
    522528
    523529.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;
    527535  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;
    529540  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 {
    538544  width: 16px;
    539545  height: 16px;
     546  color: var(--acrb-single-primary, #4f46e5);
    540547}
    541548
    … …  
    543550  display: flex;
    544551  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;
    547555  color: #334155;
    548556  padding-bottom: 10px;
    … …  
    561569.acrb-bd-label {
    562570  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;
    566574}
    567575
    … …  
    571579  border-radius: 8px;
    572580  background: #eef2ff;
    573   color: var(--acrb-single-primary);
     581  color: var(--acrb-single-primary, #4f46e5);
    574582  display: flex;
    575583  align-items: center;
    576584  justify-content: center;
     585  font-size: 1rem;
    577586  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;
    579594}
    580595
    581596.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;
    587600}
    588601
    589602.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;
    590622  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 */
     640button.acrb-submit-btn,
     641.acrb-submit-btn {
    612642  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);
    616645  color: #ffffff;
    617   border-radius: 10px;
     646  border: none;
     647  border-radius: 12px;
     648  font-size: 0.95rem;
    618649  font-weight: 800;
    619   font-size: 14.5px;
     650  display: flex;
     651  align-items: center;
     652  justify-content: center;
     653  gap: 8px;
    620654  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);
    627657  font-family: inherit;
    628658}
    629659
    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;
     660button.acrb-submit-btn:hover,
     661.acrb-submit-btn:hover {
     662  background: var(--acrb-single-btn-hover, #4338ca);
    634663  transform: translateY(-1px);
    635 }
    636 
    637 button.acrb-submit-icon {
     664  box-shadow: 0 6px 18px rgba(79, 70, 229, 0.35);
     665}
     666
     667button.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 {
    638676  width: 18px;
    639677  height: 18px;
     678  stroke-width: 2.2;
    640679}
    641680
    … …  
    643682   Responsive Breakpoints
    644683   -------------------------------------------------------------------------- */
    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;
    650687  }
    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  
    11/* ==========================================================================
    22   ACRB THANK YOU & CONFIRMATION COMPONENT (SCOPED - NO :ROOT, NO GRADIENTS)
     3   Location: assets/css/frontend/thanks.css
    34   ========================================================================== */
    45
    … …  
    1415  --acrb-thanks-font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    1516
    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);
    1819  box-sizing: border-box;
    1920}
    2021
    21 .acrb-thanks-wrapper,
    2222.acrb-thanks-wrapper *,
    2323.acrb-thanks-wrapper *::before,
    2424.acrb-thanks-wrapper *::after,
    25 .acrb-error-container,
    2625.acrb-error-container *,
    2726.acrb-error-container *::before,
    2827.acrb-error-container *::after {
    29   box-sizing: border-box;
     28  box-sizing: inherit;
    3029}
    3130
    … …  
    4544
    4645.acrb-error-container h3 {
    47   color: var(--acrb-thanks-text);
     46  color: var(--acrb-thanks-text, #0f172a);
    4847  font-size: 24px;
    4948  font-weight: 900;
    … …  
    5352
    5453.acrb-error-container p {
    55   color: var(--acrb-thanks-secondary);
     54  color: var(--acrb-thanks-secondary, #64748b);
    5655  font-size: 14.5px;
    5756  margin: 0 0 32px;
    … …  
    5958}
    6059
    61 .acrb-btn-home {
     60.acrb-error-container .acrb-btn-home {
    6261  display: inline-flex;
    6362  align-items: center;
    6463  gap: 10px;
    6564  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);
    6867  color: #ffffff !important;
    6968  padding: 14px 28px;
    … …  
    7574}
    7675
    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);
    8079  opacity: 0.94;
    8180  transform: translateY(-1px);
    … …  
    8382
    8483/* --------------------------------------------------------------------------
    85    Confirmation Main Card
     84   Confirmation Main Container & Stepper
    8685   -------------------------------------------------------------------------- */
    8786.acrb-thanks-wrapper {
    8887  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   -------------------------------------------------------------------------- */
    92161.acrb-thanks-card {
    93   padding: 56px;
     162  padding: 48px 56px;
    94163  border: 1px solid #e2e8f0;
    95164  border-radius: 24px;
    … …  
    98167}
    99168
     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
    100188.acrb-thanks-icon {
    101189  display: inline-block;
    102   width: 18px;
    103   height: 18px;
     190  width: 32px;
     191  height: 32px;
    104192  stroke-width: 2.2;
    105193  stroke: currentColor;
    … …  
    111199}
    112200
    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 
    132201.acrb-success-icon .acrb-thanks-icon {
    133202  width: 40px;
    … …  
    138207  font-size: 32px;
    139208  font-weight: 900;
    140   color: var(--acrb-thanks-text);
     209  color: var(--acrb-thanks-text, #0f172a);
    141210  margin: 0 0 10px 0;
    142211  letter-spacing: -0.03em;
    … …  
    144213
    145214.acrb-thanks-sub {
    146   color: var(--acrb-thanks-secondary);
     215  color: var(--acrb-thanks-secondary, #64748b);
    147216  font-size: 15px;
    148   margin: 0;
     217  margin: 0 0 14px 0;
    149218  line-height: 1.6;
    150219}
    151220
    152221.acrb-thanks-sub strong {
    153   color: var(--acrb-thanks-text);
     222  color: var(--acrb-thanks-text, #0f172a);
    154223}
    155224
    … …  
    158227  align-items: center;
    159228  gap: 8px;
    160   margin-top: 20px;
     229  margin-top: 4px;
    161230  padding: 8px 16px;
    162231  background: #fffbeb;
    … …  
    175244.acrb-summary-box {
    176245  background: #f8fafc;
     246  border: 1px solid #e2e8f0;
     247  border-radius: 18px;
    177248  padding: 32px;
    178   border-radius: 18px;
    179249  margin-bottom: 28px;
    180   border: 1px solid #e2e8f0;
    181250}
    182251
    … …  
    185254  font-size: 12.5px;
    186255  font-weight: 900;
    187   color: var(--acrb-thanks-secondary);
    188256  text-transform: uppercase;
    189257  letter-spacing: 0.06em;
     258  color: var(--acrb-thanks-secondary, #64748b);
    190259  border-bottom: 1px solid #e2e8f0;
    191260  padding-bottom: 12px;
    … …  
    214283  font-size: 11px;
    215284  font-weight: 800;
    216   color: var(--acrb-thanks-secondary);
    217285  text-transform: uppercase;
    218286  letter-spacing: 0.04em;
     287  color: var(--acrb-thanks-secondary, #64748b);
    219288}
    220289
    … …  
    222291  font-size: 14.5px;
    223292  font-weight: 900;
    224   color: var(--acrb-thanks-text);
     293  color: var(--acrb-thanks-text, #0f172a);
    225294}
    226295
    227296.acrb-val-primary {
    228   color: var(--acrb-thanks-primary);
     297  color: var(--acrb-thanks-primary, #4f46e5);
     298  font-size: 1.1rem;
    229299}
    230300
    231301.acrb-val-contact {
    232302  font-size: 13px;
     303  line-height: 1.4;
    233304}
    234305
    235306.acrb-val-contact-sub {
    236   color: var(--acrb-thanks-secondary);
     307  font-size: 11.5px;
     308  color: var(--acrb-thanks-secondary, #64748b);
    237309  font-weight: 600;
     310  display: inline-block;
     311  margin-top: 2px;
    238312}
    239313
    … …  
    242316}
    243317
     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
    244326/* --------------------------------------------------------------------------
    245327   Financial Breakdown Table
    246328   -------------------------------------------------------------------------- */
    247329.acrb-table-container {
     330  width: 100%;
     331  overflow-x: auto;
    248332  background: #ffffff;
    249333  border: 1px solid #e2e8f0;
    250334  border-radius: 14px;
    251   overflow: hidden;
     335  margin-bottom: 20px;
    252336  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.02);
    253337}
    … …  
    256340  width: 100%;
    257341  border-collapse: collapse;
    258 }
    259 
    260 .acrb-breakdown-table thead th {
     342  text-align: left;
     343}
     344
     345.acrb-breakdown-table th {
    261346  background: #f1f5f9;
    262   color: var(--acrb-thanks-secondary);
     347  color: var(--acrb-thanks-secondary, #64748b);
    263348  font-size: 11px;
    264349  font-weight: 900;
    … …  
    266351  letter-spacing: 0.05em;
    267352  padding: 12px 18px;
    268   text-align: left;
    269 }
    270 
    271 .acrb-breakdown-table thead th:last-child {
     353  border-bottom: 1px solid #e2e8f0;
     354}
     355
     356.acrb-breakdown-table th:last-child {
    272357  text-align: right;
    273358}
    274359
    275 .acrb-breakdown-table tr td {
     360.acrb-breakdown-table td {
    276361  padding: 16px 18px;
    277362  border-bottom: 1px solid #f1f5f9;
     363  vertical-align: middle;
     364  color: #334155;
    278365  font-size: 13.5px;
    279   color: #334155;
    280366  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 {
    285370  border-bottom: none;
    286371}
    287372
    288 .acrb-breakdown-table tr td:last-child {
     373.acrb-breakdown-table td:last-child {
    289374  text-align: right;
    290375  font-weight: 900;
    291   color: var(--acrb-thanks-text);
     376  color: var(--acrb-thanks-text, #0f172a);
    292377}
    293378
    … …  
    295380  display: flex;
    296381  align-items: center;
    297   gap: 10px;
     382  gap: 12px;
    298383}
    299384
    300385.acrb-table-item-badge {
    301   width: 28px;
    302   height: 28px;
    303   border-radius: 8px;
     386  width: 32px;
     387  height: 32px;
     388  border-radius: 10px;
    304389  background: #eef2ff;
    305   color: var(--acrb-thanks-primary);
     390  color: var(--acrb-thanks-primary, #4f46e5);
    306391  display: flex;
    307392  align-items: center;
    308393  justify-content: center;
    309   font-size: 13px;
     394  font-size: 14px;
    310395  flex-shrink: 0;
    311396}
    … …  
    313398.acrb-table-item-badge.promo-badge {
    314399  background: #ecfdf5;
    315   color: #059669;
     400  color: var(--acrb-thanks-accent, #059669);
    316401}
    317402
    318403.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,
    323410.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);
    333412}
    334413
    335414.acrb-val-included {
    336   color: var(--acrb-thanks-primary);
     415  color: var(--acrb-thanks-primary, #4f46e5) !important;
     416  font-weight: 700;
    337417}
    338418
    339419.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 */
    345425.acrb-receipt-total-bar {
     426  display: flex;
     427  justify-content: space-between;
     428  align-items: center;
    346429  background: #ffffff;
    347430  border: 1.5px solid #cbd5e1;
     431  border-radius: 14px;
    348432  padding: 20px 24px;
    349   border-radius: 14px;
    350   display: flex;
    351   justify-content: space-between;
    352   align-items: center;
    353   margin-top: 20px;
    354433  box-shadow: 0 4px 12px rgba(15, 23, 42, 0.02);
    355434}
    … …  
    358437  display: flex;
    359438  align-items: center;
    360   gap: 10px;
     439  gap: 12px;
    361440}
    362441
    … …  
    364443  font-size: 16px;
    365444  font-weight: 900;
    366   color: var(--acrb-thanks-text);
     445  color: var(--acrb-thanks-text, #0f172a);
    367446}
    368447
    … …  
    370449  font-size: 12px;
    371450  font-weight: 800;
    372   color: var(--acrb-thanks-secondary);
     451  color: var(--acrb-thanks-secondary, #64748b);
    373452  background: #f1f5f9;
    374453  padding: 4px 10px;
    … …  
    380459  font-size: 26px;
    381460  font-weight: 900;
    382   color: var(--acrb-thanks-primary);
     461  color: var(--acrb-thanks-primary, #4f46e5);
    383462  letter-spacing: -0.02em;
    384463}
    … …  
    389468.acrb-thanks-footer {
    390469  text-align: center;
     470  margin-top: 40px;
    391471}
    392472
    393473.acrb-footer-desc {
    394474  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;
    397478  line-height: 1.6;
    398479}
    … …  
    403484  gap: 14px;
    404485  flex-wrap: wrap;
    405 }
    406 
    407 button.acrb-btn-action {
    408   cursor: pointer;
     486  margin-bottom: 16px;
     487}
     488
     489button.acrb-btn-action,
     490.acrb-btn-action {
     491  display: inline-flex;
     492  align-items: center;
     493  gap: 8px;
    409494  background: #ffffff;
    410495  border: 1.5px solid #cbd5e1;
    411   color: var(--acrb-thanks-text);
     496  color: var(--acrb-thanks-text, #0f172a);
    412497  padding: 12px 24px;
    413498  border-radius: 12px;
    414   font-weight: 800;
    415499  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;
    419503  transition: all 0.15s ease;
    420   text-decoration: none !important;
    421504  font-family: inherit;
    422505}
    423506
    424 button.acrb-btn-action:hover {
     507button.acrb-btn-action:hover,
     508.acrb-btn-action:hover {
    425509  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);
    428512  transform: translateY(-1px);
    429513}
    430514
    431515.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);
    434518  color: #ffffff !important;
    435519  box-shadow: 0 8px 20px -4px rgba(79, 70, 229, 0.35);
    … …  
    437521
    438522.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);
    441525  opacity: 0.94;
    442526  transform: translateY(-1px);
     527  color: #ffffff !important;
    443528}
    444529
    445530.acrb-support-link {
    446   margin-top: 24px;
    447531  font-size: 13px;
    448   color: var(--acrb-thanks-secondary);
     532  color: var(--acrb-thanks-secondary, #64748b);
    449533  font-weight: 600;
     534  margin: 0;
    450535}
    451536
    452537.acrb-support-link a {
    453   color: var(--acrb-thanks-primary);
     538  color: var(--acrb-thanks-primary, #4f46e5);
     539  font-weight: 800;
    454540  text-decoration: none;
    455   font-weight: 800;
    456541}
    457542
    … …  
    463548   Responsive Breakpoints
    464549   -------------------------------------------------------------------------- */
    465 @media (max-width: 640px) {
     550@media (max-width: 768px) {
    466551  .acrb-thanks-wrapper {
    467     margin: 20px;
     552    margin: 20px auto;
     553  }
     554  .acrb-receipt-grid {
     555    grid-template-columns: 1fr;
    468556  }
    469557  .acrb-thanks-card {
    470558    padding: 32px 20px;
    471559  }
    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
    479572   -------------------------------------------------------------------------- */
    480573@media print {
    … …  
    492585    width: 100%;
    493586    margin: 0;
     587    padding: 0;
    494588  }
    495589  .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,
    500595  .acrb-action-buttons,
    501   .acrb-support-link {
     596  .acrb-support-link,
     597  header,
     598  footer {
    502599    display: none !important;
    503600  }
  • awesome-car-rental/trunk/awesome-car-rental.php

    r3775773 r3777386  
    33 * Plugin Name: Awesome Car Rental & Booking
    44 * Description: Core functionality for the Car Rental System (Custom Database Architecture, Admin UI, and Logic).
    5  * Version: 1.2
     5 * Version: 1.2.1
    66 * Author: Abdullah Nahian
    77 * Author URI: https://devnahian.com
  • awesome-car-rental/trunk/frontend/account/acrb-frontned-account.php

    r3775773 r3777386  
    3939    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    4040
    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        }',
    4452        esc_attr( $primary_color ),
    4553        esc_attr( $secondary_color ),
    … …  
    5058        esc_attr( $btn_hover_color )
    5159    );
     60    wp_add_inline_style( 'acrb-account-style', $custom_css );
    5261
    5362    // 3. Auth Check & Lock Screen
    … …  
    5665        ob_start();
    5766        ?>
    58         <div class="acrb-auth-locked" style="<?php echo esc_attr( $scoped_styles ); ?>">
     67        <div class="acrb-auth-locked">
    5968            <div class="acrb-auth-locked-icon">
    6069                <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
    … …  
    8089
    8190    // 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' );
    8493    $update_msg      = '';
    8594
    … …  
    8998    };
    9099
    91     // 5. Handle Account Profile & Password Updates
     100    // 5. Handle Account Profile & Security Updates
    92101    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 {
    108125                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>';
    112127            }
    113         } else {
    114             $update_msg = '<div class="acrb-alert success">' . esc_html__( 'Profile details saved and updated successfully.', 'awesome-car-rental' ) . '</div>';
    115128        }
    116129    }
    … …  
    137150            foreach ( $db_bookings as $dbb ) {
    138151                $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
    139181                $normalized_bookings[] = array(
    140182                    'id'             => $b_id,
    141183                    'code'           => ! empty( $dbb['booking_code'] ) ? $dbb['booking_code'] : 'ACR-' . $b_id,
    142184                    '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 : '—',
    145187                    'pickup_loc'     => ! empty( $dbb['pickup_location'] ) ? $dbb['pickup_location'] : __( 'Main Terminal', 'awesome-car-rental' ),
    146188                    '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,
    147192                    'insurance_plan' => ! empty( $dbb['insurance_plan'] ) ? $dbb['insurance_plan'] : '',
     193                    'insurance_fee'  => $insurance_fee,
    148194                    'border_permit'  => ! empty( $dbb['border_permit'] ) ? $dbb['border_permit'] : '',
     195                    'border_fee'     => $border_fee,
    149196                    'promo_code'     => ! empty( $dbb['promo_code'] ) ? $dbb['promo_code'] : '',
     197                    'discount_amt'   => $discount_amt,
     198                    'tax_amt'        => $tax_amt,
    150199                    'payment_method' => ! empty( $dbb['payment_method'] ) ? $dbb['payment_method'] : 'pay_later',
    151                     'total_amt'      => floatval( $dbb['total_amount'] ?? 0 ),
     200                    'total_amt'      => $total_amt,
    152201                    'status'         => sanitize_key( (string) ( $dbb['booking_status'] ?? 'pending' ) ),
    153202                );
    … …  
    161210    ob_start();
    162211    ?>
    163     <div class="acrb-acc-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>">
     212    <div class="acrb-acc-wrapper">
    164213        <!-- Sidebar Navigation -->
    165214        <aside class="acrb-acc-nav">
    … …  
    292341                    $b_price_disp = $format_price( $booking['total_amt'] );
    293342                    $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'] ) ) );
    298343                ?>
    299344                <div class="acrb-booking-card">
    … …  
    339384                        </div>
    340385                        <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'] ) ) ); ?>">
    350406                            <svg class="acrb-icon" viewBox="0 0 24 24">
    351407                                <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"></path>
    … …  
    376432                <form method="post" class="acrb-settings-form">
    377433                    <?php wp_nonce_field( 'acrb_save_details', 'acrb_acc_nonce' ); ?>
     434                    <input type="hidden" name="acrb_form_source" value="profile">
     435                   
    378436                    <div class="acrb-form-row">
    379437                        <div class="acrb-form-group">
    … …  
    395453                            <input type="text" id="acrb_email" value="<?php echo esc_attr( $user->user_email ); ?>" disabled class="acrb-input acrb-readonly">
    396454                        </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>
    401455                    </div>
    402456                    <div>
    … …  
    416470            <div id="acrb-security-form" class="acrb-tab-panel">
    417471                <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">
    419473                    <?php wp_nonce_field( 'acrb_save_details', 'acrb_acc_nonce' ); ?>
     474                    <input type="hidden" name="acrb_form_source" value="security">
     475
    420476                    <div class="acrb-form-row">
    421477                        <div class="acrb-form-group">
    422478                            <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
    425490                        <div class="acrb-form-group">
    426491                            <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>
    428496                        </div>
    429497                    </div>
    430498                    <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">
    432500                            <svg class="acrb-icon acrb-submit-icon" viewBox="0 0 24 24">
    433501                                <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
    … …  
    442510    </div>
    443511
    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">
    446514        <div class="acrb-modal-content">
    447515            <span class="acrb-modal-close" aria-label="<?php esc_attr_e( 'Close', 'awesome-car-rental' ); ?>">&times;</span>
     516           
    448517            <div class="acrb-receipt-header">
    449518                <div class="acrb-receipt-icon-wrap">
    … …  
    452521                    </svg>
    453522                </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">
    458531                <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>
    461534                </div>
    462535                <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
    491650            <button type="button" onclick="window.print()" class="acrb-btn-print">
    492651                <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
    … …  
    502661    <script>
    503662    document.addEventListener('DOMContentLoaded', function() {
     663        // Tab Navigation
    504664        const triggers = document.querySelectorAll('.acrb-tab-trigger');
    505665        triggers.forEach(function(t) {
    … …  
    521681        });
    522682
    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        }
    526811
    527812        if (modal && detailBtns.length > 0) {
    528813            detailBtns.forEach(function(btn) {
    529814                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;
    535824                   
    536825                    const statusElem = document.getElementById('acrb-m-status');
    537826                    if (statusElem) {
    538                         statusElem.textContent = this.getAttribute('data-status');
     827                        statusElem.textContent = statusText;
    539828                    }
    540829
    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' ) ); ?>';
    546859                        insRow.style.display = 'flex';
    547860                    } else {
    … …  
    549862                    }
    550863
    551                     // Border
    552864                    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' ) ); ?>';
    556870                        borderRow.style.display = 'flex';
    557871                    } else {
    … …  
    559873                    }
    560874
    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' ) ); ?>';
    566898                        promoRow.style.display = 'flex';
    567899                    } else {
    … …  
    571903                    modal.style.display = 'block';
    572904                    modal.setAttribute('aria-hidden', 'false');
     905                    modal.scrollTop = 0;
     906                    document.body.style.overflow = 'hidden';
    573907                });
    574908            });
    575909
    576910            if (closeBtn) {
    577                 closeBtn.addEventListener('click', function() {
    578                     modal.style.display = 'none';
    579                     modal.setAttribute('aria-hidden', 'true');
    580                 });
     911                closeBtn.addEventListener('click', closeModal);
    581912            }
    582913
    583914            window.addEventListener('click', function(e) {
    584915                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();
    587923                }
    588924            });
  • awesome-car-rental/trunk/frontend/auth/acrb-frontend-auth.php

    r3775773 r3777386  
    22/**
    33 * [acrb_header_auth]
    4  * Ultra-Modern Elite SaaS Header Auth Widget
     4 * Ultra-Modern Elite SaaS Header Auth Widget with Dropdown & Redirection Support
    55 * Location: templates/shortcodes/header-auth.php
    66 *
    … …  
    1313if ( ! defined( 'ABSPATH' ) ) {
    1414    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_VERSION
    25     );
    2615}
    2716
    … …  
    5039    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    5140
    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        }',
    5552        esc_attr( $primary_color ),
    5653        esc_attr( $secondary_color ),
    … …  
    6158        esc_attr( $selected_font )
    6259    );
     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 );
    6366
    6467    ob_start();
    6568    ?>
    66     <div class="acrb-header-auth" style="<?php echo esc_attr( $scoped_styles ); ?>">
     69    <div class="acrb-header-auth">
    6770        <?php if ( is_user_logged_in() ) :
    6871            $user        = wp_get_current_user();
    … …  
    8588
    8689        <?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/' ) );
    8992        ?>
    9093            <div class="acrb-auth-group">
  • awesome-car-rental/trunk/frontend/cars/acrb-frontend-cars.php

    r3775773 r3777386  
    22/**
    33 * [acrb_all_cars]
    4  * Ultra-Modern Elite SaaS Fleet Archive with Live Filtering & Professional List/Grid Toggles
     4 * Ultra-Modern Elite SaaS Fleet Archive with Live Filtering & Numbered Pagination
    55 * Location: templates/shortcodes/all-cars.php
    66 *
    … …  
    1919function acrb_render_all_cars_archive_shortcode(): string {
    2020    global $wpdb;
    21     $table_cars       = $wpdb->prefix . 'dev_nahian_cars';
     21    $table_cars        = $wpdb->prefix . 'dev_nahian_cars';
    2222    $table_categories = $wpdb->prefix . 'dev_nahian_categories';
    2323
    … …  
    4343    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    4444
    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        }',
    4856        esc_attr( $primary_color ),
    4957        esc_attr( $secondary_color ),
    … …  
    5462        esc_attr( $selected_font )
    5563    );
     64    wp_add_inline_style( 'acrb-all-cars-style', $custom_css );
    5665
    5766    // 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' );
    6171
    6272    $format_price = static function( float $val ) use ( $currency_symbol, $currency_pos ): string {
    … …  
    7080
    7181    // 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
    7690    if ( ! empty( $cars ) ) {
    7791        foreach ( $cars as $car_item ) {
    … …  
    8094                $cat_counts[ $c_cat ] = ( $cat_counts[ $c_cat ] ?? 0 ) + 1;
    8195            }
     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            }
    82111        }
    83112    }
     113
     114    $max_car_price = ceil( $max_car_price > 0 ? $max_car_price : 500 );
    84115
    85116    if ( empty( $cars ) ) {
    86117        ob_start();
    87118        ?>
    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>
    90121        </div>
    91122        <?php
    … …  
    95126    ob_start();
    96127    ?>
    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
    98142        <div class="acrb-layout-container">
    99143            <!-- 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 -->
    101158                <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>
    103160                    <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">
    105163                            <circle cx="11" cy="11" r="8"></circle>
    106164                            <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
    107165                        </svg>
    108                         <input type="text" id="acrb-filter-search" placeholder="<?php esc_attr_e( 'Search model or brand...', 'awesome-car-rental' ); ?>">
    109166                    </div>
    110167                </div>
    111168
     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 -->
    112183                <?php if ( ! empty( $categories ) ) : ?>
    113184                <div class="acrb-filter-section">
    114                     <h4><?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>
    115186                    <ul class="acrb-filter-list">
    116187                        <?php foreach ( $categories as $cat ) :
    117188                            $c_name  = esc_html( $cat['name'] );
    118189                            $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 );
    120191                        ?>
    121192                            <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>
    128206                        <?php endforeach; ?>
    129207                    </ul>
    … …  
    131209                <?php endif; ?>
    132210
     211                <!-- 4. Transmission Chips -->
    133212                <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>
    143231                </div>
    144232
     233                <!-- 5. Fuel Type Chips -->
    145234                <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>
    161267                </div>
    162268            </aside>
    … …  
    164270            <!-- Right Side Content Area -->
    165271            <div class="acrb-right-content">
    166                 <!-- Header Toolbar with View Mode Switches -->
     272                <!-- Header Toolbar with Count, Per Page, Sorter & View Mode Switches -->
    167273                <div class="acrb-content-header">
    168274                    <span class="acrb-result-count" id="acrb-result-count">
    … …  
    172278                        ?>
    173279                    </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>
    193325                    </div>
    194326                </div>
    … …  
    197329                <div class="acrb-car-grid" id="acrb-fleet-grid">
    198330                    <?php
     331                    $single_car_page_id = (int) get_option( 'acrb_single_car_page' );
     332
    199333                    foreach ( $cars as $car ) :
    200334                        $car_id       = absint( $car['id'] );
    … …  
    203337                        $car_year     = absint( $car['year'] ?? 2026 );
    204338                        $full_title   = trim( ( $car_brand ? $car_brand . ' ' : '' ) . $car_name . ( $car_year ? ' (' . $car_year . ')' : '' ) );
    205                        
    206339                        $price_val    = floatval( $car['price'] ?? 0.00 );
    207340
    … …  
    209342                        $cat_slug      = sanitize_title( $category_name );
    210343
    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 = '';
    218351                        if ( is_numeric( $raw_img ) && absint( $raw_img ) > 0 ) {
    219352                            $thumb_url = wp_get_attachment_image_url( absint( $raw_img ), 'medium_large' ) ?: '';
    … …  
    222355                        }
    223356
    224                         $single_car_page_id = get_option( 'acrb_single_car_page' );
    225357                        $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 ) )
    227359                            : add_query_arg( array( 'sub' => 'view', 'car_id' => $car_id ), admin_url( 'admin.php?page=awesome_car_rental&tab=cars' ) );
    228360
    229                         $searchable_text = strtolower( $full_title . ' ' . $trans . ' ' . $fuel . ' ' . $category_name );
     361                        $searchable_text = strtolower( $full_title . ' ' . $trans . ' ' . $fuel . ' ' . $category_name . ' ' . $car_brand );
    230362                    ?>
    231363                        <!-- Schema.org Structured Data -->
    … …  
    248380                            "@type": "Offer",
    249381                            "price": "<?php echo esc_js( number_format( $price_val, 2, '.', '' ) ); ?>",
    250                             "priceCurrency": "GBP",
     382                            "priceCurrency": "<?php echo esc_js( $currency_code ); ?>",
    251383                            "eligibleQuantity": {
    252384                              "@type": "QuantitativeValue",
    253385                              "unitCode": "DAY",
    254                               "unitText": "Per Day"
     386                              "unitText": "Per <?php echo esc_js( ucfirst( $rental_unit ) ); ?>"
    255387                            }
    256388                          }
    … …  
    259391
    260392                        <article class="acrb-car-card <?php echo esc_attr( $cat_slug ); ?>"
     393                                 data-id="<?php echo esc_attr( (string) $car_id ); ?>"
    261394                                 data-search="<?php echo esc_attr( $searchable_text ); ?>"
     395                                 data-title="<?php echo esc_attr( strtolower( $full_title ) ); ?>"
    262396                                 data-category="<?php echo esc_attr( $cat_slug ); ?>"
    263397                                 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 ); ?>">
    265400                           
    266401                            <!-- Media Header -->
    … …  
    268403                                <a href="<?php echo esc_url( $link ); ?>" title="<?php echo esc_attr( $full_title ); ?>">
    269404                                    <?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">
    271406                                    <?php else : ?>
    272407                                        <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">
    274409                                                <path d="M5 17h14v-5l-2-6H7l-2 6v5z"></path>
    275410                                                <circle cx="7.5" cy="17.5" r="2.5"></circle>
    … …  
    295430                                    <div class="acrb-spec-grid">
    296431                                        <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">
    298433                                                <circle cx="12" cy="12" r="9"></circle>
    299434                                                <path d="M12 7v5l3 3"></path>
    … …  
    303438
    304439                                        <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">
    306441                                                <path d="M16 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"></path>
    307442                                                <circle cx="12" cy="7" r="4"></circle>
    … …  
    311446
    312447                                        <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">
    314449                                                <path d="M3 22V5a2 2 0 012-2h8a2 2 0 012 2v17"></path>
    315450                                                <path d="M15 9h2a2 2 0 012 2v2a2 2 0 002 2 2 2 0 002-2V9.5"></path>
    … …  
    320455
    321456                                        <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">
    323458                                                <rect x="2" y="7" width="20" height="14" rx="2" ry="2"></rect>
    324459                                                <path d="M16 21V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v16"></path>
    … …  
    338473                                    <a href="<?php echo esc_url( $link ); ?>" class="acrb-btn-book">
    339474                                        <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">
    341476                                            <path d="M5 12h14m-7-7l7 7-7 7"></path>
    342477                                        </svg>
    … …  
    347482                    <?php endforeach; ?>
    348483
    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">
    351486                            <circle cx="11" cy="11" r="8"></circle>
    352487                            <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
    353488                        </svg>
    354489                        <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>
    356492                    </div>
    357493                </div>
     494
     495                <!-- Numbered Pagination Controls -->
     496                <div class="acrb-pagination-container" id="acrb-pagination-container"></div>
    358497            </div>
    359498        </div>
    … …  
    362501    <script>
    363502    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        }
    374542
    375543        // View Mode Switcher
    … …  
    387555        }
    388556
    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') || '');
    415585                } else {
    416                     card.style.display = 'none';
     586                    return parseInt(b.getAttribute('data-id') || 0, 10) - parseInt(a.getAttribute('data-id') || 0, 10);
    417587                }
    418588            });
    419589
     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
    420745            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
    423749            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);
    431796    });
    432797    </script>
  • awesome-car-rental/trunk/frontend/checkout/acrb-frontned-checkout.php

    r3775773 r3777386  
    3030    $table_bookings = $wpdb->prefix . 'dev_nahian_bookings';
    3131    $table_cars     = $wpdb->prefix . 'dev_nahian_cars';
     32    $table_promos   = $wpdb->prefix . 'dev_nahian_promo_codes';
    3233
    3334    $acrb_car_id      = isset( $_POST['car_id'] ) ? absint( wp_unslash( $_POST['car_id'] ) ) : 0;
    … …  
    3940    $acrb_pickup_date = isset( $_POST['pickup_date'] ) ? sanitize_text_field( wp_unslash( $_POST['pickup_date'] ) ) : gmdate( 'Y-m-d H:i' );
    4041    $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;
    4242    $acrb_method      = isset( $_POST['payment_method'] ) ? sanitize_text_field( wp_unslash( $_POST['payment_method'] ) ) : 'pay_later';
    4343   
    4444    $acrb_insurance   = isset( $_POST['insurance_plan'] ) ? sanitize_text_field( wp_unslash( $_POST['insurance_plan'] ) ) : '';
    4545    $acrb_border      = isset( $_POST['border_permit'] ) ? sanitize_text_field( wp_unslash( $_POST['border_permit'] ) ) : '';
    46     $acrb_promo       = isset( $_POST['promo_code'] ) ? sanitize_text_field( wp_unslash( $_POST['promo_code'] ) ) : '';
     46    $acrb_promo       = isset( $_POST['promo_code'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_POST['promo_code'] ) ) ) : '';
    4747
    4848    if ( $acrb_car_id > 0 && ! empty( $acrb_pickup_date ) && ! empty( $acrb_return_date ) ) {
    4949        // 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 );
    54120
    55121        // Insert complete data directly into custom database table
    … …  
    58124            $table_bookings,
    59125            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' ),
    77147            ),
    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' )
    79149        );
    80150
    … …  
    83153            delete_transient( 'acrb_dashboard_revenue' );
    84154
    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
    86163            wp_safe_redirect( $acrb_redirect_url );
    87164            exit;
    … …  
    117194    $acrb_selected_font = $acrb_font_stacks[ $acrb_font_slug ] ?? $acrb_font_stacks['jakarta'];
    118195
    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        }',
    122207        esc_attr( $acrb_primary_color ),
    123208        esc_attr( $acrb_secondary_color ),
    … …  
    128213        esc_attr( $acrb_selected_font )
    129214    );
     215    wp_add_inline_style( 'acrb-checkout-style', $custom_css );
    130216
    131217    // 3. User Authentication Gate
    132218    if ( ! is_user_logged_in() ) {
    133219        $acrb_login_page_url = home_url( '/acrb-login/' );
    134         // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    135220        $acrb_request_uri    = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
    136221        $acrb_final_url      = add_query_arg( 'redirect_to', rawurlencode( home_url( $acrb_request_uri ) ), $acrb_login_page_url );
    … …  
    139224        ?>
    140225        <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>
    143228        </div>
    144229        <?php
    … …  
    165250
    166251    // Retrieve GET parameters from booking flow
    167     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     252    // phpcs:disable WordPress.Security.NonceVerification.Recommended
    168253    $acrb_car_id      = isset( $_GET['car_id'] ) ? absint( wp_unslash( $_GET['car_id'] ) ) : 0;
    169     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    170254    $acrb_pickup_date = isset( $_GET['pdate'] ) ? sanitize_text_field( wp_unslash( $_GET['pdate'] ) ) : gmdate( 'Y-m-d' );
    171     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    172255    $acrb_pickup_time = isset( $_GET['ptime'] ) ? sanitize_text_field( wp_unslash( $_GET['ptime'] ) ) : '10:00';
    173     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    174256    $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.Recommended
    176257    $acrb_return_time = isset( $_GET['rtime'] ) ? sanitize_text_field( wp_unslash( $_GET['rtime'] ) ) : '10:00';
    177     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    178258    $acrb_pickup_loc  = isset( $_GET['ploc'] ) ? sanitize_text_field( wp_unslash( $_GET['ploc'] ) ) : __( 'Main Terminal', 'awesome-car-rental' );
    179     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    180259    $acrb_return_loc  = isset( $_GET['dloc'] ) ? sanitize_text_field( wp_unslash( $_GET['dloc'] ) ) : $acrb_pickup_loc;
    181     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    182260    $acrb_sel_ins     = isset( $_GET['acrb_selected_insurance'] ) ? sanitize_text_field( wp_unslash( $_GET['acrb_selected_insurance'] ) ) : '';
    183     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    184261    $acrb_sel_border  = isset( $_GET['acrb_selected_border'] ) ? sanitize_text_field( wp_unslash( $_GET['acrb_selected_border'] ) ) : '';
    185     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    186262    $acrb_pass_method = isset( $_GET['pmethod'] ) ? sanitize_text_field( wp_unslash( $_GET['pmethod'] ) ) : key( $acrb_enabled_methods );
     263    // phpcs:enable WordPress.Security.NonceVerification.Recommended
    187264
    188265    if ( ! array_key_exists( $acrb_pass_method, $acrb_enabled_methods ) ) {
    … …  
    205282        ob_start();
    206283        ?>
    207         <div class="acrb-checkout-error" style="<?php echo esc_attr( $scoped_styles ); ?>">
     284        <div class="acrb-checkout-error">
    208285            <h3><?php esc_html_e( 'Fleet Inventory Empty', 'awesome-car-rental' ); ?></h3>
    209286            <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>
    … …  
    223300    $acrb_insurance_fee    = floatval( $car['insurance_fee'] ?? 0.00 );
    224301   
    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;
    232308   
    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)
    234313    $acrb_subtotal = $acrb_days * $acrb_price;
    235314
    … …  
    284363                'value'     => floatval( $p['discount_value'] ),
    285364                'min_spend' => floatval( $p['min_spend'] ),
    286                 'expiry'    => $p['expiry_date'],
     365                'expiry'    => (string) $p['expiry_date'],
    287366            );
    288367        }
    … …  
    291370    ob_start();
    292371    ?>
    293     <div class="acrb-checkout-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>">
     372    <div class="acrb-checkout-wrapper">
     373        <!-- Stepper Header -->
    294374        <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>
    298389        </div>
    299390
    … …  
    317408                <!-- Left Column -->
    318409                <div>
     410                    <!-- Vehicle & Itinerary Review -->
    319411                    <div class="acrb-checkout-card">
    320412                        <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>
    322414                            <span><?php esc_html_e( 'Review Vehicle & Itinerary', 'awesome-car-rental' ); ?></span>
    323415                        </h2>
    … …  
    339431
    340432                            <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>
    350463                                </div>
    351464                            </div>
    … …  
    353466                    </div>
    354467
     468                    <!-- Verified Account Info -->
    355469                    <div class="acrb-checkout-card">
    356470                        <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>
    358472                            <span><?php esc_html_e( 'Verified Customer Account', 'awesome-car-rental' ); ?></span>
    359473                        </h2>
    … …  
    366480                            <input type="email" value="<?php echo esc_attr( $acrb_current_user->user_email ); ?>" readonly class="acrb-checkout-input">
    367481                        </div>
    368                         <div class="acrb-checkout-field acrb-checkout-field-last">
     482                        <div class="acrb-checkout-field">
    369483                            <label><?php esc_html_e( 'Registered Phone Number', 'awesome-car-rental' ); ?></label>
    370484                            <input type="text" value="<?php echo esc_attr( $acrb_display_phone ); ?>" readonly class="acrb-checkout-input">
    … …  
    378492                    <div class="acrb-checkout-card">
    379493                        <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>
    381495                            <span><?php esc_html_e( 'Select Payment Method', 'awesome-car-rental' ); ?></span>
    382496                        </h2>
    … …  
    394508                    <div class="acrb-checkout-card">
    395509                        <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>
    397511                            <span><?php esc_html_e( 'Have a Promo Code?', 'awesome-car-rental' ); ?></span>
    398512                        </h2>
    … …  
    407521                    <div class="acrb-checkout-card">
    408522                        <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>
    410524                            <span><?php esc_html_e( 'Price Breakdown Summary', 'awesome-car-rental' ); ?></span>
    411525                        </h2>
    … …  
    494608
    495609                        <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>
    497611                            <span id="acrb_btn_text"><?php esc_html_e( 'Confirm & Place Secure Reservation', 'awesome-car-rental' ); ?></span>
    498612                        </button>
    … …  
    506620    <script>
    507621    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 ); ?>;
    513627        const currencySymbol = '<?php echo esc_js( $acrb_currency ); ?>';
    514628
    515         const sumGrandTotal = document.getElementById('acrb_sum_grand_total');
     629        const sumGrandTotal   = document.getElementById('acrb_sum_grand_total');
    516630        const finalTotalInput = document.getElementById('acrb_final_total_input');
    517         const hiddenPromoInput = document.getElementById('acrb_hidden_promo_code');
     631        const hiddenPromo    = document.getElementById('acrb_hidden_promo_code');
    518632       
    519         const couponBtn = document.getElementById('acrb_apply_coupon');
     633        const couponBtn   = document.getElementById('acrb_apply_coupon');
    520634        const couponInput = document.getElementById('acrb_coupon_code');
    521         const couponMsg = document.getElementById('acrb_coupon_msg');
     635        const couponMsg   = document.getElementById('acrb_coupon_msg');
    522636        const discountDiv = document.getElementById('acrb_discount_div');
    523637        const sumDiscount = document.getElementById('acrb_sum_discount');
    … …  
    534648        function recalcCheckout() {
    535649            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;
    537652
    538653            if (sumGrandTotal) sumGrandTotal.textContent = grand.toFixed(2);
    … …  
    564679                    if (promo.expiry && promo.expiry < currentDate && promo.expiry !== '') {
    565680                        appliedDiscountAmt = 0;
    566                         if (hiddenPromoInput) hiddenPromoInput.value = '';
     681                        if (hiddenPromo) hiddenPromo.value = '';
    567682                        if (discountDiv) discountDiv.style.display = 'none';
    568683                        if (couponMsg) {
    … …  
    573688                    } else if (computedSub < promo.min_spend) {
    574689                        appliedDiscountAmt = 0;
    575                         if (hiddenPromoInput) hiddenPromoInput.value = '';
     690                        if (hiddenPromo) hiddenPromo.value = '';
    576691                        if (discountDiv) discountDiv.style.display = 'none';
    577692                        if (couponMsg) {
    … …  
    588703                        if (appliedDiscountAmt > computedSub) appliedDiscountAmt = computedSub;
    589704
    590                         if (hiddenPromoInput) hiddenPromoInput.value = code;
     705                        if (hiddenPromo) hiddenPromo.value = code;
    591706                        if (sumDiscount) sumDiscount.textContent = '-' + currencySymbol + appliedDiscountAmt.toFixed(2);
    592707                        if (discountDiv) discountDiv.style.display = 'flex';
    … …  
    600715                } else {
    601716                    appliedDiscountAmt = 0;
    602                     if (hiddenPromoInput) hiddenPromoInput.value = '';
     717                    if (hiddenPromo) hiddenPromo.value = '';
    603718                    if (discountDiv) discountDiv.style.display = 'none';
    604719                    if (couponMsg) {
  • awesome-car-rental/trunk/frontend/frontend.php

    r3775773 r3777386  
    2121    'auth/acrb-frontend-auth.php',
    2222    'cars/acrb-frontend-cars.php',
     23    'cars/acrb-frontend-cars-grid.php',
    2324    'login/acrb-frontend-login.php',
    2425    'registration/acrb-frontend-register.php',
  • awesome-car-rental/trunk/frontend/login/acrb-frontend-login.php

    r3775773 r3777386  
    11<?php
    22/**
    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.
    55 * Location: templates/shortcodes/login.php
    66 *
    … …  
    1515}
    1616
    17 // 1. BACKEND LOGIC: AJAX Authenticator
     17// 2. BACKEND LOGIC: AJAX Authenticator with Email-to-Username Mapping
    1818add_action( 'wp_ajax_nopriv_acrb_ajax_login', 'acrb_handle_ajax_login' );
    1919
    … …  
    2525    }
    2626
    27     // B. Validate existence of username and password
     27    // B. Validate existence of username/email and password
    2828    if ( ! isset( $_POST['username'] ) || ! isset( $_POST['password'] ) ) {
    2929        wp_send_json_error( esc_html__( 'Required fields are missing.', 'awesome-car-rental' ) );
    … …  
    3131
    3232    // C. Unslash and Sanitize Inputs
    33     $username = sanitize_user( wp_unslash( $_POST['username'] ) );
     33    $input_login = sanitize_text_field( wp_unslash( $_POST['username'] ) );
    3434   
    3535    // Unslash password without sanitization to preserve special characters
    3636    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    3737    $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    }
    3847
    3948    $creds = array(
    … …  
    4756
    4857    if ( is_wp_error( $user ) ) {
    49         wp_send_json_error( esc_html__( 'Invalid email or password.', 'awesome-car-rental' ) );
     58        wp_send_json_error( esc_html__( 'Invalid credentials. Please check your email and password.', 'awesome-car-rental' ) );
    5059    } else {
    5160        wp_send_json_success();
    … …  
    5362}
    5463
    55 // 2. UI SHORTCODE
     64// 3. UI SHORTCODE
    5665add_shortcode( 'acrb_login', 'acrb_render_login_shortcode' );
    5766
    5867function 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
    6069    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>';
    6373    }
    6474
    … …  
    8494    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    8595
    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        }',
    89107        esc_attr( $primary_color ),
    90108        esc_attr( $secondary_color ),
    … …  
    95113        esc_attr( $selected_font )
    96114    );
     115    wp_add_inline_style( 'acrb-login-style', $custom_css );
    97116
    98117    ob_start();
    99118    ?>
    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 -->
    114121        <div class="acrb-auth-card">
    115122            <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>
    117124
    118125            <form id="acrb-login-form">
    … …  
    120127               
    121128                <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">
    124131                </div>
    125132
  • awesome-car-rental/trunk/frontend/registration/acrb-frontend-register.php

    r3775773 r3777386  
    8383function acrb_render_register_shortcode(): string {
    8484    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>';
    8788    }
    8889
    … …  
    108109    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    109110
    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        }',
    113122        esc_attr( $primary_color ),
    114123        esc_attr( $secondary_color ),
    … …  
    119128        esc_attr( $selected_font )
    120129    );
     130    wp_add_inline_style( 'acrb-register-style', $custom_css );
    121131
    122132    ob_start();
    123133    ?>
    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                 &copy; <?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 -->
    155136        <div class="acrb-reg-card">
    156137            <h2 class="acrb-reg-title"><?php esc_html_e( 'Create Account', 'awesome-car-rental' ); ?></h2>
    … …  
    177158                        <input type="email" id="acrb_reg_email" placeholder="john@example.com" required autocomplete="email">
    178159                    </div>
    179                     <div class="acrb-reg-field">
     160                    <div class="acrb-reg-field full-width">
    180161                        <label for="acrb_reg_pass"><?php esc_html_e( 'Secure Password (Min. 6 chars)', 'awesome-car-rental' ); ?></label>
    181162                        <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">
    184173                        <label for="acrb_reg_cpass"><?php esc_html_e( 'Confirm Password', 'awesome-car-rental' ); ?></label>
    185174                        <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>
    186178                    </div>
    187179                </div>
    … …  
    197189                </button>
    198190
    199                 <div id="acrb-reg-msg" class="acrb-reg-alert" aria-live="polite"></div>
     191                <div id="acrb-reg-msg" aria-live="polite"></div>
    200192               
    201193                <div class="acrb-reg-footer">
    202194                    <?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>
    204196                </div>
    205197            </form>
    … …  
    208200
    209201    <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) {
    212269            e.preventDefault();
    213             const btn = $('#acrb-reg-submit');
    214             const msg = $('#acrb-reg-msg');
    215270           
    216             const pass = $('#acrb_reg_pass').val();
    217             const cpass = $('#acrb_reg_cpass').val();
     271            const pass = passInput.value;
     272            const cpass = cpassInput.value;
    218273
    219274            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>';
    221276                return;
    222277            }
    223278
    224279            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>';
    226281                return;
    227282            }
    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);
    247312                } 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;
    250315                }
    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;
    254320            });
    255321        });
  • awesome-car-rental/trunk/frontend/search/acrb-frontend-search-form.php

    r3775773 r3777386  
    3939    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    4040
    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        }',
    4452        esc_attr( $primary_color ),
    4553        esc_attr( $secondary_color ),
    … …  
    5058        esc_attr( $selected_font )
    5159    );
     60    wp_add_inline_style( 'acrb-search-form-style', $custom_css );
    5261
    5362    // 3. Pull locations from settings
    5463    $locations = get_option( 'acrb_custom_pickup_locations', array() ) ?: get_option( 'acrb_custom_locations', array() );
    5564   
    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/' );
    5868
    5969    // 5. Get current Search Values (to keep fields filled on results page)
    60     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     70    // phpcs:disable WordPress.Security.NonceVerification.Recommended
    6171    $current_ploc  = isset( $_GET['ploc'] ) ? sanitize_text_field( wp_unslash( $_GET['ploc'] ) ) : '';
    62     // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    6372    $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
    6876
    6977    ob_start();
    7078    ?>
    71     <div class="acrb-search-wrapper" style="<?php echo esc_attr( $scoped_styles ); ?>">
     79    <div class="acrb-search-wrapper">
    7280        <form action="<?php echo esc_url( $results_page_url ); ?>" method="GET" class="acrb-search-form">
    7381            <div class="acrb-search-main">
    … …  
    7684                <div class="acrb-search-field">
    7785                    <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">
    7987                            <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"></path>
    8088                            <circle cx="12" cy="10" r="3"></circle>
    … …  
    98106                <div class="acrb-search-field">
    99107                    <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">
    101109                            <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z"></path>
    102110                            <circle cx="12" cy="10" r="3"></circle>
    … …  
    120128                <div class="acrb-search-field">
    121129                    <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">
    123131                            <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
    124132                            <line x1="16" y1="2" x2="16" y2="6"></line>
    … …  
    140148                <div class="acrb-search-field">
    141149                    <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">
    143151                            <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
    144152                            <line x1="16" y1="2" x2="16" y2="6"></line>
    … …  
    153161                           value="<?php echo esc_attr( $current_rdate ); ?>"
    154162                           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 ); ?>"
    156164                           required>
    157165                </div>
    … …  
    160168                <button type="submit" class="acrb-search-submit">
    161169                    <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">
    163171                        <circle cx="11" cy="11" r="8"></circle>
    164172                        <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
    … …  
    173181        const pDate = document.getElementById('acrb_pdate_in');
    174182        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
    176196        if (pDate && rDate) {
    177197            pDate.addEventListener('change', function() {
  • awesome-car-rental/trunk/frontend/single/acrb-frontned-car-single.php

    r3775773 r3777386  
    3939    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    4040
    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        }',
    4452        esc_attr( $primary_color ),
    4553        esc_attr( $secondary_color ),
    … …  
    5058        esc_attr( $selected_font )
    5159    );
     60    wp_add_inline_style( 'acrb-single-car-style', $custom_css );
    5261
    5362    // 3. Auth Check
    … …  
    6170        ?>
    6271        <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>
    6574        </div>
    6675        <?php
    … …  
    7887    $car = null;
    7988    if ( $car_id > 0 ) {
    80     // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    81     $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    }
    8392
    8493    if ( ! $car ) {
    … …  
    93102        ob_start();
    94103        ?>
    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>
    97106        </div>
    98107        <?php
    … …  
    105114    $insurance_fee    = floatval( $car['insurance_fee'] ?? 0.00 );
    106115   
    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'] ?? '' );
    122131   
    123132    // Resolve Image
    … …  
    134143    $raw_gallery = (string) ( $car['gallery'] ?? '' );
    135144    if ( ! empty( $raw_gallery ) ) {
    136         $gallery_ids = explode( ',', $raw_gallery );
     145        $gallery_ids = array_filter( array_map( 'trim', explode( ',', $raw_gallery ) ) );
    137146    }
    138147
    … …  
    148157            if ( ! empty( $ins['enabled'] ) && ! empty( $ins['name'] ) ) {
    149158                $available_insurance[] = array(
    150                     'name'  => $ins['name'],
     159                    'name'  => sanitize_text_field( $ins['name'] ),
    151160                    'price' => floatval( $ins['price'] ?? 0 ),
    152                     'type'  => $ins['type'] ?? 'day',
     161                    'type'  => sanitize_key( $ins['type'] ?? 'day' ),
    153162                );
    154163            }
    … …  
    161170            if ( ! empty( $border['enabled'] ) && ! empty( $border['country'] ) ) {
    162171                $available_borders[] = array(
    163                     'country' => $border['country'],
     172                    'country' => sanitize_text_field( $border['country'] ),
    164173                    'fee'     => floatval( $border['fee'] ?? 0 ),
    165                     'type'    => $border['type'] ?? 'flat',
     174                    'type'    => sanitize_key( $border['type'] ?? 'flat' ),
    166175                );
    167176            }
    … …  
    176185        foreach ( $db_promos as $p ) {
    177186            $promo_map[ strtoupper( trim( (string) $p['code'] ) ) ] = array(
    178                 'type'      => $p['discount_type'],
     187                'type'      => sanitize_key( $p['discount_type'] ),
    179188                'value'     => floatval( $p['discount_value'] ),
    180189                'min_spend' => floatval( $p['min_spend'] ),
    181                 'expiry'    => $p['expiry_date'],
     190                'expiry'    => (string) $p['expiry_date'],
    182191            );
    183192        }
    … …  
    185194
    186195    // 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 ) : '';
    189198    if ( empty( $checkout_page_url ) ) {
    190199        $checkout_page     = get_page_by_path( 'acrb-checkout' );
    … …  
    192201    }
    193202
     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
    194213    ob_start();
    195214    ?>
    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
    197223        <div class="acrb-flex-grid">
    198224           
    … …  
    204230                    <?php else : ?>
    205231                        <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>
    207237                            <p><?php esc_html_e( 'No photo available', 'awesome-car-rental' ); ?></p>
    208238                        </div>
    … …  
    212242                <div class="acrb-header-box">
    213243                    <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 ); ?>
    215245                    </div>
    216246                    <h1 class="acrb-car-title"><?php echo esc_html( $full_title ); ?></h1>
    … …  
    221251                    <button type="button" class="acrb-tab-btn active" data-tab="overview"><?php esc_html_e( 'Overview', 'awesome-car-rental' ); ?></button>
    222252                    <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>
    224254                    <button type="button" class="acrb-tab-btn" data-tab="video"><?php esc_html_e( 'Video Walkaround', 'awesome-car-rental' ); ?></button>
    225255                </div>
    … …  
    241271                            <div class="acrb-spec-node">
    242272                                <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>
    244274                                </div>
    245275                                <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>
    247277                            </div>
    248278                            <div class="acrb-spec-node">
    249279                                <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>
    251281                                </div>
    252282                                <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Seating', 'awesome-car-rental' ); ?></div>
    … …  
    255285                            <div class="acrb-spec-node">
    256286                                <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>
    258288                                </div>
    259289                                <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Baggage', 'awesome-car-rental' ); ?></div>
    … …  
    262292                            <div class="acrb-spec-node">
    263293                                <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>
    265295                                </div>
    266296                                <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Transmission', 'awesome-car-rental' ); ?></div>
    … …  
    269299                            <div class="acrb-spec-node">
    270300                                <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>
    274304                                <div class="acrb-spec-node-val"><?php echo esc_html( $fuel_type ); ?></div>
    275305                            </div>
    276306                            <div class="acrb-spec-node">
    277307                                <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>
    279309                                </div>
    280310                                <div class="acrb-spec-node-lbl"><?php esc_html_e( 'Min Rental', 'awesome-car-rental' ); ?></div>
    … …  
    289319                            <div class="acrb-gallery-grid">
    290320                                <?php if ( ! empty( $hero_img ) ) : ?>
    291                                     <div class="acrb-gallery-thumb-wrap">
     321                                    <div class="acrb-gallery-thumb-wrap is-active">
    292322                                        <img src="<?php echo esc_url( $hero_img ); ?>" class="acrb-gallery-item" alt="<?php echo esc_attr( $full_title ); ?>">
    293323                                    </div>
    294324                                <?php endif; ?>
    295325                                <?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 ) ) :
    305333                                ?>
    306334                                    <div class="acrb-gallery-thumb-wrap">
    307335                                        <img src="<?php echo esc_url( $img_url ); ?>" class="acrb-gallery-item" alt="<?php echo esc_attr( $full_title ); ?>">
    308336                                    </div>
    309                                 <?php endif; endif; endforeach; ?>
     337                                <?php endif; endforeach; ?>
    310338                            </div>
    311339                        <?php else : ?>
    312340                            <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>
    315342                            </div>
    316343                        <?php endif; ?>
    … …  
    324351                                <div class="acrb-video-container"><?php echo wp_kses_post( $embed ); ?></div>
    325352                            <?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>
    327354                            <?php endif; ?>
    328355                        <?php else : ?>
    329356                            <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>
    332358                            </div>
    333359                        <?php endif; ?>
    … …  
    346372                    <form action="<?php echo esc_url( $checkout_page_url ); ?>" method="GET" id="acrb-booking-form">
    347373                        <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">
    348379
    349380                        <!-- Pickup Date & Time -->
    … …  
    351382                            <div class="acrb-form-col-date">
    352383                                <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">
    354385                            </div>
    355386                            <div class="acrb-form-col-time">
    356387                                <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">
    358389                            </div>
    359390                        </div>
    … …  
    363394                            <div class="acrb-form-col-date">
    364395                                <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">
    366397                            </div>
    367398                            <div class="acrb-form-col-time">
    368399                                <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">
    370401                            </div>
    371402                        </div>
    … …  
    374405                        <div class="acrb-locations-row">
    375406                            <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>
    377408                                <select id="acrb_pickup_loc" name="ploc" required class="acrb-input acrb-select">
    378409                                    <option value=""><?php esc_html_e( 'Select Hub', 'awesome-car-rental' ); ?></option>
    … …  
    381412                                        if ( ! empty( $loc_name ) ) :
    382413                                    ?>
    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>
    384415                                    <?php endif; endforeach; ?>
    385416                                </select>
    386417                            </div>
    387418                            <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>
    389420                                <select id="acrb_return_loc" name="dloc" required class="acrb-input acrb-select">
    390421                                    <option value=""><?php esc_html_e( 'Select Hub', 'awesome-car-rental' ); ?></option>
    … …  
    393424                                        if ( ! empty( $loc_name ) ) :
    394425                                    ?>
    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>
    396427                                    <?php endif; endforeach; ?>
    397428                                </select>
    … …  
    402433                        <?php if ( ! empty( $available_insurance ) ) : ?>
    403434                        <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>
    405436                            <label class="acrb-luxury-card selected">
    406437                                <div class="acrb-luxury-info">
    … …  
    414445                                    <div class="acrb-luxury-info">
    415446                                        <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>
    417448                                    </div>
    418449                                    <span class="acrb-luxury-price">+<?php echo esc_html( $currency . number_format( $ins['price'], 2 ) . ( $ins['type'] === 'day' ? '/day' : ' (flat)' ) ); ?></span>
    … …  
    429460                                <div class="acrb-luxury-info">
    430461                                    <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>
    432463                                </div>
    433464                                <span class="acrb-luxury-price"><?php echo esc_html( $currency ); ?>0.00</span>
    … …  
    445476                        <?php endif; ?>
    446477
     478                        <!-- Live Minimum Days / Calculation Alert -->
     479                        <div class="acrb-calc-error" id="acrb-min-days-alert"></div>
     480
    447481                        <!-- Price Breakdown Summary Card -->
    448482                        <div class="acrb-breakdown-card">
    449483                            <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>
    451489                                <span><?php esc_html_e( 'Price Breakdown Summary', 'awesome-car-rental' ); ?></span>
    452490                            </div>
    … …  
    458496                                    <div>
    459497                                        <span><?php esc_html_e( 'Vehicle Rental', 'awesome-car-rental' ); ?></span>
    460                                         <span class="acrb-bd-sub" id="acrb_calc_days">0 Days selected</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>
    464502                            </div>
    465503
    … …  
    523561                        </div>
    524562
    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>
    527567                            <span><?php esc_html_e( 'Proceed to Secure Checkout', 'awesome-car-rental' ); ?></span>
    528568                        </button>
    … …  
    537577    document.addEventListener('DOMContentLoaded', function() {
    538578        // Tab System
    539         const tabBtns = document.querySelectorAll('.acrb-tab-btn');
     579        const tabBtns  = document.querySelectorAll('.acrb-tab-btn');
    540580        const tabPanes = document.querySelectorAll('.acrb-tab-pane');
    541581        tabBtns.forEach(btn => {
    … …  
    569609        setupLuxuryCards('input[name="acrb_selected_border"]');
    570610
    571         // Price Breakdown Logic with Dates, Times, Insurance & Border Crossing
     611        // Form elements
    572612        const pDate = document.getElementById('p_date');
    573613        const pTime = document.getElementById('p_time');
    574614        const rDate = document.getElementById('r_date');
    575615        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');
    578618       
    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');
    581621        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');
    582630       
    583631        // Dynamic breakdown rows
    584         const insuranceRow = document.getElementById('acrb_bd_insurance_row');
     632        const insuranceRow   = document.getElementById('acrb_bd_insurance_row');
    585633        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');
    589637        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;
    595644        const insuranceBase = container ? parseFloat(container.dataset.insurance) : 0;
    596         const currency = container ? container.dataset.currency : '$';
     645        const currency      = container ? container.dataset.currency : '$';
    597646
    598647        // Auto-sync return location with pickup location if empty
    … …  
    606655            if (pDate && rDate && pDate.value && rDate.value && pTime && rTime) {
    607656                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');
    609658               
    610659                const start = new Date(startStr);
    611                 const end = new Date(endStr);
     660                const end   = new Date(endStr);
    612661               
    613662                const diffHours = (end - start) / (1000 * 60 * 60);
    614663               
    615664                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;
    618680                    let optionsTotal = 0;
    619681
    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
    621686                    const selectedIns = document.querySelector('input[name="acrb_selected_insurance"]:checked');
    622687                    let insCost = 0;
    623688                    if (selectedIns && selectedIns.value) {
    624689                        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);
    627692                        optionsTotal += insCost;
    628693
     694                        if (hiddenInsCost) hiddenInsCost.value = insCost.toFixed(2);
    629695                        if (insuranceTitle) insuranceTitle.textContent = selectedIns.value;
    630696                        if (insuranceVal) insuranceVal.textContent = '+' + currency + insCost.toFixed(2);
    631697                        if (insuranceRow) insuranceRow.style.display = 'flex';
    632698                    } else {
     699                        if (hiddenInsCost) hiddenInsCost.value = '0';
    633700                        if (insuranceRow) insuranceRow.style.display = 'none';
    634701                    }
    635702
    636                     // 2. Border Crossing Calculation & UI Update
     703                    // 2. Border Crossing Calculation
    637704                    const selectedBorder = document.querySelector('input[name="acrb_selected_border"]:checked');
    638705                    let borderCost = 0;
    639706                    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);
    643710                        optionsTotal += borderCost;
    644711
     712                        if (hiddenBorderCost) hiddenBorderCost.value = borderCost.toFixed(2);
    645713                        if (borderTitle) borderTitle.textContent = selectedBorder.value + ' Permit';
    646714                        if (borderVal) borderVal.textContent = '+' + currency + borderCost.toFixed(2);
    647715                        if (borderRow) borderRow.style.display = 'flex';
    648716                    } else {
     717                        if (hiddenBorderCost) hiddenBorderCost.value = '0';
    649718                        if (borderRow) borderRow.style.display = 'none';
    650719                    }
    … …  
    652721                    const grandTotal = subtotal + optionsTotal + deposit + insuranceBase;
    653722
    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');
    655725                    if (displaySubtotal) displaySubtotal.textContent = currency + subtotal.toFixed(2);
    656726                    if (displayTotal) displayTotal.textContent = grandTotal.toFixed(2);
    657727                } 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;
    658733                    if (displayDays) displayDays.textContent = '0 Days selected';
    659734                    if (displaySubtotal) displaySubtotal.textContent = currency + '0.00';
    … …  
    681756        }
    682757
    683         // Gallery Hero Switcher
     758        // Gallery Hero Switcher with Active Thumb State
    684759        document.querySelectorAll('.acrb-gallery-item').forEach(img => {
    685760            img.addEventListener('click', function() {
    686761                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');
    689772            });
    690773        });
     774
     775        // Run initial calculation on page load
     776        calc();
    691777    });
    692778    </script>
  • awesome-car-rental/trunk/frontend/thanks/acrb-frontned-thanks.php

    r3775773 r3777386  
    4343    $selected_font = $font_stacks[ $font_slug ] ?? $font_stacks['jakarta'];
    4444
    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        }',
    4856        esc_attr( $primary_color ),
    4957        esc_attr( $secondary_color ),
    … …  
    5462        esc_attr( $selected_font )
    5563    );
     64    wp_add_inline_style( 'acrb-thanks-style', $custom_css );
    5665
    5766    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    5867    $booking_id = isset( $_GET['booking_id'] ) ? absint( wp_unslash( $_GET['booking_id'] ) ) : 0;
    5968
    60     // Validation against Custom Table (Using %i identifier placeholder for table name)
     69    // Validation against Custom Table
    6170    $booking = null;
    6271    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 );
    6574    }
    6675
    … …  
    6877        ob_start();
    6978        ?>
    70         <div class="acrb-error-container" style="<?php echo esc_attr( $scoped_styles ); ?>">
     79        <div class="acrb-error-container">
    7180            <h3><?php esc_html_e( 'No Active Booking Found', 'awesome-car-rental' ); ?></h3>
    7281            <p><?php esc_html_e( 'It looks like you reached this confirmation page directly without a valid reservation identifier.', 'awesome-car-rental' ); ?></p>
    … …  
    109118
    110119    // 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' );
    113122
    114123    // Calculate rental duration in days
    … …  
    125134    }
    126135
    127     // Lookup Promo details if applied (Using %i identifier placeholder for table name)
     136    // Lookup Promo details if applied
    128137    $promo_display = '';
    129138    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 );
    132141        if ( $p_record ) {
    133142            $p_type        = $p_record['discount_type'];
    … …  
    141150    ob_start();
    142151    ?>
    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
    144173        <div class="acrb-thanks-card">
    145174            <div class="acrb-thanks-header">
    … …  
    297326                <div class="acrb-action-buttons">
    298327                    <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">
    300329                            <polyline points="6 9 6 2 18 2 18 9"></polyline>
    301330                            <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  
    175175                'acrb-admin-extras-style',
    176176                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',
    177195                array( 'acrb-admin-main-style' ),
    178196                ACRB_VERSION
  • awesome-car-rental/trunk/includes/database.php

    r3775773 r3777386  
    1111
    1212if ( ! defined( 'ABSPATH' ) ) {
    13         exit;
     13    exit;
    1414}
    1515
    1616if ( ! defined( 'ACRB_DB_VERSION' ) ) {
    17         define( 'ACRB_DB_VERSION', '1.4.5' );
     17    define( 'ACRB_DB_VERSION', '1.4.6' );
    1818}
    1919
    … …  
    2222 */
    2323function 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 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 (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)
    7676    $sql_bookings = "CREATE TABLE {$table_bookings} (
    7777        id mediumint(9) NOT NULL AUTO_INCREMENT,
    … …  
    8787        return_date datetime DEFAULT NULL,
    8888        insurance_plan varchar(255) DEFAULT '',
     89        insurance_amount decimal(10,2) DEFAULT 0.00,
    8990        border_permit varchar(255) DEFAULT '',
     91        border_amount decimal(10,2) DEFAULT 0.00,
    9092        promo_code varchar(50) DEFAULT '',
     93        discount_amount decimal(10,2) DEFAULT 0.00,
     94        base_subtotal decimal(10,2) DEFAULT 0.00,
    9195        total_amount decimal(10,2) DEFAULT 0.00,
    9296        payment_method varchar(50) DEFAULT 'pay_later',
    … …  
    96100    ) {$charset_collate};";
    97101
    98         // 3. Categories Table Schema
    99         $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 Schema
    111         $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 Schema
    123         $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 Schema
    138         $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 Schema
    155         $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 Schema
    168         $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 Schema
    183         $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 );
    205209}
    206210
    … …  
    210214 */
    211215function 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' );
    214218}
    215219if ( 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' );
    217221}
    218222
    … …  
    222226 */
    223227function 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();
    226230}
    227231if ( 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' );
    229233}
    230234
    … …  
    234238 */
    235239function 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.NoCaching
    259                 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    }
    264268}
    265269add_action( 'admin_init', 'acrb_maybe_create_custom_tables' );
  • awesome-car-rental/trunk/readme.txt

    r3775781 r3777386  
    33Tags: car rental, vehicle booking, rental history, car rental crm, car booking, custom database architecture, checkout engine, seo schema
    44Requires at least: 5.8
    5 Tested up to: 6.9
     5Tested up to: 7.1.4
    66Requires PHP: 7.4
    7 Stable tag: 1.2
     7Stable tag: 1.2.1
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
Note: See TracChangeset for help on using the changeset viewer.