(function(){ /* ============================================================ AI HAIRSTYLE CHANGER FOR WOMEN - by Face Shape (HSF v5 (light colors fix + edge halo cleanup)) - 18 female cuts (long-hair focus), 22 colors (browns prominent) - Aspect-ratio preserved, wide smaller/bigger range - Aggressive preload, blue-edge cleanup - NEW: Forehead detection + bang recommendations - Result panel: face shape + metrics + FOREHEAD + bars - hcHeroSwap, camera, thank-you killer ============================================================ */ var HC_CUTS=[ {k:"pixie",n:"Pixie Cut",u:"https://profreetools.online/wp-content/uploads/2026/06/BOX-1-—-SHORT-STRUCTURE-women-1-pixie-cut.webp.webp"}, {k:"frenchbob",n:"French Bob",u:"https://profreetools.online/wp-content/uploads/2026/06/women-2-french-bob.webp.webp"}, {k:"bluntbob",n:"Blunt Bob",u:"https://profreetools.online/wp-content/uploads/2026/06/women-3-blunt-bob.webp.webp"}, {k:"layeredbob",n:"Layered Bob",u:"https://profreetools.online/wp-content/uploads/2026/06/women-4-layered-bob.webp.webp"}, {k:"curlybob",n:"Short Curly Bob",u:"https://profreetools.online/wp-content/uploads/2026/06/women-5-short-curly-bob.webp.webp"}, {k:"asymmetric",n:"Asymmetric Bob",u:"https://profreetools.online/wp-content/uploads/2026/06/women-6-asymmetric-bob.web_.webp"}, {k:"curtainbangs",n:"Curtain Bangs",u:"https://profreetools.online/wp-content/uploads/2026/06/BOXMEDIUM-TRENDY-WITH-BANGS-women-7-curtain-bangs.webp.webp"}, {k:"wispybangs",n:"Wispy Bangs",u:"https://profreetools.online/wp-content/uploads/2026/06/women-8-wispy-bangs.webp.webp"}, {k:"sideswept",n:"Side-Swept Bangs",u:"https://profreetools.online/wp-content/uploads/2026/06/women-9-side-swept-bangs.webp.webp"}, {k:"lob",n:"Long Bob (Lob)",u:"https://profreetools.online/wp-content/uploads/2026/06/women-10-long-bob-lob.webp.webp"}, {k:"shagcut",n:"Shag Cut",u:"https://profreetools.online/wp-content/uploads/2026/06/women-11-shag-cut.webp.webp"}, {k:"wolfcut",n:"Wolf Cut",u:"https://profreetools.online/wp-content/uploads/2026/06/women-12-wolf-cut.webp.webp"}, {k:"longlayered",n:"Long Layered Hair",u:"https://profreetools.online/wp-content/uploads/2026/06/BOX-3-—-LONG-GLAM-women-13-long-layered.webp.webp"}, {k:"waves",n:"Beach Waves",u:"https://profreetools.online/wp-content/uploads/2026/06/women-14-waves.webp.webp"}, {k:"sleekstraight",n:"Sleek Straight Long",u:"https://profreetools.online/wp-content/uploads/2026/06/women-15-sleek-straight-long.webp.webp"}, {k:"longcurls",n:"Long Defined Curls",u:"https://profreetools.online/wp-content/uploads/2026/06/women-16-long-defined-curls.webp.webp"}, {k:"facelayers",n:"Face-Framing Layers",u:"https://profreetools.online/wp-content/uploads/2026/06/women-17-face-framing-layers.webp.webp"}, {k:"openhair",n:"Open Long Hair",u:"https://profreetools.online/wp-content/uploads/2026/06/women-18-open-hair.webp-last.webp"} ]; /* Per-style fit (female hair = wider/longer than male) */ var STYLE_FIT={ pixie: {wMul:0.80,yMul:0.08}, frenchbob: {wMul:0.85,yMul:0.10}, bluntbob: {wMul:0.83,yMul:0.10}, layeredbob: {wMul:0.90,yMul:0.10}, curlybob: {wMul:0.95,yMul:0.10}, asymmetric: {wMul:0.90,yMul:0.10}, curtainbangs: {wMul:0.72,yMul:0.18}, wispybangs: {wMul:0.70,yMul:0.18}, sideswept: {wMul:0.74,yMul:0.16}, lob: {wMul:0.88,yMul:0.10}, shagcut: {wMul:0.72,yMul:0.20}, wolfcut: {wMul:0.74,yMul:0.20}, longlayered: {wMul:1.05,yMul:0.11}, waves: {wMul:1.08,yMul:0.11}, sleekstraight:{wMul:0.93,yMul:0.10}, longcurls: {wMul:1.12,yMul:0.11}, facelayers: {wMul:0.80,yMul:0.15}, openhair: {wMul:1.02,yMul:0.11} }; /* 22 colors - browns + party shades. Default = index 0 (Dark Brown) */ var HC_COLORS=[ {n:"Natural Brown",c:"#7a5235",t:null}, {n:"Dark Brown",c:"#3b2417",t:"#3b2417"}, {n:"Medium Brown",c:"#54381f",t:"#54381f"}, {n:"Light Brown",c:"#6b4a2f",t:"#6b4a2f"}, {n:"Chestnut",c:"#4a2c20",t:"#4a2c20"}, {n:"Caramel",c:"#8a5a2e",t:"#8a5a2e"}, {n:"Ash Brown",c:"#6e5b4a",t:"#6e5b4a"}, {n:"Mocha",c:"#5d4332",t:"#5d4332"}, {n:"Natural Black",c:"#1a1a1a",t:"#1a1a1a"}, {n:"Soft Black",c:"#2b2b2b",t:"#2b2b2b"}, {n:"Honey Blonde",c:"#cb9b51",t:"#cb9b51"}, {n:"Golden Blonde",c:"#c9a24b",t:"#c9a24b"}, {n:"Dark Blonde",c:"#9c7c4d",t:"#9c7c4d"}, {n:"Platinum Silver",c:"#cfcfd6",t:"#d8d8de"}, {n:"Ash Gray",c:"#8a8a8f",t:"#9a9aa0"}, {n:"Copper Red",c:"#a8521f",t:"#a8521f"}, {n:"Auburn",c:"#6a2e1f",t:"#6a2e1f"}, {n:"Burgundy",c:"#5c2230",t:"#5c2230"}, {n:"Wine Red",c:"#722f37",t:"#722f37"}, {n:"Rose Gold",c:"#b76e79",t:"#b76e79"}, {n:"Cherry Red",c:"#8c1a2a",t:"#8c1a2a"}, {n:"Smoky Purple",c:"#6e5a86",t:"#6e5a86"}, {n:"Ice Blue",c:"#5b8fb0",t:"#5b8fb0"} ]; var HC_DEFAULT_COLOR=0; /* Dark Brown */ /* Long-hair emphasis for most face shapes (per Rubab strategy) */ var HC_BEST={ oval:["longlayered","lob","waves","curtainbangs"], round:["longlayered","lob","sleekstraight","sideswept"], square:["waves","longcurls","facelayers","wispybangs"], oblong:["lob","frenchbob","curtainbangs","layeredbob"], diamond:["lob","curtainbangs","wispybangs","facelayers"], heart:["lob","sideswept","layeredbob","longlayered"], triangle:["longlayered","waves","curtainbangs","shagcut"] }; var HC_NARRATIVE={ oval:"perfectly balanced proportions that flatter almost any cut", round:"soft equal-width features that benefit from added vertical length", square:"a beautifully defined jawline best paired with softening waves and layers", oblong:"an elegant longer face shape balanced by bangs and added width", diamond:"striking cheekbones with a narrower forehead and chin that flatter framing layers", heart:"a wider forehead and softer jawline that pair with chin-length to long cuts", triangle:"a wider jawline complemented by added volume and length on top" }; /* FOREHEAD CLASSIFICATION (NEW) */ var HC_FH_CATS={ tallwide:{name:"Tall & Wide",bangs:["curtainbangs","wispybangs","frenchbob","sideswept"],guide:"Your taller and wider forehead is best framed by Curtain Bangs or Wispy Bangs that shorten the upper face and soften the sides."}, tallnarrow:{name:"Tall & Narrow",bangs:["wispybangs","curtainbangs","sideswept"],guide:"Your taller and narrower forehead is best framed by Wispy Bangs or Curtain Bangs that visually shorten the upper face without adding width."}, average:{name:"Balanced",bangs:["sideswept","curtainbangs","facelayers","wispybangs"],guide:"Your balanced forehead works beautifully with most bang styles. Side-Swept and Curtain Bangs are universally flattering picks."}, shortwide:{name:"Short & Wide",bangs:["facelayers","sideswept","longlayered","lob"],guide:"Your shorter and wider forehead is best with Face-Framing Layers or light Side-Swept pieces - heavy bangs would make the upper face look even shorter."}, shortnarrow:{name:"Short & Narrow",bangs:["facelayers","longlayered","lob","sleekstraight"],guide:"Your shorter and narrower forehead is best showcased without heavy bangs. Face-Framing Layers beautifully flatter your delicate features."} }; var HC={api:null,img:null,box:null,marks:null,shape:null,conf:0,scores:null,sym:0,frame:0,overall:0, fhCat:null,fhConf:0,fhRatio:0,fhWRatio:0, activeCut:"longlayered",activeColor:HC_DEFAULT_COLOR, loaded:false,loading:false,cbs:[],cache:{}, hX:0,hY:0,hS:1,camStream:null}; function hcEl(id){return document.getElementById(id);} function hcQA(s){return document.querySelectorAll(s);} function hcStatus(t,sp){var x=hcEl("hc-status");if(!x)return;if(!t){x.classList.remove("show");x.innerHTML="";return;}x.innerHTML=(sp?'
':"")+'
'+t+"
";x.classList.add("show");} function hcCap(s){return s?s.charAt(0).toUpperCase()+s.slice(1):"";} function hcHeroSwap(on){var r=hcEl("hc-root");if(!r)return;if(on){r.classList.add("hc-active");}else{r.classList.remove("hc-active");}} /* ---------- FACE-API LOADING ---------- */ function hcLoadApi(cb){ if(window.faceapi){HC.api=window.faceapi;hcLoadModels(cb);return;} var s=document.createElement("script"); s.src="https://cdn.jsdelivr.net/npm/@vladmandic/face-api/dist/face-api.js"; s.onload=function(){HC.api=window.faceapi;hcLoadModels(cb);}; s.onerror=function(){ var s2=document.createElement("script"); s2.src="https://unpkg.com/@vladmandic/face-api/dist/face-api.js"; s2.onload=function(){HC.api=window.faceapi;hcLoadModels(cb);}; s2.onerror=function(){hcStatus("Could not load AI engine. Check connection.",false);}; document.head.appendChild(s2); }; document.head.appendChild(s); } function hcLoadModels(cb){ if(HC.loaded){cb&&cb();return;} if(HC.loading){if(cb)HC.cbs.push(cb);return;} HC.loading=true;if(cb)HC.cbs.push(cb); var f=HC.api; var srcs=["https://cdn.jsdelivr.net/npm/@vladmandic/face-api/model","https://unpkg.com/@vladmandic/face-api/model"]; function go(i){ if(i>=srcs.length){HC.loading=false;hcStatus("Could not load AI model.",false);return;} Promise.all([ f.nets.tinyFaceDetector.loadFromUri(srcs[i]), f.nets.faceLandmark68Net.loadFromUri(srcs[i]) ]).then(function(){ HC.loaded=true;HC.loading=false; var q=HC.cbs;HC.cbs=[]; for(var k=0;kbv){bv=sc[k];best=k;} var c=Math.round(60+bv*35);if(c>95)c=95;if(c<60)c=60; HC.shape=best;HC.conf=c;HC.scores=sc; } function hcMetrics(p){ var nx=p[27].x; var pairs=[[0,16],[1,15],[2,14],[3,13],[4,12],[5,11],[6,10],[7,9],[17,26],[18,25],[19,24],[20,23],[21,22],[36,45],[39,42]]; var totDiff=0,totRef=0; for(var i=0;i0?(1-(totDiff/totRef)):0; HC.sym=Math.max(70,Math.min(98,Math.round(symRatio*100))); var topScore=0;for(var k in HC.scores)if(HC.scores[k]>topScore)topScore=HC.scores[k]; HC.frame=Math.max(75,Math.min(96,Math.round(70+topScore*28))); HC.overall=Math.round(HC.sym*0.45+HC.frame*0.55); } /* ---------- FOREHEAD DETECTION (NEW) ---------- */ function hcForehead(p){ var chinY=p[8].y; var eyebrowY=(p[19].y+p[24].y)/2; var detTop=HC.box.y; var foreheadH=eyebrowY-detTop; var lowerFaceH=chinY-eyebrowY; var hRatio=lowerFaceH>0?(foreheadH/lowerFaceH):0.65; var foreheadW=Math.abs(p[26].x-p[17].x); var cheekW=Math.abs(p[14].x-p[2].x); var wRatio=cheekW>0?(foreheadW/cheekW):0.92; HC.fhRatio=hRatio; HC.fhWRatio=wRatio; var hCat=hRatio>0.78?"tall":(hRatio<0.55?"short":"average"); var wCat=wRatio>0.98?"wide":(wRatio<0.86?"narrow":"balanced"); var cat="average"; if(hCat==="tall"&&wCat==="wide")cat="tallwide"; else if(hCat==="tall"&&wCat==="narrow")cat="tallnarrow"; else if(hCat==="tall")cat="tallwide"; else if(hCat==="short"&&wCat==="wide")cat="shortwide"; else if(hCat==="short"&&wCat==="narrow")cat="shortnarrow"; else if(hCat==="short")cat="shortnarrow"; else cat="average"; HC.fhCat=cat; var hDev=hRatio>0.78?(hRatio-0.78):(hRatio<0.55?(0.55-hRatio):0); var wDev=wRatio>0.98?(wRatio-0.98):(wRatio<0.86?(0.86-wRatio):0); var conf=75+Math.min(20,(hDev+wDev)*120); HC.fhConf=Math.round(conf); } /* ---------- IMAGE LOADER ---------- */ function hcLoadImg(url,key,cb){ if(HC.cache[key]){cb(HC.cache[key]);return;} var im=new Image();im.crossOrigin="anonymous"; im.onload=function(){HC.cache[key]=im;cb(im);}; im.onerror=function(){var im2=new Image();im2.onload=function(){HC.cache[key]=im2;cb(im2);};im2.onerror=function(){cb(null);};im2.src=url;}; im.src=url; } /* ---------- RENDER (aspect-ratio preserved) ---------- */ function hcRender(){ var c=hcEl("hc-canvas"),im=HC.img; if(!c||!im)return; var maxW=560,maxH=760,ratio=im.width/im.height,W,H; if(im.width/maxW>=im.height/maxH){W=maxW;H=Math.round(maxW/ratio);} else{H=maxH;W=Math.round(maxH*ratio);} if(W<1)W=1;if(H<1)H=1; c.width=W;c.height=H; var ctx=c.getContext("2d"); ctx.clearRect(0,0,W,H);ctx.drawImage(im,0,0,W,H); c.style.display="block"; var adj=hcEl("hc-adjust");if(adj)adj.classList.add("show"); var cut=null;for(var i=0;i440; } for(var i=0;i205&&(mx-mn)<28){d[i+3]=0;continue;} if(avg>180&&(mx-mn)<22){var ff=1-((avg-180)/25);d[i+3]=Math.round(d[i+3]*Math.max(0,ff));} if(avg>160&&(mx-mn)<14&&d[i+3]>200){d[i+3]=Math.round(d[i+3]*0.65);} if(bb>r+18&&bb>g+10&&avg<160){d[i+3]=Math.round(d[i+3]*0.20);} if(tint&&d[i+3]>0){ if(isLight){ var br=avg/255; var lerp=0.35+br*0.50; d[i]=Math.round(r*(1-lerp)+tint.r*lerp); d[i+1]=Math.round(g*(1-lerp)+tint.g*lerp); d[i+2]=Math.round(bb*(1-lerp)+tint.b*lerp); }else{ d[i]=Math.round(r*tint.r/255); d[i+1]=Math.round(g*tint.g/255); d[i+2]=Math.round(bb*tint.b/255); } } } octx.putImageData(data,0,0); }catch(err){pixelOK=false;} if(pixelOK){ctx.drawImage(oc,x,y,w,h);} else{ if(color&&color.t){octx.globalCompositeOperation="multiply";octx.fillStyle=color.t;octx.fillRect(0,0,W,H2);octx.globalCompositeOperation="source-over";ctx.save();ctx.globalCompositeOperation="multiply";ctx.drawImage(oc,x,y,w,h);ctx.restore();} else{ctx.drawImage(oc,x,y,w,h);} } } /* ---------- RESULT PANEL (face shape + forehead) ---------- */ function hcRenderResult(){ var rp=hcEl("hc-result");if(!rp)return; rp.classList.add("show"); var emp=hcEl("hc-result-empty");if(emp)emp.style.display="none"; var chip=hcEl("hc-chip");if(chip)chip.innerHTML='DETECTED  '+hcCap(HC.shape)+' Face  · '+HC.conf+'%'; var s=hcEl("hc-sym-v"),fr=hcEl("hc-frame-v"),ov=hcEl("hc-ov-v"); if(s)s.textContent=HC.sym+"%"; if(fr)fr.textContent=HC.frame+"%"; if(ov)ov.textContent=HC.overall+"%"; var sR=hcEl("hc-sym-ring"),fR=hcEl("hc-frame-ring"),oR=hcEl("hc-ov-ring"); if(sR)sR.setAttribute("stroke-dasharray",(HC.sym*1.759)+" 999"); if(fR)fR.setAttribute("stroke-dasharray",(HC.frame*1.759)+" 999"); if(oR)oR.setAttribute("stroke-dasharray",(HC.overall*1.759)+" 999"); var nm=hcEl("hc-narr"); if(nm){ var cutName="";for(var i=0;i'+fhInfo+' forehead':''; nm.innerHTML='Because your face shape is '+hcCap(HC.shape)+' with '+HC_NARRATIVE[HC.shape]+extra+', we recommend '+cutName+' styles that complement your features.'; } /* FOREHEAD card */ var fhSize=hcEl("hc-fh-size"),fhConfEl=hcEl("hc-fh-conf"),fhGuide=hcEl("hc-fh-guide"),fhBangs=hcEl("hc-fh-bangs"),fhBlock=hcEl("hc-fh-block"); if(HC.fhCat&&HC_FH_CATS[HC.fhCat]){ var fc=HC_FH_CATS[HC.fhCat]; if(fhBlock)fhBlock.style.display="block"; if(fhSize)fhSize.textContent=fc.name+" Forehead"; if(fhConfEl)fhConfEl.textContent=HC.fhConf+"%"; if(fhGuide)fhGuide.innerHTML=fc.guide; if(fhBangs){ fhBangs.innerHTML=""; fc.bangs.forEach(function(bk){ var ct=null;for(var j=0;j'+pct.toFixed(1)+'%
'; bars.appendChild(row); }); } var bh=hcEl("hc-besthint");if(bh)bh.textContent="Best cuts for your "+hcCap(HC.shape)+" face shown first"; } /* ---------- BUILD UI ---------- */ function hcBuildCuts(){ var g=hcEl("hc-cutgrid");if(!g)return;g.innerHTML=""; var bl=HC_BEST[HC.shape||"oval"]||[]; var ordered=[],seen={}; bl.forEach(function(k){for(var i=0;iBEST FIT':"")+''+ct.n+' hairstyle for women'+ct.n+''; d.addEventListener("click",function(){ var all=g.querySelectorAll(".hc-cut");for(var j=0;j'+ct.n+''; d.addEventListener("click",function(){ var all=g.querySelectorAll(".hc-cut");for(var j=0;jUpload your photo'; }); } } /* ---------- THANK-YOU KILLER ---------- */ function hcKillThankYou(){ function kill(){ try{ var nodes=document.querySelectorAll("p,div,span,h2,h3,h4"); for(var i=0;i0&&txt.length<140&&txt.indexOf("thank you for reading")>=0&&txt.indexOf("subscribe")>=0){ n.style.display="none";n.style.visibility="hidden";n.setAttribute("aria-hidden","true"); } n.__hcChecked=true; } }catch(e){} } kill(); try{var obs=new MutationObserver(function(){kill();});obs.observe(document.body,{childList:true,subtree:true});setTimeout(function(){obs.disconnect();},10000);}catch(e){} setTimeout(kill,300);setTimeout(kill,1000);setTimeout(kill,2500);setTimeout(kill,5000); } /* ---------- BOOT ---------- */ function hcInit(){ hcBuildCuts();hcBuildColors();hcBuildForeheadGrid();hcInitTabs();hcInitAdjust();hcInitButtons();hcArmPreload();hcKillThankYou(); } var hcTries=0,hcDone=false; function hcRetry(){ if(hcDone)return; if(hcEl("hc-cutgrid")&&hcEl("hc-upload")){try{hcInit();hcDone=true;}catch(err){if(window.console)console.log("HC err:",err);}} if(!hcDone&&hcTries<200){hcTries++;setTimeout(hcRetry,120);} } if(document.readyState!=="loading"){hcRetry();}else{document.addEventListener("DOMContentLoaded",hcRetry);} window.addEventListener("load",function(){if(!hcDone)hcRetry();}); setTimeout(hcRetry,500);setTimeout(hcRetry,1500);setTimeout(hcRetry,3000); })();