create-skit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +36 -0
  2. package/bin/create-skit.mjs +1064 -0
  3. package/lib/module-application.mjs +281 -0
  4. package/lib/module-resolver.mjs +179 -0
  5. package/modules/README.md +22 -0
  6. package/modules/ai-dx/files/AGENTS.md +116 -0
  7. package/modules/ai-dx/files/ARCHITECTURE.md +103 -0
  8. package/modules/ai-dx/module.json +14 -0
  9. package/modules/ai-dx-claude/files/CLAUDE.md +8 -0
  10. package/modules/ai-dx-claude/module.json +13 -0
  11. package/modules/ai-dx-cursor/files/.cursor/rules/auth.mdc +53 -0
  12. package/modules/ai-dx-cursor/files/.cursor/rules/database.mdc +48 -0
  13. package/modules/ai-dx-cursor/files/.cursor/rules/env.mdc +43 -0
  14. package/modules/ai-dx-cursor/files/.cursor/rules/nextjs.mdc +58 -0
  15. package/modules/ai-dx-cursor/files/.cursor/rules/project.mdc +33 -0
  16. package/modules/ai-dx-cursor/files/.cursor/rules/testing.mdc +55 -0
  17. package/modules/ai-dx-cursor/module.json +18 -0
  18. package/modules/ai-dx-gemini/files/.gemini/GEMINI.md +5 -0
  19. package/modules/ai-dx-gemini/module.json +13 -0
  20. package/modules/auth-core/module.json +8 -0
  21. package/modules/auth-github/module.json +20 -0
  22. package/modules/billing-polar/module.json +20 -0
  23. package/modules/billing-stripe/module.json +23 -0
  24. package/modules/dashboard-shell/files/src/app/globals.css +756 -0
  25. package/modules/dashboard-shell/files/src/app/settings/page.tsx +67 -0
  26. package/modules/dashboard-shell/module.json +11 -0
  27. package/modules/db-pg/module.json +21 -0
  28. package/modules/db-postgresjs/module.json +21 -0
  29. package/modules/deploy-docker/files/.dockerignore +19 -0
  30. package/modules/deploy-docker/files/Dockerfile +25 -0
  31. package/modules/deploy-docker/module.json +11 -0
  32. package/modules/email-resend/module.json +21 -0
  33. package/modules/quality-baseline/module.json +8 -0
  34. package/modules/testing-baseline/module.json +8 -0
  35. package/package.json +40 -0
  36. package/presets/README.md +12 -0
  37. package/presets/blank.json +67 -0
  38. package/presets/dashboard.json +67 -0
  39. package/templates/base-web/.env.example +17 -0
  40. package/templates/base-web/.github/workflows/ci.yml +34 -0
  41. package/templates/base-web/.husky/pre-commit +3 -0
  42. package/templates/base-web/.husky/pre-push +3 -0
  43. package/templates/base-web/.prettierignore +3 -0
  44. package/templates/base-web/README.md +42 -0
  45. package/templates/base-web/drizzle.config.ts +16 -0
  46. package/templates/base-web/eslint.config.mjs +127 -0
  47. package/templates/base-web/manifest.json +5 -0
  48. package/templates/base-web/next-env.d.ts +4 -0
  49. package/templates/base-web/next.config.ts +5 -0
  50. package/templates/base-web/package.json +75 -0
  51. package/templates/base-web/playwright.config.ts +21 -0
  52. package/templates/base-web/prettier.config.mjs +9 -0
  53. package/templates/base-web/proxy.ts +23 -0
  54. package/templates/base-web/src/app/api/auth/[...all]/route.ts +5 -0
  55. package/templates/base-web/src/app/api/billing/checkout/route.ts +26 -0
  56. package/templates/base-web/src/app/api/billing/portal/route.ts +25 -0
  57. package/templates/base-web/src/app/api/email/test/route.ts +28 -0
  58. package/templates/base-web/src/app/api/webhooks/polar/route.ts +5 -0
  59. package/templates/base-web/src/app/api/webhooks/stripe/route.ts +5 -0
  60. package/templates/base-web/src/app/billing/page.tsx +55 -0
  61. package/templates/base-web/src/app/dashboard/page.tsx +15 -0
  62. package/templates/base-web/src/app/email/page.tsx +46 -0
  63. package/templates/base-web/src/app/error.tsx +27 -0
  64. package/templates/base-web/src/app/globals.css +534 -0
  65. package/templates/base-web/src/app/layout.tsx +19 -0
  66. package/templates/base-web/src/app/llms-full.txt/route.ts +158 -0
  67. package/templates/base-web/src/app/llms.txt/route.ts +59 -0
  68. package/templates/base-web/src/app/loading.tsx +24 -0
  69. package/templates/base-web/src/app/not-found.tsx +16 -0
  70. package/templates/base-web/src/app/page.tsx +5 -0
  71. package/templates/base-web/src/app/sign-in/page.tsx +14 -0
  72. package/templates/base-web/src/app/sign-up/page.tsx +14 -0
  73. package/templates/base-web/src/components/auth/email-auth-form.test.tsx +40 -0
  74. package/templates/base-web/src/components/auth/email-auth-form.tsx +128 -0
  75. package/templates/base-web/src/components/auth/sign-out-button.tsx +29 -0
  76. package/templates/base-web/src/db/index.ts +16 -0
  77. package/templates/base-web/src/db/schema/auth.ts +4 -0
  78. package/templates/base-web/src/db/schema/index.ts +2 -0
  79. package/templates/base-web/src/db/schema/projects.ts +17 -0
  80. package/templates/base-web/src/db/seeds/index.ts +32 -0
  81. package/templates/base-web/src/lib/auth-client.ts +5 -0
  82. package/templates/base-web/src/lib/auth-session.ts +21 -0
  83. package/templates/base-web/src/lib/auth.ts +23 -0
  84. package/templates/base-web/src/lib/billing/index.ts +37 -0
  85. package/templates/base-web/src/lib/billing/providers/polar.ts +80 -0
  86. package/templates/base-web/src/lib/billing/providers/stripe.ts +77 -0
  87. package/templates/base-web/src/lib/billing/types.ts +25 -0
  88. package/templates/base-web/src/lib/email/index.ts +19 -0
  89. package/templates/base-web/src/lib/email/templates.test.ts +12 -0
  90. package/templates/base-web/src/lib/email/templates.ts +40 -0
  91. package/templates/base-web/src/lib/env.ts +83 -0
  92. package/templates/base-web/tests/e2e/home.spec.ts +8 -0
  93. package/templates/base-web/tsconfig.json +34 -0
  94. package/templates/base-web/vitest.config.ts +19 -0
  95. package/templates/blank/.env.example +16 -0
  96. package/templates/blank/.github/workflows/ci.yml +34 -0
  97. package/templates/blank/.husky/pre-commit +3 -0
  98. package/templates/blank/.husky/pre-push +3 -0
  99. package/templates/blank/.prettierignore +3 -0
  100. package/templates/blank/drizzle.config.ts +16 -0
  101. package/templates/blank/eslint.config.mjs +127 -0
  102. package/templates/blank/next-env.d.ts +4 -0
  103. package/templates/blank/next.config.ts +5 -0
  104. package/templates/blank/package.json +75 -0
  105. package/templates/blank/playwright.config.ts +21 -0
  106. package/templates/blank/prettier.config.mjs +9 -0
  107. package/templates/blank/proxy.ts +28 -0
  108. package/templates/blank/src/app/api/auth/[...all]/route.ts +5 -0
  109. package/templates/blank/src/app/api/billing/checkout/route.ts +26 -0
  110. package/templates/blank/src/app/api/billing/portal/route.ts +25 -0
  111. package/templates/blank/src/app/api/email/test/route.ts +28 -0
  112. package/templates/blank/src/app/api/webhooks/polar/route.ts +5 -0
  113. package/templates/blank/src/app/api/webhooks/stripe/route.ts +5 -0
  114. package/templates/blank/src/app/billing/page.tsx +70 -0
  115. package/templates/blank/src/app/email/page.tsx +46 -0
  116. package/templates/blank/src/app/globals.css +394 -0
  117. package/templates/blank/src/app/layout.tsx +19 -0
  118. package/templates/blank/src/app/page.tsx +23 -0
  119. package/templates/blank/src/app/sign-in/page.tsx +18 -0
  120. package/templates/blank/src/app/sign-up/page.tsx +18 -0
  121. package/templates/blank/src/components/auth/email-auth-form.test.tsx +39 -0
  122. package/templates/blank/src/components/auth/email-auth-form.tsx +109 -0
  123. package/templates/blank/src/components/auth/sign-out-button.tsx +29 -0
  124. package/templates/blank/src/db/index.ts +16 -0
  125. package/templates/blank/src/db/schema/auth.ts +4 -0
  126. package/templates/blank/src/db/schema/index.ts +2 -0
  127. package/templates/blank/src/db/schema/projects.ts +17 -0
  128. package/templates/blank/src/db/seeds/index.ts +28 -0
  129. package/templates/blank/src/lib/auth-client.ts +5 -0
  130. package/templates/blank/src/lib/auth-session.ts +11 -0
  131. package/templates/blank/src/lib/auth.ts +23 -0
  132. package/templates/blank/src/lib/billing/index.ts +37 -0
  133. package/templates/blank/src/lib/billing/providers/polar.ts +80 -0
  134. package/templates/blank/src/lib/billing/providers/stripe.ts +77 -0
  135. package/templates/blank/src/lib/billing/types.ts +25 -0
  136. package/templates/blank/src/lib/email/index.ts +19 -0
  137. package/templates/blank/src/lib/email/templates.test.ts +15 -0
  138. package/templates/blank/src/lib/email/templates.ts +40 -0
  139. package/templates/blank/src/lib/env.ts +80 -0
  140. package/templates/blank/tsconfig.json +34 -0
  141. package/templates/blank/vitest.config.ts +19 -0
  142. package/templates/dashboard/.env.example +16 -0
  143. package/templates/dashboard/.github/workflows/ci.yml +34 -0
  144. package/templates/dashboard/.husky/pre-commit +3 -0
  145. package/templates/dashboard/.husky/pre-push +3 -0
  146. package/templates/dashboard/.prettierignore +3 -0
  147. package/templates/dashboard/drizzle.config.ts +16 -0
  148. package/templates/dashboard/eslint.config.mjs +127 -0
  149. package/templates/dashboard/next-env.d.ts +4 -0
  150. package/templates/dashboard/next.config.ts +5 -0
  151. package/templates/dashboard/package.json +75 -0
  152. package/templates/dashboard/playwright.config.ts +21 -0
  153. package/templates/dashboard/prettier.config.mjs +9 -0
  154. package/templates/dashboard/proxy.ts +36 -0
  155. package/templates/dashboard/src/app/api/auth/[...all]/route.ts +5 -0
  156. package/templates/dashboard/src/app/api/billing/checkout/route.ts +26 -0
  157. package/templates/dashboard/src/app/api/billing/portal/route.ts +25 -0
  158. package/templates/dashboard/src/app/api/email/test/route.ts +28 -0
  159. package/templates/dashboard/src/app/api/webhooks/polar/route.ts +5 -0
  160. package/templates/dashboard/src/app/api/webhooks/stripe/route.ts +5 -0
  161. package/templates/dashboard/src/app/billing/layout.tsx +22 -0
  162. package/templates/dashboard/src/app/billing/page.tsx +73 -0
  163. package/templates/dashboard/src/app/dashboard/layout.tsx +22 -0
  164. package/templates/dashboard/src/app/dashboard/page.tsx +104 -0
  165. package/templates/dashboard/src/app/email/layout.tsx +22 -0
  166. package/templates/dashboard/src/app/email/page.tsx +54 -0
  167. package/templates/dashboard/src/app/globals.css +1357 -0
  168. package/templates/dashboard/src/app/layout.tsx +25 -0
  169. package/templates/dashboard/src/app/page.tsx +154 -0
  170. package/templates/dashboard/src/app/settings/layout.tsx +22 -0
  171. package/templates/dashboard/src/app/settings/page.tsx +85 -0
  172. package/templates/dashboard/src/app/sign-in/page.tsx +47 -0
  173. package/templates/dashboard/src/app/sign-up/page.tsx +47 -0
  174. package/templates/dashboard/src/components/auth/email-auth-form.test.tsx +39 -0
  175. package/templates/dashboard/src/components/auth/email-auth-form.tsx +160 -0
  176. package/templates/dashboard/src/components/auth/sign-out-button.tsx +29 -0
  177. package/templates/dashboard/src/components/dashboard/shell.tsx +158 -0
  178. package/templates/dashboard/src/db/index.ts +16 -0
  179. package/templates/dashboard/src/db/schema/auth.ts +4 -0
  180. package/templates/dashboard/src/db/schema/index.ts +2 -0
  181. package/templates/dashboard/src/db/schema/projects.ts +17 -0
  182. package/templates/dashboard/src/db/seeds/index.ts +28 -0
  183. package/templates/dashboard/src/lib/auth-client.ts +5 -0
  184. package/templates/dashboard/src/lib/auth-session.ts +11 -0
  185. package/templates/dashboard/src/lib/auth.ts +41 -0
  186. package/templates/dashboard/src/lib/billing/index.ts +37 -0
  187. package/templates/dashboard/src/lib/billing/providers/polar.ts +80 -0
  188. package/templates/dashboard/src/lib/billing/providers/stripe.ts +77 -0
  189. package/templates/dashboard/src/lib/billing/types.ts +25 -0
  190. package/templates/dashboard/src/lib/email/index.ts +19 -0
  191. package/templates/dashboard/src/lib/email/templates.test.ts +15 -0
  192. package/templates/dashboard/src/lib/email/templates.ts +40 -0
  193. package/templates/dashboard/src/lib/env.ts +88 -0
  194. package/templates/dashboard/tsconfig.json +34 -0
  195. package/templates/dashboard/vitest.config.ts +19 -0
@@ -0,0 +1,1357 @@
1
+ /* ── Skit Dashboard Template ── Design System ─────────────── */
2
+
3
+ @import url("https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700,900&f[]=general-sans@400,500,600&display=swap");
4
+
5
+ /* ── Tokens ─────────────────────────────────────────────────────── */
6
+
7
+ :root {
8
+ --font-display: "Satoshi", system-ui, sans-serif;
9
+ --font-body: "General Sans", system-ui, sans-serif;
10
+ --font-mono: "SF Mono", "Fira Code", "JetBrains Mono", ui-monospace, monospace;
11
+
12
+ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
13
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
14
+
15
+ --radius-sm: 8px;
16
+ --radius-md: 12px;
17
+ --radius-lg: 16px;
18
+ --radius-xl: 24px;
19
+ --radius-full: 9999px;
20
+
21
+ --color-bg: #0a0a0f;
22
+ --color-bg-raised: #111118;
23
+ --color-bg-overlay: #16161f;
24
+ --color-bg-subtle: #1c1c27;
25
+ --color-bg-muted: #23232f;
26
+
27
+ --color-border: rgba(255, 255, 255, 0.06);
28
+ --color-border-hover: rgba(255, 255, 255, 0.12);
29
+ --color-border-active: rgba(255, 255, 255, 0.2);
30
+
31
+ --color-text: #f0eef5;
32
+ --color-text-secondary: #9490a5;
33
+ --color-text-muted: #5e5a70;
34
+ --color-text-inverse: #0a0a0f;
35
+
36
+ --color-accent: #00d4aa;
37
+ --color-accent-dim: rgba(0, 212, 170, 0.15);
38
+ --color-accent-glow: rgba(0, 212, 170, 0.3);
39
+ --color-accent-hover: #00eabc;
40
+
41
+ --color-warm: #f5a623;
42
+ --color-warm-dim: rgba(245, 166, 35, 0.12);
43
+
44
+ --color-danger: #f04e4e;
45
+ --color-danger-dim: rgba(240, 78, 78, 0.12);
46
+ --color-success: #34c759;
47
+ --color-success-dim: rgba(52, 199, 89, 0.12);
48
+ --color-info: #5b8def;
49
+ --color-info-dim: rgba(91, 141, 239, 0.12);
50
+
51
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
52
+ --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.3);
53
+ --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.4);
54
+ --shadow-glow: 0 0 40px var(--color-accent-glow);
55
+ }
56
+
57
+ /* ── Reset & base ───────────────────────────────────────────────── */
58
+
59
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
60
+
61
+ html {
62
+ -webkit-font-smoothing: antialiased;
63
+ -moz-osx-font-smoothing: grayscale;
64
+ text-rendering: optimizeLegibility;
65
+ scroll-behavior: smooth;
66
+ }
67
+
68
+ body {
69
+ font-family: var(--font-body);
70
+ font-size: 15px;
71
+ line-height: 1.6;
72
+ color: var(--color-text);
73
+ background: var(--color-bg);
74
+ min-height: 100dvh;
75
+ }
76
+
77
+ a { color: inherit; text-decoration: none; }
78
+ button { cursor: pointer; font: inherit; border: none; background: none; }
79
+ input, textarea, select { font: inherit; }
80
+ img { display: block; max-width: 100%; }
81
+
82
+ ::selection {
83
+ background: var(--color-accent-dim);
84
+ color: var(--color-accent);
85
+ }
86
+
87
+ /* ── Scrollbar ──────────────────────────────────────────────────── */
88
+
89
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
90
+ ::-webkit-scrollbar-track { background: transparent; }
91
+ ::-webkit-scrollbar-thumb { background: var(--color-border-hover); border-radius: 3px; }
92
+ ::-webkit-scrollbar-thumb:hover { background: var(--color-border-active); }
93
+
94
+ /* ── Noise texture overlay ──────────────────────────────────────── */
95
+
96
+ body::before {
97
+ content: "";
98
+ position: fixed;
99
+ inset: 0;
100
+ z-index: 9999;
101
+ pointer-events: none;
102
+ opacity: 0.025;
103
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
104
+ background-repeat: repeat;
105
+ background-size: 256px 256px;
106
+ }
107
+
108
+ /* ── Animations ─────────────────────────────────────────────────── */
109
+
110
+ @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
111
+ @keyframes fade-up {
112
+ from { opacity: 0; transform: translateY(20px); }
113
+ to { opacity: 1; transform: translateY(0); }
114
+ }
115
+ @keyframes fade-down {
116
+ from { opacity: 0; transform: translateY(-10px); }
117
+ to { opacity: 1; transform: translateY(0); }
118
+ }
119
+ @keyframes scale-in {
120
+ from { opacity: 0; transform: scale(0.95); }
121
+ to { opacity: 1; transform: scale(1); }
122
+ }
123
+ @keyframes shimmer {
124
+ 0% { background-position: -200% 0; }
125
+ 100% { background-position: 200% 0; }
126
+ }
127
+ @keyframes pulse-glow {
128
+ 0%, 100% { box-shadow: 0 0 20px var(--color-accent-glow); }
129
+ 50% { box-shadow: 0 0 40px var(--color-accent-glow); }
130
+ }
131
+ @keyframes gradient-shift {
132
+ 0% { background-position: 0% 50%; }
133
+ 50% { background-position: 100% 50%; }
134
+ 100% { background-position: 0% 50%; }
135
+ }
136
+ @keyframes float {
137
+ 0%, 100% { transform: translateY(0); }
138
+ 50% { transform: translateY(-8px); }
139
+ }
140
+
141
+ /* ── Typography ─────────────────────────────────────────────────── */
142
+
143
+ h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; color: var(--color-text); }
144
+ h1 { font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 900; letter-spacing: -0.035em; }
145
+ h2 { font-size: clamp(1.5rem, 3vw, 2.25rem); }
146
+ h3 { font-size: clamp(1.125rem, 2vw, 1.5rem); }
147
+ h4 { font-size: 1.125rem; font-weight: 600; }
148
+
149
+ .eyebrow {
150
+ font-family: var(--font-mono);
151
+ font-size: 0.75rem;
152
+ font-weight: 500;
153
+ text-transform: uppercase;
154
+ letter-spacing: 0.15em;
155
+ color: var(--color-accent);
156
+ }
157
+
158
+ .lede {
159
+ font-size: 1.0625rem;
160
+ line-height: 1.7;
161
+ color: var(--color-text-secondary);
162
+ max-width: 540px;
163
+ }
164
+
165
+ /* ── Buttons ────────────────────────────────────────────────────── */
166
+
167
+ .btn-primary {
168
+ display: inline-flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ gap: 8px;
172
+ padding: 12px 28px;
173
+ font-family: var(--font-display);
174
+ font-weight: 600;
175
+ font-size: 0.9375rem;
176
+ color: var(--color-text-inverse);
177
+ background: var(--color-accent);
178
+ border-radius: var(--radius-full);
179
+ transition: all 0.2s var(--ease-out-expo);
180
+ position: relative;
181
+ overflow: hidden;
182
+ }
183
+ .btn-primary::before {
184
+ content: "";
185
+ position: absolute;
186
+ inset: 0;
187
+ background: linear-gradient(135deg, transparent 40%, rgba(255, 255, 255, 0.2) 50%, transparent 60%);
188
+ background-size: 200% 200%;
189
+ animation: shimmer 3s ease-in-out infinite;
190
+ }
191
+ .btn-primary:hover {
192
+ background: var(--color-accent-hover);
193
+ transform: translateY(-1px);
194
+ box-shadow: var(--shadow-glow);
195
+ }
196
+ .btn-primary:active { transform: translateY(0); }
197
+ .btn-primary:disabled { opacity: 0.5; pointer-events: none; }
198
+
199
+ .btn-secondary {
200
+ display: inline-flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ gap: 8px;
204
+ padding: 12px 28px;
205
+ font-family: var(--font-display);
206
+ font-weight: 600;
207
+ font-size: 0.9375rem;
208
+ color: var(--color-text);
209
+ background: var(--color-bg-raised);
210
+ border: 1px solid var(--color-border);
211
+ border-radius: var(--radius-full);
212
+ transition: all 0.2s var(--ease-out-expo);
213
+ }
214
+ .btn-secondary:hover {
215
+ border-color: var(--color-border-hover);
216
+ background: var(--color-bg-overlay);
217
+ transform: translateY(-1px);
218
+ }
219
+
220
+ .btn-ghost {
221
+ display: inline-flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ gap: 6px;
225
+ padding: 8px 16px;
226
+ font-weight: 500;
227
+ font-size: 0.875rem;
228
+ color: var(--color-text-secondary);
229
+ border-radius: var(--radius-sm);
230
+ transition: all 0.15s ease;
231
+ }
232
+ .btn-ghost:hover { color: var(--color-text); background: var(--color-bg-subtle); }
233
+
234
+ .ghost-button { composes: btn-ghost; }
235
+
236
+ /* ── Cards ──────────────────────────────────────────────────────── */
237
+
238
+ .card {
239
+ background: var(--color-bg-raised);
240
+ border: 1px solid var(--color-border);
241
+ border-radius: var(--radius-lg);
242
+ padding: 24px;
243
+ transition: all 0.25s var(--ease-out-expo);
244
+ }
245
+ .card:hover {
246
+ border-color: var(--color-border-hover);
247
+ box-shadow: var(--shadow-md);
248
+ }
249
+ .card-glass {
250
+ background: rgba(17, 17, 24, 0.7);
251
+ backdrop-filter: blur(16px) saturate(180%);
252
+ -webkit-backdrop-filter: blur(16px) saturate(180%);
253
+ border: 1px solid var(--color-border);
254
+ border-radius: var(--radius-lg);
255
+ padding: 24px;
256
+ }
257
+
258
+ /* ── Form fields ────────────────────────────────────────────────── */
259
+
260
+ .field {
261
+ display: flex;
262
+ flex-direction: column;
263
+ gap: 6px;
264
+ }
265
+ .field span {
266
+ font-size: 0.8125rem;
267
+ font-weight: 500;
268
+ color: var(--color-text-secondary);
269
+ }
270
+ .field input, .field textarea, .field select {
271
+ padding: 11px 16px;
272
+ background: var(--color-bg);
273
+ border: 1px solid var(--color-border);
274
+ border-radius: var(--radius-md);
275
+ color: var(--color-text);
276
+ font-size: 0.9375rem;
277
+ outline: none;
278
+ transition: all 0.2s ease;
279
+ }
280
+ .field input::placeholder { color: var(--color-text-muted); }
281
+ .field input:focus, .field textarea:focus {
282
+ border-color: var(--color-accent);
283
+ box-shadow: 0 0 0 3px var(--color-accent-dim);
284
+ }
285
+
286
+ /* ── Feedback messages ──────────────────────────────────────────── */
287
+
288
+ .form-error {
289
+ padding: 12px 16px;
290
+ background: var(--color-danger-dim);
291
+ border: 1px solid rgba(240, 78, 78, 0.2);
292
+ border-radius: var(--radius-md);
293
+ color: var(--color-danger);
294
+ font-size: 0.875rem;
295
+ font-weight: 500;
296
+ }
297
+ .form-success {
298
+ padding: 12px 16px;
299
+ background: var(--color-success-dim);
300
+ border: 1px solid rgba(52, 199, 89, 0.2);
301
+ border-radius: var(--radius-md);
302
+ color: var(--color-success);
303
+ font-size: 0.875rem;
304
+ font-weight: 500;
305
+ }
306
+
307
+ /* ═══════════════════════════════════════════════════════════════════
308
+ LANDING PAGE
309
+ ═══════════════════════════════════════════════════════════════════ */
310
+
311
+ .landing {
312
+ min-height: 100dvh;
313
+ position: relative;
314
+ overflow: hidden;
315
+ }
316
+
317
+ /* Gradient orbs */
318
+ .landing::before, .landing::after {
319
+ content: "";
320
+ position: absolute;
321
+ border-radius: 50%;
322
+ filter: blur(120px);
323
+ opacity: 0.4;
324
+ pointer-events: none;
325
+ }
326
+ .landing::before {
327
+ width: 600px;
328
+ height: 600px;
329
+ background: radial-gradient(circle, var(--color-accent-glow), transparent 70%);
330
+ top: -200px;
331
+ right: -100px;
332
+ }
333
+ .landing::after {
334
+ width: 500px;
335
+ height: 500px;
336
+ background: radial-gradient(circle, rgba(91, 141, 239, 0.2), transparent 70%);
337
+ bottom: -100px;
338
+ left: -150px;
339
+ }
340
+
341
+ /* Nav */
342
+ .landing-nav {
343
+ position: fixed;
344
+ top: 0;
345
+ left: 0;
346
+ right: 0;
347
+ z-index: 100;
348
+ padding: 16px 32px;
349
+ display: flex;
350
+ align-items: center;
351
+ justify-content: space-between;
352
+ background: rgba(10, 10, 15, 0.6);
353
+ backdrop-filter: blur(20px) saturate(180%);
354
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
355
+ border-bottom: 1px solid var(--color-border);
356
+ animation: fade-down 0.6s var(--ease-out-expo);
357
+ }
358
+ .landing-nav .logo {
359
+ font-family: var(--font-display);
360
+ font-weight: 900;
361
+ font-size: 1.125rem;
362
+ letter-spacing: -0.03em;
363
+ }
364
+ .landing-nav .logo span { color: var(--color-accent); }
365
+ .landing-nav-links {
366
+ display: flex;
367
+ align-items: center;
368
+ gap: 8px;
369
+ }
370
+ .landing-nav-links a {
371
+ padding: 8px 18px;
372
+ font-size: 0.875rem;
373
+ font-weight: 500;
374
+ color: var(--color-text-secondary);
375
+ border-radius: var(--radius-full);
376
+ transition: all 0.2s ease;
377
+ }
378
+ .landing-nav-links a:hover { color: var(--color-text); }
379
+ .landing-nav-links a.nav-cta {
380
+ background: var(--color-accent);
381
+ color: var(--color-text-inverse);
382
+ font-weight: 600;
383
+ }
384
+ .landing-nav-links a.nav-cta:hover { background: var(--color-accent-hover); }
385
+
386
+ /* Hero */
387
+ .landing-hero {
388
+ max-width: 900px;
389
+ margin: 0 auto;
390
+ padding: 160px 32px 80px;
391
+ text-align: center;
392
+ position: relative;
393
+ z-index: 1;
394
+ }
395
+ .landing-hero .eyebrow {
396
+ animation: fade-up 0.6s var(--ease-out-expo) 0.1s both;
397
+ display: inline-flex;
398
+ align-items: center;
399
+ gap: 8px;
400
+ padding: 6px 16px;
401
+ background: var(--color-accent-dim);
402
+ border: 1px solid rgba(0, 212, 170, 0.15);
403
+ border-radius: var(--radius-full);
404
+ margin-bottom: 24px;
405
+ }
406
+ .landing-hero h1 {
407
+ animation: fade-up 0.6s var(--ease-out-expo) 0.2s both;
408
+ margin-bottom: 20px;
409
+ }
410
+ .landing-hero h1 em {
411
+ font-style: normal;
412
+ background: linear-gradient(135deg, var(--color-accent), #5b8def);
413
+ background-clip: text;
414
+ -webkit-background-clip: text;
415
+ -webkit-text-fill-color: transparent;
416
+ }
417
+ .landing-hero .lede {
418
+ animation: fade-up 0.6s var(--ease-out-expo) 0.3s both;
419
+ margin: 0 auto 40px;
420
+ max-width: 560px;
421
+ }
422
+ .hero-actions {
423
+ display: flex;
424
+ align-items: center;
425
+ justify-content: center;
426
+ gap: 12px;
427
+ flex-wrap: wrap;
428
+ animation: fade-up 0.6s var(--ease-out-expo) 0.4s both;
429
+ }
430
+
431
+ /* Social proof */
432
+ .social-proof {
433
+ display: flex;
434
+ align-items: center;
435
+ justify-content: center;
436
+ gap: 32px;
437
+ padding: 60px 32px 20px;
438
+ position: relative;
439
+ z-index: 1;
440
+ animation: fade-up 0.6s var(--ease-out-expo) 0.5s both;
441
+ }
442
+ .social-proof p {
443
+ font-size: 0.8125rem;
444
+ color: var(--color-text-muted);
445
+ text-transform: uppercase;
446
+ letter-spacing: 0.1em;
447
+ font-weight: 500;
448
+ }
449
+ .social-proof-logos {
450
+ display: flex;
451
+ align-items: center;
452
+ gap: 28px;
453
+ opacity: 0.35;
454
+ }
455
+ .social-proof-logos span {
456
+ font-family: var(--font-display);
457
+ font-weight: 700;
458
+ font-size: 1rem;
459
+ letter-spacing: -0.01em;
460
+ }
461
+
462
+ /* Bento grid */
463
+ .bento-section {
464
+ max-width: 1100px;
465
+ margin: 0 auto;
466
+ padding: 60px 32px 100px;
467
+ position: relative;
468
+ z-index: 1;
469
+ }
470
+ .bento-section > .eyebrow { text-align: center; margin-bottom: 12px; }
471
+ .bento-section > h2 { text-align: center; margin-bottom: 48px; }
472
+ .bento-grid {
473
+ display: grid;
474
+ grid-template-columns: repeat(3, 1fr);
475
+ gap: 16px;
476
+ }
477
+ .bento-card {
478
+ background: var(--color-bg-raised);
479
+ border: 1px solid var(--color-border);
480
+ border-radius: var(--radius-lg);
481
+ padding: 28px;
482
+ display: flex;
483
+ flex-direction: column;
484
+ gap: 12px;
485
+ transition: all 0.3s var(--ease-out-expo);
486
+ position: relative;
487
+ overflow: hidden;
488
+ }
489
+ .bento-card::before {
490
+ content: "";
491
+ position: absolute;
492
+ top: 0;
493
+ left: 0;
494
+ right: 0;
495
+ height: 1px;
496
+ background: linear-gradient(90deg, transparent, var(--color-accent-dim), transparent);
497
+ opacity: 0;
498
+ transition: opacity 0.3s ease;
499
+ }
500
+ .bento-card:hover {
501
+ border-color: var(--color-border-hover);
502
+ transform: translateY(-2px);
503
+ box-shadow: var(--shadow-md);
504
+ }
505
+ .bento-card:hover::before { opacity: 1; }
506
+ .bento-card.span-2 { grid-column: span 2; }
507
+ .bento-card-icon {
508
+ width: 40px;
509
+ height: 40px;
510
+ border-radius: var(--radius-md);
511
+ display: flex;
512
+ align-items: center;
513
+ justify-content: center;
514
+ font-size: 1.25rem;
515
+ background: var(--color-accent-dim);
516
+ color: var(--color-accent);
517
+ }
518
+ .bento-card h3 { font-size: 1.125rem; }
519
+ .bento-card p { font-size: 0.875rem; color: var(--color-text-secondary); line-height: 1.65; }
520
+ .bento-card .tag-row {
521
+ display: flex;
522
+ flex-wrap: wrap;
523
+ gap: 6px;
524
+ margin-top: auto;
525
+ }
526
+ .bento-tag {
527
+ font-family: var(--font-mono);
528
+ font-size: 0.6875rem;
529
+ padding: 3px 10px;
530
+ background: var(--color-bg-subtle);
531
+ border: 1px solid var(--color-border);
532
+ border-radius: var(--radius-full);
533
+ color: var(--color-text-secondary);
534
+ }
535
+
536
+ /* CTA footer */
537
+ .cta-section {
538
+ max-width: 700px;
539
+ margin: 0 auto;
540
+ padding: 40px 32px 120px;
541
+ text-align: center;
542
+ position: relative;
543
+ z-index: 1;
544
+ }
545
+ .cta-section h2 { margin-bottom: 16px; }
546
+ .cta-section p { color: var(--color-text-secondary); margin-bottom: 32px; }
547
+ .cta-section .hero-actions { justify-content: center; }
548
+
549
+ /* Landing footer */
550
+ .landing-footer {
551
+ padding: 32px;
552
+ text-align: center;
553
+ border-top: 1px solid var(--color-border);
554
+ position: relative;
555
+ z-index: 1;
556
+ }
557
+ .landing-footer p {
558
+ font-size: 0.8125rem;
559
+ color: var(--color-text-muted);
560
+ }
561
+
562
+ @media (max-width: 768px) {
563
+ .bento-grid { grid-template-columns: 1fr; }
564
+ .bento-card.span-2 { grid-column: span 1; }
565
+ .landing-hero { padding: 120px 20px 60px; }
566
+ .landing-nav { padding: 12px 20px; }
567
+ .social-proof { flex-direction: column; gap: 16px; }
568
+ }
569
+
570
+ /* ═══════════════════════════════════════════════════════════════════
571
+ AUTH SCREENS
572
+ ═══════════════════════════════════════════════════════════════════ */
573
+
574
+ .auth-screen {
575
+ min-height: 100dvh;
576
+ display: grid;
577
+ grid-template-columns: 1fr 1fr;
578
+ position: relative;
579
+ }
580
+
581
+ .auth-brand {
582
+ display: flex;
583
+ flex-direction: column;
584
+ justify-content: center;
585
+ padding: 60px;
586
+ background: var(--color-bg-raised);
587
+ position: relative;
588
+ overflow: hidden;
589
+ }
590
+ .auth-brand::before {
591
+ content: "";
592
+ position: absolute;
593
+ width: 400px;
594
+ height: 400px;
595
+ background: radial-gradient(circle, var(--color-accent-glow), transparent 70%);
596
+ top: 50%;
597
+ left: 50%;
598
+ transform: translate(-50%, -50%);
599
+ filter: blur(100px);
600
+ opacity: 0.3;
601
+ }
602
+ .auth-brand .logo {
603
+ font-family: var(--font-display);
604
+ font-weight: 900;
605
+ font-size: 1.25rem;
606
+ margin-bottom: 40px;
607
+ position: relative;
608
+ }
609
+ .auth-brand .logo span { color: var(--color-accent); }
610
+ .auth-brand blockquote {
611
+ font-family: var(--font-display);
612
+ font-size: 1.75rem;
613
+ font-weight: 700;
614
+ line-height: 1.3;
615
+ letter-spacing: -0.02em;
616
+ position: relative;
617
+ max-width: 380px;
618
+ }
619
+ .auth-brand blockquote::before {
620
+ content: "\201C";
621
+ font-size: 4rem;
622
+ color: var(--color-accent);
623
+ line-height: 1;
624
+ position: absolute;
625
+ top: -20px;
626
+ left: -8px;
627
+ opacity: 0.3;
628
+ }
629
+ .auth-brand cite {
630
+ display: block;
631
+ font-style: normal;
632
+ font-size: 0.875rem;
633
+ color: var(--color-text-secondary);
634
+ margin-top: 20px;
635
+ }
636
+ .auth-features {
637
+ display: flex;
638
+ flex-direction: column;
639
+ gap: 12px;
640
+ margin-top: 40px;
641
+ position: relative;
642
+ }
643
+ .auth-feature-item {
644
+ display: flex;
645
+ align-items: center;
646
+ gap: 12px;
647
+ font-size: 0.875rem;
648
+ color: var(--color-text-secondary);
649
+ }
650
+ .auth-feature-check {
651
+ width: 20px;
652
+ height: 20px;
653
+ border-radius: 50%;
654
+ background: var(--color-accent-dim);
655
+ color: var(--color-accent);
656
+ display: flex;
657
+ align-items: center;
658
+ justify-content: center;
659
+ font-size: 0.6875rem;
660
+ flex-shrink: 0;
661
+ }
662
+
663
+ .auth-form-side {
664
+ display: flex;
665
+ align-items: center;
666
+ justify-content: center;
667
+ padding: 40px;
668
+ position: relative;
669
+ }
670
+
671
+ .auth-panel {
672
+ width: 100%;
673
+ max-width: 400px;
674
+ display: flex;
675
+ flex-direction: column;
676
+ gap: 24px;
677
+ animation: fade-up 0.5s var(--ease-out-expo);
678
+ }
679
+ .auth-panel h1 { font-size: 1.75rem; }
680
+ .auth-panel .lede { font-size: 0.9375rem; margin-top: 4px; }
681
+ .auth-grid { display: flex; flex-direction: column; gap: 16px; }
682
+
683
+ .auth-button {
684
+ display: flex;
685
+ align-items: center;
686
+ justify-content: center;
687
+ width: 100%;
688
+ padding: 13px 24px;
689
+ font-family: var(--font-display);
690
+ font-weight: 600;
691
+ font-size: 0.9375rem;
692
+ color: var(--color-text-inverse);
693
+ background: var(--color-accent);
694
+ border-radius: var(--radius-md);
695
+ transition: all 0.2s var(--ease-out-expo);
696
+ position: relative;
697
+ overflow: hidden;
698
+ }
699
+ .auth-button::before {
700
+ content: "";
701
+ position: absolute;
702
+ inset: 0;
703
+ background: linear-gradient(135deg, transparent 40%, rgba(255, 255, 255, 0.15) 50%, transparent 60%);
704
+ background-size: 200% 200%;
705
+ animation: shimmer 3s ease-in-out infinite;
706
+ }
707
+ .auth-button:hover {
708
+ background: var(--color-accent-hover);
709
+ box-shadow: var(--shadow-glow);
710
+ }
711
+ .auth-button:disabled { opacity: 0.5; pointer-events: none; }
712
+
713
+ .auth-switch {
714
+ font-size: 0.875rem;
715
+ color: var(--color-text-secondary);
716
+ text-align: center;
717
+ }
718
+ .auth-switch a {
719
+ color: var(--color-accent);
720
+ font-weight: 500;
721
+ transition: color 0.15s ease;
722
+ }
723
+ .auth-switch a:hover { color: var(--color-accent-hover); }
724
+
725
+ /* Social auth buttons */
726
+ .auth-social-buttons {
727
+ display: flex;
728
+ flex-direction: column;
729
+ gap: 10px;
730
+ }
731
+
732
+ .auth-social-btn {
733
+ display: flex;
734
+ align-items: center;
735
+ justify-content: center;
736
+ gap: 10px;
737
+ width: 100%;
738
+ padding: 11px 20px;
739
+ font-size: 0.9375rem;
740
+ font-weight: 500;
741
+ color: var(--color-text);
742
+ background: var(--color-bg);
743
+ border: 1px solid var(--color-border);
744
+ border-radius: var(--radius-md);
745
+ transition: all 0.2s ease;
746
+ cursor: pointer;
747
+ }
748
+ .auth-social-btn:hover {
749
+ border-color: var(--color-border-hover);
750
+ background: var(--color-bg-overlay);
751
+ }
752
+ .auth-social-btn:disabled { opacity: 0.5; pointer-events: none; }
753
+
754
+ /* Divider */
755
+ .auth-divider {
756
+ display: flex;
757
+ align-items: center;
758
+ gap: 12px;
759
+ color: var(--color-text-muted);
760
+ font-size: 0.8125rem;
761
+ }
762
+ .auth-divider::before,
763
+ .auth-divider::after {
764
+ content: "";
765
+ flex: 1;
766
+ height: 1px;
767
+ background: var(--color-border);
768
+ }
769
+
770
+ @media (max-width: 768px) {
771
+ .auth-screen { grid-template-columns: 1fr; }
772
+ .auth-brand { display: none; }
773
+ .auth-form-side { padding: 32px 20px; }
774
+ }
775
+
776
+ /* ═══════════════════════════════════════════════════════════════════
777
+ DASHBOARD SHELL
778
+ ═══════════════════════════════════════════════════════════════════ */
779
+
780
+ .dashboard-layout {
781
+ display: flex;
782
+ min-height: 100dvh;
783
+ }
784
+
785
+ /* ── Sidebar ────────────────────────────────────────────────────── */
786
+
787
+ .sidebar {
788
+ width: 260px;
789
+ flex-shrink: 0;
790
+ background: var(--color-bg-raised);
791
+ border-right: 1px solid var(--color-border);
792
+ display: flex;
793
+ flex-direction: column;
794
+ position: sticky;
795
+ top: 0;
796
+ height: 100dvh;
797
+ overflow: hidden;
798
+ overflow-y: auto;
799
+ transition: width 0.25s var(--ease-out-expo);
800
+ z-index: 10;
801
+ }
802
+
803
+ /* Collapsed state */
804
+ .sidebar.collapsed {
805
+ width: 64px;
806
+ }
807
+
808
+ /* Header: logo + toggle */
809
+ .sidebar-header {
810
+ display: flex;
811
+ align-items: center;
812
+ justify-content: space-between;
813
+ padding: 20px 14px 12px;
814
+ gap: 8px;
815
+ flex-shrink: 0;
816
+ }
817
+
818
+ .sidebar-logo {
819
+ display: flex;
820
+ align-items: center;
821
+ gap: 8px;
822
+ font-family: var(--font-display);
823
+ font-weight: 900;
824
+ font-size: 1.0625rem;
825
+ letter-spacing: -0.03em;
826
+ white-space: nowrap;
827
+ overflow: hidden;
828
+ min-width: 0;
829
+ }
830
+ .sidebar-logo-icon {
831
+ font-size: 1.25rem;
832
+ flex-shrink: 0;
833
+ color: var(--color-accent);
834
+ }
835
+ .sidebar-logo-text {
836
+ overflow: hidden;
837
+ white-space: nowrap;
838
+ transition: opacity 0.2s ease, max-width 0.25s var(--ease-out-expo);
839
+ max-width: 160px;
840
+ }
841
+ .sidebar-logo-text span { color: var(--color-accent); }
842
+
843
+ .sidebar.collapsed .sidebar-logo-text {
844
+ opacity: 0;
845
+ max-width: 0;
846
+ }
847
+
848
+ .sidebar-toggle {
849
+ width: 28px;
850
+ height: 28px;
851
+ display: flex;
852
+ align-items: center;
853
+ justify-content: center;
854
+ border-radius: var(--radius-sm);
855
+ color: var(--color-text-muted);
856
+ transition: all 0.15s ease;
857
+ flex-shrink: 0;
858
+ }
859
+ .sidebar-toggle:hover {
860
+ color: var(--color-text);
861
+ background: var(--color-bg-subtle);
862
+ }
863
+
864
+ /* Nav section */
865
+ .sidebar-nav {
866
+ display: flex;
867
+ flex-direction: column;
868
+ gap: 2px;
869
+ padding: 8px 10px;
870
+ flex: 1;
871
+ }
872
+
873
+ .sidebar-section {
874
+ padding: 16px 4px 6px;
875
+ }
876
+ .sidebar-section-label {
877
+ font-family: var(--font-mono);
878
+ font-size: 0.6875rem;
879
+ text-transform: uppercase;
880
+ letter-spacing: 0.12em;
881
+ color: var(--color-text-muted);
882
+ white-space: nowrap;
883
+ overflow: hidden;
884
+ transition: opacity 0.15s ease;
885
+ }
886
+ .sidebar.collapsed .sidebar-section-label {
887
+ opacity: 0;
888
+ }
889
+
890
+ .sidebar-link {
891
+ display: flex;
892
+ align-items: center;
893
+ gap: 10px;
894
+ padding: 9px 10px;
895
+ font-size: 0.875rem;
896
+ font-weight: 500;
897
+ color: var(--color-text-secondary);
898
+ border-radius: var(--radius-sm);
899
+ transition: all 0.15s ease;
900
+ white-space: nowrap;
901
+ overflow: hidden;
902
+ position: relative;
903
+ }
904
+ .sidebar-link:hover { color: var(--color-text); background: var(--color-bg-subtle); }
905
+ .sidebar-link.active {
906
+ color: var(--color-text);
907
+ background: var(--color-bg-subtle);
908
+ }
909
+ .sidebar-link.active::before {
910
+ content: "";
911
+ position: absolute;
912
+ left: 0;
913
+ top: 50%;
914
+ transform: translateY(-50%);
915
+ width: 3px;
916
+ height: 18px;
917
+ background: var(--color-accent);
918
+ border-radius: 0 2px 2px 0;
919
+ }
920
+ .sidebar-link-icon {
921
+ display: flex;
922
+ align-items: center;
923
+ justify-content: center;
924
+ width: 18px;
925
+ height: 18px;
926
+ opacity: 0.65;
927
+ flex-shrink: 0;
928
+ transition: opacity 0.15s ease;
929
+ }
930
+ .sidebar-link:hover .sidebar-link-icon,
931
+ .sidebar-link.active .sidebar-link-icon { opacity: 1; }
932
+
933
+ .sidebar-link-label {
934
+ overflow: hidden;
935
+ white-space: nowrap;
936
+ transition: opacity 0.15s ease, max-width 0.25s var(--ease-out-expo);
937
+ max-width: 160px;
938
+ }
939
+ .sidebar.collapsed .sidebar-link-label {
940
+ opacity: 0;
941
+ max-width: 0;
942
+ }
943
+
944
+ .sidebar-spacer { flex: 1; }
945
+
946
+ /* Footer: user info + sign out */
947
+ .sidebar-footer {
948
+ padding: 12px 10px 16px;
949
+ border-top: 1px solid var(--color-border);
950
+ display: flex;
951
+ flex-direction: column;
952
+ gap: 8px;
953
+ flex-shrink: 0;
954
+ }
955
+
956
+ .sidebar-user {
957
+ display: flex;
958
+ align-items: center;
959
+ gap: 10px;
960
+ padding: 4px 2px;
961
+ overflow: hidden;
962
+ }
963
+ .sidebar-avatar {
964
+ width: 32px;
965
+ height: 32px;
966
+ border-radius: 50%;
967
+ background: linear-gradient(135deg, var(--color-accent), var(--color-info));
968
+ display: flex;
969
+ align-items: center;
970
+ justify-content: center;
971
+ font-family: var(--font-display);
972
+ font-weight: 700;
973
+ font-size: 0.8125rem;
974
+ color: var(--color-text-inverse);
975
+ flex-shrink: 0;
976
+ }
977
+ .sidebar-user-info {
978
+ overflow: hidden;
979
+ flex: 1;
980
+ min-width: 0;
981
+ transition: opacity 0.15s ease, max-width 0.25s var(--ease-out-expo);
982
+ max-width: 160px;
983
+ }
984
+ .sidebar.collapsed .sidebar-user-info {
985
+ opacity: 0;
986
+ max-width: 0;
987
+ }
988
+ .sidebar-user-name {
989
+ font-size: 0.8125rem;
990
+ font-weight: 600;
991
+ white-space: nowrap;
992
+ overflow: hidden;
993
+ text-overflow: ellipsis;
994
+ }
995
+ .sidebar-user-email {
996
+ font-size: 0.6875rem;
997
+ color: var(--color-text-muted);
998
+ white-space: nowrap;
999
+ overflow: hidden;
1000
+ text-overflow: ellipsis;
1001
+ }
1002
+
1003
+ .sidebar-signout {
1004
+ overflow: hidden;
1005
+ transition: opacity 0.15s ease, max-height 0.25s var(--ease-out-expo);
1006
+ max-height: 60px;
1007
+ }
1008
+ .sidebar.collapsed .sidebar-signout {
1009
+ opacity: 0;
1010
+ max-height: 0;
1011
+ pointer-events: none;
1012
+ }
1013
+
1014
+ /* ── Mobile sidebar ─────────────────────────────────────────────── */
1015
+
1016
+ @media (max-width: 768px) {
1017
+ .dashboard-layout { flex-direction: column; }
1018
+ .sidebar {
1019
+ width: 100% !important;
1020
+ height: auto;
1021
+ position: static;
1022
+ flex-direction: row;
1023
+ align-items: center;
1024
+ flex-wrap: nowrap;
1025
+ padding: 0;
1026
+ overflow-x: auto;
1027
+ overflow-y: hidden;
1028
+ }
1029
+ .sidebar-header { padding: 12px 16px; flex-shrink: 0; }
1030
+ .sidebar-nav { flex-direction: row; padding: 8px; gap: 2px; flex: 1; overflow-x: auto; }
1031
+ .sidebar-section, .sidebar-spacer { display: none; }
1032
+ .sidebar-link { flex-direction: column; gap: 4px; padding: 8px 12px; font-size: 0.75rem; }
1033
+ .sidebar-link-icon { width: 20px; height: 20px; }
1034
+ .sidebar-link-label { max-width: unset !important; opacity: 1 !important; font-size: 0.6875rem; }
1035
+ .sidebar-link.active::before { width: 100%; height: 2px; top: 0; left: 0; transform: none; border-radius: 0 0 2px 2px; }
1036
+ .sidebar-footer { display: none; }
1037
+ .sidebar-toggle { display: none; }
1038
+ .sidebar.collapsed .sidebar-logo-text { opacity: 1; max-width: 160px; }
1039
+ }
1040
+
1041
+ /* ── Main content area ──────────────────────────────────────────── */
1042
+
1043
+ .dashboard-main {
1044
+ flex: 1;
1045
+ min-width: 0;
1046
+ padding: 32px 40px;
1047
+ overflow-y: auto;
1048
+ position: relative;
1049
+ }
1050
+ .dashboard-header {
1051
+ display: flex;
1052
+ align-items: center;
1053
+ justify-content: space-between;
1054
+ margin-bottom: 32px;
1055
+ animation: fade-down 0.4s var(--ease-out-expo);
1056
+ }
1057
+ .dashboard-header h1 { font-size: 1.75rem; }
1058
+ .dashboard-header-actions { display: flex; align-items: center; gap: 8px; }
1059
+
1060
+ /* Stat cards */
1061
+ .stat-grid {
1062
+ display: grid;
1063
+ grid-template-columns: repeat(4, 1fr);
1064
+ gap: 16px;
1065
+ margin-bottom: 32px;
1066
+ }
1067
+ .stat-card {
1068
+ background: var(--color-bg-raised);
1069
+ border: 1px solid var(--color-border);
1070
+ border-radius: var(--radius-lg);
1071
+ padding: 24px;
1072
+ display: flex;
1073
+ flex-direction: column;
1074
+ gap: 8px;
1075
+ transition: all 0.25s var(--ease-out-expo);
1076
+ animation: fade-up 0.5s var(--ease-out-expo) both;
1077
+ }
1078
+ .stat-card:nth-child(1) { animation-delay: 0.05s; }
1079
+ .stat-card:nth-child(2) { animation-delay: 0.1s; }
1080
+ .stat-card:nth-child(3) { animation-delay: 0.15s; }
1081
+ .stat-card:nth-child(4) { animation-delay: 0.2s; }
1082
+ .stat-card:hover { border-color: var(--color-border-hover); }
1083
+ .stat-label {
1084
+ font-size: 0.8125rem;
1085
+ font-weight: 500;
1086
+ color: var(--color-text-secondary);
1087
+ }
1088
+ .stat-value {
1089
+ font-family: var(--font-display);
1090
+ font-size: 2rem;
1091
+ font-weight: 900;
1092
+ letter-spacing: -0.03em;
1093
+ line-height: 1;
1094
+ }
1095
+ .stat-change {
1096
+ font-family: var(--font-mono);
1097
+ font-size: 0.75rem;
1098
+ font-weight: 500;
1099
+ }
1100
+ .stat-change.up { color: var(--color-success); }
1101
+ .stat-change.down { color: var(--color-danger); }
1102
+
1103
+ /* Dashboard content grid */
1104
+ .dashboard-grid {
1105
+ display: grid;
1106
+ grid-template-columns: 2fr 1fr;
1107
+ gap: 16px;
1108
+ }
1109
+ .dashboard-panel {
1110
+ background: var(--color-bg-raised);
1111
+ border: 1px solid var(--color-border);
1112
+ border-radius: var(--radius-lg);
1113
+ padding: 24px;
1114
+ animation: fade-up 0.5s var(--ease-out-expo) 0.25s both;
1115
+ }
1116
+ .dashboard-panel h3 {
1117
+ font-size: 1rem;
1118
+ margin-bottom: 20px;
1119
+ display: flex;
1120
+ align-items: center;
1121
+ justify-content: space-between;
1122
+ }
1123
+ .dashboard-panel h3 .badge {
1124
+ font-family: var(--font-mono);
1125
+ font-size: 0.6875rem;
1126
+ font-weight: 500;
1127
+ padding: 2px 10px;
1128
+ background: var(--color-accent-dim);
1129
+ color: var(--color-accent);
1130
+ border-radius: var(--radius-full);
1131
+ }
1132
+
1133
+ /* Chart placeholder */
1134
+ .chart-placeholder {
1135
+ height: 200px;
1136
+ border-radius: var(--radius-md);
1137
+ background: linear-gradient(180deg, var(--color-accent-dim) 0%, transparent 100%);
1138
+ position: relative;
1139
+ overflow: hidden;
1140
+ display: flex;
1141
+ align-items: flex-end;
1142
+ padding: 0 8px;
1143
+ gap: 4px;
1144
+ }
1145
+ .chart-bar {
1146
+ flex: 1;
1147
+ background: var(--color-accent);
1148
+ border-radius: 4px 4px 0 0;
1149
+ opacity: 0.6;
1150
+ transition: opacity 0.2s ease;
1151
+ }
1152
+ .chart-bar:hover { opacity: 1; }
1153
+
1154
+ /* Activity feed */
1155
+ .activity-feed { display: flex; flex-direction: column; gap: 0; }
1156
+ .activity-item {
1157
+ display: flex;
1158
+ align-items: flex-start;
1159
+ gap: 12px;
1160
+ padding: 14px 0;
1161
+ border-bottom: 1px solid var(--color-border);
1162
+ }
1163
+ .activity-item:last-child { border-bottom: none; }
1164
+ .activity-dot {
1165
+ width: 8px;
1166
+ height: 8px;
1167
+ border-radius: 50%;
1168
+ margin-top: 6px;
1169
+ flex-shrink: 0;
1170
+ }
1171
+ .activity-dot.green { background: var(--color-success); }
1172
+ .activity-dot.blue { background: var(--color-info); }
1173
+ .activity-dot.amber { background: var(--color-warm); }
1174
+ .activity-text { font-size: 0.8125rem; color: var(--color-text-secondary); line-height: 1.5; }
1175
+ .activity-text strong { color: var(--color-text); font-weight: 600; }
1176
+ .activity-time {
1177
+ font-family: var(--font-mono);
1178
+ font-size: 0.6875rem;
1179
+ color: var(--color-text-muted);
1180
+ margin-top: 2px;
1181
+ }
1182
+
1183
+ @media (max-width: 1024px) {
1184
+ .dashboard-layout { grid-template-columns: 1fr; }
1185
+ .sidebar {
1186
+ position: fixed;
1187
+ left: -280px;
1188
+ z-index: 200;
1189
+ width: 260px;
1190
+ transition: left 0.3s var(--ease-out-expo);
1191
+ }
1192
+ .sidebar.open { left: 0; }
1193
+ .stat-grid { grid-template-columns: repeat(2, 1fr); }
1194
+ .dashboard-grid { grid-template-columns: 1fr; }
1195
+ .dashboard-main { padding: 24px 20px; }
1196
+ }
1197
+
1198
+ /* ═══════════════════════════════════════════════════════════════════
1199
+ SETTINGS PAGE
1200
+ ═══════════════════════════════════════════════════════════════════ */
1201
+
1202
+ .settings-grid {
1203
+ display: flex;
1204
+ flex-direction: column;
1205
+ gap: 24px;
1206
+ max-width: 680px;
1207
+ }
1208
+ .settings-section {
1209
+ background: var(--color-bg-raised);
1210
+ border: 1px solid var(--color-border);
1211
+ border-radius: var(--radius-lg);
1212
+ padding: 28px;
1213
+ animation: fade-up 0.5s var(--ease-out-expo) both;
1214
+ }
1215
+ .settings-section:nth-child(2) { animation-delay: 0.1s; }
1216
+ .settings-section:nth-child(3) { animation-delay: 0.15s; }
1217
+ .settings-section h3 { margin-bottom: 4px; }
1218
+ .settings-section > p { font-size: 0.875rem; color: var(--color-text-secondary); margin-bottom: 20px; }
1219
+ .settings-fields { display: flex; flex-direction: column; gap: 16px; }
1220
+ .settings-row {
1221
+ display: flex;
1222
+ align-items: center;
1223
+ justify-content: space-between;
1224
+ gap: 16px;
1225
+ }
1226
+ .settings-row .field { flex: 1; }
1227
+ .settings-actions {
1228
+ display: flex;
1229
+ justify-content: flex-end;
1230
+ gap: 8px;
1231
+ margin-top: 8px;
1232
+ }
1233
+
1234
+ /* Toggle switch */
1235
+ .toggle-row {
1236
+ display: flex;
1237
+ align-items: center;
1238
+ justify-content: space-between;
1239
+ padding: 12px 0;
1240
+ border-bottom: 1px solid var(--color-border);
1241
+ }
1242
+ .toggle-row:last-child { border-bottom: none; }
1243
+ .toggle-label { font-size: 0.875rem; }
1244
+ .toggle-label p { font-size: 0.75rem; color: var(--color-text-muted); margin-top: 2px; }
1245
+ .toggle-switch {
1246
+ width: 44px;
1247
+ height: 24px;
1248
+ background: var(--color-bg-muted);
1249
+ border-radius: var(--radius-full);
1250
+ position: relative;
1251
+ cursor: pointer;
1252
+ transition: background 0.2s ease;
1253
+ flex-shrink: 0;
1254
+ }
1255
+ .toggle-switch.on { background: var(--color-accent); }
1256
+ .toggle-switch::after {
1257
+ content: "";
1258
+ position: absolute;
1259
+ width: 18px;
1260
+ height: 18px;
1261
+ background: white;
1262
+ border-radius: 50%;
1263
+ top: 3px;
1264
+ left: 3px;
1265
+ transition: transform 0.2s var(--ease-spring);
1266
+ }
1267
+ .toggle-switch.on::after { transform: translateX(20px); }
1268
+
1269
+ /* Danger zone */
1270
+ .danger-zone {
1271
+ border-color: rgba(240, 78, 78, 0.2);
1272
+ }
1273
+ .danger-zone h3 { color: var(--color-danger); }
1274
+
1275
+ /* ═══════════════════════════════════════════════════════════════════
1276
+ BILLING PAGE (inside dashboard)
1277
+ ═══════════════════════════════════════════════════════════════════ */
1278
+
1279
+ .billing-grid {
1280
+ display: grid;
1281
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
1282
+ gap: 16px;
1283
+ margin-top: 24px;
1284
+ }
1285
+ .billing-card {
1286
+ background: var(--color-bg-raised);
1287
+ border: 1px solid var(--color-border);
1288
+ border-radius: var(--radius-lg);
1289
+ padding: 28px;
1290
+ display: flex;
1291
+ flex-direction: column;
1292
+ gap: 12px;
1293
+ transition: all 0.25s var(--ease-out-expo);
1294
+ animation: fade-up 0.5s var(--ease-out-expo) both;
1295
+ }
1296
+ .billing-card:nth-child(2) { animation-delay: 0.1s; }
1297
+ .billing-card:hover {
1298
+ border-color: var(--color-border-hover);
1299
+ transform: translateY(-2px);
1300
+ }
1301
+ .billing-card h2 {
1302
+ font-size: 1.25rem;
1303
+ display: flex;
1304
+ align-items: center;
1305
+ gap: 10px;
1306
+ }
1307
+ .billing-card p { font-size: 0.875rem; color: var(--color-text-secondary); line-height: 1.6; flex: 1; }
1308
+
1309
+ /* ═══════════════════════════════════════════════════════════════════
1310
+ EMAIL PAGE (inside dashboard)
1311
+ ═══════════════════════════════════════════════════════════════════ */
1312
+
1313
+ .email-section {
1314
+ max-width: 560px;
1315
+ }
1316
+ .email-section .lede { margin-bottom: 24px; }
1317
+ .email-actions {
1318
+ display: flex;
1319
+ align-items: center;
1320
+ gap: 12px;
1321
+ }
1322
+
1323
+ /* ═══════════════════════════════════════════════════════════════════
1324
+ UTILITIES
1325
+ ═══════════════════════════════════════════════════════════════════ */
1326
+
1327
+ .badge {
1328
+ font-family: var(--font-mono);
1329
+ font-size: 0.6875rem;
1330
+ font-weight: 500;
1331
+ padding: 2px 10px;
1332
+ border-radius: var(--radius-full);
1333
+ display: inline-flex;
1334
+ align-items: center;
1335
+ gap: 4px;
1336
+ }
1337
+ .badge-accent { background: var(--color-accent-dim); color: var(--color-accent); }
1338
+ .badge-warm { background: var(--color-warm-dim); color: var(--color-warm); }
1339
+ .badge-info { background: var(--color-info-dim); color: var(--color-info); }
1340
+ .badge-danger { background: var(--color-danger-dim); color: var(--color-danger); }
1341
+ .badge-success { background: var(--color-success-dim); color: var(--color-success); }
1342
+
1343
+ .empty-state {
1344
+ display: flex;
1345
+ flex-direction: column;
1346
+ align-items: center;
1347
+ justify-content: center;
1348
+ padding: 60px 20px;
1349
+ text-align: center;
1350
+ }
1351
+ .empty-state-icon {
1352
+ font-size: 2.5rem;
1353
+ margin-bottom: 16px;
1354
+ opacity: 0.3;
1355
+ }
1356
+ .empty-state h3 { margin-bottom: 8px; }
1357
+ .empty-state p { color: var(--color-text-secondary); font-size: 0.875rem; max-width: 360px; }