// Screens restantes (Bubblegum): Listas, Historial, Ajustes

const LIST_COLOR = { lime: '#D4FF3A', pink: '#FF3D8B', cyan: '#5EEAD4', orange: '#FDBA74', violet: '#A78BFA' };

// Renderiza un preview de un icono de categoría en un modo específico, sin
// depender del estado global. Útil para los swatches del selector en Ajustes.
function IconPreview({ catKey, mode, size = 20 }) {
  const c = CATEGORIES[catKey] || CATEGORIES.otros;
  if (!c) return null;
  const glyph = c.glyph || 'cat-box';
  if (mode === 'line') {
    return <Icon name={glyph} size={size} stroke={2.2} />;
  }
  if (mode === 'material') {
    return (
      <span className="material-symbols-outlined" aria-hidden="true"
        style={{ fontSize: size + 4, lineHeight: 1 }}>
        {(window.__MATERIAL_NAMES__ || {})[glyph] || materialNameFor(glyph)}
      </span>
    );
  }
  if (mode === 'openmoji') {
    const code = openmojiFor(glyph);
    return <img alt="" src={`https://cdn.jsdelivr.net/npm/openmoji@15.1.0/color/svg/${code}.svg`}
      width={size + 4} height={size + 4} style={{ verticalAlign: 'middle' }} />;
  }
  return <span aria-hidden="true" style={{ fontSize: size + 4, lineHeight: 1 }}>{c.emoji}</span>;
}

// Tablas duplicadas (mismas que en data.jsx) para el preview. Se mantienen
// pequeñas y solo cubren las categorías que el preview muestra.
function materialNameFor(glyph) {
  const m = {
    'cat-leaf': 'eco', 'cat-meat': 'kebab_dining', 'cat-milk': 'egg_alt', 'cat-bread': 'bakery_dining',
  };
  return m[glyph] || 'inventory_2';
}
function openmojiFor(glyph) {
  const m = {
    'cat-leaf': '1F96C', 'cat-meat': '1F969', 'cat-milk': '1F95B', 'cat-bread': '1F956',
  };
  return m[glyph] || '1F4E6';
}

// Metadata para el selector de temas (visual). Las paletas reales viven en
// themes.jsx — aquí solo necesitamos colores de muestra para los swatches.
const THEME_PICKER = [
  { id: 'bubblegum', name: 'Bubblegum', sub: 'Cian · Violeta',  accent: '#5EEAD4', accent2: '#A78BFA' },
  { id: 'kraft',     name: 'Kraft',     sub: 'Naranja · Marrón', accent: '#FB8500', accent2: '#C68A47' },
  { id: 'ocean',     name: 'Ocean',     sub: 'Cian profundo',    accent: '#06B6D4', accent2: '#0EA5E9' },
  { id: 'forest',    name: 'Forest',    sub: 'Verde · Lima',     accent: '#22C55E', accent2: '#84CC16' },
  { id: 'sunset',    name: 'Sunset',    sub: 'Rosa · Coral',     accent: '#F472B6', accent2: '#FB7185' },
];

function ListsScreen({ app, theme, openSheet }) {
  const c = theme.c;
  const t = app.t;
  const isDesktop = app.isDesktop;
  const innerMax = isDesktop ? 1080 : '100%';
  const sidePad = isDesktop ? 32 : 22;
  // Sin SmartInput flotante: solo dejamos espacio al BottomNav (~80px) + margen.
  const bottomPad = isDesktop ? 32 : 100;
  const [pendingDelete, setPendingDelete] = React.useState(null);
  const [renaming, setRenaming]           = React.useState(null); // { id, name }
  const [renameDraft, setRenameDraft]     = React.useState('');
  React.useEffect(() => {
    if (renaming) setRenameDraft(renaming.name || '');
  }, [renaming]);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', background: c.bg }}>
      <div style={{ maxWidth: innerMax, margin: '0 auto', width: '100%', boxSizing: 'border-box' }}>
        <ScreenHeader theme={theme} subtitle={app.lang === 'es' ? 'TUS LISTAS' : 'YOUR LISTS'} title={t.tabs.lists} />
      </div>
      <div style={{
        padding: `4px ${sidePad}px 16px`, display: 'flex', gap: 8,
        maxWidth: innerMax, margin: '0 auto', width: '100%', boxSizing: 'border-box',
      }}>
        <Btn theme={theme} variant="solid" size="md" icon="plus" full onClick={() => openSheet('newList')}>{t.newList}</Btn>
        <Btn theme={theme} variant="ghost" size="md" icon="qr" onClick={() => openSheet('join')}>{t.join}</Btn>
      </div>
      <div className="sl-scroll" style={{
        flex: 1, overflow: 'auto', padding: `0 ${sidePad}px ${bottomPad}px`,
        display: 'flex', flexDirection: 'column',
      }}>
        {app.lists.length === 0 ? (
          <EmptyState theme={theme} big="📋"
            title={app.lang === 'es' ? 'Sin listas' : 'No lists'}
            sub={app.lang === 'es' ? 'Crea una nueva o únete con un código.' : 'Create one or join with a code.'} />
        ) : (
        <div style={{
          maxWidth: innerMax, margin: '0 auto', width: '100%',
          display: isDesktop ? 'grid' : 'flex',
          gridTemplateColumns: isDesktop ? 'repeat(auto-fill, minmax(320px, 1fr))' : undefined,
          flexDirection: isDesktop ? undefined : 'column',
          gap: 12,
        }}>
        {app.lists.map(l => {
          const items = (app.products[l.id] || []);
          const pendingN = items.filter(i => !i.is_purchased).length;
          const isCurrent = l.id === app.currentListId;
          const color = LIST_COLOR[l.color];
          const canDelete = app.lists.length > 1;
          const onDelete = (e) => {
            e.stopPropagation();
            if (!canDelete) return;
            setPendingDelete({ id: l.id, name: l.name[app.lang] });
          };
          return (
            <div key={l.id} role="button" tabIndex={0}
              onClick={() => { app.setCurrentListId(l.id); app.setTab('list'); }}
              onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { app.setCurrentListId(l.id); app.setTab('list'); } }}
              style={{
                textAlign: 'left', padding: '18px 18px',
                background: c.bgCard,
                border: isCurrent ? `2px solid ${c.accent}` : `1px solid ${c.border}`,
                borderRadius: theme.radius.xl,
                boxShadow: c.shadowSoft,
                cursor: 'pointer', position: 'relative',
                display: 'flex', alignItems: 'center', gap: 14,
              }}>
              <div style={{
                width: 56, height: 56, borderRadius: theme.radius.lg,
                background: color, display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 26, fontWeight: 800, color: c.ink,
                fontFamily: theme.fontDisplay,
                flexShrink: 0,
              }}>{l.name[app.lang][0]}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontSize: 19, fontWeight: 800, fontFamily: theme.fontDisplay, color: c.ink }}>{l.name[app.lang]}</span>
                  {isCurrent && <ChipBadge theme={theme} color={c.accent}>{app.lang === 'es' ? 'ACTIVA' : 'ACTIVE'}</ChipBadge>}
                </div>
                <div style={{ display: 'flex', gap: 12, marginTop: 6, fontSize: 12, fontFamily: theme.fontMono, color: c.inkSub }}>
                  <span><strong style={{ color: c.ink, fontWeight: 700 }}>{pendingN}</strong> {t.pending}</span>
                  <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                    <Icon name="people" size={12} stroke={2.4} /> {l.members}
                  </span>
                  <span>{formatDate(l.createdAt, app.lang)}</span>
                </div>
              </div>
              <button
                className="sl-press-soft"
                onClick={(e) => { e.stopPropagation(); setRenaming({ id: l.id, name: l.name[app.lang] }); }}
                onPointerDown={() => { if (navigator.vibrate) navigator.vibrate(8); }}
                aria-label={app.lang === 'es' ? 'Renombrar' : 'Rename'}
                title={app.lang === 'es' ? 'Renombrar' : 'Rename'}
                style={{
                  width: 36, height: 36, borderRadius: theme.radius.md,
                  background: 'transparent', border: `1px solid ${c.border}`,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  color: c.inkSub, cursor: 'pointer', flexShrink: 0,
                  WebkitTapHighlightColor: 'transparent',
                }}>
                <Icon name="edit" size={16} stroke={2.2} />
              </button>
              <button
                className="sl-press"
                onClick={onDelete}
                onPointerDown={canDelete ? () => { if (navigator.vibrate) navigator.vibrate(8); } : undefined}
                disabled={!canDelete}
                aria-label={app.lang === 'es' ? 'Eliminar de este dispositivo' : 'Delete from this device'}
                title={app.lang === 'es' ? 'Eliminar de este dispositivo' : 'Delete from this device'}
                style={{
                  width: 36, height: 36, borderRadius: theme.radius.md,
                  background: 'transparent', border: `1px solid ${c.border}`,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  color: canDelete ? c.inkSub : c.inkMuted,
                  cursor: canDelete ? 'pointer' : 'not-allowed',
                  opacity: canDelete ? 1 : 0.4, flexShrink: 0,
                  transition: 'transform .12s ease, background .12s ease, color .12s ease',
                  WebkitTapHighlightColor: 'transparent',
                }}>
                <Icon name="trash" size={16} stroke={2.2} />
              </button>
            </div>
          );
        })}
        </div>
        )}
      </div>
      <Sheet theme={theme} open={!!pendingDelete} mode={isDesktop ? 'dialog' : 'sheet'}
        onClose={() => setPendingDelete(null)}
        title={app.lang === 'es' ? 'Eliminar lista' : 'Delete list'}>
        {pendingDelete && (
          <>
            <div style={{
              fontSize: 15, lineHeight: 1.5, color: c.inkSub,
              fontFamily: theme.fontBody, marginBottom: 18,
            }}>
              {app.lang === 'es' ? (
                <>¿Eliminar <strong style={{ color: c.ink }}>"{pendingDelete.name}"</strong> solo de este dispositivo? Seguirá existiendo en la nube y podrás volver a unirte con su código.</>
              ) : (
                <>Delete <strong style={{ color: c.ink }}>"{pendingDelete.name}"</strong> from this device only? It will still exist in the cloud and you can rejoin with its code.</>
              )}
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <Btn theme={theme} variant="ghost" size="md" full onClick={() => setPendingDelete(null)}>
                {app.lang === 'es' ? 'Cancelar' : 'Cancel'}
              </Btn>
              <Btn theme={theme} variant="solid" size="md" full icon="trash"
                onClick={() => { app.deleteList(pendingDelete.id); setPendingDelete(null); }}>
                {app.lang === 'es' ? 'Eliminar' : 'Delete'}
              </Btn>
            </div>
          </>
        )}
      </Sheet>
      <Sheet theme={theme} open={!!renaming} mode={isDesktop ? 'dialog' : 'sheet'}
        onClose={() => setRenaming(null)}
        title={app.lang === 'es' ? 'Renombrar lista' : 'Rename list'}>
        {renaming && (
          <>
            <input autoFocus value={renameDraft}
              onChange={(e) => setRenameDraft(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && renameDraft.trim()) {
                  app.renameList(renaming.id, renameDraft.trim());
                  setRenaming(null);
                }
              }}
              placeholder={t.listName}
              style={{
                width: '100%', padding: '14px 16px', fontSize: 16, fontFamily: theme.fontDisplay,
                border: `1.5px solid ${c.border}`,
                borderRadius: theme.radius.lg, outline: 'none',
                background: c.bg, color: c.ink, marginBottom: 12, boxSizing: 'border-box',
              }} />
            <div style={{ display: 'flex', gap: 8 }}>
              <Btn theme={theme} variant="ghost" size="md" full onClick={() => setRenaming(null)}>
                {app.lang === 'es' ? 'Cancelar' : 'Cancel'}
              </Btn>
              <Btn theme={theme} variant="solid" size="md" full icon="check"
                disabled={!renameDraft.trim() || renameDraft.trim() === renaming.name}
                onClick={() => { app.renameList(renaming.id, renameDraft.trim()); setRenaming(null); }}>
                {app.lang === 'es' ? 'Guardar' : 'Save'}
              </Btn>
            </div>
          </>
        )}
      </Sheet>
    </div>
  );
}

// ─── HISTORIAL — autocompacto, agrupado por día y por acción ────
function HistoryScreen({ app, theme }) {
  const c = theme.c;
  const t = app.t;
  if (!app.list) return <NoListEmptyState app={app} theme={theme} />;
  const isDesktop = app.isDesktop;
  const innerMax = isDesktop ? 720 : '100%';
  const sidePad = isDesktop ? 32 : 22;
  // History no tiene SmartInput flotante: bottomPad mínimo para BottomNav.
  const bottomPad = isDesktop ? 32 : 100;
  const allLogs = app.history[app.currentListId] || [];
  const [expanded, setExpanded] = React.useState(() => new Set());
  const [actionFilter, setActionFilter] = React.useState('all'); // all | added | purchased | edited | deleted | archived
  const [whoFilter, setWhoFilter]       = React.useState('all'); // all | <name>
  const [search, setSearch]             = React.useState('');
  const toggleExpanded = (id) => {
    setExpanded(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  // Personas que aparecen en el historial (para el filtro who).
  const whoOptions = React.useMemo(() => {
    const s = new Set();
    for (const l of allLogs) if (l.who) s.add(l.who);
    return Array.from(s).sort();
  }, [allLogs]);

  // Logs filtrados por acción / quién / texto antes de agrupar por día.
  const logs = React.useMemo(() => {
    const q = search.trim().toLowerCase();
    return allLogs.filter(l => {
      if (actionFilter !== 'all' && l.action !== actionFilter) return false;
      if (whoFilter !== 'all' && l.who !== whoFilter) return false;
      if (q && !(l.item_name || '').toLowerCase().includes(q)) return false;
      return true;
    });
  }, [allLogs, actionFilter, whoFilter, search]);

  const grouped = React.useMemo(() => {
    const byDay = {};
    logs.forEach(log => {
      const bucket = dayBucket(log.at, app.lang);
      if (!byDay[bucket]) byDay[bucket] = [];
      byDay[bucket].push(log);
    });
    const compact = {};
    Object.keys(byDay).forEach(day => {
      const arr = [];
      byDay[day].forEach(log => {
        const last = arr[arr.length - 1];
        if (last && last.action === log.action && last.who === log.who && (last.at - log.at) < 10*60*1000) {
          last.items.push(log.item_name);
          last.at = Math.max(last.at, log.at);
        } else {
          arr.push({ ...log, items: [log.item_name] });
        }
      });
      compact[day] = arr;
    });
    return compact;
  }, [logs, app.lang]);

  const actionMeta = {
    added:       { color: c.accent,  ink: c.accentInk, icon: 'plus' },
    purchased:   { color: c.success, ink: '#fff',      icon: 'check' },
    unpurchased: { color: c.border,  ink: c.ink,       icon: 'undo-circle' },
    edited:      { color: c.accent2, ink: '#fff',      icon: 'edit' },
    deleted:     { color: c.danger,  ink: '#fff',      icon: 'trash' },
    archived:    { color: c.inkSub,  ink: c.bg,        icon: 'sparkle' },
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', background: c.bg }}>
      <div style={{ maxWidth: innerMax, margin: '0 auto', width: '100%', boxSizing: 'border-box' }}>
        <ScreenHeader theme={theme} subtitle={app.list.name[app.lang].toUpperCase()} title={t.tabs.history} />
      </div>
      {/* Filtros: chips de acción + búsqueda + chip de quién (cuando hay
          más de una persona en el historial). */}
      {allLogs.length > 0 && (
        <div style={{
          padding: `0 ${sidePad}px 12px`, maxWidth: innerMax, margin: '0 auto',
          width: '100%', boxSizing: 'border-box',
          display: 'flex', flexDirection: 'column', gap: 8,
        }}>
          {/* Búsqueda por nombre de item */}
          <div style={{
            display: 'flex', alignItems: 'center', gap: 8,
            padding: '8px 14px', background: c.bgCard,
            border: `1px solid ${c.border}`, borderRadius: 999,
          }}>
            <Icon name="qr" size={14} stroke={2.2} style={{ color: c.inkMuted, opacity: 0 }} />
            <input
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              placeholder={app.lang === 'es' ? 'Buscar producto…' : 'Search item…'}
              style={{
                flex: 1, border: 'none', outline: 'none', background: 'transparent',
                fontSize: 14, fontFamily: theme.fontBody, color: c.ink, minWidth: 0,
              }} />
            {search && (
              <button onClick={() => setSearch('')}
                aria-label={app.lang === 'es' ? 'Limpiar' : 'Clear'}
                style={{
                  background: 'transparent', border: 'none', cursor: 'pointer',
                  color: c.inkSub, padding: 4,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}>
                <Icon name="x" size={14} stroke={2.4} />
              </button>
            )}
          </div>
          {/* Chips de acción */}
          <div className="sl-scroll" style={{
            display: 'flex', gap: 6, overflow: 'auto',
            paddingBottom: 2,
          }}>
            {[
              { id: 'all',       label: app.lang === 'es' ? 'Todo' : 'All' },
              { id: 'added',     label: t.actions.added },
              { id: 'purchased', label: t.actions.purchased },
              { id: 'edited',    label: t.actions.edited },
              { id: 'deleted',   label: t.actions.deleted },
              { id: 'archived',  label: t.actions.archived },
            ].map(opt => {
              const active = opt.id === actionFilter;
              return (
                <button key={opt.id} onClick={() => setActionFilter(opt.id)}
                  style={{
                    padding: '6px 12px', borderRadius: 999,
                    background: active ? c.accent : 'transparent',
                    color: active ? c.accentInk : c.inkSub,
                    border: `1px solid ${active ? c.accent : c.border}`,
                    fontSize: 12, fontWeight: 700, fontFamily: theme.fontDisplay,
                    cursor: 'pointer', whiteSpace: 'nowrap', flexShrink: 0,
                    textTransform: 'capitalize',
                  }}>
                  {opt.label}
                </button>
              );
            })}
          </div>
          {/* Chips de quién (solo si hay >1 persona) */}
          {whoOptions.length > 1 && (
            <div className="sl-scroll" style={{
              display: 'flex', gap: 6, overflow: 'auto',
              paddingBottom: 2,
            }}>
              <button onClick={() => setWhoFilter('all')}
                style={{
                  padding: '6px 12px', borderRadius: 999,
                  background: whoFilter === 'all' ? c.accent2 : 'transparent',
                  color: whoFilter === 'all' ? '#fff' : c.inkSub,
                  border: `1px solid ${whoFilter === 'all' ? c.accent2 : c.border}`,
                  fontSize: 12, fontWeight: 700, fontFamily: theme.fontDisplay,
                  cursor: 'pointer', whiteSpace: 'nowrap', flexShrink: 0,
                }}>
                {app.lang === 'es' ? 'Cualquiera' : 'Anyone'}
              </button>
              {whoOptions.map(name => {
                const active = whoFilter === name;
                return (
                  <button key={name} onClick={() => setWhoFilter(name)}
                    style={{
                      padding: '6px 12px', borderRadius: 999,
                      background: active ? c.accent2 : 'transparent',
                      color: active ? '#fff' : c.inkSub,
                      border: `1px solid ${active ? c.accent2 : c.border}`,
                      fontSize: 12, fontWeight: 700, fontFamily: theme.fontDisplay,
                      cursor: 'pointer', whiteSpace: 'nowrap', flexShrink: 0,
                    }}>
                    {name}
                  </button>
                );
              })}
            </div>
          )}
        </div>
      )}
      <div className="sl-scroll" style={{ flex: 1, overflow: 'auto', padding: `8px ${sidePad}px ${bottomPad}px` }}>
        <div style={{ maxWidth: innerMax, margin: '0 auto', width: '100%' }}>
        {logs.length === 0 ? (
          allLogs.length === 0
            ? <EmptyState theme={theme} big="📜" title={t.emptyHistory} sub={t.emptyHistorySub} />
            : <EmptyState theme={theme} big="🔍"
                title={app.lang === 'es' ? 'Sin resultados' : 'No matches'}
                sub={app.lang === 'es' ? 'Cambia los filtros o limpia la búsqueda.' : 'Change filters or clear the search.'} />
        ) : Object.keys(grouped).map(day => (
          <div key={day} style={{ marginBottom: 18 }}>
            <div style={{
              fontSize: 11, fontWeight: 700, color: c.inkMuted,
              textTransform: 'uppercase', letterSpacing: 1.5,
              fontFamily: theme.fontMono,
              padding: '6px 4px 10px',
              position: 'sticky', top: 0, background: c.bg, zIndex: 2,
            }}>{day}</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
              {grouped[day].map(log => {
                const meta = actionMeta[log.action] || actionMeta.edited;
                const verb = log.items.length > 1 ? (t.grouped[log.action] || t.actions[log.action]) : t.actions[log.action];
                const multi = log.items.length > 1;
                const isOpen = expanded.has(log.id);
                return (
                  <div key={log.id} style={{
                    background: c.bgCard,
                    border: `1px solid ${c.border}`,
                    borderRadius: theme.radius.md,
                    fontFamily: theme.fontBody,
                    overflow: 'hidden',
                  }}>
                    <div role={multi ? 'button' : undefined}
                      tabIndex={multi ? 0 : undefined}
                      onClick={multi ? () => toggleExpanded(log.id) : undefined}
                      onKeyDown={multi ? (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleExpanded(log.id); } } : undefined}
                      style={{
                        display: 'flex', alignItems: 'center', gap: 12,
                        padding: '10px 12px',
                        cursor: multi ? 'pointer' : 'default',
                      }}>
                      <div style={{
                        width: 32, height: 32, borderRadius: '50%',
                        background: meta.color, color: meta.ink,
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        flexShrink: 0,
                      }}>
                        <Icon name={meta.icon} size={14} stroke={2.6} />
                      </div>
                      <div style={{ flex: 1, minWidth: 0, fontSize: 13, color: c.ink, lineHeight: 1.3 }}>
                        <strong style={{ fontWeight: 700, fontFamily: theme.fontDisplay }}>
                          {log.who || (app.lang === 'es' ? 'Anónimo' : 'Anonymous')}
                        </strong>
                        <span style={{ color: c.inkSub }}> {verb} </span>
                        {multi ? (
                          <strong style={{ fontWeight: 700 }}>{log.items.length} {app.lang === 'es' ? 'productos' : 'items'}</strong>
                        ) : (
                          <strong style={{ fontWeight: 700 }}>{log.items[0]}</strong>
                        )}
                        {multi && !isOpen && (
                          <div style={{
                            fontSize: 11, color: c.inkMuted, marginTop: 2,
                            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                            fontFamily: theme.fontMono,
                          }}>
                            {log.items.slice(0, 3).join(' · ')}{log.items.length > 3 ? ` +${log.items.length - 3}` : ''}
                          </div>
                        )}
                      </div>
                      <span style={{
                        fontSize: 11, color: c.inkMuted, fontFamily: theme.fontMono,
                        flexShrink: 0,
                      }}>{relativeTime(log.at, app.lang)}</span>
                      {multi && (
                        <Icon name={isOpen ? 'chevron-up' : 'chevron-down'} size={16} stroke={2.4}
                          style={{ color: c.inkMuted, flexShrink: 0, marginLeft: 2 }} />
                      )}
                    </div>
                    {multi && isOpen && (
                      <div style={{
                        borderTop: `1px solid ${c.border}`,
                        padding: '8px 12px 12px 56px',
                        display: 'flex', flexDirection: 'column', gap: 4,
                        background: c.bg,
                      }}>
                        {log.items.map((it, i) => (
                          <div key={i} style={{
                            fontSize: 12, color: c.ink,
                            fontFamily: theme.fontMono,
                            display: 'flex', alignItems: 'center', gap: 8,
                          }}>
                            <span style={{
                              width: 4, height: 4, borderRadius: '50%',
                              background: meta.color, flexShrink: 0,
                            }} />
                            {it}
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
        ))}
        </div>
      </div>
    </div>
  );
}

// ─── AJUSTES ───────────────────────────────────────────────────
function SettingsScreen({ app, theme, openSheet }) {
  const c = theme.c;
  const t = app.t;
  const isDesktop = app.isDesktop;
  const innerMax = isDesktop ? 720 : '100%';
  const sidePad = isDesktop ? 32 : 22;
  // Settings no tiene SmartInput flotante: bottomPad mínimo para BottomNav.
  const bottomPad = isDesktop ? 32 : 100;
  const [linkCopied, setLinkCopied] = React.useState(false);
  const [qrZoomed, setQrZoomed]     = React.useState(false);
  const [deleteOpen, setDeleteOpen]       = React.useState(false);
  const [deleteInput, setDeleteInput]     = React.useState('');
  const [deleteBusy, setDeleteBusy]       = React.useState(false);
  const [deleteError, setDeleteError]     = React.useState('');
  // Easter egg: 10 taps en JarsRushCode despliega un mensaje secreto.
  const [authorTaps, setAuthorTaps]   = React.useState(0);
  const [secretOpen, setSecretOpen]   = React.useState(false);
  const tapTimeoutRef = React.useRef(null);
  const onAuthorTap = () => {
    setAuthorTaps(prev => {
      const next = prev + 1;
      if (next >= 10) {
        setSecretOpen(true);
        return 0;
      }
      // Reset si pasan más de 1.5s sin click → tienen que ser seguidos.
      if (tapTimeoutRef.current) clearTimeout(tapTimeoutRef.current);
      tapTimeoutRef.current = setTimeout(() => setAuthorTaps(0), 1500);
      return next;
    });
  };

  // Descarga el QR ampliado como PNG. Serializa el SVG visible, lo dibuja en
  // un canvas 1024x1024 con fondo blanco (alto contraste para escáneres) y
  // lanza un download.
  function downloadQR(filenameBase) {
    const svg = document.querySelector('.sl-qr-zoom svg');
    if (!svg) return;
    const xml = new XMLSerializer().serializeToString(svg);
    const b64 = btoa(unescape(encodeURIComponent(xml)));
    const img = new Image();
    img.onload = () => {
      const size = 1024;
      const canvas = document.createElement('canvas');
      canvas.width = size; canvas.height = size;
      const ctx = canvas.getContext('2d');
      ctx.fillStyle = '#fff';
      ctx.fillRect(0, 0, size, size);
      ctx.drawImage(img, 0, 0, size, size);
      canvas.toBlob((blob) => {
        if (!blob) return;
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        const safe = (filenameBase || 'lista').replace(/[^\w\-]+/g, '_').toLowerCase();
        a.download = `komprapp-${safe}.png`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        setTimeout(() => URL.revokeObjectURL(url), 1000);
      }, 'image/png');
    };
    img.src = `data:image/svg+xml;base64,${b64}`;
  }

  // Copia al portapapeles con fallback execCommand para WebViews donde
  // navigator.clipboard no está disponible (Android viejo, file://, etc).
  async function copyText(text) {
    try {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(text);
        return true;
      }
    } catch (_) { /* cae al fallback */ }
    try {
      const ta = document.createElement('textarea');
      ta.value = text;
      ta.style.position = 'fixed'; ta.style.opacity = '0';
      ta.setAttribute('readonly', '');
      document.body.appendChild(ta);
      ta.select(); ta.setSelectionRange(0, text.length);
      const ok = document.execCommand('copy');
      document.body.removeChild(ta);
      return ok;
    } catch (_) { return false; }
  }

  function Section({ title, children }) {
    return (
      <div style={{ marginBottom: 22 }}>
        <div style={{
          fontSize: 11, fontWeight: 700, color: c.inkMuted,
          textTransform: 'uppercase', letterSpacing: 1.5,
          fontFamily: theme.fontMono, padding: '0 6px 8px',
        }}>{title}</div>
        <div style={{
          background: c.bgCard,
          border: `1px solid ${c.border}`,
          borderRadius: theme.radius.lg,
          overflow: 'hidden',
        }}>
          {children}
        </div>
      </div>
    );
  }

  function Row({ children, onClick, last, danger }) {
    return (
      <div onClick={onClick} style={{
        padding: '14px 16px',
        borderBottom: last ? 'none' : `1px solid ${c.border}`,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12,
        cursor: onClick ? 'pointer' : 'default',
        color: danger ? c.danger : c.ink,
        fontFamily: theme.fontBody,
      }}>
        {children}
      </div>
    );
  }

  function Toggle({ on, onClick }) {
    return (
      <button onClick={onClick} style={{
        width: 48, height: 28, borderRadius: 999,
        background: on ? c.accent : c.border, border: 'none', cursor: 'pointer',
        padding: 2, position: 'relative', transition: 'background .2s',
      }}>
        <span style={{
          display: 'block', width: 22, height: 22, borderRadius: '50%',
          background: '#fff', transform: `translateX(${on ? 22 : 2}px)`,
          transition: 'transform .22s cubic-bezier(.2,1.3,.4,1)',
          boxShadow: '0 1px 3px rgba(0,0,0,0.25)',
        }} />
      </button>
    );
  }

  function Radio({ value, options, onChange }) {
    return (
      <div style={{ display: 'flex', gap: 6, padding: 4, background: c.bg, borderRadius: 999 }}>
        {options.map(o => (
          <button key={o.value} onClick={() => onChange(o.value)} style={{
            flex: 1, padding: '8px 10px', fontSize: 12, fontWeight: 700,
            fontFamily: theme.fontDisplay,
            background: value === o.value ? c.accent : 'transparent',
            color: value === o.value ? c.accentInk : c.inkSub,
            border: 'none', borderRadius: 999, cursor: 'pointer',
            transition: 'background .15s',
          }}>{o.label}</button>
        ))}
      </div>
    );
  }

  // URL canónica con hash routing. Siempre apuntamos al dominio público para
  // que el mismo link funcione en web, iOS nativo y Android nativo (en
  // Capacitor `window.location.origin` es `capacitor://localhost`).
  const link = app.list ? `${SHARE_ORIGIN}/#/s/${app.list.token}` : '';

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', background: c.bg }}>
      <div style={{ maxWidth: innerMax, margin: '0 auto', width: '100%', boxSizing: 'border-box' }}>
        <ScreenHeader theme={theme} subtitle={app.lang === 'es' ? 'CONFIGURACIÓN' : 'SETTINGS'} title={t.tabs.settings} />
      </div>
      <div className="sl-scroll" style={{ flex: 1, overflow: 'auto', padding: `8px ${sidePad}px ${bottomPad}px` }}>
        <div style={{ maxWidth: innerMax, margin: '0 auto', width: '100%' }}>
        <Section title={t.account}>
          {app.user ? (
            <>
              <Row>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12, flex: 1, minWidth: 0 }}>
                  {app.user.user_metadata?.avatar_url ? (
                    <img src={app.user.user_metadata.avatar_url} alt="" style={{
                      width: 44, height: 44, borderRadius: '50%', objectFit: 'cover', flexShrink: 0,
                    }} referrerPolicy="no-referrer" />
                  ) : (
                    <div style={{
                      width: 44, height: 44, borderRadius: '50%',
                      background: 'linear-gradient(135deg, #5EEAD4, #A78BFA)',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      fontWeight: 800, color: '#0F2C28', fontFamily: theme.fontDisplay, fontSize: 18,
                      flexShrink: 0,
                    }}>{(app.user.user_metadata?.full_name || app.user.email || '?')[0].toUpperCase()}</div>
                  )}
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{
                      fontSize: 15, fontWeight: 700, fontFamily: theme.fontDisplay,
                      overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                    }}>
                      {app.user.user_metadata?.full_name || app.user.email?.split('@')[0] || (app.lang === 'es' ? 'Tú' : 'You')}
                    </div>
                    <div style={{
                      fontSize: 12, color: c.inkSub, fontFamily: theme.fontMono,
                      overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                    }}>{app.user.email}</div>
                  </div>
                </div>
                <ChipBadge theme={theme} color={c.success} style={{ color: '#fff' }}>{app.lang === 'es' ? 'CONECTADO' : 'CONNECTED'}</ChipBadge>
              </Row>
              <Row onClick={() => app.signOut()}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, color: c.danger }}>
                  <Icon name="logout" size={18} stroke={2.4} />
                  <span style={{ fontSize: 14, fontWeight: 700, fontFamily: theme.fontDisplay }}>{t.signOut}</span>
                </div>
                <Icon name="chevron-right" size={18} stroke={2.2} style={{ color: c.inkMuted }} />
              </Row>
              <Row last onClick={() => {
                setDeleteInput('');
                setDeleteError('');
                setDeleteOpen(true);
              }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, color: c.danger }}>
                  <Icon name="trash" size={18} stroke={2.4} />
                  <span style={{ fontSize: 14, fontWeight: 700, fontFamily: theme.fontDisplay }}>{t.deleteAccount}</span>
                </div>
                <Icon name="chevron-right" size={18} stroke={2.2} style={{ color: c.inkMuted }} />
              </Row>
            </>
          ) : (
            <>
              <Row>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12, flex: 1 }}>
                  <div style={{
                    width: 44, height: 44, borderRadius: '50%',
                    background: c.bg, border: `1.5px dashed ${c.border}`,
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    color: c.inkMuted, fontFamily: theme.fontDisplay, fontSize: 18, fontWeight: 800,
                    flexShrink: 0,
                  }}>?</div>
                  <div>
                    <div style={{ fontSize: 15, fontWeight: 700, fontFamily: theme.fontDisplay }}>
                      {app.lang === 'es' ? 'Invitado' : 'Guest'}
                    </div>
                    <div style={{ fontSize: 12, color: c.inkSub, fontFamily: theme.fontBody, lineHeight: 1.35 }}>
                      {t.guestNote}
                    </div>
                  </div>
                </div>
              </Row>
              <Row onClick={() => app.signInWithApple()}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <span style={{
                    width: 32, height: 32, borderRadius: '50%', background: '#000',
                    border: `1px solid #000`,
                    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  }}>
                    <svg width="16" height="16" viewBox="0 0 384 512" aria-hidden="true">
                      <path fill="#fff" d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zM263.5 75.5c25.4-30.1 23.1-57.5 22.3-67.5-22.4 1.3-48.3 15.3-63 32.5-16.2 18.4-25.7 41.2-23.6 67 24.2 1.9 46.2-10.6 64.3-32z"/>
                    </svg>
                  </span>
                  <span style={{ fontSize: 14, fontWeight: 700, fontFamily: theme.fontDisplay }}>{t.signInWithApple}</span>
                </div>
                <Icon name="chevron-right" size={18} stroke={2.2} style={{ color: c.inkMuted }} />
              </Row>
              <Row last onClick={() => app.signInWithGoogle()}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                  <span style={{
                    width: 32, height: 32, borderRadius: '50%', background: '#fff',
                    border: `1px solid ${c.border}`,
                    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                  }}>
                    <svg width="16" height="16" viewBox="0 0 48 48" aria-hidden="true">
                      <path fill="#FFC107" d="M43.6 20.5H42V20H24v8h11.3c-1.6 4.7-6.1 8-11.3 8-6.6 0-12-5.4-12-12s5.4-12 12-12c3 0 5.8 1.1 7.9 3l5.7-5.7C34 6.1 29.3 4 24 4 12.9 4 4 12.9 4 24s8.9 20 20 20 20-8.9 20-20c0-1.3-.1-2.4-.4-3.5z"/>
                      <path fill="#FF3D00" d="M6.3 14.1l6.6 4.8C14.7 15.1 19 12 24 12c3 0 5.8 1.1 7.9 3l5.7-5.7C34 6.1 29.3 4 24 4 16.3 4 9.6 8.4 6.3 14.1z"/>
                      <path fill="#4CAF50" d="M24 44c5.2 0 9.9-2 13.4-5.2l-6.2-5.2c-2 1.4-4.5 2.3-7.2 2.3-5.2 0-9.6-3.3-11.3-8l-6.5 5C9.4 39.5 16.1 44 24 44z"/>
                      <path fill="#1976D2" d="M43.6 20.5H42V20H24v8h11.3c-.8 2.2-2.2 4.1-4.1 5.5l6.2 5.2c-.4.4 6.6-4.8 6.6-14.7 0-1.3-.1-2.4-.4-3.5z"/>
                    </svg>
                  </span>
                  <span style={{ fontSize: 14, fontWeight: 700, fontFamily: theme.fontDisplay }}>{t.signInWithGoogle}</span>
                </div>
                <Icon name="chevron-right" size={18} stroke={2.2} style={{ color: c.inkMuted }} />
              </Row>
            </>
          )}
        </Section>

        <Section title={t.appearance}>
          <Row>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <Icon name={app.dark ? 'moon' : 'sun'} size={18} stroke={2.2} />
              <span style={{ fontSize: 14, fontWeight: 600 }}>{app.dark ? t.dark : t.light}</span>
            </div>
            <Toggle on={app.dark} onClick={() => app.setDark(!app.dark)} />
          </Row>
          <Row>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <Icon name="sparkle-sm" size={18} stroke={2.2} />
              <span style={{ fontSize: 14, fontWeight: 600 }}>{app.lang === 'es' ? 'Animaciones' : 'Animations'}</span>
            </div>
            <Toggle on={app.animations} onClick={() => app.setAnimations(!app.animations)} />
          </Row>
          <div style={{ padding: '14px 18px 16px' }}>
            <div style={{
              fontSize: 13, fontWeight: 700, color: c.inkSub,
              fontFamily: theme.fontDisplay, marginBottom: 10,
              letterSpacing: 0.2,
            }}>{app.lang === 'es' ? 'Tema' : 'Theme'}</div>
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
              {THEME_PICKER.map(th => {
                const active = th.id === app.themeId;
                return (
                  <button key={th.id}
                    onClick={() => app.setThemeId(th.id)}
                    aria-label={th.name}
                    title={th.name}
                    style={{
                      flex: '1 1 calc(50% - 5px)', minWidth: 0, maxWidth: '100%',
                      boxSizing: 'border-box',
                      display: 'flex', alignItems: 'center', gap: 10,
                      padding: '10px 12px',
                      background: active ? c.bg : 'transparent',
                      border: `2px solid ${active ? th.accent : c.border}`,
                      borderRadius: theme.radius.md,
                      cursor: 'pointer', textAlign: 'left', overflow: 'hidden',
                      fontFamily: theme.fontDisplay,
                      transition: 'border-color .18s, background .18s',
                    }}>
                    <span style={{
                      width: 36, height: 36, flexShrink: 0,
                      borderRadius: '50%', position: 'relative',
                      background: `linear-gradient(135deg, ${th.accent} 0%, ${th.accent} 50%, ${th.accent2} 50%, ${th.accent2} 100%)`,
                      border: `1.5px solid ${c.border}`,
                    }}>
                      {active && (
                        <span style={{
                          position: 'absolute', inset: -2,
                          borderRadius: '50%',
                          boxShadow: `0 0 0 2px ${th.accent}`,
                        }} />
                      )}
                    </span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{
                        fontSize: 13, fontWeight: 800, color: c.ink,
                        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                      }}>
                        {th.name}
                      </div>
                      <div style={{
                        fontSize: 10, color: c.inkSub, fontFamily: theme.fontMono,
                        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                      }}>{th.sub}</div>
                    </div>
                    {active && <Icon name="check" size={16} stroke={2.6} style={{ color: th.accent, flexShrink: 0 }} />}
                  </button>
                );
              })}
            </div>
          </div>
          {/* Selector de estilo de iconos de categoría */}
          <div style={{ padding: '4px 18px 16px' }}>
            <div style={{
              fontSize: 13, fontWeight: 700, color: c.inkSub,
              fontFamily: theme.fontDisplay, marginBottom: 10,
              letterSpacing: 0.2,
            }}>{app.lang === 'es' ? 'Iconos' : 'Icons'}</div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              {[
                { id: 'emoji',    label: app.lang === 'es' ? 'Emoji'    : 'Emoji',    sub: 'Sistema' },
                { id: 'openmoji', label: 'OpenMoji', sub: app.lang === 'es' ? 'Color flat' : 'Flat color' },
                { id: 'material', label: 'Material', sub: app.lang === 'es' ? 'Outlined' : 'Outlined' },
                { id: 'line',     label: app.lang === 'es' ? 'Línea' : 'Line', sub: 'Minimal' },
              ].map(opt => {
                const active = opt.id === app.iconStyle;
                // Renderiza una preview con el estilo del botón. Forzamos el
                // modo via prop temporal.
                const previewCats = ['frutaverdura','carne','lacteos','panaderia'];
                return (
                  <button key={opt.id}
                    onClick={() => app.setIconStyle(opt.id)}
                    style={{
                      flex: '1 1 calc(50% - 4px)', minWidth: 0, maxWidth: '100%',
                      boxSizing: 'border-box',
                      display: 'flex', flexDirection: 'column',
                      alignItems: 'flex-start', gap: 8,
                      padding: '12px',
                      background: active ? c.bg : 'transparent',
                      border: `2px solid ${active ? c.accent : c.border}`,
                      borderRadius: theme.radius.md,
                      cursor: 'pointer', overflow: 'hidden',
                      transition: 'border-color .18s, background .18s',
                    }}>
                    <div style={{
                      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                      width: '100%', minWidth: 0, gap: 6,
                    }}>
                      <div style={{ minWidth: 0, overflow: 'hidden' }}>
                        <div style={{
                          fontSize: 14, fontWeight: 800,
                          color: c.ink, fontFamily: theme.fontDisplay,
                          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                        }}>{opt.label}</div>
                        <div style={{
                          fontSize: 11, color: c.inkSub, fontFamily: theme.fontMono,
                          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                        }}>{opt.sub}</div>
                      </div>
                      {active && <Icon name="check" size={16} stroke={2.6} style={{ color: c.accent, flexShrink: 0 }} />}
                    </div>
                    <div style={{
                      display: 'flex', gap: 6, alignItems: 'center',
                      color: c.ink, opacity: 0.85,
                      width: '100%', overflow: 'hidden',
                    }}>
                      {previewCats.map(k => (
                        <IconPreview key={k} catKey={k} mode={opt.id} size={16} />
                      ))}
                    </div>
                  </button>
                );
              })}
            </div>
          </div>
        </Section>

        <Section title={t.preferences}>
          <Row>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <Icon name="sparkle" size={18} stroke={2.2} />
              <span style={{ fontSize: 14, fontWeight: 600 }}>{t.autoCategory}</span>
            </div>
            <Toggle on={app.autoCategory} onClick={() => app.setAutoCategory(!app.autoCategory)} />
          </Row>
          <Row>
            <span style={{ fontSize: 14, fontWeight: 600 }}>{app.lang === 'es' ? 'Idioma' : 'Language'}</span>
            <div style={{ minWidth: 130 }}>
              <Radio value={app.lang} onChange={app.setLang} options={[
                { value: 'es', label: 'ES' },
                { value: 'en', label: 'EN' },
              ]} />
            </div>
          </Row>
          <Row>
            <span style={{ fontSize: 14, fontWeight: 600 }}>{app.lang === 'es' ? 'Densidad' : 'Density'}</span>
            <div style={{ minWidth: 200 }}>
              <Radio value={app.density} onChange={app.setDensity} options={[
                { value: 'compact',  label: app.lang === 'es' ? 'Comp' : 'Comp' },
                { value: 'comfy',    label: app.lang === 'es' ? 'Comfy' : 'Comfy' },
                { value: 'spacious', label: app.lang === 'es' ? 'Amplio' : 'Wide' },
              ]} />
            </div>
          </Row>
          <Row last>
            <span style={{ fontSize: 14, fontWeight: 600 }}>{app.lang === 'es' ? 'Modo compra' : 'Shop layout'}</span>
            <div style={{ minWidth: 140 }}>
              <Radio value={app.shopLayout} onChange={app.setShopLayout} options={[
                { value: 'mega', label: 'Mega' },
                { value: 'grid', label: 'Grid' },
              ]} />
            </div>
          </Row>
        </Section>

        {app.list && <Section title={t.share}>
          <Row>
            <span style={{ fontSize: 14, fontWeight: 600 }}>{app.lang === 'es' ? 'Lista' : 'List'}</span>
            <select
              value={app.currentListId || ''}
              onChange={(e) => app.setCurrentListId(e.target.value)}
              style={{
                padding: '8px 14px', fontSize: 13,
                fontFamily: theme.fontBody, fontWeight: 600,
                color: c.ink, background: c.bg,
                border: `1px solid ${c.border}`, borderRadius: 12,
                cursor: 'pointer', maxWidth: 220,
              }}>
              {app.lists.map(l => (
                <option key={l.id} value={l.id}>{l.name[app.lang]}</option>
              ))}
            </select>
          </Row>
          <div style={{ padding: 18, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14, borderBottom: `1px solid ${c.border}` }}>
            <button type="button"
              onClick={() => setQrZoomed(true)}
              aria-label={app.lang === 'es' ? 'Ampliar QR' : 'Enlarge QR'}
              title={app.lang === 'es' ? 'Ampliar QR' : 'Enlarge QR'}
              style={{
                background: 'transparent', border: 'none', padding: 0,
                cursor: 'zoom-in', WebkitTapHighlightColor: 'transparent',
              }}>
              <FakeQR theme={theme} value={link} />
            </button>
            <button
              type="button"
              onClick={async () => {
                const ok = await copyText(link);
                if (!ok) return;
                setLinkCopied(true);
                setTimeout(() => setLinkCopied(false), 1600);
              }}
              aria-label={app.lang === 'es' ? 'Copiar enlace' : 'Copy link'}
              title={app.lang === 'es' ? 'Copiar enlace' : 'Copy link'}
              style={{
                fontSize: 12, fontFamily: theme.fontMono,
                color: linkCopied ? c.success : c.inkSub,
                padding: '8px 14px',
                background: c.bg, borderRadius: 999,
                border: `1px solid ${linkCopied ? c.success : c.border}`,
                letterSpacing: 0.3, cursor: 'pointer',
                display: 'inline-flex', alignItems: 'center', gap: 8,
                transition: 'color .2s, border-color .2s',
              }}>
              <Icon name={linkCopied ? 'check' : 'copy'} size={12} stroke={2.4} />
              <span>{linkCopied ? (app.lang === 'es' ? '¡Copiado!' : 'Copied!') : link}</span>
            </button>
          </div>
          <Row last>
            <span style={{ fontSize: 13, color: c.inkSub, fontFamily: theme.fontBody, lineHeight: 1.4 }}>
              {t.shareNote}
            </span>
          </Row>
        </Section>}

        <Section title={t.about}>
          <Row last>
            {/* Easter egg: tap 10 veces seguidas en cualquier parte del texto
                "KomprApp · v2.0 · Web · JarsRushCode". Sin cursor pointer ni
                indicador visual — pasa desapercibido. */}
            <span onClick={onAuthorTap} style={{
              flex: 1, fontSize: 13, color: c.inkSub, fontFamily: theme.fontMono,
              cursor: 'inherit', WebkitUserSelect: 'none', userSelect: 'none',
            }}>
              KomprApp · v{window.__APP_VERSION__ || 'dev'} · {PLATFORM === 'ios' ? 'iOS' : PLATFORM === 'android' ? 'Android' : 'Web'} · JarsRushCode
            </span>
            <Icon name="flame" size={16} style={{ color: c.accent2 }} stroke={2.4} />
          </Row>
        </Section>

        </div>
      </div>
      <Sheet theme={theme} open={qrZoomed && !!app.list}
        mode={isDesktop ? 'dialog' : 'sheet'}
        onClose={() => setQrZoomed(false)}
        title={app.lang === 'es' ? 'Compartir lista' : 'Share list'}>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>
          <div className="sl-qr-zoom">
            <FakeQR theme={theme} value={link} size={isDesktop ? 360 : 280} />
          </div>
          <Btn theme={theme} variant="solid" size="md" full icon="download"
            onClick={() => downloadQR(app.list?.name?.[app.lang] || 'lista')}>
            {app.lang === 'es' ? 'Descargar QR' : 'Download QR'}
          </Btn>
        </div>
      </Sheet>
      <Sheet theme={theme} open={secretOpen}
        mode={isDesktop ? 'dialog' : 'sheet'}
        onClose={() => setSecretOpen(false)}
        title={app.lang === 'es' ? 'Para Lore' : 'For Lore'}>
        <div style={{
          display: 'flex', flexDirection: 'column', alignItems: 'center',
          gap: 16, textAlign: 'center', padding: '4px 4px 8px',
        }}>
          <div style={{ fontSize: 56, lineHeight: 1 }} aria-hidden="true">💛</div>
          <div style={{
            fontSize: 16, lineHeight: 1.6, color: c.ink,
            fontFamily: theme.fontBody,
          }}>
            {app.lang === 'es' ? (
              <>Esta aplicación ha sido hecha gracias al apoyo de mi mujer{' '}
                <strong style={{ color: c.accent2, fontFamily: theme.fontDisplay }}>Lore Puketa</strong>{' '}
                a la que quiero con locura. Gracias por ayudarme y apoyarme siempre.
                <br /><br />
                <em style={{ color: c.accent }}>Eres mi persona favorita.</em>
              </>
            ) : (
              <>This app exists thanks to the support of my wife{' '}
                <strong style={{ color: c.accent2, fontFamily: theme.fontDisplay }}>Lore Puketa</strong>,
                whom I love madly. Thank you for helping me and standing by me always.
                <br /><br />
                <em style={{ color: c.accent }}>You are my favorite person.</em>
              </>
            )}
          </div>
          <div style={{
            fontSize: 12, color: c.inkMuted, fontFamily: theme.fontMono,
            letterSpacing: 1, marginTop: 4,
          }}>— JarsRushCode</div>
        </div>
      </Sheet>
      <Sheet theme={theme} open={deleteOpen}
        mode={isDesktop ? 'dialog' : 'sheet'}
        onClose={() => { if (!deleteBusy) setDeleteOpen(false); }}
        title={t.deleteAccountTitle}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14, padding: '4px 4px 8px' }}>
          <div style={{
            fontSize: 14, lineHeight: 1.5, color: c.ink, fontFamily: theme.fontBody,
          }}>
            {t.deleteAccountWarn}
          </div>
          <label style={{
            fontSize: 12, fontWeight: 700, color: c.inkSub,
            fontFamily: theme.fontMono, textTransform: 'uppercase', letterSpacing: 1.2,
          }}>
            {t.deleteAccountConfirmHint}
          </label>
          <input
            type="text"
            autoComplete="off"
            autoCapitalize="characters"
            value={deleteInput}
            onChange={(e) => setDeleteInput(e.target.value)}
            placeholder={t.deleteAccountConfirmWord}
            disabled={deleteBusy}
            style={{
              padding: '12px 14px', fontSize: 16, fontWeight: 700,
              fontFamily: theme.fontMono, letterSpacing: 1.5,
              background: c.bg, color: c.ink,
              border: `1.5px solid ${deleteInput === t.deleteAccountConfirmWord ? c.danger : c.border}`,
              borderRadius: theme.radius.md, outline: 'none',
            }}
          />
          {deleteError ? (
            <div style={{ fontSize: 13, color: c.danger, fontFamily: theme.fontBody }}>
              {deleteError}
            </div>
          ) : null}
          <div style={{ display: 'flex', gap: 10, marginTop: 4 }}>
            <Btn theme={theme} variant="ghost" size="md" full
              onClick={() => { if (!deleteBusy) setDeleteOpen(false); }}>
              {t.deleteAccountCancel}
            </Btn>
            <Btn theme={theme} variant="danger" size="md" full
              disabled={deleteBusy || deleteInput !== t.deleteAccountConfirmWord}
              onClick={async () => {
                setDeleteBusy(true);
                setDeleteError('');
                const res = await app.deleteAccount();
                if (res?.error) {
                  setDeleteBusy(false);
                  setDeleteError(t.deleteAccountError);
                  return;
                }
                setDeleteBusy(false);
                setDeleteOpen(false);
                setDeleteInput('');
              }}>
              {deleteBusy ? '…' : t.deleteAccountCta}
            </Btn>
          </div>
        </div>
      </Sheet>
    </div>
  );
}

// QR real (usa qrcode-generator UMD cargado en index.html, window.qrcode).
// Si la librería no estuviera disponible, cae a un placeholder visual para
// evitar crashes — pero ya no es escaneable.
function FakeQR({ theme, value, size = 160 }) {
  const c = theme.c;
  const qr = React.useMemo(() => {
    const text = value ? (value.startsWith('http') ? value : 'https://' + value) : '';
    if (!text || typeof window.qrcode !== 'function') return null;
    try {
      const q = window.qrcode(0, 'M'); // typeNumber=0 (auto), ECC=M
      q.addData(text);
      q.make();
      return q;
    } catch (e) {
      console.error('[shoplist] qr generate', e);
      return null;
    }
  }, [value]);

  const cells = qr ? qr.getModuleCount() : 21;
  return (
    <div style={{
      padding: 12, background: '#fff',
      borderRadius: theme.radius.lg,
      border: `1px solid ${c.border}`,
      boxShadow: c.shadowSoft,
    }}>
      <svg width={size} height={size} viewBox={`0 0 ${cells} ${cells}`}
        shapeRendering="crispEdges"
        style={{ display: 'block' }}>
        {qr ? (
          Array.from({ length: cells }, (_, y) =>
            Array.from({ length: cells }, (_, x) => {
              if (!qr.isDark(y, x)) return null;
              return <rect key={`${x}-${y}`} x={x} y={y} width="1" height="1" fill="#0F0B1F" />;
            })
          )
        ) : (
          <rect x="0" y="0" width={cells} height={cells} fill="#fff" />
        )}
      </svg>
    </div>
  );
}

window.ListsScreen = ListsScreen;
window.HistoryScreen = HistoryScreen;
window.SettingsScreen = SettingsScreen;
window.FakeQR = FakeQR;
