// tnych-modal.jsx — LinkModal (create/edit) + QRModal
const { useState: useSt } = React;

function genCode() {
  const c = 'abcdefghijkmnpqrstuvwxyz23456789';
  return Array.from({ length: 5 }, () => c[Math.floor(Math.random() * c.length)]).join('');
}

function buildFinalUrl(f) {
  if (!f.dest) return '';
  const p = [
    f.utmSource   && `utm_source=${encodeURIComponent(f.utmSource)}`,
    f.utmMedium   && `utm_medium=${encodeURIComponent(f.utmMedium)}`,
    f.utmCampaign && `utm_campaign=${encodeURIComponent(f.utmCampaign)}`,
    f.utmContent  && `utm_content=${encodeURIComponent(f.utmContent)}`,
    f.utmTerm     && `utm_term=${encodeURIComponent(f.utmTerm)}`,
  ].filter(Boolean);
  if (!p.length) return f.dest;
  return f.dest + (f.dest.includes('?') ? '&' : '?') + p.join('&');
}

/* ── Discord-style embed preview ── */
function EmbedPreview({ title, desc, mediaType, mediaUrl, color, domain, shortCode }) {
  const accent = color || '#2ec4ca';
  return (
    <div style={{ borderRadius:6, overflow:'hidden', border:'1px solid var(--border)', background:'oklch(16% 0.008 230)', maxWidth:420 }}>
      <div style={{ borderLeft:`4px solid ${accent}`, padding:'12px 14px' }}>
        <div style={{ fontSize:11, color:'var(--text-dim)', marginBottom:4, fontWeight:500 }}>{domain}/{shortCode}</div>
        {title && <div style={{ fontSize:15, fontWeight:700, color:'var(--text)', marginBottom:4, lineHeight:1.4 }}>{title}</div>}
        {desc  && <div style={{ fontSize:13, color:'var(--text-muted)', lineHeight:1.6, marginBottom: mediaUrl?8:0 }}>{desc}</div>}
        {mediaUrl
          ? <div style={{ marginTop:6, borderRadius:4, overflow:'hidden', background:'var(--surface-2)', maxHeight:160, display:'flex', alignItems:'center', justifyContent:'center' }}>
              <img src={mediaUrl} alt="embed media" style={{ maxWidth:'100%', maxHeight:160, objectFit:'cover', display:'block' }}
                onError={e=>{ e.target.style.display='none'; e.target.nextSibling.style.display='flex'; }}/>
              <div style={{ display:'none', alignItems:'center', justifyContent:'center', height:80, fontSize:12, color:'var(--text-dim)', padding:8, textAlign:'center' }}>
                {mediaType==='gif'?'GIF':'Image'} preview — paste a URL above to test
              </div>
            </div>
          : <div style={{ marginTop:6, borderRadius:4, background:'var(--surface-2)', height:70, display:'flex', alignItems:'center', justifyContent:'center', fontSize:11, color:'var(--text-dim)', fontStyle:'italic' }}>
              no {mediaType==='gif'?'gif':'image'} url set
            </div>
        }
      </div>
    </div>
  );
}

/* ── Canvas QR helpers ── */
async function overlayLogoOnCanvas(canvas, logoUrl, bgColor) {
  return new Promise(resolve => {
    const img = new Image();
    img.crossOrigin = 'anonymous';
    img.onload = () => {
      const ctx = canvas.getContext('2d');
      const s   = canvas.width;
      const ls  = Math.round(s * 0.22);
      const x   = (s - ls) / 2;
      const y   = (s - ls) / 2;
      const pad = Math.round(s * 0.03);
      ctx.fillStyle = bgColor;
      ctx.beginPath();
      if (ctx.roundRect) ctx.roundRect(x - pad, y - pad, ls + pad*2, ls + pad*2, pad);
      else ctx.rect(x - pad, y - pad, ls + pad*2, ls + pad*2);
      ctx.fill();
      ctx.drawImage(img, x, y, ls, ls);
      resolve();
    };
    img.onerror = resolve;
    img.src = logoUrl;
  });
}

/* Build qrserver.com URL */
function qrApiUrl(url, fg, bg, size, margin=2) {
  const fgHex = (fg || '#000000').replace(/^#/, '');
  const bgHex = (bg || '#ffffff').replace(/^#/, '');
  return `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${encodeURIComponent(url)}&color=${fgHex}&bgcolor=${bgHex}&margin=${margin}&ecc=H`;
}

/* Download QR: fetch from same-origin proxy (no CORS taint) → canvas → optional logo → save */
async function downloadQRCanvas(url, fg, bg, size, logoUrl, filename) {
  const proxyUrl = `/api/qr?${new URLSearchParams({ data: url, fg: fg||'#000000', bg: bg||'#ffffff', size, margin: 3, ecc: 'H' })}`;
  const fallbackUrl = qrApiUrl(url, fg, bg, size, 3);
  const canvas = document.createElement('canvas');
  canvas.width = size; canvas.height = size;
  const ctx = canvas.getContext('2d');
  try {
    const qrImg = new Image();
    await new Promise((res, rej) => { qrImg.onload = res; qrImg.onerror = rej; qrImg.src = proxyUrl; });
    ctx.drawImage(qrImg, 0, 0, size, size);
    if (logoUrl) await overlayLogoOnCanvas(canvas, logoUrl, bg || '#ffffff');
    let dataUrl;
    try {
      dataUrl = canvas.toDataURL('image/png');
    } catch (_) {
      // logo cross-origin tainted canvas — re-draw QR only
      ctx.clearRect(0, 0, size, size);
      ctx.drawImage(qrImg, 0, 0, size, size);
      dataUrl = canvas.toDataURL('image/png');
    }
    const a = document.createElement('a'); a.download = filename; a.href = dataUrl; a.click();
  } catch(e) {
    const a = document.createElement('a'); a.href = fallbackUrl; a.target = '_blank'; a.click();
  }
}

function BrandedQRPreview({ url, fg, bg, logoUrl, size=260 }) {
  if (!url) return null;
  const src = qrApiUrl(url, fg, bg, size);
  return (
    <div style={{ position:'relative', display:'inline-block', lineHeight:0, borderRadius:8, overflow:'hidden' }}>
      <img src={src} width={size} height={size} alt="QR Code" style={{ display:'block', maxWidth:'100%' }} />
      {logoUrl && (
        <div style={{ position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center', pointerEvents:'none' }}>
          <div style={{
            width: Math.round(size*0.24), height: Math.round(size*0.24),
            background: bg || '#ffffff', borderRadius: Math.round(size*0.035),
            padding: Math.round(size*0.025),
            display:'flex', alignItems:'center', justifyContent:'center', overflow:'hidden',
          }}>
            <img src={logoUrl} alt="logo"
              style={{ maxWidth:'100%', maxHeight:'100%', objectFit:'contain' }}
              onError={e => { e.target.style.display='none'; }}/>
          </div>
        </div>
      )}
    </div>
  );
}

/* ── Field label ── */
const FL = ({ children }) =>
  <div style={{ fontSize:11, fontWeight:700, color:'var(--text-muted)', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:6 }}>{children}</div>;

/* ── Tab button ── */
const TB = ({ active, onClick, children }) =>
  <button onClick={onClick} style={{
    padding:'7px 14px', borderRadius:7, border:'none', cursor:'pointer',
    fontFamily:'inherit', fontSize:13, fontWeight:600, transition:'all 0.15s',
    background: active ? 'var(--surface-hi)' : 'transparent',
    color:       active ? 'var(--text)'       : 'var(--text-dim)',
  }}>{children}</button>;

/* ── Toggle row ── */
function ToggleRow({ label, sub, value, onChange }) {
  return (
    <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16 }}>
      <div>
        <div style={{ fontSize:13, fontWeight:600, color:'var(--text)' }}>{label}</div>
        {sub && <div style={{ fontSize:12, color:'var(--text-muted)', marginTop:2, lineHeight:1.5 }}>{sub}</div>}
      </div>
      <button className={`toggle${value?' on':''}`} onClick={()=>onChange(!value)}/>
    </div>
  );
}

/* ── Vis radio ── */
function VisRadio({ value, onChange }) {
  return (
    <div style={{ display:'flex', gap:8 }}>
      {[{v:'public',l:'🌐 Public'},{v:'private',l:'🔒 Private'},{v:'restricted',l:'🔏 Restricted'}].map(({v,l})=>
        <button key={v} onClick={()=>onChange(v)} style={{
          flex:1, padding:'8px 6px', borderRadius:8,
          border:`1px solid ${value===v?'var(--accent)':'var(--border)'}`,
          background: value===v ? 'var(--accent-dim)' : 'var(--surface-hi)',
          color:       value===v ? 'var(--accent)'    : 'var(--text-muted)',
          cursor:'pointer', fontFamily:'inherit', fontSize:12, fontWeight:600, transition:'all 0.15s',
        }}>{l}</button>
      )}
    </div>
  );
}

/* ── Color picker: hex input + native picker + last-5 recents ── */
const RECENT_COLORS_KEY = 'tnych-recent-colors';
const getRecentColors = () => { try { return JSON.parse(localStorage.getItem(RECENT_COLORS_KEY) || '[]'); } catch { return []; } };
const pushRecentColor = (hex) => {
  const n = hex.toLowerCase();
  localStorage.setItem(RECENT_COLORS_KEY, JSON.stringify([n, ...getRecentColors().filter(c => c !== n)].slice(0, 5)));
};

function ColorPicker({ label, value, onChange }) {
  const [recents, setRecents] = useSt(getRecentColors);
  const raw = (value || '#000000').replace(/^#/, '');
  const fullHex = `#${raw.padEnd(6, '0')}`;
  const isValid = /^[0-9a-fA-F]{6}$/.test(raw);

  const commit = (hex) => {
    onChange(hex);
    pushRecentColor(hex);
    setRecents(getRecentColors());
  };

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:5 }}>
      {label && <FL>{label}</FL>}
      <div style={{ display:'flex', gap:6, alignItems:'center' }}>
        {/* Hex text input */}
        <div style={{ flex:1, position:'relative', display:'flex', alignItems:'center' }}>
          <span style={{ position:'absolute', left:9, fontSize:12, color:'var(--text-dim)', pointerEvents:'none', fontFamily:"'Space Grotesk',monospace" }}>#</span>
          <input
            className="input input-sm"
            value={raw}
            maxLength={6}
            onChange={e => {
              const v = e.target.value.replace(/[^0-9a-fA-F]/g, '').slice(0, 6);
              onChange('#' + v);
              if (v.length === 6) { pushRecentColor('#' + v); setRecents(getRecentColors()); }
            }}
            style={{ paddingLeft:22, fontFamily:"'Space Grotesk',monospace", letterSpacing:'0.04em', fontSize:12 }}
            placeholder="000000"
          />
        </div>
        {/* Color swatch — clicking opens native picker */}
        <div style={{ position:'relative', width:30, height:30, flexShrink:0 }}>
          <div style={{ width:30, height:30, borderRadius:7, background:isValid ? `#${raw}` : '#888', border:'1px solid var(--border)' }}/>
          <input type="color" value={isValid ? fullHex : '#888888'} onChange={e => commit(e.target.value)}
            style={{ position:'absolute', inset:0, opacity:0, width:'100%', height:'100%', cursor:'pointer', padding:0, margin:0 }}/>
        </div>
      </div>
      {/* Recent swatches */}
      {recents.length > 0 && (
        <div style={{ display:'flex', gap:4 }}>
          {recents.map(c => (
            <button key={c} onClick={() => commit(c)} title={c} style={{
              width:20, height:20, borderRadius:5, background:c, flexShrink:0, padding:0, cursor:'pointer',
              border: c === `#${raw}` ? '2px solid var(--accent)' : '1px solid var(--border)',
            }}/>
          ))}
        </div>
      )}
    </div>
  );
}

/* ─────────────────────────────────────────────────
   LINK MODAL — 4 tabs: General / Tracking / Embed / QR
───────────────────────────────────────────────── */
function LinkModal({ link, domain, allLinks, onSave, onClose }) {
  const INIT = link ? { ...link } : {
    shortCode:'', dest:'', label:'', visibility:'public', active:true,
    scammerTrap:false, trackDetails:false,
    utmSource:'', utmMedium:'', utmCampaign:'', utmContent:'', utmTerm:'',
    embedEnabled:false, embedTitle:'', embedDesc:'',
    embedMediaType:'image', embedMediaUrl:'', embedColor:'#2ec4ca',
  };
  const [form, setForm] = useSt({...INIT, shortCode: INIT.shortCode || genCode()});
  const [tab,     setTab]     = useSt('general');
  const [codeErr, setCodeErr] = useSt('');

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSave = () => {
    if (!form.dest.trim()) return;
    const conflict = allLinks.find(l => l.shortCode === form.shortCode && l.id !== form.id);
    if (conflict) { setCodeErr('Short code already in use.'); setTab('general'); return; }
    onSave(form);
  };

  const finalUrl = buildFinalUrl(form);
  const shortUrl = `https://${domain}/${form.shortCode}`;

  /* ── General tab ── */
  const tabGeneral = (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      <div>
        <FL>Short URL</FL>
        <div style={{ display:'flex', gap:6 }}>
          <div style={{ display:'flex', alignItems:'center', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:'8px 0 0 8px', padding:'0 10px', fontSize:13, color:'var(--text-dim)', whiteSpace:'nowrap', borderRight:'none' }}>
            {domain}/
          </div>
          <input className="input" value={form.shortCode}
            onChange={e=>{ set('shortCode', e.target.value.replace(/[^a-z0-9_-]/gi,'').toLowerCase()); setCodeErr(''); }}
            style={{ borderRadius:'0 8px 8px 0', flex:1 }} placeholder="my-link"/>
          <button className="btn btn-surface btn-sm" onClick={()=>set('shortCode', genCode())} title="Regenerate" style={{ flexShrink:0 }}>↻</button>
        </div>
        {codeErr && <p style={{ fontSize:12, color:'var(--danger)', marginTop:4 }}>{codeErr}</p>}
      </div>
      <div>
        <FL>Destination URL</FL>
        <input className="input" value={form.dest} onChange={e=>set('dest', e.target.value)} placeholder="https://example.com/your-long-url"/>
      </div>
      <div>
        <FL>Label <span style={{ fontWeight:400, textTransform:'none', letterSpacing:0, color:'var(--text-dim)' }}>(optional)</span></FL>
        <input className="input" value={form.label} onChange={e=>set('label', e.target.value)} placeholder="A short note for yourself"/>
      </div>
      <div>
        <FL>Visibility</FL>
        <VisRadio value={form.visibility} onChange={v=>set('visibility', v)}/>
      </div>
      <ToggleRow label="Active" sub="Inactive links return a 404." value={form.active} onChange={v=>set('active', v)}/>
    </div>
  );

  /* ── Tracking tab ── */
  const tabTracking = (
    <div style={{ display:'flex', flexDirection:'column', gap:20 }}>
      <div>
        <div style={{ fontSize:12, fontWeight:700, color:'var(--text-muted)', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:12 }}>UTM Parameters</div>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
          {[['utmSource','Source','e.g. twitter'],['utmMedium','Medium','e.g. social'],['utmCampaign','Campaign','e.g. summer-launch'],['utmContent','Content','optional'],['utmTerm','Term','optional']].map(([k,l,ph])=>
            <div key={k}>
              <FL>{l}</FL>
              <input className="input input-sm" value={form[k]} onChange={e=>set(k, e.target.value)} placeholder={ph}/>
            </div>
          )}
        </div>
        {finalUrl && finalUrl !== form.dest &&
          <div style={{ marginTop:12 }}>
            <FL>Final URL preview</FL>
            <div style={{ fontSize:11, color:'var(--text-muted)', background:'var(--surface-2)', borderRadius:7, padding:'8px 10px', wordBreak:'break-all', lineHeight:1.6, fontFamily:"'Space Grotesk',monospace" }}>
              {finalUrl}
            </div>
          </div>
        }
      </div>
      <div style={{ borderTop:'1px solid var(--border)', paddingTop:18 }}>
        <div style={{ fontSize:12, fontWeight:700, color:'var(--text-muted)', textTransform:'uppercase', letterSpacing:'0.06em', marginBottom:12 }}>Visitor Logging</div>
        <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
          <ToggleRow
            label="Track visit details"
            sub="Logs browser, OS, device, screen, language, referrer, and timestamp for each click."
            value={form.trackDetails}
            onChange={v=>{ set('trackDetails', v); if (!v) set('scammerTrap', false); }}/>
          <div style={{ padding:'14px 16px', background:'oklch(62% 0.17 25 / 0.06)', border:'1px solid oklch(62% 0.17 25 / 0.22)', borderRadius:10 }}>
              <ToggleRow
                label="🪤 Trap Link"
                sub="Like Grabify — a bait link that silently captures the visitor's IP address, geolocation, device, browser, OS, and referrer before redirecting. Use to identify who is clicking your links. Enabling this automatically turns on visit tracking."
                value={form.scammerTrap}
                onChange={v=>{ set('scammerTrap', v); if (v) set('trackDetails', true); }}/>
            </div>
        </div>
      </div>
    </div>
  );

  /* ── Embed tab ── */
  const tabEmbed = (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      <ToggleRow
        label="Enable link embed"
        sub="Controls Open Graph metadata — shown when this link is pasted in Discord, Slack, etc."
        value={form.embedEnabled}
        onChange={v=>set('embedEnabled', v)}/>
      {form.embedEnabled &&
        <div style={{ display:'flex', flexDirection:'column', gap:14, paddingTop:4, animation:'fadeUp 0.2s ease both' }}>
          <div>
            <FL>Title</FL>
            <input className="input" value={form.embedTitle} onChange={e=>set('embedTitle', e.target.value)} placeholder="Page title shown in embeds"/>
          </div>
          <div>
            <FL>Description</FL>
            <textarea className="input" value={form.embedDesc} onChange={e=>set('embedDesc', e.target.value)}
              placeholder="Short description…" rows={2} style={{ resize:'vertical', fontFamily:'inherit', lineHeight:1.5 }}/>
          </div>
          <div>
            <FL>Media type</FL>
            <div style={{ display:'flex', gap:6 }}>
              {['image','gif'].map(t=>
                <button key={t} onClick={()=>set('embedMediaType', t)} style={{
                  flex:1, padding:'7px', borderRadius:7,
                  border:`1px solid ${form.embedMediaType===t?'var(--accent)':'var(--border)'}`,
                  background: form.embedMediaType===t ? 'var(--accent-dim)' : 'var(--surface-hi)',
                  color:       form.embedMediaType===t ? 'var(--accent)'    : 'var(--text-muted)',
                  cursor:'pointer', fontFamily:'inherit', fontSize:12, fontWeight:600, textTransform:'uppercase',
                }}>{t}</button>
              )}
            </div>
          </div>
          <div>
            <FL>{form.embedMediaType==='gif'?'GIF URL':'Image URL'}</FL>
            <input className="input" value={form.embedMediaUrl} onChange={e=>set('embedMediaUrl', e.target.value)} placeholder="https://…"/>
          </div>
          <ColorPicker label="Accent color" value={form.embedColor} onChange={v=>set('embedColor', v)}/>
          <div>
            <FL>Live Preview</FL>
            <EmbedPreview title={form.embedTitle} desc={form.embedDesc}
              mediaType={form.embedMediaType} mediaUrl={form.embedMediaUrl}
              color={form.embedColor} domain={domain} shortCode={form.shortCode}/>
          </div>
        </div>
      }
    </div>
  );

  /* ── QR tab ── */
  const [qrSize,    setQrSize]    = useSt(512);
  const [qrFg,      setQrFg]      = useSt('#000000');
  const [qrBg,      setQrBg]      = useSt('#ffffff');
  const [qrLogoUrl, setQrLogoUrl] = useSt('');


  const downloadQR = async () => {
    await downloadQRCanvas(shortUrl, qrFg, qrBg, qrSize, qrLogoUrl, `qr-${form.shortCode||'code'}.png`);
  };

  const tabQR = form.shortCode
    ? (
      <div style={{ display:'flex', flexDirection:'column', gap:18 }}>
        <div style={{ display:'flex', gap:18, alignItems:'flex-start', flexWrap:'wrap' }}>
          {/* Preview */}
          <div style={{ padding:14, background:qrBg, borderRadius:12, border:'1px solid var(--border)', flexShrink:0 }}>
            <BrandedQRPreview url={shortUrl} fg={qrFg} bg={qrBg} logoUrl={qrLogoUrl} size={200}/>
          </div>

          {/* Controls */}
          <div style={{ flex:1, minWidth:200, display:'flex', flexDirection:'column', gap:14 }}>
            <ColorPicker label="Foreground Color" value={qrFg} onChange={setQrFg}/>
            <ColorPicker label="Background Color" value={qrBg} onChange={setQrBg}/>
            <div>
              <FL>Center Logo <span style={{ fontWeight:400, textTransform:'none', letterSpacing:0, color:'var(--text-dim)' }}>(URL, optional)</span></FL>
              <input className="input input-sm" value={qrLogoUrl} onChange={e=>setQrLogoUrl(e.target.value)} placeholder="https://…/logo.png"/>
            </div>
            <div>
              <FL>Export Size — {qrSize}×{qrSize}px</FL>
              <input type="range" min={256} max={2048} step={128} value={qrSize} onChange={e=>setQrSize(+e.target.value)}
                style={{ width:'100%', accentColor:'var(--accent)' }}/>
            </div>
          </div>
        </div>
        <button className="btn btn-primary" onClick={downloadQR} style={{ justifyContent:'center' }}>
          ↓ Download PNG ({qrSize}×{qrSize})
        </button>
      </div>
    )
    : <p style={{ color:'var(--text-dim)', fontSize:13 }}>Set a short code first (General tab).</p>;

  const TABS = [{id:'general',l:'General'},{id:'tracking',l:'Tracking'},{id:'embed',l:'Embed'},{id:'qr',l:'QR Code'}];

  return (
    <div className="modal-overlay">
      <div className="modal modal-wide">
        <div style={{ padding:'20px 24px 0', borderBottom:'1px solid var(--border)' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
            <div>
              <h2 style={{ fontSize:17, fontWeight:700 }}>{link?'Edit Link':'New Link'}</h2>
              {form.shortCode && <code style={{ fontSize:12, color:'var(--text-dim)', fontFamily:"'Space Grotesk',monospace" }}>https://{domain}/{form.shortCode}</code>}
            </div>
            <button onClick={onClose} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--text-dim)', fontSize:18, padding:4, lineHeight:1 }}>✕</button>
          </div>
          <div style={{ display:'flex', gap:2 }}>
            {TABS.map(t=><TB key={t.id} active={tab===t.id} onClick={()=>setTab(t.id)}>{t.l}</TB>)}
          </div>
        </div>
        <div style={{ padding:'20px 24px' }}>
          {tab==='general'  && tabGeneral}
          {tab==='tracking' && tabTracking}
          {tab==='embed'    && tabEmbed}
          {tab==='qr'       && tabQR}
        </div>
        <div style={{ padding:'14px 24px', borderTop:'1px solid var(--border)', display:'flex', justifyContent:'flex-end', gap:8 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancel</button>
          <button className="btn btn-primary" onClick={handleSave} disabled={!form.dest.trim()}>
            {link ? 'Save Changes' : 'Create Link'}
          </button>
        </div>
      </div>
    </div>
  );
}

/* ─────────────────────────────────────────────────
   QR MODAL — quick standalone QR code view
───────────────────────────────────────────────── */
function QRModal({ link, domain, onClose }) {
  const [qrFg,      setQrFg]      = useSt('#000000');
  const [qrBg,      setQrBg]      = useSt('#ffffff');
  const [qrLogoUrl, setQrLogoUrl] = useSt('');
  const [qrSize,    setQrSize]    = useSt(512);
  const [qrMode,    setQrMode]    = useSt('standard');
  const shortUrl = `https://${domain}/${link.shortCode}`;

  const download = async () => {
    await downloadQRCanvas(shortUrl, qrFg, qrBg, qrSize, qrMode==='branded' ? qrLogoUrl : '', `qr-${link.shortCode}.png`);
  };


  return (
    <div className="modal-overlay" onClick={e=>e.target===e.currentTarget&&onClose()}>
      <div className="modal" style={{ maxWidth:420 }}>
        <div style={{ padding:'18px 20px', borderBottom:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'space-between' }}>
          <div>
            <div style={{ fontSize:15, fontWeight:700 }}>QR Code</div>
            <code style={{ fontSize:12, color:'var(--text-dim)', fontFamily:"'Space Grotesk',monospace" }}>/{link.shortCode}</code>
          </div>
          <button onClick={onClose} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--text-dim)', fontSize:18, padding:4, lineHeight:1 }}>✕</button>
        </div>
        <div style={{ padding:'18px 20px', display:'flex', flexDirection:'column', gap:14 }}>

          {/* Mode toggle */}
          <div style={{ display:'flex', gap:3, background:'var(--surface-2)', borderRadius:8, padding:3 }}>
            {[['standard','Standard'],['branded','🎨 Branded']].map(([m,l]) =>
              <button key={m} onClick={()=>setQrMode(m)} style={{
                flex:1, padding:'6px 0', borderRadius:6, border:'none', cursor:'pointer',
                fontFamily:'inherit', fontSize:12, fontWeight:600, transition:'all 0.15s',
                background: qrMode===m ? 'var(--surface-hi)' : 'transparent',
                color:       qrMode===m ? 'var(--text)'       : 'var(--text-dim)',
                boxShadow:   qrMode===m ? '0 1px 4px oklch(0% 0 0 / 0.25)' : 'none',
              }}>{l}</button>
            )}
          </div>

          {/* QR preview */}
          <div style={{ display:'flex', justifyContent:'center', padding:14, background:qrBg, borderRadius:12, border:'1px solid var(--border)', transition:'background 0.2s' }}>
            <BrandedQRPreview url={shortUrl} fg={qrFg} bg={qrBg} logoUrl={qrMode==='branded' ? qrLogoUrl : ''} size={220}/>
          </div>

          {/* Branded: center logo */}
          {qrMode==='branded' &&
            <div style={{ animation:'fadeUp 0.18s ease both' }}>
              <FL>Center Image <span style={{ fontWeight:400, textTransform:'none', letterSpacing:0, color:'var(--text-dim)' }}>(URL)</span></FL>
              <input className="input input-sm" value={qrLogoUrl} onChange={e=>setQrLogoUrl(e.target.value)} placeholder="https://…/logo.png"/>
              {!qrLogoUrl && <p style={{ fontSize:11, color:'var(--text-muted)', marginTop:5 }}>Paste an image URL — it'll be embedded in the center of the QR code.</p>}
            </div>
          }

          {/* Colors */}
          <div style={{ display:'flex', gap:14 }}>
            <div style={{ flex:1 }}><ColorPicker label="Foreground" value={qrFg} onChange={setQrFg}/></div>
            <div style={{ flex:1 }}><ColorPicker label="Background" value={qrBg} onChange={setQrBg}/></div>
          </div>

          {/* Size */}
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <span style={{ fontSize:11, color:'var(--text-muted)', whiteSpace:'nowrap', fontVariantNumeric:'tabular-nums' }}>{qrSize}×{qrSize}px</span>
            <input type="range" min={256} max={2048} step={128} value={qrSize} onChange={e=>setQrSize(+e.target.value)}
              style={{ flex:1, accentColor:'var(--accent)' }} data-comment-anchor="bd21b32f39-input-392-15"/>
            <span style={{ fontSize:11, color:'var(--text-dim)', whiteSpace:'nowrap' }}>2048 max</span>
          </div>

          <button className="btn btn-primary" onClick={download} style={{ width:'100%', justifyContent:'center' }}>
            ↓ Download {qrSize}×{qrSize} PNG
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { LinkModal, QRModal });
