@sonordev/agency-site-kit 0.3.1 → 0.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 (369) hide show
  1. package/README.md +302 -0
  2. package/bin/setup.mjs +79 -0
  3. package/dist/{chunk-RXBK2EOE.js → chunk-4IES23GV.js} +3 -3
  4. package/dist/{chunk-RXBK2EOE.js.map → chunk-4IES23GV.js.map} +1 -1
  5. package/dist/chunk-4N7ENJ7L.cjs +108 -0
  6. package/dist/chunk-4N7ENJ7L.cjs.map +1 -0
  7. package/dist/{chunk-WNR4KNG4.cjs → chunk-5MEZU3OG.cjs} +4 -4
  8. package/dist/{chunk-WNR4KNG4.cjs.map → chunk-5MEZU3OG.cjs.map} +1 -1
  9. package/dist/chunk-7ZHRMWJU.cjs +306 -0
  10. package/dist/chunk-7ZHRMWJU.cjs.map +1 -0
  11. package/dist/chunk-CVT7I5BQ.js +71 -0
  12. package/dist/chunk-CVT7I5BQ.js.map +1 -0
  13. package/dist/chunk-HQGAX2LI.cjs +8 -0
  14. package/dist/chunk-HQGAX2LI.cjs.map +1 -0
  15. package/dist/chunk-KXLROAO5.js +291 -0
  16. package/dist/chunk-KXLROAO5.js.map +1 -0
  17. package/dist/chunk-L4EOQVRJ.js +6 -0
  18. package/dist/chunk-L4EOQVRJ.js.map +1 -0
  19. package/dist/chunk-L7E3UHQC.cjs +535 -0
  20. package/dist/chunk-L7E3UHQC.cjs.map +1 -0
  21. package/dist/chunk-NI4FVCLS.cjs +32 -0
  22. package/dist/chunk-NI4FVCLS.cjs.map +1 -0
  23. package/dist/chunk-NIZJLONK.js +106 -0
  24. package/dist/chunk-NIZJLONK.js.map +1 -0
  25. package/dist/chunk-QDXZ27R7.js +33 -0
  26. package/dist/chunk-QDXZ27R7.js.map +1 -0
  27. package/dist/{chunk-TVFXN6W6.js → chunk-QL6KVIFR.js} +8 -4
  28. package/dist/chunk-QL6KVIFR.js.map +1 -0
  29. package/dist/chunk-UNTOEWQL.js +504 -0
  30. package/dist/chunk-UNTOEWQL.js.map +1 -0
  31. package/dist/chunk-XJ434N7I.js +30 -0
  32. package/dist/chunk-XJ434N7I.js.map +1 -0
  33. package/dist/chunk-XLK77USA.js +45 -0
  34. package/dist/chunk-XLK77USA.js.map +1 -0
  35. package/dist/{chunk-EE75WRCM.cjs → chunk-XOWSXZYW.cjs} +8 -4
  36. package/dist/chunk-XOWSXZYW.cjs.map +1 -0
  37. package/dist/chunk-ZINKVJQU.js +67 -0
  38. package/dist/chunk-ZINKVJQU.js.map +1 -0
  39. package/dist/index.cjs +29 -31
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +17 -9
  42. package/dist/index.d.ts +17 -9
  43. package/dist/index.js +7 -9
  44. package/dist/index.js.map +1 -1
  45. package/dist/layout/index.cjs +3 -3
  46. package/dist/layout/index.d.cts +1 -1
  47. package/dist/layout/index.d.ts +1 -1
  48. package/dist/layout/index.js +2 -2
  49. package/dist/portfolio/client.cjs +342 -12
  50. package/dist/portfolio/client.cjs.map +1 -1
  51. package/dist/portfolio/client.d.cts +11 -88
  52. package/dist/portfolio/client.d.ts +11 -88
  53. package/dist/portfolio/client.js +150 -4
  54. package/dist/portfolio/client.js.map +1 -1
  55. package/dist/portfolio/components/PortfolioAnalytics.cjs +87 -0
  56. package/dist/portfolio/components/PortfolioAnalytics.cjs.map +1 -0
  57. package/dist/portfolio/components/PortfolioAnalytics.d.cts +5 -0
  58. package/dist/portfolio/components/PortfolioAnalytics.d.ts +5 -0
  59. package/dist/portfolio/components/PortfolioAnalytics.js +9 -0
  60. package/dist/portfolio/components/PortfolioAnalytics.js.map +1 -0
  61. package/dist/portfolio/components/PortfolioErrorFallback.cjs +65 -0
  62. package/dist/portfolio/components/PortfolioErrorFallback.cjs.map +1 -0
  63. package/dist/portfolio/components/PortfolioErrorFallback.d.cts +22 -0
  64. package/dist/portfolio/components/PortfolioErrorFallback.d.ts +22 -0
  65. package/dist/portfolio/components/PortfolioErrorFallback.js +9 -0
  66. package/dist/portfolio/components/PortfolioErrorFallback.js.map +1 -0
  67. package/dist/portfolio/components/PortfolioLeadCTA.cjs +91 -0
  68. package/dist/portfolio/components/PortfolioLeadCTA.cjs.map +1 -0
  69. package/dist/portfolio/components/PortfolioLeadCTA.d.cts +34 -0
  70. package/dist/portfolio/components/PortfolioLeadCTA.d.ts +34 -0
  71. package/dist/portfolio/components/PortfolioLeadCTA.js +9 -0
  72. package/dist/portfolio/components/PortfolioLeadCTA.js.map +1 -0
  73. package/dist/portfolio/index.cjs +19 -20
  74. package/dist/portfolio/index.d.cts +133 -7
  75. package/dist/portfolio/index.d.ts +133 -7
  76. package/dist/portfolio/index.js +6 -7
  77. package/dist/portfolio/primitives/AnimatedCounter.cjs +88 -0
  78. package/dist/portfolio/primitives/AnimatedCounter.cjs.map +1 -0
  79. package/dist/portfolio/primitives/AnimatedCounter.d.cts +22 -0
  80. package/dist/portfolio/primitives/AnimatedCounter.d.ts +22 -0
  81. package/dist/portfolio/primitives/AnimatedCounter.js +68 -0
  82. package/dist/portfolio/primitives/AnimatedCounter.js.map +1 -0
  83. package/dist/portfolio/primitives/AnnotatedImage.cjs +320 -0
  84. package/dist/portfolio/primitives/AnnotatedImage.cjs.map +1 -0
  85. package/dist/portfolio/primitives/AnnotatedImage.d.cts +18 -0
  86. package/dist/portfolio/primitives/AnnotatedImage.d.ts +18 -0
  87. package/dist/portfolio/primitives/AnnotatedImage.js +264 -0
  88. package/dist/portfolio/primitives/AnnotatedImage.js.map +1 -0
  89. package/dist/portfolio/primitives/BeforeAfterSlider.cjs +348 -0
  90. package/dist/portfolio/primitives/BeforeAfterSlider.cjs.map +1 -0
  91. package/dist/portfolio/primitives/BeforeAfterSlider.d.cts +13 -0
  92. package/dist/portfolio/primitives/BeforeAfterSlider.d.ts +13 -0
  93. package/dist/portfolio/primitives/BeforeAfterSlider.js +292 -0
  94. package/dist/portfolio/primitives/BeforeAfterSlider.js.map +1 -0
  95. package/dist/portfolio/primitives/DeviceTrifolio.cjs +298 -0
  96. package/dist/portfolio/primitives/DeviceTrifolio.cjs.map +1 -0
  97. package/dist/portfolio/primitives/DeviceTrifolio.d.cts +14 -0
  98. package/dist/portfolio/primitives/DeviceTrifolio.d.ts +14 -0
  99. package/dist/portfolio/primitives/DeviceTrifolio.js +242 -0
  100. package/dist/portfolio/primitives/DeviceTrifolio.js.map +1 -0
  101. package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs +88 -0
  102. package/dist/portfolio/primitives/FrequencyBarSkeleton.cjs.map +1 -0
  103. package/dist/portfolio/primitives/FrequencyBarSkeleton.d.cts +10 -0
  104. package/dist/portfolio/primitives/FrequencyBarSkeleton.d.ts +10 -0
  105. package/dist/portfolio/primitives/FrequencyBarSkeleton.js +68 -0
  106. package/dist/portfolio/primitives/FrequencyBarSkeleton.js.map +1 -0
  107. package/dist/portfolio/primitives/GlassCard.cjs +45 -0
  108. package/dist/portfolio/primitives/GlassCard.cjs.map +1 -0
  109. package/dist/portfolio/primitives/GlassCard.d.cts +11 -0
  110. package/dist/portfolio/primitives/GlassCard.d.ts +11 -0
  111. package/dist/portfolio/primitives/GlassCard.js +43 -0
  112. package/dist/portfolio/primitives/GlassCard.js.map +1 -0
  113. package/dist/portfolio/primitives/MetricBadge.cjs +74 -0
  114. package/dist/portfolio/primitives/MetricBadge.cjs.map +1 -0
  115. package/dist/portfolio/primitives/MetricBadge.d.cts +9 -0
  116. package/dist/portfolio/primitives/MetricBadge.d.ts +9 -0
  117. package/dist/portfolio/primitives/MetricBadge.js +54 -0
  118. package/dist/portfolio/primitives/MetricBadge.js.map +1 -0
  119. package/dist/portfolio/primitives/SVGChart.cjs +316 -0
  120. package/dist/portfolio/primitives/SVGChart.cjs.map +1 -0
  121. package/dist/portfolio/primitives/SVGChart.d.cts +18 -0
  122. package/dist/portfolio/primitives/SVGChart.d.ts +18 -0
  123. package/dist/portfolio/primitives/SVGChart.js +296 -0
  124. package/dist/portfolio/primitives/SVGChart.js.map +1 -0
  125. package/dist/portfolio/primitives/ScrollReveal.cjs +97 -0
  126. package/dist/portfolio/primitives/ScrollReveal.cjs.map +1 -0
  127. package/dist/portfolio/primitives/ScrollReveal.d.cts +27 -0
  128. package/dist/portfolio/primitives/ScrollReveal.d.ts +27 -0
  129. package/dist/portfolio/primitives/ScrollReveal.js +77 -0
  130. package/dist/portfolio/primitives/ScrollReveal.js.map +1 -0
  131. package/dist/portfolio/primitives/SplitHeadline.cjs +107 -0
  132. package/dist/portfolio/primitives/SplitHeadline.cjs.map +1 -0
  133. package/dist/portfolio/primitives/SplitHeadline.d.cts +24 -0
  134. package/dist/portfolio/primitives/SplitHeadline.d.ts +24 -0
  135. package/dist/portfolio/primitives/SplitHeadline.js +87 -0
  136. package/dist/portfolio/primitives/SplitHeadline.js.map +1 -0
  137. package/dist/portfolio/sections/BeforeAfterSection.cjs +271 -0
  138. package/dist/portfolio/sections/BeforeAfterSection.cjs.map +1 -0
  139. package/dist/portfolio/sections/BeforeAfterSection.d.cts +9 -0
  140. package/dist/portfolio/sections/BeforeAfterSection.d.ts +9 -0
  141. package/dist/{BeforeAfterSection-6BHFLY4Y.js → portfolio/sections/BeforeAfterSection.js} +66 -27
  142. package/dist/portfolio/sections/BeforeAfterSection.js.map +1 -0
  143. package/dist/portfolio/sections/CTASection.cjs +123 -0
  144. package/dist/portfolio/sections/CTASection.cjs.map +1 -0
  145. package/dist/portfolio/sections/CTASection.d.cts +9 -0
  146. package/dist/portfolio/sections/CTASection.d.ts +9 -0
  147. package/dist/portfolio/sections/CTASection.js +93 -0
  148. package/dist/portfolio/sections/CTASection.js.map +1 -0
  149. package/dist/{ChallengesSection-IZ3DHECS.cjs → portfolio/sections/ChallengesSection.cjs} +12 -6
  150. package/dist/portfolio/sections/ChallengesSection.cjs.map +1 -0
  151. package/dist/portfolio/sections/ChallengesSection.d.cts +9 -0
  152. package/dist/portfolio/sections/ChallengesSection.d.ts +9 -0
  153. package/dist/{ChallengesSection-GEQGVSJN.js → portfolio/sections/ChallengesSection.js} +5 -4
  154. package/dist/portfolio/sections/ChallengesSection.js.map +1 -0
  155. package/dist/portfolio/sections/ConversionFunnelSection.cjs +263 -0
  156. package/dist/portfolio/sections/ConversionFunnelSection.cjs.map +1 -0
  157. package/dist/portfolio/sections/ConversionFunnelSection.d.cts +9 -0
  158. package/dist/portfolio/sections/ConversionFunnelSection.d.ts +9 -0
  159. package/dist/{ConversionFunnelSection-D3GE4NKE.js → portfolio/sections/ConversionFunnelSection.js} +60 -56
  160. package/dist/portfolio/sections/ConversionFunnelSection.js.map +1 -0
  161. package/dist/{DesignSystemSection-KXIQXITF.cjs → portfolio/sections/DesignSystemSection.cjs} +13 -7
  162. package/dist/portfolio/sections/DesignSystemSection.cjs.map +1 -0
  163. package/dist/portfolio/sections/DesignSystemSection.d.cts +32 -0
  164. package/dist/portfolio/sections/DesignSystemSection.d.ts +32 -0
  165. package/dist/{DesignSystemSection-2R5BRBGO.js → portfolio/sections/DesignSystemSection.js} +5 -4
  166. package/dist/portfolio/sections/DesignSystemSection.js.map +1 -0
  167. package/dist/{DetailsSection-TTUZAPZZ.cjs → portfolio/sections/DetailsSection.cjs} +12 -6
  168. package/dist/portfolio/sections/DetailsSection.cjs.map +1 -0
  169. package/dist/portfolio/sections/DetailsSection.d.cts +9 -0
  170. package/dist/portfolio/sections/DetailsSection.d.ts +9 -0
  171. package/dist/{DetailsSection-A6PZQUQL.js → portfolio/sections/DetailsSection.js} +5 -4
  172. package/dist/portfolio/sections/DetailsSection.js.map +1 -0
  173. package/dist/portfolio/sections/FeatureSpotlightSection.cjs +267 -0
  174. package/dist/portfolio/sections/FeatureSpotlightSection.cjs.map +1 -0
  175. package/dist/portfolio/sections/FeatureSpotlightSection.d.cts +9 -0
  176. package/dist/portfolio/sections/FeatureSpotlightSection.d.ts +9 -0
  177. package/dist/{FeatureSpotlightSection-B7P3JGNL.js → portfolio/sections/FeatureSpotlightSection.js} +39 -33
  178. package/dist/portfolio/sections/FeatureSpotlightSection.js.map +1 -0
  179. package/dist/portfolio/sections/GallerySection.cjs +321 -0
  180. package/dist/portfolio/sections/GallerySection.cjs.map +1 -0
  181. package/dist/portfolio/sections/GallerySection.d.cts +9 -0
  182. package/dist/portfolio/sections/GallerySection.d.ts +9 -0
  183. package/dist/{GallerySection-VMKORC47.js → portfolio/sections/GallerySection.js} +65 -18
  184. package/dist/portfolio/sections/GallerySection.js.map +1 -0
  185. package/dist/portfolio/sections/HeroSection.cjs +180 -0
  186. package/dist/portfolio/sections/HeroSection.cjs.map +1 -0
  187. package/dist/portfolio/sections/HeroSection.d.cts +15 -0
  188. package/dist/portfolio/sections/HeroSection.d.ts +15 -0
  189. package/dist/portfolio/sections/HeroSection.js +171 -0
  190. package/dist/portfolio/sections/HeroSection.js.map +1 -0
  191. package/dist/{MetricsTimelineSection-4L6DUHJ5.cjs → portfolio/sections/MetricsTimelineSection.cjs} +102 -61
  192. package/dist/portfolio/sections/MetricsTimelineSection.cjs.map +1 -0
  193. package/dist/portfolio/sections/MetricsTimelineSection.d.cts +9 -0
  194. package/dist/portfolio/sections/MetricsTimelineSection.d.ts +9 -0
  195. package/dist/{MetricsTimelineSection-6BT5GNFV.js → portfolio/sections/MetricsTimelineSection.js} +45 -29
  196. package/dist/portfolio/sections/MetricsTimelineSection.js.map +1 -0
  197. package/dist/{PerformanceSection-24TVVFZA.cjs → portfolio/sections/PerformanceSection.cjs} +136 -93
  198. package/dist/portfolio/sections/PerformanceSection.cjs.map +1 -0
  199. package/dist/portfolio/sections/PerformanceSection.d.cts +22 -0
  200. package/dist/portfolio/sections/PerformanceSection.d.ts +22 -0
  201. package/dist/{PerformanceSection-MGCEIXDX.js → portfolio/sections/PerformanceSection.js} +58 -40
  202. package/dist/portfolio/sections/PerformanceSection.js.map +1 -0
  203. package/dist/{ResultsSection-XLGMMQKY.cjs → portfolio/sections/ResultsSection.cjs} +22 -10
  204. package/dist/portfolio/sections/ResultsSection.cjs.map +1 -0
  205. package/dist/portfolio/sections/ResultsSection.d.cts +13 -0
  206. package/dist/portfolio/sections/ResultsSection.d.ts +13 -0
  207. package/dist/{ResultsSection-DFUJ5U6M.js → portfolio/sections/ResultsSection.js} +13 -7
  208. package/dist/portfolio/sections/ResultsSection.js.map +1 -0
  209. package/dist/portfolio/sections/ServicesSection.cjs +129 -0
  210. package/dist/portfolio/sections/ServicesSection.cjs.map +1 -0
  211. package/dist/portfolio/sections/ServicesSection.d.cts +9 -0
  212. package/dist/portfolio/sections/ServicesSection.d.ts +9 -0
  213. package/dist/portfolio/sections/ServicesSection.js +122 -0
  214. package/dist/portfolio/sections/ServicesSection.js.map +1 -0
  215. package/dist/{SiteArchitectureSection-J7BPBERH.cjs → portfolio/sections/SiteArchitectureSection.cjs} +116 -92
  216. package/dist/portfolio/sections/SiteArchitectureSection.cjs.map +1 -0
  217. package/dist/portfolio/sections/SiteArchitectureSection.d.cts +21 -0
  218. package/dist/portfolio/sections/SiteArchitectureSection.d.ts +21 -0
  219. package/dist/{SiteArchitectureSection-TE22OAWV.js → portfolio/sections/SiteArchitectureSection.js} +46 -47
  220. package/dist/portfolio/sections/SiteArchitectureSection.js.map +1 -0
  221. package/dist/{SpeedComparisonSection-EZKFQVGW.cjs → portfolio/sections/SpeedComparisonSection.cjs} +12 -6
  222. package/dist/portfolio/sections/SpeedComparisonSection.cjs.map +1 -0
  223. package/dist/portfolio/sections/SpeedComparisonSection.d.cts +20 -0
  224. package/dist/portfolio/sections/SpeedComparisonSection.d.ts +20 -0
  225. package/dist/{SpeedComparisonSection-Y3K7OFZQ.js → portfolio/sections/SpeedComparisonSection.js} +5 -4
  226. package/dist/portfolio/sections/SpeedComparisonSection.js.map +1 -0
  227. package/dist/portfolio/sections/StrategySection.cjs +233 -0
  228. package/dist/portfolio/sections/StrategySection.cjs.map +1 -0
  229. package/dist/portfolio/sections/StrategySection.d.cts +9 -0
  230. package/dist/portfolio/sections/StrategySection.d.ts +9 -0
  231. package/dist/{StrategySection-DI5RSCJU.js → portfolio/sections/StrategySection.js} +60 -26
  232. package/dist/portfolio/sections/StrategySection.js.map +1 -0
  233. package/dist/portfolio/sections/TeamSection.cjs +162 -0
  234. package/dist/portfolio/sections/TeamSection.cjs.map +1 -0
  235. package/dist/portfolio/sections/TeamSection.d.cts +9 -0
  236. package/dist/portfolio/sections/TeamSection.d.ts +9 -0
  237. package/dist/portfolio/sections/TeamSection.js +106 -0
  238. package/dist/portfolio/sections/TeamSection.js.map +1 -0
  239. package/dist/portfolio/sections/TechStackSection.cjs +106 -0
  240. package/dist/portfolio/sections/TechStackSection.cjs.map +1 -0
  241. package/dist/portfolio/sections/TechStackSection.d.cts +9 -0
  242. package/dist/portfolio/sections/TechStackSection.d.ts +9 -0
  243. package/dist/portfolio/sections/TechStackSection.js +99 -0
  244. package/dist/portfolio/sections/TechStackSection.js.map +1 -0
  245. package/dist/{TestimonialSection-XPTFUQIN.cjs → portfolio/sections/TestimonialSection.cjs} +47 -28
  246. package/dist/portfolio/sections/TestimonialSection.cjs.map +1 -0
  247. package/dist/portfolio/sections/TestimonialSection.d.cts +9 -0
  248. package/dist/portfolio/sections/TestimonialSection.d.ts +9 -0
  249. package/dist/{TestimonialSection-6RGSMXQB.js → portfolio/sections/TestimonialSection.js} +40 -27
  250. package/dist/portfolio/sections/TestimonialSection.js.map +1 -0
  251. package/dist/portfolio/sections/VideoSection.cjs +181 -0
  252. package/dist/portfolio/sections/VideoSection.cjs.map +1 -0
  253. package/dist/portfolio/sections/VideoSection.d.cts +9 -0
  254. package/dist/portfolio/sections/VideoSection.d.ts +9 -0
  255. package/dist/{VideoSection-4A2HC6K6.js → portfolio/sections/VideoSection.js} +21 -13
  256. package/dist/portfolio/sections/VideoSection.js.map +1 -0
  257. package/dist/portfolio/server.cjs +56 -144
  258. package/dist/portfolio/server.cjs.map +1 -1
  259. package/dist/portfolio/server.d.cts +157 -7
  260. package/dist/portfolio/server.d.ts +157 -7
  261. package/dist/portfolio/server.js +3 -142
  262. package/dist/portfolio/server.js.map +1 -1
  263. package/dist/preview.cjs +56 -0
  264. package/dist/preview.cjs.map +1 -0
  265. package/dist/preview.d.cts +31 -0
  266. package/dist/preview.d.ts +31 -0
  267. package/dist/preview.js +54 -0
  268. package/dist/preview.js.map +1 -0
  269. package/dist/{types-DL4t_Cfa.d.ts → types-0tVPy4pU.d.cts} +7 -1
  270. package/dist/{types-DL4t_Cfa.d.cts → types-0tVPy4pU.d.ts} +7 -1
  271. package/dist/types-D0nb6KAx.d.cts +299 -0
  272. package/dist/types-D0nb6KAx.d.ts +299 -0
  273. package/package.json +38 -14
  274. package/templates/api-portfolio-preview.ts +6 -0
  275. package/templates/api-revalidate.ts +5 -0
  276. package/templates/work-category-page.tsx +40 -0
  277. package/templates/work-error.tsx +3 -0
  278. package/templates/work-loading.tsx +1 -0
  279. package/templates/work-page.tsx +37 -0
  280. package/templates/work-slug-loading.tsx +1 -0
  281. package/templates/work-slug-page.tsx +41 -0
  282. package/dist/BeforeAfterSection-6BHFLY4Y.js.map +0 -1
  283. package/dist/BeforeAfterSection-JTORBR3A.cjs +0 -181
  284. package/dist/BeforeAfterSection-JTORBR3A.cjs.map +0 -1
  285. package/dist/CTASection-4JKLXEUF.cjs +0 -111
  286. package/dist/CTASection-4JKLXEUF.cjs.map +0 -1
  287. package/dist/CTASection-BJA72XIL.js +0 -106
  288. package/dist/CTASection-BJA72XIL.js.map +0 -1
  289. package/dist/ChallengesSection-GEQGVSJN.js.map +0 -1
  290. package/dist/ChallengesSection-IZ3DHECS.cjs.map +0 -1
  291. package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs +0 -209
  292. package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs.map +0 -1
  293. package/dist/ConversionFunnelSection-D3GE4NKE.js.map +0 -1
  294. package/dist/DesignSystemSection-2R5BRBGO.js.map +0 -1
  295. package/dist/DesignSystemSection-KXIQXITF.cjs.map +0 -1
  296. package/dist/DetailsSection-A6PZQUQL.js.map +0 -1
  297. package/dist/DetailsSection-TTUZAPZZ.cjs.map +0 -1
  298. package/dist/FeatureSpotlightSection-B7P3JGNL.js.map +0 -1
  299. package/dist/FeatureSpotlightSection-WRHXS7TU.cjs +0 -210
  300. package/dist/FeatureSpotlightSection-WRHXS7TU.cjs.map +0 -1
  301. package/dist/GallerySection-VMKORC47.js.map +0 -1
  302. package/dist/GallerySection-WJ4PQDBI.cjs +0 -219
  303. package/dist/GallerySection-WJ4PQDBI.cjs.map +0 -1
  304. package/dist/MetricsTimelineSection-4L6DUHJ5.cjs.map +0 -1
  305. package/dist/MetricsTimelineSection-6BT5GNFV.js.map +0 -1
  306. package/dist/PerformanceSection-24TVVFZA.cjs.map +0 -1
  307. package/dist/PerformanceSection-MGCEIXDX.js.map +0 -1
  308. package/dist/ResultsSection-DFUJ5U6M.js.map +0 -1
  309. package/dist/ResultsSection-XLGMMQKY.cjs.map +0 -1
  310. package/dist/ServicesSection-D5V3Q4GR.js +0 -118
  311. package/dist/ServicesSection-D5V3Q4GR.js.map +0 -1
  312. package/dist/ServicesSection-WJMGK2MF.cjs +0 -120
  313. package/dist/ServicesSection-WJMGK2MF.cjs.map +0 -1
  314. package/dist/SiteArchitectureSection-J7BPBERH.cjs.map +0 -1
  315. package/dist/SiteArchitectureSection-TE22OAWV.js.map +0 -1
  316. package/dist/SpeedComparisonSection-EZKFQVGW.cjs.map +0 -1
  317. package/dist/SpeedComparisonSection-Y3K7OFZQ.js.map +0 -1
  318. package/dist/StrategySection-CJ7Y6OFQ.cjs +0 -174
  319. package/dist/StrategySection-CJ7Y6OFQ.cjs.map +0 -1
  320. package/dist/StrategySection-DI5RSCJU.js.map +0 -1
  321. package/dist/TeamSection-DZVSNZE6.cjs +0 -112
  322. package/dist/TeamSection-DZVSNZE6.cjs.map +0 -1
  323. package/dist/TeamSection-HGKFW6PQ.js +0 -107
  324. package/dist/TeamSection-HGKFW6PQ.js.map +0 -1
  325. package/dist/TechStackSection-2AQ7RGY3.js +0 -93
  326. package/dist/TechStackSection-2AQ7RGY3.js.map +0 -1
  327. package/dist/TechStackSection-VTNNZR5V.cjs +0 -95
  328. package/dist/TechStackSection-VTNNZR5V.cjs.map +0 -1
  329. package/dist/TestimonialSection-6RGSMXQB.js.map +0 -1
  330. package/dist/TestimonialSection-XPTFUQIN.cjs.map +0 -1
  331. package/dist/VideoSection-4A2HC6K6.js.map +0 -1
  332. package/dist/VideoSection-G3DFS7UH.cjs +0 -118
  333. package/dist/VideoSection-G3DFS7UH.cjs.map +0 -1
  334. package/dist/chunk-2Y4O3LWM.js +0 -53
  335. package/dist/chunk-2Y4O3LWM.js.map +0 -1
  336. package/dist/chunk-633UMQQH.cjs +0 -31
  337. package/dist/chunk-633UMQQH.cjs.map +0 -1
  338. package/dist/chunk-7CFFAKDM.js +0 -74
  339. package/dist/chunk-7CFFAKDM.js.map +0 -1
  340. package/dist/chunk-APG2QSMB.js +0 -131
  341. package/dist/chunk-APG2QSMB.js.map +0 -1
  342. package/dist/chunk-AVCH4LMG.cjs +0 -620
  343. package/dist/chunk-AVCH4LMG.cjs.map +0 -1
  344. package/dist/chunk-AYBUHRFS.js +0 -613
  345. package/dist/chunk-AYBUHRFS.js.map +0 -1
  346. package/dist/chunk-EE75WRCM.cjs.map +0 -1
  347. package/dist/chunk-IKBK7HYX.cjs +0 -79
  348. package/dist/chunk-IKBK7HYX.cjs.map +0 -1
  349. package/dist/chunk-KEOHORIH.cjs +0 -79
  350. package/dist/chunk-KEOHORIH.cjs.map +0 -1
  351. package/dist/chunk-OA5ZM4OA.cjs +0 -139
  352. package/dist/chunk-OA5ZM4OA.cjs.map +0 -1
  353. package/dist/chunk-TVFXN6W6.js.map +0 -1
  354. package/dist/chunk-VVTK4OL6.js +0 -28
  355. package/dist/chunk-VVTK4OL6.js.map +0 -1
  356. package/dist/chunk-XCKXHK44.js +0 -15
  357. package/dist/chunk-XCKXHK44.js.map +0 -1
  358. package/dist/chunk-XONXEFJY.cjs +0 -58
  359. package/dist/chunk-XONXEFJY.cjs.map +0 -1
  360. package/dist/chunk-XQNJED46.cjs +0 -19
  361. package/dist/chunk-XQNJED46.cjs.map +0 -1
  362. package/dist/chunk-YB4B3OMC.js +0 -74
  363. package/dist/chunk-YB4B3OMC.js.map +0 -1
  364. package/dist/portfolio/sections.cjs +0 -20
  365. package/dist/portfolio/sections.cjs.map +0 -1
  366. package/dist/portfolio/sections.d.cts +0 -42
  367. package/dist/portfolio/sections.d.ts +0 -42
  368. package/dist/portfolio/sections.js +0 -4
  369. package/dist/portfolio/sections.js.map +0 -1
@@ -1,210 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkIKBK7HYX_cjs = require('./chunk-IKBK7HYX.cjs');
4
- var react = require('react');
5
- var gsap = require('gsap');
6
- var jsxRuntime = require('react/jsx-runtime');
7
-
8
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
-
10
- var gsap__default = /*#__PURE__*/_interopDefault(gsap);
11
-
12
- function AnnotationPin({
13
- annotation,
14
- index,
15
- activeIndex,
16
- onSelect
17
- }) {
18
- const pinRef = react.useRef(null);
19
- const isActive = activeIndex === index;
20
- react.useEffect(() => {
21
- if (!pinRef.current) return;
22
- if (isActive) {
23
- gsap__default.default.to(pinRef.current, {
24
- scale: 1.2,
25
- duration: 0.3,
26
- ease: "back.out(2)"
27
- });
28
- } else {
29
- gsap__default.default.to(pinRef.current, {
30
- scale: 1,
31
- duration: 0.2,
32
- ease: "power2.out"
33
- });
34
- }
35
- }, [isActive]);
36
- return /* @__PURE__ */ jsxRuntime.jsxs(
37
- "button",
38
- {
39
- ref: pinRef,
40
- onClick: () => onSelect(isActive ? null : index),
41
- className: "absolute z-10 flex items-center justify-center w-8 h-8 rounded-full text-xs font-bold transition-colors cursor-pointer",
42
- style: {
43
- left: `${annotation.x}%`,
44
- top: `${annotation.y}%`,
45
- transform: "translate(-50%, -50%)",
46
- background: isActive ? "var(--sk-primary, #6366f1)" : "color-mix(in srgb, var(--sk-primary, #6366f1) 80%, transparent)",
47
- color: "#ffffff",
48
- boxShadow: isActive ? "0 0 20px color-mix(in srgb, var(--sk-primary, #6366f1) 50%, transparent)" : "0 4px 12px rgba(0,0,0,0.3)",
49
- border: "2px solid rgba(255,255,255,0.3)",
50
- willChange: "transform"
51
- },
52
- "aria-label": annotation.label,
53
- children: [
54
- index + 1,
55
- isActive && /* @__PURE__ */ jsxRuntime.jsxs(
56
- "div",
57
- {
58
- className: "absolute bottom-full left-1/2 mb-3 w-56 p-3 rounded-xl text-left",
59
- style: {
60
- transform: "translateX(-50%)",
61
- background: "var(--sk-surface, rgba(255,255,255,0.05))",
62
- backdropFilter: "blur(16px)",
63
- border: "1px solid var(--sk-border, rgba(255,255,255,0.1))",
64
- boxShadow: "0 8px 32px rgba(0,0,0,0.3)"
65
- },
66
- children: [
67
- /* @__PURE__ */ jsxRuntime.jsx(
68
- "div",
69
- {
70
- className: "text-sm font-semibold mb-1",
71
- style: { color: "var(--sk-text-primary, #ffffff)" },
72
- children: annotation.label
73
- }
74
- ),
75
- /* @__PURE__ */ jsxRuntime.jsx(
76
- "div",
77
- {
78
- className: "text-xs leading-relaxed",
79
- style: { color: "var(--sk-text-tertiary, #71717a)" },
80
- children: annotation.description
81
- }
82
- ),
83
- /* @__PURE__ */ jsxRuntime.jsx(
84
- "div",
85
- {
86
- className: "absolute top-full left-1/2 w-0 h-0",
87
- style: {
88
- transform: "translateX(-50%)",
89
- borderLeft: "6px solid transparent",
90
- borderRight: "6px solid transparent",
91
- borderTop: "6px solid var(--sk-border, rgba(255,255,255,0.1))"
92
- }
93
- }
94
- )
95
- ]
96
- }
97
- )
98
- ]
99
- }
100
- );
101
- }
102
- function FeatureSpotlightSection({ data }) {
103
- const [activeAnnotation, setActiveAnnotation] = react.useState(null);
104
- const imageUrl = data.image?.asset?._ref || "";
105
- const layout = data.layout || "left";
106
- const handleSelect = react.useCallback((index) => {
107
- setActiveAnnotation(index);
108
- }, []);
109
- const imageBlock = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
110
- /* @__PURE__ */ jsxRuntime.jsx(
111
- "img",
112
- {
113
- src: imageUrl,
114
- alt: data.title,
115
- className: "w-full h-auto rounded-xl",
116
- style: {
117
- border: "1px solid var(--sk-border, rgba(255,255,255,0.1))"
118
- },
119
- loading: "lazy"
120
- }
121
- ),
122
- data.annotations.map((annotation, index) => /* @__PURE__ */ jsxRuntime.jsx(
123
- AnnotationPin,
124
- {
125
- annotation,
126
- index,
127
- activeIndex: activeAnnotation,
128
- onSelect: handleSelect
129
- },
130
- index
131
- ))
132
- ] });
133
- const textBlock = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center gap-4", children: [
134
- /* @__PURE__ */ jsxRuntime.jsx(
135
- "h2",
136
- {
137
- className: "text-3xl md:text-4xl font-bold",
138
- style: {
139
- color: "var(--sk-text-primary, #ffffff)",
140
- fontFamily: "var(--sk-font-heading, inherit)"
141
- },
142
- children: data.title
143
- }
144
- ),
145
- /* @__PURE__ */ jsxRuntime.jsx(
146
- "p",
147
- {
148
- className: "text-base md:text-lg leading-relaxed",
149
- style: { color: "var(--sk-text-secondary, #a1a1aa)" },
150
- children: data.description
151
- }
152
- ),
153
- data.annotations.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 mt-4", children: data.annotations.map((annotation, index) => /* @__PURE__ */ jsxRuntime.jsxs(
154
- "button",
155
- {
156
- onClick: () => handleSelect(activeAnnotation === index ? null : index),
157
- className: "flex items-start gap-3 text-left p-2 rounded-lg transition-colors cursor-pointer",
158
- style: {
159
- background: activeAnnotation === index ? "color-mix(in srgb, var(--sk-primary, #6366f1) 10%, transparent)" : "transparent"
160
- },
161
- children: [
162
- /* @__PURE__ */ jsxRuntime.jsx(
163
- "span",
164
- {
165
- className: "flex items-center justify-center w-6 h-6 rounded-full text-xs font-bold shrink-0",
166
- style: {
167
- background: "color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)",
168
- color: "var(--sk-primary, #6366f1)"
169
- },
170
- children: index + 1
171
- }
172
- ),
173
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
174
- "span",
175
- {
176
- className: "text-sm font-medium",
177
- style: { color: "var(--sk-text-primary, #ffffff)" },
178
- children: annotation.label
179
- }
180
- ) })
181
- ]
182
- },
183
- index
184
- )) })
185
- ] });
186
- return /* @__PURE__ */ jsxRuntime.jsx(
187
- "section",
188
- {
189
- className: "w-full py-20 md:py-28",
190
- style: { background: "var(--sk-bg, #0a0a0a)" },
191
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-7xl mx-auto px-6", children: layout === "full" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-8", children: [
192
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 30, children: textBlock }),
193
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 40, delay: 0.15, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: imageBlock }) })
194
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(
195
- "div",
196
- {
197
- className: `grid lg:grid-cols-2 gap-12 items-center ${layout === "right" ? "lg:[direction:rtl] lg:[&>*]:![direction:ltr]" : ""}`,
198
- children: [
199
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 40, children: imageBlock }),
200
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 40, delay: 0.15, children: textBlock })
201
- ]
202
- }
203
- ) })
204
- }
205
- );
206
- }
207
-
208
- module.exports = FeatureSpotlightSection;
209
- //# sourceMappingURL=FeatureSpotlightSection-WRHXS7TU.cjs.map
210
- //# sourceMappingURL=FeatureSpotlightSection-WRHXS7TU.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/portfolio/components/sections/FeatureSpotlightSection.tsx"],"names":["useRef","useEffect","gsap","jsxs","jsx","useState","useCallback","ScrollReveal"],"mappings":"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","file":"FeatureSpotlightSection-WRHXS7TU.cjs","sourcesContent":["'use client';\n\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport gsap from 'gsap';\nimport type { PortfolioFeatureSpotlightData, PortfolioAnnotation } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\n\ninterface FeatureSpotlightSectionProps {\n data: PortfolioFeatureSpotlightData;\n}\n\nfunction AnnotationPin({\n annotation,\n index,\n activeIndex,\n onSelect,\n}: {\n annotation: PortfolioAnnotation;\n index: number;\n activeIndex: number | null;\n onSelect: (index: number | null) => void;\n}) {\n const pinRef = useRef<HTMLButtonElement>(null);\n const isActive = activeIndex === index;\n\n useEffect(() => {\n if (!pinRef.current) return;\n\n if (isActive) {\n gsap.to(pinRef.current, {\n scale: 1.2,\n duration: 0.3,\n ease: 'back.out(2)',\n });\n } else {\n gsap.to(pinRef.current, {\n scale: 1,\n duration: 0.2,\n ease: 'power2.out',\n });\n }\n }, [isActive]);\n\n return (\n <button\n ref={pinRef}\n onClick={() => onSelect(isActive ? null : index)}\n className=\"absolute z-10 flex items-center justify-center w-8 h-8 rounded-full text-xs font-bold transition-colors cursor-pointer\"\n style={{\n left: `${annotation.x}%`,\n top: `${annotation.y}%`,\n transform: 'translate(-50%, -50%)',\n background: isActive\n ? 'var(--sk-primary, #6366f1)'\n : 'color-mix(in srgb, var(--sk-primary, #6366f1) 80%, transparent)',\n color: '#ffffff',\n boxShadow: isActive\n ? '0 0 20px color-mix(in srgb, var(--sk-primary, #6366f1) 50%, transparent)'\n : '0 4px 12px rgba(0,0,0,0.3)',\n border: '2px solid rgba(255,255,255,0.3)',\n willChange: 'transform',\n }}\n aria-label={annotation.label}\n >\n {index + 1}\n\n {/* Tooltip */}\n {isActive && (\n <div\n className=\"absolute bottom-full left-1/2 mb-3 w-56 p-3 rounded-xl text-left\"\n style={{\n transform: 'translateX(-50%)',\n background: 'var(--sk-surface, rgba(255,255,255,0.05))',\n backdropFilter: 'blur(16px)',\n border: '1px solid var(--sk-border, rgba(255,255,255,0.1))',\n boxShadow: '0 8px 32px rgba(0,0,0,0.3)',\n }}\n >\n <div\n className=\"text-sm font-semibold mb-1\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {annotation.label}\n </div>\n <div\n className=\"text-xs leading-relaxed\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {annotation.description}\n </div>\n {/* Arrow */}\n <div\n className=\"absolute top-full left-1/2 w-0 h-0\"\n style={{\n transform: 'translateX(-50%)',\n borderLeft: '6px solid transparent',\n borderRight: '6px solid transparent',\n borderTop: '6px solid var(--sk-border, rgba(255,255,255,0.1))',\n }}\n />\n </div>\n )}\n </button>\n );\n}\n\nexport default function FeatureSpotlightSection({ data }: FeatureSpotlightSectionProps) {\n const [activeAnnotation, setActiveAnnotation] = useState<number | null>(null);\n\n const imageUrl = data.image?.asset?._ref || '';\n const layout = data.layout || 'left';\n\n const handleSelect = useCallback((index: number | null) => {\n setActiveAnnotation(index);\n }, []);\n\n const imageBlock = (\n <div className=\"relative w-full\">\n <img\n src={imageUrl}\n alt={data.title}\n className=\"w-full h-auto rounded-xl\"\n style={{\n border: '1px solid var(--sk-border, rgba(255,255,255,0.1))',\n }}\n loading=\"lazy\"\n />\n {/* Annotation pins */}\n {data.annotations.map((annotation, index) => (\n <AnnotationPin\n key={index}\n annotation={annotation}\n index={index}\n activeIndex={activeAnnotation}\n onSelect={handleSelect}\n />\n ))}\n </div>\n );\n\n const textBlock = (\n <div className=\"flex flex-col justify-center gap-4\">\n <h2\n className=\"text-3xl md:text-4xl font-bold\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n <p\n className=\"text-base md:text-lg leading-relaxed\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n\n {/* Annotation legend */}\n {data.annotations.length > 0 && (\n <div className=\"flex flex-col gap-2 mt-4\">\n {data.annotations.map((annotation, index) => (\n <button\n key={index}\n onClick={() => handleSelect(activeAnnotation === index ? null : index)}\n className=\"flex items-start gap-3 text-left p-2 rounded-lg transition-colors cursor-pointer\"\n style={{\n background:\n activeAnnotation === index\n ? 'color-mix(in srgb, var(--sk-primary, #6366f1) 10%, transparent)'\n : 'transparent',\n }}\n >\n <span\n className=\"flex items-center justify-center w-6 h-6 rounded-full text-xs font-bold shrink-0\"\n style={{\n background: 'color-mix(in srgb, var(--sk-primary, #6366f1) 20%, transparent)',\n color: 'var(--sk-primary, #6366f1)',\n }}\n >\n {index + 1}\n </span>\n <div>\n <span\n className=\"text-sm font-medium\"\n style={{ color: 'var(--sk-text-primary, #ffffff)' }}\n >\n {annotation.label}\n </span>\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-7xl mx-auto px-6\">\n {layout === 'full' ? (\n <div className=\"flex flex-col gap-8\">\n <ScrollReveal y={30}>{textBlock}</ScrollReveal>\n <ScrollReveal y={40} delay={0.15}>\n <div className=\"relative\">{imageBlock}</div>\n </ScrollReveal>\n </div>\n ) : (\n <div\n className={`grid lg:grid-cols-2 gap-12 items-center ${\n layout === 'right' ? 'lg:[direction:rtl] lg:[&>*]:![direction:ltr]' : ''\n }`}\n >\n <ScrollReveal y={40}>{imageBlock}</ScrollReveal>\n <ScrollReveal y={40} delay={0.15}>{textBlock}</ScrollReveal>\n </div>\n )}\n </div>\n </section>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/portfolio/components/sections/GallerySection.tsx"],"names":[],"mappings":"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","file":"GallerySection-VMKORC47.js","sourcesContent":["'use client';\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport type { PortfolioGalleryData } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\n\ninterface GallerySectionProps {\n data: PortfolioGalleryData;\n}\n\nconst typeBadgeColors: Record<string, { bg: string; text: string; border: string }> = {\n screenshot: {\n bg: 'color-mix(in srgb, #6366f1 12%, transparent)',\n text: '#6366f1',\n border: 'color-mix(in srgb, #6366f1 20%, transparent)',\n },\n before: {\n bg: 'color-mix(in srgb, #f59e0b 12%, transparent)',\n text: '#f59e0b',\n border: 'color-mix(in srgb, #f59e0b 20%, transparent)',\n },\n after: {\n bg: 'color-mix(in srgb, #10b981 12%, transparent)',\n text: '#10b981',\n border: 'color-mix(in srgb, #10b981 20%, transparent)',\n },\n design: {\n bg: 'color-mix(in srgb, #ec4899 12%, transparent)',\n text: '#ec4899',\n border: 'color-mix(in srgb, #ec4899 20%, transparent)',\n },\n};\n\nexport default function GallerySection({ data }: GallerySectionProps) {\n const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);\n\n const layout = data.layout || 'grid';\n\n const openLightbox = useCallback((index: number) => {\n setLightboxIndex(index);\n }, []);\n\n const closeLightbox = useCallback(() => {\n setLightboxIndex(null);\n }, []);\n\n const goNext = useCallback(() => {\n setLightboxIndex((prev) =>\n prev !== null ? (prev + 1) % data.images.length : null,\n );\n }, [data.images.length]);\n\n const goPrev = useCallback(() => {\n setLightboxIndex((prev) =>\n prev !== null ? (prev - 1 + data.images.length) % data.images.length : null,\n );\n }, [data.images.length]);\n\n // Keyboard navigation\n useEffect(() => {\n if (lightboxIndex === null) return;\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') closeLightbox();\n if (e.key === 'ArrowRight') goNext();\n if (e.key === 'ArrowLeft') goPrev();\n }\n\n document.addEventListener('keydown', handleKeyDown);\n document.body.style.overflow = 'hidden';\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = '';\n };\n }, [lightboxIndex, closeLightbox, goNext, goPrev]);\n\n function getImageUrl(image: typeof data.images[0]) {\n // Extract URL from SanityImageRef asset _ref or fall back\n return image.image.asset._ref || '';\n }\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-7xl mx-auto px-6\">\n <ScrollReveal y={30}>\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-12\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n Gallery\n </h2>\n </ScrollReveal>\n\n <ScrollReveal stagger={0.08}>\n <div\n className={\n layout === 'masonry'\n ? 'columns-1 md:columns-2 lg:columns-3 gap-4 space-y-4'\n : 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4'\n }\n >\n {data.images.map((img, index) => {\n const url = getImageUrl(img);\n const colors = typeBadgeColors[img.type || 'screenshot'] || typeBadgeColors.screenshot;\n\n return (\n <div\n key={index}\n className={`relative group cursor-pointer overflow-hidden rounded-xl ${\n layout === 'masonry' ? 'break-inside-avoid' : ''\n }`}\n style={{\n border: '1px solid var(--sk-border, rgba(255,255,255,0.1))',\n }}\n onClick={() => openLightbox(index)}\n >\n <img\n src={url}\n alt={img.caption || `Gallery image ${index + 1}`}\n className=\"w-full h-auto object-cover transition-transform duration-500 group-hover:scale-105\"\n loading=\"lazy\"\n />\n\n {/* Overlay on hover */}\n <div\n className=\"absolute inset-0 flex flex-col justify-end p-4 opacity-0 group-hover:opacity-100 transition-opacity duration-300\"\n style={{\n background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%)',\n }}\n >\n {img.caption && (\n <p className=\"text-sm text-white font-medium\">{img.caption}</p>\n )}\n </div>\n\n {/* Type badge */}\n {img.type && (\n <span\n className=\"absolute top-3 left-3 px-2.5 py-1 rounded-full text-[11px] uppercase tracking-wider font-medium\"\n style={{\n background: colors.bg,\n color: colors.text,\n border: `1px solid ${colors.border}`,\n backdropFilter: 'blur(8px)',\n }}\n >\n {img.type}\n </span>\n )}\n </div>\n );\n })}\n </div>\n </ScrollReveal>\n </div>\n\n {/* Lightbox modal */}\n {lightboxIndex !== null && (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{ background: 'rgba(0,0,0,0.9)' }}\n onClick={closeLightbox}\n >\n {/* Close button */}\n <button\n onClick={closeLightbox}\n className=\"absolute top-6 right-6 w-10 h-10 flex items-center justify-center rounded-full transition-colors z-10\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n color: '#ffffff',\n }}\n aria-label=\"Close lightbox\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M15 5L5 15M5 5l10 10\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n\n {/* Prev button */}\n <button\n onClick={(e) => { e.stopPropagation(); goPrev(); }}\n className=\"absolute left-4 md:left-8 w-12 h-12 flex items-center justify-center rounded-full transition-colors z-10\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n color: '#ffffff',\n }}\n aria-label=\"Previous image\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M12.5 15l-5-5 5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n\n {/* Next button */}\n <button\n onClick={(e) => { e.stopPropagation(); goNext(); }}\n className=\"absolute right-4 md:right-8 w-12 h-12 flex items-center justify-center rounded-full transition-colors z-10\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n color: '#ffffff',\n }}\n aria-label=\"Next image\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M7.5 5l5 5-5 5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n\n {/* Image */}\n <div\n className=\"max-w-[90vw] max-h-[85vh] flex flex-col items-center gap-4\"\n onClick={(e) => e.stopPropagation()}\n >\n <img\n src={getImageUrl(data.images[lightboxIndex])}\n alt={data.images[lightboxIndex].caption || ''}\n className=\"max-w-full max-h-[80vh] object-contain rounded-lg\"\n />\n {data.images[lightboxIndex].caption && (\n <p className=\"text-sm text-white/70 text-center\">\n {data.images[lightboxIndex].caption}\n </p>\n )}\n </div>\n </div>\n )}\n </section>\n );\n}\n"]}
@@ -1,219 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkIKBK7HYX_cjs = require('./chunk-IKBK7HYX.cjs');
4
- var react = require('react');
5
- var jsxRuntime = require('react/jsx-runtime');
6
-
7
- var typeBadgeColors = {
8
- screenshot: {
9
- bg: "color-mix(in srgb, #6366f1 12%, transparent)",
10
- text: "#6366f1",
11
- border: "color-mix(in srgb, #6366f1 20%, transparent)"
12
- },
13
- before: {
14
- bg: "color-mix(in srgb, #f59e0b 12%, transparent)",
15
- text: "#f59e0b",
16
- border: "color-mix(in srgb, #f59e0b 20%, transparent)"
17
- },
18
- after: {
19
- bg: "color-mix(in srgb, #10b981 12%, transparent)",
20
- text: "#10b981",
21
- border: "color-mix(in srgb, #10b981 20%, transparent)"
22
- },
23
- design: {
24
- bg: "color-mix(in srgb, #ec4899 12%, transparent)",
25
- text: "#ec4899",
26
- border: "color-mix(in srgb, #ec4899 20%, transparent)"
27
- }
28
- };
29
- function GallerySection({ data }) {
30
- const [lightboxIndex, setLightboxIndex] = react.useState(null);
31
- const layout = data.layout || "grid";
32
- const openLightbox = react.useCallback((index) => {
33
- setLightboxIndex(index);
34
- }, []);
35
- const closeLightbox = react.useCallback(() => {
36
- setLightboxIndex(null);
37
- }, []);
38
- const goNext = react.useCallback(() => {
39
- setLightboxIndex(
40
- (prev) => prev !== null ? (prev + 1) % data.images.length : null
41
- );
42
- }, [data.images.length]);
43
- const goPrev = react.useCallback(() => {
44
- setLightboxIndex(
45
- (prev) => prev !== null ? (prev - 1 + data.images.length) % data.images.length : null
46
- );
47
- }, [data.images.length]);
48
- react.useEffect(() => {
49
- if (lightboxIndex === null) return;
50
- function handleKeyDown(e) {
51
- if (e.key === "Escape") closeLightbox();
52
- if (e.key === "ArrowRight") goNext();
53
- if (e.key === "ArrowLeft") goPrev();
54
- }
55
- document.addEventListener("keydown", handleKeyDown);
56
- document.body.style.overflow = "hidden";
57
- return () => {
58
- document.removeEventListener("keydown", handleKeyDown);
59
- document.body.style.overflow = "";
60
- };
61
- }, [lightboxIndex, closeLightbox, goNext, goPrev]);
62
- function getImageUrl(image) {
63
- return image.image.asset._ref || "";
64
- }
65
- return /* @__PURE__ */ jsxRuntime.jsxs(
66
- "section",
67
- {
68
- className: "w-full py-20 md:py-28",
69
- style: { background: "var(--sk-bg, #0a0a0a)" },
70
- children: [
71
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-7xl mx-auto px-6", children: [
72
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 30, children: /* @__PURE__ */ jsxRuntime.jsx(
73
- "h2",
74
- {
75
- className: "text-3xl md:text-4xl font-bold mb-12",
76
- style: {
77
- color: "var(--sk-text-primary, #ffffff)",
78
- fontFamily: "var(--sk-font-heading, inherit)"
79
- },
80
- children: "Gallery"
81
- }
82
- ) }),
83
- /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { stagger: 0.08, children: /* @__PURE__ */ jsxRuntime.jsx(
84
- "div",
85
- {
86
- className: layout === "masonry" ? "columns-1 md:columns-2 lg:columns-3 gap-4 space-y-4" : "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",
87
- children: data.images.map((img, index) => {
88
- const url = getImageUrl(img);
89
- const colors = typeBadgeColors[img.type || "screenshot"] || typeBadgeColors.screenshot;
90
- return /* @__PURE__ */ jsxRuntime.jsxs(
91
- "div",
92
- {
93
- className: `relative group cursor-pointer overflow-hidden rounded-xl ${layout === "masonry" ? "break-inside-avoid" : ""}`,
94
- style: {
95
- border: "1px solid var(--sk-border, rgba(255,255,255,0.1))"
96
- },
97
- onClick: () => openLightbox(index),
98
- children: [
99
- /* @__PURE__ */ jsxRuntime.jsx(
100
- "img",
101
- {
102
- src: url,
103
- alt: img.caption || `Gallery image ${index + 1}`,
104
- className: "w-full h-auto object-cover transition-transform duration-500 group-hover:scale-105",
105
- loading: "lazy"
106
- }
107
- ),
108
- /* @__PURE__ */ jsxRuntime.jsx(
109
- "div",
110
- {
111
- className: "absolute inset-0 flex flex-col justify-end p-4 opacity-0 group-hover:opacity-100 transition-opacity duration-300",
112
- style: {
113
- background: "linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%)"
114
- },
115
- children: img.caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white font-medium", children: img.caption })
116
- }
117
- ),
118
- img.type && /* @__PURE__ */ jsxRuntime.jsx(
119
- "span",
120
- {
121
- className: "absolute top-3 left-3 px-2.5 py-1 rounded-full text-[11px] uppercase tracking-wider font-medium",
122
- style: {
123
- background: colors.bg,
124
- color: colors.text,
125
- border: `1px solid ${colors.border}`,
126
- backdropFilter: "blur(8px)"
127
- },
128
- children: img.type
129
- }
130
- )
131
- ]
132
- },
133
- index
134
- );
135
- })
136
- }
137
- ) })
138
- ] }),
139
- lightboxIndex !== null && /* @__PURE__ */ jsxRuntime.jsxs(
140
- "div",
141
- {
142
- className: "fixed inset-0 z-50 flex items-center justify-center",
143
- style: { background: "rgba(0,0,0,0.9)" },
144
- onClick: closeLightbox,
145
- children: [
146
- /* @__PURE__ */ jsxRuntime.jsx(
147
- "button",
148
- {
149
- onClick: closeLightbox,
150
- className: "absolute top-6 right-6 w-10 h-10 flex items-center justify-center rounded-full transition-colors z-10",
151
- style: {
152
- background: "rgba(255,255,255,0.1)",
153
- color: "#ffffff"
154
- },
155
- "aria-label": "Close lightbox",
156
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
157
- }
158
- ),
159
- /* @__PURE__ */ jsxRuntime.jsx(
160
- "button",
161
- {
162
- onClick: (e) => {
163
- e.stopPropagation();
164
- goPrev();
165
- },
166
- className: "absolute left-4 md:left-8 w-12 h-12 flex items-center justify-center rounded-full transition-colors z-10",
167
- style: {
168
- background: "rgba(255,255,255,0.1)",
169
- color: "#ffffff"
170
- },
171
- "aria-label": "Previous image",
172
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.5 15l-5-5 5-5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
173
- }
174
- ),
175
- /* @__PURE__ */ jsxRuntime.jsx(
176
- "button",
177
- {
178
- onClick: (e) => {
179
- e.stopPropagation();
180
- goNext();
181
- },
182
- className: "absolute right-4 md:right-8 w-12 h-12 flex items-center justify-center rounded-full transition-colors z-10",
183
- style: {
184
- background: "rgba(255,255,255,0.1)",
185
- color: "#ffffff"
186
- },
187
- "aria-label": "Next image",
188
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7.5 5l5 5-5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
189
- }
190
- ),
191
- /* @__PURE__ */ jsxRuntime.jsxs(
192
- "div",
193
- {
194
- className: "max-w-[90vw] max-h-[85vh] flex flex-col items-center gap-4",
195
- onClick: (e) => e.stopPropagation(),
196
- children: [
197
- /* @__PURE__ */ jsxRuntime.jsx(
198
- "img",
199
- {
200
- src: getImageUrl(data.images[lightboxIndex]),
201
- alt: data.images[lightboxIndex].caption || "",
202
- className: "max-w-full max-h-[80vh] object-contain rounded-lg"
203
- }
204
- ),
205
- data.images[lightboxIndex].caption && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/70 text-center", children: data.images[lightboxIndex].caption })
206
- ]
207
- }
208
- )
209
- ]
210
- }
211
- )
212
- ]
213
- }
214
- );
215
- }
216
-
217
- module.exports = GallerySection;
218
- //# sourceMappingURL=GallerySection-WJ4PQDBI.cjs.map
219
- //# sourceMappingURL=GallerySection-WJ4PQDBI.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/portfolio/components/sections/GallerySection.tsx"],"names":["useState","useCallback","useEffect","jsxs","jsx","ScrollReveal"],"mappings":"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","file":"GallerySection-WJ4PQDBI.cjs","sourcesContent":["'use client';\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport type { PortfolioGalleryData } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\n\ninterface GallerySectionProps {\n data: PortfolioGalleryData;\n}\n\nconst typeBadgeColors: Record<string, { bg: string; text: string; border: string }> = {\n screenshot: {\n bg: 'color-mix(in srgb, #6366f1 12%, transparent)',\n text: '#6366f1',\n border: 'color-mix(in srgb, #6366f1 20%, transparent)',\n },\n before: {\n bg: 'color-mix(in srgb, #f59e0b 12%, transparent)',\n text: '#f59e0b',\n border: 'color-mix(in srgb, #f59e0b 20%, transparent)',\n },\n after: {\n bg: 'color-mix(in srgb, #10b981 12%, transparent)',\n text: '#10b981',\n border: 'color-mix(in srgb, #10b981 20%, transparent)',\n },\n design: {\n bg: 'color-mix(in srgb, #ec4899 12%, transparent)',\n text: '#ec4899',\n border: 'color-mix(in srgb, #ec4899 20%, transparent)',\n },\n};\n\nexport default function GallerySection({ data }: GallerySectionProps) {\n const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);\n\n const layout = data.layout || 'grid';\n\n const openLightbox = useCallback((index: number) => {\n setLightboxIndex(index);\n }, []);\n\n const closeLightbox = useCallback(() => {\n setLightboxIndex(null);\n }, []);\n\n const goNext = useCallback(() => {\n setLightboxIndex((prev) =>\n prev !== null ? (prev + 1) % data.images.length : null,\n );\n }, [data.images.length]);\n\n const goPrev = useCallback(() => {\n setLightboxIndex((prev) =>\n prev !== null ? (prev - 1 + data.images.length) % data.images.length : null,\n );\n }, [data.images.length]);\n\n // Keyboard navigation\n useEffect(() => {\n if (lightboxIndex === null) return;\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') closeLightbox();\n if (e.key === 'ArrowRight') goNext();\n if (e.key === 'ArrowLeft') goPrev();\n }\n\n document.addEventListener('keydown', handleKeyDown);\n document.body.style.overflow = 'hidden';\n\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n document.body.style.overflow = '';\n };\n }, [lightboxIndex, closeLightbox, goNext, goPrev]);\n\n function getImageUrl(image: typeof data.images[0]) {\n // Extract URL from SanityImageRef asset _ref or fall back\n return image.image.asset._ref || '';\n }\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-7xl mx-auto px-6\">\n <ScrollReveal y={30}>\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-12\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n Gallery\n </h2>\n </ScrollReveal>\n\n <ScrollReveal stagger={0.08}>\n <div\n className={\n layout === 'masonry'\n ? 'columns-1 md:columns-2 lg:columns-3 gap-4 space-y-4'\n : 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4'\n }\n >\n {data.images.map((img, index) => {\n const url = getImageUrl(img);\n const colors = typeBadgeColors[img.type || 'screenshot'] || typeBadgeColors.screenshot;\n\n return (\n <div\n key={index}\n className={`relative group cursor-pointer overflow-hidden rounded-xl ${\n layout === 'masonry' ? 'break-inside-avoid' : ''\n }`}\n style={{\n border: '1px solid var(--sk-border, rgba(255,255,255,0.1))',\n }}\n onClick={() => openLightbox(index)}\n >\n <img\n src={url}\n alt={img.caption || `Gallery image ${index + 1}`}\n className=\"w-full h-auto object-cover transition-transform duration-500 group-hover:scale-105\"\n loading=\"lazy\"\n />\n\n {/* Overlay on hover */}\n <div\n className=\"absolute inset-0 flex flex-col justify-end p-4 opacity-0 group-hover:opacity-100 transition-opacity duration-300\"\n style={{\n background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%)',\n }}\n >\n {img.caption && (\n <p className=\"text-sm text-white font-medium\">{img.caption}</p>\n )}\n </div>\n\n {/* Type badge */}\n {img.type && (\n <span\n className=\"absolute top-3 left-3 px-2.5 py-1 rounded-full text-[11px] uppercase tracking-wider font-medium\"\n style={{\n background: colors.bg,\n color: colors.text,\n border: `1px solid ${colors.border}`,\n backdropFilter: 'blur(8px)',\n }}\n >\n {img.type}\n </span>\n )}\n </div>\n );\n })}\n </div>\n </ScrollReveal>\n </div>\n\n {/* Lightbox modal */}\n {lightboxIndex !== null && (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{ background: 'rgba(0,0,0,0.9)' }}\n onClick={closeLightbox}\n >\n {/* Close button */}\n <button\n onClick={closeLightbox}\n className=\"absolute top-6 right-6 w-10 h-10 flex items-center justify-center rounded-full transition-colors z-10\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n color: '#ffffff',\n }}\n aria-label=\"Close lightbox\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M15 5L5 15M5 5l10 10\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n\n {/* Prev button */}\n <button\n onClick={(e) => { e.stopPropagation(); goPrev(); }}\n className=\"absolute left-4 md:left-8 w-12 h-12 flex items-center justify-center rounded-full transition-colors z-10\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n color: '#ffffff',\n }}\n aria-label=\"Previous image\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M12.5 15l-5-5 5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n\n {/* Next button */}\n <button\n onClick={(e) => { e.stopPropagation(); goNext(); }}\n className=\"absolute right-4 md:right-8 w-12 h-12 flex items-center justify-center rounded-full transition-colors z-10\"\n style={{\n background: 'rgba(255,255,255,0.1)',\n color: '#ffffff',\n }}\n aria-label=\"Next image\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M7.5 5l5 5-5 5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n\n {/* Image */}\n <div\n className=\"max-w-[90vw] max-h-[85vh] flex flex-col items-center gap-4\"\n onClick={(e) => e.stopPropagation()}\n >\n <img\n src={getImageUrl(data.images[lightboxIndex])}\n alt={data.images[lightboxIndex].caption || ''}\n className=\"max-w-full max-h-[80vh] object-contain rounded-lg\"\n />\n {data.images[lightboxIndex].caption && (\n <p className=\"text-sm text-white/70 text-center\">\n {data.images[lightboxIndex].caption}\n </p>\n )}\n </div>\n </div>\n )}\n </section>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/portfolio/components/sections/MetricsTimelineSection.tsx"],"names":["useRef","useState","useMemo","useEffect","gsap","ScrollTrigger","useCallback","jsx","jsxs","ScrollReveal","GlassCard","Fragment"],"mappings":";;;;;;;;;;;;;AAeA,IAAM,YAAA,GAA0C;AAAA,EAC9C,OAAA,EAAS,SAAA;AAAA,EACT,WAAA,EAAa,SAAA;AAAA,EACb,OAAA,EAAS,SAAA;AAAA,EACT,QAAA,EAAU;AACZ,CAAA;AAEA,IAAM,YAAA,GAA0C;AAAA,EAC9C,OAAA,EAAS,SAAA;AAAA,EACT,WAAA,EAAa,aAAA;AAAA,EACb,OAAA,EAAS,SAAA;AAAA,EACT,QAAA,EAAU;AACZ,CAAA;AAEe,SAAR,sBAAA,CAAwC,EAAE,IAAA,EAAK,EAAgC;AACpF,EAAA,MAAM,MAAA,GAASA,aAAsB,IAAI,CAAA;AACzC,EAAA,MAAM,OAAA,GAAUA,aAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIC,eAAoB,SAAS,CAAA;AACrE,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIA,eAAS,KAAK,CAAA;AAGtD,EAAA,MAAM,gBAAA,GAAmBC,cAAQ,MAAM;AACrC,IAAA,MAAM,IAAA,GAAoB,CAAC,SAAA,EAAW,aAAA,EAAe,WAAW,UAAU,CAAA;AAC1E,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,MAAO,CAAC,GAAA,KAClB,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,CAAC,EAAA,KAAO,EAAA,CAAG,OAAA,CAAQ,GAAG,MAAM,MAAA,IAAa,EAAA,CAAG,OAAA,CAAQ,GAAG,MAAM,IAAI;AAAA,KACxF;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,CAAK,UAAU,CAAC,CAAA;AAGpB,EAAA,MAAM,SAAA,GAAYA,cAAQ,MAAM;AAC9B,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,CAAC,OAAO,EAAA,CAAG,OAAA,CAAQ,YAAY,CAAA,IAAK,CAAC,CAAA;AACxE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAC,CAAA;AACpC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAC,CAAA;AACpC,IAAA,MAAM,KAAA,GAAQ,SAAS,MAAA,IAAU,CAAA;AAEjC,IAAA,MAAM,UAAA,GAAa,GAAA;AACnB,IAAA,MAAM,WAAA,GAAc,GAAA;AACpB,IAAA,MAAM,OAAA,GAAU,EAAA;AAEhB,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,CAAC,KAAK,CAAA,MAAO;AAAA,MACrC,CAAA,EAAG,OAAA,GAAW,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,CAAC,CAAA,IAAM,UAAA,GAAa,OAAA,GAAU,CAAA,CAAA;AAAA,MAC5E,GAAG,WAAA,GAAc,OAAA,GAAA,CAAY,MAAM,MAAA,IAAU,KAAA,IAAU,cAAc,OAAA,GAAU,CAAA;AAAA,KACjF,CAAE,CAAA;AAGF,IAAA,IAAI,CAAA,GAAI,EAAA;AACR,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,CAAA,GAAI,CAAA,EAAA,EAAK,OAAO,CAAC,CAAA,CAAE,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,CAAC,CAAA,CAAE,CAAC,CAAA,CAAA;AACnC,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,MAAM,IAAA,GAAA,CAAQ,OAAO,CAAA,GAAI,CAAC,EAAE,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA,CAAE,CAAA,IAAK,CAAA;AAC/C,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,CAAE,CAAA;AAC3B,QAAA,MAAM,IAAA,GAAA,CAAQ,OAAO,CAAA,GAAI,CAAC,EAAE,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA,CAAE,CAAA,IAAK,CAAA;AAC/C,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAC,CAAA,CAAE,CAAA;AACvB,QAAA,CAAA,IAAK,MAAM,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,CAAC,CAAA,CAAE,CAAC,IAAI,MAAA,CAAO,CAAC,EAAE,CAAC,CAAA,CAAA;AAAA,MACzE;AAAA,IACF;AAGA,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,KAAA,IAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,EAAE,CAAC,CAAA,CAAA,EAAI,WAAA,GAAc,OAAO,MAAM,MAAA,CAAO,CAAC,EAAE,CAAC,CAAA,CAAA,EAAI,cAAc,OAAO,CAAA,EAAA,CAAA;AAAA,IAC/G;AAGA,IAAA,MAAM,WAAA,GAAc,KAAK,UAAA,CAAW,SAAA,CAAU,CAAC,EAAA,KAAO,EAAA,CAAG,KAAA,KAAU,IAAA,CAAK,YAAY,CAAA;AACpF,IAAA,MAAM,YAAY,WAAA,IAAe,CAAA,GAAI,MAAA,CAAO,WAAW,GAAG,CAAA,GAAI,MAAA;AAE9D,IAAA,OAAO;AAAA,MACL,CAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAQ,IAAA,CAAK,UAAA,CAAW,IAAI,CAAC,EAAA,KAAO,GAAG,KAAK;AAAA,KAC9C;AAAA,EACF,GAAG,CAAC,IAAA,CAAK,YAAY,IAAA,CAAK,YAAA,EAAc,YAAY,CAAC,CAAA;AAGrD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAAC,qBAAA,CAAK,eAAeC,2BAAa,CAAA;AAEjC,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,GAAA,EAAK;AAEnB,IAAA,MAAM,oBAAA,GAAuB,MAAA,CAAO,UAAA,CAAW,kCAAkC,CAAA,CAAE,OAAA;AAEnF,IAAA,MAAM,GAAA,GAAMD,qBAAA,CAAK,OAAA,CAAQ,MAAM;AAC7B,MAAA,MAAM,MAAA,GAAS,KAAK,cAAA,EAAe;AACnC,MAAAA,qBAAA,CAAK,IAAI,IAAA,EAAM,EAAE,iBAAiB,MAAA,EAAQ,gBAAA,EAAkB,QAAQ,CAAA;AAEpE,MAAA,IAAI,oBAAA,EAAsB;AACxB,QAAAA,qBAAA,CAAK,GAAA,CAAI,IAAA,EAAM,EAAE,gBAAA,EAAkB,GAAG,CAAA;AACtC,QAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,QAAA;AAAA,MACF;AAEA,MAAAA,qBAAA,CAAK,GAAG,IAAA,EAAM;AAAA,QACZ,gBAAA,EAAkB,CAAA;AAAA,QAClB,QAAA,EAAU,CAAA;AAAA,QACV,IAAA,EAAM,YAAA;AAAA,QACN,aAAA,EAAe;AAAA,UACb,OAAA,EAAS,GAAA;AAAA,UACT,KAAA,EAAO,SAAA;AAAA,UACP,aAAA,EAAe;AAAA,SACjB;AAAA,QACA,UAAA,EAAY,MAAM,eAAA,CAAgB,IAAI;AAAA,OACvC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,OAAO,MAAM,IAAI,MAAA,EAAO;AAAA,EAC1B,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,MAAM,kBAAA,GAAqBE,iBAAA,CAAY,CAAC,MAAA,KAAsB;AAC5D,IAAA,eAAA,CAAgB,MAAM,CAAA;AACtB,IAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,EACvB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQ,aAAa,YAAY,CAAA;AAEvC,EAAA,uBACEC,cAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,uBAAA;AAAA,MACV,KAAA,EAAO,EAAE,UAAA,EAAY,uBAAA,EAAwB;AAAA,MAE7C,QAAA,kBAAAC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EACX,QAAA,EAAA;AAAA,QAAA,CAAA,IAAA,CAAK,SAAS,IAAA,CAAK,WAAA,qBACnBA,eAAA,CAACC,8BAAA,EAAA,EAAa,GAAG,EAAA,EACd,QAAA,EAAA;AAAA,UAAA,IAAA,CAAK,KAAA,oBACJF,cAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,qCAAA;AAAA,cACV,KAAA,EAAO;AAAA,gBACL,KAAA,EAAO,iCAAA;AAAA,gBACP,UAAA,EAAY;AAAA,eACd;AAAA,cAEC,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA,WACR;AAAA,UAED,KAAK,WAAA,oBACJA,cAAA;AAAA,YAAC,GAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAU,wBAAA;AAAA,cACV,KAAA,EAAO,EAAE,KAAA,EAAO,mCAAA,EAAoC;AAAA,cAEnD,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA;AACR,SAAA,EAEJ,CAAA;AAAA,wBAIFA,cAAA,CAACE,8BAAA,EAAA,EAAa,CAAA,EAAG,EAAA,EAAI,KAAA,EAAO,GAAA,EAC1B,QAAA,kBAAAF,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2BAAA,EACZ,QAAA,EAAA,gBAAA,CAAiB,GAAA,CAAI,CAAC,MAAA,qBACrBA,cAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YAEC,OAAA,EAAS,MAAM,kBAAA,CAAmB,MAAM,CAAA;AAAA,YACxC,SAAA,EAAU,uFAAA;AAAA,YACV,KAAA,EAAO;AAAA,cACL,UAAA,EACE,YAAA,KAAiB,MAAA,GACb,YAAA,CAAa,MAAM,CAAA,GACnB,2CAAA;AAAA,cACN,KAAA,EACE,YAAA,KAAiB,MAAA,GACb,SAAA,GACA,mCAAA;AAAA,cACN,QAAQ,CAAA,UAAA,EACN,YAAA,KAAiB,SACb,YAAA,CAAa,MAAM,IACnB,yCACN,CAAA;AAAA,aACF;AAAA,YAEC,uBAAa,MAAM;AAAA,WAAA;AAAA,UAnBf;AAAA,SAqBR,GACH,CAAA,EACF,CAAA;AAAA,wBAEAA,cAAA,CAACE,8BAAA,EAAA,EAAa,CAAA,EAAG,EAAA,EAAI,KAAA,EAAO,GAAA,EAC1B,QAAA,kBAAAF,cAAA,CAACG,2BAAA,EAAA,EAAU,OAAA,EAAQ,IAAA,EAAK,KAAA,EAAO,KAAA,EAC7B,QAAA,kBAAAF,eAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,MAAA;AAAA,YACL,SAAS,CAAA,IAAA,EAAO,SAAA,CAAU,UAAU,CAAA,CAAA,EAAI,UAAU,WAAW,CAAA,CAAA;AAAA,YAC7D,SAAA,EAAU,eAAA;AAAA,YACV,mBAAA,EAAoB,eAAA;AAAA,YAGnB,QAAA,EAAA;AAAA,cAAA,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM;AAC1B,gBAAA,MAAM,CAAA,GACJ,UAAU,OAAA,GACT,CAAA,GAAI,KAAM,SAAA,CAAU,WAAA,GAAc,UAAU,OAAA,GAAU,CAAA,CAAA;AACzD,gBAAA,uBACED,cAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBAEC,IAAI,SAAA,CAAU,OAAA;AAAA,oBACd,EAAA,EAAI,CAAA;AAAA,oBACJ,EAAA,EAAI,SAAA,CAAU,UAAA,GAAa,SAAA,CAAU,OAAA;AAAA,oBACrC,EAAA,EAAI,CAAA;AAAA,oBACJ,MAAA,EAAO,yCAAA;AAAA,oBACP,WAAA,EAAY;AAAA,mBAAA;AAAA,kBANP;AAAA,iBAOP;AAAA,cAEJ,CAAC,CAAA;AAAA,cAGA,SAAA,CAAU,SAAA,KAAc,MAAA,oBACvBC,eAAA,CAAAG,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,gCAAAJ,cAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,IAAI,SAAA,CAAU,SAAA;AAAA,oBACd,IAAI,SAAA,CAAU,OAAA;AAAA,oBACd,IAAI,SAAA,CAAU,SAAA;AAAA,oBACd,EAAA,EAAI,SAAA,CAAU,WAAA,GAAc,SAAA,CAAU,OAAA;AAAA,oBACtC,MAAA,EAAO,kCAAA;AAAA,oBACP,WAAA,EAAY,KAAA;AAAA,oBACZ,eAAA,EAAgB;AAAA;AAAA,iBAClB;AAAA,gCACAA,cAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,GAAG,SAAA,CAAU,SAAA;AAAA,oBACb,CAAA,EAAG,UAAU,OAAA,GAAU,EAAA;AAAA,oBACvB,UAAA,EAAW,QAAA;AAAA,oBACX,IAAA,EAAK,kCAAA;AAAA,oBACL,QAAA,EAAS,IAAA;AAAA,oBACT,UAAA,EAAW,4BAAA;AAAA,oBACZ,QAAA,EAAA;AAAA;AAAA;AAED,eAAA,EACF,CAAA;AAAA,8BAIFA,cAAA,CAAC,MAAA,EAAA,EACC,QAAA,kBAAAC,eAAA,CAAC,gBAAA,EAAA,EAAe,IAAI,CAAA,cAAA,EAAiB,YAAY,CAAA,CAAA,EAAI,EAAA,EAAG,KAAI,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,IAAG,GAAA,EAC3E,QAAA,EAAA;AAAA,gCAAAD,cAAA,CAAC,UAAK,MAAA,EAAO,IAAA,EAAK,SAAA,EAAW,KAAA,EAAO,aAAY,KAAA,EAAM,CAAA;AAAA,+CACrD,MAAA,EAAA,EAAK,MAAA,EAAO,QAAO,SAAA,EAAW,KAAA,EAAO,aAAY,GAAA,EAAI;AAAA,eAAA,EACxD,CAAA,EACF,CAAA;AAAA,cACC,YAAA,IAAgB,UAAU,KAAA,oBACzBA,cAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,GAAG,SAAA,CAAU,KAAA;AAAA,kBACb,IAAA,EAAM,sBAAsB,YAAY,CAAA,CAAA;AAAA;AAAA,eAC1C;AAAA,cAID,UAAU,CAAA,oBACTA,cAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,GAAA,EAAK,OAAA;AAAA,kBACL,GAAG,SAAA,CAAU,CAAA;AAAA,kBACb,IAAA,EAAK,MAAA;AAAA,kBACL,MAAA,EAAQ,KAAA;AAAA,kBACR,WAAA,EAAY,GAAA;AAAA,kBACZ,aAAA,EAAc,OAAA;AAAA,kBACd,cAAA,EAAe;AAAA;AAAA,eACjB;AAAA,cAID,gBACC,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAC,IAAI,CAAA,qBACxBA,cAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBAEC,IAAI,EAAA,CAAG,CAAA;AAAA,kBACP,IAAI,EAAA,CAAG,CAAA;AAAA,kBACP,CAAA,EAAE,GAAA;AAAA,kBACF,IAAA,EAAM,KAAA;AAAA,kBACN,MAAA,EAAO,uBAAA;AAAA,kBACP,WAAA,EAAY;AAAA,iBAAA;AAAA,gBANP;AAAA,eAQR,CAAA;AAAA,cAGF,SAAA,CAAU,MAAA,CAAO,GAAA,CAAI,CAAC,OAAO,CAAA,qBAC5BA,cAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBAEC,CAAA,EAAG,SAAA,CAAU,MAAA,CAAO,CAAC,GAAG,CAAA,IAAK,CAAA;AAAA,kBAC7B,CAAA,EAAG,UAAU,WAAA,GAAc,EAAA;AAAA,kBAC3B,UAAA,EAAW,QAAA;AAAA,kBACX,IAAA,EAAK,kCAAA;AAAA,kBACL,QAAA,EAAS,IAAA;AAAA,kBACT,UAAA,EAAW,4BAAA;AAAA,kBAEV,QAAA,EAAA;AAAA,iBAAA;AAAA,gBARI;AAAA,eAUR;AAAA;AAAA;AAAA,WAEL,CAAA,EACF;AAAA,OAAA,EACF;AAAA;AAAA,GACF;AAEJ","file":"MetricsTimelineSection-4L6DUHJ5.cjs","sourcesContent":["'use client';\n\nimport React, { useRef, useEffect, useState, useCallback, useMemo } from 'react';\nimport gsap from 'gsap';\nimport { ScrollTrigger } from 'gsap/ScrollTrigger';\nimport type { PortfolioMetricsTimelineData } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\nimport GlassCard from '../primitives/GlassCard';\n\ninterface MetricsTimelineSectionProps {\n data: PortfolioMetricsTimelineData;\n}\n\ntype MetricKey = 'traffic' | 'conversions' | 'revenue' | 'rankings';\n\nconst metricColors: Record<MetricKey, string> = {\n traffic: '#6366f1',\n conversions: '#10b981',\n revenue: '#f59e0b',\n rankings: '#ec4899',\n};\n\nconst metricLabels: Record<MetricKey, string> = {\n traffic: 'Traffic',\n conversions: 'Conversions',\n revenue: 'Revenue',\n rankings: 'Rankings',\n};\n\nexport default function MetricsTimelineSection({ data }: MetricsTimelineSectionProps) {\n const svgRef = useRef<SVGSVGElement>(null);\n const pathRef = useRef<SVGPathElement>(null);\n const [activeMetric, setActiveMetric] = useState<MetricKey>('traffic');\n const [hasTriggered, setHasTriggered] = useState(false);\n\n // Determine available metrics\n const availableMetrics = useMemo(() => {\n const keys: MetricKey[] = ['traffic', 'conversions', 'revenue', 'rankings'];\n return keys.filter((key) =>\n data.dataPoints.some((dp) => dp.metrics[key] !== undefined && dp.metrics[key] !== null),\n );\n }, [data.dataPoints]);\n\n // Compute chart path for the active metric\n const chartData = useMemo(() => {\n const values = data.dataPoints.map((dp) => dp.metrics[activeMetric] ?? 0);\n const maxVal = Math.max(...values, 1);\n const minVal = Math.min(...values, 0);\n const range = maxVal - minVal || 1;\n\n const chartWidth = 800;\n const chartHeight = 300;\n const padding = 40;\n\n const points = values.map((val, i) => ({\n x: padding + (i / Math.max(values.length - 1, 1)) * (chartWidth - padding * 2),\n y: chartHeight - padding - ((val - minVal) / range) * (chartHeight - padding * 2),\n }));\n\n // Build SVG path\n let d = '';\n if (points.length > 0) {\n d = `M ${points[0].x} ${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n const cpx1 = (points[i - 1].x + points[i].x) / 2;\n const cpy1 = points[i - 1].y;\n const cpx2 = (points[i - 1].x + points[i].x) / 2;\n const cpy2 = points[i].y;\n d += ` C ${cpx1} ${cpy1}, ${cpx2} ${cpy2}, ${points[i].x} ${points[i].y}`;\n }\n }\n\n // Area fill path\n let areaD = d;\n if (points.length > 0) {\n areaD += ` L ${points[points.length - 1].x} ${chartHeight - padding} L ${points[0].x} ${chartHeight - padding} Z`;\n }\n\n // Find baseline index\n const baselineIdx = data.dataPoints.findIndex((dp) => dp.month === data.baselineDate);\n const baselineX = baselineIdx >= 0 ? points[baselineIdx]?.x : undefined;\n\n return {\n d,\n areaD,\n points,\n chartWidth,\n chartHeight,\n padding,\n baselineX,\n labels: data.dataPoints.map((dp) => dp.label),\n };\n }, [data.dataPoints, data.baselineDate, activeMetric]);\n\n // Animate path draw on scroll trigger\n useEffect(() => {\n gsap.registerPlugin(ScrollTrigger);\n\n const path = pathRef.current;\n const svg = svgRef.current;\n if (!path || !svg) return;\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const ctx = gsap.context(() => {\n const length = path.getTotalLength();\n gsap.set(path, { strokeDasharray: length, strokeDashoffset: length });\n\n if (prefersReducedMotion) {\n gsap.set(path, { strokeDashoffset: 0 });\n setHasTriggered(true);\n return;\n }\n\n gsap.to(path, {\n strokeDashoffset: 0,\n duration: 2,\n ease: 'power2.out',\n scrollTrigger: {\n trigger: svg,\n start: 'top 75%',\n toggleActions: 'play none none none',\n },\n onComplete: () => setHasTriggered(true),\n });\n });\n\n return () => ctx.revert();\n }, [activeMetric]);\n\n const handleMetricChange = useCallback((metric: MetricKey) => {\n setActiveMetric(metric);\n setHasTriggered(false);\n }, []);\n\n const color = metricColors[activeMetric];\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-6xl mx-auto px-6\">\n {(data.title || data.description) && (\n <ScrollReveal y={30}>\n {data.title && (\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-4\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n )}\n {data.description && (\n <p\n className=\"text-lg mb-8 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n )}\n </ScrollReveal>\n )}\n\n {/* Metric toggle pills */}\n <ScrollReveal y={20} delay={0.1}>\n <div className=\"flex flex-wrap gap-2 mb-8\">\n {availableMetrics.map((metric) => (\n <button\n key={metric}\n onClick={() => handleMetricChange(metric)}\n className=\"px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 cursor-pointer\"\n style={{\n background:\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-surface, rgba(255,255,255,0.05))',\n color:\n activeMetric === metric\n ? '#ffffff'\n : 'var(--sk-text-secondary, #a1a1aa)',\n border: `1px solid ${\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-border, rgba(255,255,255,0.1))'\n }`,\n }}\n >\n {metricLabels[metric]}\n </button>\n ))}\n </div>\n </ScrollReveal>\n\n <ScrollReveal y={40} delay={0.2}>\n <GlassCard padding=\"lg\" hover={false}>\n <svg\n ref={svgRef}\n viewBox={`0 0 ${chartData.chartWidth} ${chartData.chartHeight}`}\n className=\"w-full h-auto\"\n preserveAspectRatio=\"xMidYMid meet\"\n >\n {/* Grid lines */}\n {[0, 1, 2, 3, 4].map((i) => {\n const y =\n chartData.padding +\n (i / 4) * (chartData.chartHeight - chartData.padding * 2);\n return (\n <line\n key={i}\n x1={chartData.padding}\n y1={y}\n x2={chartData.chartWidth - chartData.padding}\n y2={y}\n stroke=\"var(--sk-border, rgba(255,255,255,0.1))\"\n strokeWidth=\"1\"\n />\n );\n })}\n\n {/* Baseline marker */}\n {chartData.baselineX !== undefined && (\n <>\n <line\n x1={chartData.baselineX}\n y1={chartData.padding}\n x2={chartData.baselineX}\n y2={chartData.chartHeight - chartData.padding}\n stroke=\"var(--sk-text-tertiary, #71717a)\"\n strokeWidth=\"1.5\"\n strokeDasharray=\"6 4\"\n />\n <text\n x={chartData.baselineX}\n y={chartData.padding - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"11\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n Launch\n </text>\n </>\n )}\n\n {/* Area fill (gradient) */}\n <defs>\n <linearGradient id={`area-gradient-${activeMetric}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.3\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n {hasTriggered && chartData.areaD && (\n <path\n d={chartData.areaD}\n fill={`url(#area-gradient-${activeMetric})`}\n />\n )}\n\n {/* Chart line (animated draw) */}\n {chartData.d && (\n <path\n ref={pathRef}\n d={chartData.d}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {/* Data points */}\n {hasTriggered &&\n chartData.points.map((pt, i) => (\n <circle\n key={i}\n cx={pt.x}\n cy={pt.y}\n r=\"4\"\n fill={color}\n stroke=\"var(--sk-bg, #0a0a0a)\"\n strokeWidth=\"2\"\n />\n ))}\n\n {/* X-axis labels */}\n {chartData.labels.map((label, i) => (\n <text\n key={i}\n x={chartData.points[i]?.x ?? 0}\n y={chartData.chartHeight - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"10\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n {label}\n </text>\n ))}\n </svg>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/portfolio/components/sections/MetricsTimelineSection.tsx"],"names":[],"mappings":"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","file":"MetricsTimelineSection-6BT5GNFV.js","sourcesContent":["'use client';\n\nimport React, { useRef, useEffect, useState, useCallback, useMemo } from 'react';\nimport gsap from 'gsap';\nimport { ScrollTrigger } from 'gsap/ScrollTrigger';\nimport type { PortfolioMetricsTimelineData } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\nimport GlassCard from '../primitives/GlassCard';\n\ninterface MetricsTimelineSectionProps {\n data: PortfolioMetricsTimelineData;\n}\n\ntype MetricKey = 'traffic' | 'conversions' | 'revenue' | 'rankings';\n\nconst metricColors: Record<MetricKey, string> = {\n traffic: '#6366f1',\n conversions: '#10b981',\n revenue: '#f59e0b',\n rankings: '#ec4899',\n};\n\nconst metricLabels: Record<MetricKey, string> = {\n traffic: 'Traffic',\n conversions: 'Conversions',\n revenue: 'Revenue',\n rankings: 'Rankings',\n};\n\nexport default function MetricsTimelineSection({ data }: MetricsTimelineSectionProps) {\n const svgRef = useRef<SVGSVGElement>(null);\n const pathRef = useRef<SVGPathElement>(null);\n const [activeMetric, setActiveMetric] = useState<MetricKey>('traffic');\n const [hasTriggered, setHasTriggered] = useState(false);\n\n // Determine available metrics\n const availableMetrics = useMemo(() => {\n const keys: MetricKey[] = ['traffic', 'conversions', 'revenue', 'rankings'];\n return keys.filter((key) =>\n data.dataPoints.some((dp) => dp.metrics[key] !== undefined && dp.metrics[key] !== null),\n );\n }, [data.dataPoints]);\n\n // Compute chart path for the active metric\n const chartData = useMemo(() => {\n const values = data.dataPoints.map((dp) => dp.metrics[activeMetric] ?? 0);\n const maxVal = Math.max(...values, 1);\n const minVal = Math.min(...values, 0);\n const range = maxVal - minVal || 1;\n\n const chartWidth = 800;\n const chartHeight = 300;\n const padding = 40;\n\n const points = values.map((val, i) => ({\n x: padding + (i / Math.max(values.length - 1, 1)) * (chartWidth - padding * 2),\n y: chartHeight - padding - ((val - minVal) / range) * (chartHeight - padding * 2),\n }));\n\n // Build SVG path\n let d = '';\n if (points.length > 0) {\n d = `M ${points[0].x} ${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n const cpx1 = (points[i - 1].x + points[i].x) / 2;\n const cpy1 = points[i - 1].y;\n const cpx2 = (points[i - 1].x + points[i].x) / 2;\n const cpy2 = points[i].y;\n d += ` C ${cpx1} ${cpy1}, ${cpx2} ${cpy2}, ${points[i].x} ${points[i].y}`;\n }\n }\n\n // Area fill path\n let areaD = d;\n if (points.length > 0) {\n areaD += ` L ${points[points.length - 1].x} ${chartHeight - padding} L ${points[0].x} ${chartHeight - padding} Z`;\n }\n\n // Find baseline index\n const baselineIdx = data.dataPoints.findIndex((dp) => dp.month === data.baselineDate);\n const baselineX = baselineIdx >= 0 ? points[baselineIdx]?.x : undefined;\n\n return {\n d,\n areaD,\n points,\n chartWidth,\n chartHeight,\n padding,\n baselineX,\n labels: data.dataPoints.map((dp) => dp.label),\n };\n }, [data.dataPoints, data.baselineDate, activeMetric]);\n\n // Animate path draw on scroll trigger\n useEffect(() => {\n gsap.registerPlugin(ScrollTrigger);\n\n const path = pathRef.current;\n const svg = svgRef.current;\n if (!path || !svg) return;\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const ctx = gsap.context(() => {\n const length = path.getTotalLength();\n gsap.set(path, { strokeDasharray: length, strokeDashoffset: length });\n\n if (prefersReducedMotion) {\n gsap.set(path, { strokeDashoffset: 0 });\n setHasTriggered(true);\n return;\n }\n\n gsap.to(path, {\n strokeDashoffset: 0,\n duration: 2,\n ease: 'power2.out',\n scrollTrigger: {\n trigger: svg,\n start: 'top 75%',\n toggleActions: 'play none none none',\n },\n onComplete: () => setHasTriggered(true),\n });\n });\n\n return () => ctx.revert();\n }, [activeMetric]);\n\n const handleMetricChange = useCallback((metric: MetricKey) => {\n setActiveMetric(metric);\n setHasTriggered(false);\n }, []);\n\n const color = metricColors[activeMetric];\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-6xl mx-auto px-6\">\n {(data.title || data.description) && (\n <ScrollReveal y={30}>\n {data.title && (\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-4\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n )}\n {data.description && (\n <p\n className=\"text-lg mb-8 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n )}\n </ScrollReveal>\n )}\n\n {/* Metric toggle pills */}\n <ScrollReveal y={20} delay={0.1}>\n <div className=\"flex flex-wrap gap-2 mb-8\">\n {availableMetrics.map((metric) => (\n <button\n key={metric}\n onClick={() => handleMetricChange(metric)}\n className=\"px-4 py-2 rounded-full text-sm font-medium transition-all duration-200 cursor-pointer\"\n style={{\n background:\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-surface, rgba(255,255,255,0.05))',\n color:\n activeMetric === metric\n ? '#ffffff'\n : 'var(--sk-text-secondary, #a1a1aa)',\n border: `1px solid ${\n activeMetric === metric\n ? metricColors[metric]\n : 'var(--sk-border, rgba(255,255,255,0.1))'\n }`,\n }}\n >\n {metricLabels[metric]}\n </button>\n ))}\n </div>\n </ScrollReveal>\n\n <ScrollReveal y={40} delay={0.2}>\n <GlassCard padding=\"lg\" hover={false}>\n <svg\n ref={svgRef}\n viewBox={`0 0 ${chartData.chartWidth} ${chartData.chartHeight}`}\n className=\"w-full h-auto\"\n preserveAspectRatio=\"xMidYMid meet\"\n >\n {/* Grid lines */}\n {[0, 1, 2, 3, 4].map((i) => {\n const y =\n chartData.padding +\n (i / 4) * (chartData.chartHeight - chartData.padding * 2);\n return (\n <line\n key={i}\n x1={chartData.padding}\n y1={y}\n x2={chartData.chartWidth - chartData.padding}\n y2={y}\n stroke=\"var(--sk-border, rgba(255,255,255,0.1))\"\n strokeWidth=\"1\"\n />\n );\n })}\n\n {/* Baseline marker */}\n {chartData.baselineX !== undefined && (\n <>\n <line\n x1={chartData.baselineX}\n y1={chartData.padding}\n x2={chartData.baselineX}\n y2={chartData.chartHeight - chartData.padding}\n stroke=\"var(--sk-text-tertiary, #71717a)\"\n strokeWidth=\"1.5\"\n strokeDasharray=\"6 4\"\n />\n <text\n x={chartData.baselineX}\n y={chartData.padding - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"11\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n Launch\n </text>\n </>\n )}\n\n {/* Area fill (gradient) */}\n <defs>\n <linearGradient id={`area-gradient-${activeMetric}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.3\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n {hasTriggered && chartData.areaD && (\n <path\n d={chartData.areaD}\n fill={`url(#area-gradient-${activeMetric})`}\n />\n )}\n\n {/* Chart line (animated draw) */}\n {chartData.d && (\n <path\n ref={pathRef}\n d={chartData.d}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n )}\n\n {/* Data points */}\n {hasTriggered &&\n chartData.points.map((pt, i) => (\n <circle\n key={i}\n cx={pt.x}\n cy={pt.y}\n r=\"4\"\n fill={color}\n stroke=\"var(--sk-bg, #0a0a0a)\"\n strokeWidth=\"2\"\n />\n ))}\n\n {/* X-axis labels */}\n {chartData.labels.map((label, i) => (\n <text\n key={i}\n x={chartData.points[i]?.x ?? 0}\n y={chartData.chartHeight - 10}\n textAnchor=\"middle\"\n fill=\"var(--sk-text-tertiary, #71717a)\"\n fontSize=\"10\"\n fontFamily=\"var(--sk-font, sans-serif)\"\n >\n {label}\n </text>\n ))}\n </svg>\n </GlassCard>\n </ScrollReveal>\n </div>\n </section>\n );\n}\n"]}