(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+'';
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);
})();