aeon-ui-engine 1.0.0 → 1.0.2

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 (88) hide show
  1. package/.changeset/config.json +2 -1
  2. package/CHANGELOG.md +38 -0
  3. package/COMPONENTS.md +7 -2
  4. package/INTEGRATION.md +14 -0
  5. package/PUBLISHING.md +20 -0
  6. package/README.md +8 -4
  7. package/apps/demo/og.config.mjs +8 -3
  8. package/apps/demo/public/og-aeon-ui-engine.png +0 -0
  9. package/apps/demo/public/og.svg +2 -2
  10. package/apps/demo/scripts/generate-og-png.mjs +4 -2
  11. package/apps/demo/src/App.tsx +2 -2
  12. package/apps/demo/src/aeonDiagrams.ts +17 -75
  13. package/apps/demo/src/components/DiagramsSection.tsx +8 -9
  14. package/apps/demo/src/components/HeroInstall.tsx +7 -4
  15. package/apps/demo/src/components/LandingFaq.tsx +1 -1
  16. package/apps/demo/src/components/LandingFooter.tsx +8 -0
  17. package/apps/demo/src/components/LandingHeader.tsx +4 -2
  18. package/apps/demo/src/components/LayersSection.tsx +6 -10
  19. package/apps/demo/src/components/MermaidDiagram.tsx +5 -3
  20. package/apps/demo/src/components/PhilosophySection.tsx +0 -2
  21. package/apps/demo/src/components/PlaygroundBlock.tsx +3 -8
  22. package/apps/demo/src/components/PlaygroundControlsDemo.tsx +63 -0
  23. package/apps/demo/src/components/PlaygroundSection.tsx +7 -91
  24. package/apps/demo/src/components/ThemeSwitcher.tsx +13 -10
  25. package/apps/demo/src/demo-layout.css +29 -0
  26. package/apps/demo/src/landing.css +138 -89
  27. package/apps/demo/src/nav.ts +3 -3
  28. package/apps/demo/src/site.ts +99 -228
  29. package/docs/MACHINES.md +6 -1
  30. package/package.json +1 -1
  31. package/packages/core/src/anatomy.ts +23 -0
  32. package/packages/panda/panda.config.ts +19 -1
  33. package/packages/panda/src/recipes/button.ts +4 -4
  34. package/packages/panda/src/recipes/combobox.ts +1 -1
  35. package/packages/panda/src/recipes/index.ts +5 -0
  36. package/packages/panda/src/recipes/pin-input.ts +29 -0
  37. package/packages/panda/src/recipes/progress.ts +44 -0
  38. package/packages/panda/src/recipes/radio-group.ts +51 -0
  39. package/packages/panda/src/recipes/select.ts +3 -1
  40. package/packages/panda/src/recipes/separator.ts +35 -0
  41. package/packages/panda/src/recipes/slider.ts +57 -0
  42. package/packages/panda/src/theme/tokens.ts +5 -0
  43. package/packages/panda/styled-system/recipes/aeon-pin-input.d.ts +28 -0
  44. package/packages/panda/styled-system/recipes/aeon-pin-input.mjs +36 -0
  45. package/packages/panda/styled-system/recipes/aeon-progress.d.ts +28 -0
  46. package/packages/panda/styled-system/recipes/aeon-progress.mjs +44 -0
  47. package/packages/panda/styled-system/recipes/aeon-radio-group.d.ts +28 -0
  48. package/packages/panda/styled-system/recipes/aeon-radio-group.mjs +48 -0
  49. package/packages/panda/styled-system/recipes/aeon-separator.d.ts +31 -0
  50. package/packages/panda/styled-system/recipes/aeon-separator.mjs +41 -0
  51. package/packages/panda/styled-system/recipes/aeon-slider.d.ts +28 -0
  52. package/packages/panda/styled-system/recipes/aeon-slider.mjs +48 -0
  53. package/packages/panda/styled-system/recipes/index.d.ts +5 -0
  54. package/packages/panda/styled-system/recipes/index.mjs +5 -0
  55. package/packages/panda/styled-system/styles.css +233 -52
  56. package/packages/panda/styled-system/tokens/index.mjs +32 -0
  57. package/packages/panda/styled-system/tokens/tokens.d.ts +2 -2
  58. package/packages/panda/styled-system/types/conditions.d.ts +1 -1
  59. package/packages/primitives/src/index.ts +1 -0
  60. package/packages/primitives/src/machines/slider.ts +93 -0
  61. package/packages/react/src/checkbox/index.tsx +14 -0
  62. package/packages/react/src/floating/FloatingPositioner.tsx +59 -0
  63. package/packages/react/src/hooks/use-anchor-position.ts +33 -5
  64. package/packages/react/src/hooks/use-prefers-hover.ts +16 -0
  65. package/packages/react/src/index.ts +5 -0
  66. package/packages/react/src/menu/index.tsx +38 -11
  67. package/packages/react/src/pin-input/index.tsx +223 -0
  68. package/packages/react/src/popover/index.tsx +38 -11
  69. package/packages/react/src/progress/index.tsx +110 -0
  70. package/packages/react/src/radio-group/index.tsx +199 -0
  71. package/packages/react/src/select/index.tsx +51 -28
  72. package/packages/react/src/select/select.test.tsx +21 -0
  73. package/packages/react/src/separator/index.tsx +23 -0
  74. package/packages/react/src/slider/index.tsx +264 -0
  75. package/packages/react/src/toast/primitives.tsx +8 -1
  76. package/packages/react/src/toast/toast.test.tsx +40 -0
  77. package/packages/react/src/tooltip/index.tsx +124 -20
  78. package/packages/react/src/tooltip/tooltip.test.tsx +114 -0
  79. package/packages/site/README.md +1 -1
  80. package/packages/ui/src/index.ts +5 -0
  81. package/packages/ui/src/pin-input.tsx +16 -0
  82. package/packages/ui/src/progress.tsx +21 -0
  83. package/packages/ui/src/radio-group.tsx +24 -0
  84. package/packages/ui/src/select.tsx +3 -4
  85. package/packages/ui/src/separator.tsx +15 -0
  86. package/packages/ui/src/slider.tsx +24 -0
  87. package/apps/demo/public/og.png +0 -0
  88. package/apps/demo/src/components/SceneSection.tsx +0 -157
@@ -1,29 +1,17 @@
1
1
  import {
2
- Accordion,
3
2
  Button,
4
- Checkbox,
5
3
  Dialog,
6
4
  Menu,
7
5
  Popover,
8
- Switch,
9
- Tabs,
10
6
  Tooltip,
11
7
  useToast,
12
8
  } from '@aeon-ui/ui'
13
- import { ComboboxDemo } from './ComboboxDemo.js'
14
- import { useState } from 'react'
15
- import {
16
- accordionExamples,
17
- playgroundBlocks,
18
- site,
19
- tabsExamples,
20
- } from '../site.js'
9
+ import { playgroundBlocks, site } from '../site.js'
21
10
  import { AsyncMachineDemo } from './AsyncMachineDemo.js'
22
11
  import { ButtonLifecycleDemo } from './ButtonLifecycleDemo.js'
23
- import { CodeExample } from './CodeExample.js'
24
12
  import { FieldStateDemo } from './FieldStateDemo.js'
25
- import { ScrollRegionDemo } from './ScrollRegionDemo.js'
26
13
  import { PlaygroundBlock } from './PlaygroundBlock.js'
14
+ import { PlaygroundControlsDemo } from './PlaygroundControlsDemo.js'
27
15
 
28
16
  function ToastDemo() {
29
17
  const { publish } = useToast()
@@ -45,7 +33,6 @@ function ToastDemo() {
45
33
  }
46
34
 
47
35
  export function PlaygroundSection() {
48
- const [notifications, setNotifications] = useState(true)
49
36
  const b = playgroundBlocks
50
37
 
51
38
  return (
@@ -70,37 +57,8 @@ export function PlaygroundSection() {
70
57
  <FieldStateDemo />
71
58
  </PlaygroundBlock>
72
59
 
73
- <PlaygroundBlock {...b.scroll}>
74
- <ScrollRegionDemo />
75
- </PlaygroundBlock>
76
-
77
- <PlaygroundBlock {...b.buttons}>
78
- <Button.Group className="playground-button-row">
79
- <Button.Root>Primary</Button.Root>
80
- <Button.Root variant="outline">Outline</Button.Root>
81
- <Button.Root variant="ghost">Ghost</Button.Root>
82
- </Button.Group>
83
- </PlaygroundBlock>
84
-
85
- <PlaygroundBlock {...b.toggle}>
86
- <div className="demo-stack">
87
- <Switch.Root checked={notifications} onCheckedChange={setNotifications}>
88
- <Switch.Control>
89
- <Switch.Thumb />
90
- </Switch.Control>
91
- <Switch.Label>Enable notifications</Switch.Label>
92
- </Switch.Root>
93
- <Checkbox.Root checked={notifications} onCheckedChange={setNotifications}>
94
- <Checkbox.Control>
95
- <Checkbox.Indicator />
96
- </Checkbox.Control>
97
- <Checkbox.Label>Email digest</Checkbox.Label>
98
- </Checkbox.Root>
99
- </div>
100
- </PlaygroundBlock>
101
-
102
- <PlaygroundBlock {...b.combobox}>
103
- <ComboboxDemo />
60
+ <PlaygroundBlock {...b.controls}>
61
+ <PlaygroundControlsDemo />
104
62
  </PlaygroundBlock>
105
63
 
106
64
  <PlaygroundBlock {...b.dialog}>
@@ -111,7 +69,7 @@ export function PlaygroundSection() {
111
69
  <Dialog.Content>
112
70
  <Dialog.Title>Example modal</Dialog.Title>
113
71
  <Dialog.Description>
114
- Press Escape or click outside — both close via the dialog machine.
72
+ Escape and backdrop clicks close via defined transitions.
115
73
  </Dialog.Description>
116
74
  <Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
117
75
  </Dialog.Content>
@@ -119,7 +77,7 @@ export function PlaygroundSection() {
119
77
  </Dialog.Root>
120
78
  </PlaygroundBlock>
121
79
 
122
- <PlaygroundBlock {...b.overlay}>
80
+ <PlaygroundBlock {...b.overlay} last>
123
81
  <div className="demo-stack demo-overlay-row">
124
82
  <Menu.Root>
125
83
  <Menu.Trigger>Menu</Menu.Trigger>
@@ -137,7 +95,7 @@ export function PlaygroundSection() {
137
95
  <Popover.Trigger>Popover</Popover.Trigger>
138
96
  <Popover.Positioner>
139
97
  <Popover.Content>
140
- <p style={{ margin: 0 }}>Anchored panel — open/closed is explicit on the machine.</p>
98
+ <p style={{ margin: 0 }}>Anchored panel with explicit open/closed states.</p>
141
99
  <Popover.CloseTrigger>Close</Popover.CloseTrigger>
142
100
  </Popover.Content>
143
101
  </Popover.Positioner>
@@ -155,48 +113,6 @@ export function PlaygroundSection() {
155
113
  <ToastDemo />
156
114
  </div>
157
115
  </PlaygroundBlock>
158
-
159
- <PlaygroundBlock {...b.tabsAccordion} last>
160
- <Tabs.Root defaultValue="philosophy" className="demo-spaced-bottom">
161
- <Tabs.List>
162
- <Tabs.Trigger value="philosophy">{tabsExamples.philosophy.label}</Tabs.Trigger>
163
- <Tabs.Trigger value="machines">{tabsExamples.machines.label}</Tabs.Trigger>
164
- <Tabs.Trigger value="anatomy">{tabsExamples.anatomy.label}</Tabs.Trigger>
165
- </Tabs.List>
166
- <Tabs.Content value="philosophy">
167
- <p>{tabsExamples.philosophy.content}</p>
168
- <CodeExample code={tabsExamples.philosophy.example} />
169
- </Tabs.Content>
170
- <Tabs.Content value="machines">
171
- <p>{tabsExamples.machines.content}</p>
172
- <CodeExample code={tabsExamples.machines.example} />
173
- </Tabs.Content>
174
- <Tabs.Content value="anatomy">
175
- <p>{tabsExamples.anatomy.content}</p>
176
- <CodeExample code={tabsExamples.anatomy.example} />
177
- </Tabs.Content>
178
- </Tabs.Root>
179
- <Accordion.Root defaultValue={['what']}>
180
- <Accordion.Item value="what">
181
- <Accordion.ItemTrigger value="what">
182
- {accordionExamples.what.trigger}
183
- </Accordion.ItemTrigger>
184
- <Accordion.ItemContent value="what">
185
- <p>{accordionExamples.what.content}</p>
186
- <CodeExample code={accordionExamples.what.example} />
187
- </Accordion.ItemContent>
188
- </Accordion.Item>
189
- <Accordion.Item value="why">
190
- <Accordion.ItemTrigger value="why">
191
- {accordionExamples.why.trigger}
192
- </Accordion.ItemTrigger>
193
- <Accordion.ItemContent value="why">
194
- <p>{accordionExamples.why.content}</p>
195
- <CodeExample code={accordionExamples.why.example} />
196
- </Accordion.ItemContent>
197
- </Accordion.Item>
198
- </Accordion.Root>
199
- </PlaygroundBlock>
200
116
  </div>
201
117
  </div>
202
118
  </section>
@@ -42,7 +42,7 @@ export function ThemeSwitcher() {
42
42
  <Button.Root
43
43
  key={m}
44
44
  type="button"
45
- size="xs"
45
+ size="sm"
46
46
  variant={mode === m ? 'solid' : 'ghost'}
47
47
  aria-pressed={mode === m}
48
48
  className="theme-switcher__mode-btn"
@@ -60,16 +60,19 @@ export function ThemeSwitcher() {
60
60
  if (isAeonThemeId(v)) setTheme(v)
61
61
  }}
62
62
  >
63
- <Select.Trigger aria-label="Theme preset">
64
- {AEON_THEME_MAP[themeId].label}
63
+ <Select.Trigger aria-label={`Theme preset: ${AEON_THEME_MAP[themeId].label}`}>
64
+ <span className="theme-switcher__trigger-prefix">Theme</span>
65
+ <span className="theme-switcher__trigger-value">{AEON_THEME_MAP[themeId].label}</span>
65
66
  </Select.Trigger>
66
- <Select.Content>
67
- {AEON_THEMES.map((t) => (
68
- <Select.Item key={t.id} value={t.id}>
69
- {t.label}
70
- </Select.Item>
71
- ))}
72
- </Select.Content>
67
+ <Select.Positioner>
68
+ <Select.Content>
69
+ {AEON_THEMES.map((t) => (
70
+ <Select.Item key={t.id} value={t.id}>
71
+ {t.label}
72
+ </Select.Item>
73
+ ))}
74
+ </Select.Content>
75
+ </Select.Positioner>
73
76
  </Select.Root>
74
77
  </div>
75
78
  )
@@ -157,6 +157,35 @@
157
157
  max-width: 24rem;
158
158
  }
159
159
 
160
+ .playground-controls {
161
+ display: flex;
162
+ flex-direction: column;
163
+ align-items: flex-start;
164
+ gap: var(--aeon-gap-lg);
165
+ }
166
+
167
+ .playground-controls__toggles {
168
+ display: flex;
169
+ flex-direction: column;
170
+ align-items: flex-start;
171
+ gap: var(--aeon-gap);
172
+ width: 100%;
173
+ max-width: 20rem;
174
+ }
175
+
176
+ .playground-controls__radio {
177
+ display: flex;
178
+ flex-direction: column;
179
+ gap: var(--aeon-gap-sm);
180
+ width: 100%;
181
+ max-width: 20rem;
182
+ }
183
+
184
+ .playground-controls__slider {
185
+ width: 100%;
186
+ max-width: 20rem;
187
+ }
188
+
160
189
  /* State track — equal columns; scales type to container (no clipped labels) */
161
190
  .state-track {
162
191
  --aeon-state-track-count: 5;
@@ -14,8 +14,6 @@
14
14
  --border-strong: color-mix(in srgb, var(--aeon-border) 70%, var(--aeon-text));
15
15
  --text-muted: var(--aeon-muted);
16
16
  --site-header-offset: var(--header-h);
17
- /* Header chrome — mode toggles, theme select, CTA share one height */
18
- --header-control-h: 2.25rem;
19
17
  }
20
18
 
21
19
  .landing {
@@ -58,11 +56,11 @@
58
56
  }
59
57
 
60
58
  .section-lead {
61
- font-size: 1.05rem;
59
+ font-size: 1rem;
62
60
  color: var(--text-muted);
63
- max-width: 40rem;
61
+ max-width: 42ch;
64
62
  margin: 0;
65
- line-height: 1.65;
63
+ line-height: 1.6;
66
64
  }
67
65
 
68
66
  .text-accent {
@@ -211,12 +209,19 @@
211
209
 
212
210
  .landing-header__cta {
213
211
  display: inline-flex;
214
- align-items: center;
215
212
  flex-shrink: 0;
216
- align-self: center;
217
213
  text-decoration: none;
218
214
  }
219
215
 
216
+ .landing-header__cta [data-aeon-scope='button'][data-aeon-part='root'] {
217
+ letter-spacing: 0.04em;
218
+ white-space: nowrap;
219
+ }
220
+
221
+ .landing-header__cta-label--short {
222
+ display: none;
223
+ }
224
+
220
225
  /* Theme switcher — segmented light/dark + preset select */
221
226
  .theme-switcher {
222
227
  display: flex;
@@ -228,10 +233,12 @@
228
233
 
229
234
  .theme-switcher__modes {
230
235
  display: inline-flex;
231
- align-items: center;
236
+ align-items: stretch;
232
237
  gap: 0.125rem;
233
238
  flex-shrink: 0;
234
- padding: 0.15rem;
239
+ box-sizing: border-box;
240
+ height: var(--spacing-control-min-h-sm);
241
+ padding: 2px;
235
242
  border: 1px solid var(--aeon-border);
236
243
  border-radius: var(--aeon-radius);
237
244
  background: color-mix(in srgb, var(--aeon-surface) 92%, var(--aeon-bg));
@@ -239,6 +246,8 @@
239
246
 
240
247
  .theme-switcher__mode-btn {
241
248
  min-width: 2.75rem;
249
+ height: auto;
250
+ align-self: stretch;
242
251
  margin: 0 !important;
243
252
  }
244
253
 
@@ -251,25 +260,56 @@
251
260
  max-width: 24vw;
252
261
  min-width: 0;
253
262
  flex-shrink: 1;
254
- height: var(--header-control-h);
255
263
  }
256
264
 
257
- .theme-switcher__theme-select [data-aeon-part='trigger'] {
258
- min-height: var(--header-control-h);
259
- height: 100%;
260
- max-width: 100%;
265
+ .theme-switcher__trigger-prefix {
266
+ display: none;
267
+ flex-shrink: 0;
268
+ font-weight: 600;
269
+ }
270
+
271
+ .theme-switcher__trigger-value {
272
+ min-width: 0;
261
273
  overflow: hidden;
262
274
  text-overflow: ellipsis;
263
275
  white-space: nowrap;
276
+ }
277
+
278
+ .theme-switcher__theme-select [data-aeon-part='trigger'] {
279
+ max-width: 100%;
280
+ overflow: hidden;
264
281
  padding-inline: 0.5rem 1.75rem;
265
282
  font-size: 0.7rem;
266
283
  }
267
284
 
285
+ @media (max-width: 719px) {
286
+ .theme-switcher__trigger-prefix {
287
+ display: inline;
288
+ }
289
+ }
290
+
291
+ @media (max-width: 640px) {
292
+ .landing-header__cta [data-aeon-scope='button'][data-aeon-part='root'] {
293
+ padding-inline: 0.55rem !important;
294
+ font-size: 0.6875rem;
295
+ }
296
+
297
+ .landing-header__cta-label--long {
298
+ display: none;
299
+ }
300
+
301
+ .landing-header__cta-label--short {
302
+ display: inline;
303
+ }
304
+ }
305
+
268
306
  @media (max-width: 420px) {
269
- :root {
270
- --header-control-h: 2rem;
307
+ .theme-switcher__trigger-value {
308
+ display: none;
271
309
  }
310
+ }
272
311
 
312
+ @media (max-width: 420px) {
273
313
  .landing-header__shell {
274
314
  gap: 0.35rem;
275
315
  }
@@ -294,29 +334,15 @@
294
334
  }
295
335
 
296
336
  .theme-switcher__theme-select {
297
- width: 4.75rem;
298
- max-width: 20vw;
337
+ width: auto;
338
+ min-width: 4.35rem;
339
+ max-width: none;
299
340
  }
300
341
 
301
342
  .theme-switcher__theme-select [data-aeon-part='trigger'] {
302
- padding-inline: 0.4rem 1.5rem;
343
+ padding-inline: 0.45rem 1.5rem;
303
344
  font-size: 0.625rem;
304
345
  }
305
-
306
- .landing-header__cta [data-aeon-scope='button'][data-aeon-part='root'] {
307
- min-height: var(--header-control-h);
308
- padding-inline: 0.45rem !important;
309
- font-size: 0.625rem;
310
- letter-spacing: 0.04em;
311
- }
312
-
313
- .landing-header__cta-label--long {
314
- display: none;
315
- }
316
-
317
- .landing-header__cta-label--short {
318
- display: inline;
319
- }
320
346
  }
321
347
 
322
348
  .sr-only {
@@ -331,26 +357,14 @@
331
357
  border: 0;
332
358
  }
333
359
 
334
- /* Header CTA — same vertical rhythm as mode toggles + select */
335
- .landing-header__cta [data-aeon-scope='button'][data-aeon-part='root'] {
336
- min-height: var(--header-control-h);
337
- letter-spacing: 0.06em;
338
- text-transform: uppercase;
339
- font-size: 0.75rem;
340
- }
341
-
342
- .landing-header__cta-label--short {
343
- display: none;
344
- }
345
-
346
360
  /* Hero */
347
361
  .hero {
348
362
  padding-top: clamp(2.5rem, 6vw, 4rem);
349
363
  padding-bottom: clamp(1.25rem, 3vw, 2rem);
350
364
  }
351
365
 
352
- /* One-line install — above hero CTAs */
353
- .hero__copy .hero-install__line {
366
+ /* Install line — above hero CTAs */
367
+ .hero__copy .hero-install {
354
368
  margin: 0 0 1rem;
355
369
  }
356
370
 
@@ -369,6 +383,14 @@
369
383
  scrollbar-width: thin;
370
384
  }
371
385
 
386
+ .hero-install__hint {
387
+ margin: 0.4rem 0 0;
388
+ font-size: 0.75rem;
389
+ line-height: 1.45;
390
+ color: var(--text-muted);
391
+ max-width: 36ch;
392
+ }
393
+
372
394
  .hero-install__label {
373
395
  flex-shrink: 0;
374
396
  font-size: 0.65rem;
@@ -378,18 +400,19 @@
378
400
  color: var(--aeon-accent);
379
401
  }
380
402
 
381
- .hero-install__access {
403
+ .hero-install__command {
382
404
  flex: 1 1 auto;
383
405
  min-width: 0;
384
406
  margin: 0;
385
407
  padding: 0;
386
- font-family: var(--font-display);
387
- font-size: clamp(0.85rem, 3.2vw, 1.05rem);
388
- font-weight: 700;
389
- letter-spacing: 0.12em;
408
+ font-family: var(--font-mono, 'IBM Plex Mono', ui-monospace, monospace);
409
+ font-size: clamp(0.78rem, 2.8vw, 0.92rem);
410
+ font-weight: 500;
411
+ letter-spacing: 0.02em;
390
412
  line-height: 1.3;
391
413
  white-space: nowrap;
392
414
  color: var(--aeon-text);
415
+ background: transparent;
393
416
  }
394
417
 
395
418
  .hero__eyebrow {
@@ -412,7 +435,7 @@
412
435
  }
413
436
 
414
437
  .hero__lead {
415
- margin: 0 0 0.35rem;
438
+ margin: 0 0 0.75rem;
416
439
  font-size: 1.0625rem;
417
440
  font-weight: 500;
418
441
  color: var(--text-muted);
@@ -421,14 +444,16 @@
421
444
  }
422
445
 
423
446
  .hero__sub {
424
- margin: 0 0 1.5rem;
425
- font-size: 0.98rem;
426
- color: color-mix(in srgb, var(--text-muted) 82%, transparent);
427
- max-width: 42ch;
447
+ margin: 0 0 1.25rem;
448
+ font-size: 0.9375rem;
449
+ line-height: 1.55;
450
+ color: var(--text-muted);
451
+ max-width: 46ch;
452
+ opacity: 0.92;
428
453
  }
429
454
 
430
455
  .hero__actions {
431
- margin-bottom: 2rem;
456
+ margin-bottom: 1.5rem;
432
457
  }
433
458
 
434
459
  .hero__actions a {
@@ -493,6 +518,39 @@
493
518
  }
494
519
  }
495
520
 
521
+ .hero__pillars {
522
+ list-style: none;
523
+ margin: 0;
524
+ padding: 0;
525
+ display: flex;
526
+ flex-direction: column;
527
+ }
528
+
529
+ .hero__pillar {
530
+ display: flex;
531
+ flex-direction: column;
532
+ gap: 0.2rem;
533
+ padding: 0.85rem 1rem;
534
+ border-bottom: 1px solid var(--border);
535
+ }
536
+
537
+ .hero__pillar:last-child {
538
+ border-bottom: none;
539
+ }
540
+
541
+ .hero__pillar strong {
542
+ font-family: var(--font-display);
543
+ font-size: 0.8125rem;
544
+ font-weight: 600;
545
+ color: var(--aeon-text);
546
+ }
547
+
548
+ .hero__pillar span {
549
+ font-size: 0.8125rem;
550
+ line-height: 1.45;
551
+ color: var(--text-muted);
552
+ }
553
+
496
554
  .hero__visual {
497
555
  margin-top: 2.5rem;
498
556
  }
@@ -665,11 +723,15 @@
665
723
  }
666
724
 
667
725
  .playground__block-sub {
668
- margin: 0 0 0.75rem;
726
+ margin: 0 0 0.85rem;
669
727
  font-size: 0.875rem;
670
728
  line-height: 1.55;
671
729
  color: var(--text-muted);
672
- max-width: 52ch;
730
+ max-width: 48ch;
731
+ }
732
+
733
+ .playground__block-demo {
734
+ margin: 0;
673
735
  }
674
736
 
675
737
  .code-example {
@@ -1013,55 +1075,42 @@
1013
1075
  .diagrams__grid {
1014
1076
  display: grid;
1015
1077
  gap: clamp(1.25rem, 3vw, 1.75rem);
1016
- }
1017
-
1018
- @media (min-width: 52rem) {
1019
- .diagrams__grid {
1020
- grid-template-columns: repeat(2, minmax(0, 1fr));
1021
- }
1022
-
1023
- .diagram-card:first-child {
1024
- grid-column: 1 / -1;
1025
- }
1078
+ max-width: 40rem;
1026
1079
  }
1027
1080
 
1028
1081
  .diagram-card__head {
1029
- padding: 1.25rem 1.25rem 0;
1082
+ padding: 1.15rem 1.15rem 0;
1030
1083
  }
1031
1084
 
1032
1085
  .diagram-card__head h3 {
1033
- margin: 0 0 0.5rem;
1086
+ margin: 0 0 0.35rem;
1034
1087
  font-family: var(--font-display);
1035
- font-size: 1.15rem;
1088
+ font-size: 1.05rem;
1036
1089
  font-weight: 600;
1037
1090
  }
1038
1091
 
1039
1092
  .diagram-card__head p {
1040
- margin: 0 0 0.65rem;
1041
- font-size: 0.9rem;
1093
+ margin: 0;
1094
+ font-size: 0.875rem;
1042
1095
  color: var(--text-muted);
1043
- line-height: 1.55;
1044
- }
1045
-
1046
- .diagram-card__ref {
1047
- display: inline-block;
1048
- font-size: 0.72rem;
1049
- padding: 0.2rem 0.5rem;
1050
- border-radius: 4px;
1051
- background: var(--bg-elevated);
1052
- border: 1px solid var(--border);
1053
- color: var(--aeon-accent);
1096
+ line-height: 1.5;
1097
+ max-width: 40ch;
1054
1098
  }
1055
1099
 
1056
1100
  .diagram-card__figure {
1057
1101
  margin: 0;
1058
- padding: 0.75rem 1rem 1.25rem;
1102
+ padding: 1rem 1.15rem 1.15rem;
1059
1103
  overflow-x: auto;
1060
1104
  }
1061
1105
 
1106
+ .diagram-card__mermaid {
1107
+ min-height: 5rem;
1108
+ }
1109
+
1062
1110
  .diagram-card__mermaid svg {
1063
1111
  display: block;
1064
- max-width: 100%;
1112
+ width: 100%;
1113
+ max-width: 36rem;
1065
1114
  height: auto;
1066
1115
  margin-inline: auto;
1067
1116
  }
@@ -1,8 +1,8 @@
1
1
  export const navLinks = [
2
- { href: '#layers', label: 'Architecture', sectionId: 'layers' },
3
- { href: '#diagrams', label: 'Diagrams', sectionId: 'diagrams' },
4
- { href: '#playground', label: 'Components', sectionId: 'playground' },
5
2
  { href: '#philosophy', label: 'Foundation', sectionId: 'philosophy' },
3
+ { href: '#playground', label: 'Components', sectionId: 'playground' },
4
+ { href: '#layers', label: 'Shape', sectionId: 'layers' },
5
+ { href: '#diagrams', label: 'Statecharts', sectionId: 'diagrams' },
6
6
  { href: '#faq', label: 'FAQ', sectionId: 'faq' },
7
7
  ] as const
8
8