@prosophia/lab-minimal 0.0.2 → 0.0.4

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