@prosophia/lab-minimal 0.0.3 → 0.0.5

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.
package/dist/index.js CHANGED
@@ -30,241 +30,120 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AnimatedCard: () => AnimatedCard,
34
+ AnimatedGalleryGrid: () => AnimatedGalleryGrid,
35
+ AnimatedGalleryHeader: () => AnimatedGalleryHeader,
36
+ AnimatedGrid: () => AnimatedGrid,
37
+ AnimatedHeader: () => AnimatedHeader,
33
38
  AnimatedHero: () => AnimatedHero,
39
+ AnimatedHeroContent: () => AnimatedHeroContent,
40
+ AnimatedImage: () => AnimatedImage,
41
+ AnimatedItem: () => AnimatedItem,
42
+ AnimatedList: () => AnimatedList,
43
+ AnimatedMain: () => AnimatedMain,
44
+ AnimatedPage: () => AnimatedPage,
45
+ AnimatedSection: () => AnimatedSection,
46
+ AnimatedSectionHeader: () => AnimatedSectionHeader,
47
+ AnimatedStats: () => AnimatedStats,
34
48
  ClientLayout: () => ClientLayout,
35
49
  ContactCTA: () => ContactCTA,
36
50
  Footer: () => Footer,
37
51
  Header: () => Header,
38
- ThemeToggle: () => ThemeToggle
52
+ HomePage: () => HomePage,
53
+ ScrollRevealSection: () => ScrollRevealSection,
54
+ StaggeredGrid: () => StaggeredGrid,
55
+ ThemeToggle: () => ThemeToggle,
56
+ cardHover: () => cardHover,
57
+ client: () => client,
58
+ defineConfig: () => defineConfig,
59
+ escapeHtml: () => escapeHtml,
60
+ fadeIn: () => fadeIn,
61
+ fadeInUp: () => fadeInUp,
62
+ fadeInUpShort: () => fadeInUpShort,
63
+ getClient: () => getClient,
64
+ imageZoom: () => imageZoom,
65
+ isValidEmail: () => isValidEmail,
66
+ isValidExternalUrl: () => isValidExternalUrl,
67
+ isValidGoogleMapsEmbedUrl: () => isValidGoogleMapsEmbedUrl,
68
+ isValidSlug: () => isValidSlug,
69
+ pageTransition: () => pageTransition,
70
+ reducedMotion: () => reducedMotion,
71
+ sanitizeUrl: () => sanitizeUrl,
72
+ scaleIn: () => scaleIn,
73
+ scrollReveal: () => scrollReveal,
74
+ slideInLeft: () => slideInLeft,
75
+ slideInRight: () => slideInRight,
76
+ staggerContainer: () => staggerContainer,
77
+ staggerItem: () => staggerItem,
78
+ urlFor: () => urlFor,
79
+ viewportSettings: () => viewportSettings
39
80
  });
40
81
  module.exports = __toCommonJS(index_exports);
41
82
 
42
- // src/components/AnimatedCard.tsx
43
- var import_framer_motion = require("framer-motion");
44
-
45
- // src/lib/animations.ts
46
- var fadeInUp = {
47
- hidden: { opacity: 0, y: 30 },
48
- visible: {
49
- opacity: 1,
50
- y: 0,
51
- transition: {
52
- duration: 0.8,
53
- ease: [0.65, 0, 0.35, 1]
54
- }
55
- }
56
- };
57
- var scaleIn = {
58
- hidden: { opacity: 0, scale: 0.9 },
59
- visible: {
60
- opacity: 1,
61
- scale: 1,
62
- transition: {
63
- duration: 0.8,
64
- ease: [0.65, 0, 0.35, 1]
65
- }
66
- }
67
- };
68
-
69
- // src/components/AnimatedCard.tsx
70
- var import_jsx_runtime = require("react/jsx-runtime");
71
-
72
- // src/components/AnimatedGallery.tsx
73
- var import_framer_motion2 = require("framer-motion");
74
- var import_image = __toESM(require("next/image"));
75
- var import_react = require("react");
76
- var import_PicturesPage = __toESM(require("./PicturesPage.module.css"));
77
- var import_jsx_runtime2 = require("react/jsx-runtime");
78
-
79
- // src/components/AnimatedHero.tsx
80
- var import_framer_motion3 = require("framer-motion");
81
- var import_react2 = require("react");
82
- var import_image2 = __toESM(require("next/image"));
83
- var import_link = __toESM(require("next/link"));
84
- var import_HomePage = __toESM(require("./HomePage.module.css"));
85
- var import_jsx_runtime3 = require("react/jsx-runtime");
86
- function AnimatedHero({ heroData, ArrowRightIcon }) {
87
- const ref = (0, import_react2.useRef)(null);
88
- const { scrollY } = (0, import_framer_motion3.useScroll)();
89
- const y = (0, import_framer_motion3.useTransform)(scrollY, [0, 500], [0, 150]);
90
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("section", { className: import_HomePage.default.heroSection, ref, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_HomePage.default.heroContainer, children: [
91
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
92
- import_framer_motion3.motion.div,
93
- {
94
- className: import_HomePage.default.heroContent,
95
- initial: "hidden",
96
- animate: "visible",
97
- variants: fadeInUp,
98
- children: [
99
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
100
- import_framer_motion3.motion.span,
101
- {
102
- className: import_HomePage.default.heroTagline,
103
- initial: { opacity: 0 },
104
- animate: { opacity: 1 },
105
- transition: { duration: 0.6, delay: 0.2 },
106
- children: heroData.tagline
107
- }
108
- ),
109
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
110
- import_framer_motion3.motion.h1,
111
- {
112
- className: import_HomePage.default.heroHeading,
113
- initial: { opacity: 0, y: 20 },
114
- animate: { opacity: 1, y: 0 },
115
- transition: { duration: 0.8, delay: 0.3 },
116
- children: [
117
- heroData.heading,
118
- " ",
119
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: import_HomePage.default.heroHeadingAccent, children: heroData.headingAccent })
120
- ]
121
- }
122
- ),
123
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
124
- import_framer_motion3.motion.p,
125
- {
126
- className: import_HomePage.default.heroDescription,
127
- initial: { opacity: 0, y: 20 },
128
- animate: { opacity: 1, y: 0 },
129
- transition: { duration: 0.8, delay: 0.4 },
130
- children: heroData.description
131
- }
132
- ),
133
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
134
- import_framer_motion3.motion.div,
135
- {
136
- className: import_HomePage.default.heroCtas,
137
- initial: { opacity: 0, y: 20 },
138
- animate: { opacity: 1, y: 0 },
139
- transition: { duration: 0.8, delay: 0.5 },
140
- children: [
141
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_link.default, { href: heroData.ctaLink, className: import_HomePage.default.heroPrimaryCta, children: [
142
- heroData.ctaText,
143
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ArrowRightIcon, {})
144
- ] }),
145
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link.default, { href: "/publications", className: import_HomePage.default.heroSecondaryCta, children: "View Publications" })
146
- ]
147
- }
148
- )
149
- ]
150
- }
151
- ),
152
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
153
- import_framer_motion3.motion.div,
154
- {
155
- className: import_HomePage.default.heroImageWrapper,
156
- style: { y },
157
- initial: "hidden",
158
- animate: "visible",
159
- variants: scaleIn,
160
- transition: { duration: 0.8, delay: 0.6 },
161
- children: heroData.image ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
162
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
163
- import_image2.default,
164
- {
165
- src: heroData.image,
166
- alt: "Research lab",
167
- width: 800,
168
- height: 600,
169
- className: import_HomePage.default.heroImage,
170
- priority: true
171
- }
172
- ),
173
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: import_HomePage.default.heroImageOverlay })
174
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: import_HomePage.default.heroImagePlaceholder, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
175
- "svg",
176
- {
177
- width: "120",
178
- height: "120",
179
- viewBox: "0 0 24 24",
180
- fill: "none",
181
- stroke: "currentColor",
182
- strokeWidth: "1",
183
- children: [
184
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
185
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
186
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M21 15l-5-5L5 21" })
187
- ]
188
- }
189
- ) })
190
- }
191
- )
192
- ] }) });
193
- }
194
-
195
- // src/components/AnimatedPage.tsx
196
- var import_framer_motion4 = require("framer-motion");
197
- var import_react3 = require("react");
198
- var import_jsx_runtime4 = require("react/jsx-runtime");
199
-
200
- // src/components/AnimatedSections.tsx
201
- var import_framer_motion5 = require("framer-motion");
202
- var import_jsx_runtime5 = require("react/jsx-runtime");
203
-
204
83
  // src/components/ClientLayout.tsx
205
- var import_react6 = require("react");
84
+ var import_react3 = require("react");
206
85
  var import_next_themes2 = require("next-themes");
207
86
 
208
87
  // src/components/Header.tsx
209
- var import_link2 = __toESM(require("next/link"));
210
- var import_react5 = require("react");
88
+ var import_link = __toESM(require("next/link"));
89
+ var import_react2 = require("react");
211
90
  var import_navigation = require("next/navigation");
212
91
  var import_Layout = __toESM(require("./Layout.module.css"));
213
92
 
214
93
  // src/components/ThemeToggle.tsx
215
94
  var import_next_themes = require("next-themes");
216
- var import_react4 = require("react");
217
- var import_framer_motion6 = require("framer-motion");
95
+ var import_react = require("react");
96
+ var import_framer_motion = require("framer-motion");
218
97
  var import_ThemeToggle = __toESM(require("./ThemeToggle.module.css"));
219
- var import_jsx_runtime6 = require("react/jsx-runtime");
98
+ var import_jsx_runtime = require("react/jsx-runtime");
220
99
  function ThemeToggle() {
221
100
  const { theme, setTheme, resolvedTheme } = (0, import_next_themes.useTheme)();
222
- const [mounted, setMounted] = (0, import_react4.useState)(false);
223
- (0, import_react4.useEffect)(() => {
101
+ const [mounted, setMounted] = (0, import_react.useState)(false);
102
+ (0, import_react.useEffect)(() => {
224
103
  setMounted(true);
225
104
  }, []);
226
105
  if (!mounted) {
227
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: import_ThemeToggle.default.togglePlaceholder });
106
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: import_ThemeToggle.default.togglePlaceholder });
228
107
  }
229
108
  const isDark = resolvedTheme === "dark";
230
109
  const toggleTheme = () => {
231
110
  setTheme(isDark ? "light" : "dark");
232
111
  };
233
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
234
- import_framer_motion6.motion.button,
112
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
113
+ import_framer_motion.motion.button,
235
114
  {
236
115
  className: import_ThemeToggle.default.toggle,
237
116
  onClick: toggleTheme,
238
117
  "aria-label": `Switch to ${isDark ? "light" : "dark"} mode`,
239
118
  whileTap: { scale: 0.95 },
240
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: import_ThemeToggle.default.track, children: [
241
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `${import_ThemeToggle.default.icon} ${import_ThemeToggle.default.sunIcon} ${!isDark ? import_ThemeToggle.default.iconActive : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
242
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
243
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
244
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
245
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
246
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
247
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
248
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
249
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
250
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
119
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: import_ThemeToggle.default.track, children: [
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `${import_ThemeToggle.default.icon} ${import_ThemeToggle.default.sunIcon} ${!isDark ? import_ThemeToggle.default.iconActive : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
121
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
122
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
251
130
  ] }) }),
252
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
253
- import_framer_motion6.motion.span,
131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
132
+ import_framer_motion.motion.span,
254
133
  {
255
134
  className: import_ThemeToggle.default.thumb,
256
135
  animate: { x: isDark ? 26 : 0 },
257
136
  transition: { type: "spring", stiffness: 500, damping: 30 }
258
137
  }
259
138
  ),
260
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `${import_ThemeToggle.default.icon} ${import_ThemeToggle.default.moonIcon} ${isDark ? import_ThemeToggle.default.iconActive : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }) })
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `${import_ThemeToggle.default.icon} ${import_ThemeToggle.default.moonIcon} ${isDark ? import_ThemeToggle.default.iconActive : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }) })
261
140
  ] })
262
141
  }
263
142
  );
264
143
  }
265
144
 
266
145
  // src/components/Header.tsx
267
- var import_jsx_runtime7 = require("react/jsx-runtime");
146
+ var import_jsx_runtime2 = require("react/jsx-runtime");
268
147
  var navLinks = [
269
148
  { href: "/research", label: "Research" },
270
149
  { href: "/publications", label: "Publications" },
@@ -273,17 +152,17 @@ var navLinks = [
273
152
  { href: "/pictures", label: "Gallery" }
274
153
  ];
275
154
  function Header({ settings }) {
276
- const [menuOpen, setMenuOpen] = (0, import_react5.useState)(false);
277
- const [scrolled, setScrolled] = (0, import_react5.useState)(false);
155
+ const [menuOpen, setMenuOpen] = (0, import_react2.useState)(false);
156
+ const [scrolled, setScrolled] = (0, import_react2.useState)(false);
278
157
  const pathname = (0, import_navigation.usePathname)();
279
- (0, import_react5.useEffect)(() => {
158
+ (0, import_react2.useEffect)(() => {
280
159
  const handleScroll = () => {
281
160
  setScrolled(window.scrollY > 20);
282
161
  };
283
162
  window.addEventListener("scroll", handleScroll, { passive: true });
284
163
  return () => window.removeEventListener("scroll", handleScroll);
285
164
  }, []);
286
- (0, import_react5.useEffect)(() => {
165
+ (0, import_react2.useEffect)(() => {
287
166
  if (menuOpen) {
288
167
  document.body.style.overflow = "hidden";
289
168
  } else {
@@ -293,15 +172,15 @@ function Header({ settings }) {
293
172
  document.body.style.overflow = "";
294
173
  };
295
174
  }, [menuOpen]);
296
- (0, import_react5.useEffect)(() => {
175
+ (0, import_react2.useEffect)(() => {
297
176
  setMenuOpen(false);
298
177
  }, [pathname]);
299
- const handleKeyDown = (0, import_react5.useCallback)((e) => {
178
+ const handleKeyDown = (0, import_react2.useCallback)((e) => {
300
179
  if (e.key === "Escape" && menuOpen) {
301
180
  setMenuOpen(false);
302
181
  }
303
182
  }, [menuOpen]);
304
- (0, import_react5.useEffect)(() => {
183
+ (0, import_react2.useEffect)(() => {
305
184
  document.addEventListener("keydown", handleKeyDown);
306
185
  return () => document.removeEventListener("keydown", handleKeyDown);
307
186
  }, [handleKeyDown]);
@@ -309,9 +188,9 @@ function Header({ settings }) {
309
188
  if (href === "/") return pathname === "/";
310
189
  return pathname.startsWith(href);
311
190
  };
312
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("header", { className: `${import_Layout.default.header} ${scrolled ? import_Layout.default.headerScrolled : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: import_Layout.default.navContainer, children: [
313
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_link2.default, { href: "/", className: import_Layout.default.navLogo, "aria-label": "Go to homepage", children: [
314
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
191
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("header", { className: `${import_Layout.default.header} ${scrolled ? import_Layout.default.headerScrolled : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: import_Layout.default.navContainer, children: [
192
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_link.default, { href: "/", className: import_Layout.default.navLogo, "aria-label": "Go to homepage", children: [
193
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
315
194
  "svg",
316
195
  {
317
196
  width: "32",
@@ -321,7 +200,7 @@ function Header({ settings }) {
321
200
  xmlns: "http://www.w3.org/2000/svg",
322
201
  "aria-hidden": "true",
323
202
  children: [
324
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
203
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
325
204
  "path",
326
205
  {
327
206
  d: "M12 2L2 7L12 12L22 7L12 2Z",
@@ -331,7 +210,7 @@ function Header({ settings }) {
331
210
  strokeLinejoin: "round"
332
211
  }
333
212
  ),
334
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
213
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
335
214
  "path",
336
215
  {
337
216
  d: "M2 17L12 22L22 17",
@@ -341,7 +220,7 @@ function Header({ settings }) {
341
220
  strokeLinejoin: "round"
342
221
  }
343
222
  ),
344
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
223
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
345
224
  "path",
346
225
  {
347
226
  d: "M2 12L12 17L22 12",
@@ -354,16 +233,16 @@ function Header({ settings }) {
354
233
  ]
355
234
  }
356
235
  ),
357
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
236
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
358
237
  settings.labName || "Research",
359
- settings.labNameAccent && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: import_Layout.default.navLogoAccent, children: [
238
+ settings.labNameAccent && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: import_Layout.default.navLogoAccent, children: [
360
239
  " ",
361
240
  settings.labNameAccent
362
241
  ] })
363
242
  ] })
364
243
  ] }),
365
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("nav", { className: import_Layout.default.desktopNav, "aria-label": "Main navigation", children: navLinks.map((link) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
366
- import_link2.default,
244
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("nav", { className: import_Layout.default.desktopNav, "aria-label": "Main navigation", children: navLinks.map((link) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
245
+ import_link.default,
367
246
  {
368
247
  href: link.href,
369
248
  className: `${import_Layout.default.navLink} ${isActive(link.href) ? import_Layout.default.navLinkActive : ""}`,
@@ -371,11 +250,11 @@ function Header({ settings }) {
371
250
  },
372
251
  link.href
373
252
  )) }),
374
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: import_Layout.default.navActions, children: [
375
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThemeToggle, {}),
376
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_link2.default, { href: "/contact", className: import_Layout.default.navCta, children: "Contact Us" })
253
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: import_Layout.default.navActions, children: [
254
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThemeToggle, {}),
255
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { href: "/contact", className: import_Layout.default.navCta, children: "Contact Us" })
377
256
  ] }),
378
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
257
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
379
258
  "button",
380
259
  {
381
260
  className: import_Layout.default.menuButton,
@@ -383,21 +262,21 @@ function Header({ settings }) {
383
262
  "aria-label": menuOpen ? "Close menu" : "Open menu",
384
263
  "aria-expanded": menuOpen,
385
264
  "aria-controls": "mobile-menu",
386
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: import_Layout.default.menuButtonLines, children: [
387
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `${import_Layout.default.menuLine} ${menuOpen ? import_Layout.default.menuLineOpen1 : ""}` }),
388
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `${import_Layout.default.menuLine} ${menuOpen ? import_Layout.default.menuLineOpen2 : ""}` }),
389
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `${import_Layout.default.menuLine} ${menuOpen ? import_Layout.default.menuLineOpen3 : ""}` })
265
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: import_Layout.default.menuButtonLines, children: [
266
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${import_Layout.default.menuLine} ${menuOpen ? import_Layout.default.menuLineOpen1 : ""}` }),
267
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${import_Layout.default.menuLine} ${menuOpen ? import_Layout.default.menuLineOpen2 : ""}` }),
268
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: `${import_Layout.default.menuLine} ${menuOpen ? import_Layout.default.menuLineOpen3 : ""}` })
390
269
  ] })
391
270
  }
392
271
  ),
393
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
272
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
394
273
  "div",
395
274
  {
396
275
  id: "mobile-menu",
397
276
  className: `${import_Layout.default.mobileMenu} ${menuOpen ? import_Layout.default.mobileMenuOpen : ""}`,
398
277
  "aria-hidden": !menuOpen,
399
278
  children: [
400
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
279
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
401
280
  "div",
402
281
  {
403
282
  className: import_Layout.default.mobileMenuOverlay,
@@ -405,14 +284,14 @@ function Header({ settings }) {
405
284
  "aria-hidden": "true"
406
285
  }
407
286
  ),
408
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
287
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
409
288
  "nav",
410
289
  {
411
290
  className: import_Layout.default.mobileMenuContent,
412
291
  "aria-label": "Mobile navigation",
413
292
  children: [
414
- navLinks.map((link, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
415
- import_link2.default,
293
+ navLinks.map((link, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
294
+ import_link.default,
416
295
  {
417
296
  href: link.href,
418
297
  className: `${import_Layout.default.mobileNavLink} ${isActive(link.href) ? import_Layout.default.mobileNavLinkActive : ""}`,
@@ -422,8 +301,8 @@ function Header({ settings }) {
422
301
  },
423
302
  link.href
424
303
  )),
425
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
426
- import_link2.default,
304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
305
+ import_link.default,
427
306
  {
428
307
  href: "/contact",
429
308
  className: import_Layout.default.mobileNavCta,
@@ -442,7 +321,7 @@ function Header({ settings }) {
442
321
  }
443
322
 
444
323
  // src/components/Footer.tsx
445
- var import_link3 = __toESM(require("next/link"));
324
+ var import_link2 = __toESM(require("next/link"));
446
325
  var import_Footer = __toESM(require("./Footer.module.css"));
447
326
 
448
327
  // src/lib/utils.ts
@@ -455,64 +334,104 @@ function isValidExternalUrl(url) {
455
334
  return false;
456
335
  }
457
336
  }
337
+ function isValidGoogleMapsEmbedUrl(url) {
338
+ if (!url || typeof url !== "string") return false;
339
+ try {
340
+ const parsed = new URL(url);
341
+ const allowedHosts = [
342
+ "www.google.com",
343
+ "google.com",
344
+ "maps.google.com"
345
+ ];
346
+ return parsed.protocol === "https:" && allowedHosts.includes(parsed.hostname) && parsed.pathname.startsWith("/maps/embed");
347
+ } catch {
348
+ return false;
349
+ }
350
+ }
351
+ function sanitizeUrl(url) {
352
+ if (isValidExternalUrl(url)) {
353
+ return url;
354
+ }
355
+ return void 0;
356
+ }
357
+ function isValidEmail(email) {
358
+ if (!email || typeof email !== "string") return false;
359
+ const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
360
+ return emailPattern.test(email) && email.length <= 254;
361
+ }
362
+ function escapeHtml(text) {
363
+ const htmlEntities = {
364
+ "&": "&amp;",
365
+ "<": "&lt;",
366
+ ">": "&gt;",
367
+ '"': "&quot;",
368
+ "'": "&#39;"
369
+ };
370
+ return text.replace(/[&<>"']/g, (char) => htmlEntities[char]);
371
+ }
372
+ function isValidSlug(slug) {
373
+ if (!slug || typeof slug !== "string") return false;
374
+ const slugPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
375
+ return slugPattern.test(slug) && slug.length <= 200;
376
+ }
458
377
 
459
378
  // src/components/Footer.tsx
460
- var import_jsx_runtime8 = require("react/jsx-runtime");
461
- var SocialIcon = ({ href, children }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: import_Footer.default.socialIcon, children });
379
+ var import_jsx_runtime3 = require("react/jsx-runtime");
380
+ var SocialIcon = ({ href, children }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: import_Footer.default.socialIcon, children });
462
381
  function Footer({ settings }) {
463
382
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
464
383
  const showPrivacy = settings?.showPrivacyPolicy !== false;
465
384
  const showTerms = settings?.showTerms !== false;
466
385
  const hasLegalLinks = showPrivacy || showTerms;
467
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("footer", { className: import_Footer.default.footerWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerContainer, children: [
468
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.mainFooter, children: [
469
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerAbout, children: [
470
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_link3.default, { href: "/", className: import_Footer.default.footerLogo, children: [
386
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("footer", { className: import_Footer.default.footerWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerContainer, children: [
387
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.mainFooter, children: [
388
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerAbout, children: [
389
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_link2.default, { href: "/", className: import_Footer.default.footerLogo, children: [
471
390
  settings?.labName || "Cavendish",
472
391
  " ",
473
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: import_Footer.default.logoAccent, children: settings?.labNameAccent || "Lab" })
392
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: import_Footer.default.logoAccent, children: settings?.labNameAccent || "Lab" })
474
393
  ] }),
475
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: import_Footer.default.footerDescription, children: settings?.labNameDescription || "Advancing the frontiers of physics and our understanding of the universe." }),
476
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.socials, children: [
477
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SocialIcon, { href: "#", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" }) }) }),
478
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SocialIcon, { href: "#", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24h-6.617l-5.21-6.817-6.044 6.817h-3.308l7.73-8.835-7.73-10.668h6.78l4.522 6.312 5.59-6.312z" }) }) })
394
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: import_Footer.default.footerDescription, children: settings?.labNameDescription || "Advancing the frontiers of physics and our understanding of the universe." }),
395
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.socials, children: [
396
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SocialIcon, { href: "#", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" }) }) }),
397
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SocialIcon, { href: "#", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24h-6.617l-5.21-6.817-6.044 6.817h-3.308l7.73-8.835-7.73-10.668h6.78l4.522 6.312 5.59-6.312z" }) }) })
479
398
  ] })
480
399
  ] }),
481
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerLinksGrid, children: [
482
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerColumn, children: [
483
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Quick Links" }),
484
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/research", children: "Research" }),
485
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/publications", children: "Publications" }),
486
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/pictures", children: "Gallery" })
400
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerLinksGrid, children: [
401
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerColumn, children: [
402
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h4", { children: "Quick Links" }),
403
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/research", children: "Research" }),
404
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/publications", children: "Publications" }),
405
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/pictures", children: "Gallery" })
487
406
  ] }),
488
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerColumn, children: [
489
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "About" }),
490
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/news", children: "News" }),
491
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/people", children: "Our Team" }),
492
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/contact", children: "Contact" })
407
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerColumn, children: [
408
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h4", { children: "About" }),
409
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/news", children: "News" }),
410
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/people", children: "Our Team" }),
411
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/contact", children: "Contact" })
493
412
  ] }),
494
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerColumn, children: [
495
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { children: "Resources" }),
496
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "https://www.cam.ac.uk/", children: "University" }),
497
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "#", children: "Careers" })
413
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerColumn, children: [
414
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h4", { children: "Resources" }),
415
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "https://www.cam.ac.uk/", children: "University" }),
416
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "#", children: "Careers" })
498
417
  ] })
499
418
  ] })
500
419
  ] }),
501
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.footerBottomBar, children: [
502
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { children: settings?.footerText || `\xA9 ${currentYear} The Research Group. All Rights Reserved.` }),
503
- hasLegalLinks && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: import_Footer.default.legalLinks, children: [
504
- showPrivacy && (settings?.privacyPolicyUrl && isValidExternalUrl(settings.privacyPolicyUrl) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href: settings.privacyPolicyUrl, target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/privacy", children: "Privacy Policy" })),
505
- showTerms && (settings?.termsUrl && isValidExternalUrl(settings.termsUrl) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("a", { href: settings.termsUrl, target: "_blank", rel: "noopener noreferrer", children: "Terms & Conditions" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_link3.default, { href: "/terms", children: "Terms & Conditions" }))
420
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.footerBottomBar, children: [
421
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: settings?.footerText || `\xA9 ${currentYear} The Research Group. All Rights Reserved.` }),
422
+ hasLegalLinks && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: import_Footer.default.legalLinks, children: [
423
+ showPrivacy && (settings?.privacyPolicyUrl && isValidExternalUrl(settings.privacyPolicyUrl) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: settings.privacyPolicyUrl, target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/privacy", children: "Privacy Policy" })),
424
+ showTerms && (settings?.termsUrl && isValidExternalUrl(settings.termsUrl) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("a", { href: settings.termsUrl, target: "_blank", rel: "noopener noreferrer", children: "Terms & Conditions" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_link2.default, { href: "/terms", children: "Terms & Conditions" }))
506
425
  ] })
507
426
  ] })
508
427
  ] }) });
509
428
  }
510
429
 
511
430
  // src/components/ClientLayout.tsx
512
- var import_jsx_runtime9 = require("react/jsx-runtime");
431
+ var import_jsx_runtime4 = require("react/jsx-runtime");
513
432
  function ThemeBodySync() {
514
433
  const { resolvedTheme } = (0, import_next_themes2.useTheme)();
515
- (0, import_react6.useEffect)(() => {
434
+ (0, import_react3.useEffect)(() => {
516
435
  if (resolvedTheme === "dark") {
517
436
  document.body.classList.add("dark-mode");
518
437
  document.body.classList.remove("light-mode");
@@ -524,33 +443,854 @@ function ThemeBodySync() {
524
443
  return null;
525
444
  }
526
445
  function ClientLayout({ children, settings }) {
527
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_next_themes2.ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, children: [
528
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ThemeBodySync, {}),
529
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "pageWrapper", children: [
530
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Header, { settings }),
531
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("main", { children }),
532
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Footer, { settings })
446
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_next_themes2.ThemeProvider, { attribute: "class", defaultTheme: "light", enableSystem: false, children: [
447
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ThemeBodySync, {}),
448
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "pageWrapper", children: [
449
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Header, { settings }),
450
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("main", { children }),
451
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Footer, { settings })
533
452
  ] })
534
453
  ] });
535
454
  }
536
455
 
537
456
  // src/components/ContactCTA.tsx
538
- var import_link4 = __toESM(require("next/link"));
457
+ var import_link3 = __toESM(require("next/link"));
539
458
  var import_ContactCTA = __toESM(require("./ContactCTA.module.css"));
540
- var import_jsx_runtime10 = require("react/jsx-runtime");
459
+ var import_jsx_runtime5 = require("react/jsx-runtime");
541
460
  function ContactCTA() {
542
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("section", { className: import_ContactCTA.default.ctaContainer, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: import_ContactCTA.default.ctaContent, children: [
543
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: import_ContactCTA.default.ctaHeading, children: "Interested in Our Research?" }),
544
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: import_ContactCTA.default.ctaText, children: "Follow our work, explore our publications, or get in touch to discuss potential collaborations." }),
545
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_link4.default, { href: "/contact", className: import_ContactCTA.default.ctaButton, children: "Contact Us" })
461
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("section", { className: import_ContactCTA.default.ctaContainer, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: import_ContactCTA.default.ctaContent, children: [
462
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: import_ContactCTA.default.ctaHeading, children: "Interested in Our Research?" }),
463
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: import_ContactCTA.default.ctaText, children: "Follow our work, explore our publications, or get in touch to discuss potential collaborations." }),
464
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_link3.default, { href: "/contact", className: import_ContactCTA.default.ctaButton, children: "Contact Us" })
546
465
  ] }) });
547
466
  }
467
+
468
+ // src/components/AnimatedHero.tsx
469
+ var import_framer_motion2 = require("framer-motion");
470
+ var import_react4 = require("react");
471
+ var import_image = __toESM(require("next/image"));
472
+ var import_link4 = __toESM(require("next/link"));
473
+ var import_HomePage = __toESM(require("./HomePage.module.css"));
474
+
475
+ // src/lib/animations.ts
476
+ var fadeIn = {
477
+ hidden: { opacity: 0 },
478
+ visible: {
479
+ opacity: 1,
480
+ transition: {
481
+ duration: 0.6,
482
+ ease: [0.65, 0, 0.35, 1]
483
+ }
484
+ }
485
+ };
486
+ var fadeInUp = {
487
+ hidden: { opacity: 0, y: 30 },
488
+ visible: {
489
+ opacity: 1,
490
+ y: 0,
491
+ transition: {
492
+ duration: 0.8,
493
+ ease: [0.65, 0, 0.35, 1]
494
+ }
495
+ }
496
+ };
497
+ var fadeInUpShort = {
498
+ hidden: { opacity: 0, y: 20 },
499
+ visible: {
500
+ opacity: 1,
501
+ y: 0,
502
+ transition: {
503
+ duration: 0.6,
504
+ ease: [0.4, 0, 0.2, 1]
505
+ }
506
+ }
507
+ };
508
+ var scaleIn = {
509
+ hidden: { opacity: 0, scale: 0.9 },
510
+ visible: {
511
+ opacity: 1,
512
+ scale: 1,
513
+ transition: {
514
+ duration: 0.8,
515
+ ease: [0.65, 0, 0.35, 1]
516
+ }
517
+ }
518
+ };
519
+ var slideInRight = {
520
+ hidden: { opacity: 0, x: 20 },
521
+ visible: {
522
+ opacity: 1,
523
+ x: 0,
524
+ transition: {
525
+ duration: 0.6,
526
+ ease: [0.4, 0, 0.2, 1]
527
+ }
528
+ }
529
+ };
530
+ var slideInLeft = {
531
+ hidden: { opacity: 0, x: -20 },
532
+ visible: {
533
+ opacity: 1,
534
+ x: 0,
535
+ transition: {
536
+ duration: 0.6,
537
+ ease: [0.4, 0, 0.2, 1]
538
+ }
539
+ }
540
+ };
541
+ var staggerContainer = {
542
+ hidden: { opacity: 0 },
543
+ visible: {
544
+ opacity: 1,
545
+ transition: {
546
+ staggerChildren: 0.1,
547
+ delayChildren: 0.2
548
+ }
549
+ }
550
+ };
551
+ var staggerItem = {
552
+ hidden: { opacity: 0, y: 20 },
553
+ visible: {
554
+ opacity: 1,
555
+ y: 0,
556
+ transition: {
557
+ duration: 0.5,
558
+ ease: [0.4, 0, 0.2, 1]
559
+ }
560
+ }
561
+ };
562
+ var cardHover = {
563
+ hover: {
564
+ y: -8,
565
+ transition: {
566
+ duration: 0.3,
567
+ ease: [0.4, 0, 0.2, 1]
568
+ }
569
+ }
570
+ };
571
+ var imageZoom = {
572
+ hover: {
573
+ scale: 1.08,
574
+ transition: {
575
+ duration: 0.5,
576
+ ease: [0.65, 0, 0.35, 1]
577
+ }
578
+ }
579
+ };
580
+ var pageTransition = {
581
+ hidden: { opacity: 0, y: 20 },
582
+ visible: {
583
+ opacity: 1,
584
+ y: 0,
585
+ transition: {
586
+ duration: 0.6,
587
+ ease: [0.4, 0, 0.2, 1]
588
+ }
589
+ },
590
+ exit: {
591
+ opacity: 0,
592
+ y: -20,
593
+ transition: {
594
+ duration: 0.4,
595
+ ease: [0.4, 0, 0.2, 1]
596
+ }
597
+ }
598
+ };
599
+ var viewportSettings = {
600
+ once: true,
601
+ amount: 0.3,
602
+ margin: "0px 0px -100px 0px"
603
+ };
604
+ var scrollReveal = {
605
+ hidden: { opacity: 0, y: 50 },
606
+ visible: {
607
+ opacity: 1,
608
+ y: 0,
609
+ transition: {
610
+ duration: 0.8,
611
+ ease: [0.65, 0, 0.35, 1]
612
+ }
613
+ }
614
+ };
615
+ var reducedMotion = {
616
+ hidden: { opacity: 0 },
617
+ visible: {
618
+ opacity: 1,
619
+ transition: {
620
+ duration: 0.01
621
+ }
622
+ }
623
+ };
624
+
625
+ // src/components/AnimatedHero.tsx
626
+ var import_jsx_runtime6 = require("react/jsx-runtime");
627
+ function AnimatedHero({ heroData, ArrowRightIcon }) {
628
+ const ref = (0, import_react4.useRef)(null);
629
+ const { scrollY } = (0, import_framer_motion2.useScroll)();
630
+ const y = (0, import_framer_motion2.useTransform)(scrollY, [0, 500], [0, 150]);
631
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("section", { className: import_HomePage.default.heroSection, ref, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: import_HomePage.default.heroContainer, children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
633
+ import_framer_motion2.motion.div,
634
+ {
635
+ className: import_HomePage.default.heroContent,
636
+ initial: "hidden",
637
+ animate: "visible",
638
+ variants: fadeInUp,
639
+ children: [
640
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
641
+ import_framer_motion2.motion.span,
642
+ {
643
+ className: import_HomePage.default.heroTagline,
644
+ initial: { opacity: 0 },
645
+ animate: { opacity: 1 },
646
+ transition: { duration: 0.6, delay: 0.2 },
647
+ children: heroData.tagline
648
+ }
649
+ ),
650
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
651
+ import_framer_motion2.motion.h1,
652
+ {
653
+ className: import_HomePage.default.heroHeading,
654
+ initial: { opacity: 0, y: 20 },
655
+ animate: { opacity: 1, y: 0 },
656
+ transition: { duration: 0.8, delay: 0.3 },
657
+ children: [
658
+ heroData.heading,
659
+ " ",
660
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: import_HomePage.default.heroHeadingAccent, children: heroData.headingAccent })
661
+ ]
662
+ }
663
+ ),
664
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
665
+ import_framer_motion2.motion.p,
666
+ {
667
+ className: import_HomePage.default.heroDescription,
668
+ initial: { opacity: 0, y: 20 },
669
+ animate: { opacity: 1, y: 0 },
670
+ transition: { duration: 0.8, delay: 0.4 },
671
+ children: heroData.description
672
+ }
673
+ ),
674
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
675
+ import_framer_motion2.motion.div,
676
+ {
677
+ className: import_HomePage.default.heroCtas,
678
+ initial: { opacity: 0, y: 20 },
679
+ animate: { opacity: 1, y: 0 },
680
+ transition: { duration: 0.8, delay: 0.5 },
681
+ children: [
682
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_link4.default, { href: heroData.ctaLink, className: import_HomePage.default.heroPrimaryCta, children: [
683
+ heroData.ctaText,
684
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArrowRightIcon, {})
685
+ ] }),
686
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_link4.default, { href: "/publications", className: import_HomePage.default.heroSecondaryCta, children: "View Publications" })
687
+ ]
688
+ }
689
+ )
690
+ ]
691
+ }
692
+ ),
693
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
694
+ import_framer_motion2.motion.div,
695
+ {
696
+ className: import_HomePage.default.heroImageWrapper,
697
+ style: { y },
698
+ initial: "hidden",
699
+ animate: "visible",
700
+ variants: scaleIn,
701
+ transition: { duration: 0.8, delay: 0.6 },
702
+ children: heroData.image ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
703
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
704
+ import_image.default,
705
+ {
706
+ src: heroData.image,
707
+ alt: "Research lab",
708
+ width: 800,
709
+ height: 600,
710
+ className: import_HomePage.default.heroImage,
711
+ priority: true
712
+ }
713
+ ),
714
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: import_HomePage.default.heroImageOverlay })
715
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: import_HomePage.default.heroImagePlaceholder, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
716
+ "svg",
717
+ {
718
+ width: "120",
719
+ height: "120",
720
+ viewBox: "0 0 24 24",
721
+ fill: "none",
722
+ stroke: "currentColor",
723
+ strokeWidth: "1",
724
+ children: [
725
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
726
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
727
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M21 15l-5-5L5 21" })
728
+ ]
729
+ }
730
+ ) })
731
+ }
732
+ )
733
+ ] }) });
734
+ }
735
+
736
+ // src/components/HomePage.tsx
737
+ var import_jsx_runtime7 = require("react/jsx-runtime");
738
+ function HomePage({
739
+ children,
740
+ settings = null,
741
+ header,
742
+ footer
743
+ }) {
744
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
745
+ header ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Header, { settings: settings || {} }),
746
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("main", { children }),
747
+ footer ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Footer, { settings: settings || {} })
748
+ ] });
749
+ }
750
+
751
+ // src/components/AnimatedCard.tsx
752
+ var import_framer_motion3 = require("framer-motion");
753
+ var import_jsx_runtime8 = require("react/jsx-runtime");
754
+ function AnimatedCard({ children, className, delay = 0 }) {
755
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
756
+ import_framer_motion3.motion.div,
757
+ {
758
+ className,
759
+ initial: "hidden",
760
+ whileInView: "visible",
761
+ viewport: viewportSettings,
762
+ variants: {
763
+ hidden: { opacity: 0, y: 30 },
764
+ visible: {
765
+ opacity: 1,
766
+ y: 0,
767
+ transition: {
768
+ duration: 0.6,
769
+ delay,
770
+ ease: [0.4, 0, 0.2, 1]
771
+ }
772
+ }
773
+ },
774
+ whileHover: "hover",
775
+ children
776
+ }
777
+ );
778
+ }
779
+ function AnimatedImage({ children, className }) {
780
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_framer_motion3.motion.div, { className, variants: imageZoom, children });
781
+ }
782
+ function AnimatedSection({ children, className }) {
783
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
784
+ import_framer_motion3.motion.section,
785
+ {
786
+ className,
787
+ initial: "hidden",
788
+ whileInView: "visible",
789
+ viewport: viewportSettings,
790
+ variants: fadeInUpShort,
791
+ children
792
+ }
793
+ );
794
+ }
795
+
796
+ // src/components/AnimatedGallery.tsx
797
+ var import_framer_motion4 = require("framer-motion");
798
+ var import_image2 = __toESM(require("next/image"));
799
+ var import_react5 = require("react");
800
+ var import_PicturesPage = __toESM(require("./PicturesPage.module.css"));
801
+ var import_jsx_runtime9 = require("react/jsx-runtime");
802
+ function useMounted() {
803
+ const [mounted, setMounted] = (0, import_react5.useState)(false);
804
+ (0, import_react5.useEffect)(() => {
805
+ setMounted(true);
806
+ }, []);
807
+ return mounted;
808
+ }
809
+ function AnimatedGalleryHeader({ children, className }) {
810
+ const mounted = useMounted();
811
+ if (!mounted) {
812
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("header", { className, children });
813
+ }
814
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
815
+ import_framer_motion4.motion.header,
816
+ {
817
+ className,
818
+ initial: { opacity: 0, y: 30 },
819
+ animate: { opacity: 1, y: 0 },
820
+ transition: { duration: 0.8, ease: [0.4, 0, 0.2, 1] },
821
+ children
822
+ }
823
+ );
824
+ }
825
+ function AnimatedGalleryGrid({ images }) {
826
+ const mounted = useMounted();
827
+ if (!mounted) {
828
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: import_PicturesPage.default.photosGrid, children: images.map((pic) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: import_PicturesPage.default.photoCard, children: [
829
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: import_PicturesPage.default.photoImageWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
830
+ import_image2.default,
831
+ {
832
+ src: pic.imageUrl,
833
+ alt: pic.altText,
834
+ width: pic.width,
835
+ height: pic.height,
836
+ sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
837
+ className: import_PicturesPage.default.photoImage
838
+ }
839
+ ) }),
840
+ pic.caption && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: import_PicturesPage.default.photoCaption, children: pic.caption })
841
+ ] }, pic._id)) });
842
+ }
843
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
844
+ import_framer_motion4.motion.div,
845
+ {
846
+ className: import_PicturesPage.default.photosGrid,
847
+ initial: "hidden",
848
+ animate: "visible",
849
+ variants: {
850
+ hidden: { opacity: 0 },
851
+ visible: {
852
+ opacity: 1,
853
+ transition: {
854
+ staggerChildren: 0.08,
855
+ delayChildren: 0.2
856
+ }
857
+ }
858
+ },
859
+ children: images.map((pic) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
860
+ import_framer_motion4.motion.div,
861
+ {
862
+ className: import_PicturesPage.default.photoCard,
863
+ variants: {
864
+ hidden: { opacity: 0, y: 40, scale: 0.95 },
865
+ visible: {
866
+ opacity: 1,
867
+ y: 0,
868
+ scale: 1,
869
+ transition: {
870
+ duration: 0.6,
871
+ ease: [0.4, 0, 0.2, 1]
872
+ }
873
+ }
874
+ },
875
+ whileHover: {
876
+ scale: 1.05,
877
+ transition: { duration: 0.3 }
878
+ },
879
+ children: [
880
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: import_PicturesPage.default.photoImageWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
881
+ import_image2.default,
882
+ {
883
+ src: pic.imageUrl,
884
+ alt: pic.altText,
885
+ width: pic.width,
886
+ height: pic.height,
887
+ sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
888
+ className: import_PicturesPage.default.photoImage
889
+ }
890
+ ) }),
891
+ pic.caption && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: import_PicturesPage.default.photoCaption, children: pic.caption })
892
+ ]
893
+ },
894
+ pic._id
895
+ ))
896
+ }
897
+ );
898
+ }
899
+
900
+ // src/components/AnimatedPage.tsx
901
+ var import_framer_motion5 = require("framer-motion");
902
+ var import_react6 = require("react");
903
+ var import_jsx_runtime10 = require("react/jsx-runtime");
904
+ function useMounted2() {
905
+ const [mounted, setMounted] = (0, import_react6.useState)(false);
906
+ (0, import_react6.useEffect)(() => {
907
+ setMounted(true);
908
+ }, []);
909
+ return mounted;
910
+ }
911
+ function AnimatedPage({ children, className }) {
912
+ const mounted = useMounted2();
913
+ if (!mounted) {
914
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className, children });
915
+ }
916
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
917
+ import_framer_motion5.motion.div,
918
+ {
919
+ className,
920
+ initial: { opacity: 0 },
921
+ animate: { opacity: 1 },
922
+ transition: { duration: 0.6, ease: [0.4, 0, 0.2, 1] },
923
+ children
924
+ }
925
+ );
926
+ }
927
+ function AnimatedHeader({ children, className }) {
928
+ const mounted = useMounted2();
929
+ if (!mounted) {
930
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("header", { className, children });
931
+ }
932
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
933
+ import_framer_motion5.motion.header,
934
+ {
935
+ className,
936
+ initial: { opacity: 0, y: 15 },
937
+ animate: { opacity: 1, y: 0 },
938
+ transition: { duration: 0.5, ease: [0.4, 0, 0.2, 1] },
939
+ children
940
+ }
941
+ );
942
+ }
943
+ function AnimatedMain({ children, className }) {
944
+ const mounted = useMounted2();
945
+ if (!mounted) {
946
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("main", { className, children });
947
+ }
948
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
949
+ import_framer_motion5.motion.main,
950
+ {
951
+ className,
952
+ initial: { opacity: 0, y: 10 },
953
+ animate: { opacity: 1, y: 0 },
954
+ transition: { duration: 0.5, delay: 0.1, ease: [0.4, 0, 0.2, 1] },
955
+ children
956
+ }
957
+ );
958
+ }
959
+ function StaggeredGrid({ children, className }) {
960
+ const mounted = useMounted2();
961
+ const childArray = Array.isArray(children) ? children : [children];
962
+ if (!mounted) {
963
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className, children });
964
+ }
965
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
966
+ import_framer_motion5.motion.div,
967
+ {
968
+ className,
969
+ initial: "hidden",
970
+ whileInView: "visible",
971
+ viewport: { once: true, amount: 0.1 },
972
+ variants: {
973
+ hidden: { opacity: 0 },
974
+ visible: {
975
+ opacity: 1,
976
+ transition: {
977
+ staggerChildren: 0.05,
978
+ delayChildren: 0.05
979
+ }
980
+ }
981
+ },
982
+ children: childArray.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
983
+ import_framer_motion5.motion.div,
984
+ {
985
+ variants: {
986
+ hidden: { opacity: 0, y: 15 },
987
+ visible: {
988
+ opacity: 1,
989
+ y: 0,
990
+ transition: {
991
+ duration: 0.5,
992
+ ease: [0.4, 0, 0.2, 1]
993
+ }
994
+ }
995
+ },
996
+ children: child
997
+ },
998
+ index
999
+ ))
1000
+ }
1001
+ );
1002
+ }
1003
+ function AnimatedItem({ children, className, delay = 0, index = 0 }) {
1004
+ const mounted = useMounted2();
1005
+ if (!mounted) {
1006
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className, children });
1007
+ }
1008
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1009
+ import_framer_motion5.motion.div,
1010
+ {
1011
+ className,
1012
+ initial: { opacity: 0, y: 15 },
1013
+ whileInView: { opacity: 1, y: 0 },
1014
+ viewport: { once: true, amount: 0.2 },
1015
+ transition: {
1016
+ duration: 0.5,
1017
+ delay: delay || index * 0.05,
1018
+ ease: [0.4, 0, 0.2, 1]
1019
+ },
1020
+ children
1021
+ }
1022
+ );
1023
+ }
1024
+ function ScrollRevealSection({ children, className }) {
1025
+ const mounted = useMounted2();
1026
+ if (!mounted) {
1027
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("section", { className, children });
1028
+ }
1029
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1030
+ import_framer_motion5.motion.section,
1031
+ {
1032
+ className,
1033
+ initial: { opacity: 0, y: 20 },
1034
+ whileInView: { opacity: 1, y: 0 },
1035
+ viewport: { once: true, amount: 0.15 },
1036
+ transition: { duration: 0.5, ease: [0.4, 0, 0.2, 1] },
1037
+ children
1038
+ }
1039
+ );
1040
+ }
1041
+ function AnimatedHeroContent({ children, className }) {
1042
+ const mounted = useMounted2();
1043
+ const childArray = Array.isArray(children) ? children : [children];
1044
+ if (!mounted) {
1045
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className, children });
1046
+ }
1047
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1048
+ import_framer_motion5.motion.div,
1049
+ {
1050
+ className,
1051
+ initial: "hidden",
1052
+ animate: "visible",
1053
+ variants: {
1054
+ hidden: { opacity: 0 },
1055
+ visible: {
1056
+ opacity: 1,
1057
+ transition: {
1058
+ staggerChildren: 0.08,
1059
+ delayChildren: 0.05
1060
+ }
1061
+ }
1062
+ },
1063
+ children: childArray.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1064
+ import_framer_motion5.motion.div,
1065
+ {
1066
+ variants: {
1067
+ hidden: { opacity: 0, y: 10 },
1068
+ visible: {
1069
+ opacity: 1,
1070
+ y: 0,
1071
+ transition: {
1072
+ duration: 0.5,
1073
+ ease: [0.4, 0, 0.2, 1]
1074
+ }
1075
+ }
1076
+ },
1077
+ children: child
1078
+ },
1079
+ index
1080
+ ))
1081
+ }
1082
+ );
1083
+ }
1084
+
1085
+ // src/components/AnimatedSections.tsx
1086
+ var import_framer_motion6 = require("framer-motion");
1087
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1088
+ function AnimatedGrid({ children, className }) {
1089
+ const childArray = Array.isArray(children) ? children : [children];
1090
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1091
+ import_framer_motion6.motion.div,
1092
+ {
1093
+ className,
1094
+ initial: "hidden",
1095
+ whileInView: "visible",
1096
+ viewport: viewportSettings,
1097
+ variants: staggerContainer,
1098
+ children: childArray.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_framer_motion6.motion.div, { variants: staggerItem, children: child }, index))
1099
+ }
1100
+ );
1101
+ }
1102
+ function AnimatedStats({ children, className }) {
1103
+ const childArray = Array.isArray(children) ? children : [children];
1104
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1105
+ import_framer_motion6.motion.div,
1106
+ {
1107
+ className,
1108
+ initial: "hidden",
1109
+ whileInView: "visible",
1110
+ viewport: { once: true, amount: 0.3 },
1111
+ variants: {
1112
+ hidden: { opacity: 0 },
1113
+ visible: {
1114
+ opacity: 1,
1115
+ transition: {
1116
+ staggerChildren: 0.15,
1117
+ delayChildren: 0.1
1118
+ }
1119
+ }
1120
+ },
1121
+ children: childArray.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1122
+ import_framer_motion6.motion.div,
1123
+ {
1124
+ variants: {
1125
+ hidden: { opacity: 0, scale: 0.8 },
1126
+ visible: {
1127
+ opacity: 1,
1128
+ scale: 1,
1129
+ transition: {
1130
+ duration: 0.5,
1131
+ ease: [0.4, 0, 0.2, 1]
1132
+ }
1133
+ }
1134
+ },
1135
+ children: child
1136
+ },
1137
+ index
1138
+ ))
1139
+ }
1140
+ );
1141
+ }
1142
+ function AnimatedSectionHeader({ children, className }) {
1143
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1144
+ import_framer_motion6.motion.header,
1145
+ {
1146
+ className,
1147
+ initial: "hidden",
1148
+ whileInView: "visible",
1149
+ viewport: viewportSettings,
1150
+ variants: fadeInUpShort,
1151
+ children
1152
+ }
1153
+ );
1154
+ }
1155
+ function AnimatedList({ children, className }) {
1156
+ const childArray = Array.isArray(children) ? children : [children];
1157
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1158
+ import_framer_motion6.motion.div,
1159
+ {
1160
+ className,
1161
+ initial: "hidden",
1162
+ whileInView: "visible",
1163
+ viewport: viewportSettings,
1164
+ variants: {
1165
+ hidden: { opacity: 0 },
1166
+ visible: {
1167
+ opacity: 1,
1168
+ transition: {
1169
+ staggerChildren: 0.08,
1170
+ delayChildren: 0.1
1171
+ }
1172
+ }
1173
+ },
1174
+ children: childArray.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1175
+ import_framer_motion6.motion.div,
1176
+ {
1177
+ variants: {
1178
+ hidden: { opacity: 0, x: -20 },
1179
+ visible: {
1180
+ opacity: 1,
1181
+ x: 0,
1182
+ transition: {
1183
+ duration: 0.5,
1184
+ ease: [0.4, 0, 0.2, 1]
1185
+ }
1186
+ }
1187
+ },
1188
+ children: child
1189
+ },
1190
+ index
1191
+ ))
1192
+ }
1193
+ );
1194
+ }
1195
+
1196
+ // src/config.ts
1197
+ function defineConfig(config) {
1198
+ return config;
1199
+ }
1200
+
1201
+ // src/lib/sanity.ts
1202
+ var import_next_sanity = require("next-sanity");
1203
+ var import_image_url = __toESM(require("@sanity/image-url"));
1204
+ var projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID;
1205
+ var dataset = process.env.NEXT_PUBLIC_SANITY_DATASET || "production";
1206
+ var apiVersion = "2023-05-03";
1207
+ var _client = null;
1208
+ function getClient() {
1209
+ if (!_client) {
1210
+ if (!projectId) {
1211
+ throw new Error(
1212
+ "Sanity Project ID is not defined. Please set NEXT_PUBLIC_SANITY_PROJECT_ID in your environment."
1213
+ );
1214
+ }
1215
+ _client = (0, import_next_sanity.createClient)({
1216
+ projectId,
1217
+ dataset,
1218
+ apiVersion,
1219
+ useCdn: process.env.NODE_ENV === "production"
1220
+ });
1221
+ }
1222
+ return _client;
1223
+ }
1224
+ var client = {
1225
+ get projectId() {
1226
+ return projectId;
1227
+ },
1228
+ get dataset() {
1229
+ return dataset;
1230
+ },
1231
+ fetch: (...args) => getClient().fetch(...args)
1232
+ };
1233
+ var _builder = null;
1234
+ function urlFor(source) {
1235
+ if (!_builder) {
1236
+ if (!projectId) {
1237
+ return {
1238
+ width: () => ({ height: () => ({ url: () => "" }), url: () => "" }),
1239
+ height: () => ({ width: () => ({ url: () => "" }), url: () => "" }),
1240
+ url: () => ""
1241
+ };
1242
+ }
1243
+ _builder = (0, import_image_url.default)({ projectId, dataset });
1244
+ }
1245
+ return _builder.image(source);
1246
+ }
548
1247
  // Annotate the CommonJS export names for ESM import in node:
549
1248
  0 && (module.exports = {
1249
+ AnimatedCard,
1250
+ AnimatedGalleryGrid,
1251
+ AnimatedGalleryHeader,
1252
+ AnimatedGrid,
1253
+ AnimatedHeader,
550
1254
  AnimatedHero,
1255
+ AnimatedHeroContent,
1256
+ AnimatedImage,
1257
+ AnimatedItem,
1258
+ AnimatedList,
1259
+ AnimatedMain,
1260
+ AnimatedPage,
1261
+ AnimatedSection,
1262
+ AnimatedSectionHeader,
1263
+ AnimatedStats,
551
1264
  ClientLayout,
552
1265
  ContactCTA,
553
1266
  Footer,
554
1267
  Header,
555
- ThemeToggle
1268
+ HomePage,
1269
+ ScrollRevealSection,
1270
+ StaggeredGrid,
1271
+ ThemeToggle,
1272
+ cardHover,
1273
+ client,
1274
+ defineConfig,
1275
+ escapeHtml,
1276
+ fadeIn,
1277
+ fadeInUp,
1278
+ fadeInUpShort,
1279
+ getClient,
1280
+ imageZoom,
1281
+ isValidEmail,
1282
+ isValidExternalUrl,
1283
+ isValidGoogleMapsEmbedUrl,
1284
+ isValidSlug,
1285
+ pageTransition,
1286
+ reducedMotion,
1287
+ sanitizeUrl,
1288
+ scaleIn,
1289
+ scrollReveal,
1290
+ slideInLeft,
1291
+ slideInRight,
1292
+ staggerContainer,
1293
+ staggerItem,
1294
+ urlFor,
1295
+ viewportSettings
556
1296
  });