@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,98 @@
1
+ ---
2
+ import Layout from "@/layouts/Layout.astro";
3
+ import { listBlogPosts } from "@/lib/blog/provider.js";
4
+
5
+ const { tenant, basePath, canonicalBase } = Astro.locals;
6
+ const posts = await listBlogPosts(tenant.tenant_id);
7
+ if (posts.length === 0) return new Response(null, { status: 404 });
8
+
9
+ const href = (path: string) => `${basePath}${path}` || "/";
10
+ const tags = [...new Set(posts.flatMap((post) => post.tags))].sort((a, b) => a.localeCompare(b));
11
+ const itemList = {
12
+ "@context": "https://schema.org",
13
+ "@type": "ItemList",
14
+ numberOfItems: posts.length,
15
+ itemListElement: posts.map((post, index) => ({
16
+ "@type": "ListItem",
17
+ position: index + 1,
18
+ name: post.title,
19
+ url: new URL(`/blog/${post.slug}/`, canonicalBase + "/").toString(),
20
+ })),
21
+ };
22
+ ---
23
+
24
+ <Layout
25
+ title="Blog"
26
+ description="Product updates, compliance news, and practical guidance from Token of Trust."
27
+ path="/blog/"
28
+ fullBleed
29
+ jsonLd={itemList}
30
+ >
31
+ <header class="blog-hero">
32
+ <div class="blog-shell">
33
+ <p class="eyebrow eyebrow--tick">Insights &amp; updates</p>
34
+ <h1>Token of Trust blog</h1>
35
+ <p>Practical guidance for identity, age assurance, fraud prevention, and regulated commerce.</p>
36
+ </div>
37
+ </header>
38
+
39
+ <div class="blog-shell blog-layout">
40
+ <aside aria-label="Blog topics">
41
+ <p class="filter-label">Explore topics</p>
42
+ <div class="tag-list">
43
+ {tags.map((tag) => <span>{tag}</span>)}
44
+ </div>
45
+ </aside>
46
+
47
+ <section class="post-grid" aria-label="Blog posts" id="blog-posts">
48
+ {posts.map((post, index) => (
49
+ <article class="post-card">
50
+ <a href={href(`/blog/${post.slug}/`)} aria-label={`Read ${post.title}`}>
51
+ {post.featuredImage ? (
52
+ <img
53
+ src={post.featuredImage.src}
54
+ alt={post.featuredImage.alt}
55
+ width={post.featuredImage.width}
56
+ height={post.featuredImage.height}
57
+ loading={index < 3 ? "eager" : "lazy"}
58
+ decoding="async"
59
+ />
60
+ ) : <div class="image-placeholder" aria-hidden="true"></div>}
61
+ <div class="post-card-copy">
62
+ <p class="post-meta"><time datetime={post.publishedAt}>{new Date(post.publishedAt).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" })}</time>{post.tags[0] && <> · {post.tags[0]}</>}</p>
63
+ <h2>{post.title}</h2>
64
+ <p>{post.excerpt}</p>
65
+ <span>Read article <span aria-hidden="true">→</span></span>
66
+ </div>
67
+ </a>
68
+ </article>
69
+ ))}
70
+ </section>
71
+ </div>
72
+ </Layout>
73
+
74
+ <style>
75
+ .blog-shell { width: min(1180px, calc(100% - 2rem)); margin-inline: auto; }
76
+ .blog-hero { padding: clamp(4.5rem, 9vw, 8rem) 0 clamp(3rem, 6vw, 5rem); background: linear-gradient(145deg, var(--color-primary), color-mix(in srgb, var(--color-primary) 82%, var(--color-accent))); color: var(--color-primary-contrast); }
77
+ .blog-hero h1 { max-width: 12ch; margin-top: .75rem; color: inherit; font-size: clamp(2.9rem, 7vw, 5.6rem); }
78
+ .blog-hero p:last-child { max-width: 58ch; margin-top: 1.25rem; color: color-mix(in srgb, var(--color-primary-contrast) 82%, transparent); font-size: 1.12rem; }
79
+ .blog-hero .eyebrow { color: color-mix(in srgb, var(--color-primary-contrast) 75%, transparent); }
80
+ .blog-layout { display: grid; grid-template-columns: 210px minmax(0, 1fr); gap: clamp(2rem, 5vw, 4rem); padding-block: clamp(3rem, 7vw, 6rem); }
81
+ aside { align-self: start; position: sticky; top: 7rem; }
82
+ .filter-label { margin-bottom: .85rem; font: 700 .76rem/1 var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--color-muted); }
83
+ .tag-list { display: flex; flex-direction: column; align-items: stretch; gap: .3rem; }
84
+ .tag-list span { padding: .45rem .7rem; border: 1px solid var(--color-border); border-radius: var(--radius-full); background: var(--color-surface); color: var(--color-muted); font-size: .76rem; }
85
+ .post-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.35rem; align-items: start; }
86
+ .post-card { height: 100%; overflow: hidden; border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); box-shadow: var(--shadow-sm); transition: transform .2s ease, box-shadow .2s ease; }
87
+ .post-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
88
+ .post-card a { display: flex; height: 100%; flex-direction: column; }
89
+ .post-card img, .image-placeholder { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: linear-gradient(135deg, color-mix(in srgb, var(--color-primary) 12%, white), color-mix(in srgb, var(--color-accent) 24%, white)); }
90
+ .post-card-copy { display: flex; flex: 1; flex-direction: column; padding: 1.25rem; }
91
+ .post-meta { margin: 0 0 .7rem; color: var(--color-muted); font: 600 .72rem/1.45 var(--font-mono); text-transform: uppercase; letter-spacing: .05em; }
92
+ .post-card h2 { font-size: 1.18rem; line-height: 1.25; }
93
+ .post-card-copy > p:not(.post-meta) { display: -webkit-box; margin: .75rem 0 1rem; overflow: hidden; color: var(--color-muted); font-size: .92rem; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
94
+ .post-card-copy > span { margin-top: auto; color: var(--color-accent-ink); font-weight: 700; font-size: .88rem; }
95
+ @media (max-width: 980px) { .post-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
96
+ @media (max-width: 720px) { .blog-layout { grid-template-columns: 1fr; } aside { position: static; } .tag-list { flex-direction: row; overflow-x: auto; padding-bottom: .4rem; } .tag-list button { flex: 0 0 auto; } }
97
+ @media (max-width: 520px) { .post-grid { grid-template-columns: 1fr; } }
98
+ </style>
@@ -9,7 +9,15 @@
9
9
  * toggle here would bypass the promote gate this whole design exists to enforce.
10
10
  * The console reflects the real per-environment resolved state (each column reads
11
11
  * the published capabilities artifact for its pointer) and makes the flow legible.
12
+ *
13
+ * DELIBERATELY on-demand — do NOT prerender (audit finding "selective-prerender").
14
+ * It resolves per-request against the running host: Astro.locals.tenant + cspNonce
15
+ * (from middleware), live/preview/test capability pointers read from TENANT_CACHE KV,
16
+ * and a host-based "you are here" marker. Prerendering would freeze one tenant's
17
+ * capability state at build time and strip the middleware CSP + security headers.
12
18
  */
19
+ export const prerender = false;
20
+
13
21
  import { readKv } from "@/lib/env";
14
22
  import {
15
23
  readPublishedArtifact,