// Biertje — App Screens: Dashboard, Feed, Achievements, Profile, LogBeerModal
const { useState, useEffect, useCallback, useRef } = React;

// ── Shortcut beer helpers ─────────────────────────────────────────
const CATEGORY_META = {
  beer: { icon: '🍺', label: 'Bier', step1Title: 'Welk bier?',   placeholder: 'bijv. Westmalle Tripel', nameLabel: 'Biernaam',      celebrateEmoji: '🍺' },
  shot: { icon: '🥃', label: 'Shot', step1Title: 'Welke shot?',  placeholder: 'bijv. Jägermeister',    nameLabel: 'Shotnaam',      celebrateEmoji: '🥃' },
  wine: { icon: '🍷', label: 'Wijn', step1Title: 'Welke wijn?',  placeholder: 'bijv. Sauvignon Blanc', nameLabel: 'Naam wijn',     celebrateEmoji: '🍷' },
  mix:  { icon: '🍹', label: 'Mix',  step1Title: 'Welk mixje?',  placeholder: 'bijv. Mojito',          nameLabel: 'Naam cocktail', celebrateEmoji: '🍹' },
};

const CATEGORY_SUBCATEGORIES = {
  beer: ['IPA', 'Stout', 'Lager', 'Weizen', 'Tripel', 'Anders'],
  shot: ['Whisky', 'Vodka', 'Gin', 'Rum', 'Tequila', 'Anders'],
  wine: ['Rood', 'Wit', 'Rosé', 'Schuimwijn', 'Anders'],
  mix:  ['Cocktail', 'Longdrink', 'Shooter', 'Mocktail', 'Anders'],
};

const CATEGORY_DEFAULTS = {
  beer: ['Hertog-Jan', 'Guinness', 'Heineken'],
  shot: ['Jägermeister', 'Tequila', 'Wodka'],
  wine: ['Sauvignon Blanc', 'Merlot', 'Prosecco'],
  mix:  ['Mojito', 'Gin Tonic', 'Aperol Spritz'],
};

function drinkChipStyle(name, category) {
  const l = (name || '').toLowerCase();
  if (l.includes('guinness')) return { bg: '#2C1810', fg: '#FFFFFF', shadow: 'rgba(44,24,16,0.30)' };
  if (l.includes('heineken')) return { bg: '#00A651', fg: '#FFFFFF', shadow: 'rgba(0,166,81,0.25)' };
  if (category === 'wine')    return { bg: '#7B2D8B', fg: '#FFFFFF', shadow: 'rgba(123,45,139,0.25)' };
  if (category === 'shot')    return { bg: '#5D3A1A', fg: '#F5E6D3', shadow: 'rgba(93,58,26,0.28)' };
  if (category === 'mix')     return { bg: '#0097A7', fg: '#FFFFFF', shadow: 'rgba(0,151,167,0.25)' };
  return                             { bg: T.amber,   fg: T.brown,   shadow: 'rgba(245,166,35,0.28)' };
}

async function fetchUserShortcuts(userId, category) {
  const cat = category || 'beer';
  const { data } = await db
    .from('beer_logs').select('beer_name, drink_category')
    .eq('user_id', userId).not('beer_name', 'is', null);
  const filtered = (data || []).filter(r => (r.drink_category || 'beer') === cat);
  const counts = {};
  for (const { beer_name } of filtered) {
    const n = (beer_name || '').trim();
    if (n) counts[n] = (counts[n] || 0) + 1;
  }
  const top = Object.entries(counts).sort(([, a], [, b]) => b - a).slice(0, 3).map(([n]) => n);
  const result = [...top];
  const defaults = CATEGORY_DEFAULTS[cat] || CATEGORY_DEFAULTS.beer;
  for (const d of defaults) { if (result.length >= 3) break; if (!result.includes(d)) result.push(d); }
  return result;
}

// ── Streak helper ─────────────────────────────────────────────────
function computeStreak(logs) {
  if (!logs || logs.length === 0) return 0;
  const dateSet = new Set(logs.map(l => l.logged_at.slice(0, 10)));
  const today   = new Date();
  let d = new Date(today.getFullYear(), today.getMonth(), today.getDate());
  // If no log today yet, start from yesterday (day still in progress)
  if (!dateSet.has(d.toISOString().slice(0, 10))) d.setDate(d.getDate() - 1);
  let count = 0;
  while (dateSet.has(d.toISOString().slice(0, 10))) { count++; d.setDate(d.getDate() - 1); }
  return count;
}

// ── Dashboard Screen ─────────────────────────────────────────────
function DashboardScreen({ profile, group, groups = [], onLogBeer, refreshKey }) {
  const [period, setPeriod]       = useState('Maand');
  const [members, setMembers]     = useState([]);
  const [activity, setActivity]   = useState([]);
  const [loading, setLoading]     = useState(true);
  const [viewingUserId, setViewingUserId] = useState(null);
  const [shortcuts, setShortcuts]         = useState([]);
  const [streak, setStreak]               = useState(0);
  const [nearBadges, setNearBadges]       = useState([]);
  const [groupHighlights, setGroupHighlights] = useState(null);
  const [challenges, setChallenges]       = useState([]);
  const [countdown, setCountdown]         = useState('');

  useEffect(() => {
    if (!profile) return;
    fetchUserShortcuts(profile.id).then(setShortcuts);
  }, [profile?.id]);

  useEffect(() => {
    if (!document.getElementById('brtje-ticker-style')) {
      const s = document.createElement('style');
      s.id = 'brtje-ticker-style';
      s.textContent = '@keyframes brtjeTicker{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}';
      document.head.appendChild(s);
    }
  }, []);

  // Countdown to end of month
  useEffect(() => {
    const tick = () => {
      const now = new Date();
      const end = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59);
      const diff = end - now;
      if (diff <= 0) { setCountdown('Verlopen'); return; }
      const d = Math.floor(diff / 86400000);
      const h = Math.floor((diff % 86400000) / 3600000);
      setCountdown(`Nog ${d}d ${h}u`);
    };
    tick();
    const iv = setInterval(tick, 60000);
    return () => clearInterval(iv);
  }, []);

  const getStartDate = useCallback((p) => {
    const now = new Date();
    if (p === 'Dag') {
      const d = new Date(now); d.setHours(0, 0, 0, 0); return d.toISOString();
    }
    if (p === 'Week') {
      const d = new Date(now); d.setDate(d.getDate() - 7); return d.toISOString();
    }
    if (p === 'Maand') {
      return new Date(now.getFullYear(), now.getMonth(), 1).toISOString();
    }
    return null;
  }, []);

  useEffect(() => {
    if (!group || !profile) return;
    fetchData();
  }, [group, profile, period, refreshKey]);

  const fetchData = async () => {
    setLoading(true);
    const startDate = getStartDate(period);
    const now2 = new Date();
    const monthKey  = `${now2.getFullYear()}-${String(now2.getMonth() + 1).padStart(2, '0')}`;
    const monthStart = new Date(now2.getFullYear(), now2.getMonth(), 1).toISOString();

    // Parallel fetch everything at once
    const [
      { data: gmData },
      { data: logs },
      { data: actData },
      { data: myAllLogs },
      { data: allAchs },
      { data: myUA },
      { data: groupAllLogs },
      { data: monthlyGroupLogs },
      { data: completions },
      { data: limitedBadges },
    ] = await Promise.all([
      db.from('group_members').select('user_id, profiles(display_name)').eq('group_id', group.id),
      (() => {
        let q = db.from('beer_logs').select('user_id, logged_at').eq('group_id', group.id);
        if (startDate) q = q.gte('logged_at', startDate);
        return q;
      })(),
      db.from('beer_logs')
        .select('user_id, beer_name, beer_type, logged_at, profiles(display_name, avatar_url)')
        .eq('group_id', group.id).neq('user_id', profile.id)
        .order('logged_at', { ascending: false }).limit(4),
      db.from('beer_logs').select('*').eq('user_id', profile.id),
      db.from('achievements').select('*').eq('is_limited', false),
      db.from('user_achievements').select('achievement_id').eq('user_id', profile.id),
      db.from('beer_logs').select('user_id, logged_at, beer_name').eq('group_id', group.id),
      db.from('beer_logs').select('user_id, beer_name').eq('group_id', group.id).gte('logged_at', monthStart),
      db.from('group_challenge_completions').select('challenge_key').eq('group_id', group.id).like('challenge_key', `${monthKey}-%`),
      db.from('achievements').select('id, challenge_key, name, icon').eq('is_limited', true).eq('period', monthKey),
    ]);

    // Leaderboard
    const counts = {};
    (gmData || []).forEach(m => {
      counts[m.user_id] = { user_id: m.user_id, name: m.profiles?.display_name || '?', count: 0, isMe: m.user_id === profile.id };
    });
    (logs || []).forEach(l => { if (counts[l.user_id]) counts[l.user_id].count++; });
    const membersArr = Object.values(counts);
    setMembers(membersArr);
    setActivity(actData || []);

    // Streak (cross-group, user's own logs)
    setStreak(computeStreak(myAllLogs || []));

    // Near badges — closest unearned, non-limited achievements
    const unlockedIds = new Set((myUA || []).map(u => u.achievement_id));
    const nearList = (allAchs || [])
      .filter(a => !unlockedIds.has(a.id))
      .map(a => {
        const { progress, total } = computeAchievementProgress(a, myAllLogs || []);
        return { ...a, progress, total, pct: total > 0 ? progress / total : 0 };
      })
      .filter(a => a.pct > 0 && a.pct < 1)
      .sort((a, b) => b.pct - a.pct)
      .slice(0, 2);
    setNearBadges(nearList);

    // Group highlights (all-time)
    const allLogs = groupAllLogs || [];
    const groupTotal = allLogs.length;

    // Most active member
    const perUser = {};
    for (const l of allLogs) perUser[l.user_id] = (perUser[l.user_id] || 0) + 1;
    const topEntry = Object.entries(perUser).sort(([, a], [, b]) => b - a)[0];
    const topName  = topEntry ? (membersArr.find(m => m.user_id === topEntry[0])?.name || '?') : null;

    // Most popular day of week
    const dayNames = ['Zondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrijdag','Zaterdag'];
    const dayCounts = [0,0,0,0,0,0,0];
    for (const l of allLogs) dayCounts[new Date(l.logged_at).getDay()]++;
    const popularDayIdx = dayCounts.indexOf(Math.max(...dayCounts));
    const popularDay = groupTotal > 0 ? dayNames[popularDayIdx] : null;

    // Average per member
    const memberCount = membersArr.length;
    const avgPerMember = memberCount > 0 ? Math.round(groupTotal / memberCount) : 0;

    // Most logged beer brand
    const brandCounts = {};
    for (const l of allLogs) {
      if (l.beer_name) { const n = l.beer_name.trim(); brandCounts[n] = (brandCounts[n] || 0) + 1; }
    }
    const topBrandEntry = Object.entries(brandCounts).sort(([, a], [, b]) => b - a)[0];
    const topBrand = topBrandEntry ? topBrandEntry[0] : null;

    setGroupHighlights({ total: groupTotal, topName, topCount: topEntry ? topEntry[1] : 0, memberCount, popularDay, avgPerMember, topBrand });

    // ── Group challenges ──────────────────────────────────────────
    const completedKeys = new Set((completions || []).map(c => c.challenge_key));
    const badgeMap = {};
    (limitedBadges || []).forEach(b => { if (b.challenge_key) badgeMap[b.challenge_key] = b; });

    const monthTotal2    = (monthlyGroupLogs || []).length;
    const uniqueBeerSet  = new Set((monthlyGroupLogs || []).map(l => l.beer_name).filter(Boolean));
    const memberCounts   = {};
    (monthlyGroupLogs || []).forEach(l => { memberCounts[l.user_id] = (memberCounts[l.user_id] || 0) + 1; });
    const qualifiedMembers = Object.values(memberCounts).filter(c => c >= 5).length;

    const monthNames = ['Jan','Feb','Mrt','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Dec'];
    const mName = monthNames[now2.getMonth()];

    const challengeDefs = [
      { key: `${monthKey}-quantity`,     icon: '🍺', title: 'Kwantiteitsmeesters', desc: `Log samen 100 drankjes in ${mName}`,      goal: 100,                    progress: monthTotal2,         color: T.amber },
      { key: `${monthKey}-variety`,      icon: '🌟', title: 'Smaakexplorers',       desc: 'Proef samen 15 unieke drankjes',           goal: 15,                     progress: uniqueBeerSet.size,  color: '#9B59B6' },
      { key: `${monthKey}-participation`,icon: '🤝', title: 'Geen Man Achter',       desc: `Elk lid logt minstens 5 drankjes`,        goal: Math.max(1, membersArr.length), progress: qualifiedMembers, color: '#27AE60' },
    ];
    const enriched = challengeDefs.map(c => ({
      ...c,
      pct:       Math.min(1, c.progress / Math.max(1, c.goal)),
      completed: completedKeys.has(c.key),
      badge:     badgeMap[c.key] || null,
    }));
    setChallenges(enriched);

    // Auto-award completed challenges to current user
    for (const c of enriched) {
      if (c.pct >= 1 && c.badge) {
        await db.from('group_challenge_completions').upsert(
          { group_id: group.id, challenge_key: c.key },
          { onConflict: 'group_id,challenge_key', ignoreDuplicates: true }
        );
        if (!unlockedIds.has(c.badge.id)) {
          await db.from('user_achievements').upsert(
            { user_id: profile.id, achievement_id: c.badge.id },
            { onConflict: 'user_id,achievement_id', ignoreDuplicates: true }
          );
        }
      } else if (c.completed && c.badge && !unlockedIds.has(c.badge.id)) {
        await db.from('user_achievements').upsert(
          { user_id: profile.id, achievement_id: c.badge.id },
          { onConflict: 'user_id,achievement_id', ignoreDuplicates: true }
        );
      }
    }

    setLoading(false);
  };

  const sorted = [...members].sort((a, b) => b.count - a.count);
  const myEntry = members.find(m => m.isMe);
  const myCount = myEntry ? myEntry.count : 0;
  const myRank  = sorted.findIndex(m => m.isMe) + 1 || sorted.length + 1;
  const leader  = sorted[0];
  const diff    = leader && myRank !== 1 ? Math.max(0, leader.count - myCount) : 0;
  const isMobile = useIsMobile();
  if (loading) return <Loading />;

  const heroPills = [
    { label: 'Jouw positie',  value: sorted.length === 0 ? '—' : `#${myRank}` },
    { label: period === 'Dag' ? 'vandaag gelogd' : period === 'Week' ? 'deze week' : period === 'Maand' ? 'deze maand' : 'ooit totaal', value: myCount },
    { label: 'actieve streak', value: streak > 0 ? `🔥 ${streak}d` : '—' },
  ];

  // Groepsstatistieken carousel chips
  const statChips = groupHighlights && groupHighlights.total > 0 ? [
    { icon: '🍺', value: groupHighlights.total,       label: 'drankjes ooit' },
    { icon: '👥', value: groupHighlights.memberCount, label: 'leden' },
    ...(groupHighlights.avgPerMember > 0 ? [{ icon: '📊', value: groupHighlights.avgPerMember, label: 'gem. per lid' }] : []),
    ...(groupHighlights.popularDay ? [{ icon: '📅', value: groupHighlights.popularDay, label: 'populairste dag' }] : []),
    ...(groupHighlights.topBrand ? [{ icon: '🥇', value: groupHighlights.topBrand.length > 12 ? groupHighlights.topBrand.slice(0, 11) + '...' : groupHighlights.topBrand, label: 'populairste drankje' }] : []),
    ...(groupHighlights.topName ? [{ icon: '🏆', value: groupHighlights.topName.split(' ')[0], label: `meest actief (${groupHighlights.topCount}x)` }] : []),
  ] : [];

  return (
    <div style={{ padding: isMobile ? '16px 14px' : '28px 32px', maxWidth: 900, margin: '0 auto' }}>

      {/* ── Hero Banner ──────────────────────────────────────────── */}
      <div style={{
        background: 'linear-gradient(135deg, #FCC24A 0%, #F5A623 28%, #A0622B 62%, #3D2B1F 100%)',
        borderRadius: isMobile ? 20 : 24,
        padding: isMobile ? '28px 22px 26px' : '38px 44px 32px',
        marginBottom: 20,
        position: 'relative', overflow: 'hidden',
        boxShadow: '0 8px 32px rgba(61,43,31,0.25), 0 2px 8px rgba(245,166,35,0.20)',
      }}>
        <div style={{ position: 'absolute', top: -60, right: -60, width: 220, height: 220, borderRadius: '50%', background: 'rgba(255,255,255,0.07)', pointerEvents: 'none' }} />
        <div style={{ position: 'absolute', bottom: -50, left: -50, width: 160, height: 160, borderRadius: '50%', background: 'rgba(255,255,255,0.05)', pointerEvents: 'none' }} />
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16, position: 'relative', marginBottom: 22 }}>
          <div style={{ flexShrink: 0, borderRadius: '50%', border: '3px solid rgba(255,255,255,0.35)', overflow: 'hidden' }}>
            <Avatar name={profile.display_name} size={isMobile ? 52 : 64} src={profile.avatar_url} />
          </div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 34, fontWeight: 700, color: '#FFF', lineHeight: 1.1, marginBottom: 6 }}>
              Hey {profile.display_name}!
            </div>
            <div style={{ fontSize: isMobile ? 13 : 15, color: 'rgba(255,255,255,0.82)', fontFamily: "'Nunito', sans-serif", lineHeight: 1.5, fontWeight: 600 }}>
              {sorted.length === 0
                ? `Welkom bij ${group.emoji} ${group.name}! Log je eerste bier.`
                : myRank === 1
                  ? `Je leidt ${group.emoji} ${group.name}! 👑 Houd ze achter je.`
                  : leader
                    ? `Je staat #${myRank} — ${diff} drankje${diff === 1 ? '' : 's'} achter ${leader.name}.`
                    : `Je staat op #${myRank} in ${group.emoji} ${group.name}.`
              }
            </div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: isMobile ? 10 : 14, flexWrap: 'wrap', position: 'relative' }}>
          {heroPills.map((pill, i) => (
            <div key={i} style={{
              background: 'rgba(255,255,255,0.16)',
              backdropFilter: 'blur(14px)',
              WebkitBackdropFilter: 'blur(14px)',
              borderRadius: 16,
              padding: isMobile ? '13px 18px' : '16px 24px',
              border: '1px solid rgba(255,255,255,0.26)',
              textAlign: 'center',
              minWidth: isMobile ? 88 : 108,
              flex: '1 1 auto',
              maxWidth: isMobile ? 130 : 160,
            }}>
              <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 30, fontWeight: 700, color: '#FFF', lineHeight: 1 }}>{pill.value}</div>
              <div style={{ fontSize: isMobile ? 10 : 11, color: 'rgba(255,255,255,0.80)', fontFamily: "'Nunito', sans-serif", marginTop: 5, fontWeight: 700, letterSpacing: '0.03em' }}>{pill.label}</div>
            </div>
          ))}
        </div>
      </div>

      {/* ── Leaderboard ──────────────────────────────────────────── */}
      <Card style={{ padding: '22px 24px', marginBottom: 20 }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 22, fontWeight: 700, color: T.brown, marginBottom: 20 }}>Leaderboard</div>
        <GroupBarChart members={sorted} period={period} onPeriodChange={p => setPeriod(p)} onMemberClick={uid => setViewingUserId(uid)} />
        {sorted.length > 0 && (
          <div style={{ marginTop: 20, padding: '12px 16px', background: T.chalk, borderRadius: 10, display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontSize: 16 }}>{myRank === 1 ? '👑' : '💡'}</span>
            <div style={{ fontSize: 12, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>
              {myRank === 1
                ? `Je leidt! Niet laten inhalen. 🍺`
                : leader ? `Log ${diff} meer drankje${diff === 1 ? '' : 's'} om ${leader.name} in te halen!` : 'Log je eerste drankje!'}
            </div>
          </div>
        )}
      </Card>

      {/* ── Groepsstatistieken (infinite carrousel) ──────────────── */}
      {statChips.length > 0 && (
        <div style={{ marginBottom: 22 }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 18, fontWeight: 700, color: T.brown, marginBottom: 12 }}>
            Groepsstatistieken
          </div>
          <div style={{ overflow: 'hidden', paddingBottom: 8 }}>
            <div style={{
              display: 'flex', gap: 12,
              animation: `brtjeTicker ${statChips.length * 3}s linear infinite`,
              width: 'max-content',
            }}>
              {[...statChips, ...statChips].map((chip, i) => (
                <div key={i} style={{
                  flexShrink: 0,
                  background: T.foam,
                  borderRadius: 18,
                  padding: isMobile ? '16px 20px' : '20px 28px',
                  border: '1.5px solid rgba(245,166,35,0.18)',
                  boxShadow: T.shadow,
                  minWidth: isMobile ? 120 : 144,
                  textAlign: 'center',
                }}>
                  <div style={{ fontSize: isMobile ? 30 : 36, marginBottom: 8, lineHeight: 1 }}>{chip.icon}</div>
                  <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 18 : 22, fontWeight: 700, color: T.brown, lineHeight: 1.1, marginBottom: 5 }}>{chip.value}</div>
                  <div style={{ fontSize: 10, color: T.brownLight, fontFamily: "'Nunito', sans-serif", fontWeight: 700, lineHeight: 1.4 }}>{chip.label}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}

      {/* ── Groeps-uitdagingen ──────────────────────────────────── */}
      {challenges.length > 0 && (
        <div style={{ marginBottom: 22 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 18, fontWeight: 700, color: T.brown }}>
              Groeps-uitdagingen
            </div>
            <div style={{
              display: 'flex', alignItems: 'center', gap: 6,
              background: T.chalk, borderRadius: 9999, padding: '5px 13px',
              fontFamily: "'Nunito', sans-serif", fontSize: 11, fontWeight: 700, color: T.brownLight,
            }}>
              📅 {countdown}
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : 'repeat(3, 1fr)', gap: 12 }}>
            {challenges.map(c => (
              <Card key={c.key} style={{ padding: '18px 20px', position: 'relative', overflow: 'hidden' }}>
                {c.completed && (
                  <div style={{
                    position: 'absolute', top: 0, right: 0,
                    background: '#27AE60', color: '#fff',
                    fontSize: 9, fontWeight: 700, fontFamily: "'Nunito', sans-serif",
                    letterSpacing: '0.1em', textTransform: 'uppercase',
                    padding: '3px 10px', borderBottomLeftRadius: 8,
                  }}>✓ Voltooid</div>
                )}
                <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, marginBottom: 12 }}>
                  <span style={{ fontSize: 28, lineHeight: 1, flexShrink: 0 }}>{c.icon}</span>
                  <div>
                    <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 16, fontWeight: 700, color: T.brown, lineHeight: 1.2 }}>{c.title}</div>
                    <div style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif", marginTop: 2, lineHeight: 1.4 }}>{c.desc}</div>
                  </div>
                </div>
                <div style={{ marginBottom: 10 }}>
                  <div style={{ height: 7, background: T.chalk, borderRadius: 9999, overflow: 'hidden', marginBottom: 5 }}>
                    <div style={{
                      height: '100%', borderRadius: 9999,
                      background: c.completed ? '#27AE60' : c.color,
                      width: `${Math.round(c.pct * 100)}%`,
                      transition: 'width 700ms ease',
                    }} />
                  </div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: T.brownLight, fontFamily: "'Nunito', sans-serif", fontWeight: 700 }}>
                    <span>{c.progress} / {c.goal}</span>
                    <span>{Math.round(c.pct * 100)}%</span>
                  </div>
                </div>
                {c.badge && (
                  <div style={{ display: 'flex', alignItems: 'center', gap: 7, padding: '7px 10px', background: 'linear-gradient(135deg, rgba(245,166,35,0.10) 0%, rgba(155,89,182,0.08) 100%)', borderRadius: 9, border: '1px solid rgba(245,166,35,0.18)' }}>
                    <span style={{ fontSize: 15 }}>{c.badge.icon}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 10, fontFamily: "'Nunito', sans-serif", fontWeight: 800, color: T.brownMid, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {c.badge.name}
                      </div>
                      <div style={{ fontSize: 9, color: T.amberDark, fontFamily: "'Nunito', sans-serif", fontWeight: 700 }}>✦ LIMITED EDITION</div>
                    </div>
                  </div>
                )}
              </Card>
            ))}
          </div>
        </div>
      )}

      {/* ── Bijna een Badge ──────────────────────────────────────── */}
      {nearBadges.length > 0 && (
        <Card style={{ padding: '20px 22px', marginBottom: 16 }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 18, fontWeight: 700, color: T.brown, marginBottom: 14 }}>Bijna een Badge 🏆</div>
          <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 14 }}>
            {nearBadges.map(b => (
              <div key={b.id}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 7 }}>
                  <span style={{ fontSize: 28, lineHeight: 1, flexShrink: 0 }}>{b.icon}</span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 800, fontSize: 13, color: T.brown, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{b.name}</div>
                    <div style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>{b.progress} / {b.total}</div>
                  </div>
                  <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 16, fontWeight: 700, color: T.amber, flexShrink: 0 }}>
                    {Math.round(b.pct * 100)}%
                  </div>
                </div>
                <ProgressBar value={b.progress} max={b.total} color={T.amber} />
              </div>
            ))}
          </div>
        </Card>
      )}

      {/* ── Streak ───────────────────────────────────────────────── */}
      <div style={{
        borderRadius: 18, padding: '18px 22px', marginBottom: 16,
        background: streak > 0 ? 'linear-gradient(135deg, #FCC24A 0%, #F5A623 100%)' : T.foam,
        border: streak > 0 ? 'none' : `1.5px solid rgba(245,166,35,0.13)`,
        boxShadow: streak > 0 ? '0 4px 20px rgba(245,166,35,0.40)' : T.shadow,
        display: 'flex', alignItems: 'center', gap: 16,
      }}>
        <div style={{ fontSize: streak > 0 ? 46 : 38, lineHeight: 1, filter: streak === 0 ? 'grayscale(0.85)' : 'none', flexShrink: 0 }}>🔥</div>
        <div>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 30, fontWeight: 700, color: streak > 0 ? T.brown : T.brownLight, lineHeight: 1 }}>
            {streak} {streak === 1 ? 'dag' : 'dagen'}
          </div>
          <div style={{ fontSize: 11, color: streak > 0 ? T.brownMid : T.brownLight, fontFamily: "'Nunito', sans-serif", fontWeight: 700, marginTop: 3 }}>
            {streak >= 7 ? '🔥 Ongestoppabel! Hou vol!' : streak > 0 ? 'Streak actief! Blijf loggen.' : 'Log vandaag een drankje.'}
          </div>
        </div>
      </div>

      {/* ── Log een biertje ──────────────────────────────────────── */}
      <Card style={{ padding: '20px 22px', marginBottom: 16 }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 18, fontWeight: 700, color: T.brown, marginBottom: 6 }}>Log een Drankje</div>
        <div style={{ fontSize: 13, color: T.brownLight, marginBottom: 14, fontFamily: "'Nunito', sans-serif" }}>Wat drink jij op dit moment?</div>
        {shortcuts.length > 0 && (
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 14 }}>
            {shortcuts.map(name => {
              const s = drinkChipStyle(name, 'beer');
              return (
                <button key={name} onClick={() => onLogBeer(name)} style={{
                  background: s.bg, border: 'none',
                  borderRadius: 9999, padding: '9px 18px',
                  fontFamily: "'Nunito', sans-serif", fontWeight: 800, fontSize: 13,
                  color: s.fg, cursor: 'pointer',
                  boxShadow: `0 2px 8px ${s.shadow}`,
                  transition: 'transform 140ms ease',
                }}
                  onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.06)'}
                  onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}
                >{name}</button>
              );
            })}
          </div>
        )}
        <Button variant="primary" size="md" onClick={() => onLogBeer()} fullWidth>+ Log een drankje</Button>
      </Card>

      {/* ── Activiteit ───────────────────────────────────────────── */}
      <Card style={{ overflow: 'hidden', marginBottom: 8 }}>
        <div style={{ padding: '16px 18px', borderBottom: `1px solid ${T.chalk}`, fontFamily: "'Fredoka', sans-serif", fontSize: 17, fontWeight: 700, color: T.brown }}>Activiteit</div>
        {activity.length === 0 ? (
          <div style={{ padding: '20px 18px', fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif", textAlign: 'center' }}>
            Nog geen activiteit van groepsleden 🕐
          </div>
        ) : activity.map((a, i) => {
          const aName  = a.profiles ? a.profiles.display_name : '?';
          const aAvUrl = a.profiles?.avatar_url;
          return (
            <div key={a.id || i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 18px', borderBottom: i < activity.length - 1 ? `1px solid ${T.chalk}` : 'none', cursor: 'pointer' }}
              onClick={() => setViewingUserId(a.user_id)}
            >
              <Avatar name={aName} size={32} src={aAvUrl} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <span style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 12, color: T.amberDark }}>{aName}</span>
                <span style={{ fontFamily: "'Nunito', sans-serif", fontSize: 12, color: T.brownLight }}>{' '}logde {a.beer_name || a.beer_type || 'een drankje'}</span>
              </div>
              <div style={{ fontSize: 10, color: '#B89880', fontFamily: "'Nunito', sans-serif", flexShrink: 0 }}>
                {timeAgo(a.logged_at)}
              </div>
            </div>
          );
        })}
      </Card>

      {viewingUserId && (
        <UserProfileModal
          userId={viewingUserId}
          currentUserId={profile.id}
          currentGroups={groups}
          onClose={() => setViewingUserId(null)}
        />
      )}
    </div>
  );
}

// ── Comment Section ───────────────────────────────────────────────
function CommentSection({ logId, comments, profile, draft, submitting, onDraftChange, onSubmit, onDelete }) {
  const inputRef = useRef(null);

  // Focus input when section opens
  useEffect(() => {
    if (inputRef.current) setTimeout(() => inputRef.current?.focus(), 50);
  }, []);

  return (
    <div style={{ borderTop: `1px solid ${T.chalk}`, padding: '12px 16px 14px', background: 'rgba(0,0,0,0.015)' }}>
      {/* Bestaande comments */}
      {comments.length > 0 && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 12 }}>
          {comments.map(c => (
            <div key={c.id} style={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}>
              <Avatar name={c.profiles?.display_name || '?'} size={28} src={c.profiles?.avatar_url} />
              <div style={{ flex: 1, background: T.chalk, borderRadius: 12, padding: '7px 11px', position: 'relative' }}>
                <span style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 800, fontSize: 12, color: T.brown }}>
                  {c.profiles?.display_name || '?'}
                </span>
                <span style={{ fontFamily: "'Nunito', sans-serif", fontSize: 13, color: T.brownMid, marginLeft: 6, lineHeight: 1.5 }}>
                  {c.content}
                </span>
                <div style={{ fontSize: 10, color: '#B89880', marginTop: 2, fontFamily: "'Nunito', sans-serif" }}>
                  {timeAgo(c.created_at)}
                </div>
              </div>
              {c.user_id === profile.id && (
                <button
                  onClick={() => onDelete(c.id, logId)}
                  title="Verwijder reactie"
                  style={{ background: 'transparent', border: 'none', cursor: 'pointer', fontSize: 13, padding: '4px', color: '#B89880', lineHeight: 1, flexShrink: 0, marginTop: 2 }}
                  onMouseEnter={e => e.currentTarget.style.color = T.berry}
                  onMouseLeave={e => e.currentTarget.style.color = '#B89880'}
                >✕</button>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Invoer */}
      <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <Avatar name={profile.display_name} size={28} src={profile.avatar_url} />
        <input
          ref={inputRef}
          value={draft || ''}
          onChange={e => onDraftChange(logId, e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey && !submitting) { e.preventDefault(); onSubmit(logId); } }}
          placeholder="Schrijf een reactie..."
          maxLength={300}
          style={{
            flex: 1, border: `1.5px solid ${T.brownBorder}`, borderRadius: 9999,
            padding: '7px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 13,
            color: T.brown, background: T.chalk, outline: 'none',
            transition: 'border-color 150ms',
          }}
          onFocus={e => e.target.style.borderColor = T.amber}
          onBlur={e => e.target.style.borderColor = T.brownBorder}
        />
        <button
          onClick={() => onSubmit(logId)}
          disabled={!(draft || '').trim() || submitting}
          style={{
            background: T.amber, border: 'none', borderRadius: 9999,
            padding: '7px 14px', fontFamily: "'Nunito', sans-serif",
            fontWeight: 800, fontSize: 12, color: T.brown, flexShrink: 0,
            cursor: (draft || '').trim() && !submitting ? 'pointer' : 'not-allowed',
            opacity: (draft || '').trim() && !submitting ? 1 : 0.45,
            transition: 'opacity 150ms',
          }}
        >
          {submitting ? '...' : 'Stuur'}
        </button>
      </div>
    </div>
  );
}

// ── Feed Screen ──────────────────────────────────────────────────
function FeedScreen({ profile, group, groups = [], refreshKey }) {
  const [logs, setLogs]           = useState([]);
  const [reactions, setReactions] = useState({}); // { [logId]: [{id, user_id, emoji}] }
  const [comments, setComments]   = useState({}); // { [logId]: [{id, user_id, content, ...}] }
  const [openComments, setOpenComments]     = useState(new Set());
  const [commentDraft, setCommentDraft]     = useState({});     // { [logId]: text }
  const [submittingComment, setSubmittingComment] = useState(null);
  const [loading, setLoading]     = useState(true);
  const [confirmDelete, setConfirmDelete] = useState(null);
  const [deleting, setDeleting]           = useState(null);
  const [viewingUserId, setViewingUserId] = useState(null);
  const [newIds, setNewIds]               = useState(new Set());
  const [newBanner, setNewBanner]         = useState(null);

  const topRef   = useRef(null);
  const atTopRef = useRef(true);
  const logsRef  = useRef([]);

  const isMobile = useIsMobile();
  const isOwner  = group?.created_by === profile?.id;

  useEffect(() => { logsRef.current = logs; }, [logs]);

  // ── Scroll-detectie ───────────────────────────────────────────
  useEffect(() => {
    const el = topRef.current;
    if (!el) return;
    const observer = new IntersectionObserver(
      ([entry]) => {
        atTopRef.current = entry.isIntersecting;
        if (entry.isIntersecting) setNewBanner(null);
      },
      { threshold: 0.1 }
    );
    observer.observe(el);
    return () => observer.disconnect();
  }, []);

  // ── Fetch ─────────────────────────────────────────────────────
  useEffect(() => {
    if (!group) return;
    fetchFeed();
  }, [group, refreshKey]);

  const fetchFeed = async () => {
    setLoading(true);
    const { data } = await db
      .from('beer_logs')
      .select('*, profiles(display_name, avatar_url)')
      .eq('group_id', group.id)
      .order('logged_at', { ascending: false })
      .limit(30);
    const fetched = data || [];
    setLogs(fetched);
    if (fetched.length > 0) {
      const ids = fetched.map(l => l.id);
      await Promise.all([fetchReactions(ids), fetchComments(ids)]);
    }
    setLoading(false);
  };

  const fetchReactions = async (logIds) => {
    const { data } = await db
      .from('beer_reactions')
      .select('id, beer_log_id, user_id, emoji')
      .in('beer_log_id', logIds);
    const map = {};
    for (const r of (data || [])) {
      if (!map[r.beer_log_id]) map[r.beer_log_id] = [];
      map[r.beer_log_id].push(r);
    }
    setReactions(map);
  };

  const fetchComments = async (logIds) => {
    const { data } = await db
      .from('beer_comments')
      .select('id, beer_log_id, user_id, content, created_at, profiles(display_name, avatar_url)')
      .in('beer_log_id', logIds)
      .order('created_at', { ascending: true });
    const map = {};
    for (const c of (data || [])) {
      if (!map[c.beer_log_id]) map[c.beer_log_id] = [];
      map[c.beer_log_id].push(c);
    }
    setComments(map);
  };

  // ── Realtime ──────────────────────────────────────────────────
  useEffect(() => {
    if (!group) return;

    const channel = db
      .channel(`feed-${group.id}`)

      .on('postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'beer_logs', filter: `group_id=eq.${group.id}` },
        async (payload) => {
          const { data } = await db
            .from('beer_logs')
            .select('*, profiles(display_name, avatar_url)')
            .eq('id', payload.new.id).single();
          if (!data) return;
          if (logsRef.current.find(l => l.id === data.id)) return;
          setLogs(prev => [data, ...prev]);
          setNewIds(ids => new Set([...ids, data.id]));
          setTimeout(() => setNewIds(ids => { const s = new Set(ids); s.delete(data.id); return s; }), 600);
          if (!atTopRef.current) {
            const author = data.profiles?.display_name || 'Iemand';
            setNewBanner(prev => prev
              ? { count: prev.count + 1, author: prev.author }
              : { count: 1, author }
            );
          }
        }
      )

      .on('postgres_changes',
        { event: 'DELETE', schema: 'public', table: 'beer_logs' },
        (payload) => {
          setLogs(prev => prev.filter(l => l.id !== payload.old.id));
          setReactions(prev => { const n = { ...prev }; delete n[payload.old.id]; return n; });
          setComments(prev => { const n = { ...prev }; delete n[payload.old.id]; return n; });
        }
      )

      .on('postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'beer_reactions' },
        (payload) => {
          const r = payload.new;
          setReactions(prev => {
            const cur = prev[r.beer_log_id] || [];
            if (cur.find(x => x.id === r.id)) return prev;
            const filtered = cur.filter(x => !(x.id.startsWith('temp-') && x.user_id === r.user_id && x.emoji === r.emoji));
            return { ...prev, [r.beer_log_id]: [...filtered, r] };
          });
        }
      )

      .on('postgres_changes',
        { event: 'DELETE', schema: 'public', table: 'beer_reactions' },
        (payload) => {
          const r = payload.old;
          setReactions(prev => ({
            ...prev,
            [r.beer_log_id]: (prev[r.beer_log_id] || []).filter(x => x.id !== r.id),
          }));
        }
      )

      // Nieuw comment → ophalen met profiel-join
      .on('postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'beer_comments' },
        async (payload) => {
          const c = payload.new;
          if (!logsRef.current.find(l => l.id === c.beer_log_id)) return;
          const { data } = await db
            .from('beer_comments')
            .select('id, beer_log_id, user_id, content, created_at, profiles(display_name, avatar_url)')
            .eq('id', c.id).single();
          if (!data) return;
          setComments(prev => {
            const cur = prev[c.beer_log_id] || [];
            // Vervang optimistic temp-entry als die er al in zit
            if (cur.find(x => x.id === data.id)) return prev;
            const filtered = cur.filter(x => !(x.id.startsWith('temp-') && x.user_id === data.user_id));
            return { ...prev, [c.beer_log_id]: [...filtered, data] };
          });
        }
      )

      .on('postgres_changes',
        { event: 'DELETE', schema: 'public', table: 'beer_comments' },
        (payload) => {
          const c = payload.old;
          setComments(prev => ({
            ...prev,
            [c.beer_log_id]: (prev[c.beer_log_id] || []).filter(x => x.id !== c.id),
          }));
        }
      )

      .subscribe();

    return () => { db.removeChannel(channel); };
  }, [group?.id]);

  // ── Toggle reactie ────────────────────────────────────────────
  const handleToggleReaction = useCallback(async (logId, emoji) => {
    const existing = (reactions[logId] || []).find(r => r.user_id === profile.id && r.emoji === emoji);
    if (existing) {
      setReactions(prev => ({ ...prev, [logId]: (prev[logId] || []).filter(r => r.id !== existing.id) }));
      await db.from('beer_reactions').delete().eq('id', existing.id);
    } else {
      const tempId = `temp-${Date.now()}`;
      setReactions(prev => ({ ...prev, [logId]: [...(prev[logId] || []), { id: tempId, beer_log_id: logId, user_id: profile.id, emoji }] }));
      const { data } = await db.from('beer_reactions').insert({ beer_log_id: logId, user_id: profile.id, emoji }).select().single();
      if (data) setReactions(prev => ({ ...prev, [logId]: (prev[logId] || []).map(r => r.id === tempId ? data : r) }));
    }
  }, [reactions, profile.id]);

  // ── Comments ──────────────────────────────────────────────────
  const handleToggleComments = useCallback((logId) => {
    setOpenComments(prev => {
      const next = new Set(prev);
      if (next.has(logId)) next.delete(logId); else next.add(logId);
      return next;
    });
  }, []);

  const handleDraftChange = useCallback((logId, text) => {
    setCommentDraft(prev => ({ ...prev, [logId]: text }));
  }, []);

  const handleSubmitComment = useCallback(async (logId) => {
    const text = (commentDraft[logId] || '').trim();
    if (!text || submittingComment) return;
    setSubmittingComment(logId);

    // Optimistic add
    const tempId = `temp-${Date.now()}`;
    const tempEntry = {
      id: tempId, beer_log_id: logId, user_id: profile.id,
      content: text, created_at: new Date().toISOString(),
      profiles: { display_name: profile.display_name, avatar_url: profile.avatar_url },
    };
    setComments(prev => ({ ...prev, [logId]: [...(prev[logId] || []), tempEntry] }));
    setCommentDraft(prev => ({ ...prev, [logId]: '' }));

    const { data } = await db
      .from('beer_comments')
      .insert({ beer_log_id: logId, user_id: profile.id, content: text })
      .select('id, beer_log_id, user_id, content, created_at, profiles(display_name, avatar_url)')
      .single();
    if (data) setComments(prev => ({ ...prev, [logId]: (prev[logId] || []).map(c => c.id === tempId ? data : c) }));

    setSubmittingComment(null);
  }, [commentDraft, profile, submittingComment]);

  const handleDeleteComment = useCallback(async (commentId, logId) => {
    setComments(prev => ({ ...prev, [logId]: (prev[logId] || []).filter(c => c.id !== commentId) }));
    await db.from('beer_comments').delete().eq('id', commentId);
  }, []);

  // ── Verwijder log ─────────────────────────────────────────────
  const handleDelete = async (logId) => {
    setDeleting(logId);
    const { error } = await db.from('beer_logs').delete().eq('id', logId);
    if (!error) {
      setLogs(prev => prev.filter(l => l.id !== logId));
      setReactions(prev => { const n = { ...prev }; delete n[logId]; return n; });
      setComments(prev => { const n = { ...prev }; delete n[logId]; return n; });
    }
    setDeleting(null);
    setConfirmDelete(null);
  };

  const scrollToTop = () => {
    topRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
    setNewBanner(null);
  };

  if (loading) return <Loading />;

  return (
    <div style={{ padding: isMobile ? '16px 0' : '28px 0', maxWidth: 640, margin: '0 auto' }}>
      <style>{`
        @keyframes feedSlideIn {
          from { opacity: 0; transform: translateY(-20px); }
          to   { opacity: 1; transform: translateY(0); }
        }
        @keyframes bannerDrop {
          from { opacity: 0; transform: translateY(-10px); }
          to   { opacity: 1; transform: translateY(0); }
        }
      `}</style>

      <div ref={topRef} style={{ padding: isMobile ? '0 14px 16px' : '0 24px 20px' }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 32, fontWeight: 700, color: T.brown, marginBottom: 4 }}>
          Activiteitenfeed
        </div>
        <p style={{ fontFamily: "'Nunito', sans-serif", fontSize: 15, color: T.brownLight }}>
          {group.emoji} {group.name} — wat drinkt de crew?
        </p>
      </div>

      {newBanner && (
        <div onClick={scrollToTop} style={{
          position: 'sticky', top: 8, zIndex: 20,
          margin: isMobile ? '0 14px 10px' : '0 24px 10px',
          background: T.amber, borderRadius: 12, padding: '10px 16px',
          display: 'flex', alignItems: 'center', gap: 8,
          cursor: 'pointer', boxShadow: '0 4px 18px rgba(245,166,35,0.40)',
          animation: 'bannerDrop 0.28s ease-out', userSelect: 'none',
        }}>
          <span style={{ fontSize: 20 }}>🍺</span>
          <span style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 800, fontSize: 13, color: T.brown, flex: 1 }}>
            {newBanner.count === 1 ? `${newBanner.author} logde een nieuw drankje!` : `${newBanner.count} nieuwe drankjes gelogd!`}
          </span>
          <span style={{ fontFamily: "'Nunito', sans-serif", fontSize: 12, color: T.brownMid, fontWeight: 700 }}>↑ Bekijk</span>
        </div>
      )}

      {logs.length === 0 ? (
        <div style={{ textAlign: 'center', padding: '60px 24px', color: T.brownLight }}>
          <div style={{ fontSize: 56, marginBottom: 14 }}>🍺</div>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 22, fontWeight: 700, color: T.brownMid, marginBottom: 8 }}>Nog geen drankjes gelogd</div>
          <div style={{ fontSize: 14, fontFamily: "'Nunito', sans-serif" }}>Wees de eerste! Log een drankje via de knop bovenin.</div>
        </div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12, padding: isMobile ? '0 14px' : '0 24px' }}>
          {logs.map((item) => {
            const name         = item.profiles ? item.profiles.display_name : '?';
            const avUrl        = item.profiles?.avatar_url;
            const isMe         = item.user_id === profile.id;
            const logReactions = reactions[item.id] || [];
            const logComments  = comments[item.id] || [];
            const myProost     = logReactions.find(r => r.user_id === profile.id && r.emoji === '🍺');
            const proostCount  = logReactions.filter(r => r.emoji === '🍺').length;
            const commentCount = logComments.length;
            const isNew        = newIds.has(item.id);
            const commentsOpen = openComments.has(item.id);

            return (
              <div key={item.id} style={{
                background: T.foam, borderRadius: 16,
                border: `1.5px solid rgba(245,166,35,0.12)`,
                boxShadow: T.shadow, overflow: 'hidden',
                animation: isNew ? 'feedSlideIn 0.45s ease-out' : 'none',
              }}>
                {/* Header */}
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '14px 16px 10px' }}>
                  <div onClick={() => !isMe && setViewingUserId(item.user_id)} style={{ cursor: isMe ? 'default' : 'pointer' }}>
                    <Avatar name={name} size={40} src={avUrl} />
                  </div>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14, color: T.brown }}>
                      <span
                        onClick={() => !isMe && setViewingUserId(item.user_id)}
                        style={{ cursor: isMe ? 'default' : 'pointer' }}
                        onMouseEnter={e => { if (!isMe) e.currentTarget.style.color = T.amberDark; }}
                        onMouseLeave={e => { if (!isMe) e.currentTarget.style.color = T.brown; }}
                      >{name}</span>
                      {isMe && <span style={{ color: T.amber }}> (jij)</span>}
                      <span style={{ fontWeight: 400, color: T.brownLight }}> logde een drankje</span>
                    </div>
                    <div style={{ fontSize: 11, color: '#B89880', fontFamily: "'Nunito', sans-serif", marginTop: 2 }}>{timeAgo(item.logged_at)}</div>
                  </div>
                </div>

                {/* Photo */}
                {item.photo_url && (
                  <img src={item.photo_url} alt={item.beer_name || 'bierfoto'}
                    style={{ width: '100%', maxHeight: 320, objectFit: 'cover', display: 'block' }} loading="lazy" />
                )}

                {/* Beer details */}
                <div style={{ padding: '4px 16px 14px' }}>
                  {item.beer_name && (
                    <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 21, fontWeight: 700, color: T.brown, marginBottom: 8 }}>{item.beer_name}</div>
                  )}
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: item.comment ? 10 : 0 }}>
                    {item.beer_type && <Badge variant="amber" size="sm">{item.beer_type}</Badge>}
                    {item.location && (
                      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, background: T.chalk, borderRadius: 9999, padding: '4px 10px', fontSize: 12, color: T.brownMid, fontFamily: "'Nunito', sans-serif", fontWeight: 600 }}>
                        📍 {item.location}
                      </span>
                    )}
                    {item.rating > 0 && <StarRating value={item.rating} readonly size={15} />}
                  </div>
                  {item.comment && (
                    <p style={{ fontSize: 14, color: T.brownMid, fontFamily: "'Nunito', sans-serif", margin: 0, lineHeight: 1.55, fontStyle: 'italic' }}>"{item.comment}"</p>
                  )}
                </div>

                {/* Reactions bar */}
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 16px 12px', borderTop: `1px solid ${T.chalk}` }}>
                  {/* Proost */}
                  <button onClick={() => handleToggleReaction(item.id, '🍺')} style={{
                    display: 'flex', alignItems: 'center', gap: 5,
                    background: myProost ? 'rgba(245,166,35,0.12)' : 'transparent',
                    border: `1.5px solid ${myProost ? T.amber : T.brownBorder}`,
                    borderRadius: 9999, padding: '5px 12px', cursor: 'pointer',
                    fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13,
                    color: myProost ? T.amberDark : T.brownMid, transition: 'all 150ms ease',
                  }}>
                    🍺 Proost!{proostCount > 0 && <span style={{ marginLeft: 2 }}>· {proostCount}</span>}
                  </button>

                  {/* Reageer / comment toggle */}
                  <button onClick={() => handleToggleComments(item.id)} style={{
                    display: 'flex', alignItems: 'center', gap: 5,
                    background: commentsOpen ? 'rgba(61,43,31,0.07)' : 'transparent',
                    border: `1.5px solid ${commentsOpen ? T.brownMid : T.brownBorder}`,
                    borderRadius: 9999, padding: '5px 12px', cursor: 'pointer',
                    fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13,
                    color: T.brownMid, transition: 'all 150ms ease',
                  }}>
                    💬 Reageer{commentCount > 0 && <span style={{ marginLeft: 2 }}>· {commentCount}</span>}
                  </button>

                  <span style={{ fontSize: 12, color: '#B89880', fontFamily: "'Nunito', sans-serif", flex: 1, textAlign: 'right' }}>
                    {new Date(item.logged_at).toLocaleString('nl-NL', { weekday: 'short', hour: '2-digit', minute: '2-digit' })}
                  </span>

                  {/* Delete */}
                  {(isOwner || item.user_id === profile.id) && (
                    confirmDelete === item.id ? (
                      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                        <span style={{ fontSize: 11, color: T.berry, fontFamily: "'Nunito', sans-serif", fontWeight: 700 }}>Verwijderen?</span>
                        <button onClick={() => setConfirmDelete(null)}
                          style={{ background: 'transparent', border: `1.5px solid ${T.brownBorder}`, borderRadius: 6, padding: '3px 8px', fontSize: 11, cursor: 'pointer', fontFamily: "'Nunito', sans-serif", fontWeight: 700, color: T.brownMid }}>Nee</button>
                        <button onClick={() => handleDelete(item.id)} disabled={deleting === item.id}
                          style={{ background: T.berry, border: 'none', borderRadius: 6, padding: '3px 8px', fontSize: 11, cursor: 'pointer', fontFamily: "'Nunito', sans-serif", fontWeight: 700, color: '#fff' }}>
                          {deleting === item.id ? '...' : 'Ja'}</button>
                      </div>
                    ) : (
                      <button onClick={() => setConfirmDelete(item.id)} title="Verwijder dit bier"
                        style={{ background: 'transparent', border: 'none', cursor: 'pointer', fontSize: 15, padding: '2px 4px', opacity: 0.45, transition: 'opacity 150ms ease', lineHeight: 1 }}
                        onMouseEnter={e => e.currentTarget.style.opacity = '1'}
                        onMouseLeave={e => e.currentTarget.style.opacity = '0.45'}>🗑️</button>
                    )
                  )}
                </div>

                {/* Comment sectie — klapt open/dicht */}
                {commentsOpen && (
                  <CommentSection
                    logId={item.id}
                    comments={logComments}
                    profile={profile}
                    draft={commentDraft[item.id]}
                    submitting={submittingComment === item.id}
                    onDraftChange={handleDraftChange}
                    onSubmit={handleSubmitComment}
                    onDelete={handleDeleteComment}
                  />
                )}
              </div>
            );
          })}
        </div>
      )}

      {viewingUserId && (
        <UserProfileModal
          userId={viewingUserId}
          currentUserId={profile.id}
          currentGroups={groups}
          onClose={() => setViewingUserId(null)}
        />
      )}
    </div>
  );
}

// ── Achievements Screen ──────────────────────────────────────────
function AchievementsScreen({ userId, group, refreshKey }) {
  const [achievements, setAchievements] = useState([]);
  const [unlocked, setUnlocked]         = useState([]);
  const [myLogs, setMyLogs]             = useState([]);
  const [loading, setLoading]           = useState(true);
  const [filterTier, setFilterTier]     = useState(null); // null = alles
  const [showFilterMenu, setShowFilterMenu] = useState(false);

  useEffect(() => {
    if (!userId) return;
    fetchData();
  }, [userId, refreshKey]);

  const fetchData = async () => {
    setLoading(true);
    const [{ data: achs }, { data: ua }, { data: logs }] = await Promise.all([
      db.from('achievements').select('*').order('sort_order'),
      db.from('user_achievements').select('achievement_id, unlocked_at').eq('user_id', userId),
      db.from('beer_logs').select('*').eq('user_id', userId),
    ]);
    setAchievements(achs || []);
    setUnlocked(ua || []);
    setMyLogs(logs || []);
    setLoading(false);
  };

  const isMobile = useIsMobile();
  const unlockedIds   = new Set((unlocked || []).map(u => u.achievement_id));
  const limitedAchs   = achievements.filter(a => a.is_limited);
  const customAchs    = achievements.filter(a => !a.is_limited && a.group_id);
  const regularAchs   = achievements.filter(a => !a.is_limited && !a.group_id);
  const unlockedCount = unlocked.filter(u => regularAchs.some(a => a.id === u.achievement_id)).length;
  const totalCount    = regularAchs.length;

  // Group regular badges by category
  const catOrder = ['quantity','streak','timing','variety','location','social'];
  const byCategory = {};
  regularAchs.forEach(a => {
    const cat = a.category || 'overig';
    if (!byCategory[cat]) byCategory[cat] = [];
    const { progress, total } = computeAchievementProgress(a, myLogs);
    const isUnlocked = unlockedIds.has(a.id);
    byCategory[cat].push({ ...a, progress: isUnlocked ? total : progress, total, unlocked: isUnlocked });
  });

  // Custom group badges with progress
  const customWithProgress = customAchs.map(a => {
    const { progress, total } = computeAchievementProgress(a, myLogs);
    const isUnlocked = unlockedIds.has(a.id);
    return { ...a, progress: isUnlocked ? total : progress, total, unlocked: isUnlocked };
  });
  const catEntries = [
    ...catOrder.filter(c => byCategory[c]).map(c => [c, byCategory[c]]),
    ...Object.entries(byCategory).filter(([c]) => !catOrder.includes(c)),
  ];

  const catLabels = { quantity: 'Kwantiteit', streak: 'Streaks', timing: 'Timing', variety: 'Variëteit', location: 'Locaties', social: 'Sociaal', overig: 'Overig' };
  const levelLabel = unlockedCount === 0 ? 'Prooster' : unlockedCount < 4 ? 'Biergenieter' : unlockedCount < 8 ? 'Bierliefhebber' : unlockedCount < 14 ? 'Brouwmeester' : unlockedCount < 23 ? 'Bierwarrior' : unlockedCount < 36 ? 'Legendaire Drinker' : 'Biergod';

  if (loading) return <Loading />;

  const tierOptions = [
    { key: 'bronze',   label: 'Brons',    dot: '#CD7F32' },
    { key: 'silver',   label: 'Zilver',   dot: '#9E9E9E' },
    { key: 'gold',     label: 'Goud',     dot: T.amber   },
    { key: 'platinum', label: 'Platina',  dot: T.grape   },
    { key: 'diamond',  label: 'Diamant',  dot: '#1565C0' },
  ];

  const filteredCatEntries = filterTier
    ? catEntries.map(([cat, items]) => [cat, items.filter(a => a.tier === filterTier)]).filter(function(pair) { return pair[1].length > 0; })
    : catEntries;

  return (
    <div style={{ padding: isMobile ? '16px 14px' : '28px 32px', maxWidth: 1000, margin: '0 auto' }}>
      {/* Header */}
      <div style={{ marginBottom: 24 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 32, fontWeight: 700, color: T.brown }}>Badges</div>
          {/* Tier filter */}
          <div style={{ position: 'relative' }}>
            <button onClick={() => setShowFilterMenu(v => !v)} style={{
              display: 'flex', alignItems: 'center', gap: 6,
              background: filterTier ? T.amberLight : T.chalk,
              border: filterTier ? `1.5px solid ${T.amber}` : `1.5px solid ${T.brownBorder}`,
              borderRadius: 10, padding: '7px 13px', cursor: 'pointer',
              fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.brownMid,
              transition: 'all 150ms ease',
            }}>
              <span style={{ fontSize: 16 }}>🎯</span>
              {filterTier ? tierOptions.find(t => t.key === filterTier)?.label : 'Filter'}
              {filterTier && (
                <span onClick={e => { e.stopPropagation(); setFilterTier(null); setShowFilterMenu(false); }}
                  style={{ marginLeft: 2, color: T.amberDark, fontSize: 14, fontWeight: 900, lineHeight: 1 }}>×</span>
              )}
            </button>
            {showFilterMenu && (
              <div style={{
                position: 'absolute', top: 'calc(100% + 6px)', right: 0, zIndex: 50,
                background: T.foam, borderRadius: 12, padding: '6px 0',
                boxShadow: T.shadowLg, border: `1.5px solid ${T.brownBorder}`,
                minWidth: 140,
              }}>
                {tierOptions.map(t => (
                  <button key={t.key} onClick={() => { setFilterTier(t.key); setShowFilterMenu(false); }} style={{
                    display: 'flex', alignItems: 'center', gap: 8,
                    width: '100%', padding: '9px 14px', border: 'none',
                    background: filterTier === t.key ? T.amberLight : 'transparent',
                    cursor: 'pointer', fontFamily: "'Nunito', sans-serif",
                    fontWeight: filterTier === t.key ? 800 : 600, fontSize: 13, color: T.brown,
                    transition: 'background 100ms ease',
                  }}>
                    <span style={{ width: 10, height: 10, borderRadius: '50%', background: t.dot, flexShrink: 0, display: 'inline-block' }} />
                    {t.label}
                  </button>
                ))}
              </div>
            )}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
          <div style={{ fontSize: 15, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>{unlockedCount} van {totalCount} vrijgespeeld</div>
          <div style={{ flex: 1, maxWidth: 200 }}><ProgressBar value={unlockedCount} max={Math.max(1, totalCount)} height={6} /></div>
          <Badge variant="amber">Level: {levelLabel} 🍺</Badge>
        </div>
      </div>

      {/* Limited Edition section */}
      {limitedAchs.length > 0 && (
        <div style={{ marginBottom: 32 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14 }}>
            <div style={{ fontFamily: "'Nunito', sans-serif", fontSize: 11, fontWeight: 700, letterSpacing: '0.11em', textTransform: 'uppercase', color: T.amberDark }}>⚡ Limited Edition</div>
            <div style={{ flex: 1, height: 1, background: 'linear-gradient(90deg, rgba(245,166,35,0.4) 0%, transparent 100%)' }} />
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 14 }}>
            {limitedAchs.map(a => {
              const isUnlocked = unlockedIds.has(a.id);
              return (
                <div key={a.id} style={{
                  background: isUnlocked
                    ? 'linear-gradient(135deg, #FCC24A 0%, #F5A623 50%, #C7831A 100%)'
                    : T.foam,
                  borderRadius: 16, padding: '18px 20px',
                  border: isUnlocked ? 'none' : `1.5px dashed rgba(245,166,35,0.40)`,
                  boxShadow: isUnlocked ? '0 4px 20px rgba(245,166,35,0.35)' : T.shadow,
                  opacity: isUnlocked ? 1 : 0.65,
                  position: 'relative', overflow: 'hidden',
                  transition: 'all 200ms ease',
                }}>
                  {isUnlocked && <div style={{ position: 'absolute', top: 0, right: 0, background: 'rgba(0,0,0,0.15)', padding: '3px 10px', borderBottomLeftRadius: 8, fontSize: 9, fontWeight: 700, color: '#fff', fontFamily: "'Nunito', sans-serif", letterSpacing: '0.1em' }}>✦ VERDIEND</div>}
                  <div style={{ fontSize: 38, marginBottom: 8 }}>{a.icon}</div>
                  <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 16, fontWeight: 700, color: isUnlocked ? T.brown : T.brownMid, marginBottom: 4 }}>{a.name}</div>
                  <div style={{ fontSize: 11, color: isUnlocked ? T.brownMid : T.brownLight, fontFamily: "'Nunito', sans-serif", lineHeight: 1.5, marginBottom: 8 }}>{a.description}</div>
                  <div style={{ fontSize: 9, fontWeight: 700, fontFamily: "'Nunito', sans-serif", color: isUnlocked ? T.brown : T.amberDark, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
                    {isUnlocked ? '🏆 Vrijgespeeld!' : '🔒 Groepsuitdaging'}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* Custom group badges */}
      {customWithProgress.length > 0 && (
        <div style={{ marginBottom: 32 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 14 }}>
            <div style={{ fontFamily: "'Nunito', sans-serif", fontSize: 11, fontWeight: 700, letterSpacing: '0.11em', textTransform: 'uppercase', color: T.brownMid }}>
              🏅 {group ? `${group.emoji} ${group.name}` : 'Groepsbadges'}
            </div>
            <div style={{ flex: 1, height: 1, background: T.brownBorder }} />
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 14 }}>
            {customWithProgress.map(a => (
              <AchievementCard key={a.id} icon={a.icon} name={a.name} desc={a.description} tier={a.tier} progress={a.progress} total={a.total} unlocked={a.unlocked} />
            ))}
          </div>
        </div>
      )}

      {/* Regular badges by category */}
      {filteredCatEntries.map(([cat, items]) => (
        <div key={cat} style={{ marginBottom: 34 }}>
          <div style={{ fontFamily: "'Nunito', sans-serif", fontSize: 11, fontWeight: 700, letterSpacing: '0.11em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 14 }}>
            {catLabels[cat] || cat}
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 14 }}>
            {items.map(a => (
              <AchievementCard key={a.id} icon={a.icon} name={a.name} desc={a.description} tier={a.tier} progress={a.progress} total={a.total} unlocked={a.unlocked} />
            ))}
          </div>
        </div>
      ))}

      {achievements.length === 0 && (
        <div style={{ textAlign: 'center', padding: 60, color: T.brownLight }}>
          <div style={{ fontSize: 48 }}>🏆</div>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, marginTop: 12 }}>Badges laden...</div>
        </div>
      )}
    </div>
  );
}

// ── Profile Screen ───────────────────────────────────────────────
function ProfileScreen({ profile, userId, group, groups = [], onSignOut, onProfileUpdated, refreshKey }) {
  const [totalBeers, setTotalBeers]         = useState(0);
  const [recentBeers, setRecentBeers]       = useState([]);
  const [favBeers, setFavBeers]             = useState([]);
  const [categoryBreakdown, setCategoryBreakdown] = useState([]);
  const [earnedAchs, setEarnedAchs]         = useState([]);
  const [totalAchCount, setTotalAchCount]   = useState(0);
  const [loading, setLoading]               = useState(true);

  // Profile editing
  const [uploadingPhoto, setUploadingPhoto] = useState(false);
  const [editBio, setEditBio]               = useState(false);
  const [bioText, setBioText]               = useState(profile?.bio || '');
  const [savingBio, setSavingBio]           = useState(false);
  const [feedback, setFeedback]             = useState(null);

  const showFeedback = (type, msg) => {
    setFeedback({ type, msg });
    setTimeout(() => setFeedback(null), 3500);
  };

  // Resize image before upload (max 400px, JPEG 88%)
  const resizeImage = (file) => new Promise((resolve) => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      URL.revokeObjectURL(url);
      const MAX = 400;
      const ratio = Math.min(1, MAX / Math.max(img.width, img.height));
      const canvas = document.createElement('canvas');
      canvas.width  = Math.round(img.width  * ratio);
      canvas.height = Math.round(img.height * ratio);
      canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
      canvas.toBlob(resolve, 'image/jpeg', 0.88);
    };
    img.src = url;
  });

  const handlePhotoUpload = async (e) => {
    const file = e.target.files[0];
    if (!file) return;
    setUploadingPhoto(true);
    const blob = await resizeImage(file);
    const path = `${userId}/avatar.jpg`;
    const { error: upErr } = await db.storage.from('profile-photos').upload(path, blob, {
      contentType: 'image/jpeg', upsert: true,
    });
    if (upErr) { showFeedback('err', 'Foto uploaden mislukt.'); setUploadingPhoto(false); return; }
    const { data: { publicUrl } } = db.storage.from('profile-photos').getPublicUrl(path);
    const avatarUrl = `${publicUrl}?v=${Date.now()}`;
    const { error: updErr } = await db.from('profiles').update({ avatar_url: avatarUrl }).eq('id', userId);
    if (updErr) { showFeedback('err', 'Profiel bijwerken mislukt.'); setUploadingPhoto(false); return; }
    onProfileUpdated && onProfileUpdated({ avatar_url: avatarUrl });
    showFeedback('ok', 'Profielfoto bijgewerkt! 📸');
    setUploadingPhoto(false);
  };

  const handleSaveBio = async () => {
    setSavingBio(true);
    const { error } = await db.from('profiles').update({ bio: bioText.trim() }).eq('id', userId);
    if (error) { showFeedback('err', 'Bio opslaan mislukt.'); setSavingBio(false); return; }
    onProfileUpdated && onProfileUpdated({ bio: bioText.trim() });
    setEditBio(false);
    setSavingBio(false);
    showFeedback('ok', 'Bio opgeslagen!');
  };

  const [deleteAccountConfirm, setDeleteAccountConfirm] = useState(false);
  const handleDeleteAccount = async () => {
    const { error } = await db.rpc('delete_user_account', { uid: userId });
    if (error) { showFeedback('err', 'Account verwijderen mislukt. Probeer opnieuw.'); setDeleteAccountConfirm(false); return; }
    await db.auth.signOut();
  };

  useEffect(() => {
    if (!userId) return;
    fetchData();
  }, [userId, refreshKey]);

  const fetchData = async () => {
    setLoading(true);
    const [
      { count },
      { data: recent },
      { data: allLogs },
      { data: ua },
      { count: achTotal },
    ] = await Promise.all([
      db.from('beer_logs').select('*', { count: 'exact', head: true }).eq('user_id', userId),
      db.from('beer_logs').select('*').eq('user_id', userId).order('logged_at', { ascending: false }).limit(5),
      db.from('beer_logs').select('beer_name, drink_category').eq('user_id', userId),
      db.from('user_achievements').select('unlocked_at, achievements(icon, name, tier, is_limited)').eq('user_id', userId).order('unlocked_at', { ascending: false }),
      db.from('achievements').select('*', { count: 'exact', head: true }).eq('is_limited', false),
    ]);
    setTotalBeers(count || 0);
    setRecentBeers(recent || []);
    setEarnedAchs(ua || []);
    setTotalAchCount(achTotal || 0);

    // Favourite drinks (count by name, track dominant category)
    const nameCounts = {};
    (allLogs || []).forEach(l => {
      if (!l.beer_name) return;
      const n = l.beer_name;
      if (!nameCounts[n]) nameCounts[n] = { count: 0, cats: {} };
      nameCounts[n].count++;
      const cat = l.drink_category || 'beer';
      nameCounts[n].cats[cat] = (nameCounts[n].cats[cat] || 0) + 1;
    });
    const sortedNames = Object.entries(nameCounts).sort((a, b) => b[1].count - a[1].count).slice(0, 5);
    const maxCnt = sortedNames[0] ? sortedNames[0][1].count : 1;
    setFavBeers(sortedNames.map(([name, { count, cats }]) => {
      const topCat = Object.entries(cats).sort((a, b) => b[1] - a[1])[0]?.[0] || 'beer';
      return { name, count, pct: Math.round((count / maxCnt) * 100), category: topCat };
    }));

    // Category breakdown (only if multiple categories used)
    const catTotals = { beer: 0, shot: 0, wine: 0, mix: 0 };
    (allLogs || []).forEach(l => {
      const cat = l.drink_category || 'beer';
      if (cat in catTotals) catTotals[cat]++;
    });
    const usedCats = Object.entries(catTotals).filter(([, v]) => v > 0);
    setCategoryBreakdown(usedCats.length > 1 ? usedCats : []);

    setLoading(false);
  };

  const tierColors = {
    gold:     { bg: T.amberLight, color: '#9A5F0C' },
    silver:   { bg: '#F5F5F5',    color: '#616161' },
    platinum: { bg: T.grapeBg,    color: '#3F2766' },
    bronze:   { bg: '#FFF3E0',    color: '#8B5000' },
    diamond:  { bg: '#E3F2FD',    color: '#0D47A1' },
  };

  const isMobile = useIsMobile();
  const joinedDate = profile ? new Date(profile.created_at).toLocaleDateString('nl-NL', { month: 'long', year: 'numeric' }) : '';
  const earnedNonLimited = earnedAchs.filter(u => !u.achievements?.is_limited);
  const totalAchievements = totalAchCount;

  if (loading) return <Loading />;

  return (
    <div style={{ padding: isMobile ? '16px 14px' : '28px 32px', maxWidth: 820, margin: '0 auto' }}>

      {/* Feedback banner */}
      {feedback && (
        <div style={{
          padding: '12px 16px', borderRadius: 10, marginBottom: 14,
          background: feedback.type === 'ok' ? T.leafBg : T.berryBg,
          border: `1.5px solid ${feedback.type === 'ok' ? T.leaf : T.berry}`,
          color: feedback.type === 'ok' ? '#2E7D32' : T.berry,
          fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14,
        }}>
          {feedback.type === 'ok' ? '✅ ' : '❌ '}{feedback.msg}
        </div>
      )}

      {/* Header card */}
      <Card style={{ padding: isMobile ? '20px 16px' : '28px', marginBottom: 16 }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: isMobile ? 14 : 20, marginBottom: 18, flexWrap: 'wrap' }}>

          {/* Avatar with upload overlay */}
          <div style={{ position: 'relative', flexShrink: 0 }}>
            <Avatar name={profile.display_name} size={isMobile ? 72 : 88} src={profile.avatar_url} />
            <label style={{
              position: 'absolute', bottom: 0, right: 0,
              width: 28, height: 28, background: T.amber, borderRadius: '50%',
              border: `2.5px solid ${T.foam}`, cursor: 'pointer',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 13, transition: 'transform 150ms ease',
            }}
              onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.15)'}
              onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}
            >
              📷
              <input type="file" accept="image/*" style={{ display: 'none' }} onChange={handlePhotoUpload} />
            </label>
            {uploadingPhoto && (
              <div style={{
                position: 'absolute', inset: 0, borderRadius: '50%',
                background: 'rgba(61,43,31,0.55)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 20,
              }}>⏳</div>
            )}
          </div>

          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 32, fontWeight: 700, color: T.brown }}>{profile.display_name}</div>
            <div style={{ fontFamily: "'Nunito', sans-serif", fontSize: 13, color: T.brownLight, marginTop: 2 }}>
              Lid van {groups.length} groep{groups.length !== 1 ? 'en' : ''} · Sinds {joinedDate}
            </div>

            {/* Bio */}
            {!editBio ? (
              <div style={{ marginTop: 8, display: 'flex', alignItems: 'baseline', gap: 6, flexWrap: 'wrap' }}>
                <span style={{ fontSize: 13, color: profile.bio ? T.brownMid : '#B89880', fontFamily: "'Nunito', sans-serif", fontStyle: profile.bio ? 'italic' : 'normal', lineHeight: 1.5 }}>
                  {profile.bio || 'Voeg een bio toe...'}
                </span>
                <button onClick={() => { setBioText(profile.bio || ''); setEditBio(true); }} style={{
                  background: 'none', border: 'none', cursor: 'pointer',
                  fontSize: 11, color: T.amber, fontWeight: 700, fontFamily: "'Nunito', sans-serif', flexShrink: 0",
                }}>✏️</button>
              </div>
            ) : (
              <div style={{ marginTop: 8, width: '100%' }}>
                <textarea
                  value={bioText}
                  onChange={e => setBioText(e.target.value)}
                  placeholder="Schrijf iets over jezelf... (max 160 tekens)"
                  maxLength={160}
                  autoFocus
                  style={{
                    width: '100%', padding: '8px 12px', fontFamily: "'Nunito', sans-serif",
                    fontSize: 13, color: T.brown, background: T.cream,
                    border: `2px solid ${T.amber}`, borderRadius: 10, outline: 'none',
                    resize: 'none', height: 68, lineHeight: 1.5, boxSizing: 'border-box',
                  }}
                />
                <div style={{ display: 'flex', gap: 8, marginTop: 6 }}>
                  <button onClick={() => setEditBio(false)} style={{ flex: 1, padding: '6px 0', background: 'transparent', border: `1.5px solid ${T.brownBorder}`, borderRadius: 8, cursor: 'pointer', fontFamily: "'Nunito', sans-serif", fontSize: 12, fontWeight: 700, color: T.brownMid }}>Annuleren</button>
                  <button onClick={handleSaveBio} disabled={savingBio} style={{ flex: 2, padding: '6px 0', background: T.amber, border: 'none', borderRadius: 8, cursor: 'pointer', fontFamily: "'Nunito', sans-serif", fontSize: 12, fontWeight: 700, color: T.brown }}>
                    {savingBio ? '⏳' : '💾 Opslaan'}
                  </button>
                </div>
              </div>
            )}

            <div style={{ display: 'flex', gap: 8, marginTop: 10, flexWrap: 'wrap' }}>
              {earnedAchs.length > 0 && <Badge variant="amber">🎖️ {earnedAchs.length} badges</Badge>}
              {totalBeers >= 100 && <Badge variant="dark">💎 Century Club</Badge>}
            </div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: isMobile ? 8 : 12, flexWrap: 'wrap' }}>
          <StatCard label="Totaal Drankjes" value={totalBeers} />
          <StatCard label="Badges" value={earnedNonLimited.length} sub={`van ${totalAchievements}`} amber />
          <StatCard label="Groepen" value={groups.length} sub={groups.length === 1 ? groups[0]?.name : `actief: ${group?.name || ''}`} dark />
        </div>
      </Card>

      <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1.2fr 1fr', gap: 16 }}>
        {/* Left column */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          {/* Earned Badges — prominent on left */}
          <Card style={{ padding: '22px' }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 19, fontWeight: 700, color: T.brown, marginBottom: 6 }}>Badges</div>
            <div style={{ fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif", marginBottom: earnedAchs.length ? 14 : 0 }}>
              {earnedNonLimited.length} van {totalAchievements} vrijgespeeld
            </div>
            {earnedAchs.length === 0 ? (
              <div style={{ fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif", lineHeight: 1.6, paddingTop: 6 }}>
                Log drankjes om badges te verdienen!
              </div>
            ) : (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
                {earnedAchs.map((ua, i) => {
                  if (!ua.achievements) return null;
                  const tc = tierColors[ua.achievements.tier] || tierColors.bronze;
                  return (
                    <div key={i} title={ua.achievements.name}
                      style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, background: tc.bg, borderRadius: 12, padding: '10px 12px', minWidth: 60, transition: 'transform 150ms ease', cursor: 'default' }}
                      onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.10)'}
                      onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}
                    >
                      <div style={{ fontSize: 30 }}>{ua.achievements.icon}</div>
                      <div style={{ fontSize: 9, fontWeight: 700, color: tc.color, fontFamily: "'Nunito', sans-serif", textAlign: 'center', lineHeight: 1.2, maxWidth: 56 }}>{ua.achievements.name}</div>
                    </div>
                  );
                })}
              </div>
            )}
          </Card>

          {/* Favourite Drinks */}
          <Card style={{ padding: '22px' }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 19, fontWeight: 700, color: T.brown, marginBottom: favBeers.length ? 18 : 10 }}>Favoriete Drankjes</div>
            {favBeers.length === 0 ? (
              <div style={{ fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif", lineHeight: 1.6 }}>Log drankjes met een naam om je favorieten te zien!</div>
            ) : favBeers.map((b, i) => {
              const catEmoji = { beer: '🍺', shot: '🥃', wine: '🍷', mix: '🍹' };
              return (
                <div key={i} style={{ marginBottom: 14 }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: "'Nunito', sans-serif", fontSize: 13, fontWeight: 600, color: T.brown, marginBottom: 5 }}>
                    <span>{catEmoji[b.category] || '🍺'} {b.name}</span>
                    <span style={{ color: T.brownLight }}>{b.count}×</span>
                  </div>
                  <ProgressBar value={b.pct} max={100} />
                </div>
              );
            })}
          </Card>

          {/* Category breakdown (only when multiple categories used) */}
          {categoryBreakdown.length > 0 && (
            <Card style={{ padding: '22px' }}>
              <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 19, fontWeight: 700, color: T.brown, marginBottom: 18 }}>Categorie-verdeling</div>
              {(() => {
                const maxCatVal = Math.max(...categoryBreakdown.map(([, v]) => v));
                const catEmoji  = { beer: '🍺', shot: '🥃', wine: '🍷', mix: '🍹' };
                const catLabel  = { beer: 'Bier', shot: 'Shot', wine: 'Wijn', mix: 'Mix' };
                return categoryBreakdown.map(([cat, cnt]) => (
                  <div key={cat} style={{ marginBottom: 14 }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: "'Nunito', sans-serif", fontSize: 13, fontWeight: 600, color: T.brown, marginBottom: 5 }}>
                      <span>{catEmoji[cat]} {catLabel[cat]}</span>
                      <span style={{ color: T.brownLight }}>{cnt}×</span>
                    </div>
                    <ProgressBar value={cnt} max={maxCatVal} />
                  </div>
                ));
              })()}
            </Card>
          )}
        </div>

        {/* Right column */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          {/* Mijn groepen */}
          <Card style={{ overflow: 'hidden' }}>
            <div style={{ padding: '16px 18px', borderBottom: `1px solid ${T.chalk}`, fontFamily: "'Fredoka', sans-serif", fontSize: 17, fontWeight: 700, color: T.brown }}>
              Mijn Groepen
            </div>
            {groups.length === 0 ? (
              <div style={{ padding: '16px 18px', fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>Je bent nog geen lid van een groep.</div>
            ) : groups.map((g, i) => {
              const isActive = group?.id === g.id;
              return (
                <div key={g.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 18px', borderBottom: i < groups.length - 1 ? `1px solid ${T.chalk}` : 'none', background: isActive ? T.amberLight : 'transparent' }}>
                  <span style={{ fontSize: 22, width: 28, textAlign: 'center', flexShrink: 0 }}>{g.emoji}</span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.brown, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{g.name}</div>
                    <div style={{ fontSize: 10, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>{g.myRole === 'owner' ? '👑 Eigenaar' : '👤 Lid'}</div>
                  </div>
                  {isActive && <Badge variant="amber" size="sm">Actief</Badge>}
                </div>
              );
            })}
          </Card>

          {/* Recent Beers */}
          <Card style={{ overflow: 'hidden' }}>
            <div style={{ padding: '16px 18px', borderBottom: `1px solid ${T.chalk}`, fontFamily: "'Fredoka', sans-serif", fontSize: 17, fontWeight: 700, color: T.brown }}>Recente Drankjes</div>
            {recentBeers.length === 0 ? (
              <div style={{ padding: '16px 18px', fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>Nog geen drankjes gelogd.</div>
            ) : recentBeers.map((b, i) => (
              <div key={b.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 18px', borderBottom: i < recentBeers.length - 1 ? `1px solid ${T.chalk}` : 'none' }}>
                <div style={{ fontSize: 20 }}>{({ beer: '🍺', shot: '🥃', wine: '🍷', mix: '🍹' })[b.drink_category] || '🍺'}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.brown, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{b.beer_name || b.beer_type || 'Bier'}</div>
                  {b.location && <div style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>📍 {b.location}</div>}
                </div>
                <div style={{ textAlign: 'right', flexShrink: 0 }}>
                  {b.rating > 0 && <StarRating value={b.rating} readonly size={12} />}
                  <div style={{ fontSize: 10, color: '#B89880', fontFamily: "'Nunito', sans-serif", marginTop: 2 }}>{timeAgo(b.logged_at)}</div>
                </div>
              </div>
            ))}
          </Card>
        </div>
      </div>

      {/* ── Account acties ─────────────────────────────────── */}
      <div style={{ marginTop: 24, display: 'flex', flexDirection: 'column', gap: 10 }}>
        <Button variant="danger" size="sm" onClick={onSignOut} fullWidth>Uitloggen</Button>
        {!deleteAccountConfirm ? (
          <button onClick={() => setDeleteAccountConfirm(true)} style={{
            background: 'transparent', border: `1.5px solid rgba(232,62,90,0.30)`,
            borderRadius: 10, padding: '10px 0', cursor: 'pointer',
            fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13,
            color: '#B0576A', transition: 'all 150ms ease',
          }}
          onMouseEnter={e => { e.currentTarget.style.background = '#FFF0F3'; e.currentTarget.style.borderColor = T.berry; }}
          onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.borderColor = 'rgba(232,62,90,0.30)'; }}
          >Account verwijderen</button>
        ) : (
          <div style={{ background: '#FFF0F3', borderRadius: 10, padding: '14px 16px', border: `1.5px solid ${T.berry}` }}>
            <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.berry, marginBottom: 10 }}>
              Weet je het zeker? Dit verwijdert je account en alle gegevens permanent.
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <Button variant="ghost" size="sm" onClick={() => setDeleteAccountConfirm(false)}>Annuleren</Button>
              <Button variant="danger" size="sm" onClick={handleDeleteAccount}>Ja, account verwijderen</Button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Log Beer Modal ───────────────────────────────────────────────
function LogBeerModal({ onClose, onLog, profile, prefillName }) {
  const isMobile = useIsMobile();
  const [step, setStep]                         = useState(0);
  const [drinkCategory, setDrinkCategory]       = useState('beer');
  const [drinkSubcategory, setDrinkSubcategory] = useState(null);
  const [beerName, setBeerName]                 = useState(String(prefillName || ''));
  const [location, setLocation]                 = useState('');
  const [rating, setRating]                     = useState(0);
  const [comment, setComment]                   = useState('');
  const [photo, setPhoto]                       = useState(null);
  const [photoPreview, setPhotoPreview]         = useState(null);
  const [saving, setSaving]                     = useState(false);
  const [shortcuts, setShortcuts]               = useState([]);
  const [locating, setLocating]                 = useState(false);
  const [nearbyPlaces, setNearbyPlaces]         = useState([]);

  const meta = CATEGORY_META[drinkCategory] || CATEGORY_META.beer;

  useEffect(() => {
    fetchUserShortcuts(profile.id, drinkCategory).then(setShortcuts);
  }, [profile.id, drinkCategory]);

  // ── GPS: detecteer nabijgelegen kroegen via OpenStreetMap (gratis) ──
  const handleGetLocation = () => {
    if (!navigator.geolocation) return;
    setLocating(true);
    setNearbyPlaces([]);

    navigator.geolocation.getCurrentPosition(
      async ({ coords: { latitude: lat, longitude: lng } }) => {
        try {
          // Overpass API (OpenStreetMap) — gratis, geen API-key nodig
          const query = `[out:json][timeout:8];(node["amenity"~"^(bar|pub|cafe)$"](around:300,${lat},${lng});way["amenity"~"^(bar|pub|cafe)$"](around:300,${lat},${lng}););out center 8;`;
          const r = await fetch('https://overpass-api.de/api/interpreter', {
            method: 'POST',
            body: 'data=' + encodeURIComponent(query),
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
          });
          const data = await r.json();
          const places = [...new Set(
            (data.elements || []).map(e => e.tags?.name).filter(Boolean)
          )].slice(0, 5);

          if (places.length > 0) {
            setNearbyPlaces(places);
          } else {
            await fetchCity(lat, lng);
          }
        } catch (_) {
          // Overpass onbereikbaar → valt door naar Nominatim
          try { await fetchCity(lat, lng); } catch (__) {}
        }
        setLocating(false);
      },
      () => setLocating(false),
      { timeout: 10000, maximumAge: 60000 }
    );
  };

  // Nominatim (OpenStreetMap) reverse geocoding — gratis, geen API-key nodig
  const fetchCity = async (lat, lng) => {
    try {
      const r = await fetch(
        `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&accept-language=nl`,
        { headers: { 'User-Agent': 'Drankmaatje-App/1.0' } }
      );
      const j = await r.json();
      const city =
        j.address?.city      ||
        j.address?.town      ||
        j.address?.village   ||
        j.address?.suburb    ||
        j.address?.county    || '';
      if (city) setLocation(city);
    } catch (_) {}
  };

  // ── Foto helpers ──────────────────────────────────────────────
  const resizeImage = (file) => new Promise((resolve) => {
    const img = new Image();
    const url = URL.createObjectURL(file);
    img.onload = () => {
      URL.revokeObjectURL(url);
      const MAX = 1200;
      const ratio = Math.min(1, MAX / Math.max(img.width, img.height));
      const canvas = document.createElement('canvas');
      canvas.width  = Math.round(img.width  * ratio);
      canvas.height = Math.round(img.height * ratio);
      canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
      canvas.toBlob(resolve, 'image/jpeg', 0.82);
    };
    img.src = url;
  });

  const handlePhotoChange = (e) => {
    const file = e.target.files[0];
    if (!file) return;
    setPhoto(file);
    const reader = new FileReader();
    reader.onload = () => setPhotoPreview(reader.result);
    reader.readAsDataURL(file);
  };

  const removePhoto = () => { setPhoto(null); setPhotoPreview(null); };

  const uploadPhoto = async (file) => {
    const blob = await resizeImage(file);
    const path = `${profile.id}/${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`;
    const { error } = await db.storage.from('beer-photos').upload(path, blob, { contentType: 'image/jpeg' });
    if (error) return null;
    const { data: { publicUrl } } = db.storage.from('beer-photos').getPublicUrl(path);
    return publicUrl;
  };

  const handleLog = async () => {
    setSaving(true);
    let photoUrl = null;
    if (photo) photoUrl = await uploadPhoto(photo);
    setStep(3);
    await onLog({
      beer_name:         (beerName + '').trim() || null,
      beer_type:         null,
      location:          (location + '').trim() || null,
      rating:            rating || null,
      comment:           (comment + '').trim() || null,
      photo_url:         photoUrl,
      has_photo:         !!photoUrl,
      drink_category:    drinkCategory,
      drink_subcategory: drinkSubcategory || null,
    });
    setSaving(false);
  };

  return (
    <div
      style={{ position: 'fixed', inset: 0, background: 'rgba(61,43,31,0.62)', display: 'flex', alignItems: isMobile ? 'flex-end' : 'center', justifyContent: 'center', zIndex: 500, backdropFilter: 'blur(6px)', padding: isMobile ? 0 : 24 }}
      onClick={step < 3 ? onClose : undefined}
    >
      <div
        onClick={e => e.stopPropagation()}
        style={{ background: T.foam, borderRadius: isMobile ? '24px 24px 0 0' : 24, padding: isMobile ? '24px 20px 32px' : 32, width: '100%', maxWidth: isMobile ? '100%' : 420, boxShadow: '0 32px 80px rgba(0,0,0,0.32)', animation: 'modalPop 350ms cubic-bezier(0.34,1.56,0.64,1)', maxHeight: isMobile ? '92vh' : 'auto', overflowY: 'auto' }}
      >
        {step < 3 && (
          <div style={{ display: 'flex', gap: 6, marginBottom: 24 }}>
            {[1, 2, 3].map(s => (
              <div key={s} style={{ flex: 1, height: 4, borderRadius: 9999, background: step >= s ? T.amber : T.brownBorder, transition: 'background 300ms ease' }} />
            ))}
          </div>
        )}

        {/* ── Stap 0: Categorie keuze ─────────────────────────── */}
        {step === 0 && (
          <>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 26, fontWeight: 700, color: T.brown, marginBottom: 4 }}>Wat ga je drinken?</div>
            <div style={{ fontSize: 13, color: T.brownLight, marginBottom: 22, fontFamily: "'Nunito', sans-serif" }}>Stap 1 — Kies een categorie</div>

            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 20 }}>
              {Object.entries(CATEGORY_META).map(([key, m]) => (
                <button
                  key={key}
                  onClick={() => { if (drinkCategory !== key) { setDrinkCategory(key); setDrinkSubcategory(null); } }}
                  style={{
                    background: drinkCategory === key ? T.amberLight : T.chalk,
                    border: `2px solid ${drinkCategory === key ? T.amber : T.brownBorder}`,
                    borderRadius: 14, padding: '16px 12px',
                    cursor: 'pointer', textAlign: 'center',
                    transition: 'all 160ms ease',
                  }}
                >
                  <div style={{ fontSize: 32, marginBottom: 6 }}>{m.icon}</div>
                  <div style={{ fontFamily: "'Fredoka', sans-serif", fontWeight: 700, fontSize: 16, color: drinkCategory === key ? T.brown : T.brownMid }}>
                    {m.label}
                  </div>
                </button>
              ))}
            </div>

            <div style={{ marginBottom: 20 }}>
              <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif" }}>
                Type (optioneel)
              </div>
              <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>
                {CATEGORY_SUBCATEGORIES[drinkCategory].map(sub => (
                  <button
                    key={sub}
                    onClick={() => setDrinkSubcategory(drinkSubcategory === sub ? null : sub)}
                    style={{
                      background: drinkSubcategory === sub ? T.amber : T.chalk,
                      border: `1.5px solid ${drinkSubcategory === sub ? T.amber : T.brownBorder}`,
                      borderRadius: 9999, padding: '6px 14px',
                      fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13,
                      color: drinkSubcategory === sub ? T.brown : T.brownMid,
                      cursor: 'pointer', transition: 'all 140ms ease',
                    }}
                  >
                    {sub}
                  </button>
                ))}
              </div>
            </div>

            <div style={{ display: 'flex', gap: 10 }}>
              <Button variant="ghost" size="md" onClick={onClose} style={{ flex: 1 }}>Annuleren</Button>
              <Button variant="primary" size="md" onClick={() => setStep(1)} style={{ flex: 2 }}>Volgende →</Button>
            </div>
          </>
        )}

        {/* ── Stap 1: Naam ──────────────────────────────────────── */}
        {step === 1 && (
          <>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 26, fontWeight: 700, color: T.brown, marginBottom: 4 }}>Log een {meta.label} {meta.icon}</div>
            <div style={{ fontSize: 13, color: T.brownLight, marginBottom: 22, fontFamily: "'Nunito', sans-serif" }}>Stap 2 — {meta.step1Title}</div>

            {/* Snelkoppelingen — top 3 favorieten per categorie */}
            <div style={{ marginBottom: 20 }}>
              <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 12, fontFamily: "'Nunito', sans-serif" }}>
                ⚡ Snel loggen
              </div>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {shortcuts.map(name => {
                  const s = drinkChipStyle(name, drinkCategory);
                  return (
                    <button
                      key={name}
                      onClick={() => { setBeerName(name); setStep(2); }}
                      style={{
                        background: s.bg, border: 'none',
                        borderRadius: 9999, padding: '10px 18px',
                        fontFamily: "'Nunito', sans-serif", fontWeight: 800, fontSize: 14,
                        color: s.fg, cursor: 'pointer',
                        boxShadow: `0 2px 8px ${s.shadow}`,
                        transition: 'transform 140ms ease',
                      }}
                      onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.05)'}
                      onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}
                    >
                      {name}
                    </button>
                  );
                })}
              </div>
            </div>

            {/* Scheider */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18 }}>
              <div style={{ flex: 1, height: 1, background: T.brownBorder }} />
              <span style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif", fontWeight: 700 }}>of typ zelf</span>
              <div style={{ flex: 1, height: 1, background: T.brownBorder }} />
            </div>

            <Input label={meta.nameLabel} placeholder={meta.placeholder} value={beerName} onChange={setBeerName} icon={meta.icon} />

            <div style={{ display: 'flex', gap: 10, marginTop: 6 }}>
              <Button variant="ghost" size="md" onClick={() => setStep(0)} style={{ flex: 1 }}>← Terug</Button>
              <Button variant="primary" size="md" onClick={() => setStep(2)} style={{ flex: 2 }} disabled={!(beerName + '').trim()}>Volgende →</Button>
            </div>
          </>
        )}

        {/* ── Stap 2: Locatie, rating, foto ───────────────────── */}
        {step === 2 && (
          <>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 26, fontWeight: 700, color: T.brown, marginBottom: 4 }}>Beoordeel je drankje ⭐</div>
            <div style={{ fontSize: 13, color: T.brownLight, marginBottom: 22, fontFamily: "'Nunito', sans-serif" }}>Stap 3 — Waar en hoe was het?</div>

            {/* Locatie + GPS knop */}
            <div style={{ marginBottom: nearbyPlaces.length > 0 ? 10 : 18 }}>
              <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif" }}>
                Locatie (optioneel)
              </div>
              <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                <div style={{ flex: 1, position: 'relative' }}>
                  <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', fontSize: 16, pointerEvents: 'none' }}>📍</span>
                  <input
                    placeholder="Bar, stad, of Thuis 🏡"
                    value={location}
                    onChange={e => setLocation(e.target.value)}
                    style={{ width: '100%', padding: '11px 14px 11px 36px', fontFamily: "'Nunito', sans-serif", fontSize: 14, color: T.brown, background: T.cream, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', boxSizing: 'border-box', transition: 'border-color 150ms' }}
                    onFocus={e => e.target.style.borderColor = T.amber}
                    onBlur={e => e.target.style.borderColor = T.brownBorder}
                  />
                </div>
                {/* GPS detectie-knop */}
                <button
                  onClick={handleGetLocation}
                  disabled={locating}
                  title={locating ? 'Locatie ophalen...' : 'Detecteer mijn locatie'}
                  style={{
                    background: locating ? T.chalk : T.amber,
                    border: 'none', borderRadius: 10,
                    width: 46, height: 46, flexShrink: 0,
                    cursor: locating ? 'default' : 'pointer',
                    fontSize: 22, display: 'flex', alignItems: 'center', justifyContent: 'center',
                    transition: 'all 140ms ease', boxShadow: locating ? 'none' : '0 2px 8px rgba(245,166,35,0.25)',
                  }}
                >
                  {locating ? '⏳' : '🧭'}
                </button>
              </div>
            </div>

            {/* Nabijgelegen plekken als chips */}
            {nearbyPlaces.length > 0 && (
              <div style={{ marginBottom: 18 }}>
                <div style={{ fontSize: 11, color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif", fontWeight: 600 }}>
                  In de buurt gevonden:
                </div>
                <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  {nearbyPlaces.map(place => (
                    <button
                      key={place}
                      onClick={() => { setLocation(place); setNearbyPlaces([]); }}
                      style={{
                        background: location === place ? T.amber : T.chalk,
                        border: `1.5px solid ${location === place ? T.amber : T.brownBorder}`,
                        borderRadius: 9999, padding: '6px 12px',
                        fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 12,
                        color: location === place ? T.brown : T.brownMid,
                        cursor: 'pointer', transition: 'all 140ms ease',
                      }}
                    >
                      {place}
                    </button>
                  ))}
                </div>
              </div>
            )}

            {/* Rating */}
            <div style={{ marginBottom: 18 }}>
              <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 10, fontFamily: "'Nunito', sans-serif" }}>Jouw Beoordeling</div>
              <StarRating value={rating} onChange={setRating} size={32} />
            </div>

            {/* Review */}
            <div style={{ marginBottom: 22 }}>
              <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif" }}>Korte Review (optioneel)</div>
              <textarea
                placeholder="Wat vond je ervan? Wees eerlijk."
                value={comment} onChange={e => setComment(e.target.value)}
                style={{ width: '100%', padding: '10px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 14, color: T.brown, background: T.cream, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', resize: 'none', height: 76, lineHeight: 1.5, boxSizing: 'border-box' }}
                onFocus={e => e.target.style.borderColor = T.amber}
                onBlur={e => e.target.style.borderColor = T.brownBorder}
              />
            </div>

            {/* Foto */}
            <div style={{ marginBottom: 20 }}>
              <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 10, fontFamily: "'Nunito', sans-serif" }}>Foto (optioneel)</div>
              {photoPreview ? (
                <div style={{ position: 'relative', borderRadius: 12, overflow: 'hidden' }}>
                  <img src={photoPreview} alt="preview" style={{ width: '100%', maxHeight: 220, objectFit: 'cover', display: 'block' }} />
                  <button onClick={removePhoto} style={{ position: 'absolute', top: 8, right: 8, background: 'rgba(61,43,31,0.75)', border: 'none', borderRadius: '50%', width: 28, height: 28, cursor: 'pointer', color: '#fff', fontSize: 13, display: 'flex', alignItems: 'center', justifyContent: 'center', lineHeight: 1 }}>✕</button>
                </div>
              ) : (
                <div style={{ display: 'flex', gap: 10 }}>
                  <label style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, background: T.chalk, border: `2px dashed ${T.brownBorder}`, borderRadius: 12, padding: '16px 10px', cursor: 'pointer', transition: 'all 140ms ease' }}
                    onMouseEnter={e => { e.currentTarget.style.borderColor = T.amber; e.currentTarget.style.background = T.amberLight; }}
                    onMouseLeave={e => { e.currentTarget.style.borderColor = T.brownBorder; e.currentTarget.style.background = T.chalk; }}>
                    <span style={{ fontSize: 28 }}>📸</span>
                    <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.brown }}>Camera</div>
                    <input type="file" accept="image/*" capture="environment" style={{ display: 'none' }} onChange={handlePhotoChange} />
                  </label>
                  <label style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, background: T.chalk, border: `2px dashed ${T.brownBorder}`, borderRadius: 12, padding: '16px 10px', cursor: 'pointer', transition: 'all 140ms ease' }}
                    onMouseEnter={e => { e.currentTarget.style.borderColor = T.amber; e.currentTarget.style.background = T.amberLight; }}
                    onMouseLeave={e => { e.currentTarget.style.borderColor = T.brownBorder; e.currentTarget.style.background = T.chalk; }}>
                    <span style={{ fontSize: 28 }}>🖼️</span>
                    <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.brown }}>Galerij</div>
                    <input type="file" accept="image/*" style={{ display: 'none' }} onChange={handlePhotoChange} />
                  </label>
                </div>
              )}
            </div>

            <div style={{ display: 'flex', gap: 10 }}>
              <Button variant="ghost" size="md" onClick={() => setStep(1)} style={{ flex: 1 }}>← Terug</Button>
              <Button variant="primary" size="md" onClick={handleLog} style={{ flex: 2 }} disabled={saving}>
                {saving ? (photo ? '📸 Uploaden...' : '⏳ Opslaan...') : `Log het! ${meta.icon}`}
              </Button>
            </div>
          </>
        )}

        {/* ── Stap 3: Gevierd ─────────────────────────────────── */}
        {step === 3 && (
          <div style={{ textAlign: 'center', padding: '24px 0 16px' }}>
            <div style={{ fontSize: 76, marginBottom: 18, display: 'inline-block', animation: 'beerCelebrate 650ms cubic-bezier(0.34,1.56,0.64,1)' }}>{meta.celebrateEmoji}</div>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 34, fontWeight: 700, color: T.brown, marginBottom: 8 }}>Gelogd!</div>
            <div style={{ fontSize: 16, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>Proost, {profile ? profile.display_name : ''}! 🎉</div>
          </div>
        )}
      </div>

      <style>{`
        @keyframes modalPop      { from{transform:scale(0.85) translateY(24px);opacity:0} to{transform:scale(1) translateY(0);opacity:1} }
        @keyframes beerCelebrate { from{transform:scale(0.2) rotate(-25deg);opacity:0} 65%{transform:scale(1.25) rotate(8deg)} to{transform:scale(1) rotate(0);opacity:1} }
      `}</style>
    </div>
  );
}

// ── Group Settings Screen ────────────────────────────────────────
function GroupSettingsScreen({ profile, group, userId, isOwner, onBack, onGroupUpdated, onGroupLeft, onGroupDeleted }) {
  const [members, setMembers]         = useState([]);
  const [loading, setLoading]         = useState(true);
  const [groupName, setGroupName]     = useState(group.name);
  const [emoji, setEmoji]             = useState(group.emoji);
  const [saving, setSaving]           = useState(false);
  const [kicking, setKicking]         = useState(null);
  const [deleteConfirm, setDeleteConfirm] = useState(false);
  const [leaveConfirm, setLeaveConfirm]   = useState(false);
  const [feedback, setFeedback]       = useState(null); // { type: 'ok'|'err', msg }
  const [showCode, setShowCode]       = useState(false);
  const EMOJIS = ['🍺','🏆','🔥','🎉','👑','⚡','🌍','🤘','🍻','🎸'];

  // Custom badges state
  const [customBadges, setCustomBadges]       = useState([]);
  const [badgesLoading, setBadgesLoading]     = useState(false);
  const [showBadgeForm, setShowBadgeForm]     = useState(false);
  const [badgeIcon, setBadgeIcon]             = useState('🏅');
  const [badgeName, setBadgeName]             = useState('');
  const [badgeDesc, setBadgeDesc]             = useState('');
  const [badgeTier, setBadgeTier]             = useState('bronze');
  const [badgeTrigger, setBadgeTrigger]       = useState('total_count');
  const [badgeValue, setBadgeValue]           = useState(10);
  const [savingBadge, setSavingBadge]         = useState(false);
  const [deletingBadge, setDeletingBadge]     = useState(null);
  const [editingBadge, setEditingBadge]       = useState(null);
  const [badgeBeerTarget, setBadgeBeerTarget] = useState('');

  const BADGE_ICONS = ['🏅','🎖','🏆','⭐','🌟','💫','🔥','⚡','🎯','🎪','🍺','🍻','🥇','🎉','👑','🦁','🐯','🌈','💎','🦄'];
  const BADGE_TIERS = [
    { key: 'bronze',   label: 'Brons',   color: '#CD7F32' },
    { key: 'silver',   label: 'Zilver',  color: '#9E9E9E' },
    { key: 'gold',     label: 'Goud',    color: T.amber   },
    { key: 'platinum', label: 'Platina', color: T.grape   },
    { key: 'diamond',  label: 'Diamant', color: '#1565C0' },
  ];
  const BADGE_TRIGGERS = [
    { key: 'total_count',       label: 'Aantal bieren gelogd',       unit: 'bieren' },
    { key: 'unique_beer_names', label: 'Unieke bieren geprobeerd',   unit: 'unieke bieren' },
    { key: 'streak',            label: 'Dagen op rij gedronken',     unit: 'dagen op rij' },
    { key: 'same_beer_repeat',  label: 'Zelfde bier herhaald',       unit: 'keer hetzelfde bier' },
    { key: 'with_note',         label: 'Bieren met review gelogd',   unit: 'bieren met review' },
    { key: 'unique_locations',  label: 'Unieke locaties bezocht',    unit: 'locaties' },
  ];

  useEffect(() => { fetchMembers(); }, [group.id]);
  useEffect(() => { if (isOwner) fetchCustomBadges(); }, [group.id, isOwner]);

  const fetchCustomBadges = async () => {
    setBadgesLoading(true);
    const { data } = await db.from('achievements').select('*').eq('group_id', group.id).order('created_at', { ascending: false });
    setCustomBadges(data || []);
    setBadgesLoading(false);
  };

  const resetBadgeForm = () => {
    setBadgeIcon('🏅'); setBadgeName(''); setBadgeDesc('');
    setBadgeTier('bronze'); setBadgeTrigger('total_count'); setBadgeValue(10);
    setBadgeBeerTarget(''); setEditingBadge(null);
    setShowBadgeForm(false);
  };

  const startEditBadge = (b) => {
    setEditingBadge(b);
    setBadgeIcon(b.icon);
    setBadgeName(b.name);
    setBadgeDesc(b.description || '');
    setBadgeTier(b.tier);
    setBadgeTrigger(b.trigger_type);
    setBadgeValue(b.total);
    setBadgeBeerTarget(b.trigger_filter || '');
    setShowBadgeForm(true);
  };

  const handleSaveBadge = async () => {
    if (!badgeName.trim()) return;
    setSavingBadge(true);
    const payload = {
      icon: badgeIcon,
      name: badgeName.trim(),
      description: badgeDesc.trim() || `Behaal ${badgeValue} ${BADGE_TRIGGERS.find(t => t.key === badgeTrigger)?.unit || 'keer'}.`,
      tier: badgeTier,
      trigger_type: badgeTrigger,
      total: Number(badgeValue),
      trigger_filter: (badgeTrigger === 'same_beer_repeat' && badgeBeerTarget.trim()) ? badgeBeerTarget.trim() : null,
    };
    let error;
    if (editingBadge) {
      ({ error } = await db.from('achievements').update(payload).eq('id', editingBadge.id));
    } else {
      ({ error } = await db.from('achievements').insert({
        ...payload, group_id: group.id, category: 'custom', is_limited: false, sort_order: 9999,
      }));
    }
    if (error) {
      showFeedback('err', editingBadge ? 'Bijwerken mislukt.' : 'Aanmaken mislukt. Probeer opnieuw.');
    } else {
      showFeedback('ok', editingBadge ? `Badge "${badgeName.trim()}" bijgewerkt!` : `Badge "${badgeName.trim()}" aangemaakt!`);
      resetBadgeForm();
      fetchCustomBadges();
    }
    setSavingBadge(false);
  };

  const handleDeleteBadge = async (badgeId, badgeName) => {
    setDeletingBadge(badgeId);
    const { error } = await db.from('achievements').delete().eq('id', badgeId);
    if (error) {
      showFeedback('err', `Verwijderen van "${badgeName}" mislukt.`);
    } else {
      setCustomBadges(b => b.filter(x => x.id !== badgeId));
      showFeedback('ok', `Badge "${badgeName}" verwijderd.`);
    }
    setDeletingBadge(null);
  };

  const fetchMembers = async () => {
    setLoading(true);
    const { data } = await db
      .from('group_members')
      .select('user_id, role, joined_at, profiles(display_name)')
      .eq('group_id', group.id);
    setMembers(data || []);
    setLoading(false);
  };

  const showFeedback = (type, msg) => {
    setFeedback({ type, msg });
    setTimeout(() => setFeedback(null), 3500);
  };

  // ── Groep bijwerken ──────────────────────────────────────────
  const handleSave = async () => {
    if (!groupName.trim()) return;
    setSaving(true);
    const { error } = await db
      .from('groups').update({ name: groupName.trim(), emoji }).eq('id', group.id);
    if (error) {
      showFeedback('err', 'Opslaan mislukt. Probeer opnieuw.');
    } else {
      onGroupUpdated({ ...group, name: groupName.trim(), emoji });
      showFeedback('ok', 'Wijzigingen opgeslagen!');
    }
    setSaving(false);
  };

  // ── Uitnodigingscode vernieuwen ──────────────────────────────
  const handleNewCode = async () => {
    const newCode = generateInviteCode();
    const { error } = await db
      .from('groups').update({ invite_code: newCode }).eq('id', group.id);
    if (error) {
      showFeedback('err', 'Code vernieuwen mislukt.');
    } else {
      onGroupUpdated({ ...group, invite_code: newCode, name: groupName.trim(), emoji });
      showFeedback('ok', `Nieuwe code: ${newCode}`);
    }
  };

  // ── Lid eruit gooien ─────────────────────────────────────────
  const handleKick = async (memberId, memberName) => {
    setKicking(memberId);
    const { error } = await db
      .from('group_members').delete()
      .eq('group_id', group.id).eq('user_id', memberId);
    if (error) {
      showFeedback('err', `Kon ${memberName} niet verwijderen.`);
    } else {
      setMembers(m => m.filter(m => m.user_id !== memberId));
      showFeedback('ok', `${memberName} verwijderd uit de groep.`);
    }
    setKicking(null);
  };

  // ── Groep verlaten ───────────────────────────────────────────
  const handleLeave = async () => {
    const { error } = await db
      .from('group_members').delete()
      .eq('group_id', group.id).eq('user_id', userId);
    if (error) {
      showFeedback('err', 'Verlaten mislukt. Probeer opnieuw.');
      setLeaveConfirm(false);
    } else {
      onGroupLeft();
    }
  };

  // ── Groep verwijderen ────────────────────────────────────────
  const handleDelete = async () => {
    const { error } = await db
      .from('groups').delete().eq('id', group.id);
    if (error) {
      showFeedback('err', 'Verwijderen mislukt. Probeer opnieuw.');
      setDeleteConfirm(false);
    } else {
      onGroupDeleted();
    }
  };

  const isMobile = useIsMobile();
  const tierColors = { owner: { bg: T.amberLight, color: '#9A5F0C' }, member: { bg: T.chalk, color: T.brownLight } };

  return (
    <div style={{ padding: isMobile ? '16px 14px' : '28px 32px', maxWidth: 760, margin: '0 auto' }}>
      {/* Back button */}
      {onBack && (
        <button onClick={onBack} style={{
          display: 'inline-flex', alignItems: 'center', gap: 6, marginBottom: 16,
          background: 'none', border: 'none', cursor: 'pointer', padding: '4px 0',
          fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14, color: T.brownMid,
          transition: 'color 150ms ease',
        }}
          onMouseEnter={e => e.currentTarget.style.color = T.brown}
          onMouseLeave={e => e.currentTarget.style.color = T.brownMid}
        >← Terug naar groepen</button>
      )}
      {/* Header */}
      <div style={{ marginBottom: 20 }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 32, fontWeight: 700, color: T.brown, marginBottom: 4 }}>
          ⚙️ Groepsinstellingen
        </div>
        <div style={{ fontSize: 15, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>
          {group.emoji} {group.name} · {isOwner ? '👑 Jij bent eigenaar' : '👤 Jij bent lid'}
        </div>
      </div>

      {/* Feedback banner */}
      {feedback && (
        <div style={{
          padding: '12px 16px', borderRadius: 10, marginBottom: 20,
          background: feedback.type === 'ok' ? T.leafBg : T.berryBg,
          border: `1.5px solid ${feedback.type === 'ok' ? T.leaf : T.berry}`,
          color: feedback.type === 'ok' ? '#2E7D32' : T.berry,
          fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14,
        }}>
          {feedback.type === 'ok' ? '✅ ' : '❌ '}{feedback.msg}
        </div>
      )}

      {/* ── Sectie: Uitnodigingscode ───────────────────────── */}
      <Card style={{ padding: '22px 24px', marginBottom: 20 }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, fontWeight: 700, color: T.brown, marginBottom: 16 }}>
          🔑 Uitnodigingscode
        </div>
        <div style={{ background: T.chalk, borderRadius: 12, padding: '14px 18px' }}>
          <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.08em', color: T.brownLight, fontFamily: "'Nunito', sans-serif", marginBottom: 6 }}>Deel deze code met vrienden</div>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 10 }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 28, fontWeight: 700, color: T.amber, letterSpacing: 4 }}>
              {showCode ? (group.invite_code || '—') : '••••••••••'}
            </div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              <Button variant="ghost" size="sm" onClick={() => setShowCode(s => !s)}>
                {showCode ? '👁 Verberg' : '👁 Toon'}
              </Button>
              {isOwner && (
                <Button variant="secondary" size="sm" onClick={handleNewCode}>🔄 Nieuwe code</Button>
              )}
            </div>
          </div>
        </div>
      </Card>

      {/* ── Sectie: Groep bewerken (alleen eigenaar) ──────── */}
      {isOwner && (
        <Card style={{ padding: '22px 24px', marginBottom: 20 }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, fontWeight: 700, color: T.brown, marginBottom: 16 }}>
            ✏️ Groep bewerken
          </div>
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 10, fontFamily: "'Nunito', sans-serif" }}>Emoji</div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              {EMOJIS.map(e => (
                <button key={e} onClick={() => setEmoji(e)} style={{
                  width: 40, height: 40, fontSize: 20,
                  background: emoji === e ? T.amberLight : T.chalk,
                  border: `2px solid ${emoji === e ? T.amber : T.brownBorder}`,
                  borderRadius: 10, cursor: 'pointer', transition: 'all 140ms ease',
                }}>{e}</button>
              ))}
            </div>
          </div>
          <Input label="Groepsnaam" placeholder="Naam van je groep" value={groupName} onChange={setGroupName} icon={emoji} />
          <Button variant="primary" size="md" onClick={handleSave} disabled={saving || !groupName.trim()}>
            {saving ? '⏳ Opslaan...' : '💾 Wijzigingen opslaan'}
          </Button>
        </Card>
      )}

      {/* ── Sectie: Leden ─────────────────────────────────── */}
      <Card style={{ overflow: 'hidden', marginBottom: 20 }}>
        <div style={{ padding: '18px 22px', borderBottom: `1px solid ${T.chalk}` }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, fontWeight: 700, color: T.brown }}>
            👥 Leden {!loading && `(${members.length})`}
          </div>
        </div>
        {loading ? (
          <div style={{ padding: 24 }}><Loading /></div>
        ) : members.length === 0 ? (
          <div style={{ padding: '20px 22px', color: T.brownLight, fontFamily: "'Nunito', sans-serif", fontSize: 14 }}>Geen leden gevonden.</div>
        ) : members.map((m, i) => {
          const name = m.profiles ? m.profiles.display_name : '?';
          const isMe = m.user_id === userId;
          const tc = tierColors[m.role] || tierColors.member;
          return (
            <div key={m.user_id} style={{
              display: 'flex', alignItems: 'center', gap: 12,
              padding: '13px 22px',
              borderBottom: i < members.length - 1 ? `1px solid ${T.chalk}` : 'none',
            }}>
              <Avatar name={name} size={38} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14, color: T.brown }}>
                  {name}{isMe && <span style={{ color: T.amber }}> (jij)</span>}
                </div>
                <div style={{ fontSize: 11, color: '#B89880', fontFamily: "'Nunito', sans-serif", marginTop: 1 }}>
                  Lid sinds {new Date(m.joined_at).toLocaleDateString('nl-NL', { day: 'numeric', month: 'short', year: 'numeric' })}
                </div>
              </div>
              <span style={{
                display: 'inline-block', fontSize: 10, fontWeight: 700, letterSpacing: '0.08em',
                textTransform: 'uppercase', background: tc.bg, color: tc.color,
                borderRadius: 9999, padding: '3px 10px', fontFamily: "'Nunito', sans-serif",
              }}>{m.role === 'owner' ? '👑 Eigenaar' : 'Lid'}</span>
              {/* Eigenaar kan anderen eruit gooien */}
              {isOwner && !isMe && m.role !== 'owner' && (
                <Button
                  variant="danger" size="xs"
                  disabled={kicking === m.user_id}
                  onClick={() => handleKick(m.user_id, name)}
                >
                  {kicking === m.user_id ? '...' : 'Verwijderen'}
                </Button>
              )}
            </div>
          );
        })}
      </Card>

      {/* ── Sectie: Eigen Badges ──────────────────────────── */}
      {isOwner && (
        <Card style={{ padding: '22px 24px', marginBottom: 20 }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
            <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, fontWeight: 700, color: T.brown }}>
              🏅 Eigen Badges
            </div>
            {!showBadgeForm && (
              <Button variant="secondary" size="sm" onClick={() => setShowBadgeForm(true)}>+ Nieuwe badge</Button>
            )}
          </div>

          {/* Create form */}
          {showBadgeForm && (
            <div style={{ background: T.chalk, borderRadius: 14, padding: '18px 20px', marginBottom: 16 }}>
              <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 800, fontSize: 14, color: T.brown, marginBottom: 14 }}>{editingBadge ? 'Badge bewerken' : 'Nieuwe badge aanmaken'}</div>

              {/* Icon picker */}
              <div style={{ marginBottom: 14 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif" }}>Icoon</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                  {BADGE_ICONS.map(ic => (
                    <button key={ic} onClick={() => setBadgeIcon(ic)} style={{
                      width: 38, height: 38, fontSize: 20, borderRadius: 9,
                      background: badgeIcon === ic ? T.amberLight : T.foam,
                      border: `2px solid ${badgeIcon === ic ? T.amber : T.brownBorder}`,
                      cursor: 'pointer', transition: 'all 120ms ease',
                    }}>{ic}</button>
                  ))}
                </div>
              </div>

              {/* Name */}
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 6, fontFamily: "'Nunito', sans-serif" }}>Naam</div>
                <input
                  placeholder="bijv. Groepslegende"
                  value={badgeName}
                  onChange={e => setBadgeName(e.target.value)}
                  maxLength={40}
                  style={{ width: '100%', padding: '10px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 14, color: T.brown, background: T.foam, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', boxSizing: 'border-box', transition: 'border-color 150ms' }}
                  onFocus={e => e.target.style.borderColor = T.amber}
                  onBlur={e => e.target.style.borderColor = T.brownBorder}
                />
              </div>

              {/* Description */}
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 6, fontFamily: "'Nunito', sans-serif" }}>Beschrijving (optioneel)</div>
                <input
                  placeholder="Korte beschrijving van de badge"
                  value={badgeDesc}
                  onChange={e => setBadgeDesc(e.target.value)}
                  maxLength={80}
                  style={{ width: '100%', padding: '10px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 14, color: T.brown, background: T.foam, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', boxSizing: 'border-box', transition: 'border-color 150ms' }}
                  onFocus={e => e.target.style.borderColor = T.amber}
                  onBlur={e => e.target.style.borderColor = T.brownBorder}
                />
              </div>

              {/* Tier */}
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif" }}>Tier</div>
                <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  {BADGE_TIERS.map(t => (
                    <button key={t.key} onClick={() => setBadgeTier(t.key)} style={{
                      display: 'flex', alignItems: 'center', gap: 5,
                      padding: '6px 12px', borderRadius: 9999,
                      background: badgeTier === t.key ? T.amberLight : T.foam,
                      border: `2px solid ${badgeTier === t.key ? T.amber : T.brownBorder}`,
                      fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 12, color: T.brown,
                      cursor: 'pointer', transition: 'all 120ms ease',
                    }}>
                      <span style={{ width: 8, height: 8, borderRadius: '50%', background: t.color, display: 'inline-block', flexShrink: 0 }} />
                      {t.label}
                    </button>
                  ))}
                </div>
              </div>

              {/* Trigger type + value */}
              <div style={{ display: 'flex', gap: 10, marginBottom: 16, flexWrap: 'wrap' }}>
                <div style={{ flex: 2, minWidth: 180 }}>
                  <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 6, fontFamily: "'Nunito', sans-serif" }}>Voorwaarde</div>
                  <select
                    value={badgeTrigger}
                    onChange={e => setBadgeTrigger(e.target.value)}
                    style={{ width: '100%', padding: '10px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 13, color: T.brown, background: T.foam, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', boxSizing: 'border-box', cursor: 'pointer' }}
                  >
                    {BADGE_TRIGGERS.map(t => (
                      <option key={t.key} value={t.key}>{t.label}</option>
                    ))}
                  </select>
                </div>
                <div style={{ flex: 1, minWidth: 80 }}>
                  <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 6, fontFamily: "'Nunito', sans-serif" }}>Doel</div>
                  <input
                    type="number"
                    min={1} max={9999}
                    value={badgeValue}
                    onChange={e => setBadgeValue(Math.max(1, Number(e.target.value) || 1))}
                    style={{ width: '100%', padding: '10px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 14, fontWeight: 700, color: T.brown, background: T.foam, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', boxSizing: 'border-box', transition: 'border-color 150ms', textAlign: 'center' }}
                    onFocus={e => e.target.style.borderColor = T.amber}
                    onBlur={e => e.target.style.borderColor = T.brownBorder}
                  />
                </div>
              </div>

              {/* Specifiek bier (alleen bij same_beer_repeat) */}
              {badgeTrigger === 'same_beer_repeat' && (
                <div style={{ marginBottom: 12 }}>
                  <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 6, fontFamily: "'Nunito', sans-serif" }}>Specifiek bier (optioneel)</div>
                  <input
                    placeholder="bijv. Guinness — leeg = willekeurig bier"
                    value={badgeBeerTarget}
                    onChange={e => setBadgeBeerTarget(e.target.value)}
                    maxLength={50}
                    style={{ width: '100%', padding: '10px 14px', fontFamily: "'Nunito', sans-serif", fontSize: 14, color: T.brown, background: T.foam, border: `2px solid ${T.brownBorder}`, borderRadius: 10, outline: 'none', boxSizing: 'border-box', transition: 'border-color 150ms' }}
                    onFocus={e => e.target.style.borderColor = T.amber}
                    onBlur={e => e.target.style.borderColor = T.brownBorder}
                  />
                </div>
              )}

              {/* Preview */}
              <div style={{ background: T.foam, borderRadius: 10, padding: '10px 14px', marginBottom: 14, display: 'flex', alignItems: 'center', gap: 12 }}>
                <span style={{ fontSize: 30 }}>{badgeIcon}</span>
                <div>
                  <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 15, fontWeight: 700, color: T.brown }}>{badgeName || 'Badgenaam'}</div>
                  <div style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>
                    {badgeDesc || `Behaal ${badgeValue} ${BADGE_TRIGGERS.find(t => t.key === badgeTrigger)?.unit || 'keer'}.`}
                  </div>
                  <div style={{ fontSize: 10, fontWeight: 700, color: BADGE_TIERS.find(t => t.key === badgeTier)?.color, fontFamily: "'Nunito', sans-serif", textTransform: 'uppercase', letterSpacing: '0.07em', marginTop: 2 }}>
                    {BADGE_TIERS.find(t => t.key === badgeTier)?.label}
                  </div>
                </div>
              </div>

              <div style={{ display: 'flex', gap: 8 }}>
                <Button variant="ghost" size="sm" onClick={resetBadgeForm} style={{ flex: 1 }}>Annuleren</Button>
                <Button variant="primary" size="sm" onClick={handleSaveBadge} disabled={savingBadge || !badgeName.trim()} style={{ flex: 2 }}>
                  {savingBadge ? '⏳ Opslaan...' : editingBadge ? '💾 Opslaan' : '✅ Badge aanmaken'}
                </Button>
              </div>
            </div>
          )}

          {/* List of existing custom badges */}
          {badgesLoading ? (
            <div style={{ padding: '10px 0', color: T.brownLight, fontFamily: "'Nunito', sans-serif", fontSize: 14 }}>Laden...</div>
          ) : customBadges.length === 0 && !showBadgeForm ? (
            <div style={{ padding: '14px 0', color: T.brownLight, fontFamily: "'Nunito', sans-serif", fontSize: 14 }}>
              Nog geen eigen badges. Klik op "+ Nieuwe badge" om er een aan te maken.
            </div>
          ) : customBadges.map(b => {
            const tierColor = BADGE_TIERS.find(t => t.key === b.tier)?.color || T.amber;
            const trigLabel = BADGE_TRIGGERS.find(t => t.key === b.trigger_type)?.label || b.trigger_type;
            return (
              <div key={b.id} style={{
                display: 'flex', alignItems: 'center', gap: 12,
                padding: '12px 14px', borderRadius: 10, marginBottom: 8,
                background: T.foam, border: `1.5px solid ${T.brownBorder}`,
              }}>
                <span style={{ fontSize: 28, flexShrink: 0 }}>{b.icon}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 15, fontWeight: 700, color: T.brown }}>{b.name}</div>
                  <div style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif", marginTop: 1 }}>
                    {trigLabel} — doel: {b.total}
                  </div>
                </div>
                <span style={{ fontSize: 10, fontWeight: 700, color: tierColor, fontFamily: "'Nunito', sans-serif", textTransform: 'uppercase', letterSpacing: '0.07em', flexShrink: 0 }}>
                  {BADGE_TIERS.find(t => t.key === b.tier)?.label}
                </span>
                <Button variant="secondary" size="xs" onClick={() => startEditBadge(b)}>Bewerk</Button>
                <Button
                  variant="danger" size="xs"
                  disabled={deletingBadge === b.id}
                  onClick={() => handleDeleteBadge(b.id, b.name)}
                >
                  {deletingBadge === b.id ? '...' : 'Verwijder'}
                </Button>
              </div>
            );
          })}
        </Card>
      )}

      {/* ── Sectie: Gevarenzone ───────────────────────────── */}
      <Card style={{ padding: '22px 24px', border: `1.5px solid rgba(232,62,90,0.20)` }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, fontWeight: 700, color: T.berry, marginBottom: 16 }}>
          ⚠️ Gevarenzone
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {/* Groep verlaten — voor iedereen (niet de eigenaar als er nog leden zijn) */}
          {!isOwner && (
            <div style={{ background: T.chalk, borderRadius: 12, padding: '14px 18px' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 10 }}>
              <div>
                <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14, color: T.brown }}>Groep verlaten</div>
                <div style={{ fontSize: 12, color: T.brownLight, fontFamily: "'Nunito', sans-serif", marginTop: 2 }}>Je biergeschiedenis blijft bewaard.</div>
              </div>
              {leaveConfirm ? (
                <div style={{ display: 'flex', gap: 8 }}>
                  <Button variant="ghost" size="sm" onClick={() => setLeaveConfirm(false)}>Annuleren</Button>
                  <Button variant="danger" size="sm" onClick={handleLeave}>Ja, verlaten</Button>
                </div>
              ) : (
                <Button variant="danger" size="sm" onClick={() => setLeaveConfirm(true)}>Verlaten</Button>
              )}
              </div>
            </div>
          )}

          {/* Groep verwijderen — alleen eigenaar */}
          {isOwner && (
            <div style={{ background: '#FFF0F3', borderRadius: 12, padding: '14px 18px', border: `1px solid rgba(232,62,90,0.20)` }}>
              <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14, color: T.brown, marginBottom: 4 }}>Groep verwijderen</div>
              <div style={{ fontSize: 12, color: T.brownLight, fontFamily: "'Nunito', sans-serif", marginBottom: 12, lineHeight: 1.5 }}>
                Dit verwijdert de groep <strong>permanent</strong>, inclusief alle bierloggen en activiteit van alle leden. Dit kan niet ongedaan worden gemaakt.
              </div>
              {deleteConfirm ? (
                <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
                  <span style={{ fontSize: 13, fontWeight: 700, color: T.berry, fontFamily: "'Nunito', sans-serif" }}>Weet je het zeker?</span>
                  <Button variant="ghost" size="sm" onClick={() => setDeleteConfirm(false)}>Annuleren</Button>
                  <Button variant="danger" size="sm" onClick={handleDelete}>Ja, definitief verwijderen</Button>
                </div>
              ) : (
                <Button variant="danger" size="sm" onClick={() => setDeleteConfirm(true)}>🗑️ Groep verwijderen</Button>
              )}
            </div>
          )}
        </div>
      </Card>
    </div>
  );
}

// ── User Profile Modal ───────────────────────────────────────────
function UserProfileModal({ userId, currentUserId, currentGroups = [], onClose }) {
  const [prof, setProf]             = useState(null);
  const [totalBeers, setTotalBeers] = useState(0);
  const [earnedAchs, setEarnedAchs] = useState([]);
  const [recentBeers, setRecentBeers] = useState([]);
  const [loading, setLoading]       = useState(true);
  const isMobile = useIsMobile();

  useEffect(() => { if (userId) fetchProfile(); }, [userId]);

  const fetchProfile = async () => {
    setLoading(true);
    const [{ data: p }, { count }, { data: ua }, { data: theirGroups }] = await Promise.all([
      db.from('profiles').select('*').eq('id', userId).single(),
      db.from('beer_logs').select('*', { count: 'exact', head: true }).eq('user_id', userId),
      db.from('user_achievements').select('achievements(icon, name, tier)').eq('user_id', userId),
      db.from('group_members').select('group_id').eq('user_id', userId),
    ]);
    setProf(p);
    setTotalBeers(count || 0);
    setEarnedAchs(ua || []);

    // Recent beers from shared groups only
    const myGroupIds   = new Set((currentGroups || []).map(g => g.id));
    const sharedGroupIds = (theirGroups || []).map(g => g.group_id).filter(id => myGroupIds.has(id));
    if (sharedGroupIds.length > 0) {
      const { data: beers } = await db.from('beer_logs')
        .select('*').eq('user_id', userId)
        .in('group_id', sharedGroupIds)
        .order('logged_at', { ascending: false }).limit(5);
      setRecentBeers(beers || []);
    }
    setLoading(false);
  };

  const tierColors = {
    gold:     { bg: T.amberLight, color: '#9A5F0C' },
    silver:   { bg: '#F5F5F5',    color: '#616161' },
    platinum: { bg: T.grapeBg,    color: '#3F2766' },
    bronze:   { bg: '#FFF3E0',    color: '#8B5000' },
    diamond:  { bg: '#E3F2FD',    color: '#0D47A1' },
  };

  return (
    <div
      style={{ position: 'fixed', inset: 0, background: 'rgba(61,43,31,0.62)', display: 'flex', alignItems: isMobile ? 'flex-end' : 'center', justifyContent: 'center', zIndex: 600, backdropFilter: 'blur(6px)', padding: isMobile ? 0 : 24 }}
      onClick={onClose}
    >
      <div
        onClick={e => e.stopPropagation()}
        style={{
          background: T.foam, borderRadius: isMobile ? '24px 24px 0 0' : 24,
          width: '100%', maxWidth: isMobile ? '100%' : 460,
          maxHeight: isMobile ? '88vh' : '84vh', overflowY: 'auto',
          boxShadow: '0 32px 80px rgba(0,0,0,0.32)',
          animation: 'modalPop 350ms cubic-bezier(0.34,1.56,0.64,1)',
        }}
      >
        {/* Close */}
        <div style={{ display: 'flex', justifyContent: 'flex-end', padding: '16px 18px 0' }}>
          <button onClick={onClose} style={{ background: T.chalk, border: 'none', borderRadius: '50%', width: 32, height: 32, cursor: 'pointer', fontSize: 14, display: 'flex', alignItems: 'center', justifyContent: 'center', color: T.brownMid, fontWeight: 700 }}>✕</button>
        </div>

        {loading ? (
          <div style={{ padding: '32px 24px 48px' }}><Loading /></div>
        ) : !prof ? (
          <div style={{ padding: '40px 24px', textAlign: 'center', color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>Profiel niet gevonden.</div>
        ) : (
          <div style={{ padding: '0 24px 36px' }}>

            {/* Profile header */}
            <div style={{ textAlign: 'center', paddingBottom: 22, borderBottom: `1px solid ${T.chalk}`, marginBottom: 22 }}>
              <Avatar name={prof.display_name} size={80} src={prof.avatar_url} />
              <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 28, fontWeight: 700, color: T.brown, marginTop: 12 }}>{prof.display_name}</div>
              {prof.bio && (
                <div style={{ fontSize: 13, color: T.brownMid, fontFamily: "'Nunito', sans-serif", marginTop: 6, lineHeight: 1.6, fontStyle: 'italic', maxWidth: 300, margin: '8px auto 0' }}>
                  "{prof.bio}"
                </div>
              )}
              <div style={{ fontSize: 12, color: T.brownLight, marginTop: 8, fontFamily: "'Nunito', sans-serif" }}>
                🍺 Lid sinds {new Date(prof.created_at).toLocaleDateString('nl-NL', { month: 'long', year: 'numeric' })}
              </div>
            </div>

            {/* Stats */}
            <div style={{ display: 'flex', gap: 10, marginBottom: 22 }}>
              <StatCard label="Totaal Drankjes" value={totalBeers} />
              <StatCard label="Badges" value={earnedAchs.length} amber />
            </div>

            {/* Earned achievements */}
            {earnedAchs.length > 0 && (
              <div style={{ marginBottom: 22 }}>
                <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 18, fontWeight: 700, color: T.brown, marginBottom: 12 }}>Badges</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                  {earnedAchs.map((ua, i) => {
                    if (!ua.achievements) return null;
                    const tc = tierColors[ua.achievements.tier] || tierColors.bronze;
                    return (
                      <div key={i} title={ua.achievements.name}
                        style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, background: tc.bg, borderRadius: 10, padding: '8px 10px', minWidth: 54, transition: 'transform 150ms ease', cursor: 'default' }}
                        onMouseEnter={e => e.currentTarget.style.transform = 'scale(1.10)'}
                        onMouseLeave={e => e.currentTarget.style.transform = 'scale(1)'}
                      >
                        <div style={{ fontSize: 26 }}>{ua.achievements.icon}</div>
                        <div style={{ fontSize: 9, fontWeight: 700, color: tc.color, fontFamily: "'Nunito', sans-serif", textAlign: 'center', lineHeight: 1.2 }}>{ua.achievements.name}</div>
                      </div>
                    );
                  })}
                </div>
              </div>
            )}

            {/* Recent drinks from shared groups */}
            {recentBeers.length > 0 && (
              <div>
                <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 18, fontWeight: 700, color: T.brown, marginBottom: 12 }}>Recente Drankjes</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                  {recentBeers.map((b) => (
                    <div key={b.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', background: T.chalk, borderRadius: 10 }}>
                      <div style={{ fontSize: 20, flexShrink: 0 }}>{({ beer: '🍺', shot: '🥃', wine: '🍷', mix: '🍹' })[b.drink_category] || '🍺'}</div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 13, color: T.brown, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{b.beer_name || b.beer_type || 'Drankje'}</div>
                        {b.location && <div style={{ fontSize: 11, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>📍 {b.location}</div>}
                      </div>
                      <div style={{ textAlign: 'right', flexShrink: 0 }}>
                        {b.rating > 0 && <StarRating value={b.rating} readonly size={12} />}
                        <div style={{ fontSize: 10, color: '#B89880', fontFamily: "'Nunito', sans-serif", marginTop: 2 }}>{timeAgo(b.logged_at)}</div>
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            )}

            {/* No shared groups message */}
            {recentBeers.length === 0 && earnedAchs.length === 0 && (
              <div style={{ textAlign: 'center', padding: '20px 0', fontSize: 13, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>
                Zit in dezelfde groep om recente drankjes te zien 🥂
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ── Groups Screen ────────────────────────────────────────────────
function GroupsScreen({ userId, profile, groups, activeGroup, onSwitchGroup, onGroupAdded, onGroupRemoved, onGroupUpdated }) {
  const [view, setView]                 = useState('list'); // 'list' | 'settings'
  const [settingsGroup, setSettingsGroup] = useState(null);
  const [feedback, setFeedback]         = useState(null);

  // Create group form
  const [showCreate, setShowCreate]     = useState(false);
  const [newName, setNewName]           = useState('');
  const [newEmoji, setNewEmoji]         = useState('🍺');
  const [creating, setCreating]         = useState(false);

  // Join group form
  const [showJoin, setShowJoin]         = useState(false);
  const [joinCode, setJoinCode]         = useState('');
  const [joining, setJoining]           = useState(false);

  const isMobile = useIsMobile();
  const EMOJIS = ['🍺','🏆','🔥','🎉','👑','⚡','🌍','🤘','🍻','🎸'];

  const showFeedback = (type, msg) => {
    setFeedback({ type, msg });
    setTimeout(() => setFeedback(null), 3500);
  };

  const handleCreate = async () => {
    if (!newName.trim()) return;
    setCreating(true);

    // Generate groupId client-side so we don't need .select() after INSERT.
    // RLS blocks SELECT until the user is a member, so we add membership first,
    // then fetch the group row afterwards.
    const groupId   = crypto.randomUUID();
    let   invCode   = generateInviteCode();

    const { error: insErr } = await db.from('groups').insert({
      id: groupId, name: newName.trim(), emoji: newEmoji,
      created_by: userId, invite_code: invCode,
    });

    if (insErr && insErr.code === '23505') {
      // Invite-code collision — retry with a fresh code
      invCode = generateInviteCode();
      const { error: retryErr } = await db.from('groups').insert({
        id: groupId, name: newName.trim(), emoji: newEmoji,
        created_by: userId, invite_code: invCode,
      });
      if (retryErr) { showFeedback('err', 'Aanmaken mislukt. Probeer opnieuw.'); setCreating(false); return; }
    } else if (insErr) {
      showFeedback('err', 'Aanmaken mislukt. Probeer opnieuw.');
      setCreating(false); return;
    }

    // Add creator as owner — after this the SELECT policy kicks in
    const { error: memberErr } = await db.from('group_members').insert({
      group_id: groupId, user_id: userId, role: 'owner',
    });
    if (memberErr) { showFeedback('err', 'Aanmaken mislukt. Probeer opnieuw.'); setCreating(false); return; }

    // Now we're a member, we can SELECT the group
    const { data: newGroup } = await db.from('groups').select('*').eq('id', groupId).single();
    onGroupAdded({ ...(newGroup || { id: groupId, name: newName.trim(), emoji: newEmoji, invite_code: invCode, created_by: userId }), myRole: 'owner' });
    setNewName(''); setNewEmoji('🍺'); setShowCreate(false);
    showFeedback('ok', `${newEmoji} ${newName.trim()} aangemaakt!`);
    setCreating(false);
  };

  const handleJoin = async () => {
    if (!joinCode.trim()) return;
    setJoining(true);

    // RLS blocks direct SELECT by invite_code — use the SECURITY DEFINER RPC
    // (same pattern as OnboardingScreen)
    const { data, error: rpcErr } = await db.rpc('join_group_by_invite_code', {
      p_invite_code: joinCode.trim().toUpperCase(),
    });

    if (rpcErr || !data || !data.success) {
      const msg = data && data.error === 'not_found'
        ? 'Groep niet gevonden. Controleer de code.'
        : data && data.error === 'already_member'
          ? 'Je bent al lid van deze groep!'
          : 'Joinen mislukt. Probeer opnieuw.';
      showFeedback('err', msg);
      setJoining(false); return;
    }

    const grp = data.group;
    if (groups.find(g => g.id === grp.id)) {
      showFeedback('err', 'Je bent al lid van deze groep!');
      setJoining(false); return;
    }

    onGroupAdded({ ...grp, myRole: 'member' });
    setJoinCode(''); setShowJoin(false);
    showFeedback('ok', `Je bent lid geworden van ${grp.emoji} ${grp.name}!`);
    setJoining(false);
  };

  // ── Sub-view: Group settings ─────────────────────────────────
  if (view === 'settings' && settingsGroup) {
    return (
      <GroupSettingsScreen
        profile={profile}
        group={settingsGroup}
        userId={userId}
        isOwner={settingsGroup.created_by === userId}
        onBack={() => { setView('list'); setSettingsGroup(null); }}
        onGroupUpdated={(updated) => {
          onGroupUpdated(updated);
          setSettingsGroup(prev => ({ ...prev, ...updated }));
        }}
        onGroupLeft={() => {
          onGroupRemoved(settingsGroup.id);
          setView('list'); setSettingsGroup(null);
        }}
        onGroupDeleted={() => {
          onGroupRemoved(settingsGroup.id);
          setView('list'); setSettingsGroup(null);
        }}
      />
    );
  }

  // ── Main list view ───────────────────────────────────────────
  return (
    <div style={{ padding: isMobile ? '16px 14px' : '28px 32px', maxWidth: 760, margin: '0 auto' }}>
      {/* Header */}
      <div style={{ marginBottom: 20 }}>
        <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: isMobile ? 26 : 32, fontWeight: 700, color: T.brown, marginBottom: 6 }}>
          Groepen
        </div>
        <div style={{ fontSize: 15, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>
          Jij bent lid van {groups.length} groep{groups.length !== 1 ? 'en' : ''}
        </div>
      </div>

      {/* Feedback banner */}
      {feedback && (
        <div style={{
          padding: '12px 16px', borderRadius: 10, marginBottom: 20,
          background: feedback.type === 'ok' ? T.leafBg : T.berryBg,
          border: `1.5px solid ${feedback.type === 'ok' ? T.leaf : T.berry}`,
          color: feedback.type === 'ok' ? '#2E7D32' : T.berry,
          fontFamily: "'Nunito', sans-serif", fontWeight: 700, fontSize: 14,
        }}>
          {feedback.type === 'ok' ? '✅ ' : '❌ '}{feedback.msg}
        </div>
      )}

      {/* Group list */}
      {groups.length === 0 ? (
        <Card style={{ padding: '40px 24px', textAlign: 'center', marginBottom: 20 }}>
          <div style={{ fontSize: 48, marginBottom: 12 }}>🍺</div>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 22, color: T.brownMid, marginBottom: 8 }}>Geen groepen</div>
          <div style={{ fontSize: 14, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>Maak een groep aan of join er één met een uitnodigingscode.</div>
        </Card>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 24 }}>
          {groups.map(g => {
            const isActive = activeGroup?.id === g.id;
            const isOwner  = g.created_by === userId;
            return (
              <Card key={g.id} style={{ padding: '18px 20px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: isMobile ? 10 : 14, flexWrap: 'wrap' }}>
                  <div style={{ fontSize: 36, width: 48, textAlign: 'center', flexShrink: 0 }}>{g.emoji}</div>
                  <div style={{ flex: 1, minWidth: 120 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 4 }}>
                      <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 20, fontWeight: 700, color: T.brown }}>{g.name}</div>
                      {isActive && <Badge variant="amber" size="sm">✓ Actief</Badge>}
                      {isOwner && <Badge variant="dark" size="sm">👑 Eigenaar</Badge>}
                    </div>
                    <div style={{ fontSize: 12, color: T.brownLight, fontFamily: "'Nunito', sans-serif" }}>
                      {isOwner ? 'Jij bent eigenaar' : 'Jij bent lid'} · Klik ⚙️ voor instellingen
                    </div>
                  </div>
                  <div style={{ display: 'flex', gap: 8, flexShrink: 0, alignItems: 'center' }}>
                    {!isActive && (
                      <Button variant="primary" size="sm" onClick={() => onSwitchGroup(g)}>
                        Schakel →
                      </Button>
                    )}
                    <Button variant="secondary" size="sm" onClick={() => { setSettingsGroup(g); setView('settings'); }}>
                      ⚙️
                    </Button>
                  </div>
                </div>
              </Card>
            );
          })}
        </div>
      )}

      {/* Create / Join cards */}
      <div style={{ display: 'grid', gridTemplateColumns: isMobile ? '1fr' : '1fr 1fr', gap: 16 }}>
        {/* Create */}
        <Card style={{ padding: '22px' }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 19, fontWeight: 700, color: T.brown, marginBottom: 12 }}>
            ➕ Groep aanmaken
          </div>
          {!showCreate ? (
            <Button variant="primary" size="md" onClick={() => { setShowCreate(true); setShowJoin(false); }} fullWidth>
              Nieuwe groep
            </Button>
          ) : (
            <>
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: T.brownLight, marginBottom: 8, fontFamily: "'Nunito', sans-serif" }}>Emoji</div>
                <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  {EMOJIS.map(e => (
                    <button key={e} onClick={() => setNewEmoji(e)} style={{
                      width: 38, height: 38, fontSize: 18,
                      background: newEmoji === e ? T.amberLight : T.chalk,
                      border: `2px solid ${newEmoji === e ? T.amber : T.brownBorder}`,
                      borderRadius: 10, cursor: 'pointer', transition: 'all 140ms ease',
                    }}>{e}</button>
                  ))}
                </div>
              </div>
              <Input label="Groepsnaam" placeholder="bijv. Dublin Crew" value={newName} onChange={setNewName} icon={newEmoji} />
              <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
                <Button variant="ghost" size="sm" onClick={() => { setShowCreate(false); setNewName(''); }} style={{ flex: 1 }}>Annuleren</Button>
                <Button variant="primary" size="sm" onClick={handleCreate} disabled={creating || !newName.trim()} style={{ flex: 2 }}>
                  {creating ? '⏳ Aanmaken...' : '✅ Aanmaken'}
                </Button>
              </div>
            </>
          )}
        </Card>

        {/* Join */}
        <Card style={{ padding: '22px' }}>
          <div style={{ fontFamily: "'Fredoka', sans-serif", fontSize: 19, fontWeight: 700, color: T.brown, marginBottom: 12 }}>
            🔑 Groep joinen
          </div>
          {!showJoin ? (
            <Button variant="secondary" size="md" onClick={() => { setShowJoin(true); setShowCreate(false); }} fullWidth>
              Code invoeren
            </Button>
          ) : (
            <>
              <Input label="Uitnodigingscode" placeholder="BRTJE-XXXX" value={joinCode} onChange={setJoinCode} icon="🔑" />
              <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
                <Button variant="ghost" size="sm" onClick={() => { setShowJoin(false); setJoinCode(''); }} style={{ flex: 1 }}>Annuleren</Button>
                <Button variant="primary" size="sm" onClick={handleJoin} disabled={joining || !joinCode.trim()} style={{ flex: 2 }}>
                  {joining ? '⏳ Joinen...' : '🍺 Joinen'}
                </Button>
              </div>
            </>
          )}
        </Card>
      </div>
    </div>
  );
}

Object.assign(window, { DashboardScreen, FeedScreen, AchievementsScreen, ProfileScreen, LogBeerModal, GroupSettingsScreen, GroupsScreen, UserProfileModal });
