@flamingo-stack/openframe-frontend-core 0.0.457 → 0.0.458-snapshot.20260720215024

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 (290) hide show
  1. package/dist/chat-protocol/decode.d.ts +58 -0
  2. package/dist/chat-protocol/decode.d.ts.map +1 -0
  3. package/dist/chat-protocol/encode.d.ts +44 -0
  4. package/dist/chat-protocol/encode.d.ts.map +1 -0
  5. package/dist/chat-protocol/env-flag.d.ts +35 -0
  6. package/dist/chat-protocol/env-flag.d.ts.map +1 -0
  7. package/dist/chat-protocol/events.d.ts +192 -0
  8. package/dist/chat-protocol/events.d.ts.map +1 -0
  9. package/dist/chat-protocol/frames.d.ts +206 -0
  10. package/dist/chat-protocol/frames.d.ts.map +1 -0
  11. package/dist/chat-protocol/index.cjs +493 -0
  12. package/dist/chat-protocol/index.cjs.map +1 -0
  13. package/dist/chat-protocol/index.d.ts +18 -0
  14. package/dist/chat-protocol/index.d.ts.map +1 -0
  15. package/dist/chat-protocol/index.js +477 -0
  16. package/dist/chat-protocol/index.js.map +1 -0
  17. package/dist/chat-protocol/ip-normalize.d.ts +44 -0
  18. package/dist/chat-protocol/ip-normalize.d.ts.map +1 -0
  19. package/dist/chat-protocol/nats-decoder.d.ts +26 -0
  20. package/dist/chat-protocol/nats-decoder.d.ts.map +1 -0
  21. package/dist/{chunk-SQ3CP2IV.cjs → chunk-3N3TMZ62.cjs} +7 -7
  22. package/dist/{chunk-SQ3CP2IV.cjs.map → chunk-3N3TMZ62.cjs.map} +1 -1
  23. package/dist/{chunk-I7M6KCCS.js → chunk-4R6H2U77.js} +4 -4
  24. package/dist/{chunk-CCT5VCRP.cjs → chunk-4XDWNAZW.cjs} +9 -9
  25. package/dist/{chunk-CCT5VCRP.cjs.map → chunk-4XDWNAZW.cjs.map} +1 -1
  26. package/dist/{chunk-KQ36EHE4.cjs → chunk-7KSEINAE.cjs} +15 -15
  27. package/dist/{chunk-KQ36EHE4.cjs.map → chunk-7KSEINAE.cjs.map} +1 -1
  28. package/dist/{chunk-FM5DTJPA.cjs → chunk-ADD3FPDG.cjs} +6851 -4713
  29. package/dist/chunk-ADD3FPDG.cjs.map +1 -0
  30. package/dist/{chunk-RSW42GTZ.js → chunk-APF5QBAU.js} +2 -2
  31. package/dist/{chunk-YCIVMKRS.cjs → chunk-BLZZXZNM.cjs} +26 -26
  32. package/dist/{chunk-YCIVMKRS.cjs.map → chunk-BLZZXZNM.cjs.map} +1 -1
  33. package/dist/{chunk-YHB4MNUX.cjs → chunk-BQ7PMWLM.cjs} +28 -27
  34. package/dist/chunk-BQ7PMWLM.cjs.map +1 -0
  35. package/dist/{chunk-GJ7BN4MI.js → chunk-CGNDAJ7V.js} +4 -4
  36. package/dist/{chunk-R5IQJXA3.js → chunk-F2NMWV44.js} +2 -2
  37. package/dist/{chunk-EOVQVVDJ.cjs → chunk-F7F43U7Q.cjs} +11 -11
  38. package/dist/{chunk-EOVQVVDJ.cjs.map → chunk-F7F43U7Q.cjs.map} +1 -1
  39. package/dist/{chunk-2ZW2ZPDW.js → chunk-LAOO7XHO.js} +2 -2
  40. package/dist/{chunk-O7F7RZFN.js → chunk-LJKZIIK4.js} +6 -5
  41. package/dist/chunk-LJKZIIK4.js.map +1 -0
  42. package/dist/{chunk-AJGZ3YSR.js → chunk-OR5AMXYN.js} +2 -2
  43. package/dist/{chunk-5XFJG3TC.cjs → chunk-P5JQDFRM.cjs} +60 -60
  44. package/dist/chunk-P5JQDFRM.cjs.map +1 -0
  45. package/dist/{chunk-U4APSAAR.cjs → chunk-PXZ7YQ5V.cjs} +5 -5
  46. package/dist/{chunk-U4APSAAR.cjs.map → chunk-PXZ7YQ5V.cjs.map} +1 -1
  47. package/dist/{chunk-WXDEMTLD.js → chunk-QO2XD3FR.js} +2 -2
  48. package/dist/{chunk-C2TDHJBO.cjs → chunk-QSGZE6AZ.cjs} +37 -37
  49. package/dist/{chunk-C2TDHJBO.cjs.map → chunk-QSGZE6AZ.cjs.map} +1 -1
  50. package/dist/{chunk-NSL5MNS4.js → chunk-REWRUV3K.js} +11644 -9506
  51. package/dist/chunk-REWRUV3K.js.map +1 -0
  52. package/dist/{chunk-BDTQIIJR.cjs → chunk-TA7MFVUS.cjs} +31 -31
  53. package/dist/{chunk-BDTQIIJR.cjs.map → chunk-TA7MFVUS.cjs.map} +1 -1
  54. package/dist/{chunk-4423DHRX.js → chunk-UI7CIUAR.js} +2 -2
  55. package/dist/{chunk-5BKBG653.js → chunk-VXJH5TDN.js} +10 -10
  56. package/dist/chunk-VXJH5TDN.js.map +1 -0
  57. package/dist/{chunk-AB65PWU2.cjs → chunk-WCE66C2Z.cjs} +62 -62
  58. package/dist/{chunk-AB65PWU2.cjs.map → chunk-WCE66C2Z.cjs.map} +1 -1
  59. package/dist/{chunk-KXIIUE75.js → chunk-XF5ROTMQ.js} +2 -2
  60. package/dist/components/case-studies/index.cjs +8 -8
  61. package/dist/components/case-studies/index.js +2 -2
  62. package/dist/components/chart.d.ts +1 -1
  63. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  64. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  65. package/dist/components/chat/hooks/index.d.ts +0 -1
  66. package/dist/components/chat/hooks/index.d.ts.map +1 -1
  67. package/dist/components/chat/hooks/use-chat.d.ts.map +1 -1
  68. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +15 -48
  69. package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
  70. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts +3 -47
  71. package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
  72. package/dist/components/chat/index.cjs +10 -2
  73. package/dist/components/chat/index.cjs.map +1 -1
  74. package/dist/components/chat/index.d.ts +1 -0
  75. package/dist/components/chat/index.d.ts.map +1 -1
  76. package/dist/components/chat/index.js +21 -13
  77. package/dist/components/chat/stream/chat-dialog-store.d.ts +184 -0
  78. package/dist/components/chat/stream/chat-dialog-store.d.ts.map +1 -0
  79. package/dist/components/chat/stream/chat-stream-reducer.d.ts +367 -0
  80. package/dist/components/chat/stream/chat-stream-reducer.d.ts.map +1 -0
  81. package/dist/components/chat/stream/delta-batcher.d.ts +51 -0
  82. package/dist/components/chat/stream/delta-batcher.d.ts.map +1 -0
  83. package/dist/components/chat/stream/index.d.ts +17 -0
  84. package/dist/components/chat/stream/index.d.ts.map +1 -0
  85. package/dist/components/chat/stream/message-mutations.d.ts +77 -0
  86. package/dist/components/chat/stream/message-mutations.d.ts.map +1 -0
  87. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts +22 -0
  88. package/dist/components/chat/stream/use-chat-stream-reducer.d.ts.map +1 -0
  89. package/dist/components/chat/types/api.types.d.ts +1 -81
  90. package/dist/components/chat/types/api.types.d.ts.map +1 -1
  91. package/dist/components/chat/types/processing.types.d.ts +2 -90
  92. package/dist/components/chat/types/processing.types.d.ts.map +1 -1
  93. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts +34 -6
  94. package/dist/components/chat/utils/extract-incomplete-message-state.d.ts.map +1 -1
  95. package/dist/components/chat/utils/index.d.ts +2 -3
  96. package/dist/components/chat/utils/index.d.ts.map +1 -1
  97. package/dist/components/chat/utils/process-historical-messages.d.ts +59 -11
  98. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  99. package/dist/components/contact/index.cjs +3 -3
  100. package/dist/components/contact/index.js +2 -2
  101. package/dist/components/docs/index.cjs +5 -5
  102. package/dist/components/docs/index.js +4 -4
  103. package/dist/components/embeds/index.cjs +3 -3
  104. package/dist/components/embeds/index.js +2 -2
  105. package/dist/components/faq/index.cjs +3 -3
  106. package/dist/components/faq/index.js +2 -2
  107. package/dist/components/features/index.cjs +2 -2
  108. package/dist/components/features/index.js +1 -1
  109. package/dist/components/features/time-tracker/time-tracker-panel.d.ts.map +1 -1
  110. package/dist/components/help-center-pages/index.cjs +20 -20
  111. package/dist/components/help-center-pages/index.js +11 -11
  112. package/dist/components/index.cjs +171 -129
  113. package/dist/components/index.cjs.map +1 -1
  114. package/dist/components/index.js +63 -21
  115. package/dist/components/index.js.map +1 -1
  116. package/dist/components/layout/page-container.d.ts.map +1 -1
  117. package/dist/components/navigation/index.cjs +2 -2
  118. package/dist/components/navigation/index.js +1 -1
  119. package/dist/components/onboarding-guides/index.cjs +5 -5
  120. package/dist/components/onboarding-guides/index.js +4 -4
  121. package/dist/components/onboarding-guides/onboarding-guide-detail-view.d.ts.map +1 -1
  122. package/dist/components/related-content/index.cjs +3 -3
  123. package/dist/components/related-content/index.js +2 -2
  124. package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
  125. package/dist/components/tickets/index.cjs +5 -5
  126. package/dist/components/tickets/index.js +4 -4
  127. package/dist/components/ui/index.cjs +44 -2
  128. package/dist/components/ui/index.cjs.map +1 -1
  129. package/dist/components/ui/index.d.ts +1 -2
  130. package/dist/components/ui/index.d.ts.map +1 -1
  131. package/dist/components/ui/index.js +55 -13
  132. package/dist/components/ui/markdown/base-components.d.ts +56 -0
  133. package/dist/components/ui/markdown/base-components.d.ts.map +1 -0
  134. package/dist/components/ui/markdown/engine.d.ts +99 -0
  135. package/dist/components/ui/markdown/engine.d.ts.map +1 -0
  136. package/dist/components/ui/markdown/heading-ids.d.ts +65 -0
  137. package/dist/components/ui/markdown/heading-ids.d.ts.map +1 -0
  138. package/dist/components/ui/markdown/index.d.ts +18 -0
  139. package/dist/components/ui/markdown/index.d.ts.map +1 -0
  140. package/dist/components/ui/markdown/mermaid-diagram.d.ts +79 -0
  141. package/dist/components/ui/markdown/mermaid-diagram.d.ts.map +1 -0
  142. package/dist/components/ui/markdown/rich/embed-overrides.d.ts +14 -0
  143. package/dist/components/ui/markdown/rich/embed-overrides.d.ts.map +1 -0
  144. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts +40 -0
  145. package/dist/components/ui/markdown/rich/rich-markdown-renderer.d.ts.map +1 -0
  146. package/dist/components/ui/markdown/rich/shortcodes.d.ts +8 -0
  147. package/dist/components/ui/markdown/rich/shortcodes.d.ts.map +1 -0
  148. package/dist/components/ui/markdown/sanitize.d.ts +153 -0
  149. package/dist/components/ui/markdown/sanitize.d.ts.map +1 -0
  150. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts +23 -0
  151. package/dist/components/ui/markdown/simple-markdown-renderer.d.ts.map +1 -0
  152. package/dist/components/ui/markdown/streaming.d.ts +78 -0
  153. package/dist/components/ui/markdown/streaming.d.ts.map +1 -0
  154. package/dist/components/ui/markdown/text-size.d.ts +34 -0
  155. package/dist/components/ui/markdown/text-size.d.ts.map +1 -0
  156. package/dist/components/ui/modal-v2.d.ts.map +1 -1
  157. package/dist/components/ui/modal.d.ts.map +1 -1
  158. package/dist/index.cjs +60 -2
  159. package/dist/index.cjs.map +1 -1
  160. package/dist/index.js +71 -13
  161. package/dist/utils/index.cjs +169 -40
  162. package/dist/utils/index.cjs.map +1 -1
  163. package/dist/utils/index.d.ts +1 -0
  164. package/dist/utils/index.d.ts.map +1 -1
  165. package/dist/utils/index.js +162 -41
  166. package/dist/utils/index.js.map +1 -1
  167. package/dist/utils/markdown-fences.d.ts +42 -0
  168. package/dist/utils/markdown-fences.d.ts.map +1 -0
  169. package/dist/utils/markdown-heading-id.d.ts +85 -0
  170. package/dist/utils/markdown-heading-id.d.ts.map +1 -0
  171. package/dist/utils/markdown-section-extractor.d.ts.map +1 -1
  172. package/package.json +7 -1
  173. package/src/chat-protocol/__tests__/__snapshots__/nats-decoder-golden.test.ts.snap +307 -0
  174. package/src/chat-protocol/__tests__/chat-protocol.test.ts +515 -0
  175. package/src/chat-protocol/__tests__/env-flag.test.ts +52 -0
  176. package/src/chat-protocol/__tests__/ip-normalize.test.ts +136 -0
  177. package/src/chat-protocol/__tests__/nats-decoder-golden.test.ts +228 -0
  178. package/src/chat-protocol/decode.ts +277 -0
  179. package/src/chat-protocol/encode.ts +71 -0
  180. package/src/chat-protocol/env-flag.ts +39 -0
  181. package/src/chat-protocol/events.ts +228 -0
  182. package/src/chat-protocol/frames.ts +238 -0
  183. package/src/chat-protocol/index.ts +21 -0
  184. package/src/chat-protocol/ip-normalize.ts +146 -0
  185. package/src/chat-protocol/nats-decoder.ts +252 -0
  186. package/src/components/chat/__tests__/chat-message-list.test.tsx +293 -5
  187. package/src/components/chat/__tests__/chat-message-streaming-memo.test.tsx +207 -0
  188. package/src/components/chat/__tests__/chat-pending-turn.test.tsx +209 -0
  189. package/src/components/chat/chat-message-enhanced.tsx +111 -17
  190. package/src/components/chat/chat-message-list.tsx +367 -113
  191. package/src/components/chat/embeddable-chat.tsx +6 -0
  192. package/src/components/chat/hooks/.index.md +1 -1
  193. package/src/components/chat/hooks/.use-nats-chat-adapter.md +1 -1
  194. package/src/components/chat/hooks/__tests__/__snapshots__/persisted-state-v1-golden.test.ts.snap +297 -0
  195. package/src/components/chat/hooks/__tests__/__snapshots__/sse-stream-golden.test.ts.snap +0 -0
  196. package/src/components/chat/hooks/__tests__/persisted-state-v1-golden.test.ts +272 -0
  197. package/src/components/chat/hooks/__tests__/sse-stream-golden.test.ts +318 -0
  198. package/src/components/chat/hooks/index.ts +0 -1
  199. package/src/components/chat/hooks/use-chat.ts +8 -0
  200. package/src/components/chat/hooks/use-nats-chat-adapter.ts +243 -822
  201. package/src/components/chat/hooks/use-sse-chat-adapter.ts +318 -666
  202. package/src/components/chat/index.ts +5 -0
  203. package/src/components/chat/stream/__tests__/__snapshots__/chat-stream-reducer-golden.test.ts.snap +937 -0
  204. package/src/components/chat/stream/__tests__/chat-dialog-store.test.ts +756 -0
  205. package/src/components/chat/stream/__tests__/chat-stream-reducer-golden.test.ts +460 -0
  206. package/src/components/chat/stream/__tests__/chat-stream-reducer.test.ts +894 -0
  207. package/src/components/chat/stream/__tests__/delta-batcher.test.ts +255 -0
  208. package/src/components/chat/stream/__tests__/use-chat-stream-reducer.test.ts +98 -0
  209. package/src/components/chat/stream/chat-dialog-store.ts +536 -0
  210. package/src/components/chat/stream/chat-stream-reducer.ts +1796 -0
  211. package/src/components/chat/stream/delta-batcher.ts +159 -0
  212. package/src/components/chat/stream/index.ts +55 -0
  213. package/src/components/chat/stream/message-mutations.ts +338 -0
  214. package/src/components/chat/stream/use-chat-stream-reducer.ts +126 -0
  215. package/src/components/chat/thinking-display.tsx +1 -1
  216. package/src/components/chat/types/.api.types.md +1 -3
  217. package/src/components/chat/types/.processing.types.md +6 -23
  218. package/src/components/chat/types/api.types.ts +6 -73
  219. package/src/components/chat/types/processing.types.ts +11 -52
  220. package/src/components/chat/utils/.index.md +0 -5
  221. package/src/components/chat/utils/__tests__/__snapshots__/process-historical-messages-golden.test.ts.snap +418 -0
  222. package/src/components/chat/utils/__tests__/__snapshots__/segment-accumulator-golden.test.ts.snap +599 -0
  223. package/src/components/chat/utils/__tests__/process-historical-messages-golden.test.ts +317 -0
  224. package/src/components/chat/utils/__tests__/segment-accumulator-golden.test.ts +270 -0
  225. package/src/components/chat/utils/extract-incomplete-message-state.ts +63 -5
  226. package/src/components/chat/utils/index.ts +5 -8
  227. package/src/components/chat/utils/process-historical-messages.ts +352 -383
  228. package/src/components/features/notifications/notification-drawer.tsx +4 -2
  229. package/src/components/features/time-tracker/time-tracker-panel.tsx +8 -2
  230. package/src/components/layout/page-container.tsx +5 -1
  231. package/src/components/onboarding-guides/onboarding-guide-detail-view.tsx +22 -4
  232. package/src/components/shared/legal-document/legal-document-page.tsx +1 -1
  233. package/src/components/shared/product-release/release-detail-page.tsx +19 -4
  234. package/src/components/ui/__tests__/__snapshots__/markdown-parity.test.tsx.snap +2420 -0
  235. package/src/components/ui/__tests__/markdown-parity.test.tsx +2528 -0
  236. package/src/components/ui/index.ts +1 -2
  237. package/src/components/ui/markdown/__tests__/mermaid-security.test.ts +115 -0
  238. package/src/components/ui/markdown/__tests__/mermaid-stale-render.test.tsx +95 -0
  239. package/src/components/ui/markdown/__tests__/sanitize-invariant.test.ts +309 -0
  240. package/src/components/ui/markdown/__tests__/streaming.test.tsx +388 -0
  241. package/src/components/ui/markdown/base-components.tsx +341 -0
  242. package/src/components/ui/markdown/engine.tsx +315 -0
  243. package/src/components/ui/markdown/heading-ids.ts +239 -0
  244. package/src/components/ui/markdown/index.ts +49 -0
  245. package/src/components/ui/markdown/mermaid-diagram.tsx +291 -0
  246. package/src/components/ui/markdown/rich/embed-overrides.tsx +199 -0
  247. package/src/components/ui/markdown/rich/rich-markdown-renderer.tsx +184 -0
  248. package/src/components/ui/markdown/rich/shortcodes.ts +170 -0
  249. package/src/components/ui/markdown/sanitize.ts +3499 -0
  250. package/src/components/ui/markdown/simple-markdown-renderer.tsx +28 -0
  251. package/src/components/ui/markdown/streaming.ts +362 -0
  252. package/src/components/ui/markdown/text-size.ts +106 -0
  253. package/src/components/ui/modal-v2.tsx +6 -0
  254. package/src/components/ui/modal.tsx +3 -0
  255. package/src/components/ui/release-changelog-section.tsx +1 -1
  256. package/src/components/ui/ticket-info-section.tsx +1 -1
  257. package/src/utils/index.ts +1 -0
  258. package/src/utils/markdown-fences.ts +127 -0
  259. package/src/utils/markdown-heading-id.ts +348 -0
  260. package/src/utils/markdown-section-extractor.ts +41 -56
  261. package/dist/chunk-5BKBG653.js.map +0 -1
  262. package/dist/chunk-5XFJG3TC.cjs.map +0 -1
  263. package/dist/chunk-FM5DTJPA.cjs.map +0 -1
  264. package/dist/chunk-NSL5MNS4.js.map +0 -1
  265. package/dist/chunk-O7F7RZFN.js.map +0 -1
  266. package/dist/chunk-YHB4MNUX.cjs.map +0 -1
  267. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts +0 -6
  268. package/dist/components/chat/hooks/use-realtime-chunk-processor.d.ts.map +0 -1
  269. package/dist/components/chat/utils/chunk-parser.d.ts +0 -25
  270. package/dist/components/chat/utils/chunk-parser.d.ts.map +0 -1
  271. package/dist/components/ui/rich-markdown-renderer.d.ts +0 -34
  272. package/dist/components/ui/rich-markdown-renderer.d.ts.map +0 -1
  273. package/dist/components/ui/simple-markdown-renderer.d.ts +0 -73
  274. package/dist/components/ui/simple-markdown-renderer.d.ts.map +0 -1
  275. package/src/components/chat/hooks/.use-realtime-chunk-processor.md +0 -50
  276. package/src/components/chat/hooks/use-realtime-chunk-processor.ts +0 -479
  277. package/src/components/chat/utils/.chunk-parser.md +0 -51
  278. package/src/components/chat/utils/chunk-parser.ts +0 -255
  279. package/src/components/ui/.simple-markdown-renderer.md +0 -40
  280. package/src/components/ui/rich-markdown-renderer.tsx +0 -1223
  281. package/src/components/ui/simple-markdown-renderer.tsx +0 -965
  282. /package/dist/{chunk-I7M6KCCS.js.map → chunk-4R6H2U77.js.map} +0 -0
  283. /package/dist/{chunk-RSW42GTZ.js.map → chunk-APF5QBAU.js.map} +0 -0
  284. /package/dist/{chunk-GJ7BN4MI.js.map → chunk-CGNDAJ7V.js.map} +0 -0
  285. /package/dist/{chunk-R5IQJXA3.js.map → chunk-F2NMWV44.js.map} +0 -0
  286. /package/dist/{chunk-2ZW2ZPDW.js.map → chunk-LAOO7XHO.js.map} +0 -0
  287. /package/dist/{chunk-AJGZ3YSR.js.map → chunk-OR5AMXYN.js.map} +0 -0
  288. /package/dist/{chunk-WXDEMTLD.js.map → chunk-QO2XD3FR.js.map} +0 -0
  289. /package/dist/{chunk-4423DHRX.js.map → chunk-UI7CIUAR.js.map} +0 -0
  290. /package/dist/{chunk-KXIIUE75.js.map → chunk-XF5ROTMQ.js.map} +0 -0
@@ -192,8 +192,10 @@ function DrawerScrollList({
192
192
  return (
193
193
  <OverlayScrollArea
194
194
  viewportRef={scrollRef}
195
- className="flex-1 min-h-0"
196
- contentClassName="flex flex-col gap-[var(--spacing-system-xs)] px-[var(--spacing-system-m)]"
195
+ // Horizontal padding lives on the host: OverlayScrollbars zeroes viewport
196
+ // padding, so `px-*` on `contentClassName` would be silently dropped.
197
+ className="flex-1 min-h-0 px-[var(--spacing-system-m)]"
198
+ contentClassName="flex flex-col gap-[var(--spacing-system-xs)]"
197
199
  >
198
200
  {isEmpty && !isLoadingMore ? (
199
201
  <EmptyState />
@@ -152,10 +152,16 @@ export function TimeTrackerPanel({
152
152
  return (
153
153
  <OverlayScrollArea
154
154
  className={cn(
155
- 'max-h-[calc(100vh-6rem)] w-full rounded-md border border-ods-border bg-ods-card',
155
+ // Padding lives on the host, NOT `contentClassName`: OverlayScrollbars
156
+ // forces `padding: 0` on the viewport, so padding on the scroller is
157
+ // silently dropped (see OverlayScrollArea docs).
158
+ 'max-h-[calc(100vh-6rem)] w-full rounded-md border border-ods-border bg-ods-card p-[var(--spacing-system-m)]',
156
159
  className,
157
160
  )}
158
- contentClassName="relative flex flex-col gap-[var(--spacing-system-l)] p-[var(--spacing-system-m)]"
161
+ // No `relative` here so the absolute close button anchors to the padded
162
+ // host (OverlayScrollArea's host is always relative) and keeps its inset
163
+ // from the card edge instead of from the padding box.
164
+ contentClassName="flex flex-col gap-[var(--spacing-system-l)]"
159
165
  >
160
166
  <Button
161
167
  variant="transparent"
@@ -411,7 +411,11 @@ function renderAdvancedPageContainer({
411
411
 
412
412
  {variant === 'detail' ? (
413
413
  // The only scrolling variant — standardized overlay scrollbar.
414
- <OverlayScrollArea className={getContentClasses()}>
414
+ // `contentClassName` is forwarded to BOTH layers: padding stays effective
415
+ // on the host, while layout (`flex flex-col gap-*`) reaches the scroller,
416
+ // the direct parent of the children (OverlayScrollbars zeroes viewport
417
+ // padding, so padding on the scroller alone would be dropped).
418
+ <OverlayScrollArea className={getContentClasses()} contentClassName={contentClassName}>
415
419
  {children}
416
420
  </OverlayScrollArea>
417
421
  ) : (
@@ -15,7 +15,7 @@
15
15
  * renderer with extra plugins.
16
16
  */
17
17
 
18
- import { type ComponentType, type ReactNode } from 'react'
18
+ import { Fragment, type ComponentType, type ReactNode } from 'react'
19
19
  import { PageLayout } from '../layout/page-layout'
20
20
 
21
21
  import { useRouter } from '../../embed-shims'
@@ -30,7 +30,7 @@ import { VideoBitesStrip } from '../features/video-bites-strip'
30
30
  import { toStripProfile } from '../features/video-bites-shared'
31
31
  import { useVideoWarmup } from '../features/use-video-warmup'
32
32
  import { getCaptionsUrl } from '../features/captions-url'
33
- import { RichMarkdownRenderer } from '../ui/rich-markdown-renderer'
33
+ import { RichMarkdownRenderer } from '../ui/markdown'
34
34
  import { EntityTagBadges } from '../features/entity-tag-badges'
35
35
  import { LoadError } from '../ui/error-state'
36
36
  import { ArticleAuthorByline } from '../shared/article-author-byline'
@@ -244,8 +244,26 @@ export function OnboardingGuideDetailView({
244
244
  </div>
245
245
  )}
246
246
 
247
- {/* Host slot — cross-type related-content / FAQ rail. */}
248
- {relatedContent}
247
+ {/*
248
+ * Host slot — cross-type related-content / FAQ rail.
249
+ *
250
+ * KEYED DELIBERATELY. This is one member of PageLayout's static children
251
+ * array, and the only member whose element may be created in a SERVER
252
+ * component and crossed over the RSC boundary. Static JSX children are
253
+ * normally exempt from the key warning because `jsxs` runs
254
+ * `validateChildKeys` and stamps `_store.validated = 1` on each element —
255
+ * but a slot arriving over the wire is referenced as a lazy chunk wrapper,
256
+ * so validation marks the WRAPPER and the fulfilled path never copies the
257
+ * flag onto the revived element. It reaches the reconciler with
258
+ * `validated: 0, key: null` and warns, blaming PageLayout (the owner of the
259
+ * enclosing element) rather than anything actually at fault.
260
+ *
261
+ * A keyed Fragment emits no DOM, so rendered output is byte-identical.
262
+ * Do NOT "fix" this in PageLayout via `React.Children.toArray` — that would
263
+ * auto-key every consumer's children and change reconciliation identity for
264
+ * all of them, and that file carries an explicit FROZEN contract.
265
+ */}
266
+ <Fragment key="related-content">{relatedContent}</Fragment>
249
267
  </PageLayout>
250
268
  )
251
269
  }
@@ -19,7 +19,7 @@
19
19
 
20
20
  import type { ComponentType } from 'react';
21
21
  import { PageShell, PageLayout } from '../../ui';
22
- import { RichMarkdownRenderer } from '../../ui/rich-markdown-renderer';
22
+ import { RichMarkdownRenderer } from '../../ui/markdown';
23
23
  import { useRouter } from '../../../embed-shims/next-navigation';
24
24
  import { useLegalDocs, type LegalDocument } from './use-legal-docs';
25
25
  import { formatLegalDate } from '../../../utils/format';
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useState, useEffect, ComponentType, type ReactNode } from 'react';
3
+ import { useState, useEffect, Fragment, ComponentType, type ReactNode } from 'react';
4
4
  import Link from '../../../embed-shims/next-link';
5
5
  import { useRouter } from '../../../embed-shims/next-navigation';
6
6
  import { Card, CardContent } from '../../ui/card';
@@ -11,7 +11,7 @@ import { PageShell } from '../../layout/article-detail-layout';
11
11
  import { PageLayout } from '../../layout/page-layout';
12
12
  import { FadePreview } from '../../ui/fade-preview';
13
13
  import { ReleaseChangelogSection } from '../../ui/release-changelog-section';
14
- import { RichMarkdownRenderer } from '../../ui/rich-markdown-renderer';
14
+ import { RichMarkdownRenderer } from '../../ui/markdown';
15
15
  import { EntityTagBadges } from '../../features/entity-tag-badges';
16
16
  import { EntityMetadataAuthorCell } from '../../chat/entity-cards/entity-author-card';
17
17
  import type { EntityAuthor } from '../../../types/entity-author';
@@ -582,8 +582,23 @@ export function ReleaseDetailPage({
582
582
  )}
583
583
  </div>
584
584
 
585
- {/* Host slot — end-of-article byline + related-content / FAQ rail. */}
586
- {relatedContent}
585
+ {/*
586
+ * Host slot — end-of-article byline + related-content / FAQ rail.
587
+ *
588
+ * KEYED for the same reason as `onboarding-guide-detail-view.tsx`: this is a
589
+ * member of PageLayout's static children array, and a slot element built in a
590
+ * SERVER component crosses the RSC boundary as a lazy chunk wrapper, so
591
+ * `validateChildKeys` marks the wrapper and the fulfilled path never copies
592
+ * `_store.validated` onto the revived element — it reaches the reconciler
593
+ * unvalidated and warns.
594
+ *
595
+ * Today the hub's only consumer of this view is a `'use client'` wrapper that
596
+ * builds the slot locally, so no element actually crosses the boundary and
597
+ * this is pre-emptive. It is kept because the trap is invisible from here: a
598
+ * future server-built slot would warn with no clue pointing at this line.
599
+ * A keyed Fragment emits no DOM, so output is byte-identical either way.
600
+ */}
601
+ <Fragment key="related-content">{relatedContent}</Fragment>
587
602
  </PageLayout>
588
603
  );
589
604
  }