<script setup>
    import { computed, reactive, ref, watch } from 'vue';
    import { useI18n } from 'vue-i18n';
    import { useRoute, useRouter } from 'vue-router';
    import {
        mdiCalendarPlus,
        mdiChevronDown,
        mdiChevronLeft,
        mdiChevronRight,
        mdiClockOutline,
        mdiClose,
        mdiFacebook,
        mdiInstagram,
        mdiLinkedin,
        mdiMagnify,
        mdiMusicNote,
        mdiPlus,
        mdiWeb,
        mdiYoutube,
    } from '@mdi/js';
    import { useCampaignsStore } from '@/features/campaigns/stores/campaignsStore.js';
    import { organizationPermissions, useOrganizationStore } from '@/features/organizations/stores/organizationStore.js';
    import { useAuthStore } from '@/features/auth/stores/authStore.js';
    import { useWorkspaceStore } from '@/features/workspaces/stores/workspaceStore.js';
    import ColorPalette from '@/features/content/components/ColorPalette.vue';
    import { useCalendarIntegrationsStore } from '@/features/content/stores/calendarIntegrationsStore.js';
    import { useContentItemsStore } from '@/features/content/stores/contentItemsStore.js';

    const { t, locale } = useI18n();
    const route = useRoute();
    const router = useRouter();
    const authStore = useAuthStore();
    const workspaceStore = useWorkspaceStore();
    const organizationStore = useOrganizationStore();
    const campaignsStore = useCampaignsStore();
    const contentItemsStore = useContentItemsStore();
    const calendarStore = useCalendarIntegrationsStore();

    const today = startOfDay(new Date());
    const viewMode = ref(parseViewMode(route.query.view));
    const cursorDate = ref(parseCursorDate(route.query.date, today));
    const isAddCalendarOpen = ref(route.query.addCalendar === 'true');
    const isCalendarSelectorOpen = ref(false);
    const activeColorSourceId = ref('');
    const activeAddMode = ref('catalog');
    const catalogFilters = reactive({
        search: '',
        country: '',
        category: '',
    });
    const customCalendarForm = reactive({
        title: '',
        sourceUrl: '',
        color: '#2F80ED',
        category: 'public-holiday',
        scope: 'User',
    });
    const addCalendarError = ref('');
    const calendarPaletteColors = [
        '#2F80ED',
        '#0F766E',
        '#16A34A',
        '#F59E0B',
        '#EF4444',
        '#EC4899',
        '#8B5CF6',
        '#475569',
    ];

    const contentStatusMeta = {
        Draft: { tone: 'production' },
        'In production': { tone: 'production' },
        'In approval': { tone: 'approval' },
        Approved: { tone: 'ready' },
        Scheduled: { tone: 'ready' },
        Published: { tone: 'published' },
    };

    const contentItemsByCampaignId = computed(() => {
        const grouped = new Map();

        for (const item of contentItemsStore.items) {
            const existing = grouped.get(item.campaignId) ?? [];
            existing.push(item);
            grouped.set(item.campaignId, existing);
        }

        return grouped;
    });

    const calendarEntries = computed(() => {
        const campaignEntries = campaignsStore.campaigns
            .filter(campaign => campaign.endDate || campaign.startDate)
            .map(campaign => buildCampaignEntry(campaign));

        const contentEntries = contentItemsStore.items
            .filter(item => item.dueDate)
            .map(item => buildContentEntry(item));

        const importedEntries = calendarStore.visibleEvents
            .flatMap(event => buildImportedCalendarEntries(event));

        return [...campaignEntries, ...contentEntries, ...importedEntries].sort(sortByDate);
    });

    const entriesByDay = computed(() => {
        const grouped = new Map();

        for (const entry of calendarEntries.value) {
            const existing = grouped.get(entry.dayKey) ?? [];
            existing.push(entry);
            grouped.set(entry.dayKey, existing);
        }

        return grouped;
    });

    const visibleDays = computed(() => {
        if (viewMode.value === 'week') {
            const start = startOfWeek(cursorDate.value);
            return Array.from({ length: 7 }, (_, index) => buildDay(addDays(start, index), false));
        }

        const start = startOfWeek(startOfMonth(cursorDate.value));
        const end = endOfWeek(endOfMonth(cursorDate.value));
        const days = [];
        let current = start;

        while (current <= end) {
            days.push(buildDay(current, current.getMonth() !== cursorDate.value.getMonth()));
            current = addDays(current, 1);
        }

        return days;
    });

    const weekdayLabels = computed(() => {
        const base = startOfWeek(cursorDate.value);

        return Array.from({ length: 7 }, (_, index) =>
            new Intl.DateTimeFormat(locale.value, { weekday: 'short' }).format(addDays(base, index))
        );
    });

    const periodLabel = computed(() => {
        if (viewMode.value === 'week') {
            const start = startOfWeek(cursorDate.value);
            const end = addDays(start, 6);
            const sameMonth = start.getMonth() === end.getMonth() && start.getFullYear() === end.getFullYear();

            if (sameMonth) {
                return new Intl.DateTimeFormat(locale.value, {
                    month: 'long',
                    day: 'numeric',
                    year: 'numeric',
                }).formatRange(start, end);
            }

            return new Intl.DateTimeFormat(locale.value, {
                month: 'short',
                day: 'numeric',
                year: 'numeric',
            }).formatRange(start, end);
        }

        return new Intl.DateTimeFormat(locale.value, {
            month: 'long',
            year: 'numeric',
        }).format(cursorDate.value);
    });

    const upcomingItems = computed(() =>
        [...contentItemsStore.items].sort((left, right) => {
            if (!left.dueDate && !right.dueDate) {
                return left.title.localeCompare(right.title);
            }

            if (!left.dueDate) {
                return 1;
            }

            if (!right.dueDate) {
                return -1;
            }

            return new Date(left.dueDate).getTime() - new Date(right.dueDate).getTime();
        })
    );

    const upcomingEntries = computed(() =>
        calendarEntries.value
            .filter(entry => entry.scheduledAt >= today)
            .slice(0, 80)
    );

    const isLoading = computed(() =>
        contentItemsStore.isLoading || campaignsStore.isLoading
    );

    const pageError = computed(() =>
        contentItemsStore.error || campaignsStore.error
    );

    const isCalendarView = computed(() => viewMode.value === 'month' || viewMode.value === 'week');
    const isTodayVisible = computed(() =>
        visibleDays.value.some(day => day.isToday)
    );
    const previousPeriodLabel = computed(() =>
        viewMode.value === 'week'
            ? t('contentItems.calendar.previousWeek')
            : t('contentItems.calendar.previousMonth')
    );
    const nextPeriodLabel = computed(() =>
        viewMode.value === 'week'
            ? t('contentItems.calendar.nextWeek')
            : t('contentItems.calendar.nextMonth')
    );
    const tableItems = computed(() =>
        [...contentItemsStore.items].sort((left, right) => {
            const leftDate = left.dueDate ? new Date(left.dueDate).getTime() : Number.MAX_SAFE_INTEGER;
            const rightDate = right.dueDate ? new Date(right.dueDate).getTime() : Number.MAX_SAFE_INTEGER;

            return leftDate - rightDate || left.title.localeCompare(right.title);
        })
    );
    const calendarWorkspaceId = computed(() =>
        workspaceStore.activeWorkspaceId ?? workspaceStore.visibleWorkspaceIds[0] ?? null
    );
    const calendarRange = computed(() => {
        if (viewMode.value === 'week') {
            const start = startOfWeek(cursorDate.value);
            return {
                startDate: dateKey(start),
                endDate: dateKey(addDays(start, 6)),
            };
        }

        const start = startOfWeek(startOfMonth(cursorDate.value));
        const end = endOfWeek(endOfMonth(cursorDate.value));
        return {
            startDate: dateKey(start),
            endDate: dateKey(end),
        };
    });
    const canManageOrganizationCalendars = computed(() =>
        organizationStore.userCan(organizationStore.activeOrganization, organizationPermissions.manageConnectors)
    );
    const canManageWorkspaceCalendars = computed(() => authStore.isManager);
    const availableCalendarSources = computed(() =>
        [...calendarStore.sources].sort((left, right) => {
            const scopeSort = ['Organization', 'Workspace', 'User'];
            const scopeDiff = scopeSort.indexOf(left.scope) - scopeSort.indexOf(right.scope);
            return scopeDiff || left.displayTitle.localeCompare(right.displayTitle);
        })
    );
    const visibleCalendarSourceCount = computed(() =>
        availableCalendarSources.value.filter(source => sourceIsVisible(source.id)).length
    );
    const addScopeOptions = computed(() => [
        ...(canManageOrganizationCalendars.value ? [{ value: 'Organization', label: t('contentItems.calendar.organization') }] : []),
        ...(canManageWorkspaceCalendars.value && calendarWorkspaceId.value ? [{ value: 'Workspace', label: t('contentItems.calendar.workspace') }] : []),
        { value: 'User', label: t('contentItems.calendar.mine') },
    ]);

    function buildDay(date, isOutsideMonth) {
        const key = dateKey(date);

        return {
            key,
            date,
            entries: entriesByDay.value.get(key) ?? [],
            isOutsideMonth,
            isToday: key === dateKey(today),
        };
    }

    function buildContentEntry(item) {
        const statusMeta = contentStatusMeta[item.status] ?? { tone: 'production' };
        const campaign = campaignsStore.campaigns.find(candidate => candidate.id === item.campaignId);
        const channels = parseTargets(item.publicationTargets).map(target => ({
            label: target,
            icon: channelIcon(target),
        }));

        return {
            id: item.id,
            type: 'content',
            title: item.title,
            subtitle: campaign?.name ?? t('dashboard.labels.unassignedCampaign'),
            campaignLabel: campaign?.name ?? '',
            hashtags: parseHashtags(item.hashtags),
            preview: item.publicationMessage || item.title,
            channels,
            scheduledAt: new Date(item.dueDate),
            dayKey: dateKey(item.dueDate),
            timeLabel: formatHour(item.dueDate),
            tone: statusMeta.tone,
            route: { name: 'content-item-detail', params: { id: item.id }, query: { returnTo: route.fullPath } },
        };
    }

    function parseTargets(value) {
        return String(value ?? '')
            .split(/[,;\n]+/)
            .map(target => target.trim())
            .filter(Boolean);
    }

    function parseHashtags(value) {
        return String(value ?? '')
            .split(/[\s,;]+/)
            .map(tag => tag.trim())
            .filter(Boolean)
            .map(tag => tag.startsWith('#') ? tag : `#${tag}`);
    }

    function channelIcon(value) {
        const target = String(value ?? '').toLowerCase();

        if (target.includes('instagram')) {
            return mdiInstagram;
        }

        if (target.includes('tiktok') || target.includes('tik tok')) {
            return mdiMusicNote;
        }

        if (target.includes('facebook')) {
            return mdiFacebook;
        }

        if (target.includes('linkedin')) {
            return mdiLinkedin;
        }

        if (target.includes('youtube')) {
            return mdiYoutube;
        }

        return mdiWeb;
    }

    function buildCampaignEntry(campaign) {
        const campaignItems = contentItemsByCampaignId.value.get(campaign.id) ?? [];
        const approvedCount = campaignItems.filter(item => ['Approved', 'Scheduled', 'Published'].includes(item.status)).length;

        return {
            id: campaign.id,
            type: 'campaign',
            title: campaign.name,
            subtitle: campaignItems.length
                ? t('dashboard.campaignProgress', { scheduled: campaignItems.length, approved: approvedCount })
                : t('dashboard.readiness.missing'),
            scheduledAt: new Date(campaign.endDate ?? campaign.startDate),
            dayKey: dateKey(campaign.endDate ?? campaign.startDate),
            timeLabel: t('dashboard.campaignDeadline'),
            tone: campaignItems.length ? 'campaign' : 'risk',
            route: { name: 'campaign-detail', params: { campaignId: campaign.id } },
        };
    }

    function buildImportedCalendarEntries(event) {
        const source = calendarStore.sourceById(event.calendarSourceId);
        const scheduledAt = parseCalendarEventDate(event);
        const eventStart = startOfDay(`${event.startDate}T00:00:00`);
        const eventEnd = displayEndDate(event);
        const rangeStart = startOfDay(`${calendarRange.value.startDate}T00:00:00`);
        const rangeEnd = startOfDay(`${calendarRange.value.endDate}T00:00:00`);
        const visibleStart = maxDate(eventStart, rangeStart);
        const visibleEnd = minDate(eventEnd, rangeEnd);
        const segments = [];
        let segmentStart = visibleStart;

        while (segmentStart <= visibleEnd) {
            const segmentEnd = minDate(endOfWeek(segmentStart), visibleEnd);
            const segmentDayCount = dayDiff(segmentStart, segmentEnd) + 1;
            segments.push({
                id: `${event.id}-${dateKey(segmentStart)}`,
                originalEventId: event.id,
                type: 'imported-calendar',
                title: event.title,
                subtitle: source?.displayTitle ?? t('contentItems.calendar.importedEvent'),
                description: event.description,
                location: event.location,
                scheduledAt: segmentStart,
                dayKey: dateKey(segmentStart),
                timeLabel: event.isAllDay ? t('contentItems.calendar.allDay') : formatHour(scheduledAt),
                tone: 'calendar-context',
                source,
                color: source?.color ?? '#64748b',
                route: null,
                spanDays: segmentDayCount,
                eventStart,
                eventEnd,
                isAllDay: event.isAllDay,
            });

            segmentStart = addDays(segmentEnd, 1);
        }

        return segments;
    }

    function parseCalendarEventDate(event) {
        if (event.startLocalDateTime) {
            return new Date(event.startLocalDateTime);
        }

        if (event.startUtc) {
            return new Date(event.startUtc);
        }

        return new Date(`${event.startDate}T00:00:00`);
    }

    function displayEndDate(event) {
        const startDate = startOfDay(`${event.startDate}T00:00:00`);
        const endDate = startOfDay(`${event.endDate ?? event.startDate}T00:00:00`);

        if (event.isAllDay && endDate > startDate) {
            return addDays(endDate, -1);
        }

        return endDate;
    }

    function normalizeCalendarUrl(value) {
        return String(value ?? '').trim().replace(/\/$/, '').toLowerCase();
    }

    function entryStyle(entry) {
        if (entry.type !== 'imported-calendar') {
            return {};
        }

        const color = entry.color || '#64748b';
        return {
            '--calendar-source-color': color,
            '--calendar-source-tint': hexToRgba(color, 0.1),
            borderColor: `${color}55`,
            borderLeftColor: color,
        };
    }

    function importedEventChipStyle(entry) {
        const baseStyle = entryStyle(entry);
        const spanDays = Math.max(1, entry.spanDays ?? 1);

        return {
            ...baseStyle,
            width: spanDays === 1
                ? '100%'
                : `calc(${spanDays * 100}% + ${(spanDays - 1) * 0.5}rem)`,
        };
    }

    function importedEventTooltip(entry) {
        const parts = [
            entry.title,
            entry.subtitle,
            entry.timeLabel,
        ];

        if (entry.eventStart && entry.eventEnd && dateKey(entry.eventStart) !== dateKey(entry.eventEnd)) {
            parts.push(`${formatEntryDate(entry.eventStart)} - ${formatEntryDate(entry.eventEnd)}`);
        }

        if (entry.location) {
            parts.push(entry.location);
        }

        if (entry.description) {
            parts.push(entry.description);
        }

        return parts.filter(Boolean).join('\n');
    }

    function sourceIsVisible(sourceId) {
        return !calendarStore.hiddenSourceIds.has(sourceId);
    }

    function toggleSource(sourceId) {
        calendarStore.toggleSourceVisibility(sourceId);
    }

    function toggleColorPalette(sourceId) {
        activeColorSourceId.value = activeColorSourceId.value === sourceId ? '' : sourceId;
    }

    async function updateSourceColor(source, color) {
        if (!source || source.isReadOnly || source.color?.toLowerCase() === color.toLowerCase()) {
            activeColorSourceId.value = '';
            return;
        }

        await calendarStore.updateSource(source.id, {
            scope: source.scope,
            organizationId: source.scope === 'Organization' ? source.organizationId : null,
            workspaceId: source.scope === 'Workspace' ? source.workspaceId : null,
            sourceUrl: source.sourceUrl,
            catalogSourceReference: source.catalogSourceReference,
            displayTitle: source.displayTitle,
            color,
            category: source.category,
            isEnabled: source.isEnabled,
            inheritanceMode: source.scope === 'Organization' ? source.inheritanceMode : null,
        });
        activeColorSourceId.value = '';
    }

    function openAddCalendar() {
        isCalendarSelectorOpen.value = false;
        isAddCalendarOpen.value = true;
    }

    function createFromImportedEvent(entry) {
        router.push({
            name: 'content-item-create',
            query: {
                date: entry.dayKey,
                title: entry.title,
            },
        });
    }

    async function refreshCalendarData() {
        if (!calendarWorkspaceId.value) {
            return;
        }

        await calendarStore.fetchSources(calendarWorkspaceId.value);

        const sourcesToRefresh = calendarStore.sources.filter(source =>
            source.isEnabled &&
            !calendarStore.hiddenSourceIds.has(source.id) &&
            (!source.lastSuccessfulSyncAt || source.lastSyncError)
        );

        await Promise.all(sourcesToRefresh.map(source => calendarStore.refreshSource(source.id)));

        await calendarStore.fetchEvents({
            workspaceId: calendarWorkspaceId.value,
            startDate: calendarRange.value.startDate,
            endDate: calendarRange.value.endDate,
        });
    }

    async function searchCatalog() {
        await calendarStore.searchCatalog({
            search: catalogFilters.search || undefined,
            country: catalogFilters.country || undefined,
            category: catalogFilters.category || undefined,
        });
    }

    async function addCatalogSource(entry) {
        if (catalogEntryAlreadyAdded(entry)) {
            addCalendarError.value = t('contentItems.calendar.errors.duplicate');
            return;
        }

        await addCalendarSource({
            title: entry.title,
            sourceUrl: entry.sourceUrl,
            color: entry.defaultColor,
            category: entry.category,
            catalogSourceReference: String(entry.id),
        });
    }

    async function addCustomSource() {
        await addCalendarSource({
            title: customCalendarForm.title,
            sourceUrl: customCalendarForm.sourceUrl,
            color: customCalendarForm.color,
            category: customCalendarForm.category,
            catalogSourceReference: null,
        });
    }

    async function addCalendarSource({ title, sourceUrl, color, category, catalogSourceReference }) {
        addCalendarError.value = '';
        const scope = customCalendarForm.scope;
        const payload = {
            scope,
            organizationId: scope === 'Organization' ? organizationStore.activeOrganization?.id : null,
            workspaceId: scope === 'Workspace' ? calendarWorkspaceId.value : null,
            sourceUrl,
            catalogSourceReference,
            displayTitle: title.trim(),
            color,
            category,
            isEnabled: true,
            inheritanceMode: scope === 'Organization' ? 'Optional' : null,
        };

        if (!payload.displayTitle || !payload.sourceUrl) {
            addCalendarError.value = t('contentItems.calendar.errors.required');
            return;
        }

        if (sourceAlreadyAdded(payload)) {
            addCalendarError.value = t('contentItems.calendar.errors.duplicate');
            return;
        }

        try {
            const source = await calendarStore.createSource(payload);
            await calendarStore.refreshSource(source?.id);
            isAddCalendarOpen.value = false;
            customCalendarForm.title = '';
            customCalendarForm.sourceUrl = '';
            await refreshCalendarData();
        } catch {
            addCalendarError.value = t('contentItems.calendar.errors.createFailed');
        }
    }

    function catalogEntryAlreadyAdded(entry) {
        return sourceAlreadyAdded({
            scope: customCalendarForm.scope,
            organizationId: customCalendarForm.scope === 'Organization' ? organizationStore.activeOrganization?.id : null,
            workspaceId: customCalendarForm.scope === 'Workspace' ? calendarWorkspaceId.value : null,
            sourceUrl: entry.sourceUrl,
            catalogSourceReference: String(entry.id),
        });
    }

    function sourceAlreadyAdded(payload) {
        const normalizedUrl = normalizeCalendarUrl(payload.sourceUrl);
        const normalizedReference = String(payload.catalogSourceReference ?? '').trim();

        return calendarStore.sources.some(source => {
            if (source.scope !== payload.scope) {
                return false;
            }

            if (payload.scope === 'Organization' && source.organizationId !== payload.organizationId) {
                return false;
            }

            if (payload.scope === 'Workspace' && source.workspaceId !== payload.workspaceId) {
                return false;
            }

            if (payload.scope === 'User' && (source.organizationId || source.workspaceId)) {
                return false;
            }

            return Boolean(normalizedReference && source.catalogSourceReference === normalizedReference) ||
                Boolean(normalizedUrl && normalizeCalendarUrl(source.sourceUrl) === normalizedUrl);
        });
    }

    function setView(mode) {
        viewMode.value = mode;

        if (mode === 'month') {
            cursorDate.value = startOfMonth(cursorDate.value);
        }

        if (mode === 'week') {
            cursorDate.value = startOfWeek(cursorDate.value);
        }
    }

    function shiftPeriod(direction) {
        cursorDate.value = viewMode.value === 'month'
            ? addMonths(cursorDate.value, direction)
            : addDays(cursorDate.value, direction * 7);
    }

    function jumpToToday() {
        cursorDate.value = viewMode.value === 'month' ? startOfMonth(today) : startOfWeek(today);
    }

    function formatDayNumber(date) {
        return new Intl.DateTimeFormat(locale.value, { day: 'numeric' }).format(date);
    }

    function formatHour(value) {
        return new Intl.DateTimeFormat(locale.value, {
            hour: 'numeric',
            minute: '2-digit',
        }).format(new Date(value));
    }

    function formatDueDate(value) {
        return value ? new Date(value).toLocaleDateString() : t('contentItems.noDueDate');
    }

    function formatEntryDate(value) {
        return new Intl.DateTimeFormat(locale.value, {
            month: 'short',
            day: 'numeric',
            year: 'numeric',
        }).format(value);
    }

    function startOfDay(value) {
        const date = new Date(value);
        date.setHours(0, 0, 0, 0);
        return date;
    }

    function startOfWeek(value) {
        const date = startOfDay(value);
        const day = date.getDay();
        const diff = day === 0 ? -6 : 1 - day;
        return addDays(date, diff);
    }

    function endOfWeek(value) {
        return addDays(startOfWeek(value), 6);
    }

    function startOfMonth(value) {
        const date = startOfDay(value);
        date.setDate(1);
        return date;
    }

    function endOfMonth(value) {
        const date = startOfMonth(value);
        date.setMonth(date.getMonth() + 1);
        date.setDate(0);
        return date;
    }

    function addDays(value, amount) {
        const date = startOfDay(value);
        date.setDate(date.getDate() + amount);
        return date;
    }

    function addMonths(value, amount) {
        const date = startOfMonth(value);
        date.setMonth(date.getMonth() + amount);
        return date;
    }

    function dateKey(value) {
        if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) {
            return value.slice(0, 10);
        }

        const date = new Date(value);
        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
    }

    function sortByDate(left, right) {
        return left.scheduledAt.getTime() - right.scheduledAt.getTime();
    }

    function dayDiff(left, right) {
        return Math.round((startOfDay(right).getTime() - startOfDay(left).getTime()) / 86400000);
    }

    function minDate(left, right) {
        return left <= right ? left : right;
    }

    function maxDate(left, right) {
        return left >= right ? left : right;
    }

    function hexToRgba(value, alpha) {
        const normalized = String(value ?? '').replace('#', '');
        if (!/^[0-9A-Fa-f]{6}$/.test(normalized)) {
            return `rgba(100, 116, 139, ${alpha})`;
        }

        const red = parseInt(normalized.slice(0, 2), 16);
        const green = parseInt(normalized.slice(2, 4), 16);
        const blue = parseInt(normalized.slice(4, 6), 16);
        return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
    }

    function parseViewMode(value) {
        return ['month', 'week', 'upcoming', 'table'].includes(value) ? value : 'month';
    }

    function parseCursorDate(value, fallback) {
        if (typeof value !== 'string') {
            return fallback;
        }

        const parsed = new Date(`${value}T00:00:00`);
        return Number.isNaN(parsed.getTime()) ? fallback : startOfDay(parsed);
    }

    watch(
        () => route.query,
        query => {
            viewMode.value = parseViewMode(query.view);
            cursorDate.value = parseCursorDate(query.date, today);
        }
    );

    watch(
        () => [viewMode.value, dateKey(cursorDate.value)],
        ([view, date]) => {
            if (route.query.view === view && route.query.date === date) {
                return;
            }

            router.replace({
                name: 'content-items',
                query: {
                    ...route.query,
                    view,
                    date,
                },
            });
        }
    );

    watch(
        () => [calendarWorkspaceId.value, viewMode.value, calendarRange.value.startDate, calendarRange.value.endDate],
        async () => {
            await refreshCalendarData();
        },
        { immediate: true }
    );

    watch(
        () => addScopeOptions.value.map(option => option.value).join(','),
        () => {
            if (!addScopeOptions.value.some(option => option.value === customCalendarForm.scope)) {
                customCalendarForm.scope = addScopeOptions.value[0]?.value ?? 'User';
            }
        },
        { immediate: true }
    );

    watch(
        () => isAddCalendarOpen.value,
        async value => {
            if (value && calendarStore.catalogEntries.length === 0) {
                await searchCatalog();
            }
        }
    );
</script>

<template>
    <section class="page-shell">
        <div
            v-if="isLoading"
            class="page-message"
        >
            {{ t('contentItems.loading') }}
        </div>

        <div
            v-else-if="pageError"
            class="page-message error"
        >
            {{ pageError }}
        </div>

        <article
            v-else-if="isCalendarView"
            class="calendar-card"
        >
            <div class="calendar-toolbar">
                <div class="range-selector">
                    <button
                        class="toggle-button"
                        :class="{ 'toggle-button-active': viewMode === 'month' }"
                        type="button"
                        @click="setView('month')"
                    >
                        {{ t('dashboard.month') }}
                    </button>
                    <button
                        class="toggle-button"
                        :class="{ 'toggle-button-active': viewMode === 'week' }"
                        type="button"
                        @click="setView('week')"
                    >
                        {{ t('dashboard.week') }}
                    </button>
                </div>

                <div class="calendar-nav">
                    <button
                        class="icon-button"
                        type="button"
                        :title="previousPeriodLabel"
                        :aria-label="previousPeriodLabel"
                        @click="shiftPeriod(-1)"
                    >
                        <v-icon :icon="mdiChevronLeft" />
                    </button>

                    <div class="calendar-period">{{ periodLabel }}</div>

                    <button
                        class="icon-button"
                        type="button"
                        :title="nextPeriodLabel"
                        :aria-label="nextPeriodLabel"
                        @click="shiftPeriod(1)"
                    >
                        <v-icon :icon="mdiChevronRight" />
                    </button>
                </div>

                <button
                    v-if="!isTodayVisible"
                    class="text-button"
                    type="button"
                    @click="jumpToToday"
                >
                    {{ t('dashboard.today') }}
                </button>

                <div class="calendar-selector">
                    <button
                        class="calendar-selector-button"
                        type="button"
                        @click="isCalendarSelectorOpen = !isCalendarSelectorOpen"
                    >
                        <span>{{ t('contentItems.calendar.calendars') }}</span>
                        <strong>{{ visibleCalendarSourceCount }}/{{ availableCalendarSources.length }}</strong>
                        <v-icon :icon="mdiChevronDown" />
                    </button>

                    <div
                        v-if="isCalendarSelectorOpen"
                        class="calendar-selector-menu"
                    >
                        <div
                            v-for="source in availableCalendarSources"
                            :key="source.id"
                            class="calendar-selector-row"
                        >
                            <span class="source-color-control">
                                <button
                                    class="source-swatch-button"
                                    type="button"
                                    :disabled="source.isReadOnly"
                                    :title="source.isReadOnly ? source.displayTitle : t('contentItems.calendar.editColor')"
                                    @click.stop="toggleColorPalette(source.id)"
                                >
                                    <span
                                        class="source-swatch"
                                        :style="{ background: source.color }"
                                    />
                                </button>

                                <ColorPalette
                                    v-if="activeColorSourceId === source.id"
                                    class="source-color-palette"
                                    :model-value="source.color"
                                    :colors="calendarPaletteColors"
                                    @click.stop
                                    @update:model-value="color => updateSourceColor(source, color)"
                                />
                            </span>
                            <button
                                class="calendar-selector-title"
                                type="button"
                                @click="toggleSource(source.id)"
                            >
                                {{ source.displayTitle }}
                            </button>
                            <button
                                class="visibility-switch"
                                :class="{ active: sourceIsVisible(source.id) }"
                                type="button"
                                :aria-label="source.displayTitle"
                                @click="toggleSource(source.id)"
                            />
                        </div>

                        <div
                            v-if="!availableCalendarSources.length"
                            class="calendar-selector-empty"
                        >
                            {{ t('contentItems.calendar.noCalendars') }}
                        </div>

                        <button
                            class="calendar-selector-add"
                            type="button"
                            @click="openAddCalendar"
                        >
                            <v-icon :icon="mdiCalendarPlus" />
                            <span>{{ t('contentItems.calendar.addCalendar') }}</span>
                        </button>
                    </div>
                </div>
            </div>

            <div class="calendar-grid calendar-grid-head">
                <div
                    v-for="label in weekdayLabels"
                    :key="label"
                    class="weekday-label"
                >
                    {{ label }}
                </div>
            </div>

            <div
                class="calendar-grid"
                :class="viewMode === 'week' ? 'calendar-grid-week' : 'calendar-grid-month'"
            >
                <div
                    v-for="day in visibleDays"
                    :key="day.key"
                    class="calendar-day"
                    :class="{
                        'calendar-day-outside': day.isOutsideMonth,
                        'calendar-day-today': day.isToday,
                        'calendar-day-week': viewMode === 'week',
                    }"
                >
                    <div class="day-number">
                        {{ formatDayNumber(day.date) }}
                    </div>

                    <div
                        v-if="day.entries.length"
                        class="day-entries"
                    >
                        <template
                            v-for="entry in viewMode === 'month' ? day.entries.slice(0, 3) : day.entries"
                            :key="`${entry.type}-${entry.id}`"
                        >
                            <button
                                v-if="entry.type === 'imported-calendar'"
                                class="calendar-entry calendar-context-entry"
                                :class="entry.tone"
                                :style="importedEventChipStyle(entry)"
                                type="button"
                                :title="importedEventTooltip(entry)"
                                @click="createFromImportedEvent(entry)"
                            >
                                <span class="calendar-event-chip">{{ entry.title }}</span>
                            </button>

                            <router-link
                                v-else-if="entry.type === 'content'"
                                :to="entry.route"
                                class="calendar-entry content-calendar-entry"
                                :class="entry.tone"
                            >
                                <div
                                    v-if="entry.campaignLabel"
                                    class="content-entry-top-row"
                                >
                                    <span class="campaign-chip">
                                        {{ entry.campaignLabel }}
                                    </span>
                                </div>

                                <div
                                    v-if="entry.hashtags.length"
                                    class="hashtag-row"
                                >
                                    <span
                                        v-for="tag in entry.hashtags.slice(0, 3)"
                                        :key="tag"
                                        class="hashtag-chip"
                                    >
                                        {{ tag }}
                                    </span>
                                </div>

                                <div class="content-preview">
                                    <strong>{{ entry.title }}</strong>
                                    <span>{{ entry.preview }}</span>
                                </div>

                                <div class="content-meta-row">
                                    <span class="planned-time">
                                        <v-icon :icon="mdiClockOutline" />
                                        {{ entry.timeLabel }}
                                    </span>
                                </div>

                                <div
                                    v-if="entry.channels.length"
                                    class="content-channel-row"
                                >
                                    <span class="channel-icons">
                                        <v-icon
                                            v-for="channel in entry.channels.slice(0, 4)"
                                            :key="channel.label"
                                            :icon="channel.icon"
                                            :title="channel.label"
                                        />
                                    </span>
                                </div>
                            </router-link>

                            <router-link
                                v-else
                                :to="entry.route"
                                class="calendar-entry"
                                :class="entry.tone"
                            >
                                <span class="entry-time">{{ entry.timeLabel }}</span>
                                <strong>{{ entry.title }}</strong>
                                <span>{{ entry.subtitle }}</span>
                            </router-link>
                        </template>

                        <div
                            v-if="viewMode === 'month' && day.entries.length > 3"
                            class="entry-more"
                        >
                            {{ t('dashboard.moreItems', { count: day.entries.length - 3 }) }}
                        </div>
                    </div>

                    <div
                        v-else-if="viewMode === 'week'"
                        class="day-empty"
                    >
                        {{ t('dashboard.emptyPeriod') }}
                    </div>
                </div>
            </div>
        </article>

        <div
            v-else-if="viewMode === 'upcoming' && upcomingEntries.length"
            class="item-grid"
        >
            <template
                v-for="entry in upcomingEntries"
                :key="`${entry.type}-${entry.id}`"
            >
                <button
                    v-if="entry.type === 'imported-calendar'"
                    class="item-card calendar-upcoming-card"
                    :style="entryStyle(entry)"
                    type="button"
                    @click="createFromImportedEvent(entry)"
                >
                    <div class="version-chip calendar-event-chip">{{ t('contentItems.calendar.context') }}</div>
                    <strong>{{ entry.title }}</strong>
                    <span>{{ entry.subtitle }}</span>
                    <div class="status-row">
                        <em>{{ entry.timeLabel }}</em>
                        <small>{{ formatEntryDate(entry.scheduledAt) }}</small>
                    </div>
                </button>

                <router-link
                    v-else-if="entry.type === 'content'"
                    :to="entry.route"
                    class="item-card content-item-card"
                >
                    <div
                        v-if="entry.campaignLabel"
                        class="content-entry-top-row"
                    >
                        <span class="campaign-chip">
                            {{ entry.campaignLabel }}
                        </span>
                    </div>

                    <div
                        v-if="entry.hashtags.length"
                        class="hashtag-row"
                    >
                        <span
                            v-for="tag in entry.hashtags.slice(0, 5)"
                            :key="tag"
                            class="hashtag-chip"
                        >
                            {{ tag }}
                        </span>
                    </div>

                    <div class="content-preview">
                        <strong>{{ entry.title }}</strong>
                        <span>{{ entry.preview }}</span>
                    </div>

                    <div class="content-meta-row">
                        <span class="planned-time">
                            <v-icon :icon="mdiClockOutline" />
                            {{ entry.timeLabel }}
                        </span>
                    </div>

                    <div
                        v-if="entry.channels.length"
                        class="content-channel-row"
                    >
                        <span class="channel-icons">
                            <v-icon
                                v-for="channel in entry.channels.slice(0, 5)"
                                :key="channel.label"
                                :icon="channel.icon"
                                :title="channel.label"
                            />
                        </span>
                    </div>
                </router-link>

                <router-link
                    v-else
                    :to="entry.route"
                    class="item-card"
                >
                    <div class="version-chip">{{ t('dashboard.campaignDeadline') }}</div>
                    <strong>{{ entry.title }}</strong>
                    <span>{{ entry.subtitle }}</span>
                    <div class="status-row">
                        <em>{{ entry.timeLabel }}</em>
                        <small>{{ formatEntryDate(entry.scheduledAt) }}</small>
                    </div>
                </router-link>
            </template>
        </div>

        <div
            v-else-if="viewMode === 'table' && tableItems.length"
            class="content-table-shell"
        >
            <table class="content-table">
                <thead>
                    <tr>
                        <th>{{ t('contentItems.table.content') }}</th>
                        <th>{{ t('contentItems.table.status') }}</th>
                        <th>{{ t('contentItems.table.channels') }}</th>
                        <th>{{ t('contentItems.table.revision') }}</th>
                        <th>{{ t('contentItems.table.dueDate') }}</th>
                    </tr>
                </thead>
                <tbody>
                    <tr
                        v-for="item in tableItems"
                        :key="item.id"
                    >
                        <td>
                            <router-link
                                :to="{ name: 'content-item-detail', params: { id: item.id }, query: { returnTo: route.fullPath } }"
                                class="content-table-title"
                            >
                                {{ item.title }}
                            </router-link>
                        </td>
                        <td>
                            <span class="table-status">{{ item.status }}</span>
                        </td>
                        <td>{{ item.publicationTargets }}</td>
                        <td>{{ item.currentRevisionLabel }}</td>
                        <td>{{ formatDueDate(item.dueDate) }}</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <div
            v-else
            class="page-message"
        >
            {{ t('contentItems.empty') }}
        </div>

        <v-dialog
            v-model="isAddCalendarOpen"
            max-width="760"
        >
            <div class="calendar-dialog">
                <div class="dialog-header">
                    <strong>{{ t('contentItems.calendar.addCalendar') }}</strong>
                    <button
                        class="icon-button"
                        type="button"
                        @click="isAddCalendarOpen = false"
                    >
                        <v-icon :icon="mdiClose" />
                    </button>
                </div>

                <div class="add-mode-toggle">
                    <button
                        class="toggle-button"
                        :class="{ 'toggle-button-active': activeAddMode === 'catalog' }"
                        type="button"
                        @click="activeAddMode = 'catalog'"
                    >
                        {{ t('contentItems.calendar.catalog') }}
                    </button>
                    <button
                        class="toggle-button"
                        :class="{ 'toggle-button-active': activeAddMode === 'custom' }"
                        type="button"
                        @click="activeAddMode = 'custom'"
                    >
                        {{ t('contentItems.calendar.customIcs') }}
                    </button>
                </div>

                <div class="scope-row">
                    <label
                        v-for="option in addScopeOptions"
                        :key="option.value"
                        class="scope-option"
                    >
                        <input
                            v-model="customCalendarForm.scope"
                            type="radio"
                            :value="option.value"
                        >
                        <span>{{ option.label }}</span>
                    </label>
                </div>

                <div
                    v-if="activeAddMode === 'catalog'"
                    class="catalog-panel"
                >
                    <div class="catalog-search">
                        <input
                            v-model="catalogFilters.search"
                            type="search"
                            :placeholder="t('contentItems.calendar.searchCatalog')"
                        >
                        <input
                            v-model="catalogFilters.country"
                            type="text"
                            maxlength="2"
                            :placeholder="t('contentItems.calendar.country')"
                        >
                        <input
                            v-model="catalogFilters.category"
                            type="text"
                            :placeholder="t('contentItems.calendar.category')"
                        >
                        <button
                            class="text-button"
                            type="button"
                            @click="searchCatalog"
                        >
                            <v-icon :icon="mdiMagnify" />
                            <span>{{ t('contentItems.calendar.search') }}</span>
                        </button>
                    </div>

                    <div class="catalog-results">
                        <button
                            v-for="entry in calendarStore.catalogEntries"
                            :key="entry.id"
                            class="catalog-entry"
                            :class="{ 'catalog-entry-disabled': catalogEntryAlreadyAdded(entry) }"
                            type="button"
                            :disabled="catalogEntryAlreadyAdded(entry)"
                            @click="addCatalogSource(entry)"
                        >
                            <span
                                class="source-swatch"
                                :style="{ background: entry.defaultColor }"
                            />
                            <strong>{{ entry.title }}</strong>
                            <span>
                                {{ catalogEntryAlreadyAdded(entry)
                                    ? t('contentItems.calendar.alreadyAdded')
                                    : `${entry.providerName} · ${entry.category}` }}
                            </span>
                        </button>
                    </div>
                </div>

                <form
                    v-else
                    class="custom-calendar-form"
                    @submit.prevent="addCustomSource"
                >
                    <input
                        v-model="customCalendarForm.title"
                        type="text"
                        :placeholder="t('contentItems.calendar.calendarName')"
                    >
                    <input
                        v-model="customCalendarForm.sourceUrl"
                        type="url"
                        :placeholder="t('contentItems.calendar.icsUrl')"
                    >
                    <div class="custom-form-row">
                        <input
                            v-model="customCalendarForm.color"
                            type="color"
                        >
                        <input
                            v-model="customCalendarForm.category"
                            type="text"
                            :placeholder="t('contentItems.calendar.category')"
                        >
                        <button
                            class="text-button"
                            type="submit"
                        >
                            <v-icon :icon="mdiPlus" />
                            <span>{{ t('contentItems.calendar.addCalendar') }}</span>
                        </button>
                    </div>
                </form>

                <p
                    v-if="addCalendarError || calendarStore.error"
                    class="dialog-error"
                >
                    {{ addCalendarError || calendarStore.error }}
                </p>
            </div>
        </v-dialog>
    </section>
</template>

<style scoped>
    .page-shell {
        @apply flex w-full flex-col gap-4 px-4 py-5 md:px-6;
    }

    .item-card span,
    .status-row em,
    .status-row small {
        @apply text-sm leading-6 not-italic;
        color: #526178;
    }

    .range-selector {
        @apply inline-flex w-fit rounded-full border p-1;
        background: #f8fafc;
        border-color: rgba(23, 32, 51, 0.1);
    }

    .calendar-selector {
        @apply relative w-full sm:w-auto;
    }

    .calendar-selector-button {
        @apply inline-flex min-h-11 w-full items-center justify-between gap-2 rounded-full border px-4 py-2 text-sm font-bold transition sm:w-auto;
        background: #ffffff;
        border-color: rgba(23, 32, 51, 0.1);
        color: #172033;
    }

    .calendar-selector-button strong {
        @apply rounded-full px-2 py-0.5 text-xs;
        background: rgba(15, 118, 110, 0.1);
        color: #0f766e;
    }

    .calendar-selector-menu {
        @apply absolute right-0 top-[calc(100%+0.5rem)] z-30 flex w-full min-w-72 flex-col gap-1 rounded-[1rem] border p-2 shadow-xl sm:w-80;
        background: #ffffff;
        border-color: rgba(23, 32, 51, 0.1);
    }

    .calendar-selector-row,
    .calendar-selector-add {
        @apply flex min-h-11 w-full items-center gap-3 rounded-[0.75rem] px-3 text-left text-sm font-semibold transition;
        color: #172033;
    }

    .calendar-selector-row:hover,
    .calendar-selector-add:hover {
        background: #f8fafc;
    }

    .calendar-selector-title {
        @apply min-w-0 flex-1 truncate text-left;
    }

    .source-color-control {
        @apply relative inline-flex shrink-0 items-center;
    }

    .source-swatch-button {
        @apply inline-flex h-7 w-7 items-center justify-center rounded-full transition;
    }

    .source-swatch-button:not(:disabled):hover {
        background: rgba(23, 32, 51, 0.06);
    }

    .source-swatch-button:disabled {
        cursor: default;
    }

    .source-color-palette {
        @apply absolute left-0 top-[calc(100%+0.5rem)] z-40;
    }

    .calendar-selector-empty {
        @apply px-3 py-2 text-sm;
        color: #526178;
    }

    .calendar-selector-add {
        @apply border-t;
        border-color: rgba(23, 32, 51, 0.08);
        color: #0f766e;
    }

    .visibility-switch {
        @apply relative h-6 w-10 shrink-0 rounded-full transition;
        background: rgba(148, 163, 184, 0.35);
    }

    .visibility-switch::after {
        @apply absolute left-1 top-1 h-4 w-4 rounded-full bg-white transition;
        content: '';
        box-shadow: 0 1px 4px rgba(23, 32, 51, 0.2);
    }

    .visibility-switch.active {
        background: #0f766e;
    }

    .visibility-switch.active::after {
        transform: translateX(1rem);
    }

    .toggle-button,
    .icon-button,
    .text-button {
        @apply inline-flex items-center justify-center rounded-full border px-3 py-2 text-sm font-semibold transition;
        background: #f8fafc;
        border-color: rgba(23, 32, 51, 0.1);
        color: #172033;
    }

    .toggle-button {
        @apply border-0 bg-transparent;
    }

    .toggle-button-active {
        background: #172033;
        color: #ffffff;
    }

    .icon-button {
        @apply h-10 w-10 px-0 py-0;
    }

    .icon-button:hover,
    .text-button:hover,
    .toggle-button:hover {
        background: #eef4ff;
    }

    .page-message,
    .item-card {
        @apply rounded-[1.5rem] border;
        background: rgba(255, 255, 255, 0.9);
        border-color: rgba(23, 32, 51, 0.08);
    }

    .page-message {
        @apply p-5 text-sm;
        color: #526178;
    }

    .page-message.error {
        color: #b91c1c;
    }

    .calendar-card {
        @apply flex flex-col;
        background: #ffffff;
    }

    .calendar-toolbar {
        @apply mb-3 flex flex-col gap-2 lg:flex-row lg:items-center;
    }

    .calendar-nav {
        @apply flex items-center gap-2;
    }

    .calendar-toolbar > .calendar-selector {
        @apply lg:ml-auto;
    }

    .calendar-period {
        @apply min-w-0 px-2 text-base font-bold md:text-lg;
        color: #172033;
    }

    .source-swatch {
        @apply h-3 w-3 shrink-0 rounded-full;
    }

    .calendar-grid {
        @apply grid gap-2;
        grid-template-columns: repeat(7, minmax(0, 1fr));
    }

    .calendar-grid-head {
        @apply mb-2;
    }

    .weekday-label {
        @apply px-2 text-xs font-bold uppercase tracking-[0.16em];
        color: #526178;
    }

    .calendar-day {
        @apply min-h-[8rem] overflow-visible rounded-[1rem] border p-2.5;
        border-color: rgba(23, 32, 51, 0.08);
    }

    .calendar-day-week {
        @apply min-h-[22rem];
    }

    .calendar-day-outside {
        opacity: 0.48;
    }

    .calendar-day-today {
        border-color: rgba(15, 118, 110, 0.22);
        box-shadow: inset 0 0 0 1px rgba(15, 118, 110, 0.18);
    }

    .day-number {
        @apply mb-2 text-sm font-bold;
        color: #172033;
    }

    .day-entries,
    .item-card {
        @apply flex flex-col gap-2;
    }

    .day-entries {
        @apply relative;
    }

    .calendar-entry {
        @apply flex flex-col gap-0.5 rounded-[1rem] border px-3 py-2 no-underline transition;
    }

    button.calendar-entry,
    button.item-card {
        @apply w-full text-left;
    }

    .calendar-entry:hover,
    .item-card:hover {
        transform: translateY(-1px);
    }

    .calendar-entry strong,
    .item-card strong {
        @apply text-sm font-bold;
        color: #172033;
    }

    .calendar-entry span {
        @apply text-xs leading-5;
        color: #526178;
    }

    .content-calendar-entry,
    .content-item-card {
        @apply gap-2;
    }

    .content-entry-top-row,
    .hashtag-row,
    .content-meta-row,
    .content-channel-row,
    .channel-icons,
    .planned-time {
        @apply flex items-center;
    }

    .content-entry-top-row,
    .hashtag-row {
        @apply flex-wrap gap-1.5;
    }

    .campaign-chip,
    .hashtag-chip {
        @apply inline-flex max-w-full items-center truncate rounded-full px-2 py-0.5 text-[0.68rem] font-bold leading-5;
    }

    .campaign-chip {
        background: rgba(23, 32, 51, 0.08);
        color: #172033;
    }

    .hashtag-chip {
        background: rgba(15, 118, 110, 0.1);
        color: #0f766e;
    }

    .content-preview {
        @apply flex min-w-0 flex-col gap-0.5;
    }

    .content-preview strong,
    .content-preview span {
        @apply min-w-0 overflow-hidden text-ellipsis;
        display: -webkit-box;
        -webkit-box-orient: vertical;
    }

    .content-preview strong {
        -webkit-line-clamp: 1;
    }

    .content-preview span {
        @apply text-xs leading-5;
        -webkit-line-clamp: 2;
        color: #526178;
    }

    .content-meta-row {
        @apply gap-2;
    }

    .content-channel-row {
        @apply justify-end;
    }

    .planned-time {
        @apply gap-1 text-[0.7rem] font-bold uppercase;
        color: #0f766e;
    }

    .planned-time i,
    .channel-icons i {
        @apply text-sm;
    }

    .channel-icons {
        @apply justify-end gap-1;
        color: #526178;
    }

    .entry-time {
        @apply text-[0.7rem] font-bold uppercase tracking-[0.12em];
        color: #0f766e;
    }

    .calendar-event-chip {
        @apply block min-w-0 truncate text-[0.68rem] font-bold leading-5;
        color: var(--calendar-source-color, #64748b);
    }

    .entry-more,
    .day-empty {
        @apply px-1 text-xs font-semibold;
        color: #526178;
    }

    .calendar-entry.production {
        background: #fff7ed;
        border-color: rgba(249, 115, 22, 0.18);
    }

    .calendar-entry.approval {
        background: #eff6ff;
        border-color: rgba(37, 99, 235, 0.16);
    }

    .calendar-entry.ready {
        background: #ecfdf5;
        border-color: rgba(5, 150, 105, 0.16);
    }

    .calendar-entry.risk {
        background: #fef2f2;
        border-color: rgba(220, 38, 38, 0.16);
    }

    .calendar-entry.campaign {
        background: #f8fafc;
        border-color: rgba(71, 85, 105, 0.18);
        border-style: dashed;
    }

    .calendar-entry.published,
    .calendar-entry.muted {
        background: #f8fafc;
        border-color: rgba(148, 163, 184, 0.18);
    }

    .calendar-context-entry {
        @apply relative z-10 min-h-7 flex-row items-center overflow-hidden rounded-full px-2 py-1;
        max-width: none;
        background: var(--calendar-source-tint, rgba(100, 116, 139, 0.1));
        opacity: 0.86;
    }

    .calendar-context-entry:hover {
        opacity: 1;
    }

    .calendar-upcoming-card {
        border-left-width: 4px;
    }

    .calendar-dialog {
        @apply flex flex-col gap-4 rounded-[1.5rem] border bg-white p-5;
        border-color: rgba(23, 32, 51, 0.1);
    }

    .dialog-header,
    .add-mode-toggle,
    .scope-row,
    .catalog-search,
    .custom-form-row {
        @apply flex flex-wrap items-center gap-3;
    }

    .dialog-header {
        @apply justify-between;
    }

    .dialog-header strong {
        @apply text-lg font-black;
        color: #172033;
    }

    .scope-option {
        @apply inline-flex items-center gap-2 rounded-full border px-3 py-2 text-sm font-semibold;
        border-color: rgba(23, 32, 51, 0.1);
        color: #172033;
    }

    .catalog-panel,
    .custom-calendar-form,
    .catalog-results {
        @apply flex flex-col gap-3;
    }

    .catalog-search input,
    .custom-calendar-form input {
        @apply min-h-11 rounded-[0.75rem] border px-3 text-sm;
        border-color: rgba(23, 32, 51, 0.12);
        color: #172033;
    }

    .catalog-search input[type='search'],
    .custom-calendar-form input[type='url'],
    .custom-calendar-form input[type='text'] {
        @apply min-w-0 flex-1;
    }

    .catalog-results {
        @apply max-h-[22rem] overflow-auto;
    }

    .catalog-entry {
        @apply grid min-h-14 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-3 rounded-[0.75rem] border px-3 py-2 text-left transition;
        border-color: rgba(23, 32, 51, 0.08);
        background: #ffffff;
    }

    .catalog-entry:hover {
        background: #f8fafc;
    }

    .catalog-entry-disabled {
        cursor: not-allowed;
        opacity: 0.58;
    }

    .catalog-entry-disabled:hover {
        background: #ffffff;
    }

    .catalog-entry strong {
        @apply text-sm font-bold;
        color: #172033;
    }

    .catalog-entry span:last-child {
        @apply col-start-2 text-xs;
        color: #526178;
    }

    .dialog-error {
        @apply text-sm font-semibold;
        color: #b91c1c;
    }

    .item-grid {
        @apply grid gap-4 md:grid-cols-2 xl:grid-cols-3;
    }

    .item-card {
        @apply gap-4 p-5 no-underline transition;
    }

    .version-chip {
        @apply w-fit rounded-full px-4 py-2 text-xs font-bold uppercase tracking-[0.16em];
        background: rgba(23, 32, 51, 0.08);
        color: #172033;
    }

    .version-chip.calendar-event-chip {
        background: var(--calendar-source-tint, rgba(100, 116, 139, 0.1));
        color: var(--calendar-source-color, #64748b);
    }

    .status-row {
        @apply flex items-center justify-between gap-3;
    }

    .content-table-shell {
        @apply overflow-x-auto rounded-[1.5rem] border;
        background: rgba(255, 255, 255, 0.94);
        border-color: rgba(23, 32, 51, 0.08);
    }

    .content-table {
        @apply w-full min-w-[52rem] border-collapse text-left text-sm;
        color: #526178;
    }

    .content-table th {
        @apply px-5 py-4 text-xs font-black uppercase tracking-[0.14em];
        background: #f8fafc;
        color: #172033;
    }

    .content-table td {
        @apply border-t px-5 py-4 align-middle;
        border-color: rgba(23, 32, 51, 0.08);
    }

    .content-table-title {
        @apply font-bold no-underline;
        color: #172033;
    }

    .content-table-title:hover {
        color: #0f766e;
    }

    .table-status {
        @apply inline-flex rounded-full px-3 py-1 text-xs font-bold;
        background: rgba(23, 32, 51, 0.08);
        color: #172033;
    }

    @media (max-width: 960px) {
        .calendar-grid {
            gap: 0.5rem;
        }

        .weekday-label {
            @apply text-[0.65rem];
        }

        .calendar-day {
            @apply min-h-[7rem] p-2;
        }

        .calendar-day-week {
            @apply min-h-[18rem];
        }

        .calendar-entry {
            @apply px-2 py-2;
        }
    }

    @media (max-width: 720px) {
        .calendar-toolbar {
            @apply items-stretch;
        }

        .calendar-nav {
            @apply justify-between;
        }

        .calendar-grid-head,
        .calendar-grid {
            min-width: 46rem;
        }

        .calendar-card {
            overflow-x: auto;
        }
    }
</style>
