/* ================================================================
   components-elvis.jsx — Elvis AI orb + full chat quote system.
   Loaded BEFORE app.jsx. Exposes: ElvisAv, ElvisChat, AmbientElvisOrb
   via window so app.jsx can reference them across Babel script scopes.
   ================================================================ */

/* ── Inject all animation CSS once ── */
if (!document.getElementById('ax-elvis-css')) {
  const s = document.createElement('style');
  s.id = 'ax-elvis-css';
  s.textContent = `
.elvis-chat-overlay{height:100vh;height:100dvh}
@keyframes orbRingPulse{0%{transform:scale(0.9);opacity:0.55}100%{transform:scale(1.4);opacity:0}}
@media(prefers-reduced-motion:reduce){.ax-orb-ring{animation:none!important}}
@keyframes elvisArrowBounce{0%,100%{transform:translateY(0);opacity:.85}50%{transform:translateY(6px);opacity:1}}
/* Glass orb */
.ag-orb{position:relative;width:72px;height:72px;border-radius:50%;transform:rotateX(var(--tilt-y)) rotateY(var(--tilt-x));transition:transform 160ms linear;animation:ag-drift 5.2s ease-in-out infinite;box-shadow:0 10px 24px -8px rgba(80,90,100,.38)}
.ag-frost,.ag-aura,.ag-glow,.ag-breath,.ag-shine,.ag-seam{position:absolute;inset:0;border-radius:50%}
.ag-frost{background:radial-gradient(130% 90% at 50% 35%,rgba(244,246,248,.34),rgba(207,216,224,.08) 50%,rgba(203,212,220,.18) 82%),radial-gradient(80% 80% at 50% 50%,rgba(221,228,234,.38),rgba(205,213,220,.3));border:1px solid rgba(245,247,249,.92);backdrop-filter:blur(2px)}
.ag-frost::before,.ag-frost::after{content:"";position:absolute;border-radius:50%}
.ag-frost::before{inset:4%;border:1px solid rgba(255,255,255,.3);filter:blur(.4px)}
.ag-frost::after{inset:0;box-shadow:inset 0 0 20px rgba(255,255,255,.28),inset 0 -8px 20px rgba(152,168,183,.18)}
.ag-aura{filter:blur(10px);mix-blend-mode:screen;opacity:.78}
.ag-aura-1{width:68%;height:52%;left:9%;top:30%;background:radial-gradient(circle at 48% 55%,rgba(79,184,255,1),rgba(79,184,255,.55) 58%,rgba(79,184,255,0) 84%);animation:ag-auraOne 7.2s ease-in-out infinite}
.ag-aura-2{width:60%;height:44%;left:45%;top:33%;background:radial-gradient(circle at 42% 52%,rgba(255,154,50,1),rgba(255,154,50,.52) 58%,rgba(255,154,50,0) 84%);animation:ag-auraTwo 8.1s ease-in-out infinite}
.ag-aura-3{width:58%;height:48%;left:23%;top:12%;background:radial-gradient(circle at 50% 50%,rgba(156,116,255,.96),rgba(156,116,255,.5) 58%,rgba(156,116,255,0) 84%);animation:ag-auraThree 9.4s ease-in-out infinite}
.ag-glow{filter:blur(8px);mix-blend-mode:screen;opacity:1}
.ag-glow-blue{width:41%;height:29%;left:16%;top:50%;transform:rotate(-10deg);background:radial-gradient(circle at 45% 50%,rgba(79,184,255,1),rgba(79,184,255,.82) 55%,rgba(79,184,255,.1) 80%);animation:ag-pulseBlue 4.8s ease-in-out infinite}
.ag-glow-orange{width:31%;height:24%;left:62%;top:44%;transform:rotate(-12deg);background:radial-gradient(circle at 48% 48%,rgba(255,154,50,1),rgba(255,154,50,.8) 56%,rgba(255,154,50,.1) 80%);animation:ag-pulseOrange 5.4s ease-in-out infinite reverse}
.ag-glow-purple{width:35%;height:27%;left:36%;top:18%;transform:rotate(8deg);background:radial-gradient(circle at 50% 48%,rgba(156,116,255,1),rgba(156,116,255,.78) 56%,rgba(156,116,255,.12) 80%);animation:ag-pulsePurple 6.2s ease-in-out infinite}
.ag-breath{inset:-2%;border:1.4px solid rgba(255,255,255,.35);filter:blur(.2px);animation:ag-breathe 3.4s ease-in-out infinite}
.ag-seam{inset:0;overflow:visible;border-radius:50%}
.ag-seam path{fill:none;stroke-linecap:round}
.ag-seam-shadow{stroke:rgba(101,116,127,.4);stroke-width:1.6;filter:blur(1.3px)}
.ag-seam-main{stroke:rgba(79,93,105,.82);stroke-width:.48;stroke-dasharray:92;animation:ag-seamFlow 6.5s linear infinite}
.ag-shine{pointer-events:none;background:radial-gradient(45% 34% at 38% 23%,rgba(255,255,255,.5),rgba(255,255,255,.08) 45%,rgba(255,255,255,0) 70%),radial-gradient(58% 58% at 50% 73%,rgba(170,187,201,.2),rgba(170,187,201,.06) 45%,rgba(170,187,201,0) 78%)}
@keyframes ag-drift{0%,100%{transform:translateY(0) scale(.972) rotateX(var(--tilt-y)) rotateY(var(--tilt-x))}50%{transform:translateY(-4px) scale(1.03) rotateX(calc(var(--tilt-y) + .4deg)) rotateY(calc(var(--tilt-x) - .5deg))}}
@keyframes ag-pulseBlue{0%,100%{opacity:.8;transform:rotate(-10deg) translate(0,0) scale(1.02)}50%{opacity:1;transform:rotate(-10deg) translate(3px,-1px) scale(1.14)}}
@keyframes ag-pulseOrange{0%,100%{opacity:.82;transform:rotate(-12deg) translate(0,0) scale(1)}50%{opacity:.95;transform:rotate(-12deg) translate(-2px,1px) scale(1.12)}}
@keyframes ag-pulsePurple{0%,100%{opacity:.74;transform:rotate(8deg) translate(0,0) scale(1)}50%{opacity:.93;transform:rotate(8deg) translate(1px,-2px) scale(1.1)}}
@keyframes ag-auraOne{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(4px,-3px) scale(1.07)}}
@keyframes ag-auraTwo{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(-5px,2px) scale(1.09)}}
@keyframes ag-auraThree{0%,100%{transform:translate(0,0) scale(.98)}50%{transform:translate(2px,3px) scale(1.08)}}
@keyframes ag-breathe{0%,100%{opacity:.38;transform:scale(.94)}50%{opacity:.9;transform:scale(1.08)}}
@keyframes ag-seamFlow{0%{stroke-dashoffset:92}100%{stroke-dashoffset:0}}
@keyframes ag-pop{0%{transform:scale(0);opacity:0}65%{transform:scale(1.1);opacity:1}100%{transform:scale(1);opacity:1}}
@keyframes ag-ring{0%{transform:scale(.85);opacity:.7}100%{transform:scale(1.65);opacity:0}}
@keyframes ag-label-in{0%{opacity:0;transform:translateX(12px)}100%{opacity:1;transform:translateX(0)}}
@keyframes ag-label-out{0%{opacity:1;transform:translateX(0)}100%{opacity:0;transform:translateX(12px)}}
@media(prefers-reduced-motion:reduce){.ag-orb,.ag-glow,.ag-aura,.ag-breath,.ag-seam-main{animation:none!important}}
`;
  document.head.appendChild(s);
}

/* ── Local icon components (private to this file) ── */
const _Svg = ({ children, size = 18, ...p }) => (
  <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24"
    fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
    {children}
  </svg>
);
const _XIcon = ({ size = 18 }) => <_Svg size={size}><path d="M18 6 6 18"/><path d="m6 6 12 12"/></_Svg>;
const _ArrowRight = ({ size = 18 }) => <_Svg size={size}><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></_Svg>;
const _WA = ({ size = 16 }) => (
  <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="currentColor">
    <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a12.8 12.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413z"/>
  </svg>
);

/* ── Data ── */
const ALL_PACKAGES = {
  "1": { name: "Basic Website Package",    price: 2499,  desc: "Up to 5 pages, mobile-responsive, contact form, basic SEO" },
  "2": { name: "Business Website Package", price: 5999,  desc: "Up to 10 pages, blog, social integration, Google Analytics" },
  "3": { name: "Premium Website Package",  price: 9999,  desc: "Unlimited pages, e-commerce ready, advanced animations, priority support" },
  "4": { name: "Custom Quote",             price: 0,     desc: "Tell me your needs and I'll build a tailored estimate" }
};

const ALL_ADDONS = {
  "1":  { name: "Website Hosting (Monthly)",                    price: 100,  cat: "Essentials" },
  "2":  { name: "Website Hosting (Annual — 1st month free)",    price: 850,  cat: "Essentials" },
  "3":  { name: "Monthly Maintenance Plan",                     price: 250,  cat: "Essentials" },
  "4":  { name: "Content Update",                               price: 150,  cat: "Essentials" },
  "5":  { name: "Troubleshooting / Bug Fix",                    price: 350,  cat: "Essentials" },
  "6":  { name: "Extra Page Design",                            price: 350,  cat: "Essentials" },
  "7":  { name: "Payment Gateway (PayFast)",                    price: 1250, cat: "Integrations" },
  "8":  { name: "Booking System",                               price: 1250, cat: "Integrations" },
  "9":  { name: "WhatsApp Chat Button",                         price: 200,  cat: "Integrations" },
  "10": { name: "Business Email Setup",                         price: 350,  cat: "Integrations" },
  "11": { name: "Advanced Contact Form",                        price: 450,  cat: "Integrations" },
  "12": { name: "Logo Design & Branding Package",               price: 850,  cat: "Design" },
  "13": { name: "Custom Web Animations",                        price: 450,  cat: "Design" },
  "14": { name: "Social Media Identity Design",                 price: 350,  cat: "Design" },
  "15": { name: "Digital Business Cards",                       price: 150,  cat: "Design" },
  "20": { name: "Social Media Content Package (20+ Posts/mo)",  price: 750,  cat: "Social Media" },
  "16": { name: "Advanced Local SEO Setup",                     price: 1800, cat: "SEO" },
  "17": { name: "Google Business Profile Optimization",         price: 650,  cat: "SEO" },
  "18": { name: "Conversion Rate Optimization (CRO)",          price: 900,  cat: "SEO" },
  "19": { name: "Global SEO Strategy",                          price: 2500, cat: "SEO" },
};

const ADDON_CAT_META = {
  'Essentials':   { gradient: 'linear-gradient(135deg,#FF5A00 0%,#FF8C42 60%,#FFB07A 100%)', img: 'images/addon-cards/essentials.png' },
  'Integrations': { gradient: 'linear-gradient(135deg,#0284c7 0%,#38bdf8 60%,#7dd3fc 100%)', img: 'images/addon-cards/integrations.png' },
  'Design':       { gradient: 'linear-gradient(135deg,#7c3aed 0%,#a78bfa 60%,#ddd6fe 100%)', img: 'images/addon-cards/design.png' },
  'Social Media': { gradient: 'linear-gradient(135deg,#db2777 0%,#f472b6 60%,#fbcfe8 100%)', img: 'images/addon-cards/social.png' },
  'SEO':          { gradient: 'linear-gradient(135deg,#16a34a 0%,#4ade80 60%,#bbf7d0 100%)', img: 'images/addon-cards/seo.png' },
};

const ADDON_DESCS = {
  '1':'Reliable hosting, 99.9% uptime','2':'Full year — 1st month free','3':'Updates, security & support',
  '4':'Fresh text, images & pages','5':'Fast fix when things break','6':'Add another page to your site',
  '7':'Accept card payments via PayFast','8':'Let clients book appointments','9':'Click-to-chat on your site',
  '10':'name@yourdomain.co.za setup','11':'Advanced forms + file uploads','12':'Logo, colours & typography',
  '13':'Scroll & hover micro-animations','14':'Profile headers & story kits','15':'NFC-ready digital card',
  '20':'20+ posts/mo + cover design','16':'Rank on Google Maps & Search','17':'Optimised Google Business profile',
  '18':'Turn more visitors into clients','19':'International search strategy',
};

const PORTAL_TIERS = {
  "1": { name: "Cloud-Based Point of Sale (POS) System", price: 12500 },
  "0": { name: "No POS", price: 0 }
};

/* ── Local NLP fallback ── */
const LOCAL_KB = [
  { topics:['price','cost','how much','rate','packages','what do you offer','services'],
    reply:`Website Packages:\nBasic — R2,499 | Business — R5,999 | Premium — R9,999\n\nCloud POS System — R12,500 (once-off)\nApp Development — Custom (WhatsApp us)\nSocial Media Content — R750/month\nAdd-ons from R150\n\nAll packages include free domain, SSL & mobile-first design. Which interests you?`,
    chips:[{label:'Get a Quote',value:'1'},{label:'POS System',value:'2'},{label:'Add-Ons',value:'3'}] },
  { topics:['basic','starter','small business','cheapest','affordable'],
    reply:`Basic Package — R2,499\n\n- 1-5 custom-coded pages\n- Mobile-responsive design\n- Contact form + basic SEO\n- Free .co.za domain (1 year)\n- SSL certificate\n- Google Analytics\n- 2 revision rounds`,
    chips:[{label:'Get Basic Quote',value:'1'}] },
  { topics:['business','ecommerce','e-commerce','online shop','growing'],
    reply:`Business Package — R5,999\n\n- 6-10 custom-coded pages\n- E-commerce ready\n- Blog / news section\n- WhatsApp chat button\n- Advanced SEO + 1 year free hosting`,
    chips:[{label:'Get Business Quote',value:'1'}] },
  { topics:['premium','enterprise','unlimited','full package'],
    reply:`Premium Package — R9,999\n\n- Unlimited custom pages\n- Full custom design system\n- Priority support\n- API integrations + custom animations\n- 2 years free hosting`,
    chips:[{label:'Get Premium Quote',value:'1'}] },
  { topics:['pos','point of sale','till','inventory','cashier','stock'],
    reply:`Cloud POS System — R12,500 once-off\n\n- Sales & till management\n- Live inventory & stock tracking\n- Staff management & access levels\n- Cloud reporting from any device\n- Setup + training + 3 months support\n\nNo monthly fees!`,
    chips:[{label:'Get POS Quote',value:'2'}] },
  { topics:['timeline','how long','turnaround','delivery','days','weeks'],
    reply:`Typical turnaround:\nBasic: 7-10 business days\nBusiness: 10-14 business days\nPremium: 14-21 business days\n\nTimeline starts once deposit is received.`,
    chips:[{label:'Get a Quote',value:'1'}] },
  { topics:['contact','reach','whatsapp','phone','email'],
    reply:`Reach us directly:\nWhatsApp: 062 379 0118\nEmail: design@axiouscreativestudio.co.za\nSite: axiouscreativestudio.co.za\n\nBusiness hours: Mon-Fri 9am-5pm`,
    chips:[{label:'Get a Quote',value:'1'}] },
  { topics:['about','who are you','axious','team','cape town','rating','stars'],
    reply:`We are Axious Creative Studio!\n\nBased in Cape Town, Western Cape\nServing clients nationwide\n5.0-star rating on Google & Facebook\n40+ custom websites built\n100% custom code — no templates\n\nCustom websites, Cloud POS, App Dev, SEO & more.`,
    chips:[{label:'Get a Quote',value:'1'}] },
  { topics:['payment','pay','deposit','eft','bank transfer','banking'],
    reply:`Payment Options:\nCard via Yoco — secure online payment\nEFT / Bank Transfer\n\n50% deposit to start, balance on launch.\n\nEFT Banking Details:\nBank: Capitec Entrepreneur\nHolder: Axious Creative Studio\nAccount: 248650558\nReference: Your domain name`,
    chips:[{label:'Get a Quote',value:'1'}] },
];

const localElvisNLP = (text) => {
  const lower = text.toLowerCase().trim();
  let best = null; let score = 0;
  for (const entry of LOCAL_KB) {
    let s = 0;
    for (const kw of entry.topics) { if (lower.includes(kw)) s += kw.length; }
    if (s > score) { score = s; best = entry; }
  }
  if (best && score > 0) return { reply: best.reply, chips: best.chips || [] };
  return {
    reply: "I'm not sure about that — but I'd love to help! You can ask me about our packages, pricing, POS systems, timeline, or just tap below to get a quote.",
    chips: [{ label: 'Get a Quote', value: '1' }, { label: 'Contact Us', value: '4' }]
  };
};

/* ── ElvisAv — the glowing orb avatar ── */
const ElvisAv = ({ size = 28, style = {} }) => {
  const s = Number(size);
  const blur = Math.max(2, Math.round(s * 0.11));
  return (
    <div style={{
      width: s, height: s, borderRadius: '50%', flexShrink: 0,
      position: 'relative', overflow: 'hidden',
      background: 'radial-gradient(circle at 50% 35%, #252535, #0e0e1a)',
      boxShadow: `0 0 0 1.5px rgba(156,116,255,0.4), 0 2px ${Math.round(s*0.3)}px rgba(0,0,0,0.35)`,
      ...style
    }}>
      <div style={{position:'absolute',width:'62%',height:'52%',left:'5%',top:'42%',background:'radial-gradient(circle,rgba(79,184,255,0.9),rgba(79,184,255,0) 70%)',filter:`blur(${blur}px)`,mixBlendMode:'screen'}} />
      <div style={{position:'absolute',width:'52%',height:'42%',left:'52%',top:'48%',background:'radial-gradient(circle,rgba(255,154,50,0.85),rgba(255,154,50,0) 70%)',filter:`blur(${blur}px)`,mixBlendMode:'screen'}} />
      <div style={{position:'absolute',width:'56%',height:'46%',left:'22%',top:'5%',background:'radial-gradient(circle,rgba(156,116,255,0.8),rgba(156,116,255,0) 70%)',filter:`blur(${blur}px)`,mixBlendMode:'screen'}} />
      <div style={{position:'absolute',inset:0,background:'radial-gradient(42% 32% at 35% 20%,rgba(255,255,255,0.45),rgba(255,255,255,0) 70%)',borderRadius:'50%'}} />
      <div style={{position:'absolute',inset:0,borderRadius:'50%',border:'1px solid rgba(255,255,255,0.22)'}} />
      <svg style={{position:'absolute',inset:0,width:'100%',height:'100%',overflow:'visible'}} viewBox="0 0 100 100" aria-hidden="true">
        <path d="M18 63 C35 78, 58 48, 79 35" fill="none" stroke="rgba(79,93,105,0.6)" strokeWidth="0.9" strokeLinecap="round" strokeDasharray="60" />
      </svg>
    </div>
  );
};

/* ── ElvisChat — full-page chat + quote flow ── */
const ElvisChat = React.forwardRef(function ElvisChat({ onClose }, ref) {

  const getTimeGreeting = () => {
    const h = new Date().getHours();
    if (h < 12) return 'Good morning';
    if (h < 17) return 'Good afternoon';
    return 'Good evening';
  };

  const initMsg = {
    text: `${getTimeGreeting()}! I'm Elvis — Axious Creative Studio's AI assistant.\n\nI can help you with:\n- Website packages & pricing\n- Cloud POS system info\n- Add-ons (SEO, bookings, payments & more)\n- Get a full quote in under 2 minutes\n\nWhat would you like to know?`,
    sender: 'elvis'
  };

  const [phase, setPhase] = React.useState(0);
  const [messages, setMessages] = React.useState([initMsg]);
  const [quoteData, setQuoteData] = React.useState({
    name:'', email:'', phone:'', address:'', businessType:'',
    description:'', timeline:'', package:'', packagePrice:0,
    selectedAddons:[], portalTier:'', portalPrice:0, paymentMethod:'', eftRef:'',
    flowType:'',
    referredBy:(()=>{ try { return localStorage.getItem('ax_ref')||''; } catch(e){ return ''; } })()
  });
  const [inputValue, setInputValue] = React.useState('');
  const [isTyping, setIsTyping] = React.useState(false);
  const [showPayment, setShowPayment] = React.useState(false);
  const [showWhatsApp, setShowWhatsApp] = React.useState(false);
  const [quoteTotal, setQuoteTotal] = React.useState(0);
  const [quoteRef, setQuoteRef] = React.useState('');
  const [inputDisabled, setInputDisabled] = React.useState(false);
  const [quickReplies, setQuickReplies] = React.useState([]);
  const [selectedAddons, setSelectedAddons] = React.useState(new Set());
  const [showAddonPicker, setShowAddonPicker] = React.useState(false);
  const [showEFTOptions, setShowEFTOptions] = React.useState(false);
  const [showRetryPayment, setShowRetryPayment] = React.useState(false);
  const [aiMessages, setAiMessages] = React.useState([]);

  const chatEndRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const phaseRef = React.useRef(phase);
  const hasSubmittedPartial = React.useRef(false);
  React.useEffect(() => { phaseRef.current = phase; }, [phase]);

  /* Session persistence */
  React.useEffect(() => {
    try {
      const saved = localStorage.getItem('elvis_v3');
      if (saved) {
        const s = JSON.parse(saved);
        if (s.phase !== undefined && s.messages?.length > 1) {
          setMessages(s.messages); setPhase(s.phase);
          setQuoteData(s.quoteData || {}); setQuoteTotal(s.quoteTotal || 0);
          setQuoteRef(s.quoteRef || ''); setInputDisabled(s.inputDisabled || false);
          setQuickReplies([]);
        }
      }
    } catch(e) {}
  }, []);

  React.useEffect(() => {
    try {
      localStorage.setItem('elvis_v3', JSON.stringify({
        messages: messages.slice(-40), phase, quoteData, quoteTotal, quoteRef, inputDisabled
      }));
    } catch(e) {}
  }, [messages, phase, quoteData, quoteTotal, quoteRef, inputDisabled]);

  /* Auto quick-reply menu on first open */
  const hasAutoPrompted = React.useRef(false);
  React.useEffect(() => {
    if (hasAutoPrompted.current) return;
    const saved = (() => { try { return localStorage.getItem('elvis_v3'); } catch(e){ return null; } })();
    const hasSaved = saved && JSON.parse(saved)?.messages?.length > 1;
    if (hasSaved) { hasAutoPrompted.current = true; return; }
    hasAutoPrompted.current = true;
    const t = setTimeout(() => {
      if (phaseRef.current !== 0) return;
      setIsTyping(true);
      setTimeout(() => {
        setIsTyping(false);
        setMessages(prev => [...prev, { text: "Here's what I can help you with:", sender: 'elvis' }]);
        setQuickReplies([
          { label: 'Website Quote', value: '1' },
          { label: 'POS System', value: '2' },
          { label: 'Add-Ons & Extras', value: '3' },
          { label: 'General Enquiry', value: '4' },
        ]);
      }, 700);
    }, 1800);
    return () => clearTimeout(t);
  }, []);

  /* Imperative handle — for external startWithPackage() */
  React.useImperativeHandle(ref, () => ({
    startWithPackage: (pkg) => {
      let price = 0;
      if (pkg.name.includes('Basic')) price = 2499;
      if (pkg.name.includes('Business')) price = 5999;
      if (pkg.name.includes('Premium')) price = 9999;
      localStorage.removeItem('elvis_v3');
      hasSubmittedPartial.current = false;
      setQuoteData(prev => ({ ...prev, package: pkg.name, packagePrice: price }));
      setShowPayment(false); setShowWhatsApp(false); setShowRetryPayment(false);
      setInputDisabled(false); setPhase(100); setQuickReplies([]); setShowAddonPicker(false);
      setMessages([{ text:`${getTimeGreeting()}! I've pre-selected the ${pkg.name} (R${price.toLocaleString()}) — great choice!\n\nWhat's your full name?`, sender:'elvis' }]);
      setInputValue('');
    }
  }));

  React.useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior:'smooth' }); }, [messages, showPayment, showWhatsApp, showAddonPicker, showRetryPayment, quickReplies]);

  const elvis = (text, delay) => {
    const d = delay !== undefined ? delay : Math.min(350 + text.length * 10, 2000);
    setIsTyping(true);
    setTimeout(() => { setIsTyping(false); setMessages(prev => [...prev, { text, sender:'elvis' }]); }, d);
  };
  const user = (text) => setMessages(prev => [...prev, { text, sender:'user' }]);

  const sendToAI = async (userText, resumeAfter = null) => {
    const newMsg = { role: 'user', content: userText };
    const updatedHistory = [...aiMessages, newMsg];
    setAiMessages(updatedHistory);
    setIsTyping(true);
    try {
      const res = await fetch('/api/elvis-chat', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ messages: updatedHistory })
      });
      if (!res.ok) throw new Error('API error');
      const data = await res.json();
      setIsTyping(false);
      const replyText = data.reply || "I'm having a moment — please try again or WhatsApp us at 062 379 0118!";
      setMessages(prev => [...prev, { text: replyText, sender: 'elvis' }]);
      setAiMessages(prev => [...prev, { role: 'assistant', content: replyText }]);
      if (phaseRef.current === 0) {
        if (data.chips?.length > 0) setQuickReplies(data.chips);
        if (data.action?.type === 'start_quote') {
          if (data.action.service === 'pos') setQuoteData(prev => ({ ...prev, portalTier: 'Cloud-Based POS System', portalPrice: 12500 }));
          setTimeout(() => setPhase(100), 150);
        }
      }
      if (resumeAfter) setTimeout(() => setMessages(prev => [...prev, { text: resumeAfter, sender: 'elvis' }]), 600);
    } catch(err) {
      setIsTyping(false);
      const fb = localElvisNLP(userText);
      setMessages(prev => [...prev, { text: fb.reply, sender: 'elvis' }]);
      setAiMessages(prev => [...prev, { role: 'assistant', content: fb.reply }]);
      if (fb.chips.length > 0 && phaseRef.current === 0) setQuickReplies(fb.chips);
      if (resumeAfter) setTimeout(() => setMessages(prev => [...prev, { text: resumeAfter, sender: 'elvis' }]), 700);
    }
  };

  const handleSend = () => {
    const val = inputValue.trim();
    if (!val || inputDisabled) return;
    setInputValue(''); setQuickReplies([]);
    user(val);
    if (phase === 0) { setTimeout(() => sendToAI(val), 300); }
    else { setTimeout(() => processPhase(val), 300); }
  };

  const handleQuickReply = (value, label) => {
    setQuickReplies([]);
    user(label || value);
    if (phase === 0 && !['1','2','3','4'].includes(value)) {
      setTimeout(() => sendToAI(label || value), 300);
    } else {
      setTimeout(() => processPhase(value), 300);
    }
  };

  const confirmAddons = () => {
    const addonsList = Array.from(selectedAddons).map(k => ALL_ADDONS[k]).filter(Boolean);
    setShowAddonPicker(false); setQuickReplies([]);
    user(addonsList.length > 0 ? `${addonsList.length} add-on${addonsList.length>1?'s':''} selected` : 'No add-ons');
    const nd = { ...quoteData, selectedAddons: addonsList };
    setQuoteData(nd); setPhase(7);
    const summary = addonsList.length > 0 ? '\n' + addonsList.map(a => `- ${a.name} — R${a.price.toLocaleString()}`).join('\n') + '\n\n' : ' ';
    elvis(`Got it!${addonsList.length > 0 ? summary : ' No add-ons — '}Do you also need our Cloud POS System? (R12,500 once-off)`, 900);
    setTimeout(() => setQuickReplies([
      {label:'Yes — Cloud POS (R12,500)', value:'1'},
      {label:'No thanks, website only', value:'0'},
    ]), 1000 + Math.min(350 + 120 * 10, 2000));
  };

  const sendPartialLead = async (data) => {
    if (hasSubmittedPartial.current) return;
    hasSubmittedPartial.current = true;
    try {
      await fetch('/api/quote-request', {
        method:'POST', headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ quoteData: data, total:0, deposit:0, quoteRef:'LEAD-'+Date.now(), partial:true, referredBy: data.referredBy||'' })
      });
    } catch(e) {}
  };

  const isValidEmail = v => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.trim());
  const isValidPhone = v => /^(\+?27|0)[6-8][0-9]{8}$/.test(v.replace(/[\s\-()+]/g,''));

  const handleRestart = () => {
    localStorage.removeItem('elvis_v3');
    hasSubmittedPartial.current = false;
    setPhase(0); setMessages([initMsg]);
    setQuoteData({name:'',email:'',phone:'',address:'',businessType:'',description:'',timeline:'',package:'',packagePrice:0,selectedAddons:[],portalTier:'',portalPrice:0,paymentMethod:'',eftRef:'',flowType:'',referredBy:(()=>{try{return localStorage.getItem('ax_ref')||'';}catch(e){return '';}})()});
    setInputValue(''); setIsTyping(false);
    setShowPayment(false); setShowWhatsApp(false); setShowEFTOptions(false); setShowRetryPayment(false);
    setQuoteTotal(0); setQuoteRef(''); setInputDisabled(false); setAiMessages([]);
    setSelectedAddons(new Set()); setShowAddonPicker(false); setQuickReplies([]);
  };

  const processPhase = async (reply) => {
    let nd = { ...quoteData };
    const r = reply.trim();
    const lower = r.toLowerCase();

    /* Off-topic interception inside structured flow */
    if (phase !== 0 && phase !== 9) {
      const isQ = r.includes('?') || ['what ','how ','when ','where ','why ','can you','do you','is there','tell me','explain','help me'].some(k=>lower.includes(k));
      const isLong = phase !== 5 && r.split(' ').length > 5 && ['want','need','know','about','service','package','price','cost','your','help','website'].some(k=>lower.includes(k));
      if (isQ || isLong) {
        const phaseQs = {100:"Happy to help! Now, what's your full name?",1:"Got it! Your email for the quote?",2:"Appreciated! Your WhatsApp / phone number?",33:"Good to know! What city or area are you based in?",3:"Great info! Which package are you leaning toward?",4:"Useful! What type of business do you run?",5:"Noted! Tell me about your business and website goals.",8:"Happy to help! What's your preferred project timeline?"};
        sendToAI(r, phaseQs[phase] || null);
        return;
      }
    }

    switch (phase) {
      case 0: {
        const isWeb = r==='1'||['website','web ','site','online','build','quote','page'].some(k=>lower.includes(k));
        const isPOS = r==='2'||['pos','point of sale','till','cashier','stock','inventory','retail'].some(k=>lower.includes(k));
        const isAddon = r==='3'||['add-on','addon','extra','hosting','seo','chatbot','logo','booking'].some(k=>lower.includes(k));
        const isGeneral = r==='4'||['contact us','reach you','phone number','email address','call you','speak to someone'].some(k=>lower.includes(k));
        if (isWeb) {
          nd.flowType='website'; setQuoteData(nd); setPhase(100);
          elvis(`Great choice! Let's build your website quote.\n\nFirst, what's your full name?`);
        } else if (isPOS) {
          nd.portalTier='Cloud-Based POS System'; nd.portalPrice=12500; nd.flowType='pos'; setQuoteData(nd); setPhase(100);
          elvis(`Our Cloud POS System (R12,500 once-off) is a complete business solution — inventory, sales, staff & reporting in one place.\n\nLet's build your quote. What's your full name?`);
        } else if (isAddon) {
          nd.flowType='addon'; setQuoteData(nd); setPhase(100);
          elvis(`Let's build a custom add-ons quote for you. What's your full name?`);
        } else if (isGeneral) {
          elvis(`Here's how to reach us directly:\n\nWhatsApp: 062 379 0118\nEmail: design@axiouscreativestudio.co.za\nSite: axiouscreativestudio.co.za\n\nOr tap below to start a quote:`);
          setTimeout(() => setQuickReplies([{label:'Get a Website Quote', value:'1'}]), 1500);
        } else {
          sendToAI(r);
        }
        return;
      }
      case 100:
        nd.name=r; setQuoteData(nd); setPhase(1);
        elvis(`Nice to meet you, ${r}!\n\nWhat's the best email address for you?`);
        return;
      case 1:
        if (!isValidEmail(r)) { elvis(`That doesn't look like a valid email. Could you double-check? `); return; }
        nd.email=r; setQuoteData(nd); setPhase(2);
        elvis(`Got it. And your WhatsApp / phone number?`);
        return;
      case 2: {
        if (!isValidPhone(r)) { elvis(`That doesn't look like a valid SA number (e.g. 0812345678). Please check and try again.`); return; }
        nd.phone=r; setQuoteData(nd);
        sendPartialLead(nd);
        setPhase(33);
        elvis(`Perfect! What city or area are you based in?`);
        setTimeout(() => setQuickReplies([
          {label:'Cape Town',value:'Cape Town'},{label:'Johannesburg',value:'Johannesburg'},
          {label:'Pretoria',value:'Pretoria'},{label:'Durban',value:'Durban'},
          {label:'Gqeberha',value:'Gqeberha'},{label:'George',value:'George'},
        ]), 1000);
        return;
      }
      case 33:
        nd.address=r; setQuoteData(nd);
        const isWebFlow = !nd.flowType || nd.flowType==='website';
        if (isWebFlow) {
          setPhase(3);
          elvis(`Got it — ${r}! Now let's pick your package:`);
          setTimeout(() => setQuickReplies([
            {label:'Basic — R2,499', value:'1'},{label:'Business — R5,999', value:'2'},
            {label:'Premium — R9,999', value:'3'},{label:'Custom Quote', value:'4'},
          ]), 1000);
        } else {
          setPhase(4);
          elvis(`Got it — ${r}! What type of business or industry are you in?`);
          setTimeout(() => setQuickReplies([
            {label:'E-Commerce',value:'E-Commerce'},{label:'Restaurant / Food',value:'Restaurant / Food'},
            {label:'Professional Services',value:'Professional Services'},{label:'Healthcare',value:'Healthcare'},
            {label:'Construction',value:'Construction'},{label:'Beauty & Wellness',value:'Beauty & Wellness'},
            {label:'Trades & Services',value:'Trades & Services'},{label:'Other',value:'Other'},
          ]), 1000);
        }
        return;
      case 3: {
        const pkg = ALL_PACKAGES[r] || Object.values(ALL_PACKAGES).find(p=>p.name.toLowerCase().includes(lower));
        if (pkg) {
          nd.package=pkg.name; nd.packagePrice=pkg.price; setQuoteData(nd); setPhase(4);
          elvis(`${pkg.name} at R${pkg.price.toLocaleString()} — great choice!\n\nWhat type of business or industry are you in?`);
          setTimeout(() => setQuickReplies([
            {label:'E-Commerce',value:'E-Commerce'},{label:'Restaurant / Food',value:'Restaurant / Food'},
            {label:'Professional Services',value:'Professional Services'},{label:'Healthcare',value:'Healthcare'},
            {label:'Construction',value:'Construction'},{label:'Beauty & Wellness',value:'Beauty & Wellness'},
            {label:'Trades & Services',value:'Trades & Services'},{label:'Other',value:'Other'},
          ]), 1200);
        } else {
          elvis(`Please tap your preferred package:`);
          setTimeout(() => setQuickReplies([
            {label:'Basic — R2,499', value:'1'},{label:'Business — R5,999', value:'2'},
            {label:'Premium — R9,999', value:'3'},{label:'Custom Quote', value:'4'},
          ]), 700);
        }
        return;
      }
      case 4:
        nd.businessType=r; setQuoteData(nd); setPhase(5);
        elvis(`Got it! Now tell me about your business and what you'd like the website to achieve:`);
        return;
      case 5:
        nd.description=r; setQuoteData(nd); setPhase(6);
        elvis(`Noted! Now let's pick any add-ons to power up your site. Tap to select, tap again to deselect:`);
        setTimeout(() => setShowAddonPicker(true), 1600);
        return;
      case 7: {
        const tier = PORTAL_TIERS[r] || PORTAL_TIERS["0"];
        nd.portalTier=tier.name; nd.portalPrice=tier.price; setQuoteData(nd); setPhase(8);
        elvis(`${tier.price > 0 ? `${tier.name} — R${tier.price.toLocaleString()} noted!` : 'No POS — got it.'}\n\nWhat's your preferred project timeline?`);
        setTimeout(() => setQuickReplies([
          {label:'ASAP',value:'ASAP — as fast as possible'},{label:'1 Week',value:'1 week'},
          {label:'2 Weeks',value:'2 weeks'},{label:'1 Month',value:'1 month'},
          {label:'Flexible / TBD',value:'Flexible — no rush'},
        ]), 900);
        return;
      }
      case 8: {
        nd.timeline=r;
        const total = nd.packagePrice + (nd.selectedAddons||[]).reduce((s,a)=>s+a.price,0) + nd.portalPrice;
        const ref = 'EST-' + Math.floor(Math.random()*90000+10000);
        setQuoteTotal(total); setQuoteRef(ref); setQuoteData(nd); setPhase(9); setInputDisabled(true);
        let summary = `All done, ${nd.name}! Here's your itemised quote (${ref}):\n`;
        summary += `\nPackage: ${nd.package||'Custom'} — R${nd.packagePrice.toLocaleString()}`;
        (nd.selectedAddons||[]).forEach(a => { summary += `\nAdd-on: ${a.name} — R${a.price.toLocaleString()}`; });
        if (nd.portalPrice > 0) summary += `\nPOS: ${nd.portalTier} — R${nd.portalPrice.toLocaleString()}`;
        summary += `\n\nTOTAL: R${total.toLocaleString()}\nDeposit (50%): R${Math.ceil(total/2).toLocaleString()}\n\nChoose how you'd like to pay:`;
        elvis(summary, 1200);
        setTimeout(() => setShowPayment(true), 2800);
        return;
      }
      default: break;
    }
    setQuoteData(nd);
  };

  /* Payment handlers */
  const handleCardPayment = async () => {
    setShowPayment(false); setInputDisabled(true);
    const depositAmount = Math.ceil(quoteTotal / 2);
    elvis(`Opening secure Yoco payment for R${depositAmount.toLocaleString()}...`, 400);
    try {
      const res = await fetch('/api/public/yoco-checkout', {
        method:'POST', headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ amount: depositAmount, description:`${quoteRef} — 50% Deposit` })
      });
      if (!res.ok) throw new Error('error');
      const { checkoutUrl } = await res.json();
      window.location.href = checkoutUrl;
    } catch(err) {
      elvis(`Something went wrong with the payment gateway. No charge was made. You can try EFT instead.`, 500);
      setTimeout(() => setShowRetryPayment(true), 1200);
    }
  };

  const handleEFT = () => {
    setShowPayment(false);
    const depositAmt = Math.ceil(quoteTotal / 2);
    elvis(`EFT / Bank Transfer it is!\n\nBank: Capitec Entrepreneur\nAccount Holder: Axious Creative Studio\nAccount Number: 248650558\n\nDeposit due: R${depositAmt.toLocaleString()} (50% of R${quoteTotal.toLocaleString()})\nReference: Your preferred domain name`);
    const delay = Math.min(350 + 300 * 10, 2000);
    setTimeout(() => setShowEFTOptions(true), delay + 350);
  };

  const handleEFTPayNow = () => {
    setShowEFTOptions(false); setPhase(9); setInputDisabled(false);
    elvis(`Once you've made the transfer, type your preferred domain name here as confirmation (e.g. mybusiness.co.za):`, 500);
  };

  const handleEFTPayLater = async () => {
    setShowEFTOptions(false); setInputDisabled(true); setPhase(10);
    const nd = { ...quoteData, paymentMethod:'eft-pending', eftRef:'' };
    setQuoteData(nd);
    elvis(`No rush! Sending your application and invoice to ${nd.email || 'your email'} now — banking details included.`, 500);
    try {
      await fetch('/api/quote-request', {
        method:'POST', headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ quoteData: nd, total: quoteTotal, deposit: Math.ceil(quoteTotal/2), quoteRef, paymentMethod:'eft-pending', eftRef:'', referredBy: nd.referredBy||'' })
      });
    } catch(e) {}
    localStorage.removeItem('elvis_v3');
    elvis(`Application submitted! Check your inbox for your invoice with full banking details.\n\nDeposit: R${Math.ceil(quoteTotal/2).toLocaleString()} (50%)\nOnce received we'll kick off your project within 24 hours.`, 1600);
    setTimeout(() => setShowWhatsApp(true), 3500);
  };

  const handleEFTConfirm = async (ref) => {
    setInputDisabled(true); setPhase(10);
    const nd = { ...quoteData, paymentMethod:'eft', eftRef:ref };
    setQuoteData(nd);
    elvis(`Reference "${ref}" noted. Sending your quote to our team now...`, 400);
    try {
      await fetch('/api/quote-request', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({quoteData:nd,total:quoteTotal,deposit:Math.ceil(quoteTotal/2),quoteRef,paymentMethod:'eft',eftRef:ref,referredBy:nd.referredBy||''})});
    } catch(e) {}
    localStorage.removeItem('elvis_v3');
    elvis(`Quote submitted! We'll follow up within 24 hours.\n\nYour Studio Xonnect login will be sent to ${quoteData.email||'your email'} once payment is confirmed.`, 1000);
    setTimeout(() => setShowWhatsApp(true), 2500);
  };

  const sendToWhatsApp = () => {
    const addonLines = (quoteData.selectedAddons||[]).map(a=>`  - ${a.name} — R${a.price.toLocaleString()}`).join('\n');
    const waText = [`Hi Axious! I've submitted a quote via your website:`,``,`Quote Ref: ${quoteRef}`,``,`Client: ${quoteData.name}`,`Email: ${quoteData.email}`,quoteData.phone?`Phone: ${quoteData.phone}`:'',``,`Services:`,quoteData.package?`Package: ${quoteData.package} — R${(quoteData.packagePrice||0).toLocaleString()}`:'',addonLines?`Add-ons:\n${addonLines}`:'',``,`Total: R${quoteTotal.toLocaleString()}`,`Deposit: R${Math.round(quoteTotal*0.5).toLocaleString()}`,``,`Let's get started!`].filter(l=>l!=='').join('\n');
    window.open(`https://wa.me/27623790118?text=${encodeURIComponent(waText)}`,'_blank');
    if (onClose) setTimeout(onClose, 500);
  };

  const phaseOrder = [0,100,1,2,33,3,4,5,6,7,8,9,10];
  const progressPct = Math.min(100, Math.round((Math.max(0, phaseOrder.indexOf(phase)) / (phaseOrder.length-1)) * 100));
  const isEFTWaiting = phase === 9 && !inputDisabled;

  const addonCategories = {};
  Object.entries(ALL_ADDONS).forEach(([k,v]) => { if(!addonCategories[v.cat]) addonCategories[v.cat]=[]; addonCategories[v.cat].push({key:k,...v}); });

  return (
    <div style={{display:'flex',flexDirection:'column',height:'100%',position:'relative',overflow:'hidden',background:'var(--bg, #fff)'}}>
      {/* Header */}
      <div style={{padding:'1rem 1.25rem',display:'flex',alignItems:'center',justifyContent:'space-between',flexShrink:0,background:'var(--bg,#fff)',borderBottom:'1px solid var(--border,#ececec)',position:'relative',zIndex:10}}>
        <div style={{display:'flex',alignItems:'center',gap:'0.75rem'}}>
          <ElvisAv size={44} style={{border:'1px solid rgba(249,115,22,0.5)'}} />
          <div>
            <div style={{fontWeight:700,letterSpacing:'0.08em',textTransform:'uppercase',fontSize:'0.7rem',color:'var(--text,#111)'}}>Elvis — AI Assistant</div>
            <div style={{display:'flex',alignItems:'center',gap:'0.375rem',marginTop:2}}>
              <span style={{width:6,height:6,borderRadius:'50%',background:'#22c55e',animation:'pulse 2s ease-in-out infinite',display:'block'}} />
              <span style={{fontSize:'0.7rem',color:'var(--text-muted,#666)'}}>Online · Axious Creative Studio</span>
            </div>
          </div>
        </div>
        <div style={{display:'flex',alignItems:'center',gap:'0.5rem'}}>
          <div style={{textAlign:'right',marginRight:4}}>
            <div style={{fontSize:'0.6rem',textTransform:'uppercase',letterSpacing:'0.06em',color:'var(--text-muted,#666)'}}>Progress</div>
            <div style={{fontSize:'0.875rem',fontWeight:700,color:'var(--accent,#f97316)'}}>{progressPct}%</div>
          </div>
          {phase > 0 && (
            <button onClick={handleRestart} aria-label="Start over" title="Start over" style={{padding:'0.4rem',borderRadius:8,border:'1px solid var(--border,#ececec)',background:'var(--bg,#fff)',cursor:'pointer',color:'var(--text-muted,#666)',lineHeight:0}}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
            </button>
          )}
          {onClose && (
            <button onClick={onClose} aria-label="Close" style={{padding:'0.4rem',borderRadius:8,border:'none',background:'transparent',cursor:'pointer',color:'var(--text-muted,#666)',lineHeight:0}}>
              <_XIcon size={18} />
            </button>
          )}
        </div>
        {/* Progress bar */}
        <div style={{position:'absolute',bottom:0,left:0,right:0,height:2,background:'var(--border,#ececec)'}}>
          <div style={{height:'100%',background:'#f97316',width:`${progressPct}%`,transition:'width 0.7s ease'}} />
        </div>
      </div>

      {/* Messages */}
      <div style={{flex:1,overflowY:'auto',padding:'1.25rem 1rem',display:'flex',flexDirection:'column',gap:'0.75rem',minHeight:0,overscrollBehavior:'contain'}}>
        {messages.map((m, i) => (
          <div key={i} style={{display:'flex',justifyContent:m.sender==='user'?'flex-end':'flex-start'}}>
            {m.sender==='elvis' && <ElvisAv size={28} style={{marginRight:'0.625rem',marginTop:2}} />}
            <div style={{
              maxWidth:'78%',padding:'0.75rem 1rem',fontSize:'0.875rem',lineHeight:1.6,whiteSpace:'pre-wrap',
              borderRadius:m.sender==='user'?'1.25rem 1.25rem 0.25rem 1.25rem':'0.25rem 1.25rem 1.25rem 1.25rem',
              background:m.sender==='user'?'var(--accent,#f97316)':'var(--bg-card,#f9f9f9)',
              color:m.sender==='user'?'#fff':'var(--text,#111)',
              border:m.sender==='user'?'none':'1px solid var(--border,#ececec)',
            }}>{m.text}</div>
          </div>
        ))}

        {isTyping && (
          <div style={{display:'flex',justifyContent:'flex-start'}}>
            <ElvisAv size={28} style={{marginRight:'0.625rem'}} />
            <div style={{padding:'0.75rem 1rem',display:'flex',gap:6,alignItems:'center',borderRadius:'0.25rem 1.25rem 1.25rem 1.25rem',background:'var(--bg-card,#f9f9f9)',border:'1px solid var(--border,#ececec)'}}>
              {[0,0.15,0.3].map((d,i) => <div key={i} style={{width:8,height:8,borderRadius:'50%',background:'#f97316',animation:`bounce 1s ease-in-out ${d}s infinite`}} />)}
            </div>
          </div>
        )}

        {quickReplies.length > 0 && !isTyping && (
          <div style={{display:'flex',flexWrap:'wrap',gap:'0.5rem',paddingLeft:'2.5rem'}}>
            {quickReplies.map((qr, i) => (
              <button key={i} onClick={() => handleQuickReply(qr.value, qr.label)}
                style={{fontSize:'0.8rem',fontWeight:600,padding:'0.4rem 0.875rem',borderRadius:9999,border:'1.5px solid var(--border,#ececec)',background:'var(--bg-card,#f9f9f9)',color:'var(--text,#111)',cursor:'pointer',whiteSpace:'nowrap',transition:'all 0.15s'}}
                onMouseEnter={e=>{e.currentTarget.style.borderColor='var(--accent,#f97316)';e.currentTarget.style.color='var(--accent,#f97316)';}}
                onMouseLeave={e=>{e.currentTarget.style.borderColor='var(--border,#ececec)';e.currentTarget.style.color='var(--text,#111)';}}
              >{qr.label}</button>
            ))}
          </div>
        )}

        {/* Add-on picker */}
        {showAddonPicker && (
          <div style={{display:'flex',justifyContent:'flex-start'}}>
            <ElvisAv size={28} style={{marginRight:'0.625rem',marginTop:2}} />
            <div style={{borderRadius:'0.25rem 1.25rem 1.25rem 1.25rem',padding:'1rem',maxWidth:'22rem',width:'100%',background:'var(--bg-card,#f9f9f9)',border:'1px solid var(--border,#ececec)'}}>
              <p style={{fontSize:'0.65rem',fontWeight:800,textTransform:'uppercase',letterSpacing:'0.12em',color:'var(--text-muted,#666)',marginBottom:'0.875rem'}}>Tap to add — tap again to remove</p>
              {Object.entries(addonCategories).map(([cat, items]) => {
                const meta = ADDON_CAT_META[cat] || ADDON_CAT_META['Essentials'];
                return (
                  <div key={cat} style={{marginBottom:'1rem'}}>
                    <p style={{fontSize:'0.6rem',fontWeight:800,textTransform:'uppercase',letterSpacing:'0.1em',color:'var(--accent,#f97316)',marginBottom:'0.5rem'}}>{cat}</p>
                    <div style={{display:'flex',gap:'0.5rem',overflowX:'auto',paddingBottom:4,scrollbarWidth:'none'}}>
                      {items.map(item => {
                        const sel = selectedAddons.has(item.key);
                        return (
                          <button key={item.key} onClick={() => { const n=new Set(selectedAddons); sel?n.delete(item.key):n.add(item.key); setSelectedAddons(n); }}
                            style={{flexShrink:0,width:148,borderRadius:14,border:`2px solid ${sel?'#FF5A00':'transparent'}`,background:'var(--bg,#fff)',padding:0,cursor:'pointer',overflow:'hidden',textAlign:'left',boxShadow:sel?'0 0 0 4px rgba(255,90,0,0.12)':'0 2px 10px rgba(0,0,0,0.09)',transition:'border-color 0.18s,box-shadow 0.18s'}}>
                            <div style={{height:72,background:meta.gradient,position:'relative',overflow:'hidden'}}>
                              <img src={meta.img} alt={cat} loading="lazy" style={{width:'100%',height:'100%',objectFit:'cover'}} onError={e=>{e.currentTarget.style.display='none';}} />
                              {sel && <div style={{position:'absolute',top:6,right:6,width:16,height:16,borderRadius:'50%',background:'#FF5A00',display:'flex',alignItems:'center',justifyContent:'center'}}><svg width="8" height="8" viewBox="0 0 12 12" fill="none"><polyline points="2,6 5,9 10,3" stroke="white" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg></div>}
                            </div>
                            <div style={{padding:'0.5rem 0.55rem'}}>
                              <div style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between',gap:4,marginBottom:4}}>
                                <p style={{fontSize:'0.65rem',fontWeight:700,color:'var(--text,#111)',lineHeight:1.3,flex:1,margin:0}}>{item.name.length>28?item.name.slice(0,28)+'...':item.name}</p>
                                <span style={{flexShrink:0,fontSize:'0.58rem',fontWeight:700,background:'#FF5A00',color:'#fff',borderRadius:9999,padding:'2px 6px'}}>R{item.price.toLocaleString()}</span>
                              </div>
                              {ADDON_DESCS[item.key] && <p style={{fontSize:'0.58rem',color:'var(--text-muted,#666)',lineHeight:1.3,margin:'0 0 6px'}}>{ADDON_DESCS[item.key]}</p>}
                              <div style={{width:'100%',padding:'4px 0',borderRadius:8,textAlign:'center',background:sel?'#111':'#FF5A00',color:'#fff',fontSize:'0.6rem',fontWeight:700}}>
                                {sel ? 'Added' : '+ Add'}
                              </div>
                            </div>
                          </button>
                        );
                      })}
                    </div>
                  </div>
                );
              })}
              <button onClick={confirmAddons} style={{width:'100%',marginTop:4,background:'var(--accent,#f97316)',color:'#fff',fontWeight:700,fontSize:'0.875rem',padding:'0.625rem 1rem',borderRadius:'0.75rem',border:'none',cursor:'pointer'}}>
                Confirm {selectedAddons.size>0?`(${selectedAddons.size} selected)`:' — No Add-Ons'} →
              </button>
            </div>
          </div>
        )}

        {/* Payment options */}
        {showPayment && (
          <div style={{display:'flex',justifyContent:'flex-start'}}>
            <ElvisAv size={28} style={{marginRight:'0.625rem',marginTop:2}} />
            <div style={{borderRadius:'0.25rem 1.25rem 1.25rem 1.25rem',padding:'1rem',maxWidth:'18rem',width:'100%',background:'var(--bg-card,#f9f9f9)',border:'1px solid var(--border,#ececec)'}}>
              <p style={{fontSize:'0.65rem',fontWeight:800,textTransform:'uppercase',letterSpacing:'0.12em',color:'var(--text-muted,#666)',marginBottom:'0.75rem'}}>Choose payment method</p>
              <button onClick={handleCardPayment} style={{width:'100%',marginBottom:'0.5rem',background:'#00a1e0',color:'#fff',fontWeight:700,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'none',cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',gap:'0.5rem'}}>
                Pay with Yoco (Card)
              </button>
              <button onClick={handleEFT} style={{width:'100%',background:'var(--bg,#fff)',color:'var(--text,#111)',fontWeight:700,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'1px solid var(--border,#ececec)',cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',gap:'0.5rem'}}>
                EFT / Bank Transfer
              </button>
            </div>
          </div>
        )}

        {/* EFT Pay Now / Pay Later */}
        {showEFTOptions && (
          <div style={{display:'flex',justifyContent:'flex-start'}}>
            <ElvisAv size={28} style={{marginRight:'0.625rem',marginTop:2}} />
            <div style={{borderRadius:'0.25rem 1.25rem 1.25rem 1.25rem',padding:'1rem',maxWidth:'20rem',width:'100%',background:'var(--bg-card,#f9f9f9)',border:'1px solid var(--border,#ececec)'}}>
              <p style={{fontSize:'0.65rem',fontWeight:800,textTransform:'uppercase',letterSpacing:'0.12em',color:'var(--text-muted,#666)',marginBottom:'0.75rem'}}>When would you like to pay?</p>
              <button onClick={handleEFTPayNow} style={{width:'100%',marginBottom:'0.5rem',background:'var(--accent,#f97316)',color:'#fff',fontWeight:700,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'none',cursor:'pointer'}}>
                Paying now — enter reference
              </button>
              <button onClick={handleEFTPayLater} style={{width:'100%',background:'var(--bg,#fff)',color:'var(--text,#111)',fontWeight:600,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'1px solid var(--border,#ececec)',cursor:'pointer'}}>
                Just send my application — I'll pay later
              </button>
            </div>
          </div>
        )}

        {/* Retry payment */}
        {showRetryPayment && (
          <div style={{display:'flex',justifyContent:'flex-start'}}>
            <ElvisAv size={28} style={{marginRight:'0.625rem',marginTop:2}} />
            <div style={{borderRadius:'0.25rem 1.25rem 1.25rem 1.25rem',padding:'1rem',maxWidth:'18rem',width:'100%',background:'var(--bg-card,#f9f9f9)',border:'1px solid var(--border,#ececec)'}}>
              <p style={{fontSize:'0.65rem',fontWeight:800,textTransform:'uppercase',letterSpacing:'0.12em',color:'var(--text-muted,#666)',marginBottom:'0.75rem'}}>What would you like to do?</p>
              <button onClick={() => { setShowRetryPayment(false); handleCardPayment(); }} style={{width:'100%',marginBottom:'0.5rem',background:'#00a1e0',color:'#fff',fontWeight:700,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'none',cursor:'pointer'}}>Try again with card</button>
              <button onClick={() => { setShowRetryPayment(false); handleEFT(); }} style={{width:'100%',background:'var(--bg,#fff)',color:'var(--text,#111)',fontWeight:700,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'1px solid var(--border,#ececec)',cursor:'pointer'}}>Switch to EFT instead</button>
            </div>
          </div>
        )}

        {/* WhatsApp follow-up */}
        {showWhatsApp && (
          <div style={{display:'flex',justifyContent:'flex-start'}}>
            <ElvisAv size={28} style={{marginRight:'0.625rem',marginTop:2}} />
            <div style={{borderRadius:'0.25rem 1.25rem 1.25rem 1.25rem',padding:'1rem',maxWidth:'18rem',width:'100%',background:'var(--bg-card,#f9f9f9)',border:'1px solid var(--border,#ececec)'}}>
              <p style={{fontSize:'0.875rem',fontWeight:700,color:'var(--text,#111)',marginBottom:4}}>Want a faster response?</p>
              <p style={{fontSize:'0.75rem',color:'var(--text-muted,#666)',marginBottom:'0.75rem'}}>Send your quote summary directly to our team on WhatsApp.</p>
              <button onClick={sendToWhatsApp} style={{width:'100%',marginBottom:'0.5rem',background:'#25D366',color:'#fff',fontWeight:700,fontSize:'0.875rem',padding:'0.75rem 1rem',borderRadius:'0.75rem',border:'none',cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',gap:'0.5rem'}}>
                <_WA size={16} /> Send via WhatsApp
              </button>
              <button onClick={() => { if(onClose) onClose(); else setShowWhatsApp(false); }} style={{width:'100%',fontSize:'0.75rem',padding:'0.5rem',background:'none',border:'none',cursor:'pointer',color:'var(--text-muted,#666)'}}>
                No thanks, email is fine
              </button>
            </div>
          </div>
        )}

        <div ref={chatEndRef} />
      </div>

      {/* Input bar */}
      <div style={{flexShrink:0,padding:'0.75rem',display:'flex',gap:'0.625rem',background:'var(--bg-card,#f9f9f9)',borderTop:'1px solid var(--border,#ececec)',paddingBottom:'calc(0.75rem + env(safe-area-inset-bottom))'}}>
        <input
          ref={inputRef}
          type="text"
          value={inputValue}
          onChange={e => setInputValue(e.target.value)}
          onKeyDown={e => {
            if (e.key !== 'Enter') return;
            if (isEFTWaiting && inputValue.trim()) { user(inputValue.trim()); handleEFTConfirm(inputValue.trim()); setInputValue(''); }
            else if (!inputDisabled) { handleSend(); }
          }}
          disabled={inputDisabled && !isEFTWaiting}
          style={{flex:1,background:'var(--bg,#fff)',border:'1px solid var(--border,#ececec)',borderRadius:'0.75rem',padding:'0.75rem 1rem',fontSize:16,color:'var(--text,#111)',outline:'none'}}
          onFocus={e=>e.target.style.borderColor='var(--accent,#f97316)'}
          onBlur={e=>e.target.style.borderColor='var(--border,#ececec)'}
          placeholder={inputDisabled&&!isEFTWaiting?'Processing…':isEFTWaiting?'Enter your preferred domain name…':showAddonPicker?'Use the cards above to select add-ons…':'Type your message…'}
          autoFocus
        />
        <button
          onClick={() => {
            if (isEFTWaiting && inputValue.trim()) { user(inputValue.trim()); handleEFTConfirm(inputValue.trim()); setInputValue(''); }
            else { handleSend(); }
          }}
          disabled={(inputDisabled && !isEFTWaiting) || !inputValue.trim()}
          style={{background:'var(--accent,#f97316)',color:'#fff',padding:'0.75rem 1.125rem',borderRadius:'0.75rem',border:'none',cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',opacity:((inputDisabled&&!isEFTWaiting)||!inputValue.trim())?0.38:1}}
        >
          <_ArrowRight size={18} />
        </button>
      </div>
    </div>
  );
});

/* ── AmbientElvisOrb — floating bottom-right glass orb button ── */
const AmbientElvisOrb = ({ onOpen, isElvisOpen }) => {
  const [hover, setHover] = React.useState(false);
  const [dismissed, setDismissed] = React.useState(() => {
    try { return sessionStorage.getItem('ax_orb_d') === '1'; } catch(e) { return false; }
  });
  const [showAutoLabel, setShowAutoLabel] = React.useState(false);
  const orbRef = React.useRef(null);

  React.useEffect(() => {
    try { if (sessionStorage.getItem('ax_orb_lbl')) return; } catch(e) {}
    const t = setTimeout(() => {
      setShowAutoLabel(true);
      try { sessionStorage.setItem('ax_orb_lbl','1'); } catch(e) {}
      setTimeout(() => setShowAutoLabel(false), 3800);
    }, 2200);
    return () => clearTimeout(t);
  }, []);

  /* Pointer-responsive tilt */
  React.useEffect(() => {
    const orb = orbRef.current;
    if (!orb) return;
    const state = { x:0, y:0, tx:0, ty:0 };
    let lastInputAt = performance.now();
    let rafId;
    const tick = () => {
      const now = performance.now();
      const t = now * 0.001;
      if (now - lastInputAt > 1200) {
        state.tx = Math.sin(t*0.8)*0.9 + Math.sin(t*1.7)*0.35;
        state.ty = Math.cos(t*0.7)*0.8 + Math.cos(t*1.4)*0.3;
      }
      state.x += (state.tx - state.x) * 0.09;
      state.y += (state.ty - state.y) * 0.09;
      orb.style.setProperty('--tilt-x', `${state.x}deg`);
      orb.style.setProperty('--tilt-y', `${state.y}deg`);
      rafId = requestAnimationFrame(tick);
    };
    const updateTilt = (x, y) => {
      lastInputAt = performance.now();
      const rect = orb.getBoundingClientRect();
      const dx = (x - (rect.left + rect.width/2)) / (window.innerWidth/2);
      const dy = (y - (rect.top + rect.height/2)) / (window.innerHeight/2);
      state.tx = Math.max(-4, Math.min(4, dx*3.8));
      state.ty = Math.max(-4, Math.min(4, -dy*3.8));
    };
    const onMM = e => updateTilt(e.clientX, e.clientY);
    const onTM = e => { if (e.touches.length) updateTilt(e.touches[0].clientX, e.touches[0].clientY); };
    window.addEventListener('mousemove', onMM);
    window.addEventListener('touchmove', onTM, { passive:true });
    rafId = requestAnimationFrame(tick);
    return () => {
      window.removeEventListener('mousemove', onMM);
      window.removeEventListener('touchmove', onTM);
      cancelAnimationFrame(rafId);
    };
  }, []);

  if (isElvisOpen || dismissed) return null;

  const labelStyle = {
    position:'fixed', zIndex:49,
    right:'calc(2rem + 88px)',
    bottom:'calc(max(2rem, env(safe-area-inset-bottom, 2rem)) + 24px)',
    padding:'7px 14px', borderRadius:9999,
    background:'rgba(10,10,10,0.92)',
    border:'1px solid rgba(156,116,255,0.45)',
    color:'#fff', fontSize:'0.75rem', fontWeight:700,
    letterSpacing:'0.04em', whiteSpace:'nowrap',
    boxShadow:'0 4px 20px rgba(0,0,0,0.35)',
    pointerEvents:'none',
    animation:'ag-label-in 0.35s ease forwards',
  };

  return (
    <>
      {(showAutoLabel && !hover) && <div style={labelStyle}>Chat with Elvis</div>}
      {hover && (
        <div style={{...labelStyle, pointerEvents:'auto'}}>
          Chat with Elvis
          <button onClick={e=>{e.stopPropagation();setDismissed(true);try{sessionStorage.setItem('ax_orb_d','1');}catch(ex){}}}
            aria-label="Hide" style={{marginLeft:8,background:'none',border:'none',color:'rgba(255,255,255,0.5)',cursor:'pointer',padding:0,fontSize:12}}>
            x
          </button>
        </div>
      )}
      <div style={{position:'fixed',zIndex:50,right:'2rem',bottom:'max(2rem, env(safe-area-inset-bottom, 2rem))',width:80,height:80,display:'grid',placeItems:'center',animation:'ag-pop 0.55s cubic-bezier(0.34,1.56,0.64,1) forwards'}}>
        <div style={{position:'absolute',inset:4,borderRadius:'50%',border:'2px solid rgba(156,116,255,0.5)',animation:'ag-ring 2.2s ease-out infinite',pointerEvents:'none'}} />
        <div style={{position:'absolute',inset:4,borderRadius:'50%',border:'2px solid rgba(79,184,255,0.35)',animation:'ag-ring 2.2s ease-out 1.1s infinite',pointerEvents:'none'}} />
        <button
          onClick={onOpen}
          onMouseEnter={() => setHover(true)}
          onMouseLeave={() => setHover(false)}
          aria-label="Chat with Elvis — AI assistant"
          title="Chat with Elvis"
          style={{background:'none',border:'none',padding:0,cursor:'pointer',width:80,height:80,display:'grid',placeItems:'center',perspective:'600px',filter:hover?'brightness(1.12) drop-shadow(0 0 14px rgba(156,116,255,.55))':'none',transition:'filter 0.25s ease'}}
        >
          <div ref={orbRef} className="ag-orb" style={{'--tilt-x':'0deg','--tilt-y':'0deg'}}>
            <div className="ag-frost" />
            <div className="ag-aura ag-aura-1" />
            <div className="ag-aura ag-aura-2" />
            <div className="ag-aura ag-aura-3" />
            <div className="ag-glow ag-glow-blue" />
            <div className="ag-glow ag-glow-orange" />
            <div className="ag-glow ag-glow-purple" />
            <div className="ag-breath" />
            <svg className="ag-seam" viewBox="0 0 100 100" aria-hidden="true">
              <path className="ag-seam-shadow" d="M18 63 C35 78, 58 48, 79 35" />
              <path className="ag-seam-main" d="M18 63 C35 78, 58 48, 79 35" />
            </svg>
            <div className="ag-shine" />
          </div>
        </button>
      </div>
    </>
  );
};

/* Expose to global scope for app.jsx (cross-script-tag access) */
Object.assign(window, { ElvisAv, ElvisChat, AmbientElvisOrb });
