code wiki / _hdl_build / nx_kit_counsel.nx

nx_kit_counsel.nx source

↩ module page · 209 lines · 17145 B

1// nx_kit_counsel.nx -- the COUNSEL design family: professional-services grammar grounded in the extracted 2// 30-site best-law-firm reference bar (2026-07-25 /uigen diagnosis). What it deliberately is NOT: the SaaS 3// marketing grammar (no pill buttons, no rounded card grid, no gradient display text, no pricing band). 4// What it IS: serif display over sans body (the Dispatch/finance precedent) with a gold-rule emphasis 5// underline; an ASYMMETRIC split hero whose right half is a GENERATIVE SVG scene (seed-driven column 6// composition -- authentic generated art, never stock); a stats-first trust band (serif numerals, thin 7// rules); practice areas as a RULED editorial list; an oversized-quote testimonial; a small-caps 8// accreditation row; one strong rectangular CTA into a real contact page. Restrained palette: deep 9// topic-hue primary + ONE bronze accent over the generated neutral field; both themes; reduced-motion 10// respected. Pure emit (mmap only) -- composes on top of sk_head's token shell, own .kc- namespace. 11// license_tier: ORIGINAL 12import "nx_uigen_l1.nx" 13import "nx_kit_shell.nx" 14 15// ---- the Counsel stylesheet (emitted AFTER the kit stylesheet + generated palette so it wins) ---- 16func kc_styles(buf: *u8, off: i64, hue: i64) -> i64 { 17 var o: i64 = he_puts(buf, off, "<style>:root{" as *u8) 18 o = l1_tok(buf, o, "--kc-deep:" as *u8, hue, 46, 27) 19 o = l1_tok(buf, o, "--kc-deep2:" as *u8, hue, 40, 38) 20 o = he_puts(buf, o, "--kc-gold:rgb(176,138,64);--kc-serif:ui-serif,Georgia,\"Iowan Old Style\",\"Palatino Linotype\",serif}" as *u8) 21 o = he_puts(buf, o, "@media(prefers-color-scheme:dark){:root{" as *u8) 22 o = l1_tok(buf, o, "--kc-deep:" as *u8, hue, 38, 72) 23 o = l1_tok(buf, o, "--kc-deep2:" as *u8, hue, 34, 60) 24 o = he_puts(buf, o, "--kc-gold:rgb(214,178,110)}}" as *u8) 25 // the FIELD: one warm ivory paper, no cool tint, no striped section bands (seen-and-fixed 07-25) 26 o = he_puts(buf, o, "body{background:rgb(250,249,246);color:rgb(28,27,24)}@media(prefers-color-scheme:dark){body{background:rgb(21,20,18);color:rgb(233,229,221)}}" as *u8) 27 // the CHROME: serif wordmark, no gradient dot, letter-spaced small-caps nav, quiet ivory bar 28 o = kx_shell_reset(buf, o) 29 o = he_puts(buf, o, "header.site{background:rgb(250,249,246);border-bottom:1px solid var(--nx-color-line)}header.site .bar{padding:22px 24px}@media(prefers-color-scheme:dark){header.site{background:rgb(21,20,18)}}header.site nav.top a{font-size:.76rem;letter-spacing:.15em;text-transform:uppercase;font-weight:600;color:var(--kc-deep)}header.site nav.top a:hover{color:var(--kc-gold)}" as *u8) 30 o = kx_wordmark(buf, o, "var(--kc-serif)" as *u8, "600" as *u8, "font-size:1.22rem;letter-spacing:.005em" as *u8) 31 // the footer carries the SAME wordmark treatment -- the render caught the gradient dot surviving 32 // down there after the header was fixed (one shell, two logos = the amateur tell) 33 o = he_puts(buf, o, "footer.site{border-top:1px solid var(--nx-color-line)}" as *u8) 34 o = he_puts(buf, o, ".kc-hero{display:grid;grid-template-columns:minmax(0,6fr) minmax(0,5fr);gap:clamp(24px,4vw,56px);align-items:stretch;padding:clamp(36px,5vw,64px) 0 clamp(40px,6vw,72px)}.kc-hero>div:first-child{align-self:center}@media(max-width:820px){.kc-hero{grid-template-columns:1fr}}" as *u8) 35 o = he_puts(buf, o, ".kc-eyebrow{font-size:.78rem;letter-spacing:.22em;text-transform:uppercase;color:var(--kc-gold);font-weight:640}" as *u8) 36 o = he_puts(buf, o, ".kc-hero h1{font-family:var(--kc-serif);font-weight:600;font-size:clamp(2.1rem,5.2vw,3.6rem);line-height:1.08;letter-spacing:-.015em;margin:.35em 0 .3em;text-wrap:balance}" as *u8) 37 o = he_puts(buf, o, ".kc-lede{color:var(--nx-color-ink2);font-size:1.07rem;max-width:56ch;line-height:1.7}" as *u8) 38 o = he_puts(buf, o, ".kc-btn{display:inline-block;margin-top:26px;padding:15px 34px;background:var(--kc-deep);color:#fff;text-decoration:none;font-weight:640;letter-spacing:.02em;border-radius:3px}.kc-btn:hover{background:var(--kc-deep2)}.kc-btn:focus-visible{outline:3px solid var(--kc-gold);outline-offset:3px}" as *u8) 39 o = he_puts(buf, o, ".kc-alt{margin-left:22px;color:var(--kc-deep);font-weight:600;text-decoration:none;border-bottom:2px solid var(--kc-gold)}" as *u8) 40 // the scene sits in a DEEP PANEL with the engraving reversed out (v3: a thin line drawing floating on 41 // ivory read as a diagram, not art direction -- seen in the render and fixed) 42 o = he_puts(buf, o, ".kc-scene{background:var(--kc-deep);padding:clamp(28px,4vw,52px);align-self:stretch;display:flex;align-items:center}.kc-scene svg{width:100%;height:auto;display:block}@media(max-width:820px){.kc-scene{display:none}}" as *u8) 43 // bands: tighter rhythm + a 3-col grid so the heading sits in the FIRST column and content fills the 44 // remaining measure (v3: every band hugged the left edge with the right half empty) 45 o = he_puts(buf, o, ".kc-sec{padding:clamp(34px,5vw,60px) 0;border-top:1px solid var(--nx-color-line);background:transparent}.kc-sec>.wrap{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,9fr);gap:clamp(20px,4vw,56px);align-items:start}@media(max-width:820px){.kc-sec>.wrap{grid-template-columns:1fr;gap:14px}}.kc-sec h2{font-family:var(--kc-serif);font-weight:600;font-size:clamp(1.15rem,2.2vw,1.5rem);letter-spacing:-.01em;margin:0;line-height:1.25}.kc-sec h2 em{font-style:normal;border-bottom:2px solid rgba(176,138,64,.65);padding-bottom:4px}" as *u8) 46 o = he_puts(buf, o, ".kc-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:clamp(18px,3vw,40px)}.kc-stat{border-left:2px solid rgba(176,138,64,.55);padding-left:16px}.kc-stat b{display:block;font-family:var(--kc-serif);font-weight:600;font-size:clamp(2rem,4vw,2.9rem);color:var(--kc-deep);font-variant-numeric:tabular-nums;line-height:1}.kc-stat span{display:block;margin-top:7px;font-size:.72rem;letter-spacing:.13em;text-transform:uppercase;color:var(--nx-color-ink2);line-height:1.45}" as *u8) 47 o = he_puts(buf, o, ".kc-list{list-style:none;margin:0;padding:0;columns:2;column-gap:clamp(24px,4vw,52px)}@media(max-width:820px){.kc-list{columns:1}}.kc-list li{break-inside:avoid;border-top:1px solid var(--nx-color-line);padding:14px 0 16px}.kc-list li:first-child{padding-top:14px}.kc-list h3{font-family:var(--kc-serif);font-weight:600;font-size:1.06rem;margin:0 0 .22em}.kc-list p{margin:0;color:var(--nx-color-ink2);font-size:.93rem;line-height:1.58}" as *u8) 48 o = he_puts(buf, o, ".kc-quote{margin:0;max-width:60ch}.kc-quote blockquote{margin:0;font-family:var(--kc-serif);font-size:clamp(1.15rem,2.2vw,1.5rem);line-height:1.48;color:var(--nx-color-ink);text-indent:-.4em}.kc-quote blockquote:before{content:\"\\201C\";color:var(--kc-gold)}.kc-quote figcaption{margin-top:14px;font-size:.74rem;letter-spacing:.13em;text-transform:uppercase;color:var(--nx-color-ink2)}" as *u8) 49 o = he_puts(buf, o, ".kc-accred{display:flex;flex-wrap:wrap;gap:10px 26px;margin-top:26px;padding-top:20px;border-top:1px solid var(--nx-color-line);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--nx-color-ink2)}.kc-accred span{border-left:2px solid var(--kc-gold);padding-left:11px}" as *u8) 50 o = he_puts(buf, o, ".kc-final{background:var(--kc-deep);color:#fff;padding:clamp(40px,6vw,72px) 0;margin-top:clamp(28px,4vw,48px)}.kc-final>.wrap{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,4fr);gap:clamp(20px,4vw,48px);align-items:center}@media(max-width:820px){.kc-final>.wrap{grid-template-columns:1fr}}.kc-final h2{font-family:var(--kc-serif);font-weight:600;font-size:clamp(1.4rem,3vw,2rem);margin:0 0 .3em;color:#fff}.kc-final p{color:rgba(255,255,255,.8);margin:0;font-size:.98rem}.kc-final .kc-btn{background:#fff;color:var(--kc-deep);margin-top:0;justify-self:start}.kc-final .kc-btn:hover{background:rgba(255,255,255,.88)}" as *u8) 51 o = he_puts(buf, o, "@media(prefers-reduced-motion:reduce){.kc-hero,.kc-sec{animation:none;transition:none}}</style>" as *u8) 52 return o 53} 54 55// ---- the DOC-TIER half of the family (about/contact/docs/status). Without this a Counsel site shipped 56// TWO design languages: a serif ivory home page and a cool-grey SaaS subpage with a gradient-dot 57// logo, sans headings and a rounded gradient button (seen in the render, 07-25). Emitted AFTER 58// sk_doc_styles so it wins; overrides the doc tier onto the same field, type and controls. ---- 59func kc_doc_styles(buf: *u8, off: i64) -> i64 { 60 var o: i64 = he_puts(buf, off, "<style>.doc{max-width:1000px;padding-top:clamp(24px,4vw,44px);padding-bottom:clamp(40px,6vw,72px)}" as *u8) 61 o = he_puts(buf, o, ".doc h1{font-family:var(--kc-serif);font-weight:600;font-size:clamp(1.9rem,4.4vw,2.9rem);letter-spacing:-.015em;line-height:1.1;margin:.1em 0 .35em}" as *u8) 62 o = he_puts(buf, o, ".doc h2{font-family:var(--kc-serif);font-weight:600;font-size:clamp(1.15rem,2.2vw,1.5rem);letter-spacing:-.008em;margin:1.9em 0 .45em}" as *u8) 63 // the lede was indenting/centering off the h1 -- pin it flush left on its own measure 64 o = he_puts(buf, o, ".doc .lede{margin:0 0 1.1em;max-width:60ch;color:var(--nx-color-ink2);font-size:1.03rem;line-height:1.7}" as *u8) 65 o = he_puts(buf, o, ".doc .callout{background:transparent;border-left:2px solid var(--kc-gold);border-radius:0;padding:6px 0 6px 18px;box-shadow:none;max-width:64ch}" as *u8) 66 // controls: squared, ivory, gold focus -- no rounded SaaS fields, no gradient submit 67 o = he_puts(buf, o, ".nform{max-width:34rem;gap:17px}.field label{font-size:.74rem;letter-spacing:.13em;text-transform:uppercase;font-weight:640;color:var(--nx-color-ink2)}" as *u8) 68 o = he_puts(buf, o, ".field input,.field textarea,.field select{border-radius:2px;border:1px solid var(--nx-color-line);background:var(--nx-color-surface);padding:13px 15px;font-size:1rem}" as *u8) 69 o = he_puts(buf, o, ".field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible{outline:none;border-color:var(--kc-gold);box-shadow:0 0 0 3px rgba(176,138,64,.22)}" as *u8) 70 o = he_puts(buf, o, ".btnp{background:var(--kc-deep);border-radius:3px;padding:15px 34px;font-weight:640;letter-spacing:.02em;box-shadow:none}.btnp:hover{background:var(--kc-deep2);transform:none}.btnp:focus-visible{outline:3px solid var(--kc-gold);outline-offset:3px}" as *u8) 71 o = he_puts(buf, o, ".docfoot{border-top:1px solid var(--nx-color-line);font-size:.8rem;letter-spacing:.02em}" as *u8) 72 o = he_puts(buf, o, "</style>" as *u8) 73 return o 74} 75 76// ---- generative hero scene: a seed-driven column composition (thin architectural verticals, one gold). 77// Same seed -> same art; different practice -> different skyline. Authentic generated, never stock. ---- 78func kc_scene(buf: *u8, off: i64, seed: i64) -> i64 { 79 // v2 (seen-and-fixed): an engraved ARCH + COLONNADE line drawing. Column heights are UNIFORM on 80 // purpose -- varied heights read as a bar chart, the exact amateur tell the operator flagged. 81 // Seed varies: number of concentric arch lines (2-3), number of columns (5-8), which column is gold. 82 var o: i64 = he_puts(buf, off, "<div class=\"kc-scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 260\" role=\"img\" aria-label=\"\">" as *u8) 83 let st: *i64 = sys_mmap(8) as *i64 84 st[0] = seed 85 l3_rng_next(st) 86 let narc: i64 = 2 + l3_choice(st, 2) 87 let nrules: i64 = 5 + l3_choice(st, 4) 88 let gold: i64 = l3_choice(st, nrules) 89 var a: i64 = 0 90 while a < narc + 1 { 91 let inset: i64 = a * 13 92 let lx: i64 = 30 + inset 93 let rx: i64 = 290 - inset 94 let r: i64 = 130 - inset 95 o = he_puts(buf, o, "<path d=\"M" as *u8) 96 o = l1_put_u8(buf, o, lx) 97 o = he_puts(buf, o, " 250 V130 A" as *u8) 98 o = l1_put_u8(buf, o, r) 99 o = he_puts(buf, o, " " as *u8) 100 o = l1_put_u8(buf, o, r) 101 o = he_puts(buf, o, " 0 0 1 " as *u8) 102 o = l1_put_u8(buf, o, rx) 103 o = he_puts(buf, o, " 130 V250\" fill=\"none\" stroke=\"rgb(255,255,255)\" stroke-width=\"1.5\" opacity=\"" as *u8) 104 if a == 0 { o = he_puts(buf, o, "0.92" as *u8) } else { o = he_puts(buf, o, "0.34" as *u8) } 105 o = he_puts(buf, o, "\"/>" as *u8) 106 a = a + 1 107 } 108 let sp: i64 = 164 / (nrules - 1) 109 let x0: i64 = 160 - ((nrules - 1) * sp) / 2 110 var i: i64 = 0 111 while i < nrules { 112 let x: i64 = x0 + i * sp 113 o = he_puts(buf, o, "<line x1=\"" as *u8) 114 o = l1_put_u8(buf, o, x) 115 o = he_puts(buf, o, "\" y1=\"250\" x2=\"" as *u8) 116 o = l1_put_u8(buf, o, x) 117 o = he_puts(buf, o, "\" y2=\"158\" stroke=\"" as *u8) 118 if i == gold { o = he_puts(buf, o, "var(--kc-gold)\" stroke-width=\"2.6\" opacity=\"1\"" as *u8) } else { o = he_puts(buf, o, "rgb(255,255,255)\" stroke-width=\"1.5\" opacity=\"0.42\"" as *u8) } 119 o = he_puts(buf, o, "/>" as *u8) 120 i = i + 1 121 } 122 o = he_puts(buf, o, "<line x1=\"18\" y1=\"250\" x2=\"302\" y2=\"250\" stroke=\"rgb(255,255,255)\" stroke-width=\"1.5\" opacity=\"0.92\"/><line x1=\"34\" y1=\"257\" x2=\"286\" y2=\"257\" stroke=\"var(--kc-gold)\" stroke-width=\"1.6\" opacity=\"0.85\"/></svg></div>" as *u8) 123 return o 124} 125 126// ---- bands ---- 127func kc_hero(buf: *u8, off: i64, eyebrow: *u8, h1: *u8, lede: *u8, cta: *u8, ctahref: *u8, alt: *u8, althref: *u8, seed: i64) -> i64 { 128 var o: i64 = he_puts(buf, off, "<section class=\"kc-hero wrap\" id=\"top\"><div><span class=\"kc-eyebrow\">" as *u8) 129 o = he_puts(buf, o, eyebrow) 130 o = he_puts(buf, o, "</span><h1>" as *u8) 131 o = he_puts(buf, o, h1) 132 o = he_puts(buf, o, "</h1><p class=\"kc-lede\">" as *u8) 133 o = he_puts(buf, o, lede) 134 o = he_puts(buf, o, "</p><p><a class=\"kc-btn\" href=\"" as *u8) 135 o = he_puts(buf, o, ctahref) 136 o = he_puts(buf, o, "\">" as *u8) 137 o = he_puts(buf, o, cta) 138 o = he_puts(buf, o, "</a><a class=\"kc-alt\" href=\"" as *u8) 139 o = he_puts(buf, o, althref) 140 o = he_puts(buf, o, "\">" as *u8) 141 o = he_puts(buf, o, alt) 142 o = he_puts(buf, o, "</a></p></div>" as *u8) 143 o = kc_scene(buf, o, seed) 144 o = he_puts(buf, o, "</section>" as *u8) 145 return o 146} 147func kc_sec_open(buf: *u8, off: i64, h2pre: *u8, h2em: *u8) -> i64 { 148 var o: i64 = he_puts(buf, off, "<section class=\"kc-sec\"><div class=\"wrap\"><h2>" as *u8) 149 o = he_puts(buf, o, h2pre) 150 o = he_puts(buf, o, " <em>" as *u8) 151 o = he_puts(buf, o, h2em) 152 // the band's CONTENT is one grid cell -- everything the caller emits (list, stats, quote AND the 153 // accreditation row) belongs to the right column (v3 bug: accred wrapped back under the heading) 154 o = he_puts(buf, o, "</em></h2><div>" as *u8) 155 return o 156} 157func kc_sec_close(buf: *u8, off: i64) -> i64 { return he_puts(buf, off, "</div></div></section>" as *u8) } 158func kc_stats_open(buf: *u8, off: i64) -> i64 { return he_puts(buf, off, "<div class=\"kc-stats\">" as *u8) } 159func kc_stat(buf: *u8, off: i64, num: *u8, label: *u8) -> i64 { 160 var o: i64 = he_puts(buf, off, "<div class=\"kc-stat\"><b>" as *u8) 161 o = he_puts(buf, o, num) 162 o = he_puts(buf, o, "</b><span>" as *u8) 163 o = he_puts(buf, o, label) 164 o = he_puts(buf, o, "</span></div>" as *u8) 165 return o 166} 167func kc_stats_close(buf: *u8, off: i64) -> i64 { return he_puts(buf, off, "</div>" as *u8) } 168func kc_list_open(buf: *u8, off: i64) -> i64 { return he_puts(buf, off, "<ul class=\"kc-list\">" as *u8) } 169func kc_item(buf: *u8, off: i64, title: *u8, body: *u8) -> i64 { 170 var o: i64 = he_puts(buf, off, "<li><h3>" as *u8) 171 o = he_puts(buf, o, title) 172 o = he_puts(buf, o, "</h3><p>" as *u8) 173 o = he_puts(buf, o, body) 174 o = he_puts(buf, o, "</p></li>" as *u8) 175 return o 176} 177func kc_list_close(buf: *u8, off: i64) -> i64 { return he_puts(buf, off, "</ul>" as *u8) } 178func kc_quote(buf: *u8, off: i64, quote: *u8, name: *u8, role: *u8) -> i64 { 179 var o: i64 = he_puts(buf, off, "<figure class=\"kc-quote\"><blockquote>" as *u8) 180 o = he_puts(buf, o, quote) 181 o = he_puts(buf, o, "</blockquote><figcaption>" as *u8) 182 o = he_puts(buf, o, name) 183 o = he_puts(buf, o, " &middot; " as *u8) 184 o = he_puts(buf, o, role) 185 o = he_puts(buf, o, "</figcaption></figure>" as *u8) 186 return o 187} 188func kc_accred(buf: *u8, off: i64, a: *u8, b: *u8, c: *u8) -> i64 { 189 var o: i64 = he_puts(buf, off, "<div class=\"kc-accred\"><span>" as *u8) 190 o = he_puts(buf, o, a) 191 o = he_puts(buf, o, "</span><span>" as *u8) 192 o = he_puts(buf, o, b) 193 o = he_puts(buf, o, "</span><span>" as *u8) 194 o = he_puts(buf, o, c) 195 o = he_puts(buf, o, "</span></div>" as *u8) 196 return o 197} 198func kc_final(buf: *u8, off: i64, h2: *u8, p: *u8, cta: *u8, href: *u8) -> i64 { 199 var o: i64 = he_puts(buf, off, "<section class=\"kc-final\"><div class=\"wrap\"><div><h2>" as *u8) 200 o = he_puts(buf, o, h2) 201 o = he_puts(buf, o, "</h2><p>" as *u8) 202 o = he_puts(buf, o, p) 203 o = he_puts(buf, o, "</p></div><a class=\"kc-btn\" href=\"" as *u8) 204 o = he_puts(buf, o, href) 205 o = he_puts(buf, o, "\">" as *u8) 206 o = he_puts(buf, o, cta) 207 o = he_puts(buf, o, "</a></div></section>" as *u8) 208 return o 209}