@orangecheck/app-design 1.2.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/chrome.d.mts +8 -3
  2. package/dist/chrome.d.ts +8 -3
  3. package/dist/chrome.js +605 -553
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/chrome.mjs +605 -555
  6. package/dist/chrome.mjs.map +1 -1
  7. package/dist/code.js +3 -1
  8. package/dist/code.js.map +1 -1
  9. package/dist/code.mjs +3 -1
  10. package/dist/code.mjs.map +1 -1
  11. package/dist/components.d.mts +3 -3
  12. package/dist/components.d.ts +3 -3
  13. package/dist/components.js +730 -666
  14. package/dist/components.js.map +1 -1
  15. package/dist/components.mjs +731 -667
  16. package/dist/components.mjs.map +1 -1
  17. package/dist/{docs-Dxg4Tp_q.d.ts → docs-BB9gK4KF.d.ts} +18 -4
  18. package/dist/{docs-wJBfLS08.d.mts → docs-D-T-nHiu.d.mts} +18 -4
  19. package/dist/index.d.mts +4 -4
  20. package/dist/index.d.ts +4 -4
  21. package/dist/index.js +1549 -1406
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +1548 -1407
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/mdx.d.mts +6 -2
  26. package/dist/mdx.d.ts +6 -2
  27. package/dist/mdx.js +168 -74
  28. package/dist/mdx.js.map +1 -1
  29. package/dist/mdx.mjs +169 -75
  30. package/dist/mdx.mjs.map +1 -1
  31. package/dist/primitives.d.mts +9 -3
  32. package/dist/primitives.d.ts +9 -3
  33. package/dist/primitives.js +7 -6
  34. package/dist/primitives.js.map +1 -1
  35. package/dist/primitives.mjs +7 -6
  36. package/dist/primitives.mjs.map +1 -1
  37. package/dist/session.d.mts +4 -3
  38. package/dist/session.d.ts +4 -3
  39. package/dist/session.js +27 -3
  40. package/dist/session.js.map +1 -1
  41. package/dist/session.mjs +27 -3
  42. package/dist/session.mjs.map +1 -1
  43. package/dist/styles/swagger.css +252 -0
  44. package/dist/styles/tokens.css +2 -0
  45. package/dist/{tool-shell-kqGWMTep.d.mts → tool-shell-D8Q8XX11.d.mts} +8 -5
  46. package/dist/{tool-shell-DLSwUxTD.d.ts → tool-shell-gmlj47Ie.d.ts} +8 -5
  47. package/package.json +1 -1
@@ -11,6 +11,7 @@ var reactSlot = require('@radix-ui/react-slot');
11
11
  var SeparatorPrimitive = require('@radix-ui/react-separator');
12
12
  require('sonner');
13
13
  var Link = require('next/link');
14
+ var router = require('next/compat/router');
14
15
  var CheckboxPrimitive = require('@radix-ui/react-checkbox');
15
16
  var LabelPrimitive = require('@radix-ui/react-label');
16
17
  var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
@@ -1707,11 +1708,13 @@ function forClipboard(text, lang) {
1707
1708
  if (!lines.some((l) => l.startsWith("$ "))) return text;
1708
1709
  return lines.filter((l) => l.startsWith("$ ")).map((l) => l.slice(2)).join("\n");
1709
1710
  }
1710
- function linesFromDom(pre) {
1711
+ function linesFromDom(pre, newline) {
1711
1712
  if (!pre) return null;
1712
1713
  const lines = pre.querySelectorAll("[data-line]");
1713
1714
  if (lines.length === 0) return pre.textContent ?? "";
1714
- return Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
1715
+ const text = Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
1716
+ return newline ? `${text}
1717
+ ` : text;
1715
1718
  }
1716
1719
  function prepare(code, lang, marks, diff) {
1717
1720
  const d = diff ? readDiff(code) : null;
@@ -1720,7 +1723,8 @@ function prepare(code, lang, marks, diff) {
1720
1723
  const kept = d ? src.split("\n").filter((_, i) => d.diff.get(i + 1) !== "remove") : null;
1721
1724
  return {
1722
1725
  html: linesToHtml(lines, { highlight: parseLineRanges(marks), diff: d?.diff }),
1723
- copy: kept ? kept.join("\n") : src,
1726
+ // Byte for byte, the final newline too: a hash printed beside the code must match a copy of it.
1727
+ copy: kept ? kept.join("\n") + (/\n$/.test(code) ? "\n" : "") : code,
1724
1728
  lines: lines.length,
1725
1729
  diff: !!d
1726
1730
  };
@@ -1785,6 +1789,7 @@ function CodeBlock({
1785
1789
  code,
1786
1790
  html,
1787
1791
  children,
1792
+ trailingNewline = false,
1788
1793
  lang,
1789
1794
  caption,
1790
1795
  copy = true,
@@ -1805,7 +1810,7 @@ function CodeBlock({
1805
1810
  );
1806
1811
  const markup = prepared?.html ?? html;
1807
1812
  const lines = prepared?.lines ?? (html !== void 0 ? html.split("\n").length : code?.split("\n").length ?? 0);
1808
- const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current) ?? code ?? "", lang);
1813
+ const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current, trailingNewline) ?? code ?? "", lang);
1809
1814
  return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: cn(FRAME, className), children: [
1810
1815
  /* @__PURE__ */ jsxRuntime.jsxs("figcaption", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-5 pr-2", children: [
1811
1816
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? languageName(lang) ?? "Code" }),
@@ -2584,12 +2589,21 @@ function Faq({
2584
2589
  return /* @__PURE__ */ jsxRuntime.jsx(Accordion, { single: true, className, children: items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsx(AccordionItem, { id: it.id, title: it.q, children: it.a }, it.id ?? i)) });
2585
2590
  }
2586
2591
  var LINK = "text-foreground underline decoration-foreground/35 underline-offset-4 transition-colors hover:decoration-foreground";
2592
+ var SCHEME = /^[a-z][a-z\d+.-]*:/i;
2593
+ function useResolved(href) {
2594
+ const router$1 = router.useRouter();
2595
+ if (!router$1 || !href || href.startsWith("/") || href.startsWith("#") || href.startsWith("?") || SCHEME.test(href)) return href;
2596
+ const here = router$1.asPath.split(/[?#]/)[0] || "/";
2597
+ const url = new URL(href, `https://page.invalid${here}`);
2598
+ return url.pathname + url.search + url.hash;
2599
+ }
2587
2600
  function TextLink({
2588
- href,
2601
+ href: written,
2589
2602
  children,
2590
2603
  external,
2591
2604
  className
2592
2605
  }) {
2606
+ const href = useResolved(written);
2593
2607
  const internal = href.startsWith("/") && !href.startsWith("/api/") && !href.startsWith("/.well-known/");
2594
2608
  const offsite = external ?? /^https?:\/\//.test(href);
2595
2609
  if (internal && !offsite) {
@@ -2825,6 +2839,10 @@ function protocolSite(slug) {
2825
2839
  { href: `${OCHK_IO}/trust`, label: "Trust" },
2826
2840
  { href: `${OCHK_IO}/about`, label: "About" }
2827
2841
  ];
2842
+ var InDocsContext = sharedContext("in-docs", false);
2843
+ function useInDocs() {
2844
+ return react.useContext(InDocsContext);
2845
+ }
2828
2846
  var WORD = {
2829
2847
  live: "Live",
2830
2848
  testing: "In testing",
@@ -2854,6 +2872,7 @@ function ProtocolGrid({
2854
2872
  link = "page",
2855
2873
  className
2856
2874
  }) {
2875
+ const inDocs = useInDocs();
2857
2876
  return /* @__PURE__ */ jsxRuntime.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) => {
2858
2877
  const p = protocolSite(slug);
2859
2878
  const i = PROTOCOL_ORDER.indexOf(slug);
@@ -2866,7 +2885,7 @@ function ProtocolGrid({
2866
2885
  ] }),
2867
2886
  p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
2868
2887
  ] }),
2869
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsxRuntime.jsx(
2888
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-display-3", children: link === "docs" && inDocs ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: `/${p.slug}`, className: STRETCH, children: p.label }) : /* @__PURE__ */ jsxRuntime.jsx(
2870
2889
  "a",
2871
2890
  {
2872
2891
  href: link === "tool" ? p.toolHref : link === "docs" ? `${DOCS_HREF}/${p.slug}` : p.pageHref,
@@ -2973,16 +2992,17 @@ var Label = react.forwardRef(function Label2({ className, ...props }, ref) {
2973
2992
  }
2974
2993
  );
2975
2994
  });
2976
- function Field({ label, hint, optional, error, children, className, hideLabel, action }) {
2977
- const id = react.useId();
2995
+ function Field({ label, hint, optional, error, children, id: fixedId, className, hideLabel, action }) {
2996
+ const generated = react.useId();
2997
+ const id = fixedId ?? generated;
2978
2998
  const hintId = hint ? `${id}-hint` : void 0;
2979
2999
  const errorId = error ? `${id}-error` : void 0;
2980
- const describedBy = [hintId, errorId].filter(Boolean).join(" ") || void 0;
2981
- const control = react.isValidElement(children) ? react.cloneElement(children, {
3000
+ const wiring = {
2982
3001
  id,
2983
- "aria-describedby": describedBy,
3002
+ "aria-describedby": [hintId, errorId].filter(Boolean).join(" ") || void 0,
2984
3003
  "aria-invalid": error ? true : void 0
2985
- }) : children;
3004
+ };
3005
+ const control = typeof children === "function" ? children(wiring) : react.isValidElement(children) ? react.cloneElement(children, { ...wiring }) : children;
2986
3006
  const hintNode = hint ? /* @__PURE__ */ jsxRuntime.jsx("p", { id: hintId, className: "text-[0.8125rem] leading-snug text-muted-foreground", children: hint }) : null;
2987
3007
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
2988
3008
  /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: id, className: hideLabel ? "sr-only" : "flex items-baseline gap-2", children: [
@@ -3113,736 +3133,780 @@ react.forwardRef(function RadioGroupItem2({ className, ...props }, ref) {
3113
3133
  }
3114
3134
  );
3115
3135
  });
3116
- function ProtocolHero({
3117
- protocol: protocol2,
3136
+ var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
3137
+ function DocLink({ href, className, children, ...rest }) {
3138
+ return isInternal(href) ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, ...rest, children });
3139
+ }
3140
+ function Breadcrumbs({ items, action, className }) {
3141
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
3142
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex min-w-0 items-center gap-1.5 text-[0.875rem] text-muted-foreground", children: items.map((c, i) => {
3143
+ const last = i === items.length - 1;
3144
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
3145
+ c.href && !last ? /* @__PURE__ */ jsxRuntime.jsx(DocLink, { href: c.href, className: "inline-flex min-h-11 items-center transition-colors hover:text-foreground sm:min-h-0", children: c.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": last ? "page" : void 0, className: cn("truncate", last && "text-foreground"), children: c.label }),
3146
+ !last ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
3147
+ ] }, i);
3148
+ }) }) }),
3149
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
3150
+ ] });
3151
+ }
3152
+ function DocsPager({ prev, next, className }) {
3153
+ if (!prev && !next) return null;
3154
+ const card = (l, dir) => /* @__PURE__ */ jsxRuntime.jsxs(
3155
+ DocLink,
3156
+ {
3157
+ href: l.href,
3158
+ className: cn(
3159
+ "group flex min-h-20 flex-col justify-center gap-1 rounded-2xl border border-border bg-card px-5 py-4 transition-colors hover:border-oca-hairline-strong",
3160
+ dir === "next" && "items-end text-right sm:col-start-2"
3161
+ ),
3162
+ children: [
3163
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
3164
+ dir === "prev" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
3165
+ dir === "prev" ? "Previous" : "Next",
3166
+ l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
3167
+ l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: l.section }) : null,
3168
+ dir === "next" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
3169
+ ] }),
3170
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
3171
+ ]
3172
+ }
3173
+ );
3174
+ return /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-label": "Previous and next page", className: cn("grid grid-cols-1 gap-3 border-t border-border pt-8 sm:grid-cols-2", className), children: [
3175
+ prev ? card(prev, "prev") : null,
3176
+ next ? card(next, "next") : null
3177
+ ] });
3178
+ }
3179
+ function useHeadings(selector = "#docs-content", key) {
3180
+ const [items, setItems] = react.useState([]);
3181
+ react.useEffect(() => {
3182
+ const read = () => {
3183
+ const root = document.querySelector(selector);
3184
+ if (!root) return setItems([]);
3185
+ setItems(
3186
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
3187
+ id: h.id,
3188
+ // The anchor link's "#" is not part of the name.
3189
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
3190
+ level: h.tagName === "H3" ? 3 : 2
3191
+ }))
3192
+ );
3193
+ };
3194
+ const raf = requestAnimationFrame(read);
3195
+ const t = setTimeout(read, 80);
3196
+ return () => {
3197
+ cancelAnimationFrame(raf);
3198
+ clearTimeout(t);
3199
+ };
3200
+ }, [selector, key]);
3201
+ const activeId = useActiveHeading(items.map((i) => i.id));
3202
+ return { items, activeId };
3203
+ }
3204
+ function OnThisPage({
3205
+ items,
3206
+ activeId,
3207
+ title = "On this page",
3208
+ onNavigate,
3209
+ className
3210
+ }) {
3211
+ const id = react.useId();
3212
+ if (items.length === 0) return null;
3213
+ return (
3214
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
3215
+ /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
3216
+ title ? /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
3217
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((t) => {
3218
+ const on = t.id === activeId;
3219
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
3220
+ "a",
3221
+ {
3222
+ href: `#${t.id}`,
3223
+ onClick: onNavigate,
3224
+ "aria-current": on ? "location" : void 0,
3225
+ className: cn(
3226
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
3227
+ t.level === 3 ? "pl-7" : "pl-4",
3228
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
3229
+ ),
3230
+ children: t.label
3231
+ }
3232
+ ) }, t.id);
3233
+ }) })
3234
+ ] })
3235
+ );
3236
+ }
3237
+ var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
3238
+ function Callout({
3239
+ tone = "note",
3118
3240
  title,
3119
- lead,
3120
- actions,
3121
- art,
3122
3241
  children,
3123
3242
  className
3124
3243
  }) {
3125
- const p = protocolSite(protocol2);
3126
3244
  return /* @__PURE__ */ jsxRuntime.jsx(
3127
- PageHero,
3245
+ Notice,
3128
3246
  {
3129
- className,
3130
- eyebrow: `Protocol \xB7 ${p.verb}`,
3247
+ tone: CALLOUT_TONE[tone],
3131
3248
  title,
3132
- lead,
3133
- actions,
3134
- art,
3135
- children: p.status !== "live" || children ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-4", children: [
3136
- p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null,
3137
- children
3138
- ] }) : null
3249
+ role: "note",
3250
+ className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
3251
+ children
3139
3252
  }
3140
3253
  );
3141
3254
  }
3142
- function ProtocolNav({
3143
- current,
3144
- link = "page",
3145
- className
3146
- }) {
3147
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Protocols", className, children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--background)", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex w-max min-w-full items-center gap-6 border-b border-border", children: PROTOCOLS.map((p) => {
3148
- const on = p.slug === current;
3149
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
3150
- "a",
3151
- {
3152
- href: link === "tool" ? p.toolHref : p.pageHref,
3153
- "aria-current": on ? "page" : void 0,
3154
- className: cn(
3155
- "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
3156
- on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3157
- ),
3158
- children: p.label
3159
- }
3160
- ) }, p.slug);
3161
- }) }) }) });
3162
- }
3163
- function SpecCard({
3164
- protocol: protocol2,
3165
- version,
3166
- license,
3167
- vectors,
3168
- size = "md",
3169
- className
3170
- }) {
3171
- const p = protocolSite(protocol2);
3172
- const repo = `oc-${p.slug}-protocol`;
3173
- const facts = [
3174
- ["Version", version],
3175
- ...license ? [["Licence", license]] : [],
3176
- ["Nostr kind", p.kinds],
3177
- ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
3178
- ];
3179
- if (size === "sm") {
3180
- return /* @__PURE__ */ jsxRuntime.jsxs(
3181
- "a",
3255
+ function Step({ title, id, children }) {
3256
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
3257
+ /* @__PURE__ */ jsxRuntime.jsx(
3258
+ "span",
3182
3259
  {
3183
- href: p.specHref,
3184
- className: cn(
3185
- "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",
3186
- className
3187
- ),
3188
- children: [
3189
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
3190
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: facts.map(([k, v]) => k === "Version" ? `v${v}` : k === "Nostr kind" ? `kind ${v}` : v).join(" \xB7 ") }),
3191
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
3192
- "Read the spec ",
3193
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
3194
- ] })
3195
- ]
3260
+ "aria-hidden": true,
3261
+ className: "absolute left-0 top-0 flex size-7 items-center justify-center rounded-full border border-oca-hairline-strong bg-card text-[0.8125rem] oca-tabular text-foreground before:content-[counter(oca-step)]"
3196
3262
  }
3197
- );
3198
- }
3199
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-6 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className), children: [
3200
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3201
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
3202
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
3203
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
3204
- ] }),
3205
- p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
3206
- ] }),
3207
- /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-4", children: facts.map(([k, v]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
3208
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
3209
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
3210
- ] }, k)) }),
3211
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: p.specHref, children: [
3212
- "Read the spec ",
3213
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true })
3214
- ] }) }) })
3263
+ ),
3264
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
3265
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { id, className: "scroll-mt-28 pt-0.5 text-[1.0625rem] font-medium leading-snug tracking-[-0.008em] text-foreground", children: title }),
3266
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
3215
3267
  ] });
3216
3268
  }
3217
- function VerifyBox({
3218
- action,
3219
- param = "q",
3269
+ function Steps({ children, className }) {
3270
+ return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: cn("not-prose my-8 flex flex-col [counter-reset:oca-step] [&>li:last-child>span:nth-child(2)]:hidden", className), children });
3271
+ }
3272
+ function LinkCard({
3273
+ href,
3220
3274
  title,
3221
3275
  description,
3222
- label = "Id, envelope or link",
3223
- placeholder,
3224
- hint,
3225
- submitLabel = "Verify",
3226
- multiline = false,
3227
- onVerify,
3276
+ icon,
3277
+ meta,
3228
3278
  className
3229
3279
  }) {
3230
- const [value, setValue] = react.useState("");
3231
- const submit = (e) => {
3232
- if (!onVerify) return;
3233
- e.preventDefault();
3234
- if (value.trim()) onVerify(value.trim());
3235
- };
3236
- const button = /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
3280
+ const Arrow = isInternal(href) ? lucideReact.ArrowRight : lucideReact.ArrowUpRight;
3237
3281
  return /* @__PURE__ */ jsxRuntime.jsxs(
3238
- "form",
3282
+ DocLink,
3239
3283
  {
3240
- action,
3241
- method: "get",
3242
- onSubmit: submit,
3243
- className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
3284
+ href,
3285
+ className: cn(
3286
+ "group flex h-full flex-col gap-3 rounded-[1.25rem] border border-border bg-card p-5 transition-colors hover:border-oca-hairline-strong",
3287
+ className
3288
+ ),
3244
3289
  children: [
3245
- title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
3246
- title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: title }) : null,
3247
- description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
3248
- ] }) : null,
3249
- multiline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3250
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, children: /* @__PURE__ */ jsxRuntime.jsx(
3251
- Textarea,
3252
- {
3253
- name: param,
3254
- required: true,
3255
- value,
3256
- onChange: (e) => setValue(e.target.value),
3257
- placeholder,
3258
- spellCheck: false,
3259
- className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
3260
- }
3261
- ) }),
3262
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: button })
3263
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsxRuntime.jsx(
3264
- Input,
3265
- {
3266
- name: param,
3267
- required: true,
3268
- value,
3269
- onChange: (e) => setValue(e.target.value),
3270
- placeholder,
3271
- spellCheck: false,
3272
- autoComplete: "off",
3273
- className: "font-mono text-base md:text-[0.875rem]"
3274
- }
3275
- ) })
3290
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-3", children: [
3291
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground [&_svg]:size-[1.125rem]", children: icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }),
3292
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
3293
+ meta,
3294
+ /* @__PURE__ */ jsxRuntime.jsx(Arrow, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" })
3295
+ ] })
3296
+ ] }),
3297
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
3298
+ description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
3276
3299
  ]
3277
3300
  }
3278
3301
  );
3279
3302
  }
3280
- var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
3281
- function ComparisonTable({
3282
- columns,
3303
+ function CardGrid({ columns = 2, children, className }) {
3304
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("not-prose my-6 grid grid-cols-1 gap-3 sm:grid-cols-2", columns === 3 && "lg:grid-cols-3", className), children });
3305
+ }
3306
+ function MdxTable({ className, ...props }) {
3307
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "not-prose my-6 overflow-hidden rounded-2xl border border-border bg-card", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
3308
+ "table",
3309
+ {
3310
+ className: cn(
3311
+ "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
3312
+ "[&_th]:whitespace-nowrap [&_th]:border-b [&_th]:border-oca-hairline-strong [&_th]:bg-oca-table-head [&_th]:px-4 [&_th]:py-2.5 [&_th]:text-[0.8125rem] [&_th]:font-medium [&_th]:text-foreground",
3313
+ "[&_td]:border-t [&_td]:border-border [&_td]:px-4 [&_td]:py-2.5 [&_td]:align-top [&_td]:text-muted-foreground [&_tbody_tr:first-child_td]:border-t-0",
3314
+ "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
3315
+ "[&_[align=center]]:text-center [&_[align=right]]:text-right",
3316
+ // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
3317
+ "max-sm:[&_td]:min-w-[9rem]",
3318
+ className
3319
+ ),
3320
+ ...props
3321
+ }
3322
+ ) }) });
3323
+ }
3324
+ var said = (n) => n !== void 0 && n !== null && n !== false && n !== "";
3325
+ function ApiTable({
3283
3326
  rows,
3284
- label,
3285
- propertyHeading = "Property",
3327
+ caption,
3328
+ nameHeader = "Name",
3286
3329
  className
3287
3330
  }) {
3288
- const wide = columns.length > 3;
3289
- const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
3290
- const desk = wide ? "lg" : "md";
3291
- const style = {
3292
- // The argued-for column gets a little more room: its answers carry the page.
3293
- "--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
3331
+ const hasDefault = rows.some((r) => r.default !== void 0);
3332
+ const hasDescription = rows.some((r) => said(r.description));
3333
+ const hasSource = rows.some((r) => said(r.source));
3334
+ const cell = "px-4 py-3 max-sm:p-0";
3335
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("not-prose my-6 overflow-hidden rounded-2xl border border-border bg-card", className), children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse text-left text-[0.875rem] max-sm:block", children: [
3336
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
3337
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "max-sm:sr-only", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
3338
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
3339
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
3340
+ hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
3341
+ hasDescription ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" }) : null,
3342
+ hasSource ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Defined in" }) : null
3343
+ ] }) }),
3344
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border max-sm:block", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
3345
+ "tr",
3346
+ {
3347
+ id: r.id,
3348
+ className: "scroll-mt-28 align-top target:bg-muted max-sm:flex max-sm:flex-col max-sm:gap-1.5 max-sm:px-4 max-sm:py-3.5",
3349
+ children: [
3350
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "row", className: cn(cell, "text-left font-normal"), children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-start gap-1 max-sm:flex-row max-sm:flex-wrap max-sm:items-baseline max-sm:gap-x-2", children: [
3351
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground max-sm:text-[0.875rem]", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3352
+ r.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
3353
+ r.deprecated ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
3354
+ r.status ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: r.status }) : null
3355
+ ] }) }),
3356
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(cell, "font-mono text-[0.8125rem] text-muted-foreground max-sm:break-all", !said(r.type) && "max-sm:hidden"), children: r.type ?? "\u2014" }),
3357
+ hasDefault ? /* @__PURE__ */ jsxRuntime.jsxs("td", { className: cn(cell, "font-mono text-[0.8125rem] text-muted-foreground max-sm:order-last", r.default === void 0 && "max-sm:hidden"), children: [
3358
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans sm:hidden", children: "Default " }),
3359
+ r.default ?? "\u2014"
3360
+ ] }) : null,
3361
+ hasDescription ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(cell, "leading-relaxed text-muted-foreground", !said(r.description) && "max-sm:hidden"), children: r.description }) : null,
3362
+ hasSource ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(cell, "text-[0.8125rem] text-muted-foreground max-sm:order-last max-sm:break-all", !said(r.source) && "max-sm:hidden"), children: r.source }) : null
3363
+ ]
3364
+ },
3365
+ r.id ?? r.name
3366
+ )) })
3367
+ ] }) }) });
3368
+ }
3369
+ function useDarkMode() {
3370
+ const [dark, setDark] = react.useState(false);
3371
+ react.useEffect(() => {
3372
+ const root = document.documentElement;
3373
+ const read = () => setDark(root.classList.contains("dark"));
3374
+ read();
3375
+ const mo = new MutationObserver(read);
3376
+ mo.observe(root, { attributes: true, attributeFilter: ["class"] });
3377
+ return () => mo.disconnect();
3378
+ }, []);
3379
+ return dark;
3380
+ }
3381
+ function mermaidTheme(el) {
3382
+ const css = getComputedStyle(el);
3383
+ const v = (name) => css.getPropertyValue(name).trim();
3384
+ const card = v("--card");
3385
+ const muted = v("--muted");
3386
+ const text = v("--foreground");
3387
+ const subtle = v("--muted-foreground");
3388
+ const line = v("--input");
3389
+ const hair = v("--oca-hairline-strong");
3390
+ return {
3391
+ background: "transparent",
3392
+ fontFamily: css.fontFamily,
3393
+ fontSize: "14px",
3394
+ textColor: text,
3395
+ mainBkg: card,
3396
+ primaryColor: card,
3397
+ primaryTextColor: text,
3398
+ primaryBorderColor: hair,
3399
+ secondaryColor: muted,
3400
+ secondaryTextColor: text,
3401
+ secondaryBorderColor: hair,
3402
+ tertiaryColor: muted,
3403
+ tertiaryTextColor: text,
3404
+ tertiaryBorderColor: hair,
3405
+ nodeBorder: hair,
3406
+ lineColor: line,
3407
+ edgeLabelBackground: card,
3408
+ clusterBkg: muted,
3409
+ clusterBorder: hair,
3410
+ titleColor: text,
3411
+ noteBkgColor: muted,
3412
+ noteTextColor: text,
3413
+ noteBorderColor: hair,
3414
+ actorBkg: card,
3415
+ actorBorder: hair,
3416
+ actorTextColor: text,
3417
+ actorLineColor: line,
3418
+ signalColor: text,
3419
+ signalTextColor: text,
3420
+ labelBoxBkgColor: card,
3421
+ labelBoxBorderColor: hair,
3422
+ labelTextColor: text,
3423
+ loopTextColor: subtle,
3424
+ activationBkgColor: muted,
3425
+ activationBorderColor: hair,
3426
+ sequenceNumberColor: card
3294
3427
  };
3295
- const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
3296
- return /* @__PURE__ */ jsxRuntime.jsxs("ul", { "aria-label": label, style, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: [
3297
- /* @__PURE__ */ jsxRuntime.jsxs(
3298
- "li",
3428
+ }
3429
+ var FIT = 4 / 3;
3430
+ function naturalSize(svg) {
3431
+ const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
3432
+ if (!w) return { svg, width: null };
3433
+ const width = Math.ceil(Number(w));
3434
+ return {
3435
+ svg: svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${width}"`).replace(/max-width:\s*[\d.]+px;?/, ""),
3436
+ width
3437
+ };
3438
+ }
3439
+ function useInnerWidth(ref, padding) {
3440
+ const [width, setWidth] = react.useState(null);
3441
+ react.useEffect(() => {
3442
+ const el = ref.current;
3443
+ if (!el) return;
3444
+ const ro = new ResizeObserver(() => setWidth(el.clientWidth - padding));
3445
+ ro.observe(el);
3446
+ return () => ro.disconnect();
3447
+ }, [ref, padding]);
3448
+ return width;
3449
+ }
3450
+ function Diagram({ chart, caption, load, className }) {
3451
+ const ref = react.useRef(null);
3452
+ const dark = useDarkMode();
3453
+ const raw = react.useId();
3454
+ const [drawn, setDrawn] = react.useState(null);
3455
+ const [failed, setFailed] = react.useState(false);
3456
+ const room = useInnerWidth(ref, 48);
3457
+ const fits = drawn?.width != null && room != null && drawn.width <= room * FIT;
3458
+ react.useEffect(() => {
3459
+ let live = true;
3460
+ const el = ref.current;
3461
+ if (!el) return;
3462
+ (async () => {
3463
+ try {
3464
+ const mod = await load();
3465
+ const mermaid = "default" in mod ? mod.default : mod;
3466
+ mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
3467
+ const { svg } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
3468
+ if (live) {
3469
+ setDrawn(naturalSize(svg));
3470
+ setFailed(false);
3471
+ }
3472
+ } catch {
3473
+ if (live) setFailed(true);
3474
+ }
3475
+ })();
3476
+ return () => {
3477
+ live = false;
3478
+ };
3479
+ }, [chart, dark, load, raw]);
3480
+ if (failed) return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
3481
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
3482
+ drawn ? /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
3483
+ "div",
3299
3484
  {
3300
- "aria-hidden": true,
3485
+ "data-fit": fits ? "" : void 0,
3301
3486
  className: cn(
3302
- "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
3303
- wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
3304
- grid
3487
+ "flex justify-center p-6 [&_svg]:h-auto",
3488
+ fits ? "w-full [&_svg]:max-w-full" : "w-max min-w-full [&_svg]:max-w-none"
3305
3489
  ),
3306
- children: [
3307
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: propertyHeading }),
3308
- columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(c.highlight && cn(TINT, "-my-4 px-4 py-4 text-oca-accent-ink")), children: c.label }, c.key))
3309
- ]
3490
+ role: "img",
3491
+ "aria-label": typeof caption === "string" ? caption : "Diagram",
3492
+ dangerouslySetInnerHTML: { __html: drawn.svg }
3310
3493
  }
3311
- ),
3312
- rows.map((r, ri) => /* @__PURE__ */ jsxRuntime.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: [
3313
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
3314
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-title-sm", children: r.label }),
3315
- r.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
3316
- ] }),
3317
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
3318
- return /* @__PURE__ */ jsxRuntime.jsxs(
3319
- "div",
3320
- {
3321
- style: { "--oca-order": ordered.indexOf(c) },
3322
- className: cn(
3323
- // Two rows of the pair's grid (name, answer), so answers line up
3324
- // across a pair even when one name wraps.
3325
- "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
3326
- 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",
3327
- c.highlight ? cn(
3328
- TINT,
3329
- "col-span-2",
3330
- 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"
3331
- ) : desk === "lg" ? "lg:p-0" : "md:p-0"
3332
- ),
3333
- children: [
3334
- /* @__PURE__ */ jsxRuntime.jsx(
3335
- "span",
3336
- {
3337
- className: cn(
3338
- "text-[0.8125rem]",
3339
- c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
3340
- desk === "lg" ? "lg:sr-only" : "md:sr-only"
3341
- ),
3342
- children: c.label
3343
- }
3344
- ),
3345
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
3346
- ]
3347
- },
3348
- c.key
3349
- );
3350
- }) })
3351
- ] }, ri))
3494
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-label": "Drawing the diagram", className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-40 w-full rounded-xl" }) }),
3495
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
3352
3496
  ] });
3353
3497
  }
3354
- var CHECK = {
3355
- ok: { word: "Passed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}), tone: "text-success" },
3356
- fail: { word: "Failed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}), tone: "text-destructive" },
3357
- pending: { word: "Pending", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, {}), tone: "text-oca-accent-ink" },
3358
- skipped: { word: "Skipped", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleMinus, {}), tone: "text-muted-foreground" },
3359
- unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, {}), tone: "text-oca-subtle" }
3498
+ var HEADING = {
3499
+ h1: "oca-display-3 mb-4 text-foreground",
3500
+ h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
3501
+ h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
3502
+ h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
3360
3503
  };
3361
- function VerifyReport({
3362
- verdict,
3363
- title,
3364
- summary,
3365
- checks,
3366
- facts,
3367
- notChecked,
3368
- actions,
3369
- as: Heading = "h2",
3370
- className
3504
+ function DocsHeading({
3505
+ as: Tag,
3506
+ id,
3507
+ children,
3508
+ className,
3509
+ ...props
3371
3510
  }) {
3372
- return /* @__PURE__ */ jsxRuntime.jsxs(
3373
- "section",
3374
- {
3375
- "aria-label": "Verification result",
3376
- className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
3377
- children: [
3378
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
3379
- /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verdict }),
3380
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-display-3", children: title }),
3381
- summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body max-w-[40rem]", children: summary }) : null
3382
- ] }),
3383
- /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
3384
- const k = CHECK[c.state];
3385
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
3386
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
3387
- /* @__PURE__ */ jsxRuntime.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: [
3388
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
3389
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem]", children: c.label }),
3390
- c.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
3391
- ] }),
3392
- /* @__PURE__ */ jsxRuntime.jsx(
3393
- "span",
3394
- {
3395
- className: cn(
3396
- "shrink-0 text-[0.8125rem]",
3397
- c.state === "fail" ? "text-destructive" : "text-muted-foreground"
3398
- ),
3399
- children: k.word
3400
- }
3401
- )
3402
- ] })
3403
- ] }, i);
3404
- }) }),
3405
- facts && facts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { items: facts, className: "rounded-none border-x-0 border-b-0 bg-transparent [&>div]:px-6 md:[&>div]:px-8" }) : null,
3406
- notChecked && notChecked.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 border-t border-border bg-muted/50 px-6 py-5 md:px-8", children: [
3407
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
3408
- /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("li", { children: n }, i)) })
3409
- ] }) : null,
3410
- actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3 border-t border-border px-6 py-5 md:px-8", children: actions }) : null
3411
- ]
3412
- }
3413
- );
3414
- }
3415
- function SignMessage({
3416
- lead,
3417
- address,
3418
- message,
3419
- wallets,
3420
- busy = false,
3421
- error,
3422
- submitLabel = "Confirm",
3423
- secondary,
3424
- onSignature,
3425
- className
3426
- }) {
3427
- const [pasted, setPasted] = react.useState("");
3428
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
3429
- lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
3430
- wallets ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3431
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
3432
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
3433
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
3434
- "or sign it in any wallet",
3435
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
3436
- ] })
3437
- ] }) : null,
3438
- /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3439
- /* @__PURE__ */ jsxRuntime.jsxs(
3440
- "form",
3511
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
3512
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-heading-text": "", children }),
3513
+ id && Tag !== "h1" ? /* @__PURE__ */ jsxRuntime.jsxs(
3514
+ "a",
3441
3515
  {
3442
- className: "flex flex-col gap-4",
3443
- onSubmit: (e) => {
3444
- e.preventDefault();
3445
- if (pasted.trim()) onSignature(pasted.trim());
3446
- },
3516
+ href: `#${id}`,
3517
+ className: "ml-2 inline-block rounded-md px-1 align-baseline text-[0.85em] font-normal text-oca-subtle no-underline opacity-0 transition-opacity hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100",
3447
3518
  children: [
3448
- /* @__PURE__ */ jsxRuntime.jsx(
3449
- Field,
3450
- {
3451
- label: "Signature",
3452
- error,
3453
- hint: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3454
- "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3455
- " ",
3456
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all font-mono", children: address }),
3457
- "."
3458
- ] }),
3459
- children: /* @__PURE__ */ jsxRuntime.jsx(
3460
- Textarea,
3461
- {
3462
- value: pasted,
3463
- onChange: (e) => setPasted(e.target.value),
3464
- rows: 3,
3465
- spellCheck: false,
3466
- className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
3467
- }
3468
- )
3469
- }
3470
- ),
3471
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
3472
- /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
3473
- secondary
3474
- ] })
3519
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
3520
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Link to this section" })
3475
3521
  ]
3476
3522
  }
3477
- )
3478
- ] });
3479
- }
3480
- var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
3481
- function DocLink({ href, className, children, ...rest }) {
3482
- return isInternal(href) ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, ...rest, children });
3483
- }
3484
- function Breadcrumbs({ items, action, className }) {
3485
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
3486
- /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex min-w-0 items-center gap-1.5 text-[0.875rem] text-muted-foreground", children: items.map((c, i) => {
3487
- const last = i === items.length - 1;
3488
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
3489
- c.href && !last ? /* @__PURE__ */ jsxRuntime.jsx(DocLink, { href: c.href, className: "inline-flex min-h-11 items-center transition-colors hover:text-foreground sm:min-h-0", children: c.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": last ? "page" : void 0, className: cn("truncate", last && "text-foreground"), children: c.label }),
3490
- !last ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
3491
- ] }, i);
3492
- }) }) }),
3493
- action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
3494
- ] });
3495
- }
3496
- function DocsPager({ prev, next, className }) {
3497
- if (!prev && !next) return null;
3498
- const card = (l, dir) => /* @__PURE__ */ jsxRuntime.jsxs(
3499
- DocLink,
3500
- {
3501
- href: l.href,
3502
- className: cn(
3503
- "group flex min-h-20 flex-col justify-center gap-1 rounded-2xl border border-border bg-card px-5 py-4 transition-colors hover:border-oca-hairline-strong",
3504
- dir === "next" && "items-end text-right sm:col-start-2"
3505
- ),
3506
- children: [
3507
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
3508
- dir === "prev" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
3509
- dir === "prev" ? "Previous" : "Next",
3510
- l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
3511
- l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: l.section }) : null,
3512
- dir === "next" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
3513
- ] }),
3514
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
3515
- ]
3516
- }
3517
- );
3518
- return /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-label": "Previous and next page", className: cn("grid grid-cols-1 gap-3 border-t border-border pt-8 sm:grid-cols-2", className), children: [
3519
- prev ? card(prev, "prev") : null,
3520
- next ? card(next, "next") : null
3523
+ ) : null
3521
3524
  ] });
3522
3525
  }
3523
- function useHeadings(selector = "#docs-content", key) {
3524
- const [items, setItems] = react.useState([]);
3525
- react.useEffect(() => {
3526
- const read = () => {
3527
- const root = document.querySelector(selector);
3528
- if (!root) return setItems([]);
3529
- setItems(
3530
- Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
3531
- id: h.id,
3532
- // The anchor link's "#" is not part of the name.
3533
- label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
3534
- level: h.tagName === "H3" ? 3 : 2
3535
- }))
3536
- );
3537
- };
3538
- const raf = requestAnimationFrame(read);
3539
- const t = setTimeout(read, 80);
3540
- return () => {
3541
- cancelAnimationFrame(raf);
3542
- clearTimeout(t);
3543
- };
3544
- }, [selector, key]);
3545
- const activeId = useActiveHeading(items.map((i) => i.id));
3546
- return { items, activeId };
3547
- }
3548
- function OnThisPage({
3549
- items,
3550
- activeId,
3551
- title = "On this page",
3552
- onNavigate,
3553
- className
3554
- }) {
3555
- const id = react.useId();
3556
- if (items.length === 0) return null;
3557
- return (
3558
- // With no visible title (a folded list under its own summary) the name is still "On this page".
3559
- /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
3560
- title ? /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
3561
- /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((t) => {
3562
- const on = t.id === activeId;
3563
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
3564
- "a",
3565
- {
3566
- href: `#${t.id}`,
3567
- onClick: onNavigate,
3568
- "aria-current": on ? "location" : void 0,
3569
- className: cn(
3570
- "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
3571
- t.level === 3 ? "pl-7" : "pl-4",
3572
- on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
3573
- ),
3574
- children: t.label
3575
- }
3576
- ) }, t.id);
3577
- }) })
3578
- ] })
3579
- );
3580
- }
3581
- var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
3582
- function Callout({
3583
- tone = "note",
3526
+ function ProtocolHero({
3527
+ protocol: protocol2,
3584
3528
  title,
3529
+ lead,
3530
+ actions,
3531
+ art,
3585
3532
  children,
3586
3533
  className
3587
3534
  }) {
3535
+ const p = protocolSite(protocol2);
3588
3536
  return /* @__PURE__ */ jsxRuntime.jsx(
3589
- Notice,
3537
+ PageHero,
3590
3538
  {
3591
- tone: CALLOUT_TONE[tone],
3539
+ className,
3540
+ eyebrow: `Protocol \xB7 ${p.verb}`,
3592
3541
  title,
3593
- role: "note",
3594
- className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
3595
- children
3542
+ lead,
3543
+ actions,
3544
+ art,
3545
+ children: p.status !== "live" || children ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-4", children: [
3546
+ p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null,
3547
+ children
3548
+ ] }) : null
3596
3549
  }
3597
3550
  );
3598
3551
  }
3599
- function Step({ title, id, children }) {
3600
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
3601
- /* @__PURE__ */ jsxRuntime.jsx(
3602
- "span",
3603
- {
3604
- "aria-hidden": true,
3605
- className: "absolute left-0 top-0 flex size-7 items-center justify-center rounded-full border border-oca-hairline-strong bg-card text-[0.8125rem] oca-tabular text-foreground before:content-[counter(oca-step)]"
3606
- }
3607
- ),
3608
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
3609
- /* @__PURE__ */ jsxRuntime.jsx("h3", { id, className: "scroll-mt-28 pt-0.5 text-[1.0625rem] font-medium leading-snug tracking-[-0.008em] text-foreground", children: title }),
3610
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
3611
- ] });
3612
- }
3613
- function Steps({ children, className }) {
3614
- return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: cn("not-prose my-8 flex flex-col [counter-reset:oca-step] [&>li:last-child>span:nth-child(2)]:hidden", className), children });
3615
- }
3616
- function LinkCard({
3617
- href,
3618
- title,
3619
- description,
3620
- icon,
3621
- meta,
3552
+ function ProtocolNav({
3553
+ current,
3554
+ link = "page",
3622
3555
  className
3623
3556
  }) {
3624
- const Arrow = isInternal(href) ? lucideReact.ArrowRight : lucideReact.ArrowUpRight;
3557
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Protocols", className, children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--background)", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex w-max min-w-full items-center gap-6 border-b border-border", children: PROTOCOLS.map((p) => {
3558
+ const on = p.slug === current;
3559
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
3560
+ "a",
3561
+ {
3562
+ href: link === "tool" ? p.toolHref : p.pageHref,
3563
+ "aria-current": on ? "page" : void 0,
3564
+ className: cn(
3565
+ "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
3566
+ on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3567
+ ),
3568
+ children: p.label
3569
+ }
3570
+ ) }, p.slug);
3571
+ }) }) }) });
3572
+ }
3573
+ var SPEC_FILE = {
3574
+ spec: {
3575
+ file: "SPEC.md",
3576
+ title: "Normative source",
3577
+ note: "This page is a human-readable summary. The authoritative copy lives in the spec repo. If the two ever drift, the repo wins."
3578
+ },
3579
+ security: {
3580
+ file: "SECURITY.md",
3581
+ title: "Normative threat model",
3582
+ note: "This page is the short form. The authoritative, numbered threat model lives in the spec repo."
3583
+ },
3584
+ rationale: {
3585
+ file: "WHY.md",
3586
+ title: "Design rationale",
3587
+ note: "This page is the short version. The full rationale and the rejected-design log live in the spec repo."
3588
+ }
3589
+ };
3590
+ function SpecCard(props) {
3591
+ return props.repo !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(SpecFileNote, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(ProtocolSpecCard, { ...props });
3592
+ }
3593
+ function SpecFileNote({ repo, file, kind = "spec", version, note, className }) {
3594
+ const d = SPEC_FILE[kind];
3595
+ const f = file ?? d.file;
3596
+ return /* @__PURE__ */ jsxRuntime.jsxs(Callout, { title: version ? `${d.title} \xB7 ${version}` : d.title, className, children: [
3597
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: note ?? d.note }),
3598
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsx(TextLink, { href: `https://github.com/orangecheck/${repo}/blob/main/${f}`, className: "break-all font-mono text-[0.875rem]", children: `${repo}/${f}` }) })
3599
+ ] });
3600
+ }
3601
+ function ProtocolSpecCard({ protocol: protocol2, version, license, vectors, size = "md", className }) {
3602
+ const p = protocolSite(protocol2);
3603
+ const repo = `oc-${p.slug}-protocol`;
3604
+ const facts = [
3605
+ ["Version", version],
3606
+ ...license ? [["Licence", license]] : [],
3607
+ ["Nostr kind", p.kinds],
3608
+ ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
3609
+ ];
3610
+ if (size === "sm") {
3611
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3612
+ "a",
3613
+ {
3614
+ href: p.specHref,
3615
+ className: cn(
3616
+ "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",
3617
+ className
3618
+ ),
3619
+ children: [
3620
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
3621
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: facts.map(([k, v]) => k === "Version" ? `v${v}` : k === "Nostr kind" ? `kind ${v}` : v).join(" \xB7 ") }),
3622
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
3623
+ "Read the spec ",
3624
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
3625
+ ] })
3626
+ ]
3627
+ }
3628
+ );
3629
+ }
3630
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-6 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className), children: [
3631
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3632
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
3633
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
3634
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
3635
+ ] }),
3636
+ p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
3637
+ ] }),
3638
+ /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-4", children: facts.map(([k, v]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
3639
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
3640
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
3641
+ ] }, k)) }),
3642
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: p.specHref, children: [
3643
+ "Read the spec ",
3644
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true })
3645
+ ] }) }) })
3646
+ ] });
3647
+ }
3648
+ function VerifyBox({
3649
+ action,
3650
+ param = "q",
3651
+ title,
3652
+ description,
3653
+ label = "Id, envelope or link",
3654
+ placeholder,
3655
+ hint,
3656
+ submitLabel = "Verify",
3657
+ multiline = false,
3658
+ onVerify,
3659
+ className
3660
+ }) {
3661
+ const [value, setValue] = react.useState("");
3662
+ const submit = (e) => {
3663
+ if (!onVerify) return;
3664
+ e.preventDefault();
3665
+ if (value.trim()) onVerify(value.trim());
3666
+ };
3667
+ const button = /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
3625
3668
  return /* @__PURE__ */ jsxRuntime.jsxs(
3626
- DocLink,
3669
+ "form",
3627
3670
  {
3628
- href,
3629
- className: cn(
3630
- "group flex h-full flex-col gap-3 rounded-[1.25rem] border border-border bg-card p-5 transition-colors hover:border-oca-hairline-strong",
3631
- className
3632
- ),
3671
+ action,
3672
+ method: "get",
3673
+ onSubmit: submit,
3674
+ className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
3633
3675
  children: [
3634
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-3", children: [
3635
- icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground [&_svg]:size-[1.125rem]", children: icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }),
3636
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
3637
- meta,
3638
- /* @__PURE__ */ jsxRuntime.jsx(Arrow, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" })
3639
- ] })
3640
- ] }),
3641
- icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
3642
- description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
3676
+ title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
3677
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: title }) : null,
3678
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
3679
+ ] }) : null,
3680
+ multiline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3681
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, children: /* @__PURE__ */ jsxRuntime.jsx(
3682
+ Textarea,
3683
+ {
3684
+ name: param,
3685
+ required: true,
3686
+ value,
3687
+ onChange: (e) => setValue(e.target.value),
3688
+ placeholder,
3689
+ spellCheck: false,
3690
+ className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
3691
+ }
3692
+ ) }),
3693
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: button })
3694
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsxRuntime.jsx(
3695
+ Input,
3696
+ {
3697
+ name: param,
3698
+ required: true,
3699
+ value,
3700
+ onChange: (e) => setValue(e.target.value),
3701
+ placeholder,
3702
+ spellCheck: false,
3703
+ autoComplete: "off",
3704
+ className: "font-mono text-base md:text-[0.875rem]"
3705
+ }
3706
+ ) })
3643
3707
  ]
3644
3708
  }
3645
3709
  );
3646
3710
  }
3647
- function CardGrid({ columns = 2, children, className }) {
3648
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("not-prose my-6 grid grid-cols-1 gap-3 sm:grid-cols-2", columns === 3 && "lg:grid-cols-3", className), children });
3649
- }
3650
- function MdxTable({ className, ...props }) {
3651
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "not-prose my-6 overflow-hidden rounded-2xl border border-border bg-card", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
3652
- "table",
3653
- {
3654
- className: cn(
3655
- "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
3656
- "[&_th]:whitespace-nowrap [&_th]:border-b [&_th]:border-oca-hairline-strong [&_th]:bg-oca-table-head [&_th]:px-4 [&_th]:py-2.5 [&_th]:text-[0.8125rem] [&_th]:font-medium [&_th]:text-foreground",
3657
- "[&_td]:border-t [&_td]:border-border [&_td]:px-4 [&_td]:py-2.5 [&_td]:align-top [&_td]:text-muted-foreground [&_tbody_tr:first-child_td]:border-t-0",
3658
- "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
3659
- "[&_[align=center]]:text-center [&_[align=right]]:text-right",
3660
- // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
3661
- "max-sm:[&_td]:min-w-[9rem]",
3662
- className
3663
- ),
3664
- ...props
3665
- }
3666
- ) }) });
3667
- }
3668
- function ApiTable({
3711
+ var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
3712
+ function ComparisonTable({
3713
+ columns,
3669
3714
  rows,
3670
- caption,
3671
- nameHeader = "Name",
3715
+ label,
3716
+ propertyHeading = "Property",
3672
3717
  className
3673
3718
  }) {
3674
- const hasDefault = rows.some((r) => r.default !== void 0);
3675
- const marks = (r) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3676
- r.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
3677
- r.deprecated ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
3678
- r.status ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: r.status }) : null
3679
- ] });
3680
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("not-prose my-6", className), children: [
3681
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-2xl border border-border bg-card max-sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse text-left text-[0.875rem]", children: [
3682
- caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
3683
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
3684
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
3685
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
3686
- hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
3687
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" })
3688
- ] }) }),
3689
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "align-top", children: [
3690
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "row", className: "px-4 py-3 text-left font-normal", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-start gap-1", children: [
3691
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3692
- marks(r)
3693
- ] }) }),
3694
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.type ?? "\u2014" }),
3695
- hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.default ?? "\u2014" }) : null,
3696
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 leading-relaxed text-muted-foreground", children: r.description })
3697
- ] }, r.name)) })
3698
- ] }) }) }),
3699
- /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": caption, className: "divide-y divide-border rounded-2xl border border-border bg-card sm:hidden", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex flex-col gap-1.5 px-4 py-3.5", children: [
3700
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
3701
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.875rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3702
- r.type ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "break-all font-mono text-[0.8125rem] text-muted-foreground", children: r.type }) : null
3703
- ] }),
3704
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-2 empty:hidden", children: marks(r) }),
3705
- r.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-relaxed text-muted-foreground", children: r.description }) : null,
3706
- r.default !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.8125rem] text-muted-foreground", children: [
3707
- "Default ",
3708
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-foreground", children: r.default })
3709
- ] }) : null
3710
- ] }, r.name)) })
3711
- ] });
3712
- }
3713
- function useDarkMode() {
3714
- const [dark, setDark] = react.useState(false);
3715
- react.useEffect(() => {
3716
- const root = document.documentElement;
3717
- const read = () => setDark(root.classList.contains("dark"));
3718
- read();
3719
- const mo = new MutationObserver(read);
3720
- mo.observe(root, { attributes: true, attributeFilter: ["class"] });
3721
- return () => mo.disconnect();
3722
- }, []);
3723
- return dark;
3724
- }
3725
- function mermaidTheme(el) {
3726
- const css = getComputedStyle(el);
3727
- const v = (name) => css.getPropertyValue(name).trim();
3728
- const card = v("--card");
3729
- const muted = v("--muted");
3730
- const text = v("--foreground");
3731
- const subtle = v("--muted-foreground");
3732
- const line = v("--input");
3733
- const hair = v("--oca-hairline-strong");
3734
- return {
3735
- background: "transparent",
3736
- fontFamily: css.fontFamily,
3737
- fontSize: "14px",
3738
- textColor: text,
3739
- mainBkg: card,
3740
- primaryColor: card,
3741
- primaryTextColor: text,
3742
- primaryBorderColor: hair,
3743
- secondaryColor: muted,
3744
- secondaryTextColor: text,
3745
- secondaryBorderColor: hair,
3746
- tertiaryColor: muted,
3747
- tertiaryTextColor: text,
3748
- tertiaryBorderColor: hair,
3749
- nodeBorder: hair,
3750
- lineColor: line,
3751
- edgeLabelBackground: card,
3752
- clusterBkg: muted,
3753
- clusterBorder: hair,
3754
- titleColor: text,
3755
- noteBkgColor: muted,
3756
- noteTextColor: text,
3757
- noteBorderColor: hair,
3758
- actorBkg: card,
3759
- actorBorder: hair,
3760
- actorTextColor: text,
3761
- actorLineColor: line,
3762
- signalColor: text,
3763
- signalTextColor: text,
3764
- labelBoxBkgColor: card,
3765
- labelBoxBorderColor: hair,
3766
- labelTextColor: text,
3767
- loopTextColor: subtle,
3768
- activationBkgColor: muted,
3769
- activationBorderColor: hair,
3770
- sequenceNumberColor: card
3719
+ const wide = columns.length > 3;
3720
+ const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
3721
+ const desk = wide ? "lg" : "md";
3722
+ const style = {
3723
+ // The argued-for column gets a little more room: its answers carry the page.
3724
+ "--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
3771
3725
  };
3772
- }
3773
- function naturalSize(svg) {
3774
- const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
3775
- if (!w) return svg;
3776
- return svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${Math.ceil(Number(w))}"`).replace(/max-width:\s*[\d.]+px;?/, "");
3777
- }
3778
- function Diagram({ chart, caption, load, className }) {
3779
- const ref = react.useRef(null);
3780
- const dark = useDarkMode();
3781
- const raw = react.useId();
3782
- const [svg, setSvg] = react.useState(null);
3783
- const [failed, setFailed] = react.useState(false);
3784
- react.useEffect(() => {
3785
- let live = true;
3786
- const el = ref.current;
3787
- if (!el) return;
3788
- (async () => {
3789
- try {
3790
- const mod = await load();
3791
- const mermaid = "default" in mod ? mod.default : mod;
3792
- mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
3793
- const { svg: drawn } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
3794
- if (live) {
3795
- setSvg(naturalSize(drawn));
3796
- setFailed(false);
3797
- }
3798
- } catch {
3799
- if (live) setFailed(true);
3800
- }
3801
- })();
3802
- return () => {
3803
- live = false;
3804
- };
3805
- }, [chart, dark, load, raw]);
3806
- if (failed) return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
3807
- return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
3808
- svg ? /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
3809
- "div",
3726
+ const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
3727
+ return /* @__PURE__ */ jsxRuntime.jsxs("ul", { "aria-label": label, style, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: [
3728
+ /* @__PURE__ */ jsxRuntime.jsxs(
3729
+ "li",
3810
3730
  {
3811
- className: "flex w-max min-w-full justify-center p-6 [&_svg]:h-auto [&_svg]:max-w-none",
3812
- role: "img",
3813
- "aria-label": typeof caption === "string" ? caption : "Diagram",
3814
- dangerouslySetInnerHTML: { __html: svg }
3731
+ "aria-hidden": true,
3732
+ className: cn(
3733
+ "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
3734
+ wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
3735
+ grid
3736
+ ),
3737
+ children: [
3738
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: propertyHeading }),
3739
+ columns.map((c) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(c.highlight && cn(TINT, "-my-4 px-4 py-4 text-oca-accent-ink")), children: c.label }, c.key))
3740
+ ]
3815
3741
  }
3816
- ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-label": "Drawing the diagram", className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-40 w-full rounded-xl" }) }),
3817
- caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
3742
+ ),
3743
+ rows.map((r, ri) => /* @__PURE__ */ jsxRuntime.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: [
3744
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
3745
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-title-sm", children: r.label }),
3746
+ r.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
3747
+ ] }),
3748
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
3749
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3750
+ "div",
3751
+ {
3752
+ style: { "--oca-order": ordered.indexOf(c) },
3753
+ className: cn(
3754
+ // Two rows of the pair's grid (name, answer), so answers line up
3755
+ // across a pair even when one name wraps.
3756
+ "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
3757
+ 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",
3758
+ c.highlight ? cn(
3759
+ TINT,
3760
+ "col-span-2",
3761
+ 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"
3762
+ ) : desk === "lg" ? "lg:p-0" : "md:p-0"
3763
+ ),
3764
+ children: [
3765
+ /* @__PURE__ */ jsxRuntime.jsx(
3766
+ "span",
3767
+ {
3768
+ className: cn(
3769
+ "text-[0.8125rem]",
3770
+ c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
3771
+ desk === "lg" ? "lg:sr-only" : "md:sr-only"
3772
+ ),
3773
+ children: c.label
3774
+ }
3775
+ ),
3776
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
3777
+ ]
3778
+ },
3779
+ c.key
3780
+ );
3781
+ }) })
3782
+ ] }, ri))
3818
3783
  ] });
3819
3784
  }
3820
- var HEADING = {
3821
- h1: "oca-display-3 mb-4 text-foreground",
3822
- h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
3823
- h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
3824
- h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
3785
+ var CHECK = {
3786
+ ok: { word: "Passed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}), tone: "text-success" },
3787
+ fail: { word: "Failed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}), tone: "text-destructive" },
3788
+ pending: { word: "Pending", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, {}), tone: "text-oca-accent-ink" },
3789
+ none: { word: "None", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlash, {}), tone: "text-muted-foreground" },
3790
+ skipped: { word: "Skipped", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleMinus, {}), tone: "text-muted-foreground" },
3791
+ unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, {}), tone: "text-oca-subtle" }
3825
3792
  };
3826
- function DocsHeading({
3827
- as: Tag,
3828
- id,
3829
- children,
3830
- className,
3831
- ...props
3793
+ function VerifyReport({
3794
+ verdict,
3795
+ title,
3796
+ summary,
3797
+ checks,
3798
+ facts,
3799
+ notChecked,
3800
+ actions,
3801
+ as: Heading = "h2",
3802
+ className
3832
3803
  }) {
3833
- return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
3834
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-heading-text": "", children }),
3835
- id && Tag !== "h1" ? /* @__PURE__ */ jsxRuntime.jsxs(
3836
- "a",
3804
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3805
+ "section",
3806
+ {
3807
+ "aria-label": "Verification result",
3808
+ className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
3809
+ children: [
3810
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
3811
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verdict }),
3812
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-display-3 [overflow-wrap:anywhere]", children: title }),
3813
+ summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body max-w-[40rem] [overflow-wrap:anywhere]", children: summary }) : null
3814
+ ] }),
3815
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
3816
+ const k = CHECK[c.state];
3817
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
3818
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
3819
+ /* @__PURE__ */ jsxRuntime.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: [
3820
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
3821
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem]", children: c.label }),
3822
+ c.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
3823
+ ] }),
3824
+ /* @__PURE__ */ jsxRuntime.jsx(
3825
+ "span",
3826
+ {
3827
+ className: cn(
3828
+ "shrink-0 text-[0.8125rem]",
3829
+ c.state === "fail" ? "text-destructive" : "text-muted-foreground"
3830
+ ),
3831
+ children: k.word
3832
+ }
3833
+ )
3834
+ ] })
3835
+ ] }, i);
3836
+ }) }),
3837
+ facts && facts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { items: facts, className: "rounded-none border-x-0 border-b-0 bg-transparent [&>div]:px-6 md:[&>div]:px-8" }) : null,
3838
+ notChecked && notChecked.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 border-t border-border bg-muted/50 px-6 py-5 md:px-8", children: [
3839
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
3840
+ /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("li", { children: n }, i)) })
3841
+ ] }) : null,
3842
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-3 border-t border-border px-6 py-5 md:px-8", children: actions }) : null
3843
+ ]
3844
+ }
3845
+ );
3846
+ }
3847
+ function SignMessage({
3848
+ lead,
3849
+ address,
3850
+ message,
3851
+ wallets,
3852
+ busy = false,
3853
+ error,
3854
+ submitLabel = "Confirm",
3855
+ secondary,
3856
+ onSignature,
3857
+ className
3858
+ }) {
3859
+ const [pasted, setPasted] = react.useState("");
3860
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
3861
+ lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
3862
+ wallets ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3863
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
3864
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
3865
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
3866
+ "or sign it in any wallet",
3867
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
3868
+ ] })
3869
+ ] }) : null,
3870
+ /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3871
+ /* @__PURE__ */ jsxRuntime.jsxs(
3872
+ "form",
3837
3873
  {
3838
- href: `#${id}`,
3839
- className: "ml-2 inline-block rounded-md px-1 align-baseline text-[0.85em] font-normal text-oca-subtle no-underline opacity-0 transition-opacity hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100",
3874
+ className: "flex flex-col gap-4",
3875
+ onSubmit: (e) => {
3876
+ e.preventDefault();
3877
+ if (pasted.trim()) onSignature(pasted.trim());
3878
+ },
3840
3879
  children: [
3841
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
3842
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Link to this section" })
3880
+ /* @__PURE__ */ jsxRuntime.jsx(
3881
+ Field,
3882
+ {
3883
+ label: "Signature",
3884
+ error,
3885
+ hint: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3886
+ "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3887
+ " ",
3888
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all font-mono", children: address }),
3889
+ "."
3890
+ ] }),
3891
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3892
+ Textarea,
3893
+ {
3894
+ value: pasted,
3895
+ onChange: (e) => setPasted(e.target.value),
3896
+ rows: 3,
3897
+ spellCheck: false,
3898
+ className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
3899
+ }
3900
+ )
3901
+ }
3902
+ ),
3903
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
3904
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
3905
+ secondary
3906
+ ] })
3843
3907
  ]
3844
3908
  }
3845
- ) : null
3909
+ )
3846
3910
  ] });
3847
3911
  }
3848
3912
  function useMacKeys() {