@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.
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ var PopoverPrimitive = require('@radix-ui/react-popover');
20
20
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
21
21
  var TabsPrimitive = require('@radix-ui/react-tabs');
22
22
  var QRCode = require('qrcode');
23
- var Link8 = require('next/link');
23
+ var Link6 = require('next/link');
24
24
  var router = require('next/compat/router');
25
25
  var nextThemes = require('next-themes');
26
26
 
@@ -56,7 +56,7 @@ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitiv
56
56
  var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
57
57
  var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
58
58
  var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
59
- var Link8__default = /*#__PURE__*/_interopDefault(Link8);
59
+ var Link6__default = /*#__PURE__*/_interopDefault(Link6);
60
60
 
61
61
  // src/tokens/index.ts
62
62
  var APP_ATTRIBUTE = "data-oc-app";
@@ -3006,11 +3006,13 @@ function forClipboard(text, lang) {
3006
3006
  if (!lines.some((l) => l.startsWith("$ "))) return text;
3007
3007
  return lines.filter((l) => l.startsWith("$ ")).map((l) => l.slice(2)).join("\n");
3008
3008
  }
3009
- function linesFromDom(pre) {
3009
+ function linesFromDom(pre, newline) {
3010
3010
  if (!pre) return null;
3011
3011
  const lines = pre.querySelectorAll("[data-line]");
3012
3012
  if (lines.length === 0) return pre.textContent ?? "";
3013
- return Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
3013
+ const text = Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
3014
+ return newline ? `${text}
3015
+ ` : text;
3014
3016
  }
3015
3017
  function prepare(code, lang, marks, diff) {
3016
3018
  const d = diff ? readDiff(code) : null;
@@ -3019,7 +3021,8 @@ function prepare(code, lang, marks, diff) {
3019
3021
  const kept = d ? src.split("\n").filter((_, i) => d.diff.get(i + 1) !== "remove") : null;
3020
3022
  return {
3021
3023
  html: linesToHtml(lines, { highlight: parseLineRanges(marks), diff: d?.diff }),
3022
- copy: kept ? kept.join("\n") : src,
3024
+ // Byte for byte, the final newline too: a hash printed beside the code must match a copy of it.
3025
+ copy: kept ? kept.join("\n") + (/\n$/.test(code) ? "\n" : "") : code,
3023
3026
  lines: lines.length,
3024
3027
  diff: !!d
3025
3028
  };
@@ -3084,6 +3087,7 @@ function CodeBlock({
3084
3087
  code,
3085
3088
  html,
3086
3089
  children,
3090
+ trailingNewline = false,
3087
3091
  lang,
3088
3092
  caption,
3089
3093
  copy = true,
@@ -3104,7 +3108,7 @@ function CodeBlock({
3104
3108
  );
3105
3109
  const markup = prepared?.html ?? html;
3106
3110
  const lines = prepared?.lines ?? (html !== void 0 ? html.split("\n").length : code?.split("\n").length ?? 0);
3107
- const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current) ?? code ?? "", lang);
3111
+ const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current, trailingNewline) ?? code ?? "", lang);
3108
3112
  return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: cn(FRAME, className), children: [
3109
3113
  /* @__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: [
3110
3114
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? languageName(lang) ?? "Code" }),
@@ -3621,7 +3625,7 @@ function ErrorPage({
3621
3625
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead oca-enter [--enter-delay:150ms]", children: detail ?? words.detail }),
3622
3626
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3623
3627
  server ? /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => window.location.reload(), children: "Try again" }) : null,
3624
- /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href: home, children: "Go home" }) })
3628
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: home, children: "Go home" }) })
3625
3629
  ] }) })
3626
3630
  ] }),
3627
3631
  art !== null ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "oca-enter hidden justify-center md:col-span-5 md:flex [--enter-delay:120ms]", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(MarkOutline, { className: "w-full max-w-[20rem] text-oca-hairline-strong" }) }) : null
@@ -3740,16 +3744,25 @@ function Faq({
3740
3744
  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)) });
3741
3745
  }
3742
3746
  var LINK = "text-foreground underline decoration-foreground/35 underline-offset-4 transition-colors hover:decoration-foreground";
3747
+ var SCHEME = /^[a-z][a-z\d+.-]*:/i;
3748
+ function useResolved(href) {
3749
+ const router$1 = router.useRouter();
3750
+ if (!router$1 || !href || href.startsWith("/") || href.startsWith("#") || href.startsWith("?") || SCHEME.test(href)) return href;
3751
+ const here = router$1.asPath.split(/[?#]/)[0] || "/";
3752
+ const url = new URL(href, `https://page.invalid${here}`);
3753
+ return url.pathname + url.search + url.hash;
3754
+ }
3743
3755
  function TextLink({
3744
- href,
3756
+ href: written,
3745
3757
  children,
3746
3758
  external,
3747
3759
  className
3748
3760
  }) {
3761
+ const href = useResolved(written);
3749
3762
  const internal = href.startsWith("/") && !href.startsWith("/api/") && !href.startsWith("/.well-known/");
3750
3763
  const offsite = external ?? /^https?:\/\//.test(href);
3751
3764
  if (internal && !offsite) {
3752
- return /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href, className: cn(LINK, className), children });
3765
+ return /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href, className: cn(LINK, className), children });
3753
3766
  }
3754
3767
  return /* @__PURE__ */ jsxRuntime.jsxs("a", { href, className: cn(LINK, className), ...offsite ? { target: "_blank", rel: "noreferrer" } : {}, children: [
3755
3768
  children,
@@ -4017,6 +4030,10 @@ var OCHK_IO_FOOTER = [
4017
4030
  ]
4018
4031
  }
4019
4032
  ];
4033
+ var InDocsContext = sharedContext("in-docs", false);
4034
+ function useInDocs() {
4035
+ return react.useContext(InDocsContext);
4036
+ }
4020
4037
  var CARD = "group relative flex h-full flex-col rounded-[1.25rem] border border-border bg-card p-6 transition-colors hover:border-oca-hairline-strong md:p-7 has-[a:focus-visible]:ring-2 has-[a:focus-visible]:ring-ring has-[a:focus-visible]:ring-offset-2 has-[a:focus-visible]:ring-offset-background";
4021
4038
  var STRETCH = 'outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-[""]';
4022
4039
  var pad2 = (n) => String(n + 1).padStart(2, "0");
@@ -4025,6 +4042,7 @@ function ProtocolGrid({
4025
4042
  link = "page",
4026
4043
  className
4027
4044
  }) {
4045
+ const inDocs = useInDocs();
4028
4046
  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) => {
4029
4047
  const p = protocolSite(slug);
4030
4048
  const i = PROTOCOL_ORDER.indexOf(slug);
@@ -4037,7 +4055,7 @@ function ProtocolGrid({
4037
4055
  ] }),
4038
4056
  p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
4039
4057
  ] }),
4040
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsxRuntime.jsx(
4058
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-display-3", children: link === "docs" && inDocs ? /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: `/${p.slug}`, className: STRETCH, children: p.label }) : /* @__PURE__ */ jsxRuntime.jsx(
4041
4059
  "a",
4042
4060
  {
4043
4061
  href: link === "tool" ? p.toolHref : link === "docs" ? `${DOCS_HREF}/${p.slug}` : p.pageHref,
@@ -4095,752 +4113,795 @@ function AppGrid({
4095
4113
  const list = sites ? sites.map((slug) => FAMILY.find((s) => s.slug === slug)).filter((s) => s !== void 0) : FAMILY.filter((s) => s.group === group);
4096
4114
  return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-5", className), children: list.map((s) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(AppCard, { name: s.label, line: s.line, href: s.href, protocols: s.protocols, status: s.status }) }, s.slug)) });
4097
4115
  }
4098
- function ProtocolHero({
4099
- protocol: protocol2,
4116
+ var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
4117
+ function DocLink({ href, className, children, ...rest }) {
4118
+ return isInternal(href) ? /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href, className, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, ...rest, children });
4119
+ }
4120
+ function Breadcrumbs({ items, action, className }) {
4121
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
4122
+ /* @__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) => {
4123
+ const last = i === items.length - 1;
4124
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
4125
+ 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 }),
4126
+ !last ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
4127
+ ] }, i);
4128
+ }) }) }),
4129
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
4130
+ ] });
4131
+ }
4132
+ function DocsPager({ prev, next, className }) {
4133
+ if (!prev && !next) return null;
4134
+ const card = (l, dir) => /* @__PURE__ */ jsxRuntime.jsxs(
4135
+ DocLink,
4136
+ {
4137
+ href: l.href,
4138
+ className: cn(
4139
+ "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",
4140
+ dir === "next" && "items-end text-right sm:col-start-2"
4141
+ ),
4142
+ children: [
4143
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
4144
+ dir === "prev" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
4145
+ dir === "prev" ? "Previous" : "Next",
4146
+ l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
4147
+ l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: l.section }) : null,
4148
+ dir === "next" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
4149
+ ] }),
4150
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
4151
+ ]
4152
+ }
4153
+ );
4154
+ 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: [
4155
+ prev ? card(prev, "prev") : null,
4156
+ next ? card(next, "next") : null
4157
+ ] });
4158
+ }
4159
+ function useHeadings(selector = "#docs-content", key) {
4160
+ const [items, setItems] = react.useState([]);
4161
+ react.useEffect(() => {
4162
+ const read = () => {
4163
+ const root = document.querySelector(selector);
4164
+ if (!root) return setItems([]);
4165
+ setItems(
4166
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
4167
+ id: h.id,
4168
+ // The anchor link's "#" is not part of the name.
4169
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
4170
+ level: h.tagName === "H3" ? 3 : 2
4171
+ }))
4172
+ );
4173
+ };
4174
+ const raf = requestAnimationFrame(read);
4175
+ const t = setTimeout(read, 80);
4176
+ return () => {
4177
+ cancelAnimationFrame(raf);
4178
+ clearTimeout(t);
4179
+ };
4180
+ }, [selector, key]);
4181
+ const activeId = useActiveHeading(items.map((i) => i.id));
4182
+ return { items, activeId };
4183
+ }
4184
+ function OnThisPage({
4185
+ items,
4186
+ activeId,
4187
+ title = "On this page",
4188
+ onNavigate,
4189
+ className
4190
+ }) {
4191
+ const id = react.useId();
4192
+ if (items.length === 0) return null;
4193
+ return (
4194
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
4195
+ /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
4196
+ title ? /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
4197
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((t) => {
4198
+ const on = t.id === activeId;
4199
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
4200
+ "a",
4201
+ {
4202
+ href: `#${t.id}`,
4203
+ onClick: onNavigate,
4204
+ "aria-current": on ? "location" : void 0,
4205
+ className: cn(
4206
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
4207
+ t.level === 3 ? "pl-7" : "pl-4",
4208
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
4209
+ ),
4210
+ children: t.label
4211
+ }
4212
+ ) }, t.id);
4213
+ }) })
4214
+ ] })
4215
+ );
4216
+ }
4217
+ var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
4218
+ function Callout({
4219
+ tone = "note",
4100
4220
  title,
4101
- lead,
4102
- actions,
4103
- art,
4104
4221
  children,
4105
4222
  className
4106
4223
  }) {
4107
- const p = protocolSite(protocol2);
4108
4224
  return /* @__PURE__ */ jsxRuntime.jsx(
4109
- PageHero,
4225
+ Notice,
4110
4226
  {
4111
- className,
4112
- eyebrow: `Protocol \xB7 ${p.verb}`,
4227
+ tone: CALLOUT_TONE[tone],
4113
4228
  title,
4114
- lead,
4115
- actions,
4116
- art,
4117
- children: p.status !== "live" || children ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-4", children: [
4118
- p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null,
4119
- children
4120
- ] }) : null
4229
+ role: "note",
4230
+ className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
4231
+ children
4121
4232
  }
4122
4233
  );
4123
4234
  }
4124
- function ProtocolNav({
4125
- current: current2,
4126
- link = "page",
4127
- className
4128
- }) {
4129
- 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) => {
4130
- const on = p.slug === current2;
4131
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
4132
- "a",
4133
- {
4134
- href: link === "tool" ? p.toolHref : p.pageHref,
4135
- "aria-current": on ? "page" : void 0,
4136
- className: cn(
4137
- "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
4138
- on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
4139
- ),
4140
- children: p.label
4141
- }
4142
- ) }, p.slug);
4143
- }) }) }) });
4144
- }
4145
- function SpecCard({
4146
- protocol: protocol2,
4147
- version,
4148
- license,
4149
- vectors,
4150
- size = "md",
4151
- className
4152
- }) {
4153
- const p = protocolSite(protocol2);
4154
- const repo = `oc-${p.slug}-protocol`;
4155
- const facts = [
4156
- ["Version", version],
4157
- ...license ? [["Licence", license]] : [],
4158
- ["Nostr kind", p.kinds],
4159
- ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
4160
- ];
4161
- if (size === "sm") {
4162
- return /* @__PURE__ */ jsxRuntime.jsxs(
4163
- "a",
4235
+ function Step({ title, id, children }) {
4236
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
4237
+ /* @__PURE__ */ jsxRuntime.jsx(
4238
+ "span",
4164
4239
  {
4165
- href: p.specHref,
4166
- className: cn(
4167
- "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",
4168
- className
4169
- ),
4170
- children: [
4171
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
4172
- /* @__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 ") }),
4173
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
4174
- "Read the spec ",
4175
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
4176
- ] })
4177
- ]
4240
+ "aria-hidden": true,
4241
+ 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)]"
4178
4242
  }
4179
- );
4180
- }
4181
- 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: [
4182
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
4183
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
4184
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
4185
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
4186
- ] }),
4187
- p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
4188
- ] }),
4189
- /* @__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: [
4190
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
4191
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
4192
- ] }, k)) }),
4193
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: p.specHref, children: [
4194
- "Read the spec ",
4195
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true })
4196
- ] }) }) })
4243
+ ),
4244
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
4245
+ /* @__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 }),
4246
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
4197
4247
  ] });
4198
4248
  }
4199
- function VerifyBox({
4200
- action,
4201
- param = "q",
4249
+ function Steps({ children, className }) {
4250
+ 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 });
4251
+ }
4252
+ function LinkCard({
4253
+ href,
4202
4254
  title,
4203
4255
  description,
4204
- label = "Id, envelope or link",
4205
- placeholder,
4206
- hint,
4207
- submitLabel = "Verify",
4208
- multiline = false,
4209
- onVerify,
4256
+ icon,
4257
+ meta,
4210
4258
  className
4211
4259
  }) {
4212
- const [value, setValue] = react.useState("");
4213
- const submit = (e) => {
4214
- if (!onVerify) return;
4215
- e.preventDefault();
4216
- if (value.trim()) onVerify(value.trim());
4217
- };
4218
- const button = /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
4260
+ const Arrow = isInternal(href) ? lucideReact.ArrowRight : lucideReact.ArrowUpRight;
4219
4261
  return /* @__PURE__ */ jsxRuntime.jsxs(
4220
- "form",
4262
+ DocLink,
4221
4263
  {
4222
- action,
4223
- method: "get",
4224
- onSubmit: submit,
4225
- className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
4264
+ href,
4265
+ className: cn(
4266
+ "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",
4267
+ className
4268
+ ),
4226
4269
  children: [
4227
- title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
4228
- title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: title }) : null,
4229
- description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
4230
- ] }) : null,
4231
- multiline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4232
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, children: /* @__PURE__ */ jsxRuntime.jsx(
4233
- Textarea,
4234
- {
4235
- name: param,
4236
- required: true,
4237
- value,
4238
- onChange: (e) => setValue(e.target.value),
4239
- placeholder,
4240
- spellCheck: false,
4241
- className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
4242
- }
4243
- ) }),
4244
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: button })
4245
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsxRuntime.jsx(
4246
- Input,
4247
- {
4248
- name: param,
4249
- required: true,
4250
- value,
4251
- onChange: (e) => setValue(e.target.value),
4252
- placeholder,
4253
- spellCheck: false,
4254
- autoComplete: "off",
4255
- className: "font-mono text-base md:text-[0.875rem]"
4256
- }
4257
- ) })
4270
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-3", children: [
4271
+ 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 }),
4272
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
4273
+ meta,
4274
+ /* @__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" })
4275
+ ] })
4276
+ ] }),
4277
+ icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
4278
+ description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
4258
4279
  ]
4259
4280
  }
4260
4281
  );
4261
4282
  }
4262
- var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
4263
- function ComparisonTable({
4264
- columns,
4283
+ function CardGrid({ columns = 2, children, className }) {
4284
+ 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 });
4285
+ }
4286
+ function MdxTable({ className, ...props }) {
4287
+ 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(
4288
+ "table",
4289
+ {
4290
+ className: cn(
4291
+ "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
4292
+ "[&_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",
4293
+ "[&_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",
4294
+ "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
4295
+ "[&_[align=center]]:text-center [&_[align=right]]:text-right",
4296
+ // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
4297
+ "max-sm:[&_td]:min-w-[9rem]",
4298
+ className
4299
+ ),
4300
+ ...props
4301
+ }
4302
+ ) }) });
4303
+ }
4304
+ var said = (n) => n !== void 0 && n !== null && n !== false && n !== "";
4305
+ function ApiTable({
4265
4306
  rows,
4266
- label,
4267
- propertyHeading = "Property",
4307
+ caption,
4308
+ nameHeader = "Name",
4268
4309
  className
4269
4310
  }) {
4270
- const wide = columns.length > 3;
4271
- const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
4272
- const desk = wide ? "lg" : "md";
4273
- const style = {
4274
- // The argued-for column gets a little more room: its answers carry the page.
4275
- "--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
4311
+ const hasDefault = rows.some((r) => r.default !== void 0);
4312
+ const hasDescription = rows.some((r) => said(r.description));
4313
+ const hasSource = rows.some((r) => said(r.source));
4314
+ const cell = "px-4 py-3 max-sm:p-0";
4315
+ 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: [
4316
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
4317
+ /* @__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: [
4318
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
4319
+ /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
4320
+ hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
4321
+ hasDescription ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" }) : null,
4322
+ hasSource ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Defined in" }) : null
4323
+ ] }) }),
4324
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border max-sm:block", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs(
4325
+ "tr",
4326
+ {
4327
+ id: r.id,
4328
+ 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",
4329
+ children: [
4330
+ /* @__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: [
4331
+ /* @__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 }),
4332
+ r.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
4333
+ r.deprecated ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
4334
+ r.status ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: r.status }) : null
4335
+ ] }) }),
4336
+ /* @__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" }),
4337
+ 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: [
4338
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-sans sm:hidden", children: "Default " }),
4339
+ r.default ?? "\u2014"
4340
+ ] }) : null,
4341
+ hasDescription ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn(cell, "leading-relaxed text-muted-foreground", !said(r.description) && "max-sm:hidden"), children: r.description }) : null,
4342
+ 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
4343
+ ]
4344
+ },
4345
+ r.id ?? r.name
4346
+ )) })
4347
+ ] }) }) });
4348
+ }
4349
+ function useDarkMode() {
4350
+ const [dark, setDark] = react.useState(false);
4351
+ react.useEffect(() => {
4352
+ const root = document.documentElement;
4353
+ const read = () => setDark(root.classList.contains("dark"));
4354
+ read();
4355
+ const mo = new MutationObserver(read);
4356
+ mo.observe(root, { attributes: true, attributeFilter: ["class"] });
4357
+ return () => mo.disconnect();
4358
+ }, []);
4359
+ return dark;
4360
+ }
4361
+ function mermaidTheme(el) {
4362
+ const css = getComputedStyle(el);
4363
+ const v = (name) => css.getPropertyValue(name).trim();
4364
+ const card = v("--card");
4365
+ const muted = v("--muted");
4366
+ const text = v("--foreground");
4367
+ const subtle = v("--muted-foreground");
4368
+ const line = v("--input");
4369
+ const hair = v("--oca-hairline-strong");
4370
+ return {
4371
+ background: "transparent",
4372
+ fontFamily: css.fontFamily,
4373
+ fontSize: "14px",
4374
+ textColor: text,
4375
+ mainBkg: card,
4376
+ primaryColor: card,
4377
+ primaryTextColor: text,
4378
+ primaryBorderColor: hair,
4379
+ secondaryColor: muted,
4380
+ secondaryTextColor: text,
4381
+ secondaryBorderColor: hair,
4382
+ tertiaryColor: muted,
4383
+ tertiaryTextColor: text,
4384
+ tertiaryBorderColor: hair,
4385
+ nodeBorder: hair,
4386
+ lineColor: line,
4387
+ edgeLabelBackground: card,
4388
+ clusterBkg: muted,
4389
+ clusterBorder: hair,
4390
+ titleColor: text,
4391
+ noteBkgColor: muted,
4392
+ noteTextColor: text,
4393
+ noteBorderColor: hair,
4394
+ actorBkg: card,
4395
+ actorBorder: hair,
4396
+ actorTextColor: text,
4397
+ actorLineColor: line,
4398
+ signalColor: text,
4399
+ signalTextColor: text,
4400
+ labelBoxBkgColor: card,
4401
+ labelBoxBorderColor: hair,
4402
+ labelTextColor: text,
4403
+ loopTextColor: subtle,
4404
+ activationBkgColor: muted,
4405
+ activationBorderColor: hair,
4406
+ sequenceNumberColor: card
4276
4407
  };
4277
- const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
4278
- 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: [
4279
- /* @__PURE__ */ jsxRuntime.jsxs(
4280
- "li",
4408
+ }
4409
+ var FIT = 4 / 3;
4410
+ function naturalSize(svg) {
4411
+ const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
4412
+ if (!w) return { svg, width: null };
4413
+ const width = Math.ceil(Number(w));
4414
+ return {
4415
+ svg: svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${width}"`).replace(/max-width:\s*[\d.]+px;?/, ""),
4416
+ width
4417
+ };
4418
+ }
4419
+ function useInnerWidth(ref, padding) {
4420
+ const [width, setWidth] = react.useState(null);
4421
+ react.useEffect(() => {
4422
+ const el = ref.current;
4423
+ if (!el) return;
4424
+ const ro = new ResizeObserver(() => setWidth(el.clientWidth - padding));
4425
+ ro.observe(el);
4426
+ return () => ro.disconnect();
4427
+ }, [ref, padding]);
4428
+ return width;
4429
+ }
4430
+ function Diagram({ chart, caption, load, className }) {
4431
+ const ref = react.useRef(null);
4432
+ const dark = useDarkMode();
4433
+ const raw = react.useId();
4434
+ const [drawn, setDrawn] = react.useState(null);
4435
+ const [failed, setFailed] = react.useState(false);
4436
+ const room = useInnerWidth(ref, 48);
4437
+ const fits = drawn?.width != null && room != null && drawn.width <= room * FIT;
4438
+ react.useEffect(() => {
4439
+ let live = true;
4440
+ const el = ref.current;
4441
+ if (!el) return;
4442
+ (async () => {
4443
+ try {
4444
+ const mod = await load();
4445
+ const mermaid = "default" in mod ? mod.default : mod;
4446
+ mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
4447
+ const { svg } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
4448
+ if (live) {
4449
+ setDrawn(naturalSize(svg));
4450
+ setFailed(false);
4451
+ }
4452
+ } catch {
4453
+ if (live) setFailed(true);
4454
+ }
4455
+ })();
4456
+ return () => {
4457
+ live = false;
4458
+ };
4459
+ }, [chart, dark, load, raw]);
4460
+ if (failed) return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
4461
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
4462
+ drawn ? /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
4463
+ "div",
4281
4464
  {
4282
- "aria-hidden": true,
4465
+ "data-fit": fits ? "" : void 0,
4283
4466
  className: cn(
4284
- "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
4285
- wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
4286
- grid
4467
+ "flex justify-center p-6 [&_svg]:h-auto",
4468
+ fits ? "w-full [&_svg]:max-w-full" : "w-max min-w-full [&_svg]:max-w-none"
4287
4469
  ),
4288
- children: [
4289
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: propertyHeading }),
4290
- 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))
4291
- ]
4470
+ role: "img",
4471
+ "aria-label": typeof caption === "string" ? caption : "Diagram",
4472
+ dangerouslySetInnerHTML: { __html: drawn.svg }
4292
4473
  }
4293
- ),
4294
- 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: [
4295
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
4296
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-title-sm", children: r.label }),
4297
- r.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
4298
- ] }),
4299
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
4300
- return /* @__PURE__ */ jsxRuntime.jsxs(
4301
- "div",
4302
- {
4303
- style: { "--oca-order": ordered.indexOf(c) },
4304
- className: cn(
4305
- // Two rows of the pair's grid (name, answer), so answers line up
4306
- // across a pair even when one name wraps.
4307
- "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
4308
- 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",
4309
- c.highlight ? cn(
4310
- TINT,
4311
- "col-span-2",
4312
- 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"
4313
- ) : desk === "lg" ? "lg:p-0" : "md:p-0"
4314
- ),
4315
- children: [
4316
- /* @__PURE__ */ jsxRuntime.jsx(
4317
- "span",
4318
- {
4319
- className: cn(
4320
- "text-[0.8125rem]",
4321
- c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
4322
- desk === "lg" ? "lg:sr-only" : "md:sr-only"
4323
- ),
4324
- children: c.label
4325
- }
4326
- ),
4327
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
4328
- ]
4329
- },
4330
- c.key
4331
- );
4332
- }) })
4333
- ] }, ri))
4474
+ ) }) : /* @__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" }) }),
4475
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
4334
4476
  ] });
4335
4477
  }
4336
- var CHECK = {
4337
- ok: { word: "Passed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}), tone: "text-success" },
4338
- fail: { word: "Failed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}), tone: "text-destructive" },
4339
- pending: { word: "Pending", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, {}), tone: "text-oca-accent-ink" },
4340
- none: { word: "None", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlash, {}), tone: "text-muted-foreground" },
4341
- skipped: { word: "Skipped", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleMinus, {}), tone: "text-muted-foreground" },
4342
- unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, {}), tone: "text-oca-subtle" }
4478
+ var HEADING = {
4479
+ h1: "oca-display-3 mb-4 text-foreground",
4480
+ h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
4481
+ h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
4482
+ h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
4343
4483
  };
4344
- function VerifyReport({
4345
- verdict,
4346
- title,
4347
- summary,
4348
- checks,
4349
- facts,
4350
- notChecked,
4351
- actions,
4352
- as: Heading = "h2",
4353
- className
4484
+ function DocsHeading({
4485
+ as: Tag,
4486
+ id,
4487
+ children,
4488
+ className,
4489
+ ...props
4354
4490
  }) {
4355
- return /* @__PURE__ */ jsxRuntime.jsxs(
4356
- "section",
4357
- {
4358
- "aria-label": "Verification result",
4359
- className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
4360
- children: [
4361
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
4362
- /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verdict }),
4363
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-display-3 [overflow-wrap:anywhere]", children: title }),
4364
- summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body max-w-[40rem] [overflow-wrap:anywhere]", children: summary }) : null
4365
- ] }),
4366
- /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
4367
- const k = CHECK[c.state];
4368
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
4369
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
4370
- /* @__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: [
4371
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
4372
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem]", children: c.label }),
4373
- c.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
4374
- ] }),
4375
- /* @__PURE__ */ jsxRuntime.jsx(
4376
- "span",
4377
- {
4378
- className: cn(
4379
- "shrink-0 text-[0.8125rem]",
4380
- c.state === "fail" ? "text-destructive" : "text-muted-foreground"
4381
- ),
4382
- children: k.word
4383
- }
4384
- )
4385
- ] })
4386
- ] }, i);
4387
- }) }),
4388
- 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,
4389
- 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: [
4390
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
4391
- /* @__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)) })
4392
- ] }) : null,
4393
- 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
4394
- ]
4395
- }
4396
- );
4397
- }
4398
- function SignMessage({
4399
- lead,
4400
- address,
4401
- message,
4402
- wallets,
4403
- busy = false,
4404
- error,
4405
- submitLabel = "Confirm",
4406
- secondary,
4407
- onSignature,
4408
- className
4409
- }) {
4410
- const [pasted, setPasted] = react.useState("");
4411
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
4412
- lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
4413
- wallets ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4414
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
4415
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
4416
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
4417
- "or sign it in any wallet",
4418
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
4419
- ] })
4420
- ] }) : null,
4421
- /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: message, caption: "Message to sign" }),
4422
- /* @__PURE__ */ jsxRuntime.jsxs(
4423
- "form",
4491
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
4492
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-heading-text": "", children }),
4493
+ id && Tag !== "h1" ? /* @__PURE__ */ jsxRuntime.jsxs(
4494
+ "a",
4424
4495
  {
4425
- className: "flex flex-col gap-4",
4426
- onSubmit: (e) => {
4427
- e.preventDefault();
4428
- if (pasted.trim()) onSignature(pasted.trim());
4429
- },
4496
+ href: `#${id}`,
4497
+ 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",
4430
4498
  children: [
4431
- /* @__PURE__ */ jsxRuntime.jsx(
4432
- Field,
4433
- {
4434
- label: "Signature",
4435
- error,
4436
- hint: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4437
- "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
4438
- " ",
4439
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all font-mono", children: address }),
4440
- "."
4441
- ] }),
4442
- children: /* @__PURE__ */ jsxRuntime.jsx(
4443
- Textarea,
4444
- {
4445
- value: pasted,
4446
- onChange: (e) => setPasted(e.target.value),
4447
- rows: 3,
4448
- spellCheck: false,
4449
- className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
4450
- }
4451
- )
4452
- }
4453
- ),
4454
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
4455
- /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
4456
- secondary
4457
- ] })
4499
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
4500
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Link to this section" })
4458
4501
  ]
4459
4502
  }
4460
- )
4461
- ] });
4462
- }
4463
- var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
4464
- function DocLink({ href, className, children, ...rest }) {
4465
- return isInternal(href) ? /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href, className, ...rest, children }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href, className, ...rest, children });
4466
- }
4467
- function Breadcrumbs({ items, action, className }) {
4468
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
4469
- /* @__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) => {
4470
- const last = i === items.length - 1;
4471
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
4472
- 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 }),
4473
- !last ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
4474
- ] }, i);
4475
- }) }) }),
4476
- action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
4477
- ] });
4478
- }
4479
- function DocsPager({ prev, next, className }) {
4480
- if (!prev && !next) return null;
4481
- const card = (l, dir) => /* @__PURE__ */ jsxRuntime.jsxs(
4482
- DocLink,
4483
- {
4484
- href: l.href,
4485
- className: cn(
4486
- "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",
4487
- dir === "next" && "items-end text-right sm:col-start-2"
4488
- ),
4489
- children: [
4490
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
4491
- dir === "prev" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
4492
- dir === "prev" ? "Previous" : "Next",
4493
- l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
4494
- l.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: l.section }) : null,
4495
- dir === "next" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
4496
- ] }),
4497
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
4498
- ]
4499
- }
4500
- );
4501
- 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: [
4502
- prev ? card(prev, "prev") : null,
4503
- next ? card(next, "next") : null
4503
+ ) : null
4504
4504
  ] });
4505
4505
  }
4506
- function useHeadings(selector = "#docs-content", key) {
4507
- const [items, setItems] = react.useState([]);
4508
- react.useEffect(() => {
4509
- const read = () => {
4510
- const root = document.querySelector(selector);
4511
- if (!root) return setItems([]);
4512
- setItems(
4513
- Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
4514
- id: h.id,
4515
- // The anchor link's "#" is not part of the name.
4516
- label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
4517
- level: h.tagName === "H3" ? 3 : 2
4518
- }))
4519
- );
4520
- };
4521
- const raf = requestAnimationFrame(read);
4522
- const t = setTimeout(read, 80);
4523
- return () => {
4524
- cancelAnimationFrame(raf);
4525
- clearTimeout(t);
4526
- };
4527
- }, [selector, key]);
4528
- const activeId = useActiveHeading(items.map((i) => i.id));
4529
- return { items, activeId };
4506
+ function codeText(node) {
4507
+ if (typeof node === "string") return node;
4508
+ if (typeof node === "number") return String(node);
4509
+ if (Array.isArray(node)) return node.map(codeText).join("");
4510
+ if (react.isValidElement(node)) return codeText(node.props.children);
4511
+ return "";
4530
4512
  }
4531
- function OnThisPage({
4532
- items,
4533
- activeId,
4534
- title = "On this page",
4535
- onNavigate,
4536
- className
4537
- }) {
4538
- const id = react.useId();
4539
- if (items.length === 0) return null;
4540
- return (
4541
- // With no visible title (a folded list under its own summary) the name is still "On this page".
4542
- /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
4543
- title ? /* @__PURE__ */ jsxRuntime.jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
4544
- /* @__PURE__ */ jsxRuntime.jsx("ul", { children: items.map((t) => {
4545
- const on = t.id === activeId;
4546
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
4547
- "a",
4548
- {
4549
- href: `#${t.id}`,
4550
- onClick: onNavigate,
4551
- "aria-current": on ? "location" : void 0,
4552
- className: cn(
4553
- "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
4554
- t.level === 3 ? "pl-7" : "pl-4",
4555
- on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
4556
- ),
4557
- children: t.label
4558
- }
4559
- ) }, t.id);
4560
- }) })
4561
- ] })
4562
- );
4513
+ function codeLang(node) {
4514
+ const child = react.Children.toArray(node)[0];
4515
+ if (!react.isValidElement(child)) return void 0;
4516
+ const cls = child.props.className ?? "";
4517
+ return cls.match(/language-([\w+-]+)/)?.[1];
4563
4518
  }
4564
- var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
4565
- function Callout({
4566
- tone = "note",
4519
+ function ProtocolHero({
4520
+ protocol: protocol2,
4567
4521
  title,
4522
+ lead,
4523
+ actions,
4524
+ art,
4568
4525
  children,
4569
4526
  className
4570
4527
  }) {
4528
+ const p = protocolSite(protocol2);
4571
4529
  return /* @__PURE__ */ jsxRuntime.jsx(
4572
- Notice,
4530
+ PageHero,
4573
4531
  {
4574
- tone: CALLOUT_TONE[tone],
4532
+ className,
4533
+ eyebrow: `Protocol \xB7 ${p.verb}`,
4575
4534
  title,
4576
- role: "note",
4577
- className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
4578
- children
4535
+ lead,
4536
+ actions,
4537
+ art,
4538
+ children: p.status !== "live" || children ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-4", children: [
4539
+ p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null,
4540
+ children
4541
+ ] }) : null
4579
4542
  }
4580
4543
  );
4581
4544
  }
4582
- function Step({ title, id, children }) {
4583
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
4584
- /* @__PURE__ */ jsxRuntime.jsx(
4585
- "span",
4545
+ function ProtocolNav({
4546
+ current: current2,
4547
+ link = "page",
4548
+ className
4549
+ }) {
4550
+ 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) => {
4551
+ const on = p.slug === current2;
4552
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
4553
+ "a",
4586
4554
  {
4587
- "aria-hidden": true,
4588
- 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)]"
4589
- }
4590
- ),
4591
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
4592
- /* @__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 }),
4593
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
4555
+ href: link === "tool" ? p.toolHref : p.pageHref,
4556
+ "aria-current": on ? "page" : void 0,
4557
+ className: cn(
4558
+ "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
4559
+ on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
4560
+ ),
4561
+ children: p.label
4562
+ }
4563
+ ) }, p.slug);
4564
+ }) }) }) });
4565
+ }
4566
+ var SPEC_FILE = {
4567
+ spec: {
4568
+ file: "SPEC.md",
4569
+ title: "Normative source",
4570
+ note: "This page is a human-readable summary. The authoritative copy lives in the spec repo. If the two ever drift, the repo wins."
4571
+ },
4572
+ security: {
4573
+ file: "SECURITY.md",
4574
+ title: "Normative threat model",
4575
+ note: "This page is the short form. The authoritative, numbered threat model lives in the spec repo."
4576
+ },
4577
+ rationale: {
4578
+ file: "WHY.md",
4579
+ title: "Design rationale",
4580
+ note: "This page is the short version. The full rationale and the rejected-design log live in the spec repo."
4581
+ }
4582
+ };
4583
+ function SpecCard(props) {
4584
+ return props.repo !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(SpecFileNote, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(ProtocolSpecCard, { ...props });
4585
+ }
4586
+ function SpecFileNote({ repo, file, kind = "spec", version, note, className }) {
4587
+ const d = SPEC_FILE[kind];
4588
+ const f = file ?? d.file;
4589
+ return /* @__PURE__ */ jsxRuntime.jsxs(Callout, { title: version ? `${d.title} \xB7 ${version}` : d.title, className, children: [
4590
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: note ?? d.note }),
4591
+ /* @__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}` }) })
4594
4592
  ] });
4595
4593
  }
4596
- function Steps({ children, className }) {
4597
- 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 });
4594
+ function ProtocolSpecCard({ protocol: protocol2, version, license, vectors, size = "md", className }) {
4595
+ const p = protocolSite(protocol2);
4596
+ const repo = `oc-${p.slug}-protocol`;
4597
+ const facts = [
4598
+ ["Version", version],
4599
+ ...license ? [["Licence", license]] : [],
4600
+ ["Nostr kind", p.kinds],
4601
+ ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
4602
+ ];
4603
+ if (size === "sm") {
4604
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4605
+ "a",
4606
+ {
4607
+ href: p.specHref,
4608
+ className: cn(
4609
+ "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",
4610
+ className
4611
+ ),
4612
+ children: [
4613
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
4614
+ /* @__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 ") }),
4615
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
4616
+ "Read the spec ",
4617
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true, className: "size-4" })
4618
+ ] })
4619
+ ]
4620
+ }
4621
+ );
4622
+ }
4623
+ 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: [
4624
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
4625
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
4626
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
4627
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
4628
+ ] }),
4629
+ p.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: p.status }) : null
4630
+ ] }),
4631
+ /* @__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: [
4632
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
4633
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
4634
+ ] }, k)) }),
4635
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: p.specHref, children: [
4636
+ "Read the spec ",
4637
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { "aria-hidden": true })
4638
+ ] }) }) })
4639
+ ] });
4598
4640
  }
4599
- function LinkCard({
4600
- href,
4641
+ function VerifyBox({
4642
+ action,
4643
+ param = "q",
4601
4644
  title,
4602
4645
  description,
4603
- icon,
4604
- meta,
4646
+ label = "Id, envelope or link",
4647
+ placeholder,
4648
+ hint,
4649
+ submitLabel = "Verify",
4650
+ multiline = false,
4651
+ onVerify,
4605
4652
  className
4606
4653
  }) {
4607
- const Arrow = isInternal(href) ? lucideReact.ArrowRight : lucideReact.ArrowUpRight;
4654
+ const [value, setValue] = react.useState("");
4655
+ const submit = (e) => {
4656
+ if (!onVerify) return;
4657
+ e.preventDefault();
4658
+ if (value.trim()) onVerify(value.trim());
4659
+ };
4660
+ const button = /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
4608
4661
  return /* @__PURE__ */ jsxRuntime.jsxs(
4609
- DocLink,
4662
+ "form",
4610
4663
  {
4611
- href,
4612
- className: cn(
4613
- "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",
4614
- className
4615
- ),
4664
+ action,
4665
+ method: "get",
4666
+ onSubmit: submit,
4667
+ className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
4616
4668
  children: [
4617
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-3", children: [
4618
- 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 }),
4619
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
4620
- meta,
4621
- /* @__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" })
4622
- ] })
4623
- ] }),
4624
- icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
4625
- description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
4669
+ title || description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
4670
+ title ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "oca-title", children: title }) : null,
4671
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
4672
+ ] }) : null,
4673
+ multiline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4674
+ /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, children: /* @__PURE__ */ jsxRuntime.jsx(
4675
+ Textarea,
4676
+ {
4677
+ name: param,
4678
+ required: true,
4679
+ value,
4680
+ onChange: (e) => setValue(e.target.value),
4681
+ placeholder,
4682
+ spellCheck: false,
4683
+ className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
4684
+ }
4685
+ ) }),
4686
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: button })
4687
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsxRuntime.jsx(
4688
+ Input,
4689
+ {
4690
+ name: param,
4691
+ required: true,
4692
+ value,
4693
+ onChange: (e) => setValue(e.target.value),
4694
+ placeholder,
4695
+ spellCheck: false,
4696
+ autoComplete: "off",
4697
+ className: "font-mono text-base md:text-[0.875rem]"
4698
+ }
4699
+ ) })
4626
4700
  ]
4627
4701
  }
4628
4702
  );
4629
4703
  }
4630
- function CardGrid({ columns = 2, children, className }) {
4631
- 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 });
4632
- }
4633
- function MdxTable({ className, ...props }) {
4634
- 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(
4635
- "table",
4636
- {
4637
- className: cn(
4638
- "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
4639
- "[&_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",
4640
- "[&_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",
4641
- "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
4642
- "[&_[align=center]]:text-center [&_[align=right]]:text-right",
4643
- // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
4644
- "max-sm:[&_td]:min-w-[9rem]",
4645
- className
4646
- ),
4647
- ...props
4648
- }
4649
- ) }) });
4650
- }
4651
- function ApiTable({
4704
+ var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
4705
+ function ComparisonTable({
4706
+ columns,
4652
4707
  rows,
4653
- caption,
4654
- nameHeader = "Name",
4708
+ label,
4709
+ propertyHeading = "Property",
4655
4710
  className
4656
4711
  }) {
4657
- const hasDefault = rows.some((r) => r.default !== void 0);
4658
- const marks = (r) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4659
- r.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
4660
- r.deprecated ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
4661
- r.status ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: r.status }) : null
4662
- ] });
4663
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("not-prose my-6", className), children: [
4664
- /* @__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: [
4665
- caption ? /* @__PURE__ */ jsxRuntime.jsx("caption", { className: "sr-only", children: caption }) : null,
4666
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
4667
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
4668
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
4669
- hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
4670
- /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" })
4671
- ] }) }),
4672
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "align-top", children: [
4673
- /* @__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: [
4674
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
4675
- marks(r)
4676
- ] }) }),
4677
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.type ?? "\u2014" }),
4678
- hasDefault ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.default ?? "\u2014" }) : null,
4679
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 leading-relaxed text-muted-foreground", children: r.description })
4680
- ] }, r.name)) })
4681
- ] }) }) }),
4682
- /* @__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: [
4683
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
4684
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn("font-mono text-[0.875rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
4685
- r.type ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "break-all font-mono text-[0.8125rem] text-muted-foreground", children: r.type }) : null
4712
+ const wide = columns.length > 3;
4713
+ const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
4714
+ const desk = wide ? "lg" : "md";
4715
+ const style = {
4716
+ // The argued-for column gets a little more room: its answers carry the page.
4717
+ "--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
4718
+ };
4719
+ const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
4720
+ 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: [
4721
+ /* @__PURE__ */ jsxRuntime.jsxs(
4722
+ "li",
4723
+ {
4724
+ "aria-hidden": true,
4725
+ className: cn(
4726
+ "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
4727
+ wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
4728
+ grid
4729
+ ),
4730
+ children: [
4731
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: propertyHeading }),
4732
+ 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))
4733
+ ]
4734
+ }
4735
+ ),
4736
+ 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: [
4737
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
4738
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-title-sm", children: r.label }),
4739
+ r.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
4686
4740
  ] }),
4687
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-wrap items-center gap-2 empty:hidden", children: marks(r) }),
4688
- r.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] leading-relaxed text-muted-foreground", children: r.description }) : null,
4689
- r.default !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.8125rem] text-muted-foreground", children: [
4690
- "Default ",
4691
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "font-mono text-foreground", children: r.default })
4692
- ] }) : null
4693
- ] }, r.name)) })
4741
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
4742
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4743
+ "div",
4744
+ {
4745
+ style: { "--oca-order": ordered.indexOf(c) },
4746
+ className: cn(
4747
+ // Two rows of the pair's grid (name, answer), so answers line up
4748
+ // across a pair even when one name wraps.
4749
+ "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
4750
+ 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",
4751
+ c.highlight ? cn(
4752
+ TINT,
4753
+ "col-span-2",
4754
+ 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"
4755
+ ) : desk === "lg" ? "lg:p-0" : "md:p-0"
4756
+ ),
4757
+ children: [
4758
+ /* @__PURE__ */ jsxRuntime.jsx(
4759
+ "span",
4760
+ {
4761
+ className: cn(
4762
+ "text-[0.8125rem]",
4763
+ c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
4764
+ desk === "lg" ? "lg:sr-only" : "md:sr-only"
4765
+ ),
4766
+ children: c.label
4767
+ }
4768
+ ),
4769
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
4770
+ ]
4771
+ },
4772
+ c.key
4773
+ );
4774
+ }) })
4775
+ ] }, ri))
4694
4776
  ] });
4695
4777
  }
4696
- function useDarkMode() {
4697
- const [dark, setDark] = react.useState(false);
4698
- react.useEffect(() => {
4699
- const root = document.documentElement;
4700
- const read = () => setDark(root.classList.contains("dark"));
4701
- read();
4702
- const mo = new MutationObserver(read);
4703
- mo.observe(root, { attributes: true, attributeFilter: ["class"] });
4704
- return () => mo.disconnect();
4705
- }, []);
4706
- return dark;
4707
- }
4708
- function mermaidTheme(el) {
4709
- const css = getComputedStyle(el);
4710
- const v = (name) => css.getPropertyValue(name).trim();
4711
- const card = v("--card");
4712
- const muted = v("--muted");
4713
- const text = v("--foreground");
4714
- const subtle = v("--muted-foreground");
4715
- const line = v("--input");
4716
- const hair = v("--oca-hairline-strong");
4717
- return {
4718
- background: "transparent",
4719
- fontFamily: css.fontFamily,
4720
- fontSize: "14px",
4721
- textColor: text,
4722
- mainBkg: card,
4723
- primaryColor: card,
4724
- primaryTextColor: text,
4725
- primaryBorderColor: hair,
4726
- secondaryColor: muted,
4727
- secondaryTextColor: text,
4728
- secondaryBorderColor: hair,
4729
- tertiaryColor: muted,
4730
- tertiaryTextColor: text,
4731
- tertiaryBorderColor: hair,
4732
- nodeBorder: hair,
4733
- lineColor: line,
4734
- edgeLabelBackground: card,
4735
- clusterBkg: muted,
4736
- clusterBorder: hair,
4737
- titleColor: text,
4738
- noteBkgColor: muted,
4739
- noteTextColor: text,
4740
- noteBorderColor: hair,
4741
- actorBkg: card,
4742
- actorBorder: hair,
4743
- actorTextColor: text,
4744
- actorLineColor: line,
4745
- signalColor: text,
4746
- signalTextColor: text,
4747
- labelBoxBkgColor: card,
4748
- labelBoxBorderColor: hair,
4749
- labelTextColor: text,
4750
- loopTextColor: subtle,
4751
- activationBkgColor: muted,
4752
- activationBorderColor: hair,
4753
- sequenceNumberColor: card
4754
- };
4755
- }
4756
- function naturalSize(svg) {
4757
- const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
4758
- if (!w) return svg;
4759
- return svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${Math.ceil(Number(w))}"`).replace(/max-width:\s*[\d.]+px;?/, "");
4760
- }
4761
- function Diagram({ chart, caption, load, className }) {
4762
- const ref = react.useRef(null);
4763
- const dark = useDarkMode();
4764
- const raw = react.useId();
4765
- const [svg, setSvg] = react.useState(null);
4766
- const [failed, setFailed] = react.useState(false);
4767
- react.useEffect(() => {
4768
- let live = true;
4769
- const el = ref.current;
4770
- if (!el) return;
4771
- (async () => {
4772
- try {
4773
- const mod = await load();
4774
- const mermaid = "default" in mod ? mod.default : mod;
4775
- mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
4776
- const { svg: drawn } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
4777
- if (live) {
4778
- setSvg(naturalSize(drawn));
4779
- setFailed(false);
4780
- }
4781
- } catch {
4782
- if (live) setFailed(true);
4783
- }
4784
- })();
4785
- return () => {
4786
- live = false;
4787
- };
4788
- }, [chart, dark, load, raw]);
4789
- if (failed) return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
4790
- return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
4791
- svg ? /* @__PURE__ */ jsxRuntime.jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxRuntime.jsx(
4792
- "div",
4793
- {
4794
- className: "flex w-max min-w-full justify-center p-6 [&_svg]:h-auto [&_svg]:max-w-none",
4795
- role: "img",
4796
- "aria-label": typeof caption === "string" ? caption : "Diagram",
4797
- dangerouslySetInnerHTML: { __html: svg }
4798
- }
4799
- ) }) : /* @__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" }) }),
4800
- caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
4801
- ] });
4802
- }
4803
- var HEADING = {
4804
- h1: "oca-display-3 mb-4 text-foreground",
4805
- h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
4806
- h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
4807
- h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
4778
+ var CHECK = {
4779
+ ok: { word: "Passed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}), tone: "text-success" },
4780
+ fail: { word: "Failed", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleX, {}), tone: "text-destructive" },
4781
+ pending: { word: "Pending", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, {}), tone: "text-oca-accent-ink" },
4782
+ none: { word: "None", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlash, {}), tone: "text-muted-foreground" },
4783
+ skipped: { word: "Skipped", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleMinus, {}), tone: "text-muted-foreground" },
4784
+ unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, {}), tone: "text-oca-subtle" }
4808
4785
  };
4809
- function DocsHeading({
4810
- as: Tag,
4811
- id,
4812
- children,
4813
- className,
4814
- ...props
4786
+ function VerifyReport({
4787
+ verdict,
4788
+ title,
4789
+ summary,
4790
+ checks,
4791
+ facts,
4792
+ notChecked,
4793
+ actions,
4794
+ as: Heading = "h2",
4795
+ className
4815
4796
  }) {
4816
- return /* @__PURE__ */ jsxRuntime.jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
4817
- /* @__PURE__ */ jsxRuntime.jsx("span", { "data-heading-text": "", children }),
4818
- id && Tag !== "h1" ? /* @__PURE__ */ jsxRuntime.jsxs(
4819
- "a",
4797
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4798
+ "section",
4799
+ {
4800
+ "aria-label": "Verification result",
4801
+ className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
4802
+ children: [
4803
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
4804
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: verdict }),
4805
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-display-3 [overflow-wrap:anywhere]", children: title }),
4806
+ summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-body max-w-[40rem] [overflow-wrap:anywhere]", children: summary }) : null
4807
+ ] }),
4808
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
4809
+ const k = CHECK[c.state];
4810
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
4811
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
4812
+ /* @__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: [
4813
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
4814
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem]", children: c.label }),
4815
+ c.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
4816
+ ] }),
4817
+ /* @__PURE__ */ jsxRuntime.jsx(
4818
+ "span",
4819
+ {
4820
+ className: cn(
4821
+ "shrink-0 text-[0.8125rem]",
4822
+ c.state === "fail" ? "text-destructive" : "text-muted-foreground"
4823
+ ),
4824
+ children: k.word
4825
+ }
4826
+ )
4827
+ ] })
4828
+ ] }, i);
4829
+ }) }),
4830
+ 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,
4831
+ 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: [
4832
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
4833
+ /* @__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)) })
4834
+ ] }) : null,
4835
+ 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
4836
+ ]
4837
+ }
4838
+ );
4839
+ }
4840
+ function SignMessage({
4841
+ lead,
4842
+ address,
4843
+ message,
4844
+ wallets,
4845
+ busy = false,
4846
+ error,
4847
+ submitLabel = "Confirm",
4848
+ secondary,
4849
+ onSignature,
4850
+ className
4851
+ }) {
4852
+ const [pasted, setPasted] = react.useState("");
4853
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
4854
+ lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
4855
+ wallets ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4856
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
4857
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
4858
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
4859
+ "or sign it in any wallet",
4860
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
4861
+ ] })
4862
+ ] }) : null,
4863
+ /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: message, caption: "Message to sign" }),
4864
+ /* @__PURE__ */ jsxRuntime.jsxs(
4865
+ "form",
4820
4866
  {
4821
- href: `#${id}`,
4822
- 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",
4867
+ className: "flex flex-col gap-4",
4868
+ onSubmit: (e) => {
4869
+ e.preventDefault();
4870
+ if (pasted.trim()) onSignature(pasted.trim());
4871
+ },
4823
4872
  children: [
4824
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "#" }),
4825
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Link to this section" })
4873
+ /* @__PURE__ */ jsxRuntime.jsx(
4874
+ Field,
4875
+ {
4876
+ label: "Signature",
4877
+ error,
4878
+ hint: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4879
+ "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
4880
+ " ",
4881
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "break-all font-mono", children: address }),
4882
+ "."
4883
+ ] }),
4884
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4885
+ Textarea,
4886
+ {
4887
+ value: pasted,
4888
+ onChange: (e) => setPasted(e.target.value),
4889
+ rows: 3,
4890
+ spellCheck: false,
4891
+ className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
4892
+ }
4893
+ )
4894
+ }
4895
+ ),
4896
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
4897
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
4898
+ secondary
4899
+ ] })
4826
4900
  ]
4827
4901
  }
4828
- ) : null
4902
+ )
4829
4903
  ] });
4830
4904
  }
4831
- function codeText(node) {
4832
- if (typeof node === "string") return node;
4833
- if (typeof node === "number") return String(node);
4834
- if (Array.isArray(node)) return node.map(codeText).join("");
4835
- if (react.isValidElement(node)) return codeText(node.props.children);
4836
- return "";
4837
- }
4838
- function codeLang(node) {
4839
- const child = react.Children.toArray(node)[0];
4840
- if (!react.isValidElement(child)) return void 0;
4841
- const cls = child.props.className ?? "";
4842
- return cls.match(/language-([\w+-]+)/)?.[1];
4843
- }
4844
4905
  function useMacKeys() {
4845
4906
  const [mac, setMac] = react.useState(true);
4846
4907
  react.useEffect(() => {
@@ -5643,7 +5704,7 @@ function ToolGrid({
5643
5704
  ] }),
5644
5705
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
5645
5706
  /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: "oca-title-sm", children: /* @__PURE__ */ jsxRuntime.jsx(
5646
- Link8__default.default,
5707
+ Link6__default.default,
5647
5708
  {
5648
5709
  href: t.href,
5649
5710
  className: "outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-['']",
@@ -5736,800 +5797,827 @@ function FamilyMenu({ current: current2, className }) {
5736
5797
  )
5737
5798
  ] });
5738
5799
  }
5739
- function NavLink({
5740
- item,
5741
- className,
5742
- onNavigate,
5743
- line = false
5744
- }) {
5745
- const cls = cn(
5746
- "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
5747
- item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
5748
- line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
5749
- line && item.active && "after:bg-foreground",
5750
- className
5751
- );
5752
- if (item.external) {
5753
- return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
5754
- }
5755
- return /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
5756
- }
5757
- function NavRow({ item, onNavigate }) {
5758
- const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5759
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
5760
- item.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
5761
- ] });
5762
- const cls = cn(
5763
- "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
5764
- item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
5765
- );
5766
- return item.external ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
5767
- }
5768
- var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
5769
- function NavDropdown({ item }) {
5770
- const [open, setOpen] = react.useState(false);
5771
- const active = item.active || item.children?.some((c) => c.active);
5772
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
5773
- /* @__PURE__ */ jsxRuntime.jsxs(
5774
- PopoverTrigger,
5800
+ function SideNav({ groups, onNavigate }) {
5801
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
5802
+ g.label ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
5803
+ g.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
5804
+ Link6__default.default,
5775
5805
  {
5806
+ href: it.href,
5807
+ onClick: onNavigate,
5808
+ "aria-current": it.active ? "page" : void 0,
5776
5809
  className: cn(
5777
- "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors md:max-lg:pl-2.5 md:max-lg:pr-2",
5778
- active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
5810
+ "flex h-9 items-center gap-3 rounded-xl px-3 text-[0.9375rem] transition-colors",
5811
+ "[&_svg]:size-[1.0625rem] [&_svg]:shrink-0",
5812
+ it.active ? "bg-card text-foreground shadow-sm ring-1 ring-border [&_svg]:text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
5779
5813
  ),
5780
5814
  children: [
5781
- item.label,
5782
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
5815
+ it.icon,
5816
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: it.label }),
5817
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: it.badge }) : null
5783
5818
  ]
5784
- }
5785
- ),
5786
- /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
5787
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
5788
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
5789
- NavLink,
5790
- {
5791
- item: { ...item, label: seeAll(item), children: void 0 },
5792
- className: "block rounded-xl px-2 py-2 text-[0.875rem]",
5793
- onNavigate: () => setOpen(false)
5794
- }
5795
- ) })
5796
- ] })
5797
- ] });
5819
+ },
5820
+ it.href
5821
+ ))
5822
+ ] }, g.label ?? gi)) });
5798
5823
  }
5799
- function SiteHeader({
5800
- home = "/",
5801
- brand,
5802
- product,
5803
- family,
5804
- nav = [],
5805
- search,
5806
- actions,
5807
- variant = "site",
5808
- navOnPhone = true,
5809
- menu: menuExtra,
5810
- className
5824
+ function SectionSwitch({
5825
+ sections,
5826
+ current: current2,
5827
+ onNavigate
5811
5828
  }) {
5812
- const [open, setOpen] = react.useState(false);
5813
- const tool = variant === "tool";
5814
- const size = tool ? 24 : 28;
5815
- const current2 = typeof family === "string" ? family : void 0;
5816
- const phoneNav = navOnPhone ? nav : [];
5817
- const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
5818
- const brandNode = brand ?? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center", children: [
5819
- /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size }),
5820
- product ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5821
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
5822
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
5823
- ] }) : null
5824
- ] });
5825
- const navigation = nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
5826
- (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsx(NavDropdown, { item: n }, n.href) : (
5827
- // Between md and lg the family menu and the actions share the row: tighter.
5828
- /* @__PURE__ */ jsxRuntime.jsx(NavLink, { item: n, line: tool, className: tool ? void 0 : "md:max-lg:px-2.5" }, n.href)
5829
- )
5830
- ) }) : null;
5829
+ const cols = sections.length <= 3 ? sections.length : 2;
5831
5830
  return /* @__PURE__ */ jsxRuntime.jsx(
5832
- "header",
5831
+ "nav",
5833
5832
  {
5834
- className: cn(
5835
- "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
5836
- tool ? "border-border" : "border-transparent",
5837
- className
5838
- ),
5839
- children: /* @__PURE__ */ jsxRuntime.jsxs(
5833
+ "aria-label": "Sections",
5834
+ className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
5835
+ style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
5836
+ children: sections.map((sec) => {
5837
+ const on = sec.id === current2.id;
5838
+ return /* @__PURE__ */ jsxRuntime.jsx(
5839
+ Link6__default.default,
5840
+ {
5841
+ href: sec.href,
5842
+ onClick: onNavigate,
5843
+ "aria-current": on ? "true" : void 0,
5844
+ className: cn(
5845
+ "flex h-8 min-w-0 items-center justify-center rounded-full px-1.5 text-[0.8125rem] font-medium transition-colors",
5846
+ on ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
5847
+ ),
5848
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: sec.label })
5849
+ },
5850
+ sec.id
5851
+ );
5852
+ })
5853
+ }
5854
+ );
5855
+ }
5856
+ function TabBar({ items }) {
5857
+ return /* @__PURE__ */ jsxRuntime.jsx(
5858
+ "nav",
5859
+ {
5860
+ "aria-label": "Pages",
5861
+ "data-oca-tabbar": "",
5862
+ className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
5863
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5840
5864
  "div",
5841
5865
  {
5842
- className: cn(
5843
- "flex items-center justify-between gap-4",
5844
- tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem] md:max-lg:gap-2",
5845
- // Three columns, the outer two each at least their content: the
5846
- // navigation stays centred whatever the actions hold, so it does
5847
- // not shift when they change (signed out to signed in).
5848
- !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
5849
- ),
5850
- children: [
5851
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
5852
- /* @__PURE__ */ jsxRuntime.jsxs(Link8__default.default, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
5853
- brandNode,
5854
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
5855
- ] }),
5856
- family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current: current2, className: "max-md:hidden" }) : null,
5857
- tool && navigation ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-5", children: navigation }) : null
5858
- ] }),
5859
- !tool ? navigation : null,
5860
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
5861
- search,
5862
- actions,
5863
- menu ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
5864
- /* @__PURE__ */ jsxRuntime.jsx(
5865
- SheetTrigger,
5866
+ className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
5867
+ style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
5868
+ children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
5869
+ Link6__default.default,
5870
+ {
5871
+ href: it.href,
5872
+ "aria-current": it.active ? "page" : void 0,
5873
+ className: cn(
5874
+ "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
5875
+ it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
5876
+ ),
5877
+ children: [
5878
+ /* @__PURE__ */ jsxRuntime.jsxs(
5879
+ "span",
5866
5880
  {
5867
- className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
5868
- "aria-label": "Open menu",
5869
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
5881
+ className: cn(
5882
+ "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
5883
+ "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
5884
+ it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
5885
+ ),
5886
+ children: [
5887
+ it.icon,
5888
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
5889
+ ]
5870
5890
  }
5871
5891
  ),
5872
- /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "right", className: "pt-16", children: [
5873
- /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
5874
- menuExtra ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
5875
- phoneNav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
5876
- (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-2", children: [
5877
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
5878
- n.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
5879
- NavLink,
5880
- {
5881
- item: c,
5882
- className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
5883
- onNavigate: () => setOpen(false)
5884
- },
5885
- c.href
5886
- ))
5887
- ] }, n.href) : /* @__PURE__ */ jsxRuntime.jsx(
5888
- NavLink,
5889
- {
5890
- item: n,
5891
- className: "rounded-xl px-3 py-3 text-[1.0625rem]",
5892
- onNavigate: () => setOpen(false)
5893
- },
5894
- n.href
5895
- )
5896
- ) }) : null,
5897
- family ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
5898
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
5899
- "All orangecheck sites",
5900
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
5901
- ] }),
5902
- /* @__PURE__ */ jsxRuntime.jsx(FamilyList, { current: current2, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
5903
- ] }) : null
5904
- ] })
5905
- ] }) : null
5906
- ] })
5907
- ]
5892
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
5893
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: it.badge }) : null
5894
+ ]
5895
+ },
5896
+ it.href
5897
+ ))
5908
5898
  }
5909
5899
  )
5910
5900
  }
5911
5901
  );
5912
5902
  }
5913
- function SkipLink({ href = "#main-content", children = "Skip to content" }) {
5914
- return /* @__PURE__ */ jsxRuntime.jsx(
5915
- "a",
5916
- {
5917
- href,
5918
- className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
5919
- children
5903
+ function tabsFor(groups) {
5904
+ const items = groups.flatMap((g) => g.items);
5905
+ return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
5906
+ }
5907
+ var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
5908
+ var warned = /* @__PURE__ */ new Set();
5909
+ function warnDuplicateLabels(groups) {
5910
+ if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
5911
+ const seen = /* @__PURE__ */ new Set();
5912
+ for (const it of groups.flatMap((g) => g.items)) {
5913
+ if (seen.has(it.label) && !warned.has(it.label)) {
5914
+ warned.add(it.label);
5915
+ console.warn(`AppShell: two pages are labelled "${it.label}"; give each its own name.`);
5920
5916
  }
5921
- );
5917
+ seen.add(it.label);
5918
+ }
5922
5919
  }
5923
- var BANNER_TONE = {
5924
- neutral: "border-border bg-muted",
5925
- brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
5926
- danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
5927
- };
5928
- function SiteBanner({
5929
- tone = "neutral",
5920
+ function AppShell({
5921
+ nav,
5922
+ sections,
5923
+ activeSection,
5924
+ page: pageOverride,
5925
+ persistent = [],
5926
+ home = "/",
5927
+ family,
5928
+ account,
5929
+ banner,
5930
+ footer,
5930
5931
  children,
5931
- action,
5932
5932
  className
5933
5933
  }) {
5934
- return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "data-tone": tone, className: cn("border-b text-[0.875rem]", BANNER_TONE[tone], className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oca-container flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-2.5", children: [
5935
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
5936
- tone !== "neutral" ? /* @__PURE__ */ jsxRuntime.jsx(
5937
- "span",
5938
- {
5939
- "aria-hidden": true,
5940
- className: cn(
5941
- "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
5942
- tone === "brand" ? "bg-oca-orange" : "bg-destructive"
5943
- )
5944
- }
5945
- ) : null,
5946
- /* @__PURE__ */ jsxRuntime.jsx("span", { children })
5947
- ] }),
5948
- action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
5949
- ] }) });
5950
- }
5951
- var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
5952
- function LegalRow({ links }) {
5953
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
5954
- /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-5", children: links.map((l) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: l.href.startsWith("/") ? /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href: l.href, className: FOOT_LINK, children: l.label }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
5955
- /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
5956
- "\xA9 ",
5957
- (/* @__PURE__ */ new Date()).getFullYear(),
5958
- " OrangeCheck"
5959
- ] })
5960
- ] });
5961
- }
5962
- function SiteFooter({
5963
- columns = [],
5964
- family = false,
5965
- legal = false,
5966
- compact = false,
5967
- fineprint,
5968
- meta,
5969
- signature = true,
5970
- className
5971
- }) {
5972
- const legalLinks = legal === true ? LEGAL_LINKS : legal || null;
5973
- if (compact) {
5974
- return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: cn("border-t border-border bg-background text-[0.875rem] text-muted-foreground", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oca-container flex flex-col gap-x-8 gap-y-3 py-5 lg:flex-row lg:items-center lg:justify-between", children: [
5975
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
5976
- /* @__PURE__ */ jsxRuntime.jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
5977
- family ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Protocols", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-4", children: PROTOCOLS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: p.pageHref, className: FOOT_LINK, children: p.label }) }, p.slug)) }) }) : null
5978
- ] }),
5979
- legalLinks || meta ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
5980
- legalLinks ? /* @__PURE__ */ jsxRuntime.jsx(LegalRow, { links: legalLinks }) : null,
5981
- meta
5982
- ] }) : null
5983
- ] }) });
5984
- }
5985
- const cols = [
5986
- ...columns,
5987
- ...family ? familyByGroup().map((g) => ({
5988
- // The lockup above already says orangecheck.
5989
- heading: g.id === "orangecheck" ? "Start here" : g.label,
5990
- links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
5991
- })) : []
5992
- ];
5993
- const n = cols.length;
5994
- const inline = n <= 5;
5995
- const grid = {
5996
- "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
5997
- "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
5998
- };
5999
- return /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
6000
- /* @__PURE__ */ jsxRuntime.jsxs(
6001
- "div",
6002
- {
6003
- style: grid,
6004
- className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[var(--oca-footer-md)] md:py-16 lg:grid-cols-[var(--oca-footer-lg)]",
6005
- children: [
6006
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
6007
- /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }),
6008
- fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
6009
- ] }),
6010
- cols.map((col, i) => {
6011
- const spans = n % 2 === 1 && i === n - 1;
6012
- return /* @__PURE__ */ jsxRuntime.jsxs(
6013
- "div",
6014
- {
6015
- className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
6016
- children: [
6017
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
6018
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
6019
- NavLink,
6020
- {
6021
- item: l,
6022
- className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
6023
- },
6024
- l.href
6025
- )) })
6026
- ]
6027
- },
6028
- col.heading
6029
- );
6030
- })
6031
- ]
6032
- }
6033
- ),
6034
- signature ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "oca-container select-none overflow-hidden pb-8 md:pb-12", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-[0.18em] text-[clamp(3rem,11.5vw,10rem)] leading-[0.78] tracking-[-0.065em] [font-family:var(--oc-font-display)]", children: [
6035
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Mark, { className: "block h-auto w-full" }) }),
6036
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "orangecheck" })
6037
- ] }) }) : null,
6038
- legalLinks || meta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: [
6039
- legalLinks ? /* @__PURE__ */ jsxRuntime.jsx(LegalRow, { links: legalLinks }) : null,
6040
- meta
6041
- ] }) }) : null
6042
- ] });
6043
- }
6044
- function SignInFrame({
6045
- title = "Sign in",
6046
- lead,
6047
- children,
6048
- error,
6049
- fineprint,
6050
- brand,
6051
- home = "/",
6052
- back,
6053
- art,
6054
- caption,
6055
- className
6056
- }) {
6057
- return /* @__PURE__ */ jsxRuntime.jsxs(
6058
- "main",
5934
+ const [open, setOpen] = react.useState(false);
5935
+ const current2 = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
5936
+ const groups = current2 ? [...current2.groups, ...persistent] : [...nav ?? [], ...persistent];
5937
+ warnDuplicateLabels(groups);
5938
+ const tabs = current2 ? null : tabsFor(groups);
5939
+ const page = activeItem(groups);
5940
+ const place = react.useMemo(
5941
+ () => ({
5942
+ section: current2 ? current2.title ?? current2.label : void 0,
5943
+ page: pageOverride ?? page?.label
5944
+ }),
5945
+ [current2, page?.label, pageOverride]
5946
+ );
5947
+ const familyMenu = family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current: typeof family === "string" ? family : void 0 }) : null;
5948
+ const switcher = sections && current2 && sections.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(SectionSwitch, { sections, current: current2, onNavigate: () => setOpen(false) }) : null;
5949
+ return /* @__PURE__ */ jsxRuntime.jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxRuntime.jsxs(
5950
+ "div",
6059
5951
  {
6060
- id: "main-content",
6061
- className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
5952
+ className: cn(
5953
+ "min-h-dvh bg-background",
5954
+ tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
5955
+ className
5956
+ ),
6062
5957
  children: [
6063
- /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
6064
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-center justify-between gap-4", children: [
6065
- /* @__PURE__ */ jsxRuntime.jsxs(Link8__default.default, { href: home, className: "w-fit rounded-lg", children: [
6066
- brand ?? /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 28 }),
6067
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
5958
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
5959
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
5960
+ /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
5961
+ /* @__PURE__ */ jsxRuntime.jsx(
5962
+ SheetTrigger,
5963
+ {
5964
+ className: cn(
5965
+ "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
5966
+ // The tab bar holds every page; the sheet is left for a footer.
5967
+ tabs && !footer && "max-md:hidden"
5968
+ ),
5969
+ "aria-label": "Open navigation",
5970
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
5971
+ }
5972
+ ),
5973
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
5974
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
5975
+ switcher,
5976
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
5977
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
5978
+ ] })
6068
5979
  ] }),
6069
- back === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
6070
- Link8__default.default,
6071
- {
6072
- href: home,
6073
- className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
6074
- children: "Back to home"
6075
- }
6076
- ) : back
5980
+ /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
5981
+ familyMenu,
5982
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: account })
6077
5983
  ] }),
6078
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
6079
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
6080
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2", children: title }),
6081
- lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead", children: lead }) : null
5984
+ place.page ? /* @__PURE__ */ jsxRuntime.jsxs(
5985
+ "div",
5986
+ {
5987
+ className: cn(
5988
+ "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
5989
+ // The active tab already names the page.
5990
+ tabs && !pageOverride && "max-md:hidden"
5991
+ ),
5992
+ children: [
5993
+ place.section ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5994
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
5995
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
5996
+ ] }) : null,
5997
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
5998
+ ]
5999
+ }
6000
+ ) : null
6001
+ ] }),
6002
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
6003
+ /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
6004
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
6005
+ /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }) }),
6006
+ familyMenu
6082
6007
  ] }),
6083
- /* @__PURE__ */ jsxRuntime.jsx("div", { children }),
6084
- error ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
6085
- fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
6008
+ switcher,
6009
+ /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups }),
6010
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
6011
+ ] }),
6012
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6013
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
6014
+ banner ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
6015
+ /* @__PURE__ */ jsxRuntime.jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
6086
6016
  ] })
6087
6017
  ] }),
6088
- /* @__PURE__ */ jsxRuntime.jsxs(
6089
- "aside",
6090
- {
6091
- "aria-hidden": true,
6092
- className: "relative hidden flex-col justify-between gap-10 overflow-hidden border-l border-[var(--oca-band-line)] bg-oca-ink p-14 text-oca-ink-foreground lg:flex",
6093
- children: [
6094
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center justify-center", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) }),
6095
- caption ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
6096
- ]
6097
- }
6098
- )
6018
+ tabs ? /* @__PURE__ */ jsxRuntime.jsx(TabBar, { items: tabs }) : null
6099
6019
  ]
6100
6020
  }
6101
- );
6102
- }
6103
- var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
6104
- var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
6105
- function DocsNav({
6106
- sections,
6107
- current: current2,
6108
- onNavigate,
6109
- className
6110
- }) {
6111
- const here = pathOf(current2);
6112
- const activeSection = react.useMemo(
6113
- () => sections.findIndex((s) => s.items.some((i) => pathOf(i.href) === here)),
6114
- [sections, here]
6115
- );
6116
- const [peeked, setPeeked] = react.useState(() => /* @__PURE__ */ new Set());
6117
- react.useEffect(() => setPeeked(/* @__PURE__ */ new Set()), [activeSection]);
6118
- const activeRef = react.useRef(null);
6119
- react.useEffect(() => {
6120
- const id = requestAnimationFrame(() => activeRef.current?.scrollIntoView({ block: "nearest" }));
6121
- return () => cancelAnimationFrame(id);
6122
- }, [here]);
6123
- const base = react.useId();
6124
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Docs", className: cn("flex flex-col gap-0.5", className), children: sections.map((section, si) => {
6125
- const isActive = si === activeSection;
6126
- const open = isActive || peeked.has(si);
6127
- const panel = `${base}-s${si}`;
6128
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
6129
- /* @__PURE__ */ jsxRuntime.jsxs(
6130
- "button",
6131
- {
6132
- type: "button",
6133
- "aria-expanded": open,
6134
- "aria-controls": panel,
6135
- onClick: () => {
6136
- if (isActive) return;
6137
- setPeeked((p) => {
6138
- const n = new Set(p);
6139
- if (n.has(si)) n.delete(si);
6140
- else n.add(si);
6141
- return n;
6142
- });
6143
- },
6144
- className: cn(
6145
- "flex min-h-9 w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-[0.875rem] transition-colors",
6146
- isActive ? "font-medium text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground",
6147
- isActive && "cursor-default"
6148
- ),
6149
- children: [
6150
- section.label,
6151
- /* @__PURE__ */ jsxRuntime.jsx(
6152
- lucideReact.ChevronRight,
6153
- {
6154
- "aria-hidden": true,
6155
- className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
6156
- }
6157
- )
6158
- ]
6159
- }
6160
- ),
6161
- /* @__PURE__ */ jsxRuntime.jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
6162
- const on = pathOf(item.href) === here;
6163
- const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: item.badge }) : null;
6164
- return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
6165
- Link8__default.default,
6166
- {
6167
- href: item.href,
6168
- ref: on ? activeRef : void 0,
6169
- onClick: onNavigate,
6170
- "aria-current": on ? "page" : void 0,
6171
- className: cn(
6172
- "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
6173
- on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
6174
- ),
6175
- children: [
6176
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: item.label }),
6177
- badge
6178
- ]
6179
- }
6180
- ) }, item.href);
6181
- }) })
6182
- ] }, section.label);
6183
- }) });
6021
+ ) });
6184
6022
  }
6185
- var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
6186
- function DocsShell({
6187
- nav,
6188
- current: current2,
6189
- header,
6190
- search,
6191
- actions,
6192
- breadcrumbs,
6193
- toc,
6194
- pager,
6195
- footer,
6196
- children
6023
+ function AccountMenu({
6024
+ name,
6025
+ detail,
6026
+ items,
6027
+ nameFrom = "sm"
6197
6028
  }) {
6198
- const [menu, setMenu] = react.useState(false);
6199
- react.useEffect(() => setMenu(false), [current2]);
6200
- const read = useHeadings("#docs-content", current2);
6201
- const items = toc ?? read.items;
6202
- const activeId = toc ? void 0 : read.activeId;
6203
- const here = pathOf(current2);
6204
- const place = react.useMemo(() => {
6205
- for (const s of nav) {
6206
- const it = s.items.find((i) => pathOf(i.href) === here);
6207
- if (it) return { section: s.label, page: it.label };
6208
- }
6209
- return null;
6210
- }, [nav, here]);
6211
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
6212
- /* @__PURE__ */ jsxRuntime.jsx(SkipLink, {}),
6213
- header ?? /* @__PURE__ */ jsxRuntime.jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
6214
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
6215
- /* @__PURE__ */ jsxRuntime.jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
6216
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
6217
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Docs menu. " }),
6218
- place ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
6219
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
6220
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
6221
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
6222
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Docs" })
6223
- ] }),
6224
- /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
6225
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
6226
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current: current2, onNavigate: () => setMenu(false) }) })
6227
- ] })
6228
- ] }) }) }),
6229
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
6230
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current: current2 }) }),
6231
- /* @__PURE__ */ jsxRuntime.jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
6232
- breadcrumbs ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
6233
- items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
6234
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
6235
- "On this page",
6236
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
6237
- ] }),
6238
- /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
6239
- ] }) : null,
6240
- /* @__PURE__ */ jsxRuntime.jsx("article", { id: "docs-content", className: "max-w-[46rem]", children }),
6241
- pager ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
6242
- ] }),
6243
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId }) : null })
6244
- ] }) }),
6245
- footer ?? /* @__PURE__ */ jsxRuntime.jsx(SiteFooter, { columns: OCHK_IO_FOOTER, family: true, legal: true, signature: false })
6246
- ] });
6247
- }
6248
- function SideNav({ groups, onNavigate }) {
6249
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
6250
- g.label ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
6251
- g.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
6252
- Link8__default.default,
6029
+ const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
6030
+ return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
6031
+ /* @__PURE__ */ jsxRuntime.jsxs(
6032
+ DropdownMenuTrigger,
6253
6033
  {
6254
- href: it.href,
6255
- onClick: onNavigate,
6256
- "aria-current": it.active ? "page" : void 0,
6257
6034
  className: cn(
6258
- "flex h-9 items-center gap-3 rounded-xl px-3 text-[0.9375rem] transition-colors",
6259
- "[&_svg]:size-[1.0625rem] [&_svg]:shrink-0",
6260
- it.active ? "bg-card text-foreground shadow-sm ring-1 ring-border [&_svg]:text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground"
6035
+ "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
6036
+ nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
6261
6037
  ),
6038
+ "aria-label": `${name}, account menu`,
6262
6039
  children: [
6263
- it.icon,
6264
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: it.label }),
6265
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: it.badge }) : null
6040
+ /* @__PURE__ */ jsxRuntime.jsx(
6041
+ "span",
6042
+ {
6043
+ "aria-hidden": true,
6044
+ "data-initial": initial,
6045
+ className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
6046
+ }
6047
+ ),
6048
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
6266
6049
  ]
6267
- },
6268
- it.href
6269
- ))
6270
- ] }, g.label ?? gi)) });
6050
+ }
6051
+ ),
6052
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-64", children: [
6053
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
6054
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: name }),
6055
+ detail ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-[0.75rem]", children: detail }) : null
6056
+ ] }),
6057
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
6058
+ items.map(
6059
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxRuntime.jsxs(Link6__default.default, { href: it.href, children: [
6060
+ it.icon,
6061
+ it.label
6062
+ ] }) }, it.label) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
6063
+ it.icon,
6064
+ it.label
6065
+ ] }, it.label)
6066
+ )
6067
+ ] })
6068
+ ] });
6271
6069
  }
6272
- function SectionSwitch({
6273
- sections,
6274
- current: current2,
6275
- onNavigate
6276
- }) {
6277
- const cols = sections.length <= 3 ? sections.length : 2;
6070
+ function ThemeToggle({ className }) {
6071
+ const { theme, setTheme } = nextThemes.useTheme();
6072
+ const [mounted, setMounted] = react.useState(false);
6073
+ react.useEffect(() => setMounted(true), []);
6074
+ const current2 = mounted ? theme ?? "system" : "system";
6075
+ const next = current2 === "light" ? "dark" : current2 === "dark" ? "system" : "light";
6076
+ const Icon2 = current2 === "light" ? lucideReact.Sun : current2 === "dark" ? lucideReact.Moon : lucideReact.SunMoon;
6278
6077
  return /* @__PURE__ */ jsxRuntime.jsx(
6279
- "nav",
6078
+ "button",
6280
6079
  {
6281
- "aria-label": "Sections",
6282
- className: cn("grid gap-1 bg-muted p-1", cols === sections.length ? "rounded-full" : "rounded-[1.25rem]"),
6283
- style: { gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))` },
6284
- children: sections.map((sec) => {
6285
- const on = sec.id === current2.id;
6286
- return /* @__PURE__ */ jsxRuntime.jsx(
6287
- Link8__default.default,
6288
- {
6289
- href: sec.href,
6290
- onClick: onNavigate,
6291
- "aria-current": on ? "true" : void 0,
6292
- className: cn(
6293
- "flex h-8 min-w-0 items-center justify-center rounded-full px-1.5 text-[0.8125rem] font-medium transition-colors",
6294
- on ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
6295
- ),
6296
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: sec.label })
6297
- },
6298
- sec.id
6299
- );
6300
- })
6080
+ type: "button",
6081
+ onClick: () => setTheme(next),
6082
+ "aria-label": `Theme: ${current2}. Switch to ${next}`,
6083
+ title: `Theme: ${current2}`,
6084
+ className: cn(
6085
+ "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
6086
+ className
6087
+ ),
6088
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-[1.125rem]" })
6301
6089
  }
6302
6090
  );
6303
6091
  }
6304
- function TabBar({ items }) {
6092
+ function NavLink({
6093
+ item,
6094
+ className,
6095
+ onNavigate,
6096
+ line = false
6097
+ }) {
6098
+ const cls = cn(
6099
+ "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
6100
+ item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
6101
+ line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
6102
+ line && item.active && "after:bg-foreground",
6103
+ className
6104
+ );
6105
+ if (item.external) {
6106
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
6107
+ }
6108
+ return /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
6109
+ }
6110
+ function NavRow({ item, onNavigate }) {
6111
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6112
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
6113
+ item.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
6114
+ ] });
6115
+ const cls = cn(
6116
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
6117
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
6118
+ );
6119
+ return item.external ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
6120
+ }
6121
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
6122
+ function NavDropdown({ item }) {
6123
+ const [open, setOpen] = react.useState(false);
6124
+ const active = item.active || item.children?.some((c) => c.active);
6125
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
6126
+ /* @__PURE__ */ jsxRuntime.jsxs(
6127
+ PopoverTrigger,
6128
+ {
6129
+ className: cn(
6130
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors md:max-lg:pl-2.5 md:max-lg:pr-2",
6131
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
6132
+ ),
6133
+ children: [
6134
+ item.label,
6135
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
6136
+ ]
6137
+ }
6138
+ ),
6139
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
6140
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
6141
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
6142
+ NavLink,
6143
+ {
6144
+ item: { ...item, label: seeAll(item), children: void 0 },
6145
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
6146
+ onNavigate: () => setOpen(false)
6147
+ }
6148
+ ) })
6149
+ ] })
6150
+ ] });
6151
+ }
6152
+ function SiteHeader({
6153
+ home = "/",
6154
+ brand,
6155
+ product,
6156
+ family,
6157
+ nav = [],
6158
+ search,
6159
+ actions,
6160
+ variant = "site",
6161
+ navOnPhone = true,
6162
+ menu: menuExtra,
6163
+ className
6164
+ }) {
6165
+ const [open, setOpen] = react.useState(false);
6166
+ const tool = variant === "tool";
6167
+ const size = tool ? 24 : 28;
6168
+ const current2 = typeof family === "string" ? family : void 0;
6169
+ const phoneNav = navOnPhone ? nav : [];
6170
+ const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
6171
+ const brandNode = brand ?? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center", children: [
6172
+ /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size }),
6173
+ product ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6174
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
6175
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
6176
+ ] }) : null
6177
+ ] });
6178
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
6179
+ (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsx(NavDropdown, { item: n }, n.href) : (
6180
+ // Between md and lg the family menu and the actions share the row: tighter.
6181
+ /* @__PURE__ */ jsxRuntime.jsx(NavLink, { item: n, line: tool, className: tool ? void 0 : "md:max-lg:px-2.5" }, n.href)
6182
+ )
6183
+ ) }) : null;
6305
6184
  return /* @__PURE__ */ jsxRuntime.jsx(
6306
- "nav",
6185
+ "header",
6307
6186
  {
6308
- "aria-label": "Pages",
6309
- "data-oca-tabbar": "",
6310
- className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
6311
- children: /* @__PURE__ */ jsxRuntime.jsx(
6187
+ className: cn(
6188
+ "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
6189
+ tool ? "border-border" : "border-transparent",
6190
+ className
6191
+ ),
6192
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
6312
6193
  "div",
6313
6194
  {
6314
- className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
6315
- style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
6316
- children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
6317
- Link8__default.default,
6318
- {
6319
- href: it.href,
6320
- "aria-current": it.active ? "page" : void 0,
6321
- className: cn(
6322
- "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
6323
- it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
6324
- ),
6325
- children: [
6326
- /* @__PURE__ */ jsxRuntime.jsxs(
6327
- "span",
6195
+ className: cn(
6196
+ "flex items-center justify-between gap-4",
6197
+ tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem] md:max-lg:gap-2",
6198
+ // Three columns, the outer two each at least their content: the
6199
+ // navigation stays centred whatever the actions hold, so it does
6200
+ // not shift when they change (signed out to signed in).
6201
+ !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
6202
+ ),
6203
+ children: [
6204
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
6205
+ /* @__PURE__ */ jsxRuntime.jsxs(Link6__default.default, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
6206
+ brandNode,
6207
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
6208
+ ] }),
6209
+ family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current: current2, className: "max-md:hidden" }) : null,
6210
+ tool && navigation ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-5", children: navigation }) : null
6211
+ ] }),
6212
+ !tool ? navigation : null,
6213
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
6214
+ search,
6215
+ actions,
6216
+ menu ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
6217
+ /* @__PURE__ */ jsxRuntime.jsx(
6218
+ SheetTrigger,
6328
6219
  {
6329
- className: cn(
6330
- "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
6331
- "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
6332
- it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
6333
- ),
6334
- children: [
6335
- it.icon,
6336
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
6337
- ]
6220
+ className: "inline-flex size-10 items-center justify-center rounded-full text-foreground hover:bg-accent md:hidden",
6221
+ "aria-label": "Open menu",
6222
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
6338
6223
  }
6339
6224
  ),
6340
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
6341
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: it.badge }) : null
6342
- ]
6343
- },
6344
- it.href
6345
- ))
6225
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "right", className: "pt-16", children: [
6226
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
6227
+ menuExtra ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
6228
+ phoneNav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
6229
+ (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-2", children: [
6230
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
6231
+ n.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
6232
+ NavLink,
6233
+ {
6234
+ item: c,
6235
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
6236
+ onNavigate: () => setOpen(false)
6237
+ },
6238
+ c.href
6239
+ ))
6240
+ ] }, n.href) : /* @__PURE__ */ jsxRuntime.jsx(
6241
+ NavLink,
6242
+ {
6243
+ item: n,
6244
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
6245
+ onNavigate: () => setOpen(false)
6246
+ },
6247
+ n.href
6248
+ )
6249
+ ) }) : null,
6250
+ family ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
6251
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
6252
+ "All orangecheck sites",
6253
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
6254
+ ] }),
6255
+ /* @__PURE__ */ jsxRuntime.jsx(FamilyList, { current: current2, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
6256
+ ] }) : null
6257
+ ] })
6258
+ ] }) : null
6259
+ ] })
6260
+ ]
6346
6261
  }
6347
6262
  )
6348
6263
  }
6349
6264
  );
6350
6265
  }
6351
- function tabsFor(groups) {
6352
- const items = groups.flatMap((g) => g.items);
6353
- return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
6354
- }
6355
- var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
6356
- var warned = /* @__PURE__ */ new Set();
6357
- function warnDuplicateLabels(groups) {
6358
- if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
6359
- const seen = /* @__PURE__ */ new Set();
6360
- for (const it of groups.flatMap((g) => g.items)) {
6361
- if (seen.has(it.label) && !warned.has(it.label)) {
6362
- warned.add(it.label);
6363
- console.warn(`AppShell: two pages are labelled "${it.label}"; give each its own name.`);
6266
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
6267
+ return /* @__PURE__ */ jsxRuntime.jsx(
6268
+ "a",
6269
+ {
6270
+ href,
6271
+ className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
6272
+ children
6364
6273
  }
6365
- seen.add(it.label);
6366
- }
6274
+ );
6367
6275
  }
6368
- function AppShell({
6369
- nav,
6370
- sections,
6371
- activeSection,
6372
- page: pageOverride,
6373
- persistent = [],
6374
- home = "/",
6375
- account,
6376
- banner,
6377
- footer,
6276
+ var BANNER_TONE = {
6277
+ neutral: "border-border bg-muted",
6278
+ brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
6279
+ danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
6280
+ };
6281
+ function SiteBanner({
6282
+ tone = "neutral",
6378
6283
  children,
6284
+ action,
6379
6285
  className
6380
6286
  }) {
6381
- const [open, setOpen] = react.useState(false);
6382
- const current2 = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
6383
- const groups = current2 ? [...current2.groups, ...persistent] : [...nav ?? [], ...persistent];
6384
- warnDuplicateLabels(groups);
6385
- const tabs = current2 ? null : tabsFor(groups);
6386
- const page = activeItem(groups);
6387
- const place = react.useMemo(
6388
- () => ({
6389
- section: current2 ? current2.title ?? current2.label : void 0,
6390
- page: pageOverride ?? page?.label
6391
- }),
6392
- [current2, page?.label, pageOverride]
6393
- );
6394
- const switcher = sections && current2 && sections.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(SectionSwitch, { sections, current: current2, onNavigate: () => setOpen(false) }) : null;
6395
- return /* @__PURE__ */ jsxRuntime.jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxRuntime.jsxs(
6396
- "div",
6397
- {
6398
- className: cn(
6399
- "min-h-dvh bg-background",
6400
- tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]",
6401
- className
6402
- ),
6403
- children: [
6404
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-md lg:hidden", children: [
6405
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 items-center gap-2 px-3", children: [
6406
- /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
6407
- /* @__PURE__ */ jsxRuntime.jsx(
6408
- SheetTrigger,
6409
- {
6410
- className: cn(
6411
- "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
6412
- // The tab bar holds every page; the sheet is left for a footer.
6413
- tabs && !footer && "max-md:hidden"
6414
- ),
6415
- "aria-label": "Open navigation",
6416
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
6417
- }
6418
- ),
6419
- /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
6420
- /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
6421
- switcher,
6422
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
6423
- footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
6424
- ] })
6425
- ] }),
6426
- /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
6427
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: account })
6287
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "data-tone": tone, className: cn("border-b text-[0.875rem]", BANNER_TONE[tone], className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oca-container flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-2.5", children: [
6288
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
6289
+ tone !== "neutral" ? /* @__PURE__ */ jsxRuntime.jsx(
6290
+ "span",
6291
+ {
6292
+ "aria-hidden": true,
6293
+ className: cn(
6294
+ "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
6295
+ tone === "brand" ? "bg-oca-orange" : "bg-destructive"
6296
+ )
6297
+ }
6298
+ ) : null,
6299
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children })
6300
+ ] }),
6301
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
6302
+ ] }) });
6303
+ }
6304
+ var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
6305
+ function LegalRow({ links }) {
6306
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
6307
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-5", children: links.map((l) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: l.href.startsWith("/") ? /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: l.href, className: FOOT_LINK, children: l.label }) : /* @__PURE__ */ jsxRuntime.jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
6308
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
6309
+ "\xA9 ",
6310
+ (/* @__PURE__ */ new Date()).getFullYear(),
6311
+ " OrangeCheck"
6312
+ ] })
6313
+ ] });
6314
+ }
6315
+ function SiteFooter({
6316
+ columns = [],
6317
+ family = false,
6318
+ legal = false,
6319
+ compact = false,
6320
+ fineprint,
6321
+ meta,
6322
+ signature = true,
6323
+ className
6324
+ }) {
6325
+ const legalLinks = legal === true ? LEGAL_LINKS : legal || null;
6326
+ if (compact) {
6327
+ return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: cn("border-t border-border bg-background text-[0.875rem] text-muted-foreground", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oca-container flex flex-col gap-x-8 gap-y-3 py-5 lg:flex-row lg:items-center lg:justify-between", children: [
6328
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
6329
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
6330
+ family ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Protocols", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-4", children: PROTOCOLS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: p.pageHref, className: FOOT_LINK, children: p.label }) }, p.slug)) }) }) : null
6331
+ ] }),
6332
+ legalLinks || meta ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
6333
+ legalLinks ? /* @__PURE__ */ jsxRuntime.jsx(LegalRow, { links: legalLinks }) : null,
6334
+ meta
6335
+ ] }) : null
6336
+ ] }) });
6337
+ }
6338
+ const cols = [
6339
+ ...columns,
6340
+ ...family ? familyByGroup().map((g) => ({
6341
+ // The lockup above already says orangecheck.
6342
+ heading: g.id === "orangecheck" ? "Start here" : g.label,
6343
+ links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
6344
+ })) : []
6345
+ ];
6346
+ const n = cols.length;
6347
+ const inline = n <= 5;
6348
+ const grid = {
6349
+ "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
6350
+ "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
6351
+ };
6352
+ return /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
6353
+ /* @__PURE__ */ jsxRuntime.jsxs(
6354
+ "div",
6355
+ {
6356
+ style: grid,
6357
+ className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[var(--oca-footer-md)] md:py-16 lg:grid-cols-[var(--oca-footer-lg)]",
6358
+ children: [
6359
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
6360
+ /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }),
6361
+ fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
6428
6362
  ] }),
6429
- place.page ? /* @__PURE__ */ jsxRuntime.jsxs(
6430
- "div",
6431
- {
6432
- className: cn(
6433
- "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
6434
- // The active tab already names the page.
6435
- tabs && !pageOverride && "max-md:hidden"
6436
- ),
6437
- children: [
6438
- place.section ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6439
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
6440
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-muted-foreground" })
6441
- ] }) : null,
6442
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
6443
- ]
6444
- }
6445
- ) : null
6363
+ cols.map((col, i) => {
6364
+ const spans = n % 2 === 1 && i === n - 1;
6365
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6366
+ "div",
6367
+ {
6368
+ className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
6369
+ children: [
6370
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
6371
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
6372
+ NavLink,
6373
+ {
6374
+ item: l,
6375
+ className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
6376
+ },
6377
+ l.href
6378
+ )) })
6379
+ ]
6380
+ },
6381
+ col.heading
6382
+ );
6383
+ })
6384
+ ]
6385
+ }
6386
+ ),
6387
+ signature ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "oca-container select-none overflow-hidden pb-8 md:pb-12", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-[0.18em] text-[clamp(3rem,11.5vw,10rem)] leading-[0.78] tracking-[-0.065em] [font-family:var(--oc-font-display)]", children: [
6388
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Mark, { className: "block h-auto w-full" }) }),
6389
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "orangecheck" })
6390
+ ] }) }) : null,
6391
+ legalLinks || meta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: [
6392
+ legalLinks ? /* @__PURE__ */ jsxRuntime.jsx(LegalRow, { links: legalLinks }) : null,
6393
+ meta
6394
+ ] }) }) : null
6395
+ ] });
6396
+ }
6397
+ function OchkIoFooter({ columns = OCHK_IO_FOOTER, className }) {
6398
+ return /* @__PURE__ */ jsxRuntime.jsx(
6399
+ SiteFooter,
6400
+ {
6401
+ columns,
6402
+ family: true,
6403
+ legal: true,
6404
+ fineprint: "Open protocols on Bitcoin. Anyone can check the result.",
6405
+ meta: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
6406
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
6407
+ "Open-source work on orangecheck is ",
6408
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: "supported by OpenSats." })
6446
6409
  ] }),
6447
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
6448
- /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
6449
- /* @__PURE__ */ jsxRuntime.jsx(Link8__default.default, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }) }),
6450
- switcher,
6451
- /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups }),
6452
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
6410
+ /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, { className: "-mx-3" })
6411
+ ] }),
6412
+ className
6413
+ }
6414
+ );
6415
+ }
6416
+ function SignInFrame({
6417
+ title = "Sign in",
6418
+ lead,
6419
+ children,
6420
+ error,
6421
+ fineprint,
6422
+ brand,
6423
+ home = "/",
6424
+ back,
6425
+ art,
6426
+ caption,
6427
+ className
6428
+ }) {
6429
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6430
+ "main",
6431
+ {
6432
+ id: "main-content",
6433
+ className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
6434
+ children: [
6435
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
6436
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-center justify-between gap-4", children: [
6437
+ /* @__PURE__ */ jsxRuntime.jsxs(Link6__default.default, { href: home, className: "w-fit rounded-lg", children: [
6438
+ brand ?? /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 28 }),
6439
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
6440
+ ] }),
6441
+ back === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
6442
+ Link6__default.default,
6443
+ {
6444
+ href: home,
6445
+ className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
6446
+ children: "Back to home"
6447
+ }
6448
+ ) : back
6453
6449
  ] }),
6454
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6455
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden h-[4.5rem] items-center justify-end gap-3 px-8 lg:flex", children: account }),
6456
- banner ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2 pt-4 md:px-8 lg:pt-0", children: banner }) : null,
6457
- /* @__PURE__ */ jsxRuntime.jsx("main", { id: "main-content", className: "flex-1 px-4 pb-16 pt-6 md:px-8 lg:pt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-[72rem]", children }) })
6450
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
6451
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
6452
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2", children: title }),
6453
+ lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead", children: lead }) : null
6454
+ ] }),
6455
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children }),
6456
+ error ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
6457
+ fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
6458
6458
  ] })
6459
6459
  ] }),
6460
- tabs ? /* @__PURE__ */ jsxRuntime.jsx(TabBar, { items: tabs }) : null
6460
+ /* @__PURE__ */ jsxRuntime.jsxs(
6461
+ "aside",
6462
+ {
6463
+ "aria-hidden": true,
6464
+ className: "relative hidden flex-col justify-between gap-10 overflow-hidden border-l border-[var(--oca-band-line)] bg-oca-ink p-14 text-oca-ink-foreground lg:flex",
6465
+ children: [
6466
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center justify-center", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) }),
6467
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
6468
+ ]
6469
+ }
6470
+ )
6461
6471
  ]
6462
6472
  }
6463
- ) });
6473
+ );
6464
6474
  }
6465
- function AccountMenu({
6466
- name,
6467
- detail,
6468
- items,
6469
- nameFrom = "sm"
6475
+ var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
6476
+ var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
6477
+ function DocsNav({
6478
+ sections,
6479
+ current: current2,
6480
+ onNavigate,
6481
+ className
6470
6482
  }) {
6471
- const initial = name.trim().charAt(0).toUpperCase() || "\xB7";
6472
- return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
6473
- /* @__PURE__ */ jsxRuntime.jsxs(
6474
- DropdownMenuTrigger,
6475
- {
6476
- className: cn(
6477
- "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
6478
- nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
6479
- ),
6480
- "aria-label": `${name}, account menu`,
6481
- children: [
6482
- /* @__PURE__ */ jsxRuntime.jsx(
6483
- "span",
6484
- {
6485
- "aria-hidden": true,
6486
- "data-initial": initial,
6487
- className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
6488
- }
6483
+ const here = pathOf(current2);
6484
+ const activeSection = react.useMemo(
6485
+ () => sections.findIndex((s) => s.items.some((i) => pathOf(i.href) === here)),
6486
+ [sections, here]
6487
+ );
6488
+ const [peeked, setPeeked] = react.useState(() => /* @__PURE__ */ new Set());
6489
+ react.useEffect(() => setPeeked(/* @__PURE__ */ new Set()), [activeSection]);
6490
+ const activeRef = react.useRef(null);
6491
+ react.useEffect(() => {
6492
+ const id = requestAnimationFrame(() => activeRef.current?.scrollIntoView({ block: "nearest" }));
6493
+ return () => cancelAnimationFrame(id);
6494
+ }, [here]);
6495
+ const base = react.useId();
6496
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Docs", className: cn("flex flex-col gap-0.5", className), children: sections.map((section, si) => {
6497
+ const isActive = si === activeSection;
6498
+ const open = isActive || peeked.has(si);
6499
+ const panel = `${base}-s${si}`;
6500
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
6501
+ /* @__PURE__ */ jsxRuntime.jsxs(
6502
+ "button",
6503
+ {
6504
+ type: "button",
6505
+ "aria-expanded": open,
6506
+ "aria-controls": panel,
6507
+ onClick: () => {
6508
+ if (isActive) return;
6509
+ setPeeked((p) => {
6510
+ const n = new Set(p);
6511
+ if (n.has(si)) n.delete(si);
6512
+ else n.add(si);
6513
+ return n;
6514
+ });
6515
+ },
6516
+ className: cn(
6517
+ "flex min-h-9 w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-[0.875rem] transition-colors",
6518
+ isActive ? "font-medium text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground",
6519
+ isActive && "cursor-default"
6489
6520
  ),
6490
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
6491
- ]
6492
- }
6493
- ),
6494
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuContent, { align: "end", className: "w-64", children: [
6495
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuLabel, { className: "flex flex-col gap-0.5", children: [
6496
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: name }),
6497
- detail ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono text-[0.75rem]", children: detail }) : null
6498
- ] }),
6499
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
6500
- items.map(
6501
- (it, i) => it === "separator" ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxRuntime.jsxs(Link8__default.default, { href: it.href, children: [
6502
- it.icon,
6503
- it.label
6504
- ] }) }, it.label) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
6505
- it.icon,
6506
- it.label
6507
- ] }, it.label)
6508
- )
6509
- ] })
6510
- ] });
6511
- }
6512
- function ThemeToggle({ className }) {
6513
- const { theme, setTheme } = nextThemes.useTheme();
6514
- const [mounted, setMounted] = react.useState(false);
6515
- react.useEffect(() => setMounted(true), []);
6516
- const current2 = mounted ? theme ?? "system" : "system";
6517
- const next = current2 === "light" ? "dark" : current2 === "dark" ? "system" : "light";
6518
- const Icon2 = current2 === "light" ? lucideReact.Sun : current2 === "dark" ? lucideReact.Moon : lucideReact.SunMoon;
6519
- return /* @__PURE__ */ jsxRuntime.jsx(
6520
- "button",
6521
- {
6522
- type: "button",
6523
- onClick: () => setTheme(next),
6524
- "aria-label": `Theme: ${current2}. Switch to ${next}`,
6525
- title: `Theme: ${current2}`,
6526
- className: cn(
6527
- "inline-flex size-10 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
6528
- className
6521
+ children: [
6522
+ section.label,
6523
+ /* @__PURE__ */ jsxRuntime.jsx(
6524
+ lucideReact.ChevronRight,
6525
+ {
6526
+ "aria-hidden": true,
6527
+ className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
6528
+ }
6529
+ )
6530
+ ]
6531
+ }
6529
6532
  ),
6530
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-[1.125rem]" })
6533
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
6534
+ const on = pathOf(item.href) === here;
6535
+ const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: "muted", children: item.badge }) : null;
6536
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
6537
+ Link6__default.default,
6538
+ {
6539
+ href: item.href,
6540
+ ref: on ? activeRef : void 0,
6541
+ onClick: onNavigate,
6542
+ "aria-current": on ? "page" : void 0,
6543
+ className: cn(
6544
+ "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
6545
+ on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
6546
+ ),
6547
+ children: [
6548
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: item.label }),
6549
+ badge
6550
+ ]
6551
+ }
6552
+ ) }, item.href);
6553
+ }) })
6554
+ ] }, section.label);
6555
+ }) });
6556
+ }
6557
+ var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
6558
+ function DocsShell({
6559
+ nav,
6560
+ current: current2,
6561
+ navCurrent,
6562
+ header,
6563
+ search,
6564
+ actions,
6565
+ breadcrumbs,
6566
+ toc,
6567
+ pager,
6568
+ footer,
6569
+ children
6570
+ }) {
6571
+ const [menu, setMenu] = react.useState(false);
6572
+ react.useEffect(() => setMenu(false), [current2]);
6573
+ const read = useHeadings("#docs-content", current2);
6574
+ const items = toc ?? read.items;
6575
+ const activeId = toc ? void 0 : read.activeId;
6576
+ const marked = navCurrent ?? current2;
6577
+ const here = pathOf(marked);
6578
+ const place = react.useMemo(() => {
6579
+ for (const s of nav) {
6580
+ const it = s.items.find((i) => pathOf(i.href) === here);
6581
+ if (it) return { section: s.label, page: it.label };
6531
6582
  }
6532
- );
6583
+ return null;
6584
+ }, [nav, here]);
6585
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
6586
+ /* @__PURE__ */ jsxRuntime.jsx(SkipLink, {}),
6587
+ header ?? /* @__PURE__ */ jsxRuntime.jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
6588
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
6589
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
6590
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
6591
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Docs menu. " }),
6592
+ place ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
6593
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
6594
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
6595
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: place.page })
6596
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Docs" })
6597
+ ] }),
6598
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
6599
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
6600
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current: marked, onNavigate: () => setMenu(false) }) })
6601
+ ] })
6602
+ ] }) }) }),
6603
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
6604
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsxRuntime.jsx(DocsNav, { sections: nav, current: marked }) }),
6605
+ /* @__PURE__ */ jsxRuntime.jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
6606
+ breadcrumbs ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
6607
+ items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
6608
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
6609
+ "On this page",
6610
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
6611
+ ] }),
6612
+ /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
6613
+ ] }) : null,
6614
+ /* @__PURE__ */ jsxRuntime.jsx("article", { id: "docs-content", className: "max-w-[46rem]", children: /* @__PURE__ */ jsxRuntime.jsx(InDocsContext.Provider, { value: true, children }) }),
6615
+ pager ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
6616
+ ] }),
6617
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(OnThisPage, { items, activeId }) : null })
6618
+ ] }) }),
6619
+ footer ?? /* @__PURE__ */ jsxRuntime.jsx(OchkIoFooter, {})
6620
+ ] });
6533
6621
  }
6534
6622
  var OCHK_APP_ACCOUNT = "https://ochk.app/me/account";
6535
6623
  function onHistory(change) {
@@ -6691,6 +6779,7 @@ function rehypeCode(options = {}) {
6691
6779
  if (lang && skip.has(lang)) continue;
6692
6780
  const meta = parseCodeMeta(code.data?.meta);
6693
6781
  let source = textOf(code);
6782
+ const newline = /\n$/.test(source);
6694
6783
  const diff = meta.diff || lang === "diff" ? readDiff(source) : null;
6695
6784
  if (diff) source = diff.code;
6696
6785
  const lines = options.tokenize?.(source, lang) ?? highlight(source, lang === "diff" ? void 0 : lang);
@@ -6701,7 +6790,8 @@ function rehypeCode(options = {}) {
6701
6790
  ...lang ? { dataLang: lang } : {},
6702
6791
  ...meta.title ? { dataTitle: meta.title } : {},
6703
6792
  ...diff ? { dataDiff: "" } : {},
6704
- ...meta.lineNumbers ? { dataLineNumbers: "" } : {}
6793
+ ...meta.lineNumbers ? { dataLineNumbers: "" } : {},
6794
+ ...newline ? { dataEol: "" } : {}
6705
6795
  };
6706
6796
  child.children = [];
6707
6797
  continue;
@@ -6722,6 +6812,7 @@ function createMdxComponents({ mermaid } = {}) {
6722
6812
  caption: props["data-title"],
6723
6813
  diff: props["data-diff"] !== void 0,
6724
6814
  lineNumbers: props["data-line-numbers"] !== void 0,
6815
+ trailingNewline: props["data-eol"] !== void 0,
6725
6816
  className: "my-6"
6726
6817
  }
6727
6818
  );
@@ -6748,6 +6839,9 @@ function createMdxComponents({ mermaid } = {}) {
6748
6839
  const heading = (as) => function Heading(props) {
6749
6840
  return /* @__PURE__ */ jsxRuntime.jsx(DocsHeading, { as, ...props });
6750
6841
  };
6842
+ const minor = (Tag) => function Minor({ className, ...props }) {
6843
+ return /* @__PURE__ */ jsxRuntime.jsx(Tag, { className: cn("mb-2 mt-6 scroll-mt-28 text-[0.9375rem] font-medium leading-snug text-foreground", className), ...props });
6844
+ };
6751
6845
  return {
6752
6846
  h1: heading("h1"),
6753
6847
  h2: heading("h2"),
@@ -6756,11 +6850,15 @@ function createMdxComponents({ mermaid } = {}) {
6756
6850
  p: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("my-4 text-[1rem] leading-[1.75] text-muted-foreground md:text-[1.0625rem]", className), ...props }),
6757
6851
  a: A,
6758
6852
  strong: (props) => /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-medium text-foreground", ...props }),
6853
+ h5: minor("h5"),
6854
+ h6: minor("h6"),
6759
6855
  ul: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
6760
6856
  "ul",
6761
6857
  {
6762
6858
  className: cn(
6763
6859
  "my-4 list-disc space-y-1.5 pl-5 text-[1rem] leading-[1.7] text-muted-foreground marker:text-oca-subtle md:text-[1.0625rem]",
6860
+ // A GitHub task list: the box replaces the bullet.
6861
+ className?.includes("contains-task-list") && "list-none pl-0",
6764
6862
  className
6765
6863
  ),
6766
6864
  ...props
@@ -6776,7 +6874,26 @@ function createMdxComponents({ mermaid } = {}) {
6776
6874
  ...props
6777
6875
  }
6778
6876
  ),
6779
- li: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: cn("pl-1 [&>p]:my-1 [&>ul]:my-1.5 [&>ol]:my-1.5", className), ...props }),
6877
+ li: ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
6878
+ "li",
6879
+ {
6880
+ className: cn(
6881
+ "pl-1 [&>p]:my-1 [&>ul]:my-1.5 [&>ol]:my-1.5",
6882
+ // A wrapped task starts under its text, not under the box.
6883
+ className?.includes("task-list-item") && "pl-6 -indent-6",
6884
+ className
6885
+ ),
6886
+ ...props
6887
+ }
6888
+ ),
6889
+ input: (props) => props.type === "checkbox" ? /* @__PURE__ */ jsxRuntime.jsx(
6890
+ "input",
6891
+ {
6892
+ ...props,
6893
+ className: cn("mr-2 size-4 translate-y-[2px] align-baseline accent-foreground", props.className),
6894
+ "aria-label": props.checked ? "Done" : "To do"
6895
+ }
6896
+ ) : /* @__PURE__ */ jsxRuntime.jsx("input", { ...props }),
6780
6897
  blockquote: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx(Callout, { children }),
6781
6898
  hr: () => /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-10 border-border" }),
6782
6899
  table: MdxTable,
@@ -6919,6 +7036,7 @@ exports.OCHK_APP_ACCOUNT = OCHK_APP_ACCOUNT;
6919
7036
  exports.OCHK_IO = OCHK_IO;
6920
7037
  exports.OCHK_IO_FOOTER = OCHK_IO_FOOTER;
6921
7038
  exports.OCHK_IO_NAV = OCHK_IO_NAV;
7039
+ exports.OchkIoFooter = OchkIoFooter;
6922
7040
  exports.OnThisPage = OnThisPage;
6923
7041
  exports.PROTOCOLS = PROTOCOLS;
6924
7042
  exports.PROTOCOL_ORDER = PROTOCOL_ORDER;