@sudajs/cli 0.18.10 → 0.19.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudajs/cli",
3
- "version": "0.18.10",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "suda": "./bin/suda.js"
@@ -24,7 +24,6 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@modelcontextprotocol/sdk": "^1.29.0",
28
27
  "@puckeditor/core": "^0.22.4",
29
28
  "commander": "^12.1.0",
30
29
  "esbuild": "^0.25.12",
@@ -34,7 +33,7 @@
34
33
  "react": "^19.2.7",
35
34
  "react-dom": "^19.2.7",
36
35
  "zod": "^3.24.1",
37
- "@sudajs/theme-engine": "6.5.0"
36
+ "@sudajs/theme-engine": "6.6.0"
38
37
  },
39
38
  "devDependencies": {
40
39
  "@tailwindcss/postcss": "^4.3.0",
@@ -80,6 +80,11 @@ Extract shared code only when multiple sections genuinely reuse it.
80
80
  names and filler suffixes such as `Section`, `Component`, `New`, or `Custom`.
81
81
  - Prefer semantic variant names. Use numbered variants only when the variants
82
82
  truly share a purpose and no concise name describes the difference.
83
+ - Every page section must declare `section.motion`. Use `"reveal"` for ordinary
84
+ sections that use the shared viewport entrance animation. Use `"custom"` when
85
+ the section owns its own client animation (timeline, carousel, marquee, or
86
+ scroll-scrub), and use `"none"` when it must remain static. TypeScript will
87
+ report an error when the motion declaration is missing.
83
88
  - Keep `fields`, TypeScript props, `defaultProps`, and `render` aligned. Every
84
89
  normal field needs a sensible serializable default.
85
90
  - Use the most specific field: `url`, `image`, `video`, `media`, `icon`,
@@ -100,7 +105,8 @@ Default ownership is strict:
100
105
  <div>{val || "defaultValue"}</div>;
101
106
 
102
107
  // Correct: defaultProps owns the default.
103
- export const Example: SudaComponentConfig<ExampleProps> = {
108
+ export const Example: SudaSectionConfig<ExampleProps> = {
109
+ section: { category: "features", variant: "example", motion: "reveal" },
104
110
  fields: { val: { type: "text", label: t("sections.example.fields.val") } },
105
111
  defaultProps: { val: "defaultValue" },
106
112
  render: ({ val }) => <div>{val}</div>,
@@ -155,9 +161,71 @@ it must not substitute placeholder copy, labels, links, icons, or menu items.
155
161
 
156
162
  - Define one editable design system in `sourceManifest.designSystem`, expose it
157
163
  at the layout root, resolve it once there, and render components through the
158
- resulting `--suda-*` CSS variables.
159
- - Tailwind token mappings use `@theme inline`. Hand-written CSS consumes
160
- `--suda-*` variables directly, not `--color-*` or `--radius-*` aliases.
164
+ resulting unprefixed CSS variables. Do not add or consume `--suda-*` aliases.
165
+ - Set `tokens.layout.contentWidth` in every preset in `src/manifest.ts`. Choose only
166
+ `"1024px"`, `"1200px"`, `"1280px"`, or `"1440px"`:
167
+
168
+ ```ts
169
+ tokens: {
170
+ colors: { /* ... */ },
171
+ radius: { /* ... */ },
172
+ layout: { contentWidth: "1280px" },
173
+ }
174
+ ```
175
+
176
+ - In the layout root, resolve the selected preset and apply its CSS variables
177
+ to the element that wraps `children`. Use this exact pattern:
178
+
179
+ ```tsx
180
+ render: ({ children, designSystem }) => {
181
+ const tokens = resolveThemeDesignTokens(sourceManifest.designSystem, designSystem);
182
+ return (
183
+ <div
184
+ className="my-theme-root"
185
+ style={createThemeDesignCssVariables(tokens)}
186
+ >
187
+ {children}
188
+ </div>
189
+ );
190
+ },
191
+ ```
192
+
193
+ - Do not set `max-width` on the layout root or `PageOutlet`; doing so prevents
194
+ full-width sections. Apply `--content-max-width` only to inner content
195
+ containers. Wrap Header and Footer contents in that same container when they
196
+ must align with page sections.
197
+
198
+ - Every page section root must include `w-full`. Put the section background,
199
+ border, and full-bleed media on this root. Do not set `max-width` on it.
200
+ - Put normal section content inside one shared container class and define that
201
+ class once in `src/styles.css`:
202
+
203
+ ```css
204
+ .my-theme-container {
205
+ width: min(var(--content-max-width), 100%);
206
+ margin-inline: auto;
207
+ }
208
+ ```
209
+
210
+ - Use the same container inside full-width Hero and band sections when their
211
+ text, buttons, cards, or navigation must align with ordinary sections. Omit
212
+ the inner container only when the section content itself must be edge to
213
+ edge. Do not repeat `1024px`, `1200px`, `1280px`, or `1440px` in section CSS.
214
+ - `--background` / `--foreground`: default page surface and readable default
215
+ content. `--primary` / `--primary-foreground`: main brand and action surface
216
+ plus readable content on it. `--secondary` / `--secondary-foreground`:
217
+ supporting surface plus its content; it is not assumed light or dark.
218
+ - `--accent` / `--accent-foreground`: high-attention emphasis, selection, or
219
+ decorative surface plus its content, not a default CTA substitute.
220
+ `--muted` / `--muted-foreground`: subdued surface and secondary text/icons.
221
+ Always pair a chosen surface with its corresponding foreground token.
222
+ - `--radius` is the generic fallback; use `--radius-card`,
223
+ `--radius-button`, and `--radius-input` for cards, command buttons, and form
224
+ controls. Tailwind token mappings use `@theme inline`; hand-written CSS may
225
+ consume these variables directly.
226
+ - The theme decides which semantic surface each of its components uses. Do not
227
+ alter built-in section styling to accommodate a single theme palette, and do
228
+ not hardcode replacement colors in individual sections.
161
229
  - Keep typography, spacing, containers, buttons, cards, forms, and media frames
162
230
  consistent across ordinary sections, CMS sections, and starter pages.
163
231
  - Theme-local assets live under top-level `assets/`. Required preview images are
@@ -177,12 +245,14 @@ Before editing:
177
245
  When adding or changing a section:
178
246
 
179
247
  1. Define serializable props in its dedicated `.tsx` file.
180
- 2. Add `label`, useful `ai.instructions`, typed `fields`, optional
248
+ 2. Add `section` metadata with `category`, semantic `variant`, and an explicit
249
+ `motion` mode (`reveal`, `custom`, or `none`).
250
+ 3. Add `label`, useful `ai.instructions`, typed `fields`, optional
181
251
  `blockSlots`, `defaultProps`, and `render`.
182
- 3. Add all editor label keys to `src/locales/en.json`.
183
- 4. Register it in `pageConfig` and the appropriate translated category.
184
- 5. Add realistic usage to starter pages or CMS templates where appropriate.
185
- 6. Verify public rendering plus editor desktop, tablet, and mobile behavior.
252
+ 4. Add all editor label keys to `src/locales/en.json`.
253
+ 5. Register it in `pageConfig` and the appropriate translated category.
254
+ 6. Add realistic usage to starter pages or CMS templates where appropriate.
255
+ 7. Verify public rendering plus editor desktop, tablet, and mobile behavior.
186
256
 
187
257
  Before handoff:
188
258
 
@@ -192,7 +262,17 @@ pnpm typecheck
192
262
  pnpm build
193
263
  pnpm validate
194
264
  suda theme check
265
+ suda theme visual-check
195
266
  ```
196
267
 
197
- Run `suda theme capture` when visuals change. Do not use removed skip flags or
198
- bypass build, validation, AI metadata, locale, or screenshot checks.
268
+ Run `suda theme visual-check` after developing or substantially changing a
269
+ theme. It renders every page component declared by the theme's
270
+ `pageConfig.components` with each declared design preset at desktop, tablet,
271
+ and mobile sizes, writes screenshots and `report.json` to
272
+ `.suda-build/visual-check/`, and fails on token contrast, semantic surface,
273
+ or page-overflow errors. Fixed-header overlap is reported as a layout warning;
274
+ solve it in the theme layout. Platform built-in sections are covered by
275
+ theme-engine tests, not repeated for every theme. Run `suda theme capture` when
276
+ publish-preview visuals change.
277
+ Do not use removed skip flags or bypass build, validation, AI metadata, locale,
278
+ visual, or screenshot checks.
@@ -34,6 +34,20 @@ pnpm build
34
34
 
35
35
  By default capture writes `assets/preview/desktop.png`, `assets/preview/tablet.png`, and `assets/preview/mobile.png`.
36
36
 
37
+ Run a reusable visual audit after creating or substantially changing the theme:
38
+
39
+ ```bash
40
+ suda theme visual-check
41
+ ```
42
+
43
+ It renders every page component declared by the theme's `pageConfig.components`
44
+ with every design preset at desktop, tablet, and mobile sizes. Screenshots and
45
+ `report.json` are written to `.suda-build/visual-check/`; the command fails on
46
+ token contrast, semantic surface-color, or page-overflow errors. Platform
47
+ built-in sections are covered by theme-engine tests rather than being repeated
48
+ for every theme. Use `--preset <id>`, `--device <device>`, or `--full-page` to
49
+ narrow a review.
50
+
37
51
  Fields can use `visibleIf: ({ props }, { fields }) => boolean` for synchronous dynamic visibility. The starter hero shows this by hiding the Logo picker when `showLogo` is false. Suda converts `visibleIf` to Puck `resolveFields` during normalization, and the generated AI/MCP section schema marks those fields as dynamically visible.
38
52
 
39
53
  When adding fields, prefer purpose-built Suda field types over generic text inputs: use `url` for links, `image` / `video` / `media` for media, `color` for colors, `icon` for icon names, `range` for bounded numbers, `spacing` for spacing tokens, `menu` for navigation, `select` / `radio` for fixed choices, and `array` / `object` for structured values. Multi-column sections such as card grids should expose a `columns` prop.
@@ -21,10 +21,18 @@ icons, AI metadata, or block slots. The root `AGENTS.md` rules still apply.
21
21
 
22
22
  ## Field source of truth
23
23
 
24
- Type props first. Use `SudaComponentConfig<Props>`, `SudaFields<Props>`, and
24
+ Type props first. Use `SudaSectionConfig<Props>`, `SudaFields<Props>`, and
25
25
  `defineSudaPageData(pageConfig, data)` to catch shape mismatches. Do not invent a
26
26
  parallel Zod schema for theme fields.
27
27
 
28
+ Every page section must include `section` metadata. Its `motion` value is
29
+ required: ordinary sections use `"reveal"`, sections with their own client-side
30
+ animation use `"custom"`, and intentionally static sections use `"none"`.
31
+ The rendered section root must also carry the matching
32
+ `data-section-motion="reveal"`, `"custom"`, or `"none"` attribute. Do not rely
33
+ on a class-name convention; TypeScript checks the metadata contract and the
34
+ runtime uses the data attribute to avoid hiding content before hydration.
35
+
28
36
  Keep these four structures aligned:
29
37
 
30
38
  1. TypeScript props.
@@ -219,7 +227,8 @@ pricing cards, feature rows, stats, timeline items, or contact methods.
219
227
  ```tsx
220
228
  type HeroProps = { title?: string; actions?: Slot };
221
229
 
222
- export const Hero: SudaComponentConfig<HeroProps> = {
230
+ export const Hero: SudaSectionConfig<HeroProps> = {
231
+ section: { category: "hero", variant: "centered", motion: "reveal" },
223
232
  label: t("sections.hero.label"),
224
233
  ai: { instructions: "Primary landing-page introduction. Use once near the top." },
225
234
  fields: {
@@ -64,17 +64,30 @@ scales, radii, shadows, or spacing.
64
64
 
65
65
  For Tailwind, map Suda tokens through `@theme inline` and consume semantic
66
66
  utilities such as `bg-primary`, `text-primary-foreground`, and `rounded-card`.
67
- The `inline` keyword is required because Suda injects `--suda-*` variables on
67
+ The `inline` keyword is required because Suda injects unprefixed variables on
68
68
  the rendered theme root.
69
69
 
70
- Hand-written CSS consumes `--suda-*` directly. Do not use Suda-backed aliases
71
- such as `var(--color-primary)`, `var(--color-background)`, or
72
- `var(--radius-card)` in hand-written rules. For derived values, declare a
73
- theme-prefixed variable on the root:
70
+ Use the token meanings below rather than guessing from a theme's current
71
+ palette. Foreground tokens always pair with the surface token actually used.
72
+
73
+ | CSS variables | Meaning and use |
74
+ | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
75
+ | `--background` / `--foreground` | Default page surface and readable default content. |
76
+ | `--primary` / `--primary-foreground` | Main brand and action surface, plus readable content on it. |
77
+ | `--secondary` / `--secondary-foreground` | Supporting surface, plus readable content on it. It is not assumed light or dark. |
78
+ | `--accent` / `--accent-foreground` | High-attention emphasis, selection, or decorative surface, plus readable content on it. Do not use it as a default CTA substitute. |
79
+ | `--muted` / `--muted-foreground` | Low-emphasis surface and secondary text/icons. |
80
+ | `--radius` | Generic radius fallback. |
81
+ | `--radius-card` / `--radius-button` / `--radius-input` | Radius for cards, command buttons, and form controls. |
82
+
83
+ Hand-written CSS consumes these unprefixed variables directly. Do not use
84
+ Tailwind aliases such as `var(--color-primary)` or `var(--color-background)`
85
+ in hand-written rules. For derived values, declare a theme-prefixed variable on
86
+ the root:
74
87
 
75
88
  ```css
76
89
  .my-theme-root {
77
- --my-theme-primary-hover: color-mix(in srgb, var(--suda-color-primary) 84%, black);
90
+ --my-theme-primary-hover: color-mix(in srgb, var(--primary) 84%, black);
78
91
  }
79
92
 
80
93
  .my-theme-button:hover {
@@ -82,8 +95,10 @@ theme-prefixed variable on the root:
82
95
  }
83
96
  ```
84
97
 
85
- Build/check/publish reject hand-written consumption of Suda-backed Tailwind
86
- aliases.
98
+ Theme authors decide which semantic surface each component uses. Do not alter
99
+ built-in section styling to match one theme palette, and do not hardcode
100
+ replacement colors in individual sections. Build/check/publish reject
101
+ hand-written consumption of Suda-backed Tailwind aliases.
87
102
 
88
103
  ## Visual consistency
89
104
 
@@ -35,6 +35,9 @@ export const sourceManifest: ThemeSourceManifest = {
35
35
  button: "8px",
36
36
  input: "8px",
37
37
  },
38
+ layout: {
39
+ contentWidth: "1280px",
40
+ },
38
41
  },
39
42
  },
40
43
  {
@@ -58,6 +61,9 @@ export const sourceManifest: ThemeSourceManifest = {
58
61
  button: "9999px",
59
62
  input: "10px",
60
63
  },
64
+ layout: {
65
+ contentWidth: "1280px",
66
+ },
61
67
  },
62
68
  },
63
69
  ],
@@ -1,4 +1,4 @@
1
- import type { SudaComponentConfig } from "@sudajs/theme-engine";
1
+ import type { SudaSectionConfig, SudaSectionMetadata } from "@sudajs/theme-engine";
2
2
  import {
3
3
  SudaIcon,
4
4
  type SudaIconName,
@@ -48,7 +48,8 @@ type FeaturedPostsProps = {
48
48
  postList?: ThemePostResourceQuery;
49
49
  } & PuckExtras;
50
50
 
51
- export const Hero: SudaComponentConfig<HeroProps> = {
51
+ export const Hero: SudaSectionConfig<HeroProps> = {
52
+ section: { category: "hero", variant: "centered", motion: "reveal" } satisfies SudaSectionMetadata,
52
53
  label: t("sections.hero.label"),
53
54
  ai: {
54
55
  instructions:
@@ -98,7 +99,7 @@ export const Hero: SudaComponentConfig<HeroProps> = {
98
99
  }) => {
99
100
  const logoSrc = resolveAsset(puck?.metadata, logo);
100
101
  return (
101
- <section className="__SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-hero">
102
+ <section data-section-motion="reveal" className="w-full __SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-hero">
102
103
  {showLogo && logoSrc ? (
103
104
  <img className="__SUDA_THEME_KEY__-hero-logo" src={logoSrc} alt="" />
104
105
  ) : null}
@@ -113,7 +114,8 @@ export const Hero: SudaComponentConfig<HeroProps> = {
113
114
  },
114
115
  };
115
116
 
116
- export const FeatureGrid: SudaComponentConfig<FeatureGridProps> = {
117
+ export const FeatureGrid: SudaSectionConfig<FeatureGridProps> = {
118
+ section: { category: "features", variant: "feature-grid", motion: "reveal" } satisfies SudaSectionMetadata,
117
119
  label: t("sections.featureGrid.label"),
118
120
  ai: {
119
121
  instructions:
@@ -146,7 +148,7 @@ export const FeatureGrid: SudaComponentConfig<FeatureGridProps> = {
146
148
  ],
147
149
  },
148
150
  render: ({ title, description, columns = 3, features = [] }) => (
149
- <section className="__SUDA_THEME_KEY__-section">
151
+ <section data-section-motion="reveal" className="w-full __SUDA_THEME_KEY__-section">
150
152
  <h2>{title}</h2>
151
153
  <p>{description}</p>
152
154
  <div
@@ -165,7 +167,8 @@ export const FeatureGrid: SudaComponentConfig<FeatureGridProps> = {
165
167
  ),
166
168
  };
167
169
 
168
- export const Testimonial: SudaComponentConfig<TestimonialProps> = {
170
+ export const Testimonial: SudaSectionConfig<TestimonialProps> = {
171
+ section: { category: "social-proof", variant: "testimonial", motion: "reveal" } satisfies SudaSectionMetadata,
169
172
  label: t("sections.testimonial.label"),
170
173
  ai: {
171
174
  instructions:
@@ -184,7 +187,7 @@ export const Testimonial: SudaComponentConfig<TestimonialProps> = {
184
187
  role: "Founder",
185
188
  },
186
189
  render: ({ quote, author, role }) => (
187
- <section className="__SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-quote">
190
+ <section data-section-motion="reveal" className="w-full __SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-quote">
188
191
  <blockquote>{quote}</blockquote>
189
192
  <p>
190
193
  {author} · {role}
@@ -193,7 +196,8 @@ export const Testimonial: SudaComponentConfig<TestimonialProps> = {
193
196
  ),
194
197
  };
195
198
 
196
- export const CallToAction: SudaComponentConfig<CallToActionProps> = {
199
+ export const CallToAction: SudaSectionConfig<CallToActionProps> = {
200
+ section: { category: "conversion", variant: "cta", motion: "reveal" } satisfies SudaSectionMetadata,
197
201
  label: t("sections.callToAction.label"),
198
202
  ai: {
199
203
  instructions:
@@ -214,7 +218,7 @@ export const CallToAction: SudaComponentConfig<CallToActionProps> = {
214
218
  buttonHref: "#contact",
215
219
  },
216
220
  render: ({ title, description, buttonLabel, buttonHref }) => (
217
- <section className="__SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-cta" id="contact">
221
+ <section data-section-motion="reveal" className="w-full __SUDA_THEME_KEY__-section __SUDA_THEME_KEY__-cta" id="contact">
218
222
  <h2>{title}</h2>
219
223
  <p>{description}</p>
220
224
  <a className="__SUDA_THEME_KEY__-button" href={buttonHref}>
@@ -224,7 +228,8 @@ export const CallToAction: SudaComponentConfig<CallToActionProps> = {
224
228
  ),
225
229
  };
226
230
 
227
- export const FeaturedPosts: SudaComponentConfig<FeaturedPostsProps> = {
231
+ export const FeaturedPosts: SudaSectionConfig<FeaturedPostsProps> = {
232
+ section: { category: "content", variant: "featured-posts", motion: "reveal" } satisfies SudaSectionMetadata,
228
233
  label: t("sections.featuredPosts.label"),
229
234
  ai: {
230
235
  instructions:
@@ -251,7 +256,7 @@ export const FeaturedPosts: SudaComponentConfig<FeaturedPostsProps> = {
251
256
  const postHref = (post: (typeof posts)[number]) =>
252
257
  post.url || (post.slug ? `/posts/${encodeURIComponent(post.slug)}` : "#");
253
258
  return (
254
- <section className="__SUDA_THEME_KEY__-section">
259
+ <section data-section-motion="reveal" className="w-full __SUDA_THEME_KEY__-section">
255
260
  <h2>{title}</h2>
256
261
  <p>{description}</p>
257
262
  <div className="__SUDA_THEME_KEY__-grid" style={{ "--__SUDA_THEME_KEY__-columns": 3 }}>
@@ -1,24 +1,44 @@
1
1
  @import "tailwindcss";
2
2
  @source "./**/*.{ts,tsx}";
3
3
 
4
+ [data-suda-motion-ready] [data-section-motion="reveal"] {
5
+ opacity: 0;
6
+ transform: translateY(24px);
7
+ transition:
8
+ opacity 700ms ease,
9
+ transform 700ms ease;
10
+ }
11
+ [data-suda-motion-ready] [data-section-motion="reveal"][data-motion-visible="true"],
12
+ [data-suda-motion-reduced] [data-section-motion="reveal"] {
13
+ opacity: 1;
14
+ transform: none;
15
+ }
16
+ @media (prefers-reduced-motion: reduce) {
17
+ [data-section-motion="reveal"] {
18
+ opacity: 1;
19
+ transform: none;
20
+ transition: none;
21
+ }
22
+ }
23
+
4
24
  .__SUDA_THEME_KEY__-root {
5
25
  font-family: Inter, ui-sans-serif, system-ui, sans-serif;
6
- color: var(--suda-color-foreground, #111827);
7
- background: var(--suda-color-background, #ffffff);
26
+ color: var(--foreground, #111827);
27
+ background: var(--background, #ffffff);
8
28
  }
9
29
  .__SUDA_THEME_KEY__-header,
10
30
  .__SUDA_THEME_KEY__-footer {
11
31
  padding: 20px clamp(20px, 5vw, 64px);
12
- border-bottom: 1px solid var(--suda-color-muted, #e5e7eb);
32
+ border-bottom: 1px solid var(--muted, #e5e7eb);
13
33
  }
14
34
  .__SUDA_THEME_KEY__-footer {
15
35
  display: flex;
16
36
  flex-wrap: wrap;
17
37
  align-items: center;
18
38
  gap: 12px 20px;
19
- border-top: 1px solid var(--suda-color-muted, #e5e7eb);
39
+ border-top: 1px solid var(--muted, #e5e7eb);
20
40
  border-bottom: 0;
21
- color: var(--suda-color-muted-foreground, #6b7280);
41
+ color: var(--muted-foreground, #6b7280);
22
42
  }
23
43
  .__SUDA_THEME_KEY__-footer a {
24
44
  display: inline-flex;
@@ -35,19 +55,19 @@
35
55
  padding: 64px clamp(20px, 5vw, 64px);
36
56
  }
37
57
  .__SUDA_THEME_KEY__-hero {
38
- background: var(--suda-color-accent, #f8fafc);
58
+ background: var(--accent, #f8fafc);
39
59
  }
40
60
  .__SUDA_THEME_KEY__-hero-logo {
41
61
  width: 64px;
42
62
  height: 64px;
43
- border-radius: var(--suda-radius-card, 14px);
63
+ border-radius: var(--radius-card, 14px);
44
64
  margin-bottom: 24px;
45
65
  }
46
66
  .__SUDA_THEME_KEY__-eyebrow {
47
67
  text-transform: uppercase;
48
68
  letter-spacing: 0.08em;
49
69
  font-size: 12px;
50
- color: var(--suda-color-primary, #2563eb);
70
+ color: var(--primary, #2563eb);
51
71
  font-weight: 700;
52
72
  }
53
73
  .__SUDA_THEME_KEY__-section h1 {
@@ -65,16 +85,16 @@
65
85
  .__SUDA_THEME_KEY__-section p {
66
86
  max-width: 680px;
67
87
  line-height: 1.7;
68
- color: var(--suda-color-muted-foreground, #4b5563);
88
+ color: var(--muted-foreground, #4b5563);
69
89
  }
70
90
  .__SUDA_THEME_KEY__-button {
71
91
  display: inline-flex;
72
92
  align-items: center;
73
93
  min-height: 42px;
74
94
  padding: 0 18px;
75
- border-radius: var(--suda-radius-button, 8px);
76
- background: var(--suda-color-primary, #111827);
77
- color: var(--suda-color-primary-foreground, #ffffff);
95
+ border-radius: var(--radius-button, 8px);
96
+ background: var(--primary, #111827);
97
+ color: var(--primary-foreground, #ffffff);
78
98
  text-decoration: none;
79
99
  font-weight: 700;
80
100
  }
@@ -85,14 +105,14 @@
85
105
  margin-top: 28px;
86
106
  }
87
107
  .__SUDA_THEME_KEY__-card {
88
- border: 1px solid var(--suda-color-muted, #e5e7eb);
89
- border-radius: var(--suda-radius-card, 8px);
108
+ border: 1px solid var(--muted, #e5e7eb);
109
+ border-radius: var(--radius-card, 8px);
90
110
  padding: 20px;
91
111
  }
92
112
  .__SUDA_THEME_KEY__-card-icon {
93
113
  width: 24px;
94
114
  height: 24px;
95
- color: var(--suda-color-primary, #2563eb);
115
+ color: var(--primary, #2563eb);
96
116
  }
97
117
  .__SUDA_THEME_KEY__-quote blockquote {
98
118
  max-width: 780px;
@@ -101,15 +121,15 @@
101
121
  margin: 0 0 16px;
102
122
  }
103
123
  .__SUDA_THEME_KEY__-cta {
104
- background: var(--suda-color-foreground, #111827);
105
- color: var(--suda-color-background, #ffffff);
124
+ background: var(--foreground, #111827);
125
+ color: var(--background, #ffffff);
106
126
  }
107
127
  .__SUDA_THEME_KEY__-cta p {
108
- color: var(--suda-color-muted, #d1d5db);
128
+ color: var(--muted, #d1d5db);
109
129
  }
110
130
  .__SUDA_THEME_KEY__-cta .__SUDA_THEME_KEY__-button {
111
- background: var(--suda-color-background, #ffffff);
112
- color: var(--suda-color-foreground, #111827);
131
+ background: var(--background, #ffffff);
132
+ color: var(--foreground, #111827);
113
133
  }
114
134
  @media (max-width: 760px) {
115
135
  .__SUDA_THEME_KEY__-grid {