import fs from 'node:fs';
const fm=JSON.parse(fs.readFileSync(new URL('./font-metrics.json',import.meta.url),'utf8'));
export const C={canvas:'#F5F7F4',paper:'#FFFFFF',ink:'#152B22',muted:'#617168',subtle:'#657267',line:'#DCE4DC',controlBorder:'#7B8C80',soft:'#EDF1EC',green:'#13734E',onPrimary:'#FFFFFE',onDanger:'#FFFEFF',greenSoft:'#E7F3EB',lime:'#DEEF8E',dark:'#11271E',nav:'#132B21',navMuted:'#A9BAAF',navActive:'#294638',amber:'#8A570F',amberSoft:'#FBF0D8',red:'#AE3B39',redSoft:'#FBEDEC',blue:'#315FAD',blueSoft:'#EAF0FC',purple:'#7057A5',purpleSoft:'#F0EBFA'};
export const chapters=['00 / Direction','01 / Brand & foundations','02 / Component library','03 / Intelligence','04 / Applications & delivery','05 / Infrastructure','06 / Observability & operations','07 / Security & cost','08 / Organisation & account','09 / Responsive & states','10 / Route coverage'];
export const boards=[];let parent;let counter=0;
export function node(type,o={}){const n={type,id:'n'+(++counter),...o};parent.children.push(n);return n;}
export function group(name,x,y,w,h,fn,extras={}){const prev=parent;const g=node('FRAME',{name,x,y,w,h,children:[],...extras});parent=g;fn?.(g);parent=prev;return g;}
export function frame(id,title,chapter,fn,{w=1440,h=1000,bg=C.canvas,description='',kind='screen',...rest}={}){const prev=parent;const f={id,name:title,title,chapter,w,h,bg,children:[],description,kind,...rest};boards.push(f);parent=f;fn(f);parent=prev;return f;}
export function rect(x,y,w,h,fill=C.paper,r=0,stroke,extras={}){return node('RECTANGLE',{name:extras.name||'Surface',x,y,w,h,fill,r,stroke,...extras});}
export function line(x,y,w,color=C.line,thickness=1){return rect(x,y,w,thickness,color);}
export function ellipse(x,y,w,h,fill=C.green,stroke,sw=1){return node('ELLIPSE',{name:'Dot',x,y,w,h,fill,stroke,sw});}
export function path(x,y,w,h,d,stroke=C.green,sw=1.5,fill='none',extra={}){return node('VECTOR',{name:'Vector',x,y,w,h,d,stroke,sw,fill,...extra});}
export function estimate(s,size=14,weight=500,tracking=0,mono=false){return [...String(s)].reduce((a,c)=>a+(mono?.602:fm[weight+'/'+size]?.[c]??fm['500/14']?.[c]??.6)*size+tracking,0)*1.015;}
export function text(x,y,value,size=14,color=C.ink,weight=400,w,extra={}){value=String(value);const lines=[];const measure=s=>estimate(s,size,weight,extra.tracking||0,extra.mono);const width=w||Math.max(10,...value.split('\n').map(s=>measure(s)+4));for(const para of value.split('\n')){if(!w||extra.mono){lines.push(para);continue;}let s='';for(const word of para.split(' ')){if(s&&measure(s+' '+word)>w-2){lines.push(s);s=word;}else s+=(s?' ':'')+word;}lines.push(s);}return node('TEXT',{name:extra.name||value.slice(0,55),x,y,w:width,h:Math.ceil(lines.length*(extra.lineHeight||size*1.45)),text:lines.join('\n'),size,color,weight,font:extra.mono?'Roboto Mono':'Inter',lineHeight:size*1.45,...extra});}
export function label(x,y,value,color=C.muted){return text(x,y,value.toUpperCase(),11,color,600,undefined,{tracking:1.4});}
export function icon(name,x,y,size=18,color=C.muted){const paths={home:'M3 10L12 3L21 10V21H15V14H9V21H3Z',spark:'M12 2L14.5 9.5L22 12L14.5 14.5L12 22L9.5 14.5L2 12L9.5 9.5Z',grid:'M3 3H10V10H3ZM14 3H21V10H14ZM3 14H10V21H3ZM14 14H21V21H14Z',stack:'M2 7L12 2L22 7L12 12ZM2 12L12 17L22 12M2 17L12 22L22 17',server:'M3 3H21V10H3ZM3 14H21V21H3ZM6 6H7M6 17H7',mesh:'M12 4V9M6 18L10 14M18 18L14 14M9 2H15V6H9ZM2 17H7V22H2ZM17 17H22V22H17ZM9 9H15V15H9Z',shield:'M12 2L21 6V12C21 18 12 22 12 22C12 22 3 18 3 12V6ZM8 12L11 15L17 9',chart:'M3 3V21H22M7 15L11 10L15 13L21 5',key:'M9 10C12 10 12 3 8 3C3 3 3 10 8 10ZM8 10L20 22M15 17L18 14M18 20L21 17',settings:'M12 2L15 5L19 5V9L22 12L19 15V19H15L12 22L9 19H5V15L2 12L5 9V5H9ZM9 9H15V15H9Z',search:'M10 3A7 7 0 1 0 10 17A7 7 0 1 0 10 3M15 15L22 22',arrow:'M4 12H20M14 6L20 12L14 18',chevron:'M8 4L16 12L8 20',check:'M4 12L9 17L20 6',plus:'M12 4V20M4 12H20',clock:'M12 2A10 10 0 1 0 12 22A10 10 0 1 0 12 2M12 6V12L16 15',bell:'M4 18H20L18 14V9C18 1 6 1 6 9V14ZM10 21H14',git:'M7 3V16C7 23 17 23 17 16V9M7 8L17 8M4 2H10V6H4ZM14 5H20V11H14Z',terminal:'M4 6L10 12L4 18M12 18H21',pause:'M7 5V19M17 5V19',play:'M6 3L21 12L6 21Z',info:'M12 2A10 10 0 1 0 12 22A10 10 0 1 0 12 2M12 11V17M12 6V7',user:'M8 4H16V12H8ZM3 22V18C3 13 21 13 21 18V22',book:'M3 3H10L12 5L14 3H21V21H14L12 23L10 21H3ZM12 5V23',globe:'M12 2A10 10 0 1 0 12 22A10 10 0 1 0 12 2M2 12H22M12 2C5 8 5 16 12 22C19 16 19 8 12 2',external:'M13 3H21V11M21 3L10 14M10 3H3V21H21V14',filter:'M3 5H21M6 12H18M10 19H14',dots:'M4 12H5M11 12H12M18 12H19',close:'M5 5L19 19M19 5L5 19',file:'M5 2H15L21 8V22H5ZM15 2V8H21M8 12H17M8 17H17',down:'M5 8L12 15L19 8',alert:'M12 3L23 22H1ZM12 9V15M12 18V19',refresh:'M20 8A9 9 0 1 0 20 17M20 2V8H14',moon:'M20 16A10 10 0 0 1 8 3A10 10 0 1 0 20 16'};return path(x,y,size,size,paths[name]||paths.grid,color,1.6,'none',{viewW:24,viewH:24,name:'Icon / '+name});}
export function mark(x,y,s=32,color=C.lime){return path(x,y,s,s,'M12 2L22 8V20L12 26L2 20V8ZM12 6L18 18H6ZM6 18L12 22L18 18',color,1.65,'none',{viewW:24,viewH:28,name:'Ankra / Facet mark'});}
export function pill(x,y,value,kind='neutral',{w,small=false}={}){const colors={green:[C.greenSoft,C.green],amber:[C.amberSoft,C.amber],red:[C.redSoft,C.red],blue:[C.blueSoft,C.blue],purple:[C.purpleSoft,C.purple],neutral:[C.soft,C.muted],dark:[C.navActive,C.lime]};const [bg,fg]=colors[kind]||colors.neutral;const h=small?23:28;w=w||estimate(value,small?11:12)+24;return group('Status / '+value,x,y,w,h,()=>{rect(0,0,w,h,bg,6);text(12,small?4:5,value,small?11:12,fg,500,w-20);},{componentKey:'status/'+kind+'/'+value});}
export function button(x,y,value,{kind='primary',w=136,h=38,icon:ico,target,disabled=false}={}){const bg=kind==='primary'?C.green:kind==='dark'?C.dark:kind==='danger'?C.red:C.paper;const fg=kind==='primary'?C.onPrimary:kind==='danger'?C.onDanger:kind==='dark'?C.paper:C.ink;return group('Button / '+value,x,y,w,h,()=>{rect(0,0,w,h,disabled?C.soft:bg,7,kind==='secondary'?C.controlBorder:undefined);if(ico)icon(ico,13,(h-16)/2,16,disabled?C.subtle:fg);text(ico?38:14,(h-20)/2,value,13,disabled?C.subtle:fg,600,w-(ico?45:22));},{target:disabled?undefined:target,componentKey:'button/'+(disabled?'disabled':kind)+'/'+value,role:'button'});}
export function card(x,y,w,h,title,subtitle,fn){return group('Card / '+title,x,y,w,h,()=>{rect(0,0,w,h,C.paper,12,C.line);if(title)text(22,20,title,16,C.ink,600,w-44);if(subtitle)text(22,47,subtitle,12,C.muted,400,w-44);fn?.();});}
export function field(x,y,w,title,value,{hint,select=false,error,secret=false}={}){return group('Field / '+title,x,y,w,hint?102:80,()=>{text(0,0,title,12,C.ink,500,w);rect(0,26,w,42,C.paper,7,error?C.red:C.controlBorder);text(13,37,secret?'••••••••••••••••':value,13,C.muted,400,w-45);if(select)icon('down',w-29,40,14);if(hint)text(0,75,hint,11,error?C.red:C.muted,400,w);});}
export function metric(x,y,w,title,value,detail,kind='green'){return card(x,y,w,126,null,null,()=>{text(20,17,title,12,C.muted,500,w-40);text(20,43,value,29,C.ink,600,w-40);text(20,90,detail,11,C[kind]||C.muted,500,w-40);});}
export function tabs(x,y,w,items,active=0){line(x,y+43,w);let cur=x;items.forEach((item,i)=>{const name=typeof item==='string'?item:item.label;const width=estimate(name,13)+28;text(cur+10,y+10,name,13,i===active?C.green:C.muted,i===active?600:400,width-16,{target:typeof item==='object'?item.target:undefined});if(i===active)rect(cur,y+42,width,2,C.green,1);cur+=width+10;});}
export function table(x,y,w,headers,rows,{widths,rowH=59,targets=[],selected=-1}={}){const colWidths=widths||headers.map(()=>w/headers.length);return group('Table / '+headers.join(', '),x,y,w,44+rows.length*rowH,()=>{rect(0,0,w,44,C.soft,6);let cx=16;headers.forEach((v,i)=>{text(cx,13,v,11,C.muted,500,colWidths[i]-25);cx+=colWidths[i];});rows.forEach((row,ri)=>{const yy=44+ri*rowH;if(ri===selected)rect(0,yy,w,rowH,C.greenSoft);line(0,yy+rowH-1,w);let xx=16;row.forEach((cell,ci)=>{if(typeof cell==='object'&&cell.kind){pill(xx,yy+(rowH-25)/2,cell.text,cell.kind,{small:true});}else{const vals=String(cell).split('|');text(xx,yy+(vals.length>1?10:21),vals[0],13,ci===0?C.ink:C.muted,ci===0?500:400,colWidths[ci]-24,{target:targets[ri]});if(vals[1])text(xx,yy+30,vals[1],10,C.subtle,400,colWidths[ci]-24);}xx+=colWidths[ci];});});});}
export function chart(x,y,w,h,{color=C.green,secondary=false,area=true,labels=['00:00','06:00','12:00','18:00','Now'],seed=1}={}){return group('Chart / time series',x,y,w,h,()=>{for(let i=0;i<4;i++)line(0,i*(h-28)/3,w,C.line);const points=Array.from({length:32},(_,i)=>[i*w/31,18+((Math.sin(i*.61+seed)+1)*.18+(Math.cos(i*.23)+1)*.15)*(h-50)]);const d=points.map(([x,y],i)=>(i?'L':'M')+x.toFixed(1)+' '+y.toFixed(1)).join(' ');if(area)path(0,0,w,h,d+` L${w} ${h-28} L0 ${h-28}Z`,'none',0,C.greenSoft,{viewW:w,viewH:h});path(0,0,w,h,d,color,2,'none',{viewW:w,viewH:h});if(secondary){const d2=points.map(([x,y],i)=>(i?'L':'M')+x.toFixed(1)+' '+(h-y-30).toFixed(1)).join(' ');path(0,0,w,h,d2,C.blue,1.5,'none',{viewW:w,viewH:h});}labels.forEach((s,i)=>text(i*(w-48)/(labels.length-1),h-15,s,10,C.subtle));});}
export function progress(x,y,w,ratio,color=C.green,h=5){rect(x,y,w,h,C.soft,h/2);rect(x,y,w*Math.max(.01,ratio),h,color,h/2);}
export function aiNote(x,y,w,title,body,{target='ai-investigation',h=108}={}){return group('Intelligence / Evidence summary',x,y,w,h,()=>{rect(0,0,w,h,C.greenSoft,10);icon('spark',18,18,18,C.green);text(47,17,title,13,C.green,600,w-66);text(18,47,body,12,C.muted,400,w-40);if(target)text(w-115,h-27,'Investigate  →',11,C.green,600,105,{target});});}
export function shell(title,section,{subtitle='',action,context='Northstar / Production',ai=true}={}){rect(0,0,224,1000,C.nav);mark(26,23,30);text(68,24,'ankra',27,C.paper,600);text(181,31,'↗',18,C.navMuted);rect(16,82,192,45,C.navActive,8);ellipse(30,96,18,18,C.lime);text(58,94,'Northstar',13,C.paper,500);icon('down',181,98,14,C.navMuted);const menu=[['WORKSPACE'],['home','Overview','overview'],['spark','Intelligence','ai-home'],['bell','Inbox','inbox'],['BUILD & RUN'],['grid','Applications','applications'],['stack','Stacks & catalog','stacks'],['server','Infrastructure','clusters'],['OPERATE'],['chart','Observability','metrics'],['shield','Security','security'],['chart','Cost','cost'],['settings','Organisation','org-settings']];let yy=156;for(const m of menu){if(m.length===1){label(26,yy,m[0],C.navMuted);yy+=31;continue;}const active=m[1]===section;if(active){rect(14,yy-3,196,37,C.navActive,7);rect(14,yy+6,3,18,C.lime,1);}icon(m[0],27,yy+6,17,active?C.lime:C.navMuted);text(56,yy+5,m[1],13,active?C.paper:C.navMuted,active?600:400,150,{target:m[2]});if(m[1]==='Inbox')pill(175,yy+3,'3','dark',{small:true});yy+=43;}line(24,844,176,'#355143');icon('book',27,867,17,C.navMuted);text(56,866,'Help & documentation',12,C.navMuted,400,150,{target:'support'});icon('user',27,908,17,C.navMuted);text(56,906,'Alex Morgan',13,C.paper,500,150,{target:'profile'});text(56,927,'Platform engineer',11,C.navMuted);text(26,970,'ANKRA  /  DESIGN CONCEPT',9,C.navMuted,500);rect(224,0,1216,64,C.paper);line(224,63,1216);text(256,24,context,12,C.muted,400,540);rect(978,16,229,33,C.canvas,7,C.line);icon('search',990,25,15);text(1014,23,'Search anything',12,C.muted);text(1168,23,'⌘ K',11,C.muted);icon('bell',1231,24,18);if(ai)button(1271,16,'Ask Ankra',{w:139,h:34,icon:'spark',target:'ai-chat'});text(256,95,title,30,C.ink,600,900);if(subtitle)text(257,141,subtitle,13,C.muted,400,880);if(action)button(1250,99,action.label,{w:158,target:action.target,icon:action.icon||'plus'});}
export function screen(id,title,chapter,section,fn,opts={}){return frame(id,title,chapter,()=>{shell(title,section,opts);fn();},{section,...opts});}
export function sectionHeader(x,y,title,meta,w=1128){text(x,y,title,17,C.ink,600,w-130);if(meta)text(x+w-140,y+3,meta,11,C.muted,400,140);}
export function codeBlock(x,y,w,h,lines,{title='configuration.yaml',dark=true}={}){return group('Editor / '+title,x,y,w,h,()=>{rect(0,0,w,h,dark?C.dark:C.paper,9,dark?undefined:C.line);rect(0,0,w,38,dark?'#1D392D':C.soft,9);icon('file',14,11,15,dark?C.navMuted:C.muted);text(38,10,title,12,dark?C.navMuted:C.muted,500);lines.forEach((s,i)=>{text(15,55+i*23,String(i+1).padStart(2,'0'),11,dark?C.navMuted:C.subtle,400,30,{mono:true});text(49,55+i*23,s,12,dark?(s.startsWith('+')?C.lime:s.startsWith('-')?'#FFA6A2':'#D5E5DA'):C.ink,400,w-65,{mono:true});});});}
export function steps(x,y,w,items,active=1){items.forEach((s,i)=>{const dx=x+i*w/items.length;ellipse(dx,y,25,25,i<active?C.green:i===active?C.greenSoft:C.soft,i===active?C.green:undefined);text(dx+8,y+5,i<active?'✓':i+1,11,i<active?C.onPrimary:C.green,600);text(dx+35,y+4,s,12,i===active?C.ink:C.muted,500,w/items.length-45);});}
export function rowList(x,y,w,items){items.forEach((item,i)=>{const yy=y+i*66;ellipse(x,yy+4,28,28,C.greenSoft);icon(item.icon||'check',x+7,yy+11,14,C.green);text(x+42,yy,item.title,13,C.ink,500,w-140);text(x+42,yy+25,item.detail,11,C.muted,400,w-140);if(item.status)pill(x+w-93,yy+3,item.status,item.kind||'green',{small:true});line(x+42,yy+57,w-42);});}
export function donut(x,y,size,value,labelText){ellipse(x,y,size,size,C.soft);const r=size/2-8;path(x,y,size,size,`M${size/2} 8 A${r} ${r} 0 1 1 8 ${size/2}`,C.green,12,'none',{viewW:size,viewH:size});ellipse(x+16,y+16,size-32,size-32,C.paper);text(x+size*.27,y+size*.3,value,28,C.ink,600,size*.6);text(x+size*.23,y+size*.57,labelText,10,C.muted,500,size*.65);}
