<script>
	import { createEventDispatcher, onMount, onDestroy } from 'svelte';
	import { marked } from 'marked';
	import DOMPurify from 'dompurify';
	import { ttsEnabled, isUserMuted, toggleUserMute, ttsMutedUsers } from '$lib/chat/ttsStore';
	import { stickerFavorites } from '$lib/chat/stickerFavorites';
	import { stickersMap as sharedStickersMap, ensureLoaded } from '$lib/stores/stickers';

	export let message;
	export let currentUserId;
	export let currentUsername = '';
	export let isModerator = false;
	export let isAdmin = false;
	export let terminalMode = false; // When true, stickers render as small or text based on renderStickers
	export let renderStickers = true; // Only used when terminalMode=true: false shows :stickername: as text
	export let showHeader = true; // Show username/avatar header (false for consecutive messages from same user)
	export let currentRealmId = null; // Current realm being viewed (to hide redundant realm tags)
	export let headerBelow = false; // When true, show header below message content (for messages-from-bottom layout)

	// Reactive check if this user is TTS muted
	$: isTtsMuted = $ttsMutedUsers.has(message.userId);

	const dispatch = createEventDispatcher();

	// Admins and mods have moderation powers
	$: hasModPowers = isModerator || isAdmin;
	$: isOwnMessage = message.userId === currentUserId;
	$: canModerate = hasModPowers && !isOwnMessage;
	$: canDeleteOwn = hasModPowers && isOwnMessage;  // Mods/admins can delete their own messages
	$: showRealmTag = message.realmId && message.realmId !== 'null' && currentRealmId && currentRealmId !== 'null' && String(message.realmId) !== String(currentRealmId);

	let showModMenu = false;
	let parsedContent = '';

	// Sticker context menu
	let stickerContextMenu = null; // { x, y, stickerName }

	// Self-destruct countdown
	let countdownSeconds = 0;
	let countdownInterval = null;
	$: hasSelfDestruct = message.selfDestructAt && message.selfDestructAt > 0;

	function updateCountdown() {
		if (!message.selfDestructAt) return;
		const now = Date.now();
		const remaining = Math.max(0, Math.ceil((message.selfDestructAt - now) / 1000));
		countdownSeconds = remaining;
		if (remaining <= 0 && countdownInterval) {
			clearInterval(countdownInterval);
			countdownInterval = null;
		}
	}

	function formatCountdown(seconds) {
		if (seconds >= 60) {
			const m = Math.floor(seconds / 60);
			const s = seconds % 60;
			return `${m}:${s.toString().padStart(2, '0')}`;
		}
		return `${seconds}s`;
	}

	// Configure marked.js
	marked.setOptions({
		breaks: true,
		gfm: true
	});

	onMount(async () => {
		// Set up self-destruct countdown if applicable
		if (message.selfDestructAt && message.selfDestructAt > 0) {
			updateCountdown();
			countdownInterval = setInterval(updateCountdown, 1000);
		}

		// Ensure stickers are loaded (uses shared store - only fetches once across all components)
		await ensureLoaded();
	});

	onDestroy(() => {
		if (countdownInterval) {
			clearInterval(countdownInterval);
		}
	});

	// Track if current user is mentioned
	let isMentioned = false;
	let hasFiredMentionEvent = false;

	// Re-run when message.content, $sharedStickersMap, OR currentUsername changes
	// The currentUsername dependency is critical for guests - their username is set async via WebSocket
	$: {
		// Pass currentUsername as parameter to ensure reactive updates when it changes
		// Also pass terminalMode and renderStickers for terminal sticker handling
		// Use $sharedStickersMap to trigger re-render when stickers are loaded
		const result = $sharedStickersMap && parseMessage(message.content, currentUsername, terminalMode, renderStickers, $sharedStickersMap);
		parsedContent = result.html;
		// If user is mentioned, highlight and play honk (only fire event once)
		if (result.mentioned) {
			isMentioned = true;
			console.log('[MENTION] Detected mention for', currentUsername, 'in message:', message.content);
			if (!hasFiredMentionEvent) {
				hasFiredMentionEvent = true;
				console.log('[MENTION] Dispatching mentioned event:', { messageId: message.messageId, timestamp: message.timestamp });
				// Use setTimeout to dispatch event outside reactive block (Svelte quirk)
				setTimeout(() => {
					console.log('[MENTION] Actually dispatching now...');
					dispatch('mentioned', { messageId: message.messageId, timestamp: message.timestamp });
				}, 0);
			} else {
				console.log('[MENTION] Already fired event for this message, skipping');
			}
		}
	}

	function parseMessage(content, username, isTerminal = false, showStickers = true, stickersMap = {}) {
		if (!content) return { html: '', mentioned: false };

		// Limit message length to 500 characters
		let msg = content.slice(0, 500);
		let mentioned = false;

		// Check if current user is mentioned (case-insensitive)
		if (username) {
			const mentionPattern = new RegExp(`@${username.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i');
			mentioned = mentionPattern.test(msg);
		}

		// Handle [graffiti] tags - user pixel art signatures (88x33, displayed at 1:1 scale)
		msg = msg.replace(/\[graffiti\](\/uploads\/graffiti\/[a-f0-9]+\.png)\[\/graffiti\]/gi, (match, url) => {
			return `<img src="${url}" alt="graffiti" class="graffiti-img" style="image-rendering: pixelated; width: 88px; height: 33px;" />`;
		});

		// Step 1: Replace stickers with img tags BEFORE markdown parsing
		// In terminal mode with stickers disabled, skip all sticker replacement (show as :name: text)
		// In terminal mode with stickers enabled, only do inline replacement (small stickers only)

		if (!isTerminal || showStickers) {
			// Normal mode OR terminal with stickers enabled

			if (!isTerminal) {
				// Only do h1/h2 sticker expansion in normal chat mode (not terminal)
				// Replace # :sticker: with h1 containing img
				msg = msg.replace(/^#\s+:(\w+):$/gm, (match, stickerName) => {
					const stickerKey = stickerName.toLowerCase();
					if (stickersMap[stickerKey]) {
						return `# <img src="${stickersMap[stickerKey]}" alt="${stickerName}" title="${stickerName}" data-sticker="${stickerName}" class="sticker-img" />`;
					}
					return match;
				});

				// Replace ## :sticker: with h2 containing img
				msg = msg.replace(/^##\s+:(\w+):$/gm, (match, stickerName) => {
					const stickerKey = stickerName.toLowerCase();
					if (stickersMap[stickerKey]) {
						return `## <img src="${stickersMap[stickerKey]}" alt="${stickerName}" title="${stickerName}" data-sticker="${stickerName}" class="sticker-img" />`;
					}
					return match;
				});
			}

			// Replace inline :sticker: with img tags (all modes with stickers enabled)
			// In terminal mode, # :sticker: stays as text since we skip the h1/h2 processing above
			msg = msg.replace(/:(\w+):/g, (match, stickerName) => {
				const stickerKey = stickerName.toLowerCase();
				if (stickersMap[stickerKey]) {
					return `<img src="${stickersMap[stickerKey]}" alt="${stickerName}" title="${stickerName}" data-sticker="${stickerName}" class="sticker-img" />`;
				}
				return match;
			});
		}
		// If isTerminal && !showStickers, we skip all sticker replacement - they stay as :name: text

		// Step 2: Run marked.js to parse markdown (handles >greentext via blockquotes)
		let html = marked.parse(msg);

		// Step 3: Process redtext syntax (after markdown, before sanitization)
		// Handle both single line and with newline - match entire paragraph content
		html = html.replace(/<p>&lt;&lt;(.+?)<\/p>/gs, '<p class="redtext">&lt;&lt;$1</p>');

		// Step 4: Highlight @mentions (before sanitization)
		// Replace @username with highlighted span
		html = html.replace(/@(\w+)/g, '<span class="mention">@$1</span>');

		// Step 5: Sanitize with DOMPurify - allow img tags and safe CSS
		html = DOMPurify.sanitize(html, {
			ALLOWED_TAGS: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'img', 'br', 'strong', 'em', 'code', 'pre', 'del', 'span'],
			ALLOWED_ATTR: ['src', 'alt', 'title', 'class', 'style', 'data-sticker'],
			FORBID_TAGS: ['a', 'button', 'script'],
			ALLOW_DATA_ATTR: false
		});

		return { html, mentioned };
	}

	function formatTime(timestamp) {
		const date = new Date(timestamp);
		return date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
	}

	function formatEpoch(timestamp) {
		const epoch = new Date(timestamp).getTime();
		// Get last 8 digits of epoch for maximum randomness
		const last8 = String(epoch).slice(-8);
		return `No.${last8}`;
	}

	function handleDelete() {
		dispatch('delete');
		showModMenu = false;
	}

	function handleModAction(action, duration = 0) {
		dispatch('modAction', {
			action,
			userId: message.userId,
			duration,
			reason: ''
		});
		showModMenu = false;
	}

	function handleTtsMute() {
		toggleUserMute(message.userId, message.username);
	}

	function handleUsernameClick(event) {
		event.stopPropagation();
		dispatch('showProfile', {
			username: message.username,
			userId: message.userId,
			isGuest: message.isGuest,
			messageId: message.id,
			position: {
				x: event.clientX,
				y: event.clientY
			}
		});
	}

	function handleUsernameDoubleClick(event) {
		event.stopPropagation();
		dispatch('mention', { username: message.username });
	}

	/**
	 * Sanitize color to prevent CSS injection
	 * Only allows valid hex colors (#RGB or #RRGGBB format)
	 */
	function sanitizeColor(color) {
		if (!color || typeof color !== 'string') {
			return '#FFFFFF';
		}
		// Match #RGB or #RRGGBB format only
		const hexPattern = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
		if (hexPattern.test(color)) {
			return color;
		}
		return '#FFFFFF';
	}

	$: safeUserColor = sanitizeColor(message.userColor);

	function handleContentDblClick(event) {
		// Check if double-clicked element is a sticker image
		const target = event.target;
		if (target.tagName === 'IMG' && target.dataset.sticker) {
			const stickerName = target.dataset.sticker;
			dispatch('copySticker', { stickerName: `:${stickerName}:` });
		}
	}

	function handleContentContextMenu(event) {
		const target = event.target;
		if (target.tagName === 'IMG' && target.dataset.sticker) {
			event.preventDefault();
			stickerContextMenu = {
				x: event.clientX,
				y: event.clientY,
				stickerName: target.dataset.sticker
			};
		}
	}

	function closeStickerContextMenu() {
		stickerContextMenu = null;
	}

	function openStickerInNewTab() {
		if (stickerContextMenu) {
			const url = $sharedStickersMap[stickerContextMenu.stickerName.toLowerCase()];
			if (url) {
				window.open(url, '_blank');
			}
		}
		stickerContextMenu = null;
	}

	function copyStickerLink() {
		if (stickerContextMenu) {
			const url = $sharedStickersMap[stickerContextMenu.stickerName.toLowerCase()];
			if (url) {
				const fullUrl = window.location.origin + url;
				navigator.clipboard.writeText(fullUrl);
			}
		}
		stickerContextMenu = null;
	}

	function addStickerToFavorites() {
		if (stickerContextMenu) {
			stickerFavorites.toggle(stickerContextMenu.stickerName);
		}
		stickerContextMenu = null;
	}

	// Check if current context menu sticker is already in favorites
	$: isStickerInFavorites = stickerContextMenu ? $stickerFavorites.includes(stickerContextMenu.stickerName) : false;
</script>

<div class="chat-message" class:own-message={isOwnMessage} class:mentioned={isMentioned} class:compact={!showHeader} class:header-below={headerBelow && showHeader}>
	{#if showHeader}
	<div class="message-header">
		{#if message.avatarUrl}
			<img src={message.avatarUrl} alt={message.username} class="user-avatar" />
		{:else}
			<div class="user-avatar-placeholder" style="background: {safeUserColor}">
				{message.username.charAt(0).toUpperCase()}
			</div>
		{/if}
		<button class="username-btn" style="color: {safeUserColor}" on:click={handleUsernameClick} on:dblclick={handleUsernameDoubleClick}>
			{message.username}
			{#if message.isStreamer}
				<span class="badge streamer">STREAMER</span>
			{/if}
			{#if message.isGuest}
				<span class="badge guest">GUEST</span>
			{/if}
		</button>
		{#if message.usedRoll}
			<span class="cmd-tag roll-tag">R</span>
		{/if}
		{#if message.usedRtd}
			<span class="cmd-tag rtd-tag">D</span>
		{/if}
		{#if showRealmTag}
			<a href="/{message.realmId}/live" class="realm-link" title="Go to {message.realmId}'s stream">
				{message.realmId}
			</a>
		{/if}
		{#if hasSelfDestruct && countdownSeconds > 0}
			<span class="self-destruct-indicator" title="Self-destructing message">
				<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor">
					<path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z"/>
					<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z"/>
				</svg>
				{formatCountdown(countdownSeconds)}
			</span>
		{/if}

		{#if $ttsEnabled && !isOwnMessage}
			<button
				class="tts-mute-btn"
				class:muted={isTtsMuted}
				on:click={handleTtsMute}
				title={isTtsMuted ? `Unmute ${message.username} TTS` : `Mute ${message.username} TTS`}
			>
				{#if isTtsMuted}
					<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
						<path d="M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06z"/>
						<path d="M10.707 4.293a.5.5 0 0 1 0 .707L9.414 6.293l1.293 1.293a.5.5 0 0 1-.707.707L8.707 7 7.414 8.293a.5.5 0 0 1-.707-.707L8 6.293 6.707 5a.5.5 0 0 1 .707-.707L8.707 5.586l1.293-1.293a.5.5 0 0 1 .707 0z"/>
					</svg>
				{:else}
					<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
						<path d="M11.536 14.01A8.473 8.473 0 0 0 14.026 8a8.473 8.473 0 0 0-2.49-6.01l-.708.707A7.476 7.476 0 0 1 13.025 8c0 2.071-.84 3.946-2.197 5.303l.708.707z"/>
						<path d="M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.483 5.483 0 0 1 11.025 8a5.483 5.483 0 0 1-1.61 3.89l.706.706z"/>
						<path d="M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06z"/>
					</svg>
				{/if}
			</button>
		{/if}

		<div class="header-meta">
			{#if canModerate}
				<button class="mod-button" on:click={() => (showModMenu = !showModMenu)}>⋮</button>
			{:else if canDeleteOwn}
				<button class="self-delete-btn" on:click={handleDelete} title="Delete your message">
					<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor">
						<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
						<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
					</svg>
				</button>
			{/if}
			<span class="timestamp">{formatTime(message.timestamp)}</span>
			<span class="epoch">{formatEpoch(message.timestamp)}</span>
		</div>
	</div>
	{/if}

	<div class="message-row">
		<div class="message-content" on:dblclick={handleContentDblClick} on:contextmenu={handleContentContextMenu}>
			{@html parsedContent}
		</div>
		{#if !showHeader}
		<div class="compact-meta">
			{#if canModerate}
				<button class="mod-button" on:click={() => (showModMenu = !showModMenu)}>⋮</button>
			{:else if canDeleteOwn}
				<button class="self-delete-btn" on:click={handleDelete} title="Delete your message">
					<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor">
						<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
						<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
					</svg>
				</button>
			{/if}
			<span class="timestamp">{formatTime(message.timestamp)}</span>
			<span class="epoch">{formatEpoch(message.timestamp)}</span>
		</div>
		{/if}
	</div>

	{#if showModMenu}
		<div class="mod-menu">
			<button on:click={handleDelete}>Delete Message</button>
			<button on:click={() => handleModAction('mute', 0)}>Mute</button>
			<button on:click={() => handleModAction('ban')}>Ban</button>
		</div>
	{/if}
</div>

<svelte:window on:click={closeStickerContextMenu} />

{#if stickerContextMenu}
	<div
		class="sticker-context-menu"
		style="left: {stickerContextMenu.x}px; top: {stickerContextMenu.y}px;"
		on:click|stopPropagation
	>
		<button on:click={openStickerInNewTab}>
			<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
				<path fill-rule="evenodd" d="M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z"/>
				<path fill-rule="evenodd" d="M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z"/>
			</svg>
			Open in new tab
		</button>
		<button on:click={copyStickerLink}>
			<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
				<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
				<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
			</svg>
			Copy image link
		</button>
		{#if !isStickerInFavorites}
			<button on:click={addStickerToFavorites}>
				<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor">
					<path d="M2 2v13.5a.5.5 0 0 0 .74.439L8 13.069l5.26 2.87A.5.5 0 0 0 14 15.5V2a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2zm2-1h8a1 1 0 0 1 1 1v12.566l-4.723-2.576a.5.5 0 0 0-.554 0L3 14.566V2a1 1 0 0 1 1-1z"/>
					<path d="M8 4a.5.5 0 0 1 .5.5V6H10a.5.5 0 0 1 0 1H8.5v1.5a.5.5 0 0 1-1 0V7H6a.5.5 0 0 1 0-1h1.5V4.5A.5.5 0 0 1 8 4z"/>
				</svg>
				Add to favorites
			</button>
		{/if}
	</div>
{/if}

<style>
	.chat-message {
		display: flex;
		flex-direction: column;
		padding: 0.1rem 0.2rem;
		border-radius: 2px;
		background: #000;
		transition: background 0.2s;
		position: relative;
	}

	.chat-message:hover {
		background: #111;
	}

	.chat-message.own-message {
		background: #000;
	}

	.chat-message.compact {
		padding-top: 0.05rem;
		padding-bottom: 0.05rem;
	}

	/* Header below message content (for messages-from-bottom layout) */
	.chat-message.header-below {
		flex-direction: column-reverse;
	}

	.chat-message.header-below .message-header {
		margin-bottom: 0;
		margin-top: 0;
	}

	.message-header {
		display: flex;
		align-items: center;
		gap: 0.3rem;
		margin-bottom: 0;
		font-size: 0.75rem;
	}

	.user-avatar {
		width: 18px;
		height: 18px;
		object-fit: cover;
		flex-shrink: 0;
		cursor: pointer;
		transition: all 0.2s ease;
		position: relative;
		z-index: 1;
	}

	.user-avatar:hover {
		transform: scale(2.0);
		z-index: 100;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
	}

	.user-avatar-placeholder {
		width: 18px;
		height: 18px;
		display: flex;
		align-items: center;
		justify-content: center;
		font-size: 0.55rem;
		font-weight: 700;
		color: #fff;
		flex-shrink: 0;
		background: #666;
		cursor: pointer;
		transition: all 0.2s ease;
		position: relative;
		z-index: 1;
	}

	.user-avatar-placeholder:hover {
		transform: scale(2.0);
		z-index: 100;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
	}

	.username-btn {
		font-weight: 600;
		display: flex;
		align-items: center;
		gap: 0.25rem;
		background: none;
		border: none;
		padding: 0;
		cursor: pointer;
		font-size: inherit;
		font-family: inherit;
		transition: filter 0.15s ease;
	}

	.username-btn:hover {
		filter: invert(1);
	}

	.badge {
		font-size: 0.55rem;
		padding: 0.05rem 0.25rem;
		border-radius: 2px;
		text-transform: uppercase;
		font-weight: 700;
		letter-spacing: 0.5px;
	}

	.badge.streamer {
		background: #9b59b6;
		color: #fff;
	}

	.badge.moderator {
		background: #27ae60;
		color: #fff;
	}

	.badge.guest {
		background: #666;
		color: #fff;
	}

	.cmd-tag {
		font-size: 0.55rem;
		padding: 0.05rem 0.25rem;
		border-radius: 2px;
		font-weight: 700;
		background: #888;
		color: #000;
	}

	.realm-link {
		color: #888;
		font-size: 0.6rem;
		text-decoration: none;
		padding: 0.05rem 0.25rem;
		background: rgba(145, 70, 255, 0.15);
		border-radius: 2px;
		transition: all 0.15s ease;
		margin-left: 0.15rem;
	}

	.realm-link:hover {
		color: #9146ff;
		background: rgba(145, 70, 255, 0.3);
		text-decoration: none;
	}

	.header-meta {
		display: flex;
		align-items: center;
		gap: 0.2rem;
		margin-left: auto;
	}

	.timestamp {
		color: #666;
		font-size: 0.65rem;
	}

	.epoch {
		color: #555;
		font-size: 0.6rem;
		font-family: monospace;
	}

	.self-destruct-indicator {
		display: flex;
		align-items: center;
		gap: 0.25rem;
		color: #ff9800;
		font-size: 0.7rem;
		font-weight: 600;
		padding: 0.125rem 0.375rem;
		background: rgba(255, 152, 0, 0.15);
		border-radius: 3px;
		animation: pulse 2s ease-in-out infinite;
	}

	@keyframes pulse {
		0%, 100% { opacity: 1; }
		50% { opacity: 0.6; }
	}

	.mod-button {
		background: none;
		border: none;
		color: #666;
		cursor: pointer;
		padding: 0 0.25rem;
		font-size: 1rem;
		line-height: 1;
		opacity: 0;
		transition: all 0.2s;
	}

	.chat-message:hover .mod-button {
		opacity: 1;
	}

	.mod-button:hover {
		color: #fff;
	}

	.message-row {
		display: flex;
		align-items: flex-start;
		gap: 0.3rem;
	}

	.compact-meta {
		display: flex;
		align-items: center;
		gap: 0.2rem;
		flex-shrink: 0;
		margin-left: auto;
	}

	.message-content {
		color: #ddd;
		line-height: 1.25;
		word-wrap: break-word;
		flex: 1;
		min-width: 0;
		font-size: 0.8rem;
	}

	/* Heading styles */
	.message-content :global(h1),
	.message-content :global(h2),
	.message-content :global(h3),
	.message-content :global(h4),
	.message-content :global(h5),
	.message-content :global(h6) {
		line-height: 1.0;
		margin-bottom: 0 !important;
		font-weight: 700;
	}

	.message-content :global(h1) {
		font-size: 1.375rem;
	}

	.message-content :global(h2) {
		font-size: 1.25rem;
	}

	.message-content :global(h3) {
		font-size: 1rem;
	}

	.message-content :global(h4) {
		font-size: 0.875rem;
		font-weight: 500;
	}

	.message-content :global(h5) {
		font-size: 0.75rem;
		font-weight: 500;
	}

	.message-content :global(h6) {
		font-size: 0.5rem;
		font-weight: 500;
	}

	/* Greentext - markdown blockquotes */
	.message-content :global(blockquote) {
		margin: 0;
		margin-inline-start: 0;
		margin-inline-end: 0;
		padding: 0;
		display: block;
		background-repeat: no-repeat;
		overflow-wrap: break-word;
	}

	.message-content :global(blockquote p) {
		font-weight: 500;
		color: #789922;
		margin: 0;
		padding: 0;
		display: block;
		background-repeat: no-repeat;
		overflow-wrap: break-word;
	}

	.message-content :global(blockquote p::before) {
		content: '>';
	}

	.message-content :global(blockquote h1) {
		font-weight: bold;
		color: #789922;
		margin: 0;
		padding: 0;
		display: block;
		background-repeat: no-repeat;
		overflow-wrap: break-word;
	}

	.message-content :global(blockquote h1::before) {
		content: '>';
	}

	/* Redtext - custom syntax */
	.message-content :global(.redtext) {
		font-weight: 500;
		color: #cc1105;
		display: block;
	}

	/* Default size for all images (inline stickers) */
	.message-content :global(img) {
		max-height: 33px;
		max-width: 200px;
		height: auto;
		width: auto;
		vertical-align: middle;
	}

	/* Inline stickers in paragraphs */
	.message-content :global(p img) {
		max-height: 33px;
		max-width: 200px;
		height: auto;
		width: auto;
		vertical-align: middle;
	}

	.message-content :global(.sticker-inline) {
		max-height: 33px;
		max-width: 200px;
		height: auto;
		width: auto;
		vertical-align: middle;
		margin: 0 2px;
	}

	/* Full-size stickers in h1 */
	.message-content :global(h1 img) {
		max-width: 475px;
		max-height: none;
		height: auto;
		width: auto;
		vertical-align: bottom;
	}

	@media (max-width: 768px) {
		.message-content :global(h1 img) {
			max-width: 33vw;
			max-height: none;
			height: auto;
			width: auto;
		}
	}

	/* Horizontally flipped stickers in h2 */
	.message-content :global(h2 img) {
		max-width: 475px;
		max-height: none;
		height: auto;
		width: auto;
		transform: scaleX(-1);
		vertical-align: bottom;
	}

	@media (max-width: 768px) {
		.message-content :global(h2 img) {
			max-width: 33vw;
			max-height: none;
			height: auto;
			width: auto;
		}
	}

	/* h3 stickers - small flipped */
	.message-content :global(h3 img) {
		max-height: 41px;
		height: auto;
		width: auto;
		transform: scaleX(-1);
		vertical-align: bottom;
	}

	/* h4 stickers - medium size */
	.message-content :global(h4 img) {
		max-height: 82px;
		width: auto;
		vertical-align: bottom;
	}

	/* h5 stickers - full size */
	.message-content :global(h5 img) {
		max-width: 475px;
		max-height: none;
		height: auto;
		width: auto;
		vertical-align: bottom;
	}

	/* h6 stickers - tiny */
	.message-content :global(h6 img) {
		width: auto;
		height: 20.5px;
		vertical-align: bottom;
	}

	.mod-menu {
		position: absolute;
		right: 0;
		top: 100%;
		background: #333;
		border: 1px solid #444;
		border-radius: 4px;
		padding: 0.25rem;
		z-index: 10;
		display: flex;
		flex-direction: column;
		gap: 0.25rem;
		min-width: 150px;
	}

	.mod-menu button {
		background: #444;
		border: none;
		color: #fff;
		padding: 0.5rem;
		border-radius: 3px;
		cursor: pointer;
		text-align: left;
		font-size: 0.875rem;
	}

	.mod-menu button:hover {
		background: #555;
	}

	/* TTS mute button */
	.tts-mute-btn {
		background: none;
		border: none;
		color: #666;
		cursor: pointer;
		padding: 2px;
		display: flex;
		align-items: center;
		justify-content: center;
		opacity: 0;
		transition: all 0.2s;
		border-radius: 3px;
	}

	.chat-message:hover .tts-mute-btn {
		opacity: 1;
	}

	.tts-mute-btn:hover {
		color: #999;
		background: rgba(255, 255, 255, 0.1);
	}

	.tts-mute-btn.muted {
		color: #f44336;
		opacity: 1;
	}

	.tts-mute-btn.muted:hover {
		color: #ff6659;
	}

	/* Self-delete button for mods */
	.self-delete-btn {
		background: none;
		border: none;
		color: #666;
		cursor: pointer;
		padding: 2px;
		display: flex;
		align-items: center;
		justify-content: center;
		opacity: 0;
		transition: all 0.2s;
		border-radius: 3px;
	}

	.chat-message:hover .self-delete-btn {
		opacity: 1;
	}

	.self-delete-btn:hover {
		color: #f44336;
		background: rgba(244, 67, 54, 0.1);
	}

	/* Sticker context menu - must be global since it's outside the component div */
	:global(.sticker-context-menu) {
		position: fixed;
		background: #1a1a1a;
		border: 1px solid #333;
		border-radius: 6px;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
		z-index: 1000;
		overflow: hidden;
	}

	:global(.sticker-context-menu button) {
		display: flex;
		align-items: center;
		gap: 0.5rem;
		width: 100%;
		padding: 0.6rem 0.75rem;
		background: none;
		border: none;
		color: #ccc;
		font-size: 0.85rem;
		cursor: pointer;
		text-align: left;
		white-space: nowrap;
	}

	:global(.sticker-context-menu button:hover) {
		background: rgba(255, 255, 255, 0.1);
		color: #fff;
	}

	/* Mentioned message styling */
	.chat-message.mentioned {
		background: rgba(255, 215, 0, 0.1);
		border-left: 2px solid #ffd700;
	}

	.chat-message.mentioned:hover {
		background: rgba(255, 215, 0, 0.15);
	}

	.chat-message.mentioned .message-content {
		color: #fff;
		font-weight: 600;
	}

	/* @mention highlighting */
	.message-content :global(.mention) {
		color: #ffd700;
		font-weight: 700;
		background: rgba(255, 215, 0, 0.2);
		padding: 0 0.25rem;
		border-radius: 3px;
	}

	/* Graffiti images - override generic img rules to maintain exact size */
	.message-content :global(.graffiti-img) {
		width: 88px !important;
		height: 33px !important;
		max-width: none !important;
		max-height: none !important;
		image-rendering: pixelated;
		vertical-align: middle;
	}
</style>
