/**
 * Centralized icon registry.
 * Supports 5 libraries: Builtin SVGs, Font Awesome 6 Free, Bootstrap Icons, Material Symbols, Tabler Icons.
 * CDN libraries are lazy-loaded (CSS injected on first library tab open).
 * Recent icons and favorites persist in localStorage.
 */

import { IconValue } from '../types';

// ── Types ─────────────────────────────────────────────────────────────────────

export interface PickerIcon {
  lib: string;
  name: string;
  label: string;
  category: string;
  type: 'svg' | 'font';
  svg?: string;   // full SVG string for svg type
  cls?: string;   // CSS class for font type (e.g. 'fa-solid fa-house')
  keywords?: string[];
}

export interface LibraryDef {
  id: string;
  label: string;
  cssUrl?: string;
  type: 'svg' | 'font';
  prefix?: string;    // for building cls (e.g. 'fa-solid fa-')
  specialRender?: 'material';  // special render mode
  count: number;
}

// ── Library Definitions ───────────────────────────────────────────────────────

export const LIBRARIES: LibraryDef[] = [
  { id: 'builtin',    label: 'Built-in',          type: 'svg',  count: 72 },
  { id: 'fa-solid',   label: 'FA Solid',           type: 'font', prefix: 'fa-solid fa-',   cssUrl: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css',           count: 1390 },
  { id: 'fa-regular', label: 'FA Regular',         type: 'font', prefix: 'fa-regular fa-',  cssUrl: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css',           count: 163 },
  { id: 'fa-brands',  label: 'FA Brands',          type: 'font', prefix: 'fa-brands fa-',   cssUrl: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css',           count: 481 },
  { id: 'bootstrap',  label: 'Bootstrap Icons',    type: 'font', prefix: 'bi bi-',           cssUrl: 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css', count: 2000 },
  { id: 'material',   label: 'Material Symbols',   type: 'font', prefix: 'material-symbols-outlined', specialRender: 'material', cssUrl: 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=block', count: 2900 },
  { id: 'tabler',     label: 'Tabler Icons',       type: 'font', prefix: 'ti ti-',           cssUrl: 'https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@3.10.0/dist/tabler-icons.min.css', count: 5200 },
];

// ── Builtin SVG Icons ─────────────────────────────────────────────────────────

// Uses Feather / Heroicons outline style: stroke="currentColor", fill="none", stroke-width="1.5-2"
function svg(inner: string): string {
  return `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${inner}</svg>`;
}
function svgFill(inner: string): string {
  return `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="currentColor">${inner}</svg>`;
}

const BUILTIN_RAW: { name: string; label: string; category: string; svgStr: string }[] = [
  // Legacy (preserved from icons.ts)
  { name: 'star',     label: 'Star',      category: 'Interface',      svgStr: svgFill('<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>') },
  { name: 'heart',    label: 'Heart',     category: 'Interface',      svgStr: svgFill('<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/>') },
  { name: 'check',    label: 'Check',     category: 'Interface',      svgStr: svg('<polyline points="20 6 9 17 4 12" stroke-width="2.5"/>') },
  { name: 'arrow',    label: 'Arrow Right', category: 'Arrows',       svgStr: svg('<path d="M5 12h14M12 5l7 7-7 7" stroke-width="2"/>') },
  { name: 'phone',    label: 'Phone',     category: 'Communication',  svgStr: svg('<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 13a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.6 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L7.91 9.91a16 16 0 0 0 6.18 6.18l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" stroke-width="2"/>') },
  { name: 'email',    label: 'Email',     category: 'Communication',  svgStr: svg('<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" stroke-width="2"/><polyline points="22,6 12,13 2,6" stroke-width="2"/>') },
  { name: 'location', label: 'Location',  category: 'Maps',           svgStr: svg('<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" stroke-width="2"/><circle cx="12" cy="10" r="3" stroke-width="2"/>') },
  { name: 'user',     label: 'User',      category: 'People',         svgStr: svg('<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" stroke-width="2"/><circle cx="12" cy="7" r="4" stroke-width="2"/>') },
  { name: 'calendar', label: 'Calendar',  category: 'Time',           svgStr: svg('<rect x="3" y="4" width="18" height="18" rx="2" ry="2" stroke-width="2"/><line x1="16" y1="2" x2="16" y2="6" stroke-width="2"/><line x1="8" y1="2" x2="8" y2="6" stroke-width="2"/><line x1="3" y1="10" x2="21" y2="10" stroke-width="2"/>') },
  { name: 'clock',    label: 'Clock',     category: 'Time',           svgStr: svg('<circle cx="12" cy="12" r="10" stroke-width="2"/><polyline points="12 6 12 12 16 14" stroke-width="2"/>') },
  { name: 'globe',    label: 'Globe',     category: 'Maps',           svgStr: svg('<circle cx="12" cy="12" r="10" stroke-width="2"/><line x1="2" y1="12" x2="22" y2="12" stroke-width="2"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" stroke-width="2"/>') },
  { name: 'info',     label: 'Info',      category: 'Alerts',         svgStr: svg('<circle cx="12" cy="12" r="10" stroke-width="2"/><line x1="12" y1="8" x2="12" y2="12" stroke-width="2"/><line x1="12" y1="16" x2="12.01" y2="16" stroke-width="2"/>') },

  // New builtin icons (Heroicons 2 outline style)
  { name: 'home',     label: 'Home',      category: 'Interface',      svgStr: svg('<path d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"/>') },
  { name: 'bell',     label: 'Bell',      category: 'Interface',      svgStr: svg('<path d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0"/>') },
  { name: 'bookmark', label: 'Bookmark',  category: 'Interface',      svgStr: svg('<path d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0111.186 0z"/>') },
  { name: 'camera',   label: 'Camera',    category: 'Media',          svgStr: svg('<path d="M6.827 6.175A2.31 2.31 0 015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316z"/><path d="M16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0z"/>') },
  { name: 'chat',     label: 'Chat',      category: 'Communication',  svgStr: svg('<path d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.076-4.076a1.526 1.526 0 011.037-.443 48.282 48.282 0 005.68-.494c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z"/>') },
  { name: 'cog',      label: 'Settings',  category: 'Interface',      svgStr: svg('<path d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z"/><path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>') },
  { name: 'download', label: 'Download',  category: 'Interface',      svgStr: svg('<path d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/>') },
  { name: 'upload',   label: 'Upload',    category: 'Interface',      svgStr: svg('<path d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"/>') },
  { name: 'edit',     label: 'Edit',      category: 'Interface',      svgStr: svg('<path d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"/>') },
  { name: 'eye',      label: 'Eye',       category: 'Interface',      svgStr: svg('<path d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/><path d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>') },
  { name: 'eye-off',  label: 'Eye Off',   category: 'Interface',      svgStr: svg('<path d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88"/>') },
  { name: 'file',     label: 'File',      category: 'Files',          svgStr: svg('<path d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"/>') },
  { name: 'filter',   label: 'Filter',    category: 'Interface',      svgStr: svg('<path d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z"/>') },
  { name: 'folder',   label: 'Folder',    category: 'Files',          svgStr: svg('<path d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"/>') },
  { name: 'key',      label: 'Key',       category: 'Security',       svgStr: svg('<path d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"/>') },
  { name: 'link',     label: 'Link',      category: 'Interface',      svgStr: svg('<path d="M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244"/>') },
  { name: 'lock',     label: 'Lock',      category: 'Security',       svgStr: svg('<path d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"/>') },
  { name: 'lock-open',label: 'Lock Open', category: 'Security',       svgStr: svg('<path d="M13.5 10.5V6.75a4.5 4.5 0 119 0v3.75M3.75 21.75h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H3.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z"/>') },
  { name: 'map-pin',  label: 'Map Pin',   category: 'Maps',           svgStr: svg('<path d="M15 10.5a3 3 0 11-6 0 3 3 0 016 0z"/><path d="M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z"/>') },
  { name: 'minus',    label: 'Minus',     category: 'Interface',      svgStr: svg('<path d="M19.5 12h-15"/>') },
  { name: 'moon',     label: 'Moon',      category: 'Interface',      svgStr: svg('<path d="M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z"/>') },
  { name: 'music',    label: 'Music',     category: 'Media',          svgStr: svg('<path d="M9 9l10.5-3m0 6.553v3.75a2.25 2.25 0 01-1.632 2.163l-1.32.377a1.803 1.803 0 11-.99-3.467l2.31-.66a2.25 2.25 0 001.632-2.163zm0 0V2.25L9 5.25v10.303m0 0v3.75a2.25 2.25 0 01-1.632 2.163l-1.32.377a1.803 1.803 0 01-.99-3.467l2.31-.66A2.25 2.25 0 009 15.553z"/>') },
  { name: 'send',     label: 'Send',      category: 'Communication',  svgStr: svg('<path d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5"/>') },
  { name: 'photo',    label: 'Photo',     category: 'Media',          svgStr: svg('<path d="M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z"/>') },
  { name: 'play',     label: 'Play',      category: 'Media',          svgStr: svg('<path d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"/>') },
  { name: 'plus',     label: 'Plus',      category: 'Interface',      svgStr: svg('<path d="M12 4.5v15m7.5-7.5h-15"/>') },
  { name: 'print',    label: 'Print',     category: 'Interface',      svgStr: svg('<path d="M6.72 13.829c-.24.03-.48.062-.72.096m.72-.096a42.415 42.415 0 0110.56 0m-10.56 0L6.34 18m10.94-4.171c.24.03.48.062.72.096m-.72-.096L17.66 18m0 0l.229 2.523a1.125 1.125 0 01-1.12 1.227H7.231c-.662 0-1.18-.568-1.12-1.227L6.34 18m11.318 0h1.091A2.25 2.25 0 0021 15.75V9.456c0-1.081-.768-2.015-1.837-2.175a48.055 48.055 0 00-1.913-.247M6.34 18H5.25A2.25 2.25 0 013 15.75V9.456c0-1.081.768-2.015 1.837-2.175a48.041 48.041 0 011.913-.247m10.5 0a48.536 48.536 0 00-10.5 0m10.5 0V3.375c0-.621-.504-1.125-1.125-1.125h-8.25c-.621 0-1.125.504-1.125 1.125v3.659M18 10.5h.008v.008H18V10.5zm-3 0h.008v.008H15V10.5z"/>') },
  { name: 'refresh',  label: 'Refresh',   category: 'Interface',      svgStr: svg('<path d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"/>') },
  { name: 'reply',    label: 'Reply',     category: 'Communication',  svgStr: svg('<path d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3"/>') },
  { name: 'save',     label: 'Save',      category: 'Interface',      svgStr: svg('<path d="M3 7.5L7.5 3h13.121a.75.75 0 01.53.22l2.878 2.879A.75.75 0 0124 6.62V20.25A2.25 2.25 0 0121.75 22.5h-15A2.25 2.25 0 014.5 20.25V7.5" /><path d="M8.25 4.5v5.25a.75.75 0 00.75.75h6a.75.75 0 00.75-.75V4.5M6.75 19.5v-7.5a.75.75 0 01.75-.75h9a.75.75 0 01.75.75v7.5"/>') },
  { name: 'search',   label: 'Search',    category: 'Interface',      svgStr: svg('<path d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/>') },
  { name: 'share',    label: 'Share',     category: 'Interface',      svgStr: svg('<path d="M7.217 10.907a2.25 2.25 0 100 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186l9.566-5.314m-9.566 7.5l9.566 5.314m0 0a2.25 2.25 0 103.935 2.186 2.25 2.25 0 00-3.935-2.186zm0-12.814a2.25 2.25 0 103.933-2.185 2.25 2.25 0 00-3.933 2.185z"/>') },
  { name: 'shield',   label: 'Shield',    category: 'Security',       svgStr: svg('<path d="M9 12.75L11.25 15 15 9.75m-3-7A6.97 6.97 0 006 6.75a6.97 6.97 0 01-3 2.25c0 5.25 3.75 8.25 9 9.75 5.25-1.5 9-4.5 9-9.75A6.97 6.97 0 0018 6.75a6.97 6.97 0 01-3-2.25z"/>') },
  { name: 'cart',     label: 'Cart',      category: 'Shopping',       svgStr: svg('<path d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 00-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 00-16.536-1.84M7.5 14.25L5.106 5.272M6 20.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm12.75 0a.75.75 0 11-1.5 0 .75.75 0 011.5 0z"/>') },
  { name: 'sun',      label: 'Sun',       category: 'Interface',      svgStr: svg('<path d="M12 3v2.25m6.364.386l-1.591 1.591M21 12h-2.25m-.386 6.364l-1.591-1.591M12 18.75V21m-4.773-4.227l-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0z"/>') },
  { name: 'tag',      label: 'Tag',       category: 'Interface',      svgStr: svg('<path d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L9.568 3z"/><path d="M6 6h.008v.008H6V6z"/>') },
  { name: 'trash',    label: 'Trash',     category: 'Interface',      svgStr: svg('<path d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"/>') },
  { name: 'truck',    label: 'Truck',     category: 'Shopping',       svgStr: svg('<path d="M8.25 18.75a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h6m-9 0H3.375a1.125 1.125 0 01-1.125-1.125V14.25m17.25 4.5a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m3 0h1.125c.621 0 1.129-.504 1.09-1.124a17.902 17.902 0 00-3.213-9.193 2.056 2.056 0 00-1.58-.86H14.25M16.5 18.75h-2.25m0-11.177v-.958c0-.568-.422-1.048-.987-1.106a48.554 48.554 0 00-10.026 0 1.106 1.106 0 00-.987 1.106v7.635m12-6.677v6.677m0 4.5v-4.5m0 0h-12"/>') },
  { name: 'users',    label: 'Users',     category: 'People',         svgStr: svg('<path d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"/>') },
  { name: 'video',    label: 'Video',     category: 'Media',          svgStr: svg('<path d="M15.75 10.5l4.72-4.72a.75.75 0 011.28.53v11.38a.75.75 0 01-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25h-9A2.25 2.25 0 002.25 7.5v9a2.25 2.25 0 002.25 2.25z"/>') },
  { name: 'wifi',     label: 'Wifi',      category: 'Technology',     svgStr: svg('<path d="M8.288 15.038a5.25 5.25 0 017.424 0M5.106 11.856c3.807-3.808 9.98-3.808 13.788 0M1.924 8.674c5.565-5.565 14.587-5.565 20.152 0M12.53 18.22l-.53.53-.53-.53a.75.75 0 011.06 0z"/>') },
  { name: 'x',        label: 'Close',     category: 'Interface',      svgStr: svg('<path d="M6 18L18 6M6 6l12 12"/>') },
  { name: 'zoom-in',  label: 'Zoom In',   category: 'Interface',      svgStr: svg('<path d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM10.5 7.5v6m3-3h-6"/>') },
  { name: 'zoom-out', label: 'Zoom Out',  category: 'Interface',      svgStr: svg('<path d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM13.5 10.5h-6"/>') },
  { name: 'fire',     label: 'Fire',      category: 'Interface',      svgStr: svg('<path d="M15.362 5.214A8.252 8.252 0 0112 21 8.25 8.25 0 016.038 7.048 8.287 8.287 0 009 9.6a8.983 8.983 0 013.361-6.867 8.21 8.21 0 003 2.48z"/><path d="M12 18a3.75 3.75 0 00.495-7.467 5.99 5.99 0 00-1.925 3.546 5.974 5.974 0 01-2.133-1A3.75 3.75 0 0012 18z"/>') },
  { name: 'bulb',     label: 'Light Bulb',category: 'Interface',      svgStr: svg('<path d="M12 18v-5.25m0 0a6.01 6.01 0 001.5-.189m-1.5.189a6.01 6.01 0 01-1.5-.189m3.75 7.478a12.06 12.06 0 01-4.5 0m3.75 2.383a14.406 14.406 0 01-3 0M14.25 18v-.192c0-.983.658-1.823 1.508-2.316a7.5 7.5 0 10-7.517 0c.85.493 1.509 1.333 1.509 2.316V18"/>') },
  { name: 'rocket',   label: 'Rocket',    category: 'Interface',      svgStr: svg('<path d="M15.59 14.37a6 6 0 01-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 006.16-12.12A14.98 14.98 0 009.631 8.41m5.96 5.96a14.926 14.926 0 01-5.841 2.58m-.119-8.54a6 6 0 00-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 00-2.58 5.84m2.699 2.7c-.103.021-.207.041-.311.06a15.09 15.09 0 01-2.448-2.448 14.9 14.9 0 01.06-.312m-2.24 2.39a4.493 4.493 0 00-1.757 4.306 4.493 4.493 0 004.306-1.758M16.5 9a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z"/>') },
  { name: 'trophy',   label: 'Trophy',    category: 'Interface',      svgStr: svg('<path d="M16.5 18.75h-9m9 0a3 3 0 013 3h-15a3 3 0 013-3m9 0v-3.375c0-.621-.503-1.125-1.125-1.125h-.871M7.5 18.75v-3.375c0-.621.504-1.125 1.125-1.125h.872m5.007 0H9.497m5.007 0a7.454 7.454 0 01-.982-3.172M9.497 14.25a7.454 7.454 0 00.981-3.172M5.25 4.236c-.982.143-1.954.317-2.916.52A6.003 6.003 0 007.73 9.728M5.25 4.236V4.5c0 2.108.966 3.99 2.48 5.228M5.25 4.236V2.721C7.456 2.41 9.71 2.25 12 2.25c2.291 0 4.545.16 6.75.47v1.516M7.73 9.728a6.726 6.726 0 002.748 1.35m8.272-6.842V4.5c0 2.108-.966 3.99-2.48 5.228m2.48-5.492a46.32 46.32 0 012.916.52 6.003 6.003 0 01-5.395 4.972m0 0a6.726 6.726 0 01-2.749 1.35m0 0a6.772 6.772 0 01-3.044 0"/>') },
  { name: 'gift',     label: 'Gift',      category: 'Interface',      svgStr: svg('<path d="M21 11.25v8.25a1.5 1.5 0 01-1.5 1.5H5.25a1.5 1.5 0 01-1.5-1.5v-8.25M12 4.875A2.625 2.625 0 1010.875 6H12V4.875zm0 0A2.625 2.625 0 1113.125 6H12V4.875zm0 0V6m-3 0H6.75a1.5 1.5 0 000 3h15a1.5 1.5 0 000-3H9m3 0H9m3 0h-3m3 0h3"/>') },
  { name: 'flag',     label: 'Flag',      category: 'Interface',      svgStr: svg('<path d="M3 3v1.5M3 21v-6m0 0l2.77-.693a9 9 0 016.208.682l.108.054a9 9 0 006.086.71l3.114-.732a48.524 48.524 0 01-.005-10.499l-3.11.732a9 9 0 01-6.085-.711l-.108-.054a9 9 0 00-6.208-.682L3 4.5M3 15V4.5"/>') },
  { name: 'code',     label: 'Code',      category: 'Technology',     svgStr: svg('<path d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"/>') },
  { name: 'cloud',    label: 'Cloud',     category: 'Interface',      svgStr: svg('<path d="M2.25 15a4.5 4.5 0 004.5 4.5H18a3.75 3.75 0 001.332-7.257 3 3 0 00-3.758-3.848 5.25 5.25 0 00-10.233 2.33A4.502 4.502 0 002.25 15z"/>') },
  { name: 'chart',    label: 'Chart',     category: 'Business',       svgStr: svg('<path d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"/>') },
  { name: 'building', label: 'Building',  category: 'Business',       svgStr: svg('<path d="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"/>') },
  { name: 'card',     label: 'Credit Card',category: 'Business',      svgStr: svg('<path d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 002.25-2.25V6.75A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25v10.5A2.25 2.25 0 004.5 19.5z"/>') },
  { name: 'thumb-up', label: 'Thumbs Up', category: 'Interface',      svgStr: svg('<path d="M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z"/>') },
  { name: 'thumb-dn', label: 'Thumbs Down',category: 'Interface',     svgStr: svg('<path d="M7.5 15h2.25m8.954-9.853A2.25 2.25 0 0018 3.75H5.625a2.25 2.25 0 00-2.157 1.6L1.5 14.25v5.25a2.25 2.25 0 002.25 2.25h.75a2.25 2.25 0 002.25-2.25v-1.5a2.25 2.25 0 012.25-2.25h4.5a2.25 2.25 0 012.25 2.25v1.5a2.25 2.25 0 002.25 2.25h.75a2.25 2.25 0 002.25-2.25V6.75m0-3H4.5"/>') },
  { name: 'newspaper',label: 'Newspaper', category: 'Media',          svgStr: svg('<path d="M12 7.5h1.5m-1.5 3h1.5m-7.5 3h7.5m-7.5 3h7.5m3-9h3.375c.621 0 1.125.504 1.125 1.125V18a2.25 2.25 0 01-2.25 2.25M16.5 7.5V18a2.25 2.25 0 002.25 2.25M16.5 7.5V4.875c0-.621-.504-1.125-1.125-1.125H4.125C3.504 3.75 3 4.254 3 4.875V18a2.25 2.25 0 002.25 2.25h13.5M6 7.5h3v3H6V7.5z"/>') },
  { name: 'wrench',   label: 'Wrench',    category: 'Interface',      svgStr: svg('<path d="M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 11-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 004.486-6.336l-3.276 3.277a3.004 3.004 0 01-2.25-2.25l3.276-3.276a4.5 4.5 0 00-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437l1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008z"/>') },
];

// Pre-built PickerIcon objects for builtin icons
export const BUILTIN_ICONS: PickerIcon[] = BUILTIN_RAW.map((r) => ({
  lib: 'builtin', name: r.name, label: r.label, category: r.category,
  type: 'svg' as const, svg: r.svgStr,
}));

// ── CDN Library Icon Data ─────────────────────────────────────────────────────

type CatMap = Record<string, string[]>;

// Font Awesome 6 Solid
const FA_SOLID_ICONS: CatMap = {
  'Interface': ['bars','check','chevron-down','chevron-left','chevron-right','chevron-up','circle','circle-check','circle-info','circle-question','circle-xmark','filter','magnifying-glass','minus','plus','rotate-left','rotate-right','sliders','sort','xmark','grip-horizontal','grip-vertical','ellipsis','ellipsis-vertical','list','list-check','table-list','table-cells','border-all','window-restore','maximize','minimize'],
  'Arrows': ['arrow-down','arrow-left','arrow-right','arrow-up','arrow-down-long','arrow-up-long','arrow-trend-down','arrow-trend-up','arrows-rotate','arrows-left-right','arrows-up-down','chevron-down','chevron-left','chevron-right','chevron-up','turn-down','turn-up','right-long','left-long','up-long','down-long','angles-down','angles-left','angles-right','angles-up','caret-down','caret-left','caret-right','caret-up','circle-chevron-down','circle-chevron-left','circle-chevron-right','circle-chevron-up','location-arrow','share'],
  'Communication': ['bell','bell-slash','comment','comment-dots','comment-slash','comments','envelope','envelope-open','fax','inbox','message','microphone','microphone-slash','paper-plane','phone','phone-flip','phone-slash','phone-volume','reply','reply-all','rss','share-nodes','tower-broadcast','voicemail','broadcast-tower','at','hashtag'],
  'Business': ['briefcase','building','building-columns','chart-bar','chart-line','chart-pie','chart-simple','clipboard','clipboard-check','clipboard-list','coins','credit-card','database','dollar-sign','file-invoice','file-invoice-dollar','handshake','industry','landmark','money-bill','money-bill-wave','percent','receipt','scale-balanced','suitcase','wallet','calculator','chart-column','chart-area','piggy-bank','file-contract','signature'],
  'Media': ['camera','camera-retro','clapperboard','compact-disc','film','headphones','image','images','music','photo-film','play','podcast','radio','record-vinyl','stop','tv','video','video-slash','volume-high','volume-low','volume-off','volume-xmark','circle-play','pause','fast-forward','backward','forward','shuffle','repeat','youtube'],
  'People & Social': ['child','circle-user','face-frown','face-grin','face-meh','face-smile','person','person-biking','person-running','person-swimming','person-walking','users','users-gear','user','user-gear','user-group','user-plus','user-minus','user-check','user-xmark','user-lock','user-secret','user-shield','user-doctor','user-nurse','people-group','person-hiking','person-skiing'],
  'Alerts': ['bell','circle-check','circle-exclamation','circle-info','circle-question','circle-xmark','exclamation','triangle-exclamation','skull','skull-crossbones','radiation','ban','fire-flame-curved','virus','bug'],
  'Time': ['calendar','calendar-check','calendar-day','calendar-week','calendar-days','calendar-plus','calendar-minus','calendar-xmark','clock','hourglass','hourglass-end','hourglass-half','hourglass-start','stopwatch','sun','moon','calendar-alt','history','rotate-left'],
  'Shopping': ['bag-shopping','basket-shopping','cart-arrow-down','cart-plus','cart-shopping','gifts','shop','store','tag','tags','truck','truck-fast','warehouse','barcode','qrcode','receipt','credit-card','money-bill','dollar-sign'],
  'Health & Medical': ['brain','dna','eye','eye-dropper','hand-holding-medical','heart','heart-pulse','hospital','hospital-user','kit-medical','lungs','pills','prescription-bottle','syringe','teeth','thermometer','wheelchair','stethoscope','user-doctor','user-nurse','ambulance','capsules','band-aid','heartbeat'],
  'Security': ['lock','lock-open','shield','shield-check','shield-halved','shield-virus','user-lock','user-shield','key','fingerprint','id-badge','id-card','passport','eye','eye-slash'],
  'Transportation': ['bicycle','bus','car','car-rear','ferry','gas-pump','helicopter','motorcycle','plane','plane-arrival','plane-departure','ship','taxi','tractor','train','truck','van-shuttle','rocket','sailboat','cable-car','person-biking'],
  'Nature': ['bug','cat','cloud','cloud-rain','cloud-sun','dog','earth-americas','frog','horse','leaf','mountain','paw','rainbow','seedling','snowflake','spider','sun','tornado','tree','wind','moon','star','fire'],
  'Food & Drink': ['apple-whole','bacon','beer-mug-empty','bone','bowl-rice','candy-cane','carrot','cheese','cookie','egg','fish','hotdog','ice-cream','lemon','martini-glass','mug-hot','pepper-hot','pizza-slice','utensils','wine-glass','drumstick-bite','burger','mug-saucer'],
  'Technology': ['code','code-branch','cube','cubes','ethernet','floppy-disk','hard-drive','laptop','microchip','mobile-screen','mobile-screen-button','network-wired','robot','satellite','satellite-dish','server','tablet-screen-button','terminal','tower-broadcast','tv','desktop','keyboard','computer-mouse','print','usb'],
  'Education': ['atom','book','book-open','chalkboard','chalkboard-user','graduation-cap','microscope','pen','pencil','school','spell-check','trophy','ruler','compass','flask','globe'],
  'Shapes': ['circle','square','triangle','star','heart','diamond','hexagon','minus','plus','xmark','slash'],
};

// Font Awesome 6 Regular (lighter stroke versions)
const FA_REGULAR_ICONS: CatMap = {
  'Interface': ['bell','bookmark','calendar','circle','circle-check','circle-dot','circle-question','circle-xmark','clock','comment','comments','copy','envelope','eye','eye-slash','file','flag','folder','frown','gem','hand','heart','id-badge','id-card','image','lightbulb','list-alt','map','minus-square','meh','paper-plane','pause','pen-to-square','plus-square','rectangle-list','save','smile','square','star','thumbs-down','thumbs-up','trash-can','user'],
};

// Font Awesome 6 Brands
const FA_BRANDS_ICONS: CatMap = {
  'Social Media': ['facebook','instagram','twitter','x-twitter','linkedin','youtube','tiktok','snapchat','pinterest','reddit','tumblr','discord','slack','telegram','whatsapp','wechat','weibo','vk','line'],
  'Tech & Dev': ['github','gitlab','bitbucket','docker','npm','node-js','react','angular','vuejs','bootstrap','sass','less','css3','html5','js','php','python','java','apple','android','windows','linux','ubuntu','centos','debian','fedora','git'],
  'Companies': ['google','amazon','apple','microsoft','meta','spotify','netflix','uber','airbnb','dropbox','stripe','paypal','shopify','wordpress','woocommerce','joomla','drupal','magento','squarespace','wix'],
  'Design': ['figma','sketch','adobe','behance','dribbble','invision','font-awesome','trello','asana','jira','confluence'],
  'Dev Tools': ['github','gitlab','stack-overflow','codepen','jsfiddle','dev','hashnode','medium','substack'],
};

// Bootstrap Icons
const BOOTSTRAP_ICONS: CatMap = {
  'Interface': ['alarm','app','archive','asterisk','at','award','badge-check','badge-check-fill','bag','bag-fill','bag-heart','bar-chart','bar-chart-fill','bell','bell-fill','bell-slash','bookmark','bookmark-check','bookmark-fill','bookmark-heart','bookmark-star','box','boxes','bullseye','calendar','calendar-check','calendar-date','calendar-event','calendar-fill','calendar-heart','calendar-plus','capslock','card-checklist','card-heading','card-image','card-list','check','check-all','check-circle','check-circle-fill','check-lg','check-square','check-square-fill','circle','circle-fill','circle-half','clipboard','clipboard-check','clipboard-data','clipboard-fill','clipboard-heart','clipboard-plus','clock','clock-fill','code','code-slash','collection','command','copy','dash','dash-circle','dash-circle-fill','diamond','display','download','eraser','eye','eye-fill','eye-slash','filter','filter-circle','fingerprint','flag','flag-fill','funnel','funnel-fill','gear','gear-fill','gem','globe','graph-down','graph-up','grid','grid-1x2','grid-3x2','grid-3x3','hammer','hash','heart','heart-arrow','heart-fill','heart-half','heart-pulse','info','info-circle','info-circle-fill','kanban','keyboard','laptop','laptop-fill','layers','layout-sidebar','list','list-check','list-ol','list-stars','lock','lock-fill','magic','map','markdown','mask','megaphone','mic','mic-fill','mic-mute','moon','mortarboard','newspaper','palette','paperclip','patch-check','patch-exclamation','pause','pen','pencil','pencil-fill','pencil-square','percent','pie-chart','pie-chart-fill','pin','play','play-circle','plug','plus','plus-circle','plus-lg','plus-square','printer','puzzle','question','question-circle','question-circle-fill','reply','robot','rss','rulers','save','save-fill','scissors','search','send','server','share','shield','shield-check','shield-fill','shop','shuffle','sliders','sliders2','sort-alpha-down','sort-alpha-up','sort-down','sort-up','star','star-fill','star-half','sticky','stop','stopwatch','table','tag','tags','three-dots','three-dots-vertical','toggle-off','toggle-on','tools','trash','trash-fill','trash2','trophy','trophy-fill','tv','tv-fill','type','upload','wallet','watch','webcam','wifi','wifi-off','window','wrench','x','x-circle','x-circle-fill','x-lg','x-square','zoom-in','zoom-out'],
  'Arrows': ['arrow-bar-down','arrow-bar-left','arrow-bar-right','arrow-bar-up','arrow-clockwise','arrow-counterclockwise','arrow-down','arrow-down-circle','arrow-down-left','arrow-down-right','arrow-down-short','arrow-down-square','arrow-left','arrow-left-circle','arrow-left-right','arrow-repeat','arrow-return-left','arrow-right','arrow-right-circle','arrow-up','arrow-up-circle','arrow-up-right','arrows','arrows-angle-contract','arrows-angle-expand','caret-down','caret-left','caret-right','caret-up','chevron-bar-down','chevron-bar-left','chevron-bar-right','chevron-bar-up','chevron-compact-down','chevron-compact-left','chevron-compact-right','chevron-compact-up','chevron-double-down','chevron-double-left','chevron-double-right','chevron-double-up','chevron-down','chevron-left','chevron-right','chevron-up','skip-backward','skip-forward','skip-end','skip-start'],
  'Communication': ['broadcast','broadcast-pin','chat','chat-dots','chat-fill','chat-heart','chat-left','chat-left-dots','chat-quote','chat-right','chat-right-dots','chat-right-text','chat-square','chat-square-dots','chat-text','envelope','envelope-arrow-down','envelope-arrow-up','envelope-at','envelope-check','envelope-fill','envelope-heart','envelope-open','envelope-paper','envelope-plus','phone','phone-fill','phone-flip','telephone','telephone-fill','telephone-forward','telephone-inbound','telephone-outbound','telephone-plus','telegram','reddit','rss','rss-fill'],
  'Business': ['bank','bank2','briefcase','cash','cash-coin','cash-stack','coin','coins','credit-card','credit-card-2-back','credit-card-2-front','database','database-add','database-check','database-dash','database-fill','pie-chart','receipt','safe','safe-fill','stack','wallet','wallet-fill','speedometer','speedometer2'],
  'Files': ['file','file-arrow-down','file-arrow-up','file-bar-graph','file-binary','file-check','file-code','file-diff','file-earmark','file-earmark-arrow-down','file-earmark-arrow-up','file-earmark-code','file-earmark-fill','file-earmark-image','file-earmark-lock','file-earmark-minus','file-earmark-pdf','file-earmark-plus','file-earmark-richtext','file-earmark-text','file-earmark-word','file-earmark-zip','file-fill','file-image','file-music','file-pdf','file-plus','file-richtext','file-text','file-word','file-zip','files','folder','folder-check','folder-fill','folder-minus','folder-plus','folder-x','folder2'],
  'Media': ['camera','camera-fill','camera-reels','camera-video','camera-video-fill','compact-disc','film','headphones','headset','image','images','mic','mic-fill','music-note','music-note-beamed','music-player','play','play-btn','play-btn-fill','play-circle','record','record-btn','record-circle','skip-backward','skip-forward','speaker','tv','tv-fill','vinyl','volume-down','volume-mute','volume-off','volume-up'],
  'People': ['person','person-badge','person-check','person-circle','person-fill','person-gear','person-heart','person-lines-fill','person-lock','person-plus','person-rolodex','person-slash','people','people-fill'],
  'Transport': ['bicycle','bus','bus-front','car-front','ev-front','fuel-pump','train-front','truck','truck-flatbed','bicycle'],
  'Social': ['discord','facebook','github','instagram','linkedin','mastodon','slack','snapchat','spotify','steam','tiktok','twitter','twitch','vimeo','wechat','whatsapp','wordpress','x','youtube'],
  'Weather': ['cloud','cloud-arrow-down','cloud-arrow-up','cloud-check','cloud-drizzle','cloud-fill','cloud-fog','cloud-hail','cloud-lightning','cloud-lightning-rain','cloud-moon','cloud-rain','cloud-rain-heavy','cloud-sleet','cloud-snow','cloud-sun','clouds','moon','moon-fill','moon-stars','sun','sun-fill','sunglasses','thermometer','thermometer-half','thermometer-high','thermometer-low','thermometer-snow','thermometer-sun','tornado','wind'],
  'Technology': ['bluetooth','broadcast','bug','bug-fill','code','code-slash','cpu','cpu-fill','device-hdd','device-ssd','display','ethernet','hdd','hdd-fill','hdd-network','keyboard','keyboard-fill','laptop','laptop-fill','memory','modem','pc','pc-display','phone','phone-fill','router','router-fill','server','sim','smartwatch','terminal','terminal-fill','usb','usb-drive','wifi','wifi-off'],
  'Emoji': ['emoji-angry','emoji-dizzy','emoji-expressionless','emoji-frown','emoji-grimace','emoji-grin','emoji-heart-eyes','emoji-kiss','emoji-laughing','emoji-neutral','emoji-smile','emoji-sunglasses','emoji-wink'],
};

// Material Symbols Outlined
const MATERIAL_ICONS: CatMap = {
  'Action': ['accessibility','account_balance','account_balance_wallet','account_box','account_circle','add_shopping_cart','alarm','alarm_add','alarm_off','alarm_on','all_out','analytics','announcement','aspect_ratio','assessment','assignment','assignment_ind','assignment_late','assignment_return','assignment_returned','assignment_turned_in','autorenew','backup','block','bookmark','bookmark_border','bookmark_add','bookmarks','bug_report','build','build_circle','cached','calendar_today','calendar_view_month','cancel','change_history','check_circle','check_circle_outline','chrome_reader_mode','class','close','code','commute','compare_arrows','copyright','credit_card','dashboard','delete','delete_forever','delete_outline','description','dns','done','done_all','donut_large','donut_small','drag_indicator','dynamic_form','eco','edit_calendar','euro_symbol','event','event_seat','exit_to_app','explore','explore_off','extension','face','fact_check','favorite','favorite_border','feedback','file_download_done','filter_alt','find_in_page','fingerprint','flight_land','flight_takeoff','flip_to_back','flip_to_front','flutter_dash','g_translate','gavel','get_app','gif','grade','group_work','help','help_center','help_outline','highlight_off','history','history_toggle_off','home','home_filled','horizontal_split','hotel_class','hourglass_disabled','hourglass_empty','hourglass_full','http','https','important_devices','info','input','integration_instructions','invert_colors','label','label_important','language','launch','lightbulb','lightbulb_outline','line_style','line_weight','list','lock','lock_open','login','logout','loyalty','manage_accounts','mark_as_unread','maximize','mediation','minimize','model_training','new_releases','next_week','note_add','offline_bolt','offline_pin','opacity','open_in_browser','open_in_new','open_with','pageview','payment','pending','pending_actions','perm_camera_mic','perm_contact_calendar','perm_data_setting','perm_device_information','perm_identity','perm_media','perm_phone_msg','perm_scan_wifi','pets','picture_in_picture','play_for_work','polymer','power_settings_new','pregnant_woman','preview','print','privacy_tip','production_quantity_limits','published_with_changes','query_builder','question_answer','receipt','record_voice_over','redeem','remove_shopping_cart','reorder','report_problem','restore','restore_from_trash','restore_page','room','rounded_corner','satellite_alt','schedule','schedule_send','search','search_off','settings','settings_accessibility','settings_applications','settings_backup_restore','settings_bluetooth','settings_brightness','settings_cell','settings_ethernet','settings_input_antenna','settings_input_component','settings_input_hdmi','settings_overscan','settings_phone','settings_power','settings_remote','settings_system_daydream','settings_voice','share','shop','shop_two','shopping_bag','shopping_basket','shopping_cart','smart_button','source','space_dashboard','spellcheck','star_rate','stars','sticky_note_2','store','subdirectory_arrow_left','subdirectory_arrow_right','subject','subtitles','support_agent','swap_horiz','swap_vert','swap_vertical_circle','swipe','sync','sync_alt','system_update_alt','tab','tab_unselected','table_view','task_alt','text_rotate_up','text_rotation_down','text_rotation_none','timeline','today','toll','touch_app','track_changes','translate','trending_down','trending_flat','trending_up','turned_in','turned_in_not','update','upgrade','verified','verified_user','vertical_split','view_agenda','view_array','view_carousel','view_column','view_day','view_headline','view_in_ar','view_kanban','view_list','view_module','view_quilt','view_sidebar','view_stream','view_week','visibility','visibility_off','voice_over_off','watch_later','web','web_asset','width_full','width_normal','width_wide','work','work_off','work_outline','youtube_searched_for','zoom_in','zoom_out'],
  'Alert': ['add_alert','auto_delete','error','error_outline','notification_important','warning','warning_amber'],
  'AV': ['4k','5g','add_to_queue','airplay','album','art_track','av_timer','branding_watermark','call_to_action','closed_caption','closed_caption_off','control_camera','equalizer','explicit','fast_forward','fast_rewind','featured_play_list','featured_video','fiber_dvr','fiber_manual_record','fiber_new','fiber_pin','fiber_smart_record','forward_10','forward_30','forward_5','games','hd','hearing','high_quality','interpreter_mode','library_add','library_add_check','library_books','library_music','loop','mic','mic_none','mic_off','missed_video_call','movie','music_video','new_releases','not_interested','note','notes','on_demand_video','pause','pause_circle','pause_circle_filled','pause_circle_outline','play_arrow','play_circle','play_circle_filled','play_circle_outline','play_disabled','playlist_add','playlist_add_check','playlist_add_circle','playlist_play','queue','queue_music','queue_play_next','radio','recent_actors','remove_from_queue','repeat','repeat_on','repeat_one','repeat_one_on','replay','replay_10','replay_30','replay_5','shuffle','shuffle_on','skip_next','skip_previous','slow_motion_video','snooze','sort_by_alpha','stop','stop_circle','subscriptions','subtitles','surround_sound','video_call','video_collection','video_file','video_label','video_library','video_settings','videocam','videocam_off','videogame_asset','volume_down','volume_mute','volume_off','volume_up','web_asset_off'],
  'Communication': ['alternate_email','business','call','call_end','call_made','call_merge','call_missed','call_missed_outgoing','call_received','call_split','cancel_presentation','cell_tower','cell_wifi','chat','chat_bubble','chat_bubble_outline','clear_all','co_present','comment','contact_mail','contact_page','contact_phone','contact_support','contacts','desktop_access_disabled','dialpad','document_scanner','domain','domain_disabled','domain_verification','duo','email','forum','forward_to_inbox','hub','import_contacts','import_export','invert_colors_off','list_alt','live_help','location_off','location_on','mail_lock','mail_outline','manage_accounts','mark_chat_read','mark_chat_unread','mark_email_read','mark_email_unread','message','mobile_screen_share','nat','no_sim','pause_presentation','person_add_disabled','person_search','phone','phone_android','phone_bluetooth_speaker','phone_callback','phone_disabled','phone_enabled','phone_forwarded','phone_in_talk','phone_iphone','phone_locked','phone_missed','phone_paused','phonelink_erase','phonelink_lock','phonelink_ring','phonelink_setup','portable_wifi_off','present_to_all','print_disabled','queue','read_more','ring_volume','rss_feed','screen_share','send','sentiment_satisfied_alt','sip','speaker_phone','stay_current_landscape','stay_current_portrait','stay_primary_landscape','stay_primary_portrait','stop_screen_share','swap_calls','textsms','unsubscribe','voicemail','vpn_key','vpn_key_off','wifi_calling','wifi_calling_3'],
  'Content': ['add','add_box','add_circle','add_circle_outline','add_link','archive','backspace','ballot','block','bold','calculate','clear','content_copy','content_cut','content_paste','create','delete_sweep','drafts','dynamic_feed','filter_list','flag','font_download','font_download_off','forward','gesture','how_to_reg','how_to_vote','inbox','insights','inventory','inventory_2','link','link_off','low_priority','mail','markunread','markunread_mailbox','move_to_inbox','next_week','outlined_flag','policy','push_pin','redo','remove','remove_circle','remove_circle_outline','reply','reply_all','report','report_off','save','select_all','send','shield','sort','square_foot','stacked_bar_chart','stream','strikethrough_s','subscript','superscript','tag','text_format','today','undo','upcoming','waves','weekend'],
  'Maps': ['add_location','add_location_alt','add_road','agriculture','airline_stops','airlines','alt_route','atm','attractions','auto_awesome_mosaic','auto_stories','badge','beenhere','bike_scooter','boat','bus_alert','car_crash','car_rental','car_repair','church','circle','clean_hands','compass_calibration','connecting_airports','dangerous','delivery_dining','departure_board','design_services','diamond','dinner_dining','directions','directions_bike','directions_boat','directions_bus','directions_car','directions_ferry','directions_railway','directions_run','directions_subway','directions_transit','directions_walk','dry_cleaning','edit_attributes','edit_location','edit_location_alt','edit_road','electric_bike','electric_car','electric_moped','electric_rickshaw','electric_scooter','electrical_services','emergency','emergency_recording','emoji_food_beverage','emoji_nature','emoji_people','emoji_transportation','ev_station','factory','fastfood','festival','fire_truck','flight','flight_class','food_bank','forest','fort','gas_station','golf_course','grocery','hardware','hail','handyman','hike','hvac','ice_skating','kayaking','kitesurfing','layers','layers_clear','leaderboard','local_activity','local_airport','local_atm','local_bar','local_cafe','local_car_wash','local_convenience_store','local_dining','local_drink','local_fire_department','local_florist','local_gas_station','local_grocery_store','local_hospital','local_hotel','local_laundry_service','local_library','local_mall','local_movies','local_offer','local_parking','local_pharmacy','local_phone','local_pizza','local_play','local_police','local_post_office','local_printshop','local_restaurant','local_see','local_shipping','local_taxi','location_city','location_disabled','location_on','location_searching','luggage','map','minor_crash','moped','mosque','moving','museum','my_location','natural_disasters','near_me','near_me_disabled','no_meals','no_transfer','not_listed_location','park','pedal_bike','person_pin','person_pin_circle','pest_control','pharmacy','pin_drop','place','playground','plumbing','point_of_sale','ramen_dining','rate_review','recommend','restaurant','restaurant_menu','rv_hookup','sailing','satellite','set_meal','synagogue','takeout_dining','tapas','terrain','traffic','train','tram','transfer_within_a_station','transit_enterexit','trip_origin','two_wheeler','volunteer_activism','water','where_to_vote'],
  'Navigation': ['apps','arrow_back','arrow_back_ios','arrow_downward','arrow_drop_down','arrow_drop_down_circle','arrow_drop_up','arrow_forward','arrow_forward_ios','arrow_left','arrow_right','arrow_upward','cancel','check','chevron_left','chevron_right','close','expand_less','expand_more','first_page','fullscreen','fullscreen_exit','home','last_page','menu','menu_open','more_horiz','more_vert','refresh','subdirectory_arrow_left','subdirectory_arrow_right','unfold_less','unfold_more'],
  'People': ['accessibility','accessibility_new','accessible','accessible_forward','account_box','account_circle','add_moderator','admin_panel_settings','attribution','badge','follow_the_signs','group','group_add','group_off','group_remove','group_work','groups','how_to_reg','no_accounts','perm_contact_calendar','perm_identity','person','person_add','person_add_alt','person_off','person_outline','person_pin','person_pin_circle','person_remove','person_search','personal_injury','pregnant_woman','record_voice_over','reduce_capacity','self_improvement','sentiment_dissatisfied','sentiment_neutral','sentiment_satisfied','sentiment_very_dissatisfied','sentiment_very_satisfied','social_distance','supervised_user_circle','support_agent','switch_account','wc','woman'],
  'Social': ['cake','celebration','family_restroom','holiday_village','park','people','person_pin','sentiment_satisfied','sports','sports_bar','whatshot'],
};

// Tabler Icons
const TABLER_ICONS: CatMap = {
  'Interface': ['adjustments','adjustments-alt','adjustments-horizontal','alert-circle','alert-octagon','alert-triangle','apps','ban','bell','bell-off','bell-ringing','bookmark','bookmarks','check','checkbox','chevron-down','chevron-left','chevron-right','chevron-up','circle','circle-check','circle-dashed','circle-dot','circle-half','circle-minus','circle-off','circle-plus','circle-x','clipboard','clipboard-check','clipboard-copy','clipboard-list','clock','copy','devices','dots','dots-circle-horizontal','dots-vertical','drag-drop','drag-drop-2','eye','eye-check','eye-off','filter','filter-off','flame','funnel','gear','grid-dots','grid-pattern','hash','heart','heart-broken','heart-off','help','help-circle','home','home-2','inbox','info-circle','key','keyboard','layers-difference','layers-intersect','layout','link','list','list-check','list-numbers','lock','lock-access','lock-off','lock-open','login','logout','maximize','menu','menu-2','minimize','minus','moon','moon-2','more','notification','palette','paperclip','pencil','pin','plus','power','print','puzzle','qrcode','question-mark','refresh','reload','repeat','reply','rotate','route','rss','save','scan','search','selector','send','settings','share','share-2','shopping-bag','shopping-cart','sort-ascending','sort-descending','sparkles','square','square-check','square-minus','square-off','square-plus','square-x','star','star-half','star-off','sun','sun-off','switch','switch-horizontal','switch-vertical','tag','tags','target','thumb-down','thumb-up','toggle-left','toggle-right','tools','trash','trash-off','trophy','upload','user','users','wand','x','zoom-in','zoom-cancel','zoom-check','zoom-in','zoom-money','zoom-out','zoom-pan','zoom-question'],
  'Arrows': ['arrow-back','arrow-back-up','arrow-down','arrow-down-circle','arrow-down-left','arrow-down-right','arrow-forward','arrow-forward-up','arrow-left','arrow-left-bar','arrow-left-circle','arrow-left-right','arrow-narrow-down','arrow-narrow-left','arrow-narrow-right','arrow-narrow-up','arrow-right','arrow-right-bar','arrow-right-circle','arrow-up','arrow-up-bar','arrow-up-circle','arrow-up-left','arrow-up-right','arrows-diagonal','arrows-diagonal-2','arrows-double-ne-sw','arrows-double-nw-se','arrows-down','arrows-down-up','arrows-horizontal','arrows-join','arrows-join-2','arrows-left','arrows-left-right','arrows-maximize','arrows-minimize','arrows-right','arrows-split','arrows-split-2','arrows-up','arrows-up-down','arrows-vertical','axis-x','axis-y','cap','chevrons-down','chevrons-left','chevrons-right','chevrons-up','circle-arrow-down','circle-arrow-left','circle-arrow-right','circle-arrow-up','corner-down-left','corner-down-right','corner-left-down','corner-left-up','corner-right-down','corner-right-up','corner-up-left','corner-up-right','flip-horizontal','flip-vertical','fold','fold-down','fold-up','sort-ascending','sort-descending','transfer-in','transfer-out'],
  'Communication': ['antenna-bars-1','antenna-bars-2','antenna-bars-3','antenna-bars-4','antenna-bars-5','bell','bell-off','bell-ringing','bell-ringing-2','bell-school','bell-school-off','bell-x','broadcast','device-mobile','device-tablet','mail','mail-forward','mail-opened','mail-opened-filled','message','message-2','message-circle','message-circle-2','message-dots','message-off','message-plus','message-report','message-share','messages','messages-off','microphone','microphone-off','phone','phone-call','phone-check','phone-incoming','phone-off','phone-outgoing','phone-paused','phone-plus','phone-x','radio','rss','send','speakerphone','voicemail'],
  'Design': ['anchor','aperture','artboard','artboard-off','aspect-ratio','background','beach','bleed','blur','bold','border-all','border-bottom','border-horizontal','border-inner','border-left','border-none','border-outer','border-right','border-style','border-top','border-vertical','brightness','brightness-2','brightness-auto','brightness-half','brightness-off','brightness-up','brush','color-picker','color-picker-off','color-swatch','columns','contrast','contrast-2','contrast-filled','crop','design','details','device-laptop','dots','flip-horizontal','flip-vertical','focus','focus-2','font','font-size','frame','gradient','heading','heading-off','html','italic','layers-difference','layers-intersect','layers-subtract','layers-union','layout','layout-2','layout-align-bottom','layout-align-center','layout-align-left','layout-align-middle','layout-align-right','layout-align-top','layout-board','layout-bottombar','layout-bottombar-expand','layout-cards','layout-columns','layout-dashboard','layout-distribute-horizontal','layout-distribute-vertical','layout-grid','layout-kanban','layout-list','layout-navbar','layout-navbar-expand','layout-rows','layout-sidebar','layout-sidebar-left-expand','layout-sidebar-left-inactive','layout-sidebar-right','layout-sidebar-right-expand','layout-sidebar-right-inactive','layout-topbar','layout-topbar-expand','letter-a','letter-b','letter-c','line-height','link','list','list-check','list-details','list-numbers','list-search','list-tree','marquee','marquee-2','minus','paint','palette','pen-tool','pencil','pilcrow','pin','proportions','quote','radius-bottom-left','radius-bottom-right','radius-top-left','radius-top-right','shadow','shadow-off','size','slash','space','strikethrough','subscript','superscript','switch-horizontal','switch-vertical','text-direction-ltr','text-direction-rtl','text-resize','text-size','text-wrap','text-wrap-column','text-wrap-disabled','typography','underline','vector','vector-bezier','vector-bezier-2','vector-circle','vector-line','vector-spline','vector-triangle'],
  'Devices': ['access-point','access-point-off','bluetooth','bluetooth-connected','bluetooth-off','cast','cpu','cpu-2','device-analytics','device-audio-tape','device-camera-phone','device-cctv','device-computer-camera','device-computer-camera-off','device-desktop','device-desktop-analytics','device-desktop-off','device-floppy','device-gamepad','device-gamepad-2','device-heart-monitor','device-imac','device-imac-2','device-ipad','device-ipad-horizontal','device-laptop','device-laptop-off','device-mobile','device-mobile-charging','device-mobile-message','device-mobile-off','device-mobile-rotated','device-mobile-vibration','device-nintendo','device-nintendo-off','device-remote','device-sd-card','device-speaker','device-speaker-off','device-tablet','device-tablet-off','device-tv','device-tv-off','device-tv-old','device-watch','device-watch-off','device-watch-stats','device-watch-stats-2','keyboard','keyboard-hide','keyboard-off','keyboard-show','mouse','mouse-2','mouse-off','printer','printer-off','router','router-off','scan','server','server-2','server-off','tablet','tablet-old','tv','tv-off','usb'],
  'Finance': ['cash','cash-banknote','cash-banknote-off','coin','coin-bitcoin','coin-euro','coin-monero','coin-off','coin-pound','coin-rupee','coin-yen','coins','credit-card','credit-card-off','currency-bahraini','currency-baht','currency-bitcoin','currency-cent','currency-dinar','currency-dirham','currency-dollar','currency-dollar-australian','currency-dollar-canadian','currency-dollar-singapore','currency-ethereum','currency-euro','currency-forint','currency-frank','currency-guadaraní','currency-hryvnia','currency-krone-czech','currency-krone-danish','currency-krone-swedish','currency-leu','currency-lira','currency-litecoin','currency-naira','currency-pound','currency-real','currency-ripple','currency-riyal','currency-ruble','currency-rupee','currency-shekel','currency-solana','currency-tenge','currency-tugrik','currency-won','currency-yen','currency-zloty','discount','discount-2','discount-check','discount-check-2','gift','gift-card','moneybag','paywall','percentage','pig','pig-money','piggy-bank','receipt','receipt-2','receipt-off','report-money','sale','shopping-cart','shopping-cart-discount','shopping-cart-off','shopping-cart-plus','shopping-cart-x','transfer','wallet','wallet-off'],
  'Health': ['activity','affiliate','ambulance','brain','deer','disabled','disability','dna','dna-2','drug','eh','eye','eye-check','eye-closed','eye-off','eye-table','first-aid-kit','gender-agender','gender-androgyne','gender-bigender','gender-demi-boy','gender-demi-girl','gender-epicene','gender-female','gender-female-male','gender-genderfluid','gender-genderless','gender-genderqueer','gender-hermaphrodite','gender-intergender','gender-male','gender-male-female','gender-neutrois','gender-third','gender-transgender','gps','health-recognition','heart','heart-broken','heart-handshake','heart-minus','heart-off','heart-plus','heart-rate-monitor','lungs','medical-cross','microscope','mood-angry','mood-confuzed','mood-crazy-happy','mood-empty','mood-happy','mood-kid','mood-nervous','mood-nerd','mood-sad','mood-smile','mood-suprised','mood-tongue','needle','needle-thread','stethoscope','vaccine','virus','virus-off','wheelchair'],
  'Maps': ['3d-cube-sphere','beach','beacon','bike','building','building-arch','building-bank','building-bridge','building-bridge-2','building-carousel','building-castle','building-church','building-community','building-factory','building-factory-2','building-fortress','building-hospital','building-lighthouse','building-monument','building-mosque','building-pavilion','building-skyscraper','building-stadium','building-store','buildings','bus','bus-stop','car','car-crash','car-garage','car-off','car-suv','castle','church','compass','current-location','direction','direction-horizontal','direction-sign','directions','fence','gas-station','gate','gps','helicopter','home','home-2','home-search','hotel','iron','kayak','library','location','location-broken','location-off','location-search','map','map-2','map-pin','map-pin-off','map-pins','map-question','map-search','mast','moped','motorbike','mountain','navigation','network','oil-lamp','parking','pedestrian','pin','plane','plane-arrival','plane-departure','plane-inflight','plane-off','plant','plant-2','police-badge','radar','road','road-off','road-sign','sailboat','scooter','seeding','seeding-off','skateboard','skooter','snowflake','steering-wheel','submarine','swimming','temperature','tent','tie','trail-sign','tractor','trail-sign','tree','trees','truck','truck-delivery','truck-off','truck-return','windmill','windmill-off'],
  'Brand': ['brand-4chan','brand-adobe','brand-airbnb','brand-airtable','brand-amazon','brand-amd','brand-amigo','brand-amzn','brand-android','brand-angular','brand-apple','brand-apple-arcade','brand-apple-podcast','brand-appstore','brand-arch-linux','brand-at','brand-azure','brand-backblaze','brand-badoo','brand-baidu','brand-bandcamp','brand-behance','brand-binance','brand-bing','brand-bitbucket','brand-blackberry','brand-bootstrap','brand-brave','brand-bumble','brand-buzzfeed','brand-cake','brand-cashapp','brand-chrome','brand-cinema-hd','brand-citymapper','brand-clubhouse','brand-codepen','brand-codesandbox','brand-coinbase','brand-conceptboard','brand-craft','brand-crunchbase','brand-css3','brand-d3','brand-deliveroo','brand-deno','brand-deviantart','brand-discord','brand-disney','brand-disqus','brand-django','brand-docker','brand-docker-simple','brand-doctrine','brand-dolby-digital','brand-douban','brand-draft2digital','brand-dribbble','brand-dribbble-filled','brand-dropbox','brand-edge','brand-envato','brand-etsy','brand-facebook','brand-feedly','brand-figma','brand-finder','brand-firefox','brand-flickr','brand-flutter','brand-foursquare','brand-framer','brand-funimation','brand-gatsby','brand-git','brand-github','brand-gitlab','brand-gmail','brand-google','brand-google-analytics','brand-google-drive','brand-google-fit','brand-google-maps','brand-google-one','brand-google-photos','brand-google-play','brand-google-podcasts','brand-grammarly','brand-gravatar','brand-grindr','brand-html5','brand-instagram','brand-intercom','brand-ionic','brand-javascript','brand-jest','brand-kickstarter','brand-kotlin','brand-laravel','brand-last-fm','brand-line','brand-linkedin','brand-loom','brand-mailchimp','brand-mastercard','brand-medium','brand-meta','brand-messenger','brand-messenger-filled','brand-metroui','brand-microsoft','brand-microsoft-teams','brand-miniprogram','brand-mixpanel','brand-monday','brand-mongodb','brand-my-space','brand-mysql','brand-netbeans','brand-netflix','brand-netlify','brand-nextjs','brand-nordvpn','brand-notion','brand-npm','brand-nuxt','brand-nytimes','brand-office','brand-ok-ru','brand-onedrive','brand-open-source','brand-opera','brand-pagekit','brand-patreon','brand-paypal','brand-paypal-filled','brand-periscope','brand-php','brand-picsart','brand-pinterest','brand-planetscale','brand-pocket','brand-postgresql','brand-product-hunt','brand-pushbullet','brand-python','brand-react','brand-react-native','brand-reddit','brand-redux','brand-revolut','brand-safari','brand-samsungpass','brand-snapchat','brand-soundcloud','brand-sourcetree','brand-spotify','brand-stackoverflow','brand-steam','brand-stripe','brand-sublime-text','brand-svelte','brand-swift','brand-symantec','brand-tailwind','brand-telegram','brand-telegram-filled','brand-thread','brand-tidal','brand-tiktok','brand-tinder','brand-toptal','brand-tripadvisor','brand-tumblr','brand-twitch','brand-twitter','brand-uber','brand-ubuntu','brand-unity','brand-unsplash','brand-valorant','brand-vercel','brand-vimeo','brand-vinted','brand-vk','brand-vnv','brand-vsco','brand-vscode','brand-vuejs','brand-walmart','brand-waze','brand-webflow','brand-whatsapp','brand-wikipedia','brand-windows','brand-windy','brand-wordpress','brand-xbox','brand-xing','brand-yahoo','brand-ycombinator','brand-youtube','brand-youtube-filled','brand-zoom'],
  'Document': ['article','book','book-2','book-download','book-off','book-upload','books','clipboard','clipboard-check','clipboard-data','clipboard-list','clipboard-text','clipboard-x','copyleft','copyright','database','database-export','database-import','database-off','file','file-3d','file-alert','file-analytics','file-archive','file-arrow-left','file-arrow-right','file-badge','file-bar-chart','file-broken','file-certificate','file-chart','file-check','file-code','file-code-2','file-database','file-description','file-diff','file-digits','file-dislike','file-dollar','file-dots','file-download','file-euro','file-export','file-filled','file-import','file-info','file-invoice','file-like','file-minus','file-music','file-off','file-pencil','file-phone','file-plus','file-power','file-report','file-rss','file-scissors','file-search','file-settings','file-shredder','file-signal','file-spreadsheet','file-stack','file-star','file-symlink','file-text','file-time','file-typography','file-unknown','file-upload','file-vector','file-x','file-zip','files','files-off','folder','folder-down','folder-minus','folder-off','folder-open','folder-plus','folder-search','folder-symlink','folder-up','folder-x','folders','id','id-badge','id-badge-2','memo','note','notebook','notebook-off','notes','notes-off','paperclip','presentation','presentation-analytics','report','report-analytics','report-medical','report-money','report-search','script','source-code','table','table-alias','table-down','table-export','table-import','table-off','table-options','table-plus','table-shortcut'],
};

// ── Registry ──────────────────────────────────────────────────────────────────

const RECENT_KEY = 'jalpi_icon_recent';
const FAVS_KEY   = 'jalpi_icon_favs';
const MAX_RECENT = 24;

function iconKey(icon: PickerIcon): string {
  return `${icon.lib}:${icon.name}`;
}

// Build PickerIcon entries for CDN library data
function buildFontIcons(lib: string, prefix: string, catMap: CatMap): PickerIcon[] {
  const icons: PickerIcon[] = [];
  for (const [cat, names] of Object.entries(catMap)) {
    for (const name of names) {
      icons.push({
        lib, name,
        label: name.replace(/-/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()),
        category: cat,
        type: 'font',
        cls: prefix + name,
      });
    }
  }
  return icons;
}

function buildMaterialIcons(catMap: CatMap): PickerIcon[] {
  const icons: PickerIcon[] = [];
  for (const [cat, names] of Object.entries(catMap)) {
    for (const name of names) {
      icons.push({
        lib: 'material', name,
        label: name.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()),
        category: cat,
        type: 'font',
        cls: 'material-symbols-outlined',
      });
    }
  }
  return icons;
}

class IconRegistry {
  private cache: Map<string, PickerIcon[]> = new Map();
  private loadedCss: Set<string> = new Set();
  private allIcons: PickerIcon[] = [];
  private built = false;

  private build() {
    if (this.built) return;
    this.built = true;
    const fa_s  = buildFontIcons('fa-solid',   'fa-solid fa-',   FA_SOLID_ICONS);
    const fa_r  = buildFontIcons('fa-regular', 'fa-regular fa-', FA_REGULAR_ICONS);
    const fa_b  = buildFontIcons('fa-brands',  'fa-brands fa-',  FA_BRANDS_ICONS);
    const bi    = buildFontIcons('bootstrap',  'bi bi-',          BOOTSTRAP_ICONS);
    const mat   = buildMaterialIcons(MATERIAL_ICONS);
    const tab   = buildFontIcons('tabler',     'ti ti-',          TABLER_ICONS);
    this.allIcons = [...BUILTIN_ICONS, ...fa_s, ...fa_r, ...fa_b, ...bi, ...mat, ...tab];
  }

  getAll(lib?: string, category?: string): PickerIcon[] {
    this.build();
    let list = lib ? this.allIcons.filter((i) => i.lib === lib) : this.allIcons;
    if (category) list = list.filter((i) => i.category === category);
    return list;
  }

  search(query: string, lib?: string): PickerIcon[] {
    this.build();
    const q = query.toLowerCase().trim();
    if (!q) return this.getAll(lib);
    return this.allIcons.filter((i) => {
      if (lib && i.lib !== lib) return false;
      return i.name.includes(q) || i.label.toLowerCase().includes(q) || i.category.toLowerCase().includes(q);
    });
  }

  getCategories(lib?: string): string[] {
    this.build();
    const list = lib ? this.allIcons.filter((i) => i.lib === lib) : this.allIcons;
    return [...new Set(list.map((i) => i.category))];
  }

  getLibraryDef(lib: string): LibraryDef | undefined {
    return LIBRARIES.find((l) => l.id === lib);
  }

  async loadLibraryCss(lib: string): Promise<boolean> {
    if (this.loadedCss.has(lib)) return true;
    const def = LIBRARIES.find((l) => l.id === lib);
    if (!def?.cssUrl) { this.loadedCss.add(lib); return true; }
    // Check if already in document (FA loads all 3 sub-libs from same URL)
    if (document.querySelector(`link[href="${def.cssUrl}"]`)) {
      this.loadedCss.add(lib);
      // Also mark sibling fa libs
      if (lib.startsWith('fa-')) {
        this.loadedCss.add('fa-solid');
        this.loadedCss.add('fa-regular');
        this.loadedCss.add('fa-brands');
      }
      return true;
    }
    return new Promise((resolve) => {
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = def.cssUrl!;
      link.onload = () => {
        this.loadedCss.add(lib);
        if (lib.startsWith('fa-')) {
          this.loadedCss.add('fa-solid');
          this.loadedCss.add('fa-regular');
          this.loadedCss.add('fa-brands');
        }
        resolve(true);
      };
      link.onerror = () => resolve(false);
      document.head.appendChild(link);
    });
  }

  isCssLoaded(lib: string): boolean {
    return this.loadedCss.has(lib) || lib === 'builtin';
  }

  getRecent(): PickerIcon[] {
    this.build();
    try {
      const raw = JSON.parse(localStorage.getItem(RECENT_KEY) || '[]') as { lib: string; name: string }[];
      return raw.map((r) => this.allIcons.find((i) => i.lib === r.lib && i.name === r.name)).filter(Boolean) as PickerIcon[];
    } catch { return []; }
  }

  addRecent(icon: PickerIcon) {
    try {
      const existing = JSON.parse(localStorage.getItem(RECENT_KEY) || '[]') as { lib: string; name: string }[];
      const k = iconKey(icon);
      const filtered = existing.filter((r) => `${r.lib}:${r.name}` !== k);
      filtered.unshift({ lib: icon.lib, name: icon.name });
      localStorage.setItem(RECENT_KEY, JSON.stringify(filtered.slice(0, MAX_RECENT)));
    } catch { /* ignore */ }
  }

  getFavorites(): PickerIcon[] {
    this.build();
    try {
      const raw = JSON.parse(localStorage.getItem(FAVS_KEY) || '[]') as { lib: string; name: string }[];
      return raw.map((r) => this.allIcons.find((i) => i.lib === r.lib && i.name === r.name)).filter(Boolean) as PickerIcon[];
    } catch { return []; }
  }

  toggleFavorite(icon: PickerIcon) {
    try {
      const existing = JSON.parse(localStorage.getItem(FAVS_KEY) || '[]') as { lib: string; name: string }[];
      const k = iconKey(icon);
      const idx = existing.findIndex((r) => `${r.lib}:${r.name}` === k);
      if (idx >= 0) existing.splice(idx, 1);
      else existing.push({ lib: icon.lib, name: icon.name });
      localStorage.setItem(FAVS_KEY, JSON.stringify(existing));
    } catch { /* ignore */ }
  }

  isFavorite(icon: PickerIcon): boolean {
    try {
      const raw = JSON.parse(localStorage.getItem(FAVS_KEY) || '[]') as { lib: string; name: string }[];
      const k = iconKey(icon);
      return raw.some((r) => `${r.lib}:${r.name}` === k);
    } catch { return false; }
  }

  // Build an IconValue from a PickerIcon
  toIconValue(icon: PickerIcon): IconValue {
    if (icon.type === 'svg') {
      return { type: 'svg', lib: icon.lib, name: icon.name, svg: icon.svg };
    }
    return { type: 'font', lib: icon.lib, name: icon.name, cls: icon.cls };
  }
}

export const iconRegistry = new IconRegistry();

// ── Compat helpers ────────────────────────────────────────────────────────────

// Resolve legacy string key or new IconValue to a consistent IconValue
export function resolveIconValue(raw: string | IconValue | undefined): IconValue | null {
  if (!raw) return null;
  if (typeof raw === 'object' && raw.type) return raw;
  // Legacy string key — look up in BUILTIN_ICONS
  const legacy = BUILTIN_ICONS.find((i) => i.name === raw as string);
  if (legacy) return { type: 'svg', lib: 'builtin', name: legacy.name, svg: legacy.svg };
  return null;
}

// Render an IconValue to an HTML string (used by PHP renderer compat check + test renders)
export function iconValueToHtml(v: IconValue | null, style?: { size?: string; color?: string }): string {
  if (!v) return '';
  const sz    = style?.size  ? ` font-size:${style.size};`  : '';
  const col   = style?.color ? ` color:${style.color};`      : '';
  const wrapSt = sz || col ? ` style="${sz}${col}"` : '';
  if (v.type === 'svg' && v.svg) {
    return `<span class="jalpi-icon-inner"${wrapSt}>${v.svg}</span>`;
  }
  if (v.type === 'font' && v.lib === 'material') {
    return `<span class="${v.cls}"${wrapSt}>${v.name}</span>`;
  }
  if (v.type === 'font' && v.cls) {
    return `<i class="${v.cls}"${wrapSt}></i>`;
  }
  if (v.type === 'img' && v.url) {
    return `<img src="${v.url}" alt="${v.alt || ''}"${wrapSt} />`;
  }
  return '';
}
