<script setup lang="ts">
import { usePage, Link, router } from '@inertiajs/vue3';
import UserLayout from '@/layouts/user/userlayout.vue';
import { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue';
import { csrfFetch } from '@/utils/csrfFetch';
import { Picker } from 'emoji-mart';
import data from '@emoji-mart/data';
import {
    Search, UserPlus, UserCheck, UserX, MessageCircle, Send,
    Smile, ImagePlay, Reply, Flag, X, CheckCircle2, Loader2,
    ShieldAlert, MessageSquareOff, BadgeDollarSign, HelpCircle,
    ChevronLeft, Users, Inbox, Clock, Trash2, Shield,
} from 'lucide-vue-next';

const page = usePage();
const me = computed(() => (page.props.auth as any)?.user);

const GIPHY_KEY = 'GF7y5viqpCeUeJdzoj5U9PY5XkFpswmC';

// ── Tabs ─────────────────────────────────────────────────
type Tab = 'chats' | 'friends' | 'requests' | 'search';
const activeTab = ref<Tab>('chats');

// ── Left-panel data ───────────────────────────────────────
const conversations = ref<any[]>([]);
const friends       = ref<any[]>([]);
const requests      = ref<any[]>([]);
const searchQuery   = ref('');
const searchResults = ref<any[]>([]);
const searchLoading = ref(false);

// ── Chat window ───────────────────────────────────────────
const selectedPartner = ref<any>(null);
const messages        = ref<any[]>([]);
const chatLoading     = ref(false);
const input           = ref('');
const sending         = ref(false);
const replyTo         = ref<any>(null);
let pollTimer: number | undefined;

// ── Emoji / GIF ───────────────────────────────────────────
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;

// ── Guild chat ────────────────────────────────────────
const myGuild          = ref<any>(null);
const guildChatActive  = ref(false);
const guildMessages    = ref<any[]>([]);
const guildChatLoading = ref(false);
const membersOpen      = ref(false);
const guildMembers     = ref<any[]>([]);
let guildPollTimer: number | undefined;

// ── Report modal ──────────────────────────────────────────
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 Nachrichten 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',        desc: 'Betrügerische Links oder Forderungen',          icon: BadgeDollarSign,   color: '#a855f7' },
    { value: 'other',      label: 'Sonstiges',     desc: 'Anderer Verstoß gegen die Nutzungsregeln',     icon: HelpCircle,        color: '#6b7280' },
];

// ── Load data ─────────────────────────────────────────────
async function loadConversations() {
    try {
        const r = await fetch('/api/dm/conversations', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) conversations.value = (await r.json()).data ?? [];
    } catch { /* silent */ }
}

async function loadFriends() {
    try {
        const r = await fetch('/api/dm/friends', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) friends.value = (await r.json()).data ?? [];
    } catch { /* silent */ }
}

async function loadRequests() {
    try {
        const r = await fetch('/api/dm/friends/requests', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) requests.value = (await r.json()).data ?? [];
    } catch { /* silent */ }
}

let searchTimer: ReturnType<typeof setTimeout> | null = null;
async function doSearch() {
    const q = searchQuery.value.trim();
    if (!q) { searchResults.value = []; return; }
    if (searchTimer) clearTimeout(searchTimer);
    searchTimer = setTimeout(async () => {
        searchLoading.value = true;
        try {
            const r = await fetch(`/api/users/search?q=${encodeURIComponent(q)}`, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } });
            if (r.ok) {
                const data = await r.json();
                searchResults.value = Array.isArray(data) ? data : (data.users ?? data.data ?? []);
            }
        } catch { /* silent */ } finally {
            searchLoading.value = false;
        }
    }, 350);
}

// ── Open a conversation ───────────────────────────────────
async function openChat(partner: any) {
    selectedPartner.value = partner;
    messages.value = [];
    chatLoading.value = true;
    stopPolling();
    try {
        const r = await fetch(`/api/dm/${partner.id}`, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) messages.value = (await r.json()).data ?? [];
        await nextTick();
        scrollToBottom();
    } finally {
        chatLoading.value = false;
    }
    startPolling();
    // Update unread in conversations list
    const conv = conversations.value.find(c => c.partner.id === partner.id);
    if (conv) conv.unread_count = 0;
}

async function pollMessages() {
    if (!selectedPartner.value) return;
    try {
        const r = await fetch(`/api/dm/${selectedPartner.value.id}`, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (!r.ok) return;
        const fresh = (await r.json()).data ?? [];
        const lastKnown = messages.value.length ? messages.value[messages.value.length - 1].id : 0;
        const newMsgs = fresh.filter((m: any) => m.id > lastKnown);
        if (newMsgs.length) {
            messages.value.push(...newMsgs);
            await nextTick();
            scrollToBottomIfNear();
        }
    } catch { /* silent */ }
}

function startPolling() {
    stopPolling();
    pollTimer = window.setInterval(pollMessages, 4000);
}
function stopPolling() {
    if (pollTimer) window.clearInterval(pollTimer);
    pollTimer = undefined;
}

function scrollToBottom() {
    const el = document.getElementById('dm-messages');
    if (el) el.scrollTop = el.scrollHeight;
}
function scrollToBottomIfNear() {
    const el = document.getElementById('dm-messages');
    if (!el) return;
    if (el.scrollHeight - el.scrollTop - el.clientHeight < 180) scrollToBottom();
}

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

async function send() {
    const text = input.value.trim();
    if (!text || sending.value) return;
    if (!selectedPartner.value && !guildChatActive.value) return;
    sending.value = true;
    const payload: any = { message: text };
    if (replyTo.value) payload.reply_to_id = replyTo.value.id;
    try {
        const url = guildChatActive.value
            ? `/api/guild-chat/${myGuild.value.id}`
            : `/api/dm/${selectedPartner.value.id}`;
        const r = await csrfFetch(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(payload),
        });
        if (!r.ok) return;
        const msg = (await r.json()).data;
        if (guildChatActive.value) {
            guildMessages.value.push(msg);
        } else {
            messages.value.push(msg);
            updateConversationLast(msg);
        }
        input.value = '';
        replyTo.value = null;
        await nextTick();
        scrollToBottom();
    } finally {
        sending.value = false;
    }
}

async function sendGif(url: string) {
    if (sending.value) return;
    if (!selectedPartner.value && !guildChatActive.value) return;
    giphyOpen.value = false;
    sending.value = true;
    try {
        const endpoint = guildChatActive.value
            ? `/api/guild-chat/${myGuild.value.id}`
            : `/api/dm/${selectedPartner.value.id}`;
        const r = await csrfFetch(endpoint, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ message: `[GIF:${url}]` }),
        });
        if (!r.ok) return;
        const msg = (await r.json()).data;
        if (guildChatActive.value) {
            guildMessages.value.push(msg);
        } else {
            messages.value.push(msg);
            updateConversationLast(msg);
        }
        await nextTick();
        scrollToBottom();
    } finally {
        sending.value = false;
    }
}

function updateConversationLast(msg: any) {
    const pid = selectedPartner.value?.id;
    const conv = conversations.value.find(c => c.partner.id === pid);
    if (conv) {
        conv.last_message = { id: msg.id, message: msg.message, sender_id: msg.sender_id, created_at: msg.created_at };
    } else {
        conversations.value.unshift({
            partner: selectedPartner.value,
            last_message: { id: msg.id, message: msg.message, sender_id: msg.sender_id, created_at: msg.created_at },
            unread_count: 0,
        });
    }
}

// ── Emoji picker ──────────────────────────────────────────
function toggleEmoji() {
    giphyOpen.value = false;
    emojiOpen.value = !emojiOpen.value;
    if (emojiOpen.value) {
        nextTick(() => {
            if (emojiPickerEl.value && !pickerInstance) {
                pickerInstance = new Picker({
                    data,
                    onEmojiSelect: (em: any) => insertEmoji(em.native),
                    theme: 'dark',
                    locale: 'de',
                    previewPosition: 'none',
                });
                emojiPickerEl.value.appendChild(pickerInstance as unknown as Node);
            }
        });
    }
}
function insertEmoji(em: string) {
    const el = document.getElementById('dm-input') as HTMLTextAreaElement | null;
    const at = el?.selectionStart ?? input.value.length;
    input.value = input.value.slice(0, at) + em + input.value.slice(at);
    emojiOpen.value = false;
    nextTick(() => { el?.focus(); });
}

// ── GIPHY ─────────────────────────────────────────────────
function toggleGiphy() {
    emojiOpen.value = false;
    giphyOpen.value = !giphyOpen.value;
    if (giphyOpen.value && !giphyResults.value.length) searchGiphy('hello');
}
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 r = await fetch(`https://api.giphy.com/v1/gifs/search?api_key=${GIPHY_KEY}&q=${encodeURIComponent(query)}&limit=18&rating=pg-13`);
            giphyResults.value = (await r.json()).data ?? [];
        } finally { giphyLoading.value = false; }
    }, 350);
}
function onGiphyInput() { searchGiphy(giphyQuery.value); }

// ── Report ────────────────────────────────────────────────
function openReport(msg: any) { reportModal.value = { msg }; reportReason.value = ''; reportDone.value = false; }
function closeReport() { reportModal.value = null; }
async function submitReport() {
    if (!reportReason.value || reportSubmitting.value) return;
    reportSubmitting.value = true;
    try {
        const r = await csrfFetch(`/api/dm/messages/${reportModal.value!.msg.id}/report`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ reason: reportReason.value }),
        });
        if (r.ok) { reportDone.value = true; setTimeout(closeReport, 1800); }
    } finally { reportSubmitting.value = false; }
}

// ── Friend actions ────────────────────────────────────────
async function sendFriendRequest(userId: number) {
    await csrfFetch('/friends/request', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ user_id: userId }),
    });
    await loadFriends();
}
async function acceptRequest(id: number) {
    await csrfFetch(`/friends/${id}/accept`, { method: 'POST' });
    await Promise.all([loadRequests(), loadFriends()]);
}
async function declineRequest(id: number) {
    await csrfFetch(`/friends/${id}/decline`, { method: 'POST' });
    await loadRequests();
}

// ── Guild chat functions ──────────────────────────────────
async function loadMyGuild() {
    try {
        const r = await fetch('/api/guild-chat/me', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) myGuild.value = (await r.json()).data;
    } catch { /* silent */ }
}

async function loadGuildMembers() {
    if (!myGuild.value) return;
    try {
        const r = await fetch(`/api/guild-chat/${myGuild.value.id}/members`, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) guildMembers.value = (await r.json()).data ?? [];
    } catch { /* silent */ }
}

async function openGuildChat() {
    selectedPartner.value = null;
    stopPolling();
    replyTo.value = null;
    membersOpen.value = false;
    guildChatActive.value = true;
    guildMessages.value = [];
    guildChatLoading.value = true;
    try {
        const r = await fetch(`/api/guild-chat/${myGuild.value.id}`, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (r.ok) guildMessages.value = (await r.json()).data ?? [];
        await nextTick();
        scrollToBottom();
    } finally {
        guildChatLoading.value = false;
    }
    loadGuildMembers();
    startGuildPolling();
}

async function pollGuildMessages() {
    if (!guildChatActive.value || !myGuild.value) return;
    try {
        const r = await fetch(`/api/guild-chat/${myGuild.value.id}`, { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
        if (!r.ok) return;
        const fresh = (await r.json()).data ?? [];
        const lastKnown = guildMessages.value.length ? guildMessages.value[guildMessages.value.length - 1].id : 0;
        const newMsgs = fresh.filter((m: any) => m.id > lastKnown);
        if (newMsgs.length) {
            guildMessages.value.push(...newMsgs);
            await nextTick();
            scrollToBottomIfNear();
        }
    } catch { /* silent */ }
}

function startGuildPolling() {
    stopGuildPolling();
    guildPollTimer = window.setInterval(pollGuildMessages, 4000);
}
function stopGuildPolling() {
    if (guildPollTimer) window.clearInterval(guildPollTimer);
    guildPollTimer = undefined;
}

function closeActiveChat() {
    if (guildChatActive.value) {
        guildChatActive.value = false;
        stopGuildPolling();
    } else {
        selectedPartner.value = null;
        stopPolling();
    }
    replyTo.value = null;
}

// ── Helpers ───────────────────────────────────────────────
function avatar(u: any) { return u?.avatar || u?.avatar_url || null; }
function initial(u: any) { return (u?.username || u?.name || '?').charAt(0).toUpperCase(); }
function shortMsg(msg: string | null) {
    if (!msg) return 'Nachricht gelöscht';
    if (isGif(msg)) return '🎞 GIF';
    return msg.length > 40 ? msg.slice(0, 40) + '…' : msg;
}
function timeAgo(date: string) {
    const d = new Date(date);
    const diff = (Date.now() - d.getTime()) / 1000;
    if (diff < 60) return 'Jetzt';
    if (diff < 3600) return `${Math.floor(diff / 60)}m`;
    if (diff < 86400) return `${Math.floor(diff / 3600)}h`;
    return d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' });
}
function isMyMsg(msg: any) { return msg.sender_id === me.value?.id; }

const isFriendWith = (userId: number) => friends.value.some(f => f.id === userId);

const totalUnread    = computed(() => conversations.value.reduce((s, c) => s + (c.unread_count || 0), 0));
const isChatOpen     = computed(() => !!selectedPartner.value || guildChatActive.value);
const activeMessages = computed(() => guildChatActive.value ? guildMessages.value : messages.value);
const isActiveMyMsg  = (msg: any) => guildChatActive.value
    ? msg.user_id === me.value?.id
    : msg.sender_id === me.value?.id;

function formatDateLabel(dateStr: string): string {
    const date = new Date(dateStr);
    const today = new Date(); today.setHours(0, 0, 0, 0);
    const yesterday = new Date(today.getTime() - 86400000);
    const d = new Date(date); d.setHours(0, 0, 0, 0);
    if (d.getTime() === today.getTime()) return 'Heute';
    if (d.getTime() === yesterday.getTime()) return 'Gestern';
    return date.toLocaleDateString('de-DE', { day: '2-digit', month: 'long', year: 'numeric' });
}

const messageWithDates = computed(() => {
    const result: any[] = [];
    let lastDate = '';
    for (const msg of activeMessages.value) {
        const dateKey = new Date(msg.created_at).toDateString();
        if (dateKey !== lastDate) {
            result.push({ _divider: true, label: formatDateLabel(msg.created_at) });
            lastDate = dateKey;
        }
        result.push(msg);
    }
    return result;
});

watch(activeTab, (tab) => {
    if (tab === 'friends') loadFriends();
    else if (tab === 'requests') loadRequests();
    else if (tab === 'chats') loadConversations();
});

onMounted(async () => {
    await loadConversations();
    await loadFriends();
    await loadRequests();
    await loadMyGuild();
});
onUnmounted(() => { stopPolling(); stopGuildPolling(); });
</script>

<template>
    <UserLayout>
    <div class="social-hub">

        <!-- ── Left Panel ──────────────────────────────────── -->
        <div :class="['sh-left', { 'sh-left--hidden': isChatOpen }]">
            <div class="sh-left-head">
                <span class="sh-title">Social</span>
                <div class="sh-tabs">
                    <button :class="['sh-tab', { active: activeTab === 'chats' }]" @click="activeTab = 'chats'">
                        <MessageCircle :size="14" />
                        <span class="sh-tab-label">Chats</span>
                        <span v-if="totalUnread > 0" class="sh-badge">{{ totalUnread }}</span>
                    </button>
                    <button :class="['sh-tab', { active: activeTab === 'friends' }]" @click="activeTab = 'friends'">
                        <Users :size="14" />
                        <span class="sh-tab-label">Freunde</span>
                        <span v-if="friends.length" class="sh-badge sh-badge--muted">{{ friends.length }}</span>
                    </button>
                    <button :class="['sh-tab', { active: activeTab === 'requests' }]" @click="activeTab = 'requests'">
                        <Inbox :size="14" />
                        <span class="sh-tab-label">Anfragen</span>
                        <span v-if="requests.length" class="sh-badge sh-badge--warn">{{ requests.length }}</span>
                    </button>
                    <button :class="['sh-tab', { active: activeTab === 'search' }]" @click="activeTab = 'search'">
                        <Search :size="14" />
                        <span class="sh-tab-label">Suchen</span>
                    </button>
                </div>
            </div>

            <!-- Chats -->
            <div v-if="activeTab === 'chats'" class="sh-list">
                <!-- Guild chat entry -->
                <button v-if="myGuild" :class="['sh-conv-item', 'sh-conv-item--guild', { active: guildChatActive }]" @click="openGuildChat">
                    <div class="sh-ava sh-ava--guild">
                        <img v-if="myGuild.logo_url" :src="myGuild.logo_url" alt="">
                        <span v-else>{{ myGuild.tag?.[0] ?? '?' }}</span>
                    </div>
                    <div class="sh-conv-info">
                        <div class="sh-conv-row">
                            <span class="sh-conv-name">[{{ myGuild.tag }}] {{ myGuild.name }}</span>
                        </div>
                        <div class="sh-conv-row">
                            <span class="sh-conv-preview"><Shield :size="10" /> Gildenchat</span>
                        </div>
                    </div>
                </button>

                <div v-if="!conversations.length && !myGuild" class="sh-empty">
                    <MessageCircle :size="32" />
                    <strong>Noch keine Chats</strong>
                    <span>Suche nach Nutzern und schreib ihnen</span>
                </div>
                <button
                    v-for="conv in conversations"
                    :key="conv.partner.id"
                    :class="['sh-conv-item', { active: selectedPartner?.id === conv.partner.id }]"
                    @click="openChat(conv.partner)"
                >
                    <div class="sh-ava">
                        <img v-if="avatar(conv.partner)" :src="avatar(conv.partner)" alt="">
                        <span v-else>{{ initial(conv.partner) }}</span>
                    </div>
                    <div class="sh-conv-info">
                        <div class="sh-conv-row">
                            <span class="sh-conv-name">{{ conv.partner.username || conv.partner.name }}</span>
                            <span class="sh-conv-time" v-if="conv.last_message">{{ timeAgo(conv.last_message.created_at) }}</span>
                        </div>
                        <div class="sh-conv-row">
                            <span class="sh-conv-preview">{{ shortMsg(conv.last_message?.message) }}</span>
                            <span v-if="conv.unread_count > 0" class="sh-unread-pip">{{ conv.unread_count }}</span>
                        </div>
                    </div>
                </button>
            </div>

            <!-- Friends -->
            <div v-if="activeTab === 'friends'" class="sh-list">
                <div v-if="!friends.length" class="sh-empty">
                    <Users :size="32" />
                    <strong>Noch keine Freunde</strong>
                    <span>Suche nach Nutzern und füge sie hinzu</span>
                </div>
                <div v-for="f in friends" :key="f.id" class="sh-user-row">
                    <Link :href="`/profile/${f.username}`" class="sh-ava">
                        <img v-if="avatar(f)" :src="avatar(f)" alt="">
                        <span v-else>{{ initial(f) }}</span>
                    </Link>
                    <div class="sh-user-info">
                        <Link :href="`/profile/${f.username}`" class="sh-uname">{{ f.username || f.name }}</Link>
                    </div>
                    <button class="sh-icon-btn sh-icon-btn--primary" title="Nachricht" @click="openChat(f); activeTab = 'chats'">
                        <MessageCircle :size="14" />
                    </button>
                </div>
            </div>

            <!-- Requests -->
            <div v-if="activeTab === 'requests'" class="sh-list">
                <div v-if="!requests.length" class="sh-empty">
                    <Inbox :size="32" />
                    <strong>Keine Anfragen</strong>
                    <span>Eingehende Freundschaftsanfragen erscheinen hier</span>
                </div>
                <div v-for="req in requests" :key="req.id" class="sh-user-row">
                    <Link :href="`/profile/${req.from.username}`" class="sh-ava">
                        <img v-if="avatar(req.from)" :src="avatar(req.from)" alt="">
                        <span v-else>{{ initial(req.from) }}</span>
                    </Link>
                    <div class="sh-user-info">
                        <Link :href="`/profile/${req.from.username}`" class="sh-uname">{{ req.from.username || req.from.name }}</Link>
                        <span class="sh-sub"><Clock :size="10" /> {{ timeAgo(req.created_at) }}</span>
                    </div>
                    <div class="sh-row-actions">
                        <button class="sh-icon-btn sh-icon-btn--green" @click="acceptRequest(req.from.id)" title="Annehmen"><UserCheck :size="14" /></button>
                        <button class="sh-icon-btn sh-icon-btn--red" @click="declineRequest(req.from.id)" title="Ablehnen"><UserX :size="14" /></button>
                    </div>
                </div>
            </div>

            <!-- Search -->
            <div v-if="activeTab === 'search'" class="sh-list">
                <div class="sh-search-bar">
                    <Search :size="14" class="sh-search-ico" />
                    <input v-model="searchQuery" @input="doSearch" class="sh-search-inp" placeholder="Nutzer suchen..." type="text" autofocus />
                    <Loader2 v-if="searchLoading" :size="14" class="spin" />
                </div>
                <div v-if="!searchQuery" class="sh-empty">
                    <Search :size="32" />
                    <strong>Nutzer suchen</strong>
                    <span>Gib einen Nutzernamen ein</span>
                </div>
                <div v-else-if="!searchResults.length && !searchLoading" class="sh-empty">
                    <span>Keine Ergebnisse für „{{ searchQuery }}"</span>
                </div>
                <div v-for="u in searchResults" :key="u.id" class="sh-user-row">
                    <Link :href="`/profile/${u.username}`" class="sh-ava">
                        <img v-if="avatar(u)" :src="avatar(u)" alt="">
                        <span v-else>{{ initial(u) }}</span>
                    </Link>
                    <div class="sh-user-info">
                        <Link :href="`/profile/${u.username}`" class="sh-uname">{{ u.username || u.name }}</Link>
                        <span v-if="isFriendWith(u.id)" class="sh-sub sh-sub--green">Befreundet</span>
                    </div>
                    <div class="sh-row-actions">
                        <button v-if="!isFriendWith(u.id) && u.id !== me?.id" class="sh-icon-btn sh-icon-btn--green" title="Freund hinzufügen" @click="sendFriendRequest(u.id)">
                            <UserPlus :size="14" />
                        </button>
                        <button v-if="isFriendWith(u.id) && u.id !== me?.id" class="sh-icon-btn sh-icon-btn--primary" title="Nachricht" @click="openChat(u); activeTab = 'chats'">
                            <MessageCircle :size="14" />
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <!-- ── Right Panel ─────────────────────────────────── -->
        <div :class="['sh-right', { 'sh-right--active': isChatOpen }]">

            <!-- Empty state -->
            <div v-if="!isChatOpen" class="sh-right-empty">
                <div class="sh-empty-icon"><MessageCircle :size="28" /></div>
                <strong>Deine Nachrichten</strong>
                <span>Wähle einen Chat oder suche nach einem Nutzer</span>
            </div>

            <!-- Active chat -->
            <template v-else>
                <!-- Header -->
                <div class="sh-chat-head">
                    <button class="sh-back" @click="closeActiveChat">
                        <ChevronLeft :size="18" />
                    </button>
                    <!-- Guild header -->
                    <template v-if="guildChatActive">
                        <div class="sh-chat-user sh-chat-user--guild">
                            <div class="sh-ava sh-ava--sm sh-ava--guild">
                                <img v-if="myGuild?.logo_url" :src="myGuild.logo_url" alt="">
                                <span v-else>{{ myGuild?.tag?.[0] ?? '?' }}</span>
                            </div>
                            <div>
                                <span class="sh-chat-uname">[{{ myGuild?.tag }}] {{ myGuild?.name }}</span>
                                <span class="sh-chat-sub">{{ guildMembers.length }} Mitglieder</span>
                            </div>
                        </div>
                        <button :class="['sh-members-btn', { active: membersOpen }]" @click="membersOpen = !membersOpen" title="Mitgliederliste">
                            <Users :size="15" />
                        </button>
                    </template>
                    <!-- DM header -->
                    <template v-else>
                        <Link :href="`/profile/${selectedPartner.username}`" class="sh-chat-user">
                            <div class="sh-ava sh-ava--sm">
                                <img v-if="avatar(selectedPartner)" :src="avatar(selectedPartner)" alt="">
                                <span v-else>{{ initial(selectedPartner) }}</span>
                            </div>
                            <span class="sh-chat-uname">{{ selectedPartner.username || selectedPartner.name }}</span>
                        </Link>
                    </template>
                </div>

                <!-- Messages -->
                <div :class="['sh-messages', { 'sh-messages--shifted': membersOpen }]" id="dm-messages">
                    <div v-if="chatLoading || guildChatLoading" class="sh-loading-center"><Loader2 :size="22" class="spin" /></div>
                    <template v-else>
                        <template v-for="item in messageWithDates" :key="item._divider ? item.label : item.id">
                            <!-- Date divider -->
                            <div v-if="item._divider" class="sh-date-divider">
                                <span>{{ item.label }}</span>
                            </div>
                            <!-- System message -->
                            <div v-else-if="item.type === 'system'" class="sh-system-msg">
                                <span class="sh-system-inner">
                                    <Shield :size="11" />
                                    <b>{{ item.user?.username }}</b> {{ item.message }}
                                </span>
                            </div>
                            <!-- Regular message -->
                            <div v-else
                                :class="['sh-msg', { 'sh-msg--mine': isActiveMyMsg(item), 'sh-msg--del': item.is_deleted }]">

                                <div v-if="!isActiveMyMsg(item)" class="sh-msg-ava">
                                    <img v-if="avatar(item.user)" :src="avatar(item.user)" alt="">
                                    <span v-else>{{ initial(item.user) }}</span>
                                </div>

                                <div class="sh-msg-body">
                                    <span v-if="guildChatActive && !isActiveMyMsg(item)" class="sh-msg-sender">{{ item.user?.username }}</span>
                                    <div v-if="item.reply_to && !item.is_deleted" class="sh-reply-quote">
                                        <Reply :size="9" />
                                        <span>{{ shortMsg(item.reply_to.message) }}</span>
                                    </div>
                                    <div class="sh-bubble">
                                        <span v-if="item.is_deleted" class="sh-del-text">Nachricht gelöscht</span>
                                        <template v-else>
                                            <img v-if="isGif(item.message)" :src="gifUrl(item.message)" class="sh-gif" alt="GIF" />
                                            <span v-else>{{ item.message }}</span>
                                        </template>
                                    </div>
                                    <div v-if="!item.is_deleted" class="sh-msg-opts">
                                        <button @click="replyTo = item"><Reply :size="11" /></button>
                                        <button v-if="!isActiveMyMsg(item) && !guildChatActive" @click="openReport(item)"><Flag :size="11" /></button>
                                    </div>
                                    <span class="sh-msg-ts">{{ timeAgo(item.created_at) }}</span>
                                </div>
                            </div>
                        </template>
                    </template>
                </div>

                <!-- Guild member list panel -->
                <div v-if="guildChatActive && membersOpen" class="sh-members-panel">
                    <div class="sh-members-head">
                        <Shield :size="13" />
                        <span>Mitglieder ({{ guildMembers.length }})</span>
                        <button @click="membersOpen = false"><X :size="13" /></button>
                    </div>
                    <div class="sh-members-list">
                        <div v-for="m in guildMembers" :key="m.id" class="sh-member-row">
                            <div class="sh-ava sh-ava--xs">
                                <img v-if="avatar(m)" :src="avatar(m)" alt="">
                                <span v-else>{{ initial(m) }}</span>
                            </div>
                            <span class="sh-member-name">{{ m.username }}</span>
                            <span :class="['sh-member-role', `sh-member-role--${m.role}`]">{{ m.role }}</span>
                        </div>
                    </div>
                </div>

                <!-- Reply bar -->
                <div v-if="replyTo" class="sh-reply-bar">
                    <Reply :size="12" />
                    <span>{{ shortMsg(replyTo.message) }}</span>
                    <button @click="replyTo = null"><X :size="12" /></button>
                </div>

                <!-- Emoji picker -->
                <div v-if="emojiOpen" class="sh-emoji-wrap" ref="emojiPickerEl"></div>

                <!-- GIF picker -->
                <div v-if="giphyOpen" class="sh-gif-panel">
                    <div class="sh-gif-top">
                        <Search :size="12" />
                        <input v-model="giphyQuery" @input="onGiphyInput" placeholder="GIF suchen..." />
                    </div>
                    <div class="sh-gif-grid">
                        <div v-if="giphyLoading" class="sh-gif-spin"><Loader2 :size="18" class="spin" /></div>
                        <img v-else v-for="g in giphyResults" :key="g.id"
                            :src="g.images.fixed_height_small.url"
                            @click="sendGif(g.images.original.url)" alt="GIF" />
                    </div>
                </div>

                <!-- Input -->
                <div class="sh-input-row">
                    <button :class="['sh-tool', { on: emojiOpen }]" @click="toggleEmoji"><Smile :size="17" /></button>
                    <button :class="['sh-tool', { on: giphyOpen }]" @click="toggleGiphy"><ImagePlay :size="17" /></button>
                    <textarea id="dm-input" v-model="input" class="sh-inp" :placeholder="guildChatActive ? 'Nachricht an Gilde...' : 'Nachricht...'" rows="1"
                        @keydown.enter.exact.prevent="send" />
                    <button class="sh-send" :disabled="!input.trim() || sending" @click="send">
                        <Loader2 v-if="sending" :size="15" class="spin" />
                        <Send v-else :size="15" />
                    </button>
                </div>
            </template>
        </div>

        <!-- ── Report Modal ─────────────────────────────────── -->
        <Teleport to="body">
            <div v-if="reportModal" class="sh-overlay" @click.self="closeReport">
                <div class="sh-modal">
                    <div class="sh-modal-head">
                        <span>Nachricht melden</span>
                        <button @click="closeReport"><X :size="15" /></button>
                    </div>
                    <div v-if="reportDone" class="sh-modal-ok">
                        <CheckCircle2 :size="30" color="#22c55e" />
                        <p>Gemeldet — Danke!</p>
                    </div>
                    <template v-else>
                        <p class="sh-modal-quote">„{{ shortMsg(reportModal.msg.message) }}"</p>
                        <div class="sh-reasons">
                            <button v-for="r in reportReasons" :key="r.value"
                                :class="['sh-reason', { active: reportReason === r.value }]"
                                @click="reportReason = r.value">
                                <component :is="r.icon" :size="14" :style="{ color: r.color }" />
                                <div>
                                    <b>{{ r.label }}</b>
                                    <span>{{ r.desc }}</span>
                                </div>
                            </button>
                        </div>
                        <button class="sh-submit" :disabled="!reportReason || reportSubmitting" @click="submitReport">
                            <Loader2 v-if="reportSubmitting" :size="13" class="spin" />
                            <Flag v-else :size="13" />
                            Absenden
                        </button>
                    </template>
                </div>
            </div>
        </Teleport>

    </div>
    </UserLayout>
</template>

<style scoped>
/* ── Layout ──────────────────────────────────────────── */
.social-hub {
    display: flex;
    height: calc(100vh - 76px);
    overflow: hidden;
    background: var(--bg-deep, #050505);
    position: relative;
}

/* Background animation orbs */
.social-hub::before {
    content: '';
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse 60% 50% at 10% 90%, rgba(223,0,106,0.055) 0%, transparent 70%),
        radial-gradient(ellipse 50% 40% at 90% 10%, rgba(120,40,200,0.035) 0%, transparent 70%);
    animation: hub-orb 18s ease-in-out infinite alternate;
    pointer-events: none;
    z-index: 0;
}
.social-hub > * { position: relative; z-index: 1; }

@keyframes hub-orb {
    0%   { opacity: 0.6; transform: scale(1)    translate(0, 0); }
    50%  { opacity: 1;   transform: scale(1.04) translate(1%, 0.5%); }
    100% { opacity: 0.7; transform: scale(1.02) translate(-0.5%, 1%); }
}

/* ── Left panel ──────────────────────────────────────── */
.sh-left {
    width: 300px;
    min-width: 300px;
    display: flex;
    flex-direction: column;
    border-right: 1px solid #181818;
    background: #070707;
    overflow: hidden;
    transition: transform 0.22s ease;
}

.sh-left-head {
    padding: 18px 14px 0;
    flex-shrink: 0;
}

.sh-title {
    font-size: 18px;
    font-weight: 900;
    color: #fff;
    display: block;
    margin-bottom: 12px;
    letter-spacing: -0.4px;
    background: linear-gradient(90deg, #fff 60%, rgba(223,0,106,0.7));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

/* Tabs */
.sh-tabs {
    display: flex;
    border-bottom: 1px solid #161616;
}
.sh-tab {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 8px 4px;
    border: none;
    background: transparent;
    color: #484848;
    font-size: 11px;
    font-weight: 700;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color 0.15s, border-color 0.15s;
    white-space: nowrap;
}
.sh-tab:hover { color: #888; }
.sh-tab.active { color: #fff; border-bottom-color: var(--primary); }

.sh-badge {
    background: var(--primary);
    color: #fff;
    border-radius: 99px;
    font-size: 9px;
    font-weight: 900;
    padding: 1px 5px;
    min-width: 15px;
    text-align: center;
    line-height: 1.4;
}
.sh-badge--warn { background: #f59e0b; }
.sh-badge--muted { background: #333; color: #888; }

/* List area */
.sh-list {
    flex: 1;
    overflow-y: auto;
    padding: 6px 0;
}

/* Empty state */
.sh-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    color: #333;
    padding: 40px 24px;
    text-align: center;
}
.sh-empty strong { font-size: 13px; color: #484848; }
.sh-empty span { font-size: 11.5px; line-height: 1.4; }

/* Conversation row */
.sh-conv-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    background: transparent;
    border: none;
    width: 100%;
    text-align: left;
    cursor: pointer;
    transition: background 0.12s;
    color: inherit;
}
.sh-conv-item:hover { background: #0d0d0d; }
.sh-conv-item.active { background: rgba(223,0,106,0.06); border-right: 2px solid var(--primary); }

.sh-conv-info { flex: 1; min-width: 0; }
.sh-conv-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}
.sh-conv-name { font-size: 13px; font-weight: 700; color: #e0e0e0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-conv-time { font-size: 10px; color: #353535; flex-shrink: 0; }
.sh-conv-preview { font-size: 11.5px; color: #424242; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; margin-top: 2px; }
.sh-unread-pip {
    background: var(--primary);
    color: #fff;
    border-radius: 99px;
    font-size: 9px;
    font-weight: 900;
    padding: 1px 5px;
    min-width: 15px;
    text-align: center;
    flex-shrink: 0;
}

/* Avatar */
.sh-ava {
    width: 38px; height: 38px;
    border-radius: 50%;
    background: #1a1a1a;
    border: 1px solid #272727;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px; font-weight: 900; color: #ddd;
    overflow: hidden; flex-shrink: 0; text-decoration: none;
}
.sh-ava img { width: 100%; height: 100%; object-fit: cover; }
.sh-ava--sm { width: 32px; height: 32px; font-size: 12px; }

/* Friend / search / request row */
.sh-user-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    transition: background 0.12s;
}
.sh-user-row:hover { background: #0d0d0d; }

.sh-user-info { flex: 1; min-width: 0; }
.sh-uname { font-size: 13px; font-weight: 700; color: #ddd; text-decoration: none; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-uname:hover { color: var(--primary); }
.sh-sub { font-size: 10px; color: #444; display: flex; align-items: center; gap: 3px; margin-top: 1px; }
.sh-sub--green { color: #22c55e; }

/* Action buttons */
.sh-row-actions { display: flex; gap: 4px; flex-shrink: 0; }
.sh-icon-btn {
    width: 30px; height: 30px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.06);
    background: transparent;
    color: #484848;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: all 0.15s;
}
.sh-icon-btn--green:hover  { background: rgba(34,197,94,0.1);  border-color: rgba(34,197,94,0.2);  color: #22c55e; }
.sh-icon-btn--red:hover    { background: rgba(239,68,68,0.1);   border-color: rgba(239,68,68,0.2);   color: #ef4444; }
.sh-icon-btn--primary:hover{ background: rgba(223,0,106,0.1);  border-color: rgba(223,0,106,0.2);  color: var(--primary); }

/* Search bar in panel */
.sh-search-bar {
    display: flex; align-items: center; gap: 8px;
    margin: 10px 14px 6px;
    padding: 7px 10px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: 9px;
}
.sh-search-ico { color: #444; flex-shrink: 0; }
.sh-search-inp {
    flex: 1; background: transparent; border: none; outline: none;
    color: #fff; font-size: 13px;
}

/* ── Right panel ──────────────────────────────────────── */
.sh-right {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: relative;
    min-width: 0;
}

.sh-right-empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    color: #2a2a2a;
    text-align: center;
    padding: 40px;
}
.sh-right-empty strong { font-size: 15px; color: #3a3a3a; }
.sh-right-empty span { font-size: 12px; line-height: 1.5; color: #2e2e2e; }
.sh-empty-icon {
    width: 64px; height: 64px;
    border-radius: 50%;
    background: radial-gradient(circle, #111 0%, #080808 100%);
    border: 1px solid rgba(223,0,106,0.12);
    box-shadow: 0 0 24px rgba(223,0,106,0.06);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 4px;
    color: #272727;
}

/* Chat header */
.sh-chat-head {
    height: 54px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 14px;
    border-bottom: 1px solid #141414;
    background: #070707;
    flex-shrink: 0;
}
.sh-back {
    width: 30px; height: 30px; border-radius: 8px;
    background: transparent; border: none; color: #555;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: 0.15s; flex-shrink: 0;
}
.sh-back:hover { background: #111; color: #fff; }
.sh-chat-user { display: flex; align-items: center; gap: 9px; text-decoration: none; }
.sh-chat-uname { font-size: 14px; font-weight: 800; color: #fff; }
.sh-chat-uname:hover { color: var(--primary); }

/* Messages */
.sh-messages {
    flex: 1;
    overflow-y: auto;
    padding: 14px 14px 6px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.sh-loading-center { flex: 1; display: flex; align-items: center; justify-content: center; color: #333; }

.sh-msg {
    display: flex;
    align-items: flex-end;
    gap: 7px;
    max-width: 72%;
}
.sh-msg--mine { align-self: flex-end; flex-direction: row-reverse; }

.sh-msg-ava {
    width: 26px; height: 26px; border-radius: 50%;
    background: #1a1a1a; border: 1px solid #272727;
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 900; color: #ddd;
    overflow: hidden; flex-shrink: 0;
}
.sh-msg-ava img { width: 100%; height: 100%; object-fit: cover; }

.sh-msg-body { display: flex; flex-direction: column; gap: 2px; position: relative; min-width: 0; }
.sh-msg--mine .sh-msg-body { align-items: flex-end; }

.sh-reply-quote {
    display: flex; align-items: center; gap: 4px;
    font-size: 10px; color: #555;
    background: rgba(255,255,255,0.03);
    border-left: 2px solid #333;
    padding: 3px 7px;
    border-radius: 4px;
    max-width: 220px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sh-bubble {
    background: #111;
    border: 1px solid #1e1e1e;
    border-radius: 16px 16px 16px 4px;
    padding: 8px 12px;
    font-size: 13.5px; color: #d8d8d8;
    line-height: 1.5; word-break: break-word;
    box-shadow: 0 1px 4px rgba(0,0,0,0.3);
}
.sh-msg--mine .sh-bubble {
    background: var(--primary);
    border-color: transparent;
    border-radius: 16px 16px 4px 16px;
    color: #fff;
    box-shadow: 0 2px 8px rgba(223,0,106,0.25);
}
.sh-msg--del .sh-bubble { opacity: 0.45; }
.sh-del-text { font-style: italic; color: #555; font-size: 12px; }
.sh-gif { max-width: 200px; max-height: 150px; border-radius: 8px; display: block; }

.sh-msg-ts { font-size: 9px; color: #333; padding: 0 2px; align-self: flex-end; }

/* Hover opts */
.sh-msg-opts {
    display: none;
    gap: 2px;
    position: absolute;
    top: -24px;
    right: 0;
    background: #111;
    border: 1px solid #222;
    border-radius: 7px;
    padding: 3px 5px;
    z-index: 2;
}
.sh-msg--mine .sh-msg-opts { right: auto; left: 0; }
.sh-msg-body:hover .sh-msg-opts { display: flex; }
.sh-msg-opts button {
    background: transparent; border: none; color: #555;
    cursor: pointer; display: flex; align-items: center;
    padding: 3px; border-radius: 4px; transition: 0.12s;
}
.sh-msg-opts button:hover { color: #ccc; }

/* Reply bar */
.sh-reply-bar {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 14px;
    background: rgba(255,255,255,0.02);
    border-top: 1px solid #151515;
    font-size: 12px; color: #555;
    flex-shrink: 0;
}
.sh-reply-bar span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-reply-bar button { background: transparent; border: none; color: #444; cursor: pointer; display: flex; align-items: center; transition: 0.12s; }
.sh-reply-bar button:hover { color: #aaa; }

/* Emoji */
.sh-emoji-wrap {
    position: absolute; bottom: 56px; left: 10px; z-index: 50;
}
.sh-emoji-wrap :deep(em-emoji-picker) { --shadow: none; --border-radius: 12px; height: 320px; }

/* GIF panel */
.sh-gif-panel {
    position: absolute; bottom: 56px; left: 10px;
    width: 320px;
    background: #0e0e0e; border: 1px solid #1e1e1e; border-radius: 12px;
    z-index: 50; overflow: hidden;
}
.sh-gif-top {
    display: flex; align-items: center; gap: 7px;
    padding: 8px 11px; border-bottom: 1px solid #181818; color: #555;
}
.sh-gif-top input { flex: 1; background: transparent; border: none; outline: none; color: #fff; font-size: 12.5px; }
.sh-gif-grid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 3px;
    padding: 6px; max-height: 240px; overflow-y: auto;
}
.sh-gif-grid img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 5px; cursor: pointer; transition: 0.12s; }
.sh-gif-grid img:hover { opacity: 0.8; }
.sh-gif-spin { grid-column: 1/-1; display: flex; justify-content: center; padding: 18px; color: #333; }

/* Input row */
.sh-input-row {
    display: flex; align-items: flex-end; gap: 5px;
    padding: 8px 10px;
    border-top: 1px solid #131313;
    background: #070707;
    flex-shrink: 0;
}
.sh-tool {
    width: 32px; height: 32px; border-radius: 8px;
    background: transparent; border: none; color: #404040;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: 0.12s; flex-shrink: 0;
}
.sh-tool:hover, .sh-tool.on { color: var(--primary); background: rgba(223,0,106,0.07); }
.sh-inp {
    flex: 1;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.07);
    border-radius: 10px;
    padding: 7px 12px;
    color: #fff; font-size: 13.5px; font-family: inherit;
    outline: none; resize: none; max-height: 100px; line-height: 1.4;
}
.sh-inp:focus { border-color: rgba(223,0,106,0.22); }
.sh-send {
    width: 34px; height: 34px; border-radius: 9px;
    background: var(--primary); border: none; color: #fff;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: 0.15s; flex-shrink: 0;
}
.sh-send:hover:not(:disabled) { box-shadow: 0 3px 12px rgba(223,0,106,0.3); transform: translateY(-1px); }
.sh-send:disabled { opacity: 0.35; cursor: default; }

/* ── Report Modal ─────────────────────────────────────── */
.sh-overlay {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.75); backdrop-filter: blur(4px);
    display: flex; align-items: center; justify-content: center; z-index: 1000;
}
.sh-modal {
    background: #0d0d0d; border: 1px solid #1e1e1e; border-radius: 16px;
    width: 360px; max-width: 95vw; overflow: hidden;
}
.sh-modal-head {
    display: flex; justify-content: space-between; align-items: center;
    padding: 14px 16px; border-bottom: 1px solid #181818;
    font-size: 14px; font-weight: 800; color: #fff;
}
.sh-modal-head button { background: transparent; border: none; color: #555; cursor: pointer; display: flex; align-items: center; transition: 0.12s; }
.sh-modal-head button:hover { color: #fff; }
.sh-modal-ok { padding: 36px; display: flex; flex-direction: column; align-items: center; gap: 10px; font-size: 14px; color: #888; }
.sh-modal-quote { padding: 10px 16px; font-size: 12px; color: #555; font-style: italic; border-bottom: 1px solid #181818; margin: 0; }
.sh-reasons { display: flex; flex-direction: column; gap: 3px; padding: 8px 10px; }
.sh-reason {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 10px; border-radius: 9px;
    border: 1px solid transparent; background: transparent;
    cursor: pointer; text-align: left; transition: 0.12s; color: inherit; width: 100%;
}
.sh-reason:hover { background: rgba(255,255,255,0.04); }
.sh-reason.active { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.1); }
.sh-reason b { display: block; font-size: 12.5px; color: #ddd; }
.sh-reason span { font-size: 11px; color: #555; }
.sh-submit {
    display: flex; align-items: center; justify-content: center; gap: 6px;
    width: calc(100% - 20px); margin: 4px 10px 12px;
    height: 38px; border-radius: 9px;
    background: var(--primary); border: none; color: #fff;
    font-size: 13px; font-weight: 800; cursor: pointer; transition: 0.15s;
}
.sh-submit:disabled { opacity: 0.4; cursor: default; }
.sh-submit:not(:disabled):hover { box-shadow: 0 3px 12px rgba(223,0,106,0.3); transform: translateY(-1px); }

/* ── Responsive ───────────────────────────────────────── */
@media (max-width: 768px) {
    .sh-left {
        position: absolute;
        inset: 0;
        width: 100%;
        min-width: 0;
        z-index: 2;
    }
    /* Hide left when chat is open on mobile */
    .sh-left--hidden {
        transform: translateX(-100%);
        pointer-events: none;
    }
    .sh-right {
        position: absolute;
        inset: 0;
        z-index: 3;
        transform: translateX(100%);
        transition: transform 0.22s ease;
        background: var(--bg-deep, #050505);
    }
    .sh-right--active {
        transform: translateX(0);
    }
    /* Always show back button on mobile */
    .sh-back { display: flex !important; }
}
@media (min-width: 769px) {
    .sh-back { display: none; }
    .sh-tab-label { display: inline; }
}

@keyframes spin { to { transform: rotate(360deg); } }
.spin { animation: spin 0.7s linear infinite; }

/* ── Date divider ────────────────────────────────────── */
.sh-date-divider {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 10px 0 6px;
    color: #2e2e2e;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    flex-shrink: 0;
}
.sh-date-divider::before,
.sh-date-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: #181818;
}
.sh-date-divider span { white-space: nowrap; }

/* ── System message ──────────────────────────────────── */
.sh-system-msg {
    display: flex;
    justify-content: center;
    margin: 4px 0;
}
.sh-system-inner {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: rgba(223,0,106,0.06);
    border: 1px solid rgba(223,0,106,0.12);
    border-radius: 99px;
    padding: 3px 12px;
    font-size: 11px;
    color: #666;
}
.sh-system-inner svg { color: rgba(223,0,106,0.5); flex-shrink: 0; }
.sh-system-inner b { color: #999; font-weight: 700; }

/* ── Guild chat ──────────────────────────────────────── */
.sh-conv-item--guild {
    border-left: 2px solid var(--primary, #df006a);
    background: rgba(223,0,106,0.03);
}
.sh-conv-item--guild:hover { background: rgba(223,0,106,0.06); }
.sh-conv-item--guild.active { background: rgba(223,0,106,0.08); }

.sh-ava--guild {
    background: linear-gradient(135deg, #1a0a12 0%, #2d0f1e 100%);
    border: 1px solid rgba(223,0,106,0.35);
    color: var(--primary, #df006a);
    font-weight: 700;
}
.sh-ava--xs { width: 26px; height: 26px; font-size: 9px; }

.sh-chat-user { flex: 1; min-width: 0; }
.sh-chat-user--guild { flex-direction: row; align-items: center; gap: 10px; }
.sh-chat-sub {
    display: block;
    font-size: 11px;
    color: #555;
    margin-top: 1px;
}

.sh-members-btn {
    width: 30px; height: 30px; border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.06);
    background: transparent; color: #444;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; transition: 0.15s; flex-shrink: 0; margin-left: auto;
}
.sh-members-btn:hover, .sh-members-btn.active {
    background: rgba(223,0,106,0.1);
    border-color: rgba(223,0,106,0.2);
    color: var(--primary);
}

.sh-msg-sender {
    font-size: 11px;
    font-weight: 700;
    color: var(--primary, #df006a);
    margin-bottom: 2px;
    display: block;
}

/* ── Member list panel ───────────────────────────────── */
.sh-messages--shifted { /* no layout shift needed — panel overlays */ }

.sh-members-panel {
    position: absolute;
    top: 54px; /* below header */
    right: 0;
    bottom: 0;
    width: 210px;
    background: #080808;
    border-left: 1px solid #181818;
    display: flex;
    flex-direction: column;
    z-index: 10;
    animation: slide-in-right 0.18s ease;
}
@keyframes slide-in-right {
    from { transform: translateX(100%); opacity: 0; }
    to   { transform: translateX(0);   opacity: 1; }
}

.sh-members-head {
    display: flex; align-items: center; gap: 7px;
    padding: 10px 12px;
    border-bottom: 1px solid #161616;
    font-size: 12px; font-weight: 800; color: #888;
}
.sh-members-head svg { color: rgba(223,0,106,0.6); }
.sh-members-head span { flex: 1; }
.sh-members-head button {
    background: transparent; border: none; color: #444;
    cursor: pointer; display: flex; align-items: center;
    padding: 2px; border-radius: 4px; transition: 0.12s;
}
.sh-members-head button:hover { color: #ccc; }

.sh-members-list {
    flex: 1; overflow-y: auto; padding: 6px 0;
}
.sh-member-row {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 12px;
    transition: background 0.12s;
}
.sh-member-row:hover { background: #0d0d0d; }

.sh-member-name {
    flex: 1; font-size: 12px; font-weight: 600; color: #ccc;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sh-member-role {
    font-size: 9px; font-weight: 800; letter-spacing: 0.4px;
    text-transform: uppercase; border-radius: 4px;
    padding: 1px 6px; flex-shrink: 0;
}
.sh-member-role--owner   { background: rgba(223,0,106,0.15); color: var(--primary); }
.sh-member-role--officer { background: rgba(245,158,11,0.12); color: #f59e0b; }
.sh-member-role--member  { background: rgba(255,255,255,0.05); color: #555; }
</style>
