@geomak/ui 6.31.0 → 6.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -9474,6 +9474,397 @@ function Testimonials({ testimonials, eyebrow, title, description, columns = 3,
9474
9474
  ] }, tm.key ?? i)) })
9475
9475
  ] });
9476
9476
  }
9477
+ var Arrow4 = ({ dir }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: dir === "left" ? "M15 18l-6-6 6-6" : "M9 18l6-6-6-6" }) });
9478
+ var SCRIM = "linear-gradient(to top, color-mix(in oklab, var(--color-foreground) 70%, transparent), color-mix(in oklab, var(--color-foreground) 25%, transparent))";
9479
+ function SlideShow({
9480
+ slides,
9481
+ autoPlay = true,
9482
+ interval = 6e3,
9483
+ showArrows = true,
9484
+ showDots = true,
9485
+ height = 460,
9486
+ "aria-label": ariaLabel = "Slideshow",
9487
+ className = "",
9488
+ style
9489
+ }) {
9490
+ const reduced = framerMotion.useReducedMotion();
9491
+ const [index, setIndex] = React28.useState(0);
9492
+ const [paused, setPaused] = React28.useState(false);
9493
+ const count = slides.length;
9494
+ const idx = count ? (index % count + count) % count : 0;
9495
+ const go = React28.useCallback((d) => setIndex((i) => i + d), []);
9496
+ const timer = React28.useRef(null);
9497
+ React28.useEffect(() => {
9498
+ if (!autoPlay || paused || count <= 1) return;
9499
+ timer.current = setInterval(() => setIndex((i) => i + 1), interval);
9500
+ return () => {
9501
+ if (timer.current) clearInterval(timer.current);
9502
+ };
9503
+ }, [autoPlay, paused, interval, count]);
9504
+ if (count === 0) return null;
9505
+ const slide = slides[idx];
9506
+ const onImage = Boolean(slide.image);
9507
+ const align = slide.align ?? "center";
9508
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9509
+ "section",
9510
+ {
9511
+ "aria-label": ariaLabel,
9512
+ "aria-roledescription": "carousel",
9513
+ className: ["relative overflow-hidden rounded-2xl", className].filter(Boolean).join(" "),
9514
+ style: { height, ...style },
9515
+ onMouseEnter: () => setPaused(true),
9516
+ onMouseLeave: () => setPaused(false),
9517
+ children: [
9518
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: /* @__PURE__ */ jsxRuntime.jsxs(
9519
+ framerMotion.motion.div,
9520
+ {
9521
+ className: "absolute inset-0",
9522
+ initial: { opacity: 0 },
9523
+ animate: { opacity: 1 },
9524
+ exit: { opacity: 0 },
9525
+ transition: { duration: reduced ? 0 : 0.6, ease: "easeInOut" },
9526
+ style: onImage ? { backgroundImage: `url(${slide.image})`, backgroundSize: "cover", backgroundPosition: "center" } : void 0,
9527
+ children: [
9528
+ onImage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0", style: { backgroundImage: SCRIM }, "aria-hidden": "true" }),
9529
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["relative flex h-full flex-col justify-center gap-5 px-8 sm:px-14", align === "center" ? "items-center text-center" : "items-start text-left", onImage ? "text-white" : "bg-surface text-foreground"].join(" "), children: [
9530
+ slide.eyebrow != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["text-xs font-semibold uppercase tracking-wide", onImage ? "text-white/80" : "text-accent"].join(" "), children: slide.eyebrow }),
9531
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "max-w-3xl text-3xl font-bold leading-tight tracking-tight sm:text-5xl", children: slide.title }),
9532
+ slide.description != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: ["max-w-xl text-base leading-relaxed sm:text-lg", onImage ? "text-white/85" : "text-foreground-secondary"].join(" "), children: slide.description }),
9533
+ slide.actions != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["mt-2 flex flex-wrap gap-3", align === "center" ? "justify-center" : ""].join(" "), children: slide.actions })
9534
+ ] })
9535
+ ]
9536
+ },
9537
+ slide.key ?? idx
9538
+ ) }),
9539
+ showArrows && count > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9540
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Previous slide", onClick: () => go(-1), className: "absolute left-3 top-1/2 z-10 flex h-9 w-9 -translate-y-1/2 items-center justify-center rounded-full border border-white/30 bg-white/15 text-white backdrop-blur transition-colors hover:bg-white/25 focus:outline-none focus-visible:ring-2 focus-visible:ring-white", children: /* @__PURE__ */ jsxRuntime.jsx(Arrow4, { dir: "left" }) }),
9541
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Next slide", onClick: () => go(1), className: "absolute right-3 top-1/2 z-10 flex h-9 w-9 -translate-y-1/2 items-center justify-center rounded-full border border-white/30 bg-white/15 text-white backdrop-blur transition-colors hover:bg-white/25 focus:outline-none focus-visible:ring-2 focus-visible:ring-white", children: /* @__PURE__ */ jsxRuntime.jsx(Arrow4, { dir: "right" }) })
9542
+ ] }),
9543
+ showDots && count > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-4 left-1/2 z-10 flex -translate-x-1/2 items-center gap-1.5", children: slides.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9544
+ "button",
9545
+ {
9546
+ type: "button",
9547
+ "aria-label": `Go to slide ${i + 1}`,
9548
+ "aria-current": i === idx,
9549
+ onClick: () => setIndex(i),
9550
+ className: ["h-1.5 rounded-full transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-white", i === idx ? "w-6 bg-white" : "w-1.5 bg-white/50 hover:bg-white/80"].join(" ")
9551
+ },
9552
+ i
9553
+ )) })
9554
+ ]
9555
+ }
9556
+ );
9557
+ }
9558
+ var PlayGlyph = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", className: "h-7 w-7 translate-x-0.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 5v14l11-7z" }) });
9559
+ function Video({
9560
+ src,
9561
+ embedUrl,
9562
+ poster,
9563
+ aspect = "16/9",
9564
+ title,
9565
+ controls = true,
9566
+ autoPlay = false,
9567
+ loop = false,
9568
+ muted = false,
9569
+ framed = true,
9570
+ className = "",
9571
+ style
9572
+ }) {
9573
+ const [playing, setPlaying] = React28.useState(autoPlay);
9574
+ const frame = ["relative w-full overflow-hidden bg-backdrop", framed ? "rounded-2xl border border-border shadow-sm" : "", className].filter(Boolean).join(" ");
9575
+ const ratio = aspect.replace("/", " / ");
9576
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: frame, style: { aspectRatio: ratio, ...style }, children: embedUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9577
+ "iframe",
9578
+ {
9579
+ src: embedUrl,
9580
+ title: title ?? "Embedded video",
9581
+ className: "absolute inset-0 h-full w-full",
9582
+ frameBorder: 0,
9583
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
9584
+ allowFullScreen: true
9585
+ }
9586
+ ) : src ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9587
+ /* @__PURE__ */ jsxRuntime.jsx(
9588
+ "video",
9589
+ {
9590
+ src,
9591
+ poster,
9592
+ title,
9593
+ controls: controls && playing,
9594
+ autoPlay: playing,
9595
+ loop,
9596
+ muted: muted || autoPlay,
9597
+ playsInline: true,
9598
+ className: "absolute inset-0 h-full w-full object-cover"
9599
+ }
9600
+ ),
9601
+ !playing && /* @__PURE__ */ jsxRuntime.jsxs(
9602
+ "button",
9603
+ {
9604
+ type: "button",
9605
+ "aria-label": title ? `Play ${title}` : "Play video",
9606
+ onClick: () => setPlaying(true),
9607
+ className: "group absolute inset-0 flex items-center justify-center focus:outline-none",
9608
+ style: poster ? { backgroundImage: `url(${poster})`, backgroundSize: "cover", backgroundPosition: "center" } : void 0,
9609
+ children: [
9610
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0", style: { backgroundColor: "color-mix(in oklab, var(--color-foreground) 30%, transparent)" }, "aria-hidden": "true" }),
9611
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative flex h-16 w-16 items-center justify-center rounded-full bg-white/90 text-accent shadow-lg transition-transform duration-200 ease-out group-hover:scale-105 group-focus-visible:ring-4 group-focus-visible:ring-white", children: /* @__PURE__ */ jsxRuntime.jsx(PlayGlyph, {}) })
9612
+ ]
9613
+ }
9614
+ )
9615
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-sm text-foreground-muted", children: "No video source" }) });
9616
+ }
9617
+ var isUrl = (v) => typeof v === "string";
9618
+ function Parallax({
9619
+ background,
9620
+ children,
9621
+ height = 440,
9622
+ speed = 0.3,
9623
+ overlay = true,
9624
+ className = "",
9625
+ style
9626
+ }) {
9627
+ const reduced = framerMotion.useReducedMotion();
9628
+ const ref = React28.useRef(null);
9629
+ const { scrollYProgress } = framerMotion.useScroll({ target: ref, offset: ["start end", "end start"] });
9630
+ const shift = Math.max(0, Math.min(1, speed)) * 100;
9631
+ const y = framerMotion.useTransform(scrollYProgress, [0, 1], reduced ? ["0%", "0%"] : [`-${shift / 2}%`, `${shift / 2}%`]);
9632
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9633
+ "div",
9634
+ {
9635
+ ref,
9636
+ className: ["relative overflow-hidden rounded-2xl", className].filter(Boolean).join(" "),
9637
+ style: { height, ...style },
9638
+ children: [
9639
+ /* @__PURE__ */ jsxRuntime.jsx(
9640
+ framerMotion.motion.div,
9641
+ {
9642
+ "aria-hidden": isUrl(background) ? true : void 0,
9643
+ className: "absolute inset-x-0 -top-[15%] -bottom-[15%] will-change-transform",
9644
+ style: {
9645
+ y,
9646
+ ...isUrl(background) ? { backgroundImage: `url(${background})`, backgroundSize: "cover", backgroundPosition: "center" } : {}
9647
+ },
9648
+ children: !isUrl(background) && background
9649
+ }
9650
+ ),
9651
+ overlay && /* @__PURE__ */ jsxRuntime.jsx(
9652
+ "div",
9653
+ {
9654
+ className: "absolute inset-0",
9655
+ style: { backgroundColor: "color-mix(in oklab, var(--color-foreground) 45%, transparent)" },
9656
+ "aria-hidden": "true"
9657
+ }
9658
+ ),
9659
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex h-full flex-col items-center justify-center gap-4 px-6 text-center", children })
9660
+ ]
9661
+ }
9662
+ );
9663
+ }
9664
+ var COLS3 = {
9665
+ 2: "sm:grid-cols-2",
9666
+ 3: "sm:grid-cols-2 lg:grid-cols-3"
9667
+ };
9668
+ function Blog({
9669
+ posts,
9670
+ eyebrow,
9671
+ title,
9672
+ description,
9673
+ columns = 3,
9674
+ centeredHeader = true,
9675
+ className = "",
9676
+ style
9677
+ }) {
9678
+ const hasHeader = eyebrow != null || title != null || description != null;
9679
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: ["w-full", className].filter(Boolean).join(" "), style, children: [
9680
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("header", { className: ["mb-10 flex flex-col gap-3", centeredHeader ? "items-center text-center" : "items-start text-left"].join(" "), children: [
9681
+ eyebrow != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-semibold uppercase tracking-wide text-accent", children: eyebrow }),
9682
+ title != null && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold tracking-tight text-foreground sm:text-3xl", children: title }),
9683
+ description != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-2xl text-base leading-relaxed text-foreground-secondary", children: description })
9684
+ ] }),
9685
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["grid grid-cols-1 gap-6", COLS3[columns]].join(" "), children: posts.map((post, i) => {
9686
+ const meta = [post.author, post.date, post.readTime].filter((m) => m != null);
9687
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9688
+ post.image && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative aspect-video overflow-hidden bg-backdrop", children: [
9689
+ /* @__PURE__ */ jsxRuntime.jsx("img", { src: post.image, alt: "", className: "h-full w-full object-cover transition-transform duration-300 ease-out group-hover:scale-105", loading: "lazy" }),
9690
+ post.tag != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-3 top-3", children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "accent", variant: "solid", size: "sm", children: post.tag }) })
9691
+ ] }),
9692
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col gap-2 p-5", children: [
9693
+ post.tag != null && !post.image && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "accent", variant: "soft", size: "sm", children: post.tag }) }),
9694
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold leading-snug text-foreground transition-colors group-hover:text-accent", children: post.title }),
9695
+ post.excerpt != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-3 text-sm leading-relaxed text-foreground-secondary", children: post.excerpt }),
9696
+ meta.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-wrap items-center gap-x-2 gap-y-1 pt-3 text-xs text-foreground-muted", children: meta.map((m, j) => /* @__PURE__ */ jsxRuntime.jsxs(React28__default.default.Fragment, { children: [
9697
+ j > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xB7" }),
9698
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: m })
9699
+ ] }, j)) })
9700
+ ] })
9701
+ ] });
9702
+ const cardCx = "group flex flex-col overflow-hidden rounded-xl border border-border bg-surface text-left shadow-sm transition-all duration-200 ease-out hover:-translate-y-0.5 hover:border-border-strong hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent";
9703
+ if (post.href) {
9704
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: post.href, className: cardCx, children: inner }, post.key ?? i);
9705
+ }
9706
+ if (post.onClick) {
9707
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: post.onClick, className: cardCx, children: inner }, post.key ?? i);
9708
+ }
9709
+ return /* @__PURE__ */ jsxRuntime.jsx("article", { className: cardCx.replace("focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent", ""), children: inner }, post.key ?? i);
9710
+ }) })
9711
+ ] });
9712
+ }
9713
+ var P = ({ d }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", className: "h-[55%] w-[55%]", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d }) });
9714
+ var ICONS = {
9715
+ x: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" }),
9716
+ twitter: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482A13.978 13.978 0 011.64 3.162a4.822 4.822 0 001.523 6.574 4.9 4.9 0 01-2.229-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z" }),
9717
+ github: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23a11.5 11.5 0 013.003-.404c1.02.005 2.045.138 3.003.404 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" }),
9718
+ linkedin: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z" }),
9719
+ youtube: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M23.498 6.186a3.016 3.016 0 00-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 00.502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" }),
9720
+ instagram: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z" }),
9721
+ facebook: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" }),
9722
+ mastodon: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 00.023-.043v-1.809a.052.052 0 00-.02-.041.053.053 0 00-.046-.01 20.282 20.282 0 01-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 01-.319-1.433.053.053 0 01.066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.301-.547-1.963-1.66-1.963-1.226 0-1.84.79-1.84 2.352v3.408h-2.546V8.68c0-1.563-.615-2.353-1.84-2.353-1.107 0-1.66.662-1.66 1.963v6.218H4.844V8.105c0-1.3.332-2.333.996-3.097.685-.764 1.583-1.156 2.7-1.156 1.29 0 2.265.498 2.916 1.49l.638 1.071.638-1.071c.65-.992 1.626-1.49 2.916-1.49 1.116 0 2.014.392 2.7 1.156.663.764.995 1.797.995 3.097z" }),
9723
+ email: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M1.5 4.5h21A1.5 1.5 0 0124 6v12a1.5 1.5 0 01-1.5 1.5h-21A1.5 1.5 0 010 18V6a1.5 1.5 0 011.5-1.5zM12 13.06L2.41 6.5h19.18zm-3.43-1.36L1.5 16.94V7.06zM9.9 12.9l1.55 1.06a.99.99 0 001.1 0l1.55-1.06 6.74 4.6H3.16zm5.53-1.2l7.07-4.64v9.88z" }),
9724
+ website: /* @__PURE__ */ jsxRuntime.jsx(P, { d: "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm7.931 7h-3.07a15.4 15.4 0 00-1.32-3.853A8.03 8.03 0 0119.931 7zM12 2.042c.86 1.243 1.535 2.6 1.99 4.958h-3.98C10.465 4.642 11.14 3.285 12 2.042zM2.069 14A8.05 8.05 0 012 12c0-.69.07-1.36.069-2h3.518c-.05.66-.087 1.32-.087 2 0 .68.037 1.34.087 2zm.943 2h3.07a15.4 15.4 0 001.32 3.853A8.03 8.03 0 014.069 17zm3.07-9h-3.07a8.03 8.03 0 014.39-3.853A15.4 15.4 0 006.139 7zM12 21.958c-.86-1.243-1.535-2.6-1.99-4.958h3.98c-.455 2.358-1.13 3.715-1.99 4.958zM14.34 14H9.66c-.055-.66-.095-1.32-.095-2 0-.68.04-1.34.095-2h4.68c.055.66.095 1.32.095 2 0 .68-.04 1.34-.095 2zm.527 5.853A15.4 15.4 0 0016.187 16h3.07a8.03 8.03 0 01-4.39 3.853zM16.413 14c.05-.66.087-1.32.087-2 0-.68-.037-1.34-.087-2h3.518c.05.64.069 1.31.069 2 0 .69-.019 1.36-.069 2z" })
9725
+ };
9726
+ var SIZE6 = { sm: "h-8 w-8", md: "h-10 w-10" };
9727
+ var VARIANT = {
9728
+ ghost: "text-foreground-secondary hover:bg-surface-raised hover:text-foreground",
9729
+ solid: "bg-surface-raised text-foreground-secondary hover:bg-accent hover:text-accent-fg",
9730
+ outline: "border border-border text-foreground-secondary hover:border-border-strong hover:text-foreground"
9731
+ };
9732
+ function Socials({
9733
+ links,
9734
+ variant = "ghost",
9735
+ size = "md",
9736
+ newTab = true,
9737
+ "aria-label": ariaLabel = "Social links",
9738
+ className = "",
9739
+ style
9740
+ }) {
9741
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": ariaLabel, className: ["flex flex-wrap items-center gap-2", className].filter(Boolean).join(" "), style, children: links.map((link, i) => {
9742
+ const label = link.label ?? (link.platform ? link.platform[0].toUpperCase() + link.platform.slice(1) : "Link");
9743
+ const icon = link.icon ?? (link.platform ? ICONS[link.platform] : null);
9744
+ const ext = newTab && !link.href.startsWith("mailto:");
9745
+ return /* @__PURE__ */ jsxRuntime.jsx(
9746
+ "a",
9747
+ {
9748
+ href: link.href,
9749
+ "aria-label": label,
9750
+ title: label,
9751
+ ...ext ? { target: "_blank", rel: "noopener noreferrer" } : {},
9752
+ className: ["flex items-center justify-center rounded-full transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent", SIZE6[size], VARIANT[variant]].join(" "),
9753
+ children: icon
9754
+ },
9755
+ i
9756
+ );
9757
+ }) });
9758
+ }
9759
+ var POS2 = {
9760
+ "bottom": "inset-x-0 bottom-0 sm:inset-x-4 sm:bottom-4",
9761
+ "bottom-left": "inset-x-0 bottom-0 sm:inset-x-auto sm:left-4 sm:bottom-4 sm:max-w-md",
9762
+ "bottom-right": "inset-x-0 bottom-0 sm:inset-x-auto sm:right-4 sm:bottom-4 sm:max-w-md"
9763
+ };
9764
+ function CookieConsent({
9765
+ message = "We use cookies to enhance your experience, analyse traffic, and personalise content.",
9766
+ title,
9767
+ acceptLabel = "Accept all",
9768
+ declineLabel,
9769
+ onAccept,
9770
+ onDecline,
9771
+ learnMoreHref,
9772
+ learnMoreLabel = "Learn more",
9773
+ storageKey = "oxygen-cookie-consent",
9774
+ open,
9775
+ position = "bottom",
9776
+ className = ""
9777
+ }) {
9778
+ const persist = typeof storageKey === "string";
9779
+ const [stored, setStored] = useLocalStorage(persist ? storageKey : "__oxygen_cc_off__", null);
9780
+ const visible = open ?? (persist ? stored == null : true);
9781
+ const choose = (choice, cb) => {
9782
+ if (persist) setStored(choice);
9783
+ cb?.();
9784
+ };
9785
+ if (!visible) return null;
9786
+ return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
9787
+ "div",
9788
+ {
9789
+ role: "dialog",
9790
+ "aria-label": "Cookie consent",
9791
+ "aria-live": "polite",
9792
+ className: ["fixed z-[60]", POS2[position], className].filter(Boolean).join(" "),
9793
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 border-t border-border bg-surface p-5 shadow-lg sm:flex-row sm:items-center sm:rounded-xl sm:border", children: [
9794
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 text-sm leading-relaxed text-foreground-secondary", children: [
9795
+ title != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-1 font-semibold text-foreground", children: title }),
9796
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: message }),
9797
+ learnMoreHref && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9798
+ " ",
9799
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: learnMoreHref, className: "font-medium text-accent underline-offset-2 hover:underline", children: learnMoreLabel })
9800
+ ] })
9801
+ ] }),
9802
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 gap-2", children: [
9803
+ declineLabel && /* @__PURE__ */ jsxRuntime.jsx(Button_default, { variant: "outline", content: declineLabel, onClick: () => choose("declined", onDecline) }),
9804
+ /* @__PURE__ */ jsxRuntime.jsx(Button_default, { content: acceptLabel, onClick: () => choose("accepted", onAccept) })
9805
+ ] })
9806
+ ] })
9807
+ }
9808
+ ) });
9809
+ }
9810
+ var GRADIENT2 = "radial-gradient(120% 140% at 50% 0%, color-mix(in oklab, var(--color-accent) 14%, transparent), transparent 70%)";
9811
+ function LeadCapture({
9812
+ title,
9813
+ description,
9814
+ placeholder = "you@company.com",
9815
+ inputLabel = "Email address",
9816
+ buttonLabel = "Subscribe",
9817
+ onSubmit,
9818
+ note,
9819
+ successMessage = "Thanks \u2014 you\u2019re on the list.",
9820
+ background = "gradient",
9821
+ centered = true,
9822
+ className = "",
9823
+ style
9824
+ }) {
9825
+ const [email, setEmail] = React28.useState("");
9826
+ const [done, setDone] = React28.useState(false);
9827
+ const submit = (e) => {
9828
+ e.preventDefault();
9829
+ const value = email.trim();
9830
+ if (!value) return;
9831
+ onSubmit?.(value);
9832
+ setDone(true);
9833
+ };
9834
+ const isGradient = background === "gradient";
9835
+ return /* @__PURE__ */ jsxRuntime.jsx(
9836
+ "section",
9837
+ {
9838
+ className: ["w-full overflow-hidden rounded-2xl border border-border bg-surface px-6 py-12 sm:px-12 sm:py-16", className].filter(Boolean).join(" "),
9839
+ style: { ...isGradient ? { backgroundImage: GRADIENT2 } : {}, ...style },
9840
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["mx-auto flex max-w-2xl flex-col gap-4", centered ? "items-center text-center" : "items-start text-left"].join(" "), children: [
9841
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold tracking-tight text-foreground sm:text-3xl", children: title }),
9842
+ description != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xl text-base leading-relaxed text-foreground-secondary", children: description }),
9843
+ done ? /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", className: "mt-2 inline-flex items-center gap-2 text-sm font-medium text-status-success", children: [
9844
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", className: "h-5 w-5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }),
9845
+ successMessage
9846
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: submit, className: ["mt-2 flex w-full max-w-md flex-col gap-2 sm:flex-row", centered ? "sm:justify-center" : ""].join(" "), children: [
9847
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "oxygen-lead-email", className: "sr-only", children: inputLabel }),
9848
+ /* @__PURE__ */ jsxRuntime.jsx(
9849
+ "input",
9850
+ {
9851
+ id: "oxygen-lead-email",
9852
+ type: "email",
9853
+ required: true,
9854
+ value: email,
9855
+ onChange: (e) => setEmail(e.target.value),
9856
+ placeholder,
9857
+ autoComplete: "email",
9858
+ className: [fieldShell({ size: "md" }), "flex-1"].join(" ")
9859
+ }
9860
+ ),
9861
+ /* @__PURE__ */ jsxRuntime.jsx(Button_default, { content: buttonLabel, className: "shrink-0" })
9862
+ ] }),
9863
+ note != null && !done && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-foreground-muted", children: note })
9864
+ ] })
9865
+ }
9866
+ );
9867
+ }
9477
9868
 
9478
9869
  Object.defineProperty(exports, "COLORS", {
9479
9870
  enumerable: true,
@@ -9496,6 +9887,7 @@ exports.AppShell = AppShell;
9496
9887
  exports.AutoComplete = AutoComplete;
9497
9888
  exports.Avatar = Avatar;
9498
9889
  exports.Badge = Badge;
9890
+ exports.Blog = Blog;
9499
9891
  exports.Box = Box;
9500
9892
  exports.Breadcrumbs = Breadcrumbs;
9501
9893
  exports.Button = Button_default;
@@ -9513,6 +9905,7 @@ exports.Checkbox = Checkbox;
9513
9905
  exports.Checkout = Checkout;
9514
9906
  exports.ColorPicker = ColorPicker;
9515
9907
  exports.ContextMenu = ContextMenu;
9908
+ exports.CookieConsent = CookieConsent;
9516
9909
  exports.CreditCardForm = CreditCardForm;
9517
9910
  exports.DateRangePicker = DateRangePicker;
9518
9911
  exports.Drawer = Drawer;
@@ -9536,6 +9929,7 @@ exports.Icon = icons_default;
9536
9929
  exports.IconButton = IconButton;
9537
9930
  exports.Jumbotron = Jumbotron;
9538
9931
  exports.Kbd = Kbd;
9932
+ exports.LeadCapture = LeadCapture;
9539
9933
  exports.List = List2;
9540
9934
  exports.LoadingSpinner = LoadingSpinner;
9541
9935
  exports.LogoutTimer = LogoutTimer;
@@ -9546,6 +9940,7 @@ exports.NotificationProvider = NotificationProvider;
9546
9940
  exports.NumberInput = NumberInput;
9547
9941
  exports.OpaqueGridCard = OpaqueGridCard;
9548
9942
  exports.OtpInput = OtpInput;
9943
+ exports.Parallax = Parallax;
9549
9944
  exports.Password = Password;
9550
9945
  exports.PopConfirm = PopConfirm;
9551
9946
  exports.Portal = Portal;
@@ -9562,7 +9957,9 @@ exports.SkeletonBox = SkeletonBox;
9562
9957
  exports.SkeletonCard = SkeletonCard;
9563
9958
  exports.SkeletonCircle = SkeletonCircle;
9564
9959
  exports.SkeletonText = SkeletonText;
9960
+ exports.SlideShow = SlideShow;
9565
9961
  exports.Slider = Slider;
9962
+ exports.Socials = Socials;
9566
9963
  exports.Statistic = Statistic;
9567
9964
  exports.Stepper = Stepper;
9568
9965
  exports.Switch = Switch;
@@ -9583,6 +9980,7 @@ exports.TopBar = TopBar;
9583
9980
  exports.Tree = Tree;
9584
9981
  exports.TreeSelect = TreeSelect;
9585
9982
  exports.Typography = Typography;
9983
+ exports.Video = Video;
9586
9984
  exports.Wizard = Wizard;
9587
9985
  exports.cardNumberError = cardNumberError;
9588
9986
  exports.cvvError = cvvError;