code wiki / (root) / nx_site_chrome_composable_t48.nx

nx_site_chrome_composable_t48.nx source

↩ module page · 416 lines · 36670 B

1// nx_site_chrome.nx -- SOVEREIGN site-wide navigation authority. Reads knowledge/site/surfaces.reg 2// (SSOT of every visitor surface: route|section|title|icon|scope|order|desc) and emits, per mode: 3// gate -- self-test + liar-kill (surfaces>=1, sections present, required fields non-empty) 4// header -- global responsive nav bar fragment (brand + primary links + pure-CSS hamburger mega-menu) 5// footer -- grouped footer sitemap fragment 6// sitemapxml -- real sitemap.xml (sitemaps.org 0.9 urlset, public surfaces) 7// page -- complete human /sitemap page (chrome + full grouped index of EVERY surface) 8// This makes ALL assets discoverable from one place, on desktop and mobile, ZERO JavaScript 9// (checkbox-hack menu), a11y (skip-link, aria, focus-visible, >=44px touch targets), light/dark. 10// nx_cc traps honored: no '#'/'!' in string literals -> wc(35)/wc(33); w2 turns ' into " for attrs; 11// CSS uses class selectors (no id '#'); no else-if chains. license_tier: ORIGINAL expect_exit:0 12import "nx_syscalls.nx" 13// One sink lets page emitters compose the same navigation without subprocess capture. 14struct SiteChromeSink { fd:i64, data:*u8, pos:i64, capacity:i64, failed:i64 } 15func sc_put(s:*SiteChromeSink,text:*u8)->i64 { 16 var n:i64=0;while text[n]!=(0 as u8) { n=n+1 } 17 if s.failed!=0 { return -1 } 18 if s.fd>=0 { let wrote:i64=sys_write(s.fd,text,n);if wrote!=n {s.failed=1;return -1};return n } 19 if s.pos<0||s.capacity<s.pos||n>s.capacity-s.pos {s.failed=1;return -1} 20 var i:i64=0;while i<n {s.data[s.pos+i]=text[i];i=i+1};s.pos=s.pos+n;return n 21} 22func sc_char(s:*SiteChromeSink,c:i64)->i64 { 23 if s.failed!=0 {return -1} 24 var value:u8=c as u8 25 if s.fd>=0 {let wrote:i64=sys_write(s.fd,&value,1);if wrote!=1 {s.failed=1;return -1};return 1} 26 if s.pos<0||s.pos>=s.capacity {s.failed=1;return -1} 27 s.data[s.pos]=value;s.pos=s.pos+1;return 1 28} 29func sc_quote(s:*SiteChromeSink,text:*u8)->i64 { 30 var i:i64=0;while text[i]!=(0 as u8) {var c:i64=text[i] as i64;if c==39 {c=34};sc_char(s,c);i=i+1};return s.failed 31} 32func sc_escape(s:*SiteChromeSink,text:*u8)->i64 { 33 var i:i64=0;while text[i]!=(0 as u8) { 34 let c:i64=text[i] as i64 35 if c==38 {sc_put(s,"&amp;" as *u8)} else {if c==60 {sc_put(s,"&lt;" as *u8)} else {if c==62 {sc_put(s,"&gt;" as *u8)} else {if c==34 {sc_put(s,"&quot;" as *u8)} else {if c==39 {sc_put(s,"&#39;" as *u8)} else {sc_char(s,c)}}}}} 36 i=i+1};return s.failed 37} 38 39const K_MAGIC_1024: i64 = 1024 40const K_MAGIC_65536: i64 = 65536 41 42func w(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 43func wc(fd: i64, code: i64) -> i64 { let t: *u8 = sys_mmap(2); t[0] = code as u8; sys_write(fd, t, 1); return 0 } 44func wn(fd: i64, v: i64) -> i64 { 45 var m: i64 = v; if m < 0 { w(fd, "-" as *u8); m = 0 - m } 46 let t: *u8 = sys_mmap(24); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } 47 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 48 let o: *u8 = sys_mmap(24); var i: i64 = 0; while i < k { o[i] = t[k-1-i]; i = i + 1 } sys_write(fd, o, k); return 0 49} 50func streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 51func c_read(path: *u8, buf: *u8, cap: i64) -> i64 { 52 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 - 1 } 53 var tot: i64 = 0 54 while tot < cap { let r: i64 = sys_read(fd, (buf as i64 + tot) as *u8, cap - tot); if r <= 0 { break } tot = tot + r } 55 sys_close(fd); return tot 56} 57// w2: emit a literal, converting apostrophe(39)->doublequote(34) so HTML attrs live in nishilang 58// string literals (which cannot contain the " byte). Text with a literal apostrophe must use w(). 59func w2(fd: i64, s: *u8) -> i64 { 60 var i: i64 = 0 61 while s[i] != (0 as u8) { if (s[i] as i64) == 39 { wc(fd, 34) } else { wc(fd, s[i] as i64) } i = i + 1 } 62 return 0 63} 64// field: extract |-delimited field `idx` (0-based) from buf[ls,le) into out, trimming ASCII spaces. 65// UTF-8 glyphs pass through (continuation/lead bytes are never 0x20 or 0x7C). Empty if idx absent. 66func sc_field(buf: *u8, ls: i64, le: i64, idx: i64, out: *u8, capacity:i64) -> i64 { 67 if capacity<1||ls<0||le<ls||idx<0 {return -1} 68 var end:i64=le;if end>ls&&buf[end-1]==(13 as u8) {end=end-1} 69 var cur: i64 = 0; var s: i64 = ls; var i: i64 = ls 70 while i < end { if cur == idx { break } if buf[i] == (124 as u8) { cur = cur + 1; s = i + 1 } i = i + 1 } 71 if cur < idx { out[0] = 0 as u8; return 0 } 72 var e: i64 = s 73 while e < end { if buf[e] == (124 as u8) { break } e = e + 1 } 74 var a: i64 = s 75 while a < e { if buf[a] != (32 as u8) { break } a = a + 1 } 76 var b: i64 = e 77 while b > a { if buf[b-1] != (32 as u8) { break } b = b - 1 } 78 if b-a>=capacity {out[0]=0 as u8;return -1} 79 var o: i64 = 0 80 while a < b { out[o] = buf[a]; o = o + 1; a = a + 1 } 81 out[o] = 0 as u8 82 return o 83} 84 85func sc_route_ok(route:*u8)->i64 { 86 if route[0]!=(47 as u8)||route[1]==(47 as u8) {return 0} 87 var i:i64=0;while route[i]!=(0 as u8) {let c:i64=route[i] as i64;if c<=32||c==92||c==127 {return 0};i=i+1};return 1 88} 89func sc_registry_ok(buf:*u8,n:i64)->i64 { 90 if buf==(0 as *u8)||n<=0 {return 0} 91 let tmp:*u8=sys_mmap(1024);var rows:i64=0;var i:i64=0 92 while i<n { 93 var j:i64=i;while j<n {if buf[j]==(10 as u8) {break};j=j+1} 94 if j>i&&buf[j-1]==(13 as u8) {j=j-1} 95 if j>i&&buf[i]!=(35 as u8) { 96 var k:i64=i;var separators:i64=0 97 while k<j {let c:i64=buf[k] as i64;if c==0||c<32||c==127 {return 0};if c==124 {separators=separators+1};k=k+1} 98 if separators<6||separators>7 {return 0} 99 var f:i64=0 100 while f<7 { 101 var cap:i64=256;if f==0 {cap=512};if f==3||f==4 {cap=64};if f==6 {cap=1024} 102 let len:i64=sc_field(buf,i,j,f,tmp,cap);if len<=0 {return 0} 103 if f==0 {if sc_route_ok(tmp)==0 {return 0}} 104 if f==1 {var found:i64=0;var g:i64=0;while g<5 {if streq(tmp,sec_name(g))==1 {found=1};g=g+1};if found==0 {return 0}} 105 if f==4 {if streq(tmp,"public" as *u8)==0&&streq(tmp,"gated" as *u8)==0&&streq(tmp,"machine" as *u8)==0 {return 0}} 106 if f==5 {var d:i64=0;while d<len {if tmp[d]<(48 as u8)||tmp[d]>(57 as u8) {return 0};d=d+1}} 107 f=f+1 108 } 109 if separators==7 {if sc_field(buf,i,j,7,tmp,512)<=0 {return 0};if sc_route_ok(tmp)==0 {return 0}} 110 rows=rows+1 111 };i=j+1 112 };return (rows>0) as i64 113} 114 115// Compatibility entry point: legacy registry field indices retain their schema capacities. 116func field(buf:*u8,ls:i64,le:i64,idx:i64,out:*u8)->i64 { 117 var capacity:i64=256;if idx==0||idx==7 {capacity=512};if idx==3||idx==4 {capacity=64};if idx==6 {capacity=1024} 118 return sc_field(buf,ls,le,idx,out,capacity) 119} 120 121// brand diamond as inline SVG (proven-safe: no '#'/'!'/glyph-escape; inherits currentColor) 122func sc_mark(sink: *SiteChromeSink) -> i64 { 123 sc_quote(sink, "<svg class='nxmark' viewBox='0 0 24 24' width='17' height='17' aria-hidden='true'><path d='M12 2l10 10-10 10L2 12z' fill='currentColor'/></svg>" as *u8) 124 return 0 125} 126// health_of: scan link_health.tsv (route \t class \t ...) -> 1 healthy, 0 down (class DEAD), -1 unknown. 127func health_of(led: *u8, ln: i64, route: *u8) -> i64 { 128 var i: i64 = 0 129 while i < ln { 130 var j: i64 = i 131 while j < ln { if led[j] == (10 as u8) { break } j = j + 1 } 132 if j > i { 133 var k: i64 = i; var m: i64 = 0; var hit: i64 = 1 134 while k < j { if led[k] == (9 as u8) { break } if route[m] != led[k] { hit = 0 } if route[m] == (0 as u8) { hit = 0 } k = k + 1; m = m + 1 } 135 if hit == 1 { if route[m] == (0 as u8) { if k < j { if led[k] == (9 as u8) { 136 if led[k+1] == (68 as u8) { return 0 } 137 return 1 138 } } } } 139 } 140 i = j + 1 141 } 142 return 0 - 1 143} 144func sec_name(i: i64) -> *u8 { 145 if i == 0 { return "Family" as *u8 } 146 if i == 1 { return "Create" as *u8 } 147 if i == 2 { return "Media" as *u8 } 148 if i == 3 { return "Explore" as *u8 } 149 return "Play" as *u8 150} 151// primary top-bar links (always visible on wide screens): route|label pairs, by index 152func prim_route(i: i64) -> *u8 { 153 if i == 0 { return "/compare" as *u8 } 154 if i == 1 { return "/gallery" as *u8 } 155 if i == 2 { return "/library" as *u8 } 156 return "/research" as *u8 157} 158func prim_label(i: i64) -> *u8 { 159 if i == 0 { return "Compare" as *u8 } 160 if i == 1 { return "Gallery" as *u8 } 161 if i == 2 { return "Library" as *u8 } 162 return "Research" as *u8 163} 164 165// ---- shared CSS blocks (emitted into <style>) ---- 166func sc_css_nav(sink: *SiteChromeSink) -> i64 { 167 sc_quote(sink, ".nxnav{position:sticky;top:0;z-index:50;display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:linear-gradient(90deg,rgb(42,77,143),rgb(9,58,136));color:rgb(255,255,255);padding:9px clamp(12px,4vw,26px);font-family:-apple-system,Segoe UI,Roboto,sans-serif;box-shadow:0 2px 12px rgba(9,20,40,.28)}\n" as *u8) 168 sc_quote(sink, ".nxnav a{color:rgb(255,255,255);text-decoration:none}.nxbrand{font-weight:800;font-size:1.05rem;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 6px}.nxmark{font-size:1.25rem}\n" as *u8) 169 sc_quote(sink, ".nxlinks{display:flex;gap:3px;margin-left:4px}.nxlinks a{padding:10px 12px;border-radius:9px;font-weight:600;min-height:44px;display:inline-flex;align-items:center}.nxlinks a:hover{background:rgba(255,255,255,.16)}\n" as *u8) 170 sc_quote(sink, ".nxmenu{margin-left:auto}.nxburger{display:flex;align-items:center;justify-content:center;min-width:46px;min-height:46px;padding:8px 12px;cursor:pointer;border-radius:10px;list-style:none}.nxburger::-webkit-details-marker{display:none}.nxburger:hover{background:rgba(255,255,255,.16)}.nxburger:focus-visible{outline:3px solid white;outline-offset:2px}.nxpanel{position:absolute;top:100%;left:0;right:0;max-height:calc(100dvh - 80px);overflow:auto;background:rgb(9,58,136);border-radius:0 0 14px 14px;padding:8px;display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:4px}\n" as *u8) 171 sc_quote(sink, ".nxgrp{padding:8px}.nxgrp h2{font-size:.72rem;letter-spacing:.09em;text-transform:uppercase;opacity:.72;margin:4px 6px 8px}.nxgrp a{display:flex;gap:10px;align-items:flex-start;padding:9px 10px;border-radius:10px;min-height:44px}.nxgrp a:hover{background:rgba(255,255,255,.14)}.nxgrp .gi{font-size:1.05rem;line-height:1.45;width:1.4rem;text-align:center;flex:none}.nxgrp b{display:block;font-size:.94rem}.nxgrp em{font-style:normal;opacity:.72;font-size:.77rem;line-height:1.35}\n" as *u8) 172 sc_quote(sink, ".nxscope{font-size:.6rem;background:rgba(255,255,255,.22);padding:1px 6px;border-radius:20px;margin-left:6px;vertical-align:middle;letter-spacing:.03em}.nxall{grid-column:1/-1;text-align:center;padding:11px;font-weight:700;border-top:1px solid rgba(255,255,255,.18);margin-top:2px}@media(max-width:640px){.nxlinks{display:none}}\n" as *u8) 173 return 0 174} 175func css_foot(fd: i64) -> i64 { 176 w2(fd, ".nxfoot{margin-top:48px;background:rgb(16,20,32);color:rgb(214,220,236);border-radius:16px 16px 0 0;padding:26px clamp(16px,5vw,34px) 30px;font-family:-apple-system,Segoe UI,Roboto,sans-serif}.nxfoot a{color:rgb(190,205,240);text-decoration:none;display:block;padding:5px 0;min-height:32px}.nxfoot a:hover{color:rgb(255,255,255);text-decoration:underline}\n" as *u8) 177 w2(fd, ".nxfwrap{display:grid;grid-template-columns:1.5fr repeat(5,1fr);gap:18px;max-width:1120px;margin:0 auto}.nxfbrand{font-weight:800}.nxfbrand span{display:block;font-weight:400;opacity:.6;font-size:.8rem;margin-top:8px;line-height:1.5}.nxfcol h3{font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;opacity:.55;margin:0 0 6px}.nxfsm{grid-column:1/-1;text-align:center;border-top:1px solid rgba(255,255,255,.1);margin-top:12px;padding-top:14px;font-weight:700}@media(max-width:760px){.nxfwrap{grid-template-columns:1fr 1fr}}\n" as *u8) 178 return 0 179} 180 181// ---- NAV FRAGMENT (header mode): brand + primary links + hamburger mega-panel ---- 182func sc_emit_nav(sink: *SiteChromeSink, sbuf: *u8, sn: i64) -> i64 { 183 if sc_registry_ok(sbuf,sn)==0 {sink.failed=1;return -1} 184 let route: *u8 = sys_mmap(512); let section: *u8 = sys_mmap(256); let title: *u8 = sys_mmap(256) 185 let icon: *u8 = sys_mmap(64); let scope: *u8 = sys_mmap(64); let desc: *u8 = sys_mmap(K_MAGIC_1024) 186 sc_quote(sink, "<style>\n" as *u8); sc_css_nav(sink); sc_quote(sink, "</style>" as *u8) 187 sc_quote(sink, "<nav class='nxnav' aria-label='Primary navigation'><a class='nxbrand' href='/'>" as *u8) 188 sc_mark(sink) 189 sc_quote(sink, " Nishi Family</a><div class='nxlinks'>" as *u8) 190 var p: i64 = 0 191 while p < 4 { sc_quote(sink, "<a href='" as *u8); sc_put(sink, prim_route(p)); sc_quote(sink, "'>" as *u8); sc_put(sink, prim_label(p)); sc_quote(sink, "</a>" as *u8); p = p + 1 } 192 sc_quote(sink, "</div><details class='nxmenu'><summary class='nxburger'>Menu</summary><div class='nxpanel'>" as *u8) 193 var s: i64 = 0 194 while s < 5 { 195 let sname: *u8 = sec_name(s) 196 sc_quote(sink, "<div class='nxgrp'><h2>" as *u8); sc_escape(sink, sname); sc_quote(sink, "</h2>" as *u8) 197 var i: i64 = 0 198 while i < sn { 199 var j: i64 = i 200 while j < sn { if sbuf[j] == (10 as u8) { break } j = j + 1 } 201 if sbuf[i] != (35 as u8) { if j > i { 202 sc_field(sbuf, i, j, 1, section, 256) 203 if streq(section, sname) == 1 { 204 sc_field(sbuf, i, j, 0, route, 512); sc_field(sbuf, i, j, 2, title, 256); sc_field(sbuf, i, j, 3, icon, 64) 205 sc_field(sbuf, i, j, 4, scope, 64); sc_field(sbuf, i, j, 6, desc, 1024) 206 sc_quote(sink, "<a href='" as *u8); sc_escape(sink, route); sc_quote(sink, "'><span class='gi' aria-hidden='true'>" as *u8); sc_escape(sink, icon) 207 sc_quote(sink, "</span><span><b>" as *u8); sc_escape(sink, title) 208 if streq(scope, "gated" as *u8) == 1 { sc_quote(sink, "<span class='nxscope'>sign in</span>" as *u8) } 209 if streq(scope, "machine" as *u8) == 1 { sc_quote(sink, "<span class='nxscope'>API</span>" as *u8) } 210 sc_quote(sink, "</b><em>" as *u8); sc_escape(sink, desc); sc_quote(sink, "</em></span></a>" as *u8) 211 } 212 } } 213 i = j + 1 214 } 215 sc_quote(sink, "</div>" as *u8) 216 s = s + 1 217 } 218 sc_quote(sink, "<a class='nxall' href='/sitemap'>View the full sitemap &rarr;</a></div></details></nav>\n" as *u8) 219 return 0 220} 221 222// ---- FOOTER FRAGMENT (footer mode): grouped sitemap columns ---- 223func emit_foot(sbuf: *u8, sn: i64) -> i64 { 224 let route: *u8 = sys_mmap(512); let section: *u8 = sys_mmap(256); let title: *u8 = sys_mmap(256) 225 w2(1, "<style>\n" as *u8); css_foot(1); w2(1, "</style>" as *u8) 226 w2(1, "<footer class='nxfoot' aria-label='Site map'><div class='nxfwrap'><div class='nxfbrand'>" as *u8) 227 mark_svg(1); w2(1, " Nishi Family<span>The sovereign family ecosystem &mdash; served bits-up over TLS 1.3, no third-party web server, no trackers.</span></div>" as *u8) 228 var s: i64 = 0 229 while s < 5 { 230 let sname: *u8 = sec_name(s) 231 w2(1, "<nav class='nxfcol' aria-label='" as *u8); w(1, sname); w2(1, "'><h3>" as *u8); w(1, sname); w2(1, "</h3>" as *u8) 232 var i: i64 = 0 233 while i < sn { 234 var j: i64 = i 235 while j < sn { if sbuf[j] == (10 as u8) { break } j = j + 1 } 236 if sbuf[i] != (35 as u8) { if j > i { 237 sc_field(sbuf, i, j, 1, section, 256) 238 if streq(section, sname) == 1 { 239 sc_field(sbuf, i, j, 0, route, 512); sc_field(sbuf, i, j, 2, title, 256) 240 w2(1, "<a href='" as *u8); w(1, route); w2(1, "'>" as *u8); w(1, title); w2(1, "</a>" as *u8) 241 } 242 } } 243 i = j + 1 244 } 245 w2(1, "</nav>" as *u8) 246 s = s + 1 247 } 248 w2(1, "<a class='nxfsm' href='/sitemap'>Full sitemap &rarr;</a></div></footer>\n" as *u8) 249 return 0 250} 251 252// ---- sitemap.xml (sitemapxml mode): public surfaces only (gated -> 302 login, not crawlable) ---- 253func emit_xml(sbuf: *u8, sn: i64) -> i64 { 254 let route: *u8 = sys_mmap(512); let scope: *u8 = sys_mmap(64) 255 w2(1, "<?xml version='1.0' encoding='UTF-8'?>\n<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>\n" as *u8) 256 var i: i64 = 0 257 while i < sn { 258 var j: i64 = i 259 while j < sn { if sbuf[j] == (10 as u8) { break } j = j + 1 } 260 if sbuf[i] != (35 as u8) { if j > i { 261 sc_field(sbuf, i, j, 0, route, 512); sc_field(sbuf, i, j, 4, scope, 64) 262 if streq(scope, "public" as *u8) == 1 { 263 w2(1, " <url><loc>https://nishifamily.com" as *u8); w(1, route); w2(1, "</loc>" as *u8) 264 if streq(route, "/" as *u8) == 1 { w2(1, "<changefreq>daily</changefreq><priority>1.0</priority>" as *u8) } else { w2(1, "<changefreq>weekly</changefreq><priority>0.7</priority>" as *u8) } 265 w2(1, "</url>\n" as *u8) 266 } 267 } } 268 i = j + 1 269 } 270 w2(1, " <url><loc>https://nishifamily.com/sitemap</loc><changefreq>weekly</changefreq><priority>0.5</priority></url>\n</urlset>\n" as *u8) 271 return 0 272} 273 274// ---- /sitemap human page (page mode): full standalone doc, chrome + grouped index of every surface ---- 275func emit_doc(sbuf: *u8, sn: i64, is_home: i64) -> i64 { 276 let route: *u8 = sys_mmap(512); let section: *u8 = sys_mmap(256); let title: *u8 = sys_mmap(256) 277 let icon: *u8 = sys_mmap(64); let scope: *u8 = sys_mmap(64); let desc: *u8 = sys_mmap(K_MAGIC_1024) 278 // link health ledger (from nx_link_sentinel) -> down surfaces get an 'offline' badge, never a silent orphan 279 // dual-path: repo layout, else CWD (NAS: knowledge/ is root-owned so the sentinel writes ./link_health.tsv) 280 let led: *u8 = sys_mmap(K_MAGIC_65536); var ln: i64 = c_read("knowledge/site/link_health.tsv" as *u8, led, K_MAGIC_65536) 281 if ln <= 0 { ln = c_read("link_health.tsv" as *u8, led, K_MAGIC_65536) } 282 if ln < 0 { ln = 0 } 283 w2(1, "<" as *u8); wc(1, 33); w2(1, "DOCTYPE html>\n<html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1'>\n" as *u8) 284 if is_home == 1 { w2(1, "<title>Nishi Family &mdash; the sovereign ecosystem</title>\n<meta name='description' content='Home of the Nishi sovereign ecosystem: create, watch, read, compare and play. Every surface served bits-up over TLS 1.3, no third-party web server.'>\n<style>\n" as *u8) } else { w2(1, "<title>Sitemap &mdash; every Nishi surface</title>\n<meta name='description' content='The complete map of the Nishi sovereign ecosystem: create, media, explore, play and family surfaces.'>\n<style>\n" as *u8) } 285 w2(1, ":root{--bg:rgb(252,252,254);--fg:rgb(22,22,34);--ac:rgb(42,77,143);--line:rgb(228,228,236);--soft:rgb(246,247,251);--mut:rgb(104,104,118)}*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);color:var(--fg);font-family:-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6}\n" as *u8) 286 w2(1, "main{max-width:1000px;margin:0 auto;padding:0 clamp(16px,5vw,26px) 8vh}.skip{position:absolute;left:-999px;background:var(--ac);color:rgb(255,255,255);padding:12px 16px;border-radius:0 0 8px 0;z-index:99}.skip:focus{left:0}\n" as *u8) 287 w2(1, ".hero{margin:26px 0 8px}.hero h1{font-size:clamp(1.9rem,6vw,2.6rem);margin:0 0 6px;background:linear-gradient(90deg,var(--ac),rgb(130,80,223));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}.hero p{color:var(--mut);margin:0;font-size:clamp(1rem,2vw,1.1rem);max-width:640px}\n" as *u8) 288 w2(1, ".cta{display:flex;flex-wrap:wrap;gap:10px;margin-top:18px}.cta a{display:inline-flex;align-items:center;min-height:48px;padding:12px 22px;border-radius:12px;font-weight:700;text-decoration:none}.cta .p{background:var(--ac);color:rgb(255,255,255)}.cta .s{background:var(--soft);color:var(--ac);border:1px solid var(--line)}.cta a:hover{filter:brightness(1.07)}\n" as *u8) 289 w2(1, ".sec{margin:30px 0 6px;padding-top:6px;border-top:2px solid var(--line)}.sec h2{font-size:1.15rem;margin:8px 0 2px;color:var(--ac)}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px;margin:14px 0}\n" as *u8) 290 w2(1, ".it{display:flex;gap:12px;align-items:flex-start;border:1px solid var(--line);border-radius:13px;padding:13px 15px;background:var(--soft);color:inherit;text-decoration:none;transition:border-color .15s,box-shadow .15s}.it:hover{border-color:var(--ac);box-shadow:0 4px 14px rgba(42,77,143,.14)}.it .gi{font-size:1.3rem;width:1.7rem;text-align:center;flex:none;color:var(--ac)}\n" as *u8) 291 w2(1, ".it b{display:block;font-size:1.02rem}.it em{font-style:normal;color:var(--mut);font-size:.85rem;line-height:1.4}.sc{font-size:.62rem;background:var(--ac);color:rgb(255,255,255);padding:1px 7px;border-radius:20px;margin-left:6px;vertical-align:middle}.sc.off{background:rgb(179,38,30)}.it.dn{opacity:.6}:focus-visible{outline:3px solid var(--ac);outline-offset:2px}\n" as *u8) 292 w2(1, "@media(prefers-color-scheme:dark){:root{--bg:rgb(14,14,19);--fg:rgb(231,231,239);--line:rgb(38,38,48);--soft:rgb(22,22,30);--mut:rgb(156,156,168)}}\n" as *u8) 293 w2(1, "</style></head><body>\n<a class='skip' href='" as *u8); wc(1, 35); w2(1, "main'>Skip to content</a>\n" as *u8) 294 emit_nav(sbuf, sn) 295 var pubn: i64 = 0 296 var i0: i64 = 0 297 while i0 < sn { 298 var j0: i64 = i0 299 while j0 < sn { if sbuf[j0] == (10 as u8) { break } j0 = j0 + 1 } 300 if sbuf[i0] != (35 as u8) { if j0 > i0 { sc_field(sbuf, i0, j0, 0, route, 512); if route[0] != (0 as u8) { pubn = pubn + 1 } } } 301 i0 = j0 + 1 302 } 303 w2(1, "<main id='main'><div class='hero'>" as *u8) 304 if is_home == 1 { 305 w2(1, "<h1>Nishi Family</h1><p>Welcome to the sovereign ecosystem &mdash; create, watch, read, compare and play, all served bits-up on our own hardware. " as *u8) 306 wn(1, pubn); w2(1, " surfaces, TLS 1.3, no third-party web server.</p><style>.nxq{display:flex;gap:8px;max-width:640px;margin:18px 0 8px;background:var(--soft);border:1px solid var(--line);border-radius:999px;padding:6px 6px 6px 18px}.nxq:focus-within{border-color:var(--ac)}.nxq input{flex:1;min-width:0;border:0;background:transparent;font:inherit;color:var(--fg);outline:none;min-height:44px}.nxq input::placeholder{color:var(--mut)}.nxq button{border:0;border-radius:999px;background:var(--ac);color:rgb(255,255,255);font:inherit;font-weight:700;padding:0 22px;min-height:44px;cursor:pointer}.nxqex{color:var(--mut);font-size:.82rem;margin:0;max-width:640px}.nxqex a{color:var(--ac);text-decoration:none}</style><form class='nxq' action='/search' method='get' role='search'><input name='q' type='search' placeholder='Search the library, this site, or the open web&hellip;' aria-label='Search query' autocomplete='off'><button type='submit'>Search</button></form><p class='nxqex'>Sovereign BM25 &middot; zero JS, zero ads, zero trackers on results &middot; <a href='/search?q=okapi+bm25'>try: okapi bm25 &rarr;</a> &middot; <a href='/api/openapi.json'>API spec</a></p><div class='cta'><a class='p' href='/sitemap'>Explore everything &rarr;</a><a class='s' href='/compare'>See the comparisons</a></div></div>\n" as *u8) 307 } else { 308 w2(1, "<h1>Sitemap</h1><p>Every surface in the Nishi sovereign ecosystem, in one place. " as *u8) 309 wn(1, pubn); w2(1, " surfaces across five sections.</p></div>\n" as *u8) 310 } 311 var s: i64 = 0 312 while s < 5 { 313 let sname: *u8 = sec_name(s) 314 w2(1, "<section class='sec'><h2>" as *u8); w(1, sname); w2(1, "</h2><div class='grid'>" as *u8) 315 var i: i64 = 0 316 while i < sn { 317 var j: i64 = i 318 while j < sn { if sbuf[j] == (10 as u8) { break } j = j + 1 } 319 if sbuf[i] != (35 as u8) { if j > i { 320 sc_field(sbuf, i, j, 1, section, 256) 321 if streq(section, sname) == 1 { 322 sc_field(sbuf, i, j, 0, route, 512); sc_field(sbuf, i, j, 2, title, 256); sc_field(sbuf, i, j, 3, icon, 64) 323 sc_field(sbuf, i, j, 4, scope, 64); sc_field(sbuf, i, j, 6, desc, 1024) 324 let hlth: i64 = health_of(led, ln, route) 325 w2(1, "<a class='it" as *u8) 326 if hlth == 0 { w2(1, " dn" as *u8) } 327 w2(1, "' href='" as *u8); w(1, route); w2(1, "'><span class='gi' aria-hidden='true'>" as *u8); w(1, icon) 328 w2(1, "</span><span><b>" as *u8); w(1, title) 329 if hlth == 0 { w2(1, "<span class='sc off'>offline</span>" as *u8) } else { 330 if streq(scope, "gated" as *u8) == 1 { w2(1, "<span class='sc'>sign in</span>" as *u8) } 331 if streq(scope, "machine" as *u8) == 1 { w2(1, "<span class='sc'>API</span>" as *u8) } 332 } 333 w2(1, "</b><em>" as *u8); w(1, desc); w2(1, "</em></span></a>" as *u8) 334 } 335 } } 336 i = j + 1 337 } 338 w2(1, "</div></section>\n" as *u8) 339 s = s + 1 340 } 341 w2(1, "</main>\n" as *u8) 342 emit_foot(sbuf, sn) 343 w2(1, "</body></html>\n" as *u8) 344 return 0 345} 346func emit_page(sbuf: *u8, sn: i64) -> i64 { emit_doc(sbuf, sn, 0); return 0 } 347func emit_home(sbuf: *u8, sn: i64) -> i64 { emit_doc(sbuf, sn, 1); return 0 } 348 349 350func mark_svg(fd:i64)->i64 {var s:SiteChromeSink;s.fd=fd;s.failed=0;sc_mark(&s);return s.failed} 351func css_nav(fd:i64)->i64 {var s:SiteChromeSink;s.fd=fd;s.failed=0;sc_css_nav(&s);return s.failed} 352func emit_nav(sbuf:*u8,sn:i64)->i64 {var s:SiteChromeSink;s.fd=1;s.failed=0;sc_emit_nav(&s,sbuf,sn);return s.failed} 353func sc_nav_buffer(out:*u8,pos:i64,capacity:i64,sbuf:*u8,sn:i64)->i64 { 354 var s:SiteChromeSink;s.fd=-1;s.data=out;s.pos=pos;s.capacity=capacity;s.failed=0 355 if out==(0 as *u8)||sbuf==(0 as *u8)||sn<0||pos<0||capacity<pos {return -1} 356 sc_emit_nav(&s,sbuf,sn);if s.failed!=0 {return -1};return s.pos 357} 358 359func main(argc: i64, argv: *i64) -> i64 { 360 var mode: i64 = 0 361 if argc >= 2 { 362 if streq(argv[1] as *u8, "header" as *u8) == 1 { mode = 1 } 363 if streq(argv[1] as *u8, "footer" as *u8) == 1 { mode = 2 } 364 if streq(argv[1] as *u8, "sitemapxml" as *u8) == 1 { mode = 3 } 365 if streq(argv[1] as *u8, "page" as *u8) == 1 { mode = 4 } 366 if streq(argv[1] as *u8, "home" as *u8) == 1 { mode = 5 } 367 } 368 let cap: i64 = K_MAGIC_65536 369 let sbuf: *u8 = sys_mmap(cap) 370 var sn: i64 = c_read("knowledge/site/surfaces.reg" as *u8, sbuf, cap) 371 if sn <= 0 { sn = c_read("surfaces.reg" as *u8, sbuf, cap) } 372 373 if sc_registry_ok(sbuf,sn)==0 {w(2,"registry_invalid\n" as *u8);return 2} 374 if mode == 1 { return emit_nav(sbuf, sn) } 375 if mode == 2 { emit_foot(sbuf, sn); sys_exit(0); return 0 } 376 if mode == 3 { emit_xml(sbuf, sn); sys_exit(0); return 0 } 377 if mode == 4 { emit_page(sbuf, sn); sys_exit(0); return 0 } 378 if mode == 5 { emit_home(sbuf, sn); sys_exit(0); return 0 } 379 380 // gate / console -- count surfaces + sections, verify required fields, liar-kill 381 w(1, "=== NX-SITE-CHROME -- global navigation from knowledge/site/surfaces.reg ===\n" as *u8) 382 let route: *u8 = sys_mmap(512); let section: *u8 = sys_mmap(256); let title: *u8 = sys_mmap(256) 383 var n: i64 = 0; var bad: i64 = 0 384 let seen: *u8 = sys_mmap(8) 385 var z: i64 = 0; while z < 5 { seen[z] = 0 as u8; z = z + 1 } 386 var i: i64 = 0 387 while i < sn { 388 var j: i64 = i 389 while j < sn { if sbuf[j] == (10 as u8) { break } j = j + 1 } 390 if sbuf[i] != (35 as u8) { if j > i { 391 sc_field(sbuf, i, j, 0, route, 512); sc_field(sbuf, i, j, 1, section, 256); sc_field(sbuf, i, j, 2, title, 256) 392 if route[0] != (0 as u8) { 393 n = n + 1 394 if title[0] == (0 as u8) { bad = bad + 1 } 395 var s: i64 = 0 396 while s < 5 { if streq(section, sec_name(s)) == 1 { seen[s] = 1 as u8 } s = s + 1 } 397 w(1, " surface: " as *u8); w(1, route); w(1, " [" as *u8); w(1, section); w(1, "] " as *u8); w(1, title); w(1, "\n" as *u8) 398 } 399 } } 400 i = j + 1 401 } 402 var secn: i64 = 0; var s2: i64 = 0 403 while s2 < 5 { if seen[s2] == (1 as u8) { secn = secn + 1 } s2 = s2 + 1 } 404 w(1, " surfaces=" as *u8); wn(1, n); w(1, " sections=" as *u8); wn(1, secn); w(1, "/5 bad-rows=" as *u8); wn(1, bad); w(1, "\n" as *u8) 405 let liar_have: i64 = (n >= 1) as i64 406 let liar_sec: i64 = (secn >= 1) as i64 407 let liar_clean: i64 = (bad == 0) as i64 408 w(1, " LIAR-KILL: have-surfaces=" as *u8); wn(1, liar_have); w(1, " sections-present=" as *u8); wn(1, liar_sec); w(1, " all-titled=" as *u8); wn(1, liar_clean); w(1, "\n" as *u8) 409 let ok: i64 = liar_have & liar_sec & liar_clean 410 w(1, "NX-SITE-CHROME surfaces=" as *u8); wn(1, n); w(1, " verdict=" as *u8) 411 if ok == 1 { w(1, "GREEN -- modes: header footer sitemapxml page\n" as *u8); sys_exit(0); return 0 } 412 w(1, "RED (empty registry or untitled rows)\n" as *u8); sys_exit(1); return 1 413} 414 415func sc_workspace_style()->*u8 {return ".nx-product-body{display:grid;grid-template-rows:auto minmax(0,1fr);height:100dvh;min-height:0;padding:0;gap:0;align-items:stretch;justify-content:stretch;overflow:hidden}.nx-product-workspace{display:grid;grid-template-rows:auto minmax(0,1fr);min-height:0;padding:0}.nx-product-context{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center;padding:.5rem 1rem;border-bottom:1px solid var(--nx-line,#2f2a4a)}.nx-product-context nav{display:flex;flex-wrap:wrap;gap:.25rem}.nx-product-context button,.nx-product-context select{min-height:var(--nx-control-size,44px);font:inherit;color:inherit;background:var(--nx-panel,#161c25);border:1px solid var(--nx-line,#64748b);border-radius:.5rem;padding:.5rem .75rem}.nx-product-context button[aria-pressed=true]{border-color:var(--nx-focus,#a8e6c0)}.nx-product-context :focus-visible,.nx-product-inspector :focus-visible{outline:2px solid var(--nx-focus,#a8e6c0);outline-offset:2px}.nx-product-content{display:flex;min-height:0;min-width:0}.nx-product-stage{flex:1;min-width:0;min-height:0;display:grid;place-items:stretch}.nx-product-stage canvas{width:100%;height:100%;min-width:0;min-height:0;border:0;border-radius:0;object-fit:contain}.nx-product-inspector{flex:0 1 24rem;min-width:0;overflow:auto;padding:1rem;border-left:1px solid var(--nx-line,#2f2a4a);box-sizing:border-box}.nx-product-inspector[hidden]{display:none}.nx-product-inspector p{text-align:left;max-width:100%;overflow-wrap:anywhere}.nx-product-inspector table{max-width:100%;table-layout:fixed;overflow-wrap:anywhere}.nx-product-inspector *{box-sizing:border-box}@media(max-width:48rem){.nx-product-content{flex-direction:column}.nx-product-inspector{flex-basis:45%;border-left:0;border-top:1px solid var(--nx-line,#2f2a4a)}}" as *u8} 416func sc_workspace_script()->*u8 {return "(function(){\nconst config=window.NX_PRODUCT_CONTEXT;\nif(!config||config.version!==1||!config.product||!Array.isArray(config.parts)||!Array.isArray(config.stages)||!Array.isArray(config.actions)||!config.primary||typeof config.primary.id!=='string'||typeof config.primary.label!=='string')throw Error('workspace-context-contract');\nconst parts=new Map(),actions=new Map();let mounted=false,selected='scene',inspector=null,buttons=new Map(),panels=new Map(),actionButtons=new Map();\nconst localRoute=value=>typeof value==='string'&&value.startsWith('/')&&!value.startsWith('//')&&!/[\\\\\\u0000-\\u0020]/.test(value);\nconst unique=rows=>rows.every((row,i)=>row&&typeof row.id==='string'&&/^[a-z][a-z0-9-]*$/.test(row.id)&&typeof row.label==='string'&&rows.findIndex(x=>x.id===row.id)===i);\nif(!unique(config.parts)||!unique(config.stages)||!unique(config.actions)||!config.parts.some(x=>x.id==='scene')||!config.stages.some(x=>x.id===config.stage))throw Error('workspace-context-identities');\nfor(const stage of config.stages)if(stage.route!==null&&!localRoute(stage.route))throw Error('workspace-context-route');\nfunction show(id){\n if(!buttons.has(id))return false;selected=id;\n for(const [key,b]of buttons){b.setAttribute('aria-pressed',String(key===id));}\n for(const [key,p]of panels)p.hidden=key!==id;\n inspector.hidden=id==='scene';window.NishiWorkspace.state={product:config.product.id,stage:config.stage,part:id};return true;\n}\nfunction registerPart(id,node){\n if(!config.parts.some(x=>x.id===id)||!(node instanceof Element))throw Error('workspace-part-contract');\n parts.set(id,node);if(mounted&&panels.has(id)){const panel=panels.get(id);const part=config.parts.find(x=>x.id===id);panel.replaceChildren();if(part.reason&&part.state==='needs-intervention'){const status=document.createElement('output');status.textContent=part.reason;status.setAttribute('role','status');panel.append(status);}panel.append(node);node.style.position='static';node.style.maxWidth='100%';node.style.maxHeight='none';node.style.margin='0';if(node instanceof HTMLDetailsElement)node.open=true;}return true;\n}\nwindow.NishiWorkspace={version:1,registerPart,selectPart:show,registerAction:(id,handler)=>{if(!config.actions.some(x=>x.id===id)||typeof handler!=='function')throw Error('workspace-action-contract');actions.set(id,handler);if(actionButtons.has(id))actionButtons.get(id).disabled=false;},state:{product:config.product.id,stage:config.stage,part:selected}};\nfunction mount(){\n const main=document.querySelector('main'),primary=document.getElementById(config.primary.id);if(!main||!primary)throw Error('workspace-required-parts');\n const old=Array.from(main.childNodes),title=main.querySelector('h1');\n document.body.classList.add('nx-product-body');main.classList.add('nx-product-workspace');\n const bar=document.createElement('header');bar.className='nx-product-context';\n if(title){title.textContent=config.product.label;bar.append(title);}\n const label=document.createElement('label');label.textContent='Stage ';const stages=document.createElement('select');stages.setAttribute('aria-label','Release stage');\n for(const row of config.stages){const o=document.createElement('option');o.value=row.id;o.textContent=row.label;o.disabled=row.state!=='available';stages.append(o);}stages.value=config.stage;\n stages.addEventListener('change',()=>{const row=config.stages.find(x=>x.id===stages.value);if(row&&row.state==='available'&&localRoute(row.route))location.assign(row.route);});label.append(stages);bar.append(label);\n const nav=document.createElement('nav');nav.setAttribute('aria-label','Product components');\n inspector=document.createElement('aside');inspector.className='nx-product-inspector';inspector.setAttribute('aria-label','Component inspector');\n for(const part of config.parts){\n const button=document.createElement('button');button.type='button';button.textContent=part.label;button.addEventListener('click',()=>show(part.id));buttons.set(part.id,button);nav.append(button);\n if(part.id!=='scene'){const panel=document.createElement('section');panel.id='nx-workspace-'+part.id;panel.setAttribute('aria-label',part.label);panel.hidden=true;const status=document.createElement('output');status.textContent=part.reason||'This component has not registered a view.';status.setAttribute('role','status');panel.append(status);panels.set(part.id,panel);inspector.append(panel);button.setAttribute('aria-controls',panel.id);}\n }\n bar.append(nav);\n for(const action of config.actions){const b=document.createElement('button');b.type='button';b.textContent=action.label;b.disabled=!actions.has(action.id);actionButtons.set(action.id,b);b.setAttribute('aria-pressed','false');b.addEventListener('click',()=>{const handler=actions.get(action.id);if(!handler)return;const active=b.getAttribute('aria-pressed')!=='true';handler(active);b.setAttribute('aria-pressed',String(active));});bar.append(b);}\n const stage=document.createElement('section');stage.className='nx-product-stage';stage.setAttribute('aria-label',config.primary.label);stage.append(primary);\n const body=document.createElement('div');body.className='nx-product-content';body.append(stage,inspector);\n const help=document.createElement('div');for(const node of old){if(node!==title&&node!==primary)help.append(node);}\n main.replaceChildren(bar,body);parts.set('help',help);mounted=true;\n for(const [id,node]of parts)registerPart(id,node);\n for(const host of [bar,inspector])for(const type of ['keydown','pointerdown','mousedown','click','wheel'])host.addEventListener(type,e=>e.stopPropagation());\n show(selected);\n}\nif(document.readyState==='loading')document.addEventListener('DOMContentLoaded',mount,{once:true});else mount();\n})();" as *u8}