/**
 * <rstack-history-panel> — Document history slide-out panel.
 *
 * Activity feed shows Automerge change history with author attribution,
 * grouped by author within time windows. Time Machine tab provides a
 * scrubber over the change timeline to view document state at any point.
 */

import * as Automerge from "@automerge/automerge";
import { parseChangeMessage, type ParsedChangeMessage } from "../local-first/change-message";

// ── Types ──

export interface HistoryEntry {
	hash: string;
	actor: string;
	username: string;
	time: number;
	message: string;
	opsCount: number;
	seq: number;
}

export interface GroupedEntry {
	username: string;
	entries: HistoryEntry[];
	timeRange: { start: number; end: number };
	summary: string;
}

interface TimeGroup {
	label: string;
	groups: GroupedEntry[];
}

// ── Component ──

export class RStackHistoryPanel extends HTMLElement {
	private _open = false;
	private _tab: "activity" | "timemachine" = "activity";
	private _doc: Automerge.Doc<any> | null = null;
	private _entries: HistoryEntry[] = [];
	private _visibleCount = 50;
	private _timeMachineIndex = -1;
	private _timeMachineSnapshot: any = null;
	private _docChangeHandler: (() => void) | null = null;

	static define() {
		if (!customElements.get("rstack-history-panel")) {
			customElements.define("rstack-history-panel", RStackHistoryPanel);
		}
	}

	private _clickOutsideHandler = (e: MouseEvent) => {
		const path = e.composedPath();
		if (!path.includes(this) && !path.includes(document.getElementById("history-btn")!)) {
			this.close();
		}
	};

	private _syncReadyHandler = (e: Event) => {
		const sync = (e as CustomEvent).detail?.sync;
		if (sync?.doc) {
			this._doc = sync.doc;
			if (this._open) {
				this._refreshHistory();
				this._render();
			}
		}
	};

	connectedCallback() {
		if (!this.shadowRoot) this.attachShadow({ mode: "open" });
		this._render();
		// Pick up CommunitySync when it connects (may be after mount)
		document.addEventListener("community-sync-ready", this._syncReadyHandler);
	}

	disconnectedCallback() {
		document.removeEventListener("click", this._clickOutsideHandler, true);
		document.removeEventListener("community-sync-ready", this._syncReadyHandler);
	}

	open() {
		this._open = true;
		// Lazy doc acquisition: try CommunitySync global first, then offline runtime
		if (!this._doc) {
			const sync = (window as any).__communitySync;
			if (sync?.doc) {
				this._doc = sync.doc;
			} else {
				const rt = (window as any).__rspaceOfflineRuntime;
				if (rt?.documentManager) {
					const docs = rt.documentManager.listAll?.() || [];
					if (docs.length > 0) {
						const doc = rt.documentManager.get(docs[0]);
						if (doc) this._doc = doc;
					}
				}
			}
		}
		this._refreshHistory();
		this._render();
		document.getElementById("history-btn")?.classList.add("active");
		document.addEventListener("click", this._clickOutsideHandler, true);
	}

	close() {
		this._open = false;
		this._timeMachineSnapshot = null;
		this._render();
		document.getElementById("history-btn")?.classList.remove("active");
		document.removeEventListener("click", this._clickOutsideHandler, true);
	}

	toggle() {
		if (this._open) this.close(); else this.open();
	}

	/** Position the panel below the history button, right-aligned to button, clamped to viewport. */
	private _positionPanel() {
		const panel = this.shadowRoot?.querySelector(".panel") as HTMLElement | null;
		const btn = document.getElementById("history-btn");
		if (!panel || !btn) return;
		const rect = btn.getBoundingClientRect();
		const topPos = rect.bottom + 6;
		panel.style.top = `${topPos}px`;
		// Clamp max-height so panel never overflows bottom of viewport
		panel.style.maxHeight = `${window.innerHeight - topPos - 8}px`;
		// Right-align to button's right edge, but clamp so left edge stays on screen
		const rightOffset = window.innerWidth - rect.right;
		panel.style.right = `${rightOffset}px`;
		panel.style.left = "auto";
		// After layout, check if panel overflows left edge
		requestAnimationFrame(() => {
			const panelRect = panel.getBoundingClientRect();
			if (panelRect.left < 8) {
				panel.style.right = "auto";
				panel.style.left = "8px";
			}
		});
	}

	setDoc(doc: Automerge.Doc<any>) {
		this._doc = doc;
		if (this._open) {
			this._refreshHistory();
			this._render();
		}
	}

	// ── History extraction ──

	private _refreshHistory() {
		if (!this._doc) {
			this._entries = [];
			return;
		}

		try {
			const changes = Automerge.getHistory(this._doc);
			this._entries = changes.map((entry, i) => {
				const change = entry.change;
				const parsed = parseChangeMessage(change.message || null);
				return {
					hash: change.hash || `change-${i}`,
					actor: change.actor || "unknown",
					username: parsed.user || "Unknown",
					time: parsed.ts || (change.time ? change.time * 1000 : 0),
					message: parsed.text,
					opsCount: change.ops?.length || 0,
					seq: change.seq || i,
				};
			});
		} catch (e) {
			console.warn("[HistoryPanel] Failed to extract history:", e);
			this._entries = [];
		}
	}

	// ── Grouping ──

	private _groupEntries(): TimeGroup[] {
		const entries = this._entries.slice(-this._visibleCount).reverse();
		if (entries.length === 0) return [];

		// Group by same author within 5-minute windows
		const grouped: GroupedEntry[] = [];
		let current: GroupedEntry | null = null;
		const WINDOW = 5 * 60 * 1000;

		for (const entry of entries) {
			if (
				current &&
				current.username === entry.username &&
				entry.time - current.timeRange.end < WINDOW
			) {
				current.entries.push(entry);
				current.timeRange.start = Math.min(current.timeRange.start, entry.time);
				current.timeRange.end = Math.max(current.timeRange.end, entry.time);
			} else {
				current = {
					username: entry.username,
					entries: [entry],
					timeRange: { start: entry.time, end: entry.time },
					summary: "",
				};
				grouped.push(current);
			}
		}

		// Build summaries
		for (const g of grouped) {
			g.summary = this._buildSummary(g.entries);
		}

		// Nest into time groups
		const now = Date.now();
		const todayStart = new Date(); todayStart.setHours(0, 0, 0, 0);
		const yesterdayStart = new Date(todayStart); yesterdayStart.setDate(yesterdayStart.getDate() - 1);
		const weekStart = new Date(todayStart); weekStart.setDate(weekStart.getDate() - 7);

		const timeGroups: TimeGroup[] = [];
		const buckets: Record<string, GroupedEntry[]> = {};

		for (const g of grouped) {
			const t = g.timeRange.end;
			let label: string;
			if (t >= todayStart.getTime()) label = "Today";
			else if (t >= yesterdayStart.getTime()) label = "Yesterday";
			else if (t >= weekStart.getTime()) label = "This Week";
			else label = "Older";

			if (!buckets[label]) buckets[label] = [];
			buckets[label].push(g);
		}

		for (const label of ["Today", "Yesterday", "This Week", "Older"]) {
			if (buckets[label]?.length) {
				timeGroups.push({ label, groups: buckets[label] });
			}
		}

		return timeGroups;
	}

	private _buildSummary(entries: HistoryEntry[]): string {
		const actions: Record<string, number> = {};
		for (const e of entries) {
			const msg = e.message.toLowerCase();
			if (msg.startsWith("update shape")) actions["moved/edited shapes"] = (actions["moved/edited shapes"] || 0) + 1;
			else if (msg.startsWith("update layer")) actions["updated layers"] = (actions["updated layers"] || 0) + 1;
			else if (msg.startsWith("update")) actions["updated items"] = (actions["updated items"] || 0) + 1;
			else if (msg.startsWith("add shape") || msg.startsWith("add ")) actions["added"] = (actions["added"] || 0) + 1;
			else if (msg.startsWith("delete") || msg.startsWith("remove")) actions["removed"] = (actions["removed"] || 0) + 1;
			else if (msg.startsWith("forget")) actions["forgot"] = (actions["forgot"] || 0) + 1;
			else if (msg.startsWith("remember")) actions["restored"] = (actions["restored"] || 0) + 1;
			else if (msg.startsWith("undo")) actions["undid"] = (actions["undid"] || 0) + 1;
			else if (msg.startsWith("redo")) actions["redid"] = (actions["redid"] || 0) + 1;
			else actions["changed"] = (actions["changed"] || 0) + 1;
		}
		return Object.entries(actions)
			.map(([action, count]) => `${action}: ${count}`)
			.join("  ·  ");
	}

	/** Turn raw Automerge change messages into human-readable text with icons. */
	private _humanizeMessage(msg: string): { icon: string; text: string } {
		// Strip shape/layer/flow UUIDs for readability
		const short = msg.replace(/\s+[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "")
			.replace(/\s+[a-z]+-[a-z0-9]{6,}/gi, ""); // short IDs like folk-abc123

		const m = msg.toLowerCase();
		if (m.startsWith("update shape")) return { icon: "✏️", text: "Edited shape" };
		if (m.startsWith("add shape")) return { icon: "➕", text: "Added shape" };
		if (m.startsWith("delete shape")) return { icon: "🗑", text: "Deleted shape" };
		if (m.startsWith("forget shape")) return { icon: "👻", text: "Forgot shape" };
		if (m.startsWith("remember shape")) return { icon: "💡", text: "Restored shape" };
		if (m.startsWith("undo delete")) return { icon: "↩️", text: "Undid delete" };
		if (m.startsWith("undo")) return { icon: "↩️", text: "Undo" };
		if (m.startsWith("redo")) return { icon: "↪️", text: "Redo" };
		if (m.startsWith("add layer")) return { icon: "📑", text: "Added layer" };
		if (m.startsWith("remove layer")) return { icon: "📑", text: "Removed layer" };
		if (m.startsWith("update layer")) return { icon: "📑", text: "Updated layer" };
		if (m.startsWith("add flow")) return { icon: "🔀", text: "Added flow" };
		if (m.startsWith("remove flow")) return { icon: "🔀", text: "Removed flow" };
		if (m.startsWith("add connection")) return { icon: "🔗", text: "Added connection" };
		if (m.startsWith("remove connection")) return { icon: "🔗", text: "Removed connection" };
		if (m.startsWith("event:")) return { icon: "⚡", text: short.trim() };
		if (m.startsWith("subscribe")) return { icon: "📡", text: "Subscribed shape" };
		if (m.startsWith("set view mode")) return { icon: "👁", text: short.trim() };
		if (m.startsWith("initialize")) return { icon: "🏗", text: "Initialized space" };
		return { icon: "·", text: short.trim() || msg };
	}

	// ── Time Machine ──

	private _onScrub(index: number) {
		if (!this._doc || this._entries.length === 0) return;
		this._timeMachineIndex = index;

		try {
			const changes = Automerge.getHistory(this._doc);
			if (index >= 0 && index < changes.length) {
				// Get heads at this point in history
				const hash = changes[index].change.hash;
				if (hash) {
					this._timeMachineSnapshot = Automerge.view(this._doc, [hash]);
				}
			}
		} catch (e) {
			console.warn("[HistoryPanel] Time machine error:", e);
		}

		this._renderTimeMachineDetails();
	}

	// ── Rendering ──

	private _render() {
		if (!this.shadowRoot) return;

		if (!this._open) {
			this.shadowRoot.innerHTML = "";
			return;
		}

		const timeGroups = this._groupEntries();

		const activityHTML = timeGroups.length === 0
			? '<div class="empty-state">No history available yet. Make some changes to see them here.</div>'
			: timeGroups.map(tg => `
				<div class="time-group">
					<div class="time-group__label">${tg.label}</div>
					${tg.groups.map(g => `
						<div class="activity-group">
							<div class="activity-group__header">
								<div class="activity-group__avatar">${this._initial(g.username)}</div>
								<div class="activity-group__info">
									<span class="activity-group__user">${this._esc(g.username)}</span>
									<span class="activity-group__time">${this._relativeTime(g.timeRange.end)}</span>
								</div>
							</div>
							<div class="activity-group__summary">${this._esc(g.summary)}</div>
							<div class="activity-group__details">
								${g.entries.slice(0, 8).map(e => {
									const h = this._humanizeMessage(e.message);
									const t = e.time ? this._shortTime(e.time) : "";
									return `
									<div class="activity-entry">
										<span class="activity-entry__icon">${h.icon}</span>
										<span class="activity-entry__msg">${this._esc(h.text)}</span>
										<span class="activity-entry__time">${t}</span>
									</div>`;
								}).join("")}
								${g.entries.length > 8 ? `<div class="activity-entry activity-entry--more">+${g.entries.length - 8} more</div>` : ""}
							</div>
						</div>
					`).join("")}
				</div>
			`).join("");

		const totalChanges = this._entries.length;
		const scrubberMax = Math.max(0, totalChanges - 1);
		const scrubberVal = this._timeMachineIndex >= 0 ? this._timeMachineIndex : scrubberMax;

		const timeMachineHTML = totalChanges === 0
			? '<div class="empty-state">No history to scrub. Make some changes first.</div>'
			: `
				<div class="time-machine">
					<div class="time-machine__scrubber">
						<label class="time-machine__label">Change ${scrubberVal + 1} of ${totalChanges}</label>
						<input type="range" class="time-machine__range" min="0" max="${scrubberMax}" value="${scrubberVal}" id="tm-scrubber" />
					</div>
					<div class="time-machine__details" id="tm-details">
						<div class="empty-state">Drag the slider to view document state at any point in time.</div>
					</div>
				</div>
			`;

		this.shadowRoot.innerHTML = `
			<style>${PANEL_CSS}</style>
			<div class="panel">
				<div class="panel-header">
					<h2>History</h2>
					<button class="close-btn" id="close-btn">&times;</button>
				</div>
				<div class="tabs">
					<button class="tab ${this._tab === "activity" ? "active" : ""}" data-tab="activity">Activity</button>
					<button class="tab ${this._tab === "timemachine" ? "active" : ""}" data-tab="timemachine">Time Machine</button>
				</div>
				<div class="panel-content">
					${this._tab === "activity" ? activityHTML : timeMachineHTML}
				</div>
				${this._entries.length > this._visibleCount && this._tab === "activity" ? `
					<div class="load-more">
						<button class="load-more__btn" id="load-more-btn">Load more</button>
					</div>
				` : ""}
			</div>
		`;

		this._bindEvents();
		// Re-position after every render since innerHTML replacement destroys inline styles
		if (this._open) this._positionPanel();
	}

	private _renderTimeMachineDetails() {
		const details = this.shadowRoot?.getElementById("tm-details");
		if (!details) return;

		const entry = this._entries[this._timeMachineIndex];
		if (!entry) {
			details.innerHTML = '<div class="empty-state">Select a point in history.</div>';
			return;
		}

		const parsed = parseChangeMessage(entry.message);

		// Show snapshot info
		const shapeCount = this._timeMachineSnapshot?.shapes
			? Object.keys(this._timeMachineSnapshot.shapes).length
			: 0;

		details.innerHTML = `
			<div class="tm-info">
				<div class="tm-info__row">
					<span class="tm-info__label">Time</span>
					<span class="tm-info__value">${entry.time ? new Date(entry.time).toLocaleString() : "Unknown"}</span>
				</div>
				<div class="tm-info__row">
					<span class="tm-info__label">Author</span>
					<span class="tm-info__value">${this._esc(entry.username)}</span>
				</div>
				<div class="tm-info__row">
					<span class="tm-info__label">Message</span>
					<span class="tm-info__value">${this._esc(entry.message)}</span>
				</div>
				<div class="tm-info__row">
					<span class="tm-info__label">Operations</span>
					<span class="tm-info__value">${entry.opsCount}</span>
				</div>
				${this._timeMachineSnapshot ? `
				<div class="tm-info__row">
					<span class="tm-info__label">Shapes at this point</span>
					<span class="tm-info__value">${shapeCount}</span>
				</div>
				` : ""}
			</div>
			<button class="revert-btn" id="revert-btn">Revert to this point</button>
		`;

		// Update the label
		const label = this.shadowRoot?.querySelector(".time-machine__label");
		if (label) label.textContent = `Change ${this._timeMachineIndex + 1} of ${this._entries.length}`;
	}

	private _bindEvents() {
		const sr = this.shadowRoot!;

		sr.getElementById("close-btn")?.addEventListener("click", () => this.close());

		// Tab switching
		sr.querySelectorAll(".tab").forEach(btn => {
			btn.addEventListener("click", () => {
				this._tab = (btn as HTMLElement).dataset.tab as "activity" | "timemachine";
				this._render();
			});
		});

		// Load more
		sr.getElementById("load-more-btn")?.addEventListener("click", () => {
			this._visibleCount += 50;
			this._render();
		});

		// Time machine scrubber
		const scrubber = sr.getElementById("tm-scrubber") as HTMLInputElement;
		if (scrubber) {
			scrubber.addEventListener("input", () => {
				this._onScrub(parseInt(scrubber.value, 10));
			});
		}

		// Revert to history point
		sr.getElementById("revert-btn")?.addEventListener("click", () => {
			const entry = this._entries[this._timeMachineIndex];
			if (!entry?.hash) return;
			if (!confirm(`Revert to change from ${new Date(entry.time).toLocaleString()} by ${entry.username}?\n\nThis creates a new change that restores the document to that state.`)) return;
			this.dispatchEvent(new CustomEvent("revert-requested", {
				bubbles: true, composed: true,
				detail: { hash: entry.hash, index: this._timeMachineIndex },
			}));
			this.close();
		});
	}

	// ── Helpers ──

	private _initial(name: string): string {
		return (name.charAt(0) || "?").toUpperCase();
	}

	private _relativeTime(ts: number): string {
		if (!ts) return "";
		const diff = Date.now() - ts;
		if (diff < 60_000) return "just now";
		if (diff < 3600_000) return `${Math.floor(diff / 60_000)}m ago`;
		if (diff < 86400_000) return `${Math.floor(diff / 3600_000)}h ago`;
		return new Date(ts).toLocaleDateString();
	}

	private _shortTime(ts: number): string {
		if (!ts) return "";
		const d = new Date(ts);
		return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
	}

	private _esc(s: string): string {
		return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
	}
}

// ── CSS ──

const PANEL_CSS = `
:host {
	display: contents;
}

.panel {
	position: fixed;
	width: min(420px, 92vw);
	max-height: calc(100vh - 72px);
	background: var(--rs-bg-surface, #1e293b);
	border: 1px solid var(--rs-border, #334155);
	border-radius: 12px;
	box-shadow: 0 8px 32px rgba(0,0,0,0.3);
	z-index: 200001;
	display: flex;
	flex-direction: column;
	animation: dropDown 0.2s ease;
	color: var(--rs-text-primary, #e2e8f0);
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

@keyframes dropDown {
	from { opacity: 0; transform: translateY(-8px); }
	to { opacity: 1; transform: translateY(0); }
}

.panel-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 16px 20px;
	border-bottom: 1px solid var(--rs-btn-secondary-bg, #334155);
	flex-shrink: 0;
}

.panel-header h2 {
	margin: 0;
	font-size: 1.1rem;
	font-weight: 600;
	background: linear-gradient(135deg, #14b8a6, #22d3ee);
	-webkit-background-clip: text;
	-webkit-text-fill-color: transparent;
	background-clip: text;
}

.close-btn {
	background: none;
	border: none;
	color: var(--rs-text-muted, #64748b);
	font-size: 1.5rem;
	cursor: pointer;
	padding: 4px 8px;
	border-radius: 4px;
	line-height: 1;
}
.close-btn:hover { color: var(--rs-text-primary); background: var(--rs-btn-secondary-bg); }

/* Tabs */
.tabs {
	display: flex;
	border-bottom: 1px solid var(--rs-btn-secondary-bg, #334155);
	flex-shrink: 0;
}

.tab {
	flex: 1;
	padding: 10px 16px;
	background: none;
	border: none;
	border-bottom: 2px solid transparent;
	color: var(--rs-text-secondary, #94a3b8);
	font-size: 0.82rem;
	font-weight: 600;
	cursor: pointer;
	transition: color 0.15s, border-color 0.15s;
}
.tab:hover { color: var(--rs-text-primary); }
.tab.active {
	color: #14b8a6;
	border-bottom-color: #14b8a6;
}

.panel-content {
	flex: 1;
	overflow-y: auto;
	padding: 0;
}

.empty-state {
	padding: 32px 20px;
	text-align: center;
	color: var(--rs-text-muted, #64748b);
	font-size: 0.85rem;
	line-height: 1.5;
}

/* Time groups */
.time-group {
	padding: 0;
}

.time-group__label {
	position: sticky;
	top: 0;
	padding: 8px 20px;
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--rs-text-muted, #64748b);
	background: var(--rs-bg-surface, #1e293b);
	border-bottom: 1px solid var(--rs-border-subtle, rgba(255,255,255,0.05));
	z-index: 1;
}

/* Activity groups */
.activity-group {
	padding: 12px 20px;
	border-bottom: 1px solid var(--rs-border-subtle, rgba(255,255,255,0.05));
	transition: background 0.15s;
}
.activity-group:hover {
	background: var(--rs-bg-hover, rgba(255,255,255,0.03));
}

.activity-group__header {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 6px;
}

.activity-group__avatar {
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: rgba(20,184,166,0.15);
	color: #14b8a6;
	display: flex;
	align-items: center;
	justify-content: center;
	font-weight: 700;
	font-size: 0.75rem;
	flex-shrink: 0;
}

.activity-group__info {
	display: flex;
	align-items: baseline;
	gap: 8px;
	flex: 1;
	min-width: 0;
}

.activity-group__user {
	font-size: 0.82rem;
	font-weight: 600;
	color: var(--rs-text-primary);
}

.activity-group__time {
	font-size: 0.7rem;
	color: var(--rs-text-muted, #64748b);
}

.activity-group__summary {
	font-size: 0.78rem;
	color: var(--rs-text-secondary, #94a3b8);
	margin-bottom: 6px;
	padding-left: 38px;
}

.activity-group__details {
	padding-left: 38px;
}

.activity-entry {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 3px 0;
	font-size: 0.75rem;
	color: var(--rs-text-secondary, #94a3b8);
}

.activity-entry__icon {
	flex-shrink: 0;
	width: 18px;
	text-align: center;
	font-size: 0.7rem;
}

.activity-entry__msg {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.activity-entry__time {
	flex-shrink: 0;
	font-size: 0.65rem;
	color: var(--rs-text-muted, #64748b);
	opacity: 0.7;
}

.activity-entry--more {
	color: #14b8a6;
	font-style: italic;
}

/* Time Machine */
.time-machine {
	padding: 20px;
}

.time-machine__scrubber {
	margin-bottom: 20px;
}

.time-machine__label {
	display: block;
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--rs-text-secondary);
	margin-bottom: 8px;
}

.time-machine__range {
	width: 100%;
	accent-color: #14b8a6;
	cursor: pointer;
}

.time-machine__details {
	min-height: 100px;
}

.tm-info {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.tm-info__row {
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

.tm-info__label {
	flex: 0 0 90px;
	font-size: 0.72rem;
	font-weight: 600;
	color: var(--rs-text-muted, #64748b);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.tm-info__value {
	flex: 1;
	font-size: 0.82rem;
	color: var(--rs-text-primary);
	word-break: break-word;
}

.revert-btn {
	width: 100%;
	margin-top: 16px;
	padding: 10px;
	background: rgba(239, 68, 68, 0.1);
	border: 1px solid rgba(239, 68, 68, 0.3);
	color: #ef4444;
	border-radius: 8px;
	font-size: 0.8rem;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s;
}
.revert-btn:hover { background: rgba(239, 68, 68, 0.2); }

/* Load more */
.load-more {
	padding: 12px 20px;
	border-top: 1px solid var(--rs-border-subtle, rgba(255,255,255,0.05));
	flex-shrink: 0;
}

.load-more__btn {
	width: 100%;
	padding: 8px;
	background: rgba(20,184,166,0.1);
	border: 1px solid rgba(20,184,166,0.2);
	color: #14b8a6;
	border-radius: 8px;
	font-size: 0.78rem;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s;
}
.load-more__btn:hover {
	background: rgba(20,184,166,0.2);
}
`;
