<script setup lang="ts">
import { usePage } from '@inertiajs/vue3';
import { ref, onMounted, onBeforeUnmount, nextTick, watch, computed } from 'vue';
import { csrfFetch } from '@/utils/csrfFetch';
import {
    Flag, X, AlertCircle, UserX, ShieldAlert, BadgeDollarSign, HelpCircle,
    MessageSquareOff, CheckCircle2, Loader2, ChevronRight, Smile, ImagePlay,
    Reply, Trash2
} from 'lucide-vue-next';
import { Picker } from 'emoji-mart';
import data from '@emoji-mart/data';

const GIPHY_KEY = 'GF7y5viqpCeUeJdzoj5U9PY5XkFpswmC';

// v-model:open support
const props = defineProps<{ open: boolean }>();
const emit = defineEmits<{
    (e: 'update:open', v: boolean): void;
    (e: 'update:unread', n: number): void;
}>();

// ── Popup mode (persisted in localStorage) ───────────────────
const chatMode = ref<'drawer' | 'popup'>(
    (localStorage.getItem('chatMode') as 'drawer' | 'popup') || 'drawer'
);
function toggleChatMode() {
    chatMode.value = chatMode.value === 'drawer' ? 'popup' : 'drawer';
    localStorage.setItem('chatMode', chatMode.value);
}

// ── Drag for popup mode ───────────────────────────────────────
const popupPos = ref({ right: 20, bottom: 80 });
let dragging = false;
let dragStart = { x: 0, y: 0, right: 0, bottom: 0 };

function onPopupDragStart(e: MouseEvent) {
    if (chatMode.value !== 'popup') return;
    dragging = true;
    dragStart = { x: e.clientX, y: e.clientY, right: popupPos.value.right, bottom: popupPos.value.bottom };
    window.addEventListener('mousemove', onPopupDragMove);
    window.addEventListener('mouseup', onPopupDragEnd);
}
function onPopupDragMove(e: MouseEvent) {
    if (!dragging) return;
    const dx = dragStart.x - e.clientX;
    const dy = dragStart.y - e.clientY;
    popupPos.value = {
        right:  Math.max(0, Math.min(window.innerWidth  - 380, dragStart.right  + dx)),
        bottom: Math.max(0, Math.min(window.innerHeight - 60,  dragStart.bottom + dy)),
    };
}
function onPopupDragEnd() {
    dragging = false;
    window.removeEventListener('mousemove', onPopupDragMove);
    window.removeEventListener('mouseup', onPopupDragEnd);
}

// ── Unread badge (persisted) ──────────────────────────────────
const UNREAD_KEY = 'chatUnread';
const unreadCount = ref<number>(parseInt(localStorage.getItem(UNREAD_KEY) || '0', 10) || 0);
function resetUnread() {
    unreadCount.value = 0;
    localStorage.setItem(UNREAD_KEY, '0');
    emit('update:unread', 0);
}

const page = usePage();
const me = computed(() => (page.props.auth as any)?.user || null);
const isAdmin = computed(() => {
    const role = me.value?.role?.toLowerCase();
    return role === 'admin' || role === 'moderator' || role === 'mod';
});

function openProfile(user: any) {
    if (!user?.username) return;
    window.open(`/profile/${user.username}`, '_blank');
}

async function deleteMessage(msg: any) {
    if (!isAdmin.value) return;
    try {
        const csrf = (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content || '';
        const res = await fetch(`/api/chat/${msg.id}`, {
            method: 'DELETE',
            headers: { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': csrf },
        });
        if (res.ok) {
            const j = await res.json();
            if (j?.data) mergeMessageUpdate(j.data);
        }
    } catch { /* silent */ }
}

// Active chat ban detection (frontend gate)
const chatBan = computed<any | null>(() => {
    // Depend on nowTs so this recomputes every second when open
    void nowTs.value;
    const u: any = me.value;
    if (!u || !Array.isArray(u.restrictions)) return null;
    const now = Date.now();
    const found = u.restrictions.find((r: any) => {
        if (!r || r.type !== 'chat_ban') return false;
        const startsOk = !r.starts_at || new Date(r.starts_at).getTime() <= now;
        const endsOk = !r.ends_at || new Date(r.ends_at).getTime() > now;
        return (!!r.active || r.active === undefined) && startsOk && endsOk;
    });
    return found || null;
});
const chatBanned = computed<boolean>(() => !!chatBan.value);

const isOpen = computed({
    get: () => props.open,
    set: (v: boolean) => emit('update:open', v),
});

const messages = ref<any[]>([]);
const input = ref('');
const loading = ref(false);
const sending = ref(false);
const lastId = ref<number | null>(null);
let pollTimer: number | undefined;
let pollFailCount = 0;
const POLL_BASE_MS = 5_000;
const POLL_MAX_MS  = 60_000;
// Countdown ticker for bans
const nowTs = ref<number>(Date.now());
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let nowTimer: number | undefined;

function startNowTicker() {
    stopNowTicker();
    nowTimer = window.setInterval(() => { nowTs.value = Date.now(); }, 1000);
}
function stopNowTicker() {
    if (nowTimer) window.clearInterval(nowTimer);
    nowTimer = undefined;
}

// Countdown helpers for chat ban
const banEndsAt = computed<Date | null>(() => {
    const e = (chatBan.value as any)?.ends_at;
    if (!e) return null;
    const d = new Date(e);
    return isNaN(d.getTime()) ? null : d;
});

const remainingMs = computed<number>(() => {
    if (!banEndsAt.value) return 0;
    return Math.max(0, banEndsAt.value.getTime() - nowTs.value);
});

function formatCountdown(ms: number): string {
    const totalSec = Math.floor(ms / 1000);
    const days = Math.floor(totalSec / 86400);
    const hours = Math.floor((totalSec % 86400) / 3600);
    const minutes = Math.floor((totalSec % 3600) / 60);
    const seconds = totalSec % 60;
    const pad = (n: number) => n.toString().padStart(2, '0');
    if (days > 0) return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
    return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
}

const countdownText = computed<string | null>(() => {
    if (!banEndsAt.value || remainingMs.value <= 0) return null;
    return formatCountdown(remainingMs.value);
});

const exactEndText = computed<string | null>(() => {
    if (!banEndsAt.value) return null;
    try {
        return banEndsAt.value.toLocaleString();
    } catch {
        return banEndsAt.value.toISOString();
    }
});

const emojiOpen        = ref(false);
const emojiPickerEl    = ref<HTMLElement | null>(null);
let   pickerInstance: any = null;

const giphyOpen    = ref(false);
const giphyQuery   = ref('');
const giphyResults = ref<any[]>([]);
const giphyLoading = ref(false);
let   giphyTimer: ReturnType<typeof setTimeout> | null = null;

function toggleEmoji() {
    giphyOpen.value = false;
    emojiOpen.value = !emojiOpen.value;
}
function toggleGiphy() {
    emojiOpen.value = false;
    giphyOpen.value = !giphyOpen.value;
    if (giphyOpen.value && !giphyResults.value.length) searchGiphy('casino');
}
function closeToolPanels() {
    emojiOpen.value = false;
    giphyOpen.value = false;
}

async function searchGiphy(q?: string) {
    const query = q ?? giphyQuery.value;
    if (!query.trim()) return;
    if (giphyTimer) clearTimeout(giphyTimer);
    giphyTimer = setTimeout(async () => {
        giphyLoading.value = true;
        try {
            const res = await fetch(
                `https://api.giphy.com/v1/gifs/search?api_key=${GIPHY_KEY}&q=${encodeURIComponent(query)}&limit=18&rating=pg-13`
            );
            const j = await res.json();
            giphyResults.value = j.data ?? [];
        } catch { /* silent */ } finally {
            giphyLoading.value = false;
        }
    }, 400);
}

function onGiphyInput() {
    searchGiphy(giphyQuery.value);
}

async function sendGif(url: string) {
    if (sending.value || chatBanned.value) return;
    giphyOpen.value = false;
    sending.value = true;
    try {
        const res = await csrfFetch('/api/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ message: `[GIF:${url}]` }),
        });
        if (!res.ok) return;
        const j = await res.json();
        if (j?.data) {
            messages.value.push(j.data);
            lastId.value = j.data.id;
            await nextTick();
            scrollToBottom();
        }
    } catch { /* silent */ } finally {
        sending.value = false;
    }
}

function isGif(msg: string) {
    return typeof msg === 'string' && msg.startsWith('[GIF:') && msg.endsWith(']');
}
function gifUrl(msg: string) {
    return msg.slice(5, -1);
}

// Reduced list for quick bar to prevent overflow on mobile
const reactionEmojis = ['👍','😂','🔥','😍','🎉','💎'];

// Reply state
const replyTo = ref<any>(null);

// Report modal state
const reportModal = ref<{ msg: any } | null>(null);
const reportReason = ref('');
const reportSubmitting = ref(false);
const reportDone = ref(false);

const reportReasons = [
    { value: 'spam',       label: 'Spam',            desc: 'Unerwünschte Werbung oder Wiederholungen',   icon: MessageSquareOff, color: '#f59e0b' },
    { value: 'harassment', label: 'Belästigung',      desc: 'Belästigendes oder feindseliges Verhalten',  icon: UserX,            color: '#ef4444' },
    { value: 'offensive',  label: 'Beleidigung',      desc: 'Beleidigende oder diskriminierende Inhalte', icon: ShieldAlert,       color: '#f97316' },
    { value: 'scam',       label: 'Betrug / Scam',    desc: 'Betrügerische Links oder Forderungen',       icon: BadgeDollarSign,   color: '#a855f7' },
    { value: 'other',      label: 'Sonstiges',        desc: 'Anderer Verstoß gegen die Nutzungsregeln',   icon: HelpCircle,        color: '#6b7280' },
];

function openReportModal(msg: any) {
    reportModal.value = { msg };
    reportReason.value = '';
    reportDone.value = false;
}

function closeReportModal() {
    reportModal.value = null;
}

async function submitReport() {
    if (!reportReason.value || reportSubmitting.value) return;
    const msg = reportModal.value?.msg;
    if (!msg) return;

    const msgIndex = messages.value.findIndex((m: any) => m.id === msg.id);
    const contextStart = Math.max(0, msgIndex - 10);
    const contextMessages = messages.value.slice(contextStart, msgIndex).map((m: any) => ({
        id: m.id,
        message: m.message,
        user: { id: m.user?.id, username: m.user?.username },
        created_at: m.created_at,
    }));

    reportSubmitting.value = true;
    try {
        const csrf = (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content || '';
        const res = await fetch(`/api/chat/${msg.id}/report`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-CSRF-TOKEN': csrf,
            },
            body: JSON.stringify({
                message_text: msg.message,
                sender_id: msg.user?.id ?? null,
                sender_username: msg.user?.username ?? null,
                context_messages: contextMessages,
                reason: reportReason.value,
            }),
        });
        if (res.ok) {
            reportDone.value = true;
            setTimeout(closeReportModal, 1800);
        }
    } catch {
        // silent
    } finally {
        reportSubmitting.value = false;
    }
}

function mergeMessageUpdate(updated: any) {
    const idx = messages.value.findIndex(x => x.id === updated.id);
    if (idx >= 0) {
        // shallow merge to keep reactivity
        messages.value[idx] = { ...messages.value[idx], ...updated };
    } else {
        messages.value.push(updated);
    }
}

async function fetchInitial() {
    loading.value = true;
    try {
        const res = await fetch('/api/chat?limit=50', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (!res.ok) throw new Error('Failed to load chat');
        const data = await res.json();
        messages.value = data.data || [];
        lastId.value = data.last_id ?? (messages.value.length ? messages.value[messages.value.length - 1].id : null);
        await nextTick();
        if ((window as any).lucide) (window as any).lucide.createIcons();
        scrollToBottom();
    } finally {
        loading.value = false;
    }
}

async function fetchAfter() {
    if (lastId.value == null) return;
    try {
        const res = await fetch(`/api/chat?after_id=${lastId.value}&limit=100`, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (!res.ok) {
            pollFailCount++;
            return;
        }
        pollFailCount = 0;
        const data = await res.json();
        const batch = data.data || [];
        if (batch.length) {
            const newCount = batch.filter((m: any) => m.user_id !== me.value?.id).length;
            for (const msg of batch) {
                mergeMessageUpdate(msg);
            }
            lastId.value = data.last_id ?? lastId.value;
            if (!isOpen.value && chatMode.value === 'drawer' && newCount > 0) {
                unreadCount.value = Math.min(99, unreadCount.value + newCount);
                localStorage.setItem(UNREAD_KEY, String(unreadCount.value));
                emit('update:unread', unreadCount.value);
            }
            await nextTick();
            if ((window as any).lucide) (window as any).lucide.createIcons();
            scrollToBottomIfNearEnd();
        }
    } catch {
        pollFailCount++;
    }
}

function scheduleNextPoll() {
    stopPolling();
    // Exponential backoff: 5s → 10s → 20s → … → max 60s
    const delay = Math.min(POLL_BASE_MS * Math.pow(2, pollFailCount), POLL_MAX_MS);
    pollTimer = window.setTimeout(async () => {
        await fetchAfter();
        if (pollTimer !== undefined) scheduleNextPoll();
    }, delay);
}

function startPolling() {
    pollFailCount = 0;
    scheduleNextPoll();
}

function stopPolling() {
    if (pollTimer) window.clearTimeout(pollTimer);
    pollTimer = undefined;
}

function onKeydown(e: KeyboardEvent) {
    if (e.key === 'Escape') {
        isOpen.value = false;
    }
}

function getListEl() {
    return document.getElementById(chatMode.value === 'popup' ? 'gc-list-popup' : 'gc-list');
}

function scrollToBottom() {
    const el = getListEl();
    if (el) el.scrollTop = el.scrollHeight;
}

function scrollToBottomIfNearEnd() {
    const el = getListEl();
    if (!el) return;
    const nearEnd = el.scrollHeight - el.scrollTop - el.clientHeight < 200;
    if (nearEnd) scrollToBottom();
}

async function send() {
    if (chatBanned.value) return;
    const text = input.value.trim();
    if (!text || sending.value) return;
    sending.value = true;
    try {
        const payload: any = { message: text };
        if (replyTo.value) {
            payload.reply_to_id = replyTo.value.id;
        }

        const res = await csrfFetch('/api/chat', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(payload),
        });
        if (!res.ok) {
            const j = await res.json().catch(() => ({}));
            throw new Error(j.message || 'Failed to send');
        }
        const j = await res.json();
        if (j?.data) {
            messages.value.push(j.data);
            lastId.value = j.data.id;
            input.value = '';
            replyTo.value = null; // Clear reply
            await nextTick();
            if ((window as any).lucide) (window as any).lucide.createIcons();
            scrollToBottom();
        }
    } catch (e) {
        console.warn(e);
    } finally {
        sending.value = false;
    }
}

function insertEmoji(em: string) {
    const el = document.getElementById('gc-input') as HTMLTextAreaElement | null;
    const at = el?.selectionStart ?? input.value.length;
    input.value = input.value.slice(0, at) + em + input.value.slice(at);
    nextTick(() => {
        if (el) {
            el.focus();
            const pos = at + em.length;
            el.setSelectionRange(pos, pos);
        }
    });
}

async function toggleReaction(msg: any, emoji: string) {
    // Optimistic update
    const orig = JSON.parse(JSON.stringify(msg.reactions_agg || []));
    const arr = Array.isArray(msg.reactions_agg) ? [...msg.reactions_agg] : [];
    const idx = arr.findIndex((r: any) => r.emoji === emoji);
    if (idx === -1) {
        arr.push({ emoji, count: 1, reactedByMe: true });
    } else {
        const r = { ...arr[idx] };
        if (r.reactedByMe) {
            r.count -= 1;
            r.reactedByMe = false;
            if (r.count <= 0) { arr.splice(idx, 1); }
            else { arr[idx] = r; }
        } else {
            r.count += 1;
            r.reactedByMe = true;
            arr[idx] = r;
        }
    }
    mergeMessageUpdate({ ...msg, reactions_agg: arr });

    try {
        const res = await csrfFetch(`/api/chat/${msg.id}/react`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ emoji }),
        });
        if (!res.ok) throw new Error('Failed');
        const j = await res.json();
        if (j?.data) mergeMessageUpdate(j.data);
    } catch {
        // Revert optimistic on error
        mergeMessageUpdate({ ...msg, reactions_agg: orig });
    }
}

function scrollToMessage(id?: number) {
    if (!id) return;
    const el = document.getElementById(`msg-${id}`);
    if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'center' });
        el.classList.add('flash');
        setTimeout(() => el.classList.remove('flash'), 1200);
    }
}

function setReply(msg: any) {
    replyTo.value = msg;
    nextTick(() => {
        const el = document.getElementById('gc-input');
        if (el) el.focus();
    });
}

function reportMessage(msg: any) {
    openReportModal(msg);
}

// Date separator helper
function showDateSeparator(index: number) {
    if (index === 0) return true;
    const curr = new Date(messages.value[index].created_at);
    const prev = new Date(messages.value[index - 1].created_at);
    return curr.toDateString() !== prev.toDateString();
}

function formatDate(dateStr: string) {
    return new Date(dateStr).toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
}

watch(emojiOpen, async (open) => {
    if (open) {
        await nextTick();
        if (emojiPickerEl.value) {
            // Re-create if mounted in a different element (e.g. mode switched)
            if (pickerInstance && !emojiPickerEl.value.children.length) {
                pickerInstance = null;
            }
            if (!pickerInstance) {
                pickerInstance = new Picker({
                    data,
                    theme: 'dark',
                    locale: 'de',
                    onEmojiSelect: (em: any) => {
                        insertEmoji(em.native);
                        emojiOpen.value = false;
                    },
                    parent: emojiPickerEl.value,
                    previewPosition: 'none',
                    skinTonePosition: 'none',
                });
            }
        }
    }
});

watch(isOpen, async (open) => {
    if (open) {
        resetUnread();
        // Prevent body scroll when chat is open on mobile (drawer only)
        if (chatMode.value === 'drawer') document.body.style.overflow = 'hidden';
        startNowTicker();

        // If user is chat-banned, do not fetch; just show ban panel
        if (chatBanned.value) {
            document.addEventListener('keydown', onKeydown);
            return;
        }

        await nextTick();
        if (messages.value.length === 0) await fetchInitial();
        else scrollToBottom();
        document.addEventListener('keydown', onKeydown);
    } else {
        if (chatMode.value === 'drawer') document.body.style.overflow = '';
        stopNowTicker();
        closeToolPanels();
        document.removeEventListener('keydown', onKeydown);
        // Keep polling running so the unread badge updates while chat is closed
    }
});

onMounted(async () => {
    if ((window as any).lucide) (window as any).lucide.createIcons();
    // Restore persisted unread count to parent
    if (unreadCount.value > 0) emit('update:unread', unreadCount.value);
    // Fetch lastId on mount so polling can detect new messages even before chat opens
    try {
        const res = await fetch('/api/chat?limit=1', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (res.ok) {
            const d = await res.json();
            const items: any[] = d.data || [];
            if (items.length) lastId.value = d.last_id ?? items[items.length - 1].id;
        }
    } catch {}
    startPolling();
});

onBeforeUnmount(() => {
    stopPolling();
    stopNowTicker();
    document.removeEventListener('keydown', onKeydown);
    document.body.style.overflow = '';
});
</script>

<template>
    <!-- Report Modal -->
    <teleport to="body">
        <transition name="modal-fade">
            <div v-if="reportModal" class="gc-report-overlay" @click.self="closeReportModal">
                <div class="gc-report-modal" role="dialog" aria-modal="true" aria-labelledby="rm-title">

                    <!-- ── Success ── -->
                    <div v-if="reportDone" class="report-success">
                        <div class="success-ring">
                            <CheckCircle2 :size="36" />
                        </div>
                        <h3>Erfolgreich gemeldet</h3>
                        <p>Danke für deinen Hinweis.<br>Unser Moderationsteam wird den Fall prüfen.</p>
                    </div>

                    <template v-else>
                        <!-- ── Header ── -->
                        <div class="rm-head">
                            <div class="rm-head-left">
                                <div class="rm-head-icon">
                                    <Flag :size="16" />
                                </div>
                                <span id="rm-title" class="rm-title">Nachricht melden</span>
                            </div>
                            <button class="rm-close" @click="closeReportModal" aria-label="Schließen">
                                <X :size="15" />
                            </button>
                        </div>

                        <!-- ── User card ── -->
                        <div class="rm-user">
                            <div class="rm-avatar-wrap">
                                <div class="rm-avatar">
                                    <img v-if="reportModal.msg.user?.avatar_url" :src="reportModal.msg.user.avatar_url" :alt="reportModal.msg.user?.username" />
                                    <div v-else class="rm-avatar-fallback">{{ (reportModal.msg.user?.username || '?')[0].toUpperCase() }}</div>
                                </div>
                                <div class="rm-avatar-glow"></div>
                            </div>
                            <div class="rm-user-info">
                                <span class="rm-username">@{{ reportModal.msg.user?.username || 'Unbekannt' }}</span>
                                <div class="rm-badges">
                                    <span v-if="reportModal.msg.user?.role === 'admin'" class="rm-badge admin">ADMIN</span>
                                    <span v-else-if="reportModal.msg.user?.role === 'staff'" class="rm-badge staff">STAFF</span>
                                    <span v-else-if="reportModal.msg.user?.role === 'mod'" class="rm-badge mod">MOD</span>
                                    <span v-else-if="reportModal.msg.user?.role === 'streamer'" class="rm-badge streamer">STREAMER</span>
                                    <span v-else class="rm-badge user">USER</span>
                                    <span v-if="reportModal.msg.user?.vip_level && reportModal.msg.user.vip_level > 0" class="rm-badge vip">
                                        ★ VIP {{ reportModal.msg.user.vip_level }}
                                    </span>
                                    <span v-if="reportModal.msg.user?.clan_tag" class="rm-badge clan">[{{ reportModal.msg.user.clan_tag }}]</span>
                                </div>
                            </div>
                        </div>

                        <!-- ── Reported message ── -->
                        <div class="rm-section">
                            <div class="rm-section-label">
                                <AlertCircle :size="12" />
                                Gemeldete Nachricht
                            </div>
                            <div class="rm-message-bubble">
                                <div class="rm-quote-mark">"</div>
                                <p class="rm-message-text">{{ reportModal.msg.message }}</p>
                            </div>
                        </div>

                        <!-- ── Reason grid ── -->
                        <div class="rm-section">
                            <div class="rm-section-label">
                                <Flag :size="12" />
                                Meldegrund auswählen
                            </div>
                            <div class="rm-reasons">
                                <button
                                    v-for="r in reportReasons"
                                    :key="r.value"
                                    class="rm-reason-btn"
                                    :class="{ selected: reportReason === r.value }"
                                    :style="reportReason === r.value ? `--reason-color: ${r.color}` : ''"
                                    @click="reportReason = r.value"
                                >
                                    <div class="reason-icon-wrap" :style="`color: ${r.color}`">
                                        <component :is="r.icon" :size="18" />
                                    </div>
                                    <div class="reason-text">
                                        <span class="reason-label">{{ r.label }}</span>
                                        <span class="reason-desc">{{ r.desc }}</span>
                                    </div>
                                    <div class="reason-check-wrap" v-if="reportReason === r.value">
                                        <CheckCircle2 :size="16" />
                                    </div>
                                    <ChevronRight v-else :size="14" class="reason-chevron" />
                                </button>
                            </div>
                        </div>

                        <!-- ── Actions ── -->
                        <div class="rm-actions">
                            <button class="rm-btn-cancel" @click="closeReportModal">
                                <X :size="14" />
                                Abbrechen
                            </button>
                            <button
                                class="rm-btn-submit"
                                :disabled="!reportReason || reportSubmitting"
                                @click="submitReport"
                            >
                                <Loader2 v-if="reportSubmitting" :size="15" class="rm-spin" />
                                <Flag v-else :size="15" />
                                {{ reportSubmitting ? 'Wird gesendet…' : 'Jetzt melden' }}
                            </button>
                        </div>
                    </template>
                </div>
            </div>
        </transition>
    </teleport>

    <!-- Popup mode -->
    <transition name="pop-up">
        <div
            v-show="isOpen && chatMode === 'popup'"
            class="gc-popup"
            :style="{ right: popupPos.right + 'px', bottom: popupPos.bottom + 'px' }"
        >
            <header class="gc-head" @mousedown="onPopupDragStart" style="cursor:grab">
                <div class="head-left">
                    <div class="online-dot"></div>
                    <span class="head-title">Global Chat</span>
                </div>
                <div style="display:flex;gap:4px;align-items:center">
                    <button class="mode-btn" title="Drawer-Modus" @click.stop="toggleChatMode">
                        <i data-lucide="panel-right"></i>
                    </button>
                    <button class="close-btn" title="Schließen" @click.stop="isOpen = false">
                        <i data-lucide="x"></i>
                    </button>
                </div>
            </header>
            <!-- reuse same body via slot trick — just include it inline -->
            <div v-if="chatBanned" class="gc-banned">
                <div class="ban-card">
                    <div class="ban-stamp">BANNED</div>
                    <h2 class="ban-title">Chat Suspended</h2>
                    <p class="ban-reason" v-if="chatBan?.reason">Reason: {{ chatBan.reason }}</p>
                    <p class="ban-sub" v-if="chatBan?.ends_at">Until: {{ new Date(chatBan.ends_at).toLocaleString() }}</p>
                </div>
            </div>
            <div v-else id="gc-list-popup" class="gc-list" style="flex:1;overflow-y:auto">
                <div v-if="loading" class="loading-state"><div class="spinner"></div><span>Verbinde...</span></div>
                <template v-else>
                    <div v-if="!messages.length" class="empty-state"><p>Noch keine Nachrichten.</p></div>
                    <transition-group name="msg-list">
                        <template v-for="(m, index) in messages" :key="m.id">
                            <div v-if="showDateSeparator(index)" class="date-separator"><span>{{ formatDate(m.created_at) }}</span></div>
                            <div class="msg-row" :id="`msg-p-${m.id}`" :class="{ 'msg-me': m.user_id === me?.id }">
                                <div class="msg-avatar">
                                    <img v-if="m.user?.avatar_url" :src="m.user.avatar_url" />
                                    <div v-else class="avatar-fallback">{{ (m.user?.username || 'U')[0].toUpperCase() }}</div>
                                </div>
                                <div class="msg-content">
                                    <div class="msg-meta">
                                        <span class="msg-name">@{{ m.user?.username || 'user' }}</span>
                                        <span class="msg-time">{{ new Date(m.created_at).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'}) }}</span>
                                    </div>
                                    <div class="msg-bubble-wrap">
                                        <div class="msg-bubble">
                                            <img v-if="isGif(m.message)" :src="gifUrl(m.message)" class="msg-gif" loading="lazy" />
                                            <template v-else>{{ m.message }}</template>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </template>
                    </transition-group>
                </template>
            </div>
            <footer v-if="!chatBanned" class="gc-footer">
                <div class="compose-area" :class="{ disabled: !me }">
                    <div v-if="!me" class="login-prompt">Bitte <a href="/login">einloggen</a></div>
                    <template v-else>
                        <transition name="pop-up">
                            <div v-if="emojiOpen" class="emoji-picker-wrap"><div ref="emojiPickerEl"></div></div>
                        </transition>
                        <transition name="pop-up">
                            <div v-if="giphyOpen" class="giphy-panel">
                                <div class="giphy-search-row">
                                    <input v-model="giphyQuery" @input="onGiphyInput" placeholder="GIF suchen..." class="giphy-input" />
                                </div>
                                <div class="giphy-grid">
                                    <img v-for="g in giphyResults" :key="g.id" :src="g.images.fixed_height_small.url" class="giphy-thumb" loading="lazy" @click="sendGif(g.images.downsized.url)" />
                                </div>
                            </div>
                        </transition>
                        <div class="input-row">
                            <div class="tools">
                                <button class="tool-btn" :class="{ active: emojiOpen }" @click="toggleEmoji"><Smile :size="16" /></button>
                                <button class="tool-btn gif-btn" :class="{ active: giphyOpen }" @click="toggleGiphy"><ImagePlay :size="16" /></button>
                            </div>
                            <textarea id="gc-input-popup" class="chat-input" rows="1" placeholder="Nachricht..." v-model="input" @keydown.enter.exact.prevent="send" @keydown.enter.shift.exact.stop></textarea>
                            <button class="send-btn" :disabled="sending || !input.trim()" @click="send"><i data-lucide="send"></i></button>
                        </div>
                    </template>
                </div>
            </footer>
        </div>
    </transition>

    <transition name="slide-fade">
        <div v-show="isOpen && chatMode === 'drawer'" class="gc-overlay" role="dialog" aria-modal="true" aria-label="Global chat" @click.self="isOpen = false">
            <aside class="gc-drawer">
                <header class="gc-head">
                    <div class="head-left">
                        <div class="online-dot"></div>
                        <span class="head-title">Global Chat</span>
                    </div>
                    <div style="display:flex;gap:4px;align-items:center">
                        <button class="mode-btn" title="Popup-Modus" @click="toggleChatMode">
                            <i data-lucide="picture-in-picture-2"></i>
                        </button>
                        <button class="close-btn" title="Close" @click="isOpen = false">
                            <i data-lucide="x"></i>
                        </button>
                    </div>
                </header>

                <div v-if="chatBanned" class="gc-banned">
                    <div class="ban-card">
                        <div class="ban-stamp">BANNED</div>
                        <h2 class="ban-title">Chat Suspended</h2>
                        <p class="ban-reason" v-if="chatBan?.reason">Reason: {{ chatBan.reason }}</p>
                        <p class="ban-sub" v-if="chatBan?.ends_at">Until: {{ new Date(chatBan.ends_at).toLocaleString() }}</p>
                        <p class="ban-sub" v-else>Your account currently has a restriction that prevents using the global chat.</p>
                    </div>
                </div>

                <div v-else id="gc-list" class="gc-list">
                    <div v-if="loading" class="loading-state">
                        <div class="spinner"></div>
                        <span>Connecting to server...</span>
                    </div>
                    <template v-else>
                        <div v-if="!messages.length" class="empty-state">
                            <i data-lucide="message-square" style="width: 40px; height: 40px; opacity: 0.3; margin-bottom: 10px;"></i>
                            <p>No messages yet.</p>
                            <small>Be the first to say hello! 👋</small>
                        </div>

                        <transition-group name="msg-list">
                            <template v-for="(m, index) in messages" :key="m.id">
                                <div v-if="showDateSeparator(index)" class="date-separator">
                                    <span>{{ formatDate(m.created_at) }}</span>
                                </div>

                                <div class="msg-row" :id="`msg-${m.id}`" :class="{ 'msg-me': m.user_id === me?.id }">
                                    <div class="msg-avatar">
                                        <img v-if="m.user?.avatar_url" :src="m.user.avatar_url" alt="" />
                                        <div v-else class="avatar-fallback">{{ (m.user?.username || m.user?.name || 'U')?.[0]?.toUpperCase?.() }}</div>

                                        <!-- Level Badge (Absolute on Avatar) -->
                                        <div class="level-badge" v-if="m.user?.vip_level && m.user.vip_level > 0">{{ m.user.vip_level }}</div>
                                    </div>

                                    <div class="msg-content">
                                        <div class="msg-meta">
                                            <span class="msg-name msg-name-link" @click="openProfile(m.user)">@{{ m.user?.username || 'user' }}</span>

                                            <!-- Role Badge -->
                                            <span v-if="m.user?.role === 'admin'" class="badge badge-admin" title="Admin">ADMIN</span>
                                            <span v-else-if="m.user?.role === 'staff'" class="badge badge-staff" title="Staff">STAFF</span>
                                            <span v-else-if="m.user?.role === 'mod'" class="badge badge-mod" title="Moderator">MOD</span>
                                            <span v-else-if="m.user?.role === 'streamer'" class="badge badge-streamer" title="Streamer">STREAMER</span>
                                            <span v-else-if="m.user?.role === 'youtuber'" class="badge badge-youtuber" title="YouTuber">YOUTUBER</span>
                                            <span v-else class="badge badge-user" title="User">USER</span>

                                            <!-- VIP Badge -->
                                            <span v-if="m.user?.vip_level && m.user.vip_level > 0" class="badge badge-vip" :title="`VIP Level ${m.user.vip_level}`">VIP {{ m.user.vip_level }}</span>

                                            <!-- Clan tag -->
                                            <span v-if="m.user?.clan_tag" class="badge badge-clan" :title="`Clan ${m.user.clan_tag}`">[{{ m.user.clan_tag }}]</span>

                                            <span class="msg-time">{{ new Date(m.created_at).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) }}</span>
                                        </div>

                                        <div class="msg-bubble-wrap">
                                            <div v-if="m.reply_to" class="reply-preview" @click="scrollToMessage(m.reply_to?.id)" title="Jump to original">
                                                <div class="reply-bar"></div>
                                                <span class="reply-user">@{{ m.reply_to.user?.username || 'user' }}:</span>
                                                <span class="reply-text">{{ m.reply_to.message }}</span>
                                            </div>
                                            <div class="msg-bubble" :class="{ 'msg-deleted': m.is_deleted }">
                                                <template v-if="m.is_deleted">
                                                    <Trash2 :size="12" style="opacity:.45;flex-shrink:0;" />
                                                    <span class="deleted-text">
                                                        Nachricht gelöscht
                                                        <span v-if="m.deleted_by_user" class="deleted-by">
                                                            von <span class="deleted-role">[{{ (m.deleted_by_user.role || 'mod').toUpperCase() }}]</span>
                                                            {{ m.deleted_by_user.username }}
                                                        </span>
                                                    </span>
                                                </template>
                                                <template v-else-if="isGif(m.message)">
                                                    <img :src="gifUrl(m.message)" class="msg-gif" loading="lazy" />
                                                </template>
                                                <template v-else>{{ m.message }}</template>
                                            </div>

                                            <!-- Actions & Reactions Container -->
                                            <div class="msg-controls" v-if="!m.is_deleted">
                                                <!-- Reaction quick bar -->
                                                <div class="reaction-bar">
                                                    <button
                                                        v-for="em in reactionEmojis"
                                                        :key="em"
                                                        class="reaction-btn"
                                                        :aria-label="`React ${em}`"
                                                        @click="toggleReaction(m, em)"
                                                    >{{ em }}</button>
                                                </div>

                                                <!-- Actions -->
                                                <div class="msg-actions">
                                                    <button class="act-btn" title="Reply" @click="setReply(m)"><Reply :size="14" /></button>
                                                    <button class="act-btn" title="Report" @click="reportMessage(m)"><Flag :size="14" /></button>
                                                    <button v-if="isAdmin" class="act-btn act-btn-delete" title="Löschen" @click="deleteMessage(m)"><Trash2 :size="14" /></button>
                                                </div>
                                            </div>

                                            <!-- Existing reactions -->
                                            <div v-if="m.reactions_agg && m.reactions_agg.length" class="reactions">
                                                <button
                                                    v-for="r in m.reactions_agg"
                                                    :key="r.emoji"
                                                    class="reaction-chip"
                                                    :class="{ reacted: r.reactedByMe }"
                                                    @click="toggleReaction(m, r.emoji)"
                                                    :title="r.reactedByMe ? 'Remove reaction' : 'Add reaction'"
                                                >
                                                    <span class="emoji">{{ r.emoji }}</span>
                                                    <span class="count">{{ r.count }}</span>
                                                </button>
                                            </div>
                                        </div>

                                    </div>
                                </div>
                            </template>
                        </transition-group>
                    </template>
                </div>

                <footer v-if="!chatBanned" class="gc-footer">


                    <div class="compose-area" :class="{ disabled: !me }">
                        <div v-if="!me" class="login-prompt">
                            Please <a href="/login">login</a> to chat
                        </div>

                        <template v-else>
                            <transition name="slide-up">
                                <div v-if="replyTo" class="replying-to">
                                    <div class="reply-info">
                                        <span class="reply-label">Replying to <span class="reply-target">{{ replyTo.user?.username || 'User' }}</span></span>
                                        <button class="close-reply" @click="replyTo = null"><i data-lucide="x"></i></button>
                                    </div>
                                    <div class="reply-msg-preview">{{ replyTo.message }}</div>
                                </div>
                            </transition>

                            <!-- Emoji picker (above footer) -->
                            <transition name="pop-up">
                                <div v-if="emojiOpen" class="emoji-picker-wrap">
                                    <div ref="emojiPickerEl"></div>
                                </div>
                            </transition>

                            <!-- Giphy panel (above footer) -->
                            <transition name="pop-up">
                                <div v-if="giphyOpen" class="giphy-panel">
                                    <div class="giphy-search-row">
                                        <input
                                            v-model="giphyQuery"
                                            @input="onGiphyInput"
                                            placeholder="GIF suchen..."
                                            class="giphy-input"
                                            autofocus
                                        />
                                        <span v-if="giphyLoading" class="giphy-spin"><Loader2 :size="14" class="spin-anim" /></span>
                                    </div>
                                    <div class="giphy-grid">
                                        <div v-if="!giphyResults.length && !giphyLoading" class="giphy-empty">Keine GIFs gefunden</div>
                                        <img
                                            v-for="g in giphyResults"
                                            :key="g.id"
                                            :src="g.images.fixed_height_small.url"
                                            class="giphy-thumb"
                                            loading="lazy"
                                            @click="sendGif(g.images.downsized.url)"
                                        />
                                    </div>
                                    <div class="giphy-brand">Powered by GIPHY</div>
                                </div>
                            </transition>

                            <div class="input-row">
                                <div class="tools">
                                    <button class="tool-btn" :class="{ active: emojiOpen }" @click="toggleEmoji" title="Emoji">
                                        <Smile :size="16" />
                                    </button>
                                    <button class="tool-btn gif-btn" :class="{ active: giphyOpen }" @click="toggleGiphy" title="GIF">
                                        <ImagePlay :size="16" />
                                    </button>
                                </div>

                                <textarea
                                    id="gc-input"
                                    class="chat-input"
                                    rows="1"
                                    placeholder="Type a message..."
                                    v-model="input"
                                    @keydown.enter.exact.prevent="send"
                                    @keydown.enter.shift.exact.stop
                                ></textarea>

                                <button class="send-btn" :disabled="sending || !input.trim()" @click="send">
                                    <i data-lucide="send"></i>
                                </button>
                            </div>
                        </template>
                    </div>
                </footer>
            </aside>
        </div>
    </transition>
</template>

<style scoped>
:global(:root) {
    --chat-bg: #0a0a0a;
    --chat-border: #1a1a1a;
    --chat-bubble-me: #1a1a1a;
    --chat-bubble-other: #111;
    --accent: #00f2ff;

    /* Roles */
    --admin: #ff3e3e;
    --staff: #007bff;
    --mod: #00ff9d;
    --streamer: #a855f7;
    --youtuber: #ff0000;
    --gold: #f7931a;
    --user: #666;
}

/* Compact banned view inside chat drawer */
.gc-banned { flex: 1; display: flex; align-items: center; justify-content: center; padding: 20px; }
.ban-card { text-align: center; color: #fff; background: #0d0d0d; border: 1px solid #1a1a1a; border-radius: 16px; padding: 24px; max-width: 340px; width: 100%; box-shadow: 0 10px 30px rgba(0,0,0,0.4); }
.ban-stamp { display: inline-block; color: #ff3e3e; border: 2px solid #ff3e3e; padding: 4px 12px; font-weight: 900; letter-spacing: 2px; border-radius: 6px; transform: rotate(-6deg); margin-bottom: 12px; font-size: 14px; }
.ban-title { margin: 0 0 8px; font-size: 18px; font-weight: 900; text-transform: uppercase; letter-spacing: 1px; }
.ban-reason { font-size: 12px; color: #ffaaaa; background: rgba(255,0,0,0.06); border: 1px solid rgba(255,0,0,0.2); padding: 6px 10px; border-radius: 8px; display: inline-block; margin-bottom: 8px; }
.ban-sub { font-size: 12px; color: #888; }

/* Popup mode */
.gc-popup {
    position: fixed; z-index: 9999;
    width: 380px; height: 580px;
    background: var(--chat-bg); border: 1px solid #222;
    border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,0.7);
    display: flex; flex-direction: column; overflow: hidden;
    user-select: none;
}

/* Mode toggle button */
.mode-btn {
    width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
    background: transparent; border: none; color: #666; cursor: pointer; border-radius: 6px; transition: .15s;
}
.mode-btn:hover { color: #fff; background: #1a1a1a; }
.mode-btn i { width: 15px; height: 15px; }

.gc-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.6); backdrop-filter: blur(4px); z-index: 9999; display: flex; justify-content: flex-end; }
.gc-drawer { width: 100%; max-width: 400px; height: 100%; background: var(--chat-bg); border-left: 1px solid var(--chat-border); display: flex; flex-direction: column; box-shadow: -10px 0 50px rgba(0,0,0,0.5); }

/* Transitions */
.slide-fade-enter-active, .slide-fade-leave-active { transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1); }
.slide-fade-enter-from, .slide-fade-leave-to { opacity: 0; }
.slide-fade-enter-from .gc-drawer { transform: translateX(100%); }
.slide-fade-leave-to .gc-drawer { transform: translateX(100%); }

.msg-list-enter-active { transition: all 0.4s ease; }
.msg-list-enter-from { opacity: 0; transform: translateY(20px); }

.slide-up-enter-active, .slide-up-leave-active { transition: all 0.2s ease; }
.slide-up-enter-from, .slide-up-leave-to { opacity: 0; transform: translateY(10px); }

.pop-up-enter-active, .pop-up-leave-active { transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.pop-up-enter-from, .pop-up-leave-to { opacity: 0; transform: scale(0.8) translateY(10px); }

/* Header */
.gc-head { height: 60px; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; border-bottom: 1px solid var(--chat-border); background: rgba(10,10,10,0.95); backdrop-filter: blur(10px); flex-shrink: 0; }
.head-left { display: flex; align-items: center; gap: 10px; }
.online-dot { width: 8px; height: 8px; background: var(--mod); border-radius: 50%; box-shadow: 0 0 10px var(--mod); animation: pulse-dot 2s infinite; }
.head-title { font-weight: 900; font-size: 14px; text-transform: uppercase; letter-spacing: 1px; color: #fff; }
.close-btn { background: transparent; border: none; color: #666; cursor: pointer; transition: 0.2s; padding: 5px; border-radius: 5px; }
.close-btn:hover { color: #fff; background: #1a1a1a; }

@keyframes pulse-dot { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } }

/* List */
.gc-list { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 40px 20px 20px; display: flex; flex-direction: column; gap: 15px; scroll-behavior: smooth; overscroll-behavior: contain; }
.gc-list::-webkit-scrollbar { width: 6px; }
.gc-list::-webkit-scrollbar-thumb { background: #222; border-radius: 10px; }

/* Date Separator */
.date-separator { display: flex; justify-content: center; margin: 10px 0; position: relative; }
.date-separator span { background: #151515; color: #666; font-size: 10px; padding: 4px 12px; border-radius: 20px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; z-index: 1; border: 1px solid #222; }
.date-separator::before { content: ''; position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: #1a1a1a; z-index: 0; }

/* Messages */
.msg-row { display: flex; gap: 12px; align-items: flex-start; }
.msg-me { flex-direction: row-reverse; }

.msg-avatar { width: 32px; height: 32px; border-radius: 10px; overflow: visible; background: #151515; flex-shrink: 0; border: 1px solid #222; transition: 0.2s; position: relative; }
.msg-row:hover .msg-avatar { border-color: #333; transform: scale(1.05); }
.msg-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 10px; }
.avatar-fallback { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-weight: 800; color: #555; font-size: 12px; border-radius: 10px; }

.level-badge { position: absolute; bottom: -5px; right: -5px; background: #000; border: 1px solid var(--accent); color: var(--accent); font-size: 8px; font-weight: 900; padding: 1px 4px; border-radius: 4px; z-index: 2; box-shadow: 0 2px 5px rgba(0,0,0,0.5); }

.msg-content { display: flex; flex-direction: column; gap: 4px; max-width: 80%; position: relative; }
.msg-me .msg-content { align-items: flex-end; }

.msg-meta { display: flex; align-items: center; gap: 6px; font-size: 10px; color: #666; flex-wrap: wrap; }
.msg-name { font-weight: 800; color: #aaa; transition: 0.2s; cursor: pointer; }
.msg-name-link:hover { color: var(--primary); text-decoration: underline; }
.msg-time { font-size: 9px; opacity: 0.7; margin-left: 4px; }
.msg-time-me { font-size: 9px; color: #444; margin-top: 2px; }

/* Badges */
.badge { font-size: 8px; font-weight: 900; padding: 2px 6px; border-radius: 4px; text-transform: uppercase; letter-spacing: 0.5px; animation: pulse-badge 2s infinite; box-shadow: 0 0 10px rgba(0,0,0,0.2); }
.badge-admin { background: rgba(255,62,62,0.15); color: var(--admin); border: 1px solid rgba(255,62,62,0.3); animation: pulse-admin 1.5s infinite; }
.badge-staff { background: rgba(0,123,255,0.15); color: var(--staff); border: 1px solid rgba(0,123,255,0.3); }
.badge-mod { background: rgba(0,255,157,0.15); color: var(--mod); border: 1px solid rgba(0,255,157,0.3); }
.badge-streamer { background: linear-gradient(45deg, rgba(0,255,157,0.15), rgba(168,85,247,0.15)); color: var(--streamer); border: 1px solid rgba(168,85,247,0.3); animation: pulse-streamer 3s infinite; }
.badge-youtuber { background: rgba(255,0,0,0.15); color: var(--youtuber); border: 1px solid rgba(255,0,0,0.3); animation: pulse-yt 2s infinite; }
.badge-vip { background: rgba(247,147,26,0.15); color: var(--gold); border: 1px solid rgba(247,147,26,0.3); animation: pulse-vip 2s infinite; }
.badge-clan { background: #151515; color: #888; border: 1px solid #222; animation: none; }
.badge-user { background: #151515; color: var(--user); border: 1px solid #222; animation: none; }

@keyframes pulse-badge { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } }
@keyframes pulse-admin { 0% { box-shadow: 0 0 0 rgba(255,62,62,0); } 50% { box-shadow: 0 0 10px rgba(255,62,62,0.4); } 100% { box-shadow: 0 0 0 rgba(255,62,62,0); } }
@keyframes pulse-streamer { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } }
@keyframes pulse-yt { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } }
@keyframes pulse-vip { 0% { border-color: var(--gold); } 50% { border-color: #fff; } 100% { border-color: var(--gold); } }

.msg-bubble-wrap { position: relative; transition: 0.2s; }
.msg-row:hover .msg-controls { opacity: 1; pointer-events: auto; transform: translateY(0); }

.msg-bubble { background: var(--chat-bubble-other); padding: 10px 14px; border-radius: 12px; border-top-left-radius: 2px; font-size: 13px; line-height: 1.5; color: #ddd; border: 1px solid #1a1a1a; word-break: break-word; box-shadow: 0 2px 5px rgba(0,0,0,0.1); transition: 0.2s; }
.msg-row:hover .msg-bubble { border-color: #2a2a2a; }
.msg-me .msg-bubble { background: var(--chat-bubble-me); border-radius: 12px; border-top-right-radius: 2px; color: #fff; border-color: #222; }
.msg-me:hover .msg-bubble { border-color: #333; }

/* Reply Preview inside bubble */
.reply-preview { font-size: 11px; margin-bottom: 6px; padding-left: 8px; position: relative; opacity: 0.7; cursor: pointer; transition: 0.2s; }
.reply-preview:hover { opacity: 1; }
.reply-bar { position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--accent); border-radius: 2px; }
.reply-user { font-weight: 800; margin-right: 5px; color: var(--accent); }
.reply-text { color: #aaa; }

/* Controls Container (Reactions + Actions) */
.msg-controls {
    position: absolute;
    top: -38px;
    /* Default: Left aligned message -> Align controls to left, grow right */
    left: 0;
    right: auto;

    display: flex;
    gap: 8px;
    opacity: 0;
    pointer-events: none;
    transition: 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    transform: translateY(5px);
    z-index: 10;
}

/* Me: Right aligned message -> Align controls to right, grow left */
.msg-me .msg-controls {
    left: auto;
    right: 0;
    flex-direction: row; /* Keep order consistent */
}

/* Actions (Reply/Report) */
.msg-actions { background: #151515; border: 1px solid #222; border-radius: 8px; display: flex; gap: 2px; padding: 3px; box-shadow: 0 5px 15px rgba(0,0,0,0.5); }
.act-btn { width: 26px; height: 26px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; color: #666; cursor: pointer; border-radius: 6px; transition: 0.2s; }
.act-btn:hover { background: #222; color: #fff; transform: scale(1.1); }
.act-btn-delete:hover { background: rgba(239,68,68,0.15) !important; color: #ef4444 !important; }
.act-btn i { width: 14px; height: 14px; }
.msg-deleted { opacity: .65; display: flex; align-items: center; gap: 6px; }
.deleted-text { font-style: italic; font-size: 12px; color: #888; }
.deleted-by { font-style: normal; font-size: 11px; color: #666; margin-left: 4px; }
.deleted-role { color: #ef4444; font-weight: 700; font-size: 10px; margin-right: 2px; }

/* Reactions Bar */
.reaction-bar { display: flex; gap: 4px; background: #151515; padding: 4px; border-radius: 8px; border: 1px solid #222; box-shadow: 0 5px 15px rgba(0,0,0,0.5); }
.reaction-btn { background: transparent; border: none; color: #ccc; font-size: 16px; padding: 2px 4px; cursor: pointer; transition: 0.15s; border-radius: 4px; }
.reaction-btn:hover { background: rgba(255,255,255,0.1); transform: scale(1.2); }

.reactions { display: flex; gap: 4px; margin-top: 6px; flex-wrap: wrap; }
.reaction-chip { display: inline-flex; align-items: center; gap: 4px; background: #121212; border: 1px solid #222; color: #aaa; border-radius: 6px; padding: 2px 6px; font-size: 11px; cursor: pointer; transition: 0.15s; }
.reaction-chip .emoji { font-size: 12px; }
.reaction-chip .count { font-weight: 800; font-size: 10px; color: #888; }
.reaction-chip:hover { border-color: #333; color: #ddd; transform: translateY(-1px); }
.reaction-chip.reacted { background: rgba(0,242,255,0.1); border-color: var(--accent); color: var(--accent); }

/* Flash highlight when jumping to a replied message */
@keyframes flashPulse {
    0% { box-shadow: 0 0 0px rgba(0,242,255,0.0); }
    50% { box-shadow: 0 0 20px rgba(0,242,255,0.5); }
    100% { box-shadow: 0 0 0px rgba(0,242,255,0.0); }
}
.flash .msg-bubble { animation: flashPulse 1.2s ease; border-color: var(--accent) !important; }

/* Footer */
.gc-footer { padding: 15px; border-top: 1px solid var(--chat-border); background: #0a0a0a; position: relative; z-index: 20; flex-shrink: 0; }

.compose-area { background: #050505; border: 1px solid #1a1a1a; padding: 8px; border-radius: 12px; transition: 0.3s; display: flex; flex-direction: column; gap: 8px; position: relative; }
.compose-area:focus-within { border-color: #333; box-shadow: 0 0 20px rgba(0,0,0,0.3); }
.compose-area.disabled { opacity: 0.7; pointer-events: none; justify-content: center; align-items: center; padding: 15px; }

.replying-to { display: flex; flex-direction: column; gap: 2px; padding: 8px; background: #111; border-radius: 8px; border-left: 2px solid var(--accent); font-size: 11px; position: relative; }
.reply-info { display: flex; justify-content: space-between; align-items: center; color: #888; }
.reply-target { color: var(--accent); font-weight: 800; }
.reply-msg-preview { color: #ccc; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.close-reply { background: transparent; border: none; color: #666; cursor: pointer; transition: 0.2s; }
.close-reply:hover { color: #fff; transform: scale(1.1); }

.input-row { display: flex; align-items: flex-end; gap: 10px; }

.login-prompt { font-size: 12px; color: #666; text-align: center; }
.login-prompt a { color: var(--accent); text-decoration: none; font-weight: 800; pointer-events: auto; }

.chat-input { flex: 1; background: transparent; border: none; color: #fff; font-size: 13px; resize: none; max-height: 100px; padding: 8px 5px; outline: none; }
.chat-input::placeholder { color: #444; }

.tool-btn, .send-btn { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 8px; border: none; cursor: pointer; transition: 0.2s; }
.tool-btn { background: transparent; color: #666; }
.tool-btn:hover { color: #fff; background: #151515; transform: scale(1.1); }
.tool-btn.active { color: #df006a; background: rgba(223,0,106,0.1); }
.gif-btn { font-size: 10px; font-weight: 800; color: #555; width: auto; padding: 0 8px; border-radius: 6px; border: 1px solid #252525; }
.gif-btn.active { color: #df006a; border-color: rgba(223,0,106,0.3); background: rgba(223,0,106,0.08); }

.send-btn { background: var(--accent); color: #000; }
.send-btn:disabled { opacity: 0.5; cursor: not-allowed; background: #222; color: #555; }
.send-btn:hover:not(:disabled) { transform: scale(1.05); box-shadow: 0 0 15px rgba(0,242,255,0.4); }

/* emoji-mart dark theme override */
.emoji-picker-wrap {
    position: absolute; bottom: calc(100% + 6px); left: 0;
    z-index: 9999; border-radius: 12px; overflow: hidden;
    box-shadow: 0 10px 40px rgba(0,0,0,0.6);
}
:global(em-emoji-picker) {
    --border-radius: 12px;
    --background-rgb: 17, 17, 19;
    --rgb-background: 17, 17, 19;
    --color-border: #2a2a2a;
    --rgb-color: 220, 220, 220;
    --rgb-input: 255, 255, 255;
    --color-border-over: #3a3a3a;
    height: 380px;
}

/* Giphy panel */
.giphy-panel {
    position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
    background: #111113; border: 1px solid #252528; border-radius: 12px;
    padding: 10px; z-index: 9999; box-shadow: 0 10px 40px rgba(0,0,0,0.6);
    display: flex; flex-direction: column; gap: 8px;
}
.giphy-search-row { display: flex; align-items: center; gap: 6px; }
.giphy-input {
    flex: 1; background: #0c0c0e; border: 1px solid #252528; color: #ccc;
    padding: 7px 11px; border-radius: 8px; font-size: 12px;
}
.giphy-input:focus { outline: none; border-color: rgba(223,0,106,0.35); }
.giphy-spin { color: #555; display: flex; }
.spin-anim { animation: spin-anim .7s linear infinite; }
@keyframes spin-anim { to { transform: rotate(360deg); } }
.giphy-grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px;
    max-height: 260px; overflow-y: auto;
}
.giphy-grid::-webkit-scrollbar { width: 4px; }
.giphy-grid::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 2px; }
.giphy-thumb {
    width: 100%; height: 80px; object-fit: cover; border-radius: 6px;
    cursor: pointer; transition: 0.15s; border: 2px solid transparent;
}
.giphy-thumb:hover { border-color: #df006a; transform: scale(1.02); }
.giphy-empty { grid-column: 1/-1; text-align: center; color: #555; font-size: 12px; padding: 20px 0; }
.giphy-brand { font-size: 9px; color: #444; text-align: right; font-weight: 600; }

/* GIF in chat */
.msg-gif { max-width: 200px; border-radius: 8px; display: block; }

/* States */
.loading-state, .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; color: #444; font-size: 12px; gap: 10px; }
.spinner { width: 20px; height: 20px; border: 2px solid #222; border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; }

@keyframes spin { to { transform: rotate(360deg); } }

@media (max-width: 600px) {
    .gc-drawer { max-width: 100%; }
    .gc-overlay { z-index: 99999; }
}

/* ===== Report Modal ===== */
.gc-report-overlay {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.8);
    backdrop-filter: blur(8px) saturate(0.8);
    -webkit-backdrop-filter: blur(8px) saturate(0.8);
    z-index: 2147483647;
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
}

.gc-report-modal {
    background: #0c0c0e;
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: 22px;
    width: 100%; max-width: 460px;
    box-shadow: 0 40px 100px rgba(0,0,0,0.9), 0 0 0 1px rgba(223,0,106,0.05);
    overflow: hidden;
    animation: modal-pop 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes modal-pop {
    from { opacity: 0; transform: scale(0.9) translateY(16px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* Transition */
.modal-fade-enter-active { transition: opacity 0.25s ease; }
.modal-fade-leave-active { transition: opacity 0.15s ease; }
.modal-fade-enter-from, .modal-fade-leave-to { opacity: 0; }

/* ── Header ── */
.rm-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 18px;
    background: linear-gradient(135deg, rgba(223,0,106,0.12), rgba(0,0,0,0));
    border-bottom: 1px solid rgba(255,255,255,0.06);
}
.rm-head-left { display: flex; align-items: center; gap: 10px; }
.rm-head-icon {
    width: 30px; height: 30px; border-radius: 9px;
    background: rgba(223,0,106,0.18); border: 1px solid rgba(223,0,106,0.35);
    color: #df006a; display: flex; align-items: center; justify-content: center;
}
.rm-title { font-size: 14px; font-weight: 800; color: #fff; letter-spacing: 0.2px; }
.rm-close {
    width: 28px; height: 28px; border-radius: 8px;
    background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08);
    color: #555; cursor: pointer; display: flex; align-items: center; justify-content: center;
    transition: 0.2s; flex-shrink: 0;
}
.rm-close:hover { background: rgba(255,255,255,0.1); color: #fff; }

/* ── User card ── */
.rm-user {
    display: flex; align-items: center; gap: 14px;
    padding: 14px 18px;
    background: rgba(255,255,255,0.02);
    border-bottom: 1px solid rgba(255,255,255,0.05);
}
.rm-avatar-wrap { position: relative; flex-shrink: 0; }
.rm-avatar {
    width: 52px; height: 52px; border-radius: 14px; overflow: hidden;
    border: 2px solid rgba(255,255,255,0.08); background: #151515; position: relative; z-index: 1;
}
.rm-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rm-avatar-fallback {
    width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
    font-size: 20px; font-weight: 900; color: #555;
}
.rm-avatar-glow {
    position: absolute; inset: -4px; border-radius: 18px; z-index: 0;
    background: radial-gradient(circle, rgba(223,0,106,0.25), transparent 70%);
    filter: blur(6px);
}
.rm-user-info { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.rm-username { font-size: 15px; font-weight: 800; color: #fff; }
.rm-badges { display: flex; gap: 5px; flex-wrap: wrap; }
.rm-badge {
    font-size: 9px; font-weight: 800; padding: 2px 8px; border-radius: 5px;
    text-transform: uppercase; letter-spacing: 0.5px; border: 1px solid;
}
.rm-badge.admin    { color: #ff3e3e; border-color: rgba(255,62,62,0.35);  background: rgba(255,62,62,0.08); }
.rm-badge.staff    { color: #3b82f6; border-color: rgba(59,130,246,0.35); background: rgba(59,130,246,0.08); }
.rm-badge.mod      { color: #00ff9d; border-color: rgba(0,255,157,0.35);  background: rgba(0,255,157,0.08); }
.rm-badge.streamer { color: #a855f7; border-color: rgba(168,85,247,0.35); background: rgba(168,85,247,0.08); }
.rm-badge.user     { color: #555; border-color: rgba(255,255,255,0.08);   background: rgba(255,255,255,0.03); }
.rm-badge.vip      { color: #ffd700; border-color: rgba(255,215,0,0.35);  background: rgba(255,215,0,0.08); }
.rm-badge.clan     { color: #00f2ff; border-color: rgba(0,242,255,0.35);  background: rgba(0,242,255,0.08); }

/* ── Sections ── */
.rm-section { padding: 14px 18px; border-bottom: 1px solid rgba(255,255,255,0.05); }
.rm-section-label {
    display: flex; align-items: center; gap: 6px;
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.7px; color: #444; margin-bottom: 10px;
}

/* ── Message bubble ── */
.rm-message-bubble {
    background: rgba(255,255,255,0.03);
    border: 1px solid rgba(255,255,255,0.07);
    border-left: 3px solid #df006a;
    border-radius: 10px; padding: 12px 14px;
    position: relative; overflow: hidden;
}
.rm-quote-mark {
    position: absolute; top: 4px; right: 12px;
    font-size: 40px; line-height: 1; color: rgba(255,255,255,0.04);
    font-family: Georgia, serif; font-weight: 900; pointer-events: none;
}
.rm-message-text {
    font-size: 13px; color: #ccc; line-height: 1.6;
    word-break: break-word; margin: 0; position: relative; z-index: 1;
}

/* ── Reasons ── */
.rm-reasons { display: flex; flex-direction: column; gap: 7px; }
.rm-reason-btn {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 14px; border-radius: 12px;
    background: rgba(255,255,255,0.03);
    border: 1px solid rgba(255,255,255,0.06);
    color: #888; cursor: pointer; transition: all 0.18s ease;
    text-align: left; width: 100%;
}
.rm-reason-btn:hover {
    background: rgba(255,255,255,0.06);
    border-color: rgba(255,255,255,0.12);
    color: #ddd;
    transform: translateX(2px);
}
.rm-reason-btn.selected {
    background: rgba(var(--reason-color, 223 0 106) / 0.1);
    border-color: color-mix(in srgb, var(--reason-color, #df006a) 50%, transparent);
    color: #fff;
}
.reason-icon-wrap {
    width: 34px; height: 34px; border-radius: 10px;
    background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.06);
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    transition: 0.18s;
}
.rm-reason-btn.selected .reason-icon-wrap {
    background: rgba(var(--reason-color, 223 0 106) / 0.15);
    border-color: color-mix(in srgb, var(--reason-color, #df006a) 40%, transparent);
}
.reason-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.reason-label { font-size: 13px; font-weight: 700; color: inherit; }
.reason-desc  { font-size: 11px; color: #555; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rm-reason-btn.selected .reason-desc { color: #888; }
.reason-check-wrap { color: #22c55e; flex-shrink: 0; }
.reason-chevron { color: #333; flex-shrink: 0; transition: 0.18s; }
.rm-reason-btn:hover .reason-chevron { color: #555; transform: translateX(2px); }

/* ── Actions ── */
.rm-actions {
    display: flex; gap: 10px;
    padding: 14px 18px 18px;
}
.rm-btn-cancel {
    flex: 1; padding: 11px 14px; border-radius: 11px;
    background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08);
    color: #888; cursor: pointer; font-size: 13px; font-weight: 700;
    transition: 0.2s; display: flex; align-items: center; justify-content: center; gap: 7px;
}
.rm-btn-cancel:hover { background: rgba(255,255,255,0.08); color: #ccc; }
.rm-btn-submit {
    flex: 2; padding: 11px 14px; border-radius: 11px;
    background: linear-gradient(135deg, #df006a, #a8004e);
    border: 1px solid rgba(223,0,106,0.5);
    color: #fff; cursor: pointer; font-size: 13px; font-weight: 800;
    transition: 0.2s; display: flex; align-items: center; justify-content: center; gap: 8px;
    box-shadow: 0 4px 20px rgba(223,0,106,0.25);
}
.rm-btn-submit:hover:not(:disabled) {
    background: linear-gradient(135deg, #f2007a, #c0005c);
    box-shadow: 0 6px 30px rgba(223,0,106,0.45);
    transform: translateY(-1px);
}
.rm-btn-submit:active:not(:disabled) { transform: translateY(0); }
.rm-btn-submit:disabled { opacity: 0.35; cursor: not-allowed; box-shadow: none; }
.rm-spin { animation: spin 0.8s linear infinite; }

/* ── Success ── */
.report-success {
    padding: 44px 24px 40px;
    display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center;
}
.success-ring {
    width: 64px; height: 64px; border-radius: 50%;
    background: radial-gradient(circle, rgba(34,197,94,0.2), rgba(34,197,94,0.05));
    border: 2px solid rgba(34,197,94,0.4);
    color: #22c55e; display: flex; align-items: center; justify-content: center;
    box-shadow: 0 0 30px rgba(34,197,94,0.25);
    animation: success-bounce 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes success-bounce {
    0%   { transform: scale(0); opacity: 0; }
    60%  { transform: scale(1.12); }
    100% { transform: scale(1);   opacity: 1; }
}
.report-success h3 { font-size: 18px; font-weight: 900; color: #fff; margin: 0; }
.report-success p  { font-size: 13px; color: #666; margin: 0; line-height: 1.6; }

/* ── Responsive ── */
@media (max-width: 480px) {
    .gc-report-overlay { align-items: flex-end; padding: 0; }
    .gc-report-modal { border-radius: 22px 22px 0 0; max-width: 100%; }
    .reason-desc { display: none; }
}
</style>
