Chat Support | Tiny Cactii
/* ========================================================================= */ /* ========================================================================= */ /* PLANT SOUL REPLY FEEDBACK — injected after psBotMessage renders */ /* ========================================================================= */ (function() { function _attachPsReplyFb(bubbleWrap) { var textEl = bubbleWrap.querySelector('.ps-bot-text, .tc-chat-text'); if (!textEl) return; if (bubbleWrap.querySelector('.tc-ps-reply-fb')) return; // already attached var _fbId = 'ps-rf-' + Math.random().toString(36).slice(2,8); var fbDiv = document.createElement('div'); fbDiv.className = 'tc-ps-reply-fb'; fbDiv.style.cssText = 'margin-top:8px;padding-top:8px;border-top:1px solid rgba(124,58,237,0.15);'; fbDiv.innerHTML = '
Was this helpful?
' + '
' + '★' + '★' + '★' + '★' + '★' + '
' + '' + '' + '' + '' + ''; var bubble = bubbleWrap.querySelector('.tc-chat-bubble') || bubbleWrap; bubble.appendChild(fbDiv); // Stop keyboard propagation fbDiv.querySelectorAll('input').forEach(function(inp) { ['click','keydown','keyup','keypress','input','focus'].forEach(function(ev) { inp.addEventListener(ev, function(e) { e.stopPropagation(); e.stopImmediatePropagation(); }); }); }); // Stars var _rfRating = 0; fbDiv.querySelectorAll('.tc-ps-rf-star').forEach(function(star) { star.addEventListener('click', function(e) { e.stopPropagation(); _rfRating = parseInt(star.dataset.v); fbDiv.querySelectorAll('.tc-ps-rf-star').forEach(function(s) { s.style.color = parseInt(s.dataset.v) <= _rfRating ? '#f59e0b' : '#c4b5fd'; }); var errEl = fbDiv.querySelector('.tc-ps-rf-err'); if (errEl) errEl.style.display = 'none'; }); }); // Submit fbDiv.querySelector('.tc-ps-rf-btn').addEventListener('click', function(e) { e.stopPropagation(); if (_rfRating === 0) { var errEl = fbDiv.querySelector('.tc-ps-rf-err'); if (errEl) { errEl.style.display = 'block'; errEl.classList.remove('_tc-shake'); void errEl.offsetWidth; errEl.classList.add('_tc-shake'); } return; } var nameInp = fbDiv.querySelector('.tc-ps-rf-name'); var nameVal = nameInp ? nameInp.value.trim() : ''; var psRfNameErr = fbDiv.querySelector('.tc-ps-rf-name-err'); if (!nameVal) { if (psRfNameErr) { psRfNameErr.style.display = 'block'; psRfNameErr.classList.remove('_tc-shake'); void psRfNameErr.offsetWidth; psRfNameErr.classList.add('_tc-shake'); } if (nameInp) nameInp.focus(); return; } if (psRfNameErr) psRfNameErr.style.display = 'none'; var commentVal = textEl.innerText ? textEl.innerText.slice(0, 200) : ''; this.disabled = true; (async function() { try { await fetch('https://script.google.com/macros/s/AKfycbz87razgDl9TWuyBnCr3jfheIJ5SYZIaCPuR5Q4sMpK5JwOqegs-hU7Ezc0UKUU5NBS/exec', { method: 'POST', body: JSON.stringify({ name: nameVal || 'Anonymous', rating: _rfRating, comment: 'PS Reply: ' + commentVal }) }); } catch(err) { console.error(err); } })(); fbDiv.querySelector('.tc-ps-rf-thanks').style.display = 'inline'; fbDiv.querySelector('.tc-ps-rf-btn').style.display = 'none'; fbDiv.querySelector('.tc-ps-rf-err').style.display = 'none'; fbDiv.querySelector('.tc-ps-rf-name').style.display = 'none'; fbDiv.querySelectorAll('.tc-ps-rf-star').forEach(function(s) { s.style.pointerEvents = 'none'; }); if (window.tcShowThankYou) { window.tcShowThankYou({ rating: _rfRating, name: nameVal, redirect: null }); } }, { once: true }); } // MutationObserver: watch for new Plant Soul bot messages being added function _watchForPsReplies() { var body = document.getElementById('tc-chat-body'); if (!body) return; var obs = new MutationObserver(function(mutations) { if (!document.body.classList.contains('ps-active')) return; mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (!node || node.nodeType !== 1) return; // Bot message bubble added if (node.classList && node.classList.contains('tc-chat-message-bot')) { // Wait a moment for inner content to render setTimeout(function() { _attachPsReplyFb(node); }, 600); } }); }); }); obs.observe(body, { childList: true }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', _watchForPsReplies); } else { _watchForPsReplies(); } // Also initialise the product card feedback handler via delegation document.addEventListener('click', function(e) { var star = e.target.closest('.tc-pc-fb-star'); if (star) { e.stopPropagation(); var card = star.closest('.tc-pc-fb'); if (!card) return; var rating = parseInt(star.dataset.v); card._pcRating = rating; card.querySelectorAll('.tc-pc-fb-star').forEach(function(s) { s.style.color = parseInt(s.dataset.v) <= rating ? '#f59e0b' : '#d1d5db'; }); var errEl = card.querySelector('.tc-pc-fb-err'); if (errEl) errEl.style.display = 'none'; return; } var pcBtn = e.target.closest('.tc-pc-fb-btn'); if (pcBtn) { e.stopPropagation(); var card = pcBtn.closest('.tc-pc-fb'); if (!card) return; var rating = card._pcRating || 0; if (!rating) { var errEl = card.querySelector('.tc-pc-fb-err'); if (errEl) errEl.style.display = 'block'; return; } var nameInp = card.querySelector('.tc-pc-fb-name'); var nameVal = nameInp ? nameInp.value.trim() : ''; var nameErrEl = card.querySelector('.tc-pc-fb-name-err'); if (!nameVal) { if (nameErrEl) nameErrEl.style.display = 'block'; if (nameInp) nameInp.focus(); return; } if (nameErrEl) nameErrEl.style.display = 'none'; var productTitle = (card.closest('.tc-product-card') || {}).querySelector && (card.closest('.tc-product-card').querySelector('.tc-product-title') || {}).innerText || ''; pcBtn.disabled = true; (async function() { try { await fetch('https://script.google.com/macros/s/AKfycbz87razgDl9TWuyBnCr3jfheIJ5SYZIaCPuR5Q4sMpK5JwOqegs-hU7Ezc0UKUU5NBS/exec', { method: 'POST', body: JSON.stringify({ name: nameVal || 'Anonymous', rating: rating, comment: 'Product: ' + productTitle }) }); } catch(err) { console.error(err); } })(); // Hide the card feedback UI card.querySelector('.tc-pc-fb-thanks').style.display = 'block'; pcBtn.style.display = 'none'; if (card.querySelector('.tc-pc-fb-name')) card.querySelector('.tc-pc-fb-name').style.display = 'none'; card.querySelectorAll('.tc-pc-fb-star').forEach(function(s) { s.style.pointerEvents = 'none'; }); // Store rating/name for bot reply if (typeof psData !== 'undefined') { psData.feedbackRating = rating; psData.feedbackName = nameVal; } // Show user bubble then bot thank-you reply if (typeof psUserMsg === 'function') psUserMsg('Feedback submitted ✨'); if (typeof psDoThankYouForFeedback === 'function') { psDoThankYouForFeedback(); } else if (window.tcShowThankYou) { window.tcShowThankYou({ rating: rating, name: nameVal, redirect: null }); } } }, true); })(); /* =========================================================================== */ /* TINY CACTII — THANK YOU OVERLAY (botanical luxury, full-bleed) */ /* =========================================================================== */ (function() { 'use strict'; /* ── inject styles ── */ var _tyCSS = document.createElement('style'); _tyCSS.textContent = ` @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,700;1,400&family=DM+Sans:wght@300;400;500&display=swap'); #tc-ty-overlay { position: fixed; inset: 0; z-index: 99999999; display: flex; align-items: center; justify-content: center; background: transparent; pointer-events: none; opacity: 0; } #tc-ty-overlay.tc-ty-show { pointer-events: all; opacity: 1; } /* ── liquid backdrop ── */ #tc-ty-backdrop { position: absolute; inset: 0; background: radial-gradient(ellipse 120% 110% at 20% 0%, #0b2a14 0%, #061a0c 55%, #010a04 100%); opacity: 0; transition: opacity 0.55s cubic-bezier(0.22,1,0.36,1); } #tc-ty-overlay.tc-ty-show #tc-ty-backdrop { opacity: 1; } /* ── noise grain ── */ #tc-ty-backdrop::after { content: ''; position: absolute; inset: 0; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E"); opacity: 0.35; mix-blend-mode: overlay; } /* ── floating leaf particles ── */ .tc-ty-leaf { position: absolute; font-size: 22px; opacity: 0; pointer-events: none; animation: tc-leaf-drift 4s ease-in-out forwards; } @keyframes tc-leaf-drift { 0% { opacity: 0; transform: translateY(60px) rotate(0deg) scale(0.6); } 15% { opacity: 0.55; } 80% { opacity: 0.3; } 100% { opacity: 0; transform: translateY(-180px) rotate(var(--rot, 40deg)) scale(1.1); } } /* ── petal burst ring ── */ #tc-ty-ring { position: absolute; width: 340px; height: 340px; border-radius: 50%; border: 1.5px solid rgba(134,239,172,0.12); left: 50%; top: 50%; transform: translate(-50%,-50%) scale(0); transition: transform 0.9s cubic-bezier(0.34,1.56,0.64,1) 0.3s, opacity 0.9s ease 0.3s; opacity: 0; } #tc-ty-ring-2 { position: absolute; width: 520px; height: 520px; border-radius: 50%; border: 1px solid rgba(134,239,172,0.06); left: 50%; top: 50%; transform: translate(-50%,-50%) scale(0); transition: transform 1.1s cubic-bezier(0.34,1.56,0.64,1) 0.5s, opacity 1.1s ease 0.5s; opacity: 0; } #tc-ty-overlay.tc-ty-show #tc-ty-ring, #tc-ty-overlay.tc-ty-show #tc-ty-ring-2 { transform: translate(-50%,-50%) scale(1); opacity: 1; } /* ── card ── */ #tc-ty-card { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; text-align: center; padding: 0 28px; transform: translateY(40px) scale(0.92); opacity: 0; transition: transform 0.75s cubic-bezier(0.34,1.56,0.64,1) 0.18s, opacity 0.6s ease 0.18s; max-width: 380px; } #tc-ty-overlay.tc-ty-show #tc-ty-card { transform: translateY(0) scale(1); opacity: 1; } /* ── icon orb ── */ #tc-ty-orb { width: 96px; height: 96px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #4ade80, #16a34a 60%, #052e16); box-shadow: 0 0 0 16px rgba(74,222,128,0.08), 0 0 0 32px rgba(74,222,128,0.04), 0 20px 60px rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; font-size: 40px; margin-bottom: 32px; animation: tc-orb-pulse 2.4s ease-in-out infinite 0.8s; flex-shrink: 0; } @keyframes tc-orb-pulse { 0%,100% { box-shadow: 0 0 0 16px rgba(74,222,128,0.08), 0 0 0 32px rgba(74,222,128,0.04), 0 20px 60px rgba(0,0,0,0.5); } 50% { box-shadow: 0 0 0 22px rgba(74,222,128,0.13), 0 0 0 44px rgba(74,222,128,0.06), 0 20px 60px rgba(0,0,0,0.5); } } /* ── checkmark SVG ── */ #tc-ty-check { width: 48px; height: 48px; stroke-dasharray: 80; stroke-dashoffset: 80; transition: stroke-dashoffset 0.7s cubic-bezier(0.22,1,0.36,1) 0.55s; } #tc-ty-overlay.tc-ty-show #tc-ty-check { stroke-dashoffset: 0; } /* ── text ── */ #tc-ty-headline { font-family: 'Playfair Display', Georgia, serif; font-size: clamp(26px, 5vw, 34px); font-weight: 700; color: #f0fdf4; line-height: 1.15; letter-spacing: -0.5px; margin: 0 0 10px; opacity: 0; transform: translateY(12px); transition: opacity 0.6s ease 0.45s, transform 0.6s ease 0.45s; } #tc-ty-overlay.tc-ty-show #tc-ty-headline { opacity: 1; transform: translateY(0); } #tc-ty-sub { font-family: 'DM Sans', sans-serif; font-size: 14px; font-weight: 300; color: rgba(187,247,208,0.7); line-height: 1.6; letter-spacing: 0.2px; margin: 0 0 28px; opacity: 0; transform: translateY(10px); transition: opacity 0.6s ease 0.6s, transform 0.6s ease 0.6s; } #tc-ty-overlay.tc-ty-show #tc-ty-sub { opacity: 1; transform: translateY(0); } /* ── star row ── */ #tc-ty-stars { display: flex; gap: 6px; margin-bottom: 28px; opacity: 0; transition: opacity 0.6s ease 0.7s; } #tc-ty-overlay.tc-ty-show #tc-ty-stars { opacity: 1; } .tc-ty-star { font-size: 22px; color: #fbbf24; display: inline-block; transform: scale(0) rotate(-30deg); animation: none; } .tc-ty-star.pop { animation: tc-star-pop 0.45s cubic-bezier(0.34,1.56,0.64,1) forwards; } @keyframes tc-star-pop { 0% { transform: scale(0) rotate(-30deg); } 100% { transform: scale(1) rotate(0deg); } } /* ── redirect bar ── */ #tc-ty-bar-wrap { width: 200px; height: 3px; background: rgba(255,255,255,0.08); border-radius: 99px; overflow: hidden; opacity: 0; transition: opacity 0.4s ease 0.9s; } #tc-ty-overlay.tc-ty-show #tc-ty-bar-wrap { opacity: 1; } #tc-ty-bar { height: 100%; width: 0%; background: linear-gradient(90deg, #4ade80, #86efac); border-radius: 99px; transition: width 2.4s linear 1s; } #tc-ty-overlay.tc-ty-show #tc-ty-bar { width: 100%; } #tc-ty-redirect-txt { font-family: 'DM Sans', sans-serif; font-size: 11px; font-weight: 400; color: rgba(187,247,208,0.4); letter-spacing: 0.8px; text-transform: uppercase; margin-top: 10px; opacity: 0; transition: opacity 0.4s ease 1s; } #tc-ty-overlay.tc-ty-show #tc-ty-redirect-txt { opacity: 1; } /* ── diagonal decorative lines ── */ .tc-ty-deco-line { position: absolute; height: 1px; background: linear-gradient(90deg, transparent, rgba(74,222,128,0.15), transparent); pointer-events: none; } /* ── confetti dots ── */ .tc-ty-dot { position: absolute; border-radius: 50%; opacity: 0; animation: tc-dot-burst 1s ease-out forwards; } @keyframes tc-dot-burst { 0% { opacity: 0.9; transform: translate(0,0) scale(1); } 100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(0.3); } } `; document.head.appendChild(_tyCSS); /* ── helper: spawn leaf particles ── */ function _spawnLeaves(overlay) { var emojis = ['🌿','🍃','✨','🌱','💚','🌸','🪴','🌺']; for (var i = 0; i < 14; i++) { (function(idx) { setTimeout(function() { var leaf = document.createElement('div'); leaf.className = 'tc-ty-leaf'; leaf.textContent = emojis[idx % emojis.length]; var x = 8 + Math.random() * 84; var rot = (Math.random() - 0.5) * 120; leaf.style.cssText = 'left:' + x + '%;bottom:8%;--rot:' + rot + 'deg;animation-delay:' + (idx * 0.18) + 's;animation-duration:' + (3.2 + Math.random() * 1.8) + 's;font-size:' + (14 + Math.random() * 18) + 'px;'; overlay.appendChild(leaf); setTimeout(function() { try { overlay.removeChild(leaf); } catch(e){} }, 6000); }, idx * 160); })(i); } } /* ── helper: spawn confetti dots ── */ function _spawnDots(card) { var colors = ['#4ade80','#86efac','#fbbf24','#f9a8d4','#a5f3fc','#c4b5fd']; for (var i = 0; i < 20; i++) { (function(idx) { setTimeout(function() { var dot = document.createElement('div'); dot.className = 'tc-ty-dot'; var size = 4 + Math.random() * 7; var angle = (idx / 20) * 360; var dist = 80 + Math.random() * 80; var dx = Math.cos(angle * Math.PI / 180) * dist + 'px'; var dy = Math.sin(angle * Math.PI / 180) * dist + 'px'; dot.style.cssText = 'width:' + size + 'px;height:' + size + 'px;background:' + colors[idx % colors.length] + ';left:50%;top:30%;margin-left:-' + (size/2) + 'px;margin-top:-' + (size/2) + 'px;--dx:' + dx + ';--dy:' + dy + ';animation-delay:' + (0.5 + idx * 0.04) + 's;animation-duration:' + (0.8 + Math.random() * 0.5) + 's;'; card.appendChild(dot); setTimeout(function() { try { card.removeChild(dot); } catch(e){} }, 3000); }, idx * 30); })(i); } } /* ── helper: animate stars with stagger ── */ function _animateStars(count) { var stars = document.querySelectorAll('.tc-ty-star'); stars.forEach(function(s, i) { var filled = i < count; s.textContent = filled ? '★' : '☆'; s.style.color = filled ? '#fbbf24' : 'rgba(255,255,255,0.2)'; setTimeout(function() { s.classList.add('pop'); }, 750 + i * 90); }); } /* ── MAIN: show the overlay, then redirect ── */ window.tcShowThankYou = function(opts) { /* opts = { rating : 1-5 (int), name : string, redirect : 'https://...' | null (null = no redirect, just close), onDone : function called after redirect or close (optional) } */ opts = opts || {}; var rating = opts.rating || 5; var name = opts.name || ''; var redirect = opts.redirect !== undefined ? opts.redirect : 'https://www.tinycactii.shop/'; var onDone = opts.onDone || null; // Remove any existing overlay var existing = document.getElementById('tc-ty-overlay'); if (existing) existing.parentNode.removeChild(existing); // Pick a warm message var headlines = [ 'You're a Green Star!', 'Thank You So Much!', 'Roots & Gratitude!', 'Blooming Grateful!', 'Your Feedback Matters!', 'You Made Our Day!' ]; var subs = [ 'Every word you share helps Tiny Cactii grow a little greener.', 'Your thoughts are the sunlight that helps us bloom better.', 'Thank you' + (name ? ', ' + name : '') + ' — we cherish every review.', 'We're rooted in gratitude for feedback like yours.', 'Small words, big impact. Thank you for caring.', name ? (name + ', you're officially our favourite plant parent 🌿') : 'You're officially our favourite plant parent 🌿' ]; var pickedHeadline = (typeof _ps6060pick === 'function') ? _ps6060pick(headlines, 'ty_headline') : headlines[Math.floor(Math.random() * headlines.length)]; var pickedSub = (typeof _ps6060pick === 'function') ? _ps6060pick(subs, 'ty_sub') : subs[Math.floor(Math.random() * subs.length)]; // Build overlay var ov = document.createElement('div'); ov.id = 'tc-ty-overlay'; ov.innerHTML = '
' + '
' + '
' + '
' + '
' + '
' + '
' + '' + '' + '' + '
' + '

' + pickedHeadline + '

' + '

' + pickedSub + '

' + '
' + '★★★★★' + '
' + (redirect ? '
' + '
Heading to our shop…
' : '
') + '
'; document.body.appendChild(ov); // Trigger show on next frame requestAnimationFrame(function() { requestAnimationFrame(function() { ov.classList.add('tc-ty-show'); _spawnLeaves(ov); _spawnDots(document.getElementById('tc-ty-card')); _animateStars(rating); }); }); // Redirect or close after 3.5s var _delay = redirect ? 3500 : 2800; setTimeout(function() { ov.style.transition = 'opacity 0.5s ease'; ov.style.opacity = '0'; setTimeout(function() { try { ov.parentNode.removeChild(ov); } catch(e) {} if (redirect) { try { (window.top || window).location.replace(redirect); } catch(e) { window.location.href = redirect; } } if (onDone) onDone(); }, 500); }, _delay); }; })(); /* TINY CACTII — PAHI SECURITY PROTECTION / DEV TOOLS / INSPECT RESTRICTION */ /* ========================================================================= */ /* =========================================================================== */ /* CHATBOT UI LOCK MANAGER (PREVENTS USER INTERACTION WHILE BOT IS RESPONDING) */ /* =========================================================================== */ /* ======================================================================= */ /* END OF SCRIPT ABOVE ⬆️ */ /* ======================================================================= */ /* ========================================================================= */ /* Fn key + F3 = FIND */ /* Ctrl + U = UPPERCASE */ /* Ctrl + shift + U = LOWERCASE */ /* ========================================================================= */ // ======================================================================= // SOCIAL ICONS DESIGNS AND COLOUR BELOW — floating side social-icon bar // removed per request; the inline "Connect with us" social row used // inside chat messages elsewhere is untouched. // =======================================================================
Rate Your Match ✨
Your Name *
Please enter your name to continue.
Rating *
★ ★ ★ ★ ★
Please select a rating to continue.
Message (optional)
/* ========================================================================= */ /* DR. SPROUT CHATBOT CODE */ /* ========================================================================= */ Dr. Sprout · Complete Botanical MD | 143+ Plants
Dr. Sprout

🌱 Dr. Sprout · B.Med

Complete care & diagnosis for 143+ species

🌿 I am Dr. Sprout, your board-certified botanical physician.
I have detailed clinical knowledge of over 143 cultivated species and their care needs.

✏️ Which plant would you like me to look up? Type its name.

Only required for issues related to an existing order.

Ticket Raised!

Our support team will respond to your ticket within 24-48 hours.

Please keep an eye on your email inbox for updates.