import React from "react";
import ReactDOM from "react-dom/client";
import { useState, useEffect, useRef, useCallback } from "react";
import {
  Play, Pause, RotateCcw, Edit3, Save, ChevronDown, ChevronRight,
  Plus, Trash2, CheckCircle, XCircle, GitBranch,
  BookOpen, X, AlertCircle, Shield,
  MessageSquare, Phone, Bot, LogIn, Eye, EyeOff,
  Lock, User, Volume2, VolumeX, Mic, Send,
  PhoneCall, PhoneOff, Radio, Wifi, Signal, Delete, Smile,
  Upload, Image, FileJson, ArrowRight, Download, FlaskConical,
  BarChart2, MicOff, GitCompare
} from "lucide-react";

const FL=document.createElement("link");FL.rel="stylesheet";FL.href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400&display=swap";document.head.appendChild(FL);

const DS={
  font:"'Montserrat',sans-serif",
  color:{
    deepBlue:"#001A7B",midBlue:"#3048B1",brightBlue:"#0BBBEF",
    cyan50:"#DDF4FC",cyan100:"#A9E1F8",cyan200:"#6DCDF3",
    purple:"#A259FE",purple100:"#D9BCFD",green:"#09CF82",
    neutral100:"#F6F6F6",neutral200:"#F0F0F0",neutral300:"#E5DEE7",neutral400:"#ADAEAF",neutral700:"#655F67",white:"#FFFFFF",
    success:"#35C759",successLight:"#C0EBC5",
    error:"#F5434E",errorLight:"#FFCAD2",
    warning:"#FFC700",warningLight:"#FFEBAF",
    info:"#2445F2",infoLight:"#C7C9FC",
    waDark:"#075E54",waPanel:"#128C7E",waLight:"#25D366",waBubbleOut:"#DCF8C6",waBubbleIn:"#FFFFFF",
  },
  radius:{xs:4,sm:8,md:12,lg:16,xl:20,full:999},
  space:{xs:8,sm:12,md:16,lg:24,xl:32},
  shadow:{A1:"0 1px 3px rgba(0,26,123,0.08)",A2:"0 4px 12px rgba(0,26,123,0.12)",B1:"0 8px 24px rgba(0,26,123,0.14)",B2:"0 16px 40px rgba(0,26,123,0.18)"},
};

const TYPE_THEME={
  IVR:{gradient:`linear-gradient(135deg,${DS.color.deepBlue},${DS.color.midBlue},${DS.color.brightBlue})`,panelBg:DS.color.cyan50,lcdBg:DS.color.white,lcdBorder:DS.color.cyan200,keyBg:"rgba(11,187,239,0.07)",keyBorder:DS.color.cyan200,keyText:DS.color.deepBlue,keySubText:DS.color.midBlue,accent:DS.color.brightBlue,accentDark:DS.color.midBlue,logBg:DS.color.cyan50,logText:DS.color.deepBlue,validText:DS.color.midBlue,lcdText:DS.color.deepBlue,lcdSub:DS.color.midBlue,desc:"IVR"},
  Chatbot:{gradient:`linear-gradient(135deg,${DS.color.deepBlue},${DS.color.midBlue})`,accent:DS.color.brightBlue,accentDark:DS.color.midBlue,desc:"Chatbot"},
  Voicebot:{gradient:`linear-gradient(135deg,${DS.color.deepBlue},${DS.color.purple})`,panelBg:"#F5F3FF",lcdBg:DS.color.white,lcdBorder:DS.color.purple100,keyBg:"rgba(162,89,254,0.07)",keyBorder:DS.color.purple100,keyText:DS.color.deepBlue,keySubText:DS.color.purple,accent:DS.color.purple,accentDark:"#7B2FE5",optBg:"rgba(162,89,254,0.07)",optBorder:DS.color.purple100,labelText:DS.color.deepBlue,msgText:"#4A1D96",logBg:"rgba(162,89,254,0.05)",logText:DS.color.deepBlue,desc:"Voicebot"},
  WhatsApp:{gradient:`linear-gradient(135deg,${DS.color.waDark},${DS.color.waPanel},${DS.color.waLight})`,accent:DS.color.waLight,accentDark:DS.color.waPanel,desc:"WhatsApp"},
};

const NODE_ST={
  start:   {bg:DS.color.cyan50,       border:DS.color.brightBlue,text:DS.color.deepBlue},
  action:  {bg:"#EEF2FF",             border:DS.color.midBlue,   text:DS.color.deepBlue},
  decision:{bg:DS.color.warningLight, border:DS.color.warning,   text:"#7A4F00"},
  success: {bg:DS.color.successLight, border:DS.color.success,   text:"#1A4D2E"},
  error:   {bg:DS.color.errorLight,   border:DS.color.error,     text:"#7F1D1D"},
};

const VOICE_PROFILES=[
  {id:"male",  label:"Masculina",icon:"🎙️",pitch:0.85,rate:0.9},
  {id:"female",label:"Femenina", icon:"💬",pitch:1.1, rate:1.0},
  {id:"robot", label:"Robótica", icon:"🤖",pitch:0.5, rate:0.75},
];

let _voices=[];
const loadVoices=()=>{if(window.speechSynthesis)_voices=window.speechSynthesis.getVoices();};
if(window.speechSynthesis){loadVoices();window.speechSynthesis.addEventListener("voiceschanged",loadVoices);}
function getVoice(id){const a=_voices.length?_voices:(window.speechSynthesis?.getVoices()||[]);const g=a.filter(v=>v.name.toLowerCase().includes("google")&&v.lang.startsWith("es"));if(g.length){if(id==="female")return g.find(v=>/female|2/i.test(v.name))||g[0];if(id==="male")return g.find(v=>/male|1/i.test(v.name))||g[g.length-1];return g[0];}return a.find(v=>v.lang.startsWith("es"))||null;}
function speak(text,vp,onEnd){if(!window.speechSynthesis)return;window.speechSynthesis.cancel();const u=new SpeechSynthesisUtterance(text);u.lang="es-ES";u.pitch=vp.pitch;u.rate=vp.rate;u.volume=1;const v=getVoice(vp.id);if(v)u.voice=v;if(onEnd)u.onend=onEnd;setTimeout(()=>window.speechSynthesis.speak(u),80);}

const USERS=[
  {id:1,name:"Admin Principal",role:"admin",     initials:"AP",color:DS.color.deepBlue,username:"admin",    password:"dsxp2026"},
  {id:2,name:"Diseñadora UX",  role:"designer",  initials:"DX",color:DS.color.green,   username:"ux",       password:"ux123"},
  {id:3,name:"Tester 1",       role:"tester",    initials:"T1",color:DS.color.error,   username:"tester1",  password:"test1"},
  {id:4,name:"Tester 2",       role:"tester",    initials:"T2",color:DS.color.purple,  username:"tester2",  password:"test2"},
  {id:5,name:"Operador IVR",   role:"operator",  initials:"OP",color:DS.color.midBlue, username:"operador", password:"ivr123"},
  {id:6,name:"Supervisor QA",  role:"supervisor",initials:"SQ",color:DS.color.warning, username:"supervisor",password:"qa2024"},
];

function useTimer(){const[t,setT]=useState(0);const[on,setOn]=useState(false);const ref=useRef();useEffect(()=>{if(on)ref.current=setInterval(()=>setT(x=>x+1),1000);else clearInterval(ref.current);return()=>clearInterval(ref.current);},[on]);const fmt=s=>`${String(Math.floor(s/60)).padStart(2,"0")}:${String(s%60).padStart(2,"0")}`;return{fmt:fmt(t),t,running:on,start:()=>setOn(true),pause:()=>setOn(false),reset:()=>{setOn(false);setT(0);}};}
const normOpts=opts=>(opts||[]).map(o=>typeof o==="string"?{label:o,next:""}:o);
function dlJSON(data,fn){const b=new Blob([JSON.stringify(data,null,2)],{type:"application/json"});const u=URL.createObjectURL(b);const a=document.createElement("a");a.href=u;a.download=fn;a.click();URL.revokeObjectURL(u);}
function dlCSV(rows,fn){const h=Object.keys(rows[0]||{});const csv=[h.join(","),...rows.map(r=>h.map(k=>`"${(r[k]||"").toString().replace(/"/g,'""')}"`).join(","))].join("\n");const b=new Blob(["\uFEFF"+csv],{type:"text/csv;charset=utf-8"});const u=URL.createObjectURL(b);const a=document.createElement("a");a.href=u;a.download=fn;a.click();URL.revokeObjectURL(u);}

/* ─── ATOMS ────────────────────────────────────────────────────────────────── */
function Btn({children,variant="filled",onClick,disabled,full,style={}}){
  const base={fontFamily:DS.font,fontWeight:600,borderRadius:DS.radius.full,cursor:disabled?"default":"pointer",display:"flex",alignItems:"center",justifyContent:"center",gap:6,border:"none",transition:"all 0.15s",fontSize:13,padding:"9px 20px",width:full?"100%":undefined,...style};
  const v={
    filled:{background:`linear-gradient(135deg,${DS.color.midBlue},${DS.color.deepBlue})`,color:DS.color.white,boxShadow:DS.shadow.A2},
    ghost:{background:"transparent",color:DS.color.midBlue,border:`1px solid ${DS.color.cyan200}`},
    success:{background:DS.color.successLight,color:"#1A4D2E",border:`1px solid ${DS.color.success}`},
    danger:{background:DS.color.errorLight,color:DS.color.error,border:`1px solid ${DS.color.error}`},
  }[variant]||{};
  return <button onClick={onClick} disabled={disabled} style={{...base,...v,opacity:disabled?0.5:1}}>{children}</button>;
}
function Tag({label,color=DS.color.brightBlue}){return <span style={{fontSize:10,padding:"2px 8px",borderRadius:DS.radius.full,border:`1px solid ${color}`,color,fontFamily:DS.font,fontWeight:600,whiteSpace:"nowrap"}}>{label}</span>;}
function Toast({type="info",children}){const c={success:{bg:DS.color.successLight,b:DS.color.success,t:"#1A4D2E"},error:{bg:DS.color.errorLight,b:DS.color.error,t:DS.color.error},warning:{bg:DS.color.warningLight,b:DS.color.warning,t:"#7A4F00"},info:{bg:DS.color.infoLight,b:DS.color.info,t:DS.color.info}}[type];return <div style={{background:c.bg,border:`1px solid ${c.b}`,borderRadius:DS.radius.sm,padding:"7px 10px",fontSize:11,color:c.t,display:"flex",alignItems:"center",gap:5,fontFamily:DS.font,fontWeight:500,marginBottom:DS.space.xs}}><AlertCircle size={12}/>{children}</div>;}
function Overlay({onClose,children}){return <div style={{position:"fixed",inset:0,background:"rgba(0,26,123,0.5)",backdropFilter:"blur(4px)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:9999}} onClick={e=>{if(e.target===e.currentTarget)onClose();}}>{children}</div>;}
function Card({children,style={}}){return <div style={{background:DS.color.white,border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.lg,padding:DS.space.lg,boxShadow:DS.shadow.A2,...style}}>{children}</div>;}

/* ─── AVATAR UPLOADER ─────────────────────────────────────────────────────── */
function AvatarUploader({avatar,onUpload,size=34}){
  const inp=useRef();
  return(
    <div style={{display:"flex",alignItems:"center",gap:DS.space.xs,flexShrink:0}}>
      <div style={{width:size,height:size,borderRadius:DS.radius.full,background:DS.color.neutral200,overflow:"hidden",border:`2px solid ${DS.color.neutral300}`,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}} onClick={()=>inp.current.click()}>
        {avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="av"/>:<Image size={size*0.38} style={{color:DS.color.neutral400}}/>}
      </div>
      <button onClick={()=>inp.current.click()} style={{fontSize:10,padding:"3px 8px",border:`1px dashed ${DS.color.brightBlue}`,borderRadius:DS.radius.full,background:"none",cursor:"pointer",color:DS.color.midBlue,fontFamily:DS.font,fontWeight:600,display:"flex",alignItems:"center",gap:3}}><Upload size={9}/>Foto</button>
      <input ref={inp} type="file" accept="image/*" style={{display:"none"}} onChange={e=>{const f=e.target.files?.[0];if(!f)return;const r=new FileReader();r.onload=ev=>onUpload(ev.target.result);r.readAsDataURL(f);e.target.value="";}}/>
    </div>
  );
}

/* ─── KEYPAD ─────────────────────────────────────────────────────────────── */
const KEYS=[["1","2","3"],["4","5","6"],["7","8","9"],["*","0","#"]];
const KSUB={"1":"","2":"ABC","3":"DEF","4":"GHI","5":"JKL","6":"MNO","7":"PQRS","8":"TUV","9":"WXYZ","0":"+","*":"","#":""};
function PhoneKeypad({onPress,disabled,kbg,kbd,kt,ks}){
  return(
    <div style={{display:"flex",flexDirection:"column",gap:DS.space.xs,padding:`0 ${DS.space.xs}px`}}>
      {KEYS.map((row,ri)=>(
        <div key={ri} style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:DS.space.xs}}>
          {row.map(k=>(
            <button key={k} onClick={()=>!disabled&&onPress(k)} disabled={disabled}
              style={{background:disabled?"rgba(0,0,0,0.03)":kbg,border:`1px solid ${disabled?"rgba(0,0,0,0.08)":kbd}`,borderRadius:DS.radius.md,padding:"10px 4px 8px",cursor:disabled?"default":"pointer",display:"flex",flexDirection:"column",alignItems:"center",gap:1,fontFamily:DS.font,transition:"all 0.1s"}}
              onMouseDown={e=>{if(!disabled)e.currentTarget.style.transform="scale(0.93)";}}
              onMouseUp={e=>{e.currentTarget.style.transform="scale(1)";}}
              onMouseLeave={e=>{e.currentTarget.style.transform="scale(1)";}}>
              <span style={{fontSize:22,fontWeight:300,color:disabled?"#ccc":kt,lineHeight:1}}>{k}</span>
              <span style={{fontSize:7,color:disabled?"#ddd":ks,letterSpacing:1.5}}>{KSUB[k]}</span>
            </button>
          ))}
        </div>
      ))}
    </div>
  );
}

/* ─── EDIT NODE MODAL ─────────────────────────────────────────────────────── */
function EditNodeModal({node,onSave,onClose}){
  const[f,setF]=useState({...node,options:[...normOpts(node.options)]});
  return(
    <Overlay onClose={onClose}>
      <Card style={{width:430,maxHeight:"85vh",overflowY:"auto"}}>
        <div style={{display:"flex",justifyContent:"space-between",marginBottom:DS.space.md}}>
          <h3 style={{margin:0,fontSize:16,fontWeight:700,color:DS.color.deepBlue}}>Editar nodo</h3>
          <button onClick={onClose} style={{background:"none",border:"none",cursor:"pointer",color:DS.color.neutral400}}><X size={16}/></button>
        </div>
        {[["Etiqueta","label","input"],["Mensaje","message","textarea"]].map(([lbl,key,t])=>(
          <div key={key} style={{marginBottom:DS.space.sm}}>
            <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:3,fontWeight:600}}>{lbl}</label>
            {t==="textarea"?<textarea value={f[key]} onChange={e=>setF(x=>({...x,[key]:e.target.value}))} rows={3} style={{width:"100%",boxSizing:"border-box",fontFamily:DS.font,fontSize:12,padding:DS.space.xs,resize:"vertical",border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,color:DS.color.deepBlue}}/>:<input value={f[key]} onChange={e=>setF(x=>({...x,[key]:e.target.value}))} style={{width:"100%",boxSizing:"border-box",border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,color:DS.color.deepBlue,padding:`${DS.space.xs}px`,fontFamily:DS.font}}/>}
          </div>
        ))}
        <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:3,fontWeight:600}}>Tipo</label>
        <select value={f.type} onChange={e=>setF(x=>({...x,type:e.target.value}))} style={{width:"100%",marginBottom:DS.space.sm,border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,color:DS.color.deepBlue,padding:`${DS.space.xs}px`,fontFamily:DS.font}}>
          {Object.keys(NODE_ST).map(t=><option key={t} value={t}>{t}</option>)}
        </select>
        <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:3,fontWeight:600}}>Opciones</label>
        {f.options.map((o,i)=>(
          <div key={i} style={{display:"flex",gap:DS.space.xs,marginBottom:DS.space.xs,alignItems:"center"}}>
            <input value={o.label||o} onChange={e=>setF(x=>({...x,options:x.options.map((v,j)=>j===i?{...(typeof v==="object"?v:{label:v}),label:e.target.value}:v)}))} placeholder="Texto" style={{flex:1,border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,color:DS.color.deepBlue,padding:"5px 8px",fontFamily:DS.font,fontSize:12}}/>
            <button onClick={()=>setF(x=>({...x,options:x.options.filter((_,j)=>j!==i)}))} style={{background:"none",border:`1px solid ${DS.color.error}`,borderRadius:DS.radius.sm,cursor:"pointer",color:DS.color.error,padding:"0 7px"}}><Trash2 size={11}/></button>
          </div>
        ))}
        <button onClick={()=>setF(x=>({...x,options:[...x.options,{label:"Nueva opción",next:""}]}))} style={{fontSize:11,padding:"4px 10px",border:`1px dashed ${DS.color.brightBlue}`,borderRadius:DS.radius.sm,background:"none",cursor:"pointer",display:"flex",alignItems:"center",gap:4,color:DS.color.midBlue,fontFamily:DS.font,fontWeight:600}}><Plus size={11}/>Agregar opción</button>
        <div style={{display:"flex",gap:DS.space.xs,marginTop:DS.space.md,justifyContent:"flex-end"}}>
          <Btn variant="ghost" onClick={onClose}>Cancelar</Btn>
          <Btn variant="success" onClick={()=>onSave({...f,options:normOpts(f.options)})}><Save size={11}/>Guardar</Btn>
        </div>
      </Card>
    </Overlay>
  );
}

/* ─── TREE VIEW ───────────────────────────────────────────────────────────── */
function TreeView({nodes,setNodes,editMode,canEdit,testName}){
  const[editing,setEditing]=useState(null);
  const[activeId,setActiveId]=useState(null);
  const[importErr,setImportErr]=useState("");
  const fileRef=useRef();
  const activeNode=nodes.find(n=>n.id===activeId)||nodes[0]||null;

  const importFlow=e=>{
    const f=e.target.files?.[0];if(!f)return;
    const r=new FileReader();
    r.onload=ev=>{
      try{
        const raw=JSON.parse(ev.target.result);
        const arr=Array.isArray(raw)?raw:(raw.nodes||raw.steps||null);
        if(!arr||!Array.isArray(arr))throw new Error();
        const nd=arr.map((n,i)=>({id:n.id||`imp_${i}`,label:n.label||n.name||`Nodo ${i+1}`,type:n.type||"action",message:n.message||n.text||"",options:normOpts(n.options||n.choices||[])}));
        setNodes(nd);setActiveId(nd[0]?.id||null);setImportErr("");
      }catch{setImportErr("JSON inválido. Asegúrate que sea un array de nodos.");}
    };r.readAsText(f);e.target.value="";
  };

  return(
    <div style={{height:"100%",display:"flex",flexDirection:"column",background:DS.color.neutral100,fontFamily:DS.font}}>
      {editing&&<EditNodeModal node={editing} onSave={upd=>{setNodes(p=>p.map(n=>n.id===upd.id?upd:n));setEditing(null);}} onClose={()=>setEditing(null)}/>}
      <div style={{padding:`${DS.space.xs}px ${DS.space.sm}px`,borderBottom:`1px solid ${DS.color.neutral200}`,display:"flex",alignItems:"center",gap:DS.space.xs,flexShrink:0,background:DS.color.white,flexWrap:"wrap"}}>
        {canEdit&&editMode&&<button onClick={()=>{const id=`n${Date.now()}`;setNodes(p=>[...p,{id,label:"Nuevo nodo",type:"action",message:"",options:[]}]);setActiveId(id);}} style={{fontSize:10,padding:"4px 9px",border:`1px solid ${DS.color.brightBlue}`,borderRadius:DS.radius.sm,background:DS.color.cyan50,cursor:"pointer",color:DS.color.midBlue,display:"flex",alignItems:"center",gap:3,fontFamily:DS.font,fontWeight:600}}><Plus size={10}/>Nodo</button>}
        {canEdit&&editMode&&<button onClick={()=>fileRef.current.click()} style={{fontSize:10,padding:"4px 9px",border:`1px dashed ${DS.color.purple}`,borderRadius:DS.radius.sm,background:"rgba(162,89,254,0.06)",cursor:"pointer",color:DS.color.purple,display:"flex",alignItems:"center",gap:3,fontFamily:DS.font,fontWeight:600}}><FileJson size={10}/>Importar JSON</button>}
        <button onClick={()=>dlJSON({name:testName,nodes},`${testName||"flujo"}_arbol.json`)} style={{fontSize:10,padding:"4px 9px",border:`1px solid ${DS.color.success}`,borderRadius:DS.radius.sm,background:DS.color.successLight,cursor:"pointer",color:"#1A4D2E",display:"flex",alignItems:"center",gap:3,fontFamily:DS.font,fontWeight:600}}><Download size={10}/>Descargar JSON</button>
        <input ref={fileRef} type="file" accept=".json" style={{display:"none"}} onChange={importFlow}/>
        {importErr&&<span style={{fontSize:10,color:DS.color.error}}>{importErr}</span>}
      </div>
      <div style={{flex:1,overflow:"hidden",display:"flex"}}>
        <div style={{width:165,flexShrink:0,overflowY:"auto",borderRight:`1px solid ${DS.color.neutral200}`,padding:DS.space.xs,background:DS.color.white}}>
          {nodes.map((nd,i)=>{
            const s=NODE_ST[nd.type]||NODE_ST.action;const isA=nd.id===activeId||(activeId===null&&i===0);
            return(
              <div key={nd.id} onClick={()=>setActiveId(nd.id)} style={{display:"flex",alignItems:"center",gap:5,padding:"6px 8px",borderRadius:DS.radius.sm,background:isA?s.bg:"none",border:isA?`1.5px solid ${s.border}`:"1px solid transparent",cursor:"pointer",marginBottom:3}}>
                <div style={{width:16,height:16,borderRadius:DS.radius.full,background:s.bg,border:`2px solid ${s.border}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:8,fontWeight:700,color:s.text,flexShrink:0}}>{i+1}</div>
                <div style={{flex:1,overflow:"hidden"}}><div style={{fontSize:11,fontWeight:isA?700:500,color:isA?s.text:DS.color.neutral700,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{nd.label}</div><div style={{fontSize:9,color:isA?s.text:DS.color.neutral400}}>{nd.type}</div></div>
                {canEdit&&editMode&&<button onClick={e=>{e.stopPropagation();setEditing({...nd,options:normOpts(nd.options)});}} style={{background:"none",border:"none",cursor:"pointer",color:s.text,padding:2,opacity:0.7}}><Edit3 size={9}/></button>}
              </div>
            );
          })}
        </div>
        {activeNode&&(()=>{
          const nd=activeNode;const s=NODE_ST[nd.type]||NODE_ST.action;const opts=normOpts(nd.options);
          return(
            <div style={{flex:1,overflowY:"auto",padding:DS.space.md}}>
              <div style={{background:s.bg,border:`1.5px solid ${s.border}`,borderRadius:DS.radius.md,padding:DS.space.md,marginBottom:DS.space.md,boxShadow:DS.shadow.A2}}>
                <div style={{display:"flex",alignItems:"center",gap:DS.space.xs,marginBottom:DS.space.xs}}>
                  <Tag label={nd.type} color={s.border}/>
                  <span style={{fontSize:13,fontWeight:700,color:s.text,flex:1}}>{nd.label}</span>
                  {canEdit&&editMode&&<>
                    <button onClick={()=>setEditing({...nd,options:normOpts(nd.options)})} style={{background:"none",border:`1px solid ${s.border}`,borderRadius:DS.radius.sm,cursor:"pointer",padding:"3px 7px",fontSize:10,color:s.text,display:"flex",alignItems:"center",gap:3,fontFamily:DS.font,fontWeight:600}}><Edit3 size={9}/>Editar</button>
                    <button onClick={()=>{setNodes(p=>p.filter(x=>x.id!==nd.id));setActiveId(nodes.find(n=>n.id!==nd.id)?.id||null);}} style={{background:"none",border:`1px solid ${DS.color.error}`,borderRadius:DS.radius.sm,cursor:"pointer",padding:"3px 7px",fontSize:10,color:DS.color.error,display:"flex",alignItems:"center",gap:3,fontFamily:DS.font,fontWeight:600}}><Trash2 size={9}/>Eliminar</button>
                  </>}
                </div>
                <p style={{fontSize:12,color:s.text,margin:0,lineHeight:1.6,opacity:0.9}}>{nd.message}</p>
              </div>
              {opts.length>0&&<div>
                <div style={{fontSize:11,color:DS.color.neutral700,fontWeight:700,marginBottom:DS.space.xs,display:"flex",alignItems:"center",gap:5}}><ArrowRight size={12} style={{color:DS.color.midBlue}}/>Rutas por opción</div>
                <div style={{display:"flex",flexDirection:"column",gap:DS.space.xs}}>
                  {opts.map((opt,i)=>{
                    const nextNode=nodes[nodes.findIndex(n=>n.id===nd.id)+1]||null;
                    const ds2=nextNode?(NODE_ST[nextNode.type]||NODE_ST.action):null;
                    return(
                      <div key={i} style={{display:"flex",alignItems:"center",gap:DS.space.xs}}>
                        <div style={{background:DS.color.white,border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,padding:"7px 12px",flex:1,display:"flex",alignItems:"center",gap:DS.space.xs,boxShadow:DS.shadow.A1}}>
                          <span style={{fontSize:12,fontWeight:600,color:DS.color.midBlue,minWidth:20}}>{i+1}.</span>
                          <span style={{fontSize:12,color:DS.color.deepBlue,flex:1}}>{typeof opt==="string"?opt:opt.label}</span>
                        </div>
                        <ChevronRight size={14} style={{color:DS.color.neutral400,flexShrink:0}}/>
                        {nextNode?(
                          <div onClick={()=>setActiveId(nextNode.id)} style={{background:ds2.bg,border:`1.5px solid ${ds2.border}`,borderRadius:DS.radius.sm,padding:"7px 12px",minWidth:110,cursor:"pointer",boxShadow:DS.shadow.A1}}>
                            <div style={{fontSize:9,color:ds2.text,fontWeight:600,opacity:0.7}}>{nextNode.type}</div>
                            <div style={{fontSize:11,fontWeight:700,color:ds2.text}}>{nextNode.label}</div>
                          </div>
                        ):(
                          <div style={{background:DS.color.neutral200,border:`1px dashed ${DS.color.neutral400}`,borderRadius:DS.radius.sm,padding:"7px 12px",minWidth:110}}>
                            <div style={{fontSize:11,color:DS.color.neutral400}}>Fin del flujo</div>
                          </div>
                        )}
                      </div>
                    );
                  })}
                </div>
              </div>}
            </div>
          );
        })()}
      </div>
    </div>
  );
}

/* ─── IVR SIMULATOR ───────────────────────────────────────────────────────── */
function IVRSimulator({nodes,timer,voiceProfile,voiceOn,onComplete,minimal}){
  const th=TYPE_THEME.IVR;
  const[step,setStep]=useState(0);const[input,setInput]=useState("");const[log,setLog]=useState([]);
  const[speaking,setSpeaking]=useState(false);const[callActive,setCallActive]=useState(false);const[flash,setFlash]=useState(null);
  const node=nodes[Math.min(step,nodes.length-1)];
  const reset=useCallback(()=>{setStep(0);setInput("");setLog([]);timer.reset();window.speechSynthesis?.cancel();setSpeaking(false);setCallActive(false);setFlash(null);},[]);
  useEffect(()=>reset(),[nodes]);
  useEffect(()=>{if(voiceOn&&node&&callActive){setSpeaking(true);speak(node.message,voiceProfile,()=>setSpeaking(false));}else{window.speechSynthesis?.cancel();setSpeaking(false);}},[step,voiceOn,callActive]);
  useEffect(()=>{if(node?.type==="success"&&callActive&&onComplete)onComplete(node);},[step,callActive]);
  const advance=choice=>{setFlash(choice);setTimeout(()=>{setLog(l=>[...l,{label:node.label,choice}]);if(!timer.running)timer.start();setFlash(null);setInput("");if(step<nodes.length-1)setStep(x=>x+1);},500);};
  const pressKey=k=>{
    const valid=normOpts(node?.options||[]).map(o=>o.label);
    if(k==="#"){if(input)advance(input);return;}
    setInput(p=>p+k);
    if(valid.includes(k))advance(k);
  };
  const pct=Math.round(((step+1)/nodes.length)*100);const vk=normOpts(node?.options||[]).map(o=>o.label);
  return(
    <div style={{display:"flex",flexDirection:"column",height:"100%",background:th.panelBg,fontFamily:DS.font}}>
      <div style={{padding:`${DS.space.sm}px ${DS.space.md}px ${DS.space.xs}px`,background:`linear-gradient(180deg,${DS.color.cyan50},transparent)`,flexShrink:0}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:DS.space.xs}}>
          <div style={{display:"flex",alignItems:"center",gap:5}}><Signal size={10} style={{color:th.accentDark}}/><Wifi size={10} style={{color:th.accentDark}}/><span style={{fontSize:9,color:th.accentDark,letterSpacing:1.5,fontWeight:700}}>IVR SYSTEM</span></div>
          <div style={{display:"flex",alignItems:"center",gap:6}}>{speaking&&<div style={{display:"flex",gap:2,alignItems:"flex-end"}}>{[8,13,10,16,8].map((h,i)=><div key={i} style={{width:2.5,height:h,background:th.accent,borderRadius:2}}/>)}</div>}<span style={{fontFamily:"monospace",fontSize:11,color:timer.running?DS.color.success:th.lcdSub,fontWeight:700}}>{timer.fmt}</span></div>
        </div>
        {!minimal&&<>
          <div style={{background:th.lcdBg,borderRadius:DS.radius.md,padding:`${DS.space.sm}px ${DS.space.md}px`,border:`1.5px solid ${th.lcdBorder}`,boxShadow:DS.shadow.A2,minHeight:86}}>
            <div style={{fontSize:9,color:th.lcdSub,letterSpacing:2,marginBottom:DS.space.xs,fontWeight:700}}>{callActive?node?.label?.toUpperCase():"MARCANDO..."}</div>
            <p style={{fontSize:12,color:callActive?th.lcdText:DS.color.neutral400,margin:`0 0 ${DS.space.xs}px`,lineHeight:1.65}}>{callActive?node?.message:"Presiona ☎ para iniciar"}</p>
            <div style={{fontFamily:"monospace",fontSize:20,color:th.accent,letterSpacing:5,minHeight:26,textAlign:"right",fontWeight:700}}>{flash?<span style={{color:DS.color.success}}>{flash}</span>:input}</div>
          </div>
          <div style={{marginTop:DS.space.xs,height:3,background:DS.color.cyan50,borderRadius:2}}><div style={{width:`${pct}%`,height:"100%",background:th.accent,borderRadius:2,transition:"width 0.4s"}}/></div>
          {callActive&&vk.length>0&&<div style={{marginTop:3,fontSize:9,color:th.validText,textAlign:"center",fontWeight:700}}>TECLAS: {vk.join(" · ")}</div>}
          {callActive&&<div style={{marginTop:2,fontSize:9,color:th.lcdSub,textAlign:"center"}}>Para ingresar números largos, finaliza con #</div>}
        </>}
        {minimal&&!callActive&&<div style={{textAlign:"center",fontSize:12,color:DS.color.neutral400,padding:`${DS.space.sm}px 0`}}>Presiona ☎ para iniciar</div>}
        {minimal&&callActive&&<div style={{marginTop:DS.space.xs,height:3,background:DS.color.cyan50,borderRadius:2}}><div style={{width:`${pct}%`,height:"100%",background:th.accent,borderRadius:2,transition:"width 0.4s"}}/></div>}
      </div>
      <div style={{flex:1,overflowY:"auto",padding:`${DS.space.sm}px ${DS.space.sm}px ${DS.space.xs}px`,display:"flex",flexDirection:"column",gap:DS.space.xs}}>
        {!minimal&&node?.type==="success"&&callActive&&<Toast type="success">Llamada finalizada exitosamente</Toast>}
        {!minimal&&log.length>0&&<div style={{background:th.logBg,borderRadius:DS.radius.sm,padding:`${DS.space.xs}px ${DS.space.sm}px`,border:`1px solid ${th.lcdBorder}`}}>
          <div style={{fontSize:8,color:th.logText,marginBottom:3,letterSpacing:1.5,fontWeight:700}}>REGISTRO</div>
          {log.map((e,i)=><div key={i} style={{fontSize:10,color:th.logText,display:"flex",gap:5,marginBottom:1,fontWeight:500}}><span style={{color:DS.color.success}}>▶</span>{e.label} → [{e.choice}]</div>)}
        </div>}
        <PhoneKeypad onPress={pressKey} disabled={!callActive||node?.type==="success"||node?.type==="error"} kbg={th.keyBg} kbd={th.keyBorder} kt={th.keyText} ks={th.keySubText}/>
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:DS.space.xs,padding:`0 ${DS.space.xs}px`,marginTop:4}}>
          <button onClick={()=>setInput(p=>p.slice(0,-1))} style={{background:th.keyBg,border:`1px solid ${th.keyBorder}`,borderRadius:DS.radius.sm,padding:"10px 4px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}><Delete size={16} style={{color:th.keyText}}/></button>
          {!callActive?<button onClick={()=>{setCallActive(true);if(!timer.running)timer.start();}} style={{background:DS.color.success,border:"none",borderRadius:DS.radius.sm,padding:"10px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 14px rgba(53,199,89,0.35)"}}><PhoneCall size={20} style={{color:"#fff"}}/></button>:<button onClick={reset} style={{background:DS.color.error,border:"none",borderRadius:DS.radius.sm,padding:"10px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 14px rgba(245,67,78,0.3)"}}><PhoneOff size={20} style={{color:"#fff"}}/></button>}
          <button onClick={timer.running?timer.pause:timer.start} style={{background:th.keyBg,border:`1px solid ${th.keyBorder}`,borderRadius:DS.radius.sm,padding:"10px 4px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>{timer.running?<Pause size={14} style={{color:th.keyText}}/>:<Play size={14} style={{color:th.keyText}}/>}</button>
        </div>
      </div>
    </div>
  );
}

/* ─── CHATBOT SIMULATOR ───────────────────────────────────────────────────── */
function ChatbotSim({nodes,timer,voiceProfile,voiceOn,msgs,setMsgs,step,setStep,avatar,onComplete}){
  const[speaking,setSpeaking]=useState(false);const[typing,setTyping]=useState(false);
  const[txt,setTxt]=useState("");const[waiting,setWaiting]=useState(false);
  const bottom=useRef();const inputRef=useRef();
  const node=nodes[Math.min(step,nodes.length-1)];
  const init=useRef(false);
  useEffect(()=>{if(!init.current&&msgs.length===0&&node){init.current=true;botSay(node);}},[]);
  const botSay=useCallback((n)=>{setTyping(true);setTimeout(()=>{setTyping(false);setMsgs(m=>[...m,{from:"bot",text:n.message,label:n.label,type:n.type,options:normOpts(n.options)}]);if(voiceOn){setSpeaking(true);speak(n.message,voiceProfile,()=>setSpeaking(false));}if(n.type==="success"&&onComplete)onComplete(n);setWaiting(true);setTimeout(()=>inputRef.current?.focus(),100);},800);},[voiceOn,voiceProfile,onComplete]);
  useEffect(()=>{bottom.current?.scrollIntoView({behavior:"smooth"});},[msgs,typing]);
  const send=text=>{if(!text.trim())return;setWaiting(false);setMsgs(m=>[...m,{from:"user",text}]);setTxt("");if(!timer.running)timer.start();const next=step+1;if(next<nodes.length){setStep(next);setTimeout(()=>botSay(nodes[next]),500);}};
  const c=DS.color;const lastOpts=msgs.length>0?normOpts(msgs[msgs.length-1]?.options||[]):[];
  return(
    <div style={{display:"flex",flexDirection:"column",height:"100%",background:c.neutral100,fontFamily:DS.font}}>
      <div style={{background:`linear-gradient(135deg,${c.deepBlue},${c.midBlue})`,padding:`${DS.space.sm}px ${DS.space.md}px`,display:"flex",alignItems:"center",gap:DS.space.sm,flexShrink:0,boxShadow:DS.shadow.A2}}>
        <div style={{width:36,height:36,borderRadius:c.full,overflow:"hidden",background:"rgba(255,255,255,0.15)",border:"2px solid rgba(255,255,255,0.3)",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
          {avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="bot"/>:<Bot size={18} style={{color:c.white}}/>}
        </div>
        <div><div style={{fontSize:13,fontWeight:700,color:c.white}}>Asistente</div><div style={{fontSize:10,color:c.cyan100,display:"flex",alignItems:"center",gap:4}}><div style={{width:5,height:5,borderRadius:DS.radius.full,background:speaking?c.warning:c.green}}/>{typing?"Escribiendo...":speaking?"Hablando...":"En línea"}</div></div>
        <div style={{marginLeft:"auto",display:"flex",alignItems:"center",gap:8}}><span style={{fontFamily:"monospace",fontSize:10,color:c.cyan100}}>{timer.fmt}</span><button onClick={timer.running?timer.pause:timer.start} style={{background:"none",border:"none",cursor:"pointer",color:c.cyan100}}>{timer.running?<Pause size={12}/>:<Play size={12}/>}</button></div>
      </div>
      <div style={{flex:1,overflowY:"auto",padding:`${DS.space.md}px ${DS.space.sm}px`,display:"flex",flexDirection:"column",gap:DS.space.sm}}>
        <div style={{textAlign:"center",fontSize:10,color:c.neutral400,background:"rgba(0,0,0,0.04)",borderRadius:DS.radius.full,padding:"3px 10px",alignSelf:"center",fontWeight:500}}>Conversación iniciada</div>
        {msgs.map((m,i)=>(
          <div key={i} style={{display:"flex",justifyContent:m.from==="user"?"flex-end":"flex-start"}}>
            {m.from==="bot"&&<div style={{width:26,height:26,borderRadius:DS.radius.full,overflow:"hidden",background:c.midBlue,display:"flex",alignItems:"center",justifyContent:"center",marginRight:6,flexShrink:0,alignSelf:"flex-end"}}>{avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="b"/>:<Bot size={12} style={{color:c.white}}/>}</div>}
            <div style={{maxWidth:"78%",background:m.from==="user"?`linear-gradient(135deg,${c.midBlue},${c.deepBlue})`:c.white,color:m.from==="user"?c.white:c.deepBlue,borderRadius:m.from==="user"?`${DS.radius.md}px ${DS.radius.md}px 4px ${DS.radius.md}px`:`${DS.radius.md}px ${DS.radius.md}px ${DS.radius.md}px 4px`,padding:`${DS.space.xs}px ${DS.space.sm}px`,fontSize:12,lineHeight:1.5,boxShadow:DS.shadow.A1}}>
              {m.from==="bot"&&<div style={{fontSize:9,color:c.brightBlue,fontWeight:700,marginBottom:2}}>{m.label?.toUpperCase()}</div>}
              {m.text}{m.type==="success"&&<div style={{fontSize:10,color:c.success,marginTop:3,display:"flex",alignItems:"center",gap:3}}><CheckCircle size={11}/>✓ Resuelto</div>}
            </div>
            {m.from==="user"&&<div style={{width:26,height:26,borderRadius:DS.radius.full,background:c.deepBlue,display:"flex",alignItems:"center",justifyContent:"center",marginLeft:6,flexShrink:0,alignSelf:"flex-end",fontSize:9,color:c.white,fontWeight:700}}>U</div>}
          </div>
        ))}
        {typing&&<div style={{display:"flex",alignItems:"flex-end",gap:6}}><div style={{width:26,height:26,borderRadius:DS.radius.full,overflow:"hidden",background:c.midBlue,display:"flex",alignItems:"center",justifyContent:"center"}}>{avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="b"/>:<Bot size={12} style={{color:c.white}}/>}</div><div style={{background:c.white,borderRadius:`${DS.radius.md}px ${DS.radius.md}px ${DS.radius.md}px 4px`,padding:"10px 14px",boxShadow:DS.shadow.A1}}><div style={{display:"flex",gap:4}}>{[0,1,2].map(i=><div key={i} style={{width:7,height:7,borderRadius:DS.radius.full,background:c.neutral400}}/>)}</div></div></div>}
        <div ref={bottom}/>
      </div>
      {!typing&&waiting&&lastOpts.length>0&&<div style={{padding:`${DS.space.xs}px ${DS.space.sm}px`,background:"rgba(255,255,255,0.9)",borderTop:`1px solid ${c.neutral200}`,display:"flex",flexWrap:"wrap",gap:6}}>
        {lastOpts.map((opt,i)=><button key={i} onClick={()=>send(typeof opt==="string"?opt:opt.label)} style={{fontSize:11,padding:"5px 12px",borderRadius:DS.radius.full,border:`1.5px solid ${c.brightBlue}`,background:c.white,color:c.midBlue,cursor:"pointer",fontFamily:DS.font,fontWeight:600}}>{typeof opt==="string"?opt:opt.label}</button>)}
      </div>}
      <div style={{padding:`${DS.space.sm}px`,background:c.white,borderTop:`1px solid ${c.neutral200}`,display:"flex",gap:DS.space.xs,alignItems:"flex-end",flexShrink:0}}>
        <textarea ref={inputRef} value={txt} onChange={e=>setTxt(e.target.value)} onKeyDown={e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();send(txt);}}} disabled={typing||!waiting} placeholder={typing?"Esperando...":waiting?"Escribe un mensaje...":"Iniciando..."} rows={1} style={{flex:1,resize:"none",border:`1px solid ${c.neutral300}`,borderRadius:DS.radius.xl,padding:`${DS.space.xs}px ${DS.space.sm}px`,fontSize:12,fontFamily:DS.font,background:typing?c.neutral100:c.white,color:c.deepBlue,outline:"none",maxHeight:80}}/>
        <button onClick={()=>send(txt)} disabled={!txt.trim()||typing} style={{width:36,height:36,borderRadius:DS.radius.full,background:txt.trim()&&!typing?`linear-gradient(135deg,${c.midBlue},${c.deepBlue})`:c.neutral200,border:"none",cursor:txt.trim()&&!typing?"pointer":"default",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}><Send size={14} style={{color:c.white}}/></button>
      </div>
    </div>
  );
}

/* ─── WHATSAPP SIMULATOR ──────────────────────────────────────────────────── */
const WA_SVG=`<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400'><rect width='100%' height='100%' fill='%23e5ddd5'/><g fill='none' stroke='%23c8bfb5' stroke-width='0.6' opacity='0.45'>${Array.from({length:6},(_,r)=>Array.from({length:5},(_,c)=>`<circle cx='${c*80+40}' cy='${r*70+35}' r='28'/>`).join("")).join("")}</g></svg>`;
const WA_BG=`data:image/svg+xml,${WA_SVG}`;

function WhatsAppSim({nodes,timer,msgs,setMsgs,step,setStep,avatar,onComplete}){
  const c=DS.color;const[typing,setTyping]=useState(false);const[txt,setTxt]=useState("");const[waiting,setWaiting]=useState(false);
  const bottom=useRef();const inputRef=useRef();const node=nodes[Math.min(step,nodes.length-1)];const init=useRef(false);
  useEffect(()=>{if(!init.current&&msgs.length===0&&node){init.current=true;botSay(node);}},[]);
  const botSay=useCallback((n)=>{setTyping(true);setTimeout(()=>{setTyping(false);setMsgs(m=>[...m,{from:"bot",text:n.message,label:n.label,type:n.type,options:normOpts(n.options)}]);if(n.type==="success"&&onComplete)onComplete(n);setWaiting(true);setTimeout(()=>inputRef.current?.focus(),100);},900);},[onComplete]);
  useEffect(()=>{bottom.current?.scrollIntoView({behavior:"smooth"});},[msgs,typing]);
  const send=text=>{if(!text.trim())return;setWaiting(false);setMsgs(m=>[...m,{from:"user",text}]);setTxt("");if(!timer.running)timer.start();const next=step+1;if(next<nodes.length){setStep(next);setTimeout(()=>botSay(nodes[next]),700);}};
  const now=new Date();const ts=`${now.getHours()}:${String(now.getMinutes()).padStart(2,"0")}`;
  const lastOpts=msgs.length>0?normOpts(msgs[msgs.length-1]?.options||[]):[];
  return(
    <div style={{display:"flex",flexDirection:"column",height:"100%",fontFamily:DS.font}}>
      <div style={{background:c.waDark,padding:`${DS.space.xs}px ${DS.space.md}px`,display:"flex",alignItems:"center",gap:DS.space.sm,flexShrink:0,boxShadow:"0 1px 3px rgba(0,0,0,0.25)"}}>
        <div style={{width:38,height:38,borderRadius:DS.radius.full,overflow:"hidden",background:c.waLight,border:"2px solid rgba(255,255,255,0.3)",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
          {avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="wa"/>:<Bot size={18} style={{color:c.white}}/>}
        </div>
        <div style={{flex:1}}><div style={{fontSize:13,fontWeight:700,color:c.white}}>Soporte Emtelco</div><div style={{fontSize:10,color:"rgba(255,255,255,0.75)",display:"flex",alignItems:"center",gap:4}}><div style={{width:5,height:5,borderRadius:DS.radius.full,background:c.waLight}}/>{typing?"escribiendo...":"en línea"}</div></div>
        <div style={{display:"flex",alignItems:"center",gap:10}}><span style={{fontFamily:"monospace",fontSize:10,color:"rgba(255,255,255,0.75)"}}>{timer.fmt}</span><button onClick={timer.running?timer.pause:timer.start} style={{background:"none",border:"none",cursor:"pointer",color:"rgba(255,255,255,0.75)"}}>{timer.running?<Pause size={12}/>:<Play size={12}/>}</button></div>
      </div>
      <div style={{flex:1,overflowY:"auto",padding:`${DS.space.sm}px`,display:"flex",flexDirection:"column",gap:DS.space.xs,backgroundImage:`url("${WA_BG}")`,backgroundSize:"400px 400px",backgroundRepeat:"repeat"}}>
        <div style={{alignSelf:"center",background:"rgba(255,255,255,0.85)",borderRadius:DS.radius.xl,padding:"3px 12px",fontSize:10,color:c.neutral700,boxShadow:DS.shadow.A1,fontWeight:500,marginBottom:4}}>HOY</div>
        {msgs.map((m,i)=>(
          <div key={i} style={{display:"flex",justifyContent:m.from==="user"?"flex-end":"flex-start",marginBottom:1}}>
            {m.from==="bot"&&<div style={{width:28,height:28,borderRadius:DS.radius.full,overflow:"hidden",background:c.waLight,display:"flex",alignItems:"center",justifyContent:"center",marginRight:5,flexShrink:0,alignSelf:"flex-end",border:"2px solid rgba(255,255,255,0.5)"}}>
              {avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="wa"/>:<Bot size={13} style={{color:c.white}}/>}
            </div>}
            <div style={{maxWidth:"75%",background:m.from==="user"?c.waBubbleOut:c.waBubbleIn,borderRadius:m.from==="user"?"12px 2px 12px 12px":"2px 12px 12px 12px",padding:"7px 10px 5px",fontSize:12,lineHeight:1.5,boxShadow:"0 1px 2px rgba(0,0,0,0.13)",color:"#111"}}>
              {m.from==="bot"&&<div style={{fontSize:9,color:c.waPanel,fontWeight:700,marginBottom:2}}>Soporte Emtelco</div>}
              <div style={{whiteSpace:"pre-line"}}>{m.text}</div>
              {m.type==="success"&&<div style={{fontSize:10,color:c.waPanel,marginTop:3,display:"flex",alignItems:"center",gap:3}}><CheckCircle size={10}/>✓ Resuelto</div>}
              <div style={{fontSize:9,color:c.neutral400,textAlign:"right",marginTop:3,display:"flex",alignItems:"center",justifyContent:"flex-end",gap:3}}>{ts}{m.from==="user"&&<span style={{color:"#53bdeb",fontSize:12}}>✓✓</span>}</div>
            </div>
          </div>
        ))}
        {typing&&<div style={{display:"flex",justifyContent:"flex-start",marginBottom:1}}>
          <div style={{width:28,height:28,borderRadius:DS.radius.full,overflow:"hidden",background:c.waLight,display:"flex",alignItems:"center",justifyContent:"center",marginRight:5,flexShrink:0,alignSelf:"flex-end"}}>{avatar?<img src={avatar} style={{width:"100%",height:"100%",objectFit:"cover"}} alt="wa"/>:<Bot size={13} style={{color:c.white}}/>}</div>
          <div style={{background:c.waBubbleIn,borderRadius:"2px 12px 12px 12px",padding:"10px 14px",boxShadow:"0 1px 2px rgba(0,0,0,0.1)"}}><div style={{display:"flex",gap:4}}>{[0,1,2].map(i=><div key={i} style={{width:7,height:7,borderRadius:DS.radius.full,background:"#aaa"}}/>)}</div></div>
        </div>}
        {!typing&&waiting&&lastOpts.length>0&&<div style={{display:"flex",flexWrap:"wrap",gap:6,justifyContent:"flex-end",marginTop:4}}>
          {lastOpts.map((opt,i)=><button key={i} onClick={()=>send(typeof opt==="string"?opt:opt.label)} style={{fontSize:11,padding:"6px 14px",borderRadius:DS.radius.full,border:`1.5px solid ${c.waPanel}`,background:c.white,color:c.waPanel,cursor:"pointer",fontFamily:DS.font,fontWeight:600,boxShadow:DS.shadow.A1}}>{typeof opt==="string"?opt:opt.label}</button>)}
        </div>}
        <div ref={bottom}/>
      </div>
      <div style={{padding:`${DS.space.xs}px ${DS.space.sm}px`,background:"#F0F0F0",borderTop:"1px solid #ddd",display:"flex",gap:DS.space.xs,alignItems:"flex-end",flexShrink:0}}>
        <div style={{width:34,height:34,borderRadius:DS.radius.full,background:c.neutral300,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}><Smile size={20} style={{color:c.neutral700}}/></div>
        <textarea value={txt} onChange={e=>setTxt(e.target.value)} ref={inputRef} onKeyDown={e=>{if(e.key==="Enter"&&!e.shiftKey){e.preventDefault();send(txt);}}} disabled={typing||!waiting} placeholder="Escribe un mensaje" rows={1} style={{flex:1,resize:"none",border:"none",borderRadius:DS.radius.xl,padding:"9px 14px",fontSize:13,fontFamily:DS.font,background:c.white,color:"#111",outline:"none",maxHeight:80,boxShadow:DS.shadow.A1}}/>
        <button onClick={()=>send(txt)} disabled={!txt.trim()||typing} style={{width:40,height:40,borderRadius:DS.radius.full,background:txt.trim()&&!typing?c.waLight:c.neutral300,border:"none",cursor:txt.trim()&&!typing?"pointer":"default",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
          {txt.trim()?<Send size={16} style={{color:c.white}}/>:<Mic size={16} style={{color:c.neutral700}}/>}
        </button>
      </div>
    </div>
  );
}

/* ─── VOICEBOT SIMULATOR (STT mejorado) ──────────────────────────────────── */
function VoicebotSim({nodes,timer,voiceProfile,voiceOn,onComplete,minimal}){
  const th=TYPE_THEME.Voicebot;
  const[step,setStep]=useState(0);const[input,setInput]=useState("");const[log,setLog]=useState([]);
  const[active,setActive]=useState(false);const[flash,setFlash]=useState(null);
  const[listening,setListening]=useState(false);const[liveText,setLiveText]=useState("");const[sttErr,setSttErr]=useState("");
  const recRef=useRef(null);const node=nodes[Math.min(step,nodes.length-1)];
  const reset=useCallback(()=>{setStep(0);setInput("");setLog([]);timer.reset();window.speechSynthesis?.cancel();setActive(false);setFlash(null);setListening(false);setLiveText("");setSttErr("");},[]);
  useEffect(()=>reset(),[nodes]);
  useEffect(()=>{if(node?.type==="success"&&active&&onComplete)onComplete(node);},[step,active]);

  const pressKey=k=>{setInput(p=>p+k);const valid=normOpts(node?.options||[]).map(o=>o.label);if(valid.includes(k))doSelect(k);};
  const doSelect=k=>{setFlash(k);setTimeout(()=>{setLog(l=>[...l,{label:node.label,choice:k}]);if(!timer.running)timer.start();setFlash(null);setInput("");if(step<nodes.length-1)setStep(x=>x+1);},500);};

  const startListening=()=>{
    const SR=window.SpeechRecognition||window.webkitSpeechRecognition;
    if(!SR){setSttErr("Reconocimiento de voz no disponible. Usa Chrome en escritorio.");return;}
    setSttErr("");setLiveText("");
    const rec=new SR();rec.lang="es-ES";rec.continuous=false;rec.interimResults=true;recRef.current=rec;
    rec.onstart=()=>setListening(true);
    rec.onresult=e=>{
      const interims=Array.from(e.results).map(r=>r[0].transcript).join(" ").toLowerCase().trim();
      setLiveText(interims);
    };
    rec.onend=()=>{
      setListening(false);
      const finalT=liveText;
      const opts=normOpts(node?.options||[]);
      // Buscar coincidencia por nombre exacto o número
      const match=opts.find(o=>{
        const lbl=(o.label||"").toLowerCase();
        if(finalT.includes(lbl))return true;
        const nums={"uno":"1","dos":"2","tres":"3","cuatro":"4","cinco":"5","seis":"6","siete":"7","ocho":"8","nueve":"9","cero":"0","asterisco":"*"};
        return Object.keys(nums).some(n=>finalT.includes(n)&&nums[n]===o.label);
      });
      if(match){setSttErr("");doSelect(match.label);}
      else if(finalT)setSttErr(`No reconocí una opción válida en: "${finalT}"`);
      setLiveText("");
    };
    rec.onerror=ev=>{setListening(false);setSttErr(ev.error==="not-allowed"?"Permiso de micrófono denegado. Actívalo en el navegador.":"Error al escuchar. Intenta de nuevo.");};
    rec.start();
  };
  const stopListening=()=>{recRef.current?.stop();setListening(false);};

  const pct=Math.round(((step+1)/nodes.length)*100);const vk=normOpts(node?.options||[]).map(o=>o.label);
  return(
    <div style={{display:"flex",flexDirection:"column",height:"100%",background:th.panelBg,fontFamily:DS.font}}>
      <div style={{padding:`${DS.space.sm}px ${DS.space.md}px ${DS.space.xs}px`,background:"linear-gradient(180deg,rgba(162,89,254,0.08),transparent)",flexShrink:0}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:DS.space.xs}}>
          <div style={{display:"flex",alignItems:"center",gap:5}}><Radio size={10} style={{color:th.accent}}/><span style={{fontSize:9,color:th.labelText,letterSpacing:1.5,fontWeight:700}}>VOICEBOT · NLU</span></div>
          <span style={{fontFamily:"monospace",fontSize:11,color:timer.running?DS.color.success:th.labelText,fontWeight:700}}>{timer.fmt}</span>
        </div>
        {!minimal&&<>
          <div style={{background:th.lcdBg,borderRadius:DS.radius.md,padding:`${DS.space.sm}px ${DS.space.md}px`,border:`1.5px solid ${th.lcdBorder}`,boxShadow:DS.shadow.A2,minHeight:86}}>
            <div style={{fontSize:9,color:th.labelText,letterSpacing:2,marginBottom:DS.space.xs,fontWeight:700}}>{active?node?.label?.toUpperCase():"ASISTENTE DE VOZ"}</div>
            <p style={{fontSize:12,color:active?th.msgText:DS.color.neutral400,margin:`0 0 ${DS.space.xs}px`,lineHeight:1.65}}>{active?node?.message:"Presiona ☎ para iniciar"}</p>
            {listening&&<div style={{fontSize:11,color:th.accent,display:"flex",alignItems:"center",gap:6,background:"rgba(162,89,254,0.08)",borderRadius:DS.radius.sm,padding:"4px 8px"}}>
              <div style={{width:8,height:8,borderRadius:DS.radius.full,background:DS.color.error,flexShrink:0}}/>
              <span style={{fontStyle:"italic",flex:1,color:th.msgText}}>{liveText||"Escuchando..."}</span>
            </div>}
            <div style={{fontFamily:"monospace",fontSize:20,color:th.accent,letterSpacing:5,minHeight:26,textAlign:"right",fontWeight:700}}>{flash?<span style={{color:DS.color.success}}>{flash}</span>:input}</div>
          </div>
          <div style={{marginTop:DS.space.xs,height:3,background:"rgba(162,89,254,0.12)",borderRadius:2}}><div style={{width:`${pct}%`,height:"100%",background:th.accent,borderRadius:2,transition:"width 0.4s"}}/></div>
          {active&&vk.length>0&&<div style={{marginTop:3,fontSize:9,color:th.labelText,textAlign:"center",fontWeight:700}}>DI O MARCA: {vk.join(" · ")}</div>}
          {sttErr&&<div style={{marginTop:4,fontSize:10,color:DS.color.error,textAlign:"center",padding:"4px 8px",background:DS.color.errorLight,borderRadius:DS.radius.xs}}>{sttErr}</div>}
        </>}
        {minimal&&!active&&<div style={{textAlign:"center",fontSize:12,color:DS.color.neutral400,padding:`${DS.space.sm}px 0`}}>Presiona el micrófono para iniciar</div>}
        {minimal&&active&&<div style={{marginTop:DS.space.xs,height:3,background:"rgba(162,89,254,0.12)",borderRadius:2}}><div style={{width:`${pct}%`,height:"100%",background:th.accent,borderRadius:2,transition:"width 0.4s"}}/></div>}
      </div>
      <div style={{flex:1,overflowY:"auto",padding:`${DS.space.sm}px ${DS.space.sm}px ${DS.space.xs}px`,display:"flex",flexDirection:"column",gap:DS.space.xs}}>
        {!minimal&&node?.type==="success"&&active&&<Toast type="success">Interacción completada</Toast>}
        {!minimal&&log.length>0&&<div style={{background:th.logBg,borderRadius:DS.radius.sm,padding:`${DS.space.xs}px ${DS.space.sm}px`,border:`1px solid ${th.lcdBorder}`}}>
          <div style={{fontSize:8,color:th.logText,marginBottom:3,letterSpacing:1.5,fontWeight:700}}>TRANSCRIPCIÓN</div>
          {log.map((e,i)=><div key={i} style={{fontSize:10,color:th.logText,display:"flex",gap:5,marginBottom:1,fontWeight:500}}><span style={{color:DS.color.success}}>▶</span>{e.label} → [{e.choice}]</div>)}
        </div>}
        <PhoneKeypad onPress={pressKey} disabled={!active||node?.type==="success"||node?.type==="error"} kbg={th.optBg} kbd={th.optBorder} kt={th.labelText} ks={th.accent}/>
        {!active?<div style={{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:DS.space.sm,paddingTop:DS.space.sm}}>
          <span style={{fontSize:11,color:th.labelText,fontWeight:500}}>Activa el asistente</span>
          <button onClick={()=>{setActive(true);if(!timer.running)timer.start();}} style={{width:56,height:56,borderRadius:DS.radius.full,background:`linear-gradient(135deg,${th.accent},${th.accentDark})`,border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 0 0 10px rgba(162,89,254,0.1)"}}><Mic size={22} style={{color:DS.color.white}}/></button>
        </div>:<div style={{display:"flex",flexDirection:"column",gap:DS.space.xs}}>
          {!minimal&&<div style={{padding:`0 ${DS.space.xs}px`}}>
            <button onClick={listening?stopListening:startListening} style={{width:"100%",padding:"10px",borderRadius:DS.radius.sm,border:`1.5px solid ${listening?DS.color.error:th.accent}`,background:listening?"rgba(245,67,78,0.1)":"rgba(162,89,254,0.1)",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",gap:6,fontFamily:DS.font,fontSize:12,fontWeight:700,color:listening?DS.color.error:th.accent}}>
              {listening?<><MicOff size={14}/>Detener escucha</>:<><Mic size={14}/>Hablar (reconocimiento de voz)</>}
            </button>
          </div>}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:DS.space.xs,padding:`0 ${DS.space.xs}px`}}>
            <button onClick={()=>setInput(p=>p.slice(0,-1))} style={{background:th.optBg,border:`1px solid ${th.optBorder}`,borderRadius:DS.radius.sm,padding:"10px 4px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}><Delete size={16} style={{color:th.labelText}}/></button>
            <button onClick={reset} style={{background:DS.color.error,border:"none",borderRadius:DS.radius.sm,padding:"10px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 14px rgba(245,67,78,0.3)"}}><PhoneOff size={20} style={{color:DS.color.white}}/></button>
            <button onClick={timer.running?timer.pause:timer.start} style={{background:th.optBg,border:`1px solid ${th.optBorder}`,borderRadius:DS.radius.sm,padding:"10px 4px",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}}>{timer.running?<Pause size={14} style={{color:th.labelText}}/>:<Play size={14} style={{color:th.labelText}}/>}</button>
          </div>
        </div>}
      </div>
    </div>
  );
}

/* ─── FLOW PANEL ──────────────────────────────────────────────────────────── */
function FlowPanel({testType,nodes,setNodes,editMode,canEdit,timer,voiceProfile,voiceOn,avatar,onAvatarChange,testName}){
  const[view,setView]=useState("simulate");
  const th=TYPE_THEME[testType]||TYPE_THEME.IVR;
  const[chatMsgs,setChatMsgs]=useState([]);const[chatStep,setChatStep]=useState(0);
  const[waMsgs,setWaMsgs]=useState([]);const[waStep,setWaStep]=useState(0);
  const showAvatar=testType==="Chatbot"||testType==="WhatsApp";
  const renderSim=()=>{
    if(testType==="WhatsApp")return <WhatsAppSim nodes={nodes} timer={timer} msgs={waMsgs} setMsgs={setWaMsgs} step={waStep} setStep={setWaStep} avatar={avatar}/>;
    if(testType==="Chatbot") return <ChatbotSim  nodes={nodes} timer={timer} voiceProfile={voiceProfile} voiceOn={voiceOn} msgs={chatMsgs} setMsgs={setChatMsgs} step={chatStep} setStep={setChatStep} avatar={avatar}/>;
    if(testType==="Voicebot")return <VoicebotSim nodes={nodes} timer={timer} voiceProfile={voiceProfile} voiceOn={voiceOn}/>;
    return <IVRSimulator nodes={nodes} timer={timer} voiceProfile={voiceProfile} voiceOn={voiceOn}/>;
  };
  return(
    <div style={{display:"flex",flexDirection:"column",height:"100%",overflow:"hidden"}}>
      <div style={{display:"flex",background:DS.color.white,borderBottom:`1px solid ${DS.color.neutral200}`,padding:`4px ${DS.space.sm}px`,gap:DS.space.xs,alignItems:"center",flexShrink:0}}>
        {showAvatar&&<AvatarUploader avatar={avatar} onUpload={onAvatarChange}/>}
        <span style={{fontSize:10,color:DS.color.neutral400,flex:1,fontFamily:DS.font,fontWeight:500}}>{nodes.length} nodos</span>
        <div style={{display:"flex",borderRadius:DS.radius.sm,overflow:"hidden",border:`1px solid ${DS.color.neutral300}`}}>
          {["simulate","tree"].map(v=>(
            <button key={v} onClick={()=>setView(v)} style={{padding:`3px ${DS.space.sm}px`,fontSize:10,border:"none",background:view===v?th.accentDark:DS.color.white,color:view===v?DS.color.white:DS.color.neutral700,cursor:"pointer",fontFamily:DS.font,fontWeight:600}}>
              {v==="simulate"?"▶ Simular":"Árbol"}
            </button>
          ))}
        </div>
      </div>
      <div style={{flex:1,overflow:"hidden",display:view==="simulate"?"block":"none"}}>{renderSim()}</div>
      <div style={{flex:1,overflow:"hidden",display:view==="tree"?"block":"none"}}><TreeView nodes={nodes} setNodes={setNodes} editMode={editMode} canEdit={canEdit} testName={testName}/></div>
    </div>
  );
}

/* ─── TESTER MODE (resultados compartidos via window.storage) ──────────────── */
const STORAGE_KEY="flowtester_v2_sessions";
const ACTIVE_TEST_KEY="flowtester_v2_active_test";

async function loadSharedSessions(){
  try{const r=await window.storage.get(STORAGE_KEY,true);return r?JSON.parse(r.value):[];}catch{return[];}
}
async function saveSharedSessions(arr){
  try{await window.storage.set(STORAGE_KEY,JSON.stringify(arr),true);}catch{}
}
async function loadActiveTestId(){
  try{const r=await window.storage.get(ACTIVE_TEST_KEY,true);return r?JSON.parse(r.value):null;}catch{return null;}
}
async function saveActiveTestId(id){
  try{await window.storage.set(ACTIVE_TEST_KEY,JSON.stringify(id),true);}catch{}
}

function TesterMode({test,avatar,onGoHome}){
  const[name,setName]=useState("");const[started,setStarted]=useState(false);
  const[msgs,setMsgs]=useState([]);const[step,setStep]=useState(0);
  const[saved,setSaved]=useState(false);
  const[completed,setCompleted]=useState(false);
  const[comment,setComment]=useState("");
  const[finished,setFinished]=useState(false);
  const timer=useTimer();
  const nodes=test?.proposed?.nodes||[];
  const testType=test?.type||"Chatbot";
  const canListen=testType==="IVR"||testType==="Voicebot";

  const saveSession=useCallback(async()=>{
    if(saved)return;
    const userMsgs=msgs.filter(m=>m.from==="user").map(m=>m.text);
    const session={id:Date.now(),name,testName:test?.name||"",type:testType,date:new Date().toLocaleString("es-CO"),steps:userMsgs,duration:timer.fmt,completed:true,comment:comment.trim()};
    const current=await loadSharedSessions();
    const updated=[...current,session];
    await saveSharedSessions(updated);
    setSaved(true);setFinished(true);
  },[name,test,testType,timer.fmt,saved,msgs,comment]);

  const startOver=()=>{setStarted(false);setFinished(false);setMsgs([]);setStep(0);setCompleted(false);setComment("");setSaved(false);timer.reset();};

  if(!started){
    return(
      <div style={{height:"100%",display:"flex",alignItems:"center",justifyContent:"center",background:`linear-gradient(135deg,${DS.color.deepBlue},${DS.color.midBlue})`,fontFamily:DS.font,padding:DS.space.lg}}>
        <Card style={{maxWidth:360,width:"100%",textAlign:"center"}}>
          <div style={{width:56,height:56,borderRadius:DS.radius.full,background:DS.color.cyan50,border:`2px solid ${DS.color.brightBlue}`,display:"flex",alignItems:"center",justifyContent:"center",margin:"0 auto",marginBottom:DS.space.md}}><FlaskConical size={26} style={{color:DS.color.midBlue}}/></div>
          <h2 style={{margin:`0 0 ${DS.space.xs}px`,fontSize:20,fontWeight:700,color:DS.color.deepBlue}}>Modo Testeo</h2>
          <p style={{fontSize:12,color:DS.color.neutral700,marginBottom:DS.space.md,lineHeight:1.6}}>Vas a probar el <b>flujo propuesto</b> de <b>{test?.name}</b>.</p>
          <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:4,fontWeight:600,textAlign:"left"}}>Tu nombre completo</label>
          <input value={name} onChange={e=>setName(e.target.value)} onKeyDown={e=>e.key==="Enter"&&name.trim()&&setStarted(true)} placeholder="Ej. Ana Martínez" style={{width:"100%",boxSizing:"border-box",border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,padding:`${DS.space.xs}px`,fontFamily:DS.font,fontSize:13,color:DS.color.deepBlue,marginBottom:DS.space.md}}/>
          <Btn full onClick={()=>name.trim()&&setStarted(true)} disabled={!name.trim()}><Play size={14}/>Iniciar prueba</Btn>
        </Card>
      </div>
    );
  }

  if(finished){
    return(
      <div style={{height:"100%",display:"flex",alignItems:"center",justifyContent:"center",background:`linear-gradient(135deg,${DS.color.deepBlue},${DS.color.midBlue})`,fontFamily:DS.font,padding:DS.space.lg}}>
        <Card style={{maxWidth:360,width:"100%",textAlign:"center"}}>
          <div style={{width:56,height:56,borderRadius:DS.radius.full,background:DS.color.successLight,border:`2px solid ${DS.color.success}`,display:"flex",alignItems:"center",justifyContent:"center",margin:"0 auto",marginBottom:DS.space.md}}><CheckCircle size={26} style={{color:DS.color.success}}/></div>
          <h2 style={{margin:`0 0 ${DS.space.xs}px`,fontSize:20,fontWeight:700,color:DS.color.deepBlue}}>¡Gracias por tu prueba!</h2>
          <p style={{fontSize:12,color:DS.color.neutral700,marginBottom:DS.space.md,lineHeight:1.6}}>Tu resultado{comment?" y tu comentario ":" "}quedaron registrados.</p>
          <div style={{display:"flex",flexDirection:"column",gap:DS.space.xs}}>
            <Btn full onClick={startOver}><RotateCcw size={14}/>Realizar otra prueba</Btn>
            <Btn full variant="ghost" onClick={()=>onGoHome?onGoHome():startOver()}><GitBranch size={14}/>Volver al inicio</Btn>
          </div>
        </Card>
      </div>
    );
  }

  const SimComp=testType==="WhatsApp"?WhatsAppSim:testType==="Voicebot"?VoicebotSim:testType==="IVR"?IVRSimulator:ChatbotSim;
  const effectiveVoiceOn=canListen; // el audio siempre está activo para IVR y Voicebot
  return(
    <div style={{display:"flex",flexDirection:"column",height:"100%"}}>
      <div style={{padding:`${DS.space.xs}px ${DS.space.md}px`,background:DS.color.midBlue,display:"flex",alignItems:"center",gap:DS.space.sm,flexShrink:0,flexWrap:"wrap"}}>
        <FlaskConical size={14} style={{color:DS.color.cyan100}}/>
        <span style={{fontSize:12,fontWeight:700,color:DS.color.white}}>Testeando: {test?.name}</span>
        <span style={{fontSize:11,color:DS.color.cyan100}}>— {name}</span>
        {canListen&&<span style={{marginLeft:"auto",display:"flex",alignItems:"center",gap:4,fontSize:11,color:DS.color.cyan100,fontWeight:600}}><Volume2 size={12}/>Audio activado</span>}
      </div>
      <div style={{flex:1,overflow:"hidden"}}>
        <SimComp nodes={nodes} timer={timer} msgs={msgs} setMsgs={setMsgs} step={step} setStep={setStep} avatar={avatar} voiceProfile={VOICE_PROFILES[1]} voiceOn={effectiveVoiceOn} onComplete={()=>setCompleted(true)} minimal={canListen}/>
      </div>
      {completed&&(
        <div style={{padding:`${DS.space.sm}px ${DS.space.md}px`,background:DS.color.white,borderTop:`1px solid ${DS.color.neutral200}`,flexShrink:0}}>
          <Toast type="success">Flujo finalizado. Puedes dejar un comentario y finalizar cuando quieras.</Toast>
          <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:4,fontWeight:600}}>Comentarios (opcional)</label>
          <textarea value={comment} onChange={e=>setComment(e.target.value)} rows={2} placeholder="Cuéntanos cómo fue tu experiencia..." style={{width:"100%",boxSizing:"border-box",border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,padding:DS.space.xs,fontFamily:DS.font,fontSize:12,color:DS.color.deepBlue,resize:"vertical",marginBottom:DS.space.sm}}/>
          <Btn full variant="success" onClick={saveSession}><CheckCircle size={13}/>Finalizar prueba</Btn>
        </div>
      )}
    </div>
  );
}

/* ─── LOGIN ───────────────────────────────────────────────────────────────── */
function LoginScreen({onLogin}){
  const[usr,setUsr]=useState("");const[pwd,setPwd]=useState("");const[show,setShow]=useState(false);const[err,setErr]=useState("");const[loading,setLoading]=useState(false);
  const go=()=>{setErr("");const u=USERS.find(u=>u.username===usr.trim()&&u.password===pwd);if(!u){setErr("Usuario o contraseña incorrectos.");return;}setLoading(true);setTimeout(()=>onLogin(u),700);};
  const c=DS.color;
  return(
    <div style={{minHeight:"100vh",background:`linear-gradient(135deg,${c.deepBlue},${c.midBlue},${c.brightBlue})`,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:DS.space.lg,fontFamily:DS.font}}>
      <div style={{textAlign:"center",marginBottom:DS.space.xl}}>
        <div style={{display:"inline-flex",alignItems:"center",justifyContent:"center",width:60,height:60,borderRadius:DS.radius.lg,background:"rgba(255,255,255,0.12)",border:"1.5px solid rgba(255,255,255,0.3)",marginBottom:DS.space.md,backdropFilter:"blur(8px)"}}><GitBranch size={28} style={{color:c.white}}/></div>
        <h1 style={{margin:`0 0 ${DS.space.xs}px`,fontSize:32,fontWeight:800,color:c.white,letterSpacing:-0.5,textShadow:"0 2px 8px rgba(0,0,0,0.2)"}}>FlowTester</h1>
        <p style={{margin:0,fontSize:14,color:c.cyan100,fontWeight:500}}>Simulador de flujos conversacionales · emtelco DSXP</p>
      </div>
      <Card style={{maxWidth:400,width:"100%"}}>
        <h2 style={{fontSize:18,fontWeight:700,margin:`0 0 ${DS.space.md}px`,color:c.deepBlue}}>Iniciar sesión</h2>
        <label style={{fontSize:11,color:c.neutral700,display:"block",marginBottom:3,fontWeight:600}}>Usuario</label>
        <div style={{position:"relative",marginBottom:DS.space.sm}}>
          <User size={13} style={{position:"absolute",left:10,top:"50%",transform:"translateY(-50%)",color:c.neutral400}}/>
          <input value={usr} onChange={e=>setUsr(e.target.value)} onKeyDown={e=>e.key==="Enter"&&go()} placeholder="usuario" style={{paddingLeft:30,width:"100%",boxSizing:"border-box",fontFamily:DS.font,fontSize:13,padding:`${DS.space.xs}px ${DS.space.xs}px ${DS.space.xs}px 30px`,border:`1px solid ${c.neutral300}`,borderRadius:DS.radius.sm,color:c.deepBlue}}/>
        </div>
        <label style={{fontSize:11,color:c.neutral700,display:"block",marginBottom:3,fontWeight:600}}>Contraseña</label>
        <div style={{position:"relative",marginBottom:DS.space.md}}>
          <Lock size={13} style={{position:"absolute",left:10,top:"50%",transform:"translateY(-50%)",color:c.neutral400}}/>
          <input type={show?"text":"password"} value={pwd} onChange={e=>setPwd(e.target.value)} onKeyDown={e=>e.key==="Enter"&&go()} placeholder="contraseña" style={{paddingLeft:30,paddingRight:34,width:"100%",boxSizing:"border-box",fontFamily:DS.font,fontSize:13,padding:`${DS.space.xs}px 34px ${DS.space.xs}px 30px`,border:`1px solid ${c.neutral300}`,borderRadius:DS.radius.sm,color:c.deepBlue}}/>
          <button onClick={()=>setShow(s=>!s)} style={{position:"absolute",right:DS.space.xs,top:"50%",transform:"translateY(-50%)",background:"none",border:"none",cursor:"pointer",color:c.neutral400}}>{show?<EyeOff size={13}/>:<Eye size={13}/>}</button>
        </div>
        {err&&<Toast type="error">{err}</Toast>}
        <Btn full onClick={go} disabled={loading}><LogIn size={14}/>{loading?"Verificando...":"Ingresar"}</Btn>
      </Card>
    </div>
  );
}

/* ─── EDIT TEST MODAL ─────────────────────────────────────────────────────── */
function EditTestModal({test,onSave,onClose}){
  const[name,setName]=useState(test.name);const[desc,setDesc]=useState(test.description||"");const[type,setType]=useState(test.type);
  return(
    <Overlay onClose={onClose}>
      <Card style={{width:360}}>
        <div style={{display:"flex",justifyContent:"space-between",marginBottom:DS.space.md}}>
          <h3 style={{margin:0,fontSize:16,fontWeight:700,color:DS.color.deepBlue}}>Editar test</h3>
          <button onClick={onClose} style={{background:"none",border:"none",cursor:"pointer",color:DS.color.neutral400}}><X size={16}/></button>
        </div>
        {[["Nombre","name"],["Descripción","desc"]].map(([lbl,key])=>(
          <div key={key} style={{marginBottom:DS.space.sm}}>
            <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:3,fontWeight:600}}>{lbl}</label>
            <input value={key==="name"?name:desc} onChange={e=>key==="name"?setName(e.target.value):setDesc(e.target.value)} style={{width:"100%",boxSizing:"border-box",border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,color:DS.color.deepBlue,padding:`${DS.space.xs}px`,fontFamily:DS.font}}/>
          </div>
        ))}
        <label style={{fontSize:11,color:DS.color.neutral700,display:"block",marginBottom:3,fontWeight:600}}>Tipo</label>
        <select value={type} onChange={e=>setType(e.target.value)} style={{width:"100%",border:`1px solid ${DS.color.neutral300}`,borderRadius:DS.radius.sm,color:DS.color.deepBlue,padding:`${DS.space.xs}px`,fontFamily:DS.font,marginBottom:DS.space.md}}>
          {["IVR","Chatbot","Voicebot","WhatsApp"].map(t=><option key={t} value={t}>{t}</option>)}
        </select>
        <div style={{display:"flex",gap:DS.space.xs,justifyContent:"flex-end"}}>
          <Btn variant="ghost" onClick={onClose}>Cancelar</Btn>
          <Btn onClick={()=>onSave({...test,name,description:desc,type})}><Save size={11}/>Guardar</Btn>
        </div>
      </Card>
    </Overlay>
  );
}

/* ─── INIT DATA ───────────────────────────────────────────────────────────── */
const INIT_TESTS=[
  {id:1,name:"Autenticación",type:"IVR",description:"IVR de acceso",
    current:{nodes:[{id:"n1",label:"Bienvenida",type:"start",message:"Bienvenido. Ingrese su número de cliente.",options:[{label:"1",next:""},{label:"0",next:""}]},{id:"n2",label:"Validación",type:"action",message:"Validando información...",options:[{label:"1",next:""},{label:"2",next:""}]},{id:"n3",label:"Confirmación",type:"decision",message:"Confirme los últimos 4 dígitos de su documento.",options:[{label:"1",next:""},{label:"2",next:""}]},{id:"n4",label:"Acceso OK",type:"success",message:"Autenticación exitosa.",options:[]},{id:"n5",label:"Acceso Denegado",type:"error",message:"No fue posible verificar. Comuníquese con soporte.",options:[{label:"0",next:""}]}]},
    proposed:{nodes:[{id:"p1",label:"Saludo",type:"start",message:"Hola. Detectamos tu número. ¿Eres el titular?",options:[{label:"1",next:""},{label:"2",next:""}]},{id:"p2",label:"Auth Biométrica",type:"action",message:"Di tu frase de seguridad o ingresa tu PIN.",options:[{label:"1",next:""},{label:"2",next:""}]},{id:"p3",label:"Acceso Inmediato",type:"success",message:"Verificado. ¿Qué deseas hacer?",options:[{label:"1",next:""},{label:"2",next:""}]}]}
  },
  {id:2,name:"Soporte Técnico",type:"Chatbot",description:"Chatbot de soporte nivel 1",
    current:{nodes:[{id:"n1",label:"Inicio",type:"start",message:"Hola, soy el asistente de soporte. ¿En qué te puedo ayudar hoy?",options:[{label:"Internet",next:""},{label:"Facturación",next:""},{label:"Equipos",next:""},{label:"Agente",next:""}]},{id:"n2",label:"Diagnóstico",type:"action",message:"¿El servicio está caído o presenta lentitud?",options:[{label:"Sin servicio",next:""},{label:"Servicio lento",next:""}]},{id:"n4",label:"Resuelto",type:"success",message:"¡Tu servicio fue restablecido!",options:[{label:"Otra consulta",next:""},{label:"No, gracias",next:""}]}]},
    proposed:{nodes:[{id:"p1",label:"Triaje",type:"start",message:"¡Hola! Cuéntame qué está pasando con tu servicio.",options:[{label:"Internet",next:""},{label:"Facturación",next:""},{label:"Equipos",next:""},{label:"Otro",next:""}]},{id:"p2",label:"Diagnóstico IA",type:"action",message:"Detectamos una incidencia en tu zona. ¿Persiste más de 10 min?",options:[{label:"Sí",next:""},{label:"Ya se resolvió",next:""}]},{id:"p3",label:"Solución",type:"action",message:"Te enviamos los pasos. ¿Probamos autodiagnóstico?",options:[{label:"Ver pasos",next:""},{label:"Autodiagnóstico",next:""}]},{id:"p4",label:"Confirmado",type:"success",message:"¡Incidencia resuelta! Reporte generado.",options:[{label:"Ver reporte",next:""},{label:"Calificar",next:""}]}]}
  },
  {id:4,name:"WhatsApp Bot",type:"WhatsApp",description:"Atención por WhatsApp",
    current:{nodes:[{id:"w1",label:"Bienvenida",type:"start",message:"👋 ¡Hola! ¿En qué te puedo ayudar?",options:[{label:"📋 Servicios",next:""},{label:"🔧 Soporte",next:""},{label:"💳 Pagos",next:""},{label:"👤 Agente",next:""}]},{id:"w2",label:"Soporte",type:"action",message:"🔧 ¿Cuál es tu inconveniente?",options:[{label:"Internet caído",next:""},{label:"Servicio lento",next:""},{label:"Otro",next:""}]},{id:"w3",label:"Solución",type:"success",message:"✅ ¡Listo! Servicio restablecido. ¿Algo más?",options:[{label:"Sí",next:""},{label:"No 😊",next:""}]}]},
    proposed:{nodes:[{id:"pw1",label:"Saludo",type:"start",message:"👋 ¡Hola! Soy emtelco Assistant. ¿En qué te ayudo?",options:[{label:"🔧 Tengo un problema",next:""},{label:"📊 Ver consumo",next:""},{label:"💰 Factura",next:""}]},{id:"pw2",label:"NLU",type:"decision",message:"Entendí que tienes un problema con internet. ¿Es correcto?",options:[{label:"✅ Sí",next:""},{label:"❌ No",next:""}]},{id:"pw3",label:"Resolución",type:"success",message:"✅ ¡Servicio restaurado!\n📊 Compensación: 1 día gratis. ¿Algo más?",options:[{label:"Ver compensación",next:""},{label:"Calificar ⭐",next:""}]}]}
  }
];

/* ─── HOME SCREEN (2 botones principales) ─────────────────────────────────── */
function HomeScreen({onSelect}){
  const c=DS.color;
  return(
    <div style={{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",background:`linear-gradient(135deg,${c.deepBlue}ee,${c.midBlue}dd)`,padding:DS.space.xl,gap:DS.space.xl,fontFamily:DS.font}}>
      <div style={{textAlign:"center",marginBottom:DS.space.md}}>
        <h2 style={{margin:`0 0 ${DS.space.xs}px`,fontSize:24,fontWeight:700,color:c.white}}>¿Qué deseas hacer?</h2>
        <p style={{margin:0,fontSize:13,color:c.cyan100,fontWeight:400}}>Selecciona el modo de trabajo</p>
      </div>
      <div style={{display:"flex",gap:DS.space.xl,flexWrap:"wrap",justifyContent:"center"}}>
        {/* Testeo — primera opción, sin necesidad de iniciar sesión */}
        <button onClick={()=>onSelect("tester")}
          style={{background:"rgba(255,255,255,0.95)",borderRadius:DS.radius.lg,padding:`${DS.space.xl}px ${DS.space.xxl||48}px`,border:"none",cursor:"pointer",boxShadow:DS.shadow.B2,display:"flex",flexDirection:"column",alignItems:"center",gap:DS.space.md,transition:"transform 0.15s, box-shadow 0.15s",minWidth:220,fontFamily:DS.font}}
          onMouseEnter={e=>{e.currentTarget.style.transform="translateY(-4px)";e.currentTarget.style.boxShadow="0 20px 48px rgba(0,26,123,0.25)";}}
          onMouseLeave={e=>{e.currentTarget.style.transform="translateY(0)";e.currentTarget.style.boxShadow=DS.shadow.B2;}}>
          <div style={{width:64,height:64,borderRadius:DS.radius.full,background:`linear-gradient(135deg,${c.green},${c.success})`,display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 16px rgba(53,199,89,0.3)"}}>
            <FlaskConical size={30} style={{color:c.white}}/>
          </div>
          <div style={{textAlign:"center"}}>
            <div style={{fontSize:18,fontWeight:700,color:c.deepBlue,marginBottom:4}}>Testeo de Propuesta</div>
            <div style={{fontSize:12,color:c.neutral700,lineHeight:1.5}}>Prueba el flujo propuesto<br/>y guarda los resultados</div>
          </div>
          <div style={{background:c.successLight,borderRadius:DS.radius.full,padding:"5px 16px",fontSize:11,color:"#1A4D2E",fontWeight:600,border:`1px solid ${c.success}`}}>Modo Usuario / Tester</div>
        </button>

        {/* Comparativo — requiere iniciar sesión como Admin */}
        <button onClick={()=>onSelect("compare")}
          style={{background:"rgba(255,255,255,0.95)",borderRadius:DS.radius.lg,padding:`${DS.space.xl}px ${DS.space.xxl||48}px`,border:"none",cursor:"pointer",boxShadow:DS.shadow.B2,display:"flex",flexDirection:"column",alignItems:"center",gap:DS.space.md,transition:"transform 0.15s, box-shadow 0.15s",minWidth:220,fontFamily:DS.font}}
          onMouseEnter={e=>{e.currentTarget.style.transform="translateY(-4px)";e.currentTarget.style.boxShadow="0 20px 48px rgba(0,26,123,0.25)";}}
          onMouseLeave={e=>{e.currentTarget.style.transform="translateY(0)";e.currentTarget.style.boxShadow=DS.shadow.B2;}}>
          <div style={{width:64,height:64,borderRadius:DS.radius.full,background:`linear-gradient(135deg,${c.midBlue},${c.deepBlue})`,display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 16px rgba(0,26,123,0.3)"}}>
            <GitCompare size={30} style={{color:c.white}}/>
          </div>
          <div style={{textAlign:"center"}}>
            <div style={{fontSize:18,fontWeight:700,color:c.deepBlue,marginBottom:4}}>Comparativo</div>
            <div style={{fontSize:12,color:c.neutral700,lineHeight:1.5}}>Contrasta el flujo actual<br/>con la propuesta en paralelo</div>
          </div>
          <div style={{background:c.cyan50,borderRadius:DS.radius.full,padding:"5px 16px",fontSize:11,color:c.midBlue,fontWeight:600,border:`1px solid ${c.cyan200}`}}>Modo Admin / Diseño · requiere login</div>
        </button>
      </div>
    </div>
  );
}

/* ─── SESSIONS PANEL ─────────────────────────────────────────────────────── */
const toSec=str=>{const p=(str||"0:00").split(":").map(Number);return(p[0]||0)*60+(p[1]||0);};
const toMMSS=sec=>`${String(Math.floor(sec/60)).padStart(2,"0")}:${String(sec%60).padStart(2,"0")}`;
const SESSION_TYPE_ICON={IVR:<Phone size={12}/>,Chatbot:<MessageSquare size={12}/>,Voicebot:<Mic size={12}/>,WhatsApp:<span style={{fontSize:12}}>🟢</span>};
function SessionsPanel(){
  const c=DS.color;
  const[sessions,setSessions]=useState([]);const[loading,setLoading]=useState(true);
  useEffect(()=>{loadSharedSessions().then(s=>{setSessions(s);setLoading(false);});const t=setInterval(()=>loadSharedSessions().then(setSessions),3000);return()=>clearInterval(t);},[]);
  const clear=async()=>{await saveSharedSessions([]);setSessions([]);};
  const completedCount=sessions.filter(s=>s.completed).length;
  const avgSec=sessions.length?Math.round(sessions.reduce((a,s)=>a+toSec(s.duration),0)/sessions.length):0;
  const sorted=[...sessions].sort((a,b)=>(b.id||0)-(a.id||0));
  return(
    <div style={{padding:DS.space.md,fontFamily:DS.font,height:"100%",overflowY:"auto",background:c.neutral100}}>
      <div style={{display:"flex",alignItems:"center",gap:DS.space.sm,marginBottom:DS.space.md}}>
        <BarChart2 size={18} style={{color:c.midBlue}}/>
        <h3 style={{margin:0,fontSize:16,fontWeight:700,color:c.deepBlue}}>Resultados de testeo</h3>
        <span style={{marginLeft:"auto",fontSize:11,color:c.neutral400}}>Compartidos entre equipos</span>
      </div>

      {/* RESUMEN */}
      <div style={{display:"flex",gap:DS.space.sm,marginBottom:DS.space.md,flexWrap:"wrap"}}>
        {[
          {label:"Sesiones",value:sessions.length,icon:<FlaskConical size={14} style={{color:c.midBlue}}/>,bg:c.cyan50,bd:c.cyan200},
          {label:"Completadas",value:`${completedCount}/${sessions.length||0}`,icon:<CheckCircle size={14} style={{color:c.success}}/>,bg:c.successLight,bd:c.success},
          {label:"Duración promedio",value:toMMSS(avgSec),icon:<Radio size={14} style={{color:c.purple}}/>,bg:"#F5F3FF",bd:c.purple100},
        ].map((st,i)=>(
          <div key={i} style={{flex:"1 1 140px",background:st.bg,border:`1px solid ${st.bd}`,borderRadius:DS.radius.md,padding:`${DS.space.xs}px ${DS.space.sm}px`,display:"flex",alignItems:"center",gap:8}}>
            <div style={{width:28,height:28,borderRadius:DS.radius.full,background:c.white,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>{st.icon}</div>
            <div><div style={{fontSize:16,fontWeight:800,color:c.deepBlue,lineHeight:1.1}}>{st.value}</div><div style={{fontSize:9,color:c.neutral700,fontWeight:600}}>{st.label}</div></div>
          </div>
        ))}
      </div>

      <div style={{display:"flex",gap:DS.space.sm,marginBottom:DS.space.md}}>
        <button onClick={()=>dlCSV(sessions.map(s=>({Nombre:s.name,Test:s.testName,Tipo:s.type,Fecha:s.date,"Duración":s.duration,Pasos:s.steps.join(" → "),Completado:s.completed?"Sí":"No",Comentario:s.comment||""})),"resultados_testeo.csv")} disabled={!sessions.length} style={{fontSize:11,padding:"5px 14px",border:`1px solid ${c.success}`,borderRadius:DS.radius.full,background:c.successLight,cursor:sessions.length?"pointer":"default",color:"#1A4D2E",display:"flex",alignItems:"center",gap:4,fontFamily:DS.font,fontWeight:600,opacity:sessions.length?1:0.5}}><Download size={11}/>Descargar CSV</button>
        <button onClick={clear} disabled={!sessions.length} style={{fontSize:11,padding:"5px 14px",border:`1px solid ${c.error}`,borderRadius:DS.radius.full,background:c.errorLight,cursor:sessions.length?"pointer":"default",color:c.error,display:"flex",alignItems:"center",gap:4,fontFamily:DS.font,fontWeight:600,opacity:sessions.length?1:0.5}}><Trash2 size={11}/>Limpiar</button>
      </div>

      {loading?<div style={{textAlign:"center",padding:DS.space.xl,color:c.neutral400}}>Cargando...</div>:sorted.length===0?<div style={{textAlign:"center",padding:DS.space.xl,color:c.neutral400,fontSize:12}}>No hay sesiones registradas aún.</div>:sorted.map((s,i)=>{
        const th=TYPE_THEME[s.type]||TYPE_THEME.IVR;
        const accent=th.accentDark||th.accent||c.midBlue;
        return(
        <div key={s.id||i} style={{background:c.white,border:`1px solid ${c.neutral300}`,borderLeft:`4px solid ${accent}`,borderRadius:DS.radius.sm,padding:`${DS.space.sm}px ${DS.space.md}px`,marginBottom:DS.space.sm,boxShadow:DS.shadow.A1}}>
          <div style={{display:"flex",alignItems:"center",gap:DS.space.xs,marginBottom:6,flexWrap:"wrap"}}>
            <div style={{width:24,height:24,borderRadius:DS.radius.full,background:c.deepBlue,color:c.white,display:"flex",alignItems:"center",justifyContent:"center",fontSize:10,fontWeight:800,flexShrink:0}}>{(s.name||"?").trim().charAt(0).toUpperCase()}</div>
            <span style={{fontSize:13,fontWeight:700,color:c.deepBlue}}>{s.name}</span>
            <Tag label={s.testName} color={c.midBlue}/>
            <span style={{display:"flex",alignItems:"center",gap:3,fontSize:10,color:accent,fontWeight:700}}>{SESSION_TYPE_ICON[s.type]||null}{s.type}</span>
            <div style={{marginLeft:"auto",display:"flex",alignItems:"center",gap:6}}>
              <span style={{display:"flex",alignItems:"center",gap:3,fontSize:11,fontWeight:700,color:c.deepBlue,background:c.neutral100,borderRadius:DS.radius.full,padding:"3px 9px"}}><Radio size={10} style={{color:c.midBlue}}/>{s.duration}</span>
              <span style={{fontSize:10,color:s.completed?c.success:c.warning,fontWeight:700}}>{s.completed?"✓ Completado":"Parcial"}</span>
            </div>
          </div>
          <div style={{fontSize:10,color:c.neutral400,marginBottom:6}}>{s.date}</div>
          {s.steps.length>0&&(
            <div style={{marginBottom:s.comment?6:0}}>
              <div style={{fontSize:9,color:c.neutral700,fontWeight:700,letterSpacing:1,marginBottom:4}}>OPCIONES SELECCIONADAS</div>
              <div style={{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"}}>
                {s.steps.map((opt,j)=>(
                  <span key={j} style={{display:"flex",alignItems:"center",gap:5}}>
                    <span style={{display:"flex",alignItems:"center",gap:4,fontSize:11,color:c.deepBlue,background:c.neutral100,border:`1px solid ${c.neutral300}`,borderRadius:DS.radius.full,padding:"3px 10px"}}>
                      <span style={{fontSize:9,fontWeight:800,color:accent}}>{j+1}</span>{opt}
                    </span>
                    {j<s.steps.length-1&&<ChevronRight size={12} style={{color:c.neutral400}}/>}
                  </span>
                ))}
              </div>
            </div>
          )}
          {s.comment&&(
            <div style={{display:"flex",gap:6,alignItems:"flex-start",background:"#FFFBEA",border:`1px solid ${c.warning}`,borderRadius:DS.radius.sm,padding:"6px 10px"}}>
              <MessageSquare size={12} style={{color:"#7A4F00",flexShrink:0,marginTop:1}}/>
              <span style={{fontSize:11,color:"#7A4F00",fontStyle:"italic",lineHeight:1.4}}>{s.comment}</span>
            </div>
          )}
        </div>
      );})}
    </div>
  );
}

/* ─── MAIN ────────────────────────────────────────────────────────────────── */
export default function App(){
  const[user,setUser]=useState(null);
  const[tests,setTests]=useState(INIT_TESTS);
  const[tid,setTid]=useState(1);
  const[editMode,setEditMode]=useState(false);
  const[showTests,setShowTests]=useState(false);
  const[showSave,setShowSave]=useState(false);
  const[showUserMenu,setShowUserMenu]=useState(false);
  const[saveName,setSaveName]=useState("");
  const[voiceProfile,setVoiceProfile]=useState(VOICE_PROFILES[1]);
  const[voiceOn,setVoiceOn]=useState(false);
  const[editingTest,setEditingTest]=useState(null);
  const[avatars,setAvatars]=useState({});
  const[activeTestId,setActiveTestId]=useState(null);
  // "home" | "compare" | "tester" | "sessions"
  const[appMode,setAppMode]=useState("home");
  const timerL=useTimer();const timerR=useTimer();

  useEffect(()=>{if(window.speechSynthesis){loadVoices();window.speechSynthesis.onvoiceschanged=loadVoices;}},[]);
  useEffect(()=>{loadActiveTestId().then(id=>setActiveTestId(id||tests[0]?.id||1));},[]);
  // Solo el modo Comparativo (edición de flujos) exige iniciar sesión.
  if(appMode==="compare"&&!user)return <LoginScreen onLogin={setUser}/>;

  const isAdmin=user?.role==="admin";
  const test=tests.find(t=>t.id===tid);
  const theme=TYPE_THEME[test?.type]||TYPE_THEME.IVR;
  const setNodes=(side,upd)=>setTests(p=>p.map(t=>t.id===tid?{...t,[side]:{...t[side],nodes:typeof upd==="function"?upd(t[side].nodes):upd}}:t));
  const saveNew=()=>{if(!saveName.trim())return;const n={...test,id:Date.now(),name:saveName};setTests(p=>[...p,n]);setTid(n.id);setShowSave(false);setSaveName("");};
  const getAvatar=side=>avatars[tid]?.[side]||null;
  const setAvatar=(side,url)=>setAvatars(a=>({...a,[tid]:{...a[tid],[side]:url}}));
  const markActiveForTesting=()=>{setActiveTestId(tid);saveActiveTestId(tid);};
  const TI={IVR:<Phone size={10}/>,Chatbot:<MessageSquare size={10}/>,Voicebot:<Mic size={10}/>,WhatsApp:<span style={{fontSize:10}}>🟢</span>};
  const c=DS.color;
  const showVoice=test?.type==="IVR"||test?.type==="Voicebot";
  const topGradient=appMode==="compare"?theme.gradient:`linear-gradient(135deg,${c.deepBlue},${c.midBlue})`;

  return(
    <div style={{display:"flex",flexDirection:"column",height:"100vh",background:c.neutral100,fontFamily:DS.font,overflow:"hidden"}}>
      {editingTest&&<EditTestModal test={editingTest} onSave={upd=>{setTests(p=>p.map(t=>t.id===upd.id?upd:t));setEditingTest(null);}} onClose={()=>setEditingTest(null)}/>}

      {/* TOPBAR */}
      <div style={{display:"flex",alignItems:"center",gap:DS.space.sm,padding:`0 ${DS.space.md}px`,height:48,background:topGradient,flexShrink:0,boxShadow:DS.shadow.B1}}>
        <button onClick={()=>setAppMode("home")} style={{background:"none",border:"none",cursor:"pointer",display:"flex",alignItems:"center",gap:6,padding:0}}>
          <GitBranch size={16} style={{color:c.white,opacity:0.9}}/>
          <span style={{fontSize:18,fontWeight:800,color:c.white,letterSpacing:-0.3,textShadow:"0 1px 4px rgba(0,0,0,0.2)"}}>FlowTester</span>
        </button>

        {/* MODE PILLS — solo visibles dentro de Comparativo (no en inicio ni en testeo) */}
        {appMode==="compare"&&<div style={{display:"flex",gap:4,background:"rgba(0,0,0,0.2)",borderRadius:DS.radius.full,padding:"3px 5px"}}>
          <button onClick={()=>setAppMode("compare")} style={{display:"flex",alignItems:"center",gap:4,padding:`4px ${DS.space.sm}px`,fontSize:11,border:"none",borderRadius:DS.radius.full,background:appMode==="compare"?"rgba(255,255,255,0.25)":"none",color:c.white,cursor:"pointer",fontFamily:DS.font,fontWeight:appMode==="compare"?700:400}}>
            <GitCompare size={11}/>Comparativo
          </button>
          <button onClick={()=>setAppMode("sessions")} style={{display:"flex",alignItems:"center",gap:4,padding:`4px ${DS.space.sm}px`,fontSize:11,border:"none",borderRadius:DS.radius.full,background:appMode==="sessions"?"rgba(255,255,255,0.25)":"none",color:c.white,cursor:"pointer",fontFamily:DS.font,fontWeight:appMode==="sessions"?700:400}}>
            <BarChart2 size={11}/>Resultados
          </button>
        </div>}

        <div style={{flex:1}}/>

        {/* TEST TABS — solo en compare */}
        {appMode==="compare"&&<div style={{display:"flex",gap:2,background:"rgba(0,0,0,0.18)",borderRadius:DS.radius.sm,padding:3}}>
          {tests.map(t=>(
            <div key={t.id} style={{display:"flex",alignItems:"center"}}>
              <button onClick={()=>setTid(t.id)} style={{display:"flex",alignItems:"center",gap:4,padding:`4px ${DS.space.sm}px`,fontSize:11,border:"none",borderRadius:DS.radius.xs,background:tid===t.id?"rgba(255,255,255,0.22)":"none",color:c.white,cursor:"pointer",fontFamily:DS.font,fontWeight:tid===t.id?700:400}}>
                {TI[t.type]}{t.name}
              </button>
              {isAdmin&&<button onClick={()=>setEditingTest(t)} style={{padding:"2px 3px",border:"none",background:"none",color:"rgba(255,255,255,0.45)",cursor:"pointer",display:"flex",alignItems:"center"}}><Edit3 size={9}/></button>}
            </div>
          ))}
          <button onClick={()=>setShowTests(true)} style={{padding:`3px ${DS.space.xs}px`,border:"none",background:"none",color:"rgba(255,255,255,0.45)",cursor:"pointer",display:"flex",alignItems:"center"}}><BookOpen size={13}/></button>
        </div>}

        {/* VOICE */}
        {appMode==="compare"&&showVoice&&<button onClick={()=>setVoiceOn(v=>!v)} style={{display:"flex",alignItems:"center",gap:3,padding:`5px ${DS.space.sm}px`,fontSize:11,border:`1px solid ${voiceOn?"rgba(255,255,255,0.6)":"rgba(255,255,255,0.25)"}`,borderRadius:DS.radius.sm,background:voiceOn?"rgba(255,255,255,0.2)":"none",cursor:"pointer",color:c.white,fontFamily:DS.font,fontWeight:600}}>{voiceOn?<Volume2 size={13}/>:<VolumeX size={13}/>}</button>}

        {isAdmin&&appMode==="compare"&&<>
          <button onClick={()=>setEditMode(e=>!e)} style={{display:"flex",alignItems:"center",gap:4,padding:`5px ${DS.space.sm}px`,fontSize:12,border:`1px solid ${editMode?"#fff":"rgba(255,255,255,0.3)"}`,borderRadius:DS.radius.sm,background:editMode?"rgba(255,255,255,0.2)":"none",cursor:"pointer",color:c.white,fontFamily:DS.font,fontWeight:700}}>
            <Edit3 size={12}/>{editMode?"Editando":"Editar"}
          </button>
          <button onClick={()=>setShowSave(true)} style={{display:"flex",alignItems:"center",gap:4,padding:`5px ${DS.space.sm}px`,fontSize:12,border:"1px solid rgba(255,255,255,0.35)",borderRadius:DS.radius.sm,background:"rgba(255,255,255,0.15)",cursor:"pointer",color:c.white,fontFamily:DS.font,fontWeight:700}}>
            <Save size={12}/>Guardar
          </button>
          <button onClick={markActiveForTesting} title="Este será el flujo que verán los testers en Modo Testeo" style={{display:"flex",alignItems:"center",gap:4,padding:`5px ${DS.space.sm}px`,fontSize:12,border:`1px solid ${tid===activeTestId?DS.color.success:"rgba(255,255,255,0.35)"}`,borderRadius:DS.radius.sm,background:tid===activeTestId?"rgba(53,199,89,0.28)":"rgba(255,255,255,0.15)",cursor:"pointer",color:c.white,fontFamily:DS.font,fontWeight:700}}>
            <FlaskConical size={12}/>{tid===activeTestId?"✓ En Testeo":"Usar en Testeo"}
          </button>
        </>}

        {/* USER — solo en Comparativo (única sección que exige sesión) */}
        {appMode==="compare"&&(user?(
          <button onClick={()=>setShowUserMenu(s=>!s)} style={{display:"flex",alignItems:"center",gap:5,padding:`3px ${DS.space.xs}px`,border:"1px solid rgba(255,255,255,0.25)",borderRadius:DS.radius.sm,background:"rgba(255,255,255,0.1)",cursor:"pointer"}}>
            <div style={{width:26,height:26,borderRadius:DS.radius.full,background:user.color+"44",border:`2px solid ${user.color}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:9,fontWeight:800,color:c.white}}>{user.initials}</div>
            {isAdmin&&<Shield size={11} style={{color:c.cyan100}}/>}
            <span style={{fontSize:11,color:c.white,fontWeight:600,maxWidth:70,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{user.name}</span>
            <ChevronDown size={10} style={{color:"rgba(255,255,255,0.7)"}}/>
          </button>
        ):(
          <button onClick={()=>setAppMode("compare")} style={{display:"flex",alignItems:"center",gap:5,padding:`5px ${DS.space.sm}px`,border:"1px solid rgba(255,255,255,0.3)",borderRadius:DS.radius.sm,background:"rgba(255,255,255,0.12)",cursor:"pointer",color:c.white,fontFamily:DS.font,fontWeight:600,fontSize:11}}>
            <LogIn size={12}/>Iniciar sesión
          </button>
        ))}
      </div>

      {/* USER MENU — solo el usuario actual */}
      {showUserMenu&&user&&(<>
        <div style={{position:"fixed",inset:0,zIndex:8888}} onClick={()=>setShowUserMenu(false)}/>
        <div style={{position:"fixed",top:52,right:DS.space.md,zIndex:9999,minWidth:220,overflow:"hidden",boxShadow:DS.shadow.B2,borderRadius:DS.radius.md,border:`1px solid ${c.neutral200}`,background:c.white,fontFamily:DS.font}}>
          <div style={{padding:`${DS.space.sm}px ${DS.space.md}px`,borderBottom:`1px solid ${c.neutral200}`,background:c.cyan50}}>
            <div style={{display:"flex",alignItems:"center",gap:DS.space.sm}}>
              <div style={{width:36,height:36,borderRadius:DS.radius.full,background:user.color+"22",border:`2px solid ${user.color}`,display:"flex",alignItems:"center",justifyContent:"center",fontSize:12,fontWeight:800,color:user.color}}>{user.initials}</div>
              <div><div style={{fontSize:13,fontWeight:700,color:c.deepBlue}}>{user.name}</div><div style={{fontSize:10,color:c.neutral400}}>{user.role}{isAdmin&&" · Admin"}</div></div>
            </div>
          </div>
          <button onClick={()=>{setUser(null);setShowUserMenu(false);setEditMode(false);window.speechSynthesis?.cancel();setAppMode("home");}} style={{display:"flex",alignItems:"center",gap:DS.space.xs,width:"100%",padding:`${DS.space.sm}px ${DS.space.md}px`,background:"none",border:"none",cursor:"pointer",color:c.error,fontSize:13,fontFamily:DS.font,fontWeight:700}}><LogIn size={13}/>Cerrar sesión</button>
        </div>
      </>)}

      {/* VOICE BAR */}
      {voiceOn&&appMode==="compare"&&showVoice&&(
        <div style={{padding:`5px ${DS.space.md}px`,borderBottom:`1px solid ${c.cyan100}`,background:c.cyan50,display:"flex",alignItems:"center",gap:DS.space.sm,flexShrink:0}}>
          <Volume2 size={12} style={{color:c.midBlue}}/>
          <span style={{fontSize:11,color:c.midBlue,fontWeight:700}}>Perfil de voz:</span>
          <div style={{display:"flex",gap:DS.space.xs}}>
            {VOICE_PROFILES.map(v=>(
              <button key={v.id} onClick={()=>setVoiceProfile(v)} style={{fontSize:10,padding:`3px ${DS.space.sm}px`,border:`1.5px solid ${voiceProfile.id===v.id?c.midBlue:c.cyan200}`,borderRadius:DS.radius.full,background:voiceProfile.id===v.id?c.midBlue:"rgba(255,255,255,0.6)",color:voiceProfile.id===v.id?c.white:c.midBlue,cursor:"pointer",fontFamily:DS.font,fontWeight:700}}>
                {v.icon} {v.label}
              </button>
            ))}
          </div>
        </div>
      )}

      {appMode==="compare"&&!isAdmin&&<div style={{background:c.warningLight,borderBottom:`1px solid ${c.warning}`,padding:`4px ${DS.space.md}px`,display:"flex",alignItems:"center",gap:6,flexShrink:0}}><AlertCircle size={12} style={{color:"#7A4F00"}}/><span style={{fontSize:11,color:"#7A4F00",fontWeight:600}}>Solo lectura — solo el Administrador puede editar flujos</span></div>}

      {/* MAIN CONTENT */}
      <div style={{flex:1,overflow:"hidden",display:"flex",flexDirection:"column"}}>
        {appMode==="home"&&<HomeScreen onSelect={setAppMode}/>}

        {appMode==="sessions"&&<SessionsPanel/>}

        {appMode==="tester"&&(()=>{
          const activeTest=tests.find(t=>t.id===activeTestId)||tests[0];
          const activeAvatar=avatars[activeTest?.id]?.["proposed"]||null;
          return(
            <div style={{flex:1,overflow:"hidden"}}>
              <TesterMode key={activeTest?.id} test={activeTest} avatar={activeAvatar} onGoHome={()=>setAppMode("home")}/>
            </div>
          );
        })()}

        {appMode==="compare"&&test&&(
          <div style={{flex:1,display:"flex",overflow:"hidden"}}>
            {[{side:"current",label:"Flujo Actual",dot:c.error,txt:c.error,bg:c.errorLight},{side:"proposed",label:"Propuesta",dot:c.success,txt:c.success,bg:c.successLight}].map(({side,label,dot,txt,bg},idx)=>(
              <div key={side} style={{flex:1,borderRight:idx===0?`1px solid ${c.neutral200}`:"none",overflow:"hidden",display:"flex",flexDirection:"column"}}>
                <div style={{padding:`5px ${DS.space.sm}px`,background:bg+"55",borderBottom:`1px solid ${c.neutral200}`,flexShrink:0,display:"flex",alignItems:"center",gap:DS.space.xs}}>
                  <div style={{width:7,height:7,borderRadius:DS.radius.full,background:dot}}/>
                  <span style={{fontSize:11,fontWeight:700,color:txt}}>{label}</span>
                  <span style={{fontSize:10,color:dot,opacity:0.7}}>{test[side].nodes.length} nodos</span>
                </div>
                <div style={{flex:1,overflow:"hidden"}}>
                  <FlowPanel testType={test.type} nodes={test[side].nodes} setNodes={u=>setNodes(side,u)} editMode={editMode} canEdit={isAdmin} timer={idx===0?timerL:timerR} voiceProfile={voiceProfile} voiceOn={voiceOn} avatar={getAvatar(side)} onAvatarChange={url=>setAvatar(side,url)} testName={`${test.name}_${side}`}/>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* TESTS MODAL */}
      {showTests&&(
        <Overlay onClose={()=>setShowTests(false)}>
          <Card style={{width:440,maxHeight:"80vh",overflowY:"auto"}}>
            <div style={{display:"flex",alignItems:"center",marginBottom:DS.space.md}}>
              <BookOpen size={14} style={{marginRight:DS.space.xs,color:c.midBlue}}/>
              <h3 style={{margin:0,fontSize:16,fontWeight:700,color:c.deepBlue}}>Repositorio de Tests</h3>
              <span style={{marginLeft:"auto",fontSize:11,color:c.neutral400}}>{tests.length} tests</span>
              <button onClick={()=>setShowTests(false)} style={{background:"none",border:"none",cursor:"pointer",color:c.neutral400,marginLeft:DS.space.sm}}><X size={15}/></button>
            </div>
            {tests.map(t=>{const th2=TYPE_THEME[t.type]||TYPE_THEME.IVR;return(
              <div key={t.id} onClick={()=>{setTid(t.id);setShowTests(false);}} style={{border:`${tid===t.id?`2px solid ${c.brightBlue}`:`1px solid ${c.neutral200}`}`,borderRadius:DS.radius.sm,padding:`${DS.space.sm}px ${DS.space.md}px`,marginBottom:DS.space.xs,background:tid===t.id?c.cyan50:c.white,cursor:"pointer",boxShadow:DS.shadow.A1}}>
                <div style={{display:"flex",alignItems:"center",gap:DS.space.xs}}>
                  <span style={{fontSize:12,fontWeight:700,color:tid===t.id?c.deepBlue:c.neutral700,flex:1}}>{t.name}</span>
                  <Tag label={t.type} color={th2.accentDark}/>
                  {tid===t.id&&<CheckCircle size={13} style={{color:c.brightBlue}}/>}
                  {isAdmin&&<button onClick={e=>{e.stopPropagation();setEditingTest(t);setShowTests(false);}} style={{background:"none",border:"none",cursor:"pointer",color:c.neutral400,padding:3}}><Edit3 size={11}/></button>}
                  {isAdmin&&tests.length>1&&<button onClick={e=>{e.stopPropagation();const r=tests.filter(x=>x.id!==t.id);setTests(r);if(tid===t.id)setTid(r[0].id);}} style={{background:"none",border:"none",cursor:"pointer",color:c.error,padding:3}}><Trash2 size={11}/></button>}
                </div>
                <p style={{fontSize:11,color:c.neutral400,margin:`3px 0 ${DS.space.xs}px`}}>{t.description}</p>
              </div>
            );})}
          </Card>
        </Overlay>
      )}

      {/* SAVE MODAL */}
      {showSave&&(
        <Overlay onClose={()=>setShowSave(false)}>
          <Card style={{width:330}}>
            <h3 style={{margin:`0 0 ${DS.space.xs}px`,fontSize:16,fontWeight:700,color:c.deepBlue}}>Guardar nueva versión</h3>
            <p style={{fontSize:12,color:c.neutral400,marginBottom:DS.space.sm}}>El test actual se duplica.</p>
            <input value={saveName} onChange={e=>setSaveName(e.target.value)} onKeyDown={e=>e.key==="Enter"&&saveNew()} placeholder="Ej. Autenticación v2" style={{width:"100%",marginBottom:DS.space.md,boxSizing:"border-box",border:`1px solid ${c.neutral300}`,borderRadius:DS.radius.sm,color:c.deepBlue,padding:`${DS.space.xs}px`,fontFamily:DS.font}}/>
            <div style={{display:"flex",gap:DS.space.xs,justifyContent:"flex-end"}}>
              <Btn variant="ghost" onClick={()=>setShowSave(false)}>Cancelar</Btn>
              <Btn variant="success" onClick={saveNew}><Save size={11}/>Guardar</Btn>
            </div>
          </Card>
        </Overlay>
      )}
    </div>
  );
}

/* ── Polyfill de window.storage usando localStorage (ver README) ── */
(function () {
  const NS = "flowtester_storage_v1";
  function readAll() {
    try { return JSON.parse(localStorage.getItem(NS) || "{}"); } catch { return {}; }
  }
  function writeAll(data) { localStorage.setItem(NS, JSON.stringify(data)); }
  window.storage = {
    async get(key) {
      const all = readAll();
      if (!(key in all)) return null;
      return { key, value: all[key], shared: false };
    },
    async set(key, value) {
      const all = readAll();
      all[key] = value;
      writeAll(all);
      return { key, value, shared: false };
    },
    async delete(key) {
      const all = readAll();
      if (!(key in all)) return null;
      delete all[key];
      writeAll(all);
      return { key, deleted: true, shared: false };
    },
    async list(prefix) {
      const all = readAll();
      const keys = Object.keys(all).filter((k) => !prefix || k.startsWith(prefix));
      return { keys, prefix, shared: false };
    },
  };
})();

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
