@rizom/site-rizom-ai 0.2.0-alpha.180 → 0.2.0-alpha.182

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rizom/site-rizom-ai",
3
- "version": "0.2.0-alpha.180",
3
+ "version": "0.2.0-alpha.182",
4
4
  "description": "Rizom AI site package for hosted Rover deployments",
5
5
  "type": "module",
6
6
  "exports": {
@@ -18,9 +18,9 @@
18
18
  "prepack": "publish-manifest prepare"
19
19
  },
20
20
  "dependencies": {
21
- "@rizom/site": "0.2.0-alpha.180",
22
- "@rizom/site-rizom": "0.2.0-alpha.180",
23
- "@rizom/site-sections": "0.2.0-alpha.180",
21
+ "@rizom/site": "0.2.0-alpha.182",
22
+ "@rizom/site-rizom": "0.2.0-alpha.182",
23
+ "@rizom/site-sections": "0.2.0-alpha.182",
24
24
  "preact": "^10.27.2"
25
25
  },
26
26
  "publishConfig": {
@@ -97,6 +97,15 @@ export const SCREEN_STYLES = `
97
97
  @keyframes brainScreenFlicker { 0%, 100% { opacity: .75; } 50% { opacity: 1; } }
98
98
  @media (prefers-reduced-motion: reduce) { .brain-screen .ifc-status i { animation: none; } }
99
99
  @media (max-width: 900px) { .brain-screen .dash-canvas { grid-template-columns: 1fr; } .brain-screen .dash-canvas .ifc-card { grid-column: auto !important; } }
100
+ @media (max-width: 640px) {
101
+ .brain-screen .ifc-strip { flex-wrap: wrap; row-gap: 6px; }
102
+ .brain-screen .ifc-tabs { overflow-x: auto; }
103
+ /* The studio's library pane becomes a horizontal file strip above the
104
+ manuscript instead of a crushed side column. */
105
+ .brain-screen .cms-cols { grid-template-columns: 1fr; }
106
+ .brain-screen .cms-list { display: flex; gap: 2px; overflow-x: auto; padding: 8px 10px; border-right: 0; border-bottom: 1px solid rgba(241,234,221,.09); }
107
+ .brain-screen .cms-item { flex: none; gap: 6px; padding: 5px 10px; border-left: 0; border-radius: 6px; }
108
+ }
100
109
  `;
101
110
 
102
111
  /** Emitted once per page; scopes all screen styles under `.brain-screen`. */
package/src/brain.tsx CHANGED
@@ -237,7 +237,7 @@ function BrainRunSection({
237
237
  headline={headline}
238
238
  intro={intro}
239
239
  />
240
- <div className="reveal reveal-delay-1 mt-7 max-w-[1120px]">
240
+ <div className="reveal reveal-delay-1 mt-7">
241
241
  <DashboardScreen />
242
242
  </div>
243
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]">
@@ -334,7 +334,7 @@ function BrainQuickstartSection({
334
334
  return (
335
335
  <Section id="quickstart" className="py-14">
336
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]">
337
+ <div className="mt-7 grid items-start gap-12 md:grid-cols-[1.15fr_1fr]">
338
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
339
  {lines.map((line, i) => (
340
340
  <div key={i} className={termLineClass(line.kind)}>
@@ -159,7 +159,7 @@ function FoundationSupportSection({
159
159
  return (
160
160
  <Section id="support" className="py-14">
161
161
  <SectCap lead={cap} trail={capNote} />
162
- <div className="mt-[26px] grid max-w-[900px] gap-13 md:grid-cols-2">
162
+ <div className="mt-[26px] grid gap-13 md:grid-cols-2">
163
163
  {options.map((option, i) => (
164
164
  <div key={option.kicker} className={`reveal ${delayClass(i + 1)}`}>
165
165
  <span className="font-label text-label-xs uppercase tracking-[0.16em] text-accent">
@@ -168,7 +168,7 @@ function FoundationSupportSection({
168
168
  <div className="mt-2 font-display text-[30px] font-[480] text-theme [font-variation-settings:'SOFT'_40]">
169
169
  {option.amount}
170
170
  </div>
171
- <p className="mt-2 font-body text-[15.5px] text-theme-light">
171
+ <p className="mt-2 max-w-[52ch] font-body text-[15.5px] text-theme-light">
172
172
  {option.text}
173
173
  </p>
174
174
  </div>
@@ -8,7 +8,7 @@ import type { JSX } from "preact";
8
8
  The wrapper's `reveal` class lets boot.js trigger the sequence. */
9
9
  export function GrowthDiagram(): JSX.Element {
10
10
  return (
11
- <div className="growth reveal reveal-delay-1 mt-5 max-w-[1020px]">
11
+ <div className="growth reveal reveal-delay-1 mt-5">
12
12
  <svg
13
13
  viewBox="0 0 980 290"
14
14
  role="img"
package/src/layout.tsx CHANGED
@@ -67,13 +67,14 @@ const FACE_CHROME: Record<FaceKey, FaceChrome> = {
67
67
  },
68
68
  };
69
69
 
70
- // The umbrella page's own chrome: the plain wordmark, links into the room and
71
- // docs, and a get-started CTA that points at the product room.
70
+ // The umbrella page's own chrome: the plain wordmark, the org-level indexes
71
+ // (everything published, everyone in the network the strip above already
72
+ // offers the faces), and a get-started CTA that points at the product room.
72
73
  const HOME_CHROME: FaceChrome = {
73
74
  nameplate: null,
74
75
  links: [
75
- { label: "Brain", href: "/brain" },
76
- { label: "Docs ↗", href: "https://docs.rizom.ai", external: true },
76
+ { label: "Writing", href: "/writing" },
77
+ { label: "Network", href: "/network" },
77
78
  ],
78
79
  cta: { label: "Get Started", href: "/brain" },
79
80
  };
@@ -94,8 +95,9 @@ function activeFace(path: string): FaceKey {
94
95
  }
95
96
 
96
97
  // The org-level indexes: cross-room aggregations (everything published,
97
- // everyone in the network) that belong to no single face. They live
98
- // top-right on every face, and claim the current page on their own path.
98
+ // everyone in the network) that belong to no single face. They live in the
99
+ // home nav and the footer; the strip only needs their paths so no face
100
+ // claims the current page there.
99
101
  const ORG_INDEXES: { label: string; href: string }[] = [
100
102
  { label: "Writing", href: "/writing" },
101
103
  { label: "Network", href: "/network" },
@@ -113,15 +115,20 @@ function FacesStrip({ path }: { path: string }): JSX.Element {
113
115
  const activeIndex = orgIndexActive(path);
114
116
  const home = isHome(path);
115
117
  return (
116
- <div className="relative z-[2] flex items-baseline gap-6 border-b border-theme-light px-6 py-3 font-label text-label-xs uppercase tracking-[0.14em] md:px-10 xl:px-20">
117
- <span className="text-theme-muted">rizom</span>
118
+ <div className="relative z-[2] flex flex-wrap items-baseline gap-x-4 gap-y-1.5 border-b border-theme-light px-4 py-3 font-label text-label-xs uppercase tracking-[0.12em] sm:gap-x-6 sm:px-6 sm:tracking-[0.14em] md:px-10 xl:px-20">
119
+ <a
120
+ href="/"
121
+ className="-my-2 inline-block py-2 text-theme-muted transition-colors hover:text-theme"
122
+ >
123
+ rizom
124
+ </a>
118
125
  {FACES.map((item) =>
119
126
  // No face is current on the umbrella home, nor on a cross-room index.
120
127
  item.key === face && !activeIndex && !home ? (
121
128
  <a
122
129
  key={item.key}
123
130
  href={item.href}
124
- className="text-accent"
131
+ className="-my-2 inline-block py-2 text-accent"
125
132
  aria-current="page"
126
133
  >
127
134
  {item.label}
@@ -130,28 +137,23 @@ function FacesStrip({ path }: { path: string }): JSX.Element {
130
137
  <a
131
138
  key={item.key}
132
139
  href={item.href}
133
- className="text-theme-light transition-colors hover:text-theme"
140
+ className="-my-2 inline-block py-2 text-theme-light transition-colors hover:text-theme"
134
141
  >
135
142
  {item.label}
136
143
  </a>
137
144
  ),
138
145
  )}
139
- <div className="ml-auto flex items-baseline gap-6">
140
- {ORG_INDEXES.map((index) => {
141
- const active = activeIndex === index.href;
142
- return (
143
- <a
144
- key={index.href}
145
- href={index.href}
146
- className={`transition-colors ${
147
- active ? "text-accent" : "text-theme-light hover:text-theme"
148
- }`}
149
- {...(active ? { "aria-current": "page" } : {})}
150
- >
151
- {index.label}
152
- </a>
153
- );
154
- })}
146
+ <div className="ml-auto flex items-baseline">
147
+ {/* boot.js binds by id and syncs the label; window.toggleTheme
148
+ (injected by site-engine) flips data-theme + persists it. */}
149
+ <button
150
+ id="themeToggle"
151
+ type="button"
152
+ aria-label="Toggle color theme"
153
+ className="-my-2 inline-block cursor-pointer py-2 uppercase text-theme-light transition-colors hover:text-theme"
154
+ >
155
+ ☀ Light
156
+ </button>
155
157
  </div>
156
158
  </div>
157
159
  );
@@ -161,13 +163,13 @@ function Wordmark({ nameplate }: { nameplate: string | null }): JSX.Element {
161
163
  return (
162
164
  <a
163
165
  href="/"
164
- className="font-display text-[26px] font-semibold tracking-[-0.01em] [font-variation-settings:'SOFT'_100]"
166
+ className="font-display text-[clamp(22px,5.5vw,26px)] font-semibold tracking-[-0.01em] [font-variation-settings:'SOFT'_100]"
165
167
  aria-label="Rizom home"
166
168
  >
167
169
  <span className="text-theme">rizom</span>
168
170
  <span className="text-accent">.</span>
169
171
  {nameplate && (
170
- <span className="text-[20px] font-normal text-theme-muted">
172
+ <span className="text-[clamp(17px,4.3vw,20px)] font-normal text-theme-muted">
171
173
  {nameplate}
172
174
  </span>
173
175
  )}
@@ -177,21 +179,25 @@ function Wordmark({ nameplate }: { nameplate: string | null }): JSX.Element {
177
179
 
178
180
  function FaceNav({
179
181
  face,
180
- home,
182
+ umbrella,
181
183
  }: {
182
184
  face: FaceKey;
183
- home: boolean;
185
+ umbrella: boolean;
184
186
  }): JSX.Element {
185
- const chrome = home ? HOME_CHROME : FACE_CHROME[face];
187
+ // Home and the org indexes (/writing, /network) belong to no face
188
+ // they wear the plain umbrella chrome, not a room nameplate.
189
+ const chrome = umbrella ? HOME_CHROME : FACE_CHROME[face];
186
190
  // Deliberately NOT merged with siteInfo.navigation: entity plugins
187
191
  // register slot-based nav entries for every list route (topics,
188
192
  // posts, …), which floods the bar. Each room owns its own links.
189
193
  const links: FaceLink[] = chrome.links;
190
194
 
191
195
  return (
192
- <nav className="relative z-[2] flex items-baseline gap-8 px-6 py-5 md:px-10 xl:px-20">
196
+ <nav className="relative z-[2] flex items-baseline gap-4 px-4 py-5 sm:gap-8 sm:px-6 md:px-10 xl:px-20">
193
197
  <Wordmark nameplate={chrome.nameplate} />
194
- <div className="hidden items-baseline gap-7 md:flex">
198
+ {/* Below sm the footer carries every chrome link; the row keeps
199
+ just the wordmark and the CTA so nothing overflows. */}
200
+ <div className="hidden items-baseline gap-7 sm:flex">
195
201
  {links.map((link) => (
196
202
  <a
197
203
  key={`${link.href}-${link.label}`}
@@ -205,7 +211,7 @@ function FaceNav({
205
211
  <div className="flex-1" />
206
212
  <a
207
213
  href={chrome.cta.href}
208
- className="self-center rounded-[3px] bg-accent px-[18px] py-[9px] font-body text-[16px] font-medium text-theme-inverse transition-[filter,transform] hover:brightness-110 hover:-translate-y-px"
214
+ className="self-center whitespace-nowrap rounded-[3px] bg-accent px-3.5 py-2 font-body text-[15px] font-medium text-theme-inverse transition-[filter,transform] hover:brightness-110 hover:-translate-y-px sm:px-[18px] sm:py-[9px] sm:text-[16px]"
209
215
  >
210
216
  {chrome.cta.label}
211
217
  </a>
@@ -265,7 +271,7 @@ function SiteFooter({
265
271
  siteInfo: RizomLayoutProps["siteInfo"];
266
272
  }): JSX.Element {
267
273
  return (
268
- <footer className="relative z-[1] grid gap-10 border-t border-theme px-6 pt-11 pb-[38px] md:grid-cols-2 md:px-10 xl:grid-cols-[1.3fr_1fr_1fr_1fr] xl:px-20">
274
+ <footer className="relative z-[1] grid gap-10 border-t border-theme px-4 pt-11 pb-[38px] sm:grid-cols-2 sm:px-6 md:px-10 lg:grid-cols-[1.3fr_1fr_1fr_1fr] xl:px-20">
269
275
  <div>
270
276
  <a
271
277
  href="/"
@@ -287,7 +293,7 @@ function SiteFooter({
287
293
  <a
288
294
  key={link.href + link.label}
289
295
  href={link.href}
290
- className="block py-[3px] font-body text-[15.5px] text-theme-light no-underline transition-colors hover:text-theme"
296
+ className="block py-1.5 font-body text-[15.5px] text-theme-light no-underline transition-colors hover:text-theme"
291
297
  >
292
298
  {link.label}
293
299
  </a>
@@ -357,7 +363,7 @@ function RizomAiChrome({
357
363
  children: ComponentChildren;
358
364
  }): JSX.Element {
359
365
  const face = activeFace(path);
360
- const home = isHome(path);
366
+ const umbrella = isHome(path) || orgIndexActive(path) !== null;
361
367
  return (
362
368
  <RizomFrame canvas={false}>
363
369
  {/* xl:pl matches the mockup's 148px left rail (68 + the 80px
@@ -366,7 +372,7 @@ function RizomAiChrome({
366
372
  <MyceliumRail />
367
373
  <header className="sticky top-0 z-[100] border-b border-theme-light bg-nav-fade backdrop-blur-[12px]">
368
374
  <FacesStrip path={path} />
369
- <FaceNav face={face} home={home} />
375
+ <FaceNav face={face} umbrella={umbrella} />
370
376
  </header>
371
377
  <main>{children}</main>
372
378
  <SiteFooter siteInfo={siteInfo} />
package/src/shared.tsx CHANGED
@@ -44,11 +44,15 @@ export function SectCap({
44
44
  <p
45
45
  className={`reveal flex flex-wrap items-baseline gap-3.5 font-label text-label-xs uppercase tracking-[0.2em] ${className}`}
46
46
  >
47
- <span
48
- aria-hidden="true"
49
- className="h-px w-[26px] self-center bg-accent opacity-80"
50
- />
51
- <span className="font-medium text-accent">{lead}</span>
47
+ {/* Tick and lead wrap as one unit — a long trail may drop to its
48
+ own line, but the tick never orphans away from the lead. */}
49
+ <span className="flex items-baseline gap-3.5">
50
+ <span
51
+ aria-hidden="true"
52
+ className="h-px w-[26px] self-center bg-accent opacity-80"
53
+ />
54
+ <span className="font-medium text-accent">{lead}</span>
55
+ </span>
52
56
  {trail && (
53
57
  <span className="normal-case tracking-[0.1em] text-theme-light">
54
58
  {trail}
@@ -133,7 +137,10 @@ export function IndexRow({
133
137
  <span className="font-label text-label-xs uppercase tracking-[0.1em] text-theme-light">
134
138
  {row.kicker}
135
139
  </span>
136
- <span className="block">
140
+ {/* Below md the two-column grid is folio|kicker on the first row;
141
+ title and meta take full-width rows of their own instead of
142
+ falling into the 44px folio column. */}
143
+ <span className="col-span-2 block md:col-span-1">
137
144
  <span className="block font-display text-[26px] font-[470] tracking-[-0.01em] text-theme transition-colors group-hover:text-accent [font-variation-settings:'SOFT'_75,'opsz'_60]">
138
145
  {row.title}
139
146
  </span>
@@ -141,7 +148,7 @@ export function IndexRow({
141
148
  {row.text}
142
149
  </span>
143
150
  </span>
144
- <span className="text-right font-label text-[12px] text-theme-light">
151
+ <span className="col-span-2 text-right font-label text-[12px] text-theme-light md:col-span-1">
145
152
  {row.meta ?? "→"}
146
153
  {row.metaSub && (
147
154
  <small className="block text-theme-light opacity-70">
@@ -152,7 +159,7 @@ export function IndexRow({
152
159
  </>
153
160
  );
154
161
 
155
- const rowClass = `reveal ${delayClass} group grid max-w-[1040px] grid-cols-[44px_1fr] items-baseline gap-6 border-t border-theme-light py-6 no-underline md:grid-cols-[64px_176px_1fr_auto]`;
162
+ const rowClass = `reveal ${delayClass} group grid grid-cols-[44px_1fr] items-baseline gap-x-6 gap-y-2 border-t border-theme-light py-6 no-underline md:grid-cols-[64px_176px_1fr_auto] md:gap-6`;
156
163
 
157
164
  return row.href ? (
158
165
  <a href={row.href} className={rowClass}>
@@ -181,7 +188,7 @@ export function AliveLine({
181
188
  <a
182
189
  key={link.href + link.label}
183
190
  href={link.href}
184
- className={`reveal ${i > 0 ? "reveal-delay-1" : ""} border-b border-theme-light font-label text-[12px] text-theme-light no-underline transition-colors hover:text-accent-bright`}
191
+ className={`reveal ${i > 0 ? "reveal-delay-1" : ""} -mt-2 inline-block border-b border-theme-light pt-2 font-label text-[12px] text-theme-light no-underline transition-colors hover:text-accent-bright`}
185
192
  >
186
193
  {link.label}
187
194
  </a>
@@ -230,7 +237,7 @@ export function Trio({
230
237
  mono: boolean;
231
238
  }): JSX.Element {
232
239
  return (
233
- <div className="mt-[30px] grid max-w-[1040px] gap-11 md:grid-cols-3">
240
+ <div className="mt-[30px] grid gap-11 md:grid-cols-3">
234
241
  {items.map((item, i) => (
235
242
  <div key={item.title} className={`reveal ${delayClass(i)}`}>
236
243
  {mono ? (
package/src/work.tsx CHANGED
@@ -216,7 +216,7 @@ function WorkWorkshopSection({
216
216
  return (
217
217
  <Section id="workshop" className="py-14">
218
218
  <Statement {...statement} />
219
- <div className="mt-7 max-w-[880px]">
219
+ <div className="mt-7">
220
220
  {steps.map((step, i) => (
221
221
  <div
222
222
  key={step.title}
@@ -228,7 +228,8 @@ function WorkWorkshopSection({
228
228
  <b className="font-display text-[21px] font-[520] text-theme [font-variation-settings:'SOFT'_60]">
229
229
  {step.title}
230
230
  </b>
231
- <div>
231
+ {/* The row spans the column; the copy keeps a reading measure. */}
232
+ <div className="max-w-[60ch]">
232
233
  <p className="mb-[3px] font-body text-[16.5px] text-theme-muted">
233
234
  {step.lead}
234
235
  </p>
@@ -263,7 +264,7 @@ function WorkPersonasSection({
263
264
  return (
264
265
  <Section id="personas" className="py-14">
265
266
  <SectCap lead={cap} />
266
- <div className="mt-7 grid max-w-[980px] gap-11 md:grid-cols-2">
267
+ <div className="mt-7 grid gap-11 md:grid-cols-2">
267
268
  {personas.map((persona, i) => (
268
269
  <div key={persona.role} className={`reveal ${delayClass(i + 1)}`}>
269
270
  <span className="font-label text-label-xs uppercase tracking-[0.16em] text-accent">
@@ -272,7 +273,7 @@ function WorkPersonasSection({
272
273
  <blockquote className="mt-2.5 font-display text-[24px] font-[450] italic leading-[1.3] tracking-[-0.008em] text-theme [font-variation-settings:'SOFT'_85]">
273
274
  {persona.quote}
274
275
  </blockquote>
275
- <p className="mt-2.5 font-body text-[16px] text-theme-light">
276
+ <p className="mt-2.5 max-w-[52ch] font-body text-[16px] text-theme-light">
276
277
  {persona.text}
277
278
  </p>
278
279
  </div>
@@ -303,7 +304,7 @@ function WorkQuotesSection({
303
304
  return (
304
305
  <Section id="proof" className="py-14">
305
306
  <SectCap lead={cap} trail={capNote} />
306
- <div className="mt-7 max-w-[980px]">
307
+ <div className="mt-7">
307
308
  {quotes.map((quote, i) => (
308
309
  <div
309
310
  key={quote.by}
@@ -352,7 +353,7 @@ function WorkRosterSection({
352
353
  return (
353
354
  <Section id="people" className="py-14">
354
355
  <SectCap lead={cap} trail={capNote} />
355
- <div className="reveal reveal-delay-1 mt-6 flex max-w-[900px] flex-wrap gap-x-[34px] gap-y-2.5">
356
+ <div className="reveal reveal-delay-1 mt-6 flex flex-wrap gap-x-[34px] gap-y-2.5">
356
357
  {people.map((person) => (
357
358
  <span
358
359
  key={person.name}