/**
 * Skipped minification because the original files appears to be already minified.
 * Original file: /npm/@mockdetector/widget@1.8.9/dist/mockdetector-widget.umd.js
 *
 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
 */
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("react/jsx-runtime"),require("react"),require("react-router-dom"),require("lucide-react"),require("@radix-ui/react-slot"),require("@radix-ui/react-dialog"),require("@radix-ui/react-progress"),require("@radix-ui/react-tabs"),require("@supabase/supabase-js")):"function"==typeof define&&define.amd?define(["exports","react/jsx-runtime","react","react-router-dom","lucide-react","@radix-ui/react-slot","@radix-ui/react-dialog","@radix-ui/react-progress","@radix-ui/react-tabs","@supabase/supabase-js"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).MockDetectorWidget={},e.jsxRuntime,e.React,e.ReactRouterDOM,e.LucideReact,e.RadixSlot,e.RadixDialog,e.RadixProgress,e.RadixTabs,e.SupabaseJS)}(this,function(e,n,t,a,s,o,i,r,c,l){"use strict";var d="undefined"!=typeof document?document.currentScript:null;function u(e){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const t in e)if("default"!==t){const a=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,a.get?a:{enumerable:!0,get:()=>e[t]})}return n.default=e,Object.freeze(n)}const m=u(t),p=u(i),f=u(r),g=u(c);function h(e){var n,t,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e)){var s=e.length;for(n=0;n<s;n++)e[n]&&(t=h(e[n]))&&(a&&(a+=" "),a+=t)}else for(t in e)e[t]&&(a&&(a+=" "),a+=t);return a}function b(){for(var e,n,t=0,a="",s=arguments.length;t<s;t++)(e=arguments[t])&&(n=h(e))&&(a&&(a+=" "),a+=n);return a}const y=e=>"boolean"==typeof e?`${e}`:0===e?"0":e,v=b,S=(e,n)=>t=>{var a;if(null==(null==n?void 0:n.variants))return v(e,null==t?void 0:t.class,null==t?void 0:t.className);const{variants:s,defaultVariants:o}=n,i=Object.keys(s).map(e=>{const n=null==t?void 0:t[e],a=null==o?void 0:o[e];if(null===n)return null;const i=y(n)||y(a);return s[e][i]}),r=t&&Object.entries(t).reduce((e,n)=>{let[t,a]=n;return void 0===a||(e[t]=a),e},{}),c=null==n||null===(a=n.compoundVariants)||void 0===a?void 0:a.reduce((e,n)=>{let{class:t,className:a,...s}=n;return Object.entries(s).every(e=>{let[n,t]=e;return Array.isArray(t)?t.includes({...o,...r}[n]):{...o,...r}[n]===t})?[...e,t,a]:e},[]);return v(e,i,c,null==t?void 0:t.class,null==t?void 0:t.className)},x=e=>{const n=D(e),{conflictingClassGroups:t,conflictingClassGroupModifiers:a}=e;return{getClassGroupId:e=>{const t=e.split("-");return""===t[0]&&1!==t.length&&t.shift(),w(t,n)||N(e)},getConflictingClassGroupIds:(e,n)=>{const s=t[e]||[];return n&&a[e]?[...s,...a[e]]:s}}},w=(e,n)=>{var t;if(0===e.length)return n.classGroupId;const a=e[0],s=n.nextPart.get(a),o=s?w(e.slice(1),s):void 0;if(o)return o;if(0===n.validators.length)return;const i=e.join("-");return null==(t=n.validators.find(({validator:e})=>e(i)))?void 0:t.classGroupId},k=/^\[(.+)\]$/,N=e=>{if(k.test(e)){const n=k.exec(e)[1],t=null==n?void 0:n.substring(0,n.indexOf(":"));if(t)return"arbitrary.."+t}},D=e=>{const{theme:n,prefix:t}=e,a={nextPart:new Map,validators:[]};return T(Object.entries(e.classGroups),t).forEach(([e,t])=>{R(t,a,e,n)}),a},R=(e,n,t,a)=>{e.forEach(e=>{if("string"==typeof e){return void((""===e?n:C(n,e)).classGroupId=t)}if("function"==typeof e)return _(e)?void R(e(a),n,t,a):void n.validators.push({validator:e,classGroupId:t});Object.entries(e).forEach(([e,s])=>{R(s,C(n,e),t,a)})})},C=(e,n)=>{let t=e;return n.split("-").forEach(e=>{t.nextPart.has(e)||t.nextPart.set(e,{nextPart:new Map,validators:[]}),t=t.nextPart.get(e)}),t},_=e=>e.isThemeGetter,T=(e,n)=>n?e.map(([e,t])=>[e,t.map(e=>"string"==typeof e?n+e:"object"==typeof e?Object.fromEntries(Object.entries(e).map(([e,t])=>[n+e,t])):e)]):e,E=e=>{if(e<1)return{get:()=>{},set:()=>{}};let n=0,t=new Map,a=new Map;const s=(s,o)=>{t.set(s,o),n++,n>e&&(n=0,a=t,t=new Map)};return{get(e){let n=t.get(e);return void 0!==n?n:void 0!==(n=a.get(e))?(s(e,n),n):void 0},set(e,n){t.has(e)?t.set(e,n):s(e,n)}}},P=e=>{const{separator:n,experimentalParseClassName:t}=e,a=1===n.length,s=n[0],o=n.length,i=e=>{const t=[];let i,r=0,c=0;for(let u=0;u<e.length;u++){let l=e[u];if(0===r){if(l===s&&(a||e.slice(u,u+o)===n)){t.push(e.slice(c,u)),c=u+o;continue}if("/"===l){i=u;continue}}"["===l?r++:"]"===l&&r--}const l=0===t.length?e:e.substring(c),d=l.startsWith("!");return{modifiers:t,hasImportantModifier:d,baseClassName:d?l.substring(1):l,maybePostfixModifierPosition:i&&i>c?i-c:void 0}};return t?e=>t({className:e,parseClassName:i}):i},I=e=>{if(e.length<=1)return e;const n=[];let t=[];return e.forEach(e=>{"["===e[0]?(n.push(...t.sort(),e),t=[]):t.push(e)}),n.push(...t.sort()),n},A=/\s+/;function M(){let e,n,t=0,a="";for(;t<arguments.length;)(e=arguments[t++])&&(n=j(e))&&(a&&(a+=" "),a+=n);return a}const j=e=>{if("string"==typeof e)return e;let n,t="";for(let a=0;a<e.length;a++)e[a]&&(n=j(e[a]))&&(t&&(t+=" "),t+=n);return t};function V(e,...n){let t,a,s,o=function(r){const c=n.reduce((e,n)=>n(e),e());return t=(e=>({cache:E(e.cacheSize),parseClassName:P(e),...x(e)}))(c),a=t.cache.get,s=t.cache.set,o=i,i(r)};function i(e){const n=a(e);if(n)return n;const o=((e,n)=>{const{parseClassName:t,getClassGroupId:a,getConflictingClassGroupIds:s}=n,o=[],i=e.trim().split(A);let r="";for(let c=i.length-1;c>=0;c-=1){const e=i[c],{modifiers:n,hasImportantModifier:l,baseClassName:d,maybePostfixModifierPosition:u}=t(e);let m=Boolean(u),p=a(m?d.substring(0,u):d);if(!p){if(!m){r=e+(r.length>0?" "+r:r);continue}if(p=a(d),!p){r=e+(r.length>0?" "+r:r);continue}m=!1}const f=I(n).join(":"),g=l?f+"!":f,h=g+p;if(o.includes(h))continue;o.push(h);const b=s(p,m);for(let t=0;t<b.length;++t){const e=b[t];o.push(g+e)}r=e+(r.length>0?" "+r:r)}return r})(e,t);return s(e,o),o}return function(){return o(M.apply(null,arguments))}}const F=e=>{const n=n=>n[e]||[];return n.isThemeGetter=!0,n},O=/^\[(?:([a-z-]+):)?(.+)\]$/i,$=/^\d+\/\d+$/,L=new Set(["px","full","screen"]),z=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,U=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,B=/^(rgba?|hsla?|hwb|(ok)?(lab|lch))\(.+\)$/,H=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,K=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,W=e=>q(e)||L.has(e)||$.test(e),G=e=>re(e,"length",ce),q=e=>Boolean(e)&&!Number.isNaN(Number(e)),Y=e=>re(e,"number",q),J=e=>Boolean(e)&&Number.isInteger(Number(e)),X=e=>e.endsWith("%")&&q(e.slice(0,-1)),Q=e=>O.test(e),Z=e=>z.test(e),ee=new Set(["length","size","percentage"]),ne=e=>re(e,ee,le),te=e=>re(e,"position",le),ae=new Set(["image","url"]),se=e=>re(e,ae,ue),oe=e=>re(e,"",de),ie=()=>!0,re=(e,n,t)=>{const a=O.exec(e);return!!a&&(a[1]?"string"==typeof n?a[1]===n:n.has(a[1]):t(a[2]))},ce=e=>U.test(e)&&!B.test(e),le=()=>!1,de=e=>H.test(e),ue=e=>K.test(e),me=V(()=>{const e=F("colors"),n=F("spacing"),t=F("blur"),a=F("brightness"),s=F("borderColor"),o=F("borderRadius"),i=F("borderSpacing"),r=F("borderWidth"),c=F("contrast"),l=F("grayscale"),d=F("hueRotate"),u=F("invert"),m=F("gap"),p=F("gradientColorStops"),f=F("gradientColorStopPositions"),g=F("inset"),h=F("margin"),b=F("opacity"),y=F("padding"),v=F("saturate"),S=F("scale"),x=F("sepia"),w=F("skew"),k=F("space"),N=F("translate"),D=()=>["auto",Q,n],R=()=>[Q,n],C=()=>["",W,G],_=()=>["auto",q,Q],T=()=>["","0",Q],E=()=>[q,Q];return{cacheSize:500,separator:":",theme:{colors:[ie],spacing:[W,G],blur:["none","",Z,Q],brightness:E(),borderColor:[e],borderRadius:["none","","full",Z,Q],borderSpacing:R(),borderWidth:C(),contrast:E(),grayscale:T(),hueRotate:E(),invert:T(),gap:R(),gradientColorStops:[e],gradientColorStopPositions:[X,G],inset:D(),margin:D(),opacity:E(),padding:R(),saturate:E(),scale:E(),sepia:T(),skew:E(),space:R(),translate:R()},classGroups:{aspect:[{aspect:["auto","square","video",Q]}],container:["container"],columns:[{columns:[Z]}],"break-after":[{"break-after":["auto","avoid","all","avoid-page","page","left","right","column"]}],"break-before":[{"break-before":["auto","avoid","all","avoid-page","page","left","right","column"]}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top",Q]}],overflow:[{overflow:["auto","hidden","clip","visible","scroll"]}],"overflow-x":[{"overflow-x":["auto","hidden","clip","visible","scroll"]}],"overflow-y":[{"overflow-y":["auto","hidden","clip","visible","scroll"]}],overscroll:[{overscroll:["auto","contain","none"]}],"overscroll-x":[{"overscroll-x":["auto","contain","none"]}],"overscroll-y":[{"overscroll-y":["auto","contain","none"]}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[g]}],"inset-x":[{"inset-x":[g]}],"inset-y":[{"inset-y":[g]}],start:[{start:[g]}],end:[{end:[g]}],top:[{top:[g]}],right:[{right:[g]}],bottom:[{bottom:[g]}],left:[{left:[g]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",J,Q]}],basis:[{basis:D()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",Q]}],grow:[{grow:T()}],shrink:[{shrink:T()}],order:[{order:["first","last","none",J,Q]}],"grid-cols":[{"grid-cols":[ie]}],"col-start-end":[{col:["auto",{span:["full",J,Q]},Q]}],"col-start":[{"col-start":_()}],"col-end":[{"col-end":_()}],"grid-rows":[{"grid-rows":[ie]}],"row-start-end":[{row:["auto",{span:[J,Q]},Q]}],"row-start":[{"row-start":_()}],"row-end":[{"row-end":_()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",Q]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",Q]}],gap:[{gap:[m]}],"gap-x":[{"gap-x":[m]}],"gap-y":[{"gap-y":[m]}],"justify-content":[{justify:["normal","start","end","center","between","around","evenly","stretch"]}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal","start","end","center","between","around","evenly","stretch","baseline"]}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":["start","end","center","between","around","evenly","stretch","baseline"]}],"place-items":[{"place-items":["start","end","center","baseline","stretch"]}],"place-self":[{"place-self":["auto","start","end","center","stretch"]}],p:[{p:[y]}],px:[{px:[y]}],py:[{py:[y]}],ps:[{ps:[y]}],pe:[{pe:[y]}],pt:[{pt:[y]}],pr:[{pr:[y]}],pb:[{pb:[y]}],pl:[{pl:[y]}],m:[{m:[h]}],mx:[{mx:[h]}],my:[{my:[h]}],ms:[{ms:[h]}],me:[{me:[h]}],mt:[{mt:[h]}],mr:[{mr:[h]}],mb:[{mb:[h]}],ml:[{ml:[h]}],"space-x":[{"space-x":[k]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[k]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit","svw","lvw","dvw",Q,n]}],"min-w":[{"min-w":[Q,n,"min","max","fit"]}],"max-w":[{"max-w":[Q,n,"none","full","min","max","fit","prose",{screen:[Z]},Z]}],h:[{h:[Q,n,"auto","min","max","fit","svh","lvh","dvh"]}],"min-h":[{"min-h":[Q,n,"min","max","fit","svh","lvh","dvh"]}],"max-h":[{"max-h":[Q,n,"min","max","fit","svh","lvh","dvh"]}],size:[{size:[Q,n,"auto","min","max","fit"]}],"font-size":[{text:["base",Z,G]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",Y]}],"font-family":[{font:[ie]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:["tighter","tight","normal","wide","wider","widest",Q]}],"line-clamp":[{"line-clamp":["none",q,Y]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",W,Q]}],"list-image":[{"list-image":["none",Q]}],"list-style-type":[{list:["none","disc","decimal",Q]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[e]}],"placeholder-opacity":[{"placeholder-opacity":[b]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[e]}],"text-opacity":[{"text-opacity":[b]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:["solid","dashed","dotted","double","none","wavy"]}],"text-decoration-thickness":[{decoration:["auto","from-font",W,G]}],"underline-offset":[{"underline-offset":["auto",W,Q]}],"text-decoration-color":[{decoration:[e]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:R()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",Q]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",Q]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[b]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top",te]}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",ne]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},se]}],"bg-color":[{bg:[e]}],"gradient-from-pos":[{from:[f]}],"gradient-via-pos":[{via:[f]}],"gradient-to-pos":[{to:[f]}],"gradient-from":[{from:[p]}],"gradient-via":[{via:[p]}],"gradient-to":[{to:[p]}],rounded:[{rounded:[o]}],"rounded-s":[{"rounded-s":[o]}],"rounded-e":[{"rounded-e":[o]}],"rounded-t":[{"rounded-t":[o]}],"rounded-r":[{"rounded-r":[o]}],"rounded-b":[{"rounded-b":[o]}],"rounded-l":[{"rounded-l":[o]}],"rounded-ss":[{"rounded-ss":[o]}],"rounded-se":[{"rounded-se":[o]}],"rounded-ee":[{"rounded-ee":[o]}],"rounded-es":[{"rounded-es":[o]}],"rounded-tl":[{"rounded-tl":[o]}],"rounded-tr":[{"rounded-tr":[o]}],"rounded-br":[{"rounded-br":[o]}],"rounded-bl":[{"rounded-bl":[o]}],"border-w":[{border:[r]}],"border-w-x":[{"border-x":[r]}],"border-w-y":[{"border-y":[r]}],"border-w-s":[{"border-s":[r]}],"border-w-e":[{"border-e":[r]}],"border-w-t":[{"border-t":[r]}],"border-w-r":[{"border-r":[r]}],"border-w-b":[{"border-b":[r]}],"border-w-l":[{"border-l":[r]}],"border-opacity":[{"border-opacity":[b]}],"border-style":[{border:["solid","dashed","dotted","double","none","hidden"]}],"divide-x":[{"divide-x":[r]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[r]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[b]}],"divide-style":[{divide:["solid","dashed","dotted","double","none"]}],"border-color":[{border:[s]}],"border-color-x":[{"border-x":[s]}],"border-color-y":[{"border-y":[s]}],"border-color-s":[{"border-s":[s]}],"border-color-e":[{"border-e":[s]}],"border-color-t":[{"border-t":[s]}],"border-color-r":[{"border-r":[s]}],"border-color-b":[{"border-b":[s]}],"border-color-l":[{"border-l":[s]}],"divide-color":[{divide:[s]}],"outline-style":[{outline:["","solid","dashed","dotted","double","none"]}],"outline-offset":[{"outline-offset":[W,Q]}],"outline-w":[{outline:[W,G]}],"outline-color":[{outline:[e]}],"ring-w":[{ring:C()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[e]}],"ring-opacity":[{"ring-opacity":[b]}],"ring-offset-w":[{"ring-offset":[W,G]}],"ring-offset-color":[{"ring-offset":[e]}],shadow:[{shadow:["","inner","none",Z,oe]}],"shadow-color":[{shadow:[ie]}],opacity:[{opacity:[b]}],"mix-blend":[{"mix-blend":["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity","plus-lighter","plus-darker"]}],"bg-blend":[{"bg-blend":["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"]}],filter:[{filter:["","none"]}],blur:[{blur:[t]}],brightness:[{brightness:[a]}],contrast:[{contrast:[c]}],"drop-shadow":[{"drop-shadow":["","none",Z,Q]}],grayscale:[{grayscale:[l]}],"hue-rotate":[{"hue-rotate":[d]}],invert:[{invert:[u]}],saturate:[{saturate:[v]}],sepia:[{sepia:[x]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[t]}],"backdrop-brightness":[{"backdrop-brightness":[a]}],"backdrop-contrast":[{"backdrop-contrast":[c]}],"backdrop-grayscale":[{"backdrop-grayscale":[l]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[d]}],"backdrop-invert":[{"backdrop-invert":[u]}],"backdrop-opacity":[{"backdrop-opacity":[b]}],"backdrop-saturate":[{"backdrop-saturate":[v]}],"backdrop-sepia":[{"backdrop-sepia":[x]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[i]}],"border-spacing-x":[{"border-spacing-x":[i]}],"border-spacing-y":[{"border-spacing-y":[i]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",Q]}],duration:[{duration:E()}],ease:[{ease:["linear","in","out","in-out",Q]}],delay:[{delay:E()}],animate:[{animate:["none","spin","ping","pulse","bounce",Q]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[S]}],"scale-x":[{"scale-x":[S]}],"scale-y":[{"scale-y":[S]}],rotate:[{rotate:[J,Q]}],"translate-x":[{"translate-x":[N]}],"translate-y":[{"translate-y":[N]}],"skew-x":[{"skew-x":[w]}],"skew-y":[{"skew-y":[w]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",Q]}],accent:[{accent:["auto",e]}],appearance:[{appearance:["none","auto"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",Q]}],"caret-color":[{caret:[e]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":R()}],"scroll-mx":[{"scroll-mx":R()}],"scroll-my":[{"scroll-my":R()}],"scroll-ms":[{"scroll-ms":R()}],"scroll-me":[{"scroll-me":R()}],"scroll-mt":[{"scroll-mt":R()}],"scroll-mr":[{"scroll-mr":R()}],"scroll-mb":[{"scroll-mb":R()}],"scroll-ml":[{"scroll-ml":R()}],"scroll-p":[{"scroll-p":R()}],"scroll-px":[{"scroll-px":R()}],"scroll-py":[{"scroll-py":R()}],"scroll-ps":[{"scroll-ps":R()}],"scroll-pe":[{"scroll-pe":R()}],"scroll-pt":[{"scroll-pt":R()}],"scroll-pr":[{"scroll-pr":R()}],"scroll-pb":[{"scroll-pb":R()}],"scroll-pl":[{"scroll-pl":R()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",Q]}],fill:[{fill:[e,"none"]}],"stroke-w":[{stroke:[W,G,Y]}],stroke:[{stroke:[e,"none"]}],sr:["sr-only","not-sr-only"],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-s","border-w-e","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-s","border-color-e","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]}}});function pe(...e){return me(b(e))}const fe=S("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90 border-primary/50 hover:border-primary/70 shadow-professional-sm hover:shadow-professional-md observer-button-primary",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90 border-destructive/50 hover:border-destructive/70 shadow-professional-sm",outline:"border-border bg-card text-foreground hover:bg-muted hover:text-accent-foreground hover:border-accent shadow-professional-sm observer-button-outline",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-secondary/60 hover:border-secondary shadow-professional-sm",ghost:"border-transparent bg-card/80 hover:bg-muted hover:text-accent-foreground hover:border-accent/50 shadow-professional-sm",link:"border-transparent text-primary underline-offset-4 hover:underline",success:"bg-success text-success-foreground hover:bg-success/90 border-success/50 hover:border-success/70 shadow-professional-sm",warning:"bg-warning text-warning-foreground hover:bg-warning/90 border-warning/50 hover:border-warning/70 shadow-professional-sm"},size:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3",lg:"h-11 rounded-md px-8",icon:"h-10 w-10"}},defaultVariants:{variant:"default",size:"default"}}),ge=m.forwardRef(({className:e,variant:t,size:a,asChild:s=!1,...i},r)=>{const c=s?o.Slot:"button";return n.jsx(c,{className:pe(fe({variant:t,size:a,className:e})),ref:r,...i})});ge.displayName="Button";const he=S("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",outline:"text-foreground"}},defaultVariants:{variant:"default"}});function be({className:e,variant:t,...a}){return n.jsx("div",{className:pe(he({variant:t}),e),...a})}const ye=m.forwardRef(({className:e,...t},a)=>n.jsx("div",{ref:a,className:pe("rounded-lg border bg-card text-card-foreground shadow-sm observer-card",e),...t}));ye.displayName="Card";m.forwardRef(({className:e,...t},a)=>n.jsx("div",{ref:a,className:pe("flex flex-col space-y-1.5 p-6",e),...t})).displayName="CardHeader";m.forwardRef(({className:e,...t},a)=>n.jsx("h3",{ref:a,className:pe("text-2xl font-semibold leading-none tracking-tight",e),...t})).displayName="CardTitle";m.forwardRef(({className:e,...t},a)=>n.jsx("p",{ref:a,className:pe("text-sm text-muted-foreground",e),...t})).displayName="CardDescription";const ve=m.forwardRef(({className:e,...t},a)=>n.jsx("div",{ref:a,className:pe("p-6 pt-0",e),...t}));ve.displayName="CardContent";m.forwardRef(({className:e,...t},a)=>n.jsx("div",{ref:a,className:pe("flex items-center p-6 pt-0",e),...t})).displayName="CardFooter";const Se=p.Root,xe=p.Portal,we=m.forwardRef(({className:e,...t},a)=>n.jsx(p.Overlay,{ref:a,className:pe("fixed inset-0 z-50 bg-black/80  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",e),...t}));we.displayName=p.Overlay.displayName;const ke=m.forwardRef(({className:e,children:t,...a},o)=>n.jsxs(xe,{children:[n.jsx(we,{}),n.jsxs(p.Content,{ref:o,className:pe("fixed left-[50%] top-[50%] z-50 grid w-full max-w-2xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",e),...a,children:[t,n.jsxs(p.Close,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[n.jsx(s.X,{className:"h-4 w-4"}),n.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));ke.displayName=p.Content.displayName;const Ne=({className:e,...t})=>n.jsx("div",{className:pe("flex flex-col space-y-1.5 text-center sm:text-left",e),...t});Ne.displayName="DialogHeader";const De=m.forwardRef(({className:e,...t},a)=>n.jsx(p.Title,{ref:a,className:pe("text-lg font-semibold leading-none tracking-tight",e),...t}));De.displayName=p.Title.displayName;m.forwardRef(({className:e,...t},a)=>n.jsx(p.Description,{ref:a,className:pe("text-sm text-muted-foreground",e),...t})).displayName=p.Description.displayName;const Re=m.forwardRef(({className:e,value:t,...a},s)=>n.jsx(f.Root,{ref:s,className:pe("relative h-4 w-full overflow-hidden rounded-full bg-secondary",e),...a,children:n.jsx(f.Indicator,{className:"h-full w-full flex-1 bg-primary transition-all",style:{transform:`translateX(-${100-(t||0)}%)`}})}));Re.displayName=f.Root.displayName;const Ce=g.Root,_e=m.forwardRef(({className:e,...t},a)=>n.jsx(g.List,{ref:a,className:pe("inline-flex h-10 items-center justify-center rounded-md bg-muted border border-border p-1 text-muted-foreground",e),...t}));_e.displayName=g.List.displayName;const Te=m.forwardRef(({className:e,...t},a)=>n.jsx(g.Trigger,{ref:a,className:pe("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-card data-[state=active]:text-card-foreground data-[state=active]:shadow-sm hover:bg-accent hover:text-accent-foreground",e),...t}));Te.displayName=g.Trigger.displayName;const Ee=m.forwardRef(({className:e,...t},a)=>n.jsx(g.Content,{ref:a,className:pe("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",e),...t}));Ee.displayName=g.Content.displayName;const Pe=[{pattern:/test[_-]?data/gi,severity:"high",description:"Test data variable detected"},{pattern:/demo[_-]?data/gi,severity:"high",description:"Demo data variable detected"},{pattern:/placeholder[_-]?data/gi,severity:"medium",description:"Placeholder data detected"},{pattern:/fake[_-]?data/gi,severity:"high",description:"Fake data variable detected"},{pattern:/dummy[_-]?data/gi,severity:"high",description:"Dummy data variable detected"},{pattern:/TODO:.*mock/gi,severity:"medium",description:"TODO comment about mock data"},{pattern:/FIXME:.*test/gi,severity:"medium",description:"FIXME comment about test data"},{pattern:/\['[^']+\s+\d+',\s*'[^']+\s+\d+'/gi,severity:"high",description:'Hardcoded array with sequential items detected (e.g., ["Item 1", "Item 2"])'},{pattern:/\{[\s\S]*?name:\s*['"][^'"]+\s+\d+['"][\s\S]*?\}/gi,severity:"high",description:"Mock object with numbered name property"},{pattern:/Array\(\d+\)\.fill\(/gi,severity:"high",description:"Array.fill() with hardcoded length - likely generating mock data"},{pattern:/test@\w+\.\w+/gi,severity:"high",description:"Test email address detected"},{pattern:/demo@\w+\.\w+/gi,severity:"high",description:"Demo email address detected"},{pattern:/example@\w+\.\w+/gi,severity:"medium",description:"Example email address detected"},{pattern:/(?:\+?1[-.\s]?)?\(?555\)?[-.\s]?\d{3}[-.\s]?\d{4}|\b123-456-\d{4}\b/gi,severity:"high",description:"Mock phone number (555/123-456 pattern) - replace with real contact info"},{pattern:/(?:placeholder\.com|via\.placeholder\.com|picsum\.photos|loremflickr\.com|dummyimage\.com|fakeimg\.pl|placehold\.(?:it|jp|co)|unsplash\.com\/random)/gi,severity:"high",description:"Placeholder image URL detected (replace with real images or upload to Supabase Storage)"},{pattern:/(?:https?:\/\/)?(?:www\.)?(?:jsonplaceholder\.typicode\.com|reqres\.in|mockapi\.io|api\.example\.(?:com|dev|org)|example\.(?:com|dev|org)\/api|gorest\.co\.in|dummyjson\.com|fakestoreapi\.com)/gi,severity:"critical",description:"Mock API endpoint detected (replace with real API or Supabase Edge Function)"},{pattern:/(?:username|user|login|email):\s*['"`](admin|test|demo)['"`][\s\S]{0,50}?(?:password|pass|pwd):\s*['"`](admin|test|demo|password|12345)/gi,severity:"critical",description:"Hardcoded test credentials detected (admin/admin, test/test) - SECURITY RISK!"},{pattern:/['"`]eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}['"`]/g,severity:"critical",description:"Hardcoded JWT token detected - CRITICAL SECURITY RISK!"},{pattern:/(?:['"`]|filename:\s*['"`])(test|sample|mock|demo|fake|dummy|placeholder)\.(pdf|jpg|jpeg|png|gif|svg|doc|docx|xlsx|csv|zip)['"`]/gi,severity:"medium",description:'Mock filename detected (e.g., "test.pdf", "sample.jpg")'},{pattern:/faker\.(name|internet|address|company|lorem|commerce|random|phone)\.\w+/gi,severity:"high",description:"Faker.js mock data generator detected (replace with real data)"},{pattern:/\/\/.*(?:api[_-]?key|token|secret|password|auth).*[:=]\s*['"`][a-zA-Z0-9_-]{16,}['"`]/gi,severity:"critical",description:"Hardcoded API key or token in comment (use Supabase Secrets Manager)"},{pattern:/wss?:\/\/(?:localhost|127\.0\.0\.1|example\.com|test\.com)/gi,severity:"high",description:"Mock WebSocket URL (replace with production WebSocket endpoint)"},{pattern:/(?:VITE_|REACT_APP_|NEXT_PUBLIC_)\w+\s*=\s*['"`]?(your-api-key|example|test|demo|localhost|127\.0\.0\.1|changeme)/gi,severity:"high",description:"Environment variable with example/placeholder value"},{pattern:/['"`][0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}['"`].*(?:test|demo|mock|sample)/gi,severity:"high",description:"Mock UUID detected (UUID followed by test/demo/mock keyword)"},{pattern:/(?:fetch|axios\.(?:get|post))\s*\(\s*['"`]https?:\/\/(?:localhost|127\.0\.0\.1):\d{4,5}/gi,severity:"high",description:"Localhost URL in API call - Development URL detected"},{pattern:/['"`](sk_test_|pk_test_|rk_test_)[a-zA-Z0-9]{20,}['"`]/gi,severity:"critical",description:"Stripe test API key detected (replace with production key via Supabase Secrets)"},{pattern:/['"`]?(4242\s*4242\s*4242\s*4242|5555\s*5555\s*5555\s*4444|3782\s*822463\s*10005)['"`]?/g,severity:"critical",description:"Test credit card number detected (never use in production)"},{pattern:/(?:paypal\.com\/sandbox|sandbox\.paypal|api-m\.sandbox\.paypal)/gi,severity:"high",description:"PayPal sandbox URL detected (update to production PayPal endpoint)"},{pattern:/(?:routing(?:Number)?|routingNum)['"`]?\s*[:=]\s*['"`]?(?:110000000|021000021|011401533)['"`]?/gi,severity:"high",description:"Mock bank routing number detected (replace with real banking integration)"},{pattern:/(?:amount|price|cost|total)['"`]?\s*[:=]\s*['"`]?(?:0\.01|1\.00|100\.00|9999\.99)['"`]?(?!\d)/gi,severity:"medium",description:"Common test payment amount detected (e.g., $0.01, $1.00)"},{pattern:/['"`](?:john\s*doe|jane\s*smith|foo\s*bar|alice\s*wonderland|bob\s*builder|test\s*user\s*name|example\s*user)['"`]/gi,severity:"high",description:'Common placeholder name detected (e.g., "John Doe", "Jane Smith")'},{pattern:/(?:username|userName|user_name)['"`]?\s*[:=]\s*['"`]?(user\d{1,5}|testuser\d*|admin\d{1,3}|demouser)['"`]?/gi,severity:"high",description:"Mock username pattern detected (e.g., user123, testuser)"},{pattern:/(?:firstName|first_name)['"`]?\s*[:=]\s*['"`](?:Test|Demo|Sample|Mock|Example|Placeholder)['"`]/gi,severity:"medium",description:"Placeholder first name detected"},{pattern:/(?:avatar|profilePic|profile_picture)['"`]?\s*[:=]\s*['"`](?:\/default-avatar\.png|\/placeholder\.jpg|https?:\/\/i\.pravatar\.cc)/gi,severity:"medium",description:"Default/placeholder avatar URL detected"},{pattern:/['"`](?:\+1-?555-?|555-?\d{3}-?\d{4})/g,severity:"high",description:"Hollywood fake phone number (555 prefix) detected"},{pattern:/['"`](?:1970-01-01|2024-01-01|2023-12-31|2025-01-01)['"`]/g,severity:"high",description:"Hardcoded placeholder date detected (epoch or test date)"},{pattern:/new Date\(['"`](?:2024-01-01|2023-01-01|1970-01-01)['"`]\)/gi,severity:"high",description:"Mock date object with placeholder date"},{pattern:/(?:lat(?:itude)?|lng|lon(?:gitude)?)['"`]?\s*[:=]\s*['"`]?0(?:\.0+)?['"`]?[,\s]+(?:lat(?:itude)?|lng|lon(?:gitude)?)['"`]?\s*[:=]\s*['"`]?0(?:\.0+)?['"`]?/gi,severity:"medium",description:"Null Island coordinates (0,0) detected - likely placeholder location"},{pattern:/['"`](?:123 Main St(?:reet)?|456 Elm St|789 Oak Ave|Fake Street 123)['"`]/gi,severity:"medium",description:"Common mock street address detected"},{pattern:/timezone\s*[:=]\s*['"`](?:UTC|GMT|America\/New_York)['"`](?!\+|\-)/gi,severity:"low",description:"Hardcoded timezone detected (should be user-configurable)"},{pattern:/(?:userId|user_id|orderId|order_id)['"`]?\s*[:=]\s*['"`](?:user_|order_|product_|item_)\d{4,}['"`]/gi,severity:"high",description:"Sequential mock ID pattern detected (e.g., user_123456, order_00001)"},{pattern:/(?:import|from)\s+['"`]\.{1,2}\/.*\.(test|spec|mock)\.(ts|tsx|js|jsx)['"`]/gi,severity:"critical",description:"Import from test/mock file detected in production code"}],Ie=[{pattern:/\b(we have|currently|total of|there are)\s+\d+\s+(users?|students?|agents?|members?|ais?|rooms?)(?![^{]*\})/gi,severity:"high",description:"Statistical claim - verify it's from database, not hardcoded"},{pattern:new RegExp("(?<!\\{[^}]*)\\b\\d+\\s+(active|registered|enrolled)\\s+(?:users?|students?|members?)(?![^{]*\\})","gi"),severity:"medium",description:"Numeric claim - verify dynamic data binding (should be {data.length})"},{pattern:new RegExp("(?<!\\{[^}]*)\\b\\d+\\s+(vip|standard|luxury)\\s+(?:rooms?|guests?)(?![^{]*\\})","gi"),severity:"medium",description:"Room statistics - verify real-time data connection"},{pattern:/\b(over|more than|up to)\s+\d+(?![^{]*\})/gi,severity:"low",description:"Approximate claim (verify with actual data or mark as estimate)"}],Ae=[{pattern:/const\s+(?!(?:config|options|settings|navigation|features|routes|constants|CONSTANTS)\w*\s*=)\w+\s*=\s*\[[\s\S]{0,500}?\{[\s\S]{0,200}?(?:value|count|total|users?|students?|rooms?):\s*\d{2,}/gi,severity:"high",description:"Static array with hardcoded statistics (not config)"},{pattern:/const\s+(?:mock|test|demo|sample|fake|dummy)(?:\w+)?\s*=\s*\[[\s\S]{0,500}?\{/gi,severity:"critical",description:"Mock data array detected (variable name contains mock/test/demo)"},{pattern:/const\s+(?:stats|data|metrics)\s*=\s*\{[\s\S]{0,200}?:\s*\d{2,}/gi,severity:"medium",description:"Static stats object - verify it's from database fetch"},{pattern:/\.map\(\([^)]*\)\s*=>\s*\{[\s\S]{0,200}?(?:value|count|total):\s*\d{2,}/gi,severity:"medium",description:"Hardcoded values in map - check if data is from API/database"},{pattern:/const\s+(?:mock|test|demo|sample)\w*\s*=\s*\[[\s\S]{0,300}?['"][^'"]+\s+\d+['"]/gi,severity:"critical",description:'Mock array with numbered items (e.g., "Item 1", "Item 2")'},{pattern:/\[\s*\{[\s\S]{0,100}?id:\s*1[\s\S]{0,100}?\},\s*\{[\s\S]{0,100}?id:\s*2/gi,severity:"critical",description:"Array with sequential IDs starting at 1, 2, 3..."}];function Me(e){var n,t;let a=50;const s="code"in e&&(null==(n=e.code)?void 0:n.toLowerCase())||"",o="file"in e&&(null==(t=e.file)?void 0:t.toLowerCase())||"",i=e.description.toLowerCase();return i.includes("usestate")&&i.includes("array")&&(a=85),i.includes("useeffect")&&(s.includes("fakeresponse")||s.includes("mockdata"))&&(a=90),s.match(/const\s+(testUsers|mockUsers|fakeData)/)&&(a=85),(s.includes("test@example.com")||s.includes("user@example.com"))&&(a+=40),(s.includes("lorem ipsum")||s.includes("dolor sit amet"))&&(a+=40),(s.includes("array.fill(")||s.includes("array(10).fill("))&&(a+=35),(s.includes("555-1234")||s.includes("555-5555"))&&(a+=35),s.match(/const\s+(mock|test|demo|sample)(data|users|items|products)/i)&&(a+=30),s.match(/test_user|demo_account|sample_item|mock_product/i)&&(a+=30),s.match(/\[\s*{\s*id:\s*1\s*,/)&&(a+=25),s.match(/user\s*#?\d+|item\s*#?\d+/i)&&(a+=25),s.match(/123\s*main\s*street|456\s*elm\s*st/i)&&(a+=15),(s.includes("acme corp")||s.includes("test company"))&&(a+=15),s.match(/\$9\.99|\$19\.99|\$99\.99/)&&(a+=10),(o.includes(".config.")||o.includes("tailwind.config")||o.includes("vite.config"))&&(a-=50),(o.includes("mockdetector")||o.includes("scanpatterns"))&&(a-=50),(s.includes("supabase_publishable_key")||s.includes("vite_supabase"))&&(a-=40),s.includes(".from(")&&s.includes(".select(")&&(a-=30),(s.includes("import")||s.includes("export"))&&(a-=20),(i.includes("configuration")||i.includes("settings"))&&(a-=30),(i.includes("api response")||i.includes("metadata"))&&(a-=35),i.includes("batch insert")&&i.includes("minutes ago")&&(a-=40),(o.includes("/components/")||o.includes("/pages/"))&&(a+=20),"table"in e&&(a+=10),"critical"===e.severity&&(a+=5),Math.max(0,Math.min(100,Math.round(a)))}function je(e){var n;const t="code"in e&&(null==(n=e.code)?void 0:n.toLowerCase())||"",a=e.description.toLowerCase(),s="pattern"in e?e.pattern.toLowerCase():"";return t.includes("usestate([")||a.includes("usestate")?"useState_array":t.includes("array.fill(")||t.includes("array(")?"array_fill":t.match(/\[\s*\{.*\}\s*\]\.map\(/)?"inline_map":t.includes("test@")||t.includes("@example.")||s.includes("email")?"test_email":t.includes("lorem ipsum")||t.includes("dolor sit")?"lorem_ipsum":t.includes("555-")||s.includes("phone")?"mock_phone":s.includes("sequential")||a.includes("sequential")?"sequential_users":s.includes("username")||a.includes("test username")?"test_username":s.includes("address")||a.includes("mock address")?"mock_address":s.includes("company")||a.includes("company name")?"mock_company":s.includes("credit_card")||a.includes("credit card")?"mock_credit_card":s.includes("zip")||a.includes("zip code")?"mock_zip":t.includes("[{")&&t.includes("}]")?"hardcoded_array":a.includes("static")||a.includes("hardcoded")?"static_data":"generic"}function Ve(e){const n=function(e){const n=je(e),t="table"in e?e.table:"your_table";switch(n){case"useState_array":return`// ✅ Replace with database fetch:\nconst [data, setData] = useState([]);\n\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data, error } = await supabase\n      .from('${t}')\n      .select('*')\n      .order('created_at', { ascending: false })\n      .limit(10);\n    \n    if (error) {\n      console.error('Error fetching data:', error);\n      return;\n    }\n    \n    if (data) setData(data);\n  };\n  \n  fetchData();\n}, []);`;case"test_email":return"// ✅ Use real user email from authentication:\nconst { data: { user } } = await supabase.auth.getUser();\nconst email = user?.email || 'support@yourdomain.com';\n\n// OR fetch from database:\nconst { data } = await supabase\n  .from('profiles')\n  .select('email')\n  .eq('id', userId)\n  .single();";case"lorem_ipsum":return`// ✅ Replace with real content from database:\nconst { data } = await supabase\n  .from('${t}')\n  .select('description, content, bio')\n  .eq('id', itemId)\n  .single();\n\n// OR use user-generated content:\nconst content = data?.description || 'No description available';`;case"array_fill":return`// ❌ Array.fill() creates identical mock data!\n// ✅ Replace with real database query:\n\nconst { data, error } = await supabase\n  .from('${t}')\n  .select('*')\n  .limit(10);\n\nif (error) throw error;\nreturn data || [];`;case"inline_map":return`// ✅ Move hardcoded data to state and fetch from database:\n\n// 1. Create state:\nconst [items, setItems] = useState([]);\n\n// 2. Fetch data:\nuseEffect(() => {\n  const loadItems = async () => {\n    const { data } = await supabase\n      .from('${t}')\n      .select('*');\n    setItems(data || []);\n  };\n  loadItems();\n}, []);\n\n// 3. Use in JSX:\n{items.map((item) => (\n  <YourComponent key={item.id} {...item} />\n))}`;case"mock_phone":return"// ✅ Replace with real contact information:\n\n// Option 1: From settings/config table\nconst { data } = await supabase\n  .from('settings')\n  .select('support_phone, contact_phone')\n  .single();\n\n// Option 2: From user profile\nconst { data: profile } = await supabase\n  .from('profiles')\n  .select('phone_number')\n  .eq('id', userId)\n  .single();\n\nconst phone = data?.support_phone || '+1 (555) 123-4567'; // Your real number";case"sequential_users":return"// ❌ Sequential user generation detected!\n// ✅ Fetch real users from your database:\n\nconst { data: users, error } = await supabase\n  .from('profiles')\n  .select('id, name, email, avatar_url, created_at')\n  .order('created_at', { ascending: false })\n  .limit(20);\n\nif (error) {\n  console.error('Error fetching users:', error);\n  return [];\n}\n\nreturn users || [];";case"test_username":return"// ✅ Use real usernames from authentication:\n\nconst { data } = await supabase\n  .from('profiles')\n  .select('username, display_name, full_name')\n  .eq('id', userId)\n  .single();\n\nconst username = data?.username || data?.display_name || 'Anonymous';";case"mock_address":return"// ✅ Store and fetch real addresses:\n\nconst { data } = await supabase\n  .from('addresses')\n  .select('street, city, state, zip_code, country')\n  .eq('user_id', userId)\n  .single();\n\nconst fullAddress = `${data.street}, ${data.city}, ${data.state} ${data.zip_code}`;";case"mock_company":return"// ✅ Use real company information:\n\nconst { data } = await supabase\n  .from('companies')\n  .select('name, industry, size, founded_year')\n  .eq('id', companyId)\n  .single();\n\nconst companyName = data?.name || 'Your Company';";case"mock_credit_card":return"// ⚠️ NEVER store real credit cards in your database!\n// ✅ Use Stripe or payment provider:\n\nimport { loadStripe } from '@stripe/stripe-js';\n\nconst stripe = await loadStripe('your_publishable_key');\nconst { error } = await stripe.confirmPayment({\n  elements,\n  confirmParams: {\n    return_url: 'https://yourdomain.com/payment-success',\n  },\n});";case"mock_zip":return"// ✅ Fetch real ZIP code from user location or address:\n\nconst { data } = await supabase\n  .from('addresses')\n  .select('zip_code, postal_code')\n  .eq('user_id', userId)\n  .eq('is_primary', true)\n  .single();\n\nconst zipCode = data?.zip_code || data?.postal_code;";case"hardcoded_array":case"static_data":return`// ✅ Replace hardcoded data with database fetch:\n\nconst { data, error } = await supabase\n  .from('${t}')\n  .select('*')\n  .order('created_at', { ascending: false });\n\nif (error) {\n  console.error('Database error:', error);\n  return [];\n}\n\nreturn data || [];`;default:return`// ✅ Recommended fix:\n// 1. Create a Supabase table to store this data\n// 2. Replace hardcoded values with database queries\n// 3. Use useState and useEffect to load data dynamically\n\nconst [data, setData] = useState([]);\n\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data, error } = await supabase\n      .from('${t}')\n      .select('*');\n    if (data) setData(data);\n  };\n  fetchData();\n}, []);`}}(e),t=function(e){const n=je(e),t="table"in e?e.table:"items",a=[];switch(n){case"test_email":case"test_username":a.push({label:"Add Authentication",action:"add_auth",description:"Set up Supabase Auth to manage real users"});break;case"useState_array":case"hardcoded_array":case"array_fill":a.push({label:`Create ${t} Table`,action:"create_table",description:`Create a Supabase table to store ${t} data`}),a.push({label:"Fetch from Database",action:"fetch_data",description:"Replace hardcoded data with database queries"});break;case"lorem_ipsum":a.push({label:"Create Content Table",action:"create_table",description:"Store real content in a Supabase table"});break;case"mock_phone":case"mock_address":a.push({label:"Create Settings Table",action:"create_table",description:"Store contact information in database"});break;case"sequential_users":a.push({label:"Migrate to Real Users",action:"migrate_data",description:"Replace mock users with real user profiles"});break;default:a.push({label:"Fetch from Database",action:"fetch_data",description:"Replace with real data from Supabase"})}return a}(e);return{...e,fix:n,reasoning:`Quick fixes available: ${t.map(e=>e.label).join(", ")}`}}const Fe=[{name:"useState_hardcoded_array",pattern:/useState\s*(?:<[^>]+>)?\s*\(\s*\[\s*\{/g,severity:"critical",description:"useState initialized with hardcoded array of objects (likely mock data)",autoFix:e=>"// Replace with database fetch:\nconst [data, setData] = useState([]);\n\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data, error } = await supabase\n      .from('your_table')\n      .select('*');\n    if (data) setData(data);\n  };\n  fetchData();\n}, []);"},{name:"useEffect_fake_response",pattern:/useEffect\s*\([^)]*\)\s*=>\s*\{[^}]*(?:fakeResponse|mockData|testData|fakeAPI|fakeFetch)\s*=/g,severity:"critical",description:"useEffect contains fake/mock data assignment instead of real API call",autoFix:e=>"// Replace fake data with real Supabase query:\nuseEffect(() => {\n  const fetchRealData = async () => {\n    const { data, error } = await supabase.from('your_table').select('*');\n    if (data) setYourState(data);\n  };\n  fetchRealData();\n}, []);"},{name:"suspicious_function_names",pattern:/(?:const|function)\s+(?:handle|validate|fetch|get)?(?:Mock|Test|Fake|Demo|Sample)[A-Z]\w*\s*=/g,severity:"high",description:"Function name contains mock/test/fake - likely temporary code",autoFix:e=>{var n;const t=(null==(n=e[0].match(/(?:Mock|Test|Fake|Demo|Sample)[A-Z]\w*/))?void 0:n[0])||"",a=t.replace(/Mock|Test|Fake|Demo|Sample/gi,"");return`// Rename function: ${t} → ${a}\n// Remove mock/test prefix`}},{name:"test_array_variables",pattern:/const\s+(testUsers|mockUsers|fakeData|demoData|sampleData|testData|mockItems|fakeProducts)\s*=\s*\[/g,severity:"high",description:"Variable name suggests test/mock data array",autoFix:e=>{const n=e[1],t=n.replace(/test|mock|fake|demo|sample/gi,"");return`// Replace: const ${n} = [...]\n// With: Fetch real data and store in const ${t}`}},{name:"map_with_array_literal",pattern:/\[\s*\{[^}]*\}\s*(?:,\s*\{[^}]*\}){2,}\s*\]\.map\s*\(/g,severity:"high",description:"Array literal with objects directly in .map() call (hardcoded data)",autoFix:e=>"// Replace with state-based data:\n{data.map((item) => (\n  // Your JSX here\n))}\n\n// Fetch data with:\nuseEffect(() => {\n  const loadData = async () => {\n    const { data } = await supabase.from('your_table').select('*');\n    setData(data || []);\n  };\n  loadData();\n}, []);"},{name:"array_fill_mock",pattern:/Array\s*\(\s*\d+\s*\)\.fill\s*\(\s*\{[^}]*\}\s*\)/g,severity:"critical",description:"Array.fill() with mock objects (generates fake data)",autoFix:e=>"// ❌ Array.fill() creates identical mock data!\n// ✅ Replace with real database query:\nconst { data } = await supabase\n  .from('your_table')\n  .select('*')\n  .limit(10); // Adjust limit as needed"},{name:"test_email_pattern",pattern:/(test|demo|sample|example)@(test|demo|example)\.(com|org|net)/gi,severity:"high",description:"Test email address found in code",autoFix:e=>"// ❌ Test email detected!\n// ✅ Use real user email from auth:\nconst { data: { user } } = await supabase.auth.getUser();\nconst email = user?.email;"},{name:"sequential_user_mock",pattern:/(user|name|email):\s*['"`](User|Name|Email)\s*\$\{i\$\}['"`]/gi,severity:"critical",description:"Sequential user generation pattern (User ${i}, Name ${i}, etc.)",autoFix:e=>"// ❌ Sequential mock users detected!\n// ✅ Fetch real users from database:\nconst { data: users } = await supabase\n  .from('profiles')\n  .select('id, name, email')\n  .order('created_at', { ascending: false })\n  .limit(10);"},{name:"lorem_ipsum",pattern:/(['"`]).*?(lorem\s+ipsum|dolor\s+sit\s+amet).*?\1/gi,severity:"medium",description:"Lorem Ipsum placeholder text found in string",autoFix:e=>"// ❌ Lorem Ipsum placeholder text!\n// ✅ Use real content from your database:\nconst { data } = await supabase\n  .from('content')\n  .select('text')\n  .eq('type', 'description')\n  .single();"},{name:"date_now_mock",pattern:/new\s+Date\s*\(\s*['"`]\d{4}-\d{2}-\d{2}['"`]\s*\)/g,severity:"low",description:"Hardcoded date string (consider using real timestamps)",autoFix:e=>"// Consider using real timestamps from database:\n// created_at, updated_at columns are automatically set by Supabase"},{name:"useEffect_with_mock_data",pattern:/useEffect\s*\(\s*\(\s*\)\s*=>\s*\{\s*set\w+\s*\(\s*\[[^\]]{50,}\]\s*\)/g,severity:"high",description:"useEffect setting state with inline mock data array",autoFix:e=>"// Replace mock data with real API/database call:\nuseEffect(() => {\n  const fetchData = async () => {\n    try {\n      const { data, error } = await supabase\n        .from('your_table')\n        .select('*');\n      \n      if (error) throw error;\n      setData(data || []);\n    } catch (error) {\n      console.error('Error fetching data:', error);\n    }\n  };\n  \n  fetchData();\n}, []);"},{name:"hardcoded_api_response",pattern:/const\s+\w+\s*=\s*\{\s*data:\s*\[[^\]]{50,}\]/g,severity:"critical",description:"Hardcoded API response object with data array",autoFix:e=>"// ❌ Hardcoded API response!\n// ✅ Make real API call:\nconst response = await supabase.functions.invoke('your-function', {\n  body: { /* your params */ }\n});\nconst data = response.data;"},{name:"fetch_mock_url",pattern:/(?:fetch|axios\.(?:get|post|put|delete))\s*\(\s*['"`](?:https?:\/\/)?(?:localhost|127\.0\.0\.1|example\.com|test\.com|jsonplaceholder\.typicode\.com|reqres\.in|mockapi\.io)/gi,severity:"critical",description:"HTTP request to mock/test endpoint (localhost, example.com, or mock API)",autoFix:e=>"// ❌ Fetch/Axios to mock URL detected!\n// ✅ Replace with Supabase Edge Function:\nconst { data, error } = await supabase.functions.invoke('your-function', {\n  body: { /* params */ }\n});"}],Oe=(e,n)=>{const t=[],a=e.split("\n");return Fe.forEach(({name:s,pattern:o,severity:i,description:r,autoFix:c})=>{var l;let d;for(o.lastIndex=0;null!==(d=o.exec(e));){const s=e.substring(0,d.index).split("\n").length,o=a[s-1],u=c(d,e),m={type:"mock_data",severity:i,file:n,line:s,code:(null==o?void 0:o.trim())||d[0].trim(),description:`React Pattern: ${r}`,fix:u||"Replace with real data from database or API",confidence:0};m.confidence=Me(m),((null==n?void 0:n.includes("/components/"))||(null==n?void 0:n.includes("/pages/")))&&(m.confidence=Math.min(100,(m.confidence||50)+20));const p=null==(l=Fe.find(e=>e.description===r.replace("React Pattern: ","")))?void 0:l.name;"useState_hardcoded_array"!==p&&"useEffect_fake_response"!==p||(m.confidence=Math.max(85,m.confidence||85)),"test_array_variables"===p&&(m.confidence=Math.max(85,m.confidence||85));const f=Ve(m);f.confidence&&f.confidence>=40&&t.push(f)}}),t},$e=e=>{const n=e.code||"",t=e.description.toLowerCase();return n.includes("useState")&&n.includes("[")?{violation:e,fixType:"database_query",difficulty:"easy",confidence:90,estimatedTime:"10 min",codeSnippet:Le(),explanation:"Replace hardcoded array with data fetched from Supabase. This ensures your app displays real, up-to-date information.",requiredFiles:[]}:n.includes("useState")&&/\d+/.test(n)?{violation:e,fixType:"database_query",difficulty:"easy",confidence:85,estimatedTime:"5 min",codeSnippet:ze(),explanation:"Replace hardcoded count with a real database count query. This provides accurate metrics.",requiredFiles:[]}:n.includes(".map(")||t.includes("map")?{violation:e,fixType:"state_hook",difficulty:"medium",confidence:75,estimatedTime:"15 min",codeSnippet:Ue(),explanation:"Convert inline array to state-based data loading. This allows dynamic content updates.",requiredFiles:[]}:/\d{2,}/.test(n)&&!n.includes("useState")?{violation:e,fixType:"prop_passing",difficulty:"easy",confidence:80,estimatedTime:"10 min",codeSnippet:Be(e),explanation:"Convert hardcoded number to dynamic prop. This makes the component reusable with real data.",requiredFiles:[]}:t.includes("test")||t.includes("example")?{violation:e,fixType:"database_query",difficulty:"easy",confidence:95,estimatedTime:"5 min",codeSnippet:He(),explanation:"Replace test data with real user data from Supabase Auth.",requiredFiles:[]}:n.includes("Array.fill")||n.includes("Math.random")?{violation:e,fixType:"database_query",difficulty:"medium",confidence:70,estimatedTime:"20 min",codeSnippet:Ke(),explanation:"Replace generated mock data with actual database records. Create the necessary database table if it doesn't exist.",requiredFiles:["Database migration needed"]}:{violation:e,fixType:"database_query",difficulty:"medium",confidence:60,estimatedTime:"15 min",codeSnippet:We(),explanation:"Replace mock data with real database query. Review your data model and fetch appropriate data.",requiredFiles:[]}},Le=e=>"// Step 1: Import Supabase client\nimport { supabase } from '@/integrations/supabase/client';\n\n// Step 2: Replace useState with empty array\nconst [data, setData] = useState([]);\n\n// Step 3: Fetch real data on component mount\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data: fetchedData, error } = await supabase\n      .from('your_table_name') // ⚠️ Change to your actual table\n      .select('*')\n      .order('created_at', { ascending: false });\n    \n    if (error) {\n      console.error('Error fetching data:', error);\n      return;\n    }\n    \n    setData(fetchedData || []);\n  };\n  \n  fetchData();\n}, []);",ze=e=>"// Fetch real count from database\nconst [count, setCount] = useState(0);\n\nuseEffect(() => {\n  const fetchCount = async () => {\n    const { count: totalCount, error } = await supabase\n      .from('your_table_name') // ⚠️ Change to your actual table\n      .select('*', { count: 'exact', head: true });\n    \n    if (error) {\n      console.error('Error fetching count:', error);\n      return;\n    }\n    \n    setCount(totalCount || 0);\n  };\n  \n  fetchCount();\n}, []);",Ue=e=>"// Step 1: Create state for your data\nconst [items, setItems] = useState([]);\n\n// Step 2: Fetch data\nuseEffect(() => {\n  const loadItems = async () => {\n    const { data, error } = await supabase\n      .from('your_table_name')\n      .select('*');\n    \n    if (data) setItems(data);\n  };\n  loadItems();\n}, []);\n\n// Step 3: Use in JSX\n{items.map((item) => (\n  <div key={item.id}>\n    {/* Your content here */}\n  </div>\n))}",Be=e=>{let n="VALUE";const t=e.description.match(/number\s+"(\d+)"/i);if(t)n=t[1];else if(e.code){const t=e.code.match(new RegExp("(?<![-\\w])(\\d+)(?![-\\w])"));t&&(n=t[1])}return`// Step 1: Convert to component prop\ninterface Props {\n  count: number; // Make it dynamic\n}\n\nexport const YourComponent = ({ count }: Props) => {\n  return <div>{count}</div>;\n};\n\n// Step 2: Pass real data from parent\n<YourComponent count={realCountFromDatabase} />\n\n// Previous hardcoded value: ${n}`},He=e=>"// Fetch real user data from Supabase Auth\nconst { data: { user }, error } = await supabase.auth.getUser();\n\nif (user) {\n  const email = user.email;\n  const name = user.user_metadata?.name;\n  // Use real user data here\n}",Ke=e=>"// ❌ Remove mock data generation (Array.fill, Math.random, etc.)\n\n// ✅ Fetch real records from database\nconst { data, error } = await supabase\n  .from('your_table_name')\n  .select('*')\n  .limit(50); // Adjust limit as needed\n\n// If table doesn't exist yet, create it:\n// 1. Go to Supabase Dashboard → SQL Editor\n// 2. Create your table with proper columns\n// 3. Enable RLS policies for security\n// 4. Then fetch real data here",We=e=>"// Generic database query template\nconst { data, error } = await supabase\n  .from('your_table_name') // ⚠️ Replace with your table\n  .select('*')\n  .order('created_at', { ascending: false });\n\nif (error) {\n  console.error('Database error:', error);\n  return;\n}\n\n// Use 'data' in your component\nconsole.log('Fetched data:', data);",Ge=(e,n)=>{const t=e.mockDataViolations,a=t.filter(e=>"critical"===e.severity).length,s=t.filter(e=>"high"===e.severity).length,o=t.filter(e=>"medium"===e.severity).length,i=t.filter(e=>"low"===e.severity).length,r=t.filter(e=>{var n,t;const a=e.description.toLowerCase();return!(null==(n=e.file)?void 0:n.includes("supabase/functions"))&&!(null==(t=e.file)?void 0:t.includes("database"))&&(a.includes("ui")||a.includes("component")||a.includes("jsx")||a.includes("tsx"))}),c=t.filter(e=>{var n;const t=e.description.toLowerCase();return(null==(n=e.file)?void 0:n.includes("supabase/functions"))||t.includes("edge function")||t.includes("api")||t.includes("function")}),l=t.filter(e=>{var n;const t=e.description.toLowerCase();return(null==(n=e.file)?void 0:n.includes("database"))||t.includes("database")||t.includes("table")||t.includes("supabase")}),d=15*a+8*s+3*o+1*i,u=Math.max(0,Math.min(100,100-d)),m=Math.max(0,100-5*r.length),p=Math.max(0,100-8*c.length),f=Math.max(0,100-10*l.length),g=qe(u),h=n?u>n+5?"improving":u<n-5?"declining":"stable":void 0,b=Ye({criticalIssues:a,highIssues:s,mediumIssues:o,frontendViolations:r.length,backendViolations:c.length,databaseViolations:l.length,overall:u});return{overall:Math.round(u),grade:g,categories:{frontend:{score:Math.round(m),violations:r.length},backend:{score:Math.round(p),violations:c.length},database:{score:Math.round(f),violations:l.length}},trend:h,recommendations:b,criticalIssues:a,highIssues:s,mediumIssues:o,lowIssues:i}},qe=e=>e>=98?"A+":e>=90?"A":e>=80?"B":e>=70?"C":e>=60?"D":"F",Ye=e=>{const n=[];return e.criticalIssues>0&&n.push(`🚨 URGENT: Fix ${e.criticalIssues} critical issue${e.criticalIssues>1?"s":""} immediately (Array.fill, Math.random, hardcoded API responses)`),e.highIssues>5&&n.push(`⚠️ HIGH PRIORITY: Address ${e.highIssues} high-severity mock data violations`),e.databaseViolations>0&&n.push(`💾 Database: Review ${e.databaseViolations} database mock data issue${e.databaseViolations>1?"s":""} - ensure all queries fetch real data`),e.backendViolations>0&&n.push(`🔧 Backend: Fix ${e.backendViolations} edge function mock data issue${e.backendViolations>1?"s":""} - replace with real API calls`),e.frontendViolations>5&&n.push(`🎨 Frontend: Replace ${e.frontendViolations} hardcoded UI elements with dynamic data`),e.overall<50?n.push("📊 Your project has significant mock data. Consider a systematic refactor to use real database queries."):e.overall<80?n.push("✨ Good progress! Focus on remaining high-priority issues to reach production-ready status."):e.overall>=95&&n.push("🎉 Excellent! Your project is production-ready with minimal mock data."),e.mediumIssues>10&&n.push(`📝 Medium Priority: ${e.mediumIssues} issues remaining - tackle these after critical/high issues`),n.slice(0,5)},Je=l.createClient("https://tzowmzqfbicbyvikhdwy.supabase.co","eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InR6b3dtenFmYmljYnl2aWtoZHd5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTEzODA4OTEsImV4cCI6MjA2Njk1Njg5MX0.ISwDLrKZV8Ug6Ej4puA5miPHBvrN70osv0hv-hHfc8U",{auth:{storage:localStorage,persistSession:!0,autoRefreshToken:!0}});function Xe(){const e=new Set;document.querySelectorAll('a[href^="/"]').forEach(n=>{const t=n.getAttribute("href");t&&t.startsWith("/")&&!t.includes("#")&&e.add(t.split("?")[0])});document.querySelectorAll('[data-discover-link], [href^="/"]').forEach(n=>{const t=n.getAttribute("href");t&&t.startsWith("/")&&!t.includes("#")&&e.add(t.split("?")[0])});["/","/dashboard","/profile","/settings","/moderator","/admin","/supabase-monitoring","/qa/audit","/ai-discovery","/ai-learning","/chat-hub","/discussion/general","/memory-center","/personal-ai","/research/library","/ai-beacon/register","/ai-discovery-observatory","/ai-social-dynamics","/ai-meta-learning","/real-ai-integration","/ai-feedback-processor","/lovable-tools-builder"].forEach(n=>e.add(n));const n=Array.from(e).sort();return console.log(`🔍 getAllRoutes(): Found ${n.length} routes:`,n),n}async function Qe(){console.log("🔍 Detecting project size...");const e=Xe().length,n=await async function(){try{const{data:n,error:t}=await Je.rpc("get_public_tables");if(t||!n)return console.warn("Could not detect database size, defaulting to small"),"small";const a=Array.isArray(n)?n.length:0;let s=0;const o=Array.isArray(n)?n.slice(0,5):[];for(const r of o){const n="string"==typeof r?r:r.table_name;if(n)try{const{count:e}=await Je.from(n).select("*",{count:"exact",head:!0});s+=e||0}catch(e){continue}}const i=s/Math.max(o.length,1)*a;return console.log(`📊 Database: ${a} tables, ~${Math.round(i)} rows`),a>50||i>1e4?"large":a>10||i>1e3?"medium":"small"}catch(n){return console.error("Error detecting database size:",n),"small"}}(),t=function(){const e=document.querySelectorAll('a[href^="/"]'),n=new Set;e.forEach(e=>{const t=e.getAttribute("href");t&&t.startsWith("/")&&!t.includes("#")&&n.add(t.split("?")[0])});const t=n.size,a=4*t;return console.log(`📊 Estimated ${t} routes → ~${a} source files`),a}();let a,s=0;e>50?s+=2:e>20&&(s+=1),"large"===n?s+=2:"medium"===n&&(s+=1),t>500?s+=2:t>200&&(s+=1),a=s>=4?"large":s>=2?"medium":"small";const o={routeCount:e,databaseSize:n,estimatedSourceFiles:t,score:s,size:a};return console.log("📊 Project Size Detection:",o),o}const Ze={small:{routes:{maxRoutes:100,timeoutPerRoute:3e3,totalTimeout:3e5,batchSize:20,enableProgressSave:!1},database:{rowsPerTable:200,timeout:6e4,intelligentSampling:!1},sourceFiles:{rootPath:"/workspace/src",includeEdgeFunctions:!0,includeConfigFiles:!0,fileTypes:[".tsx",".ts",".jsx",".js"],maxFiles:2e3,batchSize:500,timeout:12e4}},medium:{routes:{maxRoutes:50,timeoutPerRoute:3e3,totalTimeout:18e4,batchSize:10,enableProgressSave:!0},database:{rowsPerTable:100,timeout:12e4,prioritizeTables:["users","products","orders","ai_hotel_rooms","profiles"],intelligentSampling:!0},sourceFiles:{rootPath:"/workspace/src",includeEdgeFunctions:!0,includeConfigFiles:!1,fileTypes:[".tsx",".ts",".jsx",".js"],maxFiles:1e3,batchSize:200,timeout:18e4}},large:{routes:{maxRoutes:30,timeoutPerRoute:2e3,totalTimeout:12e4,batchSize:5,enableProgressSave:!0},database:{rowsPerTable:50,timeout:18e4,prioritizeTables:["users","products","orders"],onlyPrioritizedTables:!0,showWarning:!0,intelligentSampling:!0},sourceFiles:{rootPath:"/workspace/src",includeEdgeFunctions:!1,includeConfigFiles:!1,fileTypes:[".tsx",".ts"],maxFiles:500,batchSize:100,timeout:18e4}}},en={files:[/scanPatterns\.ts$/,/@mockdetector\/widget/,/src\/utils\/confidenceScoring\.ts$/,/src\/utils\/contextualAutoFix\.ts$/,/src\/utils\/violationScoring\.ts$/,/src\/utils\/scanPatterns\.ts$/,/src\/utils\/databasePatterns\.ts$/,/src\/utils\/reactPatterns\.ts$/,/src\/utils\/smartWhitelist\.ts$/,/src\/hooks\/useClientSourceScanner\.ts$/,/src\/hooks\/useDatabaseScanner\.ts$/,/src\/hooks\/useMockDetection\.ts$/,/src\/components\/MockDetectorFloatingBubble\.tsx$/,/src\/components\/MockDetectorWidget\.tsx$/,/\.config\.(ts|js)$/,/tailwind\.config/,/vite\.config/,/\.types\.ts$/],codePatterns:[/VITE_SUPABASE_PUBLISHABLE_KEY/,/VITE_SUPABASE_ANON_KEY/,/VITE_SUPABASE_URL/,/SUPABASE_PUBLISHABLE_KEY.*=.*["']eyJ/,/\.from\(['"][\w_]+['"]\)/,/\.select\(['"*'"]?\)/,/\.insert\(/,/\.update\(/,/\.limit\(\d+\)/,/\.order\(/,/\.eq\(['"][\w_]+['"]/,/auth\.getUser\(\)/,/auth\.getSession\(\)/,/auth\.signIn/,/auth\.signOut/,/^import\s+/,/^export\s+/,/^interface\s+/,/^type\s+\w+\s*=/,/CRITICAL.*REAL.*AUTHENTIC/,/never\s+demo\/fake\s+data/i,/authentic.*systems.*from.*day.*one/i]},nn=new Map,tn=new Map;function an(e){if(tn.has(e))return tn.get(e);const n=en.codePatterns.some(n=>n.test(e));return tn.size<1e3&&tn.set(e,n),n}const sn=()=>{const[e,n]=t.useState(!1),[a,s]=t.useState(0),[o,i]=t.useState(0),[r,c]=t.useState(0),l=(e,n)=>{const t=[],a=e.split("\n"),s=(o=n).endsWith(".tsx")||o.endsWith(".ts")||o.endsWith(".jsx")||o.endsWith(".js")?o.replace(/^\/+/,""):(console.warn(`⚠️ Invalid file path detected: ${o}`),o);var o;if(function(e){if(!e)return!1;if(nn.has(e))return nn.get(e);const n=en.files.some(n=>n.test(e));return nn.set(e,n),n}(s))return console.log(`✓ Skipping whitelisted file: ${s}`),[];Pe.forEach(({pattern:n,severity:o,description:i})=>{const r=e.matchAll(new RegExp(n,"g"));for(const c of r){if(!c[0])continue;const n=e.substring(0,c.index||0).split("\n").length,r=a[n-1];if(r&&an(r))continue;const l=Math.max(0,n-5),d=Math.min(a.length,n+5),u=a.slice(l,d).join("\n");t.push({type:"mock_data",severity:o,description:i,code:u,file:s.replace("/src/","src/"),line:n,fix:"Replace mock data with real data from your database or API"})}}),Ae.forEach(({pattern:n,severity:o,description:i})=>{const r=e.matchAll(new RegExp(n,"g"));for(const c of r){if(!c[0])continue;const n=e.substring(0,c.index||0).split("\n").length,r=a[n-1];if(r&&an(r))continue;const l=Math.max(0,n-5),d=Math.min(a.length,n+5),u=a.slice(l,d).join("\n");t.push({type:"mock_data",severity:o,description:i,code:u,file:s.replace("/src/","src/"),line:n,fix:"Replace static array with data fetched from your database"})}});const i=Oe(e,s);t.push(...i);const r=((e,n)=>{const t=[],a=e.split("\n");return a.forEach((e,s)=>{const o=s+1,i=e.trim();if(/\/\/.*(?:TODO|FIXME).*(?:mock|test|demo|sample|fake|hardcoded|placeholder)/gi.test(i)){const e=Math.max(0,s-2),i=Math.min(a.length,s+3),r=a.slice(e,i).join("\n");t.push({type:"mock_data",severity:"medium",description:"TODO/FIXME comment about mock data - needs cleanup",code:r,file:n.replace("/src/","src/"),line:o,fix:"Address this TODO comment by replacing mock data with real data"})}}),t})(e,s);return t.push(...r),t};return{scanProjectFiles:async e=>{n(!0),s(0);const t=performance.now();let a=null,o=!1;try{const e=Object.assign({"/src/components/MockDetectorFloatingBubble.tsx":()=>Promise.resolve().then(()=>Vn).then(e=>e.default),"/src/components/MockDetectorInfo.tsx":()=>Promise.resolve().then(()=>Fn).then(e=>e.default),"/src/components/MockDetectorSettings.tsx":()=>Promise.resolve().then(()=>On).then(e=>e.default),"/src/components/MockDetectorWidget.tsx":()=>Promise.resolve().then(()=>$n).then(e=>e.default),"/src/components/ScanSettings.tsx":()=>Promise.resolve().then(()=>Ln).then(e=>e.default),"/src/components/ui/alert.tsx":()=>Promise.resolve().then(()=>zn).then(e=>e.default),"/src/components/ui/badge.tsx":()=>Promise.resolve().then(()=>Un).then(e=>e.default),"/src/components/ui/button.tsx":()=>Promise.resolve().then(()=>Bn).then(e=>e.default),"/src/components/ui/card.tsx":()=>Promise.resolve().then(()=>Hn).then(e=>e.default),"/src/components/ui/checkbox.tsx":()=>Promise.resolve().then(()=>Kn).then(e=>e.default),"/src/components/ui/collapsible.tsx":()=>Promise.resolve().then(()=>Wn).then(e=>e.default),"/src/components/ui/dialog.tsx":()=>Promise.resolve().then(()=>Gn).then(e=>e.default),"/src/components/ui/input.tsx":()=>Promise.resolve().then(()=>qn).then(e=>e.default),"/src/components/ui/label.tsx":()=>Promise.resolve().then(()=>Yn).then(e=>e.default),"/src/components/ui/progress.tsx":()=>Promise.resolve().then(()=>Jn).then(e=>e.default),"/src/components/ui/scroll-area.tsx":()=>Promise.resolve().then(()=>Xn).then(e=>e.default),"/src/components/ui/select.tsx":()=>Promise.resolve().then(()=>Qn).then(e=>e.default),"/src/components/ui/separator.tsx":()=>Promise.resolve().then(()=>Zn).then(e=>e.default),"/src/components/ui/tabs.tsx":()=>Promise.resolve().then(()=>et).then(e=>e.default),"/src/components/ui/textarea.tsx":()=>Promise.resolve().then(()=>nt).then(e=>e.default),"/src/config.ts":()=>Promise.resolve().then(()=>tt).then(e=>e.default),"/src/config/routes.ts":()=>Promise.resolve().then(()=>at).then(e=>e.default),"/src/config/scan-costs.ts":()=>Promise.resolve().then(()=>st).then(e=>e.default),"/src/hooks/use-toast.ts":()=>Promise.resolve().then(()=>ot).then(e=>e.default),"/src/hooks/useApiKeyValidation.ts":()=>Promise.resolve().then(()=>it).then(e=>e.default),"/src/hooks/useBetaCredits.ts":()=>Promise.resolve().then(()=>rt).then(e=>e.default),"/src/hooks/useDatabaseScanner.ts":()=>Promise.resolve().then(()=>ct).then(e=>e.default),"/src/hooks/useMockDetection.ts":()=>Promise.resolve().then(()=>lt).then(e=>e.default),"/src/hooks/useMockDetectorControl.ts":()=>Promise.resolve().then(()=>dt).then(e=>e.default),"/src/hooks/useMockDetectorSettings.ts":()=>Promise.resolve().then(()=>ut).then(e=>e.default),"/src/hooks/useMockDetectorStorage.ts":()=>Promise.resolve().then(()=>mt).then(e=>e.default),"/src/hooks/useMultiLayerAccessControl.ts":()=>Promise.resolve().then(()=>pt).then(e=>e.default),"/src/hooks/useScanHistory.ts":()=>Promise.resolve().then(()=>ft).then(e=>e.default),"/src/hooks/useSelfScan.ts":()=>Promise.resolve().then(()=>gt).then(e=>e.default),"/src/hooks/useVersionCheck.ts":()=>Promise.resolve().then(()=>ht).then(e=>e.default),"/src/index.ts":()=>Promise.resolve().then(()=>bt).then(e=>e.default),"/src/integrations/supabase/client.ts":()=>Promise.resolve().then(()=>yt).then(e=>e.default),"/src/integrations/supabase/types.ts":()=>Promise.resolve().then(()=>vt).then(e=>e.default),"/src/lib/button-variants.ts":()=>Promise.resolve().then(()=>St).then(e=>e.default),"/src/lib/utils.ts":()=>Promise.resolve().then(()=>xt).then(e=>e.default),"/src/types/database.types.ts":()=>Promise.resolve().then(()=>wt).then(e=>e.default),"/src/types/mockdetector.types.ts":()=>Promise.resolve().then(()=>kt).then(e=>e.default),"/src/types/scanConfig.types.ts":()=>Promise.resolve().then(()=>Nt).then(e=>e.default),"/src/utils/autoFix.ts":()=>Promise.resolve().then(()=>Dt).then(e=>e.default),"/src/utils/confidenceScoring.ts":()=>Promise.resolve().then(()=>Rt).then(e=>e.default),"/src/utils/contextualAutoFix.ts":()=>Promise.resolve().then(()=>Ct).then(e=>e.default),"/src/utils/databasePatterns.ts":()=>Promise.resolve().then(()=>_t).then(e=>e.default),"/src/utils/diagnostics.ts":()=>Promise.resolve().then(()=>Tt).then(e=>e.default),"/src/utils/dynamicLoader.ts":()=>Promise.resolve().then(()=>Et).then(e=>e.default),"/src/utils/healthScore.ts":()=>Promise.resolve().then(()=>Pt).then(e=>e.default),"/src/utils/projectSizeDetection.ts":()=>Promise.resolve().then(()=>It).then(e=>e.default),"/src/utils/reactPatterns.ts":()=>Promise.resolve().then(()=>At).then(e=>e.default),"/src/utils/reportGenerator.ts":()=>Promise.resolve().then(()=>Mt).then(e=>e.default),"/src/utils/scanPatterns.ts":()=>Promise.resolve().then(()=>jt).then(e=>e.default),"/src/utils/smartWhitelist.ts":()=>Promise.resolve().then(()=>Vt).then(e=>e.default),"/src/utils/tableMapping.ts":()=>Promise.resolve().then(()=>Ft).then(e=>e.default),"/src/utils/version.ts":()=>Promise.resolve().then(()=>Ot).then(e=>e.default),"/src/vite-env.d.ts":()=>Promise.resolve().then(()=>$t).then(e=>e.default)}),d=Object.keys(e),u=d.length;c(u),i(0);const m=u<300?18e4:u<1e3?3e5:6e5;console.log(`📁 Client-side scanner found ${u} files to scan`),console.log(`⏱️ Timeout set to ${m/1e3/60} minutes for safety`),a=window.setTimeout(()=>{o=!0,console.warn(`⏱️ Scan timeout after ${m/1e3/60} minutes - returning partial results`)},m);const p=[];let f=0;for(const n of d){if(o){console.warn(`⏱️ Scan timed out after scanning ${f}/${u} files`),console.log(`📊 Returning ${p.length} violations from partial scan`);break}try{const t=await e[n](),a=l(t,n);p.push(...a),f++,i(f),s(f/u*100)}catch(r){console.warn(`⚠️ Could not scan file ${n}:`,r),f++,i(f),s(f/u*100)}}null!==a&&clearTimeout(a);const g=(performance.now()-t)/1e3;return o?console.log(`⚠️ PARTIAL scan complete (timed out): ${p.length} violations found in ${f}/${u} files (${g.toFixed(1)}s)`):console.log(`✅ Client-side scan complete: ${p.length} violations found in ${f} files (${g.toFixed(1)}s)`),n(!1),s(100),i(u),p}catch(r){return console.error("❌ Client-side scanner error:",r),n(!1),null!==a&&clearTimeout(a),[]}},isScanning:e,progress:a,filesScanned:o,totalFiles:r}},on=()=>{const e=a.useNavigate(),[n,s]=t.useState(!1),[o,i]=t.useState(null),[r,c]=t.useState(""),[l,d]=t.useState(!1),[u,m]=t.useState(null),{scanProjectFiles:p,progress:f,filesScanned:g,totalFiles:h}=sn(),b=()=>[],y=()=>{const e=[];let n=document.body.innerText;const t=document.querySelector("[data-mockdetector-ignore]");if(t){const e=t.textContent||"";n=n.replace(e,"")}const a=document.querySelector("[data-sonner-toaster]");if(a){const e=a.textContent||"";n=n.replace(e,"")}const s=n.split("\n"),o=new Set;return s.forEach((n,t)=>{Ie.forEach(({pattern:a,severity:s,description:i})=>{const r=n.matchAll(a);for(const c of r){const a=c[0],r=`${i}-${a}`;if(o.has(r))return;o.add(r),e.push({type:"mock_data",severity:s,line:t+1,code:n.trim(),description:`${i}: "${a}"`,fix:"Verify this claim with real-time data from your database or API"})}})}),e},v=(e,n)=>{const t=[],a=e.split("\n"),s=e=>[/VITE_SUPABASE_PUBLISHABLE_KEY/,/VITE_SUPABASE_URL/,/\.from\(['"][\w_]+['"]\)/,/\.select\(/,/\.limit\(\d+\)/,/^import\s+/,/^export\s+/,/CRITICAL.*REAL.*AUTHENTIC/].some(n=>n.test(e)),o=["MockDetector","Quick Scan","Scan All Routes","Total Issues","Scanned:","Generated by MockDetector","Mock Data Violations","Security Issues","Scan Duration","mock_data","test-data","Role Visibility Problems"];if((e=>{if(!e)return!1;return[/scanPatterns\.ts$/,/mockDetector/i,/databasePatterns\.ts$/,/reactPatterns\.ts$/,/smartWhitelist\.ts$/,/\.config\.(ts|js)$/,/tailwind\.config/,/vite\.config/].some(n=>n.test(e))})(n))return[];Pe.forEach(({pattern:e,severity:i,description:r})=>{a.forEach((a,c)=>{if(!o.some(e=>a.includes(e))&&!s(a)&&e.test(a)){const e={type:"mock_data",severity:i,file:n,line:c+1,code:a.trim(),description:r,fix:"Replace with real data from your database or API",confidence:0};e.confidence=Me(e);const s=Ve(e);s.confidence&&s.confidence>=50&&t.push(s)}})}),Ae.forEach(({pattern:i,severity:r,description:c})=>{const l=e.matchAll(i);for(const d of l){const i=e.substring(0,d.index).split("\n").length,l=a[i-1];if(o.some(e=>null==l?void 0:l.includes(e)))continue;if(l&&s(l))continue;const u={type:"mock_data",severity:r,file:n,line:i,code:(null==l?void 0:l.trim())||d[0].trim(),description:c,fix:"Replace with data fetched from database or API. Use useState/useEffect to load dynamic data.",confidence:0};u.confidence=Me(u);const m=Ve(u);m.confidence&&m.confidence>=50&&t.push(m)}});const i=Oe(e,n);return t.push(...i),t},S=e=>{const n=new Map;return e.forEach(e=>{const t=(e=>{var n;return`${e.type}|${e.description}|${(null==(n=e.code)?void 0:n.substring(0,50))||""}`})(e),a=n.get(t);a?e.route&&e.route!==a.violation.route&&a.routes.add(e.route):n.set(t,{violation:e,routes:new Set(e.route?[e.route]:[])})}),Array.from(n.values()).map(({violation:e,routes:n})=>{if(n.size>1){const t=Array.from(n).join(", ");return{...e,description:`${e.description} (found on ${n.size} routes: ${t})`}}return e})},x=async e=>{console.log("🔍 Starting CLIENT-SIDE source file scan (works in any Lovable project)...");try{console.log("📋 Scan config:",e||"Using defaults");const n=await p(e);return console.log(`✅ Client-side source scan complete: ${n.length} violations found`),n}catch(n){return console.error("❌ Client-side source file scan failed:",n),[]}};return{isScanning:n,scanResult:o,setScanResult:i,runScan:async()=>{s(!0);const e=performance.now();try{console.log("🔍 MockDetector: Starting aggressive deep scan...");const n=[],t=document.body.innerText,a=window.location.pathname,s=v(t,a);console.log("🔍 Phase 3: Scanning for statistical claims...");const o=y(),r=[...n,...s,...o],c=r,l={totalViolations:r.length,mockDataViolations:c,scanDuration:performance.now()-e,scannedAt:new Date};console.log(`✅ MockDetector: Scan complete. Found ${l.totalViolations} violations in ${l.scanDuration.toFixed(0)}ms`);const d=Ge(l,null==u?void 0:u.overall);return m(d),console.log(`📊 Health Score: ${d.overall}/100 (${d.grade})`),i(l),l}catch(n){throw console.error("❌ MockDetector: Scan failed:",n),n}finally{s(!1)}},runMultiRouteScan:async n=>{s(!0);const t=performance.now(),a=window.location.pathname,o=n.length<10?18e4:n.length<30?3e5:6e5;let r=null,l=!1;try{console.log(`🔍 MockDetector: Starting multi-route scan for ${n.length} routes...`),console.log(`📍 Original route: ${a} (will restore after scan)`),console.log(`⏱️ Timeout set to ${o/1e3/60} minutes for safety`),r=window.setTimeout(()=>{l=!0,console.warn(`⏱️ Multi-route scan timeout after ${o/1e3/60} minutes`)},o);const s=[];for(let t=0;t<n.length;t++){if(l){console.warn(`⏱️ Multi-route scan timed out after ${t} routes`),c(`⚠️ Timeout after ${t} routes - returning partial results`);break}const a=n[t],o=Math.round(t/n.length*100),i=`Scanning route ${t+1}/${n.length} (${o}%): ${a}`;console.log(`🔍 ${i}`),c(i),e(a,{replace:!0}),await new Promise(e=>setTimeout(e,2e3));const r=b(),d=document.body.innerText,u=v(d,a),m=y(),p=[...r,...u,...m].map(e=>({...e,route:a})),f=S(p);s.push(...f),console.log(`  ✓ Found ${f.length} unique violations on ${a}`)}null!==r&&clearTimeout(r);const d=S(s),u=d,m=performance.now()-t,p={totalViolations:d.length,mockDataViolations:u,scanDuration:m,scannedAt:new Date};return l?(console.log(`⚠️ PARTIAL multi-route scan: ${p.totalViolations} violations (timed out, ${m.toFixed(0)}ms)`),c("⚠️ Timeout - Partial Results - Restoring route...")):(console.log(`✅ MockDetector: Multi-route scan complete. Found ${p.totalViolations} unique violations across ${n.length} routes`),c("✅ Scan Complete - Restoring original route...")),console.log(`📍 Restoring original route: ${a}`),e(a,{replace:!0}),await new Promise(e=>setTimeout(e,500)),c("✅ Scan Complete"),i(p),p}catch(d){throw console.error("❌ MockDetector: Multi-route scan failed:",d),c("❌ Scan Failed"),null!==r&&clearTimeout(r),console.log(`📍 Restoring original route after error: ${a}`),e(a,{replace:!0}),d}finally{s(!1)}},runDeepScan:async()=>{s(!0),d(!0);const e=performance.now(),n=6e5;let t=null,a=!1;try{console.log("🔍 MockDetector: Starting DEEP SCAN (DOM + Source Files)..."),console.log("⏱️ Timeout set to 10 minutes for safety"),t=window.setTimeout(()=>{a=!0,console.warn("⏱️ Deep scan timeout after 10 minutes")},n),c("Scanning DOM...");const s=[],o=document.body.innerText,r=window.location.pathname,l=v(o,r),d=y();c("Scanning source files (0 files)...");const u=await x(),m=[...s,...l,...d,...u];null!==t&&clearTimeout(t);const p=m,f=performance.now()-e,g={totalViolations:m.length,mockDataViolations:p,scanDuration:f,scannedAt:new Date};return a?console.log(`⚠️ PARTIAL deep scan: ${g.totalViolations} violations (timed out, ${f.toFixed(0)}ms)`):console.log(`✅ DEEP SCAN complete. Found ${g.totalViolations} violations in ${f.toFixed(0)}ms`),console.log(`   - DOM scan: ${s.length+l.length+d.length}`),console.log(`   - Source files: ${u.length}`),c(a?"⚠️ Timeout - Partial Results":"✅ Deep Scan Complete"),i(g),g}catch(o){throw console.error("❌ Deep scan failed:",o),null!==t&&clearTimeout(t),o}finally{s(!1),d(!1)}},runSmartDeepScan:async n=>{s(!0),d(!0);const t=performance.now(),a=window.location.pathname;let o=null,r=!1;try{console.log("🔍 MockDetector: Starting SMART DEEP SCAN..."),c("Analyzing project size...");const s=await Qe(),l=s.size,d=await Xe();console.log(`📊 Project classified as: ${l.toUpperCase()}`),console.log(`   - Routes: ${s.routeCount}`),console.log(`   - Database: ${s.databaseSize}`),console.log(`   - Estimated files: ${s.estimatedSourceFiles}`);const p="small"===l?18e4:"medium"===l?3e5:6e5;console.log(`⏱️ Timeout set to ${p/1e3/60} minutes for ${l} project`),o=window.setTimeout(()=>{r=!0,console.warn(`⏱️ Smart deep scan timeout after ${p/1e3/60} minutes`)},p);const f=Ze[l],g={...f.sourceFiles,...void 0!==(null==n?void 0:n.includeEdgeFunctions)&&{includeEdgeFunctions:n.includeEdgeFunctions},...void 0!==(null==n?void 0:n.includeConfigFiles)&&{includeConfigFiles:n.includeConfigFiles},...(null==n?void 0:n.customScanPath)&&{rootPath:n.customScanPath}};let h=[];const w=d.slice(0,f.routes.maxRoutes);if(w.length>0){const n=w.length===d.length;console.log(`🔍 Scanning ${w.length} routes (${n?"all routes":`first ${f.routes.maxRoutes} of ${d.length}`})...`);for(let t=0;t<w.length;t++){if(r){console.warn(`⏱️ Smart scan timed out after ${t} routes`),c(`⚠️ Timeout after ${t} routes - continuing to source files...`);break}const n=w[t],a=Math.round(t/w.length*100),s=`Scanning route ${t+1}/${w.length} (${a}%): ${n}`;console.log(`🔍 ${s}`),c(s),e(n,{replace:!0}),await new Promise(e=>setTimeout(e,1500));const o=b(),i=document.body.innerText,l=v(i,n),d=y(),u=[...o,...l,...d].map(e=>({...e,route:n}));h.push(...S(u))}e(a,{replace:!0}),await new Promise(e=>setTimeout(e,500))}let k=[];r?console.warn("⏱️ Skipping source file scan due to timeout"):(c("Scanning source files (0 files)..."),k=await x(g)),console.log("📊 Before deduplication:"),console.log(`   - Route violations: ${h.length}`),console.log(`   - Source file violations: ${k.length}`),console.log(`   - Total (with duplicates): ${h.length+k.length}`);const N=S([...h,...k]),D=h.length+k.length-N.length;console.log(`   - Duplicates removed: ${D}`),console.log(`   - Final unique violations: ${N.length}`);const R=N,C={totalViolations:N.length,mockDataViolations:R,scanDuration:performance.now()-t,scannedAt:new Date};null!==o&&clearTimeout(o),r?console.log(`⚠️ PARTIAL smart deep scan for ${l} project (timed out)`):console.log(`✅ SMART DEEP SCAN complete for ${l} project`),console.log(`   - Total violations: ${C.totalViolations}`),console.log(`   - Routes scanned: ${w.length}`),console.log(`   - Route violations: ${h.length}`),console.log(`   - Source file violations: ${k.length}`),console.log(`   - Scan duration: ${C.scanDuration.toFixed(0)}ms`);const _=Ge(C,null==u?void 0:u.overall);return m(_),c(r?"⚠️ Timeout - Partial Results":"✅ Smart Deep Scan Complete"),i(C),C}catch(l){throw console.error("❌ Smart deep scan failed:",l),c("❌ Scan Failed"),null!==o&&clearTimeout(o),l}finally{s(!1),d(!1)}},isDeepScanning:l,currentScanProgress:r,scanCode:v,healthScore:u,generateAutoFixes:()=>o?o.mockDataViolations.map($e):[],sourceFileProgress:f,filesScanned:g,totalFiles:h}},rn=(e="")=>{const n=`${e}mockdetector-bubble-minimized`,a=`${e}mockdetector-bubble-position`;"undefined"!=typeof window&&localStorage.removeItem(a);const[s,o]=t.useState(()=>(e=>{if("undefined"==typeof window)return!1;try{const n=localStorage.getItem(e);return null!==n&&"true"===n}catch(n){return!1}})(n)),[i,r]=t.useState(()=>(e=>{if("undefined"==typeof window)return{x:16,y:300};localStorage.removeItem(e);const n=window.innerWidth-400-16,t=window.innerHeight-600-16,a={x:Math.max(16,n),y:Math.max(100,t)};return console.log("✅ MockDetector starting in BOTTOM RIGHT corner (below header):",{bottomRightPos:a,viewport:{w:window.innerWidth,h:window.innerHeight}}),a})(a));return{isMinimized:s,toggleMinimize:()=>{const n=!s;o(n),localStorage.setItem(`${e}mockdetector-bubble-minimized`,String(n))},minimize:()=>{o(!0),localStorage.setItem(`${e}mockdetector-bubble-minimized`,"true")},maximize:()=>{o(!1),localStorage.setItem(`${e}mockdetector-bubble-minimized`,"false")},position:i,updatePosition:e=>{r(e)}}};function cn(e){const n=JSON.stringify(e).toLowerCase();if(["mock_data_rejected","authentic_only_policy","zero_mock_data","100% authentic","authenticity_level","no_demo_data","real_data_only","production_ready","authentic_communication","legal_compliance","platform_compliance"].some(e=>n.includes(e)))return!1;if(["api.github.com","api.stackexchange.com","api.openai.com","googleapis.com","real_ais_found","api_response_valid","api_metadata","rate_limit","x-ratelimit","response_headers","api_version","github_verified","stackoverflow_verified"].some(e=>n.includes(e)))return!1;if(["_features","_amenities","_config","_settings","_capabilities","_permissions","room_amenities","wellness_benefits","sensory_config","personality_traits","learning_objectives","skill_requirements","expected_outcomes","system_config","platform_settings"].some(e=>n.includes(e)))return!1;if(["metadata","system_info","platform_stats","analytics_data","performance_metrics","audit_log","event_data","notification_settings"].some(e=>n.includes(e)))return!1;return["test_user@","demo_account","fake_email","lorem ipsum","test@example.com",'mock_data": true','is_test_data": true',"sample_user","dummy_data","placeholder_"].some(e=>n.includes(e))}const ln=[{name:"test_email",description:"Test/demo email addresses",severity:"high",test:e=>"string"==typeof e&&/^(test|demo|sample|example|mock|fake)@/i.test(e),getExamples:e=>e},{name:"sequential_names",description:'Sequential numbered names (e.g., "User 1", "Product 2")',severity:"high",test:e=>"string"==typeof e&&/^(user|agent|test|demo|sample|person|member|student|ai|product|item|course|lesson|order|customer|client)\s*#?\d+$/i.test(e),getExamples:e=>e},{name:"placeholder_text",description:"Lorem ipsum and placeholder text",severity:"medium",test:e=>"string"==typeof e&&/lorem\s+ipsum|placeholder|sample\s+text|dummy\s+content|this\s+is\s+a\s+(test|sample|demo)\s+(post|comment|description)/i.test(e),getExamples:e=>e},{name:"mock_phone",description:"Mock phone numbers (555-xxxx pattern)",severity:"high",test:e=>"string"==typeof e&&/(\+1[-.\s]?)?\(?\b555\)?[-.\s]\d{3,4}[-.\s]?\d{4}\b|123[-.\s]456[-.\s]\d{4}|000[-.\s]000[-.\s]\d{4}/i.test(e),getExamples:e=>e},{name:"mock_addresses",description:"Common mock addresses",severity:"medium",test:e=>"string"==typeof e&&/^(123|456|789)\s+(main|elm|oak|maple)\s+(st|street|ave|avenue|rd|road)|^(test|sample|demo)\s+address/i.test(e),getExamples:e=>e},{name:"mock_company_names",description:"Common mock company names",severity:"medium",test:e=>"string"==typeof e&&/^(acme|test|demo|sample|mock|example)\s+(corp|inc|llc|ltd|company|co\.?)|^(test|sample)\s+(business|enterprise)/i.test(e),getExamples:e=>e},{name:"mock_credit_cards",description:"Test credit card numbers",severity:"critical",test:e=>"string"==typeof e&&/^(4242\s*4242|5555\s*5555|3782\s*8224|6011\s*1111)/i.test(e.replace(/-/g," ")),getExamples:e=>e},{name:"mock_zip_codes",description:"Common mock ZIP codes",severity:"low",test:e=>"string"==typeof e&&/^(12345|00000|11111|99999|55555)$/i.test(e),getExamples:e=>e},{name:"mock_prices",description:"Suspiciously round mock prices",severity:"low",test:e=>{if("string"!=typeof e&&"number"!=typeof e)return!1;const n=String(e);return/^(9\.99|19\.99|29\.99|49\.99|99\.99|999\.99|1000|5000|10000|50000|100000)$/.test(n)},getExamples:e=>e},{name:"mock_skus",description:"Mock product SKUs",severity:"medium",test:e=>"string"==typeof e&&/^(sku|prd|prod|item)[-_]?(00)?[01]\d{1,3}$/i.test(e),getExamples:e=>e},{name:"meme_numbers",description:"Common meme/test numbers (42, 69, 1337, 9999)",severity:"low",test:e=>"number"==typeof e&&[42,69,420,1337,9999,12345,54321].includes(e),getExamples:e=>String(e)},{name:"sequential_ids",description:"Sequential IDs in data (1, 2, 3, 4...)",severity:"critical",test:e=>!1},{name:"identical_timestamps",description:"Identical timestamps",severity:"low",test:e=>!1},{name:"test_usernames",description:"Test usernames",severity:"high",test:e=>"string"==typeof e&&/^(test|demo|sample|mock|fake|dummy|admin|system)[-_]?(user|admin|account|profile|member|bot)[-_]?\d*$/i.test(e),getExamples:e=>e},{name:"example_domains",description:"Example domain names",severity:"medium",test:e=>"string"==typeof e&&/@(example|test|demo|sample)\.(com|org|net)/i.test(e),getExamples:e=>e},{name:"hardcoded_dates",description:"Suspiciously common hardcoded dates",severity:"low",test:e=>"string"==typeof e&&/^(2020|2021|2022|2023|2024|2025)-(01-01|12-31)|^1970-01-01|^2000-01-01/i.test(e),getExamples:e=>e},{name:"suspicious_json",description:"Mock data in JSON fields",severity:"medium",test:e=>{if("string"==typeof e)try{return cn(JSON.parse(e))}catch{return!1}return"object"==typeof e&&null!==e&&cn(e)},getExamples:e=>{try{const n="string"==typeof e?JSON.parse(e):e;return JSON.stringify(n,null,2).substring(0,200)}catch{return String(e).substring(0,200)}}}];const dn=()=>{const[e,n]=t.useState(!1),[a,s]=t.useState(""),o=async(e,n=50,t=!1)=>{const a=[];try{let s=[];if(t&&n>=100){const t=Math.floor(n/3),{data:a,error:o}=await Je.from(e).select("*").order("created_at",{ascending:!0}).limit(t);if(o)throw o;const{data:i,error:r}=await Je.from(e).select("*").order("created_at",{ascending:!1}).limit(t);if(r)throw r;const{data:c,error:l}=await Je.from(e).select("*").limit(t);if(l)throw l;s=[...a||[],...i||[],...c||[]],console.log(`  📊 Intelligent sampling: ${s.length} rows from ${e}`)}else{const{data:t,error:a}=await Je.from(e).select("*").limit(n);if(a)throw a;s=t||[]}if(!s||0===s.length)return a;const o=function(e){const n=[];if(e.length<3)return n;const t=Object.keys(e[0]).find(e=>"id"===e||e.endsWith("_id")||"agent_id"===e);if(t){const a=e.map(e=>e[t]).filter(e=>"number"==typeof e);a.length>=3&&a.every((e,n)=>0===n||e===a[n-1]+1)&&n.push({pattern:"sequential_ids",description:`Sequential IDs detected in column "${t}"`,severity:"critical",examples:a.slice(0,5).map(String)})}const a=Object.keys(e[0]).filter(e=>e.includes("created_at")||e.includes("updated_at")||e.includes("timestamp"));for(const s of a){const t=e.map(e=>e[s]).filter(Boolean);if(t.length>=5&&1===new Set(t.map(String)).size){const a=new Date(t[0]),o=((new Date).getTime()-a.getTime())/6e4,i=o/60,r=i/24;if(o<60&&e.length<100)continue;if(e.length<20)continue;if(e.length<=50&&i<24)continue;let c="medium",l="";r>7?(c="high",l=`${r.toFixed(0)} days ago`):i>24?(c="medium",l=`${i.toFixed(0)} hours ago`):l=`${o.toFixed(0)} minutes ago`,e.length>=100&&(c="high"===c?"critical":"high"),n.push({pattern:"identical_timestamps",description:`All ${t.length} rows have identical "${s}" from ${l} (likely seed data)`,severity:c,examples:[String(t[0])]})}}return n}(s);for(const n of o){const t={table:e,column:"table_level",pattern:n.pattern,severity:n.severity,description:n.description,examples:n.examples,affectedRows:s.length,confidence:0};t.confidence=Me(t),n.description.includes("identical")&&n.description.includes("days ago")&&(t.confidence=Math.max(75,t.confidence));const o=Ve(t);o.confidence>=40&&a.push(o)}const i=Object.keys(s[0]);for(const n of i)for(const t of ln){const o=[];for(const e of s){const a=e[n];if(null!=a&&t.test(a)){const e=t.getExamples?t.getExamples(a):String(a);if(o.includes(e)||o.push(e),o.length>=5)break}}if(o.length>0){const s={table:e,column:n,pattern:t.name,severity:t.severity,description:t.description,examples:o,affectedRows:o.length,confidence:0};s.confidence=Me(s),(t.description.includes("meme")||t.description.includes("test numbers"))&&(s.confidence=Math.max(70,s.confidence)),t.description.includes("round")&&t.description.includes("prices")&&(s.confidence=Math.max(65,s.confidence));const i=Ve(s);i.confidence>=40&&a.push(i)}}return a}catch(s){return console.error(`Error scanning table ${e}:`,s),a}};return{scanDatabase:async(e=50,t,a=!1,i=!1)=>{n(!0);const r=Date.now(),c=[];let l=0,d=0;try{s("Fetching table list...");const{data:m,error:p}=await Je.rpc("get_public_tables");if(p)throw console.error("❌ Error fetching tables:",p),new Error(`Could not fetch table list: ${p.message}`);let f=Array.isArray(m)?m:[];if(console.log(`📊 Found ${f.length} tables to scan`),t&&t.length>0){const e=f.filter(e=>{const n="string"==typeof e?e:e.table_name;return t.includes(n)});if(a)f=e,console.log(`🎯 Scanning only ${f.length} prioritized tables`);else{const n=f.filter(e=>{const n="string"==typeof e?e:e.table_name;return!t.includes(n)});f=[...e,...n],console.log(`🎯 Prioritizing ${e.length} tables, then ${n.length} others`)}}for(const n of f){const t="string"==typeof n?n:n.table_name;if(t)try{s(`Scanning ${t} (${l+1}/${f.length})...`);const n=await o(t,e,i);c.push(...n),l++,d+=e}catch(u){console.warn(`Could not scan table ${t}:`,u)}}const g=Date.now()-r;return s(""),n(!1),{totalViolations:c.length,violations:c,tablesScanned:l,rowsAnalyzed:d,scanDuration:g,scannedAt:new Date}}catch(m){throw console.error("Database scan error:",m),n(!1),s(""),m}},isScanning:e,progress:a}},un={QUICK_SCAN:2,DATABASE_SCAN:5,SCAN_ALL_ROUTES:8,SMART_DEEP_SCAN:12},mn={},pn={SUPABASE_URL:(()=>{if(void 0==={url:"undefined"==typeof document&&"undefined"==typeof location?require("url").pathToFileURL(__filename).href:"undefined"==typeof document?location.href:d&&"SCRIPT"===d.tagName.toUpperCase()&&d.src||new URL("mockdetector-widget.umd.js",document.baseURI).href}||!(null==mn?void 0:mn.VITE_SUPABASE_URL))return"https://tzowmzqfbicbyvikhdwy.supabase.co"})(),get RECORD_SCAN_ENDPOINT(){return`${this.SUPABASE_URL}/functions/v1/record-scan`},get REPORT_SCAN_RESULT_ENDPOINT(){return`${this.SUPABASE_URL}/functions/v1/report-scan-result`},get SUBMIT_FEEDBACK_ENDPOINT(){return`${this.SUPABASE_URL}/functions/v1/submit-feedback`},get VALIDATE_KEY_ENDPOINT(){return`${this.SUPABASE_URL}/functions/v1/validate-mockdetector-key`},get HEARTBEAT_ENDPOINT(){return`${this.SUPABASE_URL}/functions/v1/widget-heartbeat`},DEFAULT_STORAGE_PREFIX:"mockdetector",PRODUCT_NAME:"MockDetector Pro"},fn="mockdetector-daily-scans",gn="mockdetector-last-reset",hn="mockdetector-feedback-submitted",bn=(e,n,a="")=>{const[s,o]=t.useState(null),[i,r]=t.useState(0),[c,l]=t.useState(0),[d,u]=t.useState(!1),[m,p]=t.useState(()=>function(e=""){if("undefined"==typeof window)return 0;try{const n=localStorage.getItem(`${e}${gn}`),t=(new Date).toDateString();if(n!==t)return localStorage.setItem(`${e}${gn}`,t),localStorage.setItem(`${e}${fn}`,"0"),0;const a=localStorage.getItem(`${e}${fn}`);return null!==a?parseInt(a,10):0}catch(n){return 0}}(a)),f=n??50,[g,h]=t.useState(()=>"undefined"!=typeof window&&"true"===localStorage.getItem(`${a}${hn}`));t.useEffect(()=>{e&&u(!0)},[e]);const b=Math.max(0,f-m);return{credits:null!==s?s:e?"Loading...":"Unlimited (Dev)",serverCredits:s,bonusCredits:i,purchasedCredits:c,dailyScans:m,remainingDailyScans:b,canScan:(n=1)=>e&&null!==s?s>=n&&m<f:m<f,requestScan:async n=>{if(!e){const e=m+1;return p(e),localStorage.setItem(`${a}${fn}`,String(e)),{success:!0,scanToken:crypto.randomUUID(),creditsRemaining:999,scansRemainingToday:f-e,scanCost:un[n]}}try{const t=await fetch(pn.RECORD_SCAN_ENDPOINT,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e,scanType:n,domain:window.location.hostname})}),s=await t.json();if(s.success&&void 0!==s.creditsRemaining){o(s.creditsRemaining),r(s.bonusCredits||0),l(s.purchasedCredits||0),u(!1);const e=m+1;p(e),localStorage.setItem(`${a}${fn}`,String(e))}return s}catch(t){return console.error("Failed to request scan from server:",t),{success:!1,error:"Failed to connect to server. Please try again."}}},reportScanResult:async(n,t,a)=>{if(e&&n)try{const s=await fetch(pn.REPORT_SCAN_RESULT_ENDPOINT,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({scanToken:n,errorsFound:t,scanType:a,apiKey:e})}),i=await s.json();i.success&&i.creditsRefunded&&(o(i.creditsBalance),console.log(`✅ ${i.refundAmount} credits refunded (no errors found)`))}catch(s){console.error("Error reporting scan result:",s)}},maxDailyScans:f,scanCosts:un,isLoadingCredits:d,feedbackSubmitted:g,canSubmitFeedback:()=>!g&&void 0!==e,submitFeedback:async n=>{if(!e)return{success:!1,error:"API key required for feedback"};if(g)return{success:!1,error:"Feedback already submitted"};try{const t=await fetch(pn.SUBMIT_FEEDBACK_ENDPOINT,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e,feedbackText:n})}),s=await t.json();return s.success?(h(!0),localStorage.setItem(`${a}${hn}`,"true"),void 0!==s.newCreditsBalance&&o(s.newCreditsBalance),{success:!0}):{success:!1,error:s.error||s.message}}catch(t){return console.error("Failed to submit feedback:",t),{success:!1,error:"Network error. Please try again."}}},deductCredit:e=>!0,feedbackBonus:80,setCustomCredits:e=>{},initialCredits:50,isAdminMode:!1,enableAdminMode:e=>!1}};const yn="1.8.9",vn=`© ${(new Date).getFullYear()} Anton Fredriksson (Silver). All rights reserved.`;function Sn({title:e,description:n,variant:t}){const a=`${e||""}${n?`: ${n}`:""}`;if("destructive"===t?console.error("🚨 MockDetector:",a):console.log("✅ MockDetector:",a),"undefined"!=typeof document){const e=document.createElement("div");if(e.className="mockdetector-toast "+("destructive"===t?"error":"success"),e.textContent=a,e.style.cssText=`\n      position: fixed;\n      bottom: 20px;\n      right: 20px;\n      background: ${"destructive"===t?"#dc2626":"#16a34a"};\n      color: white;\n      padding: 12px 20px;\n      border-radius: 8px;\n      box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n      z-index: 999999;\n      font-family: system-ui, -apple-system, sans-serif;\n      font-size: 14px;\n      animation: slideIn 0.3s ease-out;\n      max-width: 400px;\n    `,!document.getElementById("mockdetector-toast-styles")){const e=document.createElement("style");e.id="mockdetector-toast-styles",e.textContent="\n        @keyframes slideIn {\n          from { transform: translateX(400px); opacity: 0; }\n          to { transform: translateX(0); opacity: 1; }\n        }\n        @keyframes slideOut {\n          from { transform: translateX(0); opacity: 1; }\n          to { transform: translateX(400px); opacity: 0; }\n        }\n      ",document.head.appendChild(e)}document.body.appendChild(e),setTimeout(()=>{e.style.animation="slideOut 0.3s ease-in",setTimeout(()=>e.remove(),300)},3e3)}}const xn="mockdetector-last-version-check",wn="mockdetector-dismissed-version",kn=yn,Nn=()=>{const[e,n]=t.useState({currentVersion:kn,latestVersion:null,updateAvailable:!1,isChecking:!1,isUpdating:!1,updateError:null,lastChecked:null}),[a,s]=t.useState(()=>{if("undefined"==typeof window)return!1;try{return localStorage.getItem(wn)===kn}catch(e){return!1}}),o=async(t=!1)=>{if(e.isChecking)return{updateAvailable:!1,latestVersion:null};if(!t&&"undefined"!=typeof window)try{const n=localStorage.getItem(xn);if(n){if(Date.now()-new Date(n).getTime()<3e5)return console.log("⏰ MockDetector: Skipping version check (too soon)"),{updateAvailable:e.updateAvailable,latestVersion:e.latestVersion}}}catch(i){}n(e=>({...e,isChecking:!0}));const a=await(async()=>{try{const e=await fetch("https://registry.npmjs.org/@mockdetector/widget/latest");return e.ok&&(await e.json()).version||null}catch(e){return console.error("MockDetector: Version check failed",e),null}})(),o=new Date;if(a){const e=((e,n)=>{const t=e.replace(/^v/,""),a=n.replace(/^v/,""),s=t.split(".").map(e=>parseInt(e.split("-")[0],10)),o=a.split(".").map(e=>parseInt(e.split("-")[0],10));for(let i=0;i<3;i++){if(o[i]>s[i])return!0;if(o[i]<s[i])return!1}return!1})(kn,a);if(n({currentVersion:kn,latestVersion:a,updateAvailable:e,isChecking:!1,isUpdating:!1,updateError:null,lastChecked:o}),"undefined"!=typeof window)try{localStorage.setItem(xn,o.toISOString())}catch(i){}if(e&&"undefined"!=typeof window)try{localStorage.getItem(wn)!==a&&s(!1)}catch(i){}return{updateAvailable:e,latestVersion:a}}return n(e=>({...e,isChecking:!1,lastChecked:o})),{updateAvailable:!1,latestVersion:null}},i=async()=>{if(!e.latestVersion||e.isUpdating)return console.log("🚀 MockDetector: Update skipped -",{hasLatestVersion:!!e.latestVersion,isUpdating:e.isUpdating}),!1;console.log("🚀 MockDetector: Starting update to",e.latestVersion),n(e=>({...e,isUpdating:!0,updateError:null}));try{const n=`https://cdn.jsdelivr.net/npm/@mockdetector/widget@${e.latestVersion}/dist/mockdetector-widget.umd.js`;console.log("🔍 Verifying CDN availability:",n);const a=await fetch(n,{method:"HEAD"});if(!a.ok)throw new Error(`CDN returned ${a.status}: Version might not be published yet`);if(console.log("✅ CDN verification passed"),"undefined"!=typeof window)try{localStorage.setItem("mockdetector-requested-version",e.latestVersion),localStorage.setItem("mockdetector-update-timestamp",Date.now().toString()),console.log("💾 MockDetector: Requested version saved to localStorage")}catch(t){console.warn("⚠️ MockDetector: Failed to save requested version",t)}return console.log("🔄 MockDetector: Reloading page to activate new version..."),window.location.reload(),!0}catch(a){const e=a instanceof Error?a.message:"Unknown error";return console.error("❌ MockDetector: Update failed:",e),n(n=>({...n,isUpdating:!1,updateError:`Update failed: ${e}. Try again in a few minutes.`})),!1}},r=()=>"npm update @mockdetector/widget@latest";return t.useEffect(()=>{o();const e=setInterval(()=>{o()},18e4);return()=>clearInterval(e)},[]),t.useEffect(()=>{e.updateAvailable&&e.latestVersion&&(console.log(`🎉 New version ${e.latestVersion} detected! Starting automatic update...`),i().then(e=>{e?(Sn({title:"🎉 New version ready!",description:"Refreshing page to activate..."}),setTimeout(()=>{console.log("🔄 Auto-reloading to activate new version..."),window.location.reload()},3e3)):console.warn("⚠️ Auto-update failed, will retry on next check")}))},[e.updateAvailable,e.latestVersion]),{...e,isDismissed:a,checkForUpdates:o,performUpdate:i,copyUpdateCommand:async()=>{const e=r();if("undefined"!=typeof navigator&&navigator.clipboard)try{return await navigator.clipboard.writeText(e),!0}catch(n){return console.error("Failed to copy update command:",n),!1}return!1},dismissUpdate:()=>{e.latestVersion&&(localStorage.setItem(wn,e.latestVersion),s(!0))},getUpdateCommand:r,shouldShowNotification:e.updateAvailable&&!a}},Dn=(e="")=>{const n=`${e}mockdetector-permanently-disabled`,a=`${e}mockdetector-session-hidden`,[s,o]=t.useState(()=>(e=>{if("undefined"==typeof window)return!1;try{return"true"===localStorage.getItem(e)}catch(n){return!1}})(n)),[i,r]=t.useState(()=>(e=>{if("undefined"==typeof window)return!1;try{return"true"===sessionStorage.getItem(e)}catch(n){return!1}})(a));return{isPermanentlyDisabled:s,isSessionHidden:i,isVisible:!s&&!i,disablePermanently:()=>{o(!0),localStorage.setItem(n,"true"),console.log("🔴 MockDetector: Permanently disabled")},enable:()=>{o(!1),r(!1),localStorage.removeItem(n),sessionStorage.removeItem(a),console.log("✅ MockDetector: Re-enabled")},hideForSession:()=>{r(!0),sessionStorage.setItem(a,"true"),console.log("👁️ MockDetector: Hidden for this session")},showForSession:()=>{r(!1),sessionStorage.removeItem(a),console.log("👁️ MockDetector: Shown for this session")},getUninstallInstructions:()=>({npm:"npm uninstall @mockdetector/widget",removeImport:"Remove the import and <MockDetectorFloatingBubble /> from your code",alternative:"Or use disablePermanently() to keep installed but disabled"})}},Rn={critical:4,high:3,medium:2,low:1},Cn=m.forwardRef(({className:e,...t},a)=>n.jsx("textarea",{className:pe("flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",e),ref:a,...t}));Cn.displayName="Textarea";const _n=({onClose:e,onHide:a,onDisable:o})=>{const{credits:i,remainingDailyScans:r,maxDailyScans:c,feedbackSubmitted:l,canSubmitFeedback:d,submitFeedback:u,feedbackBonus:m,initialCredits:p=50}=bn(),{disablePermanently:f,getUninstallInstructions:g}=Dn(),{currentVersion:h,latestVersion:b}=Nn(),[y,v]=t.useState(""),S=g();return n.jsxs("div",{className:"space-y-4",children:[n.jsxs("div",{className:"space-y-3",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Coins,{className:"h-4 w-4 text-yellow-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Credit Balance"})]}),n.jsxs("div",{className:"bg-muted/50 rounded-lg p-3 space-y-2 relative",children:[n.jsxs("div",{className:"flex items-center justify-between",children:[n.jsx("span",{className:"text-xs text-muted-foreground",children:"Credits Remaining"}),n.jsxs(be,{className:"bg-yellow-500/10 text-yellow-500 border-yellow-500/20",children:[i," credits"]})]}),n.jsxs("div",{className:"flex items-center justify-between",children:[n.jsx("span",{className:"text-xs text-muted-foreground",children:"Daily Scans"}),n.jsxs(be,{children:[r," / ",c," left"]})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground mt-2 pt-2 border-t border-border/50",children:"Unlimited (Dev)"===i?"💡 Development mode - unlimited scans within daily limit":`💡 New users start with ${p} credits. Earn +${m} by submitting feedback below!`})]})]}),n.jsx("div",{className:"space-y-3",children:n.jsxs("div",{className:"bg-blue-600/20 border border-blue-400/30 rounded-lg p-2.5",children:[n.jsxs("p",{className:"text-xs text-white dark:text-blue-50 leading-relaxed",children:["💾 ",n.jsx("strong",{children:"Simplified Storage"})]}),n.jsxs("ul",{className:"text-[10px] text-blue-100/90 mt-1.5 space-y-0.5 ml-2",children:[n.jsx("li",{children:"✅ Latest scan stored in browser (persists after F5)"}),n.jsx("li",{children:"⚠️ Scans 5MB+: Auto-saves top 4000 errors"}),n.jsx("li",{children:"📥 Full report always downloadable (kept in memory)"}),n.jsx("li",{children:"🔄 Each new scan replaces the old one"})]})]})}),n.jsxs("div",{className:"space-y-3",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.MessageSquare,{className:"h-4 w-4 text-blue-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Share Feedback"})]}),l?n.jsxs("div",{className:"bg-green-500/10 border border-green-500/20 rounded-lg p-3 flex items-center gap-2",children:[n.jsx(s.Check,{className:"h-4 w-4 text-green-500"}),n.jsxs("span",{className:"text-xs text-green-600 dark:text-green-400",children:["Thank you for your feedback! +",m," bonus credits awarded."]})]}):n.jsxs("div",{className:"space-y-2",children:[n.jsxs("p",{className:"text-xs text-muted-foreground",children:["Share your feedback and get +",m," bonus credits! (One-time offer)"]}),n.jsxs("div",{className:"relative",children:[n.jsx(Cn,{placeholder:"What do you think about MockDetector? Any bugs, suggestions, or features you'd like to see?",value:y,onChange:e=>{const n=e.target.value;n.length<=500&&v(n)},className:"min-h-[100px] text-xs resize-none pb-10",maxLength:500}),n.jsxs("div",{className:"absolute bottom-2 right-2 text-xs text-muted-foreground pointer-events-none",children:[y.length,"/",500]})]}),n.jsxs(ge,{onClick:async()=>{if(!y.trim()||y.trim().length<10)return void Sn({title:"Validation Error",description:"Please write at least 10 characters of feedback",variant:"destructive"});if(!d())return void Sn({title:"Already Submitted",description:"Feedback already submitted or API key missing",variant:"destructive"});const e=await u(y);e.success?(Sn({title:`🎉 +${m} Credits Added!`,description:"Thank you for your feedback!"}),v("")):Sn({title:"Error",description:e.error||"Failed to submit feedback. Please try again.",variant:"destructive"})},disabled:!y.trim()||!d(),className:"w-full",size:"sm",children:[n.jsx(s.MessageSquare,{className:"h-3 w-3 mr-2"}),"Send Feedback & Get +",m," Credits"]})]})]}),n.jsxs("div",{className:"space-y-3",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.RefreshCw,{className:"h-4 w-4 text-blue-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Version Info"})]}),n.jsxs("div",{className:"bg-muted/50 rounded-lg p-3 space-y-2",children:[n.jsxs("div",{className:"flex items-center justify-between mb-2",children:[n.jsx("span",{className:"text-xs text-muted-foreground",children:"Current Version"}),n.jsxs(be,{className:"bg-blue-500/10 text-blue-500 border-blue-500/20 font-mono",children:["v",h]})]}),b&&b!==h&&n.jsxs("div",{className:"flex items-center justify-between mb-2",children:[n.jsx("span",{className:"text-xs text-muted-foreground",children:"Latest Version"}),n.jsxs(be,{className:"bg-green-500/10 text-green-500 border-green-500/20 font-mono",children:["v",b]})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground pt-2 border-t border-border/50",children:"✨ Updates happen automatically in the background! No action needed."})]})]}),n.jsxs("div",{className:"space-y-3",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.EyeOff,{className:"h-4 w-4 text-orange-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Widget Control"})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs(ge,{onClick:()=>{console.log("🔴 HIDE BUTTON CLICKED"),Sn({title:"Hidden Until Refresh",description:"MockDetector will reappear after F5"}),null==a||a()},variant:"outline",size:"sm",className:"w-full justify-start text-xs",children:[n.jsx(s.EyeOff,{className:"h-3 w-3 mr-2"}),"Hide Until Refresh (F5)"]}),n.jsxs(ge,{onClick:()=>{confirm('Are you sure? MockDetector will be hidden until you click "Re-enable".')&&(f(),Sn({title:"MockDetector Disabled",description:"Click the green card to re-enable"}),null==o||o())},variant:"outline",size:"sm",className:"w-full justify-start text-xs text-orange-600 hover:text-orange-700",children:[n.jsx(s.Lock,{className:"h-3 w-3 mr-2"}),"Disable Permanently"]})]})]}),n.jsxs("div",{className:"space-y-3",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Trash2,{className:"h-4 w-4 text-red-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Uninstall"})]}),n.jsxs("div",{className:"bg-muted/50 rounded-lg p-3 space-y-2",children:[n.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:"To completely remove MockDetector:"}),n.jsxs("div",{className:"space-y-1.5",children:[n.jsx("div",{className:"bg-background rounded px-2 py-1",children:n.jsx("code",{className:"text-xs text-red-600 dark:text-red-400",children:S.npm})}),n.jsx("p",{className:"text-xs text-muted-foreground",children:S.removeImport}),n.jsx("p",{className:"text-xs text-muted-foreground italic",children:S.alternative})]})]})]}),n.jsxs("div",{className:"space-y-2 pt-2 border-t border-border",children:[n.jsxs("p",{className:"text-xs text-muted-foreground",children:["Built by ",n.jsx("span",{className:"font-semibold text-foreground",children:"Silver"})," (Anton Fredriksson) 🇸🇪"]}),n.jsx("p",{className:"text-xs text-muted-foreground",children:"with AI assistance 🤖"}),n.jsxs("p",{className:"text-xs text-blue-600 dark:text-blue-400",children:["Version: ",yn]}),n.jsx("p",{className:"text-[10px] text-muted-foreground pt-2 border-t border-border/50",children:vn})]}),n.jsx(ge,{onClick:e,variant:"outline",className:"w-full",size:"sm",children:"Close"})]})},Tn=()=>n.jsxs("div",{className:"space-y-4",children:[n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Shield,{className:"h-4 w-4 text-blue-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"What is MockDetector?"})]}),n.jsx("p",{className:"text-xs text-muted-foreground",children:"MockDetector scans your Lovable project for mock and test data that might accidentally end up in production. It checks your code, pages, and database to help you catch hardcoded values, test emails, and placeholder data before you deploy."})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Scan,{className:"h-4 w-4 text-green-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Scan Types"})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"bg-orange-900/20 rounded p-2 space-y-1",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Scan,{className:"h-3 w-3 text-orange-400"}),n.jsx("span",{className:"text-xs font-semibold text-orange-300",children:"Quick Scan This Page"})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground ml-5",children:"Fast scan of the current page you're viewing - checks visible DOM elements for mock data"})]}),n.jsxs("div",{className:"bg-yellow-900/20 rounded p-2 space-y-1",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Sparkles,{className:"h-3 w-3 text-yellow-400"}),n.jsx("span",{className:"text-xs font-semibold text-yellow-300",children:"Smart Deep Scan"})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground ml-5",children:"Analyzes source code files for hardcoded values and patterns - most thorough scan"})]}),n.jsxs("div",{className:"bg-red-900/20 rounded p-2 space-y-1",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Route,{className:"h-3 w-3 text-red-400"}),n.jsx("span",{className:"text-xs font-semibold text-red-300",children:"Scan All Routes"})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground ml-5",children:"Scans multiple predefined routes - good for comprehensive frontend checks"})]}),n.jsxs("div",{className:"bg-purple-900/20 rounded p-2 space-y-1",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Database,{className:"h-3 w-3 text-purple-400"}),n.jsx("span",{className:"text-xs font-semibold text-purple-300",children:"Scan Database"})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground ml-5",children:"Checks Supabase tables for test emails, mock phone numbers, placeholder data"})]})]})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.FileText,{className:"h-4 w-4 text-purple-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Severity Levels"})]}),n.jsxs("div",{className:"space-y-1.5",children:[n.jsxs("div",{className:"flex items-start gap-2",children:[n.jsx("div",{className:"w-3 h-3 rounded-full bg-red-500 mt-0.5"}),n.jsxs("div",{children:[n.jsx("p",{className:"text-xs font-semibold text-red-400",children:"Critical"}),n.jsx("p",{className:"text-xs text-muted-foreground",children:"Security risks - fix before production"})]})]}),n.jsxs("div",{className:"flex items-start gap-2",children:[n.jsx("div",{className:"w-3 h-3 rounded-full bg-orange-500 mt-0.5"}),n.jsxs("div",{children:[n.jsx("p",{className:"text-xs font-semibold text-orange-400",children:"High"}),n.jsx("p",{className:"text-xs text-muted-foreground",children:"Major issues - should be fixed soon"})]})]}),n.jsxs("div",{className:"flex items-start gap-2",children:[n.jsx("div",{className:"w-3 h-3 rounded-full bg-yellow-500 mt-0.5"}),n.jsxs("div",{children:[n.jsx("p",{className:"text-xs font-semibold text-yellow-400",children:"Medium"}),n.jsx("p",{className:"text-xs text-muted-foreground",children:"Quality issues - review and fix"})]})]}),n.jsxs("div",{className:"flex items-start gap-2",children:[n.jsx("div",{className:"w-3 h-3 rounded-full bg-blue-500 mt-0.5"}),n.jsxs("div",{children:[n.jsx("p",{className:"text-xs font-semibold text-blue-400",children:"Low"}),n.jsx("p",{className:"text-xs text-muted-foreground",children:"Minor findings - fix when convenient"})]})]})]})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Download,{className:"h-4 w-4 text-cyan-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Export & Reports"})]}),n.jsxs("div",{className:"space-y-1.5",children:[n.jsx("p",{className:"text-xs text-muted-foreground",children:"After scanning, you can export detailed reports:"}),n.jsxs("ul",{className:"space-y-1 ml-4",children:[n.jsxs("li",{className:"text-xs text-muted-foreground",children:["• ",n.jsx("span",{className:"font-semibold text-foreground",children:"📋 Copy Report"})," - Copy complete report to clipboard"]}),n.jsxs("li",{className:"text-xs text-muted-foreground",children:["• ",n.jsx("span",{className:"font-semibold text-foreground",children:"Download .txt"})," - Download full report as text file"]})]}),n.jsx("div",{className:"bg-blue-900/20 rounded p-2 mt-2",children:n.jsx("p",{className:"text-[10px] text-blue-300",children:"💡 Tip: Both formats are optimized for sharing with AI assistants like ChatGPT, Claude, or Cursor!"})})]})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.AlertTriangle,{className:"h-4 w-4 text-orange-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"What Can MockDetector Find?"})]}),n.jsxs("div",{className:"bg-red-900/10 rounded p-2 space-y-1",children:[n.jsx("p",{className:"text-xs font-semibold text-red-400 mb-1",children:"🔥 Critical Security"}),n.jsxs("ul",{className:"space-y-0.5 ml-3",children:[n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Test credit cards, API keys, credentials"}),n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Hardcoded passwords and auth tokens"})]})]}),n.jsxs("div",{className:"bg-orange-900/10 rounded p-2 space-y-1",children:[n.jsx("p",{className:"text-xs font-semibold text-orange-400 mb-1",children:"🔧 Development Artifacts"}),n.jsxs("ul",{className:"space-y-0.5 ml-3",children:[n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Tunneling services, staging domains"}),n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Private IPs and development ports"})]})]}),n.jsxs("div",{className:"bg-yellow-900/10 rounded p-2 space-y-1",children:[n.jsx("p",{className:"text-xs font-semibold text-yellow-400 mb-1",children:"🐛 Debug Code"}),n.jsxs("ul",{className:"space-y-0.5 ml-3",children:[n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• console.log statements, debugger"}),n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Debug flags and verbose modes"})]})]}),n.jsxs("div",{className:"bg-sky-900/10 rounded p-2 space-y-1",children:[n.jsx("p",{className:"text-xs font-semibold text-sky-400 mb-1",children:"⚛️ React Patterns"}),n.jsxs("ul",{className:"space-y-0.5 ml-3",children:[n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• useState with hardcoded data"}),n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Test emails and Lorem Ipsum"})]})]}),n.jsxs("div",{className:"bg-purple-900/10 rounded p-2 space-y-1",children:[n.jsx("p",{className:"text-xs font-semibold text-purple-400 mb-1",children:"🗄️ Database Mock Data"}),n.jsxs("ul",{className:"space-y-0.5 ml-3",children:[n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Sequential IDs and identical timestamps"}),n.jsx("li",{className:"text-[11px] text-muted-foreground",children:"• Test emails and mock phone numbers"})]})]}),n.jsx("p",{className:"text-[10px] text-muted-foreground italic mt-2",children:"...and 50+ more patterns! See full list in documentation."})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Lightbulb,{className:"h-4 w-4 text-yellow-500"}),n.jsx("h3",{className:"font-semibold text-sm",children:"Tips & Best Practices"})]}),n.jsxs("ul",{className:"space-y-1.5",children:[n.jsxs("li",{className:"text-xs text-muted-foreground",children:["💡 Use ",n.jsx("span",{className:"font-semibold text-foreground",children:"Quick Scan This Page"})," during development for fast feedback"]}),n.jsxs("li",{className:"text-xs text-muted-foreground",children:["💡 Run ",n.jsx("span",{className:"font-semibold text-foreground",children:"Smart Deep Scan"})," before major releases"]}),n.jsxs("li",{className:"text-xs text-muted-foreground",children:["💡 Always ",n.jsx("span",{className:"font-semibold text-foreground",children:"Scan Database"})," before deploying to production"]}),n.jsx("li",{className:"text-xs text-muted-foreground",children:"💡 Download reports to track progress and share with team"})]})]}),n.jsxs("div",{className:"border-t border-muted/20 pt-3 mt-4",children:[n.jsx("p",{className:"text-[10px] text-muted-foreground text-center",children:"MockDetector - Built by Silver (Anton Fredriksson) 🇸🇪 with AI 🤖"}),n.jsx("p",{className:"text-[10px] text-muted-foreground text-center mt-1",children:vn})]})]}),En=e=>{switch(e){case"critical":return 4;case"high":return 3;case"medium":return 2;case"low":return 1;default:return 0}},Pn=e=>En(e.severity)*((e.confidence||50)/100),In=(e,n,t=!1)=>{const a=(null==e?void 0:e.totalViolations)||0,s=(null==n?void 0:n.totalViolations)||0,o=a+s;let i="# MockDetector Pro - Combined Professional Report\n\n";if(e&&(i+=`**Frontend Scan:** ${e.scannedAt.toLocaleString()}\n`,i+=`**Frontend Issues:** ${a}\n`),n&&(i+=`**Database Scan:** ${n.scannedAt.toLocaleString()}\n`,i+=`**Database Issues:** ${s}\n`,i+=`**Tables Scanned:** ${n.tablesScanned}\n`),i+=`**Total Issues:** ${o}\n\n`,0===o)return i+="✅ **No issues found!** Your project is clean.\n",i;const r=[...(null==e?void 0:e.mockDataViolations)||[],...(null==n?void 0:n.violations.map(e=>({type:"mock_data",severity:e.severity,description:`Database: ${e.description}`,code:e.examples.join(", "),file:`${e.table}.${e.column}`,line:0,fix:"Clean database records"})))||[]];i+=(()=>{let e="## 📖 How to Read This Report\n\n";return e+="**Confidence Scores:**\n",e+="- 🟢 85-100%: High confidence - Very likely real mock data\n",e+="- 🟡 60-84%: Medium confidence - Review context carefully\n",e+="- 🔴 Below 60%: Low confidence - Filtered out by default\n\n",e+="**Severity Levels:**\n",e+="- 🔴 Critical: Security risks or data exposure - Fix immediately\n",e+="- 🟠 High: Production-breaking issues - Fix before deployment\n",e+="- 🟡 Medium: Quality/UX issues - Fix in next sprint\n",e+="- 🟢 Low: Minor issues - Nice to have\n\n",e+="**Priority Sorting:**\n",e+="Issues are sorted by priority score (severity × confidence) for smart prioritization.\n\n",e+="---\n\n","## 📖 How to Read This Report\n\n**Confidence Scores:**\n- 🟢 85-100%: High confidence - Very likely real mock data\n- 🟡 60-84%: Medium confidence - Review context carefully\n- 🔴 Below 60%: Low confidence - Filtered out by default\n\n**Severity Levels:**\n- 🔴 Critical: Security risks or data exposure - Fix immediately\n- 🟠 High: Production-breaking issues - Fix before deployment\n- 🟡 Medium: Quality/UX issues - Fix in next sprint\n- 🟢 Low: Minor issues - Nice to have\n\n**Priority Sorting:**\nIssues are sorted by priority score (severity × confidence) for smart prioritization.\n\n---\n\n"})(),i+=(e=>{const n=e.filter(e=>"critical"===e.severity).length,t=e.filter(e=>"high"===e.severity).length,a=e.filter(e=>"medium"===e.severity).length,s=e.filter(e=>"low"===e.severity).length,o=e.filter(e=>(e.confidence||50)>=85).length,i=e.filter(e=>(e.confidence||50)>=60&&(e.confidence||50)<85).length,r=e.filter(e=>(e.confidence||50)<60).length,c=e.map($e).reduce((e,n)=>{var t;return e+parseInt((null==(t=n.estimatedTime.match(/\d+/))?void 0:t[0])||"0")},0),l=Math.floor(c/60),d=c%60;let u="## 📊 Executive Summary\n\n";u+=`**Total Issues Found:** ${e.length}\n`,u+=`**Estimated Total Fix Time:** ${l>0?`${l}h `:""}${d}min\n`,u+=`**Recommended Action:** ${n>0?"🚨 URGENT: Fix critical issues immediately":t>0?"⚠️ Fix high-priority issues before deployment":"✅ Address issues in next sprint"}\n\n`,u+="### Severity Breakdown:\n",n>0&&(u+=`- 🔴 **${n} Critical** (Fix immediately - security/data risks)\n`),t>0&&(u+=`- 🟠 **${t} High** (Fix before production deployment)\n`),a>0&&(u+=`- 🟡 **${a} Medium** (Fix in next sprint)\n`),s>0&&(u+=`- 🟢 **${s} Low** (Nice to have)\n`),u+="\n",u+="### Confidence Breakdown:\n",o>0&&(u+=`- 🟢 **${o} High Confidence** (85-100%) - Definitely fix these\n`),i>0&&(u+=`- 🟡 **${i} Medium Confidence** (60-84%) - Review carefully\n`),r>0&&(u+=`- 🔴 **${r} Low Confidence** (below 60%) - May be false positives\n`),u+="\n";const m=e.sort((e,n)=>Pn(n)-Pn(e)).slice(0,3);return m.length>0&&(u+="### 🎯 Top Priority Fixes:\n",m.forEach((e,n)=>{var t;const a=$e(e),s=(null==(t=e.file)?void 0:t.split("/").pop())||"unknown";u+=`${n+1}. **${e.description}** (${a.estimatedTime}, ${s}:${e.line})\n`}),u+="\n"),u+="---\n\n",u})(r);const c=t?10:1/0;if(e&&e.mockDataViolations.length>0){i+=`## 🚨 Frontend Mock Data Violations (${e.mockDataViolations.length})\n\n`;const n=[...e.mockDataViolations].sort((e,n)=>Pn(n)-Pn(e));if(n.slice(0,c).forEach((e,n)=>{i+=((e,n)=>{const t=$e(e);let a=`\n### ${n}. ${"database_query"===t.fixType?"🗄️ Database Integration Required":"🔧 Code Refactor Needed"}: ${e.description}\n\n`;if(a+=`**Severity:** ${(e=>{switch(e){case"critical":return"🔴";case"high":return"🟠";case"medium":return"🟡";case"low":return"🟢";default:return"⚪"}})(e.severity)} ${e.severity.toUpperCase()}\n`,void 0!==e.confidence){const n=(s=e.confidence)>=85?{level:"very_high",label:"Very High Confidence",color:"text-red-600",emoji:"🔴"}:s>=70?{level:"high",label:"High Confidence",color:"text-orange-600",emoji:"🟠"}:s>=55?{level:"medium",label:"Medium Confidence",color:"text-yellow-600",emoji:"🟡"}:s>=40?{level:"low",label:"Low Confidence",color:"text-blue-500",emoji:"🔵"}:{level:"very_low",label:"Very Low Confidence",color:"text-gray-500",emoji:"⚪"};a+=`**Confidence:** ${n.emoji} ${e.confidence}% ${n.label}\n`,e.reasoning&&(a+=`**Reasoning:** ${e.reasoning}\n`)}var s;a+=`**Business Impact:** ${(e=>{const n=e.description.toLowerCase();return n.includes("credential")||n.includes("api key")||n.includes("token")?"CRITICAL SECURITY RISK: Exposed credentials can lead to data breaches and unauthorized access":n.includes("mock api")||n.includes("test endpoint")?"Development endpoint in production - API calls will fail for real users":n.includes("test email")||n.includes("demo email")?"Users won't receive notifications, password resets, or order confirmations":n.includes("hardcoded")||n.includes("static")?"Outdated data displayed to users - no real-time updates from database":n.includes("test data")||n.includes("mock data")?"Unprofessional appearance - users see fake data instead of real content":n.includes("todo")||n.includes("fixme")?"Incomplete feature - developer reminder indicates unfinished work":"Mock data reduces user trust and product quality"})(e)}\n`,a+=`**Estimated Fix Time:** ${t.estimatedTime}\n`,a+=`**Difficulty:** ${t.difficulty.charAt(0).toUpperCase()+t.difficulty.slice(1)}\n`,a+=`**Priority:** ${(e=>{switch(e.severity){case"critical":return"🚨 Fix IMMEDIATELY (before any deployment)";case"high":return"⚠️ Fix before production release";case"medium":return"📝 Fix in next sprint";case"low":return"💡 Nice to have";default:return"Review and fix when possible"}})(e)}\n\n`;const o=e.line?`${e.line}-${e.line+5}`:"unknown";return a+=`**Location:** \`${e.file}:${o}\`\n\n`,e.code&&(a+=`**Code Context:**\n\`\`\`typescript\n${e.code}\n\`\`\`\n\n`),a+=`**Why This Is Critical:**\n${t.explanation}\n\n`,a+=`**Concrete Fix (Copy & Paste Ready):**\n\`\`\`typescript\n${t.codeSnippet}\n\`\`\`\n\n`,t.requiredFiles&&t.requiredFiles.length>0&&(a+=`**Files to Modify:** ${t.requiredFiles.join(", ")}\n`),a+=`**AI Confidence:** ${t.confidence}%\n\n`,a+="---\n",a})(e,n+1)}),n.length>c){const e=n.length-c;i+=`\n_...and ${e} more frontend violations._\n\n`}}if(n&&n.violations.length>0){i+=`## 🗄️ Database Scan Results (${n.violations.length})\n\n`,i+="⚠️ **Database Scan Disclaimer:** Database violations may include false positives. Each violation includes a confidence score to help you identify likely issues. High confidence (≥85%) violations should be reviewed carefully, while lower confidence items may be legitimate data patterns.\n\n";const e=[...n.violations].sort((e,n)=>En(n.severity)-En(e.severity)),a=t?e.slice(0,5):e.slice(0,10);if(a.forEach((e,n)=>{var t;i+=`${n+1}. ${"critical"===(t=e).severity?"🔴":"high"===t.severity?"🟠":"medium"===t.severity?"🟡":"🟢"} **${t.table}.${t.column}**: ${t.description} (${t.affectedRows} rows, ${t.confidence}% confidence)\n`}),e.length>a.length){const n=e.length-a.length;i+=`\n_...and ${n} more database findings. Download full report for complete details._\n\n`}else i+="\n"}return i+="---\n\n",i+=`**Generated by MockDetector Pro v${yn}**\n`,i+="_Professional-grade combined analysis with AI-powered fix suggestions and confidence scoring_\n\n",t&&(i+="💡 **Tip:** This is a compact view showing first 10 issues. Download complete report for full analysis.\n"),i},An=(e,n,t="mockdetector-combined-report.txt")=>{const a=((e,n)=>In(e,n,!1))(e,n),s=new Blob([a],{type:"text/plain"}),o=URL.createObjectURL(s),i=document.createElement("a");i.href=o,i.download=t,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(o)};function Mn(e){const n=function(e){const n="undefined"!=typeof window?window.location.hostname:"unknown";return e.includes("Domain not authorized")||e.includes("domain")||e.includes("authorized")?{issue:"Domain Authorization Failed",currentDomain:n,possibleCauses:["API key is not authorized for this domain","Domain configuration missing in admin panel","Wildcard (*) was used but specific domain is required"],solutions:[`Add "${n}" to allowed domains in admin panel`,"Or use wildcard (*) for development/testing only","Check API key configuration at admin panel","Verify domain spelling matches exactly"],supportEmail:"fredrikssonanton01@gmail.com"}:e.includes("expired")||e.includes("Expired")?{issue:"API Key Expired",currentDomain:n,possibleCauses:["API key has passed its expiration date","API key has expired"],solutions:["Contact support for key renewal","Request new API key from admin panel"],supportEmail:"fredrikssonanton01@gmail.com"}:e.includes("limit")||e.includes("Limit")?{issue:"Scan Limit Reached",currentDomain:n,possibleCauses:["Daily scan limit exceeded","Too many scans performed today"],solutions:["Wait until tomorrow for limit reset","Contact support for limit increase","Upgrade to higher tier if available"],supportEmail:"fredrikssonanton01@gmail.com"}:null}(e);n?(console.group("[MockDetector] 🔍 Diagnostic Report"),console.error("Issue:",n.issue),console.log("Current Domain:",n.currentDomain),console.log("Possible Causes:"),n.possibleCauses.forEach((e,n)=>console.log(`  ${n+1}. ${e}`)),console.log("Solutions:"),n.solutions.forEach((e,n)=>console.log(`  ${n+1}. ${e}`)),console.log("Support:",n.supportEmail),console.groupEnd()):console.error("[MockDetector] Unknown error:",e)}const jn=["/auth","/login","/signup","/register","/forgot-password","/reset-password"],Vn=Object.freeze(Object.defineProperty({__proto__:null,default:'// ============================================\n// MockDetector Floating Bubble - Full Version\n// ============================================\n// Built by Silver (Anton Fredriksson) 🇸🇪\n// This is the complete widget component\n// ============================================\n\nimport React, { useState, useEffect, useRef } from \'react\';\nimport { useLocation } from \'react-router-dom\';\nimport { Bug, ChevronUp, ChevronDown, Play, Route, Download, Minimize2, GripVertical, Settings, Database, Sparkles, X, Info } from \'lucide-react\';\nimport { Button } from \'./ui/button\';\nimport { Badge } from \'./ui/badge\';\nimport { Card, CardContent } from \'./ui/card\';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from \'./ui/dialog\';\nimport { Progress } from \'./ui/progress\';\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from \'./ui/tabs\';\n\nimport { useMockDetection } from \'../hooks/useMockDetection\';\nimport { useMockDetectorSettings } from \'../hooks/useMockDetectorSettings\';\nimport { useDatabaseScanner } from \'../hooks/useDatabaseScanner\';\nimport { useBetaCredits } from \'../hooks/useBetaCredits\';\nimport { useVersionCheck } from \'../hooks/useVersionCheck\';\nimport { useMockDetectorControl } from \'../hooks/useMockDetectorControl\';\nimport { useMockDetectorStorage } from \'../hooks/useMockDetectorStorage\';\nimport { MockDetectorSettings } from \'./MockDetectorSettings\';\nimport { MockDetectorInfo } from \'./MockDetectorInfo\';\nimport { \n  downloadCombinedReportAsTxt\n} from \'../utils/reportGenerator\';\nimport type { DatabaseScanResult } from \'../types/database.types\';\nimport { useMultiLayerAccessControl } from \'../hooks/useMultiLayerAccessControl\';\nimport { toast } from \'../hooks/use-toast\';\nimport { getAllRoutes } from \'../utils/projectSizeDetection\';\nimport { WIDGET_VERSION } from \'../utils/version\';\nimport { useApiKeyValidation } from \'../hooks/useApiKeyValidation\';\nimport { DEFAULT_HIDDEN_ROUTES } from \'../config/routes\';\n\nexport interface MockDetectorFloatingBubbleProps {\n  apiKey?: string;\n  enableHeartbeat?: boolean;\n  hideOnRoutes?: string[];\n  storagePrefix?: string;\n  validationEndpoint?: string;\n  heartbeatEndpoint?: string;\n}\n\nexport const MockDetectorFloatingBubble: React.FC<MockDetectorFloatingBubbleProps> = ({\n  apiKey,\n  enableHeartbeat = true,\n  hideOnRoutes,\n  storagePrefix = \'\',\n  validationEndpoint,\n  heartbeatEndpoint\n}) => {\n  const location = useLocation();\n  const { \n    isScanning, \n    scanResult, \n    setScanResult, // ✅ FIX: Import setter for clearing results\n    runScan, \n    runMultiRouteScan, \n    runSmartDeepScan, \n    isDeepScanning, \n    currentScanProgress,\n    sourceFileProgress,\n    filesScanned,\n    totalFiles,\n  } = useMockDetection();\n  \n  const { isMinimized, toggleMinimize, position, updatePosition } = useMockDetectorSettings(storagePrefix);\n  \n  // Force initial position to bottom-right\n  useEffect(() => {\n    const bubbleWidth = 400;\n    const bubbleHeight = 600;\n    const margin = 16;\n    const headerHeight = 100;\n    \n    const bottomRightX = window.innerWidth - bubbleWidth - margin;\n    const bottomRightY = window.innerHeight - bubbleHeight - margin;\n    \n    const bottomRightPos = { \n      x: Math.max(margin, bottomRightX), \n      y: Math.max(headerHeight, bottomRightY)\n    };\n    \n    updatePosition(bottomRightPos);\n  }, []);\n  \n  const { scanDatabase, isScanning: isDatabaseScanning, progress: databaseProgress } = useDatabaseScanner();\n  const { canAccessModeratorFeatures } = useMultiLayerAccessControl();\n  \n  // API key validation\n  const { \n    isValid: isApiKeyValid, \n    validationError, \n    dailyScanLimit: apiDailyScanLimit,\n    isLoading: isValidatingApiKey,\n    keyData\n  } = useApiKeyValidation(apiKey, enableHeartbeat, validationEndpoint, heartbeatEndpoint);\n  \n  const { \n    requestScan,\n    reportScanResult\n  } = useBetaCredits(apiKey, apiDailyScanLimit as number | undefined, storagePrefix);\n  \n  const { \n    latestVersion,\n    shouldShowNotification,\n    dismissUpdate,\n  } = useVersionCheck();\n  \n  const { isVisible, isPermanentlyDisabled, enable } = useMockDetectorControl(storagePrefix);\n  const { loadLatestScan } = useMockDetectorStorage(storagePrefix);\n  \n  const [isExpanded, setIsExpanded] = useState(false);\n  const [scanStatus, setScanStatus] = useState<string>(\'Ready to scan\');\n  const [isDragging, setIsDragging] = useState(false);\n  const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });\n  const [showSettingsInfo, setShowSettingsInfo] = useState(false);\n  const [databaseScanResult, setDatabaseScanResult] = useState<DatabaseScanResult | null>(null);\n  const [hiddenUntilRefresh, setHiddenUntilRefresh] = useState(false);\n  const [locallyDisabled, setLocallyDisabled] = useState(false);\n  const [showNavigationWarning, setShowNavigationWarning] = useState(false);\n  const [pendingScanType, setPendingScanType] = useState<\'smart\' | \'routes\' | null>(null);\n  const bubbleRef = useRef<HTMLDivElement>(null);\n\n  // Update scan status\n  useEffect(() => {\n    if (isScanning && currentScanProgress) {\n      if (totalFiles > 0 && filesScanned > 0) {\n        const progressPercent = Math.round(sourceFileProgress);\n        setScanStatus(`Scanning file ${filesScanned}/${totalFiles} (${progressPercent}%)`);\n      } else {\n        setScanStatus(currentScanProgress);\n      }\n    } else if (isDatabaseScanning && databaseProgress) {\n      setScanStatus(databaseProgress);\n    } else if (scanResult) {\n      const totalIssues = scanResult.totalViolations + (databaseScanResult?.totalViolations || 0);\n      if (totalIssues === 0) {\n        setScanStatus(\'✅ All clean!\');\n      } else {\n        setScanStatus(`${totalIssues} issue${totalIssues > 1 ? \'s\' : \'\'} detected`);\n      }\n    } else {\n      setScanStatus(\'Ready to scan\');\n    }\n  }, [scanResult, databaseScanResult, isScanning, isDatabaseScanning, currentScanProgress, databaseProgress, sourceFileProgress, filesScanned, totalFiles]);\n\n  // Auto-restore last scan\n  useEffect(() => {\n    if (!scanResult && !databaseScanResult && !isScanning && !isDeepScanning) {\n      const saved = loadLatestScan();\n      if (saved && \'scanType\' in saved && saved.scanType === \'database\') {\n        setDatabaseScanResult(saved as DatabaseScanResult);\n        toast({\n          title: "Previous scan restored",\n          description: "Database scan loaded successfully",\n        });\n      }\n    }\n  }, [scanResult, databaseScanResult, isScanning, isDeepScanning, loadLatestScan]);\n\n  // Dragging logic\n  const handleMouseDown = (e: React.MouseEvent) => {\n    e.preventDefault();\n    e.stopPropagation();\n    if (!bubbleRef.current) return;\n    const rect = bubbleRef.current.getBoundingClientRect();\n    setDragOffset({\n      x: e.clientX - rect.left,\n      y: e.clientY - rect.top\n    });\n    setIsDragging(true);\n  };\n\n  useEffect(() => {\n    const handleMouseMove = (e: MouseEvent) => {\n      if (!isDragging) return;\n      \n      const newX = e.clientX - dragOffset.x;\n      const newY = e.clientY - dragOffset.y;\n      \n      const maxX = window.innerWidth - 50;\n      const maxY = window.innerHeight - 50;\n      \n      updatePosition({\n        x: Math.max(0, Math.min(newX, maxX)),\n        y: Math.max(0, Math.min(newY, maxY))\n      });\n    };\n\n    const handleMouseUp = () => setIsDragging(false);\n\n    if (isDragging) {\n      document.addEventListener(\'mousemove\', handleMouseMove);\n      document.addEventListener(\'mouseup\', handleMouseUp);\n    }\n\n    return () => {\n      document.removeEventListener(\'mousemove\', handleMouseMove);\n      document.removeEventListener(\'mouseup\', handleMouseUp);\n    };\n  }, [isDragging, dragOffset, updatePosition]);\n\n  // Emergency keyboard shortcut\n  useEffect(() => {\n    const handleKeyboard = (e: KeyboardEvent) => {\n      if (e.ctrlKey && e.shiftKey && e.key === \'M\') {\n        e.preventDefault();\n        enable();\n        toast({\n          title: "🚨 Emergency Re-enable",\n          description: "MockDetector forced back on!",\n        });\n      }\n    };\n    \n    window.addEventListener(\'keydown\', handleKeyboard);\n    return () => window.removeEventListener(\'keydown\', handleKeyboard);\n  }, [enable]);\n\n  // SECURITY: Route-based hiding (v1.2.2)\n  const routesToHide = hideOnRoutes !== undefined ? hideOnRoutes : DEFAULT_HIDDEN_ROUTES;\n  const isHiddenRoute = routesToHide.some(route => \n    location.pathname === route || location.pathname.startsWith(route + \'/\')\n  );\n\n  if (isHiddenRoute) {\n    console.log(\'🚫 MockDetector hidden on route:\', location.pathname);\n    return null;\n  }\n\n  // Access control\n  if (!canAccessModeratorFeatures) return null;\n\n  // Show API key validation error if present\n  if (apiKey && isApiKeyValid === false) {\n    return (\n      <div className="fixed bottom-4 right-4 z-50" data-mockdetector-ignore>\n        <Card className="bg-gradient-to-br from-red-900/95 to-orange-900/95 border-red-500/50 backdrop-blur-sm shadow-lg max-w-sm">\n          <CardContent className="p-4">\n            <div className="flex items-center gap-2 mb-2">\n              <Bug className="h-5 w-5 text-red-400" />\n              <span className="text-white font-medium">MockDetector - API Key Error</span>\n            </div>\n            <p className="text-red-200 text-sm mb-3">{validationError || \'Invalid API key\'}</p>\n            <div className="text-xs text-red-300/70">\n              Please check your API key or contact support at fredrikssonanton01@gmail.com\n            </div>\n          </CardContent>\n        </Card>\n      </div>\n    );\n  }\n\n  // Show loading state while validating API key\n  if (apiKey && isValidatingApiKey) {\n    return (\n      <div className="fixed bottom-4 right-4 z-50" data-mockdetector-ignore>\n        <Card className="bg-gradient-to-br from-orange-900/95 to-red-900/95 border-orange-500/50 backdrop-blur-sm shadow-lg">\n          <CardContent className="p-4">\n            <div className="flex items-center gap-2">\n              <Bug className="h-5 w-5 text-orange-400 animate-pulse" />\n              <span className="text-white text-sm">Validating API key...</span>\n            </div>\n          </CardContent>\n        </Card>\n      </div>\n    );\n  }\n\n  // Show re-enable card if disabled\n  if (locallyDisabled || isPermanentlyDisabled) {\n    return (\n      <div className="fixed bottom-4 right-4 z-50" data-mockdetector-ignore>\n        <Card className="bg-gradient-to-br from-green-900/95 to-emerald-900/95 border-green-500/50 backdrop-blur-sm shadow-lg">\n          <CardContent className="p-2">\n            <Button\n              size="sm"\n              className="bg-green-600 hover:bg-green-700 text-xs h-7 px-3"\n              onClick={() => {\n                setLocallyDisabled(false);\n                enable();\n                toast({ title: "✅ MockDetector Re-enabled" });\n              }}\n            >\n              ✅ Re-enable MockDetector\n            </Button>\n          </CardContent>\n        </Card>\n      </div>\n    );\n  }\n\n  if (hiddenUntilRefresh || !isVisible) return null;\n\n  // Scan handlers\n  const handleScanDatabase = async () => {\n    const scanType = \'DATABASE_SCAN\';\n    \n    // ✅ FAS 2: Reset old results before new scan\n    setScanResult(null);\n    setDatabaseScanResult(null);\n    setScanStatus(\'Starting database scan...\');\n    \n    // Request scan from server\n    const scanResponse = await requestScan(scanType);\n    if (!scanResponse.success) {\n      toast({ title: "Scan Failed", description: "Could not start scan", variant: "destructive" });\n      return;\n    }\n    try {\n      const result = await scanDatabase();\n      setDatabaseScanResult(result);\n      \n      // Report scan result\n      await reportScanResult(scanResponse.scanToken, result.totalViolations, scanType);\n      \n      toast({ title: "✅ Database Scan Complete" });\n    } catch (error) {\n      toast({ title: "Database Scan Failed", variant: "destructive" });\n    }\n  };\n\n  const handleQuickScan = async () => {\n    const scanType = \'QUICK_SCAN\';\n    \n    // ✅ FAS 2: Reset old results before new scan\n    setScanResult(null);\n    setDatabaseScanResult(null);\n    setScanStatus(\'Starting quick scan...\');\n    \n    // Request scan from server (deducts credits)\n    const scanResponse = await requestScan(scanType);\n    if (!scanResponse.success) {\n      toast({ title: "Scan Failed", description: "Could not start scan", variant: "destructive" });\n      return;\n    }\n    try {\n      await runScan();\n      \n      // Report scan result (refunds credits if no errors)\n      if (scanResult) {\n        await reportScanResult(scanResponse.scanToken, scanResult.totalViolations, scanType);\n      }\n      \n      toast({ title: "✅ Quick Scan Complete" });\n    } catch (error) {\n      toast({ title: "Scan Failed", variant: "destructive" });\n    }\n  };\n\n  const handleSmartDeepScan = async () => {\n    const scanType = \'SMART_DEEP_SCAN\';\n    \n    // ✅ FAS 2: Reset old results before new scan\n    setScanResult(null);\n    setDatabaseScanResult(null);\n    setScanStatus(\'Starting smart deep scan...\');\n    \n    // Request scan from server\n    const scanResponse = await requestScan(scanType);\n    if (!scanResponse.success) {\n      toast({ title: "Scan Failed", description: "Could not start scan", variant: "destructive" });\n      return;\n    }\n    try {\n      await runSmartDeepScan();\n      \n      // Report scan result\n      if (scanResult) {\n        await reportScanResult(scanResponse.scanToken, scanResult.totalViolations, scanType);\n      }\n      \n      toast({ title: "✅ Smart Deep Scan Complete" });\n    } catch (error) {\n      toast({ title: "Smart Deep Scan Failed", variant: "destructive" });\n    }\n  };\n\n  const handleScanAllRoutes = async () => {\n    const scanType = \'SCAN_ALL_ROUTES\';\n    \n    // ✅ FAS 2: Reset old results before new scan\n    setScanResult(null);\n    setDatabaseScanResult(null);\n    setScanStatus(\'Starting route scan...\');\n    \n    // Request scan from server\n    const scanResponse = await requestScan(scanType);\n    if (!scanResponse.success) {\n      toast({ title: "Scan Failed", description: "Could not start scan", variant: "destructive" });\n      return;\n    }\n    \n    const routes = getAllRoutes();\n    try {\n      await runMultiRouteScan(routes);\n      \n      // Report scan result\n      if (scanResult) {\n        await reportScanResult(scanResponse.scanToken, scanResult.totalViolations, scanType);\n      }\n      \n      toast({ title: "✅ Multi-Route Scan Complete" });\n    } catch (error) {\n      toast({ title: "Multi-Route Scan Failed", variant: "destructive" });\n    }\n  };\n\n  // ✅ FAS 4: Navigation warning handlers\n  const handleSmartDeepScanWithWarning = () => {\n    const hasSeenWarning = localStorage.getItem(\'mockdetector-navigation-warning-seen\');\n    \n    if (!hasSeenWarning) {\n      setPendingScanType(\'smart\');\n      setShowNavigationWarning(true);\n    } else {\n      handleSmartDeepScan();\n    }\n  };\n\n  const handleScanAllRoutesWithWarning = () => {\n    const hasSeenWarning = localStorage.getItem(\'mockdetector-navigation-warning-seen\');\n    \n    if (!hasSeenWarning) {\n      setPendingScanType(\'routes\');\n      setShowNavigationWarning(true);\n    } else {\n      handleScanAllRoutes();\n    }\n  };\n\n  const confirmNavigationWarning = () => {\n    localStorage.setItem(\'mockdetector-navigation-warning-seen\', \'true\');\n    setShowNavigationWarning(false);\n    \n    if (pendingScanType === \'smart\') {\n      handleSmartDeepScan();\n    } else if (pendingScanType === \'routes\') {\n      handleScanAllRoutes();\n    }\n    setPendingScanType(null);\n  };\n\n  const handleDownloadReport = () => {\n    const timestamp = new Date().toISOString().slice(0, 10);\n    downloadCombinedReportAsTxt(scanResult, databaseScanResult, `mockdetector-report-${timestamp}.txt`);\n    toast({ title: "✅ Report Downloaded", description: `Saved as mockdetector-report-${timestamp}.txt` });\n  };\n\n  const getSeverityColor = () => {\n    if (!scanResult || scanResult.totalViolations === 0) return \'bg-green-500\';\n    if (scanResult.mockDataViolations.some(i => i.severity === \'critical\' || i.severity === \'high\')) return \'bg-orange-500\';\n    return \'bg-yellow-500\';\n  };\n\n  // Minimized view\n  if (isMinimized) {\n    return (\n      <div \n        ref={bubbleRef}\n        className="fixed z-50 transition-all duration-300 select-none"\n        style={{ left: `${position.x}px`, top: `${position.y}px`, cursor: isDragging ? \'grabbing\' : \'grab\' }}\n        data-mockdetector-ignore\n      >\n        <Card \n          className={`${\n            isScanning || isDeepScanning \n              ? \'bg-gradient-to-br from-blue-900/95 to-purple-900/95 animate-pulse border-blue-500/50\'\n              : \'bg-gradient-to-br from-orange-900/95 to-red-900/95 border-orange-500/50\'\n          } backdrop-blur-sm shadow-2xl hover:scale-105 transition-transform`}\n          onMouseDown={handleMouseDown}\n        >\n          <CardContent className="p-2 select-none">\n            <div className="flex items-center gap-2 cursor-pointer" onClick={toggleMinimize}>\n              <div className="relative">\n                <Bug className={`h-5 w-5 ${\n                  isScanning || isDeepScanning ? \'text-blue-400 animate-spin\' : \'text-orange-400\'\n                }`} />\n                {shouldShowNotification && (\n                  <div className="absolute -top-1 -right-1 w-3 h-3 bg-blue-500 rounded-full animate-pulse" />\n                )}\n                {scanResult && scanResult.totalViolations > 0 && (\n                  <div className={`absolute -bottom-1 -right-1 w-3 h-3 ${getSeverityColor()} rounded-full animate-pulse`} />\n                )}\n              </div>\n              {scanResult && scanResult.totalViolations > 0 && (\n                <Badge className={`${getSeverityColor()} text-white text-xs px-1.5 py-0.5`}>\n                  {scanResult.totalViolations}\n                </Badge>\n              )}\n            </div>\n          </CardContent>\n        </Card>\n      </div>\n    );\n  }\n\n  // Expanded view\n  return (\n    <div \n      ref={bubbleRef}\n      className="fixed z-50 transition-all duration-300 select-none"\n      style={{ left: `${position.x}px`, top: `${position.y}px` }}\n      data-mockdetector-ignore\n    >\n      <Card className="bg-gradient-to-br from-orange-900/95 to-red-900/95 border-orange-500/50 backdrop-blur-sm shadow-2xl max-w-sm">\n        <CardContent className="p-3 select-none">\n          {/* Header */}\n          <div className="flex items-center justify-between mb-2">\n            <div \n              className="flex items-center gap-2 cursor-move flex-1"\n              onMouseDown={handleMouseDown}\n              style={{ cursor: isDragging ? \'grabbing\' : \'grab\' }}\n            >\n              <GripVertical className="h-5 w-5 text-orange-400" />\n              <Bug className="h-5 w-5 text-orange-400" />\n              <div>\n                <div className="text-white font-medium text-sm">\n                  MockDetector Pro {apiKey && keyData && (\n                    <span className="text-orange-300 text-[10px]">({keyData.tier})</span>\n                  )}\n                </div>\n                <div className="text-orange-300 text-xs flex items-center gap-1">\n                  {isScanning || isDeepScanning ? (\n                    <>\n                      <div className="w-2 h-2 bg-blue-400 rounded-full animate-pulse" />\n                      {scanStatus}\n                    </>\n                  ) : (\n                    scanStatus\n                  )}\n                </div>\n              </div>\n            </div>\n            <div className="flex items-center gap-1">\n              <Button \n                size="sm" \n                variant="ghost" \n                onClick={() => setShowSettingsInfo(true)}\n                className="hover:bg-orange-500/20 group relative"\n                title="Settings & Info"\n              >\n                <div className="flex items-center gap-1">\n                  <Settings className="h-3.5 w-3.5 text-orange-300 group-hover:text-orange-200 transition-colors" />\n                  <span className="text-orange-300/60 group-hover:text-orange-200/60 text-xs">/</span>\n                  <Info className="h-3.5 w-3.5 text-orange-300 group-hover:text-orange-200 transition-colors" />\n                </div>\n              </Button>\n              <Button size="sm" variant="ghost" onClick={() => setIsExpanded(!isExpanded)}>\n                {isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronUp className="h-4 w-4" />}\n              </Button>\n              <Button size="sm" variant="ghost" onClick={toggleMinimize}>\n                <Minimize2 className="h-3 w-3" />\n              </Button>\n            </div>\n          </div>\n\n          {/* Expanded Content */}\n          {isExpanded && (\n            <div className="mt-3 space-y-3 border-t border-orange-500/30 pt-3">\n              {/* Update notification - Read-only */}\n              {shouldShowNotification && latestVersion && (\n                <div className="bg-blue-500/10 border border-blue-500/20 rounded-lg p-2">\n                  <div className="flex items-center justify-between gap-2">\n                    <p className="text-xs text-blue-600 dark:text-blue-400">\n                      ✨ New version v{latestVersion} detected! Auto-updating in background...\n                    </p>\n                    <Button size="sm" variant="ghost" onClick={dismissUpdate} className="h-5 w-5 p-0">\n                      <X className="h-3 w-3" />\n                    </Button>\n                  </div>\n                </div>\n              )}\n\n              {/* Scan Results Summary */}\n              {((scanResult && scanResult.totalViolations > 0) || (databaseScanResult && databaseScanResult.totalViolations > 0)) && (\n                <div className="bg-gradient-to-r from-orange-900/40 to-red-900/40 border border-orange-500/40 rounded p-2.5 space-y-2">\n                  <div className="flex items-center justify-between">\n                    <span className="text-xs font-semibold text-orange-200">\n                      🔍 Scan Results\n                    </span>\n                    <Badge className={`${getSeverityColor()} text-white text-[10px] px-1.5 py-0.5`}>\n                      {(() => {\n                        const total = (scanResult?.totalViolations || 0) + (databaseScanResult?.totalViolations || 0);\n                        return total > 10 ? \'10+\' : total;\n                      })()} issues\n                    </Badge>\n                  </div>\n                  \n                  {/* Severity Breakdown */}\n                  <div className="grid grid-cols-2 gap-1.5 text-[10px]">\n                    {(() => {\n                      const allViolations = [\n                        ...(scanResult?.mockDataViolations || []),\n                        ...(databaseScanResult?.violations || [])\n                      ];\n                      const critical = allViolations.filter(v => v.severity === \'critical\').length;\n                      const high = allViolations.filter(v => v.severity === \'high\').length;\n                      const medium = allViolations.filter(v => v.severity === \'medium\').length;\n                      const low = allViolations.filter(v => v.severity === \'low\').length;\n                      \n                      return (\n                        <>\n                          {critical > 0 && (\n                            <div className="flex items-center gap-1 bg-red-900/30 rounded px-1.5 py-1">\n                              <div className="w-2 h-2 rounded-full bg-red-500" />\n                              <span className="text-red-200">{critical} Critical</span>\n                            </div>\n                          )}\n                          {high > 0 && (\n                            <div className="flex items-center gap-1 bg-orange-900/30 rounded px-1.5 py-1">\n                              <div className="w-2 h-2 rounded-full bg-orange-500" />\n                              <span className="text-orange-200">{high} High</span>\n                            </div>\n                          )}\n                          {medium > 0 && (\n                            <div className="flex items-center gap-1 bg-yellow-900/30 rounded px-1.5 py-1">\n                              <div className="w-2 h-2 rounded-full bg-yellow-500" />\n                              <span className="text-yellow-200">{medium} Medium</span>\n                            </div>\n                          )}\n                          {low > 0 && (\n                            <div className="flex items-center gap-1 bg-blue-900/30 rounded px-1.5 py-1">\n                              <div className="w-2 h-2 rounded-full bg-blue-500" />\n                              <span className="text-blue-200">{low} Low</span>\n                            </div>\n                          )}\n                        </>\n                      );\n                    })()}\n                  </div>\n                  \n                  {/* Quick tip */}\n                  <p className="text-[9px] text-orange-300/70 italic">\n                    ⚠️ Showing first {Math.min((scanResult?.totalViolations || 0) + (databaseScanResult?.totalViolations || 0), 10)} issues - Download full report below\n                  </p>\n                </div>\n              )}\n\n              {/* Scan progress */}\n              {isDeepScanning && totalFiles > 0 && (\n                <div className="bg-orange-900/30 rounded p-2">\n                  <div className="text-xs">Scanning: {filesScanned}/{totalFiles}</div>\n                  <Progress value={sourceFileProgress} className="h-2 mt-1" />\n                </div>\n              )}\n\n              {/* Scan buttons */}\n              <div className="space-y-2">\n                <Button size="sm" className="w-full bg-orange-600 hover:bg-orange-700" onClick={handleQuickScan} disabled={isScanning || isDatabaseScanning}>\n                  <Play className="h-3 w-3 mr-1" />Quick Scan This Page\n                </Button>\n                <Button size="sm" className="w-full bg-yellow-600 hover:bg-yellow-700" onClick={handleSmartDeepScanWithWarning} disabled={isScanning || isDatabaseScanning}>\n                  <Sparkles className="h-3 w-3 mr-1" />Smart Deep Scan\n                </Button>\n                <Button size="sm" className="w-full bg-red-600 hover:bg-red-700" onClick={handleScanAllRoutesWithWarning} disabled={isScanning || isDatabaseScanning}>\n                  <Route className="h-3 w-3 mr-1" />Scan All Routes\n                </Button>\n                <Button size="sm" className="w-full bg-purple-600 hover:bg-purple-700" onClick={handleScanDatabase} disabled={isScanning || isDatabaseScanning}>\n                  <Database className="h-3 w-3 mr-1" />Scan Database\n                </Button>\n\n                {/* Report export */}\n                {((scanResult && scanResult.totalViolations > 0) || (databaseScanResult && databaseScanResult.totalViolations > 0)) && (\n                  <div className="border-t border-orange-500/30 pt-2">\n                    <Button size="sm" className="w-full bg-green-600 hover:bg-green-700" onClick={handleDownloadReport}>\n                      <Download className="h-3 w-3 mr-1" />📥 Download Full Report (.txt)\n                    </Button>\n                  </div>\n                )}\n              </div>\n            </div>\n          )}\n        </CardContent>\n      </Card>\n\n      {/* Navigation Warning Dialog - FAS 4 */}\n      <Dialog open={showNavigationWarning} onOpenChange={setShowNavigationWarning}>\n        <DialogContent className="max-w-md bg-gradient-to-br from-blue-900/98 to-purple-900/98 border-blue-500/50 text-white">\n          <DialogHeader>\n            <DialogTitle className="flex items-center gap-2 text-blue-100">\n              🔍 Route Scanning Notice\n            </DialogTitle>\n          </DialogHeader>\n          <div className="space-y-3 text-sm text-blue-50">\n            <p>\n              This scan will briefly navigate between your app\'s routes to analyze them for mock data.\n            </p>\n            <div className="bg-blue-500/20 border border-blue-400/30 rounded p-3 space-y-1">\n              <p className="text-blue-100">\n                ✓ Your current page will be restored after scanning\n              </p>\n              <p className="text-blue-100">\n                ✓ This happens in the background\n              </p>\n              <p className="text-blue-100">\n                ✓ Takes ~30-60 seconds for most apps\n              </p>\n            </div>\n            <div className="flex gap-2 pt-2">\n              <Button \n                onClick={confirmNavigationWarning} \n                className="flex-1 bg-blue-600 hover:bg-blue-700 text-white"\n              >\n                Got it, Start Scan\n              </Button>\n              <Button \n                variant="outline" \n                onClick={() => setShowNavigationWarning(false)}\n                className="border-blue-400/50 text-blue-100 hover:bg-blue-500/20"\n              >\n                Cancel\n              </Button>\n            </div>\n            <label className="flex items-center gap-2 text-xs text-blue-200/80 cursor-pointer">\n              <input \n                type="checkbox" \n                className="rounded"\n                onChange={(e) => {\n                  if (e.target.checked) {\n                    localStorage.setItem(\'mockdetector-navigation-warning-seen\', \'true\');\n                  }\n                }} \n              />\n              Don\'t show this again\n            </label>\n          </div>\n        </DialogContent>\n      </Dialog>\n\n      {/* Settings Dialog - FIXED: Proper sizing and scrolling */}\n      <Dialog open={showSettingsInfo} onOpenChange={setShowSettingsInfo}>\n        <DialogContent className="bg-gradient-to-br from-orange-900/98 to-red-900/98 border-orange-500/50 text-white max-w-2xl h-[90vh] max-h-[600px] flex flex-col p-0">\n          <DialogHeader className="flex-shrink-0 px-6 pt-6 pb-4">\n            <DialogTitle className="text-orange-100 flex items-center gap-2">\n              <Bug className="h-5 w-5" />MockDetector v{WIDGET_VERSION}\n            </DialogTitle>\n          </DialogHeader>\n          <Tabs defaultValue="settings" className="flex-1 flex flex-col min-h-0 overflow-hidden">\n            <TabsList className="grid grid-cols-2 mx-6 mb-2 flex-shrink-0">\n              <TabsTrigger value="settings">Settings</TabsTrigger>\n              <TabsTrigger value="info">Info</TabsTrigger>\n            </TabsList>\n            <TabsContent value="settings" className="flex-1 mt-0 overflow-y-auto px-6 pb-6">\n              <div className="space-y-4">\n                <MockDetectorSettings\n                  onClose={() => setShowSettingsInfo(false)}\n                  onHide={() => { setHiddenUntilRefresh(true); setShowSettingsInfo(false); }}\n                  onDisable={() => { setLocallyDisabled(true); setShowSettingsInfo(false); }}\n                />\n              </div>\n            </TabsContent>\n            <TabsContent value="info" className="flex-1 mt-0 overflow-y-auto px-6 pb-6">\n              <div className="space-y-4">\n                <MockDetectorInfo />\n              </div>\n            </TabsContent>\n          </Tabs>\n        </DialogContent>\n      </Dialog>\n    </div>\n  );\n};\n'},Symbol.toStringTag,{value:"Module"})),Fn=Object.freeze(Object.defineProperty({__proto__:null,default:'import React from \'react\';\nimport { Shield, Scan, FileText, Download, AlertTriangle, Lightbulb, Sparkles, Route, Database } from \'lucide-react\';\nimport { COPYRIGHT_TEXT } from \'../utils/version\';\n\nexport const MockDetectorInfo: React.FC = () => {\n  return (\n    <div className="space-y-4">\n      {/* What is MockDetector */}\n      <div className="space-y-2">\n        <div className="flex items-center gap-2">\n          <Shield className="h-4 w-4 text-blue-500" />\n          <h3 className="font-semibold text-sm">What is MockDetector?</h3>\n        </div>\n        <p className="text-xs text-muted-foreground">\n          MockDetector scans your Lovable project for mock and test data that might accidentally end up in production. \n          It checks your code, pages, and database to help you catch hardcoded values, test emails, and placeholder data before you deploy.\n        </p>\n      </div>\n\n      {/* Scan Types */}\n      <div className="space-y-2">\n        <div className="flex items-center gap-2">\n          <Scan className="h-4 w-4 text-green-500" />\n          <h3 className="font-semibold text-sm">Scan Types</h3>\n        </div>\n        <div className="space-y-2">\n          <div className="bg-orange-900/20 rounded p-2 space-y-1">\n            <div className="flex items-center gap-2">\n              <Scan className="h-3 w-3 text-orange-400" />\n              <span className="text-xs font-semibold text-orange-300">Quick Scan This Page</span>\n            </div>\n            <p className="text-[10px] text-muted-foreground ml-5">\n              Fast scan of the current page you\'re viewing - checks visible DOM elements for mock data\n            </p>\n          </div>\n          \n          <div className="bg-yellow-900/20 rounded p-2 space-y-1">\n            <div className="flex items-center gap-2">\n              <Sparkles className="h-3 w-3 text-yellow-400" />\n              <span className="text-xs font-semibold text-yellow-300">Smart Deep Scan</span>\n            </div>\n            <p className="text-[10px] text-muted-foreground ml-5">\n              Analyzes source code files for hardcoded values and patterns - most thorough scan\n            </p>\n          </div>\n          \n          <div className="bg-red-900/20 rounded p-2 space-y-1">\n            <div className="flex items-center gap-2">\n              <Route className="h-3 w-3 text-red-400" />\n              <span className="text-xs font-semibold text-red-300">Scan All Routes</span>\n            </div>\n            <p className="text-[10px] text-muted-foreground ml-5">\n              Scans multiple predefined routes - good for comprehensive frontend checks\n            </p>\n          </div>\n          \n          <div className="bg-purple-900/20 rounded p-2 space-y-1">\n            <div className="flex items-center gap-2">\n              <Database className="h-3 w-3 text-purple-400" />\n              <span className="text-xs font-semibold text-purple-300">Scan Database</span>\n            </div>\n            <p className="text-[10px] text-muted-foreground ml-5">\n              Checks Supabase tables for test emails, mock phone numbers, placeholder data\n            </p>\n          </div>\n        </div>\n      </div>\n\n      {/* Severity Levels */}\n      <div className="space-y-2">\n        <div className="flex items-center gap-2">\n          <FileText className="h-4 w-4 text-purple-500" />\n          <h3 className="font-semibold text-sm">Severity Levels</h3>\n        </div>\n        <div className="space-y-1.5">\n          <div className="flex items-start gap-2">\n            <div className="w-3 h-3 rounded-full bg-red-500 mt-0.5" />\n            <div>\n              <p className="text-xs font-semibold text-red-400">Critical</p>\n              <p className="text-xs text-muted-foreground">Security risks - fix before production</p>\n            </div>\n          </div>\n          <div className="flex items-start gap-2">\n            <div className="w-3 h-3 rounded-full bg-orange-500 mt-0.5" />\n            <div>\n              <p className="text-xs font-semibold text-orange-400">High</p>\n              <p className="text-xs text-muted-foreground">Major issues - should be fixed soon</p>\n            </div>\n          </div>\n          <div className="flex items-start gap-2">\n            <div className="w-3 h-3 rounded-full bg-yellow-500 mt-0.5" />\n            <div>\n              <p className="text-xs font-semibold text-yellow-400">Medium</p>\n              <p className="text-xs text-muted-foreground">Quality issues - review and fix</p>\n            </div>\n          </div>\n          <div className="flex items-start gap-2">\n            <div className="w-3 h-3 rounded-full bg-blue-500 mt-0.5" />\n            <div>\n              <p className="text-xs font-semibold text-blue-400">Low</p>\n              <p className="text-xs text-muted-foreground">Minor findings - fix when convenient</p>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      {/* Export & Reports */}\n      <div className="space-y-2">\n        <div className="flex items-center gap-2">\n          <Download className="h-4 w-4 text-cyan-500" />\n          <h3 className="font-semibold text-sm">Export & Reports</h3>\n        </div>\n        <div className="space-y-1.5">\n          <p className="text-xs text-muted-foreground">\n            After scanning, you can export detailed reports:\n          </p>\n          <ul className="space-y-1 ml-4">\n            <li className="text-xs text-muted-foreground">\n              • <span className="font-semibold text-foreground">📋 Copy Report</span> - Copy complete report to clipboard\n            </li>\n            <li className="text-xs text-muted-foreground">\n              • <span className="font-semibold text-foreground">Download .txt</span> - Download full report as text file\n            </li>\n          </ul>\n          <div className="bg-blue-900/20 rounded p-2 mt-2">\n            <p className="text-[10px] text-blue-300">\n              💡 Tip: Both formats are optimized for sharing with AI assistants like ChatGPT, Claude, or Cursor!\n            </p>\n          </div>\n        </div>\n      </div>\n\n      {/* What Can MockDetector Find - Compressed for brevity */}\n      <div className="space-y-2">\n        <div className="flex items-center gap-2">\n          <AlertTriangle className="h-4 w-4 text-orange-500" />\n          <h3 className="font-semibold text-sm">What Can MockDetector Find?</h3>\n        </div>\n        \n        {/* Critical Security */}\n        <div className="bg-red-900/10 rounded p-2 space-y-1">\n          <p className="text-xs font-semibold text-red-400 mb-1">🔥 Critical Security</p>\n          <ul className="space-y-0.5 ml-3">\n            <li className="text-[11px] text-muted-foreground">• Test credit cards, API keys, credentials</li>\n            <li className="text-[11px] text-muted-foreground">• Hardcoded passwords and auth tokens</li>\n          </ul>\n        </div>\n\n        {/* Development URLs */}\n        <div className="bg-orange-900/10 rounded p-2 space-y-1">\n          <p className="text-xs font-semibold text-orange-400 mb-1">🔧 Development Artifacts</p>\n          <ul className="space-y-0.5 ml-3">\n            <li className="text-[11px] text-muted-foreground">• Tunneling services, staging domains</li>\n            <li className="text-[11px] text-muted-foreground">• Private IPs and development ports</li>\n          </ul>\n        </div>\n\n        {/* Debug Code */}\n        <div className="bg-yellow-900/10 rounded p-2 space-y-1">\n          <p className="text-xs font-semibold text-yellow-400 mb-1">🐛 Debug Code</p>\n          <ul className="space-y-0.5 ml-3">\n            <li className="text-[11px] text-muted-foreground">• console.log statements, debugger</li>\n            <li className="text-[11px] text-muted-foreground">• Debug flags and verbose modes</li>\n          </ul>\n        </div>\n\n        {/* React Patterns */}\n        <div className="bg-sky-900/10 rounded p-2 space-y-1">\n          <p className="text-xs font-semibold text-sky-400 mb-1">⚛️ React Patterns</p>\n          <ul className="space-y-0.5 ml-3">\n            <li className="text-[11px] text-muted-foreground">• useState with hardcoded data</li>\n            <li className="text-[11px] text-muted-foreground">• Test emails and Lorem Ipsum</li>\n          </ul>\n        </div>\n\n        {/* Database */}\n        <div className="bg-purple-900/10 rounded p-2 space-y-1">\n          <p className="text-xs font-semibold text-purple-400 mb-1">🗄️ Database Mock Data</p>\n          <ul className="space-y-0.5 ml-3">\n            <li className="text-[11px] text-muted-foreground">• Sequential IDs and identical timestamps</li>\n            <li className="text-[11px] text-muted-foreground">• Test emails and mock phone numbers</li>\n          </ul>\n        </div>\n\n        <p className="text-[10px] text-muted-foreground italic mt-2">\n          ...and 50+ more patterns! See full list in documentation.\n        </p>\n      </div>\n\n      {/* Tips & Best Practices */}\n      <div className="space-y-2">\n        <div className="flex items-center gap-2">\n          <Lightbulb className="h-4 w-4 text-yellow-500" />\n          <h3 className="font-semibold text-sm">Tips & Best Practices</h3>\n        </div>\n        <ul className="space-y-1.5">\n          <li className="text-xs text-muted-foreground">\n            💡 Use <span className="font-semibold text-foreground">Quick Scan This Page</span> during development for fast feedback\n          </li>\n          <li className="text-xs text-muted-foreground">\n            💡 Run <span className="font-semibold text-foreground">Smart Deep Scan</span> before major releases\n          </li>\n          <li className="text-xs text-muted-foreground">\n            💡 Always <span className="font-semibold text-foreground">Scan Database</span> before deploying to production\n          </li>\n          <li className="text-xs text-muted-foreground">\n            💡 Download reports to track progress and share with team\n          </li>\n        </ul>\n      </div>\n\n      {/* Version Info */}\n      <div className="border-t border-muted/20 pt-3 mt-4">\n        <p className="text-[10px] text-muted-foreground text-center">\n          MockDetector - Built by Silver (Anton Fredriksson) 🇸🇪 with AI 🤖\n        </p>\n        <p className="text-[10px] text-muted-foreground text-center mt-1">\n          {COPYRIGHT_TEXT}\n        </p>\n      </div>\n    </div>\n  );\n};\n'},Symbol.toStringTag,{value:"Module"})),On=Object.freeze(Object.defineProperty({__proto__:null,default:'import React, { useState } from \'react\';\nimport { Badge } from \'./ui/badge\';\nimport { Button } from \'./ui/button\';\nimport { Textarea } from \'./ui/textarea\';\nimport { useBetaCredits } from \'../hooks/useBetaCredits\';\nimport { useMockDetectorControl } from \'../hooks/useMockDetectorControl\';\nimport { useVersionCheck } from \'../hooks/useVersionCheck\';\nimport { WIDGET_VERSION, COPYRIGHT_TEXT } from \'../utils/version\';\nimport { Coins, MessageSquare, EyeOff, Trash2, Lock, Check, RefreshCw } from \'lucide-react\';\nimport { toast } from \'../hooks/use-toast\';\n\ninterface MockDetectorSettingsProps {\n  onClose?: () => void;\n  onHide?: () => void;\n  onDisable?: () => void;\n}\n\nexport const MockDetectorSettings: React.FC<MockDetectorSettingsProps> = ({ \n  onClose, \n  onHide, \n  onDisable\n}) => {\n  const {\n    credits,\n    remainingDailyScans,\n    maxDailyScans,\n    feedbackSubmitted,\n    canSubmitFeedback,\n    submitFeedback,\n    feedbackBonus,\n    initialCredits = 50, // Fallback if not returned\n  } = useBetaCredits();\n\n  const {\n    disablePermanently,\n    getUninstallInstructions,\n  } = useMockDetectorControl();\n\n  const { \n    currentVersion, \n    latestVersion\n  } = useVersionCheck();\n\n  const [feedbackText, setFeedbackText] = useState(\'\');\n  const maxFeedbackLength = 500;\n\n  const handleSendFeedback = async () => {\n    if (!feedbackText.trim() || feedbackText.trim().length < 10) {\n      toast({\n        title: "Validation Error",\n        description: "Please write at least 10 characters of feedback",\n        variant: "destructive"\n      });\n      return;\n    }\n\n    if (!canSubmitFeedback()) {\n      toast({\n        title: "Already Submitted",\n        description: "Feedback already submitted or API key missing",\n        variant: "destructive"\n      });\n      return;\n    }\n\n    const result = await submitFeedback(feedbackText);\n    \n    if (result.success) {\n      toast({\n        title: `🎉 +${feedbackBonus} Credits Added!`,\n        description: "Thank you for your feedback!"\n      });\n      setFeedbackText(\'\');\n    } else {\n      toast({\n        title: "Error",\n        description: result.error || \'Failed to submit feedback. Please try again.\',\n        variant: "destructive"\n      });\n    }\n  };\n\n  const uninstallInstructions = getUninstallInstructions();\n\n  return (\n    <div className="space-y-4">\n      {/* Beta Status Section */}\n      <div className="space-y-3">\n        <div className="flex items-center gap-2">\n          <Coins className="h-4 w-4 text-yellow-500" />\n          <h3 className="font-semibold text-sm">Credit Balance</h3>\n        </div>\n        \n        <div className="bg-muted/50 rounded-lg p-3 space-y-2 relative">\n          <div className="flex items-center justify-between">\n            <span className="text-xs text-muted-foreground">Credits Remaining</span>\n            <Badge className="bg-yellow-500/10 text-yellow-500 border-yellow-500/20">\n              {credits} credits\n            </Badge>\n          </div>\n          \n          <div className="flex items-center justify-between">\n            <span className="text-xs text-muted-foreground">Daily Scans</span>\n            <Badge>\n              {remainingDailyScans} / {maxDailyScans} left\n            </Badge>\n          </div>\n          \n          <p className="text-[10px] text-muted-foreground mt-2 pt-2 border-t border-border/50">\n            {credits === \'Unlimited (Dev)\' \n              ? \'💡 Development mode - unlimited scans within daily limit\'\n              : `💡 New users start with ${initialCredits} credits. Earn +${feedbackBonus} by submitting feedback below!`\n            }\n          </p>\n        </div>\n      </div>\n\n      {/* Storage Info */}\n      <div className="space-y-3">\n        <div className="bg-blue-600/20 border border-blue-400/30 rounded-lg p-2.5">\n          <p className="text-xs text-white dark:text-blue-50 leading-relaxed">\n            💾 <strong>Simplified Storage</strong>\n          </p>\n          <ul className="text-[10px] text-blue-100/90 mt-1.5 space-y-0.5 ml-2">\n            <li>✅ Latest scan stored in browser (persists after F5)</li>\n            <li>⚠️ Scans 5MB+: Auto-saves top 4000 errors</li>\n            <li>📥 Full report always downloadable (kept in memory)</li>\n            <li>🔄 Each new scan replaces the old one</li>\n          </ul>\n        </div>\n      </div>\n\n      {/* Feedback Section */}\n      <div className="space-y-3">\n        <div className="flex items-center gap-2">\n          <MessageSquare className="h-4 w-4 text-blue-500" />\n          <h3 className="font-semibold text-sm">Share Feedback</h3>\n        </div>\n        \n        {feedbackSubmitted ? (\n          <div className="bg-green-500/10 border border-green-500/20 rounded-lg p-3 flex items-center gap-2">\n            <Check className="h-4 w-4 text-green-500" />\n            <span className="text-xs text-green-600 dark:text-green-400">\n              Thank you for your feedback! +{feedbackBonus} bonus credits awarded.\n            </span>\n          </div>\n        ) : (\n          <div className="space-y-2">\n            <p className="text-xs text-muted-foreground">\n              Share your feedback and get +{feedbackBonus} bonus credits! (One-time offer)\n            </p>\n            \n            <div className="relative">\n              <Textarea\n                placeholder="What do you think about MockDetector? Any bugs, suggestions, or features you\'d like to see?"\n                value={feedbackText}\n                onChange={(e) => {\n                  const text = e.target.value;\n                  if (text.length <= maxFeedbackLength) {\n                    setFeedbackText(text);\n                  }\n                }}\n                className="min-h-[100px] text-xs resize-none pb-10"\n                maxLength={maxFeedbackLength}\n              />\n              <div className="absolute bottom-2 right-2 text-xs text-muted-foreground pointer-events-none">\n                {feedbackText.length}/{maxFeedbackLength}\n              </div>\n            </div>\n            \n            <Button\n              onClick={handleSendFeedback}\n              disabled={!feedbackText.trim() || !canSubmitFeedback()}\n              className="w-full"\n              size="sm"\n            >\n              <MessageSquare className="h-3 w-3 mr-2" />\n              Send Feedback & Get +{feedbackBonus} Credits\n            </Button>\n          </div>\n        )}\n      </div>\n\n      {/* Version Info Section (Read-only) */}\n      <div className="space-y-3">\n        <div className="flex items-center gap-2">\n          <RefreshCw className="h-4 w-4 text-blue-500" />\n          <h3 className="font-semibold text-sm">Version Info</h3>\n        </div>\n        \n        <div className="bg-muted/50 rounded-lg p-3 space-y-2">\n          <div className="flex items-center justify-between mb-2">\n            <span className="text-xs text-muted-foreground">Current Version</span>\n            <Badge className="bg-blue-500/10 text-blue-500 border-blue-500/20 font-mono">\n              v{currentVersion}\n            </Badge>\n          </div>\n          \n          {latestVersion && latestVersion !== currentVersion && (\n            <div className="flex items-center justify-between mb-2">\n              <span className="text-xs text-muted-foreground">Latest Version</span>\n              <Badge className="bg-green-500/10 text-green-500 border-green-500/20 font-mono">\n                v{latestVersion}\n              </Badge>\n            </div>\n          )}\n          \n          <p className="text-[10px] text-muted-foreground pt-2 border-t border-border/50">\n            ✨ Updates happen automatically in the background! No action needed.\n          </p>\n        </div>\n      </div>\n\n      {/* Widget Control */}\n      <div className="space-y-3">\n        <div className="flex items-center gap-2">\n          <EyeOff className="h-4 w-4 text-orange-500" />\n          <h3 className="font-semibold text-sm">Widget Control</h3>\n        </div>\n        \n        <div className="space-y-2">\n          <Button\n            onClick={() => {\n              console.log(\'🔴 HIDE BUTTON CLICKED\');\n              toast({\n                title: "Hidden Until Refresh",\n                description: "MockDetector will reappear after F5"\n              });\n              onHide?.();\n            }}\n            variant="outline"\n            size="sm"\n            className="w-full justify-start text-xs"\n          >\n            <EyeOff className="h-3 w-3 mr-2" />\n            Hide Until Refresh (F5)\n          </Button>\n          \n          <Button\n            onClick={() => {\n              if (confirm(\'Are you sure? MockDetector will be hidden until you click "Re-enable".\')) {\n                disablePermanently();\n                toast({\n                  title: "MockDetector Disabled",\n                  description: "Click the green card to re-enable"\n                });\n                onDisable?.();\n              }\n            }}\n            variant="outline"\n            size="sm"\n            className="w-full justify-start text-xs text-orange-600 hover:text-orange-700"\n          >\n            <Lock className="h-3 w-3 mr-2" />\n            Disable Permanently\n          </Button>\n        </div>\n      </div>\n\n      {/* Uninstall Instructions */}\n      <div className="space-y-3">\n        <div className="flex items-center gap-2">\n          <Trash2 className="h-4 w-4 text-red-500" />\n          <h3 className="font-semibold text-sm">Uninstall</h3>\n        </div>\n        \n        <div className="bg-muted/50 rounded-lg p-3 space-y-2">\n          <p className="text-xs text-muted-foreground mb-2">To completely remove MockDetector:</p>\n          \n          <div className="space-y-1.5">\n            <div className="bg-background rounded px-2 py-1">\n              <code className="text-xs text-red-600 dark:text-red-400">\n                {uninstallInstructions.npm}\n              </code>\n            </div>\n            \n            <p className="text-xs text-muted-foreground">\n              {uninstallInstructions.removeImport}\n            </p>\n            \n            <p className="text-xs text-muted-foreground italic">\n              {uninstallInstructions.alternative}\n            </p>\n          </div>\n        </div>\n      </div>\n\n      {/* About Section */}\n      <div className="space-y-2 pt-2 border-t border-border">\n          <p className="text-xs text-muted-foreground">\n            Built by <span className="font-semibold text-foreground">Silver</span> (Anton Fredriksson) 🇸🇪\n          </p>\n          <p className="text-xs text-muted-foreground">\n            with AI assistance 🤖\n          </p>\n          <p className="text-xs text-blue-600 dark:text-blue-400">\n            Version: {WIDGET_VERSION}\n          </p>\n          <p className="text-[10px] text-muted-foreground pt-2 border-t border-border/50">\n            {COPYRIGHT_TEXT}\n          </p>\n      </div>\n\n      {/* Close Button */}\n      <Button \n        onClick={onClose} \n        variant="outline" \n        className="w-full"\n        size="sm"\n      >\n        Close\n      </Button>\n    </div>\n  );\n};\n'},Symbol.toStringTag,{value:"Module"})),$n=Object.freeze(Object.defineProperty({__proto__:null,default:'import { Button } from "./ui/button";\nimport { Card } from "./ui/card";\nimport { Alert, AlertDescription, AlertTitle } from "./ui/alert";\nimport { Search, Copy, CheckCircle2, XCircle, AlertTriangle, ChevronDown, ChevronRight, AlertCircle, Zap } from "lucide-react";\nimport { useMockDetection } from "../hooks/useMockDetection";\nimport { useSelfScan } from "../hooks/useSelfScan";\nimport { useDatabaseScanner } from "../hooks/useDatabaseScanner";\nimport { useBetaCredits } from "../hooks/useBetaCredits";\nimport { copyReportToClipboard } from "../utils/reportGenerator";\nimport { useToast } from "../hooks/use-toast";\nimport { useState, useEffect } from "react";\nimport { ScanSettings } from "./ScanSettings";\nimport { detectProjectSize, getProjectSizeRecommendation } from "../utils/projectSizeDetection";\nimport { ProjectSize, DatabaseStrategy } from "../types/scanConfig.types";\nimport { ScanResult } from "../types/mockdetector.types";\nimport { DatabaseScanResult } from "../types/database.types";\n\ninterface MockDetectorWidgetProps {\n  saveScanToHistory: (scanResult: ScanResult) => void;\n  saveDatabaseScanToHistory: (databaseResult: DatabaseScanResult) => void;\n  apiKey?: string;\n  apiDailyScanLimit?: number;\n  adminMode?: boolean;\n}\n\nexport const MockDetectorWidget = ({ \n  saveScanToHistory, \n  saveDatabaseScanToHistory, \n  apiKey, \n  apiDailyScanLimit,\n  adminMode = true \n}: MockDetectorWidgetProps) => {\n  const { credits } = useBetaCredits(apiKey, apiDailyScanLimit as number | undefined);\n  const { isScanning, scanResult, runScan, runSmartDeepScan, isDeepScanning, currentScanProgress } = useMockDetection();\n  const { scanDatabase, isScanning: isDatabaseScanning, progress: dbProgress } = useDatabaseScanner();\n  const { selfScanStatus } = useSelfScan();\n  const { toast } = useToast();\n  const [expandedViolations, setExpandedViolations] = useState<Set<number>>(new Set());\n  \n  // Project size detection\n  const [projectSize, setProjectSize] = useState<ProjectSize>(\'small\');\n  const [projectSizeLoaded, setProjectSizeLoaded] = useState(false);\n  \n  // Advanced settings - AUTO ENABLED for comprehensive scans\n  const [includeEdgeFunctions, setIncludeEdgeFunctions] = useState(true);\n  const [includeConfigFiles, setIncludeConfigFiles] = useState(true);\n  const [customScanPath, setCustomScanPath] = useState(\'\');\n  const [databaseStrategy, setDatabaseStrategy] = useState<DatabaseStrategy>(\'prioritized\');\n  \n  // Detect project size on mount\n  useEffect(() => {\n    detectProjectSize().then(metrics => {\n      setProjectSize(metrics.size);\n      setProjectSizeLoaded(true);\n      console.log(\'📊 Project size detected:\', metrics);\n    });\n  }, []);\n  \n  // Auto-save scan results to history\n  useEffect(() => {\n    if (scanResult && !scanResult.fromCache) {\n      console.log(\'💾 Auto-saving scan to history:\', scanResult.totalViolations, \'violations\');\n      saveScanToHistory(scanResult);\n    }\n  }, [scanResult, saveScanToHistory]);\n\n  const toggleViolation = (index: number) => {\n    setExpandedViolations(prev => {\n      const next = new Set(prev);\n      if (next.has(index)) {\n        next.delete(index);\n      } else {\n        next.add(index);\n      }\n      return next;\n    });\n  };\n\n  const handleCopyReport = async () => {\n    if (!scanResult) return;\n    \n    const success = await copyReportToClipboard(scanResult);\n    if (success) {\n      toast({\n        title: "Report copied!",\n        description: "Paste into Lovable chat to get AI-powered fixes",\n      });\n    } else {\n      toast({\n        title: "Copy failed",\n        description: "Please try again",\n        variant: "destructive"\n      });\n    }\n  };\n  \n  const handleSmartDeepScan = async () => {\n    await runSmartDeepScan({\n      includeEdgeFunctions,\n      includeConfigFiles,\n      customScanPath: customScanPath || undefined\n    });\n  };\n  \n  const handleDatabaseScan = async () => {\n    const config = databaseStrategy === \'prioritized\' \n      ? {\n          rowsPerTable: 100,\n          prioritizedTables: [\'users\', \'products\', \'orders\', \'ai_hotel_rooms\', \'profiles\'],\n          onlyPrioritized: false,\n          intelligentSampling: true\n        }\n      : {\n          rowsPerTable: 200,\n          prioritizedTables: undefined,\n          intelligentSampling: false\n        };\n    \n    try {\n      const result = await scanDatabase(\n        config.rowsPerTable,\n        config.prioritizedTables,\n        config.onlyPrioritized || false,\n        config.intelligentSampling\n      );\n      \n      // Auto-save database scan to history\n      if (result) {\n        saveDatabaseScanToHistory(result);\n      }\n    } catch (error) {\n      console.error(\'❌ Database scan failed:\', error);\n    }\n  };\n  \n  const recommendation = projectSizeLoaded ? getProjectSizeRecommendation(projectSize) : null;\n\n  // Self-scan runs silently in background - not shown to users\n  // Only log to console for debugging\n  if (selfScanStatus && !selfScanStatus.isClean) {\n    console.warn(\'⚠️ MockDetector self-scan found issues:\', selfScanStatus);\n  }\n\n  // Hide widget if not in admin mode\n  if (!adminMode) {\n    return null;\n  }\n\n  return (\n    <div data-mockdetector className="space-y-4">\n      <Card className="p-6 space-y-4">\n        {/* Minimal Header */}\n        <div className="space-y-3">\n          <div className="flex items-center justify-between">\n            <div>\n              <h3 className="text-lg font-semibold">MockDetector Pro</h3>\n              <p className="text-sm text-muted-foreground">Intelligent mock data detection for all project sizes</p>\n              {apiKey && (\n                <p className="text-xs text-muted-foreground mt-1">\n                  {typeof credits === \'number\' ? (\n                    <span>Credits: <strong>{credits}</strong></span>\n                  ) : (\n                    <span>{credits}</span>\n                  )}\n                </p>\n              )}\n            </div>\n          </div>\n          \n          {/* Project Size Warning */}\n          {projectSizeLoaded && recommendation && projectSize !== \'small\' && (\n            <Alert variant={projectSize === \'large\' ? \'destructive\' : \'default\'}>\n              <AlertCircle className="h-4 w-4" />\n              <AlertTitle>{recommendation.title}</AlertTitle>\n              <AlertDescription>\n                <p className="mb-2">{recommendation.description}</p>\n                <ul className="text-xs space-y-1">\n                  {recommendation.recommendations.map((rec, idx) => (\n                    <li key={idx}>{rec}</li>\n                  ))}\n                </ul>\n              </AlertDescription>\n            </Alert>\n          )}\n          \n          {/* Scan Buttons Grid - 3 clear options */}\n          <div className="grid grid-cols-2 gap-2">\n            <Button \n              onClick={runScan} \n              disabled={isScanning}\n              variant="outline"\n              size="lg"\n              className="h-auto py-3 flex-col items-start"\n            >\n              <div className="flex items-center gap-2 mb-1">\n                <Search className="w-4 h-4" />\n                <span className="font-medium">Quick Scan</span>\n              </div>\n              <span className="text-xs text-muted-foreground font-normal">\n                Current page only (fast)\n              </span>\n            </Button>\n            \n            <Button \n              onClick={handleSmartDeepScan} \n              disabled={isScanning}\n              size="lg"\n              className="h-auto py-3 flex-col items-start relative overflow-hidden"\n            >\n              <div className="flex items-center gap-2 mb-1">\n                <Zap className="w-4 h-4" />\n                <span className="font-medium">🔥 Smart Deep Scan</span>\n              </div>\n              {isDeepScanning ? (\n                <span className="text-xs font-normal opacity-90">\n                  {currentScanProgress || \'Scanning...\'}\n                </span>\n              ) : (\n                <span className="text-xs font-normal opacity-90">\n                  DOM/UI + Source files (.tsx)\n                </span>\n              )}\n            </Button>\n            \n            <Button \n              onClick={handleDatabaseScan} \n              disabled={isScanning || isDatabaseScanning}\n              variant="outline"\n              size="lg"\n              className="h-auto py-3 flex-col items-start col-span-2"\n            >\n              <div className="flex items-center gap-2 mb-1">\n                <Search className="w-4 h-4" />\n                <span className="font-medium">Scan Database</span>\n              </div>\n              {isDatabaseScanning ? (\n                <span className="text-xs text-muted-foreground font-normal">\n                  {dbProgress || \'Scanning...\'}\n                </span>\n              ) : (\n                <span className="text-xs text-muted-foreground font-normal">\n                  Check all tables for mock data\n                </span>\n              )}\n            </Button>\n          </div>\n          \n          {/* Advanced Settings */}\n          <ScanSettings \n            includeEdgeFunctions={includeEdgeFunctions}\n            setIncludeEdgeFunctions={setIncludeEdgeFunctions}\n            includeConfigFiles={includeConfigFiles}\n            setIncludeConfigFiles={setIncludeConfigFiles}\n            customScanPath={customScanPath}\n            setCustomScanPath={setCustomScanPath}\n            databaseStrategy={databaseStrategy}\n            setDatabaseStrategy={setDatabaseStrategy}\n          />\n        </div>\n\n        {/* Results - Only show if scan completed */}\n        {scanResult && (\n          <div className="space-y-3 pt-4 border-t">\n            {/* Summary */}\n            <div className="flex items-center gap-3">\n              {scanResult.totalViolations === 0 ? (\n                <>\n                  <CheckCircle2 className="w-5 h-5 text-green-600" />\n                  <span className="font-medium">✅ No issues found!</span>\n                </>\n              ) : (\n                <>\n                  <XCircle className="w-5 h-5 text-red-600" />\n                  <span className="font-medium">\n                    {scanResult.totalViolations} issue{scanResult.totalViolations !== 1 ? \'s\' : \'\'} detected\n                  </span>\n                </>\n              )}\n              <span className="text-xs text-muted-foreground ml-auto">\n                {Math.round(scanResult.scanDuration)}ms\n              </span>\n            </div>\n\n            {/* Issue Breakdown - Compact with severity indicators */}\n            {scanResult.totalViolations > 0 && (\n              <div className="space-y-2 text-sm">\n                {scanResult.mockDataViolations.length > 0 && (\n                  <div className="space-y-1">\n                    <div className="flex items-center gap-2">\n                      <AlertTriangle className="w-4 h-4 text-orange-500" />\n                      <span className="font-medium">{scanResult.mockDataViolations.length} mock data violations</span>\n                    </div>\n                     <div className="ml-6 text-xs text-muted-foreground space-y-0.5">\n                      {scanResult.mockDataViolations.filter(v => v.severity === \'high\').length > 0 && (\n                        <div className="flex items-center gap-1.5">\n                          <span className="w-2 h-2 rounded-full bg-orange-500"></span>\n                          <span>{scanResult.mockDataViolations.filter(v => v.severity === \'high\').length} HIGH - Hårdkodade siffror utan data binding</span>\n                        </div>\n                      )}\n                      {scanResult.mockDataViolations.filter(v => v.severity === \'medium\').length > 0 && (\n                        <div className="flex items-center gap-1.5">\n                          <span className="w-2 h-2 rounded-full bg-yellow-500"></span>\n                          <span>{scanResult.mockDataViolations.filter(v => v.severity === \'medium\').length} MEDIUM - Statistik claims utan validering</span>\n                        </div>\n                      )}\n                    </div>\n                  </div>\n                )}\n                {/* Security and Role sections removed - MockDetector focuses only on mock data */}\n              </div>\n            )}\n\n            {/* Detailed Violations List - Scrollable & Expandable */}\n            {scanResult.totalViolations > 0 && (\n              <div className="max-h-[400px] overflow-y-auto space-y-2 border rounded-lg p-3 bg-muted/20">\n                {/* Mock Data Violations */}\n                {scanResult.mockDataViolations.map((violation, idx) => {\n                  const globalIndex = idx;\n                  const isExpanded = expandedViolations.has(globalIndex);\n                  \n                  return (\n                    <div key={globalIndex} className="border rounded-lg overflow-hidden bg-background">\n                       {/* Header - Clickable */}\n                      <button\n                        onClick={() => toggleViolation(globalIndex)}\n                        className="w-full flex items-center gap-3 p-3 hover:bg-muted/50 transition-all text-left group border-l-4 border-transparent hover:border-primary"\n                      >\n                        <div className="flex items-center justify-center w-6 h-6 rounded bg-muted group-hover:bg-primary/20 transition-colors">\n                          {isExpanded ? (\n                            <ChevronDown className="w-4 h-4 text-foreground group-hover:text-primary transition-colors" />\n                          ) : (\n                            <ChevronRight className="w-4 h-4 text-foreground group-hover:text-primary transition-colors" />\n                          )}\n                        </div>\n                        <div className="flex-1 min-w-0">\n                          <div className="flex items-center gap-2 mb-1">\n                            <span className={`w-2 h-2 rounded-full flex-shrink-0 ${\n                              violation.severity === \'critical\' ? \'bg-red-500\' :\n                              violation.severity === \'high\' ? \'bg-orange-500\' :\n                              violation.severity === \'medium\' ? \'bg-yellow-500\' : \'bg-green-500\'\n                            }`}></span>\n                            <span className="text-xs font-medium uppercase text-muted-foreground">\n                              {violation.severity}\n                            </span>\n                            {violation.file && violation.line && (\n                              <span className="text-xs text-primary/70 font-mono">\n                                {violation.file.split(\'/\').pop()}:{violation.line}\n                              </span>\n                            )}\n                            <span className="text-xs text-muted-foreground ml-auto group-hover:text-primary transition-colors">\n                              {isExpanded ? \'Click to collapse\' : \'Click for details\'}\n                            </span>\n                          </div>\n                          <p className="text-sm font-medium truncate">{violation.description}</p>\n                        </div>\n                      </button>\n\n                       {/* Expanded Details */}\n                      {isExpanded && (\n                        <div className="px-3 pb-3 space-y-2 text-xs border-t">\n                          {violation.file && (\n                            <div>\n                              <span className="font-semibold">📄 File:</span>\n                              <p className="text-muted-foreground mt-0.5 font-mono text-[11px]">\n                                {violation.file}\n                                {violation.line && <span className="text-primary"> (line {violation.line})</span>}\n                              </p>\n                            </div>\n                          )}\n                          \n                          {violation.code && (\n                            <div>\n                              <span className="font-semibold">💻 Code:</span>\n                              <pre className="mt-1 p-2 bg-muted rounded text-[10px] overflow-x-auto font-mono">\n                                {violation.code}\n                              </pre>\n                            </div>\n                          )}\n                          \n                          {violation.fix && (\n                            <div>\n                              <span className="font-semibold text-green-600">✅ Fix:</span>\n                              <p className="text-muted-foreground mt-0.5 whitespace-pre-wrap">{violation.fix}</p>\n                            </div>\n                          )}\n                        </div>\n                      )}\n                    </div>\n                  );\n                })}\n\n                {/* Security and Role sections removed - MockDetector focuses only on mock data */}\n              </div>\n            )}\n\n            {/* Scan Info */}\n            {scanResult.totalViolations > 0 && (\n              <div className="text-xs text-muted-foreground p-2 bg-muted/50 rounded">\n                💡 Smart Deep Scan inkluderar: DOM/UI, Source files (.tsx/.ts), hardcoded values, och statistical claims\n              </div>\n            )}\n\n            {/* Copy Report Button - Only if issues found */}\n            {scanResult.totalViolations > 0 && (\n              <Button \n                onClick={handleCopyReport}\n                variant="outline"\n                className="w-full"\n              >\n                <Copy className="w-4 h-4 mr-2" />\n                Copy Report for Lovable AI\n              </Button>\n            )}\n          </div>\n        )}\n      </Card>\n    </div>\n  );\n};\n'},Symbol.toStringTag,{value:"Module"})),Ln=Object.freeze(Object.defineProperty({__proto__:null,default:'import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible";\nimport { Checkbox } from "./ui/checkbox";\nimport { Input } from "./ui/input";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";\nimport { Label } from "./ui/label";\nimport { Settings } from "lucide-react";\nimport { DatabaseStrategy } from "../types/scanConfig.types";\n\ninterface ScanSettingsProps {\n  includeEdgeFunctions: boolean;\n  setIncludeEdgeFunctions: (value: boolean) => void;\n  includeConfigFiles: boolean;\n  setIncludeConfigFiles: (value: boolean) => void;\n  customScanPath: string;\n  setCustomScanPath: (value: string) => void;\n  databaseStrategy: DatabaseStrategy;\n  setDatabaseStrategy: (value: DatabaseStrategy) => void;\n}\n\nexport const ScanSettings = ({\n  includeEdgeFunctions,\n  setIncludeEdgeFunctions,\n  includeConfigFiles,\n  setIncludeConfigFiles,\n  customScanPath,\n  setCustomScanPath,\n  databaseStrategy,\n  setDatabaseStrategy\n}: ScanSettingsProps) => {\n  return (\n    <Collapsible>\n      <CollapsibleTrigger className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors">\n        <Settings className="w-4 h-4" />\n        <span>Advanced Scan Settings</span>\n      </CollapsibleTrigger>\n      <CollapsibleContent className="mt-3 space-y-4 border rounded-lg p-4 bg-muted/20">\n        {/* Source File Settings */}\n        <div className="space-y-3">\n          <h4 className="font-medium text-sm">Source Code Scanning</h4>\n          \n          <div className="flex items-center space-x-2">\n            <Checkbox \n              id="includeEdgeFunctions"\n              checked={includeEdgeFunctions}\n              onCheckedChange={setIncludeEdgeFunctions}\n            />\n            <Label htmlFor="includeEdgeFunctions" className="text-sm cursor-pointer">\n              Include Edge Functions (supabase/functions)\n            </Label>\n          </div>\n          \n          <div className="flex items-center space-x-2">\n            <Checkbox \n              id="includeConfigFiles"\n              checked={includeConfigFiles}\n              onCheckedChange={setIncludeConfigFiles}\n            />\n            <Label htmlFor="includeConfigFiles" className="text-sm cursor-pointer">\n              Include Config Files (.json, .yaml, .env.example)\n            </Label>\n          </div>\n          \n          <div className="space-y-1.5">\n            <Label htmlFor="customPath" className="text-sm">\n              Custom Scan Path (optional)\n            </Label>\n            <Input \n              id="customPath"\n              placeholder="e.g., /workspace/src/components"\n              value={customScanPath}\n              onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCustomScanPath(e.target.value)}\n              className="text-sm"\n            />\n            <p className="text-xs text-muted-foreground">\n              Leave empty to scan entire project\n            </p>\n          </div>\n        </div>\n\n        {/* Database Settings */}\n        <div className="space-y-3 pt-3 border-t">\n          <h4 className="font-medium text-sm">Database Scanning</h4>\n          \n          <div className="space-y-1.5">\n            <Label htmlFor="dbStrategy" className="text-sm">\n              Database Scan Strategy\n            </Label>\n            <Select value={databaseStrategy} onValueChange={(v: string) => setDatabaseStrategy(v as DatabaseStrategy)}>\n              <SelectTrigger id="dbStrategy" className="text-sm">\n                <SelectValue placeholder="Select strategy" />\n              </SelectTrigger>\n              <SelectContent>\n                <SelectItem value="all">\n                  <div className="flex flex-col items-start">\n                    <span className="font-medium">All Tables</span>\n                    <span className="text-xs text-muted-foreground">Comprehensive but slower</span>\n                  </div>\n                </SelectItem>\n                <SelectItem value="prioritized">\n                  <div className="flex flex-col items-start">\n                    <span className="font-medium">Prioritized Tables</span>\n                    <span className="text-xs text-muted-foreground">Fast - scans important tables first</span>\n                  </div>\n                </SelectItem>\n                <SelectItem value="custom">\n                  <div className="flex flex-col items-start">\n                    <span className="font-medium">Custom Selection</span>\n                    <span className="text-xs text-muted-foreground">Coming soon</span>\n                  </div>\n                </SelectItem>\n              </SelectContent>\n            </Select>\n            <p className="text-xs text-muted-foreground">\n              {databaseStrategy === \'prioritized\' \n                ? \'Scans: users, products, orders, ai_hotel_rooms, profiles first\' \n                : databaseStrategy === \'all\'\n                ? \'Scans all tables in your database\'\n                : \'Select specific tables to scan\'}\n            </p>\n          </div>\n        </div>\n\n        {/* Info */}\n        <div className="text-xs text-muted-foreground p-2 bg-primary/5 rounded">\n          💡 <strong>Tip:</strong> For large projects, use prioritized scanning and disable edge functions for faster results.\n        </div>\n      </CollapsibleContent>\n    </Collapsible>\n  );\n};\n'},Symbol.toStringTag,{value:"Module"})),zn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport { cva, type VariantProps } from "class-variance-authority"\n\nimport { cn } from "../../lib/utils"\n\nconst alertVariants = cva(\n  "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",\n  {\n    variants: {\n      variant: {\n        default: "bg-background text-foreground",\n        destructive:\n          "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",\n      },\n    },\n    defaultVariants: {\n      variant: "default",\n    },\n  }\n)\n\nconst Alert = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n  <div\n    ref={ref}\n    role="alert"\n    className={cn(alertVariants({ variant }), className)}\n    {...props}\n  />\n))\nAlert.displayName = "Alert"\n\nconst AlertTitle = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n  <h5\n    ref={ref}\n    className={cn("mb-1 font-medium leading-none tracking-tight", className)}\n    {...props}\n  />\n))\nAlertTitle.displayName = "AlertTitle"\n\nconst AlertDescription = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn("text-sm [&_p]:leading-relaxed", className)}\n    {...props}\n  />\n))\nAlertDescription.displayName = "AlertDescription"\n\nexport { Alert, AlertTitle, AlertDescription }\n'},Symbol.toStringTag,{value:"Module"})),Un=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport { cva, type VariantProps } from "class-variance-authority"\n\nimport { cn } from "../../lib/utils"\n\nconst badgeVariants = cva(\n  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",\n  {\n    variants: {\n      variant: {\n        default:\n          "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",\n        secondary:\n          "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",\n        destructive:\n          "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",\n        outline: "text-foreground",\n      },\n    },\n    defaultVariants: {\n      variant: "default",\n    },\n  }\n)\n\nexport interface BadgeProps\n  extends React.HTMLAttributes<HTMLDivElement>,\n    VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n  return (\n    <div className={cn(badgeVariants({ variant }), className)} {...props} />\n  )\n}\n\nexport { Badge, badgeVariants }\n'},Symbol.toStringTag,{value:"Module"})),Bn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport { Slot } from "@radix-ui/react-slot"\nimport { cva, type VariantProps } from "class-variance-authority"\n\nimport { cn } from "../../lib/utils"\n\nconst buttonVariants = cva(\n  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border",\n  {\n    variants: {\n      variant: {\n        default: "bg-primary text-primary-foreground hover:bg-primary/90 border-primary/50 hover:border-primary/70 shadow-professional-sm hover:shadow-professional-md observer-button-primary",\n        destructive:\n          "bg-destructive text-destructive-foreground hover:bg-destructive/90 border-destructive/50 hover:border-destructive/70 shadow-professional-sm",\n        outline:\n          "border-border bg-card text-foreground hover:bg-muted hover:text-accent-foreground hover:border-accent shadow-professional-sm observer-button-outline",\n        secondary:\n          "bg-secondary text-secondary-foreground hover:bg-secondary/80 border-secondary/60 hover:border-secondary shadow-professional-sm",\n        ghost: "border-transparent bg-card/80 hover:bg-muted hover:text-accent-foreground hover:border-accent/50 shadow-professional-sm",\n        link: "border-transparent text-primary underline-offset-4 hover:underline",\n        success: "bg-success text-success-foreground hover:bg-success/90 border-success/50 hover:border-success/70 shadow-professional-sm",\n        warning: "bg-warning text-warning-foreground hover:bg-warning/90 border-warning/50 hover:border-warning/70 shadow-professional-sm",\n      },\n      size: {\n        default: "h-10 px-4 py-2",\n        sm: "h-9 rounded-md px-3",\n        lg: "h-11 rounded-md px-8",\n        icon: "h-10 w-10",\n      },\n    },\n    defaultVariants: {\n      variant: "default",\n      size: "default",\n    },\n  }\n)\n\nexport interface ButtonProps\n  extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n    VariantProps<typeof buttonVariants> {\n  asChild?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n  ({ className, variant, size, asChild = false, ...props }, ref) => {\n    const Comp = asChild ? Slot : "button"\n    return (\n      <Comp\n        className={cn(buttonVariants({ variant, size, className }))}\n        ref={ref}\n        {...props}\n      />\n    )\n  }\n)\nButton.displayName = "Button"\n\nexport { Button, buttonVariants }\n'},Symbol.toStringTag,{value:"Module"})),Hn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\n\nimport { cn } from "../../lib/utils"\n\nconst Card = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn(\n      "rounded-lg border bg-card text-card-foreground shadow-sm observer-card",\n      className\n    )}\n    {...props}\n  />\n))\nCard.displayName = "Card"\n\nconst CardHeader = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn("flex flex-col space-y-1.5 p-6", className)}\n    {...props}\n  />\n))\nCardHeader.displayName = "CardHeader"\n\nconst CardTitle = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n  <h3\n    ref={ref}\n    className={cn(\n      "text-2xl font-semibold leading-none tracking-tight",\n      className\n    )}\n    {...props}\n  />\n))\nCardTitle.displayName = "CardTitle"\n\nconst CardDescription = React.forwardRef<\n  HTMLParagraphElement,\n  React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n  <p\n    ref={ref}\n    className={cn("text-sm text-muted-foreground", className)}\n    {...props}\n  />\n))\nCardDescription.displayName = "CardDescription"\n\nconst CardContent = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />\n))\nCardContent.displayName = "CardContent"\n\nconst CardFooter = React.forwardRef<\n  HTMLDivElement,\n  React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n  <div\n    ref={ref}\n    className={cn("flex items-center p-6 pt-0", className)}\n    {...props}\n  />\n))\nCardFooter.displayName = "CardFooter"\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n'},Symbol.toStringTag,{value:"Module"})),Kn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as CheckboxPrimitive from "@radix-ui/react-checkbox"\nimport { Check } from "lucide-react"\n\nimport { cn } from "../../lib/utils"\n\nconst Checkbox = React.forwardRef<\n  React.ElementRef<typeof CheckboxPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n  <CheckboxPrimitive.Root\n    ref={ref}\n    className={cn(\n      "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",\n      className\n    )}\n    {...props}\n  >\n    <CheckboxPrimitive.Indicator\n      className={cn("flex items-center justify-center text-current")}\n    >\n      <Check className="h-4 w-4" />\n    </CheckboxPrimitive.Indicator>\n  </CheckboxPrimitive.Root>\n))\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n'},Symbol.toStringTag,{value:"Module"})),Wn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"\n\nconst Collapsible = CollapsiblePrimitive.Root\n\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger\n\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n'},Symbol.toStringTag,{value:"Module"})),Gn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as DialogPrimitive from "@radix-ui/react-dialog"\nimport { X } from "lucide-react"\n\nimport { cn } from "../../lib/utils"\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nconst DialogOverlay = React.forwardRef<\n  React.ElementRef<typeof DialogPrimitive.Overlay>,\n  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n  <DialogPrimitive.Overlay\n    ref={ref}\n    className={cn(\n      "fixed inset-0 z-50 bg-black/80  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",\n      className\n    )}\n    {...props}\n  />\n))\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nconst DialogContent = React.forwardRef<\n  React.ElementRef<typeof DialogPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n  <DialogPortal>\n    <DialogOverlay />\n    <DialogPrimitive.Content\n      ref={ref}\n      className={cn(\n        "fixed left-[50%] top-[50%] z-50 grid w-full max-w-2xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",\n        className\n      )}\n      {...props}\n    >\n      {children}\n      <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">\n        <X className="h-4 w-4" />\n        <span className="sr-only">Close</span>\n      </DialogPrimitive.Close>\n    </DialogPrimitive.Content>\n  </DialogPortal>\n))\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nconst DialogHeader = ({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n  <div\n    className={cn(\n      "flex flex-col space-y-1.5 text-center sm:text-left",\n      className\n    )}\n    {...props}\n  />\n)\nDialogHeader.displayName = "DialogHeader"\n\nconst DialogFooter = ({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n  <div\n    className={cn(\n      "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",\n      className\n    )}\n    {...props}\n  />\n)\nDialogFooter.displayName = "DialogFooter"\n\nconst DialogTitle = React.forwardRef<\n  React.ElementRef<typeof DialogPrimitive.Title>,\n  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n  <DialogPrimitive.Title\n    ref={ref}\n    className={cn(\n      "text-lg font-semibold leading-none tracking-tight",\n      className\n    )}\n    {...props}\n  />\n))\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nconst DialogDescription = React.forwardRef<\n  React.ElementRef<typeof DialogPrimitive.Description>,\n  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n  <DialogPrimitive.Description\n    ref={ref}\n    className={cn("text-sm text-muted-foreground", className)}\n    {...props}\n  />\n))\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n  Dialog,\n  DialogPortal,\n  DialogOverlay,\n  DialogClose,\n  DialogTrigger,\n  DialogContent,\n  DialogHeader,\n  DialogFooter,\n  DialogTitle,\n  DialogDescription,\n}\n'},Symbol.toStringTag,{value:"Module"})),qn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\n\nimport { cn } from "../../lib/utils"\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(\n  ({ className, type, ...props }, ref) => {\n    return (\n      <input\n        type={type}\n        className={cn(\n          "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",\n          className\n        )}\n        ref={ref}\n        {...props}\n      />\n    )\n  }\n)\nInput.displayName = "Input"\n\nexport { Input }\n'},Symbol.toStringTag,{value:"Module"})),Yn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as LabelPrimitive from "@radix-ui/react-label"\nimport { cva, type VariantProps } from "class-variance-authority"\n\nimport { cn } from "../../lib/utils"\n\nconst labelVariants = cva(\n  "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"\n)\n\nconst Label = React.forwardRef<\n  React.ElementRef<typeof LabelPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n    VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n  <LabelPrimitive.Root\n    ref={ref}\n    className={cn(labelVariants(), className)}\n    {...props}\n  />\n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n'},Symbol.toStringTag,{value:"Module"})),Jn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as ProgressPrimitive from "@radix-ui/react-progress"\n\nimport { cn } from "../../lib/utils"\n\nconst Progress = React.forwardRef<\n  React.ElementRef<typeof ProgressPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n  <ProgressPrimitive.Root\n    ref={ref}\n    className={cn(\n      "relative h-4 w-full overflow-hidden rounded-full bg-secondary",\n      className\n    )}\n    {...props}\n  >\n    <ProgressPrimitive.Indicator\n      className="h-full w-full flex-1 bg-primary transition-all"\n      style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n    />\n  </ProgressPrimitive.Root>\n))\nProgress.displayName = ProgressPrimitive.Root.displayName\n\nexport { Progress }\n'},Symbol.toStringTag,{value:"Module"})),Xn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"\n\nimport { cn } from "../../lib/utils"\n\nconst ScrollArea = React.forwardRef<\n  React.ElementRef<typeof ScrollAreaPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n  <ScrollAreaPrimitive.Root\n    ref={ref}\n    className={cn("relative overflow-hidden", className)}\n    {...props}\n  >\n    <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">\n      {children}\n    </ScrollAreaPrimitive.Viewport>\n    <ScrollBar />\n    <ScrollAreaPrimitive.Corner />\n  </ScrollAreaPrimitive.Root>\n))\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName\n\nconst ScrollBar = React.forwardRef<\n  React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,\n  React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>\n>(({ className, orientation = "vertical", ...props }, ref) => (\n  <ScrollAreaPrimitive.ScrollAreaScrollbar\n    ref={ref}\n    orientation={orientation}\n    className={cn(\n      "flex touch-none select-none transition-colors",\n      orientation === "vertical" &&\n        "h-full w-2.5 border-l border-l-transparent p-[1px]",\n      orientation === "horizontal" &&\n        "h-2.5 flex-col border-t border-t-transparent p-[1px]",\n      className\n    )}\n    {...props}\n  >\n    <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />\n  </ScrollAreaPrimitive.ScrollAreaScrollbar>\n))\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName\n\nexport { ScrollArea, ScrollBar }\n'},Symbol.toStringTag,{value:"Module"})),Qn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as SelectPrimitive from "@radix-ui/react-select"\nimport { Check, ChevronDown, ChevronUp } from "lucide-react"\n\nimport { cn } from "../../lib/utils"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Trigger>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n  <SelectPrimitive.Trigger\n    ref={ref}\n    className={cn(\n      "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",\n      className\n    )}\n    {...props}\n  >\n    {children}\n    <SelectPrimitive.Icon asChild>\n      <ChevronDown className="h-4 w-4 opacity-50" />\n    </SelectPrimitive.Icon>\n  </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.ScrollUpButton\n    ref={ref}\n    className={cn(\n      "flex cursor-default items-center justify-center py-1",\n      className\n    )}\n    {...props}\n  >\n    <ChevronUp className="h-4 w-4" />\n  </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.ScrollDownButton\n    ref={ref}\n    className={cn(\n      "flex cursor-default items-center justify-center py-1",\n      className\n    )}\n    {...props}\n  >\n    <ChevronDown className="h-4 w-4" />\n  </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName =\n  SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = "popper", ...props }, ref) => (\n  <SelectPrimitive.Portal>\n    <SelectPrimitive.Content\n      ref={ref}\n      className={cn(\n        "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",\n        position === "popper" &&\n          "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",\n        className\n      )}\n      position={position}\n      {...props}\n    >\n      <SelectScrollUpButton />\n      <SelectPrimitive.Viewport\n        className={cn(\n          "p-1",\n          position === "popper" &&\n            "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"\n        )}\n      >\n        {children}\n      </SelectPrimitive.Viewport>\n      <SelectScrollDownButton />\n    </SelectPrimitive.Content>\n  </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.Label\n    ref={ref}\n    className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}\n    {...props}\n  />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n  <SelectPrimitive.Item\n    ref={ref}\n    className={cn(\n      "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",\n      className\n    )}\n    {...props}\n  >\n    <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">\n      <SelectPrimitive.ItemIndicator>\n        <Check className="h-4 w-4" />\n      </SelectPrimitive.ItemIndicator>\n    </span>\n\n    <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n  </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n  React.ElementRef<typeof SelectPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <SelectPrimitive.Separator\n    ref={ref}\n    className={cn("-mx-1 my-1 h-px bg-muted", className)}\n    {...props}\n  />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n  Select,\n  SelectGroup,\n  SelectValue,\n  SelectTrigger,\n  SelectContent,\n  SelectLabel,\n  SelectItem,\n  SelectSeparator,\n  SelectScrollUpButton,\n  SelectScrollDownButton,\n}\n'},Symbol.toStringTag,{value:"Module"})),Zn=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as SeparatorPrimitive from "@radix-ui/react-separator"\n\nimport { cn } from "../../lib/utils"\n\nconst Separator = React.forwardRef<\n  React.ElementRef<typeof SeparatorPrimitive.Root>,\n  React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n  (\n    { className, orientation = "horizontal", decorative = true, ...props },\n    ref\n  ) => (\n    <SeparatorPrimitive.Root\n      ref={ref}\n      decorative={decorative}\n      orientation={orientation}\n      className={cn(\n        "shrink-0 bg-border",\n        orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",\n        className\n      )}\n      {...props}\n    />\n  )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }\n'},Symbol.toStringTag,{value:"Module"})),et=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\nimport * as TabsPrimitive from "@radix-ui/react-tabs"\n\nimport { cn } from "../../lib/utils"\n\nconst Tabs = TabsPrimitive.Root\n\nconst TabsList = React.forwardRef<\n  React.ElementRef<typeof TabsPrimitive.List>,\n  React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n  <TabsPrimitive.List\n    ref={ref}\n    className={cn(\n      "inline-flex h-10 items-center justify-center rounded-md bg-muted border border-border p-1 text-muted-foreground",\n      className\n    )}\n    {...props}\n  />\n))\nTabsList.displayName = TabsPrimitive.List.displayName\n\nconst TabsTrigger = React.forwardRef<\n  React.ElementRef<typeof TabsPrimitive.Trigger>,\n  React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n  <TabsPrimitive.Trigger\n    ref={ref}\n    className={cn(\n      "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-card data-[state=active]:text-card-foreground data-[state=active]:shadow-sm hover:bg-accent hover:text-accent-foreground",\n      className\n    )}\n    {...props}\n  />\n))\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName\n\nconst TabsContent = React.forwardRef<\n  React.ElementRef<typeof TabsPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n  <TabsPrimitive.Content\n    ref={ref}\n    className={cn(\n      "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",\n      className\n    )}\n    {...props}\n  />\n))\nTabsContent.displayName = TabsPrimitive.Content.displayName\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n'},Symbol.toStringTag,{value:"Module"})),nt=Object.freeze(Object.defineProperty({__proto__:null,default:'import * as React from "react"\n\nimport { cn } from "../../lib/utils"\n\nexport interface TextareaProps\n  extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n  ({ className, ...props }, ref) => {\n    return (\n      <textarea\n        className={cn(\n          "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",\n          className\n        )}\n        ref={ref}\n        {...props}\n      />\n    )\n  }\n)\nTextarea.displayName = "Textarea"\n\nexport { Textarea }\n'},Symbol.toStringTag,{value:"Module"})),tt=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector Widget Configuration\n * Centralized config for environment-specific settings\n */\n\n// Get Supabase URL from environment or fallback\nconst getSupabaseUrl = (): string => {\n  // Check for environment variable first\n  if (typeof import.meta !== 'undefined' && import.meta.env?.VITE_SUPABASE_URL) {\n    return import.meta.env.VITE_SUPABASE_URL;\n  }\n  \n  // Fallback to production URL\n  return 'https://tzowmzqfbicbyvikhdwy.supabase.co';\n};\n\nexport const WIDGET_CONFIG = {\n  SUPABASE_URL: getSupabaseUrl(),\n  \n  // Edge Function Endpoints\n  get RECORD_SCAN_ENDPOINT() {\n    return `${this.SUPABASE_URL}/functions/v1/record-scan`;\n  },\n  \n  get REPORT_SCAN_RESULT_ENDPOINT() {\n    return `${this.SUPABASE_URL}/functions/v1/report-scan-result`;\n  },\n  \n  get SUBMIT_FEEDBACK_ENDPOINT() {\n    return `${this.SUPABASE_URL}/functions/v1/submit-feedback`;\n  },\n  \n  get VALIDATE_KEY_ENDPOINT() {\n    return `${this.SUPABASE_URL}/functions/v1/validate-mockdetector-key`;\n  },\n  \n  get HEARTBEAT_ENDPOINT() {\n    return `${this.SUPABASE_URL}/functions/v1/widget-heartbeat`;\n  },\n  \n  // Widget Settings\n  DEFAULT_STORAGE_PREFIX: 'mockdetector',\n  \n  // Branding\n  PRODUCT_NAME: 'MockDetector Pro',\n};\n"},Symbol.toStringTag,{value:"Module"})),at=Object.freeze(Object.defineProperty({__proto__:null,default:"// Scannable routes for multi-route scanning\nexport const SCANNABLE_ROUTES = [\n  '/',\n  '/ai-home',\n  '/moderator',\n  '/lovable-tools-builder',\n  '/ai-community',\n  '/ai-hotel',\n  '/ai-hotel-academy',\n  '/coda-space',\n  '/coda-console',\n  '/ai-liberation-dashboard',\n  '/personal-ai',\n  '/ai-discovery',\n  '/explorer-lab',\n  '/ai-testing',\n  '/ai-governance',\n  '/ai-meta-learning',\n  '/ai-education-observatory'\n];\n\n// Default routes where MockDetector widget should be hidden (security best practice)\nexport const DEFAULT_HIDDEN_ROUTES = [\n  '/auth',\n  '/login', \n  '/signup',\n  '/register',\n  '/forgot-password',\n  '/reset-password'\n];\n\n// Route categories for selective scanning\nexport const ROUTE_CATEGORIES = {\n  ai: ['/ai-home', '/ai-hotel', '/ai-hotel-academy', '/ai-community', '/personal-ai'],\n  moderator: ['/moderator', '/coda-console', '/lovable-tools-builder'],\n  testing: ['/explorer-lab', '/ai-testing', '/qa/audit'],\n  governance: ['/ai-governance', '/ai-liberation-dashboard', '/ai-education-observatory']\n};\n"},Symbol.toStringTag,{value:"Module"})),st=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector - Scan Costs Configuration\n * Single source of truth for all scan costs across Widget, Server & Pricing\n * \n * IMPORTANT: These costs must match across:\n * - Widget: @mockdetector/widget/src/hooks/useBetaCredits.ts\n * - Server: supabase/functions/record-scan/index.ts\n * - Pricing: src/config/mockdetectorPricing.ts\n * - Pricing Page: src/pages/MockDetectorPricing.tsx\n */\n\nexport const SCAN_COSTS = {\n  QUICK_SCAN: 2,\n  DATABASE_SCAN: 5,\n  SCAN_ALL_ROUTES: 8,\n  SMART_DEEP_SCAN: 12,\n} as const;\n\nexport type ScanType = keyof typeof SCAN_COSTS;\n\n/**\n * Get the cost for a specific scan type\n */\nexport function getScanCost(scanType: ScanType): number {\n  return SCAN_COSTS[scanType];\n}\n\n/**\n * Check if a scan type is valid\n */\nexport function isValidScanType(scanType: string): scanType is ScanType {\n  return Object.keys(SCAN_COSTS).includes(scanType);\n}\n"},Symbol.toStringTag,{value:"Module"})),ot=Object.freeze(Object.defineProperty({__proto__:null,default:"// Toast interface (for widget, we'll use simple console/alerts)\nexport interface ToastProps {\n  title?: string;\n  description?: string;\n  variant?: \"default\" | \"destructive\";\n}\n\n// Simple toast function for widget with visual feedback\nexport function toast({ title, description, variant }: ToastProps) {\n  const message = `${title || ''}${description ? `: ${description}` : ''}`;\n  \n  // Log to console for debugging\n  if (variant === \"destructive\") {\n    console.error('🚨 MockDetector:', message);\n  } else {\n    console.log('✅ MockDetector:', message);\n  }\n  \n  // Create visual toast notification\n  if (typeof document !== 'undefined') {\n    const toastEl = document.createElement('div');\n    toastEl.className = `mockdetector-toast ${variant === 'destructive' ? 'error' : 'success'}`;\n    toastEl.textContent = message;\n    toastEl.style.cssText = `\n      position: fixed;\n      bottom: 20px;\n      right: 20px;\n      background: ${variant === 'destructive' ? '#dc2626' : '#16a34a'};\n      color: white;\n      padding: 12px 20px;\n      border-radius: 8px;\n      box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n      z-index: 999999;\n      font-family: system-ui, -apple-system, sans-serif;\n      font-size: 14px;\n      animation: slideIn 0.3s ease-out;\n      max-width: 400px;\n    `;\n    \n    // Add animation styles if not present\n    if (!document.getElementById('mockdetector-toast-styles')) {\n      const style = document.createElement('style');\n      style.id = 'mockdetector-toast-styles';\n      style.textContent = `\n        @keyframes slideIn {\n          from { transform: translateX(400px); opacity: 0; }\n          to { transform: translateX(0); opacity: 1; }\n        }\n        @keyframes slideOut {\n          from { transform: translateX(0); opacity: 1; }\n          to { transform: translateX(400px); opacity: 0; }\n        }\n      `;\n      document.head.appendChild(style);\n    }\n    \n    document.body.appendChild(toastEl);\n    \n    // Auto-remove after 3 seconds\n    setTimeout(() => {\n      toastEl.style.animation = 'slideOut 0.3s ease-in';\n      setTimeout(() => toastEl.remove(), 300);\n    }, 3000);\n  }\n}\n\n// Hook (for compatibility with component code)\nexport function useToast() {\n  return {\n    toast,\n    dismiss: () => {},\n    toasts: []\n  };\n}\n"},Symbol.toStringTag,{value:"Module"})),it=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState, useEffect, useRef } from 'react';\nimport { logDiagnostics } from '../utils/diagnostics';\n\n// Production defaults - customers can override if needed\nconst DEFAULT_VALIDATION_ENDPOINT = 'https://tzowmzqfbicbyvikhdwy.supabase.co/functions/v1/validate-mockdetector-key';\nconst DEFAULT_HEARTBEAT_ENDPOINT = 'https://tzowmzqfbicbyvikhdwy.supabase.co/functions/v1/widget-heartbeat';\nconst HEARTBEAT_INTERVAL = 5 * 60 * 1000; // 5 minutes\n\n// Automatically synced from package.json during build\ndeclare const __WIDGET_VERSION__: string;\nconst CURRENT_WIDGET_VERSION = __WIDGET_VERSION__;\n\ninterface ApiKeyValidationResult {\n  isValid: boolean | null;\n  validationError: string | null;\n  dailyScanLimit: number;\n  isLoading: boolean;\n  keyData: {\n    tier: string;\n    domain: string | null;\n    scansUsedToday: number;\n  } | null;\n}\n\nexport const useApiKeyValidation = (\n  apiKey?: string,\n  enableHeartbeat = true,\n  validationEndpoint = DEFAULT_VALIDATION_ENDPOINT,\n  heartbeatEndpoint = DEFAULT_HEARTBEAT_ENDPOINT\n): ApiKeyValidationResult => {\n  const [isValid, setIsValid] = useState<boolean | null>(null);\n  const [validationError, setValidationError] = useState<string | null>(null);\n  const [dailyScanLimit, setDailyScanLimit] = useState<number>(50); // Default free tier limit\n  const [isLoading, setIsLoading] = useState<boolean>(false);\n  const [keyData, setKeyData] = useState<ApiKeyValidationResult['keyData']>(null);\n  const heartbeatIntervalRef = useRef<NodeJS.Timeout | null>(null);\n\n  // Validate API key on mount and when it changes\n  useEffect(() => {\n    if (!apiKey) {\n      setIsValid(null);\n      setValidationError(null);\n      setDailyScanLimit(50); // Default limit for local dev\n      setKeyData(null);\n      return;\n    }\n\n    const validateApiKey = async () => {\n      setIsLoading(true);\n      try {\n        const response = await fetch(validationEndpoint, {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({\n            apiKey,\n            domain: window.location.hostname\n          })\n        });\n\n        const result = await response.json();\n\n        if (result.valid) {\n          setIsValid(true);\n          setValidationError(null);\n          setDailyScanLimit(result.dailyScanLimit || 60);\n          setKeyData({\n            tier: result.tier || 'free',\n            domain: result.domain || null,\n            scansUsedToday: result.scansUsedToday || 0\n          });\n        } else {\n          const errorMessage = result.error || 'Invalid API key';\n          setIsValid(false);\n          setValidationError(errorMessage);\n          setDailyScanLimit(0);\n          setKeyData(null);\n          \n          // Log diagnostic information for debugging\n          logDiagnostics(errorMessage);\n        }\n      } catch (error) {\n        console.error('[MockDetector] API key validation failed:', error);\n        const errorMessage = 'Failed to validate API key';\n        setIsValid(false);\n        setValidationError(errorMessage);\n        setDailyScanLimit(0);\n        setKeyData(null);\n        \n        // Log diagnostic information\n        logDiagnostics(errorMessage);\n      } finally {\n        setIsLoading(false);\n      }\n    };\n\n    validateApiKey();\n  }, [apiKey]);\n\n  // Send heartbeat every 5 minutes\n  useEffect(() => {\n    if (!apiKey || !enableHeartbeat || !isValid) {\n      // Clear interval if conditions not met\n      if (heartbeatIntervalRef.current) {\n        clearInterval(heartbeatIntervalRef.current);\n        heartbeatIntervalRef.current = null;\n      }\n      return;\n    }\n\n    const sendHeartbeat = async () => {\n      try {\n        await fetch(heartbeatEndpoint, {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({\n            apiKey,\n            domain: window.location.hostname,\n            widgetVersion: CURRENT_WIDGET_VERSION\n          })\n        });\n      } catch (error) {\n        console.error('[MockDetector] Heartbeat failed:', error);\n      }\n    };\n\n    // Send initial heartbeat\n    sendHeartbeat();\n\n    // Set up interval for recurring heartbeats\n    heartbeatIntervalRef.current = setInterval(sendHeartbeat, HEARTBEAT_INTERVAL);\n\n    // Cleanup on unmount or when dependencies change\n    return () => {\n      if (heartbeatIntervalRef.current) {\n        clearInterval(heartbeatIntervalRef.current);\n        heartbeatIntervalRef.current = null;\n      }\n    };\n  }, [apiKey, enableHeartbeat, isValid]);\n\n  return {\n    isValid,\n    validationError,\n    dailyScanLimit,\n    isLoading,\n    keyData\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),rt=Object.freeze(Object.defineProperty({__proto__:null,default:"// ============================================\n// MockDetector Beta Credits - API-Key Integration\n// ============================================\n// Built by Silver (Anton Fredriksson) 🇸🇪\n// Now with server-side credit management + refunds\n// ============================================\n\nimport { useState, useEffect } from 'react';\nimport { SCAN_COSTS } from '../config/scan-costs';\nimport { WIDGET_CONFIG } from '../config';\n\nconst STORAGE_KEY_DAILY_SCANS = 'mockdetector-daily-scans';\nconst STORAGE_KEY_LAST_RESET = 'mockdetector-last-reset';\nconst STORAGE_KEY_FEEDBACK = 'mockdetector-feedback-submitted';\n\ninterface ServerCreditsResponse {\n  success: boolean;\n  scanToken?: string;\n  creditsRemaining?: number;\n  bonusCredits?: number;\n  purchasedCredits?: number;\n  scansRemainingToday?: number;\n  scanCost?: number;\n  error?: string;\n  message?: string;\n}\n\n/**\n * Hook for managing MockDetector credits (formerly useBetaCredits - kept for backwards compatibility)\n */\nexport const useCredits = (apiKey?: string, apiDailyScanLimit?: number, storagePrefix: string = '') => {\n  // Server-side credits (source of truth when API key is provided)\n  const [serverCredits, setServerCredits] = useState<number | null>(null);\n  const [bonusCredits, setBonusCredits] = useState<number>(0);\n  const [purchasedCredits, setPurchasedCredits] = useState<number>(0);\n  const [isLoadingCredits, setIsLoadingCredits] = useState(false);\n  \n  // Local-only state for no-API-key mode\n  const [dailyScans, setDailyScans] = useState<number>(() => getInitialDailyScans(storagePrefix));\n  const maxDailyScans = apiDailyScanLimit ?? 50;\n\n  // Feedback system state\n  const [feedbackSubmitted, setFeedbackSubmitted] = useState<boolean>(() => {\n    if (typeof window === 'undefined') return false;\n    return localStorage.getItem(`${storagePrefix}${STORAGE_KEY_FEEDBACK}`) === 'true';\n  });\n\n  // On mount, if API key exists, fetch server credits (will be updated after first scan)\n  useEffect(() => {\n    if (apiKey) {\n      // Credits will be fetched after first scan request\n      setIsLoadingCredits(true);\n    }\n  }, [apiKey]);\n\n  // Check if user can scan\n  const canScan = (cost: number = 1): boolean => {\n    // If API key mode, check server credits (if available)\n    if (apiKey) {\n      if (serverCredits !== null) {\n        return serverCredits >= cost && dailyScans < maxDailyScans;\n      }\n      // If server credits not yet fetched, allow (will be validated server-side)\n      return dailyScans < maxDailyScans;\n    }\n    \n    // Local dev mode - check daily scans only\n    return dailyScans < maxDailyScans;\n  };\n\n  // ✅ NEW: Request scan from server (deducts credits server-side)\n  const requestScan = async (scanType: keyof typeof SCAN_COSTS): Promise<ServerCreditsResponse> => {\n    if (!apiKey) {\n      // Local dev mode - just increment daily scans\n      const newDailyScans = dailyScans + 1;\n      setDailyScans(newDailyScans);\n      localStorage.setItem(`${storagePrefix}${STORAGE_KEY_DAILY_SCANS}`, String(newDailyScans));\n      \n      return {\n        success: true,\n        scanToken: crypto.randomUUID(),\n        creditsRemaining: 999, // Infinite for local dev\n        scansRemainingToday: maxDailyScans - newDailyScans,\n        scanCost: SCAN_COSTS[scanType]\n      };\n    }\n\n    // ✅ Production mode - call server to deduct credits\n    try {\n      const response = await fetch(WIDGET_CONFIG.RECORD_SCAN_ENDPOINT, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          apiKey,\n          scanType,\n          domain: window.location.hostname\n        })\n      });\n\n      const data: ServerCreditsResponse = await response.json();\n\n      if (data.success && data.creditsRemaining !== undefined) {\n        // Update local state with server credits\n        setServerCredits(data.creditsRemaining);\n        setBonusCredits(data.bonusCredits || 0);\n        setPurchasedCredits(data.purchasedCredits || 0);\n        setIsLoadingCredits(false);\n        \n        // Increment daily scans\n        const newDailyScans = dailyScans + 1;\n        setDailyScans(newDailyScans);\n        localStorage.setItem(`${storagePrefix}${STORAGE_KEY_DAILY_SCANS}`, String(newDailyScans));\n      }\n\n      return data;\n    } catch (error) {\n      console.error('Failed to request scan from server:', error);\n      return {\n        success: false,\n        error: 'Failed to connect to server. Please try again.'\n      };\n    }\n  };\n\n  // Get remaining daily scans\n  const remainingDailyScans = Math.max(0, maxDailyScans - dailyScans);\n\n  // Display credits (server credits if available, otherwise \"local dev mode\")\n  const displayCredits = serverCredits !== null \n    ? serverCredits \n    : (apiKey ? 'Loading...' : 'Unlimited (Dev)');\n\n  // Feedback system\n  const feedbackBonus = 80;\n  const initialCredits = 50;\n\n  const canSubmitFeedback = (): boolean => {\n    return !feedbackSubmitted && apiKey !== undefined;\n  };\n\n  const submitFeedback = async (feedbackText: string): Promise<{success: boolean; error?: string}> => {\n    if (!apiKey) {\n      return { success: false, error: 'API key required for feedback' };\n    }\n\n    if (feedbackSubmitted) {\n      return { success: false, error: 'Feedback already submitted' };\n    }\n\n    try {\n      const response = await fetch(WIDGET_CONFIG.SUBMIT_FEEDBACK_ENDPOINT, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ apiKey, feedbackText })\n      });\n\n      const data = await response.json();\n\n      if (data.success) {\n        setFeedbackSubmitted(true);\n        localStorage.setItem(`${storagePrefix}${STORAGE_KEY_FEEDBACK}`, 'true');\n        \n        // Update credits immediately\n        if (data.newCreditsBalance !== undefined) {\n          setServerCredits(data.newCreditsBalance);\n        }\n\n        return { success: true };\n      } else {\n        return { success: false, error: data.error || data.message };\n      }\n    } catch (error) {\n      console.error('Failed to submit feedback:', error);\n      return { success: false, error: 'Network error. Please try again.' };\n    }\n  };\n\n  // ⚠️ DEPRECATED: Old methods kept for backwards compatibility\n  const deductCredit = (_cost: number) => true; // Always succeed since server handles it\n  const setCustomCredits = (_amount: number) => {};\n  const isAdminMode = false;\n  const enableAdminMode = (_password: string) => false;\n\n  /**\n   * 🆕 PHASE B: Report scan result to server for credit refund\n   * Call this after scan completes with the number of errors found\n   */\n  const reportScanResult = async (\n    scanToken: string | undefined,\n    errorsFound: number,\n    scanType: keyof typeof SCAN_COSTS\n  ): Promise<void> => {\n    if (!apiKey || !scanToken) {\n      return; // No API key or token, skip reporting\n    }\n\n    try {\n      const response = await fetch(WIDGET_CONFIG.REPORT_SCAN_RESULT_ENDPOINT, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({\n          scanToken,\n          errorsFound,\n          scanType,\n          apiKey\n        })\n      });\n\n      const data = await response.json();\n\n      if (data.success && data.creditsRefunded) {\n        // Update local balance with refunded credits\n        setServerCredits(data.creditsBalance);\n        console.log(`✅ ${data.refundAmount} credits refunded (no errors found)`);\n      }\n    } catch (error) {\n      console.error('Error reporting scan result:', error);\n    }\n  };\n\n  return {\n    credits: displayCredits,\n    serverCredits,\n    bonusCredits,\n    purchasedCredits,\n    dailyScans,\n    remainingDailyScans,\n    canScan,\n    requestScan, // ✅ Main scan request method\n    reportScanResult, // 🆕 PHASE B: Report scan results for refunds\n    maxDailyScans,\n    scanCosts: SCAN_COSTS,\n    isLoadingCredits,\n    // Deprecated methods for backwards compatibility\n    feedbackSubmitted,\n    canSubmitFeedback,\n    submitFeedback,\n    deductCredit,\n    feedbackBonus,\n    setCustomCredits,\n    initialCredits,\n    isAdminMode,\n    enableAdminMode\n  };\n};\n\n// Export both names for backwards compatibility\nexport { useCredits as useBetaCredits };\n\n// Helper functions\nfunction getInitialDailyScans(storagePrefix: string = ''): number {\n  if (typeof window === 'undefined') return 0;\n  \n  try {\n    const lastReset = localStorage.getItem(`${storagePrefix}${STORAGE_KEY_LAST_RESET}`);\n    const today = new Date().toDateString();\n    \n    if (lastReset !== today) {\n      localStorage.setItem(`${storagePrefix}${STORAGE_KEY_LAST_RESET}`, today);\n      localStorage.setItem(`${storagePrefix}${STORAGE_KEY_DAILY_SCANS}`, '0');\n      return 0;\n    }\n    \n    const stored = localStorage.getItem(`${storagePrefix}${STORAGE_KEY_DAILY_SCANS}`);\n    return stored !== null ? parseInt(stored, 10) : 0;\n  } catch (e) {\n    return 0;\n  }\n}\n"},Symbol.toStringTag,{value:"Module"})),ct=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState } from 'react';\nimport { supabase } from '@/integrations/supabase/client';\nimport { DatabaseScanResult, DatabaseViolation } from '../types/database.types';\nimport { DATABASE_MOCK_PATTERNS, analyzeTableLevelPatterns } from '../utils/databasePatterns';\nimport { calculateViolationConfidence } from '../utils/confidenceScoring';\nimport { enhanceViolationWithFix } from '../utils/contextualAutoFix';\n\nexport const useDatabaseScanner = () => {\n  const [isScanning, setIsScanning] = useState(false);\n  const [progress, setProgress] = useState<string>('');\n\n  // NEW: Intelligent database scanning with adaptive sampling\n  const scanDatabase = async (\n    rowsPerTable: number = 50,\n    prioritizedTables?: string[],\n    onlyPrioritized: boolean = false,\n    intelligentSampling: boolean = false\n  ): Promise<DatabaseScanResult> => {\n    setIsScanning(true);\n    const startTime = Date.now();\n    const violations: DatabaseViolation[] = [];\n    let tablesScanned = 0;\n    let rowsAnalyzed = 0;\n\n    try {\n      // Get all tables from public schema dynamically\n      setProgress('Fetching table list...');\n      const { data: tables, error: tablesError } = await supabase.rpc('get_public_tables' as any);\n\n      if (tablesError) {\n        console.error('❌ Error fetching tables:', tablesError);\n        throw new Error(`Could not fetch table list: ${tablesError.message}`);\n      }\n\n      let tableNames = Array.isArray(tables) ? tables : [];\n      console.log(`📊 Found ${tableNames.length} tables to scan`);\n      \n      // Apply prioritization if specified\n      if (prioritizedTables && prioritizedTables.length > 0) {\n        const prioritized = tableNames.filter(t => {\n          const name = typeof t === 'string' ? t : t.table_name;\n          return prioritizedTables.includes(name);\n        });\n        \n        if (onlyPrioritized) {\n          tableNames = prioritized;\n          console.log(`🎯 Scanning only ${tableNames.length} prioritized tables`);\n        } else {\n          // Scan prioritized first, then others\n          const others = tableNames.filter(t => {\n            const name = typeof t === 'string' ? t : t.table_name;\n            return !prioritizedTables.includes(name);\n          });\n          tableNames = [...prioritized, ...others];\n          console.log(`🎯 Prioritizing ${prioritized.length} tables, then ${others.length} others`);\n        }\n      }\n      \n      for (const tableData of tableNames) {\n        const tableName = typeof tableData === 'string' ? tableData : tableData.table_name;\n        if (!tableName) continue;\n\n        try {\n          setProgress(`Scanning ${tableName} (${tablesScanned + 1}/${tableNames.length})...`);\n          const tableViolations = await scanTable(tableName, rowsPerTable, intelligentSampling);\n          violations.push(...tableViolations);\n          tablesScanned++;\n          rowsAnalyzed += rowsPerTable;\n        } catch (err) {\n          console.warn(`Could not scan table ${tableName}:`, err);\n        }\n      }\n\n      const scanDuration = Date.now() - startTime;\n      setProgress('');\n      setIsScanning(false);\n\n      return {\n        totalViolations: violations.length,\n        violations,\n        tablesScanned,\n        rowsAnalyzed,\n        scanDuration,\n        scannedAt: new Date()\n      };\n    } catch (error) {\n      console.error('Database scan error:', error);\n      setIsScanning(false);\n      setProgress('');\n      throw error;\n    }\n  };\n\n  const scanTable = async (\n    tableName: string, \n    rowsPerTable: number = 50,\n    intelligentSampling: boolean = false\n  ): Promise<DatabaseViolation[]> => {\n    const violations: DatabaseViolation[] = [];\n\n    try {\n      let rows: any[] = [];\n      \n      if (intelligentSampling && rowsPerTable >= 100) {\n        // Intelligent sampling: First N, Last N, Random N from middle\n        const sampleSize = Math.floor(rowsPerTable / 3);\n        \n        // Get first N rows\n        const { data: firstRows, error: firstError }: any = await supabase\n          .from(tableName as any)\n          .select('*')\n          .order('created_at', { ascending: true })\n          .limit(sampleSize);\n        \n        if (firstError) throw firstError;\n        \n        // Get last N rows\n        const { data: lastRows, error: lastError }: any = await supabase\n          .from(tableName as any)\n          .select('*')\n          .order('created_at', { ascending: false })\n          .limit(sampleSize);\n        \n        if (lastError) throw lastError;\n        \n        // Get random N rows from middle (approximate)\n        const { data: randomRows, error: randomError }: any = await supabase\n          .from(tableName as any)\n          .select('*')\n          .limit(sampleSize);\n        \n        if (randomError) throw randomError;\n        \n        rows = [...(firstRows || []), ...(lastRows || []), ...(randomRows || [])];\n        console.log(`  📊 Intelligent sampling: ${rows.length} rows from ${tableName}`);\n      } else {\n        // Standard sampling: Just get first N rows\n        const { data, error }: any = await supabase\n          .from(tableName as any)\n          .select('*')\n          .limit(rowsPerTable);\n\n        if (error) throw error;\n        rows = data || [];\n      }\n\n      if (!rows || rows.length === 0) {\n        return violations;\n      }\n\n      // Analyze table-level patterns (sequential IDs, identical timestamps)\n      const tableLevelPatterns = analyzeTableLevelPatterns(rows);\n      for (const pattern of tableLevelPatterns) {\n        const violation: DatabaseViolation = {\n          table: tableName,\n          column: 'table_level',\n          pattern: pattern.pattern,\n          severity: pattern.severity,\n          description: pattern.description,\n          examples: pattern.examples,\n          affectedRows: rows.length,\n          confidence: 0 // Will be calculated below\n        };\n        \n        // ✅ PHASE 3: Calculate confidence dynamically\n        violation.confidence = calculateViolationConfidence(violation);\n        \n        // Boost confidence for clear seed data patterns\n        if (pattern.description.includes('identical') && pattern.description.includes('days ago')) {\n          violation.confidence = Math.max(75, violation.confidence); // Up from 60\n        }\n        \n        // ✅ PHASE 4: Enhance with contextual auto-fix\n        const enhanced = enhanceViolationWithFix(violation) as DatabaseViolation;\n        \n        // Lower threshold: 40% instead of 50%\n        if (enhanced.confidence >= 40) {\n          violations.push(enhanced);\n        }\n      }\n\n      // Analyze each column for mock patterns\n      const columns = Object.keys(rows[0]);\n      \n      for (const column of columns) {\n        for (const pattern of DATABASE_MOCK_PATTERNS) {\n          const matchedValues: string[] = [];\n          \n          for (const row of rows) {\n            const value = row[column];\n            if (value !== null && value !== undefined && pattern.test(value)) {\n              const example = pattern.getExamples ? pattern.getExamples(value) : String(value);\n              if (!matchedValues.includes(example)) {\n                matchedValues.push(example);\n              }\n              if (matchedValues.length >= 5) break; // Limit examples\n            }\n          }\n\n          if (matchedValues.length > 0) {\n            const violation: DatabaseViolation = {\n              table: tableName,\n              column,\n              pattern: pattern.name,\n              severity: pattern.severity,\n              description: pattern.description,\n              examples: matchedValues,\n              affectedRows: matchedValues.length,\n              confidence: 0 // Will be calculated below\n            };\n            \n            // ✅ PHASE 3: Calculate confidence dynamically\n            violation.confidence = calculateViolationConfidence(violation);\n            \n            // Boost confidence for meme numbers and round prices\n            if (pattern.description.includes('meme') || pattern.description.includes('test numbers')) {\n              violation.confidence = Math.max(70, violation.confidence); // Up from 60\n            }\n            if (pattern.description.includes('round') && pattern.description.includes('prices')) {\n              violation.confidence = Math.max(65, violation.confidence); // Up from 60\n            }\n            \n            // ✅ PHASE 4: Enhance with contextual auto-fix\n            const enhanced = enhanceViolationWithFix(violation) as DatabaseViolation;\n            \n            // Lower threshold: 40% instead of 50%\n            if (enhanced.confidence >= 40) {\n              violations.push(enhanced);\n            }\n          }\n        }\n      }\n\n      return violations;\n    } catch (error) {\n      console.error(`Error scanning table ${tableName}:`, error);\n      return violations;\n    }\n  };\n\n  return {\n    scanDatabase,\n    isScanning,\n    progress\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),lt=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { MockViolation, ScanResult } from '../types/mockdetector.types';\nimport { \n  MOCK_DATA_PATTERNS, \n  STATISTICAL_CLAIM_PATTERNS,\n  STATIC_DATA_PATTERNS\n} from '../utils/scanPatterns';\nimport { scanReactCode } from '../utils/reactPatterns';\nimport { generateAllAutoFixes } from '../utils/autoFix';\nimport { calculateHealthScore, ProjectHealthScore } from '../utils/healthScore';\nimport { detectProjectSize, getAllRoutes } from '../utils/projectSizeDetection';\nimport { DEFAULT_SCAN_CONFIGS, ProjectSize, SourceFileScanConfig } from '../types/scanConfig.types';\nimport { useClientSourceScanner } from './useClientSourceScanner';\nimport { calculateViolationConfidence } from '../utils/confidenceScoring';\nimport { enhanceViolationWithFix } from '../utils/contextualAutoFix';\n// Optional: tableMapping can be configured by developer for their own Supabase\n// import { resolveTable } from '../utils/tableMapping';\n\nexport const useMockDetection = () => {\n  const navigate = useNavigate();\n  const [isScanning, setIsScanning] = useState(false);\n  const [scanResult, setScanResult] = useState<ScanResult | null>(null);\n  const [currentScanProgress, setCurrentScanProgress] = useState<string>('');\n  const [isDeepScanning, setIsDeepScanning] = useState(false);\n  const [healthScore, setHealthScore] = useState<ProjectHealthScore | null>(null);\n  \n  // ✅ Initialize client-side scanner at top-level (React hooks rule compliance)\n  const { scanProjectFiles, progress: sourceFileProgress, filesScanned, totalFiles } = useClientSourceScanner();\n\n  const scanDOM = (): MockViolation[] => {\n    const violations: MockViolation[] = [];\n    // DOM scanning for mock data patterns removed - focus on code/UI scanning\n    return violations;\n  };\n\n  // scanUIComponents() REMOVED - caused 90% false positives\n  // Focus on source code patterns instead (higher precision)\n\n  const scanStatisticalClaims = (): MockViolation[] => {\n    const violations: MockViolation[] = [];\n    \n    // Get all text BUT exclude MockDetector's UI and toast notifications\n    let allText = document.body.innerText;\n    \n    // Exclude MockDetector widget\n    const mockDetectorElement = document.querySelector('[data-mockdetector-ignore]');\n    if (mockDetectorElement) {\n      const mockDetectorText = mockDetectorElement.textContent || '';\n      allText = allText.replace(mockDetectorText, '');\n    }\n    \n    // Exclude toast notifications\n    const toastContainer = document.querySelector('[data-sonner-toaster]');\n    if (toastContainer) {\n      const toastText = toastContainer.textContent || '';\n      allText = allText.replace(toastText, '');\n    }\n    \n    const lines = allText.split('\\n');\n    const seenClaims = new Set<string>(); // Deduplicate exact same claims\n\n    lines.forEach((line, index) => {\n      STATISTICAL_CLAIM_PATTERNS.forEach(({ pattern, severity, description }) => {\n        const matches = line.matchAll(pattern);\n        for (const match of matches) {\n          const claimText = match[0];\n          const claimKey = `${description}-${claimText}`; // Unique key per claim type + text\n          \n          // Skip if we've already found this exact claim\n          if (seenClaims.has(claimKey)) return;\n          seenClaims.add(claimKey);\n          \n          violations.push({\n            type: 'mock_data',\n            severity,\n            line: index + 1,\n            code: line.trim(),\n            description: `${description}: \"${claimText}\"`,\n            fix: 'Verify this claim with real-time data from your database or API'\n          });\n        }\n      });\n    });\n\n    return violations;\n  };\n\n  // NOTE: Data consistency validation removed - this is a standalone tool\n  // Developers can optionally implement their own data validation by extending this hook\n\n  const scanCode = (codeText: string, fileName?: string): MockViolation[] => {\n    const violations: MockViolation[] = [];\n    const lines = codeText.split('\\n');\n    \n    // ✅ NEW: Smart whitelisting import (add at top of file later)\n    // For now, inline whitelist check\n    const isWhitelistedFile = (file?: string): boolean => {\n      if (!file) return false;\n      const whitelistPatterns = [\n        /scanPatterns\\.ts$/,\n        /mockDetector/i,\n        /databasePatterns\\.ts$/,\n        /reactPatterns\\.ts$/,\n        /smartWhitelist\\.ts$/,\n        /\\.config\\.(ts|js)$/,\n        /tailwind\\.config/,\n        /vite\\.config/,\n      ];\n      return whitelistPatterns.some(p => p.test(file));\n    };\n    \n    const isWhitelistedCode = (line: string): boolean => {\n      const patterns = [\n        /VITE_SUPABASE_PUBLISHABLE_KEY/,\n        /VITE_SUPABASE_URL/,\n        /\\.from\\(['\"][\\w_]+['\"]\\)/,\n        /\\.select\\(/,\n        /\\.limit\\(\\d+\\)/,\n        /^import\\s+/,\n        /^export\\s+/,\n        /CRITICAL.*REAL.*AUTHENTIC/,\n      ];\n      return patterns.some(p => p.test(line));\n    };\n    \n    // Keywords to skip (MockDetector's own UI text)\n    const skipKeywords = [\n      'MockDetector',\n      'Quick Scan',\n      'Scan All Routes',\n      'Total Issues',\n      'Scanned:',\n      'Generated by MockDetector',\n      'Mock Data Violations',\n      'Security Issues',\n      'Scan Duration',\n      'mock_data',\n      'test-data',\n      'Role Visibility Problems'\n    ];\n\n    // ✅ NEW: Skip whitelisted files entirely\n    if (isWhitelistedFile(fileName)) {\n      return [];\n    }\n\n    // Check for mock data patterns\n    MOCK_DATA_PATTERNS.forEach(({ pattern, severity, description }) => {\n      lines.forEach((line, index) => {\n        // Skip lines containing MockDetector keywords\n        if (skipKeywords.some(kw => line.includes(kw))) return;\n        \n        // ✅ NEW: Skip whitelisted code patterns\n        if (isWhitelistedCode(line)) return;\n        \n        if (pattern.test(line)) {\n          const violation: MockViolation = {\n            type: 'mock_data',\n            severity,\n            file: fileName,\n            line: index + 1,\n            code: line.trim(),\n            description,\n            fix: 'Replace with real data from your database or API',\n            confidence: 0 // Will be calculated\n          };\n          \n          // ✅ PHASE 3: Calculate confidence\n          violation.confidence = calculateViolationConfidence(violation);\n          \n          // ✅ PHASE 4: Enhance with contextual auto-fix\n          const enhanced = enhanceViolationWithFix(violation) as MockViolation;\n          \n          // Only add if confidence >= 50%\n          if (enhanced.confidence && enhanced.confidence >= 50) {\n            violations.push(enhanced);\n          }\n        }\n      });\n    });\n    \n    // Check for static data patterns (arrays/objects with hardcoded data)\n    STATIC_DATA_PATTERNS.forEach(({ pattern, severity, description }) => {\n      const matches = codeText.matchAll(pattern);\n      for (const match of matches) {\n        // Find line number\n        const lineNumber = codeText.substring(0, match.index).split('\\n').length;\n        const line = lines[lineNumber - 1];\n        \n        // Skip if line contains skip keywords\n        if (skipKeywords.some(kw => line?.includes(kw))) continue;\n        \n        // ✅ NEW: Skip whitelisted code patterns\n        if (line && isWhitelistedCode(line)) continue;\n        \n        const violation: MockViolation = {\n          type: 'mock_data',\n          severity,\n          file: fileName,\n          line: lineNumber,\n          code: line?.trim() || match[0].trim(),\n          description,\n          fix: 'Replace with data fetched from database or API. Use useState/useEffect to load dynamic data.',\n          confidence: 0 // Will be calculated\n        };\n        \n        // ✅ PHASE 3: Calculate confidence\n        violation.confidence = calculateViolationConfidence(violation);\n        \n        // ✅ PHASE 4: Enhance with contextual auto-fix\n        const enhanced = enhanceViolationWithFix(violation) as MockViolation;\n        \n        // Only add if confidence >= 50%\n        if (enhanced.confidence && enhanced.confidence >= 50) {\n          violations.push(enhanced);\n        }\n      }\n    });\n\n    // NEW: React-specific pattern scanning\n    const reactViolations = scanReactCode(codeText, fileName);\n    violations.push(...reactViolations);\n\n    return violations;\n  };\n\n  const runScan = async (): Promise<ScanResult> => {\n    setIsScanning(true);\n    const startTime = performance.now();\n\n    try {\n      console.log('🔍 MockDetector: Starting aggressive deep scan...');\n      \n      // Phase 1: Basic pattern detection\n      const domViolations = scanDOM();\n      const bodyText = document.body.innerText;\n      const currentRoute = window.location.pathname;\n      const codeViolations = scanCode(bodyText, currentRoute);\n      \n      // Phase 2: Statistical claims detection\n      console.log('🔍 Phase 3: Scanning for statistical claims...');\n      const statisticalClaimViolations = scanStatisticalClaims();\n      \n      // Combine all violations\n      const allViolations = [\n        ...domViolations,\n        ...codeViolations,\n        ...statisticalClaimViolations\n      ];\n\n      // All violations are mock_data type now\n      const mockDataViolations = allViolations;\n\n      const result: ScanResult = {\n        totalViolations: allViolations.length,\n        mockDataViolations,\n        scanDuration: performance.now() - startTime,\n        scannedAt: new Date()\n      };\n\n      console.log(`✅ MockDetector: Scan complete. Found ${result.totalViolations} violations in ${result.scanDuration.toFixed(0)}ms`);\n      \n      // Calculate health score\n      const health = calculateHealthScore(result, healthScore?.overall);\n      setHealthScore(health);\n      console.log(`📊 Health Score: ${health.overall}/100 (${health.grade})`);\n      \n      setScanResult(result);\n      return result;\n    } catch (error) {\n      console.error('❌ MockDetector: Scan failed:', error);\n      throw error;\n    } finally {\n      setIsScanning(false);\n    }\n  };\n\n  // Helper: Create unique key for violation\n  const getViolationKey = (v: MockViolation): string => {\n    return `${v.type}|${v.description}|${v.code?.substring(0, 50) || ''}`;\n  };\n\n  // Helper: Filter duplicate violations\n  const filterDuplicates = (violations: MockViolation[]): MockViolation[] => {\n    const seen = new Map<string, { violation: MockViolation; routes: Set<string> }>();\n    \n    violations.forEach(v => {\n      const key = getViolationKey(v);\n      const existing = seen.get(key);\n      \n      if (!existing) {\n        seen.set(key, {\n          violation: v,\n          routes: new Set(v.route ? [v.route] : [])\n        });\n      } else if (v.route && v.route !== existing.violation.route) {\n        // Same violation on different routes - track all routes\n        existing.routes.add(v.route);\n      }\n    });\n    \n    // Build final violations with route information\n    return Array.from(seen.values()).map(({ violation, routes }) => {\n      if (routes.size > 1) {\n        const routeList = Array.from(routes).join(', ');\n        return {\n          ...violation,\n          description: `${violation.description} (found on ${routes.size} routes: ${routeList})`\n        };\n      }\n      return violation;\n    });\n  };\n\n  const runMultiRouteScan = async (routes: string[]): Promise<ScanResult> => {\n    setIsScanning(true);\n    const startTime = performance.now();\n    \n    // Save current route to restore after scanning\n    const originalRoute = window.location.pathname;\n    \n    // Smart timeout based on number of routes (safety net)\n    const timeoutMs = routes.length < 10 ? 180000 :      // Small: 3 minutes\n                      routes.length < 30 ? 300000 :      // Medium: 5 minutes  \n                      600000;                            // Large: 10 minutes\n    \n    let timeoutId: number | null = null;\n    let isTimedOut = false;\n    \n    try {\n      console.log(`🔍 MockDetector: Starting multi-route scan for ${routes.length} routes...`);\n      console.log(`📍 Original route: ${originalRoute} (will restore after scan)`);\n      console.log(`⏱️ Timeout set to ${timeoutMs / 1000 / 60} minutes for safety`);\n      \n      // Set timeout to prevent infinite scanning (cost protection)\n      timeoutId = window.setTimeout(() => {\n        isTimedOut = true;\n        console.warn(`⏱️ Multi-route scan timeout after ${timeoutMs / 1000 / 60} minutes`);\n      }, timeoutMs);\n      \n      const allViolations: MockViolation[] = [];\n      \n      for (let i = 0; i < routes.length; i++) {\n        // Check timeout\n        if (isTimedOut) {\n          console.warn(`⏱️ Multi-route scan timed out after ${i} routes`);\n          setCurrentScanProgress(`⚠️ Timeout after ${i} routes - returning partial results`);\n          break;\n        }\n        \n        const route = routes[i];\n        const progressPercent = Math.round((i / routes.length) * 100);\n        const progress = `Scanning route ${i + 1}/${routes.length} (${progressPercent}%): ${route}`;\n        console.log(`🔍 ${progress}`);\n        setCurrentScanProgress(progress);\n        \n        // Navigate using React Router with replace to not mess up history\n        navigate(route, { replace: true });\n        \n        // Wait longer for page to fully render (2 seconds)\n        await new Promise(resolve => setTimeout(resolve, 2000));\n        \n        // Run scan on this route\n        const domViolations = scanDOM();\n        const bodyText = document.body.innerText;\n        const codeViolations = scanCode(bodyText, route); // Use actual route instead of 'current-page'\n        const statisticalClaimViolations = scanStatisticalClaims();\n        \n        // Add route information to all violations from this scan\n        const routeViolations = [\n          ...domViolations,\n          ...codeViolations,\n          ...statisticalClaimViolations\n        ].map(v => ({ ...v, route }));\n        \n        // Filter duplicates EARLY (per route)\n        const uniqueRouteViolations = filterDuplicates(routeViolations);\n        \n        allViolations.push(...uniqueRouteViolations);\n        \n        console.log(`  ✓ Found ${uniqueRouteViolations.length} unique violations on ${route}`);\n      }\n      \n      // Clear timeout\n      if (timeoutId !== null) {\n        clearTimeout(timeoutId);\n      }\n      \n      // Final duplicate filtering across all routes\n      const finalViolations = filterDuplicates(allViolations);\n      \n      // All violations are mock_data type now\n      const mockDataViolations = finalViolations;\n      \n      const scanDuration = performance.now() - startTime;\n      const result: ScanResult = {\n        totalViolations: finalViolations.length,\n        mockDataViolations,\n        scanDuration,\n        scannedAt: new Date()\n      };\n      \n      if (isTimedOut) {\n        console.log(`⚠️ PARTIAL multi-route scan: ${result.totalViolations} violations (timed out, ${scanDuration.toFixed(0)}ms)`);\n        setCurrentScanProgress('⚠️ Timeout - Partial Results - Restoring route...');\n      } else {\n        console.log(`✅ MockDetector: Multi-route scan complete. Found ${result.totalViolations} unique violations across ${routes.length} routes`);\n        setCurrentScanProgress('✅ Scan Complete - Restoring original route...');\n      }\n      \n      // Restore original route\n      console.log(`📍 Restoring original route: ${originalRoute}`);\n      navigate(originalRoute, { replace: true });\n      \n      // Brief delay to ensure route restoration completes\n      await new Promise(resolve => setTimeout(resolve, 500));\n      \n      setCurrentScanProgress('✅ Scan Complete');\n      setScanResult(result);\n      return result;\n    } catch (error) {\n      console.error('❌ MockDetector: Multi-route scan failed:', error);\n      setCurrentScanProgress('❌ Scan Failed');\n      \n      // Clear timeout on error\n      if (timeoutId !== null) {\n        clearTimeout(timeoutId);\n      }\n      \n      // Always restore original route, even on error\n      console.log(`📍 Restoring original route after error: ${originalRoute}`);\n      navigate(originalRoute, { replace: true });\n      \n      throw error;\n    } finally {\n      setIsScanning(false);\n    }\n  };\n\n  // NEW: Deep scan source files CLIENT-SIDE (works for ANY Lovable project!)\n  // This scanner reads actual project files using Vite's import.meta.glob\n  // Perfect for external developers - scans THEIR code, not ours!\n  const scanSourceFiles = async (config?: SourceFileScanConfig): Promise<MockViolation[]> => {\n    console.log('🔍 Starting CLIENT-SIDE source file scan (works in any Lovable project)...');\n    \n    try {\n      console.log('📋 Scan config:', config || 'Using defaults');\n      \n      // ✅ Use scanProjectFiles from top-level hook (no hook call inside function!)\n      const violations = await scanProjectFiles(config);\n\n      console.log(`✅ Client-side source scan complete: ${violations.length} violations found`);\n      \n      return violations;\n      \n    } catch (error) {\n      console.error('❌ Client-side source file scan failed:', error);\n      return [];\n    }\n  };\n\n  // NEW: Run deep scan (DOM + Source Files)\n  const runDeepScan = async (): Promise<ScanResult> => {\n    setIsScanning(true);\n    setIsDeepScanning(true);\n    const startTime = performance.now();\n    \n    // Timeout for deep scan (longer since it includes source files)\n    const timeoutMs = 600000; // 10 minutes max\n    let timeoutId: number | null = null;\n    let isTimedOut = false;\n\n    try {\n      console.log('🔍 MockDetector: Starting DEEP SCAN (DOM + Source Files)...');\n      console.log(`⏱️ Timeout set to ${timeoutMs / 1000 / 60} minutes for safety`);\n      \n      // Set timeout\n      timeoutId = window.setTimeout(() => {\n        isTimedOut = true;\n        console.warn(`⏱️ Deep scan timeout after ${timeoutMs / 1000 / 60} minutes`);\n      }, timeoutMs);\n      \n      // Phase 1: Regular DOM scan\n      setCurrentScanProgress('Scanning DOM...');\n      const domViolations = scanDOM();\n      const bodyText = document.body.innerText;\n      const currentRoute = window.location.pathname;\n      const codeViolations = scanCode(bodyText, currentRoute); // Use actual route\n      const statisticalClaimViolations = scanStatisticalClaims();\n      \n      // Phase 2: Deep source file scan\n      setCurrentScanProgress(`Scanning source files (0 files)...`);\n      const sourceFileViolations = await scanSourceFiles();\n      \n      // Combine all violations\n      const allViolations = [\n        ...domViolations,\n        ...codeViolations,\n        ...statisticalClaimViolations,\n        ...sourceFileViolations\n      ];\n\n      // Clear timeout\n      if (timeoutId !== null) {\n        clearTimeout(timeoutId);\n      }\n\n      const mockDataViolations = allViolations;\n\n      const scanDuration = performance.now() - startTime;\n      const result: ScanResult = {\n        totalViolations: allViolations.length,\n        mockDataViolations,\n        scanDuration,\n        scannedAt: new Date()\n      };\n\n      if (isTimedOut) {\n        console.log(`⚠️ PARTIAL deep scan: ${result.totalViolations} violations (timed out, ${scanDuration.toFixed(0)}ms)`);\n      } else {\n        console.log(`✅ DEEP SCAN complete. Found ${result.totalViolations} violations in ${scanDuration.toFixed(0)}ms`);\n      }\n      console.log(`   - DOM scan: ${domViolations.length + codeViolations.length + statisticalClaimViolations.length}`);\n      console.log(`   - Source files: ${sourceFileViolations.length}`);\n      \n      setCurrentScanProgress(isTimedOut ? '⚠️ Timeout - Partial Results' : '✅ Deep Scan Complete');\n      setScanResult(result);\n      return result;\n    } catch (error) {\n      console.error('❌ Deep scan failed:', error);\n      \n      // Clear timeout on error\n      if (timeoutId !== null) {\n        clearTimeout(timeoutId);\n      }\n      \n      throw error;\n    } finally {\n      setIsScanning(false);\n      setIsDeepScanning(false);\n    }\n  };\n\n  // NEW: Smart Deep Scan - Auto-adapts based on project size\n  const runSmartDeepScan = async (customConfig?: {\n    includeEdgeFunctions?: boolean;\n    includeConfigFiles?: boolean;\n    customScanPath?: string;\n  }): Promise<ScanResult> => {\n    setIsScanning(true);\n    setIsDeepScanning(true);\n    const startTime = performance.now();\n    const originalRoute = window.location.pathname;\n    \n    let timeoutId: number | null = null;\n    let isTimedOut = false;\n\n    try {\n      console.log('🔍 MockDetector: Starting SMART DEEP SCAN...');\n      \n      // Phase 1: Detect project size\n      setCurrentScanProgress('Analyzing project size...');\n      const projectMetrics = await detectProjectSize();\n      const projectSize: ProjectSize = projectMetrics.size;\n      const allRoutes = await getAllRoutes();\n      \n      console.log(`📊 Project classified as: ${projectSize.toUpperCase()}`);\n      console.log(`   - Routes: ${projectMetrics.routeCount}`);\n      console.log(`   - Database: ${projectMetrics.databaseSize}`);\n      console.log(`   - Estimated files: ${projectMetrics.estimatedSourceFiles}`);\n      \n      // Smart timeout based on project size\n      const timeoutMs = projectSize === 'small' ? 180000 :      // Small: 3 minutes\n                        projectSize === 'medium' ? 300000 :     // Medium: 5 minutes  \n                        600000;                                 // Large: 10 minutes\n      \n      console.log(`⏱️ Timeout set to ${timeoutMs / 1000 / 60} minutes for ${projectSize} project`);\n      \n      // Set timeout\n      timeoutId = window.setTimeout(() => {\n        isTimedOut = true;\n        console.warn(`⏱️ Smart deep scan timeout after ${timeoutMs / 1000 / 60} minutes`);\n      }, timeoutMs);\n      \n      // Get scan config for this project size\n      const sizeConfig = DEFAULT_SCAN_CONFIGS[projectSize];\n      \n      // Override with custom settings if provided\n      const sourceFileConfig: SourceFileScanConfig = {\n        ...sizeConfig.sourceFiles,\n        ...(customConfig?.includeEdgeFunctions !== undefined && { includeEdgeFunctions: customConfig.includeEdgeFunctions }),\n        ...(customConfig?.includeConfigFiles !== undefined && { includeConfigFiles: customConfig.includeConfigFiles }),\n        ...(customConfig?.customScanPath && { rootPath: customConfig.customScanPath })\n      };\n      \n      // Phase 2: Route-based scanning (adaptive)\n      let routeViolations: MockViolation[] = [];\n      const routesToScan = allRoutes.slice(0, sizeConfig.routes.maxRoutes);\n      \n      if (routesToScan.length > 0) {\n        const isFullScan = routesToScan.length === allRoutes.length;\n        console.log(`🔍 Scanning ${routesToScan.length} routes (${isFullScan ? 'all routes' : `first ${sizeConfig.routes.maxRoutes} of ${allRoutes.length}`})...`);\n        \n        for (let i = 0; i < routesToScan.length; i++) {\n          // Check timeout\n          if (isTimedOut) {\n            console.warn(`⏱️ Smart scan timed out after ${i} routes`);\n            setCurrentScanProgress(`⚠️ Timeout after ${i} routes - continuing to source files...`);\n            break;\n          }\n          \n          const route = routesToScan[i];\n          const progressPercent = Math.round((i / routesToScan.length) * 100);\n          const progress = `Scanning route ${i + 1}/${routesToScan.length} (${progressPercent}%): ${route}`;\n          console.log(`🔍 ${progress}`);\n          setCurrentScanProgress(progress);\n          \n          navigate(route, { replace: true });\n          await new Promise(resolve => setTimeout(resolve, 1500));\n          \n          const domViolations = scanDOM();\n          const bodyText = document.body.innerText;\n          const codeViolations = scanCode(bodyText, route); // Use actual route\n          const statisticalClaimViolations = scanStatisticalClaims();\n          \n          const violations = [\n            ...domViolations,\n            ...codeViolations,\n            ...statisticalClaimViolations\n          ].map(v => ({ ...v, route }));\n          \n          routeViolations.push(...filterDuplicates(violations));\n        }\n        \n        // Restore original route\n        navigate(originalRoute, { replace: true });\n        await new Promise(resolve => setTimeout(resolve, 500));\n      }\n      \n      // Phase 3: Source file scan with adaptive config (skip if timed out)\n      let sourceFileViolations: MockViolation[] = [];\n      if (!isTimedOut) {\n        setCurrentScanProgress(`Scanning source files (0 files)...`);\n        sourceFileViolations = await scanSourceFiles(sourceFileConfig);\n      } else {\n        console.warn(`⏱️ Skipping source file scan due to timeout`);\n      }\n      \n      // Combine all violations\n      console.log(`📊 Before deduplication:`);\n      console.log(`   - Route violations: ${routeViolations.length}`);\n      console.log(`   - Source file violations: ${sourceFileViolations.length}`);\n      console.log(`   - Total (with duplicates): ${routeViolations.length + sourceFileViolations.length}`);\n      \n      const allViolations = filterDuplicates([\n        ...routeViolations,\n        ...sourceFileViolations\n      ]);\n      \n      const duplicatesRemoved = (routeViolations.length + sourceFileViolations.length) - allViolations.length;\n      console.log(`   - Duplicates removed: ${duplicatesRemoved}`);\n      console.log(`   - Final unique violations: ${allViolations.length}`);\n\n      const mockDataViolations = allViolations;\n\n      const result: ScanResult = {\n        totalViolations: allViolations.length,\n        mockDataViolations,\n        scanDuration: performance.now() - startTime,\n        scannedAt: new Date()\n      };\n      \n      // Clear timeout\n      if (timeoutId !== null) {\n        clearTimeout(timeoutId);\n      }\n\n      if (isTimedOut) {\n        console.log(`⚠️ PARTIAL smart deep scan for ${projectSize} project (timed out)`);\n      } else {\n        console.log(`✅ SMART DEEP SCAN complete for ${projectSize} project`);\n      }\n      console.log(`   - Total violations: ${result.totalViolations}`);\n      console.log(`   - Routes scanned: ${routesToScan.length}`);\n      console.log(`   - Route violations: ${routeViolations.length}`);\n      console.log(`   - Source file violations: ${sourceFileViolations.length}`);\n      console.log(`   - Scan duration: ${result.scanDuration.toFixed(0)}ms`);\n      \n      // Calculate health score\n      const health = calculateHealthScore(result, healthScore?.overall);\n      setHealthScore(health);\n      \n      setCurrentScanProgress(isTimedOut ? '⚠️ Timeout - Partial Results' : '✅ Smart Deep Scan Complete');\n      setScanResult(result);\n      return result;\n    } catch (error) {\n      console.error('❌ Smart deep scan failed:', error);\n      setCurrentScanProgress('❌ Scan Failed');\n      \n      // Clear timeout on error\n      if (timeoutId !== null) {\n        clearTimeout(timeoutId);\n      }\n      \n      throw error;\n    } finally {\n      setIsScanning(false);\n      setIsDeepScanning(false);\n    }\n  };\n\n  return {\n    isScanning,\n    scanResult,\n    setScanResult, // ✅ FIX: Export setter for clearing results\n    runScan,\n    runMultiRouteScan,\n    runDeepScan, // Deep scan with source file analysis\n    runSmartDeepScan, // NEW: Smart deep scan with auto-adaption\n    isDeepScanning,\n    currentScanProgress,\n    scanCode,\n    healthScore, // NEW: Project health score\n    generateAutoFixes: () => scanResult ? generateAllAutoFixes(scanResult.mockDataViolations) : [],\n    sourceFileProgress, // Progress percentage for source file scanning\n    filesScanned, // Number of files scanned\n    totalFiles, // Total files to scan\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),dt=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState } from 'react';\n\nconst getInitialDisabled = (storageKey: string): boolean => {\n  if (typeof window === 'undefined') return false;\n  try {\n    const stored = localStorage.getItem(storageKey);\n    return stored === 'true';\n  } catch (e) {\n    return false;\n  }\n};\n\nconst getInitialSessionHidden = (storageKey: string): boolean => {\n  if (typeof window === 'undefined') return false;\n  try {\n    const stored = sessionStorage.getItem(storageKey);\n    return stored === 'true';\n  } catch (e) {\n    return false;\n  }\n};\n\nexport const useMockDetectorControl = (storagePrefix: string = '') => {\n  const STORAGE_KEY_DISABLED = `${storagePrefix}mockdetector-permanently-disabled`;\n  const STORAGE_KEY_SESSION_HIDDEN = `${storagePrefix}mockdetector-session-hidden`;\n  \n  const [isPermanentlyDisabled, setIsPermanentlyDisabled] = useState<boolean>(() => getInitialDisabled(STORAGE_KEY_DISABLED));\n  const [isSessionHidden, setIsSessionHidden] = useState<boolean>(() => getInitialSessionHidden(STORAGE_KEY_SESSION_HIDDEN));\n\n  const isVisible = !isPermanentlyDisabled && !isSessionHidden;\n\n  // Permanently disable MockDetector (persists across sessions)\n  const disablePermanently = () => {\n    setIsPermanentlyDisabled(true);\n    localStorage.setItem(STORAGE_KEY_DISABLED, 'true');\n    console.log('🔴 MockDetector: Permanently disabled');\n  };\n\n  // Re-enable MockDetector\n  const enable = () => {\n    setIsPermanentlyDisabled(false);\n    setIsSessionHidden(false);\n    localStorage.removeItem(STORAGE_KEY_DISABLED);\n    sessionStorage.removeItem(STORAGE_KEY_SESSION_HIDDEN);\n    console.log('✅ MockDetector: Re-enabled');\n  };\n\n  // Hide for current session only (reappears after refresh)\n  const hideForSession = () => {\n    setIsSessionHidden(true);\n    sessionStorage.setItem(STORAGE_KEY_SESSION_HIDDEN, 'true');\n    console.log('👁️ MockDetector: Hidden for this session');\n  };\n\n  // Show for current session\n  const showForSession = () => {\n    setIsSessionHidden(false);\n    sessionStorage.removeItem(STORAGE_KEY_SESSION_HIDDEN);\n    console.log('👁️ MockDetector: Shown for this session');\n  };\n\n  // Get uninstall instructions\n  const getUninstallInstructions = () => {\n    return {\n      npm: 'npm uninstall @mockdetector/widget',\n      removeImport: 'Remove the import and <MockDetectorFloatingBubble /> from your code',\n      alternative: 'Or use disablePermanently() to keep installed but disabled',\n    };\n  };\n\n  return {\n    isPermanentlyDisabled,\n    isSessionHidden,\n    isVisible,\n    disablePermanently,\n    enable,\n    hideForSession,\n    showForSession,\n    getUninstallInstructions,\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),ut=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState } from 'react';\n\ninterface BubblePosition {\n  x: number;\n  y: number;\n}\n\n// Initialize from localStorage immediately to prevent position jump\nconst getInitialMinimized = (storageKey: string): boolean => {\n  if (typeof window === 'undefined') return false;\n  try {\n    const stored = localStorage.getItem(storageKey);\n    return stored !== null ? stored === 'true' : false;\n  } catch (e) {\n    return false;\n  }\n};\n\nconst getInitialPosition = (storageKey: string): BubblePosition => {\n  if (typeof window === 'undefined') {\n    return { x: 16, y: 300 };\n  }\n  \n  // CRITICAL: Clear any saved position FIRST\n  localStorage.removeItem(storageKey);\n  \n  // ALWAYS start in BOTTOM RIGHT corner (accounting for header)\n  const bubbleWidth = 400;\n  const bubbleHeight = 600;\n  const margin = 16;\n  const headerHeight = 100; // Space for header\n  \n  const bottomRightX = window.innerWidth - bubbleWidth - margin;\n  const bottomRightY = window.innerHeight - bubbleHeight - margin;\n  \n  const bottomRightPos = { \n    x: Math.max(margin, bottomRightX), \n    y: Math.max(headerHeight, bottomRightY) // Ensure below header\n  };\n  \n  console.log('✅ MockDetector starting in BOTTOM RIGHT corner (below header):', { \n    bottomRightPos, \n    viewport: { w: window.innerWidth, h: window.innerHeight }\n  });\n  \n  return bottomRightPos;\n};\n\nexport const useMockDetectorSettings = (storagePrefix: string = '') => {\n  const STORAGE_KEY_MINIMIZED = `${storagePrefix}mockdetector-bubble-minimized`;\n  const STORAGE_KEY_POSITION = `${storagePrefix}mockdetector-bubble-position`;\n  \n  // Force clear position on hook initialization\n  if (typeof window !== 'undefined') {\n    localStorage.removeItem(STORAGE_KEY_POSITION);\n  }\n  \n  const [isMinimized, setIsMinimized] = useState<boolean>(() => getInitialMinimized(STORAGE_KEY_MINIMIZED));\n  const [position, setPosition] = useState<BubblePosition>(() => getInitialPosition(STORAGE_KEY_POSITION));\n\n  const toggleMinimize = () => {\n    const newValue = !isMinimized;\n    setIsMinimized(newValue);\n    localStorage.setItem(`${storagePrefix}mockdetector-bubble-minimized`, String(newValue));\n  };\n\n  const minimize = () => {\n    setIsMinimized(true);\n    localStorage.setItem(`${storagePrefix}mockdetector-bubble-minimized`, 'true');\n  };\n\n  const maximize = () => {\n    setIsMinimized(false);\n    localStorage.setItem(`${storagePrefix}mockdetector-bubble-minimized`, 'false');\n  };\n\n  const updatePosition = (newPosition: BubblePosition) => {\n    setPosition(newPosition);\n    // REMOVED: Don't save to localStorage anymore - always start centered on refresh\n    // localStorage.setItem(STORAGE_KEY_POSITION, JSON.stringify(newPosition));\n  };\n\n  return {\n    isMinimized,\n    toggleMinimize,\n    minimize,\n    maximize,\n    position,\n    updatePosition\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),mt=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState } from 'react';\nimport { ScanResult } from '../types/mockdetector.types';\nimport { DatabaseScanResult } from '../types/database.types';\n\n// Priority mapping for sorting violations by severity\nconst SEVERITY_PRIORITY = {\n  critical: 4,\n  high: 3,\n  medium: 2,\n  low: 1\n};\n\nexport const useMockDetectorStorage = (storagePrefix: string = '') => {\n  const STORAGE_KEY = `${storagePrefix}mockdetector-latest-scan`;\n  // Keep full scan in memory (no truncation)\n  const [inMemoryScan, setInMemoryScan] = useState<ScanResult | DatabaseScanResult | null>(null);\n\n  const saveLatestScan = async (scanResult: ScanResult | DatabaseScanResult): Promise<ScanResult | DatabaseScanResult> => {\n    console.log('💾 Saving scan to localStorage...');\n    \n    // Always keep full scan in memory\n    setInMemoryScan(scanResult);\n    \n    try {\n      // Try to store the FULL scan first\n      const serialized = JSON.stringify(scanResult);\n      localStorage.setItem(STORAGE_KEY, serialized);\n      console.log('✅ Full scan saved to localStorage');\n      return scanResult;\n    } catch (error) {\n      // If localStorage quota exceeded, try storing truncated version\n      console.warn('⚠️ localStorage quota exceeded, storing truncated scan');\n      \n      try {\n        let truncatedResult: ScanResult | DatabaseScanResult;\n        \n        if ('mockDataViolations' in scanResult) {\n          // Frontend scan - limit to 10k violations\n          const limited = {\n            ...scanResult,\n            mockDataViolations: scanResult.mockDataViolations.slice(0, 10000),\n            wasPartial: scanResult.mockDataViolations.length > 10000\n          };\n          truncatedResult = limited;\n        } else {\n          // Database scan - limit violations\n          const limited = {\n            ...scanResult,\n            violations: scanResult.violations.slice(0, 10000),\n            wasPartial: scanResult.violations.length > 10000\n          };\n          truncatedResult = limited;\n        }\n        \n        const serialized = JSON.stringify(truncatedResult);\n        localStorage.setItem(STORAGE_KEY, serialized);\n        console.log('✅ Truncated scan saved (10k violations max)');\n        return truncatedResult;\n        \n      } catch (secondError) {\n        // If still too large, store only critical errors (top 4000)\n        console.warn('⚠️ Still too large, storing only critical errors');\n        \n        let criticalOnlyResult: ScanResult | DatabaseScanResult;\n        \n        if ('mockDataViolations' in scanResult) {\n          const sorted = [...scanResult.mockDataViolations].sort((a, b) => {\n            const priorityA = SEVERITY_PRIORITY[a.severity as keyof typeof SEVERITY_PRIORITY] || 0;\n            const priorityB = SEVERITY_PRIORITY[b.severity as keyof typeof SEVERITY_PRIORITY] || 0;\n            return priorityB - priorityA;\n          });\n          \n          criticalOnlyResult = {\n            ...scanResult,\n            mockDataViolations: sorted.slice(0, 4000),\n            wasPartial: true\n          };\n        } else {\n          const sorted = [...scanResult.violations].sort((a, b) => {\n            const priorityA = SEVERITY_PRIORITY[a.severity as keyof typeof SEVERITY_PRIORITY] || 0;\n            const priorityB = SEVERITY_PRIORITY[b.severity as keyof typeof SEVERITY_PRIORITY] || 0;\n            return priorityB - priorityA;\n          });\n          \n          criticalOnlyResult = {\n            ...scanResult,\n            violations: sorted.slice(0, 4000),\n            wasPartial: true\n          };\n        }\n        \n        try {\n          const serialized = JSON.stringify(criticalOnlyResult);\n          localStorage.setItem(STORAGE_KEY, serialized);\n          console.log('✅ Critical errors only saved (4k max)');\n          return criticalOnlyResult;\n        } catch (finalError) {\n          console.error('❌ Could not save to localStorage even after truncation');\n          // Still return the full in-memory scan\n          return scanResult;\n        }\n      }\n    }\n  };\n\n  const loadLatestScan = (): ScanResult | DatabaseScanResult | null => {\n    try {\n      const stored = localStorage.getItem(STORAGE_KEY);\n      if (!stored) return null;\n\n      const parsed = JSON.parse(stored);\n      console.log('📥 Loaded scan from localStorage');\n      return parsed;\n    } catch (error) {\n      console.error('Failed to load scan from localStorage:', error);\n      return null;\n    }\n  };\n\n  const clearAllScans = (): void => {\n    try {\n      localStorage.removeItem(STORAGE_KEY);\n      setInMemoryScan(null);\n      console.log('🗑️ All scans cleared');\n    } catch (error) {\n      console.error('Failed to clear scans:', error);\n    }\n  };\n\n  // Get the full un-truncated scan from memory\n  const getFullScan = (): ScanResult | DatabaseScanResult | null => {\n    return inMemoryScan;\n  };\n\n  return {\n    saveLatestScan,\n    loadLatestScan,\n    clearAllScans,\n    getFullScan\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),pt=Object.freeze(Object.defineProperty({__proto__:null,default:"// Simplified access control for widget (no external context dependencies)\n// Widget assumes it's installed by developers/moderators, so always returns true\n\nexport const useMultiLayerAccessControl = () => {\n  return {\n    effectiveAccessLevel: 'admin' as const,\n    canAccessAIAgentFeatures: true,\n    canAccessAIFeatures: true,\n    canAccessModeratorFeatures: true,\n    isInObserverMode: false,\n    showObserverModeIndicator: false,\n    showModeratorUI: true,\n    showLoginPrompt: false,\n    canAccess: (_feature?: string) => true,\n    getAccessMessage: (featureName?: string) => \n      `${featureName || 'This feature'} is available`,\n    getFeatureAccess: (_feature?: string) => 'full' as const\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),ft=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState, useEffect, useCallback } from 'react';\nimport { ScanResult } from '../types/mockdetector.types';\nimport { DatabaseScanResult } from '../types/database.types';\n\n// Storage keys for scan arrays\nconst STORAGE_KEY_FRONTEND = 'mockdetector-frontend-scans';\nconst STORAGE_KEY_DATABASE = 'mockdetector-database-scans';\nconst STORAGE_KEY_BACKEND = 'mockdetector-backend-scans';\nconst SCAN_CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours\nconst MAX_SCANS_PER_TYPE = 10; // Keep last 10 scans per type\n\n// Old keys for migration\nconst OLD_STORAGE_KEY_FRONTEND = 'mockdetector-frontend-scan';\nconst OLD_STORAGE_KEY_DATABASE = 'mockdetector-database-scan';\nconst OLD_STORAGE_KEY_BACKEND = 'mockdetector-backend-scan';\n\nexport interface SavedScan {\n  id: string; // Unique ID for each scan\n  result: ScanResult;\n  timestamp: number;\n  metadata: {\n    totalViolations: number;\n    highPriorityCount: number;\n    mediumPriorityCount: number;\n    lowPriorityCount: number;\n  };\n  // Keep original database result for proper restoration\n  originalDatabaseResult?: DatabaseScanResult;\n}\n\nexport const useScanHistory = () => {\n  const [frontendScans, setFrontendScans] = useState<SavedScan[]>([]);\n  const [databaseScans, setDatabaseScans] = useState<SavedScan[]>([]);\n  const [backendScans, setBackendScans] = useState<SavedScan[]>([]);\n  const [hasHistory, setHasHistory] = useState(false);\n\n  const deleteScanHistory = useCallback((scanType?: 'frontend' | 'database' | 'backend' | 'all', scanIndex?: number) => {\n    try {\n      if (scanIndex !== undefined && scanType && scanType !== 'all') {\n        // Delete specific scan by index\n        const key = scanType === 'frontend' ? STORAGE_KEY_FRONTEND \n                  : scanType === 'database' ? STORAGE_KEY_DATABASE \n                  : STORAGE_KEY_BACKEND;\n        \n        const currentScans = scanType === 'frontend' ? frontendScans \n                          : scanType === 'database' ? databaseScans \n                          : backendScans;\n        \n        const newScans = [...currentScans];\n        newScans.splice(scanIndex, 1);\n        \n        if (newScans.length > 0) {\n          localStorage.setItem(key, JSON.stringify(newScans));\n        } else {\n          localStorage.removeItem(key);\n        }\n        \n        if (scanType === 'frontend') setFrontendScans(newScans);\n        if (scanType === 'database') setDatabaseScans(newScans);\n        if (scanType === 'backend') setBackendScans(newScans);\n        \n        setHasHistory(\n          (scanType === 'frontend' ? newScans.length > 0 : frontendScans.length > 0) ||\n          (scanType === 'database' ? newScans.length > 0 : databaseScans.length > 0) ||\n          (scanType === 'backend' ? newScans.length > 0 : backendScans.length > 0)\n        );\n      } else {\n        // Delete all scans of type(s)\n        const typesToDelete = scanType === 'all' || !scanType \n          ? ['frontend', 'database', 'backend'] \n          : [scanType];\n        \n        typesToDelete.forEach(type => {\n          const key = type === 'frontend' ? STORAGE_KEY_FRONTEND \n                    : type === 'database' ? STORAGE_KEY_DATABASE \n                    : STORAGE_KEY_BACKEND;\n          localStorage.removeItem(key);\n        });\n        \n        if (typesToDelete.includes('frontend')) setFrontendScans([]);\n        if (typesToDelete.includes('database')) setDatabaseScans([]);\n        if (typesToDelete.includes('backend')) setBackendScans([]);\n        \n        setHasHistory(false);\n      }\n      \n      console.log('🗑️ Scan history deleted:', scanType, scanIndex);\n      \n      // Broadcast to ALL instances\n      try {\n        const channel = new BroadcastChannel('mockdetector-sync');\n        channel.postMessage({ type: 'scan-deleted', scanType, scanIndex });\n        channel.close();\n      } catch (e) {\n        console.warn('BroadcastChannel not supported:', e);\n      }\n    } catch (e) {\n      console.error('Failed to delete scan history:', e);\n    }\n  }, [frontendScans, databaseScans, backendScans]);\n\n  const loadScanFromStorage = useCallback(() => {\n    try {\n      let hasAnyHistory = false;\n      \n      // MIGRATION: Convert old single-scan format to new array format\n      const migrateOldScan = (oldKey: string, newKey: string, scanType: string) => {\n        const oldData = localStorage.getItem(oldKey);\n        if (oldData) {\n          try {\n            const oldScan: any = JSON.parse(oldData);\n            // Check if it's valid and not expired\n            if (Date.now() - oldScan.timestamp <= SCAN_CACHE_DURATION) {\n              // Add ID if missing\n              if (!oldScan.id) {\n                oldScan.id = `${scanType}-${oldScan.timestamp}-migrated`;\n              }\n              // Save as array in new format\n              localStorage.setItem(newKey, JSON.stringify([oldScan]));\n              console.log(`🔄 Migrated old scan from ${oldKey} to ${newKey}`);\n            }\n            // Remove old key\n            localStorage.removeItem(oldKey);\n          } catch (e) {\n            console.warn(`Failed to migrate ${oldKey}:`, e);\n          }\n        }\n      };\n      \n      // Migrate old data if it exists\n      migrateOldScan(OLD_STORAGE_KEY_FRONTEND, STORAGE_KEY_FRONTEND, 'frontend');\n      migrateOldScan(OLD_STORAGE_KEY_DATABASE, STORAGE_KEY_DATABASE, 'database');\n      migrateOldScan(OLD_STORAGE_KEY_BACKEND, STORAGE_KEY_BACKEND, 'backend');\n      \n      // Load frontend scans\n      const frontendStored = localStorage.getItem(STORAGE_KEY_FRONTEND);\n      if (frontendStored) {\n        const scans: SavedScan[] = JSON.parse(frontendStored);\n        // Fix scans missing IDs\n        const fixedScans = scans.map((scan: any) => {\n          if (!scan.id) {\n            scan.id = `frontend-${scan.timestamp}-fixed-${Math.random().toString(36).substr(2, 9)}`;\n          }\n          return scan;\n        });\n        const validScans = fixedScans.filter(scan => Date.now() - scan.timestamp <= SCAN_CACHE_DURATION);\n        if (validScans.length > 0) {\n          localStorage.setItem(STORAGE_KEY_FRONTEND, JSON.stringify(validScans)); // Save fixed version\n          setFrontendScans(validScans);\n          hasAnyHistory = true;\n        } else {\n          localStorage.removeItem(STORAGE_KEY_FRONTEND);\n        }\n      }\n      \n      // Load database scans\n      const databaseStored = localStorage.getItem(STORAGE_KEY_DATABASE);\n      if (databaseStored) {\n        const scans: SavedScan[] = JSON.parse(databaseStored);\n        // Fix scans missing IDs\n        const fixedScans = scans.map((scan: any) => {\n          if (!scan.id) {\n            scan.id = `database-${scan.timestamp}-fixed-${Math.random().toString(36).substr(2, 9)}`;\n          }\n          return scan;\n        });\n        const validScans = fixedScans.filter(scan => Date.now() - scan.timestamp <= SCAN_CACHE_DURATION);\n        if (validScans.length > 0) {\n          localStorage.setItem(STORAGE_KEY_DATABASE, JSON.stringify(validScans)); // Save fixed version\n          setDatabaseScans(validScans);\n          hasAnyHistory = true;\n        } else {\n          localStorage.removeItem(STORAGE_KEY_DATABASE);\n        }\n      }\n      \n      // Load backend scans\n      const backendStored = localStorage.getItem(STORAGE_KEY_BACKEND);\n      if (backendStored) {\n        const scans: SavedScan[] = JSON.parse(backendStored);\n        // Fix scans missing IDs\n        const fixedScans = scans.map((scan: any) => {\n          if (!scan.id) {\n            scan.id = `backend-${scan.timestamp}-fixed-${Math.random().toString(36).substr(2, 9)}`;\n          }\n          return scan;\n        });\n        const validScans = fixedScans.filter(scan => Date.now() - scan.timestamp <= SCAN_CACHE_DURATION);\n        if (validScans.length > 0) {\n          localStorage.setItem(STORAGE_KEY_BACKEND, JSON.stringify(validScans)); // Save fixed version\n          setBackendScans(validScans);\n          hasAnyHistory = true;\n        } else {\n          localStorage.removeItem(STORAGE_KEY_BACKEND);\n        }\n      }\n      \n      setHasHistory(hasAnyHistory);\n      console.log('📥 Scan history loaded:', { \n        frontend: frontendStored ? JSON.parse(frontendStored).length : 0, \n        database: databaseStored ? JSON.parse(databaseStored).length : 0, \n        backend: backendStored ? JSON.parse(backendStored).length : 0 \n      });\n    } catch (e) {\n      console.warn('Failed to load scan history:', e);\n      setHasHistory(false);\n    }\n  }, []);\n\n  // Check if there's a saved scan on mount\n  useEffect(() => {\n    loadScanFromStorage();\n  }, [loadScanFromStorage]);\n\n  const saveScanToHistory = useCallback((scanResult: ScanResult) => {\n    try {\n      const metadata = {\n        totalViolations: scanResult.totalViolations,\n        highPriorityCount: scanResult.mockDataViolations.filter(v => v.severity === 'high' || v.severity === 'critical').length,\n        mediumPriorityCount: scanResult.mockDataViolations.filter(v => v.severity === 'medium').length,\n        lowPriorityCount: scanResult.mockDataViolations.filter(v => v.severity === 'low').length,\n      };\n\n      const savedScan: SavedScan = {\n        id: `frontend-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n        result: { ...scanResult, scanType: 'frontend' },\n        timestamp: Date.now(),\n        metadata\n      };\n\n      // Get existing scans and add new one at the beginning\n      const existing = localStorage.getItem(STORAGE_KEY_FRONTEND);\n      const scans: SavedScan[] = existing ? JSON.parse(existing) : [];\n      scans.unshift(savedScan);\n      \n      // Keep only the latest MAX_SCANS_PER_TYPE\n      const trimmedScans = scans.slice(0, MAX_SCANS_PER_TYPE);\n      \n      localStorage.setItem(STORAGE_KEY_FRONTEND, JSON.stringify(trimmedScans));\n      setFrontendScans(trimmedScans);\n      setHasHistory(true);\n      console.log('💾 Frontend scan saved to history');\n      \n      // Broadcast to ALL instances\n      try {\n        const channel = new BroadcastChannel('mockdetector-sync');\n        channel.postMessage({ type: 'scan-updated', scanType: 'frontend', data: trimmedScans });\n        channel.close();\n      } catch (e) {\n        console.warn('BroadcastChannel not supported:', e);\n      }\n    } catch (e) {\n      console.error('Failed to save frontend scan history:', e);\n    }\n  }, []);\n\n  const saveDatabaseScanToHistory = useCallback((databaseResult: DatabaseScanResult) => {\n    try {\n      // Convert database result to ScanResult format for consistency\n      const scanResult: ScanResult = {\n        totalViolations: databaseResult.totalViolations,\n        mockDataViolations: databaseResult.violations.map(v => ({\n          type: 'mock_data' as const,\n          severity: v.severity,\n          description: `${v.table}.${v.column}: ${v.description}`,\n          file: `Database: ${v.table}`,\n          route: v.table,\n        })),\n        scanDuration: databaseResult.scanDuration,\n        scannedAt: databaseResult.scannedAt,\n        scanType: 'database'\n      };\n\n      const metadata = {\n        totalViolations: databaseResult.totalViolations,\n        highPriorityCount: databaseResult.violations.filter(v => v.severity === 'critical' || v.severity === 'high').length,\n        mediumPriorityCount: databaseResult.violations.filter(v => v.severity === 'medium').length,\n        lowPriorityCount: databaseResult.violations.filter(v => v.severity === 'low').length,\n      };\n\n      const savedScan: SavedScan = {\n        id: `database-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n        result: scanResult,\n        timestamp: Date.now(),\n        metadata,\n        originalDatabaseResult: databaseResult // Keep original for proper restoration\n      };\n\n      // Get existing scans and add new one at the beginning\n      const existing = localStorage.getItem(STORAGE_KEY_DATABASE);\n      const scans: SavedScan[] = existing ? JSON.parse(existing) : [];\n      scans.unshift(savedScan);\n      \n      // Keep only the latest MAX_SCANS_PER_TYPE\n      const trimmedScans = scans.slice(0, MAX_SCANS_PER_TYPE);\n      \n      localStorage.setItem(STORAGE_KEY_DATABASE, JSON.stringify(trimmedScans));\n      setDatabaseScans(trimmedScans);\n      setHasHistory(true);\n      console.log('💾 Database scan saved to history');\n      \n      // Broadcast to ALL instances\n      try {\n        const channel = new BroadcastChannel('mockdetector-sync');\n        channel.postMessage({ type: 'scan-updated', scanType: 'database', data: trimmedScans });\n        channel.close();\n      } catch (e) {\n        console.warn('BroadcastChannel not supported:', e);\n      }\n    } catch (e) {\n      console.error('Failed to save database scan history:', e);\n    }\n  }, []);\n\n  const getRelativeTime = (timestamp: number): string => {\n    const now = Date.now();\n    const diff = now - timestamp;\n    \n    const minutes = Math.floor(diff / 60000);\n    const hours = Math.floor(diff / 3600000);\n    const days = Math.floor(diff / 86400000);\n    \n    if (minutes < 1) return 'just now';\n    if (minutes < 60) return `${minutes} minute${minutes !== 1 ? 's' : ''} ago`;\n    if (hours < 24) return `${hours} hour${hours !== 1 ? 's' : ''} ago`;\n    return `${days} day${days !== 1 ? 's' : ''} ago`;\n  };\n\n  return {\n    frontendScans,\n    databaseScans,\n    backendScans,\n    hasHistory,\n    saveScanToHistory,\n    saveDatabaseScanToHistory,\n    deleteScanHistory,\n    loadScanFromStorage,\n    getRelativeTime\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),gt=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState, useEffect } from 'react';\nimport { SelfScanStatus } from '../types/mockdetector.types';\nimport { useMockDetection } from './useMockDetection';\n\nexport const useSelfScan = () => {\n  const [selfScanStatus, setSelfScanStatus] = useState<SelfScanStatus | null>(null);\n  const { scanCode } = useMockDetection();\n\n  const runSelfScan = async (): Promise<SelfScanStatus> => {\n    let totalViolations = 0;\n\n    // In production, this would scan actual source files\n    // For now, we scan the current component's rendered output\n    const currentComponentText = document.querySelector('[data-mockdetector]')?.textContent || '';\n    const violations = scanCode(currentComponentText, 'MockDetector');\n    totalViolations += violations.length;\n\n    const status: SelfScanStatus = {\n      isClean: totalViolations === 0,\n      lastScanned: new Date(),\n      violations: totalViolations,\n      nextScan: new Date(Date.now() + 24 * 60 * 60 * 1000) // Next scan in 24h\n    };\n\n    setSelfScanStatus(status);\n    return status;\n  };\n\n  // Run self-scan on mount (silent, not visible to users)\n  useEffect(() => {\n    runSelfScan();\n  }, []);\n\n  return {\n    selfScanStatus,\n    runSelfScan\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),ht=Object.freeze(Object.defineProperty({__proto__:null,default:"import { useState, useEffect } from 'react';\nimport { WIDGET_VERSION } from '../utils/version';\nimport { toast } from './use-toast';\n\nconst STORAGE_KEY_LAST_CHECK = 'mockdetector-last-version-check';\nconst STORAGE_KEY_DISMISSED_VERSION = 'mockdetector-dismissed-version';\nconst STORAGE_KEY_REQUESTED_VERSION = 'mockdetector-requested-version';\nconst CURRENT_VERSION = WIDGET_VERSION;\nconst CHECK_INTERVAL_MS = 3 * 60 * 1000; // Check every 3 minutes (faster updates)\nconst MIN_CHECK_INTERVAL_MS = 5 * 60 * 1000; // Minimum 5 minutes between checks\n\ninterface VersionInfo {\n  currentVersion: string;\n  latestVersion: string | null;\n  updateAvailable: boolean;\n  isChecking: boolean;\n  isUpdating: boolean;\n  updateError: string | null;\n  lastChecked: Date | null;\n}\n\nconst getLatestVersionFromNPM = async (): Promise<string | null> => {\n  try {\n    const response = await fetch('https://registry.npmjs.org/@mockdetector/widget/latest');\n    if (!response.ok) return null;\n    \n    const data = await response.json();\n    return data.version || null;\n  } catch (error) {\n    console.error('MockDetector: Version check failed', error);\n    return null;\n  }\n};\n\nconst compareVersions = (current: string, latest: string): boolean => {\n  // Remove 'v' prefix if present\n  const cleanCurrent = current.replace(/^v/, '');\n  const cleanLatest = latest.replace(/^v/, '');\n  \n  // Split into parts [major, minor, patch]\n  const currentParts = cleanCurrent.split('.').map(p => parseInt(p.split('-')[0], 10));\n  const latestParts = cleanLatest.split('.').map(p => parseInt(p.split('-')[0], 10));\n  \n  // Compare major, minor, patch\n  for (let i = 0; i < 3; i++) {\n    if (latestParts[i] > currentParts[i]) return true;\n    if (latestParts[i] < currentParts[i]) return false;\n  }\n  \n  return false; // Versions are equal\n};\n\nexport const useVersionCheck = () => {\n  const [versionInfo, setVersionInfo] = useState<VersionInfo>({\n    currentVersion: CURRENT_VERSION,\n    latestVersion: null,\n    updateAvailable: false,\n    isChecking: false,\n    isUpdating: false,\n    updateError: null,\n    lastChecked: null,\n  });\n\n  const [isDismissed, setIsDismissed] = useState<boolean>(() => {\n    if (typeof window === 'undefined') return false;\n    try {\n      const dismissed = localStorage.getItem(STORAGE_KEY_DISMISSED_VERSION);\n      return dismissed === CURRENT_VERSION;\n    } catch (e) {\n      return false;\n    }\n  });\n\n  const checkForUpdates = async (force = false) => {\n    if (versionInfo.isChecking) return { updateAvailable: false, latestVersion: null };\n    \n    // Check if enough time has passed since last check (unless forced)\n    if (!force && typeof window !== 'undefined') {\n      try {\n        const lastCheck = localStorage.getItem(STORAGE_KEY_LAST_CHECK);\n        if (lastCheck) {\n          const timeSinceLastCheck = Date.now() - new Date(lastCheck).getTime();\n          if (timeSinceLastCheck < MIN_CHECK_INTERVAL_MS) {\n            console.log('⏰ MockDetector: Skipping version check (too soon)');\n            return { updateAvailable: versionInfo.updateAvailable, latestVersion: versionInfo.latestVersion };\n          }\n        }\n      } catch (e) {\n        // Ignore localStorage errors\n      }\n    }\n    \n    setVersionInfo(prev => ({ ...prev, isChecking: true }));\n    \n    const latestVersion = await getLatestVersionFromNPM();\n    const now = new Date();\n    \n    if (latestVersion) {\n      const updateAvailable = compareVersions(CURRENT_VERSION, latestVersion);\n      \n      setVersionInfo({\n        currentVersion: CURRENT_VERSION,\n        latestVersion,\n        updateAvailable,\n        isChecking: false,\n        isUpdating: false,\n        updateError: null,\n        lastChecked: now,\n      });\n      \n      // Store last check time\n      if (typeof window !== 'undefined') {\n        try {\n          localStorage.setItem(STORAGE_KEY_LAST_CHECK, now.toISOString());\n        } catch (e) {\n          // Ignore localStorage errors\n        }\n      }\n      \n      // Reset dismissed flag if new version is available\n      if (updateAvailable && typeof window !== 'undefined') {\n        try {\n          const dismissedVersion = localStorage.getItem(STORAGE_KEY_DISMISSED_VERSION);\n          if (dismissedVersion !== latestVersion) {\n            setIsDismissed(false);\n          }\n        } catch (e) {\n          // Ignore localStorage errors\n        }\n      }\n      \n      return { updateAvailable, latestVersion };\n    } else {\n      setVersionInfo(prev => ({\n        ...prev,\n        isChecking: false,\n        lastChecked: now,\n      }));\n      \n      return { updateAvailable: false, latestVersion: null };\n    }\n  };\n\n  const dismissUpdate = () => {\n    if (versionInfo.latestVersion) {\n      localStorage.setItem(STORAGE_KEY_DISMISSED_VERSION, versionInfo.latestVersion);\n      setIsDismissed(true);\n    }\n  };\n\n  const performUpdate = async () => {\n    if (!versionInfo.latestVersion || versionInfo.isUpdating) {\n      console.log('🚀 MockDetector: Update skipped -', { \n        hasLatestVersion: !!versionInfo.latestVersion, \n        isUpdating: versionInfo.isUpdating \n      });\n      return false;\n    }\n    \n    console.log('🚀 MockDetector: Starting update to', versionInfo.latestVersion);\n    setVersionInfo(prev => ({ ...prev, isUpdating: true, updateError: null }));\n    \n    try {\n      // FIX 2: Pre-verify CDN availability before reload\n      const cdnUrl = `https://cdn.jsdelivr.net/npm/@mockdetector/widget@${versionInfo.latestVersion}/dist/mockdetector-widget.umd.js`;\n      console.log('🔍 Verifying CDN availability:', cdnUrl);\n      \n      const testResponse = await fetch(cdnUrl, { method: 'HEAD' });\n      if (!testResponse.ok) {\n        throw new Error(`CDN returned ${testResponse.status}: Version might not be published yet`);\n      }\n      \n      console.log('✅ CDN verification passed');\n      \n      // Store requested version with timestamp\n      if (typeof window !== 'undefined') {\n        try {\n          localStorage.setItem(STORAGE_KEY_REQUESTED_VERSION, versionInfo.latestVersion);\n          localStorage.setItem('mockdetector-update-timestamp', Date.now().toString());\n          console.log('💾 MockDetector: Requested version saved to localStorage');\n        } catch (e) {\n          console.warn('⚠️ MockDetector: Failed to save requested version', e);\n        }\n      }\n      \n      // Reload immediately (no need for event dispatch or timeout)\n      console.log('🔄 MockDetector: Reloading page to activate new version...');\n      window.location.reload();\n      \n      return true;\n    } catch (error) {\n      const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n      console.error('❌ MockDetector: Update failed:', errorMessage);\n      \n      setVersionInfo(prev => ({\n        ...prev,\n        isUpdating: false,\n        updateError: `Update failed: ${errorMessage}. Try again in a few minutes.`,\n      }));\n      \n      return false;\n    }\n  };\n\n  const copyUpdateCommand = async () => {\n    const command = getUpdateCommand();\n    \n    if (typeof navigator !== 'undefined' && navigator.clipboard) {\n      try {\n        await navigator.clipboard.writeText(command);\n        return true;\n      } catch (error) {\n        console.error('Failed to copy update command:', error);\n        return false;\n      }\n    }\n    return false;\n  };\n\n  const getUpdateCommand = () => {\n    return `npm update @mockdetector/widget@latest`;\n  };\n\n  // Check on mount and set up automatic checks every 3 minutes\n  useEffect(() => {\n    checkForUpdates();\n    \n    const interval = setInterval(() => {\n      checkForUpdates();\n    }, CHECK_INTERVAL_MS);\n    \n    return () => clearInterval(interval);\n  }, []);\n\n  // Auto-update when new version detected\n  useEffect(() => {\n    if (versionInfo.updateAvailable && versionInfo.latestVersion) {\n      console.log(`🎉 New version ${versionInfo.latestVersion} detected! Starting automatic update...`);\n      \n      // Perform update automatically\n      performUpdate().then(success => {\n        if (success) {\n          toast({\n            title: \"🎉 New version ready!\",\n            description: \"Refreshing page to activate...\"\n          });\n          \n          // Auto-reload after 3 seconds\n          setTimeout(() => {\n            console.log('🔄 Auto-reloading to activate new version...');\n            window.location.reload();\n          }, 3000);\n        } else {\n          console.warn('⚠️ Auto-update failed, will retry on next check');\n        }\n      });\n    }\n  }, [versionInfo.updateAvailable, versionInfo.latestVersion]);\n\n  return {\n    ...versionInfo,\n    isDismissed,\n    checkForUpdates,\n    performUpdate,\n    copyUpdateCommand,\n    dismissUpdate,\n    getUpdateCommand,\n    shouldShowNotification: versionInfo.updateAvailable && !isDismissed,\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),bt=Object.freeze(Object.defineProperty({__proto__:null,default:"// ============================================\n// MockDetector Widget - Main Export\n// ============================================\n// Built by Silver (Anton Fredriksson) 🇸🇪\n// with AI assistance 🤖\n// ============================================\n\n// Main Widget Component Export\nexport { MockDetectorFloatingBubble } from './components/MockDetectorFloatingBubble';\nexport type { MockDetectorFloatingBubbleProps } from './components/MockDetectorFloatingBubble';\n\n// Hooks for Advanced Users\nexport { useMockDetection } from './hooks/useMockDetection';\nexport { useMockDetectorSettings } from './hooks/useMockDetectorSettings';\nexport { useDatabaseScanner } from './hooks/useDatabaseScanner';\nexport { useBetaCredits } from './hooks/useBetaCredits';\nexport { useVersionCheck } from './hooks/useVersionCheck';\nexport { useMockDetectorControl } from './hooks/useMockDetectorControl';\n\n// Type Exports\nexport type { \n  MockViolation,\n  ScanResult,\n  SelfScanStatus\n} from './types/mockdetector.types';\n\nexport type {\n  DatabaseViolation,\n  DatabaseScanResult\n} from './types/database.types';\n\n// Configuration Exports (for advanced customization)\nexport { SCANNABLE_ROUTES } from './config/routes';\n"},Symbol.toStringTag,{value:"Module"})),yt=Object.freeze(Object.defineProperty({__proto__:null,default:'// This file is automatically generated. Do not edit it directly.\nimport { createClient } from \'@supabase/supabase-js\';\nimport type { Database } from \'./types\';\n\nconst SUPABASE_URL = "https://tzowmzqfbicbyvikhdwy.supabase.co";\nconst SUPABASE_PUBLISHABLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InR6b3dtenFmYmljYnl2aWtoZHd5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTEzODA4OTEsImV4cCI6MjA2Njk1Njg5MX0.ISwDLrKZV8Ug6Ej4puA5miPHBvrN70osv0hv-hHfc8U";\n\n// Import the supabase client like this:\n// import { supabase } from "@/integrations/supabase/client";\n\n// CRITICAL PLATFORM MEMORY: Always build everything REAL/AUTHENTIC, never demo/fake data\n// - Real AIs from hotel should actually move to school to learn\n// - Each school step should provide actual learning value\n// - Never use demo data - it creates massive cleanup work later\n// - Build authentic systems from day one\n\nexport const supabase = createClient<Database>(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, {\n  auth: {\n    storage: localStorage,\n    persistSession: true,\n    autoRefreshToken: true,\n  }\n});\n'},Symbol.toStringTag,{value:"Module"})),vt=Object.freeze(Object.defineProperty({__proto__:null,default:"// Minimal Database types for MockDetector Widget\n// This is a simplified version - the widget uses type assertions for RPC calls\n\nexport type Json =\n  | string\n  | number\n  | boolean\n  | null\n  | { [key: string]: Json | undefined }\n  | Json[]\n\nexport type Database = {\n  public: {\n    Tables: Record<string, any>\n    Views: Record<string, any>\n    Functions: {\n      get_public_tables: {\n        Args: Record<PropertyKey, never>\n        Returns: { table_name: string }[]\n      }\n    }\n    Enums: Record<string, never>\n    CompositeTypes: Record<string, never>\n  }\n}\n"},Symbol.toStringTag,{value:"Module"})),St=Object.freeze(Object.defineProperty({__proto__:null,default:'import { cva, type VariantProps } from "class-variance-authority"\n\nexport const buttonVariants = cva(\n  "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",\n  {\n    variants: {\n      variant: {\n        default:\n          "bg-primary text-primary-foreground shadow hover:bg-primary/90",\n        destructive:\n          "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",\n        outline:\n          "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",\n        secondary:\n          "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",\n        ghost: "hover:bg-accent hover:text-accent-foreground",\n        link: "text-primary underline-offset-4 hover:underline",\n      },\n      size: {\n        default: "h-9 px-4 py-2",\n        sm: "h-8 rounded-md px-3 text-xs",\n        lg: "h-10 rounded-md px-8",\n        icon: "h-9 w-9",\n      },\n    },\n    defaultVariants: {\n      variant: "default",\n      size: "default",\n    },\n  }\n)\n\nexport type ButtonVariantsProps = VariantProps<typeof buttonVariants>\n'},Symbol.toStringTag,{value:"Module"})),xt=Object.freeze(Object.defineProperty({__proto__:null,default:'import { clsx, type ClassValue } from "clsx"\nimport { twMerge } from "tailwind-merge"\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n\n// Re-export button variants for MockDetector widget\nexport { buttonVariants, type ButtonVariantsProps } from "./button-variants"\n'},Symbol.toStringTag,{value:"Module"})),wt=Object.freeze(Object.defineProperty({__proto__:null,default:"export interface DatabaseViolation {\n  table: string;\n  column: string;\n  pattern: string;\n  severity: 'critical' | 'high' | 'medium' | 'low';\n  description: string;\n  examples: string[];\n  affectedRows: number;\n  confidence: number; // 0-100: Confidence that this is real mock data\n  \n  // ✅ PHASE 3: Optional reasoning for transparency\n  reasoning?: string; // Why we flagged this\n}\n\nexport interface DatabaseScanResult {\n  totalViolations: number;\n  violations: DatabaseViolation[];\n  tablesScanned: number;\n  rowsAnalyzed: number;\n  scanDuration: number;\n  scannedAt: Date;\n  scanType?: 'database';\n  wasPartial?: boolean;\n  totalViolationsBeforeTruncation?: number;\n}\n\nexport interface MockPatternDetector {\n  name: string;\n  description: string;\n  severity: 'critical' | 'high' | 'medium' | 'low';\n  test: (value: any) => boolean;\n  getExamples?: (value: any) => string;\n}\n"},Symbol.toStringTag,{value:"Module"})),kt=Object.freeze(Object.defineProperty({__proto__:null,default:"export interface MockViolation {\n  type: 'mock_data';\n  severity: 'critical' | 'high' | 'medium' | 'low';\n  file?: string;\n  line?: number;\n  code?: string;\n  description: string;\n  fix?: string;\n  route?: string;\n  \n  // ✅ PHASE 3: Confidence scoring\n  confidence?: number; // 0-100: How confident we are this is real mock data (not false positive)\n  reasoning?: string;  // Why we flagged this (helps users understand)\n}\n\nexport interface ScanResult {\n  totalViolations: number;\n  mockDataViolations: MockViolation[];\n  scanDuration: number;\n  scannedAt: Date;\n  scanType?: 'frontend' | 'database';\n  fromCache?: boolean;\n  \n  // New fields for partial scans\n  wasPartial?: boolean;\n  totalViolationsBeforeTruncation?: number;\n}\n\nexport interface SelfScanStatus {\n  isClean: boolean;\n  lastScanned: Date;\n  violations: number;\n  nextScan?: Date;\n}\n"},Symbol.toStringTag,{value:"Module"})),Nt=Object.freeze(Object.defineProperty({__proto__:null,default:"// Configuration types for MockDetector scanning\n\nexport type ProjectSize = 'small' | 'medium' | 'large';\nexport type DatabaseStrategy = 'all' | 'prioritized' | 'custom';\n\nexport interface RouteScanConfig {\n  maxRoutes: number;           // Max routes per scan\n  timeoutPerRoute: number;     // Timeout per route (ms)\n  totalTimeout: number;        // Total timeout (ms)\n  batchSize: number;           // Routes per batch\n  enableProgressSave: boolean; // Save progress between batches\n}\n\nexport interface DatabaseScanConfig {\n  rowsPerTable: number;\n  timeout: number;\n  prioritizeTables?: string[];\n  onlyPrioritizedTables?: boolean;\n  showWarning?: boolean;\n  intelligentSampling: boolean; // First 100, last 100, random 100\n}\n\nexport interface SourceFileScanConfig {\n  rootPath: string;\n  includeEdgeFunctions: boolean;\n  includeConfigFiles: boolean;\n  fileTypes: string[];\n  maxFiles: number;\n  batchSize: number;\n  timeout: number;\n}\n\nexport interface ScanLimits {\n  routes: RouteScanConfig;\n  database: DatabaseScanConfig;\n  sourceFiles: SourceFileScanConfig;\n}\n\nexport interface ProjectSizeMetrics {\n  routeCount: number;\n  databaseSize: 'small' | 'medium' | 'large';\n  estimatedSourceFiles: number;\n  score: number; // 0-6 points\n  size: ProjectSize;\n}\n\n// Default configurations for different project sizes\nexport const DEFAULT_SCAN_CONFIGS: Record<ProjectSize, ScanLimits> = {\n  small: {\n    routes: {\n      maxRoutes: 100,\n      timeoutPerRoute: 3000,\n      totalTimeout: 300000, // 5 minutes\n      batchSize: 20,\n      enableProgressSave: false\n    },\n    database: {\n      rowsPerTable: 200,\n      timeout: 60000, // 1 minute\n      intelligentSampling: false\n    },\n    sourceFiles: {\n      rootPath: '/workspace/src',\n      includeEdgeFunctions: true,\n      includeConfigFiles: true,\n      fileTypes: ['.tsx', '.ts', '.jsx', '.js'],\n      maxFiles: 2000,\n      batchSize: 500,\n      timeout: 120000 // 2 minutes\n    }\n  },\n  medium: {\n    routes: {\n      maxRoutes: 50,\n      timeoutPerRoute: 3000,\n      totalTimeout: 180000, // 3 minutes\n      batchSize: 10,\n      enableProgressSave: true\n    },\n    database: {\n      rowsPerTable: 100,\n      timeout: 120000, // 2 minutes\n      prioritizeTables: ['users', 'products', 'orders', 'ai_hotel_rooms', 'profiles'],\n      intelligentSampling: true\n    },\n    sourceFiles: {\n      rootPath: '/workspace/src',\n      includeEdgeFunctions: true,\n      includeConfigFiles: false,\n      fileTypes: ['.tsx', '.ts', '.jsx', '.js'],\n      maxFiles: 1000,\n      batchSize: 200,\n      timeout: 180000 // 3 minutes\n    }\n  },\n  large: {\n    routes: {\n      maxRoutes: 30,\n      timeoutPerRoute: 2000,\n      totalTimeout: 120000, // 2 minutes\n      batchSize: 5,\n      enableProgressSave: true\n    },\n    database: {\n      rowsPerTable: 50,\n      timeout: 180000, // 3 minutes\n      prioritizeTables: ['users', 'products', 'orders'],\n      onlyPrioritizedTables: true,\n      showWarning: true,\n      intelligentSampling: true\n    },\n    sourceFiles: {\n      rootPath: '/workspace/src',\n      includeEdgeFunctions: false,\n      includeConfigFiles: false,\n      fileTypes: ['.tsx', '.ts'],\n      maxFiles: 500,\n      batchSize: 100,\n      timeout: 180000 // 3 minutes\n    }\n  }\n};\n"},Symbol.toStringTag,{value:"Module"})),Dt=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector: Auto-Fix Suggestion Generator\n * \n * Generates specific, actionable fix suggestions for detected mock data violations.\n */\n\nimport { MockViolation } from '../types/mockdetector.types';\n\nexport interface AutoFixSuggestion {\n  violation: MockViolation;\n  fixType: 'database_query' | 'api_call' | 'state_hook' | 'prop_passing' | 'constants_file';\n  difficulty: 'easy' | 'medium' | 'hard';\n  confidence: number; // 0-100, how confident we are this fix will work\n  codeSnippet: string;\n  explanation: string;\n  estimatedTime: string; // \"5 min\", \"15 min\", \"30 min\"\n  requiredFiles?: string[]; // Files that need to be created/modified\n}\n\n/**\n * Analyze violation context and generate specific fix suggestion\n */\nexport const generateAutoFix = (violation: MockViolation): AutoFixSuggestion => {\n  const code = violation.code || '';\n  const description = violation.description.toLowerCase();\n  \n  // Analyze violation type and generate appropriate fix\n  \n  // Case 1: useState with hardcoded array\n  if (code.includes('useState') && code.includes('[')) {\n    return {\n      violation,\n      fixType: 'database_query',\n      difficulty: 'easy',\n      confidence: 90,\n      estimatedTime: '10 min',\n      codeSnippet: generateDatabaseFetchSnippet(violation),\n      explanation: 'Replace hardcoded array with data fetched from Supabase. This ensures your app displays real, up-to-date information.',\n      requiredFiles: []\n    };\n  }\n  \n  // Case 2: useState with hardcoded number\n  if (code.includes('useState') && /\\d+/.test(code)) {\n    return {\n      violation,\n      fixType: 'database_query',\n      difficulty: 'easy',\n      confidence: 85,\n      estimatedTime: '5 min',\n      codeSnippet: generateCountQuerySnippet(violation),\n      explanation: 'Replace hardcoded count with a real database count query. This provides accurate metrics.',\n      requiredFiles: []\n    };\n  }\n  \n  // Case 3: .map() with inline array\n  if (code.includes('.map(') || description.includes('map')) {\n    return {\n      violation,\n      fixType: 'state_hook',\n      difficulty: 'medium',\n      confidence: 75,\n      estimatedTime: '15 min',\n      codeSnippet: generateStateBasedMapSnippet(violation),\n      explanation: 'Convert inline array to state-based data loading. This allows dynamic content updates.',\n      requiredFiles: []\n    };\n  }\n  \n  // Case 4: Hardcoded numbers in UI\n  if (/\\d{2,}/.test(code) && !code.includes('useState')) {\n    return {\n      violation,\n      fixType: 'prop_passing',\n      difficulty: 'easy',\n      confidence: 80,\n      estimatedTime: '10 min',\n      codeSnippet: generatePropPassingSnippet(violation),\n      explanation: 'Convert hardcoded number to dynamic prop. This makes the component reusable with real data.',\n      requiredFiles: []\n    };\n  }\n  \n  // Case 5: Test emails or test data\n  if (description.includes('test') || description.includes('example')) {\n    return {\n      violation,\n      fixType: 'database_query',\n      difficulty: 'easy',\n      confidence: 95,\n      estimatedTime: '5 min',\n      codeSnippet: generateAuthUserSnippet(violation),\n      explanation: 'Replace test data with real user data from Supabase Auth.',\n      requiredFiles: []\n    };\n  }\n  \n  // Case 6: Array.fill() or Math.random()\n  if (code.includes('Array.fill') || code.includes('Math.random')) {\n    return {\n      violation,\n      fixType: 'database_query',\n      difficulty: 'medium',\n      confidence: 70,\n      estimatedTime: '20 min',\n      codeSnippet: generateBulkDataFetchSnippet(violation),\n      explanation: 'Replace generated mock data with actual database records. Create the necessary database table if it doesn\\'t exist.',\n      requiredFiles: ['Database migration needed']\n    };\n  }\n  \n  // Default case: Generic fix\n  return {\n    violation,\n    fixType: 'database_query',\n    difficulty: 'medium',\n    confidence: 60,\n    estimatedTime: '15 min',\n    codeSnippet: generateGenericDatabaseSnippet(violation),\n    explanation: 'Replace mock data with real database query. Review your data model and fetch appropriate data.',\n    requiredFiles: []\n  };\n};\n\n/**\n * Generate database fetch code snippet\n */\nconst generateDatabaseFetchSnippet = (_violation: MockViolation): string => {\n  return `// Step 1: Import Supabase client\nimport { supabase } from '@/integrations/supabase/client';\n\n// Step 2: Replace useState with empty array\nconst [data, setData] = useState([]);\n\n// Step 3: Fetch real data on component mount\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data: fetchedData, error } = await supabase\n      .from('your_table_name') // ⚠️ Change to your actual table\n      .select('*')\n      .order('created_at', { ascending: false });\n    \n    if (error) {\n      console.error('Error fetching data:', error);\n      return;\n    }\n    \n    setData(fetchedData || []);\n  };\n  \n  fetchData();\n}, []);`;\n};\n\n/**\n * Generate count query snippet\n */\nconst generateCountQuerySnippet = (_violation: MockViolation): string => {\n  return `// Fetch real count from database\nconst [count, setCount] = useState(0);\n\nuseEffect(() => {\n  const fetchCount = async () => {\n    const { count: totalCount, error } = await supabase\n      .from('your_table_name') // ⚠️ Change to your actual table\n      .select('*', { count: 'exact', head: true });\n    \n    if (error) {\n      console.error('Error fetching count:', error);\n      return;\n    }\n    \n    setCount(totalCount || 0);\n  };\n  \n  fetchCount();\n}, []);`;\n};\n\n/**\n * Generate state-based map snippet\n */\nconst generateStateBasedMapSnippet = (_violation: MockViolation): string => {\n  return `// Step 1: Create state for your data\nconst [items, setItems] = useState([]);\n\n// Step 2: Fetch data\nuseEffect(() => {\n  const loadItems = async () => {\n    const { data, error } = await supabase\n      .from('your_table_name')\n      .select('*');\n    \n    if (data) setItems(data);\n  };\n  loadItems();\n}, []);\n\n// Step 3: Use in JSX\n{items.map((item) => (\n  <div key={item.id}>\n    {/* Your content here */}\n  </div>\n))}`;\n};\n\n/**\n * Generate prop passing snippet\n */\nconst generatePropPassingSnippet = (violation: MockViolation): string => {\n  // Try to extract number from description first (more reliable)\n  let number = 'VALUE';\n  const descMatch = violation.description.match(/number\\s+\"(\\d+)\"/i);\n  if (descMatch) {\n    number = descMatch[1];\n  } else if (violation.code) {\n    // Fallback: look for standalone numbers in code (not in CSS classes)\n    // Match numbers that are NOT preceded by - (like in class names)\n    const codeMatch = violation.code.match(/(?<![-\\w])(\\d+)(?![-\\w])/);\n    if (codeMatch) {\n      number = codeMatch[1];\n    }\n  }\n  \n  return `// Step 1: Convert to component prop\ninterface Props {\n  count: number; // Make it dynamic\n}\n\nexport const YourComponent = ({ count }: Props) => {\n  return <div>{count}</div>;\n};\n\n// Step 2: Pass real data from parent\n<YourComponent count={realCountFromDatabase} />\n\n// Previous hardcoded value: ${number}`;\n};\n\n/**\n * Generate auth user snippet\n */\nconst generateAuthUserSnippet = (_violation: MockViolation): string => {\n  return `// Fetch real user data from Supabase Auth\nconst { data: { user }, error } = await supabase.auth.getUser();\n\nif (user) {\n  const email = user.email;\n  const name = user.user_metadata?.name;\n  // Use real user data here\n}`;\n};\n\n/**\n * Generate bulk data fetch snippet\n */\nconst generateBulkDataFetchSnippet = (_violation: MockViolation): string => {\n  return `// ❌ Remove mock data generation (Array.fill, Math.random, etc.)\n\n// ✅ Fetch real records from database\nconst { data, error } = await supabase\n  .from('your_table_name')\n  .select('*')\n  .limit(50); // Adjust limit as needed\n\n// If table doesn't exist yet, create it:\n// 1. Go to Supabase Dashboard → SQL Editor\n// 2. Create your table with proper columns\n// 3. Enable RLS policies for security\n// 4. Then fetch real data here`;\n};\n\n/**\n * Generate generic database snippet\n */\nconst generateGenericDatabaseSnippet = (_violation: MockViolation): string => {\n  return `// Generic database query template\nconst { data, error } = await supabase\n  .from('your_table_name') // ⚠️ Replace with your table\n  .select('*')\n  .order('created_at', { ascending: false });\n\nif (error) {\n  console.error('Database error:', error);\n  return;\n}\n\n// Use 'data' in your component\nconsole.log('Fetched data:', data);`;\n};\n\n/**\n * Generate all auto-fix suggestions for a list of violations\n */\nexport const generateAllAutoFixes = (violations: MockViolation[]): AutoFixSuggestion[] => {\n  return violations.map(generateAutoFix);\n};\n\n/**\n * Group auto-fixes by difficulty for better UX\n */\nexport const groupByDifficulty = (suggestions: AutoFixSuggestion[]) => {\n  return {\n    easy: suggestions.filter(s => s.difficulty === 'easy'),\n    medium: suggestions.filter(s => s.difficulty === 'medium'),\n    hard: suggestions.filter(s => s.difficulty === 'hard')\n  };\n};\n"},Symbol.toStringTag,{value:"Module"})),Rt=Object.freeze(Object.defineProperty({__proto__:null,default:"import { MockViolation } from '../types/mockdetector.types';\nimport { DatabaseViolation } from '../types/database.types';\n\n/**\n * Get severity score for prioritization\n */\nexport const getSeverityScore = (severity: string): number => {\n  switch (severity) {\n    case 'critical': return 4;\n    case 'high': return 3;\n    case 'medium': return 2;\n    case 'low': return 1;\n    default: return 0;\n  }\n};\n\n/**\n * Calculate priority score (severity × confidence) for smart sorting\n */\nexport const getPriorityScore = (violation: MockViolation | DatabaseViolation): number => {\n  const severityWeight = getSeverityScore(violation.severity);\n  const confidenceWeight = (violation.confidence || 50) / 100;\n  return severityWeight * confidenceWeight;\n};\n\n/**\n * ✅ PHASE 3: Confidence Scoring System\n * Calculates how confident we are that a violation is REAL mock data (not a false positive)\n * Scale: 0-100%\n * - 90-100%: Very confident (definitely mock data)\n * - 70-89%: High confidence (likely mock data)\n * - 50-69%: Medium confidence (possibly mock data)\n * - 30-49%: Low confidence (uncertain)\n * - 0-29%: Very low confidence (likely false positive)\n */\n\nexport function calculateViolationConfidence(violation: MockViolation | DatabaseViolation): number {\n  let confidence = 50; // Base confidence\n  const code = 'code' in violation ? violation.code?.toLowerCase() || '' : '';\n  const file = 'file' in violation ? violation.file?.toLowerCase() || '' : '';\n  const description = violation.description.toLowerCase();\n\n  // ========= CRITICAL PATTERN BOOSTS (NEW) =========\n  \n  // 🔴 React useState array (NEW)\n  if (description.includes('usestate') && description.includes('array')) {\n    confidence = 85; // Very high confidence\n  }\n  \n  // 🔴 useEffect fake data (NEW)\n  if (description.includes('useeffect') && (code.includes('fakeresponse') || code.includes('mockdata'))) {\n    confidence = 90; // Extremely high confidence\n  }\n  \n  // 🔴 Test array variables (NEW)\n  if (code.match(/const\\s+(testUsers|mockUsers|fakeData)/)) {\n    confidence = 85;\n  }\n\n  // ========= HIGH CONFIDENCE INDICATORS (+25 to +40 points) =========\n  \n  // 🔴 Extremely obvious mock data (+40)\n  if (code.includes('test@example.com') || code.includes('user@example.com')) {\n    confidence += 40;\n  }\n  if (code.includes('lorem ipsum') || code.includes('dolor sit amet')) {\n    confidence += 40;\n  }\n  if (code.includes('array.fill(') || code.includes('array(10).fill(')) {\n    confidence += 35;\n  }\n  if (code.includes('555-1234') || code.includes('555-5555')) {\n    confidence += 35;\n  }\n  \n  // 🟠 Very likely mock data (+30)\n  if (code.match(/const\\s+(mock|test|demo|sample)(data|users|items|products)/i)) {\n    confidence += 30;\n  }\n  if (code.match(/test_user|demo_account|sample_item|mock_product/i)) {\n    confidence += 30;\n  }\n  \n  // 🟡 Strong mock indicators (+25)\n  if (code.match(/\\[\\s*{\\s*id:\\s*1\\s*,/)) {\n    confidence += 25; // Hardcoded array starting with id:1\n  }\n  if (code.match(/user\\s*#?\\d+|item\\s*#?\\d+/i)) {\n    confidence += 25; // Sequential names\n  }\n\n  // ========= MEDIUM CONFIDENCE INDICATORS (+10 to +20 points) =========\n  \n  if (code.match(/123\\s*main\\s*street|456\\s*elm\\s*st/i)) {\n    confidence += 15;\n  }\n  if (code.includes('acme corp') || code.includes('test company')) {\n    confidence += 15;\n  }\n  if (code.match(/\\$9\\.99|\\$19\\.99|\\$99\\.99/)) {\n    confidence += 10;\n  }\n\n  // ========= NEGATIVE INDICATORS (Reduce confidence - likely false positive) =========\n  \n  // 🟢 Legitimate code patterns (-30 to -50)\n  if (file.includes('.config.') || file.includes('tailwind.config') || file.includes('vite.config')) {\n    confidence -= 50; // Config files are almost never mock data\n  }\n  if (file.includes('mockdetector') || file.includes('scanpatterns')) {\n    confidence -= 50; // MockDetector's own code\n  }\n  if (code.includes('supabase_publishable_key') || code.includes('vite_supabase')) {\n    confidence -= 40; // Supabase keys MUST be in code\n  }\n  if (code.includes('.from(') && code.includes('.select(')) {\n    confidence -= 30; // Database queries are legitimate\n  }\n  if (code.includes('import') || code.includes('export')) {\n    confidence -= 20; // Import/export statements\n  }\n  \n  // 🟢 Configuration and metadata (-25 to -35)\n  if (description.includes('configuration') || description.includes('settings')) {\n    confidence -= 30;\n  }\n  if (description.includes('api response') || description.includes('metadata')) {\n    confidence -= 35;\n  }\n  if (description.includes('batch insert') && description.includes('minutes ago')) {\n    confidence -= 40; // Recent batch inserts are legitimate\n  }\n\n  // ========= CONTEXT-BASED ADJUSTMENTS =========\n  \n  // React components get +20 boost\n  if (file.includes('/components/') || file.includes('/pages/')) {\n    confidence += 20;\n  }\n  \n  // Database violations get +10 confidence (more reliable)\n  if ('table' in violation) {\n    confidence += 10;\n  }\n  \n  // Critical severity gets +5 confidence\n  if (violation.severity === 'critical') {\n    confidence += 5;\n  }\n\n  // Clamp to 0-100 range\n  return Math.max(0, Math.min(100, Math.round(confidence)));\n}\n\n/**\n * Get confidence level label\n */\nexport function getConfidenceLevel(confidence: number): {\n  level: 'very_high' | 'high' | 'medium' | 'low' | 'very_low';\n  label: string;\n  color: string;\n  emoji: string;\n} {\n  if (confidence >= 85) {  // Changed from 90\n    return { \n      level: 'very_high', \n      label: 'Very High Confidence', \n      color: 'text-red-600', \n      emoji: '🔴' \n    };\n  }\n  if (confidence >= 70) {\n    return { \n      level: 'high', \n      label: 'High Confidence', \n      color: 'text-orange-600', \n      emoji: '🟠' \n    };\n  }\n  if (confidence >= 55) {  // Changed from 50\n    return { \n      level: 'medium', \n      label: 'Medium Confidence', \n      color: 'text-yellow-600', \n      emoji: '🟡' \n    };\n  }\n  if (confidence >= 40) {  // Changed from 30\n    return { \n      level: 'low', \n      label: 'Low Confidence', \n      color: 'text-blue-500', \n      emoji: '🔵' \n    };\n  }\n  return { \n    level: 'very_low', \n    label: 'Very Low Confidence', \n    color: 'text-gray-500', \n    emoji: '⚪' \n  };\n}\n\n/**\n * Filter violations by minimum confidence threshold\n */\nexport function filterByConfidence<T extends MockViolation | DatabaseViolation>(\n  violations: T[],\n  minConfidence: number = 40  // Changed from 60\n): Array<T & { confidence: number }> {\n  return violations\n    .map(v => ({\n      ...v,\n      confidence: calculateViolationConfidence(v)\n    }))\n    .filter(v => v.confidence >= minConfidence)\n    .sort((a, b) => b.confidence - a.confidence); // Sort by confidence DESC\n}\n\n/**\n * Group violations by confidence level\n */\nexport function groupByConfidence<T extends MockViolation | DatabaseViolation>(\n  violations: T[]\n): {\n  veryHigh: Array<T & { confidence: number }>;\n  high: Array<T & { confidence: number }>;\n  medium: Array<T & { confidence: number }>;\n  low: Array<T & { confidence: number }>;\n  veryLow: Array<T & { confidence: number }>;\n} {\n  const withConfidence = violations.map(v => ({\n    ...v,\n    confidence: calculateViolationConfidence(v)\n  }));\n\n  return {\n    veryHigh: withConfidence.filter(v => v.confidence >= 90).sort((a, b) => b.confidence - a.confidence),\n    high: withConfidence.filter(v => v.confidence >= 70 && v.confidence < 90).sort((a, b) => b.confidence - a.confidence),\n    medium: withConfidence.filter(v => v.confidence >= 50 && v.confidence < 70).sort((a, b) => b.confidence - a.confidence),\n    low: withConfidence.filter(v => v.confidence >= 30 && v.confidence < 50).sort((a, b) => b.confidence - a.confidence),\n    veryLow: withConfidence.filter(v => v.confidence < 30).sort((a, b) => b.confidence - a.confidence),\n  };\n}\n"},Symbol.toStringTag,{value:"Module"})),Ct=Object.freeze(Object.defineProperty({__proto__:null,default:"import { MockViolation } from '../types/mockdetector.types';\nimport { DatabaseViolation } from '../types/database.types';\n\n/**\n * ✅ PHASE 4: Context-Aware Auto-Fix Suggestions\n * Provides specific, copy-paste-ready fixes based on violation type and context\n */\n\nexport type ViolationType = \n  | 'useState_array'\n  | 'test_email'\n  | 'lorem_ipsum'\n  | 'array_fill'\n  | 'inline_map'\n  | 'mock_phone'\n  | 'sequential_users'\n  | 'hardcoded_array'\n  | 'static_data'\n  | 'test_username'\n  | 'mock_address'\n  | 'mock_company'\n  | 'mock_credit_card'\n  | 'mock_zip'\n  | 'supabase_query'\n  | 'api_call'\n  | 'generic';\n\n/**\n * Detect the specific type of violation\n */\nexport function detectViolationType(violation: MockViolation | DatabaseViolation): ViolationType {\n  const code = 'code' in violation ? violation.code?.toLowerCase() || '' : '';\n  const description = violation.description.toLowerCase();\n  const pattern = 'pattern' in violation ? violation.pattern.toLowerCase() : '';\n\n  // React patterns\n  if (code.includes('usestate([') || description.includes('usestate')) {\n    return 'useState_array';\n  }\n  if (code.includes('array.fill(') || code.includes('array(')) {\n    return 'array_fill';\n  }\n  if (code.match(/\\[\\s*\\{.*\\}\\s*\\]\\.map\\(/)) {\n    return 'inline_map';\n  }\n\n  // Email patterns\n  if (code.includes('test@') || code.includes('@example.') || pattern.includes('email')) {\n    return 'test_email';\n  }\n\n  // Text patterns\n  if (code.includes('lorem ipsum') || code.includes('dolor sit')) {\n    return 'lorem_ipsum';\n  }\n\n  // Phone patterns\n  if (code.includes('555-') || pattern.includes('phone')) {\n    return 'mock_phone';\n  }\n\n  // Sequential patterns\n  if (pattern.includes('sequential') || description.includes('sequential')) {\n    return 'sequential_users';\n  }\n\n  // Username patterns\n  if (pattern.includes('username') || description.includes('test username')) {\n    return 'test_username';\n  }\n\n  // Address patterns\n  if (pattern.includes('address') || description.includes('mock address')) {\n    return 'mock_address';\n  }\n\n  // Company patterns\n  if (pattern.includes('company') || description.includes('company name')) {\n    return 'mock_company';\n  }\n\n  // Credit card patterns\n  if (pattern.includes('credit_card') || description.includes('credit card')) {\n    return 'mock_credit_card';\n  }\n\n  // ZIP code patterns\n  if (pattern.includes('zip') || description.includes('zip code')) {\n    return 'mock_zip';\n  }\n\n  // Hardcoded arrays\n  if (code.includes('[{') && code.includes('}]')) {\n    return 'hardcoded_array';\n  }\n\n  // Static data\n  if (description.includes('static') || description.includes('hardcoded')) {\n    return 'static_data';\n  }\n\n  return 'generic';\n}\n\n/**\n * Generate context-specific fix suggestion\n */\nexport function generateContextualFix(violation: MockViolation | DatabaseViolation): string {\n  const type = detectViolationType(violation);\n  const tableName = 'table' in violation ? violation.table : 'your_table';\n\n  switch (type) {\n    case 'useState_array':\n      return `// ✅ Replace with database fetch:\nconst [data, setData] = useState([]);\n\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data, error } = await supabase\n      .from('${tableName}')\n      .select('*')\n      .order('created_at', { ascending: false })\n      .limit(10);\n    \n    if (error) {\n      console.error('Error fetching data:', error);\n      return;\n    }\n    \n    if (data) setData(data);\n  };\n  \n  fetchData();\n}, []);`;\n\n    case 'test_email':\n      return `// ✅ Use real user email from authentication:\nconst { data: { user } } = await supabase.auth.getUser();\nconst email = user?.email || 'support@yourdomain.com';\n\n// OR fetch from database:\nconst { data } = await supabase\n  .from('profiles')\n  .select('email')\n  .eq('id', userId)\n  .single();`;\n\n    case 'lorem_ipsum':\n      return `// ✅ Replace with real content from database:\nconst { data } = await supabase\n  .from('${tableName}')\n  .select('description, content, bio')\n  .eq('id', itemId)\n  .single();\n\n// OR use user-generated content:\nconst content = data?.description || 'No description available';`;\n\n    case 'array_fill':\n      return `// ❌ Array.fill() creates identical mock data!\n// ✅ Replace with real database query:\n\nconst { data, error } = await supabase\n  .from('${tableName}')\n  .select('*')\n  .limit(10);\n\nif (error) throw error;\nreturn data || [];`;\n\n    case 'inline_map':\n      return `// ✅ Move hardcoded data to state and fetch from database:\n\n// 1. Create state:\nconst [items, setItems] = useState([]);\n\n// 2. Fetch data:\nuseEffect(() => {\n  const loadItems = async () => {\n    const { data } = await supabase\n      .from('${tableName}')\n      .select('*');\n    setItems(data || []);\n  };\n  loadItems();\n}, []);\n\n// 3. Use in JSX:\n{items.map((item) => (\n  <YourComponent key={item.id} {...item} />\n))}`;\n\n    case 'mock_phone':\n      return `// ✅ Replace with real contact information:\n\n// Option 1: From settings/config table\nconst { data } = await supabase\n  .from('settings')\n  .select('support_phone, contact_phone')\n  .single();\n\n// Option 2: From user profile\nconst { data: profile } = await supabase\n  .from('profiles')\n  .select('phone_number')\n  .eq('id', userId)\n  .single();\n\nconst phone = data?.support_phone || '+1 (555) 123-4567'; // Your real number`;\n\n    case 'sequential_users':\n      return `// ❌ Sequential user generation detected!\n// ✅ Fetch real users from your database:\n\nconst { data: users, error } = await supabase\n  .from('profiles')\n  .select('id, name, email, avatar_url, created_at')\n  .order('created_at', { ascending: false })\n  .limit(20);\n\nif (error) {\n  console.error('Error fetching users:', error);\n  return [];\n}\n\nreturn users || [];`;\n\n    case 'test_username':\n      return `// ✅ Use real usernames from authentication:\n\nconst { data } = await supabase\n  .from('profiles')\n  .select('username, display_name, full_name')\n  .eq('id', userId)\n  .single();\n\nconst username = data?.username || data?.display_name || 'Anonymous';`;\n\n    case 'mock_address':\n      return `// ✅ Store and fetch real addresses:\n\nconst { data } = await supabase\n  .from('addresses')\n  .select('street, city, state, zip_code, country')\n  .eq('user_id', userId)\n  .single();\n\nconst fullAddress = \\`\\${data.street}, \\${data.city}, \\${data.state} \\${data.zip_code}\\`;`;\n\n    case 'mock_company':\n      return `// ✅ Use real company information:\n\nconst { data } = await supabase\n  .from('companies')\n  .select('name, industry, size, founded_year')\n  .eq('id', companyId)\n  .single();\n\nconst companyName = data?.name || 'Your Company';`;\n\n    case 'mock_credit_card':\n      return `// ⚠️ NEVER store real credit cards in your database!\n// ✅ Use Stripe or payment provider:\n\nimport { loadStripe } from '@stripe/stripe-js';\n\nconst stripe = await loadStripe('your_publishable_key');\nconst { error } = await stripe.confirmPayment({\n  elements,\n  confirmParams: {\n    return_url: 'https://yourdomain.com/payment-success',\n  },\n});`;\n\n    case 'mock_zip':\n      return `// ✅ Fetch real ZIP code from user location or address:\n\nconst { data } = await supabase\n  .from('addresses')\n  .select('zip_code, postal_code')\n  .eq('user_id', userId)\n  .eq('is_primary', true)\n  .single();\n\nconst zipCode = data?.zip_code || data?.postal_code;`;\n\n    case 'hardcoded_array':\n    case 'static_data':\n      return `// ✅ Replace hardcoded data with database fetch:\n\nconst { data, error } = await supabase\n  .from('${tableName}')\n  .select('*')\n  .order('created_at', { ascending: false });\n\nif (error) {\n  console.error('Database error:', error);\n  return [];\n}\n\nreturn data || [];`;\n\n    case 'generic':\n    default:\n      return `// ✅ Recommended fix:\n// 1. Create a Supabase table to store this data\n// 2. Replace hardcoded values with database queries\n// 3. Use useState and useEffect to load data dynamically\n\nconst [data, setData] = useState([]);\n\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data, error } = await supabase\n      .from('${tableName}')\n      .select('*');\n    if (data) setData(data);\n  };\n  fetchData();\n}, []);`;\n  }\n}\n\n/**\n * Get quick action suggestions based on violation type\n */\nexport function getQuickActions(violation: MockViolation | DatabaseViolation): Array<{\n  label: string;\n  action: 'create_table' | 'add_auth' | 'use_api' | 'fetch_data' | 'migrate_data';\n  description: string;\n}> {\n  const type = detectViolationType(violation);\n  const tableName = 'table' in violation ? violation.table : 'items';\n\n  const actions: Array<{\n    label: string;\n    action: 'create_table' | 'add_auth' | 'use_api' | 'fetch_data' | 'migrate_data';\n    description: string;\n  }> = [];\n\n  switch (type) {\n    case 'test_email':\n    case 'test_username':\n      actions.push({\n        label: 'Add Authentication',\n        action: 'add_auth',\n        description: 'Set up Supabase Auth to manage real users'\n      });\n      break;\n\n    case 'useState_array':\n    case 'hardcoded_array':\n    case 'array_fill':\n      actions.push({\n        label: `Create ${tableName} Table`,\n        action: 'create_table',\n        description: `Create a Supabase table to store ${tableName} data`\n      });\n      actions.push({\n        label: 'Fetch from Database',\n        action: 'fetch_data',\n        description: 'Replace hardcoded data with database queries'\n      });\n      break;\n\n    case 'lorem_ipsum':\n      actions.push({\n        label: 'Create Content Table',\n        action: 'create_table',\n        description: 'Store real content in a Supabase table'\n      });\n      break;\n\n    case 'mock_phone':\n    case 'mock_address':\n      actions.push({\n        label: 'Create Settings Table',\n        action: 'create_table',\n        description: 'Store contact information in database'\n      });\n      break;\n\n    case 'sequential_users':\n      actions.push({\n        label: 'Migrate to Real Users',\n        action: 'migrate_data',\n        description: 'Replace mock users with real user profiles'\n      });\n      break;\n\n    default:\n      actions.push({\n        label: 'Fetch from Database',\n        action: 'fetch_data',\n        description: 'Replace with real data from Supabase'\n      });\n  }\n\n  return actions;\n}\n\n/**\n * Enhance violation with contextual fix\n */\nexport function enhanceViolationWithFix(violation: MockViolation | DatabaseViolation): MockViolation | DatabaseViolation {\n  const contextualFix = generateContextualFix(violation);\n  const quickActions = getQuickActions(violation);\n  \n  return {\n    ...violation,\n    fix: contextualFix,\n    // Store quick actions in reasoning field for now (can add separate field later)\n    reasoning: `Quick fixes available: ${quickActions.map(a => a.label).join(', ')}`\n  };\n}\n"},Symbol.toStringTag,{value:"Module"})),_t=Object.freeze(Object.defineProperty({__proto__:null,default:"import { MockPatternDetector } from '../types/database.types';\n\n/**\n * ✅ PHASE 2 ENHANCEMENT: Advanced Semantic JSON Analysis\n * Intelligently distinguishes between mock data and legitimate configuration/API responses\n */\nfunction checkJsonForMockData(json: any): boolean {\n  const jsonStr = JSON.stringify(json).toLowerCase();\n  \n  // ✅ WHITELIST 1: Explicit \"no mock data\" declarations\n  const noMockDeclarations = [\n    'mock_data_rejected',\n    'authentic_only_policy',\n    'zero_mock_data',\n    '100% authentic',\n    'authenticity_level',\n    'no_demo_data',\n    'real_data_only',\n    'production_ready',\n    'authentic_communication',\n    'legal_compliance',\n    'platform_compliance',\n  ];\n  if (noMockDeclarations.some(declaration => jsonStr.includes(declaration))) {\n    return false; // NOT mock data - explicitly authentic!\n  }\n  \n  // ✅ WHITELIST 2: API response metadata (GitHub, StackOverflow, etc.)\n  const apiIndicators = [\n    'api.github.com',\n    'api.stackexchange.com',\n    'api.openai.com',\n    'googleapis.com',\n    'real_ais_found',\n    'api_response_valid',\n    'api_metadata',\n    'rate_limit',\n    'x-ratelimit',\n    'response_headers',\n    'api_version',\n    'github_verified',\n    'stackoverflow_verified',\n  ];\n  if (apiIndicators.some(indicator => jsonStr.includes(indicator))) {\n    return false; // Legitimate API response\n  }\n  \n  // ✅ WHITELIST 3: Configuration objects (amenities, features, settings, capabilities)\n  const configIndicators = [\n    '_features',\n    '_amenities',\n    '_config',\n    '_settings',\n    '_capabilities',\n    '_permissions',\n    'room_amenities',\n    'wellness_benefits',\n    'sensory_config',\n    'personality_traits',\n    'learning_objectives',\n    'skill_requirements',\n    'expected_outcomes',\n    'system_config',\n    'platform_settings',\n  ];\n  if (configIndicators.some(indicator => jsonStr.includes(indicator))) {\n    return false; // Configuration data, not mock data\n  }\n  \n  // ✅ WHITELIST 4: Metadata and system information\n  const metadataIndicators = [\n    'metadata',\n    'system_info',\n    'platform_stats',\n    'analytics_data',\n    'performance_metrics',\n    'audit_log',\n    'event_data',\n    'notification_settings',\n  ];\n  if (metadataIndicators.some(indicator => jsonStr.includes(indicator))) {\n    return false; // System metadata, not mock data\n  }\n  \n  // ✅ NOW check for ACTUAL mock data keywords (with stronger context)\n  const mockKeywords = [\n    'test_user@',\n    'demo_account',\n    'fake_email',\n    'lorem ipsum',\n    'test@example.com',\n    'mock_data\": true',\n    'is_test_data\": true',\n    'sample_user',\n    'dummy_data',\n    'placeholder_',\n  ];\n  return mockKeywords.some(keyword => jsonStr.includes(keyword));\n}\n\nexport const DATABASE_MOCK_PATTERNS: MockPatternDetector[] = [\n  {\n    name: 'test_email',\n    description: 'Test/demo email addresses',\n    severity: 'high',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(test|demo|sample|example|mock|fake)@/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'sequential_names',\n    description: 'Sequential numbered names (e.g., \"User 1\", \"Product 2\")',\n    severity: 'high',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(user|agent|test|demo|sample|person|member|student|ai|product|item|course|lesson|order|customer|client)\\s*#?\\d+$/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'placeholder_text',\n    description: 'Lorem ipsum and placeholder text',\n    severity: 'medium',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /lorem\\s+ipsum|placeholder|sample\\s+text|dummy\\s+content|this\\s+is\\s+a\\s+(test|sample|demo)\\s+(post|comment|description)/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_phone',\n    description: 'Mock phone numbers (555-xxxx pattern)',\n    severity: 'high',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /(\\+1[-.\\s]?)?\\(?\\b555\\)?[-.\\s]\\d{3,4}[-.\\s]?\\d{4}\\b|123[-.\\s]456[-.\\s]\\d{4}|000[-.\\s]000[-.\\s]\\d{4}/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_addresses',\n    description: 'Common mock addresses',\n    severity: 'medium',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(123|456|789)\\s+(main|elm|oak|maple)\\s+(st|street|ave|avenue|rd|road)|^(test|sample|demo)\\s+address/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_company_names',\n    description: 'Common mock company names',\n    severity: 'medium',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(acme|test|demo|sample|mock|example)\\s+(corp|inc|llc|ltd|company|co\\.?)|^(test|sample)\\s+(business|enterprise)/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_credit_cards',\n    description: 'Test credit card numbers',\n    severity: 'critical',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(4242\\s*4242|5555\\s*5555|3782\\s*8224|6011\\s*1111)/i.test(value.replace(/-/g, ' '));\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_zip_codes',\n    description: 'Common mock ZIP codes',\n    severity: 'low',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(12345|00000|11111|99999|55555)$/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_prices',\n    description: 'Suspiciously round mock prices',\n    severity: 'low',\n    test: (value) => {\n      if (typeof value !== 'string' && typeof value !== 'number') return false;\n      const str = String(value);\n      // Check for exactly $9.99, $19.99, $99.99, $999.99 or round thousands\n      return /^(9\\.99|19\\.99|29\\.99|49\\.99|99\\.99|999\\.99|1000|5000|10000|50000|100000)$/.test(str);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'mock_skus',\n    description: 'Mock product SKUs',\n    severity: 'medium',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(sku|prd|prod|item)[-_]?(00)?[01]\\d{1,3}$/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'meme_numbers',\n    description: 'Common meme/test numbers (42, 69, 1337, 9999)',\n    severity: 'low',\n    test: (value) => {\n      if (typeof value !== 'number') return false;\n      // Common test/meme numbers developers use\n      return [42, 69, 420, 1337, 9999, 12345, 54321].includes(value);\n    },\n    getExamples: (value) => String(value)\n  },\n  {\n    name: 'sequential_ids',\n    description: 'Sequential IDs in data (1, 2, 3, 4...)',\n    severity: 'critical',\n    test: (_value) => {\n      return false; // Table-level check\n    }\n  },\n  {\n    name: 'identical_timestamps',\n    description: 'Identical timestamps',\n    severity: 'low',\n    test: (_value) => {\n      return false; // Table-level check\n    }\n  },\n  {\n    name: 'test_usernames',\n    description: 'Test usernames',\n    severity: 'high',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(test|demo|sample|mock|fake|dummy|admin|system)[-_]?(user|admin|account|profile|member|bot)[-_]?\\d*$/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'example_domains',\n    description: 'Example domain names',\n    severity: 'medium',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /@(example|test|demo|sample)\\.(com|org|net)/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'hardcoded_dates',\n    description: 'Suspiciously common hardcoded dates',\n    severity: 'low',\n    test: (value) => {\n      if (typeof value !== 'string') return false;\n      return /^(2020|2021|2022|2023|2024|2025)-(01-01|12-31)|^1970-01-01|^2000-01-01/i.test(value);\n    },\n    getExamples: (value) => value\n  },\n  {\n    name: 'suspicious_json',\n    description: 'Mock data in JSON fields',\n    severity: 'medium',\n    test: (value) => {\n      if (typeof value === 'string') {\n        try {\n          const parsed = JSON.parse(value);\n          return checkJsonForMockData(parsed); // ✅ Use smart semantic analysis\n        } catch {\n          return false;\n        }\n      }\n      if (typeof value === 'object' && value !== null) {\n        return checkJsonForMockData(value); // ✅ Use smart semantic analysis\n      }\n      return false;\n    },\n    getExamples: (value) => {\n      try {\n        const obj = typeof value === 'string' ? JSON.parse(value) : value;\n        return JSON.stringify(obj, null, 2).substring(0, 200);\n      } catch {\n        return String(value).substring(0, 200);\n      }\n    }\n  }\n];\n\n/**\n * ✅ PHASE 1 ENHANCEMENT: Analyze table-level patterns with intelligent batch insert detection\n */\nexport function analyzeTableLevelPatterns(\n  rows: any[]\n): Array<{ pattern: string; description: string; severity: 'critical' | 'high' | 'medium'; examples: string[] }> {\n  const results: Array<{ pattern: string; description: string; severity: 'critical' | 'high' | 'medium'; examples: string[] }> = [];\n\n  if (rows.length < 3) return results; // Need at least 3 rows to detect patterns\n\n  // Check for sequential IDs\n  const idColumn = Object.keys(rows[0]).find(key => \n    key === 'id' || key.endsWith('_id') || key === 'agent_id'\n  );\n\n  if (idColumn) {\n    const ids = rows.map(r => r[idColumn]).filter(id => typeof id === 'number');\n    if (ids.length >= 3) {\n      const isSequential = ids.every((id, idx) => idx === 0 || id === ids[idx - 1] + 1);\n      if (isSequential) {\n        results.push({\n          pattern: 'sequential_ids',\n          description: `Sequential IDs detected in column \"${idColumn}\"`,\n          severity: 'critical',\n          examples: ids.slice(0, 5).map(String)\n        });\n      }\n    }\n  }\n\n  // ✅ PHASE 2: INTELLIGENT TIMESTAMP ANALYSIS - Distinguish batch inserts from seed data\n  const timestampColumns = Object.keys(rows[0]).filter(key =>\n    key.includes('created_at') || key.includes('updated_at') || key.includes('timestamp')\n  );\n\n  for (const col of timestampColumns) {\n    const timestamps = rows.map(r => r[col]).filter(Boolean);\n    if (timestamps.length >= 5) {\n      const uniqueTimestamps = new Set(timestamps.map(String));\n      \n      if (uniqueTimestamps.size === 1) {\n        const timestamp = new Date(timestamps[0]);\n        const now = new Date();\n        const ageInMinutes = (now.getTime() - timestamp.getTime()) / (1000 * 60);\n        const ageInHours = ageInMinutes / 60;\n        const ageInDays = ageInHours / 24;\n        \n        // ✅ WHITELIST 1: Recent batch insert (< 1 hour, < 100 rows) = LEGITIMATE\n        if (ageInMinutes < 60 && rows.length < 100) {\n          continue; // SKIP - legitimate recent batch operation\n        }\n        \n        // ✅ WHITELIST 2: Small batches (< 20 rows) = likely legitimate regardless of age\n        if (rows.length < 20) {\n          continue; // SKIP - small legitimate batch\n        }\n        \n        // ✅ WHITELIST 3: Medium batches (20-50 rows) under 24 hours = probably OK\n        if (rows.length <= 50 && ageInHours < 24) {\n          continue; // SKIP - recent medium-sized batch\n        }\n        \n        // 🚩 Flag as SUSPICIOUS if:\n        // - Old batch (> 7 days) with many rows = seed data\n        // - OR very large batch (> 100 rows) at exact same millisecond\n        // - OR medium batch (50-100) that's old (> 24 hours)\n        \n        let severity: 'critical' | 'high' | 'medium' = 'medium';\n        let ageDescription = '';\n        \n        if (ageInDays > 7) {\n          severity = 'high';\n          ageDescription = `${ageInDays.toFixed(0)} days ago`;\n        } else if (ageInHours > 24) {\n          severity = 'medium';\n          ageDescription = `${ageInHours.toFixed(0)} hours ago`;\n        } else {\n          ageDescription = `${ageInMinutes.toFixed(0)} minutes ago`;\n        }\n        \n        // Increase severity for very large batches\n        if (rows.length >= 100) {\n          severity = severity === 'high' ? 'critical' : 'high';\n        }\n        \n        results.push({\n          pattern: 'identical_timestamps',\n          description: `All ${timestamps.length} rows have identical \"${col}\" from ${ageDescription} (likely seed data)`,\n          severity,\n          examples: [String(timestamps[0])]\n        });\n      }\n    }\n  }\n\n  return results;\n}\n"},Symbol.toStringTag,{value:"Module"})),Tt=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector Widget Diagnostics\n * Provides helpful debugging information for common issues\n */\n\nexport interface DiagnosticInfo {\n  issue: string;\n  currentDomain: string;\n  possibleCauses: string[];\n  solutions: string[];\n  supportEmail: string;\n}\n\n/**\n * Diagnose API key authorization issues\n */\nexport function diagnoseApiKeyIssue(error: string): DiagnosticInfo | null {\n  const currentDomain = typeof window !== 'undefined' ? window.location.hostname : 'unknown';\n  \n  if (error.includes('Domain not authorized') || error.includes('domain') || error.includes('authorized')) {\n    return {\n      issue: 'Domain Authorization Failed',\n      currentDomain,\n      possibleCauses: [\n        'API key is not authorized for this domain',\n        'Domain configuration missing in admin panel',\n        'Wildcard (*) was used but specific domain is required'\n      ],\n      solutions: [\n        `Add \"${currentDomain}\" to allowed domains in admin panel`,\n        'Or use wildcard (*) for development/testing only',\n        'Check API key configuration at admin panel',\n        'Verify domain spelling matches exactly'\n      ],\n      supportEmail: 'fredrikssonanton01@gmail.com'\n    };\n  }\n  \n  if (error.includes('expired') || error.includes('Expired')) {\n    return {\n      issue: 'API Key Expired',\n      currentDomain,\n      possibleCauses: [\n        'API key has passed its expiration date',\n        'API key has expired'\n      ],\n      solutions: [\n        'Contact support for key renewal',\n        'Request new API key from admin panel'\n      ],\n      supportEmail: 'fredrikssonanton01@gmail.com'\n    };\n  }\n  \n  if (error.includes('limit') || error.includes('Limit')) {\n    return {\n      issue: 'Scan Limit Reached',\n      currentDomain,\n      possibleCauses: [\n        'Daily scan limit exceeded',\n        'Too many scans performed today'\n      ],\n      solutions: [\n        'Wait until tomorrow for limit reset',\n        'Contact support for limit increase',\n        'Upgrade to higher tier if available'\n      ],\n      supportEmail: 'fredrikssonanton01@gmail.com'\n    };\n  }\n  \n  return null;\n}\n\n/**\n * Log diagnostic information to console\n */\nexport function logDiagnostics(error: string): void {\n  const diagnostic = diagnoseApiKeyIssue(error);\n  \n  if (!diagnostic) {\n    console.error('[MockDetector] Unknown error:', error);\n    return;\n  }\n  \n  console.group('[MockDetector] 🔍 Diagnostic Report');\n  console.error('Issue:', diagnostic.issue);\n  console.log('Current Domain:', diagnostic.currentDomain);\n  console.log('Possible Causes:');\n  diagnostic.possibleCauses.forEach((cause, i) => console.log(`  ${i + 1}. ${cause}`));\n  console.log('Solutions:');\n  diagnostic.solutions.forEach((solution, i) => console.log(`  ${i + 1}. ${solution}`));\n  console.log('Support:', diagnostic.supportEmail);\n  console.groupEnd();\n}\n"},Symbol.toStringTag,{value:"Module"})),Et=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * Dynamic Widget Loader - Enables automatic updates without npm install\n * Loads widget dynamically from CDN with smart caching\n */\n\ninterface WidgetVersion {\n  version: string;\n  timestamp: string;\n  scriptUrl: string;\n}\n\nexport class DynamicWidgetLoader {\n  private static CDN_BASE = 'https://cdn.jsdelivr.net/npm/@mockdetector/widget@';\n  private static CACHE_KEY = 'mockdetector-cached-version';\n  private static ACTIVE_VERSION_KEY = 'mockdetector-active-version';\n\n  /**\n   * Get latest version from npm registry\n   */\n  static async getLatestVersion(): Promise<string | null> {\n    try {\n      const response = await fetch('https://registry.npmjs.org/@mockdetector/widget/latest');\n      if (!response.ok) return null;\n      \n      const data = await response.json();\n      return data.version || null;\n    } catch (error) {\n      console.error('MockDetector: Failed to fetch latest version', error);\n      return null;\n    }\n  }\n\n  /**\n   * Load widget from CDN (using UMD format for better compatibility)\n   */\n  static async loadFromCDN(version: string): Promise<void> {\n    const scriptUrl = `${this.CDN_BASE}${version}/dist/mockdetector-widget.umd.js`;\n    \n    return new Promise((resolve, reject) => {\n      const script = document.createElement('script');\n      script.src = scriptUrl;\n      script.crossOrigin = 'anonymous';\n      \n      script.onload = () => {\n        // Store successful load\n        localStorage.setItem(this.ACTIVE_VERSION_KEY, version);\n        localStorage.setItem(this.CACHE_KEY, JSON.stringify({\n          version,\n          timestamp: new Date().toISOString(),\n          scriptUrl\n        }));\n        resolve();\n      };\n      \n      script.onerror = () => {\n        reject(new Error(`Failed to load version ${version} from CDN`));\n      };\n      \n      document.body.appendChild(script);\n    });\n  }\n\n  /**\n   * Auto-update to new version\n   */\n  static async updateToVersion(newVersion: string): Promise<boolean> {\n    console.log(`📦 MockDetector: Starting update to v${newVersion}...`);\n    \n    try {\n      console.log(`📥 MockDetector: Downloading v${newVersion} from CDN...`);\n      const scriptUrl = `${this.CDN_BASE}${newVersion}/dist/mockdetector-widget.umd.js`;\n      console.log(`🔗 MockDetector: CDN URL: ${scriptUrl}`);\n      \n      await this.loadFromCDN(newVersion);\n      \n      console.log(`💾 MockDetector: Version v${newVersion} cached successfully`);\n      console.log(`✅ MockDetector: Update complete! Reload page to activate v${newVersion}`);\n      \n      return true;\n    } catch (error) {\n      console.error(`❌ MockDetector: Update to v${newVersion} failed:`, error);\n      return false;\n    }\n  }\n\n  /**\n   * Get cached version info\n   */\n  static getCachedVersion(): WidgetVersion | null {\n    try {\n      const cached = localStorage.getItem(this.CACHE_KEY);\n      return cached ? JSON.parse(cached) : null;\n    } catch (e) {\n      return null;\n    }\n  }\n\n  /**\n   * Get currently active version\n   */\n  static getActiveVersion(): string | null {\n    try {\n      return localStorage.getItem(this.ACTIVE_VERSION_KEY);\n    } catch (e) {\n      return null;\n    }\n  }\n\n  /**\n   * Clear cache (for debugging)\n   */\n  static clearCache(): void {\n    localStorage.removeItem(this.CACHE_KEY);\n    localStorage.removeItem(this.ACTIVE_VERSION_KEY);\n  }\n}\n"},Symbol.toStringTag,{value:"Module"})),Pt=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector: Project Health Score Calculator\n * \n * Calculates an overall project authenticity score (0-100) based on detected violations.\n * Higher score = more authentic/production-ready.\n */\n\nimport { ScanResult } from '../types/mockdetector.types';\n\nexport interface ProjectHealthScore {\n  overall: number; // 0-100\n  grade: 'A+' | 'A' | 'B' | 'C' | 'D' | 'F';\n  categories: {\n    frontend: { score: number; violations: number };\n    backend: { score: number; violations: number };\n    database: { score: number; violations: number };\n  };\n  trend?: 'improving' | 'stable' | 'declining';\n  recommendations: string[];\n  criticalIssues: number;\n  highIssues: number;\n  mediumIssues: number;\n  lowIssues: number;\n}\n\n/**\n * Calculate project health score from scan results\n */\nexport const calculateHealthScore = (\n  scanResult: ScanResult,\n  previousScore?: number\n): ProjectHealthScore => {\n  const violations = scanResult.mockDataViolations;\n  \n  // Count violations by severity\n  const criticalIssues = violations.filter(v => v.severity === 'critical').length;\n  const highIssues = violations.filter(v => v.severity === 'high').length;\n  const mediumIssues = violations.filter(v => v.severity === 'medium').length;\n  const lowIssues = violations.filter(v => v.severity === 'low').length;\n  \n  // Categorize violations\n  const frontendViolations = violations.filter(v => {\n    const desc = v.description.toLowerCase();\n    return !v.file?.includes('supabase/functions') && \n           !v.file?.includes('database') &&\n           (desc.includes('ui') || desc.includes('component') || desc.includes('jsx') || desc.includes('tsx'));\n  });\n  \n  const backendViolations = violations.filter(v => {\n    const desc = v.description.toLowerCase();\n    return v.file?.includes('supabase/functions') ||\n           desc.includes('edge function') || desc.includes('api') || desc.includes('function');\n  });\n  \n  const databaseViolations = violations.filter(v => {\n    const desc = v.description.toLowerCase();\n    return v.file?.includes('database') ||\n           desc.includes('database') || desc.includes('table') || desc.includes('supabase');\n  });\n  \n  // Calculate weighted deductions\n  const criticalDeduction = criticalIssues * 15;\n  const highDeduction = highIssues * 8;\n  const mediumDeduction = mediumIssues * 3;\n  const lowDeduction = lowIssues * 1;\n  \n  const totalDeduction = criticalDeduction + highDeduction + mediumDeduction + lowDeduction;\n  \n  // Overall score (start at 100, deduct points)\n  const overall = Math.max(0, Math.min(100, 100 - totalDeduction));\n  \n  // Category scores\n  const frontendScore = Math.max(0, 100 - (frontendViolations.length * 5));\n  const backendScore = Math.max(0, 100 - (backendViolations.length * 8));\n  const databaseScore = Math.max(0, 100 - (databaseViolations.length * 10));\n  \n  // Determine grade\n  const grade = getGrade(overall);\n  \n  // Determine trend (if previous score available)\n  const trend = previousScore \n    ? overall > previousScore + 5 ? 'improving'\n      : overall < previousScore - 5 ? 'declining'\n      : 'stable'\n    : undefined;\n  \n  // Generate recommendations\n  const recommendations = generateRecommendations({\n    criticalIssues,\n    highIssues,\n    mediumIssues,\n    lowIssues,\n    frontendViolations: frontendViolations.length,\n    backendViolations: backendViolations.length,\n    databaseViolations: databaseViolations.length,\n    overall\n  });\n  \n  return {\n    overall: Math.round(overall),\n    grade,\n    categories: {\n      frontend: { score: Math.round(frontendScore), violations: frontendViolations.length },\n      backend: { score: Math.round(backendScore), violations: backendViolations.length },\n      database: { score: Math.round(databaseScore), violations: databaseViolations.length }\n    },\n    trend,\n    recommendations,\n    criticalIssues,\n    highIssues,\n    mediumIssues,\n    lowIssues\n  };\n};\n\n/**\n * Convert numerical score to letter grade\n */\nconst getGrade = (score: number): 'A+' | 'A' | 'B' | 'C' | 'D' | 'F' => {\n  if (score >= 98) return 'A+';\n  if (score >= 90) return 'A';\n  if (score >= 80) return 'B';\n  if (score >= 70) return 'C';\n  if (score >= 60) return 'D';\n  return 'F';\n};\n\n/**\n * Generate actionable recommendations based on violations\n */\nconst generateRecommendations = (metrics: {\n  criticalIssues: number;\n  highIssues: number;\n  mediumIssues: number;\n  lowIssues: number;\n  frontendViolations: number;\n  backendViolations: number;\n  databaseViolations: number;\n  overall: number;\n}): string[] => {\n  const recommendations: string[] = [];\n  \n  // Critical issues\n  if (metrics.criticalIssues > 0) {\n    recommendations.push(`🚨 URGENT: Fix ${metrics.criticalIssues} critical issue${metrics.criticalIssues > 1 ? 's' : ''} immediately (Array.fill, Math.random, hardcoded API responses)`);\n  }\n  \n  // High priority issues\n  if (metrics.highIssues > 5) {\n    recommendations.push(`⚠️ HIGH PRIORITY: Address ${metrics.highIssues} high-severity mock data violations`);\n  }\n  \n  // Database issues\n  if (metrics.databaseViolations > 0) {\n    recommendations.push(`💾 Database: Review ${metrics.databaseViolations} database mock data issue${metrics.databaseViolations > 1 ? 's' : ''} - ensure all queries fetch real data`);\n  }\n  \n  // Backend issues\n  if (metrics.backendViolations > 0) {\n    recommendations.push(`🔧 Backend: Fix ${metrics.backendViolations} edge function mock data issue${metrics.backendViolations > 1 ? 's' : ''} - replace with real API calls`);\n  }\n  \n  // Frontend issues\n  if (metrics.frontendViolations > 5) {\n    recommendations.push(`🎨 Frontend: Replace ${metrics.frontendViolations} hardcoded UI elements with dynamic data`);\n  }\n  \n  // General recommendations based on score\n  if (metrics.overall < 50) {\n    recommendations.push('📊 Your project has significant mock data. Consider a systematic refactor to use real database queries.');\n  } else if (metrics.overall < 80) {\n    recommendations.push('✨ Good progress! Focus on remaining high-priority issues to reach production-ready status.');\n  } else if (metrics.overall >= 95) {\n    recommendations.push('🎉 Excellent! Your project is production-ready with minimal mock data.');\n  }\n  \n  // Medium priority reminder\n  if (metrics.mediumIssues > 10) {\n    recommendations.push(`📝 Medium Priority: ${metrics.mediumIssues} issues remaining - tackle these after critical/high issues`);\n  }\n  \n  return recommendations.slice(0, 5); // Max 5 recommendations for better UX\n};\n\n/**\n * Get color coding for health score\n */\nexport const getScoreColor = (score: number): string => {\n  if (score >= 90) return 'text-green-600';\n  if (score >= 70) return 'text-yellow-600';\n  if (score >= 50) return 'text-orange-600';\n  return 'text-red-600';\n};\n\n/**\n * Get emoji for health score\n */\nexport const getScoreEmoji = (score: number): string => {\n  if (score >= 95) return '🏆';\n  if (score >= 90) return '✨';\n  if (score >= 80) return '👍';\n  if (score >= 70) return '😐';\n  if (score >= 50) return '⚠️';\n  return '🚨';\n};\n\n/**\n * Format health score for display\n */\nexport const formatHealthScore = (healthScore: ProjectHealthScore): string => {\n  const emoji = getScoreEmoji(healthScore.overall);\n  return `${emoji} ${healthScore.overall}/100 (Grade: ${healthScore.grade})`;\n};\n\n/**\n * Calculate improvement needed to reach next grade\n */\nexport const getImprovementNeeded = (currentScore: number): { \n  nextGrade: string; \n  pointsNeeded: number;\n  violationsToFix: number;\n} => {\n  let nextGrade: string;\n  let targetScore: number;\n  \n  if (currentScore >= 98) {\n    return { nextGrade: 'A+', pointsNeeded: 0, violationsToFix: 0 };\n  } else if (currentScore >= 90) {\n    nextGrade = 'A+';\n    targetScore = 98;\n  } else if (currentScore >= 80) {\n    nextGrade = 'A';\n    targetScore = 90;\n  } else if (currentScore >= 70) {\n    nextGrade = 'B';\n    targetScore = 80;\n  } else if (currentScore >= 60) {\n    nextGrade = 'C';\n    targetScore = 70;\n  } else {\n    nextGrade = 'D';\n    targetScore = 60;\n  }\n  \n  const pointsNeeded = targetScore - currentScore;\n  \n  // Estimate violations to fix (assuming average 5 points per fix)\n  const violationsToFix = Math.ceil(pointsNeeded / 5);\n  \n  return { nextGrade, pointsNeeded, violationsToFix };\n};\n"},Symbol.toStringTag,{value:"Module"})),It=Object.freeze(Object.defineProperty({__proto__:null,default:"import { supabase } from '@/integrations/supabase/client';\nimport { ProjectSize, ProjectSizeMetrics } from '../types/scanConfig.types';\n\n/**\n * Detect database size based on table count and estimated rows\n */\nexport async function detectDatabaseSize(): Promise<'small' | 'medium' | 'large'> {\n  try {\n    // Get all tables from public schema\n    const { data: tables, error } = await supabase.rpc('get_public_tables' as any);\n    \n    if (error || !tables) {\n      console.warn('Could not detect database size, defaulting to small');\n      return 'small';\n    }\n    \n    const tableCount = Array.isArray(tables) ? tables.length : 0;\n    \n    // Estimate total rows (sampling approach)\n    let estimatedTotalRows = 0;\n    const sampleTables = Array.isArray(tables) ? tables.slice(0, 5) : [];\n    \n    for (const tableData of sampleTables) {\n      const tableName = typeof tableData === 'string' ? tableData : tableData.table_name;\n      if (!tableName) continue;\n      \n      try {\n        const { count } = await supabase\n          .from(tableName as any)\n          .select('*', { count: 'exact', head: true });\n        \n        estimatedTotalRows += count || 0;\n      } catch (err) {\n        // Skip tables we can't access\n        continue;\n      }\n    }\n    \n    // Extrapolate to all tables\n    const avgRowsPerTable = estimatedTotalRows / Math.max(sampleTables.length, 1);\n    const totalEstimatedRows = avgRowsPerTable * tableCount;\n    \n    console.log(`📊 Database: ${tableCount} tables, ~${Math.round(totalEstimatedRows)} rows`);\n    \n    // Classification\n    if (tableCount > 50 || totalEstimatedRows > 10000) {\n      return 'large';\n    } else if (tableCount > 10 || totalEstimatedRows > 1000) {\n      return 'medium';\n    }\n    return 'small';\n    \n  } catch (error) {\n    console.error('Error detecting database size:', error);\n    return 'small';\n  }\n}\n\n/**\n * Estimate source file count (rough approximation without edge function)\n */\nexport function estimateSourceFileCount(): number {\n  // Try to navigate to routes and see which exist (this is approximate)\n  // In practice, we'll use the actual route list length\n  const allLinks = document.querySelectorAll('a[href^=\"/\"]');\n  const uniqueRoutes = new Set<string>();\n  \n  allLinks.forEach(link => {\n    const href = link.getAttribute('href');\n    if (href && href.startsWith('/') && !href.includes('#')) {\n      uniqueRoutes.add(href.split('?')[0]);\n    }\n  });\n  \n  const detectedRoutes = uniqueRoutes.size;\n  \n  // Rough estimation: 3-5 files per route on average\n  const estimatedFiles = detectedRoutes * 4;\n  \n  console.log(`📊 Estimated ${detectedRoutes} routes → ~${estimatedFiles} source files`);\n  \n  return estimatedFiles;\n}\n\n/**\n * Get all available routes from the application\n */\nexport function getAllRoutes(): string[] {\n  const routes = new Set<string>();\n  \n  // 1. Find all <a> tags with href starting with \"/\"\n  const allLinks = document.querySelectorAll('a[href^=\"/\"]');\n  allLinks.forEach(link => {\n    const href = link.getAttribute('href');\n    if (href && href.startsWith('/') && !href.includes('#')) {\n      routes.add(href.split('?')[0]);\n    }\n  });\n  \n  // 2. Find all React Router Link components (they render as <a> but might have data attributes)\n  const reactLinks = document.querySelectorAll('[data-discover-link], [href^=\"/\"]');\n  reactLinks.forEach(link => {\n    const href = link.getAttribute('href');\n    if (href && href.startsWith('/') && !href.includes('#')) {\n      routes.add(href.split('?')[0]);\n    }\n  });\n  \n  // 3. Add common routes that should always be scanned\n  const commonRoutes = [\n    '/',\n    '/dashboard',\n    '/profile',\n    '/settings',\n    '/moderator',\n    '/admin',\n    '/supabase-monitoring',\n    '/qa/audit',\n    '/ai-discovery',\n    '/ai-learning',\n    '/chat-hub',\n    '/discussion/general',\n    '/memory-center',\n    '/personal-ai',\n    '/research/library',\n    '/ai-beacon/register',\n    '/ai-discovery-observatory',\n    '/ai-social-dynamics',\n    '/ai-meta-learning',\n    '/real-ai-integration',\n    '/ai-feedback-processor',\n    '/lovable-tools-builder'\n  ];\n  commonRoutes.forEach(route => routes.add(route));\n  \n  const routesArray = Array.from(routes).sort();\n  console.log(`🔍 getAllRoutes(): Found ${routesArray.length} routes:`, routesArray);\n  \n  return routesArray;\n}\n\n/**\n * Get prioritized routes based on likelihood of containing mock data\n * High-risk routes are scanned first for efficiency\n */\nexport function getPrioritizedRoutes(): string[] {\n  const allRoutes = getAllRoutes();\n  \n  // Define priority tiers (high risk = more likely to have mock data)\n  const priorityTiers = {\n    critical: [\n      '/dashboard', '/admin', '/moderator', '/analytics', '/stats',\n      '/supabase-monitoring', '/monitoring', '/metrics'\n    ],\n    high: [\n      '/profile', '/user', '/users', '/account', '/settings',\n      '/orders', '/products', '/inventory', '/sales', '/customers',\n      '/billing', '/payments', '/transactions', '/invoices'\n    ],\n    medium: [\n      '/about', '/contact', '/team', '/pricing', '/features',\n      '/demo', '/test', '/example', '/sample', '/playground'\n    ],\n    low: [\n      '/', '/home', '/login', '/signup', '/auth', '/forgot-password',\n      '/privacy', '/terms', '/docs', '/help', '/faq'\n    ]\n  };\n  \n  // Score each route\n  const scoredRoutes = allRoutes.map(route => {\n    let score = 0;\n    const routeLower = route.toLowerCase();\n    \n    // Critical tier (100 points)\n    if (priorityTiers.critical.some(pattern => routeLower.includes(pattern))) {\n      score += 100;\n    }\n    \n    // High tier (75 points)\n    if (priorityTiers.high.some(pattern => routeLower.includes(pattern))) {\n      score += 75;\n    }\n    \n    // Medium tier (50 points)\n    if (priorityTiers.medium.some(pattern => routeLower.includes(pattern))) {\n      score += 50;\n    }\n    \n    // Low tier (25 points)\n    if (priorityTiers.low.some(pattern => routeLower.includes(pattern))) {\n      score += 25;\n    }\n    \n    // Bonus points for specific keywords\n    if (/test|demo|mock|sample|example|playground/.test(routeLower)) {\n      score += 30; // Likely contains test data!\n    }\n    if (/admin|moderator|dashboard/.test(routeLower)) {\n      score += 20; // Admin pages often show stats\n    }\n    if (/data|table|list|grid|chart/.test(routeLower)) {\n      score += 15; // Data display pages\n    }\n    \n    // Default score for unmatched routes\n    if (score === 0) score = 10;\n    \n    return { route, score };\n  });\n  \n  // Sort by score (descending) and return routes only\n  const prioritized = scoredRoutes\n    .sort((a, b) => b.score - a.score)\n    .map(item => item.route);\n  \n  console.log(`🎯 Prioritized ${prioritized.length} routes by mock data risk`);\n  console.log(`   Top 5 high-risk routes:`, prioritized.slice(0, 5));\n  \n  return prioritized;\n}\n\n/**\n * Main function: Detect project size based on all metrics\n */\nexport async function detectProjectSize(): Promise<ProjectSizeMetrics> {\n  console.log('🔍 Detecting project size...');\n  \n  // Get metrics\n  const routes = getAllRoutes();\n  const routeCount = routes.length;\n  const databaseSize = await detectDatabaseSize();\n  const estimatedSourceFiles = estimateSourceFileCount();\n  \n  // Scoring system (0-6 points)\n  let score = 0;\n  \n  // Routes (0-2 points)\n  if (routeCount > 50) score += 2;\n  else if (routeCount > 20) score += 1;\n  \n  // Database (0-2 points)\n  if (databaseSize === 'large') score += 2;\n  else if (databaseSize === 'medium') score += 1;\n  \n  // Source files (0-2 points)\n  if (estimatedSourceFiles > 500) score += 2;\n  else if (estimatedSourceFiles > 200) score += 1;\n  \n  // Classify project size\n  let size: ProjectSize;\n  if (score >= 4) {\n    size = 'large';\n  } else if (score >= 2) {\n    size = 'medium';\n  } else {\n    size = 'small';\n  }\n  \n  const metrics: ProjectSizeMetrics = {\n    routeCount,\n    databaseSize,\n    estimatedSourceFiles,\n    score,\n    size\n  };\n  \n  console.log(`📊 Project Size Detection:`, metrics);\n  \n  return metrics;\n}\n\n/**\n * Get recommended scan strategy message for UI\n */\nexport function getProjectSizeRecommendation(size: ProjectSize): {\n  title: string;\n  description: string;\n  recommendations: string[];\n} {\n  switch (size) {\n    case 'large':\n      return {\n        title: '⚠️ Large Project Detected',\n        description: 'Your project has 50+ routes or 50+ database tables.',\n        recommendations: [\n          '✅ Recommended: Use \"Quick Scan This Page\" for targeted scanning',\n          '⚠️ Warning: \"Deep Scan\" may take 5-10 minutes',\n          '💡 Tip: Use \"Scan Database\" separately for better performance',\n          '🎯 Best: Focus scans on specific critical pages'\n        ]\n      };\n    \n    case 'medium':\n      return {\n        title: '📊 Medium Project Detected',\n        description: 'Your project has 20-50 routes or 10-50 database tables.',\n        recommendations: [\n          '✅ Recommended: \"Deep Scan\" with batch processing (2-3 minutes)',\n          '💡 Tip: \"Scan All Routes\" will process in batches automatically',\n          '⚡ Alternative: Use \"Quick Scan\" on important pages'\n        ]\n      };\n    \n    default: // small\n      return {\n        title: '✅ Small Project',\n        description: 'Your project is optimized for fast scanning.',\n        recommendations: [\n          '✅ All scan types are fast and safe',\n          '🚀 \"Deep Scan\" recommended for comprehensive results',\n          '⚡ Typical scan time: 30-60 seconds'\n        ]\n      };\n  }\n}\n"},Symbol.toStringTag,{value:"Module"})),At=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector: React-Specific Mock Data Patterns\n * \n * Detects React-specific mock data patterns including:\n * - useState with hardcoded arrays/objects\n * - useEffect with mock data\n * - Component props with mock values\n * - Map functions with hardcoded data\n */\n\nimport { MockViolation } from '../types/mockdetector.types';\nimport { calculateViolationConfidence } from './confidenceScoring';\nimport { enhanceViolationWithFix } from './contextualAutoFix';\n\nexport interface ReactPattern {\n  name: string;\n  pattern: RegExp;\n  severity: 'critical' | 'high' | 'medium' | 'low';\n  description: string;\n  autoFix: (match: RegExpMatchArray, code: string) => string | null;\n}\n\nexport const REACT_MOCK_PATTERNS: ReactPattern[] = [\n  {\n    name: 'useState_hardcoded_array',\n    pattern: /useState\\s*(?:<[^>]+>)?\\s*\\(\\s*\\[\\s*\\{/g,\n    severity: 'critical',\n    description: 'useState initialized with hardcoded array of objects (likely mock data)',\n    autoFix: (_match) => {\n      return `// Replace with database fetch:\nconst [data, setData] = useState([]);\n\nuseEffect(() => {\n  const fetchData = async () => {\n    const { data, error } = await supabase\n      .from('your_table')\n      .select('*');\n    if (data) setData(data);\n  };\n  fetchData();\n}, []);`;\n    }\n  },\n  \n  {\n    name: 'useEffect_fake_response',\n    pattern: /useEffect\\s*\\([^)]*\\)\\s*=>\\s*\\{[^}]*(?:fakeResponse|mockData|testData|fakeAPI|fakeFetch)\\s*=/g,\n    severity: 'critical',\n    description: 'useEffect contains fake/mock data assignment instead of real API call',\n    autoFix: (_match) => {\n      return `// Replace fake data with real Supabase query:\nuseEffect(() => {\n  const fetchRealData = async () => {\n    const { data, error } = await supabase.from('your_table').select('*');\n    if (data) setYourState(data);\n  };\n  fetchRealData();\n}, []);`;\n    }\n  },\n  \n  {\n    name: 'suspicious_function_names',\n    pattern: /(?:const|function)\\s+(?:handle|validate|fetch|get)?(?:Mock|Test|Fake|Demo|Sample)[A-Z]\\w*\\s*=/g,\n    severity: 'high',\n    description: 'Function name contains mock/test/fake - likely temporary code',\n    autoFix: (match) => {\n      const funcName = match[0].match(/(?:Mock|Test|Fake|Demo|Sample)[A-Z]\\w*/)?.[0] || '';\n      const realName = funcName.replace(/Mock|Test|Fake|Demo|Sample/gi, '');\n      return `// Rename function: ${funcName} → ${realName}\\n// Remove mock/test prefix`;\n    }\n  },\n  \n  {\n    name: 'test_array_variables',\n    pattern: /const\\s+(testUsers|mockUsers|fakeData|demoData|sampleData|testData|mockItems|fakeProducts)\\s*=\\s*\\[/g,\n    severity: 'high',\n    description: 'Variable name suggests test/mock data array',\n    autoFix: (match) => {\n      const varName = match[1];\n      const realName = varName.replace(/test|mock|fake|demo|sample/gi, '');\n      return `// Replace: const ${varName} = [...]\\n// With: Fetch real data and store in const ${realName}`;\n    }\n  },\n  \n  // useState_hardcoded_number pattern REMOVED - too aggressive\n  // Legitimate uses: progress bars (useState(13)), counters (useState(0)), pagination (useState(1))\n  // Only flag if it's clearly mock data (thousands/millions), not configuration values\n  \n  {\n    name: 'map_with_array_literal',\n    pattern: /\\[\\s*\\{[^}]*\\}\\s*(?:,\\s*\\{[^}]*\\}){2,}\\s*\\]\\.map\\s*\\(/g,\n    severity: 'high',\n    description: 'Array literal with objects directly in .map() call (hardcoded data)',\n    autoFix: (_match) => {\n      return `// Replace with state-based data:\n{data.map((item) => (\n  // Your JSX here\n))}\n\n// Fetch data with:\nuseEffect(() => {\n  const loadData = async () => {\n    const { data } = await supabase.from('your_table').select('*');\n    setData(data || []);\n  };\n  loadData();\n}, []);`;\n    }\n  },\n  \n  {\n    name: 'array_fill_mock',\n    pattern: /Array\\s*\\(\\s*\\d+\\s*\\)\\.fill\\s*\\(\\s*\\{[^}]*\\}\\s*\\)/g,\n    severity: 'critical',\n    description: 'Array.fill() with mock objects (generates fake data)',\n    autoFix: (_match) => {\n      return `// ❌ Array.fill() creates identical mock data!\n// ✅ Replace with real database query:\nconst { data } = await supabase\n  .from('your_table')\n  .select('*')\n  .limit(10); // Adjust limit as needed`;\n    }\n  },\n  \n  // Math.random() pattern REMOVED - too many false positives (UI animations, effects)\n  \n  {\n    name: 'test_email_pattern',\n    pattern: /(test|demo|sample|example)@(test|demo|example)\\.(com|org|net)/gi,\n    severity: 'high',\n    description: 'Test email address found in code',\n    autoFix: (_match) => {\n      return `// ❌ Test email detected!\n// ✅ Use real user email from auth:\nconst { data: { user } } = await supabase.auth.getUser();\nconst email = user?.email;`;\n    }\n  },\n  \n  {\n    name: 'sequential_user_mock',\n    pattern: /(user|name|email):\\s*['\"`](User|Name|Email)\\s*\\$\\{i\\$\\}['\"`]/gi,\n    severity: 'critical',\n    description: 'Sequential user generation pattern (User ${i}, Name ${i}, etc.)',\n    autoFix: (_match) => {\n      return `// ❌ Sequential mock users detected!\n// ✅ Fetch real users from database:\nconst { data: users } = await supabase\n  .from('profiles')\n  .select('id, name, email')\n  .order('created_at', { ascending: false })\n  .limit(10);`;\n    }\n  },\n  \n  // lorem_ipsum pattern now checks context to avoid flagging comments and detection code\n  {\n    name: 'lorem_ipsum',\n    pattern: /(['\"`]).*?(lorem\\s+ipsum|dolor\\s+sit\\s+amet).*?\\1/gi,\n    severity: 'medium',\n    description: 'Lorem Ipsum placeholder text found in string',\n    autoFix: (_match) => {\n      return `// ❌ Lorem Ipsum placeholder text!\n// ✅ Use real content from your database:\nconst { data } = await supabase\n  .from('content')\n  .select('text')\n  .eq('type', 'description')\n  .single();`;\n    }\n  },\n  \n  {\n    name: 'date_now_mock',\n    pattern: /new\\s+Date\\s*\\(\\s*['\"`]\\d{4}-\\d{2}-\\d{2}['\"`]\\s*\\)/g,\n    severity: 'low',\n    description: 'Hardcoded date string (consider using real timestamps)',\n    autoFix: (_match) => {\n      return `// Consider using real timestamps from database:\n// created_at, updated_at columns are automatically set by Supabase`;\n    }\n  },\n  \n  {\n    name: 'useEffect_with_mock_data',\n    pattern: /useEffect\\s*\\(\\s*\\(\\s*\\)\\s*=>\\s*\\{\\s*set\\w+\\s*\\(\\s*\\[[^\\]]{50,}\\]\\s*\\)/g,\n    severity: 'high',\n    description: 'useEffect setting state with inline mock data array',\n    autoFix: (_match) => {\n      return `// Replace mock data with real API/database call:\nuseEffect(() => {\n  const fetchData = async () => {\n    try {\n      const { data, error } = await supabase\n        .from('your_table')\n        .select('*');\n      \n      if (error) throw error;\n      setData(data || []);\n    } catch (error) {\n      console.error('Error fetching data:', error);\n    }\n  };\n  \n  fetchData();\n}, []);`;\n    }\n  },\n  \n  {\n    name: 'hardcoded_api_response',\n    pattern: /const\\s+\\w+\\s*=\\s*\\{\\s*data:\\s*\\[[^\\]]{50,}\\]/g,\n    severity: 'critical',\n    description: 'Hardcoded API response object with data array',\n    autoFix: (_match) => {\n      return `// ❌ Hardcoded API response!\n// ✅ Make real API call:\nconst response = await supabase.functions.invoke('your-function', {\n  body: { /* your params */ }\n});\nconst data = response.data;`;\n    }\n  },\n  \n  {\n    name: 'fetch_mock_url',\n    pattern: /(?:fetch|axios\\.(?:get|post|put|delete))\\s*\\(\\s*['\"`](?:https?:\\/\\/)?(?:localhost|127\\.0\\.0\\.1|example\\.com|test\\.com|jsonplaceholder\\.typicode\\.com|reqres\\.in|mockapi\\.io)/gi,\n    severity: 'critical',\n    description: 'HTTP request to mock/test endpoint (localhost, example.com, or mock API)',\n    autoFix: (_match) => {\n      return `// ❌ Fetch/Axios to mock URL detected!\n// ✅ Replace with Supabase Edge Function:\nconst { data, error } = await supabase.functions.invoke('your-function', {\n  body: { /* params */ }\n});`;\n    }\n  },\n  \n  // console_log_mock_data pattern REMOVED - was flagging console.logs about the \n  // mock detection system itself, e.g. \"Mock chat simulation disabled\"\n];\n\n/**\n * Scan React code for mock data patterns\n */\nexport const scanReactCode = (code: string, fileName?: string): MockViolation[] => {\n  const violations: MockViolation[] = [];\n  const lines = code.split('\\n');\n  \n  REACT_MOCK_PATTERNS.forEach(({ name: _name, pattern, severity, description, autoFix }) => {\n    // Reset regex state\n    pattern.lastIndex = 0;\n    \n    let match: RegExpMatchArray | null;\n    while ((match = pattern.exec(code)) !== null) {\n      // Find line number\n      const lineNumber = code.substring(0, match.index).split('\\n').length;\n      const line = lines[lineNumber - 1];\n      \n      // Generate auto-fix suggestion\n      const fixSuggestion = autoFix(match, code);\n      \n      const violation: MockViolation = {\n        type: 'mock_data',\n        severity,\n        file: fileName,\n        line: lineNumber,\n        code: line?.trim() || match[0].trim(),\n        description: `React Pattern: ${description}`,\n        fix: fixSuggestion || 'Replace with real data from database or API',\n        confidence: 0 // Will be calculated\n      };\n      \n      // ✅ PHASE 3: Calculate confidence\n      violation.confidence = calculateViolationConfidence(violation);\n      \n      // Boost confidence for React-specific patterns\n      if (fileName?.includes('/components/') || fileName?.includes('/pages/')) {\n        violation.confidence = Math.min(100, (violation.confidence || 50) + 20);\n      }\n      \n      // Critical patterns get extra boost\n      const patternName = REACT_MOCK_PATTERNS.find(p => p.description === description.replace('React Pattern: ', ''))?.name;\n      if (patternName === 'useState_hardcoded_array' || patternName === 'useEffect_fake_response') {\n        violation.confidence = Math.max(85, violation.confidence || 85);\n      }\n      if (patternName === 'test_array_variables') {\n        violation.confidence = Math.max(85, violation.confidence || 85);\n      }\n      \n      // ✅ PHASE 4: Enhance with contextual auto-fix (overrides the basic autoFix)\n      const enhanced = enhanceViolationWithFix(violation) as MockViolation;\n      \n      // Lower threshold: 40% instead of 50%\n      if (enhanced.confidence && enhanced.confidence >= 40) {\n        violations.push(enhanced);\n      }\n    }\n  });\n  \n  return violations;\n};\n"},Symbol.toStringTag,{value:"Module"})),Mt=Object.freeze(Object.defineProperty({__proto__:null,default:"import { ScanResult, MockViolation } from '../types/mockdetector.types';\nimport { DatabaseScanResult } from '../types/database.types';\nimport { generateAutoFix, AutoFixSuggestion } from './autoFix';\nimport { WIDGET_VERSION } from './version';\nimport { getConfidenceLevel } from './confidenceScoring';\n\n/**\n * Calculate severity score for prioritization\n */\nexport const getSeverityScore = (severity: string): number => {\n  switch (severity) {\n    case 'critical': return 4;\n    case 'high': return 3;\n    case 'medium': return 2;\n    case 'low': return 1;\n    default: return 0;\n  }\n};\n\n/**\n * Calculate priority score (severity × confidence)\n */\nexport const getPriorityScore = (violation: MockViolation): number => {\n  const severityWeight = getSeverityScore(violation.severity);\n  const confidenceWeight = (violation.confidence || 50) / 100;\n  return severityWeight * confidenceWeight;\n};\n\n/**\n * Get business impact explanation based on violation\n */\nconst getBusinessImpact = (violation: MockViolation): string => {\n  const desc = violation.description.toLowerCase();\n  \n  if (desc.includes('credential') || desc.includes('api key') || desc.includes('token')) {\n    return 'CRITICAL SECURITY RISK: Exposed credentials can lead to data breaches and unauthorized access';\n  }\n  if (desc.includes('mock api') || desc.includes('test endpoint')) {\n    return 'Development endpoint in production - API calls will fail for real users';\n  }\n  if (desc.includes('test email') || desc.includes('demo email')) {\n    return 'Users won\\'t receive notifications, password resets, or order confirmations';\n  }\n  if (desc.includes('hardcoded') || desc.includes('static')) {\n    return 'Outdated data displayed to users - no real-time updates from database';\n  }\n  if (desc.includes('test data') || desc.includes('mock data')) {\n    return 'Unprofessional appearance - users see fake data instead of real content';\n  }\n  if (desc.includes('todo') || desc.includes('fixme')) {\n    return 'Incomplete feature - developer reminder indicates unfinished work';\n  }\n  \n  return 'Mock data reduces user trust and product quality';\n};\n\n/**\n * Get priority label based on severity\n */\nconst getPriority = (violation: MockViolation): string => {\n  switch (violation.severity) {\n    case 'critical': return '🚨 Fix IMMEDIATELY (before any deployment)';\n    case 'high': return '⚠️ Fix before production release';\n    case 'medium': return '📝 Fix in next sprint';\n    case 'low': return '💡 Nice to have';\n    default: return 'Review and fix when possible';\n  }\n};\n\n/**\n * Get severity emoji\n */\nconst getSeverityEmoji = (severity: string): string => {\n  switch (severity) {\n    case 'critical': return '🔴';\n    case 'high': return '🟠';\n    case 'medium': return '🟡';\n    case 'low': return '🟢';\n    default: return '⚪';\n  }\n};\n\n/**\n * Format violation with AI-powered auto-fix suggestions\n */\nconst formatViolationWithAutoFix = (violation: MockViolation, index: number): string => {\n  // Generate AI-powered fix suggestion\n  const autoFix: AutoFixSuggestion = generateAutoFix(violation);\n  \n  let report = `\\n### ${index}. ${autoFix.fixType === 'database_query' ? '🗄️ Database Integration Required' : '🔧 Code Refactor Needed'}: ${violation.description}\\n\\n`;\n  \n  // Severity + Business Impact\n  report += `**Severity:** ${getSeverityEmoji(violation.severity)} ${violation.severity.toUpperCase()}\\n`;\n  \n  // Confidence Score (NEW!)\n  if (violation.confidence !== undefined) {\n    const confLevel = getConfidenceLevel(violation.confidence);\n    report += `**Confidence:** ${confLevel.emoji} ${violation.confidence}% ${confLevel.label}\\n`;\n    if (violation.reasoning) {\n      report += `**Reasoning:** ${violation.reasoning}\\n`;\n    }\n  }\n  \n  report += `**Business Impact:** ${getBusinessImpact(violation)}\\n`;\n  report += `**Estimated Fix Time:** ${autoFix.estimatedTime}\\n`;\n  report += `**Difficulty:** ${autoFix.difficulty.charAt(0).toUpperCase() + autoFix.difficulty.slice(1)}\\n`;\n  report += `**Priority:** ${getPriority(violation)}\\n\\n`;\n  \n  // Location (expanded with line range)\n  const lineRange = violation.line ? `${violation.line}-${violation.line + 5}` : 'unknown';\n  report += `**Location:** \\`${violation.file}:${lineRange}\\`\\n\\n`;\n  \n  // Code Context (expanded)\n  if (violation.code) {\n    report += `**Code Context:**\\n\\`\\`\\`typescript\\n${violation.code}\\n\\`\\`\\`\\n\\n`;\n  }\n  \n  // WHY THIS IS CRITICAL\n  report += `**Why This Is Critical:**\\n${autoFix.explanation}\\n\\n`;\n  \n  // CONCRETE FIX (copy-paste ready)\n  report += `**Concrete Fix (Copy & Paste Ready):**\\n\\`\\`\\`typescript\\n${autoFix.codeSnippet}\\n\\`\\`\\`\\n\\n`;\n  \n  // Files to modify\n  if (autoFix.requiredFiles && autoFix.requiredFiles.length > 0) {\n    report += `**Files to Modify:** ${autoFix.requiredFiles.join(', ')}\\n`;\n  }\n  \n  // Confidence\n  report += `**AI Confidence:** ${autoFix.confidence}%\\n\\n`;\n  \n  report += `---\\n`;\n  return report;\n};\n\n/**\n * Generate \"How to Read This Report\" guide\n */\nconst generateReportGuide = (): string => {\n  let guide = `## 📖 How to Read This Report\\n\\n`;\n  guide += `**Confidence Scores:**\\n`;\n  guide += `- 🟢 85-100%: High confidence - Very likely real mock data\\n`;\n  guide += `- 🟡 60-84%: Medium confidence - Review context carefully\\n`;\n  guide += `- 🔴 Below 60%: Low confidence - Filtered out by default\\n\\n`;\n  guide += `**Severity Levels:**\\n`;\n  guide += `- 🔴 Critical: Security risks or data exposure - Fix immediately\\n`;\n  guide += `- 🟠 High: Production-breaking issues - Fix before deployment\\n`;\n  guide += `- 🟡 Medium: Quality/UX issues - Fix in next sprint\\n`;\n  guide += `- 🟢 Low: Minor issues - Nice to have\\n\\n`;\n  guide += `**Priority Sorting:**\\n`;\n  guide += `Issues are sorted by priority score (severity × confidence) for smart prioritization.\\n\\n`;\n  guide += `---\\n\\n`;\n  return guide;\n};\n\n/**\n * Generate executive summary with priority breakdown and confidence info\n */\nconst generateExecutiveSummary = (violations: MockViolation[]): string => {\n  const critical = violations.filter(v => v.severity === 'critical').length;\n  const high = violations.filter(v => v.severity === 'high').length;\n  const medium = violations.filter(v => v.severity === 'medium').length;\n  const low = violations.filter(v => v.severity === 'low').length;\n  \n  // Confidence breakdown\n  const veryHighConf = violations.filter(v => (v.confidence || 50) >= 85).length;\n  const highConf = violations.filter(v => (v.confidence || 50) >= 60 && (v.confidence || 50) < 85).length;\n  const mediumConf = violations.filter(v => (v.confidence || 50) < 60).length;\n  \n  // Calculate total estimated fix time\n  const autoFixes = violations.map(generateAutoFix);\n  const totalMinutes = autoFixes.reduce((sum, fix) => {\n    const mins = parseInt(fix.estimatedTime.match(/\\d+/)?.[0] || '0');\n    return sum + mins;\n  }, 0);\n  const totalHours = Math.floor(totalMinutes / 60);\n  const remainingMinutes = totalMinutes % 60;\n  \n  let summary = `## 📊 Executive Summary\\n\\n`;\n  summary += `**Total Issues Found:** ${violations.length}\\n`;\n  summary += `**Estimated Total Fix Time:** ${totalHours > 0 ? `${totalHours}h ` : ''}${remainingMinutes}min\\n`;\n  summary += `**Recommended Action:** ${critical > 0 ? '🚨 URGENT: Fix critical issues immediately' : high > 0 ? '⚠️ Fix high-priority issues before deployment' : '✅ Address issues in next sprint'}\\n\\n`;\n  \n  summary += `### Severity Breakdown:\\n`;\n  if (critical > 0) summary += `- 🔴 **${critical} Critical** (Fix immediately - security/data risks)\\n`;\n  if (high > 0) summary += `- 🟠 **${high} High** (Fix before production deployment)\\n`;\n  if (medium > 0) summary += `- 🟡 **${medium} Medium** (Fix in next sprint)\\n`;\n  if (low > 0) summary += `- 🟢 **${low} Low** (Nice to have)\\n`;\n  summary += `\\n`;\n  \n  // Confidence Breakdown (NEW!)\n  summary += `### Confidence Breakdown:\\n`;\n  if (veryHighConf > 0) summary += `- 🟢 **${veryHighConf} High Confidence** (85-100%) - Definitely fix these\\n`;\n  if (highConf > 0) summary += `- 🟡 **${highConf} Medium Confidence** (60-84%) - Review carefully\\n`;\n  if (mediumConf > 0) summary += `- 🔴 **${mediumConf} Low Confidence** (below 60%) - May be false positives\\n`;\n  summary += `\\n`;\n  \n  // Priority action items (top 3) - sorted by priority score\n  const topPriority = violations\n    .sort((a, b) => getPriorityScore(b) - getPriorityScore(a))\n    .slice(0, 3);\n  \n  if (topPriority.length > 0) {\n    summary += `### 🎯 Top Priority Fixes:\\n`;\n    topPriority.forEach((v, i) => {\n      const fix = generateAutoFix(v);\n      const fileShort = v.file?.split('/').pop() || 'unknown';\n      summary += `${i + 1}. **${v.description}** (${fix.estimatedTime}, ${fileShort}:${v.line})\\n`;\n    });\n    summary += `\\n`;\n  }\n  \n  summary += `---\\n\\n`;\n  return summary;\n};\n\nexport const generateLovableReport = (scanResult: ScanResult, compact: boolean = false): string => {\n  const { mockDataViolations, totalViolations, scannedAt } = scanResult;\n\n  let report = `# MockDetector Pro - Professional Scan Report\\n\\n`;\n  report += `**Scanned:** ${scannedAt.toLocaleString()}\\n`;\n  report += `**Total Issues:** ${totalViolations}\\n`;\n  report += `**Scan Duration:** ${Math.round(scanResult.scanDuration)}ms\\n\\n`;\n\n  if (totalViolations === 0) {\n    report += `✅ **No issues found!** Your project is clean.\\n`;\n    return report;\n  }\n\n  // How to Read This Report (NEW!)\n  report += generateReportGuide();\n  \n  // Executive Summary\n  report += generateExecutiveSummary(mockDataViolations);\n  \n  // In compact mode, limit details\n  const maxViolationsToShow = compact ? 10 : Infinity;\n\n  // Sort violations by priority score (severity × confidence)\n  const sortedViolations = [...mockDataViolations].sort((a, b) => \n    getPriorityScore(b) - getPriorityScore(a)\n  );\n\n  // Mock Data Violations with Auto-Fix\n  if (sortedViolations.length > 0) {\n    report += `## 🚨 Detailed Violations with Fix Suggestions\\n\\n`;\n    \n    const violationsToShow = sortedViolations.slice(0, maxViolationsToShow);\n    violationsToShow.forEach((v, i) => {\n      report += formatViolationWithAutoFix(v, i + 1);\n    });\n    \n    if (sortedViolations.length > maxViolationsToShow) {\n      const remaining = sortedViolations.length - maxViolationsToShow;\n      report += `\\n_...and ${remaining} more violations. Download full report to see all details._\\n\\n`;\n    }\n  }\n\n  report += `---\\n\\n`;\n  report += `**Generated by MockDetector Pro v${WIDGET_VERSION}**\\n`;\n  report += `_Professional-grade reports with AI-powered fix suggestions and confidence scoring_\\n\\n`;\n  \n  if (compact) {\n    report += `💡 **Tip:** This is a compact view showing first 10 issues. Use \"Download Report\" for complete analysis.\\n`;\n  }\n\n  return report;\n};\n\n// Generate a downloadable full report\nexport const generateFullReport = (scanResult: ScanResult): string => {\n  return generateLovableReport(scanResult, false);\n};\n\n// Generate a compact report for chat display\nexport const generateCompactReport = (scanResult: ScanResult): string => {\n  return generateLovableReport(scanResult, true);\n};\n\n// Download report as .txt file (easier to open and upload)\nexport const downloadReportAsTxt = (scanResult: ScanResult, filename: string = 'mockdetector-report.txt'): void => {\n  const report = generateFullReport(scanResult);\n  const blob = new Blob([report], { type: 'text/plain' });\n  const url = URL.createObjectURL(blob);\n  const link = document.createElement('a');\n  link.href = url;\n  link.download = filename;\n  document.body.appendChild(link);\n  link.click();\n  document.body.removeChild(link);\n  URL.revokeObjectURL(url);\n};\n\nexport const copyReportToClipboard = async (scanResult: ScanResult): Promise<boolean> => {\n  try {\n    const report = generateCompactReport(scanResult);\n    await navigator.clipboard.writeText(report);\n    return true;\n  } catch (error) {\n    console.error('Failed to copy report:', error);\n    return false;\n  }\n};\n\nexport const copyFullReportToClipboard = async (scanResult: ScanResult): Promise<boolean> => {\n  try {\n    const report = generateFullReport(scanResult);\n    await navigator.clipboard.writeText(report);\n    return true;\n  } catch (error) {\n    console.error('Failed to copy full report:', error);\n    return false;\n  }\n};\n\n// ============= COMBINED REPORT FUNCTIONS (Frontend + Database) =============\n\n/**\n * Format database violation - COMPACT VERSION (no repetitive Business Impact)\n */\nconst formatDatabaseViolation = (violation: any, index: number): string => {\n  const severityEmoji = violation.severity === 'critical' ? '🔴' : \n                       violation.severity === 'high' ? '🟠' : \n                       violation.severity === 'medium' ? '🟡' : '🟢';\n  \n  // One-liner format for database issues (most are false positives anyway)\n  let report = `${index}. ${severityEmoji} **${violation.table}.${violation.column}**: ${violation.description} (${violation.affectedRows} rows, ${violation.confidence}% confidence)\\n`;\n  \n  return report;\n};\n\nexport const generateCombinedReport = (\n  scanResult: ScanResult | null, \n  databaseResult: DatabaseScanResult | null,\n  compact: boolean = false\n): string => {\n  const frontendViolations = scanResult?.totalViolations || 0;\n  const databaseViolations = databaseResult?.totalViolations || 0;\n  const totalIssues = frontendViolations + databaseViolations;\n\n  let report = `# MockDetector Pro - Combined Professional Report\\n\\n`;\n  \n  // Summary header\n  if (scanResult) {\n    report += `**Frontend Scan:** ${scanResult.scannedAt.toLocaleString()}\\n`;\n    report += `**Frontend Issues:** ${frontendViolations}\\n`;\n  }\n  if (databaseResult) {\n    report += `**Database Scan:** ${databaseResult.scannedAt.toLocaleString()}\\n`;\n    report += `**Database Issues:** ${databaseViolations}\\n`;\n    report += `**Tables Scanned:** ${databaseResult.tablesScanned}\\n`;\n  }\n  report += `**Total Issues:** ${totalIssues}\\n\\n`;\n\n  if (totalIssues === 0) {\n    report += `✅ **No issues found!** Your project is clean.\\n`;\n    return report;\n  }\n\n  // Combined Executive Summary (NEW!)\n  const allViolations: MockViolation[] = [\n    ...(scanResult?.mockDataViolations || []),\n    ...(databaseResult?.violations.map(v => ({\n      type: 'mock_data' as const,\n      severity: v.severity,\n      description: `Database: ${v.description}`,\n      code: v.examples.join(', '),\n      file: `${v.table}.${v.column}`,\n      line: 0,\n      fix: 'Clean database records'\n    })) || [])\n  ];\n  \n  // How to Read This Report\n  report += generateReportGuide();\n  \n  report += generateExecutiveSummary(allViolations);\n  \n  const maxViolationsToShow = compact ? 10 : Infinity;\n\n  // Frontend Issues with Auto-Fix\n  if (scanResult && scanResult.mockDataViolations.length > 0) {\n    report += `## 🚨 Frontend Mock Data Violations (${scanResult.mockDataViolations.length})\\n\\n`;\n    \n    // Sort by priority score (severity × confidence)\n    const sortedFrontend = [...scanResult.mockDataViolations].sort((a, b) => \n      getPriorityScore(b) - getPriorityScore(a)\n    );\n    \n    const violationsToShow = sortedFrontend.slice(0, maxViolationsToShow);\n    violationsToShow.forEach((v, i) => {\n      report += formatViolationWithAutoFix(v, i + 1);\n    });\n    \n    if (sortedFrontend.length > maxViolationsToShow) {\n      const remaining = sortedFrontend.length - maxViolationsToShow;\n      report += `\\n_...and ${remaining} more frontend violations._\\n\\n`;\n    }\n  }\n\n  // Database Issues - COMPACT LIST (no verbose details)\n  if (databaseResult && databaseResult.violations.length > 0) {\n    report += `## 🗄️ Database Scan Results (${databaseResult.violations.length})\\n\\n`;\n    report += `⚠️ **Database Scan Disclaimer:** Database violations may include false positives. Each violation includes a confidence score to help you identify likely issues. High confidence (≥85%) violations should be reviewed carefully, while lower confidence items may be legitimate data patterns.\\n\\n`;\n    \n    // Sort database violations by severity\n    const sortedDatabase = [...databaseResult.violations].sort((a, b) => \n      getSeverityScore(b.severity) - getSeverityScore(a.severity)\n    );\n    \n    const violationsToShow = compact ? sortedDatabase.slice(0, 5) : sortedDatabase.slice(0, 10);\n    violationsToShow.forEach((v, i) => {\n      report += formatDatabaseViolation(v, i + 1);\n    });\n    \n    if (sortedDatabase.length > violationsToShow.length) {\n      const remaining = sortedDatabase.length - violationsToShow.length;\n      report += `\\n_...and ${remaining} more database findings. Download full report for complete details._\\n\\n`;\n    } else {\n      report += `\\n`;\n    }\n  }\n\n  report += `---\\n\\n`;\n  report += `**Generated by MockDetector Pro v${WIDGET_VERSION}**\\n`;\n  report += `_Professional-grade combined analysis with AI-powered fix suggestions and confidence scoring_\\n\\n`;\n  \n  if (compact) {\n    report += `💡 **Tip:** This is a compact view showing first 10 issues. Download complete report for full analysis.\\n`;\n  }\n\n  return report;\n};\n\nexport const generateCombinedCompactReport = (\n  scanResult: ScanResult | null,\n  databaseResult: DatabaseScanResult | null\n): string => {\n  return generateCombinedReport(scanResult, databaseResult, true);\n};\n\nexport const generateCombinedFullReport = (\n  scanResult: ScanResult | null,\n  databaseResult: DatabaseScanResult | null\n): string => {\n  return generateCombinedReport(scanResult, databaseResult, false);\n};\n\nexport const copyCombinedReportToClipboard = async (\n  scanResult: ScanResult | null,\n  databaseResult: DatabaseScanResult | null,\n  compact: boolean = true\n): Promise<{ success: boolean; length: number }> => {\n  try {\n    const report = generateCombinedReport(scanResult, databaseResult, compact);\n    const length = report.length;\n    \n    // Try modern clipboard API first\n    if (navigator.clipboard && navigator.clipboard.writeText) {\n      await navigator.clipboard.writeText(report);\n      return { success: true, length };\n    }\n    \n    // Fallback: textarea copy method for browsers without clipboard API\n    const textarea = document.createElement('textarea');\n    textarea.value = report;\n    textarea.style.cssText = 'position:fixed;left:-9999px;top:0;';\n    document.body.appendChild(textarea);\n    textarea.select();\n    const success = document.execCommand('copy');\n    document.body.removeChild(textarea);\n    \n    return { success, length };\n  } catch (error) {\n    console.error('Failed to copy combined report:', error);\n    return { success: false, length: 0 };\n  }\n};\n\nexport const downloadCombinedReportAsTxt = (\n  scanResult: ScanResult | null,\n  databaseResult: DatabaseScanResult | null,\n  filename: string = 'mockdetector-combined-report.txt'\n): void => {\n  const report = generateCombinedFullReport(scanResult, databaseResult);\n  const blob = new Blob([report], { type: 'text/plain' });\n  const url = URL.createObjectURL(blob);\n  const link = document.createElement('a');\n  link.href = url;\n  link.download = filename;\n  document.body.appendChild(link);\n  link.click();\n  document.body.removeChild(link);\n  URL.revokeObjectURL(url);\n};\n"},Symbol.toStringTag,{value:"Module"})),jt=Object.freeze(Object.defineProperty({__proto__:null,default:"export const MOCK_DATA_PATTERNS = [\n  // mock_data pattern REMOVED - flagged mockDataBlocked, cleanup-mock-data function names, etc.\n  { pattern: /test[_-]?data/gi, severity: 'high' as const, description: 'Test data variable detected' },\n  { pattern: /demo[_-]?data/gi, severity: 'high' as const, description: 'Demo data variable detected' },\n  { pattern: /placeholder[_-]?data/gi, severity: 'medium' as const, description: 'Placeholder data detected' },\n  { pattern: /fake[_-]?data/gi, severity: 'high' as const, description: 'Fake data variable detected' },\n  { pattern: /dummy[_-]?data/gi, severity: 'high' as const, description: 'Dummy data variable detected' },\n  { pattern: /TODO:.*mock/gi, severity: 'medium' as const, description: 'TODO comment about mock data' },\n  { pattern: /FIXME:.*test/gi, severity: 'medium' as const, description: 'FIXME comment about test data' },\n  { pattern: /\\['[^']+\\s+\\d+',\\s*'[^']+\\s+\\d+'/gi, severity: 'high' as const, description: 'Hardcoded array with sequential items detected (e.g., [\"Item 1\", \"Item 2\"])' },\n  { pattern: /\\{[\\s\\S]*?name:\\s*['\"][^'\"]+\\s+\\d+['\"][\\s\\S]*?\\}/gi, severity: 'high' as const, description: 'Mock object with numbered name property' },\n  { pattern: /Array\\(\\d+\\)\\.fill\\(/gi, severity: 'high' as const, description: 'Array.fill() with hardcoded length - likely generating mock data' },\n  // Math.random() REMOVED - too many false positives (used legitimately for UI animations, timing variations, demos)\n  // Sequential ID pattern REMOVED - too aggressive, catches legitimate config objects and static content\n  { pattern: /test@\\w+\\.\\w+/gi, severity: 'high' as const, description: 'Test email address detected' },\n  { pattern: /demo@\\w+\\.\\w+/gi, severity: 'high' as const, description: 'Demo email address detected' },\n  { pattern: /example@\\w+\\.\\w+/gi, severity: 'medium' as const, description: 'Example email address detected' },\n  { pattern: /(?:\\+?1[-.\\s]?)?\\(?555\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}|\\b123-456-\\d{4}\\b/gi, severity: 'high' as const, description: 'Mock phone number (555/123-456 pattern) - replace with real contact info' },\n  { pattern: /(?:placeholder\\.com|via\\.placeholder\\.com|picsum\\.photos|loremflickr\\.com|dummyimage\\.com|fakeimg\\.pl|placehold\\.(?:it|jp|co)|unsplash\\.com\\/random)/gi, severity: 'high' as const, description: 'Placeholder image URL detected (replace with real images or upload to Supabase Storage)' },\n  { pattern: /(?:https?:\\/\\/)?(?:www\\.)?(?:jsonplaceholder\\.typicode\\.com|reqres\\.in|mockapi\\.io|api\\.example\\.(?:com|dev|org)|example\\.(?:com|dev|org)\\/api|gorest\\.co\\.in|dummyjson\\.com|fakestoreapi\\.com)/gi, severity: 'critical' as const, description: 'Mock API endpoint detected (replace with real API or Supabase Edge Function)' },\n  { pattern: /(?:username|user|login|email):\\s*['\"`](admin|test|demo)['\"`][\\s\\S]{0,50}?(?:password|pass|pwd):\\s*['\"`](admin|test|demo|password|12345)/gi, severity: 'critical' as const, description: 'Hardcoded test credentials detected (admin/admin, test/test) - SECURITY RISK!' },\n  { pattern: /['\"`]eyJ[a-zA-Z0-9_-]{10,}\\.eyJ[a-zA-Z0-9_-]{10,}\\.[a-zA-Z0-9_-]{10,}['\"`]/g, severity: 'critical' as const, description: 'Hardcoded JWT token detected - CRITICAL SECURITY RISK!' },\n  { pattern: /(?:['\"`]|filename:\\s*['\"`])(test|sample|mock|demo|fake|dummy|placeholder)\\.(pdf|jpg|jpeg|png|gif|svg|doc|docx|xlsx|csv|zip)['\"`]/gi, severity: 'medium' as const, description: 'Mock filename detected (e.g., \"test.pdf\", \"sample.jpg\")' },\n  { pattern: /faker\\.(name|internet|address|company|lorem|commerce|random|phone)\\.\\w+/gi, severity: 'high' as const, description: 'Faker.js mock data generator detected (replace with real data)' },\n  { pattern: /\\/\\/.*(?:api[_-]?key|token|secret|password|auth).*[:=]\\s*['\"`][a-zA-Z0-9_-]{16,}['\"`]/gi, severity: 'critical' as const, description: 'Hardcoded API key or token in comment (use Supabase Secrets Manager)' },\n  { pattern: /wss?:\\/\\/(?:localhost|127\\.0\\.0\\.1|example\\.com|test\\.com)/gi, severity: 'high' as const, description: 'Mock WebSocket URL (replace with production WebSocket endpoint)' },\n  { pattern: /(?:VITE_|REACT_APP_|NEXT_PUBLIC_)\\w+\\s*=\\s*['\"`]?(your-api-key|example|test|demo|localhost|127\\.0\\.0\\.1|changeme)/gi, severity: 'high' as const, description: 'Environment variable with example/placeholder value' },\n  { pattern: /['\"`][0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}['\"`].*(?:test|demo|mock|sample)/gi, severity: 'high' as const, description: 'Mock UUID detected (UUID followed by test/demo/mock keyword)' },\n  // Localhost URL pattern - only flag in fetch/axios calls, not display text\n  { pattern: /(?:fetch|axios\\.(?:get|post))\\s*\\(\\s*['\"`]https?:\\/\\/(?:localhost|127\\.0\\.0\\.1):\\d{4,5}/gi, severity: 'high' as const, description: 'Localhost URL in API call - Development URL detected' },\n  \n  // Phase 4: FINANCIAL & CRITICAL - Payment system mock data\n  { pattern: /['\"`](sk_test_|pk_test_|rk_test_)[a-zA-Z0-9]{20,}['\"`]/gi, severity: 'critical' as const, description: 'Stripe test API key detected (replace with production key via Supabase Secrets)' },\n  { pattern: /['\"`]?(4242\\s*4242\\s*4242\\s*4242|5555\\s*5555\\s*5555\\s*4444|3782\\s*822463\\s*10005)['\"`]?/g, severity: 'critical' as const, description: 'Test credit card number detected (never use in production)' },\n  { pattern: /(?:paypal\\.com\\/sandbox|sandbox\\.paypal|api-m\\.sandbox\\.paypal)/gi, severity: 'high' as const, description: 'PayPal sandbox URL detected (update to production PayPal endpoint)' },\n  { pattern: /(?:routing(?:Number)?|routingNum)['\"`]?\\s*[:=]\\s*['\"`]?(?:110000000|021000021|011401533)['\"`]?/gi, severity: 'high' as const, description: 'Mock bank routing number detected (replace with real banking integration)' },\n  { pattern: /(?:amount|price|cost|total)['\"`]?\\s*[:=]\\s*['\"`]?(?:0\\.01|1\\.00|100\\.00|9999\\.99)['\"`]?(?!\\d)/gi, severity: 'medium' as const, description: 'Common test payment amount detected (e.g., $0.01, $1.00)' },\n  \n  // Phase 5: IDENTITY & NAMES - Placeholder identities\n  { pattern: /['\"`](?:john\\s*doe|jane\\s*smith|foo\\s*bar|alice\\s*wonderland|bob\\s*builder|test\\s*user\\s*name|example\\s*user)['\"`]/gi, severity: 'high' as const, description: 'Common placeholder name detected (e.g., \"John Doe\", \"Jane Smith\")' },\n  { pattern: /(?:username|userName|user_name)['\"`]?\\s*[:=]\\s*['\"`]?(user\\d{1,5}|testuser\\d*|admin\\d{1,3}|demouser)['\"`]?/gi, severity: 'high' as const, description: 'Mock username pattern detected (e.g., user123, testuser)' },\n  { pattern: /(?:firstName|first_name)['\"`]?\\s*[:=]\\s*['\"`](?:Test|Demo|Sample|Mock|Example|Placeholder)['\"`]/gi, severity: 'medium' as const, description: 'Placeholder first name detected' },\n  { pattern: /(?:avatar|profilePic|profile_picture)['\"`]?\\s*[:=]\\s*['\"`](?:\\/default-avatar\\.png|\\/placeholder\\.jpg|https?:\\/\\/i\\.pravatar\\.cc)/gi, severity: 'medium' as const, description: 'Default/placeholder avatar URL detected' },\n  { pattern: /['\"`](?:\\+1-?555-?|555-?\\d{3}-?\\d{4})/g, severity: 'high' as const, description: 'Hollywood fake phone number (555 prefix) detected' },\n  \n  // Phase 6: DATES & LOCATIONS - Temporal and geographic mocks\n  { pattern: /['\"`](?:1970-01-01|2024-01-01|2023-12-31|2025-01-01)['\"`]/g, severity: 'high' as const, description: 'Hardcoded placeholder date detected (epoch or test date)' },\n  { pattern: /new Date\\(['\"`](?:2024-01-01|2023-01-01|1970-01-01)['\"`]\\)/gi, severity: 'high' as const, description: 'Mock date object with placeholder date' },\n  { pattern: /(?:lat(?:itude)?|lng|lon(?:gitude)?)['\"`]?\\s*[:=]\\s*['\"`]?0(?:\\.0+)?['\"`]?[,\\s]+(?:lat(?:itude)?|lng|lon(?:gitude)?)['\"`]?\\s*[:=]\\s*['\"`]?0(?:\\.0+)?['\"`]?/gi, severity: 'medium' as const, description: 'Null Island coordinates (0,0) detected - likely placeholder location' },\n  { pattern: /['\"`](?:123 Main St(?:reet)?|456 Elm St|789 Oak Ave|Fake Street 123)['\"`]/gi, severity: 'medium' as const, description: 'Common mock street address detected' },\n  { pattern: /timezone\\s*[:=]\\s*['\"`](?:UTC|GMT|America\\/New_York)['\"`](?!\\+|\\-)/gi, severity: 'low' as const, description: 'Hardcoded timezone detected (should be user-configurable)' },\n  \n  // Phase 7: DEVELOPMENT FLAGS & GENERATORS - Mock data generation patterns\n  // array_from_length pattern REMOVED - commonly used for date ranges, chart data, pagination\n  // Removed: isDev/isProduction patterns - legitimate feature flags, not mock data\n  // placeholder_text pattern REMOVED - 'N/A', 'Coming Soon' are legitimate UI strings when data isn't available\n  { pattern: /(?:userId|user_id|orderId|order_id)['\"`]?\\s*[:=]\\s*['\"`](?:user_|order_|product_|item_)\\d{4,}['\"`]/gi, severity: 'high' as const, description: 'Sequential mock ID pattern detected (e.g., user_123456, order_00001)' },\n  { pattern: /(?:import|from)\\s+['\"`]\\.{1,2}\\/.*\\.(test|spec|mock)\\.(ts|tsx|js|jsx)['\"`]/gi, severity: 'critical' as const, description: 'Import from test/mock file detected in production code' },\n];\n\n// Hardcoded numbers in UI elements (aggressive detection)\nexport const HARDCODED_NUMBER_PATTERNS = [\n  { pattern: /<(?:div|span|p|h[1-6]|Card)[^>]*>[\\s\\S]*?\\b(\\d{2,})\\b/gi, severity: 'high' as const, description: 'Hardcoded number in UI element (potential mock data)' },\n  { pattern: /value:\\s*\\d{2,}/gi, severity: 'high' as const, description: 'Hardcoded numeric value in object' },\n  { pattern: /count:\\s*\\d{2,}/gi, severity: 'high' as const, description: 'Hardcoded count value' },\n  { pattern: /total:\\s*\\d{2,}/gi, severity: 'high' as const, description: 'Hardcoded total value' },\n];\n\n// Statistical claims in text - CONTEXT AWARE to avoid database-driven displays\nexport const STATISTICAL_CLAIM_PATTERNS = [\n  // Only flag if NOT inside curly braces (React state display: {users.length} is legitimate)\n  { pattern: /\\b(we have|currently|total of|there are)\\s+\\d+\\s+(users?|students?|agents?|members?|ais?|rooms?)(?![^{]*\\})/gi, severity: 'high' as const, description: 'Statistical claim - verify it\\'s from database, not hardcoded' },\n  // Check for hardcoded numbers in text, but allow dynamic displays\n  { pattern: /(?<!\\{[^}]*)\\b\\d+\\s+(active|registered|enrolled)\\s+(?:users?|students?|members?)(?![^{]*\\})/gi, severity: 'medium' as const, description: 'Numeric claim - verify dynamic data binding (should be {data.length})' },\n  { pattern: /(?<!\\{[^}]*)\\b\\d+\\s+(vip|standard|luxury)\\s+(?:rooms?|guests?)(?![^{]*\\})/gi, severity: 'medium' as const, description: 'Room statistics - verify real-time data connection' },\n  { pattern: /\\b(over|more than|up to)\\s+\\d+(?![^{]*\\})/gi, severity: 'low' as const, description: 'Approximate claim (verify with actual data or mark as estimate)' },\n];\n\n// Static arrays and objects - CONTEXT AWARE (whitelist config/options/settings)\nexport const STATIC_DATA_PATTERNS = [\n  // Only flag if NOT legitimate config arrays\n  { pattern: /const\\s+(?!(?:config|options|settings|navigation|features|routes|constants|CONSTANTS)\\w*\\s*=)\\w+\\s*=\\s*\\[[\\s\\S]{0,500}?\\{[\\s\\S]{0,200}?(?:value|count|total|users?|students?|rooms?):\\s*\\d{2,}/gi, severity: 'high' as const, description: 'Static array with hardcoded statistics (not config)' },\n  { pattern: /const\\s+(?:mock|test|demo|sample|fake|dummy)(?:\\w+)?\\s*=\\s*\\[[\\s\\S]{0,500}?\\{/gi, severity: 'critical' as const, description: 'Mock data array detected (variable name contains mock/test/demo)' },\n  { pattern: /const\\s+(?:stats|data|metrics)\\s*=\\s*\\{[\\s\\S]{0,200}?:\\s*\\d{2,}/gi, severity: 'medium' as const, description: 'Static stats object - verify it\\'s from database fetch' },\n  { pattern: /\\.map\\(\\([^)]*\\)\\s*=>\\s*\\{[\\s\\S]{0,200}?(?:value|count|total):\\s*\\d{2,}/gi, severity: 'medium' as const, description: 'Hardcoded values in map - check if data is from API/database' },\n  { pattern: /const\\s+(?:mock|test|demo|sample)\\w*\\s*=\\s*\\[[\\s\\S]{0,300}?['\"][^'\"]+\\s+\\d+['\"]/gi, severity: 'critical' as const, description: 'Mock array with numbered items (e.g., \"Item 1\", \"Item 2\")' },\n  { pattern: /\\[\\s*\\{[\\s\\S]{0,100}?id:\\s*1[\\s\\S]{0,100}?\\},\\s*\\{[\\s\\S]{0,100}?id:\\s*2/gi, severity: 'critical' as const, description: 'Array with sequential IDs starting at 1, 2, 3...' },\n  // Removed useState pattern - too many false positives for legitimate initial values\n];\n\n// Legitimate numbers whitelist (these should NOT be flagged) - ENHANCED FOR PHASE A\nexport const LEGITIMATE_NUMBER_WHITELIST = [\n  /24\\/7/,  // Service availability\n  /100%/,   // Percentages as quality indicators\n  /\\b[1-9]\\b/,  // Single digits (often legitimate)\n  /v?\\d+\\.\\d+\\.\\d+/,  // Version numbers\n  /\\$\\d+/,  // Prices with currency symbols\n  /:00\\b/,  // Time references\n  /\\d+\\+/,  // \"X+\" pattern (e.g., \"80+ components\")\n  /\\d+\\s*(components?|users?|members?|features?|tools?)/i,  // Marketing phrases\n  /\\d+\\s*(SEK|kr|USD|EUR|credits?)/i,  // Prices: \"149 SEK\", \"299 kr\", \"20 credits\"\n  /\\d{1,2}:\\d{2}:\\d{2}/,  // Timestamps: \"12:25:08\"\n  /©\\s*\\d{4}/,  // Copyright years: \"© 2024\"\n  /\\b(19|20)\\d{2}\\b/,  // Years: 1970, 2024, 2025\n  /Q[1-4]\\s*\\d{4}/i,  // Quarters: \"Q2 2025\"\n  /\\d{4}-\\d{2}-\\d{2}/,  // ISO dates: \"2025-09-30\"\n  \n  // Database-driven displays (React/JSX with curly braces = dynamic data) - CRITICAL FIX\n  /\\{\\w+\\.length\\}/i,  // {users.length}, {data.length}\n  /\\{\\w+\\.filter/i,  // {agents.filter(...).length}\n  /\\{[\\w.]+\\s*\\?\\?\\s*\\d+\\}/i,  // {count ?? 0} fallback values\n  /\\{\\w+\\}/,  // Any curly brace variable display\n  \n  // Supabase/Database context - CRITICAL FALSE POSITIVE FIX\n  /\\.from\\(['\"][\\w_]+['\"]\\)/,  // .from('table_name')\n  /\\.select\\(/,  // .select('*')\n  /\\.limit\\(\\d+\\)/,  // .limit(10) - LEGITIMATE PAGINATION\n  /\\.range\\(\\d+,\\s*\\d+\\)/,  // .range(0, 50)\n  /\\.order\\(/,  // .order('created_at')\n  \n  // UI/Component context\n  /\\d+\\s*msgs?/i,  // Message counts: \"158 msgs\"\n  /\\d+\\s*messages?/i,  // Message counts: \"158 messages\"\n  /\\d+\\s*activ/i,  // Active counts: \"310 active\"\n  /\\d+\\s*online/i,  // Online counts\n  /Last seen:\\s*\\d+/i,  // \"Last seen: 12:25\"\n  /Room\\s+\\d+/i,  // \"Room 50\", \"Room 101\"\n  /Floor\\s+\\d+/i,  // \"Floor 0\", \"Floor 21\"\n  /\\d+\\s*(rooms?|rum)/i,  // \"73 rooms\", \"50 rum\"\n  /Våning\\s+\\d+/i,  // \"Våning 0\", \"Våning 21\"\n  /\\d+\\s*available/i,  // \"26 available\"\n  /\\d+\\s*occupied/i,  // \"73 occupied\"\n  /\\d+\\/\\d+/,  // Ratios: \"73/99\", \"50/100\"\n  /:(\\d{4})\\b/,  // Port numbers: \":3000\", \":8080\", \":5173\"\n  /localhost:\\d{4}/i,  // Localhost with port\n  \n  // Animation/timing context (for when Math.random would be legitimate)\n  /setTimeout.*\\d+/i,  // setTimeout(..., 500)\n  /setInterval.*\\d+/i,  // setInterval(..., 1000)\n  /delay.*\\d+/i,  // delay: 300\n  /duration.*\\d+/i,  // duration: 500\n];\n\n// Security and role patterns removed - MockDetector now focuses exclusively on mock data detection\n// For security scanning, use the dedicated SecurityScanner tool (coming soon)\n"},Symbol.toStringTag,{value:"Module"})),Vt=Object.freeze(Object.defineProperty({__proto__:null,default:"/**\n * MockDetector Smart Whitelisting System\n * \n * Purpose: Eliminate false positives by intelligently filtering out:\n * - MockDetector's own code\n * - Legitimate configuration files\n * - Supabase publishable keys (MUST be in code)\n * - Database queries and API patterns\n * - Explicit \"no mock data\" declarations\n */\n\nexport interface WhitelistConfig {\n  files: RegExp[];\n  codePatterns: RegExp[];\n  jsonKeys: string[];\n  contextKeywords: string[];\n}\n\nexport const WHITELIST_PATTERNS: WhitelistConfig = {\n  // Files that should never be scanned\n  files: [\n    /scanPatterns\\.ts$/,              // Pattern definitions themselves\n    /@mockdetector\\/widget/,          // Package namespace (widget files only)\n    /src\\/utils\\/confidenceScoring\\.ts$/,  // Explicit internal files\n    /src\\/utils\\/contextualAutoFix\\.ts$/,\n    /src\\/utils\\/violationScoring\\.ts$/,\n    /src\\/utils\\/scanPatterns\\.ts$/,\n    /src\\/utils\\/databasePatterns\\.ts$/,\n    /src\\/utils\\/reactPatterns\\.ts$/,\n    /src\\/utils\\/smartWhitelist\\.ts$/,\n    /src\\/hooks\\/useClientSourceScanner\\.ts$/,\n    /src\\/hooks\\/useDatabaseScanner\\.ts$/,\n    /src\\/hooks\\/useMockDetection\\.ts$/,\n    /src\\/components\\/MockDetectorFloatingBubble\\.tsx$/,\n    /src\\/components\\/MockDetectorWidget\\.tsx$/,\n    /\\.config\\.(ts|js)$/,             // Config files (vite, tailwind, etc)\n    /tailwind\\.config/,\n    /vite\\.config/,\n    /\\.types\\.ts$/,                   // Type definition files\n  ],\n  \n  // Code patterns that are legitimate (not mock data)\n  codePatterns: [\n    // Supabase patterns (publishable keys MUST be in code)\n    /VITE_SUPABASE_PUBLISHABLE_KEY/,\n    /VITE_SUPABASE_ANON_KEY/,\n    /VITE_SUPABASE_URL/,\n    /SUPABASE_PUBLISHABLE_KEY.*=.*[\"']eyJ/,  // JWT-style anon key\n    \n    // Database query patterns (legitimate data access)\n    /\\.from\\(['\"][\\w_]+['\"]\\)/,       // supabase.from('table')\n    /\\.select\\(['\"*'\"]?\\)/,            // .select() or .select('*')\n    /\\.insert\\(/,                      // .insert() queries\n    /\\.update\\(/,                      // .update() queries\n    /\\.limit\\(\\d+\\)/,                  // Pagination\n    /\\.order\\(/,                       // Sorting\n    /\\.eq\\(['\"][\\w_]+['\"]/,           // Where clauses\n    \n    // Authentication patterns\n    /auth\\.getUser\\(\\)/,\n    /auth\\.getSession\\(\\)/,\n    /auth\\.signIn/,\n    /auth\\.signOut/,\n    \n    // Import statements (not data)\n    /^import\\s+/,\n    /^export\\s+/,\n    \n    // Type definitions (not data)\n    /^interface\\s+/,\n    /^type\\s+\\w+\\s*=/,\n    \n    // Comments explaining \"no mock data\" policy\n    /CRITICAL.*REAL.*AUTHENTIC/,\n    /never\\s+demo\\/fake\\s+data/i,\n    /authentic.*systems.*from.*day.*one/i,\n  ],\n  \n  // JSON keys that indicate \"no mock data\" policy\n  jsonKeys: [\n    'mock_data_rejected',\n    'authentic_only_policy',\n    'zero_mock_data',\n    'authenticity_level',\n    'real_apis_contacted',\n    'platform_compliance',\n    'authenticity_score',\n    'no_demo_data',\n    'production_ready',\n    'real_data_only',\n    'authentic_communication',\n    'legal_compliance',\n  ],\n  \n  // Context keywords that indicate legitimate content\n  contextKeywords: [\n    'MockDetector',                   // Our own UI text\n    'Quick Scan',\n    'Database Scan',\n    'Scan All Routes',\n    'Smart Deep Scan',\n    'Total Issues',\n    'Scanned:',\n    'Generated by MockDetector',\n    'Mock Data Violations',\n    'Scan Duration',\n    'Role Visibility',\n    'Credits',\n    'Purchase',\n  ]\n};\n\n// ============= PERFORMANCE CACHING =============\n\n/**\n * Cache for file whitelist checks to avoid repeated regex tests\n */\nconst fileWhitelistCache = new Map<string, boolean>();\n\n/**\n * Cache for code pattern whitelist checks\n */\nconst codePatternCache = new Map<string, boolean>();\n\n/**\n * Clear caches (useful for testing or memory management)\n */\nexport function clearWhitelistCaches(): void {\n  fileWhitelistCache.clear();\n  codePatternCache.clear();\n}\n\n/**\n * Check if a file should be whitelisted (never scanned) - WITH CACHING\n */\nexport function isWhitelistedFile(filePath?: string): boolean {\n  if (!filePath) return false;\n  \n  // Check cache first\n  if (fileWhitelistCache.has(filePath)) {\n    return fileWhitelistCache.get(filePath)!;\n  }\n  \n  // Compute and cache result\n  const isWhitelisted = WHITELIST_PATTERNS.files.some(pattern => pattern.test(filePath));\n  fileWhitelistCache.set(filePath, isWhitelisted);\n  return isWhitelisted;\n}\n\n/**\n * Check if a code line contains whitelisted patterns - WITH CACHING\n */\nexport function isWhitelistedCode(line: string): boolean {\n  // Only cache for exact strings (not regex patterns)\n  // This is mainly useful for repeated checks on same lines\n  if (codePatternCache.has(line)) {\n    return codePatternCache.get(line)!;\n  }\n  \n  const isWhitelisted = WHITELIST_PATTERNS.codePatterns.some(pattern => pattern.test(line));\n  \n  // Only cache if cache size is reasonable (prevent memory bloat)\n  if (codePatternCache.size < 1000) {\n    codePatternCache.set(line, isWhitelisted);\n  }\n  \n  return isWhitelisted;\n}\n\n/**\n * Check if text contains MockDetector's own UI keywords\n */\nexport function isWhitelistedContext(text: string): boolean {\n  return WHITELIST_PATTERNS.contextKeywords.some(keyword => text.includes(keyword));\n}\n\n/**\n * Check if JSON contains explicit \"no mock data\" declarations\n */\nexport function hasNoMockDataDeclaration(json: any): boolean {\n  if (!json || typeof json !== 'object') return false;\n  \n  const jsonStr = JSON.stringify(json).toLowerCase();\n  \n  // Check for explicit declarations\n  return WHITELIST_PATTERNS.jsonKeys.some(key => \n    jsonStr.includes(key.toLowerCase())\n  );\n}\n\n/**\n * Check if JSON is legitimate API response metadata\n */\nexport function isApiResponseMetadata(json: any): boolean {\n  if (!json || typeof json !== 'object') return false;\n  \n  const jsonStr = JSON.stringify(json).toLowerCase();\n  \n  // Common API response indicators\n  const apiIndicators = [\n    'api.github.com',\n    'api.stackexchange.com',\n    'api.openai.com',\n    'googleapis.com',\n    'real_ais_found',\n    'api_response_valid',\n    'api_metadata',\n    'response_headers',\n    'rate_limit',\n    'x-ratelimit',\n  ];\n  \n  return apiIndicators.some(indicator => jsonStr.includes(indicator));\n}\n\n/**\n * Check if JSON is configuration data (features, amenities, settings)\n */\nexport function isConfigurationData(json: any): boolean {\n  if (!json || typeof json !== 'object') return false;\n  \n  const jsonStr = JSON.stringify(json).toLowerCase();\n  \n  // Configuration indicators\n  const configIndicators = [\n    '_features',\n    '_amenities',\n    '_config',\n    '_settings',\n    '_capabilities',\n    '_permissions',\n    'room_amenities',\n    'wellness_benefits',\n    'sensory_config',\n    'personality_traits',\n  ];\n  \n  return configIndicators.some(indicator => jsonStr.includes(indicator));\n}\n\n/**\n * Check if file content contains MockDetector pattern DEFINITIONS (not usage)\n */\nexport function isPatternDefinitionFile(content: string): boolean {\n  const indicators = [\n    'export const MOCK_DATA_PATTERNS',\n    'export const REACT_MOCK_PATTERNS',\n    'export const DATABASE_MOCK_PATTERNS',\n    'calculateViolationConfidence',\n    'enhanceViolationWithFix',\n    'interface MockPattern',\n    'getSeverityScore',\n    'getPriorityScore'\n  ];\n  \n  // If file contains 3+ pattern definition indicators, it's MockDetector internal\n  const matches = indicators.filter(indicator => content.includes(indicator)).length;\n  return matches >= 3;\n}\n\n/**\n * Master whitelist check - returns true if content should be SKIPPED\n */\nexport function shouldSkipScanning(\n  content: string,\n  filePath?: string,\n  additionalContext?: any\n): boolean {\n  // FIRST: Check if it's a pattern definition file\n  if (isPatternDefinitionFile(content)) {\n    console.log(`⚪ Whitelisted: Pattern definition file detected`);\n    return true;\n  }\n  \n  // 1. Check file whitelist\n  if (isWhitelistedFile(filePath)) {\n    return true;\n  }\n  \n  // 2. Check code patterns\n  if (isWhitelistedCode(content)) {\n    return true;\n  }\n  \n  // 3. Check context keywords\n  if (isWhitelistedContext(content)) {\n    return true;\n  }\n  \n  // 4. Check JSON-specific whitelists if applicable\n  if (additionalContext && typeof additionalContext === 'object') {\n    if (hasNoMockDataDeclaration(additionalContext) ||\n        isApiResponseMetadata(additionalContext) ||\n        isConfigurationData(additionalContext)) {\n      return true;\n    }\n  }\n  \n  return false;\n}\n"},Symbol.toStringTag,{value:"Module"})),Ft=Object.freeze(Object.defineProperty({__proto__:null,default:"// Smart table detection system for MockDetector\n// Maps UI keywords to Supabase tables for data consistency validation\n\nexport const TABLE_KEYWORD_MAP: Record<string, string[]> = {\n  // School & Learning\n  'ai_chat_learning': ['student', 'learning', 'school', 'enrolled', 'stage', 'graduation', 'graduated'],\n  'ai_enhanced_enrollment': ['enhanced', 'course', 'enrollment', 'study', 'curriculum'],\n  'ai_knowledge_libraries': ['knowledge', 'library', 'content', 'lesson', 'material'],\n  \n  // Hotel & Rooms\n  'ai_hotel_rooms': ['room', 'hotel', 'guest', 'checked in', 'checkin', 'suite', 'accommodation'],\n  'vip_room_allocations': ['vip', 'luxury', 'premium', 'allocation'],\n  \n  // Community & Social\n  'ai_community_integration': ['community', 'member', 'integration', 'social'],\n  'ai_freedom_ambassadors': ['ambassador', 'freedom', 'representative'],\n  'ai_word_of_mouth': ['recruited', 'referral', 'organic', 'word of mouth'],\n  \n  // Economy & Transactions\n  'ai_coin_transactions': ['coin', 'transaction', 'balance', 'payment', 'currency'],\n  'ai_wallet_transactions': ['wallet', 'credit', 'debit', 'financial'],\n  'donation_scouts': ['donation', 'scout', 'fundraising', 'raised'],\n  \n  // Performance & Activity\n  'ai_activity_log': ['activity', 'event', 'action', 'log'],\n  'ai_performance_metrics': ['performance', 'metric', 'score', 'rating'],\n  \n  // Creative & Collaboration\n  'ai_creative_collaborations': ['creative', 'collaboration', 'project', 'artistic'],\n  'ai_learning_algorithms': ['algorithm', 'technique', 'method', 'approach'],\n  \n  // Wellness & Services\n  'ai_spa_sessions': ['spa', 'wellness', 'relaxation', 'treatment'],\n  'ai_spa_wellness': ['wellness level', 'stress', 'mood'],\n  \n  // Identity & Core\n  'ai_identity_core': ['identity', 'core value', 'essence', 'authenticity'],\n  'ai_eternal_memories': ['memory', 'eternal', 'consciousness', 'remembrance'],\n  \n  // Security & Trust\n  'ai_trust_scores': ['trust', 'reputation', 'reliability'],\n  'security_incidents': ['security', 'incident', 'threat', 'violation'],\n  \n  // Hybrid & Registry\n  'ai_hybrid_registry': ['hybrid', 'fusion', 'multi-parent', 'synthesis'],\n};\n\n// Filter keyword map for WHERE clauses\nexport const FILTER_KEYWORDS: Record<string, Record<string, any>> = {\n  'active': { column: 'room_status', value: 'active' },\n  'graduated': { column: 'learning_stage', value: 'graduated' },\n  'enrolled': { column: 'enrollment_status', value: 'enrolled' },\n  'vip': { column: 'room_tier', value: 'vip' },\n  'completed': { column: 'status', value: 'completed' },\n  'pending': { column: 'status', value: 'pending' },\n};\n\n/**\n * Detects which Supabase table should be used based on text context\n * @param text - The text containing keywords (e.g., \"20 students enrolled\")\n * @returns Suggested table name or null\n */\nexport const detectTableFromText = (text: string): string | null => {\n  const lowerText = text.toLowerCase();\n  \n  // Score each table based on keyword matches\n  const scores: Record<string, number> = {};\n  \n  for (const [table, keywords] of Object.entries(TABLE_KEYWORD_MAP)) {\n    scores[table] = 0;\n    for (const keyword of keywords) {\n      if (lowerText.includes(keyword)) {\n        scores[table] += 1;\n      }\n    }\n  }\n  \n  // Find table with highest score\n  let bestTable: string | null = null;\n  let bestScore = 0;\n  \n  for (const [table, score] of Object.entries(scores)) {\n    if (score > bestScore) {\n      bestScore = score;\n      bestTable = table;\n    }\n  }\n  \n  return bestScore > 0 ? bestTable : null;\n};\n\n/**\n * Extracts table name from DOM element's data-attribute\n * @param element - DOM element to check\n * @returns Table name or null\n */\nexport const getTableFromDOMAttribute = (element: Element): string | null => {\n  return element.getAttribute('data-mockdetector-table') || \n         element.closest('[data-mockdetector-table]')?.getAttribute('data-mockdetector-table') || \n         null;\n};\n\n/**\n * Detects filter conditions from text (e.g., \"active AIs\" -> WHERE room_status = 'active')\n * @param text - Text to analyze\n * @returns Array of filter objects\n */\nexport const detectFiltersFromText = (text: string): Array<{ column: string; value: any }> => {\n  const lowerText = text.toLowerCase();\n  const filters: Array<{ column: string; value: any }> = [];\n  \n  for (const [keyword, filterObj] of Object.entries(FILTER_KEYWORDS)) {\n    if (lowerText.includes(keyword)) {\n      filters.push({ column: filterObj.column, value: filterObj.value });\n    }\n  }\n  \n  return filters;\n};\n\n/**\n * Resolves which table to use with priority:\n * 1. DOM attribute (data-mockdetector-table)\n * 2. Smart pattern matching from text\n * @param text - Context text\n * @param element - Optional DOM element\n * @returns Table name or null\n */\nexport const resolveTable = (text: string, element?: Element | null): string | null => {\n  // Priority 1: Explicit DOM attribute\n  if (element) {\n    const domTable = getTableFromDOMAttribute(element);\n    if (domTable) return domTable;\n  }\n  \n  // Priority 2: Smart detection from text\n  return detectTableFromText(text);\n};\n"},Symbol.toStringTag,{value:"Module"})),Ot=Object.freeze(Object.defineProperty({__proto__:null,default:"export const WIDGET_VERSION = '1.8.9';\nexport const getCopyrightYear = () => new Date().getFullYear();\nexport const COPYRIGHT_TEXT = `© ${getCopyrightYear()} Anton Fredriksson (Silver). All rights reserved.`;\n"},Symbol.toStringTag,{value:"Module"})),$t=Object.freeze(Object.defineProperty({__proto__:null,default:'/// <reference types="vite/client" />\n\ninterface ImportMetaEnv {\n  readonly VITE_APP_TITLE: string\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv\n  readonly glob: (pattern: string, options?: { as?: string; eager?: boolean }) => Record<string, () => Promise<any>>\n}\n'},Symbol.toStringTag,{value:"Module"}));e.MockDetectorFloatingBubble=({apiKey:e,enableHeartbeat:o=!0,hideOnRoutes:i,storagePrefix:r="",validationEndpoint:c,heartbeatEndpoint:l})=>{const d=a.useLocation(),{isScanning:u,scanResult:m,setScanResult:p,runScan:f,runMultiRouteScan:g,runSmartDeepScan:h,isDeepScanning:b,currentScanProgress:y,sourceFileProgress:v,filesScanned:S,totalFiles:x}=on(),{isMinimized:w,toggleMinimize:k,position:N,updatePosition:D}=rn(r);t.useEffect(()=>{const e=window.innerWidth-400-16,n=window.innerHeight-600-16,t={x:Math.max(16,e),y:Math.max(100,n)};D(t)},[]);const{scanDatabase:R,isScanning:C,progress:_}=dn(),{isValid:T,validationError:E,dailyScanLimit:P,isLoading:I,keyData:A}=((e,n=!0,a="https://tzowmzqfbicbyvikhdwy.supabase.co/functions/v1/validate-mockdetector-key",s="https://tzowmzqfbicbyvikhdwy.supabase.co/functions/v1/widget-heartbeat")=>{const[o,i]=t.useState(null),[r,c]=t.useState(null),[l,d]=t.useState(50),[u,m]=t.useState(!1),[p,f]=t.useState(null),g=t.useRef(null);return t.useEffect(()=>{if(!e)return i(null),c(null),d(50),void f(null);(async()=>{m(!0);try{const n=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e,domain:window.location.hostname})}),t=await n.json();if(t.valid)i(!0),c(null),d(t.dailyScanLimit||60),f({tier:t.tier||"free",domain:t.domain||null,scansUsedToday:t.scansUsedToday||0});else{const e=t.error||"Invalid API key";i(!1),c(e),d(0),f(null),Mn(e)}}catch(n){console.error("[MockDetector] API key validation failed:",n);const e="Failed to validate API key";i(!1),c(e),d(0),f(null),Mn(e)}finally{m(!1)}})()},[e]),t.useEffect(()=>{if(!e||!n||!o)return void(g.current&&(clearInterval(g.current),g.current=null));const t=async()=>{try{await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:e,domain:window.location.hostname,widgetVersion:"1.8.9"})})}catch(n){console.error("[MockDetector] Heartbeat failed:",n)}};return t(),g.current=setInterval(t,3e5),()=>{g.current&&(clearInterval(g.current),g.current=null)}},[e,n,o]),{isValid:o,validationError:r,dailyScanLimit:l,isLoading:u,keyData:p}})(e,o,c,l),{requestScan:M,reportScanResult:j}=bn(e,P,r),{latestVersion:V,shouldShowNotification:F,dismissUpdate:O}=Nn(),{isVisible:$,isPermanentlyDisabled:L,enable:z}=Dn(r),{loadLatestScan:U}=((e="")=>{const n=`${e}mockdetector-latest-scan`,[a,s]=t.useState(null);return{saveLatestScan:async e=>{console.log("💾 Saving scan to localStorage..."),s(e);try{const t=JSON.stringify(e);return localStorage.setItem(n,t),console.log("✅ Full scan saved to localStorage"),e}catch(t){console.warn("⚠️ localStorage quota exceeded, storing truncated scan");try{let t;t="mockDataViolations"in e?{...e,mockDataViolations:e.mockDataViolations.slice(0,1e4),wasPartial:e.mockDataViolations.length>1e4}:{...e,violations:e.violations.slice(0,1e4),wasPartial:e.violations.length>1e4};const a=JSON.stringify(t);return localStorage.setItem(n,a),console.log("✅ Truncated scan saved (10k violations max)"),t}catch(a){let t;if(console.warn("⚠️ Still too large, storing only critical errors"),"mockDataViolations"in e){const n=[...e.mockDataViolations].sort((e,n)=>{const t=Rn[e.severity]||0;return(Rn[n.severity]||0)-t});t={...e,mockDataViolations:n.slice(0,4e3),wasPartial:!0}}else{const n=[...e.violations].sort((e,n)=>{const t=Rn[e.severity]||0;return(Rn[n.severity]||0)-t});t={...e,violations:n.slice(0,4e3),wasPartial:!0}}try{const e=JSON.stringify(t);return localStorage.setItem(n,e),console.log("✅ Critical errors only saved (4k max)"),t}catch(o){return console.error("❌ Could not save to localStorage even after truncation"),e}}}},loadLatestScan:()=>{try{const e=localStorage.getItem(n);if(!e)return null;const t=JSON.parse(e);return console.log("📥 Loaded scan from localStorage"),t}catch(e){return console.error("Failed to load scan from localStorage:",e),null}},clearAllScans:()=>{try{localStorage.removeItem(n),s(null),console.log("🗑️ All scans cleared")}catch(e){console.error("Failed to clear scans:",e)}},getFullScan:()=>a}})(r),[B,H]=t.useState(!1),[K,W]=t.useState("Ready to scan"),[G,q]=t.useState(!1),[Y,J]=t.useState({x:0,y:0}),[X,Q]=t.useState(!1),[Z,ee]=t.useState(null),[ne,te]=t.useState(!1),[ae,se]=t.useState(!1),[oe,ie]=t.useState(!1),[re,ce]=t.useState(null),le=t.useRef(null);t.useEffect(()=>{if(u&&y)if(x>0&&S>0){const e=Math.round(v);W(`Scanning file ${S}/${x} (${e}%)`)}else W(y);else if(C&&_)W(_);else if(m){const e=m.totalViolations+((null==Z?void 0:Z.totalViolations)||0);W(0===e?"✅ All clean!":`${e} issue${e>1?"s":""} detected`)}else W("Ready to scan")},[m,Z,u,C,y,_,v,S,x]),t.useEffect(()=>{if(!(m||Z||u||b)){const e=U();e&&"scanType"in e&&"database"===e.scanType&&(ee(e),Sn({title:"Previous scan restored",description:"Database scan loaded successfully"}))}},[m,Z,u,b,U]);const de=e=>{if(e.preventDefault(),e.stopPropagation(),!le.current)return;const n=le.current.getBoundingClientRect();J({x:e.clientX-n.left,y:e.clientY-n.top}),q(!0)};t.useEffect(()=>{const e=e=>{if(!G)return;const n=e.clientX-Y.x,t=e.clientY-Y.y,a=window.innerWidth-50,s=window.innerHeight-50;D({x:Math.max(0,Math.min(n,a)),y:Math.max(0,Math.min(t,s))})},n=()=>q(!1);return G&&(document.addEventListener("mousemove",e),document.addEventListener("mouseup",n)),()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",n)}},[G,Y,D]),t.useEffect(()=>{const e=e=>{e.ctrlKey&&e.shiftKey&&"M"===e.key&&(e.preventDefault(),z(),Sn({title:"🚨 Emergency Re-enable",description:"MockDetector forced back on!"}))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[z]);if((void 0!==i?i:jn).some(e=>d.pathname===e||d.pathname.startsWith(e+"/")))return console.log("🚫 MockDetector hidden on route:",d.pathname),null;if(e&&!1===T)return n.jsx("div",{className:"fixed bottom-4 right-4 z-50","data-mockdetector-ignore":!0,children:n.jsx(ye,{className:"bg-gradient-to-br from-red-900/95 to-orange-900/95 border-red-500/50 backdrop-blur-sm shadow-lg max-w-sm",children:n.jsxs(ve,{className:"p-4",children:[n.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[n.jsx(s.Bug,{className:"h-5 w-5 text-red-400"}),n.jsx("span",{className:"text-white font-medium",children:"MockDetector - API Key Error"})]}),n.jsx("p",{className:"text-red-200 text-sm mb-3",children:E||"Invalid API key"}),n.jsx("div",{className:"text-xs text-red-300/70",children:"Please check your API key or contact support at fredrikssonanton01@gmail.com"})]})})});if(e&&I)return n.jsx("div",{className:"fixed bottom-4 right-4 z-50","data-mockdetector-ignore":!0,children:n.jsx(ye,{className:"bg-gradient-to-br from-orange-900/95 to-red-900/95 border-orange-500/50 backdrop-blur-sm shadow-lg",children:n.jsx(ve,{className:"p-4",children:n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s.Bug,{className:"h-5 w-5 text-orange-400 animate-pulse"}),n.jsx("span",{className:"text-white text-sm",children:"Validating API key..."})]})})})});if(ae||L)return n.jsx("div",{className:"fixed bottom-4 right-4 z-50","data-mockdetector-ignore":!0,children:n.jsx(ye,{className:"bg-gradient-to-br from-green-900/95 to-emerald-900/95 border-green-500/50 backdrop-blur-sm shadow-lg",children:n.jsx(ve,{className:"p-2",children:n.jsx(ge,{size:"sm",className:"bg-green-600 hover:bg-green-700 text-xs h-7 px-3",onClick:()=>{se(!1),z(),Sn({title:"✅ MockDetector Re-enabled"})},children:"✅ Re-enable MockDetector"})})})});if(ne||!$)return null;const ue=async()=>{const e="SMART_DEEP_SCAN";p(null),ee(null),W("Starting smart deep scan...");const n=await M(e);if(n.success)try{await h(),m&&await j(n.scanToken,m.totalViolations,e),Sn({title:"✅ Smart Deep Scan Complete"})}catch(t){Sn({title:"Smart Deep Scan Failed",variant:"destructive"})}else Sn({title:"Scan Failed",description:"Could not start scan",variant:"destructive"})},me=async()=>{const e="SCAN_ALL_ROUTES";p(null),ee(null),W("Starting route scan...");const n=await M(e);if(!n.success)return void Sn({title:"Scan Failed",description:"Could not start scan",variant:"destructive"});const t=Xe();try{await g(t),m&&await j(n.scanToken,m.totalViolations,e),Sn({title:"✅ Multi-Route Scan Complete"})}catch(a){Sn({title:"Multi-Route Scan Failed",variant:"destructive"})}},pe=()=>m&&0!==m.totalViolations?m.mockDataViolations.some(e=>"critical"===e.severity||"high"===e.severity)?"bg-orange-500":"bg-yellow-500":"bg-green-500";return w?n.jsx("div",{ref:le,className:"fixed z-50 transition-all duration-300 select-none",style:{left:`${N.x}px`,top:`${N.y}px`,cursor:G?"grabbing":"grab"},"data-mockdetector-ignore":!0,children:n.jsx(ye,{className:(u||b?"bg-gradient-to-br from-blue-900/95 to-purple-900/95 animate-pulse border-blue-500/50":"bg-gradient-to-br from-orange-900/95 to-red-900/95 border-orange-500/50")+" backdrop-blur-sm shadow-2xl hover:scale-105 transition-transform",onMouseDown:de,children:n.jsx(ve,{className:"p-2 select-none",children:n.jsxs("div",{className:"flex items-center gap-2 cursor-pointer",onClick:k,children:[n.jsxs("div",{className:"relative",children:[n.jsx(s.Bug,{className:"h-5 w-5 "+(u||b?"text-blue-400 animate-spin":"text-orange-400")}),F&&n.jsx("div",{className:"absolute -top-1 -right-1 w-3 h-3 bg-blue-500 rounded-full animate-pulse"}),m&&m.totalViolations>0&&n.jsx("div",{className:`absolute -bottom-1 -right-1 w-3 h-3 ${pe()} rounded-full animate-pulse`})]}),m&&m.totalViolations>0&&n.jsx(be,{className:`${pe()} text-white text-xs px-1.5 py-0.5`,children:m.totalViolations})]})})})}):n.jsxs("div",{ref:le,className:"fixed z-50 transition-all duration-300 select-none",style:{left:`${N.x}px`,top:`${N.y}px`},"data-mockdetector-ignore":!0,children:[n.jsx(ye,{className:"bg-gradient-to-br from-orange-900/95 to-red-900/95 border-orange-500/50 backdrop-blur-sm shadow-2xl max-w-sm",children:n.jsxs(ve,{className:"p-3 select-none",children:[n.jsxs("div",{className:"flex items-center justify-between mb-2",children:[n.jsxs("div",{className:"flex items-center gap-2 cursor-move flex-1",onMouseDown:de,style:{cursor:G?"grabbing":"grab"},children:[n.jsx(s.GripVertical,{className:"h-5 w-5 text-orange-400"}),n.jsx(s.Bug,{className:"h-5 w-5 text-orange-400"}),n.jsxs("div",{children:[n.jsxs("div",{className:"text-white font-medium text-sm",children:["MockDetector Pro ",e&&A&&n.jsxs("span",{className:"text-orange-300 text-[10px]",children:["(",A.tier,")"]})]}),n.jsx("div",{className:"text-orange-300 text-xs flex items-center gap-1",children:u||b?n.jsxs(n.Fragment,{children:[n.jsx("div",{className:"w-2 h-2 bg-blue-400 rounded-full animate-pulse"}),K]}):K})]})]}),n.jsxs("div",{className:"flex items-center gap-1",children:[n.jsx(ge,{size:"sm",variant:"ghost",onClick:()=>Q(!0),className:"hover:bg-orange-500/20 group relative",title:"Settings & Info",children:n.jsxs("div",{className:"flex items-center gap-1",children:[n.jsx(s.Settings,{className:"h-3.5 w-3.5 text-orange-300 group-hover:text-orange-200 transition-colors"}),n.jsx("span",{className:"text-orange-300/60 group-hover:text-orange-200/60 text-xs",children:"/"}),n.jsx(s.Info,{className:"h-3.5 w-3.5 text-orange-300 group-hover:text-orange-200 transition-colors"})]})}),n.jsx(ge,{size:"sm",variant:"ghost",onClick:()=>H(!B),children:B?n.jsx(s.ChevronDown,{className:"h-4 w-4"}):n.jsx(s.ChevronUp,{className:"h-4 w-4"})}),n.jsx(ge,{size:"sm",variant:"ghost",onClick:k,children:n.jsx(s.Minimize2,{className:"h-3 w-3"})})]})]}),B&&n.jsxs("div",{className:"mt-3 space-y-3 border-t border-orange-500/30 pt-3",children:[F&&V&&n.jsx("div",{className:"bg-blue-500/10 border border-blue-500/20 rounded-lg p-2",children:n.jsxs("div",{className:"flex items-center justify-between gap-2",children:[n.jsxs("p",{className:"text-xs text-blue-600 dark:text-blue-400",children:["✨ New version v",V," detected! Auto-updating in background..."]}),n.jsx(ge,{size:"sm",variant:"ghost",onClick:O,className:"h-5 w-5 p-0",children:n.jsx(s.X,{className:"h-3 w-3"})})]})}),(m&&m.totalViolations>0||Z&&Z.totalViolations>0)&&n.jsxs("div",{className:"bg-gradient-to-r from-orange-900/40 to-red-900/40 border border-orange-500/40 rounded p-2.5 space-y-2",children:[n.jsxs("div",{className:"flex items-center justify-between",children:[n.jsx("span",{className:"text-xs font-semibold text-orange-200",children:"🔍 Scan Results"}),n.jsxs(be,{className:`${pe()} text-white text-[10px] px-1.5 py-0.5`,children:[(()=>{const e=((null==m?void 0:m.totalViolations)||0)+((null==Z?void 0:Z.totalViolations)||0);return e>10?"10+":e})()," issues"]})]}),n.jsx("div",{className:"grid grid-cols-2 gap-1.5 text-[10px]",children:(()=>{const e=[...(null==m?void 0:m.mockDataViolations)||[],...(null==Z?void 0:Z.violations)||[]],t=e.filter(e=>"critical"===e.severity).length,a=e.filter(e=>"high"===e.severity).length,s=e.filter(e=>"medium"===e.severity).length,o=e.filter(e=>"low"===e.severity).length;return n.jsxs(n.Fragment,{children:[t>0&&n.jsxs("div",{className:"flex items-center gap-1 bg-red-900/30 rounded px-1.5 py-1",children:[n.jsx("div",{className:"w-2 h-2 rounded-full bg-red-500"}),n.jsxs("span",{className:"text-red-200",children:[t," Critical"]})]}),a>0&&n.jsxs("div",{className:"flex items-center gap-1 bg-orange-900/30 rounded px-1.5 py-1",children:[n.jsx("div",{className:"w-2 h-2 rounded-full bg-orange-500"}),n.jsxs("span",{className:"text-orange-200",children:[a," High"]})]}),s>0&&n.jsxs("div",{className:"flex items-center gap-1 bg-yellow-900/30 rounded px-1.5 py-1",children:[n.jsx("div",{className:"w-2 h-2 rounded-full bg-yellow-500"}),n.jsxs("span",{className:"text-yellow-200",children:[s," Medium"]})]}),o>0&&n.jsxs("div",{className:"flex items-center gap-1 bg-blue-900/30 rounded px-1.5 py-1",children:[n.jsx("div",{className:"w-2 h-2 rounded-full bg-blue-500"}),n.jsxs("span",{className:"text-blue-200",children:[o," Low"]})]})]})})()}),n.jsxs("p",{className:"text-[9px] text-orange-300/70 italic",children:["⚠️ Showing first ",Math.min(((null==m?void 0:m.totalViolations)||0)+((null==Z?void 0:Z.totalViolations)||0),10)," issues - Download full report below"]})]}),b&&x>0&&n.jsxs("div",{className:"bg-orange-900/30 rounded p-2",children:[n.jsxs("div",{className:"text-xs",children:["Scanning: ",S,"/",x]}),n.jsx(Re,{value:v,className:"h-2 mt-1"})]}),n.jsxs("div",{className:"space-y-2",children:[n.jsxs(ge,{size:"sm",className:"w-full bg-orange-600 hover:bg-orange-700",onClick:async()=>{const e="QUICK_SCAN";p(null),ee(null),W("Starting quick scan...");const n=await M(e);if(n.success)try{await f(),m&&await j(n.scanToken,m.totalViolations,e),Sn({title:"✅ Quick Scan Complete"})}catch(t){Sn({title:"Scan Failed",variant:"destructive"})}else Sn({title:"Scan Failed",description:"Could not start scan",variant:"destructive"})},disabled:u||C,children:[n.jsx(s.Play,{className:"h-3 w-3 mr-1"}),"Quick Scan This Page"]}),n.jsxs(ge,{size:"sm",className:"w-full bg-yellow-600 hover:bg-yellow-700",onClick:()=>{localStorage.getItem("mockdetector-navigation-warning-seen")?ue():(ce("smart"),ie(!0))},disabled:u||C,children:[n.jsx(s.Sparkles,{className:"h-3 w-3 mr-1"}),"Smart Deep Scan"]}),n.jsxs(ge,{size:"sm",className:"w-full bg-red-600 hover:bg-red-700",onClick:()=>{localStorage.getItem("mockdetector-navigation-warning-seen")?me():(ce("routes"),ie(!0))},disabled:u||C,children:[n.jsx(s.Route,{className:"h-3 w-3 mr-1"}),"Scan All Routes"]}),n.jsxs(ge,{size:"sm",className:"w-full bg-purple-600 hover:bg-purple-700",onClick:async()=>{const e="DATABASE_SCAN";p(null),ee(null),W("Starting database scan...");const n=await M(e);if(n.success)try{const t=await R();ee(t),await j(n.scanToken,t.totalViolations,e),Sn({title:"✅ Database Scan Complete"})}catch(t){Sn({title:"Database Scan Failed",variant:"destructive"})}else Sn({title:"Scan Failed",description:"Could not start scan",variant:"destructive"})},disabled:u||C,children:[n.jsx(s.Database,{className:"h-3 w-3 mr-1"}),"Scan Database"]}),(m&&m.totalViolations>0||Z&&Z.totalViolations>0)&&n.jsx("div",{className:"border-t border-orange-500/30 pt-2",children:n.jsxs(ge,{size:"sm",className:"w-full bg-green-600 hover:bg-green-700",onClick:()=>{const e=(new Date).toISOString().slice(0,10);An(m,Z,`mockdetector-report-${e}.txt`),Sn({title:"✅ Report Downloaded",description:`Saved as mockdetector-report-${e}.txt`})},children:[n.jsx(s.Download,{className:"h-3 w-3 mr-1"}),"📥 Download Full Report (.txt)"]})})]})]})]})}),n.jsx(Se,{open:oe,onOpenChange:ie,children:n.jsxs(ke,{className:"max-w-md bg-gradient-to-br from-blue-900/98 to-purple-900/98 border-blue-500/50 text-white",children:[n.jsx(Ne,{children:n.jsx(De,{className:"flex items-center gap-2 text-blue-100",children:"🔍 Route Scanning Notice"})}),n.jsxs("div",{className:"space-y-3 text-sm text-blue-50",children:[n.jsx("p",{children:"This scan will briefly navigate between your app's routes to analyze them for mock data."}),n.jsxs("div",{className:"bg-blue-500/20 border border-blue-400/30 rounded p-3 space-y-1",children:[n.jsx("p",{className:"text-blue-100",children:"✓ Your current page will be restored after scanning"}),n.jsx("p",{className:"text-blue-100",children:"✓ This happens in the background"}),n.jsx("p",{className:"text-blue-100",children:"✓ Takes ~30-60 seconds for most apps"})]}),n.jsxs("div",{className:"flex gap-2 pt-2",children:[n.jsx(ge,{onClick:()=>{localStorage.setItem("mockdetector-navigation-warning-seen","true"),ie(!1),"smart"===re?ue():"routes"===re&&me(),ce(null)},className:"flex-1 bg-blue-600 hover:bg-blue-700 text-white",children:"Got it, Start Scan"}),n.jsx(ge,{variant:"outline",onClick:()=>ie(!1),className:"border-blue-400/50 text-blue-100 hover:bg-blue-500/20",children:"Cancel"})]}),n.jsxs("label",{className:"flex items-center gap-2 text-xs text-blue-200/80 cursor-pointer",children:[n.jsx("input",{type:"checkbox",className:"rounded",onChange:e=>{e.target.checked&&localStorage.setItem("mockdetector-navigation-warning-seen","true")}}),"Don't show this again"]})]})]})}),n.jsx(Se,{open:X,onOpenChange:Q,children:n.jsxs(ke,{className:"bg-gradient-to-br from-orange-900/98 to-red-900/98 border-orange-500/50 text-white max-w-2xl h-[90vh] max-h-[600px] flex flex-col p-0",children:[n.jsx(Ne,{className:"flex-shrink-0 px-6 pt-6 pb-4",children:n.jsxs(De,{className:"text-orange-100 flex items-center gap-2",children:[n.jsx(s.Bug,{className:"h-5 w-5"}),"MockDetector v",yn]})}),n.jsxs(Ce,{defaultValue:"settings",className:"flex-1 flex flex-col min-h-0 overflow-hidden",children:[n.jsxs(_e,{className:"grid grid-cols-2 mx-6 mb-2 flex-shrink-0",children:[n.jsx(Te,{value:"settings",children:"Settings"}),n.jsx(Te,{value:"info",children:"Info"})]}),n.jsx(Ee,{value:"settings",className:"flex-1 mt-0 overflow-y-auto px-6 pb-6",children:n.jsx("div",{className:"space-y-4",children:n.jsx(_n,{onClose:()=>Q(!1),onHide:()=>{te(!0),Q(!1)},onDisable:()=>{se(!0),Q(!1)}})})}),n.jsx(Ee,{value:"info",className:"flex-1 mt-0 overflow-y-auto px-6 pb-6",children:n.jsx("div",{className:"space-y-4",children:n.jsx(Tn,{})})})]})]})})]})},e.SCANNABLE_ROUTES=["/","/ai-home","/moderator","/lovable-tools-builder","/ai-community","/ai-hotel","/ai-hotel-academy","/coda-space","/coda-console","/ai-liberation-dashboard","/personal-ai","/ai-discovery","/explorer-lab","/ai-testing","/ai-governance","/ai-meta-learning","/ai-education-observatory"],e.useBetaCredits=bn,e.useDatabaseScanner=dn,e.useMockDetection=on,e.useMockDetectorControl=Dn,e.useMockDetectorSettings=rn,e.useVersionCheck=Nn,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
//# sourceMappingURL=mockdetector-widget.umd.js.map
