@orangecheck/app-design 0.6.1 → 1.0.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 (46) hide show
  1. package/README.md +4 -3
  2. package/dist/brand.js.map +1 -1
  3. package/dist/brand.mjs.map +1 -1
  4. package/dist/chrome.d.mts +49 -15
  5. package/dist/chrome.d.ts +49 -15
  6. package/dist/chrome.js +619 -55
  7. package/dist/chrome.js.map +1 -1
  8. package/dist/chrome.mjs +617 -57
  9. package/dist/chrome.mjs.map +1 -1
  10. package/dist/components.d.mts +231 -1
  11. package/dist/components.d.ts +231 -1
  12. package/dist/components.js +1187 -2
  13. package/dist/components.js.map +1 -1
  14. package/dist/components.mjs +1162 -5
  15. package/dist/components.mjs.map +1 -1
  16. package/dist/family.d.mts +2 -0
  17. package/dist/family.d.ts +2 -0
  18. package/dist/family.js +167 -0
  19. package/dist/family.js.map +1 -0
  20. package/dist/family.mjs +154 -0
  21. package/dist/family.mjs.map +1 -0
  22. package/dist/index-C6hDqOOS.d.mts +58 -0
  23. package/dist/index-C6hDqOOS.d.ts +58 -0
  24. package/dist/index.d.mts +5 -3
  25. package/dist/index.d.ts +5 -3
  26. package/dist/index.js +1619 -132
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +1575 -134
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/primitives.d.mts +52 -1
  31. package/dist/primitives.d.ts +52 -1
  32. package/dist/primitives.js +280 -3
  33. package/dist/primitives.js.map +1 -1
  34. package/dist/primitives.mjs +271 -6
  35. package/dist/primitives.mjs.map +1 -1
  36. package/dist/status-badge-BEOxeY9j.d.ts +13 -0
  37. package/dist/status-badge-DRwGhB0h.d.mts +13 -0
  38. package/dist/styles/fonts.css +1 -1
  39. package/dist/styles/tokens.css +4 -2
  40. package/dist/tokens.d.mts +3 -1
  41. package/dist/tokens.d.ts +3 -1
  42. package/dist/tokens.js +5 -3
  43. package/dist/tokens.js.map +1 -1
  44. package/dist/tokens.mjs +5 -3
  45. package/dist/tokens.mjs.map +1 -1
  46. package/package.json +9 -2
package/dist/chrome.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var lucideReact = require('lucide-react');
4
- var Link2 = require('next/link');
4
+ var Link3 = require('next/link');
5
5
  var react = require('react');
6
6
  var clsx = require('clsx');
7
7
  var tailwindMerge = require('tailwind-merge');
@@ -10,6 +10,7 @@ var DialogPrimitive = require('@radix-ui/react-dialog');
10
10
  var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
11
11
  var PopoverPrimitive = require('@radix-ui/react-popover');
12
12
  var TooltipPrimitive = require('@radix-ui/react-tooltip');
13
+ var classVarianceAuthority = require('class-variance-authority');
13
14
  var nextThemes = require('next-themes');
14
15
 
15
16
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -32,7 +33,7 @@ function _interopNamespace(e) {
32
33
  return Object.freeze(n);
33
34
  }
34
35
 
35
- var Link2__default = /*#__PURE__*/_interopDefault(Link2);
36
+ var Link3__default = /*#__PURE__*/_interopDefault(Link3);
36
37
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
37
38
  var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
38
39
  var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
@@ -127,6 +128,141 @@ function Lockup({ name = "orangecheck", size = 28, className }) {
127
128
  }
128
129
  );
129
130
  }
131
+
132
+ // src/family/index.ts
133
+ var OCHK_IO = "https://ochk.io";
134
+ var DOCS_HREF = `${OCHK_IO}/docs`;
135
+ function protocol(slug, verb, line, kinds) {
136
+ return {
137
+ slug,
138
+ label: slug,
139
+ href: `${OCHK_IO}/${slug}`,
140
+ group: "protocol",
141
+ line,
142
+ status: "live",
143
+ verb,
144
+ pageHref: `${OCHK_IO}/${slug}`,
145
+ toolHref: `https://${slug}.ochk.io`,
146
+ specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
147
+ kinds
148
+ };
149
+ }
150
+ var PROTOCOLS = [
151
+ protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
152
+ protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
153
+ protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
154
+ protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
155
+ protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
156
+ protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
157
+ ];
158
+ PROTOCOLS.map((p) => p.slug);
159
+ var FAMILY = [
160
+ {
161
+ slug: "home",
162
+ label: "ochk.io",
163
+ href: OCHK_IO,
164
+ group: "orangecheck",
165
+ line: "The open protocols, and the company behind them.",
166
+ status: "live"
167
+ },
168
+ {
169
+ slug: "me",
170
+ label: "ochk.app",
171
+ href: "https://ochk.app",
172
+ group: "orangecheck",
173
+ line: "One account, with Bitcoin behind it.",
174
+ status: "testing"
175
+ },
176
+ {
177
+ slug: "docs",
178
+ label: "docs",
179
+ href: DOCS_HREF,
180
+ group: "orangecheck",
181
+ line: "Specs, SDKs and guides for every protocol.",
182
+ status: "live"
183
+ },
184
+ ...PROTOCOLS,
185
+ {
186
+ slug: "vault",
187
+ label: "vault",
188
+ href: "https://vault.ochk.io",
189
+ group: "app",
190
+ line: "A password manager, encrypted in your browser.",
191
+ status: "live",
192
+ protocols: ["lock"]
193
+ },
194
+ {
195
+ slug: "chat",
196
+ label: "chat",
197
+ href: "https://chat.ochk.io",
198
+ group: "app",
199
+ line: "Messages only the holder of a Bitcoin address can read.",
200
+ status: "testing",
201
+ protocols: ["lock"]
202
+ },
203
+ {
204
+ slug: "cosign",
205
+ label: "cosign",
206
+ href: "https://cosign.ochk.io",
207
+ group: "app",
208
+ line: "Builders find co-founders and backers.",
209
+ status: "testing",
210
+ protocols: ["attest"]
211
+ },
212
+ {
213
+ slug: "me-demo",
214
+ // "demo", not the made-up app's own name, so nobody takes it for ours.
215
+ label: "demo",
216
+ href: "https://me-demo.ochk.io",
217
+ group: "app",
218
+ line: "Lumen Notes, a made-up app that signs in with orangecheck.",
219
+ status: "live"
220
+ },
221
+ {
222
+ slug: "globe",
223
+ label: "globe",
224
+ href: "https://globe.ochk.io",
225
+ group: "public-good",
226
+ line: "The Bitcoin network, live, on a globe.",
227
+ status: "live"
228
+ },
229
+ {
230
+ slug: "btc",
231
+ label: "btc",
232
+ href: "https://btc.ochk.io",
233
+ group: "public-good",
234
+ line: "A free desk for reading the Bitcoin market.",
235
+ status: "live"
236
+ }
237
+ ];
238
+ var FAMILY_GROUPS = [
239
+ { id: "orangecheck", label: "orangecheck" },
240
+ { id: "protocol", label: "Protocols" },
241
+ { id: "app", label: "Apps" },
242
+ { id: "public-good", label: "Public goods" }
243
+ ];
244
+ new Map(FAMILY.map((s) => [s.slug, s]));
245
+ function familyByGroup() {
246
+ return FAMILY_GROUPS.map((g) => ({ ...g, sites: FAMILY.filter((s) => s.group === g.id) }));
247
+ }
248
+ var LEGAL_LINKS = [
249
+ { href: `${OCHK_IO}/privacy`, label: "Privacy" },
250
+ { href: `${OCHK_IO}/terms`, label: "Terms" },
251
+ { href: `${OCHK_IO}/security`, label: "Security" },
252
+ { href: `${OCHK_IO}/trademark`, label: "Trademarks" },
253
+ { href: `${OCHK_IO}/contact`, label: "Contact" }
254
+ ];
255
+ [
256
+ {
257
+ href: `${OCHK_IO}/protocols`,
258
+ label: "Protocols",
259
+ children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
260
+ },
261
+ { href: `${OCHK_IO}/apps`, label: "Apps" },
262
+ { href: DOCS_HREF, label: "Docs" },
263
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
264
+ { href: `${OCHK_IO}/about`, label: "About" }
265
+ ];
130
266
  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";
131
267
  react.forwardRef(function DialogContent2({ className, children, hideClose, ...props }, ref) {
132
268
  return /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Portal, { children: [
@@ -206,7 +342,9 @@ var SheetContent = react.forwardRef(function SheetContent2({ className, children
206
342
  )
207
343
  ] });
208
344
  });
209
- react.forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 8, ...props }, ref) {
345
+ var Popover = PopoverPrimitive__namespace.Root;
346
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
347
+ var PopoverContent = react.forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 8, ...props }, ref) {
210
348
  return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
211
349
  PopoverPrimitive__namespace.Content,
212
350
  {
@@ -279,6 +417,132 @@ var DropdownMenuLabel = react.forwardRef(function DropdownMenuLabel2({ className
279
417
  var DropdownMenuSeparator = react.forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
280
418
  return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Separator, { ref, className: cn("my-1.5 h-px bg-border", className), ...props });
281
419
  });
420
+ var GOOD_DOT = "border-border bg-card text-foreground before:size-1.5 before:shrink-0 before:rounded-full before:bg-success before:content-['']";
421
+ var badgeVariants = classVarianceAuthority.cva(
422
+ "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",
423
+ {
424
+ variants: {
425
+ tone: {
426
+ neutral: "border-border bg-card text-foreground",
427
+ muted: "border-transparent bg-muted text-muted-foreground",
428
+ brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
429
+ danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
430
+ // A good state is a neutral pill with a green dot, not a green pill.
431
+ success: GOOD_DOT,
432
+ // Aliases kept so older call sites keep compiling: attention is
433
+ // the brand accent, information is neutral.
434
+ warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
435
+ info: "border-border bg-card text-foreground",
436
+ // Inverted in dark mode, where ink would sit on a card of nearly its own colour.
437
+ ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
438
+ onInk: "border-white/15 bg-white/5 text-white/90"
439
+ }
440
+ },
441
+ defaultVariants: { tone: "neutral" }
442
+ }
443
+ );
444
+ function Badge({ className, tone, ...props }) {
445
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { "data-ui": "badge", className: cn(badgeVariants({ tone }), className), ...props });
446
+ }
447
+ var WORD = {
448
+ live: "Live",
449
+ testing: "In testing",
450
+ "not-yet": "Not yet",
451
+ paused: "Paused",
452
+ good: "Good",
453
+ caution: "Caution",
454
+ refused: "Refused"
455
+ };
456
+ var TONE = {
457
+ live: "success",
458
+ testing: "brand",
459
+ "not-yet": "muted",
460
+ paused: "muted",
461
+ good: "success",
462
+ caution: "brand",
463
+ refused: "danger"
464
+ };
465
+ function StatusBadge({ status, className, ...props }) {
466
+ return /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: TONE[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
467
+ }
468
+ function SiteRow({ site, here, onNavigate }) {
469
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
470
+ "a",
471
+ {
472
+ href: site.href,
473
+ onClick: onNavigate,
474
+ "aria-current": here ? "page" : void 0,
475
+ className: cn(
476
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
477
+ here && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
478
+ ),
479
+ children: [
480
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2 text-[0.9375rem] font-medium leading-6", children: [
481
+ site.label,
482
+ site.status !== "live" ? /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { status: site.status }) : null,
483
+ here ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "(this site)" }) : null
484
+ ] }),
485
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: site.line })
486
+ ]
487
+ }
488
+ ) });
489
+ }
490
+ var PLACE = {
491
+ orangecheck: "sm:col-start-1 sm:row-start-1 lg:row-span-2",
492
+ protocol: "sm:col-start-1 sm:row-start-2 lg:col-start-2 lg:row-start-1 lg:row-span-2",
493
+ app: "sm:col-start-2 sm:row-start-1 lg:col-start-3",
494
+ "public-good": "sm:col-start-2 sm:row-start-2 lg:col-start-3"
495
+ };
496
+ function FamilyList({
497
+ current,
498
+ onNavigate,
499
+ stack = false,
500
+ className
501
+ }) {
502
+ const id = react.useId();
503
+ return /* @__PURE__ */ jsxRuntime.jsx(
504
+ "div",
505
+ {
506
+ className: cn(
507
+ "grid grid-cols-1 gap-x-2 gap-y-4",
508
+ // The second desk row takes the slack, so the public goods sit right under the apps.
509
+ !stack && "sm:grid-cols-2 lg:grid-cols-3 lg:grid-rows-[auto_1fr]",
510
+ className
511
+ ),
512
+ children: familyByGroup().map((g) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1", !stack && PLACE[g.id]), children: [
513
+ /* @__PURE__ */ jsxRuntime.jsx("p", { id: `${id}-${g.id}`, className: "px-3 pt-1 text-[0.8125rem] text-muted-foreground", children: g.label }),
514
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-labelledby": `${id}-${g.id}`, className: "flex flex-col", children: g.sites.map((s) => /* @__PURE__ */ jsxRuntime.jsx(SiteRow, { site: s, here: s.slug === current, onNavigate }, s.slug)) })
515
+ ] }, g.id))
516
+ }
517
+ );
518
+ }
519
+ function FamilyMenu({ current, className }) {
520
+ const [open, setOpen] = react.useState(false);
521
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
522
+ /* @__PURE__ */ jsxRuntime.jsx(
523
+ PopoverTrigger,
524
+ {
525
+ "aria-label": "All orangecheck sites",
526
+ className: cn(
527
+ "group inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors",
528
+ "hover:bg-accent hover:text-foreground data-[state=open]:bg-accent data-[state=open]:text-foreground",
529
+ className
530
+ ),
531
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" })
532
+ }
533
+ ),
534
+ /* @__PURE__ */ jsxRuntime.jsx(
535
+ PopoverContent,
536
+ {
537
+ align: "start",
538
+ sideOffset: 14,
539
+ collisionPadding: 16,
540
+ 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)]",
541
+ children: /* @__PURE__ */ jsxRuntime.jsx(FamilyList, { current, onNavigate: () => setOpen(false) })
542
+ }
543
+ )
544
+ ] });
545
+ }
282
546
  function NavLink({ item, className, onNavigate }) {
283
547
  const cls = cn(
284
548
  "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
@@ -288,42 +552,107 @@ function NavLink({ item, className, onNavigate }) {
288
552
  if (item.external) {
289
553
  return /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
290
554
  }
291
- return /* @__PURE__ */ jsxRuntime.jsx(Link2__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
555
+ return /* @__PURE__ */ jsxRuntime.jsx(Link3__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
556
+ }
557
+ function NavRow({ item, onNavigate }) {
558
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
559
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
560
+ item.description ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
561
+ ] });
562
+ const cls = cn(
563
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
564
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
565
+ );
566
+ return item.external ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsxRuntime.jsx(Link3__default.default, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
567
+ }
568
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
569
+ function NavDropdown({ item }) {
570
+ const [open, setOpen] = react.useState(false);
571
+ const active = item.active || item.children?.some((c) => c.active);
572
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
573
+ /* @__PURE__ */ jsxRuntime.jsxs(
574
+ PopoverTrigger,
575
+ {
576
+ className: cn(
577
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors",
578
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
579
+ ),
580
+ children: [
581
+ item.label,
582
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
583
+ ]
584
+ }
585
+ ),
586
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
587
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col", children: item.children?.map((c) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(NavRow, { item: c, onNavigate: () => setOpen(false) }) }, c.href)) }),
588
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
589
+ NavLink,
590
+ {
591
+ item: { ...item, label: seeAll(item), children: void 0 },
592
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
593
+ onNavigate: () => setOpen(false)
594
+ }
595
+ ) })
596
+ ] })
597
+ ] });
292
598
  }
293
599
  function SiteHeader({
294
600
  home = "/",
295
601
  brand,
602
+ product,
603
+ family,
296
604
  nav = [],
605
+ search,
297
606
  actions,
607
+ variant = "site",
298
608
  className
299
609
  }) {
300
610
  const [open, setOpen] = react.useState(false);
611
+ const tool = variant === "tool";
612
+ const size = tool ? 24 : 28;
613
+ const current = typeof family === "string" ? family : void 0;
614
+ const menu = nav.length > 0 || Boolean(family);
615
+ const brandNode = brand ?? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center", children: [
616
+ /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size }),
617
+ product ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
618
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
619
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
620
+ ] }) : null
621
+ ] });
622
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsx(NavDropdown, { item: n }, n.href) : /* @__PURE__ */ jsxRuntime.jsx(NavLink, { item: n }, n.href)) }) : null;
301
623
  return /* @__PURE__ */ jsxRuntime.jsx(
302
624
  "header",
303
625
  {
304
626
  className: cn(
305
- "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",
306
629
  className
307
630
  ),
308
631
  children: /* @__PURE__ */ jsxRuntime.jsxs(
309
632
  "div",
310
633
  {
311
634
  className: cn(
312
- "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]",
313
637
  // Three columns, the outer two each at least their content: the
314
638
  // navigation stays centred whatever the actions hold, so it does
315
639
  // not shift when they change (signed out to signed in).
316
- 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)]"
317
641
  ),
318
642
  children: [
319
- /* @__PURE__ */ jsxRuntime.jsxs(Link2__default.default, { href: home, className: "-ml-1 justify-self-start rounded-lg p-1", children: [
320
- brand ?? /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 28 }),
321
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
644
+ /* @__PURE__ */ jsxRuntime.jsxs(Link3__default.default, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
645
+ brandNode,
646
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
647
+ ] }),
648
+ family ? /* @__PURE__ */ jsxRuntime.jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
649
+ tool && navigation ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-5", children: navigation }) : null
322
650
  ] }),
323
- nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => /* @__PURE__ */ jsxRuntime.jsx(NavLink, { item: n }, n.href)) }) : null,
651
+ !tool ? navigation : null,
324
652
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
653
+ search,
325
654
  actions,
326
- nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
655
+ menu ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open, onOpenChange: setOpen, children: [
327
656
  /* @__PURE__ */ jsxRuntime.jsx(
328
657
  SheetTrigger,
329
658
  {
@@ -334,15 +663,35 @@ function SiteHeader({
334
663
  ),
335
664
  /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "right", className: "pt-16", children: [
336
665
  /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Menu" }),
337
- /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map((n) => /* @__PURE__ */ jsxRuntime.jsx(
338
- NavLink,
339
- {
340
- item: n,
341
- className: "rounded-xl px-3 py-3 text-[1.0625rem]",
342
- onNavigate: () => setOpen(false)
343
- },
344
- n.href
345
- )) })
666
+ nav.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map(
667
+ (n) => n.children?.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col py-2", children: [
668
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
669
+ n.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(
670
+ NavLink,
671
+ {
672
+ item: c,
673
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
674
+ onNavigate: () => setOpen(false)
675
+ },
676
+ c.href
677
+ ))
678
+ ] }, n.href) : /* @__PURE__ */ jsxRuntime.jsx(
679
+ NavLink,
680
+ {
681
+ item: n,
682
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
683
+ onNavigate: () => setOpen(false)
684
+ },
685
+ n.href
686
+ )
687
+ ) }) : null,
688
+ family ? /* @__PURE__ */ jsxRuntime.jsxs("details", { className: cn("group", nav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
689
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between rounded-xl px-3 py-2.5 text-[1.0625rem] [&::-webkit-details-marker]:hidden", children: [
690
+ "All orangecheck sites",
691
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
692
+ ] }),
693
+ /* @__PURE__ */ jsxRuntime.jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
694
+ ] }) : null
346
695
  ] })
347
696
  ] }) : null
348
697
  ] })
@@ -352,48 +701,259 @@ function SiteHeader({
352
701
  }
353
702
  );
354
703
  }
704
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
705
+ return /* @__PURE__ */ jsxRuntime.jsx(
706
+ "a",
707
+ {
708
+ href,
709
+ 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",
710
+ children
711
+ }
712
+ );
713
+ }
714
+ var BANNER_TONE = {
715
+ neutral: "border-border bg-muted",
716
+ brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
717
+ danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
718
+ };
719
+ function SiteBanner({
720
+ tone = "neutral",
721
+ children,
722
+ action,
723
+ className
724
+ }) {
725
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", "aria-live": "polite", "data-tone": tone, className: cn("border-b text-[0.875rem]", BANNER_TONE[tone], className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oca-container flex flex-wrap items-center justify-between gap-x-4 gap-y-1 py-2.5", children: [
726
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
727
+ tone !== "neutral" ? /* @__PURE__ */ jsxRuntime.jsx(
728
+ "span",
729
+ {
730
+ "aria-hidden": true,
731
+ className: cn(
732
+ "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
733
+ tone === "brand" ? "bg-oca-orange" : "bg-destructive"
734
+ )
735
+ }
736
+ ) : null,
737
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children })
738
+ ] }),
739
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
740
+ ] }) });
741
+ }
742
+ var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
743
+ function LegalRow() {
744
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
745
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Legal", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-5", children: LEGAL_LINKS.map((l) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: l.href, className: FOOT_LINK, children: l.label }) }, l.href)) }) }),
746
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
747
+ "\xA9 ",
748
+ (/* @__PURE__ */ new Date()).getFullYear(),
749
+ " OrangeCheck"
750
+ ] })
751
+ ] });
752
+ }
355
753
  function SiteFooter({
356
754
  columns = [],
755
+ family = false,
756
+ legal = false,
757
+ compact = false,
357
758
  fineprint,
358
759
  meta,
359
760
  signature = true,
360
761
  className
361
762
  }) {
362
- return /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
363
- /* @__PURE__ */ jsxRuntime.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: [
364
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-2 flex flex-col gap-4 md:col-span-1", children: [
365
- /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }),
366
- fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
763
+ if (compact) {
764
+ return /* @__PURE__ */ jsxRuntime.jsx("footer", { className: cn("border-t border-border bg-background text-[0.875rem] text-muted-foreground", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "oca-container flex flex-col gap-x-8 gap-y-3 py-5 lg:flex-row lg:items-center lg:justify-between", children: [
765
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
766
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
767
+ family ? /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Protocols", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-wrap gap-x-4", children: PROTOCOLS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: p.pageHref, className: FOOT_LINK, children: p.label }) }, p.slug)) }) }) : null
367
768
  ] }),
368
- columns.map((col, i) => {
369
- const spans = columns.length % 2 === 1 && i === columns.length - 1;
370
- return /* @__PURE__ */ jsxRuntime.jsxs(
371
- "div",
372
- {
373
- className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
374
- children: [
375
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
376
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
377
- NavLink,
378
- {
379
- item: l,
380
- className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
381
- },
382
- l.href
383
- )) })
384
- ]
385
- },
386
- col.heading
387
- );
388
- })
389
- ] }),
769
+ legal || meta ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:flex-wrap sm:items-center", children: [
770
+ legal ? /* @__PURE__ */ jsxRuntime.jsx(LegalRow, {}) : null,
771
+ meta
772
+ ] }) : null
773
+ ] }) });
774
+ }
775
+ const cols = [
776
+ ...columns,
777
+ ...family ? familyByGroup().map((g) => ({
778
+ // The lockup above already says orangecheck.
779
+ heading: g.id === "orangecheck" ? "Start here" : g.label,
780
+ links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
781
+ })) : []
782
+ ];
783
+ const n = cols.length;
784
+ const inline = n <= 5;
785
+ const grid = {
786
+ "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
787
+ "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
788
+ };
789
+ return /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
790
+ /* @__PURE__ */ jsxRuntime.jsxs(
791
+ "div",
792
+ {
793
+ style: grid,
794
+ 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)]",
795
+ children: [
796
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
797
+ /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }),
798
+ fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
799
+ ] }),
800
+ cols.map((col, i) => {
801
+ const spans = n % 2 === 1 && i === n - 1;
802
+ return /* @__PURE__ */ jsxRuntime.jsxs(
803
+ "div",
804
+ {
805
+ className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
806
+ children: [
807
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
808
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-1", spans && "grid grid-cols-2 gap-x-6 md:flex md:flex-col"), children: col.links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
809
+ NavLink,
810
+ {
811
+ item: l,
812
+ className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
813
+ },
814
+ l.href
815
+ )) })
816
+ ]
817
+ },
818
+ col.heading
819
+ );
820
+ })
821
+ ]
822
+ }
823
+ ),
390
824
  signature ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "oca-container select-none overflow-hidden pb-8 md:pb-12", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-[0.18em] text-[clamp(3rem,11.5vw,10rem)] leading-[0.78] tracking-[-0.065em] [font-family:var(--oc-font-display)]", children: [
391
825
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-[0.06em] inline-block w-[1.1em] shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(Mark, { className: "block h-auto w-full" }) }),
392
826
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "orangecheck" })
393
827
  ] }) }) : null,
394
- meta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: meta }) }) : null
828
+ legal || meta ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oca-container", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 border-t border-border py-6 text-[0.875rem] text-muted-foreground", children: [
829
+ legal ? /* @__PURE__ */ jsxRuntime.jsx(LegalRow, {}) : null,
830
+ meta
831
+ ] }) }) : null
395
832
  ] });
396
833
  }
834
+ function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
835
+ const ref = react.useRef(null);
836
+ react.useEffect(() => {
837
+ const el = ref.current;
838
+ if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
839
+ let raf = 0;
840
+ let tx = 0;
841
+ let ty = 0;
842
+ let x = 0;
843
+ let y = 0;
844
+ const step = () => {
845
+ x += (tx - x) * 0.08;
846
+ y += (ty - y) * 0.08;
847
+ el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
848
+ el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
849
+ raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
850
+ };
851
+ const move = (e) => {
852
+ const b = el.getBoundingClientRect();
853
+ tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
854
+ ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
855
+ if (!raf) raf = requestAnimationFrame(step);
856
+ };
857
+ window.addEventListener("pointermove", move, { passive: true });
858
+ return () => {
859
+ cancelAnimationFrame(raf);
860
+ window.removeEventListener("pointermove", move);
861
+ };
862
+ }, [tilt]);
863
+ return /* @__PURE__ */ jsxRuntime.jsxs(
864
+ "div",
865
+ {
866
+ ref,
867
+ className: cn("relative inline-block", settle && "oca-animate-settle", className),
868
+ style: { width: size, perspective: tilt ? 900 : void 0 },
869
+ children: [
870
+ tilt ? /* @__PURE__ */ jsxRuntime.jsx(
871
+ "div",
872
+ {
873
+ "aria-hidden": true,
874
+ 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",
875
+ style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
876
+ }
877
+ ) : null,
878
+ /* @__PURE__ */ jsxRuntime.jsx(
879
+ "div",
880
+ {
881
+ className: "relative z-10 transition-transform duration-300 ease-out",
882
+ style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
883
+ children: /* @__PURE__ */ jsxRuntime.jsx(Mark, { size, title, className: "block" })
884
+ }
885
+ ),
886
+ shadow ? /* @__PURE__ */ jsxRuntime.jsx(
887
+ "div",
888
+ {
889
+ "aria-hidden": true,
890
+ className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
891
+ style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
892
+ }
893
+ ) : null
894
+ ]
895
+ }
896
+ );
897
+ }
898
+ function SignInFrame({
899
+ title = "Sign in",
900
+ lead,
901
+ children,
902
+ error,
903
+ fineprint,
904
+ brand,
905
+ home = "/",
906
+ back,
907
+ art,
908
+ caption,
909
+ className
910
+ }) {
911
+ return /* @__PURE__ */ jsxRuntime.jsxs(
912
+ "main",
913
+ {
914
+ id: "main-content",
915
+ className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
916
+ children: [
917
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
918
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-center justify-between gap-4", children: [
919
+ /* @__PURE__ */ jsxRuntime.jsxs(Link3__default.default, { href: home, className: "w-fit rounded-lg", children: [
920
+ brand ?? /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 28 }),
921
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " home" })
922
+ ] }),
923
+ back === void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
924
+ Link3__default.default,
925
+ {
926
+ href: home,
927
+ className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
928
+ children: "Back to home"
929
+ }
930
+ ) : back
931
+ ] }),
932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
933
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
934
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "oca-display-2", children: title }),
935
+ lead ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "oca-lead", children: lead }) : null
936
+ ] }),
937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children }),
938
+ error ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
939
+ fineprint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
940
+ ] })
941
+ ] }),
942
+ /* @__PURE__ */ jsxRuntime.jsxs(
943
+ "aside",
944
+ {
945
+ "aria-hidden": true,
946
+ 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",
947
+ children: [
948
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center justify-center", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(IsoCheck, { size: 340, settle: true, tilt: true, className: "max-w-full" }) }),
949
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
950
+ ]
951
+ }
952
+ )
953
+ ]
954
+ }
955
+ );
956
+ }
397
957
  var ShellContext = react.createContext({});
398
958
  function useShellPlace() {
399
959
  return react.useContext(ShellContext);
@@ -402,7 +962,7 @@ function SideNav({ groups, onNavigate }) {
402
962
  return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Pages", className: "flex flex-col gap-5", children: groups.map((g, gi) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5", children: [
403
963
  g.label ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
404
964
  g.items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
405
- Link2__default.default,
965
+ Link3__default.default,
406
966
  {
407
967
  href: it.href,
408
968
  onClick: onNavigate,
@@ -437,7 +997,7 @@ function SectionSwitch({
437
997
  children: sections.map((sec) => {
438
998
  const on = sec.id === current.id;
439
999
  return /* @__PURE__ */ jsxRuntime.jsx(
440
- Link2__default.default,
1000
+ Link3__default.default,
441
1001
  {
442
1002
  href: sec.href,
443
1003
  onClick: onNavigate,
@@ -467,7 +1027,7 @@ function TabBar({ items }) {
467
1027
  className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
468
1028
  style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
469
1029
  children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
470
- Link2__default.default,
1030
+ Link3__default.default,
471
1031
  {
472
1032
  href: it.href,
473
1033
  "aria-current": it.active ? "page" : void 0,
@@ -576,7 +1136,7 @@ function AppShell({
576
1136
  footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
577
1137
  ] })
578
1138
  ] }),
579
- /* @__PURE__ */ jsxRuntime.jsx(Link2__default.default, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
1139
+ /* @__PURE__ */ jsxRuntime.jsx(Link3__default.default, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 22 }) }),
580
1140
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: account })
581
1141
  ] }),
582
1142
  place.page ? /* @__PURE__ */ jsxRuntime.jsxs(
@@ -599,7 +1159,7 @@ function AppShell({
599
1159
  ] }),
600
1160
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
601
1161
  /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "sticky top-0 hidden h-dvh w-[17rem] shrink-0 flex-col gap-6 overflow-y-auto px-4 py-6 lg:flex", children: [
602
- /* @__PURE__ */ jsxRuntime.jsx(Link2__default.default, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }) }),
1162
+ /* @__PURE__ */ jsxRuntime.jsx(Link3__default.default, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsxRuntime.jsx(Lockup, { size: 26 }) }),
603
1163
  switcher,
604
1164
  /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups }),
605
1165
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
@@ -644,7 +1204,7 @@ function AccountMenu({
644
1204
  ] }),
645
1205
  /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}),
646
1206
  items.map(
647
- (it, i) => it === "separator" ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxRuntime.jsxs(Link2__default.default, { href: it.href, children: [
1207
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxRuntime.jsxs(Link3__default.default, { href: it.href, children: [
648
1208
  it.icon,
649
1209
  it.label
650
1210
  ] }) }, it.label) : /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
@@ -680,9 +1240,13 @@ function ThemeToggle({ className }) {
680
1240
 
681
1241
  exports.AccountMenu = AccountMenu;
682
1242
  exports.AppShell = AppShell;
1243
+ exports.FamilyMenu = FamilyMenu;
683
1244
  exports.ShellContext = ShellContext;
1245
+ exports.SignInFrame = SignInFrame;
1246
+ exports.SiteBanner = SiteBanner;
684
1247
  exports.SiteFooter = SiteFooter;
685
1248
  exports.SiteHeader = SiteHeader;
1249
+ exports.SkipLink = SkipLink;
686
1250
  exports.ThemeToggle = ThemeToggle;
687
1251
  exports.useShellPlace = useShellPlace;
688
1252
  //# sourceMappingURL=chrome.js.map