From debdf609d33e8fee8431f7d85b37d326eb975614 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 18 Aug 2026 23:10:51 +0200 Subject: [PATCH] Bound fission input before inference --- crates/ghostlight-dungeon/src/compiler.rs | 67 ++++++++++++++----- .../{index-CA3oKXnL.js => index-CGgopXvh.js} | 4 +- web/dist/index.html | 6 +- web/index.html | 4 +- web/src/main.ts | 8 ++- 5 files changed, 63 insertions(+), 26 deletions(-) rename web/dist/assets/{index-CA3oKXnL.js => index-CGgopXvh.js} (94%) diff --git a/crates/ghostlight-dungeon/src/compiler.rs b/crates/ghostlight-dungeon/src/compiler.rs index d1522bc..b85c036 100644 --- a/crates/ghostlight-dungeon/src/compiler.rs +++ b/crates/ghostlight-dungeon/src/compiler.rs @@ -555,28 +555,11 @@ impl WorldCompiler { Vec, Vec, )> { + let requested = validate_fission_request(&request)?; let parent = campaign .gestalts .get(&request.parent_gestalt_id) .ok_or_else(|| anyhow!("fission parent is unknown"))?; - let requested: BTreeSet<_> = request - .requested_partition_values - .iter() - .map(|value| value.trim().to_ascii_lowercase()) - .collect(); - if request.reason.trim().is_empty() - || requested.is_empty() - || requested.len() != request.requested_partition_values.len() - || requested.contains("other/unknown") - || request - .requested_partition_values - .iter() - .any(|value| value.trim().is_empty()) - { - return Err(anyhow!( - "fission request needs distinct named cuts and a reason" - )); - } let subject = serde_json::json!({ "request":request, "parent":parent, @@ -1217,6 +1200,31 @@ fn validate_user_text(label: &str, value: &str, max_chars: usize) -> Result<()> Ok(()) } +fn validate_fission_request(request: &GestaltFissionRequest) -> Result> { + validate_user_text("fission reason", &request.reason, 500)?; + if request.requested_partition_values.is_empty() + || request.requested_partition_values.len() > 16 + { + return Err(anyhow!("fission request needs between 1 and 16 named cuts")); + } + for value in &request.requested_partition_values { + validate_user_text("fission cut", value, 160)?; + } + let requested: BTreeSet<_> = request + .requested_partition_values + .iter() + .map(|value| value.trim().to_ascii_lowercase()) + .collect(); + if requested.len() != request.requested_partition_values.len() + || requested.contains("other/unknown") + { + return Err(anyhow!( + "fission request needs distinct named cuts and reserves other/unknown for the compiler" + )); + } + Ok(requested) +} + fn global_agency_queries(start: &CustomStart) -> Vec { let horizon = start.when.chars().take(120).collect::(); vec![ @@ -2295,6 +2303,29 @@ mod tests { assert!(validate_user_text("field", "hello\0world", 20).is_err()); assert!(validate_user_text("field", "hello\nworld", 20).is_ok()); } + + #[test] + fn fission_text_is_bounded_before_retrieval_or_inference() { + let mut request = GestaltFissionRequest { + parent_gestalt_id: "population".into(), + partition_axis: AgencyAxis::Geography, + requested_partition_values: vec!["harbor".into(), "inland".into()], + reason: "The population is dispersing along established routes.".into(), + }; + assert!(validate_fission_request(&request).is_ok()); + + request.requested_partition_values = (0..17).map(|index| format!("cut-{index}")).collect(); + assert!(validate_fission_request(&request).is_err()); + request.requested_partition_values = vec!["x".repeat(161)]; + assert!(validate_fission_request(&request).is_err()); + request.requested_partition_values = vec!["Harbor".into(), "harbor".into()]; + assert!(validate_fission_request(&request).is_err()); + request.requested_partition_values = vec!["other/unknown".into()]; + assert!(validate_fission_request(&request).is_err()); + request.requested_partition_values = vec!["harbor".into()]; + request.reason = "x".repeat(501); + assert!(validate_fission_request(&request).is_err()); + } use crate::{domain::SourceWitness, model::ModelPort, vault::FixtureVault}; use async_trait::async_trait; use sha2::Digest; diff --git a/web/dist/assets/index-CA3oKXnL.js b/web/dist/assets/index-CGgopXvh.js similarity index 94% rename from web/dist/assets/index-CA3oKXnL.js rename to web/dist/assets/index-CGgopXvh.js index 95f36d1..d75f710 100644 --- a/web/dist/assets/index-CA3oKXnL.js +++ b/web/dist/assets/index-CGgopXvh.js @@ -131,7 +131,7 @@ void main() { color += clamp(lines, 0.0, 1.7); outColor = vec4(color, 1.0); -}`,nt=new Set(["gamecult.fields.splats.v1","gamecult.fields.gravity.v1","gamecult.fields.objects.v1"]),Nt={pluginId:"fields.surface",capabilities:["field.surface2d","gravity.surface","field.scalar","field.vector","field.objects"],componentKinds:["field.surface2d","gravity.surface"],schemas:[...nt],normalizeDocument:Pe,renderComponent:Dt};function Dt(e,t,n,i,o,a){const l=document.createElement("canvas");l.className="cultui-gravity-surface",e.id&&(l.id=e.id),l.setAttribute("role","img"),l.setAttribute("aria-label",cn(t.label,"gravity surface")),l.style.display="block",l.style.width="100%",l.style.height="100%",l.style.pointerEvents="none",a.applyGeneratedLayout(l,n,i);let s=!1;const f={},c=()=>Ut(l,t,f,a.resolveAssetUrl),r=()=>{!l.isConnected||s||(s=!0,requestAnimationFrame(()=>{s=!1,l.isConnected&&c()}))};l.addEventListener("cultui:asset-loaded",r);let d=0,u;const h=()=>{d&&window.clearInterval(d),u?.disconnect(),l.removeEventListener("cultui:asset-loaded",r)},y=()=>{if(!l.isConnected){h();return}Bt(e,t,o,a.providerId,f).then(x=>{x&&l.isConnected&&r()}).catch(x=>{f.lastError=x instanceof Error?x.message:String(x)})};typeof ResizeObserver<"u"&&(u=new ResizeObserver(r),u.observe(l)),r();const b=Math.max(33,Math.min(1e3,ln(t.stateRefreshMs,100)));return d=window.setInterval(y,b),queueMicrotask(y),window.setTimeout(r,300),window.setTimeout(r,1e3),l}async function Bt(e,t,n,i,o){if(o.loading)return!1;const a=[Ie(e,t,"renderSplats","renderSplatsDocumentId","renderSplatsSchemaId"),Ie(e,t,"gravity","gravityDocumentId","gravitySchemaId"),Ie(e,t,"objects","objectsDocumentId","objectsSchemaId")].filter(l=>!!l?.documentId);if(a.length===0)return!1;o.loading=!0;try{let l=!1;for(const s of a){const f=await n.documentResolver?.(s,e);let c=Se(Pe(f?.schemaId||s.schemaId,f?.document));if(Object.keys(c).length===0&&(c=Se(Pe(s.schemaId,await qt(s,i||n.provider?.providerId)))),Object.keys(c).length===0)continue;const r=s.slotId==="renderSplats"?"renderSplats":s.slotId==="gravity"?"gravity":"objects",d=$e(o[r]?.frameId,-1),u=$e(c.frameId,d);o[r]=c,l||=u!==d}return o.lastLoadedAt=Date.now(),l}finally{o.loading=!1}}async function qt(e,t){if(typeof fetch!="function"||typeof window>"u"||!t)return;const n=new URLSearchParams({documentId:e.documentId});e.schemaId&&n.set("schemaId",e.schemaId),e.slotId&&n.set("slotId",e.slotId);const i=await fetch(`/eir/document/${encodeURIComponent(t)}?${n.toString()}`,{cache:"no-store",headers:{Accept:"application/json"}});if(i.ok)return Se(await i.json()).document}function Ie(e,t,n,i,o){const a=(e.embeddedDocuments||[]).find(s=>String(s?.slotId||"")===n),l=k(t[i],a?.documentId);if(l)return{documentId:l,schemaId:k(t[o],a?.schemaId),presentationKind:k(a?.presentationKind)||"data",slotId:n}}function Pe(e,t){const n=Array.isArray(t)?t:void 0,i=n?n[0]:t?.schema,o=String(e||i||"");return!n||!nt.has(o)?t:o==="gamecult.fields.splats.v1"?Zt(n):o==="gamecult.fields.gravity.v1"?Qt(n):en(n)}function Ut(e,t,n,i){const o=e.getBoundingClientRect(),a=Math.max(1,Math.floor(o.width||e.clientWidth||1)),l=Math.max(1,Math.floor(o.height||e.clientHeight||1)),s=Math.max(1,Math.min(2,window.devicePixelRatio||1)),f=Math.max(1,Math.floor(a*s)),c=Math.max(1,Math.floor(l*s));(e.width!==f||e.height!==c)&&(e.width=f,e.height=c);const r=e.getContext("2d");if(!r)return;r.setTransform(s,0,0,s,0,0),r.clearRect(0,0,a,l);const d=Jt(Vt(t),a,l),u=ot(n?.gravity),h=Yt(n?.gravity)||Xt(k(t.bodies,"")),y=Ht(n?.objects)||jt(k(t.objects,""));St(r,t,u,h,d,a,l,n?.renderSplats)||Wt(r,t,a,l,"field.surface2d requires WebGL2 float render targets"),Ot(r,h,t,d,a,l,i),Gt(r,y,t,d,a,l,i)}function Wt(e,t,n,i,o){e.save(),e.fillStyle=k(t.failureBackground,"rgba(0, 0, 0, 0.72)"),e.fillRect(0,0,n,i),e.font=k(t.failureFont,"700 13px Cascadia Mono, Consolas, monospace"),e.fillStyle=k(t.failureColor,"rgba(255, 184, 79, 0.95)"),e.fillText(o,16,28),e.restore()}function Ot(e,t,n,i,o,a,l){for(const s of t){const f=rt(i,s.x,s.y,o,a),c=Math.max(18,Math.min(190,s.radius/Math.max(1,i.maxX-i.minX)*o*.32)),r=l(s.icon),d=s.kind.toLowerCase().includes("sun")?Math.max(E(n.sunIconMinPx,34),c*E(n.sunIconScale,.72)):Math.max(E(n.bodyIconMinPx,24),c*E(n.bodyIconScale,.48)),u=s.iconSize>0?s.iconSize:d;r&&zt(e,r,f.x,f.y,u,.92),s.key&&it(e,n,s.key.replace(/^local\./,""),f.x+c*.44,f.y-c*.48,k(n.bodyLabelColor,"rgba(226, 244, 255, 0.82)"))}}const we=new Map;function zt(e,t,n,i,o,a){let l=we.get(t);l||(l=new Image,l.decoding="async",l.onload=()=>requestAnimationFrame(()=>{e.canvas.dispatchEvent(new CustomEvent("cultui:asset-loaded"))}),l.src=t,we.set(t,l)),!(!l.complete||l.naturalWidth===0)&&(e.save(),e.globalAlpha=a,e.drawImage(l,n-o/2,i-o/2,o,o),e.restore())}function Gt(e,t,n,i,o,a,l){for(const s of t){const f=rt(i,s.x,s.y,o,a);if(f.x<-40||f.x>o+40||f.y<-40||f.y>a+40)continue;const c=s.kind.toLowerCase().includes("station")?E(n.stationIconSizePx,34):s.controlled?E(n.shipIconSizePx,22):E(n.remoteShipIconSizePx,18),r=Kt(n,s.faction,s.controlled,s.visibility),d=l(s.icon);e.save(),e.globalAlpha=Math.max(.25,Math.min(1,s.visibility)),e.translate(f.x,f.y);const u=Math.atan2(s.directionY,s.directionX)+Math.PI/2;if(s.kind.toLowerCase().includes("ship")&&e.rotate(u),d){const h=we.get(d);if(h)h.complete&&h.naturalWidth>0&&e.drawImage(h,-c/2,-c/2,c,c);else{const y=new Image;y.decoding="async",y.onload=()=>e.canvas.dispatchEvent(new CustomEvent("cultui:asset-loaded")),y.src=d,we.set(d,y)}}e.restore(),it(e,n,s.label,f.x+c*.55,f.y-c*.45,r)}}function it(e,t,n,i,o,a){n&&(e.save(),e.font=k(t.objectLabelFont,"700 12px Ubuntu, system-ui, sans-serif"),e.textBaseline="middle",e.lineWidth=E(t.objectLabelStrokeWidth,3),e.strokeStyle=k(t.objectLabelStroke,"rgba(0, 0, 0, 0.72)"),e.fillStyle=a,e.strokeText(n,i,o),e.fillText(n,i,o),e.restore())}function Kt(e,t,n,i){const o=Math.max(.25,Math.min(1,i));if(n)return pe(k(e.objectControlledColor,"rgba(122, 240, 255, {alpha})"),o);const a=t.toLowerCase();return a.includes("raider")?pe(k(e.objectRaiderColor,"rgba(255, 143, 74, {alpha})"),o):a.includes("neutral")?pe(k(e.objectNeutralColor,"rgba(232, 232, 224, {alpha})"),o):pe(k(e.objectDefaultColor,"rgba(214, 244, 255, {alpha})"),o)}function pe(e,t){return e.replaceAll("{alpha}",String(t))}function Xt(e){return e.split(";").map(t=>t.trim()).filter(Boolean).map(t=>{const n=t.split("|");return{key:n[0]??"",kind:n[1]??"",x:Number(n[2])||0,y:Number(n[3])||0,radius:Math.max(1,Number(n[4])||1),depth:Number(n[5])||0,exponent:Number(n[6])||1,waveRadius:Number(n[7])||0,waveDepth:Number(n[8])||0,waveSpeed:Number(n[9])||0,icon:n[10]??"",iconSize:Number(n[12])||0,tint:n[11]??""}})}function jt(e){return e.split(";").map(t=>t.trim()).filter(Boolean).map(t=>{const n=t.split("|");return{key:n[0]??"",kind:n[1]??"",label:n[2]??"",x:Number(n[3])||0,y:Number(n[4])||0,directionX:Number(n[5])||0,directionY:Number(n[6])||1,faction:n[7]??"",controlled:n[8]==="1"||n[8]==="true",visibility:Number(n[9])||1,icon:n[10]??""}})}function Yt(e){const t=Array.isArray(e?.gravityInfluences)?e.gravityInfluences:[],n=Array.isArray(e?.bodies)?e.bodies:[];if(t.length===0&&n.length===0)return;const i=new Map;for(const o of n){const a=k(o.bodyKey,o.name,"");a&&i.set(a,o)}return(t.length>0?t:n).map(o=>{const a=k(o.bodyKey,o.name,"body"),l=i.get(a),s=k(o.kind,"Body");return{key:a,kind:s,x:E(o.x,0),y:E(o.y,0),radius:Math.max(1,E(o.radius,80)),depth:E(o.gravityDepth,0),exponent:E(o.gravityDepthExponent,1),waveRadius:E(o.waveRadius,0),waveDepth:E(o.waveDepth,0),waveSpeed:E(o.waveSpeed,0),icon:Le(o.iconAsset)||Le(l?.iconAsset),iconSize:E(l?.iconSize,E(o.iconSize,0)),tint:""}})}function Ht(e){const t=Array.isArray(e?.objects)?e.objects:[];if(t.length!==0)return t.map(n=>{const i=k(n.kind,"object");return{key:k(n.entityKey,String(n.entityIndex??""),"object"),kind:i,label:k(n.displayName,n.entityKey,"object"),x:E(n.x,0),y:E(n.y,0),directionX:E(n.directionX,1),directionY:E(n.directionY,0),faction:k(n.factionKey,""),controlled:dn(n.controlled),visibility:E(n.visibility,1),icon:Le(n.iconAsset)}})}function Le(e){const t=ot(e);return k(t.uri,"")}function Vt(e){const t=Math.max(1,E(e.viewRadius,Math.max(1200,E(e.terrainRadius,1200))));return{minX:E(e.minX,-t),minY:E(e.minY,-t),maxX:E(e.maxX,t),maxY:E(e.maxY,t)}}function Jt(e,t,n){const i=Math.max(1e-4,e.maxX-e.minX),o=Math.max(1e-4,e.maxY-e.minY),a=Math.max(1e-4,t/Math.max(1,n)),l=i/o,s=(e.minX+e.maxX)*.5,f=(e.minY+e.maxY)*.5;if(a>l){const r=o*a;return{minX:s-r*.5,maxX:s+r*.5,minY:e.minY,maxY:e.maxY}}const c=i/a;return{minX:e.minX,maxX:e.maxX,minY:f-c*.5,maxY:f+c*.5}}function rt(e,t,n,i,o){return{x:(t-e.minX)/Math.max(1,e.maxX-e.minX)*i,y:(n-e.minY)/Math.max(1,e.maxY-e.minY)*o}}function Zt(e){const t=N(e[9]);return{schema:e[0],frameId:e[1],publishedAtUtc:e[2],simulationTimeSeconds:e[3],runId:e[4],zoneIndex:e[5],zoneName:e[6],viewport:De(e[7]),layers:N(e[8]).map(tn),splats:{count:t[0]??0,centerX:t[1]||[],centerY:t[2]||[],halfExtentX:t[3]||[],halfExtentY:t[4]||[],rotationCos:t[5]||[],rotationSin:t[6]||[],channel:t[7]||[],falloff:t[8]||[],valueR:t[9]||[],valueG:t[10]||[],valueB:t[11]||[],valueA:t[12]||[],sourceKey:t[13]||[],layerIndex:t[14]||[],sourceKind:t[15]||[],frequencyX:t[16]||[],frequencyY:t[17]||[],phaseX:t[18]||[],phaseY:t[19]||[],animationSpeed:t[20]||[],sourceFlags:t[21]||[]}}}function Qt(e){return{schema:e[0],frameId:e[1],publishedAtUtc:e[2],simulationTimeSeconds:e[3],runId:e[4],zoneIndex:e[5],zoneName:e[6],viewport:De(e[7]),gravityInfluences:N(e[8]).map(nn),bodies:N(e[9]).map(rn),terrainRadius:e[10],terrainDepth:e[11],terrainDepthExponent:e[12],terrainWaveFrequency:e[13]}}function en(e){return{schema:e[0],frameId:e[1],publishedAtUtc:e[2],simulationTimeSeconds:e[3],runId:e[4],zoneIndex:e[5],zoneName:e[6],currentEntityKey:e[7],viewport:De(e[8]),controlledEntityIndices:N(e[9]),objects:N(e[10]).map(on)}}function De(e){const t=N(e);return t.length?{minX:t[0],minY:t[1],maxX:t[2],maxY:t[3]}:e}function tn(e){const t=N(e);return t.length?{layerKey:t[0],displayName:t[1],channel:t[2],blendMode:t[3],graphicsFormat:t[4],clearBeforeDraw:t[5],clearR:t[6],clearG:t[7],clearB:t[8],clearA:t[9]}:e}function nn(e){const t=N(e);return t.length?{bodyKey:t[0],orbitKey:t[1],kind:t[2],x:t[3],y:t[4],radius:t[5],gravityDepth:t[6],gravityDepthExponent:t[7],waveRadius:t[8],waveDepth:t[9],waveSpeed:t[10]}:e}function rn(e){const t=N(e);return t.length?{bodyKey:t[0],orbitKey:t[1],name:t[2],kind:t[3],x:t[4],y:t[5],radius:t[6],isAsteroidBelt:t[7],body:t[8],iconAsset:Be(t[9])}:e}function on(e){const t=N(e);return t.length?{entityIndex:t[0],entityKey:t[1],displayName:t[2],kind:t[3],factionKey:t[4],x:t[5],y:t[6],z:t[7],directionX:t[8],directionY:t[9],velocityX:t[10],velocityY:t[11],controlled:t[12],targetEntityIndex:t[13],isActive:t[14],visibility:t[15],status:an(t[16]),inventory:N(t[17]).map(sn),iconAsset:Be(t[18])}:e}function an(e){const t=N(e);return t.length?{hull:t[0],shield:t[1],heat:t[2]}:e||{}}function sn(e){const t=N(e);return t.length?{source:t[0],itemKey:t[1],quantity:t[2],quality:t[3],durability:t[4],enabled:t[5],sourceIndex:t[6],x:t[7],y:t[8],iconAsset:Be(t[9])}:e}function Be(e){const t=N(e);return t.length?{assetKey:t[0],kind:t[1],uri:t[2],transport:t[3],contentHash:t[4],mimeType:t[5],metadata:t[6]||{}}:e||{}}function N(e){return Array.isArray(e)?e:[]}function Se(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function k(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function cn(e,t){return typeof e=="string"&&e?e:t}function ln(e,t){const n=Number(e);return Number.isFinite(n)&&n>0?Math.floor(n):t}function $e(e,t){const n=Number(e);return Number.isFinite(n)?n:t}const ot=Se,E=$e;function dn(e){return typeof e=="boolean"?e:typeof e=="number"?e!==0:typeof e=="string"&&["1","true","yes","on"].includes(e.trim().toLowerCase())}const un=[Nt],fn={"--bg":"#020909","--bg-top":"#020909","--bg-mid":"#020909","--bg-bottom":"#020909","--shell-top":"#010707","--shell-bottom":"#010707","--panel":"#071918","--panel-2":"#0a2423","--line":"rgba(103, 240, 228, 0.28)","--line-deep":"rgba(103, 240, 228, 0.18)","--text":"#e7f1f1","--text-bright":"#e7f1f1","--quiet":"#8ba5a3","--accent":"#ffb84f","--accent-strong":"#ffb84f","--corner-accent":"#ffb84f","--cyan":"#8efcff","--shadow":"rgba(0, 0, 0, 0.35)","--pixel-grid":"rgba(142, 252, 255, 0.04)","--border-width":"1px","--border-bottom-width":"1px","--corner-accent-size":"0","--font-body":'"M PLUS 1", "Ubuntu Sans", Ubuntu, "Noto Sans JP", system-ui, sans-serif',"--font-title":'"Montserrat", "Zen Kaku Gothic New", "M PLUS 1", "Ubuntu Sans", system-ui, sans-serif',"--font-mono":'"Ubuntu Sans Mono", "M PLUS 1 Code", "Cascadia Mono", Consolas, monospace'};let he,at=qe(void 0),se,z={};const Ye=new WeakMap;function st(e,t,n={}){if(Ye.get(t)?.dispose(),se=e,z=n,at=qe(e.surface?.styles),globalThis.__eveCurrentMesh=e.mesh,Rn(e.surface?.styles,n.body??document.body),n.body&&(n.body.dataset.provider=e.providerId||n.provider?.providerId||""),n.statusElement&&(n.statusElement.textContent=`${e.title||e.surface?.title||"surface"}${n.source?` (${n.source})`:""}`),e.surface?.root){if(t.replaceChildren(L(e.surface.root,n)),n.stateBindingResolver){const i=new pn(e,t,n);Ye.set(t,i),i.start()}}else t.replaceChildren(H("No surface root"));return t}function mn(e,t,n){const i=t.targetProp.split(".").filter(Boolean);if(i.length===0)throw new Error("Eve state binding targetProp must not be empty.");e.props||={};let o=e.props;for(const a of i.slice(0,-1)){const l=o[a];(!l||typeof l!="object"||Array.isArray(l))&&(o[a]={}),o=o[a]}o[i[i.length-1]]=n}class pn{surface;host;options;disposed=!1;unsubscribers=[];constructor(t,n,i){this.surface=t,this.host=n,this.options=i}async start(){const t=this.options.stateBindingResolver,n=this.surface.surface?.root;if(!(!t||!n))for(const i of ct(n))for(const o of i.stateBindings||[]){if(this.disposed)return;const a=await t(o,i);if(!a||this.disposed)continue;const l=s=>{this.disposed||(mn(i,o,s),this.renderCanonicalProjection())};if(l(await a.latest()),this.disposed)return;this.unsubscribers.push(a.watch(l))}}dispose(){this.disposed=!0;for(const t of this.unsubscribers.splice(0))t()}renderCanonicalProjection(){const t=this.surface.surface?.root;t&&this.host.replaceChildren(L(t,this.options))}}function*ct(e){yield e;for(const t of e.children||[])yield*ct(t)}function L(e,t=z){const n=e.kind||"panel",i=w(e.props),o=w(e.layout),a=w(e.style),l=e.children||[],s=e.embeddedDocuments||[];if(n==="surface"||n==="cockpit"||n==="dashboard"){const r=m("section","cultui-surface-root eve-surface");S(r,e),typeof o.direction=="string"?r.dataset.direction=o.direction:typeof i.layout=="object"&&i.layout&&typeof i.layout.direction=="string"&&(r.dataset.direction=String(i.layout.direction)),n!=="surface"&&(r.dataset.surfaceKind=n),_(r,o,a);for(const d of l)r.append(L(d,t));return r}if(n==="column"||n==="row"||n==="form"||n==="rail"){const r=m("div",`cultui-partition eve-${n}`);S(r,e),r.dataset.direction=n==="row"||n==="rail"?"horizontal":"vertical",n==="rail"&&(r.dataset.overflow="x"),ye(r,{...o,...i}),_(r,o,a);for(const d of l)r.append(L(d,t));return r}if(n==="grid"){const r=m("section","cultui-grid"),d=q(i.columns,0);d>0?r.style.gridTemplateColumns=`repeat(${d}, minmax(0, 1fr))`:typeof i.columns=="string"&&(r.style.gridTemplateColumns=i.columns);const u=q(i.rows,0);u>0&&(r.style.gridTemplateRows=`repeat(${u}, minmax(0, auto))`),_(r,o,a);for(const h of l)r.append(L(h,t));return r}if(n==="partition"){const r=m("section",`cultui-partition split-${g(i.split,"none")}`);S(r,e),ye(r,i),_(r,o,a),r.style.minWidth="0",g(i.split,"none")==="x"&&!p(i.flexWrap,o.flexWrap,"")&&(r.style.flexWrap="wrap"),typeof i.role=="string"&&(r.dataset.role=i.role);for(const d of l)r.append(L(d,t));return r}if(n==="input.binding-map")return An(e,i,t);if(n==="inventory.drag_session")return wn(e,i,o,a);if(n==="inventory.grid")return Sn(e,i,o,a,t);if(n==="inventory.item")return _n(e,i,o,a);const f=(t.pluginAdapters||un).find(r=>r.componentKinds.includes(n));if(f?.renderComponent)return f.renderComponent(e,i,o,a,t,{applyGeneratedLayout:_,providerId:se?.providerId||t.provider?.providerId,resolveAssetUrl:ae});if(n==="world.scene3d"||n==="world.scene2d")return gn(e,i,o,a,t);if(n==="image.background"){const r=m("div","cultui-background"),d=ae(p(i.src,i.assetUri,i.assetRef,""));return d&&(r.style.backgroundImage=`url("${d}")`),r.setAttribute("aria-label",g(i.label,"background")),r}if(n==="image.sprite"){const r=m("figure",`cultui-sprite ${g(i.slot,"center")}`);S(r,e);const d=ae(p(i.src,i.assetUri,i.assetRef,""));if(d){const u=m("img");u.src=d,u.alt=g(i.alt,g(i.actor,g(i.label,""))),r.append(u)}return r}if(n==="avatar"){const r=m("figure","cultui-avatar-card");S(r,e);const d=ae(p(i.src,i.assetUri,i.assetRef,""));if(d){const b=m("img");b.src=d,b.alt=g(i.alt,g(i.text,g(i.label,""))),r.append(b)}else r.append(m("div","cultui-avatar-fallback",On(p(i.text,i.label,i.actor,"?"))));const u=p(i.text,i.label,i.actor,"");u&&r.append(m("figcaption","cultui-avatar-name",u));const h=p(i.status,"");h&&r.append(m("div","cultui-avatar-status",h));const y=p(i.detail,"");return y&&r.append(m("div","cultui-avatar-detail",y)),r}if(n==="pane"||n==="panel"){const r=m("section","pane cultui-pane");S(r,e);const d=g(i.span,"");d&&(r.dataset.span=d);const u=g(i.density,"");u&&(r.dataset.density=u);const h=g(i.title,e.text||"");h&&r.append(m("h2","",h));for(const y of l)r.append(L(y,t));return r}if(n==="list"||n.endsWith(".roster")){const r=m("section","cultui-list");S(r,e),r.dataset.componentKind=n;const d=g(i.title,"");d&&r.append(m("h3","cultui-list-title",d));for(const[u,h]of Un(i.items).entries())r.append(L({id:`${e.id||"list"}-item-${u}`,kind:"list.item",props:{...h}},t));for(const u of l)r.append(L(u,t));return r}if(n==="list.item"||n.endsWith(".item")){const r=lt(e),d=m("article","cultui-list-item");S(d,e),d.dataset.componentKind=n;const u=m("div","cultui-list-item-heading");if(u.append(m("strong","cultui-list-item-label",r.label)),r.status&&u.append(m("span","cultui-list-item-status",r.status)),d.append(u),r.detail&&d.append(m("div","cultui-list-item-detail",r.detail)),r.badges.length){const h=m("div","cultui-list-item-badges");for(const y of r.badges)h.append(m("span","cultui-list-item-badge",y));d.append(h)}for(const h of l)d.append(L(h,t));return d}if(n==="bar"){const r=m("div","cultui-meter");S(r,e);const d=g(i.label,""),u=g(i.value,"");if(d||u){const b=m("div","cultui-meter-head");b.append(m("span","",d)),b.append(m("strong","",u)),r.append(b)}const h=m("div","cultui-meter-track"),y=m("span","cultui-meter-fill");return y.style.width=`${et(i.percent)}%`,h.append(y),r.append(h),r}if(n==="card"){const r=Ze(i,e),d=r?m("button","card cultui-card cultui-card-button"):m("article","card cultui-card");S(d,e),_(d,o,a),d instanceof HTMLButtonElement&&(d.type="button");const u=g(i.title,e.text||"");u&&d.append(m("div","card-title",u));for(const h of l)d.append(L(h,t));return r&&Qe(d,e,r,i,t),d}if(n==="control.button"){const r=m("button","cultui-button eve-control-button",g(i.label,"Action"));return S(r,e),r.type="button",_(r,o,a),Qe(r,e,Ze(i,e),i,t),r}if(n==="control.popup"){const r=m("button","cultui-button eve-control-popup",g(i.label,"Open"));return S(r,e),r.type="button",_(r,o,a),r.addEventListener("click",d=>{In(e,t,r,d.clientX,d.clientY)}),r}if(n==="text.dialogue"||n==="text"||n==="text.title"||n==="text.subtitle"||n==="label"){const r=m("div",Mn(n,i),g(i.value,g(i.text,e.text||"")));return S(r,e),ye(r,i),_(r,o,a),r}if(n==="metric"){const r=m("dl","metric cultui-reactive-metric eve-metric");return S(r,e),_(r,o,a),r.append(m("dt","",g(i.label,"Metric"))),r.append(m("dd","metric-value",g(i.value,""))),r}if(n==="progress"){const r=m("div","cultui-meter eve-progress");S(r,e),_(r,o,a);const d=g(i.label,""),u=g(i.value,""),h=Number(i.min??0),y=Number(i.max??1),b=Number(i.value??0),x=Number.isFinite(b)&&Number.isFinite(h)&&Number.isFinite(y)&&y!==h?(b-h)/(y-h)*100:et(i.percent);if(d||u){const D=m("div","cultui-meter-head");D.append(m("span","",d)),D.append(m("strong","",u)),r.append(D)}const T=m("div","cultui-meter-track"),C=m("span","cultui-meter-fill");return C.style.width=`${Math.max(0,Math.min(100,x))}%`,T.append(C),r.append(T),r}if(n==="modal"){const r=m("section","cultui-modal-surface");S(r,e),_(r,o,a);const d=g(i.title,"");d&&r.append(m("h2","cultui-modal-surface-title",d));for(const u of l)r.append(L(u,t));return r}if(n==="options"){const r=m("section","cultui-options");S(r,e),_(r,o,a);const d=g(i.label,"");d&&r.append(m("h3","cultui-list-title",d));for(const u of l)r.append(L(u,t));return l.length===0&&r.append(H("waiting for options")),r}if(n==="image.preview"){const r=m("figure","cultui-image-preview");S(r,e);const d=m("div","cultui-image-frame"),u=ae(p(i.src,i.assetUri,i.assetRef,""));if(u){const h=m("img");h.src=u,h.alt=g(i.label,""),h.style.imageRendering=g(i.imageRendering,"auto"),i.zoom!==void 0&&(h.style.transform=`scale(${i.zoom})`,h.style.transformOrigin=g(i.crop,"50% 50%")),d.append(h)}else d.append(m("span","",g(i.label,"image")));return r.append(d),i.label&&r.append(m("figcaption","",String(i.label))),r}if(n==="canvas.preview"||n==="canvas.editor"){const r=m("div",`cultui-canvas-placeholder ${n==="canvas.editor"?"editor":"preview"}`);return S(r,e),r.append(m("div","viz-label",g(i.label,"Canvas"))),r.append(m("div","cultui-canvas-grid",i.state==="empty"?"waiting for pixels":g(i.state,""))),r}if(n==="surface.slot"){const r=m("section","cultui-embedded-slot");S(r,e),_(r,o,a),r.dataset.slotId=g(i.slotId,g(s[0]?.slotId,"")),r.dataset.documentId=g(i.documentId,g(s[0]?.documentId,"")),r.dataset.schemaId=g(i.schemaId,g(s[0]?.schemaId,"")),r.dataset.presentationKind=g(i.presentationKind,g(s[0]?.presentationKind,""));const d=s.map(h=>w(h.surface)).find(h=>w(h.root).kind||h.root),u=i.modal===!0||r.dataset.presentationKind.includes("modal");if((d||r.dataset.documentId)&&u){const h=m("button","cultui-button cultui-modal-trigger",g(i.label,r.dataset.slotId||"Configure"));h.type="button",h.addEventListener("click",()=>ft(Me(e,t),t)),r.append(h)}else if(d||r.dataset.documentId){const h=m("div","cultui-embedded-slot-body");h.append(m("div","detail","materializing surface")),r.append(h),Me(e,t).then(y=>{h.replaceChildren(y?.root?L(y.root,t):H("Embedded surface unavailable"))}).catch(y=>{h.replaceChildren(H(`Embedded surface failed: ${y instanceof Error?y.message:String(y)}`))})}else r.append(m("div","detail",r.dataset.presentationKind||r.dataset.slotId||"embedded surface"));return r}if(n==="control.slider")return Pn(i,l,t);if(n==="control.toggle"){const r=m("label","toggle-row cultui-toggle");return S(r,e),r.append(m("span","field-control",i.value?"on":"off")),r.append(m("span","toggle-copy",g(i.label,"Toggle"))),r}if(n==="input.number"||n==="input.select"||n==="control.range"||n==="control.input.text"||n==="control.select"){const r=m("label","field cultui-field");return S(r,e),ye(r,i),_(r,o,a),r.append(m("span","field-label",g(i.label,""))),r.append(m("span","field-control cultui-field-value",i.value===void 0?"":String(i.value))),r}if(n==="color.swatch"){const r=m("div","paint-swatch cultui-swatch");return S(r,e),r.style.background=g(i.value,g(i.color,"currentColor")),r.title=g(i.label,"Color"),r}const c=m("section","pane");S(c,e),c.append(m("h2","",n));for(const r of l)c.append(L(r,t));return c}function lt(e){const t=w(e.props);return{label:p(t.label,t.title,t.displayName,e.text,e.kind,"item"),status:p(t.status,t.state,""),detail:p(t.detail,t.phase,t.repoName,""),badges:Array.isArray(t.badges)?t.badges.map(n=>String(n).trim()).filter(Boolean):p(t.badges,"").split(",").map(n=>n.trim()).filter(Boolean)}}function _(e,t,n={}){const i=p(t.display,"");i&&(e.style.display=i);const o=p(t.direction,"");o&&(e.style.flexDirection=o==="horizontal"?"row":o==="vertical"?"column":o);const a=p(t.flexWrap,"");a&&(e.style.flexWrap=a);const l=p(t.gridTemplateColumns,"");l&&(e.style.gridTemplateColumns=l);const s=p(t.gridTemplateRows,"");s&&(e.style.gridTemplateRows=s);const f=p(t.gridTemplateAreas,"");f&&(e.style.gridTemplateAreas=f);const c=p(t.gridArea,"");c&&(e.style.gridArea=c);const r=p(t.placeItems,"");r&&(e.style.placeItems=r),M(e,"gap",p(t.gap,"")),M(e,"padding",p(t.padding,"")),M(e,"margin",p(t.margin,"")),M(e,"top",p(t.top,"")),M(e,"right",p(t.right,"")),M(e,"bottom",p(t.bottom,"")),M(e,"left",p(t.left,"")),M(e,"width",p(t.width,"")),M(e,"minWidth",p(t.minWidth,"")),M(e,"maxWidth",p(t.maxWidth,"")),M(e,"height",p(t.height,"")),M(e,"minHeight",p(t.minHeight,"")),M(e,"maxHeight",p(t.maxHeight,""));const d=p(t.alignItems,"");d&&(e.style.alignItems=d);const u=p(t.justifyContent,"");u&&(e.style.justifyContent=u);const h=p(t.alignSelf,"");h&&(e.style.alignSelf=h);const y=p(t.overflow,"");y&&(e.style.overflow=y);const b=p(t.overflowX,"");b&&(e.style.overflowX=b);const x=p(t.overflowY,"");x&&(e.style.overflowY=x);const T=p(t.position,"");T&&(e.style.position=T);const C=p(t.cursor,"");C&&(e.style.cursor=C);const D=p(n.background,"");D&&(e.style.background=xe(D));const V=p(n.color,"");V&&(e.style.color=xe(V)),M(e,"borderWidth",p(n.borderWidth,""));const G=p(n.borderColor,"");G&&(e.style.borderColor=xe(G));const J=p(n.borderStyle,"");J&&(e.style.borderStyle=J),M(e,"borderRadius",p(n.borderRadius,""));const Z=p(n.boxShadow,"");Z&&(e.style.boxShadow=Z);const K=p(n.font,"");K&&(e.style.font=K),M(e,"fontSize",p(n.fontSize,""));const I=p(n.fontWeight,"");I&&(e.style.fontWeight=I);const Q=p(n.textTransform,"");Q&&(e.style.textTransform=Q);const me=p(n.textAlign,"");me&&(e.style.textAlign=me);const Ae=p(n.whiteSpace,"");Ae&&(e.style.whiteSpace=Ae);const Oe=p(n.overflow,"");Oe&&(e.style.overflow=Oe);const ze=p(n.textOverflow,"");ze&&(e.style.textOverflow=ze),M(e,"lineHeight",p(n.lineHeight,""))}function M(e,t,n){n&&(e.style[t]=R(n))}function F(e,t){const n={};for(const[i,o]of Object.entries(e))i.startsWith(t)&&(n[i.slice(t.length)]=o);return n}function hn(e){const t=(e.children||[]).filter(u=>u.kind==="world.entity3d"),n=t.map(u=>xn(w(u.props).position,[0,0,0])),i=n.map(u=>u[0]),o=n.map(u=>u[2]),a=Math.min(...i,-1),l=Math.max(...i,1),s=Math.min(...o,-1),f=Math.max(...o,1),c=Math.max(1,l-a),r=Math.max(1,f-s),d=6;return t.map((u,h)=>{const y=w(u.props);return{entityId:p(y.entityId,u.id),faction:g(y.faction,"neutral"),kind:g(y.entityKind,"entity"),label:p(y.label,y.entityId,u.id,"Entity"),controlled:Ue(y.controllable),xPercent:d+(n[h][0]-a)/c*(100-d*2),yPercent:d+(1-(n[h][2]-s)/r)*(100-d*2),source:u}})}function gn(e,t,n,i,o){const a=m("section","cultui-world-scene");S(a,e),_(a,n,i),a.tabIndex=0,a.setAttribute("aria-label",g(t.label,"Interactive world"));const l=hn(e),s=l.find(r=>r.controlled),f=m("div","cultui-world-heading");f.append(m("strong","",g(t.label,"World"))),f.append(m("span","",`${l.length} entities`)),a.append(f);const c=m("div","cultui-world-plane");for(const r of l){const d=m("button",`cultui-world-entity faction-${He(r.faction)} kind-${He(r.kind)}`);d.type="button",d.style.left=`${r.xPercent}%`,d.style.top=`${r.yPercent}%`,d.dataset.entityId=r.entityId,d.dataset.controlled=r.controlled?"true":"false",d.title=r.label,d.setAttribute("aria-label",`${r.label}, ${r.kind}, ${r.faction}`),d.append(m("span","cultui-world-entity-glyph",vn(r.kind))),d.append(m("span","cultui-world-entity-label",r.label));const u=w(r.source.props),h=p(u.targetCommand,t.targetCommand,u.focusCommand,t.focusCommand);h&&d.addEventListener("click",()=>Te(h,{actorEntityId:s?.entityId||p(t.playerEntityId),entityId:r.entityId,targetEntityId:r.entityId,targetEntityKey:r.entityId},r.source,o)),c.append(d)}return a.append(c),a.addEventListener("keydown",r=>{const d=bn(r.key);if(d){r.preventDefault();const h=p(t.movementCommand,w(s?.source.props).moveCommand);h&&Te(h,{actorEntityId:s?.entityId||p(t.playerEntityId),actorEntityKey:s?.entityId||p(t.playerEntityId),directionX:d[0],directionY:d[1],scalar:1},e,o);return}const u=r.key===" "?p(t.actionCommand,w(s?.source.props).actionCommand):r.key.toLowerCase()==="f"?p(t.focusCommand,w(s?.source.props).focusCommand):"";u&&(r.preventDefault(),Te(u,{actionId:r.key===" "?"0":"focus",actorEntityId:s?.entityId||p(t.playerEntityId),actorEntityKey:s?.entityId||p(t.playerEntityId)},e,o))}),a}function Te(e,t,n,i){i.commandSink?.(yn(e,t,i),n)}function yn(e,t,n=z){return le(e,{action:t},n)}function bn(e){switch(e.toLowerCase()){case"w":case"arrowup":return[0,1];case"s":case"arrowdown":return[0,-1];case"a":case"arrowleft":return[-1,0];case"d":case"arrowright":return[1,0];default:return}}function vn(e){return e.includes("station")?"S":e.includes("projectile")?".":e.includes("ship")?"^":"+"}function He(e){return e.toLowerCase().replace(/[^a-z0-9_-]+/g,"-")}function Y(e,t){const n=Number(e);return Number.isFinite(n)?n:t}function xn(e,t){if(Array.isArray(e)){const n=e.map(i=>Number(i));if(n.length>=3&&n.slice(0,3).every(Number.isFinite))return[n[0],n[1],n[2]]}if(typeof e=="string"){const n=e.split(/[,\s]+/).map(i=>Number(i)).filter(Number.isFinite);if(n.length>=3)return[n[0],n[1],n[2]]}return t}function wn(e,t,n,i){const o=Ue(t.active),a=m("section","cultui-inventory-drag");S(a,e),_(a,n,i),a.dataset.active=o?"true":"false";const l=m("div","cultui-inventory-section-label","Drag");if(_(l,F(n,"sectionLabel."),F(i,"sectionLabel.")),a.append(l),!o){const d=m("div","cultui-inventory-empty","None");return _(d,F(n,"empty."),F(i,"empty.")),a.append(d),a}const s=p(t.itemKey,t.item,"item"),f=m("div","cultui-inventory-drag-chip",s);_(f,F(n,"dragChip."),F(i,"dragChip.")),a.append(f);const c=[t.originOffsetX,t.originOffsetY].map(d=>Number(d)).map(d=>Number.isFinite(d)?d:0),r=m("div","cultui-inventory-meta",`origin ${c[0]}, ${c[1]}`);return _(r,F(n,"meta."),F(i,"meta.")),a.append(r),a}function Sn(e,t,n,i,o){const a=m("section","cultui-inventory-grid");S(a,e),_(a,n,i);const l=q(p(t.columns,t.gridColumns,t.widthCells,""),0),s=l>0?l:6,f=q(t.rows,0),c=f>0?f:Math.max(3,Math.ceil(Math.max((e.children||[]).length,1)/s));a.style.setProperty("--inventory-columns",String(s)),a.style.setProperty("--inventory-rows",String(c)),a.dataset.cellSpriteMode=g(t.cellSpriteMode,"");const r=p(t.title,t.label,"Inventory"),d=m("div","cultui-inventory-section-label",r);_(d,F(n,"sectionLabel."),F(i,"sectionLabel.")),a.append(d);const u=m("div","cultui-inventory-board");u.style.display="grid",u.style.gridTemplateColumns=`repeat(${s}, ${R(p(t.cellSize,"72"))})`,u.style.gridTemplateRows=`repeat(${c}, ${R(p(t.cellSize,"72"))})`,u.style.gap=R(p(t.cellGap,"4")),u.style.overflow=p(t.boardOverflow,"auto"),u.style.padding=R(p(t.boardPadding,"4")),_(u,F(n,"board."),F(i,"board.")),u.addEventListener("dragover",b=>{En(t)&&(b.preventDefault(),b.dataTransfer&&(b.dataTransfer.dropEffect="move"))}),u.addEventListener("drop",b=>{const x=b.dataTransfer?.getData("application/vnd.gamecult.eve.inventory-item+json")||"";if(!x)return;let T;try{T=JSON.parse(x)}catch{return}const C=u.getBoundingClientRect(),D=Math.max(1,Y(t.cellSize,72)),V=Math.max(0,Y(t.cellGap,4)),G=D+V,J=Math.max(0,Math.min(s-1,Math.floor((b.clientX-C.left)/G))),Z=Math.max(0,Math.min(c-1,Math.floor((b.clientY-C.top)/G))),K=Cn(T,t,J,Z,o);K&&(b.preventDefault(),o.commandSink?.(K,e))});const h=new Set;for(const b of e.children||[]){const x=w(b.props),T=q(x.x,0),C=q(x.y,0);h.add(`${T}:${C}`),u.append(L(b,o))}const y=Math.min(s*c,256);for(let b=0;b{!a.draggable||!y.dataTransfer||(y.dataTransfer.effectAllowed="move",y.dataTransfer.setData("application/vnd.gamecult.eve.inventory-item+json",JSON.stringify(t)))});let f=q(t.shapeWidth,1),c=q(t.shapeHeight,1);const r=p(t.rotation,"").toLowerCase();["clockwise","counterclockwise","right","left","rotate90","rotate270"].includes(r)&&([f,c]=[c,f]),a.style.gridColumn=`${l+1} / span ${f}`,a.style.gridRow=`${s+1} / span ${c}`;const d=m("span","cultui-inventory-item-icon");_(d,F(n,"icon."),F(i,"icon.")),d.textContent=Wn(p(t.iconAssetUri,t.iconAssetKey,t.itemKey,t.label,"")),a.append(d);const u=p(t.label,t.itemKey,"");if(u){const y=m("span","cultui-inventory-item-label",u);_(y,F(n,"label."),F(i,"label.")),a.append(y)}const h=Number(t.quantity);if(Number.isFinite(h)&&h>1){const y=m("span","cultui-inventory-item-quantity",String(h));_(y,F(n,"quantity."),F(i,"quantity.")),a.append(y)}return a.title=[u,p(t.source,""),p(t.quality,"")?`quality ${t.quality}`:"",p(t.durability,"")?`durability ${t.durability}`:""].filter(Boolean).join(" | "),a}function En(e){return Object.entries(e).some(([t,n])=>(t==="dropCommand"||t.startsWith("dropCommand."))&&typeof n=="string"&&n.length>0)}function Cn(e,t,n,i,o=z){const a=p(e.sourceKind,e.source,""),l=p(t[`dropCommand.${a}`],t.dropCommand,"");if(!a||!l)return;const s=Y(e.sourceIndex,-1),f=Y(t.targetIndex,-1),c=p(t.targetKind,""),r={sourceKind:a,originEntityKey:p(e.sourceEntityKey,e.entityKey,""),originIndex:s,originCargoIndex:a==="cargo"?s:-1,itemKey:p(e.itemKey,""),quantity:Math.max(1,Y(e.quantity,1)),sourceX:Y(e.x,-2147483648),sourceY:Y(e.y,-2147483648),destinationKind:c,destinationEntityKey:p(t.targetEntityKey,t.entityKey,""),destinationIndex:f,destinationCargoIndex:c==="cargo"?f:-1,destinationX:Math.trunc(n),destinationY:Math.trunc(i),hasDestinationPosition:!0};return le(l,{action:r},o)}function An(e,t,n){const i=m("section","cultui-binding-map");S(i,e);const o=document.createElementNS("http://www.w3.org/2000/svg","svg");o.setAttribute("class","cultui-xbox-controller"),o.setAttribute("viewBox","0 0 780 420"),o.setAttribute("role","img"),o.setAttribute("aria-label",g(t.label,"Xbox controller remapping")),o.innerHTML=kn(),i.append(o);const a=m("div","cultui-binding-overlay");for(const l of e.children||[]){const s=w(l.props),f=g(s.target,l.id||""),c=m("button","cultui-binding-box");S(c,l),c.type="button",c.dataset.target=f,c.dataset.kind=g(s.bindingKind,"button"),c.style.left=R(s.x??"50%"),c.style.top=R(s.y??"50%"),c.append(m("span","cultui-binding-target",g(s.label,f))),c.append(m("span","cultui-binding-source",g(s.current,"unmapped"))),c.addEventListener("click",()=>{const d=ut(l);if(dt(l)||d?.documentId)ft(Me(l,n),n);else{const u=g(s.commandId,"");u&&n.commandSink?.(le(u,s,n),l)}}),a.append(c);const r=document.createElementNS("http://www.w3.org/2000/svg","line");r.setAttribute("class","cultui-binding-line"),r.setAttribute("x1",g(s.anchorX,"390")),r.setAttribute("y1",g(s.anchorY,"210")),r.setAttribute("x2",String(Je(s.x,780))),r.setAttribute("y2",String(Je(s.y,420))),o.append(r)}return i.append(a),i}function dt(e){for(const t of e.embeddedDocuments||[]){const n=w(t.surface);if(n.root)return n}}function ut(e){const t=(e.embeddedDocuments||[])[0],n=w(e.props),i=p(n.documentId,t?.documentId,"");if(i)return{documentId:i,presentationKind:p(n.presentationKind,t?.presentationKind,""),schemaId:p(n.schemaId,t?.schemaId,""),slotId:p(n.slotId,t?.slotId,"")}}async function Me(e,t){const n=dt(e);if(n)return n;const i=ut(e);if(!i?.documentId||!t.documentResolver)return;const o=await t.documentResolver(i,e);if(o)return w(o.surface).root?o.surface:o}function ft(e,t){const n=m("div","cultui-modal-backdrop"),i=m("section","cultui-modal");i.setAttribute("role","dialog"),i.setAttribute("aria-modal","true");const o=m("header","cultui-modal-header");o.append(m("h2","","Configure Binding"));const a=m("button","cultui-modal-close","Close");a.type="button",a.addEventListener("click",()=>n.remove()),o.append(a);const l=m("div","cultui-modal-body");i.append(o,l),n.append(i),n.addEventListener("click",s=>{s.target===n&&n.remove()}),document.body.append(n),l.append(m("div","detail","materializing document")),Promise.resolve(e).then(s=>{o.querySelector("h2").textContent=s?.title||"Configure Binding",l.replaceChildren(s?.root?L(s.root,t):H("Embedded document unavailable"))}).catch(s=>{l.replaceChildren(H(`Embedded document failed: ${s instanceof Error?s.message:String(s)}`))})}function In(e,t,n,i,o){const a=w(e.props),l=(e.children||[])[0],s=w(l?.props),f=p(s.anchor,a.anchor,"trigger"),c=p(s.placement,a.placement,"below-start"),r=Number(p(s.offsetX,a.offsetX,"0"))||0,d=Number(p(s.offsetY,a.offsetY,"4"))||0,u=m("div","cultui-modal-backdrop");u.style.background="transparent",u.style.placeItems="start";const h=m("section","cultui-modal");h.setAttribute("role","dialog"),h.setAttribute("aria-modal","true"),h.style.position="fixed",h.style.width="min(420px, calc(100vw - 24px))",h.style.maxHeight="min(620px, calc(100vh - 24px))";const y=m("header","cultui-modal-header");y.append(m("h2","",p(s.title,a.title,a.label,"Options")));const b=m("button","cultui-modal-close","Close");b.type="button",b.addEventListener("click",()=>u.remove()),y.append(b);const x=m("div","cultui-modal-body");if(l){const C=l.children||[];C.length>0?x.replaceChildren(...C.map(D=>L(D,t))):x.append(L(l,t))}else x.append(H("Popup has no content"));h.append(y,x),u.append(h),u.addEventListener("click",C=>{C.target===u&&u.remove()}),document.body.append(u);const T=Tn(f,c,n,h,i,o,r,d);h.style.left=`${T.left}px`,h.style.top=`${T.top}px`}function Tn(e,t,n,i,o,a,l,s){const f=n.getBoundingClientRect(),c=i.getBoundingClientRect(),r=c.width||420,d=c.height||320,u=e==="cursor"?{left:o,right:o,top:a,bottom:a}:f;if(t==="right-down"||t==="dropdown")return ge(u,r,d,l,s,"right","down");if(t==="left-down")return ge(u,r,d,l,s,"left","down");if(t==="right-up")return ge(u,r,d,l,s,"right","up");if(t==="left-up")return ge(u,r,d,l,s,"left","up");switch(t){case"above-start":return O(u.left+l,u.top-d-s,r,d);case"above-end":return O(u.right-r+l,u.top-d-s,r,d);case"below-end":return O(u.right-r+l,u.bottom+s,r,d);case"right-start":return O(u.right+l,u.top+s,r,d);case"left-start":return O(u.left-r-l,u.top+s,r,d);case"center":return O((window.innerWidth-r)/2+l,(window.innerHeight-d)/2+s,r,d);default:return O(u.left+l,u.bottom+s,r,d)}}function ge(e,t,n,i,o,a,l){const f=window.innerWidth-e.right-i-12,c=e.left-i-12,r=window.innerHeight-e.top-o-12,d=e.bottom-o-12,u=a==="right"?f>=t||f>=c:!(c>=t||c>=f),h=l==="down"?r>=n||r>=d:!(d>=n||d>=r),y=u?e.right+i:e.left-t-i,b=h?e.top+o:e.bottom-n-o;return O(y,b,t,n)}function O(e,t,n,i){return{left:Ve(e,12,window.innerWidth-n-12),top:Ve(t,12,window.innerHeight-i-12)}}function Ve(e,t,n){return nUt(l,t,f,a.resolveAssetUrl),r=()=>{!l.isConnected||s||(s=!0,requestAnimationFrame(()=>{s=!1,l.isConnected&&c()}))};l.addEventListener("cultui:asset-loaded",r);let d=0,u;const h=()=>{d&&window.clearInterval(d),u?.disconnect(),l.removeEventListener("cultui:asset-loaded",r)},y=()=>{if(!l.isConnected){h();return}Bt(e,t,o,a.providerId,f).then(x=>{x&&l.isConnected&&r()}).catch(x=>{f.lastError=x instanceof Error?x.message:String(x)})};typeof ResizeObserver<"u"&&(u=new ResizeObserver(r),u.observe(l)),r();const b=Math.max(33,Math.min(1e3,ln(t.stateRefreshMs,100)));return d=window.setInterval(y,b),queueMicrotask(y),window.setTimeout(r,300),window.setTimeout(r,1e3),l}async function Bt(e,t,n,i,o){if(o.loading)return!1;const a=[Ie(e,t,"renderSplats","renderSplatsDocumentId","renderSplatsSchemaId"),Ie(e,t,"gravity","gravityDocumentId","gravitySchemaId"),Ie(e,t,"objects","objectsDocumentId","objectsSchemaId")].filter(l=>!!l?.documentId);if(a.length===0)return!1;o.loading=!0;try{let l=!1;for(const s of a){const f=await n.documentResolver?.(s,e);let c=Se(Pe(f?.schemaId||s.schemaId,f?.document));if(Object.keys(c).length===0&&(c=Se(Pe(s.schemaId,await qt(s,i||n.provider?.providerId)))),Object.keys(c).length===0)continue;const r=s.slotId==="renderSplats"?"renderSplats":s.slotId==="gravity"?"gravity":"objects",d=$e(o[r]?.frameId,-1),u=$e(c.frameId,d);o[r]=c,l||=u!==d}return o.lastLoadedAt=Date.now(),l}finally{o.loading=!1}}async function qt(e,t){if(typeof fetch!="function"||typeof window>"u"||!t)return;const n=new URLSearchParams({documentId:e.documentId});e.schemaId&&n.set("schemaId",e.schemaId),e.slotId&&n.set("slotId",e.slotId);const i=await fetch(`/eir/document/${encodeURIComponent(t)}?${n.toString()}`,{cache:"no-store",headers:{Accept:"application/json"}});if(i.ok)return Se(await i.json()).document}function Ie(e,t,n,i,o){const a=(e.embeddedDocuments||[]).find(s=>String(s?.slotId||"")===n),l=k(t[i],a?.documentId);if(l)return{documentId:l,schemaId:k(t[o],a?.schemaId),presentationKind:k(a?.presentationKind)||"data",slotId:n}}function Pe(e,t){const n=Array.isArray(t)?t:void 0,i=n?n[0]:t?.schema,o=String(e||i||"");return!n||!nt.has(o)?t:o==="gamecult.fields.splats.v1"?Zt(n):o==="gamecult.fields.gravity.v1"?Qt(n):en(n)}function Ut(e,t,n,i){const o=e.getBoundingClientRect(),a=Math.max(1,Math.floor(o.width||e.clientWidth||1)),l=Math.max(1,Math.floor(o.height||e.clientHeight||1)),s=Math.max(1,Math.min(2,window.devicePixelRatio||1)),f=Math.max(1,Math.floor(a*s)),c=Math.max(1,Math.floor(l*s));(e.width!==f||e.height!==c)&&(e.width=f,e.height=c);const r=e.getContext("2d");if(!r)return;r.setTransform(s,0,0,s,0,0),r.clearRect(0,0,a,l);const d=Jt(Vt(t),a,l),u=ot(n?.gravity),h=Yt(n?.gravity)||Xt(k(t.bodies,"")),y=Ht(n?.objects)||jt(k(t.objects,""));St(r,t,u,h,d,a,l,n?.renderSplats)||Wt(r,t,a,l,"field.surface2d requires WebGL2 float render targets"),Ot(r,h,t,d,a,l,i),Gt(r,y,t,d,a,l,i)}function Wt(e,t,n,i,o){e.save(),e.fillStyle=k(t.failureBackground,"rgba(0, 0, 0, 0.72)"),e.fillRect(0,0,n,i),e.font=k(t.failureFont,"700 13px Cascadia Mono, Consolas, monospace"),e.fillStyle=k(t.failureColor,"rgba(255, 184, 79, 0.95)"),e.fillText(o,16,28),e.restore()}function Ot(e,t,n,i,o,a,l){for(const s of t){const f=rt(i,s.x,s.y,o,a),c=Math.max(18,Math.min(190,s.radius/Math.max(1,i.maxX-i.minX)*o*.32)),r=l(s.icon),d=s.kind.toLowerCase().includes("sun")?Math.max(E(n.sunIconMinPx,34),c*E(n.sunIconScale,.72)):Math.max(E(n.bodyIconMinPx,24),c*E(n.bodyIconScale,.48)),u=s.iconSize>0?s.iconSize:d;r&&zt(e,r,f.x,f.y,u,.92),s.key&&it(e,n,s.key.replace(/^local\./,""),f.x+c*.44,f.y-c*.48,k(n.bodyLabelColor,"rgba(226, 244, 255, 0.82)"))}}const we=new Map;function zt(e,t,n,i,o,a){let l=we.get(t);l||(l=new Image,l.decoding="async",l.onload=()=>requestAnimationFrame(()=>{e.canvas.dispatchEvent(new CustomEvent("cultui:asset-loaded"))}),l.src=t,we.set(t,l)),!(!l.complete||l.naturalWidth===0)&&(e.save(),e.globalAlpha=a,e.drawImage(l,n-o/2,i-o/2,o,o),e.restore())}function Gt(e,t,n,i,o,a,l){for(const s of t){const f=rt(i,s.x,s.y,o,a);if(f.x<-40||f.x>o+40||f.y<-40||f.y>a+40)continue;const c=s.kind.toLowerCase().includes("station")?E(n.stationIconSizePx,34):s.controlled?E(n.shipIconSizePx,22):E(n.remoteShipIconSizePx,18),r=Kt(n,s.faction,s.controlled,s.visibility),d=l(s.icon);e.save(),e.globalAlpha=Math.max(.25,Math.min(1,s.visibility)),e.translate(f.x,f.y);const u=Math.atan2(s.directionY,s.directionX)+Math.PI/2;if(s.kind.toLowerCase().includes("ship")&&e.rotate(u),d){const h=we.get(d);if(h)h.complete&&h.naturalWidth>0&&e.drawImage(h,-c/2,-c/2,c,c);else{const y=new Image;y.decoding="async",y.onload=()=>e.canvas.dispatchEvent(new CustomEvent("cultui:asset-loaded")),y.src=d,we.set(d,y)}}e.restore(),it(e,n,s.label,f.x+c*.55,f.y-c*.45,r)}}function it(e,t,n,i,o,a){n&&(e.save(),e.font=k(t.objectLabelFont,"700 12px Ubuntu, system-ui, sans-serif"),e.textBaseline="middle",e.lineWidth=E(t.objectLabelStrokeWidth,3),e.strokeStyle=k(t.objectLabelStroke,"rgba(0, 0, 0, 0.72)"),e.fillStyle=a,e.strokeText(n,i,o),e.fillText(n,i,o),e.restore())}function Kt(e,t,n,i){const o=Math.max(.25,Math.min(1,i));if(n)return pe(k(e.objectControlledColor,"rgba(122, 240, 255, {alpha})"),o);const a=t.toLowerCase();return a.includes("raider")?pe(k(e.objectRaiderColor,"rgba(255, 143, 74, {alpha})"),o):a.includes("neutral")?pe(k(e.objectNeutralColor,"rgba(232, 232, 224, {alpha})"),o):pe(k(e.objectDefaultColor,"rgba(214, 244, 255, {alpha})"),o)}function pe(e,t){return e.replaceAll("{alpha}",String(t))}function Xt(e){return e.split(";").map(t=>t.trim()).filter(Boolean).map(t=>{const n=t.split("|");return{key:n[0]??"",kind:n[1]??"",x:Number(n[2])||0,y:Number(n[3])||0,radius:Math.max(1,Number(n[4])||1),depth:Number(n[5])||0,exponent:Number(n[6])||1,waveRadius:Number(n[7])||0,waveDepth:Number(n[8])||0,waveSpeed:Number(n[9])||0,icon:n[10]??"",iconSize:Number(n[12])||0,tint:n[11]??""}})}function jt(e){return e.split(";").map(t=>t.trim()).filter(Boolean).map(t=>{const n=t.split("|");return{key:n[0]??"",kind:n[1]??"",label:n[2]??"",x:Number(n[3])||0,y:Number(n[4])||0,directionX:Number(n[5])||0,directionY:Number(n[6])||1,faction:n[7]??"",controlled:n[8]==="1"||n[8]==="true",visibility:Number(n[9])||1,icon:n[10]??""}})}function Yt(e){const t=Array.isArray(e?.gravityInfluences)?e.gravityInfluences:[],n=Array.isArray(e?.bodies)?e.bodies:[];if(t.length===0&&n.length===0)return;const i=new Map;for(const o of n){const a=k(o.bodyKey,o.name,"");a&&i.set(a,o)}return(t.length>0?t:n).map(o=>{const a=k(o.bodyKey,o.name,"body"),l=i.get(a),s=k(o.kind,"Body");return{key:a,kind:s,x:E(o.x,0),y:E(o.y,0),radius:Math.max(1,E(o.radius,80)),depth:E(o.gravityDepth,0),exponent:E(o.gravityDepthExponent,1),waveRadius:E(o.waveRadius,0),waveDepth:E(o.waveDepth,0),waveSpeed:E(o.waveSpeed,0),icon:Le(o.iconAsset)||Le(l?.iconAsset),iconSize:E(l?.iconSize,E(o.iconSize,0)),tint:""}})}function Ht(e){const t=Array.isArray(e?.objects)?e.objects:[];if(t.length!==0)return t.map(n=>{const i=k(n.kind,"object");return{key:k(n.entityKey,String(n.entityIndex??""),"object"),kind:i,label:k(n.displayName,n.entityKey,"object"),x:E(n.x,0),y:E(n.y,0),directionX:E(n.directionX,1),directionY:E(n.directionY,0),faction:k(n.factionKey,""),controlled:dn(n.controlled),visibility:E(n.visibility,1),icon:Le(n.iconAsset)}})}function Le(e){const t=ot(e);return k(t.uri,"")}function Vt(e){const t=Math.max(1,E(e.viewRadius,Math.max(1200,E(e.terrainRadius,1200))));return{minX:E(e.minX,-t),minY:E(e.minY,-t),maxX:E(e.maxX,t),maxY:E(e.maxY,t)}}function Jt(e,t,n){const i=Math.max(1e-4,e.maxX-e.minX),o=Math.max(1e-4,e.maxY-e.minY),a=Math.max(1e-4,t/Math.max(1,n)),l=i/o,s=(e.minX+e.maxX)*.5,f=(e.minY+e.maxY)*.5;if(a>l){const r=o*a;return{minX:s-r*.5,maxX:s+r*.5,minY:e.minY,maxY:e.maxY}}const c=i/a;return{minX:e.minX,maxX:e.maxX,minY:f-c*.5,maxY:f+c*.5}}function rt(e,t,n,i,o){return{x:(t-e.minX)/Math.max(1,e.maxX-e.minX)*i,y:(n-e.minY)/Math.max(1,e.maxY-e.minY)*o}}function Zt(e){const t=N(e[9]);return{schema:e[0],frameId:e[1],publishedAtUtc:e[2],simulationTimeSeconds:e[3],runId:e[4],zoneIndex:e[5],zoneName:e[6],viewport:De(e[7]),layers:N(e[8]).map(tn),splats:{count:t[0]??0,centerX:t[1]||[],centerY:t[2]||[],halfExtentX:t[3]||[],halfExtentY:t[4]||[],rotationCos:t[5]||[],rotationSin:t[6]||[],channel:t[7]||[],falloff:t[8]||[],valueR:t[9]||[],valueG:t[10]||[],valueB:t[11]||[],valueA:t[12]||[],sourceKey:t[13]||[],layerIndex:t[14]||[],sourceKind:t[15]||[],frequencyX:t[16]||[],frequencyY:t[17]||[],phaseX:t[18]||[],phaseY:t[19]||[],animationSpeed:t[20]||[],sourceFlags:t[21]||[]}}}function Qt(e){return{schema:e[0],frameId:e[1],publishedAtUtc:e[2],simulationTimeSeconds:e[3],runId:e[4],zoneIndex:e[5],zoneName:e[6],viewport:De(e[7]),gravityInfluences:N(e[8]).map(nn),bodies:N(e[9]).map(rn),terrainRadius:e[10],terrainDepth:e[11],terrainDepthExponent:e[12],terrainWaveFrequency:e[13]}}function en(e){return{schema:e[0],frameId:e[1],publishedAtUtc:e[2],simulationTimeSeconds:e[3],runId:e[4],zoneIndex:e[5],zoneName:e[6],currentEntityKey:e[7],viewport:De(e[8]),controlledEntityIndices:N(e[9]),objects:N(e[10]).map(on)}}function De(e){const t=N(e);return t.length?{minX:t[0],minY:t[1],maxX:t[2],maxY:t[3]}:e}function tn(e){const t=N(e);return t.length?{layerKey:t[0],displayName:t[1],channel:t[2],blendMode:t[3],graphicsFormat:t[4],clearBeforeDraw:t[5],clearR:t[6],clearG:t[7],clearB:t[8],clearA:t[9]}:e}function nn(e){const t=N(e);return t.length?{bodyKey:t[0],orbitKey:t[1],kind:t[2],x:t[3],y:t[4],radius:t[5],gravityDepth:t[6],gravityDepthExponent:t[7],waveRadius:t[8],waveDepth:t[9],waveSpeed:t[10]}:e}function rn(e){const t=N(e);return t.length?{bodyKey:t[0],orbitKey:t[1],name:t[2],kind:t[3],x:t[4],y:t[5],radius:t[6],isAsteroidBelt:t[7],body:t[8],iconAsset:Be(t[9])}:e}function on(e){const t=N(e);return t.length?{entityIndex:t[0],entityKey:t[1],displayName:t[2],kind:t[3],factionKey:t[4],x:t[5],y:t[6],z:t[7],directionX:t[8],directionY:t[9],velocityX:t[10],velocityY:t[11],controlled:t[12],targetEntityIndex:t[13],isActive:t[14],visibility:t[15],status:an(t[16]),inventory:N(t[17]).map(sn),iconAsset:Be(t[18])}:e}function an(e){const t=N(e);return t.length?{hull:t[0],shield:t[1],heat:t[2]}:e||{}}function sn(e){const t=N(e);return t.length?{source:t[0],itemKey:t[1],quantity:t[2],quality:t[3],durability:t[4],enabled:t[5],sourceIndex:t[6],x:t[7],y:t[8],iconAsset:Be(t[9])}:e}function Be(e){const t=N(e);return t.length?{assetKey:t[0],kind:t[1],uri:t[2],transport:t[3],contentHash:t[4],mimeType:t[5],metadata:t[6]||{}}:e||{}}function N(e){return Array.isArray(e)?e:[]}function Se(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function k(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function cn(e,t){return typeof e=="string"&&e?e:t}function ln(e,t){const n=Number(e);return Number.isFinite(n)&&n>0?Math.floor(n):t}function $e(e,t){const n=Number(e);return Number.isFinite(n)?n:t}const ot=Se,E=$e;function dn(e){return typeof e=="boolean"?e:typeof e=="number"?e!==0:typeof e=="string"&&["1","true","yes","on"].includes(e.trim().toLowerCase())}const un=[Nt],fn={"--bg":"#020909","--bg-top":"#020909","--bg-mid":"#020909","--bg-bottom":"#020909","--shell-top":"#010707","--shell-bottom":"#010707","--panel":"#071918","--panel-2":"#0a2423","--line":"rgba(103, 240, 228, 0.28)","--line-deep":"rgba(103, 240, 228, 0.18)","--text":"#e7f1f1","--text-bright":"#e7f1f1","--quiet":"#8ba5a3","--accent":"#ffb84f","--accent-strong":"#ffb84f","--corner-accent":"#ffb84f","--cyan":"#8efcff","--shadow":"rgba(0, 0, 0, 0.35)","--pixel-grid":"rgba(142, 252, 255, 0.04)","--border-width":"1px","--border-bottom-width":"1px","--corner-accent-size":"0","--font-body":'"M PLUS 1", "Ubuntu Sans", Ubuntu, "Noto Sans JP", system-ui, sans-serif',"--font-title":'"Montserrat", "Zen Kaku Gothic New", "M PLUS 1", "Ubuntu Sans", system-ui, sans-serif',"--font-mono":'"Ubuntu Sans Mono", "M PLUS 1 Code", "Cascadia Mono", Consolas, monospace'};let he,at=qe(void 0),se,z={};const Ye=new WeakMap;function st(e,t,n={}){if(Ye.get(t)?.dispose(),se=e,z=n,at=qe(e.surface?.styles),globalThis.__eveCurrentMesh=e.mesh,Rn(e.surface?.styles,n.body??document.body),n.body&&(n.body.dataset.provider=e.providerId||n.provider?.providerId||""),n.statusElement&&(n.statusElement.textContent=`${e.title||e.surface?.title||"surface"}${n.source?` (${n.source})`:""}`),e.surface?.root){if(t.replaceChildren(L(e.surface.root,n)),n.stateBindingResolver){const i=new pn(e,t,n);Ye.set(t,i),i.start()}}else t.replaceChildren(H("No surface root"));return t}function mn(e,t,n){const i=t.targetProp.split(".").filter(Boolean);if(i.length===0)throw new Error("Eve state binding targetProp must not be empty.");e.props||={};let o=e.props;for(const a of i.slice(0,-1)){const l=o[a];(!l||typeof l!="object"||Array.isArray(l))&&(o[a]={}),o=o[a]}o[i[i.length-1]]=n}class pn{surface;host;options;disposed=!1;unsubscribers=[];constructor(t,n,i){this.surface=t,this.host=n,this.options=i}async start(){const t=this.options.stateBindingResolver,n=this.surface.surface?.root;if(!(!t||!n))for(const i of ct(n))for(const o of i.stateBindings||[]){if(this.disposed)return;const a=await t(o,i);if(!a||this.disposed)continue;const l=s=>{this.disposed||(mn(i,o,s),this.renderCanonicalProjection())};if(l(await a.latest()),this.disposed)return;this.unsubscribers.push(a.watch(l))}}dispose(){this.disposed=!0;for(const t of this.unsubscribers.splice(0))t()}renderCanonicalProjection(){const t=this.surface.surface?.root;t&&this.host.replaceChildren(L(t,this.options))}}function*ct(e){yield e;for(const t of e.children||[])yield*ct(t)}function L(e,t=z){const n=e.kind||"panel",i=w(e.props),o=w(e.layout),a=w(e.style),l=e.children||[],s=e.embeddedDocuments||[];if(n==="surface"||n==="cockpit"||n==="dashboard"){const r=m("section","cultui-surface-root eve-surface");S(r,e),typeof o.direction=="string"?r.dataset.direction=o.direction:typeof i.layout=="object"&&i.layout&&typeof i.layout.direction=="string"&&(r.dataset.direction=String(i.layout.direction)),n!=="surface"&&(r.dataset.surfaceKind=n),_(r,o,a);for(const d of l)r.append(L(d,t));return r}if(n==="column"||n==="row"||n==="form"||n==="rail"){const r=m("div",`cultui-partition eve-${n}`);S(r,e),r.dataset.direction=n==="row"||n==="rail"?"horizontal":"vertical",n==="rail"&&(r.dataset.overflow="x"),ye(r,{...o,...i}),_(r,o,a);for(const d of l)r.append(L(d,t));return r}if(n==="grid"){const r=m("section","cultui-grid"),d=q(i.columns,0);d>0?r.style.gridTemplateColumns=`repeat(${d}, minmax(0, 1fr))`:typeof i.columns=="string"&&(r.style.gridTemplateColumns=i.columns);const u=q(i.rows,0);u>0&&(r.style.gridTemplateRows=`repeat(${u}, minmax(0, auto))`),_(r,o,a);for(const h of l)r.append(L(h,t));return r}if(n==="partition"){const r=m("section",`cultui-partition split-${g(i.split,"none")}`);S(r,e),ye(r,i),_(r,o,a),r.style.minWidth="0",g(i.split,"none")==="x"&&!p(i.flexWrap,o.flexWrap,"")&&(r.style.flexWrap="wrap"),typeof i.role=="string"&&(r.dataset.role=i.role);for(const d of l)r.append(L(d,t));return r}if(n==="input.binding-map")return An(e,i,t);if(n==="inventory.drag_session")return wn(e,i,o,a);if(n==="inventory.grid")return Sn(e,i,o,a,t);if(n==="inventory.item")return _n(e,i,o,a);const f=(t.pluginAdapters||un).find(r=>r.componentKinds.includes(n));if(f?.renderComponent)return f.renderComponent(e,i,o,a,t,{applyGeneratedLayout:_,providerId:se?.providerId||t.provider?.providerId,resolveAssetUrl:ae});if(n==="world.scene3d"||n==="world.scene2d")return gn(e,i,o,a,t);if(n==="image.background"){const r=m("div","cultui-background"),d=ae(p(i.src,i.assetUri,i.assetRef,""));return d&&(r.style.backgroundImage=`url("${d}")`),r.setAttribute("aria-label",g(i.label,"background")),r}if(n==="image.sprite"){const r=m("figure",`cultui-sprite ${g(i.slot,"center")}`);S(r,e);const d=ae(p(i.src,i.assetUri,i.assetRef,""));if(d){const u=m("img");u.src=d,u.alt=g(i.alt,g(i.actor,g(i.label,""))),r.append(u)}return r}if(n==="avatar"){const r=m("figure","cultui-avatar-card");S(r,e);const d=ae(p(i.src,i.assetUri,i.assetRef,""));if(d){const b=m("img");b.src=d,b.alt=g(i.alt,g(i.text,g(i.label,""))),r.append(b)}else r.append(m("div","cultui-avatar-fallback",On(p(i.text,i.label,i.actor,"?"))));const u=p(i.text,i.label,i.actor,"");u&&r.append(m("figcaption","cultui-avatar-name",u));const h=p(i.status,"");h&&r.append(m("div","cultui-avatar-status",h));const y=p(i.detail,"");return y&&r.append(m("div","cultui-avatar-detail",y)),r}if(n==="pane"||n==="panel"){const r=m("section","pane cultui-pane");S(r,e);const d=g(i.span,"");d&&(r.dataset.span=d);const u=g(i.density,"");u&&(r.dataset.density=u);const h=g(i.title,e.text||"");h&&r.append(m("h2","",h));for(const y of l)r.append(L(y,t));return r}if(n==="list"||n.endsWith(".roster")){const r=m("section","cultui-list");S(r,e),r.dataset.componentKind=n;const d=g(i.title,"");d&&r.append(m("h3","cultui-list-title",d));for(const[u,h]of Un(i.items).entries())r.append(L({id:`${e.id||"list"}-item-${u}`,kind:"list.item",props:{...h}},t));for(const u of l)r.append(L(u,t));return r}if(n==="list.item"||n.endsWith(".item")){const r=lt(e),d=m("article","cultui-list-item");S(d,e),d.dataset.componentKind=n;const u=m("div","cultui-list-item-heading");if(u.append(m("strong","cultui-list-item-label",r.label)),r.status&&u.append(m("span","cultui-list-item-status",r.status)),d.append(u),r.detail&&d.append(m("div","cultui-list-item-detail",r.detail)),r.badges.length){const h=m("div","cultui-list-item-badges");for(const y of r.badges)h.append(m("span","cultui-list-item-badge",y));d.append(h)}for(const h of l)d.append(L(h,t));return d}if(n==="bar"){const r=m("div","cultui-meter");S(r,e);const d=g(i.label,""),u=g(i.value,"");if(d||u){const b=m("div","cultui-meter-head");b.append(m("span","",d)),b.append(m("strong","",u)),r.append(b)}const h=m("div","cultui-meter-track"),y=m("span","cultui-meter-fill");return y.style.width=`${et(i.percent)}%`,h.append(y),r.append(h),r}if(n==="card"){const r=Ze(i,e),d=r?m("button","card cultui-card cultui-card-button"):m("article","card cultui-card");S(d,e),_(d,o,a),d instanceof HTMLButtonElement&&(d.type="button");const u=g(i.title,e.text||"");u&&d.append(m("div","card-title",u));for(const h of l)d.append(L(h,t));return r&&Qe(d,e,r,i,t),d}if(n==="control.button"){const r=m("button","cultui-button eve-control-button",g(i.label,"Action"));return S(r,e),r.type="button",_(r,o,a),Qe(r,e,Ze(i,e),i,t),r}if(n==="control.popup"){const r=m("button","cultui-button eve-control-popup",g(i.label,"Open"));return S(r,e),r.type="button",_(r,o,a),r.addEventListener("click",d=>{In(e,t,r,d.clientX,d.clientY)}),r}if(n==="text.dialogue"||n==="text"||n==="text.title"||n==="text.subtitle"||n==="label"){const r=m("div",Mn(n,i),g(i.value,g(i.text,e.text||"")));return S(r,e),ye(r,i),_(r,o,a),r}if(n==="metric"){const r=m("dl","metric cultui-reactive-metric eve-metric");return S(r,e),_(r,o,a),r.append(m("dt","",g(i.label,"Metric"))),r.append(m("dd","metric-value",g(i.value,""))),r}if(n==="progress"){const r=m("div","cultui-meter eve-progress");S(r,e),_(r,o,a);const d=g(i.label,""),u=g(i.value,""),h=Number(i.min??0),y=Number(i.max??1),b=Number(i.value??0),x=Number.isFinite(b)&&Number.isFinite(h)&&Number.isFinite(y)&&y!==h?(b-h)/(y-h)*100:et(i.percent);if(d||u){const D=m("div","cultui-meter-head");D.append(m("span","",d)),D.append(m("strong","",u)),r.append(D)}const T=m("div","cultui-meter-track"),C=m("span","cultui-meter-fill");return C.style.width=`${Math.max(0,Math.min(100,x))}%`,T.append(C),r.append(T),r}if(n==="modal"){const r=m("section","cultui-modal-surface");S(r,e),_(r,o,a);const d=g(i.title,"");d&&r.append(m("h2","cultui-modal-surface-title",d));for(const u of l)r.append(L(u,t));return r}if(n==="options"){const r=m("section","cultui-options");S(r,e),_(r,o,a);const d=g(i.label,"");d&&r.append(m("h3","cultui-list-title",d));for(const u of l)r.append(L(u,t));return l.length===0&&r.append(H("waiting for options")),r}if(n==="image.preview"){const r=m("figure","cultui-image-preview");S(r,e);const d=m("div","cultui-image-frame"),u=ae(p(i.src,i.assetUri,i.assetRef,""));if(u){const h=m("img");h.src=u,h.alt=g(i.label,""),h.style.imageRendering=g(i.imageRendering,"auto"),i.zoom!==void 0&&(h.style.transform=`scale(${i.zoom})`,h.style.transformOrigin=g(i.crop,"50% 50%")),d.append(h)}else d.append(m("span","",g(i.label,"image")));return r.append(d),i.label&&r.append(m("figcaption","",String(i.label))),r}if(n==="canvas.preview"||n==="canvas.editor"){const r=m("div",`cultui-canvas-placeholder ${n==="canvas.editor"?"editor":"preview"}`);return S(r,e),r.append(m("div","viz-label",g(i.label,"Canvas"))),r.append(m("div","cultui-canvas-grid",i.state==="empty"?"waiting for pixels":g(i.state,""))),r}if(n==="surface.slot"){const r=m("section","cultui-embedded-slot");S(r,e),_(r,o,a),r.dataset.slotId=g(i.slotId,g(s[0]?.slotId,"")),r.dataset.documentId=g(i.documentId,g(s[0]?.documentId,"")),r.dataset.schemaId=g(i.schemaId,g(s[0]?.schemaId,"")),r.dataset.presentationKind=g(i.presentationKind,g(s[0]?.presentationKind,""));const d=s.map(h=>w(h.surface)).find(h=>w(h.root).kind||h.root),u=i.modal===!0||r.dataset.presentationKind.includes("modal");if((d||r.dataset.documentId)&&u){const h=m("button","cultui-button cultui-modal-trigger",g(i.label,r.dataset.slotId||"Configure"));h.type="button",h.addEventListener("click",()=>ft(Me(e,t),t)),r.append(h)}else if(d||r.dataset.documentId){const h=m("div","cultui-embedded-slot-body");h.append(m("div","detail","materializing surface")),r.append(h),Me(e,t).then(y=>{h.replaceChildren(y?.root?L(y.root,t):H("Embedded surface unavailable"))}).catch(y=>{h.replaceChildren(H(`Embedded surface failed: ${y instanceof Error?y.message:String(y)}`))})}else r.append(m("div","detail",r.dataset.presentationKind||r.dataset.slotId||"embedded surface"));return r}if(n==="control.slider")return Pn(i,l,t);if(n==="control.toggle"){const r=m("label","toggle-row cultui-toggle");return S(r,e),r.append(m("span","field-control",i.value?"on":"off")),r.append(m("span","toggle-copy",g(i.label,"Toggle"))),r}if(n==="input.number"||n==="input.select"||n==="control.range"||n==="control.input.text"||n==="control.select"){const r=m("label","field cultui-field");return S(r,e),ye(r,i),_(r,o,a),r.append(m("span","field-label",g(i.label,""))),r.append(m("span","field-control cultui-field-value",i.value===void 0?"":String(i.value))),r}if(n==="color.swatch"){const r=m("div","paint-swatch cultui-swatch");return S(r,e),r.style.background=g(i.value,g(i.color,"currentColor")),r.title=g(i.label,"Color"),r}const c=m("section","pane");S(c,e),c.append(m("h2","",n));for(const r of l)c.append(L(r,t));return c}function lt(e){const t=w(e.props);return{label:p(t.label,t.title,t.displayName,e.text,e.kind,"item"),status:p(t.status,t.state,""),detail:p(t.detail,t.phase,t.repoName,""),badges:Array.isArray(t.badges)?t.badges.map(n=>String(n).trim()).filter(Boolean):p(t.badges,"").split(",").map(n=>n.trim()).filter(Boolean)}}function _(e,t,n={}){const i=p(t.display,"");i&&(e.style.display=i);const o=p(t.direction,"");o&&(e.style.flexDirection=o==="horizontal"?"row":o==="vertical"?"column":o);const a=p(t.flexWrap,"");a&&(e.style.flexWrap=a);const l=p(t.gridTemplateColumns,"");l&&(e.style.gridTemplateColumns=l);const s=p(t.gridTemplateRows,"");s&&(e.style.gridTemplateRows=s);const f=p(t.gridTemplateAreas,"");f&&(e.style.gridTemplateAreas=f);const c=p(t.gridArea,"");c&&(e.style.gridArea=c);const r=p(t.placeItems,"");r&&(e.style.placeItems=r),M(e,"gap",p(t.gap,"")),M(e,"padding",p(t.padding,"")),M(e,"margin",p(t.margin,"")),M(e,"top",p(t.top,"")),M(e,"right",p(t.right,"")),M(e,"bottom",p(t.bottom,"")),M(e,"left",p(t.left,"")),M(e,"width",p(t.width,"")),M(e,"minWidth",p(t.minWidth,"")),M(e,"maxWidth",p(t.maxWidth,"")),M(e,"height",p(t.height,"")),M(e,"minHeight",p(t.minHeight,"")),M(e,"maxHeight",p(t.maxHeight,""));const d=p(t.alignItems,"");d&&(e.style.alignItems=d);const u=p(t.justifyContent,"");u&&(e.style.justifyContent=u);const h=p(t.alignSelf,"");h&&(e.style.alignSelf=h);const y=p(t.overflow,"");y&&(e.style.overflow=y);const b=p(t.overflowX,"");b&&(e.style.overflowX=b);const x=p(t.overflowY,"");x&&(e.style.overflowY=x);const T=p(t.position,"");T&&(e.style.position=T);const C=p(t.cursor,"");C&&(e.style.cursor=C);const D=p(n.background,"");D&&(e.style.background=xe(D));const V=p(n.color,"");V&&(e.style.color=xe(V)),M(e,"borderWidth",p(n.borderWidth,""));const G=p(n.borderColor,"");G&&(e.style.borderColor=xe(G));const J=p(n.borderStyle,"");J&&(e.style.borderStyle=J),M(e,"borderRadius",p(n.borderRadius,""));const Z=p(n.boxShadow,"");Z&&(e.style.boxShadow=Z);const K=p(n.font,"");K&&(e.style.font=K),M(e,"fontSize",p(n.fontSize,""));const I=p(n.fontWeight,"");I&&(e.style.fontWeight=I);const Q=p(n.textTransform,"");Q&&(e.style.textTransform=Q);const me=p(n.textAlign,"");me&&(e.style.textAlign=me);const Ae=p(n.whiteSpace,"");Ae&&(e.style.whiteSpace=Ae);const Oe=p(n.overflow,"");Oe&&(e.style.overflow=Oe);const ze=p(n.textOverflow,"");ze&&(e.style.textOverflow=ze),M(e,"lineHeight",p(n.lineHeight,""))}function M(e,t,n){n&&(e.style[t]=R(n))}function P(e,t){const n={};for(const[i,o]of Object.entries(e))i.startsWith(t)&&(n[i.slice(t.length)]=o);return n}function hn(e){const t=(e.children||[]).filter(u=>u.kind==="world.entity3d"),n=t.map(u=>xn(w(u.props).position,[0,0,0])),i=n.map(u=>u[0]),o=n.map(u=>u[2]),a=Math.min(...i,-1),l=Math.max(...i,1),s=Math.min(...o,-1),f=Math.max(...o,1),c=Math.max(1,l-a),r=Math.max(1,f-s),d=6;return t.map((u,h)=>{const y=w(u.props);return{entityId:p(y.entityId,u.id),faction:g(y.faction,"neutral"),kind:g(y.entityKind,"entity"),label:p(y.label,y.entityId,u.id,"Entity"),controlled:Ue(y.controllable),xPercent:d+(n[h][0]-a)/c*(100-d*2),yPercent:d+(1-(n[h][2]-s)/r)*(100-d*2),source:u}})}function gn(e,t,n,i,o){const a=m("section","cultui-world-scene");S(a,e),_(a,n,i),a.tabIndex=0,a.setAttribute("aria-label",g(t.label,"Interactive world"));const l=hn(e),s=l.find(r=>r.controlled),f=m("div","cultui-world-heading");f.append(m("strong","",g(t.label,"World"))),f.append(m("span","",`${l.length} entities`)),a.append(f);const c=m("div","cultui-world-plane");for(const r of l){const d=m("button",`cultui-world-entity faction-${He(r.faction)} kind-${He(r.kind)}`);d.type="button",d.style.left=`${r.xPercent}%`,d.style.top=`${r.yPercent}%`,d.dataset.entityId=r.entityId,d.dataset.controlled=r.controlled?"true":"false",d.title=r.label,d.setAttribute("aria-label",`${r.label}, ${r.kind}, ${r.faction}`),d.append(m("span","cultui-world-entity-glyph",vn(r.kind))),d.append(m("span","cultui-world-entity-label",r.label));const u=w(r.source.props),h=p(u.targetCommand,t.targetCommand,u.focusCommand,t.focusCommand);h&&d.addEventListener("click",()=>Te(h,{actorEntityId:s?.entityId||p(t.playerEntityId),entityId:r.entityId,targetEntityId:r.entityId,targetEntityKey:r.entityId},r.source,o)),c.append(d)}return a.append(c),a.addEventListener("keydown",r=>{const d=bn(r.key);if(d){r.preventDefault();const h=p(t.movementCommand,w(s?.source.props).moveCommand);h&&Te(h,{actorEntityId:s?.entityId||p(t.playerEntityId),actorEntityKey:s?.entityId||p(t.playerEntityId),directionX:d[0],directionY:d[1],scalar:1},e,o);return}const u=r.key===" "?p(t.actionCommand,w(s?.source.props).actionCommand):r.key.toLowerCase()==="f"?p(t.focusCommand,w(s?.source.props).focusCommand):"";u&&(r.preventDefault(),Te(u,{actionId:r.key===" "?"0":"focus",actorEntityId:s?.entityId||p(t.playerEntityId),actorEntityKey:s?.entityId||p(t.playerEntityId)},e,o))}),a}function Te(e,t,n,i){i.commandSink?.(yn(e,t,i),n)}function yn(e,t,n=z){return le(e,{action:t},n)}function bn(e){switch(e.toLowerCase()){case"w":case"arrowup":return[0,1];case"s":case"arrowdown":return[0,-1];case"a":case"arrowleft":return[-1,0];case"d":case"arrowright":return[1,0];default:return}}function vn(e){return e.includes("station")?"S":e.includes("projectile")?".":e.includes("ship")?"^":"+"}function He(e){return e.toLowerCase().replace(/[^a-z0-9_-]+/g,"-")}function Y(e,t){const n=Number(e);return Number.isFinite(n)?n:t}function xn(e,t){if(Array.isArray(e)){const n=e.map(i=>Number(i));if(n.length>=3&&n.slice(0,3).every(Number.isFinite))return[n[0],n[1],n[2]]}if(typeof e=="string"){const n=e.split(/[,\s]+/).map(i=>Number(i)).filter(Number.isFinite);if(n.length>=3)return[n[0],n[1],n[2]]}return t}function wn(e,t,n,i){const o=Ue(t.active),a=m("section","cultui-inventory-drag");S(a,e),_(a,n,i),a.dataset.active=o?"true":"false";const l=m("div","cultui-inventory-section-label","Drag");if(_(l,P(n,"sectionLabel."),P(i,"sectionLabel.")),a.append(l),!o){const d=m("div","cultui-inventory-empty","None");return _(d,P(n,"empty."),P(i,"empty.")),a.append(d),a}const s=p(t.itemKey,t.item,"item"),f=m("div","cultui-inventory-drag-chip",s);_(f,P(n,"dragChip."),P(i,"dragChip.")),a.append(f);const c=[t.originOffsetX,t.originOffsetY].map(d=>Number(d)).map(d=>Number.isFinite(d)?d:0),r=m("div","cultui-inventory-meta",`origin ${c[0]}, ${c[1]}`);return _(r,P(n,"meta."),P(i,"meta.")),a.append(r),a}function Sn(e,t,n,i,o){const a=m("section","cultui-inventory-grid");S(a,e),_(a,n,i);const l=q(p(t.columns,t.gridColumns,t.widthCells,""),0),s=l>0?l:6,f=q(t.rows,0),c=f>0?f:Math.max(3,Math.ceil(Math.max((e.children||[]).length,1)/s));a.style.setProperty("--inventory-columns",String(s)),a.style.setProperty("--inventory-rows",String(c)),a.dataset.cellSpriteMode=g(t.cellSpriteMode,"");const r=p(t.title,t.label,"Inventory"),d=m("div","cultui-inventory-section-label",r);_(d,P(n,"sectionLabel."),P(i,"sectionLabel.")),a.append(d);const u=m("div","cultui-inventory-board");u.style.display="grid",u.style.gridTemplateColumns=`repeat(${s}, ${R(p(t.cellSize,"72"))})`,u.style.gridTemplateRows=`repeat(${c}, ${R(p(t.cellSize,"72"))})`,u.style.gap=R(p(t.cellGap,"4")),u.style.overflow=p(t.boardOverflow,"auto"),u.style.padding=R(p(t.boardPadding,"4")),_(u,P(n,"board."),P(i,"board.")),u.addEventListener("dragover",b=>{En(t)&&(b.preventDefault(),b.dataTransfer&&(b.dataTransfer.dropEffect="move"))}),u.addEventListener("drop",b=>{const x=b.dataTransfer?.getData("application/vnd.gamecult.eve.inventory-item+json")||"";if(!x)return;let T;try{T=JSON.parse(x)}catch{return}const C=u.getBoundingClientRect(),D=Math.max(1,Y(t.cellSize,72)),V=Math.max(0,Y(t.cellGap,4)),G=D+V,J=Math.max(0,Math.min(s-1,Math.floor((b.clientX-C.left)/G))),Z=Math.max(0,Math.min(c-1,Math.floor((b.clientY-C.top)/G))),K=Cn(T,t,J,Z,o);K&&(b.preventDefault(),o.commandSink?.(K,e))});const h=new Set;for(const b of e.children||[]){const x=w(b.props),T=q(x.x,0),C=q(x.y,0);h.add(`${T}:${C}`),u.append(L(b,o))}const y=Math.min(s*c,256);for(let b=0;b{!a.draggable||!y.dataTransfer||(y.dataTransfer.effectAllowed="move",y.dataTransfer.setData("application/vnd.gamecult.eve.inventory-item+json",JSON.stringify(t)))});let f=q(t.shapeWidth,1),c=q(t.shapeHeight,1);const r=p(t.rotation,"").toLowerCase();["clockwise","counterclockwise","right","left","rotate90","rotate270"].includes(r)&&([f,c]=[c,f]),a.style.gridColumn=`${l+1} / span ${f}`,a.style.gridRow=`${s+1} / span ${c}`;const d=m("span","cultui-inventory-item-icon");_(d,P(n,"icon."),P(i,"icon.")),d.textContent=Wn(p(t.iconAssetUri,t.iconAssetKey,t.itemKey,t.label,"")),a.append(d);const u=p(t.label,t.itemKey,"");if(u){const y=m("span","cultui-inventory-item-label",u);_(y,P(n,"label."),P(i,"label.")),a.append(y)}const h=Number(t.quantity);if(Number.isFinite(h)&&h>1){const y=m("span","cultui-inventory-item-quantity",String(h));_(y,P(n,"quantity."),P(i,"quantity.")),a.append(y)}return a.title=[u,p(t.source,""),p(t.quality,"")?`quality ${t.quality}`:"",p(t.durability,"")?`durability ${t.durability}`:""].filter(Boolean).join(" | "),a}function En(e){return Object.entries(e).some(([t,n])=>(t==="dropCommand"||t.startsWith("dropCommand."))&&typeof n=="string"&&n.length>0)}function Cn(e,t,n,i,o=z){const a=p(e.sourceKind,e.source,""),l=p(t[`dropCommand.${a}`],t.dropCommand,"");if(!a||!l)return;const s=Y(e.sourceIndex,-1),f=Y(t.targetIndex,-1),c=p(t.targetKind,""),r={sourceKind:a,originEntityKey:p(e.sourceEntityKey,e.entityKey,""),originIndex:s,originCargoIndex:a==="cargo"?s:-1,itemKey:p(e.itemKey,""),quantity:Math.max(1,Y(e.quantity,1)),sourceX:Y(e.x,-2147483648),sourceY:Y(e.y,-2147483648),destinationKind:c,destinationEntityKey:p(t.targetEntityKey,t.entityKey,""),destinationIndex:f,destinationCargoIndex:c==="cargo"?f:-1,destinationX:Math.trunc(n),destinationY:Math.trunc(i),hasDestinationPosition:!0};return le(l,{action:r},o)}function An(e,t,n){const i=m("section","cultui-binding-map");S(i,e);const o=document.createElementNS("http://www.w3.org/2000/svg","svg");o.setAttribute("class","cultui-xbox-controller"),o.setAttribute("viewBox","0 0 780 420"),o.setAttribute("role","img"),o.setAttribute("aria-label",g(t.label,"Xbox controller remapping")),o.innerHTML=kn(),i.append(o);const a=m("div","cultui-binding-overlay");for(const l of e.children||[]){const s=w(l.props),f=g(s.target,l.id||""),c=m("button","cultui-binding-box");S(c,l),c.type="button",c.dataset.target=f,c.dataset.kind=g(s.bindingKind,"button"),c.style.left=R(s.x??"50%"),c.style.top=R(s.y??"50%"),c.append(m("span","cultui-binding-target",g(s.label,f))),c.append(m("span","cultui-binding-source",g(s.current,"unmapped"))),c.addEventListener("click",()=>{const d=ut(l);if(dt(l)||d?.documentId)ft(Me(l,n),n);else{const u=g(s.commandId,"");u&&n.commandSink?.(le(u,s,n),l)}}),a.append(c);const r=document.createElementNS("http://www.w3.org/2000/svg","line");r.setAttribute("class","cultui-binding-line"),r.setAttribute("x1",g(s.anchorX,"390")),r.setAttribute("y1",g(s.anchorY,"210")),r.setAttribute("x2",String(Je(s.x,780))),r.setAttribute("y2",String(Je(s.y,420))),o.append(r)}return i.append(a),i}function dt(e){for(const t of e.embeddedDocuments||[]){const n=w(t.surface);if(n.root)return n}}function ut(e){const t=(e.embeddedDocuments||[])[0],n=w(e.props),i=p(n.documentId,t?.documentId,"");if(i)return{documentId:i,presentationKind:p(n.presentationKind,t?.presentationKind,""),schemaId:p(n.schemaId,t?.schemaId,""),slotId:p(n.slotId,t?.slotId,"")}}async function Me(e,t){const n=dt(e);if(n)return n;const i=ut(e);if(!i?.documentId||!t.documentResolver)return;const o=await t.documentResolver(i,e);if(o)return w(o.surface).root?o.surface:o}function ft(e,t){const n=m("div","cultui-modal-backdrop"),i=m("section","cultui-modal");i.setAttribute("role","dialog"),i.setAttribute("aria-modal","true");const o=m("header","cultui-modal-header");o.append(m("h2","","Configure Binding"));const a=m("button","cultui-modal-close","Close");a.type="button",a.addEventListener("click",()=>n.remove()),o.append(a);const l=m("div","cultui-modal-body");i.append(o,l),n.append(i),n.addEventListener("click",s=>{s.target===n&&n.remove()}),document.body.append(n),l.append(m("div","detail","materializing document")),Promise.resolve(e).then(s=>{o.querySelector("h2").textContent=s?.title||"Configure Binding",l.replaceChildren(s?.root?L(s.root,t):H("Embedded document unavailable"))}).catch(s=>{l.replaceChildren(H(`Embedded document failed: ${s instanceof Error?s.message:String(s)}`))})}function In(e,t,n,i,o){const a=w(e.props),l=(e.children||[])[0],s=w(l?.props),f=p(s.anchor,a.anchor,"trigger"),c=p(s.placement,a.placement,"below-start"),r=Number(p(s.offsetX,a.offsetX,"0"))||0,d=Number(p(s.offsetY,a.offsetY,"4"))||0,u=m("div","cultui-modal-backdrop");u.style.background="transparent",u.style.placeItems="start";const h=m("section","cultui-modal");h.setAttribute("role","dialog"),h.setAttribute("aria-modal","true"),h.style.position="fixed",h.style.width="min(420px, calc(100vw - 24px))",h.style.maxHeight="min(620px, calc(100vh - 24px))";const y=m("header","cultui-modal-header");y.append(m("h2","",p(s.title,a.title,a.label,"Options")));const b=m("button","cultui-modal-close","Close");b.type="button",b.addEventListener("click",()=>u.remove()),y.append(b);const x=m("div","cultui-modal-body");if(l){const C=l.children||[];C.length>0?x.replaceChildren(...C.map(D=>L(D,t))):x.append(L(l,t))}else x.append(H("Popup has no content"));h.append(y,x),u.append(h),u.addEventListener("click",C=>{C.target===u&&u.remove()}),document.body.append(u);const T=Tn(f,c,n,h,i,o,r,d);h.style.left=`${T.left}px`,h.style.top=`${T.top}px`}function Tn(e,t,n,i,o,a,l,s){const f=n.getBoundingClientRect(),c=i.getBoundingClientRect(),r=c.width||420,d=c.height||320,u=e==="cursor"?{left:o,right:o,top:a,bottom:a}:f;if(t==="right-down"||t==="dropdown")return ge(u,r,d,l,s,"right","down");if(t==="left-down")return ge(u,r,d,l,s,"left","down");if(t==="right-up")return ge(u,r,d,l,s,"right","up");if(t==="left-up")return ge(u,r,d,l,s,"left","up");switch(t){case"above-start":return O(u.left+l,u.top-d-s,r,d);case"above-end":return O(u.right-r+l,u.top-d-s,r,d);case"below-end":return O(u.right-r+l,u.bottom+s,r,d);case"right-start":return O(u.right+l,u.top+s,r,d);case"left-start":return O(u.left-r-l,u.top+s,r,d);case"center":return O((window.innerWidth-r)/2+l,(window.innerHeight-d)/2+s,r,d);default:return O(u.left+l,u.bottom+s,r,d)}}function ge(e,t,n,i,o,a,l){const f=window.innerWidth-e.right-i-12,c=e.left-i-12,r=window.innerHeight-e.top-o-12,d=e.bottom-o-12,u=a==="right"?f>=t||f>=c:!(c>=t||c>=f),h=l==="down"?r>=n||r>=d:!(d>=n||d>=r),y=u?e.right+i:e.left-t-i,b=h?e.top+o:e.bottom-n-o;return O(y,b,t,n)}function O(e,t,n,i){return{left:Ve(e,12,window.innerWidth-n-12),top:Ve(t,12,window.innerHeight-i-12)}}function Ve(e,t,n){return n @@ -150,4 +150,4 @@ void main() { YBXA - `}function Rn(e,t=document.body){const n=qe(e),i=document.documentElement.style;$n(n.assets.fontCss);for(const[c,r]of Object.entries(fn))i.setProperty(c,r);const o={colorBackground:"--bg",colorBackgroundTop:"--bg-top",colorBackgroundMid:"--bg-mid",colorBackgroundBottom:"--bg-bottom",colorShellSurfaceTop:"--shell-top",colorShellSurfaceBottom:"--shell-bottom",colorPanel:"--panel",colorPanelAlt:"--panel-2",colorPanelBorder:"--line",colorPanelBorderDeep:"--line-deep",colorText:"--text",colorTextBright:"--text-bright",colorMuted:"--quiet",colorAccent:"--accent",colorAccentStrong:"--accent-strong",colorCornerAccent:"--corner-accent",colorLink:"--cyan",colorShadow:"--shadow",colorPixelGrid:"--pixel-grid"};for(const[c,r]of Object.entries(o)){const d=n.tokens[c];d!==void 0&&i.setProperty(r,String(d))}const a=n.tokens.fontBody,l=n.tokens.fontDisplay,s=n.tokens.fontTitle,f=n.tokens.fontMono;a&&i.setProperty("--font-body",be(String(a))),l&&i.setProperty("--font-title",be(String(l))),s&&i.setProperty("--font-title",be(String(s))),f&&i.setProperty("--font-mono",be(String(f))),n.tokens.borderWidthPx&&i.setProperty("--border-width",`${n.tokens.borderWidthPx}px`),n.tokens.borderBottomWidthPx&&i.setProperty("--border-bottom-width",`${n.tokens.borderBottomWidthPx}px`),n.tokens.cornerAccentPx&&i.setProperty("--corner-accent-size",`${n.tokens.cornerAccentPx}px`),t.dataset.pixelArt=n.tokens.pixelArt||n.tokens.imageRendering==="pixelated"?"true":"false",t.dataset.scanlines=n.tokens.scanlineOverlay?"true":"false"}function le(e,t={},n=z){const i=w(t.action),o=n.provider?.providerId||se?.providerId||"surface unknown",a=n.activeSurfaceId||se?.surface?.id||n.provider?.surfaces?.[0]?.surfaceId||o,l=Fn(n,a),s=p(l.commandBoundary,t.commandBoundary,i.commandBoundary,i.target),f=p(l.receiptSchema,t.receiptSchema,i.receiptSchema),c={type:"surface-command",schema:"gamecult.eve.command_invocation.v1",providerId:o,surfaceId:a,command:e||g(i.type,"invoke"),payload:{...i,transport:t.transport??null},issuedAt:new Date().toISOString(),clientId:n.clientId||"eve.browser"};return s&&(c.commandBoundary=s),f&&(c.receiptSchema=f),c}function Fn(e,t){const n=[...e.provider?.surfaces||[],...e.provider?.localAdvertisement?.surfaces||[]];return n.find(i=>i.surfaceId===t&&i.worldInteraction)?.worldInteraction||n.find(i=>i.worldInteraction)?.worldInteraction||{}}function Ze(e,t){const n=w(e.action);return g(e.command,g(e.commandId,g(n.command,g(n.target,g(n.type,t?.commandId||"")))))}function H(e){const t=m("section","pane");return t.append(m("h2","","No Surface")),t.append(m("div","detail",e)),t}function Qe(e,t,n,i,o){e.dataset.commandId=n,e.tabIndex=e instanceof HTMLButtonElement?e.tabIndex:0;const a=()=>{const l=le(n,i,o);o.commandSink?.(l,t)};e.addEventListener("click",a),e.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),a())})}function Pn(e,t,n){const i=Ln(e,t),o=w(i.find(u=>u.kind==="control.box")?.props),a=i.filter(u=>u.kind==="control.part"),l=Number(e.min??0),s=Number(e.max??1),f=m("div","cultui-slider");f.dataset.skin=g(e.skin,"default"),f.dataset.bind=g(e.bind,""),Nn(f,o);const c=m("div","cultui-slider-visual"),r=m("input","cultui-slider-input");r.type="range",r.min=String(l),r.max=String(s),r.step=String(e.step??.01),r.setAttribute("aria-label",g(e.bind,"slider"));for(const u of a){const h=w(u.props),y=m("span",`cultui-slider-part ${g(h.name,"part")}`);Dn(y,h),c.append(y)}return a.some(u=>w(u.props).name==="track")||c.append(m("span","cultui-slider-part track")),a.some(u=>w(u.props).name==="fill")||c.append(m("span","cultui-slider-part fill")),a.some(u=>w(u.props).name==="thumb")||c.append(m("span","cultui-slider-part thumb")),f.append(c,r),(u=>{const h=Number(u??l),y=Math.max(l,Math.min(s,Number.isFinite(h)?h:l)),b=s===l?0:(y-l)/(s-l)*100;r.value=String(y),f.style.setProperty("--cultui-slider-value",`${b}%`),f.dataset.value=String(y)})(e.value??l),r.addEventListener("input",()=>{const u=le(g(e.command,"control.slider.input"),{...e,action:{...w(e.action),value:Number(r.value)},value:Number(r.value)},n);n.commandSink?.(u,{kind:"control.slider",props:e})}),f}function Ln(e,t){const n=typeof e.skin=="string"?e.skin:"",o=[...n?at.controlSkins[n]?.children||[]:[],...t];return o.length?o:[{kind:"control.box",props:{height:18,overflow:"visible"}},{kind:"control.part",props:{name:"track",anchor:"center",size:["100%",6],radius:2,fill:"color.panelInset"}},{kind:"control.part",props:{name:"fill",anchor:["left","center"],size:["value%",6],radius:2,fill:"color.accent"}},{kind:"control.part",props:{name:"thumb",anchor:["value","center"],size:[12,12],bleed:3,radius:999,fill:"color.accent"}}]}function qe(e){if(Array.isArray(e)){const t={},n={};for(const i of e)i?.name&&(i.name==="font.web.google"&&typeof i.value=="string"?n.fontCss=i.value:t[i.name]=i.value);return{tokens:t,assets:n,controlSkins:{}}}return{tokens:w(e?.tokens),assets:w(e?.assets),controlSkins:w(e?.controlSkins)}}function ae(e){if(!e)return"";const t=z.assetUrlResolver;return t?t(e,se):/^(https?:|data:|blob:)/i.test(e)?e:z.assetBaseUrl&&e.startsWith("/")?`${z.assetBaseUrl.replace(/\/+$/,"")}${e}`:e}function $n(e){const t=typeof e=="string"?e.trim():"";if(he?.dataset.href===t||(he?.remove(),he=void 0,!t))return;const n=document.createElement("link");n.rel="preconnect",n.href="https://fonts.gstatic.com",n.crossOrigin="anonymous",document.head.append(n);const i=document.createElement("link");i.rel="stylesheet",i.href=t,i.dataset.href=t,document.head.append(i),he=i}function Mn(e,t,n){const i=[];return(e==="text.title"||t.role==="title")&&i.push("cultui-title","eve-text-title"),e==="text.subtitle"&&i.push("eve-text-subtitle"),e==="label"&&i.push("cultui-label"),t.role==="mono"&&i.push("detail","mono"),i.length===0&&i.push("detail","eve-text"),i.join(" ")}function Nn(e,t){t.height!==void 0&&(e.style.minHeight=R(t.height)),t.width!==void 0&&(e.style.width=R(t.width)),typeof t.overflow=="string"&&(e.style.overflow=t.overflow)}function Dn(e,t){const n=Array.isArray(t.size)?t.size:[t.size,void 0];n[0]!==void 0&&n[0]!=="value%"&&(e.style.width=R(n[0])),n[1]!==void 0&&(e.style.height=R(n[1])),t.radius!==void 0&&(e.style.borderRadius=R(t.radius)),t.fill!==void 0&&(e.style.background=xe(String(t.fill))),t.bleed!==void 0&&e.style.setProperty("--part-bleed",R(t.bleed)),(Array.isArray(t.anchor)?t.anchor:[t.anchor]).includes("value")&&(e.dataset.anchorValue="true")}function ye(e,t){t.gap!==void 0&&(e.style.gap=R(t.gap)),t.padding!==void 0&&(e.style.padding=R(t.padding)),t.size!==void 0&&(e.style.flex=Bn(t.size)),t.min!==void 0&&(e.style.minWidth=R(t.min)),t.max!==void 0&&(e.style.maxWidth=R(t.max)),t.align!==void 0&&(e.style.alignItems=t.align==="end"?"flex-end":String(t.align)),(t.clip==="true"||t.clip===!0)&&(e.style.overflow="hidden"),t.scroll==="y"&&(e.style.overflowY="auto"),t.scroll==="x"&&(e.style.overflowX="auto")}function Bn(e){return typeof e=="string"&&e.endsWith("fr")?`${Number(e.slice(0,-2))||1} 1 0`:e==="auto"||e==="content"?"0 0 auto":`0 0 ${R(e)}`}function R(e){return Array.isArray(e)?e.map(R).join(" "):typeof e=="number"?`${e}px`:typeof e=="string"&&/^-?\d+(\.\d+)?$/.test(e)?`${e}px`:String(e??"")}function xe(e){return{"color.accent":"var(--accent)","color.panelInset":"rgba(0, 0, 0, 0.34)","color.panel":"var(--panel)","color.text":"var(--text)"}[e]||e}function be(e){return e.includes("Zen Kaku Gothic New")||e.includes("M PLUS 1")?e:e.includes("Montserrat")?`${e}, "Zen Kaku Gothic New", "M PLUS 1", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`:e.includes("Ubuntu")?`${e}, "M PLUS 1", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`:`${e}, "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`}function S(e,t){t.id&&(e.id=t.id),t.id&&(e.dataset.eveNodeId=t.id),t.kind&&(e.dataset.eveKind=t.kind)}function w(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function qn(e){return Array.isArray(e)?e:[]}function Un(e){return qn(e).map((t,n)=>lt({kind:"list.item",props:w(t)}))}function g(e,t){return e==null?t:String(e)}function p(...e){for(const t of e){if(typeof t=="string"&&t.trim())return t;if(typeof t=="number"&&Number.isFinite(t))return String(t)}return""}function Ue(e){return typeof e=="boolean"?e:typeof e=="number"?e!==0:typeof e=="string"?["1","true","yes","on"].includes(e.trim().toLowerCase()):!1}function q(e,t){const n=Number(e);return Number.isFinite(n)?Math.max(0,Math.floor(n)):t}function Wn(e){const t=e.toLowerCase();return t.includes("sensor")?"S":t.includes("thermal")?"T":t.includes("fuel")?"F":t.includes("cargo")?"C":t.includes("weapon")?"W":e.trim().slice(0,1).toUpperCase()||"?"}function On(e){const t=e.trim().split(/\s+/).filter(Boolean);return t.length&&t.slice(0,2).map(n=>n[0]?.toUpperCase()||"").join("")||"?"}function et(e){const t=Number(e);return Number.isFinite(t)?Math.max(0,Math.min(100,t)):0}function m(e,t="",n=""){const i=document.createElement(e);return t&&(i.className=t),n&&(i.textContent=n),i}const _e=document.querySelector("#surface"),P=document.querySelector("#status"),U=document.querySelector("#receipt"),mt=document.querySelector("#compiler"),We=document.querySelector("#composer"),Ee=document.querySelector("#destination-form"),pt=document.querySelector("#compiler-results"),ht=document.querySelector("#campaign-lab"),zn=document.querySelector("#campaign-list"),Gn=document.querySelector("#operator-lab");Gn.hidden=!["127.0.0.1","localhost","::1"].includes(window.location.hostname);let de=0,Ce="",Ne=0,gt=0,ke=!1;const Re=new Set;class yt extends Error{}async function ue(e){if(ke)throw new Error("A Ghostlight request is already in progress.");ke=!0,document.body.setAttribute("aria-busy","true");for(const t of document.querySelectorAll("button, input, textarea, select"))t.disabled||(t.disabled=!0,Re.add(t));try{return await e()}finally{for(const t of Re)t.disabled=!1;Re.clear(),document.body.removeAttribute("aria-busy"),ke=!1}}function v(e,t,n){const i=document.createElement(e);return t!==void 0&&(i.textContent=t),n&&(i.className=n),i}function B(e,t){const n=[v("h3",e)];for(const i of t.filter(Boolean))n.push(v("p",i));U.replaceChildren(...n),U.hidden=!1}async function ie(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("json")?e.json():e.text()}function re(e,t){return typeof e=="string"&&e.trim()?e.trim():e&&typeof e.error=="string"&&e.error.trim()?e.error.trim():t}function bt(e){const t=e instanceof Error&&e.message.trim()?e.message.trim():"The Ghostlight connection failed before a response arrived.";if(P.textContent=t,e instanceof yt){B("Request refused",[t,"The server returned an error response. Refresh campaign state before retrying."]);return}B("Request did not complete",[t,"The server remains authoritative. Refresh the campaign before retrying; the lost response may have followed a commit."])}window.addEventListener("unhandledrejection",e=>{e.preventDefault(),bt(e.reason)});function Kn(e){if(e?.kind==="assessed"){const t=e.assessment,n=[v("h3",t.admissible?"Action assessment":"That attempt is not possible")];if(t.admissible){n.push(v("p",`DC ${t.dc} · modifier ${t.modifier_total>=0?"+":""}${t.modifier_total}`));const i=v("ul");for(const o of t.modifiers??[])i.append(v("li",`${o.label}: ${o.value>=0?"+":""}${o.value}`));n.push(i),n.push(v("p",`Strong/success: ${t.success_stake}`)),n.push(v("p",`Mixed: ${t.mixed_stake}`)),n.push(v("p",`Failure: ${t.failure_stake}`)),n.push(v("p",`Effect ceiling: ${t.effect_ceiling}`,"quiet"))}else{n.push(v("p",t.missing_permission??"The attempt has no admissible path from current state."));for(const i of t.bargains??[])n.push(v("p",`Possible bargain: ${i}`))}U.replaceChildren(...n),U.hidden=!1;return}if(e?.kind==="committed"){const t=e.receipt?.roll;if(t){const n=String(t.outcome).replaceAll("_"," ");B(n.charAt(0).toUpperCase()+n.slice(1),[`d20 ${t.d20} ${t.modifier_total>=0?"+":"−"} ${Math.abs(t.modifier_total)} = ${t.total} against DC ${t.dc}`])}else B("World advanced",[`Revision ${e.revision}`]);return}if(e?.kind==="resolution_updated"){B("World resolution updated",[`Resolution epoch ${e.receipt?.resolution_epoch??"advanced"}`]);return}B("Command result",[e?.error??"The world returned no player-facing detail."])}function Xn(){const e="This laboratory requires an unused invite link.";P.textContent=e,mt.hidden=!0,We.hidden=!0,Ee.hidden=!0,ht.hidden=!0,U.hidden=!0,_e.hidden=!1;const t=v("article",void 0,"card");t.append(v("h2","Private campaign laboratory"),v("p",e),v("p","Open one of the two single-use tester invitations on this device. The resulting session stays separate from the other player's campaigns.","quiet")),_e.replaceChildren(t)}async function ce(){const e=await fetch("/api/surface");if(e.status===401){Xn();return}const t=await ie(e);if(!e.ok){P.textContent=re(t,"The campaign surface is temporarily unavailable.");return}const n=t.surface_id==="ghostlight.compiler";if(mt.hidden=!n,We.hidden=n,Ee.hidden=n,_e.hidden=n,ht.hidden=n,n){P.textContent="No campaign exists. Retrieve the Vault and approve a world seed.";return}if(de=Number(t.world_revision??t.version??0),Ce=String(t.player_actor_id??""),!Ce)throw new Error("Campaign surface omitted its canonical player actor ID.");const i=String(t.player_location_id??"");if(!i)throw new Error("Campaign surface omitted its canonical player location ID.");document.querySelector("#destination-origin").value=i,Ne=Number(t.resolution?.policy?.resolution_epoch??0),gt=Number(t.resolution?.policy?.provider_configuration_epoch??0);const o=Number(t.resolution?.policy?.active_cell_budget??8),a=document.querySelector("#active-cell-budget");a.value=String(o),document.querySelector("#active-cell-budget-value").value=String(o),document.querySelector("#resolution-status").textContent=`${t.resolution?.effective_budget??o} effective cells · ${t.resolution?.mandatory_overage??0} temporary overage · epoch ${Ne}`;const l=Number(t.resolution?.policy?.provider_parallelism??8);document.querySelector("#provider-parallelism").value=String(l),document.querySelector("#provider-parallelism-value").value=String(l);const s=document.querySelector("#fission-parent");s.replaceChildren(...(t.resolution?.fission_targets??[]).map(r=>{const d=v("option",`${r.name} · ${r.id}`);return d.value=r.id,d})),document.querySelector("#fission-form").hidden=s.options.length===0,st(t,_e,{body:document.body,clientId:"ghostlight.browser",statusElement:P});const f=await fetch("/api/campaigns"),c=await ie(f);if(!f.ok){P.textContent=re(c,"The campaign list is temporarily unavailable.");return}zn.replaceChildren(...c.campaigns.map(r=>{const d=v("button",`${r.selected?"●":"○"} ${r.name} · revision ${r.revision}`);return d.type="button",d.disabled=!!r.selected,r.selected||d.addEventListener("click",async()=>{await oe(`/api/campaigns/select/${r.id}`,{})}),d}))}async function vt(e,t){P.textContent="Retrieving evidence and compiling…";const n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)}),i=await ie(n);if(!n.ok)throw P.textContent=re(i,"Compilation failed"),new yt(P.textContent);return i}async function ne(e,t){return ue(()=>vt(e,t))}async function oe(e,t){return ue(async()=>{const n=await vt(e,t);return await ce(),n})}function tt(e,t,n){const i=v("div",void 0,"cards");e.forEach((o,a)=>{const l=v("article",void 0,"card");l.append(v("h3",o.title??o.name),v("p",o.player_hook??o.premise)),o.era&&l.append(v("p",`${o.era} · ${o.place} · ${o.pressure}`));const s=v("button",t);s.type="button",s.addEventListener("click",()=>n(e[a])),l.append(s),i.append(l)}),pt.replaceChildren(i)}function W(e,t,n){const i=v("details");i.append(v("summary",t));const o=v("ul");for(const a of n)o.append(v("li",a));n.length===0&&o.append(v("li","None declared.")),i.append(o),e.append(i)}document.querySelector("#suggest-form").addEventListener("submit",async e=>{e.preventDefault();const t=await ne("/api/compiler/openings",{setting:document.querySelector("#setting").value,constraints:[]});tt(t.openings,"Choose opening",async n=>{const i=await ne("/api/compiler/roles",n);tt(i.roles,"Choose role",async o=>xt(await ne("/api/compiler/selected",{campaign_name:n.title,opening:n,role:o})))})});document.querySelector("#custom-form").addEventListener("submit",async e=>{e.preventDefault(),await xt(await ne("/api/compiler/custom",Object.fromEntries(new FormData(e.currentTarget))))});async function xt(e){const t=e.preview,n=Array.isArray(t.evidence_coverage)?t.evidence_coverage:[],i=n.reduce((s,f)=>{const c=String(f?.lane??"excluded");return s[c]=(s[c]??0)+1,s},{}),o=v("article",void 0,"card");o.append(v("h3",t.title),v("p",t.opening??""),v("p",`${t.locations?.length??0} locations · ${(t.cast?.length??0)+1} actors · ${t.institutions?.length??0} institutions`),v("p",t.gaps.length?`Material gaps: ${t.gaps.join("; ")}`:"No declared material gaps.","warning"),v("p",`Branch assumptions: ${t.branch_assumptions.join("; ")||"none"}`),v("p",n.length?`Evidence use: ${i.direct_seed??0} direct · ${i.setting_background??0} background · ${i.excluded??0} excluded`:"Evidence use: no retrieved sources were admitted to this seed.","quiet"));const a=t.player_role??{};W(o,`Player role · ${a.name??"unnamed"}`,[`Starts at ${a.location_id??"an unspecified location"}`,...(a.capabilities??[]).map(s=>`Capability: ${s}`),...(a.equipment??[]).map(s=>`Equipment: ${s}`),...(a.conditions??[]).map(s=>`Condition: ${s}`),...(a.obligations??[]).map(s=>`Obligation: ${s}`)]),W(o,`Initial topology · ${t.locations?.length??0} locations`,(t.locations??[]).map(s=>{const f=Object.keys(s.routes??{});return`${s.name} · ${s.id}${s.container_id?` · inside ${s.container_id}`:""}${f.length?` · routes to ${f.join(", ")}`:" · no compiled route"}`})),W(o,`Present cast · ${t.cast?.length??0}`,(t.cast??[]).map(s=>`${s.name} · ${s.id} · at ${s.location_id}`)),W(o,`Institutions · ${t.institutions?.length??0}`,(t.institutions??[]).map(s=>`${s.name} · ${s.id}`)),W(o,`Populations · ${t.populations?.length??0}`,(t.populations??[]).map(s=>`${s.name} · ${s.id} · at ${s.home_location_id}`)),W(o,`World clocks · ${t.clocks?.length??0}`,(t.clocks??[]).map(s=>`${s.name} · ${s.progress}/${s.threshold} · ${s.trigger}`)),W(o,`Evidence coverage · ${n.length}`,n.map(s=>`${s.source_id} · ${String(s.lane).replaceAll("_"," ")} · ${s.rationale}`));const l=v("button","Approve and enter");l.type="button",l.addEventListener("click",async()=>{await oe(`/api/compiler/approve/${e.preview_id}`,{})}),o.append(l),pt.replaceChildren(o),P.textContent="Preview compiled. Nothing has entered world state yet."}async function fe(e){return ue(async()=>{P.textContent="The world is considering the command…";const t=await fetch("/api/command",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)}),n=await ie(t);if(!t.ok){const i=re(n,"The command was refused.");return B("Command refused",[i]),P.textContent=i,await ce(),n}return Kn(n),await ce(),n})}function wt(e){if(e?.kind!=="assessed")return;const t=document.createElement("button");t.type="button",t.textContent=e.assessment.admissible?"Confirm server roll":"Revise attempt",t.addEventListener("click",async()=>{if(!e.assessment.admissible){document.querySelector("#attempt").focus();return}const n=await fe({type:"attempt",assessment_digest:e.assessment.digest});wt(n)}),U.append(t)}We.addEventListener("submit",async e=>{e.preventDefault();const t=document.querySelector("#attempt").value.trim(),n=document.querySelector("#intended-effect"),i=n.value.trim();if(t){if(!i){P.textContent="Describe the uncertain outcome you want assessed, or use Speak for words that need no roll.",n.focus();return}wt(await fe({type:"assess",expected_revision:de,intent:{actor_id:Ce,description:t,intended_effect:i}}))}});document.querySelector("#speak").addEventListener("click",async()=>{const e=document.querySelector("#attempt"),t=e.value.trim();if(!t){P.textContent="Write what your character says first.",e.focus();return}(await fe({type:"speak",expected_revision:de,actor_id:Ce,text:t,intended_effect:null}))?.kind==="committed"&&(e.value="")});document.querySelector("#wait").addEventListener("click",()=>{fe({type:"wait",expected_revision:de,minutes:60})});document.querySelector("#active-cell-budget").addEventListener("input",e=>{document.querySelector("#active-cell-budget-value").value=e.currentTarget.value});document.querySelector("#resolution-form").addEventListener("submit",async e=>{e.preventDefault(),await fe({type:"set_resolution_budget",expected_revision:de,expected_resolution_epoch:Ne,active_cell_budget:Number(document.querySelector("#active-cell-budget").value)})});document.querySelector("#provider-parallelism").addEventListener("input",e=>{document.querySelector("#provider-parallelism-value").value=e.currentTarget.value});document.querySelector("#provider-parallelism-form").addEventListener("submit",async e=>{e.preventDefault(),await ue(async()=>{P.textContent="Applying the provider concurrency limit…";const t=await fetch("/api/operator/provider-parallelism",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({expected_provider_configuration_epoch:gt,provider_parallelism:Number(document.querySelector("#provider-parallelism").value)})}),n=await ie(t),i=re(n,"The operator limit was refused.");B(t.ok?"Provider concurrency updated":"Provider concurrency refused",[t.ok?`Parallel requests: ${n?.receipt?.provider_parallelism??n?.provider_parallelism??"updated"}`:i]),t.ok||(P.textContent=i),await ce()})});Ee.addEventListener("submit",async e=>{e.preventDefault();const t=await ne("/api/compiler/destination",Object.fromEntries(new FormData(Ee))),n=t.preview;B("Destination preview",(n.gaps??[]).map(o=>`Material gap: ${o}`)),W(U,`Compiled topology · ${n.locations?.length??0} locations`,(n.locations??[]).map(o=>{const a=Object.keys(o.routes??{}),l=[...o.persistent_features??[]];return`${o.name} · ${o.id}${o.container_id?` · inside ${o.container_id}`:""}${a.length?` · routes to ${a.join(", ")}`:" · no compiled route"}${l.length?` · ${l.join(", ")}`:""}`})),P.textContent="Destination preview compiled; topology is unchanged until approval.";const i=v("button","Approve destination");i.type="button",i.addEventListener("click",async()=>{await oe(`/api/compiler/destination/approve/${t.preview_id}`,{}),i.remove()}),U.append(i)});document.querySelector("#fission-form").addEventListener("submit",async e=>{e.preventDefault();const t=new FormData(e.currentTarget),n=await ne("/api/compiler/gestalt/fission",{parent_gestalt_id:t.get("parent_gestalt_id"),partition_axis:t.get("partition_axis"),requested_partition_values:String(t.get("requested_partition_values")??"").split(",").map(o=>o.trim()).filter(Boolean),reason:t.get("reason")});B("Population fission preview",[...(n.preview?.gaps??[]).map(o=>`Material gap: ${o}`)]),W(U,`Canonical child leaves · ${n.preview?.children?.length??0}`,(n.preview?.children??[]).map(o=>`${o.name} · ${o.id} · ${o.partition_value??"other/unknown"} · at ${o.home_location_id}`)),P.textContent="Fission preview compiled. Canonical leaves are unchanged until approval.";const i=document.createElement("button");i.type="button",i.textContent="Approve population fission",i.addEventListener("click",async()=>{await oe(`/api/compiler/gestalt/fission/approve/${n.preview_id}`,{}),i.remove()}),U.append(i)});document.querySelector("#fork-form").addEventListener("submit",async e=>{e.preventDefault(),await oe("/api/campaigns/fork",Object.fromEntries(new FormData(e.currentTarget)))});document.querySelector("#reset-form").addEventListener("submit",async e=>{e.preventDefault(),await oe("/api/campaigns/reset",Object.fromEntries(new FormData(e.currentTarget)))});document.querySelector("#load-operator").addEventListener("click",async()=>{await ue(async()=>{const e=await fetch("/api/operator"),t=await ie(e);if(!e.ok){const n=re(t,"The operator surface is unavailable.");B("Operator inspector refused",[n]),P.textContent=n;return}st(t,document.querySelector("#operator-output"),{body:document.body,clientId:"ghostlight.operator",statusElement:P})})});ce().catch(bt); + `}function Rn(e,t=document.body){const n=qe(e),i=document.documentElement.style;$n(n.assets.fontCss);for(const[c,r]of Object.entries(fn))i.setProperty(c,r);const o={colorBackground:"--bg",colorBackgroundTop:"--bg-top",colorBackgroundMid:"--bg-mid",colorBackgroundBottom:"--bg-bottom",colorShellSurfaceTop:"--shell-top",colorShellSurfaceBottom:"--shell-bottom",colorPanel:"--panel",colorPanelAlt:"--panel-2",colorPanelBorder:"--line",colorPanelBorderDeep:"--line-deep",colorText:"--text",colorTextBright:"--text-bright",colorMuted:"--quiet",colorAccent:"--accent",colorAccentStrong:"--accent-strong",colorCornerAccent:"--corner-accent",colorLink:"--cyan",colorShadow:"--shadow",colorPixelGrid:"--pixel-grid"};for(const[c,r]of Object.entries(o)){const d=n.tokens[c];d!==void 0&&i.setProperty(r,String(d))}const a=n.tokens.fontBody,l=n.tokens.fontDisplay,s=n.tokens.fontTitle,f=n.tokens.fontMono;a&&i.setProperty("--font-body",be(String(a))),l&&i.setProperty("--font-title",be(String(l))),s&&i.setProperty("--font-title",be(String(s))),f&&i.setProperty("--font-mono",be(String(f))),n.tokens.borderWidthPx&&i.setProperty("--border-width",`${n.tokens.borderWidthPx}px`),n.tokens.borderBottomWidthPx&&i.setProperty("--border-bottom-width",`${n.tokens.borderBottomWidthPx}px`),n.tokens.cornerAccentPx&&i.setProperty("--corner-accent-size",`${n.tokens.cornerAccentPx}px`),t.dataset.pixelArt=n.tokens.pixelArt||n.tokens.imageRendering==="pixelated"?"true":"false",t.dataset.scanlines=n.tokens.scanlineOverlay?"true":"false"}function le(e,t={},n=z){const i=w(t.action),o=n.provider?.providerId||se?.providerId||"surface unknown",a=n.activeSurfaceId||se?.surface?.id||n.provider?.surfaces?.[0]?.surfaceId||o,l=Fn(n,a),s=p(l.commandBoundary,t.commandBoundary,i.commandBoundary,i.target),f=p(l.receiptSchema,t.receiptSchema,i.receiptSchema),c={type:"surface-command",schema:"gamecult.eve.command_invocation.v1",providerId:o,surfaceId:a,command:e||g(i.type,"invoke"),payload:{...i,transport:t.transport??null},issuedAt:new Date().toISOString(),clientId:n.clientId||"eve.browser"};return s&&(c.commandBoundary=s),f&&(c.receiptSchema=f),c}function Fn(e,t){const n=[...e.provider?.surfaces||[],...e.provider?.localAdvertisement?.surfaces||[]];return n.find(i=>i.surfaceId===t&&i.worldInteraction)?.worldInteraction||n.find(i=>i.worldInteraction)?.worldInteraction||{}}function Ze(e,t){const n=w(e.action);return g(e.command,g(e.commandId,g(n.command,g(n.target,g(n.type,t?.commandId||"")))))}function H(e){const t=m("section","pane");return t.append(m("h2","","No Surface")),t.append(m("div","detail",e)),t}function Qe(e,t,n,i,o){e.dataset.commandId=n,e.tabIndex=e instanceof HTMLButtonElement?e.tabIndex:0;const a=()=>{const l=le(n,i,o);o.commandSink?.(l,t)};e.addEventListener("click",a),e.addEventListener("keydown",l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),a())})}function Pn(e,t,n){const i=Ln(e,t),o=w(i.find(u=>u.kind==="control.box")?.props),a=i.filter(u=>u.kind==="control.part"),l=Number(e.min??0),s=Number(e.max??1),f=m("div","cultui-slider");f.dataset.skin=g(e.skin,"default"),f.dataset.bind=g(e.bind,""),Nn(f,o);const c=m("div","cultui-slider-visual"),r=m("input","cultui-slider-input");r.type="range",r.min=String(l),r.max=String(s),r.step=String(e.step??.01),r.setAttribute("aria-label",g(e.bind,"slider"));for(const u of a){const h=w(u.props),y=m("span",`cultui-slider-part ${g(h.name,"part")}`);Dn(y,h),c.append(y)}return a.some(u=>w(u.props).name==="track")||c.append(m("span","cultui-slider-part track")),a.some(u=>w(u.props).name==="fill")||c.append(m("span","cultui-slider-part fill")),a.some(u=>w(u.props).name==="thumb")||c.append(m("span","cultui-slider-part thumb")),f.append(c,r),(u=>{const h=Number(u??l),y=Math.max(l,Math.min(s,Number.isFinite(h)?h:l)),b=s===l?0:(y-l)/(s-l)*100;r.value=String(y),f.style.setProperty("--cultui-slider-value",`${b}%`),f.dataset.value=String(y)})(e.value??l),r.addEventListener("input",()=>{const u=le(g(e.command,"control.slider.input"),{...e,action:{...w(e.action),value:Number(r.value)},value:Number(r.value)},n);n.commandSink?.(u,{kind:"control.slider",props:e})}),f}function Ln(e,t){const n=typeof e.skin=="string"?e.skin:"",o=[...n?at.controlSkins[n]?.children||[]:[],...t];return o.length?o:[{kind:"control.box",props:{height:18,overflow:"visible"}},{kind:"control.part",props:{name:"track",anchor:"center",size:["100%",6],radius:2,fill:"color.panelInset"}},{kind:"control.part",props:{name:"fill",anchor:["left","center"],size:["value%",6],radius:2,fill:"color.accent"}},{kind:"control.part",props:{name:"thumb",anchor:["value","center"],size:[12,12],bleed:3,radius:999,fill:"color.accent"}}]}function qe(e){if(Array.isArray(e)){const t={},n={};for(const i of e)i?.name&&(i.name==="font.web.google"&&typeof i.value=="string"?n.fontCss=i.value:t[i.name]=i.value);return{tokens:t,assets:n,controlSkins:{}}}return{tokens:w(e?.tokens),assets:w(e?.assets),controlSkins:w(e?.controlSkins)}}function ae(e){if(!e)return"";const t=z.assetUrlResolver;return t?t(e,se):/^(https?:|data:|blob:)/i.test(e)?e:z.assetBaseUrl&&e.startsWith("/")?`${z.assetBaseUrl.replace(/\/+$/,"")}${e}`:e}function $n(e){const t=typeof e=="string"?e.trim():"";if(he?.dataset.href===t||(he?.remove(),he=void 0,!t))return;const n=document.createElement("link");n.rel="preconnect",n.href="https://fonts.gstatic.com",n.crossOrigin="anonymous",document.head.append(n);const i=document.createElement("link");i.rel="stylesheet",i.href=t,i.dataset.href=t,document.head.append(i),he=i}function Mn(e,t,n){const i=[];return(e==="text.title"||t.role==="title")&&i.push("cultui-title","eve-text-title"),e==="text.subtitle"&&i.push("eve-text-subtitle"),e==="label"&&i.push("cultui-label"),t.role==="mono"&&i.push("detail","mono"),i.length===0&&i.push("detail","eve-text"),i.join(" ")}function Nn(e,t){t.height!==void 0&&(e.style.minHeight=R(t.height)),t.width!==void 0&&(e.style.width=R(t.width)),typeof t.overflow=="string"&&(e.style.overflow=t.overflow)}function Dn(e,t){const n=Array.isArray(t.size)?t.size:[t.size,void 0];n[0]!==void 0&&n[0]!=="value%"&&(e.style.width=R(n[0])),n[1]!==void 0&&(e.style.height=R(n[1])),t.radius!==void 0&&(e.style.borderRadius=R(t.radius)),t.fill!==void 0&&(e.style.background=xe(String(t.fill))),t.bleed!==void 0&&e.style.setProperty("--part-bleed",R(t.bleed)),(Array.isArray(t.anchor)?t.anchor:[t.anchor]).includes("value")&&(e.dataset.anchorValue="true")}function ye(e,t){t.gap!==void 0&&(e.style.gap=R(t.gap)),t.padding!==void 0&&(e.style.padding=R(t.padding)),t.size!==void 0&&(e.style.flex=Bn(t.size)),t.min!==void 0&&(e.style.minWidth=R(t.min)),t.max!==void 0&&(e.style.maxWidth=R(t.max)),t.align!==void 0&&(e.style.alignItems=t.align==="end"?"flex-end":String(t.align)),(t.clip==="true"||t.clip===!0)&&(e.style.overflow="hidden"),t.scroll==="y"&&(e.style.overflowY="auto"),t.scroll==="x"&&(e.style.overflowX="auto")}function Bn(e){return typeof e=="string"&&e.endsWith("fr")?`${Number(e.slice(0,-2))||1} 1 0`:e==="auto"||e==="content"?"0 0 auto":`0 0 ${R(e)}`}function R(e){return Array.isArray(e)?e.map(R).join(" "):typeof e=="number"?`${e}px`:typeof e=="string"&&/^-?\d+(\.\d+)?$/.test(e)?`${e}px`:String(e??"")}function xe(e){return{"color.accent":"var(--accent)","color.panelInset":"rgba(0, 0, 0, 0.34)","color.panel":"var(--panel)","color.text":"var(--text)"}[e]||e}function be(e){return e.includes("Zen Kaku Gothic New")||e.includes("M PLUS 1")?e:e.includes("Montserrat")?`${e}, "Zen Kaku Gothic New", "M PLUS 1", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`:e.includes("Ubuntu")?`${e}, "M PLUS 1", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`:`${e}, "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`}function S(e,t){t.id&&(e.id=t.id),t.id&&(e.dataset.eveNodeId=t.id),t.kind&&(e.dataset.eveKind=t.kind)}function w(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function qn(e){return Array.isArray(e)?e:[]}function Un(e){return qn(e).map((t,n)=>lt({kind:"list.item",props:w(t)}))}function g(e,t){return e==null?t:String(e)}function p(...e){for(const t of e){if(typeof t=="string"&&t.trim())return t;if(typeof t=="number"&&Number.isFinite(t))return String(t)}return""}function Ue(e){return typeof e=="boolean"?e:typeof e=="number"?e!==0:typeof e=="string"?["1","true","yes","on"].includes(e.trim().toLowerCase()):!1}function q(e,t){const n=Number(e);return Number.isFinite(n)?Math.max(0,Math.floor(n)):t}function Wn(e){const t=e.toLowerCase();return t.includes("sensor")?"S":t.includes("thermal")?"T":t.includes("fuel")?"F":t.includes("cargo")?"C":t.includes("weapon")?"W":e.trim().slice(0,1).toUpperCase()||"?"}function On(e){const t=e.trim().split(/\s+/).filter(Boolean);return t.length&&t.slice(0,2).map(n=>n[0]?.toUpperCase()||"").join("")||"?"}function et(e){const t=Number(e);return Number.isFinite(t)?Math.max(0,Math.min(100,t)):0}function m(e,t="",n=""){const i=document.createElement(e);return t&&(i.className=t),n&&(i.textContent=n),i}const _e=document.querySelector("#surface"),F=document.querySelector("#status"),U=document.querySelector("#receipt"),mt=document.querySelector("#compiler"),We=document.querySelector("#composer"),Ee=document.querySelector("#destination-form"),pt=document.querySelector("#compiler-results"),ht=document.querySelector("#campaign-lab"),zn=document.querySelector("#campaign-list"),Gn=document.querySelector("#operator-lab");Gn.hidden=!["127.0.0.1","localhost","::1"].includes(window.location.hostname);let de=0,Ce="",Ne=0,gt=0,ke=!1;const Re=new Set;class yt extends Error{}async function ue(e){if(ke)throw new Error("A Ghostlight request is already in progress.");ke=!0,document.body.setAttribute("aria-busy","true");for(const t of document.querySelectorAll("button, input, textarea, select"))t.disabled||(t.disabled=!0,Re.add(t));try{return await e()}finally{for(const t of Re)t.disabled=!1;Re.clear(),document.body.removeAttribute("aria-busy"),ke=!1}}function v(e,t,n){const i=document.createElement(e);return t!==void 0&&(i.textContent=t),n&&(i.className=n),i}function B(e,t){const n=[v("h3",e)];for(const i of t.filter(Boolean))n.push(v("p",i));U.replaceChildren(...n),U.hidden=!1}async function ie(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("json")?e.json():e.text()}function re(e,t){return typeof e=="string"&&e.trim()?e.trim():e&&typeof e.error=="string"&&e.error.trim()?e.error.trim():t}function bt(e){const t=e instanceof Error&&e.message.trim()?e.message.trim():"The Ghostlight connection failed before a response arrived.";if(F.textContent=t,e instanceof yt){B("Request refused",[t,"The server returned an error response. Refresh campaign state before retrying."]);return}B("Request did not complete",[t,"The server remains authoritative. Refresh the campaign before retrying; the lost response may have followed a commit."])}window.addEventListener("unhandledrejection",e=>{e.preventDefault(),bt(e.reason)});function Kn(e){if(e?.kind==="assessed"){const t=e.assessment,n=[v("h3",t.admissible?"Action assessment":"That attempt is not possible")];if(t.admissible){n.push(v("p",`DC ${t.dc} · modifier ${t.modifier_total>=0?"+":""}${t.modifier_total}`));const i=v("ul");for(const o of t.modifiers??[])i.append(v("li",`${o.label}: ${o.value>=0?"+":""}${o.value}`));n.push(i),n.push(v("p",`Strong/success: ${t.success_stake}`)),n.push(v("p",`Mixed: ${t.mixed_stake}`)),n.push(v("p",`Failure: ${t.failure_stake}`)),n.push(v("p",`Effect ceiling: ${t.effect_ceiling}`,"quiet"))}else{n.push(v("p",t.missing_permission??"The attempt has no admissible path from current state."));for(const i of t.bargains??[])n.push(v("p",`Possible bargain: ${i}`))}U.replaceChildren(...n),U.hidden=!1;return}if(e?.kind==="committed"){const t=e.receipt?.roll;if(t){const n=String(t.outcome).replaceAll("_"," ");B(n.charAt(0).toUpperCase()+n.slice(1),[`d20 ${t.d20} ${t.modifier_total>=0?"+":"−"} ${Math.abs(t.modifier_total)} = ${t.total} against DC ${t.dc}`])}else B("World advanced",[`Revision ${e.revision}`]);return}if(e?.kind==="resolution_updated"){B("World resolution updated",[`Resolution epoch ${e.receipt?.resolution_epoch??"advanced"}`]);return}B("Command result",[e?.error??"The world returned no player-facing detail."])}function Xn(){const e="This laboratory requires an unused invite link.";F.textContent=e,mt.hidden=!0,We.hidden=!0,Ee.hidden=!0,ht.hidden=!0,U.hidden=!0,_e.hidden=!1;const t=v("article",void 0,"card");t.append(v("h2","Private campaign laboratory"),v("p",e),v("p","Open one of the two single-use tester invitations on this device. The resulting session stays separate from the other player's campaigns.","quiet")),_e.replaceChildren(t)}async function ce(){const e=await fetch("/api/surface");if(e.status===401){Xn();return}const t=await ie(e);if(!e.ok){F.textContent=re(t,"The campaign surface is temporarily unavailable.");return}const n=t.surface_id==="ghostlight.compiler";if(mt.hidden=!n,We.hidden=n,Ee.hidden=n,_e.hidden=n,ht.hidden=n,n){F.textContent="No campaign exists. Retrieve the Vault and approve a world seed.";return}if(de=Number(t.world_revision??t.version??0),Ce=String(t.player_actor_id??""),!Ce)throw new Error("Campaign surface omitted its canonical player actor ID.");const i=String(t.player_location_id??"");if(!i)throw new Error("Campaign surface omitted its canonical player location ID.");document.querySelector("#destination-origin").value=i,Ne=Number(t.resolution?.policy?.resolution_epoch??0),gt=Number(t.resolution?.policy?.provider_configuration_epoch??0);const o=Number(t.resolution?.policy?.active_cell_budget??8),a=document.querySelector("#active-cell-budget");a.value=String(o),document.querySelector("#active-cell-budget-value").value=String(o),document.querySelector("#resolution-status").textContent=`${t.resolution?.effective_budget??o} effective cells · ${t.resolution?.mandatory_overage??0} temporary overage · epoch ${Ne}`;const l=Number(t.resolution?.policy?.provider_parallelism??8);document.querySelector("#provider-parallelism").value=String(l),document.querySelector("#provider-parallelism-value").value=String(l);const s=document.querySelector("#fission-parent");s.replaceChildren(...(t.resolution?.fission_targets??[]).map(r=>{const d=v("option",`${r.name} · ${r.id}`);return d.value=r.id,d})),document.querySelector("#fission-form").hidden=s.options.length===0,st(t,_e,{body:document.body,clientId:"ghostlight.browser",statusElement:F});const f=await fetch("/api/campaigns"),c=await ie(f);if(!f.ok){F.textContent=re(c,"The campaign list is temporarily unavailable.");return}zn.replaceChildren(...c.campaigns.map(r=>{const d=v("button",`${r.selected?"●":"○"} ${r.name} · revision ${r.revision}`);return d.type="button",d.disabled=!!r.selected,r.selected||d.addEventListener("click",async()=>{await oe(`/api/campaigns/select/${r.id}`,{})}),d}))}async function vt(e,t){F.textContent="Retrieving evidence and compiling…";const n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(t)}),i=await ie(n);if(!n.ok)throw F.textContent=re(i,"Compilation failed"),new yt(F.textContent);return i}async function ne(e,t){return ue(()=>vt(e,t))}async function oe(e,t){return ue(async()=>{const n=await vt(e,t);return await ce(),n})}function tt(e,t,n){const i=v("div",void 0,"cards");e.forEach((o,a)=>{const l=v("article",void 0,"card");l.append(v("h3",o.title??o.name),v("p",o.player_hook??o.premise)),o.era&&l.append(v("p",`${o.era} · ${o.place} · ${o.pressure}`));const s=v("button",t);s.type="button",s.addEventListener("click",()=>n(e[a])),l.append(s),i.append(l)}),pt.replaceChildren(i)}function W(e,t,n){const i=v("details");i.append(v("summary",t));const o=v("ul");for(const a of n)o.append(v("li",a));n.length===0&&o.append(v("li","None declared.")),i.append(o),e.append(i)}document.querySelector("#suggest-form").addEventListener("submit",async e=>{e.preventDefault();const t=await ne("/api/compiler/openings",{setting:document.querySelector("#setting").value,constraints:[]});tt(t.openings,"Choose opening",async n=>{const i=await ne("/api/compiler/roles",n);tt(i.roles,"Choose role",async o=>xt(await ne("/api/compiler/selected",{campaign_name:n.title,opening:n,role:o})))})});document.querySelector("#custom-form").addEventListener("submit",async e=>{e.preventDefault(),await xt(await ne("/api/compiler/custom",Object.fromEntries(new FormData(e.currentTarget))))});async function xt(e){const t=e.preview,n=Array.isArray(t.evidence_coverage)?t.evidence_coverage:[],i=n.reduce((s,f)=>{const c=String(f?.lane??"excluded");return s[c]=(s[c]??0)+1,s},{}),o=v("article",void 0,"card");o.append(v("h3",t.title),v("p",t.opening??""),v("p",`${t.locations?.length??0} locations · ${(t.cast?.length??0)+1} actors · ${t.institutions?.length??0} institutions`),v("p",t.gaps.length?`Material gaps: ${t.gaps.join("; ")}`:"No declared material gaps.","warning"),v("p",`Branch assumptions: ${t.branch_assumptions.join("; ")||"none"}`),v("p",n.length?`Evidence use: ${i.direct_seed??0} direct · ${i.setting_background??0} background · ${i.excluded??0} excluded`:"Evidence use: no retrieved sources were admitted to this seed.","quiet"));const a=t.player_role??{};W(o,`Player role · ${a.name??"unnamed"}`,[`Starts at ${a.location_id??"an unspecified location"}`,...(a.capabilities??[]).map(s=>`Capability: ${s}`),...(a.equipment??[]).map(s=>`Equipment: ${s}`),...(a.conditions??[]).map(s=>`Condition: ${s}`),...(a.obligations??[]).map(s=>`Obligation: ${s}`)]),W(o,`Initial topology · ${t.locations?.length??0} locations`,(t.locations??[]).map(s=>{const f=Object.keys(s.routes??{});return`${s.name} · ${s.id}${s.container_id?` · inside ${s.container_id}`:""}${f.length?` · routes to ${f.join(", ")}`:" · no compiled route"}`})),W(o,`Present cast · ${t.cast?.length??0}`,(t.cast??[]).map(s=>`${s.name} · ${s.id} · at ${s.location_id}`)),W(o,`Institutions · ${t.institutions?.length??0}`,(t.institutions??[]).map(s=>`${s.name} · ${s.id}`)),W(o,`Populations · ${t.populations?.length??0}`,(t.populations??[]).map(s=>`${s.name} · ${s.id} · at ${s.home_location_id}`)),W(o,`World clocks · ${t.clocks?.length??0}`,(t.clocks??[]).map(s=>`${s.name} · ${s.progress}/${s.threshold} · ${s.trigger}`)),W(o,`Evidence coverage · ${n.length}`,n.map(s=>`${s.source_id} · ${String(s.lane).replaceAll("_"," ")} · ${s.rationale}`));const l=v("button","Approve and enter");l.type="button",l.addEventListener("click",async()=>{await oe(`/api/compiler/approve/${e.preview_id}`,{})}),o.append(l),pt.replaceChildren(o),F.textContent="Preview compiled. Nothing has entered world state yet."}async function fe(e){return ue(async()=>{F.textContent="The world is considering the command…";const t=await fetch("/api/command",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)}),n=await ie(t);if(!t.ok){const i=re(n,"The command was refused.");return B("Command refused",[i]),F.textContent=i,await ce(),n}return Kn(n),await ce(),n})}function wt(e){if(e?.kind!=="assessed")return;const t=document.createElement("button");t.type="button",t.textContent=e.assessment.admissible?"Confirm server roll":"Revise attempt",t.addEventListener("click",async()=>{if(!e.assessment.admissible){document.querySelector("#attempt").focus();return}const n=await fe({type:"attempt",assessment_digest:e.assessment.digest});wt(n)}),U.append(t)}We.addEventListener("submit",async e=>{e.preventDefault();const t=document.querySelector("#attempt").value.trim(),n=document.querySelector("#intended-effect"),i=n.value.trim();if(t){if(!i){F.textContent="Describe the uncertain outcome you want assessed, or use Speak for words that need no roll.",n.focus();return}wt(await fe({type:"assess",expected_revision:de,intent:{actor_id:Ce,description:t,intended_effect:i}}))}});document.querySelector("#speak").addEventListener("click",async()=>{const e=document.querySelector("#attempt"),t=e.value.trim();if(!t){F.textContent="Write what your character says first.",e.focus();return}(await fe({type:"speak",expected_revision:de,actor_id:Ce,text:t,intended_effect:null}))?.kind==="committed"&&(e.value="")});document.querySelector("#wait").addEventListener("click",()=>{fe({type:"wait",expected_revision:de,minutes:60})});document.querySelector("#active-cell-budget").addEventListener("input",e=>{document.querySelector("#active-cell-budget-value").value=e.currentTarget.value});document.querySelector("#resolution-form").addEventListener("submit",async e=>{e.preventDefault(),await fe({type:"set_resolution_budget",expected_revision:de,expected_resolution_epoch:Ne,active_cell_budget:Number(document.querySelector("#active-cell-budget").value)})});document.querySelector("#provider-parallelism").addEventListener("input",e=>{document.querySelector("#provider-parallelism-value").value=e.currentTarget.value});document.querySelector("#provider-parallelism-form").addEventListener("submit",async e=>{e.preventDefault(),await ue(async()=>{F.textContent="Applying the provider concurrency limit…";const t=await fetch("/api/operator/provider-parallelism",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({expected_provider_configuration_epoch:gt,provider_parallelism:Number(document.querySelector("#provider-parallelism").value)})}),n=await ie(t),i=re(n,"The operator limit was refused.");B(t.ok?"Provider concurrency updated":"Provider concurrency refused",[t.ok?`Parallel requests: ${n?.receipt?.provider_parallelism??n?.provider_parallelism??"updated"}`:i]),t.ok||(F.textContent=i),await ce()})});Ee.addEventListener("submit",async e=>{e.preventDefault();const t=await ne("/api/compiler/destination",Object.fromEntries(new FormData(Ee))),n=t.preview;B("Destination preview",(n.gaps??[]).map(o=>`Material gap: ${o}`)),W(U,`Compiled topology · ${n.locations?.length??0} locations`,(n.locations??[]).map(o=>{const a=Object.keys(o.routes??{}),l=[...o.persistent_features??[]];return`${o.name} · ${o.id}${o.container_id?` · inside ${o.container_id}`:""}${a.length?` · routes to ${a.join(", ")}`:" · no compiled route"}${l.length?` · ${l.join(", ")}`:""}`})),F.textContent="Destination preview compiled; topology is unchanged until approval.";const i=v("button","Approve destination");i.type="button",i.addEventListener("click",async()=>{await oe(`/api/compiler/destination/approve/${t.preview_id}`,{}),i.remove()}),U.append(i)});document.querySelector("#fission-form").addEventListener("submit",async e=>{e.preventDefault();const t=new FormData(e.currentTarget),n=String(t.get("requested_partition_values")??"").split(",").map(a=>a.trim()).filter(Boolean);if(n.length>16||n.some(a=>[...a].length>160)){F.textContent="Use at most 16 named cuts, with at most 160 characters in each cut.",document.querySelector("#fission-values").focus();return}const i=await ne("/api/compiler/gestalt/fission",{parent_gestalt_id:t.get("parent_gestalt_id"),partition_axis:t.get("partition_axis"),requested_partition_values:n,reason:t.get("reason")});B("Population fission preview",[...(i.preview?.gaps??[]).map(a=>`Material gap: ${a}`)]),W(U,`Canonical child leaves · ${i.preview?.children?.length??0}`,(i.preview?.children??[]).map(a=>`${a.name} · ${a.id} · ${a.partition_value??"other/unknown"} · at ${a.home_location_id}`)),F.textContent="Fission preview compiled. Canonical leaves are unchanged until approval.";const o=document.createElement("button");o.type="button",o.textContent="Approve population fission",o.addEventListener("click",async()=>{await oe(`/api/compiler/gestalt/fission/approve/${i.preview_id}`,{}),o.remove()}),U.append(o)});document.querySelector("#fork-form").addEventListener("submit",async e=>{e.preventDefault(),await oe("/api/campaigns/fork",Object.fromEntries(new FormData(e.currentTarget)))});document.querySelector("#reset-form").addEventListener("submit",async e=>{e.preventDefault(),await oe("/api/campaigns/reset",Object.fromEntries(new FormData(e.currentTarget)))});document.querySelector("#load-operator").addEventListener("click",async()=>{await ue(async()=>{const e=await fetch("/api/operator"),t=await ie(e);if(!e.ok){const n=re(t,"The operator surface is unavailable.");B("Operator inspector refused",[n]),F.textContent=n;return}st(t,document.querySelector("#operator-output"),{body:document.body,clientId:"ghostlight.operator",statusElement:F})})});ce().catch(bt); diff --git a/web/dist/index.html b/web/dist/index.html index 61b0267..d9c5098 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -1,5 +1,5 @@ -GhostlightDungeon +GhostlightDungeon

STARFIRE / PRIVATE VERSE

GhostlightDungeon

Reading the world…

@@ -7,10 +7,10 @@

Or describe your own beginning

-

Use Speak when the words themselves are the action. Use Assess attempt when you want the words or action to persuade, deceive, intimidate, overcome resistance, or cause another uncertain effect.

+

Use Speak when the words themselves are the action. Use Assess attempt when you want the words or action to persuade, deceive, intimidate, overcome resistance, or cause another uncertain effect.

Compile a destination without moving there

diff --git a/web/index.html b/web/index.html index 6cec9c4..7c54ac9 100644 --- a/web/index.html +++ b/web/index.html @@ -5,10 +5,10 @@

Or describe your own beginning

-

Use Speak when the words themselves are the action. Use Assess attempt when you want the words or action to persuade, deceive, intimidate, overcome resistance, or cause another uncertain effect.

+

Use Speak when the words themselves are the action. Use Assess attempt when you want the words or action to persuade, deceive, intimidate, overcome resistance, or cause another uncertain effect.

Compile a destination without moving there

diff --git a/web/src/main.ts b/web/src/main.ts index 0a0b375..bf0c5ee 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -415,10 +415,16 @@ destinationForm.addEventListener("submit", async event => { document.querySelector("#fission-form")!.addEventListener("submit", async event => { event.preventDefault(); const data = new FormData(event.currentTarget as HTMLFormElement); + const cuts = String(data.get("requested_partition_values") ?? "").split(",").map(value => value.trim()).filter(Boolean); + if (cuts.length > 16 || cuts.some(value => [...value].length > 160)) { + status.textContent = "Use at most 16 named cuts, with at most 160 characters in each cut."; + document.querySelector("#fission-values")!.focus(); + return; + } const result = await compilerPost("/api/compiler/gestalt/fission", { parent_gestalt_id: data.get("parent_gestalt_id"), partition_axis: data.get("partition_axis"), - requested_partition_values: String(data.get("requested_partition_values") ?? "").split(",").map(value => value.trim()).filter(Boolean), + requested_partition_values: cuts, reason: data.get("reason"), }); showSummary("Population fission preview", [