@engrate/components 0.1.12 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -32187,7 +32187,7 @@ function Hm() {
32187
32187
  }
32188
32188
  const IQ = te(
32189
32189
  [
32190
- "border-border bg-card flex h-dvh flex-col border-r transition-[width] duration-300 ease-in-out",
32190
+ "border-border bg-alt flex h-dvh flex-col border-r transition-[width] duration-300 ease-in-out",
32191
32191
  "focus-visible:ring-sunflower focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
32192
32192
  ],
32193
32193
  {
@@ -32302,7 +32302,7 @@ const zQ = f.forwardRef(({ className: e, ...t }, r) => {
32302
32302
  {
32303
32303
  ref: r,
32304
32304
  className: D(
32305
- "text-label text-tertiary px-3 py-2 font-sans uppercase",
32305
+ "text-tertiary px-3 py-2 font-mono text-xs leading-5 font-normal tracking-[1.2px] uppercase",
32306
32306
  e
32307
32307
  ),
32308
32308
  ...t
@@ -32312,14 +32312,14 @@ const zQ = f.forwardRef(({ className: e, ...t }, r) => {
32312
32312
  zQ.displayName = "SidebarGroupLabel";
32313
32313
  const J0 = te(
32314
32314
  [
32315
- "text-small flex w-full items-center gap-3 rounded-md px-3 py-2 font-sans transition-colors",
32316
- "text-secondary hover:bg-alt hover:text-primary",
32315
+ "text-small relative flex w-full items-center gap-3 rounded-md px-3 py-2 font-sans font-normal",
32316
+ "text-secondary hover:bg-vanilla hover:text-primary",
32317
32317
  "focus-visible:ring-sunflower focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
32318
32318
  ],
32319
32319
  {
32320
32320
  variants: {
32321
32321
  active: {
32322
- true: "bg-alt text-primary font-medium",
32322
+ true: "text-primary",
32323
32323
  false: ""
32324
32324
  }
32325
32325
  },
@@ -32329,7 +32329,14 @@ const J0 = te(
32329
32329
  }
32330
32330
  ), FQ = f.forwardRef(
32331
32331
  ({ className: e, active: t, icon: r, asChild: n = !1, children: o, ...i }, a) => {
32332
- const { collapsed: s } = Hm(), l = n ? Ae : "button", c = /* @__PURE__ */ Z(St, { children: [
32332
+ const { collapsed: s } = Hm(), l = n ? Ae : "button", c = t ? /* @__PURE__ */ b(
32333
+ "span",
32334
+ {
32335
+ className: "bg-sunflower absolute top-1 bottom-1 left-0 w-[3px] rounded-full",
32336
+ "aria-hidden": "true"
32337
+ }
32338
+ ) : null, u = /* @__PURE__ */ Z(St, { children: [
32339
+ c,
32333
32340
  r && /* @__PURE__ */ b("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center", children: r }),
32334
32341
  !s && /* @__PURE__ */ b("span", { className: "truncate", children: o })
32335
32342
  ] });
@@ -32347,6 +32354,7 @@ const J0 = te(
32347
32354
  o,
32348
32355
  {
32349
32356
  children: /* @__PURE__ */ Z(St, { children: [
32357
+ c,
32350
32358
  r && /* @__PURE__ */ b("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center", children: r }),
32351
32359
  !s && /* @__PURE__ */ b("span", { className: "truncate", children: o.props.children })
32352
32360
  ] })
@@ -32363,7 +32371,7 @@ const J0 = te(
32363
32371
  e
32364
32372
  ),
32365
32373
  ...i,
32366
- children: c
32374
+ children: u
32367
32375
  }
32368
32376
  );
32369
32377
  }
@@ -32378,8 +32386,8 @@ const BQ = f.forwardRef(
32378
32386
  ref: r,
32379
32387
  type: "button",
32380
32388
  className: D(
32381
- "text-small flex w-full items-center rounded-md p-2 font-sans transition-colors",
32382
- "text-secondary hover:bg-alt hover:text-primary",
32389
+ "text-small flex w-full items-center rounded-md p-2 font-sans font-normal",
32390
+ "text-secondary hover:bg-vanilla hover:text-primary",
32383
32391
  "focus-visible:ring-sunflower focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none",
32384
32392
  e
32385
32393
  ),
@@ -32397,7 +32405,7 @@ const VQ = f.forwardRef(
32397
32405
  "hr",
32398
32406
  {
32399
32407
  ref: r,
32400
- className: D("border-border my-2 border-t", e),
32408
+ className: D("border-border my-3 border-t", e),
32401
32409
  ...t
32402
32410
  }
32403
32411
  )
@@ -0,0 +1,625 @@
1
+ ---
2
+ name: engrate-components
3
+ description: Use and integrate Engrate's React component library in applications. This skill covers importing components, using design tokens, and building UIs with the library. Use when building user interfaces that consume @engrate/components, styling applications with Engrate's design system, or integrating the component library into React projects.
4
+ ---
5
+
6
+ # Engrate Components Library
7
+
8
+ ## Overview
9
+
10
+ `@engrate/components` is a React component library implementing Engrate's design system. Built with TypeScript, Tailwind CSS v4, and accessible by default.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @engrate/components
16
+ ```
17
+
18
+ Peer dependencies (React 18 or 19):
19
+
20
+ ```bash
21
+ npm install react react-dom
22
+ ```
23
+
24
+ ## Basic Setup
25
+
26
+ ### Importing Styles
27
+
28
+ Always import the component styles in your application:
29
+
30
+ ```tsx
31
+ import '@engrate/components/styles.css'
32
+ ```
33
+
34
+ ### With Tailwind CSS v4
35
+
36
+ If your project uses Tailwind CSS v4, import in your CSS file to get access to all design tokens:
37
+
38
+ ```css
39
+ @import 'tailwindcss';
40
+ @import '@engrate/components/styles.css';
41
+ ```
42
+
43
+ ## Available Components
44
+
45
+ ### Layout Components
46
+
47
+ | Component | Purpose |
48
+ | ------------- | ---------------------------------------- |
49
+ | `Stack` | Vertical/horizontal flex layout with gap |
50
+ | `Grid` | CSS Grid layout wrapper |
51
+ | `Card` | Container with border and background |
52
+ | `Divider` | Visual separator line |
53
+ | `EngrateLogo` | Brand logo with compact mode (icon only) |
54
+
55
+ ### Typography Components
56
+
57
+ | Component | Purpose |
58
+ | --------- | ------------------------------- |
59
+ | `Heading` | h1-h6 headings with brand fonts |
60
+ | `Text` | Body text with size variants |
61
+ | `Eyebrow` | Small uppercase label text |
62
+ | `Link` | Styled anchor element |
63
+
64
+ ### Form Components
65
+
66
+ | Component | Purpose |
67
+ | ---------------- | --------------------------- |
68
+ | `Button` | Primary action element |
69
+ | `Input` | Text input field |
70
+ | `Textarea` | Multi-line text input |
71
+ | `Checkbox` | Boolean input |
72
+ | `Radio` | Single selection from group |
73
+ | `Slider` | Value selection via drag |
74
+ | `Switch` | Toggle on/off |
75
+ | `Select` | Dropdown selection |
76
+ | `DatePicker` | Date selection |
77
+ | `DateTimePicker` | Date and time selection |
78
+ | `Label` | Form field label |
79
+ | `FormField` | Field wrapper with label |
80
+ | `FormMessage` | Validation message display |
81
+
82
+ ### Feedback Components
83
+
84
+ | Component | Purpose |
85
+ | ------------------- | ------------------------- |
86
+ | `Toast` | Temporary notification |
87
+ | `Banner` | Persistent message banner |
88
+ | `Badge` | Status indicator |
89
+ | `Spinner` | Loading indicator |
90
+ | `Skeleton` | Content placeholder |
91
+ | `ProgressIndicator` | Progress visualization |
92
+
93
+ ### Navigation Components
94
+
95
+ | Component | Purpose |
96
+ | ------------- | ----------------------------------- |
97
+ | `Breadcrumbs` | Navigation path |
98
+ | `TabList` | Tab navigation |
99
+ | `Pagination` | Page navigation |
100
+ | `Sidebar` | Collapsible application sidebar nav |
101
+ | `Header` | Page header with logo and nav |
102
+ | `Footer` | Page footer with links and info |
103
+
104
+ ### Overlay Components
105
+
106
+ | Component | Purpose |
107
+ | -------------- | ------------------- |
108
+ | `Modal` | Dialog overlay |
109
+ | `AlertDialog` | Confirmation dialog |
110
+ | `Tooltip` | Hover information |
111
+ | `DropdownMenu` | Action menu |
112
+ | `ContextMenu` | Right-click menu |
113
+
114
+ ### Data Display Components
115
+
116
+ | Component | Purpose |
117
+ | ----------- | -------------------- |
118
+ | `Table` | Tabular data |
119
+ | `Accordion` | Collapsible sections |
120
+ | `BarChart` | Bar chart |
121
+ | `LineChart` | Line chart |
122
+ | `PieChart` | Pie chart |
123
+
124
+ ## Component Usage Patterns
125
+
126
+ ### Basic Import and Use
127
+
128
+ ```tsx
129
+ import { Button, Card, Heading, Text, Stack } from '@engrate/components'
130
+
131
+ function MyComponent() {
132
+ return (
133
+ <Card>
134
+ <Stack gap="md">
135
+ <Heading level="h2">Welcome</Heading>
136
+ <Text>This is a card with stacked content.</Text>
137
+ <Button variant="primary">Get Started</Button>
138
+ </Stack>
139
+ </Card>
140
+ )
141
+ }
142
+ ```
143
+
144
+ ### Button Variants
145
+
146
+ ```tsx
147
+ import { Button } from '@engrate/components'
148
+
149
+ // Primary (Sunflower yellow background)
150
+ <Button variant="primary">Primary Action</Button>
151
+
152
+ // Secondary (bordered, transparent)
153
+ <Button variant="secondary">Secondary</Button>
154
+
155
+ // Ghost (no background)
156
+ <Button variant="ghost">Ghost</Button>
157
+
158
+ // Sizes: sm, default, lg, icon
159
+ <Button size="lg">Large Button</Button>
160
+
161
+ // As child (for Next.js Link, etc.)
162
+ <Button asChild>
163
+ <a href="/page">Link Button</a>
164
+ </Button>
165
+ ```
166
+
167
+ ### Form Layout
168
+
169
+ ```tsx
170
+ import { FormField, Input, Button, Stack } from '@engrate/components'
171
+
172
+ function LoginForm() {
173
+ return (
174
+ <form>
175
+ <Stack gap="lg">
176
+ <FormField label="Email" htmlFor="email">
177
+ <Input id="email" type="email" placeholder="you@example.com" />
178
+ </FormField>
179
+ <FormField label="Password" htmlFor="password">
180
+ <Input id="password" type="password" />
181
+ </FormField>
182
+ <Button type="submit" variant="primary">
183
+ Sign In
184
+ </Button>
185
+ </Stack>
186
+ </form>
187
+ )
188
+ }
189
+ ```
190
+
191
+ ### Typography Hierarchy
192
+
193
+ ```tsx
194
+ import { Heading, Text, Eyebrow, Stack } from '@engrate/components'
195
+ ;<Stack gap="md">
196
+ <Eyebrow>Category</Eyebrow>
197
+ <Heading level="hero">Hero Title</Heading>
198
+ <Heading level="h1">Page Title</Heading>
199
+ <Text variant="lead">Lead paragraph with larger text.</Text>
200
+ <Text variant="semi-lead">Semi lead paragraph.</Text>
201
+ <Text variant="body">Regular body text for content.</Text>
202
+ <Text variant="descriptive">Descriptive smaller text.</Text>
203
+ </Stack>
204
+ ```
205
+
206
+ ### Layout with Grid
207
+
208
+ ```tsx
209
+ import { Grid, Card } from '@engrate/components'
210
+ ;<Grid cols={3} gap="lg">
211
+ <Card>Column 1</Card>
212
+ <Card>Column 2</Card>
213
+ <Card>Column 3</Card>
214
+ </Grid>
215
+ ```
216
+
217
+ ### Modal Dialog
218
+
219
+ ```tsx
220
+ import {
221
+ Modal,
222
+ ModalTrigger,
223
+ ModalContent,
224
+ ModalHeader,
225
+ ModalTitle,
226
+ ModalDescription,
227
+ ModalFooter,
228
+ ModalClose,
229
+ Button,
230
+ Stack,
231
+ Text,
232
+ } from '@engrate/components'
233
+
234
+ function Example() {
235
+ return (
236
+ <Modal>
237
+ <ModalTrigger asChild>
238
+ <Button>Open Modal</Button>
239
+ </ModalTrigger>
240
+ <ModalContent>
241
+ <ModalHeader>
242
+ <ModalTitle>Confirm Action</ModalTitle>
243
+ <ModalDescription>This action cannot be undone.</ModalDescription>
244
+ </ModalHeader>
245
+ <Text>Are you sure you want to proceed?</Text>
246
+ <ModalFooter>
247
+ <ModalClose asChild>
248
+ <Button variant="secondary">Cancel</Button>
249
+ </ModalClose>
250
+ <Button variant="primary">Confirm</Button>
251
+ </ModalFooter>
252
+ </ModalContent>
253
+ </Modal>
254
+ )
255
+ }
256
+ ```
257
+
258
+ ### Sidebar Navigation
259
+
260
+ ```tsx
261
+ import {
262
+ Sidebar,
263
+ SidebarContent,
264
+ SidebarFooter,
265
+ SidebarGroup,
266
+ SidebarGroupLabel,
267
+ SidebarHeader,
268
+ SidebarItem,
269
+ SidebarSeparator,
270
+ SidebarTrigger,
271
+ EngrateLogo,
272
+ } from '@engrate/components'
273
+ import { Home, Settings, BarChart3, LogOut } from 'lucide-react'
274
+
275
+ function AppLayout() {
276
+ return (
277
+ <div style={{ display: 'flex', height: '100vh' }}>
278
+ <Sidebar aria-label="Main navigation">
279
+ <SidebarHeader>
280
+ <EngrateLogo size="sm" compact />
281
+ </SidebarHeader>
282
+ <SidebarContent>
283
+ <SidebarGroup>
284
+ <SidebarGroupLabel>Main</SidebarGroupLabel>
285
+ <SidebarItem icon={<Home className="h-4 w-4" />} active>
286
+ Dashboard
287
+ </SidebarItem>
288
+ <SidebarItem icon={<BarChart3 className="h-4 w-4" />}>
289
+ Analytics
290
+ </SidebarItem>
291
+ </SidebarGroup>
292
+ <SidebarSeparator />
293
+ <SidebarGroup>
294
+ <SidebarGroupLabel>Settings</SidebarGroupLabel>
295
+ <SidebarItem icon={<Settings className="h-4 w-4" />}>
296
+ Preferences
297
+ </SidebarItem>
298
+ </SidebarGroup>
299
+ </SidebarContent>
300
+ <SidebarFooter>
301
+ <SidebarItem icon={<LogOut className="h-4 w-4" />}>
302
+ Logout
303
+ </SidebarItem>
304
+ </SidebarFooter>
305
+ </Sidebar>
306
+ <main className="flex-1 p-6">{/* Main content */}</main>
307
+ </div>
308
+ )
309
+ }
310
+ ```
311
+
312
+ ### Header and Footer
313
+
314
+ ```tsx
315
+ import {
316
+ Header,
317
+ HeaderLogo,
318
+ HeaderNav,
319
+ HeaderActions,
320
+ Footer,
321
+ FooterContent,
322
+ FooterSection,
323
+ FooterHeading,
324
+ FooterLinks,
325
+ FooterBottom,
326
+ FooterCopyright,
327
+ EngrateLogo,
328
+ Button,
329
+ Link,
330
+ } from '@engrate/components'
331
+
332
+ function PageLayout() {
333
+ return (
334
+ <>
335
+ <Header sticky>
336
+ <HeaderLogo>
337
+ <EngrateLogo />
338
+ </HeaderLogo>
339
+ <HeaderNav>
340
+ <Link variant="nav" href="/about">
341
+ About
342
+ </Link>
343
+ <Link variant="nav" href="/services">
344
+ Services
345
+ </Link>
346
+ </HeaderNav>
347
+ <HeaderActions>
348
+ <Button variant="primary">Sign In</Button>
349
+ </HeaderActions>
350
+ </Header>
351
+
352
+ <main>{/* Page content */}</main>
353
+
354
+ <Footer>
355
+ <FooterContent>
356
+ <FooterSection>
357
+ <FooterHeading>Company</FooterHeading>
358
+ <FooterLinks>
359
+ <Link href="/about">About</Link>
360
+ <Link href="/careers">Careers</Link>
361
+ </FooterLinks>
362
+ </FooterSection>
363
+ </FooterContent>
364
+ <FooterBottom>
365
+ <FooterCopyright>© 2026 Engrate</FooterCopyright>
366
+ </FooterBottom>
367
+ </Footer>
368
+ </>
369
+ )
370
+ }
371
+ ```
372
+
373
+ ## Design Tokens
374
+
375
+ The library exposes CSS custom properties for use in custom components.
376
+
377
+ ### Colors
378
+
379
+ | Token | Usage |
380
+ | ------------------------------- | ------------------------ |
381
+ | `--color-sunflower` | Primary brand color |
382
+ | `--color-sunflower-hover` | Sunflower hover state |
383
+ | `--color-primary` | Primary text color |
384
+ | `--color-secondary` | Secondary text color |
385
+ | `--color-tertiary` | Tertiary text color |
386
+ | `--color-main` (background) | Main page background |
387
+ | `--color-alt` (background) | Alternative background |
388
+ | `--color-card` (background) | Card background |
389
+ | `--color-contrast` (background) | High contrast background |
390
+ | `--color-border` | Border color |
391
+ | `--color-error` | Error state color |
392
+
393
+ ### Typography
394
+
395
+ | Token | Usage |
396
+ | ---------------- | ---------------------------- |
397
+ | `--font-display` | Libre Baskerville (headings) |
398
+ | `--font-sans` | Work Sans (body text) |
399
+ | `--font-mono` | IBM Plex Mono (code) |
400
+
401
+ ### Using Tokens in Custom Components
402
+
403
+ ```tsx
404
+ // With Tailwind CSS v4 (tokens are auto-detected)
405
+ function CustomCard({ children }) {
406
+ return (
407
+ <div className="bg-card border-border text-primary rounded-lg border p-4">
408
+ {children}
409
+ </div>
410
+ )
411
+ }
412
+
413
+ // Using CSS custom properties directly
414
+ function CustomBanner() {
415
+ return (
416
+ <div
417
+ style={{
418
+ backgroundColor: 'var(--color-sunflower)',
419
+ color: 'var(--color-primary)',
420
+ }}
421
+ >
422
+ Custom styled banner
423
+ </div>
424
+ )
425
+ }
426
+ ```
427
+
428
+ ## Common Patterns
429
+
430
+ ### Responsive Layouts
431
+
432
+ ```tsx
433
+ <Grid cols={{ base: 1, md: 2, lg: 3 }} gap="lg">
434
+ {items.map((item) => (
435
+ <Card key={item.id}>{item.content}</Card>
436
+ ))}
437
+ </Grid>
438
+ ```
439
+
440
+ ### Loading States
441
+
442
+ ```tsx
443
+ import { Skeleton, Spinner, Stack } from '@engrate/components'
444
+
445
+ // Skeleton for content placeholders
446
+ <Stack gap="sm">
447
+ <Skeleton width="60%" height="1.5rem" />
448
+ <Skeleton width="100%" height="1rem" />
449
+ <Skeleton width="80%" height="1rem" />
450
+ </Stack>
451
+
452
+ // Spinner for loading indicators
453
+ <Spinner size="lg" />
454
+ ```
455
+
456
+ ### Toast Notifications
457
+
458
+ ```tsx
459
+ import {
460
+ Toast,
461
+ ToastProvider,
462
+ ToastViewport,
463
+ ToastTitle,
464
+ ToastDescription,
465
+ ToastClose,
466
+ Button,
467
+ } from '@engrate/components'
468
+ import { useState } from 'react'
469
+
470
+ function Example() {
471
+ const [open, setOpen] = useState(false)
472
+
473
+ return (
474
+ <ToastProvider>
475
+ <Button
476
+ onClick={() => {
477
+ setOpen(true)
478
+ setTimeout(() => setOpen(false), 3000)
479
+ }}
480
+ >
481
+ Save
482
+ </Button>
483
+ <Toast open={open} onOpenChange={setOpen} variant="success">
484
+ <div className="grid gap-1">
485
+ <ToastTitle>Success</ToastTitle>
486
+ <ToastDescription>Your changes have been saved.</ToastDescription>
487
+ </div>
488
+ <ToastClose />
489
+ </Toast>
490
+ <ToastViewport />
491
+ </ToastProvider>
492
+ )
493
+ }
494
+ ```
495
+
496
+ ## Accessibility
497
+
498
+ All components are built with accessibility in mind:
499
+
500
+ - Proper ARIA attributes
501
+ - Keyboard navigation support
502
+ - Focus management
503
+ - Screen reader friendly
504
+
505
+ ## TypeScript Support
506
+
507
+ All components export their prop types:
508
+
509
+ ```tsx
510
+ import { Button, type ButtonProps } from '@engrate/components'
511
+
512
+ // Use types for custom wrappers
513
+ interface MyButtonProps extends ButtonProps {
514
+ loading?: boolean
515
+ }
516
+ ```
517
+
518
+ ## Layout Guidelines
519
+
520
+ Follow these layout principles when building UIs with Engrate components:
521
+
522
+ ### Text Alignment & Width
523
+
524
+ - **Always left-align text** — creates clarity and readability
525
+ - **Body text max 65 characters wide** — use `max-width: 65ch` or equivalent
526
+ - Heading should be **at least twice as large** as body text
527
+
528
+ ### Spacing & Grid
529
+
530
+ - **Grid spacing should be 50% tighter than typical defaults** — creates cohesive layouts
531
+ - **Even margins** — equal margins to top and left side creates natural squares
532
+ - **Card headline-to-body gap** — use 100% of body text line height for breathing room
533
+
534
+ ### Content Width
535
+
536
+ - Tables, charts, and text blocks should be ~60-70% of container width (not full width)
537
+ - Keep content blocks relatively **square in proportion** — avoid ultra-wide, thin layouts
538
+ - Exception: photographs may span full width as backgrounds or hero images
539
+
540
+ ### Backgrounds
541
+
542
+ - **Never use pure white (#FFFFFF)** for backgrounds
543
+ - Use light gray backgrounds: `bg-main` (#FAFAFA), `bg-alt` (#F5F5F5), `bg-card` (#F9F9F9)
544
+ - Light yellow backgrounds (Vanilla, Eggshell) can highlight sections
545
+
546
+ ## Spacing
547
+
548
+ The component library uses a consistent spacing scale based on Tailwind's default values.
549
+
550
+ ### Gap Values
551
+
552
+ Use `Stack` and `Grid` components with the `gap` prop:
553
+
554
+ | Gap | Value | Tailwind | Use Case |
555
+ | ----- | ------- | -------- | ---------------------------------- |
556
+ | `xs` | 0.25rem | `gap-1` | Tight spacing (icon + label) |
557
+ | `sm` | 0.5rem | `gap-2` | Compact layouts |
558
+ | `md` | 1rem | `gap-4` | Default spacing (cards, form rows) |
559
+ | `lg` | 1.5rem | `gap-6` | Section spacing |
560
+ | `xl` | 2rem | `gap-8` | Major sections |
561
+ | `2xl` | 3rem | `gap-12` | Page sections |
562
+
563
+ ### Spacing Guidelines
564
+
565
+ ```tsx
566
+ // Form fields — use md gap
567
+ <Stack gap="md">
568
+ <FormField label="Name"><Input /></FormField>
569
+ <FormField label="Email"><Input /></FormField>
570
+ </Stack>
571
+
572
+ // Button groups — use sm gap
573
+ <Stack direction="horizontal" gap="sm">
574
+ <Button variant="secondary">Cancel</Button>
575
+ <Button variant="primary">Save</Button>
576
+ </Stack>
577
+
578
+ // Page sections — use xl or 2xl gap
579
+ <Stack gap="xl">
580
+ <section>Hero content</section>
581
+ <section>Features</section>
582
+ </Stack>
583
+ ```
584
+
585
+ ### Brand Spacing Rules
586
+
587
+ - **Grid spacing 50% tighter than defaults** — prefer `sm` over `md`, `md` over `lg`
588
+ - **Card headline-to-body gap** — use 100% of body text line height
589
+ - **Even margins** — equal top and left margins create natural squares
590
+
591
+ ## Design Rules
592
+
593
+ Critical rules to maintain brand consistency:
594
+
595
+ ### Color Usage
596
+
597
+ | Rule | Description |
598
+ | ------------------------ | ------------------------------------------------------------------------------ |
599
+ | **10/90 Rule** | 10% color, 90% grayscale — colors look best when used sparingly |
600
+ | **No colored text** | All text must be grayscale only — never use Sunflower or other colors for text |
601
+ | **Sunflower is primary** | When only one color can be used, use Sunflower (#FFBE26) |
602
+
603
+ ### Typography
604
+
605
+ | Rule | Description |
606
+ | ----------------------- | ------------------------------------------------------------- |
607
+ | **-5% letter spacing** | All text above 10pt uses -5% tracking (built into components) |
608
+ | **Libre Baskerville** | Only for hero headings ≥60pt |
609
+ | **Work Sans Regular** | Everything else — no Bold, Medium, or Light weights allowed |
610
+ | **Grayscale text only** | Prioritize black (#1A1A1A), use gray only for hierarchy |
611
+
612
+ ### Design Checklist
613
+
614
+ Before shipping, verify:
615
+
616
+ - [ ] Following 10/90 color vs grayscale ratio
617
+ - [ ] All text is grayscale (no colored text)
618
+ - [ ] Text is left-aligned
619
+ - [ ] Body text max 65 characters wide
620
+ - [ ] Using light gray backgrounds, not pure white
621
+
622
+ ## Related Resources
623
+
624
+ - **Storybook Documentation**: Interactive component examples at https://engrate.github.io/eg-components
625
+ - **Design Guidelines**: See `.github/skills/engrate-designer/SKILL.md` for brand and design tokens