@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
package/dist/chrome.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { X, Menu, ChevronRight, Sun, Moon, SunMoon } from 'lucide-react';
2
- import Link2 from 'next/link';
3
- import { forwardRef, createContext, useState, useContext, useMemo, useEffect } from 'react';
1
+ import { X, ChevronDown, Menu, ChevronRight, PanelLeft, Sun, Moon, SunMoon, CircleUser, LogOut, ArrowUpRight } from 'lucide-react';
2
+ import Link5 from 'next/link';
3
+ import { forwardRef, createContext, useState, useContext, useMemo, useEffect, useRef, useId, createElement } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { extendTailwindMerge } from 'tailwind-merge';
6
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -8,6 +8,10 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
8
8
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
9
9
  import * as PopoverPrimitive from '@radix-ui/react-popover';
10
10
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
11
+ import { cva } from 'class-variance-authority';
12
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
13
+ import 'sonner';
14
+ import { Slot } from '@radix-ui/react-slot';
11
15
  import { useTheme } from 'next-themes';
12
16
 
13
17
  var merge = extendTailwindMerge({
@@ -99,6 +103,154 @@ function Lockup({ name = "orangecheck", size = 28, className }) {
99
103
  }
100
104
  );
101
105
  }
106
+
107
+ // src/family/index.ts
108
+ var OCHK_IO = "https://ochk.io";
109
+ var DOCS_HREF = `${OCHK_IO}/docs`;
110
+ function protocol(slug, verb, line, kinds) {
111
+ return {
112
+ slug,
113
+ label: slug,
114
+ href: `${OCHK_IO}/${slug}`,
115
+ group: "protocol",
116
+ line,
117
+ status: "live",
118
+ verb,
119
+ pageHref: `${OCHK_IO}/${slug}`,
120
+ toolHref: `https://${slug}.ochk.io`,
121
+ specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
122
+ kinds
123
+ };
124
+ }
125
+ var PROTOCOLS = [
126
+ protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
127
+ protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
128
+ protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
129
+ protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
130
+ protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
131
+ protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
132
+ ];
133
+ PROTOCOLS.map((p) => p.slug);
134
+ var FAMILY = [
135
+ {
136
+ slug: "home",
137
+ label: "ochk.io",
138
+ href: OCHK_IO,
139
+ group: "orangecheck",
140
+ line: "The open protocols, and the company behind them.",
141
+ status: "live"
142
+ },
143
+ {
144
+ slug: "me",
145
+ label: "ochk.app",
146
+ href: "https://ochk.app",
147
+ group: "orangecheck",
148
+ line: "One account, with Bitcoin behind it.",
149
+ status: "testing"
150
+ },
151
+ {
152
+ slug: "docs",
153
+ label: "docs",
154
+ href: DOCS_HREF,
155
+ group: "orangecheck",
156
+ line: "Specs, SDKs and guides for every protocol.",
157
+ status: "live"
158
+ },
159
+ ...PROTOCOLS,
160
+ {
161
+ slug: "vault",
162
+ label: "vault",
163
+ href: "https://vault.ochk.io",
164
+ group: "app",
165
+ line: "A password manager, encrypted in your browser.",
166
+ status: "live",
167
+ protocols: ["lock"]
168
+ },
169
+ {
170
+ slug: "chat",
171
+ label: "chat",
172
+ href: "https://chat.ochk.io",
173
+ group: "app",
174
+ line: "Messages only the holder of a Bitcoin address can read.",
175
+ status: "testing",
176
+ protocols: ["lock"]
177
+ },
178
+ {
179
+ slug: "cosign",
180
+ label: "cosign",
181
+ href: "https://cosign.ochk.io",
182
+ group: "app",
183
+ line: "Builders find co-founders and backers.",
184
+ status: "testing",
185
+ protocols: ["attest"]
186
+ },
187
+ {
188
+ slug: "me-demo",
189
+ // "demo", not the made-up app's own name, so nobody takes it for ours.
190
+ label: "demo",
191
+ href: "https://me-demo.ochk.io",
192
+ group: "app",
193
+ line: "Lumen Notes, a made-up app that signs in with orangecheck.",
194
+ status: "live"
195
+ },
196
+ {
197
+ slug: "globe",
198
+ label: "globe",
199
+ href: "https://globe.ochk.io",
200
+ group: "public-good",
201
+ line: "The Bitcoin network, live, on a globe.",
202
+ status: "live"
203
+ },
204
+ {
205
+ slug: "btc",
206
+ label: "btc",
207
+ href: "https://btc.ochk.io",
208
+ group: "public-good",
209
+ line: "A free desk for reading the Bitcoin market.",
210
+ status: "live"
211
+ }
212
+ ];
213
+ var FAMILY_GROUPS = [
214
+ { id: "orangecheck", label: "orangecheck" },
215
+ { id: "protocol", label: "Protocols" },
216
+ { id: "app", label: "Apps" },
217
+ { id: "public-good", label: "Public goods" }
218
+ ];
219
+ var BY_SLUG = new Map(FAMILY.map((s) => [s.slug, s]));
220
+ function protocolSite(slug) {
221
+ return BY_SLUG.get(slug);
222
+ }
223
+ function familyByGroup() {
224
+ return FAMILY_GROUPS.map((g) => ({ ...g, sites: FAMILY.filter((s) => s.group === g.id) }));
225
+ }
226
+ var LEGAL_LINKS = [
227
+ { href: `${OCHK_IO}/privacy`, label: "Privacy" },
228
+ { href: `${OCHK_IO}/terms`, label: "Terms" },
229
+ { href: `${OCHK_IO}/security`, label: "Security" },
230
+ { href: `${OCHK_IO}/trademark`, label: "Trademarks" },
231
+ { href: `${OCHK_IO}/contact`, label: "Contact" }
232
+ ];
233
+ var OCHK_IO_NAV = [
234
+ {
235
+ href: `${OCHK_IO}/protocols`,
236
+ label: "Protocols",
237
+ children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
238
+ },
239
+ { href: `${OCHK_IO}/apps`, label: "Apps" },
240
+ { href: DOCS_HREF, label: "Docs" },
241
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
242
+ { href: `${OCHK_IO}/about`, label: "About" }
243
+ ];
244
+ var OCHK_IO_FOOTER = [
245
+ {
246
+ heading: "Company",
247
+ links: [
248
+ { href: `${OCHK_IO}/about`, label: "About" },
249
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
250
+ { href: "https://github.com/orangecheck", label: "GitHub", external: true }
251
+ ]
252
+ }
253
+ ];
102
254
  var overlayClass = "oca-animate-fade fixed inset-0 z-50 bg-[rgb(10_10_10/0.38)] backdrop-blur-[2px] data-[state=closed]:opacity-0";
103
255
  forwardRef(function DialogContent2({ className, children, hideClose, ...props }, ref) {
104
256
  return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
@@ -178,7 +330,9 @@ var SheetContent = forwardRef(function SheetContent2({ className, children, side
178
330
  )
179
331
  ] });
180
332
  });
181
- forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 8, ...props }, ref) {
333
+ var Popover = PopoverPrimitive.Root;
334
+ var PopoverTrigger = PopoverPrimitive.Trigger;
335
+ var PopoverContent = forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 8, ...props }, ref) {
182
336
  return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
183
337
  PopoverPrimitive.Content,
184
338
  {
@@ -251,51 +405,254 @@ var DropdownMenuLabel = forwardRef(function DropdownMenuLabel2({ className, ...p
251
405
  var DropdownMenuSeparator = forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
252
406
  return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Separator, { ref, className: cn("my-1.5 h-px bg-border", className), ...props });
253
407
  });
254
- function NavLink({ item, className, onNavigate }) {
408
+ var GOOD_DOT = "border-border bg-card text-foreground before:size-1.5 before:shrink-0 before:rounded-full before:bg-success before:content-['']";
409
+ var badgeVariants = cva(
410
+ "inline-flex h-6 shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border px-2.5 text-[0.8125rem] font-medium leading-none",
411
+ {
412
+ variants: {
413
+ tone: {
414
+ neutral: "border-border bg-card text-foreground",
415
+ muted: "border-transparent bg-muted text-muted-foreground",
416
+ brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
417
+ danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
418
+ // A good state is a neutral pill with a green dot, not a green pill.
419
+ success: GOOD_DOT,
420
+ // Aliases kept so older call sites keep compiling: attention is
421
+ // the brand accent, information is neutral.
422
+ warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
423
+ info: "border-border bg-card text-foreground",
424
+ // Inverted in dark mode, where ink would sit on a card of nearly its own colour.
425
+ ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
426
+ onInk: "border-white/15 bg-white/5 text-white/90"
427
+ }
428
+ },
429
+ defaultVariants: { tone: "neutral" }
430
+ }
431
+ );
432
+ function Badge({ className, tone, ...props }) {
433
+ return /* @__PURE__ */ jsx("span", { "data-ui": "badge", className: cn(badgeVariants({ tone }), className), ...props });
434
+ }
435
+ var WORD = {
436
+ live: "Live",
437
+ testing: "In testing",
438
+ "not-yet": "Not yet",
439
+ paused: "Paused",
440
+ good: "Good",
441
+ caution: "Caution",
442
+ refused: "Refused"
443
+ };
444
+ var TONE = {
445
+ live: "success",
446
+ testing: "brand",
447
+ "not-yet": "muted",
448
+ paused: "muted",
449
+ good: "success",
450
+ caution: "brand",
451
+ refused: "danger"
452
+ };
453
+ function StatusBadge({ status, className, ...props }) {
454
+ return /* @__PURE__ */ jsx(Badge, { tone: TONE[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
455
+ }
456
+ function SiteRow({ site, here, onNavigate }) {
457
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
458
+ "a",
459
+ {
460
+ href: site.href,
461
+ onClick: onNavigate,
462
+ "aria-current": here ? "page" : void 0,
463
+ className: cn(
464
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
465
+ here && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
466
+ ),
467
+ children: [
468
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-[0.9375rem] font-medium leading-6", children: [
469
+ site.label,
470
+ site.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: site.status }) : null,
471
+ here ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(this site)" }) : null
472
+ ] }),
473
+ /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: site.line })
474
+ ]
475
+ }
476
+ ) });
477
+ }
478
+ var PLACE = {
479
+ orangecheck: "sm:col-start-1 sm:row-start-1 lg:row-span-2",
480
+ protocol: "sm:col-start-1 sm:row-start-2 lg:col-start-2 lg:row-start-1 lg:row-span-2",
481
+ app: "sm:col-start-2 sm:row-start-1 lg:col-start-3",
482
+ "public-good": "sm:col-start-2 sm:row-start-2 lg:col-start-3"
483
+ };
484
+ function FamilyList({
485
+ current,
486
+ onNavigate,
487
+ stack = false,
488
+ className
489
+ }) {
490
+ const id = useId();
491
+ return /* @__PURE__ */ jsx(
492
+ "div",
493
+ {
494
+ className: cn(
495
+ "grid grid-cols-1 gap-x-2 gap-y-4",
496
+ // The second desk row takes the slack, so the public goods sit right under the apps.
497
+ !stack && "sm:grid-cols-2 lg:grid-cols-3 lg:grid-rows-[auto_1fr]",
498
+ className
499
+ ),
500
+ children: familyByGroup().map((g) => /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", !stack && PLACE[g.id]), children: [
501
+ /* @__PURE__ */ jsx("p", { id: `${id}-${g.id}`, className: "px-3 pt-1 text-[0.8125rem] text-muted-foreground", children: g.label }),
502
+ /* @__PURE__ */ jsx("ul", { "aria-labelledby": `${id}-${g.id}`, className: "flex flex-col", children: g.sites.map((s) => /* @__PURE__ */ jsx(SiteRow, { site: s, here: s.slug === current, onNavigate }, s.slug)) })
503
+ ] }, g.id))
504
+ }
505
+ );
506
+ }
507
+ function FamilyMenu({ current, className }) {
508
+ const [open, setOpen] = useState(false);
509
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
510
+ /* @__PURE__ */ jsx(
511
+ PopoverTrigger,
512
+ {
513
+ "aria-label": "All orangecheck sites",
514
+ className: cn(
515
+ "group inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors",
516
+ "hover:bg-accent hover:text-foreground data-[state=open]:bg-accent data-[state=open]:text-foreground",
517
+ className
518
+ ),
519
+ children: /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" })
520
+ }
521
+ ),
522
+ /* @__PURE__ */ jsx(
523
+ PopoverContent,
524
+ {
525
+ align: "start",
526
+ sideOffset: 14,
527
+ collisionPadding: 16,
528
+ className: "max-h-[min(40rem,var(--radix-popover-content-available-height))] w-[min(calc(100vw-2rem),42rem)] overflow-y-auto p-3 lg:w-[min(calc(100vw-2rem),56rem)]",
529
+ children: /* @__PURE__ */ jsx(FamilyList, { current, onNavigate: () => setOpen(false) })
530
+ }
531
+ )
532
+ ] });
533
+ }
534
+ function NavLink({
535
+ item,
536
+ className,
537
+ onNavigate,
538
+ line = false
539
+ }) {
255
540
  const cls = cn(
256
541
  "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
257
542
  item.active ? "text-foreground" : "text-muted-foreground hover:text-foreground",
543
+ line && "relative after:absolute after:inset-x-3 after:-bottom-[0.625rem] after:h-0.5 after:rounded-full",
544
+ line && item.active && "after:bg-foreground",
258
545
  className
259
546
  );
260
547
  if (item.external) {
261
548
  return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
262
549
  }
263
- return /* @__PURE__ */ jsx(Link2, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
550
+ return /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
551
+ }
552
+ function NavRow({ item, onNavigate }) {
553
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
554
+ /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
555
+ item.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
556
+ ] });
557
+ const cls = cn(
558
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
559
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
560
+ );
561
+ return item.external ? /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsx(Link5, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
562
+ }
563
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
564
+ function NavDropdown({ item }) {
565
+ const [open, setOpen] = useState(false);
566
+ const active = item.active || item.children?.some((c) => c.active);
567
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
568
+ /* @__PURE__ */ jsxs(
569
+ PopoverTrigger,
570
+ {
571
+ className: cn(
572
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors",
573
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
574
+ ),
575
+ children: [
576
+ item.label,
577
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
578
+ ]
579
+ }
580
+ ),
581
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
582
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
583
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsx(
584
+ NavLink,
585
+ {
586
+ item: { ...item, label: seeAll(item), children: void 0 },
587
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
588
+ onNavigate: () => setOpen(false)
589
+ }
590
+ ) })
591
+ ] })
592
+ ] });
264
593
  }
265
594
  function SiteHeader({
266
595
  home = "/",
267
596
  brand,
597
+ product,
598
+ family,
268
599
  nav = [],
600
+ search,
269
601
  actions,
602
+ variant = "site",
603
+ navOnPhone = true,
604
+ menu: menuExtra,
270
605
  className
271
606
  }) {
272
607
  const [open, setOpen] = useState(false);
608
+ const tool = variant === "tool";
609
+ const size = tool ? 24 : 28;
610
+ const current = typeof family === "string" ? family : void 0;
611
+ const phoneNav = navOnPhone ? nav : [];
612
+ const menu = phoneNav.length > 0 || Boolean(family) || Boolean(menuExtra);
613
+ const brandNode = brand ?? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center", children: [
614
+ /* @__PURE__ */ jsx(Lockup, { size }),
615
+ product ? /* @__PURE__ */ jsxs(Fragment, { children: [
616
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
617
+ /* @__PURE__ */ jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
618
+ ] }) : null
619
+ ] });
620
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map(
621
+ (n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : /* @__PURE__ */ jsx(NavLink, { item: n, line: tool }, n.href)
622
+ ) }) : null;
273
623
  return /* @__PURE__ */ jsx(
274
624
  "header",
275
625
  {
276
626
  className: cn(
277
- "sticky top-0 z-40 w-full border-b border-transparent bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
627
+ "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
628
+ tool ? "border-border" : "border-transparent",
278
629
  className
279
630
  ),
280
631
  children: /* @__PURE__ */ jsxs(
281
632
  "div",
282
633
  {
283
634
  className: cn(
284
- "oca-container flex h-16 items-center justify-between gap-4 md:h-[4.5rem]",
635
+ "flex items-center justify-between gap-4",
636
+ tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem]",
285
637
  // Three columns, the outer two each at least their content: the
286
638
  // navigation stays centred whatever the actions hold, so it does
287
639
  // not shift when they change (signed out to signed in).
288
- nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
640
+ !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
289
641
  ),
290
642
  children: [
291
- /* @__PURE__ */ jsxs(Link2, { href: home, className: "-ml-1 justify-self-start rounded-lg p-1", children: [
292
- brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
293
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
643
+ /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
644
+ /* @__PURE__ */ jsxs(Link5, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
645
+ brandNode,
646
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
647
+ ] }),
648
+ family ? /* @__PURE__ */ jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
649
+ tool && navigation ? /* @__PURE__ */ jsx("div", { className: "ml-5", children: navigation }) : null
294
650
  ] }),
295
- nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => /* @__PURE__ */ jsx(NavLink, { item: n }, n.href)) }) : null,
651
+ !tool ? navigation : null,
296
652
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
653
+ search,
297
654
  actions,
298
- nav.length > 0 ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
655
+ menu ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
299
656
  /* @__PURE__ */ jsx(
300
657
  SheetTrigger,
301
658
  {
@@ -306,15 +663,36 @@ function SiteHeader({
306
663
  ),
307
664
  /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
308
665
  /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
309
- /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map((n) => /* @__PURE__ */ jsx(
310
- NavLink,
311
- {
312
- item: n,
313
- className: "rounded-xl px-3 py-3 text-[1.0625rem]",
314
- onNavigate: () => setOpen(false)
315
- },
316
- n.href
317
- )) })
666
+ menuExtra ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", (phoneNav.length > 0 || family) && "border-b border-border pb-3"), children: menuExtra }) : null,
667
+ phoneNav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: phoneNav.map(
668
+ (n) => n.children?.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-2", children: [
669
+ /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
670
+ n.children.map((c) => /* @__PURE__ */ jsx(
671
+ NavLink,
672
+ {
673
+ item: c,
674
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
675
+ onNavigate: () => setOpen(false)
676
+ },
677
+ c.href
678
+ ))
679
+ ] }, n.href) : /* @__PURE__ */ jsx(
680
+ NavLink,
681
+ {
682
+ item: n,
683
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
684
+ onNavigate: () => setOpen(false)
685
+ },
686
+ n.href
687
+ )
688
+ ) }) : null,
689
+ family ? /* @__PURE__ */ jsxs("details", { className: cn("group", phoneNav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
690
+ /* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
691
+ "All orangecheck sites",
692
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
693
+ ] }),
694
+ /* @__PURE__ */ jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
695
+ ] }) : null
318
696
  ] })
319
697
  ] }) : null
320
698
  ] })
@@ -324,57 +702,588 @@ function SiteHeader({
324
702
  }
325
703
  );
326
704
  }
705
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
706
+ return /* @__PURE__ */ jsx(
707
+ "a",
708
+ {
709
+ href,
710
+ className: "sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-50 focus:rounded-full focus:border focus:border-border focus:bg-card focus:px-4 focus:py-2 focus:text-[0.9375rem] focus:font-medium focus:text-foreground focus:shadow-md",
711
+ children
712
+ }
713
+ );
714
+ }
715
+ var BANNER_TONE = {
716
+ neutral: "border-border bg-muted",
717
+ brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
718
+ danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
719
+ };
720
+ function SiteBanner({
721
+ tone = "neutral",
722
+ children,
723
+ action,
724
+ className
725
+ }) {
726
+ return /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", "data-tone": tone, className: cn("border-b text-[0.875rem]", BANNER_TONE[tone], className), children: /* @__PURE__ */ jsxs("div", { className: "oca-container flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-2.5", children: [
727
+ /* @__PURE__ */ jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
728
+ tone !== "neutral" ? /* @__PURE__ */ jsx(
729
+ "span",
730
+ {
731
+ "aria-hidden": true,
732
+ className: cn(
733
+ "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
734
+ tone === "brand" ? "bg-oca-orange" : "bg-destructive"
735
+ )
736
+ }
737
+ ) : null,
738
+ /* @__PURE__ */ jsx("span", { children })
739
+ ] }),
740
+ action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
741
+ ] }) });
742
+ }
743
+ var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
744
+ function LegalRow() {
745
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
746
+ /* @__PURE__ */ jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-5", children: LEGAL_LINKS.map((l) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
747
+ /* @__PURE__ */ jsxs("p", { children: [
748
+ "\xA9 ",
749
+ (/* @__PURE__ */ new Date()).getFullYear(),
750
+ " OrangeCheck"
751
+ ] })
752
+ ] });
753
+ }
327
754
  function SiteFooter({
328
755
  columns = [],
756
+ family = false,
757
+ legal = false,
758
+ compact = false,
329
759
  fineprint,
330
760
  meta,
331
761
  signature = true,
332
762
  className
333
763
  }) {
334
- return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
335
- /* @__PURE__ */ jsxs("div", { className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[1.3fr_repeat(3,1fr)] md:py-16", children: [
336
- /* @__PURE__ */ jsxs("div", { className: "col-span-2 flex flex-col gap-4 md:col-span-1", children: [
337
- /* @__PURE__ */ jsx(Lockup, { size: 26 }),
338
- fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
764
+ if (compact) {
765
+ return /* @__PURE__ */ jsx("footer", { className: cn("border-t border-border bg-background text-[0.875rem] text-muted-foreground", className), children: /* @__PURE__ */ jsxs("div", { className: "oca-container flex flex-col gap-x-8 gap-y-3 py-5 lg:flex-row lg:items-center lg:justify-between", children: [
766
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
767
+ /* @__PURE__ */ jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
768
+ family ? /* @__PURE__ */ jsx("nav", { "aria-label": "Protocols", children: /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-x-4", children: PROTOCOLS.map((p) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: p.pageHref, className: FOOT_LINK, children: p.label }) }, p.slug)) }) }) : null
339
769
  ] }),
340
- columns.map((col, i) => {
341
- const spans = columns.length % 2 === 1 && i === columns.length - 1;
342
- return /* @__PURE__ */ jsxs(
343
- "div",
344
- {
345
- className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
346
- children: [
347
- /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
348
- /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsx(
349
- NavLink,
350
- {
351
- item: l,
352
- className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
353
- },
354
- l.href
355
- )) })
356
- ]
357
- },
358
- col.heading
359
- );
360
- })
361
- ] }),
770
+ legal || meta ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
771
+ legal ? /* @__PURE__ */ jsx(LegalRow, {}) : null,
772
+ meta
773
+ ] }) : null
774
+ ] }) });
775
+ }
776
+ const cols = [
777
+ ...columns,
778
+ ...family ? familyByGroup().map((g) => ({
779
+ // The lockup above already says orangecheck.
780
+ heading: g.id === "orangecheck" ? "Start here" : g.label,
781
+ links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
782
+ })) : []
783
+ ];
784
+ const n = cols.length;
785
+ const inline = n <= 5;
786
+ const grid = {
787
+ "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
788
+ "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
789
+ };
790
+ return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
791
+ /* @__PURE__ */ jsxs(
792
+ "div",
793
+ {
794
+ style: grid,
795
+ className: "oca-container grid grid-cols-2 gap-x-6 gap-y-10 py-14 md:grid-cols-[var(--oca-footer-md)] md:py-16 lg:grid-cols-[var(--oca-footer-lg)]",
796
+ children: [
797
+ /* @__PURE__ */ jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
798
+ /* @__PURE__ */ jsx(Lockup, { size: 26 }),
799
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
800
+ ] }),
801
+ cols.map((col, i) => {
802
+ const spans = n % 2 === 1 && i === n - 1;
803
+ return /* @__PURE__ */ jsxs(
804
+ "div",
805
+ {
806
+ className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
807
+ children: [
808
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
809
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsx(
810
+ NavLink,
811
+ {
812
+ item: l,
813
+ className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
814
+ },
815
+ l.href
816
+ )) })
817
+ ]
818
+ },
819
+ col.heading
820
+ );
821
+ })
822
+ ]
823
+ }
824
+ ),
362
825
  signature ? /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "oca-container select-none overflow-hidden pb-8 md:pb-12", children: /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-[0.18em] text-[clamp(3rem,11.5vw,10rem)] leading-[0.78] tracking-[-0.065em] [font-family:var(--oc-font-display)]", children: [
363
826
  /* @__PURE__ */ jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsx(Mark, { className: "block h-auto w-full" }) }),
364
827
  /* @__PURE__ */ jsx("span", { children: "orangecheck" })
365
828
  ] }) }) : null,
366
- meta ? /* @__PURE__ */ jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsx("div", { className: "border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: meta }) }) : null
829
+ legal || meta ? /* @__PURE__ */ jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: [
830
+ legal ? /* @__PURE__ */ jsx(LegalRow, {}) : null,
831
+ meta
832
+ ] }) }) : null
367
833
  ] });
368
834
  }
369
- var ShellContext = createContext({});
835
+ function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
836
+ const ref = useRef(null);
837
+ useEffect(() => {
838
+ const el = ref.current;
839
+ if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
840
+ let raf = 0;
841
+ let tx = 0;
842
+ let ty = 0;
843
+ let x = 0;
844
+ let y = 0;
845
+ const step = () => {
846
+ x += (tx - x) * 0.08;
847
+ y += (ty - y) * 0.08;
848
+ el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
849
+ el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
850
+ raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
851
+ };
852
+ const move = (e) => {
853
+ const b = el.getBoundingClientRect();
854
+ tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
855
+ ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
856
+ if (!raf) raf = requestAnimationFrame(step);
857
+ };
858
+ window.addEventListener("pointermove", move, { passive: true });
859
+ return () => {
860
+ cancelAnimationFrame(raf);
861
+ window.removeEventListener("pointermove", move);
862
+ };
863
+ }, [tilt]);
864
+ return /* @__PURE__ */ jsxs(
865
+ "div",
866
+ {
867
+ ref,
868
+ className: cn("relative inline-block", settle && "oca-animate-settle", className),
869
+ style: { width: size, perspective: tilt ? 900 : void 0 },
870
+ children: [
871
+ tilt ? /* @__PURE__ */ jsx(
872
+ "div",
873
+ {
874
+ "aria-hidden": true,
875
+ 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",
876
+ style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
877
+ }
878
+ ) : null,
879
+ /* @__PURE__ */ jsx(
880
+ "div",
881
+ {
882
+ className: "relative z-10 transition-transform duration-300 ease-out",
883
+ style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
884
+ children: /* @__PURE__ */ jsx(Mark, { size, title, className: "block" })
885
+ }
886
+ ),
887
+ shadow ? /* @__PURE__ */ jsx(
888
+ "div",
889
+ {
890
+ "aria-hidden": true,
891
+ className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
892
+ style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
893
+ }
894
+ ) : null
895
+ ]
896
+ }
897
+ );
898
+ }
899
+ function SignInFrame({
900
+ title = "Sign in",
901
+ lead,
902
+ children,
903
+ error,
904
+ fineprint,
905
+ brand,
906
+ home = "/",
907
+ back,
908
+ art,
909
+ caption,
910
+ className
911
+ }) {
912
+ return /* @__PURE__ */ jsxs(
913
+ "main",
914
+ {
915
+ id: "main-content",
916
+ className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
917
+ children: [
918
+ /* @__PURE__ */ jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
919
+ /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4", children: [
920
+ /* @__PURE__ */ jsxs(Link5, { href: home, className: "w-fit rounded-lg", children: [
921
+ brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
922
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
923
+ ] }),
924
+ back === void 0 ? /* @__PURE__ */ jsx(
925
+ Link5,
926
+ {
927
+ href: home,
928
+ className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
929
+ children: "Back to home"
930
+ }
931
+ ) : back
932
+ ] }),
933
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
934
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
935
+ /* @__PURE__ */ jsx("h1", { className: "oca-display-2", children: title }),
936
+ lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead", children: lead }) : null
937
+ ] }),
938
+ /* @__PURE__ */ jsx("div", { children }),
939
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
940
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
941
+ ] })
942
+ ] }),
943
+ /* @__PURE__ */ jsxs(
944
+ "aside",
945
+ {
946
+ "aria-hidden": true,
947
+ className: "relative hidden flex-col justify-between gap-10 overflow-hidden border-l border-[var(--oca-band-line)] bg-oca-ink p-14 text-oca-ink-foreground lg:flex",
948
+ children: [
949
+ /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center", children: art ?? /* @__PURE__ */ jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) }),
950
+ caption ? /* @__PURE__ */ jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
951
+ ]
952
+ }
953
+ )
954
+ ]
955
+ }
956
+ );
957
+ }
958
+ function Spinner({ className, label }) {
959
+ return /* @__PURE__ */ jsxs(
960
+ "svg",
961
+ {
962
+ viewBox: "0 0 24 24",
963
+ fill: "none",
964
+ role: label ? "status" : void 0,
965
+ "aria-label": label,
966
+ "aria-hidden": label ? void 0 : true,
967
+ className: cn("size-4 animate-spin", className),
968
+ children: [
969
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeOpacity: "0.2", strokeWidth: "2.5" }),
970
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })
971
+ ]
972
+ }
973
+ );
974
+ }
975
+ forwardRef(function Separator3({ className, orientation = "horizontal", decorative = true, ...props }, ref) {
976
+ return /* @__PURE__ */ jsx(
977
+ SeparatorPrimitive.Root,
978
+ {
979
+ ref,
980
+ decorative,
981
+ orientation,
982
+ className: cn(
983
+ "shrink-0 bg-border",
984
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
985
+ className
986
+ ),
987
+ ...props
988
+ }
989
+ );
990
+ });
991
+ function sharedContext(name, initial) {
992
+ const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
993
+ const store = globalThis;
994
+ return store[key] ?? (store[key] = createContext(initial));
995
+ }
996
+
997
+ // src/lib/density.ts
998
+ var DensityContext = sharedContext("density", "comfortable");
999
+ function DensityProvider({ density, children }) {
1000
+ return createElement(DensityContext.Provider, { value: density }, children);
1001
+ }
1002
+ var ShellContext = sharedContext("shell-place", {});
370
1003
  function useShellPlace() {
371
1004
  return useContext(ShellContext);
372
1005
  }
1006
+ var buttonVariants = cva(
1007
+ [
1008
+ "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-full font-medium",
1009
+ "transition-[background-color,border-color,color,box-shadow,transform] duration-150",
1010
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1011
+ "active:translate-y-px disabled:pointer-events-none",
1012
+ // Disabled is one look for every variant: a quiet grey pill, never a
1013
+ // faded black or orange slab that reads as broken.
1014
+ "disabled:border disabled:border-border disabled:bg-muted disabled:text-oca-subtle disabled:shadow-none",
1015
+ "[&_svg]:pointer-events-none [&_svg]:size-[1.1em] [&_svg]:shrink-0"
1016
+ ],
1017
+ {
1018
+ variants: {
1019
+ variant: {
1020
+ primary: "bg-primary text-primary-foreground hover:bg-primary/85",
1021
+ secondary: "border border-border bg-secondary text-secondary-foreground hover:border-oca-hairline-strong hover:bg-accent",
1022
+ brand: "bg-brand text-brand-foreground hover:bg-oca-orange-deep",
1023
+ ghost: "text-foreground hover:bg-accent",
1024
+ danger: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
1025
+ link: "h-auto rounded-none px-0 text-foreground underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground",
1026
+ onInk: "bg-white text-oca-ink hover:bg-white/90",
1027
+ onInkOutline: "border border-white/20 text-white hover:bg-white/10"
1028
+ },
1029
+ size: {
1030
+ sm: "h-9 px-4 text-sm",
1031
+ md: "h-11 px-5 text-[0.9375rem]",
1032
+ lg: "h-14 px-7 text-[1.0625rem]",
1033
+ icon: "size-10",
1034
+ "icon-sm": "size-8"
1035
+ }
1036
+ },
1037
+ compoundVariants: [{ variant: "link", className: "h-auto px-0" }],
1038
+ defaultVariants: { variant: "primary", size: "md" }
1039
+ }
1040
+ );
1041
+ var Button = forwardRef(function Button2({ className, variant, size, asChild = false, loading = false, disabled, children, type, ...props }, ref) {
1042
+ const Comp = asChild ? Slot : "button";
1043
+ return /* @__PURE__ */ jsx(
1044
+ Comp,
1045
+ {
1046
+ ref,
1047
+ "data-ui": "button",
1048
+ className: cn(buttonVariants({ variant, size }), className),
1049
+ disabled: asChild ? void 0 : disabled || loading,
1050
+ "aria-busy": loading || void 0,
1051
+ type: asChild ? void 0 : type ?? "button",
1052
+ ...props,
1053
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
1054
+ loading ? /* @__PURE__ */ jsx(Spinner, { className: "size-[1.1em]" }) : null,
1055
+ children
1056
+ ] })
1057
+ }
1058
+ );
1059
+ });
1060
+ function useActiveHeading(ids) {
1061
+ const [active, setActive] = useState(ids[0]);
1062
+ const key = ids.join("|");
1063
+ useEffect(() => {
1064
+ setActive(key.split("|")[0] || void 0);
1065
+ const els = key.split("|").map((id) => document.getElementById(id)).filter((el) => el !== null);
1066
+ if (els.length === 0 || typeof IntersectionObserver === "undefined") return;
1067
+ const io = new IntersectionObserver(
1068
+ (entries) => {
1069
+ const hit = entries.filter((e) => e.isIntersecting).sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0];
1070
+ if (hit) setActive(hit.target.id);
1071
+ },
1072
+ { rootMargin: "-80px 0px -65% 0px" }
1073
+ );
1074
+ els.forEach((el) => io.observe(el));
1075
+ return () => io.disconnect();
1076
+ }, [key]);
1077
+ return active;
1078
+ }
1079
+ function useHeadings(selector = "#docs-content", key) {
1080
+ const [items, setItems] = useState([]);
1081
+ useEffect(() => {
1082
+ const read = () => {
1083
+ const root = document.querySelector(selector);
1084
+ if (!root) return setItems([]);
1085
+ setItems(
1086
+ Array.from(root.querySelectorAll("h2[id], h3[id]")).map((h) => ({
1087
+ id: h.id,
1088
+ // The anchor link's "#" is not part of the name.
1089
+ label: (h.querySelector("[data-heading-text]") ?? h).textContent?.trim() ?? "",
1090
+ level: h.tagName === "H3" ? 3 : 2
1091
+ }))
1092
+ );
1093
+ };
1094
+ const raf = requestAnimationFrame(read);
1095
+ const t = setTimeout(read, 80);
1096
+ return () => {
1097
+ cancelAnimationFrame(raf);
1098
+ clearTimeout(t);
1099
+ };
1100
+ }, [selector, key]);
1101
+ const activeId = useActiveHeading(items.map((i) => i.id));
1102
+ return { items, activeId };
1103
+ }
1104
+ function OnThisPage({
1105
+ items,
1106
+ activeId,
1107
+ title = "On this page",
1108
+ onNavigate,
1109
+ className
1110
+ }) {
1111
+ const id = useId();
1112
+ if (items.length === 0) return null;
1113
+ return (
1114
+ // With no visible title (a folded list under its own summary) the name is still "On this page".
1115
+ /* @__PURE__ */ jsxs("nav", { "aria-labelledby": title ? id : void 0, "aria-label": title ? void 0 : "On this page", className, children: [
1116
+ title ? /* @__PURE__ */ jsx("p", { id, className: "mb-3 text-[0.875rem] font-medium", children: title }) : null,
1117
+ /* @__PURE__ */ jsx("ul", { children: items.map((t) => {
1118
+ const on = t.id === activeId;
1119
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1120
+ "a",
1121
+ {
1122
+ href: `#${t.id}`,
1123
+ onClick: onNavigate,
1124
+ "aria-current": on ? "location" : void 0,
1125
+ className: cn(
1126
+ "block border-l py-1.5 text-[0.875rem] leading-snug transition-colors",
1127
+ t.level === 3 ? "pl-7" : "pl-4",
1128
+ on ? "border-foreground text-foreground" : "border-border text-muted-foreground hover:text-foreground"
1129
+ ),
1130
+ children: t.label
1131
+ }
1132
+ ) }, t.id);
1133
+ }) })
1134
+ ] })
1135
+ );
1136
+ }
1137
+ var STATUS_WORDS = /* @__PURE__ */ new Set(["live", "testing", "not-yet", "paused", "good", "caution", "refused"]);
1138
+ var pathOf = (href) => href.split(/[?#]/)[0].replace(/(.)\/$/, "$1");
1139
+ function DocsNav({
1140
+ sections,
1141
+ current,
1142
+ onNavigate,
1143
+ className
1144
+ }) {
1145
+ const here = pathOf(current);
1146
+ const activeSection = useMemo(
1147
+ () => sections.findIndex((s) => s.items.some((i) => pathOf(i.href) === here)),
1148
+ [sections, here]
1149
+ );
1150
+ const [peeked, setPeeked] = useState(() => /* @__PURE__ */ new Set());
1151
+ useEffect(() => setPeeked(/* @__PURE__ */ new Set()), [activeSection]);
1152
+ const activeRef = useRef(null);
1153
+ useEffect(() => {
1154
+ const id = requestAnimationFrame(() => activeRef.current?.scrollIntoView({ block: "nearest" }));
1155
+ return () => cancelAnimationFrame(id);
1156
+ }, [here]);
1157
+ const base = useId();
1158
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Docs", className: cn("flex flex-col gap-0.5", className), children: sections.map((section, si) => {
1159
+ const isActive = si === activeSection;
1160
+ const open = isActive || peeked.has(si);
1161
+ const panel = `${base}-s${si}`;
1162
+ return /* @__PURE__ */ jsxs("div", { children: [
1163
+ /* @__PURE__ */ jsxs(
1164
+ "button",
1165
+ {
1166
+ type: "button",
1167
+ "aria-expanded": open,
1168
+ "aria-controls": panel,
1169
+ onClick: () => {
1170
+ if (isActive) return;
1171
+ setPeeked((p) => {
1172
+ const n = new Set(p);
1173
+ if (n.has(si)) n.delete(si);
1174
+ else n.add(si);
1175
+ return n;
1176
+ });
1177
+ },
1178
+ className: cn(
1179
+ "flex min-h-9 w-full items-center justify-between gap-2 rounded-lg px-2.5 py-1.5 text-left text-[0.875rem] transition-colors",
1180
+ isActive ? "font-medium text-foreground" : "text-muted-foreground hover:bg-accent hover:text-foreground",
1181
+ isActive && "cursor-default"
1182
+ ),
1183
+ children: [
1184
+ section.label,
1185
+ /* @__PURE__ */ jsx(
1186
+ ChevronRight,
1187
+ {
1188
+ "aria-hidden": true,
1189
+ className: cn("size-3.5 shrink-0 text-oca-subtle transition-transform duration-200", open && "rotate-90")
1190
+ }
1191
+ )
1192
+ ]
1193
+ }
1194
+ ),
1195
+ /* @__PURE__ */ jsx("ul", { id: panel, hidden: !open, className: "mb-2 ml-2.5 mt-0.5 border-l border-border", children: section.items.map((item) => {
1196
+ const on = pathOf(item.href) === here;
1197
+ const badge = typeof item.badge === "string" && STATUS_WORDS.has(item.badge) ? /* @__PURE__ */ jsx(StatusBadge, { status: item.badge }) : item.badge ? /* @__PURE__ */ jsx(Badge, { tone: "muted", children: item.badge }) : null;
1198
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
1199
+ Link5,
1200
+ {
1201
+ href: item.href,
1202
+ ref: on ? activeRef : void 0,
1203
+ onClick: onNavigate,
1204
+ "aria-current": on ? "page" : void 0,
1205
+ className: cn(
1206
+ "-ml-px flex min-h-9 items-center gap-2 border-l-2 py-1.5 pl-3.5 pr-2 text-[0.875rem] leading-snug transition-colors",
1207
+ on ? "border-foreground font-medium text-foreground" : "border-transparent text-muted-foreground hover:border-oca-hairline-strong hover:text-foreground"
1208
+ ),
1209
+ children: [
1210
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: item.label }),
1211
+ badge
1212
+ ]
1213
+ }
1214
+ ) }, item.href);
1215
+ }) })
1216
+ ] }, section.label);
1217
+ }) });
1218
+ }
1219
+ var DOCS_HEADER_NAV = OCHK_IO_NAV.map((n) => n.href === DOCS_HREF ? { ...n, active: true } : n);
1220
+ function DocsShell({
1221
+ nav,
1222
+ current,
1223
+ header,
1224
+ search,
1225
+ actions,
1226
+ breadcrumbs,
1227
+ toc,
1228
+ pager,
1229
+ footer,
1230
+ children
1231
+ }) {
1232
+ const [menu, setMenu] = useState(false);
1233
+ useEffect(() => setMenu(false), [current]);
1234
+ const read = useHeadings("#docs-content", current);
1235
+ const items = toc ?? read.items;
1236
+ const activeId = toc ? void 0 : read.activeId;
1237
+ const here = pathOf(current);
1238
+ const place = useMemo(() => {
1239
+ for (const s of nav) {
1240
+ const it = s.items.find((i) => pathOf(i.href) === here);
1241
+ if (it) return { section: s.label, page: it.label };
1242
+ }
1243
+ return null;
1244
+ }, [nav, here]);
1245
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-dvh flex-col bg-background", children: [
1246
+ /* @__PURE__ */ jsx(SkipLink, {}),
1247
+ header ?? /* @__PURE__ */ jsx(SiteHeader, { home: OCHK_IO, family: "docs", nav: DOCS_HEADER_NAV, search, actions }),
1248
+ /* @__PURE__ */ jsx("div", { className: "sticky top-16 z-30 border-b border-border bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90 md:top-[4.5rem] lg:hidden", children: /* @__PURE__ */ jsx("div", { className: "oca-container flex h-12 items-center gap-2", children: /* @__PURE__ */ jsxs(Sheet, { open: menu, onOpenChange: setMenu, children: [
1249
+ /* @__PURE__ */ jsxs(SheetTrigger, { className: "-ml-2 inline-flex h-10 min-w-0 items-center gap-2 rounded-full px-2.5 text-[0.875rem] hover:bg-accent", children: [
1250
+ /* @__PURE__ */ jsx(PanelLeft, { "aria-hidden": true, className: "size-[1.125rem] shrink-0" }),
1251
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Docs menu. " }),
1252
+ place ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
1253
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: place.section }),
1254
+ /* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-oca-subtle" }),
1255
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: place.page })
1256
+ ] }) : /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Docs" })
1257
+ ] }),
1258
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-[min(88vw,22rem)] gap-0 p-0", children: [
1259
+ /* @__PURE__ */ jsx("div", { className: "border-b border-border px-5 py-4 pr-14", children: /* @__PURE__ */ jsx(SheetTitle, { className: "text-[1.0625rem] font-medium", children: "Docs" }) }),
1260
+ /* @__PURE__ */ jsx("div", { className: "overflow-y-auto p-3", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current, onNavigate: () => setMenu(false) }) })
1261
+ ] })
1262
+ ] }) }) }),
1263
+ /* @__PURE__ */ jsx("div", { className: "oca-container flex-1", children: /* @__PURE__ */ jsxs("div", { className: "lg:grid lg:grid-cols-[13.5rem_minmax(0,1fr)] lg:gap-x-10 xl:grid-cols-[13.5rem_minmax(0,1fr)_11rem]", children: [
1264
+ /* @__PURE__ */ jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto overscroll-contain py-8 pr-1 lg:block", children: /* @__PURE__ */ jsx(DocsNav, { sections: nav, current }) }),
1265
+ /* @__PURE__ */ jsxs("main", { id: "main-content", className: "min-w-0 pb-16 pt-6 md:pt-8", children: [
1266
+ breadcrumbs ? /* @__PURE__ */ jsx("div", { className: "mb-6 max-lg:hidden", children: breadcrumbs }) : null,
1267
+ items.length > 1 ? /* @__PURE__ */ jsxs("details", { className: "group mb-8 rounded-2xl border border-border bg-card xl:hidden", children: [
1268
+ /* @__PURE__ */ jsxs("summary", { className: "flex min-h-12 cursor-pointer list-none items-center justify-between px-4 text-[0.9375rem] font-medium [&::-webkit-details-marker]:hidden", children: [
1269
+ "On this page",
1270
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
1271
+ ] }),
1272
+ /* @__PURE__ */ jsx(OnThisPage, { items, activeId, title: null, className: "px-4 pb-4" })
1273
+ ] }) : null,
1274
+ /* @__PURE__ */ jsx("article", { id: "docs-content", className: "max-w-[46rem]", children }),
1275
+ pager ? /* @__PURE__ */ jsx("div", { className: "mt-16 max-w-[46rem]", children: pager }) : null
1276
+ ] }),
1277
+ /* @__PURE__ */ jsx("div", { className: "sticky top-[4.5rem] hidden max-h-[calc(100dvh-4.5rem)] self-start overflow-y-auto py-10 xl:block", children: items.length > 1 ? /* @__PURE__ */ jsx(OnThisPage, { items, activeId }) : null })
1278
+ ] }) }),
1279
+ footer ?? /* @__PURE__ */ jsx(SiteFooter, { columns: OCHK_IO_FOOTER, family: true, legal: true, signature: false })
1280
+ ] });
1281
+ }
373
1282
  function SideNav({ groups, onNavigate }) {
374
1283
  return /* @__PURE__ */ jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
375
1284
  g.label ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
376
1285
  g.items.map((it) => /* @__PURE__ */ jsxs(
377
- Link2,
1286
+ Link5,
378
1287
  {
379
1288
  href: it.href,
380
1289
  onClick: onNavigate,
@@ -409,7 +1318,7 @@ function SectionSwitch({
409
1318
  children: sections.map((sec) => {
410
1319
  const on = sec.id === current.id;
411
1320
  return /* @__PURE__ */ jsx(
412
- Link2,
1321
+ Link5,
413
1322
  {
414
1323
  href: sec.href,
415
1324
  onClick: onNavigate,
@@ -439,7 +1348,7 @@ function TabBar({ items }) {
439
1348
  className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
440
1349
  style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
441
1350
  children: items.map((it) => /* @__PURE__ */ jsxs(
442
- Link2,
1351
+ Link5,
443
1352
  {
444
1353
  href: it.href,
445
1354
  "aria-current": it.active ? "page" : void 0,
@@ -548,7 +1457,7 @@ function AppShell({
548
1457
  footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
549
1458
  ] })
550
1459
  ] }),
551
- /* @__PURE__ */ jsx(Link2, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
1460
+ /* @__PURE__ */ jsx(Link5, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
552
1461
  /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
553
1462
  ] }),
554
1463
  place.page ? /* @__PURE__ */ jsxs(
@@ -571,7 +1480,7 @@ function AppShell({
571
1480
  ] }),
572
1481
  /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
573
1482
  /* @__PURE__ */ jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
574
- /* @__PURE__ */ jsx(Link2, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
1483
+ /* @__PURE__ */ jsx(Link5, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
575
1484
  switcher,
576
1485
  /* @__PURE__ */ jsx(SideNav, { groups }),
577
1486
  /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
@@ -602,9 +1511,16 @@ function AccountMenu({
602
1511
  "inline-flex h-10 items-center gap-2.5 rounded-full border border-border bg-card pl-1 pr-1 text-[0.9375rem] outline-none transition-colors hover:border-oca-hairline-strong focus-visible:ring-2 focus-visible:ring-ring",
603
1512
  nameFrom === "lg" ? "lg:pr-3.5" : "sm:pr-3.5"
604
1513
  ),
605
- "aria-label": `Account: ${name}`,
1514
+ "aria-label": `${name}, account menu`,
606
1515
  children: [
607
- /* @__PURE__ */ jsx("span", { className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background", children: initial }),
1516
+ /* @__PURE__ */ jsx(
1517
+ "span",
1518
+ {
1519
+ "aria-hidden": true,
1520
+ "data-initial": initial,
1521
+ className: "flex size-8 items-center justify-center rounded-full bg-foreground text-[0.8125rem] font-medium text-background before:content-[attr(data-initial)]"
1522
+ }
1523
+ ),
608
1524
  /* @__PURE__ */ jsx("span", { className: cn("max-w-[10rem] truncate", nameFrom === "lg" ? "max-lg:hidden" : "max-sm:hidden"), children: name })
609
1525
  ]
610
1526
  }
@@ -616,7 +1532,7 @@ function AccountMenu({
616
1532
  ] }),
617
1533
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
618
1534
  items.map(
619
- (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link2, { href: it.href, children: [
1535
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link5, { href: it.href, children: [
620
1536
  it.icon,
621
1537
  it.label
622
1538
  ] }) }, it.label) : /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
@@ -649,7 +1565,121 @@ function ThemeToggle({ className }) {
649
1565
  }
650
1566
  );
651
1567
  }
1568
+ var OCHK_APP_ACCOUNT = "https://ochk.app/me/account";
1569
+ function SessionAccountView({
1570
+ state,
1571
+ name,
1572
+ detail,
1573
+ items = [],
1574
+ signInHref,
1575
+ signInLabel = "Sign in",
1576
+ accountHref = OCHK_APP_ACCOUNT,
1577
+ onSignOut,
1578
+ nameFrom = "lg"
1579
+ }) {
1580
+ if (state === "in") {
1581
+ return /* @__PURE__ */ jsx(
1582
+ AccountMenu,
1583
+ {
1584
+ name: name || "Your account",
1585
+ detail,
1586
+ nameFrom,
1587
+ items: [
1588
+ ...items,
1589
+ ...items.length > 0 ? ["separator"] : [],
1590
+ { label: "Your account", href: accountHref, icon: /* @__PURE__ */ jsx(CircleUser, {}) },
1591
+ "separator",
1592
+ { label: "Sign out", onSelect: onSignOut, icon: /* @__PURE__ */ jsx(LogOut, {}) }
1593
+ ]
1594
+ }
1595
+ );
1596
+ }
1597
+ if (state === "unknown") {
1598
+ return /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", variant: "secondary", children: /* @__PURE__ */ jsx("a", { href: accountHref, children: "Your account" }) });
1599
+ }
1600
+ return (
1601
+ // No box of its own: it sits exactly where the signed-in chip will. While checking it is only unseen.
1602
+ /* @__PURE__ */ jsx("span", { className: state === "checking" ? "contents invisible" : "contents", "aria-hidden": state === "checking" || void 0, children: /* @__PURE__ */ jsx(Button, { asChild: true, size: "sm", variant: "secondary", tabIndex: state === "checking" ? -1 : void 0, children: /* @__PURE__ */ jsx("a", { href: signInHref, children: signInLabel }) }) })
1603
+ );
1604
+ }
1605
+ function ToolShell({
1606
+ protocol: protocol2,
1607
+ tools,
1608
+ home = "/",
1609
+ account,
1610
+ rail = false,
1611
+ railFooter,
1612
+ variant = "tool",
1613
+ banner,
1614
+ footer,
1615
+ children
1616
+ }) {
1617
+ const p = protocolSite(protocol2);
1618
+ const app = variant === "app";
1619
+ const tabs = app ? null : tabsFor([{ items: [...tools] }]);
1620
+ const about = /* @__PURE__ */ jsxs(
1621
+ "a",
1622
+ {
1623
+ href: p.pageHref,
1624
+ className: "inline-flex items-center gap-1 rounded-full px-3 py-2 text-[0.9375rem] text-muted-foreground transition-colors hover:text-foreground",
1625
+ children: [
1626
+ "About ",
1627
+ p.label,
1628
+ /* @__PURE__ */ jsx(ArrowUpRight, { "aria-hidden": true, className: "size-3.5" })
1629
+ ]
1630
+ }
1631
+ );
1632
+ return /* @__PURE__ */ jsx(DensityProvider, { density: "compact", children: /* @__PURE__ */ jsxs(
1633
+ "div",
1634
+ {
1635
+ className: cn(
1636
+ "flex flex-col bg-background",
1637
+ app ? "h-dvh overflow-hidden" : "min-h-dvh",
1638
+ tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]"
1639
+ ),
1640
+ children: [
1641
+ /* @__PURE__ */ jsx(SkipLink, {}),
1642
+ banner,
1643
+ /* @__PURE__ */ jsx(
1644
+ SiteHeader,
1645
+ {
1646
+ variant: "tool",
1647
+ home,
1648
+ product: p.label,
1649
+ family: protocol2,
1650
+ nav: tools.map((t) => ({ href: t.href, label: t.label, active: t.active })),
1651
+ navOnPhone: !tabs,
1652
+ menu: /* @__PURE__ */ jsx("div", { className: "[&>a]:px-3 [&>a]:py-3 [&>a]:text-[1.0625rem]", children: about }),
1653
+ className: cn(rail && "lg:[&_nav[aria-label=Main]]:hidden"),
1654
+ actions: /* @__PURE__ */ jsxs(Fragment, { children: [
1655
+ /* @__PURE__ */ jsx("span", { className: "hidden lg:contents", children: about }),
1656
+ p.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: p.status, className: "max-sm:hidden" }) : null,
1657
+ /* @__PURE__ */ jsx(ThemeToggle, { className: "max-sm:hidden" }),
1658
+ account
1659
+ ] })
1660
+ }
1661
+ ),
1662
+ /* @__PURE__ */ jsxs("div", { className: cn("mx-auto flex w-full", app ? "min-h-0 flex-1" : "max-w-[90rem] flex-1"), children: [
1663
+ rail ? /* @__PURE__ */ jsxs("aside", { className: "sticky top-14 hidden h-[calc(100dvh-3.5rem)] w-60 shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
1664
+ /* @__PURE__ */ jsx(SideNav, { groups: [{ label: "Tools", items: tools.map(({ href, label, icon, active }) => ({ href, label, icon, active })) }] }),
1665
+ railFooter ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-0.5 px-3 text-[0.875rem] text-muted-foreground [&_a:hover]:text-foreground [&_a]:py-1.5 [&_a]:transition-colors", children: railFooter }) : null
1666
+ ] }) : null,
1667
+ /* @__PURE__ */ jsx(
1668
+ "main",
1669
+ {
1670
+ id: "main-content",
1671
+ className: cn("min-w-0 flex-1", app ? "flex min-h-0 flex-col" : "px-4 pb-16 pt-8 md:px-8 md:pt-10"),
1672
+ children: app ? children : /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-[72rem]", children })
1673
+ }
1674
+ )
1675
+ ] }),
1676
+ app || footer === false ? null : footer ?? /* @__PURE__ */ jsx(SiteFooter, { compact: true, family: true, legal: true }),
1677
+ tabs ? /* @__PURE__ */ jsx(TabBar, { items: tabs }) : null
1678
+ ]
1679
+ }
1680
+ ) });
1681
+ }
652
1682
 
653
- export { AccountMenu, AppShell, ShellContext, SiteFooter, SiteHeader, ThemeToggle, useShellPlace };
1683
+ export { AccountMenu, AppShell, DOCS_HEADER_NAV, DocsNav, DocsShell, FamilyMenu, OCHK_APP_ACCOUNT, SessionAccountView, ShellContext, SignInFrame, SiteBanner, SiteFooter, SiteHeader, SkipLink, ThemeToggle, ToolShell, useShellPlace };
654
1684
  //# sourceMappingURL=chrome.mjs.map
655
1685
  //# sourceMappingURL=chrome.mjs.map