{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "contacts-table",
  "title": "Contacts table",
  "description": "Contacts table is a production-ready tables component from BJORK UI, packaged for shadcn registries.",
  "dependencies": [
    "framer-motion",
    "lucide-react",
    "next-themes"
  ],
  "files": [
    {
      "path": "components/bjork-ui/tables/contacts-table.tsx",
      "content": "\"use client\";\n\nimport { useState, useEffect, useMemo } from \"react\";\nimport { motion, useReducedMotion, AnimatePresence } from \"framer-motion\";\nimport { useTheme } from \"next-themes\";\nimport { Download, ChevronDown, X, Mail, Twitter, User } from \"lucide-react\";\nimport {\n  getBjorkSignalPalette,\n  getBjorkTablePalette,\n} from \"./table-theme\";\n\nexport interface Contact {\n  id: string;\n  name: string;\n  email: string;\n  connectionStrength: \"Very weak\" | \"Weak\" | \"Good\" | \"Very strong\";\n  twitterFollowers: number;\n  description?: string;\n}\n\ninterface ContactsTableProps {\n  title?: string;\n  contacts?: Contact[];\n  onContactSelect?: (contactId: string) => void;\n  className?: string;\n  enableAnimations?: boolean;\n}\n\nconst defaultContacts: Contact[] = [\n  {\n    id: \"1\",\n    name: \"Pierre from Claap\",\n    email: \"pierre@claap.io\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 2400,\n    description: \"Tech entrepreneur and investor\"\n  },\n  {\n    id: \"2\",\n    name: \"HardwareSavvy\",\n    email: \"hardwaresavvy+andr...\",\n    connectionStrength: \"Very strong\",\n    twitterFollowers: 8900,\n    description: \"Hardware specialist\"\n  },\n  {\n    id: \"3\",\n    name: \"Voiceform\",\n    email: \"harrison@voiceform.c...\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 5200,\n    description: \"Voice technology expert\"\n  },\n  {\n    id: \"4\",\n    name: \"Marketer Milk\",\n    email: \"hi@marketmilk.com\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 6100,\n    description: \"Marketing strategist\"\n  },\n  {\n    id: \"5\",\n    name: \"Allen from CAST AI\",\n    email: \"allen@mail.cast.ai\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 3300,\n    description: \"AI infrastructure lead\"\n  },\n  {\n    id: \"6\",\n    name: \"Marija Krasnovskytė\",\n    email: \"marija@cast.ai\",\n    connectionStrength: \"Very weak\",\n    twitterFollowers: 1800,\n    description: \"Technical advisor\"\n  },\n  {\n    id: \"7\",\n    name: \"eryn@basistheory.com\",\n    email: \"eryn@basistheory.com\",\n    connectionStrength: \"Very weak\",\n    twitterFollowers: 2100,\n    description: \"Security specialist\"\n  },\n  {\n    id: \"8\",\n    name: \"Brad Patterson\",\n    email: \"brad@basistheory.com\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 4500,\n    description: \"Product manager\"\n  },\n  {\n    id: \"9\",\n    name: \"Sarah Chen\",\n    email: \"sarah.chen@techvault.com\",\n    connectionStrength: \"Very strong\",\n    twitterFollowers: 12400,\n    description: \"CEO and founder\"\n  },\n  {\n    id: \"10\",\n    name: \"David Rodriguez\",\n    email: \"david.rodriguez@innovate.io\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 7800,\n    description: \"Lead developer\"\n  },\n  {\n    id: \"11\",\n    name: \"Emily Watson\",\n    email: \"emily.watson@future.co\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 3900,\n    description: \"Marketing director\"\n  },\n  {\n    id: \"12\",\n    name: \"James Mitchell\",\n    email: \"james@buildit.dev\",\n    connectionStrength: \"Very strong\",\n    twitterFollowers: 9200,\n    description: \"Architect and advisor\"\n  },\n  {\n    id: \"13\",\n    name: \"Lisa Anderson\",\n    email: \"lisa.anderson@ventures.com\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 5600,\n    description: \"Venture investor\"\n  },\n  {\n    id: \"14\",\n    name: \"Michael Zhang\",\n    email: \"michael@cloudtech.ai\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 4100,\n    description: \"Infrastructure engineer\"\n  },\n  {\n    id: \"15\",\n    name: \"Jennifer Lee\",\n    email: \"jen@designsystem.io\",\n    connectionStrength: \"Very strong\",\n    twitterFollowers: 11200,\n    description: \"Design system lead\"\n  },\n  {\n    id: \"16\",\n    name: \"Robert Chang\",\n    email: \"robert.chang@quantify.co\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 6800,\n    description: \"Analytics expert\"\n  },\n  {\n    id: \"17\",\n    name: \"Amanda Pierce\",\n    email: \"amanda@growthlab.com\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 2900,\n    description: \"Growth consultant\"\n  },\n  {\n    id: \"18\",\n    name: \"Christopher Hayes\",\n    email: \"chris.hayes@webscale.io\",\n    connectionStrength: \"Very strong\",\n    twitterFollowers: 13500,\n    description: \"Platform engineer\"\n  },\n  {\n    id: \"19\",\n    name: \"Victoria Moore\",\n    email: \"victoria@datasync.com\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 7100,\n    description: \"Data scientist\"\n  },\n  {\n    id: \"20\",\n    name: \"Nicholas Brown\",\n    email: \"nick@apibase.dev\",\n    connectionStrength: \"Very weak\",\n    twitterFollowers: 1500,\n    description: \"API developer\"\n  },\n  {\n    id: \"21\",\n    name: \"Rebecca Sullivan\",\n    email: \"rebecca.s@innovationlab.io\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 8300,\n    description: \"Innovation strategist\"\n  },\n  {\n    id: \"22\",\n    name: \"Thomas Wright\",\n    email: \"thomas@blockchain.tech\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 3700,\n    description: \"Blockchain developer\"\n  },\n  {\n    id: \"23\",\n    name: \"Maria Garcia\",\n    email: \"maria.garcia@futuretech.com\",\n    connectionStrength: \"Very strong\",\n    twitterFollowers: 10800,\n    description: \"Tech evangelist\"\n  },\n  {\n    id: \"24\",\n    name: \"Daniel Park\",\n    email: \"daniel@smartsolutions.ai\",\n    connectionStrength: \"Good\",\n    twitterFollowers: 6400,\n    description: \"Solutions architect\"\n  },\n  {\n    id: \"25\",\n    name: \"Sophie Laurent\",\n    email: \"sophie.laurent@design.co\",\n    connectionStrength: \"Weak\",\n    twitterFollowers: 4200,\n    description: \"UX lead\"\n  }\n];\n\ntype SortField = \"name\" | \"connectionStrength\" | \"twitterFollowers\";\ntype SortOrder = \"asc\" | \"desc\";\n\nexport function ContactsTable({\n  title = \"Person\",\n  contacts: initialContacts = defaultContacts,\n  onContactSelect,\n  className = \"\",\n  enableAnimations = true\n}: ContactsTableProps = {}) {\n  const [selectedContacts, setSelectedContacts] = useState<string[]>([]);\n  const [mounted, setMounted] = useState(false);\n  const [currentPage, setCurrentPage] = useState(1);\n  const [sortField, setSortField] = useState<SortField | null>(null);\n  const [sortOrder, setSortOrder] = useState<SortOrder>(\"asc\");\n  const [showSortMenu, setShowSortMenu] = useState(false);\n  const [showFilterMenu, setShowFilterMenu] = useState(false);\n  const [showExportMenu, setShowExportMenu] = useState(false);\n  const [filterStrength, setFilterStrength] = useState<string | null>(null);\n  const [selectedContactDetail, setSelectedContactDetail] = useState<Contact | null>(null);\n  const shouldReduceMotion = useReducedMotion();\n  const { resolvedTheme } = useTheme();\n  const isDark = mounted ? resolvedTheme !== \"light\" : true;\n  const palette = getBjorkTablePalette(isDark);\n\n  const ITEMS_PER_PAGE = 10;\n\n  useEffect(() => {\n    setMounted(true);\n  }, []);\n\n  const handleContactSelect = (contactId: string) => {\n    setSelectedContacts(prev => {\n      if (prev.includes(contactId)) {\n        return prev.filter(id => id !== contactId);\n      } else {\n        return [...prev, contactId];\n      }\n    });\n    if (onContactSelect) {\n      onContactSelect(contactId);\n    }\n  };\n\n  const handleSelectAll = () => {\n    if (selectedContacts.length === paginatedContacts.length) {\n      setSelectedContacts([]);\n    } else {\n      setSelectedContacts(paginatedContacts.map(c => c.id));\n    }\n  };\n\n  const handleSort = (field: SortField) => {\n    if (sortField === field) {\n      setSortOrder(sortOrder === \"asc\" ? \"desc\" : \"asc\");\n    } else {\n      setSortField(field);\n      setSortOrder(\"asc\");\n    }\n    setShowSortMenu(false);\n    setCurrentPage(1);\n  };\n\n  const handleFilter = (strength: string | null) => {\n    setFilterStrength(strength);\n    setShowFilterMenu(false);\n    setCurrentPage(1);\n  };\n\n  const sortedAndFilteredContacts = useMemo(() => {\n    let filtered = [...initialContacts];\n\n    if (filterStrength) {\n      filtered = filtered.filter(c => c.connectionStrength === filterStrength);\n    }\n\n    if (!sortField) {\n      return filtered;\n    }\n\n    const sorted = filtered.sort((a, b) => {\n      let aVal: string | number = a[sortField];\n      let bVal: string | number = b[sortField];\n\n      if (sortField === \"connectionStrength\") {\n        const strengthMap = {\n          \"Very weak\": 0,\n          \"Weak\": 1,\n          \"Good\": 2,\n          \"Very strong\": 3\n        };\n        aVal = strengthMap[aVal as keyof typeof strengthMap];\n        bVal = strengthMap[bVal as keyof typeof strengthMap];\n      }\n\n      if (aVal < bVal) return sortOrder === \"asc\" ? -1 : 1;\n      if (aVal > bVal) return sortOrder === \"asc\" ? 1 : -1;\n      return 0;\n    });\n\n    return sorted;\n  }, [initialContacts, sortField, sortOrder, filterStrength]);\n\n  const paginatedContacts = useMemo(() => {\n    const startIdx = (currentPage - 1) * ITEMS_PER_PAGE;\n    return sortedAndFilteredContacts.slice(startIdx, startIdx + ITEMS_PER_PAGE);\n  }, [sortedAndFilteredContacts, currentPage]);\n\n  const totalPages = Math.ceil(sortedAndFilteredContacts.length / ITEMS_PER_PAGE);\n\n  const getStrengthColor = (strength: string) => {\n    if (!mounted) {\n      const strengthMap: Record<string, { bgColor: string; borderColor: string; textColor: string; dotColor: string }> = {\n        \"Very weak\": getBjorkSignalPalette(\"red\", true),\n        \"Weak\": getBjorkSignalPalette(\"orange\", true),\n        \"Good\": getBjorkSignalPalette(\"neutral\", true),\n        \"Very strong\": getBjorkSignalPalette(\"green\", true),\n      };\n      return strengthMap[strength];\n    }\n\n    const strengthMap: Record<string, { bgColor: string; borderColor: string; textColor: string; dotColor: string }> = {\n      \"Very weak\": getBjorkSignalPalette(\"red\", isDark),\n      \"Weak\": getBjorkSignalPalette(\"orange\", isDark),\n      \"Good\": getBjorkSignalPalette(\"neutral\", isDark),\n      \"Very strong\": getBjorkSignalPalette(\"green\", isDark),\n    };\n\n    return strengthMap[strength];\n  };\n\n  const exportToCSV = () => {\n    const headers = [\"Name\", \"Email\", \"Connection Strength\", \"Twitter Followers\", \"Description\"];\n    const rows = sortedAndFilteredContacts.map(contact => [\n      contact.name,\n      contact.email,\n      contact.connectionStrength,\n      contact.twitterFollowers,\n      contact.description || \"\"\n    ]);\n\n    const csvContent = [\n      headers.join(\",\"),\n      ...rows.map(row => row.map(cell => `\"${String(cell).replace(/\"/g, '\"\"')}\"`).join(\",\"))\n    ].join(\"\\n\");\n\n    const blob = new Blob([csvContent], { type: \"text/csv;charset=utf-8;\" });\n    const link = document.createElement(\"a\");\n    link.href = URL.createObjectURL(blob);\n    link.download = `contacts-${new Date().toISOString().split('T')[0]}.csv`;\n    link.click();\n  };\n\n  const exportToJSON = () => {\n    const jsonContent = JSON.stringify(sortedAndFilteredContacts, null, 2);\n    const blob = new Blob([jsonContent], { type: \"application/json;charset=utf-8;\" });\n    const link = document.createElement(\"a\");\n    link.href = URL.createObjectURL(blob);\n    link.download = `contacts-${new Date().toISOString().split('T')[0]}.json`;\n    link.click();\n  };\n\n  const shouldAnimate = enableAnimations && !shouldReduceMotion;\n\n  const containerVariants = {\n    visible: {\n      transition: {\n        staggerChildren: 0.04,\n        delayChildren: 0.1,\n      },\n    }\n  };\n\n  const rowVariants = {\n    hidden: { \n      opacity: 0, \n      y: 20,\n      scale: 0.98,\n      filter: \"blur(4px)\" \n    },\n    visible: {\n      opacity: 1,\n      y: 0,\n      scale: 1,\n      filter: \"blur(0px)\",\n      transition: {\n        type: \"spring\",\n        stiffness: 400,\n        damping: 25,\n        mass: 0.7,\n      },\n    },\n    exit: {\n      opacity: 0,\n      y: -10,\n      transition: { duration: 0.2 }\n    }\n  };\n\n  return (\n    <div className={`mx-auto w-full max-w-[1040px] ${className}`}>\n      <div className=\"mb-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n        <div className=\"flex items-center gap-2\">\n        </div>\n        \n        <div className=\"flex items-center gap-2 flex-wrap\">\n          <div className=\"relative\">\n            <button \n              onClick={() => setShowFilterMenu(!showFilterMenu)}\n              className={`flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors ${palette.control} ${filterStrength ? 'ring-2 ring-[#ec5c13]/24' : ''}`}\n            >\n              <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n                <path d=\"M2 3H14M4 8H12M6 13H10\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n              </svg>\n              Filter\n              {filterStrength && <span className={`ml-1 rounded-sm px-1.5 py-0.5 text-xs ${palette.accentBg} ${palette.accent}`}>1</span>}\n            </button>\n            \n            {showFilterMenu && (\n              <>\n                <div \n                  className=\"fixed inset-0 z-10\"\n                  onClick={() => setShowFilterMenu(false)}\n                />\n                <div className={`absolute right-0 z-20 mt-1 w-44 rounded-md border py-1 ${palette.menu}`}>\n                  <button\n                    onClick={() => handleFilter(null)}\n                    className={`w-full px-3 py-2 text-left text-sm transition-colors ${palette.menuItem} ${!filterStrength ? palette.menuActive : ''}`}\n                  >\n                    All Connections\n                  </button>\n                  <div className={`my-1 h-px border-t ${palette.divider}`} />\n                  {[\"Very strong\", \"Good\", \"Weak\", \"Very weak\"].map((strength) => (\n                    <button\n                      key={strength}\n                      onClick={() => handleFilter(strength)}\n                      className={`flex w-full items-center gap-2 px-3 py-2 text-left text-sm transition-colors ${palette.menuItem} ${filterStrength === strength ? palette.menuActive : ''}`}\n                    >\n                      {strength}\n                    </button>\n                  ))}\n                </div>\n              </>\n            )}\n          </div>\n          \n          <div className=\"relative\">\n            <button \n              onClick={() => setShowSortMenu(!showSortMenu)}\n              className={`flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors ${palette.control}`}\n            >\n              <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n                <path d=\"M3 6L6 3L9 6M6 3V13M13 10L10 13L7 10M10 13V3\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n              </svg>\n              Sort {sortField && <span className={`ml-1 rounded-sm px-1.5 py-0.5 text-xs ${palette.accentBg} ${palette.accent}`}>1</span>}\n              <ChevronDown size={14} className=\"opacity-50\" />\n            </button>\n            \n            {showSortMenu && (\n              <>\n                <div \n                  className=\"fixed inset-0 z-10\"\n                  onClick={() => setShowSortMenu(false)}\n                />\n                <div className={`absolute right-0 z-20 mt-1 w-48 rounded-md border py-1 ${palette.menu}`}>\n                  <button\n                    onClick={() => handleSort(\"name\")}\n                    className={`w-full px-3 py-2 text-left text-sm transition-colors ${palette.menuItem} ${sortField === \"name\" ? palette.menuActive : ''}`}\n                  >\n                    Name {sortField === \"name\" && `(${sortOrder === \"asc\" ? \"A-Z\" : \"Z-A\"})`}\n                  </button>\n                  <button\n                    onClick={() => handleSort(\"connectionStrength\")}\n                    className={`w-full px-3 py-2 text-left text-sm transition-colors ${palette.menuItem} ${sortField === \"connectionStrength\" ? palette.menuActive : ''}`}\n                  >\n                    Connection {sortField === \"connectionStrength\" && `(${sortOrder === \"asc\" ? \"↑\" : \"↓\"})`}\n                  </button>\n                  <button\n                    onClick={() => handleSort(\"twitterFollowers\")}\n                    className={`w-full px-3 py-2 text-left text-sm transition-colors ${palette.menuItem} ${sortField === \"twitterFollowers\" ? palette.menuActive : ''}`}\n                  >\n                    Followers {sortField === \"twitterFollowers\" && `(${sortOrder === \"asc\" ? \"↑\" : \"↓\"})`}\n                  </button>\n                </div>\n              </>\n            )}\n          </div>\n\n          <div className=\"relative\">\n            <button \n              onClick={() => setShowExportMenu(!showExportMenu)}\n              className={`flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm transition-colors ${palette.control}`}\n            >\n              <Download size={14} />\n              Export\n              <ChevronDown size={14} className=\"opacity-50\" />\n            </button>\n            \n            {showExportMenu && (\n              <>\n                <div \n                  className=\"fixed inset-0 z-10\"\n                  onClick={() => setShowExportMenu(false)}\n                />\n                <div className={`absolute right-0 z-20 mt-1 w-32 rounded-md border ${palette.menu}`}>\n                  <button\n                    onClick={() => {\n                      exportToCSV();\n                      setShowExportMenu(false);\n                    }}\n                    className={`flex w-full items-center gap-2 px-3 py-2 text-left text-sm transition-colors ${palette.menuItem}`}\n                  >\n                    CSV\n                  </button>\n                  <button\n                    onClick={() => {\n                      exportToJSON();\n                      setShowExportMenu(false);\n                    }}\n                    className={`flex w-full items-center gap-2 border-t px-3 py-2 text-left text-sm transition-colors ${palette.divider} ${palette.menuItem}`}\n                  >\n                    JSON\n                  </button>\n                </div>\n              </>\n            )}\n          </div>\n        </div>\n      </div>\n\n      <div className={`relative overflow-hidden rounded-[18px] border ${palette.container}`}>\n        <div className=\"overflow-x-auto\">\n          <div className=\"min-w-[1100px]\">\n            <div \n              className={`border-b px-3 py-3 text-left text-xs font-medium uppercase tracking-wide ${palette.header}`}\n              style={{\n                display: 'grid',\n                gridTemplateColumns: '40px 220px 160px 140px 200px 1fr 40px',\n                columnGap: '0px'\n              }}\n            >\n              <div className={`flex items-center justify-center border-r pr-3 ${palette.divider}`}>\n                <input \n                  type=\"checkbox\" \n                  className=\"w-4 h-4 rounded border-border/40 cursor-pointer\"\n                  style={mounted ? {\n                    accentColor: palette.checkboxAccent\n                  } : {}}\n                  checked={paginatedContacts.length > 0 && selectedContacts.length === paginatedContacts.length}\n                  onChange={handleSelectAll}\n                />\n              </div>\n              <div className={`flex items-center gap-1.5 border-r px-3 ${palette.divider}`}>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-40\">\n                  <circle cx=\"8\" cy=\"6\" r=\"3\" stroke=\"currentColor\" strokeWidth=\"1.5\" fill=\"none\"/>\n                  <path d=\"M3 14C3 11.5 5 10 8 10C11 10 13 11.5 13 14\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>\n                </svg>\n                <span>{title}</span>\n              </div>\n              <div className={`flex items-center gap-1.5 border-r px-3 ${palette.divider}`}>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-40\">\n                  <path d=\"M3 8L6 5L10 9L13 6\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n                </svg>\n                <span>Connection Streng...</span>\n              </div>\n              <div className={`flex items-center gap-1.5 border-r px-3 ${palette.divider}`}>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-40\">\n                  <path d=\"M2 2H4M2 8H6M2 14H8M10 2V14M14 4V14\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n                </svg>\n                <span>Twitter Follo...</span>\n              </div>\n              <div className={`flex items-center gap-1.5 border-r px-3 ${palette.divider}`}>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-40\">\n                  <rect x=\"2\" y=\"4\" width=\"12\" height=\"8\" rx=\"1\" stroke=\"currentColor\" strokeWidth=\"1.5\" fill=\"none\"/>\n                  <path d=\"M2 6L8 9L14 6\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>\n                </svg>\n                <span>Email Addresses</span>\n              </div>\n              <div className={`flex items-center gap-1.5 border-r px-3 ${palette.divider}`}>\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-40\">\n                  <path d=\"M3 3H13M3 8H13M3 13H9\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"/>\n                </svg>\n                <span>Description</span>\n              </div>\n              <div className=\"flex items-center justify-center px-3\">\n                <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-30\">\n                  <circle cx=\"8\" cy=\"8\" r=\"1\" fill=\"currentColor\"/>\n                  <circle cx=\"13\" cy=\"8\" r=\"1\" fill=\"currentColor\"/>\n                  <circle cx=\"3\" cy=\"8\" r=\"1\" fill=\"currentColor\"/>\n                </svg>\n              </div>\n            </div>\n\n            <AnimatePresence mode=\"wait\">\n              <motion.div\n                key={`page-${currentPage}`}\n                variants={shouldAnimate ? containerVariants : {}}\n                initial={shouldAnimate ? \"hidden\" : \"visible\"}\n                animate=\"visible\"\n              >\n                {paginatedContacts.map((contact) => (\n                  <motion.div key={contact.id} variants={shouldAnimate ? rowVariants : {}}>\n                    <div\n                      className={`group relative border-b px-3 py-3.5 transition-all duration-150 ${\n                        selectedContacts.includes(contact.id)\n                          ? palette.selectedRow\n                          : palette.row\n                      }`}\n                      style={{\n                        display: 'grid',\n                        gridTemplateColumns: '40px 220px 160px 140px 200px 1fr 40px',\n                        columnGap: '0px',\n                        alignItems: 'center'\n                      }}\n                    >\n                      <div className={`flex items-center justify-center border-r pr-3 ${palette.divider}`}>\n                        <input \n                          type=\"checkbox\" \n                          className=\"w-4 h-4 rounded border-border/40 cursor-pointer\"\n                          style={mounted ? {\n                            accentColor: palette.checkboxAccent\n                          } : {}}\n                          checked={selectedContacts.includes(contact.id)}\n                          onChange={() => handleContactSelect(contact.id)}\n                        />\n                      </div>\n\n                      <div className={`flex min-w-0 items-center gap-2 border-r px-3 ${palette.divider}`}>\n                        <div className={`inline-flex items-center gap-2 rounded-full px-2 py-1 ${palette.mutedSurface}`}>\n                          <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" className=\"opacity-50 flex-shrink-0\">\n                            <circle cx=\"8\" cy=\"6\" r=\"3\" stroke=\"currentColor\" strokeWidth=\"1.5\" fill=\"none\"/>\n                            <path d=\"M3 14C3 11.5 5 10 8 10C11 10 13 11.5 13 14\" stroke=\"currentColor\" strokeWidth=\"1.5\"/>\n                          </svg>\n                          <div className=\"min-w-0\">\n                            <div className={`truncate text-sm ${palette.primaryText}`}>{contact.name}</div>\n                          </div>\n                        </div>\n                      </div>\n\n                      <div className={`flex items-center border-r px-3 ${palette.divider}`}>\n                        {(() => {\n                          const { bgColor, borderColor, textColor, dotColor } = getStrengthColor(contact.connectionStrength);\n                          return (\n                            <div className={`inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium ${bgColor} ${borderColor} ${textColor}`}>\n                              {contact.connectionStrength === \"Very strong\" ? (\n                                <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n                                  <path d=\"M8 1L3 9H7L8 15L13 7H9L8 1Z\"/>\n                                </svg>\n                              ) : (\n                                <div className={`w-1.5 h-1.5 rounded-full ${dotColor}`}></div>\n                              )}\n                              {contact.connectionStrength}\n                            </div>\n                          );\n                        })()}\n                      </div>\n\n                      <div className={`flex items-center border-r px-3 ${palette.divider}`}>\n                        <span className={`text-sm ${palette.primaryText}`}>\n                          {contact.twitterFollowers.toLocaleString()}\n                        </span>\n                      </div>\n\n                      <div className={`flex min-w-0 items-center border-r px-3 ${palette.divider}`}>\n                        <a \n                          href={`mailto:${contact.email}`}\n                          className={`truncate text-sm ${palette.accent}`}\n                          onClick={(e) => e.stopPropagation()}\n                        >\n                          {contact.email}\n                        </a>\n                      </div>\n\n                      <div className={`flex min-w-0 items-center border-r px-3 ${palette.divider}`}>\n                        <span className={`truncate text-sm ${palette.secondaryText}`}>\n                          {contact.description || \"—\"}\n                        </span>\n                      </div>\n\n                      <div className=\"flex items-center justify-center px-3\">\n                        <button\n                          onClick={() => setSelectedContactDetail(contact)}\n                          className=\"opacity-0 group-hover:opacity-60 hover:opacity-100 transition-opacity cursor-pointer\"\n                        >\n                          <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n                            <circle cx=\"8\" cy=\"3\" r=\"1.5\" fill=\"currentColor\"/>\n                            <circle cx=\"8\" cy=\"8\" r=\"1.5\" fill=\"currentColor\"/>\n                            <circle cx=\"8\" cy=\"13\" r=\"1.5\" fill=\"currentColor\"/>\n                          </svg>\n                        </button>\n                      </div>\n                    </div>\n                  </motion.div>\n                ))}\n              </motion.div>\n            </AnimatePresence>\n          </div>\n        </div>\n\n        <AnimatePresence>\n          {selectedContactDetail && (\n            <motion.div\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{ opacity: 0 }}\n              transition={{ duration: 0.2 }}\n              className={`absolute inset-0 z-10 flex items-center justify-center backdrop-blur-sm ${isDark ? \"bg-[#080808]/62\" : \"bg-[#f4f2ec]/64\"}`}\n              onClick={() => setSelectedContactDetail(null)}\n            >\n              <motion.div\n                initial={{ scale: 0.8, opacity: 0, y: 20 }}\n                animate={{ scale: 1, opacity: 1, y: 0 }}\n                exit={{ scale: 0.8, opacity: 0, y: 20 }}\n                transition={{ type: \"spring\", stiffness: 300, damping: 30, mass: 0.8 }}\n                className={`relative mx-6 w-full max-w-md rounded-xl border p-6 ${palette.popover} ${palette.divider}`}\n                onClick={(e) => e.stopPropagation()}\n              >\n                <button\n                  onClick={() => setSelectedContactDetail(null)}\n                  className={`absolute right-3 top-3 flex h-6 w-6 items-center justify-center rounded-full border transition-colors ${palette.control}`}\n                >\n                  <X className={`h-3 w-3 ${palette.secondaryText}`} />\n                </button>\n\n                <div className=\"space-y-4\">\n                  <div className=\"flex items-center gap-3\">\n                    <div className={`flex h-12 w-12 items-center justify-center rounded-full ${palette.accentBg}`}>\n                      <User className={`h-6 w-6 ${palette.accent}`} />\n                    </div>\n                    <div>\n                      <h3 className={`text-lg font-semibold ${palette.primaryText}`}>\n                        {selectedContactDetail.name}\n                      </h3>\n                      {(() => {\n                        const { bgColor, borderColor, textColor, dotColor } = getStrengthColor(selectedContactDetail.connectionStrength);\n                        return (\n                          <div className={`mt-1 inline-flex items-center gap-1.5 rounded-md border px-2 py-0.5 text-xs font-medium ${bgColor} ${borderColor} ${textColor}`}>\n                            {selectedContactDetail.connectionStrength === \"Very strong\" ? (\n                              <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n                                <path d=\"M8 1L3 9H7L8 15L13 7H9L8 1Z\"/>\n                              </svg>\n                            ) : (\n                              <div className={`w-1.5 h-1.5 rounded-full ${dotColor}`}></div>\n                            )}\n                            {selectedContactDetail.connectionStrength}\n                          </div>\n                        );\n                      })()}\n                    </div>\n                  </div>\n\n                  <div className=\"space-y-3\">\n                    <div>\n                      <div className=\"flex items-center gap-1.5 mb-1\">\n                        <Mail className={`h-3.5 w-3.5 ${palette.secondaryText}`} />\n                        <span className={`text-xs uppercase tracking-wide ${palette.secondaryText}`}>Email</span>\n                      </div>\n                      <a \n                        href={`mailto:${selectedContactDetail.email}`}\n                        className={`text-sm ${palette.accent}`}\n                      >\n                        {selectedContactDetail.email}\n                      </a>\n                    </div>\n\n                    <div>\n                      <div className=\"flex items-center gap-1.5 mb-1\">\n                        <Twitter className={`h-3.5 w-3.5 ${palette.secondaryText}`} />\n                        <span className={`text-xs uppercase tracking-wide ${palette.secondaryText}`}>Twitter Followers</span>\n                      </div>\n                      <p className={`text-sm font-medium ${palette.primaryText}`}>\n                        {selectedContactDetail.twitterFollowers.toLocaleString()}\n                      </p>\n                    </div>\n\n                    {selectedContactDetail.description && (\n                      <div>\n                        <div className=\"flex items-center gap-1.5 mb-1\">\n                          <span className={`text-xs uppercase tracking-wide ${palette.secondaryText}`}>Description</span>\n                        </div>\n                        <p className={`text-sm ${palette.secondaryText}`}>\n                          {selectedContactDetail.description}\n                        </p>\n                      </div>\n                    )}\n                  </div>\n\n                  <div className={`border-t pt-3 ${palette.divider}`}>\n                    <motion.button\n                      whileHover={{ scale: 1.02 }}\n                      whileTap={{ scale: 0.98 }}\n                      className={`w-full rounded-md border px-4 py-2 text-sm font-medium transition-colors ${palette.accentBg} ${palette.accentBorder} ${palette.accent}`}\n                      onClick={() => {\n                        window.location.href = `mailto:${selectedContactDetail.email}`;\n                      }}\n                    >\n                      Send Email\n                    </motion.button>\n                  </div>\n                </div>\n              </motion.div>\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </div>\n\n      {totalPages > 1 && (\n        <div className=\"mt-4 flex items-center justify-between px-2\">\n          <div className={`text-xs ${palette.secondaryText}`}>\n            Page {currentPage} of {totalPages} • {sortedAndFilteredContacts.length} contacts\n          </div>\n          \n          <div className=\"flex gap-1.5\">\n            <button\n              onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}\n              disabled={currentPage === 1}\n              className={`rounded-md border px-3 py-1.5 text-xs transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${palette.control}`}\n            >\n              Previous\n            </button>\n            <button\n              onClick={() => setCurrentPage(prev => Math.min(totalPages, prev + 1))}\n              disabled={currentPage === totalPages}\n              className={`rounded-md border px-3 py-1.5 text-xs transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${palette.control}`}\n            >\n              Next\n            </button>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/bjork-ui/tables/contacts-table.tsx"
    },
    {
      "path": "components/bjork-ui/tables/table-theme.ts",
      "content": "export function getBjorkTablePalette(isDark: boolean) {\n  return {\n    container: isDark\n      ? \"border-[#232323] bg-[#111]\"\n      : \"border-[#ded7ca] bg-[#eee9df]\",\n    header: isDark\n      ? \"border-[#232323] bg-[#181818] text-[#ededed]/42\"\n      : \"border-[#ded7ca] bg-[#e5ded1] text-[#171717]/46\",\n    row: isDark\n      ? \"border-[#232323] hover:bg-[#181818]/70\"\n      : \"border-[#ded7ca] hover:bg-[#e7e1d5]/70\",\n    selectedRow: isDark\n      ? \"border-[#2a2a2a] bg-[#181818]\"\n      : \"border-[#d6cdbc] bg-[#e7e1d5]\",\n    control: isDark\n      ? \"border-[#232323] bg-[#181818] text-[#ededed]/70 hover:bg-[#202020]\"\n      : \"border-[#d8d3c7] bg-[#eee9df] text-[#171717]/68 hover:bg-[#e4ded3]\",\n    menu: isDark\n      ? \"border-[#232323] bg-[#181818] text-[#ededed]/76 shadow-[0_18px_60px_rgba(0,0,0,0.42)]\"\n      : \"border-[#d8d3c7] bg-[#eee9df] text-[#171717]/76 shadow-[0_18px_60px_rgba(62,52,38,0.14)]\",\n    menuItem: isDark ? \"hover:bg-[#232323]\" : \"hover:bg-[#e4ded3]\",\n    menuActive: isDark ? \"bg-[#232323]\" : \"bg-[#e4ded3]\",\n    divider: isDark ? \"border-[#232323]\" : \"border-[#d8d3c7]\",\n    primaryText: isDark ? \"text-[#ededed]/90\" : \"text-[#171717]/86\",\n    secondaryText: isDark ? \"text-[#ededed]/38\" : \"text-[#171717]/46\",\n    mutedSurface: isDark ? \"bg-[#181818]\" : \"bg-[#e7e1d5]\",\n    popover: isDark ? \"bg-[#111] text-[#ededed]\" : \"bg-[#eee9df] text-[#171717]\",\n    accent: isDark ? \"text-[#d86a2c]\" : \"text-[#bd4514]\",\n    accentBg: isDark ? \"bg-[#ec5c13]/12\" : \"bg-[#ec5c13]/14\",\n    accentBorder: isDark ? \"border-[#ec5c13]/24\" : \"border-[#bd4514]/22\",\n    checkboxAccent: isDark ? \"#d86a2c\" : \"#bd4514\",\n  };\n}\n\nexport function getBjorkSignalPalette(\n  tone: \"green\" | \"red\" | \"orange\" | \"neutral\",\n  isDark: boolean\n) {\n  const palettes = {\n    green: {\n      bgColor: isDark ? \"bg-[#3e6f52]/18\" : \"bg-[#dce8dc]\",\n      borderColor: isDark ? \"border-[#5f9f78]/28\" : \"border-[#bad0bd]\",\n      textColor: isDark ? \"text-[#77b58b]\" : \"text-[#47785c]\",\n      dotColor: isDark ? \"bg-[#77b58b]\" : \"bg-[#47785c]\",\n      color: isDark ? \"#77b58b\" : \"#47785c\",\n    },\n    red: {\n      bgColor: isDark ? \"bg-[#87463f]/18\" : \"bg-[#eadad5]\",\n      borderColor: isDark ? \"border-[#c46a61]/28\" : \"border-[#d7bcb4]\",\n      textColor: isDark ? \"text-[#cf7c72]\" : \"text-[#9d5149]\",\n      dotColor: isDark ? \"bg-[#cf7c72]\" : \"bg-[#9d5149]\",\n      color: isDark ? \"#cf7c72\" : \"#9d5149\",\n    },\n    orange: {\n      bgColor: isDark ? \"bg-[#ec5c13]/14\" : \"bg-[#ead9cb]\",\n      borderColor: isDark ? \"border-[#ec5c13]/28\" : \"border-[#d5b59f]\",\n      textColor: isDark ? \"text-[#d86a2c]\" : \"text-[#9f4317]\",\n      dotColor: isDark ? \"bg-[#d86a2c]\" : \"bg-[#9f4317]\",\n      color: isDark ? \"#d86a2c\" : \"#9f4317\",\n    },\n    neutral: {\n      bgColor: isDark ? \"bg-[#ededed]/8\" : \"bg-[#ded7ca]\",\n      borderColor: isDark ? \"border-[#ededed]/14\" : \"border-[#cfc6b7]\",\n      textColor: isDark ? \"text-[#ededed]/58\" : \"text-[#171717]/58\",\n      dotColor: isDark ? \"bg-[#ededed]/45\" : \"bg-[#171717]/42\",\n      color: isDark ? \"#a3a3a3\" : \"#706b62\",\n    },\n  } as const;\n\n  return palettes[tone];\n}\n",
      "type": "registry:component",
      "target": "@components/bjork-ui/tables/table-theme.ts"
    }
  ],
  "cssVars": {
    "light": {
      "bjork-bg": "#f7f3ea",
      "bjork-surface": "#fffcf6",
      "bjork-surface-muted": "rgba(250, 246, 237, 0.94)",
      "bjork-surface-hover": "#f5efe3",
      "bjork-surface-active": "#efe7d8",
      "bjork-panel": "#f8f2e7",
      "bjork-menu": "rgba(255, 252, 246, 0.98)",
      "bjork-field": "rgba(255, 252, 246, 0.96)",
      "bjork-field-muted": "rgba(248, 242, 231, 0.82)",
      "bjork-field-inset": "rgba(239, 231, 216, 0.72)",
      "bjork-error-bg": "#fff0e8",
      "bjork-text": "#171717",
      "bjork-text-strong": "rgba(23, 23, 23, 0.9)",
      "bjork-text-medium": "rgba(23, 23, 23, 0.72)",
      "bjork-text-muted": "rgba(23, 23, 23, 0.52)",
      "bjork-text-soft": "rgba(23, 23, 23, 0.36)",
      "bjork-text-faint": "rgba(23, 23, 23, 0.22)",
      "bjork-inverted-text": "#fff8f0",
      "bjork-border": "#eee6db",
      "bjork-border-muted": "#f5ede2",
      "bjork-border-strong": "#e1d7c8",
      "bjork-thumb": "#a49b8e",
      "bjork-track": "#ded6ca",
      "bjork-accent": "#ec7d43",
      "bjork-accent-hover": "#f0935f",
      "bjork-accent-soft": "rgba(236, 125, 67, 0.1)",
      "bjork-accent-muted": "rgba(236, 125, 67, 0.2)",
      "bjork-accent-badge": "rgba(236, 125, 67, 0.16)",
      "bjork-accent-badge-foreground": "#8d421d",
      "bjork-accent-foreground": "#3f2112",
      "bjork-shadow-surface": "inset 0 7px 14px rgba(88, 72, 49, 0.045), inset 0 0.5px 0.5px rgba(255, 255, 255, 0.92), inset 1px 0 0 rgba(88, 72, 49, 0.026), inset -1px 0 0 rgba(255, 255, 255, 0.68), 0 14px 22px -9px rgba(66, 52, 33, 0.11)",
      "bjork-shadow-soft": "inset 0 1px 0 rgba(88, 72, 49, 0.045), inset 0 0.5px 0.5px rgba(255, 255, 255, 0.86)",
      "bjork-shadow-panel": "inset 0 1px 0 rgba(88, 72, 49, 0.04), inset 1px 0 0 rgba(88, 72, 49, 0.024), inset -1px 0 0 rgba(255, 255, 255, 0.64), 0 18px 38px -30px rgba(66, 52, 33, 0.2)",
      "bjork-shadow-menu": "inset 0 1px 0 rgba(88, 72, 49, 0.04), inset 0 12px 24px rgba(88, 72, 49, 0.022), inset 1px 0 0 rgba(88, 72, 49, 0.024), inset -1px 0 0 rgba(255, 255, 255, 0.62), 0 22px 44px -26px rgba(66, 52, 33, 0.22)",
      "bjork-shadow-inset": "inset 0 1px 10px rgba(88, 72, 49, 0.12), inset 0 0.5px 0.5px rgba(255, 255, 255, 0.72)",
      "bjork-ring-offset": "#f7f3ea"
    },
    "dark": {
      "bjork-bg": "#111111",
      "bjork-surface": "#121212",
      "bjork-surface-muted": "rgba(22, 22, 22, 0.92)",
      "bjork-surface-hover": "#161616",
      "bjork-surface-active": "#202020",
      "bjork-panel": "#0d0d0d",
      "bjork-menu": "rgba(18, 18, 18, 0.98)",
      "bjork-field": "rgba(18, 18, 18, 0.95)",
      "bjork-field-muted": "rgba(18, 18, 18, 0.55)",
      "bjork-field-inset": "rgba(9, 9, 9, 0.75)",
      "bjork-error-bg": "#130d0a",
      "bjork-text": "#ededed",
      "bjork-text-strong": "rgba(237, 237, 237, 0.9)",
      "bjork-text-medium": "rgba(237, 237, 237, 0.72)",
      "bjork-text-muted": "rgba(237, 237, 237, 0.52)",
      "bjork-text-soft": "rgba(237, 237, 237, 0.36)",
      "bjork-text-faint": "rgba(237, 237, 237, 0.22)",
      "bjork-inverted-text": "#080808",
      "bjork-border": "#232323",
      "bjork-border-muted": "#1c1c1c",
      "bjork-border-strong": "#343434",
      "bjork-thumb": "#626262",
      "bjork-track": "#090909",
      "bjork-accent": "#ec5c13",
      "bjork-accent-hover": "#f07832",
      "bjork-accent-soft": "rgba(236, 92, 19, 0.12)",
      "bjork-accent-muted": "rgba(236, 92, 19, 0.24)",
      "bjork-accent-badge": "#ec5c13",
      "bjork-accent-badge-foreground": "#fff2ea",
      "bjork-accent-foreground": "#fff2ea",
      "bjork-shadow-surface": "inset 0 7px 14px rgba(255, 255, 255, 0.03), inset 0 0.5px 0.5px rgba(255, 255, 255, 0.06), 0 14px 20px -6px rgba(0, 0, 0, 0.45)",
      "bjork-shadow-soft": "inset 0 1px 0 rgba(255, 255, 255, 0.045)",
      "bjork-shadow-panel": "inset 0 1px 0 rgba(255, 255, 255, 0.035), 0 18px 36px -28px rgba(0, 0, 0, 0.9)",
      "bjork-shadow-menu": "inset 0 1px 0 rgba(255, 255, 255, 0.055), inset 0 12px 24px rgba(255, 255, 255, 0.018), inset 0 -18px 26px rgba(0, 0, 0, 0.24), 0 22px 42px -22px rgba(0, 0, 0, 0.9)",
      "bjork-shadow-inset": "inset 0 1px 10px rgba(0, 0, 0, 0.45)",
      "bjork-ring-offset": "#080808"
    }
  },
  "css": {
    ".bjork-range": {
      "box-shadow": "inset 0 1px 1px rgba(255, 255, 255, 0.04), 0 0 14px rgba(189, 69, 20, 0.06)"
    },
    ".bjork-range::-webkit-slider-thumb": {
      "appearance": "none",
      "width": "16px",
      "height": "8px",
      "border": "0",
      "border-radius": "999px",
      "background": "var(--bjork-thumb)",
      "box-shadow": "inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.42)"
    },
    ".bjork-range::-moz-range-thumb": {
      "width": "16px",
      "height": "8px",
      "border": "0",
      "border-radius": "999px",
      "background": "var(--bjork-thumb)",
      "box-shadow": "inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.42)"
    },
    ".bjork-layered-button-accent, .bjork-layered-button-raised": {
      "position": "relative",
      "isolation": "isolate",
      "appearance": "none",
      "overflow": "hidden",
      "border": "0",
      "border-radius": "13px",
      "box-shadow": "inset 0 1px 0 #ffffff38, 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a",
      "transition": "filter 150ms ease-out, box-shadow 150ms ease-out"
    },
    ".bjork-layered-button-accent::after, .bjork-layered-button-raised::after": {
      "position": "absolute",
      "inset": "0",
      "pointer-events": "none",
      "content": "\"\"",
      "border": "1.5px solid transparent",
      "border-radius": "inherit",
      "background": "linear-gradient(#ffffffb8, #0000003d 41% 75%, #ffffff47) border-box",
      "mix-blend-mode": "overlay",
      "-webkit-mask-image": "linear-gradient(#000, #000), linear-gradient(#000, #000)",
      "mask-image": "linear-gradient(#000, #000), linear-gradient(#000, #000)",
      "-webkit-mask-clip": "padding-box, border-box",
      "mask-clip": "padding-box, border-box",
      "-webkit-mask-origin": "padding-box, border-box",
      "mask-origin": "padding-box, border-box",
      "-webkit-mask-composite": "xor",
      "mask-composite": "exclude"
    },
    ".bjork-layered-button-accent": {
      "color": "oklch(100% 0 0)",
      "text-shadow": "0 -1px #00000040",
      "background": "radial-gradient(ellipse at -20px top, rgba(255, 255, 255, 0.14), transparent), linear-gradient(180deg, #ec5c13 0%, #ec5c13 62%, color-mix(in oklab, #ec5c13 84%, black 16%) 100%)"
    },
    ".bjork-layered-button-raised": {
      "color": "oklch(100% 0 0)",
      "text-shadow": "0 -1px #00000026",
      "background": "radial-gradient(ellipse at -20px top, #ffffff38, #fff0), linear-gradient(180deg, oklch(0.1881 0.006 265), oklch(0.5493 0.0081 265))"
    },
    ".dark .bjork-layered-button-raised": {
      "color": "oklch(0.2574 0.0056 265)",
      "text-shadow": "0 -1px #00000026",
      "background": "radial-gradient(ellipse at -20px top, #ffffff38, #fff0), linear-gradient(180deg, color-mix(in oklab, oklch(0.9674 0.0013 265) 80%, oklch(0.2574 0.0056 265) 20%), color-mix(in oklab, oklch(0.669 0.0107 265) 80%, oklch(0.2574 0.0056 265) 20%))"
    },
    "@media (hover: hover)": {
      ".bjork-layered-button-accent:hover": {
        "filter": "brightness(1.08) saturate(1.04)"
      },
      ".bjork-layered-button-raised:hover": {
        "filter": "brightness(1.08) contrast(0.9)"
      }
    }
  },
  "meta": {
    "collection": "Tables",
    "registryUrl": "https://ui.isaiahbjork.com/contacts-table.json",
    "installCommand": "npx shadcn@latest add https://ui.isaiahbjork.com/contacts-table.json"
  },
  "type": "registry:component"
}