@rizom/site-rizom-ai 0.2.0-alpha.166 → 0.2.0-alpha.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/brain.tsx ADDED
@@ -0,0 +1,418 @@
1
+ /** @jsxImportSource preact */
2
+ import type { JSX } from "preact";
3
+ import type { SiteSectionGroup } from "@rizom/site";
4
+ import { defineSection, sectionGroup, z } from "@rizom/site-sections";
5
+ import { Section, renderHighlightedText } from "@rizom/site-rizom";
6
+ import {
7
+ Band,
8
+ CtaRow,
9
+ SectCap,
10
+ Trio,
11
+ trioSchema,
12
+ ctaSchema,
13
+ ROOM_HIGHLIGHT_CLS,
14
+ } from "./shared";
15
+ import {
16
+ BrainScreenStyles,
17
+ StudioScreen,
18
+ ChatScreen,
19
+ IntegrationsScreen,
20
+ DashboardScreen,
21
+ } from "./brain-screens";
22
+
23
+ /**
24
+ * The /brain room — the product's own page. The consolidated homepage grew
25
+ * two pages long because it told the umbrella story and the product story at
26
+ * once; the product story lives here, told as the brain's life with its owner
27
+ * in four chapters — capture, ask, see it run, connect — each illustrated by a
28
+ * real interface screen, then the data principles and the quickstart.
29
+ *
30
+ * The namespace ("brain") matches the route id, so each section stores as
31
+ * site-content/brain/<section>.md and resolves as "brain:<section>".
32
+ */
33
+
34
+ /* ============ chapter heading ============ */
35
+
36
+ /* The shared chapter head: a numbered cap, a display headline with an accent
37
+ em, and a standfirst. Used by every chapter so the copy stays authored. */
38
+ function ChapterHead({
39
+ cap,
40
+ capNote,
41
+ headline,
42
+ intro,
43
+ }: {
44
+ cap: string;
45
+ capNote?: string | undefined;
46
+ headline: string;
47
+ intro: string;
48
+ }): JSX.Element {
49
+ return (
50
+ <>
51
+ <SectCap lead={cap} trail={capNote} />
52
+ <h2 className="reveal reveal-delay-1 mt-3.5 max-w-[20em] font-display text-[clamp(28px,3vw,40px)] font-[465] leading-[1.1] tracking-[-0.014em] text-theme [font-variation-settings:'SOFT'_78,'opsz'_84]">
53
+ {renderHighlightedText(headline, ROOM_HIGHLIGHT_CLS)}
54
+ </h2>
55
+ <p className="reveal reveal-delay-2 mt-4 max-w-[62ch] font-body text-[17px] leading-[1.7] text-theme-muted">
56
+ {intro}
57
+ </p>
58
+ </>
59
+ );
60
+ }
61
+
62
+ /* ============ hero ============ */
63
+
64
+ const heroSchema = z.object({
65
+ eyebrow: z.string(),
66
+ provenance: z.string(),
67
+ headline: z.string(),
68
+ standfirst: z.string(),
69
+ primaryCta: ctaSchema,
70
+ secondaryCta: ctaSchema,
71
+ chips: z.array(z.string()),
72
+ });
73
+
74
+ function BrainHeroSection({
75
+ eyebrow,
76
+ provenance,
77
+ headline,
78
+ standfirst,
79
+ primaryCta,
80
+ secondaryCta,
81
+ chips,
82
+ }: z.infer<typeof heroSchema>): JSX.Element {
83
+ return (
84
+ <Section
85
+ id="brain-hero"
86
+ className="relative overflow-hidden pt-16 pb-8 md:pt-20"
87
+ >
88
+ <div
89
+ aria-hidden="true"
90
+ className="pointer-events-none absolute -inset-x-[10%] -inset-y-[30%] bg-[radial-gradient(680px_360px_at_14%_8%,rgb(from_var(--color-accent)_r_g_b_/_0.14),transparent_66%)]"
91
+ />
92
+ <div className="relative">
93
+ <SectCap lead={eyebrow} trail={provenance} />
94
+ <h1 className="mt-[18px] max-w-[15.5em] font-display text-[clamp(36px,4.8vw,64px)] font-[448] leading-[1.04] tracking-[-0.02em] text-theme [font-variation-settings:'SOFT'_88,'opsz'_110]">
95
+ {renderHighlightedText(headline, ROOM_HIGHLIGHT_CLS)}
96
+ </h1>
97
+ <p className="mt-4 max-w-[52ch] font-body text-[20px] leading-[1.7] text-theme-muted">
98
+ {standfirst}
99
+ </p>
100
+ <CtaRow
101
+ primaryCta={primaryCta}
102
+ secondaryCta={secondaryCta}
103
+ className="mt-[26px]"
104
+ />
105
+ <div className="mt-9 flex flex-wrap gap-2.5">
106
+ {chips.map((chip) => (
107
+ <span
108
+ key={chip}
109
+ className="rounded-full border border-theme px-[13px] py-1.5 font-label text-[10.5px] tracking-[0.06em] text-theme-light"
110
+ >
111
+ {chip}
112
+ </span>
113
+ ))}
114
+ </div>
115
+ </div>
116
+ </Section>
117
+ );
118
+ }
119
+
120
+ /* ============ shared authored checklist ============ */
121
+
122
+ function Checks({ items }: { items: string[] }): JSX.Element {
123
+ return (
124
+ <ul className="mt-[18px] max-w-[40ch] font-body text-[15.5px] text-theme-light">
125
+ {items.map((item) => (
126
+ <li
127
+ key={item}
128
+ className="flex gap-2.5 border-b border-theme-light py-[7px]"
129
+ >
130
+ <span aria-hidden="true" className="font-label text-secondary">
131
+
132
+ </span>
133
+ {item}
134
+ </li>
135
+ ))}
136
+ </ul>
137
+ );
138
+ }
139
+
140
+ /* ============ 01 · capture — the studio ============ */
141
+
142
+ const captureSchema = z.object({
143
+ cap: z.string(),
144
+ capNote: z.string().optional(),
145
+ headline: z.string(),
146
+ intro: z.string(),
147
+ checks: z.array(z.string()),
148
+ });
149
+
150
+ function BrainCaptureSection({
151
+ cap,
152
+ capNote,
153
+ headline,
154
+ intro,
155
+ checks,
156
+ }: z.infer<typeof captureSchema>): JSX.Element {
157
+ return (
158
+ <Section id="capture" className="py-14">
159
+ {/* Screen styles are global; emitted once here, the first screen chapter. */}
160
+ <BrainScreenStyles />
161
+ <SectCap lead={cap} trail={capNote} />
162
+ <div className="mt-4 grid items-center gap-11 lg:grid-cols-[4fr_8fr]">
163
+ <div>
164
+ <h2 className="reveal reveal-delay-1 font-display text-[clamp(26px,2.6vw,34px)] font-[465] leading-[1.12] tracking-[-0.012em] text-theme [font-variation-settings:'SOFT'_78,'opsz'_84]">
165
+ {renderHighlightedText(headline, ROOM_HIGHLIGHT_CLS)}
166
+ </h2>
167
+ <p className="reveal reveal-delay-2 mt-4 font-body text-[16.5px] leading-[1.7] text-theme-muted">
168
+ {intro}
169
+ </p>
170
+ <Checks items={checks} />
171
+ </div>
172
+ <div className="reveal reveal-delay-2">
173
+ <StudioScreen />
174
+ </div>
175
+ </div>
176
+ </Section>
177
+ );
178
+ }
179
+
180
+ /* ============ 02 · ask — the chat and its integrations ============ */
181
+
182
+ const askSchema = z.object({
183
+ cap: z.string(),
184
+ capNote: z.string().optional(),
185
+ headline: z.string(),
186
+ intro: z.string(),
187
+ });
188
+
189
+ function BrainAskSection({
190
+ cap,
191
+ capNote,
192
+ headline,
193
+ intro,
194
+ }: z.infer<typeof askSchema>): JSX.Element {
195
+ return (
196
+ <Section id="ask" className="py-14">
197
+ <ChapterHead
198
+ cap={cap}
199
+ capNote={capNote}
200
+ headline={headline}
201
+ intro={intro}
202
+ />
203
+ <div className="mt-7 grid items-start gap-6 lg:grid-cols-[1.12fr_1fr]">
204
+ <div className="reveal reveal-delay-1">
205
+ <ChatScreen />
206
+ </div>
207
+ <div className="reveal reveal-delay-2">
208
+ <IntegrationsScreen />
209
+ </div>
210
+ </div>
211
+ </Section>
212
+ );
213
+ }
214
+
215
+ /* ============ 03 · see it run — the dashboard ============ */
216
+
217
+ const runSchema = z.object({
218
+ cap: z.string(),
219
+ capNote: z.string().optional(),
220
+ headline: z.string(),
221
+ intro: z.string(),
222
+ note: z.string(),
223
+ });
224
+
225
+ function BrainRunSection({
226
+ cap,
227
+ capNote,
228
+ headline,
229
+ intro,
230
+ note,
231
+ }: z.infer<typeof runSchema>): JSX.Element {
232
+ return (
233
+ <Section id="run" className="py-14">
234
+ <ChapterHead
235
+ cap={cap}
236
+ capNote={capNote}
237
+ headline={headline}
238
+ intro={intro}
239
+ />
240
+ <div className="reveal reveal-delay-1 mt-7 max-w-[1120px]">
241
+ <DashboardScreen />
242
+ </div>
243
+ <p className="reveal reveal-delay-2 mt-5 max-w-[52em] font-display text-[17px] font-normal italic text-theme-light [font-variation-settings:'SOFT'_85]">
244
+ {renderHighlightedText(note, "font-medium not-italic text-theme-muted")}
245
+ </p>
246
+ </Section>
247
+ );
248
+ }
249
+
250
+ /* ============ 04 · connect — back to the map ============ */
251
+
252
+ const connectSchema = z.object({
253
+ cap: z.string(),
254
+ capNote: z.string().optional(),
255
+ headline: z.string(),
256
+ intro: z.string(),
257
+ cta: ctaSchema,
258
+ });
259
+
260
+ function BrainConnectSection({
261
+ cap,
262
+ capNote,
263
+ headline,
264
+ intro,
265
+ cta,
266
+ }: z.infer<typeof connectSchema>): JSX.Element {
267
+ return (
268
+ <Section id="connect" className="py-14">
269
+ <ChapterHead
270
+ cap={cap}
271
+ capNote={capNote}
272
+ headline={headline}
273
+ intro={intro}
274
+ />
275
+ <div className="reveal reveal-delay-2 mt-6">
276
+ <a
277
+ href={cta.href}
278
+ className="font-body text-[15.5px] text-theme-light no-underline transition-colors hover:text-accent"
279
+ >
280
+ {cta.label}
281
+ </a>
282
+ </div>
283
+ </Section>
284
+ );
285
+ }
286
+
287
+ /* ============ your data, your rules ============ */
288
+
289
+ function BrainYourDataSection({
290
+ cap,
291
+ items,
292
+ }: z.infer<typeof trioSchema>): JSX.Element {
293
+ return (
294
+ <Section id="your-data" className="py-14">
295
+ <SectCap lead={cap} />
296
+ <Trio items={items} mono={true} />
297
+ </Section>
298
+ );
299
+ }
300
+
301
+ /* ============ quickstart ============ */
302
+
303
+ const termLineSchema = z.object({
304
+ kind: z.enum(["comment", "command", "ok"]),
305
+ text: z.string(),
306
+ });
307
+
308
+ const quickstartSchema = z.object({
309
+ cap: z.string(),
310
+ capNote: z.string(),
311
+ lines: z.array(termLineSchema),
312
+ checks: z.array(z.string()),
313
+ });
314
+
315
+ type TermLine = z.infer<typeof termLineSchema>;
316
+
317
+ function termLineClass(kind: TermLine["kind"]): string {
318
+ switch (kind) {
319
+ case "comment":
320
+ return "text-theme-light opacity-70";
321
+ case "ok":
322
+ return "text-secondary";
323
+ case "command":
324
+ return "text-theme";
325
+ }
326
+ }
327
+
328
+ function BrainQuickstartSection({
329
+ cap,
330
+ capNote,
331
+ lines,
332
+ checks,
333
+ }: z.infer<typeof quickstartSchema>): JSX.Element {
334
+ return (
335
+ <Section id="quickstart" className="py-14">
336
+ <SectCap lead={cap} trail={capNote} />
337
+ <div className="mt-7 grid max-w-[1000px] items-start gap-12 md:grid-cols-[1.15fr_1fr]">
338
+ <div className="reveal reveal-delay-1 border border-theme bg-theme-subtle/60 px-6 py-5 font-label text-[14px] leading-[1.9]">
339
+ {lines.map((line, i) => (
340
+ <div key={i} className={termLineClass(line.kind)}>
341
+ {line.kind === "command" && (
342
+ <span className="select-none text-accent">$ </span>
343
+ )}
344
+ {line.text}
345
+ </div>
346
+ ))}
347
+ </div>
348
+ <Checks items={checks} />
349
+ </div>
350
+ </Section>
351
+ );
352
+ }
353
+
354
+ /* ============ closing band ============ */
355
+
356
+ const closeSchema = z.object({
357
+ quote: z.string(),
358
+ sub: z.string(),
359
+ primaryCta: ctaSchema,
360
+ secondaryCta: ctaSchema,
361
+ });
362
+
363
+ function BrainCloseSection({
364
+ quote,
365
+ sub,
366
+ primaryCta,
367
+ secondaryCta,
368
+ }: z.infer<typeof closeSchema>): JSX.Element {
369
+ return (
370
+ <Band quote={quote}>
371
+ <p className="reveal reveal-delay-1 mt-[18px] max-w-[52ch] font-body text-[17px] text-theme-light">
372
+ {sub}
373
+ </p>
374
+ <CtaRow
375
+ primaryCta={primaryCta}
376
+ secondaryCta={secondaryCta}
377
+ className="reveal reveal-delay-2 mt-[26px]"
378
+ />
379
+ </Band>
380
+ );
381
+ }
382
+
383
+ /* ============ the brain section group ============ */
384
+
385
+ export const brainSections: SiteSectionGroup = sectionGroup("brain", {
386
+ hero: defineSection(heroSchema, BrainHeroSection, {
387
+ title: "Hero",
388
+ description: "Product hero — build the agent that represents you",
389
+ }),
390
+ capture: defineSection(captureSchema, BrainCaptureSection, {
391
+ title: "Capture",
392
+ description: "01 · Capture — markdown corpus, illustrated by the studio",
393
+ }),
394
+ ask: defineSection(askSchema, BrainAskSection, {
395
+ title: "Ask",
396
+ description: "02 · Ask — chat + Discord, Claude/MCP, terminal",
397
+ }),
398
+ run: defineSection(runSchema, BrainRunSection, {
399
+ title: "See It Run",
400
+ description: "03 · See it run — the dashboard overview",
401
+ }),
402
+ connect: defineSection(connectSchema, BrainConnectSection, {
403
+ title: "Connect",
404
+ description: "04 · Connect — takes your seat in the network (the map)",
405
+ }),
406
+ "your-data": defineSection(trioSchema, BrainYourDataSection, {
407
+ title: "Your Data",
408
+ description: "Your data, your rules — ownership trio (mono markers)",
409
+ }),
410
+ quickstart: defineSection(quickstartSchema, BrainQuickstartSection, {
411
+ title: "Quickstart",
412
+ description: "Three-command quickstart terminal with a checklist",
413
+ }),
414
+ close: defineSection(closeSchema, BrainCloseSection, {
415
+ title: "Close",
416
+ description: "Closing band — own the intelligence you already have",
417
+ }),
418
+ });