@sonordev/agency-site-kit 0.1.0 → 0.1.2

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 (89) hide show
  1. package/dist/{BeforeAfterSection-6QUJOBO2.js → BeforeAfterSection-6BHFLY4Y.js} +6 -6
  2. package/dist/BeforeAfterSection-6BHFLY4Y.js.map +1 -0
  3. package/dist/{BeforeAfterSection-DVAWWE4K.cjs → BeforeAfterSection-JTORBR3A.cjs} +6 -6
  4. package/dist/BeforeAfterSection-JTORBR3A.cjs.map +1 -0
  5. package/dist/DesignSystemSection-2R5BRBGO.js +172 -0
  6. package/dist/DesignSystemSection-2R5BRBGO.js.map +1 -0
  7. package/dist/DesignSystemSection-KXIQXITF.cjs +174 -0
  8. package/dist/DesignSystemSection-KXIQXITF.cjs.map +1 -0
  9. package/dist/{DetailsSection-FB763FS7.js → DetailsSection-A6PZQUQL.js} +14 -5
  10. package/dist/DetailsSection-A6PZQUQL.js.map +1 -0
  11. package/dist/{DetailsSection-OACJFGH7.cjs → DetailsSection-TTUZAPZZ.cjs} +14 -5
  12. package/dist/DetailsSection-TTUZAPZZ.cjs.map +1 -0
  13. package/dist/PerformanceSection-24TVVFZA.cjs +356 -0
  14. package/dist/PerformanceSection-24TVVFZA.cjs.map +1 -0
  15. package/dist/PerformanceSection-MGCEIXDX.js +351 -0
  16. package/dist/PerformanceSection-MGCEIXDX.js.map +1 -0
  17. package/dist/SiteArchitectureSection-EE6VQSXM.cjs +349 -0
  18. package/dist/SiteArchitectureSection-EE6VQSXM.cjs.map +1 -0
  19. package/dist/SiteArchitectureSection-PBBRTARV.js +344 -0
  20. package/dist/SiteArchitectureSection-PBBRTARV.js.map +1 -0
  21. package/dist/SpeedComparisonSection-EZKFQVGW.cjs +174 -0
  22. package/dist/SpeedComparisonSection-EZKFQVGW.cjs.map +1 -0
  23. package/dist/SpeedComparisonSection-Y3K7OFZQ.js +172 -0
  24. package/dist/SpeedComparisonSection-Y3K7OFZQ.js.map +1 -0
  25. package/dist/{StrategySection-3ED3QW4R.cjs → StrategySection-CJ7Y6OFQ.cjs} +18 -24
  26. package/dist/StrategySection-CJ7Y6OFQ.cjs.map +1 -0
  27. package/dist/{StrategySection-VUWMIYYP.js → StrategySection-DI5RSCJU.js} +18 -24
  28. package/dist/StrategySection-DI5RSCJU.js.map +1 -0
  29. package/dist/TechStackSection-2AQ7RGY3.js +93 -0
  30. package/dist/TechStackSection-2AQ7RGY3.js.map +1 -0
  31. package/dist/TechStackSection-VTNNZR5V.cjs +95 -0
  32. package/dist/TechStackSection-VTNNZR5V.cjs.map +1 -0
  33. package/dist/{chunk-XMC4DN6G.js → chunk-APG2QSMB.js} +8 -8
  34. package/dist/chunk-APG2QSMB.js.map +1 -0
  35. package/dist/chunk-JTI3F3QY.cjs +619 -0
  36. package/dist/chunk-JTI3F3QY.cjs.map +1 -0
  37. package/dist/{chunk-NAS4K5UR.cjs → chunk-OA5ZM4OA.cjs} +8 -8
  38. package/dist/chunk-OA5ZM4OA.cjs.map +1 -0
  39. package/dist/{chunk-QIC6JFFD.js → chunk-OMOF4VR5.js} +14 -14
  40. package/dist/chunk-OMOF4VR5.js.map +1 -0
  41. package/dist/chunk-RLVW7WEK.js +612 -0
  42. package/dist/chunk-RLVW7WEK.js.map +1 -0
  43. package/dist/{chunk-5FKOLIV6.cjs → chunk-XM2QD3AK.cjs} +14 -14
  44. package/dist/chunk-XM2QD3AK.cjs.map +1 -0
  45. package/dist/index.cjs +13 -13
  46. package/dist/index.d.cts +2 -2
  47. package/dist/index.d.ts +2 -2
  48. package/dist/index.js +3 -3
  49. package/dist/layout/index.cjs +2 -2
  50. package/dist/layout/index.d.cts +1 -1
  51. package/dist/layout/index.d.ts +1 -1
  52. package/dist/layout/index.js +1 -1
  53. package/dist/portfolio/client.cjs +3 -3
  54. package/dist/portfolio/client.d.cts +7 -3
  55. package/dist/portfolio/client.d.ts +7 -3
  56. package/dist/portfolio/client.js +1 -1
  57. package/dist/portfolio/index.cjs +6 -6
  58. package/dist/portfolio/index.d.cts +2 -2
  59. package/dist/portfolio/index.d.ts +2 -2
  60. package/dist/portfolio/index.js +2 -2
  61. package/dist/portfolio/sections.d.cts +1 -1
  62. package/dist/portfolio/sections.d.ts +1 -1
  63. package/dist/portfolio/server.cjs +1 -0
  64. package/dist/portfolio/server.cjs.map +1 -1
  65. package/dist/portfolio/server.d.cts +1 -1
  66. package/dist/portfolio/server.d.ts +1 -1
  67. package/dist/portfolio/server.js +1 -0
  68. package/dist/portfolio/server.js.map +1 -1
  69. package/dist/{types-BMUhBhWx.d.cts → types-DL4t_Cfa.d.cts} +3 -1
  70. package/dist/{types-BMUhBhWx.d.ts → types-DL4t_Cfa.d.ts} +3 -1
  71. package/package.json +1 -1
  72. package/dist/BeforeAfterSection-6QUJOBO2.js.map +0 -1
  73. package/dist/BeforeAfterSection-DVAWWE4K.cjs.map +0 -1
  74. package/dist/DetailsSection-FB763FS7.js.map +0 -1
  75. package/dist/DetailsSection-OACJFGH7.cjs.map +0 -1
  76. package/dist/StrategySection-3ED3QW4R.cjs.map +0 -1
  77. package/dist/StrategySection-VUWMIYYP.js.map +0 -1
  78. package/dist/TechStackSection-OCUYG4XT.js +0 -90
  79. package/dist/TechStackSection-OCUYG4XT.js.map +0 -1
  80. package/dist/TechStackSection-VKJK4KQB.cjs +0 -91
  81. package/dist/TechStackSection-VKJK4KQB.cjs.map +0 -1
  82. package/dist/chunk-2VNNFAG6.js +0 -415
  83. package/dist/chunk-2VNNFAG6.js.map +0 -1
  84. package/dist/chunk-5FKOLIV6.cjs.map +0 -1
  85. package/dist/chunk-NAS4K5UR.cjs.map +0 -1
  86. package/dist/chunk-QIC6JFFD.js.map +0 -1
  87. package/dist/chunk-TAPNXT7X.cjs +0 -422
  88. package/dist/chunk-TAPNXT7X.cjs.map +0 -1
  89. package/dist/chunk-XMC4DN6G.js.map +0 -1
@@ -0,0 +1,619 @@
1
+ 'use strict';
2
+
3
+ var chunkXONXEFJY_cjs = require('./chunk-XONXEFJY.cjs');
4
+ var chunkKEOHORIH_cjs = require('./chunk-KEOHORIH.cjs');
5
+ var chunkIKBK7HYX_cjs = require('./chunk-IKBK7HYX.cjs');
6
+ var dynamic = require('next/dynamic');
7
+ var react = require('react');
8
+ var gsap2 = require('gsap');
9
+ var ScrollTrigger = require('gsap/ScrollTrigger');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
+
12
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
+
14
+ var dynamic__default = /*#__PURE__*/_interopDefault(dynamic);
15
+ var gsap2__default = /*#__PURE__*/_interopDefault(gsap2);
16
+
17
+ function SplitHeadline({
18
+ children,
19
+ tag: Tag = "h2",
20
+ className,
21
+ style,
22
+ delay = 0,
23
+ duration = 0.8,
24
+ staggerAmount = 0.02
25
+ }) {
26
+ const ref = react.useRef(null);
27
+ const splitContent = react.useMemo(() => {
28
+ const words = children.split(" ");
29
+ return words.map((word, wi) => /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-block", whiteSpace: "nowrap" }, children: [
30
+ word.split("").map((char, ci) => /* @__PURE__ */ jsxRuntime.jsx(
31
+ "span",
32
+ {
33
+ className: "split-char",
34
+ style: { display: "inline-block" },
35
+ children: char
36
+ },
37
+ ci
38
+ )),
39
+ wi < words.length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block" }, children: "\xA0" })
40
+ ] }, wi));
41
+ }, [children]);
42
+ react.useEffect(() => {
43
+ gsap2__default.default.registerPlugin(ScrollTrigger.ScrollTrigger);
44
+ const el = ref.current;
45
+ if (!el) return;
46
+ const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
47
+ if (prefersReducedMotion) {
48
+ gsap2__default.default.set(el.querySelectorAll(".split-char"), { opacity: 1, y: 0 });
49
+ return;
50
+ }
51
+ const chars = el.querySelectorAll(".split-char");
52
+ const ctx = gsap2__default.default.context(() => {
53
+ gsap2__default.default.fromTo(
54
+ chars,
55
+ {
56
+ opacity: 0,
57
+ y: 20
58
+ },
59
+ {
60
+ opacity: 1,
61
+ y: 0,
62
+ duration,
63
+ delay,
64
+ stagger: staggerAmount,
65
+ ease: "power2.out",
66
+ scrollTrigger: {
67
+ trigger: el,
68
+ start: "top 85%",
69
+ toggleActions: "play none none none"
70
+ }
71
+ }
72
+ );
73
+ }, el);
74
+ return () => ctx.revert();
75
+ }, [delay, duration, staggerAmount]);
76
+ return /* @__PURE__ */ jsxRuntime.jsx(
77
+ Tag,
78
+ {
79
+ ref,
80
+ className,
81
+ style: {
82
+ overflowX: "clip",
83
+ overflowY: "hidden",
84
+ overflowWrap: "break-word",
85
+ wordBreak: "break-word",
86
+ ...style
87
+ },
88
+ children: splitContent
89
+ }
90
+ );
91
+ }
92
+ function useScaledIframe(viewportWidth) {
93
+ const containerRef = react.useRef(null);
94
+ const [scale, setScale] = react.useState(1);
95
+ react.useEffect(() => {
96
+ const container = containerRef.current;
97
+ if (!container) return;
98
+ const updateScale = () => {
99
+ const containerWidth = container.offsetWidth;
100
+ setScale(containerWidth / viewportWidth);
101
+ };
102
+ updateScale();
103
+ const resizeObserver = new ResizeObserver(updateScale);
104
+ resizeObserver.observe(container);
105
+ return () => resizeObserver.disconnect();
106
+ }, [viewportWidth]);
107
+ return { containerRef, scale };
108
+ }
109
+ function useIframeLoadDetection() {
110
+ const [loaded, setLoaded] = react.useState(false);
111
+ const iframeRef = react.useRef(null);
112
+ const onLoad = react.useCallback(() => {
113
+ const iframe = iframeRef.current;
114
+ if (!iframe) return;
115
+ setTimeout(() => {
116
+ try {
117
+ const doc = iframe.contentDocument;
118
+ if (!doc?.body) {
119
+ return;
120
+ }
121
+ const numElements = doc.querySelectorAll("*").length;
122
+ if (numElements > 20) setLoaded(true);
123
+ } catch {
124
+ setLoaded(true);
125
+ }
126
+ }, 1500);
127
+ }, []);
128
+ return { iframeRef, loaded, onLoad };
129
+ }
130
+ function MacBookFrame({ url, screenshot }) {
131
+ const viewportWidth = 1440;
132
+ const viewportHeight = 900;
133
+ const { containerRef, scale } = useScaledIframe(viewportWidth);
134
+ const { iframeRef, loaded: iframeLoaded, onLoad: onIframeLoad } = useIframeLoadDetection();
135
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
136
+ /* @__PURE__ */ jsxRuntime.jsx(
137
+ "div",
138
+ {
139
+ className: "relative rounded-t-[10px] p-[4px] pb-0",
140
+ style: {
141
+ background: "linear-gradient(135deg, #e8e8ed 0%, #d1d1d6 100%)",
142
+ boxShadow: "0 -4px 30px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.9)"
143
+ },
144
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
145
+ "div",
146
+ {
147
+ className: "relative rounded-t-[7px] px-[8px] pt-[8px] pb-0",
148
+ style: { background: "#0a0a0a" },
149
+ children: [
150
+ /* @__PURE__ */ jsxRuntime.jsx(
151
+ "div",
152
+ {
153
+ className: "absolute top-0 left-1/2 -translate-x-1/2 w-[70px] h-[18px] flex items-center justify-center z-10",
154
+ style: { background: "#0a0a0a", borderRadius: "0 0 10px 10px" },
155
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[5px] h-[5px] rounded-full", style: { background: "#2a3a2a", boxShadow: "0 0 0 1px #1a1a1a" } })
156
+ }
157
+ ),
158
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative overflow-hidden rounded-t-[3px]", style: { aspectRatio: `${viewportWidth}/${viewportHeight}`, background: "#0a0a0a" }, children: [
159
+ screenshot && /* @__PURE__ */ jsxRuntime.jsx("img", { src: screenshot, alt: "Desktop preview", style: { width: "100%", height: "100%", objectFit: "cover", objectPosition: "top center", display: "block", position: "absolute", inset: 0, zIndex: 2, opacity: iframeLoaded ? 0 : 1, transition: "opacity 0.8s ease", pointerEvents: "none" } }),
160
+ url && /* @__PURE__ */ jsxRuntime.jsx("iframe", { src: url, title: "Desktop", loading: "eager", scrolling: "no", tabIndex: -1, sandbox: "allow-scripts allow-same-origin", ref: iframeRef, onLoad: onIframeLoad, className: "border-0 pointer-events-none", style: { position: "absolute", top: 0, left: 0, width: `${viewportWidth}px`, height: `${viewportHeight}px`, transformOrigin: "top left", transform: `scale(${scale})` } })
161
+ ] })
162
+ ]
163
+ }
164
+ )
165
+ }
166
+ ),
167
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[8px]", style: { background: "#0a0a0a", boxShadow: "0 1px 4px rgba(0,0,0,0.3)" } }),
168
+ /* @__PURE__ */ jsxRuntime.jsx(
169
+ "div",
170
+ {
171
+ className: "relative h-[12px] rounded-b-[10px]",
172
+ style: {
173
+ background: "linear-gradient(to bottom, #e0e0e5, #c8c8cd 20%, #b0b0b5 80%, #a0a0a5)",
174
+ boxShadow: "0 4px 15px rgba(0,0,0,0.3)"
175
+ },
176
+ children: /* @__PURE__ */ jsxRuntime.jsx(
177
+ "div",
178
+ {
179
+ className: "absolute top-0 left-1/2 -translate-x-1/2 w-[25%] h-[4px] rounded-b-[4px]",
180
+ style: { background: "linear-gradient(to bottom, #909095, #a8a8ad)" }
181
+ }
182
+ )
183
+ }
184
+ )
185
+ ] });
186
+ }
187
+ function IPadFrame({ url, screenshot }) {
188
+ const viewportWidth = 768;
189
+ const viewportHeight = 1024;
190
+ const { containerRef, scale } = useScaledIframe(viewportWidth);
191
+ const { iframeRef, loaded: iframeLoaded, onLoad: onIframeLoad } = useIframeLoadDetection();
192
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative p-[1.5%]", style: { background: "linear-gradient(135deg, #e8e8ed 0%, #d1d1d6 100%)", borderRadius: "8% / 6%", boxShadow: "0 30px 60px -15px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.9) inset, inset 0 1px 0 rgba(255,255,255,0.8)" }, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative p-[2%]", style: { background: "#0a0a0a", borderRadius: "6% / 4.5%" }, children: [
193
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-[1.2%] left-1/2 -translate-x-1/2 w-[1.8%] aspect-square rounded-full z-10", style: { background: "#1a1a1f" } }),
194
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative overflow-hidden", style: { borderRadius: "2%", aspectRatio: `${viewportWidth}/${viewportHeight}`, background: "#0a0a0a" }, children: [
195
+ screenshot && /* @__PURE__ */ jsxRuntime.jsx("img", { src: screenshot, alt: "Tablet preview", style: { width: "100%", height: "100%", objectFit: "cover", objectPosition: "top center", display: "block", position: "absolute", inset: 0, zIndex: 2, opacity: iframeLoaded ? 0 : 1, transition: "opacity 0.8s ease", pointerEvents: "none" } }),
196
+ url && /* @__PURE__ */ jsxRuntime.jsx("iframe", { src: url, title: "Tablet", loading: "eager", scrolling: "no", tabIndex: -1, sandbox: "allow-scripts allow-same-origin", ref: iframeRef, onLoad: onIframeLoad, className: "border-0 pointer-events-none", style: { position: "absolute", top: 0, left: 0, width: `${viewportWidth}px`, height: `${viewportHeight}px`, transformOrigin: "top left", transform: `scale(${scale})` } })
197
+ ] })
198
+ ] }) });
199
+ }
200
+ function IPhoneFrame({ url, screenshot }) {
201
+ const viewportWidth = 393;
202
+ const viewportHeight = 852;
203
+ const { containerRef, scale } = useScaledIframe(viewportWidth);
204
+ const { iframeRef, loaded: iframeLoaded, onLoad: onIframeLoad } = useIframeLoadDetection();
205
+ return /* @__PURE__ */ jsxRuntime.jsxs(
206
+ "div",
207
+ {
208
+ className: "relative p-[2.5%]",
209
+ style: {
210
+ background: "linear-gradient(135deg, #e8e8ed 0%, #d1d1d6 100%)",
211
+ borderRadius: "18% / 8%",
212
+ boxShadow: "0 30px 60px -15px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.9) inset, inset 0 1px 0 rgba(255,255,255,0.8)"
213
+ },
214
+ children: [
215
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 top-[18%] w-[1%] h-[6%] rounded-l-sm", style: { background: "#c8c8cd" } }),
216
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 top-[26%] w-[1%] h-[10%] rounded-l-sm", style: { background: "#c8c8cd" } }),
217
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 top-[38%] w-[1%] h-[10%] rounded-l-sm", style: { background: "#c8c8cd" } }),
218
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-[22%] w-[1%] h-[12%] rounded-r-sm", style: { background: "#c8c8cd" } }),
219
+ /* @__PURE__ */ jsxRuntime.jsxs(
220
+ "div",
221
+ {
222
+ className: "relative p-[3%]",
223
+ style: { background: "#0a0a0a", borderRadius: "14% / 6%" },
224
+ children: [
225
+ /* @__PURE__ */ jsxRuntime.jsx(
226
+ "div",
227
+ {
228
+ className: "absolute top-[2.5%] left-1/2 -translate-x-1/2 w-[28%] h-[3.5%] rounded-full z-10",
229
+ style: { background: "#1a1a1a" }
230
+ }
231
+ ),
232
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative overflow-hidden", style: { borderRadius: "8% / 4%", aspectRatio: `${viewportWidth}/${viewportHeight}`, background: "#0a0a0a" }, children: [
233
+ screenshot && /* @__PURE__ */ jsxRuntime.jsx("img", { src: screenshot, alt: "Mobile preview", style: { width: "100%", height: "100%", objectFit: "cover", objectPosition: "top center", display: "block", position: "absolute", inset: 0, zIndex: 2, opacity: iframeLoaded ? 0 : 1, transition: "opacity 0.8s ease", pointerEvents: "none" } }),
234
+ url && /* @__PURE__ */ jsxRuntime.jsx("iframe", { src: url, title: "Mobile", loading: "eager", scrolling: "no", tabIndex: -1, sandbox: "allow-scripts allow-same-origin", ref: iframeRef, onLoad: onIframeLoad, className: "border-0 pointer-events-none", style: { position: "absolute", top: 0, left: 0, width: `${viewportWidth}px`, height: `${viewportHeight}px`, transformOrigin: "top left", transform: `scale(${scale})` } })
235
+ ] }),
236
+ /* @__PURE__ */ jsxRuntime.jsx(
237
+ "div",
238
+ {
239
+ className: "absolute bottom-[2%] left-1/2 -translate-x-1/2 w-[34%] h-[1%] rounded-full",
240
+ style: { background: "rgba(255,255,255,0.25)" }
241
+ }
242
+ )
243
+ ]
244
+ }
245
+ )
246
+ ]
247
+ }
248
+ );
249
+ }
250
+ function DeviceTrifolio({
251
+ url,
252
+ screenshots,
253
+ className = "",
254
+ disableAnimation = false
255
+ }) {
256
+ const trifolioRef = react.useRef(null);
257
+ const frameUrl = url || "";
258
+ react.useEffect(() => {
259
+ gsap2__default.default.registerPlugin(ScrollTrigger.ScrollTrigger);
260
+ const container = trifolioRef.current;
261
+ if (!container || disableAnimation) return;
262
+ const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
263
+ if (prefersReducedMotion) return;
264
+ const macbook = container.querySelector('[data-device="macbook"]');
265
+ const ipad = container.querySelector('[data-device="ipad"]');
266
+ const iphone = container.querySelector('[data-device="iphone"]');
267
+ if (!macbook || !ipad || !iphone) return;
268
+ const ctx = gsap2__default.default.context(() => {
269
+ gsap2__default.default.set(container, { opacity: 0 });
270
+ gsap2__default.default.set(macbook, { opacity: 0, y: 40 });
271
+ gsap2__default.default.set(ipad, { opacity: 0, x: -60, y: 30 });
272
+ gsap2__default.default.set(iphone, { opacity: 0, x: 60, y: 30 });
273
+ const tl = gsap2__default.default.timeline({
274
+ scrollTrigger: {
275
+ trigger: container,
276
+ start: "top bottom",
277
+ toggleActions: "play none none none"
278
+ }
279
+ });
280
+ tl.to(container, { opacity: 1, duration: 0.3 }).to(macbook, { opacity: 1, y: 0, duration: 0.7, ease: "power2.out" }, 0.1).to(ipad, { opacity: 1, x: 0, y: 0, duration: 0.6, ease: "power2.out" }, 0.25).to(iphone, { opacity: 1, x: 0, y: 0, duration: 0.6, ease: "power2.out" }, 0.4);
281
+ }, container);
282
+ return () => ctx.revert();
283
+ }, [disableAnimation]);
284
+ return /* @__PURE__ */ jsxRuntime.jsxs(
285
+ "div",
286
+ {
287
+ ref: trifolioRef,
288
+ "data-screenshot-target": "device-trifolio",
289
+ className: `relative w-full min-w-0 max-w-full overflow-x-clip ${className}`,
290
+ style: { aspectRatio: "11/5", minHeight: "200px" },
291
+ children: [
292
+ /* @__PURE__ */ jsxRuntime.jsx(
293
+ "div",
294
+ {
295
+ "data-device": "macbook",
296
+ className: "absolute left-1/2 -translate-x-1/2 bottom-0 w-[65%] z-10",
297
+ children: /* @__PURE__ */ jsxRuntime.jsx(MacBookFrame, { url: frameUrl, screenshot: screenshots?.desktop })
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsxRuntime.jsx(
301
+ "div",
302
+ {
303
+ "data-device": "ipad",
304
+ className: "absolute left-[8%] bottom-0 w-[28%] z-20",
305
+ children: /* @__PURE__ */ jsxRuntime.jsx(IPadFrame, { url: frameUrl, screenshot: screenshots?.tablet })
306
+ }
307
+ ),
308
+ /* @__PURE__ */ jsxRuntime.jsx(
309
+ "div",
310
+ {
311
+ "data-device": "iphone",
312
+ className: "absolute right-[10%] bottom-0 w-[14%] z-30",
313
+ children: /* @__PURE__ */ jsxRuntime.jsx(IPhoneFrame, { url: frameUrl, screenshot: screenshots?.mobile })
314
+ }
315
+ )
316
+ ]
317
+ }
318
+ );
319
+ }
320
+ function HeroSection({ data, screenshots, liveUrl }) {
321
+ const bgRef = react.useRef(null);
322
+ const deviceRef = react.useRef(null);
323
+ const shots = screenshots || data.screenshots;
324
+ const url = liveUrl || data.liveUrl;
325
+ react.useEffect(() => {
326
+ gsap2__default.default.registerPlugin(ScrollTrigger.ScrollTrigger);
327
+ const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
328
+ if (prefersReducedMotion) return;
329
+ const ctx = gsap2__default.default.context(() => {
330
+ if (bgRef.current) {
331
+ gsap2__default.default.to(bgRef.current, {
332
+ yPercent: 30,
333
+ ease: "none",
334
+ scrollTrigger: {
335
+ trigger: bgRef.current.parentElement,
336
+ start: "top top",
337
+ end: "bottom top",
338
+ scrub: true
339
+ }
340
+ });
341
+ }
342
+ });
343
+ return () => ctx.revert();
344
+ }, []);
345
+ return /* @__PURE__ */ jsxRuntime.jsxs(
346
+ "section",
347
+ {
348
+ className: "relative overflow-hidden w-full",
349
+ style: {
350
+ minHeight: "90vh",
351
+ display: "flex",
352
+ flexDirection: "column",
353
+ justifyContent: "center",
354
+ background: "var(--sk-bg, #0a0a0a)"
355
+ },
356
+ children: [
357
+ /* @__PURE__ */ jsxRuntime.jsx(
358
+ "div",
359
+ {
360
+ ref: bgRef,
361
+ className: "absolute inset-0 pointer-events-none",
362
+ style: {
363
+ background: `radial-gradient(ellipse at 50% 20%, color-mix(in srgb, var(--sk-primary, #6366f1) 15%, transparent) 0%, transparent 70%)`,
364
+ willChange: "transform"
365
+ }
366
+ }
367
+ ),
368
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 max-w-7xl mx-auto w-full min-w-0 px-4 sm:px-6 py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 min-w-0 lg:grid-cols-2 gap-12 lg:gap-16 items-start", children: [
369
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 max-w-full flex-col gap-6", children: [
370
+ /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, duration: 0.6, children: /* @__PURE__ */ jsxRuntime.jsx(
371
+ "span",
372
+ {
373
+ className: "inline-flex items-center self-start px-4 py-1.5 rounded-full text-sm font-medium",
374
+ style: {
375
+ background: "color-mix(in srgb, var(--sk-primary, #6366f1) 15%, transparent)",
376
+ color: "var(--sk-primary, #6366f1)",
377
+ border: "1px solid color-mix(in srgb, var(--sk-primary, #6366f1) 25%, transparent)"
378
+ },
379
+ children: data.category?.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
380
+ }
381
+ ) }),
382
+ /* @__PURE__ */ jsxRuntime.jsx(
383
+ SplitHeadline,
384
+ {
385
+ tag: "h1",
386
+ className: "text-4xl md:text-5xl lg:text-6xl font-bold leading-tight",
387
+ style: {
388
+ color: "var(--sk-text-primary, #ffffff)",
389
+ fontFamily: "var(--sk-font-heading, inherit)"
390
+ },
391
+ children: data.headline
392
+ }
393
+ ),
394
+ /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, delay: 0.2, children: /* @__PURE__ */ jsxRuntime.jsx(
395
+ "p",
396
+ {
397
+ className: "text-xl md:text-2xl font-medium",
398
+ style: { color: "var(--sk-text-secondary, #a1a1aa)" },
399
+ children: data.subheadline
400
+ }
401
+ ) }),
402
+ /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, delay: 0.3, children: /* @__PURE__ */ jsxRuntime.jsx(
403
+ "p",
404
+ {
405
+ className: "text-base md:text-lg leading-relaxed",
406
+ style: { color: "var(--sk-text-tertiary, #71717a)" },
407
+ children: data.description
408
+ }
409
+ ) }),
410
+ data.services.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, delay: 0.4, stagger: 0.05, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: data.services.map((service) => /* @__PURE__ */ jsxRuntime.jsx(
411
+ "span",
412
+ {
413
+ className: "px-3 py-1 rounded-full text-xs font-medium",
414
+ style: {
415
+ background: "var(--sk-surface, rgba(255,255,255,0.05))",
416
+ color: "var(--sk-text-secondary, #a1a1aa)",
417
+ border: "1px solid var(--sk-border, rgba(255,255,255,0.1))"
418
+ },
419
+ children: service
420
+ },
421
+ service
422
+ )) }) }),
423
+ url && /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, delay: 0.5, children: /* @__PURE__ */ jsxRuntime.jsxs(
424
+ "a",
425
+ {
426
+ href: url,
427
+ target: "_blank",
428
+ rel: "noopener noreferrer",
429
+ className: "inline-flex items-center gap-2 self-start px-6 py-3 rounded-xl text-sm font-semibold transition-opacity hover:opacity-90",
430
+ style: {
431
+ background: "var(--sk-primary, #6366f1)",
432
+ color: "#ffffff"
433
+ },
434
+ children: [
435
+ "View Live Site",
436
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3h7v7M13 3L3 13", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
437
+ ]
438
+ }
439
+ ) })
440
+ ] }),
441
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 max-w-full flex-col gap-10 lg:pt-8", children: [
442
+ (url || shots?.desktop || shots?.tablet || shots?.mobile) && /* @__PURE__ */ jsxRuntime.jsx("div", { ref: deviceRef, className: "min-w-0 max-w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
443
+ DeviceTrifolio,
444
+ {
445
+ screenshots: {
446
+ desktop: shots?.desktop,
447
+ tablet: shots?.tablet,
448
+ mobile: shots?.mobile
449
+ },
450
+ url
451
+ }
452
+ ) }),
453
+ data.kpis.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 30, delay: 0.6, stagger: 0.1, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3", children: data.kpis.map((kpi, i) => /* @__PURE__ */ jsxRuntime.jsxs(chunkKEOHORIH_cjs.GlassCard, { padding: "sm", hover: false, className: "text-center", children: [
454
+ /* @__PURE__ */ jsxRuntime.jsx(
455
+ "div",
456
+ {
457
+ className: "text-2xl md:text-3xl font-bold",
458
+ style: { color: "var(--sk-primary, #6366f1)" },
459
+ children: /* @__PURE__ */ jsxRuntime.jsx(
460
+ chunkXONXEFJY_cjs.AnimatedCounter,
461
+ {
462
+ value: kpi.value,
463
+ suffix: kpi.suffix,
464
+ prefix: kpi.prefix,
465
+ duration: 2.5
466
+ }
467
+ )
468
+ }
469
+ ),
470
+ /* @__PURE__ */ jsxRuntime.jsx(
471
+ "div",
472
+ {
473
+ className: "text-xs mt-1 font-medium",
474
+ style: { color: "var(--sk-text-secondary, #a1a1aa)" },
475
+ children: kpi.label
476
+ }
477
+ )
478
+ ] }, i)) }) })
479
+ ] })
480
+ ] }) })
481
+ ]
482
+ }
483
+ );
484
+ }
485
+ var ChallengesSection = dynamic__default.default(() => import('./ChallengesSection-IZ3DHECS.cjs'), { ssr: true });
486
+ var StrategySection = dynamic__default.default(() => import('./StrategySection-CJ7Y6OFQ.cjs'), { ssr: true });
487
+ var ResultsSection = dynamic__default.default(() => import('./ResultsSection-XLGMMQKY.cjs'), { ssr: true });
488
+ var TechStackSection = dynamic__default.default(() => import('./TechStackSection-VTNNZR5V.cjs'), { ssr: true });
489
+ var ServicesSection = dynamic__default.default(() => import('./ServicesSection-WJMGK2MF.cjs'), { ssr: true });
490
+ var TestimonialSection = dynamic__default.default(() => import('./TestimonialSection-XPTFUQIN.cjs'), { ssr: true });
491
+ var GallerySection = dynamic__default.default(() => import('./GallerySection-WJ4PQDBI.cjs'), { ssr: true });
492
+ var VideoSection = dynamic__default.default(() => import('./VideoSection-G3DFS7UH.cjs'), { ssr: true });
493
+ var TeamSection = dynamic__default.default(() => import('./TeamSection-DZVSNZE6.cjs'), { ssr: true });
494
+ var FeatureSpotlightSection = dynamic__default.default(() => import('./FeatureSpotlightSection-WRHXS7TU.cjs'), { ssr: true });
495
+ var BeforeAfterSection = dynamic__default.default(() => import('./BeforeAfterSection-JTORBR3A.cjs'), { ssr: true });
496
+ var MetricsTimelineSection = dynamic__default.default(() => import('./MetricsTimelineSection-4L6DUHJ5.cjs'), { ssr: true });
497
+ var ConversionFunnelSection = dynamic__default.default(() => import('./ConversionFunnelSection-AUUSJ5HQ.cjs'), { ssr: true });
498
+ var PerformanceSection = dynamic__default.default(() => import('./PerformanceSection-24TVVFZA.cjs'), { ssr: true });
499
+ var SiteArchitectureSection = dynamic__default.default(() => import('./SiteArchitectureSection-EE6VQSXM.cjs'), { ssr: true });
500
+ var SpeedComparisonSection = dynamic__default.default(() => import('./SpeedComparisonSection-EZKFQVGW.cjs'), { ssr: true });
501
+ var DesignSystemSection = dynamic__default.default(() => import('./DesignSystemSection-KXIQXITF.cjs'), { ssr: true });
502
+ var DetailsSection = dynamic__default.default(() => import('./DetailsSection-TTUZAPZZ.cjs'), { ssr: true });
503
+ var CTASection = dynamic__default.default(() => import('./CTASection-4JKLXEUF.cjs'), { ssr: true });
504
+ function renderSection(section, item, index) {
505
+ const key = `${section.sectionType}-${index}`;
506
+ switch (section.sectionType) {
507
+ case "portfolioHero":
508
+ return /* @__PURE__ */ jsxRuntime.jsx(
509
+ HeroSection,
510
+ {
511
+ data: section.data,
512
+ screenshots: item.hero_screenshots ?? void 0,
513
+ liveUrl: item.live_url ?? void 0
514
+ },
515
+ key
516
+ );
517
+ case "portfolioChallenges":
518
+ return /* @__PURE__ */ jsxRuntime.jsx(ChallengesSection, { data: section.data }, key);
519
+ case "portfolioStrategy":
520
+ return /* @__PURE__ */ jsxRuntime.jsx(StrategySection, { data: section.data }, key);
521
+ case "portfolioResults":
522
+ return /* @__PURE__ */ jsxRuntime.jsx(ResultsSection, { data: section.data }, key);
523
+ case "portfolioTechStack":
524
+ return /* @__PURE__ */ jsxRuntime.jsx(TechStackSection, { data: section.data }, key);
525
+ case "portfolioServices":
526
+ return /* @__PURE__ */ jsxRuntime.jsx(ServicesSection, { data: section.data }, key);
527
+ case "portfolioTestimonial":
528
+ return /* @__PURE__ */ jsxRuntime.jsx(TestimonialSection, { data: section.data }, key);
529
+ case "portfolioGallery":
530
+ return /* @__PURE__ */ jsxRuntime.jsx(GallerySection, { data: section.data }, key);
531
+ case "portfolioVideo":
532
+ return /* @__PURE__ */ jsxRuntime.jsx(VideoSection, { data: section.data }, key);
533
+ case "portfolioTeam":
534
+ return /* @__PURE__ */ jsxRuntime.jsx(TeamSection, { data: section.data }, key);
535
+ case "portfolioFeatureSpotlight":
536
+ return /* @__PURE__ */ jsxRuntime.jsx(FeatureSpotlightSection, { data: section.data }, key);
537
+ case "portfolioBeforeAfter":
538
+ return /* @__PURE__ */ jsxRuntime.jsx(BeforeAfterSection, { data: section.data }, key);
539
+ case "portfolioMetricsTimeline":
540
+ return /* @__PURE__ */ jsxRuntime.jsx(MetricsTimelineSection, { data: section.data }, key);
541
+ case "portfolioConversionFunnel":
542
+ return /* @__PURE__ */ jsxRuntime.jsx(ConversionFunnelSection, { data: section.data }, key);
543
+ case "portfolioPerformance":
544
+ return /* @__PURE__ */ jsxRuntime.jsx(PerformanceSection, { data: section.data }, key);
545
+ case "portfolioSpeedComparison":
546
+ return /* @__PURE__ */ jsxRuntime.jsx(SpeedComparisonSection, { data: section.data }, key);
547
+ case "portfolioSiteArchitecture":
548
+ return /* @__PURE__ */ jsxRuntime.jsx(SiteArchitectureSection, { data: section.data }, key);
549
+ case "portfolioDesignSystem":
550
+ return /* @__PURE__ */ jsxRuntime.jsx(DesignSystemSection, { data: section.data }, key);
551
+ case "portfolioDetails":
552
+ return /* @__PURE__ */ jsxRuntime.jsx(DetailsSection, { data: section.data }, key);
553
+ case "portfolioCTA":
554
+ return /* @__PURE__ */ jsxRuntime.jsx(CTASection, { data: section.data }, key);
555
+ case "portfolioSeo":
556
+ return null;
557
+ default:
558
+ return null;
559
+ }
560
+ }
561
+ var SECTION_ORDER = {
562
+ portfolioHero: 0,
563
+ portfolioChallenges: 1,
564
+ portfolioStrategy: 2,
565
+ portfolioResults: 3,
566
+ portfolioPerformance: 4,
567
+ portfolioSpeedComparison: 5,
568
+ portfolioSiteArchitecture: 6,
569
+ portfolioTechStack: 7,
570
+ portfolioDesignSystem: 8,
571
+ portfolioServices: 9,
572
+ portfolioBeforeAfter: 10,
573
+ portfolioTestimonial: 11,
574
+ portfolioMetricsTimeline: 12,
575
+ portfolioConversionFunnel: 13,
576
+ portfolioDetails: 11,
577
+ portfolioSeo: 12,
578
+ portfolioCta: 13
579
+ };
580
+ function PortfolioPage({ item }) {
581
+ const sortedSections = [...item.sections].sort(
582
+ (a, b) => (SECTION_ORDER[a.sectionType] ?? 99) - (SECTION_ORDER[b.sectionType] ?? 99)
583
+ );
584
+ return /* @__PURE__ */ jsxRuntime.jsx("article", { className: "flex w-full min-w-0 max-w-full flex-col overflow-x-clip", children: sortedSections.map((section, index) => {
585
+ const rendered = renderSection(section, item, index);
586
+ if (!rendered) return null;
587
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: rendered }, `wrapper-${section.sectionType}-${index}`);
588
+ }) });
589
+ }
590
+
591
+ // src/types.ts
592
+ var PORTFOLIO_SECTION_TYPES = [
593
+ "portfolioHero",
594
+ "portfolioChallenges",
595
+ "portfolioStrategy",
596
+ "portfolioResults",
597
+ "portfolioTechStack",
598
+ "portfolioServices",
599
+ "portfolioTestimonial",
600
+ "portfolioGallery",
601
+ "portfolioVideo",
602
+ "portfolioTeam",
603
+ "portfolioFeatureSpotlight",
604
+ "portfolioBeforeAfter",
605
+ "portfolioMetricsTimeline",
606
+ "portfolioConversionFunnel",
607
+ "portfolioPerformance",
608
+ "portfolioSpeedComparison",
609
+ "portfolioSiteArchitecture",
610
+ "portfolioDesignSystem",
611
+ "portfolioDetails",
612
+ "portfolioSeo",
613
+ "portfolioCTA"
614
+ ];
615
+
616
+ exports.PORTFOLIO_SECTION_TYPES = PORTFOLIO_SECTION_TYPES;
617
+ exports.PortfolioPage = PortfolioPage;
618
+ //# sourceMappingURL=chunk-JTI3F3QY.cjs.map
619
+ //# sourceMappingURL=chunk-JTI3F3QY.cjs.map