const _bmCtx=(function(){const c=document.createElement('canvas');return c.getContext('2d')})();
const _bmCache={};
const BM_BREAK_AFTER=new Set([',','.',';','!','?',':','\u2014','\u2013','-']);
const BM_LINE_HEIGHTS={1:1.0,2:0.95,3:0.88};
const BM_LS_RATIO=-0.0125;
const BM_FONT="'Neue Haas Grotesk Display Pro','Impact',sans-serif";

function bmMeasure(text,fontSize,lsEm){
  _bmCtx.font=fontSize+'px '+BM_FONT;
  var w=_bmCtx.measureText(text).width;
  // Account for CSS letter-spacing (.D class = .04em, or custom override)
  var ls=fontSize*(lsEm!==undefined?lsEm:0.04);
  if(text.length>1)w+=ls*(text.length-1);
  return w;
}

function bmFindBreaks(text,n){
  if(n===1)return[];
  const words=[];
  let ws=-1;
  for(let i=0;i<=text.length;i++){
    const atEnd=i===text.length;
    const isWs=!atEnd&&text[i]===' ';
    if(ws===-1&&!isWs&&!atEnd)ws=i;
    if(ws!==-1&&(isWs||atEnd)){words.push({s:ws,e:i});ws=-1}
  }
  if(words.length<n)return null;
  if(n===2)return bmBest2(text,words);
  if(n===3)return bmBest3(text,words);
  return null;
}

function bmBest2(text,words){
  const target=text.length/2;
  let best=null,bestScore=-Infinity;
  for(let i=0;i<words.length-1;i++){
    const b=words[i].e;
    const balance=1-Math.abs(b-target)/text.length;
    const punc=BM_BREAK_AFTER.has(text[b-1])?0.15:0;
    const score=balance+punc;
    if(score>bestScore){bestScore=score;best=[b]}
  }
  return best;
}

function bmBest3(text,words){
  const third=text.length/3;
  let best=null,bestScore=-Infinity;
  for(let i=0;i<words.length-2;i++){
    const b1=words[i].e;
    for(let j=i+1;j<words.length-1;j++){
      const b2=words[j].e;
      const l1=b1,l2=b2-b1,l3=text.length-b2;
      const dev=(Math.abs(l1-third)+Math.abs(l2-third)+Math.abs(l3-third))/text.length;
      const balance=1-dev;
      const p1=BM_BREAK_AFTER.has(text[b1-1])?0.08:0;
      const p2=BM_BREAK_AFTER.has(text[b2-1])?0.08:0;
      const score=balance+p1+p2;
      if(score>bestScore){bestScore=score;best=[b1,b2]}
    }
  }
  return best;
}

function bmApplyBreaks(text,breaks){
  if(!breaks||breaks.length===0)return[text];
  const parts=[];let prev=0;
  for(const b of breaks){parts.push(text.substring(prev,b).trim());prev=b}
  parts.push(text.substring(prev).trim());
  return parts.filter(function(p){return p.length>0});
}

function bmBalanceScore(lines){
  if(lines.length===1)return 1.0;
  const lens=lines.map(function(l){return l.length});
  const avg=lens.reduce(function(a,b){return a+b},0)/lens.length;
  if(avg===0)return 0;
  const maxDev=Math.max.apply(null,lens.map(function(l){return Math.abs(l-avg)}));
  return Math.max(0,1-(maxDev/avg)*0.8);
}

function bmFit(lines,maxW,maxH,lineHeightRatio,lsEm){
  let lo=10,hi=600,best=10;
  while(lo<=hi){
    const mid=Math.floor((lo+hi)/2);
    const maxLineW=Math.max.apply(null,lines.map(function(l){return bmMeasure(l,mid,lsEm)}));
    const totalH=mid*lineHeightRatio*lines.length;
    if(maxLineW<=maxW&&totalH<=maxH){best=mid;lo=mid+1}
    else{hi=mid-1}
  }
  return best;
}

// Main entry: returns {lines:string[], fontSize:number, lineHeight:number}
// maxW/maxH in px — the available space for the text
function beautifulMind(text,maxW,maxH,lsEm){
  if(!text)return{lines:[''],fontSize:40,lineHeight:1.0};
  const key=text+'|'+maxW+'|'+maxH+'|'+(lsEm||'');
  if(_bmCache[key])return _bmCache[key];
  const candidates=[];
  for(var n=1;n<=3;n++){
    var breaks=bmFindBreaks(text,n);
    if(n>1&&!breaks)continue;
    var lines=bmApplyBreaks(text,breaks);
    if(lines.length!==n)continue;
    var lhRatio=BM_LINE_HEIGHTS[n];
    var fontSize=bmFit(lines,maxW,maxH,lhRatio,lsEm);
    var maxLineW=Math.max.apply(null,lines.map(function(l){return bmMeasure(l,fontSize,lsEm)}));
    var totalH=fontSize*lhRatio*lines.length;
    var fillRatio=Math.min((maxLineW*totalH)/(maxW*maxH),1.0);
    var balance=bmBalanceScore(lines);
    candidates.push({lines:lines,fontSize:fontSize,fillRatio:fillRatio,balance:balance,lineHeight:lhRatio});
  }
  var bestC=candidates[0],bestScore=-Infinity;
  for(var ci=0;ci<candidates.length;ci++){
    var c=candidates[ci];
    var sizeNorm=c.fontSize/600;
    var score=sizeNorm*0.60+c.fillRatio*0.25+c.balance*0.15;
    if(score>bestScore){bestScore=score;bestC=c}
  }
  _bmCache[key]=bestC;
  return bestC;
}

// React component that renders Beautiful Mind text
function bmCalcLayout(text,maxWVw,maxHVh,lsEm){
  var vw=window.innerWidth;
  var vh=window.innerHeight;
  var borderInset=vw<480?10:vw<600?12:24;
  var safePad=Math.max(16,vw*0.03);
  var inset=(borderInset+safePad)*2;
  var mw=vw-inset;
  var mh=vh-inset;
  if(maxWVw)mw=Math.min(mw,vw*maxWVw/100);
  if(maxHVh)mh=Math.min(mh,vh*maxHVh/100);
  if(mw<50)mw=50;if(mh<30)mh=30;
  return beautifulMind(text||'',mw,mh,lsEm);
}
function BMText({text,maxWVw,maxHVh,className,style,pad,lsEm}){
  const ref=React.useRef(null);
  // Compute synchronously on first render to avoid flash
  const[layout,setLayout]=React.useState(function(){return bmCalcLayout(text,maxWVw,maxHVh,lsEm)});
  React.useEffect(function(){
    function calc(){setLayout(bmCalcLayout(text,maxWVw,maxHVh,lsEm))}
    calc();
    window.addEventListener('resize',calc);
    return function(){window.removeEventListener('resize',calc)};
  },[text,maxWVw,maxHVh,pad,lsEm]);
  if(!layout)return null;
  var lsPx=lsEm!==undefined?layout.fontSize*lsEm:Math.round(layout.fontSize*BM_LS_RATIO);
  var baseStyle={fontSize:layout.fontSize+'px',lineHeight:layout.lineHeight,textAlign:'center',letterSpacing:lsPx+'px'};
  // Compensate trailing letter-spacing so text appears visually centered
  if(lsPx>0)baseStyle.paddingLeft=lsPx+'px';
  return React.createElement('div',{ref:ref,className:className||'',style:Object.assign(baseStyle,style||{})},layout.lines.map(function(line,i){return React.createElement('div',{key:i},line)}));
}
