Plugin Directory

Changeset 3445596


Ignore:
Timestamp:
01/23/2026 01:01:09 PM (4 weeks ago)
Author:
2wstechnologies
Message:

fix design for mobile devices
fix the chat bulble displayed on page load !
interface optimizations ...

Location:
convertybot
Files:
97 added
10 edited

Legend:

Unmodified
Added
Removed
  • convertybot/trunk/assets/css/chat-modal-fixes.css

    r3437100 r3445596  
    1515#convertybot-chat-button {
    1616    z-index: 999998;
     17}
     18
     19/* ===================================
     20   HIDE BUTTON WHEN CHAT IS OPEN
     21   =================================== */
     22#convertybot-chat-button.convertybot-hidden {
     23    display: none !important;
    1724}
    1825
     
    3340
    3441@media (max-width: 768px) {
    35     /* Chat widget adjustments for mobile */
     42    /* Widget container - BOTTOM RIGHT CORNER ONLY */
    3643    #convertybot-widget {
    37         bottom: 0 !important;
    38         right: 0 !important;
    39         left: 0 !important;
    40         width: 100% !important;
     44        bottom: 10px !important;
     45        right: 10px !important;
     46        left: auto !important;
     47        top: auto !important;
     48        width: auto !important;
     49        max-width: none !important;
     50        height: auto !important;
     51        max-height: none !important;
     52    }
     53
     54    /* Chat window - SMALL, BOTTOM RIGHT, NOT FULL WIDTH */
     55    .convertybot-chat-window {
     56        position: fixed !important;
     57        bottom: 60px !important;
     58        right: 10px !important;
     59        left: auto !important; /* NOT from left - stay right */
     60        top: auto !important;
     61        width: 280px !important; /* Fixed small width */
     62        max-width: 85vw !important; /* Never more than 85% of viewport */
     63        height: 45vh !important;
     64        max-height: 320px !important;
     65        border-radius: 12px !important;
     66        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2) !important;
     67        overflow: hidden !important;
     68    }
     69
     70    /* Chat button - small circle on mobile */
     71    #convertybot-chat-button {
     72        width: 44px !important;
     73        height: 44px !important;
     74        padding: 0 !important;
     75        border-radius: 50% !important;
     76    }
     77
     78    /* Hidden button */
     79    #convertybot-chat-button.convertybot-hidden {
     80        display: none !important;
     81    }
     82
     83    #convertybot-chat-button .chat-button-text {
     84        display: none !important;
     85    }
     86
     87    #convertybot-chat-button svg {
     88        width: 18px !important;
     89        height: 18px !important;
     90    }
     91
     92    /* Chat header - very compact */
     93    .convertybot-chat-header {
     94        padding: 6px 8px !important;
     95    }
     96
     97    .convertybot-chat-header h4 {
     98        font-size: 11px !important;
     99    }
     100
     101    .convertybot-header-info {
     102        gap: 4px !important;
     103    }
     104
     105    .convertybot-avatar {
     106        width: 18px !important;
     107        height: 18px !important;
     108    }
     109
     110    .convertybot-avatar svg {
     111        width: 10px !important;
     112        height: 10px !important;
     113    }
     114
     115    .convertybot-status {
     116        font-size: 8px !important;
     117    }
     118
     119    .status-indicator {
     120        width: 5px !important;
     121        height: 5px !important;
     122    }
     123
     124    .convertybot-minimize {
     125        width: 20px !important;
     126        height: 20px !important;
     127        padding: 3px !important;
     128    }
     129
     130    .convertybot-minimize svg {
     131        width: 10px !important;
     132        height: 10px !important;
     133    }
     134
     135    /* Messages area - very compact */
     136    .convertybot-chat-messages {
     137        padding: 6px !important;
     138    }
     139
     140    .convertybot-message {
     141        gap: 4px !important;
     142        margin-bottom: 6px !important;
     143    }
     144
     145    .message-avatar {
     146        width: 15px !important;
     147        height: 15px !important;
     148        flex-shrink: 0 !important;
     149        border-radius: 50% !important;
     150    }
     151
     152    .message-avatar svg {
     153        width: 9px !important;
     154        height: 9px !important;
     155    }
     156
     157    .message-content {
     158        max-width: calc(100% - 10px) !important;
     159    }
     160
     161    /* IMPORTANT: Use high specificity to override desktop styles */
     162    .convertybot-message.bot .message-bubble,
     163    .convertybot-message.user .message-bubble,
     164    .message-bubble {
     165        padding: 4px 6px !important;
     166        font-size: 9px !important;
     167        line-height: 1.25 !important;
     168        border-radius: 8px !important;
     169        word-wrap: break-word !important;
     170        overflow-wrap: break-word !important;
     171    }
     172
     173    .convertybot-message .message-bubble strong,
     174    .message-bubble strong {
     175        font-size: 9px !important;
     176    }
     177
     178    .convertybot-message .message-bubble p,
     179    .message-bubble p {
     180        font-size: 9px !important;
     181        margin: 2px 0 !important;
     182    }
     183
     184    .convertybot-message .message-bubble ul,
     185    .message-bubble ul {
     186        margin: 2px 0 !important;
     187        padding-left: 12px !important;
     188    }
     189
     190    .convertybot-message .message-bubble li,
     191    .message-bubble li {
     192        font-size: 9px !important;
     193        margin: 1px 0 !important;
     194    }
     195
     196    .message-time {
     197        font-size: 8px !important;
     198        margin-top: 2px !important;
     199    }
     200
     201    /* Input area - very compact */
     202    .convertybot-chat-input {
     203        padding: 5px 6px !important;
     204        border-top: 1px solid #e0e0e0 !important;
     205    }
     206
     207    .convertybot-chat-input form {
     208        gap: 4px !important;
     209        display: flex !important;
     210        align-items: center !important;
     211    }
     212
     213    .convertybot-chat-input textarea,
     214    .convertybot-chat-input input {
     215        font-size: 11px !important;
     216        padding: 5px 8px !important;
     217        min-width: 0 !important;
     218        flex: 1 !important;
     219        border-radius: 14px !important;
     220        min-height: 26px !important;
     221        max-height: 50px !important;
     222    }
     223
     224    .convertybot-chat-input button {
     225        padding: 5px !important;
     226        min-width: 26px !important;
     227        width: 26px !important;
     228        height: 26px !important;
     229        flex-shrink: 0 !important;
     230        border-radius: 50% !important;
     231    }
     232
     233    .convertybot-chat-input button svg {
     234        width: 12px !important;
     235        height: 12px !important;
     236    }
     237
     238    /* Product cards in chat - ultra compact */
     239    .ai-products-inline {
     240        padding: 5px !important;
     241        margin-top: 5px !important;
     242        gap: 4px !important;
     243        background: #f5f5f5 !important;
     244        border-radius: 6px !important;
     245    }
     246
     247    .ai-product-card-inline {
     248        padding: 4px !important;
     249        border-radius: 4px !important;
     250    }
     251
     252    .product-inline-content {
     253        gap: 4px !important;
     254    }
     255
     256    .product-inline-header {
     257        gap: 6px !important;
     258    }
     259
     260    .product-inline-image {
     261        width: 30px !important;
     262        height: 30px !important;
     263        border-radius: 3px !important;
     264    }
     265
     266    .product-inline-title h5 {
     267        font-size: 9px !important;
     268        line-height: 1.2 !important;
     269    }
     270
     271    /* Show product details on mobile with compact size */
     272    .product-inline-details {
     273        display: block !important;
     274        padding: 2px 0 !important;
     275    }
     276
     277    .product-inline-rating {
     278        display: flex !important;
     279        font-size: 8px !important;
     280        gap: 2px !important;
     281        margin-bottom: 2px !important;
     282    }
     283
     284    .product-inline-rating .stars {
     285        font-size: 8px !important;
     286    }
     287
     288    .product-inline-rating .reviews {
     289        font-size: 7px !important;
     290    }
     291
     292    .product-inline-description {
     293        font-size: 7px !important;
     294        line-height: 1.2 !important;
     295        -webkit-line-clamp: 1 !important;
     296        overflow: hidden !important;
     297        text-overflow: ellipsis !important;
     298        white-space: nowrap !important;
     299        margin: 0 !important;
     300    }
     301
     302    .product-inline-footer {
     303        gap: 4px !important;
     304    }
     305
     306    .product-inline-price {
     307        font-size: 9px !important;
     308    }
     309
     310    .product-inline-link {
     311        padding: 2px 5px !important;
     312        font-size: 8px !important;
     313        border-radius: 3px !important;
     314    }
     315
     316    .ai-more-products-btn {
     317        padding: 4px 8px !important;
     318        font-size: 8px !important;
     319        border-radius: 8px !important;
     320    }
     321
     322    /* Suggestion chips - ultra compact, no horizontal scroll */
     323    .message-suggestions {
     324        display: flex !important;
     325        flex-wrap: wrap !important;
     326        gap: 2px !important;
     327        margin-top: 3px !important;
     328        overflow-x: hidden !important;
    41329        max-width: 100% !important;
    42         height: 100% !important;
    43         max-height: 100vh !important;
    44         border-radius: 0 !important;
    45     }
    46 
    47     /* Chat button smaller on mobile */
    48     #convertybot-chat-button {
    49         width: 56px !important;
    50         height: 56px !important;
    51         bottom: 16px !important;
    52         right: 16px !important;
    53     }
    54 
    55     /* Chat header smaller text */
    56     #convertybot-widget .chat-header h3 {
    57         font-size: 16px !important;
    58     }
    59 
    60     /* Messages smaller text */
    61     #convertybot-widget .message-text {
    62         font-size: 14px !important;
    63         line-height: 1.4 !important;
    64     }
    65 
    66     /* Input area adjustments */
    67     #convertybot-widget .chat-input-area {
    68         padding: 10px !important;
    69     }
    70 
    71     #convertybot-widget .chat-input {
    72         font-size: 14px !important;
    73         padding: 10px 12px !important;
    74     }
    75 
    76     #convertybot-widget .send-button {
    77         padding: 10px 16px !important;
    78         font-size: 14px !important;
    79     }
    80 
    81     /* Product cards in chat - smaller */
    82     #convertybot-widget .product-card {
    83         font-size: 12px !important;
    84     }
    85 
    86     #convertybot-widget .product-card h5 {
    87         font-size: 13px !important;
    88     }
    89 
    90     #convertybot-widget .product-card .price {
    91         font-size: 14px !important;
    92     }
    93 }
    94 
    95 /* Small phones */
    96 @media (max-width: 480px) {
    97     /* Even smaller button */
    98     #convertybot-chat-button {
    99         width: 50px !important;
    100         height: 50px !important;
    101         bottom: 12px !important;
    102         right: 12px !important;
    103     }
    104 
    105     /* Smaller text */
    106     #convertybot-widget .message-text {
    107         font-size: 13px !important;
    108     }
    109 
    110     #convertybot-widget .chat-input {
    111         font-size: 13px !important;
     330    }
     331
     332    .suggestion-chip {
     333        font-size: 7px !important;
     334        padding: 2px 4px !important;
     335        border-radius: 6px !important;
     336        white-space: nowrap !important;
     337        flex-shrink: 1 !important;
     338        max-width: 80px !important;
     339        overflow: hidden !important;
     340        text-overflow: ellipsis !important;
     341    }
     342
     343    /* Coupon cards - ultra compact */
     344    .ai-coupons-container {
     345        margin-top: 5px !important;
     346        gap: 4px !important;
     347    }
     348
     349    .ai-coupon-card {
     350        padding: 5px !important;
     351    }
     352
     353    .coupon-badge {
     354        font-size: 8px !important;
     355        padding: 2px 4px !important;
     356    }
     357
     358    .coupon-title {
     359        font-size: 10px !important;
     360    }
     361
     362    .coupon-description {
     363        font-size: 8px !important;
     364    }
     365
     366    .coupon-code {
     367        font-size: 9px !important;
     368    }
     369
     370    .coupon-copy-btn {
     371        padding: 3px 6px !important;
     372        font-size: 8px !important;
     373    }
     374}
     375
     376/* Small phones - even more compact */
     377@media (max-width: 380px) {
     378    .convertybot-chat-window {
     379        width: 260px !important;
     380        height: 40vh !important;
     381        max-height: 280px !important;
     382        bottom: 55px !important;
     383    }
     384
     385    .convertybot-message.bot .message-bubble,
     386    .convertybot-message.user .message-bubble,
     387    .message-bubble {
     388        font-size: 9px !important;
     389        padding: 4px 6px !important;
     390    }
     391
     392    .product-inline-image {
     393        width: 25px !important;
     394        height: 25px !important;
     395    }
     396
     397    .product-inline-title h5 {
     398        font-size: 8px !important;
     399    }
     400
     401    .convertybot-chat-input textarea,
     402    .convertybot-chat-input input {
     403        font-size: 10px !important;
    112404    }
    113405}
  • convertybot/trunk/assets/css/chatbot-improvements.css

    r3437100 r3445596  
    1111    visibility: hidden !important;
    1212    opacity: 0 !important;
     13    pointer-events: none !important;
     14    width: 0 !important;
     15    height: 0 !important;
     16    overflow: hidden !important;
     17    position: absolute !important;
     18    left: -9999px !important;
    1319}
    1420
     
    1723    visibility: visible !important;
    1824    opacity: 1 !important;
     25}
     26
     27/* ======================
     28   AUTO-HIDE BUTTON WHEN CHAT IS OPEN
     29   Multiple CSS solutions for maximum compatibility
     30   ====================== */
     31/* Solution 1: When chat window has visible class */
     32#convertybot-widget:has(#convertybot-chat-window.convertybot-visible) #convertybot-chat-button {
     33    display: none !important;
     34    visibility: hidden !important;
     35    opacity: 0 !important;
     36    pointer-events: none !important;
     37    width: 0 !important;
     38    height: 0 !important;
     39    position: absolute !important;
     40    left: -9999px !important;
     41}
     42
     43/* Solution 2: When chat window has inline display flex */
     44#convertybot-widget:has(#convertybot-chat-window[style*="flex"]) #convertybot-chat-button {
     45    display: none !important;
     46    visibility: hidden !important;
     47    opacity: 0 !important;
     48    pointer-events: none !important;
     49    width: 0 !important;
     50    height: 0 !important;
     51    position: absolute !important;
     52    left: -9999px !important;
     53}
     54
     55/* Solution 3: When widget has data-chat-open attribute */
     56#convertybot-widget[data-chat-open="true"] #convertybot-chat-button {
     57    display: none !important;
     58    visibility: hidden !important;
     59    opacity: 0 !important;
     60    pointer-events: none !important;
     61    width: 0 !important;
     62    height: 0 !important;
     63    position: absolute !important;
     64    left: -9999px !important;
    1965}
    2066
     
    110156.convertybot-message.bot {
    111157    display: block !important;
    112     margin-bottom: 5px !important;
    113     margin-left: 16px !important;
     158    margin-bottom: 8px !important;
     159    margin-left: 18px !important;
    114160    position: relative !important;
    115161}
    116162
    117163.convertybot-message.bot .message-avatar {
    118     width: 21px !important;
    119     height: 21px !important;
     164    width: 24px !important;
     165    height: 24px !important;
    120166    border-radius: 50% !important;
    121167    background: var(--convertybot-gradient, linear-gradient(135deg, #040404 0%, #2a2a2a 100%)) !important;
     
    123169    align-items: center !important;
    124170    justify-content: center !important;
    125     box-shadow: 0 2px 8px rgba(4, 4, 4, 0.3) !important;
     171    box-shadow: 0 2px 6px rgba(4, 4, 4, 0.3) !important;
    126172    position: absolute !important;
    127173    top: 0 !important;
    128     left: -12px !important;
     174    left: -14px !important;
    129175    z-index: 2 !important;
    130176    border: 2px solid white !important;
     
    132178
    133179.convertybot-message.bot .message-avatar svg {
    134     width: 16px !important;
    135     height: 16px !important;
     180    width: 14px !important;
     181    height: 14px !important;
    136182    color: white !important;
    137183}
     
    162208.convertybot-message.user {
    163209    display: block !important;
    164     margin-bottom: 5px !important;
    165     margin-right: 16px !important;
     210    margin-bottom: 8px !important;
     211    margin-right: 18px !important;
    166212    margin-left: auto !important;
    167213    position: relative !important;
     
    170216
    171217.convertybot-message.user .message-avatar {
    172     width: 20px !important;
    173     height: 20px !important;
     218    width: 24px !important;
     219    height: 24px !important;
    174220    border-radius: 50% !important;
    175221    background: linear-gradient(135deg, #00b894 0%, #00cec9 100%) !important;
     
    177223    align-items: center !important;
    178224    justify-content: center !important;
    179     box-shadow: 0 2px 8px rgba(0, 184, 148, 0.3) !important;
     225    box-shadow: 0 2px 6px rgba(0, 184, 148, 0.3) !important;
    180226    position: absolute !important;
    181227    top: 0 !important;
    182     right: -12px !important;
     228    right: -14px !important;
    183229    z-index: 2 !important;
    184230    border: 2px solid white !important;
     
    186232
    187233.convertybot-message.user .message-avatar svg {
    188     width: 15px !important;
    189     height: 15px !important;
     234    width: 14px !important;
     235    height: 14px !important;
    190236    fill: white !important;
    191237}
     
    541587    height: 650px !important;
    542588    max-height: calc(100vh - 120px) !important;
    543     display: flex !important;
    544589    flex-direction: column !important;
     590}
     591
     592/* Only show as flex when visible class is added */
     593.convertybot-chat-window.convertybot-visible {
     594    display: flex !important;
    545595}
    546596
     
    565615
    566616/* ======================
    567    RESPONSIVE
    568    ====================== */
    569 @media (max-width: 480px) {
     617   RESPONSIVE - MOBILE 768px
     618   ====================== */
     619@media (max-width: 768px) {
     620    /* CRITICAL: Force 10px font on mobile - this file loads LAST so these rules win */
     621    .convertybot-message.bot .message-bubble {
     622        font-size: 10px !important;
     623        line-height: 1.3 !important;
     624        padding: 5px 8px !important;
     625        padding-left: 14px !important;
     626    }
     627
     628    .convertybot-message.user .message-bubble {
     629        font-size: 10px !important;
     630        line-height: 1.3 !important;
     631        padding: 5px 8px !important;
     632        padding-right: 14px !important;
     633    }
     634
    570635    .convertybot-message.bot .message-content,
    571636    .convertybot-message.user .message-content {
    572         max-width: calc(100% - 38px) !important;
    573     }
    574 
    575     .convertybot-message.bot .message-avatar,
     637        max-width: calc(100% - 10px) !important;
     638    }
     639
     640    .convertybot-message.bot {
     641        margin-left: 12px !important;
     642    }
     643
     644    .convertybot-message.user {
     645        margin-right: 12px !important;
     646    }
     647
     648    .convertybot-message.bot .message-avatar {
     649        width: 15px !important;
     650        height: 15px !important;
     651        left: -10px !important;
     652        border-width: 1px !important;
     653    }
     654
    576655    .convertybot-message.user .message-avatar {
    577         width: 28px !important;
    578         height: 28px !important;
     656        width: 15px !important;
     657        height: 15px !important;
     658        right: -11px !important;
     659        border-width: 1px !important;
     660    }
     661
     662    .convertybot-message.bot .message-avatar svg,
     663    .convertybot-message.user .message-avatar svg {
     664        width: 9px !important;
     665        height: 9px !important;
    579666    }
    580667
    581668    .suggestion-chip {
    582         font-size: 12px !important;
    583         padding: 6px 12px !important;
    584     }
    585 }
     669        font-size: 8px !important;
     670        padding: 3px 6px !important;
     671    }
     672
     673}
     674
     675/* ======================
     676   RESPONSIVE - SMALL PHONES 480px
     677   ====================== */
     678@media (max-width: 480px) {
     679    .convertybot-message.bot .message-bubble,
     680    .convertybot-message.user .message-bubble {
     681        font-size: 10px !important;
     682        padding: 5px 8px !important;
     683    }
     684}
     685
     686/* Hide button when chat is open */
     687#convertybot-chat-button.convertybot-hidden {
     688    display: none !important;
     689}
  • convertybot/trunk/assets/css/consent-banner.css

    r3437100 r3445596  
    289289}
    290290
    291 /* Mobile Responsive */
     291/* Mobile Responsive - NOT full screen */
    292292@media (max-width: 640px) {
     293    .ai-consent-banner {
     294        padding: 15px !important;
     295    }
     296
     297    .ai-consent-overlay {
     298        background: rgba(0, 0, 0, 0.5) !important;
     299    }
     300
    293301    .ai-consent-modal {
    294         max-width: 100%;
    295         width: 100%;
    296         height: 100%;
    297         max-height: 100%;
    298         border-radius: 0;
     302        max-width: 300px !important;
     303        width: calc(100% - 30px) !important;
     304        height: auto !important;
     305        max-height: 70vh !important;
     306        border-radius: 12px !important;
     307        margin: auto !important;
    299308    }
    300309
    301310    .ai-consent-header {
    302         padding: 20px 20px 15px;
     311        padding: 12px 14px 10px !important;
    303312    }
    304313
    305314    .ai-consent-header h2 {
    306         font-size: 20px;
     315        font-size: 14px !important;
     316        margin-bottom: 6px !important;
    307317    }
    308318
    309319    .ai-consent-header p {
    310         font-size: 13px;
     320        font-size: 10px !important;
     321        line-height: 1.4 !important;
    311322    }
    312323
    313324    .ai-consent-body {
    314         padding: 15px 20px;
     325        padding: 10px 12px !important;
     326        max-height: 30vh !important;
     327        overflow-y: auto !important;
     328    }
     329
     330    .ai-consent-category {
     331        margin-bottom: 10px !important;
     332        padding-bottom: 10px !important;
     333    }
     334
     335    .ai-consent-category-header {
     336        gap: 10px !important;
     337    }
     338
     339    .ai-consent-category-info h3 {
     340        font-size: 12px !important;
     341        margin-bottom: 4px !important;
     342    }
     343
     344    .ai-consent-category-info p {
     345        font-size: 10px !important;
     346        line-height: 1.3 !important;
     347    }
     348
     349    .ai-consent-switch {
     350        width: 40px !important;
     351        height: 20px !important;
     352    }
     353
     354    .ai-consent-slider:before {
     355        height: 16px !important;
     356        width: 16px !important;
     357        left: 2px !important;
     358        bottom: 2px !important;
     359    }
     360
     361    .ai-consent-switch input:checked + .ai-consent-slider:before {
     362        transform: translateX(20px) !important;
    315363    }
    316364
    317365    .ai-consent-footer {
    318         padding: 15px 20px;
     366        padding: 10px 12px !important;
     367    }
     368
     369    .ai-consent-links {
     370        gap: 8px !important;
     371        margin-bottom: 10px !important;
     372    }
     373
     374    .ai-consent-links a {
     375        font-size: 10px !important;
    319376    }
    320377
    321378    .ai-consent-actions {
    322         flex-direction: column;
     379        flex-direction: row !important;
     380        flex-wrap: wrap !important;
     381        gap: 4px !important;
     382        justify-content: center !important;
    323383    }
    324384
    325385    .ai-consent-btn {
    326         width: 100%;
    327     }
    328 
    329     .ai-consent-links {
    330         flex-direction: column;
    331         gap: 10px;
    332         align-items: center;
     386        padding: 5px 6px !important;
     387        font-size: 8px !important;
     388        flex: 1 1 auto !important;
     389        min-width: 55px !important;
     390        max-width: 90px !important;
     391        white-space: nowrap !important;
     392        overflow: hidden !important;
     393        text-overflow: ellipsis !important;
     394    }
     395
     396    .ai-consent-btn-reject {
     397        flex: 0 1 auto !important;
     398    }
     399
     400    .ai-consent-btn-custom {
     401        flex: 1 1 auto !important;
     402    }
     403
     404    .ai-consent-btn-accept {
     405        flex: 1.5 1 auto !important;
    333406    }
    334407
    335408    .ai-consent-settings-btn {
    336         bottom: 10px;
    337         left: 10px;
    338         font-size: 12px;
    339         padding: 8px 12px;
     409        bottom: 8px !important;
     410        left: 8px !important;
     411        font-size: 10px !important;
     412        padding: 6px 10px !important;
     413    }
     414}
     415
     416/* Very small phones */
     417@media (max-width: 380px) {
     418    .ai-consent-modal {
     419        max-width: 260px !important;
     420        max-height: 65vh !important;
     421    }
     422
     423    .ai-consent-header h2 {
     424        font-size: 13px !important;
     425    }
     426
     427    .ai-consent-header p {
     428        font-size: 9px !important;
     429    }
     430
     431    .ai-consent-category-info h3 {
     432        font-size: 11px !important;
     433    }
     434
     435    .ai-consent-category-info p {
     436        font-size: 9px !important;
     437    }
     438
     439    .ai-consent-btn {
     440        font-size: 7px !important;
     441        padding: 4px 5px !important;
     442        min-width: 45px !important;
     443        max-width: 75px !important;
    340444    }
    341445}
  • convertybot/trunk/assets/css/frontend.css

    r3444997 r3445596  
    88    bottom: 20px;
    99    right: 20px;
     10    left: auto;
     11    top: auto;
    1012    z-index: 999999;
    1113    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
     
    408410/* Mobile Responsive */
    409411@media (max-width: 480px) {
     412    /* Widget container - ensure bottom right on mobile */
     413    .convertybot-widget {
     414        bottom: 15px !important;
     415        right: 15px !important;
     416        left: auto !important;
     417        top: auto !important;
     418    }
     419
     420    /* Chat window - NOT full screen, leave some margin to see the site */
    410421    .convertybot-chat-window {
    411         width: 100%;
    412         height: 100%;
    413         bottom: 0;
    414         right: 0;
    415         border-radius: 0;
     422        width: calc(100% - 20px);
     423        height: 70vh;
     424        max-height: 500px;
     425        bottom: 70px;
     426        right: 10px;
     427        left: 10px;
     428        border-radius: 16px;
    416429        position: fixed;
    417430    }
    418    
     431
     432    /* Smaller header on mobile */
     433    .convertybot-chat-header {
     434        padding: 12px 14px;
     435    }
     436
     437    .convertybot-chat-header h4 {
     438        font-size: 14px;
     439    }
     440
     441    /* Smaller messages on mobile */
     442    .convertybot-chat-messages {
     443        padding: 12px;
     444    }
     445
     446    .message-bubble {
     447        padding: 8px 12px;
     448        font-size: 14px;
     449    }
     450
     451    .message-avatar svg {
     452        width: 16px;
     453        height: 16px;
     454    }
     455
     456    /* Smaller input area on mobile */
     457    .convertybot-chat-input {
     458        padding: 10px;
     459    }
     460
     461    .convertybot-chat-input input {
     462        padding: 10px 12px;
     463        font-size: 14px;
     464    }
     465
     466    .convertybot-chat-input button {
     467        padding: 10px;
     468    }
     469
     470    /* Chat button - fixed position bottom right */
    419471    .convertybot-chat-button {
    420         bottom: 10px;
    421         right: 10px;
     472        bottom: 15px !important;
     473        right: 15px !important;
     474        left: auto !important;
     475        top: auto !important;
     476        width: 50px;
     477        height: 50px;
     478        font-size: 12px;
     479    }
     480
     481    .convertybot-chat-button svg {
     482        width: 22px;
     483        height: 22px;
     484    }
     485
     486    /* Hide button text on mobile if any */
     487    .convertybot-chat-button span {
     488        display: none;
     489    }
     490
     491    /* Suggestions smaller on mobile */
     492    .suggestion-chip {
     493        padding: 5px 10px;
     494        font-size: 12px;
    422495    }
    423496}
     
    845918}
    846919
    847 /* Mobile responsive */
     920/* Mobile responsive - product modal */
    848921@media (max-width: 480px) {
    849     .product-inline-content {
    850         flex-direction: column;
    851     }
    852    
    853     .product-inline-image {
    854         width: 100%;
    855         height: 120px;
    856     }
    857    
    858922    .ai-products-modal .modal-content {
    859923        width: 95%;
     924        max-height: 80vh;
    860925        margin: 10px;
    861926    }
    862    
     927
    863928    .ai-products-modal .products-grid {
    864929        grid-template-columns: 1fr;
     930        gap: 12px;
     931    }
     932
     933    .modal-product-card img {
     934        height: 150px;
     935    }
     936
     937    .modal-product-info {
     938        padding: 12px;
     939    }
     940
     941    .modal-product-info h4 {
     942        font-size: 14px;
     943    }
     944
     945    .btn-view-product-modal {
     946        padding: 10px 16px;
     947        font-size: 13px;
    865948    }
    866949}
  • convertybot/trunk/assets/css/product-cards-inline.css

    r3444997 r3445596  
    161161/* Mobile responsiveness */
    162162@media (max-width: 480px) {
     163    .ai-products-inline {
     164        padding: 10px;
     165        gap: 10px;
     166    }
     167
     168    .ai-product-card-inline {
     169        padding: 10px;
     170    }
     171
     172    /* Keep horizontal layout on mobile, just smaller */
    163173    .product-inline-content {
    164174        flex-direction: column;
    165     }
    166    
     175        gap: 8px;
     176    }
     177
     178    .product-inline-header {
     179        flex-direction: row;
     180        gap: 10px;
     181    }
     182
    167183    .product-inline-image {
    168         width: 100%;
    169         height: 150px;
    170     }
    171 }
     184        width: 50px;
     185        height: 50px;
     186        flex-shrink: 0;
     187    }
     188
     189    .product-inline-title h5 {
     190        font-size: 13px;
     191        line-height: 1.3;
     192    }
     193
     194    .product-inline-description {
     195        font-size: 12px;
     196        -webkit-line-clamp: 2;
     197    }
     198
     199    .product-inline-price {
     200        font-size: 14px;
     201    }
     202
     203    .product-inline-link {
     204        padding: 5px 10px;
     205        font-size: 12px;
     206    }
     207
     208    .ai-more-products-btn {
     209        padding: 8px 16px;
     210        font-size: 11px;
     211    }
     212}
  • convertybot/trunk/assets/css/products-modal-improved.css

    r3437100 r3445596  
    4949}
    5050
    51 /* Header */
    52 .ai-products-modal-header {
     51/* Header - gradient with white text (consistent across all devices) */
     52.ai-products-modal-header,
     53.ai-products-modal .modal-header {
    5354    display: flex;
    5455    justify-content: space-between;
    5556    align-items: center;
    5657    padding: 16px 20px;
    57     border-bottom: 1px solid #e0e0e0;
    58     background: #f8f9fa;
    59 }
    60 
    61 .ai-products-modal-header h3 {
     58    border-bottom: none;
     59    background: linear-gradient(135deg, var(--convertybot-primary, #007cba) 0%, #005a8a 100%);
     60    color: white;
     61    border-radius: 12px 12px 0 0;
     62}
     63
     64.ai-products-modal-header h3,
     65.ai-products-modal .modal-header h3 {
    6266    margin: 0;
    6367    font-size: 18px;
    6468    font-weight: 600;
    65     color: #333;
    66 }
    67 
    68 /* Close Button */
    69 .ai-products-modal-close {
    70     background: none;
     69    color: white;
     70}
     71
     72/* Close Button - white to match gradient header */
     73.ai-products-modal-close,
     74.ai-products-modal .modal-close {
     75    background: rgba(255, 255, 255, 0.2);
    7176    border: none;
    7277    font-size: 24px;
    73     color: #999;
     78    color: white;
    7479    cursor: pointer;
    7580    padding: 0;
     
    8388}
    8489
    85 .ai-products-modal-close:hover {
    86     background: #e0e0e0;
    87     color: #333;
     90.ai-products-modal-close:hover,
     91.ai-products-modal .modal-close:hover {
     92    background: rgba(255, 255, 255, 0.4);
     93    color: white;
    8894}
    8995
     
    247253
    248254@media (max-width: 768px) {
    249     /* Modal takes full screen on mobile */
     255    /* Modal overlay - centered with padding */
     256    .ai-products-modal {
     257        padding: 20px !important;
     258        align-items: center !important;
     259        justify-content: center !important;
     260    }
     261
     262    /* Modal content - NOT full screen, centered with margins */
    250263    .ai-products-modal .modal-content {
    251         max-width: 100%;
    252         max-height: 100vh;
    253         width: 100%;
    254         height: 100%;
    255         border-radius: 0;
    256         margin: 0;
    257     }
    258 
    259     /* Header - smaller on mobile */
     264        max-width: 320px !important;
     265        width: calc(100% - 40px) !important;
     266        max-height: 70vh !important;
     267        height: auto !important;
     268        border-radius: 12px !important;
     269        margin: auto !important;
     270        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
     271    }
     272
     273    /* Header - proper styling with gradient and WHITE text */
     274    .ai-products-modal .modal-header,
    260275    .ai-products-modal-header {
    261         padding: 12px 16px;
    262     }
    263 
     276        padding: 10px 12px !important;
     277        background: linear-gradient(135deg, var(--convertybot-primary, #007cba) 0%, #005a8a 100%) !important;
     278        color: white !important;
     279        border-radius: 12px 12px 0 0 !important;
     280    }
     281
     282    .ai-products-modal .modal-header h3,
    264283    .ai-products-modal-header h3 {
    265         font-size: 16px;
    266     }
    267 
     284        font-size: 12px !important;
     285        color: white !important;
     286        margin: 0 !important;
     287        font-weight: 600 !important;
     288    }
     289
     290    .ai-products-modal .modal-close,
    268291    .ai-products-modal-close {
    269         font-size: 22px;
    270         width: 28px;
    271         height: 28px;
    272     }
    273 
    274     /* Body - less padding */
     292        font-size: 18px !important;
     293        width: 24px !important;
     294        height: 24px !important;
     295        color: white !important;
     296        background: rgba(255, 255, 255, 0.2) !important;
     297        border-radius: 50% !important;
     298        display: flex !important;
     299        align-items: center !important;
     300        justify-content: center !important;
     301    }
     302
     303    /* Body - compact */
     304    .ai-products-modal .modal-body,
    275305    .ai-products-modal-body {
    276         padding: 12px;
     306        padding: 8px !important;
     307        max-height: 50vh !important;
     308        overflow-y: auto !important;
     309        background: #f8f9fa !important;
    277310    }
    278311
    279312    /* Single column on mobile */
    280     .ai-products-grid {
    281         grid-template-columns: 1fr;
    282         gap: 12px;
    283     }
    284 
    285     /* Smaller product cards on mobile */
    286     .ai-product-card-modal {
    287         display: flex;
    288         flex-direction: row;
    289         min-height: 120px;
    290     }
    291 
    292     .ai-product-card-modal img {
    293         width: 120px;
    294         height: 120px;
    295         flex-shrink: 0;
    296         border-bottom: none;
    297         border-right: 1px solid #e0e0e0;
    298     }
    299 
    300     .ai-product-info {
    301         padding: 10px;
    302         flex: 1;
    303     }
    304 
    305     .ai-product-info h4 {
    306         font-size: 13px;
    307         -webkit-line-clamp: 2;
    308         min-height: auto;
    309         margin-bottom: 6px;
    310     }
    311 
    312     .ai-product-rating {
    313         margin-bottom: 6px;
    314         font-size: 11px;
    315     }
    316 
    317     .ai-product-rating .stars {
    318         font-size: 12px;
    319     }
    320 
    321     .ai-product-description {
    322         font-size: 11px;
    323         -webkit-line-clamp: 2;
    324         margin-bottom: 8px;
    325     }
    326 
    327     .ai-product-price {
    328         font-size: 14px;
    329         margin-bottom: 8px;
    330     }
    331 
    332     .ai-product-btn {
    333         padding: 6px 10px;
    334         font-size: 12px;
     313    .ai-products-grid,
     314    .products-grid {
     315        grid-template-columns: 1fr !important;
     316        gap: 6px !important;
     317    }
     318
     319    /* Compact product cards - horizontal layout */
     320    .ai-product-card-modal,
     321    .modal-product-card {
     322        display: flex !important;
     323        flex-direction: row !important;
     324        min-height: 60px !important;
     325        padding: 0 !important;
     326        background: white !important;
     327        border-radius: 6px !important;
     328        overflow: hidden !important;
     329    }
     330
     331    .ai-product-card-modal img,
     332    .modal-product-card img {
     333        width: 55px !important;
     334        height: 55px !important;
     335        flex-shrink: 0 !important;
     336        border-bottom: none !important;
     337        border-right: 1px solid #e0e0e0 !important;
     338        border-radius: 0 !important;
     339        object-fit: cover !important;
     340    }
     341
     342    .ai-product-info,
     343    .modal-product-card .product-info {
     344        padding: 5px 6px !important;
     345        flex: 1 !important;
     346        display: flex !important;
     347        flex-direction: column !important;
     348        justify-content: center !important;
     349        gap: 2px !important;
     350    }
     351
     352    .ai-product-info h4,
     353    .modal-product-card .product-info h5 {
     354        font-size: 10px !important;
     355        -webkit-line-clamp: 1 !important;
     356        min-height: auto !important;
     357        margin: 0 0 2px 0 !important;
     358        line-height: 1.2 !important;
     359        overflow: hidden !important;
     360        text-overflow: ellipsis !important;
     361        white-space: nowrap !important;
     362    }
     363
     364    /* Show rating on mobile with smaller size */
     365    .ai-product-rating,
     366    .modal-product-card .product-rating {
     367        display: flex !important;
     368        font-size: 8px !important;
     369        gap: 2px !important;
     370        margin-bottom: 3px !important;
     371    }
     372
     373    .ai-product-rating .stars,
     374    .modal-product-card .product-rating .stars {
     375        font-size: 9px !important;
     376        letter-spacing: 0 !important;
     377    }
     378
     379    .ai-product-rating span:last-child,
     380    .modal-product-card .product-rating .reviews {
     381        font-size: 7px !important;
     382    }
     383
     384    /* Show description on mobile with smaller size */
     385    .ai-product-description,
     386    .modal-product-card .product-description {
     387        display: -webkit-box !important;
     388        font-size: 8px !important;
     389        line-height: 1.2 !important;
     390        -webkit-line-clamp: 2 !important;
     391        -webkit-box-orient: vertical !important;
     392        overflow: hidden !important;
     393        margin-bottom: 4px !important;
     394    }
     395
     396    .ai-product-price,
     397    .modal-product-card .price {
     398        font-size: 10px !important;
     399        margin: 0 !important;
     400        color: #e74c3c !important;
     401        font-weight: bold !important;
     402    }
     403
     404    .ai-product-btn,
     405    .btn-view-product-modal {
     406        padding: 3px 6px !important;
     407        font-size: 8px !important;
     408        border-radius: 3px !important;
     409        margin-top: 2px !important;
     410        display: inline-block !important;
     411        width: auto !important;
    335412    }
    336413
    337414    /* Show More Button */
    338     .ai-show-more-btn {
    339         font-size: 13px;
    340         padding: 10px 20px;
    341         margin-top: 12px;
     415    .ai-show-more-btn,
     416    .modal-show-more {
     417        font-size: 10px !important;
     418        padding: 6px 12px !important;
     419        margin-top: 8px !important;
    342420    }
    343421}
    344422
    345423/* Small phones */
    346 @media (max-width: 480px) {
    347     .ai-product-card-modal img {
    348         width: 100px;
    349         height: 100px;
    350     }
    351 
    352     .ai-product-info h4 {
    353         font-size: 12px;
    354     }
    355 
    356     .ai-product-price {
    357         font-size: 13px;
    358     }
    359 
    360     .ai-product-btn {
    361         font-size: 11px;
    362         padding: 5px 8px;
     424@media (max-width: 380px) {
     425    .ai-products-modal .modal-content {
     426        max-width: 280px !important;
     427        max-height: 65vh !important;
     428    }
     429
     430    .ai-product-card-modal img,
     431    .modal-product-card img {
     432        width: 45px !important;
     433        height: 45px !important;
     434    }
     435
     436    .ai-product-info h4,
     437    .modal-product-card .product-info h5 {
     438        font-size: 9px !important;
     439    }
     440
     441    .ai-product-price,
     442    .modal-product-card .price {
     443        font-size: 9px !important;
     444    }
     445
     446    .ai-product-btn,
     447    .btn-view-product-modal {
     448        font-size: 7px !important;
     449        padding: 2px 4px !important;
    363450    }
    364451}
  • convertybot/trunk/assets/js/frontend.js

    r3444997 r3445596  
    6868            const hasExistingSession = this.loadSession();
    6969
     70            // Handle autoOpen setting
     71            if (convertyBotConfig.autoOpen) {
     72                $('#convertybot-widget').attr('data-chat-open', 'true');
     73                $('#convertybot-chat-button').addClass('convertybot-hidden').hide();
     74                $('#convertybot-chat-window').addClass('convertybot-visible').css('display', 'flex');
     75                this.isOpen = true;
     76            } else {
     77                $('#convertybot-chat-button').show();
     78            }
     79
    7080            // Show the widget
    7181            $('#convertybot-widget').show();
     
    7888                this.createNewLocalSession();
    7989            }
    80            
     90
    8191            // Bind events
    8292            this.bindEvents();
    83            
    84             // Auto-open if configured
     93
     94            // Auto-open: focus input after a short delay (chat is already open)
    8595            if (convertyBotConfig.autoOpen) {
    8696                setTimeout(() => {
    87                     this.openChat();
    88                 }, 2000);
     97                    $('#convertybot-message-input').focus();
     98                    this.trackEvent('chat_opened');
     99                }, 500);
    89100            }
    90101
     
    383394        openChat: function() {
    384395            console.log('Opening chat...');
     396            const widget = $('#convertybot-widget');
    385397            const chatWindow = $('#convertybot-chat-window');
    386398            const chatButton = $('#convertybot-chat-button');
    387399
    388             // Use both class and direct style for reliability
    389             chatWindow.removeClass('convertybot-hidden').addClass('convertybot-visible');
    390             chatWindow.css('display', 'flex');
    391             chatButton.addClass('convertybot-hidden').removeClass('convertybot-visible');
    392             chatButton.css('display', 'none');
     400            // Set data attribute for CSS targeting
     401            widget.attr('data-chat-open', 'true');
     402
     403            // Show chat window
     404            chatWindow.addClass('convertybot-visible').css('display', 'flex');
     405
     406            // Hide button
     407            chatButton.addClass('convertybot-hidden').hide();
    393408
    394409            this.isOpen = true;
     
    401416            // Track event
    402417            this.trackEvent('chat_opened');
    403             console.log('Chat opened, button hidden');
    404418        },
    405419
     
    407421        closeChat: function() {
    408422            console.log('Closing chat...');
     423            const widget = $('#convertybot-widget');
    409424            const chatWindow = $('#convertybot-chat-window');
    410425            const chatButton = $('#convertybot-chat-button');
    411426
    412             // Use both class and direct style for reliability
    413             chatWindow.addClass('convertybot-hidden').removeClass('convertybot-visible');
    414             chatWindow.css('display', 'none');
    415             chatButton.removeClass('convertybot-hidden').addClass('convertybot-visible');
    416             chatButton.css('display', 'flex');
     427            // Remove data attribute
     428            widget.attr('data-chat-open', 'false');
     429
     430            // Hide chat window
     431            chatWindow.removeClass('convertybot-visible').css('display', 'none');
     432
     433            // Show button
     434            chatButton.removeClass('convertybot-hidden').show();
    417435
    418436            this.isOpen = false;
     
    651669            this.messageHistory.push(historyItem);
    652670            this.saveSession();
    653            
    654             // Scroll to bottom
    655             messagesContainer.scrollTop(messagesContainer[0].scrollHeight);
     671
     672            // Scroll behavior: for bot messages, scroll to the START of the message so user can read from beginning
     673            const lastAddedMessage = messagesContainer.find('.convertybot-message').last();
     674            if (type === 'bot' && lastAddedMessage.length) {
     675                // Scroll to the top of the new bot message
     676                const messageTop = lastAddedMessage[0].offsetTop - 10; // 10px padding
     677                messagesContainer.scrollTop(messageTop);
     678            } else {
     679                // For user messages, scroll to bottom as usual
     680                messagesContainer.scrollTop(messagesContainer[0].scrollHeight);
     681            }
    656682           
    657683            // Play sound if enabled
     
    729755                            </div>
    730756                            <div class="product-inline-footer">
    731                                 <div class="product-inline-price">${product.price_html || product.price || 'Prix sur demande'}</div>
     757                                <div class="product-inline-price">${product.price_html || this.formatPrice(product.price)}</div>
    732758                                <a href="${product.url || '#'}" class="product-inline-link" target="_blank" rel="noopener noreferrer">
    733759                                    ${convertyBotConfig.viewProductText || 'Voir le produit'}
     
    760786            // Append products HTML INSIDE the message bubble
    761787            messageBubble.append(productsHtml);
    762            
     788
    763789            // Hide the separate products container
    764790            $('#convertybot-products').hide();
    765            
    766             // Scroll to show new content
     791
     792            // Scroll to the START of the bot message so user can read from beginning
    767793            const messagesContainer = $('#convertybot-chat-messages');
    768             messagesContainer.scrollTop(messagesContainer[0].scrollHeight);
     794            const lastBotMsg = messagesContainer.find('.convertybot-message.bot').last();
     795            if (lastBotMsg.length) {
     796                const messageTop = lastBotMsg[0].offsetTop - 10; // 10px padding
     797                messagesContainer.scrollTop(messageTop);
     798            }
    769799        },
    770800       
     
    797827                                </div>
    798828                            ` : '<div class="product-rating"><span class="stars">★★★★☆</span> <span class="reviews">(Pas encore d\'avis)</span></div>'}
    799                             <div class="price">${product.price_html || product.price || 'Prix sur demande'}</div>
     829                            <div class="price">${product.price_html || this.formatPrice(product.price)}</div>
    800830                            <div class="product-description">${product.shortDescription || product.description ? this.escapeHtml(product.shortDescription || product.description) : 'Excellent produit recommandé pour vous'}</div>
    801831                            <div class="product-actions">
     
    10261056        },
    10271057
     1058        // Format price with currency symbol (fix EUR120 -> 120,00 €)
     1059        formatPrice: function(priceData) {
     1060            // If already HTML formatted (from WooCommerce), use it
     1061            if (typeof priceData === 'string' && (priceData.includes('<span') || priceData.includes('€') || priceData.includes('$'))) {
     1062                return priceData;
     1063            }
     1064
     1065            // Extract numeric value from string like "EUR120" or "120" or "120.00"
     1066            let numericPrice = priceData;
     1067            if (typeof priceData === 'string') {
     1068                // Remove currency codes (EUR, USD, etc.) and extract number
     1069                numericPrice = priceData.replace(/[A-Z]{3}/gi, '').replace(/[^\d.,]/g, '').trim();
     1070            }
     1071
     1072            // Parse the number
     1073            const price = parseFloat(numericPrice);
     1074            if (isNaN(price)) {
     1075                return priceData || 'Prix sur demande';
     1076            }
     1077
     1078            // Format with locale (French style: 120,00 €)
     1079            const currencySymbol = convertyBotConfig.currencySymbol || '€';
     1080            const formattedNumber = price.toLocaleString('fr-FR', {
     1081                minimumFractionDigits: 2,
     1082                maximumFractionDigits: 2
     1083            });
     1084
     1085            // Return price with symbol after (European style)
     1086            return `${formattedNumber} ${currencySymbol}`;
     1087        },
     1088
    10281089        // Format markdown to HTML (safe - escapes HTML first, then converts markdown)
    10291090        formatMarkdown: function(text) {
    1030             if (!text) return '';
    1031 
    1032             // First escape HTML to prevent XSS
    1033             let formatted = this.escapeHtml(text);
    1034 
    1035             // Convert markdown to HTML (order matters!)
    1036 
    1037             // 1. Bold: **text** or __text__ (must be before italic)
    1038             formatted = formatted.replace(/\*\*([^*]+?)\*\*/g, '<strong>$1</strong>');
    1039             formatted = formatted.replace(/__([^_]+?)__/g, '<strong>$1</strong>');
    1040 
    1041             // 2. Italic: *text* or _text_ (simple version, browser compatible)
    1042             // Only match single * or _ that are not part of ** or __
    1043             formatted = formatted.replace(/(?:^|[^*])\*([^*\n]+?)\*(?:[^*]|$)/g, function(match, content) {
    1044                 // Preserve the characters before and after if they exist
    1045                 const before = match.charAt(0) === '*' ? '' : match.charAt(0);
    1046                 const after = match.charAt(match.length - 1) === '*' ? '' : match.charAt(match.length - 1);
    1047                 return before + '<em>' + content + '</em>' + after;
    1048             });
    1049 
    1050             // 3. Inline code: `code`
    1051             formatted = formatted.replace(/`([^`]+?)`/g, '<code>$1</code>');
    1052 
    1053             // 4. Bullet lists: lines starting with - or * (before line breaks conversion)
    1054             // Split by newlines, process, then rejoin
    1055             const lines = formatted.split('\n');
    1056             let inList = false;
    1057             const processedLines = [];
    1058 
    1059             for (let i = 0; i < lines.length; i++) {
    1060                 const line = lines[i];
    1061                 const listMatch = line.match(/^[\-\*]\s+(.+)$/);
    1062 
    1063                 if (listMatch) {
    1064                     if (!inList) {
    1065                         processedLines.push('<ul>');
    1066                         inList = true;
     1091            try {
     1092                if (!text) return '';
     1093                if (typeof text !== 'string') {
     1094                    text = String(text);
     1095                }
     1096
     1097                // First escape HTML to prevent XSS
     1098                let formatted = this.escapeHtml(text);
     1099
     1100                // Convert markdown to HTML (order matters!)
     1101
     1102                // 1. Bold: **text** or __text__ (must be before italic)
     1103                formatted = formatted.replace(/\*\*([^*]+?)\*\*/g, '<strong>$1</strong>');
     1104                formatted = formatted.replace(/__([^_]+?)__/g, '<strong>$1</strong>');
     1105
     1106                // 2. Italic: *text* (after bold conversion, remaining single * are italic)
     1107                // Since ** is already converted to <strong>, remaining *text* patterns are italic
     1108                formatted = formatted.replace(/\*([^*\n]+?)\*/g, '<em>$1</em>');
     1109
     1110                // 3. Inline code: `code`
     1111                formatted = formatted.replace(/`([^`]+?)`/g, '<code>$1</code>');
     1112
     1113                // 4. Bullet lists: lines starting with - or * (before line breaks conversion)
     1114                const lines = formatted.split('\n');
     1115                let inList = false;
     1116                const processedLines = [];
     1117
     1118                for (let i = 0; i < lines.length; i++) {
     1119                    const line = lines[i];
     1120                    const listMatch = line.match(/^[\-\*]\s+(.+)$/);
     1121
     1122                    if (listMatch) {
     1123                        if (!inList) {
     1124                            processedLines.push('<ul>');
     1125                            inList = true;
     1126                        }
     1127                        processedLines.push('<li>' + listMatch[1] + '</li>');
     1128                    } else {
     1129                        if (inList) {
     1130                            processedLines.push('</ul>');
     1131                            inList = false;
     1132                        }
     1133                        processedLines.push(line);
    10671134                    }
    1068                     processedLines.push('<li>' + listMatch[1] + '</li>');
    1069                 } else {
    1070                     if (inList) {
    1071                         processedLines.push('</ul>');
    1072                         inList = false;
    1073                     }
    1074                     processedLines.push(line);
    1075                 }
    1076             }
    1077 
    1078             if (inList) {
    1079                 processedLines.push('</ul>');
    1080             }
    1081 
    1082             formatted = processedLines.join('\n');
    1083 
    1084             // 5. Line breaks: \n to <br> (but not inside lists)
    1085             formatted = formatted.replace(/\n(?!<\/?[uo]l|<\/?li)/g, '<br>');
    1086             formatted = formatted.replace(/\n/g, '');
    1087 
    1088             return formatted;
     1135                }
     1136
     1137                if (inList) {
     1138                    processedLines.push('</ul>');
     1139                }
     1140
     1141                formatted = processedLines.join('\n');
     1142
     1143                // 5. Line breaks: \n to <br> (but not inside lists)
     1144                formatted = formatted.replace(/\n(?!<\/?[uo]l|<\/?li)/g, '<br>');
     1145                formatted = formatted.replace(/\n/g, '');
     1146
     1147                return formatted;
     1148            } catch (error) {
     1149                console.error('formatMarkdown error:', error);
     1150                // Fallback: just escape HTML and convert newlines
     1151                return this.escapeHtml(text).replace(/\n/g, '<br>');
     1152            }
    10891153        },
    10901154
     
    12521316            }
    12531317
    1254             // Remove or replace problematic characters
     1318            // Remove problematic control characters BUT PRESERVE newlines (\n = \u000A) and tabs (\t = \u0009)
     1319            // Control chars: \u0000-\u0008, \u000B-\u000C, \u000E-\u001F, \u007F-\u009F
    12551320            return content
    1256                 .replace(/[\u0000-\u001F\u007F-\u009F]/g, '') // Remove control characters
    1257                 .replace(/\u2028/g, ' ') // Replace line separator
    1258                 .replace(/\u2029/g, ' ') // Replace paragraph separator
     1321                .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, '') // Remove control chars except \t, \n, \r
     1322                .replace(/\r\n/g, '\n') // Normalize Windows line endings
     1323                .replace(/\r/g, '\n')   // Normalize old Mac line endings
     1324                .replace(/\u2028/g, '\n') // Replace line separator with newline
     1325                .replace(/\u2029/g, '\n\n') // Replace paragraph separator with double newline
    12591326                .trim();
    12601327        },
  • convertybot/trunk/convertybot.php

    r3444997 r3445596  
    33 * Plugin Name: ConvertyBot
    44 * Description: An intelligent AI-powered sales assistant for WooCommerce that helps visitors discover products, provides personalized recommendations, and generates dynamic discount codes to boost sales.
    5  * Version: 1.0.16
     5 * Version: 1.0.21
    66 * Author: ConvertyBot, 2wstechnologies Team
    77 * Author URI: https://convertybot.com
     
    4242
    4343// Define plugin constants
    44 define('CONVERTYBOT_VERSION', '1.0.16');
     44define('CONVERTYBOT_VERSION', '1.0.26');
    4545define('CONVERTYBOT_PLUGIN_URL', plugin_dir_url(__FILE__));
    4646define('CONVERTYBOT_PLUGIN_PATH', plugin_dir_path(__FILE__));
  • convertybot/trunk/readme.txt

    r3444997 r3445596  
    66Tested up to: 6.9
    77Requires PHP: 7.2
    8 Stable tag: 1.0.16
     8Stable tag: 1.0.26
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    249249== Changelog ==
    250250
     251= 1.0.26 =
     252* FIXED: Chat window not closing when minimize button clicked
     253* FIXED: Removed CSS rule that was preventing chat from hiding (display: flex !important)
     254* IMPROVED: Chat visibility now properly controlled by .convertybot-visible class
     255
     256= 1.0.25 =
     257* FIXED: Page load performance issues caused by aggressive JavaScript
     258* REMOVED: MutationObserver and multiple timeout watchers that slowed page load
     259* SIMPLIFIED: Button show/hide logic using standard jQuery methods
     260
     261= 1.0.24 =
     262* FIXED: Chat button visibility improvements
     263* ADDED: Global function for button hiding
     264
     265= 1.0.23 =
     266* FIXED: Mobile font size (10px) for chat messages now properly applied
     267* FIXED: Mobile avatar positioning (bot: left -10px, user: right -11px)
     268* IMPROVED: CSS specificity for mobile styles in chatbot-improvements.css
     269
     270= 1.0.22 =
     271* ADDED: Inline styles in PHP template for mobile responsiveness
     272* IMPROVED: Button hiding mechanism
     273
     274= 1.0.21 =
     275* IMPROVED: Mobile responsive design - smaller, more compact chat interface
     276* FIXED: Message text size reduced to 12px for better mobile readability
     277* FIXED: Suggestion chips font size optimized for mobile (10px)
     278* FIXED: Chat button visibility issue on initial page load with auto-open
     279* FIXED: Cookie consent banner button text overflow on mobile
     280* IMPROVED: Better user experience on small screens
     281
     282= 1.0.20 =
     283* FIXED: Auto-scroll now scrolls to the START of bot messages (not the end)
     284* FIXED: Currency format display (EUR120 now shows as 120,00 €)
     285* IMPROVED: Price formatting with proper locale support
     286* FIXED: Suggestion chips no longer require horizontal scroll on mobile
     287* IMPROVED: Cookie consent banner mobile layout
     288
     289= 1.0.19 =
     290* IMPROVED: Mobile responsive chat window - positioned in bottom-right corner
     291* IMPROVED: Products modal with margins and centered layout on mobile
     292* IMPROVED: Cookie consent banner compact design for mobile
     293* FIXED: Chat window no longer covers full screen on mobile devices
     294* REDUCED: All mobile element sizes for better UX
     295
     296= 1.0.18 =
     297* FIXED: Message formatting preserved after page navigation
     298* FIXED: Bot message HTML/CSS formatting no longer lost on reload
     299* FIXED: Newline characters preserved in sanitizeMessageContent()
     300
     301= 1.0.17 =
     302* FIXED: Sender name in support emails
     303* FIXED: Last occurrence of old plugin name updated to ConvertyBot
     304* IMPROVED: Brand consistency across all plugin files
     305
     306= 1.0.16 =
     307* NEW: Tax inclusion in payment sessions
     308* FIXED: Deleted customer ID handling for subscription retry
     309* FIXED: Z-index problems in modals for plugin interfaces
     310* ADDED: Confirmation dialogs before subscription upgrade/downgrade
     311
     312= 1.0.15 =
     313* NEW: Usage tracking for monthly conversations and API calls
     314* IMPROVED: Plugin ready for marketplace submission
     315* FIXED: Various UI/UX improvements
     316
    251317= 1.0.14 =
    252318* Full WordPress Plugin Check compliance
     
    294360== Upgrade Notice ==
    295361
     362= 1.0.26 =
     363Critical fix - Chat window can now be properly closed/minimized. Also fixes mobile font sizes and avatar positioning.
     364
     365= 1.0.21 =
     366Mobile experience update - Significantly improved mobile responsive design with smaller, more compact chat interface. Recommended for all users with mobile visitors.
     367
     368= 1.0.20 =
     369UX improvements - Better auto-scroll behavior and proper currency formatting. Recommended update.
     370
     371= 1.0.19 =
     372Major mobile responsive update - Chat window and modals now properly sized for mobile devices.
     373
    296374= 1.0.14 =
    297375WordPress Plugin Check compliance update - Recommended for all users. Includes security improvements and internationalization enhancements.
  • convertybot/trunk/templates/frontend/chatbot-widget.php

    r3437100 r3445596  
    1010
    1111$options = get_option('convertybot_options', array());
     12$auto_open = !empty($options['auto_open']);
    1213?>
    1314
    1415<!-- ConvertyBot Widget -->
    15 <div id="convertybot-widget" class="convertybot-widget" style="display: none;">
    16     <!-- Modern Chat Button -->
    17     <div id="convertybot-chat-button" class="convertybot-chat-button">
     16<div id="convertybot-widget" class="convertybot-widget" style="display: none;"<?php echo $auto_open ? ' data-chat-open="true"' : ''; ?>>
     17    <!-- Modern Chat Button - Hidden initially if auto_open is enabled -->
     18    <div id="convertybot-chat-button" class="convertybot-chat-button<?php echo $auto_open ? ' convertybot-hidden' : ''; ?>" <?php echo $auto_open ? 'style="display: none !important; visibility: hidden !important; opacity: 0 !important; width: 0 !important; height: 0 !important;"' : ''; ?>>
    1819        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    1920            <path d="m3 21 1.9-5.7a8.5 8.5 0 1 1 3.8 3.8z"/>
     
    2223        <span class="convertybot-badge" style="display: none;">0</span>
    2324    </div>
    24    
    25     <!-- Chat Window -->
    26     <div id="convertybot-chat-window" class="convertybot-chat-window" style="display: none;">
     25
     26    <!-- Chat Window - Shown initially if auto_open is enabled -->
     27    <div id="convertybot-chat-window" class="convertybot-chat-window<?php echo $auto_open ? ' convertybot-visible' : ''; ?>" style="display: <?php echo $auto_open ? 'flex' : 'none'; ?>;">
    2728        <!-- Header -->
    2829        <div class="convertybot-chat-header">
     
    126127    <div class="modal-content" onclick="event.stopPropagation()">
    127128        <div class="modal-header">
    128             <h3><?php esc_html_e('All Recommended Products', 'convertybot'); ?></h3>
    129             <button class="modal-close" onclick="ConvertyBotChat.closeProductsModal()">&times;</button>
     129            <h3><?php echo esc_html__('Tous les produits recommandés', 'convertybot'); ?></h3>
     130            <button class="modal-close" onclick="ConvertyBotChat.closeProductsModal()" aria-label="<?php esc_attr_e('Fermer', 'convertybot'); ?>">&times;</button>
    130131        </div>
    131132        <div class="modal-body">
Note: See TracChangeset for help on using the changeset viewer.