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, " · " 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}