/* ─── Campaigns page — v2 redesign ───────────────────────────────────────────
   Stat-tile filters → search → consolidated table (campaign+promo merged,
   claims badges, performance bar, product stack, share/QR actions).
   Overrides window.Campaigns. Demo numbers are invented. */

const CAMPS_V2 = [
  { name:'SPAIN',                        promo:'SPAIN',                        icon:'shield', claims:'rr',  products:2, claimed:14, reviews:11, status:true },
  { name:'Australia Campaign',           promo:'Australia Promotion',          icon:'shield', claims:'rr',  products:1, claimed:9,  reviews:7,  status:true },
  { name:'Cashback testing',             promo:'cashback image test 2',        icon:'cash',   claims:'rrs', products:3, claimed:31, reviews:22, status:true },
  { name:'Canada testing',               promo:'Warranty check',               icon:'shield', claims:'rr',  products:1, claimed:5,  reviews:4,  status:true },
  { name:'usa testing',                  promo:'Giveaway',                     icon:'gift',   claims:'rr',  products:2, claimed:18, reviews:12, status:true },
  { name:'UK campaign',                  promo:'Warranty check',               icon:'shield', claims:'rr',  products:1, claimed:7,  reviews:6,  status:true },
  { name:'Digital Download Test - Husain', promo:'Digital Download Test - Husain', icon:'cloud', claims:'rrs', products:1, claimed:3, reviews:2, status:false },
  { name:'Gift card Test - Husain',      promo:'Gift card Test - Husain',      icon:'gift',   claims:'r',   products:1, claimed:12, reviews:8, status:true },
];

const CLAIM_BADGE = {
  rr:  { label:'Review + Rating',   cls:'bg-brand-50 text-brand' },
  rrs: { label:'+ Screenshot',      cls:'acc-bg-soft acc-text' },
  r:   { label:'Rating only',       cls:'bg-surface-input text-ink-muted' },
};
const ClaimBadge = ({ kind }) => {
  const b = CLAIM_BADGE[kind] || CLAIM_BADGE.rr;
  return <span className={"inline-flex text-[10.5px] font-bold px-2 py-1 rounded-full whitespace-nowrap "+b.cls}>{b.label}</span>;
};

const ProductStack = ({ n, hue }) => (
  <span className="inline-flex items-center">
    {Array.from({length: Math.min(n,3)}).map((_,i) => (
      <span key={i} className="w-7 h-7 rounded-lg ring-2 ring-white -ml-1.5 first:ml-0"
            style={{background:`linear-gradient(135deg, hsl(${(hue+i*47)%360},75%,72%), hsl(${(hue+i*47+40)%360},65%,50%))`}}></span>
    ))}
    {n > 3 && <span className="w-7 h-7 rounded-lg ring-2 ring-white -ml-1.5 bg-surface-input text-[10px] font-bold text-ink-muted flex items-center justify-center">+{n-3}</span>}
    <span className="ml-2 text-[12px] text-ink-muted">{n}</span>
  </span>
);

const PerfBar = ({ claimed, reviews }) => {
  const pct = claimed ? Math.round((reviews/claimed)*100) : 0;
  return (
    <div className="min-w-[130px]">
      <div className="flex items-baseline justify-between text-[12px]">
        <span className="font-bold text-ink">{reviews} <span className="font-medium text-ink-muted">reviews</span></span>
        <span className="text-ink-soft">{claimed} claims</span>
      </div>
      <div className="mt-1.5 h-1.5 rounded-full bg-surface-input overflow-hidden">
        <div className="h-full rounded-full bg-gradient-to-r from-brand to-brand-light" style={{width:pct+'%'}}></div>
      </div>
    </div>
  );
};

const LinkIcon = () => (
  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2">
    <path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7" strokeLinecap="round"/>
  </svg>
);

/* QR design studio — Hovercode-inspired: templates, pattern/eye styles, colors, frame, logo */
function StudioQR({ size=190, pattern='square', eye='square', color='#1B2733', eyeColor, frame='none', logoUrl=null, label='SCAN ME' }) {
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g,'') + 'qr';
  const N=25, cell=size/N, ec=eyeColor||color;
  const circleFrames=['ring','confetti','burst','dashed','dotring','inverted','shutter','donut'];
  const circle=circleFrames.includes(frame);
  const inv = frame==='inverted'||frame==='shutter';
  const fg=inv?'#FFFFFF':color, feg=inv?'#FFFFFF':ec;
  const mods=[];
  const inEye=(r,c)=>(r<7&&c<7)||(r<7&&c>=N-7)||(r>=N-7&&c<7);
  const inLogo=(r,c)=>logoUrl && r>=10&&r<=14&&c>=10&&c<=14;
  for(let r=0;r<N;r++)for(let c=0;c<N;c++){ if(inEye(r,c)||inLogo(r,c))continue; if(((r*31+c*17+r*c)%5)<2) mods.push([r,c]); }
  const eyeR = eye==='square'?0:eye==='rounded'?cell*1.4:cell*3.5;
  const eyeInR = eye==='square'?0:eye==='rounded'?cell*0.8:cell*1.5;
  const eyeEl=(x,y)=>(
    <g key={x+'-'+y}>
      <rect x={(x+0.1)*cell} y={(y+0.1)*cell} width={cell*6.8} height={cell*6.8} rx={eyeR} fill="none" stroke={feg} strokeWidth={cell*0.85}/>
      <rect x={(x+2)*cell} y={(y+2)*cell} width={cell*3} height={cell*3} rx={eyeInR} fill={feg}/>
    </g>
  );
  const labelFrames=['tab','pill','cardfill','shadow'];
  const hasLabel=labelFrames.includes(frame);
  const pad = frame==='donut'? size*0.30 : circle? size*0.26 : (frame==='cardfill'||frame==='shadow')? size*0.13 : frame==='border'? size*0.09 : frame==='archtext'? size*0.17 : size*0.05;
  const lh = hasLabel? Math.max(13,size*0.15):0;
  const W=size+pad*2;
  const H = hasLabel? pad+size+pad*0.45+lh+pad*0.3 : size+pad*2;
  const cx=W/2, cy=pad+size/2, R=size/2+pad*0.6;
  let s0=7; const rnd=()=>((s0=(s0*1103515245+12345)%2147483648)/2147483648);
  const confetti = frame==='confetti' && Array.from({length:34}).map((_,i)=>{
    const a=rnd()*Math.PI*2, rr=R+(rnd()-0.5)*pad*0.5, x=cx+Math.cos(a)*rr, y=cy+Math.sin(a)*rr;
    return <line key={i} x1={-cell*0.9} y1="0" x2={cell*0.9} y2="0" transform={`translate(${x},${y}) rotate(${rnd()*180})`} stroke={fg} strokeWidth={cell*0.38} strokeLinecap="round"/>;
  });
  const burst = frame==='burst' && Array.from({length:56}).map((_,i)=>{
    const a=(i/56)*Math.PI*2, r1=R*0.96, r2=R*(1.04+rnd()*0.1);
    return <line key={i} x1={cx+Math.cos(a)*r1} y1={cy+Math.sin(a)*r1} x2={cx+Math.cos(a)*r2} y2={cy+Math.sin(a)*r2} stroke={fg} strokeWidth={cell*0.3} strokeLinecap="round"/>;
  });
  const dotring = frame==='dotring' && Array.from({length:36}).map((_,i)=>{
    const a=(i/36)*Math.PI*2;
    return <circle key={i} cx={cx+Math.cos(a)*R} cy={cy+Math.sin(a)*R} r={cell*(0.3+rnd()*0.22)} fill={fg}/>;
  });
  const blades = frame==='shutter' && Array.from({length:6}).map((_,i)=>{
    const a=(i/6)*Math.PI*2, rr=size/2+pad*0.45, x=cx+Math.cos(a)*rr, y=cy+Math.sin(a)*rr;
    return <line key={i} x1={-pad*0.45} y1="0" x2={pad*0.45} y2="0" transform={`translate(${x},${y}) rotate(${a*180/Math.PI+55})`} stroke="white" strokeWidth={cell*0.55} strokeLinecap="round"/>;
  });
  const labelW = frame==='pill'? size*0.5 : Math.min(size*0.72, W-pad*1.2);
  const labelY = pad+size+pad*0.45;
  const arcR = frame==='donut'? size/2+pad*0.5 : size/2+pad*0.55;
  const labelEl = (w,rx) => (<g>
    <rect x={cx-w/2} y={labelY} width={w} height={lh} rx={rx} fill={color}/>
    <text x={cx} y={labelY+lh/2+1} textAnchor="middle" dominantBaseline="central" fontSize={Math.min(lh*0.5, w/(label.length*0.72+1))} fontWeight="800" letterSpacing="1" fill="white">{label}</text>
  </g>);
  return (
    <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} className="block">
      <defs><path id={uid+'arc'} d={`M ${cx-arcR} ${cy} A ${arcR} ${arcR} 0 0 1 ${cx+arcR} ${cy}`} fill="none"/></defs>
      {frame==='cardfill'
        ? <g><rect width={W} height={H} rx={size*0.1} fill={color}/><rect x={pad*0.3} y={pad*0.3} width={W-pad*0.6} height={labelY-pad*0.15-pad*0.3} rx={size*0.06} fill="white"/></g>
        : <rect width={W} height={H} fill="white"/>}
      {frame==='shadow' && <g>
        <rect x={pad*0.3+size*0.035} y={pad*0.3+size*0.035} width={W-pad*0.6} height={H-pad*0.6} rx={size*0.09} fill={color}/>
        <rect x={pad*0.3} y={pad*0.3} width={W-pad*0.6} height={H-pad*0.6} rx={size*0.09} fill="white" stroke={color} strokeWidth={Math.max(1.5,size*0.025)}/>
      </g>}
      {inv && <circle cx={cx} cy={cy} r={size/2+pad*0.85} fill={color}/>}
      {blades}
      {frame==='donut' && <g>
        <circle cx={cx} cy={cy} r={arcR} fill="none" stroke={color} strokeWidth={pad*0.55}/>
        <text fontSize={pad*0.34} fontWeight="800" letterSpacing="2" fill="white"><textPath href={'#'+uid+'arc'} startOffset="50%" textAnchor="middle">{label}</textPath></text>
      </g>}
      {frame==='archtext' && <text fontSize={pad*0.42} fontWeight="800" letterSpacing="2" fill={color}><textPath href={'#'+uid+'arc'} startOffset="50%" textAnchor="middle">{label}</textPath></text>}
      {frame==='ring' && <circle cx={cx} cy={cy} r={R} fill="none" stroke={fg} strokeWidth={Math.max(1.5,size*0.022)}/>}
      {frame==='dashed' && <circle cx={cx} cy={cy} r={R} fill="none" stroke={fg} strokeWidth={Math.max(1.5,size*0.025)} strokeDasharray={`${size*0.08} ${size*0.055}`} strokeLinecap="round"/>}
      {frame==='arcs' && <circle cx={cx} cy={cy} r={R} fill="none" stroke={fg} strokeWidth={Math.max(2,cell*0.8)} strokeDasharray={`${2*Math.PI*R*0.17} ${2*Math.PI*R*0.08}`} strokeLinecap="round" transform={`rotate(-30 ${cx} ${cy})`}/>}
      {confetti}{burst}{dotring}
      {frame==='border' && <rect x={pad*0.35} y={pad*0.35} width={W-pad*0.7} height={W-pad*0.7} rx={size*0.02} fill="none" stroke={fg} strokeWidth={Math.max(2,size*0.045)}/>}
      <g transform={`translate(${pad},${pad})`}>
        {mods.map(([r,c])=>pattern==='dots'
          ? <circle key={r+'-'+c} cx={(c+0.5)*cell} cy={(r+0.5)*cell} r={cell*0.42} fill={fg}/>
          : <rect key={r+'-'+c} x={c*cell+(pattern==='rounded'?cell*0.08:0)} y={r*cell+(pattern==='rounded'?cell*0.08:0)} width={cell*(pattern==='rounded'?0.84:1)} height={cell*(pattern==='rounded'?0.84:1)} rx={pattern==='rounded'?cell*0.3:0} fill={fg}/>)}
        {eyeEl(0,0)}{eyeEl(N-7,0)}{eyeEl(0,N-7)}
        {logoUrl && <g><rect x={10*cell} y={10*cell} width={cell*5} height={cell*5} rx={cell} fill="white"/><image href={logoUrl} x={10.3*cell} y={10.3*cell} width={cell*4.4} height={cell*4.4} preserveAspectRatio="xMidYMid meet"/></g>}
      </g>
      {frame==='tab' && <g><polygon points={`${cx-lh*0.4},${labelY+1} ${cx+lh*0.4},${labelY+1} ${cx},${labelY-lh*0.45}`} fill={color}/>{labelEl(labelW, lh*0.28)}</g>}
      {frame==='pill' && labelEl(labelW, lh/2)}
      {frame==='shadow' && labelEl(labelW, lh*0.28)}
      {frame==='cardfill' && <text x={cx} y={labelY+lh/2+1} textAnchor="middle" dominantBaseline="central" fontSize={Math.min(lh*0.55, labelW/(label.length*0.72+1))} fontWeight="800" letterSpacing="1.5" fill="white">{label}</text>}
    </svg>
  );
}
const QR_TEMPLATES = [
  { id:'classic',  lb:'Classic',  p:{pattern:'square',  eye:'square',  frame:'none'} },
  { id:'border',   lb:'Border',   p:{pattern:'square',  eye:'square',  frame:'border'} },
  { id:'donut',    lb:'Donut',    p:{pattern:'dots',    eye:'rounded', frame:'donut'} },
  { id:'cardfill', lb:'Card',     p:{pattern:'square',  eye:'rounded', frame:'cardfill'} },
  { id:'shadow',   lb:'Shadow',   p:{pattern:'rounded', eye:'rounded', frame:'shadow'} },
  { id:'tab',      lb:'Tab',      p:{pattern:'square',  eye:'rounded', frame:'tab'} },
  { id:'pill',     lb:'Pill',     p:{pattern:'square',  eye:'square',  frame:'pill'} },
  { id:'confetti', lb:'Confetti', p:{pattern:'dots',    eye:'rounded', frame:'confetti'} },
  { id:'arcs',     lb:'Arcs',     p:{pattern:'square',  eye:'rounded', frame:'arcs'} },
  { id:'ring',     lb:'Ring',     p:{pattern:'dots',    eye:'rounded', frame:'ring'} },
  { id:'burst',    lb:'Burst',    p:{pattern:'square',  eye:'square',  frame:'burst'} },
  { id:'shutter',  lb:'Shutter',  p:{pattern:'square',  eye:'square',  frame:'shutter'} },
  { id:'inverted', lb:'Inverted', p:{pattern:'square',  eye:'square',  frame:'inverted'} },
  { id:'archtext', lb:'Arch text',p:{pattern:'dots',    eye:'rounded', frame:'archtext'} },
  { id:'dashed',   lb:'Dashed',   p:{pattern:'dots',    eye:'rounded', frame:'dashed'} },
  { id:'dotring',  lb:'Dot ring', p:{pattern:'dots',    eye:'rounded', frame:'dotring'} },
];
const QR_COLORS = [['#1B2733','Ink'],['#0E6FA8','Brand blue'],['#0F766E','Teal'],['#166B4A','Forest'],['#6D28D9','Violet'],['#3730A3','Indigo'],['#B4232A','Crimson'],['#B45309','Amber'],['#BE185D','Rose'],['#334155','Slate']];
function QrPopover({ name, onClose }) {
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-ink/40 p-4" onClick={onClose}>
      <div className="bg-white rounded-3xl shadow-pop p-7 w-[320px] text-center" onClick={e=>e.stopPropagation()}>
        <p className="text-[15px] font-extrabold text-ink">{name}</p>
        <p className="text-[12px] text-ink-muted mt-1">Scan to open the claim page</p>
        <div className="mx-auto my-5 flex justify-center rounded-2xl border border-line bg-white p-2"><StudioQR size={200} color="#000000" pattern="square" eye="square" frame="none" logoUrl={null}/></div>
        <div className="flex gap-2">
          <button className="flex-1 rounded-full py-2.5 text-[13px] font-bold text-white bg-gradient-to-b from-brand to-brand-dark shadow-btn">Download PNG</button>
          <button onClick={onClose} className="flex-1 rounded-full py-2.5 text-[13px] font-bold text-ink border border-line hover:bg-surface-subtle">Close</button>
        </div>
      </div>
    </div>
  );
}

/* kebab menu — collapses row actions into one control */
function Kebab({ onEdit, onCopy, onQr, copied }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', h); return () => document.removeEventListener('mousedown', h);
  }, [open]);
  const Item = ({ children, onClick, danger }) => (
    <button onClick={()=>{onClick&&onClick(); if(!danger) setOpen(false);}}
      className={"w-full text-left px-3.5 py-2 text-[12.5px] font-semibold rounded-lg transition-colors "+(danger?"text-rose-600 hover:bg-rose-50":"text-ink hover:bg-surface-subtle")}>
      {children}
    </button>
  );
  return (
    <div className="relative" ref={ref}>
      <button onClick={()=>setOpen(o=>!o)} className={"w-8 h-8 rounded-lg flex items-center justify-center transition-colors "+(open?"bg-surface-input text-ink":"text-ink-soft hover:bg-surface-input hover:text-ink")}>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="1.8"/><circle cx="12" cy="12" r="1.8"/><circle cx="12" cy="19" r="1.8"/></svg>
      </button>
      {open && (
        <div className="absolute right-0 top-9 z-40 w-44 bg-white rounded-xl border border-line shadow-pop p-1.5">
          <Item onClick={onCopy}>{copied ? 'Copied!' : 'Copy claim link'}</Item>
          <Item onClick={onQr}>Show QR code</Item>
          <Item onClick={onEdit}>Edit campaign</Item>
          <Item danger>Delete</Item>
        </div>
      )}
    </div>
  );
}

const PromoAvatar = ({ kind }) => (
  <span className="w-10 h-10 rounded-xl bg-surface-input flex items-center justify-center shrink-0"><PromoIcon kind={kind}/></span>
);

/* 1 — List rows: aligned table with headers + share actions */
const CAMP_COLS = 'minmax(190px,1.6fr) minmax(88px,1fr) minmax(110px,1fr) minmax(150px,1.2fr) minmax(56px,.6fr) minmax(120px,1fr) 40px';
function CampListRows({ rows, all, onNav, setQr, copy, copied }) {
  return (
    <Card className="overflow-hidden">
      <div className="overflow-x-auto">
      <div className="min-w-[900px]">
      <div className="grid items-center gap-3 px-5 py-3 bg-surface-subtle text-[11px] font-bold uppercase tracking-wider text-ink-muted border-b border-line" style={{gridTemplateColumns:CAMP_COLS}}>
        <span>Campaign</span><span>Products</span><span>Claim rule</span><span>Performance</span><span>Status</span><span>Share</span><span></span>
      </div>
      <div className="divide-y divide-gray-100">
      {rows.map((c) => {
        const i = all.indexOf(c);
        return (
          <div key={c.name} className="grid items-center gap-3 px-5 py-3 hover:bg-surface-subtle transition-colors" style={{gridTemplateColumns:CAMP_COLS}}>
            <span className="flex items-center gap-2.5 min-w-0">
              <PromoAvatar kind={c.icon}/>
              <span className="min-w-0">
                <span className="block font-bold text-[13px] text-ink leading-snug truncate">{c.name}</span>
                <span className="block text-[11.5px] text-ink-muted truncate">{c.promo}</span>
              </span>
            </span>
            <span><ProductStack n={c.products} hue={(i*47)%360}/></span>
            <span><ClaimBadge kind={c.claims}/></span>
            <span><PerfBar claimed={c.claimed} reviews={c.reviews}/></span>
            <StatusToggle checked={c.status}/>
            <span className="flex items-center gap-1.5">
              <button onClick={()=>copy(i)} title="Copy claim link"
                className={"h-8 rounded-lg px-2.5 flex items-center gap-1.5 text-[11.5px] font-bold transition-colors whitespace-nowrap "+(copied===i?"bg-green-50 text-green-700":"bg-brand-50 text-brand hover:bg-brand hover:text-white")}>
                <LinkIcon/>{copied===i?'Copied!':'Link'}
              </button>
              <button onClick={()=>setQr(i)} title="Show QR code"
                className="w-8 h-8 rounded-lg bg-brand-50 text-brand hover:bg-brand hover:text-white flex items-center justify-center transition-colors shrink-0"><QrIcon/></button>
            </span>
            <span className="flex justify-end"><Kebab copied={copied===i} onCopy={()=>copy(i)} onQr={()=>setQr(i)} onEdit={()=>onNav('campaign-add')}/></span>
          </div>
        );
      })}
      </div>
      </div>
      </div>
    </Card>
  );
}

/* 2 — Compact table: 4 tight columns, meta stacked in the campaign cell */
function CampCompactTable({ rows, all, onNav, setQr, copy, copied }) {
  return (
    <Card className="overflow-hidden">
      <div className="overflow-x-auto">
      <table className="w-full min-w-[640px] text-[13px]">
        <thead>
          <tr className="bg-surface-subtle text-[11.5px] uppercase tracking-wider text-ink-muted">
            <th className="text-left font-semibold px-5 py-3.5">Campaign</th>
            <th className="text-left font-semibold px-3 py-3.5 w-48">Performance</th>
            <th className="text-left font-semibold px-3 py-3.5 w-20">Status</th>
            <th className="text-right font-semibold px-5 py-3.5 w-32">Actions</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((c) => {
            const i = all.indexOf(c);
            return (
              <tr key={c.name} className="border-t border-gray-100 hover:bg-surface-subtle">
                <td className="px-5 py-3.5">
                  <div className="flex items-center gap-3.5">
                    <PromoAvatar kind={c.icon}/>
                    <div className="min-w-0">
                      <p className="font-bold text-ink leading-snug">{c.name}</p>
                      <p className="mt-1 flex flex-wrap items-center gap-x-2.5 gap-y-1 text-[12px] text-ink-muted">
                        <span className="truncate max-w-[200px]">{c.promo}</span>
                        <ClaimBadge kind={c.claims}/>
                        <span className="whitespace-nowrap">{c.products} product{c.products>1?'s':''}</span>
                      </p>
                    </div>
                  </div>
                </td>
                <td className="px-3 py-3.5"><PerfBar claimed={c.claimed} reviews={c.reviews}/></td>
                <td className="px-3 py-3.5"><StatusToggle checked={c.status}/></td>
                <td className="px-5 py-3.5">
                  <div className="flex justify-end"><Kebab copied={copied===i} onCopy={()=>copy(i)} onQr={()=>setQr(i)} onEdit={()=>onNav('campaign-add')}/></div>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
      </div>
    </Card>
  );
}

/* 3 — Cards: grid of campaign cards */
function CampCards({ rows, all, onNav, setQr, copy, copied }) {
  return (
    <div className="grid gap-4" style={{gridTemplateColumns:'repeat(auto-fill, minmax(290px, 1fr))'}}>
      {rows.map((c) => {
        const i = all.indexOf(c);
        return (
          <div key={c.name} className="bg-white rounded-2xl border border-line shadow-soft hover:shadow-card hover:border-brand-200 transition-all p-5 flex flex-col gap-4">
            <div className="flex items-start gap-3">
              <PromoAvatar kind={c.icon}/>
              <div className="min-w-0 flex-1">
                <p className="font-bold text-[13.5px] text-ink leading-snug">{c.name}</p>
                <p className="text-[12px] text-ink-muted truncate mt-0.5">{c.promo}</p>
              </div>
              <StatusToggle checked={c.status}/>
            </div>
            <div className="flex items-center justify-between">
              <ProductStack n={c.products} hue={(i*47)%360}/>
              <ClaimBadge kind={c.claims}/>
            </div>
            <PerfBar claimed={c.claimed} reviews={c.reviews}/>
            <div className="pt-3 border-t border-line/70 flex items-center justify-between">
              <div className="flex gap-2">
                <button onClick={()=>copy(i)} className={"h-8 rounded-lg px-2.5 flex items-center gap-1.5 text-[11.5px] font-bold transition-colors "+(copied===i?"bg-green-50 text-green-700":"bg-brand-50 text-brand hover:bg-brand hover:text-white")}><LinkIcon/>{copied===i?'Copied!':'Link'}</button>
                <button onClick={()=>setQr(i)} title="Show QR code" className="w-8 h-8 rounded-lg bg-brand-50 text-brand hover:bg-brand hover:text-white flex items-center justify-center transition-colors"><QrIcon/></button>
              </div>
              <RowActions onEdit={()=>onNav('campaign-add')}/>
            </div>
          </div>
        );
      })}
    </div>
  );
}

const CAMP_LAYOUTS = { 'List rows':CampListRows, 'Compact table':CampCompactTable, 'Cards':CampCards };

function CampaignsV2({ onNav, layout='List rows' }) {
  const [query, setQuery]   = React.useState('');
  const [filter, setFilter] = React.useState('all');   // all | active | inactive
  const [qr, setQr]         = React.useState(null);    // row index for popover
  const [copied, setCopied] = React.useState(null);
  const rows = CAMPS_V2
    .filter(c => c.name.toLowerCase().includes(query.toLowerCase()))
    .filter(c => filter === 'all' ? true : filter === 'active' ? c.status : !c.status);
  const active = CAMPS_V2.filter(c=>c.status).length;
  const totalReviews = CAMPS_V2.reduce((a,c)=>a+c.reviews,0);
  const copy = (i) => { setCopied(i); setTimeout(()=>setCopied(null), 1400); };
  return (
    <>
      <PageHeader title="Campaigns" action={
        <BtnPrimary icon={<PlusIcon/>} onClick={() => onNav('campaign-add')}>Add Campaign</BtnPrimary>
      }/>
      <div className="px-7 py-6 space-y-5">
        <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
          <StatTileV2 label="All campaigns" value={CAMPS_V2.length} sub={`${CAMPS_V2.reduce((a,c)=>a+c.products,0)} products covered`} active={filter==='all'} onClick={()=>setFilter('all')}/>
          <StatTileV2 label="Active" value={active} sub="collecting reviews now" active={filter==='active'} onClick={()=>setFilter('active')}/>
          <StatTileV2 label="Inactive" value={CAMPS_V2.length-active} sub="paused or draft" active={filter==='inactive'} onClick={()=>setFilter('inactive')}/>
          <StatTileV2 label="Reviews collected" value={totalReviews} sub="across all campaigns" onClick={()=>{}}/>
        </div>
        <SearchInput placeholder="Search by campaign name" value={query} onChange={e=>setQuery(e.target.value)}/>
        {rows.length === 0 ? (
          <div className="bg-white rounded-2xl border border-line shadow-soft py-16 text-center">
            <p className="text-[15px] font-bold text-ink">No campaigns match</p>
            <p className="text-[13px] text-ink-muted mt-1">Try a different search or clear the filter.</p>
            <button onClick={()=>{setQuery('');setFilter('all');}} className="mt-4 text-[13px] font-bold text-brand hover:text-brand-dark">Clear filters</button>
          </div>
        ) : (
          React.createElement(CAMP_LAYOUTS[layout] || CampListRows, { rows, all:CAMPS_V2, onNav, setQr, copy, copied })
        )}
        {qr !== null && <QrPopover name={CAMPS_V2[qr].name} onClose={()=>setQr(null)}/>}
      </div>
    </>
  );
}

window.Campaigns = CampaignsV2;
CampaignsV2.v2 = true;
