/**
 * <folk-feed> — Canvas shape that renders a live feed from another layer.
 *
 * Bridges layers by pulling data from a source layer's module API endpoint
 * and rendering it as a live, updating feed within the current canvas.
 *
 * Attributes:
 *   source-layer  — source layer ID
 *   source-module — source module ID (e.g. "notes", "funds", "vote")
 *   feed-id       — which feed to pull (e.g. "recent-notes", "proposals")
 *   flow-kind     — flow type for visual styling ("economic", "trust", "data", etc.)
 *   feed-filter   — optional JSON filter string
 *   max-items     — max items to display (default 10)
 *   refresh-interval — auto-refresh ms (default 30000, 0 = manual only)
 *
 * The shape auto-fetches from /{space}/{source-module}/api/{feed-endpoint}
 * and renders results as a scrollable card list.
 */

import { FolkShape } from "./folk-shape";
import { FLOW_COLORS, FLOW_LABELS } from "./layer-types";
import type { FlowKind } from "./layer-types";
import { getModuleApiBase, rspaceNavUrl, getCurrentSpace } from "../shared/url-helpers";

export class FolkFeed extends FolkShape {
	static tagName = "folk-feed";

	#feedData: any[] = [];
	#loading = false;
	#error: string | null = null;
	#refreshTimer: ReturnType<typeof setInterval> | null = null;
	#inner: HTMLElement | null = null;
	#editingIndex: number | null = null;

	static get observedAttributes() {
		return [
			...FolkShape.observedAttributes,
			"source-layer", "source-module", "feed-id", "flow-kind",
			"feed-filter", "max-items", "refresh-interval",
		];
	}

	get sourceLayer(): string { return this.getAttribute("source-layer") || ""; }
	set sourceLayer(v: string) { this.setAttribute("source-layer", v); }

	get sourceModule(): string { return this.getAttribute("source-module") || ""; }
	set sourceModule(v: string) { this.setAttribute("source-module", v); }

	get feedId(): string { return this.getAttribute("feed-id") || ""; }
	set feedId(v: string) { this.setAttribute("feed-id", v); }

	get flowKind(): FlowKind { return (this.getAttribute("flow-kind") as FlowKind) || "data"; }
	set flowKind(v: FlowKind) { this.setAttribute("flow-kind", v); }

	get feedFilter(): string { return this.getAttribute("feed-filter") || ""; }
	set feedFilter(v: string) { this.setAttribute("feed-filter", v); }

	get maxItems(): number { return parseInt(this.getAttribute("max-items") || "10", 10); }
	set maxItems(v: number) { this.setAttribute("max-items", String(v)); }

	get refreshInterval(): number { return parseInt(this.getAttribute("refresh-interval") || "30000", 10); }
	set refreshInterval(v: number) { this.setAttribute("refresh-interval", String(v)); }

	connectedCallback() {
		super.connectedCallback();
		this.#buildUI();
		// Defer API calls until shape is visible (onBecameVisible handles it)
	}

	disconnectedCallback() {
		super.disconnectedCallback();
		this.#stopAutoRefresh();
	}

	protected override onBecameVisible(): void {
		this.#fetchFeed();
		this.#startAutoRefresh();
	}

	attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null) {
		super.attributeChangedCallback(name, oldVal, newVal);
		if (["source-module", "feed-id", "feed-filter", "max-items"].includes(name)) {
			this.#fetchFeed();
		}
		if (name === "refresh-interval") {
			this.#stopAutoRefresh();
			this.#startAutoRefresh();
		}
		if (name === "flow-kind") {
			this.#updateHeader();
		}
	}

	// ── Build the inner UI ──

	#buildUI() {
		if (this.#inner) return;

		this.#inner = document.createElement("div");
		this.#inner.className = "folk-feed-inner";
		this.#inner.innerHTML = `
			<div class="feed-header">
				<div class="feed-kind-dot"></div>
				<div class="feed-title"></div>
				<button class="feed-navigate" title="Go to source layer">↗</button>
				<button class="feed-refresh" title="Refresh">↻</button>
			</div>
			<div class="feed-items"></div>
			<div class="feed-edit-overlay"></div>
			<div class="feed-status"></div>
		`;

		const style = document.createElement("style");
		style.textContent = FEED_STYLES;
		this.#inner.prepend(style);

		this.appendChild(this.#inner);

		// Refresh button
		this.#inner.querySelector(".feed-refresh")?.addEventListener("click", (e) => {
			e.stopPropagation();
			this.#fetchFeed();
		});

		// Navigate to source layer
		this.#inner.querySelector(".feed-navigate")?.addEventListener("click", (e) => {
			e.stopPropagation();
			if (this.sourceModule) {
				window.location.href = rspaceNavUrl(getCurrentSpace(), this.sourceModule);
			}
		});

		this.#updateHeader();
	}

	#updateHeader() {
		if (!this.#inner) return;
		const color = FLOW_COLORS[this.flowKind] || "#94a3b8";
		const label = FLOW_LABELS[this.flowKind] || "Feed";
		const dot = this.#inner.querySelector<HTMLElement>(".feed-kind-dot");
		const title = this.#inner.querySelector<HTMLElement>(".feed-title");
		if (dot) dot.style.background = color;
		if (title) title.textContent = `${this.sourceModule} / ${this.feedId || label}`;
	}

	// ── Fetch feed data ──

	async #fetchFeed() {
		if (!this.sourceModule) return;
		if (this.#loading) return;

		this.#loading = true;
		this.#updateStatus("loading");

		try {
			// Construct feed URL based on feed ID
			const feedEndpoint = this.#getFeedEndpoint();
			const url = `${getModuleApiBase(this.sourceModule)}/api/${feedEndpoint}`;

			const res = await fetch(url);
			if (!res.ok) throw new Error(`HTTP ${res.status}`);

			const data = await res.json();

			// Normalize: extract the array from common response shapes
			if (Array.isArray(data)) {
				this.#feedData = data.slice(0, this.maxItems);
			} else if (data.notes) {
				this.#feedData = data.notes.slice(0, this.maxItems);
			} else if (data.notebooks) {
				this.#feedData = data.notebooks.slice(0, this.maxItems);
			} else if (data.proposals) {
				this.#feedData = data.proposals.slice(0, this.maxItems);
			} else if (data.tasks) {
				this.#feedData = data.tasks.slice(0, this.maxItems);
			} else if (data.nodes) {
				this.#feedData = data.nodes.slice(0, this.maxItems);
			} else if (data.flows) {
				this.#feedData = data.flows.slice(0, this.maxItems);
			} else if (data.threads) {
				this.#feedData = data.threads.slice(0, this.maxItems);
			} else if (data.campaigns) {
				this.#feedData = data.campaigns.slice(0, this.maxItems);
			} else if (data.drafts) {
				this.#feedData = data.drafts.slice(0, this.maxItems);
			} else {
				// Try to use the data as-is if it has array-like fields
				const firstArray = Object.values(data).find(v => Array.isArray(v));
				this.#feedData = firstArray ? (firstArray as any[]).slice(0, this.maxItems) : [data];
			}

			this.#error = null;
			this.#renderItems();
			this.#updateStatus("ok");
		} catch (err: any) {
			this.#error = err.message || "Failed to fetch";
			this.#updateStatus("error");
		} finally {
			this.#loading = false;
		}
	}

	#getFeedEndpoint(): string {
		// Map feed IDs to actual API endpoints
		const FEED_ENDPOINTS: Record<string, Record<string, string>> = {
			notes: {
				"notes-by-tag": "notes",
				"recent-notes": "notes",
				default: "notes",
			},
			funds: {
				"treasury-flows": "flows",
				"transactions": "flows",
				default: "flows",
			},
			vote: {
				proposals: "proposals",
				decisions: "proposals?status=PASSED,FAILED",
				default: "proposals",
			},
			choices: {
				"poll-results": "choices",
				default: "choices",
			},
			wallet: {
				balances: "safe/detect",
				transfers: "safe/detect",
				default: "safe/detect",
			},
			data: {
				analytics: "stats",
				"active-users": "active",
				default: "stats",
			},
			work: {
				"task-activity": "spaces",
				"board-summary": "spaces",
				default: "spaces",
			},
			network: {
				"trust-graph": "graph",
				connections: "people",
				default: "graph",
			},
			trips: {
				"trip-expenses": "trips",
				itinerary: "trips",
				default: "trips",
			},
			socials: {
				threads: "threads",
				campaigns: "campaigns",
				newsletter: "newsletter/drafts",
				default: "threads",
			},
		};

		const moduleEndpoints = FEED_ENDPOINTS[this.sourceModule];
		if (!moduleEndpoints) return this.feedId || "info";
		return moduleEndpoints[this.feedId] || moduleEndpoints.default || this.feedId;
	}

	// ── Render feed items ──

	#renderItems() {
		const container = this.#inner?.querySelector(".feed-items");
		if (!container) return;

		const color = FLOW_COLORS[this.flowKind] || "#94a3b8";

		if (this.#feedData.length === 0) {
			container.innerHTML = `<div class="feed-empty">No data</div>`;
			return;
		}

		container.innerHTML = this.#feedData.map((item, i) => {
			const title = item.title || item.name || item.label || item.id || `Item ${i + 1}`;
			const subtitle = item.description || item.content_plain?.slice(0, 80) || item.status || item.type || "";
			const badge = item.status || item.kind || item.type || "";
			const editable = this.#isEditable(item);

			return `
				<div class="feed-item ${editable ? "feed-item--editable" : ""}" data-index="${i}" data-item-id="${item.id || ""}">
					<div class="feed-item-line" style="background:${color}"></div>
					<div class="feed-item-content">
						<div class="feed-item-title">${this.#escapeHtml(String(title))}</div>
						${subtitle ? `<div class="feed-item-subtitle">${this.#escapeHtml(String(subtitle).slice(0, 100))}</div>` : ""}
					</div>
					<div class="feed-item-actions">
						${editable ? `<button class="feed-item-edit" data-edit="${i}" title="Edit">✎</button>` : ""}
						${badge ? `<div class="feed-item-badge" style="color:${color}">${this.#escapeHtml(String(badge))}</div>` : ""}
					</div>
				</div>
			`;
		}).join("");

		// Attach item click and edit events
		container.querySelectorAll<HTMLElement>(".feed-item").forEach(el => {
			// Double-click to navigate to source
			el.addEventListener("dblclick", (e) => {
				e.stopPropagation();
				const idx = parseInt(el.dataset.index || "0", 10);
				const item = this.#feedData[idx];
				if (item) this.#navigateToItem(item);
			});
		});

		container.querySelectorAll<HTMLElement>(".feed-item-edit").forEach(btn => {
			btn.addEventListener("click", (e) => {
				e.stopPropagation();
				const idx = parseInt(btn.dataset.edit || "0", 10);
				this.#openEditOverlay(idx);
			});
		});
	}

	/** Check if an item supports write-back */
	#isEditable(item: any): boolean {
		// Items with an ID from modules that support PUT/PATCH are editable
		if (!item.id) return false;
		const editableModules = ["notes", "work", "vote", "trips"];
		return editableModules.includes(this.sourceModule);
	}

	/** Navigate to the source item in its module */
	#navigateToItem(item: any) {
		const mod = this.sourceModule;

		// Build a deep link to the item in its source module
		// Emit an event so the canvas/shell can handle it
		this.dispatchEvent(new CustomEvent("feed-navigate", {
			bubbles: true,
			detail: {
				sourceModule: mod,
				itemId: item.id,
				item,
				url: getModuleApiBase(mod),
			}
		}));
	}

	// ── Edit overlay (bidirectional write-back) ──

	#openEditOverlay(index: number) {
		const overlay = this.#inner?.querySelector<HTMLElement>(".feed-edit-overlay");
		if (!overlay) return;

		const item = this.#feedData[index];
		if (!item) return;

		this.#editingIndex = index;
		const color = FLOW_COLORS[this.flowKind] || "#94a3b8";

		// Build edit fields based on item properties
		const editableFields = this.#getEditableFields(item);

		overlay.innerHTML = `
			<div class="edit-panel">
				<div class="edit-header">
					<span style="color:${color}">Edit: ${this.#escapeHtml(item.title || item.name || "Item")}</span>
					<button class="edit-close">&times;</button>
				</div>
				<div class="edit-fields">
					${editableFields.map(f => `
						<label class="edit-field">
							<span class="edit-label">${f.label}</span>
							${f.type === "textarea"
								? `<textarea class="edit-input" data-field="${f.key}" rows="3">${this.#escapeHtml(String(f.value))}</textarea>`
								: f.type === "select"
									? `<select class="edit-input" data-field="${f.key}">
										${f.options!.map(o => `<option value="${o}" ${o === f.value ? "selected" : ""}>${o}</option>`).join("")}
									</select>`
									: `<input class="edit-input" type="text" data-field="${f.key}" value="${this.#escapeHtml(String(f.value))}" />`
							}
						</label>
					`).join("")}
				</div>
				<div class="edit-actions">
					<button class="edit-cancel">Cancel</button>
					<button class="edit-save" style="background:${color}20; color:${color}; border-color:${color}40">Save & Push</button>
				</div>
			</div>
		`;

		overlay.classList.add("open");

		// Events
		overlay.querySelector(".edit-close")?.addEventListener("click", () => this.#closeEditOverlay());
		overlay.querySelector(".edit-cancel")?.addEventListener("click", () => this.#closeEditOverlay());
		overlay.querySelector(".edit-save")?.addEventListener("click", () => this.#saveEdit());
	}

	#closeEditOverlay() {
		const overlay = this.#inner?.querySelector<HTMLElement>(".feed-edit-overlay");
		if (overlay) {
			overlay.classList.remove("open");
			overlay.innerHTML = "";
		}
		this.#editingIndex = null;
	}

	async #saveEdit() {
		if (this.#editingIndex === null) return;
		const item = this.#feedData[this.#editingIndex];
		if (!item?.id) return;

		const overlay = this.#inner?.querySelector<HTMLElement>(".feed-edit-overlay");
		if (!overlay) return;

		// Collect edited values
		const updates: Record<string, string> = {};
		overlay.querySelectorAll<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>(".edit-input").forEach(el => {
			const field = el.dataset.field;
			if (field && el.value !== String(item[field] ?? "")) {
				updates[field] = el.value;
			}
		});

		if (Object.keys(updates).length === 0) {
			this.#closeEditOverlay();
			return;
		}

		// Write back to source module API
		try {
			const endpoint = this.#getWriteBackEndpoint(item);
			const url = `${getModuleApiBase(this.sourceModule)}/api/${endpoint}`;

			const method = this.#getWriteBackMethod();
			const token = this.#getAuthToken();

			const res = await fetch(url, {
				method,
				headers: {
					"Content-Type": "application/json",
					...(token ? { Authorization: `Bearer ${token}` } : {}),
				},
				body: JSON.stringify(updates),
			});

			if (!res.ok) {
				const err = await res.json().catch(() => ({ error: "Failed" }));
				throw new Error(err.error || `HTTP ${res.status}`);
			}

			// Update local data
			Object.assign(item, updates);
			this.#renderItems();
			this.#closeEditOverlay();

			// Emit event for flow tracking
			this.dispatchEvent(new CustomEvent("feed-writeback", {
				bubbles: true,
				detail: {
					sourceModule: this.sourceModule,
					itemId: item.id,
					updates,
					flowKind: this.flowKind,
				}
			}));
		} catch (err: any) {
			// Show error in overlay
			const actions = overlay.querySelector(".edit-actions");
			if (actions) {
				const existing = actions.querySelector(".edit-error");
				if (existing) existing.remove();
				const errorEl = document.createElement("div");
				errorEl.className = "edit-error";
				errorEl.textContent = err.message;
				actions.prepend(errorEl);
			}
		}
	}

	#getEditableFields(item: any): { key: string; label: string; value: string; type: string; options?: string[] }[] {
		const fields: { key: string; label: string; value: string; type: string; options?: string[] }[] = [];

		// Module-specific editable fields
		switch (this.sourceModule) {
			case "notes":
				if (item.title !== undefined) fields.push({ key: "title", label: "Title", value: item.title || "", type: "text" });
				if (item.content !== undefined) fields.push({ key: "content", label: "Content", value: item.content || "", type: "textarea" });
				break;
			case "work":
				if (item.title !== undefined) fields.push({ key: "title", label: "Title", value: item.title || "", type: "text" });
				if (item.status !== undefined) fields.push({
					key: "status", label: "Status", value: item.status,
					type: "select", options: ["TODO", "IN_PROGRESS", "REVIEW", "DONE"],
				});
				if (item.priority !== undefined) fields.push({
					key: "priority", label: "Priority", value: item.priority || "MEDIUM",
					type: "select", options: ["LOW", "MEDIUM", "HIGH", "URGENT"],
				});
				break;
			case "vote":
				if (item.title !== undefined) fields.push({ key: "title", label: "Title", value: item.title || "", type: "text" });
				if (item.description !== undefined) fields.push({ key: "description", label: "Description", value: item.description || "", type: "textarea" });
				break;
			case "trips":
				if (item.title !== undefined) fields.push({ key: "title", label: "Title", value: item.title || "", type: "text" });
				if (item.description !== undefined) fields.push({ key: "description", label: "Description", value: item.description || "", type: "textarea" });
				break;
			default:
				// Generic: expose title and description if present
				if (item.title !== undefined) fields.push({ key: "title", label: "Title", value: item.title || "", type: "text" });
				if (item.description !== undefined) fields.push({ key: "description", label: "Description", value: item.description || "", type: "textarea" });
		}

		return fields;
	}

	#getWriteBackEndpoint(item: any): string {
		switch (this.sourceModule) {
			case "notes": return `notes/${item.id}`;
			case "work": return `tasks/${item.id}`;
			case "vote": return `proposals/${item.id}`;
			case "trips": return `trips/${item.id}`;
			default: return `${item.id}`;
		}
	}

	#getWriteBackMethod(): string {
		switch (this.sourceModule) {
			case "work": return "PATCH";
			default: return "PUT";
		}
	}

	#getAuthToken(): string | null {
		// Try to get token from EncryptID (stored in localStorage by rstack-identity)
		try {
			return localStorage.getItem("encryptid-token") || null;
		} catch {
			return null;
		}
	}

	#updateStatus(state: "loading" | "ok" | "error") {
		const el = this.#inner?.querySelector<HTMLElement>(".feed-status");
		if (!el) return;

		if (state === "loading") {
			el.textContent = "Loading...";
			el.style.color = "#94a3b8";
		} else if (state === "error") {
			el.textContent = this.#error || "Error";
			el.style.color = "#ef4444";
		} else {
			el.textContent = `${this.#feedData.length} items`;
			el.style.color = FLOW_COLORS[this.flowKind] || "#94a3b8";
		}
	}

	// ── Auto-refresh ──

	#startAutoRefresh() {
		if (this.refreshInterval > 0) {
			this.#refreshTimer = setInterval(() => this.#fetchFeed(), this.refreshInterval);
		}
	}

	#stopAutoRefresh() {
		if (this.#refreshTimer) {
			clearInterval(this.#refreshTimer);
			this.#refreshTimer = null;
		}
	}

	// ── Serialization ──

	static override fromData(data: Record<string, any>): FolkFeed {
		const shape = FolkShape.fromData(data) as FolkFeed;
		if (data.sourceLayer !== undefined) shape.sourceLayer = data.sourceLayer;
		if (data.sourceModule !== undefined) shape.sourceModule = data.sourceModule;
		if (data.feedId !== undefined) shape.feedId = data.feedId;
		if (data.flowKind !== undefined) shape.flowKind = data.flowKind;
		if (data.feedFilter !== undefined) shape.feedFilter = data.feedFilter;
		if (data.maxItems !== undefined) shape.maxItems = data.maxItems;
		if (data.refreshInterval !== undefined) shape.refreshInterval = data.refreshInterval;
		return shape;
	}

	override applyData(data: Record<string, any>): void {
		super.applyData(data);
		if (data.sourceLayer !== undefined && data.sourceLayer !== this.sourceLayer) this.sourceLayer = data.sourceLayer;
		if (data.sourceModule !== undefined && data.sourceModule !== this.sourceModule) this.sourceModule = data.sourceModule;
		if (data.feedId !== undefined && data.feedId !== this.feedId) this.feedId = data.feedId;
		if (data.flowKind !== undefined && data.flowKind !== this.flowKind) this.flowKind = data.flowKind;
		if (data.feedFilter !== undefined && data.feedFilter !== this.feedFilter) this.feedFilter = data.feedFilter;
		if (data.maxItems !== undefined && data.maxItems !== this.maxItems) this.maxItems = data.maxItems;
		if (data.refreshInterval !== undefined && data.refreshInterval !== this.refreshInterval) this.refreshInterval = data.refreshInterval;
	}

	override toJSON() {
		return {
			...super.toJSON(),
			type: "folk-feed",
			sourceLayer: this.sourceLayer,
			sourceModule: this.sourceModule,
			feedId: this.feedId,
			flowKind: this.flowKind,
			feedFilter: this.feedFilter,
			maxItems: this.maxItems,
			refreshInterval: this.refreshInterval,
		};
	}

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

	static define(tag = "folk-feed") {
		if (!customElements.get(tag)) customElements.define(tag, FolkFeed);
	}
}

// ── Styles ──

const FEED_STYLES = `
.folk-feed-inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: rgba(15, 23, 42, 0.9);
  border: 1px solid rgba(255,255,255,0.08);
}

.feed-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  flex-shrink: 0;
}

.feed-kind-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.feed-title {
  flex: 1;
  font-size: 0.75rem;
  font-weight: 600;
  color: #e2e8f0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.feed-refresh {
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: #64748b;
  font-size: 0.85rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s, background 0.15s;
}
.feed-refresh:hover {
  color: #e2e8f0;
  background: rgba(255,255,255,0.06);
}

.feed-items {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0;
  scrollbar-width: thin;
  scrollbar-color: rgba(148,163,184,0.2) transparent;
}

.feed-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 6px 12px;
  transition: background 0.12s;
  cursor: default;
}
.feed-item:hover {
  background: rgba(255,255,255,0.03);
}

.feed-item-line {
  width: 3px;
  min-height: 24px;
  border-radius: 2px;
  flex-shrink: 0;
  margin-top: 2px;
  opacity: 0.6;
}

.feed-item-content {
  flex: 1;
  min-width: 0;
}

.feed-item-title {
  font-size: 0.75rem;
  font-weight: 500;
  color: #e2e8f0;
  line-height: 1.3;
}

.feed-item-subtitle {
  font-size: 0.65rem;
  color: #64748b;
  margin-top: 2px;
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.feed-item-badge {
  font-size: 0.55rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  padding: 2px 4px;
  border-radius: 3px;
  background: rgba(255,255,255,0.04);
  flex-shrink: 0;
  margin-top: 2px;
}

.feed-navigate {
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: #64748b;
  font-size: 0.75rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s, background 0.15s;
}
.feed-navigate:hover {
  color: #22d3ee;
  background: rgba(34,211,238,0.1);
}

.feed-item--editable { cursor: pointer; }
.feed-item--editable:hover { background: rgba(255,255,255,0.05); }

.feed-item-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.feed-item-edit {
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 3px;
  background: transparent;
  color: #475569;
  font-size: 0.7rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
}
.feed-item:hover .feed-item-edit { opacity: 0.7; }
.feed-item-edit:hover { opacity: 1 !important; color: #22d3ee; background: rgba(34,211,238,0.1); }

.feed-empty {
  padding: 20px;
  text-align: center;
  font-size: 0.75rem;
  color: #475569;
}

.feed-status {
  padding: 4px 12px;
  font-size: 0.6rem;
  text-align: right;
  border-top: 1px solid rgba(255,255,255,0.04);
  flex-shrink: 0;
}

/* ── Edit overlay ── */

.feed-edit-overlay {
  display: none;
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.95);
  border-radius: 8px;
  z-index: 10;
  overflow: auto;
}
.feed-edit-overlay.open { display: flex; }

.edit-panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 12px;
  gap: 10px;
}

.edit-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.75rem;
  font-weight: 600;
}

.edit-close {
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: #94a3b8;
  font-size: 1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.edit-close:hover { color: #ef4444; background: rgba(239,68,68,0.1); }

.edit-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}

.edit-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.edit-label {
  font-size: 0.6rem;
  font-weight: 600;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.edit-input {
  padding: 6px 8px;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 5px;
  background: rgba(255,255,255,0.04);
  color: #e2e8f0;
  font-size: 0.75rem;
  font-family: inherit;
  outline: none;
  transition: border-color 0.15s;
  resize: vertical;
}
.edit-input:focus { border-color: rgba(34,211,238,0.4); }

select.edit-input { cursor: pointer; }

.edit-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  justify-content: flex-end;
}

.edit-cancel, .edit-save {
  padding: 5px 12px;
  border-radius: 5px;
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}

.edit-cancel {
  border: 1px solid rgba(255,255,255,0.1);
  background: transparent;
  color: #94a3b8;
}
.edit-cancel:hover { color: #e2e8f0; }

.edit-save {
  border: 1px solid;
}
.edit-save:hover { opacity: 0.8; }

.edit-error {
  font-size: 0.65rem;
  color: #ef4444;
  flex: 1;
}
`;
