@invisibleloop/pulse 0.12.3 → 0.14.1

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 (166) hide show
  1. package/.claude/commands/verify.md +9 -5
  2. package/.claude/pulse-checklist.md +21 -1
  3. package/.github/workflows/publish.yml +1 -0
  4. package/.pulse-verified +1 -0
  5. package/CLAUDE.md +56 -15
  6. package/docs/.claude/commands/verify.md +4 -0
  7. package/docs/.claude/pulse-checklist.md +20 -2
  8. package/docs/public/.pulse-ui-version +1 -1
  9. package/docs/public/andypixel.css +237 -0
  10. package/docs/public/bookworms.css +422 -0
  11. package/docs/public/coutumes.css +584 -0
  12. package/docs/public/images/bookworms/hero-books.jpg +0 -0
  13. package/docs/public/images/bookworms/how-we-read-now.jpg +0 -0
  14. package/docs/public/images/bookworms/lantern-keepers.jpg +0 -0
  15. package/docs/public/images/bookworms/provincial-bookseller.jpg +0 -0
  16. package/docs/public/images/journey/178.jpg +0 -0
  17. package/docs/public/images/journey/29.jpg +0 -0
  18. package/docs/public/images/retrowheels/hero.jpg +0 -0
  19. package/docs/public/images/shop/devbook-pro.jpg +0 -0
  20. package/docs/public/images/suzukibento/1015.jpg +0 -0
  21. package/docs/public/images/suzukibento/1025.jpg +0 -0
  22. package/docs/public/images/suzukibento/1043.jpg +0 -0
  23. package/docs/public/images/suzukibento/1059.jpg +0 -0
  24. package/docs/public/images/suzukibento/1062.jpg +0 -0
  25. package/docs/public/images/suzukibento/1084.jpg +0 -0
  26. package/docs/public/images/swish/1469334031218-e382a71b716b.jpg +0 -0
  27. package/docs/public/images/swish/1483985988355-763728e1935b.jpg +0 -0
  28. package/docs/public/images/swish/1485518882345-15568b007407.jpg +0 -0
  29. package/docs/public/images/swish/1490481651871-ab68de25d43d.jpg +0 -0
  30. package/docs/public/images/swish/1496747611176-843222e1e57c.jpg +0 -0
  31. package/docs/public/images/swish/1502716119720-b23a93e5fe1b.jpg +0 -0
  32. package/docs/public/images/swish/1539109136881-3be0616acf4b.jpg +0 -0
  33. package/docs/public/images/swish/1551803091-e20673f15770.jpg +0 -0
  34. package/docs/public/images/swish/1558769132-cb1aea458c5e.jpg +0 -0
  35. package/docs/public/images/swish/1572804013309-59a88b7e92f1.jpg +0 -0
  36. package/docs/public/journey.css +528 -0
  37. package/docs/public/pulse-ui.css +1036 -22
  38. package/docs/public/retrowheels.css +402 -0
  39. package/docs/public/shop.css +235 -0
  40. package/docs/public/sparkys.css +349 -0
  41. package/docs/public/suzukibento.css +517 -0
  42. package/docs/public/swish.css +394 -0
  43. package/docs/server.js +19 -4
  44. package/docs/src/lib/nav.js +14 -3
  45. package/docs/src/pages/components/decorate.js +74 -0
  46. package/docs/src/pages/components/gallery.js +102 -0
  47. package/docs/src/pages/components/hero.js +1 -0
  48. package/docs/src/pages/components/marquee.js +76 -0
  49. package/docs/src/pages/components/photo-card.js +74 -0
  50. package/docs/src/pages/components/section.js +40 -1
  51. package/docs/src/pages/meta.js +26 -0
  52. package/docs/src/pages/templates/andypixel.js +260 -0
  53. package/docs/src/pages/templates/bookworms.js +227 -0
  54. package/docs/src/pages/templates/coutumes.js +226 -0
  55. package/docs/src/pages/templates/journey.js +186 -0
  56. package/docs/src/pages/templates/retrowheels.js +342 -0
  57. package/docs/src/pages/templates/shop.js +257 -0
  58. package/docs/src/pages/templates/sparkys.js +249 -0
  59. package/docs/src/pages/templates/suzukibento.js +200 -0
  60. package/docs/src/pages/templates/swish.js +313 -0
  61. package/docs/src/pages/templates.js +313 -2
  62. package/docs/src/pages/testing.js +2 -1
  63. package/examples/andypixel.css +237 -0
  64. package/examples/andypixel.js +258 -0
  65. package/examples/bookworms.css +422 -0
  66. package/examples/bookworms.js +225 -0
  67. package/examples/contact.js +1 -0
  68. package/examples/counter.js +1 -0
  69. package/examples/dev.server.js +17 -0
  70. package/examples/journey.css +528 -0
  71. package/examples/journey.js +186 -0
  72. package/examples/pricing.js +1 -0
  73. package/examples/quiz.js +1 -0
  74. package/examples/retrowheels.css +402 -0
  75. package/examples/retrowheels.js +340 -0
  76. package/examples/shared.js +6 -0
  77. package/examples/suzukibento.css +513 -0
  78. package/examples/suzukibento.js +200 -0
  79. package/examples/swish.css +394 -0
  80. package/examples/swish.js +311 -0
  81. package/examples/todos.js +1 -0
  82. package/package.json +2 -3
  83. package/public/.pulse-ui-version +1 -1
  84. package/public/images/bookworms/hero-books.jpg +0 -0
  85. package/public/images/bookworms/how-we-read-now.jpg +0 -0
  86. package/public/images/bookworms/lantern-keepers.jpg +0 -0
  87. package/public/images/bookworms/provincial-bookseller.jpg +0 -0
  88. package/public/images/journey/178.jpg +0 -0
  89. package/public/images/journey/29.jpg +0 -0
  90. package/public/images/retrowheels/hero.jpg +0 -0
  91. package/public/images/shop/devbook-pro.jpg +0 -0
  92. package/public/images/suzukibento/1015.jpg +0 -0
  93. package/public/images/suzukibento/1025.jpg +0 -0
  94. package/public/images/suzukibento/1043.jpg +0 -0
  95. package/public/images/suzukibento/1059.jpg +0 -0
  96. package/public/images/suzukibento/1062.jpg +0 -0
  97. package/public/images/suzukibento/1084.jpg +0 -0
  98. package/public/images/swish/1469334031218-e382a71b716b.jpg +0 -0
  99. package/public/images/swish/1483985988355-763728e1935b.jpg +0 -0
  100. package/public/images/swish/1485518882345-15568b007407.jpg +0 -0
  101. package/public/images/swish/1490481651871-ab68de25d43d.jpg +0 -0
  102. package/public/images/swish/1496747611176-843222e1e57c.jpg +0 -0
  103. package/public/images/swish/1502716119720-b23a93e5fe1b.jpg +0 -0
  104. package/public/images/swish/1539109136881-3be0616acf4b.jpg +0 -0
  105. package/public/images/swish/1551803091-e20673f15770.jpg +0 -0
  106. package/public/images/swish/1558769132-cb1aea458c5e.jpg +0 -0
  107. package/public/images/swish/1572804013309-59a88b7e92f1.jpg +0 -0
  108. package/public/pulse-ui.css +1036 -22
  109. package/scripts/build.js +72 -18
  110. package/src/agent/checklist.md +20 -2
  111. package/src/agent/commands/verify.md +4 -0
  112. package/src/agent/guide-components.md +145 -7
  113. package/src/agent/guide-design-gallery.md +288 -0
  114. package/src/agent/guide-design-references.md +172 -0
  115. package/src/agent/guide-explore.md +313 -0
  116. package/src/agent/guide-styles.md +197 -11
  117. package/src/agent/guide-templates.md +220 -10
  118. package/src/agent/guide.md +9 -4
  119. package/src/agent/workflow.md +208 -58
  120. package/src/cli/dev.js +39 -7
  121. package/src/cli/fmt.js +113 -0
  122. package/src/cli/index.js +63 -30
  123. package/src/cli/scaffold.js +2 -2
  124. package/src/html.js +6 -1
  125. package/src/mcp/server.js +2415 -101
  126. package/src/mcp/validate-worker.js +34 -5
  127. package/src/runtime/ssr.js +4 -1
  128. package/src/server/index.js +22 -2
  129. package/src/spec/schema.js +5 -0
  130. package/src/testing/html.js +130 -4
  131. package/src/testing/testing.test.js +58 -0
  132. package/src/ui/banner.js +24 -9
  133. package/src/ui/brand-statement.js +58 -0
  134. package/src/ui/button.js +12 -1
  135. package/src/ui/card.js +20 -1
  136. package/src/ui/colophon.js +29 -0
  137. package/src/ui/contact-row.js +41 -0
  138. package/src/ui/cta.js +18 -4
  139. package/src/ui/decorate.js +55 -0
  140. package/src/ui/display-heading.js +44 -0
  141. package/src/ui/drop-cap.js +29 -0
  142. package/src/ui/editorial-hero.js +63 -0
  143. package/src/ui/entry-list.js +36 -0
  144. package/src/ui/feature.js +20 -3
  145. package/src/ui/footer.js +78 -9
  146. package/src/ui/gallery.js +56 -0
  147. package/src/ui/hero.js +68 -18
  148. package/src/ui/image-pair.js +72 -0
  149. package/src/ui/index.js +20 -0
  150. package/src/ui/input.js +1 -0
  151. package/src/ui/marquee.js +48 -0
  152. package/src/ui/nav.js +19 -9
  153. package/src/ui/photo-card.js +44 -0
  154. package/src/ui/product-card.js +65 -0
  155. package/src/ui/pullquote.js +14 -3
  156. package/src/ui/search.js +1 -0
  157. package/src/ui/section-label.js +38 -0
  158. package/src/ui/section.js +1 -1
  159. package/src/ui/service-card.js +47 -0
  160. package/src/ui/stat-grid.js +40 -0
  161. package/src/ui/stat.js +16 -2
  162. package/src/ui/testimonial.js +17 -6
  163. package/src/ui/textarea.js +1 -0
  164. package/src/ui/top-strip.js +47 -0
  165. package/src/ui/trust-list.js +46 -0
  166. package/src/ui/ui.test.js +35 -0
package/examples/quiz.js CHANGED
@@ -67,6 +67,7 @@ export default {
67
67
  title: 'Quiz — Pulse',
68
68
  description: 'A multiple-choice quiz built with Pulse. Demonstrates multi-step state machine and computed views.',
69
69
  styles: ['/pulse-ui.css'],
70
+ theme: 'dark',
70
71
  },
71
72
 
72
73
  state: {
@@ -0,0 +1,402 @@
1
+ /*
2
+ * retrowheels.css — Retro Wheels Co. bicycle shop example
3
+ *
4
+ * 1970s enamel-sign aesthetic: cream paper, burnt orange, mustard yellow,
5
+ * forest green, oxidised navy. Rockwell slab serif + Courier New monospace.
6
+ * All system fonts — zero external HTTP requests.
7
+ *
8
+ * Split into two logical sections:
9
+ * 1. Token overrides — hex values, palette definitions
10
+ * 2. Component styles — layout, typography, custom elements (var() only)
11
+ */
12
+
13
+ /* ==========================================================================
14
+ 1. Token overrides (hex values live here)
15
+ ========================================================================== */
16
+
17
+ /* Named palette — referenced throughout this file via var() */
18
+ :root {
19
+ --rw-orange: #c8431f;
20
+ --rw-orange-dark: #a8351a;
21
+ --rw-cream: #f4e9d3;
22
+ --rw-cream-deep: #ead9b8;
23
+ --rw-navy: #1f2a3a;
24
+ --rw-mustard: #d9a441;
25
+ --rw-mustard-dark: #8a6418;
26
+ --rw-green: #2f5d3a;
27
+ --rw-green-dark: #1f3f27;
28
+ --rw-ink: #2b2018;
29
+ }
30
+
31
+ /* System slab-serif stack for headings — no Google Fonts needed */
32
+ :root {
33
+ --font: Georgia, 'Bookman Old Style', serif;
34
+ --font-display: 'Rockwell', 'Bookman Old Style', Georgia, serif;
35
+ }
36
+
37
+ [data-theme="light"] {
38
+ --ui-bg: #f4e9d3;
39
+ --ui-surface: #fbf3df;
40
+ --ui-surface-2: #ead9b8;
41
+ --ui-border: #c9b890;
42
+ --ui-text: #2b2018;
43
+ --ui-muted: #6b5d48;
44
+ --ui-accent: #a8351a;
45
+ --ui-accent-hover: #8a2912;
46
+ --ui-accent-dim: rgba(168, 53, 26, 0.12);
47
+ --ui-accent-text: #fbf3df;
48
+ }
49
+
50
+ [data-theme="light"] .ui-btn--primary {
51
+ color: #fbf3df;
52
+ }
53
+
54
+ /* ==========================================================================
55
+ 2. Component styles (var() only — no hex values below this line)
56
+ ========================================================================== */
57
+
58
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
59
+
60
+ body {
61
+ font-family: var(--ui-font);
62
+ line-height: 1.6;
63
+ color: var(--ui-text);
64
+ background: var(--ui-bg);
65
+ }
66
+
67
+ /* Slab-serif for all headings and named component titles */
68
+ h1, h2, h3, h4, h5, h6,
69
+ .ui-hero-title, .ui-section-title, .ui-card-title,
70
+ .ui-cta-title, .ui-feature-title, .ui-stat-value {
71
+ font-family: var(--ui-font-display);
72
+ letter-spacing: -0.01em;
73
+ }
74
+
75
+ /* --------------------------------------------------------------------------
76
+ Brand logo wordmark
77
+ -------------------------------------------------------------------------- */
78
+ .rw-logo-text {
79
+ font-family: var(--ui-font-display);
80
+ font-weight: 900;
81
+ letter-spacing: -0.01em;
82
+ font-size: 1.1rem;
83
+ }
84
+
85
+ /* --------------------------------------------------------------------------
86
+ Skip link
87
+ -------------------------------------------------------------------------- */
88
+ .rw-skip-link {
89
+ position: absolute;
90
+ left: -9999px;
91
+ top: 0;
92
+ }
93
+
94
+ .rw-skip-link:focus {
95
+ left: var(--ui-space-2);
96
+ top: var(--ui-space-2);
97
+ background: var(--rw-cream);
98
+ color: var(--rw-navy);
99
+ padding: var(--ui-space-2) var(--ui-space-3);
100
+ z-index: 1000;
101
+ }
102
+
103
+ /* --------------------------------------------------------------------------
104
+ Eyebrow labels
105
+ -------------------------------------------------------------------------- */
106
+ .rw-eyebrow {
107
+ font-family: 'Courier New', monospace;
108
+ letter-spacing: 0.25em;
109
+ text-transform: uppercase;
110
+ font-size: var(--ui-text-xs);
111
+ color: var(--rw-orange-dark);
112
+ }
113
+
114
+ .rw-eyebrow--on-orange {
115
+ color: var(--rw-cream);
116
+ }
117
+
118
+ /* --------------------------------------------------------------------------
119
+ Decorative rule
120
+ -------------------------------------------------------------------------- */
121
+ .rw-rule {
122
+ border: 0;
123
+ border-top: 3px double var(--ui-border);
124
+ margin: var(--ui-space-8) 0;
125
+ }
126
+
127
+ /* --------------------------------------------------------------------------
128
+ Full-bleed hero
129
+ -------------------------------------------------------------------------- */
130
+ .rw-hero {
131
+ position: relative;
132
+ min-height: 70vh;
133
+ background:
134
+ linear-gradient(180deg, rgba(31, 42, 58, 0.55) 0%, rgba(31, 42, 58, 0.85) 100%),
135
+ url('/images/retrowheels/hero.jpg') center / cover no-repeat;
136
+ color: var(--rw-cream);
137
+ padding: var(--ui-space-24) var(--ui-space-6);
138
+ display: flex;
139
+ align-items: flex-end;
140
+ }
141
+
142
+ .rw-hero-inner {
143
+ max-width: 64rem;
144
+ margin: 0 auto;
145
+ width: 100%;
146
+ }
147
+
148
+ .rw-hero-eyebrow {
149
+ font-family: 'Courier New', monospace;
150
+ letter-spacing: 0.3em;
151
+ text-transform: uppercase;
152
+ font-size: var(--ui-text-sm);
153
+ color: var(--rw-mustard);
154
+ display: inline-block;
155
+ padding: var(--ui-space-1) var(--ui-space-3);
156
+ border: 2px solid var(--rw-mustard);
157
+ margin-bottom: var(--ui-space-6);
158
+ }
159
+
160
+ .rw-hero-title {
161
+ font-family: var(--ui-font-display);
162
+ font-weight: 900;
163
+ font-size: clamp(2.5rem, 7vw, 5.5rem);
164
+ line-height: 1.05;
165
+ letter-spacing: -0.02em;
166
+ margin-bottom: var(--ui-space-5);
167
+ text-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
168
+ }
169
+
170
+ .rw-hero-title em {
171
+ font-style: italic;
172
+ color: var(--rw-mustard);
173
+ }
174
+
175
+ .rw-hero-sub {
176
+ font-size: var(--ui-text-xl);
177
+ max-width: 38rem;
178
+ margin-bottom: var(--ui-space-6);
179
+ color: var(--rw-cream);
180
+ opacity: 0.95;
181
+ }
182
+
183
+ .rw-hero-actions {
184
+ display: flex;
185
+ gap: var(--ui-space-3);
186
+ flex-wrap: wrap;
187
+ }
188
+
189
+ .rw-hero-image-credit {
190
+ position: absolute;
191
+ bottom: var(--ui-space-2);
192
+ right: var(--ui-space-3);
193
+ font-size: var(--ui-text-xs);
194
+ opacity: 0.6;
195
+ font-family: 'Courier New', monospace;
196
+ }
197
+
198
+ /* --------------------------------------------------------------------------
199
+ Stat strip (inverted navy bar)
200
+ -------------------------------------------------------------------------- */
201
+ .rw-stat-strip {
202
+ background: var(--rw-navy);
203
+ color: var(--rw-cream);
204
+ padding: var(--ui-space-8) var(--ui-space-6);
205
+ }
206
+
207
+ .rw-stat-strip .ui-stat-label {
208
+ color: var(--rw-mustard);
209
+ font-family: 'Courier New', monospace;
210
+ letter-spacing: 0.2em;
211
+ text-transform: uppercase;
212
+ font-size: var(--ui-text-xs);
213
+ }
214
+
215
+ .rw-stat-strip .ui-stat-value {
216
+ color: var(--rw-cream);
217
+ font-family: var(--ui-font-display);
218
+ font-size: var(--ui-text-4xl);
219
+ }
220
+
221
+ .rw-stat-strip-inner {
222
+ max-width: 64rem;
223
+ margin: 0 auto;
224
+ display: grid;
225
+ grid-template-columns: repeat(4, 1fr);
226
+ gap: var(--ui-space-6);
227
+ text-align: center;
228
+ }
229
+
230
+ @media (max-width: 640px) {
231
+ .rw-stat-strip-inner {
232
+ grid-template-columns: repeat(2, 1fr);
233
+ }
234
+ }
235
+
236
+ /* --------------------------------------------------------------------------
237
+ Editorial prose section (drop cap on first paragraph)
238
+ -------------------------------------------------------------------------- */
239
+ .rw-editorial {
240
+ max-width: 42rem;
241
+ margin: 0 auto;
242
+ padding: var(--ui-space-16) var(--ui-space-6);
243
+ }
244
+
245
+ .rw-editorial p {
246
+ font-size: var(--ui-text-lg);
247
+ margin-bottom: var(--ui-space-5);
248
+ }
249
+
250
+ .rw-editorial hr + p::first-letter {
251
+ font-family: var(--ui-font-display);
252
+ font-size: 3.5rem;
253
+ font-weight: 900;
254
+ float: left;
255
+ line-height: 0.9;
256
+ padding: 0.25rem var(--ui-space-2) 0 0;
257
+ color: var(--rw-orange-dark);
258
+ }
259
+
260
+ /* --------------------------------------------------------------------------
261
+ Section template
262
+ -------------------------------------------------------------------------- */
263
+ .rw-section {
264
+ padding: var(--ui-space-16) var(--ui-space-6);
265
+ }
266
+
267
+ .rw-section--alt {
268
+ background: var(--rw-cream-deep);
269
+ }
270
+
271
+ .rw-section-inner {
272
+ max-width: 64rem;
273
+ margin: 0 auto;
274
+ }
275
+
276
+ .rw-section-title {
277
+ font-family: var(--ui-font-display);
278
+ font-size: var(--ui-text-4xl);
279
+ font-weight: 900;
280
+ margin-bottom: var(--ui-space-2);
281
+ letter-spacing: -0.01em;
282
+ }
283
+
284
+ .rw-section-deck {
285
+ color: var(--ui-muted);
286
+ font-size: var(--ui-text-lg);
287
+ margin-bottom: var(--ui-space-10);
288
+ max-width: 36rem;
289
+ }
290
+
291
+ /* --------------------------------------------------------------------------
292
+ Services grid
293
+ -------------------------------------------------------------------------- */
294
+ .rw-service-grid {
295
+ display: grid;
296
+ grid-template-columns: repeat(3, 1fr);
297
+ gap: var(--ui-space-6);
298
+ }
299
+
300
+ @media (max-width: 900px) { .rw-service-grid { grid-template-columns: repeat(2, 1fr); } }
301
+ @media (max-width: 600px) { .rw-service-grid { grid-template-columns: 1fr; } }
302
+
303
+ .rw-service {
304
+ background: var(--ui-surface);
305
+ border: 2px solid var(--ui-border);
306
+ padding: var(--ui-space-6);
307
+ position: relative;
308
+ }
309
+
310
+ .rw-service-num {
311
+ font-family: 'Courier New', monospace;
312
+ font-size: var(--ui-text-xs);
313
+ letter-spacing: 0.2em;
314
+ color: var(--rw-orange-dark);
315
+ margin-bottom: var(--ui-space-3);
316
+ }
317
+
318
+ .rw-service h3 {
319
+ font-family: var(--ui-font-display);
320
+ font-size: var(--ui-text-xl);
321
+ font-weight: 900;
322
+ margin-bottom: var(--ui-space-2);
323
+ }
324
+
325
+ .rw-service p {
326
+ color: var(--ui-muted);
327
+ margin-bottom: var(--ui-space-4);
328
+ }
329
+
330
+ .rw-service-price {
331
+ font-family: 'Courier New', monospace;
332
+ font-size: var(--ui-text-sm);
333
+ color: var(--rw-green-dark);
334
+ border-top: 1px dashed var(--ui-border);
335
+ padding-top: var(--ui-space-3);
336
+ }
337
+
338
+ /* --------------------------------------------------------------------------
339
+ Visit section — hours + booking card
340
+ -------------------------------------------------------------------------- */
341
+ .rw-visit-grid {
342
+ display: grid;
343
+ grid-template-columns: 1fr 1fr;
344
+ gap: var(--ui-space-12);
345
+ align-items: start;
346
+ }
347
+
348
+ @media (max-width: 720px) {
349
+ .rw-visit-grid { grid-template-columns: 1fr; }
350
+ }
351
+
352
+ .rw-hours-heading {
353
+ font-family: var(--ui-font-display);
354
+ font-size: var(--ui-text-xl);
355
+ font-weight: 900;
356
+ margin-bottom: var(--ui-space-3);
357
+ }
358
+
359
+ .rw-hours {
360
+ font-family: 'Courier New', monospace;
361
+ font-size: var(--ui-text-base);
362
+ list-style: none;
363
+ }
364
+
365
+ .rw-hours-row {
366
+ display: flex;
367
+ justify-content: space-between;
368
+ padding: var(--ui-space-2) 0;
369
+ border-bottom: 1px dashed var(--ui-border);
370
+ }
371
+
372
+ .rw-hours li:last-child { border-bottom: 0; }
373
+
374
+ .rw-closed { color: var(--rw-orange-dark); }
375
+
376
+ .rw-address {
377
+ margin-top: var(--ui-space-6);
378
+ line-height: 1.7;
379
+ }
380
+
381
+ /* --------------------------------------------------------------------------
382
+ Saturday ride banner (full-bleed burnt orange)
383
+ -------------------------------------------------------------------------- */
384
+ .rw-ride-banner {
385
+ background: var(--rw-orange-dark);
386
+ color: var(--rw-cream);
387
+ padding: var(--ui-space-16) var(--ui-space-6);
388
+ text-align: center;
389
+ }
390
+
391
+ .rw-ride-banner h2 {
392
+ color: var(--rw-cream);
393
+ font-size: clamp(2rem, 5vw, 3.5rem);
394
+ font-weight: 900;
395
+ margin-bottom: var(--ui-space-3);
396
+ }
397
+
398
+ .rw-ride-banner p {
399
+ font-size: var(--ui-text-lg);
400
+ max-width: 40rem;
401
+ margin: 0 auto var(--ui-space-6);
402
+ }