@orangecheck/app-design 0.6.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +4 -3
  2. package/dist/brand.js.map +1 -1
  3. package/dist/brand.mjs.map +1 -1
  4. package/dist/chrome.d.mts +49 -15
  5. package/dist/chrome.d.ts +49 -15
  6. package/dist/chrome.js +619 -55
  7. package/dist/chrome.js.map +1 -1
  8. package/dist/chrome.mjs +617 -57
  9. package/dist/chrome.mjs.map +1 -1
  10. package/dist/components.d.mts +231 -1
  11. package/dist/components.d.ts +231 -1
  12. package/dist/components.js +1187 -2
  13. package/dist/components.js.map +1 -1
  14. package/dist/components.mjs +1162 -5
  15. package/dist/components.mjs.map +1 -1
  16. package/dist/family.d.mts +2 -0
  17. package/dist/family.d.ts +2 -0
  18. package/dist/family.js +167 -0
  19. package/dist/family.js.map +1 -0
  20. package/dist/family.mjs +154 -0
  21. package/dist/family.mjs.map +1 -0
  22. package/dist/index-C6hDqOOS.d.mts +58 -0
  23. package/dist/index-C6hDqOOS.d.ts +58 -0
  24. package/dist/index.d.mts +5 -3
  25. package/dist/index.d.ts +5 -3
  26. package/dist/index.js +1619 -132
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +1575 -134
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/primitives.d.mts +52 -1
  31. package/dist/primitives.d.ts +52 -1
  32. package/dist/primitives.js +280 -3
  33. package/dist/primitives.js.map +1 -1
  34. package/dist/primitives.mjs +271 -6
  35. package/dist/primitives.mjs.map +1 -1
  36. package/dist/status-badge-BEOxeY9j.d.ts +13 -0
  37. package/dist/status-badge-DRwGhB0h.d.mts +13 -0
  38. package/dist/styles/fonts.css +1 -1
  39. package/dist/styles/tokens.css +4 -2
  40. package/dist/tokens.d.mts +3 -1
  41. package/dist/tokens.d.ts +3 -1
  42. package/dist/tokens.js +5 -3
  43. package/dist/tokens.js.map +1 -1
  44. package/dist/tokens.mjs +5 -3
  45. package/dist/tokens.mjs.map +1 -1
  46. package/package.json +9 -2
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Slot } from '@radix-ui/react-slot';
2
2
  import { cva } from 'class-variance-authority';
3
- import { forwardRef, createContext, useContext, useRef, useState, useCallback, useEffect, useId, isValidElement, cloneElement, createElement, Children, Component, useMemo } from 'react';
3
+ import { forwardRef, createContext, useContext, useRef, useState, useCallback, useEffect, useId, isValidElement, cloneElement, useSyncExternalStore, useMemo, createElement, Children, Component, Fragment as Fragment$1 } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { extendTailwindMerge } from 'tailwind-merge';
6
6
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
@@ -12,13 +12,14 @@ import * as LabelPrimitive from '@radix-ui/react-label';
12
12
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
13
13
  import * as SelectPrimitive from '@radix-ui/react-select';
14
14
  import * as SwitchPrimitive from '@radix-ui/react-switch';
15
- import { ChevronDown, Check, X, Copy, Menu, ChevronRight, Sun, Moon, SunMoon } from 'lucide-react';
15
+ import { ChevronDown, Check, X, ChevronLeft, ChevronRight, Copy, ArrowUpRight, Menu, Sun, Moon, SunMoon, CircleDashed, CircleMinus, Clock, CircleX, CircleCheck } from 'lucide-react';
16
16
  import * as DialogPrimitive from '@radix-ui/react-dialog';
17
17
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
18
18
  import * as PopoverPrimitive from '@radix-ui/react-popover';
19
19
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
20
20
  import * as TabsPrimitive from '@radix-ui/react-tabs';
21
- import Link2 from 'next/link';
21
+ import QRCode from 'qrcode';
22
+ import Link5 from 'next/link';
22
23
  import { useTheme } from 'next-themes';
23
24
 
24
25
  // src/tokens/index.ts
@@ -35,7 +36,8 @@ var appColors = {
35
36
  border: "#ECECEC",
36
37
  hairlineStrong: "#DADADA",
37
38
  accentDisplay: "#F55819",
38
- accentInk: "#C73F09"
39
+ accentInk: "#C73F09",
40
+ ring: "#EA580B"
39
41
  },
40
42
  dark: {
41
43
  background: "#0A0A0A",
@@ -44,10 +46,11 @@ var appColors = {
44
46
  muted: "#1E1E1E",
45
47
  mutedForeground: "#A3A6AA",
46
48
  subtleForeground: "#8B8E93",
47
- border: "#262626",
49
+ border: "#2A2A2A",
48
50
  hairlineStrong: "#333333",
49
51
  accentDisplay: "#F66D36",
50
- accentInk: "#F0835A"
52
+ accentInk: "#F0835A",
53
+ ring: "#F66D36"
51
54
  },
52
55
  brand: {
53
56
  orange: "#F66D36",
@@ -249,13 +252,13 @@ var badgeVariants = cva(
249
252
  tone: {
250
253
  neutral: "border-border bg-card text-foreground",
251
254
  muted: "border-transparent bg-muted text-muted-foreground",
252
- brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_12%,var(--card))] text-oca-accent-ink",
255
+ brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
253
256
  danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
254
257
  // A good state is a neutral pill with a green dot, not a green pill.
255
258
  success: GOOD_DOT,
256
259
  // Aliases kept so older call sites keep compiling: attention is
257
260
  // the brand accent, information is neutral.
258
- warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_12%,var(--card))] text-oca-accent-ink",
261
+ warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
259
262
  info: "border-border bg-card text-foreground",
260
263
  // Inverted in dark mode, where ink would sit on a card of nearly its own colour.
261
264
  ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
@@ -293,6 +296,30 @@ function StatusPill({
293
296
  }
294
297
  );
295
298
  }
299
+ var WORD = {
300
+ live: "Live",
301
+ testing: "In testing",
302
+ "not-yet": "Not yet",
303
+ paused: "Paused",
304
+ good: "Good",
305
+ caution: "Caution",
306
+ refused: "Refused"
307
+ };
308
+ var TONE = {
309
+ live: "success",
310
+ testing: "brand",
311
+ "not-yet": "muted",
312
+ paused: "muted",
313
+ good: "success",
314
+ caution: "brand",
315
+ refused: "danger"
316
+ };
317
+ function statusWord(status) {
318
+ return WORD[status];
319
+ }
320
+ function StatusBadge({ status, className, ...props }) {
321
+ return /* @__PURE__ */ jsx(Badge, { tone: TONE[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
322
+ }
296
323
  var cardVariants = cva("relative rounded-[1.25rem] border", {
297
324
  variants: {
298
325
  tone: {
@@ -476,7 +503,8 @@ var Switch = forwardRef(function Switch2({ className, ...props }, ref) {
476
503
  className: cn(
477
504
  "peer inline-flex h-6 w-11 shrink-0 items-center rounded-full border border-transparent bg-input p-0.5",
478
505
  "outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
479
- "data-[state=checked]:bg-brand disabled:cursor-not-allowed disabled:opacity-50",
506
+ // The deep orange: the track is the state, so it must clear 3:1 on a card.
507
+ "data-[state=checked]:bg-oca-orange-deep disabled:cursor-not-allowed disabled:opacity-50",
480
508
  className
481
509
  ),
482
510
  ...props,
@@ -768,6 +796,245 @@ var TabsTrigger = forwardRef(function TabsTrigger2({ className, ...props }, ref)
768
796
  var TabsContent = forwardRef(function TabsContent2({ className, ...props }, ref) {
769
797
  return /* @__PURE__ */ jsx(TabsPrimitive.Content, { ref, className: cn("mt-6 outline-none", className), ...props });
770
798
  });
799
+ var GroupName = createContext(void 0);
800
+ function Accordion({
801
+ single = false,
802
+ children,
803
+ className
804
+ }) {
805
+ const name = useId();
806
+ return /* @__PURE__ */ jsx(GroupName.Provider, { value: single ? name : void 0, children: /* @__PURE__ */ jsx("div", { className: cn("divide-y divide-border overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children }) });
807
+ }
808
+ function AccordionItem({
809
+ title,
810
+ children,
811
+ defaultOpen = false,
812
+ id,
813
+ className
814
+ }) {
815
+ const name = useContext(GroupName);
816
+ return /* @__PURE__ */ jsxs("details", { id, name, open: defaultOpen || void 0, className: cn("group scroll-mt-24", className), children: [
817
+ /* @__PURE__ */ jsxs(
818
+ "summary",
819
+ {
820
+ className: cn(
821
+ "flex min-h-14 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[1rem] font-medium leading-snug md:px-6",
822
+ // Inside the card's clip, so the ring is drawn within the row.
823
+ "transition-colors hover:bg-accent/60 focus-visible:outline-offset-[-2px] [&::-webkit-details-marker]:hidden"
824
+ ),
825
+ children: [
826
+ title,
827
+ /* @__PURE__ */ jsx(
828
+ ChevronDown,
829
+ {
830
+ "aria-hidden": true,
831
+ className: "size-4 shrink-0 text-muted-foreground transition-transform duration-200 group-open:rotate-180"
832
+ }
833
+ )
834
+ ]
835
+ }
836
+ ),
837
+ /* @__PURE__ */ jsx("div", { className: "oca-body px-5 pb-5 text-[0.9375rem] md:px-6 md:pb-6", children })
838
+ ] });
839
+ }
840
+ var queue = [];
841
+ var asked = 0;
842
+ var hosts = 0;
843
+ var listeners = /* @__PURE__ */ new Set();
844
+ var emit = () => listeners.forEach((l) => l());
845
+ function ask(item) {
846
+ queue = [...queue, { ...item, id: ++asked }];
847
+ emit();
848
+ }
849
+ function done() {
850
+ queue = queue.slice(1);
851
+ emit();
852
+ }
853
+ function confirm(options) {
854
+ if (hosts === 0) {
855
+ console.error("confirm(): no <DialogHost /> is mounted, so nothing was asked; treating it as no.");
856
+ return Promise.resolve(false);
857
+ }
858
+ return new Promise((resolve) => ask({ id: 0, kind: "confirm", options, settle: resolve }));
859
+ }
860
+ function prompt(options) {
861
+ if (hosts === 0) {
862
+ console.error("prompt(): no <DialogHost /> is mounted, so nothing was asked; treating it as cancelled.");
863
+ return Promise.resolve(null);
864
+ }
865
+ return new Promise((resolve) => ask({ id: 0, kind: "prompt", options, settle: resolve }));
866
+ }
867
+ function subscribe(listener) {
868
+ listeners.add(listener);
869
+ hosts++;
870
+ return () => {
871
+ listeners.delete(listener);
872
+ hosts--;
873
+ };
874
+ }
875
+ var current = () => queue[0] ?? null;
876
+ var none = () => null;
877
+ function PromptBody({ ask: a }) {
878
+ const o = a.options;
879
+ const [value, setValue] = useState(o.defaultValue ?? "");
880
+ const [error, setError] = useState(null);
881
+ const submit = (e) => {
882
+ e.preventDefault();
883
+ if (o.minLength && value.length < o.minLength) {
884
+ setError(`At least ${o.minLength} characters.`);
885
+ return;
886
+ }
887
+ const refused = o.validate?.(value);
888
+ if (refused) {
889
+ setError(refused);
890
+ return;
891
+ }
892
+ a.settle(value);
893
+ done();
894
+ };
895
+ return /* @__PURE__ */ jsxs("form", { onSubmit: submit, noValidate: true, children: [
896
+ /* @__PURE__ */ jsx(Field, { label: o.label ?? "Your answer", hint: o.hint, error, children: /* @__PURE__ */ jsx(
897
+ Input,
898
+ {
899
+ autoFocus: true,
900
+ type: o.secret ? "password" : "text",
901
+ autoComplete: o.secret ? "new-password" : "off",
902
+ placeholder: o.placeholder,
903
+ value,
904
+ onChange: (e) => {
905
+ setValue(e.target.value);
906
+ setError(null);
907
+ }
908
+ }
909
+ ) }),
910
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
911
+ /* @__PURE__ */ jsx(
912
+ Button,
913
+ {
914
+ variant: "secondary",
915
+ onClick: () => {
916
+ a.settle(null);
917
+ done();
918
+ },
919
+ children: o.cancelLabel ?? "Cancel"
920
+ }
921
+ ),
922
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: o.destructive ? "danger" : "primary", children: o.confirmLabel ?? "Continue" })
923
+ ] })
924
+ ] });
925
+ }
926
+ function DialogHost() {
927
+ const a = useSyncExternalStore(subscribe, current, none);
928
+ const cancel = () => {
929
+ if (!a) return;
930
+ if (a.kind === "confirm") a.settle(false);
931
+ else a.settle(null);
932
+ done();
933
+ };
934
+ return /* @__PURE__ */ jsx(Dialog, { open: a !== null, onOpenChange: (open) => open ? void 0 : cancel(), children: a ? /* @__PURE__ */ jsxs(
935
+ DialogContent,
936
+ {
937
+ role: "alertdialog",
938
+ ...a.options.message ? {} : { "aria-describedby": void 0 },
939
+ className: "w-[min(92vw,28rem)]",
940
+ children: [
941
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
942
+ /* @__PURE__ */ jsx(DialogTitle, { children: a.options.title }),
943
+ a.options.message ? /* @__PURE__ */ jsx(DialogDescription, { children: a.options.message }) : null
944
+ ] }),
945
+ a.kind === "prompt" ? (
946
+ // Keyed by the ask, so a second prompt starts empty.
947
+ /* @__PURE__ */ jsx(PromptBody, { ask: a }, a.id)
948
+ ) : /* @__PURE__ */ jsxs(DialogFooter, { children: [
949
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: cancel, children: a.options.cancelLabel ?? "Cancel" }),
950
+ /* @__PURE__ */ jsx(
951
+ Button,
952
+ {
953
+ variant: a.options.destructive ? "danger" : "primary",
954
+ onClick: () => {
955
+ a.settle(true);
956
+ done();
957
+ },
958
+ children: a.options.confirmLabel ?? "Continue"
959
+ }
960
+ )
961
+ ] })
962
+ ]
963
+ }
964
+ ) : null });
965
+ }
966
+ var N = new Intl.NumberFormat("en-US");
967
+ function Pagination({
968
+ pageIndex,
969
+ pageSize,
970
+ total,
971
+ onPage,
972
+ label = "Pages",
973
+ className
974
+ }) {
975
+ const pages = Math.max(1, Math.ceil(total / pageSize));
976
+ const index = Math.min(Math.max(0, pageIndex), pages - 1);
977
+ if (index !== pageIndex && typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
978
+ console.warn(`Pagination: pageIndex ${pageIndex} is outside 0\u2013${pages - 1}; it counts from 0.`);
979
+ }
980
+ if (total <= pageSize) return null;
981
+ const from = index * pageSize + 1;
982
+ const to = Math.min(total, (index + 1) * pageSize);
983
+ return /* @__PURE__ */ jsxs("nav", { "aria-label": label, className: cn("flex items-center justify-between gap-4", className), children: [
984
+ /* @__PURE__ */ jsxs("p", { "aria-live": "polite", className: "oca-tabular text-[0.875rem] text-muted-foreground", children: [
985
+ N.format(from),
986
+ "\u2013",
987
+ N.format(to),
988
+ " of ",
989
+ N.format(total)
990
+ ] }),
991
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
992
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "sm", disabled: index === 0, onClick: () => onPage(index - 1), className: "pl-3", children: [
993
+ /* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": true }),
994
+ "Previous"
995
+ ] }),
996
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "sm", disabled: index >= pages - 1, onClick: () => onPage(index + 1), className: "pr-3", children: [
997
+ "Next",
998
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true })
999
+ ] })
1000
+ ] })
1001
+ ] });
1002
+ }
1003
+ function QrCode({
1004
+ value,
1005
+ size = 200,
1006
+ label,
1007
+ className
1008
+ }) {
1009
+ const matrix = useMemo(() => {
1010
+ try {
1011
+ return QRCode.create(value, { errorCorrectionLevel: "M" }).modules;
1012
+ } catch {
1013
+ return null;
1014
+ }
1015
+ }, [value]);
1016
+ const path = useMemo(() => {
1017
+ if (!matrix) return "";
1018
+ let d = "";
1019
+ for (let y = 0; y < matrix.size; y++) {
1020
+ for (let x = 0; x < matrix.size; x++) {
1021
+ if (matrix.get(y, x)) d += `M${x} ${y}h1v1h-1z`;
1022
+ }
1023
+ }
1024
+ return d;
1025
+ }, [matrix]);
1026
+ const short = value.length > 28 ? `${value.slice(0, 28)}\u2026` : value;
1027
+ return /* @__PURE__ */ jsx(
1028
+ "div",
1029
+ {
1030
+ role: "img",
1031
+ "aria-label": matrix ? label ?? `QR code for ${short}` : "Too long for a QR code",
1032
+ className: cn("inline-block shrink-0 rounded-2xl bg-white p-3 ring-1 ring-border", className),
1033
+ style: { width: size, height: size },
1034
+ children: matrix ? /* @__PURE__ */ jsx("svg", { viewBox: `0 0 ${matrix.size} ${matrix.size}`, shapeRendering: "crispEdges", "aria-hidden": true, className: "block size-full", children: /* @__PURE__ */ jsx("path", { d: path, fill: "#0a0a0a" }) }) : /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex size-full items-center justify-center text-center text-[0.8125rem] text-[#54585e]", children: "Too long for a QR code" })
1035
+ }
1036
+ );
1037
+ }
771
1038
  var TOP = "0,3 2,2 6,4 14,0 16,1 6,6";
772
1039
  var LEFT = "0,3 6,6 6,8 0,5";
773
1040
  var RIGHT = "6,6 16,1 16,3 6,8";
@@ -792,6 +1059,20 @@ function Mark({ title, size, className, ...rest }) {
792
1059
  }
793
1060
  );
794
1061
  }
1062
+ function MarkOutline({ className }) {
1063
+ return /* @__PURE__ */ jsx("svg", { viewBox: "-0.2 -0.2 16.4 8.4", "aria-hidden": true, className: cn("shrink-0 overflow-visible", className), children: [TOP, LEFT, RIGHT].map((points) => /* @__PURE__ */ jsx(
1064
+ "polygon",
1065
+ {
1066
+ points,
1067
+ fill: "none",
1068
+ stroke: "currentColor",
1069
+ strokeWidth: "1",
1070
+ strokeLinejoin: "round",
1071
+ vectorEffect: "non-scaling-stroke"
1072
+ },
1073
+ points
1074
+ )) });
1075
+ }
795
1076
  function AppIcon({ title, size = 32, className, ...rest }) {
796
1077
  return /* @__PURE__ */ jsxs(
797
1078
  "svg",
@@ -2116,7 +2397,7 @@ var LABEL = {
2116
2397
  "not-yet": "Not yet",
2117
2398
  no: "No"
2118
2399
  };
2119
- var TONE = {
2400
+ var TONE2 = {
2120
2401
  yes: "text-oca-accent-ink",
2121
2402
  testing: "text-foreground",
2122
2403
  "not-yet": "text-muted-foreground",
@@ -2137,7 +2418,7 @@ function TruthTable({
2137
2418
  className
2138
2419
  ),
2139
2420
  children: rows.map((r, i) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-1.5 px-4 py-3.5", children: [
2140
- /* @__PURE__ */ jsx("span", { className: cn("text-[0.875rem] font-medium", TONE[r.status]), children: LABEL[r.status] }),
2421
+ /* @__PURE__ */ jsx("span", { className: cn("text-[0.875rem] font-medium", TONE2[r.status]), children: LABEL[r.status] }),
2141
2422
  /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] leading-relaxed", children: r.what })
2142
2423
  ] }, i))
2143
2424
  }
@@ -2154,7 +2435,7 @@ function TruthTable({
2154
2435
  className: cn(
2155
2436
  "border-t border-oca-hairline-strong px-4 py-3 font-medium",
2156
2437
  i === 0 && "border-t-0",
2157
- TONE[r.status]
2438
+ TONE2[r.status]
2158
2439
  ),
2159
2440
  children: LABEL[r.status]
2160
2441
  }
@@ -2413,126 +2694,1286 @@ var ErrorBoundary = class extends Component {
2413
2694
  ) });
2414
2695
  }
2415
2696
  };
2416
- function NavLink({ item, className, onNavigate }) {
2417
- const cls = cn(
2418
- "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
2419
- item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
2420
- className
2421
- );
2422
- if (item.external) {
2423
- return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
2697
+ var WORDS = {
2698
+ 404: {
2699
+ name: "Not found",
2700
+ title: "This page isn\u2019t here.",
2701
+ detail: "The link may be old, or the address mistyped."
2702
+ },
2703
+ 500: {
2704
+ name: "Server error",
2705
+ title: "Something broke on our side.",
2706
+ detail: "Try again in a moment."
2424
2707
  }
2425
- return /* @__PURE__ */ jsx(Link2, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
2426
- }
2427
- function SiteHeader({
2428
- home = "/",
2429
- brand,
2430
- nav = [],
2708
+ };
2709
+ function ErrorPage({
2710
+ code = 404,
2711
+ title,
2712
+ detail,
2431
2713
  actions,
2714
+ home = "/",
2715
+ art,
2432
2716
  className
2433
2717
  }) {
2434
- const [open, setOpen] = useState(false);
2435
- return /* @__PURE__ */ jsx(
2436
- "header",
2718
+ const words = WORDS[code] ?? (code >= 500 ? WORDS[500] : WORDS[404]);
2719
+ const server = code >= 500;
2720
+ return /* @__PURE__ */ jsx(Section, { space: "none", className: cn("flex min-h-[min(40rem,72dvh)] items-center py-16 md:py-24", className), children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
2721
+ /* @__PURE__ */ jsxs("div", { className: "flex max-w-[40rem] flex-col items-start gap-6 md:col-span-7", children: [
2722
+ /* @__PURE__ */ jsxs("p", { className: "oca-eyebrow oca-enter", children: [
2723
+ /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: code }),
2724
+ " \xB7 ",
2725
+ WORDS[code]?.name ?? (server ? "Error" : "Not available")
2726
+ ] }),
2727
+ /* @__PURE__ */ jsx("h1", { className: "oca-display-2 oca-enter [--enter-delay:70ms]", children: title ?? words.title }),
2728
+ /* @__PURE__ */ jsx("p", { className: "oca-lead oca-enter [--enter-delay:150ms]", children: detail ?? words.detail }),
2729
+ /* @__PURE__ */ jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions ?? /* @__PURE__ */ jsxs(Fragment, { children: [
2730
+ server ? /* @__PURE__ */ jsx(Button, { onClick: () => window.location.reload(), children: "Try again" }) : null,
2731
+ /* @__PURE__ */ jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsx(Link5, { href: home, children: "Go home" }) })
2732
+ ] }) })
2733
+ ] }),
2734
+ art !== null ? /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "oca-enter hidden justify-center md:col-span-5 md:flex [--enter-delay:120ms]", children: art ?? /* @__PURE__ */ jsx(MarkOutline, { className: "w-full max-w-[20rem] text-oca-hairline-strong" }) }) : null
2735
+ ] }) });
2736
+ }
2737
+ function SectionHeading({
2738
+ eyebrow,
2739
+ title,
2740
+ lead,
2741
+ id,
2742
+ onInk = false,
2743
+ level = 2,
2744
+ as = "h2",
2745
+ align = "start",
2746
+ reveal = true,
2747
+ className
2748
+ }) {
2749
+ return /* @__PURE__ */ jsxs(SectionIntro, { align, reveal, className: cn("max-w-3xl gap-4 md:gap-4", className), children: [
2750
+ eyebrow ? /* @__PURE__ */ jsx(Eyebrow, { onInk, children: eyebrow }) : null,
2751
+ /* @__PURE__ */ jsx(Display, { level, as, id, className: "scroll-mt-24", children: title }),
2752
+ lead ? /* @__PURE__ */ jsx("p", { className: cn("oca-lead", onInk && "text-oca-ink-muted"), children: lead }) : null
2753
+ ] });
2754
+ }
2755
+ function FactBlock({
2756
+ id,
2757
+ title,
2758
+ description,
2759
+ aside,
2760
+ children,
2761
+ className
2762
+ }) {
2763
+ return /* @__PURE__ */ jsxs("section", { id, className: cn("flex scroll-mt-24 flex-col gap-6", className), children: [
2764
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-end md:justify-between md:gap-8", children: [
2765
+ /* @__PURE__ */ jsxs("div", { className: "flex max-w-[44rem] flex-col gap-3", children: [
2766
+ /* @__PURE__ */ jsx("h2", { className: "oca-display-3", children: title }),
2767
+ description ? /* @__PURE__ */ jsx("div", { className: "oca-body text-[1.0625rem]", children: description }) : null
2768
+ ] }),
2769
+ aside ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-wrap gap-x-5 gap-y-2 text-[0.9375rem]", children: aside }) : null
2770
+ ] }),
2771
+ children
2772
+ ] });
2773
+ }
2774
+ function FactRows({
2775
+ rows,
2776
+ columns = 1,
2777
+ label,
2778
+ className
2779
+ }) {
2780
+ return /* @__PURE__ */ jsx("ul", { "aria-label": label, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: rows.map((r) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-5 px-5 py-6 md:px-8 md:py-7", children: [
2781
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-x-6", children: [
2782
+ /* @__PURE__ */ jsx("h3", { className: "oca-title min-w-0 text-pretty", children: r.title }),
2783
+ r.figure ? /* @__PURE__ */ jsx("span", { className: "oca-tabular shrink-0 whitespace-nowrap text-[1.75rem] leading-none tracking-[-0.02em]", children: r.figure }) : null
2784
+ ] }),
2785
+ /* @__PURE__ */ jsx("dl", { className: columns === 2 ? "grid grid-cols-1 gap-x-10 gap-y-4 md:grid-cols-2" : "flex flex-col gap-4", children: r.fields.map((f, i) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
2786
+ /* @__PURE__ */ jsx("dt", { className: "text-[0.875rem] font-medium text-muted-foreground", children: f.label }),
2787
+ /* @__PURE__ */ jsx("dd", { className: "break-words text-[1rem] leading-relaxed", children: f.value })
2788
+ ] }, i)) })
2789
+ ] }, r.key)) });
2790
+ }
2791
+ function EndpointList({ items, label, className }) {
2792
+ return /* @__PURE__ */ jsx("ul", { "aria-label": label, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: items.map((a) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
2793
+ "a",
2437
2794
  {
2438
- className: cn(
2439
- "sticky top-0 z-40 w-full border-b border-transparent bg-background/85 backdrop-blur-md supports-[backdrop-filter]:bg-background/70",
2440
- className
2441
- ),
2442
- children: /* @__PURE__ */ jsxs(
2443
- "div",
2444
- {
2445
- className: cn(
2446
- "oca-container flex h-16 items-center justify-between gap-4 md:h-[4.5rem]",
2447
- // Three columns, the outer two each at least their content: the
2448
- // navigation stays centred whatever the actions hold, so it does
2449
- // not shift when they change (signed out to signed in).
2450
- nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
2451
- ),
2452
- children: [
2453
- /* @__PURE__ */ jsxs(Link2, { href: home, className: "-ml-1 justify-self-start rounded-lg p-1", children: [
2454
- brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
2455
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
2456
- ] }),
2457
- nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => /* @__PURE__ */ jsx(NavLink, { item: n }, n.href)) }) : null,
2458
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
2459
- actions,
2460
- nav.length > 0 ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
2461
- /* @__PURE__ */ jsx(
2462
- SheetTrigger,
2463
- {
2464
- className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
2465
- "aria-label": "Open menu",
2466
- children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
2467
- }
2468
- ),
2469
- /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
2470
- /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
2471
- /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map((n) => /* @__PURE__ */ jsx(
2472
- NavLink,
2473
- {
2474
- item: n,
2475
- className: "rounded-xl px-3 py-3 text-[1.0625rem]",
2476
- onNavigate: () => setOpen(false)
2477
- },
2478
- n.href
2479
- )) })
2480
- ] })
2481
- ] }) : null
2482
- ] })
2483
- ]
2484
- }
2485
- )
2795
+ href: a.href,
2796
+ target: "_blank",
2797
+ rel: "noreferrer",
2798
+ className: "flex flex-col gap-1 px-5 py-3.5 transition-colors hover:bg-accent/60 sm:flex-row sm:items-baseline sm:justify-between sm:gap-6",
2799
+ children: [
2800
+ /* @__PURE__ */ jsx("code", { className: "break-all text-[0.875rem] text-foreground", children: a.label ?? a.href }),
2801
+ /* @__PURE__ */ jsxs("span", { className: "text-[0.875rem] text-muted-foreground sm:text-right", children: [
2802
+ a.description,
2803
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens in a new tab)" })
2804
+ ] })
2805
+ ]
2486
2806
  }
2487
- );
2807
+ ) }, a.href)) });
2488
2808
  }
2489
- function SiteFooter({
2490
- columns = [],
2491
- fineprint,
2492
- meta,
2493
- signature = true,
2809
+ function ProofStrip({ items, className }) {
2810
+ return /* @__PURE__ */ jsx("div", { className: cn("border-y border-border", className), children: /* @__PURE__ */ jsx("ul", { className: "oca-container grid grid-cols-2 gap-x-6 gap-y-4 py-6 md:grid-cols-4", children: items.map((it, i) => /* @__PURE__ */ jsxs(
2811
+ "li",
2812
+ {
2813
+ className: "flex items-center gap-3 text-[0.9375rem] [&_svg]:size-[1.1rem] [&_svg]:shrink-0 [&_svg]:text-oca-accent-ink",
2814
+ children: [
2815
+ it.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "flex", children: it.icon }) : null,
2816
+ it.label
2817
+ ]
2818
+ },
2819
+ i
2820
+ )) }) });
2821
+ }
2822
+ function Closing({
2823
+ title,
2824
+ lead,
2825
+ actions,
2826
+ art,
2494
2827
  className
2495
2828
  }) {
2496
- return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
2497
- /* @__PURE__ */ jsxs("div", { className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[1.3fr_repeat(3,1fr)] md:py-16", children: [
2498
- /* @__PURE__ */ jsxs("div", { className: "col-span-2 flex flex-col gap-4 md:col-span-1", children: [
2499
- /* @__PURE__ */ jsx(Lockup, { size: 26 }),
2500
- fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
2829
+ return /* @__PURE__ */ jsx(Section, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
2830
+ /* @__PURE__ */ jsxs(Reveal, { className: "flex flex-col items-start gap-8 md:col-span-7", children: [
2831
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5", children: [
2832
+ /* @__PURE__ */ jsx("h2", { className: "oca-display-1 text-[clamp(2.5rem,1.5rem+4vw,5rem)] leading-[1]", children: title }),
2833
+ lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead max-w-[34rem]", children: lead }) : null
2501
2834
  ] }),
2502
- columns.map((col, i) => {
2503
- const spans = columns.length % 2 === 1 && i === columns.length - 1;
2504
- return /* @__PURE__ */ jsxs(
2505
- "div",
2506
- {
2507
- className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
2508
- children: [
2509
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
2510
- /* @__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(
2511
- NavLink,
2512
- {
2513
- item: l,
2514
- className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
2515
- },
2516
- l.href
2517
- )) })
2518
- ]
2519
- },
2520
- col.heading
2521
- );
2522
- })
2835
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3", children: actions }) : null
2523
2836
  ] }),
2524
- 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: [
2525
- /* @__PURE__ */ jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsx(Mark, { className: "block h-auto w-full" }) }),
2526
- /* @__PURE__ */ jsx("span", { children: "orangecheck" })
2527
- ] }) }) : null,
2528
- meta ? /* @__PURE__ */ jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsx("div", { className: "border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: meta }) }) : null
2837
+ art !== null ? (
2838
+ // Room under the check on a phone, so its glow fades before the band ends.
2839
+ /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex justify-center max-md:pb-16 md:col-span-5", children: art ?? /* @__PURE__ */ jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) })
2840
+ ) : null
2841
+ ] }) });
2842
+ }
2843
+ function Faq({
2844
+ items,
2845
+ className
2846
+ }) {
2847
+ return /* @__PURE__ */ jsx(Accordion, { single: true, className, children: items.map((it, i) => /* @__PURE__ */ jsx(AccordionItem, { id: it.id, title: it.q, children: it.a }, it.id ?? i)) });
2848
+ }
2849
+ var LINK = "text-foreground underline decoration-foreground/35 underline-offset-4 transition-colors hover:decoration-foreground";
2850
+ function TextLink({
2851
+ href,
2852
+ children,
2853
+ external,
2854
+ className
2855
+ }) {
2856
+ const internal = href.startsWith("/") && !href.startsWith("/api/") && !href.startsWith("/.well-known/");
2857
+ const offsite = external ?? /^https?:\/\//.test(href);
2858
+ if (internal && !offsite) {
2859
+ return /* @__PURE__ */ jsx(Link5, { href, className: cn(LINK, className), children });
2860
+ }
2861
+ return /* @__PURE__ */ jsxs("a", { href, className: cn(LINK, className), ...offsite ? { target: "_blank", rel: "noreferrer" } : {}, children: [
2862
+ children,
2863
+ offsite ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens in a new tab)" }) : null
2529
2864
  ] });
2530
2865
  }
2866
+ var PROPER = {
2867
+ kyc: "KYC",
2868
+ pii: "PII",
2869
+ ccpa: "CCPA",
2870
+ cpra: "CPRA",
2871
+ gdpr: "GDPR",
2872
+ uk: "UK",
2873
+ eu: "EU",
2874
+ california: "California",
2875
+ europe: "Europe",
2876
+ united: "United",
2877
+ kingdom: "Kingdom"
2878
+ };
2879
+ function headingCase(text) {
2880
+ const words = text.replace(/\b[a-z]+\b/g, (w) => PROPER[w] ?? w);
2881
+ if (/^orangecheck\b/.test(words)) return `OrangeCheck${words.slice("orangecheck".length)}`;
2882
+ return words.length === 0 ? words : words[0].toUpperCase() + words.slice(1);
2883
+ }
2884
+ function sentencesCase(text) {
2885
+ return text.split(/(?<=[.!?])\s+/).map((s) => headingCase(s)).join(" ");
2886
+ }
2887
+ function openSentence(text) {
2888
+ const first = /^\S+/.exec(text)?.[0] ?? "";
2889
+ if (!/^[a-z][a-z'’-]*,?$/.test(first)) return text;
2890
+ return text[0].toUpperCase() + text.slice(1);
2891
+ }
2892
+ var INLINE = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/g;
2893
+ var LINK2 = /^\[([^\]]+)\]\(([^)]+)\)$/;
2894
+ function Inline({ text }) {
2895
+ return /* @__PURE__ */ jsx(Fragment, { children: text.split(INLINE).map((part, i) => {
2896
+ if (!part) return null;
2897
+ if (part.startsWith("**") && part.endsWith("**") && part.length > 4) {
2898
+ return /* @__PURE__ */ jsx("strong", { children: /* @__PURE__ */ jsx(Inline, { text: part.slice(2, -2) }) }, i);
2899
+ }
2900
+ if (part.startsWith("`") && part.endsWith("`") && part.length > 2) return /* @__PURE__ */ jsx("code", { children: part.slice(1, -1) }, i);
2901
+ const link = LINK2.exec(part);
2902
+ if (link) {
2903
+ return /* @__PURE__ */ jsx(TextLink, { href: link[2] ?? "", children: link[1] }, i);
2904
+ }
2905
+ return /* @__PURE__ */ jsx(Fragment$1, { children: part }, i);
2906
+ }) });
2907
+ }
2908
+ function BlockView({ block }) {
2909
+ switch (block.kind) {
2910
+ case "para":
2911
+ return /* @__PURE__ */ jsx(Fragment, { children: block.text.split(/\n{2,}/).map((para, i) => /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(Inline, { text: para }) }, i)) });
2912
+ case "subhead":
2913
+ return /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsx(Inline, { text: headingCase(block.text) }) });
2914
+ case "bullets":
2915
+ return /* @__PURE__ */ jsx("ul", { children: block.items.map(
2916
+ (item, i) => typeof item === "string" ? /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Inline, { text: item }) }, i) : /* @__PURE__ */ jsxs("li", { children: [
2917
+ /* @__PURE__ */ jsxs("strong", { children: [
2918
+ headingCase(item.k),
2919
+ "."
2920
+ ] }),
2921
+ " ",
2922
+ /* @__PURE__ */ jsx(Inline, { text: openSentence(item.v) })
2923
+ ] }, i)
2924
+ ) });
2925
+ case "callout":
2926
+ return /* @__PURE__ */ jsx("div", { className: "not-prose my-6", children: /* @__PURE__ */ jsx(Notice, { tone: block.emphatic ? "brand" : "neutral", children: /* @__PURE__ */ jsx(Inline, { text: block.text }) }) });
2927
+ case "stub":
2928
+ return /* @__PURE__ */ jsx("div", { className: "not-prose my-6", children: /* @__PURE__ */ jsx(Notice, { tone: "brand", title: "Pending counsel review", children: /* @__PURE__ */ jsx(Inline, { text: block.text }) }) });
2929
+ }
2930
+ }
2931
+ function LegalDocument({ doc, className }) {
2932
+ return /* @__PURE__ */ jsx(
2933
+ DocLayout,
2934
+ {
2935
+ className,
2936
+ header: /* @__PURE__ */ jsx(
2937
+ DocHeader,
2938
+ {
2939
+ eyebrow: headingCase(doc.eyebrow),
2940
+ title: doc.title,
2941
+ lead: doc.description,
2942
+ meta: `Effective ${doc.effective} \xB7 last updated ${doc.updated}`
2943
+ }
2944
+ ),
2945
+ toc: doc.sections.map((s) => ({ id: s.id, label: headingCase(s.heading) })),
2946
+ children: /* @__PURE__ */ jsx("article", { className: "min-w-0", children: /* @__PURE__ */ jsxs(Prose, { children: [
2947
+ doc.preamble?.map((b, i) => /* @__PURE__ */ jsx(BlockView, { block: b }, i)),
2948
+ doc.sections.map((s) => /* @__PURE__ */ jsxs("section", { children: [
2949
+ /* @__PURE__ */ jsxs("h2", { id: s.id, className: "scroll-mt-24", children: [
2950
+ s.num ? /* @__PURE__ */ jsxs("span", { className: "oca-tabular text-muted-foreground", children: [
2951
+ s.num,
2952
+ " "
2953
+ ] }) : null,
2954
+ headingCase(s.heading)
2955
+ ] }),
2956
+ s.hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem]", children: headingCase(s.hint) }) : null,
2957
+ s.blocks.map((b, i) => /* @__PURE__ */ jsx(BlockView, { block: b }, i))
2958
+ ] }, s.id)),
2959
+ doc.summary ? /* @__PURE__ */ jsxs("p", { className: "mt-14 border-t border-border pt-6 text-[0.9375rem]", children: [
2960
+ /* @__PURE__ */ jsx("strong", { children: "In short." }),
2961
+ " ",
2962
+ sentencesCase(doc.summary.replace(/^summary:\s*/i, ""))
2963
+ ] }) : null
2964
+ ] }) })
2965
+ }
2966
+ );
2967
+ }
2968
+
2969
+ // src/family/index.ts
2970
+ var OCHK_IO = "https://ochk.io";
2971
+ var DOCS_HREF = `${OCHK_IO}/docs`;
2972
+ function protocol(slug, verb, line, kinds) {
2973
+ return {
2974
+ slug,
2975
+ label: slug,
2976
+ href: `${OCHK_IO}/${slug}`,
2977
+ group: "protocol",
2978
+ line,
2979
+ status: "live",
2980
+ verb,
2981
+ pageHref: `${OCHK_IO}/${slug}`,
2982
+ toolHref: `https://${slug}.ochk.io`,
2983
+ specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
2984
+ kinds
2985
+ };
2986
+ }
2987
+ var PROTOCOLS = [
2988
+ protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
2989
+ protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
2990
+ protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
2991
+ protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
2992
+ protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
2993
+ protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
2994
+ ];
2995
+ var PROTOCOL_ORDER = PROTOCOLS.map((p) => p.slug);
2996
+ var FAMILY = [
2997
+ {
2998
+ slug: "home",
2999
+ label: "ochk.io",
3000
+ href: OCHK_IO,
3001
+ group: "orangecheck",
3002
+ line: "The open protocols, and the company behind them.",
3003
+ status: "live"
3004
+ },
3005
+ {
3006
+ slug: "me",
3007
+ label: "ochk.app",
3008
+ href: "https://ochk.app",
3009
+ group: "orangecheck",
3010
+ line: "One account, with Bitcoin behind it.",
3011
+ status: "testing"
3012
+ },
3013
+ {
3014
+ slug: "docs",
3015
+ label: "docs",
3016
+ href: DOCS_HREF,
3017
+ group: "orangecheck",
3018
+ line: "Specs, SDKs and guides for every protocol.",
3019
+ status: "live"
3020
+ },
3021
+ ...PROTOCOLS,
3022
+ {
3023
+ slug: "vault",
3024
+ label: "vault",
3025
+ href: "https://vault.ochk.io",
3026
+ group: "app",
3027
+ line: "A password manager, encrypted in your browser.",
3028
+ status: "live",
3029
+ protocols: ["lock"]
3030
+ },
3031
+ {
3032
+ slug: "chat",
3033
+ label: "chat",
3034
+ href: "https://chat.ochk.io",
3035
+ group: "app",
3036
+ line: "Messages only the holder of a Bitcoin address can read.",
3037
+ status: "testing",
3038
+ protocols: ["lock"]
3039
+ },
3040
+ {
3041
+ slug: "cosign",
3042
+ label: "cosign",
3043
+ href: "https://cosign.ochk.io",
3044
+ group: "app",
3045
+ line: "Builders find co-founders and backers.",
3046
+ status: "testing",
3047
+ protocols: ["attest"]
3048
+ },
3049
+ {
3050
+ slug: "me-demo",
3051
+ // "demo", not the made-up app's own name, so nobody takes it for ours.
3052
+ label: "demo",
3053
+ href: "https://me-demo.ochk.io",
3054
+ group: "app",
3055
+ line: "Lumen Notes, a made-up app that signs in with orangecheck.",
3056
+ status: "live"
3057
+ },
3058
+ {
3059
+ slug: "globe",
3060
+ label: "globe",
3061
+ href: "https://globe.ochk.io",
3062
+ group: "public-good",
3063
+ line: "The Bitcoin network, live, on a globe.",
3064
+ status: "live"
3065
+ },
3066
+ {
3067
+ slug: "btc",
3068
+ label: "btc",
3069
+ href: "https://btc.ochk.io",
3070
+ group: "public-good",
3071
+ line: "A free desk for reading the Bitcoin market.",
3072
+ status: "live"
3073
+ }
3074
+ ];
3075
+ var FAMILY_GROUPS = [
3076
+ { id: "orangecheck", label: "orangecheck" },
3077
+ { id: "protocol", label: "Protocols" },
3078
+ { id: "app", label: "Apps" },
3079
+ { id: "public-good", label: "Public goods" }
3080
+ ];
3081
+ var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
3082
+ function familySite(slug) {
3083
+ return BY_SLUG.get(slug);
3084
+ }
3085
+ function protocolSite(slug) {
3086
+ return BY_SLUG.get(slug);
3087
+ }
3088
+ function familyByGroup() {
3089
+ return FAMILY_GROUPS.map((g) => ({ ...g, sites: FAMILY.filter((s) => s.group === g.id) }));
3090
+ }
3091
+ var LEGAL_LINKS = [
3092
+ { href: `${OCHK_IO}/privacy`, label: "Privacy" },
3093
+ { href: `${OCHK_IO}/terms`, label: "Terms" },
3094
+ { href: `${OCHK_IO}/security`, label: "Security" },
3095
+ { href: `${OCHK_IO}/trademark`, label: "Trademarks" },
3096
+ { href: `${OCHK_IO}/contact`, label: "Contact" }
3097
+ ];
3098
+ var OCHK_IO_NAV = [
3099
+ {
3100
+ href: `${OCHK_IO}/protocols`,
3101
+ label: "Protocols",
3102
+ children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
3103
+ },
3104
+ { href: `${OCHK_IO}/apps`, label: "Apps" },
3105
+ { href: DOCS_HREF, label: "Docs" },
3106
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
3107
+ { href: `${OCHK_IO}/about`, label: "About" }
3108
+ ];
3109
+ var OCHK_IO_FOOTER = [
3110
+ {
3111
+ heading: "Company",
3112
+ links: [
3113
+ { href: `${OCHK_IO}/about`, label: "About" },
3114
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
3115
+ { href: "https://github.com/orangecheck", label: "GitHub", external: true }
3116
+ ]
3117
+ }
3118
+ ];
3119
+ var CARD = "group relative flex h-full flex-col rounded-[1.25rem] border border-border bg-card p-6 transition-colors hover:border-oca-hairline-strong md:p-7 has-[a:focus-visible]:ring-2 has-[a:focus-visible]:ring-ring has-[a:focus-visible]:ring-offset-2 has-[a:focus-visible]:ring-offset-background";
3120
+ var STRETCH = 'outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-[""]';
3121
+ var pad2 = (n) => String(n + 1).padStart(2, "0");
3122
+ function ProtocolGrid({
3123
+ protocols = PROTOCOL_ORDER,
3124
+ link = "page",
3125
+ className
3126
+ }) {
3127
+ return /* @__PURE__ */ jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 md:gap-5", className), children: protocols.map((slug) => {
3128
+ const p = protocolSite(slug);
3129
+ const i = PROTOCOL_ORDER.indexOf(slug);
3130
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("div", { className: cn(CARD, "gap-4"), children: [
3131
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
3132
+ /* @__PURE__ */ jsxs("span", { className: "oca-numeral", children: [
3133
+ pad2(i),
3134
+ " ",
3135
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5 capitalize", children: p.verb })
3136
+ ] }),
3137
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null
3138
+ ] }),
3139
+ /* @__PURE__ */ jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsx("a", { href: link === "tool" ? p.toolHref : p.pageHref, className: STRETCH, children: p.label }) }),
3140
+ /* @__PURE__ */ jsx("p", { className: "oca-body", children: p.line }),
3141
+ /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between gap-3 pt-2 text-[0.875rem] text-muted-foreground", children: [
3142
+ /* @__PURE__ */ jsxs("span", { className: "oca-tabular", children: [
3143
+ "Nostr kind ",
3144
+ p.kinds
3145
+ ] }),
3146
+ /* @__PURE__ */ jsx(
3147
+ ArrowUpRight,
3148
+ {
3149
+ "aria-hidden": true,
3150
+ className: "size-4 transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-foreground"
3151
+ }
3152
+ )
3153
+ ] })
3154
+ ] }) }, slug);
3155
+ }) });
3156
+ }
3157
+ function AppCard({ name, line, href, protocols = [], status = "live", className }) {
3158
+ return /* @__PURE__ */ jsxs("div", { className: cn(CARD, "gap-3", className), children: [
3159
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
3160
+ /* @__PURE__ */ jsx("h3", { className: "oca-title", children: /* @__PURE__ */ jsx("a", { href, className: STRETCH, children: name }) }),
3161
+ status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status }) : null
3162
+ ] }),
3163
+ /* @__PURE__ */ jsx("p", { className: "oca-body text-[0.9375rem]", children: line }),
3164
+ /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-end justify-between gap-3 pt-3", children: [
3165
+ protocols.length > 0 ? /* @__PURE__ */ jsxs("p", { className: "flex flex-wrap items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
3166
+ "Shows",
3167
+ protocols.map((p) => /* @__PURE__ */ jsx(Badge, { tone: "muted", children: p }, p))
3168
+ ] }) : /* @__PURE__ */ jsx("span", {}),
3169
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-[0.875rem] text-muted-foreground transition-colors group-hover:text-foreground", children: [
3170
+ href.replace(/^https?:\/\//, ""),
3171
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true, className: "size-4" })
3172
+ ] })
3173
+ ] })
3174
+ ] });
3175
+ }
3176
+ function AppGrid({
3177
+ group = "app",
3178
+ sites,
3179
+ className
3180
+ }) {
3181
+ const list = sites ? sites.map((slug) => FAMILY.find((s) => s.slug === slug)).filter((s) => s !== void 0) : FAMILY.filter((s) => s.group === group);
3182
+ return /* @__PURE__ */ jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-5", className), children: list.map((s) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(AppCard, { name: s.label, line: s.line, href: s.href, protocols: s.protocols, status: s.status }) }, s.slug)) });
3183
+ }
3184
+ function ProtocolHero({
3185
+ protocol: protocol2,
3186
+ title,
3187
+ lead,
3188
+ actions,
3189
+ art,
3190
+ children,
3191
+ className
3192
+ }) {
3193
+ const p = protocolSite(protocol2);
3194
+ return /* @__PURE__ */ jsx(
3195
+ PageHero,
3196
+ {
3197
+ className,
3198
+ eyebrow: `Protocol \xB7 ${p.verb}`,
3199
+ title,
3200
+ lead,
3201
+ actions,
3202
+ art,
3203
+ children: p.status !== "live" || children ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-4", children: [
3204
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null,
3205
+ children
3206
+ ] }) : null
3207
+ }
3208
+ );
3209
+ }
3210
+ function ProtocolNav({
3211
+ current: current2,
3212
+ link = "page",
3213
+ className
3214
+ }) {
3215
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Protocols", className, children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--background)", children: /* @__PURE__ */ jsx("ul", { className: "flex w-max min-w-full items-center gap-6 border-b border-border", children: PROTOCOLS.map((p) => {
3216
+ const on = p.slug === current2;
3217
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
3218
+ "a",
3219
+ {
3220
+ href: link === "tool" ? p.toolHref : p.pageHref,
3221
+ "aria-current": on ? "page" : void 0,
3222
+ className: cn(
3223
+ "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
3224
+ on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3225
+ ),
3226
+ children: p.label
3227
+ }
3228
+ ) }, p.slug);
3229
+ }) }) }) });
3230
+ }
3231
+ function SpecCard({
3232
+ protocol: protocol2,
3233
+ version,
3234
+ license,
3235
+ vectors,
3236
+ size = "md",
3237
+ className
3238
+ }) {
3239
+ const p = protocolSite(protocol2);
3240
+ const repo = `oc-${p.slug}-protocol`;
3241
+ const facts = [
3242
+ ["Version", version],
3243
+ ...license ? [["Licence", license]] : [],
3244
+ ["Nostr kind", p.kinds],
3245
+ ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
3246
+ ];
3247
+ if (size === "sm") {
3248
+ return /* @__PURE__ */ jsxs(
3249
+ "a",
3250
+ {
3251
+ href: p.specHref,
3252
+ className: cn(
3253
+ "group flex flex-wrap items-center gap-x-4 gap-y-1 rounded-2xl border border-border bg-card px-4 py-3 text-[0.875rem] transition-colors hover:border-oca-hairline-strong",
3254
+ className
3255
+ ),
3256
+ children: [
3257
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
3258
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: facts.map(([k, v]) => k === "Version" ? `v${v}` : k === "Nostr kind" ? `kind ${v}` : v).join(" \xB7 ") }),
3259
+ /* @__PURE__ */ jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
3260
+ "Read the spec ",
3261
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true, className: "size-4" })
3262
+ ] })
3263
+ ]
3264
+ }
3265
+ );
3266
+ }
3267
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-6 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className), children: [
3268
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3269
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
3270
+ /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
3271
+ /* @__PURE__ */ jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
3272
+ ] }),
3273
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null
3274
+ ] }),
3275
+ /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-4", children: facts.map(([k, v]) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3276
+ /* @__PURE__ */ jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
3277
+ /* @__PURE__ */ jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
3278
+ ] }, k)) }),
3279
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxs("a", { href: p.specHref, children: [
3280
+ "Read the spec ",
3281
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true })
3282
+ ] }) }) })
3283
+ ] });
3284
+ }
3285
+ function VerifyBox({
3286
+ action,
3287
+ param = "q",
3288
+ title,
3289
+ description,
3290
+ label = "Id, envelope or link",
3291
+ placeholder,
3292
+ hint,
3293
+ submitLabel = "Verify",
3294
+ multiline = false,
3295
+ onVerify,
3296
+ className
3297
+ }) {
3298
+ const [value, setValue] = useState("");
3299
+ const submit = (e) => {
3300
+ if (!onVerify) return;
3301
+ e.preventDefault();
3302
+ if (value.trim()) onVerify(value.trim());
3303
+ };
3304
+ const button = /* @__PURE__ */ jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
3305
+ return /* @__PURE__ */ jsxs(
3306
+ "form",
3307
+ {
3308
+ action,
3309
+ method: "get",
3310
+ onSubmit: submit,
3311
+ className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
3312
+ children: [
3313
+ title || description ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
3314
+ title ? /* @__PURE__ */ jsx("h3", { className: "oca-title", children: title }) : null,
3315
+ description ? /* @__PURE__ */ jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
3316
+ ] }) : null,
3317
+ multiline ? /* @__PURE__ */ jsxs(Fragment, { children: [
3318
+ /* @__PURE__ */ jsx(Field, { label, hint, children: /* @__PURE__ */ jsx(
3319
+ Textarea,
3320
+ {
3321
+ name: param,
3322
+ required: true,
3323
+ value,
3324
+ onChange: (e) => setValue(e.target.value),
3325
+ placeholder,
3326
+ spellCheck: false,
3327
+ className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
3328
+ }
3329
+ ) }),
3330
+ /* @__PURE__ */ jsx("div", { children: button })
3331
+ ] }) : /* @__PURE__ */ jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsx(
3332
+ Input,
3333
+ {
3334
+ name: param,
3335
+ required: true,
3336
+ value,
3337
+ onChange: (e) => setValue(e.target.value),
3338
+ placeholder,
3339
+ spellCheck: false,
3340
+ autoComplete: "off",
3341
+ className: "font-mono text-base md:text-[0.875rem]"
3342
+ }
3343
+ ) })
3344
+ ]
3345
+ }
3346
+ );
3347
+ }
3348
+ var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
3349
+ function ComparisonTable({
3350
+ columns,
3351
+ rows,
3352
+ label,
3353
+ propertyHeading = "Property",
3354
+ className
3355
+ }) {
3356
+ const wide = columns.length > 3;
3357
+ const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
3358
+ const desk = wide ? "lg" : "md";
3359
+ const style = {
3360
+ // The argued-for column gets a little more room: its answers carry the page.
3361
+ "--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
3362
+ };
3363
+ const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
3364
+ return /* @__PURE__ */ jsxs("ul", { "aria-label": label, style, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: [
3365
+ /* @__PURE__ */ jsxs(
3366
+ "li",
3367
+ {
3368
+ "aria-hidden": true,
3369
+ className: cn(
3370
+ "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
3371
+ wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
3372
+ grid
3373
+ ),
3374
+ children: [
3375
+ /* @__PURE__ */ jsx("span", { children: propertyHeading }),
3376
+ columns.map((c) => /* @__PURE__ */ jsx("span", { className: cn(c.highlight && cn(TINT, "-my-4 px-4 py-4 text-oca-accent-ink")), children: c.label }, c.key))
3377
+ ]
3378
+ }
3379
+ ),
3380
+ rows.map((r, ri) => /* @__PURE__ */ jsxs("li", { className: cn("grid grid-cols-1 gap-3 px-5 py-5", wide ? "lg:items-start lg:gap-5 lg:px-8" : "md:items-start md:gap-5 md:px-8", grid), children: [
3381
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
3382
+ /* @__PURE__ */ jsx("span", { className: "oca-title-sm", children: r.label }),
3383
+ r.note ? /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
3384
+ ] }),
3385
+ /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
3386
+ return /* @__PURE__ */ jsxs(
3387
+ "div",
3388
+ {
3389
+ style: { "--oca-order": ordered.indexOf(c) },
3390
+ className: cn(
3391
+ // Two rows of the pair's grid (name, answer), so answers line up
3392
+ // across a pair even when one name wraps.
3393
+ "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
3394
+ desk === "lg" ? "lg:order-none lg:row-span-1 lg:flex lg:flex-col" : "md:order-none md:row-span-1 md:flex md:flex-col",
3395
+ c.highlight ? cn(
3396
+ TINT,
3397
+ "col-span-2",
3398
+ desk === "lg" ? "lg:col-span-1 lg:-my-5 lg:self-stretch lg:rounded-none lg:px-4 lg:py-5" : "md:col-span-1 md:-my-5 md:self-stretch md:rounded-none md:px-4 md:py-5"
3399
+ ) : desk === "lg" ? "lg:p-0" : "md:p-0"
3400
+ ),
3401
+ children: [
3402
+ /* @__PURE__ */ jsx(
3403
+ "span",
3404
+ {
3405
+ className: cn(
3406
+ "text-[0.8125rem]",
3407
+ c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
3408
+ desk === "lg" ? "lg:sr-only" : "md:sr-only"
3409
+ ),
3410
+ children: c.label
3411
+ }
3412
+ ),
3413
+ /* @__PURE__ */ jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
3414
+ ]
3415
+ },
3416
+ c.key
3417
+ );
3418
+ }) })
3419
+ ] }, ri))
3420
+ ] });
3421
+ }
3422
+ var CHECK = {
3423
+ ok: { word: "Passed", icon: /* @__PURE__ */ jsx(CircleCheck, {}), tone: "text-success" },
3424
+ fail: { word: "Failed", icon: /* @__PURE__ */ jsx(CircleX, {}), tone: "text-destructive" },
3425
+ pending: { word: "Pending", icon: /* @__PURE__ */ jsx(Clock, {}), tone: "text-oca-accent-ink" },
3426
+ skipped: { word: "Skipped", icon: /* @__PURE__ */ jsx(CircleMinus, {}), tone: "text-muted-foreground" },
3427
+ unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsx(CircleDashed, {}), tone: "text-oca-subtle" }
3428
+ };
3429
+ function VerifyReport({
3430
+ verdict,
3431
+ title,
3432
+ summary,
3433
+ checks,
3434
+ facts,
3435
+ notChecked,
3436
+ actions,
3437
+ className
3438
+ }) {
3439
+ return /* @__PURE__ */ jsxs(
3440
+ "section",
3441
+ {
3442
+ "aria-label": "Verification result",
3443
+ className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
3444
+ children: [
3445
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
3446
+ /* @__PURE__ */ jsx(StatusBadge, { status: verdict }),
3447
+ /* @__PURE__ */ jsx("h3", { className: "oca-display-3", children: title }),
3448
+ summary ? /* @__PURE__ */ jsx("p", { className: "oca-body max-w-[40rem]", children: summary }) : null
3449
+ ] }),
3450
+ /* @__PURE__ */ jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
3451
+ const k = CHECK[c.state];
3452
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
3453
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
3454
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5 sm:flex-row sm:items-baseline sm:justify-between sm:gap-6", children: [
3455
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
3456
+ /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem]", children: c.label }),
3457
+ c.note ? /* @__PURE__ */ jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
3458
+ ] }),
3459
+ /* @__PURE__ */ jsx(
3460
+ "span",
3461
+ {
3462
+ className: cn(
3463
+ "shrink-0 text-[0.8125rem]",
3464
+ c.state === "fail" ? "text-destructive" : "text-muted-foreground"
3465
+ ),
3466
+ children: k.word
3467
+ }
3468
+ )
3469
+ ] })
3470
+ ] }, i);
3471
+ }) }),
3472
+ facts && facts.length > 0 ? /* @__PURE__ */ jsx(KeyValueList, { items: facts, className: "rounded-none border-x-0 border-b-0 bg-transparent [&>div]:px-6 md:[&>div]:px-8" }) : null,
3473
+ notChecked && notChecked.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 border-t border-border bg-muted/50 px-6 py-5 md:px-8", children: [
3474
+ /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
3475
+ /* @__PURE__ */ jsx("ul", { className: "flex list-disc flex-col gap-1 pl-5 text-[0.875rem] leading-relaxed text-muted-foreground", children: notChecked.map((n, i) => /* @__PURE__ */ jsx("li", { children: n }, i)) })
3476
+ ] }) : null,
3477
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3 border-t border-border px-6 py-5 md:px-8", children: actions }) : null
3478
+ ]
3479
+ }
3480
+ );
3481
+ }
3482
+ function SignMessage({
3483
+ lead,
3484
+ address,
3485
+ message,
3486
+ wallets,
3487
+ busy = false,
3488
+ error,
3489
+ submitLabel = "Confirm",
3490
+ secondary,
3491
+ onSignature,
3492
+ className
3493
+ }) {
3494
+ const [pasted, setPasted] = useState("");
3495
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
3496
+ lead ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
3497
+ wallets ? /* @__PURE__ */ jsxs(Fragment, { children: [
3498
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
3499
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
3500
+ /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" }),
3501
+ "or sign it in any wallet",
3502
+ /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
3503
+ ] })
3504
+ ] }) : null,
3505
+ /* @__PURE__ */ jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3506
+ /* @__PURE__ */ jsxs(
3507
+ "form",
3508
+ {
3509
+ className: "flex flex-col gap-4",
3510
+ onSubmit: (e) => {
3511
+ e.preventDefault();
3512
+ if (pasted.trim()) onSignature(pasted.trim());
3513
+ },
3514
+ children: [
3515
+ /* @__PURE__ */ jsx(
3516
+ Field,
3517
+ {
3518
+ label: "Signature",
3519
+ error,
3520
+ hint: /* @__PURE__ */ jsxs(Fragment, { children: [
3521
+ "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3522
+ " ",
3523
+ /* @__PURE__ */ jsx("span", { className: "break-all font-mono", children: address }),
3524
+ "."
3525
+ ] }),
3526
+ children: /* @__PURE__ */ jsx(
3527
+ Textarea,
3528
+ {
3529
+ value: pasted,
3530
+ onChange: (e) => setPasted(e.target.value),
3531
+ rows: 3,
3532
+ spellCheck: false,
3533
+ className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
3534
+ }
3535
+ )
3536
+ }
3537
+ ),
3538
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
3539
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
3540
+ secondary
3541
+ ] })
3542
+ ]
3543
+ }
3544
+ )
3545
+ ] });
3546
+ }
3547
+ function SiteRow({ site, here, onNavigate }) {
3548
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
3549
+ "a",
3550
+ {
3551
+ href: site.href,
3552
+ onClick: onNavigate,
3553
+ "aria-current": here ? "page" : void 0,
3554
+ className: cn(
3555
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
3556
+ here && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
3557
+ ),
3558
+ children: [
3559
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-[0.9375rem] font-medium leading-6", children: [
3560
+ site.label,
3561
+ site.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: site.status }) : null,
3562
+ here ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(this site)" }) : null
3563
+ ] }),
3564
+ /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: site.line })
3565
+ ]
3566
+ }
3567
+ ) });
3568
+ }
3569
+ var PLACE = {
3570
+ orangecheck: "sm:col-start-1 sm:row-start-1 lg:row-span-2",
3571
+ protocol: "sm:col-start-1 sm:row-start-2 lg:col-start-2 lg:row-start-1 lg:row-span-2",
3572
+ app: "sm:col-start-2 sm:row-start-1 lg:col-start-3",
3573
+ "public-good": "sm:col-start-2 sm:row-start-2 lg:col-start-3"
3574
+ };
3575
+ function FamilyList({
3576
+ current: current2,
3577
+ onNavigate,
3578
+ stack = false,
3579
+ className
3580
+ }) {
3581
+ const id = useId();
3582
+ return /* @__PURE__ */ jsx(
3583
+ "div",
3584
+ {
3585
+ className: cn(
3586
+ "grid grid-cols-1 gap-x-2 gap-y-4",
3587
+ // The second desk row takes the slack, so the public goods sit right under the apps.
3588
+ !stack && "sm:grid-cols-2 lg:grid-cols-3 lg:grid-rows-[auto_1fr]",
3589
+ className
3590
+ ),
3591
+ children: familyByGroup().map((g) => /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", !stack && PLACE[g.id]), children: [
3592
+ /* @__PURE__ */ jsx("p", { id: `${id}-${g.id}`, className: "px-3 pt-1 text-[0.8125rem] text-muted-foreground", children: g.label }),
3593
+ /* @__PURE__ */ jsx("ul", { "aria-labelledby": `${id}-${g.id}`, className: "flex flex-col", children: g.sites.map((s) => /* @__PURE__ */ jsx(SiteRow, { site: s, here: s.slug === current2, onNavigate }, s.slug)) })
3594
+ ] }, g.id))
3595
+ }
3596
+ );
3597
+ }
3598
+ function FamilyMenu({ current: current2, className }) {
3599
+ const [open, setOpen] = useState(false);
3600
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
3601
+ /* @__PURE__ */ jsx(
3602
+ PopoverTrigger,
3603
+ {
3604
+ "aria-label": "All orangecheck sites",
3605
+ className: cn(
3606
+ "group inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors",
3607
+ "hover:bg-accent hover:text-foreground data-[state=open]:bg-accent data-[state=open]:text-foreground",
3608
+ className
3609
+ ),
3610
+ children: /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" })
3611
+ }
3612
+ ),
3613
+ /* @__PURE__ */ jsx(
3614
+ PopoverContent,
3615
+ {
3616
+ align: "start",
3617
+ sideOffset: 14,
3618
+ collisionPadding: 16,
3619
+ className: "max-h-[min(40rem,var(--radix-popover-content-available-height))] w-[min(calc(100vw-2rem),42rem)] overflow-y-auto p-3 lg:w-[min(calc(100vw-2rem),56rem)]",
3620
+ children: /* @__PURE__ */ jsx(FamilyList, { current: current2, onNavigate: () => setOpen(false) })
3621
+ }
3622
+ )
3623
+ ] });
3624
+ }
3625
+ function NavLink({ item, className, onNavigate }) {
3626
+ const cls = cn(
3627
+ "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
3628
+ item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
3629
+ className
3630
+ );
3631
+ if (item.external) {
3632
+ return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
3633
+ }
3634
+ return /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
3635
+ }
3636
+ function NavRow({ item, onNavigate }) {
3637
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
3638
+ /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
3639
+ item.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
3640
+ ] });
3641
+ const cls = cn(
3642
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
3643
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
3644
+ );
3645
+ 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 });
3646
+ }
3647
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
3648
+ function NavDropdown({ item }) {
3649
+ const [open, setOpen] = useState(false);
3650
+ const active = item.active || item.children?.some((c) => c.active);
3651
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
3652
+ /* @__PURE__ */ jsxs(
3653
+ PopoverTrigger,
3654
+ {
3655
+ className: cn(
3656
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors",
3657
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
3658
+ ),
3659
+ children: [
3660
+ item.label,
3661
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
3662
+ ]
3663
+ }
3664
+ ),
3665
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
3666
+ /* @__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)) }),
3667
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsx(
3668
+ NavLink,
3669
+ {
3670
+ item: { ...item, label: seeAll(item), children: void 0 },
3671
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
3672
+ onNavigate: () => setOpen(false)
3673
+ }
3674
+ ) })
3675
+ ] })
3676
+ ] });
3677
+ }
3678
+ function SiteHeader({
3679
+ home = "/",
3680
+ brand,
3681
+ product,
3682
+ family,
3683
+ nav = [],
3684
+ search,
3685
+ actions,
3686
+ variant = "site",
3687
+ className
3688
+ }) {
3689
+ const [open, setOpen] = useState(false);
3690
+ const tool = variant === "tool";
3691
+ const size = tool ? 24 : 28;
3692
+ const current2 = typeof family === "string" ? family : void 0;
3693
+ const menu = nav.length > 0 || Boolean(family);
3694
+ const brandNode = brand ?? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center", children: [
3695
+ /* @__PURE__ */ jsx(Lockup, { size }),
3696
+ product ? /* @__PURE__ */ jsxs(Fragment, { children: [
3697
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
3698
+ /* @__PURE__ */ jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
3699
+ ] }) : null
3700
+ ] });
3701
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : /* @__PURE__ */ jsx(NavLink, { item: n }, n.href)) }) : null;
3702
+ return /* @__PURE__ */ jsx(
3703
+ "header",
3704
+ {
3705
+ className: cn(
3706
+ "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
3707
+ tool ? "border-border" : "border-transparent",
3708
+ className
3709
+ ),
3710
+ children: /* @__PURE__ */ jsxs(
3711
+ "div",
3712
+ {
3713
+ className: cn(
3714
+ "flex items-center justify-between gap-4",
3715
+ tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem]",
3716
+ // Three columns, the outer two each at least their content: the
3717
+ // navigation stays centred whatever the actions hold, so it does
3718
+ // not shift when they change (signed out to signed in).
3719
+ !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
3720
+ ),
3721
+ children: [
3722
+ /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
3723
+ /* @__PURE__ */ jsxs(Link5, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
3724
+ brandNode,
3725
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
3726
+ ] }),
3727
+ family ? /* @__PURE__ */ jsx(FamilyMenu, { current: current2, className: "max-md:hidden" }) : null,
3728
+ tool && navigation ? /* @__PURE__ */ jsx("div", { className: "ml-5", children: navigation }) : null
3729
+ ] }),
3730
+ !tool ? navigation : null,
3731
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
3732
+ search,
3733
+ actions,
3734
+ menu ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
3735
+ /* @__PURE__ */ jsx(
3736
+ SheetTrigger,
3737
+ {
3738
+ className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
3739
+ "aria-label": "Open menu",
3740
+ children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
3741
+ }
3742
+ ),
3743
+ /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
3744
+ /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
3745
+ nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map(
3746
+ (n) => n.children?.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-2", children: [
3747
+ /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
3748
+ n.children.map((c) => /* @__PURE__ */ jsx(
3749
+ NavLink,
3750
+ {
3751
+ item: c,
3752
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
3753
+ onNavigate: () => setOpen(false)
3754
+ },
3755
+ c.href
3756
+ ))
3757
+ ] }, n.href) : /* @__PURE__ */ jsx(
3758
+ NavLink,
3759
+ {
3760
+ item: n,
3761
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
3762
+ onNavigate: () => setOpen(false)
3763
+ },
3764
+ n.href
3765
+ )
3766
+ ) }) : null,
3767
+ family ? /* @__PURE__ */ jsxs("details", { className: cn("group", nav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
3768
+ /* @__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: [
3769
+ "All orangecheck sites",
3770
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
3771
+ ] }),
3772
+ /* @__PURE__ */ jsx(FamilyList, { current: current2, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
3773
+ ] }) : null
3774
+ ] })
3775
+ ] }) : null
3776
+ ] })
3777
+ ]
3778
+ }
3779
+ )
3780
+ }
3781
+ );
3782
+ }
3783
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
3784
+ return /* @__PURE__ */ jsx(
3785
+ "a",
3786
+ {
3787
+ href,
3788
+ 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",
3789
+ children
3790
+ }
3791
+ );
3792
+ }
3793
+ var BANNER_TONE = {
3794
+ neutral: "border-border bg-muted",
3795
+ brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
3796
+ danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
3797
+ };
3798
+ function SiteBanner({
3799
+ tone = "neutral",
3800
+ children,
3801
+ action,
3802
+ className
3803
+ }) {
3804
+ 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: [
3805
+ /* @__PURE__ */ jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
3806
+ tone !== "neutral" ? /* @__PURE__ */ jsx(
3807
+ "span",
3808
+ {
3809
+ "aria-hidden": true,
3810
+ className: cn(
3811
+ "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
3812
+ tone === "brand" ? "bg-oca-orange" : "bg-destructive"
3813
+ )
3814
+ }
3815
+ ) : null,
3816
+ /* @__PURE__ */ jsx("span", { children })
3817
+ ] }),
3818
+ action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
3819
+ ] }) });
3820
+ }
3821
+ var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
3822
+ function LegalRow() {
3823
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
3824
+ /* @__PURE__ */ jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-5", children: LEGAL_LINKS.map((l) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
3825
+ /* @__PURE__ */ jsxs("p", { children: [
3826
+ "\xA9 ",
3827
+ (/* @__PURE__ */ new Date()).getFullYear(),
3828
+ " OrangeCheck"
3829
+ ] })
3830
+ ] });
3831
+ }
3832
+ function SiteFooter({
3833
+ columns = [],
3834
+ family = false,
3835
+ legal = false,
3836
+ compact = false,
3837
+ fineprint,
3838
+ meta,
3839
+ signature = true,
3840
+ className
3841
+ }) {
3842
+ if (compact) {
3843
+ 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: [
3844
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
3845
+ /* @__PURE__ */ jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
3846
+ 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
3847
+ ] }),
3848
+ legal || meta ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
3849
+ legal ? /* @__PURE__ */ jsx(LegalRow, {}) : null,
3850
+ meta
3851
+ ] }) : null
3852
+ ] }) });
3853
+ }
3854
+ const cols = [
3855
+ ...columns,
3856
+ ...family ? familyByGroup().map((g) => ({
3857
+ // The lockup above already says orangecheck.
3858
+ heading: g.id === "orangecheck" ? "Start here" : g.label,
3859
+ links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
3860
+ })) : []
3861
+ ];
3862
+ const n = cols.length;
3863
+ const inline = n <= 5;
3864
+ const grid = {
3865
+ "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
3866
+ "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
3867
+ };
3868
+ return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
3869
+ /* @__PURE__ */ jsxs(
3870
+ "div",
3871
+ {
3872
+ style: grid,
3873
+ 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)]",
3874
+ children: [
3875
+ /* @__PURE__ */ jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
3876
+ /* @__PURE__ */ jsx(Lockup, { size: 26 }),
3877
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
3878
+ ] }),
3879
+ cols.map((col, i) => {
3880
+ const spans = n % 2 === 1 && i === n - 1;
3881
+ return /* @__PURE__ */ jsxs(
3882
+ "div",
3883
+ {
3884
+ className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
3885
+ children: [
3886
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
3887
+ /* @__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(
3888
+ NavLink,
3889
+ {
3890
+ item: l,
3891
+ className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
3892
+ },
3893
+ l.href
3894
+ )) })
3895
+ ]
3896
+ },
3897
+ col.heading
3898
+ );
3899
+ })
3900
+ ]
3901
+ }
3902
+ ),
3903
+ 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: [
3904
+ /* @__PURE__ */ jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsx(Mark, { className: "block h-auto w-full" }) }),
3905
+ /* @__PURE__ */ jsx("span", { children: "orangecheck" })
3906
+ ] }) }) : null,
3907
+ legal || 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: [
3908
+ legal ? /* @__PURE__ */ jsx(LegalRow, {}) : null,
3909
+ meta
3910
+ ] }) }) : null
3911
+ ] });
3912
+ }
3913
+ function SignInFrame({
3914
+ title = "Sign in",
3915
+ lead,
3916
+ children,
3917
+ error,
3918
+ fineprint,
3919
+ brand,
3920
+ home = "/",
3921
+ back,
3922
+ art,
3923
+ caption,
3924
+ className
3925
+ }) {
3926
+ return /* @__PURE__ */ jsxs(
3927
+ "main",
3928
+ {
3929
+ id: "main-content",
3930
+ className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
3931
+ children: [
3932
+ /* @__PURE__ */ jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
3933
+ /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4", children: [
3934
+ /* @__PURE__ */ jsxs(Link5, { href: home, className: "w-fit rounded-lg", children: [
3935
+ brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
3936
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
3937
+ ] }),
3938
+ back === void 0 ? /* @__PURE__ */ jsx(
3939
+ Link5,
3940
+ {
3941
+ href: home,
3942
+ className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
3943
+ children: "Back to home"
3944
+ }
3945
+ ) : back
3946
+ ] }),
3947
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
3948
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
3949
+ /* @__PURE__ */ jsx("h1", { className: "oca-display-2", children: title }),
3950
+ lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead", children: lead }) : null
3951
+ ] }),
3952
+ /* @__PURE__ */ jsx("div", { children }),
3953
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
3954
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
3955
+ ] })
3956
+ ] }),
3957
+ /* @__PURE__ */ jsxs(
3958
+ "aside",
3959
+ {
3960
+ "aria-hidden": true,
3961
+ 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",
3962
+ children: [
3963
+ /* @__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" }) }),
3964
+ caption ? /* @__PURE__ */ jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
3965
+ ]
3966
+ }
3967
+ )
3968
+ ]
3969
+ }
3970
+ );
3971
+ }
2531
3972
  function SideNav({ groups, onNavigate }) {
2532
3973
  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: [
2533
3974
  g.label ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
2534
3975
  g.items.map((it) => /* @__PURE__ */ jsxs(
2535
- Link2,
3976
+ Link5,
2536
3977
  {
2537
3978
  href: it.href,
2538
3979
  onClick: onNavigate,
@@ -2554,7 +3995,7 @@ function SideNav({ groups, onNavigate }) {
2554
3995
  }
2555
3996
  function SectionSwitch({
2556
3997
  sections,
2557
- current,
3998
+ current: current2,
2558
3999
  onNavigate
2559
4000
  }) {
2560
4001
  const cols = sections.length <= 3 ? sections.length : 2;
@@ -2565,9 +4006,9 @@ function SectionSwitch({
2565
4006
  className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
2566
4007
  style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
2567
4008
  children: sections.map((sec) => {
2568
- const on = sec.id === current.id;
4009
+ const on = sec.id === current2.id;
2569
4010
  return /* @__PURE__ */ jsx(
2570
- Link2,
4011
+ Link5,
2571
4012
  {
2572
4013
  href: sec.href,
2573
4014
  onClick: onNavigate,
@@ -2597,7 +4038,7 @@ function TabBar({ items }) {
2597
4038
  className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
2598
4039
  style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
2599
4040
  children: items.map((it) => /* @__PURE__ */ jsxs(
2600
- Link2,
4041
+ Link5,
2601
4042
  {
2602
4043
  href: it.href,
2603
4044
  "aria-current": it.active ? "page" : void 0,
@@ -2662,19 +4103,19 @@ function AppShell({
2662
4103
  className
2663
4104
  }) {
2664
4105
  const [open, setOpen] = useState(false);
2665
- const current = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
2666
- const groups = current ? [...current.groups, ...persistent] : [...nav ?? [], ...persistent];
4106
+ const current2 = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
4107
+ const groups = current2 ? [...current2.groups, ...persistent] : [...nav ?? [], ...persistent];
2667
4108
  warnDuplicateLabels(groups);
2668
- const tabs = current ? null : tabsFor(groups);
4109
+ const tabs = current2 ? null : tabsFor(groups);
2669
4110
  const page = activeItem(groups);
2670
4111
  const place = useMemo(
2671
4112
  () => ({
2672
- section: current ? current.title ?? current.label : void 0,
4113
+ section: current2 ? current2.title ?? current2.label : void 0,
2673
4114
  page: pageOverride ?? page?.label
2674
4115
  }),
2675
- [current, page?.label, pageOverride]
4116
+ [current2, page?.label, pageOverride]
2676
4117
  );
2677
- const switcher = sections && current && sections.length > 1 ? /* @__PURE__ */ jsx(SectionSwitch, { sections, current, onNavigate: () => setOpen(false) }) : null;
4118
+ const switcher = sections && current2 && sections.length > 1 ? /* @__PURE__ */ jsx(SectionSwitch, { sections, current: current2, onNavigate: () => setOpen(false) }) : null;
2678
4119
  return /* @__PURE__ */ jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxs(
2679
4120
  "div",
2680
4121
  {
@@ -2706,7 +4147,7 @@ function AppShell({
2706
4147
  footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
2707
4148
  ] })
2708
4149
  ] }),
2709
- /* @__PURE__ */ jsx(Link2, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
4150
+ /* @__PURE__ */ jsx(Link5, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
2710
4151
  /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
2711
4152
  ] }),
2712
4153
  place.page ? /* @__PURE__ */ jsxs(
@@ -2729,7 +4170,7 @@ function AppShell({
2729
4170
  ] }),
2730
4171
  /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
2731
4172
  /* @__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: [
2732
- /* @__PURE__ */ jsx(Link2, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
4173
+ /* @__PURE__ */ jsx(Link5, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
2733
4174
  switcher,
2734
4175
  /* @__PURE__ */ jsx(SideNav, { groups }),
2735
4176
  /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
@@ -2774,7 +4215,7 @@ function AccountMenu({
2774
4215
  ] }),
2775
4216
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
2776
4217
  items.map(
2777
- (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link2, { href: it.href, children: [
4218
+ (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: [
2778
4219
  it.icon,
2779
4220
  it.label
2780
4221
  ] }) }, it.label) : /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
@@ -2789,16 +4230,16 @@ function ThemeToggle({ className }) {
2789
4230
  const { theme, setTheme } = useTheme();
2790
4231
  const [mounted, setMounted] = useState(false);
2791
4232
  useEffect(() => setMounted(true), []);
2792
- const current = mounted ? theme ?? "system" : "system";
2793
- const next = current === "light" ? "dark" : current === "dark" ? "system" : "light";
2794
- const Icon2 = current === "light" ? Sun : current === "dark" ? Moon : SunMoon;
4233
+ const current2 = mounted ? theme ?? "system" : "system";
4234
+ const next = current2 === "light" ? "dark" : current2 === "dark" ? "system" : "light";
4235
+ const Icon2 = current2 === "light" ? Sun : current2 === "dark" ? Moon : SunMoon;
2795
4236
  return /* @__PURE__ */ jsx(
2796
4237
  "button",
2797
4238
  {
2798
4239
  type: "button",
2799
4240
  onClick: () => setTheme(next),
2800
- "aria-label": `Theme: ${current}. Switch to ${next}`,
2801
- title: `Theme: ${current}`,
4241
+ "aria-label": `Theme: ${current2}. Switch to ${next}`,
4242
+ title: `Theme: ${current2}`,
2802
4243
  className: cn(
2803
4244
  "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
2804
4245
  className
@@ -2808,6 +4249,6 @@ function ThemeToggle({ className }) {
2808
4249
  );
2809
4250
  }
2810
4251
 
2811
- export { APP_ATTRIBUTE, APP_ID, Accent, AccountMenu, ActivityList, AppIcon, AppShell, Badge, BrowserFrame, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNumeral, CardTitle, Checkbox, CodeBlock, Container, CopyButton, Crowd, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Display, DocHeader, DocLayout, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, EmptyLine, EmptyState, ErrorBoundary, Eyebrow, Field, FloatChip, Footnote, HalftoneCanvas, HalftoneSphere, HashChip, Input, IsoCheck, Kbd, KeyValueList, Label, Lead, LoadingBlock, Lockup, MARK_FACES, Mark, Monogram, Notice, PackageCard, PageHeader, PageHero, PhoneFrame, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProgressSteps, Prose, RadioGroup, RadioGroupItem, Reveal, SPHERE_GRADIENT, Sats, SatsFigure, ScrollFade, ScrollStory, Section, SectionIntro, Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetTitle, SheetTrigger, ShellContext, SiteFooter, SiteHeader, Skeleton, Spinner, SplitBar, StatCard, StatGrid, StatusDot, StatusPill, StepGrid, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeToggle, Ticker, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TruthTable, UsdApprox, appColors, appFonts, badgeVariants, buttonVariants, cardVariants, cn, monogramGround, monogramLetter, portraitTone, satsText, sectionVariants, useCopy, useInView, useShellPlace, useTimedOut };
4252
+ export { APP_ATTRIBUTE, APP_ID, Accent, Accordion, AccordionItem, AccountMenu, ActivityList, AppCard, AppGrid, AppIcon, AppShell, Badge, BrowserFrame, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNumeral, CardTitle, Checkbox, Closing, CodeBlock, ComparisonTable, Container, CopyButton, Crowd, DOCS_HREF, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogHost, DialogTitle, DialogTrigger, Display, DocHeader, DocLayout, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, EmptyLine, EmptyState, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FAMILY, FAMILY_GROUPS, FactBlock, FactRows, FamilyMenu, Faq, Field, FloatChip, Footnote, HalftoneCanvas, HalftoneSphere, HashChip, Input, IsoCheck, Kbd, KeyValueList, LEGAL_LINKS, Label, Lead, LegalDocument, LoadingBlock, Lockup, MARK_FACES, Mark, Monogram, Notice, OCHK_IO, OCHK_IO_FOOTER, OCHK_IO_NAV, PROTOCOLS, PROTOCOL_ORDER, PackageCard, PageHeader, PageHero, Pagination, PhoneFrame, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProgressSteps, ProofStrip, Prose, ProtocolGrid, ProtocolHero, ProtocolNav, QrCode, RadioGroup, RadioGroupItem, Reveal, SPHERE_GRADIENT, Sats, SatsFigure, ScrollFade, ScrollStory, Section, SectionHeading, SectionIntro, Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetTitle, SheetTrigger, ShellContext, SignInFrame, SignMessage, SiteBanner, SiteFooter, SiteHeader, Skeleton, SkipLink, SpecCard, Spinner, SplitBar, StatCard, StatGrid, StatusBadge, StatusDot, StatusPill, StepGrid, Switch, Tabs, TabsContent, TabsList, TabsTrigger, TextLink, Textarea, ThemeToggle, Ticker, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TruthTable, UsdApprox, VerifyBox, VerifyReport, appColors, appFonts, badgeVariants, buttonVariants, cardVariants, cn, confirm, familyByGroup, familySite, monogramGround, monogramLetter, portraitTone, prompt, protocolSite, satsText, sectionVariants, statusWord, useCopy, useInView, useShellPlace, useTimedOut };
2812
4253
  //# sourceMappingURL=index.mjs.map
2813
4254
  //# sourceMappingURL=index.mjs.map