@grove-dev/astro 0.2.18 → 0.2.20

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 (48) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +44 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/theme.test.d.ts +2 -0
  6. package/dist/theme.test.d.ts.map +1 -0
  7. package/dist/theme.test.js +55 -0
  8. package/dist/theme.test.js.map +1 -0
  9. package/package.json +1 -1
  10. package/src/components/CategoryGrid.astro +2 -11
  11. package/src/components/ContributorsGrid.astro +2 -11
  12. package/src/components/CurationGrid.astro +1 -1
  13. package/src/components/DecisionRow.astro +1 -1
  14. package/src/components/ExploreByCategory.astro +3 -3
  15. package/src/components/ExploreByStack.astro +3 -3
  16. package/src/components/FilterGroupMenu.astro +5 -5
  17. package/src/components/Hero.astro +11 -11
  18. package/src/components/Icon.astro +6 -33
  19. package/src/components/IndexRow.astro +5 -5
  20. package/src/components/ItemCard.astro +5 -16
  21. package/src/components/MinimalAbout.astro +2 -2
  22. package/src/components/OriginalCollection.astro +4 -4
  23. package/src/components/Pagination.astro +2 -2
  24. package/src/components/RecordSection.astro +1 -1
  25. package/src/components/RefinePanel.astro +1 -1
  26. package/src/components/SmartLensTabs.astro +3 -3
  27. package/src/components/StackGrid.astro +6 -15
  28. package/src/components/WhyThisExists.astro +3 -3
  29. package/src/index.ts +52 -1
  30. package/src/layouts/BaseLayout.astro +1 -1
  31. package/src/layouts/Container.astro +4 -4
  32. package/src/layouts/Footer.astro +3 -3
  33. package/src/layouts/Header.astro +5 -5
  34. package/src/layouts/ThemeToggle.astro +1 -1
  35. package/src/styles.css +217 -408
  36. package/src/theme.test.ts +67 -0
  37. package/templates/default/package.json +1 -1
  38. package/templates/default/public/icons/stacks/rag.svg +7 -0
  39. package/templates/default/public/llms-full.txt +1 -1
  40. package/templates/default/public/sitemap.xml +10 -10
  41. package/templates/default/src/pages/404.astro +5 -5
  42. package/templates/default/src/pages/[slug]/[recordSlug].astro +27 -31
  43. package/templates/default/src/pages/[slug]/index.astro +8 -37
  44. package/templates/default/src/pages/about.astro +9 -9
  45. package/templates/default/src/pages/contributors.astro +8 -17
  46. package/templates/default/src/pages/submit.astro +23 -31
  47. package/templates/default/src/styles/global.css +14 -39
  48. package/templates/default/tailwind.config.mjs +0 -130
package/src/styles.css CHANGED
@@ -6,72 +6,112 @@
6
6
  *
7
7
  * import "@grove-dev/astro/styles.css";
8
8
  *
9
- * The `grove-` prefix below is the stable contract for the showcase
10
- * component classes (`grove-section`, `grove-card`, `grove-btn`, etc.).
11
- * Tailwind v4's `@theme` block declares the same tokens as CSS custom
12
- * properties and Tailwind utility names — components can use either
13
- * bare `grove-*` classes or Tailwind utilities like `text-ink-900`.
14
- *
15
- * Namespace history: earlier V0 drafts used a different (now
16
- * removed) prefix. Only `grove-*` remains.
9
+ * This file owns only Tailwind theme tokens, runtime light/dark values,
10
+ * base element defaults, and rendered Markdown styles. Astro components
11
+ * keep their presentation in HTML with Tailwind utilities.
17
12
  */
18
13
 
19
14
  @import "tailwindcss";
15
+ /*
16
+ * Custom `dark` variant — `dark:` utilities must key off the `.dark`
17
+ * class on <html> (set by the THEME_INIT script in BaseLayout.astro),
18
+ * NOT off `prefers-color-scheme`. Tailwind v4.3.0 splits the selector
19
+ * argument on commas — including commas inside `:where(...)` — so
20
+ * `(&:where(.dark, .dark *))` is silently parsed as two separate
21
+ * (and broken) selectors and the variant never registers. Use two
22
+ * selectors joined by a space instead.
23
+ */
24
+ @custom-variant dark (&:where(.dark), &:where(.dark *));
20
25
  @source "./**/*.{astro,html,js,jsx,ts,tsx}";
21
26
 
22
27
  @theme {
23
- /* ── Neutral ink scale (V1 default) ───────────────────────────── */
24
- --color-ink-50: #fafafa;
25
- --color-ink-100: #f4f4f5;
26
- --color-ink-200: #e4e4e7;
27
- --color-ink-300: #d4d4d8;
28
- --color-ink-400: #a1a1aa;
29
- --color-ink-500: #71717a;
30
- --color-ink-600: #52525b;
31
- --color-ink-700: #3f3f46;
32
- --color-ink-800: #27272a;
33
- --color-ink-900: #18181b;
34
- --color-ink-950: #09090b;
28
+ /* ── Starlight-aligned neutral scale ──────────────────────────── */
29
+ --color-ink-50: oklch(98.5% 0 0);
30
+ --color-ink-100: oklch(97% 0 0);
31
+ --color-ink-200: oklch(92.2% 0 0);
32
+ --color-ink-300: oklch(87% 0 0);
33
+ --color-ink-400: oklch(70.8% 0 0);
34
+ --color-ink-500: oklch(55.6% 0 0);
35
+ --color-ink-600: oklch(43.9% 0 0);
36
+ --color-ink-700: oklch(37.1% 0 0);
37
+ --color-ink-800: oklch(26.9% 0 0);
38
+ --color-ink-900: oklch(20.5% 0 0);
39
+ --color-ink-950: oklch(14.5% 0 0);
40
+
41
+ /* ── Semantic colors ────────────────────────────────────────────
42
+ * These point at runtime variables instead of fixed palette steps so
43
+ * Tailwind utilities such as `bg-background` and `text-foreground`
44
+ * follow the resolved theme without requiring a `dark:` twin. The
45
+ * values below mirror packages/starlight/styles/{theme,base}.css.
46
+ */
47
+ --color-background: var(--grove-background);
48
+ --color-foreground: var(--grove-foreground);
49
+ --color-primary: var(--grove-primary);
50
+ --color-primary-foreground: var(--grove-primary-foreground);
51
+ --color-secondary: var(--grove-secondary);
52
+ --color-secondary-foreground: var(--grove-secondary-foreground);
53
+ --color-muted: var(--grove-muted);
54
+ --color-muted-foreground: var(--grove-muted-foreground);
55
+ --color-accent: var(--grove-accent);
56
+ --color-accent-foreground: var(--grove-accent-foreground);
57
+ --color-border: var(--grove-border);
58
+ --color-input: var(--grove-input);
59
+ --color-ring: var(--grove-ring);
60
+ --color-card: var(--grove-card);
61
+ --color-card-foreground: var(--grove-card-foreground);
62
+ --color-popover: var(--grove-popover);
63
+ --color-popover-foreground: var(--grove-popover-foreground);
35
64
 
36
65
  /* ── Accent (interactive states) ─────────────────────────────── */
37
- --color-accent: #1f6feb;
38
- --color-accent-muted: #388bfd1a;
66
+ --color-accent-muted: color-mix(in oklab, var(--grove-foreground) 8%, transparent);
39
67
 
40
68
  /* ── Status palettes (badges only) ───────────────────────────── */
41
- --color-emerald-50: #ecfdf5;
42
- --color-emerald-300: #6ee7b7;
43
- --color-emerald-400: #34d399;
44
- --color-emerald-700: #047857;
45
- --color-emerald-800: #065f46;
46
- --color-emerald-950: #022c22;
47
-
48
- --color-orange-50: #fff7ed;
49
- --color-orange-300: #fdba74;
50
- --color-orange-400: #fb923c;
51
- --color-orange-700: #c2410c;
52
- --color-orange-800: #9a3412;
53
- --color-orange-950: #431407;
54
-
55
- --color-blue-50: #eff6ff;
56
- --color-blue-300: #93c5fd;
57
- --color-blue-400: #60a5fa;
58
- --color-blue-700: #1d4ed8;
59
- --color-blue-800: #1e40af;
60
- --color-blue-950: #172554;
61
-
62
- --color-amber-50: #fffbeb;
63
- --color-amber-300: #fcd34d;
64
- --color-amber-400: #fbbf24;
65
- --color-amber-700: #b45309;
66
- --color-amber-800: #92400e;
67
- --color-amber-950: #451a03;
69
+ --color-emerald-50: oklch(98.2% 0.018 155.826);
70
+ --color-emerald-300: oklch(87.1% 0.15 154.449);
71
+ --color-emerald-400: oklch(79.2% 0.209 151.711);
72
+ --color-emerald-500: oklch(72.3% 0.219 149.579);
73
+ --color-emerald-600: oklch(52.7% 0.154 150.069);
74
+ --color-emerald-700: oklch(52.7% 0.154 150.069);
75
+ --color-emerald-800: oklch(26.6% 0.065 152.934);
76
+ --color-emerald-950: oklch(26.6% 0.065 152.934);
77
+
78
+ --color-orange-50: oklch(98% 0.016 73.684);
79
+ --color-orange-300: oklch(90.1% 0.076 70.697);
80
+ --color-orange-400: oklch(83.7% 0.128 66.29);
81
+ --color-orange-500: oklch(70.5% 0.213 47.604);
82
+ --color-orange-700: oklch(70.5% 0.213 47.604);
83
+ --color-orange-800: oklch(55.3% 0.195 38.402);
84
+ --color-orange-950: oklch(40.8% 0.123 38.172);
85
+
86
+ --color-blue-50: oklch(97% 0.014 254.604);
87
+ --color-blue-300: oklch(82.8% 0.111 230.318);
88
+ --color-blue-400: oklch(70.7% 0.165 254.624);
89
+ --color-blue-700: oklch(48.8% 0.243 264.376);
90
+ --color-blue-800: oklch(29.3% 0.066 243.157);
91
+ --color-blue-950: oklch(29.3% 0.066 243.157);
92
+
93
+ --color-amber-50: oklch(98% 0.016 73.684);
94
+ --color-amber-300: oklch(90.1% 0.076 70.697);
95
+ --color-amber-400: oklch(83.7% 0.128 66.29);
96
+ --color-amber-500: oklch(83.7% 0.128 66.29);
97
+ --color-amber-600: oklch(70.5% 0.213 47.604);
98
+ --color-amber-700: oklch(70.5% 0.213 47.604);
99
+ --color-amber-800: oklch(55.3% 0.195 38.402);
100
+ --color-amber-900: oklch(40.8% 0.123 38.172);
101
+ --color-amber-950: oklch(40.8% 0.123 38.172);
68
102
 
69
103
  /* ── Font stacks ─────────────────────────────────────────────── */
70
- --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
71
- "Helvetica Neue", Arial, sans-serif;
104
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
105
+ "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji",
106
+ "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
72
107
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
73
108
  "Liberation Mono", "Courier New", monospace;
74
109
 
110
+ /* ── Starlight typography weight/rhythm ──────────────────────── */
111
+ --font-weight-semibold: 500;
112
+ --font-weight-bold: 600;
113
+ --leading-relaxed: 1.75;
114
+
75
115
  /* ── Font size extensions (2xs) ──────────────────────────────── */
76
116
  --text-2xs: 0.6875rem;
77
117
  --text-2xs--line-height: 1rem;
@@ -82,7 +122,7 @@
82
122
  --container-narrow: 720px;
83
123
 
84
124
  /* ── Border radius scale ─────────────────────────────────────── */
85
- --radius: 0.375rem;
125
+ --radius: 0.625rem;
86
126
  --radius-lg: 0.5rem;
87
127
  --radius-xl: 0.75rem;
88
128
 
@@ -139,7 +179,61 @@
139
179
 
140
180
  @layer base {
141
181
  :root {
142
- color-scheme: light dark;
182
+ color-scheme: light;
183
+
184
+ /* Starlight light theme, expressed as Grove's public semantic API. */
185
+ --grove-background: oklch(100% 0 0);
186
+ --grove-foreground: var(--color-ink-950);
187
+ --grove-gray-1: var(--color-ink-900);
188
+ --grove-gray-2: var(--color-ink-800);
189
+ --grove-gray-3: var(--color-ink-700);
190
+ --grove-gray-4: var(--color-ink-500);
191
+ --grove-gray-5: var(--color-ink-400);
192
+ --grove-gray-6: var(--color-ink-300);
193
+ --grove-gray-7: var(--color-ink-100);
194
+ --grove-primary: var(--grove-foreground);
195
+ --grove-primary-foreground: var(--grove-gray-7);
196
+ --grove-secondary: var(--grove-gray-7);
197
+ --grove-secondary-foreground: var(--grove-foreground);
198
+ --grove-muted: var(--grove-gray-7);
199
+ --grove-muted-foreground: var(--grove-gray-4);
200
+ --grove-accent: var(--grove-gray-7);
201
+ --grove-accent-foreground: var(--grove-foreground);
202
+ --grove-border: var(--grove-gray-6);
203
+ --grove-input: var(--grove-gray-6);
204
+ --grove-ring: var(--grove-gray-4);
205
+ --grove-card: var(--grove-background);
206
+ --grove-card-foreground: var(--grove-foreground);
207
+ --grove-popover: var(--grove-background);
208
+ --grove-popover-foreground: var(--grove-foreground);
209
+ }
210
+
211
+ :root.dark {
212
+ color-scheme: dark;
213
+ --grove-background: var(--color-ink-950);
214
+ --grove-foreground: var(--color-ink-50);
215
+ --grove-gray-1: var(--color-ink-50);
216
+ --grove-gray-2: var(--color-ink-300);
217
+ --grove-gray-3: var(--color-ink-400);
218
+ --grove-gray-4: var(--color-ink-500);
219
+ --grove-gray-5: var(--color-ink-700);
220
+ --grove-gray-6: var(--color-ink-800);
221
+ --grove-gray-7: var(--color-ink-900);
222
+ --grove-primary: var(--grove-foreground);
223
+ --grove-primary-foreground: var(--grove-gray-7);
224
+ --grove-secondary: var(--grove-gray-6);
225
+ --grove-secondary-foreground: var(--grove-foreground);
226
+ --grove-muted: var(--grove-gray-6);
227
+ --grove-muted-foreground: var(--grove-gray-3);
228
+ --grove-accent: var(--grove-gray-5);
229
+ --grove-accent-foreground: var(--grove-foreground);
230
+ --grove-border: var(--grove-gray-6);
231
+ --grove-input: var(--grove-gray-5);
232
+ --grove-ring: var(--grove-gray-4);
233
+ --grove-card: var(--grove-background);
234
+ --grove-card-foreground: var(--grove-foreground);
235
+ --grove-popover: var(--grove-gray-7);
236
+ --grove-popover-foreground: var(--grove-foreground);
143
237
  }
144
238
 
145
239
  html {
@@ -150,16 +244,11 @@
150
244
 
151
245
  body {
152
246
  margin: 0;
153
- background: #ffffff;
154
- color: var(--color-ink-900);
247
+ background: var(--grove-background);
248
+ color: var(--grove-foreground);
155
249
  font-family: var(--font-sans);
156
250
  font-size: 15px;
157
- line-height: 1.55;
158
- }
159
-
160
- .dark body {
161
- background: var(--color-ink-950);
162
- color: var(--color-ink-100);
251
+ line-height: 1.75;
163
252
  }
164
253
 
165
254
  a {
@@ -169,30 +258,23 @@
169
258
 
170
259
  /* Subtle selection */
171
260
  ::selection {
172
- background: var(--color-ink-200);
173
- color: var(--color-ink-900);
174
- }
175
- .dark ::selection {
176
- background: var(--color-ink-800);
177
- color: var(--color-ink-100);
261
+ background: var(--grove-muted);
262
+ color: var(--grove-foreground);
178
263
  }
179
264
 
180
265
  /* Slim, neutral scrollbar */
181
266
  * {
182
267
  scrollbar-width: thin;
183
- scrollbar-color: var(--color-ink-300) transparent;
268
+ scrollbar-color: var(--grove-border) transparent;
184
269
  }
185
270
  *::-webkit-scrollbar {
186
271
  width: 8px;
187
272
  height: 8px;
188
273
  }
189
274
  *::-webkit-scrollbar-thumb {
190
- background: var(--color-ink-200);
275
+ background: var(--grove-border);
191
276
  border-radius: 4px;
192
277
  }
193
- .dark *::-webkit-scrollbar-thumb {
194
- background: var(--color-ink-800);
195
- }
196
278
 
197
279
  input,
198
280
  select,
@@ -200,6 +282,35 @@
200
282
  button {
201
283
  font: inherit;
202
284
  }
285
+
286
+ :where(
287
+ input[type="text"],
288
+ input[type="search"],
289
+ input[type="url"],
290
+ input[type="email"],
291
+ input:not([type]),
292
+ select,
293
+ textarea
294
+ ) {
295
+ border-color: var(--grove-input) !important;
296
+ border-radius: var(--radius) !important;
297
+ background-color: var(--grove-background) !important;
298
+ color: var(--grove-foreground) !important;
299
+ }
300
+
301
+ :where(
302
+ input[type="text"],
303
+ input[type="search"],
304
+ input[type="url"],
305
+ input[type="email"],
306
+ input:not([type]),
307
+ select,
308
+ textarea
309
+ ):focus-visible {
310
+ border-color: var(--grove-ring) !important;
311
+ outline: none;
312
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--grove-ring) 35%, transparent);
313
+ }
203
314
  }
204
315
 
205
316
  /* ──────────────────────────────────────────────────────────────────
@@ -207,26 +318,47 @@
207
318
  * ────────────────────────────────────────────────────────────────── */
208
319
  .grove-prose {
209
320
  max-width: 72ch;
210
- color: var(--color-ink-700);
211
- font-size: 0.9375rem;
321
+ color: var(--color-ink-800);
322
+ font-size: 15px;
212
323
  line-height: 1.75;
213
324
  }
214
325
 
215
326
  .dark .grove-prose {
216
- color: var(--color-ink-200);
327
+ color: var(--color-ink-300);
217
328
  }
218
329
 
219
330
  .grove-prose :where(h1, h2, h3, h4) {
220
331
  margin: 1.75em 0 0.65em;
221
332
  color: var(--color-ink-900);
222
- font-weight: 650;
223
- line-height: 1.25;
333
+ font-weight: 500;
334
+ letter-spacing: -0.025em;
224
335
  }
225
336
 
226
337
  .dark .grove-prose :where(h1, h2, h3, h4) {
227
338
  color: var(--color-ink-100);
228
339
  }
229
340
 
341
+ .grove-prose h1 {
342
+ font-size: 1.875rem;
343
+ font-weight: 600;
344
+ line-height: 2.25rem;
345
+ }
346
+
347
+ .grove-prose h2 {
348
+ font-size: 1.25rem;
349
+ line-height: 1.75rem;
350
+ }
351
+
352
+ .grove-prose h3 {
353
+ font-size: 1.125rem;
354
+ line-height: 1.75rem;
355
+ }
356
+
357
+ .grove-prose h4 {
358
+ font-size: 1rem;
359
+ line-height: 1.5rem;
360
+ }
361
+
230
362
  .grove-prose :where(p, ul, ol, pre, blockquote) {
231
363
  margin: 1em 0;
232
364
  }
@@ -236,9 +368,16 @@
236
368
  }
237
369
 
238
370
  .grove-prose a {
239
- color: var(--color-accent);
371
+ color: var(--color-ink-900);
372
+ font-weight: 500;
240
373
  text-decoration: underline;
241
374
  text-underline-offset: 0.18em;
375
+ text-decoration-color: var(--color-ink-500);
376
+ }
377
+
378
+ .dark .grove-prose a {
379
+ color: var(--color-ink-50);
380
+ text-decoration-color: var(--color-ink-400);
242
381
  }
243
382
 
244
383
  .grove-prose :where(code, pre) {
@@ -279,333 +418,3 @@
279
418
  padding-left: 1rem;
280
419
  color: var(--color-ink-500);
281
420
  }
282
-
283
- /* ──────────────────────────────────────────────────────────────────
284
- * Component classes — shared by the showcase component library.
285
- * Use these directly; you can also use the equivalent Tailwind
286
- * utilities (text-ink-900, bg-white, …) and mix freely.
287
- * ────────────────────────────────────────────────────────────────── */
288
-
289
- @layer components {
290
- /*
291
- * Stable container classes for consumers of the packaged stylesheet.
292
- * Tailwind does not emit utilities referenced only inside a dependency,
293
- * so relying on `max-w-container` alone can leave template content
294
- * unconstrained.
295
- */
296
- .grove-container,
297
- .grove-container-wide,
298
- .grove-container-narrow {
299
- width: 100%;
300
- margin-inline: auto;
301
- }
302
-
303
- .grove-container {
304
- max-width: var(--container-container);
305
- }
306
-
307
- .grove-container-wide {
308
- max-width: var(--container-wide);
309
- }
310
-
311
- .grove-container-narrow {
312
- max-width: var(--container-narrow);
313
- }
314
-
315
- /* Section spacing — consistent vertical rhythm */
316
- .grove-section {
317
- padding-top: 3rem;
318
- padding-bottom: 3rem;
319
- }
320
- @media (min-width: 640px) {
321
- .grove-section {
322
- padding-top: 4rem;
323
- padding-bottom: 4rem;
324
- }
325
- }
326
-
327
- .grove-section-tight {
328
- padding-top: 2.5rem;
329
- padding-bottom: 2.5rem;
330
- }
331
- @media (min-width: 640px) {
332
- .grove-section-tight {
333
- padding-top: 3rem;
334
- padding-bottom: 3rem;
335
- }
336
- }
337
-
338
- /* Subtle card border + hover lift, used everywhere */
339
- .grove-card {
340
- border: 1px solid var(--color-ink-200);
341
- background: #ffffff;
342
- border-radius: var(--radius-lg);
343
- transition:
344
- border-color 150ms ease,
345
- box-shadow 150ms ease,
346
- background-color 150ms ease;
347
- }
348
- .dark .grove-card {
349
- border-color: var(--color-ink-800);
350
- background: var(--color-ink-950);
351
- }
352
-
353
- .grove-card-hover:hover {
354
- border-color: var(--color-ink-300);
355
- background: rgba(244, 244, 245, 0.6);
356
- box-shadow:
357
- 0 1px 2px rgba(0, 0, 0, 0.04),
358
- 0 4px 12px -2px rgba(0, 0, 0, 0.06);
359
- }
360
- .dark .grove-card-hover:hover {
361
- border-color: var(--color-ink-700);
362
- background: rgba(24, 24, 27, 0.4);
363
- box-shadow:
364
- 0 1px 2px rgba(0, 0, 0, 0.4),
365
- 0 4px 12px -2px rgba(0, 0, 0, 0.3);
366
- }
367
-
368
- /* Pill badge — small, neutral */
369
- .grove-badge {
370
- display: inline-flex;
371
- align-items: center;
372
- gap: 0.25rem;
373
- border-radius: 0.25rem;
374
- border: 1px solid var(--color-ink-200);
375
- background: var(--color-ink-50);
376
- padding: 0.125rem 0.375rem;
377
- font-size: var(--text-2xs);
378
- line-height: var(--text-2xs--line-height);
379
- font-weight: 500;
380
- color: var(--color-ink-700);
381
- }
382
- .dark .grove-badge {
383
- border-color: var(--color-ink-800);
384
- background: rgba(24, 24, 27, 0.6);
385
- color: var(--color-ink-300);
386
- }
387
-
388
- .grove-badge-accent {
389
- border-color: var(--color-ink-900);
390
- background: var(--color-ink-900);
391
- color: #ffffff;
392
- }
393
- .dark .grove-badge-accent {
394
- border-color: var(--color-ink-100);
395
- background: var(--color-ink-100);
396
- color: var(--color-ink-900);
397
- }
398
-
399
- .grove-badge-new {
400
- border-color: rgba(110, 231, 183, 0.6);
401
- background: var(--color-emerald-50);
402
- color: var(--color-emerald-800);
403
- }
404
- .dark .grove-badge-new {
405
- border-color: rgba(6, 95, 70, 0.6);
406
- background: rgba(2, 44, 34, 0.4);
407
- color: var(--color-emerald-300);
408
- }
409
-
410
- .grove-badge-hot {
411
- border-color: rgba(253, 186, 116, 0.6);
412
- background: var(--color-orange-50);
413
- color: var(--color-orange-800);
414
- }
415
- .dark .grove-badge-hot {
416
- border-color: rgba(154, 52, 18, 0.6);
417
- background: rgba(67, 20, 7, 0.4);
418
- color: var(--color-orange-300);
419
- }
420
-
421
- .grove-badge-mature {
422
- border-color: rgba(147, 197, 253, 0.6);
423
- background: var(--color-blue-50);
424
- color: var(--color-blue-800);
425
- }
426
- .dark .grove-badge-mature {
427
- border-color: rgba(30, 64, 175, 0.6);
428
- background: rgba(23, 37, 84, 0.4);
429
- color: var(--color-blue-300);
430
- }
431
-
432
- .grove-badge-stale {
433
- border-color: rgba(252, 211, 77, 0.6);
434
- background: var(--color-amber-50);
435
- color: var(--color-amber-800);
436
- }
437
- .dark .grove-badge-stale {
438
- border-color: rgba(146, 64, 14, 0.6);
439
- background: rgba(69, 26, 3, 0.4);
440
- color: var(--color-amber-300);
441
- }
442
-
443
- /* Buttons — outline / ghost / primary */
444
- .grove-btn {
445
- display: inline-flex;
446
- align-items: center;
447
- justify-content: center;
448
- gap: 0.375rem;
449
- border-radius: var(--radius);
450
- border: 1px solid transparent;
451
- padding: 0.375rem 0.75rem;
452
- font-size: 0.875rem;
453
- line-height: 1.25rem;
454
- font-weight: 500;
455
- transition: color 150ms ease, background-color 150ms ease,
456
- border-color 150ms ease;
457
- text-decoration: none;
458
- cursor: pointer;
459
- }
460
-
461
- .grove-btn-ghost {
462
- color: var(--color-ink-700);
463
- }
464
- .grove-btn-ghost:hover {
465
- background: var(--color-ink-100);
466
- }
467
- .dark .grove-btn-ghost {
468
- color: var(--color-ink-300);
469
- }
470
- .dark .grove-btn-ghost:hover {
471
- background: var(--color-ink-900);
472
- }
473
-
474
- .grove-btn-outline {
475
- border-color: var(--color-ink-200);
476
- background: #ffffff;
477
- color: var(--color-ink-900);
478
- }
479
- .grove-btn-outline:hover {
480
- border-color: var(--color-ink-300);
481
- background: var(--color-ink-50);
482
- }
483
- .dark .grove-btn-outline {
484
- border-color: var(--color-ink-800);
485
- background: var(--color-ink-950);
486
- color: var(--color-ink-100);
487
- }
488
- .dark .grove-btn-outline:hover {
489
- border-color: var(--color-ink-700);
490
- background: rgba(24, 24, 27, 0.4);
491
- }
492
-
493
- .grove-btn-primary {
494
- border-color: var(--color-ink-900);
495
- background: var(--color-ink-900);
496
- color: #ffffff;
497
- }
498
- .grove-btn-primary:hover {
499
- background: var(--color-ink-800);
500
- }
501
- .dark .grove-btn-primary {
502
- border-color: var(--color-ink-100);
503
- background: var(--color-ink-100);
504
- color: var(--color-ink-900);
505
- }
506
- .dark .grove-btn-primary:hover {
507
- background: #ffffff;
508
- }
509
- }
510
-
511
- /* ────────────────────────────────────────────────────────────────────
512
- * Backwards-compat aliases — openapps used the unprefixed utility
513
- * names (`card`, `btn-primary`, `btn-outline`, `btn-ghost`). New
514
- * components should use the `grove-` prefix. These rules mirror
515
- * the `grove-*` definitions above so the openapps-derived
516
- * components (ItemCard, AppCard, etc. — kept as `ItemCard` for V1
517
- * published API stability) work without per-component
518
- * edits.
519
- * ────────────────────────────────────────────────────────────────────*/
520
- .card {
521
- border: 1px solid var(--color-ink-200);
522
- background: #ffffff;
523
- border-radius: 0.5rem;
524
- transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
525
- }
526
- .dark .card {
527
- border-color: var(--color-ink-800);
528
- background: var(--color-ink-950);
529
- }
530
- .card-hover:hover {
531
- border-color: var(--color-ink-300);
532
- background: rgba(244, 244, 245, 0.6);
533
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 12px -2px rgba(0, 0, 0, 0.06);
534
- }
535
- .dark .card-hover:hover {
536
- border-color: var(--color-ink-700);
537
- background: rgba(24, 24, 27, 0.4);
538
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px -2px rgba(0, 0, 0, 0.3);
539
- }
540
-
541
- /* Chip — small inline label used for platforms/stacks/etc. on
542
- * ItemCard. Mirrors openapps' `.chip` from the ItemCard.astro
543
- * (component name retained for V1 published API stability).
544
- * `<style>` block so the @apply in the component still works. */
545
- .chip {
546
- display: inline-flex;
547
- align-items: center;
548
- gap: 0.25rem;
549
- border-radius: 0.375rem;
550
- border: 1px solid var(--color-ink-200);
551
- background: #ffffff;
552
- padding: 0.125rem 0.375rem;
553
- font-size: 0.6875rem;
554
- font-weight: 500;
555
- color: var(--color-ink-700);
556
- transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease;
557
- }
558
- .dark .chip {
559
- border-color: var(--color-ink-200);
560
- background: var(--color-ink-950);
561
- color: var(--color-ink-300);
562
- }
563
- .chip-stack {
564
- background: var(--color-ink-50);
565
- }
566
- .dark .chip-stack {
567
- background: rgba(24, 24, 27, 0.6);
568
- }
569
- .btn-primary,
570
- .btn-outline,
571
- .btn-ghost {
572
- display: inline-flex;
573
- align-items: center;
574
- justify-content: center;
575
- gap: 0.375rem;
576
- border-radius: 0.5rem;
577
- padding: 0.5rem 0.875rem;
578
- font-size: 0.875rem;
579
- font-weight: 500;
580
- white-space: nowrap;
581
- transition: color 0.15s, background-color 0.15s, border-color 0.15s;
582
- cursor: pointer;
583
- border: 1px solid transparent;
584
- text-decoration: none;
585
- }
586
- .btn-primary {
587
- border-color: var(--color-ink-900);
588
- background: var(--color-ink-900);
589
- color: var(--color-ink-50);
590
- }
591
- .btn-primary:hover {
592
- background: var(--color-ink-700);
593
- border-color: var(--color-ink-700);
594
- }
595
- .btn-outline {
596
- border-color: var(--color-ink-200);
597
- background: var(--color-ink-50);
598
- color: var(--color-ink-700);
599
- }
600
- .btn-outline:hover {
601
- border-color: var(--color-ink-300);
602
- background: var(--color-ink-100);
603
- }
604
- .btn-ghost {
605
- background: transparent;
606
- color: var(--color-ink-500);
607
- }
608
- .btn-ghost:hover {
609
- color: var(--color-ink-900);
610
- background: var(--color-ink-100);
611
- }