diff --git a/CHANGELOG.md b/CHANGELOG.md index b76e203..0f80f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,25 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) · Versioning: ## [Unreleased] +## [0.6.1] - 2026-07-21 + +### Fixed +- **The full learning loop now fits a 320 px window.** A compact Menu replaces + the crowded action rail, the architecture Map waits for real layout + dimensions before fitting, guidance gets its own row instead of covering Map + controls, and Study becomes a full-stage reading sheet. The header, canvas, + guidance, and local-only status remain visible without horizontal overflow. +- **Modules and Find work from the Star chart.** Both global commands now render + their surface in chart mode instead of accepting a click into hidden state + that only appeared after returning to the galaxy. +- **First-run guidance no longer competes with Home calibration.** After an + audience is chosen, a required Home choice finishes before the three-step + coach opens, so there is one decision in the foreground at a time. +- **Canvas clicks no longer corrupt OrbitControls pointer state.** Codemble's + parser-owned node layout is now explicitly non-draggable, preventing the 3D + dependency's drag-end bridge from injecting a synthetic touch release into a + mouse release. A stale-pointer guard and focused contract pin the fallback. + ## [0.6.0] - 2026-07-21 ### Added diff --git a/CLAUDE.md b/CLAUDE.md index 78d9c2d..2225e3e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -168,7 +168,14 @@ Polish, then the coordinated launch (Show HN / X; lit-galaxy GIF as hero). ## Current State **[AGENT-MAINTAINED]** **Current milestone: Phase 1 tester evidence** · Last updated: 2026-07-21 · -Session note: the v0.6.0 architecture-depth pass is complete in five +Session note: v0.6.1 closes the four verified user-flow gaps from the +2026-07-21 usability audit: the 320 px shell reserves a usable map/study stage, +Modules and Find render from the Star chart, required Home calibration finishes +before coach marks begin, and parser-owned 3D nodes no longer install drag +controls that can corrupt OrbitControls pointer state. The release is verified +against the real bundled app at desktop and 320 px widths; the milestone does +not advance because issue #13 still requires human tester evidence. The v0.6.0 +architecture-depth pass is complete in five behavior-preserving waves: project selection owns the home-jailed filesystem policy; project activation atomically owns parse-to-live binding and graph/map caches; project mapping owns picker attempts, polling, retry, outage, stale @@ -534,6 +541,7 @@ shows lower repeated-commit work without changing derived values. | 2026-07-21 | Architecture boxes are named by the tail of their file path (`short_label`, map schema 3); `label` keeps the full identifier for title and aria | A box is a fixed width, so its text always truncates on a real project — and truncating a dotted region id rendered `codemble.server.app` and `codemble.server.runtime` as the same glyphs. Identical text for different modules is worse than no label, and it is exactly the kind of wrong a learner cannot detect. The path tail also survives the `__init__.py` collision a basename alone cannot | | 2026-07-21 | The Map gains zoom, Fit, and drag-to-pan; panning rides the container's own scroll and zoom only scales the rendered size | The 2D counterpart of bounded orbit: a 960x2640 diagram in a plain scroll box showed four of nine layers and no way to see the whole shape. Scroll-based panning keeps native scrollbars, keyboard scrolling and screen-reader behaviour intact, and because every coordinate inside the SVG stays backend-computed, React remains a pure renderer of graph-owned geometry. It opens at true size rather than auto-fitting: fitting on mount measured the scroller before layout settled and landed on a scale that was neither fitted nor honest | | 2026-07-21 | v0.6.0 deepens five private boundaries without changing the HTTP, graph, check, persistence, or learner-visible contracts: Project Selection, Project Activation, Project Mapping Run, Name Atlas, and Learner Projection | Approved by UD as five behavior-preserving waves in one release PR. The deletion test now holds at each seam, stale activation and mapping responses lose atomically, and dependency-scoped learner projections measured ~0.331 ms → ~0.001 ms per hover commit on a synthetic 1,000-node project while preserving derived outputs | +| 2026-07-21 | v0.6.1 treats Modules and Find as global surfaces, sequences first-run decisions as audience → required Home → coach, and makes the 3D parser-owned layout explicitly non-draggable | Approved by UD as implementation of every verified user-flow audit finding. Global commands must never accept hidden state, onboarding must expose one foreground decision at a time, and learners orbit the immutable graph rather than editing its coordinates. The compact shell is a structural breakpoint of the existing Formal Edo interface, not a new visual system | ## Non-Goals — do NOT build (point here when asked) diff --git a/codemble/__init__.py b/codemble/__init__.py index 882d5f1..28ed4e3 100644 --- a/codemble/__init__.py +++ b/codemble/__init__.py @@ -1,4 +1,4 @@ """Codemble — a learning game that turns the code AI wrote for you into a galaxy you light up by understanding it. See CLAUDE.md for the agent brief and roadmap.""" -__version__ = "0.6.0" +__version__ = "0.6.1" diff --git a/codemble/web_dist/assets/index-BWorxSL3.js b/codemble/web_dist/assets/index-0OmvUbwQ.js similarity index 95% rename from codemble/web_dist/assets/index-BWorxSL3.js rename to codemble/web_dist/assets/index-0OmvUbwQ.js index cd39bf3..73cdc7b 100644 --- a/codemble/web_dist/assets/index-BWorxSL3.js +++ b/codemble/web_dist/assets/index-0OmvUbwQ.js @@ -5349,4 +5349,4 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho float bloomAlpha = max( bloom.r, max( bloom.g, bloom.b ) ); gl_FragColor = vec4( bloom, bloomAlpha ); - }`})}};UW.BlurDirectionX=new L(1,0),UW.BlurDirectionY=new L(0,1);var WW=.9,GW=.45,KW=.52,qW=1600;function JW(e){let t=e.postProcessingComposer(),n=new UW(new L(t._width??1,t._height??1),WW,GW,KW),r=n.setSize.bind(n);n.setSize=(e,t)=>{let n=Math.min(1,qW/Math.max(e,t,1));r(Math.max(1,Math.round(e*n)),Math.max(1,Math.round(t*n)))},t.addPass(n);let i=new Ez(xz);return t.addPass(i),{pass:n,composer:t,dispose(){t.removePass(i),i.dispose(),t.removePass(n),n.dispose()}}}var YW=1200;function XW(){return globalThis.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches??!1}function ZW({scene:e,regionId:t,palette:n}){if(XW())return()=>{};let r=e.getObjectByName(`codemble-system-${t}`);if(!r)return()=>{};let i=[];r.traverse(e=>{e.isSprite&&i.push([e,e.material.opacity,e.scale.x])});let a=new B(n.star),o=i.map(([e])=>e.material.color.clone()),s=0,c=performance.now(),l=()=>{let e=Math.min(1,(performance.now()-c)/YW);1-(1-e)**3;let t=Math.sin(e*Math.PI);if(i.forEach(([e,n,r],i)=>{e.material.color.copy(o[i]).lerp(a,t*.85),e.material.opacity=n+t*.5,e.scale.setScalar(r*(1+t*.45))}),e<1){s=requestAnimationFrame(l);return}i.forEach(([e,t,n],r)=>{e.material.color.copy(o[r]),e.material.opacity=t,e.scale.setScalar(n)})};return s=requestAnimationFrame(l),()=>{cancelAnimationFrame(s),i.forEach(([e,t,n],r)=>{e.material.color.copy(o[r]),e.material.opacity=t,e.scale.setScalar(n)})}}var QW=Object.freeze({width:132,height:30}),$W=Object.freeze({far:14,near:44}),eG=Object.freeze([0,-1,1,-2,2]),tG=4,nG=.034;function rG(e,{radius:t,aspect:n}){return e.scale.set(nG*n,nG,1),e.userData.baseOffsetY=t*2.2+1.2,e.position.set(0,e.userData.baseOffsetY,0),e.visible=!1,e.userData.codembleLabel=!0,e.userData.screenWidthFraction=nG*n,e.userData.screenHeightFraction=nG,e}function iG(e){let t=aG(e),n=new R,r=new R;function i({scene:e,camera:i,width:a,height:o,distance:s,distanceBounds:c,hoverNodeId:l=null}){let u=oG(e);for(let e of u)e.visible=!1;if(!u.length||!t.size)return Object.freeze({budget:0,shown:0,visibleIds:Object.freeze([])});let d=sG(s,c),f=[];for(let e of u){let s=e.userData.nodeId,c=e.parent;if(!c)continue;c.getWorldPosition(r);let u=e.userData.baseOffsetY??0,d=cG(r,u,i,a,o,n);if(!d)continue;let p=cG(r,u+1,i,a,o,n),m=p?Math.abs(p.screenY-d.screenY):0;f.push({sprite:e,nodeId:s,origin:r.clone(),base:u,pixelsPerUnit:m,anchor:d,halfWidth:(e.userData.screenWidthFraction??.14)*o/2,halfHeight:(e.userData.screenHeightFraction??.034)*o/2,rank:s===l?-1:t.get(s)??1/0})}f.sort((e,t)=>e.rank-t.rank||e.nodeId.localeCompare(t.nodeId));let p=new Set,m=[];for(let e of f){if(m.length>=d)break;let t=lG(e,{camera:i,width:a,height:o,projected:n,taken:p});if(t){for(let e of t.cells)p.add(e);e.sprite.position.y=e.base+t.offset,e.sprite.visible=!0,m.push(e.nodeId)}}return Object.freeze({budget:d,shown:m.length,visibleIds:Object.freeze(m)})}function a(e){for(let t of oG(e))t.visible=!1}return Object.freeze({hide:a,place:i})}function aG(e){let t=e.filter(e=>e.label).map(e=>({id:e.id,weight:(e.home?3e6:0)+(e.understood?1e6:0)+(e.centrality??0)*1e3})).sort((e,t)=>t.weight-e.weight||e.id.localeCompare(t.id));return new Map(t.map((e,t)=>[e.id,t]))}function oG(e){let t=[];return e.traverse(e=>{e.userData?.codembleLabel&&t.push(e)}),t}function sG(e,t){let n=Math.max(1,t.max-t.min),r=1-Math.min(1,Math.max(0,(e-t.min)/n));return Math.round($W.far+($W.near-$W.far)*r)}function cG(e,t,n,r,i,a){if(a.set(e.x,e.y+t,e.z).project(n),a.z>1)return null;let o=(a.x*.5+.5)*r,s=(-a.y*.5+.5)*i;return o<0||o>r||s<0||s>i?null:{screenX:o,screenY:s}}function lG(e,{camera:t,width:n,height:r,projected:i,taken:a}){let o=e.pixelsPerUnit?(e.halfHeight*2+tG)/e.pixelsPerUnit:0;for(let s of eG){let c=s*o,l=s===0?e.anchor:cG(e.origin,e.base+c,t,n,r,i);if(!l)continue;let u=uG(l,e);if(!u.some(e=>a.has(e)))return{cells:u,offset:c}}return null}function uG(e,{halfWidth:t,halfHeight:n}){let r=Math.floor((e.screenX-t)/QW.width),i=Math.floor((e.screenX+t)/QW.width),a=Math.floor((e.screenY-n)/QW.height),o=Math.floor((e.screenY+n)/QW.height),s=[];for(let e=r;e<=i;e+=1)for(let t=a;t<=o;t+=1)s.push(`${e}:${t}`);return s}var dG=128,fG=256;function pG(e,t){let n=document.createElement(`canvas`);n.width=e,n.height=e;let r=n.getContext(`2d`),i=r.createRadialGradient(e/2,e/2,0,e/2,e/2,e/2);for(let[e,n]of t)i.addColorStop(e,`rgba(255, 255, 255, ${n})`);r.fillStyle=i,r.fillRect(0,0,e,e);let a=new Ra(n);return a.colorSpace=lt,a}function mG(e){let t=document.createElement(`canvas`);t.width=e,t.height=e;let n=t.getContext(`2d`);n.strokeStyle=`rgba(255, 255, 255, 1)`,n.lineWidth=e*.05,n.beginPath(),n.arc(e/2,e/2,e*.4,0,Math.PI*2),n.stroke();let r=new Ra(t);return r.colorSpace=lt,r}function hG(e){let t=[];function n(e){let n=e.dispose.bind(e);return e.dispose=()=>{},t.push(n),e}let r=n(pG(dG,[[0,.85],[.25,.42],[.6,.1],[1,0]])),i=n(pG(fG,[[0,.32],[.45,.14],[.8,.03],[1,0]])),a=n(mG(dG)),o=new Map,s=new Map,c=new Map;function l(t){return c.has(t)||c.set(t,n(vG(t,e))),c.get(t)}function u(t){return o.has(t)||o.set(t,n(new Si({map:r,color:new B(t).multiply(new B(e.starHalo)),blending:2,transparent:!0,depthWrite:!1,opacity:.6}))),o.get(t)}return{halo(e,t){let n=new Ii(u(e.color));return n.scale.setScalar(t*6.5),n.renderOrder=-1,n},nebula(e,t){s.has(e)||s.set(e,n(new Si({map:i,color:new B(e),blending:2,transparent:!0,depthWrite:!1,opacity:.16})));let r=new Ii(s.get(e));return r.scale.setScalar(t),r.renderOrder=-2,r},reticle(t){let n=new Ii(new Si({map:a,color:new B(e.orbit),transparent:!0,depthWrite:!1,depthTest:!1}));return n.scale.setScalar(t*5),n.renderOrder=3,n},label(e,t){let n=l(e),r=new Ii(n);return rG(r,{radius:t,aspect:n.userData.aspect??4}),r.renderOrder=4,r},dispose(){for(let e of t)e();t.length=0,o.clear(),s.clear(),c.clear()}}}var gG=34,_G=12;function vG(e,t){let n=document.createElement(`canvas`),r=n.getContext(`2d`),i=`${gG}px "JetBrains Mono", ui-monospace, monospace`;r.font=i;let a=Math.ceil(r.measureText(e).width)+_G*2;n.width=a,n.height=58,r.font=i,r.textBaseline=`middle`,r.textAlign=`center`,r.fillStyle=t.labelPlate,yG(r,0,0,a,58,8),r.fill(),r.fillStyle=t.labelInk,r.fillText(e,a/2,30);let o=new Ra(n);o.colorSpace=lt;let s=new Si({map:o,transparent:!0,depthWrite:!1,depthTest:!1,sizeAttenuation:!1});s.userData.aspect=a/58;let c=s.dispose.bind(s);return s.dispose=()=>{o.dispose(),c()},s}function yG(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.arcTo(t+r,n,t+r,n+i,a),e.arcTo(t+r,n+i,t,n+i,a),e.arcTo(t,n+i,t,n,a),e.arcTo(t,n,t+r,n,a),e.closePath()}function bG(e){return Object.entries(e??{}).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}:${t}`).join(`|`)}function xG(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}function SG(e){let t=2166136261;for(let n=0;n>>0}function CG(e,t,n=1400,r=1600){let i=xG(SG(e)),a=new Float32Array(n*3);for(let e=0;ee.language===t),r=new Set(n.map(e=>e.id)),i=new Set(e.nodes.map(e=>e.id)),a=new Set(n.map(e=>e.region)),o=new Set(n.map(e=>e.file));return{...e,nodes:n,edges:e.edges.filter(e=>r.has(e.src)&&(r.has(e.dst)||e.external||!i.has(e.dst))),entrypoint_candidates:e.entrypoint_candidates.filter(e=>r.has(e)),selected_entrypoint:r.has(e.selected_entrypoint)?e.selected_entrypoint:null,file_hashes:Object.fromEntries(Object.entries(e.file_hashes).filter(([e])=>o.has(e))),concept_annotations:e.concept_annotations.filter(e=>e.language===t&&r.has(e.node_id)),regions:e.regions.filter(e=>a.has(e.id)),region_edges:e.region_edges.filter(e=>a.has(e.src)&&a.has(e.dst)),partial_files:e.partial_files.filter(e=>o.has(e))}}function EG(e,t){if(!e||!t||t===`all`)return e;let n=e.architecture,r=n.boxes.filter(e=>e.language===t),i=new Set(r.map(e=>e.id)),a=e.workflow,o=`${t}:`;return{...e,architecture:{...n,boxes:r,edges:n.edges.filter(e=>i.has(e.src)&&i.has(e.dst)),unreachable:n.unreachable.filter(e=>i.has(e))},workflow:{...a,nodes:a.nodes.filter(e=>e.language===t),unreachable:a.unreachable.filter(e=>e.startsWith(o))}}}function DG(e){let t=new Map;for(let n of e.regions)t.set(n.language,(t.get(n.language)??0)+1);let n=[...t].map(([e,t])=>({id:e,label:AG(e),shortLabel:jG(e),count:t})).sort((e,t)=>e.label.localeCompare(t.label));return[{id:`all`,label:`All languages`,shortLabel:`All`,count:e.regions.length},...n]}function OG(e,t){let n=new Map(e.nodes.map(e=>[e.id,e])),r=new Map;for(let i of e.concept_annotations??[]){let e=`${i.language}:${i.concept}`,a=r.get(e)??{language:i.language,concept:i.concept,occurrences:0,nodeIds:new Set,studiedNodeIds:new Set,understoodNodeIds:new Set};a.occurrences+=1,a.nodeIds.add(i.node_id),t.has(i.node_id)&&a.studiedNodeIds.add(i.node_id),n.get(i.node_id)?.understood&&a.understoodNodeIds.add(i.node_id),r.set(e,a)}return[...r.values()].map(e=>({language:e.language,concept:e.concept,occurrences:e.occurrences,nodes:e.nodeIds.size,studied_nodes:e.studiedNodeIds.size,understood_nodes:e.understoodNodeIds.size})).sort((e,t)=>e.language.localeCompare(t.language)||e.concept.localeCompare(t.concept))}function kG(e){let t={javascript:`JavaScript`,jsx:`JSX`,typescript:`TypeScript`};return t[e]?t[e]:e.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function AG(e){return kG(e)}function jG(e){return e===`javascript`?`JS`:e===`typescript`?`TS`:AG(e)}function MG(e){return e===`python`?`nebPython`:e===`javascript`?`nebJs`:e===`typescript`?`nebTs`:null}var NG=2;function PG(e,{showAll:t=!1,selectionId:n=null}={}){let r=()=>new Set(e.regions.map(e=>e.id));if(t||!e.regions.some(e=>e.home))return r();let i=new Set,a=new Set;for(let t of e.regions)typeof t.hops_from_home==`number`&&t.hops_from_home<=NG&&i.add(t.id),t.understood&&a.add(t.id);n&&a.add(n);for(let e of a)i.add(e);for(let t of e.region_edges)(a.has(t.src)||a.has(t.dst))&&(i.add(t.src),i.add(t.dst));return i}function FG(e){let t=new Map;for(let n of e.nodes)t.has(n.region)||t.set(n.region,n.file);return t}function IG(e){return e.split(`/`).filter(Boolean).at(-1)??e}function LG(e){let t=FG(e);return e.regions.map(e=>({id:e.id,file:t.get(e.id)??e.id,label:IG(t.get(e.id)??e.id),language:e.language,community:e.community,understood:e.understood,home:e.home,hops:typeof e.hops_from_home==`number`?e.hops_from_home:null,centrality:e.centrality,loc:e.loc})).sort((e,t)=>e.label.localeCompare(t.label)||e.id.localeCompare(t.id))}function RG(e){if(!e.length)return``;let t=e.map(e=>e.file.split(`/`).slice(0,-1)),n=t[0];for(let e of t.slice(1)){let t=0;for(;t{let n=RG(t),r=n.endsWith(`/`)?n:``;return{community:e,name:n,members:t.map(e=>({...e,display:r&&e.file.startsWith(r)?e.file.slice(r.length):e.file})).sort((e,t)=>e.display.localeCompare(t.display))}}).sort((e,t)=>t.members.length-e.members.length||e.community-t.community)}var BG=5,VG=2;function HG(e,t,n=null){let r=e=>n===null||n.has(e),i=FG(e);return{nodes:e.regions.map(n=>{let a=r(n.id);return{...n,kind:`region`,name:n.id,label:a?IG(i.get(n.id)??n.id):``,charted:a,fx:n.x,fy:n.y,fz:n.z,val:qG(n.loc,5,24),color:a?n.understood?t.star:e.nodes.some(e=>e.region===n.id&&e.partial)?t.routePossible:JG(n.centrality,t,BG):t.nodeDim,focusDim:!1}}),links:e.region_edges.filter(e=>r(e.src)&&r(e.dst)).map(e=>({...e,source:e.src,target:e.dst,color:e.certain?t.route:t.routePossible,focusDim:!1}))}}function UG(e,t,n,{selectedId:r=null}={}){let i=e.nodes.filter(e=>e.region===t),a=new Set(i.map(e=>e.id)),o=e.edges.filter(e=>e.kind===`call`&&!e.external&&a.has(e.src)&&a.has(e.dst)),s=new Set(r?[r]:[]);if(r)for(let e of o)e.src===r&&s.add(e.dst),e.dst===r&&s.add(e.src);return{nodes:i.map(e=>({...e,fx:e.system_x,fy:e.system_y,fz:e.system_z,val:qG(e.loc,2.8,11),color:e.understood?n.star:e.partial?n.routePossible:JG(e.centrality,n,VG),selected:e.id===r,focusDim:!!r&&!s.has(e.id)})),links:o.map(e=>({...e,source:e.src,target:e.dst,color:e.certain?n.route:n.routePossible,focusDim:!!r&&e.src!==r&&e.dst!==r}))}}function WG(e){return e.regions.find(e=>e.home)??e.regions[0]??null}function GG(e){let t=e.kind===`region`?`star system`:e.kind,n=e.partial?` · unchartable · syntax error`:``,r=e.home?` · Home`:``;return`${e.name} · ${t} · ${e.loc} LOC${r}${n}`}function KG(e){let t=e.kind===`import`?`import`:e.kind===`call`?`call`:`import route`,n=e.certain?`certain`:t===`call`?`possible call`:`possible import`,r=typeof e.weight==`number`?` · ${e.weight} ${e.weight===1?`import`:`imports`}`:``,i=typeof e.lineno==`number`?` · line ${e.lineno}`:``;return`${e.src} → ${e.dst} · ${t} · ${n}${r}${i}`}function qG(e,t,n){return Math.min(n,Math.max(t,Math.sqrt(Math.max(1,e))*1.15))}function JG(e,t,n){return e>=n?t.nodeBright:e>=1?t.node:t.nodeDim}var YG=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),$=o(((e,t)=>{t.exports=YG()}))(),XG=420,ZG=1.6,QG={GALAXY:{min:120,max:640},SYSTEM:{min:55,max:320},STUDY:{min:22,max:170}},$G=.16,eK=1.5,tK=110,nK=6;function rK({graph:e,level:t,region:n,selectedNode:r,hoverNodeId:i,pendingDawnRegionId:a,revealedRegionIds:o,mode:s,onHoverNode:c,onAdvance:l,onRetreat:u,onDawnConsumed:d}){let f=(0,_.useRef)(null),p=(0,_.useRef)(null),m=(0,_.useRef)(null),h=(0,_.useRef)(l),g=(0,_.useRef)(u),v=(0,_.useRef)(c),y=(0,_.useRef)(a),b=(0,_.useRef)(d),x=(0,_.useRef)(null),S=(0,_.useRef)({activeId:null,neighborIds:new Set}),C=(0,_.useRef)(null),w=(0,_.useRef)(null),T=(0,_.useRef)(null),[E,D]=(0,_.useState)(0),[O,k]=(0,_.useState)(``),A=(0,_.useMemo)(sK,[]),ee=(0,_.useMemo)(XW,[]),te=bG(e.file_hashes),ne=(0,_.useMemo)(()=>t===wG.GALAXY?HG(e,A,o):UG(e,n?.id,A,{selectedId:r?.id}),[e,t,A,n?.id,o,r?.id]);(0,_.useEffect)(()=>{h.current=l,g.current=u,v.current=c,y.current=a,b.current=d},[l,u,c,a,d]);function re(e){let{activeId:t,neighborIds:n}=S.current;return t?e.id===t?A.orbit:n.has(e.id)?e.color:A.faded:e.color}function ie(e){if(e.focusDim)return A.faded;let{activeId:t,neighborIds:n}=S.current,r=e.certain?A.route:A.routePossible;if(!t)return r;let i=aK(e.source),a=aK(e.target);return i===t||a===t?A.orbit:n.has(i)&&n.has(a)?r:A.faded}function j(e){if(e.focusDim)return .4;let{activeId:t}=S.current,n=Math.min(2.2,.45+(e.weight??1)*.25);if(!t)return n;let r=aK(e.source),i=aK(e.target);return r===t||i===t?n+.9:n}(0,_.useEffect)(()=>{let e=f.current;if(!e)return;let t=document.createElement(`canvas`);if(!t.getContext(`webgl2`)&&!t.getContext(`webgl`)){k(`Codemble needs WebGL to draw your galaxy. Enable WebGL and reload.`);return}try{let t=hG(A);C.current=t;let n=BW({controlType:`orbit`})(e).backgroundColor(A.ground).showNavInfo(!1).enableNavigationControls(!0).warmupTicks(0).cooldownTicks(0).nodeId(`id`).nodeLabel(GG).nodeVal(`val`).nodeColor(re).nodeRelSize(ZG).nodeResolution(8).nodeOpacity(.82).nodeThreeObject(e=>iK(e,A,t,T.current)).nodeThreeObjectExtend(!0).linkColor(ie).linkLabel(KG).linkOpacity(.32).linkWidth(j).linkCurvature(.12).linkVisibility(e=>!(s===`easy`&&e.focusDim)).linkHoverPrecision(4).linkDirectionalArrowRelPos(1).linkDirectionalArrowColor(ie).linkDirectionalParticles(e=>e.kind===`call`&&e.certain&&!e.focusDim&&!ee?2:0).linkDirectionalParticleSpeed(.006).linkDirectionalParticleWidth(1.1).linkDirectionalParticleColor(()=>A.orbit).onNodeHover(t=>{e.style.cursor=t?`pointer`:`default`,v.current(t?.id??null)}).onNodeClick(e=>h.current(e)),r=requestAnimationFrame(()=>{e.querySelector(`.scene-nav-info`)?.remove()}),i=n.controls();i.enablePan=!1,i.enableDamping=!ee,i.dampingFactor=.12,i.rotateSpeed=.55,i.zoomSpeed=.7,i.minPolarAngle=$G,i.maxPolarAngle=eK,m.current=i,w.current=JW(n),p.current=n;let a=new ResizeObserver(([e])=>{n.width(e.contentRect.width).height(e.contentRect.height)});return a.observe(e),()=>{a.disconnect(),cancelAnimationFrame(r),n.pauseAnimation(),w.current?.dispose(),w.current=null,n._destructor(),t.dispose(),C.current=null,m.current=null,e.replaceChildren(),p.current=null}}catch(e){k(`The galaxy could not start: ${e.message}`);return}},[A]),(0,_.useEffect)(()=>{let e=p.current;if(!e)return;e.nodeResolution(ne.nodes.length>=900?4:8).linkVisibility(e=>!(s===`easy`&&e.focusDim)).linkDirectionalArrowLength(t===wG.GALAXY?0:3.2).graphData(ne);let n=QG[t]??QG.GALAXY;m.current&&(m.current.minDistance=n.min,m.current.maxDistance=n.max),t===wG.GALAXY?e.cameraPosition({x:0,y:105,z:310},{x:0,y:0,z:0},XG):e.cameraPosition({x:0,y:52,z:150},{x:0,y:0,z:0},XG),D(0)},[ne,t,s]),(0,_.useEffect)(()=>{T.current=ne.nodes[E]?.id??null,p.current?.refresh()},[ne.nodes,E]),(0,_.useEffect)(()=>{let e=p.current;if(!e)return;let t=e.scene(),n=t.getObjectByName(`codemble-starfield`);n&&(t.remove(n),n.geometry.dispose(),n.material.dispose());let r=CG(te,A);return t.add(r),()=>{t.remove(r),r.geometry.dispose(),r.material.dispose()}},[te,A]),(0,_.useEffect)(()=>{let e=p.current;if(!e||t!==wG.GALAXY)return;let n=y.current;if(!n||x.current===n)return;x.current=n,b.current?.(n);let r=!1,i=()=>{},a=t=>{if(r)return;let s=e.scene();if(s.getObjectByName(`codemble-system-${n}`)||t>=nK){i=ZW({scene:s,regionId:n,palette:A});return}o=requestAnimationFrame(()=>a(t+1))},o=requestAnimationFrame(()=>a(0));return()=>{r=!0,cancelAnimationFrame(o),i()}},[t,A]),(0,_.useEffect)(()=>{let e=i??(t===wG.STUDY?r?.id??null:null),n=new Set;if(e)for(let t of ne.links){let r=aK(t.source),i=aK(t.target);r===e&&n.add(i),i===e&&n.add(r)}S.current={activeId:e,neighborIds:n};let a=p.current;a&&a.nodeColor(a.nodeColor()).linkColor(a.linkColor()).linkWidth(a.linkWidth()).linkDirectionalArrowColor(a.linkDirectionalArrowColor())},[ne,i,t,r?.id]);let M=(0,_.useMemo)(()=>iG(ne.nodes),[ne.nodes]);(0,_.useEffect)(()=>{let e=p.current;if(!e)return;let n=e.scene();function r(){let r=e.camera(),a=m.current,o=QG[t]??QG.GALAXY,s=a?r.position.distanceTo(a.target):r.position.length();M.place({scene:n,camera:r,width:e.width(),height:e.height(),distance:s,distanceBounds:o,hoverNodeId:i})}let a=null;function o(){try{r()}catch(e){a!==null&&clearInterval(a),M.hide(n),console.error(`Codemble: label declutter failed, names disabled`,e)}}return o(),a=setInterval(o,tK),()=>{clearInterval(a),M.hide(n)}},[i,t,M]),(0,_.useEffect)(()=>{if(!new URLSearchParams(window.location.search).has(`benchmark`)||ne.nodes.length<900)return;document.documentElement.removeAttribute(`data-codemble-fps`);let e=setTimeout(()=>{let e=p.current;if(!e)return;let t=e.renderer(),n=e.postProcessingComposer(),r=performance.now();for(let e=0;e<60;e+=1)n.render();t.getContext().finish();let i=performance.now()-r;document.documentElement.dataset.codembleFps=(60*1e3/i).toFixed(1)},1e3);return()=>clearTimeout(e)},[ne.nodes.length]),(0,_.useEffect)(()=>{!r||!p.current||t!==wG.STUDY||p.current.cameraPosition({x:r.system_x+20,y:r.system_y+15,z:r.system_z+42},{x:r.system_x,y:r.system_y,z:r.system_z},XG)},[t,r]);let ae=ne.nodes[E]??null;function oe(e){e.key===`ArrowRight`||e.key===`ArrowDown`?(e.preventDefault(),D(e=>(e+1)%Math.max(1,ne.nodes.length))):e.key===`ArrowLeft`||e.key===`ArrowUp`?(e.preventDefault(),D(e=>(e-1+ne.nodes.length)%Math.max(1,ne.nodes.length))):e.key===`Enter`&&ae?(e.preventDefault(),h.current(ae)):(e.key===`Escape`||e.key===`Backspace`)&&(e.preventDefault(),g.current())}return O?(0,$.jsxs)(`section`,{className:`webgl-error`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The sky could not open.`}),(0,$.jsx)(`p`,{children:O}),(0,$.jsxs)(`p`,{children:[`The `,s===`easy`?`Diagram`:`Map`,` layer works without WebGL — switch to it at the top of the window to explore the same code.`]})]}):(0,$.jsxs)(`div`,{className:`galaxy-frame`,role:`application`,tabIndex:`0`,"aria-label":`Codemble ${t.toLowerCase()} view. Drag to orbit, scroll to zoom. Use arrow keys to choose a node and Enter to move closer.`,onKeyDown:oe,children:[(0,$.jsx)(`div`,{ref:f,className:`galaxy-canvas`,"aria-hidden":`true`}),ae?(0,$.jsx)(`output`,{className:`keyboard-focus`,"aria-live":`polite`,children:GG(ae)}):null]})}function iK(e,t,n,r){let i=new lr;i.name=e.kind===`region`?`codemble-system-${e.id}`:`codemble-node-${e.id}`;let a=Math.cbrt(e.val??1)*ZG,o=e.charted===!1;if(!e.focusDim&&!o&&i.add(n.halo(e,a)),e.kind===`region`&&!o){let r=MG(e.language);r&&i.add(n.nebula(t[r],a*14))}if(e.label){let t=n.label(e.label,a);t.userData.nodeId=e.id,i.add(t)}if(e.home){let e=new ia(new xo(a*1.7,Math.max(.18,a*.07),8,36),new Ki({color:t.home}));e.rotation.x=Math.PI/2.8,i.add(e)}if(e.selected){let e=new ia(new xo(a*2.1,Math.max(.16,a*.05),6,24),new Ki({color:t.orbit}));e.rotation.x=Math.PI/2.8,i.add(e)}return e.id===r&&i.add(n.reticle(a)),i}function aK(e){return typeof e==`object`&&e?e.id:e}function oK(e){let t=document.createElement(`canvas`).getContext(`2d`);t.fillStyle=`#000000`,t.fillStyle=e,t.fillRect(0,0,1,1);let[n,r,i]=t.getImageData(0,0,1,1).data;return`rgb(${n}, ${r}, ${i})`}function sK(){let e=getComputedStyle(document.documentElement),t=t=>oK(e.getPropertyValue(t).trim());return Object.freeze({ground:t(`--cm-ground`),home:t(`--cm-ink`),orbit:t(`--cm-orbit`),nodeBright:t(`--cm-ink-2`),node:t(`--cm-ink-3`),nodeDim:t(`--cm-node-unlit`),route:t(`--cm-hairline`),routePossible:t(`--cm-route-possible`),faded:t(`--cm-hairline-soft`),star:t(`--cm-star-high`),starHalo:t(`--cm-star-halo`),nebPython:t(`--cm-neb-python`),nebJs:t(`--cm-neb-js`),nebTs:t(`--cm-neb-ts`),labelPlate:e.getPropertyValue(`--cm-label-plate`).trim(),labelInk:e.getPropertyValue(`--cm-label-ink`).trim()})}function cK({hint:e,onStudy:t}){return e?(0,$.jsxs)(`output`,{className:`hint-chip`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`→`}),(0,$.jsxs)(`span`,{children:[`Study `,(0,$.jsx)(`strong`,{children:e.regionId}),` next`]}),(0,$.jsx)(`small`,{children:e.reason}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>t(e.regionId),children:`Take me there`})]}):null}var lK=[{title:`What you see`,body:`Every star system is one file, named once you have charted it. Size is how much code it holds; brightness is how many places in your project call it. Faint unnamed markers are modules you have not reached yet.`},{title:`How to move`,body:`Drag to look around and scroll to zoom — the view stays locked on whatever you are studying, so you cannot get lost. Click a system to go in, Escape to come back, and press ⌘K to jump straight to any module by name.`},{title:`What lights stars`,body:`A system lights up only after you answer questions drawn from your own code. Nothing lights up just by looking at it — and each one you light reveals the modules it connects to.`}],uK=[{title:`What you see`,body:`Every box is one file, placed by how your imports connect them. A dashed link is a relationship the parser could not fully prove.`},{title:`How to move`,body:`Click a box to study that module, or press ⌘K to jump to one by name. The tabs above show how it fits together and what runs first. Switch to the Galaxy anytime to fly through the same code.`},{title:`What lights up`,body:`A module lights up only after you answer questions drawn from your own code. Nothing lights up just by looking at it.`}];function dK({layer:e,onDismiss:t}){let[n,r]=(0,_.useState)(0),i=(0,_.useRef)(null),a=e===`map`?uK:lK,o=a[n];(0,_.useLayoutEffect)(()=>{let e=i.current;e&&!e.open&&e.showModal()},[]);function s(){i.current?.close(),t()}return(0,$.jsxs)(`dialog`,{ref:i,className:`coach-marks`,"aria-labelledby":`coach-heading`,onCancel:e=>{e.preventDefault(),s()},children:[(0,$.jsxs)(`p`,{className:`coach-marks__progress`,children:[`Step `,n+1,` of `,a.length]}),(0,$.jsx)(`h1`,{id:`coach-heading`,children:o.title}),(0,$.jsx)(`p`,{children:o.body}),(0,$.jsxs)(`div`,{className:`coach-marks__actions`,children:[(0,$.jsx)(`button`,{type:`button`,className:`coach-skip`,onClick:s,children:`Skip`}),(0,$.jsx)(`button`,{type:`button`,className:`check-primary`,onClick:()=>n+1{let n=i.current?.getBoundingClientRect();!n||!e||!t||o(hK(Math.min(n.width/e,n.height/t)))},[e,t]);function d(e){if(e.button!==0||e.target.closest(`[role='button']`))return;let t=i.current;l.current={x:e.clientX,y:e.clientY,left:t.scrollLeft,top:t.scrollTop},c(!0),t.setPointerCapture(e.pointerId)}function f(e){if(!l.current)return;let t=i.current;t.scrollLeft=l.current.left-(e.clientX-l.current.x),t.scrollTop=l.current.top-(e.clientY-l.current.y)}function p(e){l.current&&(l.current=null,c(!1),i.current?.releasePointerCapture?.(e.pointerId))}return(0,$.jsxs)(`div`,{className:`map-canvas`,children:[(0,$.jsxs)(`div`,{className:`map-zoom`,role:`group`,"aria-label":`Zoom ${n}`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom out`,disabled:a<=fK,onClick:()=>o(e=>hK(e/mK)),children:`−`}),(0,$.jsx)(`button`,{type:`button`,onClick:u,children:`Fit`}),(0,$.jsxs)(`button`,{type:`button`,onClick:()=>o(1),children:[Math.round(a*100),`%`]}),(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom in`,disabled:a>=pK,onClick:()=>o(e=>hK(e*mK)),children:`+`})]}),(0,$.jsx)(`div`,{ref:i,className:`map-scroll`,"data-panning":s||void 0,onPointerDown:d,onPointerMove:f,onPointerUp:p,onPointerCancel:p,children:(0,$.jsx)(`div`,{className:`map-canvas__sized`,style:{width:e*a,height:t*a},children:r})})]})}var _K={nebPython:`var(--cm-neb-python)`,nebJs:`var(--cm-neb-js)`,nebTs:`var(--cm-neb-ts)`};function vK(e){let t=MG(e);return t?_K[t]:`var(--cm-hairline)`}function yK(e){return e.map(([e,t],n)=>`${n===0?`M`:`L`} ${e} ${t}`).join(` `)}function bK(e){return 1+Math.min(2.5,(Math.max(1,e)-1)*.5)}var xK=13,SK=.62,CK=14,wK=6;function TK(e,t){let n=t-CK-wK,r=Math.max(1,Math.floor(n/(xK*SK)));return e.length<=r?e:`${e.slice(0,Math.max(1,r-1))}…`}function EK({data:e,mapTab:t,mode:n,selectedRegionId:r,hasEntrypointCandidates:i,error:a,onSelectTab:o,onSelectRegion:s,onSelectNode:c,onRetry:l,children:u}){return(0,$.jsxs)(`section`,{className:`map-view`,"aria-label":`Two-dimensional project map`,children:[(0,$.jsxs)(`nav`,{className:`map-tabs`,"aria-label":`Map view`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`architecture`,onClick:()=>o(`architecture`),children:n===`easy`?`How it fits together`:`Architecture`}),(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`workflow`,onClick:()=>o(`workflow`),children:n===`easy`?`What runs first`:`Workflow`})]}),u,a?(0,$.jsxs)(`div`,{className:`map-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The map did not load.`}),(0,$.jsxs)(`p`,{children:[a,` The galaxy layer is unaffected.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:l,children:`Try again`})]}):e?t===`architecture`?(0,$.jsx)(DK,{architecture:e.architecture,mode:n,selectedRegionId:r,hasEntrypointCandidates:i,onSelectRegion:s}):(0,$.jsx)(OK,{workflow:e.workflow,mode:n,selectedRegionId:r,hasEntrypointCandidates:i,onSelectNode:c}):(0,$.jsx)(`p`,{className:`map-loading`,role:`status`,children:`Laying out parser evidence…`})]})}function DK({architecture:e,mode:t,selectedRegionId:n,hasEntrypointCandidates:r,onSelectRegion:i}){let a=new Map(e.boxes.map(e=>[e.id,e]));return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(gK,{contentWidth:e.width+64,contentHeight:e.height+64,label:`the architecture map`,children:(0,$.jsxs)(`svg`,{className:`architecture-map`,width:`100%`,height:`100%`,preserveAspectRatio:`xMidYMin meet`,viewBox:`-32 -32 ${e.width+64} ${e.height+64}`,role:`group`,"aria-label":e.home?`${e.boxes.length} modules in ${e.layer_count} import layers from Home`:`${e.boxes.length} modules in ${e.layer_count} import layers, measured from the modules nothing imports`,children:[(0,$.jsxs)(`defs`,{children:[(0,$.jsx)(`marker`,{id:`architecture-arrow`,className:`architecture-map__arrow`,markerWidth:`8`,markerHeight:`8`,refX:`8`,refY:`4`,orient:`auto`,markerUnits:`strokeWidth`,children:(0,$.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 Z`,fill:`currentColor`})}),(0,$.jsx)(`marker`,{id:`architecture-cycle-arrow`,className:`architecture-map__arrow is-cycle`,markerWidth:`8`,markerHeight:`8`,refX:`8`,refY:`4`,orient:`auto`,markerUnits:`strokeWidth`,children:(0,$.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 Z`,fill:`currentColor`})})]}),(0,$.jsx)(`g`,{className:`architecture-map__edges`,children:e.edges.map(e=>{let t=a.get(e.src),n=a.get(e.dst);return!t||!n?null:(0,$.jsx)(`path`,{d:yK(e.points),strokeDasharray:e.certain?void 0:`5 4`,strokeWidth:bK(e.weight),markerEnd:`url(#${e.cycle?`architecture-cycle-arrow`:`architecture-arrow`})`,className:`architecture-map__edge${e.cycle?` is-cycle`:``}`},`${e.src}->${e.dst}`)})}),e.boxes.map(e=>(0,$.jsxs)(`g`,{className:`architecture-map__box`,"data-understood":e.understood,"data-home":e.home,"data-reachable":e.reachable,"data-partial":e.partial,"data-selected":e.id===n,transform:`translate(${e.x} ${e.y})`,role:`button`,tabIndex:0,"aria-label":`${e.label}, ${e.node_count} structures, ${e.loc} lines${e.understood?`, understood`:`, not yet understood`}${e.home?`, Home`:``}${e.reachable?``:`, no import route from Home`}${e.partial?`, unchartable, syntax error`:``}`,onClick:()=>i(e.id),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),i(e.id))},children:[(0,$.jsxs)(`title`,{children:[e.label,e.partial?` — unchartable, syntax error`:``]}),(0,$.jsx)(`rect`,{width:e.width,height:e.height,rx:`3`}),(0,$.jsx)(`rect`,{className:`box-tint`,width:`4`,height:e.height,fill:vK(e.language)}),e.partial?(0,$.jsx)(`path`,{className:`box-partial`,d:`M ${e.width-16} 2 L ${e.width-2} 2 L ${e.width-2} 16 Z`}):null,(0,$.jsx)(`text`,{x:CK,y:`24`,children:TK(e.short_label??e.label,e.width)}),(0,$.jsx)(`text`,{className:`box-meta`,x:`14`,y:`42`,children:t===`easy`?`${e.node_count} ${e.node_count===1?`piece`:`pieces`}`:`${e.node_count} nodes · ${e.loc} LOC`})]},e.id))]})}),e.home?null:(0,$.jsxs)(`p`,{className:`map-note`,children:[`No Home is selected, so these layers run from the modules nothing else imports rather than from your entrypoint. Both are read from your imports, not guessed.`,` `,r?`Pick your starting point with “Change Home” to see the same modules layered by what the project runs first.`:`This project has no parser-recognisable entrypoint, so there is no “runs first” order to layer by instead.`]}),e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`module has`:`modules have`,` no import route from Home, so `,e.unreachable.length===1?`it sits`:`they sit`,` `,`in the bottom row rather than being placed by guesswork.`]}):null]})}function OK({workflow:e,mode:t,selectedRegionId:n,hasEntrypointCandidates:r,onSelectNode:i}){if(!e.root)return r?(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No Home is selected.`}),(0,$.jsx)(`p`,{children:`The workflow tree starts at your entrypoint. Pick Home and this tab will show what runs first, then what that calls.`})]}):(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No “runs first” order to show.`}),(0,$.jsx)(`p`,{children:`This project has no parser-recognisable entrypoint — nothing here declares a startup structure Codemble recognises, and it will not guess one. The other tab still maps how your modules import each other.`})]});let a=new Map(e.nodes.map(e=>[e.order,e]));return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(gK,{contentWidth:e.width+32,contentHeight:e.height+32,label:`the workflow tree`,children:(0,$.jsxs)(`svg`,{className:`workflow-tree`,width:`100%`,height:`100%`,preserveAspectRatio:`xMinYMin meet`,viewBox:`-16 -16 ${e.width+32} ${e.height+32}`,role:`group`,"aria-label":`Call tree from ${e.root}, ${e.nodes.length} steps deep to ${e.depth_count} levels`,children:[(0,$.jsx)(`g`,{className:`workflow-tree__edges`,children:e.nodes.map(e=>{if(e.parent===null)return null;let t=[...a.values()].filter(t=>t.id===e.parent&&t.order(0,$.jsxs)(`g`,{className:`workflow-tree__row`,"data-understood":e.understood,"data-cut":e.cut??void 0,"data-partial":e.partial,"data-relation":e.relation,"data-selected":e.region===n,transform:`translate(${e.x} ${e.y})`,role:`button`,tabIndex:0,"aria-label":`${e.label} at ${e.file}:${e.lineno}${e.certain?``:`, possible call`}${e.cut===`cycle`?`, repeats an earlier step`:``}${e.cut===`repeat`?`, already shown above`:``}${e.partial?`, unchartable, syntax error`:``}`,onClick:()=>i(e.id),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),i(e.id))},children:[(0,$.jsx)(`circle`,{cx:`8`,cy:`16`,r:`4`}),(0,$.jsx)(`text`,{x:`20`,y:`20`,children:e.label}),(0,$.jsxs)(`text`,{className:`row-meta`,x:`20`,y:`20`,dx:`${e.label.length*.62}em`,children:[e.relation===`defines`?t===`easy`?` — lives here`:` — defined in this module`:e.certain?``:` — possible call`,e.cut===`cycle`?` — loops back`:``,e.cut===`repeat`?` — shown above`:``,e.partial?t===`easy`?` — could not be read`:` — unchartable`:``]})]},e.order))]})}),e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`structure is`:`structures are`,` never reached from Home by a parser-proven call. They are listed as unreached rather than attached to the tree by guesswork.`]}):null]})}var kK=[{mode:`easy`,label:`New to coding?`},{mode:`expert`,label:`I build software`}],AK=[{mode:`easy`,label:`Easy`},{mode:`expert`,label:`Expert`}];function jK({mode:e,modeChosen:t,onChoose:n}){let r=(0,_.useRef)(null),i=(0,_.useRef)(null),a=(0,_.useRef)(t);(0,_.useLayoutEffect)(()=>{let e=r.current;e&&t===!1&&!e.open&&e.showModal()},[t]),(0,_.useEffect)(()=>{t===!0&&a.current===!1&&i.current?.focus(),a.current=t},[t]);function o(e){r.current?.close(),n(e)}return t===null?null:t?(0,$.jsxs)(`fieldset`,{className:`mode-toggle`,children:[(0,$.jsx)(`legend`,{className:`mode-toggle__label`,children:`Audience`}),(0,$.jsx)(`div`,{className:`mode-toggle__options`,children:AK.map(t=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:`radio`,name:`audience-mode`,value:t.mode,checked:e===t.mode,ref:e===t.mode?i:void 0,onChange:()=>o(t.mode)}),(0,$.jsx)(`span`,{children:t.label})]},t.mode))})]}):(0,$.jsxs)(`dialog`,{ref:r,className:`mode-gate`,"aria-labelledby":`mode-gate-heading`,"aria-describedby":`mode-gate-detail`,onCancel:e=>e.preventDefault(),children:[(0,$.jsx)(`h1`,{id:`mode-gate-heading`,children:`New to coding, or do you build software already?`}),(0,$.jsx)(`p`,{id:`mode-gate-detail`,children:`This changes how much Codemble explains and how much it assumes you already know.`}),(0,$.jsx)(`div`,{className:`mode-gate__options`,children:kK.map(e=>(0,$.jsx)(`button`,{type:`button`,onClick:()=>o(e.mode),children:e.label},e.mode))})]})}function MK({node:e,study:t,error:n,mode:r,explanation:i,explanationLoading:a,explanationError:o,llmStatus:s,onSelectNode:c,onRetryNarration:l}){return(0,$.jsxs)(`aside`,{className:`study-preview`,"aria-label":`Selected source structure`,"aria-busy":!t&&!n,children:[(0,$.jsxs)(`header`,{className:`study-preview__header`,children:[(0,$.jsxs)(`p`,{className:`study-preview__path`,children:[e.file,`:`,e.lineno]}),(0,$.jsx)(`h1`,{children:e.name}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Kind`}),(0,$.jsx)(`dd`,{children:e.kind})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Span`}),(0,$.jsxs)(`dd`,{children:[e.loc,` lines`]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r===`easy`?`Used by`:`Callers`}),(0,$.jsx)(`dd`,{children:e.centrality})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Resolution`}),(0,$.jsx)(`dd`,{children:e.partial?`Partial parse`:`Parser-proven`})]})]})]}),n?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`Study data did not load.`}),(0,$.jsxs)(`p`,{children:[n,` The parser map is still available.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>c(e.id),children:`Try again`})]}):null,!t&&!n?(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:`Reading parser evidence…`}):null,t?(0,$.jsxs)(`div`,{className:`study-content`,children:[(0,$.jsx)(NK,{structural:t.structural,mode:r}),(0,$.jsx)(HK,{explanation:i,loading:a,error:o,llmStatus:s,mode:r,node:e,onSelectNode:c,onRetry:l}),(0,$.jsx)(FK,{neighbors:t.neighbors,node:e,mode:r,onSelectNode:c}),(0,$.jsx)(VK,{source:t.source}),(0,$.jsx)(BK,{lens:t.lens,language:e.language,mode:r})]}):null]})}function NK({structural:e,mode:t}){return e?(0,$.jsxs)(`section`,{className:`structural-summary`,"aria-labelledby":`structural-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`structural-heading`,children:t===`easy`?`What this is`:`Structural summary`}),(0,$.jsx)(`span`,{children:`No model needed`})]}),(0,$.jsx)(`p`,{children:e[t]??e.easy})]}):null}var PK=8;function FK({neighbors:e,node:t,mode:n,onSelectNode:r}){let i=e??[],a=i.filter(e=>e.direction===`inbound`),o=i.filter(e=>e.direction===`outbound`);return(0,$.jsxs)(`section`,{className:`connections`,"aria-labelledby":`connections-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`connections-heading`,children:n===`easy`?`What this connects to`:`Parser connections`}),(0,$.jsxs)(`span`,{children:[i.length,` parser `,i.length===1?`relationship`:`relationships`]})]}),i.length===0?(0,$.jsx)(`p`,{className:`study-loading`,children:n===`easy`?`Nothing in your code reaches this yet, and it does not reach anything else.`:`The parser observed no relationship into or out of this structure.`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(zK,{inbound:a,outbound:o,node:t}),(0,$.jsx)(IK,{title:n===`easy`?`Uses this`:`Inbound`,items:a,mode:n,onSelectNode:r}),(0,$.jsx)(IK,{title:n===`easy`?`This uses`:`Outbound`,items:o,mode:n,onSelectNode:r})]})]})}function IK({title:e,items:t,mode:n,onSelectNode:r}){return t.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:e}),(0,$.jsx)(`ul`,{className:`connection-list`,children:t.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,onClick:()=>r(e.node_id),children:[(0,$.jsx)(`span`,{className:`connection-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`connection-meta`,children:[LK(e,n),` · `,RK(e,n)]}),(0,$.jsx)(`span`,{className:`source-citation`,children:e.citation})]})},`${e.direction}-${e.node_id}`))})]}):null}function LK(e,t){return e.relationship===`import`?e.direction===`inbound`?t===`easy`?`brings this in`:`import · inbound`:t===`easy`?`this brings it in`:`import · outbound`:e.direction===`inbound`?t===`easy`?`calls this`:`call · inbound`:t===`easy`?`this calls it`:`call · outbound`}function RK(e,t){return e.certain?`certain`:e.relationship===`import`?t===`easy`?`possible link, not certain`:`possible import`:t===`easy`?`possible link, not certain`:`possible call`}function zK({inbound:e,outbound:t,node:n}){let r=e.slice(0,PK),i=t.slice(0,PK),a=Math.max(r.length,i.length,1)*22+16,o=a/2,s=(e,t)=>(e+1)*a/(t+1);return(0,$.jsxs)(`svg`,{className:`mini-constellation`,viewBox:`0 0 280 ${a}`,role:`img`,"aria-label":`${e.length} inbound and ${t.length} outbound parser relationships for ${n.name}`,children:[r.map((e,t)=>(0,$.jsx)(`line`,{x1:`26`,y1:s(t,r.length),x2:`132`,y2:o,strokeDasharray:e.certain?void 0:`3 3`},`in-line-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`line`,{x1:`148`,y1:o,x2:`254`,y2:s(t,i.length),strokeDasharray:e.certain?void 0:`3 3`},`out-line-${e.node_id}`)),r.map((e,t)=>(0,$.jsx)(`circle`,{cx:`22`,cy:s(t,r.length),r:`4`},`in-dot-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`circle`,{cx:`258`,cy:s(t,i.length),r:`4`},`out-dot-${e.node_id}`)),(0,$.jsx)(`circle`,{className:`mini-constellation__self`,cx:`140`,cy:o,r:`6`})]})}function BK({lens:e,language:t,mode:n}){return e?.length?(0,$.jsxs)(`section`,{className:`lens-study`,"aria-labelledby":`lens-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsxs)(`h2`,{id:`lens-heading`,children:[kG(t),` lens`]}),(0,$.jsxs)(`span`,{children:[e.length,` detected`]})]}),(0,$.jsx)(`div`,{className:`lens-notes`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`lens-note`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h3`,{children:e.title}),(0,$.jsx)(WK,{citation:e.citation,fallbackLine:e.line})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:e.note_voices[n]}),(0,$.jsx)(`code`,{children:e.snippet})]})]},`${e.concept}-${e.line}-${e.snippet}`))})]}):null}function VK({source:e}){return(0,$.jsxs)(`section`,{className:`source-study`,"aria-labelledby":`source-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`source-heading`,children:`Real source`}),(0,$.jsxs)(`span`,{children:[e.file,`:`,e.start_line,`–`,e.end_line]})]}),(0,$.jsx)(`ol`,{className:`source-code`,start:e.start_line,"aria-label":`Source excerpt from ${e.file}`,children:e.lines.map(e=>(0,$.jsx)(`li`,{id:`source-L${e.number}`,"data-line":e.number,children:(0,$.jsx)(`code`,{children:e.text||` `})},e.number))})]})}function HK({explanation:e,loading:t,error:n,llmStatus:r,mode:i,node:a,onSelectNode:o,onRetry:s}){return t?(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:i===`easy`?`Asking your model to explain this in plain language…`:`Requesting a grounded narration for this structure…`}):n?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`The explanation request failed.`}),(0,$.jsx)(`p`,{children:n}),(0,$.jsx)(`p`,{children:`Every fact above and below this block came from the parser and is unaffected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]}):e?e.status===`no_key`?(0,$.jsx)(UK,{message:e.message,llmStatus:r,mode:i}):e.status===`error`?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`The explanation was withheld.`}),(0,$.jsx)(`p`,{children:e.message}),(0,$.jsx)(`p`,{children:`Codemble will not display provider output that falls outside parser evidence.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]}):e.status===`partial`?(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`Narration stays off for partial source.`}),(0,$.jsx)(`p`,{children:e.message})]}):(0,$.jsxs)(`section`,{className:`grounded-explanation`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,role:`status`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:i===`easy`?`In plain language`:`Grounded explanation`}),(0,$.jsx)(`span`,{children:e.cached?`Local cache`:e.provider})]}),(0,$.jsxs)(`p`,{children:[e.summary.text,` `,(0,$.jsx)(WK,{citation:e.summary.citation,fallbackLine:a.lineno})]}),(0,$.jsx)(`h3`,{children:i===`easy`?`Line by line`:`Walkthrough`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.walkthrough.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`p`,{children:e.text}),(0,$.jsx)(WK,{citation:e.citation,fallbackLine:e.line})]},`${e.citation}-${e.text}`))}),e.relationships.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:i===`easy`?`How it fits in`:`Parser relationships`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.relationships.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`strong`,{children:e.certain?e.node_id:`Possible: ${e.node_id}`}),(0,$.jsx)(`p`,{children:e.text}),(0,$.jsxs)(`button`,{className:`source-citation source-citation--button`,type:`button`,onClick:()=>o(e.node_id),children:[`Study `,e.citation]})]},`${e.node_id}-${e.text}`))})]}):null]}):null}function UK({message:e,llmStatus:t,mode:n}){let r=t?.ollama??null;return(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:n===`easy`?`The plain-language write-up needs a model.`:`No narration provider is configured.`}),(0,$.jsx)(`p`,{children:e}),r?(0,$.jsx)(`p`,{children:r.running?`Ollama is already running on this machine. Set CODEMBLE_PROVIDER=ollama and CODEMBLE_OLLAMA_MODEL=${r.recommended}, then restart Codemble to narrate without sending code anywhere.`:`Want to stay fully local? Install Ollama, run "ollama pull ${r.recommended}" (or ${r.fallback} on a smaller machine), set CODEMBLE_PROVIDER=ollama, then restart Codemble.`}):null,(0,$.jsx)(`p`,{children:`Everything else on this panel is parser evidence and works without any model at all.`})]})}function WK({citation:e,fallbackLine:t}){return(0,$.jsx)(`a`,{className:`source-citation`,href:`#source-L${Number(e.split(`:`).at(-1))||t}`,children:e})}var GK=Object.freeze([]),KK=new Set;function qK(){let e=new WeakMap,t=new WeakMap,n=new WeakMap,r=new WeakMap,i=new WeakMap,a=new WeakMap,o=null,s=null,c=null,l=null;function u(e){let t=e.graph,n=t?d(t,e.languageFocus):null,r=n?p(n):null,i=e.level,a=r?.regionById.get(e.region?.id)??null,o=e.selectedNode;n&&(a?o&&(o=r.nodeById.get(o.id)??null,!o&&i===wG.STUDY&&(i=wG.SYSTEM)):(a=WG(n),o=null,i=wG.GALAXY));let s=e.studiedNodeIds;return{...e,focusedGraph:n,focusedMapData:f(e.mapData,e.languageFocus),entrypointOpen:!!t&&!e.entrypointDismissed,level:i,region:a,selectedNode:o,languageOptions:t?m(t):GK,projectName:t?g(t):`Loading local project`,chart:n?_(n,s):GK,focusedStudiedCount:n?v(n,s):0,hint:n?y(n,e.mode):null,revealedRegionIds:n?b(n,e.showAll,a?.id??null):KK,moduleIndex:n?h(n):GK}}function d(t,n){let r=e.get(t);r||(r=new Map,e.set(t,r));let i=n||`all`;return r.has(i)||r.set(i,TG(t,n)),r.get(i)}function f(e,n){if(!e)return e;let r=t.get(e);r||(r=new Map,t.set(e,r));let i=n||`all`;return r.has(i)||r.set(i,EG(e,n)),r.get(i)}function p(e){return n.has(e)||n.set(e,{nodeById:new Map(e.nodes.map(e=>[e.id,e])),regionById:new Map(e.regions.map(e=>[e.id,e]))}),n.get(e)}function m(e){return r.has(e)||r.set(e,DG(e)),r.get(e)}function h(e){return i.has(e)||i.set(e,LG(e)),i.get(e)}function g(e){return a.has(e)||a.set(e,e.project_root.split(`/`).filter(Boolean).at(-1)??e.project_root),a.get(e)}function _(e,t){return(!o||o.graph!==e||o.studiedNodeIds!==t)&&(o={graph:e,studiedNodeIds:t,value:OG(e,t)}),o.value}function v(e,t){return(!s||s.graph!==e||s.studiedNodeIds!==t)&&(s={graph:e,studiedNodeIds:t,value:e.nodes.filter(e=>t.has(e.id)).length}),s.value}function y(e,t){return(!c||c.graph!==e||c.mode!==t)&&(c={graph:e,mode:t,value:JK(e,t)}),c.value}function b(e,t,n){return(!l||l.graph!==e||l.showAll!==t||l.selectionId!==n)&&(l={graph:e,showAll:t,selectionId:n,value:PG(e,{showAll:t,selectionId:n})}),l.value}return Object.freeze({derive:u})}function JK(e,t){if(t!==`easy`)return null;let n=e.regions.filter(e=>!e.understood);if(!n.length)return null;let r=n.map(e=>({regionId:e.id,hops:typeof e.hops_from_home==`number`?e.hops_from_home:1/0})).sort((e,t)=>e.hops-t.hops||e.regionId.localeCompare(t.regionId))[0];return{...r,reason:r.hops===0?`Home is not lit yet.`:Number.isFinite(r.hops)?`${r.hops} ${r.hops===1?`route`:`routes`} from Home.`:`No import route reaches it from Home.`}}var YK=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}}),XK=300,ZK=400,QK=4e3,$K=8,eq=Object.freeze([Object.freeze({id:`discovering`,copy:`Finding your source files`}),Object.freeze({id:`parsing`,copy:`Reading each file`}),Object.freeze({id:`resolving`,copy:`Connecting imports and calls`}),Object.freeze({id:`checks`,copy:`Building graph-only checks`}),Object.freeze({id:`layout`,copy:`Placing your galaxy`})]);function tq({adapter:e,clock:t=YK,onReady:n=async()=>{}}={}){if(!e)throw TypeError(`Project mapping requires a learner adapter.`);let r=new Set,i=nq({phase:`idle`,error:``,picker:null,progress:null,failure:null}),a=0,o=null,s=null,c=null,l=null;function u(){return i}function d(e){return r.add(e),()=>r.delete(e)}function f(e){i=nq({...i,...e});for(let e of r)e()}async function p(){a+=1;let t=a;b(),rq(o),o=new AbortController;let n=o;f({phase:`idle`,error:``,picker:null,progress:null,failure:null});try{let[r,o]=await Promise.all([e.loadRecents({signal:n.signal}),e.browsePicker(null,{signal:n.signal})]);if(t!==a||n.signal.aborted)return i;f({phase:`picking`,picker:{...o,recents:r.recents,error:``,scale:null,busy:!1}})}catch(e){!iq(e)&&t===a&&f({phase:`error`,error:oq(e)})}return i}async function m(t){if(i.phase!==`picking`||i.picker?.busy)return;rq(o),o=new AbortController;let n=o,r=a;f({failure:null});try{let s=await e.browsePicker(t,{signal:n.signal});o===n&&r===a&&!n.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...s,error:``}})}catch(e){o===n&&r===a&&!iq(e)&&i.phase===`picking`&&f({picker:{...i.picker,error:oq(e)}})}}async function h(t){if(i.phase!==`picking`||i.picker?.busy)return;a+=1;let r=a;rq(o),b(),o=new AbortController;let s=o;f({failure:null,picker:{...i.picker,busy:!0,error:``,scale:null}});try{let o=await e.selectProject(t,{signal:s.signal});if(r!==a||s.signal.aborted||i.phase!==`picking`)return o;if(o.state===`parsing`)return f({progress:{state:`parsing`,stage:`discovering`,detail:null,files_done:0,files_total:0,error:null,pollError:``,attempts:0,pollOutage:!1,path:t}}),_(0,r),o;if(o.state===`ready`)return y(),await n(),o;if(o.state===`scale`){let t=await e.browsePicker(o.root,{signal:s.signal});return r===a&&!s.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...t,busy:!1,scale:o}}),o}let c=o.detail??``;return f({picker:{...i.picker,busy:!1,error:c},failure:c?{path:t,detail:c}:null}),o}catch(e){if(r===a&&!iq(e)&&i.phase===`picking`){let n=oq(e);f({picker:{...i.picker,busy:!1,error:n},failure:{path:t,detail:n}})}return}}async function g(){rq(c),c=new AbortController;let t=c;try{await e.resetProject({signal:t.signal})}catch(e){if(iq(e))return!1;if(aq(e))throw e}return t.signal.aborted?!1:(a+=1,rq(o),o=null,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null}),!0)}function _(e,n){l!==null&&t.clearTimeout(l),l=t.setTimeout(async()=>{l=null,await v(n)},e)}async function v(t){if(!i.progress||t!==a)return;rq(s),s=new AbortController;let r=s,o=i.progress,c;try{c=await e.fetchParseProgress({signal:r.signal})}catch(e){if(s!==r||t!==a||iq(e)||!i.progress)return;let n=o.attempts+1;f({progress:{...o,pollError:oq(e),attempts:n,pollOutage:n>=$K}}),_(Math.min(QK,ZK*2**(n-1)),t);return}if(!(s!==r||t!==a||!i.progress)){if(c.state===`ready`){y(),await n();return}if(c.state===`error`||c.state===`idle`){b();let e=c.error??``;f({progress:null,picker:{...i.picker,busy:!1,error:e},failure:e?{path:o.path,detail:e}:null});return}f({progress:{...o,...c,pollError:``,attempts:0,pollOutage:!1}}),_(XK,t)}}function y(){a+=1,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null})}function b(){rq(s),s=null,l!==null&&(t.clearTimeout(l),l=null)}function x(){a+=1;for(let e of[o,s,c])rq(e);o=null,c=null,b(),r.clear()}return Object.freeze({browse:m,dispose:x,getSnapshot:u,reset:g,select:h,start:p,subscribe:d})}function nq(e){return Object.freeze(e)}function rq(e){e&&!e.signal.aborted&&e.abort()}function iq(e){return e?.name===`AbortError`}function aq(e){return Number.isInteger(e?.status)}function oq(e){return e instanceof Error?e.message:String(e)}var sq=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}});function cq({adapter:e=lq(),clock:t=sq}={}){let n=new Set,r=qK(),i=r.derive({status:`idle`,error:``,graph:null,level:wG.GALAXY,region:null,selectedNode:null,studyData:null,studyError:``,explanation:null,explanationLoading:!1,explanationError:``,showChart:!1,studiedNodeIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,picker:null,parseProgress:null,projectFailure:null,layer:`galaxy`,layerChosen:!1,mapTab:`architecture`,mapData:null,mapError:``,coachmarksSeen:fq(),llmStatus:null,hoverNodeId:null,showAll:hq(),finderOpen:!1,sidebarOpen:!1,legendOpen:!1,mode:`easy`,modeChosen:null}),a=0,o=0,s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,h=null;function g(){return i}function _(e){return n.add(e),()=>n.delete(e)}function v(e,{preserveChecks:t=!1}={}){let a=i,o=r.derive({...a,...e});if(o.level!==a.level||o.region?.id!==a.region?.id){let e={hoverNodeId:null};t||(_q(u),_q(d),u=null,d=null,e.showChecks=!1,e.checkData=null,e.checkError=``),o=r.derive({...o,...e})}i=Object.freeze(o);for(let e of n)e()}let y=tq({adapter:e,clock:t,async onReady(){a+=1;let e=a;return _q(s),s=new AbortController,S(s,e)}}),b=y.subscribe(()=>{let e=y.getSnapshot(),t={picker:e.picker,parseProgress:e.progress,projectFailure:e.failure};e.phase===`picking`&&(t.status=`picking`),e.phase===`error`&&(t.status=`error`,t.error=e.error),v(t)});async function x(){a+=1;let t=a;_q(s),s=new AbortController;let n=s;v({status:`loading`,error:``});let r;try{r=await e.loadPickerState({signal:n.signal})}catch(e){return!vq(e)&&t===a&&v({status:`error`,error:xq(e)}),i}return t!==a||n.signal.aborted?i:r.state===`unpicked`?(await y.start(),i):S(n,t)}async function S(t,n){v({status:`loading`,error:``,picker:null});try{let r=await e.loadGraph({signal:t.signal});if(n!==a||t.signal.aborted)return i;v({status:`ready`,graph:r,region:WG(r),error:``,entrypointDismissed:!!r.selected_entrypoint})}catch(e){!vq(e)&&n===a&&v({status:`error`,error:xq(e)})}return await C(t,n),i}async function C(t,n){let r=o,[s,c]=await Promise.allSettled([(async()=>e.loadMode({signal:t.signal}))(),(async()=>e.fetchLlmStatus({signal:t.signal}))()]);if(!(n!==a||t.signal.aborted)){if(r===o){let e=s.status===`fulfilled`?s.value:null;e?.mode===`easy`||e?.mode===`expert`?te(e.mode,e.chosen===!0):i.modeChosen===null&&v({modeChosen:!0})}c.status===`fulfilled`&&v({llmStatus:c.value})}}async function w(){let t=a;if(await e.clearProgress({}),t!==a)return i;a+=1;let n=a;return _q(s),s=new AbortController,S(s,n)}async function T(){return await y.reset()?(ie(),_q(f),f=null,_q(p),p=null,_q(m),m=null,v({graph:null,parseProgress:null,projectFailure:null,region:null,selectedNode:null,level:wG.GALAXY,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1,showChart:!1,studiedNodeIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,llmStatus:null,picker:null,mapData:null,mapError:``}),x()):i}async function E(e){switch(e.type){case`ADVANCE`:return O(e.node);case`ADVANCE_REGION`:D(e.regionId);return;case`RETREAT`:k();return;case`SELECT_STUDY_NODE`:return A(e.nodeId);case`SET_LANGUAGE_FOCUS`:ee(e.language);return;case`SET_MODE`:return ne(e.mode);case`HOVER_NODE`:i.hoverNodeId!==(e.nodeId??null)&&v({hoverNodeId:e.nodeId??null});return;case`SHOW_CHART`:v({showChart:!0});return;case`HIDE_CHART`:v({showChart:!1});return;case`OPEN_CHECKS`:return M();case`CLOSE_CHECKS`:oe();return;case`SUBMIT_CHECK`:return se(e.checkId,e.selectedIds);case`CONSUME_DAWN`:pe(e.regionId);return;case`SELECT_ENTRYPOINT`:return ce(e.nodeId);case`DISMISS_ENTRYPOINT`:v({entrypointDismissed:!0});return;case`CHANGE_HOME`:ie(),v({entrypointDismissed:!1,entrypointError:``,level:wG.GALAXY,selectedNode:null,showChart:!1,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1});return;case`BROWSE_PICKER`:return y.browse(e.path);case`SELECT_PROJECT`:return y.select(e.path);case`RESET_PROJECT`:return T();case`CLEAR_PROGRESS`:return w();case`SET_LAYER`:return le(e.layer);case`SET_MAP_TAB`:v({mapTab:e.tab});return;case`DISMISS_COACHMARKS`:pq(),v({coachmarksSeen:!0});return;case`SET_LEVEL_GALAXY`:ie(),v({level:wG.GALAXY,selectedNode:null});return;case`TOGGLE_SHOW_ALL`:gq(!i.showAll),v({showAll:!i.showAll});return;case`SET_FINDER_OPEN`:v({finderOpen:e.open});return;case`TOGGLE_SIDEBAR`:v({sidebarOpen:!i.sidebarOpen});return;case`TOGGLE_LEGEND`:v({legendOpen:!i.legendOpen});return;case`GO_TO_REGION`:return v({finderOpen:!1}),D(e.regionId);default:throw Error(`Unknown learner-session event: ${e.type}`)}}function D(e){let t=i.graph?.regions.find(t=>t.id===e);t&&(ie(),v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:t,selectedNode:null,level:wG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}async function O(e){if(!(!i.focusedGraph||!e)){if(i.level===wG.GALAXY){let t=i.focusedGraph.regions.find(t=>t.id===e.id)??e;ie(),v({region:t,selectedNode:null,level:wG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``});return}if(i.level===wG.SYSTEM){let t=i.focusedGraph.nodes.find(t=>t.id===e.id)??e;return v({selectedNode:t,level:wG.STUDY}),re(t.id)}}}function k(){i.level===wG.STUDY?(ie(),v({selectedNode:null,level:wG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1})):i.level===wG.SYSTEM&&v({level:wG.GALAXY})}async function A(e){let t=i.graph?.nodes.find(t=>t.id===e);if(!t)return;let n=i.graph.regions.find(e=>e.id===t.region);return v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:n??i.region,selectedNode:t,level:wG.STUDY}),re(t.id)}function ee(e){let t=i.selectedNode?.id;v({languageFocus:e}),t&&i.selectedNode?.id!==t&&(ie(),v({studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}function te(e,t){let n=i.layerChosen?i.layer:e===`easy`?`map`:`galaxy`;v({mode:e,layer:n,modeChosen:t}),n===`map`&&ue()}async function ne(t){if(t!==`easy`&&t!==`expert`)return;let n=i.mode,r=i.modeChosen;if(t===n&&i.modeChosen)return;o+=1,_q(m),m=new AbortController;let s=m,c=a;te(t,!0);try{await e.saveMode(t,{signal:s.signal})}catch(e){m===s&&c===a&&!vq(e)&&te(n,r);return}if(!(c!==a||s.signal.aborted)&&i.level===wG.STUDY&&i.selectedNode)return j(i.selectedNode.id)}async function re(t){ie(),c=new AbortController;let n=c;v({studyData:null,studyError:``}),j(t);try{let r=await e.loadStudy(t,{signal:n.signal});if(n.signal.aborted||i.level!==wG.STUDY||i.selectedNode?.id!==t)return;v({studyData:r,studiedNodeIds:new Set(i.studiedNodeIds).add(r.node.id)})}catch(e){c===n&&!n.signal.aborted&&!vq(e)&&i.selectedNode?.id===t&&v({studyError:bq(e)})}}function ie(){_q(c),c=null,_q(l),l=null}async function j(t){_q(l),l=new AbortController;let n=l;v({explanation:null,explanationError:``,explanationLoading:!0});try{let r=await e.loadExplanation(t,i.mode,{signal:n.signal});if(n.signal.aborted||i.level!==wG.STUDY||i.selectedNode?.id!==t)return;v({explanation:r,explanationLoading:!1})}catch(e){l===n&&!n.signal.aborted&&!vq(e)&&i.selectedNode?.id===t&&v({explanationError:bq(e),explanationLoading:!1})}}async function M(){if(!i.region)return;let e=i.region.id;return v({showChecks:!0,checkData:null,checkError:``}),ae(e)}async function ae(t){_q(u),u=new AbortController;let n=u;try{let r=await e.loadChecks(t,{signal:n.signal});return!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkData:r,checkError:``},{preserveChecks:!0}),r}catch(e){u===n&&!vq(e)&&!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkError:bq(e)},{preserveChecks:!0});return}}function oe(){_q(u),u=null,v({showChecks:!1,checkData:null,checkError:``})}async function se(t,n){if(!i.region)return;let r=i.region.id;_q(d),d=new AbortController;let a=d,o=await e.submitCheck(r,t,n,{signal:a.signal});if(a.signal.aborted||i.region?.id!==r)return o;if(o.correct&&await ae(r),o.region_understood){let t=await e.loadGraph({signal:a.signal});!a.signal.aborted&&i.region?.id===r&&(_q(p),p=null,v({graph:t,region:t.regions.find(e=>e.id===r),mapData:null,mapError:``},{preserveChecks:!0}),fe(r),i.layer===`map`&&await ue())}return o}async function ce(t){let n=a;_q(f),f=new AbortController;let r=f;v({entrypointError:``});try{let o=await e.selectEntrypoint(t,{signal:r.signal});return n!==a||r.signal.aborted?i:(_q(p),p=null,v({graph:o,region:WG(o),entrypointError:``,entrypointDismissed:!0,mapData:null,mapError:``}),i.layer===`map`&&await ue(),o)}catch(e){f===r&&n===a&&!r.signal.aborted&&!vq(e)&&v({entrypointError:bq(e)});return}}async function le(e){if(v({layer:e,layerChosen:!0}),e===`map`)return ue()}function ue(){if(!i.mapData)return p&&!p.signal.aborted&&!i.mapError?void 0:de()}async function de(){let t=a;_q(p),p=new AbortController;let n=p;v({mapError:``});try{let r=await e.fetchMap({signal:n.signal});return t===a&&!n.signal.aborted&&v({mapData:r,mapError:``}),r}catch(e){p===n&&t===a&&!n.signal.aborted&&!vq(e)&&v({mapError:bq(e),mapData:null});return}}function fe(e){h!==null&&t.clearTimeout(h),v({litRegionId:e,pendingDawnRegionId:e}),h=t.setTimeout(()=>{h=null,i.litRegionId===e&&v({litRegionId:null})},520)}function pe(e){i.pendingDawnRegionId===e&&v({pendingDawnRegionId:null})}function me(){a+=1;for(let e of[s,c,l,u,d,f,p,m])_q(e);s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,b(),y.dispose(),h!==null&&(t.clearTimeout(h),h=null)}return Object.freeze({dispatch:E,dispose:me,getSnapshot:g,start:x,subscribe:_})}function lq(e=globalThis.fetch){if(typeof e!=`function`)throw TypeError(`Learner-session HTTP adapter requires fetch.`);async function t(t,n,r={}){let i=await e(t,r);if(!i.ok){let e=(await i.json().catch(()=>null))?.detail,t=Error(typeof e==`string`&&e?e:`${n} returned ${i.status}.`);throw t.status=i.status,t}return i.json()}return Object.freeze({loadGraph(e={}){return t(`/api/graph`,`Graph request`,e)},fetchMap(e={}){return t(`/api/map`,`Map request`,e)},loadStudy(e,n={}){return t(`/api/node/${encodeURIComponent(e)}/study`,`Study request`,n)},loadExplanation(e,n,r={}){return t(`/api/node/${encodeURIComponent(e)}/explanation?mode=${encodeURIComponent(n)}`,`Explanation request`,r)},loadChecks(e,n={}){return t(`/api/regions/${encodeURIComponent(e)}/checks`,`Checks request`,n)},submitCheck(e,n,r,i={}){return t(`/api/regions/${encodeURIComponent(e)}/checks/${encodeURIComponent(n)}`,`Check submission`,{...i,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selected_ids:r})})},selectEntrypoint(e,n={}){return t(`/api/entrypoint`,`Home selection`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({node_id:e})})},loadMode(e={}){return t(`/api/mode`,`Mode request`,e)},saveMode(e,n={}){return t(`/api/mode`,`Mode update`,{...n,method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({mode:e})})},fetchLlmStatus(e={}){return t(`/api/llm/status`,`Model status`,e)},resetProject(e={}){return t(`/api/picker/reset`,`Project reset`,{...e,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirmed:!0})})},loadPickerState(e={}){return t(`/api/picker/state`,`Picker state`,e)},browsePicker(e,n={}){return t(`/api/picker/browse${e?`?path=${encodeURIComponent(e)}`:``}`,`Folder listing`,n)},loadRecents(e={}){return t(`/api/picker/recents`,`Recent projects`,e)},fetchParseProgress(e={}){return t(`/api/picker/progress`,`Parse progress`,e)},clearProgress(e={}){return t(`/api/progress`,`Progress reset`,{...e,method:`DELETE`})},async selectProject(t,n={}){let r=await e(`/api/picker/select`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t})}),i=await r.json().catch(()=>null);if(r.ok)return{state:r.status===202?`parsing`:`ready`};let a=i?.detail;return a&&typeof a==`object`&&a.reason===`scale`?{state:`scale`,...a}:{state:`error`,detail:typeof a==`string`?a:`Project selection returned ${r.status}.`}}})}var uq=`codemble.coachmarks.seen`;function dq(){if(typeof document>`u`)return null;try{return globalThis.localStorage??null}catch{return null}}function fq(){try{return dq()?.getItem(uq)===`1`}catch{return!1}}function pq(){try{dq()?.setItem(uq,`1`)}catch{}}var mq=`codemble.galaxy.showAll`;function hq(){try{return dq()?.getItem(mq)===`1`}catch{return!1}}function gq(e){try{let t=dq();e?t?.setItem(mq,`1`):t?.removeItem(mq)}catch{}}function _q(e){e&&!e.signal.aborted&&e.abort()}function vq(e){return e instanceof Error&&e.name===`AbortError`}function yq(e){return Number.isInteger(e?.status)}function bq(e){return e instanceof Error?e.message:String(e)}function xq(e){return yq(e)?bq(e):`Codemble's local server is not responding, so nothing can be loaded from it. It may have stopped — start it again by running codemble in your terminal. (${bq(e)})`}function Sq(){let e=(0,_.useMemo)(()=>cq({adapter:lq()}),[]),t=(0,_.useSyncExternalStore)(e.subscribe,e.getSnapshot,e.getSnapshot);(0,_.useEffect)(()=>(e.start(),()=>e.dispose()),[e]),(0,_.useEffect)(()=>{function t(t){(t.metaKey||t.ctrlKey)&&t.key.toLowerCase()===`k`&&(t.preventDefault(),e.dispatch({type:`SET_FINDER_OPEN`,open:!0}))}return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]);let{chart:n,checkData:r,checkError:i,coachmarksSeen:a,entrypointError:o,entrypointOpen:s,error:c,explanation:l,explanationError:u,explanationLoading:d,finderOpen:f,focusedGraph:p,focusedMapData:m,focusedStudiedCount:h,graph:g,hint:v,hoverNodeId:y,languageFocus:b,languageOptions:x,layer:S,legendOpen:C,level:w,litRegionId:T,llmStatus:E,mapError:D,mapTab:O,mode:k,modeChosen:A,moduleIndex:ee,parseProgress:te,pendingDawnRegionId:ne,picker:re,projectName:ie,projectFailure:j,region:M,revealedRegionIds:ae,selectedNode:oe,showAll:se,showChart:ce,showChecks:le,sidebarOpen:ue,status:de,studyData:fe,studyError:pe}=t;if(c)return(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The graph did not load.`}),(0,$.jsx)(`p`,{children:c}),(0,$.jsx)(`p`,{children:`Your progress is stored on this machine and is not affected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>e.start(),children:`Try again`})]});if(te)return(0,$.jsx)(Tq,{progress:te,onCancel:()=>e.dispatch({type:`RESET_PROJECT`})});if(de===`picking`&&re)return(0,$.jsx)(Eq,{picker:re,failure:j,onBrowse:t=>e.dispatch({type:`BROWSE_PICKER`,path:t}),onSelect:t=>e.dispatch({type:`SELECT_PROJECT`,path:t})});if(!g||!p||!M)return(0,$.jsx)(`main`,{className:`load-state`,"aria-busy":`true`,children:(0,$.jsx)(`p`,{children:`Mapping parser evidence…`})});let me=w===wG.SYSTEM?(0,$.jsxs)(`section`,{className:`orientation-copy orientation-copy--system${S===`map`?` orientation-copy--inline`:``}`,children:[(0,$.jsx)(`p`,{children:p.nodes.some(e=>e.region===M.id&&e.partial)?`${M.node_count} source ${M.node_count===1?`file remains`:`files remain`} visible · ${M.loc} lines. The module is unchartable beyond raw source because it has a syntax error.`:S===`map`?`The ${M.node_count} parser-proven ${M.node_count===1?`structure`:`structures`} inside this module ${M.node_count===1?`is`:`are`} drawn as planets in the Galaxy layer. This map shows how modules connect, not what is inside them.`:`${M.node_count} parser-proven structures · ${M.loc} lines in this system.`}),(0,$.jsx)(`button`,{className:`check-launch`,type:`button`,onClick:()=>e.dispatch({type:`OPEN_CHECKS`}),children:p.nodes.some(e=>e.region===M.id&&e.partial)?`Check availability`:M.understood?`Review understanding`:`Prove understanding`})]}):null;return(0,$.jsxs)(`main`,{className:`app-shell`,"data-level":ce?`chart`:w.toLowerCase(),"data-mode":k,children:[(0,$.jsxs)(`header`,{className:`instrument-rail`,children:[(0,$.jsxs)(`div`,{className:`brand-lockup`,children:[(0,$.jsx)(`span`,{className:`brand-mark`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`strong`,{children:`Codemble`}),(0,$.jsx)(`span`,{children:ie})]})]}),(0,$.jsx)(`nav`,{className:`location`,"aria-label":`Breadcrumb`,"aria-live":`polite`,children:ce?(0,$.jsx)(`span`,{"aria-current":`page`,children:`Star chart`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`button`,{type:`button`,disabled:w===wG.GALAXY,"aria-current":w===wG.GALAXY?`page`:void 0,onClick:()=>e.dispatch({type:`SET_LEVEL_GALAXY`}),children:`Galaxy`}),w===wG.GALAXY?(0,$.jsxs)(`small`,{children:[` · Home `,g.selected_entrypoint?WG(g)?.id??`unresolved`:`unselected`]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`button`,{type:`button`,disabled:w===wG.SYSTEM,"aria-current":w===wG.SYSTEM?`page`:void 0,onClick:()=>e.dispatch({type:`RETREAT`}),children:M.id})]}),w===wG.STUDY&&oe?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`span`,{"aria-current":`page`,children:oe.name})]}):null,b===`all`?null:(0,$.jsxs)(`small`,{children:[` · `,AG(b),` focus`]})]})}),(0,$.jsxs)(`div`,{className:`rail-actions`,children:[(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,"aria-pressed":ue,onClick:()=>e.dispatch({type:`TOGGLE_SIDEBAR`}),children:`Modules`}),(0,$.jsxs)(`button`,{className:`rail-action`,type:`button`,onClick:()=>e.dispatch({type:`SET_FINDER_OPEN`,open:!0}),children:[`Find `,(0,$.jsx)(`kbd`,{children:`⌘K`})]}),ce?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>e.dispatch({type:`HIDE_CHART`}),children:`Return to galaxy`}):w===wG.GALAXY?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>e.dispatch({type:`SHOW_CHART`}),children:`Star chart`}):(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>e.dispatch({type:`RETREAT`}),children:w===wG.STUDY?`Return to system`:`Return to galaxy`}),g.entrypoint_candidates.length?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>e.dispatch({type:`CHANGE_HOME`}),children:`Change Home`}):null,(0,$.jsx)(Pq,{onConfirm:()=>e.dispatch({type:`RESET_PROJECT`})})]}),(0,$.jsxs)(`div`,{className:`rail-controls`,children:[S===`galaxy`?(0,$.jsx)(`button`,{className:`rail-action rail-action--toggle`,type:`button`,"aria-pressed":se,title:`Draw every module at once, including the ones no route from Home reaches`,onClick:()=>e.dispatch({type:`TOGGLE_SHOW_ALL`}),children:`Show all`}):null,(0,$.jsx)(Mq,{layer:S,mode:k,onChange:t=>e.dispatch({type:`SET_LAYER`,layer:t})}),(0,$.jsx)(Nq,{options:x,value:b,onChange:t=>e.dispatch({type:`SET_LANGUAGE_FOCUS`,language:t})}),(0,$.jsx)(jK,{mode:k,modeChosen:A,onChoose:t=>e.dispatch({type:`SET_MODE`,mode:t})})]})]}),ce?(0,$.jsx)(Lq,{chart:n,studiedCount:h,projectName:ie,onClearProgress:()=>e.dispatch({type:`CLEAR_PROGRESS`})}):(0,$.jsxs)(`section`,{className:`map-stage`,"aria-label":`Parser-proven project map`,children:[ue?(0,$.jsx)(jq,{index:ee,currentRegionId:w===wG.GALAXY?null:M?.id,onGo:t=>e.dispatch({type:`GO_TO_REGION`,regionId:t}),onClose:()=>e.dispatch({type:`TOGGLE_SIDEBAR`})}):null,S===`map`?(0,$.jsx)(EK,{data:m,mapTab:O,mode:k,selectedRegionId:w===wG.GALAXY?void 0:M?.id,hasEntrypointCandidates:g.entrypoint_candidates.length>0,error:D,onSelectTab:t=>e.dispatch({type:`SET_MAP_TAB`,tab:t}),onSelectRegion:t=>e.dispatch({type:`ADVANCE_REGION`,regionId:t}),onSelectNode:t=>e.dispatch({type:`SELECT_STUDY_NODE`,nodeId:t}),onRetry:()=>e.dispatch({type:`SET_LAYER`,layer:`map`}),children:me}):(0,$.jsx)(rK,{graph:p,level:w,region:M,selectedNode:oe,hoverNodeId:y,pendingDawnRegionId:ne,revealedRegionIds:ae,mode:k,onHoverNode:t=>e.dispatch({type:`HOVER_NODE`,nodeId:t}),onAdvance:t=>e.dispatch({type:`ADVANCE`,node:t}),onRetreat:()=>e.dispatch({type:`RETREAT`}),onDawnConsumed:t=>e.dispatch({type:`CONSUME_DAWN`,regionId:t})}),(0,$.jsx)(`button`,{className:`legend-toggle`,type:`button`,"aria-expanded":C,onClick:()=>e.dispatch({type:`TOGGLE_LEGEND`}),children:`Key`}),(0,$.jsxs)(`aside`,{className:`map-legend`,hidden:!C,"aria-label":S===`map`?`Map legend`:`Galaxy legend`,children:[S===`galaxy`?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-size`}),`Size · `,k===`easy`?`how much code`:`lines of code`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-brightness`}),`Brighter · `,k===`easy`?`used in more places`:`more distinct callers`]})]}):null,(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--dim`}),`Dim · `,k===`easy`?`not proven yet`:`not understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--lit`}),`Amber · `,k===`easy`?`you proved you understand it`:`understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--partial`}),k===`easy`?`Could not be read`:`Unchartable · syntax error`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-route`}),k===`easy`?`Certain connection`:`Parser edge · certain`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:S===`map`?`legend-route legend-route--possible legend-route--dashed`:`legend-route legend-route--possible`}),k===`easy`?`Possible connection`:`Possible relationship`]}),S===`galaxy`&&w===wG.GALAXY||S===`map`&&O===`architecture`?x.filter(e=>e.id!==`all`).map(e=>(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-tint legend-tint--${e.id}`}),` `,e.label]},e.id)):null]}),S===`galaxy`&&w===wG.GALAXY?(0,$.jsxs)(`p`,{className:`orientation-bar`,children:[(0,$.jsxs)(`span`,{children:[p.regions.length,` `,b===`all`?p.regions.length===1?`system`:`systems`:`${AG(b)} ${p.regions.length===1?`system`:`systems`}`]}),(0,$.jsx)(`span`,{className:`orientation-bar__charted`,children:se?`all charted`:`${ae.size} charted`}),p.partial_files.length?(0,$.jsxs)(`span`,{className:`partial-summary`,children:[p.partial_files.length,` unchartable · syntax error`]}):null]}):null,S===`galaxy`?me:null,w===wG.SYSTEM&&le?(0,$.jsx)(Iq,{suite:r,error:i,mode:k,onClose:()=>e.dispatch({type:`CLOSE_CHECKS`}),onSubmit:(t,n)=>e.dispatch({type:`SUBMIT_CHECK`,checkId:t,selectedIds:n})}):null,s&&w===wG.GALAXY?(0,$.jsx)(Fq,{candidates:g.entrypoint_candidates,nodes:g.nodes,selectedEntrypoint:g.selected_entrypoint,error:o,onSelect:t=>e.dispatch({type:`SELECT_ENTRYPOINT`,nodeId:t}),onContinue:()=>e.dispatch({type:`DISMISS_ENTRYPOINT`})}):null,T?(0,$.jsxs)(`output`,{className:`illumination-pulse`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),(0,$.jsxs)(`strong`,{children:[T,` understood`]})]}):null,w===wG.STUDY&&oe?(0,$.jsx)(MK,{node:oe,study:fe,error:pe,mode:k,explanation:l,explanationLoading:d,explanationError:u,llmStatus:E,onSelectNode:t=>e.dispatch({type:`SELECT_STUDY_NODE`,nodeId:t}),onRetryNarration:()=>e.dispatch({type:`SELECT_STUDY_NODE`,nodeId:oe.id})}):null,A===!0&&!a?(0,$.jsx)(dK,{layer:S,onDismiss:()=>e.dispatch({type:`DISMISS_COACHMARKS`})}):null,f?(0,$.jsx)(Aq,{index:ee,onGo:t=>e.dispatch({type:`GO_TO_REGION`,regionId:t}),onClose:()=>e.dispatch({type:`SET_FINDER_OPEN`,open:!1})}):null,(0,$.jsx)(cK,{hint:v,onStudy:t=>e.dispatch({type:`ADVANCE_REGION`,regionId:t})})]}),(0,$.jsxs)(`footer`,{className:`status-line`,children:[(0,$.jsx)(`span`,{children:ce?`${n.length} concepts detected`:b===`all`?`${g.nodes.length} nodes · ${g.edges.length} edges`:`${p.nodes.length}/${g.nodes.length} nodes · ${p.edges.length} focused edges`}),(0,$.jsx)(`span`,{children:ce?`${h} focused structures studied this session`:S===`map`?`Click a box or row to study · Switch tabs to change view`:`Drag to orbit · Scroll to zoom · Click to move closer · Escape to move back`}),(0,$.jsx)(`span`,{children:`Local only`})]})]})}var Cq=Object.fromEntries(eq.map(({id:e,copy:t})=>[e,t])),wq=eq.map(({id:e})=>e);function Tq({progress:e,onCancel:t}){let{stage:n,detail:r,files_done:i,files_total:a,pollError:o,pollOutage:s,attempts:c,path:l}=e,[u,d]=(0,_.useState)(!1),[f,p]=(0,_.useState)(``),m=(0,_.useRef)(null),h=wq.indexOf(n);(0,_.useEffect)(()=>{m.current?.focus()},[]);async function g(){d(!0),p(``);try{await t()}catch(e){p(e.message),d(!1)}}return(0,$.jsxs)(`main`,{className:`loading-screen`,children:[(0,$.jsxs)(`header`,{className:`loading-header`,children:[(0,$.jsx)(`p`,{className:`picker-wordmark`,children:`Codemble`}),(0,$.jsxs)(`h1`,{ref:m,tabIndex:-1,children:[`Mapping `,(0,$.jsx)(`span`,{className:`loading-path`,children:l})]}),(0,$.jsx)(`p`,{className:`loading-subtitle`,children:`Parsing runs on your machine. Nothing is sent anywhere.`})]}),(0,$.jsx)(`ol`,{className:`loading-stages`,"aria-label":`Parse stages`,children:wq.map((e,t)=>{let n=t(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:u,onClick:()=>r(e.project_root),children:[(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.project_root}),(0,$.jsxs)(`span`,{className:`picker-recent-lit`,children:[e.understood_count,` `,e.understood_count===1?`system`:`systems`,` lit last visit`]})]})},e.project_root))})]}):null,l?(0,$.jsx)(Dq,{scale:l,busy:u,onBrowse:n}):null,t?(0,$.jsx)(kq,{failure:t,busy:u,onSelect:r}):c?(0,$.jsx)(`p`,{className:`picker-error`,role:`alert`,children:c}):null,(0,$.jsxs)(`section`,{className:`picker-browser`,"aria-labelledby":`picker-browser-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-browser-heading`,children:`Browse folders`}),(0,$.jsx)(`p`,{className:`picker-path`,children:i}),(0,$.jsxs)(`ul`,{children:[a?(0,$.jsx)(`li`,{children:(0,$.jsx)(`button`,{type:`button`,disabled:u,onClick:()=>n(a),children:`↑ Up`})}):null,o.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:u,onClick:()=>n(e.path),children:[e.name,`/`]})},e.path))]}),(0,$.jsx)(`button`,{className:`picker-select`,type:`button`,disabled:u,onClick:()=>r(i),children:u?`Mapping…`:`Map this folder`})]})]})}function Dq({scale:e,busy:t,onBrowse:n}){let r=e.suggestions.filter(e=>e.path!==`.`);return(0,$.jsxs)(`section`,{className:`picker-scale`,role:`alert`,"aria-labelledby":`picker-scale-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-scale-heading`,children:`That folder is too big to map at once.`}),(0,$.jsxs)(`p`,{children:[`It has `,e.file_count,` supported source files; Codemble maps up to`,` `,e.scale_cap,`. Choose a smaller scope — busiest first.`]}),r.length?(0,$.jsx)(`ul`,{className:`picker-scale-scopes`,children:r.map(r=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:t,onClick:()=>n(`${e.root}/${r.path}`),children:[(0,$.jsxs)(`span`,{children:[r.path,`/`]}),(0,$.jsxs)(`small`,{children:[r.file_count,` files`]})]})},r.path))}):null,(0,$.jsx)(Oq,{busy:t,onBrowse:n})]})}function Oq({busy:e,onBrowse:t}){let[n,r]=(0,_.useState)(``);return(0,$.jsxs)(`form`,{className:`picker-path-entry`,onSubmit:e=>{e.preventDefault();let r=n.trim();r&&t(r)},children:[(0,$.jsx)(`label`,{htmlFor:`picker-path-input`,children:`Or type a folder path`}),(0,$.jsx)(`input`,{id:`picker-path-input`,type:`text`,value:n,disabled:e,placeholder:`/Users/you/project/src`,onChange:e=>r(e.target.value)}),(0,$.jsx)(`button`,{type:`submit`,disabled:e||!n.trim(),children:`Go`})]})}function kq({failure:e,busy:t,onSelect:n}){return(0,$.jsxs)(`section`,{className:`picker-failure`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`Codemble could not map that folder.`}),(0,$.jsx)(`p`,{children:`Nothing on disk changed, and no project's saved progress was touched. Try it again, or choose a different folder below.`}),(0,$.jsxs)(`p`,{className:`picker-failure__detail`,children:[(0,$.jsx)(`span`,{children:`What the parser reported`}),(0,$.jsx)(`code`,{children:e.detail})]}),(0,$.jsxs)(`button`,{className:`picker-select`,type:`button`,disabled:t,onClick:()=>n(e.path),children:[`Try `,(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.path}),` again`]})]})}function Aq({index:e,onGo:t,onClose:n}){let[r,i]=(0,_.useState)(``),[a,o]=(0,_.useState)(0),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useMemo)(()=>{let t=r.trim().toLowerCase();return(t?e.filter(e=>e.label.toLowerCase().includes(t)||e.file.toLowerCase().includes(t)):e).slice(0,60)},[e,r]);(0,_.useLayoutEffect)(()=>{let e=s.current;e&&!e.open&&e.showModal(),c.current?.focus()},[]),(0,_.useEffect)(()=>o(0),[r]);let u=l[Math.min(a,l.length-1)]??null;function d(e){e.key===`ArrowDown`?(e.preventDefault(),o(e=>Math.min(e+1,l.length-1))):e.key===`ArrowUp`?(e.preventDefault(),o(e=>Math.max(e-1,0))):e.key===`Enter`&&u&&(e.preventDefault(),t(u.id))}return(0,$.jsxs)(`dialog`,{ref:s,className:`module-finder`,"aria-label":`Find a module`,onCancel:e=>{e.preventDefault(),n()},onClose:n,children:[(0,$.jsx)(`input`,{ref:c,type:`search`,value:r,placeholder:`Find a module…`,"aria-label":`Find a module by name or path`,onChange:e=>i(e.target.value),onKeyDown:d}),(0,$.jsx)(`ul`,{role:`listbox`,"aria-label":`Matching modules`,children:l.map((e,n)=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n===a,"data-active":n===a||void 0,onMouseEnter:()=>o(n),onClick:()=>t(e.id),children:[(0,$.jsx)(`strong`,{children:e.label}),(0,$.jsx)(`small`,{children:e.file}),e.home?(0,$.jsx)(`em`,{children:`Home`}):e.understood?(0,$.jsx)(`em`,{children:`lit`}):null]})},e.id))}),l.length?null:(0,$.jsx)(`p`,{className:`module-finder__empty`,children:`No module matches that.`})]})}function jq({index:e,currentRegionId:t,onGo:n,onClose:r}){let i=(0,_.useMemo)(()=>zG(e),[e]);return(0,$.jsxs)(`aside`,{className:`index-sidebar`,"aria-label":`Project index`,children:[(0,$.jsxs)(`header`,{children:[(0,$.jsx)(`h2`,{children:`Modules`}),(0,$.jsx)(`button`,{type:`button`,onClick:r,"aria-label":`Close the project index`,children:`×`})]}),(0,$.jsx)(`div`,{className:`index-sidebar__scroll`,children:i.map(e=>(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{title:e.name,children:e.name}),(0,$.jsx)(`ul`,{children:e.members.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-current":e.id===t?`true`:void 0,"data-lit":e.understood||void 0,title:e.file,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.display??e.label}),e.home?(0,$.jsx)(`em`,{children:`Home`}):null]})},e.id))})]},e.community))})]})}function Mq({layer:e,mode:t,onChange:n}){return(0,$.jsx)(`nav`,{className:`layer-switcher`,"aria-label":`View layer`,children:[{id:`galaxy`,label:`Galaxy`},{id:`map`,label:t===`easy`?`Diagram`:`Map`}].map(t=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":e===t.id,onClick:()=>n(t.id),children:t.label},t.id))})}function Nq({options:e,value:t,onChange:n}){return e.length<=2?null:(0,$.jsxs)(`nav`,{className:`language-focus`,"aria-label":`Language focus`,children:[(0,$.jsx)(`span`,{className:`language-focus__label`,children:`Focus`}),(0,$.jsx)(`div`,{children:e.map(e=>(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Focus ${e.label}: ${e.count} ${e.count===1?`system`:`systems`}`,"aria-pressed":t===e.id,title:e.label,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.shortLabel}),(0,$.jsx)(`small`,{children:e.count})]},e.id))})]})}function Pq({onConfirm:e}){let[t,n]=(0,_.useState)(!1),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(``),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useRef)(!1);(0,_.useEffect)(()=>{t?c.current?.focus():l.current&&s.current?.focus(),l.current=t},[t]);function u(){n(!1),o(``)}async function d(){i(!0),o(``);try{await e()}catch(e){o(e.message),i(!1)}}return t?(0,$.jsxs)(`div`,{className:`switch-project`,role:`group`,"aria-label":`Switch project`,tabIndex:-1,ref:c,onKeyDown:e=>{e.key===`Escape`&&!r&&u()},children:[(0,$.jsx)(`p`,{children:`Progress is saved per project, so this galaxy comes back lit.`}),a?(0,$.jsx)(`p`,{className:`switch-project__error`,role:`alert`,children:a}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:d,children:r?`Releasing…`:`Switch`}),(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:u,children:`Cancel`})]})]}):(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,ref:s,onClick:()=>n(!0),children:`Switch project`})}function Fq({candidates:e,nodes:t,selectedEntrypoint:n,error:r,onSelect:i,onContinue:a}){let o=new Map(t.map(e=>[e.id,e]));return(0,$.jsxs)(`aside`,{className:`entrypoint-picker`,"aria-labelledby":`entrypoint-heading`,children:[(0,$.jsx)(`p`,{children:`Home calibration`}),(0,$.jsx)(`h1`,{id:`entrypoint-heading`,children:e.length?`Where does your project start?`:`No clear entrypoint found.`}),(0,$.jsx)(`p`,{children:e.length?`The parser found ranked candidates but cannot choose one honestly. Select the structure you run.`:`No file here declares a startup structure the parser recognises, and Codemble will not guess one. Explore the map without Home — every system, check, explanation, and lens note still works.`}),e.length?(0,$.jsx)(`div`,{className:`entrypoint-candidates`,children:e.map(e=>{let t=o.get(e);return(0,$.jsxs)(`button`,{type:`button`,onClick:()=>i(e),children:[(0,$.jsx)(`span`,{children:e}),(0,$.jsxs)(`small`,{children:[t?.file,`:`,t?.lineno,` · parser rank `,t?.entrypoint_rank]})]},e)})}):null,r?(0,$.jsx)(`p`,{className:`entrypoint-error`,role:`alert`,children:r}):null,(0,$.jsx)(`button`,{className:`entrypoint-continue`,type:`button`,onClick:a,children:n?`Keep current Home`:`Explore without Home`})]})}function Iq({suite:e,error:t,mode:n,onClose:r,onSubmit:i}){let a=e?.checks.find(e=>!e.passed)??null,o=e?.checks.filter(e=>e.passed).length??0,[s,c]=(0,_.useState)(()=>new Set),[l,u]=(0,_.useState)(null),[d,f]=(0,_.useState)(``),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(``);(0,_.useEffect)(()=>{c(new Set),u(null),g(``)},[a?.id]);function v(e,t){f(``),c(n=>{if(!t)return new Set([e]);let r=new Set(n);return r.has(e)?r.delete(e):r.add(e),r})}async function y(e){if(e.preventDefault(),!(!a||s.size===0)){m(!0),g(``);try{let e=await i(a.id,[...s]);e.correct?(f(e.message),u(null)):(f(``),u(e))}catch(e){g(e.message)}finally{m(!1)}}}return(0,$.jsxs)(`aside`,{className:`check-panel`,"aria-label":`Graph-derived understanding checks`,children:[(0,$.jsxs)(`header`,{className:`check-panel__header`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:`Active recall · graph only`}),(0,$.jsx)(`h1`,{children:e?.region_id??`Loading checks`})]}),(0,$.jsx)(`button`,{className:`check-close`,type:`button`,onClick:r,children:`Close`})]}),t||h?(0,$.jsxs)(`div`,{className:`check-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The checks did not load.`}),(0,$.jsxs)(`p`,{children:[t||h,` The galaxy remains available.`]})]}):null,!e&&!t?(0,$.jsx)(`p`,{className:`check-loading`,role:`status`,children:`Deriving answers from parser edges…`}):null,e?.region_understood?(0,$.jsxs)(`div`,{className:`check-complete`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{className:`check-complete__star`,"aria-hidden":`true`,children:`✦`}),(0,$.jsx)(`h2`,{children:`System lit.`}),(0,$.jsx)(`p`,{children:`This region's source hash matches the checks you passed. Edit its file and only this system will dim again.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:r,children:`Return to the system`})]}):null,e&&!e.region_understood&&e.checks.length===0?(0,$.jsxs)(`div`,{className:`check-state`,children:[(0,$.jsx)(`h2`,{children:`No safe check yet.`}),(0,$.jsx)(`p`,{children:`Every question here is answered by the parser graph, and this region has no certain relationship Codemble can build one from. It stays dim rather than lighting on a question that would prove nothing. Import this module somewhere, or call something inside it, and its checks appear.`})]}):null,a&&!e.region_understood?(0,$.jsxs)(`form`,{className:`active-check`,onSubmit:y,children:[(0,$.jsxs)(`div`,{className:`check-progress`,children:[(0,$.jsxs)(`span`,{children:[`Check `,o+1,` of `,e.checks.length]}),(0,$.jsx)(`progress`,{value:o,max:e.checks.length})]}),d?(0,$.jsxs)(`p`,{className:`check-affirmation`,role:`status`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),` `,d]}):null,(0,$.jsxs)(`fieldset`,{children:[(0,$.jsx)(`legend`,{children:a.prompt_voices[n]}),a.multiple?(0,$.jsx)(`p`,{children:`Select every answer supported by the graph.`}):null,(0,$.jsx)(`div`,{className:`check-options`,children:a.options.map(e=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:a.multiple?`checkbox`:`radio`,name:`answer-${a.id}`,value:e.id,checked:s.has(e.id),onChange:()=>v(e.id,a.multiple)}),(0,$.jsx)(`span`,{children:e.label})]},e.id))})]}),l&&!l.correct?(0,$.jsxs)(`div`,{className:`check-feedback`,role:`status`,children:[(0,$.jsx)(`strong`,{children:l.message}),(0,$.jsxs)(`span`,{children:[`Parser answer: `,l.answer_labels.join(`, `)]}),(0,$.jsxs)(`span`,{children:[`Evidence: `,l.evidence.join(`, `)]})]}):null,(0,$.jsx)(`button`,{className:`check-primary`,type:`submit`,disabled:!s.size||p,children:p?`Checking parser evidence…`:`Check answer`})]}):null]})}function Lq({chart:e,studiedCount:t,projectName:n,onClearProgress:r}){let i=e.filter(e=>e.understood_nodes>0).length;return(0,$.jsxs)(`section`,{className:`star-chart-screen`,"aria-labelledby":`star-chart-heading`,children:[(0,$.jsxs)(`header`,{className:`star-chart-intro`,children:[(0,$.jsx)(`p`,{children:`Parser-detected concepts`}),(0,$.jsx)(`h1`,{id:`star-chart-heading`,children:`Your language star chart.`}),(0,$.jsx)(`p`,{children:`Encountered comes from real syntax. Studied tracks this session. Understood lights only after graph-derived checks pass.`}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts encountered`}),(0,$.jsx)(`dd`,{children:e.length})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied this session`}),(0,$.jsx)(`dd`,{children:t})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts understood`}),(0,$.jsx)(`dd`,{children:i})]})]})]}),(0,$.jsx)(`div`,{className:`concept-ledger`,role:`list`,"aria-label":`Language concept progress`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`concept-row`,role:`listitem`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h2`,{children:kG(e.concept)}),(0,$.jsxs)(`span`,{children:[kG(e.language),` · `,e.occurrences,` parser `,e.occurrences===1?`occurrence`:`occurrences`]})]}),(0,$.jsx)(`div`,{className:`concept-meter`,"aria-label":`${e.understood_nodes} of ${e.nodes} structures understood`,children:(0,$.jsx)(`span`,{style:{width:`${e.nodes?e.understood_nodes/e.nodes*100:0}%`}})}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied (session)`}),(0,$.jsxs)(`dd`,{children:[e.studied_nodes,`/`,e.nodes]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Understood`}),(0,$.jsxs)(`dd`,{children:[e.understood_nodes,`/`,e.nodes]})]})]})]},`${e.language}:${e.concept}`))}),(0,$.jsx)(Rq,{projectName:n,onConfirm:r})]})}function Rq({projectName:e,onConfirm:t}){let[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(``),c=(0,_.useRef)(null),l=(0,_.useRef)(null),u=(0,_.useRef)(!1);(0,_.useEffect)(()=>{n?l.current?.focus():u.current&&c.current?.focus(),u.current=n},[n]);function d(){r(!1),s(``)}async function f(){a(!0),s(``);try{await t(),r(!1)}catch(e){s(e.message)}finally{a(!1)}}return n?(0,$.jsxs)(`section`,{className:`progress-reset progress-reset--confirming`,role:`group`,"aria-label":`Clear this project's progress`,tabIndex:-1,ref:l,onKeyDown:e=>{e.key===`Escape`&&!i&&d()},children:[(0,$.jsxs)(`p`,{role:`alert`,children:[`This dims every system you lit in `,e,` and cannot be undone. Your other projects keep their progress, and no source file is touched.`]}),o?(0,$.jsx)(`p`,{className:`progress-reset__error`,role:`alert`,children:o}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`check-primary progress-reset__confirm`,type:`button`,disabled:i,onClick:f,children:i?`Clearing…`:`Yes, clear ${e}`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,disabled:i,onClick:d,children:`Keep it`})]})]}):(0,$.jsxs)(`section`,{className:`progress-reset`,children:[(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,ref:c,onClick:()=>r(!0),children:`Clear this project's progress`}),(0,$.jsxs)(`p`,{children:[`Start `,e,` over with every system dim again.`]})]})}var zq=class extends _.Component{constructor(e){super(e),this.state={message:``}}static getDerivedStateFromError(e){return{message:e instanceof Error?e.message:String(e)}}componentDidCatch(e,t){console.error(`Codemble stopped rendering:`,e,t?.componentStack)}render(){return this.state.message?(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The galaxy stopped rendering.`}),(0,$.jsx)(`p`,{children:this.state.message}),(0,$.jsx)(`p`,{children:`Your progress is saved on this machine; reloading re-reads it.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>window.location.reload(),children:`Reload Codemble`})]}):this.props.children}};(0,v.createRoot)(document.getElementById(`root`)).render((0,$.jsx)(_.StrictMode,{children:(0,$.jsx)(zq,{children:(0,$.jsx)(Sq,{})})})); \ No newline at end of file + }`})}};UW.BlurDirectionX=new L(1,0),UW.BlurDirectionY=new L(0,1);var WW=.9,GW=.45,KW=.52,qW=1600;function JW(e){let t=e.postProcessingComposer(),n=new UW(new L(t._width??1,t._height??1),WW,GW,KW),r=n.setSize.bind(n);n.setSize=(e,t)=>{let n=Math.min(1,qW/Math.max(e,t,1));r(Math.max(1,Math.round(e*n)),Math.max(1,Math.round(t*n)))},t.addPass(n);let i=new Ez(xz);return t.addPass(i),{pass:n,composer:t,dispose(){t.removePass(i),i.dispose(),t.removePass(n),n.dispose()}}}var YW=1200;function XW(){return globalThis.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches??!1}function ZW({scene:e,regionId:t,palette:n}){if(XW())return()=>{};let r=e.getObjectByName(`codemble-system-${t}`);if(!r)return()=>{};let i=[];r.traverse(e=>{e.isSprite&&i.push([e,e.material.opacity,e.scale.x])});let a=new B(n.star),o=i.map(([e])=>e.material.color.clone()),s=0,c=performance.now(),l=()=>{let e=Math.min(1,(performance.now()-c)/YW);1-(1-e)**3;let t=Math.sin(e*Math.PI);if(i.forEach(([e,n,r],i)=>{e.material.color.copy(o[i]).lerp(a,t*.85),e.material.opacity=n+t*.5,e.scale.setScalar(r*(1+t*.45))}),e<1){s=requestAnimationFrame(l);return}i.forEach(([e,t,n],r)=>{e.material.color.copy(o[r]),e.material.opacity=t,e.scale.setScalar(n)})};return s=requestAnimationFrame(l),()=>{cancelAnimationFrame(s),i.forEach(([e,t,n],r)=>{e.material.color.copy(o[r]),e.material.opacity=t,e.scale.setScalar(n)})}}var QW=Object.freeze({width:132,height:30}),$W=Object.freeze({far:14,near:44}),eG=Object.freeze([0,-1,1,-2,2]),tG=4,nG=.034;function rG(e,{radius:t,aspect:n}){return e.scale.set(nG*n,nG,1),e.userData.baseOffsetY=t*2.2+1.2,e.position.set(0,e.userData.baseOffsetY,0),e.visible=!1,e.userData.codembleLabel=!0,e.userData.screenWidthFraction=nG*n,e.userData.screenHeightFraction=nG,e}function iG(e){let t=aG(e),n=new R,r=new R;function i({scene:e,camera:i,width:a,height:o,distance:s,distanceBounds:c,hoverNodeId:l=null}){let u=oG(e);for(let e of u)e.visible=!1;if(!u.length||!t.size)return Object.freeze({budget:0,shown:0,visibleIds:Object.freeze([])});let d=sG(s,c),f=[];for(let e of u){let s=e.userData.nodeId,c=e.parent;if(!c)continue;c.getWorldPosition(r);let u=e.userData.baseOffsetY??0,d=cG(r,u,i,a,o,n);if(!d)continue;let p=cG(r,u+1,i,a,o,n),m=p?Math.abs(p.screenY-d.screenY):0;f.push({sprite:e,nodeId:s,origin:r.clone(),base:u,pixelsPerUnit:m,anchor:d,halfWidth:(e.userData.screenWidthFraction??.14)*o/2,halfHeight:(e.userData.screenHeightFraction??.034)*o/2,rank:s===l?-1:t.get(s)??1/0})}f.sort((e,t)=>e.rank-t.rank||e.nodeId.localeCompare(t.nodeId));let p=new Set,m=[];for(let e of f){if(m.length>=d)break;let t=lG(e,{camera:i,width:a,height:o,projected:n,taken:p});if(t){for(let e of t.cells)p.add(e);e.sprite.position.y=e.base+t.offset,e.sprite.visible=!0,m.push(e.nodeId)}}return Object.freeze({budget:d,shown:m.length,visibleIds:Object.freeze(m)})}function a(e){for(let t of oG(e))t.visible=!1}return Object.freeze({hide:a,place:i})}function aG(e){let t=e.filter(e=>e.label).map(e=>({id:e.id,weight:(e.home?3e6:0)+(e.understood?1e6:0)+(e.centrality??0)*1e3})).sort((e,t)=>t.weight-e.weight||e.id.localeCompare(t.id));return new Map(t.map((e,t)=>[e.id,t]))}function oG(e){let t=[];return e.traverse(e=>{e.userData?.codembleLabel&&t.push(e)}),t}function sG(e,t){let n=Math.max(1,t.max-t.min),r=1-Math.min(1,Math.max(0,(e-t.min)/n));return Math.round($W.far+($W.near-$W.far)*r)}function cG(e,t,n,r,i,a){if(a.set(e.x,e.y+t,e.z).project(n),a.z>1)return null;let o=(a.x*.5+.5)*r,s=(-a.y*.5+.5)*i;return o<0||o>r||s<0||s>i?null:{screenX:o,screenY:s}}function lG(e,{camera:t,width:n,height:r,projected:i,taken:a}){let o=e.pixelsPerUnit?(e.halfHeight*2+tG)/e.pixelsPerUnit:0;for(let s of eG){let c=s*o,l=s===0?e.anchor:cG(e.origin,e.base+c,t,n,r,i);if(!l)continue;let u=uG(l,e);if(!u.some(e=>a.has(e)))return{cells:u,offset:c}}return null}function uG(e,{halfWidth:t,halfHeight:n}){let r=Math.floor((e.screenX-t)/QW.width),i=Math.floor((e.screenX+t)/QW.width),a=Math.floor((e.screenY-n)/QW.height),o=Math.floor((e.screenY+n)/QW.height),s=[];for(let e=r;e<=i;e+=1)for(let t=a;t<=o;t+=1)s.push(`${e}:${t}`);return s}var dG=128,fG=256;function pG(e,t){let n=document.createElement(`canvas`);n.width=e,n.height=e;let r=n.getContext(`2d`),i=r.createRadialGradient(e/2,e/2,0,e/2,e/2,e/2);for(let[e,n]of t)i.addColorStop(e,`rgba(255, 255, 255, ${n})`);r.fillStyle=i,r.fillRect(0,0,e,e);let a=new Ra(n);return a.colorSpace=lt,a}function mG(e){let t=document.createElement(`canvas`);t.width=e,t.height=e;let n=t.getContext(`2d`);n.strokeStyle=`rgba(255, 255, 255, 1)`,n.lineWidth=e*.05,n.beginPath(),n.arc(e/2,e/2,e*.4,0,Math.PI*2),n.stroke();let r=new Ra(t);return r.colorSpace=lt,r}function hG(e){let t=[];function n(e){let n=e.dispose.bind(e);return e.dispose=()=>{},t.push(n),e}let r=n(pG(dG,[[0,.85],[.25,.42],[.6,.1],[1,0]])),i=n(pG(fG,[[0,.32],[.45,.14],[.8,.03],[1,0]])),a=n(mG(dG)),o=new Map,s=new Map,c=new Map;function l(t){return c.has(t)||c.set(t,n(vG(t,e))),c.get(t)}function u(t){return o.has(t)||o.set(t,n(new Si({map:r,color:new B(t).multiply(new B(e.starHalo)),blending:2,transparent:!0,depthWrite:!1,opacity:.6}))),o.get(t)}return{halo(e,t){let n=new Ii(u(e.color));return n.scale.setScalar(t*6.5),n.renderOrder=-1,n},nebula(e,t){s.has(e)||s.set(e,n(new Si({map:i,color:new B(e),blending:2,transparent:!0,depthWrite:!1,opacity:.16})));let r=new Ii(s.get(e));return r.scale.setScalar(t),r.renderOrder=-2,r},reticle(t){let n=new Ii(new Si({map:a,color:new B(e.orbit),transparent:!0,depthWrite:!1,depthTest:!1}));return n.scale.setScalar(t*5),n.renderOrder=3,n},label(e,t){let n=l(e),r=new Ii(n);return rG(r,{radius:t,aspect:n.userData.aspect??4}),r.renderOrder=4,r},dispose(){for(let e of t)e();t.length=0,o.clear(),s.clear(),c.clear()}}}var gG=34,_G=12;function vG(e,t){let n=document.createElement(`canvas`),r=n.getContext(`2d`),i=`${gG}px "JetBrains Mono", ui-monospace, monospace`;r.font=i;let a=Math.ceil(r.measureText(e).width)+_G*2;n.width=a,n.height=58,r.font=i,r.textBaseline=`middle`,r.textAlign=`center`,r.fillStyle=t.labelPlate,yG(r,0,0,a,58,8),r.fill(),r.fillStyle=t.labelInk,r.fillText(e,a/2,30);let o=new Ra(n);o.colorSpace=lt;let s=new Si({map:o,transparent:!0,depthWrite:!1,depthTest:!1,sizeAttenuation:!1});s.userData.aspect=a/58;let c=s.dispose.bind(s);return s.dispose=()=>{o.dispose(),c()},s}function yG(e,t,n,r,i,a){e.beginPath(),e.moveTo(t+a,n),e.arcTo(t+r,n,t+r,n+i,a),e.arcTo(t+r,n+i,t,n+i,a),e.arcTo(t,n+i,t,n,a),e.arcTo(t,n,t+r,n,a),e.closePath()}function bG(e){return Object.entries(e??{}).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}:${t}`).join(`|`)}function xG(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}function SG(e){let t=2166136261;for(let n=0;n>>0}function CG(e,t,n=1400,r=1600){let i=xG(SG(e)),a=new Float32Array(n*3);for(let e=0;ee.language===t),r=new Set(n.map(e=>e.id)),i=new Set(e.nodes.map(e=>e.id)),a=new Set(n.map(e=>e.region)),o=new Set(n.map(e=>e.file));return{...e,nodes:n,edges:e.edges.filter(e=>r.has(e.src)&&(r.has(e.dst)||e.external||!i.has(e.dst))),entrypoint_candidates:e.entrypoint_candidates.filter(e=>r.has(e)),selected_entrypoint:r.has(e.selected_entrypoint)?e.selected_entrypoint:null,file_hashes:Object.fromEntries(Object.entries(e.file_hashes).filter(([e])=>o.has(e))),concept_annotations:e.concept_annotations.filter(e=>e.language===t&&r.has(e.node_id)),regions:e.regions.filter(e=>a.has(e.id)),region_edges:e.region_edges.filter(e=>a.has(e.src)&&a.has(e.dst)),partial_files:e.partial_files.filter(e=>o.has(e))}}function EG(e,t){if(!e||!t||t===`all`)return e;let n=e.architecture,r=n.boxes.filter(e=>e.language===t),i=new Set(r.map(e=>e.id)),a=e.workflow,o=`${t}:`;return{...e,architecture:{...n,boxes:r,edges:n.edges.filter(e=>i.has(e.src)&&i.has(e.dst)),unreachable:n.unreachable.filter(e=>i.has(e))},workflow:{...a,nodes:a.nodes.filter(e=>e.language===t),unreachable:a.unreachable.filter(e=>e.startsWith(o))}}}function DG(e){let t=new Map;for(let n of e.regions)t.set(n.language,(t.get(n.language)??0)+1);let n=[...t].map(([e,t])=>({id:e,label:AG(e),shortLabel:jG(e),count:t})).sort((e,t)=>e.label.localeCompare(t.label));return[{id:`all`,label:`All languages`,shortLabel:`All`,count:e.regions.length},...n]}function OG(e,t){let n=new Map(e.nodes.map(e=>[e.id,e])),r=new Map;for(let i of e.concept_annotations??[]){let e=`${i.language}:${i.concept}`,a=r.get(e)??{language:i.language,concept:i.concept,occurrences:0,nodeIds:new Set,studiedNodeIds:new Set,understoodNodeIds:new Set};a.occurrences+=1,a.nodeIds.add(i.node_id),t.has(i.node_id)&&a.studiedNodeIds.add(i.node_id),n.get(i.node_id)?.understood&&a.understoodNodeIds.add(i.node_id),r.set(e,a)}return[...r.values()].map(e=>({language:e.language,concept:e.concept,occurrences:e.occurrences,nodes:e.nodeIds.size,studied_nodes:e.studiedNodeIds.size,understood_nodes:e.understoodNodeIds.size})).sort((e,t)=>e.language.localeCompare(t.language)||e.concept.localeCompare(t.concept))}function kG(e){let t={javascript:`JavaScript`,jsx:`JSX`,typescript:`TypeScript`};return t[e]?t[e]:e.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}function AG(e){return kG(e)}function jG(e){return e===`javascript`?`JS`:e===`typescript`?`TS`:AG(e)}function MG(e){return e===`python`?`nebPython`:e===`javascript`?`nebJs`:e===`typescript`?`nebTs`:null}var NG=2;function PG(e,{showAll:t=!1,selectionId:n=null}={}){let r=()=>new Set(e.regions.map(e=>e.id));if(t||!e.regions.some(e=>e.home))return r();let i=new Set,a=new Set;for(let t of e.regions)typeof t.hops_from_home==`number`&&t.hops_from_home<=NG&&i.add(t.id),t.understood&&a.add(t.id);n&&a.add(n);for(let e of a)i.add(e);for(let t of e.region_edges)(a.has(t.src)||a.has(t.dst))&&(i.add(t.src),i.add(t.dst));return i}function FG(e){let t=new Map;for(let n of e.nodes)t.has(n.region)||t.set(n.region,n.file);return t}function IG(e){return e.split(`/`).filter(Boolean).at(-1)??e}function LG(e){let t=FG(e);return e.regions.map(e=>({id:e.id,file:t.get(e.id)??e.id,label:IG(t.get(e.id)??e.id),language:e.language,community:e.community,understood:e.understood,home:e.home,hops:typeof e.hops_from_home==`number`?e.hops_from_home:null,centrality:e.centrality,loc:e.loc})).sort((e,t)=>e.label.localeCompare(t.label)||e.id.localeCompare(t.id))}function RG(e){if(!e.length)return``;let t=e.map(e=>e.file.split(`/`).slice(0,-1)),n=t[0];for(let e of t.slice(1)){let t=0;for(;t{let n=RG(t),r=n.endsWith(`/`)?n:``;return{community:e,name:n,members:t.map(e=>({...e,display:r&&e.file.startsWith(r)?e.file.slice(r.length):e.file})).sort((e,t)=>e.display.localeCompare(t.display))}}).sort((e,t)=>t.members.length-e.members.length||e.community-t.community)}var BG=5,VG=2;function HG(e,t,n=null){let r=e=>n===null||n.has(e),i=FG(e);return{nodes:e.regions.map(n=>{let a=r(n.id);return{...n,kind:`region`,name:n.id,label:a?IG(i.get(n.id)??n.id):``,charted:a,fx:n.x,fy:n.y,fz:n.z,val:qG(n.loc,5,24),color:a?n.understood?t.star:e.nodes.some(e=>e.region===n.id&&e.partial)?t.routePossible:JG(n.centrality,t,BG):t.nodeDim,focusDim:!1}}),links:e.region_edges.filter(e=>r(e.src)&&r(e.dst)).map(e=>({...e,source:e.src,target:e.dst,color:e.certain?t.route:t.routePossible,focusDim:!1}))}}function UG(e,t,n,{selectedId:r=null}={}){let i=e.nodes.filter(e=>e.region===t),a=new Set(i.map(e=>e.id)),o=e.edges.filter(e=>e.kind===`call`&&!e.external&&a.has(e.src)&&a.has(e.dst)),s=new Set(r?[r]:[]);if(r)for(let e of o)e.src===r&&s.add(e.dst),e.dst===r&&s.add(e.src);return{nodes:i.map(e=>({...e,fx:e.system_x,fy:e.system_y,fz:e.system_z,val:qG(e.loc,2.8,11),color:e.understood?n.star:e.partial?n.routePossible:JG(e.centrality,n,VG),selected:e.id===r,focusDim:!!r&&!s.has(e.id)})),links:o.map(e=>({...e,source:e.src,target:e.dst,color:e.certain?n.route:n.routePossible,focusDim:!!r&&e.src!==r&&e.dst!==r}))}}function WG(e){return e.regions.find(e=>e.home)??e.regions[0]??null}function GG(e){let t=e.kind===`region`?`star system`:e.kind,n=e.partial?` · unchartable · syntax error`:``,r=e.home?` · Home`:``;return`${e.name} · ${t} · ${e.loc} LOC${r}${n}`}function KG(e){let t=e.kind===`import`?`import`:e.kind===`call`?`call`:`import route`,n=e.certain?`certain`:t===`call`?`possible call`:`possible import`,r=typeof e.weight==`number`?` · ${e.weight} ${e.weight===1?`import`:`imports`}`:``,i=typeof e.lineno==`number`?` · line ${e.lineno}`:``;return`${e.src} → ${e.dst} · ${t} · ${n}${r}${i}`}function qG(e,t,n){return Math.min(n,Math.max(t,Math.sqrt(Math.max(1,e))*1.15))}function JG(e,t,n){return e>=n?t.nodeBright:e>=1?t.node:t.nodeDim}function YG(e,t){if(t?.pointerType===`touch`||!Array.isArray(e?._pointers)||e._pointers.length===0)return!1;if(e._pointers.splice(0,e._pointers.length),e._pointerPositions&&typeof e._pointerPositions==`object`)for(let t of Object.keys(e._pointerPositions))delete e._pointerPositions[t];return!0}function XG(e,t){let n=e=>YG(t,e),r=e=>YG(t,e);return e.addEventListener(`pointerdown`,n,{capture:!0}),e.addEventListener(`lostpointercapture`,r,{capture:!0}),()=>{e.removeEventListener(`pointerdown`,n,{capture:!0}),e.removeEventListener(`lostpointercapture`,r,{capture:!0})}}var ZG=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),$=o(((e,t)=>{t.exports=ZG()}))(),QG=420,$G=1.6,eK={GALAXY:{min:120,max:640},SYSTEM:{min:55,max:320},STUDY:{min:22,max:170}},tK=.16,nK=1.5,rK=110,iK=6;function aK({graph:e,level:t,region:n,selectedNode:r,hoverNodeId:i,pendingDawnRegionId:a,revealedRegionIds:o,mode:s,onHoverNode:c,onAdvance:l,onRetreat:u,onDawnConsumed:d}){let f=(0,_.useRef)(null),p=(0,_.useRef)(null),m=(0,_.useRef)(null),h=(0,_.useRef)(l),g=(0,_.useRef)(u),v=(0,_.useRef)(c),y=(0,_.useRef)(a),b=(0,_.useRef)(d),x=(0,_.useRef)(null),S=(0,_.useRef)({activeId:null,neighborIds:new Set}),C=(0,_.useRef)(null),w=(0,_.useRef)(null),T=(0,_.useRef)(null),[E,D]=(0,_.useState)(0),[O,k]=(0,_.useState)(``),A=(0,_.useMemo)(lK,[]),ee=(0,_.useMemo)(XW,[]),te=bG(e.file_hashes),ne=(0,_.useMemo)(()=>t===wG.GALAXY?HG(e,A,o):UG(e,n?.id,A,{selectedId:r?.id}),[e,t,A,n?.id,o,r?.id]);(0,_.useEffect)(()=>{h.current=l,g.current=u,v.current=c,y.current=a,b.current=d},[l,u,c,a,d]);function re(e){let{activeId:t,neighborIds:n}=S.current;return t?e.id===t?A.orbit:n.has(e.id)?e.color:A.faded:e.color}function ie(e){if(e.focusDim)return A.faded;let{activeId:t,neighborIds:n}=S.current,r=e.certain?A.route:A.routePossible;if(!t)return r;let i=sK(e.source),a=sK(e.target);return i===t||a===t?A.orbit:n.has(i)&&n.has(a)?r:A.faded}function j(e){if(e.focusDim)return .4;let{activeId:t}=S.current,n=Math.min(2.2,.45+(e.weight??1)*.25);if(!t)return n;let r=sK(e.source),i=sK(e.target);return r===t||i===t?n+.9:n}(0,_.useEffect)(()=>{let e=f.current;if(!e)return;let t=document.createElement(`canvas`);if(!t.getContext(`webgl2`)&&!t.getContext(`webgl`)){k(`Codemble needs WebGL to draw your galaxy. Enable WebGL and reload.`);return}try{let t=hG(A);C.current=t;let n=BW({controlType:`orbit`})(e).backgroundColor(A.ground).showNavInfo(!1).enableNavigationControls(!0).enableNodeDrag(!1).warmupTicks(0).cooldownTicks(0).nodeId(`id`).nodeLabel(GG).nodeVal(`val`).nodeColor(re).nodeRelSize($G).nodeResolution(8).nodeOpacity(.82).nodeThreeObject(e=>oK(e,A,t,T.current)).nodeThreeObjectExtend(!0).linkColor(ie).linkLabel(KG).linkOpacity(.32).linkWidth(j).linkCurvature(.12).linkVisibility(e=>!(s===`easy`&&e.focusDim)).linkHoverPrecision(4).linkDirectionalArrowRelPos(1).linkDirectionalArrowColor(ie).linkDirectionalParticles(e=>e.kind===`call`&&e.certain&&!e.focusDim&&!ee?2:0).linkDirectionalParticleSpeed(.006).linkDirectionalParticleWidth(1.1).linkDirectionalParticleColor(()=>A.orbit).onNodeHover(t=>{e.style.cursor=t?`pointer`:`default`,v.current(t?.id??null)}).onNodeClick(e=>h.current(e)),r=requestAnimationFrame(()=>{e.querySelector(`.scene-nav-info`)?.remove()}),i=n.controls();i.enablePan=!1,i.enableDamping=!ee,i.dampingFactor=.12,i.rotateSpeed=.55,i.zoomSpeed=.7,i.minPolarAngle=tK,i.maxPolarAngle=nK,m.current=i;let a=XG(e,i);w.current=JW(n),p.current=n;let o=new ResizeObserver(([e])=>{n.width(e.contentRect.width).height(e.contentRect.height)});return o.observe(e),()=>{o.disconnect(),cancelAnimationFrame(r),a(),n.pauseAnimation(),w.current?.dispose(),w.current=null,n._destructor(),t.dispose(),C.current=null,m.current=null,e.replaceChildren(),p.current=null}}catch(e){k(`The galaxy could not start: ${e.message}`);return}},[A]),(0,_.useEffect)(()=>{let e=p.current;if(!e)return;e.nodeResolution(ne.nodes.length>=900?4:8).linkVisibility(e=>!(s===`easy`&&e.focusDim)).linkDirectionalArrowLength(t===wG.GALAXY?0:3.2).graphData(ne);let n=eK[t]??eK.GALAXY;m.current&&(m.current.minDistance=n.min,m.current.maxDistance=n.max),t===wG.GALAXY?e.cameraPosition({x:0,y:105,z:310},{x:0,y:0,z:0},QG):e.cameraPosition({x:0,y:52,z:150},{x:0,y:0,z:0},QG),D(0)},[ne,t,s]),(0,_.useEffect)(()=>{T.current=ne.nodes[E]?.id??null,p.current?.refresh()},[ne.nodes,E]),(0,_.useEffect)(()=>{let e=p.current;if(!e)return;let t=e.scene(),n=t.getObjectByName(`codemble-starfield`);n&&(t.remove(n),n.geometry.dispose(),n.material.dispose());let r=CG(te,A);return t.add(r),()=>{t.remove(r),r.geometry.dispose(),r.material.dispose()}},[te,A]),(0,_.useEffect)(()=>{let e=p.current;if(!e||t!==wG.GALAXY)return;let n=y.current;if(!n||x.current===n)return;x.current=n,b.current?.(n);let r=!1,i=()=>{},a=t=>{if(r)return;let s=e.scene();if(s.getObjectByName(`codemble-system-${n}`)||t>=iK){i=ZW({scene:s,regionId:n,palette:A});return}o=requestAnimationFrame(()=>a(t+1))},o=requestAnimationFrame(()=>a(0));return()=>{r=!0,cancelAnimationFrame(o),i()}},[t,A]),(0,_.useEffect)(()=>{let e=i??(t===wG.STUDY?r?.id??null:null),n=new Set;if(e)for(let t of ne.links){let r=sK(t.source),i=sK(t.target);r===e&&n.add(i),i===e&&n.add(r)}S.current={activeId:e,neighborIds:n};let a=p.current;a&&a.nodeColor(a.nodeColor()).linkColor(a.linkColor()).linkWidth(a.linkWidth()).linkDirectionalArrowColor(a.linkDirectionalArrowColor())},[ne,i,t,r?.id]);let M=(0,_.useMemo)(()=>iG(ne.nodes),[ne.nodes]);(0,_.useEffect)(()=>{let e=p.current;if(!e)return;let n=e.scene();function r(){let r=e.camera(),a=m.current,o=eK[t]??eK.GALAXY,s=a?r.position.distanceTo(a.target):r.position.length();M.place({scene:n,camera:r,width:e.width(),height:e.height(),distance:s,distanceBounds:o,hoverNodeId:i})}let a=null;function o(){try{r()}catch(e){a!==null&&clearInterval(a),M.hide(n),console.error(`Codemble: label declutter failed, names disabled`,e)}}return o(),a=setInterval(o,rK),()=>{clearInterval(a),M.hide(n)}},[i,t,M]),(0,_.useEffect)(()=>{if(!new URLSearchParams(window.location.search).has(`benchmark`)||ne.nodes.length<900)return;document.documentElement.removeAttribute(`data-codemble-fps`);let e=setTimeout(()=>{let e=p.current;if(!e)return;let t=e.renderer(),n=e.postProcessingComposer(),r=performance.now();for(let e=0;e<60;e+=1)n.render();t.getContext().finish();let i=performance.now()-r;document.documentElement.dataset.codembleFps=(60*1e3/i).toFixed(1)},1e3);return()=>clearTimeout(e)},[ne.nodes.length]),(0,_.useEffect)(()=>{!r||!p.current||t!==wG.STUDY||p.current.cameraPosition({x:r.system_x+20,y:r.system_y+15,z:r.system_z+42},{x:r.system_x,y:r.system_y,z:r.system_z},QG)},[t,r]);let ae=ne.nodes[E]??null;function oe(e){e.key===`ArrowRight`||e.key===`ArrowDown`?(e.preventDefault(),D(e=>(e+1)%Math.max(1,ne.nodes.length))):e.key===`ArrowLeft`||e.key===`ArrowUp`?(e.preventDefault(),D(e=>(e-1+ne.nodes.length)%Math.max(1,ne.nodes.length))):e.key===`Enter`&&ae?(e.preventDefault(),h.current(ae)):(e.key===`Escape`||e.key===`Backspace`)&&(e.preventDefault(),g.current())}return O?(0,$.jsxs)(`section`,{className:`webgl-error`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The sky could not open.`}),(0,$.jsx)(`p`,{children:O}),(0,$.jsxs)(`p`,{children:[`The `,s===`easy`?`Diagram`:`Map`,` layer works without WebGL — switch to it at the top of the window to explore the same code.`]})]}):(0,$.jsxs)(`div`,{className:`galaxy-frame`,role:`application`,tabIndex:`0`,"aria-label":`Codemble ${t.toLowerCase()} view. Drag to orbit, scroll to zoom. Use arrow keys to choose a node and Enter to move closer.`,onKeyDown:oe,children:[(0,$.jsx)(`div`,{ref:f,className:`galaxy-canvas`,"aria-hidden":`true`}),ae?(0,$.jsx)(`output`,{className:`keyboard-focus`,"aria-live":`polite`,children:GG(ae)}):null]})}function oK(e,t,n,r){let i=new lr;i.name=e.kind===`region`?`codemble-system-${e.id}`:`codemble-node-${e.id}`;let a=Math.cbrt(e.val??1)*$G,o=e.charted===!1;if(!e.focusDim&&!o&&i.add(n.halo(e,a)),e.kind===`region`&&!o){let r=MG(e.language);r&&i.add(n.nebula(t[r],a*14))}if(e.label){let t=n.label(e.label,a);t.userData.nodeId=e.id,i.add(t)}if(e.home){let e=new ia(new xo(a*1.7,Math.max(.18,a*.07),8,36),new Ki({color:t.home}));e.rotation.x=Math.PI/2.8,i.add(e)}if(e.selected){let e=new ia(new xo(a*2.1,Math.max(.16,a*.05),6,24),new Ki({color:t.orbit}));e.rotation.x=Math.PI/2.8,i.add(e)}return e.id===r&&i.add(n.reticle(a)),i}function sK(e){return typeof e==`object`&&e?e.id:e}function cK(e){let t=document.createElement(`canvas`).getContext(`2d`);t.fillStyle=`#000000`,t.fillStyle=e,t.fillRect(0,0,1,1);let[n,r,i]=t.getImageData(0,0,1,1).data;return`rgb(${n}, ${r}, ${i})`}function lK(){let e=getComputedStyle(document.documentElement),t=t=>cK(e.getPropertyValue(t).trim());return Object.freeze({ground:t(`--cm-ground`),home:t(`--cm-ink`),orbit:t(`--cm-orbit`),nodeBright:t(`--cm-ink-2`),node:t(`--cm-ink-3`),nodeDim:t(`--cm-node-unlit`),route:t(`--cm-hairline`),routePossible:t(`--cm-route-possible`),faded:t(`--cm-hairline-soft`),star:t(`--cm-star-high`),starHalo:t(`--cm-star-halo`),nebPython:t(`--cm-neb-python`),nebJs:t(`--cm-neb-js`),nebTs:t(`--cm-neb-ts`),labelPlate:e.getPropertyValue(`--cm-label-plate`).trim(),labelInk:e.getPropertyValue(`--cm-label-ink`).trim()})}function uK({hint:e,onStudy:t}){return e?(0,$.jsxs)(`output`,{className:`hint-chip`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`→`}),(0,$.jsxs)(`span`,{children:[`Study `,(0,$.jsx)(`strong`,{children:e.regionId}),` next`]}),(0,$.jsx)(`small`,{children:e.reason}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>t(e.regionId),children:`Take me there`})]}):null}var dK=[{title:`What you see`,body:`Every star system is one file, named once you have charted it. Size is how much code it holds; brightness is how many places in your project call it. Faint unnamed markers are modules you have not reached yet.`},{title:`How to move`,body:`Drag to look around and scroll to zoom — the view stays locked on whatever you are studying, so you cannot get lost. Click a system to go in, Escape to come back, and press ⌘K to jump straight to any module by name.`},{title:`What lights stars`,body:`A system lights up only after you answer questions drawn from your own code. Nothing lights up just by looking at it — and each one you light reveals the modules it connects to.`}],fK=[{title:`What you see`,body:`Every box is one file, placed by how your imports connect them. A dashed link is a relationship the parser could not fully prove.`},{title:`How to move`,body:`Click a box to study that module, or press ⌘K to jump to one by name. The tabs above show how it fits together and what runs first. Switch to the Galaxy anytime to fly through the same code.`},{title:`What lights up`,body:`A module lights up only after you answer questions drawn from your own code. Nothing lights up just by looking at it.`}];function pK({layer:e,onDismiss:t}){let[n,r]=(0,_.useState)(0),i=(0,_.useRef)(null),a=e===`map`?fK:dK,o=a[n];(0,_.useLayoutEffect)(()=>{let e=i.current;e&&!e.open&&e.showModal()},[]);function s(){i.current?.close(),t()}return(0,$.jsxs)(`dialog`,{ref:i,className:`coach-marks`,"aria-labelledby":`coach-heading`,onCancel:e=>{e.preventDefault(),s()},children:[(0,$.jsxs)(`p`,{className:`coach-marks__progress`,children:[`Step `,n+1,` of `,a.length]}),(0,$.jsx)(`h1`,{id:`coach-heading`,children:o.title}),(0,$.jsx)(`p`,{children:o.body}),(0,$.jsxs)(`div`,{className:`coach-marks__actions`,children:[(0,$.jsx)(`button`,{type:`button`,className:`coach-skip`,onClick:s,children:`Skip`}),(0,$.jsx)(`button`,{type:`button`,className:`check-primary`,onClick:()=>n+1{let n=i.current?.getBoundingClientRect();!n||!e||!t||o(_K(Math.min(n.width/e,n.height/t)))},[e,t]);(0,_.useEffect)(()=>{let n=i.current;if(!n||typeof ResizeObserver>`u`)return;u.current=!1;let r=0,a=()=>{if(u.current)return;let i=n.getBoundingClientRect();i.width>480||i.width<=0||i.height<=0||(cancelAnimationFrame(r),r=requestAnimationFrame(()=>{let r=n.getBoundingClientRect();r.width>480||r.width<=0||r.height<=0||(o(_K(Math.min(r.width/e,r.height/t))),u.current=!0)}))},s=new ResizeObserver(a);return s.observe(n),a(),()=>{cancelAnimationFrame(r),s.disconnect()}},[e,t]);function f(e){if(e.button!==0||e.target.closest(`[role='button']`))return;let t=i.current;l.current={x:e.clientX,y:e.clientY,left:t.scrollLeft,top:t.scrollTop},c(!0),t.setPointerCapture(e.pointerId)}function p(e){if(!l.current)return;let t=i.current;t.scrollLeft=l.current.left-(e.clientX-l.current.x),t.scrollTop=l.current.top-(e.clientY-l.current.y)}function m(e){l.current&&(l.current=null,c(!1),i.current?.releasePointerCapture?.(e.pointerId))}return(0,$.jsxs)(`div`,{className:`map-canvas`,children:[(0,$.jsxs)(`div`,{className:`map-zoom`,role:`group`,"aria-label":`Zoom ${n}`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom out`,disabled:a<=mK,onClick:()=>o(e=>_K(e/gK)),children:`−`}),(0,$.jsx)(`button`,{type:`button`,onClick:d,children:`Fit`}),(0,$.jsxs)(`button`,{type:`button`,onClick:()=>o(1),children:[Math.round(a*100),`%`]}),(0,$.jsx)(`button`,{type:`button`,"aria-label":`Zoom in`,disabled:a>=hK,onClick:()=>o(e=>_K(e*gK)),children:`+`})]}),(0,$.jsx)(`div`,{ref:i,className:`map-scroll`,"data-panning":s||void 0,onPointerDown:f,onPointerMove:p,onPointerUp:m,onPointerCancel:m,children:(0,$.jsx)(`div`,{className:`map-canvas__sized`,style:{width:e*a,height:t*a},children:r})})]})}var yK={nebPython:`var(--cm-neb-python)`,nebJs:`var(--cm-neb-js)`,nebTs:`var(--cm-neb-ts)`};function bK(e){let t=MG(e);return t?yK[t]:`var(--cm-hairline)`}function xK(e){return e.map(([e,t],n)=>`${n===0?`M`:`L`} ${e} ${t}`).join(` `)}function SK(e){return 1+Math.min(2.5,(Math.max(1,e)-1)*.5)}var CK=13,wK=.62,TK=14,EK=6;function DK(e,t){let n=t-TK-EK,r=Math.max(1,Math.floor(n/(CK*wK)));return e.length<=r?e:`${e.slice(0,Math.max(1,r-1))}…`}function OK({data:e,mapTab:t,mode:n,selectedRegionId:r,hasEntrypointCandidates:i,error:a,onSelectTab:o,onSelectRegion:s,onSelectNode:c,onRetry:l,children:u}){return(0,$.jsxs)(`section`,{className:`map-view`,"aria-label":`Two-dimensional project map`,children:[(0,$.jsxs)(`nav`,{className:`map-tabs`,"aria-label":`Map view`,children:[(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`architecture`,onClick:()=>o(`architecture`),children:n===`easy`?`How it fits together`:`Architecture`}),(0,$.jsx)(`button`,{type:`button`,"aria-pressed":t===`workflow`,onClick:()=>o(`workflow`),children:n===`easy`?`What runs first`:`Workflow`})]}),u,a?(0,$.jsxs)(`div`,{className:`map-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The map did not load.`}),(0,$.jsxs)(`p`,{children:[a,` The galaxy layer is unaffected.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:l,children:`Try again`})]}):e?t===`architecture`?(0,$.jsx)(kK,{architecture:e.architecture,mode:n,selectedRegionId:r,hasEntrypointCandidates:i,onSelectRegion:s}):(0,$.jsx)(AK,{workflow:e.workflow,mode:n,selectedRegionId:r,hasEntrypointCandidates:i,onSelectNode:c}):(0,$.jsx)(`p`,{className:`map-loading`,role:`status`,children:`Laying out parser evidence…`})]})}function kK({architecture:e,mode:t,selectedRegionId:n,hasEntrypointCandidates:r,onSelectRegion:i}){let a=new Map(e.boxes.map(e=>[e.id,e]));return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(vK,{contentWidth:e.width+64,contentHeight:e.height+64,label:`the architecture map`,children:(0,$.jsxs)(`svg`,{className:`architecture-map`,width:`100%`,height:`100%`,preserveAspectRatio:`xMidYMin meet`,viewBox:`-32 -32 ${e.width+64} ${e.height+64}`,role:`group`,"aria-label":e.home?`${e.boxes.length} modules in ${e.layer_count} import layers from Home`:`${e.boxes.length} modules in ${e.layer_count} import layers, measured from the modules nothing imports`,children:[(0,$.jsxs)(`defs`,{children:[(0,$.jsx)(`marker`,{id:`architecture-arrow`,className:`architecture-map__arrow`,markerWidth:`8`,markerHeight:`8`,refX:`8`,refY:`4`,orient:`auto`,markerUnits:`strokeWidth`,children:(0,$.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 Z`,fill:`currentColor`})}),(0,$.jsx)(`marker`,{id:`architecture-cycle-arrow`,className:`architecture-map__arrow is-cycle`,markerWidth:`8`,markerHeight:`8`,refX:`8`,refY:`4`,orient:`auto`,markerUnits:`strokeWidth`,children:(0,$.jsx)(`path`,{d:`M 0 0 L 8 4 L 0 8 Z`,fill:`currentColor`})})]}),(0,$.jsx)(`g`,{className:`architecture-map__edges`,children:e.edges.map(e=>{let t=a.get(e.src),n=a.get(e.dst);return!t||!n?null:(0,$.jsx)(`path`,{d:xK(e.points),strokeDasharray:e.certain?void 0:`5 4`,strokeWidth:SK(e.weight),markerEnd:`url(#${e.cycle?`architecture-cycle-arrow`:`architecture-arrow`})`,className:`architecture-map__edge${e.cycle?` is-cycle`:``}`},`${e.src}->${e.dst}`)})}),e.boxes.map(e=>(0,$.jsxs)(`g`,{className:`architecture-map__box`,"data-understood":e.understood,"data-home":e.home,"data-reachable":e.reachable,"data-partial":e.partial,"data-selected":e.id===n,transform:`translate(${e.x} ${e.y})`,role:`button`,tabIndex:0,"aria-label":`${e.label}, ${e.node_count} structures, ${e.loc} lines${e.understood?`, understood`:`, not yet understood`}${e.home?`, Home`:``}${e.reachable?``:`, no import route from Home`}${e.partial?`, unchartable, syntax error`:``}`,onClick:()=>i(e.id),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),i(e.id))},children:[(0,$.jsxs)(`title`,{children:[e.label,e.partial?` — unchartable, syntax error`:``]}),(0,$.jsx)(`rect`,{width:e.width,height:e.height,rx:`3`}),(0,$.jsx)(`rect`,{className:`box-tint`,width:`4`,height:e.height,fill:bK(e.language)}),e.partial?(0,$.jsx)(`path`,{className:`box-partial`,d:`M ${e.width-16} 2 L ${e.width-2} 2 L ${e.width-2} 16 Z`}):null,(0,$.jsx)(`text`,{x:TK,y:`24`,children:DK(e.short_label??e.label,e.width)}),(0,$.jsx)(`text`,{className:`box-meta`,x:`14`,y:`42`,children:t===`easy`?`${e.node_count} ${e.node_count===1?`piece`:`pieces`}`:`${e.node_count} nodes · ${e.loc} LOC`})]},e.id))]})}),e.home?null:(0,$.jsxs)(`p`,{className:`map-note`,children:[`No Home is selected, so these layers run from the modules nothing else imports rather than from your entrypoint. Both are read from your imports, not guessed.`,` `,r?`Pick your starting point with “Change Home” to see the same modules layered by what the project runs first.`:`This project has no parser-recognisable entrypoint, so there is no “runs first” order to layer by instead.`]}),e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`module has`:`modules have`,` no import route from Home, so `,e.unreachable.length===1?`it sits`:`they sit`,` `,`in the bottom row rather than being placed by guesswork.`]}):null]})}function AK({workflow:e,mode:t,selectedRegionId:n,hasEntrypointCandidates:r,onSelectNode:i}){if(!e.root)return r?(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No Home is selected.`}),(0,$.jsx)(`p`,{children:`The workflow tree starts at your entrypoint. Pick Home and this tab will show what runs first, then what that calls.`})]}):(0,$.jsxs)(`div`,{className:`map-state`,children:[(0,$.jsx)(`h2`,{children:`No “runs first” order to show.`}),(0,$.jsx)(`p`,{children:`This project has no parser-recognisable entrypoint — nothing here declares a startup structure Codemble recognises, and it will not guess one. The other tab still maps how your modules import each other.`})]});let a=new Map(e.nodes.map(e=>[e.order,e]));return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(vK,{contentWidth:e.width+32,contentHeight:e.height+32,label:`the workflow tree`,children:(0,$.jsxs)(`svg`,{className:`workflow-tree`,width:`100%`,height:`100%`,preserveAspectRatio:`xMinYMin meet`,viewBox:`-16 -16 ${e.width+32} ${e.height+32}`,role:`group`,"aria-label":`Call tree from ${e.root}, ${e.nodes.length} steps deep to ${e.depth_count} levels`,children:[(0,$.jsx)(`g`,{className:`workflow-tree__edges`,children:e.nodes.map(e=>{if(e.parent===null)return null;let t=[...a.values()].filter(t=>t.id===e.parent&&t.order(0,$.jsxs)(`g`,{className:`workflow-tree__row`,"data-understood":e.understood,"data-cut":e.cut??void 0,"data-partial":e.partial,"data-relation":e.relation,"data-selected":e.region===n,transform:`translate(${e.x} ${e.y})`,role:`button`,tabIndex:0,"aria-label":`${e.label} at ${e.file}:${e.lineno}${e.certain?``:`, possible call`}${e.cut===`cycle`?`, repeats an earlier step`:``}${e.cut===`repeat`?`, already shown above`:``}${e.partial?`, unchartable, syntax error`:``}`,onClick:()=>i(e.id),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),i(e.id))},children:[(0,$.jsx)(`circle`,{cx:`8`,cy:`16`,r:`4`}),(0,$.jsx)(`text`,{x:`20`,y:`20`,children:e.label}),(0,$.jsxs)(`text`,{className:`row-meta`,x:`20`,y:`20`,dx:`${e.label.length*.62}em`,children:[e.relation===`defines`?t===`easy`?` — lives here`:` — defined in this module`:e.certain?``:` — possible call`,e.cut===`cycle`?` — loops back`:``,e.cut===`repeat`?` — shown above`:``,e.partial?t===`easy`?` — could not be read`:` — unchartable`:``]})]},e.order))]})}),e.unreachable.length?(0,$.jsxs)(`p`,{className:`map-note`,children:[e.unreachable.length,` `,e.unreachable.length===1?`structure is`:`structures are`,` never reached from Home by a parser-proven call. They are listed as unreached rather than attached to the tree by guesswork.`]}):null]})}var jK=[{mode:`easy`,label:`New to coding?`},{mode:`expert`,label:`I build software`}],MK=[{mode:`easy`,label:`Easy`},{mode:`expert`,label:`Expert`}];function NK({mode:e,modeChosen:t,onChoose:n}){let r=(0,_.useRef)(null),i=(0,_.useRef)(null),a=(0,_.useRef)(t);(0,_.useLayoutEffect)(()=>{let e=r.current;e&&t===!1&&!e.open&&e.showModal()},[t]),(0,_.useEffect)(()=>{t===!0&&a.current===!1&&i.current?.focus(),a.current=t},[t]);function o(e){r.current?.close(),n(e)}return t===null?null:t?(0,$.jsxs)(`fieldset`,{className:`mode-toggle`,children:[(0,$.jsx)(`legend`,{className:`mode-toggle__label`,children:`Audience`}),(0,$.jsx)(`div`,{className:`mode-toggle__options`,children:MK.map(t=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:`radio`,name:`audience-mode`,value:t.mode,checked:e===t.mode,ref:e===t.mode?i:void 0,onChange:()=>o(t.mode)}),(0,$.jsx)(`span`,{children:t.label})]},t.mode))})]}):(0,$.jsxs)(`dialog`,{ref:r,className:`mode-gate`,"aria-labelledby":`mode-gate-heading`,"aria-describedby":`mode-gate-detail`,onCancel:e=>e.preventDefault(),children:[(0,$.jsx)(`h1`,{id:`mode-gate-heading`,children:`New to coding, or do you build software already?`}),(0,$.jsx)(`p`,{id:`mode-gate-detail`,children:`This changes how much Codemble explains and how much it assumes you already know.`}),(0,$.jsx)(`div`,{className:`mode-gate__options`,children:jK.map(e=>(0,$.jsx)(`button`,{type:`button`,onClick:()=>o(e.mode),children:e.label},e.mode))})]})}function PK({node:e,study:t,error:n,mode:r,explanation:i,explanationLoading:a,explanationError:o,llmStatus:s,onSelectNode:c,onRetryNarration:l}){return(0,$.jsxs)(`aside`,{className:`study-preview`,"aria-label":`Selected source structure`,"aria-busy":!t&&!n,children:[(0,$.jsxs)(`header`,{className:`study-preview__header`,children:[(0,$.jsxs)(`p`,{className:`study-preview__path`,children:[e.file,`:`,e.lineno]}),(0,$.jsx)(`h1`,{children:e.name}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Kind`}),(0,$.jsx)(`dd`,{children:e.kind})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Span`}),(0,$.jsxs)(`dd`,{children:[e.loc,` lines`]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:r===`easy`?`Used by`:`Callers`}),(0,$.jsx)(`dd`,{children:e.centrality})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Resolution`}),(0,$.jsx)(`dd`,{children:e.partial?`Partial parse`:`Parser-proven`})]})]})]}),n?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`Study data did not load.`}),(0,$.jsxs)(`p`,{children:[n,` The parser map is still available.`]}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>c(e.id),children:`Try again`})]}):null,!t&&!n?(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:`Reading parser evidence…`}):null,t?(0,$.jsxs)(`div`,{className:`study-content`,children:[(0,$.jsx)(FK,{structural:t.structural,mode:r}),(0,$.jsx)(WK,{explanation:i,loading:a,error:o,llmStatus:s,mode:r,node:e,onSelectNode:c,onRetry:l}),(0,$.jsx)(LK,{neighbors:t.neighbors,node:e,mode:r,onSelectNode:c}),(0,$.jsx)(UK,{source:t.source}),(0,$.jsx)(HK,{lens:t.lens,language:e.language,mode:r})]}):null]})}function FK({structural:e,mode:t}){return e?(0,$.jsxs)(`section`,{className:`structural-summary`,"aria-labelledby":`structural-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`structural-heading`,children:t===`easy`?`What this is`:`Structural summary`}),(0,$.jsx)(`span`,{children:`No model needed`})]}),(0,$.jsx)(`p`,{children:e[t]??e.easy})]}):null}var IK=8;function LK({neighbors:e,node:t,mode:n,onSelectNode:r}){let i=e??[],a=i.filter(e=>e.direction===`inbound`),o=i.filter(e=>e.direction===`outbound`);return(0,$.jsxs)(`section`,{className:`connections`,"aria-labelledby":`connections-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`connections-heading`,children:n===`easy`?`What this connects to`:`Parser connections`}),(0,$.jsxs)(`span`,{children:[i.length,` parser `,i.length===1?`relationship`:`relationships`]})]}),i.length===0?(0,$.jsx)(`p`,{className:`study-loading`,children:n===`easy`?`Nothing in your code reaches this yet, and it does not reach anything else.`:`The parser observed no relationship into or out of this structure.`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(VK,{inbound:a,outbound:o,node:t}),(0,$.jsx)(RK,{title:n===`easy`?`Uses this`:`Inbound`,items:a,mode:n,onSelectNode:r}),(0,$.jsx)(RK,{title:n===`easy`?`This uses`:`Outbound`,items:o,mode:n,onSelectNode:r})]})]})}function RK({title:e,items:t,mode:n,onSelectNode:r}){return t.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:e}),(0,$.jsx)(`ul`,{className:`connection-list`,children:t.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,onClick:()=>r(e.node_id),children:[(0,$.jsx)(`span`,{className:`connection-name`,children:e.name}),(0,$.jsxs)(`span`,{className:`connection-meta`,children:[zK(e,n),` · `,BK(e,n)]}),(0,$.jsx)(`span`,{className:`source-citation`,children:e.citation})]})},`${e.direction}-${e.node_id}`))})]}):null}function zK(e,t){return e.relationship===`import`?e.direction===`inbound`?t===`easy`?`brings this in`:`import · inbound`:t===`easy`?`this brings it in`:`import · outbound`:e.direction===`inbound`?t===`easy`?`calls this`:`call · inbound`:t===`easy`?`this calls it`:`call · outbound`}function BK(e,t){return e.certain?`certain`:e.relationship===`import`?t===`easy`?`possible link, not certain`:`possible import`:t===`easy`?`possible link, not certain`:`possible call`}function VK({inbound:e,outbound:t,node:n}){let r=e.slice(0,IK),i=t.slice(0,IK),a=Math.max(r.length,i.length,1)*22+16,o=a/2,s=(e,t)=>(e+1)*a/(t+1);return(0,$.jsxs)(`svg`,{className:`mini-constellation`,viewBox:`0 0 280 ${a}`,role:`img`,"aria-label":`${e.length} inbound and ${t.length} outbound parser relationships for ${n.name}`,children:[r.map((e,t)=>(0,$.jsx)(`line`,{x1:`26`,y1:s(t,r.length),x2:`132`,y2:o,strokeDasharray:e.certain?void 0:`3 3`},`in-line-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`line`,{x1:`148`,y1:o,x2:`254`,y2:s(t,i.length),strokeDasharray:e.certain?void 0:`3 3`},`out-line-${e.node_id}`)),r.map((e,t)=>(0,$.jsx)(`circle`,{cx:`22`,cy:s(t,r.length),r:`4`},`in-dot-${e.node_id}`)),i.map((e,t)=>(0,$.jsx)(`circle`,{cx:`258`,cy:s(t,i.length),r:`4`},`out-dot-${e.node_id}`)),(0,$.jsx)(`circle`,{className:`mini-constellation__self`,cx:`140`,cy:o,r:`6`})]})}function HK({lens:e,language:t,mode:n}){return e?.length?(0,$.jsxs)(`section`,{className:`lens-study`,"aria-labelledby":`lens-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsxs)(`h2`,{id:`lens-heading`,children:[kG(t),` lens`]}),(0,$.jsxs)(`span`,{children:[e.length,` detected`]})]}),(0,$.jsx)(`div`,{className:`lens-notes`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`lens-note`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h3`,{children:e.title}),(0,$.jsx)(KK,{citation:e.citation,fallbackLine:e.line})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:e.note_voices[n]}),(0,$.jsx)(`code`,{children:e.snippet})]})]},`${e.concept}-${e.line}-${e.snippet}`))})]}):null}function UK({source:e}){return(0,$.jsxs)(`section`,{className:`source-study`,"aria-labelledby":`source-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,children:[(0,$.jsx)(`h2`,{id:`source-heading`,children:`Real source`}),(0,$.jsxs)(`span`,{children:[e.file,`:`,e.start_line,`–`,e.end_line]})]}),(0,$.jsx)(`ol`,{className:`source-code`,start:e.start_line,"aria-label":`Source excerpt from ${e.file}`,children:e.lines.map(e=>(0,$.jsx)(`li`,{id:`source-L${e.number}`,"data-line":e.number,children:(0,$.jsx)(`code`,{children:e.text||` `})},e.number))})]})}function WK({explanation:e,loading:t,error:n,llmStatus:r,mode:i,node:a,onSelectNode:o,onRetry:s}){return t?(0,$.jsx)(`p`,{className:`study-loading`,role:`status`,children:i===`easy`?`Asking your model to explain this in plain language…`:`Requesting a grounded narration for this structure…`}):n?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`The explanation request failed.`}),(0,$.jsx)(`p`,{children:n}),(0,$.jsx)(`p`,{children:`Every fact above and below this block came from the parser and is unaffected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]}):e?e.status===`no_key`?(0,$.jsx)(GK,{message:e.message,llmStatus:r,mode:i}):e.status===`error`?(0,$.jsxs)(`section`,{className:`study-notice`,role:`alert`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`The explanation was withheld.`}),(0,$.jsx)(`p`,{children:e.message}),(0,$.jsx)(`p`,{children:`Codemble will not display provider output that falls outside parser evidence.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:s,children:`Try again`})]}):e.status===`partial`?(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:`Narration stays off for partial source.`}),(0,$.jsx)(`p`,{children:e.message})]}):(0,$.jsxs)(`section`,{className:`grounded-explanation`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsxs)(`div`,{className:`study-section-heading`,role:`status`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:i===`easy`?`In plain language`:`Grounded explanation`}),(0,$.jsx)(`span`,{children:e.cached?`Local cache`:e.provider})]}),(0,$.jsxs)(`p`,{children:[e.summary.text,` `,(0,$.jsx)(KK,{citation:e.summary.citation,fallbackLine:a.lineno})]}),(0,$.jsx)(`h3`,{children:i===`easy`?`Line by line`:`Walkthrough`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.walkthrough.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`p`,{children:e.text}),(0,$.jsx)(KK,{citation:e.citation,fallbackLine:e.line})]},`${e.citation}-${e.text}`))}),e.relationships.length?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`h3`,{children:i===`easy`?`How it fits in`:`Parser relationships`}),(0,$.jsx)(`ul`,{className:`evidence-list`,children:e.relationships.map(e=>(0,$.jsxs)(`li`,{children:[(0,$.jsx)(`strong`,{children:e.certain?e.node_id:`Possible: ${e.node_id}`}),(0,$.jsx)(`p`,{children:e.text}),(0,$.jsxs)(`button`,{className:`source-citation source-citation--button`,type:`button`,onClick:()=>o(e.node_id),children:[`Study `,e.citation]})]},`${e.node_id}-${e.text}`))})]}):null]}):null}function GK({message:e,llmStatus:t,mode:n}){let r=t?.ollama??null;return(0,$.jsxs)(`section`,{className:`study-notice`,"aria-labelledby":`explanation-heading`,children:[(0,$.jsx)(`h2`,{id:`explanation-heading`,children:n===`easy`?`The plain-language write-up needs a model.`:`No narration provider is configured.`}),(0,$.jsx)(`p`,{children:e}),r?(0,$.jsx)(`p`,{children:r.running?`Ollama is already running on this machine. Set CODEMBLE_PROVIDER=ollama and CODEMBLE_OLLAMA_MODEL=${r.recommended}, then restart Codemble to narrate without sending code anywhere.`:`Want to stay fully local? Install Ollama, run "ollama pull ${r.recommended}" (or ${r.fallback} on a smaller machine), set CODEMBLE_PROVIDER=ollama, then restart Codemble.`}):null,(0,$.jsx)(`p`,{children:`Everything else on this panel is parser evidence and works without any model at all.`})]})}function KK({citation:e,fallbackLine:t}){return(0,$.jsx)(`a`,{className:`source-citation`,href:`#source-L${Number(e.split(`:`).at(-1))||t}`,children:e})}var qK=Object.freeze([]),JK=new Set;function YK(){let e=new WeakMap,t=new WeakMap,n=new WeakMap,r=new WeakMap,i=new WeakMap,a=new WeakMap,o=null,s=null,c=null,l=null;function u(e){let t=e.graph,n=t?d(t,e.languageFocus):null,r=n?p(n):null,i=e.level,a=r?.regionById.get(e.region?.id)??null,o=e.selectedNode;n&&(a?o&&(o=r.nodeById.get(o.id)??null,!o&&i===wG.STUDY&&(i=wG.SYSTEM)):(a=WG(n),o=null,i=wG.GALAXY));let s=e.studiedNodeIds;return{...e,focusedGraph:n,focusedMapData:f(e.mapData,e.languageFocus),entrypointOpen:!!t&&!e.entrypointDismissed,level:i,region:a,selectedNode:o,languageOptions:t?m(t):qK,projectName:t?g(t):`Loading local project`,chart:n?_(n,s):qK,focusedStudiedCount:n?v(n,s):0,hint:n?y(n,e.mode):null,revealedRegionIds:n?b(n,e.showAll,a?.id??null):JK,moduleIndex:n?h(n):qK}}function d(t,n){let r=e.get(t);r||(r=new Map,e.set(t,r));let i=n||`all`;return r.has(i)||r.set(i,TG(t,n)),r.get(i)}function f(e,n){if(!e)return e;let r=t.get(e);r||(r=new Map,t.set(e,r));let i=n||`all`;return r.has(i)||r.set(i,EG(e,n)),r.get(i)}function p(e){return n.has(e)||n.set(e,{nodeById:new Map(e.nodes.map(e=>[e.id,e])),regionById:new Map(e.regions.map(e=>[e.id,e]))}),n.get(e)}function m(e){return r.has(e)||r.set(e,DG(e)),r.get(e)}function h(e){return i.has(e)||i.set(e,LG(e)),i.get(e)}function g(e){return a.has(e)||a.set(e,e.project_root.split(`/`).filter(Boolean).at(-1)??e.project_root),a.get(e)}function _(e,t){return(!o||o.graph!==e||o.studiedNodeIds!==t)&&(o={graph:e,studiedNodeIds:t,value:OG(e,t)}),o.value}function v(e,t){return(!s||s.graph!==e||s.studiedNodeIds!==t)&&(s={graph:e,studiedNodeIds:t,value:e.nodes.filter(e=>t.has(e.id)).length}),s.value}function y(e,t){return(!c||c.graph!==e||c.mode!==t)&&(c={graph:e,mode:t,value:XK(e,t)}),c.value}function b(e,t,n){return(!l||l.graph!==e||l.showAll!==t||l.selectionId!==n)&&(l={graph:e,showAll:t,selectionId:n,value:PG(e,{showAll:t,selectionId:n})}),l.value}return Object.freeze({derive:u})}function XK(e,t){if(t!==`easy`)return null;let n=e.regions.filter(e=>!e.understood);if(!n.length)return null;let r=n.map(e=>({regionId:e.id,hops:typeof e.hops_from_home==`number`?e.hops_from_home:1/0})).sort((e,t)=>e.hops-t.hops||e.regionId.localeCompare(t.regionId))[0];return{...r,reason:r.hops===0?`Home is not lit yet.`:Number.isFinite(r.hops)?`${r.hops} ${r.hops===1?`route`:`routes`} from Home.`:`No import route reaches it from Home.`}}var ZK=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}}),QK=300,$K=400,eq=4e3,tq=8,nq=Object.freeze([Object.freeze({id:`discovering`,copy:`Finding your source files`}),Object.freeze({id:`parsing`,copy:`Reading each file`}),Object.freeze({id:`resolving`,copy:`Connecting imports and calls`}),Object.freeze({id:`checks`,copy:`Building graph-only checks`}),Object.freeze({id:`layout`,copy:`Placing your galaxy`})]);function rq({adapter:e,clock:t=ZK,onReady:n=async()=>{}}={}){if(!e)throw TypeError(`Project mapping requires a learner adapter.`);let r=new Set,i=iq({phase:`idle`,error:``,picker:null,progress:null,failure:null}),a=0,o=null,s=null,c=null,l=null;function u(){return i}function d(e){return r.add(e),()=>r.delete(e)}function f(e){i=iq({...i,...e});for(let e of r)e()}async function p(){a+=1;let t=a;b(),aq(o),o=new AbortController;let n=o;f({phase:`idle`,error:``,picker:null,progress:null,failure:null});try{let[r,o]=await Promise.all([e.loadRecents({signal:n.signal}),e.browsePicker(null,{signal:n.signal})]);if(t!==a||n.signal.aborted)return i;f({phase:`picking`,picker:{...o,recents:r.recents,error:``,scale:null,busy:!1}})}catch(e){!oq(e)&&t===a&&f({phase:`error`,error:cq(e)})}return i}async function m(t){if(i.phase!==`picking`||i.picker?.busy)return;aq(o),o=new AbortController;let n=o,r=a;f({failure:null});try{let s=await e.browsePicker(t,{signal:n.signal});o===n&&r===a&&!n.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...s,error:``}})}catch(e){o===n&&r===a&&!oq(e)&&i.phase===`picking`&&f({picker:{...i.picker,error:cq(e)}})}}async function h(t){if(i.phase!==`picking`||i.picker?.busy)return;a+=1;let r=a;aq(o),b(),o=new AbortController;let s=o;f({failure:null,picker:{...i.picker,busy:!0,error:``,scale:null}});try{let o=await e.selectProject(t,{signal:s.signal});if(r!==a||s.signal.aborted||i.phase!==`picking`)return o;if(o.state===`parsing`)return f({progress:{state:`parsing`,stage:`discovering`,detail:null,files_done:0,files_total:0,error:null,pollError:``,attempts:0,pollOutage:!1,path:t}}),_(0,r),o;if(o.state===`ready`)return y(),await n(),o;if(o.state===`scale`){let t=await e.browsePicker(o.root,{signal:s.signal});return r===a&&!s.signal.aborted&&i.phase===`picking`&&f({picker:{...i.picker,...t,busy:!1,scale:o}}),o}let c=o.detail??``;return f({picker:{...i.picker,busy:!1,error:c},failure:c?{path:t,detail:c}:null}),o}catch(e){if(r===a&&!oq(e)&&i.phase===`picking`){let n=cq(e);f({picker:{...i.picker,busy:!1,error:n},failure:{path:t,detail:n}})}return}}async function g(){aq(c),c=new AbortController;let t=c;try{await e.resetProject({signal:t.signal})}catch(e){if(oq(e))return!1;if(sq(e))throw e}return t.signal.aborted?!1:(a+=1,aq(o),o=null,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null}),!0)}function _(e,n){l!==null&&t.clearTimeout(l),l=t.setTimeout(async()=>{l=null,await v(n)},e)}async function v(t){if(!i.progress||t!==a)return;aq(s),s=new AbortController;let r=s,o=i.progress,c;try{c=await e.fetchParseProgress({signal:r.signal})}catch(e){if(s!==r||t!==a||oq(e)||!i.progress)return;let n=o.attempts+1;f({progress:{...o,pollError:cq(e),attempts:n,pollOutage:n>=tq}}),_(Math.min(eq,$K*2**(n-1)),t);return}if(!(s!==r||t!==a||!i.progress)){if(c.state===`ready`){y(),await n();return}if(c.state===`error`||c.state===`idle`){b();let e=c.error??``;f({progress:null,picker:{...i.picker,busy:!1,error:e},failure:e?{path:o.path,detail:e}:null});return}f({progress:{...o,...c,pollError:``,attempts:0,pollOutage:!1}}),_(QK,t)}}function y(){a+=1,b(),f({phase:`idle`,error:``,picker:null,progress:null,failure:null})}function b(){aq(s),s=null,l!==null&&(t.clearTimeout(l),l=null)}function x(){a+=1;for(let e of[o,s,c])aq(e);o=null,c=null,b(),r.clear()}return Object.freeze({browse:m,dispose:x,getSnapshot:u,reset:g,select:h,start:p,subscribe:d})}function iq(e){return Object.freeze(e)}function aq(e){e&&!e.signal.aborted&&e.abort()}function oq(e){return e?.name===`AbortError`}function sq(e){return Number.isInteger(e?.status)}function cq(e){return e instanceof Error?e.message:String(e)}var lq=Object.freeze({setTimeout(e,t){return globalThis.setTimeout(e,t)},clearTimeout(e){globalThis.clearTimeout(e)}});function uq({adapter:e=dq(),clock:t=lq}={}){let n=new Set,r=YK(),i=r.derive({status:`idle`,error:``,graph:null,level:wG.GALAXY,region:null,selectedNode:null,studyData:null,studyError:``,explanation:null,explanationLoading:!1,explanationError:``,showChart:!1,studiedNodeIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,picker:null,parseProgress:null,projectFailure:null,layer:`galaxy`,layerChosen:!1,mapTab:`architecture`,mapData:null,mapError:``,coachmarksSeen:mq(),llmStatus:null,hoverNodeId:null,showAll:_q(),finderOpen:!1,sidebarOpen:!1,legendOpen:!1,mode:`easy`,modeChosen:null}),a=0,o=0,s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,h=null;function g(){return i}function _(e){return n.add(e),()=>n.delete(e)}function v(e,{preserveChecks:t=!1}={}){let a=i,o=r.derive({...a,...e});if(o.level!==a.level||o.region?.id!==a.region?.id){let e={hoverNodeId:null};t||(yq(u),yq(d),u=null,d=null,e.showChecks=!1,e.checkData=null,e.checkError=``),o=r.derive({...o,...e})}i=Object.freeze(o);for(let e of n)e()}let y=rq({adapter:e,clock:t,async onReady(){a+=1;let e=a;return yq(s),s=new AbortController,S(s,e)}}),b=y.subscribe(()=>{let e=y.getSnapshot(),t={picker:e.picker,parseProgress:e.progress,projectFailure:e.failure};e.phase===`picking`&&(t.status=`picking`),e.phase===`error`&&(t.status=`error`,t.error=e.error),v(t)});async function x(){a+=1;let t=a;yq(s),s=new AbortController;let n=s;v({status:`loading`,error:``});let r;try{r=await e.loadPickerState({signal:n.signal})}catch(e){return!bq(e)&&t===a&&v({status:`error`,error:Cq(e)}),i}return t!==a||n.signal.aborted?i:r.state===`unpicked`?(await y.start(),i):S(n,t)}async function S(t,n){v({status:`loading`,error:``,picker:null});try{let r=await e.loadGraph({signal:t.signal});if(n!==a||t.signal.aborted)return i;v({status:`ready`,graph:r,region:WG(r),error:``,entrypointDismissed:!!r.selected_entrypoint})}catch(e){!bq(e)&&n===a&&v({status:`error`,error:Cq(e)})}return await C(t,n),i}async function C(t,n){let r=o,[s,c]=await Promise.allSettled([(async()=>e.loadMode({signal:t.signal}))(),(async()=>e.fetchLlmStatus({signal:t.signal}))()]);if(!(n!==a||t.signal.aborted)){if(r===o){let e=s.status===`fulfilled`?s.value:null;e?.mode===`easy`||e?.mode===`expert`?te(e.mode,e.chosen===!0):i.modeChosen===null&&v({modeChosen:!0})}c.status===`fulfilled`&&v({llmStatus:c.value})}}async function w(){let t=a;if(await e.clearProgress({}),t!==a)return i;a+=1;let n=a;return yq(s),s=new AbortController,S(s,n)}async function T(){return await y.reset()?(ie(),yq(f),f=null,yq(p),p=null,yq(m),m=null,v({graph:null,parseProgress:null,projectFailure:null,region:null,selectedNode:null,level:wG.GALAXY,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1,showChart:!1,studiedNodeIds:new Set,showChecks:!1,checkData:null,checkError:``,entrypointDismissed:!1,entrypointError:``,litRegionId:null,pendingDawnRegionId:null,languageFocus:`all`,llmStatus:null,picker:null,mapData:null,mapError:``}),x()):i}async function E(e){switch(e.type){case`ADVANCE`:return O(e.node);case`ADVANCE_REGION`:D(e.regionId);return;case`RETREAT`:k();return;case`SELECT_STUDY_NODE`:return A(e.nodeId);case`SET_LANGUAGE_FOCUS`:ee(e.language);return;case`SET_MODE`:return ne(e.mode);case`HOVER_NODE`:i.hoverNodeId!==(e.nodeId??null)&&v({hoverNodeId:e.nodeId??null});return;case`SHOW_CHART`:v({showChart:!0});return;case`HIDE_CHART`:v({showChart:!1});return;case`OPEN_CHECKS`:return M();case`CLOSE_CHECKS`:oe();return;case`SUBMIT_CHECK`:return se(e.checkId,e.selectedIds);case`CONSUME_DAWN`:pe(e.regionId);return;case`SELECT_ENTRYPOINT`:return ce(e.nodeId);case`DISMISS_ENTRYPOINT`:v({entrypointDismissed:!0});return;case`CHANGE_HOME`:ie(),v({entrypointDismissed:!1,entrypointError:``,level:wG.GALAXY,selectedNode:null,showChart:!1,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1});return;case`BROWSE_PICKER`:return y.browse(e.path);case`SELECT_PROJECT`:return y.select(e.path);case`RESET_PROJECT`:return T();case`CLEAR_PROGRESS`:return w();case`SET_LAYER`:return le(e.layer);case`SET_MAP_TAB`:v({mapTab:e.tab});return;case`DISMISS_COACHMARKS`:hq(),v({coachmarksSeen:!0});return;case`SET_LEVEL_GALAXY`:ie(),v({level:wG.GALAXY,selectedNode:null});return;case`TOGGLE_SHOW_ALL`:vq(!i.showAll),v({showAll:!i.showAll});return;case`SET_FINDER_OPEN`:v({finderOpen:e.open});return;case`TOGGLE_SIDEBAR`:v({sidebarOpen:!i.sidebarOpen});return;case`TOGGLE_LEGEND`:v({legendOpen:!i.legendOpen});return;case`GO_TO_REGION`:return v({finderOpen:!1}),D(e.regionId);default:throw Error(`Unknown learner-session event: ${e.type}`)}}function D(e){let t=i.graph?.regions.find(t=>t.id===e);t&&(ie(),v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:t,selectedNode:null,level:wG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}async function O(e){if(!(!i.focusedGraph||!e)){if(i.level===wG.GALAXY){let t=i.focusedGraph.regions.find(t=>t.id===e.id)??e;ie(),v({region:t,selectedNode:null,level:wG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``});return}if(i.level===wG.SYSTEM){let t=i.focusedGraph.nodes.find(t=>t.id===e.id)??e;return v({selectedNode:t,level:wG.STUDY}),re(t.id)}}}function k(){i.level===wG.STUDY?(ie(),v({selectedNode:null,level:wG.SYSTEM,studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1})):i.level===wG.SYSTEM&&v({level:wG.GALAXY})}async function A(e){let t=i.graph?.nodes.find(t=>t.id===e);if(!t)return;let n=i.graph.regions.find(e=>e.id===t.region);return v({languageFocus:i.languageFocus!==`all`&&t.language!==i.languageFocus?t.language:i.languageFocus,region:n??i.region,selectedNode:t,level:wG.STUDY}),re(t.id)}function ee(e){let t=i.selectedNode?.id;v({languageFocus:e}),t&&i.selectedNode?.id!==t&&(ie(),v({studyData:null,studyError:``,explanation:null,explanationError:``,explanationLoading:!1}))}function te(e,t){let n=i.layerChosen?i.layer:e===`easy`?`map`:`galaxy`;v({mode:e,layer:n,modeChosen:t}),n===`map`&&ue()}async function ne(t){if(t!==`easy`&&t!==`expert`)return;let n=i.mode,r=i.modeChosen;if(t===n&&i.modeChosen)return;o+=1,yq(m),m=new AbortController;let s=m,c=a;te(t,!0);try{await e.saveMode(t,{signal:s.signal})}catch(e){m===s&&c===a&&!bq(e)&&te(n,r);return}if(!(c!==a||s.signal.aborted)&&i.level===wG.STUDY&&i.selectedNode)return j(i.selectedNode.id)}async function re(t){ie(),c=new AbortController;let n=c;v({studyData:null,studyError:``}),j(t);try{let r=await e.loadStudy(t,{signal:n.signal});if(n.signal.aborted||i.level!==wG.STUDY||i.selectedNode?.id!==t)return;v({studyData:r,studiedNodeIds:new Set(i.studiedNodeIds).add(r.node.id)})}catch(e){c===n&&!n.signal.aborted&&!bq(e)&&i.selectedNode?.id===t&&v({studyError:Sq(e)})}}function ie(){yq(c),c=null,yq(l),l=null}async function j(t){yq(l),l=new AbortController;let n=l;v({explanation:null,explanationError:``,explanationLoading:!0});try{let r=await e.loadExplanation(t,i.mode,{signal:n.signal});if(n.signal.aborted||i.level!==wG.STUDY||i.selectedNode?.id!==t)return;v({explanation:r,explanationLoading:!1})}catch(e){l===n&&!n.signal.aborted&&!bq(e)&&i.selectedNode?.id===t&&v({explanationError:Sq(e),explanationLoading:!1})}}async function M(){if(!i.region)return;let e=i.region.id;return v({showChecks:!0,checkData:null,checkError:``}),ae(e)}async function ae(t){yq(u),u=new AbortController;let n=u;try{let r=await e.loadChecks(t,{signal:n.signal});return!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkData:r,checkError:``},{preserveChecks:!0}),r}catch(e){u===n&&!bq(e)&&!n.signal.aborted&&i.showChecks&&i.region?.id===t&&v({checkError:Sq(e)},{preserveChecks:!0});return}}function oe(){yq(u),u=null,v({showChecks:!1,checkData:null,checkError:``})}async function se(t,n){if(!i.region)return;let r=i.region.id;yq(d),d=new AbortController;let a=d,o=await e.submitCheck(r,t,n,{signal:a.signal});if(a.signal.aborted||i.region?.id!==r)return o;if(o.correct&&await ae(r),o.region_understood){let t=await e.loadGraph({signal:a.signal});!a.signal.aborted&&i.region?.id===r&&(yq(p),p=null,v({graph:t,region:t.regions.find(e=>e.id===r),mapData:null,mapError:``},{preserveChecks:!0}),fe(r),i.layer===`map`&&await ue())}return o}async function ce(t){let n=a;yq(f),f=new AbortController;let r=f;v({entrypointError:``});try{let o=await e.selectEntrypoint(t,{signal:r.signal});return n!==a||r.signal.aborted?i:(yq(p),p=null,v({graph:o,region:WG(o),entrypointError:``,entrypointDismissed:!0,mapData:null,mapError:``}),i.layer===`map`&&await ue(),o)}catch(e){f===r&&n===a&&!r.signal.aborted&&!bq(e)&&v({entrypointError:Sq(e)});return}}async function le(e){if(v({layer:e,layerChosen:!0}),e===`map`)return ue()}function ue(){if(!i.mapData)return p&&!p.signal.aborted&&!i.mapError?void 0:de()}async function de(){let t=a;yq(p),p=new AbortController;let n=p;v({mapError:``});try{let r=await e.fetchMap({signal:n.signal});return t===a&&!n.signal.aborted&&v({mapData:r,mapError:``}),r}catch(e){p===n&&t===a&&!n.signal.aborted&&!bq(e)&&v({mapError:Sq(e),mapData:null});return}}function fe(e){h!==null&&t.clearTimeout(h),v({litRegionId:e,pendingDawnRegionId:e}),h=t.setTimeout(()=>{h=null,i.litRegionId===e&&v({litRegionId:null})},520)}function pe(e){i.pendingDawnRegionId===e&&v({pendingDawnRegionId:null})}function me(){a+=1;for(let e of[s,c,l,u,d,f,p,m])yq(e);s=null,c=null,l=null,u=null,d=null,f=null,p=null,m=null,b(),y.dispose(),h!==null&&(t.clearTimeout(h),h=null)}return Object.freeze({dispatch:E,dispose:me,getSnapshot:g,start:x,subscribe:_})}function dq(e=globalThis.fetch){if(typeof e!=`function`)throw TypeError(`Learner-session HTTP adapter requires fetch.`);async function t(t,n,r={}){let i=await e(t,r);if(!i.ok){let e=(await i.json().catch(()=>null))?.detail,t=Error(typeof e==`string`&&e?e:`${n} returned ${i.status}.`);throw t.status=i.status,t}return i.json()}return Object.freeze({loadGraph(e={}){return t(`/api/graph`,`Graph request`,e)},fetchMap(e={}){return t(`/api/map`,`Map request`,e)},loadStudy(e,n={}){return t(`/api/node/${encodeURIComponent(e)}/study`,`Study request`,n)},loadExplanation(e,n,r={}){return t(`/api/node/${encodeURIComponent(e)}/explanation?mode=${encodeURIComponent(n)}`,`Explanation request`,r)},loadChecks(e,n={}){return t(`/api/regions/${encodeURIComponent(e)}/checks`,`Checks request`,n)},submitCheck(e,n,r,i={}){return t(`/api/regions/${encodeURIComponent(e)}/checks/${encodeURIComponent(n)}`,`Check submission`,{...i,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selected_ids:r})})},selectEntrypoint(e,n={}){return t(`/api/entrypoint`,`Home selection`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({node_id:e})})},loadMode(e={}){return t(`/api/mode`,`Mode request`,e)},saveMode(e,n={}){return t(`/api/mode`,`Mode update`,{...n,method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({mode:e})})},fetchLlmStatus(e={}){return t(`/api/llm/status`,`Model status`,e)},resetProject(e={}){return t(`/api/picker/reset`,`Project reset`,{...e,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({confirmed:!0})})},loadPickerState(e={}){return t(`/api/picker/state`,`Picker state`,e)},browsePicker(e,n={}){return t(`/api/picker/browse${e?`?path=${encodeURIComponent(e)}`:``}`,`Folder listing`,n)},loadRecents(e={}){return t(`/api/picker/recents`,`Recent projects`,e)},fetchParseProgress(e={}){return t(`/api/picker/progress`,`Parse progress`,e)},clearProgress(e={}){return t(`/api/progress`,`Progress reset`,{...e,method:`DELETE`})},async selectProject(t,n={}){let r=await e(`/api/picker/select`,{...n,method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t})}),i=await r.json().catch(()=>null);if(r.ok)return{state:r.status===202?`parsing`:`ready`};let a=i?.detail;return a&&typeof a==`object`&&a.reason===`scale`?{state:`scale`,...a}:{state:`error`,detail:typeof a==`string`?a:`Project selection returned ${r.status}.`}}})}var fq=`codemble.coachmarks.seen`;function pq(){if(typeof document>`u`)return null;try{return globalThis.localStorage??null}catch{return null}}function mq(){try{return pq()?.getItem(fq)===`1`}catch{return!1}}function hq(){try{pq()?.setItem(fq,`1`)}catch{}}var gq=`codemble.galaxy.showAll`;function _q(){try{return pq()?.getItem(gq)===`1`}catch{return!1}}function vq(e){try{let t=pq();e?t?.setItem(gq,`1`):t?.removeItem(gq)}catch{}}function yq(e){e&&!e.signal.aborted&&e.abort()}function bq(e){return e instanceof Error&&e.name===`AbortError`}function xq(e){return Number.isInteger(e?.status)}function Sq(e){return e instanceof Error?e.message:String(e)}function Cq(e){return xq(e)?Sq(e):`Codemble's local server is not responding, so nothing can be loaded from it. It may have stopped — start it again by running codemble in your terminal. (${Sq(e)})`}function wq(){let e=(0,_.useRef)(null),[t,n]=(0,_.useState)(!1),r=(0,_.useMemo)(()=>uq({adapter:dq()}),[]),i=(0,_.useSyncExternalStore)(r.subscribe,r.getSnapshot,r.getSnapshot);(0,_.useEffect)(()=>(r.start(),()=>r.dispose()),[r]),(0,_.useEffect)(()=>{function e(e){(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),r.dispatch({type:`SET_FINDER_OPEN`,open:!0}))}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[r]);let{chart:a,checkData:o,checkError:s,coachmarksSeen:c,entrypointError:l,entrypointOpen:u,error:d,explanation:f,explanationError:p,explanationLoading:m,finderOpen:h,focusedGraph:g,focusedMapData:v,focusedStudiedCount:y,graph:b,hint:x,hoverNodeId:S,languageFocus:C,languageOptions:w,layer:T,legendOpen:E,level:D,litRegionId:O,llmStatus:k,mapError:A,mapTab:ee,mode:te,modeChosen:ne,moduleIndex:re,parseProgress:ie,pendingDawnRegionId:j,picker:M,projectName:ae,projectFailure:oe,region:se,revealedRegionIds:ce,selectedNode:le,showAll:ue,showChart:de,showChecks:fe,sidebarOpen:pe,status:me,studyData:he,studyError:ge}=i;if(d)return(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The graph did not load.`}),(0,$.jsx)(`p`,{children:d}),(0,$.jsx)(`p`,{children:`Your progress is stored on this machine and is not affected.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>r.start(),children:`Try again`})]});if(ie)return(0,$.jsx)(Dq,{progress:ie,onCancel:()=>r.dispatch({type:`RESET_PROJECT`})});if(me===`picking`&&M)return(0,$.jsx)(Oq,{picker:M,failure:oe,onBrowse:e=>r.dispatch({type:`BROWSE_PICKER`,path:e}),onSelect:e=>r.dispatch({type:`SELECT_PROJECT`,path:e})});if(!b||!g||!se)return(0,$.jsx)(`main`,{className:`load-state`,"aria-busy":`true`,children:(0,$.jsx)(`p`,{children:`Mapping parser evidence…`})});let _e=D===wG.SYSTEM?(0,$.jsxs)(`section`,{className:`orientation-copy orientation-copy--system${T===`map`?` orientation-copy--inline`:``}`,children:[(0,$.jsx)(`p`,{children:g.nodes.some(e=>e.region===se.id&&e.partial)?`${se.node_count} source ${se.node_count===1?`file remains`:`files remain`} visible · ${se.loc} lines. The module is unchartable beyond raw source because it has a syntax error.`:T===`map`?`The ${se.node_count} parser-proven ${se.node_count===1?`structure`:`structures`} inside this module ${se.node_count===1?`is`:`are`} drawn as planets in the Galaxy layer. This map shows how modules connect, not what is inside them.`:`${se.node_count} parser-proven structures · ${se.loc} lines in this system.`}),(0,$.jsx)(`button`,{className:`check-launch`,type:`button`,onClick:()=>r.dispatch({type:`OPEN_CHECKS`}),children:g.nodes.some(e=>e.region===se.id&&e.partial)?`Check availability`:se.understood?`Review understanding`:`Prove understanding`})]}):null;return(0,$.jsxs)(`main`,{className:`app-shell`,"data-level":de?`chart`:D.toLowerCase(),"data-mode":te,children:[(0,$.jsxs)(`header`,{className:`instrument-rail`,children:[(0,$.jsxs)(`div`,{className:`brand-lockup`,children:[(0,$.jsx)(`span`,{className:`brand-mark`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`strong`,{children:`Codemble`}),(0,$.jsx)(`span`,{children:ae})]})]}),(0,$.jsx)(`nav`,{className:`location`,"aria-label":`Breadcrumb`,"aria-live":`polite`,children:de?(0,$.jsx)(`span`,{"aria-current":`page`,children:`Star chart`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`button`,{type:`button`,disabled:D===wG.GALAXY,"aria-current":D===wG.GALAXY?`page`:void 0,onClick:()=>r.dispatch({type:`SET_LEVEL_GALAXY`}),children:`Galaxy`}),D===wG.GALAXY?(0,$.jsxs)(`small`,{children:[` · Home `,b.selected_entrypoint?WG(b)?.id??`unresolved`:`unselected`]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`button`,{type:`button`,disabled:D===wG.SYSTEM,"aria-current":D===wG.SYSTEM?`page`:void 0,onClick:()=>r.dispatch({type:`RETREAT`}),children:se.id})]}),D===wG.STUDY&&le?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,$.jsx)(`span`,{"aria-current":`page`,children:le.name})]}):null,C===`all`?null:(0,$.jsxs)(`small`,{children:[` · `,AG(C),` focus`]})]})}),(0,$.jsxs)(`div`,{className:`rail-overflow`,"data-open":t||void 0,onKeyDown:r=>{r.key===`Escape`&&t&&(r.preventDefault(),n(!1),e.current?.focus())},children:[(0,$.jsx)(`button`,{ref:e,className:`mobile-menu-trigger`,type:`button`,"aria-expanded":t,"aria-controls":`rail-overflow-panel`,onClick:()=>n(e=>!e),children:`Menu`}),(0,$.jsxs)(`div`,{className:`rail-overflow__panel`,id:`rail-overflow-panel`,onClickCapture:e=>{e.target.closest(`button`)&&!e.target.closest(`.switch-project`)&&n(!1)},children:[(0,$.jsxs)(`div`,{className:`rail-actions`,children:[(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,"aria-pressed":pe,onClick:()=>r.dispatch({type:`TOGGLE_SIDEBAR`}),children:`Modules`}),(0,$.jsxs)(`button`,{className:`rail-action`,type:`button`,onClick:()=>r.dispatch({type:`SET_FINDER_OPEN`,open:!0}),children:[`Find `,(0,$.jsx)(`kbd`,{children:`⌘K`})]}),de?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>r.dispatch({type:`HIDE_CHART`}),children:`Return to galaxy`}):D===wG.GALAXY?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>r.dispatch({type:`SHOW_CHART`}),children:`Star chart`}):(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>r.dispatch({type:`RETREAT`}),children:D===wG.STUDY?`Return to system`:`Return to galaxy`}),b.entrypoint_candidates.length?(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,onClick:()=>r.dispatch({type:`CHANGE_HOME`}),children:`Change Home`}):null,(0,$.jsx)(Iq,{onConfirm:()=>r.dispatch({type:`RESET_PROJECT`})})]}),(0,$.jsxs)(`div`,{className:`rail-controls`,children:[T===`galaxy`?(0,$.jsx)(`button`,{className:`rail-action rail-action--toggle`,type:`button`,"aria-pressed":ue,title:`Draw every module at once, including the ones no route from Home reaches`,onClick:()=>r.dispatch({type:`TOGGLE_SHOW_ALL`}),children:`Show all`}):null,(0,$.jsx)(Pq,{layer:T,mode:te,onChange:e=>r.dispatch({type:`SET_LAYER`,layer:e})}),(0,$.jsx)(Fq,{options:w,value:C,onChange:e=>r.dispatch({type:`SET_LANGUAGE_FOCUS`,language:e})}),(0,$.jsx)(NK,{mode:te,modeChosen:ne,onChoose:e=>r.dispatch({type:`SET_MODE`,mode:e})})]})]})]})]}),de?(0,$.jsxs)(`section`,{className:`chart-stage`,"aria-label":`Language concept progress`,children:[pe?(0,$.jsx)(Nq,{index:re,currentRegionId:null,onGo:e=>r.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:()=>r.dispatch({type:`TOGGLE_SIDEBAR`})}):null,(0,$.jsx)(zq,{chart:a,studiedCount:y,projectName:ae,onClearProgress:()=>r.dispatch({type:`CLEAR_PROGRESS`})})]}):(0,$.jsxs)(`section`,{className:`map-stage`,"aria-label":`Parser-proven project map`,children:[pe?(0,$.jsx)(Nq,{index:re,currentRegionId:D===wG.GALAXY?null:se?.id,onGo:e=>r.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:()=>r.dispatch({type:`TOGGLE_SIDEBAR`})}):null,T===`map`?(0,$.jsx)(OK,{data:v,mapTab:ee,mode:te,selectedRegionId:D===wG.GALAXY?void 0:se?.id,hasEntrypointCandidates:b.entrypoint_candidates.length>0,error:A,onSelectTab:e=>r.dispatch({type:`SET_MAP_TAB`,tab:e}),onSelectRegion:e=>r.dispatch({type:`ADVANCE_REGION`,regionId:e}),onSelectNode:e=>r.dispatch({type:`SELECT_STUDY_NODE`,nodeId:e}),onRetry:()=>r.dispatch({type:`SET_LAYER`,layer:`map`}),children:_e}):(0,$.jsx)(aK,{graph:g,level:D,region:se,selectedNode:le,hoverNodeId:S,pendingDawnRegionId:j,revealedRegionIds:ce,mode:te,onHoverNode:e=>r.dispatch({type:`HOVER_NODE`,nodeId:e}),onAdvance:e=>r.dispatch({type:`ADVANCE`,node:e}),onRetreat:()=>r.dispatch({type:`RETREAT`}),onDawnConsumed:e=>r.dispatch({type:`CONSUME_DAWN`,regionId:e})}),(0,$.jsx)(`button`,{className:`legend-toggle`,type:`button`,"aria-expanded":E,onClick:()=>r.dispatch({type:`TOGGLE_LEGEND`}),children:`Key`}),(0,$.jsxs)(`aside`,{className:`map-legend`,hidden:!E,"aria-label":T===`map`?`Map legend`:`Galaxy legend`,children:[T===`galaxy`?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-size`}),`Size · `,te===`easy`?`how much code`:`lines of code`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-brightness`}),`Brighter · `,te===`easy`?`used in more places`:`more distinct callers`]})]}):null,(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--dim`}),`Dim · `,te===`easy`?`not proven yet`:`not understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--lit`}),`Amber · `,te===`easy`?`you proved you understand it`:`understood`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-dot legend-dot--partial`}),te===`easy`?`Could not be read`:`Unchartable · syntax error`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-route`}),te===`easy`?`Certain connection`:`Parser edge · certain`]}),(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:T===`map`?`legend-route legend-route--possible legend-route--dashed`:`legend-route legend-route--possible`}),te===`easy`?`Possible connection`:`Possible relationship`]}),T===`galaxy`&&D===wG.GALAXY||T===`map`&&ee===`architecture`?w.filter(e=>e.id!==`all`).map(e=>(0,$.jsxs)(`span`,{children:[(0,$.jsx)(`i`,{className:`legend-tint legend-tint--${e.id}`}),` `,e.label]},e.id)):null]}),T===`galaxy`&&D===wG.GALAXY?(0,$.jsxs)(`p`,{className:`orientation-bar`,children:[(0,$.jsxs)(`span`,{children:[g.regions.length,` `,C===`all`?g.regions.length===1?`system`:`systems`:`${AG(C)} ${g.regions.length===1?`system`:`systems`}`]}),(0,$.jsx)(`span`,{className:`orientation-bar__charted`,children:ue?`all charted`:`${ce.size} charted`}),g.partial_files.length?(0,$.jsxs)(`span`,{className:`partial-summary`,children:[g.partial_files.length,` unchartable · syntax error`]}):null]}):null,T===`galaxy`?_e:null,D===wG.SYSTEM&&fe?(0,$.jsx)(Rq,{suite:o,error:s,mode:te,onClose:()=>r.dispatch({type:`CLOSE_CHECKS`}),onSubmit:(e,t)=>r.dispatch({type:`SUBMIT_CHECK`,checkId:e,selectedIds:t})}):null,u&&D===wG.GALAXY?(0,$.jsx)(Lq,{candidates:b.entrypoint_candidates,nodes:b.nodes,selectedEntrypoint:b.selected_entrypoint,error:l,onSelect:e=>r.dispatch({type:`SELECT_ENTRYPOINT`,nodeId:e}),onContinue:()=>r.dispatch({type:`DISMISS_ENTRYPOINT`})}):null,O?(0,$.jsxs)(`output`,{className:`illumination-pulse`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),(0,$.jsxs)(`strong`,{children:[O,` understood`]})]}):null,D===wG.STUDY&&le?(0,$.jsx)(PK,{node:le,study:he,error:ge,mode:te,explanation:f,explanationLoading:m,explanationError:p,llmStatus:k,onSelectNode:e=>r.dispatch({type:`SELECT_STUDY_NODE`,nodeId:e}),onRetryNarration:()=>r.dispatch({type:`SELECT_STUDY_NODE`,nodeId:le.id})}):null,ne===!0&&!u&&!c?(0,$.jsx)(pK,{layer:T,onDismiss:()=>r.dispatch({type:`DISMISS_COACHMARKS`})}):null]}),h?(0,$.jsx)(Mq,{index:re,onGo:e=>r.dispatch({type:`GO_TO_REGION`,regionId:e}),onClose:()=>r.dispatch({type:`SET_FINDER_OPEN`,open:!1})}):null,de?null:(0,$.jsx)(uK,{hint:x,onStudy:e=>r.dispatch({type:`ADVANCE_REGION`,regionId:e})}),(0,$.jsxs)(`footer`,{className:`status-line`,children:[(0,$.jsx)(`span`,{children:de?`${a.length} concepts detected`:C===`all`?`${b.nodes.length} nodes · ${b.edges.length} edges`:`${g.nodes.length}/${b.nodes.length} nodes · ${g.edges.length} focused edges`}),(0,$.jsx)(`span`,{children:de?`${y} focused structures studied this session`:T===`map`?`Click a box or row to study · Switch tabs to change view`:`Drag to orbit · Scroll to zoom · Click to move closer · Escape to move back`}),(0,$.jsx)(`span`,{children:`Local only`})]})]})}var Tq=Object.fromEntries(nq.map(({id:e,copy:t})=>[e,t])),Eq=nq.map(({id:e})=>e);function Dq({progress:e,onCancel:t}){let{stage:n,detail:r,files_done:i,files_total:a,pollError:o,pollOutage:s,attempts:c,path:l}=e,[u,d]=(0,_.useState)(!1),[f,p]=(0,_.useState)(``),m=(0,_.useRef)(null),h=Eq.indexOf(n);(0,_.useEffect)(()=>{m.current?.focus()},[]);async function g(){d(!0),p(``);try{await t()}catch(e){p(e.message),d(!1)}}return(0,$.jsxs)(`main`,{className:`loading-screen`,children:[(0,$.jsxs)(`header`,{className:`loading-header`,children:[(0,$.jsx)(`p`,{className:`picker-wordmark`,children:`Codemble`}),(0,$.jsxs)(`h1`,{ref:m,tabIndex:-1,children:[`Mapping `,(0,$.jsx)(`span`,{className:`loading-path`,children:l})]}),(0,$.jsx)(`p`,{className:`loading-subtitle`,children:`Parsing runs on your machine. Nothing is sent anywhere.`})]}),(0,$.jsx)(`ol`,{className:`loading-stages`,"aria-label":`Parse stages`,children:Eq.map((e,t)=>{let n=t(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:u,onClick:()=>r(e.project_root),children:[(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.project_root}),(0,$.jsxs)(`span`,{className:`picker-recent-lit`,children:[e.understood_count,` `,e.understood_count===1?`system`:`systems`,` lit last visit`]})]})},e.project_root))})]}):null,l?(0,$.jsx)(kq,{scale:l,busy:u,onBrowse:n}):null,t?(0,$.jsx)(jq,{failure:t,busy:u,onSelect:r}):c?(0,$.jsx)(`p`,{className:`picker-error`,role:`alert`,children:c}):null,(0,$.jsxs)(`section`,{className:`picker-browser`,"aria-labelledby":`picker-browser-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-browser-heading`,children:`Browse folders`}),(0,$.jsx)(`p`,{className:`picker-path`,children:i}),(0,$.jsxs)(`ul`,{children:[a?(0,$.jsx)(`li`,{children:(0,$.jsx)(`button`,{type:`button`,disabled:u,onClick:()=>n(a),children:`↑ Up`})}):null,o.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:u,onClick:()=>n(e.path),children:[e.name,`/`]})},e.path))]}),(0,$.jsx)(`button`,{className:`picker-select`,type:`button`,disabled:u,onClick:()=>r(i),children:u?`Mapping…`:`Map this folder`})]})]})}function kq({scale:e,busy:t,onBrowse:n}){let r=e.suggestions.filter(e=>e.path!==`.`);return(0,$.jsxs)(`section`,{className:`picker-scale`,role:`alert`,"aria-labelledby":`picker-scale-heading`,children:[(0,$.jsx)(`h2`,{id:`picker-scale-heading`,children:`That folder is too big to map at once.`}),(0,$.jsxs)(`p`,{children:[`It has `,e.file_count,` supported source files; Codemble maps up to`,` `,e.scale_cap,`. Choose a smaller scope — busiest first.`]}),r.length?(0,$.jsx)(`ul`,{className:`picker-scale-scopes`,children:r.map(r=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,disabled:t,onClick:()=>n(`${e.root}/${r.path}`),children:[(0,$.jsxs)(`span`,{children:[r.path,`/`]}),(0,$.jsxs)(`small`,{children:[r.file_count,` files`]})]})},r.path))}):null,(0,$.jsx)(Aq,{busy:t,onBrowse:n})]})}function Aq({busy:e,onBrowse:t}){let[n,r]=(0,_.useState)(``);return(0,$.jsxs)(`form`,{className:`picker-path-entry`,onSubmit:e=>{e.preventDefault();let r=n.trim();r&&t(r)},children:[(0,$.jsx)(`label`,{htmlFor:`picker-path-input`,children:`Or type a folder path`}),(0,$.jsx)(`input`,{id:`picker-path-input`,type:`text`,value:n,disabled:e,placeholder:`/Users/you/project/src`,onChange:e=>r(e.target.value)}),(0,$.jsx)(`button`,{type:`submit`,disabled:e||!n.trim(),children:`Go`})]})}function jq({failure:e,busy:t,onSelect:n}){return(0,$.jsxs)(`section`,{className:`picker-failure`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`Codemble could not map that folder.`}),(0,$.jsx)(`p`,{children:`Nothing on disk changed, and no project's saved progress was touched. Try it again, or choose a different folder below.`}),(0,$.jsxs)(`p`,{className:`picker-failure__detail`,children:[(0,$.jsx)(`span`,{children:`What the parser reported`}),(0,$.jsx)(`code`,{children:e.detail})]}),(0,$.jsxs)(`button`,{className:`picker-select`,type:`button`,disabled:t,onClick:()=>n(e.path),children:[`Try `,(0,$.jsx)(`span`,{className:`picker-recent-path`,children:e.path}),` again`]})]})}function Mq({index:e,onGo:t,onClose:n}){let[r,i]=(0,_.useState)(``),[a,o]=(0,_.useState)(0),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useMemo)(()=>{let t=r.trim().toLowerCase();return(t?e.filter(e=>e.label.toLowerCase().includes(t)||e.file.toLowerCase().includes(t)):e).slice(0,60)},[e,r]);(0,_.useLayoutEffect)(()=>{let e=s.current;e&&!e.open&&e.showModal(),c.current?.focus()},[]),(0,_.useEffect)(()=>o(0),[r]);let u=l[Math.min(a,l.length-1)]??null;function d(e){e.key===`ArrowDown`?(e.preventDefault(),o(e=>Math.min(e+1,l.length-1))):e.key===`ArrowUp`?(e.preventDefault(),o(e=>Math.max(e-1,0))):e.key===`Enter`&&u&&(e.preventDefault(),t(u.id))}return(0,$.jsxs)(`dialog`,{ref:s,className:`module-finder`,"aria-label":`Find a module`,onCancel:e=>{e.preventDefault(),n()},onClose:n,children:[(0,$.jsx)(`input`,{ref:c,type:`search`,value:r,placeholder:`Find a module…`,"aria-label":`Find a module by name or path`,onChange:e=>i(e.target.value),onKeyDown:d}),(0,$.jsx)(`ul`,{role:`listbox`,"aria-label":`Matching modules`,children:l.map((e,n)=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":n===a,"data-active":n===a||void 0,onMouseEnter:()=>o(n),onClick:()=>t(e.id),children:[(0,$.jsx)(`strong`,{children:e.label}),(0,$.jsx)(`small`,{children:e.file}),e.home?(0,$.jsx)(`em`,{children:`Home`}):e.understood?(0,$.jsx)(`em`,{children:`lit`}):null]})},e.id))}),l.length?null:(0,$.jsx)(`p`,{className:`module-finder__empty`,children:`No module matches that.`})]})}function Nq({index:e,currentRegionId:t,onGo:n,onClose:r}){let i=(0,_.useMemo)(()=>zG(e),[e]);return(0,$.jsxs)(`aside`,{className:`index-sidebar`,"aria-label":`Project index`,children:[(0,$.jsxs)(`header`,{children:[(0,$.jsx)(`h2`,{children:`Modules`}),(0,$.jsx)(`button`,{type:`button`,onClick:r,"aria-label":`Close the project index`,children:`×`})]}),(0,$.jsx)(`div`,{className:`index-sidebar__scroll`,children:i.map(e=>(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h3`,{title:e.name,children:e.name}),(0,$.jsx)(`ul`,{children:e.members.map(e=>(0,$.jsx)(`li`,{children:(0,$.jsxs)(`button`,{type:`button`,"aria-current":e.id===t?`true`:void 0,"data-lit":e.understood||void 0,title:e.file,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.display??e.label}),e.home?(0,$.jsx)(`em`,{children:`Home`}):null]})},e.id))})]},e.community))})]})}function Pq({layer:e,mode:t,onChange:n}){return(0,$.jsx)(`nav`,{className:`layer-switcher`,"aria-label":`View layer`,children:[{id:`galaxy`,label:`Galaxy`},{id:`map`,label:t===`easy`?`Diagram`:`Map`}].map(t=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":e===t.id,onClick:()=>n(t.id),children:t.label},t.id))})}function Fq({options:e,value:t,onChange:n}){return e.length<=2?null:(0,$.jsxs)(`nav`,{className:`language-focus`,"aria-label":`Language focus`,children:[(0,$.jsx)(`span`,{className:`language-focus__label`,children:`Focus`}),(0,$.jsx)(`div`,{children:e.map(e=>(0,$.jsxs)(`button`,{type:`button`,"aria-label":`Focus ${e.label}: ${e.count} ${e.count===1?`system`:`systems`}`,"aria-pressed":t===e.id,title:e.label,onClick:()=>n(e.id),children:[(0,$.jsx)(`span`,{children:e.shortLabel}),(0,$.jsx)(`small`,{children:e.count})]},e.id))})]})}function Iq({onConfirm:e}){let[t,n]=(0,_.useState)(!1),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(``),s=(0,_.useRef)(null),c=(0,_.useRef)(null),l=(0,_.useRef)(!1);(0,_.useEffect)(()=>{t?c.current?.focus():l.current&&s.current?.focus(),l.current=t},[t]);function u(){n(!1),o(``)}async function d(){i(!0),o(``);try{await e()}catch(e){o(e.message),i(!1)}}return t?(0,$.jsxs)(`div`,{className:`switch-project`,role:`group`,"aria-label":`Switch project`,tabIndex:-1,ref:c,onKeyDown:e=>{e.key===`Escape`&&!r&&u()},children:[(0,$.jsx)(`p`,{children:`Progress is saved per project, so this galaxy comes back lit.`}),a?(0,$.jsx)(`p`,{className:`switch-project__error`,role:`alert`,children:a}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:d,children:r?`Releasing…`:`Switch`}),(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,disabled:r,onClick:u,children:`Cancel`})]})]}):(0,$.jsx)(`button`,{className:`rail-action`,type:`button`,ref:s,onClick:()=>n(!0),children:`Switch project`})}function Lq({candidates:e,nodes:t,selectedEntrypoint:n,error:r,onSelect:i,onContinue:a}){let o=new Map(t.map(e=>[e.id,e]));return(0,$.jsxs)(`aside`,{className:`entrypoint-picker`,"aria-labelledby":`entrypoint-heading`,children:[(0,$.jsx)(`p`,{children:`Home calibration`}),(0,$.jsx)(`h1`,{id:`entrypoint-heading`,children:e.length?`Where does your project start?`:`No clear entrypoint found.`}),(0,$.jsx)(`p`,{children:e.length?`The parser found ranked candidates but cannot choose one honestly. Select the structure you run.`:`No file here declares a startup structure the parser recognises, and Codemble will not guess one. Explore the map without Home — every system, check, explanation, and lens note still works.`}),e.length?(0,$.jsx)(`div`,{className:`entrypoint-candidates`,children:e.map(e=>{let t=o.get(e);return(0,$.jsxs)(`button`,{type:`button`,onClick:()=>i(e),children:[(0,$.jsx)(`span`,{children:e}),(0,$.jsxs)(`small`,{children:[t?.file,`:`,t?.lineno,` · parser rank `,t?.entrypoint_rank]})]},e)})}):null,r?(0,$.jsx)(`p`,{className:`entrypoint-error`,role:`alert`,children:r}):null,(0,$.jsx)(`button`,{className:`entrypoint-continue`,type:`button`,onClick:a,children:n?`Keep current Home`:`Explore without Home`})]})}function Rq({suite:e,error:t,mode:n,onClose:r,onSubmit:i}){let a=e?.checks.find(e=>!e.passed)??null,o=e?.checks.filter(e=>e.passed).length??0,[s,c]=(0,_.useState)(()=>new Set),[l,u]=(0,_.useState)(null),[d,f]=(0,_.useState)(``),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(``);(0,_.useEffect)(()=>{c(new Set),u(null),g(``)},[a?.id]);function v(e,t){f(``),c(n=>{if(!t)return new Set([e]);let r=new Set(n);return r.has(e)?r.delete(e):r.add(e),r})}async function y(e){if(e.preventDefault(),!(!a||s.size===0)){m(!0),g(``);try{let e=await i(a.id,[...s]);e.correct?(f(e.message),u(null)):(f(``),u(e))}catch(e){g(e.message)}finally{m(!1)}}}return(0,$.jsxs)(`aside`,{className:`check-panel`,"aria-label":`Graph-derived understanding checks`,children:[(0,$.jsxs)(`header`,{className:`check-panel__header`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`p`,{children:`Active recall · graph only`}),(0,$.jsx)(`h1`,{children:e?.region_id??`Loading checks`})]}),(0,$.jsx)(`button`,{className:`check-close`,type:`button`,onClick:r,children:`Close`})]}),t||h?(0,$.jsxs)(`div`,{className:`check-state`,role:`alert`,children:[(0,$.jsx)(`h2`,{children:`The checks did not load.`}),(0,$.jsxs)(`p`,{children:[t||h,` The galaxy remains available.`]})]}):null,!e&&!t?(0,$.jsx)(`p`,{className:`check-loading`,role:`status`,children:`Deriving answers from parser edges…`}):null,e?.region_understood?(0,$.jsxs)(`div`,{className:`check-complete`,"aria-live":`polite`,children:[(0,$.jsx)(`span`,{className:`check-complete__star`,"aria-hidden":`true`,children:`✦`}),(0,$.jsx)(`h2`,{children:`System lit.`}),(0,$.jsx)(`p`,{children:`This region's source hash matches the checks you passed. Edit its file and only this system will dim again.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:r,children:`Return to the system`})]}):null,e&&!e.region_understood&&e.checks.length===0?(0,$.jsxs)(`div`,{className:`check-state`,children:[(0,$.jsx)(`h2`,{children:`No safe check yet.`}),(0,$.jsx)(`p`,{children:`Every question here is answered by the parser graph, and this region has no certain relationship Codemble can build one from. It stays dim rather than lighting on a question that would prove nothing. Import this module somewhere, or call something inside it, and its checks appear.`})]}):null,a&&!e.region_understood?(0,$.jsxs)(`form`,{className:`active-check`,onSubmit:y,children:[(0,$.jsxs)(`div`,{className:`check-progress`,children:[(0,$.jsxs)(`span`,{children:[`Check `,o+1,` of `,e.checks.length]}),(0,$.jsx)(`progress`,{value:o,max:e.checks.length})]}),d?(0,$.jsxs)(`p`,{className:`check-affirmation`,role:`status`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,children:`✦`}),` `,d]}):null,(0,$.jsxs)(`fieldset`,{children:[(0,$.jsx)(`legend`,{children:a.prompt_voices[n]}),a.multiple?(0,$.jsx)(`p`,{children:`Select every answer supported by the graph.`}):null,(0,$.jsx)(`div`,{className:`check-options`,children:a.options.map(e=>(0,$.jsxs)(`label`,{children:[(0,$.jsx)(`input`,{type:a.multiple?`checkbox`:`radio`,name:`answer-${a.id}`,value:e.id,checked:s.has(e.id),onChange:()=>v(e.id,a.multiple)}),(0,$.jsx)(`span`,{children:e.label})]},e.id))})]}),l&&!l.correct?(0,$.jsxs)(`div`,{className:`check-feedback`,role:`status`,children:[(0,$.jsx)(`strong`,{children:l.message}),(0,$.jsxs)(`span`,{children:[`Parser answer: `,l.answer_labels.join(`, `)]}),(0,$.jsxs)(`span`,{children:[`Evidence: `,l.evidence.join(`, `)]})]}):null,(0,$.jsx)(`button`,{className:`check-primary`,type:`submit`,disabled:!s.size||p,children:p?`Checking parser evidence…`:`Check answer`})]}):null]})}function zq({chart:e,studiedCount:t,projectName:n,onClearProgress:r}){let i=e.filter(e=>e.understood_nodes>0).length;return(0,$.jsxs)(`section`,{className:`star-chart-screen`,"aria-labelledby":`star-chart-heading`,children:[(0,$.jsxs)(`header`,{className:`star-chart-intro`,children:[(0,$.jsx)(`p`,{children:`Parser-detected concepts`}),(0,$.jsx)(`h1`,{id:`star-chart-heading`,children:`Your language star chart.`}),(0,$.jsx)(`p`,{children:`Encountered comes from real syntax. Studied tracks this session. Understood lights only after graph-derived checks pass.`}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts encountered`}),(0,$.jsx)(`dd`,{children:e.length})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied this session`}),(0,$.jsx)(`dd`,{children:t})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Concepts understood`}),(0,$.jsx)(`dd`,{children:i})]})]})]}),(0,$.jsx)(`div`,{className:`concept-ledger`,role:`list`,"aria-label":`Language concept progress`,children:e.map(e=>(0,$.jsxs)(`article`,{className:`concept-row`,role:`listitem`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`h2`,{children:kG(e.concept)}),(0,$.jsxs)(`span`,{children:[kG(e.language),` · `,e.occurrences,` parser `,e.occurrences===1?`occurrence`:`occurrences`]})]}),(0,$.jsx)(`div`,{className:`concept-meter`,"aria-label":`${e.understood_nodes} of ${e.nodes} structures understood`,children:(0,$.jsx)(`span`,{style:{width:`${e.nodes?e.understood_nodes/e.nodes*100:0}%`}})}),(0,$.jsxs)(`dl`,{children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Studied (session)`}),(0,$.jsxs)(`dd`,{children:[e.studied_nodes,`/`,e.nodes]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{children:`Understood`}),(0,$.jsxs)(`dd`,{children:[e.understood_nodes,`/`,e.nodes]})]})]})]},`${e.language}:${e.concept}`))}),(0,$.jsx)(Bq,{projectName:n,onConfirm:r})]})}function Bq({projectName:e,onConfirm:t}){let[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(``),c=(0,_.useRef)(null),l=(0,_.useRef)(null),u=(0,_.useRef)(!1);(0,_.useEffect)(()=>{n?l.current?.focus():u.current&&c.current?.focus(),u.current=n},[n]);function d(){r(!1),s(``)}async function f(){a(!0),s(``);try{await t(),r(!1)}catch(e){s(e.message)}finally{a(!1)}}return n?(0,$.jsxs)(`section`,{className:`progress-reset progress-reset--confirming`,role:`group`,"aria-label":`Clear this project's progress`,tabIndex:-1,ref:l,onKeyDown:e=>{e.key===`Escape`&&!i&&d()},children:[(0,$.jsxs)(`p`,{role:`alert`,children:[`This dims every system you lit in `,e,` and cannot be undone. Your other projects keep their progress, and no source file is touched.`]}),o?(0,$.jsx)(`p`,{className:`progress-reset__error`,role:`alert`,children:o}):null,(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`button`,{className:`check-primary progress-reset__confirm`,type:`button`,disabled:i,onClick:f,children:i?`Clearing…`:`Yes, clear ${e}`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,disabled:i,onClick:d,children:`Keep it`})]})]}):(0,$.jsxs)(`section`,{className:`progress-reset`,children:[(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,ref:c,onClick:()=>r(!0),children:`Clear this project's progress`}),(0,$.jsxs)(`p`,{children:[`Start `,e,` over with every system dim again.`]})]})}var Vq=class extends _.Component{constructor(e){super(e),this.state={message:``}}static getDerivedStateFromError(e){return{message:e instanceof Error?e.message:String(e)}}componentDidCatch(e,t){console.error(`Codemble stopped rendering:`,e,t?.componentStack)}render(){return this.state.message?(0,$.jsxs)(`main`,{className:`load-state`,role:`alert`,children:[(0,$.jsx)(`h1`,{children:`The galaxy stopped rendering.`}),(0,$.jsx)(`p`,{children:this.state.message}),(0,$.jsx)(`p`,{children:`Your progress is saved on this machine; reloading re-reads it.`}),(0,$.jsx)(`button`,{className:`check-primary`,type:`button`,onClick:()=>window.location.reload(),children:`Reload Codemble`})]}):this.props.children}};(0,v.createRoot)(document.getElementById(`root`)).render((0,$.jsx)(_.StrictMode,{children:(0,$.jsx)(Vq,{children:(0,$.jsx)(wq,{})})})); \ No newline at end of file diff --git a/codemble/web_dist/assets/index-CsUbeE2C.css b/codemble/web_dist/assets/index-CsUbeE2C.css new file mode 100644 index 0000000..34d42f3 --- /dev/null +++ b/codemble/web_dist/assets/index-CsUbeE2C.css @@ -0,0 +1 @@ +@font-face{font-family:Zen Kaku Gothic New;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/zen-kaku-gothic-new-latin-400-normal-BEdayliK.woff2)format("woff2"),url(/assets/zen-kaku-gothic-new-latin-400-normal-CPSmNJAU.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/shippori-mincho-latin-500-normal-XI1O8euf.woff2)format("woff2"),url(/assets/shippori-mincho-latin-500-normal-C-QwvIb3.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/shippori-mincho-latin-700-normal-DHcmzUO5.woff2)format("woff2"),url(/assets/shippori-mincho-latin-700-normal-CkoCYOiI.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff)format("woff")}:root{--cm-font-display:"Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif;--cm-font-body:"Zen Kaku Gothic New", "Hiragino Sans", system-ui, sans-serif;--cm-font-mono:"JetBrains Mono", ui-monospace, monospace;--cm-text-xs:.75rem;--cm-text-sm:.875rem;--cm-text-base:1rem;--cm-text-lg:clamp(1.0625rem, .2vw + 1rem, 1.1875rem);--cm-text-xl:clamp(1.25rem, .5vw + 1.1rem, 1.5rem);--cm-text-2xl:clamp(1.5rem, 1vw + 1.25rem, 2rem);--cm-text-3xl:clamp(1.75rem, 2vw + 1.25rem, 3rem);--cm-text-display:clamp(2.25rem, 4.4vw + .9rem, 4.75rem);--cm-space-2xs:.25rem;--cm-space-xs:.5rem;--cm-space-sm:.75rem;--cm-space-md:1rem;--cm-space-lg:2rem;--cm-space-xl:4rem;--cm-space-2xl:6rem;--cm-space-3xl:9rem;--cm-radius:3px;--cm-radius-lg:6px;--cm-rule:1px;--cm-ease:cubic-bezier(.16, .7, .3, 1);--cm-dur-quick:.16s;--cm-dur-reveal:.42s;--cm-dur-slow:.9s;--cm-z-canvas:0;--cm-z-content:1;--cm-z-rail:40;--cm-z-nav:50}:root[data-theme=dark],:root{--cm-ground:#070b1c;--cm-ground-2:#101a3e;--cm-ground-3:#1a2750;--cm-hairline:#24325c;--cm-hairline-soft:#17203f;--cm-ink:#eef2fa;--cm-ink-2:#9aa8c4;--cm-ink-3:#7d8aa8;--cm-star:#e89b2e;--cm-star-high:#f4c46a;--cm-star-low:#3a2a0c;--cm-star-tint:#e89b2e24;--cm-orbit:#82abec;--cm-orbit-fill:#3f6ac0;--cm-orbit-deep:#2b4d96;--cm-orbit-low:#14264a;--cm-on-fill:#f7faff;--cm-sky-far:#070b1c;--cm-sky-near:#16224a}:root[data-theme=light]{--cm-ground:#faf7f0;--cm-ground-2:#fff;--cm-ground-3:#f2eee4;--cm-hairline:#e6e2d6;--cm-hairline-soft:#efece3;--cm-ink:#101a3e;--cm-ink-2:#3c4a74;--cm-ink-3:#5c688c;--cm-star:#7d4a06;--cm-star-high:#a86408;--cm-star-low:#fff3d6;--cm-star-tint:#7d4a061a;--cm-orbit:#2b4d96;--cm-orbit-fill:#2b4d96;--cm-orbit-deep:#1e3a6e;--cm-orbit-low:#e3ecfb;--cm-on-fill:#faf7f0;--cm-sky-far:#e9edf7;--cm-sky-near:#fff}:root{--cm-route-possible:color-mix(in srgb, var(--cm-ink-2) 30%, var(--cm-ink-3));--cm-node-unlit:color-mix(in srgb, var(--cm-ink-3) 78%, var(--cm-ground));--cm-neb-python:#599079;--cm-neb-js:#8b7ea9;--cm-neb-ts:#568baa;--cm-star-halo:#f2efe9;--cm-label-plate:#090e1cd1;--cm-label-ink:#d6dbe7;--cm-sidebar-width:min(19rem, 82vw);--cm-scrim:color-mix(in srgb, var(--cm-ground) 82%, transparent);--cm-error:oklch(72% .16 28);--cm-space-2xs:.125rem;--cm-space-2xl:6rem;--cm-radius:.25rem;--cm-text-xs:.75rem;--cm-text-sm:.875rem;--cm-text-base:1rem;--cm-text-lg:1.25rem;--cm-text-display:clamp(1.75rem, 3vw + 1rem, 3.25rem);--cm-z-base:1;--cm-z-raised:10;--cm-z-sticky:200;--cm-z-panel:400}*{box-sizing:border-box}html,body,#root{width:100%;min-height:100%;margin:0;overflow-x:clip}body{background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-body);font-size:var(--cm-text-base);line-height:1.55}button,output{font:inherit}button:focus-visible,[href]:focus-visible,[tabindex]:focus-visible,input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:3px}.app-shell{background:var(--cm-ground);width:100%;height:100dvh;min-height:100dvh;color:var(--cm-ink);grid-template-rows:auto minmax(0,1fr) auto auto;grid-template-columns:minmax(0,1fr);display:grid;position:relative;overflow:hidden}.instrument-rail{z-index:var(--cm-z-sticky);align-items:center;gap:var(--cm-space-sm) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-left));border-block-end:1px solid var(--cm-hairline);background:var(--cm-ground);grid-row:1;grid-template-columns:minmax(0,1fr) auto;display:grid;position:relative}.brand-lockup{align-items:center;gap:var(--cm-space-sm);min-width:0;display:flex}.brand-lockup div{min-width:0;display:grid}.brand-lockup strong{font-family:var(--cm-font-display);letter-spacing:-.02em;font-weight:700}.brand-lockup span:not(.brand-mark),.home-readout,.location{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.brand-mark{width:var(--cm-space-md);height:var(--cm-space-md);border:1px solid var(--cm-ink-2);background:var(--cm-ink);border-radius:50%}.location{grid-area:2/1/auto/-1;margin:0}.rail-overflow{grid-area:1/2;justify-self:end}.mobile-menu-trigger{min-width:44px;min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);cursor:pointer;place-items:center;font-weight:600;display:grid}.rail-overflow__panel{z-index:var(--cm-z-panel);gap:var(--cm-space-md);max-height:calc(100dvh - 5rem);padding:var(--cm-space-md);border-block:1px solid var(--cm-hairline);background:var(--cm-ground-2);display:none;position:absolute;inset-block-start:100%;inset-inline:0;overflow-y:auto;box-shadow:0 1rem 2.5rem #00000061}.rail-overflow[data-open] .rail-overflow__panel{display:grid}.instrument-rail:has(.rail-overflow[data-open]){z-index:var(--cm-z-panel)}.rail-overflow__panel .rail-actions,.rail-overflow__panel .rail-controls{grid-area:auto;justify-content:start}.rail-action{min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;white-space:nowrap;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}@media (hover:hover) and (pointer:fine){.rail-action:hover{background:var(--cm-orbit-low)}}.rail-action:active{transform:translateY(1px)}.rail-action:disabled,.rail-action[aria-disabled=true]{opacity:.5;cursor:not-allowed}.rail-action[data-state=loading]{color:var(--cm-ink-2)}.rail-action[data-state=error]{border-color:var(--cm-error)}.rail-action[data-state=success]{border-color:var(--cm-star);color:var(--cm-star)}.rail-actions{justify-content:end;align-items:center;gap:var(--cm-space-sm);flex-wrap:wrap;grid-area:2/1/auto/-1;min-width:0;display:flex}.rail-controls{align-items:center;gap:var(--cm-space-md);flex-wrap:wrap;grid-area:4/1/auto/-1;min-width:0;display:flex}.switch-project{gap:var(--cm-space-xs);padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);display:grid}.switch-project p{max-width:26ch;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.switch-project__error{color:var(--cm-error)!important}.switch-project>div{gap:var(--cm-space-xs);display:flex}.language-focus{align-items:center;gap:var(--cm-space-sm);min-width:0;color:var(--cm-ink-3);scrollbar-width:none;display:flex;overflow-x:auto}.language-focus::-webkit-scrollbar{display:none}.language-focus__label{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none}.language-focus>div{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.language-focus button{justify-content:center;align-items:center;gap:var(--cm-space-xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border:0;border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap;background:0 0;display:inline-flex}.language-focus button:last-child{border-inline-end:0}.language-focus button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-orbit)}.language-focus button small{color:var(--cm-ink-3);font-size:inherit;font-variant-numeric:tabular-nums}@media (hover:hover) and (pointer:fine){.language-focus button:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.language-focus button[aria-pressed=true]:hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-toggle{align-items:center;gap:var(--cm-space-sm);border:0;grid-area:4/1/auto/-1;min-width:0;margin:0;padding:0;display:flex}.mode-toggle__label{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none}.mode-toggle__options{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.mode-toggle__options label{align-items:center;gap:var(--cm-space-2xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);display:inline-flex}.mode-toggle__options label:last-child{border-inline-end:0}.mode-toggle__options label:has(input:checked){background:var(--cm-orbit-low);color:var(--cm-orbit)}.mode-toggle__options input{width:1rem;height:1rem;accent-color:var(--cm-orbit);margin:0}@media (hover:hover) and (pointer:fine){.mode-toggle__options label:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.mode-toggle__options label:has(input:checked):hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-gate{width:min(26rem, calc(100% - var(--cm-space-xl)));max-height:min(86%,30rem);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;margin:auto;overflow:auto}.mode-gate::backdrop{background:var(--cm-scrim)}.mode-gate h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin:0;font-style:normal;line-height:1.15}.mode-gate p{max-width:42ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.mode-gate__options{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg);display:grid}.mode-gate__options button{min-height:52px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;font:inherit;text-align:start;background:0 0;font-weight:600}.mode-gate__options button:last-child{border-block-end:0}@media (hover:hover) and (pointer:fine){.mode-gate__options button:hover{color:var(--cm-orbit)}}.map-stage{background:var(--cm-ground);grid-row:2;min-width:0;max-width:100%;min-height:0;position:relative;overflow:clip}.chart-stage{background:var(--cm-ground);grid-row:2;min-width:0;min-height:0;position:relative;overflow:hidden}.chart-stage .star-chart-screen{height:100%}.galaxy-frame,.galaxy-canvas{z-index:var(--cm-z-base);position:absolute;inset:0}.galaxy-frame{overflow:hidden}.galaxy-canvas canvas{display:block}.keyboard-focus{max-width:min(34rem, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-sm) var(--cm-space-md);border-inline-start:2px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);position:absolute;inset-block-end:var(--cm-space-md);inset-inline-start:var(--cm-space-md)}.orientation-bar{z-index:var(--cm-z-raised);gap:var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);pointer-events:none;flex-wrap:wrap;margin:0;display:flex;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-bar>*+:before{content:"· ";color:var(--cm-hairline)}.orientation-bar__charted{color:var(--cm-ink-2)}.index-sidebar{z-index:var(--cm-z-panel);width:var(--cm-sidebar-width);border-inline-end:1px solid var(--cm-hairline);background:var(--cm-ground-2);flex-direction:column;display:flex;position:absolute;inset-block:0;inset-inline-start:0}@media (width>=60rem){:is(.map-stage:has(.index-sidebar) .galaxy-frame,.map-stage:has(.index-sidebar) .map-view){inset-inline-start:var(--cm-sidebar-width)}:is(.map-stage:has(.index-sidebar) .orientation-bar,.map-stage:has(.index-sidebar) .orientation-copy){inset-inline-start:calc(var(--cm-sidebar-width) + var(--cm-space-md))}}.index-sidebar>header{justify-content:space-between;align-items:center;gap:var(--cm-space-sm);padding:var(--cm-space-sm) var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:flex}.index-sidebar h2{color:var(--cm-ink);font-size:var(--cm-text-sm);letter-spacing:.08em;text-transform:uppercase;margin:0}.index-sidebar>header button{border-radius:var(--cm-radius);min-width:32px;min-height:32px;color:var(--cm-ink-2);font-size:var(--cm-text-lg);cursor:pointer;background:0 0;border:1px solid #0000;line-height:1}.index-sidebar>header button:hover,.index-sidebar>header button:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar__scroll{flex:1;padding-block-end:var(--cm-space-lg);overflow-y:auto}.index-sidebar section{padding-block-start:var(--cm-space-sm)}.index-sidebar h3{padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;margin:0;font-weight:400;overflow:hidden}.index-sidebar ul{margin:0;padding:0;list-style:none}.index-sidebar li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.index-sidebar li button span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.index-sidebar li button:hover,.index-sidebar li button:focus-visible{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.index-sidebar li button[aria-current=true]{border-inline-start-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar li button[data-lit] span{color:var(--cm-star-high)}.index-sidebar li em{color:var(--cm-ink-3);font-size:var(--cm-text-xs);font-style:normal}.module-finder{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);width:min(34rem,92vw);max-height:70vh;color:var(--cm-ink);padding:0}.module-finder::backdrop{background:var(--cm-scrim)}.module-finder input{width:100%;padding:var(--cm-space-md);border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-base);background:0 0}.module-finder input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:-2px}.module-finder ul{max-height:50vh;padding:var(--cm-space-2xs) 0;margin:0;list-style:none;overflow-y:auto}.module-finder li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:36px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.module-finder li button[data-active]{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.module-finder li strong{font-weight:400}.module-finder li small{color:var(--cm-ink-3);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.module-finder li em{color:var(--cm-star-high);font-style:normal}.module-finder__empty{padding:var(--cm-space-md);color:var(--cm-ink-3);font-size:var(--cm-text-sm);margin:0}.rail-action kbd{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin-inline-start:var(--cm-space-2xs)}.rail-action--toggle[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.orientation-copy{z-index:var(--cm-z-raised);max-width:min(28rem, calc(100% - var(--cm-space-lg)));pointer-events:none;position:absolute;inset-block-start:clamp(var(--cm-space-lg), 8vh, var(--cm-space-2xl));inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-copy--system{inset-block-start:var(--cm-space-lg)}.orientation-copy h1,.study-preview h1,.load-state h1,.webgl-error h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;font-weight:700;line-height:1.08}.orientation-copy p,.study-preview p{max-width:55ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.orientation-copy--inline{z-index:auto;pointer-events:auto;flex:none;max-block-size:45%;position:static;overflow-y:auto}.orientation-copy--inline h1{font-size:var(--cm-text-lg)}.orientation-copy--inline p{font-size:var(--cm-text-sm);margin-block-start:var(--cm-space-2xs)}.orientation-copy--inline .check-launch{margin-block-start:var(--cm-space-sm)}.check-launch,.check-primary,.check-close{border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);min-height:44px;color:var(--cm-orbit);cursor:pointer;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}.check-launch{padding-inline:var(--cm-space-md);pointer-events:auto;margin-block-start:var(--cm-space-md);position:relative}.check-primary{padding-inline:var(--cm-space-lg);justify-self:start}.check-close{padding-inline:var(--cm-space-md);border-color:var(--cm-hairline);color:var(--cm-ink-2)}@media (hover:hover) and (pointer:fine){.check-launch:hover,.check-primary:hover,.check-close:hover{background:var(--cm-orbit-low);color:var(--cm-ink)}}.check-launch:active,.check-primary:active,.check-close:active{transform:translateY(1px)}.check-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.legend-toggle{z-index:var(--cm-z-sticky);min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-end:var(--cm-space-md)}.legend-toggle:hover,.legend-toggle:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.legend-toggle[aria-expanded=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.map-legend{z-index:var(--cm-z-raised);gap:var(--cm-space-2xs) var(--cm-space-md);max-height:min(60vh,30rem);padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);grid-template-columns:repeat(2,auto);display:none;position:absolute;inset-block-start:calc(var(--cm-space-md) + 40px);inset-inline-end:var(--cm-space-md);overflow-y:auto}.map-legend span{align-items:center;gap:var(--cm-space-sm);white-space:nowrap;display:inline-flex}.legend-dot{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:50%;display:inline-block}.legend-dot--dim{background:var(--cm-ink-3)}.legend-dot--lit{background:var(--cm-star-high)}.legend-dot--partial{background:var(--cm-route-possible)}.legend-route{width:var(--cm-space-md);border-block-start:1px solid var(--cm-ink-3)}.legend-route--possible{border-block-start-color:var(--cm-route-possible)}.partial-summary{border-inline-start:2px solid var(--cm-route-possible);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);color:var(--cm-ink)!important}.entrypoint-picker{z-index:var(--cm-z-panel);inset-inline:max(var(--cm-space-md), env(safe-area-inset-left));width:min(36rem, calc(100% - var(--cm-space-xl)));max-height:min(76%,42rem);padding:var(--cm-space-lg);border-block:1px solid var(--cm-hairline);background:var(--cm-ground-2);box-shadow:0 0 0 100vmax var(--cm-ground);color:var(--cm-ink);animation:entrypoint-enter var(--cm-dur-reveal) var(--cm-ease) both;margin-inline:auto;position:absolute;inset-block-start:50%;overflow:auto;transform:translateY(-50%)}.entrypoint-picker>p:first-child{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.entrypoint-picker h1{margin:var(--cm-space-sm) 0 0;overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);line-height:1.1}.entrypoint-picker>p:not(:first-child){margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.entrypoint-candidates{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.entrypoint-candidates button{gap:var(--cm-space-xs);width:100%;min-height:58px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.entrypoint-candidates button span{overflow-wrap:anywhere;font-family:var(--cm-font-mono)}.entrypoint-candidates button small{color:var(--cm-ink-3);font-family:var(--cm-font-mono)}@media (hover:hover) and (pointer:fine){.entrypoint-candidates button:hover{color:var(--cm-orbit)}}.entrypoint-continue{min-height:44px;color:var(--cm-ink-2);cursor:pointer;text-underline-offset:3px;background:0 0;border:0;margin-block-start:var(--cm-space-lg);padding:0;text-decoration:underline}.entrypoint-error{color:var(--cm-error)!important}.illumination-pulse{z-index:var(--cm-z-raised);color:var(--cm-star);pointer-events:none;animation:illumination-pulse .42s var(--cm-ease) both;justify-items:center;display:grid;position:absolute;inset-block-start:50%;inset-inline-start:25%;transform:translate(-50%,-50%)}.illumination-pulse span{filter:drop-shadow(0 0 18px var(--cm-star));font-size:clamp(3rem,8vw,6rem);line-height:1}.illumination-pulse strong{color:var(--cm-ink);font-family:var(--cm-font-display)}.structural-summary p{max-width:62ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink)}.mini-constellation{width:100%;max-width:22rem;height:auto;margin-block-start:var(--cm-space-md)}.mini-constellation line{stroke:var(--cm-hairline);stroke-width:1px}.mini-constellation circle{fill:var(--cm-ink-3)}.mini-constellation__self{fill:var(--cm-orbit)}.connections h3{margin:var(--cm-space-lg) 0 0;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;font-weight:500}.connection-list{margin:var(--cm-space-xs) 0 0;border-block-start:1px solid var(--cm-hairline);padding:0;list-style:none}.connection-list button{gap:var(--cm-space-2xs);width:100%;min-height:52px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.connection-name{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.connection-meta{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}@media (hover:hover) and (pointer:fine){.connection-list button:hover .connection-name{color:var(--cm-orbit)}}.load-state .check-primary,.study-notice .check-primary{justify-self:start;margin-block-start:var(--cm-space-md)}.study-preview{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:72%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.check-panel{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:76%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.check-panel__header{justify-content:space-between;align-items:start;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-lg);display:flex}.check-panel__header p,.check-panel__header h1{margin:0}.check-panel__header p,.check-progress span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-panel__header h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin-block-start:var(--cm-space-xs);line-height:1.1}.check-loading,.check-state,.check-complete,.active-check{margin-block-start:var(--cm-space-lg)}.check-loading,.check-state p,.check-complete p,.active-check fieldset>p{max-width:60ch;color:var(--cm-ink-2)}.check-state h2,.check-complete h2{font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0}.check-state p,.check-complete p{margin:var(--cm-space-sm) 0 0}.check-complete{gap:var(--cm-space-sm);display:grid}.check-complete__star{color:var(--cm-star);font-size:var(--cm-text-display);line-height:1}.check-progress{align-items:center;gap:var(--cm-space-md);grid-template-columns:auto minmax(5rem,1fr);margin-block-end:var(--cm-space-xl);display:grid}.check-progress progress{background:var(--cm-hairline);width:100%;height:2px;color:var(--cm-star);border:0}.check-progress progress::-webkit-progress-bar{background:var(--cm-hairline)}.check-progress progress::-webkit-progress-value{background:var(--cm-star)}.check-progress progress::-moz-progress-bar{background:var(--cm-star)}.active-check{gap:var(--cm-space-lg);display:grid}.active-check fieldset{border:0;min-width:0;margin:0;padding:0}.active-check legend{overflow-wrap:anywhere;max-width:28ch;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);padding:0;font-weight:700;line-height:1.15}.active-check fieldset>p{margin:var(--cm-space-sm) 0 0}.check-options{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.check-options label{align-items:center;gap:var(--cm-space-md);min-height:52px;padding-block:var(--cm-space-sm);border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;grid-template-columns:auto minmax(0,1fr);display:grid}.check-options label:has(input:checked){color:var(--cm-ink)}.check-options input{width:1rem;height:1rem;accent-color:var(--cm-star);margin:0}.check-options span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.check-feedback{gap:var(--cm-space-xs);padding:var(--cm-space-md);border-inline-start:2px solid var(--cm-error);background:var(--cm-ground);color:var(--cm-ink-2);display:grid}.check-feedback strong{color:var(--cm-ink)}.check-feedback span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-affirmation{align-items:baseline;gap:var(--cm-space-xs);margin:0 0 var(--cm-space-lg);border-inline-start:2px solid var(--cm-star);color:var(--cm-star-high);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);display:flex}.study-preview__path{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);color:var(--cm-orbit)!important}.study-preview__header{display:block}.study-preview dl{gap:var(--cm-space-md);margin:var(--cm-space-lg) 0 0;grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.study-preview dl div{border-block-start:1px solid var(--cm-hairline);padding-block-start:var(--cm-space-sm)}.study-preview dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.study-preview dd{margin:var(--cm-space-2xs) 0 0;font-variant-numeric:tabular-nums}.study-content{gap:var(--cm-space-xl);min-width:0;margin-block-start:var(--cm-space-xl);display:grid}.study-content>*{min-width:0}.study-section-heading{justify-content:space-between;align-items:center;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-sm);display:flex}.study-section-heading h2,.study-notice h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal;line-height:1.15}.study-section-heading span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap}.source-code{width:100%;min-width:0;max-height:22rem;margin:var(--cm-space-md) 0 0;padding:var(--cm-space-sm) 0;border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);counter-reset:source-line;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);tab-size:4;line-height:1.65;list-style:none;overflow:auto}.source-code li{min-width:max-content;padding-inline:var(--cm-space-sm) var(--cm-space-md);grid-template-columns:3.25rem minmax(0,1fr);display:grid}.source-code li:before{content:attr(data-line);color:var(--cm-ink-3);text-align:end;-webkit-user-select:none;user-select:none;padding-inline-end:var(--cm-space-md)}.source-code li:target{background:var(--cm-orbit-low)}.source-code code{font:inherit;white-space:pre}.grounded-explanation>p,.study-notice p,.study-loading,.evidence-list p{max-width:65ch;color:var(--cm-ink-2)}.grounded-explanation>p,.study-notice p,.study-loading{margin:var(--cm-space-md) 0 0}.grounded-explanation h3{margin:var(--cm-space-lg) 0 var(--cm-space-sm);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.source-citation{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-underline-offset:2px;text-decoration-thickness:1px}.source-citation:active{color:var(--cm-ink)}@media (hover:hover) and (pointer:fine){.source-citation:hover{color:var(--cm-ink)}}.source-citation--button{cursor:pointer;background:0 0;border:0;padding:0}.source-citation--button:disabled{color:var(--cm-ink-3);cursor:not-allowed}.evidence-list{gap:var(--cm-space-sm);margin:0;padding:0;list-style:none;display:grid}.evidence-list li,.study-notice{padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground)}.evidence-list p{margin:0 0 var(--cm-space-xs)}.evidence-list strong{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);margin-block-end:var(--cm-space-xs);display:block}.lens-notes{margin-block-start:var(--cm-space-sm);display:grid}.lens-note{gap:var(--cm-space-sm);min-width:0;padding-block:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:grid}.lens-note h3{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.lens-note p{max-width:65ch;margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.lens-note code{min-width:0;padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:pre;display:block;overflow-x:auto}.star-chart-screen{min-width:0;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-xl) max(var(--cm-space-md), env(safe-area-inset-left));background:var(--cm-ground);overflow:auto}.star-chart-intro{max-width:72rem;margin-inline:auto;padding-block-end:var(--cm-space-xl);display:block}.star-chart-intro>p:first-child{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;line-height:1.08}.star-chart-intro>p:not(:first-child){max-width:65ch;margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.star-chart-intro dl{gap:var(--cm-space-md);margin:var(--cm-space-xl) 0 0;padding-block:var(--cm-space-md);border-block:1px solid var(--cm-hairline);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.star-chart-intro dt,.concept-row dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro dd{margin:var(--cm-space-xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);font-variant-numeric:tabular-nums}.concept-ledger{border-block-start:1px solid var(--cm-hairline);max-width:72rem;margin-inline:auto}.concept-row{align-items:center;gap:var(--cm-space-lg);min-width:0;padding-block:var(--cm-space-lg);border-block-end:1px solid var(--cm-hairline);grid-template-columns:minmax(10rem,.7fr) minmax(8rem,1.2fr) auto;display:grid}.concept-row h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal}.concept-row>div:first-child>span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.concept-meter{background:var(--cm-hairline);height:2px;overflow:hidden}.concept-meter span{background:var(--cm-star);height:100%;display:block}.concept-row dl{align-items:center;gap:var(--cm-space-lg);margin:0;display:flex}.concept-row dl div{min-width:5rem}.concept-row dd{margin:var(--cm-space-xs) 0 0;font-variant-numeric:tabular-nums}.status-line{z-index:var(--cm-z-sticky);justify-content:space-between;gap:var(--cm-space-2xs) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-sm), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;grid-row:4;display:flex;position:relative}.status-line span{white-space:normal}.status-line span:nth-child(2){display:none}.load-state,.webgl-error{align-content:center;gap:var(--cm-space-md);min-height:100dvh;padding:var(--cm-space-lg);background:var(--cm-ground);color:var(--cm-ink);display:grid}.load-state p,.webgl-error p{max-width:65ch;color:var(--cm-ink-2);margin:0}@keyframes panel-enter{0%{opacity:0;transform:translateY(var(--cm-space-md))}to{opacity:1;transform:translateY(0)}}@keyframes entrypoint-enter{0%{opacity:0;transform:translateY(calc(-50% + var(--cm-space-md)))}to{opacity:1;transform:translateY(-50%)}}@keyframes illumination-pulse{0%{opacity:0;transform:translate(-50%,-50%)scale(.75)}45%{opacity:1;transform:translate(-50%,-50%)scale(1.08)}to{opacity:0;transform:translate(-50%,-50%)scale(1)}}@media (width>=40rem){.instrument-rail{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr)}.rail-overflow{display:contents}.mobile-menu-trigger{display:none}.rail-overflow__panel{display:contents;position:static}.location{text-align:center;grid-area:1/2}.rail-action,.home-readout{justify-self:end}.rail-actions{grid-area:1/3}.rail-controls{grid-row:2;justify-self:center}.status-line span{white-space:nowrap;display:inline}.lens-note{gap:var(--cm-space-lg);grid-template-columns:minmax(8rem,.35fr) minmax(0,1fr)}.study-preview{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(48rem,60%);max-height:none;inset-block:0;inset-inline-start:auto}.check-panel{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(42rem,56%);max-height:none;inset-block:0;inset-inline-start:auto}}@media (width<=39.999rem){.study-preview,.check-panel{border-block-start:0;max-height:none;inset:0}}@media (width<=48rem){.illumination-pulse{inset-block-start:35%;inset-inline-start:50%}.star-chart-intro dl{grid-template-columns:1fr}.concept-row{gap:var(--cm-space-md);grid-template-columns:1fr}.concept-row dl{justify-content:space-between}}@media (width>=60rem){.map-legend:not([hidden]){display:grid}.chart-stage:has(.index-sidebar) .star-chart-screen{margin-inline-start:var(--cm-sidebar-width)}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.15s!important;animation-duration:.15s!important;animation-iteration-count:1!important}.study-preview,.check-panel,.mode-gate{animation-name:panel-enter-reduced}.entrypoint-picker{animation-name:entrypoint-enter-reduced}.illumination-pulse{animation-name:illumination-pulse-reduced}}@keyframes panel-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes entrypoint-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes illumination-pulse-reduced{0%{opacity:0}50%{opacity:1}to{opacity:0}}.picker-screen{gap:var(--cm-space-lg);min-height:100vh;padding:var(--cm-space-2xl) var(--cm-space-xl);flex-direction:column;max-width:44rem;margin:0 auto;display:flex}.picker-wordmark{font-family:var(--cm-font-display);font-size:var(--cm-text-sm);letter-spacing:.2em;text-transform:uppercase;color:var(--cm-ink-3)}.picker-subtitle{color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.picker-recents ul,.picker-browser ul{margin:var(--cm-space-sm) 0 0;gap:var(--cm-space-2xs);flex-direction:column;padding:0;list-style:none;display:flex}.picker-recents button,.picker-browser ul button{justify-content:space-between;gap:var(--cm-space-sm);width:100%;padding:var(--cm-space-xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);text-align:left;cursor:pointer;display:flex}.picker-recents button:hover,.picker-recents button:focus-visible,.picker-browser ul button:hover,.picker-browser ul button:focus-visible{border-color:var(--cm-orbit)}.picker-recents button{flex-wrap:wrap}.picker-recent-path{overflow-wrap:anywhere;min-width:0}.picker-recent-lit{color:var(--cm-star);white-space:nowrap}.picker-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2);overflow-wrap:anywhere}.picker-scale,.picker-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-error{color:var(--cm-error)}.picker-select{padding:var(--cm-space-xs) var(--cm-space-lg);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-base);cursor:pointer;align-self:flex-start}.picker-select:disabled{opacity:.6;cursor:progress}.layer-switcher{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);display:inline-flex;overflow:hidden}.layer-switcher button{padding:var(--cm-space-2xs) var(--cm-space-sm);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.layer-switcher button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-ink)}.map-view{gap:var(--cm-space-sm);padding:var(--cm-space-md);background:var(--cm-ground);flex-direction:column;display:flex;position:absolute;inset:0;overflow:hidden}.map-tabs{gap:var(--cm-space-xs);flex:none;display:flex}.map-tabs button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.map-tabs button[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-ink)}.map-canvas{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative}.map-zoom{z-index:var(--cm-z-raised);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);gap:1px;display:flex;position:absolute;inset-block-start:var(--cm-space-sm);inset-inline-end:var(--cm-space-sm)}.map-zoom button{min-width:34px;min-height:30px;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.map-zoom button:hover:not(:disabled),.map-zoom button:focus-visible{color:var(--cm-orbit)}.map-zoom button:disabled{color:var(--cm-ink-3);cursor:default}.map-scroll{cursor:grab;flex:auto;overflow:auto}.map-scroll[data-panning]{cursor:grabbing;-webkit-user-select:none;user-select:none}.map-canvas__sized{min-width:100%}.architecture-map,.workflow-tree{min-height:0;display:block}.architecture-map__edges path{color:var(--cm-hairline);stroke:currentColor;fill:none;stroke-linecap:round;stroke-linejoin:round}.architecture-map__edges path.is-cycle{color:var(--cm-route-possible)}.architecture-map__arrow{color:var(--cm-hairline)}.architecture-map__arrow.is-cycle{color:var(--cm-route-possible)}.workflow-tree__edges path{stroke:var(--cm-hairline);stroke-width:1.2px;fill:none}.architecture-map__box rect{fill:var(--cm-ground-2);stroke:var(--cm-hairline)}.architecture-map__box .box-tint{stroke:none}.architecture-map__box text{fill:var(--cm-ink);font-family:var(--cm-font-mono);font-size:13px}.architecture-map__box .box-meta{fill:var(--cm-ink-3);font-size:11px}.architecture-map__box[data-partial=true] rect:first-of-type{stroke:var(--cm-route-possible)}.architecture-map__box .box-partial{fill:var(--cm-route-possible);stroke:none}.architecture-map__box[data-understood=true] rect:first-of-type{stroke:var(--cm-star-high)}.architecture-map__box[data-home=true] rect:first-of-type{stroke-width:2px}.architecture-map__box[data-reachable=false] rect:first-of-type{stroke-dasharray:4 3}.architecture-map__box:focus-visible rect:first-of-type,.workflow-tree__row:focus-visible circle{outline:2px solid var(--cm-orbit);outline-offset:2px}.architecture-map__box,.workflow-tree__row{cursor:pointer}.workflow-tree__row circle{fill:var(--cm-ink-3)}.workflow-tree__row[data-partial=true] circle,.workflow-tree__row[data-cut] circle{fill:var(--cm-route-possible)}.workflow-tree__row[data-understood=true] circle{fill:var(--cm-star-high)}.workflow-tree__row text{fill:var(--cm-ink);font-family:var(--cm-font-mono);font-size:13px}.workflow-tree__row .row-meta{fill:var(--cm-ink-3);font-size:11px}.architecture-map__box[data-selected=true] rect:first-of-type{outline:2px solid var(--cm-orbit);outline-offset:3px}.workflow-tree__row[data-selected=true] circle{stroke:var(--cm-orbit);stroke-width:2px}.map-note,.map-loading{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);flex:none;margin:0}.map-state{text-align:center;max-width:46ch;color:var(--cm-ink-2);margin:auto}.hint-chip{z-index:var(--cm-z-raised);align-items:center;gap:var(--cm-space-sm);min-width:0;padding:var(--cm-space-sm) var(--cm-space-md);border-block:1px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-size:var(--cm-text-sm);flex-wrap:wrap;grid-row:3;display:flex;position:static}.hint-chip small{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.hint-chip button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}@media (width>=40rem){.hint-chip{max-width:calc(100% - var(--cm-space-lg));border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);grid-row:auto;position:absolute;inset-block-end:calc(3.5rem + var(--cm-space-md));inset-inline-start:var(--cm-space-md)}}.location button{color:var(--cm-orbit);font:inherit;cursor:pointer;background:0 0;border:0;padding:0}.location button[disabled]{color:var(--cm-ink-2);cursor:default}.location button:not([disabled]):hover{text-decoration:underline}.coach-marks{inset-block:auto var(--cm-space-lg);width:min(38ch, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);margin-inline:auto;inset-inline:0}.coach-marks::backdrop{background:var(--cm-scrim)}.coach-marks__progress{margin:0 0 var(--cm-space-2xs);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.coach-marks h1{margin:0 0 var(--cm-space-xs);font-size:var(--cm-text-lg)}.coach-marks__actions{justify-content:space-between;gap:var(--cm-space-sm);margin-block-start:var(--cm-space-md);display:flex}.coach-skip{color:var(--cm-ink-3);cursor:pointer;background:0 0;border:0}.legend-tint{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:2px;display:inline-block}.legend-tint--python{background:var(--cm-neb-python)}.legend-tint--javascript{background:var(--cm-neb-js)}.legend-tint--typescript{background:var(--cm-neb-ts)}.legend-route--dashed{border-block-start-style:dashed}.legend-size{width:var(--cm-space-md);height:var(--cm-space-sm);background:var(--cm-ink-3);border-radius:50%;display:inline-block}.legend-brightness{width:var(--cm-space-md);height:var(--cm-space-sm);background:linear-gradient(90deg, var(--cm-node-unlit), var(--cm-ink-2));display:inline-block}.app-shell[data-mode=easy]{--cm-text-xs:.8125rem;--cm-text-sm:.9375rem;--cm-text-base:1.125rem;--cm-text-lg:1.375rem;--cm-space-sm:1rem;--cm-space-md:1.375rem;--cm-space-lg:2.5rem;font-size:var(--cm-text-base);line-height:1.7}.app-shell[data-mode=easy] .orientation-copy p,.app-shell[data-mode=easy] .study-preview p,.app-shell[data-mode=easy] .grounded-explanation>p,.app-shell[data-mode=easy] .study-notice p,.app-shell[data-mode=easy] .evidence-list p,.app-shell[data-mode=easy] .lens-note p,.app-shell[data-mode=easy] .active-check fieldset>p,.app-shell[data-mode=easy] .check-state p,.app-shell[data-mode=easy] .check-complete p,.app-shell[data-mode=easy] .check-loading{max-width:46ch}.app-shell[data-mode=easy] .language-focus__label,.app-shell[data-mode=easy] .mode-toggle__label{text-transform:none;letter-spacing:normal}.loading-screen{gap:var(--cm-space-md);max-width:44rem;min-height:100vh;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-left));align-content:center;justify-items:start;margin:0 auto;display:grid}.loading-header h1{min-width:0;margin:var(--cm-space-2xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);overflow-wrap:anywhere;line-height:1.15}.loading-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2)}.loading-subtitle{margin:var(--cm-space-xs) 0 0;color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-stages{gap:var(--cm-space-2xs);width:100%;margin:0;padding:0;list-style:none;display:grid}.loading-stages li{justify-content:space-between;gap:var(--cm-space-sm);padding:var(--cm-space-xs) var(--cm-space-sm);border-left:2px solid var(--cm-hairline);color:var(--cm-ink-3);font-size:var(--cm-text-sm);flex-wrap:wrap;display:flex}.loading-stages li[data-state=active]{border-left-color:var(--cm-orbit);color:var(--cm-ink)}.loading-stages li[data-state=done]{border-left-color:var(--cm-orbit-deep);color:var(--cm-ink-2)}.loading-stages small{font-family:var(--cm-font-mono);color:var(--cm-ink-2)}.loading-meter{width:100%;height:var(--cm-space-xs);accent-color:var(--cm-orbit)}.loading-live{color:var(--cm-ink);font-size:var(--cm-text-sm)}.loading-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);width:100%;padding:var(--cm-space-sm);color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-actions{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.loading-actions button{padding:var(--cm-space-xs) var(--cm-space-md)}.picker-scale h2,.picker-failure h2{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base)}.picker-scale-scopes{gap:var(--cm-space-xs);margin:var(--cm-space-sm) 0;flex-wrap:wrap;padding:0;list-style:none;display:flex}.picker-scale-scopes button{align-items:flex-start;gap:var(--cm-space-2xs);min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);cursor:pointer;flex-direction:column;display:flex}.picker-scale-scopes button:hover:not(:disabled),.picker-scale-scopes button:focus-visible{border-color:var(--cm-orbit)}.picker-scale-scopes button:disabled{opacity:.6;cursor:progress}.picker-scale-scopes small{color:var(--cm-ink-2)}.picker-path-entry{gap:var(--cm-space-xs);flex-wrap:wrap;align-items:center;display:flex}.picker-path-entry label{color:var(--cm-ink-2)}.picker-path-entry input{min-width:0;min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-xs);background:var(--cm-ground);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);flex:14rem}.picker-path-entry button{min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-md);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-sm);cursor:pointer}.picker-path-entry button:disabled{opacity:.6;cursor:not-allowed}.picker-failure{border:1px solid var(--cm-error);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-failure>p{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.picker-failure__detail{gap:var(--cm-space-2xs);display:grid}.picker-failure__detail span{color:var(--cm-ink-3);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em}.picker-failure__detail code{max-height:8rem;padding:var(--cm-space-xs);background:var(--cm-ground-2);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);overflow-wrap:anywhere;display:block;overflow:auto}.picker-failure .picker-select{min-height:44px;font-size:var(--cm-text-sm);align-self:flex-start}.progress-reset{align-items:center;gap:var(--cm-space-sm);max-width:72rem;margin:var(--cm-space-lg) auto 0;padding-top:var(--cm-space-md);border-top:1px solid var(--cm-hairline);flex-wrap:wrap;display:flex}.progress-reset p{color:var(--cm-ink-2);font-size:var(--cm-text-sm);margin:0}.progress-reset button{min-height:44px;padding-inline:var(--cm-space-md);font-size:var(--cm-text-sm)}.progress-reset--confirming{justify-items:start;gap:var(--cm-space-sm);display:grid}.progress-reset--confirming>p[role=alert]{max-width:60ch;color:var(--cm-ink)}.progress-reset--confirming>div{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.progress-reset__confirm{border-color:var(--cm-error);color:var(--cm-error)}.progress-reset__error{color:var(--cm-error)} diff --git a/codemble/web_dist/assets/index-wY0ZuS7b.css b/codemble/web_dist/assets/index-wY0ZuS7b.css deleted file mode 100644 index 0e549fd..0000000 --- a/codemble/web_dist/assets/index-wY0ZuS7b.css +++ /dev/null @@ -1 +0,0 @@ -@font-face{font-family:Zen Kaku Gothic New;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/zen-kaku-gothic-new-latin-400-normal-BEdayliK.woff2)format("woff2"),url(/assets/zen-kaku-gothic-new-latin-400-normal-CPSmNJAU.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/shippori-mincho-latin-500-normal-XI1O8euf.woff2)format("woff2"),url(/assets/shippori-mincho-latin-500-normal-C-QwvIb3.woff)format("woff")}@font-face{font-family:Shippori Mincho;font-style:normal;font-display:swap;font-weight:700;src:url(/assets/shippori-mincho-latin-700-normal-DHcmzUO5.woff2)format("woff2"),url(/assets/shippori-mincho-latin-700-normal-CkoCYOiI.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff)format("woff")}@font-face{font-family:JetBrains Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2)format("woff2"),url(/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff)format("woff")}:root{--cm-font-display:"Shippori Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif;--cm-font-body:"Zen Kaku Gothic New", "Hiragino Sans", system-ui, sans-serif;--cm-font-mono:"JetBrains Mono", ui-monospace, monospace;--cm-text-xs:.75rem;--cm-text-sm:.875rem;--cm-text-base:1rem;--cm-text-lg:clamp(1.0625rem, .2vw + 1rem, 1.1875rem);--cm-text-xl:clamp(1.25rem, .5vw + 1.1rem, 1.5rem);--cm-text-2xl:clamp(1.5rem, 1vw + 1.25rem, 2rem);--cm-text-3xl:clamp(1.75rem, 2vw + 1.25rem, 3rem);--cm-text-display:clamp(2.25rem, 4.4vw + .9rem, 4.75rem);--cm-space-2xs:.25rem;--cm-space-xs:.5rem;--cm-space-sm:.75rem;--cm-space-md:1rem;--cm-space-lg:2rem;--cm-space-xl:4rem;--cm-space-2xl:6rem;--cm-space-3xl:9rem;--cm-radius:3px;--cm-radius-lg:6px;--cm-rule:1px;--cm-ease:cubic-bezier(.16, .7, .3, 1);--cm-dur-quick:.16s;--cm-dur-reveal:.42s;--cm-dur-slow:.9s;--cm-z-canvas:0;--cm-z-content:1;--cm-z-rail:40;--cm-z-nav:50}:root[data-theme=dark],:root{--cm-ground:#070b1c;--cm-ground-2:#101a3e;--cm-ground-3:#1a2750;--cm-hairline:#24325c;--cm-hairline-soft:#17203f;--cm-ink:#eef2fa;--cm-ink-2:#9aa8c4;--cm-ink-3:#7d8aa8;--cm-star:#e89b2e;--cm-star-high:#f4c46a;--cm-star-low:#3a2a0c;--cm-star-tint:#e89b2e24;--cm-orbit:#82abec;--cm-orbit-fill:#3f6ac0;--cm-orbit-deep:#2b4d96;--cm-orbit-low:#14264a;--cm-on-fill:#f7faff;--cm-sky-far:#070b1c;--cm-sky-near:#16224a}:root[data-theme=light]{--cm-ground:#faf7f0;--cm-ground-2:#fff;--cm-ground-3:#f2eee4;--cm-hairline:#e6e2d6;--cm-hairline-soft:#efece3;--cm-ink:#101a3e;--cm-ink-2:#3c4a74;--cm-ink-3:#5c688c;--cm-star:#7d4a06;--cm-star-high:#a86408;--cm-star-low:#fff3d6;--cm-star-tint:#7d4a061a;--cm-orbit:#2b4d96;--cm-orbit-fill:#2b4d96;--cm-orbit-deep:#1e3a6e;--cm-orbit-low:#e3ecfb;--cm-on-fill:#faf7f0;--cm-sky-far:#e9edf7;--cm-sky-near:#fff}:root{--cm-route-possible:color-mix(in srgb, var(--cm-ink-2) 30%, var(--cm-ink-3));--cm-node-unlit:color-mix(in srgb, var(--cm-ink-3) 78%, var(--cm-ground));--cm-neb-python:#599079;--cm-neb-js:#8b7ea9;--cm-neb-ts:#568baa;--cm-star-halo:#f2efe9;--cm-label-plate:#090e1cd1;--cm-label-ink:#d6dbe7;--cm-sidebar-width:min(19rem, 82vw);--cm-scrim:color-mix(in srgb, var(--cm-ground) 82%, transparent);--cm-error:oklch(72% .16 28);--cm-space-2xs:.125rem;--cm-space-2xl:6rem;--cm-radius:.25rem;--cm-text-xs:.75rem;--cm-text-sm:.875rem;--cm-text-base:1rem;--cm-text-lg:1.25rem;--cm-text-display:clamp(1.75rem, 3vw + 1rem, 3.25rem);--cm-z-base:1;--cm-z-raised:10;--cm-z-sticky:200;--cm-z-panel:400}*{box-sizing:border-box}html,body,#root{width:100%;min-height:100%;margin:0;overflow-x:clip}body{background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-body);font-size:var(--cm-text-base);line-height:1.55}button,output{font:inherit}button:focus-visible,[href]:focus-visible,[tabindex]:focus-visible,input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:3px}.app-shell{background:var(--cm-ground);width:100%;min-height:100dvh;color:var(--cm-ink);grid-template-rows:auto minmax(0,1fr) auto;grid-template-columns:minmax(0,1fr);display:grid;overflow-x:clip}.instrument-rail{z-index:var(--cm-z-sticky);align-items:center;gap:var(--cm-space-sm) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-left));border-block-end:1px solid var(--cm-hairline);background:var(--cm-ground);grid-template-columns:minmax(0,1fr);display:grid;position:relative}.brand-lockup{align-items:center;gap:var(--cm-space-sm);min-width:0;display:flex}.brand-lockup div{min-width:0;display:grid}.brand-lockup strong{font-family:var(--cm-font-display);letter-spacing:-.02em;font-weight:700}.brand-lockup span:not(.brand-mark),.home-readout,.location{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.brand-mark{width:var(--cm-space-md);height:var(--cm-space-md);border:1px solid var(--cm-ink-2);background:var(--cm-ink);border-radius:50%}.location{grid-area:3/1/auto/-1;margin:0}.rail-action{min-height:44px;padding-inline:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-orbit);cursor:pointer;white-space:nowrap;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}@media (hover:hover) and (pointer:fine){.rail-action:hover{background:var(--cm-orbit-low)}}.rail-action:active{transform:translateY(1px)}.rail-action:disabled,.rail-action[aria-disabled=true]{opacity:.5;cursor:not-allowed}.rail-action[data-state=loading]{color:var(--cm-ink-2)}.rail-action[data-state=error]{border-color:var(--cm-error)}.rail-action[data-state=success]{border-color:var(--cm-star);color:var(--cm-star)}.rail-actions{justify-content:end;align-items:center;gap:var(--cm-space-sm);flex-wrap:wrap;grid-area:2/1/auto/-1;min-width:0;display:flex}.rail-controls{align-items:center;gap:var(--cm-space-md);flex-wrap:wrap;grid-area:4/1/auto/-1;min-width:0;display:flex}.switch-project{gap:var(--cm-space-xs);padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);display:grid}.switch-project p{max-width:26ch;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.switch-project__error{color:var(--cm-error)!important}.switch-project>div{gap:var(--cm-space-xs);display:flex}.language-focus{align-items:center;gap:var(--cm-space-sm);min-width:0;color:var(--cm-ink-3);scrollbar-width:none;display:flex;overflow-x:auto}.language-focus::-webkit-scrollbar{display:none}.language-focus__label{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none}.language-focus>div{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.language-focus button{justify-content:center;align-items:center;gap:var(--cm-space-xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border:0;border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap;background:0 0;display:inline-flex}.language-focus button:last-child{border-inline-end:0}.language-focus button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-orbit)}.language-focus button small{color:var(--cm-ink-3);font-size:inherit;font-variant-numeric:tabular-nums}@media (hover:hover) and (pointer:fine){.language-focus button:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.language-focus button[aria-pressed=true]:hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-toggle{align-items:center;gap:var(--cm-space-sm);border:0;grid-area:4/1/auto/-1;min-width:0;margin:0;padding:0;display:flex}.mode-toggle__label{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;flex:none}.mode-toggle__options{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);min-width:max-content;display:flex}.mode-toggle__options label{align-items:center;gap:var(--cm-space-2xs);min-width:44px;min-height:44px;padding-inline:var(--cm-space-sm);border-inline-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);display:inline-flex}.mode-toggle__options label:last-child{border-inline-end:0}.mode-toggle__options label:has(input:checked){background:var(--cm-orbit-low);color:var(--cm-orbit)}.mode-toggle__options input{width:1rem;height:1rem;accent-color:var(--cm-orbit);margin:0}@media (hover:hover) and (pointer:fine){.mode-toggle__options label:hover{background:var(--cm-ground-2);color:var(--cm-ink)}.mode-toggle__options label:has(input:checked):hover{background:var(--cm-orbit-low);color:var(--cm-orbit)}}.mode-gate{width:min(26rem, calc(100% - var(--cm-space-xl)));max-height:min(86%,30rem);padding:var(--cm-space-lg);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;margin:auto;overflow:auto}.mode-gate::backdrop{background:var(--cm-scrim)}.mode-gate h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin:0;font-style:normal;line-height:1.15}.mode-gate p{max-width:42ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.mode-gate__options{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg);display:grid}.mode-gate__options button{min-height:52px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;font:inherit;text-align:start;background:0 0;font-weight:600}.mode-gate__options button:last-child{border-block-end:0}@media (hover:hover) and (pointer:fine){.mode-gate__options button:hover{color:var(--cm-orbit)}}.map-stage{background:var(--cm-ground);min-width:0;max-width:100%;min-height:0;position:relative;overflow:clip}.galaxy-frame,.galaxy-canvas{z-index:var(--cm-z-base);position:absolute;inset:0}.galaxy-frame{overflow:hidden}.galaxy-canvas canvas{display:block}.keyboard-focus{max-width:min(34rem, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-sm) var(--cm-space-md);border-inline-start:2px solid var(--cm-orbit);background:var(--cm-ground-2);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);position:absolute;inset-block-end:var(--cm-space-md);inset-inline-start:var(--cm-space-md)}.orientation-bar{z-index:var(--cm-z-raised);gap:var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);pointer-events:none;flex-wrap:wrap;margin:0;display:flex;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-bar>*+:before{content:"· ";color:var(--cm-hairline)}.orientation-bar__charted{color:var(--cm-ink-2)}.index-sidebar{z-index:var(--cm-z-panel);width:var(--cm-sidebar-width);border-inline-end:1px solid var(--cm-hairline);background:var(--cm-ground-2);flex-direction:column;display:flex;position:absolute;inset-block:0;inset-inline-start:0}@media (width>=60rem){:is(.map-stage:has(.index-sidebar) .galaxy-frame,.map-stage:has(.index-sidebar) .map-view){inset-inline-start:var(--cm-sidebar-width)}:is(.map-stage:has(.index-sidebar) .orientation-bar,.map-stage:has(.index-sidebar) .orientation-copy){inset-inline-start:calc(var(--cm-sidebar-width) + var(--cm-space-md))}}.index-sidebar>header{justify-content:space-between;align-items:center;gap:var(--cm-space-sm);padding:var(--cm-space-sm) var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:flex}.index-sidebar h2{color:var(--cm-ink);font-size:var(--cm-text-sm);letter-spacing:.08em;text-transform:uppercase;margin:0}.index-sidebar>header button{border-radius:var(--cm-radius);min-width:32px;min-height:32px;color:var(--cm-ink-2);font-size:var(--cm-text-lg);cursor:pointer;background:0 0;border:1px solid #0000;line-height:1}.index-sidebar>header button:hover,.index-sidebar>header button:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar__scroll{flex:1;padding-block-end:var(--cm-space-lg);overflow-y:auto}.index-sidebar section{padding-block-start:var(--cm-space-sm)}.index-sidebar h3{padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-overflow:ellipsis;white-space:nowrap;margin:0;font-weight:400;overflow:hidden}.index-sidebar ul{margin:0;padding:0;list-style:none}.index-sidebar li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.index-sidebar li button span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.index-sidebar li button:hover,.index-sidebar li button:focus-visible{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.index-sidebar li button[aria-current=true]{border-inline-start-color:var(--cm-orbit);color:var(--cm-ink)}.index-sidebar li button[data-lit] span{color:var(--cm-star-high)}.index-sidebar li em{color:var(--cm-ink-3);font-size:var(--cm-text-xs);font-style:normal}.module-finder{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);width:min(34rem,92vw);max-height:70vh;color:var(--cm-ink);padding:0}.module-finder::backdrop{background:var(--cm-scrim)}.module-finder input{width:100%;padding:var(--cm-space-md);border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-base);background:0 0}.module-finder input:focus-visible{outline:2px solid var(--cm-orbit);outline-offset:-2px}.module-finder ul{max-height:50vh;padding:var(--cm-space-2xs) 0;margin:0;list-style:none;overflow-y:auto}.module-finder li button{align-items:baseline;gap:var(--cm-space-sm);width:100%;min-height:36px;padding:var(--cm-space-2xs) var(--cm-space-md);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-align:start;cursor:pointer;background:0 0;border:0;border-inline-start:2px solid #0000;display:flex}.module-finder li button[data-active]{border-inline-start-color:var(--cm-orbit);background:var(--cm-ground);color:var(--cm-ink)}.module-finder li strong{font-weight:400}.module-finder li small{color:var(--cm-ink-3);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.module-finder li em{color:var(--cm-star-high);font-style:normal}.module-finder__empty{padding:var(--cm-space-md);color:var(--cm-ink-3);font-size:var(--cm-text-sm);margin:0}.rail-action kbd{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin-inline-start:var(--cm-space-2xs)}.rail-action--toggle[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.orientation-copy{z-index:var(--cm-z-raised);max-width:min(28rem, calc(100% - var(--cm-space-lg)));pointer-events:none;position:absolute;inset-block-start:clamp(var(--cm-space-lg), 8vh, var(--cm-space-2xl));inset-inline-start:max(var(--cm-space-md), env(safe-area-inset-left))}.orientation-copy--system{inset-block-start:var(--cm-space-lg)}.orientation-copy h1,.study-preview h1,.load-state h1,.webgl-error h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;font-weight:700;line-height:1.08}.orientation-copy p,.study-preview p{max-width:55ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink-2)}.orientation-copy--inline{z-index:auto;pointer-events:auto;flex:none;max-block-size:45%;position:static;overflow-y:auto}.orientation-copy--inline h1{font-size:var(--cm-text-lg)}.orientation-copy--inline p{font-size:var(--cm-text-sm);margin-block-start:var(--cm-space-2xs)}.orientation-copy--inline .check-launch{margin-block-start:var(--cm-space-sm)}.check-launch,.check-primary,.check-close{border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground);min-height:44px;color:var(--cm-orbit);cursor:pointer;transition:background-color var(--cm-dur-quick) var(--cm-ease), color var(--cm-dur-quick) var(--cm-ease), transform .1s var(--cm-ease);font-weight:600}.check-launch{padding-inline:var(--cm-space-md);pointer-events:auto;margin-block-start:var(--cm-space-md);position:relative}.check-primary{padding-inline:var(--cm-space-lg);justify-self:start}.check-close{padding-inline:var(--cm-space-md);border-color:var(--cm-hairline);color:var(--cm-ink-2)}@media (hover:hover) and (pointer:fine){.check-launch:hover,.check-primary:hover,.check-close:hover{background:var(--cm-orbit-low);color:var(--cm-ink)}}.check-launch:active,.check-primary:active,.check-close:active{transform:translateY(1px)}.check-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.legend-toggle{z-index:var(--cm-z-sticky);min-height:32px;padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;position:absolute;inset-block-start:var(--cm-space-md);inset-inline-end:var(--cm-space-md)}.legend-toggle:hover,.legend-toggle:focus-visible{border-color:var(--cm-orbit);color:var(--cm-ink)}.legend-toggle[aria-expanded=true]{border-color:var(--cm-orbit);color:var(--cm-orbit)}.map-legend{z-index:var(--cm-z-raised);gap:var(--cm-space-2xs) var(--cm-space-md);max-height:min(60vh,30rem);padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);grid-template-columns:repeat(2,auto);display:none;position:absolute;inset-block-start:calc(var(--cm-space-md) + 40px);inset-inline-end:var(--cm-space-md);overflow-y:auto}.map-legend span{align-items:center;gap:var(--cm-space-sm);white-space:nowrap;display:inline-flex}.legend-dot{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:50%;display:inline-block}.legend-dot--dim{background:var(--cm-ink-3)}.legend-dot--lit{background:var(--cm-star-high)}.legend-dot--partial{background:var(--cm-route-possible)}.legend-route{width:var(--cm-space-md);border-block-start:1px solid var(--cm-ink-3)}.legend-route--possible{border-block-start-color:var(--cm-route-possible)}.partial-summary{border-inline-start:2px solid var(--cm-route-possible);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);color:var(--cm-ink)!important}.entrypoint-picker{z-index:var(--cm-z-panel);inset-inline:max(var(--cm-space-md), env(safe-area-inset-left));width:min(36rem, calc(100% - var(--cm-space-xl)));max-height:min(76%,42rem);padding:var(--cm-space-lg);border-block:1px solid var(--cm-hairline);background:var(--cm-ground-2);box-shadow:0 0 0 100vmax var(--cm-ground);color:var(--cm-ink);animation:entrypoint-enter var(--cm-dur-reveal) var(--cm-ease) both;margin-inline:auto;position:absolute;inset-block-start:50%;overflow:auto;transform:translateY(-50%)}.entrypoint-picker>p:first-child{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);margin:0}.entrypoint-picker h1{margin:var(--cm-space-sm) 0 0;overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);line-height:1.1}.entrypoint-picker>p:not(:first-child){margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.entrypoint-candidates{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.entrypoint-candidates button{gap:var(--cm-space-xs);width:100%;min-height:58px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.entrypoint-candidates button span{overflow-wrap:anywhere;font-family:var(--cm-font-mono)}.entrypoint-candidates button small{color:var(--cm-ink-3);font-family:var(--cm-font-mono)}@media (hover:hover) and (pointer:fine){.entrypoint-candidates button:hover{color:var(--cm-orbit)}}.entrypoint-continue{min-height:44px;color:var(--cm-ink-2);cursor:pointer;text-underline-offset:3px;background:0 0;border:0;margin-block-start:var(--cm-space-lg);padding:0;text-decoration:underline}.entrypoint-error{color:var(--cm-error)!important}.illumination-pulse{z-index:var(--cm-z-raised);color:var(--cm-star);pointer-events:none;animation:illumination-pulse .42s var(--cm-ease) both;justify-items:center;display:grid;position:absolute;inset-block-start:50%;inset-inline-start:25%;transform:translate(-50%,-50%)}.illumination-pulse span{filter:drop-shadow(0 0 18px var(--cm-star));font-size:clamp(3rem,8vw,6rem);line-height:1}.illumination-pulse strong{color:var(--cm-ink);font-family:var(--cm-font-display)}.structural-summary p{max-width:62ch;margin:var(--cm-space-sm) 0 0;color:var(--cm-ink)}.mini-constellation{width:100%;max-width:22rem;height:auto;margin-block-start:var(--cm-space-md)}.mini-constellation line{stroke:var(--cm-hairline);stroke-width:1px}.mini-constellation circle{fill:var(--cm-ink-3)}.mini-constellation__self{fill:var(--cm-orbit)}.connections h3{margin:var(--cm-space-lg) 0 0;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em;font-weight:500}.connection-list{margin:var(--cm-space-xs) 0 0;border-block-start:1px solid var(--cm-hairline);padding:0;list-style:none}.connection-list button{gap:var(--cm-space-2xs);width:100%;min-height:52px;padding:var(--cm-space-sm) 0;border:0;border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink);cursor:pointer;text-align:start;background:0 0;display:grid}.connection-name{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.connection-meta{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}@media (hover:hover) and (pointer:fine){.connection-list button:hover .connection-name{color:var(--cm-orbit)}}.load-state .check-primary,.study-notice .check-primary{justify-self:start;margin-block-start:var(--cm-space-md)}.study-preview{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:72%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.check-panel{z-index:var(--cm-z-panel);width:100%;min-width:0;max-width:100%;max-height:76%;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-lg), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground-2);color:var(--cm-ink);animation:panel-enter var(--cm-dur-reveal) var(--cm-ease) both;position:absolute;inset-block-end:0;inset-inline:0;overflow:auto}.check-panel__header{justify-content:space-between;align-items:start;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-lg);display:flex}.check-panel__header p,.check-panel__header h1{margin:0}.check-panel__header p,.check-progress span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-panel__header h1{overflow-wrap:anywhere;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);margin-block-start:var(--cm-space-xs);line-height:1.1}.check-loading,.check-state,.check-complete,.active-check{margin-block-start:var(--cm-space-lg)}.check-loading,.check-state p,.check-complete p,.active-check fieldset>p{max-width:60ch;color:var(--cm-ink-2)}.check-state h2,.check-complete h2{font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0}.check-state p,.check-complete p{margin:var(--cm-space-sm) 0 0}.check-complete{gap:var(--cm-space-sm);display:grid}.check-complete__star{color:var(--cm-star);font-size:var(--cm-text-display);line-height:1}.check-progress{align-items:center;gap:var(--cm-space-md);grid-template-columns:auto minmax(5rem,1fr);margin-block-end:var(--cm-space-xl);display:grid}.check-progress progress{background:var(--cm-hairline);width:100%;height:2px;color:var(--cm-star);border:0}.check-progress progress::-webkit-progress-bar{background:var(--cm-hairline)}.check-progress progress::-webkit-progress-value{background:var(--cm-star)}.check-progress progress::-moz-progress-bar{background:var(--cm-star)}.active-check{gap:var(--cm-space-lg);display:grid}.active-check fieldset{border:0;min-width:0;margin:0;padding:0}.active-check legend{overflow-wrap:anywhere;max-width:28ch;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);padding:0;font-weight:700;line-height:1.15}.active-check fieldset>p{margin:var(--cm-space-sm) 0 0}.check-options{border-block-start:1px solid var(--cm-hairline);margin-block-start:var(--cm-space-lg)}.check-options label{align-items:center;gap:var(--cm-space-md);min-height:52px;padding-block:var(--cm-space-sm);border-block-end:1px solid var(--cm-hairline);color:var(--cm-ink-2);cursor:pointer;grid-template-columns:auto minmax(0,1fr);display:grid}.check-options label:has(input:checked){color:var(--cm-ink)}.check-options input{width:1rem;height:1rem;accent-color:var(--cm-star);margin:0}.check-options span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm)}.check-feedback{gap:var(--cm-space-xs);padding:var(--cm-space-md);border-inline-start:2px solid var(--cm-error);background:var(--cm-ground);color:var(--cm-ink-2);display:grid}.check-feedback strong{color:var(--cm-ink)}.check-feedback span{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.check-affirmation{align-items:baseline;gap:var(--cm-space-xs);margin:0 0 var(--cm-space-lg);border-inline-start:2px solid var(--cm-star);color:var(--cm-star-high);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);padding-inline-start:var(--cm-space-sm);display:flex}.study-preview__path{font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);color:var(--cm-orbit)!important}.study-preview__header{display:block}.study-preview dl{gap:var(--cm-space-md);margin:var(--cm-space-lg) 0 0;grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.study-preview dl div{border-block-start:1px solid var(--cm-hairline);padding-block-start:var(--cm-space-sm)}.study-preview dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.study-preview dd{margin:var(--cm-space-2xs) 0 0;font-variant-numeric:tabular-nums}.study-content{gap:var(--cm-space-xl);min-width:0;margin-block-start:var(--cm-space-xl);display:grid}.study-content>*{min-width:0}.study-section-heading{justify-content:space-between;align-items:center;gap:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);padding-block-end:var(--cm-space-sm);display:flex}.study-section-heading h2,.study-notice h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal;line-height:1.15}.study-section-heading span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:nowrap}.source-code{width:100%;min-width:0;max-height:22rem;margin:var(--cm-space-md) 0 0;padding:var(--cm-space-sm) 0;border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);counter-reset:source-line;font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);tab-size:4;line-height:1.65;list-style:none;overflow:auto}.source-code li{min-width:max-content;padding-inline:var(--cm-space-sm) var(--cm-space-md);grid-template-columns:3.25rem minmax(0,1fr);display:grid}.source-code li:before{content:attr(data-line);color:var(--cm-ink-3);text-align:end;-webkit-user-select:none;user-select:none;padding-inline-end:var(--cm-space-md)}.source-code li:target{background:var(--cm-orbit-low)}.source-code code{font:inherit;white-space:pre}.grounded-explanation>p,.study-notice p,.study-loading,.evidence-list p{max-width:65ch;color:var(--cm-ink-2)}.grounded-explanation>p,.study-notice p,.study-loading{margin:var(--cm-space-md) 0 0}.grounded-explanation h3{margin:var(--cm-space-lg) 0 var(--cm-space-sm);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.source-citation{color:var(--cm-orbit);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);text-underline-offset:2px;text-decoration-thickness:1px}.source-citation:active{color:var(--cm-ink)}@media (hover:hover) and (pointer:fine){.source-citation:hover{color:var(--cm-ink)}}.source-citation--button{cursor:pointer;background:0 0;border:0;padding:0}.source-citation--button:disabled{color:var(--cm-ink-3);cursor:not-allowed}.evidence-list{gap:var(--cm-space-sm);margin:0;padding:0;list-style:none;display:grid}.evidence-list li,.study-notice{padding:var(--cm-space-md);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground)}.evidence-list p{margin:0 0 var(--cm-space-xs)}.evidence-list strong{overflow-wrap:anywhere;font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);margin-block-end:var(--cm-space-xs);display:block}.lens-notes{margin-block-start:var(--cm-space-sm);display:grid}.lens-note{gap:var(--cm-space-sm);min-width:0;padding-block:var(--cm-space-md);border-block-end:1px solid var(--cm-hairline);display:grid}.lens-note h3{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base);font-style:normal}.lens-note p{max-width:65ch;margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.lens-note code{min-width:0;padding:var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);white-space:pre;display:block;overflow-x:auto}.star-chart-screen{min-width:0;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-xl) max(var(--cm-space-md), env(safe-area-inset-left));background:var(--cm-ground);overflow:auto}.star-chart-intro{max-width:72rem;margin-inline:auto;padding-block-end:var(--cm-space-xl);display:block}.star-chart-intro>p:first-child{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro h1{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-display);letter-spacing:-.035em;margin:0;font-style:normal;line-height:1.08}.star-chart-intro>p:not(:first-child){max-width:65ch;margin:var(--cm-space-md) 0 0;color:var(--cm-ink-2)}.star-chart-intro dl{gap:var(--cm-space-md);margin:var(--cm-space-xl) 0 0;padding-block:var(--cm-space-md);border-block:1px solid var(--cm-hairline);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.star-chart-intro dt,.concept-row dt{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.star-chart-intro dd{margin:var(--cm-space-xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);font-variant-numeric:tabular-nums}.concept-ledger{border-block-start:1px solid var(--cm-hairline);max-width:72rem;margin-inline:auto}.concept-row{align-items:center;gap:var(--cm-space-lg);min-width:0;padding-block:var(--cm-space-lg);border-block-end:1px solid var(--cm-hairline);grid-template-columns:minmax(10rem,.7fr) minmax(8rem,1.2fr) auto;display:grid}.concept-row h2{overflow-wrap:anywhere;min-width:0;font-family:var(--cm-font-display);font-size:var(--cm-text-lg);margin:0;font-style:normal}.concept-row>div:first-child>span{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.concept-meter{background:var(--cm-hairline);height:2px;overflow:hidden}.concept-meter span{background:var(--cm-star);height:100%;display:block}.concept-row dl{align-items:center;gap:var(--cm-space-lg);margin:0;display:flex}.concept-row dl div{min-width:5rem}.concept-row dd{margin:var(--cm-space-xs) 0 0;font-variant-numeric:tabular-nums}.status-line{z-index:var(--cm-z-sticky);justify-content:space-between;gap:var(--cm-space-2xs) var(--cm-space-md);min-width:0;max-width:100%;padding:var(--cm-space-sm) max(var(--cm-space-md), env(safe-area-inset-right)) max(var(--cm-space-sm), env(safe-area-inset-bottom)) max(var(--cm-space-md), env(safe-area-inset-left));border-block-start:1px solid var(--cm-hairline);background:var(--cm-ground);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);font-variant-numeric:tabular-nums;flex-wrap:wrap;display:flex;position:relative}.status-line span{white-space:normal}.load-state,.webgl-error{align-content:center;gap:var(--cm-space-md);min-height:100dvh;padding:var(--cm-space-lg);background:var(--cm-ground);color:var(--cm-ink);display:grid}.load-state p,.webgl-error p{max-width:65ch;color:var(--cm-ink-2);margin:0}@keyframes panel-enter{0%{opacity:0;transform:translateY(var(--cm-space-md))}to{opacity:1;transform:translateY(0)}}@keyframes entrypoint-enter{0%{opacity:0;transform:translateY(calc(-50% + var(--cm-space-md)))}to{opacity:1;transform:translateY(-50%)}}@keyframes illumination-pulse{0%{opacity:0;transform:translate(-50%,-50%)scale(.75)}45%{opacity:1;transform:translate(-50%,-50%)scale(1.08)}to{opacity:0;transform:translate(-50%,-50%)scale(1)}}@media (width>=40rem){.instrument-rail{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr)}.location{text-align:center;grid-area:1/2}.rail-action,.home-readout{justify-self:end}.rail-actions{grid-area:1/3}.rail-controls{grid-row:2;justify-self:center}.status-line span{white-space:nowrap}.lens-note{gap:var(--cm-space-lg);grid-template-columns:minmax(8rem,.35fr) minmax(0,1fr)}.study-preview{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(48rem,60%);max-height:none;inset-block:0;inset-inline-start:auto}.check-panel{border-block-start:0;border-inline-start:1px solid var(--cm-hairline);width:min(42rem,56%);max-height:none;inset-block:0;inset-inline-start:auto}}@media (width<=48rem){.illumination-pulse{inset-block-start:35%;inset-inline-start:50%}.star-chart-intro dl{grid-template-columns:1fr}.concept-row{gap:var(--cm-space-md);grid-template-columns:1fr}.concept-row dl{justify-content:space-between}}@media (width>=60rem){.map-legend:not([hidden]){display:grid}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition-duration:.15s!important;animation-duration:.15s!important;animation-iteration-count:1!important}.study-preview,.check-panel,.mode-gate{animation-name:panel-enter-reduced}.entrypoint-picker{animation-name:entrypoint-enter-reduced}.illumination-pulse{animation-name:illumination-pulse-reduced}}@keyframes panel-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes entrypoint-enter-reduced{0%{opacity:0}to{opacity:1}}@keyframes illumination-pulse-reduced{0%{opacity:0}50%{opacity:1}to{opacity:0}}.picker-screen{gap:var(--cm-space-lg);min-height:100vh;padding:var(--cm-space-2xl) var(--cm-space-xl);flex-direction:column;max-width:44rem;margin:0 auto;display:flex}.picker-wordmark{font-family:var(--cm-font-display);font-size:var(--cm-text-sm);letter-spacing:.2em;text-transform:uppercase;color:var(--cm-ink-3)}.picker-subtitle{color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.picker-recents ul,.picker-browser ul{margin:var(--cm-space-sm) 0 0;gap:var(--cm-space-2xs);flex-direction:column;padding:0;list-style:none;display:flex}.picker-recents button,.picker-browser ul button{justify-content:space-between;gap:var(--cm-space-sm);width:100%;padding:var(--cm-space-xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);text-align:left;cursor:pointer;display:flex}.picker-recents button:hover,.picker-recents button:focus-visible,.picker-browser ul button:hover,.picker-browser ul button:focus-visible{border-color:var(--cm-orbit)}.picker-recents button{flex-wrap:wrap}.picker-recent-path{overflow-wrap:anywhere;min-width:0}.picker-recent-lit{color:var(--cm-star);white-space:nowrap}.picker-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2);overflow-wrap:anywhere}.picker-scale,.picker-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-error{color:var(--cm-error)}.picker-select{padding:var(--cm-space-xs) var(--cm-space-lg);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-base);cursor:pointer;align-self:flex-start}.picker-select:disabled{opacity:.6;cursor:progress}.layer-switcher{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);display:inline-flex;overflow:hidden}.layer-switcher button{padding:var(--cm-space-2xs) var(--cm-space-sm);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.layer-switcher button[aria-pressed=true]{background:var(--cm-orbit-low);color:var(--cm-ink)}.map-view{gap:var(--cm-space-sm);padding:var(--cm-space-md);background:var(--cm-ground);flex-direction:column;display:flex;position:absolute;inset:0;overflow:hidden}.map-tabs{gap:var(--cm-space-xs);flex:none;display:flex}.map-tabs button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.map-tabs button[aria-pressed=true]{border-color:var(--cm-orbit);color:var(--cm-ink)}.map-canvas{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative}.map-zoom{z-index:var(--cm-z-raised);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);background:var(--cm-ground-2);gap:1px;display:flex;position:absolute;inset-block-start:var(--cm-space-sm);inset-inline-end:var(--cm-space-sm)}.map-zoom button{min-width:34px;min-height:30px;color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);cursor:pointer;background:0 0;border:0}.map-zoom button:hover:not(:disabled),.map-zoom button:focus-visible{color:var(--cm-orbit)}.map-zoom button:disabled{color:var(--cm-ink-3);cursor:default}.map-scroll{cursor:grab;flex:auto;overflow:auto}.map-scroll[data-panning]{cursor:grabbing;-webkit-user-select:none;user-select:none}.map-canvas__sized{min-width:100%}.architecture-map,.workflow-tree{min-height:0;display:block}.architecture-map__edges path{color:var(--cm-hairline);stroke:currentColor;fill:none;stroke-linecap:round;stroke-linejoin:round}.architecture-map__edges path.is-cycle{color:var(--cm-route-possible)}.architecture-map__arrow{color:var(--cm-hairline)}.architecture-map__arrow.is-cycle{color:var(--cm-route-possible)}.workflow-tree__edges path{stroke:var(--cm-hairline);stroke-width:1.2px;fill:none}.architecture-map__box rect{fill:var(--cm-ground-2);stroke:var(--cm-hairline)}.architecture-map__box .box-tint{stroke:none}.architecture-map__box text{fill:var(--cm-ink);font-family:var(--cm-font-mono);font-size:13px}.architecture-map__box .box-meta{fill:var(--cm-ink-3);font-size:11px}.architecture-map__box[data-partial=true] rect:first-of-type{stroke:var(--cm-route-possible)}.architecture-map__box .box-partial{fill:var(--cm-route-possible);stroke:none}.architecture-map__box[data-understood=true] rect:first-of-type{stroke:var(--cm-star-high)}.architecture-map__box[data-home=true] rect:first-of-type{stroke-width:2px}.architecture-map__box[data-reachable=false] rect:first-of-type{stroke-dasharray:4 3}.architecture-map__box:focus-visible rect:first-of-type,.workflow-tree__row:focus-visible circle{outline:2px solid var(--cm-orbit);outline-offset:2px}.architecture-map__box,.workflow-tree__row{cursor:pointer}.workflow-tree__row circle{fill:var(--cm-ink-3)}.workflow-tree__row[data-partial=true] circle,.workflow-tree__row[data-cut] circle{fill:var(--cm-route-possible)}.workflow-tree__row[data-understood=true] circle{fill:var(--cm-star-high)}.workflow-tree__row text{fill:var(--cm-ink);font-family:var(--cm-font-mono);font-size:13px}.workflow-tree__row .row-meta{fill:var(--cm-ink-3);font-size:11px}.architecture-map__box[data-selected=true] rect:first-of-type{outline:2px solid var(--cm-orbit);outline-offset:3px}.workflow-tree__row[data-selected=true] circle{stroke:var(--cm-orbit);stroke-width:2px}.map-note,.map-loading{color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);flex:none;margin:0}.map-state{text-align:center;max-width:46ch;color:var(--cm-ink-2);margin:auto}.hint-chip{z-index:var(--cm-z-raised);align-items:center;gap:var(--cm-space-sm);padding:var(--cm-space-sm) var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);font-size:var(--cm-text-sm);display:flex;position:absolute;inset-block-end:var(--cm-space-md);inset-inline-start:var(--cm-space-md)}.hint-chip small{color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.hint-chip button{padding:var(--cm-space-2xs) var(--cm-space-sm);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-orbit);font-size:var(--cm-text-xs);cursor:pointer;background:0 0}.location button{color:var(--cm-orbit);font:inherit;cursor:pointer;background:0 0;border:0;padding:0}.location button[disabled]{color:var(--cm-ink-2);cursor:default}.location button:not([disabled]):hover{text-decoration:underline}.coach-marks{inset-block:auto var(--cm-space-lg);width:min(38ch, calc(100% - var(--cm-space-lg)));padding:var(--cm-space-md);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);background:var(--cm-ground-2);color:var(--cm-ink);margin-inline:auto;inset-inline:0}.coach-marks::backdrop{background:var(--cm-scrim)}.coach-marks__progress{margin:0 0 var(--cm-space-2xs);color:var(--cm-ink-3);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs)}.coach-marks h1{margin:0 0 var(--cm-space-xs);font-size:var(--cm-text-lg)}.coach-marks__actions{justify-content:space-between;gap:var(--cm-space-sm);margin-block-start:var(--cm-space-md);display:flex}.coach-skip{color:var(--cm-ink-3);cursor:pointer;background:0 0;border:0}.legend-tint{width:var(--cm-space-sm);height:var(--cm-space-sm);border-radius:2px;display:inline-block}.legend-tint--python{background:var(--cm-neb-python)}.legend-tint--javascript{background:var(--cm-neb-js)}.legend-tint--typescript{background:var(--cm-neb-ts)}.legend-route--dashed{border-block-start-style:dashed}.legend-size{width:var(--cm-space-md);height:var(--cm-space-sm);background:var(--cm-ink-3);border-radius:50%;display:inline-block}.legend-brightness{width:var(--cm-space-md);height:var(--cm-space-sm);background:linear-gradient(90deg, var(--cm-node-unlit), var(--cm-ink-2));display:inline-block}.app-shell[data-mode=easy]{--cm-text-xs:.8125rem;--cm-text-sm:.9375rem;--cm-text-base:1.125rem;--cm-text-lg:1.375rem;--cm-space-sm:1rem;--cm-space-md:1.375rem;--cm-space-lg:2.5rem;font-size:var(--cm-text-base);line-height:1.7}.app-shell[data-mode=easy] .orientation-copy p,.app-shell[data-mode=easy] .study-preview p,.app-shell[data-mode=easy] .grounded-explanation>p,.app-shell[data-mode=easy] .study-notice p,.app-shell[data-mode=easy] .evidence-list p,.app-shell[data-mode=easy] .lens-note p,.app-shell[data-mode=easy] .active-check fieldset>p,.app-shell[data-mode=easy] .check-state p,.app-shell[data-mode=easy] .check-complete p,.app-shell[data-mode=easy] .check-loading{max-width:46ch}.app-shell[data-mode=easy] .language-focus__label,.app-shell[data-mode=easy] .mode-toggle__label{text-transform:none;letter-spacing:normal}.loading-screen{gap:var(--cm-space-md);max-width:44rem;min-height:100vh;padding:var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-right)) var(--cm-space-lg) max(var(--cm-space-md), env(safe-area-inset-left));align-content:center;justify-items:start;margin:0 auto;display:grid}.loading-header h1{min-width:0;margin:var(--cm-space-2xs) 0 0;font-family:var(--cm-font-display);font-size:var(--cm-text-xl);overflow-wrap:anywhere;line-height:1.15}.loading-path{font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);color:var(--cm-ink-2)}.loading-subtitle{margin:var(--cm-space-xs) 0 0;color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-stages{gap:var(--cm-space-2xs);width:100%;margin:0;padding:0;list-style:none;display:grid}.loading-stages li{justify-content:space-between;gap:var(--cm-space-sm);padding:var(--cm-space-xs) var(--cm-space-sm);border-left:2px solid var(--cm-hairline);color:var(--cm-ink-3);font-size:var(--cm-text-sm);flex-wrap:wrap;display:flex}.loading-stages li[data-state=active]{border-left-color:var(--cm-orbit);color:var(--cm-ink)}.loading-stages li[data-state=done]{border-left-color:var(--cm-orbit-deep);color:var(--cm-ink-2)}.loading-stages small{font-family:var(--cm-font-mono);color:var(--cm-ink-2)}.loading-meter{width:100%;height:var(--cm-space-xs);accent-color:var(--cm-orbit)}.loading-live{color:var(--cm-ink);font-size:var(--cm-text-sm)}.loading-error{border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);width:100%;padding:var(--cm-space-sm);color:var(--cm-ink-2);font-size:var(--cm-text-sm)}.loading-actions{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.loading-actions button{padding:var(--cm-space-xs) var(--cm-space-md)}.picker-scale h2,.picker-failure h2{margin:0 0 var(--cm-space-xs);font-family:var(--cm-font-display);font-size:var(--cm-text-base)}.picker-scale-scopes{gap:var(--cm-space-xs);margin:var(--cm-space-sm) 0;flex-wrap:wrap;padding:0;list-style:none;display:flex}.picker-scale-scopes button{align-items:flex-start;gap:var(--cm-space-2xs);min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-sm);background:var(--cm-ground-2);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);cursor:pointer;flex-direction:column;display:flex}.picker-scale-scopes button:hover:not(:disabled),.picker-scale-scopes button:focus-visible{border-color:var(--cm-orbit)}.picker-scale-scopes button:disabled{opacity:.6;cursor:progress}.picker-scale-scopes small{color:var(--cm-ink-2)}.picker-path-entry{gap:var(--cm-space-xs);flex-wrap:wrap;align-items:center;display:flex}.picker-path-entry label{color:var(--cm-ink-2)}.picker-path-entry input{min-width:0;min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-xs);background:var(--cm-ground);border:1px solid var(--cm-hairline);border-radius:var(--cm-radius);color:var(--cm-ink);font-family:var(--cm-font-mono);font-size:var(--cm-text-sm);flex:14rem}.picker-path-entry button{min-height:44px;padding:var(--cm-space-2xs) var(--cm-space-md);background:var(--cm-orbit-low);border:1px solid var(--cm-orbit);border-radius:var(--cm-radius);color:var(--cm-ink);font-size:var(--cm-text-sm);cursor:pointer}.picker-path-entry button:disabled{opacity:.6;cursor:not-allowed}.picker-failure{border:1px solid var(--cm-error);border-radius:var(--cm-radius);padding:var(--cm-space-sm);font-size:var(--cm-text-sm)}.picker-failure>p{margin:0 0 var(--cm-space-sm);color:var(--cm-ink-2)}.picker-failure__detail{gap:var(--cm-space-2xs);display:grid}.picker-failure__detail span{color:var(--cm-ink-3);font-size:var(--cm-text-xs);text-transform:uppercase;letter-spacing:.08em}.picker-failure__detail code{max-height:8rem;padding:var(--cm-space-xs);background:var(--cm-ground-2);border-radius:var(--cm-radius);color:var(--cm-ink-2);font-family:var(--cm-font-mono);font-size:var(--cm-text-xs);overflow-wrap:anywhere;display:block;overflow:auto}.picker-failure .picker-select{min-height:44px;font-size:var(--cm-text-sm);align-self:flex-start}.progress-reset{align-items:center;gap:var(--cm-space-sm);max-width:72rem;margin:var(--cm-space-lg) auto 0;padding-top:var(--cm-space-md);border-top:1px solid var(--cm-hairline);flex-wrap:wrap;display:flex}.progress-reset p{color:var(--cm-ink-2);font-size:var(--cm-text-sm);margin:0}.progress-reset button{min-height:44px;padding-inline:var(--cm-space-md);font-size:var(--cm-text-sm)}.progress-reset--confirming{justify-items:start;gap:var(--cm-space-sm);display:grid}.progress-reset--confirming>p[role=alert]{max-width:60ch;color:var(--cm-ink)}.progress-reset--confirming>div{gap:var(--cm-space-sm);flex-wrap:wrap;display:flex}.progress-reset__confirm{border-color:var(--cm-error);color:var(--cm-error)}.progress-reset__error{color:var(--cm-error)} diff --git a/codemble/web_dist/index.html b/codemble/web_dist/index.html index 399131a..a7bde98 100644 --- a/codemble/web_dist/index.html +++ b/codemble/web_dist/index.html @@ -9,8 +9,8 @@ content="Explore the parser-proven structure of your local project with Codemble." /> Codemble · Your code, mapped - - + +
diff --git a/docs-site/package.json b/docs-site/package.json index 48a5abf..ee5a05f 100644 --- a/docs-site/package.json +++ b/docs-site/package.json @@ -1,7 +1,7 @@ { "name": "codemble-docs", "type": "module", - "version": "0.6.0", + "version": "0.6.1", "private": true, "scripts": { "dev": "astro dev", diff --git a/docs-site/src/content/docs/star-chart.md b/docs-site/src/content/docs/star-chart.md index d12cff9..93b7aae 100644 --- a/docs-site/src/content/docs/star-chart.md +++ b/docs-site/src/content/docs/star-chart.md @@ -39,6 +39,10 @@ In a mixed project, the chart follows the current language focus. This changes only the rows and session counts you are viewing; the underlying project graph and persisted understanding remain intact when you return to **All**. +**Modules** and **Find** remain available while the chart is open. The module +index opens beside the chart, and `⌘K` / `Ctrl-K` opens the same project-wide +finder used by the Map and Galaxy, including modules not yet charted. + "Studied" counts the structures you have opened **in this session** and resets when you reload — that is deliberate. Opening a file is not evidence that you understood it, so only "Understood", which comes from passing graph-derived diff --git a/docs-site/src/content/docs/the-galaxy.md b/docs-site/src/content/docs/the-galaxy.md index d9e41b1..92d8fb2 100644 --- a/docs-site/src/content/docs/the-galaxy.md +++ b/docs-site/src/content/docs/the-galaxy.md @@ -64,13 +64,19 @@ lit state — not a faster animation, none at all. Keyboard focus carries a visible reticle in the 3D scene as well as a live text readout, so arrow-key navigation is never a guess about where you are. -## Semantic zoom, not free flight +## Bounded orbit, not free flight -Free-flight 3D looks fun in demos and is where comprehension goes to die. -Codemble's camera moves on rails between three levels — galaxy for orientation, -system for structure, study for learning — with scripted fly-to transitions. -Reading never happens "in space": the study panel takes the foreground, and the -sky behind it recedes to the structure you are reading and its connections. +Drag to orbit the current subject and use the wheel to zoom. Panning is off, +distance and polar angle are clamped for each level, and clicking a node moves +between galaxy, system, and study with a scripted transition. The parser owns +every node position, so nodes do not drag away from the graph. Reading never +happens "in space": the study panel takes the foreground, and the sky behind it +recedes to the structure you are reading and its connections. + +At narrow widths the header's secondary actions live behind **Menu**, guidance +occupies its own row below the stage, and Study becomes a full-stage scrolling +sheet. The map/canvas and the local-only status remain in the viewport instead +of being squeezed behind controls. ## Two layers, one truth @@ -139,3 +145,7 @@ works whether you started from the picker or passed a path. least one candidate. The Home you choose is remembered for the next run of the same project, and a saved choice the parser no longer ranks is dropped rather than restored. + +On a first run with more than one honest Home candidate, Codemble asks for your +audience first, then Home, then opens the three-step coach. Those decisions do +not stack on top of one another. diff --git a/docs/releases/v0.6.1.md b/docs/releases/v0.6.1.md new file mode 100644 index 0000000..0a084bf --- /dev/null +++ b/docs/releases/v0.6.1.md @@ -0,0 +1,39 @@ +# Codemble v0.6.1 — the complete loop at every width + +v0.6.1 closes every verified finding from the 2026-07-21 user-flow audit. It is +a focused usability and reliability release; parser, graph, checks, +persistence, local-first behavior, and the Formal Edo visual identity are +unchanged. + +## Highlights + +- The full map-to-study loop now remains usable at 320 px. Secondary actions + collapse into a keyboard-accessible Menu, the Map auto-fits only after its + real dimensions settle, guidance no longer covers its controls, and Study + owns the complete reading stage. +- Modules and Find are genuinely global: both render immediately from the Star + chart and close without leaving latent UI state behind. +- First-run decisions are sequenced as audience, required Home calibration, + then coach marks. +- The 3D graph is explicitly non-draggable. This matches the parser-owned layout + contract and removes a dependency-level mouse/touch pointer collision that + could throw after a canvas click. + +## Verification + +- Python tests and Ruff +- Web contract suite and production SPA build +- Documentation validation and production build +- Real bundled-app browser checks at 1280×900 and 320×800 +- Repeated empty-canvas clicks, node travel into Study, Star-chart Modules and + Find, first-run audience/Home/coach order, horizontal overflow, and console + errors +- Wheel/sdist build, clean `uvx` install, Graphify refresh, CI, Pages, GitHub + release assets, and PyPI publication + +## Known limits + +- The 3D Galaxy still requires WebGL; the parser-backed Map remains the fallback. +- Progress stays local to the machine, and Star-chart Studied counts remain + session-only by design. +- The Phase 1 milestone still requires human tester evidence in issue #13. diff --git a/pyproject.toml b/pyproject.toml index c52e4c0..ee10174 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "codemble" -version = "0.6.0" +version = "0.6.1" description = "A learning game that turns the code AI wrote for you into a galaxy you light up by understanding it." readme = "README.md" license = "Apache-2.0" diff --git a/web/package-lock.json b/web/package-lock.json index 8bfebde..ff602c9 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "codemble-web", - "version": "0.6.0", + "version": "0.6.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codemble-web", - "version": "0.6.0", + "version": "0.6.1", "dependencies": { "@fontsource/jetbrains-mono": "5.2.8", "@fontsource/shippori-mincho": "^5.3.0", diff --git a/web/package.json b/web/package.json index 4e933be..a42a663 100644 --- a/web/package.json +++ b/web/package.json @@ -1,12 +1,12 @@ { "name": "codemble-web", "private": true, - "version": "0.6.0", + "version": "0.6.1", "type": "module", "scripts": { "dev": "vite", "build": "vite build", - "check": "node scripts/check_graph_data.mjs && node scripts/check_name_atlas.mjs && node scripts/check_project_mapping.mjs && node scripts/check_learner_projection.mjs && node scripts/check_learner_session.mjs && vite build", + "check": "node scripts/check_graph_data.mjs && node scripts/check_name_atlas.mjs && node scripts/check_project_mapping.mjs && node scripts/check_learner_projection.mjs && node scripts/check_learner_session.mjs && node scripts/check_orbit_pointer_guard.mjs && vite build", "benchmark:projection": "node scripts/benchmark_learner_projection.mjs" }, "dependencies": { diff --git a/web/scripts/check_orbit_pointer_guard.mjs b/web/scripts/check_orbit_pointer_guard.mjs new file mode 100644 index 0000000..0033ba0 --- /dev/null +++ b/web/scripts/check_orbit_pointer_guard.mjs @@ -0,0 +1,34 @@ +import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; + +import { clearStaleNonTouchPointers } from "../src/orbitPointerGuard.js"; + +const empty = { _pointers: [], _pointerPositions: {} }; +assert.equal(clearStaleNonTouchPointers(empty, { pointerType: "mouse" }), false); + +const touch = { _pointers: [4, 7], _pointerPositions: { 4: { x: 1 }, 7: { x: 2 } } }; +assert.equal(clearStaleNonTouchPointers(touch, { pointerType: "touch" }), false); +assert.deepEqual(touch._pointers, [4, 7]); + +const stalePointers = [3, 9]; +const stalePositions = { 3: { x: 20, y: 30 } }; +const mouse = { _pointers: stalePointers, _pointerPositions: stalePositions }; +assert.equal(clearStaleNonTouchPointers(mouse, { pointerType: "mouse" }), true); +assert.equal(mouse._pointers, stalePointers, "mutate OrbitControls' collection in place"); +assert.deepEqual(mouse._pointers, []); +assert.deepEqual(mouse._pointerPositions, {}); + +const pen = { _pointers: [11], _pointerPositions: {} }; +assert.equal(clearStaleNonTouchPointers(pen, { pointerType: "pen" }), true); +assert.deepEqual(pen._pointers, []); + +assert.equal(clearStaleNonTouchPointers({}, { pointerType: "mouse" }), false); + +const galaxySource = readFileSync(new URL("../src/GalaxyCanvas.jsx", import.meta.url), "utf8"); +assert.match( + galaxySource, + /\.enableNodeDrag\(false\)/, + "the immutable graph must not install 3d-force-graph drag controls", +); + +console.log("orbit pointer guard contract: ok"); diff --git a/web/src/App.jsx b/web/src/App.jsx index 72ec4f8..51e3188 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -26,6 +26,8 @@ import { import { PARSE_STAGES } from "./projectMapping.js"; export function App() { + const mobileMenuRef = useRef(null); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const session = useMemo( () => createLearnerSession({ adapter: createHttpLearnerSessionAdapter() }), [], @@ -241,102 +243,147 @@ export function App() { )} -
+
{ + if (event.key === "Escape" && mobileMenuOpen) { + event.preventDefault(); + setMobileMenuOpen(false); + mobileMenuRef.current?.focus(); + } + }} + > - - {showChart ? ( - - ) : level !== LEVELS.GALAXY ? ( - - ) : ( - - )} - {graph.entrypoint_candidates.length ? ( - - ) : null} - session.dispatch({ type: "RESET_PROJECT" })} /> -
-
- {/* A view preference over the immutable graph, exactly like language - focus: it changes how much sky is drawn, never what the parser - found. Galaxy-only, because reveal is a galaxy affordance. */} - {layer === "galaxy" ? ( - - ) : null} - session.dispatch({ type: "SET_LAYER", layer: next })} - /> - - session.dispatch({ type: "SET_LANGUAGE_FOCUS", language }) - } - /> - session.dispatch({ type: "SET_MODE", mode: nextMode })} - /> +
+ + + {showChart ? ( + + ) : level !== LEVELS.GALAXY ? ( + + ) : ( + + )} + {graph.entrypoint_candidates.length ? ( + + ) : null} + session.dispatch({ type: "RESET_PROJECT" })} /> +
+
+ {/* A view preference over the immutable graph, exactly like language + focus: it changes how much sky is drawn, never what the parser + found. Galaxy-only, because reveal is a galaxy affordance. */} + {layer === "galaxy" ? ( + + ) : null} + session.dispatch({ type: "SET_LAYER", layer: next })} + /> + + session.dispatch({ type: "SET_LANGUAGE_FOCUS", language }) + } + /> + session.dispatch({ type: "SET_MODE", mode: nextMode })} + /> +
+
{showChart ? ( - session.dispatch({ type: "CLEAR_PROGRESS" })} - /> +
+ {sidebarOpen ? ( + session.dispatch({ type: "GO_TO_REGION", regionId })} + onClose={() => session.dispatch({ type: "TOGGLE_SIDEBAR" })} + /> + ) : null} + session.dispatch({ type: "CLEAR_PROGRESS" })} + /> +
) : ( -
+
{sidebarOpen ? ( ) : null} - {/* Gated on modeChosen === true so the audience gate (shown while - modeChosen === false) resolves first and onboarding follows it as - one sequence: on a genuine first run both are native s and - would otherwise stack, the gate's backdrop over the coach-marks. */} - {modeChosen === true && !coachmarksSeen ? ( + {/* First-run work is one ordered sequence: audience, then the + parser-required Home choice (when ambiguous), then coaching over + the final layer. Two native dialogs may never compete for focus. */} + {modeChosen === true && !entrypointOpen && !coachmarksSeen ? ( session.dispatch({ type: "DISMISS_COACHMARKS" })} /> ) : null} - {/* Mounted last so its modal backdrop sits over the stage, and gated on - the coach-marks being done for the same reason the coach-marks are - gated on the audience gate: two s open at once stack. */} - {finderOpen ? ( - session.dispatch({ type: "GO_TO_REGION", regionId })} - onClose={() => session.dispatch({ type: "SET_FINDER_OPEN", open: false })} - /> - ) : null} +
+ )} + + {/* Find is a global command promised by the header and Cmd/Ctrl-K. Keep + its modal outside the Map/Star-chart branch so the command is never + accepted into state without a surface to render it. */} + {finderOpen ? ( + session.dispatch({ type: "GO_TO_REGION", regionId })} + onClose={() => session.dispatch({ type: "SET_FINDER_OPEN", open: false })} + /> + ) : null} + {!showChart ? ( session.dispatch({ type: "ADVANCE_REGION", regionId })} /> -
- )} + ) : null}