+
{ setQuery(e.target.value); setLimit(PAGE) }}
+ placeholder={`Search ${SLUGS.length} brand icons...`}
+ className="bg-[#0d1117] border-[#30363d] text-xs h-7"
+ aria-label="Brand icon search"
+ />
+
+ {filtered.length} match{filtered.length === 1 ? '' : 'es'} · icons served via jsDelivr CDN
+
+
+
+ {visible.map((slug) => {
+ const selected = slug === selectedSlug
+ return (
+
+ )
+ })}
+
+ {filtered.length > limit && (
+
+ )}
+ {filtered.length === 0 && (
+
No icons match.
+ )}
+
+
+ )
+}
diff --git a/frontend/src/components/modals/NodeModal.tsx b/frontend/src/components/modals/NodeModal.tsx
index 714d67b..da28e01 100644
--- a/frontend/src/components/modals/NodeModal.tsx
+++ b/frontend/src/components/modals/NodeModal.tsx
@@ -8,7 +8,8 @@ import { Label } from '@/components/ui/label'
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } from '@/components/ui/select'
import { NODE_TYPE_LABELS, type NodeData, type NodeType, type CheckMethod } from '@/types'
import { resolveNodeColors } from '@/utils/nodeColors'
-import { ICON_REGISTRY, ICON_CATEGORIES, NODE_TYPE_DEFAULT_ICONS } from '@/utils/nodeIcons'
+import { ICON_REGISTRY, ICON_CATEGORIES, NODE_TYPE_DEFAULT_ICONS, isBrandIconKey, brandIconSlug, brandIconUrl } from '@/utils/nodeIcons'
+import { BrandIconPicker } from './BrandIconPicker'
import { MIN_BOTTOM_HANDLES, MAX_BOTTOM_HANDLES, clampBottomHandles } from '@/utils/handleUtils'
const NODE_TYPE_GROUPS: { label: string; types: NodeType[] }[] = [
@@ -61,6 +62,7 @@ export function NodeModal({ open, onClose, onSubmit, initial, title = 'Add Node'
const [form, setForm] = useState