@nous-research/ui 0.15.0 → 0.16.0

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.
Files changed (216) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/README.md +24 -4
  3. package/dist/fonts.js +1 -0
  4. package/dist/hooks/use-capped-frame.js +1 -0
  5. package/dist/hooks/use-css-var-dims.js +1 -0
  6. package/dist/hooks/use-gpu-tier.js +1 -0
  7. package/dist/hooks/use-render-loop.js +1 -0
  8. package/dist/hooks/use-smooth-controls.js +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/ui/basic-page.js +1 -0
  11. package/dist/ui/components/animated-count.js +1 -0
  12. package/dist/ui/components/ascii.js +1 -0
  13. package/dist/ui/components/badge.js +2 -1
  14. package/dist/ui/components/badges/nous-girl.js +1 -0
  15. package/dist/ui/components/blend-mode.js +1 -0
  16. package/dist/ui/components/blink.js +1 -0
  17. package/dist/ui/components/button.js +2 -1
  18. package/dist/ui/components/checkbox.js +1 -0
  19. package/dist/ui/components/command-block.js +4 -3
  20. package/dist/ui/components/cursor.js +1 -0
  21. package/dist/ui/components/dropdown-menu.js +1 -0
  22. package/dist/ui/components/fit-text/index.js +1 -0
  23. package/dist/ui/components/graphs/bar-chart.js +1 -0
  24. package/dist/ui/components/graphs/index.js +1 -0
  25. package/dist/ui/components/graphs/line-chart.js +1 -0
  26. package/dist/ui/components/graphs/utils.js +1 -0
  27. package/dist/ui/components/grid/index.js +1 -0
  28. package/dist/ui/components/hover-bg.js +1 -0
  29. package/dist/ui/components/icons/arrow.js +1 -0
  30. package/dist/ui/components/icons/check.js +1 -0
  31. package/dist/ui/components/icons/chevron.js +1 -0
  32. package/dist/ui/components/icons/discord.js +1 -0
  33. package/dist/ui/components/icons/eye.js +1 -0
  34. package/dist/ui/components/icons/gear.js +1 -0
  35. package/dist/ui/components/icons/github.js +1 -0
  36. package/dist/ui/components/icons/hamburger.js +1 -0
  37. package/dist/ui/components/icons/heart.js +1 -0
  38. package/dist/ui/components/icons/index.js +1 -0
  39. package/dist/ui/components/icons/link.js +1 -0
  40. package/dist/ui/components/icons/minus.js +1 -0
  41. package/dist/ui/components/icons/search.js +1 -0
  42. package/dist/ui/components/image-distortion.js +1 -0
  43. package/dist/ui/components/leva-client.js +1 -0
  44. package/dist/ui/components/list-item.js +3 -2
  45. package/dist/ui/components/modal/index.js +1 -0
  46. package/dist/ui/components/modal/modal.css +1 -1
  47. package/dist/ui/components/overlays/blend-modes.js +1 -0
  48. package/dist/ui/components/overlays/glitch.js +1 -0
  49. package/dist/ui/components/overlays/greys.js +1 -0
  50. package/dist/ui/components/overlays/index.js +1 -0
  51. package/dist/ui/components/overlays/lens-layers.js +1 -0
  52. package/dist/ui/components/overlays/lens.js +1 -0
  53. package/dist/ui/components/overlays/noise.js +1 -0
  54. package/dist/ui/components/overlays/vignette.js +1 -0
  55. package/dist/ui/components/poster.js +1 -0
  56. package/dist/ui/components/progress.js +1 -0
  57. package/dist/ui/components/scene-canvas.js +1 -0
  58. package/dist/ui/components/scramble.js +1 -0
  59. package/dist/ui/components/segmented.js +5 -4
  60. package/dist/ui/components/select.js +1 -0
  61. package/dist/ui/components/selection-switcher.js +1 -0
  62. package/dist/ui/components/shader.js +1 -0
  63. package/dist/ui/components/socials.js +1 -0
  64. package/dist/ui/components/spinner.js +1 -0
  65. package/dist/ui/components/stats.js +2 -1
  66. package/dist/ui/components/switch.js +1 -0
  67. package/dist/ui/components/tabs.js +4 -3
  68. package/dist/ui/components/terminal-demo.js +2 -1
  69. package/dist/ui/components/theme-toggle.js +1 -0
  70. package/dist/ui/components/tier-card.js +2 -1
  71. package/dist/ui/components/tv.js +1 -0
  72. package/dist/ui/components/typography/h1.js +1 -0
  73. package/dist/ui/components/typography/h2.js +1 -0
  74. package/dist/ui/components/typography/index.js +1 -0
  75. package/dist/ui/components/typography/legend.js +1 -0
  76. package/dist/ui/components/typography/small.js +1 -0
  77. package/dist/ui/components/watchlist.js +2 -1
  78. package/dist/ui/footer.js +1 -0
  79. package/dist/ui/globals.css +33 -1
  80. package/dist/ui/header.js +1 -0
  81. package/dist/ui/layout-wrapper.js +2 -1
  82. package/dist/utils/color.js +1 -0
  83. package/dist/utils/index.js +1 -0
  84. package/dist/utils/poly.js +1 -0
  85. package/package.json +4 -2
  86. package/src/assets/filler-bg0.webp +0 -0
  87. package/src/assets.d.ts +38 -0
  88. package/src/fonts/Collapse-Bold.woff2 +0 -0
  89. package/src/fonts/Collapse-BoldItalic.woff2 +0 -0
  90. package/src/fonts/Collapse-Italic.woff2 +0 -0
  91. package/src/fonts/Collapse-Light.woff2 +0 -0
  92. package/src/fonts/Collapse-LightItalic.woff2 +0 -0
  93. package/src/fonts/Collapse-Regular.woff2 +0 -0
  94. package/src/fonts/Collapse-Thin.woff2 +0 -0
  95. package/src/fonts/Collapse-ThinItalic.woff2 +0 -0
  96. package/src/fonts/Mondwest-Regular.woff2 +0 -0
  97. package/src/fonts/Neuebit-Bold.woff2 +0 -0
  98. package/src/fonts/RulesCompressed-Medium.woff2 +0 -0
  99. package/src/fonts/RulesCompressed-Regular.woff2 +0 -0
  100. package/src/fonts/RulesExpanded-Bold.woff2 +0 -0
  101. package/src/fonts/RulesExpanded-Regular.woff2 +0 -0
  102. package/src/fonts.ts +6 -0
  103. package/src/hooks/use-capped-frame.ts +18 -0
  104. package/src/hooks/use-css-var-dims.ts +39 -0
  105. package/src/hooks/use-gpu-tier.ts +165 -0
  106. package/src/hooks/use-render-loop.ts +121 -0
  107. package/src/hooks/use-smooth-controls.ts +318 -0
  108. package/src/index.ts +109 -0
  109. package/src/ui/basic-page.tsx +34 -0
  110. package/src/ui/build.css +4 -0
  111. package/src/ui/components/animated-count.stories.tsx +67 -0
  112. package/src/ui/components/animated-count.tsx +168 -0
  113. package/src/ui/components/ascii.stories.tsx +30 -0
  114. package/src/ui/components/ascii.tsx +110 -0
  115. package/src/ui/components/badge.stories.tsx +31 -0
  116. package/src/ui/components/badge.tsx +60 -0
  117. package/src/ui/components/badges/nous-girl.tsx +52 -0
  118. package/src/ui/components/blend-mode.stories.tsx +33 -0
  119. package/src/ui/components/blend-mode.tsx +129 -0
  120. package/src/ui/components/blink.stories.tsx +32 -0
  121. package/src/ui/components/blink.tsx +21 -0
  122. package/src/ui/components/button.stories.tsx +68 -0
  123. package/src/ui/components/button.tsx +170 -0
  124. package/src/ui/components/checkbox.stories.tsx +113 -0
  125. package/src/ui/components/checkbox.tsx +36 -0
  126. package/src/ui/components/command-block.stories.tsx +52 -0
  127. package/src/ui/components/command-block.tsx +86 -0
  128. package/src/ui/components/cursor.tsx +115 -0
  129. package/src/ui/components/dropdown-menu.stories.tsx +52 -0
  130. package/src/ui/components/dropdown-menu.tsx +117 -0
  131. package/src/ui/components/fit-text/fit-text.css +42 -0
  132. package/src/ui/components/fit-text/index.stories.tsx +33 -0
  133. package/src/ui/components/fit-text/index.tsx +45 -0
  134. package/src/ui/components/graphs/bar-chart.tsx +153 -0
  135. package/src/ui/components/graphs/index.stories.tsx +64 -0
  136. package/src/ui/components/graphs/index.tsx +4 -0
  137. package/src/ui/components/graphs/line-chart.tsx +213 -0
  138. package/src/ui/components/graphs/utils.tsx +265 -0
  139. package/src/ui/components/grid/grid.css +79 -0
  140. package/src/ui/components/grid/index.tsx +19 -0
  141. package/src/ui/components/hover-bg.stories.tsx +29 -0
  142. package/src/ui/components/hover-bg.tsx +15 -0
  143. package/src/ui/components/icons/arrow.tsx +42 -0
  144. package/src/ui/components/icons/check.tsx +14 -0
  145. package/src/ui/components/icons/chevron.tsx +45 -0
  146. package/src/ui/components/icons/discord.tsx +16 -0
  147. package/src/ui/components/icons/eye.tsx +12 -0
  148. package/src/ui/components/icons/gear.tsx +51 -0
  149. package/src/ui/components/icons/github.tsx +16 -0
  150. package/src/ui/components/icons/hamburger.tsx +52 -0
  151. package/src/ui/components/icons/heart.tsx +12 -0
  152. package/src/ui/components/icons/index.ts +12 -0
  153. package/src/ui/components/icons/link.tsx +14 -0
  154. package/src/ui/components/icons/minus.tsx +14 -0
  155. package/src/ui/components/icons/search.tsx +28 -0
  156. package/src/ui/components/image-distortion.stories.tsx +120 -0
  157. package/src/ui/components/image-distortion.tsx +498 -0
  158. package/src/ui/components/leva-client.tsx +14 -0
  159. package/src/ui/components/list-item.stories.tsx +83 -0
  160. package/src/ui/components/list-item.tsx +37 -0
  161. package/src/ui/components/modal/index.stories.tsx +46 -0
  162. package/src/ui/components/modal/index.tsx +48 -0
  163. package/src/ui/components/modal/modal.css +36 -0
  164. package/src/ui/components/overlays/blend-modes.ts +13 -0
  165. package/src/ui/components/overlays/glitch.tsx +243 -0
  166. package/src/ui/components/overlays/greys.tsx +386 -0
  167. package/src/ui/components/overlays/index.tsx +47 -0
  168. package/src/ui/components/overlays/lens-layers.tsx +119 -0
  169. package/src/ui/components/overlays/lens.ts +91 -0
  170. package/src/ui/components/overlays/noise.tsx +174 -0
  171. package/src/ui/components/overlays/vignette.tsx +60 -0
  172. package/src/ui/components/poster.stories.tsx +513 -0
  173. package/src/ui/components/poster.tsx +411 -0
  174. package/src/ui/components/progress.stories.tsx +48 -0
  175. package/src/ui/components/progress.tsx +56 -0
  176. package/src/ui/components/scene-canvas.tsx +254 -0
  177. package/src/ui/components/scramble.stories.tsx +49 -0
  178. package/src/ui/components/scramble.tsx +95 -0
  179. package/src/ui/components/segmented.stories.tsx +101 -0
  180. package/src/ui/components/segmented.tsx +81 -0
  181. package/src/ui/components/select.stories.tsx +88 -0
  182. package/src/ui/components/select.tsx +267 -0
  183. package/src/ui/components/selection-switcher.tsx +44 -0
  184. package/src/ui/components/shader.tsx +83 -0
  185. package/src/ui/components/socials.tsx +42 -0
  186. package/src/ui/components/spinner.stories.tsx +101 -0
  187. package/src/ui/components/spinner.tsx +60 -0
  188. package/src/ui/components/stats.stories.tsx +24 -0
  189. package/src/ui/components/stats.tsx +53 -0
  190. package/src/ui/components/switch.stories.tsx +77 -0
  191. package/src/ui/components/switch.tsx +48 -0
  192. package/src/ui/components/tabs.stories.tsx +101 -0
  193. package/src/ui/components/tabs.tsx +66 -0
  194. package/src/ui/components/terminal-demo.stories.tsx +67 -0
  195. package/src/ui/components/terminal-demo.tsx +189 -0
  196. package/src/ui/components/theme-toggle.stories.tsx +47 -0
  197. package/src/ui/components/theme-toggle.tsx +66 -0
  198. package/src/ui/components/tier-card.stories.tsx +217 -0
  199. package/src/ui/components/tier-card.tsx +190 -0
  200. package/src/ui/components/tv.stories.tsx +37 -0
  201. package/src/ui/components/tv.tsx +257 -0
  202. package/src/ui/components/typography/h1.tsx +18 -0
  203. package/src/ui/components/typography/h2.tsx +18 -0
  204. package/src/ui/components/typography/index.tsx +54 -0
  205. package/src/ui/components/typography/legend.tsx +24 -0
  206. package/src/ui/components/typography/small.tsx +11 -0
  207. package/src/ui/components/watchlist.stories.tsx +33 -0
  208. package/src/ui/components/watchlist.tsx +105 -0
  209. package/src/ui/fonts.css +63 -0
  210. package/src/ui/footer.tsx +111 -0
  211. package/src/ui/globals.css +383 -0
  212. package/src/ui/header.tsx +398 -0
  213. package/src/ui/layout-wrapper.tsx +11 -0
  214. package/src/utils/color.ts +21 -0
  215. package/src/utils/index.ts +62 -0
  216. package/src/utils/poly.ts +26 -0
@@ -0,0 +1,513 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite'
2
+
3
+ import fillerBg from '../../assets/filler-bg0.webp'
4
+ import { Poster } from './poster'
5
+
6
+ import type { ComponentProps } from 'react'
7
+
8
+ // Triptych-scoped story type: the gallery/triptych renders thread a
9
+ // `showLabels` toggle through the Controls panel that isn't a Poster prop.
10
+ type TriptychArgs = ComponentProps<typeof Poster> & { showLabels?: boolean }
11
+ type TriptychStory = StoryObj<TriptychArgs>
12
+
13
+ const SCOUT_SRC = fillerBg.src ?? (fillerBg as unknown as string)
14
+
15
+ // Matches the tier visuals from nous-account-service/src/app/manage-subscription/_components/TierCard.tsx
16
+ const TIERS = [
17
+ {
18
+ label: 'Scout',
19
+ src: SCOUT_SRC,
20
+ subtitle: 'warrior approaches the giant',
21
+ tint: '#88ccaa'
22
+ },
23
+ {
24
+ label: 'Visor',
25
+ src: '/img/hermes-2.png',
26
+ subtitle: 'helmeted figure, visor drawn',
27
+ tint: '#99bbdd'
28
+ },
29
+ {
30
+ label: 'Angel',
31
+ src: '/img/hermes-3.jpg',
32
+ subtitle: 'winged, in flight',
33
+ tint: '#ccaa88'
34
+ },
35
+ {
36
+ label: 'Herald',
37
+ src: '/img/hermes-4.png',
38
+ subtitle: 'plumed helm, armored',
39
+ tint: '#dd8899'
40
+ },
41
+ {
42
+ label: 'Muse',
43
+ src: '/img/hermes-1.png',
44
+ subtitle: 'portrait, pensive',
45
+ tint: '#ccaa88'
46
+ }
47
+ ] as const
48
+
49
+ const HIGHEST_TINT = '#ff4444'
50
+ const HIGHEST_TINT_STRENGTH = { active: 0.55, inactive: 0.35 }
51
+
52
+ const meta: Meta<typeof Poster> = {
53
+ argTypes: {
54
+ aspect: {
55
+ control: 'select',
56
+ options: ['square', 'portrait', 'landscape', 'story', 'wide']
57
+ },
58
+ autoPlay: {
59
+ control: 'select',
60
+ options: ['slash', 'gentle', 'aggressive']
61
+ },
62
+ // `React.ReactNode` props default to Storybook's "object" control, which
63
+ // shows as "Set object" and can't be edited in-place. Force them to
64
+ // plain text / object inputs since that's how they're used in practice.
65
+ body: {
66
+ control: 'text',
67
+ table: { category: 'Dispatch variant' }
68
+ },
69
+ border: { control: 'boolean' },
70
+ channel: { control: 'text' },
71
+ // `children` and `className` are dev-only escape hatches (arbitrary JSX
72
+ // / Tailwind passthrough). Neither is useful for the "record a GIF for
73
+ // socials" workflow, so hide them from the panel to keep it tidy.
74
+ children: { table: { disable: true } },
75
+ className: { table: { disable: true } },
76
+ cornerMarks: { control: 'boolean' },
77
+ eyebrow: {
78
+ control: 'text',
79
+ table: { category: 'Dispatch variant' }
80
+ },
81
+ headline: {
82
+ control: 'object',
83
+ table: { category: 'Dispatch variant' }
84
+ },
85
+ layout: {
86
+ control: 'inline-radio',
87
+ options: ['split', 'stacked'],
88
+ table: { category: 'Dispatch variant' }
89
+ },
90
+ scale: { control: { max: 1, min: 0.25, step: 0.05, type: 'range' } },
91
+ seal: {
92
+ control: 'text',
93
+ table: { category: 'Dispatch variant' }
94
+ },
95
+ signature: { control: 'text' },
96
+ src: { control: 'text' },
97
+ tags: {
98
+ control: 'object',
99
+ table: { category: 'Dispatch variant' }
100
+ },
101
+ tint: { control: 'color' },
102
+ tintStrength: { control: 'object' },
103
+ variant: {
104
+ control: 'inline-radio',
105
+ options: ['vibe', 'dispatch']
106
+ }
107
+ },
108
+ component: Poster,
109
+ parameters: {
110
+ docs: {
111
+ description: {
112
+ component:
113
+ 'A social-ready glitchy card built around the haptic-distortion image component. Defaults to the `vibe` variant — full-bleed distortion with minimal registration chrome — matching the overlay on the Hermes agent website. Switch to `variant="dispatch"` for the broadcast-card layout with copy + sidebar tags.\n\nPoster stories include all five tier images from the `manage-subscription` page so you can screen-record any character on-demand.'
114
+ }
115
+ },
116
+ layout: 'centered'
117
+ },
118
+ title: 'Components/Poster'
119
+ }
120
+
121
+ export default meta
122
+
123
+ type Story = StoryObj<typeof Poster>
124
+
125
+ /**
126
+ * Primary story. Full-bleed "Scout" scene (warrior approaching the giant),
127
+ * minimal chrome, just the subtle `Hermes Agent` overlay at the bottom-right.
128
+ * Screen-record one ~7s pass (two 3.6s slash cycles) → export as GIF →
129
+ * attach to the pricing tweet.
130
+ *
131
+ * Rendered at full target resolution (1080×1080). The storybook viewport
132
+ * naturally clamps it via `max-width: 100%` if your window is narrower.
133
+ */
134
+ export const Vibe: Story = {
135
+ args: {
136
+ aspect: 'square',
137
+ autoPlay: 'slash',
138
+ scale: 1,
139
+ signature: 'Hermes Agent',
140
+ variant: 'vibe'
141
+ }
142
+ }
143
+
144
+ /** 9:16 for Instagram / TikTok stories and reels. */
145
+ export const VibeStory: Story = {
146
+ args: {
147
+ aspect: 'story',
148
+ autoPlay: 'slash',
149
+ scale: 1,
150
+ signature: 'Hermes Agent',
151
+ variant: 'vibe'
152
+ },
153
+ name: 'Vibe · Story (9:16)'
154
+ }
155
+
156
+ /** 16:9 for Twitter cards, LinkedIn, Discord embeds. */
157
+ export const VibeLandscape: Story = {
158
+ args: {
159
+ aspect: 'landscape',
160
+ autoPlay: 'slash',
161
+ scale: 1,
162
+ signature: 'Hermes Agent',
163
+ variant: 'vibe'
164
+ },
165
+ name: 'Vibe · Landscape (16:9)'
166
+ }
167
+
168
+ /** 4:5 — the Instagram feed recommendation. */
169
+ export const VibePortrait: Story = {
170
+ args: {
171
+ aspect: 'portrait',
172
+ autoPlay: 'slash',
173
+ scale: 1,
174
+ signature: 'Hermes Agent',
175
+ variant: 'vibe'
176
+ },
177
+ name: 'Vibe · Portrait (4:5)'
178
+ }
179
+
180
+ // ─── Tier images, each on its canonical tint ───
181
+
182
+ /**
183
+ * All five `manage-subscription` tier images in one view, each with the
184
+ * tint from `TierCard.tsx`. Pick whichever one matches the vibe for the
185
+ * release and screen-record it on its own.
186
+ */
187
+ export const TierGallery: TriptychStory = {
188
+ args: {
189
+ aspect: 'square',
190
+ autoPlay: 'slash',
191
+ border: true,
192
+ cornerMarks: true,
193
+ scale: 0.3,
194
+ showLabels: true,
195
+ variant: 'vibe'
196
+ },
197
+ argTypes: { showLabels: { control: 'boolean' } },
198
+ name: 'Tier Gallery',
199
+ parameters: { layout: 'fullscreen' },
200
+ render: ({ showLabels, ...args }) => (
201
+ <div className="bg-background flex min-h-screen items-center justify-center p-8">
202
+ <div className="grid grid-cols-3 items-start gap-4 xl:grid-cols-5">
203
+ {TIERS.map(tier => (
204
+ <div className="flex flex-col gap-2" key={tier.label}>
205
+ {showLabels && (
206
+ <div className="flex items-baseline justify-between gap-2 px-1">
207
+ <span className="font-mondwest text-[0.75rem] tracking-[0.1875rem] uppercase opacity-80">
208
+ {tier.label}
209
+ </span>
210
+
211
+ <span className="font-courier text-[0.625rem] tracking-widest opacity-40">
212
+ {tier.tint}
213
+ </span>
214
+ </div>
215
+ )}
216
+
217
+ <Poster
218
+ {...args}
219
+ signature={showLabels ? tier.label : undefined}
220
+ src={tier.src}
221
+ tint={tier.tint}
222
+ />
223
+
224
+ {showLabels && (
225
+ <span className="font-courier px-1 text-[0.625rem] tracking-wider opacity-50">
226
+ {tier.subtitle}
227
+ </span>
228
+ )}
229
+ </div>
230
+ ))}
231
+ </div>
232
+ </div>
233
+ )
234
+ }
235
+
236
+ export const TierScout: Story = {
237
+ args: {
238
+ aspect: 'square',
239
+ autoPlay: 'slash',
240
+ scale: 1,
241
+ signature: 'Hermes Agent',
242
+ src: SCOUT_SRC,
243
+ tint: TIERS[0].tint,
244
+ variant: 'vibe'
245
+ },
246
+ name: 'Tier · Scout'
247
+ }
248
+
249
+ export const TierVisor: Story = {
250
+ args: {
251
+ aspect: 'square',
252
+ autoPlay: 'slash',
253
+ scale: 1,
254
+ signature: 'Hermes Agent',
255
+ src: TIERS[1].src,
256
+ tint: TIERS[1].tint,
257
+ variant: 'vibe'
258
+ },
259
+ name: 'Tier · Visor'
260
+ }
261
+
262
+ export const TierAngel: Story = {
263
+ args: {
264
+ aspect: 'square',
265
+ autoPlay: 'gentle',
266
+ scale: 1,
267
+ signature: 'Hermes Agent',
268
+ src: TIERS[2].src,
269
+ tint: TIERS[2].tint,
270
+ variant: 'vibe'
271
+ },
272
+ name: 'Tier · Angel'
273
+ }
274
+
275
+ export const TierHerald: Story = {
276
+ args: {
277
+ aspect: 'square',
278
+ autoPlay: 'slash',
279
+ scale: 1,
280
+ signature: 'Hermes Agent',
281
+ src: TIERS[3].src,
282
+ tint: TIERS[3].tint,
283
+ variant: 'vibe'
284
+ },
285
+ name: 'Tier · Herald'
286
+ }
287
+
288
+ export const TierMuse: Story = {
289
+ args: {
290
+ aspect: 'square',
291
+ autoPlay: 'gentle',
292
+ scale: 1,
293
+ signature: 'Hermes Agent',
294
+ src: TIERS[4].src,
295
+ tint: TIERS[4].tint,
296
+ variant: 'vibe'
297
+ },
298
+ name: 'Tier · Muse'
299
+ }
300
+
301
+ /**
302
+ * Top-tier red-overlay treatment from `TierCard` — use this for the
303
+ * "Sovereign" / highest tier poster.
304
+ */
305
+ export const TierApex: Story = {
306
+ args: {
307
+ aspect: 'square',
308
+ autoPlay: 'aggressive',
309
+ scale: 1,
310
+ signature: 'Hermes · Apex',
311
+ src: TIERS[3].src,
312
+ tint: HIGHEST_TINT,
313
+ tintStrength: HIGHEST_TINT_STRENGTH,
314
+ variant: 'vibe'
315
+ },
316
+ name: 'Tier · Apex (highest)'
317
+ }
318
+
319
+ /** Three vibe tiles side-by-side — same scene, three tier tints. */
320
+ export const VibeTriptychScout: TriptychStory = {
321
+ args: {
322
+ aspect: 'square',
323
+ autoPlay: 'slash',
324
+ border: true,
325
+ cornerMarks: true,
326
+ scale: 0.35,
327
+ showLabels: true,
328
+ variant: 'vibe'
329
+ },
330
+ argTypes: { showLabels: { control: 'boolean' } },
331
+ name: 'Vibe · Triptych (Scout, 3 tints)',
332
+ parameters: { layout: 'fullscreen' },
333
+ // `args` here drives the shared props across all three tiles; per-tile
334
+ // specifics (signature, tint) stay hardcoded inside the render so the
335
+ // triptych keeps its identity while you tweak chrome/scale/etc. from the
336
+ // Controls panel. `showLabels` hides the per-tile signature text.
337
+ render: ({ showLabels, ...args }) => (
338
+ <div className="bg-background flex min-h-screen items-center justify-center p-8">
339
+ <div className="flex items-stretch gap-4">
340
+ <Poster
341
+ {...args}
342
+ signature={showLabels ? 'Studio' : undefined}
343
+ tint="#88ccaa"
344
+ />
345
+
346
+ <Poster
347
+ {...args}
348
+ signature={showLabels ? 'Pro' : undefined}
349
+ tint="#ccaa88"
350
+ />
351
+
352
+ <Poster
353
+ {...args}
354
+ signature={showLabels ? 'Sovereign' : undefined}
355
+ tint={HIGHEST_TINT}
356
+ tintStrength={HIGHEST_TINT_STRENGTH}
357
+ />
358
+ </div>
359
+ </div>
360
+ )
361
+ }
362
+
363
+ /** Three vibe tiles, three tier images — mixed character set. */
364
+ export const VibeTriptychMixed: TriptychStory = {
365
+ args: {
366
+ aspect: 'square',
367
+ autoPlay: 'slash',
368
+ border: true,
369
+ cornerMarks: true,
370
+ scale: 0.35,
371
+ showLabels: true,
372
+ variant: 'vibe'
373
+ },
374
+ argTypes: { showLabels: { control: 'boolean' } },
375
+ name: 'Vibe · Triptych (mixed characters)',
376
+ parameters: { layout: 'fullscreen' },
377
+ render: ({ showLabels, ...args }) => (
378
+ <div className="bg-background flex min-h-screen items-center justify-center p-8">
379
+ <div className="flex items-stretch gap-4">
380
+ <Poster
381
+ {...args}
382
+ signature={showLabels ? TIERS[0].label : undefined}
383
+ src={TIERS[0].src}
384
+ tint={TIERS[0].tint}
385
+ />
386
+
387
+ <Poster
388
+ {...args}
389
+ signature={showLabels ? TIERS[2].label : undefined}
390
+ src={TIERS[2].src}
391
+ tint={TIERS[2].tint}
392
+ />
393
+
394
+ <Poster
395
+ {...args}
396
+ signature={showLabels ? TIERS[3].label : undefined}
397
+ src={TIERS[3].src}
398
+ tint={HIGHEST_TINT}
399
+ tintStrength={HIGHEST_TINT_STRENGTH}
400
+ />
401
+ </div>
402
+ </div>
403
+ )
404
+ }
405
+
406
+ /** "Gentle" choreography — softer, slower drift. */
407
+ export const VibeGentle: Story = {
408
+ args: {
409
+ aspect: 'square',
410
+ autoPlay: 'gentle',
411
+ scale: 1,
412
+ signature: 'Hermes Agent',
413
+ tint: '#88ccaa',
414
+ variant: 'vibe'
415
+ }
416
+ }
417
+
418
+ /** "Aggressive" choreography — rapid multi-directional stabs. */
419
+ export const VibeAggressive: Story = {
420
+ args: {
421
+ aspect: 'square',
422
+ autoPlay: 'aggressive',
423
+ scale: 1,
424
+ signature: 'Hermes Agent',
425
+ tint: HIGHEST_TINT,
426
+ variant: 'vibe'
427
+ }
428
+ }
429
+
430
+ // ─── Dispatch variants (in the backpocket if copy ends up on the poster) ───
431
+
432
+ /** Full broadcast-card layout with copy, sidebar tags, and chrome. */
433
+ export const DispatchPricingTeaser: Story = {
434
+ args: {
435
+ aspect: 'square',
436
+ body: 'New tiers. Same autonomous agent, scaled to how you actually run it — solo on a laptop, shared across a team, or sovereign on your own hardware.',
437
+ channel: 'NOUS • HERMES AGENT',
438
+ eyebrow: 'PRICING / 2026',
439
+ headline: ['Pricing', 'That Grows', 'With You.'],
440
+ scale: 1,
441
+ seal: 'v0.9 · 2026',
442
+ signature: 'nousresearch.com/hermes-agent',
443
+ tags: ['Studio · free', 'Pro · $20/mo', 'Sovereign · on-prem'],
444
+ tint: '#ccaa88',
445
+ variant: 'dispatch'
446
+ },
447
+ name: 'Dispatch · Pricing Teaser'
448
+ }
449
+
450
+ /** Three dispatch posters side-by-side for the full tier rollout. */
451
+ export const DispatchTriptych: TriptychStory = {
452
+ args: {
453
+ aspect: 'square',
454
+ border: true,
455
+ cornerMarks: true,
456
+ scale: 0.35,
457
+ showLabels: true,
458
+ variant: 'dispatch'
459
+ },
460
+ argTypes: { showLabels: { control: 'boolean' } },
461
+ name: 'Dispatch · Triptych',
462
+ parameters: { layout: 'fullscreen' },
463
+ render: ({ showLabels, ...args }) => (
464
+ <div className="bg-background flex min-h-screen items-center justify-center p-8">
465
+ <div className="flex items-stretch gap-4">
466
+ <Poster
467
+ {...args}
468
+ channel={showLabels ? 'NOUS • STUDIO' : undefined}
469
+ eyebrow={showLabels ? 'TIER / 001' : undefined}
470
+ headline={showLabels ? ['Hermes', 'Studio.'] : ['']}
471
+ seal={showLabels ? 'FREE · MIT' : undefined}
472
+ signature={showLabels ? 'hermes.run / studio' : undefined}
473
+ src={TIERS[0].src}
474
+ tags={showLabels ? ['Local-first', 'Unlimited tools', 'MIT'] : []}
475
+ tint={TIERS[0].tint}
476
+ />
477
+
478
+ <Poster
479
+ {...args}
480
+ channel={showLabels ? 'NOUS • PRO' : undefined}
481
+ eyebrow={showLabels ? 'TIER / 002' : undefined}
482
+ headline={showLabels ? ['Hermes', 'Pro.'] : ['']}
483
+ seal={showLabels ? '$20/mo' : undefined}
484
+ signature={showLabels ? 'hermes.run / pro' : undefined}
485
+ src={TIERS[2].src}
486
+ tags={
487
+ showLabels
488
+ ? ['Hosted memory', 'Priority inference', 'Team workspaces']
489
+ : []
490
+ }
491
+ tint={TIERS[2].tint}
492
+ />
493
+
494
+ <Poster
495
+ {...args}
496
+ channel={showLabels ? 'NOUS • SOVEREIGN' : undefined}
497
+ eyebrow={showLabels ? 'TIER / 003' : undefined}
498
+ headline={showLabels ? ['Hermes', 'Sovereign.'] : ['']}
499
+ seal={showLabels ? 'talk to us' : undefined}
500
+ signature={showLabels ? 'hermes.run / sovereign' : undefined}
501
+ src={TIERS[3].src}
502
+ tags={
503
+ showLabels
504
+ ? ['Self-hosted', 'Dedicated inference', 'SSO + audit']
505
+ : []
506
+ }
507
+ tint={HIGHEST_TINT}
508
+ tintStrength={HIGHEST_TINT_STRENGTH}
509
+ />
510
+ </div>
511
+ </div>
512
+ )
513
+ }