5454 < main >
5555 < h1 > 🏗️ CII — Community Investment Interface</ h1 >
5656 < p class ="lead ">
57- CII is the “last-mile” interface that turns verified recovery value into **live, trackable projects**:
58- housing, clinics, food systems, broadband, transit, and workforce pipelines. It consumes < em > CIRI</ em >
59- results, aligns with < em > CIBS</ em > budgets, and publishes an auditable portfolio.
57+ CII is the “last-mile” interface that turns verified recovery value into
58+ < strong > live, trackable projects</ strong > : housing, clinics, food systems, broadband,
59+ transit, and workforce pipelines. It consumes < em > CIRI</ em > results, aligns with
60+ < em > CIBS</ em > budgets, and publishes an auditable portfolio.
6061 </ p >
6162
6263 <!-- Status cards -->
6364 < div class ="cards " id ="status ">
6465 < div class ="card ">
6566 < h3 > Model</ h3 >
66- < div class ="kv "> < span class ="label "> /cii/model.json</ span >
67- < span class ="value " id ="model-status " class ="warn "> Checking…</ span > </ div >
67+ < div class ="kv ">
68+ < span class ="label "> < a href ="model.json "> /cii/model.json</ a > </ span >
69+ < span class ="value " id ="model-status "> Checking…</ span >
70+ </ div >
6871 </ div >
6972 < div class ="card ">
7073 < h3 > Portfolio</ h3 >
71- < div class ="kv "> < span class ="label "> /cii/portfolio.csv</ span >
72- < span class ="value " id ="port-status " class ="warn "> Checking…</ span > </ div >
74+ < div class ="kv ">
75+ < span class ="label "> < a href ="portfolio.csv "> /cii/portfolio.csv</ a > </ span >
76+ < span class ="value " id ="port-status "> Checking…</ span >
77+ </ div >
7378 </ div >
7479 < div class ="card ">
7580 < h3 > Integration</ h3 >
76- < div class ="kv "> < span class ="label "> Ready to publish to</ span >
77- < span class ="value "> < a href ="../integration/index.html "> Integration Layer</ a > </ span > </ div >
81+ < div class ="kv ">
82+ < span class ="label "> Ready to publish to</ span >
83+ < span class ="value "> < a href ="../integration/index.html "> Integration Layer</ a > </ span >
84+ </ div >
7885 </ div >
7986 </ div >
8087
@@ -90,8 +97,8 @@ <h2>🔗 Links</h2>
9097 < a class ="btn " href ="portfolio.csv "> Open portfolio.csv</ a >
9198 </ div >
9299 < p class ="hint ">
93- Don’t have files yet? Create a < code > model.json</ code > describing project types and multipliers,
94- and a < code > portfolio.csv</ code > listing projects (name, category, cost, households served, status).
100+ Don’t have files yet? Create a < code > model.json</ code > describing project categories and multipliers,
101+ and a < code > portfolio.csv</ code > listing projects (< code > name,category,cost_usd, households, status</ code > ).
95102 </ p >
96103 </ section >
97104
@@ -106,20 +113,20 @@ <h2>📄 Portfolio Preview</h2>
106113 < section >
107114 < h2 > 🧬 How CII Fits</ h2 >
108115 < ul >
109- < li > < strong > Inputs:</ strong > CIRI’s < em > Total Recovery</ em > and risk signals; community needs; ABE doctrine guardrails.</ li >
116+ < li > < strong > Inputs:</ strong > CIRI’s < em > Total Recovery</ em > and risk signals; community needs; A.B.E. doctrine guardrails.</ li >
110117 < li > < strong > Process:</ strong > Score candidate projects → allocate via CIBS → publish portfolio and status.</ li >
111118 < li > < strong > Outputs:</ strong > Live investments, KPIs (households served, jobs, ROI per project), and audit-ready trails.</ li >
112119 </ ul >
113120 </ section >
114121
115122 < footer >
116- CII is part of A.B.E.’s open, auditable toolchain.< br / >
123+ CII is part of A.B.E.’s open, auditable toolchain.< br >
117124 License: < a href ="https://creativecommons.org/licenses/by-nc/4.0/ " target ="_blank " rel ="noopener "> CC BY-NC 4.0</ a > — non-commercial use with attribution.
118125 </ footer >
119126 </ main >
120127
121128 < script >
122- // tiny CSV -> table
129+ // --- helpers ---
123130 function parseCSV ( text ) {
124131 const lines = text . split ( / \r ? \n / ) . filter ( Boolean ) ;
125132 return lines . map ( l => l . split ( ',' ) . map ( x => x . trim ( ) ) ) ;
@@ -129,30 +136,26 @@ <h2>🧬 How CII Fits</h2>
129136 try { return new Intl . NumberFormat ( undefined , { style :'currency' , currency :'USD' , maximumFractionDigits :0 } ) . format ( v ) ; }
130137 catch { return '$' + ( Math . round ( v ) || 0 ) . toLocaleString ( ) ; }
131138 }
132-
133139 async function checkFile ( path , okId ) {
134140 const el = document . getElementById ( okId ) ;
135141 try {
136142 const res = await fetch ( path , { cache :'no-store' } ) ;
137143 if ( ! res . ok ) throw 0 ;
138144 const text = await res . text ( ) ;
139145 if ( ! text . trim ( ) ) throw 0 ;
140- el . textContent = 'Present' ;
141- el . classList . add ( 'ok' ) ;
146+ el . textContent = 'Present' ; el . classList . add ( 'ok' ) ;
142147 return text ;
143148 } catch ( e ) {
144- el . textContent = 'Missing' ;
145- el . classList . add ( 'warn' ) ;
149+ el . textContent = 'Missing' ; el . classList . add ( 'warn' ) ;
146150 return null ;
147151 }
148152 }
149153
154+ // --- boot ---
150155 async function boot ( ) {
151- // existence checks
152156 const modelText = await checkFile ( 'model.json' , 'model-status' ) ;
153157 const portfolioText = await checkFile ( 'portfolio.csv' , 'port-status' ) ;
154158
155- // render table if CSV exists
156159 const wrap = document . getElementById ( 'portfolio-table' ) ;
157160 const hint = document . getElementById ( 'portfolio-hint' ) ;
158161
@@ -184,6 +187,16 @@ <h2>🧬 How CII Fits</h2>
184187 </div>` ;
185188 hint . textContent = 'Once portfolio.csv is added, refresh to see the table.' ;
186189 }
190+
191+ // (Optional light check) warn if model.json exists but looks empty
192+ if ( modelText ) {
193+ try {
194+ const j = JSON . parse ( modelText ) ;
195+ if ( ! j . categories || ! Array . isArray ( j . categories ) || j . categories . length === 0 ) {
196+ console . warn ( 'model.json has no categories.' ) ;
197+ }
198+ } catch ( e ) { console . warn ( 'model.json not valid JSON' ) ; }
199+ }
187200 }
188201 boot ( ) ;
189202 </ script >
0 commit comments