/* ============================================================
   CELLIE — AE chat widget for GMR landings.
   Two behaviour modes (HUB spec):
     • Mode A — self-service (default on product landings): explain +
       "Start free trial" CTA → app SSO. No meeting. Can escalate to B.
     • Mode B — sales-led / suite (default on genmr.co, or "Bundle"
       trigger / in-chat suite intent): BANT (8 fields) → real calendar.
   Mode follows intent (single product → trial · suite → call).
   Themed per product via CSS (.cellie{--acc}). Knowledge/brain (Opus
   4.8 + Notion/DB) wires in later; this is the deterministic skeleton.
   ============================================================ */
const {useState,useRef,useEffect}=React;

/* ---- HubSpot integration (EU1) ---------------------------------
   Mode B: inline Meetings calendar + qualification push to a form.
   Fill HS_PORTAL + HS_FORM to enable the push (the embed works regardless). */
const HS_MEETING="https://meetings-eu1.hubspot.com/alberto-nasciuti/genmr-bundle";
const HS_PORTAL="";   // EU1 portal id
const HS_FORM="";     // Forms API form GUID
let __hsPushed=false;
function pushToHubSpot(cap,extra){
  if(!HS_PORTAL||!HS_FORM||__hsPushed||!cap||!cap.email) return;
  __hsPushed=true;
  extra=extra||{};
  const strong=(STRONG_COMPANY.includes(cap.company)?1:0)+(STRONG_APPS.includes(cap.apps_wanted)?1:0)+(STRONG_TIME.includes(cap.timeline)?1:0)+((cap.usecase)?1:0);
  const fitLabel=strong>=3?"Strong fit":strong>=1?"Good fit":"Exploring";
  const rows=[["Role",cap.role],["Company",cap.company],["Team",cap.team_size],["Goal",cap.usecase],["Apps",cap.apps_wanted],["Timeline",cap.timeline],["Region",cap.region],["Fit",fitLabel]];
  const summary=rows.filter(r=>r[1]).map(r=>r[0]+": "+r[1]).join(" · ");
  const fields=[{name:"email",value:cap.email}];
  const add=(n,v)=>{ if(v) fields.push({name:n,value:v}); };
  add("cellie_source","Cellie");
  add("cellie_mode",extra.mode||"bundle");
  add("cellie_app",extra.app||"");
  add("cellie_session_id",extra.sid||"");
  add("cellie_role",cap.role); add("cellie_company",cap.company); add("cellie_team_size",cap.team_size);
  add("cellie_use_case",cap.usecase); add("cellie_apps_wanted",cap.apps_wanted);
  add("cellie_timeline",cap.timeline); add("cellie_region",cap.region);
  add("cellie_fit",fitLabel); add("cellie_qualification_summary",summary);
  try{
    fetch("https://api-eu1.hsforms.com/submissions/v3/integration/submit/"+HS_PORTAL+"/"+HS_FORM,{
      method:"POST",headers:{"Content-Type":"application/json"},
      body:JSON.stringify({fields,context:{pageUri:location.href,pageName:document.title}})
    }).catch(function(){});
  }catch(e){}
}
/* Build the HubSpot booking URL with the qualification as cellie_* params, so it
   attaches to the contact the booking creates (no email asked in chat). The big
   HubSpot iframe embed was replaced by a single on-brand button → this URL. */
function buildBookUrl(p){
  const q=Object.keys(p||{}).filter(function(k){return p[k];}).map(function(k){return encodeURIComponent(k)+"="+encodeURIComponent(p[k]);}).join("&");
  return HS_MEETING+(q?("?"+q):"");
}

/* small inline icons */
const Sv={
  chat:(<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>),
  send:(<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>),
  close:(<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>),
  cal:(<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>),
  check:(<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>),
  spark:(<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M18.4 5.6l-2.8 2.8M8.4 15.6l-2.8 2.8"/></svg>),
  arrow:(<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>),
  chevron:(<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>),
  x:(<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>),
};

/* Cellie — smiley headset agent, ink via currentColor */
const CellieFace=({s=28})=>(
  <svg width={s} height={s} viewBox="0 0 52 52" fill="none" stroke="currentColor" aria-hidden="true">
    <path d="M12 25 A 14 14 0 0 1 40 25" strokeWidth="2.6" strokeLinecap="round"/>
    <rect x="9.6" y="23" width="4" height="6" rx="2" fill="currentColor" stroke="none"/>
    <rect x="38.4" y="23" width="4" height="6" rx="2" fill="currentColor" stroke="none"/>
    <path d="M40 28 C40 34 36 37 31 37" strokeWidth="2.4" strokeLinecap="round"/>
    <circle cx="30" cy="37" r="1.5" fill="currentColor" stroke="none"/>
    <circle className="cellie-eye" cx="20" cy="28" r="2.6" fill="currentColor" stroke="none"/>
    <circle className="cellie-eye" cx="32" cy="28" r="2.6" fill="currentColor" stroke="none"/>
    <path d="M20 34 Q26 38 32 34" strokeWidth="2.4" strokeLinecap="round"/>
  </svg>
);

/* Tiny inline markdown renderer for bot bubbles (**bold**, *italic*, `code`,
   - bullets, line breaks). Inline-safe so it stays valid inside the bubble span. */
function renderInline(s,kp){
  const nodes=[]; const re=/(\*\*([^*]+)\*\*|\*([^*]+)\*|`([^`]+)`)/g;
  let m,last=0,k=0;
  while((m=re.exec(s))){
    if(m.index>last) nodes.push(s.slice(last,m.index));
    if(m[2]!=null) nodes.push(<strong key={kp+"b"+k}>{m[2]}</strong>);
    else if(m[3]!=null) nodes.push(<em key={kp+"i"+k}>{m[3]}</em>);
    else if(m[4]!=null) nodes.push(<code key={kp+"c"+k}>{m[4]}</code>);
    last=m.index+m[0].length; k++;
  }
  if(last<s.length) nodes.push(s.slice(last));
  return nodes;
}
function Rich({text}){
  const lines=(text||"").split(/\n/);
  const out=[];
  lines.forEach((ln,idx)=>{
    if(idx>0) out.push(<br key={"br"+idx}/>);
    const b=ln.match(/^\s*[-*•]\s+(.*)/);
    if(b) out.push(<span key={"s"+idx}>{"•  "}{renderInline(b[1],"l"+idx)}</span>);
    else out.push(<span key={"s"+idx}>{renderInline(ln,"p"+idx)}</span>);
  });
  return out;
}

const NAMES={brynx:"Brynx",dtwin:"DTwin",marketear:"Marketear",influrep:"InfluRep",geoky:"Geoky",klenux:"Klenux",gmr:"GMR"};
/* one-line value prop (Mode A intro) */
const VALUE={
  brynx:"A research agency, in an afternoon — board-ready research in hours, not weeks.",
  dtwin:"Your customers, on call — test ideas on thousands of digital twins before you spend.",
  marketear:"Turn the noise into decisions — agentic social listening that hands you a client-ready report.",
  influrep:"The right face, verified — discover and vet influencers on real data.",
  geoky:"Exist where people search — see how your brand shows up in ChatGPT, Gemini, Perplexity, Claude.",
  klenux:"Find the friction before your users do — test your site or app on digital twins before launch.",
  gmr:"Six AI-native products, one team of agents, one wallet — the whole agency, inside yours.",
};
const USECASES={
  brynx:["Competitive analysis","Consumer reaction","Strategy / GTM","Market sizing"],
  dtwin:["Concept testing","Survey at scale","Focus groups","What-if scenarios"],
  marketear:["Brand monitoring","Campaign tracking","Competitor watch","Reputation / crisis"],
  influrep:["Find creators","Vet an influencer","Audience check","Competitor benchmark"],
  geoky:["AI visibility audit","Share of voice","Get cited by AI","Competitor GEO"],
  klenux:["Test a signup flow","Find friction","Pre-launch UX check","Compare two designs"],
  gmr:["Market research","Consumer insight","Social intelligence","Influencer / GEO","UX research","The whole stack"],
};
/* real app SSO URL for the free-trial CTA (Mode A) */
const APP_URL={
  brynx:"https://app.brynx.ai/login",
  dtwin:"https://suite.dtwin.now",
  marketear:"https://app.marketear.co/login",
  influrep:"https://app.influrep.com/auth",
  geoky:"https://app.geoky.ai/login",
  klenux:"https://app.klenux.com/login",
};

/* ---- Step machines ---- */
function buildSteps(product,mode){
  const name=NAMES[product.id]||"GMR";
  if(mode==="A"){
    return [
      {key:"a-start",bot:[`Hi — I'm Cellie, your AE at ${name}.`,VALUE[product.id]||VALUE.gmr,`You can try ${name} free right now — no card. Or ask me anything.`],card:"trialcta"},
    ];
  }
  // Mode B — suite / sales-led (BANT)
  const isHub=product.id==="gmr";
  return [
    {key:"b-start",bot:[
      isHub
        ? `Hi — I'm Cellie. You're looking at the whole GMR suite: six products, one team of agents, one wallet.`
        : `Got it — sounds like you want the whole suite, not just ${name}.`,
      "Let me line up a call with our team. A few quick questions first."
    ],chips:["Sounds good"]},
    {key:"role",bot:["What's your role at the company?"],chips:["Founder / C-level","Marketing","Insights / Research","Sales / RevOps","Other"],capture:"role"},
    {key:"company",bot:["Agency, consulting firm, or in-house brand?"],chips:["Agency","Consulting / Advisory","Brand / in-house","Other"],capture:"company"},
    {key:"size",bot:["How big is the team that'd use it?"],chips:["1–10","11–50","51–200","200+"],capture:"team_size"},
    {key:"usecase",bot:["What are you hoping to achieve with the suite?"],input:"text",capture:"usecase"},
    {key:"apps",bot:["All six products, or a few specific ones?"],chips:["All six","A few specific ones","Not sure yet"],capture:"apps_wanted"},
    {key:"timeline",bot:["Any timeline in mind?"],chips:["This week","This month","This quarter","Just exploring"],capture:"timeline"},
    {key:"region",bot:["Where's your team based?"],chips:["Italy","Europe","North America","Other"],capture:"region"},
    {key:"book",bot:[],card:"slots"}, // no email step — captured at booking (calendar) / via SSO (trial)
  ];
}

const BRIEF_ROWS=[["role","Role"],["company","Company"],["team_size","Team"],["usecase","Goal"],["apps_wanted","Apps"],["timeline","Timeline"],["region","Region"]];
const STRONG_COMPANY=["Agency","Consulting / Advisory"];
const STRONG_APPS=["All six","A few specific ones"];
const STRONG_TIME=["This week","This month","This quarter"];

function computeFit(cap){
  const filled=BRIEF_ROWS.filter(([k])=>cap[k]).length;
  let score=0;
  if(STRONG_COMPANY.includes(cap.company)) score++;
  if(STRONG_APPS.includes(cap.apps_wanted)) score++;
  if(STRONG_TIME.includes(cap.timeline)) score++;
  if(cap.usecase) score++;
  let seg=0,label="Qualifying…";
  if(filled>=1) seg=1;
  if(filled>=4) seg=2;
  if(filled>=6) seg=3;
  if(filled>=2) label = score>=3 ? "Strong fit" : score>=1 ? "Good fit" : "Exploring";
  return {filled,seg,label};
}

function CellieChat({product}){
  const defaultMode = product.id==="gmr" ? "B" : "A";
  const [open,setOpen]=useState(false);
  const [showNudge,setShowNudge]=useState(false);
  const [mode,setMode]=useState(defaultMode);
  const [msgs,setMsgs]=useState([]);
  const [step,setStep]=useState(-1);
  const [botDone,setBotDone]=useState(false);
  const [answered,setAnswered]=useState(false);
  const [cap,setCap]=useState({});
  const [typing,setTyping]=useState(false);
  const [val,setVal]=useState("");
  const [briefOpen,setBriefOpen]=useState(true);
  const [brain,setBrain]=useState(null);          // null=unknown · true=Opus brain · false=scripted fallback
  const [sending,setSending]=useState(false);
  const [brainAction,setBrainAction]=useState(null); // 'book' | 'trial' | null (set by the brain)
  const bodyRef=useRef(null);
  const timers=useRef([]);
  const bootedRef=useRef(false);
  const stepsRef=useRef(buildSteps(product,defaultMode));
  const startModeRef=useRef(defaultMode);
  const sid=useRef((window.crypto&&crypto.randomUUID)?crypto.randomUUID():"cel_"+Date.now().toString(36)+Math.random().toString(36).slice(2)).current;

  const clearTimers=()=>{timers.current.forEach(clearTimeout);timers.current=[];};
  const T=(fn,ms)=>{const id=setTimeout(fn,ms);timers.current.push(id);return id;};
  useEffect(()=>()=>clearTimers(),[]);

  // imperative open hooks: default (entry mode) + bundle (force Mode B)
  function openPanel(m){ startModeRef.current = m || defaultMode; setOpen(true); }
  useEffect(()=>{
    const openDefault=()=>openPanel();
    const openBundle=()=>openPanel("B");
    const onEvt=(e)=>openPanel(e&&e.detail&&e.detail.mode);
    window.openCellie=openDefault;
    window.openCellieBundle=openBundle;
    window.addEventListener("cellie:open",onEvt);
    return ()=>{
      window.removeEventListener("cellie:open",onEvt);
      if(window.openCellie===openDefault) delete window.openCellie;
      if(window.openCellieBundle===openBundle) delete window.openCellieBundle;
    };
  },[]);

  // nudge teaser
  useEffect(()=>{
    if(open){setShowNudge(false);return;}
    const id=setTimeout(()=>setShowNudge(true),1600);
    return ()=>clearTimeout(id);
  },[open]);

  // start convo on first open: probe the brain, else fall back to the scripted skeleton
  useEffect(()=>{
    if(open && !bootedRef.current){ bootedRef.current=true; boot(); }
  },[open]);

  // autoscroll — follow the conversation to the bottom
  useEffect(()=>{
    const el=bodyRef.current;
    if(el) el.scrollTop=el.scrollHeight;
  },[msgs,typing,botDone,step,brainAction]);

  function start(m){
    stepsRef.current=buildSteps(product,m);
    setMode(m);
    setMsgs([]);setCap({});setAnswered(false);setBotDone(false);setStep(-1);
    T(()=>runStep(0),30);
  }

  // ---- Brain (Opus 4.8 via /api/cellie) — falls back to scripted skeleton ----
  async function boot(){
    let ok=false;
    try{
      const r=await fetch("/api/cellie",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({ping:true})});
      const j=await r.json(); ok=!!(j&&j.configured);
    }catch(e){ ok=false; }
    setBrain(ok);
    if(ok) brainOpener();
    else start(startModeRef.current);
  }
  function typeBot(lines){
    let k=0;
    const tick=()=>{
      if(k>=lines.length) return;
      setTyping(true);
      const line=lines[k];
      const delay=Math.min(420+line.length*8,1250);
      T(()=>{ setTyping(false); setMsgs(m=>[...m,{from:"bot",text:line}]); k++; T(tick,300); },delay);
    };
    tick();
  }
  function brainOpener(){
    const m=startModeRef.current; setMode(m);
    const name=NAMES[product.id]||"GMR";
    const lines = m==="B"
      ? [ product.id==="gmr"
            ? "Hi — I'm Cellie. You're looking at the whole GMR suite: six products, one team of agents, one wallet."
            : `Hi — I'm Cellie. Sounds like you're after more than just ${name}.`,
          "Tell me about you and what you're trying to do — I'll line up the right call." ]
      : [ `Hi — I'm Cellie, your AE at ${name}.`, VALUE[product.id]||VALUE.gmr,
          "Ask me anything, or tell me what you're working on." ];
    typeBot(lines);
  }
  function toApi(list){
    const out=[];
    for(const mm of list){
      const role=mm.from==="user"?"user":"assistant";
      if(out.length && out[out.length-1].role===role) out[out.length-1].content+="\n"+mm.text;
      else out.push({role,content:mm.text});
    }
    while(out.length && out[0].role!=="user") out.shift();
    return out;
  }
  function brainSend(text){
    const userMsg={from:"user",text};
    const history=[...msgs,userMsg];
    setMsgs(m=>[...m,userMsg]); setVal(""); setSending(true); setTyping(true);
    fetch("/api/cellie",{method:"POST",headers:{"content-type":"application/json"},
      body:JSON.stringify({product,mode,messages:toApi(history),captured:cap})})
      .then(r=>r.json())
      .then(j=>{
        setTyping(false); setSending(false);
        if(j && j.reply) setMsgs(m=>[...m,{from:"bot",text:j.reply}]);
        if(j && j.captured && Object.keys(j.captured).length){ setCap(c=>({...c,...j.captured})); setBriefOpen(true); }
        if(j && j.action) setBrainAction(j.action);
      })
      .catch(()=>{ setTyping(false); setSending(false);
        setMsgs(m=>[...m,{from:"bot",text:"Sorry — I had a hiccup. Mind trying again?"}]); });
  }

  function runStep(i){
    setStep(i);setBotDone(false);setAnswered(false);
    const s=stepsRef.current[i];
    if(s && s.card==="slots") setBriefOpen(false); // give the calendar room

    const lines=(s&&s.bot)||[];
    let k=0;
    const tick=()=>{
      if(k>=lines.length){setBotDone(true);return;}
      setTyping(true);
      const line=lines[k];
      const delay=Math.min(420+line.length*8,1250);
      T(()=>{
        setTyping(false);
        setMsgs(m=>[...m,{from:"bot",text:line}]);
        k++;
        T(tick,300);
      },delay);
    };
    tick();
  }

  function answer(text){
    const s=stepsRef.current[step];
    setMsgs(m=>[...m,{from:"user",text}]);
    if(s.capture){setCap(c=>({...c,[s.capture]:text}));setBriefOpen(true);}
    setAnswered(true);
    T(()=>runStep(step+1),300);
  }

  // Mode A — soft reply that does NOT advance the machine (stays on trial CTA)
  function softReply(userText,botText){
    setMsgs(m=>[...m,{from:"user",text:userText}]);
    setTyping(true);
    T(()=>{setTyping(false);setMsgs(m=>[...m,{from:"bot",text:botText}]);},650);
  }
  function mentionUseCase(chip){
    const name=NAMES[product.id]||"GMR";
    softReply(chip,`${chip} is one of the things ${name} handles. The fastest way to feel it is to try it yourself — free, no card. Want the whole suite instead? I can set up a call.`);
  }
  function startTrial(){
    const url=APP_URL[product.id];
    if(!url){ start("B"); return; } // gmr has no single-app trial → suite call
    const u=url+(url.indexOf("?")>=0?"&":"?")+"cellie_sid="+encodeURIComponent(sid);
    window.open(u,"_blank","noopener");
  }
  function bookCall(){
    const f=computeFit(cap);
    window.open(buildBookUrl({cellie_session_id:sid,cellie_app:product.id,cellie_role:cap.role,cellie_company:cap.company,cellie_team_size:cap.team_size,cellie_use_case:cap.usecase,cellie_apps_wanted:cap.apps_wanted,cellie_timeline:cap.timeline,cellie_region:cap.region,cellie_fit:f.label}),"_blank","noopener");
  }

  function onSend(){
    const t=val.trim();
    if(!t) return;
    if(brain){ if(!sending) brainSend(t); return; }   // brain: free conversation
    if(!botDone||answered) return;
    const s=stepsRef.current[step];
    if(s && s.card==="trialcta"){ setVal(""); softReply(t,"Good question — I'll have the full answer in a moment. Meanwhile the quickest way to see is the free trial. Looking at the whole suite? I can line up a call."); return; }
    if(s && s.card){setVal("");return;}
    if(s && s.input==="email" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(t)){
      setMsgs(m=>[...m,{from:"user",text:t}]);setVal("");
      T(()=>{setTyping(true);T(()=>{setTyping(false);
        setMsgs(m=>[...m,{from:"bot",text:"Hmm — that doesn't look like a work email. Mind trying again?"}]);},650);},220);
      return;
    }
    setVal("");answer(t);
  }

  const cur=step>=0?stepsRef.current[step]:null;
  const fit=computeFit(cap);
  const hasBrief=Object.keys(cap).filter(k=>k!=="email").length>0;
  const placeholder=cur&&cur.input==="email"?"name@company.com":(brain?"Ask me anything…":(mode==="A"?"Ask me anything…":"Type a message…"));

  return (
    <div className="cellie">
      {!open && (
        <React.Fragment>
          {showNudge && (
            <div className="cellie-nudge">
              <span>Hey — I'm <b>Cellie</b>. Want to see what we do?</span>
              <span className="x" onClick={(e)=>{e.stopPropagation();setShowNudge(false);}}>{Sv.x}</span>
            </div>
          )}
          <button className="cellie-launch" onClick={()=>openPanel()} aria-label="Chat with Cellie">
            <CellieFace s={30}/><span className="pog"></span>
          </button>
        </React.Fragment>
      )}

      {open && (
        <div className="cellie-panel" role="dialog" aria-label="Chat with Cellie">
          <div className="sh">
            <span className="ava"><CellieFace s={26}/><span className="pog"></span></span>
            <span className="id">
              <span className="nm">Cellie</span>
              <span className="ro">Account Executive <span className="on"><i></i>online</span></span>
            </span>
            <button className="cl" onClick={()=>setOpen(false)} aria-label="Close">{Sv.close}</button>
          </div>

          {/* Cellie collects qualification silently (used for the booking) — the
              "Your brief" summary is intentionally NOT shown to the prospect. */}

          <div className="sb" ref={bodyRef}>
            {msgs.map((m,i)=>(
              <div className={"msg "+m.from} key={i}>
                {m.from==="bot" && <span className="mava"><CellieFace s={16}/></span>}
                <span className="bubble">{m.from==="bot" ? <Rich text={m.text}/> : m.text}</span>
              </div>
            ))}
            {typing && (
              <div className="typing">
                <span className="mava"><CellieFace s={16}/></span>
                <span className="dots"><i></i><i></i><i></i></span>
              </div>
            )}

            {cur && botDone && cur.card==="trialcta" && (
              <div className="cta-card">
                {(USECASES[product.id]||[]).length>0 && (
                  <div className="chips">
                    {(USECASES[product.id]||[]).map(c=>(
                      <button className="chip" key={c} onClick={()=>mentionUseCase(c)}>{c}</button>
                    ))}
                  </div>
                )}
                <button className="cta-primary" onClick={startTrial}>{Sv.spark} Start free trial</button>
                <button className="cta-ghost" onClick={()=>start("B")}>I want the whole suite {Sv.arrow}</button>
                <div className="cta-foot">149K tokens · no card · full access to standard features</div>
              </div>
            )}

            {cur && botDone && !answered && cur.chips && (
              <div className="chips">
                {cur.chips.map(c=>(
                  <button className="chip" key={c} onClick={()=>answer(c)}>{c}</button>
                ))}
              </div>
            )}

            {cur && botDone && cur.card==="slots" && (
              <div className="cta-card">
                <button className="cta-primary" onClick={bookCall}>{Sv.cal} Book a 30-min call {Sv.arrow}</button>
                <div className="cta-foot">A quick intro with our team</div>
              </div>
            )}

            {/* brain-driven CTAs (Opus decides when) */}
            {brain && brainAction==="trial" && (
              <div className="cta-card">
                <button className="cta-primary" onClick={startTrial}>{Sv.spark} Start free trial</button>
                <div className="cta-foot">149K tokens · no card · full access to standard features</div>
              </div>
            )}
            {brain && brainAction==="book" && (
              <div className="cta-card">
                <button className="cta-primary" onClick={bookCall}>{Sv.cal} Book a 30-min call {Sv.arrow}</button>
                <div className="cta-foot">A quick intro with our team</div>
              </div>
            )}
          </div>

          <div className="sf">
            <input
              value={val}
              onChange={e=>setVal(e.target.value)}
              onKeyDown={e=>{if(e.key==="Enter")onSend();}}
              placeholder={placeholder}
              aria-label="Message"
            />
            <button className="send" onClick={onSend} disabled={!val.trim()||sending} aria-label="Send">{Sv.send}</button>
          </div>
        </div>
      )}
    </div>
  );
}
