@lukoweb/apitogo-module-landing 0.1.59 → 0.1.61

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": "@lukoweb/apitogo-module-landing",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.tsx"
@@ -14,7 +14,7 @@
14
14
  "devDependencies": {
15
15
  "@types/react": "19.2.14",
16
16
  "@types/react-dom": "19.2.3",
17
- "@lukoweb/apitogo": "0.1.59",
17
+ "@lukoweb/apitogo": "0.1.61",
18
18
  "react": "19.2.4",
19
19
  "react-dom": "19.2.4",
20
20
  "typescript": "5.9.3"
@@ -1,7 +1,6 @@
1
1
  import type { ResolvedLandingContent } from "@lukoweb/apitogo";
2
2
  import type { ComponentType } from "react";
3
3
  import { FooterSection } from "./sections/FooterSection.js";
4
- import "./landing.css";
5
4
 
6
5
  export type LandingFooterSlotConfig = ResolvedLandingContent["footer"];
7
6
 
@@ -16,11 +15,7 @@ export const createLandingFooterSlot = (
16
15
  return undefined;
17
16
  }
18
17
 
19
- const LandingFooterSlot = () => (
20
- <div className="apitogo-landing">
21
- <FooterSection footer={footer} />
22
- </div>
23
- );
18
+ const LandingFooterSlot = () => <FooterSection footer={footer} />;
24
19
 
25
20
  return LandingFooterSlot;
26
21
  };
@@ -30,7 +30,8 @@ export type LandingShellProps = {
30
30
  description?: string;
31
31
  /**
32
32
  * Show the "Built with APIToGo" line. Defaults to true.
33
- * Automatically hidden when a `FooterSection` is composed as a child.
33
+ * Automatically hidden when a `FooterSection` is composed as a child or
34
+ * a footer slot is configured (e.g. `modules.landing.content.footer`).
34
35
  */
35
36
  showPoweredBy?: boolean;
36
37
  };
@@ -45,21 +46,12 @@ export const LandingShell = ({
45
46
  const siteTitle =
46
47
  options.metadata?.applicationName ?? options.site?.title ?? "APIToGo";
47
48
  const pageTitle = title ?? siteTitle;
48
- const hasFooter = containsFooterSection(children);
49
+ const hasFooter =
50
+ containsFooterSection(children) || Boolean(options.slots?.footer);
49
51
 
50
52
  return (
51
- <div className="apitogo-landing relative overflow-hidden">
53
+ <div className="relative overflow-hidden bg-background text-foreground">
52
54
  <Head>
53
- <link rel="preconnect" href="https://fonts.googleapis.com" />
54
- <link
55
- rel="preconnect"
56
- href="https://fonts.gstatic.com"
57
- crossOrigin=""
58
- />
59
- <link
60
- href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=IBM+Plex+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
61
- rel="stylesheet"
62
- />
63
55
  <title>{pageTitle}</title>
64
56
  {description ? <meta name="description" content={description} /> : null}
65
57
  </Head>
@@ -69,7 +61,7 @@ export const LandingShell = ({
69
61
  {showPoweredBy && !hasFooter ? (
70
62
  <div
71
63
  className={cn(
72
- "landing-powered-by py-6 text-center text-xs",
64
+ "border-t border-border py-6 text-center text-xs text-muted-foreground/70",
73
65
  !options.site?.footer && "mb-8",
74
66
  )}
75
67
  >
package/src/landing.css CHANGED
@@ -1,52 +1,3 @@
1
- .apitogo-landing {
2
- --landing-display: "Space Grotesk", var(--font-sans, system-ui), sans-serif;
3
- --landing-body: "IBM Plex Sans", var(--font-sans, system-ui), sans-serif;
4
- --landing-mono: "JetBrains Mono", var(--font-mono, ui-monospace), monospace;
5
- --landing-bg: #0b0d12;
6
- --landing-bg-2: #0e1119;
7
- --landing-surface: #14171f;
8
- --landing-surface-2: #191d27;
9
- --landing-border: #252b37;
10
- --landing-border-2: #333a48;
11
- --landing-text: #edeff5;
12
- --landing-text-2: #a6aebf;
13
- --landing-text-3: #6b7385;
14
- --landing-accent: #f23645;
15
- --landing-accent-hover: #ff515d;
16
- --landing-accent-soft: rgba(242, 54, 69, 0.13);
17
- --landing-on-accent: #fff;
18
- --landing-green: #16c784;
19
- --landing-green-soft: rgba(22, 199, 132, 0.13);
20
- --landing-peri: #aeb9e8;
21
- --landing-code-bg: #0c0f16;
22
- --landing-shadow:
23
- 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -8px rgba(0, 0, 0, 0.55);
24
- background: var(--landing-bg);
25
- color: var(--landing-text);
26
- font-family: var(--landing-body);
27
- -webkit-font-smoothing: antialiased;
28
- }
29
-
30
- :not(.dark) .apitogo-landing {
31
- --landing-bg: #f5f6f9;
32
- --landing-bg-2: #ffffff;
33
- --landing-surface: #ffffff;
34
- --landing-surface-2: #fafbfc;
35
- --landing-border: #e6e8ef;
36
- --landing-border-2: #d6dae3;
37
- --landing-text: #0e1016;
38
- --landing-text-2: #565e70;
39
- --landing-text-3: #8a92a3;
40
- --landing-accent: #e11d2a;
41
- --landing-accent-hover: #c2151f;
42
- --landing-accent-soft: rgba(225, 29, 42, 0.08);
43
- --landing-green: #0e9e63;
44
- --landing-green-soft: rgba(14, 158, 99, 0.1);
45
- --landing-peri: #4e5ac0;
46
- --landing-shadow:
47
- 0 1px 2px rgba(16, 24, 40, 0.05), 0 8px 24px -10px rgba(16, 24, 40, 0.14);
48
- }
49
-
50
1
  @keyframes landing-fu {
51
2
  from {
52
3
  opacity: 0;
@@ -58,212 +9,6 @@
58
9
  }
59
10
  }
60
11
 
61
- .apitogo-landing .landing-display {
62
- font-family: var(--landing-display);
63
- }
64
-
65
- .apitogo-landing .landing-mono {
66
- font-family: var(--landing-mono);
67
- }
68
-
69
- .apitogo-landing .landing-fu {
12
+ .landing-fu {
70
13
  animation: landing-fu 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) both;
71
14
  }
72
-
73
- .apitogo-landing .landing-section-label {
74
- color: var(--landing-accent);
75
- font-family: var(--landing-mono);
76
- font-size: 0.8125rem;
77
- font-weight: 600;
78
- margin-bottom: 0.75rem;
79
- }
80
-
81
- .apitogo-landing .landing-muted {
82
- color: var(--landing-text-2);
83
- }
84
-
85
- .apitogo-landing .landing-muted-3 {
86
- color: var(--landing-text-3);
87
- }
88
-
89
- .apitogo-landing .landing-btn-primary {
90
- align-items: center;
91
- background: var(--landing-accent);
92
- border: none;
93
- border-radius: 11px;
94
- box-shadow: 0 8px 24px -8px var(--landing-accent-soft);
95
- color: var(--landing-on-accent);
96
- cursor: pointer;
97
- display: inline-flex;
98
- font-family: inherit;
99
- font-size: 0.96875rem;
100
- font-weight: 600;
101
- gap: 0.5rem;
102
- padding: 0.8125rem 1.375rem;
103
- text-decoration: none;
104
- transition: background 0.15s ease;
105
- }
106
-
107
- .apitogo-landing .landing-btn-primary:hover {
108
- background: var(--landing-accent-hover);
109
- }
110
-
111
- .apitogo-landing .landing-btn-secondary {
112
- align-items: center;
113
- background: var(--landing-surface);
114
- border: 1px solid var(--landing-border);
115
- border-radius: 11px;
116
- color: var(--landing-text);
117
- cursor: pointer;
118
- display: inline-flex;
119
- font-family: inherit;
120
- font-size: 0.96875rem;
121
- font-weight: 600;
122
- gap: 0.5rem;
123
- padding: 0.8125rem 1.375rem;
124
- text-decoration: none;
125
- transition:
126
- border-color 0.15s ease,
127
- background 0.15s ease;
128
- }
129
-
130
- .apitogo-landing .landing-btn-secondary:hover {
131
- border-color: var(--landing-border-2);
132
- }
133
-
134
- .apitogo-landing .landing-btn-sm {
135
- border-radius: 9px;
136
- font-size: 0.875rem;
137
- padding: 0.625rem 1rem;
138
- }
139
-
140
- .apitogo-landing .landing-hero-gradient {
141
- background: radial-gradient(
142
- 1000px 480px at 78% -8%,
143
- var(--landing-accent-soft),
144
- transparent 70%
145
- );
146
- }
147
-
148
- .apitogo-landing .landing-badge {
149
- align-items: center;
150
- background: var(--landing-surface);
151
- border: 1px solid var(--landing-border);
152
- border-radius: 999px;
153
- color: var(--landing-text-2);
154
- display: inline-flex;
155
- font-size: 0.78125rem;
156
- gap: 0.5rem;
157
- margin-bottom: 1.375rem;
158
- padding: 0.375rem 0.75rem 0.375rem 0.5rem;
159
- width: fit-content;
160
- }
161
-
162
- .apitogo-landing .landing-status-pill {
163
- align-items: center;
164
- background: var(--landing-green-soft);
165
- border-radius: 999px;
166
- color: var(--landing-green);
167
- display: inline-flex;
168
- font-family: var(--landing-mono);
169
- font-size: 0.6875rem;
170
- font-weight: 600;
171
- gap: 0.3125rem;
172
- padding: 0.125rem 0.5rem;
173
- }
174
-
175
- .apitogo-landing .landing-status-dot {
176
- background: var(--landing-green);
177
- border-radius: 50%;
178
- height: 6px;
179
- width: 6px;
180
- }
181
-
182
- .apitogo-landing .landing-feature-card {
183
- background: var(--landing-surface);
184
- border: 1px solid var(--landing-border);
185
- border-radius: 14px;
186
- padding: 1.5rem;
187
- transition: border-color 0.15s ease;
188
- }
189
-
190
- .apitogo-landing .landing-feature-card:hover {
191
- border-color: var(--landing-border-2);
192
- }
193
-
194
- .apitogo-landing .landing-feature-icon {
195
- background: var(--landing-accent-soft);
196
- border-radius: 11px;
197
- color: var(--landing-accent);
198
- display: grid;
199
- height: 2.625rem;
200
- margin-bottom: 1rem;
201
- place-items: center;
202
- width: 2.625rem;
203
- }
204
-
205
- .apitogo-landing .landing-api-card {
206
- background: var(--landing-surface);
207
- border: 1px solid var(--landing-border);
208
- border-radius: 13px;
209
- color: var(--landing-text);
210
- cursor: pointer;
211
- padding: 1.125rem;
212
- text-decoration: none;
213
- transition:
214
- border-color 0.15s ease,
215
- transform 0.15s ease;
216
- }
217
-
218
- .apitogo-landing .landing-api-card:hover {
219
- border-color: var(--landing-border-2);
220
- transform: translateY(-2px);
221
- }
222
-
223
- .apitogo-landing .landing-api-icon {
224
- background: var(--landing-surface-2);
225
- border: 1px solid var(--landing-border);
226
- border-radius: 9px;
227
- color: var(--landing-peri);
228
- display: grid;
229
- height: 2.25rem;
230
- place-items: center;
231
- width: 2.25rem;
232
- }
233
-
234
- .apitogo-landing .landing-latency-badge {
235
- background: var(--landing-green-soft);
236
- border-radius: 6px;
237
- color: var(--landing-green);
238
- font-family: var(--landing-mono);
239
- font-size: 0.6875rem;
240
- font-weight: 600;
241
- padding: 0.1875rem 0.4375rem;
242
- }
243
-
244
- .apitogo-landing .landing-trust-logo {
245
- color: var(--landing-text-2);
246
- font-family: var(--landing-display);
247
- font-size: 1.1875rem;
248
- font-weight: 600;
249
- letter-spacing: -0.01em;
250
- }
251
-
252
- .apitogo-landing .landing-showcase-section {
253
- background: var(--landing-bg-2);
254
- border-bottom: 1px solid var(--landing-border);
255
- border-top: 1px solid var(--landing-border);
256
- }
257
-
258
- .apitogo-landing .landing-hero-section {
259
- border-bottom: 1px solid var(--landing-border);
260
- }
261
-
262
- .apitogo-landing .landing-powered-by {
263
- border-top: 1px solid var(--landing-border);
264
- color: var(--landing-text-3);
265
- }
266
-
267
- .apitogo-landing .landing-footer-social-link {
268
- color: var(--landing-text-3);
269
- }
@@ -1,5 +1,6 @@
1
1
  import type { ResolvedLandingContent } from "@lukoweb/apitogo";
2
2
  import { Link } from "@lukoweb/apitogo/components";
3
+ import { Button } from "@lukoweb/apitogo/ui/Button.js";
3
4
  import { ArrowRightIcon } from "lucide-react";
4
5
  import { LandingIcon } from "./LandingIcon.js";
5
6
 
@@ -19,25 +20,28 @@ export const ApiShowcaseSection = ({
19
20
  const browseLabel = apiShowcase.browseAllLabel ?? "Browse all APIs";
20
21
 
21
22
  return (
22
- <section className="landing-showcase-section">
23
+ <section className="border-y border-border bg-muted/30">
23
24
  <div className="mx-auto max-w-[1200px] px-6 py-[3.75rem]">
24
25
  <div className="mb-8 flex flex-wrap items-end justify-between gap-5">
25
26
  <div>
26
- <p className="landing-section-label">{"// the catalog"}</p>
27
- <h2 className="landing-display text-[2.125rem] leading-tight font-bold tracking-[-0.025em]">
27
+ <p className="mb-3 font-mono text-[0.8125rem] font-semibold text-primary">
28
+ {"// the catalog"}
29
+ </p>
30
+ <h2 className="text-[2.125rem] leading-tight font-bold tracking-[-0.025em]">
28
31
  {apiShowcase.title ?? "Production APIs. One key."}
29
32
  </h2>
30
33
  {apiShowcase.subtitle ? (
31
- <p className="landing-muted mt-2">{apiShowcase.subtitle}</p>
34
+ <p className="mt-2 text-muted-foreground">
35
+ {apiShowcase.subtitle}
36
+ </p>
32
37
  ) : null}
33
38
  </div>
34
- <Link
35
- to={browseHref}
36
- className="landing-btn-secondary landing-btn-sm"
37
- >
38
- {browseLabel}
39
- <ArrowRightIcon size={15} aria-hidden />
40
- </Link>
39
+ <Button asChild variant="outline" size="sm">
40
+ <Link to={browseHref}>
41
+ {browseLabel}
42
+ <ArrowRightIcon size={15} aria-hidden />
43
+ </Link>
44
+ </Button>
41
45
  </div>
42
46
 
43
47
  <div className="grid gap-3.5 sm:grid-cols-2 lg:grid-cols-4">
@@ -45,20 +49,22 @@ export const ApiShowcaseSection = ({
45
49
  <Link
46
50
  key={`${item.name}-${item.path}`}
47
51
  to={browseHref}
48
- className="landing-api-card block"
52
+ className="block rounded-[13px] border border-border bg-card p-[1.125rem] text-foreground no-underline transition-[border-color,transform] hover:-translate-y-0.5 hover:border-muted-foreground/30"
49
53
  >
50
54
  <div className="mb-3.5 flex items-center justify-between">
51
- <div className="landing-api-icon">
55
+ <div className="grid size-9 place-items-center rounded-[9px] border border-border bg-muted/40 text-primary">
52
56
  <LandingIcon name={item.icon ?? "boxes"} size={18} />
53
57
  </div>
54
58
  {item.latency ? (
55
- <span className="landing-latency-badge">{item.latency}</span>
59
+ <span className="rounded-md bg-primary/10 px-[0.4375rem] py-[0.1875rem] font-mono text-[0.6875rem] font-semibold text-primary">
60
+ {item.latency}
61
+ </span>
56
62
  ) : null}
57
63
  </div>
58
- <h3 className="landing-display mb-1 text-[0.9375rem] font-semibold">
64
+ <h3 className="mb-1 text-[0.9375rem] font-semibold">
59
65
  {item.name}
60
66
  </h3>
61
- <p className="landing-mono landing-muted-3 text-[0.71875rem]">
67
+ <p className="font-mono text-[0.71875rem] text-muted-foreground/70">
62
68
  {item.path}
63
69
  </p>
64
70
  </Link>
@@ -12,24 +12,24 @@ export const CodeExampleCard = ({ example }: CodeExampleCardProps) => {
12
12
  const language = example.language ?? "bash";
13
13
 
14
14
  return (
15
- <div
16
- className="overflow-hidden rounded-2xl border border-[var(--landing-border)] shadow-[var(--landing-shadow)]"
17
- style={{ background: "var(--landing-code-bg)" }}
18
- >
19
- <div className="flex items-center gap-2 border-b border-[#1b1f2a] px-4 py-3">
20
- <span className="size-[11px] rounded-full bg-[#ff5f57]" aria-hidden />
21
- <span className="size-[11px] rounded-full bg-[#febc2e]" aria-hidden />
22
- <span className="size-[11px] rounded-full bg-[#28c840]" aria-hidden />
23
- <span className="landing-mono ms-2 text-xs text-[#6b7385]">
15
+ <div className="overflow-hidden rounded-2xl border border-border bg-card shadow-sm">
16
+ <div className="flex items-center gap-2 border-b border-border bg-muted/40 px-4 py-3">
17
+ <span
18
+ className="size-[11px] rounded-full bg-destructive/80"
19
+ aria-hidden
20
+ />
21
+ <span className="size-[11px] rounded-full bg-warning" aria-hidden />
22
+ <span className="size-[11px] rounded-full bg-primary" aria-hidden />
23
+ <span className="ms-2 font-mono text-xs text-muted-foreground">
24
24
  {filename}
25
25
  </span>
26
26
  <TerminalIcon
27
27
  size={14}
28
- className="ms-auto text-[#4b5162]"
28
+ className="ms-auto text-muted-foreground/70"
29
29
  aria-hidden
30
30
  />
31
31
  </div>
32
- <pre className="landing-mono overflow-x-auto p-[1.125rem] text-[0.78125rem] leading-[1.85] text-[#cdd3e0]">
32
+ <pre className="overflow-x-auto p-[1.125rem] font-mono text-[0.78125rem] leading-[1.85] text-foreground">
33
33
  <code data-language={language}>{example.code}</code>
34
34
  </pre>
35
35
  </div>
@@ -23,25 +23,30 @@ export const FeaturesSection = ({
23
23
  return (
24
24
  <section className="mx-auto max-w-[1200px] px-6 py-10 pb-16">
25
25
  <div className="mb-11 max-w-[640px]">
26
- <p className="landing-section-label">{label}</p>
27
- <h2 className="landing-display mb-3.5 text-[2.375rem] leading-tight font-bold tracking-[-0.025em] text-balance">
26
+ <p className="mb-3 font-mono text-[0.8125rem] font-semibold text-primary">
27
+ {label}
28
+ </p>
29
+ <h2 className="mb-3.5 text-[2.375rem] leading-tight font-bold tracking-[-0.025em] text-balance">
28
30
  {title}
29
31
  </h2>
30
- <p className="landing-muted text-[1.0625rem] leading-relaxed">
32
+ <p className="text-[1.0625rem] leading-relaxed text-muted-foreground">
31
33
  {description}
32
34
  </p>
33
35
  </div>
34
36
 
35
37
  <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
36
38
  {features.map((feature) => (
37
- <article key={feature.title} className="landing-feature-card">
38
- <div className="landing-feature-icon">
39
+ <article
40
+ key={feature.title}
41
+ className="rounded-[14px] border border-border bg-card p-6 transition-colors hover:border-muted-foreground/30"
42
+ >
43
+ <div className="mb-4 grid size-[2.625rem] place-items-center rounded-[11px] bg-primary/10 text-primary">
39
44
  <LandingIcon name={feature.icon} size={21} />
40
45
  </div>
41
- <h3 className="landing-display mb-2 text-[1.09375rem] font-semibold">
46
+ <h3 className="mb-2 text-[1.09375rem] font-semibold">
42
47
  {feature.title}
43
48
  </h3>
44
- <p className="landing-muted text-[0.90625rem] leading-relaxed">
49
+ <p className="text-[0.90625rem] leading-relaxed text-muted-foreground">
45
50
  {feature.description}
46
51
  </p>
47
52
  </article>
@@ -55,7 +55,7 @@ const FooterSocialLink = ({
55
55
  target="_blank"
56
56
  rel="noopener noreferrer"
57
57
  aria-label={accessibleLabel}
58
- className="landing-footer-social-link landing-muted-3 inline-flex items-center justify-center transition-colors hover:text-[var(--landing-text)]"
58
+ className="inline-flex items-center justify-center text-muted-foreground/70 transition-colors hover:text-foreground"
59
59
  >
60
60
  {Icon ? (
61
61
  <Icon className="h-[1.125rem] w-[1.125rem]" />
@@ -85,7 +85,7 @@ export const FooterSection = ({ footer }: FooterSectionProps) => {
85
85
  }
86
86
 
87
87
  return (
88
- <footer className="landing-footer border-t border-[var(--landing-border)] bg-[var(--landing-bg-2)]">
88
+ <footer className="border-t bg-background">
89
89
  <div className="mx-auto max-w-[1200px] px-6 py-12">
90
90
  <div className="grid gap-10 sm:grid-cols-2 lg:grid-cols-[1.4fr_repeat(3,minmax(0,1fr))]">
91
91
  <div className="sm:col-span-2 lg:col-span-1">
@@ -97,14 +97,14 @@ export const FooterSection = ({ footer }: FooterSectionProps) => {
97
97
  className="h-7 w-auto object-contain"
98
98
  />
99
99
  ) : (
100
- <span className="landing-display text-[1.125rem] font-bold tracking-[-0.02em]">
101
- <span className="text-[var(--landing-peri)]">API</span>
100
+ <span className="text-[1.125rem] font-bold tracking-[-0.02em]">
101
+ <span className="text-primary">API</span>
102
102
  <span>ToGo</span>
103
103
  </span>
104
104
  )}
105
105
  </div>
106
106
  {tagline ? (
107
- <p className="landing-muted max-w-[280px] text-[0.875rem] leading-relaxed">
107
+ <p className="max-w-[280px] text-[0.875rem] leading-relaxed text-muted-foreground">
108
108
  {tagline}
109
109
  </p>
110
110
  ) : null}
@@ -112,15 +112,13 @@ export const FooterSection = ({ footer }: FooterSectionProps) => {
112
112
 
113
113
  {columns.map((column) => (
114
114
  <div key={column.title}>
115
- <h3 className="mb-4 text-[0.875rem] font-semibold text-[var(--landing-text)]">
116
- {column.title}
117
- </h3>
115
+ <h3 className="mb-4 text-sm font-semibold">{column.title}</h3>
118
116
  <ul className="space-y-2.5">
119
117
  {column.links.map((link) => (
120
118
  <li key={`${column.title}-${link.label}`}>
121
119
  <a
122
120
  href={link.href}
123
- className="landing-muted text-[0.875rem] transition-colors hover:text-[var(--landing-text)]"
121
+ className="text-sm text-muted-foreground transition-colors hover:text-foreground"
124
122
  >
125
123
  {link.label}
126
124
  </a>
@@ -131,8 +129,8 @@ export const FooterSection = ({ footer }: FooterSectionProps) => {
131
129
  ))}
132
130
  </div>
133
131
 
134
- <div className="landing-footer-bar mt-10 flex flex-col items-center justify-between gap-4 border-t border-[var(--landing-border)] pt-6 sm:flex-row">
135
- <p className="landing-muted-3 text-[0.8125rem]">{copyright}</p>
132
+ <div className="mt-10 flex flex-col items-center justify-between gap-4 border-t border-border pt-6 sm:flex-row">
133
+ <p className="text-sm text-muted-foreground/70">{copyright}</p>
136
134
  {social.length > 0 ? (
137
135
  <div className="flex items-center gap-4">
138
136
  {social.map((item) => (
@@ -19,10 +19,10 @@ export const HeroSection = ({
19
19
  const highlights = hero.highlights ?? [];
20
20
 
21
21
  return (
22
- <section className="landing-hero-section relative overflow-hidden">
22
+ <section className="relative overflow-hidden border-b border-border">
23
23
  <div
24
24
  aria-hidden
25
- className="landing-hero-gradient pointer-events-none absolute inset-0"
25
+ className="pointer-events-none absolute inset-0 bg-[radial-gradient(1000px_480px_at_78%_-8%,color-mix(in_oklch,var(--primary)_13%,transparent),transparent_70%)]"
26
26
  />
27
27
 
28
28
  <div
@@ -39,10 +39,13 @@ export const HeroSection = ({
39
39
  )}
40
40
  >
41
41
  {(hero.badge || hero.subtitle) && (
42
- <div className="landing-badge">
42
+ <div className="mb-[1.375rem] inline-flex w-fit items-center gap-2 rounded-full border border-border bg-card px-3 py-1.5 text-[0.78125rem] text-muted-foreground">
43
43
  {hero.badge ? (
44
- <span className="landing-status-pill">
45
- <span className="landing-status-dot" aria-hidden />
44
+ <span className="inline-flex items-center gap-1.5 rounded-full bg-primary/10 px-2 py-0.5 font-mono text-[0.6875rem] font-semibold text-primary">
45
+ <span
46
+ className="size-1.5 rounded-full bg-primary"
47
+ aria-hidden
48
+ />
46
49
  {hero.badge}
47
50
  </span>
48
51
  ) : null}
@@ -50,20 +53,18 @@ export const HeroSection = ({
50
53
  </div>
51
54
  )}
52
55
 
53
- <h1 className="landing-display mb-5 text-[2.5rem] leading-[1.02] font-bold tracking-[-0.03em] text-balance sm:text-5xl lg:text-[3.5rem]">
56
+ <h1 className="mb-5 text-[2.5rem] leading-[1.02] font-bold tracking-[-0.03em] text-balance sm:text-5xl lg:text-[3.5rem]">
54
57
  {hero.title}
55
58
  {hero.titleAccent ? (
56
59
  <>
57
60
  <br />
58
- <span className="text-[var(--landing-accent)]">
59
- {hero.titleAccent}
60
- </span>
61
+ <span className="text-primary">{hero.titleAccent}</span>
61
62
  </>
62
63
  ) : null}
63
64
  </h1>
64
65
 
65
66
  {hero.description ? (
66
- <p className="landing-muted mb-[1.875rem] max-w-[480px] text-lg leading-relaxed text-pretty">
67
+ <p className="mb-[1.875rem] max-w-[480px] text-lg leading-relaxed text-pretty text-muted-foreground">
67
68
  {hero.description}
68
69
  </p>
69
70
  ) : null}
@@ -91,17 +92,13 @@ export const HeroSection = ({
91
92
  )}
92
93
 
93
94
  {highlights.length > 0 ? (
94
- <ul className="landing-muted-3 mt-[1.875rem] flex flex-wrap items-center gap-x-[1.375rem] gap-y-2 text-[0.8125rem]">
95
+ <ul className="mt-[1.875rem] flex flex-wrap items-center gap-x-[1.375rem] gap-y-2 text-[0.8125rem] text-muted-foreground/70">
95
96
  {highlights.map((item) => (
96
97
  <li
97
98
  key={item}
98
99
  className="inline-flex items-center gap-[0.4375rem]"
99
100
  >
100
- <CheckIcon
101
- size={15}
102
- className="text-[var(--landing-green)]"
103
- aria-hidden
104
- />
101
+ <CheckIcon size={15} className="text-primary" aria-hidden />
105
102
  {item}
106
103
  </li>
107
104
  ))}
@@ -1,5 +1,6 @@
1
1
  import { cn } from "@lukoweb/apitogo";
2
2
  import { Link } from "@lukoweb/apitogo/components";
3
+ import { Button } from "@lukoweb/apitogo/ui/Button.js";
3
4
  import type { LucideIcon } from "lucide-react";
4
5
  import type { ReactNode } from "react";
5
6
 
@@ -33,15 +34,13 @@ export const LandingButton = ({
33
34
  );
34
35
 
35
36
  return (
36
- <Link
37
- to={href}
38
- className={cn(
39
- variant === "primary" ? "landing-btn-primary" : "landing-btn-secondary",
40
- size === "sm" && "landing-btn-sm",
41
- className,
42
- )}
37
+ <Button
38
+ asChild
39
+ variant={variant === "primary" ? "default" : "outline"}
40
+ size={size === "sm" ? "sm" : "lg"}
41
+ className={cn(className)}
43
42
  >
44
- {content}
45
- </Link>
43
+ <Link to={href}>{content}</Link>
44
+ </Button>
46
45
  );
47
46
  };
@@ -14,10 +14,10 @@ export const PricingCtaSection = ({ pricingCta }: PricingCtaSectionProps) => {
14
14
 
15
15
  return (
16
16
  <section className="mx-auto max-w-[1200px] px-6 py-[4.5rem] text-center">
17
- <h2 className="landing-display mb-4 text-[2.5rem] leading-tight font-bold tracking-[-0.03em] text-balance">
17
+ <h2 className="mb-4 text-[2.5rem] leading-tight font-bold tracking-[-0.03em] text-balance">
18
18
  {title}
19
19
  </h2>
20
- <p className="landing-muted mx-auto mb-[1.875rem] max-w-[520px] text-[1.09375rem] leading-relaxed">
20
+ <p className="mx-auto mb-[1.875rem] max-w-[520px] text-[1.09375rem] leading-relaxed text-muted-foreground">
21
21
  {description}
22
22
  </p>
23
23
  <div className="flex flex-wrap items-center justify-center gap-3">
@@ -13,13 +13,16 @@ export const TrustSection = ({ trust }: TrustSectionProps) => {
13
13
  return (
14
14
  <section className="mx-auto max-w-[1200px] px-6 py-10">
15
15
  {trust.title ? (
16
- <p className="landing-muted-3 mb-[1.375rem] text-center text-[0.78125rem] font-semibold tracking-[0.08em] uppercase">
16
+ <p className="mb-[1.375rem] text-center text-[0.78125rem] font-semibold tracking-[0.08em] text-muted-foreground/70 uppercase">
17
17
  {trust.title}
18
18
  </p>
19
19
  ) : null}
20
20
  <div className="flex flex-wrap items-center justify-center gap-x-[2.875rem] gap-y-3.5 opacity-70">
21
21
  {logos.map((logo) => (
22
- <span key={logo} className="landing-trust-logo">
22
+ <span
23
+ key={logo}
24
+ className="text-[1.1875rem] font-semibold tracking-[-0.01em] text-muted-foreground"
25
+ >
23
26
  {logo}
24
27
  </span>
25
28
  ))}