@utopia-studio-design/design-system-cli 0.1.0 → 0.3.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 (52) hide show
  1. package/README.md +12 -41
  2. package/bin/utopia-ds-mcp.mjs +55 -0
  3. package/bin/utopia-ds.mjs +233 -318
  4. package/data/docs/ai-platform-plan.md +53 -0
  5. package/data/docs/arabic-friendly.md +72 -0
  6. package/data/docs/foundations.md +154 -0
  7. package/data/docs/guide.md +37 -0
  8. package/data/docs/quick-start-ai.md +122 -0
  9. package/data/docs/shadcn-conversion.md +35 -0
  10. package/data/docs/theme-authoring.md +46 -0
  11. package/data/manifests/catalog.json +547 -0
  12. package/data/manifests/components.json +4780 -0
  13. package/data/manifests/patterns.json +12 -0
  14. package/data/manifests/templates.json +96 -0
  15. package/data/manifests/theme-barrier-intelligence.json +123 -0
  16. package/data/manifests/theme-dextrum.json +255 -0
  17. package/data/manifests/theme-utopia-default.json +163 -0
  18. package/data/manifests/themes.json +417 -0
  19. package/data/templates/saas-solution-homepage/README.md +52 -0
  20. package/data/templates/saas-solution-homepage/agents/index.html +1 -0
  21. package/data/templates/saas-solution-homepage/changelog/index.html +1 -0
  22. package/data/templates/saas-solution-homepage/contact-sales/index.html +1 -0
  23. package/data/templates/saas-solution-homepage/customers/aster-labs/index.html +1 -0
  24. package/data/templates/saas-solution-homepage/customers/index.html +1 -0
  25. package/data/templates/saas-solution-homepage/index.html +17 -0
  26. package/data/templates/saas-solution-homepage/integrations/index.html +1 -0
  27. package/data/templates/saas-solution-homepage/integrations/slack/index.html +1 -0
  28. package/data/templates/saas-solution-homepage/main.tsx +642 -0
  29. package/data/templates/saas-solution-homepage/pricing/index.html +1 -0
  30. package/data/templates/saas-solution-homepage/product/index.html +1 -0
  31. package/data/templates/saas-solution-homepage/styles.css +863 -0
  32. package/data/templates/saas-solution-homepage/template.manifest.json +36 -0
  33. package/lib/api.mjs +152 -0
  34. package/package.json +17 -15
  35. package/LICENSE +0 -21
  36. package/templates/agent-docs/examples.md +0 -33
  37. package/templates/agent-docs/index.md +0 -78
  38. package/templates/agent-docs/llms.txt +0 -33
  39. package/templates/components/badge.tsx +0 -12
  40. package/templates/components/brand-action.tsx +0 -32
  41. package/templates/components/button-group.tsx +0 -30
  42. package/templates/components/button.tsx +0 -44
  43. package/templates/components/card.tsx +0 -23
  44. package/templates/components/cta-section.tsx +0 -34
  45. package/templates/components/icon-button.tsx +0 -44
  46. package/templates/components/page-hero.tsx +0 -47
  47. package/templates/components/tooltip.tsx +0 -48
  48. package/templates/components/topbar.tsx +0 -59
  49. package/templates/lib/utils.ts +0 -6
  50. package/templates/styles/styles.css +0 -271
  51. package/templates/styles/tokens.css +0 -21
  52. package/templates/tokens.json +0 -41
@@ -0,0 +1,642 @@
1
+ import { StrictMode, useEffect, useMemo, useState, type CSSProperties, type ReactNode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import { AnimatePresence, motion } from 'framer-motion'
4
+ import {
5
+ ArrowUpRight,
6
+ Bot,
7
+ Check,
8
+ ChevronRight,
9
+ CircleCheck,
10
+ Clock3,
11
+ Cloud,
12
+ Code2,
13
+ Database,
14
+ GitBranch,
15
+ Globe2,
16
+ Languages,
17
+ Menu,
18
+ Moon,
19
+ Network,
20
+ Play,
21
+ Search,
22
+ ShieldCheck,
23
+ Sparkles,
24
+ Sun,
25
+ Workflow,
26
+ X,
27
+ Zap,
28
+ } from 'lucide-react'
29
+ import {
30
+ Badge,
31
+ Button,
32
+ Card,
33
+ CardContent,
34
+ CardDescription,
35
+ CardHeader,
36
+ CardTitle,
37
+ MotionProvider,
38
+ Selector,
39
+ Textarea,
40
+ TextInput,
41
+ TopNav,
42
+ TopNavItem,
43
+ useMotionPattern,
44
+ } from '@utopia-studio-design/design-system'
45
+ import '@utopia-studio-design/design-system/core.css'
46
+ import '@utopia-studio-design/design-system/themes/utopia-default.css'
47
+ import './styles.css'
48
+
49
+ const activeTheme = 'utopia-default'
50
+
51
+ type Locale = 'en' | 'ar'
52
+ type PreviewMode = 'overview' | 'automations' | 'insights'
53
+ type PageKey = 'home' | 'product' | 'agents' | 'integrations' | 'integration-detail' | 'customers' | 'customer-story' | 'pricing' | 'changelog' | 'contact-sales'
54
+
55
+ type DemoData = {
56
+ product: string
57
+ company: string
58
+ leaders: string[]
59
+ price: number
60
+ metric: number
61
+ }
62
+
63
+ const templatePath = '/templates/saas-solution-homepage'
64
+ const templateBase = window.location.pathname.includes(templatePath) ? templatePath : ''
65
+
66
+ function getPageKey(): PageKey {
67
+ const route = (templateBase
68
+ ? window.location.pathname.split('/saas-solution-homepage/')[1]
69
+ : window.location.pathname.replace(/^\//, ''))?.replace(/index\.html$/, '').replace(/\/$/, '') ?? ''
70
+ if (route === 'product') return 'product'
71
+ if (route === 'agents') return 'agents'
72
+ if (route === 'integrations') return 'integrations'
73
+ if (route === 'integrations/slack') return 'integration-detail'
74
+ if (route === 'customers') return 'customers'
75
+ if (route === 'customers/aster-labs') return 'customer-story'
76
+ if (route === 'pricing') return 'pricing'
77
+ if (route === 'changelog') return 'changelog'
78
+ if (route === 'contact-sales') return 'contact-sales'
79
+ return 'home'
80
+ }
81
+
82
+ function pageHref(page: string, seed: number) {
83
+ const suffix = page ? `/${page}/` : '/index.html'
84
+ return `${templateBase}${suffix}?seed=${seed}`
85
+ }
86
+
87
+ const copy = {
88
+ en: {
89
+ nav: ['Product', 'Workflow', 'Agents', 'Integrations', 'Security', 'Pricing'],
90
+ announcement: 'New · Agent controls are now generally available',
91
+ heroEyebrow: 'Operations, connected',
92
+ heroTitle: 'Move work from signal to resolution.',
93
+ heroBody: 'One operational layer for intake, coordination, automation, and clear decisions — built for teams working across regions and systems.',
94
+ start: 'Start building',
95
+ tour: 'See the product',
96
+ trusted: 'Trusted by teams building across Doha, London, New York, and Dubai',
97
+ productEyebrow: 'Product interface',
98
+ productTitle: 'A shared system for the work between tools.',
99
+ productBody: 'Bring requests, owners, decisions, and automations into one legible workspace. Every view stays connected to the same operating model.',
100
+ previewTabs: ['Overview', 'Automations', 'Insights'],
101
+ workflowEyebrow: 'Core workflow',
102
+ workflowTitle: 'One continuous path, from intake to impact.',
103
+ workflowBody: 'Keep context attached while work changes shape. Teams can move quickly without losing ownership, approval, or history.',
104
+ agentsEyebrow: 'Agents & automation',
105
+ agentsTitle: 'Delegate repeatable work. Keep judgment with your team.',
106
+ agentsBody: 'Agents observe approved signals, prepare the next action, and pause at the boundaries you define.',
107
+ integrationsEyebrow: 'Integrations',
108
+ integrationsTitle: 'Connect the systems your team already trusts.',
109
+ integrationsBody: 'A composable integration layer keeps data moving without turning every workflow into a maintenance project.',
110
+ securityEyebrow: 'Security & reliability',
111
+ securityTitle: 'Controls that scale with the work.',
112
+ securityBody: 'Granular access, full auditability, and region-aware operations are built into the same system your team uses every day.',
113
+ proofEyebrow: 'Team proof',
114
+ proofQuote: 'We replaced three weekly coordination meetings with one shared operating view. The biggest change was not speed — it was confidence in who owned the next move.',
115
+ proofRole: 'VP Operations',
116
+ pricingEyebrow: 'Adoption',
117
+ pricingTitle: 'Start with one workflow. Expand when the proof is visible.',
118
+ pricingBody: 'Launch a focused workspace today, then add teams, automations, and controls without rebuilding the foundation.',
119
+ plan: 'Workspace plan',
120
+ perMonth: '/ month',
121
+ planNote: 'Includes unlimited viewers and a guided setup session.',
122
+ cta: 'Create your workspace',
123
+ contact: 'Talk to a specialist',
124
+ footer: 'A deterministic Ceramic template for modern SaaS products.',
125
+ menu: 'Open navigation',
126
+ closeMenu: 'Close navigation',
127
+ theme: 'Switch color mode',
128
+ language: 'العربية',
129
+ live: 'Live operations',
130
+ health: 'All systems healthy',
131
+ activity: 'Activity',
132
+ owner: 'Owner',
133
+ status: 'Status',
134
+ },
135
+ ar: {
136
+ nav: ['المنتج', 'سير العمل', 'الوكلاء', 'التكاملات', 'الأمان', 'الأسعار'],
137
+ announcement: 'جديد · أدوات التحكم في الوكلاء متاحة الآن',
138
+ heroEyebrow: 'عمليات مترابطة',
139
+ heroTitle: 'انقل العمل من الإشارة إلى الحل.',
140
+ heroBody: 'طبقة تشغيل واحدة للاستقبال والتنسيق والأتمتة واتخاذ قرارات واضحة — لفرق تعمل عبر مناطق وأنظمة متعددة.',
141
+ start: 'ابدأ البناء',
142
+ tour: 'شاهد المنتج',
143
+ trusted: 'موثوق لدى فرق تعمل في الدوحة ولندن ونيويورك ودبي',
144
+ productEyebrow: 'واجهة المنتج',
145
+ productTitle: 'نظام مشترك للعمل الذي يجري بين الأدوات.',
146
+ productBody: 'اجمع الطلبات والمسؤولين والقرارات والأتمتة في مساحة عمل واحدة واضحة. تبقى كل الواجهات متصلة بنموذج التشغيل نفسه.',
147
+ previewTabs: ['نظرة عامة', 'الأتمتة', 'المؤشرات'],
148
+ workflowEyebrow: 'سير العمل الأساسي',
149
+ workflowTitle: 'مسار متصل من الاستقبال إلى الأثر.',
150
+ workflowBody: 'يبقى السياق ملازماً للعمل أثناء تطوره، فتتحرك الفرق بسرعة من دون فقدان المسؤولية أو الاعتماد أو السجل.',
151
+ agentsEyebrow: 'الوكلاء والأتمتة',
152
+ agentsTitle: 'فوّض العمل المتكرر، واحتفظ بالحكم لفريقك.',
153
+ agentsBody: 'تراقب الوكلاء الإشارات المعتمدة، وتجهز الإجراء التالي، وتتوقف عند الحدود التي يحددها فريقك.',
154
+ integrationsEyebrow: 'التكاملات',
155
+ integrationsTitle: 'اربط الأنظمة التي يثق بها فريقك.',
156
+ integrationsBody: 'تحافظ طبقة تكامل مرنة على حركة البيانات من دون تحويل كل سير عمل إلى مشروع صيانة.',
157
+ securityEyebrow: 'الأمان والموثوقية',
158
+ securityTitle: 'ضوابط تتوسع مع العمل.',
159
+ securityBody: 'صلاحيات دقيقة وسجل تدقيق كامل وعمليات تراعي المنطقة، كلها مدمجة في النظام اليومي نفسه.',
160
+ proofEyebrow: 'دليل من الفريق',
161
+ proofQuote: 'استبدلنا ثلاثة اجتماعات تنسيق أسبوعية بمشهد تشغيلي مشترك واحد. لم يكن التغيير الأكبر في السرعة، بل في الثقة بمن يملك الخطوة التالية.',
162
+ proofRole: 'نائب الرئيس للعمليات',
163
+ pricingEyebrow: 'الاعتماد',
164
+ pricingTitle: 'ابدأ بسير عمل واحد، ثم توسع عندما يظهر الدليل.',
165
+ pricingBody: 'أطلق مساحة عمل مركزة اليوم، ثم أضف الفرق والأتمتة والضوابط من دون إعادة بناء الأساس.',
166
+ plan: 'خطة مساحة العمل',
167
+ perMonth: '/ شهرياً',
168
+ planNote: 'تشمل مشاهدين بلا حد وجلسة إعداد موجهة.',
169
+ cta: 'أنشئ مساحة العمل',
170
+ contact: 'تحدث مع مختص',
171
+ footer: 'قالب Ceramic حتمي لمنتجات SaaS الحديثة.',
172
+ menu: 'فتح التنقل',
173
+ closeMenu: 'إغلاق التنقل',
174
+ theme: 'تبديل نمط الألوان',
175
+ language: 'English',
176
+ live: 'العمليات المباشرة',
177
+ health: 'جميع الأنظمة تعمل',
178
+ activity: 'النشاط',
179
+ owner: 'المسؤول',
180
+ status: 'الحالة',
181
+ },
182
+ } as const
183
+
184
+ const demoSets = {
185
+ product: ['Namaa', 'Relay', 'Atlas', 'Madar', 'Orbit'],
186
+ company: ['Aster Labs', 'Sahm Cloud', 'Northstar Health', 'Majlis Works', 'Cedar Systems'],
187
+ leaders: [
188
+ ['Lina Al-Khatib', 'Omar Rahman', 'Maya Chen'],
189
+ ['Noor Al-Sayed', 'James Walker', 'Hana Kim'],
190
+ ['Leila Mansour', 'Ethan Brooks', 'Yousef Khalil'],
191
+ ['Dana Haddad', 'Alex Morgan', 'Sara Al-Nuaimi'],
192
+ ['Rania Farouk', 'Sam Taylor', 'Minji Park'],
193
+ ],
194
+ price: [39, 49, 59, 69, 79],
195
+ metric: [24, 31, 38, 42, 47],
196
+ }
197
+
198
+ function seededIndex(seed: number, salt: number, length: number) {
199
+ let value = (seed ^ (salt * 0x9e3779b9)) >>> 0
200
+ value ^= value << 13
201
+ value ^= value >>> 17
202
+ value ^= value << 5
203
+ return (value >>> 0) % length
204
+ }
205
+
206
+ function ArrowIcon() {
207
+ return <ArrowUpRight aria-hidden="true" className="directional-icon" />
208
+ }
209
+
210
+ function RevealBlock({ children, className, delay = 0 }: { children: ReactNode; className?: string; delay?: number }) {
211
+ const reveal = useMotionPattern('reveal')
212
+ return (
213
+ <motion.div
214
+ className={className}
215
+ initial={reveal.enabled ? { opacity: 0, y: 16 } : false}
216
+ transition={{ ...reveal.transition, delay: reveal.enabled ? delay : 0 }}
217
+ viewport={{ amount: 0.22, once: true }}
218
+ whileInView={{ opacity: 1, y: 0 }}
219
+ >
220
+ {children}
221
+ </motion.div>
222
+ )
223
+ }
224
+
225
+ function SectionHeading({ body, eyebrow, title }: { body: string; eyebrow: string; title: string }) {
226
+ const reveal = useMotionPattern('reveal')
227
+ return (
228
+ <motion.div
229
+ className="section-heading"
230
+ initial={reveal.enabled ? { opacity: 0, y: 18 } : false}
231
+ transition={reveal.transition}
232
+ viewport={{ amount: 0.35, once: true }}
233
+ whileInView={{ opacity: 1, y: 0 }}
234
+ >
235
+ <p className="eyebrow">{eyebrow}</p>
236
+ <h2>{title}</h2>
237
+ <p>{body}</p>
238
+ </motion.div>
239
+ )
240
+ }
241
+
242
+ function ProductPreview({ locale, mode, product, setMode }: { locale: Locale; mode: PreviewMode; product: string; setMode: (mode: PreviewMode) => void }) {
243
+ const t = copy[locale]
244
+ const reveal = useMotionPattern('reveal')
245
+ const pageMotion = useMotionPattern('page')
246
+ const tabs: PreviewMode[] = ['overview', 'automations', 'insights']
247
+ const rows = locale === 'ar'
248
+ ? [['مراجعة إطلاق المنطقة', 'Noor Al-Sayed', 'قيد التنفيذ'], ['توجيه طلب الشراكة', 'Maya Chen', 'مؤتمت'], ['اعتماد موجز العميل', 'James Walker', 'بانتظار المراجعة']]
249
+ : [['Review regional launch', 'Noor Al-Sayed', 'In progress'], ['Route partnership request', 'Maya Chen', 'Automated'], ['Approve customer brief', 'James Walker', 'Awaiting review']]
250
+
251
+ return (
252
+ <motion.div
253
+ className="product-window"
254
+ data-preview={mode}
255
+ initial={reveal.enabled ? { opacity: 0, y: 20 } : false}
256
+ transition={reveal.transition}
257
+ viewport={{ amount: 0.18, once: true }}
258
+ whileInView={{ opacity: 1, y: 0 }}
259
+ >
260
+ <div className="window-bar">
261
+ <span className="window-brand"><span className="brand-mark" />{product}</span>
262
+ <div className="window-search"><Search aria-hidden="true" /><span>{locale === 'ar' ? 'ابحث في مساحة العمل' : 'Search workspace'}</span><kbd>⌘ K</kbd></div>
263
+ <span className="presence"><span /> {locale === 'ar' ? '8 متصلون' : '8 online'}</span>
264
+ </div>
265
+ <div className="window-layout">
266
+ <aside className="preview-sidebar" aria-label={locale === 'ar' ? 'تنقل المنتج' : 'Product navigation'}>
267
+ <strong>{t.live}</strong>
268
+ {tabs.map((tab, index) => {
269
+ const PreviewIcon = [Workflow, Bot, Sparkles][index]
270
+ return (
271
+ <button aria-pressed={mode === tab} key={tab} onClick={() => setMode(tab)} type="button">
272
+ <PreviewIcon aria-hidden="true" />
273
+ <span>{t.previewTabs[index]}</span>
274
+ </button>
275
+ )})}
276
+ <div className="preview-sidebar__footer"><CircleCheck aria-hidden="true" />{t.health}</div>
277
+ </aside>
278
+ <AnimatePresence initial={false} mode="wait">
279
+ <motion.div
280
+ animate={{ opacity: 1, y: 0 }}
281
+ className="preview-main"
282
+ exit={pageMotion.enabled ? { opacity: 0, y: -6 } : undefined}
283
+ initial={pageMotion.enabled ? { opacity: 0, y: 8 } : false}
284
+ key={`${locale}-${mode}`}
285
+ transition={pageMotion.transition}
286
+ >
287
+ <div className="preview-toolbar">
288
+ <div><p>{t.live}</p><h3>{mode === 'overview' ? t.previewTabs[0] : mode === 'automations' ? t.previewTabs[1] : t.previewTabs[2]}</h3></div>
289
+ <Badge variant="outline">{locale === 'ar' ? 'آخر 30 يوماً' : 'Last 30 days'}</Badge>
290
+ </div>
291
+ <div className="metric-grid">
292
+ <div><span>{locale === 'ar' ? 'وقت الاستجابة' : 'Response time'}</span><strong>2.4h</strong><small>↓ 18%</small></div>
293
+ <div><span>{locale === 'ar' ? 'عمل مؤتمت' : 'Work automated'}</span><strong>38%</strong><small>↑ 12%</small></div>
294
+ <div><span>{locale === 'ar' ? 'معدل الإنجاز' : 'Resolution rate'}</span><strong>94%</strong><small>↑ 7%</small></div>
295
+ </div>
296
+ <div className="activity-panel">
297
+ <div className="activity-head"><strong>{t.activity}</strong><span>{locale === 'ar' ? 'تحديث مباشر' : 'Live update'}</span></div>
298
+ <div className="activity-labels"><span>{locale === 'ar' ? 'العمل' : 'Work item'}</span><span>{t.owner}</span><span>{t.status}</span></div>
299
+ {rows.map(([item, owner, status], index) => (
300
+ <div className="activity-row" key={item} style={{ '--row-delay': `${index * 80}ms` } as CSSProperties}>
301
+ <span><i>{index + 1}</i>{item}</span><span>{owner}</span><span><b />{status}</span>
302
+ </div>
303
+ ))}
304
+ </div>
305
+ </motion.div>
306
+ </AnimatePresence>
307
+ </div>
308
+ </motion.div>
309
+ )
310
+ }
311
+
312
+ function PageHero({ body, children, eyebrow, title }: { body: string; children?: ReactNode; eyebrow: string; title: string }) {
313
+ const reveal = useMotionPattern('reveal')
314
+ return (
315
+ <motion.section
316
+ animate="visible"
317
+ className="page-hero-secondary"
318
+ id="top"
319
+ initial={reveal.enabled ? 'hidden' : false}
320
+ variants={{
321
+ hidden: {},
322
+ visible: { transition: { delayChildren: 0.06, staggerChildren: reveal.enabled ? 0.08 : 0 } },
323
+ }}
324
+ >
325
+ <div className="hero-grid" aria-hidden="true" />
326
+ <motion.p className="eyebrow" variants={{ hidden: { opacity: 0, y: 12 }, visible: { opacity: 1, y: 0, transition: reveal.transition } }}>{eyebrow}</motion.p>
327
+ <motion.h1 variants={{ hidden: { opacity: 0, y: 16 }, visible: { opacity: 1, y: 0, transition: reveal.transition } }}>{title}</motion.h1>
328
+ <motion.p variants={{ hidden: { opacity: 0, y: 14 }, visible: { opacity: 1, y: 0, transition: reveal.transition } }}>{body}</motion.p>
329
+ {children ? <motion.div className="hero-actions" variants={{ hidden: { opacity: 0, y: 12 }, visible: { opacity: 1, y: 0, transition: reveal.transition } }}>{children}</motion.div> : null}
330
+ </motion.section>
331
+ )
332
+ }
333
+
334
+ function PageCta({ locale, seed }: { locale: Locale; seed: number }) {
335
+ return (
336
+ <section className="section page-cta">
337
+ <div><p className="eyebrow">{locale === 'ar' ? 'الخطوة التالية' : 'Next step'}</p><h2>{locale === 'ar' ? 'حوّل أول سير عمل إلى نظام مشترك.' : 'Turn your first workflow into a shared system.'}</h2></div>
338
+ <Button endContent={<ArrowIcon />} onClick={() => { window.location.href = pageHref('contact-sales', seed) }} size="lg">{locale === 'ar' ? 'تحدث مع فريقنا' : 'Talk to our team'}</Button>
339
+ </section>
340
+ )
341
+ }
342
+
343
+ function ProductPage({ demo, locale, previewMode, seed, setPreviewMode }: { demo: DemoData; locale: Locale; previewMode: PreviewMode; seed: number; setPreviewMode: (mode: PreviewMode) => void }) {
344
+ const capabilities = locale === 'ar'
345
+ ? [['الاستقبال', 'حوّل البريد والنماذج والأحداث إلى عمل منظم.'], ['التخطيط', 'اربط الأهداف بالمشاريع والقرارات اليومية.'], ['التنفيذ', 'حافظ على وضوح المسؤولية والموافقات وحالة العمل.'], ['المؤشرات', 'اقرأ الاختناقات والنتائج من نموذج تشغيل واحد.']]
346
+ : [['Intake', 'Turn email, forms, and events into structured work.'], ['Planning', 'Connect goals to projects and daily decisions.'], ['Execution', 'Keep ownership, approvals, and work state legible.'], ['Insights', 'Read bottlenecks and outcomes from one operating model.']]
347
+ return <>
348
+ <PageHero body={locale === 'ar' ? 'مساحة تشغيل واحدة تربط التخطيط والتنفيذ والأتمتة من دون فقدان السياق.' : 'One operating workspace connects planning, execution, and automation without losing context.'} eyebrow={locale === 'ar' ? 'المنتج' : 'Product'} title={locale === 'ar' ? 'خطّط للعمل وشغّله من النظام نفسه.' : 'Plan the work. Run it from the same system.'}>
349
+ <Button endContent={<ArrowIcon />} onClick={() => { window.location.href = pageHref('contact-sales', seed) }} size="lg">{locale === 'ar' ? 'اطلب عرضاً' : 'Request a demo'}</Button>
350
+ <Button onClick={() => document.getElementById('interface')?.scrollIntoView({ behavior: 'smooth' })} size="lg" variant="outline">{locale === 'ar' ? 'استكشف الواجهة' : 'Explore the interface'}</Button>
351
+ </PageHero>
352
+ <section className="section" id="interface"><SectionHeading body={locale === 'ar' ? 'تتغير الواجهات مع المهمة، لكنها تبقى متصلة بالبيانات نفسها.' : 'Views change with the task while staying connected to the same underlying data.'} eyebrow={locale === 'ar' ? 'نظام عمل حي' : 'A living work system'} title={locale === 'ar' ? 'كل فريق يرى ما يحتاجه، من دون إنشاء مصدر حقيقة جديد.' : 'Every team gets the view it needs without creating a new source of truth.'} /><ProductPreview locale={locale} mode={previewMode} product={demo.product} setMode={setPreviewMode} /></section>
353
+ <section className="section" id="workflow"><SectionHeading body={locale === 'ar' ? 'ابدأ بتدفق واحد ثم وسّع النموذج نفسه إلى بقية المؤسسة.' : 'Start with one flow, then extend the same model across the organization.'} eyebrow={locale === 'ar' ? 'القدرات الأساسية' : 'Core capabilities'} title={locale === 'ar' ? 'بنية واضحة للعمل المتغير.' : 'A clear structure for work that keeps changing.'} /><div className="capability-grid">{capabilities.map(([title, body], index) => <Card accent="hover" key={title}><CardHeader><Badge variant="outline">0{index + 1}</Badge><CardTitle>{title}</CardTitle><CardDescription>{body}</CardDescription></CardHeader></Card>)}</div></section>
354
+ <PageCta locale={locale} seed={seed} />
355
+ </>
356
+ }
357
+
358
+ function AgentsPage({ demo, locale, seed }: { demo: DemoData; locale: Locale; seed: number }) {
359
+ const useCases = locale === 'ar'
360
+ ? [['فرز الطلبات', 'اقرأ الطلب وحدد الأولوية والمسؤول قبل أن يصل إلى قائمة الفريق.'], ['تجهيز القرارات', 'اجمع السياق والخيارات والمخاطر قبل نقطة الاعتماد.'], ['متابعة الالتزامات', 'راقب المهلات والتبعيات وصعّد الحالات التي تحتاج تدخلاً.']]
361
+ : [['Request triage', 'Read the request, set priority, and identify an owner before it reaches the team queue.'], ['Decision preparation', 'Collect context, options, and risk before the approval moment.'], ['Commitment follow-up', 'Watch deadlines and dependencies, escalating only when intervention is needed.']]
362
+ return <>
363
+ <PageHero body={locale === 'ar' ? 'وكلاء يعملون داخل حدود واضحة، ويتركون القرارات الحساسة للأشخاص المناسبين.' : 'Agents work inside explicit boundaries and leave consequential decisions to the right people.'} eyebrow={locale === 'ar' ? 'الوكلاء والأتمتة' : 'Agents & automation'} title={locale === 'ar' ? 'أتمت العمل المتكرر، لا المساءلة.' : 'Automate the repeatable work, not accountability.'}>
364
+ <Button endContent={<ArrowIcon />} onClick={() => { window.location.href = pageHref('contact-sales', seed) }} size="lg">{locale === 'ar' ? 'صمّم أول وكيل' : 'Design your first agent'}</Button>
365
+ </PageHero>
366
+ <section className="section agents-detail-layout"><div><p className="eyebrow">{locale === 'ar' ? 'داخل سير العمل' : 'Inside the workflow'}</p><h2>{locale === 'ar' ? 'كل إجراء قابل للفهم والمراجعة والإيقاف.' : 'Every action can be understood, reviewed, and stopped.'}</h2><p>{locale === 'ar' ? 'يشاهد الفريق الإشارة والقاعدة والنتيجة في المكان نفسه.' : 'The team sees the signal, rule, and outcome in one place.'}</p></div><div className="agent-console"><div className="console-head"><span><Bot aria-hidden="true" />{locale === 'ar' ? 'وكيل الفرز' : 'Triage agent'}</span><Badge variant="success">{locale === 'ar' ? 'نشط' : 'Active'}</Badge></div><div className="agent-flow"><div><span>01</span><p>{locale === 'ar' ? 'تم اكتشاف إشارة جديدة' : 'New signal detected'}</p><small>09:42</small></div><i /><div><span>02</span><p>{locale === 'ar' ? 'تم تجهيز السياق والاقتراح' : 'Context and recommendation prepared'}</p><small>09:43</small></div><i /><div className="requires-review"><span>03</span><p>{locale === 'ar' ? 'مطلوب اعتماد بشري' : 'Human approval required'}</p><Button size="sm">{locale === 'ar' ? 'مراجعة' : 'Review'}</Button></div></div><div className="console-note"><ShieldCheck aria-hidden="true" /><span>{locale === 'ar' ? `جميع الإجراءات مسجلة في ${demo.product}.` : `Every action is recorded in ${demo.product}.`}</span></div></div></section>
367
+ <section className="section"><SectionHeading body={locale === 'ar' ? 'نقاط بداية عملية يمكن مراجعتها قبل التوسع.' : 'Practical starting points that can be reviewed before they scale.'} eyebrow={locale === 'ar' ? 'أنماط الوكلاء' : 'Agent patterns'} title={locale === 'ar' ? 'ابدأ من عمل يعرفه فريقك بالفعل.' : 'Begin with work your team already understands.'} /><div className="security-grid">{useCases.map(([title, body]) => <Card accent="hover" key={title}><CardHeader><div className="security-icon"><Sparkles aria-hidden="true" /></div><CardTitle>{title}</CardTitle><CardDescription>{body}</CardDescription></CardHeader></Card>)}</div></section>
368
+ <PageCta locale={locale} seed={seed} />
369
+ </>
370
+ }
371
+
372
+ const integrationDirectory = ['Slack', 'Salesforce', 'HubSpot', 'GitHub', 'Notion', 'Snowflake', 'Jira', 'Microsoft 365', 'Zendesk', 'Figma', 'Google Drive', 'Datadog']
373
+
374
+ function IntegrationsPage({ locale, seed }: { locale: Locale; seed: number }) {
375
+ const [query, setQuery] = useState('')
376
+ const visible = integrationDirectory.filter((item) => item.toLowerCase().includes(query.toLowerCase()))
377
+ return <>
378
+ <PageHero body={locale === 'ar' ? 'اربط مصادر الإشارة والعمل والبيانات من دون بناء طبقة صيانة جديدة.' : 'Connect signal, work, and data sources without creating another maintenance layer.'} eyebrow={locale === 'ar' ? 'دليل التكاملات' : 'Integration directory'} title={locale === 'ar' ? 'أدواتك الحالية، ضمن سير عمل واحد.' : 'Your existing tools, inside one workflow.'} />
379
+ <section className="section directory-section"><div className="directory-toolbar"><label><Search aria-hidden="true" /><span className="sr-only">{locale === 'ar' ? 'بحث' : 'Search'}</span><TextInput onChange={(event) => setQuery(event.target.value)} placeholder={locale === 'ar' ? 'ابحث في التكاملات' : 'Search integrations'} type="search" value={query} /></label><Badge variant="outline">{visible.length} {locale === 'ar' ? 'تكاملات' : 'integrations'}</Badge></div><div className="directory-grid">{visible.map((name, index) => { const IntegrationIcon = [Zap, Cloud, Database, GitBranch, Code2, Database, Workflow, Globe2][index % 8]; return <a className="directory-card" href={`${pageHref('integrations/slack', seed)}&connector=${encodeURIComponent(name)}`} key={name}><span><IntegrationIcon aria-hidden="true" /></span><div><strong>{name}</strong><small>{locale === 'ar' ? 'مزامنة ثنائية الاتجاه' : 'Two-way sync'}</small></div><ChevronRight aria-hidden="true" className="directional-icon" /></a>})}</div></section>
380
+ <PageCta locale={locale} seed={seed} />
381
+ </>
382
+ }
383
+
384
+ function IntegrationDetailPage({ demo, locale, seed }: { demo: DemoData; locale: Locale; seed: number }) {
385
+ const connector = new URLSearchParams(window.location.search).get('connector') || 'Slack'
386
+ return <>
387
+ <section className="detail-hero" id="top"><nav aria-label={locale === 'ar' ? 'مسار التنقل' : 'Breadcrumb'}><a href={pageHref('integrations', seed)}>{locale === 'ar' ? 'التكاملات' : 'Integrations'}</a><ChevronRight aria-hidden="true" className="directional-icon" /><span>{connector}</span></nav><div className="integration-detail-title"><span><Zap aria-hidden="true" /></span><div><p className="eyebrow">{locale === 'ar' ? 'تكامل معتمد' : 'Verified integration'}</p><h1>{connector} + {demo.product}</h1><p>{locale === 'ar' ? 'حوّل المحادثات والطلبات إلى عمل قابل للتتبع، وأعد التحديثات إلى القناة الصحيحة.' : 'Turn conversations and requests into traceable work, then return updates to the right channel.'}</p><Button endContent={<ArrowIcon />} size="lg">{locale === 'ar' ? `ربط ${connector}` : `Connect ${connector}`}</Button></div></div></section>
388
+ <section className="section detail-columns"><aside><strong>{locale === 'ar' ? 'في هذه الصفحة' : 'On this page'}</strong><a href="#capabilities">{locale === 'ar' ? 'القدرات' : 'Capabilities'}</a><a href="#setup">{locale === 'ar' ? 'الإعداد' : 'Setup'}</a><a href="#related">{locale === 'ar' ? 'تكاملات ذات صلة' : 'Related'}</a></aside><div><section id="capabilities"><h2>{locale === 'ar' ? 'اجعل القنوات نقطة دخول، لا مستودع عمل.' : 'Make channels an entry point, not a work repository.'}</h2><div className="detail-list">{(locale === 'ar' ? ['إنشاء سجل من رسالة أو رمز تفاعل', 'توجيه الطلب بناء على القناة والسياق', 'نشر حالة العمل والقرار تلقائياً'] : ['Create a record from a message or reaction', 'Route the request using channel and context', 'Publish work state and decisions automatically']).map((item) => <div key={item}><Check aria-hidden="true" /><span>{item}</span></div>)}</div></section><section id="setup"><h2>{locale === 'ar' ? 'إعداد واضح في ثلاث خطوات.' : 'A legible three-step setup.'}</h2><ol className="setup-steps">{(locale === 'ar' ? ['اعتمد مساحة العمل', 'اختر القنوات والقواعد', 'اختبر التدفق ثم انشره'] : ['Authorize the workspace', 'Choose channels and routing rules', 'Test the flow, then publish']).map((item, index) => <li key={item}><span>0{index + 1}</span>{item}</li>)}</ol></section><section id="related"><h2>{locale === 'ar' ? 'تكاملات ذات صلة' : 'Related integrations'}</h2><div className="capability-grid">{['Microsoft 365', 'Zendesk', 'Salesforce'].map((name) => <Card key={name}><CardHeader><CardTitle>{name}</CardTitle><CardDescription>{locale === 'ar' ? 'اربط السياق والتحديثات بسير العمل.' : 'Connect context and updates to the workflow.'}</CardDescription></CardHeader></Card>)}</div></section></div></section>
389
+ </>
390
+ }
391
+
392
+ function CustomersPage({ demo, locale, seed }: { demo: DemoData; locale: Locale; seed: number }) {
393
+ const stories = [['Sahm Cloud', 'Fintech', '31%'], ['Northstar Health', 'Health', '24%'], ['Majlis Works', 'Venture studio', '42%'], ['Cedar Systems', 'Infrastructure', '38%']]
394
+ return <>
395
+ <PageHero body={locale === 'ar' ? 'قصص فرق بنت إيقاعاً تشغيلياً أوضح عبر مناطق ومنتجات متعددة.' : 'Stories from teams that built a clearer operating rhythm across regions and products.'} eyebrow={locale === 'ar' ? 'العملاء' : 'Customers'} title={locale === 'ar' ? 'فرق تبني المستقبل بنظام عمل مشترك.' : 'Teams building the future on a shared work system.'} />
396
+ <section className="section featured-story"><div><p className="eyebrow">{locale === 'ar' ? 'قصة مميزة' : 'Featured story'}</p><h2>{locale === 'ar' ? `كيف وحّدت ${demo.company} العمل بين المنتج والعمليات.` : `How ${demo.company} unified product and operations.`}</h2><p>{locale === 'ar' ? 'نموذج تشغيل واحد حل محل الجداول والاجتماعات وعمليات التسليم المتكررة.' : 'One operating model replaced spreadsheets, status meetings, and repeated handoffs.'}</p><a href={pageHref('customers/aster-labs', seed)}>{locale === 'ar' ? 'اقرأ القصة' : 'Read the story'}<ArrowIcon /></a></div><div className="story-visual"><span>{demo.metric}%</span><p>{locale === 'ar' ? 'دورة عمل أقصر' : 'shorter work cycle'}</p></div></section>
397
+ <section className="section"><SectionHeading body={locale === 'ar' ? 'كل مثال يستخدم بيانات تجريبية حتمية قابلة للاستبدال.' : 'Every example uses deterministic demo data that is ready to replace.'} eyebrow={locale === 'ar' ? 'مكتبة العملاء' : 'Customer library'} title={locale === 'ar' ? 'أدلة بحسب الفريق والسياق.' : 'Proof across teams and contexts.'} /><div className="story-grid">{stories.map(([name, sector, metric]) => <a href={pageHref('customers/aster-labs', seed)} key={name}><span>{sector}</span><h3>{name}</h3><strong>{metric}</strong><p>{locale === 'ar' ? 'تحسن في سرعة التسليم' : 'faster delivery cadence'}</p><ChevronRight aria-hidden="true" className="directional-icon" /></a>)}</div></section>
398
+ <PageCta locale={locale} seed={seed} />
399
+ </>
400
+ }
401
+
402
+ function CustomerStoryPage({ demo, locale, seed }: { demo: DemoData; locale: Locale; seed: number }) {
403
+ return <>
404
+ <article className="case-study" id="top"><header><nav aria-label={locale === 'ar' ? 'مسار التنقل' : 'Breadcrumb'}><a href={pageHref('customers', seed)}>{locale === 'ar' ? 'العملاء' : 'Customers'}</a><ChevronRight aria-hidden="true" className="directional-icon" /><span>{demo.company}</span></nav><p className="eyebrow">{locale === 'ar' ? 'دراسة حالة' : 'Customer story'}</p><h1>{locale === 'ar' ? `${demo.company} تبني نظاماً واحداً للتخطيط والتنفيذ.` : `${demo.company} builds one system for planning and execution.`}</h1><p>{locale === 'ar' ? 'كيف استبدل فريق موزع تنسيقاً مجزأً بنموذج تشغيل واضح وقابل للقياس.' : 'How a distributed team replaced fragmented coordination with a clear, measurable operating model.'}</p></header><div className="case-metrics"><span><strong>{demo.metric}%</strong>{locale === 'ar' ? 'دورة أقصر' : 'shorter cycle'}</span><span><strong>3.2×</strong>{locale === 'ar' ? 'قرارات أسرع' : 'faster decisions'}</span><span><strong>1</strong>{locale === 'ar' ? 'مصدر حقيقة' : 'source of truth'}</span></div><div className="article-layout"><aside><strong>{demo.company}</strong><span>120 {locale === 'ar' ? 'موظفاً' : 'people'}</span><span>{locale === 'ar' ? 'الدوحة ولندن' : 'Doha & London'}</span><span>{locale === 'ar' ? 'التقنية المالية' : 'Financial technology'}</span></aside><div><h2>{locale === 'ar' ? 'التحدي' : 'The challenge'}</h2><p>{locale === 'ar' ? 'توزعت الطلبات والقرارات على المحادثات والجداول واجتماعات الحالة. كان كل فريق يرى جزءاً من الصورة فقط.' : 'Requests and decisions were spread across chat, spreadsheets, and status meetings. Each team could only see part of the picture.'}</p><h2>{locale === 'ar' ? 'التغيير' : 'The change'}</h2><p>{locale === 'ar' ? `بدأت ${demo.company} بسير عمل واحد عالي الاحتكاك، ثم ربطت الإشارات والموافقات والنتائج في ${demo.product}.` : `${demo.company} began with one high-friction workflow, then connected signals, approvals, and outcomes in ${demo.product}.`}</p><blockquote>“{locale === 'ar' ? 'أصبح بإمكاننا رؤية القرار والمسؤول والخطوة التالية من دون طلب تحديث جديد.' : 'We can see the decision, owner, and next move without asking for another update.'}”<cite>{demo.leaders[0]}, {locale === 'ar' ? 'نائب الرئيس للعمليات' : 'VP Operations'}</cite></blockquote><h2>{locale === 'ar' ? 'النتيجة' : 'The outcome'}</h2><p>{locale === 'ar' ? 'انخفض وقت الانتظار بين الفرق، وأصبحت نقاط الاعتماد والتصعيد جزءاً قابلاً للقياس من النظام.' : 'Wait time between teams fell, while approval and escalation became measurable parts of the system.'}</p></div></div></article>
405
+ <PageCta locale={locale} seed={seed} />
406
+ </>
407
+ }
408
+
409
+ function PricingPage({ demo, locale, seed }: { demo: DemoData; locale: Locale; seed: number }) {
410
+ const plans = locale === 'ar'
411
+ ? [['البداية', `$${demo.price}`, 'لفريق يبدأ أول سير عمل.', ['5 أعضاء أساسيين', 'تكاملات جاهزة', 'سجل نشاط']], ['النمو', `$${demo.price + 30}`, 'لفرق تربط عدة عمليات.', ['أعضاء بلا حد', 'وكلاء وأتمتة', 'تحليلات متقدمة']], ['المؤسسة', 'مخصص', 'للحوكمة والتوسع الإقليمي.', ['صلاحيات دقيقة', 'مناطق بيانات', 'دعم مخصص']]]
412
+ : [['Starter', `$${demo.price}`, 'For a team launching its first workflow.', ['5 core members', 'Native integrations', 'Activity history']], ['Scale', `$${demo.price + 30}`, 'For teams connecting multiple operations.', ['Unlimited members', 'Agents and automation', 'Advanced analytics']], ['Enterprise', 'Custom', 'For governance and regional scale.', ['Granular access', 'Data regions', 'Dedicated support']]]
413
+ return <>
414
+ <PageHero body={locale === 'ar' ? 'ابدأ صغيراً مع كل الأساسيات، ثم أضف الأتمتة والحوكمة عندما تحتاجها.' : 'Start small with the full foundation, then add automation and governance when needed.'} eyebrow={locale === 'ar' ? 'الأسعار' : 'Pricing'} title={locale === 'ar' ? 'سعر واضح لكل مرحلة من الاعتماد.' : 'Clear pricing for every stage of adoption.'} />
415
+ <section className="section pricing-page-grid">{plans.map(([name, price, description, features], index) => <Card accent={index === 1 ? 'always' : 'hover'} key={name as string}><CardHeader><Badge variant={index === 1 ? 'default' : 'outline'}>{index === 1 ? (locale === 'ar' ? 'الأكثر اختياراً' : 'Most selected') : (locale === 'ar' ? 'خطة' : 'Plan')}</Badge><CardTitle>{name as string}</CardTitle><CardDescription>{description as string}</CardDescription></CardHeader><CardContent><div className="plan-price"><strong>{price as string}</strong>{price !== 'Custom' && price !== 'مخصص' ? <span>{locale === 'ar' ? '/ شهرياً' : '/ month'}</span> : null}</div><ul>{(features as string[]).map((feature) => <li key={feature}><Check aria-hidden="true" />{feature}</li>)}</ul><Button onClick={() => { window.location.href = pageHref('contact-sales', seed) }} size="lg" variant={index === 1 ? 'default' : 'outline'}>{locale === 'ar' ? 'اختر الخطة' : 'Choose plan'}</Button></CardContent></Card>)}</section>
416
+ <section className="section comparison-section"><SectionHeading body={locale === 'ar' ? 'قارن الحدود التي تتغير مع حجم المؤسسة.' : 'Compare the controls that change with organizational scale.'} eyebrow={locale === 'ar' ? 'المقارنة' : 'Compare'} title={locale === 'ar' ? 'الأساس مشترك في كل الخطط.' : 'The foundation is shared across every plan.'} /><div className="comparison-table" role="table"><div role="row"><strong role="columnheader">{locale === 'ar' ? 'القدرة' : 'Capability'}</strong><strong role="columnheader">Starter</strong><strong role="columnheader">Scale</strong><strong role="columnheader">Enterprise</strong></div>{[['Workflows', '3', 'Unlimited', 'Unlimited'], ['Automation runs', '1k', '25k', 'Custom'], ['Audit history', '90 days', '1 year', 'Custom'], ['Data regions', '—', '2', '4']].map((row) => <div role="row" key={row[0]}>{row.map((cell) => <span role="cell" key={cell}>{cell}</span>)}</div>)}</div></section>
417
+ <section className="section faq-section"><SectionHeading body={locale === 'ar' ? 'إجابات مختصرة قبل البدء.' : 'Short answers before you begin.'} eyebrow={locale === 'ar' ? 'الأسئلة الشائعة' : 'FAQ'} title={locale === 'ar' ? 'ما تحتاج إلى معرفته.' : 'What you need to know.'} /><div>{(locale === 'ar' ? [['هل يمكن تغيير الخطة؟', 'نعم، يمكن الترقية أو التخفيض مع بداية دورة الفوترة التالية.'], ['هل يشمل السعر المشاهدين؟', 'المشاهدون بلا حد في جميع الخطط.'], ['هل تتوفر تجربة؟', 'تتضمن كل مساحة عمل فترة تقييم موجهة.']] : [['Can I change plans?', 'Yes. Upgrade or downgrade at the next billing cycle.'], ['Are viewers included?', 'Unlimited viewers are included on every plan.'], ['Is there a trial?', 'Every workspace includes a guided evaluation period.']]).map(([question, answer]) => <details key={question}><summary>{question}</summary><p>{answer}</p></details>)}</div></section>
418
+ </>
419
+ }
420
+
421
+ function ChangelogPage({ locale }: { locale: Locale }) {
422
+ const [filter, setFilter] = useState('all')
423
+ const entries = locale === 'ar'
424
+ ? [['14 يوليو 2026', 'حدود اعتماد الوكلاء', 'أضفنا سياسات اعتماد قابلة لإعادة الاستخدام لكل إجراء آلي.', 'product'], ['2 يوليو 2026', 'دليل تكاملات أسرع', 'بحث وتصنيف أوضح مع صفحات تفاصيل لكل موصل.', 'integrations'], ['18 يونيو 2026', 'مؤشرات سير العمل', 'مشاهد جديدة لوقت الانتظار والتسليم والاختناقات.', 'product'], ['3 يونيو 2026', 'مناطق بيانات إضافية', 'خيارات إقامة بيانات جديدة للفرق الإقليمية.', 'api']]
425
+ : [['July 14, 2026', 'Agent approval boundaries', 'Reusable approval policies can now govern every automated action.', 'product'], ['July 2, 2026', 'A faster integration directory', 'Clearer search and categories with detail pages for every connector.', 'integrations'], ['June 18, 2026', 'Workflow insights', 'New views for wait time, handoffs, and bottlenecks.', 'product'], ['June 3, 2026', 'Additional data regions', 'New data residency options for regional teams.', 'api']]
426
+ const filters = [['all', locale === 'ar' ? 'الكل' : 'All updates'], ['product', locale === 'ar' ? 'المنتج' : 'Product'], ['integrations', locale === 'ar' ? 'التكاملات' : 'Integrations'], ['api', 'API']]
427
+ const visibleEntries = entries.filter((entry) => filter === 'all' || entry[3] === filter)
428
+ return <>
429
+ <PageHero body={locale === 'ar' ? 'تحسينات صغيرة وكبيرة على المنتج والنظام والتجربة.' : 'Small and substantial improvements across the product, system, and experience.'} eyebrow={locale === 'ar' ? 'سجل التغييرات' : 'Changelog'} title={locale === 'ar' ? 'ما الجديد في المنتج.' : 'What is new in the product.'} />
430
+ <section className="section changelog-layout"><aside><strong>{locale === 'ar' ? 'التصفية' : 'Filter'}</strong>{filters.map(([key, label]) => <button aria-pressed={filter === key} key={key} onClick={() => setFilter(key)} type="button">{label}</button>)}</aside><div aria-live="polite">{visibleEntries.map(([date, title, body], index) => <article key={title}><span>{date}</span><div><Badge variant="outline">v2.{8 - index}</Badge><h2>{title}</h2><p>{body}</p><div className="changelog-visual"><span>{index % 2 === 0 ? <Bot aria-hidden="true" /> : <Workflow aria-hidden="true" />}</span><strong>{title}</strong><small>{locale === 'ar' ? 'معاينة تحديث المنتج' : 'Product update preview'}</small></div></div></article>)}</div></section>
431
+ </>
432
+ }
433
+
434
+ function ContactSalesPage({ demo, locale }: { demo: DemoData; locale: Locale }) {
435
+ const [submitted, setSubmitted] = useState(false)
436
+ if (submitted) return <section className="contact-success" id="top"><CircleCheck aria-hidden="true" /><p className="eyebrow">{locale === 'ar' ? 'تم استلام الطلب' : 'Request received'}</p><h1>{locale === 'ar' ? 'سنتواصل معك قريباً.' : 'We will be in touch shortly.'}</h1><p>{locale === 'ar' ? `شكراً لاهتمامك بـ ${demo.product}.` : `Thank you for your interest in ${demo.product}.`}</p></section>
437
+ return <section className="contact-layout" id="top"><div><p className="eyebrow">{locale === 'ar' ? 'تواصل مع المبيعات' : 'Contact sales'}</p><h1>{locale === 'ar' ? 'صمّم مسار اعتماد يناسب فريقك.' : 'Design an adoption path for your team.'}</h1><p>{locale === 'ar' ? 'اطلب عرضاً، اختر الخطة المناسبة، واحصل على مساعدة في الإعداد.' : 'Request a demo, choose the right plan, and get help with setup.'}</p><ul>{(locale === 'ar' ? ['عرض مخصص لسير عملك', 'توصية بالخطة والحوكمة', 'دعم للإعداد والتكامل'] : ['A demo tailored to your workflow', 'Plan and governance recommendation', 'Setup and integration support']).map((item) => <li key={item}><Check aria-hidden="true" />{item}</li>)}</ul></div><form onSubmit={(event) => { event.preventDefault(); setSubmitted(true) }}><label>{locale === 'ar' ? 'الاسم' : 'Name'}<TextInput name="name" required /></label><label>{locale === 'ar' ? 'البريد للعمل' : 'Work email'}<TextInput name="email" required type="email" /></label><label>{locale === 'ar' ? 'الشركة' : 'Company'}<TextInput name="company" required /></label><label>{locale === 'ar' ? 'حجم الفريق' : 'Team size'}<Selector defaultValue=""><option disabled value="">{locale === 'ar' ? 'اختر' : 'Select'}</option><option>1–20</option><option>21–100</option><option>101–500</option><option>500+</option></Selector></label><label>{locale === 'ar' ? 'ما سير العمل الذي تريد تحسينه؟' : 'Which workflow do you want to improve?'}<Textarea name="workflow" rows={5} /></label><Button endContent={<ArrowIcon />} size="lg" type="submit">{locale === 'ar' ? 'إرسال الطلب' : 'Submit request'}</Button><small>{locale === 'ar' ? 'بيانات تجريبية فقط — لا يتم إرسالها إلى خدمة خارجية.' : 'Demo only — data is not sent to an external service.'}</small></form></section>
438
+ }
439
+
440
+ function SecondaryPage({ demo, locale, page, previewMode, seed, setPreviewMode }: { demo: DemoData; locale: Locale; page: PageKey; previewMode: PreviewMode; seed: number; setPreviewMode: (mode: PreviewMode) => void }) {
441
+ if (page === 'product') return <ProductPage demo={demo} locale={locale} previewMode={previewMode} seed={seed} setPreviewMode={setPreviewMode} />
442
+ if (page === 'agents') return <AgentsPage demo={demo} locale={locale} seed={seed} />
443
+ if (page === 'integrations') return <IntegrationsPage locale={locale} seed={seed} />
444
+ if (page === 'integration-detail') return <IntegrationDetailPage demo={demo} locale={locale} seed={seed} />
445
+ if (page === 'customers') return <CustomersPage demo={demo} locale={locale} seed={seed} />
446
+ if (page === 'customer-story') return <CustomerStoryPage demo={demo} locale={locale} seed={seed} />
447
+ if (page === 'pricing') return <PricingPage demo={demo} locale={locale} seed={seed} />
448
+ if (page === 'changelog') return <ChangelogPage locale={locale} />
449
+ return <ContactSalesPage demo={demo} locale={locale} />
450
+ }
451
+
452
+ function App() {
453
+ const params = new URLSearchParams(window.location.search)
454
+ const seed = Number(params.get('seed')) || 1974341818
455
+ const page = getPageKey()
456
+ const [locale, setLocale] = useState<Locale>(() => window.localStorage.getItem('ceramic-saas-locale') === 'ar' ? 'ar' : 'en')
457
+ const [colorMode, setColorMode] = useState<'dark' | 'light'>(() => window.localStorage.getItem('ceramic-saas-mode') === 'light' ? 'light' : 'dark')
458
+ const [previewMode, setPreviewMode] = useState<PreviewMode>('overview')
459
+ const [isolated, setIsolated] = useState(false)
460
+ const [menuOpen, setMenuOpen] = useState(false)
461
+ const pageMotion = useMotionPattern('page')
462
+ const revealMotion = useMotionPattern('reveal')
463
+ const t = copy[locale]
464
+ const siteNav = [
465
+ { key: 'product', label: locale === 'ar' ? 'المنتج' : 'Product', href: pageHref('product', seed) },
466
+ { key: 'agents', label: locale === 'ar' ? 'الوكلاء' : 'Agents', href: pageHref('agents', seed) },
467
+ { key: 'integrations', label: locale === 'ar' ? 'التكاملات' : 'Integrations', href: pageHref('integrations', seed) },
468
+ { key: 'customers', label: locale === 'ar' ? 'العملاء' : 'Customers', href: pageHref('customers', seed) },
469
+ { key: 'pricing', label: locale === 'ar' ? 'الأسعار' : 'Pricing', href: pageHref('pricing', seed) },
470
+ { key: 'changelog', label: locale === 'ar' ? 'التحديثات' : 'Changelog', href: pageHref('changelog', seed) },
471
+ ]
472
+ const goTo = (id: string) => {
473
+ window.history.pushState(null, '', `#${id}`)
474
+ document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' })
475
+ }
476
+ const demo = useMemo(() => {
477
+ const set = seededIndex(seed, 11, demoSets.product.length)
478
+ return {
479
+ product: demoSets.product[set],
480
+ company: demoSets.company[seededIndex(seed, 23, demoSets.company.length)],
481
+ leaders: demoSets.leaders[seededIndex(seed, 37, demoSets.leaders.length)],
482
+ price: demoSets.price[seededIndex(seed, 47, demoSets.price.length)],
483
+ metric: demoSets.metric[seededIndex(seed, 59, demoSets.metric.length)],
484
+ }
485
+ }, [seed])
486
+
487
+ useEffect(() => {
488
+ document.documentElement.lang = locale
489
+ document.documentElement.dir = locale === 'ar' ? 'rtl' : 'ltr'
490
+ document.documentElement.dataset.theme = activeTheme
491
+ document.documentElement.dataset.colorMode = colorMode
492
+ window.localStorage.setItem('ceramic-saas-locale', locale)
493
+ window.localStorage.setItem('ceramic-saas-mode', colorMode)
494
+ }, [colorMode, locale])
495
+
496
+ useEffect(() => {
497
+ const pageName = page === 'home' ? (locale === 'ar' ? 'الرئيسية' : 'Home') : siteNav.find((item) => item.key === page)?.label ?? (locale === 'ar' ? 'التفاصيل' : 'Details')
498
+ document.title = `${pageName} — ${demo.product}`
499
+ }, [demo.product, locale, page])
500
+
501
+ useEffect(() => {
502
+ const onScroll = () => setIsolated(window.scrollY > 28)
503
+ onScroll()
504
+ window.addEventListener('scroll', onScroll, { passive: true })
505
+ return () => window.removeEventListener('scroll', onScroll)
506
+ }, [])
507
+
508
+ useEffect(() => {
509
+ const targetId = window.location.hash.replace(/^#/, '')
510
+ if (!targetId) return
511
+ const frame = window.requestAnimationFrame(() => {
512
+ document.getElementById(targetId)?.scrollIntoView({ block: 'start' })
513
+ })
514
+ return () => window.cancelAnimationFrame(frame)
515
+ }, [page])
516
+
517
+ const workflowSteps = locale === 'ar'
518
+ ? [['استقبل', 'حوّل الطلبات والإشارات إلى سجل منظم مع السياق الصحيح.'], ['نسّق', 'حدد المسؤول والخطوة التالية واتفاقية مستوى الخدمة تلقائياً.'], ['اعتمد', 'أدخل الحكم البشري عند القرارات الحساسة فقط.'], ['تعلّم', 'حوّل النتائج إلى قواعد ومؤشرات أوضح للدورة التالية.']]
519
+ : [['Capture', 'Turn requests and signals into structured work with the right context.'], ['Coordinate', 'Assign the owner, next action, and service level automatically.'], ['Approve', 'Bring human judgment into the moments that carry real consequence.'], ['Learn', 'Feed outcomes back into clearer rules and signals for the next cycle.']]
520
+ const integrationNames = ['Slack', 'Salesforce', 'HubSpot', 'GitHub', 'Notion', 'Snowflake', 'Jira', 'Microsoft 365']
521
+
522
+ return (
523
+ <div className="template-shell">
524
+ <header className="site-header" data-isolated={isolated || undefined}>
525
+ <div className="nav-frame">
526
+ <a className="product-logo" href={pageHref('', seed)} aria-label={`${demo.product} home`}><span className="brand-mark" />{demo.product}</a>
527
+ <TopNav aria-label={locale === 'ar' ? 'التنقل الرئيسي' : 'Primary navigation'} className="site-links">
528
+ {siteNav.map((item) => <TopNavItem href={item.href} isCurrent={page === item.key || (page === 'integration-detail' && item.key === 'integrations') || (page === 'customer-story' && item.key === 'customers')} key={item.key}>{item.label}</TopNavItem>)}
529
+ </TopNav>
530
+ <div className="nav-actions">
531
+ <Button aria-label={t.theme} isIconOnly onClick={() => setColorMode(colorMode === 'dark' ? 'light' : 'dark')} size="icon" variant="ghost">
532
+ {colorMode === 'dark' ? <Sun aria-hidden="true" /> : <Moon aria-hidden="true" />}
533
+ </Button>
534
+ <Button aria-label={locale === 'en' ? 'Switch to Arabic' : 'Switch to English'} className="language-button" onClick={() => setLocale(locale === 'en' ? 'ar' : 'en')} size="sm" startContent={<Languages aria-hidden="true" />} variant="ghost">{t.language}</Button>
535
+ <Button className="nav-cta" onClick={() => { window.location.href = pageHref('contact-sales', seed) }} size="sm">{t.contact}</Button>
536
+ <Button aria-expanded={menuOpen} aria-label={menuOpen ? t.closeMenu : t.menu} className="menu-button" isIconOnly onClick={() => setMenuOpen(!menuOpen)} size="icon" variant="ghost">
537
+ {menuOpen ? <X aria-hidden="true" /> : <Menu aria-hidden="true" />}
538
+ </Button>
539
+ </div>
540
+ </div>
541
+ <AnimatePresence initial={false}>
542
+ {menuOpen ? <motion.nav animate={{ opacity: 1, y: 0 }} className="mobile-menu" aria-label={t.menu} exit={{ opacity: 0, y: -8 }} initial={{ opacity: 0, y: -8 }} transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}>{siteNav.map((item) => <a href={item.href} key={item.key} onClick={() => setMenuOpen(false)}>{item.label}<ChevronRight aria-hidden="true" className="directional-icon" /></a>)}</motion.nav> : null}
543
+ </AnimatePresence>
544
+ </header>
545
+
546
+ <AnimatePresence mode="wait">
547
+ <motion.main
548
+ animate={{ opacity: 1, y: 0 }}
549
+ exit={pageMotion.enabled ? { opacity: 0, y: -6 } : undefined}
550
+ id="main-content"
551
+ initial={pageMotion.enabled ? { opacity: 0, y: 8 } : false}
552
+ key={`${page}-${locale}`}
553
+ transition={pageMotion.transition}
554
+ >
555
+ {page === 'home' ? <>
556
+ <motion.section
557
+ animate="visible"
558
+ className="hero"
559
+ id="top"
560
+ initial={revealMotion.enabled ? 'hidden' : false}
561
+ variants={{ hidden: {}, visible: { transition: { delayChildren: 0.08, staggerChildren: revealMotion.enabled ? 0.07 : 0 } } }}
562
+ >
563
+ <div className="hero-grid" aria-hidden="true" />
564
+ <motion.a className="announcement" href="#agents" variants={{ hidden: { opacity: 0, y: 10 }, visible: { opacity: 1, y: 0, transition: revealMotion.transition } }}><span>{t.announcement}</span><ChevronRight className="directional-icon" /></motion.a>
565
+ <motion.p className="eyebrow" variants={{ hidden: { opacity: 0, y: 12 }, visible: { opacity: 1, y: 0, transition: revealMotion.transition } }}>{t.heroEyebrow}</motion.p>
566
+ <motion.h1 variants={{ hidden: { opacity: 0, y: 18 }, visible: { opacity: 1, y: 0, transition: revealMotion.transition } }}>{t.heroTitle}</motion.h1>
567
+ <motion.p className="hero-copy" variants={{ hidden: { opacity: 0, y: 16 }, visible: { opacity: 1, y: 0, transition: revealMotion.transition } }}>{t.heroBody}</motion.p>
568
+ <motion.div className="hero-actions" variants={{ hidden: { opacity: 0, y: 14 }, visible: { opacity: 1, y: 0, transition: revealMotion.transition } }}>
569
+ <Button endContent={<ArrowIcon />} onClick={() => goTo('pricing')} size="lg">{t.start}</Button>
570
+ <Button onClick={() => goTo('product')} size="lg" startContent={<Play aria-hidden="true" />} variant="outline">{t.tour}</Button>
571
+ </motion.div>
572
+ <motion.div className="hero-proof" variants={{ hidden: { opacity: 0, y: 12 }, visible: { opacity: 1, y: 0, transition: revealMotion.transition } }}><span>{demo.metric}%</span><p>{locale === 'ar' ? 'وقت أقل في التنسيق اليدوي خلال أول 90 يوماً' : 'less time spent on manual coordination in the first 90 days'}</p></motion.div>
573
+ </motion.section>
574
+
575
+ <section className="section product-section" id="product">
576
+ <SectionHeading body={t.productBody} eyebrow={t.productEyebrow} title={t.productTitle} />
577
+ <ProductPreview locale={locale} mode={previewMode} product={demo.product} setMode={setPreviewMode} />
578
+ <RevealBlock className="logo-proof"><p>{t.trusted}</p><div>{['Sahm', 'NORTHSTAR', 'ASTER', 'CEDAR', 'MAJLIS'].map((name) => <span key={name}>{name}</span>)}</div></RevealBlock>
579
+ </section>
580
+
581
+ <section className="section workflow-section" id="workflow">
582
+ <SectionHeading body={t.workflowBody} eyebrow={t.workflowEyebrow} title={t.workflowTitle} />
583
+ <div className="workflow-grid">
584
+ {workflowSteps.map(([title, body], index) => (
585
+ <RevealBlock className="workflow-step" delay={index * 0.06} key={title}><span>0{index + 1}</span><div><h3>{title}</h3><p>{body}</p></div>{index < workflowSteps.length - 1 ? <ChevronRight aria-hidden="true" className="step-arrow directional-icon" /> : null}</RevealBlock>
586
+ ))}
587
+ </div>
588
+ </section>
589
+
590
+ <section className="section agents-section" id="agents">
591
+ <div className="agents-copy"><SectionHeading body={t.agentsBody} eyebrow={t.agentsEyebrow} title={t.agentsTitle} /><RevealBlock><ul className="check-list">
592
+ {(locale === 'ar' ? ['حدود اعتماد واضحة لكل إجراء', 'سجل قابل للمراجعة لكل قرار', 'تحويل فوري إلى عضو الفريق عند الحاجة'] : ['Explicit approval boundaries for every action', 'An inspectable trace for every decision', 'Immediate handoff to a teammate when needed']).map((item) => <li key={item}><Check aria-hidden="true" />{item}</li>)}
593
+ </ul></RevealBlock></div>
594
+ <RevealBlock className="agent-console">
595
+ <div className="console-head"><span><Bot aria-hidden="true" />{locale === 'ar' ? 'وكيل الفرز' : 'Triage agent'}</span><Badge variant="success">{locale === 'ar' ? 'نشط' : 'Active'}</Badge></div>
596
+ <div className="agent-flow"><div><span>01</span><p>{locale === 'ar' ? 'وصل طلب شراكة جديد' : 'New partnership request received'}</p><small>09:42</small></div><i /><div><span>02</span><p>{locale === 'ar' ? 'تم إثراء الحساب والسياق' : 'Account and context enriched'}</p><small>09:42</small></div><i /><div className="requires-review"><span>03</span><p>{locale === 'ar' ? 'مطلوب اعتماد بشري' : 'Human approval required'}</p><Button size="sm">{locale === 'ar' ? 'مراجعة' : 'Review'}</Button></div></div>
597
+ <div className="console-note"><ShieldCheck aria-hidden="true" /><span>{locale === 'ar' ? 'لن يرسل الوكيل أي رد قبل الاعتماد.' : 'The agent cannot send a response before approval.'}</span></div>
598
+ </RevealBlock>
599
+ </section>
600
+
601
+ <section className="section integrations-section" id="integrations">
602
+ <SectionHeading body={t.integrationsBody} eyebrow={t.integrationsEyebrow} title={t.integrationsTitle} />
603
+ <RevealBlock className="integration-stage">
604
+ <div className="integration-core"><Network aria-hidden="true" /><strong>{demo.product}</strong><span>{locale === 'ar' ? 'طبقة التشغيل' : 'Operating layer'}</span></div>
605
+ <div className="integration-grid">{integrationNames.map((name, index) => {
606
+ const IntegrationIcon = [Zap, Cloud, Database, GitBranch, Code2, Database, Workflow, Globe2][index]
607
+ return <div key={name}><span><IntegrationIcon aria-hidden="true" /></span><strong>{name}</strong><small>{locale === 'ar' ? 'متصل' : 'Connected'}</small></div>
608
+ })}</div>
609
+ </RevealBlock>
610
+ </section>
611
+
612
+ <section className="section security-section" id="security">
613
+ <SectionHeading body={t.securityBody} eyebrow={t.securityEyebrow} title={t.securityTitle} />
614
+ <div className="security-grid">
615
+ {[
616
+ [ShieldCheck, locale === 'ar' ? 'صلاحيات دقيقة' : 'Granular access', locale === 'ar' ? 'أدوار ونطاقات وموافقات تناسب طريقة عمل كل فريق.' : 'Roles, scopes, and approvals that match how each team operates.'],
617
+ [Clock3, locale === 'ar' ? 'سجل تدقيق كامل' : 'Complete audit trail', locale === 'ar' ? 'كل تغيير وإجراء آلي وقرار بشري قابل للتتبع.' : 'Every change, automated action, and human decision remains traceable.'],
618
+ [Globe2, locale === 'ar' ? 'جاهزية إقليمية' : 'Regional readiness', locale === 'ar' ? 'ضوابط بيانات وعمليات تناسب فرقاً تعمل عبر مناطق متعددة.' : 'Data and operating controls for teams working across regions.'],
619
+ ].map(([Icon, title, body], index) => <RevealBlock className="motion-card-wrap" delay={index * 0.06} key={String(title)}><Card accent="hover" className="security-card"><CardHeader><div className="security-icon"><Icon aria-hidden="true" /></div><CardTitle>{title as string}</CardTitle><CardDescription>{body as string}</CardDescription></CardHeader><CardContent><span><Check aria-hidden="true" />{locale === 'ar' ? 'متوفر في كل الخطط' : 'Available on every plan'}</span></CardContent></Card></RevealBlock>)}
620
+ </div>
621
+ <RevealBlock className="reliability-strip"><span><b>99.99%</b>{locale === 'ar' ? 'وقت التشغيل' : 'uptime'}</span><span><b>SOC 2</b>{locale === 'ar' ? 'ضوابط مدققة' : 'audited controls'}</span><span><b>24/7</b>{locale === 'ar' ? 'مراقبة' : 'monitoring'}</span><span><b>4</b>{locale === 'ar' ? 'مناطق بيانات' : 'data regions'}</span></RevealBlock>
622
+ </section>
623
+
624
+ <section className="section proof-section" aria-labelledby="proof-title">
625
+ <RevealBlock className="proof-number"><span>{demo.metric}%</span><p>{locale === 'ar' ? 'انخفاض في وقت دورة العمل بعد ربع واحد' : 'shorter work cycle after one quarter'}</p></RevealBlock>
626
+ <RevealBlock><figure className="quote"><p className="eyebrow" id="proof-title">{t.proofEyebrow}</p><blockquote>“{t.proofQuote}”</blockquote><figcaption><span>{demo.leaders[0].split(' ').map((part) => part[0]).join('')}</span><div><strong>{demo.leaders[0]}</strong><small>{t.proofRole}, {demo.company}</small></div></figcaption></figure></RevealBlock>
627
+ </section>
628
+
629
+ <section className="section pricing-section" id="pricing">
630
+ <div className="pricing-copy"><SectionHeading body={t.pricingBody} eyebrow={t.pricingEyebrow} title={t.pricingTitle} /><Button endContent={<ArrowIcon />} onClick={() => { window.location.href = 'mailto:hello@example.com?subject=SaaS%20workspace' }} size="lg">{t.contact}</Button></div>
631
+ <RevealBlock className="motion-card-wrap"><Card accent="always" className="pricing-card"><CardHeader><CardTitle>{t.plan}</CardTitle><CardDescription>{locale === 'ar' ? 'للفرق التي تبدأ سير عمل تشغيلياً مشتركاً.' : 'For teams beginning with one shared operational workflow.'}</CardDescription></CardHeader><CardContent><div className="price"><span>$</span><strong>{demo.price}</strong><small>{t.perMonth}</small></div><ul>{(locale === 'ar' ? ['5 أعضاء أساسيين', 'أتمتة ووكلاء بلا حد', 'تكاملات جاهزة', 'سجل تدقيق كامل'] : ['5 core members', 'Unlimited automations and agents', 'Native integrations', 'Complete audit history']).map((item) => <li key={item}><Check aria-hidden="true" />{item}</li>)}</ul><Button endContent={<ArrowIcon />} onClick={() => { window.location.href = 'mailto:hello@example.com?subject=Create%20workspace' }} size="lg">{t.cta}</Button><p>{t.planNote}</p></CardContent></Card></RevealBlock>
632
+ </section>
633
+ </> : <SecondaryPage demo={demo} locale={locale} page={page} previewMode={previewMode} seed={seed} setPreviewMode={setPreviewMode} />}
634
+ </motion.main>
635
+ </AnimatePresence>
636
+
637
+ <footer className="site-footer"><a className="product-logo" href={pageHref('', seed)}><span className="brand-mark" />{demo.product}</a><p>{t.footer}</p><div><a href={pageHref('product', seed)}>{locale === 'ar' ? 'المنتج' : 'Product'}</a><a href={pageHref('customers', seed)}>{locale === 'ar' ? 'العملاء' : 'Customers'}</a><a href={pageHref('pricing', seed)}>{locale === 'ar' ? 'الأسعار' : 'Pricing'}</a><a href={pageHref('contact-sales', seed)}>{locale === 'ar' ? 'اتصل بنا' : 'Contact'}</a></div><small>© 2026 {demo.product}. Seed {seed}.</small></footer>
638
+ </div>
639
+ )
640
+ }
641
+
642
+ createRoot(document.getElementById('root')!).render(<StrictMode><MotionProvider asChild><App /></MotionProvider></StrictMode>)