import {C,screen,rect,text,label,icon,line,card,metric,pill,button,tabs,table,chart,progress,aiNote,codeBlock,steps,rowList,group,path,ellipse,field,sectionHeader} from './design-lib.mjs';
const ch='04 / Applications & delivery',infra='05 / Infrastructure';
export function platform(){
screen('applications','Applications','04 / Applications & delivery','Applications',()=>{
rect(256,189,1152,117,C.dark,12);text(281,210,'From repository to a reliable service.',24,C.paper,500,840);text(282,252,'Connect your code. Ankra prepares the build, deployment, and operating context.',13,C.navMuted,400,960);
tabs(256,328,1152,['All applications  48','Production','Preview environments','Needs attention  1']);
const apps=[['checkout','Go · API service','Healthy','green','99.99%','182 ms','eu-prod-01'],['storefront','Next.js · Web application','Healthy','green','99.98%','94 ms','eu-prod-01'],['analytics-worker','Python · Background worker','Deploying','blue','99.95%','—','eu-prod-02'],['identity','Go · API service','Healthy','green','99.99%','42 ms','eu-prod-01'],['docs','Astro · Static site','Healthy','green','100%','28 ms','eu-staging-01'],['billing-api','Node.js · API service','Needs review','amber','99.97%','210 ms','eu-prod-02']];
apps.forEach(([name,stack,status,kind,slo,p95,cluster],i)=>card(256+(i%3)*391,401+Math.floor(i/3)*266,370,245,null,null,()=>{rect(21,22,37,37,C.soft,8);icon('grid',31,31,18,C.green);text(73,23,name,17,C.ink,600,269,{target:'app-overview'});text(73,49,stack,11,C.muted,400,270);pill(21,87,status,kind,{small:true});text(21,133,'AVAILABILITY',10,C.muted,600);text(196,133,'P95 LATENCY',10,C.muted,600);text(21,156,slo,20,C.ink,500);text(196,156,p95,20,C.ink,500);line(21,194,328);icon('server',21,212,13,C.muted);text(43,210,cluster,11,C.muted);text(254,210,'Open  →',11,C.green,600,90,{target:'app-overview'});}));
},{subtitle:'Service health, delivery, and ownership across every environment.',action:{label:'New application',target:'app-create'}});

screen('app-overview','checkout','04 / Applications & delivery','Applications',()=>{
tabs(256,186,1152,[{label:'Overview',target:'app-overview'},{label:'Deployments',target:'app-deployments'},{label:'Builds',target:'build-detail'},{label:'Preview environments',target:'app-previews'},{label:'Code & config',target:'app-code'},{label:'Settings',target:'app-settings'}]);
card(256,252,745,184,null,null,()=>{pill(22,23,'Production · Healthy','green');text(22,75,'checkout.northstar.example',22,C.ink,500,700);icon('external',672,79,18);text(22,117,'main  /  a31f2c8   ·   v2.8.4   ·   deployed 6 minutes ago',12,C.muted,400,699);text(22,150,'Owner: Commerce team    Cluster: eu-prod-01    Stack: commerce',11,C.muted,400,699);});
card(1023,252,385,184,'Latest delivery',null,()=>{text(22,69,'#1842 · Increase memory headroom',14,C.ink,600,340);text(22,105,'PR #248 merged by Alex Morgan',12,C.muted);pill(22,139,'Verified','green',{small:true});text(263,143,'View  →',11,C.green,600,95,{target:'deployment-detail'});});
metric(256,458,272,'Availability','99.99%','30-day SLO · 99.9% target');metric(547,458,272,'p95 latency','182 ms','12% lower than yesterday');metric(839,458,272,'Requests / min','4,820','Within expected traffic');metric(1130,458,278,'Error rate','0.02%','Below 0.1% threshold');
card(256,609,745,316,'Request latency','Last hour · p50 / p95 · milliseconds',()=>{chart(22,92,700,185,{secondary:true});});
card(1023,609,385,316,'Service context','Connected to the way your team works',()=>{rowList(22,85,338,[{title:'Repository',detail:'northstar / checkout',icon:'git'},{title:'Runbook',detail:'Checkout incident response',icon:'book'},{title:'Dependencies',detail:'PostgreSQL · Redis · identity',icon:'mesh'}]);});
},{subtitle:'Go API service · Commerce team',action:{label:'Deploy',target:'app-deploy'}});

screen('app-create','Ship a new application',ch,'Applications',()=>{
steps(256,194,1152,['Repository','Build configuration','Environment','Review'],0);
card(256,254,746,659,'Connect a repository','Ankra will inspect the code and prepare a reviewable setup.',()=>{field(24,86,697,'GitHub connection','Northstar Engineering',{select:true});field(24,185,697,'Repository','northstar / checkout',{select:true});field(24,284,337,'Application name','checkout');field(384,284,337,'Branch','main',{select:true});line(24,381,697);text(24,410,'What Ankra will prepare',16,C.ink,600);rowList(24,455,696,[{title:'A build and deploy proposal',detail:'Dockerfile, manifests, and pipeline configuration',icon:'file'},{title:'A pull request you can review',detail:'Existing repository files are identified before changes',icon:'git'}]);button(24,594,'Analyse repository',{w:218,target:'app-setup-review',icon:'spark'});});
card(1024,254,384,329,'Start with what you have','Existing Dockerfiles and manifests are supported.',()=>{text(22,102,'01  Connect your repository',14,C.ink,500,337);text(22,158,'02  Review the detected stack',14,C.ink,500,337);text(22,214,'03  Approve the setup pull request',14,C.ink,500,337);text(22,278,'No application yet? Browse starters  →',11,C.green,600,340);});aiNote(1024,606,384,'Your source of truth','Git remains the source of deployment configuration. Generated changes arrive as a pull request.',{h:175,target:null});
},{subtitle:'Bring your code. Keep control of how it runs.'});

screen('app-setup-review','Review application setup',ch,'Applications',()=>{
steps(256,193,1152,['Repository','Build configuration','Environment','Review'],1);
card(256,254,384,656,'Detected configuration','northstar / checkout · main',()=>{[['Runtime','Go 1.x'],['Build','Multi-stage Dockerfile'],['Port','8080 / HTTP'],['Health','/healthz'],['Dependencies','PostgreSQL · Redis']].forEach(([a,b],i)=>{text(22,86+i*56,a,12,C.muted);text(139,86+i*56,b,13,C.ink,500,223);});line(22,385,340);text(22,413,'3 proposed files',15,C.ink,600);text(22,455,'Dockerfile\n.ankra/deployment.yaml\n.github/workflows/build.yaml',12,C.muted,400,338,{lineHeight:28});button(22,584,'Create setup pull request',{w:340,target:'app-code',icon:'git'});});
codeBlock(664,254,744,408,['FROM golang:1 AS builder','WORKDIR /app','COPY go.mod go.sum ./','RUN go mod download','COPY . .','RUN CGO_ENABLED=0 go build -o /checkout ./cmd/api','','FROM gcr.io/distroless/static:nonroot','COPY --from=builder /checkout /checkout','EXPOSE 8080','ENTRYPOINT ["/checkout"]'],{title:'Dockerfile · proposed file'});
aiNote(664,686,744,'Review notes','The existing health endpoint is used for readiness. Database credentials are requested as secret inputs during deployment. Nothing is committed until you create the pull request.',{h:158,target:null});
},{subtitle:'Detected from your code, explained before it becomes configuration.'});

screen('app-deploy','Deploy checkout',ch,'Applications',()=>{
steps(256,193,1152,['Application','Target & dependencies','Review','Deploy'],1);
card(256,254,748,672,'Target environment','Choose where this release should run.',()=>{field(24,87,700,'Environment','Production',{select:true});field(24,185,339,'Cluster','eu-prod-01',{select:true});field(385,185,339,'Stack','commerce',{select:true});field(24,283,339,'Image tag','v2.8.4 · sha256:74b1…',{select:true});field(385,283,339,'Namespace','commerce',{select:true});text(24,387,'Dependencies',17,C.ink,600);rowList(24,434,700,[{title:'PostgreSQL',detail:'Bind to commerce-db / app credentials',status:'Bound',icon:'server'},{title:'Redis',detail:'Bind to commerce-cache / connection URL',status:'Bound',icon:'server'}]);button(24,602,'Review deployment',{w:225,target:'deployment-detail',icon:'arrow'});});
card(1026,254,382,360,'Deployment summary',null,()=>{text(22,81,'Application',12,C.muted);text(172,81,'checkout',13,C.ink,500);text(22,131,'Rollout',12,C.muted);text(172,131,'Rolling · max 1 surge',13,C.ink,500,188);text(22,181,'Replicas',12,C.muted);text(172,181,'4',13,C.ink,500);text(22,230,'Est. monthly cost',12,C.muted);text(172,230,'€24.80',18,C.ink,600);text(22,300,'Estimate · shared cluster allocation',11,C.muted,400,338);});aiNote(1026,636,382,'Ready to deploy','Health checks, image access, and dependency bindings are valid. Review the rollout before applying.',{h:173,target:null});
},{subtitle:'Environment, release, and dependency bindings stay explicit.'});

screen('app-deployments','Deployment history',ch,'Applications',()=>{
tabs(256,188,1152,[{label:'Overview',target:'app-overview'},{label:'Deployments',target:'app-deployments'},{label:'Builds',target:'build-detail'},{label:'Previews',target:'app-previews'}],1);
card(256,254,1152,620,'checkout / Production','Every revision connects code, build, rollout, and outcome.',()=>{table(22,88,1108,['RELEASE','REVISION','TRIGGER','DURATION','STATUS'],[['v2.8.4|Increase memory headroom','a31f2c8','Alex · PR #248','2m 18s',{text:'Live',kind:'green'}],['v2.8.3|Update checkout pricing','9f842ab','CI · main','2m 42s',{text:'Superseded',kind:'neutral'}],['v2.8.2|Improve retry policy','dc7712f','CI · main','2m 11s',{text:'Superseded',kind:'neutral'}],['v2.8.1|Dependency patch','229ef18','CI · main','1m 57s',{text:'Rolled back',kind:'amber'}],['v2.8.0|New payment methods','da293b1','Alex · manual','3m 05s',{text:'Superseded',kind:'neutral'}]],{widths:[367,167,237,150,187],rowH:78,targets:Array(5).fill('deployment-detail')});});
},{subtitle:'checkout · Track releases from commit to verified production.'});

screen('deployment-detail','Deployment #1842',ch,'Applications',()=>{
pill(256,191,'Live · Verified','green');text(411,198,'checkout / production / v2.8.4',13,C.muted);
card(256,253,1152,172,'From commit to production','Triggered by PR #248 · a31f2c8 · Alex Morgan',()=>{steps(25,104,1100,['Source checked','Build passed','Scan passed','Rollout ready','Health verified'],5);});
card(256,450,744,438,'Rollout timeline','4 replicas · zero unavailable',()=>{rowList(22,88,700,[{title:'Image verified',detail:'Signed digest matched the build receipt',status:'Passed'},{title:'Manifest applied',detail:'Deployment / checkout · revision 1842',status:'Done'},{title:'Pods became ready',detail:'4 / 4 ready after 48 seconds',status:'Passed'},{title:'Service health verified',detail:'p95 182 ms · error rate 0.02% · 5-minute window',status:'Passed'}]);button(22,370,'View build logs',{kind:'secondary',w:182,target:'build-detail',icon:'terminal'});});
card(1022,450,386,438,'Release details',null,()=>{[['Image','checkout:v2.8.4'],['Digest','sha256:74b1…'],['Cluster','eu-prod-01'],['Namespace','commerce'],['Started','10:18:02 UTC'],['Completed','10:25:20 UTC']].forEach(([a,b],i)=>{text(22,78+i*44,a,12,C.muted);text(156,78+i*44,b,12,C.ink,500,203)});button(22,369,'Review rollback',{kind:'secondary',w:340,target:'state-rollback',icon:'refresh'});});
},{subtitle:'A release is complete when its health is verified, not just when the command exits.'});

screen('build-detail','Build #892 · checkout',ch,'Applications',()=>{
pill(256,191,'Succeeded','green');text(376,198,'main · a31f2c8 · 1m 42s',13,C.muted);
card(256,252,272,671,'Build steps',null,()=>{rowList(18,83,236,[{title:'Checkout',detail:'3s'},{title:'Dependencies',detail:'18s'},{title:'Build',detail:'42s'},{title:'Test',detail:'29s'},{title:'Scan',detail:'7s'},{title:'Publish',detail:'3s'}]);});
codeBlock(550,252,858,516,['10:18:04  Fetching northstar/checkout @ a31f2c8','10:18:07  Restored Go module cache','10:18:25  Building linux/amd64','10:18:25  CGO_ENABLED=0 go build ./cmd/api','10:19:07  Build complete: 14.2 MB','10:19:08  Running test suite','10:19:36  184 passed, 0 failed','10:19:37  Scanning image dependencies','10:19:43  No critical vulnerabilities introduced','10:19:44  Pushing signed image','10:19:46  Published checkout:v2.8.4','','✓ Image is ready for deployment'],{title:'Build output · timestamps in UTC'});
aiNote(550,791,858,'Build summary','The image passed the test and scan gates. Artifact digest and source revision are attached to the deployment.',{h:132,target:'deployment-detail'});
},{subtitle:'Source, logs, checks, image artifacts, and security in one timeline.'});

screen('app-previews','Preview environments',ch,'Applications',()=>{
aiNote(256,190,1152,'A live environment for every review','Previews use isolated namespaces, explicit expiry, and reusable environment profiles. Bound secrets are never included in shared URLs.',{h:102,target:null});
card(256,318,1152,458,'checkout / Active previews','3 active · automatic teardown enabled',()=>{table(22,88,1108,['PREVIEW','SOURCE','PROFILE','EXPIRES','STATUS'],[['PR #251 · New checkout flow|pr-251.checkout.preview.example','feature/checkout-v3','commerce-preview','In 2 days',{text:'Ready',kind:'green'}],['PR #249 · Currency support|pr-249.checkout.preview.example','feature/currencies','commerce-preview','In 1 day',{text:'Ready',kind:'green'}],['PR #247 · API cleanup|Waiting for a successful build','refactor/api','commerce-preview','After build',{text:'Building',kind:'blue'}]],{widths:[384,209,227,130,158],rowH:86,targets:['preview-detail','preview-detail','preview-detail']});});button(256,807,'Configure environment profile',{w:261,kind:'secondary',target:'preview-config',icon:'settings'});
},{subtitle:'Share work in progress with a clear lifecycle.'});

screen('preview-detail','Preview · PR #251',ch,'Applications',()=>{
rect(256,191,1152,121,C.greenSoft,12);text(282,213,'Ready for review',25,C.green,600);text(282,256,'pr-251.checkout.preview.example   ↗',15,C.ink,500,898);pill(1182,234,'Expires in 2 days','green');
tabs(256,336,1152,['Overview','Resources','Events','Logs','Access']);
metric(256,408,369,'Environment cost','€2.10','Since creation · estimate');metric(647,408,369,'Ready resources','8 / 8','All dependencies healthy');metric(1038,408,370,'Time to ready','1m 48s','Includes dependency rollout');
card(256,559,745,346,'Bill of materials','Profile: commerce-preview · version 1.4',()=>{table(22,90,700,['RESOURCE','SOURCE','STATE'],[['checkout','Image a31f2c8',{text:'Ready',kind:'green'}],['PostgreSQL','Chart 1.4.2',{text:'Ready',kind:'green'}],['Redis','Chart 3.2.1',{text:'Ready',kind:'green'}]],{widths:[266,271,163]});});card(1023,559,385,346,'Lifecycle',null,()=>{text(22,82,'Created',12,C.muted);text(171,82,'Today · 10:41 UTC',12,C.ink,500,191);text(22,137,'Tear down',12,C.muted);text(171,137,'On merge or expiry',12,C.ink,500,191);text(22,201,'Database contents are disposable.\nThe production database is not cloned.',12,C.muted,400,339);button(22,277,'Manage preview',{w:341,kind:'secondary',target:'preview-config'});});
},{subtitle:'checkout / feature/checkout-v3 · isolated from production.'});

screen('app-code','Code & configuration',ch,'Applications',()=>{
tabs(256,188,1152,['Repository','Generated files','Pull requests','Container security']);
card(256,254,284,664,'checkout / main',null,()=>{[['Dockerfile',true],['.ankra/',false],['  deployment.yaml',false],['  service.yaml',false],['.github/workflows/',false],['  build.yaml',false],['go.mod',false],['README.md',false]].forEach(([s,a],i)=>{if(a)rect(10,74+i*44,264,37,C.greenSoft,6);icon('file',22,83+i*44,15,a?C.green:C.muted);text(49,81+i*44,s,12,a?C.green:C.muted,a?600:400,211);});});
codeBlock(562,254,846,444,['FROM golang:1 AS builder','WORKDIR /app','COPY go.mod go.sum ./','RUN go mod download','COPY . .','RUN CGO_ENABLED=0 go build -o /checkout ./cmd/api','','FROM gcr.io/distroless/static:nonroot','COPY --from=builder /checkout /checkout','USER nonroot:nonroot','EXPOSE 8080','ENTRYPOINT ["/checkout"]'],{title:'Dockerfile · main / a31f2c8'});aiNote(562,722,846,'Propose a configuration change','Describe the outcome. Ankra prepares a diff and a pull request, preserving the review process in Git.',{h:128,target:'ai-chat'});
},{subtitle:'Configuration is reviewable, versioned, and connected to its running resources.'});

screen('stacks','Stacks & catalog',ch,'Stacks & catalog',()=>{
tabs(256,188,1152,[{label:'Deployed stacks',target:'stacks'},{label:'Stack profiles',target:'stack-profiles'},{label:'Add-on catalog',target:'catalog'},{label:'Chart registries',target:'registries'}]);
card(256,255,1152,485,'Your stacks','Compose dependencies once. Operate them together.',()=>{table(22,88,1108,['STACK','CLUSTER','RESOURCES','SYNC','HEALTH'],[['commerce|Checkout, PostgreSQL, Redis','eu-prod-01','14 · 3 add-ons',{text:'Synced',kind:'green'},{text:'Healthy',kind:'green'}],['observability|Metrics, logs, and alerting','eu-prod-01','22 · 5 add-ons',{text:'Synced',kind:'green'},{text:'Healthy',kind:'green'}],['security-baseline|Policy, scanning, and admission','All production','18 · 4 add-ons',{text:'Draft changes',kind:'amber'},{text:'Healthy',kind:'green'}],['developer-platform|Build and delivery services','eu-staging-01','12 · 3 add-ons',{text:'Synced',kind:'green'},{text:'Healthy',kind:'green'}]],{widths:[357,207,208,190,146],rowH:79,targets:['stack-builder','stack-builder','stack-builder','stack-builder']});});
aiNote(256,765,744,'Drafts are recoverable','Continue editing across sessions. Review the dependency order and the exact diff before applying a draft.',{h:137,target:'stack-builder'});button(1026,780,'Start from a profile',{w:382,kind:'secondary',target:'stack-profiles',icon:'stack'});
},{subtitle:'Applications, charts, and manifests with explicit deployment order.',action:{label:'Create stack',target:'stack-builder'}});

screen('stack-builder','commerce / Stack builder',ch,'Stacks & catalog',()=>{
tabs(256,185,1152,['Builder','Deployments','History','Variables','Description']);
rect(256,253,875,647,C.paper,10,C.line);for(let x=274;x<1120;x+=24)for(let y=273;y<882;y+=24)ellipse(x,y,1.5,1.5,C.line);
pill(274,273,'Draft · 2 changes','amber');pill(445,273,'Saved just now','green');
function block(x,y,title,kind,detail,col=C.green){card(x,y,226,111,null,null,()=>{rect(0,0,4,111,col,2);icon(kind==='Namespace'?'grid':kind==='Manifest'?'file':'stack',17,18,17,col);text(45,17,title,14,C.ink,600,165);text(17,51,kind,10,C.muted,500);text(17,77,detail,11,C.muted,400,191);});}
path(441,458,483,97,'M110 0V48H0V97M110 48H483V97M-4 89L0 97L4 89M479 89L483 97L487 89',C.subtle,1.8,'none',{viewW:483,viewH:97});path(441,666,483,98,'M0 0V48H239V98M483 0V48H239M235 90L239 98L243 90',C.subtle,1.8,'none',{viewW:483,viewH:98});
block(438,347,'commerce','Namespace','Deploy wave 0');block(328,555,'PostgreSQL','Helm add-on','Wait for Ready · wave 1');block(811,555,'Redis','Helm add-on','Wait for Ready · wave 1');block(567,764,'checkout','Manifest','Depends on database + cache');
card(1153,253,255,647,'Inspector','checkout / Deployment',()=>{field(18,89,218,'Namespace','commerce',{select:true});field(18,185,218,'Deploy wave','2',{select:true});text(18,288,'Depends on',12,C.ink,600);pill(18,321,'PostgreSQL','green');pill(18,358,'Redis','green');text(18,418,'Wait until all parent resources\nare healthy before applying.',12,C.muted,400,218);line(18,487,219);button(18,511,'Review 2 changes',{w:218,target:'stack-review',icon:'arrow'});button(18,562,'Add resource',{w:218,kind:'secondary',target:'catalog',icon:'plus'});});
text(256,936,'Dependency arrows define execution order · Shift-drag to pan · + / − to zoom',11,C.muted,400,1136);
},{subtitle:'eu-prod-01 · A visual model of what runs and what must run first.',description:'Namespace, secret/config, operator/CRD, database/app parent ordering preserved. Draft saved state and review are explicit.'});

screen('stack-review','Review stack changes',ch,'Stacks & catalog',()=>{
card(256,192,383,734,'commerce / Deployment order','2 changes · 0 deletions',()=>{rowList(22,92,337,[{title:'Wave 0 · Namespace',detail:'commerce · unchanged',status:'Ready'},{title:'Wave 1 · Dependencies',detail:'PostgreSQL and Redis · unchanged',status:'Ready'},{title:'Wave 2 · Application',detail:'checkout · image + memory limit',status:'Update',kind:'amber'}]);aiNote(22,343,337,'Preflight passed','Parent resources are healthy. The namespace exists and image pull access is valid.',{h:148,target:null});button(22,595,'Apply reviewed changes',{w:337,target:'operation-detail',icon:'check'});text(22,657,'Applies to eu-prod-01 only.',11,C.muted,400,337);});
codeBlock(661,192,747,438,['# Deployment / checkout','spec:','  template:','    spec:','      containers:','-       image: checkout:v2.8.3','+       image: checkout:v2.8.4','        resources:','          limits:','-           memory: 512Mi','+           memory: 768Mi'],{title:'2 changed fields · commerce draft'});
card(661,652,747,274,'Checks before applying','Revalidated against the live cluster',()=>{rowList(22,85,700,[{title:'Manifest validation',detail:'Kubernetes schema and required inputs checked',status:'Passed'},{title:'Dependency graph',detail:'No cycles · all parents resolve',status:'Passed'}]);});
},{subtitle:'See the exact change, its order, and its impact before deployment.'});

screen('stack-profiles','Stack profiles',ch,'Stacks & catalog',()=>{
tabs(256,187,1152,[{label:'Deployed stacks',target:'stacks'},{label:'Stack profiles',target:'stack-profiles'},{label:'Add-on catalog',target:'catalog'}],1);
const profiles=[['Production web service','Application + database + ingress','6 resources','Verified'],['Observability foundation','Metrics, logs, dashboards, and alerts','8 resources','Verified'],['Security baseline','Admission policy and vulnerability scans','7 resources','Verified'],['Preview environment','Ephemeral app, data, and a shareable URL','5 resources','Org profile'],['Developer platform','Build, registry, and delivery services','9 resources','Org profile'],['AI inference stack','Model endpoint, gateway, and monitoring','7 resources','Org profile']];
profiles.forEach(([name,desc,count,status],i)=>card(256+i%3*391,254+Math.floor(i/3)*300,370,277,null,null,()=>{icon('stack',23,26,29,C.green);pill(239,29,status,status==='Verified'?'green':'neutral',{small:true});text(23,89,name,20,C.ink,600,324,{target:'profile-detail'});text(23,147,desc,13,C.muted,400,324);line(23,211,324);text(23,231,count,12,C.muted);text(243,231,'Explore  →',12,C.green,600,106,{target:'profile-detail'});}));
},{subtitle:'Reusable, versioned building blocks for your platform.',action:{label:'Create profile',target:'stack-builder'}});

screen('profile-detail','Production web service',ch,'Stacks & catalog',()=>{
tabs(256,189,1152,['Overview','Resources','Inputs','Versions','Suggestions']);
card(256,255,745,236,'A complete application foundation','Ankra curated · version 1.4.0 · Kubernetes',()=>{text(22,88,'Deploy a web application with PostgreSQL, TLS ingress,\nhealth probes, resource limits, and a baseline network policy.',18,C.ink,400,700);pill(22,170,'6 resources','neutral');pill(147,170,'3 required inputs','amber');pill(304,170,'Dependencies ordered','green');});
card(1023,255,385,497,'Deploy this profile','Inputs are resolved before stack creation.',()=>{field(22,89,340,'Target cluster','eu-staging-01',{select:true});field(22,186,340,'Stack name','new-service');field(22,283,340,'Application image','registry.example/app:v1.0.0');button(22,425,'Configure & review',{w:340,target:'stack-builder',icon:'arrow'});});
card(256,513,745,386,'Included resources',null,()=>{table(22,80,701,['RESOURCE','KIND','WAVE'],[['application','Deployment + Service','2'],['database','PostgreSQL chart','1'],['networking','Ingress + certificate','3'],['namespace','Namespace + NetworkPolicy','0']],{widths:[281,309,111],rowH:64});});
},{subtitle:'A reusable design with explicit inputs, secret bindings, and deployment dependencies.'});

screen('catalog','Add-on catalog',ch,'Stacks & catalog',()=>{
rect(256,189,1152,98,C.dark,11);text(281,211,'Extend your platform with confidence.',23,C.paper,500,900);text(282,252,'Curated add-ons, organisation templates, and your Helm registries.',13,C.navMuted,400,1000);
tabs(256,309,1152,['All add-ons','Databases','Observability','Networking','Security','AI & ML']);
[['PostgreSQL','Reliable relational storage','Database'],['Redis','Cache and message broker','Database'],['Prometheus','Metrics and alerting','Observability'],['Grafana','Dashboards and exploration','Observability'],['cert-manager','Certificate lifecycle management','Networking'],['Kyverno','Kubernetes policy management','Security']].forEach(([name,desc,cat],i)=>card(256+i%3*391,383+Math.floor(i/3)*266,370,244,null,null,()=>{rect(22,22,44,44,C.soft,10);icon(i<2?'server':i===5?'shield':'chart',34,34,20,C.green);text(82,25,name,20,C.ink,600,262,{target:'catalog-detail'});text(82,53,cat,11,C.muted);text(22,102,desc,14,C.muted,400,325);pill(22,148,'Curated','green',{small:true});text(22,202,'Configure add-on  →',12,C.green,600,320,{target:'catalog-detail'});}));
},{subtitle:'Choose a capability. Review its version, resources, and configuration.'});

screen('catalog-detail','PostgreSQL / Add-on',ch,'Stacks & catalog',()=>{
tabs(256,190,1152,['Overview','Chart values','Files','Releases','Installed clusters']);
card(256,255,745,639,'PostgreSQL','Relational storage for production applications',()=>{text(23,90,'A database service with persistent storage, health checks,\nand a clear upgrade path.',20,C.ink,500,699);label(23,189,'Chart information');table(23,229,699,['PROPERTY','VALUE'],[['Registry','Northstar charts'],['Chart','postgresql'],['Version','1.4.2'],['License','PostgreSQL License'],['Installed in','8 clusters']],{widths:[249,450],rowH:55});text(23,572,'Read upstream documentation  ↗',12,C.green,600,600);});
card(1023,255,385,475,'Add to a stack','Review dependencies before deploying.',()=>{field(22,88,340,'Chart version','1.4.2',{select:true});field(22,187,340,'Target stack','commerce / eu-staging-01',{select:true});field(22,286,340,'Namespace','commerce');button(22,401,'Configure in builder',{w:340,target:'stack-builder',icon:'stack'});});
},{subtitle:'Versioned, inspectable, and deployed with its dependencies.'});

screen('clusters','Infrastructure',infra,'Infrastructure',()=>{
tabs(256,187,1152,[{label:'Clusters',target:'clusters'},{label:'Cluster mesh',target:'mesh'},{label:'Provider connections',target:'credentials'}]);
metric(256,253,369,'Clusters connected','12','11 healthy · 1 needs attention','amber');metric(647,253,369,'Capacity','64% available','Across 48 nodes');metric(1038,253,370,'Providers','3','Public cloud + private infrastructure');
card(256,405,1152,491,'Your fleet','All environments · grouped by ownership',()=>{table(22,88,1108,['CLUSTER','PROVIDER / REGION','NODES','VERSION','HEALTH'],[['eu-prod-01|Production · Commerce','Hetzner / Helsinki','12','1.35.x',{text:'Healthy',kind:'green'}],['eu-prod-02|Production · Core','AWS / Stockholm','18','1.35.x',{text:'Healthy',kind:'green'}],['eu-staging-01|Staging · Platform','AWS / Stockholm','8','1.35.x',{text:'Healthy',kind:'green'}],['onprem-01|Development · Platform','Proxmox / Private cloud','10','1.34.x',{text:'Degraded',kind:'amber'}]],{widths:[305,299,141,163,200],rowH:79,targets:Array(4).fill('cluster-overview')});});
},{subtitle:'A consistent operating layer across cloud, on-premise, and imported clusters.',action:{label:'Add cluster',target:'cluster-create'}});

screen('cluster-create','Add a cluster',infra,'Infrastructure',()=>{
steps(256,191,1152,['Infrastructure','Configuration','Review','Provision'],0);
rect(256,252,744,86,C.greenSoft,11);text(278,272,'Where should your cluster run?',22,C.green,600,700);text(279,311,'Choose a provider or connect infrastructure you already operate.',12,C.muted,400,698);
const providers=[['AWS','Managed · EKS'],['Google Cloud','Managed · GKE'],['Microsoft Azure','Managed · AKS'],['Hetzner','Self-managed'],['OVHcloud','Managed or self-managed'],['UpCloud','Managed or self-managed'],['DigitalOcean','Managed or self-managed'],['Scaleway','Kapsule or self-managed'],['Proxmox / Morpheus','Private infrastructure']];providers.forEach(([a,b],i)=>card(256+i%3*254,365+Math.floor(i/3)*151,235,129,null,null,()=>{icon('server',18,18,20,C.green);text(18,58,a,15,C.ink,600,198,{target:'cluster-configure'});text(18,88,b,11,C.muted,400,196);}));
card(1026,252,382,303,'Already running Kubernetes?','Connect it to the same operating workspace.',()=>{text(22,106,'Import any conformant cluster or discover a managed cluster through a provider connection.',14,C.muted,400,337);button(22,217,'Import a cluster',{w:337,kind:'secondary',target:'cluster-import',icon:'plus'});});aiNote(1026,577,382,'Explore in a playground','A temporary environment helps you learn the workflows before connecting your production infrastructure.',{h:161,target:'onboarding'});
},{subtitle:'One provisioning flow, with the provider-specific choices you need.'});

screen('cluster-configure','Configure eu-prod-03',infra,'Infrastructure',()=>{
steps(256,191,1152,['Infrastructure','Configuration','Review','Provision'],1);
card(256,254,748,666,'Cluster configuration','Hetzner · self-managed Kubernetes',()=>{field(24,86,338,'Cluster name','eu-prod-03');field(385,86,339,'Environment','Production',{select:true});field(24,184,338,'Credential','hetzner-production',{select:true});field(385,184,339,'Region','Helsinki · eu-central',{select:true});field(24,282,338,'Distribution','kubeadm',{select:true});field(385,282,339,'Kubernetes version','1.35.x',{select:true});field(24,380,338,'Control plane','3 nodes · high availability',{select:true});field(385,380,339,'Worker pool','3 × 4 vCPU / 8 GiB',{select:true});text(24,482,'Advanced configuration',13,C.green,600,670);text(24,517,'Networking · SSH access · storage · labels · autoscaling',12,C.muted,400,680);button(24,589,'Review cluster',{w:211,target:'cluster-provision',icon:'arrow'});});
card(1026,254,382,391,'Estimated monthly cost','Provider list-price estimate · EUR',()=>{text(22,87,'€184.20',39,C.ink,600,337);text(22,148,'Compute',12,C.muted);text(253,148,'€162.00',13,C.ink,500);text(22,191,'Storage',12,C.muted);text(253,191,'€18.20',13,C.ink,500);text(22,234,'Load balancer',12,C.muted);text(253,234,'€4.00',13,C.ink,500);line(22,277,338);text(22,305,'Excludes variable network egress.\nPlatform fees appear separately in Billing.',12,C.muted,400,337);});aiNote(1026,667,382,'Availability recommendation','Three control-plane nodes prevent a single node failure from interrupting control-plane availability.',{h:171,target:null});
},{subtitle:'Capacity, access, and cost stay visible while you configure.'});

screen('cluster-import','Connect existing infrastructure',infra,'Infrastructure',()=>{
tabs(256,187,1152,['Install agent','Discover managed cluster']);
card(256,254,745,647,'Connect with an installation command','Run the generated command in your cluster context.',()=>{field(22,86,698,'Cluster name','existing-production');field(22,184,337,'Environment','Production',{select:true});field(382,184,338,'Access mode','Observe first',{select:true});codeBlock(22,297,698,158,['# Confirm the target context before running','kubectl config current-context','','<generated, short-lived installation command>'],{title:'Installation command · expires after 15 minutes'});pill(22,488,'Waiting for agent connection','blue');text(22,536,'Agent installation is explicit. The connected cluster will\nappear here when the handshake completes.',13,C.muted,400,695);});
card(1023,254,385,353,'Connection checklist',null,()=>{rowList(22,86,340,[{title:'Confirm cluster context',detail:'Avoid installing into the wrong cluster',icon:'server'},{title:'Review agent permissions',detail:'Cluster roles and outbound connectivity',icon:'shield'},{title:'Verify connection',detail:'Agent version and heartbeat are shown',icon:'check'}]);});
},{subtitle:'Keep your infrastructure. Add shared visibility and operating context.'});

screen('cluster-provision','Provisioning eu-prod-03',infra,'Infrastructure',()=>{
rect(256,192,1152,117,C.blueSoft,12);icon('server',281,218,25,C.blue);text(324,214,'Your cluster is taking shape.',25,C.ink,600,990);text(324,257,'Infrastructure is provisioned. Kubernetes bootstrap is in progress.',13,C.muted,400,990);
card(256,336,745,583,'Provisioning progress','Operation OP-941 · started 3 minutes ago',()=>{rowList(22,85,699,[{title:'Validate credentials and capacity',detail:'Provider connection and quotas verified',status:'Passed'},{title:'Provision networking and compute',detail:'3 control planes · 3 workers · private network',status:'Done'},{title:'Bootstrap Kubernetes',detail:'Joining worker nodes to the control plane',status:'Running',kind:'blue',icon:'spark'},{title:'Install agent and baseline',detail:'Connection, security baseline, and DNS',status:'Queued',kind:'neutral'},{title:'Verify cluster health',detail:'Wait for readiness and resource sync',status:'Queued',kind:'neutral'}]);progress(22,475,700,.58);text(22,506,'You can leave this page. The operation will continue.',12,C.muted,400,700);button(22,540,'Open operation',{kind:'secondary',w:202,target:'operation-detail',icon:'terminal'});});
card(1023,336,385,346,'Configuration',null,()=>{[['Provider','Hetzner'],['Region','Helsinki'],['Environment','Production'],['Nodes','6'],['Estimated cost','€184.20 / month']].forEach(([a,b],i)=>{text(22,87+i*46,a,12,C.muted);text(173,87+i*46,b,12,C.ink,500,190);});});
},{subtitle:'Long-running operations are durable, observable, and safe to revisit.'});

screen('cluster-overview','eu-prod-01',infra,'Infrastructure',()=>{
tabs(256,187,1152,[{label:'Overview',target:'cluster-overview'},{label:'Workloads',target:'workloads'},{label:'Nodes',target:'nodes'},{label:'Networking',target:'networking'},{label:'Storage',target:'storage'},{label:'Configuration',target:'cluster-settings'}]);
pill(256,254,'Healthy','green');text(358,260,'Production · Hetzner / Helsinki · kubeadm · 1.35.x',13,C.muted);text(1228,260,'Synced 12s ago',11,C.muted);
metric(256,310,272,'Nodes ready','12 / 12','3 control planes · 9 workers');metric(547,310,272,'CPU utilisation','43%','20.6 / 48 cores');metric(838,310,272,'Memory utilisation','61%','117 / 192 GiB');metric(1129,310,279,'Pods ready','184 / 186','2 pods waiting for rollout','amber');
card(256,461,745,294,'Cluster utilisation','Last 6 hours · CPU / memory',()=>{chart(22,85,700,169,{secondary:true});});
card(1023,461,385,294,'Operational context',null,()=>{rowList(22,77,337,[{title:'Security',detail:'2 critical findings · fixes available',status:'Review',kind:'amber',icon:'shield'},{title:'Cost',detail:'€2,810 projected this month',icon:'chart'},{title:'Agent',detail:'Connected · sync healthy',status:'Live'}]);});
aiNote(256,779,745,'A rollout is in progress','checkout is becoming ready after a reviewed memory change. Ankra is observing latency and error rate.',{h:132,target:'deployment-detail'});card(1023,779,385,132,'Infrastructure access',null,()=>{text(22,66,'Node pools, credentials, and Kubernetes config  →',12,C.green,500,339,{target:'cluster-settings'});});
},{subtitle:'Commerce production · Owned by Platform team',action:{label:'Actions',target:'operation-detail',icon:'dots'}});

screen('nodes','Nodes & capacity',infra,'Infrastructure',()=>{
tabs(256,188,1152,['Worker nodes','Node groups','Control plane','Bastion & VMs']);metric(256,254,369,'Ready nodes','12 / 12','9 workers · 3 control planes');metric(647,254,369,'Allocatable CPU','48 cores','43% requested');metric(1038,254,370,'Allocatable memory','192 GiB','61% requested');
card(256,405,1152,497,'eu-prod-01 / Worker nodes','Node lifecycle, pool membership, and workload pressure',()=>{table(22,89,1108,['NODE','POOL','CPU','MEMORY','STATE'],[['worker-01|4 vCPU · 16 GiB','general','38%','57%',{text:'Ready',kind:'green'}],['worker-02|4 vCPU · 16 GiB','general','46%','63%',{text:'Ready',kind:'green'}],['worker-03|4 vCPU · 16 GiB','general','45%','62%',{text:'Ready',kind:'green'}],['worker-04|8 vCPU · 32 GiB','compute','52%','69%',{text:'Ready',kind:'green'}]],{widths:[339,227,176,184,182],rowH:78,targets:Array(4).fill('node-detail')});});
},{subtitle:'eu-prod-01 · Capacity and lifecycle in the same view.',action:{label:'Add node group',target:'node-groups'}});

screen('node-groups','Node groups',infra,'Infrastructure',()=>{
tabs(256,188,1152,['Worker nodes','Node groups','Control plane','Bastion & VMs'],1);
card(256,254,746,642,'general / Node pool','eu-prod-01 · Hetzner',()=>{field(23,88,699,'Instance size','4 vCPU / 16 GiB',{select:true});field(23,187,337,'Minimum nodes','3');field(384,187,338,'Maximum nodes','9');field(23,286,337,'Current nodes','6');field(384,286,338,'Autoscaling','Enabled',{select:true});text(23,394,'Scheduling',16,C.ink,600);pill(23,436,'workload=general','neutral');pill(216,436,'zone=hel1','neutral');text(23,489,'Labels and taints guide workload placement. Scale-down\nrespects pod disruption budgets.',13,C.muted,400,696);button(23,572,'Review pool changes',{w:231,target:'ai-plan',icon:'arrow'});});
aiNote(1024,254,384,'Capacity recommendation','Peak demand used 5 nodes over the last week. Keep a minimum of 3 for zone resilience and allow scaling to 9.',{h:194,target:null});card(1024,473,384,300,'Projected capacity',null,()=>{chart(22,85,340,152,{seed:7});text(22,252,'6 nodes now · range 3–9',12,C.muted,400,339);});
},{subtitle:'Configure capacity, placement, scaling, and the cost envelope.'});

screen('mesh','Cluster mesh',infra,'Infrastructure',()=>{
pill(256,194,'3 connected clusters','green');pill(457,194,'Encrypted connectivity','neutral');
card(256,252,1152,490,'Your connected infrastructure','Connectivity, peer health, and cross-cluster dependencies',()=>{for(let x=20;x<1130;x+=26)for(let y=95;y<468;y+=26)ellipse(x,y,1.5,1.5,C.line);path(231,246,673,150,'M0 0L333 143L673 0M0 0H673',C.green,2,'none',{viewW:673,viewH:150});[['eu-prod-01','Helsinki · Hetzner',117,137],['onprem-01','Private cloud · Proxmox',451,316],['eu-prod-02','Stockholm · AWS',786,137]].forEach(([a,b,x,y])=>card(x,y,246,113,null,null,()=>{icon('server',17,19,21,C.green);text(51,20,a,16,C.ink,600,177);text(17,60,b,11,C.muted,400,210);pill(17,84,'Connected','green',{small:true});}));pill(442,125,'12 ms','green');pill(247,310,'18 ms','green');pill(728,310,'21 ms','green');});
card(256,766,744,146,'Network contract',null,()=>{text(22,67,'Private addressing · Explicit route advertisement · Peer access policies',13,C.muted,400,700);text(22,103,'Inspect peer connectivity  →',12,C.green,500,695,{target:'networking'});});aiNote(1022,766,386,'All peers reachable','Latency is within the configured range. No route conflicts detected.',{h:146,target:null});
},{subtitle:'Operate connected clusters as a network, with clear boundaries.'});

screen('workloads','Workloads',infra,'Infrastructure',()=>{
tabs(256,188,1152,['Deployments','Pods','StatefulSets','DaemonSets','Jobs & CronJobs','Autoscalers']);
pill(256,254,'eu-prod-01','neutral');pill(391,254,'All namespaces','neutral');pill(549,254,'Status: all','neutral');
card(256,312,1152,477,'Deployments','Resource health with the context to act',()=>{table(22,88,1108,['NAME / NAMESPACE','READY','RESTARTS','CPU / MEMORY','STATUS'],[['checkout|commerce','4 / 4','0','420m / 1.6 GiB',{text:'Available',kind:'green'}],['storefront|commerce','3 / 3','0','180m / 768 MiB',{text:'Available',kind:'green'}],['identity|core','3 / 3','0','260m / 920 MiB',{text:'Available',kind:'green'}],['analytics|data','1 / 2','3','710m / 1.2 GiB',{text:'Degraded',kind:'amber'}]],{widths:[315,147,149,293,204],rowH:75,targets:['workload-detail','workload-detail','workload-detail','workload-detail']});});
aiNote(256,813,1152,'analytics needs attention','One replica is restarting. Open the resource to inspect events and logs, or start a scoped investigation.',{h:111,target:'workload-detail'});
},{subtitle:'eu-prod-01 · A consistent explorer for every Kubernetes workload kind.'});

screen('workload-detail','analytics / Deployment',infra,'Infrastructure',()=>{
tabs(256,188,1152,['Overview','Pods','Events','Logs','YAML','Security']);pill(256,251,'Degraded · 1 / 2 ready','amber');text(471,259,'data namespace · owned by analytics stack',12,C.muted);
metric(256,307,368,'Ready replicas','1 / 2','1 replica is restarting','amber');metric(647,307,368,'CPU','710m','Limit: 2 cores');metric(1038,307,370,'Memory','1.2 GiB','Limit: 1 GiB per replica','amber');
card(256,458,746,302,'Pods',null,()=>{table(22,86,700,['POD','RESTARTS','STATE'],[['analytics-6b5c4-7h8x2','0',{text:'Running',kind:'green'}],['analytics-6b5c4-9m4q1','3',{text:'CrashLoop',kind:'amber'}]],{widths:[343,145,212],rowH:72,targets:['pod-detail','pod-detail']});});
card(1024,458,384,302,'Resource context',null,()=>{[['Namespace','data'],['Stack','analytics'],['Image','analytics:v1.9.2'],['Owner','Data platform'],['Updated','18 minutes ago']].forEach(([a,b],i)=>{text(22,81+i*40,a,11,C.muted);text(162,81+i*40,b,12,C.ink,500,200)});});aiNote(256,784,1152,'Investigate with resource context','Inspect recent events, compare rollout revisions, and correlate metrics without losing the selected resource.',{h:131,target:'ai-investigation'});
},{subtitle:'eu-prod-01 / data · Resource details, not a context switch.',action:{label:'Investigate',target:'ai-investigation',icon:'spark'}});
}
