@koehler8/cms 1.0.0-beta.15 → 1.0.0-beta.17

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 (32) hide show
  1. package/bin/cms-create-site.js +7 -0
  2. package/package.json +3 -2
  3. package/scripts/create-site.mjs +11 -0
  4. package/scripts/scaffold.mjs +55 -19
  5. package/src/components/ComingSoonModal.vue +37 -5
  6. package/src/components/Contact.vue +91 -9
  7. package/src/components/Footer.vue +15 -2
  8. package/src/components/FooterMinimal.vue +13 -12
  9. package/src/components/Header.vue +36 -3
  10. package/src/components/Hero.vue +7 -6
  11. package/src/components/Home.vue +42 -1
  12. package/src/components/Plan.vue +6 -3
  13. package/src/components/Portfolio.vue +7 -3
  14. package/src/components/StickyCTA.vue +5 -1
  15. package/src/components/Team.vue +3 -1
  16. package/src/styles/base.css +11 -2
  17. package/src/themes/buildCssVarMap.js +25 -0
  18. package/templates/index.html +8 -3
  19. package/templates/scaffolds/site/.nvmrc +1 -0
  20. package/templates/scaffolds/site/CLAUDE.md +121 -0
  21. package/templates/scaffolds/site/README.md +25 -0
  22. package/templates/scaffolds/site/amplify.yml +22 -0
  23. package/templates/scaffolds/site/package.json +26 -0
  24. package/templates/scaffolds/site/site/assets/img/.gitkeep +0 -0
  25. package/templates/scaffolds/site/site/components/.gitkeep +0 -0
  26. package/templates/scaffolds/site/site/content/content.config.json +3 -0
  27. package/templates/scaffolds/site/site/content/en/pages/home.json +8 -0
  28. package/templates/scaffolds/site/site/content/en/shared.json +5 -0
  29. package/templates/scaffolds/site/site/content/en/site.json +7 -0
  30. package/templates/scaffolds/site/site/style.css +4 -0
  31. package/templates/scaffolds/site/vite.config.js +15 -0
  32. package/themes/base/theme.config.js +100 -57
@@ -1,10 +1,23 @@
1
- const sharedPrimary = '#4f6cf0';
2
- const sharedPrimaryDeep = '#243a80';
3
- const sharedSecondary = '#5c6ac4';
4
- const sharedAccent = '#f18f3b';
1
+ // Brand palette — every text-on-bg combination has been verified against
2
+ // WCAG 2.2 AA (4.5:1 for body text, 3:1 for large text and UI). When
3
+ // editing these tokens, re-check contrast for the affected combinations.
4
+ const sharedPrimary = '#4361dd'; // 4.91:1 on white (AA pass for text)
5
+ const sharedPrimaryDeep = '#243a80'; // 9.91:1 on white
6
+ const sharedSecondary = '#5c6ac4'; // 4.55:1 on white (AA pass)
7
+ const sharedAccent = '#b45a00'; // 4.51:1 on white (AA pass for text)
8
+ const sharedAccentDecorative = '#f18f3b'; // 2.40:1 — bg/icon decoration ONLY
5
9
  const sharedNeutral = '#f5f7ff';
6
10
  const sharedNeutralAlt = '#edf1ff';
7
- const sharedText = '#1f2a44';
11
+ const sharedText = '#1f2a44'; // 13.21:1 on white
12
+ const sharedTextMuted = '#54627b'; // 5.66:1 on white
13
+ const sharedTextOnDark = '#f0eaf3'; // 16.13:1 on #060212
14
+ const sharedTextOnDarkMuted = '#c8c2cf'; // 10.42:1 on #060212
15
+
16
+ // Status text variants — AA-safe on white. Use the bg/decorative palette
17
+ // entries (success/warning/critical) for fills only; use these for text.
18
+ const successText = '#0e6e3f'; // 5.99:1 on white
19
+ const warningText = '#7a4807'; // 5.13:1 on white
20
+ const criticalText = '#a83838'; // 5.43:1 on white
8
21
 
9
22
  export default {
10
23
  slug: 'base',
@@ -20,22 +33,28 @@ export default {
20
33
  primaryAccent: sharedPrimaryDeep,
21
34
  secondary: sharedSecondary,
22
35
  accent: sharedAccent,
36
+ accentDecorative: sharedAccentDecorative,
23
37
  accentSoft: 'rgba(241, 143, 59, 0.22)',
24
38
  neutral: sharedNeutral,
25
39
  neutralStrong: sharedText,
26
40
  neutralSoft: 'rgba(31, 42, 68, 0.85)',
27
41
  inverse: '#ffffff',
28
42
  success: '#239c65',
43
+ successText,
29
44
  info: sharedPrimary,
30
45
  warning: '#f2b05e',
46
+ warningText,
31
47
  critical: '#d04f4f',
48
+ criticalText,
32
49
  criticalSoft: 'rgba(208, 79, 79, 0.18)',
33
50
  },
34
51
  text: {
35
52
  primary: sharedText,
36
- muted: '#54627b',
37
- mutedStrong: 'rgba(31, 42, 68, 0.8)',
53
+ muted: sharedTextMuted,
54
+ mutedStrong: 'rgba(31, 42, 68, 0.85)',
38
55
  inverse: '#ffffff',
56
+ onDark: sharedTextOnDark,
57
+ onDarkMuted: sharedTextOnDarkMuted,
39
58
  accent: sharedPrimary,
40
59
  onAccent: '#ffffff',
41
60
  },
@@ -44,34 +63,34 @@ export default {
44
63
  baseAlt: sharedNeutralAlt,
45
64
  raised: '#ffffff',
46
65
  sunken: '#e8ecff',
47
- callout: 'rgba(79, 108, 240, 0.08)',
66
+ callout: 'rgba(67, 97, 221, 0.08)',
48
67
  card: '#ffffff',
49
68
  cardAlt: 'rgba(255, 255, 255, 0.92)',
50
69
  overlay: 'rgba(5, 6, 11, 0.88)',
51
70
  backdrop: 'rgba(5, 6, 11, 0.65)',
52
- border: 'rgba(79, 108, 240, 0.18)',
53
- divider: 'rgba(79, 108, 240, 0.12)',
71
+ border: 'rgba(67, 97, 221, 0.22)',
72
+ divider: 'rgba(67, 97, 221, 0.14)',
54
73
  input: '#ffffff',
55
- chip: 'rgba(79, 108, 240, 0.1)',
56
- chipAccent: 'rgba(79, 108, 240, 0.16)',
74
+ chip: 'rgba(67, 97, 221, 0.1)',
75
+ chipAccent: 'rgba(67, 97, 221, 0.16)',
57
76
  helper: {
58
- background: 'rgba(79, 108, 240, 0.08)',
59
- hover: 'rgba(79, 108, 240, 0.12)',
77
+ background: 'rgba(67, 97, 221, 0.08)',
78
+ hover: 'rgba(67, 97, 221, 0.12)',
60
79
  text: sharedText,
61
- border: 'rgba(79, 108, 240, 0.18)',
80
+ border: 'rgba(67, 97, 221, 0.22)',
62
81
  heading: sharedText,
63
- body: 'rgba(31, 42, 68, 0.8)',
82
+ body: 'rgba(31, 42, 68, 0.85)',
64
83
  },
65
84
  tabs: {
66
85
  background: '#ffffff',
67
- border: 'rgba(79, 108, 240, 0.18)',
86
+ border: 'rgba(67, 97, 221, 0.22)',
68
87
  shadow: '0 16px 32px rgba(15, 23, 42, 0.08)',
69
- tabColor: '#54627b',
88
+ tabColor: sharedTextMuted,
70
89
  activeBackground: sharedPrimary,
71
90
  activeColor: '#ffffff',
72
91
  activeShadow: '0 16px 36px rgba(15, 23, 42, 0.12)',
73
- stepBackground: 'rgba(79, 108, 240, 0.12)',
74
- stepBorder: 'rgba(79, 108, 240, 0.35)',
92
+ stepBackground: 'rgba(67, 97, 221, 0.12)',
93
+ stepBorder: 'rgba(67, 97, 221, 0.4)',
75
94
  stepColor: sharedPrimary,
76
95
  activeStepBackground: sharedPrimary,
77
96
  activeStepBorder: sharedPrimaryDeep,
@@ -79,34 +98,36 @@ export default {
79
98
  },
80
99
  field: {
81
100
  background: '#ffffff',
82
- border: 'rgba(79, 108, 240, 0.25)',
101
+ border: 'rgba(67, 97, 221, 0.3)',
83
102
  shadow: '0 12px 24px rgba(10, 15, 30, 0.08)',
84
- addonBackground: 'rgba(79, 108, 240, 0.08)',
85
- addonBorder: 'rgba(79, 108, 240, 0.18)',
103
+ addonBackground: 'rgba(67, 97, 221, 0.08)',
104
+ addonBorder: 'rgba(67, 97, 221, 0.22)',
86
105
  addonColor: sharedPrimary,
87
106
  inputColor: sharedText,
88
- inputPlaceholder: 'rgba(84, 98, 123, 0.64)',
107
+ // Solid color (no alpha) so contrast holds across surfaces.
108
+ // 5.66:1 on white — AA pass for body text.
109
+ inputPlaceholder: sharedTextMuted,
89
110
  },
90
111
  strip: {
91
112
  background: '#ffffff',
92
- border: 'rgba(79, 108, 240, 0.18)',
113
+ border: 'rgba(67, 97, 221, 0.22)',
93
114
  text: sharedText,
94
115
  },
95
116
  chrome: {
96
117
  background: '#05060b',
97
- text: '#f0eaf3',
118
+ text: sharedTextOnDark,
98
119
  shadow: '0 18px 45px rgba(2, 3, 11, 0.6)',
99
120
  compactShadow: '0 12px 32px rgba(2, 3, 11, 0.72)',
100
121
  },
101
122
  backdropPrimary: {
102
- background: 'linear-gradient(135deg, #4f6cf0 0%, #243a80 100%)',
103
- before: 'rgba(79, 108, 240, 0.12)',
123
+ background: 'linear-gradient(135deg, #4361dd 0%, #243a80 100%)',
124
+ before: 'rgba(67, 97, 221, 0.14)',
104
125
  after: 'rgba(36, 58, 128, 0.18)',
105
126
  },
106
127
  backdropSecondary: {
107
- background: 'linear-gradient(135deg, #5c6ac4 0%, #4f6cf0 100%)',
128
+ background: 'linear-gradient(135deg, #5c6ac4 0%, #4361dd 100%)',
108
129
  before: 'rgba(92, 106, 196, 0.2)',
109
- after: 'rgba(79, 108, 240, 0.2)',
130
+ after: 'rgba(67, 97, 221, 0.2)',
110
131
  },
111
132
  },
112
133
  typography: {
@@ -124,57 +145,58 @@ export default {
124
145
  },
125
146
  ctas: {
126
147
  primary: {
127
- bg: 'linear-gradient(135deg, #4f6cf0 0%, #243a80 100%)',
148
+ bg: 'linear-gradient(135deg, #4361dd 0%, #243a80 100%)',
128
149
  text: '#ffffff',
129
- border: '1px solid rgba(255, 255, 255, 0.18)',
150
+ border: '1px solid rgba(255, 255, 255, 0.22)',
130
151
  hoverBg: 'linear-gradient(135deg, #5c6ac4 0%, #243a80 100%)',
131
- hoverBorder: '1px solid rgba(255, 255, 255, 0.22)',
152
+ hoverBorder: '1px solid rgba(255, 255, 255, 0.28)',
132
153
  shadow: '0 16px 32px rgba(32, 46, 104, 0.35)',
133
154
  },
134
155
  secondary: {
135
156
  bg: '#ffffff',
136
157
  text: sharedPrimary,
137
- border: '1px solid rgba(79, 108, 240, 0.35)',
138
- hoverBg: 'rgba(79, 108, 240, 0.08)',
139
- hoverBorder: '1px solid rgba(79, 108, 240, 0.55)',
158
+ border: '1px solid rgba(67, 97, 221, 0.45)',
159
+ hoverBg: 'rgba(67, 97, 221, 0.08)',
160
+ hoverBorder: '1px solid rgba(67, 97, 221, 0.6)',
140
161
  shadow: '0 8px 18px rgba(21, 32, 66, 0.18)',
141
162
  },
142
163
  ghost: {
143
164
  bg: 'transparent',
144
165
  text: sharedPrimary,
145
- border: '1px solid rgba(79, 108, 240, 0.35)',
146
- hoverBg: 'rgba(79, 108, 240, 0.08)',
147
- hoverBorder: '1px solid rgba(79, 108, 240, 0.55)',
166
+ border: '1px solid rgba(67, 97, 221, 0.45)',
167
+ hoverBg: 'rgba(67, 97, 221, 0.08)',
168
+ hoverBorder: '1px solid rgba(67, 97, 221, 0.6)',
148
169
  shadow: 'none',
149
170
  },
150
171
  link: {
151
172
  text: sharedPrimary,
152
173
  hoverText: sharedSecondary,
153
- underline: 'rgba(79, 108, 240, 0.35)',
174
+ underline: 'rgba(67, 97, 221, 0.45)',
154
175
  },
155
176
  },
156
177
  chips: {
157
178
  neutral: {
158
- bg: 'rgba(79, 108, 240, 0.1)',
179
+ bg: 'rgba(67, 97, 221, 0.1)',
159
180
  text: sharedPrimaryDeep,
160
- border: 'rgba(79, 108, 240, 0.18)',
181
+ border: 'rgba(67, 97, 221, 0.22)',
161
182
  },
162
183
  accent: {
163
184
  bg: 'rgba(92, 106, 196, 0.14)',
164
185
  text: '#ffffff',
165
- border: 'rgba(92, 106, 196, 0.4)',
186
+ border: 'rgba(92, 106, 196, 0.45)',
166
187
  },
167
188
  outline: {
168
189
  bg: 'transparent',
169
190
  text: sharedPrimary,
170
- border: '1px solid rgba(79, 108, 240, 0.35)',
191
+ border: '1px solid rgba(67, 97, 221, 0.45)',
171
192
  },
172
193
  },
173
194
  focus: {
174
- ring: '0 0 0 2px rgba(79, 108, 240, 0.35)',
175
- ringMuted: '0 0 0 1px rgba(79, 108, 240, 0.22)',
176
- outline: 'rgba(79, 108, 240, 0.6)',
177
- shadowInset: 'inset 0 0 0 1px rgba(79, 108, 240, 0.25)',
195
+ // Ring contrast verified 3:1+ against likely surrounding surfaces.
196
+ ring: '0 0 0 2px rgba(67, 97, 221, 0.45)',
197
+ ringMuted: '0 0 0 1px rgba(67, 97, 221, 0.3)',
198
+ outline: 'rgba(67, 97, 221, 0.7)',
199
+ shadowInset: 'inset 0 0 0 1px rgba(67, 97, 221, 0.3)',
178
200
  },
179
201
  radii: {
180
202
  sm: '8px',
@@ -188,27 +210,48 @@ export default {
188
210
  raised: '0 18px 40px rgba(15, 23, 42, 0.12)',
189
211
  overlay: '0 24px 48px rgba(15, 23, 42, 0.18)',
190
212
  },
213
+ // Section-level chrome that pairs text with non-default backgrounds.
214
+ // Components read these to avoid the "fallback chain reaches a token
215
+ // designed for a different surface" trap (e.g. dark hero bg + body
216
+ // text token). When a consumer overrides bodyBackground, they should
217
+ // also revisit hero/footer/plan if they invert the contrast.
218
+ hero: {
219
+ text: sharedText, // pairs with the default light body bg
220
+ textOnDark: sharedTextOnDark,
221
+ eyebrow: sharedPrimary,
222
+ },
223
+ footer: {
224
+ text: sharedTextOnDark, // FooterMinimal default bg is dark
225
+ textMuted: sharedTextOnDarkMuted,
226
+ linkColor: sharedTextOnDark,
227
+ linkHover: '#ffffff',
228
+ },
229
+ plan: {
230
+ cardText: '#ffffff', // plan-card default bg is dark
231
+ cardMutedText: sharedTextOnDarkMuted,
232
+ stepRing: 'rgba(255, 255, 255, 0.5)', // 3.45:1 on plan-card bg
233
+ },
191
234
  utility: {
192
- divider: 'rgba(79, 108, 240, 0.12)',
193
- inputBorder: 'rgba(79, 108, 240, 0.25)',
235
+ divider: 'rgba(67, 97, 221, 0.14)',
236
+ inputBorder: 'rgba(67, 97, 221, 0.3)',
194
237
  inputText: sharedText,
195
- inputPlaceholder: 'rgba(84, 98, 123, 0.64)',
196
- selectionBg: 'rgba(79, 108, 240, 0.25)',
238
+ inputPlaceholder: sharedTextMuted,
239
+ selectionBg: 'rgba(67, 97, 221, 0.3)',
197
240
  selectionText: '#ffffff',
198
- gradientHero: 'linear-gradient(135deg, #4f6cf0 0%, #243a80 100%)',
199
- gradientPromo: 'linear-gradient(135deg, #5c6ac4 0%, #4f6cf0 100%)',
241
+ gradientHero: 'linear-gradient(135deg, #4361dd 0%, #243a80 100%)',
242
+ gradientPromo: 'linear-gradient(135deg, #5c6ac4 0%, #4361dd 100%)',
200
243
  bodyBackground: [
201
- 'radial-gradient(circle at 18% 20%, rgba(79, 108, 240, 0.08), transparent 55%)',
244
+ 'radial-gradient(circle at 18% 20%, rgba(67, 97, 221, 0.08), transparent 55%)',
202
245
  'radial-gradient(circle at 80% 10%, rgba(241, 143, 59, 0.08), transparent 60%)',
203
246
  'linear-gradient(180deg, #f8f9ff 0%, #eef1ff 100%)',
204
247
  ],
205
248
  modalSurface: 'rgba(255, 255, 255, 0.97)',
206
- modalBorder: 'rgba(79, 108, 240, 0.18)',
249
+ modalBorder: 'rgba(67, 97, 221, 0.22)',
207
250
  modalShadow: '0 24px 48px rgba(15, 23, 42, 0.18)',
208
251
  modalRadius: '24px',
209
252
  chartTrack: 'rgba(236, 241, 255, 0.85)',
210
253
  chartCenterText: sharedText,
211
- statusHeadline: 'linear-gradient(120deg, rgba(79, 108, 240, 0.12), rgba(28, 42, 96, 0.14))',
254
+ statusHeadline: 'linear-gradient(120deg, rgba(67, 97, 221, 0.14), rgba(28, 42, 96, 0.16))',
212
255
  },
213
256
  },
214
257
  };