// ─── Shared UI: BottomNav, Header, RegisterModal, SmartImg ─────────────

const { useState, useEffect, useRef, useMemo } = React;

const API = 'https://helix-api.barush-axel.workers.dev';

const loadBusinesses = async (zone = 'la-paz') => {
  try {
    const data = await fetch(`${API}/businesses?zone=${zone}`).then(r => r.json());
    window.BUSINESSES = (data && data.length > 0) ? data.map(b => ({
      ...b,
      rewardGoal: b.reward_goal,
      img: b.img_url || (b.category === 'food' ? IMG?.cafe : b.category === 'adventure' ? IMG?.escape : b.category === 'grooming' ? IMG?.barber : IMG?.cafe) || '',
      accent: '#06B6D4',
    })) : [];
  } catch(_) {}
  if (!window.BUSINESSES || window.BUSINESSES.length === 0) window.BUSINESSES = [];
  return true;
};

Object.assign(window, { loadBusinesses });

// SmartImg — image with elegant fog fallback on error
const SmartImg = ({ src, alt, style, className, onLoadEnd }) => {
  const [errored, setErrored] = useState(false);
  return (
    <div
      className={className}
      style={{
        background: 'var(--fog)',
        position: 'relative',
        overflow: 'hidden',
        ...style,
      }}
    >
      {!errored && (
        <img
          src={src}
          alt={alt || ''}
          loading="lazy"
          onError={() => setErrored(true)}
          onLoad={onLoadEnd}
          style={{
            width: '100%',
            height: '100%',
            objectFit: 'cover',
            display: 'block',
          }}
        />
      )}
      {errored && (
        <div style={{
          position:'absolute', inset:0,
          background:
            'repeating-linear-gradient(135deg, var(--fog) 0 14px, #e7e2d3 14px 16px)',
          display:'flex', alignItems:'center', justifyContent:'center',
          color:'var(--muted)', fontFamily:'ui-monospace, monospace',
          fontSize:11, letterSpacing:'.08em', textTransform:'uppercase'
        }}>
          {alt || t('img_alt_fallback')}
        </div>
      )}
    </div>
  );
};

// Pill — small uppercase capsule
const Pill = ({ children, color, bg, style, border }) => (
  <span style={{
    display:'inline-flex', alignItems:'center', gap:6,
    padding:'5px 10px',
    borderRadius:999,
    fontSize:10.5, fontWeight:600,
    letterSpacing:'0.08em', textTransform:'uppercase',
    color: color || 'var(--ink)',
    background: bg || 'transparent',
    border: border || '1px solid rgba(15,23,42,0.10)',
    lineHeight:1,
    ...style,
  }}>{children}</span>
);

// HeaderBar (internal views)
const HeaderBar = ({ title, onBack, onProfile, right }) => (
  <div style={{
    position:'sticky', top:0, zIndex:20,
    height:56,
    background:'rgba(251,249,243,0.92)',
    backdropFilter:'blur(10px)',
    WebkitBackdropFilter:'blur(10px)',
    borderBottom:'1px solid rgba(15,23,42,0.08)',
    display:'grid', gridTemplateColumns:'56px 1fr 56px',
    alignItems:'center',
  }}>
    <button onClick={onBack} style={{
      background:'transparent', border:0, height:56, width:56,
      display:'flex', alignItems:'center', justifyContent:'center',
      color:'var(--ink)', cursor:'pointer'
    }}>
      <IconArrowLeft size={22}/>
    </button>
    <div style={{ textAlign:'center', fontWeight:700, fontSize:14, letterSpacing:'.04em', textTransform:'uppercase' }}>
      {title}
    </div>
    {right ? right : (
      <button onClick={onProfile} style={{
        background:'transparent', border:0, height:56, width:56,
        display:'flex', alignItems:'center', justifyContent:'center',
        color:'var(--ink)', cursor:'pointer'
      }}>
        <IconUser size={20}/>
      </button>
    )}
  </div>
);

// BottomNav
const BottomNav = ({ currentView, user, setCurrentView, setShowRegisterModal, setScannerDirect }) => {
  const t = useT();
  const items = [
    { id:'home',        label:t('nav_explore'),  Icon: IconHome },
    { id:'map',         label:t('nav_explore'),  Icon: IconCompass },
    { id:'passport',    label:t('nav_passport'), Icon: IconBookOpen, guarded:true },
    { id:'leaderboard', label:t('nav_ranking'),  Icon: IconTrophy },
  ];
  return (
    <nav style={{
      position:'fixed', bottom:0, left:'50%', transform:'translateX(-50%)',
      width:'100%', maxWidth:430,
      height:68, zIndex:50,
      background:'rgba(251,249,243,0.92)',
      backdropFilter:'blur(14px)',
      WebkitBackdropFilter:'blur(14px)',
      borderTop:'1px solid rgba(15,23,42,0.08)',
      display:'grid', gridTemplateColumns:'1fr 1fr 72px 1fr 1fr',
      alignItems:'center',
      paddingBottom:'env(safe-area-inset-bottom, 0px)',
    }}>
      {items.slice(0,2).map(it => {
        const active = currentView === it.id;
        return (
          <button
            key={it.id}
            onClick={() => {
              if (it.guarded && !user) { setShowRegisterModal('passport'); return; }
              setCurrentView(it.id);
            }}
            style={{
              background:'transparent', border:0, cursor:'pointer',
              display:'flex', flexDirection:'column', alignItems:'center',
              justifyContent:'center', gap:3, position:'relative',
              color: active ? 'var(--teal)' : 'var(--muted)',
              paddingTop: 8, height:'100%'
            }}
          >
            {active && (
              <span style={{
                position:'absolute', top:6, width:14, height:3,
                background:'var(--teal)', borderRadius:2
              }}/>
            )}
            <it.Icon size={20} strokeWidth={active ? 2.2 : 1.8}/>
            <span style={{
              fontSize:10, fontWeight: active ? 600 : 500,
              letterSpacing:'.04em', textTransform:'uppercase'
            }}>{it.label}</span>
          </button>
        );
      })}

      {/* Botón cámara central */}
      <div style={{ display:'flex', justifyContent:'center', alignItems:'center' }}>
        <button
          onClick={() => {
            if (!user) { setShowRegisterModal('scan'); return; }
            setScannerDirect(true);
            setCurrentView('scanner');
          }}
          style={{
            width:52, height:52,
            borderRadius:'50%',
            background:'var(--teal)',
            border:'3px solid var(--canvas)',
            boxShadow:'0 4px 16px rgba(13,148,136,0.45)',
            display:'flex', alignItems:'center', justifyContent:'center',
            cursor:'pointer', color:'white',
            marginBottom:8
          }}
        >
          <IconQrCode size={22} color="white" strokeWidth={1.8}/>
        </button>
      </div>

      {items.slice(2).map(it => {
        const active = currentView === it.id;
        return (
          <button
            key={it.id}
            onClick={() => {
              if (it.guarded && !user) { setShowRegisterModal('passport'); return; }
              setCurrentView(it.id);
            }}
            style={{
              background:'transparent', border:0, cursor:'pointer',
              display:'flex', flexDirection:'column', alignItems:'center',
              justifyContent:'center', gap:3, position:'relative',
              color: active ? 'var(--teal)' : 'var(--muted)',
              paddingTop: 8, height:'100%'
            }}
          >
            {active && (
              <span style={{
                position:'absolute', top:6, width:14, height:3,
                background:'var(--teal)', borderRadius:2
              }}/>
            )}
            <it.Icon size={20} strokeWidth={active ? 2.2 : 1.8}/>
            <span style={{
              fontSize:10, fontWeight: active ? 600 : 500,
              letterSpacing:'.04em', textTransform:'uppercase'
            }}>{it.label}</span>
          </button>
        );
      })}
    </nav>
  );
};

// RegisterModal
const RegisterModal = ({ open, onClose, onRegister, contextLabel }) => {
  const [name, setName] = useState('');
  const [phone, setPhone] = useState('');
  const [pin, setPin] = useState('');
  const [mode, setMode] = useState('register');
  const t = useT();
  const nameRef = useRef(null);
  const phoneRef = useRef(null);

  useEffect(() => {
    if (open) {
      try {
        const draft = JSON.parse(localStorage.getItem('helixDraft') || '{}');
        if (draft.name)  setName(draft.name);
        if (draft.phone) setPhone(draft.phone);
      } catch (_) {}
      requestAnimationFrame(() => { (nameRef.current || phoneRef.current)?.focus(); });
    } else {
      setName(''); setPhone(''); setPin(''); setMode('register');
    }
  }, [open]);

  if (!open) return null;

  const saveDraft = (n, p) => {
    try { localStorage.setItem('helixDraft', JSON.stringify({ name: n, phone: p })); } catch (_) {}
  };
  const handleNameChange  = (e) => { setName(e.target.value); saveDraft(e.target.value, phone); };
  const handlePhoneChange = (e) => { const v = e.target.value.replace(/[^\d+\s]/g,''); setPhone(v); saveDraft(name, v); };
  const handleSubmit = () => {
    if (!valid) return;
    try { localStorage.removeItem('helixDraft'); } catch (_) {}
    onRegister({ name: name.trim(), phone: phone.trim(), pin });
  };

  const valid = mode === 'login'
    ? phone.trim().length >= 6 && pin.length === 4
    : name.trim().length >= 2 && phone.trim().length >= 6 && pin.length === 4;

  return (
    <div
      onClick={onClose}
      onTouchStart={(e) => { window._swipeStartY = e.touches[0].clientY; }}
      onTouchMove={(e) => { if (e.touches[0].clientY - (window._swipeStartY||0) > 180) onClose(); }}
      style={{
        position:'fixed', inset:0, zIndex:100,
        background:'rgba(15,23,42,0.55)',
        backdropFilter:'blur(6px)',
        WebkitBackdropFilter:'blur(6px)',
        display:'flex', alignItems:'flex-end', justifyContent:'center',
        animation:'overlayIn .2s ease both',
      }}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          width:'100%', maxWidth:430,
          background:'var(--canvas)',
          borderRadius:'24px 24px 0 0',
          padding:'14px 24px 32px',
          animation:'slideUp .35s cubic-bezier(.2,.8,.2,1) both',
          paddingBottom:'calc(32px + env(safe-area-inset-bottom, 0px))'
        }}
      >
        <div
          onClick={onClose}
          onTouchStart={(e) => { e.stopPropagation(); window._swipeStartY = e.touches[0].clientY; }}
          onTouchMove={(e) => { e.stopPropagation(); if (e.touches[0].clientY - (window._swipeStartY||0) > 180) onClose(); }}
          style={{
          width:40, height:4, borderRadius:99,
          background:'var(--sealed)', margin:'4px auto 22px', cursor:'pointer'
        }}/>
        {contextLabel && (
          <div className="label-eyebrow" style={{marginBottom:8, color:'var(--teal)'}}>
            {contextLabel}
          </div>
        )}
        <h2 className="h-section" style={{ fontSize:26, margin:'0 0 6px', letterSpacing:'-0.03em' }}>
          {mode === 'login' ? t('reg_title_login') : name.trim().length > 0 ? t('reg_title_activate') : t('reg_title_register')}
        </h2>
        <p className="body-soft" style={{ margin:'0 0 22px', fontSize:14 }}>
          {mode === 'login' ? t('reg_subtitle_login') : t('reg_subtitle_register')}
        </p>

        <div style={{ display:'flex', gap:8, marginBottom:16 }}>
          {['register','login'].map(m => (
            <button key={m} onClick={() => setMode(m)} style={{
              flex:1, padding:'13px 10px', minHeight:46, borderRadius:10, border:0,
              background: mode === m ? 'var(--ink)' : 'var(--fog)',
              color: mode === m ? 'white' : 'var(--muted)',
              fontWeight:600, fontSize:13, cursor:'pointer'
            }}>
              {m === 'register' ? t('reg_tab_register') : t('reg_tab_login')}
            </button>
          ))}
        </div>

        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {mode === 'register' && (
            <input
              ref={nameRef}
              value={name}
              onChange={handleNameChange}
              placeholder={t('reg_placeholder_name')}
              autoComplete="name"
              style={{ background:'var(--fog)', border:0, borderRadius:12, padding:'16px', fontSize:16, color:'var(--ink)', outline:'none' }}
            />
          )}
          <input
            ref={mode === 'login' ? phoneRef : null}
            value={phone}
            onChange={handlePhoneChange}
            inputMode="tel"
            type="tel"
            placeholder={t('reg_placeholder_phone')}
            autoComplete="tel"
            style={{ background:'var(--fog)', border:0, borderRadius:12, padding:'16px', fontSize:16, color:'var(--ink)', outline:'none' }}
          />
          <input
            value={pin}
            onChange={(e) => setPin(e.target.value.replace(/\D/g,'').slice(0,4))}
            inputMode="numeric"
            type="password"
            placeholder={t('reg_placeholder_pin')}
            autoComplete="new-password"
            style={{ background:'var(--fog)', border:0, borderRadius:12, padding:'16px', fontSize:16, color:'var(--ink)', outline:'none' }}
          />
          {mode === 'login' && (
            <div style={{ fontSize:11, color:'var(--muted)', textAlign:'center' }}>
              {t('reg_forgot_pin')}{' '}
              <a
                href={`mailto:helixpassport@gmail.com?subject=${encodeURIComponent(t('reg_mailto_subject'))}&body=${encodeURIComponent(t('reg_mailto_body'))}`}
                style={{color:'var(--teal)', fontWeight:700}}
              >
                helixpassport@gmail.com
              </a>
            </div>
          )}
        </div>

        <button
          onClick={handleSubmit}
          disabled={!valid}
          style={{
            marginTop:18, width:'100%',
            background: valid ? 'var(--teal)' : 'rgba(13,148,136,0.4)',
            color:'white', border:0,
            borderRadius:14, padding:'16px',
            fontWeight:700, fontSize:15,
            letterSpacing:'.01em',
            cursor: valid ? 'pointer' : 'not-allowed',
            transition:'all .2s',
            display:'flex', alignItems:'center', justifyContent:'center', gap:8
          }}
        >
          {mode === 'register' ? t('reg_cta_activate') : t('reg_cta_login')}
          <IconChevronRight size={18}/>
        </button>

        <p style={{ textAlign:'center', marginTop:14, fontSize:12, color:'var(--muted)', lineHeight:1.6 }}>
          Al registrarte aceptas nuestros{' '}
          <a href="/legal.html" target="_blank" rel="noopener" style={{ color:'var(--teal)', textDecoration:'none', fontWeight:600 }}>Términos y Condiciones</a>
          {' '}y el{' '}
          <a href="/legal.html" target="_blank" rel="noopener" style={{ color:'var(--teal)', textDecoration:'none', fontWeight:600 }}>Aviso de Privacidad</a>.
        </p>
      </div>
    </div>
  );
};

// Reward celebration modal
const RewardModal = ({ open, business, onClose }) => {
  const t = useT();
  const plt = usePLT();
  if (!open || !business) return null;
  return (
    <div style={{
      position:'fixed', inset:0, zIndex:120,
      background:'var(--teal)',
      color:'white',
      display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      padding:'40px 24px', textAlign:'center',
      animation:'fadeIn .3s ease both'
    }}>
      <div style={{
        fontSize:72, marginBottom:20,
        animation:'stampIn .8s cubic-bezier(.2,.8,.2,1) both'
      }}>🎉</div>
      <div style={{
        fontSize:11, fontWeight:600, letterSpacing:'.18em',
        textTransform:'uppercase', opacity:.85, marginBottom:14
      }}>{t('reward_unlocked')}</div>
      <h2 style={{
        fontSize:34, fontWeight:800, letterSpacing:'-0.03em',
        margin:'0 0 14px', lineHeight:1.1
      }}>
        {t('reward_achieved')}<br/>{business.name}!
      </h2>
      <p style={{
        margin:'0 0 32px', maxWidth:300, fontSize:15,
        opacity:.95, lineHeight:1.5
      }}>{plt(business.reward)}</p>
      <button onClick={onClose} style={{
        background:'white', color:'var(--teal)',
        border:0, borderRadius:14,
        padding:'14px 32px', fontSize:15, fontWeight:700,
        cursor:'pointer', minWidth:200
      }}>{t('reward_great')}</button>
      <div style={{
        marginTop:32, fontSize:11, opacity:.6,
        letterSpacing:'.12em', textTransform:'uppercase'
      }}>Helix Passport</div>
    </div>
  );
};

// Section label
const SectionLabel = ({ children, style }) => (
  <div className="label-eyebrow" style={{
    padding:'0 24px', marginBottom:12, color:'var(--muted)', ...style
  }}>{children}</div>
);
const ZonePicker = ({ open, onSelect, activeZones = [] }) => {
  const t = useT();
  const safeZones = Array.isArray(activeZones) ? activeZones : [];
  if (!open) return null;
  return (
    <div onClick={() => localStorage.getItem('helixZone') ? onSelect(null) : null} style={{ position:'fixed', inset:0, zIndex:999, background:'rgba(15,23,42,0.7)', backdropFilter:'blur(8px)', display:'flex', alignItems:'flex-end', justifyContent:'center', animation:'overlayIn .2s ease both' }}>
      <div className="safe-pb" style={{ width:'100%', maxWidth:430, background:'var(--canvas)', borderRadius:'24px 24px 0 0', padding:'24px 24px 40px', animation:'slideUp .35s cubic-bezier(.2,.8,.2,1) both' }}
        onClick={e => e.stopPropagation()}>
        <div onClick={() => localStorage.getItem('helixZone') ? onSelect(null) : null} style={{ display:'flex', justifyContent:'center', marginBottom:24, cursor: localStorage.getItem('helixZone') ? 'pointer' : 'default' }}>
          <div style={{ width:40, height:4, borderRadius:99, background:'var(--sealed)' }}/>
        </div>
        <LangSelector/>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', margin:'16px 0 8px' }}>
          <div className="label-eyebrow" style={{ color:'var(--teal)', margin:0 }}>{t('zone_eyebrow')}</div>
          <button onClick={() => {
            if (!navigator.geolocation) return;
            navigator.geolocation.getCurrentPosition(pos => {
              const { latitude, longitude } = pos.coords;
              const zonesData = window.ZONES?.length ? window.ZONES : ZONES;
              const centerLat = zonesData.reduce((s, z) => s + z.lat, 0) / zonesData.length;
              const centerLng = zonesData.reduce((s, z) => s + z.lng, 0) / zonesData.length;
              const spread = zonesData.reduce((max, z) => Math.max(max, Math.hypot(z.lat - centerLat, z.lng - centerLng)), 0);
              const distFromCenter = Math.hypot(centerLat - latitude, centerLng - longitude);
              if (distFromCenter > spread * 3 + 2) { onSelect('nowhere'); return; }
              const closest = ZONES.reduce((best, z) => {
                const d = Math.hypot(z.lat - latitude, z.lng - longitude);
                return d < best.d ? { z, d } : best;
              }, { z: ZONES[0], d: Infinity });
              onSelect(closest.z.id);
            }, () => {});
          }} style={{ background:'transparent', border:0, padding:'10px 4px', minHeight:40, color:'var(--teal)', fontSize:11, fontWeight:700, cursor:'pointer', display:'flex', alignItems:'center', gap:4, letterSpacing:'.04em' }}>
            {t('zone_use_loc')}
          </button>
        </div>
        <h2 className="h-section" style={{ fontSize:24, margin:'0 0 6px' }}>{t('zone_title')}</h2>
        <p className="body-soft" style={{ fontSize:14, margin:'0 0 22px' }}>{t('zone_subtitle')}</p>
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {ZONES.map(z => {
            const hasSpots = safeZones.length === 0 || safeZones.some(s => (typeof s === 'string' ? s : s.id) === z.id);
            return (
              <button key={z.id} onClick={() => onSelect(z.id)} style={{ background: hasSpots ? 'var(--fog)' : 'transparent', border: hasSpots ? '1px solid rgba(15,23,42,0.06)' : '1px solid rgba(15,23,42,0.1)', borderRadius:14, padding:'16px 18px', display:'flex', alignItems:'center', justifyContent:'space-between', cursor:'pointer', fontWeight:600, fontSize:15, color: hasSpots ? 'var(--ink)' : 'var(--muted)', opacity: hasSpots ? 1 : 0.45 }}>
                <div>
                  {z.label}
                  {!hasSpots && <div style={{ fontSize:11, fontWeight:500, marginTop:2 }}>{t('zone_soon')}</div>}
                </div>
                {hasSpots ? <IconChevronRight size={18} color="var(--muted)"/> : <span style={{ fontSize:11 }}>🔜</span>}
              </button>
            );
          })}
        </div>
      </div>
    </div>
  );
};
const BusinessCard = ({ business: b, onClose, onScan, onMap }) => {
  const t = useT();
  const plt = usePLT();
  const lang = useLang();
  const socials = [
    b.instagram && { icon: '📸', label: 'Instagram', url: b.instagram.startsWith('http') ? b.instagram : `https://instagram.com/${b.instagram.replace('@','')}` },
    b.facebook && { icon: '👍', label: 'Facebook', url: b.facebook.startsWith('http') ? b.facebook : `https://facebook.com/${b.facebook}` },
    b.tiktok && { icon: '🎵', label: 'TikTok', url: b.tiktok.startsWith('http') ? b.tiktok : `https://tiktok.com/@${b.tiktok.replace('@','')}` },
    b.website && { icon: '🌐', label: t('biz_website_label'), url: b.website.startsWith('http') ? b.website : `https://${b.website}` },
  ].filter(Boolean);
  return (
    <div onClick={onClose} style={{ position:'fixed', inset:0, zIndex:500, background:'rgba(15,23,42,0.7)', backdropFilter:'blur(8px)', display:'flex', alignItems:'flex-end', justifyContent:'center', animation:'overlayIn .2s ease both' }}>
      <div onClick={e => e.stopPropagation()} className="scroll-panel safe-pb" style={{ width:'100%', maxWidth:430, background:'var(--canvas)', borderRadius:'24px 24px 0 0', maxHeight:'92vh', overflowY:'auto', animation:'slideUp .35s cubic-bezier(.2,.8,.2,1) both' }}>
        <div style={{ position:'relative', height:220 }}>
          <SmartImg src={b.img} alt={b.name} style={{ position:'absolute', inset:0, height:'100%', borderRadius:'24px 24px 0 0', overflow:'hidden' }}/>
          <div style={{ position:'absolute', inset:0, background:'linear-gradient(to top, rgba(10,20,30,0.85) 0%, transparent 60%)', borderRadius:'24px 24px 0 0' }}/>
          <button onClick={onClose} style={{ position:'absolute', top:16, right:16, background:'rgba(15,23,42,0.5)', backdropFilter:'blur(8px)', border:0, borderRadius:99, width:44, height:44, display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer', color:'white' }}>
            <IconX size={18}/>
          </button>
          <div style={{ position:'absolute', bottom:16, left:18, right:18 }}>
            <div className="label-eyebrow" style={{ color:'rgba(255,255,255,0.6)', marginBottom:4 }}>{b.tag}</div>
            <div style={{ fontWeight:800, fontSize:22, color:'white', letterSpacing:'-0.02em' }}>{b.name}</div>
            {b.address && <div style={{ fontSize:12, color:'rgba(255,255,255,0.6)', marginTop:4 }}>📍 {b.address}</div>}
          </div>
        </div>
        {b._birthdayMode ? (
          <div style={{ padding:'20px 20px 40px' }}>
            <div style={{ background:'rgba(233,30,140,0.06)', border:'1px solid rgba(233,30,140,0.2)', borderRadius:14, padding:'16px', marginBottom:14 }}>
              <div style={{ fontSize:11, fontWeight:700, color:'#E91E8C', textTransform:'uppercase', letterSpacing:'.06em', marginBottom:8 }}>🎁 {t('map_filter_birthday')}</div>
              <div style={{ fontSize:16, fontWeight:700, lineHeight:1.5, color:'var(--ink)' }}>{b.birthday_gift}</div>
            </div>
            {b.birthday_terms && (
              <div style={{ background:'var(--fog)', borderRadius:12, padding:'14px 16px', marginBottom:20 }}>
                <div style={{ fontSize:11, fontWeight:700, color:'var(--muted)', textTransform:'uppercase', letterSpacing:'.06em', marginBottom:8 }}>{t('map_bday_terms_label')}</div>
                <div style={{ fontSize:14, color:'var(--ink)', lineHeight:1.7 }}>{b.birthday_terms}</div>
              </div>
            )}
            <button onClick={onClose} style={{ width:'100%', background:'var(--fog)', border:'1px solid rgba(15,23,42,0.1)', borderRadius:12, padding:'15px', minHeight:50, fontSize:13, fontWeight:600, cursor:'pointer' }}>
              {t('scan_cancel')}
            </button>
          </div>
        ) : (
          <div style={{ padding:'20px 20px 40px' }}>
            {b.description && <p style={{ fontSize:14, color:'var(--ink)', lineHeight:1.6, margin:'0 0 20px', opacity:0.8 }}>{plt(b.description)}</p>}
            <div style={{ background:'rgba(13,148,136,0.08)', border:'1px solid rgba(13,148,136,0.15)', borderRadius:12, padding:'12px 14px', marginBottom:20, display:'flex', alignItems:'center', gap:10 }}>
              <IconGift size={16} color="var(--teal)"/>
              <div>
                <div style={{ fontSize:11, color:'var(--teal)', fontWeight:700, textTransform:'uppercase', letterSpacing:'.06em' }}>{t('biz_vip_eyebrow')}</div>
                <div style={{ fontSize:13, fontWeight:600, marginTop:2 }}>{plt(b.reward)} · {t('biz_vip_every')} {b.rewardGoal} {t('biz_vip_visits')}</div>
              </div>
            </div>
            {socials.length > 0 && (
              <div style={{ marginBottom:20 }}>
                <div className="label-eyebrow" style={{ padding:0, marginBottom:10 }}>{t('biz_social_title')}</div>
                <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
                  {socials.map(s => (
                    <a key={s.label} href={s.url} target="_blank" rel="noopener noreferrer" style={{ background:'var(--fog)', border:'1px solid rgba(15,23,42,0.08)', borderRadius:10, padding:'11px 14px', minHeight:44, fontSize:13, fontWeight:600, color:'var(--ink)', textDecoration:'none', display:'inline-flex', alignItems:'center', gap:6 }}>
                      {s.icon} {s.label}
                    </a>
                  ))}
                </div>
              </div>
            )}
            <button onClick={onMap} style={{ width:'100%', background:'var(--fog)', border:'1px solid rgba(15,23,42,0.1)', borderRadius:12, padding:'15px', minHeight:50, fontSize:13, fontWeight:600, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center', gap:6 }}>
              {t('biz_see_map')}
            </button>
          </div>
        )}
      </div>
    </div>
  );
};
const RewardsDrawer = ({ businessName, rewards, onClose, readOnly = false, userId, onRedeemed }) => {
  const t = useT();
  const plt = usePLT();
  if (!rewards?.length) return null;
  return (
    <div onClick={onClose} style={{
      position:'fixed', inset:0, zIndex:9999,
      background:'rgba(15,23,42,0.6)',
      backdropFilter:'blur(4px)',
      display:'flex', alignItems:'center', justifyContent:'center',
      padding:'40px 24px'
    }}>
      <div onClick={e => e.stopPropagation()} className="scroll-panel" style={{
        width:'100%', maxWidth:430,
        background:'var(--canvas)',
        borderRadius:'24px',
        padding:'24px 24px 32px',
        animation:'slideUp .35s cubic-bezier(.2,.8,.2,1) both',
        maxHeight:'80vh', overflowY:'auto',
        border:'2px solid var(--teal)',
        boxShadow:'0 8px 40px rgba(13,148,136,0.18)'
      }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:20 }}>
          <div>
            <div className="label-eyebrow" style={{ color:'var(--teal)' }}>{t('rewards_title')}</div>
            <div style={{ fontWeight:800, fontSize:18 }}>{businessName}</div>
          </div>
          <button onClick={onClose} style={{ background:'transparent', border:0, cursor:'pointer', color:'var(--muted)', padding:8, minWidth:44, minHeight:44, display:'flex', alignItems:'center', justifyContent:'center' }}>
            <IconX size={22}/>
          </button>
        </div>
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {rewards.map(r => readOnly ? (
            <div key={r.id} style={{ background:'var(--fog)', borderRadius:14, padding:'14px 16px', border:'1px solid rgba(13,148,136,0.2)', fontSize:12, color:'var(--teal)', fontWeight:600, display:'inline-flex', alignItems:'center', gap:6 }}>
              <IconGift size={13}/> {plt(r.reward)}
            </div>
          ) : (
            <RewardCoupon key={r.id} reward={r} userId={userId} onRedeemed={onRedeemed}/>
          ))}
        </div>
      </div>
    </div>
  );
};

const RewardCoupon = ({ reward, userId, onRedeemed }) => {
  const [qrToken, setQrToken] = useState(null);
  const [loading, setLoading] = useState(false);
  const [redeemed, setRedeemed] = useState(false);
  const [redeemedMsg, setRedeemedMsg] = useState('');
  const pollRef = useRef(null);
  const t = useT();
  const plt = usePLT();

  useEffect(() => {
    return () => { if (pollRef.current) clearInterval(pollRef.current); };
  }, []);

  const showQR = async () => {
    setLoading(true);
    try {
      const res = await fetch(`${API}/rewards/qr`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ rewardId: reward.id })
      });
      const data = await res.json();
      setQrToken(data.token);
      // Iniciar polling
      pollRef.current = setInterval(async () => {
        try {
          const r = await fetch(`${API}/rewards?userId=${userId}`);
          const list = await r.json();
          if (Array.isArray(list) && !list.find(x => x.id === reward.id)) {
            clearInterval(pollRef.current);
            setRedeemed(true);
            setRedeemedMsg(plt(reward.reward));
          }
        } catch(_) {}
      }, 3000);
    } catch(_) {}
    setLoading(false);
  };

  if (redeemed) return (
    <div style={{ background:'var(--teal)', borderRadius:14, padding:'20px 16px', textAlign:'center', color:'white' }}>
      <div style={{ fontSize:32, marginBottom:8 }}>🎉</div>
      <div style={{ fontWeight:800, fontSize:16, marginBottom:6 }}>{t('coupon_redeemed')}</div>
      <div style={{ fontSize:13, opacity:.9, marginBottom:16 }}>{t('coupon_enjoy')} {redeemedMsg}</div>
      <button onClick={() => onRedeemed && onRedeemed(reward.id)} style={{
        background:'white', color:'var(--teal)',
        border:0, borderRadius:10, padding:'10px 20px',
        fontSize:13, fontWeight:700, cursor:'pointer'
      }}>{t('reward_great')}</button>
    </div>
  );

  return (
    <div style={{
      background:'var(--fog)', borderRadius:14, padding:'14px 16px',
      border:'1px solid rgba(13,148,136,0.2)'
    }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom: qrToken ? 12 : 0 }}>
        <div style={{ fontSize:12, color:'var(--teal)', fontWeight:600, display:'inline-flex', alignItems:'center', gap:6 }}>
          <IconGift size={13}/> {plt(reward.reward)}
        </div>
        {!qrToken && (
          <button onClick={showQR} disabled={loading} style={{
            background:'var(--teal)', color:'white',
            border:0, borderRadius:10, padding:'11px 16px', minHeight:42,
            fontSize:13, fontWeight:700, cursor:'pointer',
            opacity: loading ? 0.6 : 1
          }}>
            {loading ? '...' : t('coupon_show_qr')}
          </button>
        )}
      </div>
      {qrToken && (
        <div style={{ textAlign:'center' }}>
          <div style={{ fontSize:11, color:'var(--muted)', marginBottom:8 }}>{t('coupon_show_local')}</div>
          <div style={{ display:'inline-block', background:'white', padding:10, borderRadius:10 }}>
            <img
              src={`https://api.qrserver.com/v1/create-qr-code/?size=160x160&data=${encodeURIComponent(qrToken)}`}
              width={160} height={160} alt="QR canje"
              style={{ display:'block', borderRadius:4 }}
            />
          </div>
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:6 }}>{t('coupon_waiting')}</div>
        </div>
      )}
    </div>
  );
};

Object.assign(window, {
  SmartImg, Pill, HeaderBar, BottomNav, RegisterModal, RewardModal, RewardCoupon, RewardsDrawer, SectionLabel, ZonePicker, BusinessCard
});