@tokenoftrust/storefront-runner 1.3.4-rc.3 → 1.4.0

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 (225) hide show
  1. package/apps/storefront/astro.config.mjs +15 -0
  2. package/apps/storefront/dev-plugins/dev-publish.mjs +55 -0
  3. package/apps/storefront/dev-plugins/tenant-hot-reload.mjs +86 -7
  4. package/apps/storefront/drizzle.config.apps.ts +13 -0
  5. package/apps/storefront/env.d.ts +10 -0
  6. package/apps/storefront/migrations/README.md +13 -7
  7. package/apps/storefront/migrations-apps/0000_fast_millenium_guard.sql +129 -0
  8. package/apps/storefront/migrations-apps/meta/0000_snapshot.json +843 -0
  9. package/apps/storefront/migrations-apps/meta/_journal.json +13 -0
  10. package/apps/storefront/package.json +13 -1
  11. package/apps/storefront/perf/README.md +64 -0
  12. package/apps/storefront/perf/assert-budgets.ts +159 -0
  13. package/apps/storefront/playwright.config.ts +23 -0
  14. package/apps/storefront/public/js/dashboard-apps.js +173 -0
  15. package/apps/storefront/public/shared/commerce-marketing.css +221 -0
  16. package/apps/storefront/src/components/CollectionCard.astro +1 -0
  17. package/apps/storefront/src/components/ProductCard.astro +1 -0
  18. package/apps/storefront/src/components/admin/AdminPublishTab.astro +1959 -0
  19. package/apps/storefront/src/components/apps/AppWidgetFrame.astro +30 -0
  20. package/apps/storefront/src/components/chrome/NavDropdown.astro +6 -3
  21. package/apps/storefront/src/components/chrome/SiteFooter.astro +10 -0
  22. package/apps/storefront/src/components/chrome/SiteHeader.astro +10 -0
  23. package/apps/storefront/src/components/commerce/RatingStars.astro +3 -2
  24. package/apps/storefront/src/components/content/Callout.astro +75 -0
  25. package/apps/storefront/src/components/content/NeedsReviewCallout.astro +66 -0
  26. package/apps/storefront/src/components/content/ProseSections.astro +121 -0
  27. package/apps/storefront/src/components/content/ProseToc.astro +34 -0
  28. package/apps/storefront/src/components/content/RichText.astro +44 -0
  29. package/apps/storefront/src/components/content/TrustStrip.astro +46 -0
  30. package/apps/storefront/src/components/home/Hero.astro +14 -0
  31. package/apps/storefront/src/components/islands/CheckoutComplianceGate.tsx +295 -0
  32. package/apps/storefront/src/components/islands/ImageGallery.tsx +42 -21
  33. package/apps/storefront/src/components/islands/VariantSelector.tsx +62 -12
  34. package/apps/storefront/src/components/plp/FacetSidebar.astro +2 -2
  35. package/apps/storefront/src/components/subscription/ManageSubscriptionEntry.astro +1 -0
  36. package/apps/storefront/src/config/compliance/rulesets.ts +79 -0
  37. package/apps/storefront/src/config/storeName.ts +34 -0
  38. package/apps/storefront/src/layouts/Layout.astro +97 -23
  39. package/apps/storefront/src/lib/analytics/budgets.json +69 -0
  40. package/apps/storefront/src/lib/analytics/lighthouseReport.ts +109 -0
  41. package/apps/storefront/src/lib/analytics/perfBudgets.ts +452 -0
  42. package/apps/storefront/src/lib/analytics/rumAlert.ts +179 -0
  43. package/apps/storefront/src/lib/analytics/webVitals.ts +269 -0
  44. package/apps/storefront/src/lib/apps/adminService.ts +106 -0
  45. package/apps/storefront/src/lib/apps/adminSession.ts +205 -0
  46. package/apps/storefront/src/lib/apps/apiAuth.ts +91 -0
  47. package/apps/storefront/src/lib/apps/apiRoute.ts +35 -0
  48. package/apps/storefront/src/lib/apps/catalogMapper.ts +39 -0
  49. package/apps/storefront/src/lib/apps/credentials.ts +153 -0
  50. package/apps/storefront/src/lib/apps/gatewayKeys.ts +156 -0
  51. package/apps/storefront/src/lib/apps/healthAggregate.ts +66 -0
  52. package/apps/storefront/src/lib/apps/orders/attributionService.ts +206 -0
  53. package/apps/storefront/src/lib/apps/orders/customerHash.ts +28 -0
  54. package/apps/storefront/src/lib/apps/orders/foxyOrderClient.ts +203 -0
  55. package/apps/storefront/src/lib/apps/orders/idempotency.ts +100 -0
  56. package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +117 -0
  57. package/apps/storefront/src/lib/apps/orders/orderMapper.ts +91 -0
  58. package/apps/storefront/src/lib/apps/orders/ordersStore.ts +181 -0
  59. package/apps/storefront/src/lib/apps/registryService.ts +579 -0
  60. package/apps/storefront/src/lib/apps/scopes.ts +79 -0
  61. package/apps/storefront/src/lib/apps/tokenIssuer.ts +121 -0
  62. package/apps/storefront/src/lib/apps/tokenVerifier.ts +148 -0
  63. package/apps/storefront/src/lib/apps/widgets/eligibility.ts +18 -0
  64. package/apps/storefront/src/lib/apps/widgets/frameProps.ts +52 -0
  65. package/apps/storefront/src/lib/apps/widgets/launchToken.ts +84 -0
  66. package/apps/storefront/src/lib/apps/widgets/placements.ts +57 -0
  67. package/apps/storefront/src/lib/apps/widgets/renderSlot.ts +111 -0
  68. package/apps/storefront/src/lib/auth/adminEntry.ts +119 -0
  69. package/apps/storefront/src/lib/auth/identityToken.ts +21 -2
  70. package/apps/storefront/src/lib/auth/loginGate.ts +102 -18
  71. package/apps/storefront/src/lib/auth/mcpClientAssertion.ts +215 -0
  72. package/apps/storefront/src/lib/auth/route.ts +16 -1
  73. package/apps/storefront/src/lib/auth/session.ts +8 -0
  74. package/apps/storefront/src/lib/auth/stepUpChallenge.ts +107 -0
  75. package/apps/storefront/src/lib/auth/totAccessClient.ts +208 -0
  76. package/apps/storefront/src/lib/blog/provider.ts +39 -0
  77. package/apps/storefront/src/lib/blog/types.ts +26 -0
  78. package/apps/storefront/src/lib/checkoutCommerce.ts +39 -1
  79. package/apps/storefront/src/lib/chrome/model.ts +11 -0
  80. package/apps/storefront/src/lib/compliance/enforcement.ts +95 -0
  81. package/apps/storefront/src/lib/content/callout.ts +78 -0
  82. package/apps/storefront/src/lib/content/index.ts +27 -0
  83. package/apps/storefront/src/lib/content/needsReview.ts +58 -0
  84. package/apps/storefront/src/lib/content/prose.ts +186 -0
  85. package/apps/storefront/src/lib/content/richtext.ts +76 -0
  86. package/apps/storefront/src/lib/content/trustStrip.ts +74 -0
  87. package/apps/storefront/src/lib/content-edit/client.ts +70 -14
  88. package/apps/storefront/src/lib/d1/catalog.ts +12 -0
  89. package/apps/storefront/src/lib/d1/schema-apps.ts +213 -0
  90. package/apps/storefront/src/lib/dev/apiBase.ts +8 -2
  91. package/apps/storefront/src/lib/dev/cliSignInCode.ts +65 -115
  92. package/apps/storefront/src/lib/dev/cockpitStore.ts +65 -0
  93. package/apps/storefront/src/lib/dev/obstacleStore.ts +214 -0
  94. package/apps/storefront/src/lib/dev/previewStatus.ts +112 -0
  95. package/apps/storefront/src/lib/dev/rendezvousBroker.ts +241 -0
  96. package/apps/storefront/src/lib/dev/subjectReissue.ts +67 -0
  97. package/apps/storefront/src/lib/email/magicLinkInviteEmail.ts +10 -10
  98. package/apps/storefront/src/lib/env.ts +12 -0
  99. package/apps/storefront/src/lib/jsonld.ts +12 -17
  100. package/apps/storefront/src/lib/membership/eligibility.ts +37 -0
  101. package/apps/storefront/src/lib/monitoring/manifest.ts +302 -0
  102. package/apps/storefront/src/lib/privacy/emailHint.ts +13 -5
  103. package/apps/storefront/src/lib/publish/apex-readiness.ts +337 -0
  104. package/apps/storefront/src/lib/publish/dispatchHealth.ts +269 -0
  105. package/apps/storefront/src/lib/publish/domainState.ts +351 -0
  106. package/apps/storefront/src/lib/publish/shipWorkspace.ts +362 -0
  107. package/apps/storefront/src/lib/rawChrome.ts +34 -3
  108. package/apps/storefront/src/lib/storyblok/content-model.ts +34 -2
  109. package/apps/storefront/src/lib/storyblok/provider.ts +11 -4
  110. package/apps/storefront/src/lib/subscription/model.ts +114 -0
  111. package/apps/storefront/src/lib/tot/ToTClient.ts +3 -3
  112. package/apps/storefront/src/lib/tot/query.ts +32 -0
  113. package/apps/storefront/src/lib/webhooks/cloudflareQueueDispatcher.ts +82 -0
  114. package/apps/storefront/src/lib/webhooks/deliveryEngine.ts +245 -0
  115. package/apps/storefront/src/lib/webhooks/deliveryMapper.ts +34 -0
  116. package/apps/storefront/src/lib/webhooks/deliveryStore.ts +668 -0
  117. package/apps/storefront/src/lib/webhooks/dispatcher.ts +168 -0
  118. package/apps/storefront/src/lib/webhooks/emit.ts +167 -0
  119. package/apps/storefront/src/lib/webhooks/endpointGuard.ts +135 -0
  120. package/apps/storefront/src/lib/webhooks/events.ts +98 -0
  121. package/apps/storefront/src/lib/webhooks/getDispatcher.ts +49 -0
  122. package/apps/storefront/src/lib/webhooks/signing.ts +29 -0
  123. package/apps/storefront/src/lib/webhooks/webhookSigningKey.ts +146 -0
  124. package/apps/storefront/src/middleware/index.ts +28 -13
  125. package/apps/storefront/src/pages/404.astro +21 -9
  126. package/apps/storefront/src/pages/[...slug].astro +36 -2
  127. package/apps/storefront/src/pages/admin.astro +29 -3
  128. package/apps/storefront/src/pages/api/apps/admin/credentials/rotate.ts +60 -0
  129. package/apps/storefront/src/pages/api/apps/admin/health.ts +44 -0
  130. package/apps/storefront/src/pages/api/apps/admin/install.ts +100 -0
  131. package/apps/storefront/src/pages/api/apps/admin/list.ts +26 -0
  132. package/apps/storefront/src/pages/api/apps/admin/resume.ts +56 -0
  133. package/apps/storefront/src/pages/api/apps/admin/suspend.ts +57 -0
  134. package/apps/storefront/src/pages/api/apps/admin/uninstall.ts +74 -0
  135. package/apps/storefront/src/pages/api/apps/admin/update.ts +103 -0
  136. package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries/[deliveryId]/replay.ts +59 -0
  137. package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries.ts +51 -0
  138. package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +172 -0
  139. package/apps/storefront/src/pages/api/apps/oauth/token.ts +87 -0
  140. package/apps/storefront/src/pages/api/apps/v1/attribution.ts +142 -0
  141. package/apps/storefront/src/pages/api/apps/v1/catalog/products/[handle].ts +39 -0
  142. package/apps/storefront/src/pages/api/apps/v1/catalog/products.ts +49 -0
  143. package/apps/storefront/src/pages/api/apps/v1/health.ts +32 -0
  144. package/apps/storefront/src/pages/api/apps/v1/inventory.ts +59 -0
  145. package/apps/storefront/src/pages/api/apps/v1/orders/[id].ts +48 -0
  146. package/apps/storefront/src/pages/api/apps/v1/orders.ts +73 -0
  147. package/apps/storefront/src/pages/api/apps/v1/reports.ts +21 -0
  148. package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries/[deliveryId]/replay.ts +62 -0
  149. package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries.ts +47 -0
  150. package/apps/storefront/src/pages/api/auth/magic-exchange.ts +48 -1
  151. package/apps/storefront/src/pages/api/auth/step-up-send.ts +57 -0
  152. package/apps/storefront/src/pages/api/auth/step-up-verify.ts +129 -0
  153. package/apps/storefront/src/pages/api/auth/verify.ts +23 -0
  154. package/apps/storefront/src/pages/api/compliance/preflight.ts +206 -0
  155. package/apps/storefront/src/pages/api/rum/vitals.ts +54 -0
  156. package/apps/storefront/src/pages/api/test/dev-session.ts +133 -0
  157. package/apps/storefront/src/pages/auth/login.astro +197 -41
  158. package/apps/storefront/src/pages/auth/magic.astro +75 -43
  159. package/apps/storefront/src/pages/blog/[slug].astro +107 -0
  160. package/apps/storefront/src/pages/blog/index.astro +98 -0
  161. package/apps/storefront/src/pages/capabilities.astro +8 -0
  162. package/apps/storefront/src/pages/cockpit.astro +496 -74
  163. package/apps/storefront/src/pages/collections/[handle].astro +8 -0
  164. package/apps/storefront/src/pages/collections/index.astro +10 -2
  165. package/apps/storefront/src/pages/dashboard/[appDomain]/apps/index.astro +119 -0
  166. package/apps/storefront/src/pages/dashboard/[appDomain]/index.astro +5 -0
  167. package/apps/storefront/src/pages/index.astro +57 -0
  168. package/apps/storefront/src/pages/llms.txt.ts +31 -10
  169. package/apps/storefront/src/pages/products/[handle].astro +100 -9
  170. package/apps/storefront/src/pages/sitemap.xml.ts +21 -4
  171. package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +198 -0
  172. package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +7 -0
  173. package/apps/storefront/src/pages/style-guide/[tenant]/guide/[theme].astro +7 -0
  174. package/apps/storefront/src/pages/style-guide/[tenant]/index.astro +7 -0
  175. package/apps/storefront/src/pages/style-guide/index.astro +10 -0
  176. package/apps/storefront/src/styles/fonts.css +54 -0
  177. package/apps/storefront/src/styles/global.css +22 -2
  178. package/apps/storefront/src/themes/schema.ts +3 -25
  179. package/apps/storefront/tsconfig.json +1 -1
  180. package/apps/storefront/vitest.config.ts +4 -1
  181. package/package.json +1 -1
  182. package/packages/public-runtime/src/candidate-index.ts +311 -0
  183. package/packages/public-runtime/src/checkout.ts +94 -2
  184. package/packages/public-runtime/src/compliance/evaluate.ts +265 -0
  185. package/packages/public-runtime/src/compliance/evidence-signals.ts +81 -0
  186. package/packages/public-runtime/src/compliance/index.ts +22 -0
  187. package/packages/public-runtime/src/compliance/pact-report.ts +94 -0
  188. package/packages/public-runtime/src/compliance/profile.ts +198 -0
  189. package/packages/public-runtime/src/compliance/ruleset.ts +117 -0
  190. package/packages/public-runtime/src/compliance/verification.ts +81 -0
  191. package/packages/public-runtime/src/csp.ts +27 -3
  192. package/packages/public-runtime/src/customization-reconcile.ts +35 -0
  193. package/packages/public-runtime/src/customization-runtime.ts +8 -0
  194. package/packages/public-runtime/src/customization-versioning.ts +17 -0
  195. package/packages/public-runtime/src/extension-contract.ts +2 -1
  196. package/packages/public-runtime/src/hash.ts +25 -0
  197. package/packages/public-runtime/src/index.ts +6 -0
  198. package/packages/public-runtime/src/membership.ts +353 -0
  199. package/packages/public-runtime/src/product.ts +24 -2
  200. package/packages/public-runtime/src/review-trust-proof.ts +194 -0
  201. package/packages/public-runtime/src/tenant-assets.ts +40 -5
  202. package/packages/public-runtime/src/tenant.ts +236 -0
  203. package/packages/public-runtime/src/widget-postmessage.ts +205 -0
  204. package/scripts/dev/publish.mjs +158 -0
  205. package/scripts/dev/transient-files.mjs +2 -1
  206. package/tenants/home/public/fonts/inter-latin-400-normal.woff2 +0 -0
  207. package/tenants/home/public/fonts/inter-latin-500-normal.woff2 +0 -0
  208. package/tenants/home/public/fonts/inter-latin-600-normal.woff2 +0 -0
  209. package/tenants/home/public/fonts/inter-latin-ext-400-normal.woff2 +0 -0
  210. package/tenants/home/public/fonts/inter-latin-ext-500-normal.woff2 +0 -0
  211. package/tenants/home/public/fonts/inter-latin-ext-600-normal.woff2 +0 -0
  212. package/tenants/home/public/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  213. package/tenants/home/public/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
  214. package/tenants/home/public/fonts/jetbrains-mono-latin-ext-400-normal.woff2 +0 -0
  215. package/tenants/home/public/fonts/jetbrains-mono-latin-ext-500-normal.woff2 +0 -0
  216. package/tenants/home/public/fonts/plus-jakarta-sans-latin-500-normal.woff2 +0 -0
  217. package/tenants/home/public/fonts/plus-jakarta-sans-latin-600-normal.woff2 +0 -0
  218. package/tenants/home/public/fonts/plus-jakarta-sans-latin-700-normal.woff2 +0 -0
  219. package/tenants/home/public/fonts/plus-jakarta-sans-latin-800-normal.woff2 +0 -0
  220. package/tenants/home/public/fonts/plus-jakarta-sans-latin-ext-500-normal.woff2 +0 -0
  221. package/tenants/home/public/fonts/plus-jakarta-sans-latin-ext-600-normal.woff2 +0 -0
  222. package/tenants/home/public/fonts/plus-jakarta-sans-latin-ext-700-normal.woff2 +0 -0
  223. package/tenants/home/public/fonts/plus-jakarta-sans-latin-ext-800-normal.woff2 +0 -0
  224. package/tenants/home/public/pages/storefront.css +23 -0
  225. package/apps/storefront/src/lib/dev/hostedCockpit.ts +0 -169
@@ -0,0 +1,221 @@
1
+ /* ============================================================================
2
+ Shared commerce-MARKETING stylesheet — the raw-marketing-fragment page layer
3
+ (go-live workstream, unit F5 `shared-css-layer`). Companion to
4
+ /shared/commerce-chrome.css (unit F2): chrome styles the SITE FRAME (header,
5
+ nav, footer, announcement, age gate); THIS sheet styles the RAW MARKETING PAGE
6
+ BODY patterns a hybrid commerce tenant repeats across its static content pages
7
+ (about / contact / policy / compliance / membership): page hero, breadcrumbs,
8
+ eyebrow, prose, needs-review + illustrative callouts, TOC chips, value grid,
9
+ contact form, membership tier cards / comparison table, how-it-works, FAQ, and
10
+ the closing CTA band.
11
+
12
+ WHY (spec §F5): "page-local CSS in every tenant file is not maintainable." Every
13
+ sample-store.com content page shipped a ~90–290-line <style> block that was
14
+ ~80% byte-identical page-to-page (the `.container`/`.section`/`.page-hero`/
15
+ `.crumbs`/`.eyebrow`/`.needs-review`/`.nr`/`.prose` core repeated verbatim), so a
16
+ copy drifted the moment one page was edited. This lifts the framework-generic
17
+ patterns into ONE platform-shipped sheet a page LINKS; the tenant pages keep
18
+ little or no page-local CSS (acceptance: "Hybrid tenant pages need little or no
19
+ page-local CSS for standard patterns").
20
+
21
+ OPT-IN, not automatic. A tenant links this only when its chrome.json sets
22
+ `sharedMarketingCss: true` (see lib/rawChrome.ts SHARED_MARKETING_STYLESHEET) —
23
+ the same deliberate-adoption gate `sharedChrome` uses, so a SHIPPED tenant that
24
+ already hand-authored its own page CSS (e.g. sample-store-2's tenant-scoped
25
+ /tenants/sample-store-2.net/pages/page.css, which reuses names like `.cta-band` /
26
+ `.sec-head` with DIFFERENT semantics) never silently flips until its integration
27
+ unit reconciles. Linked AFTER commerce-chrome.css so its page-level `.sec-head`
28
+ variant intentionally wins over chrome's centered home-section `.sec-head`.
29
+
30
+ CONTRACT-TOKEN-ONLY (docs/architecture/token-contract.md, unit F1) — enforced by
31
+ commerce-marketing.contract.test.ts, same gate as the chrome sheet. Every value
32
+ reads the shared `--color-*` / `--font-*` / `--radius-*` / `--shadow-*` /
33
+ `--container-max` vocabulary and NO tenant-private brand var (never `--brand-red`,
34
+ `--brand-blue`, `--ink`/`--ink-2`, `--surface`, `--accent`, `--container`,
35
+ `--radius`) and no hard-coded brand hex. The retired page <style> blocks mixed
36
+ PVC-private vars with the contract; this normalizes them:
37
+ --container -> (dropped; chrome owns .container via --container-max)
38
+ --surface / --surface-2 -> --color-surface / --color-surface-2
39
+ --bg -> --color-bg
40
+ --border -> --color-border
41
+ --ink / --ink-2 -> --color-text (contract has ONE body/heading ink)
42
+ --muted -> --color-muted
43
+ --brand-blue -> --color-accent (PVC secondary brand / links)
44
+ --accent (amber fill) -> semantic tint: --color-info (illustrative note) /
45
+ --color-warning (compliance + needs-review flag) mixed
46
+ over --color-surface, so the callout is token-driven
47
+ and AA without a solid-fill contrast token
48
+ --accent-ink -> --color-warning (needs-review badge/icon)
49
+ --radius -> --radius-md
50
+ .cta-band pale-blue-band/white/hairline -> --color-text ground +
51
+ --color-primary-contrast text via color-mix (mirrors
52
+ the chrome footer's on-dark derivation; this removed
53
+ the only hard-coded hex the page blocks carried).
54
+ Tenant colour/type stays 100% token-driven: a tenant reskins every pattern here
55
+ by supplying tokens/aliases — nothing PVC-specific is baked in.
56
+
57
+ CSP: this is a LINKED same-origin sheet (style-src 'self'), so it needs no nonce
58
+ and does not weaken policy — strictly better than the nonce-stamped inline
59
+ <style> blocks it replaces (rawMarketingHtml.nonceInlineTags).
60
+
61
+ DELIVERY: platform static asset served at /shared/commerce-marketing.css (root,
62
+ global — like /shared/commerce-chrome.css). prefixTenantLinks exempts /shared/
63
+ so the link survives path-prefix tenant routing.
64
+ ========================================================================== */
65
+
66
+ /* --- Page shell ----------------------------------------------------------- */
67
+ /* .container / .section / .section--surface are owned by commerce-chrome.css and
68
+ NOT redefined here. Raw fragments use <main id="main"> as the page-body root. */
69
+ #main { display: block; }
70
+
71
+ /* --- Page hero (policy / marketing subpage header) ------------------------ */
72
+ .page-hero { background: linear-gradient(180deg, var(--color-surface-2), var(--color-bg)); border-bottom: 1px solid var(--color-border); }
73
+ .page-hero h1 { max-width: 22ch; }
74
+ .page-hero .lede { margin-top: 12px; font-size: 1.1rem; max-width: 64ch; color: var(--color-muted); }
75
+ .page-hero p { margin-top: 10px; max-width: 62ch; color: var(--color-muted); }
76
+
77
+ /* --- Breadcrumbs + eyebrow ------------------------------------------------ */
78
+ .crumbs { font-size: .82rem; color: var(--color-muted); margin-bottom: 14px; }
79
+ .crumbs a { color: var(--color-accent); }
80
+ .eyebrow { display: inline-block; font-family: var(--font-display); font-weight: 700; font-size: .76rem; letter-spacing: .12em; text-transform: uppercase; color: var(--color-accent); margin-bottom: .5rem; }
81
+
82
+ /* --- Section heads (marketing-page variant) -------------------------------
83
+ Distinct from chrome's centered home-section .sec-head: left by default, with a
84
+ --center modifier. Loaded after the chrome sheet, so these win for pages that
85
+ link this layer; the eyebrow inside is re-tinted to --color-accent to match the
86
+ standalone .eyebrow (chrome scopes .sec-head .eyebrow to --color-primary). */
87
+ .sec-head { max-width: 60ch; margin: 0 0 clamp(1.5rem, 3vw, 2.25rem); text-align: left; }
88
+ .sec-head--center { max-width: 62ch; margin-inline: auto; text-align: center; }
89
+ .sec-head h2 { font-size: clamp(1.5rem, 3vw, 2.15rem); }
90
+ .sec-head p { margin-top: .5rem; color: var(--color-muted); }
91
+ .sec-head .eyebrow { color: var(--color-accent); }
92
+
93
+ /* --- Prose (policy / long-form copy) -------------------------------------- */
94
+ .prose { max-width: 76ch; }
95
+ .prose h2 { font-size: clamp(1.35rem, 2.4vw, 1.8rem); margin-top: 2rem; scroll-margin-top: 90px; }
96
+ .prose p { margin-top: .7rem; color: var(--color-text); }
97
+ .prose ul { margin-top: .7rem; padding-left: 1.2rem; display: flex; flex-direction: column; gap: .45rem; }
98
+ .prose li { list-style: disc; color: var(--color-text); }
99
+ .prose a { color: var(--color-accent); }
100
+
101
+ /* --- Callouts ------------------------------------------------------------- */
102
+ /* Illustrative / informational note (e.g. "illustrative demo — figures unconfirmed").
103
+ Info-tinted over surface with --color-text so it is AA without needing a
104
+ solid-fill-with-contrast token; the old solid amber fill had no contract slot. */
105
+ .disclaimer { display: flex; gap: 10px; align-items: flex-start; margin-top: 22px; padding: 12px 16px; background: color-mix(in srgb, var(--color-info) 10%, var(--color-surface)); border: 1px solid color-mix(in srgb, var(--color-info) 32%, var(--color-border)); color: var(--color-text); border-radius: var(--radius-md); font-size: .86rem; font-weight: 600; max-width: 70ch; }
106
+ .disclaimer svg { flex: none; width: 18px; height: 18px; stroke: var(--color-info); fill: none; stroke-width: 2; margin-top: 1px; }
107
+
108
+ /* Compliance warning band (prominent, warning-toned). */
109
+ .warn-band { display: flex; gap: 10px; align-items: flex-start; margin-top: 20px; padding: 12px 16px; background: color-mix(in srgb, var(--color-warning) 12%, var(--color-surface)); border: 1px solid color-mix(in srgb, var(--color-warning) 40%, var(--color-border)); border-left: 4px solid var(--color-warning); color: var(--color-text); border-radius: var(--radius-md); font-size: .86rem; font-weight: 700; max-width: 76ch; }
110
+ .warn-band svg { flex: none; width: 18px; height: 18px; stroke: var(--color-warning); fill: none; stroke-width: 2; margin-top: 1px; }
111
+
112
+ /* Needs-review flag: source content pending confirmation (never fabricated proof). */
113
+ .needs-review { display: flex; gap: 10px; align-items: flex-start; margin-top: 20px; padding: 12px 16px; background: var(--color-surface); border: 1px solid var(--color-border); border-left: 4px solid var(--color-warning); border-radius: var(--radius-md); font-size: .86rem; color: var(--color-text); max-width: 76ch; }
114
+ .needs-review svg { flex: none; width: 18px; height: 18px; stroke: var(--color-warning); fill: none; stroke-width: 2; margin-top: 1px; }
115
+ .nr { display: inline-block; font-size: .6rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--color-warning); background: var(--color-surface-2); border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 1px 5px; vertical-align: middle; margin-left: 4px; }
116
+
117
+ /* --- Table-of-contents chips (long policy pages) -------------------------- */
118
+ .toc { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
119
+ .toc a { font-size: .82rem; font-weight: 600; color: var(--color-accent); border: 1px solid var(--color-border); border-radius: var(--radius-full); padding: 6px 12px; background: var(--color-surface); }
120
+ .toc a:hover { border-color: var(--color-accent); text-decoration: none; }
121
+
122
+ /* --- Value / feature card grid (about) ------------------------------------ */
123
+ .val-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 2vw, 20px); margin-top: 1.4rem; }
124
+ .val-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 22px; }
125
+ .val-card h3 { font-size: 1.05rem; }
126
+ .val-card p { margin-top: .5rem; color: var(--color-text); font-size: .92rem; }
127
+
128
+ /* --- Contact: info column + form ------------------------------------------ */
129
+ .contact-cols { display: grid; grid-template-columns: 1fr 1.2fr; gap: clamp(20px, 4vw, 48px); align-items: start; }
130
+ .contact-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 20px; margin-bottom: 14px; }
131
+ .contact-card h3 { font-size: 1.05rem; }
132
+ .contact-card p { margin-top: .4rem; color: var(--color-text); font-size: .92rem; }
133
+ .contact-card a { color: var(--color-accent); }
134
+ .contact-form { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 24px; display: flex; flex-direction: column; gap: 12px; }
135
+ .contact-form h2 { font-size: 1.25rem; margin-bottom: 4px; }
136
+ .contact-form .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
137
+ .contact-form input, .contact-form textarea { width: 100%; border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 11px 13px; font: inherit; font-size: .92rem; background: var(--color-surface); color: var(--color-text); }
138
+ .contact-form input::placeholder, .contact-form textarea::placeholder { color: var(--color-muted); }
139
+ .contact-form textarea { min-height: 120px; resize: vertical; }
140
+ .contact-form .attest { display: flex; gap: 8px; align-items: flex-start; font-size: .8rem; color: var(--color-muted); }
141
+ .contact-form .attest input { width: auto; margin-top: 3px; }
142
+ .contact-form .btn { align-self: flex-start; }
143
+
144
+ /* --- Membership tier cards (mirrors components/membership/TierCards.astro) --
145
+ Illustrative figures carry an "e.g." affordance + data-illustrative hooks in the
146
+ markup; this sheet is presentational only. */
147
+ .tier-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 2vw, 24px); align-items: stretch; }
148
+ .tier-card { position: relative; display: flex; flex-direction: column; background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 26px 22px; }
149
+ .tier-card--featured { border: 2px solid var(--color-primary); box-shadow: var(--shadow-md); }
150
+ .tier-badge { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: var(--color-primary); color: var(--color-primary-contrast); font-size: .65rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; padding: 4px 12px; border-radius: var(--radius-full); white-space: nowrap; }
151
+ .tier-card h3 { font-size: 1.15rem; color: var(--color-text); }
152
+ .tier-tagline { margin-top: 4px; font-size: .88rem; color: var(--color-muted); }
153
+ .tier-figure { margin-top: 16px; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; color: var(--color-text); }
154
+ .tier-figure-val { font-family: var(--font-display); font-size: 1.9rem; font-weight: 800; line-height: 1; }
155
+ .tier-figure-cap { font-size: .84rem; color: var(--color-muted); }
156
+ .tier-eg { font-size: .72rem; font-weight: 500; color: var(--color-muted); }
157
+ .tier-feats { margin-top: 20px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
158
+ .tier-feats li { display: flex; gap: 10px; align-items: flex-start; font-size: .9rem; color: var(--color-text); }
159
+ .tier-feats li.is-no { color: var(--color-muted); }
160
+ .tier-feats li.is-no > span:last-child { text-decoration: line-through; }
161
+ .tier-feats .glyph { flex: none; margin-top: 1px; font-weight: 700; color: var(--color-success); }
162
+ .tier-feats li.is-no .glyph { color: var(--color-muted); }
163
+ .tier-cta { margin-top: 24px; width: 100%; }
164
+
165
+ /* --- Illustrative label (mirrors components/membership/IllustrativeLabel.astro) */
166
+ .illus-badge-wrap { margin-top: 14px; }
167
+ .illus-badge { display: inline-flex; align-items: center; gap: 5px; border: 1px solid var(--color-info); color: var(--color-info); border-radius: var(--radius-full); padding: 2px 9px; font-size: .65rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
168
+ .illus-note { margin-top: 16px; text-align: center; font-size: .75rem; font-style: italic; color: var(--color-muted); }
169
+
170
+ /* --- Tier comparison table (mirrors components/membership/TierComparisonTable.astro) */
171
+ .cmp-wrap { overflow-x: auto; border: 1px solid var(--color-border); border-radius: var(--radius-lg); }
172
+ table.cmp { width: 100%; border-collapse: collapse; min-width: 640px; background: var(--color-surface); }
173
+ table.cmp th, table.cmp td { padding: 13px 16px; border-bottom: 1px solid var(--color-border); font-size: .9rem; vertical-align: middle; }
174
+ table.cmp tbody th[scope="row"] { text-align: left; color: var(--color-text); font-weight: 600; }
175
+ table.cmp thead th { text-align: center; background: var(--color-surface-2); vertical-align: bottom; }
176
+ table.cmp thead th:first-child { background: transparent; }
177
+ table.cmp td { text-align: center; color: var(--color-text); }
178
+ .cmp-tier { display: block; font-family: var(--font-display); font-size: .95rem; font-weight: 700; color: var(--color-text); }
179
+ .col-feat .cmp-tier { color: var(--color-primary); }
180
+ .cmp-fig { display: block; margin-top: 2px; font-size: .72rem; font-weight: 500; color: var(--color-muted); }
181
+ .cell-yes { color: var(--color-success); font-weight: 700; }
182
+ .cell-no { color: var(--color-muted); }
183
+
184
+ /* --- How it works --------------------------------------------------------- */
185
+ .how-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(14px, 2vw, 22px); }
186
+ .how-card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 24px; }
187
+ .how-card h3 { font-size: 1.15rem; }
188
+ .how-card ol { margin-top: 12px; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
189
+ .how-card ol li { color: var(--color-text); font-size: .92rem; list-style: decimal; }
190
+
191
+ /* --- FAQ (native <details> accordion) ------------------------------------- */
192
+ .faq { display: flex; flex-direction: column; gap: 10px; max-width: 780px; }
193
+ .faq details { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); }
194
+ .faq summary { cursor: pointer; padding: 15px 18px; font-weight: 600; color: var(--color-text); list-style: none; display: flex; justify-content: space-between; gap: 12px; }
195
+ .faq summary::-webkit-details-marker { display: none; }
196
+ .faq summary::after { content: "+"; color: var(--color-accent); font-weight: 700; }
197
+ .faq details[open] summary::after { content: "\2013"; }
198
+ .faq details > p { padding: 0 18px 16px; color: var(--color-text); font-size: .92rem; }
199
+
200
+ /* --- Closing CTA band (on-dark, mirrors chrome footer's token derivation) --- */
201
+ .cta-band { background: var(--color-text); color: color-mix(in srgb, var(--color-primary-contrast) 82%, transparent); border-radius: var(--radius-lg); padding: clamp(28px, 4vw, 44px); text-align: center; }
202
+ .cta-band h2 { color: var(--color-primary-contrast); }
203
+ .cta-band p { color: color-mix(in srgb, var(--color-primary-contrast) 82%, transparent); margin-top: 8px; max-width: 52ch; margin-inline: auto; }
204
+ .cta-band .cta-actions { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin-top: 22px; }
205
+
206
+ /* --- CTA / button helpers (class-based, never inline style) --------------- */
207
+ /* Button base + variants (.btn / .btn-primary / .btn-secondary / .btn-outline)
208
+ live in commerce-chrome.css + the tenant theme; these are marketing-page layout
209
+ helpers on top of them. */
210
+ .btn.mt { margin-top: 1.6rem; }
211
+
212
+ /* --- Responsive ----------------------------------------------------------- */
213
+ @media (max-width: 860px) {
214
+ .tier-grid { grid-template-columns: 1fr; }
215
+ .how-grid { grid-template-columns: 1fr; }
216
+ }
217
+ @media (max-width: 780px) {
218
+ .val-grid { grid-template-columns: 1fr; }
219
+ .contact-cols { grid-template-columns: 1fr; }
220
+ .contact-form .row2 { grid-template-columns: 1fr; }
221
+ }
@@ -20,6 +20,7 @@ const image = collection.image;
20
20
 
21
21
  <a
22
22
  href={withBase(basePath, `/collections/${collection.handle}`)}
23
+ data-astro-prefetch
23
24
  class="group relative block aspect-[3/2] overflow-hidden rounded-md bg-border"
24
25
  data-reveal
25
26
  >
@@ -188,6 +188,7 @@ const quickview = {
188
188
  <h3 class="mt-1 font-display text-[0.95rem] font-medium leading-snug">
189
189
  <a
190
190
  href={withBase(basePath, `/products/${product.handle}`)}
191
+ data-astro-prefetch
191
192
  class="after:absolute after:inset-0 after:z-0 transition-colors motion-safe:group-hover:text-primary"
192
193
  >
193
194
  {product.title}