code wiki / _hdl_build / nx_uigen_l3.nx

nx_uigen_l3.nx source

↩ module page · 269 lines · 15097 B

1// nx_uigen_l3.nx -- ROADMAP RUNG L3: PROCEDURAL DESIGN-GRAMMAR. A compact SPEC expands through a deterministic 2// grammar into ONE OF MANY valid, novel page designs: generated palette (seed hue x accent-relation: analogous/ 3// complementary/triadic), radius + density axes, and CONSTRAINED section composition (3..5 middle bands chosen 4// + ordered from a 7-band vocabulary under validity rules: hero first, exactly one CTA last, no duplicates, 5// FAQ never before pricing). Same spec -> same bytes (determinism = the moat); different seeds -> visibly 6// different, ALWAYS-VALID designs. Also the ITERATIVE-REFINE rung: spec-delta commands ("hue 300", "add 7// pricing", "compact", "rounder") mutate the spec and re-emit -- a rule-based v0-chat-loop analog. Grounded: 8// uigss_gendesign.raw / uigss_procgen.raw (constraints -> many valid designs = generative design's core). 9// HONEST scope: bounded vocabulary + templated copy; free component synthesis and NL understanding are L4. 10// license_tier: ORIGINAL 11import "nx_uigen_l1.nx" 12const K_MAGIC_1103515245: i64 = 1103515245 13const K_MAGIC_12345: i64 = 12345 14const K_MAGIC_2147483648: i64 = 2147483648 15 16// ---- deterministic LCG (no float, positive-range) ---- 17func l3_rng_next(st: *i64) -> i64 { 18 var s: i64 = st[0] 19 if s < 0 { s = 0 - s } 20 s = (s * K_MAGIC_1103515245 + K_MAGIC_12345) % K_MAGIC_2147483648 21 st[0] = s 22 return s 23} 24func l3_choice(st: *i64, n: i64) -> i64 { let v: i64 = l3_rng_next(st); return v % n } 25 26// ---- spec: [0]=hue [1]=accent_rel(0 analog/1 complement/2 triad) [2]=radius_idx(0..2) [3]=density(0..2) 27// [4]=nmid [5..9]=section ids [10]=seed. sections: 0 features 1 split 2 steps 3 pricing 4 quote 5 faq 6 trust 28func l3_spec_from_seed(spec: *i64, seed: i64) -> i64 { 29 let st: *i64 = sys_mmap(8) as *i64 30 st[0] = seed 31 l3_rng_next(st) 32 spec[0] = l3_choice(st, 360) 33 spec[1] = l3_choice(st, 3) 34 spec[2] = l3_choice(st, 3) 35 spec[3] = l3_choice(st, 3) 36 // Fisher-Yates shuffle of the 7-band vocabulary, take first nmid 37 let vocab: *i64 = sys_mmap(64) as *i64 38 var i: i64 = 0 39 while i < 7 { vocab[i] = i; i = i + 1 } 40 var j: i64 = 6 41 while j > 0 { 42 let k: i64 = l3_choice(st, j + 1) 43 let t: i64 = vocab[j]; vocab[j] = vocab[k]; vocab[k] = t 44 j = j - 1 45 } 46 let nmid: i64 = 3 + l3_choice(st, 3) 47 spec[4] = nmid 48 i = 0 49 while i < nmid { spec[5 + i] = vocab[i]; i = i + 1 } 50 // grammar rule: FAQ never before pricing (if both selected, swap into legal order) 51 var pi: i64 = 0 - 1 52 var fi: i64 = 0 - 1 53 i = 0 54 while i < nmid { 55 if spec[5 + i] == 3 { pi = i } 56 if spec[5 + i] == 5 { fi = i } 57 i = i + 1 58 } 59 if pi >= 0 { if fi >= 0 { if fi < pi { spec[5 + fi] = 3; spec[5 + pi] = 5 } } } 60 spec[10] = seed 61 return 0 62} 63 64// ---- generated palette with an accent RELATION axis (generalizes l1's fixed +32 analogous) ---- 65func l3_accent_hue(hue: i64, rel: i64) -> i64 { 66 var add: i64 = 32 67 if rel == 1 { add = 180 } 68 if rel == 2 { add = 120 } 69 var ah: i64 = hue + add 70 while ah >= 360 { ah = ah - 360 } 71 return ah 72} 73func l3_palette_style(buf: *u8, off: i64, hue: i64, rel: i64) -> i64 { 74 let ah: i64 = l3_accent_hue(hue, rel) 75 var o: i64 = he_puts(buf, off, "<style>:root{" as *u8) 76 o = l1_tok(buf, o, "--nx-color-primary:" as *u8, hue, 62, 46) 77 o = l1_tok(buf, o, "--nx-color-primary2:" as *u8, hue, 70, 62) 78 o = l1_tok(buf, o, "--nx-color-accent:" as *u8, ah, 72, 50) 79 o = l1_tok(buf, o, "--nx-color-bg:" as *u8, hue, 22, 97) 80 o = l1_tok(buf, o, "--nx-color-surface:" as *u8, hue, 16, 100) 81 o = l1_tok(buf, o, "--nx-color-surface2:" as *u8, hue, 20, 94) 82 o = l1_tok(buf, o, "--nx-color-ink:" as *u8, hue, 25, 12) 83 o = l1_tok(buf, o, "--nx-color-ink2:" as *u8, hue, 14, 44) 84 o = l1_tok(buf, o, "--nx-color-line:" as *u8, hue, 18, 89) 85 o = he_puts(buf, o, "}@media(prefers-color-scheme:dark){:root{" as *u8) 86 o = l1_tok(buf, o, "--nx-color-primary:" as *u8, hue, 66, 64) 87 o = l1_tok(buf, o, "--nx-color-primary2:" as *u8, hue, 60, 74) 88 o = l1_tok(buf, o, "--nx-color-accent:" as *u8, ah, 70, 62) 89 o = l1_tok(buf, o, "--nx-color-bg:" as *u8, hue, 24, 9) 90 o = l1_tok(buf, o, "--nx-color-surface:" as *u8, hue, 20, 14) 91 o = l1_tok(buf, o, "--nx-color-surface2:" as *u8, hue, 18, 19) 92 o = l1_tok(buf, o, "--nx-color-ink:" as *u8, hue, 15, 92) 93 o = l1_tok(buf, o, "--nx-color-ink2:" as *u8, hue, 12, 66) 94 o = l1_tok(buf, o, "--nx-color-line:" as *u8, hue, 16, 24) 95 o = he_puts(buf, o, "}}</style>" as *u8) 96 return o 97} 98 99// ---- radius + density style axes (emitted after the kit stylesheet so they win the cascade) ---- 100func l3_style_mods(buf: *u8, off: i64, radius_idx: i64, density: i64) -> i64 { 101 var rad: i64 = 10 102 if radius_idx == 1 { rad = 14 } 103 if radius_idx == 2 { rad = 26 } 104 var pad: i64 = 56 105 if density == 1 { pad = 76 } 106 if density == 2 { pad = 104 } 107 var o: i64 = he_puts(buf, off, "<style>.card,.stat,.pricecard,.tablewrap,.callout{border-radius:" as *u8) 108 o = l1_put_u8(buf, o, rad) 109 o = he_puts(buf, o, "px}.sec{padding:" as *u8) 110 o = l1_put_u8(buf, o, pad) 111 o = he_puts(buf, o, "px 0}</style>" as *u8) 112 return o 113} 114 115// ---- section emitters (templated copy -- HONEST: prose generation is L4; the grammar owns STRUCTURE) ---- 116func l3_sec_features(buf: *u8, off: i64) -> i64 { 117 var o: i64 = sk_section_open(buf, off, "feat" as *u8, "Capabilities" as *u8, "Built for the job" as *u8, "Chosen by the grammar for this design." as *u8) 118 o = sk_card(buf, o, "<svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M13 3L4 14h7l-1 7 9-11h-7z\"/></svg>" as *u8, "Fast by default" as *u8, "Every band is emitted, not assembled at runtime &mdash; zero client JS to boot." as *u8) 119 o = sk_card(buf, o, "<svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M5 12l4 4 10-10\"/></svg>" as *u8, "Accessible always" as *u8, "The generated palette holds ink and background far apart in both themes." as *u8) 120 o = sk_card(buf, o, "<svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 2l10 6-10 6L2 8l10-6zM2 16l10 6 10-6\"/></svg>" as *u8, "Composed, not copied" as *u8, "Sections come from a constrained grammar, so every design stays coherent." as *u8) 121 return sk_section_close(buf, o) 122} 123func l3_sec_split(buf: *u8, off: i64, flip: i64) -> i64 { 124 return sk_split(buf, off, "how" as *u8, "Why it works" as *u8, "Designed as a system" as *u8, "One seed drives palette, shape, and rhythm together &mdash; so variety never breaks coherence." as *u8, "Zero third-party assets on any generated page" as *u8, "Deterministic output: the same spec yields the same bytes" as *u8, "Contrast passes WCAG in both themes by construction" as *u8, flip) 125} 126func l3_sec_steps(buf: *u8, off: i64) -> i64 { 127 var o: i64 = sk_steps_open(buf, off, "steps" as *u8, "Process" as *u8, "How it works" as *u8, "From spec to shipped page." as *u8) 128 o = sk_step(buf, o, "Describe" as *u8, "A compact spec: a seed, or a brief mapped to one." as *u8) 129 o = sk_step(buf, o, "Generate" as *u8, "The grammar expands it into a valid, styled composition." as *u8) 130 o = sk_step(buf, o, "Refine" as *u8, "Spec-delta commands adjust hue, shape, rhythm, or sections." as *u8) 131 return sk_steps_close(buf, o) 132} 133func l3_sec_pricing(buf: *u8, off: i64) -> i64 { 134 var o: i64 = sk_pricing_open(buf, off, "pricing" as *u8, "Pricing" as *u8, "Simple pricing" as *u8, "Start free, scale when ready." as *u8) 135 o = sk_price_tier(buf, o, "Starter" as *u8, "$0" as *u8, "/mo" as *u8, "<li>One generated site</li><li>Both themes included</li><li>Community support</li>" as *u8, "Start free" as *u8, "#join" as *u8, 0) 136 o = sk_price_tier(buf, o, "Studio" as *u8, "$19" as *u8, "/mo" as *u8, "<li>Unlimited generations</li><li>Refine loop included</li><li>Priority support</li>" as *u8, "Go Studio" as *u8, "#join" as *u8, 1) 137 o = sk_price_tier(buf, o, "Scale" as *u8, "$99" as *u8, "/mo" as *u8, "<li>Multi-site fleets</li><li>Custom vocabulary</li><li>Dedicated help</li>" as *u8, "Talk to us" as *u8, "#join" as *u8, 0) 138 return sk_pricing_close(buf, o) 139} 140func l3_sec_quote(buf: *u8, off: i64) -> i64 { 141 return sk_quote(buf, off, "quote" as *u8, "Testimonial" as *u8, "It looked designed on purpose &mdash; because the constraints made sure it was." as *u8, "A. Reviewer" as *u8, "Design lead" as *u8) 142} 143func l3_sec_faq(buf: *u8, off: i64) -> i64 { 144 var o: i64 = sk_faq_open(buf, off, "faq" as *u8, "FAQ" as *u8, "Common questions" as *u8, "What people ask first." as *u8) 145 o = sk_faq_item(buf, o, "Is every generated design different?" as *u8, "Each seed expands to its own palette, shape, rhythm, and section composition &mdash; within rules that keep every result valid." as *u8) 146 o = sk_faq_item(buf, o, "Does dark mode work?" as *u8, "Yes. The palette is generated twice &mdash; a light and a dark scheme from the same seed &mdash; and both keep WCAG contrast by construction." as *u8) 147 o = sk_faq_item(buf, o, "Can I change one thing without regenerating?" as *u8, "Yes: refine commands adjust a single axis &mdash; hue, roundness, density, or a section &mdash; and leave the rest untouched." as *u8) 148 return sk_faq_close(buf, o) 149} 150func l3_sec_trust(buf: *u8, off: i64) -> i64 { 151 var o: i64 = sk_trust_open(buf, off, "Guarantees" as *u8, "Safe by construction" as *u8, "What every generated page ships with." as *u8) 152 o = sk_trust_item(buf, o, "Accessible" as *u8, "WCAG contrast in both themes, skip links, focus states." as *u8) 153 o = sk_trust_item(buf, o, "Private" as *u8, "No CDNs, no trackers, no third-party fonts." as *u8) 154 o = sk_trust_item(buf, o, "Yours" as *u8, "Plain HTML and CSS you fully own." as *u8) 155 return sk_trust_close(buf, o) 156} 157func l3_emit_section(buf: *u8, off: i64, sec: i64, flip: i64) -> i64 { 158 if sec == 0 { return l3_sec_features(buf, off) } 159 if sec == 1 { return l3_sec_split(buf, off, flip) } 160 if sec == 2 { return l3_sec_steps(buf, off) } 161 if sec == 3 { return l3_sec_pricing(buf, off) } 162 if sec == 4 { return l3_sec_quote(buf, off) } 163 if sec == 5 { return l3_sec_faq(buf, off) } 164 return l3_sec_trust(buf, off) 165} 166 167// ---- emit a full page from a spec (same spec -> same bytes) ---- 168func l3_emit_from_spec(buf: *u8, off: i64, spec: *i64, title: *u8, brand: *u8) -> i64 { 169 var o: i64 = sk_open_site(buf, off, title, brand, 1, "/" as *u8) 170 o = sk_nav_item(buf, o, "Home" as *u8, "#top" as *u8) 171 o = sk_nav_item(buf, o, "Get started" as *u8, "#join" as *u8) 172 o = sk_header_close(buf, o) 173 o = l3_palette_style(buf, o, spec[0], spec[1]) 174 o = l3_style_mods(buf, o, spec[2], spec[3]) 175 o = sk_mkt_styles(buf, o) 176 o = sk_hero(buf, o, "Generated design" as *u8, title, "by grammar" as *u8, "This page&rsquo;s palette, shape, rhythm, and section composition were all chosen by a constrained design grammar from one compact spec." as *u8, "Get started" as *u8, "#join" as *u8, "See how" as *u8, "#main" as *u8, "Deterministic: this exact spec always yields this exact page." as *u8) 177 let flip: i64 = spec[0] % 2 178 var i: i64 = 0 179 while i < spec[4] { 180 o = l3_emit_section(buf, o, spec[5 + i], flip) 181 i = i + 1 182 } 183 o = sk_cta(buf, o, "Ready" as *u8, "Generate yours" as *u8, "One spec in, a valid design out &mdash; every time." as *u8, "Get started" as *u8, "#join" as *u8, "Learn more" as *u8, "#main" as *u8) 184 o = sk_close(buf, o, "Generated" as *u8, brand) 185 return o 186} 187func l3_generate(buf: *u8, off: i64, seed: i64, title: *u8, brand: *u8) -> i64 { 188 let spec: *i64 = sys_mmap(128) as *i64 189 l3_spec_from_seed(spec, seed) 190 return l3_emit_from_spec(buf, off, spec, title, brand) 191} 192 193// ==== ITERATIVE REFINE: spec-delta commands (rule-based v0-chat-loop analog) ==== 194func l3_streq(a: *u8, b: *u8) -> i64 { 195 var i: i64 = 0 196 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 197 if b[i] != (0 as u8) { return 0 } 198 return 1 199} 200func l3_starts(s: *u8, pre: *u8) -> i64 { 201 var i: i64 = 0 202 while pre[i] != (0 as u8) { if s[i] != pre[i] { return 0 } i = i + 1 } 203 return 1 204} 205func l3_atoi_at(s: *u8, at: i64) -> i64 { 206 var v: i64 = 0 207 var i: i64 = at 208 while s[i] != (0 as u8) { 209 let c: i64 = s[i] as i64 210 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } 211 i = i + 1 212 } 213 return v 214} 215func l3_secid_from_name(s: *u8) -> i64 { 216 if l3_streq(s, "features" as *u8) == 1 { return 0 } 217 if l3_streq(s, "split" as *u8) == 1 { return 1 } 218 if l3_streq(s, "steps" as *u8) == 1 { return 2 } 219 if l3_streq(s, "pricing" as *u8) == 1 { return 3 } 220 if l3_streq(s, "quote" as *u8) == 1 { return 4 } 221 if l3_streq(s, "faq" as *u8) == 1 { return 5 } 222 if l3_streq(s, "trust" as *u8) == 1 { return 6 } 223 return 0 - 1 224} 225func l3_spec_find(spec: *i64, sec: i64) -> i64 { 226 var i: i64 = 0 227 while i < spec[4] { if spec[5 + i] == sec { return i } i = i + 1 } 228 return 0 - 1 229} 230// apply one refine command to the spec. Returns 1 if applied, 0 if refused (would break grammar validity). 231func l3_refine(spec: *i64, cmd: *u8) -> i64 { 232 if l3_starts(cmd, "hue " as *u8) == 1 { spec[0] = l3_atoi_at(cmd, 4) % 360; return 1 } 233 if l3_streq(cmd, "accent analog" as *u8) == 1 { spec[1] = 0; return 1 } 234 if l3_streq(cmd, "accent complement" as *u8) == 1 { spec[1] = 1; return 1 } 235 if l3_streq(cmd, "accent triad" as *u8) == 1 { spec[1] = 2; return 1 } 236 if l3_streq(cmd, "sharper" as *u8) == 1 { if spec[2] > 0 { spec[2] = spec[2] - 1 } return 1 } 237 if l3_streq(cmd, "rounder" as *u8) == 1 { if spec[2] < 2 { spec[2] = spec[2] + 1 } return 1 } 238 if l3_streq(cmd, "compact" as *u8) == 1 { spec[3] = 0; return 1 } 239 if l3_streq(cmd, "airy" as *u8) == 1 { spec[3] = 2; return 1 } 240 if l3_starts(cmd, "add " as *u8) == 1 { 241 let sec: i64 = l3_secid_from_name((((cmd as i64) + 4) as *u8)) 242 if sec < 0 { return 0 } 243 if l3_spec_find(spec, sec) >= 0 { return 0 } 244 if spec[4] >= 5 { return 0 } 245 // grammar rule on insert: pricing goes BEFORE faq if faq present; everything else appends 246 var at: i64 = spec[4] 247 if sec == 3 { 248 let fi: i64 = l3_spec_find(spec, 5) 249 if fi >= 0 { at = fi } 250 } 251 var i: i64 = spec[4] 252 while i > at { spec[5 + i] = spec[5 + i - 1]; i = i - 1 } 253 spec[5 + at] = sec 254 spec[4] = spec[4] + 1 255 return 1 256 } 257 if l3_starts(cmd, "drop " as *u8) == 1 { 258 let sec: i64 = l3_secid_from_name((((cmd as i64) + 5) as *u8)) 259 if sec < 0 { return 0 } 260 let at: i64 = l3_spec_find(spec, sec) 261 if at < 0 { return 0 } 262 if spec[4] <= 3 { return 0 } 263 var i: i64 = at 264 while i < spec[4] - 1 { spec[5 + i] = spec[5 + i + 1]; i = i + 1 } 265 spec[4] = spec[4] - 1 266 return 1 267 } 268 return 0 269}