@mdxui/services 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.d.ts +18 -3
- package/dist/components/index.js +163 -31
- package/dist/components/index.js.map +1 -1
- package/dist/{index-D2nWoFGI.d.ts → index-DNgc8Joy.d.ts} +33 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +339 -192
- package/dist/index.js.map +1 -1
- package/dist/schemas/index.d.ts +1 -1
- package/dist/schemas/index.js +14 -1
- package/dist/schemas/index.js.map +1 -1
- package/dist/shared/index.d.ts +7 -1
- package/dist/shared/index.js +3 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/styles.css +9 -0
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { H as HeroPropsExtended, e as SiteAction, P as ProblemProps$1, f as ProblemItem$1, W as WhatYouGetProps$1, g as WhatYouGetItem$1, a as HowItWorksProps$1, h as HowItWorksStep$1, D as DefensibilityPropsFromSchema, j as DefensibilityColumnFromSchema, k as PriceTier$1, b as PricingPropsExtended, c as Pricing$1, F as FaqPropsExtended, l as FaqItem$1, d as FinalCtaProps$1, M as MastheadProps$1, S as SiteFooterProps, m as SiteFooterLink } from '../index-
|
|
2
|
+
import { H as HeroPropsExtended, e as SiteAction, P as ProblemProps$1, f as ProblemItem$1, W as WhatYouGetProps$1, g as WhatYouGetItem$1, a as HowItWorksProps$1, h as HowItWorksStep$1, D as DefensibilityPropsFromSchema, j as DefensibilityColumnFromSchema, k as PriceTier$1, b as PricingPropsExtended, c as Pricing$1, F as FaqPropsExtended, l as FaqItem$1, d as FinalCtaProps$1, M as MastheadProps$1, N as NavLink, S as SiteFooterProps, m as SiteFooterLink } from '../index-DNgc8Joy.js';
|
|
3
3
|
import 'zod/v4/core';
|
|
4
4
|
import 'zod';
|
|
5
5
|
import 'react';
|
|
@@ -59,7 +59,22 @@ type FinalCtaProps = FinalCtaProps$1;
|
|
|
59
59
|
declare function FinalCta({ eyebrow, headline, primary, secondary, }: FinalCtaProps): react_jsx_runtime.JSX.Element;
|
|
60
60
|
|
|
61
61
|
type MastheadProps = MastheadProps$1;
|
|
62
|
-
declare function Masthead({ brand, cta, eyebrow, narrow }: MastheadProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
declare function Masthead({ brand, cta, links, eyebrow, narrow }: MastheadProps): react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
interface MobileNavProps {
|
|
65
|
+
links: NavLink[];
|
|
66
|
+
cta?: {
|
|
67
|
+
label: string;
|
|
68
|
+
href: string;
|
|
69
|
+
};
|
|
70
|
+
brand: {
|
|
71
|
+
primary: string;
|
|
72
|
+
secondary?: string;
|
|
73
|
+
href: string;
|
|
74
|
+
};
|
|
75
|
+
narrow?: boolean;
|
|
76
|
+
}
|
|
77
|
+
declare function MobileNav({ links, cta, brand, narrow }: MobileNavProps): react_jsx_runtime.JSX.Element;
|
|
63
78
|
|
|
64
79
|
type FooterLink = SiteFooterLink;
|
|
65
80
|
type FooterProps = SiteFooterProps;
|
|
@@ -71,4 +86,4 @@ interface ScrollHeaderProps extends MastheadProps {
|
|
|
71
86
|
}
|
|
72
87
|
declare function ScrollHeader({ threshold, ...mastheadProps }: ScrollHeaderProps): react_jsx_runtime.JSX.Element;
|
|
73
88
|
|
|
74
|
-
export { Defensibility, type DefensibilityColumn, type DefensibilityProps, Faq, type FaqItem, type FaqProps, FinalCta, type FinalCtaProps, Footer, type FooterLink, type FooterProps, Hero, type HeroAction, type HeroProps, HeroSplit, HeroStacked, HowItWorks, type HowItWorksProps, type HowItWorksStep, Masthead, type MastheadProps, type PriceTier, Pricing, type PricingComponentProps, type PricingData, type PricingProps, PrimaryAction, Problem, type ProblemItem, type ProblemProps, Pricing as ReportPricing, ScrollHeader, type ScrollHeaderProps, SecondaryAction, Hero as ServiceHero, WhatYouGet, type WhatYouGetItem, type WhatYouGetProps };
|
|
89
|
+
export { Defensibility, type DefensibilityColumn, type DefensibilityProps, Faq, type FaqItem, type FaqProps, FinalCta, type FinalCtaProps, Footer, type FooterLink, type FooterProps, Hero, type HeroAction, type HeroProps, HeroSplit, HeroStacked, HowItWorks, type HowItWorksProps, type HowItWorksStep, Masthead, type MastheadProps, MobileNav, type MobileNavProps, NavLink, type PriceTier, Pricing, type PricingComponentProps, type PricingData, type PricingProps, PrimaryAction, Problem, type ProblemItem, type ProblemProps, Pricing as ReportPricing, ScrollHeader, type ScrollHeaderProps, SecondaryAction, Hero as ServiceHero, WhatYouGet, type WhatYouGetItem, type WhatYouGetProps };
|
package/dist/components/index.js
CHANGED
|
@@ -507,49 +507,180 @@ function SecondaryLink({ action }) {
|
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
// src/components/Masthead.tsx
|
|
510
|
+
import Link5 from "next/link";
|
|
511
|
+
|
|
512
|
+
// src/components/MobileNav.tsx
|
|
513
|
+
import { useEffect, useState } from "react";
|
|
510
514
|
import Link4 from "next/link";
|
|
511
|
-
import {
|
|
512
|
-
|
|
513
|
-
|
|
515
|
+
import { Menu, X } from "lucide-react";
|
|
516
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
517
|
+
function MobileNav({ links, cta, brand, narrow }) {
|
|
518
|
+
const [open, setOpen] = useState(false);
|
|
519
|
+
const [scrollbarWidth, setScrollbarWidth] = useState(0);
|
|
520
|
+
useEffect(() => {
|
|
521
|
+
if (!open) return;
|
|
522
|
+
const onKey = (e) => {
|
|
523
|
+
if (e.key === "Escape") setOpen(false);
|
|
524
|
+
};
|
|
525
|
+
const prevOverflow = document.body.style.overflow;
|
|
526
|
+
const prevPaddingRight = document.body.style.paddingRight;
|
|
527
|
+
document.body.style.overflow = "hidden";
|
|
528
|
+
if (scrollbarWidth > 0) {
|
|
529
|
+
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
530
|
+
}
|
|
531
|
+
window.addEventListener("keydown", onKey);
|
|
532
|
+
return () => {
|
|
533
|
+
document.body.style.overflow = prevOverflow;
|
|
534
|
+
document.body.style.paddingRight = prevPaddingRight;
|
|
535
|
+
window.removeEventListener("keydown", onKey);
|
|
536
|
+
};
|
|
537
|
+
}, [open, scrollbarWidth]);
|
|
538
|
+
const openMenu = () => {
|
|
539
|
+
setScrollbarWidth(window.innerWidth - document.documentElement.clientWidth);
|
|
540
|
+
setOpen(true);
|
|
541
|
+
};
|
|
542
|
+
const row = "mx-auto px-6 sm:px-10 " + (narrow ? "max-w-[900px]" : "max-w-container");
|
|
543
|
+
return /* @__PURE__ */ jsxs10("div", { className: "md:hidden", children: [
|
|
544
|
+
/* @__PURE__ */ jsx12(
|
|
545
|
+
"button",
|
|
546
|
+
{
|
|
547
|
+
type: "button",
|
|
548
|
+
"aria-label": "Open menu",
|
|
549
|
+
"aria-expanded": open,
|
|
550
|
+
onClick: openMenu,
|
|
551
|
+
className: "flex h-9 w-9 items-center justify-center rounded-cta text-ink transition-colors hover:bg-surface",
|
|
552
|
+
children: /* @__PURE__ */ jsx12(Menu, { className: "h-5 w-5", strokeWidth: 1.75, "aria-hidden": "true" })
|
|
553
|
+
}
|
|
554
|
+
),
|
|
555
|
+
/* @__PURE__ */ jsx12(
|
|
556
|
+
"div",
|
|
557
|
+
{
|
|
558
|
+
"aria-hidden": "true",
|
|
559
|
+
onClick: () => setOpen(false),
|
|
560
|
+
className: "fixed inset-0 z-50 bg-ink/40 transition-opacity duration-[220ms] ease-out-quart " + (open ? "opacity-100" : "pointer-events-none opacity-0")
|
|
561
|
+
}
|
|
562
|
+
),
|
|
563
|
+
/* @__PURE__ */ jsxs10(
|
|
564
|
+
"div",
|
|
565
|
+
{
|
|
566
|
+
role: "dialog",
|
|
567
|
+
"aria-modal": "true",
|
|
568
|
+
"aria-label": "Site navigation",
|
|
569
|
+
style: scrollbarWidth ? { paddingRight: scrollbarWidth } : void 0,
|
|
570
|
+
className: "fixed inset-x-0 top-0 z-50 origin-top bg-paper shadow-sheet transition-[transform,opacity] duration-[220ms] ease-out-quart " + (open ? "translate-y-0 opacity-100" : "pointer-events-none -translate-y-3 opacity-0"),
|
|
571
|
+
children: [
|
|
572
|
+
/* @__PURE__ */ jsxs10(
|
|
573
|
+
"div",
|
|
574
|
+
{
|
|
575
|
+
className: `flex items-center justify-between gap-4 border-b border-line py-5 ${row}`,
|
|
576
|
+
children: [
|
|
577
|
+
/* @__PURE__ */ jsx12(
|
|
578
|
+
Link4,
|
|
579
|
+
{
|
|
580
|
+
href: brand.href,
|
|
581
|
+
onClick: () => setOpen(false),
|
|
582
|
+
className: "font-display text-[18px] tracking-tightish text-ink",
|
|
583
|
+
children: brand.primary
|
|
584
|
+
}
|
|
585
|
+
),
|
|
586
|
+
/* @__PURE__ */ jsx12(
|
|
587
|
+
"button",
|
|
588
|
+
{
|
|
589
|
+
type: "button",
|
|
590
|
+
"aria-label": "Close menu",
|
|
591
|
+
onClick: () => setOpen(false),
|
|
592
|
+
className: "flex h-9 w-9 items-center justify-center rounded-cta text-ink transition-colors hover:bg-surface",
|
|
593
|
+
children: /* @__PURE__ */ jsx12(X, { className: "h-5 w-5", strokeWidth: 1.75, "aria-hidden": "true" })
|
|
594
|
+
}
|
|
595
|
+
)
|
|
596
|
+
]
|
|
597
|
+
}
|
|
598
|
+
),
|
|
599
|
+
/* @__PURE__ */ jsx12("nav", { className: `flex flex-col py-2 ${row}`, children: links.map((l) => /* @__PURE__ */ jsx12(
|
|
600
|
+
Link4,
|
|
601
|
+
{
|
|
602
|
+
href: l.href,
|
|
603
|
+
onClick: () => setOpen(false),
|
|
604
|
+
className: "border-b border-line py-4 font-display text-[20px] tracking-tightish text-ink transition-colors last:border-b-0 hover:text-accent",
|
|
605
|
+
children: l.label
|
|
606
|
+
},
|
|
607
|
+
l.href
|
|
608
|
+
)) }),
|
|
609
|
+
cta && /* @__PURE__ */ jsx12("div", { className: `pb-6 pt-3 ${row}`, children: /* @__PURE__ */ jsx12(
|
|
610
|
+
Link4,
|
|
611
|
+
{
|
|
612
|
+
href: cta.href,
|
|
613
|
+
onClick: () => setOpen(false),
|
|
614
|
+
className: "block rounded-cta bg-cta px-4 py-3 text-center text-[13px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover",
|
|
615
|
+
children: cta.label
|
|
616
|
+
}
|
|
617
|
+
) })
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
)
|
|
621
|
+
] });
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/components/Masthead.tsx
|
|
625
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
626
|
+
function Masthead({ brand, cta, links, eyebrow, narrow }) {
|
|
627
|
+
const hasNav = Boolean(links && links.length > 0);
|
|
628
|
+
return /* @__PURE__ */ jsx13("header", { className: "border-b border-line", children: /* @__PURE__ */ jsxs11(
|
|
514
629
|
"div",
|
|
515
630
|
{
|
|
516
|
-
className: "mx-auto flex items-center justify-between gap-4 px-6 py-5 sm:px-10 " + (narrow ? "max-w-[900px]" : "max-w-container"),
|
|
631
|
+
className: "relative mx-auto flex items-center justify-between gap-4 px-6 py-5 sm:px-10 " + (narrow ? "max-w-[900px]" : "max-w-container"),
|
|
517
632
|
children: [
|
|
518
|
-
/* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */
|
|
520
|
-
|
|
633
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3", children: [
|
|
634
|
+
/* @__PURE__ */ jsxs11(
|
|
635
|
+
Link5,
|
|
521
636
|
{
|
|
522
637
|
href: brand.href,
|
|
523
|
-
className: "font-display text-[18px] tracking-tightish text-ink",
|
|
524
|
-
children:
|
|
638
|
+
className: "inline-flex items-center gap-2 font-display text-[18px] tracking-tightish text-ink",
|
|
639
|
+
children: [
|
|
640
|
+
brand.logo && // eslint-disable-next-line @next/next/no-img-element
|
|
641
|
+
/* @__PURE__ */ jsx13("img", { src: brand.logo.src, alt: brand.logo.alt, className: "h-6 w-auto" }),
|
|
642
|
+
brand.primary
|
|
643
|
+
]
|
|
525
644
|
}
|
|
526
645
|
),
|
|
527
|
-
brand.secondary && /* @__PURE__ */
|
|
528
|
-
/* @__PURE__ */
|
|
529
|
-
/* @__PURE__ */
|
|
646
|
+
brand.secondary && /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
647
|
+
/* @__PURE__ */ jsx13("span", { className: "hidden h-4 w-px bg-line2 sm:inline-block" }),
|
|
648
|
+
/* @__PURE__ */ jsx13("span", { className: "hidden text-[11px] uppercase tracking-[0.18em] text-ink3 sm:inline", children: brand.secondary })
|
|
530
649
|
] })
|
|
531
650
|
] }),
|
|
532
|
-
|
|
533
|
-
|
|
651
|
+
hasNav && /* @__PURE__ */ jsx13("nav", { className: "absolute left-1/2 hidden -translate-x-1/2 items-center gap-7 md:flex", children: links.map((l) => /* @__PURE__ */ jsx13(
|
|
652
|
+
Link5,
|
|
534
653
|
{
|
|
535
|
-
href:
|
|
536
|
-
className: "
|
|
537
|
-
children:
|
|
538
|
-
}
|
|
539
|
-
|
|
654
|
+
href: l.href,
|
|
655
|
+
className: "text-[13px] tracking-tightish text-ink2 transition-colors hover:text-ink",
|
|
656
|
+
children: l.label
|
|
657
|
+
},
|
|
658
|
+
l.href
|
|
659
|
+
)) }),
|
|
660
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
661
|
+
cta ? /* @__PURE__ */ jsx13(
|
|
662
|
+
Link5,
|
|
663
|
+
{
|
|
664
|
+
href: cta.href,
|
|
665
|
+
className: "rounded-cta bg-cta px-4 py-2 text-[12px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover",
|
|
666
|
+
children: cta.label
|
|
667
|
+
}
|
|
668
|
+
) : eyebrow ? /* @__PURE__ */ jsx13("span", { className: "text-[10.5px] uppercase tracking-[0.18em] text-ink3", children: eyebrow }) : null,
|
|
669
|
+
hasNav && /* @__PURE__ */ jsx13(MobileNav, { links, cta, brand, narrow })
|
|
670
|
+
] })
|
|
540
671
|
]
|
|
541
672
|
}
|
|
542
673
|
) });
|
|
543
674
|
}
|
|
544
675
|
|
|
545
676
|
// src/components/Footer.tsx
|
|
546
|
-
import
|
|
547
|
-
import { jsx as
|
|
677
|
+
import Link6 from "next/link";
|
|
678
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
548
679
|
function Footer({ text, links }) {
|
|
549
|
-
return /* @__PURE__ */
|
|
550
|
-
/* @__PURE__ */
|
|
551
|
-
links && links.length > 0 && /* @__PURE__ */
|
|
552
|
-
|
|
680
|
+
return /* @__PURE__ */ jsx14("footer", { className: "border-t border-line", children: /* @__PURE__ */ jsxs12("div", { className: "mx-auto flex max-w-container flex-col items-center gap-4 px-6 py-10 text-center text-[12px] text-ink3 sm:flex-row sm:justify-between sm:px-10 sm:text-left", children: [
|
|
681
|
+
/* @__PURE__ */ jsx14("p", { children: text }),
|
|
682
|
+
links && links.length > 0 && /* @__PURE__ */ jsx14("ul", { className: "flex flex-wrap items-center justify-center gap-x-5 gap-y-2 sm:justify-end", children: links.map((l) => /* @__PURE__ */ jsx14("li", { children: /* @__PURE__ */ jsx14(
|
|
683
|
+
Link6,
|
|
553
684
|
{
|
|
554
685
|
href: l.href,
|
|
555
686
|
className: "text-ink3 no-underline transition-colors hover:text-ink",
|
|
@@ -560,14 +691,14 @@ function Footer({ text, links }) {
|
|
|
560
691
|
}
|
|
561
692
|
|
|
562
693
|
// src/components/ScrollHeader.tsx
|
|
563
|
-
import { useEffect, useState } from "react";
|
|
564
|
-
import { jsx as
|
|
694
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
695
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
565
696
|
function ScrollHeader({
|
|
566
697
|
threshold = 480,
|
|
567
698
|
...mastheadProps
|
|
568
699
|
}) {
|
|
569
|
-
const [visible, setVisible] =
|
|
570
|
-
|
|
700
|
+
const [visible, setVisible] = useState2(false);
|
|
701
|
+
useEffect2(() => {
|
|
571
702
|
let raf = 0;
|
|
572
703
|
const update = () => {
|
|
573
704
|
raf = 0;
|
|
@@ -584,12 +715,12 @@ function ScrollHeader({
|
|
|
584
715
|
if (raf) cancelAnimationFrame(raf);
|
|
585
716
|
};
|
|
586
717
|
}, [threshold]);
|
|
587
|
-
return /* @__PURE__ */
|
|
718
|
+
return /* @__PURE__ */ jsx15(
|
|
588
719
|
"div",
|
|
589
720
|
{
|
|
590
721
|
"aria-hidden": !visible,
|
|
591
722
|
className: "pointer-events-none fixed inset-x-0 top-0 z-40 transition-[transform,opacity] duration-[220ms] ease-out-quart " + (visible ? "translate-y-0 opacity-100" : "-translate-y-full opacity-0"),
|
|
592
|
-
children: /* @__PURE__ */
|
|
723
|
+
children: /* @__PURE__ */ jsx15("div", { className: "pointer-events-auto bg-paper shadow-sheet", children: /* @__PURE__ */ jsx15(Masthead, { ...mastheadProps }) })
|
|
593
724
|
}
|
|
594
725
|
);
|
|
595
726
|
}
|
|
@@ -603,6 +734,7 @@ export {
|
|
|
603
734
|
HeroStacked,
|
|
604
735
|
HowItWorks,
|
|
605
736
|
Masthead,
|
|
737
|
+
MobileNav,
|
|
606
738
|
Pricing,
|
|
607
739
|
PrimaryAction,
|
|
608
740
|
Problem,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/HeroSplit.tsx","../../src/components/HeroStacked.tsx","../../src/components/Hero.tsx","../../src/shared/section-eyebrow.tsx","../../src/components/Problem.tsx","../../src/components/WhatYouGet.tsx","../../src/components/HowItWorks.tsx","../../src/components/Defensibility.tsx","../../src/components/Pricing.tsx","../../src/components/Faq.tsx","../../src/components/FinalCta.tsx","../../src/components/Masthead.tsx","../../src/components/Footer.tsx","../../src/components/ScrollHeader.tsx"],"sourcesContent":["/** Hero variant: split-illustration-right.\n *\n * Text-left + ~360px illustration column on lg+. The Services-dialect hero\n * layout — outcome-led grammar (eyebrow / headline / body / primary /\n * secondary), NOT neo's code-bento hero with `installSnippet`.\n *\n * The illustration column accepts either:\n * 1. A custom `illustration` prop (raw ReactNode, used by the per-service\n * illustration manifest AND by per-product HeroGlyph SVGs)\n * 2. The dialect default `<HeroGlyph />` when no custom one provided\n * 3. Nothing at all when `showGlyph={false}` (text-only hero)\n *\n * Pairs with the `glyphOnMobile` prop to control mobile rendering. */\n\nimport Link from 'next/link'\nimport { ChevronRight } from 'lucide-react'\n\nimport * as schemas from '../schemas'\n\n/** Inline call-to-action. Sourced from the schema — `SiteActionSchema`. */\nexport type HeroAction = schemas.SiteAction\n\n/** Hero component props. Sourced from the schema (`HeroPropsExtendedSchema`).\n * The schema is the canonical shape; this component reads `variant`,\n * `showGlyph`, `glyphOnMobile`, `illustration` from it. */\nexport type HeroProps = schemas.HeroPropsExtended\n\nexport function HeroSplit({\n eyebrow,\n headline,\n body,\n primary,\n secondary,\n showGlyph = true,\n /* INTENTIONALLY UNDEFAULTED — the smart default below uses the\n * undefined state to distinguish \"explicitly unset\" from\n * \"explicitly false\" (the opt-out escape hatch). */\n glyphOnMobile,\n illustration,\n}: HeroProps) {\n /* Smart mobile-visibility default for hero illustrations.\n *\n * - Explicit `glyphOnMobile: true` → show on mobile\n * - Explicit `glyphOnMobile: false` → hide on mobile (opt-out)\n * - Unset + bespoke `illustration` → DEFAULT TRUE (bespoke illustrations\n * ARE the value-prop preview and must show on mobile)\n * - Unset + no illustration (HeroGlyph renders) → DEFAULT FALSE\n */\n const effectiveGlyphOnMobile = glyphOnMobile ?? Boolean(illustration)\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-28 lg:py-32\">\n <div className={showGlyph ? 'lg:grid lg:grid-cols-[minmax(0,1fr)_360px] lg:items-center lg:gap-16' : ''}>\n <div>\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </p>\n <h1 className=\"mt-5 max-w-[18ch] font-display text-display-hero leading-[1.04] tracking-tighter2 text-ink\">\n {headline}\n </h1>\n <p className=\"mt-6 max-w-[58ch] text-[16px] leading-relaxed text-ink2 sm:mt-7 sm:text-[17px]\">\n {body}\n </p>\n <div className=\"mt-10 flex flex-col items-stretch gap-4 sm:flex-row sm:flex-wrap sm:items-center\">\n <PrimaryAction action={primary} />\n {secondary && <SecondaryAction action={secondary} />}\n </div>\n </div>\n {showGlyph && (\n <div\n className={\n effectiveGlyphOnMobile\n ? 'mt-12 lg:mt-0 lg:block'\n : 'hidden lg:block'\n }\n aria-hidden=\"true\"\n >\n {illustration ?? <HeroGlyph />}\n </div>\n )}\n </div>\n </div>\n </section>\n )\n}\n\nexport function PrimaryAction({ action }: { action: HeroAction }) {\n // Theme-driven CTA recipe. `bg-cta / bg-cta-hover / text-cta-fg` resolve via\n // `--cta-*` vars set by `@mdxui/themes`' `themeToCssVars()` per theme.\n const className =\n 'inline-flex w-full items-center justify-center gap-1.5 rounded-cta bg-cta px-5 py-3 text-[14px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover sm:w-auto sm:justify-start'\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {action.label}\n <ChevronRight className=\"h-4 w-4\" strokeWidth={1.7} />\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {action.label}\n <ChevronRight className=\"h-4 w-4\" strokeWidth={1.7} />\n </Link>\n )\n}\n\nexport function SecondaryAction({ action }: { action: HeroAction }) {\n const className =\n 'inline-flex items-center justify-center gap-1.5 text-[13px] font-medium tracking-tightish text-ink2 transition-colors hover:text-accentDeep sm:justify-start'\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {action.label}\n <ChevronRight className=\"h-3.5 w-3.5\" strokeWidth={1.7} />\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {action.label}\n <ChevronRight className=\"h-3.5 w-3.5\" strokeWidth={1.7} />\n </Link>\n )\n}\n\n/** Sparse geometric mark: stack of comp lines, median emphasized in\n * accent teal, range bracket on the right. Default for split-variant\n * heroes that don't pass a custom `illustration`. */\nfunction HeroGlyph() {\n return (\n <svg\n viewBox=\"0 0 360 280\"\n className=\"h-auto w-full\"\n fill=\"none\"\n role=\"presentation\"\n >\n <g\n stroke=\"oklch(var(--ink3) / 0.55)\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"40\" y1=\"40\" x2=\"180\" y2=\"40\" />\n <line x1=\"60\" y1=\"78\" x2=\"220\" y2=\"78\" />\n <line x1=\"40\" y1=\"172\" x2=\"200\" y2=\"172\" />\n <line x1=\"80\" y1=\"210\" x2=\"260\" y2=\"210\" />\n <line x1=\"60\" y1=\"248\" x2=\"180\" y2=\"248\" />\n </g>\n <line\n x1=\"40\"\n y1=\"135\"\n x2=\"280\"\n y2=\"135\"\n stroke=\"oklch(var(--accent))\"\n strokeWidth=\"2.75\"\n strokeLinecap=\"round\"\n />\n <circle cx=\"280\" cy=\"135\" r=\"4\" fill=\"oklch(var(--accent-deep))\" />\n <g\n stroke=\"oklch(var(--accent-deep) / 0.85)\"\n strokeWidth=\"1\"\n strokeLinecap=\"round\"\n >\n <line x1=\"312\" y1=\"100\" x2=\"312\" y2=\"170\" />\n <line x1=\"306\" y1=\"100\" x2=\"318\" y2=\"100\" />\n <line x1=\"306\" y1=\"170\" x2=\"318\" y2=\"170\" />\n <line x1=\"308\" y1=\"135\" x2=\"316\" y2=\"135\" />\n </g>\n </svg>\n )\n}\n","/** Hero variant: stacked-illustration-below.\n *\n * Text-center top + illustration centered below at ~1080px cap. For services\n * whose hero illustration needs full-bleed scale — code editors, spreadsheets,\n * dashboard mockups — that would feel cramped in the 360px split slot.\n *\n * Unlike HeroSplit, this variant has NO default glyph fallback — the\n * dispatcher in `./Hero.tsx` only routes here when an `illustration` is\n * provided. Services without a bespoke illustration fall back to HeroSplit\n * (which has the `<HeroGlyph />` default mark). */\n\nimport type { HeroProps } from './HeroSplit'\nimport { PrimaryAction, SecondaryAction } from './HeroSplit'\n\nexport function HeroStacked({\n eyebrow,\n headline,\n body,\n primary,\n secondary,\n illustration,\n}: HeroProps) {\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-28 lg:py-32\">\n <div className=\"text-center\">\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </p>\n <h1 className=\"mx-auto mt-5 max-w-[22ch] font-display text-display-hero leading-[1.04] tracking-tighter2 text-ink\">\n {headline}\n </h1>\n <p className=\"mx-auto mt-6 max-w-[60ch] text-[16px] leading-relaxed text-ink2 sm:mt-7 sm:text-[17px]\">\n {body}\n </p>\n <div className=\"mt-10 flex flex-col items-stretch justify-center gap-4 sm:flex-row sm:flex-wrap sm:items-center\">\n <PrimaryAction action={primary} />\n {secondary && <SecondaryAction action={secondary} />}\n </div>\n </div>\n {/* Illustration sits below text, capped at 1080px so it feels\n * substantial without bullying the page. */}\n <div className=\"mx-auto mt-14 max-w-[1080px] sm:mt-16\" aria-hidden=\"true\">\n {illustration}\n </div>\n </div>\n </section>\n )\n}\n","/** ServiceHero — Services-dialect hero composition dispatcher.\n *\n * Routes to the variant render based on `variant` (from the\n * `HeroPropsExtendedSchema`). Default is `'split-illustration-right'`\n * (`HeroSplit`). Adding a future variant = new `Hero<Name>.tsx` file + one\n * additional dispatcher branch here. */\n\nimport { HeroSplit, type HeroAction, type HeroProps } from './HeroSplit'\nimport { HeroStacked } from './HeroStacked'\n\nexport type { HeroAction, HeroProps }\n\nexport function Hero(props: HeroProps) {\n if (props.variant === 'stacked-illustration-below' && props.illustration) {\n return <HeroStacked {...props} />\n }\n return <HeroSplit {...props} />\n}\n\n/** Services-dialect alias — the dialect names this block `ServiceHero`\n * (ADR 0003 §3). Same component as `Hero`. */\nexport { Hero as ServiceHero }\n","/** Small uppercase label that anchors a section heading. */\n\nexport function SectionEyebrow({ children }: { children: React.ReactNode }) {\n return (\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {children}\n </p>\n )\n}\n","/** Three-card \"problem\" section. Each card has a category label, a\n * cost line, a one-line outcome verdict, and a body paragraph. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type ProblemItem = schemas.ProblemItem\n\nexport type ProblemProps = schemas.ProblemProps\n\nexport function Problem({ eyebrow, heading, items }: ProblemProps) {\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className=\"mt-12 grid gap-8 md:grid-cols-3\">\n {items.map((item) => (\n <ProblemCard key={item.label} {...item} />\n ))}\n </div>\n </div>\n </section>\n )\n}\n\nfunction ProblemCard({ label, cost, outcome, body }: ProblemItem) {\n return (\n <article>\n <p className=\"text-[10.5px] uppercase tracking-[0.16em] text-ink3\">\n {label}\n </p>\n <p className=\"mt-3 font-display text-[24px] leading-tight tracking-tightish text-ink\">\n {cost}\n </p>\n <p className=\"mt-4 text-body-sm font-medium leading-snug tracking-tightish text-accentDeep\">\n {outcome}\n </p>\n <p className=\"mt-3 text-body-sm leading-relaxed text-ink2\">{body}</p>\n </article>\n )\n}\n","/** \"What's in the report\" — numbered grid listing each section. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type WhatYouGetItem = schemas.WhatYouGetItem\n\nexport type WhatYouGetProps = schemas.WhatYouGetProps\n\nexport function WhatYouGet({ eyebrow, heading, sections }: WhatYouGetProps) {\n // Empty-array graceful handling — skip the section entirely rather\n // than render dangling chrome (eyebrow + heading) above an empty grid.\n if (sections.length === 0) return null\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <ul className=\"mt-12 grid gap-x-8 gap-y-7 md:grid-cols-2 lg:grid-cols-3\">\n {sections.map((s) => (\n <li key={s.n}>\n <p className=\"font-display text-[14px] tracking-tightish text-ink3\">\n {s.n}\n </p>\n <p className=\"mt-1.5 text-[15px] font-medium tracking-tightish text-ink\">\n {s.title}\n </p>\n <p className=\"mt-1.5 text-[13.5px] leading-relaxed text-ink2\">\n {s.body}\n </p>\n </li>\n ))}\n </ul>\n </div>\n </section>\n )\n}\n","/** Three-column \"how it works\" strip with large numbered eyebrows.\n *\n * Optional per-step illustration row above the number — opt in by passing\n * `stepIllustrations` (a `ComponentType[]` matching `steps.length`). When the\n * lengths don't match (or the prop is absent), the text-only layout renders\n * unchanged. Opt-in only, never degrade. */\n\nimport type { ComponentType } from 'react'\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type HowItWorksStep = schemas.HowItWorksStep\n\n/** HowItWorks component props. Sourced from `HowItWorksPropsSchema`, which\n * includes the opt-in `stepIllustrations` field. */\nexport type HowItWorksProps = schemas.HowItWorksProps\n\nexport function HowItWorks({\n eyebrow,\n heading,\n steps,\n stepIllustrations,\n}: HowItWorksProps) {\n // Empty-array graceful handling — skip the section entirely.\n if (steps.length === 0) return null\n const hasIllustrations =\n stepIllustrations !== undefined &&\n stepIllustrations.length === steps.length\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <ol\n itemScope\n itemType=\"https://schema.org/HowTo\"\n className=\"mt-12 grid gap-10 md:grid-cols-3\"\n >\n {steps.map((s, i) => (\n <Step\n key={s.n}\n {...s}\n illustration={hasIllustrations ? stepIllustrations![i] : undefined}\n />\n ))}\n </ol>\n </div>\n </section>\n )\n}\n\nfunction Step({\n n,\n title,\n body,\n illustration: Illustration,\n}: HowItWorksStep & { illustration?: ComponentType }) {\n /* When step illustrations are present, the parent grid stretches all <li>s to\n * the height of the tallest column; the flex-col + `mt-auto` on the text block\n * pushes numbers / titles / bodies to a shared baseline. Without an\n * illustration, content flows naturally from the top (text-only layout). */\n return (\n <li\n itemScope\n itemType=\"https://schema.org/HowToStep\"\n className={Illustration ? 'flex flex-col' : undefined}\n >\n {Illustration && (\n <div className=\"mb-6 w-full lg:max-w-[320px]\">\n <Illustration />\n </div>\n )}\n <div className={Illustration ? 'mt-auto' : undefined}>\n <p className=\"font-display text-[36px] leading-none tracking-tighter2 text-ink3/60\">\n {n}\n </p>\n <p className=\"mt-4 font-display text-[20px] leading-tight tracking-tightish text-ink\">\n {title}\n </p>\n <p className=\"mt-3 text-body-sm leading-relaxed text-ink2\">{body}</p>\n </div>\n </li>\n )\n}\n","/** Two-column \"what it is / what it isn't\" block with a closing caveat\n * paragraph — THE Services signature block (ADR 0003 §3). Used to set scope\n * expectations on a service page. No neo equivalent. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type DefensibilityColumn = schemas.DefensibilityColumnFromSchema\n\nexport type DefensibilityProps = schemas.DefensibilityPropsFromSchema\n\nexport function Defensibility({\n eyebrow,\n heading,\n columns,\n caveat,\n}: DefensibilityProps) {\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className=\"mt-10 grid gap-10 lg:grid-cols-2\">\n {columns.map((col) => (\n <Column key={col.heading} {...col} />\n ))}\n </div>\n {caveat && (\n <p className=\"mt-12 max-w-[68ch] text-body-xs leading-relaxed text-ink3\">\n {caveat}\n </p>\n )}\n </div>\n </section>\n )\n}\n\nfunction Column({ heading, bullets }: DefensibilityColumn) {\n return (\n <div>\n <h3 className=\"font-display text-[18px] leading-tight tracking-tightish text-ink\">\n {heading}\n </h3>\n <ul className=\"mt-4 space-y-3 text-body-sm leading-relaxed text-ink2\">\n {bullets.map((b, i) => (\n <li key={i} className=\"flex gap-2.5\">\n <span className=\"mt-2 h-1 w-1 shrink-0 rounded-full bg-ink3\" />\n <span>{b}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n","/** ReportPricing — the Services-dialect pricing section. Two variants on the\n * discriminated `Pricing` union:\n *\n * - `kind: 'tiered'` — renders 1, 2, or 3 tier cards. CTAs flex to the bottom\n * of each card so heights stay symmetric.\n * - `kind: 'unit'` — renders a single per-unit price (\"$3 per transcript\"\n * style) with billing cadence. No tier chrome, no per-tier CTA.\n *\n * Services grammar: \"per report, no subscription\" — NOT neo's subscription\n * tier pricing. The default price suffix is \"/ report\". */\n\nimport Link from 'next/link'\nimport { ChevronRight } from 'lucide-react'\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type PriceTier = schemas.PriceTier\n\n/** Legacy tiered-only props shape (omits `kind` + `currency`). The component\n * accepts EITHER this OR the wider discriminated `Pricing` union. */\nexport type PricingProps = schemas.PricingPropsExtended\n\n/** The canonical discriminated `Pricing` union (carries `kind: 'unit'`). */\nexport type PricingData = schemas.Pricing\n\n/** Component-level accepted props: the legacy tiered-only shape OR the\n * discriminated `Pricing` union. The component branches on `kind` internally. */\nexport type PricingComponentProps = PricingProps | PricingData\n\nconst GRID_COLS: Record<1 | 2 | 3, string> = {\n 1: 'max-w-[420px]',\n 2: 'max-w-[820px] md:grid-cols-2',\n 3: 'max-w-container md:grid-cols-3',\n}\n\nexport function Pricing(props: PricingComponentProps) {\n if ('kind' in props && props.kind === 'unit') {\n return <UnitPricing {...props} />\n }\n // Both legacy `PricingProps` (no `kind`) and `PricingTiered`\n // (`kind: 'tiered'`) hit this branch — both carry `tiers[]`.\n return <TieredPricing {...(props as TieredRenderProps)} />\n}\n\ntype TieredRenderProps = {\n eyebrow: string\n heading: string\n tiers: readonly PriceTier[]\n footnote?: string\n}\n\nfunction TieredPricing({\n eyebrow,\n heading,\n tiers,\n footnote,\n}: TieredRenderProps) {\n // Empty-array graceful handling — skip the section entirely.\n if (tiers.length === 0) return null\n const count = (\n tiers.length === 1 || tiers.length === 2 ? tiers.length : 3\n ) as 1 | 2 | 3\n return (\n <section className=\"border-b border-line bg-surface\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className={`mt-12 mx-auto grid gap-6 ${GRID_COLS[count]}`}>\n {tiers.map((t) => (\n <PriceCard key={t.tier} {...t} />\n ))}\n </div>\n {footnote && (\n <p className=\"mt-10 max-w-[64ch] text-[13px] text-ink3\">{footnote}</p>\n )}\n </div>\n </section>\n )\n}\n\n/** Format a per-unit price using `Intl.NumberFormat`. Trims trailing\n * zero-cents for clean reading (\"$3\" not \"$3.00\"). */\nfunction formatPerUnit(perUnit: number, currency: 'usd' | 'eur' | 'gbp'): string {\n const isWhole = Number.isInteger(perUnit)\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: isWhole ? 0 : 2,\n maximumFractionDigits: 2,\n }).format(perUnit)\n}\n\nfunction UnitPricing({\n eyebrow,\n heading,\n footnote,\n currency,\n perUnit,\n billingCadence,\n}: Extract<PricingData, { kind: 'unit' }>) {\n const formatted = formatPerUnit(perUnit, currency)\n return (\n <section className=\"border-b border-line bg-surface\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className=\"mt-12 mx-auto max-w-[420px]\">\n <article\n itemScope\n itemType=\"https://schema.org/Offer\"\n data-pricing-kind=\"unit\"\n className=\"flex flex-col rounded-card border border-line bg-paper p-7\"\n >\n <p className=\"text-[10.5px] uppercase tracking-[0.16em] text-ink3\">\n Per call\n </p>\n <p className=\"mt-3 flex items-baseline gap-2\">\n <span className=\"font-display text-[40px] leading-none tracking-tighter2 text-ink\">\n {formatted}\n </span>\n <span className=\"text-[12px] text-ink3\">{billingCadence}</span>\n </p>\n </article>\n </div>\n {footnote && (\n <p className=\"mt-10 max-w-[64ch] text-[13px] text-ink3\">{footnote}</p>\n )}\n </div>\n </section>\n )\n}\n\n/** Split a price string like \"$0.10/VIN\" into (\"$0.10\", \"/VIN\"). */\nfunction splitPrice(price: string): { core: string; suffix: string | null } {\n const i = price.indexOf('/')\n if (i === -1) return { core: price, suffix: null }\n return { core: price.slice(0, i).trim(), suffix: price.slice(i) }\n}\n\n/** Resolve the suffix shown after the price. Explicit per-tier `priceSuffix`\n * wins; otherwise an auto-extracted \"/X\"; otherwise the dialect default\n * \"/ report\" (the \"per report, no subscription\" Services grammar). */\nfunction resolvePriceSuffix(\n price: string,\n override: string | undefined,\n): string {\n if (override !== undefined) return override\n const { suffix } = splitPrice(price)\n return suffix ?? '/ report'\n}\n\nfunction PriceCard({\n tierKey,\n tier,\n price,\n priceSuffix,\n audience,\n features,\n featured,\n cta,\n}: PriceTier) {\n const isMailto = cta.href.startsWith('mailto:')\n const { core } = splitPrice(price)\n const suffix = resolvePriceSuffix(price, priceSuffix)\n return (\n <article\n itemScope\n itemType=\"https://schema.org/Offer\"\n data-tier-key={tierKey}\n className={\n 'flex flex-col rounded-card border bg-paper p-7 ' +\n (featured ? 'border-accent shadow-lift' : 'border-line')\n }\n >\n <p className=\"text-[10.5px] uppercase tracking-[0.16em] text-ink3\">\n {tier}\n </p>\n <p className=\"mt-3 flex items-baseline gap-2\">\n <span className=\"font-display text-[40px] leading-none tracking-tighter2 text-ink\">\n {core}\n </span>\n {suffix && <span className=\"text-[12px] text-ink3\">{suffix}</span>}\n </p>\n <p className=\"mt-2 text-[13px] text-ink2\">{audience}</p>\n <ul className=\"mt-6 flex-1 space-y-2.5 text-[13.5px] text-ink2\">\n {features.map((f) => (\n <li key={f} className=\"flex gap-2.5\">\n <span\n className={\n 'mt-2 h-1 w-1 shrink-0 rounded-full ' +\n (featured ? 'bg-accent' : 'bg-ink3')\n }\n />\n <span>{f}</span>\n </li>\n ))}\n </ul>\n <PriceCardCta\n label={cta.label}\n href={cta.href}\n featured={featured}\n external={isMailto}\n />\n </article>\n )\n}\n\nfunction PriceCardCta({\n label,\n href,\n featured,\n external,\n}: {\n label: string\n href: string\n featured?: boolean\n external?: boolean\n}) {\n const baseClass =\n 'mt-7 inline-flex w-full items-center justify-center gap-1.5 rounded-cta px-5 py-2.5 text-[13.5px] font-medium tracking-tightish transition-colors'\n // Theme-driven CTA recipe for the featured tier. The unfeatured (outlined)\n // variant stays ink-typed as a quiet secondary action.\n const variantClass = featured\n ? 'bg-cta text-cta-fg hover:bg-cta-hover'\n : 'border border-line2 bg-paper text-ink hover:border-ink hover:text-ink'\n const className = `${baseClass} ${variantClass}`\n const body = (\n <>\n {label}\n <ChevronRight className=\"h-3.5 w-3.5\" strokeWidth={1.7} />\n </>\n )\n if (external) {\n return (\n <a className={className} href={href} data-action=\"buy\">\n {body}\n </a>\n )\n }\n return (\n <Link className={className} href={href} data-action=\"buy\">\n {body}\n </Link>\n )\n}\n\n/** Services-dialect alias — the dialect names this block `ReportPricing`\n * (ADR 0003 §3: \"per report, no subscription\"). Same component as `Pricing`. */\nexport { Pricing as ReportPricing }\n","/** Two-column FAQ grid. Each item is a question (display serif) and an\n * answer paragraph (sans). Uses Services' short-key q/a convention. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type FaqItem = schemas.FaqItem\n\nexport type FaqProps = schemas.FaqPropsExtended\n\nexport function Faq({ eyebrow, heading, items }: FaqProps) {\n // Empty-array graceful handling — skip the section entirely.\n if (items.length === 0) return null\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[20ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <dl className=\"mt-12 grid gap-x-12 gap-y-10 md:grid-cols-2\">\n {items.map((f) => (\n <div key={f.q} itemScope itemType=\"https://schema.org/Question\">\n <dt className=\"font-display text-body leading-snug tracking-tightish text-ink\">\n {f.q}\n </dt>\n <dd className=\"mt-2 text-body-sm leading-relaxed text-ink2\">\n {f.a}\n </dd>\n </div>\n ))}\n </dl>\n </div>\n </section>\n )\n}\n","/** Closing call-to-action with a centered headline and one or two buttons.\n * Primary is always rendered; secondary is optional and rendered as a quieter\n * link beside the primary pill. */\n\nimport Link from 'next/link'\nimport { ChevronRight } from 'lucide-react'\nimport * as schemas from '../schemas'\n\nexport type FinalCtaProps = schemas.FinalCtaProps\n\ntype CtaAction = schemas.SiteAction\n\nexport function FinalCta({\n eyebrow,\n headline,\n primary,\n secondary,\n}: FinalCtaProps) {\n return (\n <section>\n <div className=\"mx-auto max-w-container px-6 py-20 text-center sm:px-10 sm:py-32\">\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </p>\n <h2 className=\"mx-auto mt-4 max-w-[22ch] font-display text-[36px] leading-[1.04] tracking-tighter2 text-ink sm:text-[52px]\">\n {headline}\n </h2>\n <div className=\"mt-10 flex flex-col items-stretch gap-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-center\">\n <PrimaryButton action={primary} />\n {secondary && <SecondaryLink action={secondary} />}\n </div>\n </div>\n </section>\n )\n}\n\nfunction PrimaryButton({ action }: { action: CtaAction }) {\n // Theme-driven CTA recipe — see Hero.tsx for context.\n const className =\n 'inline-flex w-full items-center justify-center gap-1.5 rounded-cta bg-cta px-6 py-3 text-[14px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover sm:w-auto'\n const body = (\n <>\n {action.label}\n <ChevronRight className=\"h-4 w-4\" strokeWidth={1.7} />\n </>\n )\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {body}\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {body}\n </Link>\n )\n}\n\nfunction SecondaryLink({ action }: { action: CtaAction }) {\n const className =\n 'inline-flex items-center justify-center gap-1.5 text-[13px] font-medium tracking-tightish text-ink3 transition-colors hover:text-ink'\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {action.label}\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {action.label}\n </Link>\n )\n}\n","/** Static masthead at the top of a service page. Pairs with ScrollHeader,\n * which reveals on scroll once this one has scrolled away.\n *\n * Right-side slot is either a primary CTA pill (`cta`) or a small uppercase\n * status label (`eyebrow`) — passing both lets `cta` win. Use `narrow` when\n * the page below uses the 900px container instead of the default 1100px. */\n\nimport Link from 'next/link'\nimport * as schemas from '../schemas'\n\nexport type MastheadProps = schemas.MastheadProps\n\nexport function Masthead({ brand, cta, eyebrow, narrow }: MastheadProps) {\n return (\n <header className=\"border-b border-line\">\n <div\n className={\n 'mx-auto flex items-center justify-between gap-4 px-6 py-5 sm:px-10 ' +\n (narrow ? 'max-w-[900px]' : 'max-w-container')\n }\n >\n <div className=\"flex items-center gap-3\">\n <Link\n href={brand.href}\n className=\"font-display text-[18px] tracking-tightish text-ink\"\n >\n {brand.primary}\n </Link>\n {brand.secondary && (\n <>\n <span className=\"hidden h-4 w-px bg-line2 sm:inline-block\" />\n <span className=\"hidden text-[11px] uppercase tracking-[0.18em] text-ink3 sm:inline\">\n {brand.secondary}\n </span>\n </>\n )}\n </div>\n {cta ? (\n <Link\n href={cta.href}\n // Theme-driven CTA recipe — see Hero.tsx.\n className=\"rounded-cta bg-cta px-4 py-2 text-[12px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover\"\n >\n {cta.label}\n </Link>\n ) : eyebrow ? (\n <span className=\"text-[10.5px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </span>\n ) : null}\n </div>\n </header>\n )\n}\n","/** Page footer with attribution text on the left and an optional legal-link\n * list (Privacy, Terms) on the right. */\n\nimport Link from 'next/link'\nimport * as schemas from '../schemas'\n\nexport type FooterLink = schemas.SiteFooterLink\n\nexport type FooterProps = schemas.SiteFooterProps\n\nexport function Footer({ text, links }: FooterProps) {\n return (\n <footer className=\"border-t border-line\">\n <div className=\"mx-auto flex max-w-container flex-col items-center gap-4 px-6 py-10 text-center text-[12px] text-ink3 sm:flex-row sm:justify-between sm:px-10 sm:text-left\">\n <p>{text}</p>\n {links && links.length > 0 && (\n <ul className=\"flex flex-wrap items-center justify-center gap-x-5 gap-y-2 sm:justify-end\">\n {links.map((l) => (\n <li key={l.href}>\n <Link\n href={l.href}\n className=\"text-ink3 no-underline transition-colors hover:text-ink\"\n >\n {l.label}\n </Link>\n </li>\n ))}\n </ul>\n )}\n </div>\n </footer>\n )\n}\n","'use client'\n\n/**\n * Reveals on scroll past `threshold` pixels and stays fixed at the top of the\n * viewport. Renders the same `Masthead` component used at the top of the page so\n * the two are visually identical — the scroll variant is `Masthead` inside a\n * fixed-positioned sliding wrapper, never both visible at once.\n */\n\nimport { useEffect, useState } from 'react'\nimport { Masthead, type MastheadProps } from './Masthead'\n\nexport interface ScrollHeaderProps extends MastheadProps {\n /** Pixels of scrollY before the header reveals. Default 480. */\n threshold?: number\n}\n\nexport function ScrollHeader({\n threshold = 480,\n ...mastheadProps\n}: ScrollHeaderProps) {\n const [visible, setVisible] = useState(false)\n\n useEffect(() => {\n let raf = 0\n const update = () => {\n raf = 0\n setVisible(window.scrollY > threshold)\n }\n const onScroll = () => {\n if (raf) return\n raf = requestAnimationFrame(update)\n }\n update()\n window.addEventListener('scroll', onScroll, { passive: true })\n return () => {\n window.removeEventListener('scroll', onScroll)\n if (raf) cancelAnimationFrame(raf)\n }\n }, [threshold])\n\n return (\n <div\n aria-hidden={!visible}\n className={\n 'pointer-events-none fixed inset-x-0 top-0 z-40 transition-[transform,opacity] duration-[220ms] ease-out-quart ' +\n (visible\n ? 'translate-y-0 opacity-100'\n : '-translate-y-full opacity-0')\n }\n >\n <div className=\"pointer-events-auto bg-paper shadow-sheet\">\n <Masthead {...mastheadProps} />\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","Link","ChevronRight","jsx","jsxs","ChevronRight","Link","jsx","jsxs","Link","ChevronRight","Fragment","jsx","jsxs","Link","Fragment","jsx","jsxs","Link","jsx","jsxs","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/HeroSplit.tsx","../../src/components/HeroStacked.tsx","../../src/components/Hero.tsx","../../src/shared/section-eyebrow.tsx","../../src/components/Problem.tsx","../../src/components/WhatYouGet.tsx","../../src/components/HowItWorks.tsx","../../src/components/Defensibility.tsx","../../src/components/Pricing.tsx","../../src/components/Faq.tsx","../../src/components/FinalCta.tsx","../../src/components/Masthead.tsx","../../src/components/MobileNav.tsx","../../src/components/Footer.tsx","../../src/components/ScrollHeader.tsx"],"sourcesContent":["/** Hero variant: split-illustration-right.\n *\n * Text-left + ~360px illustration column on lg+. The Services-dialect hero\n * layout — outcome-led grammar (eyebrow / headline / body / primary /\n * secondary), NOT neo's code-bento hero with `installSnippet`.\n *\n * The illustration column accepts either:\n * 1. A custom `illustration` prop (raw ReactNode, used by the per-service\n * illustration manifest AND by per-product HeroGlyph SVGs)\n * 2. The dialect default `<HeroGlyph />` when no custom one provided\n * 3. Nothing at all when `showGlyph={false}` (text-only hero)\n *\n * Pairs with the `glyphOnMobile` prop to control mobile rendering. */\n\nimport Link from 'next/link'\nimport { ChevronRight } from 'lucide-react'\n\nimport * as schemas from '../schemas'\n\n/** Inline call-to-action. Sourced from the schema — `SiteActionSchema`. */\nexport type HeroAction = schemas.SiteAction\n\n/** Hero component props. Sourced from the schema (`HeroPropsExtendedSchema`).\n * The schema is the canonical shape; this component reads `variant`,\n * `showGlyph`, `glyphOnMobile`, `illustration` from it. */\nexport type HeroProps = schemas.HeroPropsExtended\n\nexport function HeroSplit({\n eyebrow,\n headline,\n body,\n primary,\n secondary,\n showGlyph = true,\n /* INTENTIONALLY UNDEFAULTED — the smart default below uses the\n * undefined state to distinguish \"explicitly unset\" from\n * \"explicitly false\" (the opt-out escape hatch). */\n glyphOnMobile,\n illustration,\n}: HeroProps) {\n /* Smart mobile-visibility default for hero illustrations.\n *\n * - Explicit `glyphOnMobile: true` → show on mobile\n * - Explicit `glyphOnMobile: false` → hide on mobile (opt-out)\n * - Unset + bespoke `illustration` → DEFAULT TRUE (bespoke illustrations\n * ARE the value-prop preview and must show on mobile)\n * - Unset + no illustration (HeroGlyph renders) → DEFAULT FALSE\n */\n const effectiveGlyphOnMobile = glyphOnMobile ?? Boolean(illustration)\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-28 lg:py-32\">\n <div className={showGlyph ? 'lg:grid lg:grid-cols-[minmax(0,1fr)_360px] lg:items-center lg:gap-16' : ''}>\n <div>\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </p>\n <h1 className=\"mt-5 max-w-[18ch] font-display text-display-hero leading-[1.04] tracking-tighter2 text-ink\">\n {headline}\n </h1>\n <p className=\"mt-6 max-w-[58ch] text-[16px] leading-relaxed text-ink2 sm:mt-7 sm:text-[17px]\">\n {body}\n </p>\n <div className=\"mt-10 flex flex-col items-stretch gap-4 sm:flex-row sm:flex-wrap sm:items-center\">\n <PrimaryAction action={primary} />\n {secondary && <SecondaryAction action={secondary} />}\n </div>\n </div>\n {showGlyph && (\n <div\n className={\n effectiveGlyphOnMobile\n ? 'mt-12 lg:mt-0 lg:block'\n : 'hidden lg:block'\n }\n aria-hidden=\"true\"\n >\n {illustration ?? <HeroGlyph />}\n </div>\n )}\n </div>\n </div>\n </section>\n )\n}\n\nexport function PrimaryAction({ action }: { action: HeroAction }) {\n // Theme-driven CTA recipe. `bg-cta / bg-cta-hover / text-cta-fg` resolve via\n // `--cta-*` vars set by `@mdxui/themes`' `themeToCssVars()` per theme.\n const className =\n 'inline-flex w-full items-center justify-center gap-1.5 rounded-cta bg-cta px-5 py-3 text-[14px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover sm:w-auto sm:justify-start'\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {action.label}\n <ChevronRight className=\"h-4 w-4\" strokeWidth={1.7} />\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {action.label}\n <ChevronRight className=\"h-4 w-4\" strokeWidth={1.7} />\n </Link>\n )\n}\n\nexport function SecondaryAction({ action }: { action: HeroAction }) {\n const className =\n 'inline-flex items-center justify-center gap-1.5 text-[13px] font-medium tracking-tightish text-ink2 transition-colors hover:text-accentDeep sm:justify-start'\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {action.label}\n <ChevronRight className=\"h-3.5 w-3.5\" strokeWidth={1.7} />\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {action.label}\n <ChevronRight className=\"h-3.5 w-3.5\" strokeWidth={1.7} />\n </Link>\n )\n}\n\n/** Sparse geometric mark: stack of comp lines, median emphasized in\n * accent teal, range bracket on the right. Default for split-variant\n * heroes that don't pass a custom `illustration`. */\nfunction HeroGlyph() {\n return (\n <svg\n viewBox=\"0 0 360 280\"\n className=\"h-auto w-full\"\n fill=\"none\"\n role=\"presentation\"\n >\n <g\n stroke=\"oklch(var(--ink3) / 0.55)\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n >\n <line x1=\"40\" y1=\"40\" x2=\"180\" y2=\"40\" />\n <line x1=\"60\" y1=\"78\" x2=\"220\" y2=\"78\" />\n <line x1=\"40\" y1=\"172\" x2=\"200\" y2=\"172\" />\n <line x1=\"80\" y1=\"210\" x2=\"260\" y2=\"210\" />\n <line x1=\"60\" y1=\"248\" x2=\"180\" y2=\"248\" />\n </g>\n <line\n x1=\"40\"\n y1=\"135\"\n x2=\"280\"\n y2=\"135\"\n stroke=\"oklch(var(--accent))\"\n strokeWidth=\"2.75\"\n strokeLinecap=\"round\"\n />\n <circle cx=\"280\" cy=\"135\" r=\"4\" fill=\"oklch(var(--accent-deep))\" />\n <g\n stroke=\"oklch(var(--accent-deep) / 0.85)\"\n strokeWidth=\"1\"\n strokeLinecap=\"round\"\n >\n <line x1=\"312\" y1=\"100\" x2=\"312\" y2=\"170\" />\n <line x1=\"306\" y1=\"100\" x2=\"318\" y2=\"100\" />\n <line x1=\"306\" y1=\"170\" x2=\"318\" y2=\"170\" />\n <line x1=\"308\" y1=\"135\" x2=\"316\" y2=\"135\" />\n </g>\n </svg>\n )\n}\n","/** Hero variant: stacked-illustration-below.\n *\n * Text-center top + illustration centered below at ~1080px cap. For services\n * whose hero illustration needs full-bleed scale — code editors, spreadsheets,\n * dashboard mockups — that would feel cramped in the 360px split slot.\n *\n * Unlike HeroSplit, this variant has NO default glyph fallback — the\n * dispatcher in `./Hero.tsx` only routes here when an `illustration` is\n * provided. Services without a bespoke illustration fall back to HeroSplit\n * (which has the `<HeroGlyph />` default mark). */\n\nimport type { HeroProps } from './HeroSplit'\nimport { PrimaryAction, SecondaryAction } from './HeroSplit'\n\nexport function HeroStacked({\n eyebrow,\n headline,\n body,\n primary,\n secondary,\n illustration,\n}: HeroProps) {\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-28 lg:py-32\">\n <div className=\"text-center\">\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </p>\n <h1 className=\"mx-auto mt-5 max-w-[22ch] font-display text-display-hero leading-[1.04] tracking-tighter2 text-ink\">\n {headline}\n </h1>\n <p className=\"mx-auto mt-6 max-w-[60ch] text-[16px] leading-relaxed text-ink2 sm:mt-7 sm:text-[17px]\">\n {body}\n </p>\n <div className=\"mt-10 flex flex-col items-stretch justify-center gap-4 sm:flex-row sm:flex-wrap sm:items-center\">\n <PrimaryAction action={primary} />\n {secondary && <SecondaryAction action={secondary} />}\n </div>\n </div>\n {/* Illustration sits below text, capped at 1080px so it feels\n * substantial without bullying the page. */}\n <div className=\"mx-auto mt-14 max-w-[1080px] sm:mt-16\" aria-hidden=\"true\">\n {illustration}\n </div>\n </div>\n </section>\n )\n}\n","/** ServiceHero — Services-dialect hero composition dispatcher.\n *\n * Routes to the variant render based on `variant` (from the\n * `HeroPropsExtendedSchema`). Default is `'split-illustration-right'`\n * (`HeroSplit`). Adding a future variant = new `Hero<Name>.tsx` file + one\n * additional dispatcher branch here. */\n\nimport { HeroSplit, type HeroAction, type HeroProps } from './HeroSplit'\nimport { HeroStacked } from './HeroStacked'\n\nexport type { HeroAction, HeroProps }\n\nexport function Hero(props: HeroProps) {\n if (props.variant === 'stacked-illustration-below' && props.illustration) {\n return <HeroStacked {...props} />\n }\n return <HeroSplit {...props} />\n}\n\n/** Services-dialect alias — the dialect names this block `ServiceHero`\n * (ADR 0003 §3). Same component as `Hero`. */\nexport { Hero as ServiceHero }\n","/** Small uppercase label that anchors a section heading. */\n\nexport function SectionEyebrow({ children }: { children: React.ReactNode }) {\n return (\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {children}\n </p>\n )\n}\n","/** Three-card \"problem\" section. Each card has a category label, a\n * cost line, a one-line outcome verdict, and a body paragraph. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type ProblemItem = schemas.ProblemItem\n\nexport type ProblemProps = schemas.ProblemProps\n\nexport function Problem({ eyebrow, heading, items }: ProblemProps) {\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className=\"mt-12 grid gap-8 md:grid-cols-3\">\n {items.map((item) => (\n <ProblemCard key={item.label} {...item} />\n ))}\n </div>\n </div>\n </section>\n )\n}\n\nfunction ProblemCard({ label, cost, outcome, body }: ProblemItem) {\n return (\n <article>\n <p className=\"text-[10.5px] uppercase tracking-[0.16em] text-ink3\">\n {label}\n </p>\n <p className=\"mt-3 font-display text-[24px] leading-tight tracking-tightish text-ink\">\n {cost}\n </p>\n <p className=\"mt-4 text-body-sm font-medium leading-snug tracking-tightish text-accentDeep\">\n {outcome}\n </p>\n <p className=\"mt-3 text-body-sm leading-relaxed text-ink2\">{body}</p>\n </article>\n )\n}\n","/** \"What's in the report\" — numbered grid listing each section. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type WhatYouGetItem = schemas.WhatYouGetItem\n\nexport type WhatYouGetProps = schemas.WhatYouGetProps\n\nexport function WhatYouGet({ eyebrow, heading, sections }: WhatYouGetProps) {\n // Empty-array graceful handling — skip the section entirely rather\n // than render dangling chrome (eyebrow + heading) above an empty grid.\n if (sections.length === 0) return null\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <ul className=\"mt-12 grid gap-x-8 gap-y-7 md:grid-cols-2 lg:grid-cols-3\">\n {sections.map((s) => (\n <li key={s.n}>\n <p className=\"font-display text-[14px] tracking-tightish text-ink3\">\n {s.n}\n </p>\n <p className=\"mt-1.5 text-[15px] font-medium tracking-tightish text-ink\">\n {s.title}\n </p>\n <p className=\"mt-1.5 text-[13.5px] leading-relaxed text-ink2\">\n {s.body}\n </p>\n </li>\n ))}\n </ul>\n </div>\n </section>\n )\n}\n","/** Three-column \"how it works\" strip with large numbered eyebrows.\n *\n * Optional per-step illustration row above the number — opt in by passing\n * `stepIllustrations` (a `ComponentType[]` matching `steps.length`). When the\n * lengths don't match (or the prop is absent), the text-only layout renders\n * unchanged. Opt-in only, never degrade. */\n\nimport type { ComponentType } from 'react'\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type HowItWorksStep = schemas.HowItWorksStep\n\n/** HowItWorks component props. Sourced from `HowItWorksPropsSchema`, which\n * includes the opt-in `stepIllustrations` field. */\nexport type HowItWorksProps = schemas.HowItWorksProps\n\nexport function HowItWorks({\n eyebrow,\n heading,\n steps,\n stepIllustrations,\n}: HowItWorksProps) {\n // Empty-array graceful handling — skip the section entirely.\n if (steps.length === 0) return null\n const hasIllustrations =\n stepIllustrations !== undefined &&\n stepIllustrations.length === steps.length\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <ol\n itemScope\n itemType=\"https://schema.org/HowTo\"\n className=\"mt-12 grid gap-10 md:grid-cols-3\"\n >\n {steps.map((s, i) => (\n <Step\n key={s.n}\n {...s}\n illustration={hasIllustrations ? stepIllustrations![i] : undefined}\n />\n ))}\n </ol>\n </div>\n </section>\n )\n}\n\nfunction Step({\n n,\n title,\n body,\n illustration: Illustration,\n}: HowItWorksStep & { illustration?: ComponentType }) {\n /* When step illustrations are present, the parent grid stretches all <li>s to\n * the height of the tallest column; the flex-col + `mt-auto` on the text block\n * pushes numbers / titles / bodies to a shared baseline. Without an\n * illustration, content flows naturally from the top (text-only layout). */\n return (\n <li\n itemScope\n itemType=\"https://schema.org/HowToStep\"\n className={Illustration ? 'flex flex-col' : undefined}\n >\n {Illustration && (\n <div className=\"mb-6 w-full lg:max-w-[320px]\">\n <Illustration />\n </div>\n )}\n <div className={Illustration ? 'mt-auto' : undefined}>\n <p className=\"font-display text-[36px] leading-none tracking-tighter2 text-ink3/60\">\n {n}\n </p>\n <p className=\"mt-4 font-display text-[20px] leading-tight tracking-tightish text-ink\">\n {title}\n </p>\n <p className=\"mt-3 text-body-sm leading-relaxed text-ink2\">{body}</p>\n </div>\n </li>\n )\n}\n","/** Two-column \"what it is / what it isn't\" block with a closing caveat\n * paragraph — THE Services signature block (ADR 0003 §3). Used to set scope\n * expectations on a service page. No neo equivalent. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type DefensibilityColumn = schemas.DefensibilityColumnFromSchema\n\nexport type DefensibilityProps = schemas.DefensibilityPropsFromSchema\n\nexport function Defensibility({\n eyebrow,\n heading,\n columns,\n caveat,\n}: DefensibilityProps) {\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className=\"mt-10 grid gap-10 lg:grid-cols-2\">\n {columns.map((col) => (\n <Column key={col.heading} {...col} />\n ))}\n </div>\n {caveat && (\n <p className=\"mt-12 max-w-[68ch] text-body-xs leading-relaxed text-ink3\">\n {caveat}\n </p>\n )}\n </div>\n </section>\n )\n}\n\nfunction Column({ heading, bullets }: DefensibilityColumn) {\n return (\n <div>\n <h3 className=\"font-display text-[18px] leading-tight tracking-tightish text-ink\">\n {heading}\n </h3>\n <ul className=\"mt-4 space-y-3 text-body-sm leading-relaxed text-ink2\">\n {bullets.map((b, i) => (\n <li key={i} className=\"flex gap-2.5\">\n <span className=\"mt-2 h-1 w-1 shrink-0 rounded-full bg-ink3\" />\n <span>{b}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n","/** ReportPricing — the Services-dialect pricing section. Two variants on the\n * discriminated `Pricing` union:\n *\n * - `kind: 'tiered'` — renders 1, 2, or 3 tier cards. CTAs flex to the bottom\n * of each card so heights stay symmetric.\n * - `kind: 'unit'` — renders a single per-unit price (\"$3 per transcript\"\n * style) with billing cadence. No tier chrome, no per-tier CTA.\n *\n * Services grammar: \"per report, no subscription\" — NOT neo's subscription\n * tier pricing. The default price suffix is \"/ report\". */\n\nimport Link from 'next/link'\nimport { ChevronRight } from 'lucide-react'\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type PriceTier = schemas.PriceTier\n\n/** Legacy tiered-only props shape (omits `kind` + `currency`). The component\n * accepts EITHER this OR the wider discriminated `Pricing` union. */\nexport type PricingProps = schemas.PricingPropsExtended\n\n/** The canonical discriminated `Pricing` union (carries `kind: 'unit'`). */\nexport type PricingData = schemas.Pricing\n\n/** Component-level accepted props: the legacy tiered-only shape OR the\n * discriminated `Pricing` union. The component branches on `kind` internally. */\nexport type PricingComponentProps = PricingProps | PricingData\n\nconst GRID_COLS: Record<1 | 2 | 3, string> = {\n 1: 'max-w-[420px]',\n 2: 'max-w-[820px] md:grid-cols-2',\n 3: 'max-w-container md:grid-cols-3',\n}\n\nexport function Pricing(props: PricingComponentProps) {\n if ('kind' in props && props.kind === 'unit') {\n return <UnitPricing {...props} />\n }\n // Both legacy `PricingProps` (no `kind`) and `PricingTiered`\n // (`kind: 'tiered'`) hit this branch — both carry `tiers[]`.\n return <TieredPricing {...(props as TieredRenderProps)} />\n}\n\ntype TieredRenderProps = {\n eyebrow: string\n heading: string\n tiers: readonly PriceTier[]\n footnote?: string\n}\n\nfunction TieredPricing({\n eyebrow,\n heading,\n tiers,\n footnote,\n}: TieredRenderProps) {\n // Empty-array graceful handling — skip the section entirely.\n if (tiers.length === 0) return null\n const count = (\n tiers.length === 1 || tiers.length === 2 ? tiers.length : 3\n ) as 1 | 2 | 3\n return (\n <section className=\"border-b border-line bg-surface\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className={`mt-12 mx-auto grid gap-6 ${GRID_COLS[count]}`}>\n {tiers.map((t) => (\n <PriceCard key={t.tier} {...t} />\n ))}\n </div>\n {footnote && (\n <p className=\"mt-10 max-w-[64ch] text-[13px] text-ink3\">{footnote}</p>\n )}\n </div>\n </section>\n )\n}\n\n/** Format a per-unit price using `Intl.NumberFormat`. Trims trailing\n * zero-cents for clean reading (\"$3\" not \"$3.00\"). */\nfunction formatPerUnit(perUnit: number, currency: 'usd' | 'eur' | 'gbp'): string {\n const isWhole = Number.isInteger(perUnit)\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: isWhole ? 0 : 2,\n maximumFractionDigits: 2,\n }).format(perUnit)\n}\n\nfunction UnitPricing({\n eyebrow,\n heading,\n footnote,\n currency,\n perUnit,\n billingCadence,\n}: Extract<PricingData, { kind: 'unit' }>) {\n const formatted = formatPerUnit(perUnit, currency)\n return (\n <section className=\"border-b border-line bg-surface\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[22ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <div className=\"mt-12 mx-auto max-w-[420px]\">\n <article\n itemScope\n itemType=\"https://schema.org/Offer\"\n data-pricing-kind=\"unit\"\n className=\"flex flex-col rounded-card border border-line bg-paper p-7\"\n >\n <p className=\"text-[10.5px] uppercase tracking-[0.16em] text-ink3\">\n Per call\n </p>\n <p className=\"mt-3 flex items-baseline gap-2\">\n <span className=\"font-display text-[40px] leading-none tracking-tighter2 text-ink\">\n {formatted}\n </span>\n <span className=\"text-[12px] text-ink3\">{billingCadence}</span>\n </p>\n </article>\n </div>\n {footnote && (\n <p className=\"mt-10 max-w-[64ch] text-[13px] text-ink3\">{footnote}</p>\n )}\n </div>\n </section>\n )\n}\n\n/** Split a price string like \"$0.10/VIN\" into (\"$0.10\", \"/VIN\"). */\nfunction splitPrice(price: string): { core: string; suffix: string | null } {\n const i = price.indexOf('/')\n if (i === -1) return { core: price, suffix: null }\n return { core: price.slice(0, i).trim(), suffix: price.slice(i) }\n}\n\n/** Resolve the suffix shown after the price. Explicit per-tier `priceSuffix`\n * wins; otherwise an auto-extracted \"/X\"; otherwise the dialect default\n * \"/ report\" (the \"per report, no subscription\" Services grammar). */\nfunction resolvePriceSuffix(\n price: string,\n override: string | undefined,\n): string {\n if (override !== undefined) return override\n const { suffix } = splitPrice(price)\n return suffix ?? '/ report'\n}\n\nfunction PriceCard({\n tierKey,\n tier,\n price,\n priceSuffix,\n audience,\n features,\n featured,\n cta,\n}: PriceTier) {\n const isMailto = cta.href.startsWith('mailto:')\n const { core } = splitPrice(price)\n const suffix = resolvePriceSuffix(price, priceSuffix)\n return (\n <article\n itemScope\n itemType=\"https://schema.org/Offer\"\n data-tier-key={tierKey}\n className={\n 'flex flex-col rounded-card border bg-paper p-7 ' +\n (featured ? 'border-accent shadow-lift' : 'border-line')\n }\n >\n <p className=\"text-[10.5px] uppercase tracking-[0.16em] text-ink3\">\n {tier}\n </p>\n <p className=\"mt-3 flex items-baseline gap-2\">\n <span className=\"font-display text-[40px] leading-none tracking-tighter2 text-ink\">\n {core}\n </span>\n {suffix && <span className=\"text-[12px] text-ink3\">{suffix}</span>}\n </p>\n <p className=\"mt-2 text-[13px] text-ink2\">{audience}</p>\n <ul className=\"mt-6 flex-1 space-y-2.5 text-[13.5px] text-ink2\">\n {features.map((f) => (\n <li key={f} className=\"flex gap-2.5\">\n <span\n className={\n 'mt-2 h-1 w-1 shrink-0 rounded-full ' +\n (featured ? 'bg-accent' : 'bg-ink3')\n }\n />\n <span>{f}</span>\n </li>\n ))}\n </ul>\n <PriceCardCta\n label={cta.label}\n href={cta.href}\n featured={featured}\n external={isMailto}\n />\n </article>\n )\n}\n\nfunction PriceCardCta({\n label,\n href,\n featured,\n external,\n}: {\n label: string\n href: string\n featured?: boolean\n external?: boolean\n}) {\n const baseClass =\n 'mt-7 inline-flex w-full items-center justify-center gap-1.5 rounded-cta px-5 py-2.5 text-[13.5px] font-medium tracking-tightish transition-colors'\n // Theme-driven CTA recipe for the featured tier. The unfeatured (outlined)\n // variant stays ink-typed as a quiet secondary action.\n const variantClass = featured\n ? 'bg-cta text-cta-fg hover:bg-cta-hover'\n : 'border border-line2 bg-paper text-ink hover:border-ink hover:text-ink'\n const className = `${baseClass} ${variantClass}`\n const body = (\n <>\n {label}\n <ChevronRight className=\"h-3.5 w-3.5\" strokeWidth={1.7} />\n </>\n )\n if (external) {\n return (\n <a className={className} href={href} data-action=\"buy\">\n {body}\n </a>\n )\n }\n return (\n <Link className={className} href={href} data-action=\"buy\">\n {body}\n </Link>\n )\n}\n\n/** Services-dialect alias — the dialect names this block `ReportPricing`\n * (ADR 0003 §3: \"per report, no subscription\"). Same component as `Pricing`. */\nexport { Pricing as ReportPricing }\n","/** Two-column FAQ grid. Each item is a question (display serif) and an\n * answer paragraph (sans). Uses Services' short-key q/a convention. */\n\nimport { SectionEyebrow } from '../shared/section-eyebrow'\nimport * as schemas from '../schemas'\n\nexport type FaqItem = schemas.FaqItem\n\nexport type FaqProps = schemas.FaqPropsExtended\n\nexport function Faq({ eyebrow, heading, items }: FaqProps) {\n // Empty-array graceful handling — skip the section entirely.\n if (items.length === 0) return null\n return (\n <section className=\"border-b border-line\">\n <div className=\"mx-auto max-w-container px-6 py-16 sm:px-10 sm:py-24\">\n <SectionEyebrow>{eyebrow}</SectionEyebrow>\n <h2 className=\"mt-3 max-w-[20ch] font-display text-display-section leading-[1.08] tracking-tightish text-ink\">\n {heading}\n </h2>\n <dl className=\"mt-12 grid gap-x-12 gap-y-10 md:grid-cols-2\">\n {items.map((f) => (\n <div key={f.q} itemScope itemType=\"https://schema.org/Question\">\n <dt className=\"font-display text-body leading-snug tracking-tightish text-ink\">\n {f.q}\n </dt>\n <dd className=\"mt-2 text-body-sm leading-relaxed text-ink2\">\n {f.a}\n </dd>\n </div>\n ))}\n </dl>\n </div>\n </section>\n )\n}\n","/** Closing call-to-action with a centered headline and one or two buttons.\n * Primary is always rendered; secondary is optional and rendered as a quieter\n * link beside the primary pill. */\n\nimport Link from 'next/link'\nimport { ChevronRight } from 'lucide-react'\nimport * as schemas from '../schemas'\n\nexport type FinalCtaProps = schemas.FinalCtaProps\n\ntype CtaAction = schemas.SiteAction\n\nexport function FinalCta({\n eyebrow,\n headline,\n primary,\n secondary,\n}: FinalCtaProps) {\n return (\n <section>\n <div className=\"mx-auto max-w-container px-6 py-20 text-center sm:px-10 sm:py-32\">\n <p className=\"text-[11px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </p>\n <h2 className=\"mx-auto mt-4 max-w-[22ch] font-display text-[36px] leading-[1.04] tracking-tighter2 text-ink sm:text-[52px]\">\n {headline}\n </h2>\n <div className=\"mt-10 flex flex-col items-stretch gap-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-center\">\n <PrimaryButton action={primary} />\n {secondary && <SecondaryLink action={secondary} />}\n </div>\n </div>\n </section>\n )\n}\n\nfunction PrimaryButton({ action }: { action: CtaAction }) {\n // Theme-driven CTA recipe — see Hero.tsx for context.\n const className =\n 'inline-flex w-full items-center justify-center gap-1.5 rounded-cta bg-cta px-6 py-3 text-[14px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover sm:w-auto'\n const body = (\n <>\n {action.label}\n <ChevronRight className=\"h-4 w-4\" strokeWidth={1.7} />\n </>\n )\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {body}\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {body}\n </Link>\n )\n}\n\nfunction SecondaryLink({ action }: { action: CtaAction }) {\n const className =\n 'inline-flex items-center justify-center gap-1.5 text-[13px] font-medium tracking-tightish text-ink3 transition-colors hover:text-ink'\n if (action.external) {\n return (\n <a\n href={action.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={className}\n >\n {action.label}\n </a>\n )\n }\n return (\n <Link href={action.href} className={className}>\n {action.label}\n </Link>\n )\n}\n","/** Static masthead at the top of a service page. Pairs with ScrollHeader,\n * which reveals on scroll once this one has scrolled away.\n *\n * Three zones (carriage parity, origin/master a8700e6 + fda6fb6): brand (left,\n * with an optional `brand.logo` to the LEFT of the wordmark), an optional\n * centered nav of 3–5 page `links` (middle, `md`+ only), and a right-side slot\n * that is either a primary CTA pill (`cta`) or a small uppercase status label\n * (`eyebrow`) — passing both lets `cta` win. Below `md` the centered nav\n * collapses into a hamburger (`MobileNav`) rendered to the right of the CTA,\n * which opens a dropdown overlay carrying the same links. Use `narrow` when the\n * page below uses the 900px container instead of the default 1100px. */\n\nimport Link from 'next/link'\nimport * as schemas from '../schemas'\nimport { MobileNav } from './MobileNav'\n\nexport type MastheadProps = schemas.MastheadProps\n\nexport function Masthead({ brand, cta, links, eyebrow, narrow }: MastheadProps) {\n const hasNav = Boolean(links && links.length > 0)\n\n return (\n <header className=\"border-b border-line\">\n <div\n className={\n 'relative mx-auto flex items-center justify-between gap-4 px-6 py-5 sm:px-10 ' +\n (narrow ? 'max-w-[900px]' : 'max-w-container')\n }\n >\n <div className=\"flex items-center gap-3\">\n <Link\n href={brand.href}\n className=\"inline-flex items-center gap-2 font-display text-[18px] tracking-tightish text-ink\"\n >\n {brand.logo && (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={brand.logo.src} alt={brand.logo.alt} className=\"h-6 w-auto\" />\n )}\n {brand.primary}\n </Link>\n {brand.secondary && (\n <>\n <span className=\"hidden h-4 w-px bg-line2 sm:inline-block\" />\n <span className=\"hidden text-[11px] uppercase tracking-[0.18em] text-ink3 sm:inline\">\n {brand.secondary}\n </span>\n </>\n )}\n </div>\n\n {hasNav && (\n <nav className=\"absolute left-1/2 hidden -translate-x-1/2 items-center gap-7 md:flex\">\n {links!.map((l) => (\n <Link\n key={l.href}\n href={l.href}\n className=\"text-[13px] tracking-tightish text-ink2 transition-colors hover:text-ink\"\n >\n {l.label}\n </Link>\n ))}\n </nav>\n )}\n\n <div className=\"flex items-center gap-2\">\n {cta ? (\n <Link\n href={cta.href}\n // Theme-driven CTA recipe — see Hero.tsx.\n className=\"rounded-cta bg-cta px-4 py-2 text-[12px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover\"\n >\n {cta.label}\n </Link>\n ) : eyebrow ? (\n <span className=\"text-[10.5px] uppercase tracking-[0.18em] text-ink3\">\n {eyebrow}\n </span>\n ) : null}\n {hasNav && (\n <MobileNav links={links!} cta={cta} brand={brand} narrow={narrow} />\n )}\n </div>\n </div>\n </header>\n )\n}\n","'use client'\n\n/** Mobile navigation: a hamburger trigger + a dropdown overlay panel.\n * Rendered by `Masthead` only when page `links` are present and only below the\n * `md` breakpoint (the centered desktop nav takes over at `md`). Masthead\n * itself stays a Server Component; this client island owns the open/close\n * interactivity.\n *\n * The panel drops from the top over a plain dimmed scrim (no blur). It closes\n * on link tap, backdrop click, its own close button, or Escape, and locks body\n * scroll while open. Theme-driven (paper / ink / line / cta tokens from the\n * Services envelope); motion reuses the `ease-out-quart` / 220ms language and\n * collapses under prefers-reduced-motion via the host globals.\n *\n * Ported verbatim from carriage `src/chassis/components/site/MobileNav.tsx`\n * (origin/master a8700e6) — only the `NavLink` import (now from the schema\n * contract layer) differs. */\n\nimport { useEffect, useState } from 'react'\nimport Link from 'next/link'\nimport { Menu, X } from 'lucide-react'\n\nimport type { NavLink } from '../schemas'\n\nexport interface MobileNavProps {\n links: NavLink[]\n cta?: { label: string; href: string }\n brand: { primary: string; secondary?: string; href: string }\n narrow?: boolean\n}\n\nexport function MobileNav({ links, cta, brand, narrow }: MobileNavProps) {\n const [open, setOpen] = useState(false)\n const [scrollbarWidth, setScrollbarWidth] = useState(0)\n\n useEffect(() => {\n if (!open) return\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n // Reserve the page scrollbar's width as body padding while scroll is\n // locked. Without this, `overflow: hidden` removes the scrollbar, the\n // content area widens, and the `mx-auto`-centered masthead recenters —\n // visibly shoving the right-side group over as the menu opens. Pinning the\n // width keeps the layout perfectly still.\n const prevOverflow = document.body.style.overflow\n const prevPaddingRight = document.body.style.paddingRight\n document.body.style.overflow = 'hidden'\n if (scrollbarWidth > 0) {\n document.body.style.paddingRight = `${scrollbarWidth}px`\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = prevOverflow\n document.body.style.paddingRight = prevPaddingRight\n window.removeEventListener('keydown', onKey)\n }\n }, [open, scrollbarWidth])\n\n // Measure the scrollbar BEFORE locking scroll. Batched with `setOpen` so the\n // overlay's first paint already carries the matching padding — its inner row\n // stays aligned with the (now padded) masthead row.\n const openMenu = () => {\n setScrollbarWidth(window.innerWidth - document.documentElement.clientWidth)\n setOpen(true)\n }\n\n const row =\n 'mx-auto px-6 sm:px-10 ' + (narrow ? 'max-w-[900px]' : 'max-w-container')\n\n return (\n <div className=\"md:hidden\">\n <button\n type=\"button\"\n aria-label=\"Open menu\"\n aria-expanded={open}\n onClick={openMenu}\n className=\"flex h-9 w-9 items-center justify-center rounded-cta text-ink transition-colors hover:bg-surface\"\n >\n <Menu className=\"h-5 w-5\" strokeWidth={1.75} aria-hidden=\"true\" />\n </button>\n\n <div\n aria-hidden=\"true\"\n onClick={() => setOpen(false)}\n className={\n 'fixed inset-0 z-50 bg-ink/40 transition-opacity duration-[220ms] ease-out-quart ' +\n (open ? 'opacity-100' : 'pointer-events-none opacity-0')\n }\n />\n\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Site navigation\"\n // Same scrollbar-width reservation as the body, so this fixed\n // (full-viewport) panel's centered row lines up with the masthead.\n style={scrollbarWidth ? { paddingRight: scrollbarWidth } : undefined}\n className={\n 'fixed inset-x-0 top-0 z-50 origin-top bg-paper shadow-sheet transition-[transform,opacity] duration-[220ms] ease-out-quart ' +\n (open\n ? 'translate-y-0 opacity-100'\n : 'pointer-events-none -translate-y-3 opacity-0')\n }\n >\n <div\n className={`flex items-center justify-between gap-4 border-b border-line py-5 ${row}`}\n >\n <Link\n href={brand.href}\n onClick={() => setOpen(false)}\n className=\"font-display text-[18px] tracking-tightish text-ink\"\n >\n {brand.primary}\n </Link>\n <button\n type=\"button\"\n aria-label=\"Close menu\"\n onClick={() => setOpen(false)}\n className=\"flex h-9 w-9 items-center justify-center rounded-cta text-ink transition-colors hover:bg-surface\"\n >\n <X className=\"h-5 w-5\" strokeWidth={1.75} aria-hidden=\"true\" />\n </button>\n </div>\n\n <nav className={`flex flex-col py-2 ${row}`}>\n {links.map((l) => (\n <Link\n key={l.href}\n href={l.href}\n onClick={() => setOpen(false)}\n className=\"border-b border-line py-4 font-display text-[20px] tracking-tightish text-ink transition-colors last:border-b-0 hover:text-accent\"\n >\n {l.label}\n </Link>\n ))}\n </nav>\n\n {cta && (\n <div className={`pb-6 pt-3 ${row}`}>\n <Link\n href={cta.href}\n onClick={() => setOpen(false)}\n className=\"block rounded-cta bg-cta px-4 py-3 text-center text-[13px] font-medium tracking-tightish text-cta-fg transition-colors hover:bg-cta-hover\"\n >\n {cta.label}\n </Link>\n </div>\n )}\n </div>\n </div>\n )\n}\n","/** Page footer with attribution text on the left and an optional legal-link\n * list (Privacy, Terms) on the right. */\n\nimport Link from 'next/link'\nimport * as schemas from '../schemas'\n\nexport type FooterLink = schemas.SiteFooterLink\n\nexport type FooterProps = schemas.SiteFooterProps\n\nexport function Footer({ text, links }: FooterProps) {\n return (\n <footer className=\"border-t border-line\">\n <div className=\"mx-auto flex max-w-container flex-col items-center gap-4 px-6 py-10 text-center text-[12px] text-ink3 sm:flex-row sm:justify-between sm:px-10 sm:text-left\">\n <p>{text}</p>\n {links && links.length > 0 && (\n <ul className=\"flex flex-wrap items-center justify-center gap-x-5 gap-y-2 sm:justify-end\">\n {links.map((l) => (\n <li key={l.href}>\n <Link\n href={l.href}\n className=\"text-ink3 no-underline transition-colors hover:text-ink\"\n >\n {l.label}\n </Link>\n </li>\n ))}\n </ul>\n )}\n </div>\n </footer>\n )\n}\n","'use client'\n\n/**\n * Reveals on scroll past `threshold` pixels and stays fixed at the top of the\n * viewport. Renders the same `Masthead` component used at the top of the page so\n * the two are visually identical — the scroll variant is `Masthead` inside a\n * fixed-positioned sliding wrapper, never both visible at once.\n */\n\nimport { useEffect, useState } from 'react'\nimport { Masthead, type MastheadProps } from './Masthead'\n\nexport interface ScrollHeaderProps extends MastheadProps {\n /** Pixels of scrollY before the header reveals. Default 480. */\n threshold?: number\n}\n\nexport function ScrollHeader({\n threshold = 480,\n ...mastheadProps\n}: ScrollHeaderProps) {\n const [visible, setVisible] = useState(false)\n\n useEffect(() => {\n let raf = 0\n const update = () => {\n raf = 0\n setVisible(window.scrollY > threshold)\n }\n const onScroll = () => {\n if (raf) return\n raf = requestAnimationFrame(update)\n }\n update()\n window.addEventListener('scroll', onScroll, { passive: true })\n return () => {\n window.removeEventListener('scroll', onScroll)\n if (raf) cancelAnimationFrame(raf)\n }\n }, [threshold])\n\n return (\n <div\n aria-hidden={!visible}\n className={\n 'pointer-events-none fixed inset-x-0 top-0 z-40 transition-[transform,opacity] duration-[220ms] ease-out-quart ' +\n (visible\n ? 'translate-y-0 opacity-100'\n : '-translate-y-full opacity-0')\n }\n >\n <div className=\"pointer-events-auto bg-paper shadow-sheet\">\n <Masthead {...mastheadProps} />\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","Link","ChevronRight","jsx","jsxs","ChevronRight","Link","jsx","jsxs","Link","ChevronRight","Fragment","jsx","jsxs","Link","Link","jsx","jsxs","Fragment","jsx","jsxs","Link","Link","jsx","jsxs","useEffect","useState","jsx","useState","useEffect"]}
|