@agent-cms/agentcms 0.0.0-stage → 0.1.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 (84) hide show
  1. package/LICENSE +143 -0
  2. package/README.md +1119 -2
  3. package/changelog.json +31 -0
  4. package/dist/admin/admin-files.json +48 -0
  5. package/dist/admin/assets/CodeEditor-Wx1WlF3h.js +24 -0
  6. package/dist/admin/assets/flexweg-logo-CdtuqAFA.png +0 -0
  7. package/dist/admin/assets/index-DFVZw8E0.js +5460 -0
  8. package/dist/admin/assets/index-DMcGogR2.css +1 -0
  9. package/dist/admin/assets/sql-wasm-Bfkbn6Oa.js +2 -0
  10. package/dist/admin/assets/sql-wasm-C1U8OeUW.wasm +0 -0
  11. package/dist/admin/assets/sql-wasm-V5jTDcrT.js +1 -0
  12. package/dist/admin/config.js +11 -0
  13. package/dist/admin/external.default.json +72 -0
  14. package/dist/admin/index.html +116 -0
  15. package/dist/admin/plugins/core-seo/bundle.js +55 -0
  16. package/dist/admin/plugins/core-seo/manifest.json +7 -0
  17. package/dist/admin/plugins/flexweg-archives/bundle.js +1414 -0
  18. package/dist/admin/plugins/flexweg-archives/manifest.json +7 -0
  19. package/dist/admin/plugins/flexweg-multilang/bundle.js +1187 -0
  20. package/dist/admin/plugins/flexweg-multilang/manifest.json +7 -0
  21. package/dist/admin/plugins/flexweg-rss/bundle.js +1354 -0
  22. package/dist/admin/plugins/flexweg-rss/manifest.json +7 -0
  23. package/dist/admin/plugins/flexweg-search/bundle.js +1243 -0
  24. package/dist/admin/plugins/flexweg-search/manifest.json +7 -0
  25. package/dist/admin/plugins/flexweg-sitemaps/bundle.js +1293 -0
  26. package/dist/admin/plugins/flexweg-sitemaps/manifest.json +7 -0
  27. package/dist/admin/runtime/cms-runtime.js +164 -0
  28. package/dist/admin/runtime/react-dom-client.js +13 -0
  29. package/dist/admin/runtime/react-dom.js +16 -0
  30. package/dist/admin/runtime/react-i18next.js +21 -0
  31. package/dist/admin/runtime/react-jsx-runtime.js +17 -0
  32. package/dist/admin/runtime/react.js +55 -0
  33. package/dist/admin/themes/corporate/bundle.js +14465 -0
  34. package/dist/admin/themes/corporate/manifest.json +7 -0
  35. package/dist/admin/themes/corporate/theme.css +2 -0
  36. package/dist/admin/themes/magazine/bundle.js +10229 -0
  37. package/dist/admin/themes/magazine/manifest.json +7 -0
  38. package/dist/admin/themes/magazine/theme.css +2 -0
  39. package/dist/admin/themes/marketplace-core/bundle.js +11213 -0
  40. package/dist/admin/themes/marketplace-core/manifest.json +7 -0
  41. package/dist/admin/themes/marketplace-core/theme.css +1613 -0
  42. package/dist/admin/themes/portfolio/bundle.js +9195 -0
  43. package/dist/admin/themes/portfolio/manifest.json +7 -0
  44. package/dist/admin/themes/portfolio/theme.css +2 -0
  45. package/dist/admin/themes/storefront/bundle.js +13172 -0
  46. package/dist/admin/themes/storefront/manifest.json +7 -0
  47. package/dist/admin/themes/storefront/theme.css +2 -0
  48. package/dist/agent/agentcms.mjs +1711 -0
  49. package/dist/agent/chunks/hosting-BftlDdsL.mjs +117 -0
  50. package/dist/agent/chunks/index-BG05qslv.mjs +3608 -0
  51. package/dist/agent/chunks/install-DnmgOT3F.mjs +577 -0
  52. package/dist/agent/chunks/plan-BrM8ztEp.mjs +245 -0
  53. package/dist/agent/chunks/registry-C9TSnZ77.mjs +53517 -0
  54. package/dist/agent/chunks/siteAdd-BcXhN9fk.mjs +118 -0
  55. package/dist/agent/chunks/sql-wasm-GjJDiefO.mjs +10 -0
  56. package/dist/agent/chunks/sqljs-DjSCStJ0.mjs +20 -0
  57. package/dist/agent/vendor/sql-wasm.cjs +188 -0
  58. package/dist/theme-assets/corporate-menu.js +266 -0
  59. package/dist/theme-assets/corporate-posts.js +571 -0
  60. package/dist/theme-assets/corporate.css +2 -0
  61. package/dist/theme-assets/default-menu.js +266 -0
  62. package/dist/theme-assets/default-posts.js +378 -0
  63. package/dist/theme-assets/default.css +1 -0
  64. package/dist/theme-assets/magazine-menu.js +227 -0
  65. package/dist/theme-assets/magazine-posts.js +361 -0
  66. package/dist/theme-assets/magazine.css +2 -0
  67. package/dist/theme-assets/portfolio-filters.js +104 -0
  68. package/dist/theme-assets/portfolio-menu.js +240 -0
  69. package/dist/theme-assets/portfolio-posts.js +358 -0
  70. package/dist/theme-assets/portfolio.css +2 -0
  71. package/dist/theme-assets/storefront-catalog.js +504 -0
  72. package/dist/theme-assets/storefront-menu.js +239 -0
  73. package/dist/theme-assets/storefront-posts.js +404 -0
  74. package/dist/theme-assets/storefront.css +2 -0
  75. package/dist/version.json +9 -0
  76. package/package.json +101 -4
  77. package/plugin/.claude-plugin/plugin.json +16 -0
  78. package/plugin/skills/agentcms-install/SKILL.md +110 -0
  79. package/plugin/skills/agentcms-install/references/cloudflare.md +15 -0
  80. package/plugin/skills/agentcms-install/references/flexweg.md +11 -0
  81. package/plugin/skills/agentcms-install/references/github.md +67 -0
  82. package/plugin/skills/agentcms-install/references/gitlab.md +15 -0
  83. package/plugin/skills/agentcms-install/references/s3.md +81 -0
  84. package/plugin/skills/agentcms-manage/SKILL.md +92 -0
@@ -0,0 +1,1613 @@
1
+ /* Marketplace Core — hand-written theme stylesheet (no Tailwind
2
+ build for the external scaffold to keep `npm install` light). All
3
+ rules use CSS variables for the Material 3 palette, so the
4
+ Theme Settings → Style tab can swap them at upload time via
5
+ compileCss. */
6
+ @import url("https://fonts.googleapis.com/css2?family=Hanken+Grotesk:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400&family=Inter:wght@400;500;600;700&display=swap");
7
+ @import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap");
8
+
9
+ :root {
10
+ --color-background: 249 249 255;
11
+ --color-surface: 249 249 255;
12
+ --color-surface-container-lowest: 255 255 255;
13
+ --color-surface-container-low: 241 243 255;
14
+ --color-surface-container: 233 237 255;
15
+ --color-surface-container-high: 227 232 249;
16
+ --color-surface-container-highest: 221 226 243;
17
+ --color-on-surface: 22 28 40;
18
+ --color-on-surface-variant: 67 70 85;
19
+ --color-outline: 116 118 134;
20
+ --color-outline-variant: 196 197 215;
21
+ --color-primary: 0 55 176;
22
+ --color-on-primary: 255 255 255;
23
+ --color-primary-container: 29 78 216;
24
+ --color-on-primary-container: 202 211 255;
25
+ --color-secondary: 70 72 212;
26
+ --color-on-secondary: 255 255 255;
27
+ --color-tertiary: 101 0 174;
28
+ --color-on-tertiary: 255 255 255;
29
+ --color-success: 46 125 50;
30
+ --color-success-container: 232 245 233;
31
+ --font-headline: "Hanken Grotesk";
32
+ --font-body: "Inter";
33
+ }
34
+
35
+ /* ───── Reset / base ───── */
36
+ *, *::before, *::after { box-sizing: border-box; }
37
+ html, body { margin: 0; padding: 0; }
38
+ body {
39
+ background: rgb(var(--color-background));
40
+ color: rgb(var(--color-on-surface));
41
+ font-family: var(--font-body), Inter, system-ui, sans-serif;
42
+ font-size: 16px;
43
+ line-height: 1.5;
44
+ -webkit-font-smoothing: antialiased;
45
+ }
46
+ a { color: inherit; text-decoration: none; }
47
+ img { display: block; max-width: 100%; height: auto; }
48
+ button {
49
+ font-family: inherit;
50
+ cursor: pointer;
51
+ border: 0;
52
+ background: transparent;
53
+ padding: 0;
54
+ }
55
+
56
+ /* ───── Material Symbols ───── */
57
+ .material-symbols-outlined {
58
+ font-family: "Material Symbols Outlined";
59
+ font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24;
60
+ vertical-align: middle;
61
+ line-height: 1;
62
+ font-size: 24px;
63
+ }
64
+
65
+ /* ───── Typography helpers ───── */
66
+ .font-headline {
67
+ font-family: var(--font-headline), "Hanken Grotesk", system-ui, sans-serif;
68
+ }
69
+ .text-display-lg {
70
+ font-size: 48px; line-height: 1.1; font-weight: 800; letter-spacing: -0.02em;
71
+ }
72
+ .text-headline-lg { font-size: 32px; line-height: 1.2; font-weight: 700; letter-spacing: -0.01em; }
73
+ .text-headline-md { font-size: 24px; line-height: 1.3; font-weight: 600; }
74
+ .text-body-lg { font-size: 18px; line-height: 1.6; }
75
+ .text-body-md { font-size: 16px; line-height: 1.5; }
76
+ .text-label-md { font-size: 14px; font-weight: 600; line-height: 1; letter-spacing: 0.02em; }
77
+ @media (max-width: 768px) {
78
+ .text-display-lg { font-size: 36px; }
79
+ .text-headline-lg { font-size: 28px; }
80
+ }
81
+
82
+ /* ───── Layout shell ───── */
83
+ .mp-app {
84
+ display: flex;
85
+ flex-direction: column;
86
+ min-height: 100vh;
87
+ }
88
+ .mp-header {
89
+ position: sticky;
90
+ top: 0;
91
+ z-index: 50;
92
+ background: rgb(var(--color-surface));
93
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.04);
94
+ /* Scroll-hide: the inline script in BaseLayout toggles
95
+ `.is-hidden` based on scroll direction (down → hide, up or
96
+ near top → show). We use translateY rather than display so
97
+ the transition runs smoothly. `will-change` hints the
98
+ browser to keep this on a compositing layer. */
99
+ transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
100
+ will-change: transform;
101
+ }
102
+ .mp-header.is-hidden {
103
+ transform: translateY(-100%);
104
+ box-shadow: none;
105
+ }
106
+ .mp-header__inner {
107
+ max-width: 1280px;
108
+ margin: 0 auto;
109
+ display: flex;
110
+ align-items: center;
111
+ justify-content: space-between;
112
+ padding: 16px 24px;
113
+ gap: 24px;
114
+ }
115
+ .mp-brand {
116
+ font-family: var(--font-headline);
117
+ font-size: 28px;
118
+ font-weight: 800;
119
+ color: rgb(var(--color-primary));
120
+ letter-spacing: -0.01em;
121
+ }
122
+ .mp-header__nav {
123
+ display: none;
124
+ align-items: center;
125
+ gap: 24px;
126
+ }
127
+ .mp-nav-link {
128
+ font-size: 14px;
129
+ font-weight: 600;
130
+ color: rgb(var(--color-on-surface-variant));
131
+ padding: 8px 12px;
132
+ border-radius: 9999px;
133
+ transition: background 0.2s, color 0.2s;
134
+ }
135
+ .mp-nav-link:hover { background: rgb(var(--color-surface-container)); color: rgb(var(--color-on-surface)); }
136
+ .mp-nav-link.is-active { background: rgb(var(--color-primary)); color: rgb(var(--color-on-primary)); }
137
+ .mp-header__langswitch {
138
+ /* Sits between the nav and the search input. Collapsed when
139
+ the multilang plugin hasn't injected entries yet (empty
140
+ attribute) so it doesn't push spacing around. */
141
+ --cms-langswitch-on: rgb(var(--color-on-primary));
142
+ color: rgb(var(--color-on-surface-variant));
143
+ margin-left: 8px;
144
+ }
145
+ .mp-header__langswitch[data-cms-langswitch-empty] { display: none; }
146
+ .mp-header__langswitch .cms-langswitch__current { background: rgb(var(--color-primary)); }
147
+ .mp-footer__langswitch {
148
+ --cms-langswitch-on: rgb(var(--color-on-primary));
149
+ color: rgb(var(--color-on-surface-variant));
150
+ margin-right: 12px;
151
+ }
152
+ .mp-footer__langswitch[data-cms-langswitch-empty] { display: none; }
153
+ .mp-footer__langswitch .cms-langswitch__current { background: rgb(var(--color-primary)); }
154
+
155
+ .mp-header__search {
156
+ flex: 1;
157
+ max-width: 480px;
158
+ display: none;
159
+ }
160
+ .mp-search-input {
161
+ width: 100%;
162
+ background: rgb(var(--color-surface-container));
163
+ border: 1px solid transparent;
164
+ border-radius: 12px;
165
+ padding: 10px 16px;
166
+ font-size: 14px;
167
+ color: rgb(var(--color-on-surface));
168
+ outline: none;
169
+ cursor: pointer;
170
+ text-overflow: ellipsis;
171
+ }
172
+ .mp-search-input:hover {
173
+ background: rgb(var(--color-surface-container-high));
174
+ }
175
+ .mp-search-input:focus {
176
+ border-color: rgb(var(--color-primary));
177
+ background: rgb(var(--color-surface-container-lowest));
178
+ }
179
+ @media (min-width: 768px) {
180
+ .mp-header__nav { display: flex; }
181
+ .mp-header__search { display: block; }
182
+ }
183
+
184
+ .mp-layout {
185
+ display: flex;
186
+ flex: 1;
187
+ max-width: 1280px;
188
+ width: 100%;
189
+ margin: 0 auto;
190
+ padding: 0 20px;
191
+ gap: 24px;
192
+ }
193
+ @media (min-width: 768px) {
194
+ .mp-layout { padding: 0 24px; }
195
+ }
196
+
197
+ .mp-sidebar {
198
+ display: none;
199
+ width: 280px;
200
+ flex-shrink: 0;
201
+ padding-top: 24px;
202
+ }
203
+ @media (min-width: 1024px) {
204
+ .mp-sidebar {
205
+ display: block;
206
+ position: sticky;
207
+ top: 88px;
208
+ height: calc(100vh - 88px);
209
+ overflow-y: auto;
210
+ }
211
+ }
212
+ .mp-sidebar__heading {
213
+ font-family: var(--font-headline);
214
+ font-size: 24px;
215
+ font-weight: 700;
216
+ color: rgb(var(--color-on-surface));
217
+ margin: 0 0 16px 8px;
218
+ }
219
+ .mp-sidebar__group { margin-bottom: 24px; }
220
+ .mp-sidebar__label {
221
+ display: block;
222
+ font-size: 11px;
223
+ font-weight: 600;
224
+ letter-spacing: 0.08em;
225
+ text-transform: uppercase;
226
+ color: rgb(var(--color-on-surface-variant));
227
+ padding: 0 12px;
228
+ margin-bottom: 8px;
229
+ }
230
+ .mp-sidebar__link {
231
+ display: flex;
232
+ align-items: center;
233
+ gap: 12px;
234
+ padding: 10px 12px;
235
+ border-radius: 12px;
236
+ font-size: 14px;
237
+ font-weight: 500;
238
+ color: rgb(var(--color-on-surface-variant));
239
+ transition: background 0.15s, color 0.15s;
240
+ }
241
+ .mp-sidebar__link:hover { background: rgb(var(--color-surface-container)); color: rgb(var(--color-on-surface)); }
242
+ .mp-sidebar__link.is-active { background: rgb(var(--color-primary-container)); color: rgb(var(--color-on-primary-container)); }
243
+ .mp-sidebar__link .material-symbols-outlined { font-size: 20px; }
244
+
245
+ .mp-main {
246
+ flex: 1;
247
+ min-width: 0;
248
+ padding: 24px 0 64px;
249
+ }
250
+
251
+ /* ───── Cards (product card — Level 1 elevation) ───── */
252
+ .mp-card {
253
+ background: rgb(var(--color-surface-container-lowest));
254
+ border-radius: 24px;
255
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.04);
256
+ overflow: hidden;
257
+ display: block;
258
+ transition: transform 0.25s ease, box-shadow 0.25s ease;
259
+ }
260
+ .mp-card:hover {
261
+ transform: translateY(-2px) scale(1.01);
262
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.08);
263
+ }
264
+ .mp-card__image {
265
+ width: 100%;
266
+ aspect-ratio: 16 / 10;
267
+ background: rgb(var(--color-surface-container));
268
+ object-fit: cover;
269
+ }
270
+ .mp-card__body { padding: 20px 24px 24px; }
271
+ .mp-card__category {
272
+ display: inline-block;
273
+ font-size: 11px;
274
+ font-weight: 600;
275
+ letter-spacing: 0.05em;
276
+ text-transform: uppercase;
277
+ color: rgb(var(--color-primary));
278
+ margin-bottom: 6px;
279
+ }
280
+ .mp-card__title {
281
+ font-family: var(--font-headline);
282
+ font-size: 18px;
283
+ font-weight: 700;
284
+ color: rgb(var(--color-on-surface));
285
+ margin: 0 0 6px;
286
+ letter-spacing: -0.01em;
287
+ }
288
+ .mp-card__excerpt {
289
+ font-size: 14px;
290
+ color: rgb(var(--color-on-surface-variant));
291
+ margin: 0 0 16px;
292
+ line-height: 1.5;
293
+ display: -webkit-box;
294
+ -webkit-line-clamp: 2;
295
+ -webkit-box-orient: vertical;
296
+ overflow: hidden;
297
+ }
298
+ .mp-card__footer {
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: space-between;
302
+ gap: 12px;
303
+ }
304
+ .mp-card__author {
305
+ font-size: 13px;
306
+ color: rgb(var(--color-on-surface-variant));
307
+ display: flex;
308
+ align-items: center;
309
+ gap: 8px;
310
+ }
311
+ .mp-badge-free {
312
+ display: inline-block;
313
+ font-size: 11px;
314
+ font-weight: 700;
315
+ letter-spacing: 0.05em;
316
+ text-transform: uppercase;
317
+ color: rgb(var(--color-success));
318
+ background: rgb(var(--color-success-container));
319
+ padding: 4px 10px;
320
+ border-radius: 9999px;
321
+ }
322
+
323
+ /* ───── Grid layouts ───── */
324
+ .mp-grid { display: grid; gap: 24px; }
325
+ .mp-grid--3 { grid-template-columns: 1fr; }
326
+ @media (min-width: 640px) { .mp-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
327
+ @media (min-width: 1024px) { .mp-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
328
+ .mp-grid--2 { grid-template-columns: 1fr; }
329
+ @media (min-width: 768px) { .mp-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
330
+
331
+ .mp-section { margin-bottom: 64px; }
332
+ .mp-section__heading {
333
+ display: flex;
334
+ align-items: baseline;
335
+ justify-content: space-between;
336
+ margin-bottom: 24px;
337
+ gap: 16px;
338
+ }
339
+ .mp-section__heading h2 {
340
+ font-family: var(--font-headline);
341
+ font-size: 28px;
342
+ font-weight: 700;
343
+ margin: 0;
344
+ letter-spacing: -0.01em;
345
+ }
346
+ .mp-section__see-all {
347
+ font-size: 14px;
348
+ font-weight: 600;
349
+ color: rgb(var(--color-primary));
350
+ }
351
+
352
+ /* ───── Hero banner ───── */
353
+ .mp-hero {
354
+ position: relative;
355
+ background: linear-gradient(135deg, rgb(var(--color-primary)) 0%, rgb(var(--color-tertiary)) 100%);
356
+ border-radius: 32px;
357
+ overflow: hidden;
358
+ padding: 56px 48px;
359
+ color: rgb(var(--color-on-primary));
360
+ margin-bottom: 64px;
361
+ min-height: 320px;
362
+ display: flex;
363
+ flex-direction: column;
364
+ justify-content: center;
365
+ }
366
+ .mp-hero__eyebrow {
367
+ font-size: 14px;
368
+ font-weight: 700;
369
+ letter-spacing: 0.05em;
370
+ text-transform: uppercase;
371
+ opacity: 0.85;
372
+ margin-bottom: 12px;
373
+ }
374
+ .mp-hero h1 {
375
+ font-family: var(--font-headline);
376
+ font-size: 36px;
377
+ font-weight: 800;
378
+ line-height: 1.1;
379
+ letter-spacing: -0.02em;
380
+ margin: 0 0 16px;
381
+ max-width: 680px;
382
+ }
383
+ @media (min-width: 768px) {
384
+ .mp-hero h1 { font-size: 48px; }
385
+ }
386
+ .mp-hero p {
387
+ font-size: 18px;
388
+ line-height: 1.6;
389
+ max-width: 580px;
390
+ opacity: 0.95;
391
+ margin: 0 0 24px;
392
+ }
393
+
394
+ /* ───── Buttons ───── */
395
+ .mp-btn {
396
+ display: inline-flex;
397
+ align-items: center;
398
+ justify-content: center;
399
+ gap: 8px;
400
+ font-size: 16px;
401
+ font-weight: 700;
402
+ border-radius: 9999px;
403
+ padding: 14px 28px;
404
+ transition: opacity 0.15s, transform 0.1s, box-shadow 0.2s;
405
+ min-height: 48px;
406
+ }
407
+ .mp-btn:active { transform: scale(0.98); }
408
+ a.mp-btn { text-decoration: none; }
409
+ .mp-btn.mp-btn--primary {
410
+ background: rgb(var(--color-primary));
411
+ color: rgb(var(--color-on-primary));
412
+ box-shadow: 0 6px 20px rgba(0, 55, 176, 0.25);
413
+ }
414
+ .mp-btn.mp-btn--primary:hover { opacity: 0.92; color: rgb(var(--color-on-primary)); }
415
+ .mp-btn.mp-btn--secondary {
416
+ background: rgb(var(--color-surface-container));
417
+ color: rgb(var(--color-primary));
418
+ border: 1px solid rgb(var(--color-outline-variant));
419
+ }
420
+ .mp-btn.mp-btn--secondary:hover { background: rgb(var(--color-surface-container-high)); }
421
+ .mp-btn.mp-btn--ghost {
422
+ background: rgb(var(--color-surface));
423
+ color: rgb(var(--color-on-surface));
424
+ }
425
+ .mp-btn.mp-btn--ghost:hover { background: rgb(var(--color-surface-container)); }
426
+
427
+ /* ───── Single page ───── */
428
+ .mp-product {
429
+ display: grid;
430
+ grid-template-columns: 1fr;
431
+ gap: 32px;
432
+ margin-bottom: 64px;
433
+ }
434
+ @media (min-width: 1024px) {
435
+ .mp-product { grid-template-columns: 7fr 5fr; }
436
+ }
437
+ .mp-product__gallery {
438
+ display: flex;
439
+ flex-direction: column;
440
+ gap: 16px;
441
+ }
442
+ .mp-product__hero-image {
443
+ width: 100%;
444
+ aspect-ratio: 16 / 10;
445
+ background: rgb(var(--color-surface-container));
446
+ border-radius: 24px;
447
+ object-fit: cover;
448
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.04);
449
+ }
450
+ .mp-product__thumbs {
451
+ display: grid;
452
+ grid-template-columns: repeat(4, minmax(0, 1fr));
453
+ gap: 12px;
454
+ }
455
+ .mp-product__thumb {
456
+ aspect-ratio: 1 / 1;
457
+ background: rgb(var(--color-surface-container));
458
+ border-radius: 12px;
459
+ overflow: hidden;
460
+ cursor: pointer;
461
+ border: 2px solid transparent;
462
+ transition: border-color 0.2s;
463
+ }
464
+ .mp-product__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
465
+ .mp-product__thumb:hover, .mp-product__thumb.is-active { border-color: rgb(var(--color-primary)); }
466
+ .mp-product__hero-image { cursor: zoom-in; }
467
+
468
+ .mp-product__info {
469
+ display: flex;
470
+ flex-direction: column;
471
+ gap: 16px;
472
+ }
473
+ .mp-product__category {
474
+ font-size: 13px;
475
+ font-weight: 600;
476
+ letter-spacing: 0.05em;
477
+ text-transform: uppercase;
478
+ color: rgb(var(--color-primary));
479
+ }
480
+ .mp-product__title {
481
+ font-family: var(--font-headline);
482
+ font-size: 36px;
483
+ font-weight: 700;
484
+ line-height: 1.1;
485
+ letter-spacing: -0.02em;
486
+ margin: 0;
487
+ }
488
+ .mp-product__author {
489
+ display: flex;
490
+ align-items: center;
491
+ gap: 12px;
492
+ color: rgb(var(--color-on-surface-variant));
493
+ font-size: 14px;
494
+ }
495
+ .mp-product__author img {
496
+ width: 32px;
497
+ height: 32px;
498
+ border-radius: 9999px;
499
+ object-fit: cover;
500
+ background: rgb(var(--color-surface-container));
501
+ }
502
+ .mp-product__excerpt {
503
+ font-size: 18px;
504
+ line-height: 1.6;
505
+ color: rgb(var(--color-on-surface-variant));
506
+ }
507
+ .mp-product__cta-row {
508
+ display: flex;
509
+ gap: 12px;
510
+ margin-top: 8px;
511
+ }
512
+ .mp-product__cta-row .mp-btn { flex: 1; }
513
+
514
+ /* ───── Sections inside single (description, body prose) ───── */
515
+ .mp-section-heading {
516
+ font-family: var(--font-headline);
517
+ font-size: 24px;
518
+ font-weight: 700;
519
+ border-bottom: 1px solid rgb(var(--color-outline-variant));
520
+ padding-bottom: 16px;
521
+ margin: 48px 0 24px;
522
+ }
523
+ .mp-prose {
524
+ font-size: 16px;
525
+ line-height: 1.7;
526
+ color: rgb(var(--color-on-surface));
527
+ max-width: 720px;
528
+ }
529
+ .mp-prose p { margin: 0 0 16px; }
530
+ .mp-prose h2 {
531
+ font-family: var(--font-headline);
532
+ font-size: 24px;
533
+ font-weight: 700;
534
+ margin: 32px 0 16px;
535
+ }
536
+ .mp-prose h3 {
537
+ font-family: var(--font-headline);
538
+ font-size: 18px;
539
+ font-weight: 600;
540
+ margin: 24px 0 12px;
541
+ }
542
+ .mp-prose ul, .mp-prose ol { padding-left: 24px; margin: 0 0 16px; }
543
+ .mp-prose ul { list-style: disc; }
544
+ .mp-prose ol { list-style: decimal; }
545
+ .mp-prose li { margin-bottom: 6px; }
546
+ .mp-prose a {
547
+ color: rgb(var(--color-primary));
548
+ text-decoration: underline;
549
+ text-underline-offset: 3px;
550
+ }
551
+ .mp-prose img {
552
+ border-radius: 16px;
553
+ margin: 24px 0;
554
+ }
555
+ .mp-prose code {
556
+ background: rgb(var(--color-surface-container));
557
+ padding: 2px 6px;
558
+ border-radius: 4px;
559
+ font-size: 0.9em;
560
+ font-family: ui-monospace, Menlo, monospace;
561
+ }
562
+ .mp-prose pre {
563
+ background: rgb(var(--color-surface-container));
564
+ padding: 16px;
565
+ border-radius: 12px;
566
+ overflow-x: auto;
567
+ margin: 16px 0;
568
+ }
569
+
570
+ /* ───── Specs block ───── */
571
+ .mp-specs {
572
+ background: rgb(var(--color-surface-container-lowest));
573
+ border-radius: 24px;
574
+ padding: 24px;
575
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.04);
576
+ }
577
+ .mp-specs__grid {
578
+ display: grid;
579
+ grid-template-columns: 1fr 1fr;
580
+ gap: 24px 32px;
581
+ }
582
+ @media (max-width: 640px) {
583
+ .mp-specs__grid { grid-template-columns: 1fr; }
584
+ }
585
+ .mp-specs__row {
586
+ display: flex;
587
+ flex-direction: column;
588
+ gap: 4px;
589
+ }
590
+ .mp-specs__label {
591
+ font-size: 11px;
592
+ font-weight: 600;
593
+ letter-spacing: 0.05em;
594
+ text-transform: uppercase;
595
+ color: rgb(var(--color-on-surface-variant));
596
+ }
597
+ .mp-specs__value {
598
+ font-size: 16px;
599
+ color: rgb(var(--color-on-surface));
600
+ font-weight: 500;
601
+ }
602
+
603
+ /* ───── Features bento ───── */
604
+ .mp-features {
605
+ display: grid;
606
+ grid-template-columns: 1fr;
607
+ gap: 16px;
608
+ }
609
+ @media (min-width: 640px) {
610
+ .mp-features { grid-template-columns: repeat(2, minmax(0, 1fr)); }
611
+ }
612
+ .mp-features__item {
613
+ background: rgb(var(--color-surface-container-lowest));
614
+ border-radius: 24px;
615
+ padding: 24px;
616
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.04);
617
+ display: flex;
618
+ flex-direction: column;
619
+ gap: 12px;
620
+ }
621
+ .mp-features__icon {
622
+ width: 48px;
623
+ height: 48px;
624
+ border-radius: 12px;
625
+ background: rgb(var(--color-primary-container));
626
+ color: rgb(var(--color-on-primary-container));
627
+ display: flex;
628
+ align-items: center;
629
+ justify-content: center;
630
+ }
631
+ .mp-features__icon .material-symbols-outlined { font-size: 28px; color: rgb(var(--color-on-primary));}
632
+ .mp-features__title {
633
+ font-family: var(--font-headline);
634
+ font-size: 16px;
635
+ font-weight: 700;
636
+ margin: 0;
637
+ }
638
+
639
+ /* ───── Author profile card ───── */
640
+ .mp-author-card {
641
+ background: rgb(var(--color-surface-container-lowest));
642
+ border-radius: 32px;
643
+ padding: 32px;
644
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.04);
645
+ display: flex;
646
+ flex-direction: column;
647
+ align-items: center;
648
+ gap: 24px;
649
+ margin-bottom: 48px;
650
+ }
651
+ @media (min-width: 768px) {
652
+ .mp-author-card { flex-direction: row; align-items: flex-start; }
653
+ }
654
+ .mp-author-card__avatar {
655
+ width: 120px;
656
+ height: 120px;
657
+ border-radius: 9999px;
658
+ background: rgb(var(--color-surface-container));
659
+ object-fit: cover;
660
+ flex-shrink: 0;
661
+ }
662
+ .mp-author-card__info { flex: 1; text-align: center; }
663
+ @media (min-width: 768px) { .mp-author-card__info { text-align: left; } }
664
+ .mp-author-card__name {
665
+ font-family: var(--font-headline);
666
+ font-size: 32px;
667
+ font-weight: 700;
668
+ margin: 0 0 8px;
669
+ }
670
+ .mp-author-card__title {
671
+ font-size: 14px;
672
+ font-weight: 600;
673
+ color: rgb(var(--color-primary));
674
+ margin-bottom: 12px;
675
+ text-transform: uppercase;
676
+ letter-spacing: 0.05em;
677
+ }
678
+ .mp-author-card__bio { color: rgb(var(--color-on-surface-variant)); margin: 0; }
679
+
680
+ /* ───── Breadcrumb ───── */
681
+ .mp-breadcrumb {
682
+ font-size: 13px;
683
+ color: rgb(var(--color-on-surface-variant));
684
+ margin-bottom: 16px;
685
+ display: flex;
686
+ align-items: center;
687
+ gap: 8px;
688
+ flex-wrap: wrap;
689
+ }
690
+ .mp-breadcrumb a:hover { color: rgb(var(--color-primary)); }
691
+ .mp-breadcrumb__sep { opacity: 0.6; }
692
+
693
+ /* ───── Footer ───── */
694
+ .mp-footer {
695
+ background: rgb(var(--color-surface));
696
+ padding: 48px 24px 32px;
697
+ border-top: 1px solid rgb(var(--color-outline-variant));
698
+ }
699
+ .mp-footer__inner {
700
+ max-width: 1280px;
701
+ margin: 0 auto;
702
+ display: flex;
703
+ flex-direction: column;
704
+ gap: 24px;
705
+ }
706
+ @media (min-width: 768px) {
707
+ .mp-footer__inner { flex-direction: row; align-items: center; justify-content: space-between; }
708
+ }
709
+ .mp-footer__nav {
710
+ display: flex;
711
+ flex-wrap: wrap;
712
+ gap: 24px;
713
+ }
714
+ .mp-footer__nav a {
715
+ font-size: 14px;
716
+ color: rgb(var(--color-on-surface-variant));
717
+ }
718
+ .mp-footer__nav a:hover { color: rgb(var(--color-primary)); }
719
+ .mp-footer__copyright {
720
+ font-size: 13px;
721
+ color: rgb(var(--color-on-surface-variant));
722
+ }
723
+
724
+ /* ───── Mobile bottom nav ───── */
725
+ .mp-bottom-nav {
726
+ display: flex;
727
+ position: fixed;
728
+ bottom: 0;
729
+ left: 0;
730
+ right: 0;
731
+ background: rgb(var(--color-surface));
732
+ border-top: 1px solid rgb(var(--color-outline-variant));
733
+ z-index: 40;
734
+ padding: 8px 0 max(8px, env(safe-area-inset-bottom));
735
+ /* Scroll-hide: paired with `.mp-header` via the same script.
736
+ Slides off the bottom of the viewport when the user scrolls
737
+ down, slides back when they reverse or land near the top. */
738
+ transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
739
+ will-change: transform;
740
+ }
741
+ .mp-bottom-nav.is-hidden {
742
+ transform: translateY(100%);
743
+ }
744
+ @media (min-width: 1024px) { .mp-bottom-nav { display: none; } }
745
+ .mp-bottom-nav__item {
746
+ flex: 1;
747
+ display: flex;
748
+ flex-direction: column;
749
+ align-items: center;
750
+ gap: 4px;
751
+ font-size: 11px;
752
+ font-weight: 500;
753
+ color: rgb(var(--color-on-surface-variant));
754
+ padding: 8px 4px;
755
+ }
756
+ .mp-bottom-nav__item.is-active { color: rgb(var(--color-primary)); }
757
+ .mp-bottom-nav__item .material-symbols-outlined { font-size: 24px; }
758
+
759
+ /* Add bottom padding on mobile main canvas so content doesn't sit
760
+ under the bottom nav. */
761
+ @media (max-width: 1023px) {
762
+ .mp-app { padding-bottom: 72px; }
763
+ }
764
+
765
+ /* ───── Filter tabs ───── */
766
+ .mp-tabs {
767
+ display: flex;
768
+ gap: 8px;
769
+ margin-bottom: 24px;
770
+ border-bottom: 1px solid rgb(var(--color-outline-variant));
771
+ overflow-x: auto;
772
+ }
773
+ .mp-tabs__tab {
774
+ padding: 12px 20px;
775
+ font-size: 14px;
776
+ font-weight: 600;
777
+ color: rgb(var(--color-on-surface-variant));
778
+ border-bottom: 2px solid transparent;
779
+ margin-bottom: -1px;
780
+ white-space: nowrap;
781
+ transition: color 0.15s, border-color 0.15s;
782
+ }
783
+ .mp-tabs__tab.is-active {
784
+ color: rgb(var(--color-primary));
785
+ border-bottom-color: rgb(var(--color-primary));
786
+ }
787
+
788
+ /* ───── 404 ───── */
789
+ .mp-404 {
790
+ display: flex;
791
+ flex-direction: column;
792
+ align-items: center;
793
+ justify-content: center;
794
+ text-align: center;
795
+ padding: 96px 24px;
796
+ gap: 16px;
797
+ }
798
+ .mp-404 .material-symbols-outlined {
799
+ font-size: 80px;
800
+ color: rgb(var(--color-primary));
801
+ }
802
+ .mp-404 h1 {
803
+ font-family: var(--font-headline);
804
+ font-size: 48px;
805
+ font-weight: 800;
806
+ margin: 0;
807
+ }
808
+
809
+ /* ───── Static page body ───── */
810
+ .mp-page-body {
811
+ max-width: 800px;
812
+ margin: 0 auto;
813
+ padding: 48px 0;
814
+ }
815
+ .mp-page-body h1 {
816
+ font-family: var(--font-headline);
817
+ font-size: 48px;
818
+ font-weight: 800;
819
+ letter-spacing: -0.02em;
820
+ line-height: 1.1;
821
+ margin: 0 0 32px;
822
+ }
823
+
824
+ /* ───── Lightbox (gallery zoom) ───── */
825
+ .mp-lightbox {
826
+ position: fixed;
827
+ inset: 0;
828
+ z-index: 1000;
829
+ display: flex;
830
+ align-items: center;
831
+ justify-content: center;
832
+ background: rgba(0, 0, 0, 0.92);
833
+ padding: 24px;
834
+ animation: mp-lightbox-fade 0.18s ease-out;
835
+ }
836
+ .mp-lightbox[hidden] { display: none; }
837
+ @keyframes mp-lightbox-fade {
838
+ from { opacity: 0; }
839
+ to { opacity: 1; }
840
+ }
841
+ .mp-lightbox__stage {
842
+ position: relative;
843
+ max-width: min(1200px, 100%);
844
+ max-height: 100%;
845
+ display: flex;
846
+ align-items: center;
847
+ justify-content: center;
848
+ }
849
+ .mp-lightbox__image {
850
+ max-width: 100%;
851
+ max-height: calc(100vh - 96px);
852
+ width: auto;
853
+ height: auto;
854
+ border-radius: 16px;
855
+ box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
856
+ object-fit: contain;
857
+ user-select: none;
858
+ }
859
+ .mp-lightbox__close,
860
+ .mp-lightbox__prev,
861
+ .mp-lightbox__next {
862
+ position: absolute;
863
+ display: inline-flex;
864
+ align-items: center;
865
+ justify-content: center;
866
+ width: 48px;
867
+ height: 48px;
868
+ border-radius: 999px;
869
+ border: 0;
870
+ background: rgba(255, 255, 255, 0.12);
871
+ color: #fff;
872
+ cursor: pointer;
873
+ transition: background 0.15s, transform 0.15s;
874
+ backdrop-filter: blur(8px);
875
+ }
876
+ .mp-lightbox__close:hover,
877
+ .mp-lightbox__prev:hover,
878
+ .mp-lightbox__next:hover {
879
+ background: rgba(255, 255, 255, 0.22);
880
+ }
881
+ .mp-lightbox__close:active,
882
+ .mp-lightbox__prev:active,
883
+ .mp-lightbox__next:active {
884
+ transform: scale(0.94);
885
+ }
886
+ .mp-lightbox__close {
887
+ top: 20px;
888
+ right: 20px;
889
+ }
890
+ .mp-lightbox__prev {
891
+ left: 20px;
892
+ top: 50%;
893
+ transform: translateY(-50%);
894
+ }
895
+ .mp-lightbox__next {
896
+ right: 20px;
897
+ top: 50%;
898
+ transform: translateY(-50%);
899
+ }
900
+ .mp-lightbox__prev:active { transform: translateY(-50%) scale(0.94); }
901
+ .mp-lightbox__next:active { transform: translateY(-50%) scale(0.94); }
902
+ .mp-lightbox__prev .material-symbols-outlined,
903
+ .mp-lightbox__next .material-symbols-outlined,
904
+ .mp-lightbox__close .material-symbols-outlined {
905
+ font-size: 28px;
906
+ }
907
+ .mp-lightbox__counter {
908
+ position: absolute;
909
+ left: 50%;
910
+ bottom: 20px;
911
+ transform: translateX(-50%);
912
+ color: rgba(255, 255, 255, 0.85);
913
+ font-size: 13px;
914
+ font-weight: 500;
915
+ letter-spacing: 0.04em;
916
+ padding: 6px 14px;
917
+ border-radius: 999px;
918
+ background: rgba(255, 255, 255, 0.08);
919
+ backdrop-filter: blur(8px);
920
+ }
921
+ @media (max-width: 640px) {
922
+ .mp-lightbox { padding: 12px; }
923
+ .mp-lightbox__close,
924
+ .mp-lightbox__prev,
925
+ .mp-lightbox__next {
926
+ width: 40px;
927
+ height: 40px;
928
+ }
929
+ .mp-lightbox__close { top: 12px; right: 12px; }
930
+ .mp-lightbox__prev { left: 12px; }
931
+ .mp-lightbox__next { right: 12px; }
932
+ .mp-lightbox__image { max-height: calc(100vh - 72px); }
933
+ }
934
+
935
+ /* ─────────────────────────────────────────────────────────────────
936
+ Landing surfaces (v1.3.0) — used by the marketplace home page.
937
+ All blocks: full-width sections, max-width inner column, generous
938
+ vertical padding that breathes on desktop and condenses on mobile.
939
+ ────────────────────────────────────────────────────────────────── */
940
+
941
+ /* Shared section primitives */
942
+ .mp-section-heading {
943
+ font-family: var(--font-headline);
944
+ font-size: clamp(28px, 3vw, 36px);
945
+ font-weight: 700;
946
+ letter-spacing: -0.01em;
947
+ color: rgb(var(--color-on-surface));
948
+ margin: 0 0 12px;
949
+ text-align: center;
950
+ }
951
+ .mp-section-sub {
952
+ font-size: 16px;
953
+ color: rgb(var(--color-on-surface-variant));
954
+ margin: 0 auto 40px;
955
+ text-align: center;
956
+ max-width: 640px;
957
+ line-height: 1.55;
958
+ }
959
+
960
+ /* ── Landing hero ───────────────────────────────────────────────── */
961
+ /* Single-column on every viewport: copy on top, visual below.
962
+ padding-top: 0 keeps the hero flush against the header so the
963
+ first thing the visitor sees is the headline, not whitespace. */
964
+ .mp-hero-x {
965
+ display: grid;
966
+ grid-template-columns: 1fr;
967
+ gap: 32px;
968
+ align-items: center;
969
+ padding: 0 0 56px;
970
+ margin-bottom: 24px;
971
+ }
972
+ @media (min-width: 900px) {
973
+ .mp-hero-x {
974
+ gap: 48px;
975
+ padding: 0 0 96px;
976
+ }
977
+ }
978
+ .mp-hero-x__eyebrow {
979
+ text-transform: uppercase;
980
+ font-size: 12px;
981
+ letter-spacing: 0.12em;
982
+ font-weight: 700;
983
+ color: rgb(var(--color-primary));
984
+ margin: 0 0 16px;
985
+ }
986
+ .mp-hero-x__headline {
987
+ font-family: var(--font-headline);
988
+ font-size: clamp(36px, 5vw, 56px);
989
+ line-height: 1.05;
990
+ font-weight: 800;
991
+ letter-spacing: -0.02em;
992
+ color: rgb(var(--color-on-surface));
993
+ margin: 0 0 20px;
994
+ }
995
+ .mp-hero-x__sub {
996
+ font-size: clamp(16px, 1.2vw, 19px);
997
+ color: rgb(var(--color-on-surface-variant));
998
+ line-height: 1.55;
999
+ margin: 0 0 28px;
1000
+ max-width: 540px;
1001
+ }
1002
+ .mp-hero-x__ctas {
1003
+ display: flex;
1004
+ gap: 12px;
1005
+ flex-wrap: wrap;
1006
+ }
1007
+ .mp-hero-x__visual {
1008
+ border-radius: 20px;
1009
+ overflow: hidden;
1010
+ box-shadow:
1011
+ 0 30px 60px -20px rgb(0 0 0 / 25%),
1012
+ 0 0 0 1px rgb(var(--color-surface-container));
1013
+ background: rgb(var(--color-surface-container));
1014
+ }
1015
+ .mp-hero-x__visual img {
1016
+ display: block;
1017
+ width: 100%;
1018
+ height: auto;
1019
+ }
1020
+
1021
+ /* ── Stats bar ──────────────────────────────────────────────────── */
1022
+ .mp-stats {
1023
+ padding: 24px 0;
1024
+ margin: 8px 0 16px;
1025
+ }
1026
+ .mp-stats__row {
1027
+ display: grid;
1028
+ grid-template-columns: repeat(2, 1fr);
1029
+ gap: 20px;
1030
+ padding: 28px 32px;
1031
+ background: rgb(var(--color-surface-container-low));
1032
+ border: 1px solid rgb(var(--color-surface-container));
1033
+ border-radius: 16px;
1034
+ }
1035
+ @media (min-width: 720px) {
1036
+ .mp-stats__row {
1037
+ grid-template-columns: repeat(4, 1fr);
1038
+ }
1039
+ }
1040
+ .mp-stats__cell { text-align: center; }
1041
+ .mp-stats__value {
1042
+ font-family: var(--font-headline);
1043
+ font-size: clamp(28px, 3vw, 40px);
1044
+ font-weight: 800;
1045
+ letter-spacing: -0.02em;
1046
+ color: rgb(var(--color-on-surface));
1047
+ margin: 0 0 4px;
1048
+ }
1049
+ .mp-stats__label {
1050
+ font-size: 13px;
1051
+ color: rgb(var(--color-on-surface-variant));
1052
+ margin: 0;
1053
+ text-transform: uppercase;
1054
+ letter-spacing: 0.06em;
1055
+ }
1056
+
1057
+ /* ── Feature grid (3-col cards) ─────────────────────────────────── */
1058
+ .mp-grid-feat {
1059
+ padding: 64px 0;
1060
+ }
1061
+ .mp-grid-feat__row {
1062
+ display: grid;
1063
+ grid-template-columns: 1fr;
1064
+ gap: 20px;
1065
+ }
1066
+ @media (min-width: 720px) {
1067
+ .mp-grid-feat__row { grid-template-columns: repeat(3, 1fr); }
1068
+ }
1069
+ .mp-grid-feat__card {
1070
+ padding: 28px;
1071
+ background: rgb(var(--color-surface-container-low));
1072
+ border: 1px solid rgb(var(--color-surface-container));
1073
+ border-radius: 16px;
1074
+ transition: transform 0.18s, box-shadow 0.18s, border-color 0.18s;
1075
+ }
1076
+ .mp-grid-feat__card:hover {
1077
+ transform: translateY(-2px);
1078
+ box-shadow: 0 18px 40px -16px rgb(0 0 0 / 30%);
1079
+ border-color: rgb(var(--color-primary) / 30%);
1080
+ }
1081
+ .mp-grid-feat__icon {
1082
+ width: 48px;
1083
+ height: 48px;
1084
+ border-radius: 12px;
1085
+ background: rgb(var(--color-primary) / 12%);
1086
+ color: rgb(var(--color-primary));
1087
+ display: flex;
1088
+ align-items: center;
1089
+ justify-content: center;
1090
+ margin-bottom: 16px;
1091
+ }
1092
+ .mp-grid-feat__icon .material-symbols-outlined {
1093
+ font-size: 28px;
1094
+ }
1095
+ .mp-grid-feat__title {
1096
+ font-family: var(--font-headline);
1097
+ font-size: 19px;
1098
+ font-weight: 700;
1099
+ color: rgb(var(--color-on-surface));
1100
+ margin: 0 0 8px;
1101
+ }
1102
+ .mp-grid-feat__body {
1103
+ font-size: 15px;
1104
+ color: rgb(var(--color-on-surface-variant));
1105
+ margin: 0;
1106
+ line-height: 1.55;
1107
+ }
1108
+
1109
+ /* ── Feature row (text on top, image below) ────────────────────── */
1110
+ /* Stacked single-column on every viewport. The DOM has the image
1111
+ first for legacy reasons (kept for backward compat with v1.3.0
1112
+ exports); CSS `order` flips it so the copy always reads above
1113
+ the visual — matches the mobile-style flow the design specifies
1114
+ even on desktop. The `imagePosition` attribute is preserved on
1115
+ the wrapper for any future visual treatment but doesn't affect
1116
+ layout anymore. */
1117
+ .mp-row-feat {
1118
+ display: grid;
1119
+ grid-template-columns: 1fr;
1120
+ gap: 32px;
1121
+ align-items: stretch;
1122
+ padding: 56px 0;
1123
+ }
1124
+ .mp-row-feat__copy { order: 0; }
1125
+ .mp-row-feat__visual { order: 1; }
1126
+ .mp-row-feat__eyebrow {
1127
+ text-transform: uppercase;
1128
+ font-size: 12px;
1129
+ letter-spacing: 0.12em;
1130
+ font-weight: 700;
1131
+ color: rgb(var(--color-primary));
1132
+ margin: 0 0 14px;
1133
+ }
1134
+ .mp-row-feat__headline {
1135
+ font-family: var(--font-headline);
1136
+ font-size: clamp(26px, 3vw, 38px);
1137
+ line-height: 1.1;
1138
+ font-weight: 800;
1139
+ letter-spacing: -0.02em;
1140
+ color: rgb(var(--color-on-surface));
1141
+ margin: 0 0 16px;
1142
+ }
1143
+ .mp-row-feat__body {
1144
+ font-size: 16px;
1145
+ color: rgb(var(--color-on-surface-variant));
1146
+ line-height: 1.6;
1147
+ margin: 0 0 20px;
1148
+ }
1149
+ .mp-row-feat__bullets {
1150
+ list-style: none;
1151
+ padding: 0;
1152
+ margin: 0 0 24px;
1153
+ }
1154
+ .mp-row-feat__bullets li {
1155
+ display: flex;
1156
+ align-items: flex-start;
1157
+ gap: 10px;
1158
+ padding: 6px 0;
1159
+ font-size: 15px;
1160
+ color: rgb(var(--color-on-surface));
1161
+ }
1162
+ .mp-row-feat__bullets .material-symbols-outlined {
1163
+ color: rgb(var(--color-primary));
1164
+ font-size: 20px;
1165
+ margin-top: 2px;
1166
+ flex-shrink: 0;
1167
+ }
1168
+ .mp-row-feat__cta {
1169
+ display: inline-flex;
1170
+ align-items: center;
1171
+ gap: 6px;
1172
+ color: rgb(var(--color-primary));
1173
+ font-weight: 600;
1174
+ font-size: 15px;
1175
+ text-decoration: none;
1176
+ }
1177
+ .mp-row-feat__cta:hover { opacity: 0.85; text-decoration: none; }
1178
+ /* Belt-and-braces — explicitly suppress underline on every landing-
1179
+ block button. `a.mp-btn` already declares `text-decoration: none`
1180
+ globally, but some user-agent stylesheets (Safari mainly) re-add
1181
+ it on hover or focus, so we pin it here per surface. */
1182
+ .mp-hero-x .mp-btn,
1183
+ .mp-hero-x .mp-btn:hover,
1184
+ .mp-hero-x .mp-btn:focus,
1185
+ .mp-row-feat__cta,
1186
+ .mp-row-feat__cta:hover,
1187
+ .mp-row-feat__cta:focus,
1188
+ .mp-cta-banner .mp-btn,
1189
+ .mp-cta-banner .mp-btn:hover,
1190
+ .mp-cta-banner .mp-btn:focus { text-decoration: none; }
1191
+ .mp-row-feat__visual {
1192
+ border-radius: 16px;
1193
+ overflow: hidden;
1194
+ box-shadow:
1195
+ 0 20px 50px -20px rgb(0 0 0 / 20%),
1196
+ 0 0 0 1px rgb(var(--color-surface-container));
1197
+ background: rgb(var(--color-surface-container));
1198
+ }
1199
+ .mp-row-feat__visual img {
1200
+ display: block;
1201
+ width: 100%;
1202
+ height: auto;
1203
+ }
1204
+
1205
+ /* ── CTA banner ─────────────────────────────────────────────────── */
1206
+ .mp-cta-banner {
1207
+ padding: 56px 0;
1208
+ }
1209
+ .mp-cta-banner__inner {
1210
+ padding: 56px 32px;
1211
+ background:
1212
+ linear-gradient(135deg,
1213
+ rgb(var(--color-primary) / 92%),
1214
+ rgb(var(--color-primary-container) / 75%));
1215
+ border-radius: 24px;
1216
+ text-align: center;
1217
+ color: rgb(var(--color-on-primary));
1218
+ }
1219
+ .mp-cta-banner__headline {
1220
+ font-family: var(--font-headline);
1221
+ font-size: clamp(28px, 3vw, 40px);
1222
+ font-weight: 800;
1223
+ letter-spacing: -0.02em;
1224
+ margin: 0 0 16px;
1225
+ color: rgb(var(--color-on-primary));
1226
+ }
1227
+ .mp-cta-banner__body {
1228
+ font-size: 16px;
1229
+ opacity: 0.92;
1230
+ margin: 0 auto 28px;
1231
+ max-width: 560px;
1232
+ line-height: 1.55;
1233
+ }
1234
+ .mp-cta-banner__ctas {
1235
+ display: inline-flex;
1236
+ gap: 12px;
1237
+ flex-wrap: wrap;
1238
+ justify-content: center;
1239
+ }
1240
+ .mp-cta-banner .mp-btn--primary {
1241
+ background: rgb(var(--color-on-primary));
1242
+ color: rgb(var(--color-primary));
1243
+ }
1244
+ .mp-cta-banner .mp-btn--primary:hover { opacity: 0.92; }
1245
+ .mp-cta-banner .mp-btn--ghost {
1246
+ background: transparent;
1247
+ color: rgb(var(--color-on-primary));
1248
+ border: 1px solid rgb(var(--color-on-primary) / 50%);
1249
+ }
1250
+ .mp-cta-banner .mp-btn--ghost:hover {
1251
+ background: rgb(var(--color-on-primary) / 12%);
1252
+ }
1253
+
1254
+ /* ─────────────────────────────────────────────────────────────────
1255
+ * No-image card variant — used by ProductCard when card.hero is
1256
+ * absent (typical for imported docs). Drops the 16:10 image slot,
1257
+ * adds top padding to compensate, hides the Free-badge footer.
1258
+ * The category line becomes more prominent so the card still feels
1259
+ * intentional rather than a stripped-down product card.
1260
+ * ───────────────────────────────────────────────────────────────── */
1261
+ .mp-card--no-image .mp-card__image { display: none; }
1262
+ .mp-card--no-image .mp-card__body { padding: 28px 24px; }
1263
+ .mp-card--no-image .mp-card__category {
1264
+ font-size: 12px;
1265
+ margin-bottom: 10px;
1266
+ }
1267
+ .mp-card--no-image .mp-card__title {
1268
+ font-size: 20px;
1269
+ margin-bottom: 8px;
1270
+ }
1271
+ .mp-card--no-image .mp-card__excerpt {
1272
+ -webkit-line-clamp: 3;
1273
+ margin: 0;
1274
+ }
1275
+ .mp-card--no-image .mp-card__footer { display: none; }
1276
+
1277
+ /* ─────────────────────────────────────────────────────────────────
1278
+ * Documentation single-post layout — used when the post has no
1279
+ * hero image. Centered reading column, no product chrome (no
1280
+ * download/CTA slot, no gallery, no Free badge). Includes a
1281
+ * breadcrumb at the top and prev/next sibling navigation at the
1282
+ * bottom.
1283
+ * ───────────────────────────────────────────────────────────────── */
1284
+ .mp-doc {
1285
+ max-width: 760px;
1286
+ margin: 0 auto;
1287
+ padding: 8px 0 64px;
1288
+ }
1289
+ .mp-doc__header {
1290
+ margin: 24px 0 32px;
1291
+ padding-bottom: 24px;
1292
+ border-bottom: 1px solid rgb(var(--color-outline-variant));
1293
+ }
1294
+ .mp-doc__title {
1295
+ font-family: var(--font-headline);
1296
+ font-size: clamp(28px, 4vw, 40px);
1297
+ font-weight: 700;
1298
+ line-height: 1.15;
1299
+ letter-spacing: -0.02em;
1300
+ color: rgb(var(--color-on-surface));
1301
+ margin: 0 0 12px;
1302
+ }
1303
+ .mp-doc__excerpt {
1304
+ font-size: 17px;
1305
+ line-height: 1.55;
1306
+ color: rgb(var(--color-on-surface-variant));
1307
+ margin: 0;
1308
+ }
1309
+ .mp-doc__body { margin-top: 8px; }
1310
+
1311
+ /* Prev / Next sibling pager at the bottom of a doc page. Two-cell
1312
+ * grid on desktop; stacks on mobile. The non-existing side (e.g.
1313
+ * "no previous post on the first page") gets a placeholder <span/>
1314
+ * so the grid stays balanced and the next button keeps its right
1315
+ * alignment. */
1316
+ .mp-doc__pagerow {
1317
+ display: grid;
1318
+ grid-template-columns: 1fr 1fr;
1319
+ gap: 16px;
1320
+ margin-top: 56px;
1321
+ padding-top: 28px;
1322
+ border-top: 1px solid rgb(var(--color-outline-variant));
1323
+ }
1324
+ .mp-doc__pager {
1325
+ display: flex;
1326
+ flex-direction: column;
1327
+ gap: 4px;
1328
+ padding: 18px 22px;
1329
+ border-radius: 16px;
1330
+ background: rgb(var(--color-surface-container-lowest));
1331
+ border: 1px solid rgb(var(--color-outline-variant));
1332
+ text-decoration: none;
1333
+ color: rgb(var(--color-on-surface));
1334
+ transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
1335
+ }
1336
+ .mp-doc__pager:hover {
1337
+ background: rgb(var(--color-surface-container-low));
1338
+ border-color: rgb(var(--color-primary) / 40%);
1339
+ transform: translateY(-1px);
1340
+ }
1341
+ .mp-doc__pager--next {
1342
+ text-align: right;
1343
+ align-items: flex-end;
1344
+ }
1345
+ .mp-doc__pager-label {
1346
+ font-size: 12px;
1347
+ font-weight: 600;
1348
+ letter-spacing: 0.04em;
1349
+ text-transform: uppercase;
1350
+ color: rgb(var(--color-primary));
1351
+ }
1352
+ .mp-doc__pager-title {
1353
+ font-family: var(--font-headline);
1354
+ font-size: 16px;
1355
+ font-weight: 600;
1356
+ color: rgb(var(--color-on-surface));
1357
+ line-height: 1.35;
1358
+ }
1359
+ @media (max-width: 600px) {
1360
+ .mp-doc__pagerow {
1361
+ grid-template-columns: 1fr;
1362
+ }
1363
+ .mp-doc__pager--next { text-align: left; align-items: flex-start; }
1364
+ }
1365
+
1366
+ /* ─────────────────────────────────────────────────────────────────
1367
+ * Documentation prose enhancements — applied to .mp-prose content
1368
+ * inside .mp-doc (the no-hero doc layout). Three pieces:
1369
+ * - Admonition boxes (rewritten from blockquote-with-strong)
1370
+ * - Code blocks (chrome + dark background + copy button)
1371
+ * - Tables (proper borders, header bg, zebra rows)
1372
+ * ───────────────────────────────────────────────────────────────── */
1373
+
1374
+ /* ── Admonitions ──────────────────────────────────────────────── */
1375
+ .mp-admonition {
1376
+ margin: 24px 0;
1377
+ border-radius: 12px;
1378
+ padding: 16px 18px;
1379
+ border-left: 4px solid;
1380
+ background: rgb(var(--color-surface-container-low));
1381
+ color: rgb(var(--color-on-surface));
1382
+ display: block;
1383
+ }
1384
+ .mp-admonition__title {
1385
+ display: flex;
1386
+ align-items: center;
1387
+ gap: 10px;
1388
+ font-weight: 700;
1389
+ font-size: 15px;
1390
+ margin-bottom: 8px;
1391
+ letter-spacing: -0.005em;
1392
+ }
1393
+ .mp-admonition__icon {
1394
+ display: inline-block;
1395
+ width: 18px;
1396
+ height: 18px;
1397
+ border-radius: 50%;
1398
+ flex-shrink: 0;
1399
+ background: currentColor;
1400
+ opacity: 0.18;
1401
+ position: relative;
1402
+ }
1403
+ .mp-admonition__icon::after {
1404
+ content: "";
1405
+ position: absolute;
1406
+ inset: 0;
1407
+ border-radius: 50%;
1408
+ background: currentColor;
1409
+ opacity: 1;
1410
+ transform: scale(0.35);
1411
+ }
1412
+ .mp-admonition__body {
1413
+ font-size: 15px;
1414
+ line-height: 1.6;
1415
+ }
1416
+ .mp-admonition__body > :first-child { margin-top: 0; }
1417
+ .mp-admonition__body > :last-child { margin-bottom: 0; }
1418
+
1419
+ /* Per-kind colors. Borders + title color shift; body stays neutral
1420
+ * so the box doesn't fight for attention with the surrounding prose. */
1421
+ .mp-admonition--info {
1422
+ border-left-color: rgb(60 130 246);
1423
+ background: rgb(60 130 246 / 6%);
1424
+ }
1425
+ .mp-admonition--info .mp-admonition__title { color: rgb(30 80 200); }
1426
+ .mp-admonition--tip {
1427
+ border-left-color: rgb(34 156 99);
1428
+ background: rgb(34 156 99 / 6%);
1429
+ }
1430
+ .mp-admonition--tip .mp-admonition__title { color: rgb(22 110 70); }
1431
+ .mp-admonition--warning {
1432
+ border-left-color: rgb(217 134 23);
1433
+ background: rgb(217 134 23 / 8%);
1434
+ }
1435
+ .mp-admonition--warning .mp-admonition__title { color: rgb(160 92 0); }
1436
+ .mp-admonition--danger {
1437
+ border-left-color: rgb(225 67 67);
1438
+ background: rgb(225 67 67 / 7%);
1439
+ }
1440
+ .mp-admonition--danger .mp-admonition__title { color: rgb(166 38 38); }
1441
+ .mp-admonition--note {
1442
+ border-left-color: rgb(110 90 200);
1443
+ background: rgb(110 90 200 / 6%);
1444
+ }
1445
+ .mp-admonition--note .mp-admonition__title { color: rgb(80 60 175); }
1446
+
1447
+ /* Dark-mode adjustments: lift the title color toward the lighter
1448
+ * end of the swatch so contrast against the dark background stays
1449
+ * comfortable. Backgrounds keep their tinted look. */
1450
+ @media (prefers-color-scheme: dark) {
1451
+ .mp-admonition { background: rgb(255 255 255 / 4%); }
1452
+ .mp-admonition--info .mp-admonition__title { color: rgb(140 175 255); }
1453
+ .mp-admonition--tip .mp-admonition__title { color: rgb(120 200 160); }
1454
+ .mp-admonition--warning .mp-admonition__title { color: rgb(245 190 100); }
1455
+ .mp-admonition--danger .mp-admonition__title { color: rgb(250 140 140); }
1456
+ .mp-admonition--note .mp-admonition__title { color: rgb(180 165 245); }
1457
+ }
1458
+
1459
+ /* ── Code blocks ──────────────────────────────────────────────── */
1460
+ .mp-codeblock {
1461
+ margin: 24px 0;
1462
+ border-radius: 12px;
1463
+ overflow: hidden;
1464
+ background: rgb(20 23 32);
1465
+ border: 1px solid rgb(36 40 52);
1466
+ }
1467
+ .mp-codeblock__bar {
1468
+ display: flex;
1469
+ align-items: center;
1470
+ justify-content: space-between;
1471
+ padding: 8px 14px;
1472
+ background: rgb(28 32 44);
1473
+ border-bottom: 1px solid rgb(40 44 60);
1474
+ }
1475
+ .mp-codeblock__lang {
1476
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
1477
+ font-size: 11px;
1478
+ font-weight: 600;
1479
+ letter-spacing: 0.06em;
1480
+ color: rgb(160 168 190);
1481
+ text-transform: uppercase;
1482
+ }
1483
+ .mp-codeblock__copy {
1484
+ display: inline-flex;
1485
+ align-items: center;
1486
+ gap: 6px;
1487
+ padding: 4px 10px;
1488
+ border-radius: 6px;
1489
+ background: transparent;
1490
+ border: 1px solid rgb(60 65 82);
1491
+ color: rgb(200 205 220);
1492
+ font-size: 12px;
1493
+ font-weight: 500;
1494
+ cursor: pointer;
1495
+ transition: background 0.18s ease, border-color 0.18s ease;
1496
+ }
1497
+ .mp-codeblock__copy:hover {
1498
+ background: rgb(40 44 60);
1499
+ border-color: rgb(90 95 115);
1500
+ }
1501
+ .mp-codeblock__copy:active { transform: translateY(1px); }
1502
+ .mp-codeblock__copy.is-copied {
1503
+ background: rgb(34 156 99 / 18%);
1504
+ border-color: rgb(34 156 99);
1505
+ color: rgb(160 220 195);
1506
+ }
1507
+ .mp-codeblock__copy-icon {
1508
+ display: inline-block;
1509
+ width: 12px;
1510
+ height: 12px;
1511
+ border-radius: 2px;
1512
+ background: currentColor;
1513
+ opacity: 0.7;
1514
+ position: relative;
1515
+ }
1516
+ .mp-codeblock__copy-icon::before {
1517
+ content: "";
1518
+ position: absolute;
1519
+ inset: -3px -3px 3px 3px;
1520
+ border: 1.5px solid currentColor;
1521
+ border-radius: 2px;
1522
+ background: transparent;
1523
+ opacity: 0.5;
1524
+ }
1525
+ .mp-codeblock > pre {
1526
+ margin: 0;
1527
+ padding: 16px 18px;
1528
+ background: transparent;
1529
+ overflow-x: auto;
1530
+ font-family: ui-monospace, SFMono-Regular, Menlo, "Cascadia Code", monospace;
1531
+ font-size: 13.5px;
1532
+ line-height: 1.55;
1533
+ color: rgb(225 228 240);
1534
+ }
1535
+ .mp-codeblock > pre > code {
1536
+ background: transparent;
1537
+ padding: 0;
1538
+ font-family: inherit;
1539
+ color: inherit;
1540
+ }
1541
+
1542
+ /* Inline code (NOT inside pre) — kept light + neutral so it pops
1543
+ * against the body text without competing with the code-block chrome. */
1544
+ .mp-prose :not(pre) > code,
1545
+ .mp-prose code:not(pre code) {
1546
+ background: rgb(0 0 0 / 6%);
1547
+ padding: 1px 6px;
1548
+ border-radius: 4px;
1549
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
1550
+ font-size: 0.92em;
1551
+ color: rgb(180 60 110);
1552
+ }
1553
+ @media (prefers-color-scheme: dark) {
1554
+ .mp-prose :not(pre) > code,
1555
+ .mp-prose code:not(pre code) {
1556
+ background: rgb(255 255 255 / 8%);
1557
+ color: rgb(245 145 185);
1558
+ }
1559
+ }
1560
+
1561
+ /* ── Tables ───────────────────────────────────────────────────── */
1562
+ .mp-prose table {
1563
+ width: 100%;
1564
+ border-collapse: collapse;
1565
+ margin: 24px 0;
1566
+ font-size: 14.5px;
1567
+ background: rgb(var(--color-surface-container-lowest));
1568
+ border-radius: 10px;
1569
+ overflow: hidden;
1570
+ border: 1px solid rgb(var(--color-outline-variant));
1571
+ }
1572
+ .mp-prose thead {
1573
+ background: rgb(var(--color-surface-container-low));
1574
+ }
1575
+ .mp-prose thead th {
1576
+ text-align: left;
1577
+ font-weight: 700;
1578
+ font-size: 13px;
1579
+ letter-spacing: 0.02em;
1580
+ padding: 12px 14px;
1581
+ color: rgb(var(--color-on-surface));
1582
+ border-bottom: 1px solid rgb(var(--color-outline-variant));
1583
+ }
1584
+ .mp-prose tbody td {
1585
+ padding: 11px 14px;
1586
+ vertical-align: top;
1587
+ color: rgb(var(--color-on-surface));
1588
+ border-bottom: 1px solid rgb(var(--color-outline-variant));
1589
+ }
1590
+ .mp-prose tbody tr:last-child td { border-bottom: 0; }
1591
+ .mp-prose tbody tr:nth-child(even) {
1592
+ background: rgb(var(--color-surface-container-low) / 50%);
1593
+ }
1594
+ .mp-prose tbody tr:hover {
1595
+ background: rgb(var(--color-primary) / 4%);
1596
+ }
1597
+ .mp-prose table code {
1598
+ font-size: 0.88em;
1599
+ }
1600
+
1601
+ /* Responsive overflow — narrow viewports get a horizontal scroll
1602
+ * around the table instead of mangled wrapping. The .mp-prose
1603
+ * wrapper already has overflow:auto on small screens via the
1604
+ * existing rule, but we add a safety here for direct table
1605
+ * children too. */
1606
+ @media (max-width: 720px) {
1607
+ .mp-prose table {
1608
+ display: block;
1609
+ overflow-x: auto;
1610
+ white-space: nowrap;
1611
+ }
1612
+ .mp-prose tbody td { white-space: normal; }
1613
+ }