@orangecheck/app-design 0.6.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +23 -6
  2. package/dist/brand.js.map +1 -1
  3. package/dist/brand.mjs.map +1 -1
  4. package/dist/chrome.d.mts +78 -55
  5. package/dist/chrome.d.ts +78 -55
  6. package/dist/chrome.js +1100 -59
  7. package/dist/chrome.js.map +1 -1
  8. package/dist/chrome.mjs +1091 -61
  9. package/dist/chrome.mjs.map +1 -1
  10. package/dist/code.d.mts +52 -0
  11. package/dist/code.d.ts +52 -0
  12. package/dist/code.js +534 -0
  13. package/dist/code.js.map +1 -0
  14. package/dist/code.mjs +522 -0
  15. package/dist/code.mjs.map +1 -0
  16. package/dist/components.d.mts +216 -42
  17. package/dist/components.d.ts +216 -42
  18. package/dist/components.js +3350 -100
  19. package/dist/components.js.map +1 -1
  20. package/dist/components.mjs +3293 -103
  21. package/dist/components.mjs.map +1 -1
  22. package/dist/docs-DhnstueM.d.ts +219 -0
  23. package/dist/docs-DiR6s43s.d.mts +219 -0
  24. package/dist/family.d.mts +2 -0
  25. package/dist/family.d.ts +2 -0
  26. package/dist/family.js +167 -0
  27. package/dist/family.js.map +1 -0
  28. package/dist/family.mjs +154 -0
  29. package/dist/family.mjs.map +1 -0
  30. package/dist/format.d.mts +12 -0
  31. package/dist/format.d.ts +12 -0
  32. package/dist/format.js +65 -0
  33. package/dist/format.js.map +1 -0
  34. package/dist/format.mjs +58 -0
  35. package/dist/format.mjs.map +1 -0
  36. package/dist/hero-Dn37il-9.d.mts +31 -0
  37. package/dist/hero-Dn37il-9.d.ts +31 -0
  38. package/dist/index-C6hDqOOS.d.mts +58 -0
  39. package/dist/index-C6hDqOOS.d.ts +58 -0
  40. package/dist/index.d.mts +12 -3
  41. package/dist/index.d.ts +12 -3
  42. package/dist/index.js +4319 -295
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +4219 -298
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/mdx.d.mts +58 -0
  47. package/dist/mdx.d.ts +58 -0
  48. package/dist/mdx.js +1712 -0
  49. package/dist/mdx.js.map +1 -0
  50. package/dist/mdx.mjs +1685 -0
  51. package/dist/mdx.mjs.map +1 -0
  52. package/dist/primitives.d.mts +73 -5
  53. package/dist/primitives.d.ts +73 -5
  54. package/dist/primitives.js +331 -8
  55. package/dist/primitives.js.map +1 -1
  56. package/dist/primitives.mjs +320 -11
  57. package/dist/primitives.mjs.map +1 -1
  58. package/dist/session.d.mts +18 -0
  59. package/dist/session.d.ts +18 -0
  60. package/dist/session.js +432 -0
  61. package/dist/session.js.map +1 -0
  62. package/dist/session.mjs +401 -0
  63. package/dist/session.mjs.map +1 -0
  64. package/dist/status-badge-BEOxeY9j.d.ts +13 -0
  65. package/dist/status-badge-DRwGhB0h.d.mts +13 -0
  66. package/dist/styles/code.css +97 -0
  67. package/dist/styles/fonts.css +1 -1
  68. package/dist/styles/theme.css +2 -0
  69. package/dist/styles/tokens.css +44 -2
  70. package/dist/styles.css +1 -0
  71. package/dist/tokens.d.mts +3 -1
  72. package/dist/tokens.d.ts +3 -1
  73. package/dist/tokens.js +5 -3
  74. package/dist/tokens.js.map +1 -1
  75. package/dist/tokens.mjs +5 -3
  76. package/dist/tokens.mjs.map +1 -1
  77. package/dist/tool-shell-B1C7ahKE.d.ts +81 -0
  78. package/dist/tool-shell-BDx_N5ai.d.mts +81 -0
  79. package/dist/tools-BggNN5DV.d.ts +131 -0
  80. package/dist/tools-DFIxIj5p.d.mts +131 -0
  81. package/package.json +38 -2
@@ -1,12 +1,20 @@
1
- import { forwardRef, createContext, createElement, useRef, useState, useEffect, useContext, Children, isValidElement, cloneElement, useCallback, Component } from 'react';
1
+ import { forwardRef, createContext, useContext, useState, useEffect, createElement, useRef, Children, isValidElement, cloneElement, useCallback, useMemo, Component, useId, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
2
2
  import { clsx } from 'clsx';
3
3
  import { extendTailwindMerge } from 'tailwind-merge';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { cva } from 'class-variance-authority';
6
- import { Check, Copy } from 'lucide-react';
6
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
7
+ import { ChevronDown, Check, Search, Copy, ArrowUpRight, ChevronRight, ArrowRight, CornerDownLeft, Download, FileText, Upload, ArrowLeft, Lock, CircleDashed, CircleMinus, Clock, CircleX, CircleCheck } from 'lucide-react';
7
8
  import { Slot } from '@radix-ui/react-slot';
8
9
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
9
10
  import 'sonner';
11
+ import Link from 'next/link';
12
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
13
+ import * as LabelPrimitive from '@radix-ui/react-label';
14
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
15
+ import * as SelectPrimitive from '@radix-ui/react-select';
16
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
17
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
10
18
 
11
19
  var merge = extendTailwindMerge({
12
20
  extend: {
@@ -270,6 +278,7 @@ function useActiveHeading(ids) {
270
278
  const [active, setActive] = useState(ids[0]);
271
279
  const key = ids.join("|");
272
280
  useEffect(() => {
281
+ setActive(key.split("|")[0] || void 0);
273
282
  const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
274
283
  if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
275
284
  const io = new IntersectionObserver(
@@ -343,13 +352,13 @@ var badgeVariants = cva(
343
352
  tone: {
344
353
  neutral: "border-border bg-card text-foreground",
345
354
  muted: "border-transparent bg-muted text-muted-foreground",
346
- brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_12%,var(--card))] text-oca-accent-ink",
355
+ brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
347
356
  danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
348
357
  // A good state is a neutral pill with a green dot, not a green pill.
349
358
  success: GOOD_DOT,
350
359
  // Aliases kept so older call sites keep compiling: attention is
351
360
  // the brand accent, information is neutral.
352
- warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_12%,var(--card))] text-oca-accent-ink",
361
+ warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
353
362
  info: "border-border bg-card text-foreground",
354
363
  // Inverted in dark mode, where ink would sit on a card of nearly its own colour.
355
364
  ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
@@ -419,6 +428,487 @@ function StepGrid({ items, look = "cards", className }) {
419
428
  ] }) }, i)
420
429
  ) });
421
430
  }
431
+ var KIND = {
432
+ package: "text-oca-code-package",
433
+ tag: "text-oca-code-tag",
434
+ link: "text-oca-code-link"
435
+ };
436
+ function PackageCard({ items, className }) {
437
+ return /* @__PURE__ */ jsx(
438
+ "div",
439
+ {
440
+ className: cn(
441
+ "grid gap-x-10 gap-y-7 rounded-[1.25rem] border border-oca-ink-line bg-oca-ink-card p-6 text-oca-ink-foreground md:grid-cols-2 md:p-9",
442
+ className
443
+ ),
444
+ children: items.map((it, i) => {
445
+ const code = /* @__PURE__ */ jsx("span", { className: cn("text-[0.9375rem]", KIND[it.kind ?? "package"]), children: it.code });
446
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
447
+ /* @__PURE__ */ jsx("h3", { className: "text-[1.125rem] font-semibold tracking-[-0.01em] text-oca-ink-title", children: it.title }),
448
+ it.href ? /* @__PURE__ */ jsx("a", { href: it.href, className: "w-fit underline decoration-transparent underline-offset-4 hover:decoration-current", children: code }) : code,
449
+ it.note ? /* @__PURE__ */ jsxs("p", { className: "text-[0.9375rem] leading-relaxed text-oca-ink-subtle", children: [
450
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "// " }),
451
+ it.note
452
+ ] }) : null
453
+ ] }, i);
454
+ })
455
+ }
456
+ );
457
+ }
458
+
459
+ // src/code/highlight.ts
460
+ var TOKEN_CLASS = {
461
+ keyword: "oca-k",
462
+ string: "oca-s",
463
+ number: "oca-n",
464
+ function: "oca-f",
465
+ type: "oca-y",
466
+ property: "oca-p",
467
+ comment: "oca-c",
468
+ tag: "oca-g",
469
+ url: "oca-u"
470
+ };
471
+ var ALIASES = {
472
+ ts: "js",
473
+ typescript: "js",
474
+ tsx: "js",
475
+ js: "js",
476
+ javascript: "js",
477
+ jsx: "js",
478
+ mjs: "js",
479
+ cjs: "js",
480
+ json: "json",
481
+ jsonc: "json",
482
+ json5: "json",
483
+ bash: "shell",
484
+ sh: "shell",
485
+ shell: "shell",
486
+ zsh: "shell",
487
+ console: "shell",
488
+ terminal: "shell",
489
+ py: "python",
490
+ python: "python",
491
+ yaml: "yaml",
492
+ yml: "yaml",
493
+ diff: "diff"
494
+ };
495
+ function grammarOf(lang) {
496
+ return lang && ALIASES[lang.toLowerCase()] || "plain";
497
+ }
498
+ function collector() {
499
+ const tokens = [];
500
+ const emit = (text, kind) => {
501
+ if (!text) return;
502
+ const last = tokens[tokens.length - 1];
503
+ if (last && last.kind === kind) last.text += text;
504
+ else tokens.push(kind ? { text, kind } : { text });
505
+ };
506
+ return { emit, tokens };
507
+ }
508
+ function at(re, src, i) {
509
+ re.lastIndex = i;
510
+ const m = re.exec(src);
511
+ return m ? m[0] : null;
512
+ }
513
+ var WS = /[ \t]+/y;
514
+ var NEWLINE = /\r?\n/y;
515
+ var JS_KEYWORDS = new Set(
516
+ "abstract as async await break case catch class const continue debugger declare default delete do else enum export extends finally for from function get if implements import in infer instanceof interface is keyof let module namespace new of override private protected public readonly return satisfies set static super switch this throw try type typeof unique var void while with yield".split(" ")
517
+ );
518
+ var JS_CONSTANTS = /* @__PURE__ */ new Set(["true", "false", "null", "undefined", "NaN", "Infinity"]);
519
+ var TS_PRIMITIVES = /* @__PURE__ */ new Set(["string", "number", "boolean", "bigint", "symbol", "object", "unknown", "any", "never"]);
520
+ var isConstant = (m) => /^[A-Z][A-Z\d_]+$/.test(m) && (m.includes("_") || m.length > 4);
521
+ var JS_LINE_COMMENT = /\/\/[^\n]*/y;
522
+ var JS_BLOCK_COMMENT = /\/\*[\s\S]*?(?:\*\/|$)/y;
523
+ var JS_TEMPLATE = /`(?:\\[\s\S]|[^\\`])*`?/y;
524
+ var JS_STRING = /'(?:\\.|[^\\'\n])*'?|"(?:\\.|[^\\"\n])*"?/y;
525
+ var JS_NUMBER = /(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?\d+)?|\.\d[\d_]*(?:[eE][+-]?\d+)?)n?/y;
526
+ var JS_IDENT = /[A-Za-z_$][\w$]*/y;
527
+ var JS_DECORATOR = /@[A-Za-z_$][\w$.]*/y;
528
+ var JS_CALL_AFTER = /\s*(?:<[\w$\s,.[\]|&'"]*>)?\s*\(/y;
529
+ var JS_TAG = /<\/?(?=[A-Za-z])/y;
530
+ var JS_TAG_NAME = /[A-Za-z][\w$.:-]*/y;
531
+ var JS_PUNCT = /=>|\.\.\.|[{}()[\];,.<>=+\-*/%!?:&|^~#]/y;
532
+ var JSX_BEFORE = /* @__PURE__ */ new Set(["(", ",", "=", "?", ":", "{", "[", ";", ">", "&&", "||", "=>", "return"]);
533
+ function scanJs(src, emit, jsx35) {
534
+ let i = 0;
535
+ let prev = "";
536
+ let tagDepth = 0;
537
+ let braceInTag = 0;
538
+ const sig = (t) => {
539
+ prev = t;
540
+ };
541
+ while (i < src.length) {
542
+ let m;
543
+ if ((m = at(WS, src, i)) || (m = at(NEWLINE, src, i))) {
544
+ emit(m);
545
+ i += m.length;
546
+ continue;
547
+ }
548
+ if ((m = at(JS_LINE_COMMENT, src, i)) || (m = at(JS_BLOCK_COMMENT, src, i))) {
549
+ emit(m, "comment");
550
+ i += m.length;
551
+ continue;
552
+ }
553
+ if ((m = at(JS_TEMPLATE, src, i)) || (m = at(JS_STRING, src, i))) {
554
+ emit(m, "string");
555
+ i += m.length;
556
+ sig('"');
557
+ continue;
558
+ }
559
+ if (jsx35 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
560
+ const name = at(JS_TAG_NAME, src, i + m.length);
561
+ if (name) {
562
+ emit(m);
563
+ emit(name, "tag");
564
+ i += m.length + name.length;
565
+ tagDepth = 1;
566
+ braceInTag = 0;
567
+ sig("tag");
568
+ continue;
569
+ }
570
+ }
571
+ if (jsx35 && tagDepth > 0 && braceInTag === 0) {
572
+ if (src.startsWith("/>", i) || src[i] === ">") {
573
+ const close = src[i] === ">" ? ">" : "/>";
574
+ emit(close);
575
+ i += close.length;
576
+ tagDepth = 0;
577
+ sig(">");
578
+ continue;
579
+ }
580
+ if ((m = at(JS_IDENT, src, i)) && /^\s*=/.test(src.slice(i + m.length, i + m.length + 4))) {
581
+ emit(m, "property");
582
+ i += m.length;
583
+ continue;
584
+ }
585
+ if (m = at(JS_IDENT, src, i)) {
586
+ emit(m, "property");
587
+ i += m.length;
588
+ continue;
589
+ }
590
+ if (src[i] === "{") braceInTag = 1;
591
+ } else if (jsx35 && tagDepth > 0 && braceInTag > 0) {
592
+ if (src[i] === "{") braceInTag++;
593
+ else if (src[i] === "}") braceInTag--;
594
+ }
595
+ if (m = at(JS_DECORATOR, src, i)) {
596
+ emit(m, "function");
597
+ i += m.length;
598
+ sig("@");
599
+ continue;
600
+ }
601
+ if (m = at(JS_IDENT, src, i)) {
602
+ const end = i + m.length;
603
+ let kind;
604
+ if (prev !== "." && JS_CONSTANTS.has(m)) kind = "number";
605
+ else if (prev !== "." && JS_KEYWORDS.has(m)) kind = "keyword";
606
+ else if (at(JS_CALL_AFTER, src, end) !== null) kind = "function";
607
+ else if (prev !== "." && TS_PRIMITIVES.has(m)) kind = "type";
608
+ else if (isConstant(m)) kind = "number";
609
+ else if (/^[A-Z]/.test(m)) kind = "type";
610
+ emit(m, kind);
611
+ i = end;
612
+ sig(kind === "keyword" ? m : "id");
613
+ continue;
614
+ }
615
+ if (m = at(JS_NUMBER, src, i)) {
616
+ emit(m, "number");
617
+ i += m.length;
618
+ sig("0");
619
+ continue;
620
+ }
621
+ if (m = at(JS_PUNCT, src, i)) {
622
+ emit(m);
623
+ i += m.length;
624
+ sig(m === "." ? "." : m);
625
+ continue;
626
+ }
627
+ emit(src[i]);
628
+ i++;
629
+ }
630
+ }
631
+ var JSON_STRING = /"(?:\\.|[^\\"\n])*"?/y;
632
+ var JSON_KEY_AFTER = /\s*:/y;
633
+ var JSON_NUMBER = /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y;
634
+ var JSON_WORD = /true|false|null/y;
635
+ function scanJson(src, emit) {
636
+ let i = 0;
637
+ while (i < src.length) {
638
+ let m;
639
+ if ((m = at(JS_LINE_COMMENT, src, i)) || (m = at(JS_BLOCK_COMMENT, src, i))) {
640
+ emit(m, "comment");
641
+ } else if (m = at(JSON_STRING, src, i)) {
642
+ emit(m, at(JSON_KEY_AFTER, src, i + m.length) !== null ? "property" : "string");
643
+ } else if ((m = at(JSON_NUMBER, src, i)) || (m = at(JSON_WORD, src, i))) {
644
+ emit(m, "number");
645
+ } else {
646
+ m = src[i];
647
+ emit(m);
648
+ }
649
+ i += m.length;
650
+ }
651
+ }
652
+ var SH_KEYWORDS = new Set(
653
+ "if then else elif fi for in do done case esac while until function return export local select time".split(" ")
654
+ );
655
+ var SH_PROMPT = /\$ (?=\S)/y;
656
+ var SH_COMMENT = /#[^\n]*/y;
657
+ var SH_SINGLE = /'[^']*'?/y;
658
+ var SH_DOUBLE = /"(?:\\.|[^\\"])*"?/y;
659
+ var SH_VAR = /\$(?:\{[^}\n]*\}?|[A-Za-z_][\w]*|[@*#?$!\d])/y;
660
+ var SH_URL = /https?:\/\/[^\s'"`)]+/y;
661
+ var SH_FLAG = /--?[A-Za-z][\w-]*/y;
662
+ var SH_ASSIGN = /[A-Za-z_][\w]*(?==)/y;
663
+ var SH_VALUE = /=[^\s|&;()<>'"`$]*/y;
664
+ var SH_WORD = /[^\s|&;()<>'"`$#]+/y;
665
+ var SH_OPERATOR = /\|\||&&|[|;&]|\$\(|[()<>]/y;
666
+ function scanShell(src, emit) {
667
+ let i = 0;
668
+ let command = true;
669
+ let lineStart = true;
670
+ while (i < src.length) {
671
+ let m;
672
+ if (m = at(NEWLINE, src, i)) {
673
+ emit(m);
674
+ i += m.length;
675
+ command = !/\\\s*$/.test(src.slice(0, i - m.length));
676
+ lineStart = true;
677
+ continue;
678
+ }
679
+ if (m = at(WS, src, i)) {
680
+ emit(m);
681
+ i += m.length;
682
+ continue;
683
+ }
684
+ if (lineStart && (m = at(SH_PROMPT, src, i))) {
685
+ emit(m, "comment");
686
+ i += m.length;
687
+ lineStart = false;
688
+ continue;
689
+ }
690
+ lineStart = false;
691
+ if ((m = at(SH_COMMENT, src, i)) && (i === 0 || /\s/.test(src[i - 1]))) {
692
+ emit(m, "comment");
693
+ i += m.length;
694
+ continue;
695
+ }
696
+ if ((m = at(SH_SINGLE, src, i)) || (m = at(SH_DOUBLE, src, i))) {
697
+ emit(m, "string");
698
+ i += m.length;
699
+ command = false;
700
+ continue;
701
+ }
702
+ if (m = at(SH_OPERATOR, src, i)) {
703
+ emit(m);
704
+ i += m.length;
705
+ command = m !== ")" && m !== ">" && m !== "<";
706
+ continue;
707
+ }
708
+ if (m = at(SH_VAR, src, i)) {
709
+ emit(m, "type");
710
+ i += m.length;
711
+ command = false;
712
+ continue;
713
+ }
714
+ if (m = at(SH_URL, src, i)) {
715
+ emit(m, "url");
716
+ i += m.length;
717
+ command = false;
718
+ continue;
719
+ }
720
+ if (command && (m = at(SH_ASSIGN, src, i))) {
721
+ emit(m, "property");
722
+ i += m.length;
723
+ const v = at(SH_VALUE, src, i);
724
+ emit(v);
725
+ i += v.length;
726
+ continue;
727
+ }
728
+ if ((m = at(SH_FLAG, src, i)) && !command) {
729
+ emit(m, "keyword");
730
+ i += m.length;
731
+ continue;
732
+ }
733
+ if (m = at(SH_WORD, src, i)) {
734
+ if (command && SH_KEYWORDS.has(m)) emit(m, "keyword");
735
+ else if (command) {
736
+ emit(m, "function");
737
+ command = m === "sudo" || m === "npx" || m === "env" || m === "time";
738
+ i += m.length;
739
+ continue;
740
+ } else emit(m);
741
+ i += m.length;
742
+ continue;
743
+ }
744
+ emit(src[i]);
745
+ i++;
746
+ }
747
+ }
748
+ var PY_KEYWORDS = new Set(
749
+ "and as assert async await break class continue def del elif else except finally for from global if import in is lambda match case nonlocal not or pass raise return try while with yield self cls".split(" ")
750
+ );
751
+ var PY_CONSTANTS = /* @__PURE__ */ new Set(["True", "False", "None"]);
752
+ var PY_TYPES = /* @__PURE__ */ new Set(["int", "str", "bool", "float", "bytes", "list", "dict", "tuple", "set", "object"]);
753
+ var PY_COMMENT = /#[^\n]*/y;
754
+ var PY_TRIPLE = /[rRbBuUfF]{0,2}(?:"""[\s\S]*?(?:"""|$)|'''[\s\S]*?(?:'''|$))/y;
755
+ var PY_STRING = /[rRbBuUfF]{0,2}(?:'(?:\\.|[^\\'\n])*'?|"(?:\\.|[^\\"\n])*"?)/y;
756
+ var PY_NUMBER = /(?:0[xX][\da-fA-F_]+|\d[\d_]*(?:\.[\d_]*)?(?:[eE][+-]?\d+)?j?)/y;
757
+ var PY_IDENT = /[A-Za-z_]\w*/y;
758
+ var PY_DECORATOR = /@[A-Za-z_][\w.]*/y;
759
+ var PY_CALL_AFTER = /\s*\(/y;
760
+ function scanPython(src, emit) {
761
+ let i = 0;
762
+ let prev = "";
763
+ while (i < src.length) {
764
+ let m;
765
+ if ((m = at(WS, src, i)) || (m = at(NEWLINE, src, i))) {
766
+ emit(m);
767
+ i += m.length;
768
+ continue;
769
+ }
770
+ if (m = at(PY_COMMENT, src, i)) {
771
+ emit(m, "comment");
772
+ } else if ((m = at(PY_TRIPLE, src, i)) || (m = at(PY_STRING, src, i))) {
773
+ if (/^[A-Za-z]+$/.test(m)) {
774
+ emit(m);
775
+ } else emit(m, "string");
776
+ prev = '"';
777
+ } else if (m = at(PY_DECORATOR, src, i)) {
778
+ emit(m, "function");
779
+ prev = "@";
780
+ } else if (m = at(PY_IDENT, src, i)) {
781
+ let kind;
782
+ if (PY_CONSTANTS.has(m)) kind = "number";
783
+ else if (prev !== "." && PY_KEYWORDS.has(m)) kind = "keyword";
784
+ else if (prev === "def" || at(PY_CALL_AFTER, src, i + m.length) !== null) kind = "function";
785
+ else if (prev === "class" || /^[A-Z][a-z]/.test(m) || PY_TYPES.has(m)) kind = "type";
786
+ else if (isConstant(m)) kind = "number";
787
+ emit(m, kind);
788
+ prev = kind === "keyword" ? m : "id";
789
+ } else if (m = at(PY_NUMBER, src, i)) {
790
+ emit(m, "number");
791
+ prev = "0";
792
+ } else {
793
+ m = src[i];
794
+ emit(m);
795
+ prev = m;
796
+ }
797
+ i += m.length;
798
+ }
799
+ }
800
+ var YAML_KEY = /[ \t]*(?:- )?[\w.$/-]+(?=[ \t]*:(?:\s|$))/y;
801
+ var YAML_VALUE_WORD = /(?:true|false|null|yes|no|~|-?\d+(?:\.\d+)?)(?=\s*(?:#|$))/y;
802
+ function scanYaml(src, emit) {
803
+ let i = 0;
804
+ let lineStart = true;
805
+ while (i < src.length) {
806
+ let m;
807
+ if (m = at(NEWLINE, src, i)) {
808
+ emit(m);
809
+ i += m.length;
810
+ lineStart = true;
811
+ continue;
812
+ }
813
+ if (lineStart && (m = at(YAML_KEY, src, i))) {
814
+ const dash = m.match(/^([ \t]*(?:- )?)/)[1];
815
+ emit(dash);
816
+ emit(m.slice(dash.length), "property");
817
+ i += m.length;
818
+ lineStart = false;
819
+ continue;
820
+ }
821
+ lineStart = false;
822
+ if ((m = at(SH_COMMENT, src, i)) && (i === 0 || /\s/.test(src[i - 1]))) emit(m, "comment");
823
+ else if ((m = at(SH_SINGLE, src, i)) || (m = at(JSON_STRING, src, i))) emit(m, "string");
824
+ else if (m = at(YAML_VALUE_WORD, src, i)) emit(m, "number");
825
+ else if (m = at(SH_URL, src, i)) emit(m, "url");
826
+ else {
827
+ m = src[i];
828
+ emit(m);
829
+ }
830
+ i += m.length;
831
+ }
832
+ }
833
+ function toLines(tokens) {
834
+ const lines = [[]];
835
+ for (const t of tokens) {
836
+ const parts = t.text.split(/\r?\n/);
837
+ parts.forEach((part, j) => {
838
+ if (j > 0) lines.push([]);
839
+ if (part) lines[lines.length - 1].push(t.kind ? { text: part, kind: t.kind } : { text: part });
840
+ });
841
+ }
842
+ return lines;
843
+ }
844
+ function highlight(code, lang) {
845
+ const src = code.replace(/\r?\n$/, "");
846
+ const grammar = grammarOf(lang);
847
+ const { emit, tokens } = collector();
848
+ const name = (lang ?? "").toLowerCase();
849
+ switch (grammar) {
850
+ case "js":
851
+ scanJs(src, emit, name === "tsx" || name === "jsx");
852
+ break;
853
+ case "json":
854
+ scanJson(src, emit);
855
+ break;
856
+ case "shell":
857
+ scanShell(src, emit);
858
+ break;
859
+ case "python":
860
+ scanPython(src, emit);
861
+ break;
862
+ case "yaml":
863
+ scanYaml(src, emit);
864
+ break;
865
+ default:
866
+ emit(src);
867
+ }
868
+ return toLines(tokens);
869
+ }
870
+ function readDiff(code) {
871
+ const diff = /* @__PURE__ */ new Map();
872
+ const lines = code.replace(/\r?\n$/, "").split(/\r?\n/);
873
+ const out = lines.map((line, i) => {
874
+ const c = line[0];
875
+ if (c === "+" || c === "-") {
876
+ diff.set(i + 1, c === "+" ? "add" : "remove");
877
+ return line.slice(1);
878
+ }
879
+ return c === " " ? line.slice(1) : line;
880
+ });
881
+ return { code: out.join("\n"), diff };
882
+ }
883
+ function parseLineRanges(spec) {
884
+ if (!spec) return /* @__PURE__ */ new Set();
885
+ if (typeof spec !== "string") return new Set(spec);
886
+ const out = /* @__PURE__ */ new Set();
887
+ for (const part of spec.split(",")) {
888
+ const m = part.trim().match(/^(\d+)(?:\s*-\s*(\d+))?$/);
889
+ if (!m) continue;
890
+ const a = Number(m[1]);
891
+ const b = m[2] ? Number(m[2]) : a;
892
+ for (let n = Math.min(a, b); n <= Math.max(a, b) && n - a < 1e4; n++) out.add(n);
893
+ }
894
+ return out;
895
+ }
896
+ var ESCAPE = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" };
897
+ function escapeHtml(s) {
898
+ return s.replace(/[&<>"]/g, (c) => ESCAPE[c]);
899
+ }
900
+ function linesToHtml(lines, marks = {}) {
901
+ return lines.map((line, i) => {
902
+ const n = i + 1;
903
+ const attrs = [
904
+ 'data-line=""',
905
+ marks.highlight?.has(n) ? 'data-mark=""' : "",
906
+ marks.diff?.has(n) ? `data-diff="${marks.diff.get(n)}"` : ""
907
+ ].filter(Boolean).join(" ");
908
+ const body = line.map((t) => t.kind ? `<span class="${TOKEN_CLASS[t.kind]}">${escapeHtml(t.text)}</span>` : escapeHtml(t.text)).join("");
909
+ return `<span ${attrs}>${body}</span>`;
910
+ }).join("\n");
911
+ }
422
912
  function ScrollFade({ fade = "var(--card)", className, innerClassName, children, ...props }) {
423
913
  const ref = useRef(null);
424
914
  const [edges, setEdges] = useState({ left: false, right: false });
@@ -477,7 +967,73 @@ function ScrollFade({ fade = "var(--card)", className, innerClassName, children,
477
967
  )
478
968
  ] });
479
969
  }
480
- var ShellContext = createContext({});
970
+
971
+ // src/format/index.ts
972
+ var EXPLORER = "https://mempool.space";
973
+ function explorerUrl(kind, value, network = "mainnet") {
974
+ const net = network === "mainnet" ? "" : `/${network}`;
975
+ return `${EXPLORER}${net}/${kind}/${encodeURIComponent(String(value))}`;
976
+ }
977
+ function shortenMiddle(value, head = 8, tail = 6) {
978
+ return value.length <= head + tail + 1 ? value : `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
979
+ }
980
+ function formatBlockHeight(height) {
981
+ return Math.trunc(height).toLocaleString("en-US");
982
+ }
983
+ function blocksToDuration(blocks, minutesPerBlock = 10) {
984
+ const minutes = Math.max(0, Math.round(blocks * minutesPerBlock));
985
+ if (minutes < 60) return `about ${minutes} minute${minutes === 1 ? "" : "s"}`;
986
+ const units = [
987
+ [60 * 24 * 7, "week"],
988
+ [60 * 24, "day"],
989
+ [60, "hour"],
990
+ [1, "minute"]
991
+ ];
992
+ const parts = [];
993
+ let rest = minutes;
994
+ for (const [size, word] of units) {
995
+ const n = Math.floor(rest / size);
996
+ if (n > 0 && parts.length < 2) {
997
+ parts.push(`${n} ${word}${n === 1 ? "" : "s"}`);
998
+ rest -= n * size;
999
+ } else if (parts.length > 0) break;
1000
+ }
1001
+ return `about ${parts.join(" ")}`;
1002
+ }
1003
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
1004
+ function formatUtc(at2, opts = {}) {
1005
+ const d = typeof at2 === "number" ? new Date(at2 * 1e3) : new Date(at2);
1006
+ if (Number.isNaN(d.getTime())) return "\u2014";
1007
+ const day = `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
1008
+ if (opts.date) return day;
1009
+ const hh = String(d.getUTCHours()).padStart(2, "0");
1010
+ const mm = String(d.getUTCMinutes()).padStart(2, "0");
1011
+ return `${day}, ${hh}:${mm} UTC`;
1012
+ }
1013
+ function formatBytes(bytes) {
1014
+ if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
1015
+ if (bytes < 1024) return `${bytes} B`;
1016
+ const units = ["KB", "MB", "GB", "TB"];
1017
+ let v = bytes / 1024;
1018
+ let u = 0;
1019
+ while (v >= 1024 && u < units.length - 1) {
1020
+ v /= 1024;
1021
+ u++;
1022
+ }
1023
+ return `${v < 10 ? v.toFixed(1).replace(/\.0$/, "") : Math.round(v)} ${units[u]}`;
1024
+ }
1025
+ function sharedContext(name, initial) {
1026
+ const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
1027
+ const store = globalThis;
1028
+ return store[key] ?? (store[key] = createContext(initial));
1029
+ }
1030
+
1031
+ // src/lib/density.ts
1032
+ var DensityContext = sharedContext("density", "comfortable");
1033
+ function useDensity() {
1034
+ return useContext(DensityContext);
1035
+ }
1036
+ var ShellContext = sharedContext("shell-place", {});
481
1037
  function useShellPlace() {
482
1038
  return useContext(ShellContext);
483
1039
  }
@@ -532,6 +1088,18 @@ forwardRef(function Separator2({ className, orientation = "horizontal", decorati
532
1088
  }
533
1089
  );
534
1090
  });
1091
+ function Kbd({ className, ...props }) {
1092
+ return /* @__PURE__ */ jsx(
1093
+ "kbd",
1094
+ {
1095
+ className: cn(
1096
+ "inline-flex h-5 min-w-5 items-center justify-center rounded-md border border-border bg-card px-1.5 font-mono text-[11px] text-muted-foreground",
1097
+ className
1098
+ ),
1099
+ ...props
1100
+ }
1101
+ );
1102
+ }
535
1103
  var buttonVariants = cva(
536
1104
  [
537
1105
  "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
@@ -605,26 +1173,30 @@ function PageHeader({
605
1173
  ] });
606
1174
  }
607
1175
  var InStatGrid = createContext(false);
608
- function StatCard({ label, value, hint, className }) {
1176
+ function StatCard({ label, value, hint, size, className }) {
609
1177
  const inGrid = useContext(InStatGrid);
1178
+ const density = useDensity();
1179
+ const sm = (size ?? (density === "compact" ? "sm" : "md")) === "sm";
610
1180
  return /* @__PURE__ */ jsxs(
611
1181
  "div",
612
1182
  {
613
1183
  "data-ui": "stat",
614
1184
  className: cn(
615
- "rounded-[1.25rem] border border-border bg-card p-5 md:p-6",
1185
+ "border border-border bg-card",
1186
+ sm ? "rounded-2xl p-4" : "rounded-[1.25rem] p-5 md:p-6",
616
1187
  // In a grid, label, value and hint each share a row with their
617
1188
  // neighbours, so values line up whatever wraps above them.
618
1189
  inGrid ? "row-span-3 grid grid-rows-subgrid gap-1.5" : "flex flex-col gap-2",
619
1190
  className
620
1191
  ),
621
1192
  children: [
622
- /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: label }),
1193
+ /* @__PURE__ */ jsx("span", { className: cn("leading-snug text-muted-foreground", sm ? "text-[0.8125rem]" : "text-[0.875rem]"), children: label }),
623
1194
  /* @__PURE__ */ jsx(
624
1195
  "span",
625
1196
  {
626
1197
  className: cn(
627
- "break-words oca-tabular text-[1.5rem] leading-tight tracking-[-0.02em] md:text-[1.75rem]",
1198
+ "break-words oca-tabular leading-tight tracking-[-0.02em]",
1199
+ sm ? "text-[1.25rem]" : "text-[1.5rem] md:text-[1.75rem]",
628
1200
  inGrid && "self-end"
629
1201
  ),
630
1202
  children: value
@@ -686,6 +1258,7 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
686
1258
  const items = Children.toArray(children).filter(isValidElement);
687
1259
  const n = items.length;
688
1260
  const allZero = n > 0 && items.every((el) => "raw" in el.props && (el.props.raw === 0 || el.props.raw === null));
1261
+ const compact = useDensity() === "compact";
689
1262
  if (isEmpty ?? allZero) return /* @__PURE__ */ jsx(EmptyLine, { className, children: empty ?? "Nothing here yet." });
690
1263
  const lg = columns ?? statColumns(n);
691
1264
  const md = lg > 4 ? 3 : lg;
@@ -695,7 +1268,8 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
695
1268
  "div",
696
1269
  {
697
1270
  className: cn(
698
- "grid gap-3 md:gap-4",
1271
+ "grid",
1272
+ compact ? "gap-2.5 md:gap-3" : "gap-3 md:gap-4",
699
1273
  n === 1 ? "grid-cols-1" : "grid-cols-2",
700
1274
  MD_COLS[md],
701
1275
  LG_COLS[lg],
@@ -714,11 +1288,40 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
714
1288
  }
715
1289
  ) });
716
1290
  }
717
- function KeyValueList({ items, className }) {
718
- return /* @__PURE__ */ jsx("dl", { className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: items.map((it, i) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 px-5 py-3.5 sm:flex-row sm:items-baseline sm:gap-6", children: [
719
- /* @__PURE__ */ jsx("dt", { className: "shrink-0 text-[0.875rem] text-muted-foreground sm:w-48", children: it.label }),
720
- /* @__PURE__ */ jsx("dd", { className: cn("min-w-0 break-words text-[0.9375rem]", it.mono && "font-mono text-[0.875rem]"), children: it.value })
721
- ] }, i)) });
1291
+ function KeyValueList({
1292
+ items,
1293
+ dense,
1294
+ className
1295
+ }) {
1296
+ const density = useDensity();
1297
+ const tight = dense ?? density === "compact";
1298
+ return (
1299
+ // The rows go side by side when the list itself is wide enough, wherever it sits: a narrow card stacks them.
1300
+ /* @__PURE__ */ jsx("dl", { className: cn("@container divide-y divide-border border border-border bg-card", tight ? "rounded-2xl" : "rounded-[1.25rem]", className), children: items.map((it, i) => /* @__PURE__ */ jsxs(
1301
+ "div",
1302
+ {
1303
+ className: cn(
1304
+ "flex flex-col gap-1 @md:flex-row @md:items-baseline",
1305
+ tight ? "px-4 py-2.5 @md:gap-5" : "px-5 py-3.5 @md:gap-6"
1306
+ ),
1307
+ children: [
1308
+ /* @__PURE__ */ jsx("dt", { className: cn("shrink-0 text-muted-foreground", tight ? "text-[0.8125rem] @md:w-36" : "text-[0.875rem] @md:w-48"), children: it.label }),
1309
+ /* @__PURE__ */ jsx(
1310
+ "dd",
1311
+ {
1312
+ className: cn(
1313
+ "min-w-0 break-words",
1314
+ tight ? "text-[0.875rem]" : "text-[0.9375rem]",
1315
+ it.mono && (tight ? "font-mono text-[0.8125rem]" : "font-mono text-[0.875rem]")
1316
+ ),
1317
+ children: it.value
1318
+ }
1319
+ )
1320
+ ]
1321
+ },
1322
+ i
1323
+ )) })
1324
+ );
722
1325
  }
723
1326
  function DataTable({
724
1327
  columns,
@@ -727,8 +1330,11 @@ function DataTable({
727
1330
  empty,
728
1331
  caption,
729
1332
  phone = "cards",
1333
+ dense,
730
1334
  className
731
1335
  }) {
1336
+ const density = useDensity();
1337
+ const tight = dense ?? density === "compact";
732
1338
  if (rows.length === 0 && empty) return /* @__PURE__ */ jsx(Fragment, { children: empty });
733
1339
  const primary = columns.find((c) => c.primary) ?? columns[0];
734
1340
  const right = (c) => c.numeric || c.align === "end";
@@ -736,11 +1342,12 @@ function DataTable({
736
1342
  "div",
737
1343
  {
738
1344
  className: cn(
739
- "overflow-hidden rounded-[1.25rem] border border-border bg-card",
1345
+ "overflow-hidden border border-border bg-card",
1346
+ tight ? "rounded-2xl" : "rounded-[1.25rem]",
740
1347
  phone === "cards" && "max-sm:hidden",
741
1348
  className
742
1349
  ),
743
- children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-left text-[0.9375rem]", children: [
1350
+ children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxs("table", { className: cn("w-full border-collapse text-left", tight ? "text-[0.875rem]" : "text-[0.9375rem]"), children: [
744
1351
  caption ? /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }) : null,
745
1352
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "border-b border-border", children: columns.map((c) => /* @__PURE__ */ jsx(
746
1353
  "th",
@@ -748,7 +1355,8 @@ function DataTable({
748
1355
  scope: "col",
749
1356
  style: { width: c.width, minWidth: c.minWidth },
750
1357
  className: cn(
751
- "whitespace-nowrap px-5 py-3 text-[0.8125rem] font-medium text-muted-foreground",
1358
+ "whitespace-nowrap text-[0.8125rem] font-medium text-muted-foreground",
1359
+ tight ? "px-4 py-2.5" : "px-5 py-3",
752
1360
  right(c) && "text-right",
753
1361
  c.wide && "hidden md:table-cell"
754
1362
  ),
@@ -761,7 +1369,8 @@ function DataTable({
761
1369
  {
762
1370
  style: { minWidth: c.minWidth },
763
1371
  className: cn(
764
- "px-5 py-3.5 align-middle",
1372
+ "align-middle",
1373
+ tight ? "px-4 py-2" : "px-5 py-3.5",
765
1374
  right(c) && "text-right",
766
1375
  c.numeric && "whitespace-nowrap oca-tabular",
767
1376
  c.wide && "hidden md:table-cell"
@@ -781,8 +1390,12 @@ function DataTable({
781
1390
  "ul",
782
1391
  {
783
1392
  "aria-label": caption,
784
- className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card sm:hidden", className),
785
- children: rows.map((r, i) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-2.5 px-4 py-4", children: [
1393
+ className: cn(
1394
+ "divide-y divide-border border border-border bg-card sm:hidden",
1395
+ tight ? "rounded-2xl" : "rounded-[1.25rem]",
1396
+ className
1397
+ ),
1398
+ children: rows.map((r, i) => /* @__PURE__ */ jsxs("li", { className: cn("flex flex-col gap-2.5 px-4", tight ? "py-3" : "py-4"), children: [
786
1399
  /* @__PURE__ */ jsx("div", { className: "min-w-0 break-words text-[0.9375rem] font-medium", children: primary?.cell(r) }),
787
1400
  rest.length > 0 ? /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-[minmax(5.5rem,auto)_minmax(0,1fr)] gap-x-4 gap-y-1.5 text-[0.875rem]", children: rest.map((c) => /* @__PURE__ */ jsxs("div", { className: "contents", children: [
788
1401
  /* @__PURE__ */ jsx("dt", { className: "text-muted-foreground", children: c.header }),
@@ -829,13 +1442,14 @@ function Notice({
829
1442
  title,
830
1443
  children,
831
1444
  action,
1445
+ role,
832
1446
  className
833
1447
  }) {
834
1448
  const kind = NOTICE_KIND[tone];
835
1449
  return /* @__PURE__ */ jsxs(
836
1450
  "div",
837
1451
  {
838
- role: tone === "danger" || tone === "warning" ? "alert" : "note",
1452
+ role: role ?? (tone === "danger" || tone === "warning" ? "alert" : "note"),
839
1453
  "data-tone": kind,
840
1454
  className: cn(
841
1455
  "flex flex-col gap-3 rounded-2xl border border-border bg-card px-5 py-4 sm:flex-row sm:items-start sm:justify-between",
@@ -885,45 +1499,66 @@ function LoadingBlock({
885
1499
  }
886
1500
  return /* @__PURE__ */ jsx("div", { role: "status", "aria-label": label, className: cn("flex flex-col gap-3", className), children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-16 rounded-2xl" }, i)) });
887
1501
  }
888
- function middle(v, head, tail) {
889
- return v.length <= head + tail + 1 ? v : `${v.slice(0, head)}\u2026${v.slice(-tail)}`;
1502
+ async function wipeIfUnchanged(expected) {
1503
+ try {
1504
+ if (await navigator.clipboard.readText() !== expected) return;
1505
+ } catch {
1506
+ }
1507
+ try {
1508
+ await navigator.clipboard.writeText("");
1509
+ } catch {
1510
+ }
890
1511
  }
891
1512
  function useCopy(timeoutMs = 1600) {
892
1513
  const [copied, setCopied] = useState(false);
893
1514
  const t = useRef(null);
894
- useEffect(() => () => {
895
- if (t.current) clearTimeout(t.current);
896
- }, []);
1515
+ const wipe = useRef(null);
1516
+ useEffect(
1517
+ () => () => {
1518
+ if (t.current) clearTimeout(t.current);
1519
+ },
1520
+ []
1521
+ );
897
1522
  const copy = useCallback(
898
- async (text) => {
1523
+ async (text, opts = {}) => {
899
1524
  try {
900
1525
  await navigator.clipboard.writeText(text);
901
1526
  setCopied(true);
902
1527
  if (t.current) clearTimeout(t.current);
903
1528
  t.current = setTimeout(() => setCopied(false), timeoutMs);
1529
+ if (opts.clearAfter && opts.clearAfter > 0) {
1530
+ if (wipe.current) clearTimeout(wipe.current);
1531
+ wipe.current = setTimeout(() => void wipeIfUnchanged(text), opts.clearAfter);
1532
+ }
1533
+ return true;
904
1534
  } catch {
905
1535
  setCopied(false);
1536
+ return false;
906
1537
  }
907
1538
  },
908
1539
  [timeoutMs]
909
1540
  );
910
1541
  return { copied, copy };
911
1542
  }
912
- function CopyButton({ value, label = "Copy", className }) {
1543
+ function CopyButton({ value, label = "Copy", clearAfter, onCopied, className }) {
913
1544
  const { copied, copy } = useCopy();
1545
+ const done = copied ? clearAfter ? `Copied. Cleared in ${Math.round(clearAfter / 1e3)} seconds` : "Copied" : "";
914
1546
  return /* @__PURE__ */ jsxs(
915
1547
  "button",
916
1548
  {
917
1549
  type: "button",
918
- onClick: () => void copy(value),
1550
+ onClick: async () => {
1551
+ if (await copy(typeof value === "function" ? value() : value, { clearAfter })) onCopied?.();
1552
+ },
919
1553
  "aria-label": copied ? "Copied" : label,
1554
+ title: label,
920
1555
  className: cn(
921
1556
  "inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
922
1557
  className
923
1558
  ),
924
1559
  children: [
925
1560
  copied ? /* @__PURE__ */ jsx(Check, { className: "size-4 text-success" }) : /* @__PURE__ */ jsx(Copy, { className: "size-4" }),
926
- /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: copied ? "Copied" : "" })
1561
+ /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: done })
927
1562
  ]
928
1563
  }
929
1564
  );
@@ -934,12 +1569,27 @@ function HashChip({
934
1569
  tail = 6,
935
1570
  copy = true,
936
1571
  href,
1572
+ explorer,
1573
+ network = "mainnet",
937
1574
  className
938
1575
  }) {
939
- const shown = middle(value, head, tail);
1576
+ const shown = shortenMiddle(value, head, tail);
1577
+ const link = href ?? (explorer ? explorerUrl(explorer, value, network) : void 0);
1578
+ const offsite = !!link && /^https?:\/\//.test(link);
940
1579
  const text = /* @__PURE__ */ jsx("span", { title: value, className: "font-mono text-[0.875rem]", children: shown });
941
1580
  return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex max-w-full items-center gap-1", className), children: [
942
- href ? /* @__PURE__ */ jsx("a", { href, className: "underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground", children: text }) : text,
1581
+ link ? /* @__PURE__ */ jsxs(
1582
+ "a",
1583
+ {
1584
+ href: link,
1585
+ ...offsite ? { target: "_blank", rel: "noreferrer" } : {},
1586
+ className: "underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
1587
+ children: [
1588
+ text,
1589
+ offsite ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens in a new tab)" }) : null
1590
+ ]
1591
+ }
1592
+ ) : text,
943
1593
  copy ? /* @__PURE__ */ jsx(CopyButton, { value, label: "Copy full value" }) : null
944
1594
  ] });
945
1595
  }
@@ -993,96 +1643,269 @@ function ActivityList({ items, empty, className }) {
993
1643
  return /* @__PURE__ */ jsx("li", { children: it.href ? /* @__PURE__ */ jsx("a", { href: it.href, className: "block transition-colors hover:bg-accent/60", children: body }) : body }, it.id);
994
1644
  }) });
995
1645
  }
996
- var KIND = {
997
- package: "text-oca-code-package",
998
- tag: "text-oca-code-tag",
999
- link: "text-oca-code-link"
1646
+ var LANG_NAME = {
1647
+ ts: "TypeScript",
1648
+ typescript: "TypeScript",
1649
+ tsx: "TSX",
1650
+ js: "JavaScript",
1651
+ javascript: "JavaScript",
1652
+ jsx: "JSX",
1653
+ mjs: "JavaScript",
1654
+ json: "JSON",
1655
+ jsonc: "JSON",
1656
+ bash: "Shell",
1657
+ sh: "Shell",
1658
+ shell: "Shell",
1659
+ zsh: "Shell",
1660
+ console: "Terminal",
1661
+ terminal: "Terminal",
1662
+ python: "Python",
1663
+ py: "Python",
1664
+ yaml: "YAML",
1665
+ yml: "YAML",
1666
+ diff: "Diff",
1667
+ text: "Text"
1000
1668
  };
1001
- function PackageCard({ items, className }) {
1002
- return /* @__PURE__ */ jsx(
1003
- "div",
1004
- {
1005
- className: cn(
1006
- "grid gap-x-10 gap-y-7 rounded-[1.25rem] border border-oca-ink-line bg-oca-ink-card p-6 text-oca-ink-foreground md:grid-cols-2 md:p-9",
1007
- className
1008
- ),
1009
- children: items.map((it, i) => {
1010
- const code = /* @__PURE__ */ jsx("span", { className: cn("text-[0.9375rem]", KIND[it.kind ?? "package"]), children: it.code });
1011
- return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
1012
- /* @__PURE__ */ jsx("h3", { className: "text-[1.125rem] font-semibold tracking-[-0.01em] text-oca-ink-title", children: it.title }),
1013
- it.href ? /* @__PURE__ */ jsx("a", { href: it.href, className: "w-fit underline decoration-transparent underline-offset-4 hover:decoration-current", children: code }) : code,
1014
- it.note ? /* @__PURE__ */ jsxs("p", { className: "text-[0.9375rem] leading-relaxed text-oca-ink-subtle", children: [
1015
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "// " }),
1016
- it.note
1017
- ] }) : null
1018
- ] }, i);
1019
- })
1020
- }
1021
- );
1669
+ function languageName(lang) {
1670
+ return lang ? LANG_NAME[lang.toLowerCase()] ?? lang : void 0;
1671
+ }
1672
+ function forClipboard(text, lang) {
1673
+ if (grammarOf(lang) !== "shell") return text;
1674
+ const lines = text.split("\n");
1675
+ if (!lines.some((l) => l.startsWith("$ "))) return text;
1676
+ return lines.filter((l) => l.startsWith("$ ")).map((l) => l.slice(2)).join("\n");
1677
+ }
1678
+ function linesFromDom(pre) {
1679
+ if (!pre) return null;
1680
+ const lines = pre.querySelectorAll("[data-line]");
1681
+ if (lines.length === 0) return pre.textContent ?? "";
1682
+ return Array.from(lines).filter((l) => l.getAttribute("data-diff") !== "remove").map((l) => l.textContent ?? "").join("\n");
1683
+ }
1684
+ function prepare(code, lang, marks, diff) {
1685
+ const d = diff ? readDiff(code) : null;
1686
+ const src = d ? d.code : code.replace(/\r?\n$/, "");
1687
+ const lines = highlight(src, lang === "diff" ? void 0 : lang);
1688
+ const kept = d ? src.split("\n").filter((_, i) => d.diff.get(i + 1) !== "remove") : null;
1689
+ return {
1690
+ html: linesToHtml(lines, { highlight: parseLineRanges(marks), diff: d?.diff }),
1691
+ copy: kept ? kept.join("\n") : src,
1692
+ lines: lines.length,
1693
+ diff: !!d
1694
+ };
1695
+ }
1696
+ function Well({
1697
+ preRef,
1698
+ html,
1699
+ children,
1700
+ lang,
1701
+ lines,
1702
+ maxLines,
1703
+ diff,
1704
+ lineNumbers
1705
+ }) {
1706
+ const foldable = maxLines !== void 0 && lines > maxLines + 2;
1707
+ const [open, setOpen] = useState(false);
1708
+ const folded = foldable && !open;
1709
+ const lined = html !== void 0;
1710
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1711
+ /* @__PURE__ */ jsx(
1712
+ "div",
1713
+ {
1714
+ className: cn(folded && "overflow-hidden"),
1715
+ style: folded ? { maxHeight: `calc(${maxLines} * 1.625em + 2rem)` } : void 0,
1716
+ children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--oca-code-surface)", children: /* @__PURE__ */ jsx(
1717
+ "pre",
1718
+ {
1719
+ ref: preRef,
1720
+ "data-diff": diff ? "" : void 0,
1721
+ "data-line-numbers": lineNumbers ? "" : void 0,
1722
+ className: cn(
1723
+ "oca-code w-max min-w-full py-4 font-mono text-[0.875rem] leading-[1.625] text-oca-ink-muted [font-variant-ligatures:none]",
1724
+ !lined && "px-5"
1725
+ ),
1726
+ children: lined ? /* @__PURE__ */ jsx("code", { className: "block", "data-lang": lang, dangerouslySetInnerHTML: { __html: html } }) : /* @__PURE__ */ jsx("code", { className: "block", "data-lang": lang, children })
1727
+ }
1728
+ ) })
1729
+ }
1730
+ ),
1731
+ foldable ? /* @__PURE__ */ jsx(
1732
+ "div",
1733
+ {
1734
+ className: cn("flex justify-center px-5 pb-4", folded && "absolute inset-x-0 bottom-0 pt-16"),
1735
+ style: folded ? { background: "linear-gradient(to top, var(--oca-code-surface) 40%, transparent)" } : void 0,
1736
+ children: /* @__PURE__ */ jsx(
1737
+ "button",
1738
+ {
1739
+ type: "button",
1740
+ onClick: () => setOpen((v) => !v),
1741
+ "aria-expanded": open,
1742
+ className: "rounded-full border border-white/20 px-4 py-1.5 text-[0.8125rem] text-white transition-colors hover:bg-white/10",
1743
+ children: open ? "Show less" : `Show all ${lines} lines`
1744
+ }
1745
+ )
1746
+ }
1747
+ ) : null
1748
+ ] });
1022
1749
  }
1750
+ var FRAME = "overflow-hidden rounded-[1.25rem] border border-[var(--oca-code-line)] bg-[var(--oca-code-surface)]";
1751
+ var COPY_ON_INK = "text-oca-ink-subtle hover:bg-white/10 hover:text-white";
1023
1752
  function CodeBlock({
1024
1753
  code,
1754
+ html,
1755
+ children,
1756
+ lang,
1025
1757
  caption,
1026
1758
  copy = true,
1759
+ clearAfter,
1027
1760
  maxLines,
1761
+ highlight: marks,
1762
+ diff,
1763
+ lineNumbers,
1764
+ actions,
1028
1765
  className
1029
1766
  }) {
1030
- const lines = code.split("\n").length;
1031
- const foldable = maxLines !== void 0 && lines > maxLines + 2;
1032
- const [open, setOpen] = useState(false);
1033
- const folded = foldable && !open;
1767
+ const preRef = useRef(null);
1768
+ const isDiff = diff || lang === "diff";
1769
+ const markKey = typeof marks === "string" ? marks : marks?.join(",");
1770
+ const prepared = useMemo(
1771
+ () => html === void 0 && children === void 0 && code !== void 0 ? prepare(code, lang, markKey, !!isDiff) : null,
1772
+ [code, html, children, lang, markKey, isDiff]
1773
+ );
1774
+ const markup = prepared?.html ?? html;
1775
+ const lines = prepared?.lines ?? (html !== void 0 ? html.split("\n").length : code?.split("\n").length ?? 0);
1776
+ const read = () => forClipboard(prepared?.copy ?? linesFromDom(preRef.current) ?? code ?? "", lang);
1777
+ return /* @__PURE__ */ jsxs("figure", { className: cn(FRAME, className), children: [
1778
+ /* @__PURE__ */ jsxs("figcaption", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-5 pr-2", children: [
1779
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? languageName(lang) ?? "Code" }),
1780
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [
1781
+ actions,
1782
+ copy ? /* @__PURE__ */ jsx(CopyButton, { value: read, label: "Copy code", clearAfter, className: COPY_ON_INK }) : null
1783
+ ] })
1784
+ ] }),
1785
+ /* @__PURE__ */ jsx(
1786
+ Well,
1787
+ {
1788
+ preRef,
1789
+ html: markup,
1790
+ lang,
1791
+ lines,
1792
+ maxLines,
1793
+ diff: prepared ? prepared.diff : isDiff,
1794
+ lineNumbers,
1795
+ children
1796
+ }
1797
+ )
1798
+ ] });
1799
+ }
1800
+ var tabListeners = /* @__PURE__ */ new Map();
1801
+ var tabMemory = /* @__PURE__ */ new Map();
1802
+ var storeKey = (k) => `oca-code-tab:${k}`;
1803
+ function readTab(key) {
1804
+ if (tabMemory.has(key)) return tabMemory.get(key);
1805
+ try {
1806
+ return window.localStorage.getItem(storeKey(key));
1807
+ } catch {
1808
+ return null;
1809
+ }
1810
+ }
1811
+ function writeTab(key, value) {
1812
+ tabMemory.set(key, value);
1813
+ try {
1814
+ window.localStorage.setItem(storeKey(key), value);
1815
+ } catch {
1816
+ }
1817
+ tabListeners.get(key)?.forEach((l) => l());
1818
+ }
1819
+ function useSyncedTab(key) {
1820
+ const subscribe = useCallback(
1821
+ (cb) => {
1822
+ if (!key) return () => {
1823
+ };
1824
+ const set = tabListeners.get(key) ?? /* @__PURE__ */ new Set();
1825
+ set.add(cb);
1826
+ tabListeners.set(key, set);
1827
+ return () => {
1828
+ set.delete(cb);
1829
+ };
1830
+ },
1831
+ [key]
1832
+ );
1833
+ const value = useSyncExternalStore(
1834
+ subscribe,
1835
+ () => key ? readTab(key) : null,
1836
+ () => null
1837
+ );
1838
+ return [value, (v) => key && writeTab(key, v)];
1839
+ }
1840
+ function CodeTabs({
1841
+ items,
1842
+ syncKey,
1843
+ defaultValue,
1844
+ maxLines,
1845
+ className
1846
+ }) {
1847
+ const [synced, setSynced] = useSyncedTab(syncKey);
1848
+ const [local, setLocal] = useState(null);
1849
+ const labels = items.map((it) => it.label);
1850
+ const pick = [local, synced, defaultValue].find((v) => !!v && labels.includes(v)) ?? labels[0] ?? "";
1851
+ const active = items.find((it) => it.label === pick);
1852
+ const prepared = useMemo(() => items.map((it) => prepare(it.code, it.lang, void 0, it.lang === "diff")), [items]);
1034
1853
  return /* @__PURE__ */ jsxs(
1035
- "figure",
1854
+ TabsPrimitive.Root,
1036
1855
  {
1037
- className: cn(
1038
- "overflow-hidden rounded-[1.25rem] border border-[var(--oca-code-line)] bg-[var(--oca-code-surface)]",
1039
- className
1040
- ),
1856
+ value: pick,
1857
+ onValueChange: (v) => {
1858
+ setLocal(v);
1859
+ setSynced(v);
1860
+ },
1861
+ className: cn(FRAME, className),
1041
1862
  children: [
1042
- /* @__PURE__ */ jsxs("figcaption", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-5 pr-2", children: [
1043
- /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-oca-ink-subtle", children: caption ?? "Code" }),
1044
- copy ? /* @__PURE__ */ jsx(
1045
- CopyButton,
1046
- {
1047
- value: code,
1048
- label: "Copy code",
1049
- className: "text-oca-ink-subtle hover:bg-white/10 hover:text-white"
1050
- }
1051
- ) : null
1052
- ] }),
1053
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1054
- /* @__PURE__ */ jsx(
1055
- "div",
1056
- {
1057
- className: cn(folded && "overflow-hidden"),
1058
- style: folded ? { maxHeight: `calc(${maxLines} * 1.625em + 2.5rem)` } : void 0,
1059
- children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--oca-code-surface)", children: /* @__PURE__ */ jsx("pre", { className: "w-max min-w-full p-5 font-mono text-[0.875rem] leading-[1.625] text-oca-ink-muted [font-variant-ligatures:none]", children: /* @__PURE__ */ jsx("code", { children: code }) }) })
1060
- }
1061
- ),
1062
- foldable ? /* @__PURE__ */ jsx(
1063
- "div",
1863
+ /* @__PURE__ */ jsxs("div", { className: "flex h-11 items-center justify-between gap-3 border-b border-[var(--oca-code-line)] pl-2 pr-2", children: [
1864
+ /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--oca-code-surface)", className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(TabsPrimitive.List, { "aria-label": "Versions", className: "flex w-max items-center gap-0.5", children: items.map((it) => /* @__PURE__ */ jsx(
1865
+ TabsPrimitive.Trigger,
1064
1866
  {
1867
+ value: it.label,
1065
1868
  className: cn(
1066
- "flex justify-center px-5 pb-4",
1067
- folded && "absolute inset-x-0 bottom-0 pt-16"
1869
+ "relative inline-flex h-11 items-center whitespace-nowrap px-3 text-[0.8125rem] text-oca-ink-subtle outline-none transition-colors",
1870
+ "hover:text-white focus-visible:text-white focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
1871
+ "data-[state=active]:text-white",
1872
+ "after:absolute after:inset-x-3 after:bottom-0 after:h-0.5 after:rounded-full after:bg-transparent data-[state=active]:after:bg-oca-orange"
1068
1873
  ),
1069
- style: folded ? { background: "linear-gradient(to top, var(--oca-code-surface) 40%, transparent)" } : void 0,
1070
- children: /* @__PURE__ */ jsx(
1071
- "button",
1072
- {
1073
- type: "button",
1074
- onClick: () => setOpen((v) => !v),
1075
- className: "rounded-full border border-white/20 px-4 py-1.5 text-[0.8125rem] text-white transition-colors hover:bg-white/10",
1076
- children: open ? "Show less" : `Show all ${lines} lines`
1077
- }
1078
- )
1874
+ children: it.label
1875
+ },
1876
+ it.label
1877
+ )) }) }),
1878
+ active ? /* @__PURE__ */ jsx(
1879
+ CopyButton,
1880
+ {
1881
+ value: () => forClipboard(prepared[items.indexOf(active)]?.copy ?? active.code, active.lang),
1882
+ label: `Copy ${active.label}`,
1883
+ className: COPY_ON_INK
1079
1884
  }
1080
1885
  ) : null
1081
- ] })
1886
+ ] }),
1887
+ items.map((it, i) => /* @__PURE__ */ jsx(TabsPrimitive.Content, { value: it.label, className: "outline-none", tabIndex: -1, children: /* @__PURE__ */ jsx(
1888
+ Well,
1889
+ {
1890
+ html: prepared[i].html,
1891
+ lang: it.lang,
1892
+ lines: prepared[i].lines,
1893
+ maxLines,
1894
+ diff: prepared[i].diff
1895
+ }
1896
+ ) }, it.label))
1082
1897
  ]
1083
1898
  }
1084
1899
  );
1085
1900
  }
1901
+ function InstallTabs({ pkg, dev = false, className }) {
1902
+ const items = [
1903
+ { label: "npm", code: `npm install ${dev ? "--save-dev " : ""}${pkg}`, lang: "bash" },
1904
+ { label: "yarn", code: `yarn add ${dev ? "--dev " : ""}${pkg}`, lang: "bash" },
1905
+ { label: "pnpm", code: `pnpm add ${dev ? "--save-dev " : ""}${pkg}`, lang: "bash" }
1906
+ ];
1907
+ return /* @__PURE__ */ jsx(CodeTabs, { items, syncKey: "package-manager", className });
1908
+ }
1086
1909
  function SplitBar({
1087
1910
  segments,
1088
1911
  caption,
@@ -1433,7 +2256,2374 @@ var ErrorBoundary = class extends Component {
1433
2256
  ) });
1434
2257
  }
1435
2258
  };
2259
+ var TOP = "0,3 2,2 6,4 14,0 16,1 6,6";
2260
+ var LEFT = "0,3 6,6 6,8 0,5";
2261
+ var RIGHT = "6,6 16,1 16,3 6,8";
2262
+ var MARK_FACES = { top: "#FED8AB", left: "#FB933C", right: "#EA580B" };
2263
+ function Mark({ title, size, className, ...rest }) {
2264
+ return /* @__PURE__ */ jsxs(
2265
+ "svg",
2266
+ {
2267
+ viewBox: "0 0 16 8",
2268
+ width: size,
2269
+ height: size ? size / 2 : void 0,
2270
+ role: title ? "img" : void 0,
2271
+ "aria-hidden": title ? void 0 : true,
2272
+ className: cn("shrink-0", className),
2273
+ ...rest,
2274
+ children: [
2275
+ title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2276
+ /* @__PURE__ */ jsx("polygon", { points: LEFT, fill: MARK_FACES.left }),
2277
+ /* @__PURE__ */ jsx("polygon", { points: RIGHT, fill: MARK_FACES.right }),
2278
+ /* @__PURE__ */ jsx("polygon", { points: TOP, fill: MARK_FACES.top })
2279
+ ]
2280
+ }
2281
+ );
2282
+ }
2283
+ function MarkOutline({ className }) {
2284
+ return /* @__PURE__ */ jsx("svg", { viewBox: "-0.2 -0.2 16.4 8.4", "aria-hidden": true, className: cn("shrink-0 overflow-visible", className), children: [TOP, LEFT, RIGHT].map((points) => /* @__PURE__ */ jsx(
2285
+ "polygon",
2286
+ {
2287
+ points,
2288
+ fill: "none",
2289
+ stroke: "currentColor",
2290
+ strokeWidth: "1",
2291
+ strokeLinejoin: "round",
2292
+ vectorEffect: "non-scaling-stroke"
2293
+ },
2294
+ points
2295
+ )) });
2296
+ }
2297
+ var WORDS = {
2298
+ 404: {
2299
+ name: "Not found",
2300
+ title: "This page isn\u2019t here.",
2301
+ detail: "The link may be old, or the address mistyped."
2302
+ },
2303
+ 500: {
2304
+ name: "Server error",
2305
+ title: "Something broke on our side.",
2306
+ detail: "Try again in a moment."
2307
+ }
2308
+ };
2309
+ function ErrorPage({
2310
+ code = 404,
2311
+ title,
2312
+ detail,
2313
+ actions,
2314
+ home = "/",
2315
+ art,
2316
+ className
2317
+ }) {
2318
+ const words = WORDS[code] ?? (code >= 500 ? WORDS[500] : WORDS[404]);
2319
+ const server = code >= 500;
2320
+ return /* @__PURE__ */ jsx(Section, { space: "none", className: cn("flex min-h-[min(40rem,72dvh)] items-center py-16 md:py-24", className), children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
2321
+ /* @__PURE__ */ jsxs("div", { className: "flex max-w-[40rem] flex-col items-start gap-6 md:col-span-7", children: [
2322
+ /* @__PURE__ */ jsxs("p", { className: "oca-eyebrow oca-enter", children: [
2323
+ /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: code }),
2324
+ " \xB7 ",
2325
+ WORDS[code]?.name ?? (server ? "Error" : "Not available")
2326
+ ] }),
2327
+ /* @__PURE__ */ jsx("h1", { className: "oca-display-2 oca-enter [--enter-delay:70ms]", children: title ?? words.title }),
2328
+ /* @__PURE__ */ jsx("p", { className: "oca-lead oca-enter [--enter-delay:150ms]", children: detail ?? words.detail }),
2329
+ /* @__PURE__ */ jsx("div", { className: "oca-enter flex flex-wrap gap-3 [--enter-delay:230ms]", children: actions ?? /* @__PURE__ */ jsxs(Fragment, { children: [
2330
+ server ? /* @__PURE__ */ jsx(Button, { onClick: () => window.location.reload(), children: "Try again" }) : null,
2331
+ /* @__PURE__ */ jsx(Button, { asChild: true, variant: server ? "secondary" : "primary", children: /* @__PURE__ */ jsx(Link, { href: home, children: "Go home" }) })
2332
+ ] }) })
2333
+ ] }),
2334
+ art !== null ? /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "oca-enter hidden justify-center md:col-span-5 md:flex [--enter-delay:120ms]", children: art ?? /* @__PURE__ */ jsx(MarkOutline, { className: "w-full max-w-[20rem] text-oca-hairline-strong" }) }) : null
2335
+ ] }) });
2336
+ }
2337
+ function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
2338
+ const ref = useRef(null);
2339
+ useEffect(() => {
2340
+ const el = ref.current;
2341
+ if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
2342
+ let raf = 0;
2343
+ let tx = 0;
2344
+ let ty = 0;
2345
+ let x = 0;
2346
+ let y = 0;
2347
+ const step = () => {
2348
+ x += (tx - x) * 0.08;
2349
+ y += (ty - y) * 0.08;
2350
+ el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
2351
+ el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
2352
+ raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
2353
+ };
2354
+ const move = (e) => {
2355
+ const b = el.getBoundingClientRect();
2356
+ tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
2357
+ ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
2358
+ if (!raf) raf = requestAnimationFrame(step);
2359
+ };
2360
+ window.addEventListener("pointermove", move, { passive: true });
2361
+ return () => {
2362
+ cancelAnimationFrame(raf);
2363
+ window.removeEventListener("pointermove", move);
2364
+ };
2365
+ }, [tilt]);
2366
+ return /* @__PURE__ */ jsxs(
2367
+ "div",
2368
+ {
2369
+ ref,
2370
+ className: cn("relative inline-block", settle && "oca-animate-settle", className),
2371
+ style: { width: size, perspective: tilt ? 900 : void 0 },
2372
+ children: [
2373
+ tilt ? /* @__PURE__ */ jsx(
2374
+ "div",
2375
+ {
2376
+ "aria-hidden": true,
2377
+ className: "absolute left-1/2 top-1/2 -z-0 aspect-square w-[120%] -translate-x-1/2 -translate-y-1/2 rounded-full opacity-70 blur-3xl",
2378
+ style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
2379
+ }
2380
+ ) : null,
2381
+ /* @__PURE__ */ jsx(
2382
+ "div",
2383
+ {
2384
+ className: "relative z-10 transition-transform duration-300 ease-out",
2385
+ style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
2386
+ children: /* @__PURE__ */ jsx(Mark, { size, title, className: "block" })
2387
+ }
2388
+ ),
2389
+ shadow ? /* @__PURE__ */ jsx(
2390
+ "div",
2391
+ {
2392
+ "aria-hidden": true,
2393
+ className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
2394
+ style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
2395
+ }
2396
+ ) : null
2397
+ ]
2398
+ }
2399
+ );
2400
+ }
2401
+ var GroupName = createContext(void 0);
2402
+ function Accordion({
2403
+ single = false,
2404
+ children,
2405
+ className
2406
+ }) {
2407
+ const name = useId();
2408
+ return /* @__PURE__ */ jsx(GroupName.Provider, { value: single ? name : void 0, children: /* @__PURE__ */ jsx("div", { className: cn("divide-y divide-border overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children }) });
2409
+ }
2410
+ function AccordionItem({
2411
+ title,
2412
+ children,
2413
+ defaultOpen = false,
2414
+ id,
2415
+ className
2416
+ }) {
2417
+ const name = useContext(GroupName);
2418
+ return /* @__PURE__ */ jsxs("details", { id, name, open: defaultOpen || void 0, className: cn("group scroll-mt-24", className), children: [
2419
+ /* @__PURE__ */ jsxs(
2420
+ "summary",
2421
+ {
2422
+ className: cn(
2423
+ "flex min-h-14 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[1rem] font-medium leading-snug md:px-6",
2424
+ // Inside the card's clip, so the ring is drawn within the row.
2425
+ "transition-colors hover:bg-accent/60 focus-visible:outline-offset-[-2px] [&::-webkit-details-marker]:hidden"
2426
+ ),
2427
+ children: [
2428
+ title,
2429
+ /* @__PURE__ */ jsx(
2430
+ ChevronDown,
2431
+ {
2432
+ "aria-hidden": true,
2433
+ className: "size-4 shrink-0 text-muted-foreground transition-transform duration-200 group-open:rotate-180"
2434
+ }
2435
+ )
2436
+ ]
2437
+ }
2438
+ ),
2439
+ /* @__PURE__ */ jsx("div", { className: "oca-body px-5 pb-5 text-[0.9375rem] md:px-6 md:pb-6", children })
2440
+ ] });
2441
+ }
2442
+ function SectionHeading({
2443
+ eyebrow,
2444
+ title,
2445
+ lead,
2446
+ id,
2447
+ onInk = false,
2448
+ level = 2,
2449
+ as = "h2",
2450
+ align = "start",
2451
+ reveal = true,
2452
+ className
2453
+ }) {
2454
+ return /* @__PURE__ */ jsxs(SectionIntro, { align, reveal, className: cn("max-w-3xl gap-4 md:gap-4", className), children: [
2455
+ eyebrow ? /* @__PURE__ */ jsx(Eyebrow, { onInk, children: eyebrow }) : null,
2456
+ /* @__PURE__ */ jsx(Display, { level, as, id, className: "scroll-mt-24", children: title }),
2457
+ lead ? /* @__PURE__ */ jsx("p", { className: cn("oca-lead", onInk && "text-oca-ink-muted"), children: lead }) : null
2458
+ ] });
2459
+ }
2460
+ function FactBlock({
2461
+ id,
2462
+ title,
2463
+ description,
2464
+ aside,
2465
+ children,
2466
+ className
2467
+ }) {
2468
+ return /* @__PURE__ */ jsxs("section", { id, className: cn("flex scroll-mt-24 flex-col gap-6", className), children: [
2469
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 md:flex-row md:items-end md:justify-between md:gap-8", children: [
2470
+ /* @__PURE__ */ jsxs("div", { className: "flex max-w-[44rem] flex-col gap-3", children: [
2471
+ /* @__PURE__ */ jsx("h2", { className: "oca-display-3", children: title }),
2472
+ description ? /* @__PURE__ */ jsx("div", { className: "oca-body text-[1.0625rem]", children: description }) : null
2473
+ ] }),
2474
+ aside ? /* @__PURE__ */ jsx("div", { className: "flex shrink-0 flex-wrap gap-x-5 gap-y-2 text-[0.9375rem]", children: aside }) : null
2475
+ ] }),
2476
+ children
2477
+ ] });
2478
+ }
2479
+ function FactRows({
2480
+ rows,
2481
+ columns = 1,
2482
+ label,
2483
+ className
2484
+ }) {
2485
+ return /* @__PURE__ */ jsx("ul", { "aria-label": label, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: rows.map((r) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-5 px-5 py-6 md:px-8 md:py-7", children: [
2486
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-x-6", children: [
2487
+ /* @__PURE__ */ jsx("h3", { className: "oca-title min-w-0 text-pretty", children: r.title }),
2488
+ r.figure ? /* @__PURE__ */ jsx("span", { className: "oca-tabular shrink-0 whitespace-nowrap text-[1.75rem] leading-none tracking-[-0.02em]", children: r.figure }) : null
2489
+ ] }),
2490
+ /* @__PURE__ */ jsx("dl", { className: columns === 2 ? "grid grid-cols-1 gap-x-10 gap-y-4 md:grid-cols-2" : "flex flex-col gap-4", children: r.fields.map((f, i) => /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
2491
+ /* @__PURE__ */ jsx("dt", { className: "text-[0.875rem] font-medium text-muted-foreground", children: f.label }),
2492
+ /* @__PURE__ */ jsx("dd", { className: "break-words text-[1rem] leading-relaxed", children: f.value })
2493
+ ] }, i)) })
2494
+ ] }, r.key)) });
2495
+ }
2496
+ function EndpointList({ items, label, className }) {
2497
+ return /* @__PURE__ */ jsx("ul", { "aria-label": label, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: items.map((a) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
2498
+ "a",
2499
+ {
2500
+ href: a.href,
2501
+ target: "_blank",
2502
+ rel: "noreferrer",
2503
+ className: "flex flex-col gap-1 px-5 py-3.5 transition-colors hover:bg-accent/60 sm:flex-row sm:items-baseline sm:justify-between sm:gap-6",
2504
+ children: [
2505
+ /* @__PURE__ */ jsx("code", { className: "break-all text-[0.875rem] text-foreground", children: a.label ?? a.href }),
2506
+ /* @__PURE__ */ jsxs("span", { className: "text-[0.875rem] text-muted-foreground sm:text-right", children: [
2507
+ a.description,
2508
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens in a new tab)" })
2509
+ ] })
2510
+ ]
2511
+ }
2512
+ ) }, a.href)) });
2513
+ }
2514
+ function ProofStrip({ items, className }) {
2515
+ return /* @__PURE__ */ jsx("div", { className: cn("border-y border-border", className), children: /* @__PURE__ */ jsx("ul", { className: "oca-container grid grid-cols-2 gap-x-6 gap-y-4 py-6 md:grid-cols-4", children: items.map((it, i) => /* @__PURE__ */ jsxs(
2516
+ "li",
2517
+ {
2518
+ className: "flex items-center gap-3 text-[0.9375rem] [&_svg]:size-[1.1rem] [&_svg]:shrink-0 [&_svg]:text-oca-accent-ink",
2519
+ children: [
2520
+ it.icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "flex", children: it.icon }) : null,
2521
+ it.label
2522
+ ]
2523
+ },
2524
+ i
2525
+ )) }) });
2526
+ }
2527
+ function Closing({
2528
+ title,
2529
+ lead,
2530
+ actions,
2531
+ art,
2532
+ className
2533
+ }) {
2534
+ return /* @__PURE__ */ jsx(Section, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 items-center gap-12 md:grid-cols-12", children: [
2535
+ /* @__PURE__ */ jsxs(Reveal, { className: "flex flex-col items-start gap-8 md:col-span-7", children: [
2536
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5", children: [
2537
+ /* @__PURE__ */ jsx("h2", { className: "oca-display-1 text-[clamp(2.5rem,1.5rem+4vw,5rem)] leading-[1]", children: title }),
2538
+ lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead max-w-[34rem]", children: lead }) : null
2539
+ ] }),
2540
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3", children: actions }) : null
2541
+ ] }),
2542
+ art !== null ? (
2543
+ // Room under the check on a phone, so its glow fades before the band ends.
2544
+ /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex justify-center max-md:pb-16 md:col-span-5", children: art ?? /* @__PURE__ */ jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) })
2545
+ ) : null
2546
+ ] }) });
2547
+ }
2548
+ function Faq({
2549
+ items,
2550
+ className
2551
+ }) {
2552
+ return /* @__PURE__ */ jsx(Accordion, { single: true, className, children: items.map((it, i) => /* @__PURE__ */ jsx(AccordionItem, { id: it.id, title: it.q, children: it.a }, it.id ?? i)) });
2553
+ }
2554
+ var LINK = "text-foreground underline decoration-foreground/35 underline-offset-4 transition-colors hover:decoration-foreground";
2555
+ function TextLink({
2556
+ href,
2557
+ children,
2558
+ external,
2559
+ className
2560
+ }) {
2561
+ const internal = href.startsWith("/") && !href.startsWith("/api/") && !href.startsWith("/.well-known/");
2562
+ const offsite = external ?? /^https?:\/\//.test(href);
2563
+ if (internal && !offsite) {
2564
+ return /* @__PURE__ */ jsx(Link, { href, className: cn(LINK, className), children });
2565
+ }
2566
+ return /* @__PURE__ */ jsxs("a", { href, className: cn(LINK, className), ...offsite ? { target: "_blank", rel: "noreferrer" } : {}, children: [
2567
+ children,
2568
+ offsite ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens in a new tab)" }) : null
2569
+ ] });
2570
+ }
2571
+ var PROPER = {
2572
+ kyc: "KYC",
2573
+ pii: "PII",
2574
+ ccpa: "CCPA",
2575
+ cpra: "CPRA",
2576
+ gdpr: "GDPR",
2577
+ uk: "UK",
2578
+ eu: "EU",
2579
+ california: "California",
2580
+ europe: "Europe",
2581
+ united: "United",
2582
+ kingdom: "Kingdom"
2583
+ };
2584
+ function headingCase(text) {
2585
+ const words = text.replace(/\b[a-z]+\b/g, (w) => PROPER[w] ?? w);
2586
+ if (/^orangecheck\b/.test(words)) return `OrangeCheck${words.slice("orangecheck".length)}`;
2587
+ return words.length === 0 ? words : words[0].toUpperCase() + words.slice(1);
2588
+ }
2589
+ function sentencesCase(text) {
2590
+ return text.split(/(?<=[.!?])\s+/).map((s) => headingCase(s)).join(" ");
2591
+ }
2592
+ function openSentence(text) {
2593
+ const first = /^\S+/.exec(text)?.[0] ?? "";
2594
+ if (!/^[a-z][a-z'’-]*,?$/.test(first)) return text;
2595
+ return text[0].toUpperCase() + text.slice(1);
2596
+ }
2597
+ var INLINE = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/g;
2598
+ var LINK2 = /^\[([^\]]+)\]\(([^)]+)\)$/;
2599
+ function Inline({ text }) {
2600
+ return /* @__PURE__ */ jsx(Fragment, { children: text.split(INLINE).map((part, i) => {
2601
+ if (!part) return null;
2602
+ if (part.startsWith("**") && part.endsWith("**") && part.length > 4) {
2603
+ return /* @__PURE__ */ jsx("strong", { children: /* @__PURE__ */ jsx(Inline, { text: part.slice(2, -2) }) }, i);
2604
+ }
2605
+ if (part.startsWith("`") && part.endsWith("`") && part.length > 2) return /* @__PURE__ */ jsx("code", { children: part.slice(1, -1) }, i);
2606
+ const link = LINK2.exec(part);
2607
+ if (link) {
2608
+ return /* @__PURE__ */ jsx(TextLink, { href: link[2] ?? "", children: link[1] }, i);
2609
+ }
2610
+ return /* @__PURE__ */ jsx(Fragment$1, { children: part }, i);
2611
+ }) });
2612
+ }
2613
+ function BlockView({ block }) {
2614
+ switch (block.kind) {
2615
+ case "para":
2616
+ return /* @__PURE__ */ jsx(Fragment, { children: block.text.split(/\n{2,}/).map((para, i) => /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(Inline, { text: para }) }, i)) });
2617
+ case "subhead":
2618
+ return /* @__PURE__ */ jsx("h3", { children: /* @__PURE__ */ jsx(Inline, { text: headingCase(block.text) }) });
2619
+ case "bullets":
2620
+ return /* @__PURE__ */ jsx("ul", { children: block.items.map(
2621
+ (item, i) => typeof item === "string" ? /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Inline, { text: item }) }, i) : /* @__PURE__ */ jsxs("li", { children: [
2622
+ /* @__PURE__ */ jsxs("strong", { children: [
2623
+ headingCase(item.k),
2624
+ "."
2625
+ ] }),
2626
+ " ",
2627
+ /* @__PURE__ */ jsx(Inline, { text: openSentence(item.v) })
2628
+ ] }, i)
2629
+ ) });
2630
+ case "callout":
2631
+ return /* @__PURE__ */ jsx("div", { className: "not-prose my-6", children: /* @__PURE__ */ jsx(Notice, { tone: block.emphatic ? "brand" : "neutral", children: /* @__PURE__ */ jsx(Inline, { text: block.text }) }) });
2632
+ case "stub":
2633
+ return /* @__PURE__ */ jsx("div", { className: "not-prose my-6", children: /* @__PURE__ */ jsx(Notice, { tone: "brand", title: "Pending counsel review", children: /* @__PURE__ */ jsx(Inline, { text: block.text }) }) });
2634
+ }
2635
+ }
2636
+ function LegalDocument({ doc, className }) {
2637
+ return /* @__PURE__ */ jsx(
2638
+ DocLayout,
2639
+ {
2640
+ className,
2641
+ header: /* @__PURE__ */ jsx(
2642
+ DocHeader,
2643
+ {
2644
+ eyebrow: headingCase(doc.eyebrow),
2645
+ title: doc.title,
2646
+ lead: doc.description,
2647
+ meta: `Effective ${doc.effective} \xB7 last updated ${doc.updated}`
2648
+ }
2649
+ ),
2650
+ toc: doc.sections.map((s) => ({ id: s.id, label: headingCase(s.heading) })),
2651
+ children: /* @__PURE__ */ jsx("article", { className: "min-w-0", children: /* @__PURE__ */ jsxs(Prose, { children: [
2652
+ doc.preamble?.map((b, i) => /* @__PURE__ */ jsx(BlockView, { block: b }, i)),
2653
+ doc.sections.map((s) => /* @__PURE__ */ jsxs("section", { children: [
2654
+ /* @__PURE__ */ jsxs("h2", { id: s.id, className: "scroll-mt-24", children: [
2655
+ s.num ? /* @__PURE__ */ jsxs("span", { className: "oca-tabular text-muted-foreground", children: [
2656
+ s.num,
2657
+ " "
2658
+ ] }) : null,
2659
+ headingCase(s.heading)
2660
+ ] }),
2661
+ s.hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem]", children: headingCase(s.hint) }) : null,
2662
+ s.blocks.map((b, i) => /* @__PURE__ */ jsx(BlockView, { block: b }, i))
2663
+ ] }, s.id)),
2664
+ doc.summary ? /* @__PURE__ */ jsxs("p", { className: "mt-14 border-t border-border pt-6 text-[0.9375rem]", children: [
2665
+ /* @__PURE__ */ jsx("strong", { children: "In short." }),
2666
+ " ",
2667
+ sentencesCase(doc.summary.replace(/^summary:\s*/i, ""))
2668
+ ] }) : null
2669
+ ] }) })
2670
+ }
2671
+ );
2672
+ }
2673
+
2674
+ // src/family/index.ts
2675
+ var OCHK_IO = "https://ochk.io";
2676
+ var DOCS_HREF = `${OCHK_IO}/docs`;
2677
+ function protocol(slug, verb, line, kinds) {
2678
+ return {
2679
+ slug,
2680
+ label: slug,
2681
+ href: `${OCHK_IO}/${slug}`,
2682
+ group: "protocol",
2683
+ line,
2684
+ status: "live",
2685
+ verb,
2686
+ pageHref: `${OCHK_IO}/${slug}`,
2687
+ toolHref: `https://${slug}.ochk.io`,
2688
+ specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
2689
+ kinds
2690
+ };
2691
+ }
2692
+ var PROTOCOLS = [
2693
+ protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
2694
+ protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
2695
+ protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
2696
+ protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
2697
+ protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
2698
+ protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
2699
+ ];
2700
+ var PROTOCOL_ORDER = PROTOCOLS.map((p) => p.slug);
2701
+ var FAMILY = [
2702
+ {
2703
+ slug: "home",
2704
+ label: "ochk.io",
2705
+ href: OCHK_IO,
2706
+ group: "orangecheck",
2707
+ line: "The open protocols, and the company behind them.",
2708
+ status: "live"
2709
+ },
2710
+ {
2711
+ slug: "me",
2712
+ label: "ochk.app",
2713
+ href: "https://ochk.app",
2714
+ group: "orangecheck",
2715
+ line: "One account, with Bitcoin behind it.",
2716
+ status: "testing"
2717
+ },
2718
+ {
2719
+ slug: "docs",
2720
+ label: "docs",
2721
+ href: DOCS_HREF,
2722
+ group: "orangecheck",
2723
+ line: "Specs, SDKs and guides for every protocol.",
2724
+ status: "live"
2725
+ },
2726
+ ...PROTOCOLS,
2727
+ {
2728
+ slug: "vault",
2729
+ label: "vault",
2730
+ href: "https://vault.ochk.io",
2731
+ group: "app",
2732
+ line: "A password manager, encrypted in your browser.",
2733
+ status: "live",
2734
+ protocols: ["lock"]
2735
+ },
2736
+ {
2737
+ slug: "chat",
2738
+ label: "chat",
2739
+ href: "https://chat.ochk.io",
2740
+ group: "app",
2741
+ line: "Messages only the holder of a Bitcoin address can read.",
2742
+ status: "testing",
2743
+ protocols: ["lock"]
2744
+ },
2745
+ {
2746
+ slug: "cosign",
2747
+ label: "cosign",
2748
+ href: "https://cosign.ochk.io",
2749
+ group: "app",
2750
+ line: "Builders find co-founders and backers.",
2751
+ status: "testing",
2752
+ protocols: ["attest"]
2753
+ },
2754
+ {
2755
+ slug: "me-demo",
2756
+ // "demo", not the made-up app's own name, so nobody takes it for ours.
2757
+ label: "demo",
2758
+ href: "https://me-demo.ochk.io",
2759
+ group: "app",
2760
+ line: "Lumen Notes, a made-up app that signs in with orangecheck.",
2761
+ status: "live"
2762
+ },
2763
+ {
2764
+ slug: "globe",
2765
+ label: "globe",
2766
+ href: "https://globe.ochk.io",
2767
+ group: "public-good",
2768
+ line: "The Bitcoin network, live, on a globe.",
2769
+ status: "live"
2770
+ },
2771
+ {
2772
+ slug: "btc",
2773
+ label: "btc",
2774
+ href: "https://btc.ochk.io",
2775
+ group: "public-good",
2776
+ line: "A free desk for reading the Bitcoin market.",
2777
+ status: "live"
2778
+ }
2779
+ ];
2780
+ var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
2781
+ function protocolSite(slug) {
2782
+ return BY_SLUG.get(slug);
2783
+ }
2784
+ [
2785
+ {
2786
+ href: `${OCHK_IO}/protocols`,
2787
+ label: "Protocols",
2788
+ children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
2789
+ },
2790
+ { href: `${OCHK_IO}/apps`, label: "Apps" },
2791
+ { href: DOCS_HREF, label: "Docs" },
2792
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
2793
+ { href: `${OCHK_IO}/about`, label: "About" }
2794
+ ];
2795
+ var WORD = {
2796
+ live: "Live",
2797
+ testing: "In testing",
2798
+ "not-yet": "Not yet",
2799
+ paused: "Paused",
2800
+ good: "Good",
2801
+ caution: "Caution",
2802
+ refused: "Refused"
2803
+ };
2804
+ var TONE2 = {
2805
+ live: "success",
2806
+ testing: "brand",
2807
+ "not-yet": "muted",
2808
+ paused: "muted",
2809
+ good: "success",
2810
+ caution: "brand",
2811
+ refused: "danger"
2812
+ };
2813
+ function StatusBadge({ status, className, ...props }) {
2814
+ return /* @__PURE__ */ jsx(Badge, { tone: TONE2[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
2815
+ }
2816
+ 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";
2817
+ var STRETCH = 'outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-[""]';
2818
+ var pad2 = (n) => String(n + 1).padStart(2, "0");
2819
+ function ProtocolGrid({
2820
+ protocols = PROTOCOL_ORDER,
2821
+ link = "page",
2822
+ className
2823
+ }) {
2824
+ return /* @__PURE__ */ jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 md:gap-5", className), children: protocols.map((slug) => {
2825
+ const p = protocolSite(slug);
2826
+ const i = PROTOCOL_ORDER.indexOf(slug);
2827
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("div", { className: cn(CARD, "gap-4"), children: [
2828
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
2829
+ /* @__PURE__ */ jsxs("span", { className: "oca-numeral", children: [
2830
+ pad2(i),
2831
+ " ",
2832
+ /* @__PURE__ */ jsx("span", { className: "ml-1.5 capitalize", children: p.verb })
2833
+ ] }),
2834
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null
2835
+ ] }),
2836
+ /* @__PURE__ */ jsx("h3", { className: "oca-display-3", children: /* @__PURE__ */ jsx(
2837
+ "a",
2838
+ {
2839
+ href: link === "tool" ? p.toolHref : link === "docs" ? `${DOCS_HREF}/${p.slug}` : p.pageHref,
2840
+ className: STRETCH,
2841
+ children: p.label
2842
+ }
2843
+ ) }),
2844
+ /* @__PURE__ */ jsx("p", { className: "oca-body", children: p.line }),
2845
+ /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-center justify-between gap-3 pt-2 text-[0.875rem] text-muted-foreground", children: [
2846
+ /* @__PURE__ */ jsxs("span", { className: "oca-tabular", children: [
2847
+ "Nostr kind ",
2848
+ p.kinds
2849
+ ] }),
2850
+ /* @__PURE__ */ jsx(
2851
+ ArrowUpRight,
2852
+ {
2853
+ "aria-hidden": true,
2854
+ className: "size-4 transition-transform duration-200 group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-foreground"
2855
+ }
2856
+ )
2857
+ ] })
2858
+ ] }) }, slug);
2859
+ }) });
2860
+ }
2861
+ function AppCard({ name, line, href, protocols = [], status = "live", className }) {
2862
+ return /* @__PURE__ */ jsxs("div", { className: cn(CARD, "gap-3", className), children: [
2863
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
2864
+ /* @__PURE__ */ jsx("h3", { className: "oca-title", children: /* @__PURE__ */ jsx("a", { href, className: STRETCH, children: name }) }),
2865
+ status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status }) : null
2866
+ ] }),
2867
+ /* @__PURE__ */ jsx("p", { className: "oca-body text-[0.9375rem]", children: line }),
2868
+ /* @__PURE__ */ jsxs("div", { className: "mt-auto flex items-end justify-between gap-3 pt-3", children: [
2869
+ protocols.length > 0 ? /* @__PURE__ */ jsxs("p", { className: "flex flex-wrap items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
2870
+ "Shows",
2871
+ protocols.map((p) => /* @__PURE__ */ jsx(Badge, { tone: "muted", children: p }, p))
2872
+ ] }) : /* @__PURE__ */ jsx("span", {}),
2873
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-[0.875rem] text-muted-foreground transition-colors group-hover:text-foreground", children: [
2874
+ href.replace(/^https?:\/\//, ""),
2875
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true, className: "size-4" })
2876
+ ] })
2877
+ ] })
2878
+ ] });
2879
+ }
2880
+ function AppGrid({
2881
+ group = "app",
2882
+ sites,
2883
+ className
2884
+ }) {
2885
+ const list = sites ? sites.map((slug) => FAMILY.find((s) => s.slug === slug)).filter((s) => s !== void 0) : FAMILY.filter((s) => s.group === group);
2886
+ return /* @__PURE__ */ jsx("ul", { className: cn("grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-5", className), children: list.map((s) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(AppCard, { name: s.label, line: s.line, href: s.href, protocols: s.protocols, status: s.status }) }, s.slug)) });
2887
+ }
2888
+ var fieldBase = [
2889
+ "w-full rounded-xl border border-input bg-card text-foreground placeholder:text-oca-subtle",
2890
+ "text-base md:text-[0.9375rem] outline-none transition-[border-color,box-shadow]",
2891
+ "focus:border-foreground/35 focus:ring-4 focus:ring-[color-mix(in_oklab,var(--oca-orange)_16%,transparent)]",
2892
+ "disabled:cursor-not-allowed disabled:opacity-55",
2893
+ "aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:ring-[color-mix(in_oklab,var(--destructive)_14%,transparent)]"
2894
+ ];
2895
+ var FIELD_SIZE = {
2896
+ md: "h-11 px-3.5",
2897
+ sm: "h-9 rounded-[0.625rem] px-3 md:text-[0.875rem]"
2898
+ };
2899
+ var Input = forwardRef(function Input2({ className, type = "text", size, ...props }, ref) {
2900
+ const density = useDensity();
2901
+ const s = size ?? (density === "compact" ? "sm" : "md");
2902
+ return /* @__PURE__ */ jsx(
2903
+ "input",
2904
+ {
2905
+ ref,
2906
+ type,
2907
+ "data-ui": "input",
2908
+ "data-size": s,
2909
+ className: cn(fieldBase, FIELD_SIZE[s], className),
2910
+ ...props
2911
+ }
2912
+ );
2913
+ });
2914
+ var Textarea = forwardRef(
2915
+ function Textarea2({ className, ...props }, ref) {
2916
+ return /* @__PURE__ */ jsx(
2917
+ "textarea",
2918
+ {
2919
+ ref,
2920
+ "data-ui": "textarea",
2921
+ className: cn(fieldBase, "min-h-28 px-3.5 py-3 leading-relaxed", className),
2922
+ ...props
2923
+ }
2924
+ );
2925
+ }
2926
+ );
2927
+ var Label = forwardRef(function Label2({ className, ...props }, ref) {
2928
+ return /* @__PURE__ */ jsx(
2929
+ LabelPrimitive.Root,
2930
+ {
2931
+ ref,
2932
+ className: cn("text-sm font-medium leading-none text-foreground", className),
2933
+ ...props
2934
+ }
2935
+ );
2936
+ });
2937
+ function Field({ label, hint, optional, error, children, className, hideLabel, action }) {
2938
+ const id = useId();
2939
+ const hintId = hint ? `${id}-hint` : void 0;
2940
+ const errorId = error ? `${id}-error` : void 0;
2941
+ const describedBy = [hintId, errorId].filter(Boolean).join(" ") || void 0;
2942
+ const control = isValidElement(children) ? cloneElement(children, {
2943
+ id,
2944
+ "aria-describedby": describedBy,
2945
+ "aria-invalid": error ? true : void 0
2946
+ }) : children;
2947
+ const hintNode = hint ? /* @__PURE__ */ jsx("p", { id: hintId, className: "text-[0.8125rem] leading-snug text-muted-foreground", children: hint }) : null;
2948
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
2949
+ /* @__PURE__ */ jsxs(Label, { htmlFor: id, className: hideLabel ? "sr-only" : "flex items-baseline gap-2", children: [
2950
+ label,
2951
+ optional ? /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] font-normal text-muted-foreground", children: "Optional" }) : null
2952
+ ] }),
2953
+ action ? (
2954
+ // The hint belongs to the input, so it sits under the input, not under the button.
2955
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start", children: [
2956
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2 [&>input]:w-full", children: [
2957
+ control,
2958
+ hintNode
2959
+ ] }),
2960
+ /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action })
2961
+ ] })
2962
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
2963
+ control,
2964
+ hintNode
2965
+ ] }),
2966
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] leading-snug text-destructive", children: error }) : null
2967
+ ] });
2968
+ }
2969
+ var SelectFieldContext = sharedContext("select-field", null);
2970
+ forwardRef(function SelectTrigger2({ className, children, size, ...props }, ref) {
2971
+ const density = useDensity();
2972
+ const field = useContext(SelectFieldContext);
2973
+ const s = size ?? (density === "compact" ? "sm" : "md");
2974
+ return /* @__PURE__ */ jsxs(
2975
+ SelectPrimitive.Trigger,
2976
+ {
2977
+ ref,
2978
+ id: field?.id,
2979
+ "aria-describedby": field?.["aria-describedby"],
2980
+ "aria-invalid": field?.["aria-invalid"],
2981
+ className: cn(fieldBase, FIELD_SIZE[s], "flex items-center justify-between gap-2 text-left", className),
2982
+ ...props,
2983
+ children: [
2984
+ /* @__PURE__ */ jsx("span", { className: "truncate", children }),
2985
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 shrink-0 text-muted-foreground" }) })
2986
+ ]
2987
+ }
2988
+ );
2989
+ });
2990
+ forwardRef(function SelectContent2({ className, children, position = "popper", ...props }, ref) {
2991
+ return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2992
+ SelectPrimitive.Content,
2993
+ {
2994
+ ref,
2995
+ position,
2996
+ sideOffset: 6,
2997
+ className: cn(
2998
+ "oca-animate-fade z-50 max-h-[min(24rem,var(--radix-select-content-available-height))] min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-lg",
2999
+ className
3000
+ ),
3001
+ ...props,
3002
+ children: /* @__PURE__ */ jsx(SelectPrimitive.Viewport, { children })
3003
+ }
3004
+ ) });
3005
+ });
3006
+ forwardRef(function SelectItem2({ className, children, ...props }, ref) {
3007
+ return /* @__PURE__ */ jsxs(
3008
+ SelectPrimitive.Item,
3009
+ {
3010
+ ref,
3011
+ className: cn(
3012
+ "relative flex h-10 cursor-default select-none items-center rounded-lg pl-3 pr-9 text-[0.9375rem] outline-none",
3013
+ "data-[highlighted]:bg-accent data-[disabled]:opacity-50",
3014
+ className
3015
+ ),
3016
+ ...props,
3017
+ children: [
3018
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children }),
3019
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { className: "absolute right-3", children: /* @__PURE__ */ jsx(Check, { className: "size-4" }) })
3020
+ ]
3021
+ }
3022
+ );
3023
+ });
3024
+ forwardRef(function Checkbox2({ className, ...props }, ref) {
3025
+ return /* @__PURE__ */ jsx(
3026
+ CheckboxPrimitive.Root,
3027
+ {
3028
+ ref,
3029
+ className: cn(
3030
+ "peer inline-flex size-5 shrink-0 items-center justify-center rounded-[6px] border border-input bg-card",
3031
+ "outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
3032
+ "data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
3033
+ "disabled:cursor-not-allowed disabled:opacity-50",
3034
+ className
3035
+ ),
3036
+ ...props,
3037
+ children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-3.5", strokeWidth: 3 }) })
3038
+ }
3039
+ );
3040
+ });
3041
+ forwardRef(function Switch2({ className, ...props }, ref) {
3042
+ return /* @__PURE__ */ jsx(
3043
+ SwitchPrimitive.Root,
3044
+ {
3045
+ ref,
3046
+ className: cn(
3047
+ "peer inline-flex h-6 w-11 shrink-0 items-center rounded-full border border-transparent bg-input p-0.5",
3048
+ "outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
3049
+ // The deep orange: the track is the state, so it must clear 3:1 on a card.
3050
+ "data-[state=checked]:bg-oca-orange-deep disabled:cursor-not-allowed disabled:opacity-50",
3051
+ className
3052
+ ),
3053
+ ...props,
3054
+ children: /* @__PURE__ */ jsx(SwitchPrimitive.Thumb, { className: "pointer-events-none block size-5 rounded-full bg-white shadow-sm transition-transform data-[state=checked]:translate-x-5" })
3055
+ }
3056
+ );
3057
+ });
3058
+ forwardRef(function RadioGroup2({ className, ...props }, ref) {
3059
+ return /* @__PURE__ */ jsx(RadioGroupPrimitive.Root, { ref, className: cn("grid gap-3", className), ...props });
3060
+ });
3061
+ forwardRef(function RadioGroupItem2({ className, ...props }, ref) {
3062
+ return /* @__PURE__ */ jsx(
3063
+ RadioGroupPrimitive.Item,
3064
+ {
3065
+ ref,
3066
+ className: cn(
3067
+ "inline-flex size-5 shrink-0 items-center justify-center rounded-full border border-input bg-card",
3068
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
3069
+ "data-[state=checked]:border-primary disabled:cursor-not-allowed disabled:opacity-50",
3070
+ className
3071
+ ),
3072
+ ...props,
3073
+ children: /* @__PURE__ */ jsx(RadioGroupPrimitive.Indicator, { className: "block size-2.5 rounded-full bg-primary" })
3074
+ }
3075
+ );
3076
+ });
3077
+ function ProtocolHero({
3078
+ protocol: protocol2,
3079
+ title,
3080
+ lead,
3081
+ actions,
3082
+ art,
3083
+ children,
3084
+ className
3085
+ }) {
3086
+ const p = protocolSite(protocol2);
3087
+ return /* @__PURE__ */ jsx(
3088
+ PageHero,
3089
+ {
3090
+ className,
3091
+ eyebrow: `Protocol \xB7 ${p.verb}`,
3092
+ title,
3093
+ lead,
3094
+ actions,
3095
+ art,
3096
+ children: p.status !== "live" || children ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-4", children: [
3097
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null,
3098
+ children
3099
+ ] }) : null
3100
+ }
3101
+ );
3102
+ }
3103
+ function ProtocolNav({
3104
+ current,
3105
+ link = "page",
3106
+ className
3107
+ }) {
3108
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Protocols", className, children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--background)", children: /* @__PURE__ */ jsx("ul", { className: "flex w-max min-w-full items-center gap-6 border-b border-border", children: PROTOCOLS.map((p) => {
3109
+ const on = p.slug === current;
3110
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
3111
+ "a",
3112
+ {
3113
+ href: link === "tool" ? p.toolHref : p.pageHref,
3114
+ "aria-current": on ? "page" : void 0,
3115
+ className: cn(
3116
+ "-mb-px inline-flex h-11 items-center border-b-2 text-[0.9375rem] transition-colors",
3117
+ on ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
3118
+ ),
3119
+ children: p.label
3120
+ }
3121
+ ) }, p.slug);
3122
+ }) }) }) });
3123
+ }
3124
+ function SpecCard({
3125
+ protocol: protocol2,
3126
+ version,
3127
+ license,
3128
+ vectors,
3129
+ size = "md",
3130
+ className
3131
+ }) {
3132
+ const p = protocolSite(protocol2);
3133
+ const repo = `oc-${p.slug}-protocol`;
3134
+ const facts = [
3135
+ ["Version", version],
3136
+ ...license ? [["Licence", license]] : [],
3137
+ ["Nostr kind", p.kinds],
3138
+ ...vectors !== void 0 ? [["Test vectors", String(vectors)]] : []
3139
+ ];
3140
+ if (size === "sm") {
3141
+ return /* @__PURE__ */ jsxs(
3142
+ "a",
3143
+ {
3144
+ href: p.specHref,
3145
+ className: cn(
3146
+ "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",
3147
+ className
3148
+ ),
3149
+ children: [
3150
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-[0.8125rem] text-foreground", children: repo }),
3151
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: facts.map(([k, v]) => k === "Version" ? `v${v}` : k === "Nostr kind" ? `kind ${v}` : v).join(" \xB7 ") }),
3152
+ /* @__PURE__ */ jsxs("span", { className: "ml-auto flex items-center gap-1 text-muted-foreground group-hover:text-foreground", children: [
3153
+ "Read the spec ",
3154
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true, className: "size-4" })
3155
+ ] })
3156
+ ]
3157
+ }
3158
+ );
3159
+ }
3160
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-6 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className), children: [
3161
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-4", children: [
3162
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
3163
+ /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: "The spec" }),
3164
+ /* @__PURE__ */ jsx("h3", { className: "oca-title break-all font-mono text-[1.0625rem] tracking-normal", children: repo })
3165
+ ] }),
3166
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status }) : null
3167
+ ] }),
3168
+ /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-4", children: facts.map(([k, v]) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3169
+ /* @__PURE__ */ jsx("dt", { className: "text-[0.8125rem] text-muted-foreground", children: k }),
3170
+ /* @__PURE__ */ jsx("dd", { className: "oca-tabular text-[1.0625rem]", children: v })
3171
+ ] }, k)) }),
3172
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: /* @__PURE__ */ jsxs("a", { href: p.specHref, children: [
3173
+ "Read the spec ",
3174
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true })
3175
+ ] }) }) })
3176
+ ] });
3177
+ }
3178
+ function VerifyBox({
3179
+ action,
3180
+ param = "q",
3181
+ title,
3182
+ description,
3183
+ label = "Id, envelope or link",
3184
+ placeholder,
3185
+ hint,
3186
+ submitLabel = "Verify",
3187
+ multiline = false,
3188
+ onVerify,
3189
+ className
3190
+ }) {
3191
+ const [value, setValue] = useState("");
3192
+ const submit = (e) => {
3193
+ if (!onVerify) return;
3194
+ e.preventDefault();
3195
+ if (value.trim()) onVerify(value.trim());
3196
+ };
3197
+ const button = /* @__PURE__ */ jsx(Button, { type: "submit", className: multiline ? void 0 : "w-full sm:w-auto", children: submitLabel });
3198
+ return /* @__PURE__ */ jsxs(
3199
+ "form",
3200
+ {
3201
+ action,
3202
+ method: "get",
3203
+ onSubmit: submit,
3204
+ className: cn("flex flex-col gap-5 rounded-[1.25rem] border border-border bg-card p-6 md:p-8", className),
3205
+ children: [
3206
+ title || description ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
3207
+ title ? /* @__PURE__ */ jsx("h3", { className: "oca-title", children: title }) : null,
3208
+ description ? /* @__PURE__ */ jsx("p", { className: "oca-body text-[0.9375rem]", children: description }) : null
3209
+ ] }) : null,
3210
+ multiline ? /* @__PURE__ */ jsxs(Fragment, { children: [
3211
+ /* @__PURE__ */ jsx(Field, { label, hint, children: /* @__PURE__ */ jsx(
3212
+ Textarea,
3213
+ {
3214
+ name: param,
3215
+ required: true,
3216
+ value,
3217
+ onChange: (e) => setValue(e.target.value),
3218
+ placeholder,
3219
+ spellCheck: false,
3220
+ className: "min-h-32 font-mono text-base md:text-[0.8125rem]"
3221
+ }
3222
+ ) }),
3223
+ /* @__PURE__ */ jsx("div", { children: button })
3224
+ ] }) : /* @__PURE__ */ jsx(Field, { label, hint, action: button, children: /* @__PURE__ */ jsx(
3225
+ Input,
3226
+ {
3227
+ name: param,
3228
+ required: true,
3229
+ value,
3230
+ onChange: (e) => setValue(e.target.value),
3231
+ placeholder,
3232
+ spellCheck: false,
3233
+ autoComplete: "off",
3234
+ className: "font-mono text-base md:text-[0.875rem]"
3235
+ }
3236
+ ) })
3237
+ ]
3238
+ }
3239
+ );
3240
+ }
3241
+ var TINT = "bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))]";
3242
+ function ComparisonTable({
3243
+ columns,
3244
+ rows,
3245
+ label,
3246
+ propertyHeading = "Property",
3247
+ className
3248
+ }) {
3249
+ const wide = columns.length > 3;
3250
+ const grid = wide ? "lg:grid lg:grid-cols-[var(--oca-compare)]" : "md:grid md:grid-cols-[var(--oca-compare)]";
3251
+ const desk = wide ? "lg" : "md";
3252
+ const style = {
3253
+ // The argued-for column gets a little more room: its answers carry the page.
3254
+ "--oca-compare": ["minmax(0, 1.4fr)", ...columns.map((c) => c.highlight ? "minmax(0, 1.3fr)" : "minmax(0, 1fr)")].join(" ")
3255
+ };
3256
+ const ordered = [...columns].sort((a, b) => Number(Boolean(b.highlight)) - Number(Boolean(a.highlight)));
3257
+ return /* @__PURE__ */ jsxs("ul", { "aria-label": label, style, className: cn("divide-y divide-border rounded-[1.25rem] border border-border bg-card", className), children: [
3258
+ /* @__PURE__ */ jsxs(
3259
+ "li",
3260
+ {
3261
+ "aria-hidden": true,
3262
+ className: cn(
3263
+ "hidden gap-5 px-5 py-4 text-[0.875rem] font-medium text-muted-foreground",
3264
+ wide ? "lg:grid lg:px-8" : "md:grid md:px-8",
3265
+ grid
3266
+ ),
3267
+ children: [
3268
+ /* @__PURE__ */ jsx("span", { children: propertyHeading }),
3269
+ columns.map((c) => /* @__PURE__ */ jsx("span", { className: cn(c.highlight && cn(TINT, "-my-4 px-4 py-4 text-oca-accent-ink")), children: c.label }, c.key))
3270
+ ]
3271
+ }
3272
+ ),
3273
+ rows.map((r, ri) => /* @__PURE__ */ jsxs("li", { className: cn("grid grid-cols-1 gap-3 px-5 py-5", wide ? "lg:items-start lg:gap-5 lg:px-8" : "md:items-start md:gap-5 md:px-8", grid), children: [
3274
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
3275
+ /* @__PURE__ */ jsx("span", { className: "oca-title-sm", children: r.label }),
3276
+ r.note ? /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: r.note }) : null
3277
+ ] }),
3278
+ /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-2 gap-1", desk === "lg" ? "lg:contents" : "md:contents"), children: columns.map((c) => {
3279
+ return /* @__PURE__ */ jsxs(
3280
+ "div",
3281
+ {
3282
+ style: { "--oca-order": ordered.indexOf(c) },
3283
+ className: cn(
3284
+ // Two rows of the pair's grid (name, answer), so answers line up
3285
+ // across a pair even when one name wraps.
3286
+ "order-[var(--oca-order)] row-span-2 grid min-w-0 grid-rows-subgrid gap-1 rounded-xl px-3 py-2.5",
3287
+ 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",
3288
+ c.highlight ? cn(
3289
+ TINT,
3290
+ "col-span-2",
3291
+ 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"
3292
+ ) : desk === "lg" ? "lg:p-0" : "md:p-0"
3293
+ ),
3294
+ children: [
3295
+ /* @__PURE__ */ jsx(
3296
+ "span",
3297
+ {
3298
+ className: cn(
3299
+ "text-[0.8125rem]",
3300
+ c.highlight ? "text-oca-accent-ink" : "text-muted-foreground",
3301
+ desk === "lg" ? "lg:sr-only" : "md:sr-only"
3302
+ ),
3303
+ children: c.label
3304
+ }
3305
+ ),
3306
+ /* @__PURE__ */ jsx("span", { className: cn("text-[0.9375rem]", c.highlight && "font-medium"), children: r.values[c.key] ?? "\u2014" })
3307
+ ]
3308
+ },
3309
+ c.key
3310
+ );
3311
+ }) })
3312
+ ] }, ri))
3313
+ ] });
3314
+ }
3315
+ var CHECK = {
3316
+ ok: { word: "Passed", icon: /* @__PURE__ */ jsx(CircleCheck, {}), tone: "text-success" },
3317
+ fail: { word: "Failed", icon: /* @__PURE__ */ jsx(CircleX, {}), tone: "text-destructive" },
3318
+ pending: { word: "Pending", icon: /* @__PURE__ */ jsx(Clock, {}), tone: "text-oca-accent-ink" },
3319
+ skipped: { word: "Skipped", icon: /* @__PURE__ */ jsx(CircleMinus, {}), tone: "text-muted-foreground" },
3320
+ unchecked: { word: "Not checked", icon: /* @__PURE__ */ jsx(CircleDashed, {}), tone: "text-oca-subtle" }
3321
+ };
3322
+ function VerifyReport({
3323
+ verdict,
3324
+ title,
3325
+ summary,
3326
+ checks,
3327
+ facts,
3328
+ notChecked,
3329
+ actions,
3330
+ as: Heading = "h2",
3331
+ className
3332
+ }) {
3333
+ return /* @__PURE__ */ jsxs(
3334
+ "section",
3335
+ {
3336
+ "aria-label": "Verification result",
3337
+ className: cn("overflow-hidden rounded-[1.25rem] border border-border bg-card", className),
3338
+ children: [
3339
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col items-start gap-3 p-6 md:p-8", children: [
3340
+ /* @__PURE__ */ jsx(StatusBadge, { status: verdict }),
3341
+ /* @__PURE__ */ jsx(Heading, { className: "oca-display-3", children: title }),
3342
+ summary ? /* @__PURE__ */ jsx("p", { className: "oca-body max-w-[40rem]", children: summary }) : null
3343
+ ] }),
3344
+ /* @__PURE__ */ jsx("ul", { "aria-label": "Checks", className: "divide-y divide-border border-t border-border", children: checks.map((c, i) => {
3345
+ const k = CHECK[c.state];
3346
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-3 px-6 py-3.5 md:px-8", children: [
3347
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("mt-0.5 shrink-0 [&_svg]:size-[1.125rem]", k.tone), children: k.icon }),
3348
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5 sm:flex-row sm:items-baseline sm:justify-between sm:gap-6", children: [
3349
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
3350
+ /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem]", children: c.label }),
3351
+ c.note ? /* @__PURE__ */ jsx("span", { className: "break-words text-[0.8125rem] leading-snug text-muted-foreground", children: c.note }) : null
3352
+ ] }),
3353
+ /* @__PURE__ */ jsx(
3354
+ "span",
3355
+ {
3356
+ className: cn(
3357
+ "shrink-0 text-[0.8125rem]",
3358
+ c.state === "fail" ? "text-destructive" : "text-muted-foreground"
3359
+ ),
3360
+ children: k.word
3361
+ }
3362
+ )
3363
+ ] })
3364
+ ] }, i);
3365
+ }) }),
3366
+ facts && facts.length > 0 ? /* @__PURE__ */ jsx(KeyValueList, { items: facts, className: "rounded-none border-x-0 border-b-0 bg-transparent [&>div]:px-6 md:[&>div]:px-8" }) : null,
3367
+ notChecked && notChecked.length > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 border-t border-border bg-muted/50 px-6 py-5 md:px-8", children: [
3368
+ /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] font-medium", children: "What this did not check" }),
3369
+ /* @__PURE__ */ jsx("ul", { className: "flex list-disc flex-col gap-1 pl-5 text-[0.875rem] leading-relaxed text-muted-foreground", children: notChecked.map((n, i) => /* @__PURE__ */ jsx("li", { children: n }, i)) })
3370
+ ] }) : null,
3371
+ actions ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3 border-t border-border px-6 py-5 md:px-8", children: actions }) : null
3372
+ ]
3373
+ }
3374
+ );
3375
+ }
3376
+ function SignMessage({
3377
+ lead,
3378
+ address,
3379
+ message,
3380
+ wallets,
3381
+ busy = false,
3382
+ error,
3383
+ submitLabel = "Confirm",
3384
+ secondary,
3385
+ onSignature,
3386
+ className
3387
+ }) {
3388
+ const [pasted, setPasted] = useState("");
3389
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-5", className), children: [
3390
+ lead ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-relaxed", children: lead }) : null,
3391
+ wallets ? /* @__PURE__ */ jsxs(Fragment, { children: [
3392
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: wallets }),
3393
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[0.8125rem] text-muted-foreground", children: [
3394
+ /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" }),
3395
+ "or sign it in any wallet",
3396
+ /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
3397
+ ] })
3398
+ ] }) : null,
3399
+ /* @__PURE__ */ jsx(CodeBlock, { code: message, caption: "Message to sign" }),
3400
+ /* @__PURE__ */ jsxs(
3401
+ "form",
3402
+ {
3403
+ className: "flex flex-col gap-4",
3404
+ onSubmit: (e) => {
3405
+ e.preventDefault();
3406
+ if (pasted.trim()) onSignature(pasted.trim());
3407
+ },
3408
+ children: [
3409
+ /* @__PURE__ */ jsx(
3410
+ Field,
3411
+ {
3412
+ label: "Signature",
3413
+ error,
3414
+ hint: /* @__PURE__ */ jsxs(Fragment, { children: [
3415
+ "From your wallet\u2019s \u201Csign message\u201D (BIP-322), signed by",
3416
+ " ",
3417
+ /* @__PURE__ */ jsx("span", { className: "break-all font-mono", children: address }),
3418
+ "."
3419
+ ] }),
3420
+ children: /* @__PURE__ */ jsx(
3421
+ Textarea,
3422
+ {
3423
+ value: pasted,
3424
+ onChange: (e) => setPasted(e.target.value),
3425
+ rows: 3,
3426
+ spellCheck: false,
3427
+ className: "min-h-24 font-mono text-base md:text-[0.8125rem]"
3428
+ }
3429
+ )
3430
+ }
3431
+ ),
3432
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
3433
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading: busy, disabled: !pasted.trim(), children: submitLabel }),
3434
+ secondary
3435
+ ] })
3436
+ ]
3437
+ }
3438
+ )
3439
+ ] });
3440
+ }
3441
+ var isInternal = (href) => href.startsWith("/") || href.startsWith("#");
3442
+ function DocLink({ href, className, children, ...rest }) {
3443
+ return isInternal(href) ? /* @__PURE__ */ jsx(Link, { href, className, ...rest, children }) : /* @__PURE__ */ jsx("a", { href, className, ...rest, children });
3444
+ }
3445
+ function Breadcrumbs({ items, action, className }) {
3446
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-11 items-center justify-between gap-4 sm:min-h-0", className), children: [
3447
+ /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "min-w-0", children: /* @__PURE__ */ jsx("ol", { className: "flex min-w-0 items-center gap-1.5 text-[0.875rem] text-muted-foreground", children: items.map((c, i) => {
3448
+ const last = i === items.length - 1;
3449
+ return /* @__PURE__ */ jsxs("li", { className: cn("flex items-center gap-1.5", last ? "min-w-0" : "shrink-0"), children: [
3450
+ c.href && !last ? /* @__PURE__ */ 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__ */ jsx("span", { "aria-current": last ? "page" : void 0, className: cn("truncate", last && "text-foreground"), children: c.label }),
3451
+ !last ? /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }) : null
3452
+ ] }, i);
3453
+ }) }) }),
3454
+ action ? /* @__PURE__ */ jsx("div", { className: "shrink-0 text-[0.875rem]", children: action }) : null
3455
+ ] });
3456
+ }
3457
+ function DocsPager({ prev, next, className }) {
3458
+ if (!prev && !next) return null;
3459
+ const card = (l, dir) => /* @__PURE__ */ jsxs(
3460
+ DocLink,
3461
+ {
3462
+ href: l.href,
3463
+ className: cn(
3464
+ "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",
3465
+ dir === "next" && "items-end text-right sm:col-start-2"
3466
+ ),
3467
+ children: [
3468
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-[0.8125rem] text-muted-foreground", children: [
3469
+ dir === "prev" ? /* @__PURE__ */ jsx(ArrowLeft, { "aria-hidden": true, className: "size-3.5" }) : null,
3470
+ dir === "prev" ? "Previous" : "Next",
3471
+ l.section ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\xB7" }) : null,
3472
+ l.section ? /* @__PURE__ */ jsx("span", { className: "truncate", children: l.section }) : null,
3473
+ dir === "next" ? /* @__PURE__ */ jsx(ArrowRight, { "aria-hidden": true, className: "size-3.5" }) : null
3474
+ ] }),
3475
+ /* @__PURE__ */ jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: l.label })
3476
+ ]
3477
+ }
3478
+ );
3479
+ return /* @__PURE__ */ 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: [
3480
+ prev ? card(prev, "prev") : null,
3481
+ next ? card(next, "next") : null
3482
+ ] });
3483
+ }
3484
+ function useHeadings(selector = "#docs-content", key) {
3485
+ const [items, setItems] = useState([]);
3486
+ useEffect(() => {
3487
+ const read = () => {
3488
+ const root = document.querySelector(selector);
3489
+ if (!root) return setItems([]);
3490
+ setItems(
3491
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
3492
+ id: h.id,
3493
+ // The anchor link's "#" is not part of the name.
3494
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
3495
+ level: h.tagName === "H3" ? 3 : 2
3496
+ }))
3497
+ );
3498
+ };
3499
+ const raf = requestAnimationFrame(read);
3500
+ const t = setTimeout(read, 80);
3501
+ return () => {
3502
+ cancelAnimationFrame(raf);
3503
+ clearTimeout(t);
3504
+ };
3505
+ }, [selector, key]);
3506
+ const activeId = useActiveHeading(items.map((i) => i.id));
3507
+ return { items, activeId };
3508
+ }
3509
+ function OnThisPage({
3510
+ items,
3511
+ activeId,
3512
+ title = "On this page",
3513
+ onNavigate,
3514
+ className
3515
+ }) {
3516
+ const id = useId();
3517
+ if (items.length === 0) return null;
3518
+ return (
3519
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
3520
+ /* @__PURE__ */ jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
3521
+ title ? /* @__PURE__ */ jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
3522
+ /* @__PURE__ */ jsx("ul", { children: items.map((t) => {
3523
+ const on = t.id === activeId;
3524
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
3525
+ "a",
3526
+ {
3527
+ href: `#${t.id}`,
3528
+ onClick: onNavigate,
3529
+ "aria-current": on ? "location" : void 0,
3530
+ className: cn(
3531
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
3532
+ t.level === 3 ? "pl-7" : "pl-4",
3533
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
3534
+ ),
3535
+ children: t.label
3536
+ }
3537
+ ) }, t.id);
3538
+ }) })
3539
+ ] })
3540
+ );
3541
+ }
3542
+ var CALLOUT_TONE = { note: "neutral", warning: "brand", danger: "danger" };
3543
+ function Callout({
3544
+ tone = "note",
3545
+ title,
3546
+ children,
3547
+ className
3548
+ }) {
3549
+ return /* @__PURE__ */ jsx(
3550
+ Notice,
3551
+ {
3552
+ tone: CALLOUT_TONE[tone],
3553
+ title,
3554
+ role: "note",
3555
+ className: cn("my-6 [&_p]:my-0 [&_p]:text-[0.9375rem] [&_p]:leading-relaxed [&_p+p]:mt-3", className),
3556
+ children
3557
+ }
3558
+ );
3559
+ }
3560
+ function Step({ title, id, children }) {
3561
+ return /* @__PURE__ */ jsxs("li", { className: "relative pb-8 pl-11 last:pb-0 [counter-increment:oca-step]", children: [
3562
+ /* @__PURE__ */ jsx(
3563
+ "span",
3564
+ {
3565
+ "aria-hidden": true,
3566
+ 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)]"
3567
+ }
3568
+ ),
3569
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute bottom-1 left-[0.8125rem] top-9 w-px bg-border" }),
3570
+ /* @__PURE__ */ jsx("h3", { id, className: "scroll-mt-28 pt-0.5 text-[1.0625rem] font-medium leading-snug tracking-[-0.008em] text-foreground", children: title }),
3571
+ /* @__PURE__ */ jsx("div", { className: "mt-2 text-muted-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children })
3572
+ ] });
3573
+ }
3574
+ function Steps({ children, className }) {
3575
+ return /* @__PURE__ */ 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 });
3576
+ }
3577
+ function LinkCard({
3578
+ href,
3579
+ title,
3580
+ description,
3581
+ icon,
3582
+ meta,
3583
+ className
3584
+ }) {
3585
+ const Arrow = isInternal(href) ? ArrowRight : ArrowUpRight;
3586
+ return /* @__PURE__ */ jsxs(
3587
+ DocLink,
3588
+ {
3589
+ href,
3590
+ className: cn(
3591
+ "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",
3592
+ className
3593
+ ),
3594
+ children: [
3595
+ /* @__PURE__ */ jsxs("span", { className: "flex items-start justify-between gap-3", children: [
3596
+ icon ? /* @__PURE__ */ 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__ */ jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }),
3597
+ /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-2", children: [
3598
+ meta,
3599
+ /* @__PURE__ */ jsx(Arrow, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-hover:translate-x-0.5 group-hover:text-foreground" })
3600
+ ] })
3601
+ ] }),
3602
+ icon ? /* @__PURE__ */ jsx("span", { className: "text-[1rem] font-medium leading-snug text-foreground", children: title }) : null,
3603
+ description ? /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: description }) : null
3604
+ ]
3605
+ }
3606
+ );
3607
+ }
3608
+ function CardGrid({ columns = 2, children, className }) {
3609
+ return /* @__PURE__ */ 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 });
3610
+ }
3611
+ function MdxTable({ className, ...props }) {
3612
+ return /* @__PURE__ */ jsx("div", { className: "not-prose my-6 overflow-hidden rounded-2xl border border-border bg-card", children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsx(
3613
+ "table",
3614
+ {
3615
+ className: cn(
3616
+ "w-full border-collapse text-left text-[0.875rem] leading-relaxed",
3617
+ "[&_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",
3618
+ "[&_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",
3619
+ "[&_td_code]:bg-transparent [&_td_code]:p-0 [&_td_code]:text-foreground [&_td:first-child]:text-foreground",
3620
+ "[&_[align=center]]:text-center [&_[align=right]]:text-right",
3621
+ // On a phone a cell keeps a readable width; the table scrolls instead of crushing it.
3622
+ "max-sm:[&_td]:min-w-[9rem]",
3623
+ className
3624
+ ),
3625
+ ...props
3626
+ }
3627
+ ) }) });
3628
+ }
3629
+ function ApiTable({
3630
+ rows,
3631
+ caption,
3632
+ nameHeader = "Name",
3633
+ className
3634
+ }) {
3635
+ const hasDefault = rows.some((r) => r.default !== void 0);
3636
+ const marks = (r) => /* @__PURE__ */ jsxs(Fragment, { children: [
3637
+ r.required ? /* @__PURE__ */ jsx("span", { className: "text-[0.75rem] text-oca-accent-ink", children: "Required" }) : null,
3638
+ r.deprecated ? /* @__PURE__ */ jsx(Badge, { tone: "muted", children: "Deprecated" }) : null,
3639
+ r.status ? /* @__PURE__ */ jsx(StatusBadge, { status: r.status }) : null
3640
+ ] });
3641
+ return /* @__PURE__ */ jsxs("div", { className: cn("not-prose my-6", className), children: [
3642
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-2xl border border-border bg-card max-sm:hidden", children: /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-left text-[0.875rem]", children: [
3643
+ caption ? /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }) : null,
3644
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-oca-hairline-strong bg-oca-table-head text-[0.8125rem]", children: [
3645
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: nameHeader }),
3646
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Type" }),
3647
+ hasDefault ? /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Default" }) : null,
3648
+ /* @__PURE__ */ jsx("th", { scope: "col", className: "px-4 py-2.5 font-medium", children: "Description" })
3649
+ ] }) }),
3650
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-border", children: rows.map((r) => /* @__PURE__ */ jsxs("tr", { className: "align-top", children: [
3651
+ /* @__PURE__ */ jsx("th", { scope: "row", className: "px-4 py-3 text-left font-normal", children: /* @__PURE__ */ jsxs("span", { className: "flex flex-col items-start gap-1", children: [
3652
+ /* @__PURE__ */ jsx("code", { className: cn("font-mono text-[0.8125rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3653
+ marks(r)
3654
+ ] }) }),
3655
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.type ?? "\u2014" }),
3656
+ hasDefault ? /* @__PURE__ */ jsx("td", { className: "px-4 py-3 font-mono text-[0.8125rem] text-muted-foreground", children: r.default ?? "\u2014" }) : null,
3657
+ /* @__PURE__ */ jsx("td", { className: "px-4 py-3 leading-relaxed text-muted-foreground", children: r.description })
3658
+ ] }, r.name)) })
3659
+ ] }) }) }),
3660
+ /* @__PURE__ */ jsx("ul", { "aria-label": caption, className: "divide-y divide-border rounded-2xl border border-border bg-card sm:hidden", children: rows.map((r) => /* @__PURE__ */ jsxs("li", { className: "flex flex-col gap-1.5 px-4 py-3.5", children: [
3661
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
3662
+ /* @__PURE__ */ jsx("code", { className: cn("font-mono text-[0.875rem] text-foreground", r.deprecated && "line-through decoration-oca-subtle"), children: r.name }),
3663
+ r.type ? /* @__PURE__ */ jsx("code", { className: "break-all font-mono text-[0.8125rem] text-muted-foreground", children: r.type }) : null
3664
+ ] }),
3665
+ /* @__PURE__ */ jsx("span", { className: "flex flex-wrap items-center gap-2 empty:hidden", children: marks(r) }),
3666
+ r.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.875rem] leading-relaxed text-muted-foreground", children: r.description }) : null,
3667
+ r.default !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "text-[0.8125rem] text-muted-foreground", children: [
3668
+ "Default ",
3669
+ /* @__PURE__ */ jsx("code", { className: "font-mono text-foreground", children: r.default })
3670
+ ] }) : null
3671
+ ] }, r.name)) })
3672
+ ] });
3673
+ }
3674
+ function useDarkMode() {
3675
+ const [dark, setDark] = useState(false);
3676
+ useEffect(() => {
3677
+ const root = document.documentElement;
3678
+ const read = () => setDark(root.classList.contains("dark"));
3679
+ read();
3680
+ const mo = new MutationObserver(read);
3681
+ mo.observe(root, { attributes: true, attributeFilter: ["class"] });
3682
+ return () => mo.disconnect();
3683
+ }, []);
3684
+ return dark;
3685
+ }
3686
+ function mermaidTheme(el) {
3687
+ const css = getComputedStyle(el);
3688
+ const v = (name) => css.getPropertyValue(name).trim();
3689
+ const card = v("--card");
3690
+ const muted = v("--muted");
3691
+ const text = v("--foreground");
3692
+ const subtle = v("--muted-foreground");
3693
+ const line = v("--input");
3694
+ const hair = v("--oca-hairline-strong");
3695
+ return {
3696
+ background: "transparent",
3697
+ fontFamily: css.fontFamily,
3698
+ fontSize: "14px",
3699
+ textColor: text,
3700
+ mainBkg: card,
3701
+ primaryColor: card,
3702
+ primaryTextColor: text,
3703
+ primaryBorderColor: hair,
3704
+ secondaryColor: muted,
3705
+ secondaryTextColor: text,
3706
+ secondaryBorderColor: hair,
3707
+ tertiaryColor: muted,
3708
+ tertiaryTextColor: text,
3709
+ tertiaryBorderColor: hair,
3710
+ nodeBorder: hair,
3711
+ lineColor: line,
3712
+ edgeLabelBackground: card,
3713
+ clusterBkg: muted,
3714
+ clusterBorder: hair,
3715
+ titleColor: text,
3716
+ noteBkgColor: muted,
3717
+ noteTextColor: text,
3718
+ noteBorderColor: hair,
3719
+ actorBkg: card,
3720
+ actorBorder: hair,
3721
+ actorTextColor: text,
3722
+ actorLineColor: line,
3723
+ signalColor: text,
3724
+ signalTextColor: text,
3725
+ labelBoxBkgColor: card,
3726
+ labelBoxBorderColor: hair,
3727
+ labelTextColor: text,
3728
+ loopTextColor: subtle,
3729
+ activationBkgColor: muted,
3730
+ activationBorderColor: hair,
3731
+ sequenceNumberColor: card
3732
+ };
3733
+ }
3734
+ function naturalSize(svg) {
3735
+ const w = svg.match(/viewBox="[\d.-]+ [\d.-]+ ([\d.]+) [\d.]+"/)?.[1];
3736
+ if (!w) return svg;
3737
+ return svg.replace(/<svg([^>]*?)\swidth="100%"/, `<svg$1 width="${Math.ceil(Number(w))}"`).replace(/max-width:\s*[\d.]+px;?/, "");
3738
+ }
3739
+ function Diagram({ chart, caption, load, className }) {
3740
+ const ref = useRef(null);
3741
+ const dark = useDarkMode();
3742
+ const raw = useId();
3743
+ const [svg, setSvg] = useState(null);
3744
+ const [failed, setFailed] = useState(false);
3745
+ useEffect(() => {
3746
+ let live = true;
3747
+ const el = ref.current;
3748
+ if (!el) return;
3749
+ (async () => {
3750
+ try {
3751
+ const mod = await load();
3752
+ const mermaid = "default" in mod ? mod.default : mod;
3753
+ mermaid.initialize({ startOnLoad: false, securityLevel: "strict", theme: "base", themeVariables: mermaidTheme(el) });
3754
+ const { svg: drawn } = await mermaid.render(`oca-diagram-${raw.replace(/[^a-zA-Z0-9]/g, "")}-${dark ? "d" : "l"}`, chart);
3755
+ if (live) {
3756
+ setSvg(naturalSize(drawn));
3757
+ setFailed(false);
3758
+ }
3759
+ } catch {
3760
+ if (live) setFailed(true);
3761
+ }
3762
+ })();
3763
+ return () => {
3764
+ live = false;
3765
+ };
3766
+ }, [chart, dark, load, raw]);
3767
+ if (failed) return /* @__PURE__ */ jsx(CodeBlock, { code: chart, caption: "Diagram (shown as its source)", className: cn("my-6", className) });
3768
+ return /* @__PURE__ */ jsxs("figure", { ref, className: cn("not-prose my-6 overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children: [
3769
+ svg ? /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--card)", children: /* @__PURE__ */ jsx(
3770
+ "div",
3771
+ {
3772
+ className: "flex w-max min-w-full justify-center p-6 [&_svg]:h-auto [&_svg]:max-w-none",
3773
+ role: "img",
3774
+ "aria-label": typeof caption === "string" ? caption : "Diagram",
3775
+ dangerouslySetInnerHTML: { __html: svg }
3776
+ }
3777
+ ) }) : /* @__PURE__ */ jsx("div", { role: "status", "aria-label": "Drawing the diagram", className: "p-6", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-40 w-full rounded-xl" }) }),
3778
+ caption ? /* @__PURE__ */ jsx("figcaption", { className: "border-t border-border px-5 py-3 text-[0.8125rem] text-muted-foreground", children: caption }) : null
3779
+ ] });
3780
+ }
3781
+ var HEADING = {
3782
+ h1: "oca-display-3 mb-4 text-foreground",
3783
+ h2: "mb-3 mt-12 text-[1.375rem] font-medium leading-tight tracking-[-0.015em] text-foreground md:text-[1.5rem]",
3784
+ h3: "mb-2 mt-9 text-[1.125rem] font-medium leading-snug tracking-[-0.01em] text-foreground",
3785
+ h4: "mb-2 mt-7 text-[1rem] font-medium leading-snug text-foreground"
3786
+ };
3787
+ function DocsHeading({
3788
+ as: Tag,
3789
+ id,
3790
+ children,
3791
+ className,
3792
+ ...props
3793
+ }) {
3794
+ return /* @__PURE__ */ jsxs(Tag, { id, className: cn("group scroll-mt-28", HEADING[Tag], className), ...props, children: [
3795
+ /* @__PURE__ */ jsx("span", { "data-heading-text": "", children }),
3796
+ id && Tag !== "h1" ? /* @__PURE__ */ jsxs(
3797
+ "a",
3798
+ {
3799
+ href: `#${id}`,
3800
+ 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",
3801
+ children: [
3802
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "#" }),
3803
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Link to this section" })
3804
+ ]
3805
+ }
3806
+ ) : null
3807
+ ] });
3808
+ }
3809
+ function useMacKeys() {
3810
+ const [mac, setMac] = useState(true);
3811
+ useEffect(() => {
3812
+ setMac(/Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent));
3813
+ }, []);
3814
+ return mac;
3815
+ }
3816
+ var typing = (el) => el instanceof HTMLElement && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName));
3817
+ var SearchButton = forwardRef(function SearchButton2({ label = "Search", onClick, className }, ref) {
3818
+ const mac = useMacKeys();
3819
+ return /* @__PURE__ */ jsxs(
3820
+ "button",
3821
+ {
3822
+ ref,
3823
+ type: "button",
3824
+ onClick,
3825
+ "aria-keyshortcuts": mac ? "Meta+K" : "Control+K",
3826
+ className: cn(
3827
+ "inline-flex size-10 items-center justify-center gap-2 rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
3828
+ "md:h-10 md:w-56 md:justify-start md:border md:border-border md:bg-card md:pl-3.5 md:pr-2 md:hover:border-oca-hairline-strong md:hover:bg-card",
3829
+ className
3830
+ ),
3831
+ children: [
3832
+ /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-[1.125rem] shrink-0 md:size-4" }),
3833
+ /* @__PURE__ */ jsx("span", { className: "sr-only flex-1 text-left text-[0.9375rem] md:not-sr-only", children: label }),
3834
+ /* @__PURE__ */ jsx(Kbd, { "aria-hidden": true, className: "hidden md:inline-flex", children: mac ? "\u2318K" : "Ctrl K" })
3835
+ ]
3836
+ }
3837
+ );
3838
+ });
3839
+ function SearchDialog({
3840
+ onQuery,
3841
+ open: openProp,
3842
+ onOpenChange,
3843
+ onSelect,
3844
+ button = true,
3845
+ hotkey = true,
3846
+ label = "Search",
3847
+ placeholder = "Search the docs",
3848
+ idle,
3849
+ defaultQuery = "",
3850
+ debounceMs = 120,
3851
+ className
3852
+ }) {
3853
+ const [own, setOwn] = useState(false);
3854
+ const open = openProp ?? own;
3855
+ const setOpen = (v) => {
3856
+ if (openProp === void 0) setOwn(v);
3857
+ onOpenChange?.(v);
3858
+ };
3859
+ const [query, setQuery] = useState(defaultQuery);
3860
+ const [groups, setGroups] = useState([]);
3861
+ const [state, setState] = useState("idle");
3862
+ const [active, setActive] = useState(0);
3863
+ const listId = useId();
3864
+ const listRef = useRef(null);
3865
+ const buttonRef = useRef(null);
3866
+ const returnTo = useRef(null);
3867
+ const flat = useMemo(() => groups.flatMap((g) => g.results), [groups]);
3868
+ const latest = useRef({ open, setOpen, onQuery });
3869
+ latest.current = { open, setOpen, onQuery };
3870
+ useEffect(() => {
3871
+ if (!hotkey) return;
3872
+ const onKey = (e) => {
3873
+ const { open: isOpen, setOpen: set } = latest.current;
3874
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
3875
+ e.preventDefault();
3876
+ set(!isOpen);
3877
+ } else if (e.key === "/" && !isOpen && !typing(e.target)) {
3878
+ e.preventDefault();
3879
+ set(true);
3880
+ }
3881
+ };
3882
+ window.addEventListener("keydown", onKey);
3883
+ return () => window.removeEventListener("keydown", onKey);
3884
+ }, [hotkey]);
3885
+ useEffect(() => {
3886
+ const q = query.trim();
3887
+ if (!q) {
3888
+ setGroups([]);
3889
+ setState("idle");
3890
+ return;
3891
+ }
3892
+ const ctl = new AbortController();
3893
+ setState("loading");
3894
+ const t = setTimeout(async () => {
3895
+ try {
3896
+ const out = await latest.current.onQuery(q, ctl.signal);
3897
+ if (ctl.signal.aborted) return;
3898
+ setGroups(out.filter((g) => g.results.length > 0));
3899
+ setActive(0);
3900
+ setState("done");
3901
+ } catch {
3902
+ if (!ctl.signal.aborted) setState("error");
3903
+ }
3904
+ }, debounceMs);
3905
+ return () => {
3906
+ clearTimeout(t);
3907
+ ctl.abort();
3908
+ };
3909
+ }, [query, debounceMs]);
3910
+ useEffect(() => {
3911
+ listRef.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
3912
+ }, [active]);
3913
+ const choose = (r) => {
3914
+ setOpen(false);
3915
+ if (onSelect) onSelect(r);
3916
+ else window.location.assign(r.href);
3917
+ };
3918
+ const optionId = (i) => `${listId}-o${i}`;
3919
+ const showList = state === "done" && flat.length > 0;
3920
+ let index = -1;
3921
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3922
+ button ? /* @__PURE__ */ jsx(SearchButton, { ref: buttonRef, label, onClick: () => setOpen(true), className }) : null,
3923
+ /* @__PURE__ */ jsx(DialogPrimitive.Root, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
3924
+ /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "oca-animate-fade fixed inset-0 z-50 bg-[rgb(10_10_10/0.38)] backdrop-blur-[2px]" }),
3925
+ /* @__PURE__ */ jsxs(
3926
+ DialogPrimitive.Content,
3927
+ {
3928
+ "aria-describedby": void 0,
3929
+ onOpenAutoFocus: () => {
3930
+ const el = document.activeElement;
3931
+ returnTo.current = el instanceof HTMLElement && el !== document.body ? el : null;
3932
+ },
3933
+ onCloseAutoFocus: (e) => {
3934
+ const back = returnTo.current?.isConnected ? returnTo.current : buttonRef.current;
3935
+ if (back) {
3936
+ e.preventDefault();
3937
+ back.focus();
3938
+ }
3939
+ },
3940
+ className: "oca-animate-rise fixed left-1/2 top-3 z-50 flex max-h-[calc(100dvh-1.5rem)] w-[calc(100vw-1.5rem)] -translate-x-1/2 flex-col overflow-hidden rounded-[1.5rem] border border-border bg-popover text-popover-foreground shadow-xl outline-none sm:top-[12vh] sm:max-h-[min(36rem,76vh)] sm:w-[min(92vw,40rem)]",
3941
+ children: [
3942
+ /* @__PURE__ */ jsx(DialogPrimitive.Title, { className: "sr-only", children: label }),
3943
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 shrink-0 items-center gap-3 border-b border-border pl-5 pr-3", children: [
3944
+ state === "loading" ? /* @__PURE__ */ jsx(Spinner, { className: "size-[1.125rem] text-muted-foreground" }) : /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-[1.125rem] shrink-0 text-muted-foreground" }),
3945
+ /* @__PURE__ */ jsx(
3946
+ "input",
3947
+ {
3948
+ autoFocus: true,
3949
+ value: query,
3950
+ onChange: (e) => setQuery(e.target.value),
3951
+ onKeyDown: (e) => {
3952
+ if (!showList) return;
3953
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
3954
+ e.preventDefault();
3955
+ const d = e.key === "ArrowDown" ? 1 : -1;
3956
+ setActive((a) => (a + d + flat.length) % flat.length);
3957
+ } else if (e.key === "Enter" && flat[active]) {
3958
+ e.preventDefault();
3959
+ choose(flat[active]);
3960
+ }
3961
+ },
3962
+ placeholder,
3963
+ role: "combobox",
3964
+ "aria-label": label,
3965
+ "aria-expanded": showList,
3966
+ "aria-controls": listId,
3967
+ "aria-autocomplete": "list",
3968
+ "aria-activedescendant": showList ? optionId(active) : void 0,
3969
+ spellCheck: false,
3970
+ autoComplete: "off",
3971
+ className: "h-full min-w-0 flex-1 bg-transparent text-base text-foreground outline-none placeholder:text-oca-subtle"
3972
+ }
3973
+ ),
3974
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "inline-flex h-8 shrink-0 items-center rounded-md border border-border px-2 text-[0.75rem] text-muted-foreground transition-colors hover:text-foreground", children: [
3975
+ /* @__PURE__ */ jsx("span", { className: "sm:hidden", children: "Close" }),
3976
+ /* @__PURE__ */ jsx("span", { className: "max-sm:hidden", "aria-hidden": true, children: "Esc" }),
3977
+ /* @__PURE__ */ jsx("span", { className: "sr-only max-sm:hidden", children: "Close search" })
3978
+ ] })
3979
+ ] }),
3980
+ /* @__PURE__ */ jsxs("div", { ref: listRef, className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-2", children: [
3981
+ /* @__PURE__ */ jsx("div", { id: listId, role: "listbox", "aria-label": "Results", className: cn(!showList && "hidden"), children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-label": typeof g.label === "string" ? g.label : void 0, className: "pb-1", children: [
3982
+ /* @__PURE__ */ jsx("p", { "aria-hidden": true, className: "px-3 pb-1.5 pt-3 text-[0.8125rem] text-muted-foreground", children: g.label }),
3983
+ g.results.map((r) => {
3984
+ index++;
3985
+ const i = index;
3986
+ const on = i === active;
3987
+ return /* @__PURE__ */ jsxs(
3988
+ "a",
3989
+ {
3990
+ id: optionId(i),
3991
+ href: r.href,
3992
+ role: "option",
3993
+ "aria-selected": on,
3994
+ tabIndex: -1,
3995
+ onMouseMove: () => setActive(i),
3996
+ onClick: (e) => {
3997
+ if (e.metaKey || e.ctrlKey || e.shiftKey) return;
3998
+ e.preventDefault();
3999
+ choose(r);
4000
+ },
4001
+ className: cn(
4002
+ "flex items-start gap-3 rounded-xl px-3 py-2.5 transition-colors",
4003
+ on ? "bg-accent" : "hover:bg-accent"
4004
+ ),
4005
+ children: [
4006
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
4007
+ /* @__PURE__ */ jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: r.title }),
4008
+ r.section ? /* @__PURE__ */ jsx("span", { className: "truncate text-[0.8125rem] text-muted-foreground", children: r.section }) : null,
4009
+ r.excerptHtml ? /* @__PURE__ */ jsx(
4010
+ "span",
4011
+ {
4012
+ className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground [&_mark]:rounded-sm [&_mark]:bg-[color-mix(in_oklab,var(--oca-orange)_22%,transparent)] [&_mark]:px-0.5 [&_mark]:text-foreground",
4013
+ dangerouslySetInnerHTML: { __html: r.excerptHtml }
4014
+ }
4015
+ ) : r.excerpt ? /* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground", children: r.excerpt }) : null
4016
+ ] }),
4017
+ /* @__PURE__ */ jsx(CornerDownLeft, { "aria-hidden": true, className: cn("mt-1 size-4 shrink-0 text-muted-foreground", !on && "invisible") })
4018
+ ]
4019
+ },
4020
+ r.id
4021
+ );
4022
+ })
4023
+ ] }, gi)) }),
4024
+ state === "idle" ? /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: idle ?? "Type a word: a protocol, a function, an error." }) : null,
4025
+ state === "done" && flat.length === 0 ? /* @__PURE__ */ jsxs("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: [
4026
+ "No results for \u201C",
4027
+ query.trim(),
4028
+ "\u201D."
4029
+ ] }) : null,
4030
+ state === "error" ? /* @__PURE__ */ jsx("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: "Search is not available right now. Try again in a moment." }) : null
4031
+ ] }),
4032
+ /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: "hidden shrink-0 items-center gap-4 border-t border-border px-5 py-2.5 text-[0.75rem] text-muted-foreground sm:flex", children: [
4033
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
4034
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2191" }),
4035
+ /* @__PURE__ */ jsx(Kbd, { children: "\u2193" }),
4036
+ " to move"
4037
+ ] }),
4038
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
4039
+ /* @__PURE__ */ jsx(Kbd, { children: "\u21B5" }),
4040
+ " to open"
4041
+ ] }),
4042
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
4043
+ /* @__PURE__ */ jsx(Kbd, { children: "esc" }),
4044
+ " to close"
4045
+ ] })
4046
+ ] }),
4047
+ /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", children: state === "done" ? `${flat.length} result${flat.length === 1 ? "" : "s"}` : "" })
4048
+ ]
4049
+ }
4050
+ )
4051
+ ] }) })
4052
+ ] });
4053
+ }
4054
+ function pretty(content) {
4055
+ try {
4056
+ return JSON.stringify(JSON.parse(content), null, 2);
4057
+ } catch {
4058
+ return null;
4059
+ }
4060
+ }
4061
+ function download(content, filename, mime) {
4062
+ const url = URL.createObjectURL(new Blob([content], { type: mime }));
4063
+ const a = document.createElement("a");
4064
+ a.href = url;
4065
+ a.download = filename;
4066
+ document.body.appendChild(a);
4067
+ a.click();
4068
+ a.remove();
4069
+ setTimeout(() => URL.revokeObjectURL(url), 0);
4070
+ }
4071
+ var BAR_BUTTON = "inline-flex h-7 items-center gap-1.5 rounded-full px-2.5 text-[0.75rem] text-oca-ink-subtle transition-colors hover:bg-white/10 hover:text-white";
4072
+ function ArtifactView({
4073
+ content,
4074
+ title,
4075
+ filename,
4076
+ mime,
4077
+ defaultView = "formatted",
4078
+ maxLines = 28,
4079
+ className
4080
+ }) {
4081
+ const formatted = useMemo(() => pretty(content), [content]);
4082
+ const [view, setView] = useState(formatted ? defaultView : "raw");
4083
+ const shown = view === "formatted" && formatted ? formatted : content;
4084
+ const json = formatted !== null;
4085
+ return /* @__PURE__ */ jsx(
4086
+ CodeBlock,
4087
+ {
4088
+ code: shown,
4089
+ lang: json ? "json" : void 0,
4090
+ caption: title,
4091
+ maxLines,
4092
+ className,
4093
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
4094
+ json ? /* @__PURE__ */ jsx("span", { role: "group", "aria-label": "View", className: "mr-1 flex items-center rounded-full bg-white/[0.06] p-0.5", children: ["formatted", "raw"].map((v) => /* @__PURE__ */ jsx(
4095
+ "button",
4096
+ {
4097
+ type: "button",
4098
+ "aria-pressed": view === v,
4099
+ onClick: () => setView(v),
4100
+ className: cn(
4101
+ "h-7 rounded-full px-2.5 text-[0.75rem] transition-colors",
4102
+ view === v ? "bg-white/[0.12] text-white" : "text-oca-ink-subtle hover:text-white"
4103
+ ),
4104
+ children: v === "formatted" ? "Formatted" : "Raw"
4105
+ },
4106
+ v
4107
+ )) }) : null,
4108
+ filename ? /* @__PURE__ */ jsxs(
4109
+ "button",
4110
+ {
4111
+ type: "button",
4112
+ onClick: () => download(content, filename, mime ?? (json ? "application/json" : "text/plain")),
4113
+ className: BAR_BUTTON,
4114
+ "aria-label": `Download ${filename}`,
4115
+ children: [
4116
+ /* @__PURE__ */ jsx(Download, { "aria-hidden": true, className: "size-3.5" }),
4117
+ /* @__PURE__ */ jsx("span", { className: "max-sm:hidden", children: "Download" })
4118
+ ]
4119
+ }
4120
+ ) : null
4121
+ ] })
4122
+ }
4123
+ );
4124
+ }
4125
+ function DropZone({
4126
+ onFile,
4127
+ onText,
4128
+ accept,
4129
+ title = "Drop a file here, or choose one",
4130
+ hint,
4131
+ privacy = "It stays in your browser. Only its hash leaves this page.",
4132
+ file,
4133
+ progress,
4134
+ progressLabel = "Hashing",
4135
+ onClear,
4136
+ error,
4137
+ disabled = false,
4138
+ className
4139
+ }) {
4140
+ const input = useRef(null);
4141
+ const [over, setOver] = useState(false);
4142
+ const depth = useRef(0);
4143
+ const [mode, setMode] = useState("file");
4144
+ const [text, setText] = useState("");
4145
+ const errorId = useId();
4146
+ const titleId = useId();
4147
+ const busy = progress !== null && progress !== void 0;
4148
+ const pct = busy ? Math.round(Math.max(0, Math.min(1, progress)) * 100) : 0;
4149
+ const take = (f) => {
4150
+ if (f && !disabled) onFile(f);
4151
+ };
4152
+ const privacyLine = privacy === null ? null : /* @__PURE__ */ jsxs("p", { className: "flex items-start gap-2 text-[0.8125rem] leading-snug text-muted-foreground", children: [
4153
+ /* @__PURE__ */ jsx(Lock, { "aria-hidden": true, className: "mt-0.5 size-3.5 shrink-0" }),
4154
+ /* @__PURE__ */ jsx("span", { children: privacy })
4155
+ ] });
4156
+ if (mode === "text" && onText) {
4157
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
4158
+ /* @__PURE__ */ jsx(
4159
+ Textarea,
4160
+ {
4161
+ value: text,
4162
+ onChange: (e) => setText(e.target.value),
4163
+ rows: 6,
4164
+ "aria-label": "Text",
4165
+ "aria-describedby": error ? errorId : void 0,
4166
+ "aria-invalid": error ? true : void 0,
4167
+ placeholder: "Paste the text here",
4168
+ className: "font-mono text-base md:text-[0.875rem]"
4169
+ }
4170
+ ),
4171
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
4172
+ /* @__PURE__ */ jsx(Button, { size: "sm", disabled: !text.trim() || disabled, onClick: () => onText(text), children: "Use this text" }),
4173
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", onClick: () => setMode("file"), children: "Choose a file instead" })
4174
+ ] }),
4175
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] text-destructive", children: error }) : null,
4176
+ privacyLine
4177
+ ] });
4178
+ }
4179
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
4180
+ /* @__PURE__ */ jsxs(
4181
+ "div",
4182
+ {
4183
+ role: "group",
4184
+ "aria-labelledby": titleId,
4185
+ "aria-describedby": error ? errorId : void 0,
4186
+ "aria-busy": busy || void 0,
4187
+ onDragEnter: (e) => {
4188
+ e.preventDefault();
4189
+ depth.current++;
4190
+ if (!disabled) setOver(true);
4191
+ },
4192
+ onDragOver: (e) => e.preventDefault(),
4193
+ onDragLeave: () => {
4194
+ depth.current = Math.max(0, depth.current - 1);
4195
+ if (depth.current === 0) setOver(false);
4196
+ },
4197
+ onDrop: (e) => {
4198
+ e.preventDefault();
4199
+ depth.current = 0;
4200
+ setOver(false);
4201
+ take(e.dataTransfer.files?.[0]);
4202
+ },
4203
+ className: cn(
4204
+ "relative flex flex-col gap-3 rounded-[1.25rem] border border-dashed transition-colors",
4205
+ file ? "px-4 py-4 sm:px-5" : "items-center px-5 py-8 text-center md:py-10",
4206
+ over ? "border-foreground bg-accent" : "border-oca-hairline-strong bg-card",
4207
+ error && "border-destructive",
4208
+ disabled && "opacity-55"
4209
+ ),
4210
+ children: [
4211
+ /* @__PURE__ */ jsx(
4212
+ "input",
4213
+ {
4214
+ ref: input,
4215
+ type: "file",
4216
+ accept,
4217
+ disabled,
4218
+ tabIndex: -1,
4219
+ "aria-hidden": true,
4220
+ className: "sr-only",
4221
+ onChange: (e) => {
4222
+ take(e.target.files?.[0]);
4223
+ e.target.value = "";
4224
+ }
4225
+ }
4226
+ ),
4227
+ file ? /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-3", children: [
4228
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
4229
+ /* @__PURE__ */ jsx("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground", children: busy ? /* @__PURE__ */ jsx(FileText, { "aria-hidden": true, className: "size-5" }) : /* @__PURE__ */ jsx(Check, { "aria-hidden": true, className: "size-5" }) }),
4230
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
4231
+ /* @__PURE__ */ jsx("span", { id: titleId, className: "truncate text-[0.9375rem] font-medium", title: file.name, children: file.name }),
4232
+ /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] text-muted-foreground", children: [formatBytes(file.size), file.type].filter(Boolean).join(" \xB7 ") })
4233
+ ] }),
4234
+ !busy && onClear ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", onClick: onClear, disabled, className: "shrink-0", children: "Choose another" }) : null
4235
+ ] }),
4236
+ busy ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4237
+ /* @__PURE__ */ jsx(
4238
+ "div",
4239
+ {
4240
+ role: "progressbar",
4241
+ "aria-valuemin": 0,
4242
+ "aria-valuemax": 100,
4243
+ "aria-valuenow": pct,
4244
+ "aria-label": typeof progressLabel === "string" ? progressLabel : "Progress",
4245
+ className: "h-1.5 overflow-hidden rounded-full bg-muted",
4246
+ children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-full bg-foreground transition-[width] duration-200", style: { width: `${pct}%` } })
4247
+ }
4248
+ ),
4249
+ /* @__PURE__ */ jsxs("span", { className: "text-[0.8125rem] text-muted-foreground oca-tabular", children: [
4250
+ progressLabel,
4251
+ " ",
4252
+ pct,
4253
+ "%"
4254
+ ] })
4255
+ ] }) : null
4256
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4257
+ /* @__PURE__ */ jsx("span", { className: "flex size-11 items-center justify-center rounded-full bg-muted text-foreground", children: /* @__PURE__ */ jsx(Upload, { "aria-hidden": true, className: "size-5" }) }),
4258
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
4259
+ /* @__PURE__ */ jsx("p", { id: titleId, className: "text-[1rem] font-medium", children: over ? "Drop it to add it" : title }),
4260
+ hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] text-muted-foreground", children: hint }) : null
4261
+ ] }),
4262
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap items-center justify-center gap-2", children: [
4263
+ /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", disabled, onClick: () => input.current?.click(), children: "Choose a file" }),
4264
+ onText ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", disabled, onClick: () => setMode("text"), children: "Paste text instead" }) : null
4265
+ ] })
4266
+ ] })
4267
+ ]
4268
+ }
4269
+ ),
4270
+ error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] text-destructive", children: error }) : null,
4271
+ privacyLine
4272
+ ] });
4273
+ }
4274
+ function FormSection({
4275
+ n,
4276
+ title,
4277
+ hint,
4278
+ status,
4279
+ action,
4280
+ as: Heading = "h2",
4281
+ id,
4282
+ children,
4283
+ className
4284
+ }) {
4285
+ const titleId = useId();
4286
+ const tight = useDensity() === "compact";
4287
+ return /* @__PURE__ */ jsxs(
4288
+ "section",
4289
+ {
4290
+ id,
4291
+ "aria-labelledby": titleId,
4292
+ "aria-current": status === "current" ? "step" : void 0,
4293
+ className: cn("scroll-mt-24 rounded-[1.25rem] border border-border bg-card", className),
4294
+ children: [
4295
+ /* @__PURE__ */ jsxs("header", { className: cn("flex items-start gap-3.5", tight ? "px-5 pt-5" : "px-6 pt-6"), children: [
4296
+ n !== void 0 ? /* @__PURE__ */ jsx(
4297
+ "span",
4298
+ {
4299
+ "aria-hidden": true,
4300
+ className: cn(
4301
+ "mt-px flex size-7 shrink-0 items-center justify-center rounded-full border text-[0.8125rem] oca-tabular",
4302
+ status === "done" && "border-primary bg-primary text-primary-foreground",
4303
+ status === "current" && "border-brand text-oca-accent-ink",
4304
+ status === "blocked" && "border-destructive text-destructive",
4305
+ (status === "upcoming" || status === void 0) && "border-oca-hairline-strong text-muted-foreground"
4306
+ ),
4307
+ children: status === "done" ? /* @__PURE__ */ jsx(Check, { className: "size-3.5", strokeWidth: 3 }) : n
4308
+ }
4309
+ ) : null,
4310
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
4311
+ /* @__PURE__ */ jsxs(Heading, { id: titleId, className: "text-[1.0625rem] font-medium leading-snug tracking-[-0.008em]", children: [
4312
+ n !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
4313
+ "Step ",
4314
+ n,
4315
+ ": "
4316
+ ] }) : null,
4317
+ title,
4318
+ status === "done" ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (done)" }) : null
4319
+ ] }),
4320
+ hint ? /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: hint }) : null
4321
+ ] }),
4322
+ action ? /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }) : null
4323
+ ] }),
4324
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", tight ? "gap-4 p-5" : "gap-5 p-6", n !== void 0 && (tight ? "sm:pl-[3.875rem]" : "sm:pl-[4.125rem]")), children })
4325
+ ]
4326
+ }
4327
+ );
4328
+ }
4329
+ var STATE_TONE = { good: "success", attention: "brand", bad: "danger", neutral: "neutral", quiet: "muted" };
4330
+ function StateBadge({
4331
+ tone = "neutral",
4332
+ children,
4333
+ title,
4334
+ className
4335
+ }) {
4336
+ return /* @__PURE__ */ jsx(Badge, { tone: STATE_TONE[tone], title, className, children });
4337
+ }
4338
+ function createStateBadge(states) {
4339
+ function ProtocolStateBadge({ state, className }) {
4340
+ const def = states[state];
4341
+ if (!def) {
4342
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
4343
+ console.warn(`StateBadge: no state "${state}"; known: ${Object.keys(states).join(", ")}`);
4344
+ }
4345
+ return /* @__PURE__ */ jsx(StateBadge, { className, children: String(state) });
4346
+ }
4347
+ return /* @__PURE__ */ jsx(StateBadge, { tone: def.tone, title: def.hint, className, children: def.label });
4348
+ }
4349
+ return ProtocolStateBadge;
4350
+ }
4351
+ function BlockHeight({
4352
+ height,
4353
+ label = false,
4354
+ link = true,
4355
+ network = "mainnet",
4356
+ className
4357
+ }) {
4358
+ const text = `${label ? "block " : ""}${formatBlockHeight(height)}`;
4359
+ if (!link) return /* @__PURE__ */ jsx("span", { className: cn("oca-tabular", className), children: text });
4360
+ return /* @__PURE__ */ jsxs(
4361
+ "a",
4362
+ {
4363
+ href: explorerUrl("block", Math.trunc(height), network),
4364
+ target: "_blank",
4365
+ rel: "noreferrer",
4366
+ title: `Block ${formatBlockHeight(height)} on mempool.space`,
4367
+ className: cn("oca-tabular underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground", className),
4368
+ children: [
4369
+ text,
4370
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " (opens mempool.space in a new tab)" })
4371
+ ]
4372
+ }
4373
+ );
4374
+ }
4375
+ var ANCHOR = {
4376
+ anchored: { label: "Anchored", tone: "good" },
4377
+ pending: { label: "Anchor pending", tone: "attention" },
4378
+ unverified: { label: "Not checked", tone: "quiet" },
4379
+ none: { label: "Not anchored", tone: "quiet" },
4380
+ fail: { label: "Does not check out", tone: "bad" }
4381
+ };
4382
+ function hostOf(url) {
4383
+ try {
4384
+ return new URL(url).host;
4385
+ } catch {
4386
+ return url;
4387
+ }
4388
+ }
4389
+ function AnchorStatus({
4390
+ state,
4391
+ blockHeight,
4392
+ blockTime,
4393
+ submittedAt,
4394
+ calendar,
4395
+ message,
4396
+ network = "mainnet",
4397
+ variant = "detail",
4398
+ className
4399
+ }) {
4400
+ const def = ANCHOR[state];
4401
+ const block = blockHeight !== void 0 ? /* @__PURE__ */ jsx(BlockHeight, { height: blockHeight, label: true, network }) : null;
4402
+ const line = message ?? (state === "anchored" ? block ? /* @__PURE__ */ jsxs(Fragment, { children: [
4403
+ "In ",
4404
+ block,
4405
+ blockTime !== void 0 ? ` \xB7 ${formatUtc(blockTime)}` : null
4406
+ ] }) : "Its hash is in a Bitcoin block." : state === "pending" ? /* @__PURE__ */ jsxs(Fragment, { children: [
4407
+ "Submitted",
4408
+ submittedAt !== void 0 ? ` ${formatUtc(submittedAt)}` : "",
4409
+ " to",
4410
+ " ",
4411
+ calendar ? hostOf(calendar) : "an OpenTimestamps calendar",
4412
+ ". Waiting for a Bitcoin block."
4413
+ ] }) : state === "unverified" ? /* @__PURE__ */ jsxs(Fragment, { children: [
4414
+ "The proof names ",
4415
+ block ?? "a block",
4416
+ ", but its header could not be fetched to check it."
4417
+ ] }) : state === "fail" ? /* @__PURE__ */ jsxs(Fragment, { children: [
4418
+ "The proof does not lead to ",
4419
+ block ?? "the block it names",
4420
+ "."
4421
+ ] }) : "No timestamp yet. The signature still checks offline.");
4422
+ if (variant === "badge") {
4423
+ const plain = typeof line === "string" ? line : void 0;
4424
+ return /* @__PURE__ */ jsx(StateBadge, { tone: def.tone, title: plain, className, children: def.label });
4425
+ }
4426
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-start gap-1.5", className), children: [
4427
+ /* @__PURE__ */ jsx(StateBadge, { tone: def.tone, children: def.label }),
4428
+ /* @__PURE__ */ jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: line })
4429
+ ] });
4430
+ }
4431
+ function BlockCountdown({
4432
+ target,
4433
+ tip,
4434
+ from,
4435
+ reached = "Reached",
4436
+ minutesPerBlock = 10,
4437
+ network = "mainnet",
4438
+ className
4439
+ }) {
4440
+ const known = typeof tip === "number";
4441
+ const left = known ? target - tip : null;
4442
+ const done = left !== null && left <= 0;
4443
+ const share = known && from !== void 0 && target > from ? Math.min(1, Math.max(0, (tip - from) / (target - from))) : null;
4444
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
4445
+ /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-snug", children: !known ? /* @__PURE__ */ jsxs(Fragment, { children: [
4446
+ "At ",
4447
+ /* @__PURE__ */ jsx(BlockHeight, { height: target, label: true, network })
4448
+ ] }) : done ? /* @__PURE__ */ jsxs(Fragment, { children: [
4449
+ reached,
4450
+ " at ",
4451
+ /* @__PURE__ */ jsx(BlockHeight, { height: target, label: true, network })
4452
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4453
+ "In ",
4454
+ /* @__PURE__ */ jsx("span", { className: "oca-tabular font-medium", children: formatBlockHeight(left) }),
4455
+ " block",
4456
+ left === 1 ? "" : "s",
4457
+ /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
4458
+ ", ",
4459
+ blocksToDuration(left, minutesPerBlock)
4460
+ ] })
4461
+ ] }) }),
4462
+ share !== null ? /* @__PURE__ */ jsx(
4463
+ "div",
4464
+ {
4465
+ role: "progressbar",
4466
+ "aria-valuemin": 0,
4467
+ "aria-valuemax": 100,
4468
+ "aria-valuenow": Math.round(share * 100),
4469
+ "aria-label": "Blocks passed",
4470
+ className: "h-1.5 overflow-hidden rounded-full bg-muted",
4471
+ children: /* @__PURE__ */ jsx("div", { className: "h-full rounded-full bg-foreground", style: { width: `${share * 100}%` } })
4472
+ }
4473
+ ) : null,
4474
+ known && !done ? /* @__PURE__ */ jsxs("p", { className: "text-[0.8125rem] text-muted-foreground", children: [
4475
+ "Target ",
4476
+ /* @__PURE__ */ jsx(BlockHeight, { height: target, network }),
4477
+ " \xB7 tip ",
4478
+ /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: formatBlockHeight(tip) })
4479
+ ] }) : null
4480
+ ] });
4481
+ }
4482
+ function Meter({
4483
+ value,
4484
+ max,
4485
+ ghost,
4486
+ label,
4487
+ figure,
4488
+ tone = "ink",
4489
+ size = "md",
4490
+ className
4491
+ }) {
4492
+ const id = useId();
4493
+ const total = max > 0 ? max : 1;
4494
+ const v = Math.max(0, Math.min(1, value / total));
4495
+ const g = ghost ? Math.max(0, Math.min(1 - v, ghost / total)) : 0;
4496
+ const pct = `${Math.round(v * 100)}%`;
4497
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
4498
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-4 text-[0.875rem]", children: [
4499
+ /* @__PURE__ */ jsx("span", { id, className: "min-w-0 truncate", children: label }),
4500
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 oca-tabular text-muted-foreground", children: figure ?? pct })
4501
+ ] }),
4502
+ /* @__PURE__ */ jsxs(
4503
+ "div",
4504
+ {
4505
+ role: "meter",
4506
+ "aria-labelledby": id,
4507
+ "aria-valuemin": 0,
4508
+ "aria-valuemax": max,
4509
+ "aria-valuenow": value,
4510
+ "aria-valuetext": typeof figure === "string" ? figure : pct,
4511
+ className: cn("flex overflow-hidden rounded-full bg-muted", size === "sm" ? "h-1.5" : "h-2.5"),
4512
+ children: [
4513
+ /* @__PURE__ */ jsx(
4514
+ "div",
4515
+ {
4516
+ className: cn("h-full shrink-0 rounded-full", tone === "brand" ? "bg-oca-orange-deep" : "bg-foreground"),
4517
+ style: { width: `${v * 100}%` }
4518
+ }
4519
+ ),
4520
+ g > 0 ? /* @__PURE__ */ jsx(
4521
+ "div",
4522
+ {
4523
+ "aria-hidden": true,
4524
+ className: "-ml-1.5 h-full shrink-0 rounded-r-full pl-1.5 text-foreground/45",
4525
+ style: {
4526
+ width: `calc(${g * 100}% + 0.375rem)`,
4527
+ backgroundImage: "repeating-linear-gradient(-45deg, currentColor 0 2px, transparent 2px 6px)"
4528
+ }
4529
+ }
4530
+ ) : null
4531
+ ]
4532
+ }
4533
+ )
4534
+ ] });
4535
+ }
4536
+ function FilterChips({
4537
+ options,
4538
+ value,
4539
+ onChange,
4540
+ label,
4541
+ className
4542
+ }) {
4543
+ const tight = useDensity() === "compact";
4544
+ const multi = Array.isArray(value);
4545
+ const isOn = (v) => multi ? value.includes(v) : value === v;
4546
+ const press = (v) => {
4547
+ if (multi) {
4548
+ const cur = value;
4549
+ onChange(cur.includes(v) ? cur.filter((x) => x !== v) : [...cur, v]);
4550
+ } else onChange(v);
4551
+ };
4552
+ return /* @__PURE__ */ jsx(ScrollFade, { fade: "var(--background)", className: cn("w-full", className), children: /* @__PURE__ */ jsx("div", { role: "group", "aria-label": label, className: "flex w-max items-center gap-2 py-0.5", children: options.map((o) => {
4553
+ const on = isOn(o.value);
4554
+ return /* @__PURE__ */ jsxs(
4555
+ "button",
4556
+ {
4557
+ type: "button",
4558
+ "aria-pressed": on,
4559
+ onClick: () => press(o.value),
4560
+ className: cn(
4561
+ "inline-flex shrink-0 items-center gap-1.5 rounded-full border px-3.5 text-[0.875rem] transition-colors",
4562
+ tight ? "h-8" : "h-9",
4563
+ on ? "border-foreground bg-foreground text-background" : "border-border bg-card text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
4564
+ ),
4565
+ children: [
4566
+ o.label,
4567
+ o.count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "oca-tabular", children: o.count.toLocaleString("en-US") }) : null
4568
+ ]
4569
+ },
4570
+ o.value
4571
+ );
4572
+ }) }) });
4573
+ }
4574
+ function ToolGrid({
4575
+ tools,
4576
+ as: Heading = "h2",
4577
+ className
4578
+ }) {
4579
+ const tight = useDensity() === "compact";
4580
+ const n = tools.length;
4581
+ return /* @__PURE__ */ jsx(
4582
+ "ul",
4583
+ {
4584
+ className: cn(
4585
+ "grid grid-cols-1 gap-3 sm:grid-cols-2 md:gap-4",
4586
+ // Three or four sit in one row on a wide screen.
4587
+ n === 3 || n === 6 ? "lg:grid-cols-3" : n === 4 ? "xl:grid-cols-4" : null,
4588
+ className
4589
+ ),
4590
+ children: tools.map((t) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
4591
+ "div",
4592
+ {
4593
+ className: cn(
4594
+ "group relative flex h-full flex-col rounded-[1.25rem] border border-border bg-card transition-colors",
4595
+ tight ? "gap-3 p-5" : "gap-4 p-6",
4596
+ "hover:border-oca-hairline-strong 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"
4597
+ ),
4598
+ children: [
4599
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
4600
+ t.icon ? /* @__PURE__ */ jsx("span", { className: "flex size-10 items-center justify-center rounded-xl bg-muted text-foreground [&_svg]:size-5", children: t.icon }) : /* @__PURE__ */ jsx("span", {}),
4601
+ /* @__PURE__ */ jsx(
4602
+ ArrowRight,
4603
+ {
4604
+ "aria-hidden": true,
4605
+ className: "size-4 text-muted-foreground transition-transform duration-200 group-hover:translate-x-0.5 group-hover:text-foreground"
4606
+ }
4607
+ )
4608
+ ] }),
4609
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4610
+ /* @__PURE__ */ jsx(Heading, { className: "oca-title-sm", children: /* @__PURE__ */ jsx(
4611
+ Link,
4612
+ {
4613
+ href: t.href,
4614
+ className: "outline-none after:absolute after:inset-0 after:rounded-[1.25rem] after:content-['']",
4615
+ children: t.label
4616
+ }
4617
+ ) }),
4618
+ t.description ? /* @__PURE__ */ jsx("p", { className: "text-[0.9375rem] leading-relaxed text-muted-foreground", children: t.description }) : null
4619
+ ] })
4620
+ ]
4621
+ }
4622
+ ) }, t.href))
4623
+ }
4624
+ );
4625
+ }
1436
4626
 
1437
- export { Accent, ActivityList, BrowserFrame, CodeBlock, Container, CopyButton, DataTable, Display, DocHeader, DocLayout, EmptyLine, EmptyState, ErrorBoundary, Eyebrow, FloatChip, Footnote, HashChip, KeyValueList, Lead, LoadingBlock, Monogram, Notice, PackageCard, PageHeader, PageHero, PhoneFrame, ProgressSteps, Prose, Reveal, Sats, SatsFigure, ScrollStory, Section, SectionIntro, SplitBar, StatCard, StatGrid, StepGrid, Ticker, TruthTable, UsdApprox, monogramGround, monogramLetter, satsText, sectionVariants, useCopy, useInView };
4627
+ export { Accent, ActivityList, AnchorStatus, ApiTable, AppCard, AppGrid, ArtifactView, BlockCountdown, BlockHeight, Breadcrumbs, BrowserFrame, Callout, CardGrid, Closing, CodeBlock, CodeTabs, ComparisonTable, Container, CopyButton, DataTable, Diagram, Display, DocHeader, DocLayout, DocsHeading, DocsPager, DropZone, EmptyLine, EmptyState, EndpointList, ErrorBoundary, ErrorPage, Eyebrow, FactBlock, FactRows, Faq, FilterChips, FloatChip, Footnote, FormSection, HashChip, InstallTabs, KeyValueList, Lead, LegalDocument, LinkCard, LoadingBlock, MdxTable, Meter, Monogram, Notice, OnThisPage, PackageCard, PageHeader, PageHero, PhoneFrame, ProgressSteps, ProofStrip, Prose, ProtocolGrid, ProtocolHero, ProtocolNav, Reveal, Sats, SatsFigure, ScrollStory, SearchButton, SearchDialog, Section, SectionHeading, SectionIntro, SignMessage, SpecCard, SplitBar, StatCard, StatGrid, StateBadge, Step, StepGrid, Steps, TextLink, Ticker, ToolGrid, TruthTable, UsdApprox, VerifyBox, VerifyReport, createStateBadge, languageName, monogramGround, monogramLetter, satsText, sectionVariants, useActiveHeading, useCopy, useHeadings, useInView };
1438
4628
  //# sourceMappingURL=components.mjs.map
1439
4629
  //# sourceMappingURL=components.mjs.map