@orangecheck/app-design 1.3.0 → 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.
@@ -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,
@@ -3114,737 +3133,780 @@ react.forwardRef(function RadioGroupItem2({ className, ...props }, ref) {
3114
3133
  }
3115
3134
  );
3116
3135
  });
3117
- function ProtocolHero({
3118
- 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",
3119
3240
  title,
3120
- lead,
3121
- actions,
3122
- art,
3123
3241
  children,
3124
3242
  className
3125
3243
  }) {
3126
- const p = protocolSite(protocol2);
3127
3244
  return /* @__PURE__ */ jsxRuntime.jsx(
3128
- PageHero,
3245
+ Notice,
3129
3246
  {
3130
- className,
3131
- eyebrow: `Protocol \xB7 ${p.verb}`,
3247
+ tone: CALLOUT_TONE[tone],
3132
3248
  title,
3133
- lead,
3134
- actions,
3135
- art,
3136
- children: p.status !== "live" || children ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-4", children: [
3137
- p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null,
3138
- children
3139
- ] }) : 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
3140
3252
  }
3141
3253
  );
3142
3254
  }
3143
- function ProtocolNav({
3144
- current,
3145
- link = "page",
3146
- className
3147
- }) {
3148
- 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) => {
3149
- const on = p.slug === current;
3150
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
3151
- "a",
3152
- {
3153
- href: link === "tool" ? p.toolHref : p.pageHref,
3154
- "aria-current": on ? "page" : void 0,
3155
- className: cn(
3156
- "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
3157
- on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3158
- ),
3159
- children: p.label
3160
- }
3161
- ) }, p.slug);
3162
- }) }) }) });
3163
- }
3164
- function SpecCard({
3165
- protocol: protocol2,
3166
- version,
3167
- license,
3168
- vectors,
3169
- size = "md",
3170
- className
3171
- }) {
3172
- const p = protocolSite(protocol2);
3173
- const repo = `oc-${p.slug}-protocol`;
3174
- const facts = [
3175
- ["Version", version],
3176
- ...license ? [["Licence", license]] : [],
3177
- ["Nostr kind", p.kinds],
3178
- ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
3179
- ];
3180
- if (size === "sm") {
3181
- return /* @__PURE__ */ jsxRuntime.jsxs(
3182
- "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",
3183
3259
  {
3184
- href: p.specHref,
3185
- className: cn(
3186
- "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",
3187
- className
3188
- ),
3189
- children: [
3190
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
3191
- /* @__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 ") }),
3192
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
3193
- "Read the spec ",
3194
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
3195
- ] })
3196
- ]
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)]"
3197
3262
  }
3198
- );
3199
- }
3200
- 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: [
3201
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3202
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
3203
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
3204
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
3205
- ] }),
3206
- p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
3207
- ] }),
3208
- /* @__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: [
3209
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
3210
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
3211
- ] }, k)) }),
3212
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: p.specHref, children: [
3213
- "Read the spec ",
3214
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true })
3215
- ] }) }) })
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 })
3216
3267
  ] });
3217
3268
  }
3218
- function VerifyBox({
3219
- action,
3220
- 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,
3221
3274
  title,
3222
3275
  description,
3223
- label = "Id, envelope or link",
3224
- placeholder,
3225
- hint,
3226
- submitLabel = "Verify",
3227
- multiline = false,
3228
- onVerify,
3276
+ icon,
3277
+ meta,
3229
3278
  className
3230
3279
  }) {
3231
- const [value, setValue] = react.useState("");
3232
- const submit = (e) => {
3233
- if (!onVerify) return;
3234
- e.preventDefault();
3235
- if (value.trim()) onVerify(value.trim());
3236
- };
3237
- 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;
3238
3281
  return /* @__PURE__ */ jsxRuntime.jsxs(
3239
- "form",
3282
+ DocLink,
3240
3283
  {
3241
- action,
3242
- method: "get",
3243
- onSubmit: submit,
3244
- 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
+ ),
3245
3289
  children: [
3246
- title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
3247
- title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: title }) : null,
3248
- description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
3249
- ] }) : null,
3250
- multiline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3251
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, children: /* @__PURE__ */ jsxRuntime.jsx(
3252
- Textarea,
3253
- {
3254
- name: param,
3255
- required: true,
3256
- value,
3257
- onChange: (e) => setValue(e.target.value),
3258
- placeholder,
3259
- spellCheck: false,
3260
- className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
3261
- }
3262
- ) }),
3263
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: button })
3264
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsxRuntime.jsx(
3265
- Input,
3266
- {
3267
- name: param,
3268
- required: true,
3269
- value,
3270
- onChange: (e) => setValue(e.target.value),
3271
- placeholder,
3272
- spellCheck: false,
3273
- autoComplete: "off",
3274
- className: "font-mono text-base md:text-[0.875rem]"
3275
- }
3276
- ) })
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
3277
3299
  ]
3278
3300
  }
3279
3301
  );
3280
3302
  }
3281
- var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
3282
- function ComparisonTable({
3283
- 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({
3284
3326
  rows,
3285
- label,
3286
- propertyHeading = "Property",
3327
+ caption,
3328
+ nameHeader = "Name",
3287
3329
  className
3288
3330
  }) {
3289
- const wide = columns.length > 3;
3290
- const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
3291
- const desk = wide ? "lg" : "md";
3292
- const style = {
3293
- // The argued-for column gets a little more room: its answers carry the page.
3294
- "--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
3295
3427
  };
3296
- const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
3297
- 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: [
3298
- /* @__PURE__ */ jsxRuntime.jsxs(
3299
- "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",
3300
3484
  {
3301
- "aria-hidden": true,
3485
+ "data-fit": fits ? "" : void 0,
3302
3486
  className: cn(
3303
- "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
3304
- wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
3305
- 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"
3306
3489
  ),
3307
- children: [
3308
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: propertyHeading }),
3309
- 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))
3310
- ]
3490
+ role: "img",
3491
+ "aria-label": typeof caption === "string" ? caption : "Diagram",
3492
+ dangerouslySetInnerHTML: { __html: drawn.svg }
3311
3493
  }
3312
- ),
3313
- 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: [
3314
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
3315
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-title-sm", children: r.label }),
3316
- r.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
3317
- ] }),
3318
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
3319
- return /* @__PURE__ */ jsxRuntime.jsxs(
3320
- "div",
3321
- {
3322
- style: { "--oca-order": ordered.indexOf(c) },
3323
- className: cn(
3324
- // Two rows of the pair's grid (name, answer), so answers line up
3325
- // across a pair even when one name wraps.
3326
- "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
3327
- 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",
3328
- c.highlight ? cn(
3329
- TINT,
3330
- "col-span-2",
3331
- 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"
3332
- ) : desk === "lg" ? "lg:p-0" : "md:p-0"
3333
- ),
3334
- children: [
3335
- /* @__PURE__ */ jsxRuntime.jsx(
3336
- "span",
3337
- {
3338
- className: cn(
3339
- "text-[0.8125rem]",
3340
- c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
3341
- desk === "lg" ? "lg:sr-only" : "md:sr-only"
3342
- ),
3343
- children: c.label
3344
- }
3345
- ),
3346
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
3347
- ]
3348
- },
3349
- c.key
3350
- );
3351
- }) })
3352
- ] }, 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
3353
3496
  ] });
3354
3497
  }
3355
- var CHECK = {
3356
- ok: { word: "Passed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}), tone: "text-success" },
3357
- fail: { word: "Failed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}), tone: "text-destructive" },
3358
- pending: { word: "Pending", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, {}), tone: "text-oca-accent-ink" },
3359
- none: { word: "None", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlash, {}), tone: "text-muted-foreground" },
3360
- skipped: { word: "Skipped", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleMinus, {}), tone: "text-muted-foreground" },
3361
- 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"
3362
3503
  };
3363
- function VerifyReport({
3364
- verdict,
3365
- title,
3366
- summary,
3367
- checks,
3368
- facts,
3369
- notChecked,
3370
- actions,
3371
- as: Heading = "h2",
3372
- className
3504
+ function DocsHeading({
3505
+ as: Tag,
3506
+ id,
3507
+ children,
3508
+ className,
3509
+ ...props
3373
3510
  }) {
3374
- return /* @__PURE__ */ jsxRuntime.jsxs(
3375
- "section",
3376
- {
3377
- "aria-label": "Verification result",
3378
- className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
3379
- children: [
3380
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
3381
- /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verdict }),
3382
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-display-3 [overflow-wrap:anywhere]", children: title }),
3383
- summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body max-w-[40rem] [overflow-wrap:anywhere]", children: summary }) : null
3384
- ] }),
3385
- /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
3386
- const k = CHECK[c.state];
3387
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
3388
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
3389
- /* @__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: [
3390
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
3391
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem]", children: c.label }),
3392
- c.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
3393
- ] }),
3394
- /* @__PURE__ */ jsxRuntime.jsx(
3395
- "span",
3396
- {
3397
- className: cn(
3398
- "shrink-0 text-[0.8125rem]",
3399
- c.state === "fail" ? "text-destructive" : "text-muted-foreground"
3400
- ),
3401
- children: k.word
3402
- }
3403
- )
3404
- ] })
3405
- ] }, i);
3406
- }) }),
3407
- 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,
3408
- 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: [
3409
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
3410
- /* @__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)) })
3411
- ] }) : null,
3412
- 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
3413
- ]
3414
- }
3415
- );
3416
- }
3417
- function SignMessage({
3418
- lead,
3419
- address,
3420
- message,
3421
- wallets,
3422
- busy = false,
3423
- error,
3424
- submitLabel = "Confirm",
3425
- secondary,
3426
- onSignature,
3427
- className
3428
- }) {
3429
- const [pasted, setPasted] = react.useState("");
3430
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
3431
- lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
3432
- wallets ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3433
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
3434
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
3435
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
3436
- "or sign it in any wallet",
3437
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
3438
- ] })
3439
- ] }) : null,
3440
- /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3441
- /* @__PURE__ */ jsxRuntime.jsxs(
3442
- "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",
3443
3515
  {
3444
- className: "flex flex-col gap-4",
3445
- onSubmit: (e) => {
3446
- e.preventDefault();
3447
- if (pasted.trim()) onSignature(pasted.trim());
3448
- },
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",
3449
3518
  children: [
3450
- /* @__PURE__ */ jsxRuntime.jsx(
3451
- Field,
3452
- {
3453
- label: "Signature",
3454
- error,
3455
- hint: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3456
- "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3457
- " ",
3458
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all font-mono", children: address }),
3459
- "."
3460
- ] }),
3461
- children: /* @__PURE__ */ jsxRuntime.jsx(
3462
- Textarea,
3463
- {
3464
- value: pasted,
3465
- onChange: (e) => setPasted(e.target.value),
3466
- rows: 3,
3467
- spellCheck: false,
3468
- className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
3469
- }
3470
- )
3471
- }
3472
- ),
3473
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
3474
- /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
3475
- secondary
3476
- ] })
3519
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
3520
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Link to this section" })
3477
3521
  ]
3478
3522
  }
3479
- )
3480
- ] });
3481
- }
3482
- var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
3483
- function DocLink({ href, className, children, ...rest }) {
3484
- return isInternal(href) ? /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, ...rest, children });
3485
- }
3486
- function Breadcrumbs({ items, action, className }) {
3487
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
3488
- /* @__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) => {
3489
- const last = i === items.length - 1;
3490
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
3491
- 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 }),
3492
- !last ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
3493
- ] }, i);
3494
- }) }) }),
3495
- action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
3496
- ] });
3497
- }
3498
- function DocsPager({ prev, next, className }) {
3499
- if (!prev && !next) return null;
3500
- const card = (l, dir) => /* @__PURE__ */ jsxRuntime.jsxs(
3501
- DocLink,
3502
- {
3503
- href: l.href,
3504
- className: cn(
3505
- "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",
3506
- dir === "next" && "items-end text-right sm:col-start-2"
3507
- ),
3508
- children: [
3509
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
3510
- dir === "prev" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
3511
- dir === "prev" ? "Previous" : "Next",
3512
- l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
3513
- l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: l.section }) : null,
3514
- dir === "next" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
3515
- ] }),
3516
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
3517
- ]
3518
- }
3519
- );
3520
- 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: [
3521
- prev ? card(prev, "prev") : null,
3522
- next ? card(next, "next") : null
3523
+ ) : null
3523
3524
  ] });
3524
3525
  }
3525
- function useHeadings(selector = "#docs-content", key) {
3526
- const [items, setItems] = react.useState([]);
3527
- react.useEffect(() => {
3528
- const read = () => {
3529
- const root = document.querySelector(selector);
3530
- if (!root) return setItems([]);
3531
- setItems(
3532
- Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
3533
- id: h.id,
3534
- // The anchor link's "#" is not part of the name.
3535
- label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
3536
- level: h.tagName === "H3" ? 3 : 2
3537
- }))
3538
- );
3539
- };
3540
- const raf = requestAnimationFrame(read);
3541
- const t = setTimeout(read, 80);
3542
- return () => {
3543
- cancelAnimationFrame(raf);
3544
- clearTimeout(t);
3545
- };
3546
- }, [selector, key]);
3547
- const activeId = useActiveHeading(items.map((i) => i.id));
3548
- return { items, activeId };
3549
- }
3550
- function OnThisPage({
3551
- items,
3552
- activeId,
3553
- title = "On this page",
3554
- onNavigate,
3555
- className
3556
- }) {
3557
- const id = react.useId();
3558
- if (items.length === 0) return null;
3559
- return (
3560
- // With no visible title (a folded list under its own summary) the name is still "On this page".
3561
- /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
3562
- title ? /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
3563
- /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((t) => {
3564
- const on = t.id === activeId;
3565
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
3566
- "a",
3567
- {
3568
- href: `#${t.id}`,
3569
- onClick: onNavigate,
3570
- "aria-current": on ? "location" : void 0,
3571
- className: cn(
3572
- "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
3573
- t.level === 3 ? "pl-7" : "pl-4",
3574
- on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
3575
- ),
3576
- children: t.label
3577
- }
3578
- ) }, t.id);
3579
- }) })
3580
- ] })
3581
- );
3582
- }
3583
- var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
3584
- function Callout({
3585
- tone = "note",
3526
+ function ProtocolHero({
3527
+ protocol: protocol2,
3586
3528
  title,
3529
+ lead,
3530
+ actions,
3531
+ art,
3587
3532
  children,
3588
3533
  className
3589
3534
  }) {
3535
+ const p = protocolSite(protocol2);
3590
3536
  return /* @__PURE__ */ jsxRuntime.jsx(
3591
- Notice,
3537
+ PageHero,
3592
3538
  {
3593
- tone: CALLOUT_TONE[tone],
3539
+ className,
3540
+ eyebrow: `Protocol \xB7 ${p.verb}`,
3594
3541
  title,
3595
- role: "note",
3596
- className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
3597
- 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
3598
3549
  }
3599
3550
  );
3600
3551
  }
3601
- function Step({ title, id, children }) {
3602
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
3603
- /* @__PURE__ */ jsxRuntime.jsx(
3604
- "span",
3605
- {
3606
- "aria-hidden": true,
3607
- 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)]"
3608
- }
3609
- ),
3610
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
3611
- /* @__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 }),
3612
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
3613
- ] });
3614
- }
3615
- function Steps({ children, className }) {
3616
- 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 });
3617
- }
3618
- function LinkCard({
3619
- href,
3620
- title,
3621
- description,
3622
- icon,
3623
- meta,
3552
+ function ProtocolNav({
3553
+ current,
3554
+ link = "page",
3624
3555
  className
3625
3556
  }) {
3626
- 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 });
3627
3668
  return /* @__PURE__ */ jsxRuntime.jsxs(
3628
- DocLink,
3669
+ "form",
3629
3670
  {
3630
- href,
3631
- className: cn(
3632
- "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",
3633
- className
3634
- ),
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),
3635
3675
  children: [
3636
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-3", children: [
3637
- 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 }),
3638
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
3639
- meta,
3640
- /* @__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" })
3641
- ] })
3642
- ] }),
3643
- icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
3644
- 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
+ ) })
3645
3707
  ]
3646
3708
  }
3647
3709
  );
3648
3710
  }
3649
- function CardGrid({ columns = 2, children, className }) {
3650
- 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 });
3651
- }
3652
- function MdxTable({ className, ...props }) {
3653
- 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(
3654
- "table",
3655
- {
3656
- className: cn(
3657
- "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
3658
- "[&_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",
3659
- "[&_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",
3660
- "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
3661
- "[&_[align=center]]:text-center [&_[align=right]]:text-right",
3662
- // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
3663
- "max-sm:[&_td]:min-w-[9rem]",
3664
- className
3665
- ),
3666
- ...props
3667
- }
3668
- ) }) });
3669
- }
3670
- function ApiTable({
3711
+ var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
3712
+ function ComparisonTable({
3713
+ columns,
3671
3714
  rows,
3672
- caption,
3673
- nameHeader = "Name",
3715
+ label,
3716
+ propertyHeading = "Property",
3674
3717
  className
3675
3718
  }) {
3676
- const hasDefault = rows.some((r) => r.default !== void 0);
3677
- const marks = (r) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3678
- r.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
3679
- r.deprecated ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
3680
- r.status ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: r.status }) : null
3681
- ] });
3682
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("not-prose my-6", className), children: [
3683
- /* @__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: [
3684
- caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
3685
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
3686
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
3687
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
3688
- hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
3689
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" })
3690
- ] }) }),
3691
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "align-top", children: [
3692
- /* @__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: [
3693
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3694
- marks(r)
3695
- ] }) }),
3696
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.type ?? "\u2014" }),
3697
- hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.default ?? "\u2014" }) : null,
3698
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 leading-relaxed text-muted-foreground", children: r.description })
3699
- ] }, r.name)) })
3700
- ] }) }) }),
3701
- /* @__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: [
3702
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
3703
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.875rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3704
- r.type ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "break-all font-mono text-[0.8125rem] text-muted-foreground", children: r.type }) : null
3705
- ] }),
3706
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-2 empty:hidden", children: marks(r) }),
3707
- r.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-relaxed text-muted-foreground", children: r.description }) : null,
3708
- r.default !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.8125rem] text-muted-foreground", children: [
3709
- "Default ",
3710
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-foreground", children: r.default })
3711
- ] }) : null
3712
- ] }, r.name)) })
3713
- ] });
3714
- }
3715
- function useDarkMode() {
3716
- const [dark, setDark] = react.useState(false);
3717
- react.useEffect(() => {
3718
- const root = document.documentElement;
3719
- const read = () => setDark(root.classList.contains("dark"));
3720
- read();
3721
- const mo = new MutationObserver(read);
3722
- mo.observe(root, { attributes: true, attributeFilter: ["class"] });
3723
- return () => mo.disconnect();
3724
- }, []);
3725
- return dark;
3726
- }
3727
- function mermaidTheme(el) {
3728
- const css = getComputedStyle(el);
3729
- const v = (name) => css.getPropertyValue(name).trim();
3730
- const card = v("--card");
3731
- const muted = v("--muted");
3732
- const text = v("--foreground");
3733
- const subtle = v("--muted-foreground");
3734
- const line = v("--input");
3735
- const hair = v("--oca-hairline-strong");
3736
- return {
3737
- background: "transparent",
3738
- fontFamily: css.fontFamily,
3739
- fontSize: "14px",
3740
- textColor: text,
3741
- mainBkg: card,
3742
- primaryColor: card,
3743
- primaryTextColor: text,
3744
- primaryBorderColor: hair,
3745
- secondaryColor: muted,
3746
- secondaryTextColor: text,
3747
- secondaryBorderColor: hair,
3748
- tertiaryColor: muted,
3749
- tertiaryTextColor: text,
3750
- tertiaryBorderColor: hair,
3751
- nodeBorder: hair,
3752
- lineColor: line,
3753
- edgeLabelBackground: card,
3754
- clusterBkg: muted,
3755
- clusterBorder: hair,
3756
- titleColor: text,
3757
- noteBkgColor: muted,
3758
- noteTextColor: text,
3759
- noteBorderColor: hair,
3760
- actorBkg: card,
3761
- actorBorder: hair,
3762
- actorTextColor: text,
3763
- actorLineColor: line,
3764
- signalColor: text,
3765
- signalTextColor: text,
3766
- labelBoxBkgColor: card,
3767
- labelBoxBorderColor: hair,
3768
- labelTextColor: text,
3769
- loopTextColor: subtle,
3770
- activationBkgColor: muted,
3771
- activationBorderColor: hair,
3772
- 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(" ")
3773
3725
  };
3774
- }
3775
- function naturalSize(svg) {
3776
- const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
3777
- if (!w) return svg;
3778
- return svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${Math.ceil(Number(w))}"`).replace(/max-width:\s*[\d.]+px;?/, "");
3779
- }
3780
- function Diagram({ chart, caption, load, className }) {
3781
- const ref = react.useRef(null);
3782
- const dark = useDarkMode();
3783
- const raw = react.useId();
3784
- const [svg, setSvg] = react.useState(null);
3785
- const [failed, setFailed] = react.useState(false);
3786
- react.useEffect(() => {
3787
- let live = true;
3788
- const el = ref.current;
3789
- if (!el) return;
3790
- (async () => {
3791
- try {
3792
- const mod = await load();
3793
- const mermaid = "default" in mod ? mod.default : mod;
3794
- mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
3795
- const { svg: drawn } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
3796
- if (live) {
3797
- setSvg(naturalSize(drawn));
3798
- setFailed(false);
3799
- }
3800
- } catch {
3801
- if (live) setFailed(true);
3802
- }
3803
- })();
3804
- return () => {
3805
- live = false;
3806
- };
3807
- }, [chart, dark, load, raw]);
3808
- if (failed) return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
3809
- return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
3810
- svg ? /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
3811
- "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",
3812
3730
  {
3813
- className: "flex w-max min-w-full justify-center p-6 [&_svg]:h-auto [&_svg]:max-w-none",
3814
- role: "img",
3815
- "aria-label": typeof caption === "string" ? caption : "Diagram",
3816
- 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
+ ]
3817
3741
  }
3818
- ) }) : /* @__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" }) }),
3819
- 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))
3820
3783
  ] });
3821
3784
  }
3822
- var HEADING = {
3823
- h1: "oca-display-3 mb-4 text-foreground",
3824
- h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
3825
- h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
3826
- 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" }
3827
3792
  };
3828
- function DocsHeading({
3829
- as: Tag,
3830
- id,
3831
- children,
3832
- className,
3833
- ...props
3793
+ function VerifyReport({
3794
+ verdict,
3795
+ title,
3796
+ summary,
3797
+ checks,
3798
+ facts,
3799
+ notChecked,
3800
+ actions,
3801
+ as: Heading = "h2",
3802
+ className
3834
3803
  }) {
3835
- return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
3836
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-heading-text": "", children }),
3837
- id && Tag !== "h1" ? /* @__PURE__ */ jsxRuntime.jsxs(
3838
- "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",
3839
3873
  {
3840
- href: `#${id}`,
3841
- 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
+ },
3842
3879
  children: [
3843
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
3844
- /* @__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
+ ] })
3845
3907
  ]
3846
3908
  }
3847
- ) : null
3909
+ )
3848
3910
  ] });
3849
3911
  }
3850
3912
  function useMacKeys() {