"use client";
import React, { Fragment, useState, useRef, useId, useEffect, useCallback, useMemo } from "react";
import AppImage from "@/components/ui/AppImage";
import SidebarAdStack from "@/components/SidebarAdStack";
import AdImage from "@/components/AdImage";
import { rotateAll, type Ad } from "@/lib/ads";
import { PersonIcon, ChevronLeftIcon, ChevronRightIcon, SearchIcon, CloseIcon } from "@/components/ui/Icons";
import Link from "next/link";

const MOBILE_AD_EVERY_N = 4;


interface ArticleItem {
  title: string;
  excerpt: string;
  category: string;
  date: string;
  author: string;
  authorSlug: string;
  slug: string;
  image: string;
  alt: string;
  source: "live" | "imported";
  externalUrl?: string;
}



const ALL_CATEGORIES = ["All", "BROADCAST", "FEATURED", "POST PRODUCTION", "ANIMATION"];
const SOURCE_FILTERS = ["All", "Live", "Imported"] as const;
type SourceFilter = typeof SOURCE_FILTERS[number];
type FeedMode = "pagination" | "infinite";
type SortOrder = "recent" | "trending" | "most-commented";
const ARTICLES_PER_PAGE = 15;

// Derive unique authors from all articles (static + imported merged at runtime)
function getUniqueAuthors(articles: ArticleItem[]): string[] {
  const seen = new Set<string>();
  const authors: string[] = [];
  for (const a of articles) {
    if (a.author && !seen.has(a.author)) {
      seen.add(a.author);
      authors.push(a.author);
    }
  }
  return authors.sort();
}

// Parse "Month DD, YYYY" → Date object for comparison
function parseArticleDate(dateStr: string): Date | null {
  const d = new Date(dateStr);
  return isNaN(d.getTime()) ? null : d;
}

export default function ArticleFeed() {
  const [page, setPage] = useState(1);
  const [searchQuery, setSearchQuery] = useState("");
  const [activeCategory, setActiveCategory] = useState("All");
  const [sourceFilter, setSourceFilter] = useState<SourceFilter>("All");
  const [wpPosts, setWpPosts] = useState<ArticleItem[]>([]);
  const [loadingWp, setLoadingWp] = useState(true);
  const [feedMode, setFeedMode] = useState<FeedMode>("pagination");
  const [infiniteCount, setInfiniteCount] = useState(ARTICLES_PER_PAGE);
  const [isLoadingMore, setIsLoadingMore] = useState(false);
  const [sortOrder, setSortOrder] = useState<SortOrder>("recent");
  // Advanced filters
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [authorFilter, setAuthorFilter] = useState("All");
  const [dateFrom, setDateFrom] = useState("");
  const [dateTo, setDateTo] = useState("");
  const searchRef = useRef<HTMLInputElement>(null);
  const filterRefs = useRef<(HTMLButtonElement | null)[]>([]);
  const sentinelRef = useRef<HTMLDivElement>(null);
  const feedId = useId();

  // Shuffled 300x250 pool for mobile in-feed inserts (md:hidden).
  // Tablet/desktop already get the SidebarAdStack to the right of the feed.
  const mobileInfeedAds = useMemo<Ad[]>(() => rotateAll("300x250"), []);

  // Load preference from localStorage
  useEffect(() => {
    try {
      const saved = localStorage.getItem("latest-feed-mode");
      if (saved === "infinite" || saved === "pagination") {
        setFeedMode(saved);
      }
    } catch {
      // ignore
    }
  }, []);

  // Fetch imported WordPress posts for the feed
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch("/api/public/posts?limit=200", { cache: "no-store" });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const json = await res.json();
        const items = Array.isArray(json?.items) ? (json.items as ArticleItem[]) : [];
        if (!cancelled) setWpPosts(items);
      } catch {
        if (!cancelled) setWpPosts([]);
      } finally {
        if (!cancelled) setLoadingWp(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const handleFeedModeChange = (mode: FeedMode) => {
    setFeedMode(mode);
    setPage(1);
    setInfiniteCount(ARTICLES_PER_PAGE);
    try {
      localStorage.setItem("latest-feed-mode", mode);
    } catch {
      // ignore
    }
  };

  // Merge: interleave imported posts with static (imported first by recency, then static)
  const allArticles: ArticleItem[] = [...wpPosts];

  const uniqueAuthors = getUniqueAuthors(allArticles);

  const hasAdvancedActive = authorFilter !== "All" || dateFrom !== "" || dateTo !== "";

  const clearAllFilters = () => {
    setSearchQuery("");
    setActiveCategory("All");
    setSourceFilter("All");
    setAuthorFilter("All");
    setDateFrom("");
    setDateTo("");
    setPage(1);
    searchRef.current?.focus();
  };

  // Filter articles
  const filtered = allArticles.filter((a) => {
    const matchCat = activeCategory === "All" || a.category === activeCategory;
    const matchSource =
      sourceFilter === "All" ||
      (sourceFilter === "Imported" && a.source === "imported") ||
      (sourceFilter === "Live" && a.source === "live");
    const q = searchQuery.toLowerCase();
    const matchSearch = !q || a.title.toLowerCase().includes(q) || a.excerpt.toLowerCase().includes(q) || a.author.toLowerCase().includes(q);
    const matchAuthor = authorFilter === "All" || a.author === authorFilter;
    // Date range filtering
    let matchDate = true;
    if (dateFrom || dateTo) {
      const articleDate = parseArticleDate(a.date);
      if (articleDate) {
        if (dateFrom) {
          const from = new Date(dateFrom);
          if (articleDate < from) matchDate = false;
        }
        if (dateTo && matchDate) {
          const to = new Date(dateTo);
          to.setHours(23, 59, 59, 999);
          if (articleDate > to) matchDate = false;
        }
      }
    }
    return matchCat && matchSource && matchSearch && matchAuthor && matchDate;
  });

  // Sort filtered articles based on sortOrder
  const sortedFiltered = [...filtered].sort((a, b) => {
    if (sortOrder === "recent") {
      const da = parseArticleDate(a.date);
      const db = parseArticleDate(b.date);
      if (!da && !db) return 0;
      if (!da) return 1;
      if (!db) return -1;
      return db.getTime() - da.getTime();
    }
    if (sortOrder === "trending") {
      // Trending: FEATURED category gets a boost, then by recency
      const featuredBoost = (art: ArticleItem) => (art.category === "FEATURED" ? 2 : 0);
      const importedBoost = (art: ArticleItem) => (art.source === "imported" ? 1 : 0);
      const scoreA = featuredBoost(a) + importedBoost(a);
      const scoreB = featuredBoost(b) + importedBoost(b);
      if (scoreB !== scoreA) return scoreB - scoreA;
      const da = parseArticleDate(a.date);
      const db = parseArticleDate(b.date);
      if (!da && !db) return 0;
      if (!da) return 1;
      if (!db) return -1;
      return db.getTime() - da.getTime();
    }
    if (sortOrder === "most-commented") {
      // Most Commented: use a deterministic hash of the title as a proxy comment count
      const commentScore = (art: ArticleItem) => {
        let hash = 0;
        for (let i = 0; i < art.title.length; i++) {
          hash = (hash * 31 + art.title.charCodeAt(i)) & 0xffff;
        }
        return hash % 200; // 0–199 simulated comment count
      };
      return commentScore(b) - commentScore(a);
    }
    return 0;
  });

  const totalPages = Math.max(1, Math.ceil(sortedFiltered.length / ARTICLES_PER_PAGE));
  const displayedArticles = feedMode === "infinite"
    ? sortedFiltered.slice(0, infiniteCount)
    : sortedFiltered.slice((page - 1) * ARTICLES_PER_PAGE, page * ARTICLES_PER_PAGE);

  const hasMore = feedMode === "infinite" && infiniteCount < sortedFiltered.length;

  const importedCount = allArticles.filter((a) => a.source === "imported").length;

  // Reset infinite count when filters change
  useEffect(() => {
    setInfiniteCount(ARTICLES_PER_PAGE);
  }, [searchQuery, activeCategory, sourceFilter, authorFilter, dateFrom, dateTo, sortOrder]);

  // Arrow key navigation for filter chips
  const handleFilterKeyDown = (e: React.KeyboardEvent, index: number) => {
    const items = filterRefs.current.filter(Boolean);
    if (e.key === "ArrowRight") {
      e.preventDefault();
      items[(index + 1) % items.length]?.focus();
    } else if (e.key === "ArrowLeft") {
      e.preventDefault();
      items[(index - 1 + items.length) % items.length]?.focus();
    } else if (e.key === "Home") {
      e.preventDefault();
      items[0]?.focus();
    } else if (e.key === "End") {
      e.preventDefault();
      items[items.length - 1]?.focus();
    }
  };

  const clearSearch = () => {
    setSearchQuery("");
    searchRef.current?.focus();
  };

  // Infinite scroll: IntersectionObserver on sentinel
  const loadMore = useCallback(() => {
    if (isLoadingMore || !hasMore) return;
    setIsLoadingMore(true);
    setTimeout(() => {
      setInfiniteCount((prev) => Math.min(prev + ARTICLES_PER_PAGE, sortedFiltered.length));
      setIsLoadingMore(false);
    }, 400);
  }, [isLoadingMore, hasMore, sortedFiltered.length]);

  useEffect(() => {
    if (feedMode !== "infinite") return;
    const sentinel = sentinelRef.current;
    if (!sentinel) return;
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting) {
          loadMore();
        }
      },
      { rootMargin: "200px" }
    );
    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [feedMode, loadMore]);

  return (
    <section className="max-w-container mx-auto px-4 py-4 md:py-6">
      {/* Main layout */}
      <div className="grid grid-cols-1 lg:grid-cols-12 gap-6 lg:gap-8">
        {/* Main Feed */}
        <div className="lg:col-span-8">
          {/* Section header */}
          <div className="flex items-center gap-3 mb-4 md:mb-5 flex-wrap">
            <span className="section-label">The Latest</span>
            <div className="flex-1 h-px bg-[#2a2a2a]" />
            {/* Sort dropdown */}
            <div className="flex items-center gap-1.5">
              <span className="font-body text-[10px] text-[#555] uppercase tracking-wide hidden sm:inline">Sort:</span>
              <div className="relative">
                <select
                  value={sortOrder}
                  onChange={(e) => { setSortOrder(e.target.value as SortOrder); setPage(1); setInfiniteCount(ARTICLES_PER_PAGE); }}
                  aria-label="Sort articles"
                  className="bg-[#111] border border-[#2a2a2a] text-[#aaa] font-body text-[11px] font-semibold uppercase tracking-wide rounded-sm pl-2.5 pr-7 py-1 appearance-none focus:outline-none focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]/30 transition-colors [color-scheme:dark] cursor-pointer hover:border-[#3a3a3a]"
                >
                  <option value="recent">Recent</option>
                  <option value="trending">Trending</option>
                  <option value="most-commented">Most Commented</option>
                </select>
                <svg className="absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none text-[#555]" width="9" height="9" viewBox="0 0 10 10" fill="none" aria-hidden="true">
                  <path d="M2 3.5L5 6.5L8 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              </div>
            </div>
            {/* Feed mode toggle */}
            <div className="flex items-center gap-1.5" role="group" aria-label="Feed display mode">
              <span className="font-body text-[10px] text-[#555] uppercase tracking-wide hidden sm:inline">View:</span>
              <div className="flex items-center bg-[#111] border border-[#2a2a2a] rounded-sm p-0.5">
                <button
                  onClick={() => handleFeedModeChange("pagination")}
                  aria-pressed={feedMode === "pagination"}
                  title="Pagination mode"
                  className={`flex items-center gap-1 px-2.5 py-1 rounded-sm font-body text-[10px] font-semibold uppercase tracking-wide transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] ${
                    feedMode === "pagination" ?"bg-[#3b82f6]/20 text-[#3b82f6] border border-[#3b82f6]/40" :"text-[#666] hover:text-[#aaa] border border-transparent"
                  }`}>
                  <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
                    <rect x="1" y="1" width="10" height="2.5" rx="0.5" fill="currentColor" opacity="0.9"/>
                    <rect x="1" y="4.75" width="10" height="2.5" rx="0.5" fill="currentColor" opacity="0.6"/>
                    <rect x="1" y="8.5" width="6" height="2.5" rx="0.5" fill="currentColor" opacity="0.4"/>
                  </svg>
                  Pages
                </button>
                <button
                  onClick={() => handleFeedModeChange("infinite")}
                  aria-pressed={feedMode === "infinite"}
                  title="Infinite scroll mode"
                  className={`flex items-center gap-1 px-2.5 py-1 rounded-sm font-body text-[10px] font-semibold uppercase tracking-wide transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] ${
                    feedMode === "infinite" ?"bg-[#3b82f6]/20 text-[#3b82f6] border border-[#3b82f6]/40" :"text-[#666] hover:text-[#aaa] border border-transparent"
                  }`}>
                  <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden="true">
                    <rect x="1" y="1" width="10" height="2" rx="0.5" fill="currentColor" opacity="0.9"/>
                    <rect x="1" y="4" width="10" height="2" rx="0.5" fill="currentColor" opacity="0.7"/>
                    <rect x="1" y="7" width="10" height="2" rx="0.5" fill="currentColor" opacity="0.5"/>
                    <path d="M5 10.5 L6 11.5 L7 10.5" stroke="currentColor" strokeWidth="1" strokeLinecap="round" strokeLinejoin="round" opacity="0.8"/>
                  </svg>
                  Scroll
                </button>
              </div>
            </div>
            <span className="font-body text-xs text-[#555]">{sortedFiltered.length?.toLocaleString()} article{sortedFiltered.length !== 1 ? "s" : ""}</span>
          </div>

          {/* Filters only — site-wide search lives in the top-right header */}
          <div className="mb-4 space-y-3">
            <div className="flex items-center gap-2">
              {/* Advanced filters toggle button */}
              <button
                type="button"
                onClick={() => setShowAdvanced((v) => !v)}
                aria-expanded={showAdvanced}
                aria-controls={`${feedId}-advanced`}
                className={`flex items-center gap-1.5 px-3 py-2 rounded-sm border font-body text-[11px] font-semibold uppercase tracking-wide transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] whitespace-nowrap ${
                  showAdvanced || hasAdvancedActive
                    ? "bg-[#3b82f6]/15 text-[#3b82f6] border-[#3b82f6]/40"
                    : "bg-[#111] text-[#666] border-[#2a2a2a] hover:text-[#aaa] hover:border-[#3a3a3a]"
                }`}>
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
                  <path d="M1 3h10M3 6h6M5 9h2" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
                </svg>
                Filters
                {hasAdvancedActive && (
                  <span className="w-1.5 h-1.5 rounded-full bg-[#3b82f6] inline-block ml-0.5" aria-label="Active filters" />
                )}
              </button>
            </div>

            {/* Advanced filters panel */}
            {showAdvanced && (
              <div
                id={`${feedId}-advanced`}
                className="bg-[#0d0d0d] border border-[#2a2a2a] rounded-sm p-3 space-y-3"
                role="group"
                aria-label="Advanced filters">
                <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                  {/* Author filter */}
                  <div className="space-y-1">
                    <label htmlFor={`${feedId}-author`} className="font-body text-[10px] text-[#555] uppercase tracking-wide block">
                      Author
                    </label>
                    <div className="relative">
                      <select
                        id={`${feedId}-author`}
                        value={authorFilter}
                        onChange={(e) => { setAuthorFilter(e.target.value); setPage(1); }}
                        className="w-full bg-[#111] border border-[#2a2a2a] text-[#ccc] font-body text-sm rounded-sm px-3 py-1.5 pr-8 appearance-none focus:outline-none focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]/30 transition-colors [color-scheme:dark]"
                        aria-label="Filter by author">
                        <option value="All">All Authors</option>
                        {uniqueAuthors.map((author) => (
                          <option key={author} value={author}>{author}</option>
                        ))}
                      </select>
                      <svg className="absolute right-2.5 top-1/2 -translate-y-1/2 pointer-events-none text-[#555]" width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
                        <path d="M2 3.5L5 6.5L8 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                      </svg>
                    </div>
                  </div>

                  {/* Category filter (moved into advanced panel as well) */}
                  <div className="space-y-1">
                    <label htmlFor={`${feedId}-category-select`} className="font-body text-[10px] text-[#555] uppercase tracking-wide block">
                      Category
                    </label>
                    <div className="relative">
                      <select
                        id={`${feedId}-category-select`}
                        value={activeCategory}
                        onChange={(e) => { setActiveCategory(e.target.value); setPage(1); }}
                        className="w-full bg-[#111] border border-[#2a2a2a] text-[#ccc] font-body text-sm rounded-sm px-3 py-1.5 pr-8 appearance-none focus:outline-none focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]/30 transition-colors [color-scheme:dark]"
                        aria-label="Filter by category">
                        {ALL_CATEGORIES.map((cat) => (
                          <option key={cat} value={cat}>{cat === "All" ? "All Categories" : cat}</option>
                        ))}
                      </select>
                      <svg className="absolute right-2.5 top-1/2 -translate-y-1/2 pointer-events-none text-[#555]" width="10" height="10" viewBox="0 0 10 10" fill="none" aria-hidden="true">
                        <path d="M2 3.5L5 6.5L8 3.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
                      </svg>
                    </div>
                  </div>

                  {/* Date From */}
                  <div className="space-y-1">
                    <label htmlFor={`${feedId}-date-from`} className="font-body text-[10px] text-[#555] uppercase tracking-wide block">
                      Date From
                    </label>
                    <input
                      id={`${feedId}-date-from`}
                      type="date"
                      value={dateFrom}
                      onChange={(e) => { setDateFrom(e.target.value); setPage(1); }}
                      max={dateTo || undefined}
                      className="w-full bg-[#111] border border-[#2a2a2a] text-[#ccc] font-body text-sm rounded-sm px-3 py-1.5 focus:outline-none focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]/30 transition-colors [color-scheme:dark]"
                      aria-label="Filter articles from date"
                    />
                  </div>

                  {/* Date To */}
                  <div className="space-y-1">
                    <label htmlFor={`${feedId}-date-to`} className="font-body text-[10px] text-[#555] uppercase tracking-wide block">
                      Date To
                    </label>
                    <input
                      id={`${feedId}-date-to`}
                      type="date"
                      value={dateTo}
                      onChange={(e) => { setDateTo(e.target.value); setPage(1); }}
                      min={dateFrom || undefined}
                      className="w-full bg-[#111] border border-[#2a2a2a] text-[#ccc] font-body text-sm rounded-sm px-3 py-1.5 focus:outline-none focus:border-[#3b82f6] focus:ring-1 focus:ring-[#3b82f6]/30 transition-colors [color-scheme:dark]"
                      aria-label="Filter articles to date"
                    />
                  </div>
                </div>

                {/* Source filter inside advanced panel */}
                <div className="space-y-1">
                  <span className="font-body text-[10px] text-[#555] uppercase tracking-wide block">Source</span>
                  <div className="flex items-center gap-1 bg-[#111] border border-[#2a2a2a] rounded-sm p-0.5 w-fit" role="group" aria-label="Filter by source">
                    {SOURCE_FILTERS.map((sf) => {
                      const isActive = sourceFilter === sf;
                      return (
                        <button
                          key={sf}
                          onClick={() => { setSourceFilter(sf); setPage(1); }}
                          aria-pressed={isActive}
                          className={`px-3 py-1 rounded-sm font-body text-[11px] font-semibold uppercase tracking-wide transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] ${
                            isActive
                              ? sf === "Imported" ?"bg-amber-500/20 text-amber-400 border border-amber-500/40"
                                : sf === "Live" ?"bg-emerald-500/20 text-emerald-400 border border-emerald-500/40" :"bg-[#3b82f6]/20 text-[#3b82f6] border border-[#3b82f6]/40" :"text-[#666] hover:text-[#aaa] border border-transparent"
                          }`}>
                          {sf}
                          {sf === "Imported" && importedCount > 0 && (
                            <span className="ml-1 text-[9px] opacity-70">({importedCount})</span>
                          )}
                        </button>
                      );
                    })}
                  </div>
                  {loadingWp && (
                    <span className="font-body text-[10px] text-[#555] italic">Loading imported posts…</span>
                  )}
                </div>

                {/* Clear advanced filters */}
                {hasAdvancedActive && (
                  <div className="flex justify-end pt-1 border-t border-[#1e1e1e]">
                    <button
                      type="button"
                      onClick={() => { setAuthorFilter("All"); setDateFrom(""); setDateTo(""); setPage(1); }}
                      className="font-body text-[11px] text-[#3b82f6] hover:underline focus:outline-none focus-visible:underline">
                      Clear advanced filters
                    </button>
                  </div>
                )}
              </div>
            )}

            {/* Category filter chips (always visible, quick access) */}
            <div
              className="flex flex-wrap gap-1.5"
              role="group"
              aria-label="Filter articles by category">
              {ALL_CATEGORIES.map((cat, i) => {
                const isActive = activeCategory === cat;
                return (
                  <button
                    key={cat}
                    ref={(el) => { filterRefs.current[i] = el; }}
                    onClick={() => { setActiveCategory(cat); setPage(1); }}
                    onKeyDown={(e) => handleFilterKeyDown(e, i)}
                    aria-pressed={isActive}
                    tabIndex={isActive ? 0 : -1}
                    className={`filter-chip ${isActive ? "filter-chip-active" : ""} focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6]`}>
                    {cat}
                  </button>
                );
              })}
            </div>

            {/* Results count */}
            {(searchQuery || activeCategory !== "All" || sourceFilter !== "All" || authorFilter !== "All" || dateFrom || dateTo) && (
              <p
                id={`${feedId}-results`}
                className="font-body text-xs text-[#666]"
                aria-live="polite"
                aria-atomic="true">
                {sortedFiltered.length === 0
                  ? "No articles found — "
                  : `${sortedFiltered.length} article${sortedFiltered.length !== 1 ? "s" : ""} found`}
                {searchQuery ? ` for "${searchQuery}"` : ""}
                {activeCategory !== "All" ? ` in ${activeCategory}` : ""}
                {authorFilter !== "All" ? ` · by ${authorFilter}` : ""}
                {sourceFilter !== "All" ? ` · ${sourceFilter} only` : ""}
                {(dateFrom || dateTo) ? ` · ${dateFrom ? dateFrom : "any"} → ${dateTo ? dateTo : "any"}` : ""}
                {sortedFiltered.length === 0 && (
                  <button
                    onClick={clearAllFilters}
                    className="ml-1 text-[#3b82f6] hover:underline focus:outline-none focus-visible:underline">
                    Clear filters
                  </button>
                )}
              </p>
            )}
          </div>

          {/* Article list */}
          {displayedArticles.length === 0 ? (
            <div className="empty-state py-12" role="status">
              <div className="empty-state-icon">
                <SearchIcon size={48} strokeWidth={1} />
              </div>
              <p className="empty-state-title">No articles found</p>
              <p className="empty-state-desc">
                Try adjusting your search or selecting a different category.
              </p>
              <button
                onClick={clearAllFilters}
                className="mt-4 font-body text-sm text-[#3b82f6] hover:underline focus:outline-none focus-visible:underline">
                Clear filters
              </button>
            </div>
          ) : (
            <div className="divide-y divide-[#222]" id={`${feedId}-results`}>
              {displayedArticles?.map((article, i) => {
                const isImported = article.source === "imported";
                const articleHref = isImported && article.externalUrl
                  ? article.externalUrl
                  : `/articles/${article?.slug}`;
                const linkProps = isImported && article.externalUrl
                  ? { target: "_blank", rel: "noopener noreferrer" }
                  : {};

                // Mobile in-feed ad after every Nth article (skip if last item).
                const isAdSlot =
                  (i + 1) % MOBILE_AD_EVERY_N === 0 &&
                  i + 1 < displayedArticles.length &&
                  mobileInfeedAds.length > 0;
                const inFeedAd = isAdSlot
                  ? mobileInfeedAds[Math.floor((i + 1) / MOBILE_AD_EVERY_N - 1) % mobileInfeedAds.length]
                  : null;

                return (
                  <Fragment key={`feed-${i}`}>
                  <article className="article-card flex gap-3 md:gap-4 py-4 md:py-5 group cursor-pointer rounded-sm px-2 -mx-2">
                    <Link
                      href={articleHref}
                      {...linkProps}
                      className="flex-shrink-0 img-zoom overflow-hidden w-[100px] h-[70px] sm:w-[140px] sm:h-[95px] md:w-[190px] md:h-[128px] focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6]"
                      tabIndex={-1}
                      aria-hidden="true"
                    >
                      <AppImage
                        src={article?.image}
                        alt={article?.alt}
                        width={190}
                        height={128}
                        className="object-cover w-full h-full"
                        sizes="(max-width: 640px) 100px, (max-width: 768px) 140px, 190px"
                      />
                    </Link>
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-1.5 md:gap-2 mb-1 md:mb-1.5 flex-wrap">
                        {article?.category && article.category.toLowerCase() !== "legacy" && (
                          <span className="font-body text-[10px] font-bold text-[#3b82f6] uppercase tracking-wide">
                            {article.category}
                          </span>
                        )}
                      </div>
                      <h3 className="font-heading text-[#e0e0e0] font-bold text-[0.875rem] md:text-[1rem] leading-snug mb-1 md:mb-1.5 group-hover:text-[#3b82f6] transition-colors duration-200 line-clamp-2">
                        <Link
                          href={articleHref}
                          {...linkProps}
                          className="focus:outline-none focus-visible:text-[#3b82f6] focus-visible:underline">
                          {article?.title}
                        </Link>
                      </h3>
                      <p className="font-body text-[#777] text-sm leading-relaxed line-clamp-2 mb-2 md:mb-2.5 hidden sm:block">
                        {article?.excerpt}
                      </p>
                      <div className="flex items-center justify-between gap-2">
                        <div className="flex items-center gap-1 hidden sm:flex">
                          <PersonIcon size={11} className="text-[#666] flex-shrink-0" />
                          <span className="font-body text-xs text-[#666]">
                            By {article?.author}
                          </span>
                        </div>
                        <Link
                          href={articleHref}
                          {...linkProps}
                          className="read-more flex-shrink-0 text-[11px] focus:outline-none focus-visible:underline"
                          aria-label={`Read more about ${article?.title}`}>
                          Read More...
                        </Link>
                      </div>
                    </div>
                  </article>
                  {inFeedAd && (
                    <div
                      className="md:hidden py-5 flex flex-col items-center bg-[#0a0a0a]"
                      aria-label="Advertisement"
                    >
                      <span className="text-[9px] font-mono uppercase tracking-wider text-[#555] mb-2">
                        Sponsored
                      </span>
                      <AdImage ad={inFeedAd} />
                    </div>
                  )}
                  </Fragment>
                );
              })}
            </div>
          )}

          {/* Infinite scroll sentinel + loading indicator */}
          {feedMode === "infinite" && (
            <div ref={sentinelRef} className="mt-4">
              {isLoadingMore && (
                <div className="flex items-center justify-center gap-2 py-6" aria-live="polite" aria-label="Loading more articles">
                  <div className="flex gap-1">
                    <span className="w-1.5 h-1.5 rounded-full bg-[#3b82f6] animate-bounce" style={{ animationDelay: "0ms" }} />
                    <span className="w-1.5 h-1.5 rounded-full bg-[#3b82f6] animate-bounce" style={{ animationDelay: "150ms" }} />
                    <span className="w-1.5 h-1.5 rounded-full bg-[#3b82f6] animate-bounce" style={{ animationDelay: "300ms" }} />
                  </div>
                  <span className="font-body text-xs text-[#555]">Loading more articles…</span>
                </div>
              )}
              {!hasMore && displayedArticles.length > 0 && !isLoadingMore && (
                <div className="flex items-center gap-3 py-5 border-t border-[#222]">
                  <div className="flex-1 h-px bg-[#1e1e1e]" />
                  <span className="font-body text-[11px] text-[#444] uppercase tracking-wider">All {sortedFiltered.length} articles loaded</span>
                  <div className="flex-1 h-px bg-[#1e1e1e]" />
                </div>
              )}
            </div>
          )}

          {/* Pagination */}
          {feedMode === "pagination" && sortedFiltered.length > ARTICLES_PER_PAGE && (
            <div className="mt-5 md:mt-6 flex items-center justify-between flex-wrap gap-3 border-t border-[#222] pt-4 md:pt-5">
              <p className="font-body text-sm text-[#666]">
                Page <span className="font-bold text-[#aaa]">{page}</span> of{" "}
                <span className="font-bold text-[#aaa]">{totalPages?.toLocaleString()}</span>
                <span className="text-[#555] ml-2 text-xs">({sortedFiltered.length} articles)</span>
              </p>
              <div className="flex items-center gap-1" role="navigation" aria-label="Pagination">
                <button
                  className="page-btn inline-flex items-center gap-1 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6]"
                  disabled={page === 1}
                  onClick={() => { setPage(Math.max(1, page - 1)); window.scrollTo({ top: 0, behavior: "smooth" }); }}
                  aria-label="Previous page">
                  <ChevronLeftIcon size={12} />
                  Prev
                </button>
                {(() => {
                  const pages: (number | "...")[] = [];
                  if (totalPages <= 5) {
                    for (let i = 1; i <= totalPages; i++) pages.push(i);
                  } else {
                    pages.push(1);
                    if (page > 3) pages.push("...");
                    for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) pages.push(i);
                    if (page < totalPages - 2) pages.push("...");
                    pages.push(totalPages);
                  }
                  return pages.map((p, idx) =>
                    p === "..." ? (
                      <span key={`ellipsis-${idx}`} className="font-body text-[#999] text-sm px-1" aria-hidden="true">...</span>
                    ) : (
                      <button
                        key={p}
                        className={`page-btn focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6] ${page === p ? "active" : ""}`}
                        onClick={() => { setPage(p as number); window.scrollTo({ top: 0, behavior: "smooth" }); }}
                        aria-label={`Page ${p}`}
                        aria-current={page === p ? "page" : undefined}>
                        {p}
                      </button>
                    )
                  );
                })()}
                <button
                  className="page-btn inline-flex items-center gap-1 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#3b82f6]"
                  disabled={page === totalPages}
                  onClick={() => { setPage(Math.min(totalPages, page + 1)); window.scrollTo({ top: 0, behavior: "smooth" }); }}
                  aria-label="Next page">
                  Next
                  <ChevronRightIcon size={12} />
                </button>
              </div>
            </div>
          )}
        </div>

        {/* Sidebar — Blackmagic 300x600 fixed at top + every 300x250 banner stacked */}
        <aside className="lg:col-span-4" aria-label="Advertisements">
          <div className="lg:sticky lg:top-24">
            <SidebarAdStack />
          </div>
        </aside>
      </div>
    </section>
  );
}
