kofi-stack-template-generator 2.1.50 → 2.1.51
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/.turbo/turbo-build.log +5 -5
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/src/templates.generated.ts +3 -3
- package/templates/marketing/nextjs/src/app/globals.css.hbs +495 -10
- package/templates/marketing/payload/src/app/(frontend)/globals.css.hbs +1380 -0
- package/templates/marketing/payload/src/app/(frontend)/globals.css +0 -1019
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> kofi-stack-template-generator@2.1.
|
|
2
|
+
> kofi-stack-template-generator@2.1.51 build /Users/theodenanyoh/Documents/Krumalabs/create-kofi-stack-v2/packages/template-generator
|
|
3
3
|
> pnpm run prebuild && tsup src/index.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> kofi-stack-template-generator@2.1.
|
|
6
|
+
> kofi-stack-template-generator@2.1.51 prebuild /Users/theodenanyoh/Documents/Krumalabs/create-kofi-stack-v2/packages/template-generator
|
|
7
7
|
> node scripts/generate-templates.js
|
|
8
8
|
|
|
9
9
|
Generating templates.generated.ts...
|
|
@@ -13,8 +13,8 @@ CLI Using tsconfig: tsconfig.json
|
|
|
13
13
|
CLI tsup v8.5.1
|
|
14
14
|
CLI Target: es2022
|
|
15
15
|
ESM Build start
|
|
16
|
-
ESM dist/index.js 2.
|
|
17
|
-
ESM ⚡️ Build success in
|
|
16
|
+
ESM dist/index.js 2.29 MB
|
|
17
|
+
ESM ⚡️ Build success in 58ms
|
|
18
18
|
DTS Build start
|
|
19
|
-
DTS ⚡️ Build success in
|
|
19
|
+
DTS ⚡️ Build success in 497ms
|
|
20
20
|
DTS dist/index.d.ts 2.96 KB
|
package/dist/index.js
CHANGED
|
@@ -1194,7 +1194,7 @@ export function ColorPalette() {
|
|
|
1194
1194
|
"marketing/nextjs/next.config.ts.hbs": "import type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n transpilePackages: ['@repo/ui'],\n}\n\nexport default nextConfig\n",
|
|
1195
1195
|
"marketing/nextjs/package.json.hbs": '{\n "name": "@repo/marketing",\n "version": "0.1.0",\n "private": true,\n "scripts": {\n "dev": "next dev --turbopack --port 3000",\n "build": "next build",\n "start": "next start",\n "lint": "biome check .",\n "lint:fix": "biome check --write .",\n "typecheck": "tsc --noEmit"\n },\n "dependencies": {\n "next": "^16.0.0",\n "react": "^19.0.0",\n "react-dom": "^19.0.0",\n "@repo/ui": "workspace:*"\n },\n "devDependencies": {\n "@repo/config-typescript": "workspace:*",\n "@types/node": "^20.0.0",\n "@types/react": "^19.0.0",\n "@types/react-dom": "^19.0.0",\n "tailwindcss": "^4.0.0",\n "@tailwindcss/postcss": "^4.0.0",\n "postcss": "^8.4.0",\n "typescript": "^5.0.0"\n }\n}\n',
|
|
1196
1196
|
"marketing/nextjs/postcss.config.mjs.hbs": "export default {\n plugins: {\n '@tailwindcss/postcss': {},\n },\n}\n",
|
|
1197
|
-
"marketing/nextjs/src/app/globals.css.hbs": '@import "tailwindcss";\n\n:root {\n --background: #ffffff;\n --foreground: #171717;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n --background: #0a0a0a;\n --foreground: #ededed;\n }\n}\n\nbody {\n color: var(--foreground);\n background: var(--background);\n}\n',
|
|
1197
|
+
"marketing/nextjs/src/app/globals.css.hbs": '@import "tailwindcss";\n@import "tw-animate-css";\n\n@custom-variant dark (&:is(.dark *));\n\n@theme inline {\n /* Colors */\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n\n --color-destructive: var(--destructive);\n\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n\n --color-chart-1: var(--chart-1);\n --color-chart-2: var(--chart-2);\n --color-chart-3: var(--chart-3);\n --color-chart-4: var(--chart-4);\n --color-chart-5: var(--chart-5);\n\n /* Border radius */\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n\n /* Fonts */\n --font-sans: var(--font-geist-sans), system-ui, sans-serif;\n --font-mono: var(--font-geist-mono), monospace;\n\n /* Container */\n --container-sm: 40rem;\n --container-md: 48rem;\n --container-lg: 64rem;\n --container-xl: 80rem;\n --container-2xl: 96rem;\n\n /* Animations */\n --animate-accordion-down: accordion-down 0.2s ease-out;\n --animate-accordion-up: accordion-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n from {\n height: 0;\n }\n to {\n height: var(--radix-accordion-content-height);\n }\n}\n\n@keyframes accordion-up {\n from {\n height: var(--radix-accordion-content-height);\n }\n to {\n height: 0;\n }\n}\n\n/* ========================================\n THEME COLOR VARIABLES\n ======================================== */\n\n:root {\n --radius: 0.625rem;\n --background: oklch(1 0 0);\n --foreground: oklch(0.145 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.145 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.145 0 0);\n --secondary: oklch(0.97 0 0);\n --secondary-foreground: oklch(0.205 0 0);\n --muted: oklch(0.97 0 0);\n --muted-foreground: oklch(0.556 0 0);\n --accent: oklch(0.97 0 0);\n --accent-foreground: oklch(0.205 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.922 0 0);\n --input: oklch(0.922 0 0);\n\n{{#if (eq shadcn.themeColor "neutral")}}\n --primary: oklch(0.205 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.646 0.222 41.116);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "blue")}}\n --primary: oklch(0.546 0.245 262.881);\n --primary-foreground: oklch(0.985 0.002 247.858);\n --ring: oklch(0.546 0.245 262.881);\n --chart-1: oklch(0.546 0.245 262.881);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "green")}}\n --primary: oklch(0.596 0.145 163.225);\n --primary-foreground: oklch(0.982 0.018 155.826);\n --ring: oklch(0.596 0.145 163.225);\n --chart-1: oklch(0.596 0.145 163.225);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "purple")}}\n --primary: oklch(0.627 0.265 303.9);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.627 0.265 303.9);\n --chart-1: oklch(0.627 0.265 303.9);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "red")}}\n --primary: oklch(0.637 0.237 25.331);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.637 0.237 25.331);\n --chart-1: oklch(0.637 0.237 25.331);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "orange")}}\n --primary: oklch(0.705 0.191 47.604);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.705 0.191 47.604);\n --chart-1: oklch(0.705 0.191 47.604);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "amber")}}\n --primary: oklch(0.769 0.188 70.08);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.769 0.188 70.08);\n --chart-1: oklch(0.769 0.188 70.08);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.646 0.222 41.116);\n{{else if (eq shadcn.themeColor "cyan")}}\n --primary: oklch(0.715 0.143 215.221);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.715 0.143 215.221);\n --chart-1: oklch(0.715 0.143 215.221);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "emerald")}}\n --primary: oklch(0.696 0.17 162.48);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.696 0.17 162.48);\n --chart-1: oklch(0.696 0.17 162.48);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "fuchsia")}}\n --primary: oklch(0.667 0.295 322.15);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.667 0.295 322.15);\n --chart-1: oklch(0.667 0.295 322.15);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "indigo")}}\n --primary: oklch(0.585 0.233 277.117);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.585 0.233 277.117);\n --chart-1: oklch(0.585 0.233 277.117);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "lime")}}\n --primary: oklch(0.768 0.233 130.85);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.768 0.233 130.85);\n --chart-1: oklch(0.768 0.233 130.85);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "pink")}}\n --primary: oklch(0.718 0.202 349.761);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.718 0.202 349.761);\n --chart-1: oklch(0.718 0.202 349.761);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "rose")}}\n --primary: oklch(0.645 0.246 16.439);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.645 0.246 16.439);\n --chart-1: oklch(0.645 0.246 16.439);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "sky")}}\n --primary: oklch(0.685 0.169 237.323);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.685 0.169 237.323);\n --chart-1: oklch(0.685 0.169 237.323);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "teal")}}\n --primary: oklch(0.704 0.14 182.503);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.704 0.14 182.503);\n --chart-1: oklch(0.704 0.14 182.503);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "violet")}}\n --primary: oklch(0.606 0.25 292.717);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.606 0.25 292.717);\n --chart-1: oklch(0.606 0.25 292.717);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "yellow")}}\n --primary: oklch(0.795 0.184 86.047);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.795 0.184 86.047);\n --chart-1: oklch(0.795 0.184 86.047);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.646 0.222 41.116);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else}}\n --primary: oklch(0.205 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.646 0.222 41.116);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{/if}}\n}\n\n.dark {\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.269 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.371 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n\n{{#if (eq shadcn.themeColor "neutral")}}\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --ring: oklch(0.556 0 0);\n --chart-1: oklch(0.488 0.243 264.376);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "blue")}}\n --primary: oklch(0.623 0.214 262.881);\n --primary-foreground: oklch(0.273 0.033 256.848);\n --ring: oklch(0.623 0.214 262.881);\n --chart-1: oklch(0.623 0.214 262.881);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "green")}}\n --primary: oklch(0.696 0.17 162.48);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.696 0.17 162.48);\n --chart-1: oklch(0.696 0.17 162.48);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "purple")}}\n --primary: oklch(0.714 0.203 305.504);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.714 0.203 305.504);\n --chart-1: oklch(0.714 0.203 305.504);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.488 0.243 264.376);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "red")}}\n --primary: oklch(0.704 0.191 22.216);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.704 0.191 22.216);\n --chart-1: oklch(0.704 0.191 22.216);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor "orange")}}\n --primary: oklch(0.792 0.17 52.615);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.792 0.17 52.615);\n --chart-1: oklch(0.792 0.17 52.615);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "amber")}}\n --primary: oklch(0.828 0.189 84.429);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.828 0.189 84.429);\n --chart-1: oklch(0.828 0.189 84.429);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.488 0.243 264.376);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "cyan")}}\n --primary: oklch(0.789 0.154 211.53);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.789 0.154 211.53);\n --chart-1: oklch(0.789 0.154 211.53);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "emerald")}}\n --primary: oklch(0.765 0.166 160.391);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.765 0.166 160.391);\n --chart-1: oklch(0.765 0.166 160.391);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "fuchsia")}}\n --primary: oklch(0.74 0.238 322.16);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.74 0.238 322.16);\n --chart-1: oklch(0.74 0.238 322.16);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.488 0.243 264.376);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "indigo")}}\n --primary: oklch(0.673 0.182 276.935);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.673 0.182 276.935);\n --chart-1: oklch(0.673 0.182 276.935);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "lime")}}\n --primary: oklch(0.841 0.238 128.85);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.841 0.238 128.85);\n --chart-1: oklch(0.841 0.238 128.85);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "pink")}}\n --primary: oklch(0.775 0.181 349.761);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.775 0.181 349.761);\n --chart-1: oklch(0.775 0.181 349.761);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor "rose")}}\n --primary: oklch(0.712 0.194 13.428);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.712 0.194 13.428);\n --chart-1: oklch(0.712 0.194 13.428);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor "sky")}}\n --primary: oklch(0.756 0.143 232.661);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.756 0.143 232.661);\n --chart-1: oklch(0.756 0.143 232.661);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "teal")}}\n --primary: oklch(0.777 0.152 181.912);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.777 0.152 181.912);\n --chart-1: oklch(0.777 0.152 181.912);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "violet")}}\n --primary: oklch(0.702 0.183 293.541);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.702 0.183 293.541);\n --chart-1: oklch(0.702 0.183 293.541);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.488 0.243 264.376);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "yellow")}}\n --primary: oklch(0.852 0.199 91.936);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.852 0.199 91.936);\n --chart-1: oklch(0.852 0.199 91.936);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.488 0.243 264.376);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else}}\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --ring: oklch(0.556 0 0);\n --chart-1: oklch(0.488 0.243 264.376);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{/if}}\n}\n\n/* ========================================\n BASE STYLES\n ======================================== */\n\n@layer base {\n * {\n @apply border-border outline-ring/50;\n }\n body {\n @apply bg-background text-foreground;\n }\n}\n\n/* Container utility */\n.container {\n width: 100%;\n margin-left: auto;\n margin-right: auto;\n padding-left: 1rem;\n padding-right: 1rem;\n max-width: 96rem;\n}\n\n@media (min-width: 640px) {\n .container {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .container {\n padding-left: 2rem;\n padding-right: 2rem;\n }\n}\n',
|
|
1198
1198
|
"marketing/nextjs/src/app/layout.tsx.hbs": "import type { Metadata } from 'next'\nimport { Geist, Geist_Mono } from 'next/font/google'\nimport './globals.css'\n\nconst geistSans = Geist({\n variable: '--font-geist-sans',\n subsets: ['latin'],\n})\n\nconst geistMono = Geist_Mono({\n variable: '--font-geist-mono',\n subsets: ['latin'],\n})\n\nexport const metadata: Metadata = {\n title: '{{projectName}} - Marketing',\n description: 'Marketing site for {{projectName}}',\n}\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode\n}) {\n return (\n <html lang=\"en\">\n <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>\n {children}\n </body>\n </html>\n )\n}\n",
|
|
1199
1199
|
"marketing/nextjs/src/app/page.tsx.hbs": `export default function HomePage() {
|
|
1200
1200
|
return (
|
|
@@ -1524,7 +1524,7 @@ export const HeaderNav: React.FC<HeaderNavProps> = ({ data, position, className
|
|
|
1524
1524
|
"marketing/payload/src/app/(frontend)/api/docs-search/route.ts": 'import { getDocsFromConvex } from "@/lib/docs-source"\nimport { NextResponse } from "next/server"\n\n/**\n * Search API for documentation\n * Returns matching docs based on query\n */\nexport async function GET(request: Request) {\n const { searchParams } = new URL(request.url)\n const query = searchParams.get("q")?.toLowerCase() || ""\n\n if (!query || query.length < 2) {\n return NextResponse.json({ results: [] })\n }\n\n try {\n const docs = await getDocsFromConvex()\n\n // Simple search implementation\n const results = docs\n .filter((doc) => {\n const titleMatch = doc.title.toLowerCase().includes(query)\n const descriptionMatch = doc.description?.toLowerCase().includes(query)\n const contentMatch = doc.content.toLowerCase().includes(query)\n return titleMatch || descriptionMatch || contentMatch\n })\n .map((doc) => ({\n id: doc._id,\n title: doc.title,\n description: doc.description || "",\n url: `/docs/${doc.slug}`,\n // Extract a snippet from the content\n snippet: extractSnippet(doc.content, query),\n }))\n .slice(0, 10) // Limit results\n\n return NextResponse.json({ results })\n } catch (error) {\n console.error("Search error:", error)\n return NextResponse.json({ results: [], error: "Search failed" }, { status: 500 })\n }\n}\n\n/**\n * Extract a snippet around the search query\n */\nfunction extractSnippet(content: string, query: string): string {\n const lowerContent = content.toLowerCase()\n const index = lowerContent.indexOf(query)\n\n if (index === -1) {\n // Return first 150 chars if query not found in content\n return `${content.slice(0, 150).trim()}...`\n }\n\n // Get 50 chars before and 100 chars after the match\n const start = Math.max(0, index - 50)\n const end = Math.min(content.length, index + query.length + 100)\n\n let snippet = content.slice(start, end).trim()\n\n // Add ellipsis if needed\n if (start > 0) snippet = `...${snippet}`\n if (end < content.length) snippet = `${snippet}...`\n\n return snippet\n}\n',
|
|
1525
1525
|
"marketing/payload/src/app/(frontend)/api/newsletter/route.ts": 'import { NextResponse } from "next/server"\n\nconst RESEND_API_URL = "https://api.resend.com"\n\n/**\n * Email validation regex\n */\nconst EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n/**\n * Company address for CAN-SPAM compliance\n */\nconst COMPANY_ADDRESS = "KrumaLabs \u2022 102 West Main Street #501, New Albany, OH 43054"\n\n/**\n * SaaSify logo URL\n */\nconst LOGO_URL = "/logo.png"\n\n/**\n * Generate newsletter confirmation email HTML with logo and branding\n */\nfunction renderNewsletterConfirmationEmail(unsubscribeUrl?: string): string {\n const emailStyles = {\n main: `\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, \'Helvetica Neue\', Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n background-color: #f5f5f5;\n margin: 0;\n padding: 20px;\n `,\n container: `\n background-color: #ffffff;\n border-radius: 8px;\n margin: 0 auto;\n padding: 0;\n max-width: 600px;\n `,\n header: `\n padding: 32px 32px 24px;\n border-bottom: 1px solid #e5e5e5;\n `,\n logoText: `\n color: #0070f3;\n font-size: 24px;\n font-weight: 600;\n margin: 0;\n padding: 0;\n line-height: 1;\n `,\n heading: `\n color: #111111;\n font-size: 24px;\n font-weight: 600;\n line-height: 1.4;\n margin: 0 0 24px;\n `,\n content: `\n padding: 32px;\n `,\n paragraph: `\n font-size: 16px;\n color: #444444;\n margin: 0 0 16px;\n line-height: 1.6;\n `,\n paragraphSmall: `\n font-size: 14px;\n color: #666666;\n margin: 0 0 16px;\n line-height: 1.6;\n `,\n button: `\n background-color: #0070f3;\n color: white;\n padding: 14px 32px;\n text-decoration: none;\n border-radius: 6px;\n display: inline-block;\n font-weight: 500;\n font-size: 16px;\n `,\n footer: `\n padding: 24px 32px;\n text-align: center;\n `,\n footerText: `\n color: #666666;\n font-size: 14px;\n line-height: 1.6;\n margin: 0 0 8px;\n `,\n footerTextSmall: `\n color: #999999;\n font-size: 12px;\n line-height: 1.6;\n margin: 16px 0 0;\n `,\n footerAddress: `\n color: #999999;\n font-size: 11px;\n line-height: 1.6;\n margin: 8px 0 0;\n `,\n link: `\n color: #0070f3;\n text-decoration: underline;\n `,\n }\n\n return `\n<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n</head>\n<body style="${emailStyles.main}">\n <div style="${emailStyles.container}">\n <!-- Header with Logo -->\n <div style="${emailStyles.header}">\n <a href="/" style="display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: inherit;">\n <img src="${LOGO_URL}" alt="SaaSify" width="32" height="32" style="display: block; width: 32px; height: 32px;">\n <span style="${emailStyles.logoText}">SaaSify</span>\n </a>\n </div>\n \n <!-- Content -->\n <div style="padding: 32px 32px 0;"><h1 style="${emailStyles.heading}">Welcome to the Newsletter!</h1></div>\n <div style="${emailStyles.content}">\n <p style="${emailStyles.paragraph}">\n Thanks for subscribing to the SaaSify newsletter! \u{1F389}\n </p>\n <p style="${emailStyles.paragraph}">\n You\'ll now receive updates about:\n </p>\n <ul style="${emailStyles.paragraph}">\n <li>New features and product updates</li>\n <li>Tips for boosting team productivity</li>\n <li>Industry insights and best practices</li>\n <li>Special announcements and offers</li>\n </ul>\n <p style="${emailStyles.paragraph}">\n We respect your inbox and only send emails when we have something valuable to share.\n </p>\n <div style="margin: 32px 0; text-align: center;">\n <a href="/" style="${emailStyles.button}">Visit SaaSify</a>\n </div>\n <p style="${emailStyles.paragraphSmall}">\n If you didn\'t subscribe to this newsletter, you can safely ignore this email or\n <a href="${unsubscribeUrl || "/unsubscribe"}" style="${emailStyles.link}">unsubscribe here</a>.\n </p>\n </div>\n \n <!-- Divider -->\n <hr style="border: none; border-top: 1px solid #e5e5e5; margin: 0 32px;">\n \n <!-- Footer -->\n <div style="${emailStyles.footer}">\n <p style="${emailStyles.footerText}">SaaSify - The modern platform for growing teams</p>\n <p style="${emailStyles.footerText}">\n <a href="/" style="${emailStyles.link}">Visit our website</a>\n <span style="color: #999999;"> \u2022 </span>\n <a href="/support" style="${emailStyles.link}">Support</a>\n ${unsubscribeUrl ? `<span style="color: #999999;"> \u2022 </span><a href="${unsubscribeUrl}" style="${emailStyles.link}">Unsubscribe</a>` : ""}\n </p>\n <p style="${emailStyles.footerTextSmall}">You\'re receiving this email because you signed up for the SaaSify newsletter.</p>\n <p style="${emailStyles.footerAddress}">${COMPANY_ADDRESS}</p>\n </div>\n </div>\n</body>\n</html>`.trim()\n}\n\nexport async function POST(request: Request) {\n try {\n const body = await request.json()\n const { email } = body\n\n if (!email) {\n return NextResponse.json({ success: false, message: "Email is required." }, { status: 400 })\n }\n\n // Normalize and validate email\n const normalizedEmail = email.toLowerCase().trim()\n if (!EMAIL_REGEX.test(normalizedEmail)) {\n return NextResponse.json(\n { success: false, message: "Please enter a valid email address." },\n { status: 400 },\n )\n }\n\n const apiKey = process.env.RESEND_API_KEY\n const audienceId = process.env.RESEND_AUDIENCE_NEWSLETTER\n // Marketing emails sender - update with your domain\n const fromEmail = "SaaSify Team <hello@notifications.saasify.com>"\n\n // In development without API key, just return success\n if (!apiKey) {\n console.warn("RESEND_API_KEY not set - newsletter signup simulated")\n return NextResponse.json({\n success: true,\n message: "Thanks for subscribing! Check your inbox for a confirmation email.",\n })\n }\n\n // Call Convex newsletter subscribe action via HTTP\n // This ensures consistent handling and uses the proper addNewsletterSubscriber function\n const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL || process.env.CONVEX_URL\n if (!convexUrl) {\n console.warn("CONVEX_URL not set - newsletter signup will fail")\n return NextResponse.json(\n { success: false, message: "Server configuration error. Please try again later." },\n { status: 500 },\n )\n }\n\n try {\n const response = await fetch(`${convexUrl}/api/newsletter/subscribe`, {\n method: "POST",\n headers: {\n "Content-Type": "application/json",\n },\n body: JSON.stringify({\n email: normalizedEmail,\n }),\n })\n\n const result = await response.json()\n\n if (!result.success) {\n return NextResponse.json(result, { status: response.status })\n }\n\n return NextResponse.json(result)\n } catch (error) {\n console.error("Newsletter subscription error:", error)\n return NextResponse.json(\n { success: false, message: "Something went wrong. Please try again later." },\n { status: 500 },\n )\n }\n } catch (error) {\n console.error("Newsletter subscription error:", error)\n\n // Check if it\'s a duplicate subscriber error\n if (error instanceof Error && error.message.includes("already exists")) {\n return NextResponse.json({\n success: true,\n message: "You\'re already subscribed to our newsletter!",\n })\n }\n\n return NextResponse.json(\n { success: false, message: "Something went wrong. Please try again later." },\n { status: 500 },\n )\n }\n}\n',
|
|
1526
1526
|
"marketing/payload/src/app/(frontend)/api/pricing/route.ts": 'import { NextResponse } from "next/server"\nimport Stripe from "stripe"\n\n/**\n * Stripe Lookup Keys - defined in Stripe Dashboard for each price\n * These must match the lookup keys configured in your Stripe Dashboard\n */\nconst STRIPE_LOOKUP_KEYS = {\n free_monthly: "free_monthly",\n free_annual: "free_annual",\n pro_monthly: "pro_monthly",\n pro_annual: "pro_annual",\n business_monthly: "business_monthly",\n business_annual: "business_annual",\n} as const\n\n/**\n * Default product metadata when Stripe metadata is missing\n */\nconst DEFAULT_PRODUCT_INFO: Record<\n string,\n { description: string; popular: boolean; order: number }\n> = {\n free: { description: "Perfect for getting started", popular: false, order: 1 },\n pro: { description: "For growing businesses", popular: false, order: 2 },\n business: { description: "For teams and agencies", popular: true, order: 3 },\n}\n\n/**\n * Feature type from Stripe Entitlements\n */\ninterface PlanFeature {\n id: string\n lookupKey: string\n name: string\n metadata?: Record<string, string>\n}\n\n/**\n * All features type for comparison table\n */\ninterface AllFeature {\n id: string\n lookupKey: string\n name: string\n category?: string\n metadata?: Record<string, string>\n}\n\n/**\n * Plan pricing type with features from Stripe\n */\ninterface PlanPricing {\n planId: string\n stripeProductId: string\n name: string\n description: string\n features: PlanFeature[]\n monthlyPriceId?: string\n monthlyAmount: number\n annualPriceId?: string\n annualAmount: number\n annualDiscount: number\n popular: boolean\n order: number\n}\n\n/**\n * Fetch pricing and features from Stripe and return formatted data\n * GET /api/pricing\n *\n * Returns JSON with plan pricing and features for the marketing site\n */\nexport async function GET() {\n try {\n const stripeSecretKey = process.env.STRIPE_SECRET_KEY\n\n if (!stripeSecretKey) {\n return NextResponse.json(\n {\n plans: [],\n allFeatures: [],\n lastFetched: Date.now(),\n error: "Stripe not configured",\n },\n { status: 200 },\n )\n }\n\n const stripe = new Stripe(stripeSecretKey)\n\n // Fetch all features for comparison table\n const allFeatures: AllFeature[] = []\n try {\n const featuresResponse = await stripe.entitlements.features.list({ limit: 100 })\n for (const feature of featuresResponse.data) {\n allFeatures.push({\n id: feature.id,\n lookupKey: feature.lookup_key,\n name: feature.name,\n category: feature.metadata?.category,\n metadata: feature.metadata as Record<string, string> | undefined,\n })\n }\n } catch (err) {\n console.error("Error fetching Stripe features:", err)\n }\n\n // Fetch prices with product info\n const priceMap = new Map<string, { id: string; amount: number; productId: string }>()\n\n try {\n const allLookupKeys = Object.values(STRIPE_LOOKUP_KEYS)\n const prices = await stripe.prices.list({\n lookup_keys: allLookupKeys,\n active: true,\n expand: ["data.product"],\n limit: 20,\n })\n\n for (const price of prices.data) {\n if (price.lookup_key && price.unit_amount !== null) {\n const productId = typeof price.product === "string" ? price.product : price.product?.id\n if (productId) {\n priceMap.set(price.lookup_key, {\n id: price.id,\n amount: price.unit_amount,\n productId,\n })\n }\n }\n }\n } catch (stripeError) {\n console.error("Error fetching Stripe prices:", stripeError)\n }\n\n // Group prices by product\n const productPrices = new Map<\n string,\n { monthly?: { id: string; amount: number }; annual?: { id: string; amount: number } }\n >()\n\n for (const [lookupKey, priceData] of priceMap.entries()) {\n const isAnnual = lookupKey.endsWith("_annual")\n const existingPrices = productPrices.get(priceData.productId) || {}\n\n if (isAnnual) {\n existingPrices.annual = { id: priceData.id, amount: priceData.amount }\n } else {\n existingPrices.monthly = { id: priceData.id, amount: priceData.amount }\n }\n\n productPrices.set(priceData.productId, existingPrices)\n }\n\n // Build plans from products\n const plans: PlanPricing[] = []\n\n for (const [productId, prices] of productPrices.entries()) {\n // Fetch product details\n let product: Stripe.Product | null = null\n try {\n const fetched = await stripe.products.retrieve(productId)\n if (!fetched.deleted) {\n product = fetched\n }\n } catch (err) {\n console.error(`Error fetching product ${productId}:`, err)\n continue\n }\n\n if (!product) continue\n\n // Get plan ID from product metadata\n const planId = product.metadata?.plan_id\n if (!planId) {\n console.warn(`Product ${productId} missing plan_id metadata, skipping`)\n continue\n }\n\n // Fetch features for this product\n const features: PlanFeature[] = []\n try {\n const productFeatures = await stripe.products.listFeatures(productId, {\n limit: 100,\n })\n for (const pf of productFeatures.data) {\n features.push({\n id: pf.entitlement_feature.id,\n lookupKey: pf.entitlement_feature.lookup_key,\n name: pf.entitlement_feature.name,\n metadata: pf.entitlement_feature.metadata as Record<string, string> | undefined,\n })\n }\n } catch (err) {\n console.error(`Error fetching features for product ${productId}:`, err)\n }\n\n // Get metadata or use defaults\n const defaultInfo = DEFAULT_PRODUCT_INFO[planId] || {\n description: "",\n popular: false,\n order: 99,\n }\n const description =\n product.metadata?.description || product.description || defaultInfo.description\n const popular = product.metadata?.popular === "true" || defaultInfo.popular\n const order = Number.parseInt(product.metadata?.order || String(defaultInfo.order), 10)\n\n const monthlyAmount = prices.monthly?.amount ?? 0\n const annualAmount = prices.annual?.amount ?? 0\n\n // Calculate annual discount\n const yearlyMonthlyEquivalent = monthlyAmount * 12\n const annualDiscount =\n yearlyMonthlyEquivalent > 0\n ? Math.round(((yearlyMonthlyEquivalent - annualAmount) / yearlyMonthlyEquivalent) * 100)\n : 0\n\n plans.push({\n planId,\n stripeProductId: productId,\n name: product.name,\n description,\n features,\n monthlyPriceId: prices.monthly?.id,\n monthlyAmount,\n annualPriceId: prices.annual?.id,\n annualAmount,\n annualDiscount: Math.max(0, annualDiscount),\n popular,\n order,\n })\n }\n\n // Sort plans by order\n plans.sort((a, b) => a.order - b.order)\n\n return NextResponse.json(\n {\n plans,\n allFeatures,\n lastFetched: Date.now(),\n },\n {\n status: 200,\n headers: {\n // Cache for 1 hour on CDN, revalidate in background\n "Cache-Control": "public, s-maxage=3600, stale-while-revalidate=7200",\n },\n },\n )\n } catch (error) {\n console.error("Pricing API error:", error)\n\n return NextResponse.json(\n {\n plans: [],\n allFeatures: [],\n lastFetched: Date.now(),\n error: "Failed to fetch pricing",\n },\n { status: 200 },\n )\n }\n}\n',
|
|
1527
|
-
"marketing/payload/src/app/(frontend)/globals.css": '@import "tailwindcss";\n@import "tw-animate-css";\n@plugin "@tailwindcss/typography";\n\n@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));\n\n@theme {\n /* Colors */\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n\n --color-border: hsla(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n\n --color-success: hsl(var(--success));\n --color-warning: hsl(var(--warning));\n --color-error: hsl(var(--error));\n\n /* Border radius */\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n\n /* Fonts */\n --font-sans: var(--font-inter), system-ui, sans-serif;\n --font-mono: var(--font-geist-mono), monospace;\n\n /* Container - matching web app */\n --container-sm: 40rem;\n --container-md: 48rem;\n --container-lg: 64rem;\n --container-xl: 80rem;\n --container-2xl: 96rem;\n\n /* Animations */\n --animate-accordion-down: accordion-down 0.2s ease-out;\n --animate-accordion-up: accordion-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n from {\n height: 0;\n }\n to {\n height: var(--radix-accordion-content-height);\n }\n}\n\n@keyframes accordion-up {\n from {\n height: var(--radix-accordion-content-height);\n }\n to {\n height: 0;\n }\n}\n\n:root {\n --background: 0 0% 98%; /* #f7f9fc */\n --foreground: 220 59% 15%; /* #0f1f3d */\n\n --card: 217 46% 96%; /* #e9eff8 */\n --card-foreground: 220 59% 15%; /* #0f1f3d */\n\n --popover: 0 0% 100%;\n --popover-foreground: 220 59% 15%;\n\n --primary: 220 59% 15%; /* navy */\n --primary-foreground: 0 0% 100%;\n\n --secondary: 173 55% 32%; /* darker teal for WCAG AA contrast */\n --secondary-foreground: 220 59% 15%;\n\n --muted: 217 46% 96%; /* mist */\n --muted-foreground: 220 20% 25%; /* darkened further for WCAG AA on card backgrounds */\n\n --accent: 213 35% 95%; /* soft accent */\n --accent-foreground: 220 59% 15%;\n\n --destructive: 0 68% 65%; /* #e76a6a */\n --destructive-foreground: 0 0% 100%;\n\n --border: 216 23% 89%; /* #e1e6ef */\n --input: 216 23% 89%;\n --ring: 220 59% 15%;\n\n --radius: 0.75rem;\n\n --success: 157 48% 47%; /* #3fae8c */\n --warning: 41 54% 62%; /* #d9b36a */\n --error: 0 68% 65%; /* #e76a6a */\n}\n\n[data-theme="dark"] {\n --background: 219 53% 12%; /* #0b162c */\n --foreground: 216 33% 93%; /* #f7f9fc */\n\n --card: 220 52% 11%; /* #101c32 */\n --card-foreground: 216 33% 93%;\n\n --popover: 220 52% 11%;\n --popover-foreground: 216 33% 93%;\n\n --primary: 220 59% 15%;\n --primary-foreground: 0 0% 100%;\n\n --secondary: 173 46% 44%;\n --secondary-foreground: 219 53% 12%;\n\n --muted: 221 53% 12%;\n --muted-foreground: 217 23% 75%; /* improved contrast for WCAG AA */\n\n --accent: 222 44% 16%;\n --accent-foreground: 216 33% 93%;\n\n --destructive: 0 70% 71%;\n --destructive-foreground: 219 53% 12%;\n\n --border: 222 30% 21%;\n --input: 222 30% 21%;\n --ring: 173 46% 44%;\n\n --success: 157 48% 47%;\n --warning: 41 54% 62%;\n --error: 0 70% 71%;\n}\n\n* {\n border-color: var(--color-border);\n}\n\nbody {\n background-color: var(--color-background);\n color: var(--color-foreground);\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\nhtml {\n opacity: 0;\n}\n\nhtml[data-theme="dark"],\nhtml[data-theme="light"] {\n opacity: initial;\n}\n\n/* Container utility - matching web app */\n.container {\n width: 100%;\n margin-left: auto;\n margin-right: auto;\n padding-left: 1rem;\n padding-right: 1rem;\n max-width: 96rem;\n}\n\n/* Hero typography - matching web app exactly */\n.hero-content h1 {\n font-size: 2.25rem !important; /* text-4xl */\n line-height: 2.5rem !important; /* text-4xl line-height */\n font-weight: 700 !important; /* font-bold */\n letter-spacing: -0.025em !important; /* tracking-tight */\n margin-bottom: 1.5rem !important; /* mb-6 */\n color: hsl(var(--foreground)) !important;\n}\n\n.hero-content p {\n font-size: 1.25rem !important; /* text-xl */\n line-height: 1.75rem !important; /* text-xl line-height */\n color: hsl(var(--muted-foreground)) !important;\n max-width: 42rem; /* max-w-2xl */\n margin-left: auto;\n margin-right: auto;\n margin-bottom: 2rem !important; /* mb-8 */\n}\n\n.hero-content--dark h1 {\n color: white !important;\n}\n\n.hero-content--dark p {\n color: rgba(255, 255, 255, 0.8) !important;\n}\n\n@media (min-width: 768px) {\n .hero-content h1 {\n font-size: 3.75rem !important; /* md:text-6xl */\n line-height: 1 !important; /* text-6xl line-height */\n }\n}\n\n@media (min-width: 640px) {\n .container {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .container {\n padding-left: 2rem;\n padding-right: 2rem;\n }\n}\n\n/* ========================================\n PRODUCT SHOWCASE HERO STYLES\n ======================================== */\n\n/* Left-aligned hero content */\n.hero-content--left h1 {\n text-align: left !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n.hero-content--left p {\n text-align: left !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n/* Hero showcase section */\n.hero-showcase {\n position: relative;\n border-radius: 12px;\n overflow: hidden;\n padding: 3rem;\n min-height: 500px;\n}\n\n@media (min-width: 768px) {\n .hero-showcase {\n min-height: 600px;\n }\n}\n\n@media (min-width: 1024px) {\n .hero-showcase {\n min-height: 700px;\n }\n}\n\n/* Hero background image */\n.hero-bg-image {\n position: absolute;\n inset: 0;\n z-index: 0;\n}\n\n.hero-bg-image img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n object-position: center;\n}\n\n/* Mockup centered within background */\n.hero-mockup-centered {\n position: relative;\n z-index: 10;\n max-width: 800px;\n margin: 0 auto;\n width: 100%;\n}\n\n@media (min-width: 768px) {\n .hero-mockup-centered {\n max-width: 900px;\n }\n}\n\n@media (min-width: 1024px) {\n .hero-mockup-centered {\n max-width: 1000px;\n }\n}\n\n.mockup-wrapper {\n background: hsl(var(--background));\n border-radius: 12px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 12px 24px -8px rgba(0, 0, 0, 0.15), 0 0 0 1px\n rgba(0, 0, 0, 0.05);\n overflow: hidden;\n animation: mockup-entrance 0.8s ease-out;\n width: 100%;\n}\n\n.mockup-wrapper img {\n width: 100%;\n height: auto;\n display: block;\n}\n\n@keyframes mockup-entrance {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Browser chrome */\n.mockup-chrome {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n background: hsl(var(--muted));\n border-bottom: 1px solid hsl(var(--border));\n}\n\n.mockup-chrome-dots {\n display: flex;\n gap: 6px;\n}\n\n.mockup-chrome-dots .dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n}\n\n.mockup-chrome-dots .dot-red {\n background: #ff5f56;\n}\n.mockup-chrome-dots .dot-yellow {\n background: #ffbd2e;\n}\n.mockup-chrome-dots .dot-green {\n background: #27ca40;\n}\n\n.mockup-chrome-title {\n flex: 1;\n text-align: center;\n font-size: 13px;\n font-weight: 500;\n color: hsl(var(--muted-foreground));\n}\n\n.mockup-chrome-actions {\n width: 60px;\n}\n\n/* App content layout */\n.mockup-content {\n display: flex;\n min-height: 400px;\n}\n\n.mockup-sidebar {\n width: 220px;\n background: hsl(var(--card));\n border-right: 1px solid hsl(var(--border));\n flex-shrink: 0;\n}\n\n.sidebar-header {\n padding: 16px;\n border-bottom: 1px solid hsl(var(--border));\n}\n\n.sidebar-logo {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.logo-icon {\n width: 28px;\n height: 28px;\n background: hsl(var(--primary));\n color: white;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 14px;\n}\n\n.logo-text {\n font-weight: 600;\n font-size: 14px;\n color: hsl(var(--foreground));\n}\n\n.sidebar-nav {\n padding: 8px;\n}\n\n.sidebar-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 6px;\n font-size: 13px;\n color: hsl(var(--muted-foreground));\n transition: all 0.15s ease;\n cursor: pointer;\n}\n\n.sidebar-item:hover {\n background: hsl(var(--accent));\n color: hsl(var(--accent-foreground));\n}\n\n.sidebar-item--active {\n background: hsl(var(--primary) / 0.12);\n color: hsl(var(--primary));\n}\n\n.sidebar-icon {\n font-size: 16px;\n}\n\n.sidebar-label {\n flex: 1;\n}\n\n.sidebar-badge {\n background: hsl(var(--primary));\n color: hsl(var(--primary-foreground));\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 10px;\n font-weight: 500;\n}\n\n/* Main content area */\n.mockup-main {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: hsl(var(--background));\n}\n\n.main-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid hsl(var(--border));\n}\n\n.header-title {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.header-title h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 0;\n color: hsl(var(--foreground));\n}\n\n.header-breadcrumb {\n font-size: 12px;\n color: hsl(var(--muted-foreground));\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.action-btn {\n padding: 8px 16px;\n background: hsl(var(--primary));\n color: hsl(var(--primary-foreground));\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.action-btn--success {\n background: #27ca40;\n}\n\n.action-btn--featured {\n background: hsl(var(--primary));\n}\n\n/* Split view */\n.main-split {\n display: flex;\n flex: 1;\n}\n\n.editor-panel {\n flex: 1;\n padding: 20px;\n border-right: 1px solid hsl(var(--border));\n}\n\n.editor-section {\n margin-bottom: 20px;\n}\n\n.editor-label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: hsl(var(--muted-foreground));\n margin-bottom: 6px;\n}\n\n.editor-input {\n background: hsl(var(--muted));\n border: 1px solid hsl(var(--border));\n border-radius: 6px;\n padding: 10px 12px;\n font-size: 14px;\n color: hsl(var(--foreground));\n display: flex;\n align-items: center;\n}\n\n.input-text {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.input-cursor {\n width: 2px;\n height: 18px;\n background: #6c4cff;\n animation: blink 1s infinite;\n margin-left: 2px;\n}\n\n@keyframes blink {\n 0%,\n 50% {\n opacity: 1;\n }\n 51%,\n 100% {\n opacity: 0;\n }\n}\n\n.editor-select {\n background: hsl(var(--muted));\n border: 1px solid hsl(var(--border));\n border-radius: 6px;\n padding: 10px 12px;\n font-size: 14px;\n color: hsl(var(--foreground));\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.select-arrow {\n font-size: 10px;\n color: hsl(var(--muted-foreground));\n}\n\n.editor-textarea {\n background: hsl(var(--muted));\n border: 1px solid hsl(var(--border));\n border-radius: 6px;\n padding: 10px 12px;\n font-size: 14px;\n color: hsl(var(--foreground));\n min-height: 80px;\n}\n\n.textarea-text {\n transition: all 0.5s ease;\n}\n\n.textarea-text--complete {\n color: hsl(var(--foreground));\n}\n\n/* Preview panel */\n.preview-panel {\n width: 320px;\n padding: 20px;\n background: hsl(var(--muted) / 0.5);\n}\n\n.preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.preview-label {\n font-size: 12px;\n font-weight: 500;\n color: hsl(var(--muted-foreground));\n}\n\n.preview-url {\n font-size: 11px;\n color: hsl(var(--muted-foreground));\n font-family: monospace;\n}\n\n.preview-card {\n background: hsl(var(--card));\n border: 1px solid hsl(var(--border));\n border-radius: 10px;\n overflow: hidden;\n position: relative;\n transition: all 0.3s ease;\n}\n\n.preview-badge {\n position: absolute;\n top: 10px;\n right: 10px;\n background: hsl(var(--primary));\n color: white;\n font-size: 11px;\n padding: 4px 8px;\n border-radius: 4px;\n font-weight: 500;\n animation: badge-pop 0.3s ease;\n}\n\n@keyframes badge-pop {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.preview-image {\n height: 120px;\n background: linear-gradient(135deg, hsl(var(--muted)) 0%, hsl(var(--accent)) 100%);\n}\n\n.preview-image-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 40px;\n}\n\n.preview-content {\n padding: 16px;\n}\n\n.preview-category-tag {\n display: inline-block;\n font-size: 11px;\n color: hsl(var(--primary));\n font-weight: 500;\n margin-bottom: 8px;\n}\n\n.preview-title {\n font-size: 16px;\n font-weight: 600;\n margin: 0 0 8px;\n color: hsl(var(--foreground));\n}\n\n.preview-description {\n font-size: 13px;\n color: hsl(var(--muted-foreground));\n line-height: 1.5;\n margin: 0 0 12px;\n}\n\n.preview-meta {\n display: flex;\n gap: 8px;\n font-size: 12px;\n}\n\n.meta-rating {\n color: #ffc24a;\n}\n\n.meta-reviews {\n color: hsl(var(--muted-foreground));\n}\n\n/* State indicators */\n.mockup-indicators {\n display: flex;\n justify-content: center;\n gap: 24px;\n padding: 16px;\n border-top: 1px solid hsl(var(--border));\n}\n\n.indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px 12px;\n border-radius: 20px;\n transition: all 0.2s ease;\n}\n\n.indicator:hover {\n background: hsl(var(--accent));\n}\n\n.indicator--active {\n background: hsl(var(--primary) / 0.12);\n}\n\n.indicator-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: hsl(var(--muted-foreground));\n transition: all 0.2s ease;\n}\n\n.indicator--active .indicator-dot {\n background: hsl(var(--primary));\n box-shadow: 0 0 0 3px hsl(var(--primary) / 0.2);\n}\n\n.indicator-label {\n font-size: 12px;\n color: hsl(var(--muted-foreground));\n}\n\n.indicator--active .indicator-label {\n color: hsl(var(--foreground));\n font-weight: 500;\n}\n\n/* ========================================\n LOGO BANNER STYLES\n ======================================== */\n\n.logo-scroll-container {\n overflow: hidden;\n mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);\n}\n\n.logo-scroll-track {\n display: flex;\n animation: logo-scroll 30s linear infinite;\n}\n\n.logo-scroll-track:hover {\n animation-play-state: paused;\n}\n\n@keyframes logo-scroll {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(-50%);\n }\n}\n\n.logo-item {\n flex-shrink: 0;\n min-width: 150px;\n}\n\n/* ========================================\n RESPONSIVE ADJUSTMENTS\n ======================================== */\n\n@media (max-width: 768px) {\n .mockup-content {\n flex-direction: column;\n }\n\n .mockup-sidebar {\n width: 100%;\n border-right: none;\n border-bottom: 1px solid hsl(var(--border));\n }\n\n .sidebar-nav {\n display: flex;\n overflow-x: auto;\n padding: 8px;\n gap: 4px;\n }\n\n .sidebar-item {\n white-space: nowrap;\n }\n\n .main-split {\n flex-direction: column;\n }\n\n .editor-panel {\n border-right: none;\n border-bottom: 1px solid hsl(var(--border));\n }\n\n .preview-panel {\n width: 100%;\n }\n\n .mockup-indicators {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .indicator-label {\n display: none;\n }\n}\n\n/* ========================================\n BIRD-INSPIRED BLOCK STYLES\n ======================================== */\n\n/* Industry Tabs Animation */\n.industry-tab-content {\n animation: tab-fade-in 0.3s ease-out;\n}\n\n@keyframes tab-fade-in {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Feature Showcase Entrance Animation */\n@keyframes feature-slide-in {\n from {\n opacity: 0;\n transform: translateX(-20px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n\n.feature-showcase-content {\n animation: feature-slide-in 0.5s ease-out;\n}\n\n/* Testimonial Card Hover Effects */\n.testimonial-card {\n transition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.testimonial-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);\n}\n\n/* Stat Number Animation */\n@keyframes stat-count-up {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.stat-number {\n animation: stat-count-up 0.6s ease-out;\n}\n\n/* Trust Column Icon Animation */\n.trust-icon {\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.trust-icon:hover {\n transform: scale(1.1);\n}\n\n/* Final CTA Background Animation */\n@keyframes subtle-float {\n 0%,\n 100% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-10px);\n }\n}\n\n.cta-decorative {\n animation: subtle-float 6s ease-in-out infinite;\n}\n\n/* Feature Grid Card Entrance */\n@keyframes card-entrance {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.feature-card {\n animation: card-entrance 0.4s ease-out;\n animation-fill-mode: both;\n}\n\n.feature-card:nth-child(1) {\n animation-delay: 0.1s;\n}\n.feature-card:nth-child(2) {\n animation-delay: 0.2s;\n}\n.feature-card:nth-child(3) {\n animation-delay: 0.3s;\n}\n.feature-card:nth-child(4) {\n animation-delay: 0.4s;\n}\n.feature-card:nth-child(5) {\n animation-delay: 0.5s;\n}\n.feature-card:nth-child(6) {\n animation-delay: 0.6s;\n}\n\n/* Smooth Section Transitions */\nsection {\n scroll-margin-top: 80px;\n}\n\n/* Button Hover Enhancement */\n.cta-button {\n position: relative;\n overflow: hidden;\n}\n\n.cta-button::after {\n content: "";\n position: absolute;\n inset: 0;\n background: linear-gradient(rgba(255, 255, 255, 0.1), transparent);\n opacity: 0;\n transition: opacity 0.3s ease;\n}\n\n.cta-button:hover::after {\n opacity: 1;\n}\n\n/* Responsive Image Container */\n.feature-image-container {\n position: relative;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15);\n transition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.feature-image-container:hover {\n transform: translateY(-4px);\n box-shadow: 0 30px 60px -15px rgba(0, 0, 0, 0.2);\n}\n',
|
|
1527
|
+
"marketing/payload/src/app/(frontend)/globals.css.hbs": '@import "tailwindcss";\n@import "tw-animate-css";\n@plugin "@tailwindcss/typography";\n\n@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));\n\n@theme inline {\n /* Colors */\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n\n --color-destructive: var(--destructive);\n\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n\n --color-chart-1: var(--chart-1);\n --color-chart-2: var(--chart-2);\n --color-chart-3: var(--chart-3);\n --color-chart-4: var(--chart-4);\n --color-chart-5: var(--chart-5);\n\n /* Border radius */\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n\n /* Fonts */\n --font-sans: var(--font-inter), system-ui, sans-serif;\n --font-mono: var(--font-geist-mono), monospace;\n\n /* Container */\n --container-sm: 40rem;\n --container-md: 48rem;\n --container-lg: 64rem;\n --container-xl: 80rem;\n --container-2xl: 96rem;\n\n /* Animations */\n --animate-accordion-down: accordion-down 0.2s ease-out;\n --animate-accordion-up: accordion-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n from {\n height: 0;\n }\n to {\n height: var(--radix-accordion-content-height);\n }\n}\n\n@keyframes accordion-up {\n from {\n height: var(--radix-accordion-content-height);\n }\n to {\n height: 0;\n }\n}\n\n/* ========================================\n THEME COLOR VARIABLES\n Each theme color changes --primary, --ring, and --chart-* values\n Base colors (background, card, muted, etc.) remain consistent\n ======================================== */\n\n:root {\n --radius: 0.625rem;\n --background: oklch(1 0 0);\n --foreground: oklch(0.145 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.145 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.145 0 0);\n --secondary: oklch(0.97 0 0);\n --secondary-foreground: oklch(0.205 0 0);\n --muted: oklch(0.97 0 0);\n --muted-foreground: oklch(0.556 0 0);\n --accent: oklch(0.97 0 0);\n --accent-foreground: oklch(0.205 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --border: oklch(0.922 0 0);\n --input: oklch(0.922 0 0);\n\n{{#if (eq shadcn.themeColor "neutral")}}\n /* Neutral theme */\n --primary: oklch(0.205 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.646 0.222 41.116);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "blue")}}\n /* Blue theme */\n --primary: oklch(0.546 0.245 262.881);\n --primary-foreground: oklch(0.985 0.002 247.858);\n --ring: oklch(0.546 0.245 262.881);\n --chart-1: oklch(0.546 0.245 262.881);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "green")}}\n /* Green theme */\n --primary: oklch(0.596 0.145 163.225);\n --primary-foreground: oklch(0.982 0.018 155.826);\n --ring: oklch(0.596 0.145 163.225);\n --chart-1: oklch(0.596 0.145 163.225);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "purple")}}\n /* Purple theme */\n --primary: oklch(0.627 0.265 303.9);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.627 0.265 303.9);\n --chart-1: oklch(0.627 0.265 303.9);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "red")}}\n /* Red theme */\n --primary: oklch(0.637 0.237 25.331);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.637 0.237 25.331);\n --chart-1: oklch(0.637 0.237 25.331);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "orange")}}\n /* Orange theme */\n --primary: oklch(0.705 0.191 47.604);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.705 0.191 47.604);\n --chart-1: oklch(0.705 0.191 47.604);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "amber")}}\n /* Amber theme */\n --primary: oklch(0.769 0.188 70.08);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.769 0.188 70.08);\n --chart-1: oklch(0.769 0.188 70.08);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.646 0.222 41.116);\n{{else if (eq shadcn.themeColor "cyan")}}\n /* Cyan theme */\n --primary: oklch(0.715 0.143 215.221);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.715 0.143 215.221);\n --chart-1: oklch(0.715 0.143 215.221);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "emerald")}}\n /* Emerald theme */\n --primary: oklch(0.696 0.17 162.48);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.696 0.17 162.48);\n --chart-1: oklch(0.696 0.17 162.48);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "fuchsia")}}\n /* Fuchsia theme */\n --primary: oklch(0.667 0.295 322.15);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.667 0.295 322.15);\n --chart-1: oklch(0.667 0.295 322.15);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "indigo")}}\n /* Indigo theme */\n --primary: oklch(0.585 0.233 277.117);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.585 0.233 277.117);\n --chart-1: oklch(0.585 0.233 277.117);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "lime")}}\n /* Lime theme */\n --primary: oklch(0.768 0.233 130.85);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.768 0.233 130.85);\n --chart-1: oklch(0.768 0.233 130.85);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "pink")}}\n /* Pink theme */\n --primary: oklch(0.718 0.202 349.761);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.718 0.202 349.761);\n --chart-1: oklch(0.718 0.202 349.761);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "rose")}}\n /* Rose theme */\n --primary: oklch(0.645 0.246 16.439);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.645 0.246 16.439);\n --chart-1: oklch(0.645 0.246 16.439);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "sky")}}\n /* Sky theme */\n --primary: oklch(0.685 0.169 237.323);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.685 0.169 237.323);\n --chart-1: oklch(0.685 0.169 237.323);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "teal")}}\n /* Teal theme */\n --primary: oklch(0.704 0.14 182.503);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.704 0.14 182.503);\n --chart-1: oklch(0.704 0.14 182.503);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "violet")}}\n /* Violet theme */\n --primary: oklch(0.606 0.25 292.717);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.606 0.25 292.717);\n --chart-1: oklch(0.606 0.25 292.717);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor "yellow")}}\n /* Yellow theme */\n --primary: oklch(0.795 0.184 86.047);\n --primary-foreground: oklch(0.216 0.006 56.043);\n --ring: oklch(0.795 0.184 86.047);\n --chart-1: oklch(0.795 0.184 86.047);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.646 0.222 41.116);\n --chart-5: oklch(0.769 0.188 70.08);\n{{else}}\n /* Default to neutral */\n --primary: oklch(0.205 0 0);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.646 0.222 41.116);\n --chart-2: oklch(0.6 0.118 184.704);\n --chart-3: oklch(0.398 0.07 227.392);\n --chart-4: oklch(0.828 0.189 84.429);\n --chart-5: oklch(0.769 0.188 70.08);\n{{/if}}\n}\n\n[data-theme="dark"] {\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.269 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.371 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --border: oklch(1 0 0 / 10%);\n --input: oklch(1 0 0 / 15%);\n\n{{#if (eq shadcn.themeColor "neutral")}}\n /* Neutral theme - dark mode */\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --ring: oklch(0.556 0 0);\n --chart-1: oklch(0.488 0.243 264.376);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "blue")}}\n /* Blue theme - dark mode */\n --primary: oklch(0.623 0.214 262.881);\n --primary-foreground: oklch(0.273 0.033 256.848);\n --ring: oklch(0.623 0.214 262.881);\n --chart-1: oklch(0.623 0.214 262.881);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "green")}}\n /* Green theme - dark mode */\n --primary: oklch(0.696 0.17 162.48);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.696 0.17 162.48);\n --chart-1: oklch(0.696 0.17 162.48);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "purple")}}\n /* Purple theme - dark mode */\n --primary: oklch(0.714 0.203 305.504);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.714 0.203 305.504);\n --chart-1: oklch(0.714 0.203 305.504);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.488 0.243 264.376);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "red")}}\n /* Red theme - dark mode */\n --primary: oklch(0.704 0.191 22.216);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.704 0.191 22.216);\n --chart-1: oklch(0.704 0.191 22.216);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor "orange")}}\n /* Orange theme - dark mode */\n --primary: oklch(0.792 0.17 52.615);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.792 0.17 52.615);\n --chart-1: oklch(0.792 0.17 52.615);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "amber")}}\n /* Amber theme - dark mode */\n --primary: oklch(0.828 0.189 84.429);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.828 0.189 84.429);\n --chart-1: oklch(0.828 0.189 84.429);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.488 0.243 264.376);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "cyan")}}\n /* Cyan theme - dark mode */\n --primary: oklch(0.789 0.154 211.53);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.789 0.154 211.53);\n --chart-1: oklch(0.789 0.154 211.53);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "emerald")}}\n /* Emerald theme - dark mode */\n --primary: oklch(0.765 0.166 160.391);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.765 0.166 160.391);\n --chart-1: oklch(0.765 0.166 160.391);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "fuchsia")}}\n /* Fuchsia theme - dark mode */\n --primary: oklch(0.74 0.238 322.16);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.74 0.238 322.16);\n --chart-1: oklch(0.74 0.238 322.16);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.488 0.243 264.376);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "indigo")}}\n /* Indigo theme - dark mode */\n --primary: oklch(0.673 0.182 276.935);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.673 0.182 276.935);\n --chart-1: oklch(0.673 0.182 276.935);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "lime")}}\n /* Lime theme - dark mode */\n --primary: oklch(0.841 0.238 128.85);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.841 0.238 128.85);\n --chart-1: oklch(0.841 0.238 128.85);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "pink")}}\n /* Pink theme - dark mode */\n --primary: oklch(0.775 0.181 349.761);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.775 0.181 349.761);\n --chart-1: oklch(0.775 0.181 349.761);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor "rose")}}\n /* Rose theme - dark mode */\n --primary: oklch(0.712 0.194 13.428);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.712 0.194 13.428);\n --chart-1: oklch(0.712 0.194 13.428);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor "sky")}}\n /* Sky theme - dark mode */\n --primary: oklch(0.756 0.143 232.661);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.756 0.143 232.661);\n --chart-1: oklch(0.756 0.143 232.661);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "teal")}}\n /* Teal theme - dark mode */\n --primary: oklch(0.777 0.152 181.912);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.777 0.152 181.912);\n --chart-1: oklch(0.777 0.152 181.912);\n --chart-2: oklch(0.488 0.243 264.376);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "violet")}}\n /* Violet theme - dark mode */\n --primary: oklch(0.702 0.183 293.541);\n --primary-foreground: oklch(0.985 0 0);\n --ring: oklch(0.702 0.183 293.541);\n --chart-1: oklch(0.702 0.183 293.541);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.488 0.243 264.376);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor "yellow")}}\n /* Yellow theme - dark mode */\n --primary: oklch(0.852 0.199 91.936);\n --primary-foreground: oklch(0.15 0 0);\n --ring: oklch(0.852 0.199 91.936);\n --chart-1: oklch(0.852 0.199 91.936);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.488 0.243 264.376);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{else}}\n /* Default to neutral - dark mode */\n --primary: oklch(0.922 0 0);\n --primary-foreground: oklch(0.205 0 0);\n --ring: oklch(0.556 0 0);\n --chart-1: oklch(0.488 0.243 264.376);\n --chart-2: oklch(0.696 0.17 162.48);\n --chart-3: oklch(0.769 0.188 70.08);\n --chart-4: oklch(0.627 0.265 303.9);\n --chart-5: oklch(0.645 0.246 16.439);\n{{/if}}\n}\n\n/* ========================================\n BASE STYLES\n ======================================== */\n\n* {\n border-color: var(--color-border);\n}\n\nbody {\n background-color: var(--color-background);\n color: var(--color-foreground);\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n}\n\nhtml {\n opacity: 0;\n}\n\nhtml[data-theme="dark"],\nhtml[data-theme="light"] {\n opacity: initial;\n}\n\n/* Container utility */\n.container {\n width: 100%;\n margin-left: auto;\n margin-right: auto;\n padding-left: 1rem;\n padding-right: 1rem;\n max-width: 96rem;\n}\n\n@media (min-width: 640px) {\n .container {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n .container {\n padding-left: 2rem;\n padding-right: 2rem;\n }\n}\n\n/* ========================================\n HERO TYPOGRAPHY\n ======================================== */\n\n.hero-content h1 {\n font-size: 2.25rem !important;\n line-height: 2.5rem !important;\n font-weight: 700 !important;\n letter-spacing: -0.025em !important;\n margin-bottom: 1.5rem !important;\n color: var(--color-foreground) !important;\n}\n\n.hero-content p {\n font-size: 1.25rem !important;\n line-height: 1.75rem !important;\n color: var(--color-muted-foreground) !important;\n max-width: 42rem;\n margin-left: auto;\n margin-right: auto;\n margin-bottom: 2rem !important;\n}\n\n.hero-content--dark h1 {\n color: white !important;\n}\n\n.hero-content--dark p {\n color: rgba(255, 255, 255, 0.8) !important;\n}\n\n@media (min-width: 768px) {\n .hero-content h1 {\n font-size: 3.75rem !important;\n line-height: 1 !important;\n }\n}\n\n/* Left-aligned hero content */\n.hero-content--left h1 {\n text-align: left !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n.hero-content--left p {\n text-align: left !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n}\n\n/* ========================================\n PRODUCT SHOWCASE HERO STYLES\n ======================================== */\n\n.hero-showcase {\n position: relative;\n border-radius: 12px;\n overflow: hidden;\n padding: 3rem;\n min-height: 500px;\n}\n\n@media (min-width: 768px) {\n .hero-showcase {\n min-height: 600px;\n }\n}\n\n@media (min-width: 1024px) {\n .hero-showcase {\n min-height: 700px;\n }\n}\n\n.hero-bg-image {\n position: absolute;\n inset: 0;\n z-index: 0;\n}\n\n.hero-bg-image img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n object-position: center;\n}\n\n.hero-mockup-centered {\n position: relative;\n z-index: 10;\n max-width: 800px;\n margin: 0 auto;\n width: 100%;\n}\n\n@media (min-width: 768px) {\n .hero-mockup-centered {\n max-width: 900px;\n }\n}\n\n@media (min-width: 1024px) {\n .hero-mockup-centered {\n max-width: 1000px;\n }\n}\n\n.mockup-wrapper {\n background: var(--color-background);\n border-radius: 12px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 12px 24px -8px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05);\n overflow: hidden;\n animation: mockup-entrance 0.8s ease-out;\n width: 100%;\n}\n\n.mockup-wrapper img {\n width: 100%;\n height: auto;\n display: block;\n}\n\n@keyframes mockup-entrance {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Browser chrome */\n.mockup-chrome {\n display: flex;\n align-items: center;\n padding: 12px 16px;\n background: var(--color-muted);\n border-bottom: 1px solid var(--color-border);\n}\n\n.mockup-chrome-dots {\n display: flex;\n gap: 6px;\n}\n\n.mockup-chrome-dots .dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n}\n\n.mockup-chrome-dots .dot-red {\n background: #ff5f56;\n}\n.mockup-chrome-dots .dot-yellow {\n background: #ffbd2e;\n}\n.mockup-chrome-dots .dot-green {\n background: #27ca40;\n}\n\n.mockup-chrome-title {\n flex: 1;\n text-align: center;\n font-size: 13px;\n font-weight: 500;\n color: var(--color-muted-foreground);\n}\n\n.mockup-chrome-actions {\n width: 60px;\n}\n\n/* App content layout */\n.mockup-content {\n display: flex;\n min-height: 400px;\n}\n\n.mockup-sidebar {\n width: 220px;\n background: var(--color-card);\n border-right: 1px solid var(--color-border);\n flex-shrink: 0;\n}\n\n.sidebar-header {\n padding: 16px;\n border-bottom: 1px solid var(--color-border);\n}\n\n.sidebar-logo {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.logo-icon {\n width: 28px;\n height: 28px;\n background: var(--color-primary);\n color: white;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 14px;\n}\n\n.logo-text {\n font-weight: 600;\n font-size: 14px;\n color: var(--color-foreground);\n}\n\n.sidebar-nav {\n padding: 8px;\n}\n\n.sidebar-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--color-muted-foreground);\n transition: all 0.15s ease;\n cursor: pointer;\n}\n\n.sidebar-item:hover {\n background: var(--color-accent);\n color: var(--color-accent-foreground);\n}\n\n.sidebar-item--active {\n background: oklch(from var(--color-primary) l c h / 0.12);\n color: var(--color-primary);\n}\n\n.sidebar-icon {\n font-size: 16px;\n}\n\n.sidebar-label {\n flex: 1;\n}\n\n.sidebar-badge {\n background: var(--color-primary);\n color: var(--color-primary-foreground);\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 10px;\n font-weight: 500;\n}\n\n/* Main content area */\n.mockup-main {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--color-background);\n}\n\n.main-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--color-border);\n}\n\n.header-title {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.header-title h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 0;\n color: var(--color-foreground);\n}\n\n.header-breadcrumb {\n font-size: 12px;\n color: var(--color-muted-foreground);\n}\n\n.header-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.action-btn {\n padding: 8px 16px;\n background: var(--color-primary);\n color: var(--color-primary-foreground);\n border: none;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.action-btn--success {\n background: #27ca40;\n}\n\n.action-btn--featured {\n background: var(--color-primary);\n}\n\n/* Split view */\n.main-split {\n display: flex;\n flex: 1;\n}\n\n.editor-panel {\n flex: 1;\n padding: 20px;\n border-right: 1px solid var(--color-border);\n}\n\n.editor-section {\n margin-bottom: 20px;\n}\n\n.editor-label {\n display: block;\n font-size: 12px;\n font-weight: 500;\n color: var(--color-muted-foreground);\n margin-bottom: 6px;\n}\n\n.editor-input {\n background: var(--color-muted);\n border: 1px solid var(--color-border);\n border-radius: 6px;\n padding: 10px 12px;\n font-size: 14px;\n color: var(--color-foreground);\n display: flex;\n align-items: center;\n}\n\n.input-text {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.input-cursor {\n width: 2px;\n height: 18px;\n background: var(--color-primary);\n animation: blink 1s infinite;\n margin-left: 2px;\n}\n\n@keyframes blink {\n 0%,\n 50% {\n opacity: 1;\n }\n 51%,\n 100% {\n opacity: 0;\n }\n}\n\n.editor-select {\n background: var(--color-muted);\n border: 1px solid var(--color-border);\n border-radius: 6px;\n padding: 10px 12px;\n font-size: 14px;\n color: var(--color-foreground);\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.select-arrow {\n font-size: 10px;\n color: var(--color-muted-foreground);\n}\n\n.editor-textarea {\n background: var(--color-muted);\n border: 1px solid var(--color-border);\n border-radius: 6px;\n padding: 10px 12px;\n font-size: 14px;\n color: var(--color-foreground);\n min-height: 80px;\n}\n\n.textarea-text {\n transition: all 0.5s ease;\n}\n\n.textarea-text--complete {\n color: var(--color-foreground);\n}\n\n/* Preview panel */\n.preview-panel {\n width: 320px;\n padding: 20px;\n background: oklch(from var(--color-muted) l c h / 0.5);\n}\n\n.preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.preview-label {\n font-size: 12px;\n font-weight: 500;\n color: var(--color-muted-foreground);\n}\n\n.preview-url {\n font-size: 11px;\n color: var(--color-muted-foreground);\n font-family: monospace;\n}\n\n.preview-card {\n background: var(--color-card);\n border: 1px solid var(--color-border);\n border-radius: 10px;\n overflow: hidden;\n position: relative;\n transition: all 0.3s ease;\n}\n\n.preview-badge {\n position: absolute;\n top: 10px;\n right: 10px;\n background: var(--color-primary);\n color: white;\n font-size: 11px;\n padding: 4px 8px;\n border-radius: 4px;\n font-weight: 500;\n animation: badge-pop 0.3s ease;\n}\n\n@keyframes badge-pop {\n from {\n transform: scale(0);\n opacity: 0;\n }\n to {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.preview-image {\n height: 120px;\n background: linear-gradient(135deg, var(--color-muted) 0%, var(--color-accent) 100%);\n}\n\n.preview-image-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 40px;\n}\n\n.preview-content {\n padding: 16px;\n}\n\n.preview-category-tag {\n display: inline-block;\n font-size: 11px;\n color: var(--color-primary);\n font-weight: 500;\n margin-bottom: 8px;\n}\n\n.preview-title {\n font-size: 16px;\n font-weight: 600;\n margin: 0 0 8px;\n color: var(--color-foreground);\n}\n\n.preview-description {\n font-size: 13px;\n color: var(--color-muted-foreground);\n line-height: 1.5;\n margin: 0 0 12px;\n}\n\n.preview-meta {\n display: flex;\n gap: 8px;\n font-size: 12px;\n}\n\n.meta-rating {\n color: #ffc24a;\n}\n\n.meta-reviews {\n color: var(--color-muted-foreground);\n}\n\n/* State indicators */\n.mockup-indicators {\n display: flex;\n justify-content: center;\n gap: 24px;\n padding: 16px;\n border-top: 1px solid var(--color-border);\n}\n\n.indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n background: none;\n border: none;\n cursor: pointer;\n padding: 6px 12px;\n border-radius: 20px;\n transition: all 0.2s ease;\n}\n\n.indicator:hover {\n background: var(--color-accent);\n}\n\n.indicator--active {\n background: oklch(from var(--color-primary) l c h / 0.12);\n}\n\n.indicator-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: var(--color-muted-foreground);\n transition: all 0.2s ease;\n}\n\n.indicator--active .indicator-dot {\n background: var(--color-primary);\n box-shadow: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.2);\n}\n\n.indicator-label {\n font-size: 12px;\n color: var(--color-muted-foreground);\n}\n\n.indicator--active .indicator-label {\n color: var(--color-foreground);\n font-weight: 500;\n}\n\n/* ========================================\n LOGO BANNER STYLES\n ======================================== */\n\n.logo-scroll-container {\n overflow: hidden;\n mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);\n}\n\n.logo-scroll-track {\n display: flex;\n animation: logo-scroll 30s linear infinite;\n}\n\n.logo-scroll-track:hover {\n animation-play-state: paused;\n}\n\n@keyframes logo-scroll {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(-50%);\n }\n}\n\n.logo-item {\n flex-shrink: 0;\n min-width: 150px;\n}\n\n/* ========================================\n RESPONSIVE ADJUSTMENTS\n ======================================== */\n\n@media (max-width: 768px) {\n .mockup-content {\n flex-direction: column;\n }\n\n .mockup-sidebar {\n width: 100%;\n border-right: none;\n border-bottom: 1px solid var(--color-border);\n }\n\n .sidebar-nav {\n display: flex;\n overflow-x: auto;\n padding: 8px;\n gap: 4px;\n }\n\n .sidebar-item {\n white-space: nowrap;\n }\n\n .main-split {\n flex-direction: column;\n }\n\n .editor-panel {\n border-right: none;\n border-bottom: 1px solid var(--color-border);\n }\n\n .preview-panel {\n width: 100%;\n }\n\n .mockup-indicators {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .indicator-label {\n display: none;\n }\n}\n\n/* ========================================\n ANIMATION STYLES\n ======================================== */\n\n/* Industry Tabs Animation */\n.industry-tab-content {\n animation: tab-fade-in 0.3s ease-out;\n}\n\n@keyframes tab-fade-in {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Feature Showcase Entrance Animation */\n@keyframes feature-slide-in {\n from {\n opacity: 0;\n transform: translateX(-20px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n}\n\n.feature-showcase-content {\n animation: feature-slide-in 0.5s ease-out;\n}\n\n/* Testimonial Card Hover Effects */\n.testimonial-card {\n transition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.testimonial-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);\n}\n\n/* Stat Number Animation */\n@keyframes stat-count-up {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.stat-number {\n animation: stat-count-up 0.6s ease-out;\n}\n\n/* Trust Column Icon Animation */\n.trust-icon {\n transition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.trust-icon:hover {\n transform: scale(1.1);\n}\n\n/* Final CTA Background Animation */\n@keyframes subtle-float {\n 0%,\n 100% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-10px);\n }\n}\n\n.cta-decorative {\n animation: subtle-float 6s ease-in-out infinite;\n}\n\n/* Feature Grid Card Entrance */\n@keyframes card-entrance {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.feature-card {\n animation: card-entrance 0.4s ease-out;\n animation-fill-mode: both;\n}\n\n.feature-card:nth-child(1) {\n animation-delay: 0.1s;\n}\n.feature-card:nth-child(2) {\n animation-delay: 0.2s;\n}\n.feature-card:nth-child(3) {\n animation-delay: 0.3s;\n}\n.feature-card:nth-child(4) {\n animation-delay: 0.4s;\n}\n.feature-card:nth-child(5) {\n animation-delay: 0.5s;\n}\n.feature-card:nth-child(6) {\n animation-delay: 0.6s;\n}\n\n/* Smooth Section Transitions */\nsection {\n scroll-margin-top: 80px;\n}\n\n/* Button Hover Enhancement */\n.cta-button {\n position: relative;\n overflow: hidden;\n}\n\n.cta-button::after {\n content: "";\n position: absolute;\n inset: 0;\n background: linear-gradient(rgba(255, 255, 255, 0.1), transparent);\n opacity: 0;\n transition: opacity 0.3s ease;\n}\n\n.cta-button:hover::after {\n opacity: 1;\n}\n\n/* Responsive Image Container */\n.feature-image-container {\n position: relative;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15);\n transition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.feature-image-container:hover {\n transform: translateY(-4px);\n box-shadow: 0 30px 60px -15px rgba(0, 0, 0, 0.2);\n}\n',
|
|
1528
1528
|
"marketing/payload/src/app/(frontend)/layout.tsx": `import type { Metadata } from "next"
|
|
1529
1529
|
|
|
1530
1530
|
import { cn } from "@/utilities/ui"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kofi-stack-template-generator",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.51",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"typecheck": "tsc --noEmit"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"kofi-stack-types": "^2.1.
|
|
20
|
+
"kofi-stack-types": "^2.1.51",
|
|
21
21
|
"handlebars": "^4.7.8",
|
|
22
22
|
"memfs": "^4.9.0"
|
|
23
23
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-generated file. Do not edit manually.
|
|
2
2
|
// Run 'pnpm prebuild' to regenerate.
|
|
3
|
-
// Generated: 2026-01-
|
|
3
|
+
// Generated: 2026-01-19T16:07:02.986Z
|
|
4
4
|
// Template count: 343
|
|
5
5
|
|
|
6
6
|
export const EMBEDDED_TEMPLATES: Record<string, string> = {
|
|
@@ -44,7 +44,7 @@ export const EMBEDDED_TEMPLATES: Record<string, string> = {
|
|
|
44
44
|
"marketing/nextjs/next.config.ts.hbs": "import type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n transpilePackages: ['@repo/ui'],\n}\n\nexport default nextConfig\n",
|
|
45
45
|
"marketing/nextjs/package.json.hbs": "{\n \"name\": \"@repo/marketing\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"next dev --turbopack --port 3000\",\n \"build\": \"next build\",\n \"start\": \"next start\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"dependencies\": {\n \"next\": \"^16.0.0\",\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"@repo/ui\": \"workspace:*\"\n },\n \"devDependencies\": {\n \"@repo/config-typescript\": \"workspace:*\",\n \"@types/node\": \"^20.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n \"tailwindcss\": \"^4.0.0\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n \"postcss\": \"^8.4.0\",\n \"typescript\": \"^5.0.0\"\n }\n}\n",
|
|
46
46
|
"marketing/nextjs/postcss.config.mjs.hbs": "export default {\n plugins: {\n '@tailwindcss/postcss': {},\n },\n}\n",
|
|
47
|
-
"marketing/nextjs/src/app/globals.css.hbs": "@import \"tailwindcss\";\n\n:root {\n --background: #ffffff;\n --foreground: #171717;\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n --background: #0a0a0a;\n --foreground: #ededed;\n }\n}\n\nbody {\n color: var(--foreground);\n background: var(--background);\n}\n",
|
|
47
|
+
"marketing/nextjs/src/app/globals.css.hbs": "@import \"tailwindcss\";\n@import \"tw-animate-css\";\n\n@custom-variant dark (&:is(.dark *));\n\n@theme inline {\n\t/* Colors */\n\t--color-background: var(--background);\n\t--color-foreground: var(--foreground);\n\n\t--color-card: var(--card);\n\t--color-card-foreground: var(--card-foreground);\n\n\t--color-popover: var(--popover);\n\t--color-popover-foreground: var(--popover-foreground);\n\n\t--color-primary: var(--primary);\n\t--color-primary-foreground: var(--primary-foreground);\n\n\t--color-secondary: var(--secondary);\n\t--color-secondary-foreground: var(--secondary-foreground);\n\n\t--color-muted: var(--muted);\n\t--color-muted-foreground: var(--muted-foreground);\n\n\t--color-accent: var(--accent);\n\t--color-accent-foreground: var(--accent-foreground);\n\n\t--color-destructive: var(--destructive);\n\n\t--color-border: var(--border);\n\t--color-input: var(--input);\n\t--color-ring: var(--ring);\n\n\t--color-chart-1: var(--chart-1);\n\t--color-chart-2: var(--chart-2);\n\t--color-chart-3: var(--chart-3);\n\t--color-chart-4: var(--chart-4);\n\t--color-chart-5: var(--chart-5);\n\n\t/* Border radius */\n\t--radius-sm: calc(var(--radius) - 4px);\n\t--radius-md: calc(var(--radius) - 2px);\n\t--radius-lg: var(--radius);\n\t--radius-xl: calc(var(--radius) + 4px);\n\n\t/* Fonts */\n\t--font-sans: var(--font-geist-sans), system-ui, sans-serif;\n\t--font-mono: var(--font-geist-mono), monospace;\n\n\t/* Container */\n\t--container-sm: 40rem;\n\t--container-md: 48rem;\n\t--container-lg: 64rem;\n\t--container-xl: 80rem;\n\t--container-2xl: 96rem;\n\n\t/* Animations */\n\t--animate-accordion-down: accordion-down 0.2s ease-out;\n\t--animate-accordion-up: accordion-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n\tfrom {\n\t\theight: 0;\n\t}\n\tto {\n\t\theight: var(--radix-accordion-content-height);\n\t}\n}\n\n@keyframes accordion-up {\n\tfrom {\n\t\theight: var(--radix-accordion-content-height);\n\t}\n\tto {\n\t\theight: 0;\n\t}\n}\n\n/* ========================================\n THEME COLOR VARIABLES\n ======================================== */\n\n:root {\n\t--radius: 0.625rem;\n\t--background: oklch(1 0 0);\n\t--foreground: oklch(0.145 0 0);\n\t--card: oklch(1 0 0);\n\t--card-foreground: oklch(0.145 0 0);\n\t--popover: oklch(1 0 0);\n\t--popover-foreground: oklch(0.145 0 0);\n\t--secondary: oklch(0.97 0 0);\n\t--secondary-foreground: oklch(0.205 0 0);\n\t--muted: oklch(0.97 0 0);\n\t--muted-foreground: oklch(0.556 0 0);\n\t--accent: oklch(0.97 0 0);\n\t--accent-foreground: oklch(0.205 0 0);\n\t--destructive: oklch(0.577 0.245 27.325);\n\t--border: oklch(0.922 0 0);\n\t--input: oklch(0.922 0 0);\n\n{{#if (eq shadcn.themeColor \"neutral\")}}\n\t--primary: oklch(0.205 0 0);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.708 0 0);\n\t--chart-1: oklch(0.646 0.222 41.116);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"blue\")}}\n\t--primary: oklch(0.546 0.245 262.881);\n\t--primary-foreground: oklch(0.985 0.002 247.858);\n\t--ring: oklch(0.546 0.245 262.881);\n\t--chart-1: oklch(0.546 0.245 262.881);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"green\")}}\n\t--primary: oklch(0.596 0.145 163.225);\n\t--primary-foreground: oklch(0.982 0.018 155.826);\n\t--ring: oklch(0.596 0.145 163.225);\n\t--chart-1: oklch(0.596 0.145 163.225);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"purple\")}}\n\t--primary: oklch(0.627 0.265 303.9);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.627 0.265 303.9);\n\t--chart-1: oklch(0.627 0.265 303.9);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"red\")}}\n\t--primary: oklch(0.637 0.237 25.331);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.637 0.237 25.331);\n\t--chart-1: oklch(0.637 0.237 25.331);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"orange\")}}\n\t--primary: oklch(0.705 0.191 47.604);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.705 0.191 47.604);\n\t--chart-1: oklch(0.705 0.191 47.604);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"amber\")}}\n\t--primary: oklch(0.769 0.188 70.08);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.769 0.188 70.08);\n\t--chart-1: oklch(0.769 0.188 70.08);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.646 0.222 41.116);\n{{else if (eq shadcn.themeColor \"cyan\")}}\n\t--primary: oklch(0.715 0.143 215.221);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.715 0.143 215.221);\n\t--chart-1: oklch(0.715 0.143 215.221);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"emerald\")}}\n\t--primary: oklch(0.696 0.17 162.48);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.696 0.17 162.48);\n\t--chart-1: oklch(0.696 0.17 162.48);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"fuchsia\")}}\n\t--primary: oklch(0.667 0.295 322.15);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.667 0.295 322.15);\n\t--chart-1: oklch(0.667 0.295 322.15);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"indigo\")}}\n\t--primary: oklch(0.585 0.233 277.117);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.585 0.233 277.117);\n\t--chart-1: oklch(0.585 0.233 277.117);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"lime\")}}\n\t--primary: oklch(0.768 0.233 130.85);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.768 0.233 130.85);\n\t--chart-1: oklch(0.768 0.233 130.85);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"pink\")}}\n\t--primary: oklch(0.718 0.202 349.761);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.718 0.202 349.761);\n\t--chart-1: oklch(0.718 0.202 349.761);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"rose\")}}\n\t--primary: oklch(0.645 0.246 16.439);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.645 0.246 16.439);\n\t--chart-1: oklch(0.645 0.246 16.439);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"sky\")}}\n\t--primary: oklch(0.685 0.169 237.323);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.685 0.169 237.323);\n\t--chart-1: oklch(0.685 0.169 237.323);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"teal\")}}\n\t--primary: oklch(0.704 0.14 182.503);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.704 0.14 182.503);\n\t--chart-1: oklch(0.704 0.14 182.503);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"violet\")}}\n\t--primary: oklch(0.606 0.25 292.717);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.606 0.25 292.717);\n\t--chart-1: oklch(0.606 0.25 292.717);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"yellow\")}}\n\t--primary: oklch(0.795 0.184 86.047);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.795 0.184 86.047);\n\t--chart-1: oklch(0.795 0.184 86.047);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.646 0.222 41.116);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else}}\n\t--primary: oklch(0.205 0 0);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.708 0 0);\n\t--chart-1: oklch(0.646 0.222 41.116);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{/if}}\n}\n\n.dark {\n\t--background: oklch(0.145 0 0);\n\t--foreground: oklch(0.985 0 0);\n\t--card: oklch(0.205 0 0);\n\t--card-foreground: oklch(0.985 0 0);\n\t--popover: oklch(0.269 0 0);\n\t--popover-foreground: oklch(0.985 0 0);\n\t--secondary: oklch(0.269 0 0);\n\t--secondary-foreground: oklch(0.985 0 0);\n\t--muted: oklch(0.269 0 0);\n\t--muted-foreground: oklch(0.708 0 0);\n\t--accent: oklch(0.371 0 0);\n\t--accent-foreground: oklch(0.985 0 0);\n\t--destructive: oklch(0.704 0.191 22.216);\n\t--border: oklch(1 0 0 / 10%);\n\t--input: oklch(1 0 0 / 15%);\n\n{{#if (eq shadcn.themeColor \"neutral\")}}\n\t--primary: oklch(0.922 0 0);\n\t--primary-foreground: oklch(0.205 0 0);\n\t--ring: oklch(0.556 0 0);\n\t--chart-1: oklch(0.488 0.243 264.376);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"blue\")}}\n\t--primary: oklch(0.623 0.214 262.881);\n\t--primary-foreground: oklch(0.273 0.033 256.848);\n\t--ring: oklch(0.623 0.214 262.881);\n\t--chart-1: oklch(0.623 0.214 262.881);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"green\")}}\n\t--primary: oklch(0.696 0.17 162.48);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.696 0.17 162.48);\n\t--chart-1: oklch(0.696 0.17 162.48);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"purple\")}}\n\t--primary: oklch(0.714 0.203 305.504);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.714 0.203 305.504);\n\t--chart-1: oklch(0.714 0.203 305.504);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.488 0.243 264.376);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"red\")}}\n\t--primary: oklch(0.704 0.191 22.216);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.704 0.191 22.216);\n\t--chart-1: oklch(0.704 0.191 22.216);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor \"orange\")}}\n\t--primary: oklch(0.792 0.17 52.615);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.792 0.17 52.615);\n\t--chart-1: oklch(0.792 0.17 52.615);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"amber\")}}\n\t--primary: oklch(0.828 0.189 84.429);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.828 0.189 84.429);\n\t--chart-1: oklch(0.828 0.189 84.429);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.488 0.243 264.376);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"cyan\")}}\n\t--primary: oklch(0.789 0.154 211.53);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.789 0.154 211.53);\n\t--chart-1: oklch(0.789 0.154 211.53);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"emerald\")}}\n\t--primary: oklch(0.765 0.166 160.391);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.765 0.166 160.391);\n\t--chart-1: oklch(0.765 0.166 160.391);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"fuchsia\")}}\n\t--primary: oklch(0.74 0.238 322.16);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.74 0.238 322.16);\n\t--chart-1: oklch(0.74 0.238 322.16);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.488 0.243 264.376);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"indigo\")}}\n\t--primary: oklch(0.673 0.182 276.935);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.673 0.182 276.935);\n\t--chart-1: oklch(0.673 0.182 276.935);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"lime\")}}\n\t--primary: oklch(0.841 0.238 128.85);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.841 0.238 128.85);\n\t--chart-1: oklch(0.841 0.238 128.85);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"pink\")}}\n\t--primary: oklch(0.775 0.181 349.761);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.775 0.181 349.761);\n\t--chart-1: oklch(0.775 0.181 349.761);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor \"rose\")}}\n\t--primary: oklch(0.712 0.194 13.428);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.712 0.194 13.428);\n\t--chart-1: oklch(0.712 0.194 13.428);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor \"sky\")}}\n\t--primary: oklch(0.756 0.143 232.661);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.756 0.143 232.661);\n\t--chart-1: oklch(0.756 0.143 232.661);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"teal\")}}\n\t--primary: oklch(0.777 0.152 181.912);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.777 0.152 181.912);\n\t--chart-1: oklch(0.777 0.152 181.912);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"violet\")}}\n\t--primary: oklch(0.702 0.183 293.541);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.702 0.183 293.541);\n\t--chart-1: oklch(0.702 0.183 293.541);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.488 0.243 264.376);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"yellow\")}}\n\t--primary: oklch(0.852 0.199 91.936);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.852 0.199 91.936);\n\t--chart-1: oklch(0.852 0.199 91.936);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.488 0.243 264.376);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else}}\n\t--primary: oklch(0.922 0 0);\n\t--primary-foreground: oklch(0.205 0 0);\n\t--ring: oklch(0.556 0 0);\n\t--chart-1: oklch(0.488 0.243 264.376);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{/if}}\n}\n\n/* ========================================\n BASE STYLES\n ======================================== */\n\n@layer base {\n\t* {\n\t\t@apply border-border outline-ring/50;\n\t}\n\tbody {\n\t\t@apply bg-background text-foreground;\n\t}\n}\n\n/* Container utility */\n.container {\n\twidth: 100%;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tpadding-left: 1rem;\n\tpadding-right: 1rem;\n\tmax-width: 96rem;\n}\n\n@media (min-width: 640px) {\n\t.container {\n\t\tpadding-left: 1.5rem;\n\t\tpadding-right: 1.5rem;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.container {\n\t\tpadding-left: 2rem;\n\t\tpadding-right: 2rem;\n\t}\n}\n",
|
|
48
48
|
"marketing/nextjs/src/app/layout.tsx.hbs": "import type { Metadata } from 'next'\nimport { Geist, Geist_Mono } from 'next/font/google'\nimport './globals.css'\n\nconst geistSans = Geist({\n variable: '--font-geist-sans',\n subsets: ['latin'],\n})\n\nconst geistMono = Geist_Mono({\n variable: '--font-geist-mono',\n subsets: ['latin'],\n})\n\nexport const metadata: Metadata = {\n title: '{{projectName}} - Marketing',\n description: 'Marketing site for {{projectName}}',\n}\n\nexport default function RootLayout({\n children,\n}: {\n children: React.ReactNode\n}) {\n return (\n <html lang=\"en\">\n <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>\n {children}\n </body>\n </html>\n )\n}\n",
|
|
49
49
|
"marketing/nextjs/src/app/page.tsx.hbs": "export default function HomePage() {\n return (\n <main className=\"min-h-screen\">\n {/* Navigation */}\n <nav className=\"sticky top-0 z-50 w-full border-b border-gray-200 dark:border-gray-800 bg-white/80 dark:bg-gray-900/80 backdrop-blur-sm\">\n <div className=\"container mx-auto px-4\">\n <div className=\"flex h-16 items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-gray-900 dark:bg-white\">\n <svg className=\"h-4 w-4 text-white dark:text-gray-900\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n </div>\n <span className=\"font-semibold text-gray-900 dark:text-white\">{{projectName}}</span>\n </div>\n <div className=\"hidden md:flex items-center gap-6\">\n <a href=\"#features\" className=\"text-sm text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white transition-colors\">\n Features\n </a>\n <a href=\"#\" className=\"text-sm text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white transition-colors\">\n Pricing\n </a>\n <a href=\"#\" className=\"text-sm text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white transition-colors\">\n Docs\n </a>\n </div>\n <div className=\"flex items-center gap-4\">\n <a\n href=\"/sign-in\"\n className=\"text-sm font-medium text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white transition-colors\"\n >\n Sign in\n </a>\n <a\n href=\"/sign-up\"\n className=\"rounded-lg bg-gray-900 dark:bg-white px-4 py-2 text-sm font-medium text-white dark:text-gray-900 hover:opacity-90 transition-opacity\"\n >\n Get Started\n </a>\n </div>\n </div>\n </div>\n </nav>\n\n {/* Hero Section */}\n <section className=\"relative overflow-hidden bg-gradient-to-b from-gray-50 to-white dark:from-gray-900 dark:to-gray-800\">\n <div className=\"container mx-auto px-4 py-24 sm:py-32\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-6xl\">\n Welcome to {{projectName}}\n </h1>\n <p className=\"mt-6 text-lg leading-8 text-gray-600 dark:text-gray-300 max-w-2xl mx-auto\">\n A modern full-stack application built with Next.js, Convex, and Better-Auth.\n </p>\n <div className=\"mt-10 flex items-center justify-center gap-x-6\">\n <a\n href=\"/app\"\n className=\"rounded-lg bg-gray-900 dark:bg-white px-6 py-3 text-sm font-semibold text-white dark:text-gray-900 shadow-sm hover:opacity-90 transition-opacity\"\n >\n Get Started\n </a>\n <a\n href=\"#features\"\n className=\"text-sm font-semibold leading-6 text-gray-900 dark:text-white\"\n >\n Learn more <span aria-hidden=\"true\">→</span>\n </a>\n </div>\n </div>\n </div>\n </section>\n\n {/* Features Section */}\n <section id=\"features\" className=\"py-24 sm:py-32\">\n <div className=\"container mx-auto px-4\">\n <div className=\"text-center mb-16\">\n <h2 className=\"text-3xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-4xl\">\n Everything you need\n </h2>\n <p className=\"mt-4 text-lg text-gray-600 dark:text-gray-300\">\n Built with the best tools for modern web development\n </p>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-8\">\n <div className=\"p-6 rounded-xl border border-gray-200 dark:border-gray-700\">\n <div className=\"w-12 h-12 bg-gray-100 dark:bg-gray-800 rounded-lg flex items-center justify-center mb-4\">\n <svg className=\"w-6 h-6 text-gray-900 dark:text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 10V3L4 14h7v7l9-11h-7z\" />\n </svg>\n </div>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white mb-2\">\n Lightning Fast\n </h3>\n <p className=\"text-gray-600 dark:text-gray-300\">\n Built on Next.js with Turbopack for instant hot reload and optimized production builds.\n </p>\n </div>\n <div className=\"p-6 rounded-xl border border-gray-200 dark:border-gray-700\">\n <div className=\"w-12 h-12 bg-gray-100 dark:bg-gray-800 rounded-lg flex items-center justify-center mb-4\">\n <svg className=\"w-6 h-6 text-gray-900 dark:text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\" />\n </svg>\n </div>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white mb-2\">\n Real-time Database\n </h3>\n <p className=\"text-gray-600 dark:text-gray-300\">\n Powered by Convex for automatic real-time sync and type-safe queries.\n </p>\n </div>\n <div className=\"p-6 rounded-xl border border-gray-200 dark:border-gray-700\">\n <div className=\"w-12 h-12 bg-gray-100 dark:bg-gray-800 rounded-lg flex items-center justify-center mb-4\">\n <svg className=\"w-6 h-6 text-gray-900 dark:text-white\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\" />\n </svg>\n </div>\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white mb-2\">\n Secure Auth\n </h3>\n <p className=\"text-gray-600 dark:text-gray-300\">\n Better-Auth provides secure, flexible authentication with social login support.\n </p>\n </div>\n </div>\n </div>\n </section>\n\n {/* CTA Section */}\n <section className=\"py-24 sm:py-32 bg-gray-900 dark:bg-gray-800\">\n <div className=\"container mx-auto px-4 text-center\">\n <h2 className=\"text-3xl font-bold tracking-tight text-white sm:text-4xl\">\n Ready to get started?\n </h2>\n <p className=\"mt-4 text-lg text-gray-300 max-w-2xl mx-auto\">\n Start building your next project with our full-stack template.\n </p>\n <div className=\"mt-10\">\n <a\n href=\"/app\"\n className=\"rounded-lg bg-white px-6 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:opacity-90 transition-opacity\"\n >\n Launch App\n </a>\n </div>\n </div>\n </section>\n\n {/* Footer */}\n <footer className=\"border-t border-gray-200 dark:border-gray-700\">\n <div className=\"container mx-auto px-4 py-12\">\n <div className=\"text-center text-gray-600 dark:text-gray-300\">\n <p>\n Built with{' '}\n <a\n href=\"https://github.com/theodenanyoh11/create-kofi-stack\"\n className=\"text-gray-900 dark:text-white hover:underline\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n create-kofi-stack\n </a>\n </p>\n </div>\n </div>\n </footer>\n </main>\n )\n}\n",
|
|
50
50
|
"marketing/nextjs/tsconfig.json.hbs": "{\n \"compilerOptions\": {\n \"target\": \"ES2017\",\n \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n \"allowJs\": true,\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noEmit\": true,\n \"esModuleInterop\": true,\n \"module\": \"esnext\",\n \"moduleResolution\": \"bundler\",\n \"resolveJsonModule\": true,\n \"isolatedModules\": true,\n \"jsx\": \"react-jsx\",\n \"incremental\": true,\n \"plugins\": [{ \"name\": \"next\" }],\n \"paths\": {\n \"@/*\": [\"./src/*\"]\n }\n },\n \"include\": [\"next-env.d.ts\", \"**/*.ts\", \"**/*.tsx\", \".next/types/**/*.ts\", \".next/dev/types/**/*.ts\"],\n \"exclude\": [\"node_modules\"]\n}\n",
|
|
@@ -84,7 +84,7 @@ export const EMBEDDED_TEMPLATES: Record<string, string> = {
|
|
|
84
84
|
"marketing/payload/src/app/(frontend)/api/docs-search/route.ts": "import { getDocsFromConvex } from \"@/lib/docs-source\"\nimport { NextResponse } from \"next/server\"\n\n/**\n * Search API for documentation\n * Returns matching docs based on query\n */\nexport async function GET(request: Request) {\n\tconst { searchParams } = new URL(request.url)\n\tconst query = searchParams.get(\"q\")?.toLowerCase() || \"\"\n\n\tif (!query || query.length < 2) {\n\t\treturn NextResponse.json({ results: [] })\n\t}\n\n\ttry {\n\t\tconst docs = await getDocsFromConvex()\n\n\t\t// Simple search implementation\n\t\tconst results = docs\n\t\t\t.filter((doc) => {\n\t\t\t\tconst titleMatch = doc.title.toLowerCase().includes(query)\n\t\t\t\tconst descriptionMatch = doc.description?.toLowerCase().includes(query)\n\t\t\t\tconst contentMatch = doc.content.toLowerCase().includes(query)\n\t\t\t\treturn titleMatch || descriptionMatch || contentMatch\n\t\t\t})\n\t\t\t.map((doc) => ({\n\t\t\t\tid: doc._id,\n\t\t\t\ttitle: doc.title,\n\t\t\t\tdescription: doc.description || \"\",\n\t\t\t\turl: `/docs/${doc.slug}`,\n\t\t\t\t// Extract a snippet from the content\n\t\t\t\tsnippet: extractSnippet(doc.content, query),\n\t\t\t}))\n\t\t\t.slice(0, 10) // Limit results\n\n\t\treturn NextResponse.json({ results })\n\t} catch (error) {\n\t\tconsole.error(\"Search error:\", error)\n\t\treturn NextResponse.json({ results: [], error: \"Search failed\" }, { status: 500 })\n\t}\n}\n\n/**\n * Extract a snippet around the search query\n */\nfunction extractSnippet(content: string, query: string): string {\n\tconst lowerContent = content.toLowerCase()\n\tconst index = lowerContent.indexOf(query)\n\n\tif (index === -1) {\n\t\t// Return first 150 chars if query not found in content\n\t\treturn `${content.slice(0, 150).trim()}...`\n\t}\n\n\t// Get 50 chars before and 100 chars after the match\n\tconst start = Math.max(0, index - 50)\n\tconst end = Math.min(content.length, index + query.length + 100)\n\n\tlet snippet = content.slice(start, end).trim()\n\n\t// Add ellipsis if needed\n\tif (start > 0) snippet = `...${snippet}`\n\tif (end < content.length) snippet = `${snippet}...`\n\n\treturn snippet\n}\n",
|
|
85
85
|
"marketing/payload/src/app/(frontend)/api/newsletter/route.ts": "import { NextResponse } from \"next/server\"\n\nconst RESEND_API_URL = \"https://api.resend.com\"\n\n/**\n * Email validation regex\n */\nconst EMAIL_REGEX = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n/**\n * Company address for CAN-SPAM compliance\n */\nconst COMPANY_ADDRESS = \"KrumaLabs • 102 West Main Street #501, New Albany, OH 43054\"\n\n/**\n * SaaSify logo URL\n */\nconst LOGO_URL = \"/logo.png\"\n\n/**\n * Generate newsletter confirmation email HTML with logo and branding\n */\nfunction renderNewsletterConfirmationEmail(unsubscribeUrl?: string): string {\n\tconst emailStyles = {\n\t\tmain: `\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.6;\n color: #333;\n background-color: #f5f5f5;\n margin: 0;\n padding: 20px;\n `,\n\t\tcontainer: `\n background-color: #ffffff;\n border-radius: 8px;\n margin: 0 auto;\n padding: 0;\n max-width: 600px;\n `,\n\t\theader: `\n padding: 32px 32px 24px;\n border-bottom: 1px solid #e5e5e5;\n `,\n\t\tlogoText: `\n color: #0070f3;\n font-size: 24px;\n font-weight: 600;\n margin: 0;\n padding: 0;\n line-height: 1;\n `,\n\t\theading: `\n color: #111111;\n font-size: 24px;\n font-weight: 600;\n line-height: 1.4;\n margin: 0 0 24px;\n `,\n\t\tcontent: `\n padding: 32px;\n `,\n\t\tparagraph: `\n font-size: 16px;\n color: #444444;\n margin: 0 0 16px;\n line-height: 1.6;\n `,\n\t\tparagraphSmall: `\n font-size: 14px;\n color: #666666;\n margin: 0 0 16px;\n line-height: 1.6;\n `,\n\t\tbutton: `\n background-color: #0070f3;\n color: white;\n padding: 14px 32px;\n text-decoration: none;\n border-radius: 6px;\n display: inline-block;\n font-weight: 500;\n font-size: 16px;\n `,\n\t\tfooter: `\n padding: 24px 32px;\n text-align: center;\n `,\n\t\tfooterText: `\n color: #666666;\n font-size: 14px;\n line-height: 1.6;\n margin: 0 0 8px;\n `,\n\t\tfooterTextSmall: `\n color: #999999;\n font-size: 12px;\n line-height: 1.6;\n margin: 16px 0 0;\n `,\n\t\tfooterAddress: `\n color: #999999;\n font-size: 11px;\n line-height: 1.6;\n margin: 8px 0 0;\n `,\n\t\tlink: `\n color: #0070f3;\n text-decoration: underline;\n `,\n\t}\n\n\treturn `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n</head>\n<body style=\"${emailStyles.main}\">\n <div style=\"${emailStyles.container}\">\n <!-- Header with Logo -->\n <div style=\"${emailStyles.header}\">\n <a href=\"/\" style=\"display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: inherit;\">\n <img src=\"${LOGO_URL}\" alt=\"SaaSify\" width=\"32\" height=\"32\" style=\"display: block; width: 32px; height: 32px;\">\n <span style=\"${emailStyles.logoText}\">SaaSify</span>\n </a>\n </div>\n \n <!-- Content -->\n <div style=\"padding: 32px 32px 0;\"><h1 style=\"${emailStyles.heading}\">Welcome to the Newsletter!</h1></div>\n <div style=\"${emailStyles.content}\">\n <p style=\"${emailStyles.paragraph}\">\n Thanks for subscribing to the SaaSify newsletter! 🎉\n </p>\n <p style=\"${emailStyles.paragraph}\">\n You'll now receive updates about:\n </p>\n <ul style=\"${emailStyles.paragraph}\">\n <li>New features and product updates</li>\n <li>Tips for boosting team productivity</li>\n <li>Industry insights and best practices</li>\n <li>Special announcements and offers</li>\n </ul>\n <p style=\"${emailStyles.paragraph}\">\n We respect your inbox and only send emails when we have something valuable to share.\n </p>\n <div style=\"margin: 32px 0; text-align: center;\">\n <a href=\"/\" style=\"${emailStyles.button}\">Visit SaaSify</a>\n </div>\n <p style=\"${emailStyles.paragraphSmall}\">\n If you didn't subscribe to this newsletter, you can safely ignore this email or\n <a href=\"${unsubscribeUrl || \"/unsubscribe\"}\" style=\"${emailStyles.link}\">unsubscribe here</a>.\n </p>\n </div>\n \n <!-- Divider -->\n <hr style=\"border: none; border-top: 1px solid #e5e5e5; margin: 0 32px;\">\n \n <!-- Footer -->\n <div style=\"${emailStyles.footer}\">\n <p style=\"${emailStyles.footerText}\">SaaSify - The modern platform for growing teams</p>\n <p style=\"${emailStyles.footerText}\">\n <a href=\"/\" style=\"${emailStyles.link}\">Visit our website</a>\n <span style=\"color: #999999;\"> • </span>\n <a href=\"/support\" style=\"${emailStyles.link}\">Support</a>\n ${unsubscribeUrl ? `<span style=\"color: #999999;\"> • </span><a href=\"${unsubscribeUrl}\" style=\"${emailStyles.link}\">Unsubscribe</a>` : \"\"}\n </p>\n <p style=\"${emailStyles.footerTextSmall}\">You're receiving this email because you signed up for the SaaSify newsletter.</p>\n <p style=\"${emailStyles.footerAddress}\">${COMPANY_ADDRESS}</p>\n </div>\n </div>\n</body>\n</html>`.trim()\n}\n\nexport async function POST(request: Request) {\n\ttry {\n\t\tconst body = await request.json()\n\t\tconst { email } = body\n\n\t\tif (!email) {\n\t\t\treturn NextResponse.json({ success: false, message: \"Email is required.\" }, { status: 400 })\n\t\t}\n\n\t\t// Normalize and validate email\n\t\tconst normalizedEmail = email.toLowerCase().trim()\n\t\tif (!EMAIL_REGEX.test(normalizedEmail)) {\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ success: false, message: \"Please enter a valid email address.\" },\n\t\t\t\t{ status: 400 },\n\t\t\t)\n\t\t}\n\n\t\tconst apiKey = process.env.RESEND_API_KEY\n\t\tconst audienceId = process.env.RESEND_AUDIENCE_NEWSLETTER\n\t\t// Marketing emails sender - update with your domain\n\t\tconst fromEmail = \"SaaSify Team <hello@notifications.saasify.com>\"\n\n\t\t// In development without API key, just return success\n\t\tif (!apiKey) {\n\t\t\tconsole.warn(\"RESEND_API_KEY not set - newsletter signup simulated\")\n\t\t\treturn NextResponse.json({\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: \"Thanks for subscribing! Check your inbox for a confirmation email.\",\n\t\t\t})\n\t\t}\n\n\t\t// Call Convex newsletter subscribe action via HTTP\n\t\t// This ensures consistent handling and uses the proper addNewsletterSubscriber function\n\t\tconst convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL || process.env.CONVEX_URL\n\t\tif (!convexUrl) {\n\t\t\tconsole.warn(\"CONVEX_URL not set - newsletter signup will fail\")\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ success: false, message: \"Server configuration error. Please try again later.\" },\n\t\t\t\t{ status: 500 },\n\t\t\t)\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${convexUrl}/api/newsletter/subscribe`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\temail: normalizedEmail,\n\t\t\t\t}),\n\t\t\t})\n\n\t\t\tconst result = await response.json()\n\n\t\t\tif (!result.success) {\n\t\t\t\treturn NextResponse.json(result, { status: response.status })\n\t\t\t}\n\n\t\t\treturn NextResponse.json(result)\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Newsletter subscription error:\", error)\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ success: false, message: \"Something went wrong. Please try again later.\" },\n\t\t\t\t{ status: 500 },\n\t\t\t)\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(\"Newsletter subscription error:\", error)\n\n\t\t// Check if it's a duplicate subscriber error\n\t\tif (error instanceof Error && error.message.includes(\"already exists\")) {\n\t\t\treturn NextResponse.json({\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: \"You're already subscribed to our newsletter!\",\n\t\t\t})\n\t\t}\n\n\t\treturn NextResponse.json(\n\t\t\t{ success: false, message: \"Something went wrong. Please try again later.\" },\n\t\t\t{ status: 500 },\n\t\t)\n\t}\n}\n",
|
|
86
86
|
"marketing/payload/src/app/(frontend)/api/pricing/route.ts": "import { NextResponse } from \"next/server\"\nimport Stripe from \"stripe\"\n\n/**\n * Stripe Lookup Keys - defined in Stripe Dashboard for each price\n * These must match the lookup keys configured in your Stripe Dashboard\n */\nconst STRIPE_LOOKUP_KEYS = {\n\tfree_monthly: \"free_monthly\",\n\tfree_annual: \"free_annual\",\n\tpro_monthly: \"pro_monthly\",\n\tpro_annual: \"pro_annual\",\n\tbusiness_monthly: \"business_monthly\",\n\tbusiness_annual: \"business_annual\",\n} as const\n\n/**\n * Default product metadata when Stripe metadata is missing\n */\nconst DEFAULT_PRODUCT_INFO: Record<\n\tstring,\n\t{ description: string; popular: boolean; order: number }\n> = {\n\tfree: { description: \"Perfect for getting started\", popular: false, order: 1 },\n\tpro: { description: \"For growing businesses\", popular: false, order: 2 },\n\tbusiness: { description: \"For teams and agencies\", popular: true, order: 3 },\n}\n\n/**\n * Feature type from Stripe Entitlements\n */\ninterface PlanFeature {\n\tid: string\n\tlookupKey: string\n\tname: string\n\tmetadata?: Record<string, string>\n}\n\n/**\n * All features type for comparison table\n */\ninterface AllFeature {\n\tid: string\n\tlookupKey: string\n\tname: string\n\tcategory?: string\n\tmetadata?: Record<string, string>\n}\n\n/**\n * Plan pricing type with features from Stripe\n */\ninterface PlanPricing {\n\tplanId: string\n\tstripeProductId: string\n\tname: string\n\tdescription: string\n\tfeatures: PlanFeature[]\n\tmonthlyPriceId?: string\n\tmonthlyAmount: number\n\tannualPriceId?: string\n\tannualAmount: number\n\tannualDiscount: number\n\tpopular: boolean\n\torder: number\n}\n\n/**\n * Fetch pricing and features from Stripe and return formatted data\n * GET /api/pricing\n *\n * Returns JSON with plan pricing and features for the marketing site\n */\nexport async function GET() {\n\ttry {\n\t\tconst stripeSecretKey = process.env.STRIPE_SECRET_KEY\n\n\t\tif (!stripeSecretKey) {\n\t\t\treturn NextResponse.json(\n\t\t\t\t{\n\t\t\t\t\tplans: [],\n\t\t\t\t\tallFeatures: [],\n\t\t\t\t\tlastFetched: Date.now(),\n\t\t\t\t\terror: \"Stripe not configured\",\n\t\t\t\t},\n\t\t\t\t{ status: 200 },\n\t\t\t)\n\t\t}\n\n\t\tconst stripe = new Stripe(stripeSecretKey)\n\n\t\t// Fetch all features for comparison table\n\t\tconst allFeatures: AllFeature[] = []\n\t\ttry {\n\t\t\tconst featuresResponse = await stripe.entitlements.features.list({ limit: 100 })\n\t\t\tfor (const feature of featuresResponse.data) {\n\t\t\t\tallFeatures.push({\n\t\t\t\t\tid: feature.id,\n\t\t\t\t\tlookupKey: feature.lookup_key,\n\t\t\t\t\tname: feature.name,\n\t\t\t\t\tcategory: feature.metadata?.category,\n\t\t\t\t\tmetadata: feature.metadata as Record<string, string> | undefined,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(\"Error fetching Stripe features:\", err)\n\t\t}\n\n\t\t// Fetch prices with product info\n\t\tconst priceMap = new Map<string, { id: string; amount: number; productId: string }>()\n\n\t\ttry {\n\t\t\tconst allLookupKeys = Object.values(STRIPE_LOOKUP_KEYS)\n\t\t\tconst prices = await stripe.prices.list({\n\t\t\t\tlookup_keys: allLookupKeys,\n\t\t\t\tactive: true,\n\t\t\t\texpand: [\"data.product\"],\n\t\t\t\tlimit: 20,\n\t\t\t})\n\n\t\t\tfor (const price of prices.data) {\n\t\t\t\tif (price.lookup_key && price.unit_amount !== null) {\n\t\t\t\t\tconst productId = typeof price.product === \"string\" ? price.product : price.product?.id\n\t\t\t\t\tif (productId) {\n\t\t\t\t\t\tpriceMap.set(price.lookup_key, {\n\t\t\t\t\t\t\tid: price.id,\n\t\t\t\t\t\t\tamount: price.unit_amount,\n\t\t\t\t\t\t\tproductId,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (stripeError) {\n\t\t\tconsole.error(\"Error fetching Stripe prices:\", stripeError)\n\t\t}\n\n\t\t// Group prices by product\n\t\tconst productPrices = new Map<\n\t\t\tstring,\n\t\t\t{ monthly?: { id: string; amount: number }; annual?: { id: string; amount: number } }\n\t\t>()\n\n\t\tfor (const [lookupKey, priceData] of priceMap.entries()) {\n\t\t\tconst isAnnual = lookupKey.endsWith(\"_annual\")\n\t\t\tconst existingPrices = productPrices.get(priceData.productId) || {}\n\n\t\t\tif (isAnnual) {\n\t\t\t\texistingPrices.annual = { id: priceData.id, amount: priceData.amount }\n\t\t\t} else {\n\t\t\t\texistingPrices.monthly = { id: priceData.id, amount: priceData.amount }\n\t\t\t}\n\n\t\t\tproductPrices.set(priceData.productId, existingPrices)\n\t\t}\n\n\t\t// Build plans from products\n\t\tconst plans: PlanPricing[] = []\n\n\t\tfor (const [productId, prices] of productPrices.entries()) {\n\t\t\t// Fetch product details\n\t\t\tlet product: Stripe.Product | null = null\n\t\t\ttry {\n\t\t\t\tconst fetched = await stripe.products.retrieve(productId)\n\t\t\t\tif (!fetched.deleted) {\n\t\t\t\t\tproduct = fetched\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`Error fetching product ${productId}:`, err)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (!product) continue\n\n\t\t\t// Get plan ID from product metadata\n\t\t\tconst planId = product.metadata?.plan_id\n\t\t\tif (!planId) {\n\t\t\t\tconsole.warn(`Product ${productId} missing plan_id metadata, skipping`)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Fetch features for this product\n\t\t\tconst features: PlanFeature[] = []\n\t\t\ttry {\n\t\t\t\tconst productFeatures = await stripe.products.listFeatures(productId, {\n\t\t\t\t\tlimit: 100,\n\t\t\t\t})\n\t\t\t\tfor (const pf of productFeatures.data) {\n\t\t\t\t\tfeatures.push({\n\t\t\t\t\t\tid: pf.entitlement_feature.id,\n\t\t\t\t\t\tlookupKey: pf.entitlement_feature.lookup_key,\n\t\t\t\t\t\tname: pf.entitlement_feature.name,\n\t\t\t\t\t\tmetadata: pf.entitlement_feature.metadata as Record<string, string> | undefined,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(`Error fetching features for product ${productId}:`, err)\n\t\t\t}\n\n\t\t\t// Get metadata or use defaults\n\t\t\tconst defaultInfo = DEFAULT_PRODUCT_INFO[planId] || {\n\t\t\t\tdescription: \"\",\n\t\t\t\tpopular: false,\n\t\t\t\torder: 99,\n\t\t\t}\n\t\t\tconst description =\n\t\t\t\tproduct.metadata?.description || product.description || defaultInfo.description\n\t\t\tconst popular = product.metadata?.popular === \"true\" || defaultInfo.popular\n\t\t\tconst order = Number.parseInt(product.metadata?.order || String(defaultInfo.order), 10)\n\n\t\t\tconst monthlyAmount = prices.monthly?.amount ?? 0\n\t\t\tconst annualAmount = prices.annual?.amount ?? 0\n\n\t\t\t// Calculate annual discount\n\t\t\tconst yearlyMonthlyEquivalent = monthlyAmount * 12\n\t\t\tconst annualDiscount =\n\t\t\t\tyearlyMonthlyEquivalent > 0\n\t\t\t\t\t? Math.round(((yearlyMonthlyEquivalent - annualAmount) / yearlyMonthlyEquivalent) * 100)\n\t\t\t\t\t: 0\n\n\t\t\tplans.push({\n\t\t\t\tplanId,\n\t\t\t\tstripeProductId: productId,\n\t\t\t\tname: product.name,\n\t\t\t\tdescription,\n\t\t\t\tfeatures,\n\t\t\t\tmonthlyPriceId: prices.monthly?.id,\n\t\t\t\tmonthlyAmount,\n\t\t\t\tannualPriceId: prices.annual?.id,\n\t\t\t\tannualAmount,\n\t\t\t\tannualDiscount: Math.max(0, annualDiscount),\n\t\t\t\tpopular,\n\t\t\t\torder,\n\t\t\t})\n\t\t}\n\n\t\t// Sort plans by order\n\t\tplans.sort((a, b) => a.order - b.order)\n\n\t\treturn NextResponse.json(\n\t\t\t{\n\t\t\t\tplans,\n\t\t\t\tallFeatures,\n\t\t\t\tlastFetched: Date.now(),\n\t\t\t},\n\t\t\t{\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t// Cache for 1 hour on CDN, revalidate in background\n\t\t\t\t\t\"Cache-Control\": \"public, s-maxage=3600, stale-while-revalidate=7200\",\n\t\t\t\t},\n\t\t\t},\n\t\t)\n\t} catch (error) {\n\t\tconsole.error(\"Pricing API error:\", error)\n\n\t\treturn NextResponse.json(\n\t\t\t{\n\t\t\t\tplans: [],\n\t\t\t\tallFeatures: [],\n\t\t\t\tlastFetched: Date.now(),\n\t\t\t\terror: \"Failed to fetch pricing\",\n\t\t\t},\n\t\t\t{ status: 200 },\n\t\t)\n\t}\n}\n",
|
|
87
|
-
"marketing/payload/src/app/(frontend)/globals.css": "@import \"tailwindcss\";\n@import \"tw-animate-css\";\n@plugin \"@tailwindcss/typography\";\n\n@custom-variant dark (&:where([data-theme=\"dark\"], [data-theme=\"dark\"] *));\n\n@theme {\n\t/* Colors */\n\t--color-background: hsl(var(--background));\n\t--color-foreground: hsl(var(--foreground));\n\n\t--color-card: hsl(var(--card));\n\t--color-card-foreground: hsl(var(--card-foreground));\n\n\t--color-popover: hsl(var(--popover));\n\t--color-popover-foreground: hsl(var(--popover-foreground));\n\n\t--color-primary: hsl(var(--primary));\n\t--color-primary-foreground: hsl(var(--primary-foreground));\n\n\t--color-secondary: hsl(var(--secondary));\n\t--color-secondary-foreground: hsl(var(--secondary-foreground));\n\n\t--color-muted: hsl(var(--muted));\n\t--color-muted-foreground: hsl(var(--muted-foreground));\n\n\t--color-accent: hsl(var(--accent));\n\t--color-accent-foreground: hsl(var(--accent-foreground));\n\n\t--color-destructive: hsl(var(--destructive));\n\t--color-destructive-foreground: hsl(var(--destructive-foreground));\n\n\t--color-border: hsla(var(--border));\n\t--color-input: hsl(var(--input));\n\t--color-ring: hsl(var(--ring));\n\n\t--color-success: hsl(var(--success));\n\t--color-warning: hsl(var(--warning));\n\t--color-error: hsl(var(--error));\n\n\t/* Border radius */\n\t--radius-sm: calc(var(--radius) - 4px);\n\t--radius-md: calc(var(--radius) - 2px);\n\t--radius-lg: var(--radius);\n\t--radius-xl: calc(var(--radius) + 4px);\n\n\t/* Fonts */\n\t--font-sans: var(--font-inter), system-ui, sans-serif;\n\t--font-mono: var(--font-geist-mono), monospace;\n\n\t/* Container - matching web app */\n\t--container-sm: 40rem;\n\t--container-md: 48rem;\n\t--container-lg: 64rem;\n\t--container-xl: 80rem;\n\t--container-2xl: 96rem;\n\n\t/* Animations */\n\t--animate-accordion-down: accordion-down 0.2s ease-out;\n\t--animate-accordion-up: accordion-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n\tfrom {\n\t\theight: 0;\n\t}\n\tto {\n\t\theight: var(--radix-accordion-content-height);\n\t}\n}\n\n@keyframes accordion-up {\n\tfrom {\n\t\theight: var(--radix-accordion-content-height);\n\t}\n\tto {\n\t\theight: 0;\n\t}\n}\n\n:root {\n\t--background: 0 0% 98%; /* #f7f9fc */\n\t--foreground: 220 59% 15%; /* #0f1f3d */\n\n\t--card: 217 46% 96%; /* #e9eff8 */\n\t--card-foreground: 220 59% 15%; /* #0f1f3d */\n\n\t--popover: 0 0% 100%;\n\t--popover-foreground: 220 59% 15%;\n\n\t--primary: 220 59% 15%; /* navy */\n\t--primary-foreground: 0 0% 100%;\n\n\t--secondary: 173 55% 32%; /* darker teal for WCAG AA contrast */\n\t--secondary-foreground: 220 59% 15%;\n\n\t--muted: 217 46% 96%; /* mist */\n\t--muted-foreground: 220 20% 25%; /* darkened further for WCAG AA on card backgrounds */\n\n\t--accent: 213 35% 95%; /* soft accent */\n\t--accent-foreground: 220 59% 15%;\n\n\t--destructive: 0 68% 65%; /* #e76a6a */\n\t--destructive-foreground: 0 0% 100%;\n\n\t--border: 216 23% 89%; /* #e1e6ef */\n\t--input: 216 23% 89%;\n\t--ring: 220 59% 15%;\n\n\t--radius: 0.75rem;\n\n\t--success: 157 48% 47%; /* #3fae8c */\n\t--warning: 41 54% 62%; /* #d9b36a */\n\t--error: 0 68% 65%; /* #e76a6a */\n}\n\n[data-theme=\"dark\"] {\n\t--background: 219 53% 12%; /* #0b162c */\n\t--foreground: 216 33% 93%; /* #f7f9fc */\n\n\t--card: 220 52% 11%; /* #101c32 */\n\t--card-foreground: 216 33% 93%;\n\n\t--popover: 220 52% 11%;\n\t--popover-foreground: 216 33% 93%;\n\n\t--primary: 220 59% 15%;\n\t--primary-foreground: 0 0% 100%;\n\n\t--secondary: 173 46% 44%;\n\t--secondary-foreground: 219 53% 12%;\n\n\t--muted: 221 53% 12%;\n\t--muted-foreground: 217 23% 75%; /* improved contrast for WCAG AA */\n\n\t--accent: 222 44% 16%;\n\t--accent-foreground: 216 33% 93%;\n\n\t--destructive: 0 70% 71%;\n\t--destructive-foreground: 219 53% 12%;\n\n\t--border: 222 30% 21%;\n\t--input: 222 30% 21%;\n\t--ring: 173 46% 44%;\n\n\t--success: 157 48% 47%;\n\t--warning: 41 54% 62%;\n\t--error: 0 70% 71%;\n}\n\n* {\n\tborder-color: var(--color-border);\n}\n\nbody {\n\tbackground-color: var(--color-background);\n\tcolor: var(--color-foreground);\n\tmin-height: 100vh;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\nhtml {\n\topacity: 0;\n}\n\nhtml[data-theme=\"dark\"],\nhtml[data-theme=\"light\"] {\n\topacity: initial;\n}\n\n/* Container utility - matching web app */\n.container {\n\twidth: 100%;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tpadding-left: 1rem;\n\tpadding-right: 1rem;\n\tmax-width: 96rem;\n}\n\n/* Hero typography - matching web app exactly */\n.hero-content h1 {\n\tfont-size: 2.25rem !important; /* text-4xl */\n\tline-height: 2.5rem !important; /* text-4xl line-height */\n\tfont-weight: 700 !important; /* font-bold */\n\tletter-spacing: -0.025em !important; /* tracking-tight */\n\tmargin-bottom: 1.5rem !important; /* mb-6 */\n\tcolor: hsl(var(--foreground)) !important;\n}\n\n.hero-content p {\n\tfont-size: 1.25rem !important; /* text-xl */\n\tline-height: 1.75rem !important; /* text-xl line-height */\n\tcolor: hsl(var(--muted-foreground)) !important;\n\tmax-width: 42rem; /* max-w-2xl */\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tmargin-bottom: 2rem !important; /* mb-8 */\n}\n\n.hero-content--dark h1 {\n\tcolor: white !important;\n}\n\n.hero-content--dark p {\n\tcolor: rgba(255, 255, 255, 0.8) !important;\n}\n\n@media (min-width: 768px) {\n\t.hero-content h1 {\n\t\tfont-size: 3.75rem !important; /* md:text-6xl */\n\t\tline-height: 1 !important; /* text-6xl line-height */\n\t}\n}\n\n@media (min-width: 640px) {\n\t.container {\n\t\tpadding-left: 1.5rem;\n\t\tpadding-right: 1.5rem;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.container {\n\t\tpadding-left: 2rem;\n\t\tpadding-right: 2rem;\n\t}\n}\n\n/* ========================================\n PRODUCT SHOWCASE HERO STYLES\n ======================================== */\n\n/* Left-aligned hero content */\n.hero-content--left h1 {\n\ttext-align: left !important;\n\tmargin-left: 0 !important;\n\tmargin-right: 0 !important;\n}\n\n.hero-content--left p {\n\ttext-align: left !important;\n\tmargin-left: 0 !important;\n\tmargin-right: 0 !important;\n}\n\n/* Hero showcase section */\n.hero-showcase {\n\tposition: relative;\n\tborder-radius: 12px;\n\toverflow: hidden;\n\tpadding: 3rem;\n\tmin-height: 500px;\n}\n\n@media (min-width: 768px) {\n\t.hero-showcase {\n\t\tmin-height: 600px;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.hero-showcase {\n\t\tmin-height: 700px;\n\t}\n}\n\n/* Hero background image */\n.hero-bg-image {\n\tposition: absolute;\n\tinset: 0;\n\tz-index: 0;\n}\n\n.hero-bg-image img {\n\twidth: 100%;\n\theight: 100%;\n\tobject-fit: cover;\n\tobject-position: center;\n}\n\n/* Mockup centered within background */\n.hero-mockup-centered {\n\tposition: relative;\n\tz-index: 10;\n\tmax-width: 800px;\n\tmargin: 0 auto;\n\twidth: 100%;\n}\n\n@media (min-width: 768px) {\n\t.hero-mockup-centered {\n\t\tmax-width: 900px;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.hero-mockup-centered {\n\t\tmax-width: 1000px;\n\t}\n}\n\n.mockup-wrapper {\n\tbackground: hsl(var(--background));\n\tborder-radius: 12px;\n\tbox-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 12px 24px -8px rgba(0, 0, 0, 0.15), 0 0 0 1px\n\t\trgba(0, 0, 0, 0.05);\n\toverflow: hidden;\n\tanimation: mockup-entrance 0.8s ease-out;\n\twidth: 100%;\n}\n\n.mockup-wrapper img {\n\twidth: 100%;\n\theight: auto;\n\tdisplay: block;\n}\n\n@keyframes mockup-entrance {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(30px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n/* Browser chrome */\n.mockup-chrome {\n\tdisplay: flex;\n\talign-items: center;\n\tpadding: 12px 16px;\n\tbackground: hsl(var(--muted));\n\tborder-bottom: 1px solid hsl(var(--border));\n}\n\n.mockup-chrome-dots {\n\tdisplay: flex;\n\tgap: 6px;\n}\n\n.mockup-chrome-dots .dot {\n\twidth: 12px;\n\theight: 12px;\n\tborder-radius: 50%;\n}\n\n.mockup-chrome-dots .dot-red {\n\tbackground: #ff5f56;\n}\n.mockup-chrome-dots .dot-yellow {\n\tbackground: #ffbd2e;\n}\n.mockup-chrome-dots .dot-green {\n\tbackground: #27ca40;\n}\n\n.mockup-chrome-title {\n\tflex: 1;\n\ttext-align: center;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcolor: hsl(var(--muted-foreground));\n}\n\n.mockup-chrome-actions {\n\twidth: 60px;\n}\n\n/* App content layout */\n.mockup-content {\n\tdisplay: flex;\n\tmin-height: 400px;\n}\n\n.mockup-sidebar {\n\twidth: 220px;\n\tbackground: hsl(var(--card));\n\tborder-right: 1px solid hsl(var(--border));\n\tflex-shrink: 0;\n}\n\n.sidebar-header {\n\tpadding: 16px;\n\tborder-bottom: 1px solid hsl(var(--border));\n}\n\n.sidebar-logo {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n}\n\n.logo-icon {\n\twidth: 28px;\n\theight: 28px;\n\tbackground: hsl(var(--primary));\n\tcolor: white;\n\tborder-radius: 6px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tfont-weight: 700;\n\tfont-size: 14px;\n}\n\n.logo-text {\n\tfont-weight: 600;\n\tfont-size: 14px;\n\tcolor: hsl(var(--foreground));\n}\n\n.sidebar-nav {\n\tpadding: 8px;\n}\n\n.sidebar-item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tpadding: 10px 12px;\n\tborder-radius: 6px;\n\tfont-size: 13px;\n\tcolor: hsl(var(--muted-foreground));\n\ttransition: all 0.15s ease;\n\tcursor: pointer;\n}\n\n.sidebar-item:hover {\n\tbackground: hsl(var(--accent));\n\tcolor: hsl(var(--accent-foreground));\n}\n\n.sidebar-item--active {\n\tbackground: hsl(var(--primary) / 0.12);\n\tcolor: hsl(var(--primary));\n}\n\n.sidebar-icon {\n\tfont-size: 16px;\n}\n\n.sidebar-label {\n\tflex: 1;\n}\n\n.sidebar-badge {\n\tbackground: hsl(var(--primary));\n\tcolor: hsl(var(--primary-foreground));\n\tfont-size: 11px;\n\tpadding: 2px 6px;\n\tborder-radius: 10px;\n\tfont-weight: 500;\n}\n\n/* Main content area */\n.mockup-main {\n\tflex: 1;\n\tdisplay: flex;\n\tflex-direction: column;\n\tbackground: hsl(var(--background));\n}\n\n.main-header {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tpadding: 16px 20px;\n\tborder-bottom: 1px solid hsl(var(--border));\n}\n\n.header-title {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n.header-title h2 {\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tmargin: 0;\n\tcolor: hsl(var(--foreground));\n}\n\n.header-breadcrumb {\n\tfont-size: 12px;\n\tcolor: hsl(var(--muted-foreground));\n}\n\n.header-actions {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.action-btn {\n\tpadding: 8px 16px;\n\tbackground: hsl(var(--primary));\n\tcolor: hsl(var(--primary-foreground));\n\tborder: none;\n\tborder-radius: 6px;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.3s ease;\n}\n\n.action-btn--success {\n\tbackground: #27ca40;\n}\n\n.action-btn--featured {\n\tbackground: hsl(var(--primary));\n}\n\n/* Split view */\n.main-split {\n\tdisplay: flex;\n\tflex: 1;\n}\n\n.editor-panel {\n\tflex: 1;\n\tpadding: 20px;\n\tborder-right: 1px solid hsl(var(--border));\n}\n\n.editor-section {\n\tmargin-bottom: 20px;\n}\n\n.editor-label {\n\tdisplay: block;\n\tfont-size: 12px;\n\tfont-weight: 500;\n\tcolor: hsl(var(--muted-foreground));\n\tmargin-bottom: 6px;\n}\n\n.editor-input {\n\tbackground: hsl(var(--muted));\n\tborder: 1px solid hsl(var(--border));\n\tborder-radius: 6px;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tcolor: hsl(var(--foreground));\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.input-text {\n\tflex: 1;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.input-cursor {\n\twidth: 2px;\n\theight: 18px;\n\tbackground: #6c4cff;\n\tanimation: blink 1s infinite;\n\tmargin-left: 2px;\n}\n\n@keyframes blink {\n\t0%,\n\t50% {\n\t\topacity: 1;\n\t}\n\t51%,\n\t100% {\n\t\topacity: 0;\n\t}\n}\n\n.editor-select {\n\tbackground: hsl(var(--muted));\n\tborder: 1px solid hsl(var(--border));\n\tborder-radius: 6px;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tcolor: hsl(var(--foreground));\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n}\n\n.select-arrow {\n\tfont-size: 10px;\n\tcolor: hsl(var(--muted-foreground));\n}\n\n.editor-textarea {\n\tbackground: hsl(var(--muted));\n\tborder: 1px solid hsl(var(--border));\n\tborder-radius: 6px;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tcolor: hsl(var(--foreground));\n\tmin-height: 80px;\n}\n\n.textarea-text {\n\ttransition: all 0.5s ease;\n}\n\n.textarea-text--complete {\n\tcolor: hsl(var(--foreground));\n}\n\n/* Preview panel */\n.preview-panel {\n\twidth: 320px;\n\tpadding: 20px;\n\tbackground: hsl(var(--muted) / 0.5);\n}\n\n.preview-header {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tmargin-bottom: 16px;\n}\n\n.preview-label {\n\tfont-size: 12px;\n\tfont-weight: 500;\n\tcolor: hsl(var(--muted-foreground));\n}\n\n.preview-url {\n\tfont-size: 11px;\n\tcolor: hsl(var(--muted-foreground));\n\tfont-family: monospace;\n}\n\n.preview-card {\n\tbackground: hsl(var(--card));\n\tborder: 1px solid hsl(var(--border));\n\tborder-radius: 10px;\n\toverflow: hidden;\n\tposition: relative;\n\ttransition: all 0.3s ease;\n}\n\n.preview-badge {\n\tposition: absolute;\n\ttop: 10px;\n\tright: 10px;\n\tbackground: hsl(var(--primary));\n\tcolor: white;\n\tfont-size: 11px;\n\tpadding: 4px 8px;\n\tborder-radius: 4px;\n\tfont-weight: 500;\n\tanimation: badge-pop 0.3s ease;\n}\n\n@keyframes badge-pop {\n\tfrom {\n\t\ttransform: scale(0);\n\t\topacity: 0;\n\t}\n\tto {\n\t\ttransform: scale(1);\n\t\topacity: 1;\n\t}\n}\n\n.preview-image {\n\theight: 120px;\n\tbackground: linear-gradient(135deg, hsl(var(--muted)) 0%, hsl(var(--accent)) 100%);\n}\n\n.preview-image-placeholder {\n\twidth: 100%;\n\theight: 100%;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tfont-size: 40px;\n}\n\n.preview-content {\n\tpadding: 16px;\n}\n\n.preview-category-tag {\n\tdisplay: inline-block;\n\tfont-size: 11px;\n\tcolor: hsl(var(--primary));\n\tfont-weight: 500;\n\tmargin-bottom: 8px;\n}\n\n.preview-title {\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tmargin: 0 0 8px;\n\tcolor: hsl(var(--foreground));\n}\n\n.preview-description {\n\tfont-size: 13px;\n\tcolor: hsl(var(--muted-foreground));\n\tline-height: 1.5;\n\tmargin: 0 0 12px;\n}\n\n.preview-meta {\n\tdisplay: flex;\n\tgap: 8px;\n\tfont-size: 12px;\n}\n\n.meta-rating {\n\tcolor: #ffc24a;\n}\n\n.meta-reviews {\n\tcolor: hsl(var(--muted-foreground));\n}\n\n/* State indicators */\n.mockup-indicators {\n\tdisplay: flex;\n\tjustify-content: center;\n\tgap: 24px;\n\tpadding: 16px;\n\tborder-top: 1px solid hsl(var(--border));\n}\n\n.indicator {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\tpadding: 6px 12px;\n\tborder-radius: 20px;\n\ttransition: all 0.2s ease;\n}\n\n.indicator:hover {\n\tbackground: hsl(var(--accent));\n}\n\n.indicator--active {\n\tbackground: hsl(var(--primary) / 0.12);\n}\n\n.indicator-dot {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tbackground: hsl(var(--muted-foreground));\n\ttransition: all 0.2s ease;\n}\n\n.indicator--active .indicator-dot {\n\tbackground: hsl(var(--primary));\n\tbox-shadow: 0 0 0 3px hsl(var(--primary) / 0.2);\n}\n\n.indicator-label {\n\tfont-size: 12px;\n\tcolor: hsl(var(--muted-foreground));\n}\n\n.indicator--active .indicator-label {\n\tcolor: hsl(var(--foreground));\n\tfont-weight: 500;\n}\n\n/* ========================================\n LOGO BANNER STYLES\n ======================================== */\n\n.logo-scroll-container {\n\toverflow: hidden;\n\tmask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);\n}\n\n.logo-scroll-track {\n\tdisplay: flex;\n\tanimation: logo-scroll 30s linear infinite;\n}\n\n.logo-scroll-track:hover {\n\tanimation-play-state: paused;\n}\n\n@keyframes logo-scroll {\n\t0% {\n\t\ttransform: translateX(0);\n\t}\n\t100% {\n\t\ttransform: translateX(-50%);\n\t}\n}\n\n.logo-item {\n\tflex-shrink: 0;\n\tmin-width: 150px;\n}\n\n/* ========================================\n RESPONSIVE ADJUSTMENTS\n ======================================== */\n\n@media (max-width: 768px) {\n\t.mockup-content {\n\t\tflex-direction: column;\n\t}\n\n\t.mockup-sidebar {\n\t\twidth: 100%;\n\t\tborder-right: none;\n\t\tborder-bottom: 1px solid hsl(var(--border));\n\t}\n\n\t.sidebar-nav {\n\t\tdisplay: flex;\n\t\toverflow-x: auto;\n\t\tpadding: 8px;\n\t\tgap: 4px;\n\t}\n\n\t.sidebar-item {\n\t\twhite-space: nowrap;\n\t}\n\n\t.main-split {\n\t\tflex-direction: column;\n\t}\n\n\t.editor-panel {\n\t\tborder-right: none;\n\t\tborder-bottom: 1px solid hsl(var(--border));\n\t}\n\n\t.preview-panel {\n\t\twidth: 100%;\n\t}\n\n\t.mockup-indicators {\n\t\tflex-wrap: wrap;\n\t\tgap: 12px;\n\t}\n\n\t.indicator-label {\n\t\tdisplay: none;\n\t}\n}\n\n/* ========================================\n BIRD-INSPIRED BLOCK STYLES\n ======================================== */\n\n/* Industry Tabs Animation */\n.industry-tab-content {\n\tanimation: tab-fade-in 0.3s ease-out;\n}\n\n@keyframes tab-fade-in {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(10px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n/* Feature Showcase Entrance Animation */\n@keyframes feature-slide-in {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateX(-20px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n}\n\n.feature-showcase-content {\n\tanimation: feature-slide-in 0.5s ease-out;\n}\n\n/* Testimonial Card Hover Effects */\n.testimonial-card {\n\ttransition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.testimonial-card:hover {\n\ttransform: translateY(-4px);\n\tbox-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);\n}\n\n/* Stat Number Animation */\n@keyframes stat-count-up {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(20px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.stat-number {\n\tanimation: stat-count-up 0.6s ease-out;\n}\n\n/* Trust Column Icon Animation */\n.trust-icon {\n\ttransition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.trust-icon:hover {\n\ttransform: scale(1.1);\n}\n\n/* Final CTA Background Animation */\n@keyframes subtle-float {\n\t0%,\n\t100% {\n\t\ttransform: translateY(0);\n\t}\n\t50% {\n\t\ttransform: translateY(-10px);\n\t}\n}\n\n.cta-decorative {\n\tanimation: subtle-float 6s ease-in-out infinite;\n}\n\n/* Feature Grid Card Entrance */\n@keyframes card-entrance {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(20px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.feature-card {\n\tanimation: card-entrance 0.4s ease-out;\n\tanimation-fill-mode: both;\n}\n\n.feature-card:nth-child(1) {\n\tanimation-delay: 0.1s;\n}\n.feature-card:nth-child(2) {\n\tanimation-delay: 0.2s;\n}\n.feature-card:nth-child(3) {\n\tanimation-delay: 0.3s;\n}\n.feature-card:nth-child(4) {\n\tanimation-delay: 0.4s;\n}\n.feature-card:nth-child(5) {\n\tanimation-delay: 0.5s;\n}\n.feature-card:nth-child(6) {\n\tanimation-delay: 0.6s;\n}\n\n/* Smooth Section Transitions */\nsection {\n\tscroll-margin-top: 80px;\n}\n\n/* Button Hover Enhancement */\n.cta-button {\n\tposition: relative;\n\toverflow: hidden;\n}\n\n.cta-button::after {\n\tcontent: \"\";\n\tposition: absolute;\n\tinset: 0;\n\tbackground: linear-gradient(rgba(255, 255, 255, 0.1), transparent);\n\topacity: 0;\n\ttransition: opacity 0.3s ease;\n}\n\n.cta-button:hover::after {\n\topacity: 1;\n}\n\n/* Responsive Image Container */\n.feature-image-container {\n\tposition: relative;\n\tborder-radius: 12px;\n\toverflow: hidden;\n\tbox-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15);\n\ttransition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.feature-image-container:hover {\n\ttransform: translateY(-4px);\n\tbox-shadow: 0 30px 60px -15px rgba(0, 0, 0, 0.2);\n}\n",
|
|
87
|
+
"marketing/payload/src/app/(frontend)/globals.css.hbs": "@import \"tailwindcss\";\n@import \"tw-animate-css\";\n@plugin \"@tailwindcss/typography\";\n\n@custom-variant dark (&:where([data-theme=\"dark\"], [data-theme=\"dark\"] *));\n\n@theme inline {\n\t/* Colors */\n\t--color-background: var(--background);\n\t--color-foreground: var(--foreground);\n\n\t--color-card: var(--card);\n\t--color-card-foreground: var(--card-foreground);\n\n\t--color-popover: var(--popover);\n\t--color-popover-foreground: var(--popover-foreground);\n\n\t--color-primary: var(--primary);\n\t--color-primary-foreground: var(--primary-foreground);\n\n\t--color-secondary: var(--secondary);\n\t--color-secondary-foreground: var(--secondary-foreground);\n\n\t--color-muted: var(--muted);\n\t--color-muted-foreground: var(--muted-foreground);\n\n\t--color-accent: var(--accent);\n\t--color-accent-foreground: var(--accent-foreground);\n\n\t--color-destructive: var(--destructive);\n\n\t--color-border: var(--border);\n\t--color-input: var(--input);\n\t--color-ring: var(--ring);\n\n\t--color-chart-1: var(--chart-1);\n\t--color-chart-2: var(--chart-2);\n\t--color-chart-3: var(--chart-3);\n\t--color-chart-4: var(--chart-4);\n\t--color-chart-5: var(--chart-5);\n\n\t/* Border radius */\n\t--radius-sm: calc(var(--radius) - 4px);\n\t--radius-md: calc(var(--radius) - 2px);\n\t--radius-lg: var(--radius);\n\t--radius-xl: calc(var(--radius) + 4px);\n\n\t/* Fonts */\n\t--font-sans: var(--font-inter), system-ui, sans-serif;\n\t--font-mono: var(--font-geist-mono), monospace;\n\n\t/* Container */\n\t--container-sm: 40rem;\n\t--container-md: 48rem;\n\t--container-lg: 64rem;\n\t--container-xl: 80rem;\n\t--container-2xl: 96rem;\n\n\t/* Animations */\n\t--animate-accordion-down: accordion-down 0.2s ease-out;\n\t--animate-accordion-up: accordion-up 0.2s ease-out;\n}\n\n@keyframes accordion-down {\n\tfrom {\n\t\theight: 0;\n\t}\n\tto {\n\t\theight: var(--radix-accordion-content-height);\n\t}\n}\n\n@keyframes accordion-up {\n\tfrom {\n\t\theight: var(--radix-accordion-content-height);\n\t}\n\tto {\n\t\theight: 0;\n\t}\n}\n\n/* ========================================\n THEME COLOR VARIABLES\n Each theme color changes --primary, --ring, and --chart-* values\n Base colors (background, card, muted, etc.) remain consistent\n ======================================== */\n\n:root {\n\t--radius: 0.625rem;\n\t--background: oklch(1 0 0);\n\t--foreground: oklch(0.145 0 0);\n\t--card: oklch(1 0 0);\n\t--card-foreground: oklch(0.145 0 0);\n\t--popover: oklch(1 0 0);\n\t--popover-foreground: oklch(0.145 0 0);\n\t--secondary: oklch(0.97 0 0);\n\t--secondary-foreground: oklch(0.205 0 0);\n\t--muted: oklch(0.97 0 0);\n\t--muted-foreground: oklch(0.556 0 0);\n\t--accent: oklch(0.97 0 0);\n\t--accent-foreground: oklch(0.205 0 0);\n\t--destructive: oklch(0.577 0.245 27.325);\n\t--border: oklch(0.922 0 0);\n\t--input: oklch(0.922 0 0);\n\n{{#if (eq shadcn.themeColor \"neutral\")}}\n\t/* Neutral theme */\n\t--primary: oklch(0.205 0 0);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.708 0 0);\n\t--chart-1: oklch(0.646 0.222 41.116);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"blue\")}}\n\t/* Blue theme */\n\t--primary: oklch(0.546 0.245 262.881);\n\t--primary-foreground: oklch(0.985 0.002 247.858);\n\t--ring: oklch(0.546 0.245 262.881);\n\t--chart-1: oklch(0.546 0.245 262.881);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"green\")}}\n\t/* Green theme */\n\t--primary: oklch(0.596 0.145 163.225);\n\t--primary-foreground: oklch(0.982 0.018 155.826);\n\t--ring: oklch(0.596 0.145 163.225);\n\t--chart-1: oklch(0.596 0.145 163.225);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"purple\")}}\n\t/* Purple theme */\n\t--primary: oklch(0.627 0.265 303.9);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.627 0.265 303.9);\n\t--chart-1: oklch(0.627 0.265 303.9);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"red\")}}\n\t/* Red theme */\n\t--primary: oklch(0.637 0.237 25.331);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.637 0.237 25.331);\n\t--chart-1: oklch(0.637 0.237 25.331);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"orange\")}}\n\t/* Orange theme */\n\t--primary: oklch(0.705 0.191 47.604);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.705 0.191 47.604);\n\t--chart-1: oklch(0.705 0.191 47.604);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"amber\")}}\n\t/* Amber theme */\n\t--primary: oklch(0.769 0.188 70.08);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.769 0.188 70.08);\n\t--chart-1: oklch(0.769 0.188 70.08);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.646 0.222 41.116);\n{{else if (eq shadcn.themeColor \"cyan\")}}\n\t/* Cyan theme */\n\t--primary: oklch(0.715 0.143 215.221);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.715 0.143 215.221);\n\t--chart-1: oklch(0.715 0.143 215.221);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"emerald\")}}\n\t/* Emerald theme */\n\t--primary: oklch(0.696 0.17 162.48);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.696 0.17 162.48);\n\t--chart-1: oklch(0.696 0.17 162.48);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"fuchsia\")}}\n\t/* Fuchsia theme */\n\t--primary: oklch(0.667 0.295 322.15);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.667 0.295 322.15);\n\t--chart-1: oklch(0.667 0.295 322.15);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"indigo\")}}\n\t/* Indigo theme */\n\t--primary: oklch(0.585 0.233 277.117);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.585 0.233 277.117);\n\t--chart-1: oklch(0.585 0.233 277.117);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"lime\")}}\n\t/* Lime theme */\n\t--primary: oklch(0.768 0.233 130.85);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.768 0.233 130.85);\n\t--chart-1: oklch(0.768 0.233 130.85);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"pink\")}}\n\t/* Pink theme */\n\t--primary: oklch(0.718 0.202 349.761);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.718 0.202 349.761);\n\t--chart-1: oklch(0.718 0.202 349.761);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"rose\")}}\n\t/* Rose theme */\n\t--primary: oklch(0.645 0.246 16.439);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.645 0.246 16.439);\n\t--chart-1: oklch(0.645 0.246 16.439);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"sky\")}}\n\t/* Sky theme */\n\t--primary: oklch(0.685 0.169 237.323);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.685 0.169 237.323);\n\t--chart-1: oklch(0.685 0.169 237.323);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"teal\")}}\n\t/* Teal theme */\n\t--primary: oklch(0.704 0.14 182.503);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.704 0.14 182.503);\n\t--chart-1: oklch(0.704 0.14 182.503);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"violet\")}}\n\t/* Violet theme */\n\t--primary: oklch(0.606 0.25 292.717);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.606 0.25 292.717);\n\t--chart-1: oklch(0.606 0.25 292.717);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else if (eq shadcn.themeColor \"yellow\")}}\n\t/* Yellow theme */\n\t--primary: oklch(0.795 0.184 86.047);\n\t--primary-foreground: oklch(0.216 0.006 56.043);\n\t--ring: oklch(0.795 0.184 86.047);\n\t--chart-1: oklch(0.795 0.184 86.047);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.646 0.222 41.116);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{else}}\n\t/* Default to neutral */\n\t--primary: oklch(0.205 0 0);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.708 0 0);\n\t--chart-1: oklch(0.646 0.222 41.116);\n\t--chart-2: oklch(0.6 0.118 184.704);\n\t--chart-3: oklch(0.398 0.07 227.392);\n\t--chart-4: oklch(0.828 0.189 84.429);\n\t--chart-5: oklch(0.769 0.188 70.08);\n{{/if}}\n}\n\n[data-theme=\"dark\"] {\n\t--background: oklch(0.145 0 0);\n\t--foreground: oklch(0.985 0 0);\n\t--card: oklch(0.205 0 0);\n\t--card-foreground: oklch(0.985 0 0);\n\t--popover: oklch(0.269 0 0);\n\t--popover-foreground: oklch(0.985 0 0);\n\t--secondary: oklch(0.269 0 0);\n\t--secondary-foreground: oklch(0.985 0 0);\n\t--muted: oklch(0.269 0 0);\n\t--muted-foreground: oklch(0.708 0 0);\n\t--accent: oklch(0.371 0 0);\n\t--accent-foreground: oklch(0.985 0 0);\n\t--destructive: oklch(0.704 0.191 22.216);\n\t--border: oklch(1 0 0 / 10%);\n\t--input: oklch(1 0 0 / 15%);\n\n{{#if (eq shadcn.themeColor \"neutral\")}}\n\t/* Neutral theme - dark mode */\n\t--primary: oklch(0.922 0 0);\n\t--primary-foreground: oklch(0.205 0 0);\n\t--ring: oklch(0.556 0 0);\n\t--chart-1: oklch(0.488 0.243 264.376);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"blue\")}}\n\t/* Blue theme - dark mode */\n\t--primary: oklch(0.623 0.214 262.881);\n\t--primary-foreground: oklch(0.273 0.033 256.848);\n\t--ring: oklch(0.623 0.214 262.881);\n\t--chart-1: oklch(0.623 0.214 262.881);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"green\")}}\n\t/* Green theme - dark mode */\n\t--primary: oklch(0.696 0.17 162.48);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.696 0.17 162.48);\n\t--chart-1: oklch(0.696 0.17 162.48);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"purple\")}}\n\t/* Purple theme - dark mode */\n\t--primary: oklch(0.714 0.203 305.504);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.714 0.203 305.504);\n\t--chart-1: oklch(0.714 0.203 305.504);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.488 0.243 264.376);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"red\")}}\n\t/* Red theme - dark mode */\n\t--primary: oklch(0.704 0.191 22.216);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.704 0.191 22.216);\n\t--chart-1: oklch(0.704 0.191 22.216);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor \"orange\")}}\n\t/* Orange theme - dark mode */\n\t--primary: oklch(0.792 0.17 52.615);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.792 0.17 52.615);\n\t--chart-1: oklch(0.792 0.17 52.615);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"amber\")}}\n\t/* Amber theme - dark mode */\n\t--primary: oklch(0.828 0.189 84.429);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.828 0.189 84.429);\n\t--chart-1: oklch(0.828 0.189 84.429);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.488 0.243 264.376);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"cyan\")}}\n\t/* Cyan theme - dark mode */\n\t--primary: oklch(0.789 0.154 211.53);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.789 0.154 211.53);\n\t--chart-1: oklch(0.789 0.154 211.53);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"emerald\")}}\n\t/* Emerald theme - dark mode */\n\t--primary: oklch(0.765 0.166 160.391);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.765 0.166 160.391);\n\t--chart-1: oklch(0.765 0.166 160.391);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"fuchsia\")}}\n\t/* Fuchsia theme - dark mode */\n\t--primary: oklch(0.74 0.238 322.16);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.74 0.238 322.16);\n\t--chart-1: oklch(0.74 0.238 322.16);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.488 0.243 264.376);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"indigo\")}}\n\t/* Indigo theme - dark mode */\n\t--primary: oklch(0.673 0.182 276.935);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.673 0.182 276.935);\n\t--chart-1: oklch(0.673 0.182 276.935);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"lime\")}}\n\t/* Lime theme - dark mode */\n\t--primary: oklch(0.841 0.238 128.85);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.841 0.238 128.85);\n\t--chart-1: oklch(0.841 0.238 128.85);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"pink\")}}\n\t/* Pink theme - dark mode */\n\t--primary: oklch(0.775 0.181 349.761);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.775 0.181 349.761);\n\t--chart-1: oklch(0.775 0.181 349.761);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor \"rose\")}}\n\t/* Rose theme - dark mode */\n\t--primary: oklch(0.712 0.194 13.428);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.712 0.194 13.428);\n\t--chart-1: oklch(0.712 0.194 13.428);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.488 0.243 264.376);\n{{else if (eq shadcn.themeColor \"sky\")}}\n\t/* Sky theme - dark mode */\n\t--primary: oklch(0.756 0.143 232.661);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.756 0.143 232.661);\n\t--chart-1: oklch(0.756 0.143 232.661);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"teal\")}}\n\t/* Teal theme - dark mode */\n\t--primary: oklch(0.777 0.152 181.912);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.777 0.152 181.912);\n\t--chart-1: oklch(0.777 0.152 181.912);\n\t--chart-2: oklch(0.488 0.243 264.376);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"violet\")}}\n\t/* Violet theme - dark mode */\n\t--primary: oklch(0.702 0.183 293.541);\n\t--primary-foreground: oklch(0.985 0 0);\n\t--ring: oklch(0.702 0.183 293.541);\n\t--chart-1: oklch(0.702 0.183 293.541);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.488 0.243 264.376);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else if (eq shadcn.themeColor \"yellow\")}}\n\t/* Yellow theme - dark mode */\n\t--primary: oklch(0.852 0.199 91.936);\n\t--primary-foreground: oklch(0.15 0 0);\n\t--ring: oklch(0.852 0.199 91.936);\n\t--chart-1: oklch(0.852 0.199 91.936);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.488 0.243 264.376);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{else}}\n\t/* Default to neutral - dark mode */\n\t--primary: oklch(0.922 0 0);\n\t--primary-foreground: oklch(0.205 0 0);\n\t--ring: oklch(0.556 0 0);\n\t--chart-1: oklch(0.488 0.243 264.376);\n\t--chart-2: oklch(0.696 0.17 162.48);\n\t--chart-3: oklch(0.769 0.188 70.08);\n\t--chart-4: oklch(0.627 0.265 303.9);\n\t--chart-5: oklch(0.645 0.246 16.439);\n{{/if}}\n}\n\n/* ========================================\n BASE STYLES\n ======================================== */\n\n* {\n\tborder-color: var(--color-border);\n}\n\nbody {\n\tbackground-color: var(--color-background);\n\tcolor: var(--color-foreground);\n\tmin-height: 100vh;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\nhtml {\n\topacity: 0;\n}\n\nhtml[data-theme=\"dark\"],\nhtml[data-theme=\"light\"] {\n\topacity: initial;\n}\n\n/* Container utility */\n.container {\n\twidth: 100%;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tpadding-left: 1rem;\n\tpadding-right: 1rem;\n\tmax-width: 96rem;\n}\n\n@media (min-width: 640px) {\n\t.container {\n\t\tpadding-left: 1.5rem;\n\t\tpadding-right: 1.5rem;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.container {\n\t\tpadding-left: 2rem;\n\t\tpadding-right: 2rem;\n\t}\n}\n\n/* ========================================\n HERO TYPOGRAPHY\n ======================================== */\n\n.hero-content h1 {\n\tfont-size: 2.25rem !important;\n\tline-height: 2.5rem !important;\n\tfont-weight: 700 !important;\n\tletter-spacing: -0.025em !important;\n\tmargin-bottom: 1.5rem !important;\n\tcolor: var(--color-foreground) !important;\n}\n\n.hero-content p {\n\tfont-size: 1.25rem !important;\n\tline-height: 1.75rem !important;\n\tcolor: var(--color-muted-foreground) !important;\n\tmax-width: 42rem;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tmargin-bottom: 2rem !important;\n}\n\n.hero-content--dark h1 {\n\tcolor: white !important;\n}\n\n.hero-content--dark p {\n\tcolor: rgba(255, 255, 255, 0.8) !important;\n}\n\n@media (min-width: 768px) {\n\t.hero-content h1 {\n\t\tfont-size: 3.75rem !important;\n\t\tline-height: 1 !important;\n\t}\n}\n\n/* Left-aligned hero content */\n.hero-content--left h1 {\n\ttext-align: left !important;\n\tmargin-left: 0 !important;\n\tmargin-right: 0 !important;\n}\n\n.hero-content--left p {\n\ttext-align: left !important;\n\tmargin-left: 0 !important;\n\tmargin-right: 0 !important;\n}\n\n/* ========================================\n PRODUCT SHOWCASE HERO STYLES\n ======================================== */\n\n.hero-showcase {\n\tposition: relative;\n\tborder-radius: 12px;\n\toverflow: hidden;\n\tpadding: 3rem;\n\tmin-height: 500px;\n}\n\n@media (min-width: 768px) {\n\t.hero-showcase {\n\t\tmin-height: 600px;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.hero-showcase {\n\t\tmin-height: 700px;\n\t}\n}\n\n.hero-bg-image {\n\tposition: absolute;\n\tinset: 0;\n\tz-index: 0;\n}\n\n.hero-bg-image img {\n\twidth: 100%;\n\theight: 100%;\n\tobject-fit: cover;\n\tobject-position: center;\n}\n\n.hero-mockup-centered {\n\tposition: relative;\n\tz-index: 10;\n\tmax-width: 800px;\n\tmargin: 0 auto;\n\twidth: 100%;\n}\n\n@media (min-width: 768px) {\n\t.hero-mockup-centered {\n\t\tmax-width: 900px;\n\t}\n}\n\n@media (min-width: 1024px) {\n\t.hero-mockup-centered {\n\t\tmax-width: 1000px;\n\t}\n}\n\n.mockup-wrapper {\n\tbackground: var(--color-background);\n\tborder-radius: 12px;\n\tbox-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 12px 24px -8px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05);\n\toverflow: hidden;\n\tanimation: mockup-entrance 0.8s ease-out;\n\twidth: 100%;\n}\n\n.mockup-wrapper img {\n\twidth: 100%;\n\theight: auto;\n\tdisplay: block;\n}\n\n@keyframes mockup-entrance {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(30px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n/* Browser chrome */\n.mockup-chrome {\n\tdisplay: flex;\n\talign-items: center;\n\tpadding: 12px 16px;\n\tbackground: var(--color-muted);\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.mockup-chrome-dots {\n\tdisplay: flex;\n\tgap: 6px;\n}\n\n.mockup-chrome-dots .dot {\n\twidth: 12px;\n\theight: 12px;\n\tborder-radius: 50%;\n}\n\n.mockup-chrome-dots .dot-red {\n\tbackground: #ff5f56;\n}\n.mockup-chrome-dots .dot-yellow {\n\tbackground: #ffbd2e;\n}\n.mockup-chrome-dots .dot-green {\n\tbackground: #27ca40;\n}\n\n.mockup-chrome-title {\n\tflex: 1;\n\ttext-align: center;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcolor: var(--color-muted-foreground);\n}\n\n.mockup-chrome-actions {\n\twidth: 60px;\n}\n\n/* App content layout */\n.mockup-content {\n\tdisplay: flex;\n\tmin-height: 400px;\n}\n\n.mockup-sidebar {\n\twidth: 220px;\n\tbackground: var(--color-card);\n\tborder-right: 1px solid var(--color-border);\n\tflex-shrink: 0;\n}\n\n.sidebar-header {\n\tpadding: 16px;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.sidebar-logo {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n}\n\n.logo-icon {\n\twidth: 28px;\n\theight: 28px;\n\tbackground: var(--color-primary);\n\tcolor: white;\n\tborder-radius: 6px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tfont-weight: 700;\n\tfont-size: 14px;\n}\n\n.logo-text {\n\tfont-weight: 600;\n\tfont-size: 14px;\n\tcolor: var(--color-foreground);\n}\n\n.sidebar-nav {\n\tpadding: 8px;\n}\n\n.sidebar-item {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tpadding: 10px 12px;\n\tborder-radius: 6px;\n\tfont-size: 13px;\n\tcolor: var(--color-muted-foreground);\n\ttransition: all 0.15s ease;\n\tcursor: pointer;\n}\n\n.sidebar-item:hover {\n\tbackground: var(--color-accent);\n\tcolor: var(--color-accent-foreground);\n}\n\n.sidebar-item--active {\n\tbackground: oklch(from var(--color-primary) l c h / 0.12);\n\tcolor: var(--color-primary);\n}\n\n.sidebar-icon {\n\tfont-size: 16px;\n}\n\n.sidebar-label {\n\tflex: 1;\n}\n\n.sidebar-badge {\n\tbackground: var(--color-primary);\n\tcolor: var(--color-primary-foreground);\n\tfont-size: 11px;\n\tpadding: 2px 6px;\n\tborder-radius: 10px;\n\tfont-weight: 500;\n}\n\n/* Main content area */\n.mockup-main {\n\tflex: 1;\n\tdisplay: flex;\n\tflex-direction: column;\n\tbackground: var(--color-background);\n}\n\n.main-header {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tpadding: 16px 20px;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.header-title {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n.header-title h2 {\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tmargin: 0;\n\tcolor: var(--color-foreground);\n}\n\n.header-breadcrumb {\n\tfont-size: 12px;\n\tcolor: var(--color-muted-foreground);\n}\n\n.header-actions {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.action-btn {\n\tpadding: 8px 16px;\n\tbackground: var(--color-primary);\n\tcolor: var(--color-primary-foreground);\n\tborder: none;\n\tborder-radius: 6px;\n\tfont-size: 13px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.3s ease;\n}\n\n.action-btn--success {\n\tbackground: #27ca40;\n}\n\n.action-btn--featured {\n\tbackground: var(--color-primary);\n}\n\n/* Split view */\n.main-split {\n\tdisplay: flex;\n\tflex: 1;\n}\n\n.editor-panel {\n\tflex: 1;\n\tpadding: 20px;\n\tborder-right: 1px solid var(--color-border);\n}\n\n.editor-section {\n\tmargin-bottom: 20px;\n}\n\n.editor-label {\n\tdisplay: block;\n\tfont-size: 12px;\n\tfont-weight: 500;\n\tcolor: var(--color-muted-foreground);\n\tmargin-bottom: 6px;\n}\n\n.editor-input {\n\tbackground: var(--color-muted);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 6px;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tcolor: var(--color-foreground);\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.input-text {\n\tflex: 1;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.input-cursor {\n\twidth: 2px;\n\theight: 18px;\n\tbackground: var(--color-primary);\n\tanimation: blink 1s infinite;\n\tmargin-left: 2px;\n}\n\n@keyframes blink {\n\t0%,\n\t50% {\n\t\topacity: 1;\n\t}\n\t51%,\n\t100% {\n\t\topacity: 0;\n\t}\n}\n\n.editor-select {\n\tbackground: var(--color-muted);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 6px;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tcolor: var(--color-foreground);\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n}\n\n.select-arrow {\n\tfont-size: 10px;\n\tcolor: var(--color-muted-foreground);\n}\n\n.editor-textarea {\n\tbackground: var(--color-muted);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 6px;\n\tpadding: 10px 12px;\n\tfont-size: 14px;\n\tcolor: var(--color-foreground);\n\tmin-height: 80px;\n}\n\n.textarea-text {\n\ttransition: all 0.5s ease;\n}\n\n.textarea-text--complete {\n\tcolor: var(--color-foreground);\n}\n\n/* Preview panel */\n.preview-panel {\n\twidth: 320px;\n\tpadding: 20px;\n\tbackground: oklch(from var(--color-muted) l c h / 0.5);\n}\n\n.preview-header {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tmargin-bottom: 16px;\n}\n\n.preview-label {\n\tfont-size: 12px;\n\tfont-weight: 500;\n\tcolor: var(--color-muted-foreground);\n}\n\n.preview-url {\n\tfont-size: 11px;\n\tcolor: var(--color-muted-foreground);\n\tfont-family: monospace;\n}\n\n.preview-card {\n\tbackground: var(--color-card);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 10px;\n\toverflow: hidden;\n\tposition: relative;\n\ttransition: all 0.3s ease;\n}\n\n.preview-badge {\n\tposition: absolute;\n\ttop: 10px;\n\tright: 10px;\n\tbackground: var(--color-primary);\n\tcolor: white;\n\tfont-size: 11px;\n\tpadding: 4px 8px;\n\tborder-radius: 4px;\n\tfont-weight: 500;\n\tanimation: badge-pop 0.3s ease;\n}\n\n@keyframes badge-pop {\n\tfrom {\n\t\ttransform: scale(0);\n\t\topacity: 0;\n\t}\n\tto {\n\t\ttransform: scale(1);\n\t\topacity: 1;\n\t}\n}\n\n.preview-image {\n\theight: 120px;\n\tbackground: linear-gradient(135deg, var(--color-muted) 0%, var(--color-accent) 100%);\n}\n\n.preview-image-placeholder {\n\twidth: 100%;\n\theight: 100%;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tfont-size: 40px;\n}\n\n.preview-content {\n\tpadding: 16px;\n}\n\n.preview-category-tag {\n\tdisplay: inline-block;\n\tfont-size: 11px;\n\tcolor: var(--color-primary);\n\tfont-weight: 500;\n\tmargin-bottom: 8px;\n}\n\n.preview-title {\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tmargin: 0 0 8px;\n\tcolor: var(--color-foreground);\n}\n\n.preview-description {\n\tfont-size: 13px;\n\tcolor: var(--color-muted-foreground);\n\tline-height: 1.5;\n\tmargin: 0 0 12px;\n}\n\n.preview-meta {\n\tdisplay: flex;\n\tgap: 8px;\n\tfont-size: 12px;\n}\n\n.meta-rating {\n\tcolor: #ffc24a;\n}\n\n.meta-reviews {\n\tcolor: var(--color-muted-foreground);\n}\n\n/* State indicators */\n.mockup-indicators {\n\tdisplay: flex;\n\tjustify-content: center;\n\tgap: 24px;\n\tpadding: 16px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.indicator {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\tpadding: 6px 12px;\n\tborder-radius: 20px;\n\ttransition: all 0.2s ease;\n}\n\n.indicator:hover {\n\tbackground: var(--color-accent);\n}\n\n.indicator--active {\n\tbackground: oklch(from var(--color-primary) l c h / 0.12);\n}\n\n.indicator-dot {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tbackground: var(--color-muted-foreground);\n\ttransition: all 0.2s ease;\n}\n\n.indicator--active .indicator-dot {\n\tbackground: var(--color-primary);\n\tbox-shadow: 0 0 0 3px oklch(from var(--color-primary) l c h / 0.2);\n}\n\n.indicator-label {\n\tfont-size: 12px;\n\tcolor: var(--color-muted-foreground);\n}\n\n.indicator--active .indicator-label {\n\tcolor: var(--color-foreground);\n\tfont-weight: 500;\n}\n\n/* ========================================\n LOGO BANNER STYLES\n ======================================== */\n\n.logo-scroll-container {\n\toverflow: hidden;\n\tmask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);\n}\n\n.logo-scroll-track {\n\tdisplay: flex;\n\tanimation: logo-scroll 30s linear infinite;\n}\n\n.logo-scroll-track:hover {\n\tanimation-play-state: paused;\n}\n\n@keyframes logo-scroll {\n\t0% {\n\t\ttransform: translateX(0);\n\t}\n\t100% {\n\t\ttransform: translateX(-50%);\n\t}\n}\n\n.logo-item {\n\tflex-shrink: 0;\n\tmin-width: 150px;\n}\n\n/* ========================================\n RESPONSIVE ADJUSTMENTS\n ======================================== */\n\n@media (max-width: 768px) {\n\t.mockup-content {\n\t\tflex-direction: column;\n\t}\n\n\t.mockup-sidebar {\n\t\twidth: 100%;\n\t\tborder-right: none;\n\t\tborder-bottom: 1px solid var(--color-border);\n\t}\n\n\t.sidebar-nav {\n\t\tdisplay: flex;\n\t\toverflow-x: auto;\n\t\tpadding: 8px;\n\t\tgap: 4px;\n\t}\n\n\t.sidebar-item {\n\t\twhite-space: nowrap;\n\t}\n\n\t.main-split {\n\t\tflex-direction: column;\n\t}\n\n\t.editor-panel {\n\t\tborder-right: none;\n\t\tborder-bottom: 1px solid var(--color-border);\n\t}\n\n\t.preview-panel {\n\t\twidth: 100%;\n\t}\n\n\t.mockup-indicators {\n\t\tflex-wrap: wrap;\n\t\tgap: 12px;\n\t}\n\n\t.indicator-label {\n\t\tdisplay: none;\n\t}\n}\n\n/* ========================================\n ANIMATION STYLES\n ======================================== */\n\n/* Industry Tabs Animation */\n.industry-tab-content {\n\tanimation: tab-fade-in 0.3s ease-out;\n}\n\n@keyframes tab-fade-in {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(10px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n/* Feature Showcase Entrance Animation */\n@keyframes feature-slide-in {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateX(-20px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateX(0);\n\t}\n}\n\n.feature-showcase-content {\n\tanimation: feature-slide-in 0.5s ease-out;\n}\n\n/* Testimonial Card Hover Effects */\n.testimonial-card {\n\ttransition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.testimonial-card:hover {\n\ttransform: translateY(-4px);\n\tbox-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.15);\n}\n\n/* Stat Number Animation */\n@keyframes stat-count-up {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(20px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.stat-number {\n\tanimation: stat-count-up 0.6s ease-out;\n}\n\n/* Trust Column Icon Animation */\n.trust-icon {\n\ttransition: transform 0.2s ease, background-color 0.2s ease;\n}\n\n.trust-icon:hover {\n\ttransform: scale(1.1);\n}\n\n/* Final CTA Background Animation */\n@keyframes subtle-float {\n\t0%,\n\t100% {\n\t\ttransform: translateY(0);\n\t}\n\t50% {\n\t\ttransform: translateY(-10px);\n\t}\n}\n\n.cta-decorative {\n\tanimation: subtle-float 6s ease-in-out infinite;\n}\n\n/* Feature Grid Card Entrance */\n@keyframes card-entrance {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(20px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: translateY(0);\n\t}\n}\n\n.feature-card {\n\tanimation: card-entrance 0.4s ease-out;\n\tanimation-fill-mode: both;\n}\n\n.feature-card:nth-child(1) {\n\tanimation-delay: 0.1s;\n}\n.feature-card:nth-child(2) {\n\tanimation-delay: 0.2s;\n}\n.feature-card:nth-child(3) {\n\tanimation-delay: 0.3s;\n}\n.feature-card:nth-child(4) {\n\tanimation-delay: 0.4s;\n}\n.feature-card:nth-child(5) {\n\tanimation-delay: 0.5s;\n}\n.feature-card:nth-child(6) {\n\tanimation-delay: 0.6s;\n}\n\n/* Smooth Section Transitions */\nsection {\n\tscroll-margin-top: 80px;\n}\n\n/* Button Hover Enhancement */\n.cta-button {\n\tposition: relative;\n\toverflow: hidden;\n}\n\n.cta-button::after {\n\tcontent: \"\";\n\tposition: absolute;\n\tinset: 0;\n\tbackground: linear-gradient(rgba(255, 255, 255, 0.1), transparent);\n\topacity: 0;\n\ttransition: opacity 0.3s ease;\n}\n\n.cta-button:hover::after {\n\topacity: 1;\n}\n\n/* Responsive Image Container */\n.feature-image-container {\n\tposition: relative;\n\tborder-radius: 12px;\n\toverflow: hidden;\n\tbox-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15);\n\ttransition: transform 0.3s ease, box-shadow 0.3s ease;\n}\n\n.feature-image-container:hover {\n\ttransform: translateY(-4px);\n\tbox-shadow: 0 30px 60px -15px rgba(0, 0, 0, 0.2);\n}\n",
|
|
88
88
|
"marketing/payload/src/app/(frontend)/layout.tsx": "import type { Metadata } from \"next\"\n\nimport { cn } from \"@/utilities/ui\"\nimport { GeistMono } from \"geist/font/mono\"\nimport { Inter } from \"next/font/google\"\nimport type React from \"react\"\n\nimport { Footer } from \"@/Footer/Component\"\nimport { Header } from \"@/Header/Component\"\nimport { AdminBar } from \"@/components/AdminBar\"\nimport { JsonLdSchemas } from \"@/components/JsonLd\"\nimport { Providers } from \"@/providers\"\nimport { InitTheme } from \"@/providers/Theme/InitTheme\"\nimport { mergeOpenGraph } from \"@/utilities/mergeOpenGraph\"\nimport { draftMode } from \"next/headers\"\n\nimport { getServerSideURL } from \"@/utilities/getURL\"\nimport \"./globals.css\"\n\nconst inter = Inter({\n\tsubsets: [\"latin\"],\n\tvariable: \"--font-inter\",\n\tdisplay: \"swap\",\n})\n\nexport default async function RootLayout({ children }: { children: React.ReactNode }) {\n\tconst { isEnabled } = await draftMode()\n\n\treturn (\n\t\t<html className={cn(inter.variable, GeistMono.variable)} lang=\"en\" suppressHydrationWarning>\n\t\t\t<head>\n\t\t\t\t<InitTheme />\n\t\t\t\t{/* Favicon */}\n\t\t\t\t<link href=\"/favicon.ico\" rel=\"icon\" sizes=\"32x32\" />\n\t\t\t\t<link href=\"/favicon.svg\" rel=\"icon\" type=\"image/svg+xml\" />\n\n\t\t\t\t{/* Preconnect to external resources for performance */}\n\t\t\t\t<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n\t\t\t\t<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossOrigin=\"anonymous\" />\n\t\t\t\t{/* Preconnect to PostHog proxy for faster analytics initialization */}\n\t\t\t\t<link rel=\"preconnect\" href=\"/ingest\" />\n\n\t\t\t\t{/* DNS prefetch for common external services */}\n\t\t\t\t<link rel=\"dns-prefetch\" href=\"https://www.google-analytics.com\" />\n\t\t\t\t<link rel=\"dns-prefetch\" href=\"https://www.googletagmanager.com\" />\n\n\t\t\t\t{/* JSON-LD Structured Data */}\n\t\t\t\t<JsonLdSchemas />\n\t\t\t</head>\n\t\t\t<body className=\"font-sans antialiased\" suppressHydrationWarning>\n\t\t\t\t<Providers>\n\t\t\t\t\t<AdminBar\n\t\t\t\t\t\tadminBarProps={{\n\t\t\t\t\t\t\tpreview: isEnabled,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t<Header />\n\t\t\t\t\t<main id=\"main-content\" className=\"flex-1\">\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</main>\n\t\t\t\t\t<Footer />\n\t\t\t\t</Providers>\n\t\t\t</body>\n\t\t</html>\n\t)\n}\n\nexport const metadata: Metadata = {\n\tmetadataBase: new URL(getServerSideURL()),\n\ttitle: {\n\t\tdefault: \"SaaSify - The Modern Platform for Growing Teams\",\n\t\ttemplate: \"%s | SaaSify\",\n\t},\n\tdescription:\n\t\t\"Streamline workflows, boost productivity, and scale your business with one powerful platform.\",\n\tkeywords: [\n\t\t\"SaaS platform\",\n\t\t\"team productivity\",\n\t\t\"workflow automation\",\n\t\t\"business software\",\n\t\t\"collaboration tools\",\n\t\t\"project management\",\n\t\t\"team collaboration\",\n\t],\n\tauthors: [{ name: \"SaaSify\", url: getServerSideURL() }],\n\tcreator: \"SaaSify\",\n\tpublisher: \"SaaSify\",\n\trobots: {\n\t\tindex: true,\n\t\tfollow: true,\n\t\tgoogleBot: {\n\t\t\tindex: true,\n\t\t\tfollow: true,\n\t\t\t\"max-video-preview\": -1,\n\t\t\t\"max-image-preview\": \"large\",\n\t\t\t\"max-snippet\": -1,\n\t\t},\n\t},\n\topenGraph: mergeOpenGraph(),\n\ttwitter: {\n\t\tcard: \"summary_large_image\",\n\t\tcreator: \"@saasify\",\n\t\tsite: \"@saasify\",\n\t\ttitle: \"SaaSify - The Modern Platform for Growing Teams\",\n\t\tdescription:\n\t\t\t\"Streamline workflows, boost productivity, and scale your business with one powerful platform.\",\n\t},\n\tverification: {\n\t\t// Add your verification codes here when available\n\t\t// google: 'your-google-verification-code',\n\t\t// yandex: 'your-yandex-verification-code',\n\t},\n}\n",
|
|
89
89
|
"marketing/payload/src/app/(frontend)/next/exit-preview/route.ts": "import { draftMode } from \"next/headers\"\n\nexport async function GET(): Promise<Response> {\n\tconst draft = await draftMode()\n\tdraft.disable()\n\treturn new Response(\"Draft mode is disabled\")\n}\n",
|
|
90
90
|
"marketing/payload/src/app/(frontend)/next/preview/route.ts": "import type { CollectionSlug, PayloadRequest } from \"payload\"\nimport { getPayload } from \"payload\"\n\nimport { draftMode } from \"next/headers\"\nimport { redirect } from \"next/navigation\"\nimport type { NextRequest } from \"next/server\"\n\nimport configPromise from \"@payload-config\"\n\nexport async function GET(req: NextRequest): Promise<Response> {\n\tconst payload = await getPayload({ config: configPromise })\n\n\tconst { searchParams } = new URL(req.url)\n\n\tconst path = searchParams.get(\"path\")\n\tconst collection = searchParams.get(\"collection\") as CollectionSlug\n\tconst slug = searchParams.get(\"slug\")\n\tconst previewSecret = searchParams.get(\"previewSecret\")\n\n\tif (previewSecret !== process.env.PREVIEW_SECRET) {\n\t\treturn new Response(\"You are not allowed to preview this page\", { status: 403 })\n\t}\n\n\tif (!path || !collection || !slug) {\n\t\treturn new Response(\"Insufficient search params\", { status: 404 })\n\t}\n\n\tif (!path.startsWith(\"/\")) {\n\t\treturn new Response(\"This endpoint can only be used for relative previews\", { status: 500 })\n\t}\n\n\tlet user\n\n\ttry {\n\t\tuser = await payload.auth({\n\t\t\treq: req as unknown as PayloadRequest,\n\t\t\theaders: req.headers,\n\t\t})\n\t} catch (error) {\n\t\tpayload.logger.error({ err: error }, \"Error verifying token for live preview\")\n\t\treturn new Response(\"You are not allowed to preview this page\", { status: 403 })\n\t}\n\n\tconst draft = await draftMode()\n\n\tif (!user) {\n\t\tdraft.disable()\n\t\treturn new Response(\"You are not allowed to preview this page\", { status: 403 })\n\t}\n\n\t// You can add additional checks here to see if the user is allowed to preview this page\n\n\tdraft.enable()\n\n\tredirect(path)\n}\n",
|