create-omg 0.4.41 → 0.4.43

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 (81) hide show
  1. package/README.md +16 -6
  2. package/dist/index.mjs +71 -12
  3. package/dist/{template → templates/react-ts}/AGENTS.md +22 -0
  4. package/dist/templates/react-ts/_gitignore +24 -0
  5. package/dist/{template → templates/react-ts}/bun.lock +105 -58
  6. package/dist/templates/react-ts/components.json +25 -0
  7. package/dist/templates/react-ts/eslint.config.js +23 -0
  8. package/dist/templates/react-ts/functions/.gitkeep +0 -0
  9. package/dist/{template → templates/react-ts}/package.json +5 -0
  10. package/dist/templates/react-ts/public/favicon.svg +1 -0
  11. package/dist/templates/react-ts/public/icons/apple-touch-icon.png +0 -0
  12. package/dist/templates/react-ts/public/icons/pwa-192x192.png +0 -0
  13. package/dist/templates/react-ts/public/icons/pwa-512x512-maskable.png +0 -0
  14. package/dist/templates/react-ts/public/icons/pwa-512x512.png +0 -0
  15. package/dist/templates/react-ts/public/icons.svg +24 -0
  16. package/dist/templates/react-ts/schema.ts +5 -0
  17. package/dist/templates/react-ts/server/db.ts +103 -0
  18. package/dist/templates/react-ts/src/App.tsx +128 -0
  19. package/dist/templates/react-ts/src/components/ui/animated-number.tsx +102 -0
  20. package/dist/templates/react-ts/src/components/ui/animated-text.tsx +109 -0
  21. package/dist/templates/react-ts/src/components/ui/bottom-nav.tsx +131 -0
  22. package/dist/templates/react-ts/src/components/ui/button.tsx +84 -0
  23. package/dist/templates/react-ts/src/components/ui/card.tsx +70 -0
  24. package/dist/templates/react-ts/src/components/ui/otp-input.tsx +179 -0
  25. package/dist/templates/react-ts/src/components/ui/scroll-affordance.tsx +106 -0
  26. package/dist/templates/react-ts/src/components/ui/sound.ts +182 -0
  27. package/dist/templates/react-ts/src/components/ui/transitions.tsx +419 -0
  28. package/dist/templates/react-ts/src/components/ui/vibes-ui-styles.ts +388 -0
  29. package/dist/templates/react-ts/src/db.drizzle.ts +5 -0
  30. package/dist/templates/react-ts/src/index.css +168 -0
  31. package/dist/templates/react-ts/src/lib/utils.ts +6 -0
  32. package/dist/templates/react-ts/src/main.tsx +22 -0
  33. package/dist/templates/react-ts/src/routeTree.gen.ts +59 -0
  34. package/dist/templates/react-ts/src/routes/__root.tsx +7 -0
  35. package/dist/templates/react-ts/src/routes/index.tsx +9 -0
  36. package/dist/templates/react-ts/tsconfig.app.json +30 -0
  37. package/dist/templates/react-ts/tsconfig.json +10 -0
  38. package/dist/templates/react-ts/tsconfig.node.json +24 -0
  39. package/dist/{template → templates/react-ts}/vite.config.ts +9 -1
  40. package/dist/templates/react-ts-start/AGENTS.md +75 -0
  41. package/dist/templates/react-ts-start/README.md +58 -0
  42. package/dist/templates/react-ts-start/bun.lock +1688 -0
  43. package/dist/templates/react-ts-start/package.json +58 -0
  44. package/dist/templates/react-ts-start/src/routeTree.gen.ts +68 -0
  45. package/dist/templates/react-ts-start/src/router.tsx +18 -0
  46. package/dist/templates/react-ts-start/src/routes/__root.tsx +40 -0
  47. package/dist/templates/react-ts-start/src/routes/index.tsx +7 -0
  48. package/dist/templates/react-ts-start/vite.config.ts +29 -0
  49. package/package.json +3 -3
  50. package/dist/template/src/main.tsx +0 -10
  51. /package/dist/{template → templates/react-ts}/README.md +0 -0
  52. /package/dist/{template → templates/react-ts}/index.html +0 -0
  53. /package/dist/{template → templates/react-ts-start}/_gitignore +0 -0
  54. /package/dist/{template → templates/react-ts-start}/components.json +0 -0
  55. /package/dist/{template → templates/react-ts-start}/eslint.config.js +0 -0
  56. /package/dist/{template → templates/react-ts-start}/functions/.gitkeep +0 -0
  57. /package/dist/{template → templates/react-ts-start}/public/favicon.svg +0 -0
  58. /package/dist/{template → templates/react-ts-start}/public/icons/apple-touch-icon.png +0 -0
  59. /package/dist/{template → templates/react-ts-start}/public/icons/pwa-192x192.png +0 -0
  60. /package/dist/{template → templates/react-ts-start}/public/icons/pwa-512x512-maskable.png +0 -0
  61. /package/dist/{template → templates/react-ts-start}/public/icons/pwa-512x512.png +0 -0
  62. /package/dist/{template → templates/react-ts-start}/public/icons.svg +0 -0
  63. /package/dist/{template → templates/react-ts-start}/schema.ts +0 -0
  64. /package/dist/{template → templates/react-ts-start}/server/db.ts +0 -0
  65. /package/dist/{template → templates/react-ts-start}/src/App.tsx +0 -0
  66. /package/dist/{template → templates/react-ts-start}/src/components/ui/animated-number.tsx +0 -0
  67. /package/dist/{template → templates/react-ts-start}/src/components/ui/animated-text.tsx +0 -0
  68. /package/dist/{template → templates/react-ts-start}/src/components/ui/bottom-nav.tsx +0 -0
  69. /package/dist/{template → templates/react-ts-start}/src/components/ui/button.tsx +0 -0
  70. /package/dist/{template → templates/react-ts-start}/src/components/ui/card.tsx +0 -0
  71. /package/dist/{template → templates/react-ts-start}/src/components/ui/otp-input.tsx +0 -0
  72. /package/dist/{template → templates/react-ts-start}/src/components/ui/scroll-affordance.tsx +0 -0
  73. /package/dist/{template → templates/react-ts-start}/src/components/ui/sound.ts +0 -0
  74. /package/dist/{template → templates/react-ts-start}/src/components/ui/transitions.tsx +0 -0
  75. /package/dist/{template → templates/react-ts-start}/src/components/ui/vibes-ui-styles.ts +0 -0
  76. /package/dist/{template → templates/react-ts-start}/src/db.drizzle.ts +0 -0
  77. /package/dist/{template → templates/react-ts-start}/src/index.css +0 -0
  78. /package/dist/{template → templates/react-ts-start}/src/lib/utils.ts +0 -0
  79. /package/dist/{template → templates/react-ts-start}/tsconfig.app.json +0 -0
  80. /package/dist/{template → templates/react-ts-start}/tsconfig.json +0 -0
  81. /package/dist/{template → templates/react-ts-start}/tsconfig.node.json +0 -0
@@ -0,0 +1,388 @@
1
+ // Delight-primitive stylesheet — injected once at first mount.
2
+ //
3
+ // Vendored source (was @omg-dev/ui). These primitives ship plain, namespaced
4
+ // (`.vui-*`) CSS in a single injected `<style>` tag rather than Tailwind
5
+ // utility classes. That's deliberate and survives `shadcn init` rewriting
6
+ // `index.css` at bake time: the styles live here in a `.ts` module nothing
7
+ // else touches, so there's no `@source` hack and no reliance on Tailwind's
8
+ // content scan. The text/number primitives INHERIT the surrounding text color
9
+ // (so they sit correctly on any surface — a dark card, a colored hero — and
10
+ // honor a text-* utility you put on them). The standalone scroll cue reads
11
+ // --muted-foreground with a neutral prefers-color-scheme fallback for a bare,
12
+ // unthemed app. Edit the CSS below freely; it's yours now.
13
+
14
+ export const STYLE_ID = "vibes-ui-styles"
15
+
16
+ export function ensureStyles() {
17
+ if (typeof document === "undefined") return
18
+ if (document.getElementById(STYLE_ID)) return
19
+ const el = document.createElement("style")
20
+ el.id = STYLE_ID
21
+ el.textContent = CSS
22
+ document.head.appendChild(el)
23
+ }
24
+
25
+ const CSS = `
26
+ .vui {
27
+ /* Only the scroll cue still needs a bare-app fallback (--muted-foreground).
28
+ The text/number primitives inherit their color now, so no --vui-fg. */
29
+ --vui-muted: #71717a;
30
+ /* Shared transition tokens for the <Transitions> family (.vui-t-*). Soft,
31
+ fast-out eases; tune these in one place. */
32
+ --vui-ease-soft: cubic-bezier(0.22, 1, 0.36, 1);
33
+ --vui-ease-bounce: cubic-bezier(0.34, 1.36, 0.64, 1);
34
+ font-family: inherit;
35
+ }
36
+ @media (prefers-color-scheme: dark) {
37
+ .vui {
38
+ --vui-muted: #a1a1aa;
39
+ }
40
+ }
41
+
42
+ /* ── AnimatedNumber — odometer / slot-text rolling digits ──────────────── */
43
+ .vui-num {
44
+ display: inline-flex;
45
+ align-items: baseline;
46
+ /* No \`color\` here on purpose: inherit the surrounding text color (or honor a
47
+ text-* utility on the element) like normal inline text. Pinning this to
48
+ var(--foreground) made the number render page-foreground-dark even on a
49
+ dark card / colored surface, where its siblings (which inherit) sit light —
50
+ a dark-on-dark theme conflict. */
51
+ font-variant-numeric: tabular-nums;
52
+ line-height: 1;
53
+ }
54
+ .vui-num-reel {
55
+ position: relative;
56
+ display: inline-block;
57
+ height: 1em;
58
+ overflow: hidden;
59
+ vertical-align: bottom;
60
+ }
61
+ .vui-num-track {
62
+ display: flex;
63
+ flex-direction: column;
64
+ /* The roll itself. Long, soft ease so digits settle like an odometer.
65
+ transform is set inline per-digit; the per-position stagger (delay) is
66
+ set inline too so significant digits cascade in after the small ones. */
67
+ transition: transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
68
+ will-change: transform;
69
+ }
70
+ .vui-num-cell {
71
+ height: 1em;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ }
76
+ .vui-num-sym {
77
+ display: inline-block;
78
+ }
79
+ @media (prefers-reduced-motion: reduce) {
80
+ .vui-num-track { transition: none; }
81
+ }
82
+
83
+ /* ── AnimatedText — split-flap / slot-text rolling letters ────────────── */
84
+ .vui-text {
85
+ display: inline-flex;
86
+ align-items: baseline;
87
+ /* Inherit the surrounding text color (or honor a text-* utility) — see the
88
+ note on .vui-num. Don't pin to var(--foreground): it overrode the color of
89
+ whatever surface the text sits on. */
90
+ line-height: 1;
91
+ white-space: pre;
92
+ }
93
+ .vui-text-reel {
94
+ position: relative;
95
+ display: inline-block;
96
+ /* Fixed character cell — every reel is as wide as the alphabet's widest
97
+ glyph, so the row reads like a split-flap board and never reflows mid-roll. */
98
+ height: 1em;
99
+ overflow: hidden;
100
+ vertical-align: bottom;
101
+ }
102
+ .vui-text-track {
103
+ display: flex;
104
+ flex-direction: column;
105
+ /* The roll itself. Long, soft ease so letters settle like a flap board.
106
+ transform is set inline per-letter; the per-position stagger (delay) is
107
+ set inline too so the word reveals left-to-right. */
108
+ transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
109
+ will-change: transform;
110
+ }
111
+ .vui-text-cell {
112
+ height: 1em;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ white-space: pre;
117
+ }
118
+ .vui-text-sym {
119
+ display: inline-block;
120
+ white-space: pre;
121
+ }
122
+ @media (prefers-reduced-motion: reduce) {
123
+ .vui-text-track { transition: none; }
124
+ }
125
+
126
+ /* ── ScrollAffordance — "there's more below" cue ──────────────────────── */
127
+ .vui-scroll {
128
+ display: inline-flex;
129
+ flex-direction: column;
130
+ align-items: center;
131
+ gap: 6px;
132
+ color: var(--muted-foreground, var(--vui-muted));
133
+ font-size: 12px;
134
+ font-weight: 500;
135
+ letter-spacing: 0.02em;
136
+ /* Fade + lift away the instant the user starts scrolling — the cue has
137
+ done its job, lingering would be noise. */
138
+ transition: opacity 0.4s ease, transform 0.4s ease;
139
+ pointer-events: none;
140
+ user-select: none;
141
+ }
142
+ .vui-scroll[data-hidden="true"] {
143
+ opacity: 0;
144
+ transform: translateY(6px);
145
+ }
146
+ .vui-scroll-chevron {
147
+ width: 22px;
148
+ height: 22px;
149
+ animation: vui-bob 1.8s ease-in-out infinite;
150
+ }
151
+ @keyframes vui-bob {
152
+ 0%, 100% { transform: translateY(0); opacity: 0.65; }
153
+ 50% { transform: translateY(4px); opacity: 1; }
154
+ }
155
+ @media (prefers-reduced-motion: reduce) {
156
+ .vui-scroll-chevron { animation: none; }
157
+ .vui-scroll { transition: none; }
158
+ }
159
+
160
+ /* ── Transitions (transitions.dev, vendored) ──────────────────────────────
161
+ Dependency-free, CSS-only micro-interactions. Only transform/opacity/filter
162
+ animate (never color/size/shadow), close is faster than open, and every
163
+ family carries a prefers-reduced-motion guard. Driven by the React wrappers
164
+ in transitions.tsx via .is-open / .is-closing / data-* state. */
165
+
166
+ /* Modal — dialog open/close (+ optional fading backdrop) */
167
+ .vui-t-modal {
168
+ transform-origin: center;
169
+ transform: scale(0.95);
170
+ opacity: 0;
171
+ pointer-events: none;
172
+ transition:
173
+ transform 300ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
174
+ opacity 300ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
175
+ will-change: transform, opacity;
176
+ }
177
+ .vui-t-modal.is-open { transform: scale(1); opacity: 1; pointer-events: auto; }
178
+ .vui-t-modal.is-closing {
179
+ transform: scale(0.96);
180
+ opacity: 0;
181
+ pointer-events: none;
182
+ transition:
183
+ transform 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
184
+ opacity 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
185
+ }
186
+ .vui-t-backdrop {
187
+ opacity: 0;
188
+ transition: opacity 300ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
189
+ }
190
+ .vui-t-backdrop.is-open { opacity: 1; }
191
+ .vui-t-backdrop.is-closing {
192
+ opacity: 0;
193
+ transition: opacity 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
194
+ }
195
+
196
+ /* Menu — popover/dropdown anchored to its trigger (set data-origin) */
197
+ .vui-t-menu {
198
+ transform-origin: top left;
199
+ transform: scale(0.97);
200
+ opacity: 0;
201
+ pointer-events: none;
202
+ transition:
203
+ transform 250ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
204
+ opacity 250ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
205
+ will-change: transform, opacity;
206
+ }
207
+ .vui-t-menu[data-origin="top-right"] { transform-origin: top right; }
208
+ .vui-t-menu[data-origin="top-center"] { transform-origin: top center; }
209
+ .vui-t-menu[data-origin="bottom-left"] { transform-origin: bottom left; }
210
+ .vui-t-menu[data-origin="bottom-center"] { transform-origin: bottom center; }
211
+ .vui-t-menu[data-origin="bottom-right"] { transform-origin: bottom right; }
212
+ .vui-t-menu.is-open { transform: scale(1); opacity: 1; pointer-events: auto; }
213
+ .vui-t-menu.is-closing {
214
+ transform: scale(0.99);
215
+ opacity: 0;
216
+ pointer-events: none;
217
+ transition:
218
+ transform 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
219
+ opacity 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
220
+ }
221
+
222
+ /* Panel — inline reveal / drawer / expander (stays mounted, toggles data-open).
223
+ Override --vui-t-panel-y with ~half the panel height for a fuller open. */
224
+ .vui-t-panel {
225
+ transform: translateY(var(--vui-t-panel-y, 16px));
226
+ opacity: 0;
227
+ filter: blur(2px);
228
+ pointer-events: none;
229
+ transition:
230
+ transform 350ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
231
+ opacity 350ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
232
+ filter 350ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
233
+ will-change: transform, opacity, filter;
234
+ }
235
+ .vui-t-panel[data-open="true"] {
236
+ transform: translateY(0);
237
+ opacity: 1;
238
+ filter: blur(0);
239
+ pointer-events: auto;
240
+ transition:
241
+ transform 400ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
242
+ opacity 400ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
243
+ filter 400ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
244
+ }
245
+
246
+ /* PageSlide — side-by-side wizard / tab steps. Pages before the active one
247
+ exit left, pages after exit right (direction set inline per page). */
248
+ .vui-t-pages { position: relative; }
249
+ .vui-t-page {
250
+ position: absolute;
251
+ inset: 0;
252
+ opacity: 0;
253
+ pointer-events: none;
254
+ transform: translateX(var(--vui-t-page-x, 8px));
255
+ filter: blur(3px);
256
+ transition:
257
+ opacity 200ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
258
+ transform 200ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
259
+ filter 200ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
260
+ will-change: opacity, transform, filter;
261
+ }
262
+ .vui-t-page.is-active {
263
+ opacity: 1;
264
+ pointer-events: auto;
265
+ transform: translateX(0);
266
+ filter: blur(0);
267
+ }
268
+
269
+ /* IconSwap — cross-fade/scale between two stacked icons (play/pause, moon/sun) */
270
+ .vui-t-icon-swap { position: relative; display: inline-grid; }
271
+ .vui-t-icon-swap .vui-t-icon {
272
+ grid-area: 1 / 1;
273
+ transition:
274
+ opacity 200ms ease-in-out,
275
+ filter 200ms ease-in-out,
276
+ transform 200ms ease-in-out;
277
+ will-change: opacity, filter, transform;
278
+ }
279
+ .vui-t-icon-swap[data-state="a"] .vui-t-icon[data-icon="a"],
280
+ .vui-t-icon-swap[data-state="b"] .vui-t-icon[data-icon="b"] {
281
+ opacity: 1; filter: blur(0); transform: scale(1);
282
+ }
283
+ .vui-t-icon-swap[data-state="a"] .vui-t-icon[data-icon="b"],
284
+ .vui-t-icon-swap[data-state="b"] .vui-t-icon[data-icon="a"] {
285
+ opacity: 0; filter: blur(2px); transform: scale(0.25);
286
+ }
287
+
288
+ /* TextSwap — smoothly replace a label/status string in place.
289
+ --vui-t-text-dur is read by the wrapper to time the text content swap, so
290
+ tune the duration here (one place) and the JS phase stays in sync. */
291
+ .vui-t-text {
292
+ --vui-t-text-dur: 200ms;
293
+ display: inline-block;
294
+ transform: translateY(0);
295
+ filter: blur(0);
296
+ opacity: 1;
297
+ transition:
298
+ transform var(--vui-t-text-dur) ease-out,
299
+ filter var(--vui-t-text-dur) ease-out,
300
+ opacity var(--vui-t-text-dur) ease-out;
301
+ will-change: transform, filter, opacity;
302
+ }
303
+ .vui-t-text.is-exit { transform: translateY(-8px); filter: blur(2px); opacity: 0; }
304
+ .vui-t-text.is-enter-start {
305
+ transform: translateY(8px); filter: blur(2px); opacity: 0; transition: none;
306
+ }
307
+
308
+ /* NotificationBadge — pop a count/dot in and out on a relative trigger */
309
+ @keyframes vui-t-badge-slide-in {
310
+ from { transform: translate(-8.2px, 12.4px); }
311
+ to { transform: translate(0, 0); }
312
+ }
313
+ .vui-t-badge {
314
+ position: absolute;
315
+ top: -6px;
316
+ right: -8px;
317
+ pointer-events: none;
318
+ will-change: transform;
319
+ }
320
+ .vui-t-badge[data-open="true"] {
321
+ animation: vui-t-badge-slide-in 260ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
322
+ }
323
+ .vui-t-badge-dot {
324
+ display: block;
325
+ transform-origin: center;
326
+ transform: scale(1);
327
+ opacity: 1;
328
+ filter: blur(0);
329
+ transition:
330
+ transform 500ms var(--vui-ease-bounce, cubic-bezier(0.34, 1.36, 0.64, 1)),
331
+ opacity 400ms var(--vui-ease-bounce, cubic-bezier(0.34, 1.36, 0.64, 1)),
332
+ filter 500ms var(--vui-ease-bounce, cubic-bezier(0.34, 1.36, 0.64, 1));
333
+ will-change: transform, opacity, filter;
334
+ }
335
+ .vui-t-badge[data-open="false"] .vui-t-badge-dot {
336
+ transform: scale(0);
337
+ opacity: 0;
338
+ filter: blur(2px);
339
+ transition:
340
+ transform 180ms cubic-bezier(0.4, 0, 0.2, 1),
341
+ opacity 180ms cubic-bezier(0.4, 0, 0.2, 1),
342
+ filter 180ms cubic-bezier(0.4, 0, 0.2, 1);
343
+ }
344
+
345
+ /* Expand — height-auto reveal via grid-template-rows 0fr→1fr (no JS measuring,
346
+ no max-height guesswork). The inner wrapper clips overflow while collapsed;
347
+ min-height:0 lets the grid track actually shrink to zero. Content fades in
348
+ slightly behind the height so a tall body doesn't pop. */
349
+ .vui-t-expand {
350
+ display: grid;
351
+ grid-template-rows: 0fr;
352
+ transition: grid-template-rows 320ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
353
+ }
354
+ .vui-t-expand[data-open="true"] { grid-template-rows: 1fr; }
355
+ .vui-t-expand > .vui-t-expand-inner {
356
+ overflow: hidden;
357
+ min-height: 0;
358
+ opacity: 0;
359
+ transition: opacity 180ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
360
+ }
361
+ .vui-t-expand[data-open="true"] > .vui-t-expand-inner {
362
+ opacity: 1;
363
+ transition: opacity 240ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)) 80ms;
364
+ }
365
+
366
+ /* View Transitions — soft default cross-fade for the animateView() helper
367
+ (document.startViewTransition). Slightly slower than the UA default so
368
+ morphs read as intentional rather than a flicker. */
369
+ ::view-transition-old(root),
370
+ ::view-transition-new(root) {
371
+ animation-duration: 260ms;
372
+ animation-timing-function: var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
373
+ }
374
+
375
+ @media (prefers-reduced-motion: reduce) {
376
+ .vui-t-modal, .vui-t-backdrop, .vui-t-menu, .vui-t-panel, .vui-t-page,
377
+ .vui-t-icon-swap .vui-t-icon, .vui-t-text, .vui-t-expand,
378
+ .vui-t-expand > .vui-t-expand-inner {
379
+ transition: none !important;
380
+ }
381
+ .vui-t-badge, .vui-t-badge-dot { animation: none !important; transition: none !important; }
382
+ /* Kill View-Transition animations too — animateView() also short-circuits in
383
+ JS, but a transition started elsewhere still gets neutralized here. */
384
+ ::view-transition-group(*),
385
+ ::view-transition-old(*),
386
+ ::view-transition-new(*) { animation: none !important; }
387
+ }
388
+ `
@@ -0,0 +1,5 @@
1
+ // This file is auto-generated by @omg-dev/vite-plugin. Do not edit manually.
2
+ // To regenerate: restart the dev server or run `vp build`.
3
+
4
+ export const drizzleSchema = {
5
+ }
@@ -0,0 +1,168 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+ @import "@fontsource-variable/geist";
5
+
6
+ /* ── vibes design-system lock ──────────────────────────────────────────────
7
+ Tailwind's default palette is removed: raw color utilities like
8
+ bg-indigo-600 / text-zinc-400 compile to NOTHING. Style with the
9
+ semantic tokens only (bg-background, bg-card, bg-primary,
10
+ text-muted-foreground, border-border, bg-destructive, …).
11
+ To change the look, switch the whole preset:
12
+ bunx --bun shadcn@latest init --preset <code> --force
13
+ Never hand-edit the token values in this file. */
14
+ @theme {
15
+ --color-*: initial;
16
+ --color-white: #fff;
17
+ --color-black: #000;
18
+ }
19
+
20
+ @custom-variant dark (&:is(.dark *));
21
+
22
+ @theme inline {
23
+ --font-heading: var(--font-sans);
24
+ --font-sans: "Geist Variable", sans-serif;
25
+ --color-sidebar-ring: var(--sidebar-ring);
26
+ --color-sidebar-border: var(--sidebar-border);
27
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
28
+ --color-sidebar-accent: var(--sidebar-accent);
29
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
30
+ --color-sidebar-primary: var(--sidebar-primary);
31
+ --color-sidebar-foreground: var(--sidebar-foreground);
32
+ --color-sidebar: var(--sidebar);
33
+ --color-chart-5: var(--chart-5);
34
+ --color-chart-4: var(--chart-4);
35
+ --color-chart-3: var(--chart-3);
36
+ --color-chart-2: var(--chart-2);
37
+ --color-chart-1: var(--chart-1);
38
+ --color-ring: var(--ring);
39
+ --color-input: var(--input);
40
+ --color-border: var(--border);
41
+ --color-destructive: var(--destructive);
42
+ --color-accent-foreground: var(--accent-foreground);
43
+ --color-accent: var(--accent);
44
+ --color-muted-foreground: var(--muted-foreground);
45
+ --color-muted: var(--muted);
46
+ --color-secondary-foreground: var(--secondary-foreground);
47
+ --color-secondary: var(--secondary);
48
+ --color-primary-foreground: var(--primary-foreground);
49
+ --color-primary: var(--primary);
50
+ --color-popover-foreground: var(--popover-foreground);
51
+ --color-popover: var(--popover);
52
+ --color-card-foreground: var(--card-foreground);
53
+ --color-card: var(--card);
54
+ --color-foreground: var(--foreground);
55
+ --color-background: var(--background);
56
+ --radius-sm: calc(var(--radius) * 0.6);
57
+ --radius-md: calc(var(--radius) * 0.8);
58
+ --radius-lg: var(--radius);
59
+ --radius-xl: calc(var(--radius) * 1.4);
60
+ --radius-2xl: calc(var(--radius) * 1.8);
61
+ --radius-3xl: calc(var(--radius) * 2.2);
62
+ --radius-4xl: calc(var(--radius) * 2.6);
63
+ }
64
+
65
+ :root {
66
+ color-scheme: light;
67
+ --background: oklch(1 0 0);
68
+ --foreground: oklch(0.145 0 0);
69
+ --card: oklch(1 0 0);
70
+ --card-foreground: oklch(0.145 0 0);
71
+ --popover: oklch(1 0 0);
72
+ --popover-foreground: oklch(0.145 0 0);
73
+ --primary: oklch(0.205 0 0);
74
+ --primary-foreground: oklch(0.985 0 0);
75
+ --secondary: oklch(0.97 0 0);
76
+ --secondary-foreground: oklch(0.205 0 0);
77
+ --muted: oklch(0.97 0 0);
78
+ --muted-foreground: oklch(0.556 0 0);
79
+ --accent: oklch(0.97 0 0);
80
+ --accent-foreground: oklch(0.205 0 0);
81
+ --destructive: oklch(0.577 0.245 27.325);
82
+ --border: oklch(0.922 0 0);
83
+ --input: oklch(0.922 0 0);
84
+ --ring: oklch(0.708 0 0);
85
+ --chart-1: oklch(0.87 0 0);
86
+ --chart-2: oklch(0.556 0 0);
87
+ --chart-3: oklch(0.439 0 0);
88
+ --chart-4: oklch(0.371 0 0);
89
+ --chart-5: oklch(0.269 0 0);
90
+ --radius: 0.625rem;
91
+ --sidebar: oklch(0.985 0 0);
92
+ --sidebar-foreground: oklch(0.145 0 0);
93
+ --sidebar-primary: oklch(0.205 0 0);
94
+ --sidebar-primary-foreground: oklch(0.985 0 0);
95
+ --sidebar-accent: oklch(0.97 0 0);
96
+ --sidebar-accent-foreground: oklch(0.205 0 0);
97
+ --sidebar-border: oklch(0.922 0 0);
98
+ --sidebar-ring: oklch(0.708 0 0);
99
+ }
100
+
101
+ .dark {
102
+ color-scheme: dark;
103
+ --background: oklch(0.145 0 0);
104
+ --foreground: oklch(0.985 0 0);
105
+ --card: oklch(0.205 0 0);
106
+ --card-foreground: oklch(0.985 0 0);
107
+ --popover: oklch(0.205 0 0);
108
+ --popover-foreground: oklch(0.985 0 0);
109
+ --primary: oklch(0.922 0 0);
110
+ --primary-foreground: oklch(0.205 0 0);
111
+ --secondary: oklch(0.269 0 0);
112
+ --secondary-foreground: oklch(0.985 0 0);
113
+ --muted: oklch(0.269 0 0);
114
+ --muted-foreground: oklch(0.708 0 0);
115
+ --accent: oklch(0.269 0 0);
116
+ --accent-foreground: oklch(0.985 0 0);
117
+ --destructive: oklch(0.704 0.191 22.216);
118
+ --border: oklch(1 0 0 / 10%);
119
+ --input: oklch(1 0 0 / 15%);
120
+ --ring: oklch(0.556 0 0);
121
+ --chart-1: oklch(0.87 0 0);
122
+ --chart-2: oklch(0.556 0 0);
123
+ --chart-3: oklch(0.439 0 0);
124
+ --chart-4: oklch(0.371 0 0);
125
+ --chart-5: oklch(0.269 0 0);
126
+ --sidebar: oklch(0.205 0 0);
127
+ --sidebar-foreground: oklch(0.985 0 0);
128
+ --sidebar-primary: oklch(0.488 0.243 264.376);
129
+ --sidebar-primary-foreground: oklch(0.985 0 0);
130
+ --sidebar-accent: oklch(0.269 0 0);
131
+ --sidebar-accent-foreground: oklch(0.985 0 0);
132
+ --sidebar-border: oklch(1 0 0 / 10%);
133
+ --sidebar-ring: oklch(0.556 0 0);
134
+ }
135
+
136
+ @layer base {
137
+ * {
138
+ @apply border-border outline-ring/50;
139
+ }
140
+ body {
141
+ @apply bg-background text-foreground;
142
+ }
143
+ html {
144
+ @apply font-sans;
145
+ }
146
+ }
147
+
148
+ /* iOS "squishy" corners — continuous superellipse curvature (the soft
149
+ rounding Apple uses on app icons, cards, and controls). Pair with a
150
+ rounded-* utility, which sets the radius AND is the graceful fallback
151
+ for browsers without corner-shape support (Chromium 139+ today). */
152
+ @utility squircle {
153
+ corner-shape: superellipse(4);
154
+ }
155
+
156
+ @utility squircle-icon {
157
+ corner-shape: superellipse(5);
158
+ }
159
+
160
+ /* iOS input-zoom guard — keep focused form controls at >=16px on touch so
161
+ Safari never zooms the page on focus (without disabling pinch-zoom). */
162
+ @media (pointer: coarse) {
163
+ input,
164
+ textarea,
165
+ select {
166
+ font-size: max(16px, 1rem);
167
+ }
168
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,22 @@
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import { RouterProvider, createRouter } from '@tanstack/react-router'
4
+ import './index.css'
5
+ import { routeTree } from './routeTree.gen'
6
+
7
+ // Routes are files: add src/routes/pricing.tsx and you have /pricing. The
8
+ // route tree below is generated from that directory by @tanstack/router-plugin
9
+ // (see vite.config.ts) — never edit routeTree.gen.ts by hand.
10
+ const router = createRouter({ routeTree, scrollRestoration: true })
11
+
12
+ declare module '@tanstack/react-router' {
13
+ interface Register {
14
+ router: typeof router
15
+ }
16
+ }
17
+
18
+ createRoot(document.getElementById('root')!).render(
19
+ <StrictMode>
20
+ <RouterProvider router={router} />
21
+ </StrictMode>,
22
+ )
@@ -0,0 +1,59 @@
1
+ /* eslint-disable */
2
+
3
+ // @ts-nocheck
4
+
5
+ // noinspection JSUnusedGlobalSymbols
6
+
7
+ // This file was automatically generated by TanStack Router.
8
+ // You should NOT make any changes in this file as it will be overwritten.
9
+ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10
+
11
+ import { Route as rootRouteImport } from './routes/__root'
12
+ import { Route as IndexRouteImport } from './routes/index'
13
+
14
+ const IndexRoute = IndexRouteImport.update({
15
+ id: '/',
16
+ path: '/',
17
+ getParentRoute: () => rootRouteImport,
18
+ } as any)
19
+
20
+ export interface FileRoutesByFullPath {
21
+ '/': typeof IndexRoute
22
+ }
23
+ export interface FileRoutesByTo {
24
+ '/': typeof IndexRoute
25
+ }
26
+ export interface FileRoutesById {
27
+ __root__: typeof rootRouteImport
28
+ '/': typeof IndexRoute
29
+ }
30
+ export interface FileRouteTypes {
31
+ fileRoutesByFullPath: FileRoutesByFullPath
32
+ fullPaths: '/'
33
+ fileRoutesByTo: FileRoutesByTo
34
+ to: '/'
35
+ id: '__root__' | '/'
36
+ fileRoutesById: FileRoutesById
37
+ }
38
+ export interface RootRouteChildren {
39
+ IndexRoute: typeof IndexRoute
40
+ }
41
+
42
+ declare module '@tanstack/react-router' {
43
+ interface FileRoutesByPath {
44
+ '/': {
45
+ id: '/'
46
+ path: '/'
47
+ fullPath: '/'
48
+ preLoaderRoute: typeof IndexRouteImport
49
+ parentRoute: typeof rootRouteImport
50
+ }
51
+ }
52
+ }
53
+
54
+ const rootRouteChildren: RootRouteChildren = {
55
+ IndexRoute: IndexRoute,
56
+ }
57
+ export const routeTree = rootRouteImport
58
+ ._addFileChildren(rootRouteChildren)
59
+ ._addFileTypes<FileRouteTypes>()
@@ -0,0 +1,7 @@
1
+ import { createRootRoute, Outlet } from "@tanstack/react-router"
2
+
3
+ // The shell every route renders inside. Put app-wide chrome here (a nav bar, a
4
+ // providers wrapper, an error boundary) — it stays mounted across navigations.
5
+ export const Route = createRootRoute({
6
+ component: () => <Outlet />,
7
+ })
@@ -0,0 +1,9 @@
1
+ import { createFileRoute } from "@tanstack/react-router"
2
+ import App from "@/App"
3
+
4
+ // "/" — the home route. src/App.tsx stays the home view, so the build-time
5
+ // prerender (which renders the app's root view into dist/index.html) keeps
6
+ // working exactly as before.
7
+ export const Route = createFileRoute("/")({
8
+ component: App,
9
+ })