@orangecheck/app-design 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/chrome.d.mts +11 -5
  2. package/dist/chrome.d.ts +11 -5
  3. package/dist/chrome.js +985 -952
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/chrome.mjs +986 -954
  6. package/dist/chrome.mjs.map +1 -1
  7. package/dist/code.js +3 -1
  8. package/dist/code.js.map +1 -1
  9. package/dist/code.mjs +3 -1
  10. package/dist/code.mjs.map +1 -1
  11. package/dist/components.d.mts +7 -5
  12. package/dist/components.d.ts +7 -5
  13. package/dist/components.js +697 -617
  14. package/dist/components.js.map +1 -1
  15. package/dist/components.mjs +697 -617
  16. package/dist/components.mjs.map +1 -1
  17. package/dist/{docs-Dxg4Tp_q.d.ts → docs-ByUx4t-D.d.ts} +19 -4
  18. package/dist/{docs-wJBfLS08.d.mts → docs-CFE5mU_6.d.mts} +19 -4
  19. package/dist/index.d.mts +3 -3
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +1665 -1519
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +1665 -1520
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/mdx.d.mts +6 -2
  26. package/dist/mdx.d.ts +6 -2
  27. package/dist/mdx.js +175 -76
  28. package/dist/mdx.js.map +1 -1
  29. package/dist/mdx.mjs +176 -77
  30. package/dist/mdx.mjs.map +1 -1
  31. package/dist/primitives.d.mts +3 -3
  32. package/dist/primitives.d.ts +3 -3
  33. package/dist/primitives.js +10 -1
  34. package/dist/primitives.js.map +1 -1
  35. package/dist/primitives.mjs +10 -1
  36. package/dist/primitives.mjs.map +1 -1
  37. package/dist/session.d.mts +2 -2
  38. package/dist/session.d.ts +2 -2
  39. package/dist/session.js +1 -1
  40. package/dist/session.js.map +1 -1
  41. package/dist/session.mjs +1 -1
  42. package/dist/session.mjs.map +1 -1
  43. package/dist/styles/swagger.css +252 -0
  44. package/dist/styles/tokens.css +2 -0
  45. package/dist/{tool-shell-zncroOEQ.d.mts → tool-shell-D8Q8XX11.d.mts} +3 -2
  46. package/dist/{tool-shell-Be4Q0cNN.d.ts → tool-shell-gmlj47Ie.d.ts} +3 -2
  47. package/package.json +3 -2
package/dist/chrome.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { X, ChevronDown, Menu, ChevronRight, PanelLeft, Sun, Moon, SunMoon, CircleUser, LogOut, ArrowUpRight } from 'lucide-react';
2
- import Link5 from 'next/link';
3
- import { forwardRef, createContext, useState, useContext, useMemo, useEffect, useRef, useId, useSyncExternalStore, createElement } from 'react';
1
+ import { X, ChevronDown, Menu, ChevronRight, Sun, Moon, SunMoon, PanelLeft, CircleUser, LogOut, ArrowUpRight } from 'lucide-react';
2
+ import Link from 'next/link';
3
+ import { forwardRef, createContext, useContext, useState, useMemo, useEffect, useRef, useId, useSyncExternalStore, createElement } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { extendTailwindMerge } from 'tailwind-merge';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -8,12 +8,12 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
8
8
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
9
9
  import * as PopoverPrimitive from '@radix-ui/react-popover';
10
10
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
11
+ import { useTheme } from 'next-themes';
11
12
  import { cva } from 'class-variance-authority';
12
13
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
13
14
  import 'sonner';
14
15
  import { Slot } from '@radix-ui/react-slot';
15
16
  import { useRouter } from 'next/compat/router';
16
- import { useTheme } from 'next-themes';
17
17
 
18
18
  var merge = extendTailwindMerge({
19
19
  extend: {
@@ -407,6 +407,17 @@ var DropdownMenuLabel = forwardRef(function DropdownMenuLabel2({ className, ...p
407
407
  var DropdownMenuSeparator = forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
408
408
  return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Separator, { ref, className: cn("my-1.5 h-px bg-border", className), ...props });
409
409
  });
410
+ function sharedContext(name, initial) {
411
+ const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
412
+ const store = globalThis;
413
+ return store[key] ?? (store[key] = createContext(initial));
414
+ }
415
+
416
+ // src/lib/shell-context.ts
417
+ var ShellContext = sharedContext("shell-place", {});
418
+ function useShellPlace() {
419
+ return useContext(ShellContext);
420
+ }
410
421
  var GOOD_DOT = "border-border bg-card text-foreground before:size-1.5 before:shrink-0 before:rounded-full before:bg-success before:content-['']";
411
422
  var badgeVariants = cva(
412
423
  "inline-flex h-6 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 text-[0.8125rem] font-medium leading-none",
@@ -533,1044 +544,1064 @@ function FamilyMenu({ current, className }) {
533
544
  )
534
545
  ] });
535
546
  }
536
- function NavLink({
537
- item,
538
- className,
539
- onNavigate,
540
- line = false
541
- }) {
542
- const cls = cn(
543
- "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
544
- item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
545
- line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
546
- line && item.active && "after:bg-foreground",
547
- className
548
- );
549
- if (item.external) {
550
- return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
551
- }
552
- return /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
553
- }
554
- function NavRow({ item, onNavigate }) {
555
- const body = /* @__PURE__ */ jsxs(Fragment, { children: [
556
- /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
557
- item.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
558
- ] });
559
- const cls = cn(
560
- "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
561
- item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
562
- );
563
- return item.external ? /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
564
- }
565
- var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
566
- function NavDropdown({ item }) {
567
- const [open, setOpen] = useState(false);
568
- const active = item.active || item.children?.some((c) => c.active);
569
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
570
- /* @__PURE__ */ jsxs(
571
- PopoverTrigger,
547
+ function SideNav({ groups, onNavigate }) {
548
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
549
+ g.label ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
550
+ g.items.map((it) => /* @__PURE__ */ jsxs(
551
+ Link,
572
552
  {
553
+ href: it.href,
554
+ onClick: onNavigate,
555
+ "aria-current": it.active ? "page" : void 0,
573
556
  className: cn(
574
- "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors md:max-lg:pl-2.5 md:max-lg:pr-2",
575
- active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
557
+ "flex h-9 items-center gap-3 rounded-xl px-3 text-[0.9375rem] transition-colors",
558
+ "[&_svg]:size-[1.0625rem] [&_svg]:shrink-0",
559
+ it.active ? "bg-card text-foreground shadow-sm ring-1 ring-border [&_svg]:text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
576
560
  ),
577
561
  children: [
578
- item.label,
579
- /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
562
+ it.icon,
563
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: it.label }),
564
+ it.badge ? /* @__PURE__ */ jsx("span", { className: "shrink-0", children: it.badge }) : null
580
565
  ]
581
- }
582
- ),
583
- /* @__PURE__ */ jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
584
- /* @__PURE__ */ jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
585
- /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsx(
586
- NavLink,
587
- {
588
- item: { ...item, label: seeAll(item), children: void 0 },
589
- className: "block rounded-xl px-2 py-2 text-[0.875rem]",
590
- onNavigate: () => setOpen(false)
591
- }
592
- ) })
593
- ] })
594
- ] });
566
+ },
567
+ it.href
568
+ ))
569
+ ] }, g.label ?? gi)) });
595
570
  }
596
- function SiteHeader({
597
- home = "/",
598
- brand,
599
- product,
600
- family,
601
- nav = [],
602
- search,
603
- actions,
604
- variant = "site",
605
- navOnPhone = true,
606
- menu: menuExtra,
607
- className
571
+ function SectionSwitch({
572
+ sections,
573
+ current,
574
+ onNavigate
608
575
  }) {
609
- const [open, setOpen] = useState(false);
610
- const tool = variant === "tool";
611
- const size = tool ? 24 : 28;
612
- const current = typeof family === "string" ? family : void 0;
613
- const phoneNav = navOnPhone ? nav : [];
614
- const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
615
- const brandNode = brand ?? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center", children: [
616
- /* @__PURE__ */ jsx(Lockup, { size }),
617
- product ? /* @__PURE__ */ jsxs(Fragment, { children: [
618
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
619
- /* @__PURE__ */ jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
620
- ] }) : null
621
- ] });
622
- const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
623
- (n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : (
624
- // Between md and lg the family menu and the actions share the row: tighter.
625
- /* @__PURE__ */ jsx(NavLink, { item: n, line: tool, className: tool ? void 0 : "md:max-lg:px-2.5" }, n.href)
626
- )
627
- ) }) : null;
576
+ const cols = sections.length <= 3 ? sections.length : 2;
628
577
  return /* @__PURE__ */ jsx(
629
- "header",
578
+ "nav",
630
579
  {
631
- className: cn(
632
- "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
633
- tool ? "border-border" : "border-transparent",
634
- className
635
- ),
636
- children: /* @__PURE__ */ jsxs(
580
+ "aria-label": "Sections",
581
+ className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
582
+ style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
583
+ children: sections.map((sec) => {
584
+ const on = sec.id === current.id;
585
+ return /* @__PURE__ */ jsx(
586
+ Link,
587
+ {
588
+ href: sec.href,
589
+ onClick: onNavigate,
590
+ "aria-current": on ? "true" : void 0,
591
+ className: cn(
592
+ "flex h-8 min-w-0 items-center justify-center rounded-full px-1.5 text-[0.8125rem] font-medium transition-colors",
593
+ on ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
594
+ ),
595
+ children: /* @__PURE__ */ jsx("span", { className: "truncate", children: sec.label })
596
+ },
597
+ sec.id
598
+ );
599
+ })
600
+ }
601
+ );
602
+ }
603
+ function TabBar({ items }) {
604
+ return /* @__PURE__ */ jsx(
605
+ "nav",
606
+ {
607
+ "aria-label": "Pages",
608
+ "data-oca-tabbar": "",
609
+ className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
610
+ children: /* @__PURE__ */ jsx(
637
611
  "div",
638
612
  {
639
- className: cn(
640
- "flex items-center justify-between gap-4",
641
- tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem] md:max-lg:gap-2",
642
- // Three columns, the outer two each at least their content: the
643
- // navigation stays centred whatever the actions hold, so it does
644
- // not shift when they change (signed out to signed in).
645
- !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
646
- ),
647
- children: [
648
- /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
649
- /* @__PURE__ */ jsxs(Link5, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
650
- brandNode,
651
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
652
- ] }),
653
- family ? /* @__PURE__ */ jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
654
- tool && navigation ? /* @__PURE__ */ jsx("div", { className: "ml-5", children: navigation }) : null
655
- ] }),
656
- !tool ? navigation : null,
657
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
658
- search,
659
- actions,
660
- menu ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
661
- /* @__PURE__ */ jsx(
662
- SheetTrigger,
613
+ className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
614
+ style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
615
+ children: items.map((it) => /* @__PURE__ */ jsxs(
616
+ Link,
617
+ {
618
+ href: it.href,
619
+ "aria-current": it.active ? "page" : void 0,
620
+ className: cn(
621
+ "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
622
+ it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
623
+ ),
624
+ children: [
625
+ /* @__PURE__ */ jsxs(
626
+ "span",
663
627
  {
664
- className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
665
- "aria-label": "Open menu",
666
- children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
628
+ className: cn(
629
+ "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
630
+ "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
631
+ it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
632
+ ),
633
+ children: [
634
+ it.icon,
635
+ it.badge ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
636
+ ]
667
637
  }
668
638
  ),
669
- /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
670
- /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
671
- menuExtra ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
672
- phoneNav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
673
- (n) => n.children?.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-2", children: [
674
- /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
675
- n.children.map((c) => /* @__PURE__ */ jsx(
676
- NavLink,
677
- {
678
- item: c,
679
- className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
680
- onNavigate: () => setOpen(false)
681
- },
682
- c.href
683
- ))
684
- ] }, n.href) : /* @__PURE__ */ jsx(
685
- NavLink,
686
- {
687
- item: n,
688
- className: "rounded-xl px-3 py-3 text-[1.0625rem]",
689
- onNavigate: () => setOpen(false)
690
- },
691
- n.href
692
- )
693
- ) }) : null,
694
- family ? /* @__PURE__ */ jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
695
- /* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
696
- "All orangecheck sites",
697
- /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
698
- ] }),
699
- /* @__PURE__ */ jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
700
- ] }) : null
701
- ] })
702
- ] }) : null
703
- ] })
704
- ]
639
+ /* @__PURE__ */ jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
640
+ it.badge ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: it.badge }) : null
641
+ ]
642
+ },
643
+ it.href
644
+ ))
705
645
  }
706
646
  )
707
647
  }
708
648
  );
709
649
  }
710
- function SkipLink({ href = "#main-content", children = "Skip to content" }) {
711
- return /* @__PURE__ */ jsx(
712
- "a",
713
- {
714
- href,
715
- className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
716
- children
717
- }
718
- );
719
- }
720
- var BANNER_TONE = {
721
- neutral: "border-border bg-muted",
722
- brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
723
- danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
724
- };
725
- function SiteBanner({
726
- tone = "neutral",
650
+ function tabsFor(groups) {
651
+ const items = groups.flatMap((g) => g.items);
652
+ return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
653
+ }
654
+ var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
655
+ var warned = /* @__PURE__ */ new Set();
656
+ function warnDuplicateLabels(groups) {
657
+ if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
658
+ const seen = /* @__PURE__ */ new Set();
659
+ for (const it of groups.flatMap((g) => g.items)) {
660
+ if (seen.has(it.label) && !warned.has(it.label)) {
661
+ warned.add(it.label);
662
+ console.warn(`AppShell: two pages are labelled "${it.label}"; give each its own name.`);
663
+ }
664
+ seen.add(it.label);
665
+ }
666
+ }
667
+ function AppShell({
668
+ nav,
669
+ sections,
670
+ activeSection,
671
+ page: pageOverride,
672
+ persistent = [],
673
+ home = "/",
674
+ family,
675
+ account,
676
+ banner,
677
+ footer,
727
678
  children,
728
- action,
729
679
  className
730
680
  }) {
731
- return /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", "data-tone": tone, className: cn("border-b text-[0.875rem]", BANNER_TONE[tone], className), children: /* @__PURE__ */ jsxs("div", { className: "oca-container flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-2.5", children: [
732
- /* @__PURE__ */ jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
733
- tone !== "neutral" ? /* @__PURE__ */ jsx(
734
- "span",
735
- {
736
- "aria-hidden": true,
737
- className: cn(
738
- "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
739
- tone === "brand" ? "bg-oca-orange" : "bg-destructive"
740
- )
741
- }
742
- ) : null,
743
- /* @__PURE__ */ jsx("span", { children })
744
- ] }),
745
- action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
746
- ] }) });
747
- }
748
- var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
749
- function LegalRow({ links }) {
750
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
751
- /* @__PURE__ */ jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-5", children: links.map((l) => /* @__PURE__ */ jsx("li", { children: l.href.startsWith("/") ? /* @__PURE__ */ jsx(Link5, { href: l.href, className: FOOT_LINK, children: l.label }) : /* @__PURE__ */ jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
752
- /* @__PURE__ */ jsxs("p", { children: [
753
- "\xA9 ",
754
- (/* @__PURE__ */ new Date()).getFullYear(),
755
- " OrangeCheck"
756
- ] })
757
- ] });
681
+ const [open, setOpen] = useState(false);
682
+ const current = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
683
+ const groups = current ? [...current.groups, ...persistent] : [...nav ?? [], ...persistent];
684
+ warnDuplicateLabels(groups);
685
+ const tabs = current ? null : tabsFor(groups);
686
+ const page = activeItem(groups);
687
+ const place = useMemo(
688
+ () => ({
689
+ section: current ? current.title ?? current.label : void 0,
690
+ page: pageOverride ?? page?.label
691
+ }),
692
+ [current, page?.label, pageOverride]
693
+ );
694
+ const familyMenu = family ? /* @__PURE__ */ jsx(FamilyMenu, { current: typeof family === "string" ? family : void 0 }) : null;
695
+ const switcher = sections && current && sections.length > 1 ? /* @__PURE__ */ jsx(SectionSwitch, { sections, current, onNavigate: () => setOpen(false) }) : null;
696
+ return /* @__PURE__ */ jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxs(
697
+ "div",
698
+ {
699
+ className: cn(
700
+ "min-h-dvh bg-background",
701
+ tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
702
+ className
703
+ ),
704
+ children: [
705
+ /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
706
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
707
+ /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
708
+ /* @__PURE__ */ jsx(
709
+ SheetTrigger,
710
+ {
711
+ className: cn(
712
+ "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
713
+ // The tab bar holds every page; the sheet is left for a footer.
714
+ tabs && !footer && "max-md:hidden"
715
+ ),
716
+ "aria-label": "Open navigation",
717
+ children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
718
+ }
719
+ ),
720
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
721
+ /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
722
+ switcher,
723
+ /* @__PURE__ */ jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
724
+ footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
725
+ ] })
726
+ ] }),
727
+ /* @__PURE__ */ jsx(Link, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
728
+ familyMenu,
729
+ /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
730
+ ] }),
731
+ place.page ? /* @__PURE__ */ jsxs(
732
+ "div",
733
+ {
734
+ className: cn(
735
+ "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
736
+ // The active tab already names the page.
737
+ tabs && !pageOverride && "max-md:hidden"
738
+ ),
739
+ children: [
740
+ place.section ? /* @__PURE__ */ jsxs(Fragment, { children: [
741
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
742
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
743
+ ] }) : null,
744
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
745
+ ]
746
+ }
747
+ ) : null
748
+ ] }),
749
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
750
+ /* @__PURE__ */ jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
751
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
752
+ /* @__PURE__ */ jsx(Link, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
753
+ familyMenu
754
+ ] }),
755
+ switcher,
756
+ /* @__PURE__ */ jsx(SideNav, { groups }),
757
+ /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
758
+ ] }),
759
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
760
+ /* @__PURE__ */ jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
761
+ banner ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
762
+ /* @__PURE__ */ jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
763
+ ] })
764
+ ] }),
765
+ tabs ? /* @__PURE__ */ jsx(TabBar, { items: tabs }) : null
766
+ ]
767
+ }
768
+ ) });
758
769
  }
759
- function SiteFooter({
760
- columns = [],
761
- family = false,
762
- legal = false,
763
- compact = false,
764
- fineprint,
765
- meta,
766
- signature = true,
767
- className
770
+ function AccountMenu({
771
+ name,
772
+ detail,
773
+ items,
774
+ nameFrom = "sm"
768
775
  }) {
769
- const legalLinks = legal === true ? LEGAL_LINKS : legal || null;
770
- if (compact) {
771
- return /* @__PURE__ */ jsx("footer", { className: cn("border-t border-border bg-background text-[0.875rem] text-muted-foreground", className), children: /* @__PURE__ */ jsxs("div", { className: "oca-container flex flex-col gap-x-8 gap-y-3 py-5 lg:flex-row lg:items-center lg:justify-between", children: [
772
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
773
- /* @__PURE__ */ jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
774
- family ? /* @__PURE__ */ jsx("nav", { "aria-label": "Protocols", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-4", children: PROTOCOLS.map((p) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: p.pageHref, className: FOOT_LINK, children: p.label }) }, p.slug)) }) }) : null
775
- ] }),
776
- legalLinks || meta ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
777
- legalLinks ? /* @__PURE__ */ jsx(LegalRow, { links: legalLinks }) : null,
778
- meta
779
- ] }) : null
780
- ] }) });
781
- }
782
- const cols = [
783
- ...columns,
784
- ...family ? familyByGroup().map((g) => ({
785
- // The lockup above already says orangecheck.
786
- heading: g.id === "orangecheck" ? "Start here" : g.label,
787
- links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
788
- })) : []
789
- ];
790
- const n = cols.length;
791
- const inline = n <= 5;
792
- const grid = {
793
- "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
794
- "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
795
- };
796
- return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
776
+ const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
777
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
797
778
  /* @__PURE__ */ jsxs(
798
- "div",
779
+ DropdownMenuTrigger,
799
780
  {
800
- style: grid,
801
- className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[var(--oca-footer-md)] md:py-16 lg:grid-cols-[var(--oca-footer-lg)]",
781
+ className: cn(
782
+ "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
783
+ nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
784
+ ),
785
+ "aria-label": `${name}, account menu`,
802
786
  children: [
803
- /* @__PURE__ */ jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
804
- /* @__PURE__ */ jsx(Lockup, { size: 26 }),
805
- fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
806
- ] }),
807
- cols.map((col, i) => {
808
- const spans = n % 2 === 1 && i === n - 1;
809
- return /* @__PURE__ */ jsxs(
810
- "div",
811
- {
812
- className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
813
- children: [
814
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
815
- /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsx(
816
- NavLink,
817
- {
818
- item: l,
819
- className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
820
- },
821
- l.href
822
- )) })
823
- ]
824
- },
825
- col.heading
826
- );
827
- })
787
+ /* @__PURE__ */ jsx(
788
+ "span",
789
+ {
790
+ "aria-hidden": true,
791
+ "data-initial": initial,
792
+ className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
793
+ }
794
+ ),
795
+ /* @__PURE__ */ jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
828
796
  ]
829
797
  }
830
798
  ),
831
- signature ? /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "oca-container select-none overflow-hidden pb-8 md:pb-12", children: /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-[0.18em] text-[clamp(3rem,11.5vw,10rem)] leading-[0.78] tracking-[-0.065em] [font-family:var(--oc-font-display)]", children: [
832
- /* @__PURE__ */ jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsx(Mark, { className: "block h-auto w-full" }) }),
833
- /* @__PURE__ */ jsx("span", { children: "orangecheck" })
834
- ] }) }) : null,
835
- legalLinks || meta ? /* @__PURE__ */ jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: [
836
- legalLinks ? /* @__PURE__ */ jsx(LegalRow, { links: legalLinks }) : null,
837
- meta
838
- ] }) }) : null
799
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-64", children: [
800
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
801
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: name }),
802
+ detail ? /* @__PURE__ */ jsx("span", { className: "truncate font-mono text-[0.75rem]", children: detail }) : null
803
+ ] }),
804
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
805
+ items.map(
806
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link, { href: it.href, children: [
807
+ it.icon,
808
+ it.label
809
+ ] }) }, it.label) : /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
810
+ it.icon,
811
+ it.label
812
+ ] }, it.label)
813
+ )
814
+ ] })
839
815
  ] });
840
816
  }
841
- function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
842
- const ref = useRef(null);
843
- useEffect(() => {
844
- const el = ref.current;
845
- if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
846
- let raf = 0;
847
- let tx = 0;
848
- let ty = 0;
849
- let x = 0;
850
- let y = 0;
851
- const step = () => {
852
- x += (tx - x) * 0.08;
853
- y += (ty - y) * 0.08;
854
- el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
855
- el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
856
- raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
857
- };
858
- const move = (e) => {
859
- const b = el.getBoundingClientRect();
860
- tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
861
- ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
862
- if (!raf) raf = requestAnimationFrame(step);
863
- };
864
- window.addEventListener("pointermove", move, { passive: true });
865
- return () => {
866
- cancelAnimationFrame(raf);
867
- window.removeEventListener("pointermove", move);
868
- };
869
- }, [tilt]);
870
- return /* @__PURE__ */ jsxs(
871
- "div",
817
+ function ThemeToggle({ className }) {
818
+ const { theme, setTheme } = useTheme();
819
+ const [mounted, setMounted] = useState(false);
820
+ useEffect(() => setMounted(true), []);
821
+ const current = mounted ? theme ?? "system" : "system";
822
+ const next = current === "light" ? "dark" : current === "dark" ? "system" : "light";
823
+ const Icon = current === "light" ? Sun : current === "dark" ? Moon : SunMoon;
824
+ return /* @__PURE__ */ jsx(
825
+ "button",
872
826
  {
873
- ref,
874
- className: cn("relative inline-block", settle && "oca-animate-settle", className),
875
- style: { width: size, perspective: tilt ? 900 : void 0 },
876
- children: [
877
- tilt ? /* @__PURE__ */ jsx(
878
- "div",
879
- {
880
- "aria-hidden": true,
881
- className: "absolute left-1/2 top-1/2 -z-0 aspect-square w-[120%] -translate-x-1/2 -translate-y-1/2 rounded-full opacity-70 blur-3xl",
882
- style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
883
- }
884
- ) : null,
885
- /* @__PURE__ */ jsx(
886
- "div",
887
- {
888
- className: "relative z-10 transition-transform duration-300 ease-out",
889
- style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
890
- children: /* @__PURE__ */ jsx(Mark, { size, title, className: "block" })
891
- }
892
- ),
893
- shadow ? /* @__PURE__ */ jsx(
894
- "div",
895
- {
896
- "aria-hidden": true,
897
- className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
898
- style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
899
- }
900
- ) : null
901
- ]
827
+ type: "button",
828
+ onClick: () => setTheme(next),
829
+ "aria-label": `Theme: ${current}. Switch to ${next}`,
830
+ title: `Theme: ${current}`,
831
+ className: cn(
832
+ "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
833
+ className
834
+ ),
835
+ children: /* @__PURE__ */ jsx(Icon, { className: "size-[1.125rem]" })
902
836
  }
903
837
  );
904
838
  }
905
- function SignInFrame({
906
- title = "Sign in",
907
- lead,
908
- children,
909
- error,
910
- fineprint,
911
- brand,
912
- home = "/",
913
- back,
914
- art,
915
- caption,
916
- className
839
+ function NavLink({
840
+ item,
841
+ className,
842
+ onNavigate,
843
+ line = false
917
844
  }) {
918
- return /* @__PURE__ */ jsxs(
919
- "main",
920
- {
921
- id: "main-content",
922
- className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
923
- children: [
924
- /* @__PURE__ */ jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
925
- /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4", children: [
926
- /* @__PURE__ */ jsxs(Link5, { href: home, className: "w-fit rounded-lg", children: [
927
- brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
928
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
929
- ] }),
930
- back === void 0 ? /* @__PURE__ */ jsx(
931
- Link5,
932
- {
933
- href: home,
934
- className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
935
- children: "Back to home"
936
- }
937
- ) : back
938
- ] }),
939
- /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
940
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
941
- /* @__PURE__ */ jsx("h1", { className: "oca-display-2", children: title }),
942
- lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead", children: lead }) : null
943
- ] }),
944
- /* @__PURE__ */ jsx("div", { children }),
945
- error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
946
- fineprint ? /* @__PURE__ */ jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
947
- ] })
948
- ] }),
949
- /* @__PURE__ */ jsxs(
950
- "aside",
951
- {
952
- "aria-hidden": true,
953
- className: "relative hidden flex-col justify-between gap-10 overflow-hidden border-l border-[var(--oca-band-line)] bg-oca-ink p-14 text-oca-ink-foreground lg:flex",
954
- children: [
955
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center", children: art ?? /* @__PURE__ */ jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) }),
956
- caption ? /* @__PURE__ */ jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
957
- ]
958
- }
959
- )
960
- ]
961
- }
845
+ const cls = cn(
846
+ "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
847
+ item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
848
+ line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
849
+ line && item.active && "after:bg-foreground",
850
+ className
962
851
  );
852
+ if (item.external) {
853
+ return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
854
+ }
855
+ return /* @__PURE__ */ jsx(Link, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
963
856
  }
964
- function Spinner({ className, label }) {
965
- return /* @__PURE__ */ jsxs(
966
- "svg",
967
- {
968
- viewBox: "0 0 24 24",
969
- fill: "none",
970
- role: label ? "status" : void 0,
971
- "aria-label": label,
972
- "aria-hidden": label ? void 0 : true,
973
- className: cn("size-4 animate-spin", className),
974
- children: [
975
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeOpacity: "0.2", strokeWidth: "2.5" }),
976
- /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })
977
- ]
978
- }
857
+ function NavRow({ item, onNavigate }) {
858
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
859
+ /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
860
+ item.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
861
+ ] });
862
+ const cls = cn(
863
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
864
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
979
865
  );
866
+ return item.external ? /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsx(Link, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
980
867
  }
981
- forwardRef(function Separator3({ className, orientation = "horizontal", decorative = true, ...props }, ref) {
868
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
869
+ function NavDropdown({ item }) {
870
+ const [open, setOpen] = useState(false);
871
+ const active = item.active || item.children?.some((c) => c.active);
872
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
873
+ /* @__PURE__ */ jsxs(
874
+ PopoverTrigger,
875
+ {
876
+ className: cn(
877
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors md:max-lg:pl-2.5 md:max-lg:pr-2",
878
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
879
+ ),
880
+ children: [
881
+ item.label,
882
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
883
+ ]
884
+ }
885
+ ),
886
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
887
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
888
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsx(
889
+ NavLink,
890
+ {
891
+ item: { ...item, label: seeAll(item), children: void 0 },
892
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
893
+ onNavigate: () => setOpen(false)
894
+ }
895
+ ) })
896
+ ] })
897
+ ] });
898
+ }
899
+ function SiteHeader({
900
+ home = "/",
901
+ brand,
902
+ product,
903
+ family,
904
+ nav = [],
905
+ search,
906
+ actions,
907
+ variant = "site",
908
+ navOnPhone = true,
909
+ menu: menuExtra,
910
+ className
911
+ }) {
912
+ const [open, setOpen] = useState(false);
913
+ const tool = variant === "tool";
914
+ const size = tool ? 24 : 28;
915
+ const current = typeof family === "string" ? family : void 0;
916
+ const phoneNav = navOnPhone ? nav : [];
917
+ const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
918
+ const brandNode = brand ?? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center", children: [
919
+ /* @__PURE__ */ jsx(Lockup, { size }),
920
+ product ? /* @__PURE__ */ jsxs(Fragment, { children: [
921
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
922
+ /* @__PURE__ */ jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
923
+ ] }) : null
924
+ ] });
925
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
926
+ (n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : (
927
+ // Between md and lg the family menu and the actions share the row: tighter.
928
+ /* @__PURE__ */ jsx(NavLink, { item: n, line: tool, className: tool ? void 0 : "md:max-lg:px-2.5" }, n.href)
929
+ )
930
+ ) }) : null;
982
931
  return /* @__PURE__ */ jsx(
983
- SeparatorPrimitive.Root,
932
+ "header",
984
933
  {
985
- ref,
986
- decorative,
987
- orientation,
988
934
  className: cn(
989
- "shrink-0 bg-border",
990
- orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
935
+ "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
936
+ tool ? "border-border" : "border-transparent",
991
937
  className
992
938
  ),
993
- ...props
994
- }
995
- );
996
- });
997
- function sharedContext(name, initial) {
998
- const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
999
- const store = globalThis;
1000
- return store[key] ?? (store[key] = createContext(initial));
1001
- }
1002
-
1003
- // src/lib/density.ts
1004
- var DensityContext = sharedContext("density", "comfortable");
1005
- function DensityProvider({ density, children }) {
1006
- return createElement(DensityContext.Provider, { value: density }, children);
1007
- }
1008
- var ShellContext = sharedContext("shell-place", {});
1009
- function useShellPlace() {
1010
- return useContext(ShellContext);
1011
- }
1012
- var buttonVariants = cva(
1013
- [
1014
- "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
1015
- "transition-[background-color,border-color,color,box-shadow,transform] duration-150",
1016
- "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1017
- "active:translate-y-px disabled:pointer-events-none",
1018
- // Disabled is one look for every variant: a quiet grey pill, never a
1019
- // faded black or orange slab that reads as broken.
1020
- "disabled:border disabled:border-border disabled:bg-muted disabled:text-oca-subtle disabled:shadow-none",
1021
- "[&_svg]:pointer-events-none [&_svg]:size-[1.1em] [&_svg]:shrink-0"
1022
- ],
1023
- {
1024
- variants: {
1025
- variant: {
1026
- primary: "bg-primary text-primary-foreground hover:bg-primary/85",
1027
- secondary: "border border-border bg-secondary text-secondary-foreground hover:border-oca-hairline-strong hover:bg-accent",
1028
- brand: "bg-brand text-brand-foreground hover:bg-oca-orange-deep",
1029
- ghost: "text-foreground hover:bg-accent",
1030
- danger: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
1031
- link: "h-auto rounded-none px-0 text-foreground underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
1032
- onInk: "bg-white text-oca-ink hover:bg-white/90",
1033
- onInkOutline: "border border-white/20 text-white hover:bg-white/10"
1034
- },
1035
- size: {
1036
- sm: "h-9 px-4 text-sm",
1037
- md: "h-11 px-5 text-[0.9375rem]",
1038
- lg: "h-14 px-7 text-[1.0625rem]",
1039
- icon: "size-10",
1040
- "icon-sm": "size-8"
1041
- }
1042
- },
1043
- compoundVariants: [{ variant: "link", className: "h-auto px-0" }],
1044
- defaultVariants: { variant: "primary", size: "md" }
1045
- }
1046
- );
1047
- var Button = forwardRef(function Button2({ className, variant, size, asChild = false, loading = false, disabled, children, type, ...props }, ref) {
1048
- const Comp = asChild ? Slot : "button";
939
+ children: /* @__PURE__ */ jsxs(
940
+ "div",
941
+ {
942
+ className: cn(
943
+ "flex items-center justify-between gap-4",
944
+ tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem] md:max-lg:gap-2",
945
+ // Three columns, the outer two each at least their content: the
946
+ // navigation stays centred whatever the actions hold, so it does
947
+ // not shift when they change (signed out to signed in).
948
+ !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
949
+ ),
950
+ children: [
951
+ /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
952
+ /* @__PURE__ */ jsxs(Link, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
953
+ brandNode,
954
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
955
+ ] }),
956
+ family ? /* @__PURE__ */ jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
957
+ tool && navigation ? /* @__PURE__ */ jsx("div", { className: "ml-5", children: navigation }) : null
958
+ ] }),
959
+ !tool ? navigation : null,
960
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
961
+ search,
962
+ actions,
963
+ menu ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
964
+ /* @__PURE__ */ jsx(
965
+ SheetTrigger,
966
+ {
967
+ className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
968
+ "aria-label": "Open menu",
969
+ children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
970
+ }
971
+ ),
972
+ /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
973
+ /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
974
+ menuExtra ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
975
+ phoneNav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
976
+ (n) => n.children?.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-2", children: [
977
+ /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
978
+ n.children.map((c) => /* @__PURE__ */ jsx(
979
+ NavLink,
980
+ {
981
+ item: c,
982
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
983
+ onNavigate: () => setOpen(false)
984
+ },
985
+ c.href
986
+ ))
987
+ ] }, n.href) : /* @__PURE__ */ jsx(
988
+ NavLink,
989
+ {
990
+ item: n,
991
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
992
+ onNavigate: () => setOpen(false)
993
+ },
994
+ n.href
995
+ )
996
+ ) }) : null,
997
+ family ? /* @__PURE__ */ jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
998
+ /* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
999
+ "All orangecheck sites",
1000
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1001
+ ] }),
1002
+ /* @__PURE__ */ jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
1003
+ ] }) : null
1004
+ ] })
1005
+ ] }) : null
1006
+ ] })
1007
+ ]
1008
+ }
1009
+ )
1010
+ }
1011
+ );
1012
+ }
1013
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
1049
1014
  return /* @__PURE__ */ jsx(
1050
- Comp,
1015
+ "a",
1051
1016
  {
1052
- ref,
1053
- "data-ui": "button",
1054
- className: cn(buttonVariants({ variant, size }), className),
1055
- disabled: asChild ? void 0 : disabled || loading,
1056
- "aria-busy": loading || void 0,
1057
- type: asChild ? void 0 : type ?? "button",
1058
- ...props,
1059
- children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
1060
- loading ? /* @__PURE__ */ jsx(Spinner, { className: "size-[1.1em]" }) : null,
1061
- children
1062
- ] })
1017
+ href,
1018
+ className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
1019
+ children
1063
1020
  }
1064
1021
  );
1065
- });
1066
- function useActiveHeading(ids) {
1067
- const [active, setActive] = useState(ids[0]);
1068
- const key = ids.join("|");
1069
- useEffect(() => {
1070
- setActive(key.split("|")[0] || void 0);
1071
- const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
1072
- if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
1073
- const io = new IntersectionObserver(
1074
- (entries) => {
1075
- const hit = entries.filter((e) => e.isIntersecting).sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0];
1076
- if (hit) setActive(hit.target.id);
1077
- },
1078
- { rootMargin: "-80px 0px -65% 0px" }
1079
- );
1080
- els.forEach((el) => io.observe(el));
1081
- return () => io.disconnect();
1082
- }, [key]);
1083
- return active;
1084
- }
1085
- function useHeadings(selector = "#docs-content", key) {
1086
- const [items, setItems] = useState([]);
1087
- useEffect(() => {
1088
- const read = () => {
1089
- const root = document.querySelector(selector);
1090
- if (!root) return setItems([]);
1091
- setItems(
1092
- Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
1093
- id: h.id,
1094
- // The anchor link's "#" is not part of the name.
1095
- label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
1096
- level: h.tagName === "H3" ? 3 : 2
1097
- }))
1098
- );
1099
- };
1100
- const raf = requestAnimationFrame(read);
1101
- const t = setTimeout(read, 80);
1102
- return () => {
1103
- cancelAnimationFrame(raf);
1104
- clearTimeout(t);
1105
- };
1106
- }, [selector, key]);
1107
- const activeId = useActiveHeading(items.map((i) => i.id));
1108
- return { items, activeId };
1109
1022
  }
1110
- function OnThisPage({
1111
- items,
1112
- activeId,
1113
- title = "On this page",
1114
- onNavigate,
1023
+ var BANNER_TONE = {
1024
+ neutral: "border-border bg-muted",
1025
+ brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
1026
+ danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
1027
+ };
1028
+ function SiteBanner({
1029
+ tone = "neutral",
1030
+ children,
1031
+ action,
1115
1032
  className
1116
1033
  }) {
1117
- const id = useId();
1118
- if (items.length === 0) return null;
1119
- return (
1120
- // With no visible title (a folded list under its own summary) the name is still "On this page".
1121
- /* @__PURE__ */ jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
1122
- title ? /* @__PURE__ */ jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
1123
- /* @__PURE__ */ jsx("ul", { children: items.map((t) => {
1124
- const on = t.id === activeId;
1125
- return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1126
- "a",
1127
- {
1128
- href: `#${t.id}`,
1129
- onClick: onNavigate,
1130
- "aria-current": on ? "location" : void 0,
1131
- className: cn(
1132
- "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
1133
- t.level === 3 ? "pl-7" : "pl-4",
1134
- on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
1135
- ),
1136
- children: t.label
1137
- }
1138
- ) }, t.id);
1139
- }) })
1034
+ return /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", "data-tone": tone, className: cn("border-b text-[0.875rem]", BANNER_TONE[tone], className), children: /* @__PURE__ */ jsxs("div", { className: "oca-container flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-2.5", children: [
1035
+ /* @__PURE__ */ jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
1036
+ tone !== "neutral" ? /* @__PURE__ */ jsx(
1037
+ "span",
1038
+ {
1039
+ "aria-hidden": true,
1040
+ className: cn(
1041
+ "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
1042
+ tone === "brand" ? "bg-oca-orange" : "bg-destructive"
1043
+ )
1044
+ }
1045
+ ) : null,
1046
+ /* @__PURE__ */ jsx("span", { children })
1047
+ ] }),
1048
+ action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
1049
+ ] }) });
1050
+ }
1051
+ var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
1052
+ function LegalRow({ links }) {
1053
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
1054
+ /* @__PURE__ */ jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-5", children: links.map((l) => /* @__PURE__ */ jsx("li", { children: l.href.startsWith("/") ? /* @__PURE__ */ jsx(Link, { href: l.href, className: FOOT_LINK, children: l.label }) : /* @__PURE__ */ jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
1055
+ /* @__PURE__ */ jsxs("p", { children: [
1056
+ "\xA9 ",
1057
+ (/* @__PURE__ */ new Date()).getFullYear(),
1058
+ " OrangeCheck"
1140
1059
  ] })
1141
- );
1060
+ ] });
1142
1061
  }
1143
- var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
1144
- var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
1145
- function DocsNav({
1146
- sections,
1147
- current,
1148
- onNavigate,
1062
+ function SiteFooter({
1063
+ columns = [],
1064
+ family = false,
1065
+ legal = false,
1066
+ compact = false,
1067
+ fineprint,
1068
+ meta,
1069
+ signature = true,
1149
1070
  className
1150
1071
  }) {
1151
- const here = pathOf(current);
1152
- const activeSection = useMemo(
1153
- () => sections.findIndex((s) => s.items.some((i) => pathOf(i.href) === here)),
1154
- [sections, here]
1155
- );
1156
- const [peeked, setPeeked] = useState(() => /* @__PURE__ */ new Set());
1157
- useEffect(() => setPeeked(/* @__PURE__ */ new Set()), [activeSection]);
1158
- const activeRef = useRef(null);
1159
- useEffect(() => {
1160
- const id = requestAnimationFrame(() => activeRef.current?.scrollIntoView({ block: "nearest" }));
1161
- return () => cancelAnimationFrame(id);
1162
- }, [here]);
1163
- const base = useId();
1164
- return /* @__PURE__ */ jsx("nav", { "aria-label": "Docs", className: cn("flex flex-col gap-0.5", className), children: sections.map((section, si) => {
1165
- const isActive = si === activeSection;
1166
- const open = isActive || peeked.has(si);
1167
- const panel = `${base}-s${si}`;
1168
- return /* @__PURE__ */ jsxs("div", { children: [
1169
- /* @__PURE__ */ jsxs(
1170
- "button",
1171
- {
1172
- type: "button",
1173
- "aria-expanded": open,
1174
- "aria-controls": panel,
1175
- onClick: () => {
1176
- if (isActive) return;
1177
- setPeeked((p) => {
1178
- const n = new Set(p);
1179
- if (n.has(si)) n.delete(si);
1180
- else n.add(si);
1181
- return n;
1182
- });
1183
- },
1184
- className: cn(
1185
- "flex min-h-9 w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-[0.875rem] transition-colors",
1186
- isActive ? "font-medium text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground",
1187
- isActive && "cursor-default"
1188
- ),
1189
- children: [
1190
- section.label,
1191
- /* @__PURE__ */ jsx(
1192
- ChevronRight,
1193
- {
1194
- "aria-hidden": true,
1195
- className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
1196
- }
1197
- )
1198
- ]
1199
- }
1200
- ),
1201
- /* @__PURE__ */ jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
1202
- const on = pathOf(item.href) === here;
1203
- const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsx(Badge, { tone: "muted", children: item.badge }) : null;
1204
- return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1205
- Link5,
1206
- {
1207
- href: item.href,
1208
- ref: on ? activeRef : void 0,
1209
- onClick: onNavigate,
1210
- "aria-current": on ? "page" : void 0,
1211
- className: cn(
1212
- "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
1213
- on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
1214
- ),
1215
- children: [
1216
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: item.label }),
1217
- badge
1218
- ]
1219
- }
1220
- ) }, item.href);
1221
- }) })
1222
- ] }, section.label);
1223
- }) });
1224
- }
1225
- var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
1226
- function DocsShell({
1227
- nav,
1228
- current,
1229
- header,
1230
- search,
1231
- actions,
1232
- breadcrumbs,
1233
- toc,
1234
- pager,
1235
- footer,
1236
- children
1237
- }) {
1238
- const [menu, setMenu] = useState(false);
1239
- useEffect(() => setMenu(false), [current]);
1240
- const read = useHeadings("#docs-content", current);
1241
- const items = toc ?? read.items;
1242
- const activeId = toc ? void 0 : read.activeId;
1243
- const here = pathOf(current);
1244
- const place = useMemo(() => {
1245
- for (const s of nav) {
1246
- const it = s.items.find((i) => pathOf(i.href) === here);
1247
- if (it) return { section: s.label, page: it.label };
1248
- }
1249
- return null;
1250
- }, [nav, here]);
1251
- return /* @__PURE__ */ jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
1252
- /* @__PURE__ */ jsx(SkipLink, {}),
1253
- header ?? /* @__PURE__ */ jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
1254
- /* @__PURE__ */ jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
1255
- /* @__PURE__ */ jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
1256
- /* @__PURE__ */ jsx(PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
1257
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Docs menu. " }),
1258
- place ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1259
- /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1260
- /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
1261
- /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
1262
- ] }) : /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Docs" })
1263
- ] }),
1264
- /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
1265
- /* @__PURE__ */ jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
1266
- /* @__PURE__ */ jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current, onNavigate: () => setMenu(false) }) })
1267
- ] })
1268
- ] }) }) }),
1269
- /* @__PURE__ */ jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
1270
- /* @__PURE__ */ jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current }) }),
1271
- /* @__PURE__ */ jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
1272
- breadcrumbs ? /* @__PURE__ */ jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
1273
- items.length > 1 ? /* @__PURE__ */ jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
1274
- /* @__PURE__ */ jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
1275
- "On this page",
1276
- /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1277
- ] }),
1278
- /* @__PURE__ */ jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
1279
- ] }) : null,
1280
- /* @__PURE__ */ jsx("article", { id: "docs-content", className: "max-w-[46rem]", children }),
1281
- pager ? /* @__PURE__ */ jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
1072
+ const legalLinks = legal === true ? LEGAL_LINKS : legal || null;
1073
+ if (compact) {
1074
+ return /* @__PURE__ */ jsx("footer", { className: cn("border-t border-border bg-background text-[0.875rem] text-muted-foreground", className), children: /* @__PURE__ */ jsxs("div", { className: "oca-container flex flex-col gap-x-8 gap-y-3 py-5 lg:flex-row lg:items-center lg:justify-between", children: [
1075
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
1076
+ /* @__PURE__ */ jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
1077
+ family ? /* @__PURE__ */ jsx("nav", { "aria-label": "Protocols", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-4", children: PROTOCOLS.map((p) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: p.pageHref, className: FOOT_LINK, children: p.label }) }, p.slug)) }) }) : null
1282
1078
  ] }),
1283
- /* @__PURE__ */ jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsx(OnThisPage, { items, activeId }) : null })
1284
- ] }) }),
1285
- footer ?? /* @__PURE__ */ jsx(SiteFooter, { columns: OCHK_IO_FOOTER, family: true, legal: true, signature: false })
1286
- ] });
1287
- }
1288
- function SideNav({ groups, onNavigate }) {
1289
- return /* @__PURE__ */ jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
1290
- g.label ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
1291
- g.items.map((it) => /* @__PURE__ */ jsxs(
1292
- Link5,
1079
+ legalLinks || meta ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
1080
+ legalLinks ? /* @__PURE__ */ jsx(LegalRow, { links: legalLinks }) : null,
1081
+ meta
1082
+ ] }) : null
1083
+ ] }) });
1084
+ }
1085
+ const cols = [
1086
+ ...columns,
1087
+ ...family ? familyByGroup().map((g) => ({
1088
+ // The lockup above already says orangecheck.
1089
+ heading: g.id === "orangecheck" ? "Start here" : g.label,
1090
+ links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
1091
+ })) : []
1092
+ ];
1093
+ const n = cols.length;
1094
+ const inline = n <= 5;
1095
+ const grid = {
1096
+ "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
1097
+ "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
1098
+ };
1099
+ return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
1100
+ /* @__PURE__ */ jsxs(
1101
+ "div",
1293
1102
  {
1294
- href: it.href,
1295
- onClick: onNavigate,
1296
- "aria-current": it.active ? "page" : void 0,
1297
- className: cn(
1298
- "flex h-9 items-center gap-3 rounded-xl px-3 text-[0.9375rem] transition-colors",
1299
- "[&_svg]:size-[1.0625rem] [&_svg]:shrink-0",
1300
- it.active ? "bg-card text-foreground shadow-sm ring-1 ring-border [&_svg]:text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
1301
- ),
1103
+ style: grid,
1104
+ className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[var(--oca-footer-md)] md:py-16 lg:grid-cols-[var(--oca-footer-lg)]",
1302
1105
  children: [
1303
- it.icon,
1304
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: it.label }),
1305
- it.badge ? /* @__PURE__ */ jsx("span", { className: "shrink-0", children: it.badge }) : null
1106
+ /* @__PURE__ */ jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
1107
+ /* @__PURE__ */ jsx(Lockup, { size: 26 }),
1108
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
1109
+ ] }),
1110
+ cols.map((col, i) => {
1111
+ const spans = n % 2 === 1 && i === n - 1;
1112
+ return /* @__PURE__ */ jsxs(
1113
+ "div",
1114
+ {
1115
+ className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
1116
+ children: [
1117
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
1118
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsx(
1119
+ NavLink,
1120
+ {
1121
+ item: l,
1122
+ className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
1123
+ },
1124
+ l.href
1125
+ )) })
1126
+ ]
1127
+ },
1128
+ col.heading
1129
+ );
1130
+ })
1306
1131
  ]
1307
- },
1308
- it.href
1309
- ))
1310
- ] }, g.label ?? gi)) });
1132
+ }
1133
+ ),
1134
+ signature ? /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "oca-container select-none overflow-hidden pb-8 md:pb-12", children: /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-[0.18em] text-[clamp(3rem,11.5vw,10rem)] leading-[0.78] tracking-[-0.065em] [font-family:var(--oc-font-display)]", children: [
1135
+ /* @__PURE__ */ jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsx(Mark, { className: "block h-auto w-full" }) }),
1136
+ /* @__PURE__ */ jsx("span", { children: "orangecheck" })
1137
+ ] }) }) : null,
1138
+ legalLinks || meta ? /* @__PURE__ */ jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: [
1139
+ legalLinks ? /* @__PURE__ */ jsx(LegalRow, { links: legalLinks }) : null,
1140
+ meta
1141
+ ] }) }) : null
1142
+ ] });
1311
1143
  }
1312
- function SectionSwitch({
1313
- sections,
1314
- current,
1315
- onNavigate
1316
- }) {
1317
- const cols = sections.length <= 3 ? sections.length : 2;
1144
+ function OchkIoFooter({ columns = OCHK_IO_FOOTER, className }) {
1318
1145
  return /* @__PURE__ */ jsx(
1319
- "nav",
1146
+ SiteFooter,
1320
1147
  {
1321
- "aria-label": "Sections",
1322
- className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
1323
- style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
1324
- children: sections.map((sec) => {
1325
- const on = sec.id === current.id;
1326
- return /* @__PURE__ */ jsx(
1327
- Link5,
1328
- {
1329
- href: sec.href,
1330
- onClick: onNavigate,
1331
- "aria-current": on ? "true" : void 0,
1332
- className: cn(
1333
- "flex h-8 min-w-0 items-center justify-center rounded-full px-1.5 text-[0.8125rem] font-medium transition-colors",
1334
- on ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
1335
- ),
1336
- children: /* @__PURE__ */ jsx("span", { className: "truncate", children: sec.label })
1337
- },
1338
- sec.id
1339
- );
1340
- })
1148
+ columns,
1149
+ family: true,
1150
+ legal: true,
1151
+ fineprint: "Open protocols on Bitcoin. Anyone can check the result.",
1152
+ meta: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
1153
+ /* @__PURE__ */ jsxs("p", { children: [
1154
+ "Open-source work on orangecheck is ",
1155
+ /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: "supported by OpenSats." })
1156
+ ] }),
1157
+ /* @__PURE__ */ jsx(ThemeToggle, { className: "-mx-3" })
1158
+ ] }),
1159
+ className
1341
1160
  }
1342
1161
  );
1343
1162
  }
1344
- function TabBar({ items }) {
1345
- return /* @__PURE__ */ jsx(
1346
- "nav",
1347
- {
1348
- "aria-label": "Pages",
1349
- "data-oca-tabbar": "",
1350
- className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
1351
- children: /* @__PURE__ */ jsx(
1352
- "div",
1353
- {
1354
- className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
1355
- style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
1356
- children: items.map((it) => /* @__PURE__ */ jsxs(
1357
- Link5,
1358
- {
1359
- href: it.href,
1360
- "aria-current": it.active ? "page" : void 0,
1361
- className: cn(
1362
- "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
1363
- it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
1364
- ),
1365
- children: [
1366
- /* @__PURE__ */ jsxs(
1367
- "span",
1368
- {
1369
- className: cn(
1370
- "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
1371
- "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
1372
- it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
1373
- ),
1374
- children: [
1375
- it.icon,
1376
- it.badge ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
1377
- ]
1378
- }
1379
- ),
1380
- /* @__PURE__ */ jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
1381
- it.badge ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: it.badge }) : null
1382
- ]
1383
- },
1384
- it.href
1385
- ))
1386
- }
1387
- )
1163
+ function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
1164
+ const ref = useRef(null);
1165
+ useEffect(() => {
1166
+ const el = ref.current;
1167
+ if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
1168
+ let raf = 0;
1169
+ let tx = 0;
1170
+ let ty = 0;
1171
+ let x = 0;
1172
+ let y = 0;
1173
+ const step = () => {
1174
+ x += (tx - x) * 0.08;
1175
+ y += (ty - y) * 0.08;
1176
+ el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
1177
+ el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
1178
+ raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
1179
+ };
1180
+ const move = (e) => {
1181
+ const b = el.getBoundingClientRect();
1182
+ tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
1183
+ ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
1184
+ if (!raf) raf = requestAnimationFrame(step);
1185
+ };
1186
+ window.addEventListener("pointermove", move, { passive: true });
1187
+ return () => {
1188
+ cancelAnimationFrame(raf);
1189
+ window.removeEventListener("pointermove", move);
1190
+ };
1191
+ }, [tilt]);
1192
+ return /* @__PURE__ */ jsxs(
1193
+ "div",
1194
+ {
1195
+ ref,
1196
+ className: cn("relative inline-block", settle && "oca-animate-settle", className),
1197
+ style: { width: size, perspective: tilt ? 900 : void 0 },
1198
+ children: [
1199
+ tilt ? /* @__PURE__ */ jsx(
1200
+ "div",
1201
+ {
1202
+ "aria-hidden": true,
1203
+ className: "absolute left-1/2 top-1/2 -z-0 aspect-square w-[120%] -translate-x-1/2 -translate-y-1/2 rounded-full opacity-70 blur-3xl",
1204
+ style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
1205
+ }
1206
+ ) : null,
1207
+ /* @__PURE__ */ jsx(
1208
+ "div",
1209
+ {
1210
+ className: "relative z-10 transition-transform duration-300 ease-out",
1211
+ style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
1212
+ children: /* @__PURE__ */ jsx(Mark, { size, title, className: "block" })
1213
+ }
1214
+ ),
1215
+ shadow ? /* @__PURE__ */ jsx(
1216
+ "div",
1217
+ {
1218
+ "aria-hidden": true,
1219
+ className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
1220
+ style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
1221
+ }
1222
+ ) : null
1223
+ ]
1388
1224
  }
1389
1225
  );
1390
1226
  }
1391
- function tabsFor(groups) {
1392
- const items = groups.flatMap((g) => g.items);
1393
- return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
1394
- }
1395
- var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
1396
- var warned = /* @__PURE__ */ new Set();
1397
- function warnDuplicateLabels(groups) {
1398
- if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
1399
- const seen = /* @__PURE__ */ new Set();
1400
- for (const it of groups.flatMap((g) => g.items)) {
1401
- if (seen.has(it.label) && !warned.has(it.label)) {
1402
- warned.add(it.label);
1403
- console.warn(`AppShell: two pages are labelled "${it.label}"; give each its own name.`);
1404
- }
1405
- seen.add(it.label);
1406
- }
1407
- }
1408
- function AppShell({
1409
- nav,
1410
- sections,
1411
- activeSection,
1412
- page: pageOverride,
1413
- persistent = [],
1414
- home = "/",
1415
- account,
1416
- banner,
1417
- footer,
1227
+ function SignInFrame({
1228
+ title = "Sign in",
1229
+ lead,
1418
1230
  children,
1231
+ error,
1232
+ fineprint,
1233
+ brand,
1234
+ home,
1235
+ protocol: protocol2,
1236
+ back,
1237
+ art,
1238
+ caption,
1419
1239
  className
1420
1240
  }) {
1421
- const [open, setOpen] = useState(false);
1422
- const current = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
1423
- const groups = current ? [...current.groups, ...persistent] : [...nav ?? [], ...persistent];
1424
- warnDuplicateLabels(groups);
1425
- const tabs = current ? null : tabsFor(groups);
1426
- const page = activeItem(groups);
1427
- const place = useMemo(
1428
- () => ({
1429
- section: current ? current.title ?? current.label : void 0,
1430
- page: pageOverride ?? page?.label
1431
- }),
1432
- [current, page?.label, pageOverride]
1433
- );
1434
- const switcher = sections && current && sections.length > 1 ? /* @__PURE__ */ jsx(SectionSwitch, { sections, current, onNavigate: () => setOpen(false) }) : null;
1435
- return /* @__PURE__ */ jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxs(
1436
- "div",
1241
+ const homeHref = home ?? (protocol2 ? protocolSite(protocol2).pageHref : OCHK_IO);
1242
+ return /* @__PURE__ */ jsxs(
1243
+ "main",
1437
1244
  {
1438
- className: cn(
1439
- "min-h-dvh bg-background",
1440
- tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
1441
- className
1442
- ),
1245
+ id: "main-content",
1246
+ className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
1443
1247
  children: [
1444
- /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
1445
- /* @__PURE__ */ jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
1446
- /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
1447
- /* @__PURE__ */ jsx(
1448
- SheetTrigger,
1449
- {
1450
- className: cn(
1451
- "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
1452
- // The tab bar holds every page; the sheet is left for a footer.
1453
- tabs && !footer && "max-md:hidden"
1454
- ),
1455
- "aria-label": "Open navigation",
1456
- children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
1457
- }
1458
- ),
1459
- /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
1460
- /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
1461
- switcher,
1462
- /* @__PURE__ */ jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
1463
- footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
1464
- ] })
1248
+ /* @__PURE__ */ jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
1249
+ /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4", children: [
1250
+ /* @__PURE__ */ jsxs(Link, { href: homeHref, className: "w-fit rounded-lg", children: [
1251
+ brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
1252
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
1465
1253
  ] }),
1466
- /* @__PURE__ */ jsx(Link5, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
1467
- /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
1468
- ] }),
1469
- place.page ? /* @__PURE__ */ jsxs(
1470
- "div",
1471
- {
1472
- className: cn(
1473
- "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
1474
- // The active tab already names the page.
1475
- tabs && !pageOverride && "max-md:hidden"
1476
- ),
1477
- children: [
1478
- place.section ? /* @__PURE__ */ jsxs(Fragment, { children: [
1479
- /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1480
- /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
1481
- ] }) : null,
1482
- /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
1483
- ]
1484
- }
1485
- ) : null
1486
- ] }),
1487
- /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
1488
- /* @__PURE__ */ jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
1489
- /* @__PURE__ */ jsx(Link5, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
1490
- switcher,
1491
- /* @__PURE__ */ jsx(SideNav, { groups }),
1492
- /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
1254
+ back === void 0 ? /* @__PURE__ */ jsx(
1255
+ Link,
1256
+ {
1257
+ href: homeHref,
1258
+ className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
1259
+ children: "Back to home"
1260
+ }
1261
+ ) : back
1493
1262
  ] }),
1494
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
1495
- /* @__PURE__ */ jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
1496
- banner ? /* @__PURE__ */ jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
1497
- /* @__PURE__ */ jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
1263
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
1264
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
1265
+ /* @__PURE__ */ jsx("h1", { className: "oca-display-2", children: title }),
1266
+ lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead", children: lead }) : null
1267
+ ] }),
1268
+ /* @__PURE__ */ jsx("div", { children }),
1269
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
1270
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
1498
1271
  ] })
1499
1272
  ] }),
1500
- tabs ? /* @__PURE__ */ jsx(TabBar, { items: tabs }) : null
1273
+ /* @__PURE__ */ jsxs(
1274
+ "aside",
1275
+ {
1276
+ "aria-hidden": true,
1277
+ className: "relative hidden flex-col justify-between gap-10 overflow-hidden border-l border-[var(--oca-band-line)] bg-oca-ink p-14 text-oca-ink-foreground lg:flex",
1278
+ children: [
1279
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center", children: art ?? /* @__PURE__ */ jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) }),
1280
+ caption ? /* @__PURE__ */ jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
1281
+ ]
1282
+ }
1283
+ )
1501
1284
  ]
1502
1285
  }
1503
- ) });
1286
+ );
1504
1287
  }
1505
- function AccountMenu({
1506
- name,
1507
- detail,
1508
- items,
1509
- nameFrom = "sm"
1510
- }) {
1511
- const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
1512
- return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
1513
- /* @__PURE__ */ jsxs(
1514
- DropdownMenuTrigger,
1515
- {
1516
- className: cn(
1517
- "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
1518
- nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
1519
- ),
1520
- "aria-label": `${name}, account menu`,
1521
- children: [
1522
- /* @__PURE__ */ jsx(
1523
- "span",
1524
- {
1525
- "aria-hidden": true,
1526
- "data-initial": initial,
1527
- className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
1528
- }
1529
- ),
1530
- /* @__PURE__ */ jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
1531
- ]
1532
- }
1533
- ),
1534
- /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-64", children: [
1535
- /* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
1536
- /* @__PURE__ */ jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: name }),
1537
- detail ? /* @__PURE__ */ jsx("span", { className: "truncate font-mono text-[0.75rem]", children: detail }) : null
1538
- ] }),
1539
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1540
- items.map(
1541
- (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link5, { href: it.href, children: [
1542
- it.icon,
1543
- it.label
1544
- ] }) }, it.label) : /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
1545
- it.icon,
1546
- it.label
1547
- ] }, it.label)
1548
- )
1549
- ] })
1550
- ] });
1288
+ function Spinner({ className, label }) {
1289
+ return /* @__PURE__ */ jsxs(
1290
+ "svg",
1291
+ {
1292
+ viewBox: "0 0 24 24",
1293
+ fill: "none",
1294
+ role: label ? "status" : void 0,
1295
+ "aria-label": label,
1296
+ "aria-hidden": label ? void 0 : true,
1297
+ className: cn("size-4 animate-spin", className),
1298
+ children: [
1299
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeOpacity: "0.2", strokeWidth: "2.5" }),
1300
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })
1301
+ ]
1302
+ }
1303
+ );
1551
1304
  }
1552
- function ThemeToggle({ className }) {
1553
- const { theme, setTheme } = useTheme();
1554
- const [mounted, setMounted] = useState(false);
1555
- useEffect(() => setMounted(true), []);
1556
- const current = mounted ? theme ?? "system" : "system";
1557
- const next = current === "light" ? "dark" : current === "dark" ? "system" : "light";
1558
- const Icon = current === "light" ? Sun : current === "dark" ? Moon : SunMoon;
1305
+ forwardRef(function Separator3({ className, orientation = "horizontal", decorative = true, ...props }, ref) {
1559
1306
  return /* @__PURE__ */ jsx(
1560
- "button",
1307
+ SeparatorPrimitive.Root,
1561
1308
  {
1562
- type: "button",
1563
- onClick: () => setTheme(next),
1564
- "aria-label": `Theme: ${current}. Switch to ${next}`,
1565
- title: `Theme: ${current}`,
1309
+ ref,
1310
+ decorative,
1311
+ orientation,
1566
1312
  className: cn(
1567
- "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
1313
+ "shrink-0 bg-border",
1314
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
1568
1315
  className
1569
1316
  ),
1570
- children: /* @__PURE__ */ jsx(Icon, { className: "size-[1.125rem]" })
1317
+ ...props
1318
+ }
1319
+ );
1320
+ });
1321
+ var DensityContext = sharedContext("density", "comfortable");
1322
+ function DensityProvider({ density, children }) {
1323
+ return createElement(DensityContext.Provider, { value: density }, children);
1324
+ }
1325
+ var buttonVariants = cva(
1326
+ [
1327
+ "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
1328
+ "transition-[background-color,border-color,color,box-shadow,transform] duration-150",
1329
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1330
+ "active:translate-y-px disabled:pointer-events-none",
1331
+ // Disabled is one look for every variant: a quiet grey pill, never a
1332
+ // faded black or orange slab that reads as broken.
1333
+ "disabled:border disabled:border-border disabled:bg-muted disabled:text-oca-subtle disabled:shadow-none",
1334
+ "[&_svg]:pointer-events-none [&_svg]:size-[1.1em] [&_svg]:shrink-0"
1335
+ ],
1336
+ {
1337
+ variants: {
1338
+ variant: {
1339
+ primary: "bg-primary text-primary-foreground hover:bg-primary/85",
1340
+ secondary: "border border-border bg-secondary text-secondary-foreground hover:border-oca-hairline-strong hover:bg-accent",
1341
+ brand: "bg-brand text-brand-foreground hover:bg-oca-orange-deep",
1342
+ ghost: "text-foreground hover:bg-accent",
1343
+ danger: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
1344
+ link: "h-auto rounded-none px-0 text-foreground underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
1345
+ onInk: "bg-white text-oca-ink hover:bg-white/90",
1346
+ onInkOutline: "border border-white/20 text-white hover:bg-white/10"
1347
+ },
1348
+ size: {
1349
+ sm: "h-9 px-4 text-sm",
1350
+ md: "h-11 px-5 text-[0.9375rem]",
1351
+ lg: "h-14 px-7 text-[1.0625rem]",
1352
+ icon: "size-10",
1353
+ "icon-sm": "size-8"
1354
+ }
1355
+ },
1356
+ compoundVariants: [{ variant: "link", className: "h-auto px-0" }],
1357
+ defaultVariants: { variant: "primary", size: "md" }
1358
+ }
1359
+ );
1360
+ var Button = forwardRef(function Button2({ className, variant, size, asChild = false, loading = false, disabled, children, type, ...props }, ref) {
1361
+ const Comp = asChild ? Slot : "button";
1362
+ return /* @__PURE__ */ jsx(
1363
+ Comp,
1364
+ {
1365
+ ref,
1366
+ "data-ui": "button",
1367
+ className: cn(buttonVariants({ variant, size }), className),
1368
+ disabled: asChild ? void 0 : disabled || loading,
1369
+ "aria-busy": loading || void 0,
1370
+ type: asChild ? void 0 : type ?? "button",
1371
+ ...props,
1372
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
1373
+ loading ? /* @__PURE__ */ jsx(Spinner, { className: "size-[1.1em]" }) : null,
1374
+ children
1375
+ ] })
1571
1376
  }
1572
1377
  );
1378
+ });
1379
+ function useActiveHeading(ids) {
1380
+ const [active, setActive] = useState(ids[0]);
1381
+ const key = ids.join("|");
1382
+ useEffect(() => {
1383
+ setActive(key.split("|")[0] || void 0);
1384
+ const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
1385
+ if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
1386
+ const io = new IntersectionObserver(
1387
+ (entries) => {
1388
+ const hit = entries.filter((e) => e.isIntersecting).sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0];
1389
+ if (hit) setActive(hit.target.id);
1390
+ },
1391
+ { rootMargin: "-80px 0px -65% 0px" }
1392
+ );
1393
+ els.forEach((el) => io.observe(el));
1394
+ return () => io.disconnect();
1395
+ }, [key]);
1396
+ return active;
1397
+ }
1398
+ function useHeadings(selector = "#docs-content", key) {
1399
+ const [items, setItems] = useState([]);
1400
+ useEffect(() => {
1401
+ const read = () => {
1402
+ const root = document.querySelector(selector);
1403
+ if (!root) return setItems([]);
1404
+ setItems(
1405
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
1406
+ id: h.id,
1407
+ // The anchor link's "#" is not part of the name.
1408
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
1409
+ level: h.tagName === "H3" ? 3 : 2
1410
+ }))
1411
+ );
1412
+ };
1413
+ const raf = requestAnimationFrame(read);
1414
+ const t = setTimeout(read, 80);
1415
+ return () => {
1416
+ cancelAnimationFrame(raf);
1417
+ clearTimeout(t);
1418
+ };
1419
+ }, [selector, key]);
1420
+ const activeId = useActiveHeading(items.map((i) => i.id));
1421
+ return { items, activeId };
1422
+ }
1423
+ function OnThisPage({
1424
+ items,
1425
+ activeId,
1426
+ title = "On this page",
1427
+ onNavigate,
1428
+ className
1429
+ }) {
1430
+ const id = useId();
1431
+ if (items.length === 0) return null;
1432
+ return (
1433
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
1434
+ /* @__PURE__ */ jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
1435
+ title ? /* @__PURE__ */ jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
1436
+ /* @__PURE__ */ jsx("ul", { children: items.map((t) => {
1437
+ const on = t.id === activeId;
1438
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1439
+ "a",
1440
+ {
1441
+ href: `#${t.id}`,
1442
+ onClick: onNavigate,
1443
+ "aria-current": on ? "location" : void 0,
1444
+ className: cn(
1445
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
1446
+ t.level === 3 ? "pl-7" : "pl-4",
1447
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
1448
+ ),
1449
+ children: t.label
1450
+ }
1451
+ ) }, t.id);
1452
+ }) })
1453
+ ] })
1454
+ );
1455
+ }
1456
+ var InDocsContext = sharedContext("in-docs", false);
1457
+ var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
1458
+ var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
1459
+ function DocsNav({
1460
+ sections,
1461
+ current,
1462
+ onNavigate,
1463
+ className
1464
+ }) {
1465
+ const here = pathOf(current);
1466
+ const activeSection = useMemo(
1467
+ () => sections.findIndex((s) => s.items.some((i) => pathOf(i.href) === here)),
1468
+ [sections, here]
1469
+ );
1470
+ const [peeked, setPeeked] = useState(() => /* @__PURE__ */ new Set());
1471
+ useEffect(() => setPeeked(/* @__PURE__ */ new Set()), [activeSection]);
1472
+ const activeRef = useRef(null);
1473
+ useEffect(() => {
1474
+ const id = requestAnimationFrame(() => activeRef.current?.scrollIntoView({ block: "nearest" }));
1475
+ return () => cancelAnimationFrame(id);
1476
+ }, [here]);
1477
+ const base = useId();
1478
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Docs", className: cn("flex flex-col gap-0.5", className), children: sections.map((section, si) => {
1479
+ const isActive = si === activeSection;
1480
+ const open = isActive || peeked.has(si);
1481
+ const panel = `${base}-s${si}`;
1482
+ return /* @__PURE__ */ jsxs("div", { children: [
1483
+ /* @__PURE__ */ jsxs(
1484
+ "button",
1485
+ {
1486
+ type: "button",
1487
+ "aria-expanded": open,
1488
+ "aria-controls": panel,
1489
+ onClick: () => {
1490
+ if (isActive) return;
1491
+ setPeeked((p) => {
1492
+ const n = new Set(p);
1493
+ if (n.has(si)) n.delete(si);
1494
+ else n.add(si);
1495
+ return n;
1496
+ });
1497
+ },
1498
+ className: cn(
1499
+ "flex min-h-9 w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-[0.875rem] transition-colors",
1500
+ isActive ? "font-medium text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground",
1501
+ isActive && "cursor-default"
1502
+ ),
1503
+ children: [
1504
+ section.label,
1505
+ /* @__PURE__ */ jsx(
1506
+ ChevronRight,
1507
+ {
1508
+ "aria-hidden": true,
1509
+ className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
1510
+ }
1511
+ )
1512
+ ]
1513
+ }
1514
+ ),
1515
+ /* @__PURE__ */ jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
1516
+ const on = pathOf(item.href) === here;
1517
+ const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsx(Badge, { tone: "muted", children: item.badge }) : null;
1518
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1519
+ Link,
1520
+ {
1521
+ href: item.href,
1522
+ ref: on ? activeRef : void 0,
1523
+ onClick: onNavigate,
1524
+ "aria-current": on ? "page" : void 0,
1525
+ className: cn(
1526
+ "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
1527
+ on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
1528
+ ),
1529
+ children: [
1530
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: item.label }),
1531
+ badge
1532
+ ]
1533
+ }
1534
+ ) }, item.href);
1535
+ }) })
1536
+ ] }, section.label);
1537
+ }) });
1538
+ }
1539
+ var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
1540
+ function DocsShell({
1541
+ nav,
1542
+ current,
1543
+ navCurrent,
1544
+ header,
1545
+ search,
1546
+ actions,
1547
+ breadcrumbs,
1548
+ toc,
1549
+ pager,
1550
+ footer,
1551
+ children
1552
+ }) {
1553
+ const [menu, setMenu] = useState(false);
1554
+ useEffect(() => setMenu(false), [current]);
1555
+ const read = useHeadings("#docs-content", current);
1556
+ const items = toc ?? read.items;
1557
+ const activeId = toc ? void 0 : read.activeId;
1558
+ const marked = navCurrent ?? current;
1559
+ const here = pathOf(marked);
1560
+ const place = useMemo(() => {
1561
+ for (const s of nav) {
1562
+ const it = s.items.find((i) => pathOf(i.href) === here);
1563
+ if (it) return { section: s.label, page: it.label };
1564
+ }
1565
+ return null;
1566
+ }, [nav, here]);
1567
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
1568
+ /* @__PURE__ */ jsx(SkipLink, {}),
1569
+ header ?? /* @__PURE__ */ jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
1570
+ /* @__PURE__ */ jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
1571
+ /* @__PURE__ */ jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
1572
+ /* @__PURE__ */ jsx(PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
1573
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Docs menu. " }),
1574
+ place ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1575
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1576
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
1577
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
1578
+ ] }) : /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Docs" })
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
1581
+ /* @__PURE__ */ jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
1582
+ /* @__PURE__ */ jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current: marked, onNavigate: () => setMenu(false) }) })
1583
+ ] })
1584
+ ] }) }) }),
1585
+ /* @__PURE__ */ jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
1586
+ /* @__PURE__ */ jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current: marked }) }),
1587
+ /* @__PURE__ */ jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
1588
+ breadcrumbs ? /* @__PURE__ */ jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
1589
+ items.length > 1 ? /* @__PURE__ */ jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
1590
+ /* @__PURE__ */ jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
1591
+ "On this page",
1592
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1593
+ ] }),
1594
+ /* @__PURE__ */ jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
1595
+ ] }) : null,
1596
+ /* @__PURE__ */ jsx("article", { id: "docs-content", className: "max-w-[46rem]", children: /* @__PURE__ */ jsx(InDocsContext.Provider, { value: true, children }) }),
1597
+ pager ? /* @__PURE__ */ jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
1598
+ ] }),
1599
+ /* @__PURE__ */ jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsx(OnThisPage, { items, activeId }) : null })
1600
+ ] }) }),
1601
+ footer ?? /* @__PURE__ */ jsx(OchkIoFooter, {})
1602
+ ] });
1573
1603
  }
1604
+ var SiteHomeContext = sharedContext("site-home", void 0);
1574
1605
  var OCHK_APP_ACCOUNT = "https://ochk.app/me/account";
1575
1606
  function onHistory(change) {
1576
1607
  window.addEventListener("popstate", change);
@@ -1642,6 +1673,7 @@ function ToolShell({
1642
1673
  children
1643
1674
  }) {
1644
1675
  const p = protocolSite(protocol2);
1676
+ const homeHref = home ?? p.pageHref;
1645
1677
  const app = variant === "app";
1646
1678
  const tabs = app ? null : tabsFor([{ items: [...tools] }]);
1647
1679
  const about = /* @__PURE__ */ jsxs(
@@ -1671,7 +1703,7 @@ function ToolShell({
1671
1703
  SiteHeader,
1672
1704
  {
1673
1705
  variant: "tool",
1674
- home: home ?? p.pageHref,
1706
+ home: homeHref,
1675
1707
  product: p.label,
1676
1708
  family: protocol2,
1677
1709
  nav: tools.map((t) => ({ href: t.href, label: t.label, active: t.active })),
@@ -1696,7 +1728,7 @@ function ToolShell({
1696
1728
  {
1697
1729
  id: "main-content",
1698
1730
  className: cn("min-w-0 flex-1", app ? "flex min-h-0 flex-col" : "px-4 pb-16 pt-8 md:px-8 md:pt-10"),
1699
- children: app ? children : /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children })
1731
+ children: /* @__PURE__ */ jsx(SiteHomeContext.Provider, { value: homeHref, children: app ? children : /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
1700
1732
  }
1701
1733
  )
1702
1734
  ] }),
@@ -1707,6 +1739,6 @@ function ToolShell({
1707
1739
  ) });
1708
1740
  }
1709
1741
 
1710
- export { AccountMenu, AppShell, DOCS_HEADER_NAV, DocsNav, DocsShell, FamilyMenu, OCHK_APP_ACCOUNT, SessionAccountView, ShellContext, SignInFrame, SiteBanner, SiteFooter, SiteHeader, SkipLink, ThemeToggle, ToolShell, useShellPlace, useSignInHref };
1742
+ export { AccountMenu, AppShell, DOCS_HEADER_NAV, DocsNav, DocsShell, FamilyMenu, OCHK_APP_ACCOUNT, OchkIoFooter, SessionAccountView, ShellContext, SignInFrame, SiteBanner, SiteFooter, SiteHeader, SkipLink, ThemeToggle, ToolShell, useShellPlace, useSignInHref };
1711
1743
  //# sourceMappingURL=chrome.mjs.map
1712
1744
  //# sourceMappingURL=chrome.mjs.map