<template>
    <Head title="Campaigns" />
    <AppLayout>
        <!-- Page header -->
        <div class="page-header">
            <div class="page-header__left">
                <h1>Campaigns</h1>
                <p>Create, manage, and track your email campaigns all in one place.</p>
            </div>
            <div class="page-header__actions">
                <button class="btn btn-primary" @click="showCreate = true">
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="16" height="16">
                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/>
                    </svg>
                    Create campaign
                </button>
            </div>
        </div>

        <!-- Campaign list -->
        <!-- Campaign list -->
        <div class="table-wrap">
            <div class="table-toolbar" :class="{ 'has-selection': selected.length > 0 }">
                <div v-if="selected.length === 0" class="table-toolbar-left">
                    <div class="table-search">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/></svg>
                        <input v-model="search" type="search" placeholder="Search campaigns…" @input="onSearch">
                    </div>
                    <CwSelect
                        v-model="statusFilter"
                        :options="statusOptions"
                        @change="onSearch"
                        style="width: 140px;"
                    />
                </div>
                <div v-else class="table-toolbar-left">
                    <div class="selection-status">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" width="16" height="16" style="color: var(--active-text);"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
                        <span class="selection-count">{{ selected.length }} campaign{{ selected.length === 1 ? '' : 's' }} selected</span>
                    </div>
                </div>
                <div class="table-toolbar-right">
                    <template v-if="selected.length > 0">
                        <button class="btn btn-outline" style="color: var(--danger); border-color: var(--danger-border);" @click="showBulkDelete = true">Delete</button>
                        <button class="btn btn-outline" @click="selected = []">Cancel</button>
                    </template>
                    <template v-else>
                        <span class="cw-pagination-info">
                            {{ campaigns.from ?? 0 }}–{{ campaigns.to ?? 0 }} of {{ campaigns.total }}
                        </span>
                        <button class="cw-pg-btn" :disabled="!campaigns.prev_page_url" @click="goPage(campaigns.current_page - 1)">
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="14" height="14"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5"/></svg>
                        </button>
                        <button class="cw-pg-btn" :disabled="!campaigns.next_page_url" @click="goPage(campaigns.current_page + 1)">
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="14" height="14"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5"/></svg>
                        </button>
                    </template>
                </div>
            </div>

            <div class="table-scroll">
                <table class="data-table">
                    <thead>
                        <tr>
                            <th style="width:40px"><input type="checkbox" class="table-checkbox" :checked="allSelected" @change="toggleAll"></th>
                            <th>Name</th>
                            <th>Recipients</th>
                            <th>Opens</th>
                            <th>Clicks</th>
                            <th>Unsubscribed</th>
                            <th>Status</th>
                            <th style="width:120px">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-if="campaigns.data.length === 0">
                            <td colspan="8" style="text-align:center;padding:48px 24px;color:#9ca3af">
                                No campaigns yet. <button class="link-btn" @click="showCreate = true">Create your first one.</button>
                            </td>
                        </tr>
                        <tr v-for="c in campaigns.data" :key="c.id" :class="{ 'is-selected': selected.includes(c.id) }">
                            <td class="cell-checkbox"><input type="checkbox" class="table-checkbox" :value="c.id" v-model="selected"></td>
                            <td data-label="Name" class="cell-name cell-title">
                                <div class="automation-title-container">
                                    <Link :href="isDraft(c) ? route('campaigns.edit', c.id) : route('campaigns.show', c.id)" class="automation-title-link">
                                        {{ c.title }}
                                    </Link>
                                </div>
                                <div class="automation-title-sub">
                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"/></svg>
                                    Subject: {{ c.email_subject || 'No subject' }}
                                    <span v-if="c.scheduled_at && ['scheduled','queued'].includes(c.status)"> · {{ formatDateTime(c.scheduled_at) }}</span>
                                    <span v-else-if="isSent(c)"> · Sent {{ formatDate(c.updated_at) }}</span>
                                </div>
                            </td>
                            <td data-label="Recipients" style="font-size:13px">{{ isSent(c) || c.status === 'sending' ? (c.emails_sent ?? 0).toLocaleString() : '-' }}</td>
                            <td data-label="Opens" style="font-size:13px">
                                <template v-if="isSent(c) && c.unique_opens > 0">
                                    {{ c.unique_opens.toLocaleString() }} <span style="font-size:11px;color:var(--text-muted)">({{ openRate(c) }}%)</span>
                                </template>
                                <span v-else-if="isSent(c)">0</span>
                                <span v-else>-</span>
                            </td>
                            <td data-label="Clicks" style="font-size:13px">
                                <template v-if="isSent(c) && c.unique_clicks > 0">
                                    {{ c.unique_clicks.toLocaleString() }} <span style="font-size:11px;color:var(--text-muted)">({{ clickRate(c) }}%)</span>
                                </template>
                                <span v-else-if="isSent(c)">0</span>
                                <span v-else>-</span>
                            </td>
                            <td data-label="Unsubscribed" style="font-size:13px">
                                <span v-if="isSent(c) && c.unsubscribes_count > 0" style="color:var(--danger)">{{ c.unsubscribes_count.toLocaleString() }}</span>
                                <span v-else-if="isSent(c)">0</span>
                                <span v-else>-</span>
                            </td>
                            <td data-label="Status">
                                <span :class="['badge', c.status === 'sent' ? 'badge--success' : c.status === 'sending' ? 'badge--info' : c.status === 'scheduled' ? 'badge--warning' : 'badge--gray']">
                                    {{ statusLabel(c) }}
                                </span>
                            </td>
                            <td class="cell-actions" data-label="">
                                <div style="display:flex;gap:6px">
                                    <!-- Edit -->
                                    <Link v-if="isDraft(c)" :href="route('campaigns.edit', c.id)" class="re-action-btn" title="Edit Campaign">
                                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#2563eb"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931z"/></svg>
                                    </Link>
                                    <button v-else class="re-action-btn is-disabled" disabled title="Cannot edit a sent campaign">
                                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#9ca3af"><path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931z"/></svg>
                                    </button>
                                    <!-- Report -->
                                    <Link v-if="isSent(c) || c.status === 'sending'" :href="route('campaigns.show', c.id)" class="re-action-btn" title="View Report">
                                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#0f766e"><path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v5.25c0 .621-.504 1.125-1.125 1.125h-2.25A1.125 1.125 0 013 18.375v-5.25zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125v-9.75zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v14.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"/></svg>
                                    </Link>
                                    <button v-else class="re-action-btn is-disabled" disabled title="No report available for draft campaign">
                                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#9ca3af"><path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v5.25c0 .621-.504 1.125-1.125 1.125h-2.25A1.125 1.125 0 013 18.375v-5.25zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125v-9.75zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v14.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"/></svg>
                                    </button>
                                    <!-- Delete -->
                                    <button class="re-action-btn" title="Delete Campaign" @click="confirmDelete(c)">
                                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="#ef4444"><path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"/></svg>
                                    </button>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <!-- Create modal -->
        <div v-if="showCreate" class="modal-overlay is-open" @click.self="showCreate = false">
            <div class="modal" style="width:520px;max-width:96vw">
                <div class="modal-header">
                    <h2 class="modal-title">New Campaign</h2>
                    <button class="modal-close" @click="showCreate = false">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
                    </button>
                </div>
                <div class="modal-body" style="padding:24px">
                    <label class="form-label">Campaign title</label>
                    <input
                        v-model="newTitle"
                        type="text"
                        class="form-input"
                        placeholder="e.g. July Newsletter"
                        style="font-size:15px;padding:12px 14px"
                        ref="newTitleInputRef"
                        @keydown.enter="createCampaign"
                    />
                </div>
                <div class="modal-footer" style="justify-content:flex-end">
                    <button class="btn btn-ghost" @click="showCreate = false">Cancel</button>
                    <button class="btn btn-primary" @click="createCampaign" :disabled="creating">
                        <span v-if="creating">Creating…</span>
                        <span v-else>Create Campaign</span>
                    </button>
                </div>
            </div>
        </div>

        <!-- Bulk delete confirm modal -->
        <div v-if="showBulkDelete" class="modal-overlay is-open" @click.self="showBulkDelete = false">
            <div class="modal modal--sm">
                <div class="modal-header">
                    <h3 class="modal-title">Delete {{ selected.length }} {{ selected.length === 1 ? 'Campaign' : 'Campaigns' }}</h3>
                    <button class="modal-close" @click="showBulkDelete = false">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
                    </button>
                </div>
                <div class="modal-body">
                    <p style="color:#6b7280;font-size:14px">
                        Are you sure you want to delete the <strong>{{ selected.length }}</strong> selected
                        {{ selected.length === 1 ? 'campaign' : 'campaigns' }}? This cannot be undone.
                    </p>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-ghost" @click="showBulkDelete = false">Cancel</button>
                    <button class="btn btn-danger" @click="bulkDelete" :disabled="bulkDeleting">
                        <span v-if="bulkDeleting">Deleting…</span>
                        <span v-else>Delete</span>
                    </button>
                </div>
            </div>
        </div>

        <!-- Delete confirm modal -->
        <div v-if="deleteTarget" class="modal-overlay is-open" @click.self="deleteTarget = null">
            <div class="modal modal--sm">
                <div class="modal-header">
                    <h3 class="modal-title">Delete Campaign</h3>
                    <button class="modal-close" @click="deleteTarget = null">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
                    </button>
                </div>
                <div class="modal-body">
                    <p style="color:#6b7280;font-size:14px">Are you sure you want to delete <strong>{{ deleteTarget.title }}</strong>? This cannot be undone.</p>
                </div>
                <div class="modal-footer">
                    <button class="btn btn-ghost" @click="deleteTarget = null">Cancel</button>
                    <button class="btn btn-danger" @click="deleteCampaign" :disabled="deleting">
                        <span v-if="deleting">Deleting…</span>
                        <span v-else>Delete</span>
                    </button>
                </div>
            </div>
        </div>
    </AppLayout>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
import { Link, router, Head } from '@inertiajs/vue3';
import AppLayout from '@/Layouts/AppLayout.vue';
import CwSelect from '@/Components/CwSelect.vue';
import { useTenantTimezone } from '@/Composables/useTenantTimezone';

const { formatDate: formatDateTz, formatDateTime: formatDateTimeTz } = useTenantTimezone();

const props = defineProps({
    campaigns: Object,
    filters:   Object,
});

const search       = ref(props.filters?.search ?? '');
const statusFilter = ref(props.filters?.status ?? '');

const statusOptions = [
    { value: '', label: 'All statuses' },
    { value: 'draft', label: 'Draft' },
    { value: 'scheduled', label: 'Scheduled' },
    { value: 'queued', label: 'Queued' },
    { value: 'sending', label: 'Sending' },
    { value: 'sent', label: 'Sent' }
];
const showCreate   = ref(false);
const newTitle     = ref('');
const newTitleInputRef = ref(null);

watch(showCreate, (val) => {
    if (val) {
        nextTick(() => {
            newTitleInputRef.value?.focus();
        });
    }
});
const creating     = ref(false);
const deleteTarget   = ref(null);
const deleting       = ref(false);
const selected       = ref([]);
const openMenu       = ref(null);
const showBulkDelete = ref(false);
const bulkDeleting   = ref(false);

const allSelected = computed(() =>
    props.campaigns.data.length > 0 &&
    props.campaigns.data.every(c => selected.value.includes(c.id))
);

function toggleAll(e) {
    selected.value = e.target.checked ? props.campaigns.data.map(c => c.id) : [];
}

function isDraft(c) {
    return ['draft', 'new'].includes(c.status);
}
function isSent(c) {
    return ['sent', 'sending'].includes(c.status);
}

function statusLabel(c) {
    const map = { draft: 'Draft', new: 'New', scheduled: 'Scheduled', queued: 'Processing', sending: 'Sending', sent: 'Sent', paused: 'Paused' };
    return map[c.status] ?? c.status;
}
function statusClass(status) {
    return {
        draft:     'cw-badge--draft',
        new:       'cw-badge--new',
        scheduled: 'cw-badge--scheduled',
        queued:    'cw-badge--queued',
        sending:   'cw-badge--sending',
        sent:      'cw-badge--sent',
        paused:    'cw-badge--paused',
    }[status] ?? 'cw-badge--draft';
}

function formatDate(iso) {
    if (!iso) return '';
    return formatDateTz(iso);
}
function formatDateTime(iso) {
    if (!iso) return '';
    return formatDateTimeTz(iso);
}

function toggleMenu(id) {
    openMenu.value = openMenu.value === id ? null : id;
}
function closeMenu() { openMenu.value = null; }

function progressPct(c) {
    if (!c.recipients_count) return 0;
    return Math.min(100, Math.round(((c.emails_sent ?? 0) + (c.emails_failed ?? 0) + (c.emails_bounced ?? 0)) / c.recipients_count * 100));
}

// Auto-refresh campaign stats while any campaign is queued or sending
let pollTimer = null;
onMounted(() => {
    document.addEventListener('click', closeMenu);
    pollTimer = setInterval(() => {
        const active = props.campaigns.data.some(c => ['queued', 'sending'].includes(c.status));
        if (active) {
            router.reload({ only: ['campaigns'] });
        }
    }, 4000);
});
onUnmounted(() => {
    document.removeEventListener('click', closeMenu);
    clearInterval(pollTimer);
});

let searchTimer = null;
function onSearch() {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(() => {
        router.get(route('campaigns.index'), { search: search.value, status: statusFilter.value }, {
            preserveState: true,
            replace: true,
        });
    }, 350);
}

function goPage(page) {
    router.get(route('campaigns.index'), { ...props.filters, page }, { preserveState: true });
}

function createCampaign() {
    if (!newTitle.value.trim()) return;
    creating.value = true;
    router.post(route('campaigns.store'), { title: newTitle.value.trim() }, {
        onFinish: () => { creating.value = false; },
    });
}

function confirmDelete(campaign) {
    openMenu.value = null;
    deleteTarget.value = campaign;
}
function deleteCampaign() {
    const deletedId = deleteTarget.value.id;
    deleting.value = true;
    router.delete(route('campaigns.destroy', deletedId), {
        onSuccess: () => {
            deleteTarget.value = null;
            selected.value = selected.value.filter(id => id !== deletedId);
        },
        onFinish:  () => { deleting.value = false; },
    });
}

function bulkDelete() {
    bulkDeleting.value = true;
    router.post(route('campaigns.bulk-destroy'), { ids: selected.value }, {
        onSuccess: () => {
            showBulkDelete.value = false;
            selected.value = [];
        },
        onFinish: () => { bulkDeleting.value = false; },
    });
}

function openRate(c) {
    if (!c.emails_sent) return '0';
    return ((c.unique_opens / c.emails_sent) * 100).toFixed(1);
}
function clickRate(c) {
    if (!c.emails_sent) return '0';
    return ((c.unique_clicks / c.emails_sent) * 100).toFixed(1);
}

function doDuplicate(c) {
    openMenu.value = null;
    router.post(route('campaigns.duplicate', c.id));
}
</script>

<style scoped>
.link-btn { background: none; border: none; color: #4285f4; cursor: pointer; font-size: inherit; padding: 0; }

/* ── Wrapper ── */
.cw-wrap {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    overflow: visible;
}

/* ── Toolbar ── */
.cw-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    gap: 10px;
}
.cw-toolbar-left { display: flex; align-items: center; gap: 8px; }
.cw-toolbar-right { display: flex; align-items: center; gap: 6px; }
.cw-checkbox-wrap { display: flex; align-items: center; }

.cw-search {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 0 12px;
    height: 36px;
    width: 260px;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.cw-search:focus-within {
    border-color: #4285f4;
    box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.12);
}
.cw-search svg { color: var(--text-muted); flex-shrink: 0; }
.cw-search input {
    border: none;
    background: transparent;
    outline: none;
    font-size: 13px;
    color: var(--text-primary);
    width: 100%;
    height: 100%;
}
.cw-search input::placeholder { color: var(--text-muted); }
.cw-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.cw-filter-select {
    font-size: 13px;
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    background: var(--bg-surface);
    border-radius: 8px;
    padding: 0 10px;
    height: 36px;
    cursor: pointer;
    outline: none;
}
.cw-filter-select:focus {
    border-color: #4285f4;
    box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.12);
}

@media (max-width: 640px) {
    .cw-toolbar {
        flex-direction: column;
        align-items: stretch;
        padding: 10px 12px;
        gap: 10px;
    }
    .cw-toolbar-left {
        flex-wrap: wrap;
        width: 100%;
        gap: 8px;
    }
    .cw-search {
        width: 100%;
        flex: 1;
        min-width: 0;
    }
    .cw-filter-select {
        flex-shrink: 0;
        max-width: 130px;
    }
    .cw-toolbar-right {
        width: 100%;
        justify-content: space-between;
    }
}

/* ── Bulk actions ── */
.cw-selected-count {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    padding: 0 4px;
}
.cw-bulk-delete {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 36px;
    padding: 0 14px;
    font-size: 13px;
    font-weight: 600;
    color: #dc2626;
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s;
}
.cw-bulk-delete:hover { background: #fee2e2; border-color: #fca5a5; }
.cw-bulk-clear {
    height: 36px;
    padding: 0 12px;
    font-size: 13px;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    cursor: pointer;
}
.cw-bulk-clear:hover { background: var(--bg-hover); color: var(--text-primary); }
.cw-pagination-info { font-size: 12px; color: var(--text-secondary); }
.cw-pg-btn {
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--border-color);
    background: var(--bg-surface);
    border-radius: 6px;
    cursor: pointer;
    color: var(--text-primary);
}
.cw-pg-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ── Column header ── */
.cw-col-header {
    display: grid;
    grid-template-columns: 36px 1fr 100px 100px 100px 120px 100px 100px;
    align-items: center;
    padding: 0 16px;
    background: var(--bg-page);
    border-bottom: 1px solid var(--border-color);
    height: 36px;
}
@media (max-width: 1024px) {
    .cw-col-header {
        display: none;
    }
}
.cw-col-header > div {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}
.cw-col-stat { text-align: center; }
.cw-col-actions { text-align: right; }

/* ── Campaign row ── */
.cw-row {
    display: grid;
    grid-template-columns: 36px 1fr 100px 100px 100px 120px 100px 100px;
    align-items: center;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color);
    transition: background 0.12s;
}
.cw-row:last-child { border-bottom: none; }
.cw-row:hover { background: var(--bg-hover); }
.cw-row.is-selected { background: var(--active-bg); }

@media (max-width: 1024px) {
    .cw-row {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
        padding: 16px;
        position: relative;
    }
    .cw-row .cw-col-cb {
        position: absolute;
        top: 16px;
        left: 16px;
    }
    .cw-row .cw-col-name {
        padding-left: 28px;
        padding-right: 48px;
    }
    .cw-row .cw-col-actions {
        position: absolute;
        top: 16px;
        right: 16px;
    }
    .cw-row .cw-col-stat {
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-top: 1px solid var(--border-color);
        padding-top: 8px;
        text-align: left;
    }
    .cw-row .cw-col-stat::before {
        content: attr(data-label);
        font-size: 11px;
        font-weight: 600;
        text-transform: uppercase;
        color: var(--text-muted);
    }
    .cw-row .cw-stat-val {
        text-align: right;
    }
    .cw-row .cw-stat-dash {
        text-align: right;
    }
    .cw-row .cw-stat-rate {
        text-align: right;
        display: inline-block;
        margin-left: 6px;
    }
}

.cw-campaign-info { display: flex; flex-direction: column; gap: 3px; }
.cw-campaign-title { font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
.cw-campaign-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cw-campaign-subject { font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
.cw-campaign-date { font-size: 11px; color: var(--text-muted); display: flex; align-items: center; gap: 4px; margin-top: 2px; }

/* ── Sending progress ── */
.cw-progress { display: flex; align-items: center; gap: 8px; margin-top: 4px; max-width: 320px; }
.cw-progress-track {
    flex: 1;
    height: 6px;
    background: var(--bg-hover-strong);
    border-radius: 3px;
    overflow: hidden;
}
.cw-progress-fill {
    height: 100%;
    background: var(--active-text);
    border-radius: 3px;
    transition: width 0.4s ease;
}
.cw-progress-text { font-size: 11px; color: var(--text-secondary); white-space: nowrap; }
.cw-progress-waiting { margin-top: 4px; color: var(--warning); }

/* ── Badges ── */
.cw-badge {
    display: inline-block;
    font-size: 11px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 10px;
    white-space: nowrap;
}
.cw-badge--draft     { background: var(--gray-100); color: var(--text-secondary); border: 1px solid var(--border-color); }
.cw-badge--new       { background: var(--info-light); color: var(--info); border: 1px solid var(--info-border); }
.cw-badge--scheduled { background: rgba(124, 58, 237, 0.12); color: #a78bfa; border: 1px solid rgba(124, 58, 237, 0.25); }
.cw-badge--queued    { background: var(--warning-light); color: var(--warning); border: 1px solid var(--warning-border); }
.cw-badge--sending   { background: var(--info-light); color: var(--info); border: 1px solid var(--info-border); }
.cw-badge--sent      { background: var(--success-light); color: var(--success); border: 1px solid var(--success-border); }
.cw-badge--paused    { background: var(--gray-100); color: var(--text-secondary); border: 1px solid var(--border-color); }

/* ── Stats ── */
.cw-stat-val    { font-size: 13px; font-weight: 600; color: var(--text-primary); display: block; text-align: center; }
.cw-stat-dash   { font-size: 13px; color: var(--text-muted); display: block; text-align: center; }
.cw-stat-rate   { font-size: 11px; color: var(--text-muted); display: block; text-align: center; }
.cw-stat-danger { color: var(--danger) !important; }
.cw-stat-green  { color: var(--success) !important; }

/* ── Actions ── */
.cw-col-actions { display: flex; align-items: center; justify-content: flex-end; gap: 4px; }
.cw-action-btn {
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 6px;
    cursor: pointer;
    color: var(--text-secondary);
    text-decoration: none;
    transition: background 0.1s, border-color 0.1s, color 0.1s;
}
.cw-action-btn:hover { background: var(--bg-hover); border-color: var(--border-color); color: var(--text-primary); }
.cw-action-edit:hover  { color: #2563eb; border-color: #bfdbfe; background: #eff6ff; }
.cw-action-report:hover { color: #16a34a; border-color: #bbf7d0; background: #f0fdf4; }

/* ── 3-dot dropdown ── */
.cw-menu-wrap { position: relative; }
.cw-dropdown {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12);
    min-width: 170px;
    z-index: 100;
    overflow: hidden;
    padding: 4px 0;
}
.cw-dd-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    font-size: 13px;
    color: var(--text-primary);
    cursor: pointer;
    text-decoration: none;
    background: none;
    border: none;
    width: 100%;
    text-align: left;
    transition: background 0.1s;
}
.cw-dd-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.cw-dd-item svg { flex-shrink: 0; color: var(--text-muted); }
.cw-dd-danger { color: #dc2626; }
.cw-dd-danger svg { color: #dc2626; }
.cw-dd-danger:hover { background: #fef2f2; }

/* ── Empty ── */
.cw-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 64px 24px;
    color: var(--text-muted);
    font-size: 14px;
}
</style>
