/* WPSiteBeam Scanner — Plugins & Forms Tab
   Auto-split from Scanner.jsx.

   FORM PLATFORM SUPPORT MATRIX (updated May 2026 from plugin zip analysis):
   ─────────────────────────────────────────────────────────────────────────
   Platform          Key Classes / Signals                    Label Pattern
   ─────────────────────────────────────────────────────────────────────────
   gravity           gform_wrapper, gform_fields, gfield      <label for=>
   cf7               wpcf7-form, wpcf7-form-control-wrap      wrap label+br
   wpforms           wpforms-form, wpforms-field-{type}       <label for=>
   ninja             nf-form-cont, nf-field-container         separate label
   fluent            fluentform, ff-el-group, ff-el-input--*  <label for=>
   formidable        frm_form_field, frm_fields_container     <label for=>
   forminator        forminator-form, forminator-field-{type} <label for=>
   sureforms         srfm-block-wrap, srfm-input-common       <label for=>
   wsform            ws-form-wrapper, wsf-button, fl-ws-form  <label for=>
   metform           mf-form-shortcode, mf-input-wrapper      <label for=>
   calc              cff-form, cff_form_builder, data-cff-*   <label for=>
   elementor         elementor-form, elementor-field-group    aria-label
   hubspot           hbspt-form, hs-form, hs-fieldtype-*      <label for=>
   jotform           jotform class, jotformEmbedding          <label for=>
   mailchimp         mc4wp-form, mc-embedded                  <label for=>
   activecampaign    _form_submit, activehosted.com           <label for=>
   klaviyo           klaviyo-form, klaviyoForm                <label for=>
   native            plain <form> with no plugin markers      varies
   ─────────────────────────────────────────────────────────────────────────
   Brain scan note: Re-verify class patterns when any of these plugins
   release major versions (watch for: GF 3.0, CF7 7.x, WPForms 2.x).
*/
(function () {
  'use strict';
  const ScanEmptyState = window.ScanEmptyState;
  const Icon = window.Icon;

  /* Note: ScannerPagesTab (in tab-pages.jsx) defines its own internal PagesTab
     component. These are separate — ScannerPluginsFormsTab is self-contained. */

/* ── ScannerPluginsFormsTab ──────────────────────────────────────────
   Single tab consolidating three related views:
     1. Forms detected — per-form schema (action, method, fields, etc.)
                         with Gravity Forms JSON export
     2. Plugins & extensions — name + version + category + vendor URL
     3. Integrations — third-party services (CDN, analytics, mail, payment)

   Phase 1 (this commit): UI is complete. Renders empty-states until
   server-side detection lands (Phase 2). Plugin section already works
   with what server.js sends today (string[] from v1's detectSiteCounts).

   Server contract for Phase 2:
     data.forms:        [{page_url, action, method, platform, fields:[...]}]
     data.tech.plugins: [{name, slug?, version?, category?, vendor_url?,
                          description?, signals?:[]}] OR string[] (legacy)
     data.integrations: [{name, category, signal, vendor_url?, evidence?}]
*/

/* Plugin presentation catalog — enriches string-only entries from server.
   Keys are case-insensitive plugin names. Values: {category, vendor_url,
   description}. Category drives the colored badge in the table.
   Updates here are pure presentation — detection still happens server-side. */
const PLUGIN_CATALOG = {
  'woocommerce':              { category:'commerce',     vendor_url:'https://woocommerce.com',                  description:'eCommerce platform for WordPress' },
  'gravity forms':            { category:'forms',        vendor_url:'https://www.gravityforms.com',             description:'Premium form builder' },
  'wpforms':                  { category:'forms',        vendor_url:'https://wpforms.com',                      description:'Drag-and-drop form builder' },
  'contact form 7':           { category:'forms',        vendor_url:'https://contactform7.com',                 description:'Free contact form plugin' },
  'ninja forms':              { category:'forms',        vendor_url:'https://ninjaforms.com',                   description:'Drag-and-drop form builder' },
  'fluent forms':             { category:'forms',        vendor_url:'https://fluentforms.com',                  description:'Fast form builder' },
  'formidable forms':         { category:'forms',        vendor_url:'https://formidableforms.com',              description:'Form builder + view system' },
  'elementor':                { category:'builder',      vendor_url:'https://elementor.com',                    description:'Visual page builder' },
  'elementor pro':            { category:'builder',      vendor_url:'https://elementor.com/pro/',               description:'Elementor with theme builder + popup' },
  'divi':                     { category:'builder',      vendor_url:'https://www.elegantthemes.com/gallery/divi/', description:'Visual builder by Elegant Themes' },
  'beaver builder':           { category:'builder',      vendor_url:'https://www.wpbeaverbuilder.com',          description:'Drag-and-drop page builder' },
  'oxygen':                   { category:'builder',      vendor_url:'https://oxygenbuilder.com',                description:'Visual site builder for WordPress' },
  'bricks':                   { category:'builder',      vendor_url:'https://bricksbuilder.io',                 description:'Visual site builder' },
  'breakdance':               { category:'builder',      vendor_url:'https://breakdance.com',                   description:'Visual builder by Soflyy' },
  'gutenberg':                { category:'builder',      vendor_url:'https://wordpress.org/plugins/gutenberg/', description:'WordPress block editor' },
  'acf':                      { category:'fields',       vendor_url:'https://www.advancedcustomfields.com',     description:'Advanced Custom Fields' },
  'advanced custom fields':   { category:'fields',       vendor_url:'https://www.advancedcustomfields.com',     description:'Advanced Custom Fields' },
  'metabox':                  { category:'fields',       vendor_url:'https://metabox.io',                       description:'Custom field framework' },
  'pods':                     { category:'fields',       vendor_url:'https://pods.io',                          description:'Custom content types + fields' },
  'jetengine':                { category:'fields',       vendor_url:'https://crocoblock.com/plugins/jetengine/', description:'Dynamic content for Crocoblock' },
  'wpml':                     { category:'i18n',         vendor_url:'https://wpml.org',                         description:'Multilingual plugin' },
  'polylang':                 { category:'i18n',         vendor_url:'https://polylang.pro',                     description:'Multilingual plugin' },
  'translatepress':           { category:'i18n',         vendor_url:'https://translatepress.com',               description:'Translation plugin' },
  'yoast seo':                { category:'seo',          vendor_url:'https://yoast.com/wordpress/plugins/seo/', description:'SEO plugin' },
  'rank math':                { category:'seo',          vendor_url:'https://rankmath.com',                     description:'SEO plugin' },
  'all in one seo':           { category:'seo',          vendor_url:'https://aioseo.com',                       description:'SEO plugin' },
  'seopress':                 { category:'seo',          vendor_url:'https://www.seopress.org',                 description:'SEO plugin' },
  'the events calendar':      { category:'events',       vendor_url:'https://theeventscalendar.com',            description:'Events Calendar by StellarWP' },
  'events calendar pro':      { category:'events',       vendor_url:'https://theeventscalendar.com/products/wordpress-events-calendar/', description:'Events Calendar Pro' },
  'modern events calendar':   { category:'events',       vendor_url:'https://webnus.net/modern-events-calendar/', description:'Modern Events Calendar' },
  'events manager':           { category:'events',       vendor_url:'https://wp-events-plugin.com',             description:'Events Manager' },
  'eventon':                  { category:'events',       vendor_url:'https://www.myeventon.com',                description:'EventOn calendar' },
  'buddyboss':                { category:'community',    vendor_url:'https://www.buddyboss.com',                description:'Community + LMS platform' },
  'buddypress':               { category:'community',    vendor_url:'https://buddypress.org',                   description:'Community plugin' },
  'learndash':                { category:'lms',          vendor_url:'https://www.learndash.com',                description:'LMS for WordPress' },
  'lifterlms':                { category:'lms',          vendor_url:'https://lifterlms.com',                    description:'LMS for WordPress' },
  'tutor lms':                { category:'lms',          vendor_url:'https://www.themeum.com/product/tutor-lms/', description:'LMS for WordPress' },
  'memberpress':              { category:'membership',   vendor_url:'https://memberpress.com',                  description:'Membership plugin' },
  'paid memberships pro':     { category:'membership',   vendor_url:'https://www.paidmembershipspro.com',       description:'Membership plugin' },
  'restrict content pro':     { category:'membership',   vendor_url:'https://restrictcontentpro.com',           description:'Membership plugin' },
  'gravityview':              { category:'fields',       vendor_url:'https://www.gravitykit.com',               description:'Display Gravity Forms entries' },
  'barn2 document library':   { category:'content',      vendor_url:'https://barn2.com/wordpress-plugins/document-library-pro/', description:'Document library plugin' },
  'wp rocket':                { category:'performance',  vendor_url:'https://wp-rocket.me',                     description:'Caching plugin' },
  'w3 total cache':           { category:'performance',  vendor_url:'https://www.boldgrid.com/w3-total-cache/', description:'Caching plugin' },
  'wpsuper cache':            { category:'performance',  vendor_url:'https://en-ca.wordpress.org/plugins/wp-super-cache/', description:'Caching plugin' },
  'litespeed cache':          { category:'performance',  vendor_url:'https://wordpress.org/plugins/litespeed-cache/', description:'LiteSpeed caching' },
  'autoptimize':              { category:'performance',  vendor_url:'https://wordpress.org/plugins/autoptimize/', description:'Asset optimizer' },
  'wordfence':                { category:'security',     vendor_url:'https://www.wordfence.com',                description:'Security + firewall' },
  'sucuri':                   { category:'security',     vendor_url:'https://sucuri.net',                       description:'Security platform' },
  'updraftplus':              { category:'backup',       vendor_url:'https://updraftplus.com',                  description:'Backup + restore' },
  'mailchimp for wp':         { category:'mail',         vendor_url:'https://www.mc4wp.com',                    description:'Mailchimp integration' },
  'mailpoet':                 { category:'mail',         vendor_url:'https://www.mailpoet.com',                 description:'Newsletter plugin' },
  'easy digital downloads':   { category:'commerce',     vendor_url:'https://easydigitaldownloads.com',         description:'Sell digital products' },
};

/* PLUGIN_SLUG_CATALOG — keyed by WP.org slug (what the server sends).
   Entries here override PLUGIN_CATALOG name lookups for slug-identified plugins.
   Categories: forms, builder, seo, security, performance, backup, commerce,
   i18n, events, fields, community, lms, membership, mail, accessibility,
   legal, media, social, maps, analytics, cache, cdn, crm, chat, other */
const PLUGIN_SLUG_CATALOG = {
  /* ── Page Builders & Themes ── */
  'elementor':                  { category:'builder',      vendor_url:'https://elementor.com',                      description:'Visual page builder' },
  'elementor-pro':              { category:'builder',      vendor_url:'https://elementor.com/pro/',                 description:'Elementor with theme builder & popup' },
  'divi':                       { category:'builder',      vendor_url:'https://elegantthemes.com/gallery/divi/',    description:'Visual builder by Elegant Themes' },
  'beaver-builder':             { category:'builder',      vendor_url:'https://wpbeaverbuilder.com',                description:'Drag-and-drop page builder' },
  'bricks':                     { category:'builder',      vendor_url:'https://bricksbuilder.io',                   description:'Visual site builder' },
  'breakdance':                 { category:'builder',      vendor_url:'https://breakdance.com',                     description:'Visual builder by Soflyy' },
  'oxygen':                     { category:'builder',      vendor_url:'https://oxygenbuilder.com',                  description:'Low-code visual builder' },
  'brizy':                      { category:'builder',      vendor_url:'https://brizy.io',                           description:'Website builder' },
  'thrive-architect':           { category:'builder',      vendor_url:'https://thrivethemes.com',                   description:'Conversion-focused page builder' },
  'wp-page-builder':            { category:'builder',      vendor_url:'https://wordpress.org/plugins/wp-page-builder/', description:'Page builder' },
  /* ── Elementor Add-ons ── */
  'bdthemes-element-pack':      { category:'builder-addon', vendor_url:'https://bdthemes.com/element-pack/',        description:'Elementor add-on with 150+ widgets' },
  'essential-addons-for-elementor-lite': { category:'builder-addon', vendor_url:'https://essential-addons.com',    description:'Essential Addons for Elementor' },
  'premium-addons-for-elementor': { category:'builder-addon', vendor_url:'https://premiumaddons.com',              description:'Premium Addons for Elementor' },
  'happy-elementor-addons':     { category:'builder-addon', vendor_url:'https://happyaddons.com',                  description:'Happy Addons for Elementor' },
  'jet-elements':               { category:'builder-addon', vendor_url:'https://crocoblock.com',                   description:'JetElements by Crocoblock' },
  'jet-engine':                 { category:'builder-addon', vendor_url:'https://crocoblock.com',                   description:'JetEngine dynamic content' },
  'ultimate-addons-for-elementor': { category:'builder-addon', vendor_url:'https://wpvibes.com',                   description:'Ultimate Addons for Elementor' },
  'ht-mega-for-elementor':      { category:'builder-addon', vendor_url:'https://htmega.com',                       description:'HT Mega Addons for Elementor' },
  'anywhere-elementor':         { category:'builder-addon', vendor_url:'https://wpvibes.com',                      description:'Anywhere Elementor' },
  'powerpack-for-elementor':    { category:'builder-addon', vendor_url:'https://powerpackelements.com',            description:'PowerPack for Elementor' },
  /* ── Forms ── */
  'gravityforms':               { category:'forms',        vendor_url:'https://gravityforms.com',                   description:'Premium form builder' },
  'contact-form-7':             { category:'forms',        vendor_url:'https://contactform7.com',                   description:'Free contact form plugin' },
  'wpforms-lite':               { category:'forms',        vendor_url:'https://wpforms.com',                        description:'Drag-and-drop form builder' },
  'wpforms':                    { category:'forms',        vendor_url:'https://wpforms.com',                        description:'WPForms Pro' },
  'ninja-forms':                { category:'forms',        vendor_url:'https://ninjaforms.com',                     description:'Drag-and-drop form builder' },
  'fluentform':                 { category:'forms',        vendor_url:'https://fluentforms.com',                    description:'Fast drag-and-drop form builder' },
  'formidable':                 { category:'forms',        vendor_url:'https://formidableforms.com',                description:'Form builder + view system' },
  'forminator':                 { category:'forms',        vendor_url:'https://wpmudev.com/project/forminator-pro/', description:'Forminator form builder (WPMU Dev)' },
  'sureforms':                  { category:'forms',        vendor_url:'https://sureforms.com',                      description:'SureForms — no-code form builder' },
  'ws-form':                    { category:'forms',        vendor_url:'https://wsform.com',                         description:'WS Form — advanced form builder' },
  'metform':                    { category:'forms',        vendor_url:'https://metform.info',                       description:'MetForm — Elementor form builder' },
  'calculated-fields-form':     { category:'forms',        vendor_url:'https://codepeople.net',                     description:'Calculated Fields Form' },
  'happyforms':                 { category:'forms',        vendor_url:'https://happyforms.me',                      description:'HappyForms form builder' },
  'mailchimp-for-wp':           { category:'forms',        vendor_url:'https://mc4wp.com',                          description:'Mailchimp for WordPress' },
  'weforms':                    { category:'forms',        vendor_url:'https://weForms.com',                        description:'weForms — frontend form builder' },
  /* ── SEO ── */
  'wordpress-seo':              { category:'seo',          vendor_url:'https://yoast.com',                          description:'Yoast SEO' },
  'rank-math':                  { category:'seo',          vendor_url:'https://rankmath.com',                       description:'Rank Math SEO' },
  'all-in-one-seo-pack':        { category:'seo',          vendor_url:'https://aioseo.com',                         description:'All in One SEO' },
  'seopress':                   { category:'seo',          vendor_url:'https://seopress.org',                       description:'SEOPress' },
  'the-seo-framework':          { category:'seo',          vendor_url:'https://theseoframework.com',                description:'The SEO Framework' },
  'squirrly-seo':               { category:'seo',          vendor_url:'https://squirrly.co',                        description:'Squirrly SEO' },
  'broken-link-checker':        { category:'seo',          vendor_url:'https://wordpress.org/plugins/broken-link-checker/', description:'Broken Link Checker' },
  'redirection':                { category:'seo',          vendor_url:'https://redirection.me',                     description:'Redirection manager' },
  '301-redirects':              { category:'seo',          vendor_url:'https://wordpress.org/plugins/eps-301-redirects/', description:'301 Redirects' },
  /* ── Security ── */
  'wordfence':                  { category:'security',     vendor_url:'https://wordfence.com',                      description:'Wordfence Security' },
  'wordfence-login-security':   { category:'security',     vendor_url:'https://wordfence.com',                      description:'Wordfence Login Security' },
  'sucuri-scanner':             { category:'security',     vendor_url:'https://sucuri.net',                         description:'Sucuri Security' },
  'defender-security':          { category:'security',     vendor_url:'https://wpmudev.com',                        description:'Defender Security (WPMU Dev)' },
  'ithemes-security':           { category:'security',     vendor_url:'https://ithemes.com/security/',              description:'iThemes Security' },
  'all-in-one-wp-security-and-firewall': { category:'security', vendor_url:'https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/', description:'All-In-One WP Security' },
  'wps-hide-login':             { category:'security',     vendor_url:'https://wordpress.org/plugins/wps-hide-login/', description:'WPS Hide Login' },
  'limit-login-attempts-reloaded': { category:'security', vendor_url:'https://wordpress.org/plugins/limit-login-attempts-reloaded/', description:'Limit Login Attempts' },
  'loginizer':                  { category:'security',     vendor_url:'https://loginizer.com',                      description:'Loginizer' },
  'http-headers':               { category:'security',     vendor_url:'https://wordpress.org/plugins/http-headers/', description:'HTTP Headers manager' },
  /* ── Performance & Cache ── */
  'wp-rocket':                  { category:'performance',  vendor_url:'https://wp-rocket.me',                       description:'WP Rocket caching' },
  'w3-total-cache':             { category:'performance',  vendor_url:'https://wordpress.org/plugins/w3-total-cache/', description:'W3 Total Cache' },
  'wp-super-cache':             { category:'performance',  vendor_url:'https://wordpress.org/plugins/wp-super-cache/', description:'WP Super Cache' },
  'litespeed-cache':            { category:'performance',  vendor_url:'https://wordpress.org/plugins/litespeed-cache/', description:'LiteSpeed Cache' },
  'hummingbird-performance':    { category:'performance',  vendor_url:'https://wpmudev.com',                        description:'Hummingbird (WPMU Dev)' },
  'autoptimize':                { category:'performance',  vendor_url:'https://wordpress.org/plugins/autoptimize/', description:'Autoptimize — asset optimizer' },
  'flying-pages':               { category:'performance',  vendor_url:'https://wordpress.org/plugins/flying-pages/', description:'Flying Pages prefetcher' },
  'sg-optimizer':               { category:'performance',  vendor_url:'https://wordpress.org/plugins/sg-cachepress/', description:'SG Optimizer (SiteGround)' },
  'wp-optimize':                { category:'performance',  vendor_url:'https://wordpress.org/plugins/wp-optimize/', description:'WP-Optimize cache + cleanup' },
  'smush':                      { category:'performance',  vendor_url:'https://wpmudev.com',                        description:'Smush image optimizer (WPMU Dev)' },
  'ewww-image-optimizer':       { category:'performance',  vendor_url:'https://ewww.io',                            description:'EWWW Image Optimizer' },
  /* ── Backup ── */
  'updraftplus':                { category:'backup',       vendor_url:'https://updraftplus.com',                    description:'UpdraftPlus backup' },
  'all-in-one-wp-migration':    { category:'backup',       vendor_url:'https://servmask.com',                       description:'All-in-One WP Migration' },
  'duplicator':                 { category:'backup',       vendor_url:'https://duplicator.com',                     description:'Duplicator backup + migration' },
  'backwpup':                   { category:'backup',       vendor_url:'https://backwpup.com',                       description:'BackWPup backup' },
  'snapshot-backups':           { category:'backup',       vendor_url:'https://wpmudev.com',                        description:'Snapshot Backups (WPMU Dev)' },
  /* ── eCommerce ── */
  'woocommerce':                { category:'commerce',     vendor_url:'https://woocommerce.com',                    description:'WooCommerce eCommerce' },
  'easy-digital-downloads':     { category:'commerce',     vendor_url:'https://easydigitaldownloads.com',           description:'Easy Digital Downloads' },
  'surecart':                   { category:'commerce',     vendor_url:'https://surecart.com',                       description:'SureCart — modern cart' },
  'give':                       { category:'commerce',     vendor_url:'https://givewp.com',                         description:'GiveWP — donation plugin' },
  /* ── Accessibility ── */
  'pojo-accessibility':         { category:'accessibility', vendor_url:'https://pojo.me',                           description:'Pojo Accessibility (free WCAg toolbar)' },
  'wp-accessibility-helper':    { category:'accessibility', vendor_url:'https://wordpress.org/plugins/wp-accessibility-helper/', description:'WP Accessibility Helper' },
  'one-click-accessibility':    { category:'accessibility', vendor_url:'https://wordpress.org/plugins/pojo-accessibility/', description:'One Click Accessibility' },
  'accessible-poetry':          { category:'accessibility', vendor_url:'https://wordpress.org/plugins/accessible-poetry/', description:'Accessible Poetry' },
  'wp-ada-compliance-check-basic': { category:'accessibility', vendor_url:'https://wordpress.org/plugins/wp-ada-compliance-check-basic/', description:'WP ADA Compliance Check' },
  /* ── Legal / Cookies / Privacy ── */
  'termageddon-usercentrics':   { category:'legal',        vendor_url:'https://termageddon.com',                    description:'Termageddon + Usercentrics policy & cookie consent' },
  'complianz':                  { category:'legal',        vendor_url:'https://complianz.io',                       description:'Complianz GDPR/CCPA cookie consent' },
  'complianz-gdpr':             { category:'legal',        vendor_url:'https://complianz.io',                       description:'Complianz GDPR cookie consent' },
  'cookie-notice':              { category:'legal',        vendor_url:'https://wordpress.org/plugins/cookie-notice/', description:'Cookie Notice & Compliance' },
  'gdpr-cookie-compliance':     { category:'legal',        vendor_url:'https://wordpress.org/plugins/gdpr-cookie-compliance/', description:'GDPR Cookie Compliance' },
  'cookie-law-info':            { category:'legal',        vendor_url:'https://wordpress.org/plugins/cookie-law-info/', description:'GDPR Cookie Consent' },
  'uk-cookie-consent':          { category:'legal',        vendor_url:'https://wordpress.org/plugins/uk-cookie-consent/', description:'UK Cookie Consent' },
  /* ── Translation / i18n ── */
  'gtranslate':                 { category:'i18n',         vendor_url:'https://gtranslate.io',                      description:'GTranslate — Google Translate integration' },
  'wpml':                       { category:'i18n',         vendor_url:'https://wpml.org',                           description:'WPML multilingual plugin' },
  'polylang':                   { category:'i18n',         vendor_url:'https://polylang.pro',                       description:'Polylang multilingual' },
  'translatepress-multilingual': { category:'i18n',        vendor_url:'https://translatepress.com',                 description:'TranslatePress' },
  'loco-translate':             { category:'i18n',         vendor_url:'https://wordpress.org/plugins/loco-translate/', description:'Loco Translate' },
  /* ── Media ── */
  'media-library-assistant':    { category:'media',        vendor_url:'https://wordpress.org/plugins/media-library-assistant/', description:'Media Library Assistant' },
  'real-media-library-lite':    { category:'media',        vendor_url:'https://wordpress.org/plugins/real-media-library-lite/', description:'Real Media Library' },
  'image-optimization-by-imagify': { category:'media',    vendor_url:'https://imagify.io',                          description:'Imagify image optimizer' },
  'shortpixel-image-optimiser': { category:'media',        vendor_url:'https://shortpixel.com',                     description:'ShortPixel image optimizer' },
  'tinypng-compress-images':    { category:'media',        vendor_url:'https://tinypng.com',                        description:'TinyPNG compression' },
  /* ── Social & Sharing ── */
  'social-warfare':             { category:'social',       vendor_url:'https://warfareplugins.com',                 description:'Social Warfare sharing' },
  'shared-counts':              { category:'social',       vendor_url:'https://wordpress.org/plugins/shared-counts/', description:'Shared Counts social sharing' },
  'addtoany':                   { category:'social',       vendor_url:'https://addtoany.com',                       description:'AddToAny share buttons' },
  'jetpack':                    { category:'social',       vendor_url:'https://jetpack.com',                        description:'Jetpack by WordPress.com' },
  /* ── Analytics ── */
  'google-site-kit':            { category:'analytics',    vendor_url:'https://sitekit.withgoogle.com',             description:'Google Site Kit' },
  'insert-headers-and-footers': { category:'analytics',    vendor_url:'https://wordpress.org/plugins/insert-headers-and-footers/', description:'Insert Headers & Footers (for scripts)' },
  'wp-statistics':              { category:'analytics',    vendor_url:'https://wordpress.org/plugins/wp-statistics/', description:'WP Statistics' },
  'monsterinsights':            { category:'analytics',    vendor_url:'https://monsterinsights.com',                description:'MonsterInsights Google Analytics' },
  'exactmetrics':               { category:'analytics',    vendor_url:'https://exactmetrics.com',                   description:'ExactMetrics Google Analytics' },
  /* ── Custom Fields & CPTs ── */
  'advanced-custom-fields':     { category:'fields',       vendor_url:'https://advancedcustomfields.com',           description:'ACF — Advanced Custom Fields' },
  'pods':                       { category:'fields',       vendor_url:'https://pods.io',                            description:'Pods — custom content types' },
  /* ── Utilities ── */
  'classic-editor':             { category:'utility',      vendor_url:'https://wordpress.org/plugins/classic-editor/', description:'Classic Editor (restores TinyMCE)' },
  'classic-widgets':            { category:'utility',      vendor_url:'https://wordpress.org/plugins/classic-widgets/', description:'Classic Widgets' },
  'wp-mail-smtp':               { category:'mail',         vendor_url:'https://wpmailsmtp.com',                     description:'WP Mail SMTP' },
  'easy-wp-smtp':               { category:'mail',         vendor_url:'https://wordpress.org/plugins/easy-wp-smtp/', description:'Easy WP SMTP' },
  'newsletter':                 { category:'mail',         vendor_url:'https://wordpress.org/plugins/newsletter/',  description:'Newsletter plugin' },
  'mailpoet':                   { category:'mail',         vendor_url:'https://mailpoet.com',                       description:'MailPoet newsletter' },
  /* ── Maps ── */
  'wp-google-maps':             { category:'maps',         vendor_url:'https://wordpress.org/plugins/wp-google-maps/', description:'WP Google Maps' },
  'google-maps-widget':         { category:'maps',         vendor_url:'https://wordpress.org/plugins/google-maps-widget/', description:'Google Maps Widget' },
  'mappress-google-maps-for-wordpress': { category:'maps', vendor_url:'https://mappresspro.com',                    description:'MapPress Maps' },
  /* ── Reviews & Ratings ── */
  'wp-reviews-plugin-for-google': { category:'reviews',   vendor_url:'https://richplugins.com',                    description:'Google Reviews plugin' },
  /* ── Chat & Support ── */
  'tawkto-live-chat':           { category:'chat',         vendor_url:'https://tawk.to',                            description:'Tawk.to live chat' },
  'tidio-live-chat':            { category:'chat',         vendor_url:'https://tidio.com',                          description:'Tidio live chat' },
  /* ── Sliders & Galleries ── */
  'revslider':                  { category:'media',        vendor_url:'https://revolution.themepunch.com',           description:'Slider Revolution' },
  'smart-slider-3':             { category:'media',        vendor_url:'https://smartslider3.com',                   description:'Smart Slider 3' },
  'nextgen-gallery':            { category:'media',        vendor_url:'https://wordpress.org/plugins/nextgen-gallery/', description:'NextGEN Gallery' },
  'envira-gallery-lite':        { category:'media',        vendor_url:'https://enviragallery.com',                  description:'Envira Gallery' },
};

/* Add category styles for new categories */
const EXTRA_CATEGORY_STYLES = {
  'builder-addon': { bg:'rgba(236, 72, 153, 0.08)', fg:'#f9a8d4', border:'rgba(236, 72, 153, 0.2)' },
  'accessibility': { bg:'rgba(16, 185, 129, 0.12)', fg:'#6ee7b7', border:'rgba(16, 185, 129, 0.3)' },
  'legal':         { bg:'rgba(245, 158, 11, 0.10)', fg:'var(--warn)', border:'rgba(245, 158, 11, 0.25)'},
  'analytics':     { bg:'rgba(99, 102, 241, 0.12)', fg:'#a5b4fc', border:'rgba(99, 102, 241, 0.3)' },
  'social':        { bg:'rgba(59, 130, 246, 0.10)', fg:'#bfdbfe', border:'rgba(59, 130, 246, 0.25)'},
  'media':         { bg:'rgba(168, 85, 247, 0.10)', fg:'#d8b4fe', border:'rgba(168, 85, 247, 0.25)'},
  'maps':          { bg:'rgba(20, 184, 166, 0.10)', fg:'#99f6e4', border:'rgba(20, 184, 166, 0.25)'},
  'reviews':       { bg:'rgba(251, 191, 36, 0.10)', fg:'var(--warn)', border:'rgba(251, 191, 36, 0.25)'},
  'chat':          { bg:'rgba(16, 185, 129, 0.10)', fg:'#a7f3d0', border:'rgba(16, 185, 129, 0.25)'},
  'utility':       { bg:'rgba(100, 116, 139, 0.10)',fg:'#e2e8f0', border:'rgba(100, 116, 139, 0.25)'},
};

/* Map normalized plugin name → catalog entry. Returns null on miss. */
function lookupPluginMeta(nameOrSlug) {
  if (!nameOrSlug) return null;
  const key = String(nameOrSlug).toLowerCase().trim();
  /* Slug lookup first (more specific) */
  if (PLUGIN_SLUG_CATALOG[key]) return PLUGIN_SLUG_CATALOG[key];
  /* Name lookup fallback */
  return PLUGIN_CATALOG[key] || null;
}
function lookupPluginMeta(name) {
  if (!name) return null;
  const key = String(name).toLowerCase().trim();
  return PLUGIN_CATALOG[key] || null;
}

/* Normalize a plugin entry from server (string OR object) to a unified
   shape the table renders. Objects from server take precedence; the
   catalog only fills in gaps. */
function normalizePluginEntry(p) {
  if (typeof p === 'string') {
    const meta = lookupPluginMeta(p);
    return {
      name: p,
      slug: null,
      version: null,
      category: meta?.category || 'other',
      vendor_url: meta?.vendor_url || null,
      description: meta?.description || null,
    };
  }
  // Object form (post Phase 2 server work)
  const fallback = lookupPluginMeta(p.slug) || lookupPluginMeta(p.name) || {};
  /* If we don't have a vendor_url from the plugin's known metadata, fall
     back to constructing the wordpress.org/plugins/{slug}/ URL. This is
     correct for any plugin in the WP.org directory (~95% of free plugins).
     For premium-only plugins (Gravity Forms, ACF Pro, etc.), this URL
     redirects to a "not found" page on WP.org — but most premium vendors
     ALSO have a free version listed there with the same slug, and our
     known-meta lookup above usually catches the premium ones with proper
     vendor_url anyway. So in practice the fallback is right or harmless. */
  const slug = p.slug || null;
  let vendor_url = p.vendor_url || fallback.vendor_url || null;
  if (!vendor_url && slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) {
    vendor_url = `https://wordpress.org/plugins/${slug}/`;
  }
  return {
    name: p.name || p.slug || 'Unknown',
    slug,
    version: p.version || null,
    category: p.category || fallback.category || 'other',
    vendor_url,
    description: p.description || fallback.description || null,
    signals: p.signals || [],
  };
}

/* Plugin category → badge color/style. Soft pastel-on-dark to match
   the rest of the UI's tag system without adding new CSS classes. */
const PLUGIN_CATEGORY_STYLE = {
  commerce:    { bg:'rgba(168, 85, 247, 0.12)', fg:'var(--purple)', border:'rgba(168, 85, 247, 0.3)' },
  forms:       { bg:'rgba(6, 182, 212, 0.12)',  fg:'#67e8f9', border:'rgba(6, 182, 212, 0.3)'  },
  builder:     { bg:'rgba(236, 72, 153, 0.12)', fg:'#f9a8d4', border:'rgba(236, 72, 153, 0.3)' },
  fields:      { bg:'rgba(34, 197, 94, 0.12)',  fg:'#86efac', border:'rgba(34, 197, 94, 0.3)'  },
  i18n:        { bg:'rgba(251, 191, 36, 0.12)', fg:'var(--warn)', border:'rgba(251, 191, 36, 0.3)' },
  seo:         { bg:'rgba(59, 130, 246, 0.12)', fg:'#93c5fd', border:'rgba(59, 130, 246, 0.3)' },
  events:      { bg:'rgba(239, 68, 68, 0.12)',  fg:'var(--red)', border:'rgba(239, 68, 68, 0.3)'  },
  community:   { bg:'rgba(217, 70, 239, 0.12)', fg:'#f0abfc', border:'rgba(217, 70, 239, 0.3)' },
  lms:         { bg:'rgba(14, 165, 233, 0.12)', fg:'#7dd3fc', border:'rgba(14, 165, 233, 0.3)' },
  membership:  { bg:'rgba(139, 92, 246, 0.12)', fg:'var(--purple)', border:'rgba(139, 92, 246, 0.3)' },
  performance: { bg:'rgba(132, 204, 22, 0.12)', fg:'#bef264', border:'rgba(132, 204, 22, 0.3)' },
  security:    { bg:'rgba(220, 38, 38, 0.12)',  fg:'var(--red)', border:'rgba(220, 38, 38, 0.3)'  },
  backup:      { bg:'rgba(20, 184, 166, 0.12)', fg:'#5eead4', border:'rgba(20, 184, 166, 0.3)' },
  mail:        { bg:'rgba(245, 158, 11, 0.12)', fg:'var(--warn)', border:'rgba(245, 158, 11, 0.3)' },
  content:     { bg:'rgba(100, 116, 139, 0.12)',fg:'var(--muted)', border:'rgba(100, 116, 139, 0.3)'},
  other:       { bg:'rgba(100, 116, 139, 0.12)',fg:'var(--muted)', border:'rgba(100, 116, 139, 0.3)'},
  ...EXTRA_CATEGORY_STYLES,
};

/* Integration (3rd-party services) category color map */
const INT_CATEGORY_STYLE = {
  'analytics':     { bg:'rgba(99,102,241,.15)',  fg:'#a5b4fc', border:'rgba(99,102,241,.35)' },
  'cdn':           { bg:'rgba(14,165,233,.15)',   fg:'#7dd3fc', border:'rgba(14,165,233,.35)' },
  'crm':           { bg:'rgba(168,85,247,.15)',   fg:'#d8b4fe', border:'rgba(168,85,247,.35)' },
  'chat':          { bg:'var(--green-dim)',   fg:'#6ee7b7', border:'var(--green-dim)' },
  'forms':         { bg:'var(--beam-dim)',    fg:'#67e8f9', border:'var(--beam-dim)'  },
  'mail':          { bg:'var(--warn-dim)',   fg:'var(--warn)', border:'var(--warn-dim)' },
  'payment':       { bg:'rgba(132,204,22,.15)',   fg:'#bef264', border:'rgba(132,204,22,.35)' },
  'healthcare':    { bg:'var(--red-dim)',    fg:'var(--red)', border:'var(--red-dim)'  },
  'scheduling':    { bg:'var(--warn-dim)',   fg:'var(--warn)', border:'var(--warn-dim)' },
  'accessibility': { bg:'var(--green-dim)',   fg:'#a7f3d0', border:'var(--green-dim)' },
  'reviews':       { bg:'var(--warn-dim)',   fg:'var(--warn)', border:'var(--warn-dim)'  },
  'media':         { bg:'rgba(168,85,247,.12)',   fg:'var(--purple)', border:'rgba(168,85,247,.3)'  },
  'social':        { bg:'rgba(59,130,246,.15)',   fg:'#93c5fd', border:'rgba(59,130,246,.35)' },
  'maps':          { bg:'rgba(20,184,166,.15)',   fg:'#5eead4', border:'rgba(20,184,166,.35)' },
  'legal':         { bg:'var(--warn-dim)',   fg:'#fed7aa', border:'var(--warn-dim)'  },
  'external-link': { bg:'rgba(100,116,139,.12)',  fg:'var(--dim)', border:'rgba(100,116,139,.3)' },
  'other':         { bg:'rgba(100,116,139,.12)',  fg:'var(--dim)', border:'rgba(100,116,139,.3)' },
};

function getIntCategoryStyle(cat) {
  return INT_CATEGORY_STYLE[cat] || INT_CATEGORY_STYLE['other'];
}

/* Build a Gravity Forms JSON payload from a normalized form entry.
   Returns a single-form GF export ready to drop into "Forms → Import".
   Reference: Gravity Forms 2.5+ export schema (well-documented public format).
   Each field gets: id, type, label, isRequired, choices (for select/radio),
   placeholder, defaultValue. Anything we don't have stays at GF defaults. */
function buildGravityFormsJson(form, idx) {
  const GF_TYPE_MAP = {
    'text':     'text',
    'email':    'email',
    'tel':      'phone',
    'phone':    'phone',
    'number':   'number',
    'url':      'website',
    'textarea': 'textarea',
    'select':   'select',
    'checkbox': 'checkbox',
    'radio':    'radio',
    'file':     'fileupload',
    'date':     'date',
    'time':     'time',
    'hidden':   'hidden',
    'password': 'password',
  };
  const fields = (form.fields || []).map((f, i) => {
    const gfType = GF_TYPE_MAP[f.type?.toLowerCase()] || 'text';
    const out = {
      id: i + 1,
      type: gfType,
      label: f.label || f.name || `Field ${i + 1}`,
      isRequired: !!f.required,
      placeholder: f.placeholder || '',
    };
    if (f.options && (gfType === 'select' || gfType === 'checkbox' || gfType === 'radio')) {
      out.choices = f.options.map(opt => ({
        text: opt, value: opt, isSelected: false,
      }));
    }
    return out;
  });
  return {
    "0": {
      title: `Imported form ${idx + 1}`,
      description: form.page_url ? `Imported from ${form.page_url}` : '',
      labelPlacement: 'top_label',
      descriptionPlacement: 'below',
      button: { type: 'text', text: 'Submit' },
      fields,
      version: '2.7.0',
      id: idx + 1,
      date_created: new Date().toISOString(),
      is_active: '1',
      is_trash: '0',
    },
    "version": "2.7.0",
  };
}

function ScannerPluginsFormsTab({ data }) {
  const { useState } = React;

  /* Hooks unconditionally before any early returns (Rules of Hooks).
     selectedForm: which form's detail panel is open (null = list-only) */
  const [selectedForm, setSelectedForm] = useState(0);

  if (!data || !data.site) {
    return <ScanEmptyState tab="plugins & forms" reason="Run a scan first to see detected plugins, forms, and integrations." />;
  }

  const forms = Array.isArray(data.forms) ? data.forms : [];
  const rawPlugins = Array.isArray(data.tech?.plugins) ? data.tech.plugins : [];
  const plugins = rawPlugins.map(normalizePluginEntry);
  const integrations = Array.isArray(data.integrations) ? data.integrations : [];

  /* Aggregate counts for header badges */
  const formCount = forms.length;
  const pluginCount = plugins.length;
  const integrationCount = integrations.length;

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      {/* ─ FORMS SECTION ───────────────────────────────────────── */}
      <div className="card">
        <div className="card-head">
          <h2 className="card-title">Forms detected</h2>
          {formCount > 0 && <span className="tag">{formCount}</span>}
        </div>
        <div className="card-body" style={{ padding: 0 }}>
          {formCount === 0 ? (
            <ScanEmptyState
              bare
              tab="forms"
              reason="No forms were detected on the pages scanned. If this site has Gravity Forms, Contact Form 7, WPForms, or similar — try a Full or Deep scan so more pages are checked. Forms only appear in results for pages the scanner actually fetched."
            />
          ) : (
            <div>
              {/* Forms list — selectable rows, table layout */}
              <table className="table">
                <thead>
                  <tr>
                    <th scope="col" style={{ width:40 }}></th>
                    <th scope="col">Page</th>
                    <th scope="col" style={{ width:110 }}>Platform</th>
                    <th scope="col" style={{ width:80 }}>Method</th>
                    <th scope="col" style={{ width:80, textAlign:'right' }}>Fields</th>
                    <th scope="col" style={{ width:140, textAlign:'right' }}>Export</th>
                  </tr>
                </thead>
                <tbody>
                  {forms.map((f, i) => {
                    const isSelected = i === selectedForm;
                    return (
                      <tr key={i}
                          onClick={() => setSelectedForm(i)}
                          tabIndex={0}
                          aria-selected={isSelected}
                          onKeyDown={e => { if (e.key==='Enter' || e.key===' ') { e.preventDefault(); setSelectedForm(i); } }}
                          style={{ cursor:'pointer', background: isSelected ? 'var(--beam-dim)' : 'transparent' }}>
                        <td className="mono" style={{ fontSize:'.68rem', color:'var(--muted)' }}>{(i+1).toString().padStart(2,'0')}</td>
                        <td className="mono" style={{ fontSize:'.76rem', color: isSelected ? 'var(--beam)' : 'var(--text)' }}>
                          {f.page_url || f.action || '/'}
                        </td>
                        <td>
                          <span className="tag" style={{ fontSize:'.64rem' }} title={f.platform_label || f.platform || 'Native'}>
                            {(f.platform || 'native').toUpperCase()}
                          </span>
                        </td>
                        <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{(f.method || 'post').toUpperCase()}</td>
                        <td className="mono" style={{ textAlign:'right', fontSize:'.78rem', fontWeight:600 }}>
                          {(f.fields || []).length}
                        </td>
                        <td style={{ textAlign:'right' }}>
                          <button className="btn btn-ghost btn-sm"
                                  onClick={(e) => {
                                    e.stopPropagation();
                                    const platform = f.platform || 'native';
                                    let exportData, filename, label;
                                    if (platform === 'gravity') {
                                      exportData = buildGravityFormsJson(f, i);
                                      filename = `${data.site}-form-${i + 1}-gravity.json`;
                                      label = 'GF JSON';
                                    } else {
                                      /* Universal form export for CF7, WPForms, native, etc. */
                                      exportData = {
                                        export_format: 'wpsitebeam-form-v1',
                                        platform: platform,
                                        platform_label: f.platform_label || platform,
                                        page_url: f.page_url,
                                        action: f.action,
                                        method: f.method,
                                        fields: (f.fields || []).map(function(fld) {
                                          return { name: fld.name, label: fld.label, type: fld.type, required: fld.required };
                                        }),
                                        exported_at: new Date().toISOString(),
                                      };
                                      filename = `${data.site}-form-${i + 1}-${platform}.json`;
                                      label = 'Export';
                                    }
                                    window.wpsbDownload?.(filename, JSON.stringify(exportData, null, 2), 'application/json');
                                    window.wpsbToast?.(`Downloaded ${filename}`, 'ok');
                                  }}
                                  aria-label={`Export form ${i + 1}`}
                                  title={(f.platform === 'gravity') ? 'Download Gravity Forms 2.5+ import JSON' : 'Download form structure as JSON'}>
                            <Icon name="download" size={11}/>{f.platform === 'gravity' ? 'GF JSON' : 'Export'}
                          </button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>

              {/* Unknown plugin flagging — surfaces slugs not in any catalog
                  so the team can review and add them */}
              {(() => {
                const unknown = plugins.filter(p =>
                  p.category === 'other' && p.slug &&
                  !PLUGIN_SLUG_CATALOG[p.slug.toLowerCase()] &&
                  !PLUGIN_CATALOG[(p.name || '').toLowerCase()]
                );
                if (!unknown.length) return null;
                return (
                  <div style={{ margin:'12px 0 0', padding:'10px 14px', borderRadius:6,
                    background:'var(--warn-dim)', border:'1px solid var(--warn-dim)',
                    fontSize:'.76rem', color:'var(--dim)' }}>
                    <span style={{ color:'var(--warn)', fontWeight:700, marginRight:8 }}>
                      {unknown.length} unrecognized plugin{unknown.length > 1 ? 's' : ''}
                    </span>
                    {unknown.map(p => p.slug || p.name).join(' · ')}
                    <span style={{ marginLeft:8, opacity:.7 }}>— not in scanner catalog. Add to PLUGIN_SLUG_CATALOG in tab-plugins.jsx to categorize.</span>
                  </div>
                );
              })()}

              {/* Form detail panel — fields breakdown for the selected form */}
              {forms[selectedForm] && (
                <div style={{ borderTop:'1px solid var(--border)', padding:16, background:'var(--surface-2, rgba(255,255,255,0.02))' }}>
                  <div style={{ fontSize:'.72rem', color:'var(--dim)', fontFamily:'var(--font-mono)', letterSpacing:'.06em', marginBottom:10 }}>
                    FORM #{selectedForm + 1} FIELDS
                  </div>
                  {(forms[selectedForm].fields || []).length === 0 ? (
                    <div style={{ color:'var(--muted)', fontSize:'.82rem', fontStyle:'italic' }}>
                      No fields extracted for this form.
                    </div>
                  ) : (
                    <table className="table" style={{ background:'transparent' }}>
                      <thead>
                        <tr>
                          <th scope="col" style={{ width:40 }}>#</th>
                          <th scope="col">Label</th>
                          <th scope="col" style={{ width:140 }}>Name</th>
                          <th scope="col" style={{ width:100 }}>Type</th>
                          <th scope="col" style={{ width:80, textAlign:'center' }}>Required</th>
                        </tr>
                      </thead>
                      <tbody>
                        {forms[selectedForm].fields.map((field, fi) => (
                          <tr key={fi}>
                            <td className="mono" style={{ fontSize:'.68rem', color:'var(--muted)' }}>{fi + 1}</td>
                            <td>{field.label || <span style={{ color:'var(--muted)', fontStyle:'italic' }}>— no label —</span>}</td>
                            <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{field.name || '—'}</td>
                            <td>
                              <span className="tag" style={{ fontSize:'.64rem' }}>{(field.type || 'text').toUpperCase()}</span>
                            </td>
                            <td style={{ textAlign:'center' }}>
                              {field.required ? <Icon name="check" size={13}/> : <span style={{ color:'var(--dim)' }}>—</span>}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  )}
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {/* ─ PLUGINS SECTION ─────────────────────────────────────── */}
      <div className="card">
        <div className="card-head">
          <h2 className="card-title">Plugins &amp; extensions</h2>
          {pluginCount > 0 && <span className="tag">{pluginCount}</span>}
        </div>
        <div className="card-body" style={{ padding: 0 }}>
          {pluginCount === 0 ? (
            <ScanEmptyState
              bare
              tab="plugins"
              reason="No plugins or extensions detected on this site. WordPress sites typically expose plugin signatures in HTML/CSS/JS asset paths. Other platforms (Shopify, Wix, Squarespace) bundle features differently."
            />
          ) : (
            <table className="table">
              <thead>
                <tr>
                  <th scope="col">Plugin</th>
                  <th scope="col" style={{ width:120 }}>Category</th>
                  <th scope="col" style={{ width:100 }}>Version</th>
                  <th scope="col" style={{ width:80, textAlign:'right' }}>Vendor</th>
                </tr>
              </thead>
              <tbody>
                {plugins.map((p, i) => {
                  const style = PLUGIN_CATEGORY_STYLE[p.category] || PLUGIN_CATEGORY_STYLE.other;
                  return (
                    <tr key={i}>
                      <td>
                        <div style={{ display:'flex', flexDirection:'column', gap:2 }}>
                          <span style={{ fontWeight:600 }}>{p.name}</span>
                          {p.description && (
                            <span style={{ fontSize:'.68rem', color:'var(--dim)' }}>{p.description}</span>
                          )}
                        </div>
                      </td>
                      <td>
                        <span className="tag" style={{
                          background: style.bg, color: style.fg, border: `1px solid ${style.border}`,
                          fontSize:'.64rem', textTransform:'uppercase', letterSpacing:'.04em',
                        }}>{p.category}</span>
                      </td>
                      <td className="mono" style={{ fontSize:'.72rem', color:'var(--dim)' }}>{p.version || '—'}</td>
                      <td style={{ textAlign:'right' }}>
                        {p.vendor_url ? (
                          <a href={p.vendor_url} target="_blank" rel="noopener noreferrer"
                             style={{ fontSize:'.72rem', color:'var(--beam)' }}>
                            Visit →
                          </a>
                        ) : (
                          <span style={{ color:'var(--dim)', fontSize:'.72rem' }}>—</span>
                        )}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          )}
        </div>
      </div>

      {/* ─ INTEGRATIONS SECTION ─────────────────────────────────── */}
      <div className="card">
        <div className="card-head">
          <h2 className="card-title">Integrations &amp; services</h2>
          {integrationCount > 0 && <span className="tag">{integrationCount}</span>}
        </div>
        <div className="card-body" style={{ padding: 0 }}>
          {integrationCount === 0 ? (
            <ScanEmptyState
              bare
              tab="integrations"
              reason="No third-party services were detected. This can mean the site uses few external tools, or detection signals weren't present in the scanned pages. Common integrations detected automatically: Cloudflare CDN, GTM, GA4, Meta/LinkedIn pixels, HubSpot, Hotjar, reCAPTCHA, cookie banners, ADA widgets, and live chat tools. Try a Full or Deep scan for broader coverage."
            />
          ) : (
            <table className="table">
              <thead>
                <tr>
                  <th scope="col">Service</th>
                  <th scope="col" style={{ width:120 }}>Category</th>
                  <th scope="col">Detection signal</th>
                  <th scope="col" style={{ width:80, textAlign:'right' }}>Vendor</th>
                </tr>
              </thead>
              <tbody>
                {integrations.map((s, i) => {
                  const intStyle = getIntCategoryStyle(s.category || 'other');
                  return (
                  <tr key={i}>
                    <td style={{ fontWeight:600 }}>{s.name || 'Unknown'}</td>
                    <td>
                      <span style={{
                        display:'inline-block', padding:'2px 8px', borderRadius:4,
                        fontSize:'.64rem', fontWeight:700, letterSpacing:'.04em', textTransform:'uppercase',
                        background: intStyle.bg, color: intStyle.fg, border: `1px solid ${intStyle.border}`,
                      }}>
                        {(s.category || 'other').replace('-', ' ')}
                      </span>
                    </td>
                    <td style={{ fontSize:'.76rem', lineHeight:1.5 }}>
                      <div style={{ color:'var(--text-2, #b0b8c8)', fontFamily:'var(--font-mono)', fontSize:'.72rem' }}>{s.signal || '—'}</div>
                      {Array.isArray(s.evidence) && s.evidence.length > 0 && s.evidence.map((ev, ei) => (
                        <div key={ei} style={{ marginTop:2, color:'var(--muted)', fontFamily:'var(--font-mono)', fontSize:'.68rem',
                          overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', maxWidth:300 }} title={ev}>
                          {ev}
                        </div>
                      ))}
                    </td>
                    <td style={{ textAlign:'right' }}>
                      {s.vendor_url ? (
                        <a href={s.vendor_url} target="_blank" rel="noopener noreferrer"
                           style={{ fontSize:'.72rem', color:'var(--beam)' }}>
                          Visit →
                        </a>
                      ) : (
                        <span style={{ color:'var(--dim)', fontSize:'.72rem' }}>—</span>
                      )}
                    </td>
                  </tr>
                );
                })}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </div>
  );
}

window.ScannerPluginsFormsTab = ScannerPluginsFormsTab;


/* window.ScannerPluginsFormsTab already set inside body */
})();
