@invisibleloop/pulse 0.20.11 → 0.20.20

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 (266) hide show
  1. package/package.json +6 -5
  2. package/public/.pulse-ui-version +1 -1
  3. package/scripts/build.js +26 -0
  4. package/scripts/release-version.js +17 -8
  5. package/scripts/strip-server.test.js +60 -0
  6. package/src/agent/checklist.md +8 -12
  7. package/src/agent/commands/pulse-start.md +2 -0
  8. package/src/agent/commands/verify.md +30 -8
  9. package/src/agent/guide-components.md +7 -25
  10. package/src/agent/guide-routing.md +0 -12
  11. package/src/agent/guide-server.md +102 -1
  12. package/src/agent/guide-spec.md +8 -1
  13. package/src/agent/guide-styles.md +23 -0
  14. package/src/agent/identity.md +9 -0
  15. package/src/agent/workflow.md +4 -23
  16. package/src/cli/check-bundles.js +113 -0
  17. package/src/cli/check-bundles.test.js +137 -0
  18. package/src/cli/cli.test.js +105 -0
  19. package/src/cli/dev.js +48 -3
  20. package/src/cli/diagnose.js +105 -0
  21. package/src/cli/diagnose.test.js +124 -0
  22. package/src/cli/discover.js +9 -2
  23. package/src/cli/index.js +171 -9
  24. package/src/cli/process-utils.js +57 -0
  25. package/src/cli/process-utils.test.js +114 -0
  26. package/src/cli/review.js +391 -0
  27. package/src/cli/review.test.js +143 -0
  28. package/src/cli/scaffold.js +9 -4
  29. package/src/cli/stamp.js +102 -0
  30. package/src/cli/stamp.test.js +149 -0
  31. package/src/cli/start.js +15 -2
  32. package/src/cli/validate.js +184 -0
  33. package/src/cli/validate.test.js +153 -0
  34. package/src/mcp/mcp.test.js +261 -30
  35. package/src/mcp/server.js +207 -515
  36. package/src/mcp/validate-worker.js +18 -1
  37. package/src/runtime/index.js +144 -11
  38. package/src/runtime/runtime.test.js +199 -0
  39. package/src/runtime/ssr.js +13 -6
  40. package/src/runtime/ssr.test.js +31 -0
  41. package/src/server/index.js +162 -9
  42. package/src/server/server.test.js +225 -2
  43. package/src/spec/schema.js +1 -1
  44. package/src/ui/index.js +0 -5
  45. package/src/ui/ui.test.js +0 -75
  46. package/types/ui.d.ts +0 -21
  47. package/.claude/commands/build-page.md +0 -63
  48. package/.claude/commands/new-doc-page.md +0 -45
  49. package/.claude/commands/pulse-start.md +0 -11
  50. package/.claude/commands/pulse-stop.md +0 -5
  51. package/.claude/commands/verify.md +0 -118
  52. package/.claude/pulse-checklist.md +0 -189
  53. package/.github/workflows/ci.yml +0 -25
  54. package/.github/workflows/publish.yml +0 -45
  55. package/.pulse/load-reports/home/1773432711417.json +0 -22
  56. package/.pulse-verified +0 -1
  57. package/AGENTS.md +0 -697
  58. package/CLAUDE.md +0 -697
  59. package/README.md +0 -95
  60. package/benchmark/public/dist/counter.boot-PO6SNSJZ.js +0 -8
  61. package/benchmark/public/dist/home.boot-YK6VAEQI.js +0 -6
  62. package/benchmark/public/dist/manifest.json +0 -5
  63. package/benchmark/public/dist/runtime-5Y7ESAIB.js +0 -2
  64. package/benchmark/public/dist/runtime-KO4BHUQ3.js +0 -49
  65. package/benchmark/results/2026-03-27-09-20.json +0 -188
  66. package/benchmark/results/2026-03-27-09-21.json +0 -188
  67. package/benchmark/results/2026-03-27-09-29.json +0 -188
  68. package/benchmark/results/2026-03-27-10-14.json +0 -188
  69. package/benchmark/results/2026-03-27-10-18.json +0 -232
  70. package/benchmark/src/pages/counter.js +0 -37
  71. package/benchmark/src/pages/home.js +0 -21
  72. package/docs/.claude/commands/pulse-build.md +0 -7
  73. package/docs/.claude/commands/pulse-dev.md +0 -7
  74. package/docs/.claude/commands/pulse-start.md +0 -9
  75. package/docs/.claude/commands/pulse-stop.md +0 -5
  76. package/docs/.claude/commands/verify.md +0 -84
  77. package/docs/.claude/coverage-check.js +0 -196
  78. package/docs/.claude/pulse-checklist.md +0 -189
  79. package/docs/public/.pulse-ui-version +0 -1
  80. package/docs/public/andypixel.css +0 -237
  81. package/docs/public/bookworms.css +0 -422
  82. package/docs/public/coutumes.css +0 -561
  83. package/docs/public/docs.css +0 -2388
  84. package/docs/public/favicon.svg +0 -4
  85. package/docs/public/home-brut.css +0 -982
  86. package/docs/public/images/bookworms/hero-books.jpg +0 -0
  87. package/docs/public/images/bookworms/how-we-read-now.jpg +0 -0
  88. package/docs/public/images/bookworms/lantern-keepers.jpg +0 -0
  89. package/docs/public/images/bookworms/provincial-bookseller.jpg +0 -0
  90. package/docs/public/images/journey/178.jpg +0 -0
  91. package/docs/public/images/journey/29.jpg +0 -0
  92. package/docs/public/images/retrowheels/hero.jpg +0 -0
  93. package/docs/public/images/shop/devbook-pro.jpg +0 -0
  94. package/docs/public/images/suzukibento/1015.jpg +0 -0
  95. package/docs/public/images/suzukibento/1025.jpg +0 -0
  96. package/docs/public/images/suzukibento/1043.jpg +0 -0
  97. package/docs/public/images/suzukibento/1059.jpg +0 -0
  98. package/docs/public/images/suzukibento/1062.jpg +0 -0
  99. package/docs/public/images/suzukibento/1084.jpg +0 -0
  100. package/docs/public/images/swish/1469334031218-e382a71b716b.jpg +0 -0
  101. package/docs/public/images/swish/1483985988355-763728e1935b.jpg +0 -0
  102. package/docs/public/images/swish/1485518882345-15568b007407.jpg +0 -0
  103. package/docs/public/images/swish/1490481651871-ab68de25d43d.jpg +0 -0
  104. package/docs/public/images/swish/1496747611176-843222e1e57c.jpg +0 -0
  105. package/docs/public/images/swish/1502716119720-b23a93e5fe1b.jpg +0 -0
  106. package/docs/public/images/swish/1539109136881-3be0616acf4b.jpg +0 -0
  107. package/docs/public/images/swish/1551803091-e20673f15770.jpg +0 -0
  108. package/docs/public/images/swish/1558769132-cb1aea458c5e.jpg +0 -0
  109. package/docs/public/images/swish/1572804013309-59a88b7e92f1.jpg +0 -0
  110. package/docs/public/img/heic1501a.jpg +0 -0
  111. package/docs/public/img/placeholder-landscape.svg +0 -18
  112. package/docs/public/img/placeholder-square.svg +0 -14
  113. package/docs/public/img/placeholder-tall.svg +0 -22
  114. package/docs/public/journey.css +0 -528
  115. package/docs/public/menu.js +0 -327
  116. package/docs/public/pulse-ui.css +0 -3028
  117. package/docs/public/pulse-ui.js +0 -257
  118. package/docs/public/retrowheels.css +0 -425
  119. package/docs/public/shop.css +0 -269
  120. package/docs/public/sparkys.css +0 -382
  121. package/docs/public/suzukibento.css +0 -517
  122. package/docs/public/swish.css +0 -394
  123. package/docs/public/theme.css +0 -52
  124. package/docs/public/themes/lumio.css +0 -50
  125. package/docs/public/themes/observatory.css +0 -104
  126. package/docs/server.js +0 -161
  127. package/docs/src/lib/component-page.js +0 -49
  128. package/docs/src/lib/highlight.js +0 -2
  129. package/docs/src/lib/layout.js +0 -190
  130. package/docs/src/lib/metrics-store.js +0 -6
  131. package/docs/src/lib/nav.js +0 -171
  132. package/docs/src/lib/stats.js +0 -81
  133. package/docs/src/pages/accessibility.js +0 -157
  134. package/docs/src/pages/actions.js +0 -194
  135. package/docs/src/pages/auth.js +0 -176
  136. package/docs/src/pages/caching.js +0 -95
  137. package/docs/src/pages/components/accordion.js +0 -48
  138. package/docs/src/pages/components/alert.js +0 -35
  139. package/docs/src/pages/components/app-badge.js +0 -41
  140. package/docs/src/pages/components/avatar.js +0 -35
  141. package/docs/src/pages/components/badge.js +0 -36
  142. package/docs/src/pages/components/breadcrumbs.js +0 -94
  143. package/docs/src/pages/components/button.js +0 -84
  144. package/docs/src/pages/components/card.js +0 -225
  145. package/docs/src/pages/components/charts.js +0 -283
  146. package/docs/src/pages/components/checkbox.js +0 -129
  147. package/docs/src/pages/components/cluster.js +0 -47
  148. package/docs/src/pages/components/container.js +0 -40
  149. package/docs/src/pages/components/cta.js +0 -54
  150. package/docs/src/pages/components/divider.js +0 -37
  151. package/docs/src/pages/components/empty.js +0 -36
  152. package/docs/src/pages/components/feature.js +0 -60
  153. package/docs/src/pages/components/fieldset.js +0 -65
  154. package/docs/src/pages/components/fileupload.js +0 -128
  155. package/docs/src/pages/components/footer.js +0 -58
  156. package/docs/src/pages/components/grid.js +0 -169
  157. package/docs/src/pages/components/heading.js +0 -107
  158. package/docs/src/pages/components/hero.js +0 -123
  159. package/docs/src/pages/components/icons.js +0 -410
  160. package/docs/src/pages/components/image.js +0 -71
  161. package/docs/src/pages/components/input.js +0 -51
  162. package/docs/src/pages/components/media.js +0 -51
  163. package/docs/src/pages/components/modal.js +0 -111
  164. package/docs/src/pages/components/nav.js +0 -136
  165. package/docs/src/pages/components/phone-frame.js +0 -74
  166. package/docs/src/pages/components/progress.js +0 -102
  167. package/docs/src/pages/components/prose.js +0 -111
  168. package/docs/src/pages/components/pullquote.js +0 -71
  169. package/docs/src/pages/components/radio.js +0 -194
  170. package/docs/src/pages/components/rating.js +0 -106
  171. package/docs/src/pages/components/search.js +0 -61
  172. package/docs/src/pages/components/section.js +0 -98
  173. package/docs/src/pages/components/segmented.js +0 -121
  174. package/docs/src/pages/components/select.js +0 -45
  175. package/docs/src/pages/components/slider.js +0 -115
  176. package/docs/src/pages/components/spinner.js +0 -73
  177. package/docs/src/pages/components/stack.js +0 -48
  178. package/docs/src/pages/components/stat.js +0 -55
  179. package/docs/src/pages/components/stepper.js +0 -66
  180. package/docs/src/pages/components/table.js +0 -45
  181. package/docs/src/pages/components/textarea.js +0 -31
  182. package/docs/src/pages/components/toggle.js +0 -84
  183. package/docs/src/pages/components/tooltip.js +0 -48
  184. package/docs/src/pages/components.js +0 -200
  185. package/docs/src/pages/config.js +0 -193
  186. package/docs/src/pages/constraints.js +0 -100
  187. package/docs/src/pages/deploy.js +0 -233
  188. package/docs/src/pages/error-pages.js +0 -99
  189. package/docs/src/pages/extending.js +0 -198
  190. package/docs/src/pages/faq.js +0 -99
  191. package/docs/src/pages/forms.js +0 -129
  192. package/docs/src/pages/getting-started.js +0 -147
  193. package/docs/src/pages/guard.js +0 -120
  194. package/docs/src/pages/home.js +0 -350
  195. package/docs/src/pages/how-it-works.js +0 -244
  196. package/docs/src/pages/hydration.js +0 -108
  197. package/docs/src/pages/images.js +0 -120
  198. package/docs/src/pages/markdown.js +0 -156
  199. package/docs/src/pages/meta.js +0 -193
  200. package/docs/src/pages/mutations.js +0 -107
  201. package/docs/src/pages/navigation.js +0 -85
  202. package/docs/src/pages/performance.js +0 -157
  203. package/docs/src/pages/persist.js +0 -89
  204. package/docs/src/pages/project-structure.js +0 -91
  205. package/docs/src/pages/prompt-examples.js +0 -186
  206. package/docs/src/pages/raw-responses.js +0 -122
  207. package/docs/src/pages/routing.js +0 -120
  208. package/docs/src/pages/server-api.js +0 -291
  209. package/docs/src/pages/server-data.js +0 -203
  210. package/docs/src/pages/slash-commands.js +0 -55
  211. package/docs/src/pages/spec.js +0 -207
  212. package/docs/src/pages/state.js +0 -102
  213. package/docs/src/pages/store.js +0 -203
  214. package/docs/src/pages/streaming.js +0 -107
  215. package/docs/src/pages/stripe.js +0 -194
  216. package/docs/src/pages/supabase.js +0 -324
  217. package/docs/src/pages/templates/andypixel.js +0 -260
  218. package/docs/src/pages/templates/blog-post.js +0 -226
  219. package/docs/src/pages/templates/bookworms.js +0 -227
  220. package/docs/src/pages/templates/coutumes.js +0 -237
  221. package/docs/src/pages/templates/journey.js +0 -186
  222. package/docs/src/pages/templates/mobile-app.js +0 -371
  223. package/docs/src/pages/templates/retrowheels.js +0 -355
  224. package/docs/src/pages/templates/shop.js +0 -268
  225. package/docs/src/pages/templates/sparkys.js +0 -264
  226. package/docs/src/pages/templates/suzukibento.js +0 -200
  227. package/docs/src/pages/templates/swish.js +0 -313
  228. package/docs/src/pages/templates.js +0 -534
  229. package/docs/src/pages/testing.js +0 -199
  230. package/docs/src/pages/validation.js +0 -138
  231. package/examples/.claude/commands/pulse-build.md +0 -7
  232. package/examples/.claude/commands/pulse-dev.md +0 -7
  233. package/examples/.claude/commands/pulse-start.md +0 -9
  234. package/examples/.claude/commands/pulse-stop.md +0 -5
  235. package/examples/.claude/commands/verify.md +0 -84
  236. package/examples/.claude/coverage-check.js +0 -196
  237. package/examples/.claude/pulse-checklist.md +0 -189
  238. package/examples/andypixel.css +0 -237
  239. package/examples/andypixel.js +0 -258
  240. package/examples/bookworms.css +0 -422
  241. package/examples/bookworms.js +0 -225
  242. package/examples/contact.js +0 -166
  243. package/examples/counter.js +0 -94
  244. package/examples/dev.server.js +0 -110
  245. package/examples/examples.test.js +0 -394
  246. package/examples/journey.css +0 -528
  247. package/examples/journey.js +0 -186
  248. package/examples/pricing.js +0 -262
  249. package/examples/products.js +0 -190
  250. package/examples/public/.pulse-ui-version +0 -1
  251. package/examples/public/pulse-ui.css +0 -3028
  252. package/examples/public/pulse-ui.js +0 -257
  253. package/examples/quiz.js +0 -208
  254. package/examples/retrowheels.css +0 -425
  255. package/examples/retrowheels.js +0 -353
  256. package/examples/shared.js +0 -84
  257. package/examples/suzukibento.css +0 -513
  258. package/examples/suzukibento.js +0 -200
  259. package/examples/swish.css +0 -394
  260. package/examples/swish.js +0 -311
  261. package/examples/todos.js +0 -162
  262. package/src/ui/fieldset.js +0 -37
  263. package/src/ui/phone-frame.js +0 -40
  264. package/src/ui/search.js +0 -78
  265. package/src/ui/segmented.js +0 -50
  266. package/src/ui/tooltip.js +0 -28
@@ -1,269 +0,0 @@
1
- /*
2
- * shop.css — Template: Shop / Product Page
3
- * Theme tokens + layout styles for the Tech Stuff Inc. product page template.
4
- */
5
-
6
- /* ── Theme tokens ─────────────────────────────────────────────────────────── */
7
-
8
- [data-theme="light"] {
9
- --accent: #1D4ED8;
10
- --ui-color-muted: #374151;
11
- --ui-surface: #F5F5F5;
12
- --cart-bubble-text: #ffffff;
13
- }
14
-
15
- /* ── Base ─────────────────────────────────────────────────────────────────── */
16
-
17
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
18
-
19
- body {
20
- font-family: var(--ui-font, system-ui, sans-serif);
21
- line-height: 1.6;
22
- background: var(--ui-bg);
23
- }
24
-
25
- #pulse-root {
26
- max-width: 100%;
27
- overflow-x: hidden;
28
- }
29
-
30
- /* Constrain content to match nav width (1100px) */
31
- .page-body {
32
- max-width: 1100px;
33
- margin-left: auto;
34
- margin-right: auto;
35
- width: 100%;
36
- }
37
-
38
- /* ── Product display ──────────────────────────────────────────────────────── */
39
-
40
- .product-display {
41
- padding: var(--ui-space-16) var(--ui-space-6) var(--ui-space-8);
42
- }
43
-
44
- .product-display .product-display-title {
45
- font-size: clamp(3rem, 10vw, 8rem);
46
- line-height: 1;
47
- letter-spacing: -0.04em;
48
- font-weight: 700;
49
- color: var(--ui-text);
50
- }
51
-
52
- /* Section eyebrow + rule — replaces the removed sectionLabel() component */
53
- .shop-section-label {
54
- margin-bottom: var(--ui-space-6);
55
- }
56
- .shop-section-label-eyebrow {
57
- font-size: var(--ui-text-sm);
58
- letter-spacing: 0.1em;
59
- text-transform: uppercase;
60
- font-weight: 600;
61
- color: var(--ui-color-muted);
62
- margin-bottom: var(--ui-space-2);
63
- }
64
- .shop-section-label-heading {
65
- margin-bottom: var(--ui-space-3);
66
- }
67
- .shop-section-label-rule {
68
- border: none;
69
- border-top: 1px solid var(--ui-border);
70
- }
71
-
72
- /* End-of-page metadata — replaces the removed colophon() component */
73
- .shop-colophon {
74
- padding: var(--ui-space-8) var(--ui-space-6);
75
- text-align: center;
76
- border-top: 1px solid var(--ui-border);
77
- }
78
- .shop-colophon-inner {
79
- font-size: var(--ui-text-sm);
80
- color: var(--ui-color-muted);
81
- }
82
- .shop-colophon-inner a {
83
- color: inherit;
84
- }
85
-
86
- .product-display .product-tagline {
87
- margin-top: var(--ui-space-4);
88
- font-size: var(--ui-text-xl);
89
- color: var(--ui-color-muted);
90
- max-width: 48ch;
91
- }
92
-
93
- .product-display .product-meta-row {
94
- margin-top: var(--ui-space-6);
95
- display: flex;
96
- align-items: center;
97
- gap: var(--ui-space-4);
98
- flex-wrap: wrap;
99
- }
100
-
101
- /* ── Product photo ────────────────────────────────────────────────────────── */
102
-
103
- .product-photo {
104
- width: 100%;
105
- max-height: 70vh;
106
- object-fit: cover;
107
- display: block;
108
- }
109
-
110
- /* ── Purchase section ─────────────────────────────────────────────────────── */
111
-
112
- .product-purchase {
113
- padding: var(--ui-space-10) var(--ui-space-6);
114
- border-bottom: 1px solid var(--ui-border);
115
- }
116
-
117
- .product-price {
118
- font-size: var(--ui-text-4xl);
119
- font-weight: 700;
120
- letter-spacing: -0.02em;
121
- color: var(--ui-text);
122
- line-height: 1;
123
- margin-bottom: var(--ui-space-6);
124
- }
125
-
126
- .qty-control {
127
- display: flex;
128
- align-items: center;
129
- gap: var(--ui-space-3);
130
- margin-bottom: var(--ui-space-6);
131
- }
132
-
133
- .qty-value {
134
- font-size: var(--ui-text-lg);
135
- font-weight: 600;
136
- min-width: 2ch;
137
- text-align: center;
138
- }
139
-
140
- .cart-actions {
141
- display: flex;
142
- gap: var(--ui-space-3);
143
- flex-wrap: wrap;
144
- align-items: center;
145
- margin-bottom: var(--ui-space-4);
146
- }
147
-
148
- .added-confirm {
149
- font-size: var(--ui-text-sm);
150
- color: var(--ui-color-muted);
151
- }
152
-
153
- /* ── Specs section ────────────────────────────────────────────────────────── */
154
-
155
- .product-specs {
156
- padding: var(--ui-space-10) var(--ui-space-6);
157
- border-bottom: 1px solid var(--ui-border);
158
- }
159
-
160
- .spec-grid {
161
- display: grid;
162
- grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
163
- gap: var(--ui-space-6);
164
- margin-top: var(--ui-space-6);
165
- }
166
-
167
- .spec-item {
168
- display: flex;
169
- flex-direction: column;
170
- gap: var(--ui-space-1);
171
- }
172
-
173
- .spec-label {
174
- font-size: var(--ui-text-xs);
175
- text-transform: uppercase;
176
- letter-spacing: 0.08em;
177
- color: var(--ui-color-muted);
178
- font-weight: 600;
179
- }
180
-
181
- .spec-value {
182
- font-size: var(--ui-text-base);
183
- font-weight: 500;
184
- color: var(--ui-text);
185
- }
186
-
187
- /* ── Stats section ────────────────────────────────────────────────────────── */
188
-
189
- .product-stats {
190
- padding: var(--ui-space-10) var(--ui-space-6);
191
- }
192
-
193
- .product-stats-grid {
194
- margin-top: var(--ui-space-6);
195
- }
196
-
197
- /* ── Qty buttons — icon only, hide text span visually ─────────────────────── */
198
-
199
- .qty-btn > span:not(.ui-btn-icon) {
200
- position: absolute;
201
- width: 1px;
202
- height: 1px;
203
- padding: 0;
204
- margin: -1px;
205
- overflow: hidden;
206
- clip: rect(0,0,0,0);
207
- white-space: nowrap;
208
- border: 0;
209
- }
210
-
211
- /* ── Nav cart trigger button ──────────────────────────────────────────────── */
212
-
213
- .cart-trigger {
214
- position: relative;
215
- display: inline-flex;
216
- align-items: center;
217
- justify-content: center;
218
- background: none;
219
- border: none;
220
- cursor: pointer;
221
- padding: var(--ui-space-2);
222
- color: var(--ui-text);
223
- border-radius: var(--ui-radius);
224
- }
225
-
226
- .cart-trigger:hover { color: var(--ui-accent); }
227
-
228
- .cart-bubble {
229
- position: absolute;
230
- top: -2px;
231
- right: -4px;
232
- background: var(--ui-accent);
233
- color: var(--cart-bubble-text);
234
- font-size: 10px;
235
- font-weight: 700;
236
- line-height: 1;
237
- min-width: 16px;
238
- height: 16px;
239
- padding: 0 3px;
240
- border-radius: 999px;
241
- display: flex;
242
- align-items: center;
243
- justify-content: center;
244
- }
245
-
246
- /* ── Cart modal table ─────────────────────────────────────────────────────── */
247
-
248
- .cart-table {
249
- width: 100%;
250
- margin-top: var(--ui-space-2);
251
- }
252
-
253
- .cart-col-num {
254
- text-align: right;
255
- white-space: nowrap;
256
- }
257
-
258
- .cart-total-row td {
259
- padding-top: var(--ui-space-3);
260
- border-top: 2px solid var(--ui-border);
261
- }
262
-
263
- /* ── View error fallback ──────────────────────────────────────────────────── */
264
-
265
- .view-error {
266
- padding: var(--ui-space-16) var(--ui-space-6);
267
- text-align: center;
268
- color: var(--ui-color-muted);
269
- }
@@ -1,382 +0,0 @@
1
- /*
2
- * sparkys.css — Sparkys Electrical template styles
3
- * Navy + amber. Light theme.
4
- */
5
-
6
- /* ── Palette tokens ─────────────────────────────────────────────────────── */
7
- [data-theme="light"] {
8
- --ui-bg: #f7f9fc;
9
- --ui-surface: #ffffff;
10
- --ui-surface-2: #eef2f8;
11
- --ui-border: #d6deea;
12
- --ui-text: #0f172a;
13
- --ui-muted: #475569;
14
- --ui-accent: #0a3160;
15
- --ui-accent-hover: #082748;
16
- --ui-accent-dim: #e3ecf7;
17
- --ui-accent-text: #ffffff;
18
-
19
- --brand-amber: #b56f00;
20
- --brand-amber-soft: #fff4dd;
21
- --brand-amber-strong: #f4a721;
22
- --brand-navy-deep: #062247;
23
- --brand-white: #ffffff;
24
- --brand-mist: #cfd8e6;
25
- --brand-overlay-12: rgba(255, 255, 255, 0.12);
26
- }
27
-
28
- /* ── Base ───────────────────────────────────────────────────────────────── */
29
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
30
-
31
- body {
32
- font-family: var(--ui-font, system-ui, sans-serif);
33
- line-height: 1.6;
34
- }
35
-
36
- .brand-mark {
37
- font-weight: 800;
38
- letter-spacing: -0.01em;
39
- font-size: var(--ui-text-lg);
40
- color: var(--ui-accent);
41
- }
42
-
43
- /* ── Top utility strip ─────────────────────────────────────────────────── */
44
- /* raw two-column bar — replaces the removed topStrip() component */
45
- .top-strip {
46
- display: flex;
47
- align-items: center;
48
- justify-content: space-between;
49
- gap: var(--ui-space-4);
50
- padding: var(--ui-space-2) var(--ui-space-6);
51
- background: var(--brand-navy-deep);
52
- color: var(--brand-white);
53
- font-size: var(--ui-text-sm);
54
- }
55
- .top-strip a {
56
- color: inherit;
57
- text-decoration: none;
58
- font-weight: 600;
59
- }
60
- .top-strip a:hover { text-decoration: underline; }
61
-
62
- /* ── Hero ──────────────────────────────────────────────────────────────── */
63
- .hero-split {
64
- display: grid;
65
- grid-template-columns: 1.2fr 1fr;
66
- min-height: 70vh;
67
- background: var(--ui-bg);
68
- }
69
- .hero-split__text {
70
- padding: var(--ui-space-16) var(--ui-space-8);
71
- display: flex;
72
- flex-direction: column;
73
- justify-content: center;
74
- max-width: 640px;
75
- margin-left: auto;
76
- width: 100%;
77
- }
78
- .hero-split__eyebrow {
79
- font-size: var(--ui-text-sm);
80
- letter-spacing: 0.15em;
81
- text-transform: uppercase;
82
- font-weight: 700;
83
- color: var(--ui-accent);
84
- margin-bottom: var(--ui-space-4);
85
- }
86
- .hero-split__title {
87
- font-size: clamp(2.25rem, 5vw, 3.75rem);
88
- font-weight: 800;
89
- line-height: 1.05;
90
- letter-spacing: -0.02em;
91
- color: var(--ui-text);
92
- margin-bottom: var(--ui-space-5);
93
- }
94
- .hero-split__subtitle {
95
- font-size: var(--ui-text-lg);
96
- color: var(--ui-muted);
97
- margin-bottom: var(--ui-space-8);
98
- max-width: 52ch;
99
- }
100
- .hero-split__actions {
101
- display: flex;
102
- flex-wrap: wrap;
103
- gap: var(--ui-space-3);
104
- margin-bottom: var(--ui-space-8);
105
- }
106
- .hero-split__trust {
107
- display: flex;
108
- flex-wrap: wrap;
109
- gap: var(--ui-space-5);
110
- font-size: var(--ui-text-sm);
111
- color: var(--ui-muted);
112
- font-weight: 600;
113
- }
114
- /* trust-inline list — replaces the removed trustList() component */
115
- .trust-inline {
116
- display: flex;
117
- flex-wrap: wrap;
118
- gap: var(--ui-space-5);
119
- list-style: none;
120
- }
121
- .trust-inline__item {
122
- display: flex;
123
- align-items: center;
124
- gap: var(--ui-space-2);
125
- font-weight: 600;
126
- }
127
- .trust-inline__icon {
128
- display: inline-flex;
129
- color: var(--brand-amber);
130
- }
131
-
132
- .hero-split__panel {
133
- background: linear-gradient(160deg, var(--ui-accent) 0%, var(--brand-navy-deep) 100%);
134
- color: var(--brand-white);
135
- padding: var(--ui-space-12) var(--ui-space-8);
136
- display: flex;
137
- flex-direction: column;
138
- justify-content: center;
139
- gap: var(--ui-space-8);
140
- position: relative;
141
- overflow: hidden;
142
- }
143
- .hero-split__panel::before {
144
- content: "";
145
- position: absolute;
146
- inset: auto -40px -40px auto;
147
- width: 220px;
148
- height: 220px;
149
- background: var(--brand-amber-strong);
150
- opacity: 0.18;
151
- border-radius: 50%;
152
- }
153
- .hero-split__panel-title {
154
- font-size: var(--ui-text-sm);
155
- letter-spacing: 0.15em;
156
- text-transform: uppercase;
157
- font-weight: 700;
158
- color: var(--brand-amber-strong);
159
- position: relative;
160
- }
161
- .hero-stats {
162
- display: grid;
163
- grid-template-columns: 1fr 1fr;
164
- gap: var(--ui-space-6);
165
- position: relative;
166
- }
167
- .hero-stat__value {
168
- font-size: clamp(1.875rem, 3.5vw, 2.5rem);
169
- font-weight: 800;
170
- letter-spacing: -0.02em;
171
- color: var(--brand-white);
172
- line-height: 1;
173
- margin-bottom: var(--ui-space-2);
174
- }
175
- .hero-stat__label {
176
- font-size: var(--ui-text-sm);
177
- color: var(--brand-mist);
178
- }
179
- .hero-stat__rating {
180
- display: inline-flex;
181
- align-items: center;
182
- gap: var(--ui-space-1);
183
- color: var(--brand-amber-strong);
184
- }
185
-
186
- /* ── Section base ─────────────────────────────────────────────────────── */
187
- .section {
188
- padding: var(--ui-space-16) var(--ui-space-6);
189
- }
190
- .section--alt { background: var(--ui-surface-2); }
191
- .section__inner {
192
- max-width: 1200px;
193
- margin: 0 auto;
194
- }
195
- .section__head {
196
- max-width: 640px;
197
- margin: 0 auto var(--ui-space-12);
198
- text-align: center;
199
- }
200
- .section__eyebrow {
201
- font-size: var(--ui-text-sm);
202
- letter-spacing: 0.15em;
203
- text-transform: uppercase;
204
- font-weight: 700;
205
- color: var(--ui-accent);
206
- margin-bottom: var(--ui-space-3);
207
- }
208
- .section__title {
209
- font-size: clamp(1.75rem, 3.5vw, 2.5rem);
210
- font-weight: 800;
211
- letter-spacing: -0.02em;
212
- color: var(--ui-text);
213
- margin-bottom: var(--ui-space-4);
214
- }
215
- .section__subtitle {
216
- font-size: var(--ui-text-lg);
217
- color: var(--ui-muted);
218
- }
219
-
220
- /* ── Services grid — card() component with a bordered service-card look ─── */
221
- .service-card {
222
- border: 1px solid var(--ui-border);
223
- box-shadow: none;
224
- }
225
- .service-card .ui-service-card-icon {
226
- width: 44px;
227
- height: 44px;
228
- border-radius: var(--ui-radius-md);
229
- background: var(--ui-accent-dim);
230
- color: var(--ui-accent);
231
- display: grid;
232
- place-items: center;
233
- margin-bottom: var(--ui-space-4);
234
- }
235
- .service-card .ui-service-card-title {
236
- font-size: var(--ui-text-xl);
237
- font-weight: 700;
238
- margin-bottom: var(--ui-space-2);
239
- }
240
- .service-card .ui-service-card-desc {
241
- font-size: var(--ui-text-base);
242
- color: var(--ui-muted);
243
- }
244
-
245
- /* ── Why grid ──────────────────────────────────────────────────────────── */
246
- .why {
247
- display: grid;
248
- grid-template-columns: repeat(3, 1fr);
249
- gap: var(--ui-space-6);
250
- }
251
- .why__item {
252
- padding: var(--ui-space-6);
253
- border-left: 3px solid var(--brand-amber-strong);
254
- background: var(--ui-surface);
255
- }
256
- .why__title {
257
- font-size: var(--ui-text-xl);
258
- font-weight: 700;
259
- color: var(--ui-text);
260
- margin-bottom: var(--ui-space-2);
261
- }
262
- .why__body {
263
- color: var(--ui-muted);
264
- }
265
-
266
- /* ── Testimonial ───────────────────────────────────────────────────────── */
267
- .quote {
268
- max-width: 820px;
269
- margin: 0 auto;
270
- text-align: center;
271
- }
272
- .quote__mark {
273
- font-size: var(--ui-text-4xl);
274
- color: var(--brand-amber-strong);
275
- font-weight: 800;
276
- line-height: 1;
277
- margin-bottom: var(--ui-space-3);
278
- }
279
- .quote__text {
280
- font-size: clamp(1.25rem, 2.5vw, 1.625rem);
281
- font-weight: 500;
282
- color: var(--ui-text);
283
- line-height: 1.45;
284
- margin-bottom: var(--ui-space-6);
285
- }
286
- .quote__cite {
287
- color: var(--ui-muted);
288
- font-size: var(--ui-text-sm);
289
- font-weight: 600;
290
- letter-spacing: 0.05em;
291
- text-transform: uppercase;
292
- }
293
-
294
- /* ── Contact strip ─────────────────────────────────────────────────────── */
295
- .contact-strip {
296
- background: var(--ui-accent);
297
- color: var(--brand-white);
298
- padding: var(--ui-space-12) var(--ui-space-6);
299
- }
300
- .contact-strip__inner {
301
- max-width: 1200px;
302
- margin: 0 auto;
303
- display: grid;
304
- grid-template-columns: 1.4fr 1fr;
305
- gap: var(--ui-space-10);
306
- align-items: center;
307
- }
308
- .contact-strip__title {
309
- font-size: clamp(1.75rem, 3.5vw, 2.5rem);
310
- font-weight: 800;
311
- letter-spacing: -0.02em;
312
- margin-bottom: var(--ui-space-3);
313
- color: var(--brand-white);
314
- }
315
- .contact-strip__lead {
316
- font-size: var(--ui-text-lg);
317
- color: var(--brand-mist);
318
- }
319
- .contact-strip__details {
320
- display: flex;
321
- flex-direction: column;
322
- gap: var(--ui-space-3);
323
- }
324
- /* contact-inline list — replaces the removed contactRow() component */
325
- .contact-inline {
326
- display: flex;
327
- flex-direction: column;
328
- gap: var(--ui-space-3);
329
- list-style: none;
330
- }
331
- .contact-inline__item {
332
- display: flex;
333
- align-items: center;
334
- gap: var(--ui-space-3);
335
- color: var(--brand-white);
336
- font-weight: 600;
337
- font-size: var(--ui-text-lg);
338
- }
339
- .contact-inline__item a { color: var(--brand-white); text-decoration: none; }
340
- .contact-inline__item a:hover { color: var(--brand-amber-strong); }
341
- .contact-inline__icon {
342
- width: 36px;
343
- height: 36px;
344
- border-radius: 50%;
345
- background: var(--brand-overlay-12);
346
- display: grid;
347
- place-items: center;
348
- line-height: 0;
349
- color: var(--brand-white);
350
- }
351
-
352
- /* ── Footer overrides ──────────────────────────────────────────────────── */
353
- .site-footer__brand {
354
- color: var(--brand-white);
355
- font-weight: 800;
356
- font-size: var(--ui-text-lg);
357
- letter-spacing: -0.01em;
358
- }
359
- .ui-footer .site-footer__brand { color: var(--brand-white); }
360
- .ui-footer {
361
- background: var(--brand-navy-deep);
362
- color: var(--brand-mist);
363
- }
364
- .ui-footer a { color: var(--brand-mist); }
365
- .ui-footer a:hover { color: var(--brand-white); }
366
- .ui-footer .ui-footer-legal,
367
- .ui-footer p { color: var(--brand-mist); }
368
-
369
- /* ── Responsive ───────────────────────────────────────────────────────── */
370
- @media (max-width: 900px) {
371
- .hero-split { grid-template-columns: 1fr; min-height: auto; }
372
- .hero-split__text { padding: var(--ui-space-12) var(--ui-space-6); margin: 0 auto; }
373
- .hero-split__panel { padding: var(--ui-space-10) var(--ui-space-6); }
374
- .services { grid-template-columns: repeat(2, 1fr); }
375
- .why { grid-template-columns: 1fr; }
376
- .contact-strip__inner { grid-template-columns: 1fr; }
377
- }
378
- @media (max-width: 600px) {
379
- .services { grid-template-columns: 1fr; }
380
- .hero-stats { grid-template-columns: 1fr; }
381
- .section { padding: var(--ui-space-12) var(--ui-space-5); }
382
- }