@invisibleloop/pulse 0.20.11 → 0.20.19

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,561 +0,0 @@
1
- /* ============================================================
2
- Coutumes Recreation CSS
3
- Substitute fonts: Bebas Neue (→ Plaak 3), Cormorant Garamond (→ Exposure Regular)
4
- Brand amber: #F9AF26 | Text: #000 | Background: #fff
5
- ============================================================ */
6
-
7
- :root {
8
- --coutumes-amber: #F9AF26;
9
- --coutumes-black: #000000;
10
- --coutumes-white: #ffffff;
11
- --coutumes-font-display: 'Bebas Neue', sans-serif;
12
- --coutumes-font-body: 'Cormorant Garamond', serif;
13
- --coutumes-font-ui: 'Barlow', system-ui, sans-serif;
14
- }
15
-
16
- .coutumes-sr-only {
17
- position: absolute;
18
- width: 1px;
19
- height: 1px;
20
- padding: 0;
21
- margin: -1px;
22
- overflow: hidden;
23
- clip: rect(0, 0, 0, 0);
24
- white-space: nowrap;
25
- border: 0;
26
- }
27
-
28
- /* Base reset for this page */
29
- .coutumes-hero,
30
- .coutumes-nav,
31
- .coutumes-editorial-quote,
32
- .coutumes-product-grid,
33
- .coutumes-split-images,
34
- .coutumes-statement,
35
- .coutumes-portrait,
36
- .coutumes-footer,
37
- .coutumes-announce {
38
- font-family: var(--coutumes-font-body);
39
- color: var(--coutumes-black);
40
- background: var(--coutumes-white);
41
- }
42
-
43
- /* ── Announcement bar ── */
44
- .coutumes-announce {
45
- position: fixed;
46
- bottom: 0;
47
- left: 0;
48
- right: 0;
49
- z-index: 100;
50
- background: var(--coutumes-white);
51
- border-top: 1px solid #e5e5e5;
52
- padding: 10px 24px;
53
- display: flex;
54
- align-items: center;
55
- justify-content: center;
56
- font-family: var(--coutumes-font-ui);
57
- font-size: 0.6875rem;
58
- letter-spacing: 0.12em;
59
- text-transform: uppercase;
60
- }
61
-
62
- .coutumes-announce-close {
63
- position: absolute;
64
- right: 16px;
65
- background: none;
66
- border: none;
67
- cursor: pointer;
68
- font-size: 0.75rem;
69
- color: var(--coutumes-black);
70
- padding: 4px;
71
- }
72
-
73
- /* ── Nav ── */
74
- .coutumes-nav {
75
- position: sticky;
76
- top: 0;
77
- z-index: 50;
78
- background: var(--coutumes-white);
79
- border-bottom: none;
80
- display: flex;
81
- align-items: center;
82
- justify-content: space-between;
83
- padding: 0 24px;
84
- height: 60px;
85
- font-family: var(--coutumes-font-ui);
86
- font-size: 0.8125rem;
87
- }
88
-
89
- .coutumes-nav-left {
90
- display: flex;
91
- align-items: center;
92
- gap: 32px;
93
- }
94
-
95
- .coutumes-logo {
96
- font-family: var(--coutumes-font-display);
97
- font-size: 1.125rem;
98
- letter-spacing: 0.05em;
99
- color: var(--coutumes-black);
100
- text-decoration: none;
101
- }
102
-
103
- .coutumes-nav-links {
104
- display: flex;
105
- gap: 28px;
106
- list-style: none;
107
- margin: 0;
108
- padding: 0;
109
- }
110
-
111
- .coutumes-nav-links a,
112
- .coutumes-nav-right a {
113
- color: var(--coutumes-black);
114
- text-decoration: none;
115
- font-size: 0.8125rem;
116
- }
117
-
118
- .coutumes-nav-links a:hover,
119
- .coutumes-nav-right a:hover {
120
- opacity: 0.6;
121
- }
122
-
123
- .coutumes-nav-right {
124
- display: flex;
125
- align-items: center;
126
- gap: 24px;
127
- }
128
-
129
- /* ── Hero ── */
130
- .coutumes-hero {
131
- position: relative;
132
- overflow: hidden;
133
- min-height: 100svh;
134
- }
135
-
136
- .coutumes-hero-images {
137
- display: grid;
138
- grid-template-columns: 1fr 1fr;
139
- height: 100svh;
140
- min-height: 600px;
141
- }
142
-
143
- .coutumes-hero-img {
144
- overflow: hidden;
145
- }
146
-
147
- .coutumes-hero-img img {
148
- width: 100%;
149
- height: 100%;
150
- object-fit: cover;
151
- display: block;
152
- }
153
-
154
- /* Overlapping amber display type */
155
- .coutumes-hero-text {
156
- position: absolute;
157
- inset: 0;
158
- display: flex;
159
- flex-direction: column;
160
- justify-content: center;
161
- padding: 0;
162
- pointer-events: none;
163
- z-index: 10;
164
- }
165
-
166
- .coutumes-hero-text span {
167
- display: block;
168
- font-family: var(--coutumes-font-display);
169
- font-size: clamp(5rem, 14vw, 11rem);
170
- line-height: 0.92;
171
- letter-spacing: -0.02em;
172
- color: var(--coutumes-amber);
173
- padding: 0 2vw;
174
- /* Mix-blend-mode makes it appear to interact with the photos like the original */
175
- mix-blend-mode: multiply;
176
- }
177
-
178
- /* ── Editorial quote ── */
179
- .coutumes-editorial-quote {
180
- padding: 80px 24px;
181
- text-align: center;
182
- }
183
-
184
- .coutumes-editorial-quote-inner {
185
- max-width: 680px;
186
- margin: 0 auto;
187
- }
188
-
189
- .coutumes-quote-text {
190
- font-family: var(--coutumes-font-body);
191
- font-size: clamp(1.5rem, 3.5vw, 2.25rem);
192
- line-height: 1.4;
193
- font-weight: 400;
194
- margin: 0 0 24px;
195
- }
196
-
197
- .coutumes-quote-caption {
198
- font-family: var(--coutumes-font-body);
199
- font-size: 0.9375rem;
200
- font-style: italic;
201
- color: #666;
202
- margin: 0;
203
- }
204
-
205
- /* ── Product grid ── */
206
- .coutumes-product-grid {
207
- display: grid;
208
- grid-template-columns: repeat(3, 1fr);
209
- gap: 0;
210
- }
211
-
212
- .coutumes-product-card {
213
- position: relative;
214
- display: block;
215
- text-decoration: none;
216
- color: var(--coutumes-black);
217
- }
218
-
219
- .coutumes-product-card img {
220
- width: 100%;
221
- aspect-ratio: 4/5;
222
- object-fit: cover;
223
- display: block;
224
- overflow: hidden;
225
- transition: transform 0.5s ease;
226
- }
227
-
228
- .coutumes-product-card:hover img {
229
- transform: scale(1.03);
230
- }
231
-
232
- .coutumes-product-badge {
233
- position: absolute;
234
- top: 12px;
235
- left: 12px;
236
- background: var(--coutumes-white);
237
- color: var(--coutumes-black);
238
- font-family: var(--coutumes-font-ui);
239
- font-size: 0.625rem;
240
- letter-spacing: 0.08em;
241
- padding: 3px 7px;
242
- z-index: 5;
243
- }
244
-
245
- /* ── 50/50 split images ── */
246
- .coutumes-split-images {
247
- display: grid;
248
- grid-template-columns: 1fr 1fr;
249
- height: 70vw;
250
- max-height: 800px;
251
- }
252
-
253
- .coutumes-split-img {
254
- overflow: hidden;
255
- }
256
-
257
- .coutumes-split-img img {
258
- width: 100%;
259
- height: 100%;
260
- object-fit: cover;
261
- display: block;
262
- }
263
-
264
- /* ── Large editorial statement ── */
265
- .coutumes-statement {
266
- padding: 100px 24px;
267
- text-align: center;
268
- }
269
-
270
- .coutumes-statement-inner {
271
- max-width: 860px;
272
- margin: 0 auto;
273
- }
274
-
275
- .coutumes-statement-inner p {
276
- font-family: var(--coutumes-font-body);
277
- font-size: clamp(1.75rem, 4.5vw, 3rem);
278
- line-height: 1.25;
279
- font-weight: 400;
280
- margin: 0;
281
- }
282
-
283
- /* ── Portrait ── */
284
- .coutumes-portrait {
285
- display: flex;
286
- justify-content: center;
287
- padding: 40px 0 80px;
288
- }
289
-
290
- .coutumes-portrait img {
291
- width: min(500px, 80vw);
292
- height: auto;
293
- display: block;
294
- }
295
-
296
- /* ── Footer ── */
297
- .coutumes-footer {
298
- background: var(--coutumes-amber);
299
- padding: 60px 40px 0;
300
- }
301
-
302
- .coutumes-footer-top {
303
- display: grid;
304
- grid-template-columns: 1fr 1.5fr;
305
- gap: 40px;
306
- margin-bottom: 60px;
307
- align-items: start;
308
- }
309
-
310
- .coutumes-footer-bird svg {
311
- width: 120px;
312
- height: 80px;
313
- opacity: 0.4;
314
- }
315
-
316
- .coutumes-footer-subscribe-label {
317
- font-family: var(--coutumes-font-ui);
318
- font-size: 0.6875rem;
319
- letter-spacing: 0.12em;
320
- text-transform: uppercase;
321
- margin: 0 0 16px;
322
- }
323
-
324
- .coutumes-footer-form {
325
- display: flex;
326
- align-items: center;
327
- border-bottom: 1px solid var(--coutumes-black);
328
- margin-bottom: 12px;
329
- }
330
-
331
- .coutumes-footer-form input {
332
- flex: 1;
333
- background: none;
334
- border: none;
335
- outline: none;
336
- font-family: var(--coutumes-font-body);
337
- font-size: 1.0625rem;
338
- padding: 8px 0;
339
- color: var(--coutumes-black);
340
- }
341
-
342
- .coutumes-footer-form input::placeholder {
343
- color: rgba(0,0,0,0.5);
344
- }
345
-
346
- .coutumes-footer-form button {
347
- background: none;
348
- border: none;
349
- cursor: pointer;
350
- font-family: var(--coutumes-font-ui);
351
- font-size: 0.6875rem;
352
- letter-spacing: 0.08em;
353
- color: var(--coutumes-black);
354
- padding: 8px 0 8px 16px;
355
- white-space: nowrap;
356
- }
357
-
358
- .coutumes-footer-legal {
359
- font-family: var(--coutumes-font-ui);
360
- font-size: 0.6875rem;
361
- line-height: 1.5;
362
- opacity: 0.7;
363
- margin: 0;
364
- }
365
-
366
- .coutumes-footer-legal a {
367
- color: var(--coutumes-black);
368
- }
369
-
370
- /* Footer link columns */
371
- .coutumes-footer-links {
372
- display: grid;
373
- grid-template-columns: repeat(3, 1fr);
374
- gap: 24px;
375
- padding-bottom: 40px;
376
- }
377
-
378
- .coutumes-footer-col-title {
379
- font-family: var(--coutumes-font-ui);
380
- font-size: 0.625rem;
381
- letter-spacing: 0.14em;
382
- text-transform: uppercase;
383
- margin: 0 0 16px;
384
- font-weight: 500;
385
- }
386
-
387
- .coutumes-footer-col ul {
388
- list-style: none;
389
- margin: 0;
390
- padding: 0;
391
- display: flex;
392
- flex-direction: column;
393
- gap: 8px;
394
- }
395
-
396
- .coutumes-footer-col a {
397
- font-family: var(--coutumes-font-body);
398
- font-size: 0.9375rem;
399
- color: var(--coutumes-black);
400
- text-decoration: none;
401
- }
402
-
403
- .coutumes-footer-col a:hover {
404
- opacity: 0.6;
405
- }
406
-
407
- /* Giant wordmark */
408
- .coutumes-footer-wordmark {
409
- font-family: var(--coutumes-font-display);
410
- font-size: clamp(5rem, 18vw, 14rem);
411
- line-height: 0.85;
412
- letter-spacing: -0.02em;
413
- color: var(--coutumes-black);
414
- margin: 0 -40px;
415
- overflow: hidden;
416
- }
417
-
418
- /* Legal row */
419
- .coutumes-footer-legal-row {
420
- display: flex;
421
- gap: 24px;
422
- align-items: center;
423
- padding: 16px 0 24px;
424
- font-family: var(--coutumes-font-ui);
425
- font-size: 0.6875rem;
426
- opacity: 0.7;
427
- flex-wrap: wrap;
428
- }
429
-
430
- .coutumes-footer-legal-row a {
431
- color: var(--coutumes-black);
432
- text-decoration: none;
433
- }
434
-
435
- /* Padding utilities (if pulse-ui.css not loaded) */
436
- .u-py-12 { padding-top: 3rem; padding-bottom: 3rem; }
437
- .u-py-16 { padding-top: 4rem; padding-bottom: 4rem; }
438
- .u-sr-only {
439
- position: absolute;
440
- width: 1px; height: 1px;
441
- padding: 0; margin: -1px;
442
- overflow: hidden;
443
- clip: rect(0,0,0,0);
444
- white-space: nowrap;
445
- border: 0;
446
- }
447
-
448
- /* ── Responsive ── */
449
- @media (max-width: 768px) {
450
- .coutumes-nav-links { display: none; }
451
- .coutumes-hero-text span { font-size: clamp(3rem, 18vw, 6rem); }
452
- .coutumes-product-grid { grid-template-columns: 1fr; }
453
- .coutumes-split-images { grid-template-columns: 1fr; height: auto; }
454
- .coutumes-split-img { aspect-ratio: 4/3; }
455
- .coutumes-footer-top { grid-template-columns: 1fr; }
456
- .coutumes-footer-links { grid-template-columns: 1fr 1fr; }
457
- }
458
-
459
- /* Hero overlay — sans-serif display font, top-aligned so text clips at top */
460
- .coutumes-hero-text {
461
- justify-content: flex-start;
462
- padding-top: 0;
463
- bottom: -2em; /* extend past hero bottom → clips there */
464
- mix-blend-mode: normal;
465
- }
466
- .coutumes-hero-text span {
467
- font-family: var(--coutumes-font-display);
468
- font-weight: 400;
469
- font-size: clamp(5rem, 14vw, 18rem);
470
- }
471
- /* Bigger gap between SILVER LANDS and CAPSULE */
472
- .coutumes-hero-text span:nth-child(3) {
473
- margin-top: 1.7em;
474
- }
475
- /* Lock hero images to viewport height (prevents overly tall hero) */
476
- .coutumes-hero-images {
477
- aspect-ratio: unset;
478
- height: 100svh;
479
- }
480
-
481
- /* Pull hero up behind the sticky nav so the text clips at the top */
482
- .coutumes-hero {
483
- margin-top: -40px;
484
- }
485
-
486
- /* Image pair links */
487
- .coutumes-split-images {
488
- background: var(--coutumes-white);
489
- }
490
-
491
- .coutumes-split-col {
492
- display: flex;
493
- flex-direction: column;
494
- }
495
-
496
- .coutumes-split-link {
497
- font-family: var(--coutumes-font-body);
498
- color: var(--coutumes-black);
499
- padding: 0.75rem 0;
500
- display: block;
501
- text-decoration: none;
502
- }
503
-
504
- /* Product grid — name/price below image */
505
- .coutumes-product-caption {
506
- background: var(--coutumes-white);
507
- padding-bottom: 10rem;
508
- padding-top: 1rem;
509
- }
510
- .coutumes-product-name {
511
- font-family: var(--coutumes-font-body);
512
- font-size: 1.0625rem;
513
- color: var(--coutumes-black);
514
- margin: 0;
515
- }
516
- .coutumes-product-price {
517
- font-family: var(--coutumes-font-ui);
518
- font-size: 0.875rem;
519
- color: var(--coutumes-black);
520
- opacity: 0.75;
521
- margin: 0;
522
- }
523
-
524
- /* Editorial quote — non-italic, generous padding, narrow column */
525
- #collection {
526
- background: var(--coutumes-white);
527
- position: relative;
528
- z-index: 1;
529
- }
530
- #collection .ui-pullquote--editorial {
531
- padding: 8rem 1.5rem;
532
- }
533
- #collection .ui-pullquote--editorial .ui-pullquote-text {
534
- font-style: normal;
535
- max-width: 480px;
536
- font-family: var(--coutumes-font-body);
537
- color: var(--coutumes-black);
538
- font-size: clamp(1.5rem, 2.5vw, 1.875rem);
539
- line-height: 1.25;
540
- }
541
- #collection .ui-pullquote--editorial .ui-pullquote-cite {
542
- font-style: italic;
543
- font-family: var(--coutumes-font-body);
544
- font-size: 0.875rem;
545
- color: var(--coutumes-black);
546
- margin-top: 1.5rem;
547
- }
548
-
549
- /* Fix nav — serif font, correct size, no wrapping */
550
- .ui-nav .ui-nav-logo {
551
- color: var(--coutumes-black);
552
- font-family: var(--coutumes-font-display);
553
- }
554
- .ui-nav .ui-nav-link {
555
- color: var(--coutumes-black);
556
- font-family: var(--coutumes-font-body);
557
- font-size: 1.0625rem;
558
- white-space: nowrap;
559
- letter-spacing: 0.02em;
560
- }
561
-