@orangecheck/app-design 0.6.0 → 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.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, Sun, Moon, SunMoon } from 'lucide-react';
2
+ import Link3 from 'next/link';
3
+ import { forwardRef, createContext, useState, useContext, useMemo, useEffect, useId, useRef } 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,7 @@ 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';
11
12
  import { useTheme } from 'next-themes';
12
13
 
13
14
  var merge = extendTailwindMerge({
@@ -99,6 +100,141 @@ function Lockup({ name = "orangecheck", size = 28, className }) {
99
100
  }
100
101
  );
101
102
  }
103
+
104
+ // src/family/index.ts
105
+ var OCHK_IO = "https://ochk.io";
106
+ var DOCS_HREF = `${OCHK_IO}/docs`;
107
+ function protocol(slug, verb, line, kinds) {
108
+ return {
109
+ slug,
110
+ label: slug,
111
+ href: `${OCHK_IO}/${slug}`,
112
+ group: "protocol",
113
+ line,
114
+ status: "live",
115
+ verb,
116
+ pageHref: `${OCHK_IO}/${slug}`,
117
+ toolHref: `https://${slug}.ochk.io`,
118
+ specHref: `https://github.com/orangecheck/oc-${slug}-protocol`,
119
+ kinds
120
+ };
121
+ }
122
+ var PROTOCOLS = [
123
+ protocol("attest", "identity", "Show that an address holds bitcoin, and for how long.", "30078"),
124
+ protocol("lock", "confidentiality", "Encrypt to a Bitcoin address, so only its holder can open it.", "30078"),
125
+ protocol("vote", "legitimacy", "Polls weighed in sats, that anyone can tally.", "30080\u201330082"),
126
+ protocol("stamp", "provenance", "Prove who signed something, and when.", "30083"),
127
+ protocol("agent", "authority", "Give software scoped, revocable permission to act for you.", "30083\u201330086"),
128
+ protocol("pledge", "commitment", "Make a promise with bitcoin behind it, on a public record.", "30078")
129
+ ];
130
+ PROTOCOLS.map((p) => p.slug);
131
+ var FAMILY = [
132
+ {
133
+ slug: "home",
134
+ label: "ochk.io",
135
+ href: OCHK_IO,
136
+ group: "orangecheck",
137
+ line: "The open protocols, and the company behind them.",
138
+ status: "live"
139
+ },
140
+ {
141
+ slug: "me",
142
+ label: "ochk.app",
143
+ href: "https://ochk.app",
144
+ group: "orangecheck",
145
+ line: "One account, with Bitcoin behind it.",
146
+ status: "testing"
147
+ },
148
+ {
149
+ slug: "docs",
150
+ label: "docs",
151
+ href: DOCS_HREF,
152
+ group: "orangecheck",
153
+ line: "Specs, SDKs and guides for every protocol.",
154
+ status: "live"
155
+ },
156
+ ...PROTOCOLS,
157
+ {
158
+ slug: "vault",
159
+ label: "vault",
160
+ href: "https://vault.ochk.io",
161
+ group: "app",
162
+ line: "A password manager, encrypted in your browser.",
163
+ status: "live",
164
+ protocols: ["lock"]
165
+ },
166
+ {
167
+ slug: "chat",
168
+ label: "chat",
169
+ href: "https://chat.ochk.io",
170
+ group: "app",
171
+ line: "Messages only the holder of a Bitcoin address can read.",
172
+ status: "testing",
173
+ protocols: ["lock"]
174
+ },
175
+ {
176
+ slug: "cosign",
177
+ label: "cosign",
178
+ href: "https://cosign.ochk.io",
179
+ group: "app",
180
+ line: "Builders find co-founders and backers.",
181
+ status: "testing",
182
+ protocols: ["attest"]
183
+ },
184
+ {
185
+ slug: "me-demo",
186
+ // "demo", not the made-up app's own name, so nobody takes it for ours.
187
+ label: "demo",
188
+ href: "https://me-demo.ochk.io",
189
+ group: "app",
190
+ line: "Lumen Notes, a made-up app that signs in with orangecheck.",
191
+ status: "live"
192
+ },
193
+ {
194
+ slug: "globe",
195
+ label: "globe",
196
+ href: "https://globe.ochk.io",
197
+ group: "public-good",
198
+ line: "The Bitcoin network, live, on a globe.",
199
+ status: "live"
200
+ },
201
+ {
202
+ slug: "btc",
203
+ label: "btc",
204
+ href: "https://btc.ochk.io",
205
+ group: "public-good",
206
+ line: "A free desk for reading the Bitcoin market.",
207
+ status: "live"
208
+ }
209
+ ];
210
+ var FAMILY_GROUPS = [
211
+ { id: "orangecheck", label: "orangecheck" },
212
+ { id: "protocol", label: "Protocols" },
213
+ { id: "app", label: "Apps" },
214
+ { id: "public-good", label: "Public goods" }
215
+ ];
216
+ new Map(FAMILY.map((s) => [s.slug, s]));
217
+ function familyByGroup() {
218
+ return FAMILY_GROUPS.map((g) => ({ ...g, sites: FAMILY.filter((s) => s.group === g.id) }));
219
+ }
220
+ var LEGAL_LINKS = [
221
+ { href: `${OCHK_IO}/privacy`, label: "Privacy" },
222
+ { href: `${OCHK_IO}/terms`, label: "Terms" },
223
+ { href: `${OCHK_IO}/security`, label: "Security" },
224
+ { href: `${OCHK_IO}/trademark`, label: "Trademarks" },
225
+ { href: `${OCHK_IO}/contact`, label: "Contact" }
226
+ ];
227
+ [
228
+ {
229
+ href: `${OCHK_IO}/protocols`,
230
+ label: "Protocols",
231
+ children: PROTOCOLS.map((p) => ({ href: p.pageHref, label: p.label, description: p.line }))
232
+ },
233
+ { href: `${OCHK_IO}/apps`, label: "Apps" },
234
+ { href: DOCS_HREF, label: "Docs" },
235
+ { href: `${OCHK_IO}/trust`, label: "Trust" },
236
+ { href: `${OCHK_IO}/about`, label: "About" }
237
+ ];
102
238
  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
239
  forwardRef(function DialogContent2({ className, children, hideClose, ...props }, ref) {
104
240
  return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
@@ -178,7 +314,9 @@ var SheetContent = forwardRef(function SheetContent2({ className, children, side
178
314
  )
179
315
  ] });
180
316
  });
181
- forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 8, ...props }, ref) {
317
+ var Popover = PopoverPrimitive.Root;
318
+ var PopoverTrigger = PopoverPrimitive.Trigger;
319
+ var PopoverContent = forwardRef(function PopoverContent2({ className, align = "center", sideOffset = 8, ...props }, ref) {
182
320
  return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
183
321
  PopoverPrimitive.Content,
184
322
  {
@@ -251,6 +389,132 @@ var DropdownMenuLabel = forwardRef(function DropdownMenuLabel2({ className, ...p
251
389
  var DropdownMenuSeparator = forwardRef(function DropdownMenuSeparator2({ className, ...props }, ref) {
252
390
  return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Separator, { ref, className: cn("my-1.5 h-px bg-border", className), ...props });
253
391
  });
392
+ var GOOD_DOT = "border-border bg-card text-foreground before:size-1.5 before:shrink-0 before:rounded-full before:bg-success before:content-['']";
393
+ var badgeVariants = cva(
394
+ "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",
395
+ {
396
+ variants: {
397
+ tone: {
398
+ neutral: "border-border bg-card text-foreground",
399
+ muted: "border-transparent bg-muted text-muted-foreground",
400
+ brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
401
+ danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
402
+ // A good state is a neutral pill with a green dot, not a green pill.
403
+ success: GOOD_DOT,
404
+ // Aliases kept so older call sites keep compiling: attention is
405
+ // the brand accent, information is neutral.
406
+ warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
407
+ info: "border-border bg-card text-foreground",
408
+ // Inverted in dark mode, where ink would sit on a card of nearly its own colour.
409
+ ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
410
+ onInk: "border-white/15 bg-white/5 text-white/90"
411
+ }
412
+ },
413
+ defaultVariants: { tone: "neutral" }
414
+ }
415
+ );
416
+ function Badge({ className, tone, ...props }) {
417
+ return /* @__PURE__ */ jsx("span", { "data-ui": "badge", className: cn(badgeVariants({ tone }), className), ...props });
418
+ }
419
+ var WORD = {
420
+ live: "Live",
421
+ testing: "In testing",
422
+ "not-yet": "Not yet",
423
+ paused: "Paused",
424
+ good: "Good",
425
+ caution: "Caution",
426
+ refused: "Refused"
427
+ };
428
+ var TONE = {
429
+ live: "success",
430
+ testing: "brand",
431
+ "not-yet": "muted",
432
+ paused: "muted",
433
+ good: "success",
434
+ caution: "brand",
435
+ refused: "danger"
436
+ };
437
+ function StatusBadge({ status, className, ...props }) {
438
+ return /* @__PURE__ */ jsx(Badge, { tone: TONE[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
439
+ }
440
+ function SiteRow({ site, here, onNavigate }) {
441
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
442
+ "a",
443
+ {
444
+ href: site.href,
445
+ onClick: onNavigate,
446
+ "aria-current": here ? "page" : void 0,
447
+ className: cn(
448
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
449
+ here && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
450
+ ),
451
+ children: [
452
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-[0.9375rem] font-medium leading-6", children: [
453
+ site.label,
454
+ site.status !== "live" ? /* @__PURE__ */ jsx(StatusBadge, { status: site.status }) : null,
455
+ here ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(this site)" }) : null
456
+ ] }),
457
+ /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: site.line })
458
+ ]
459
+ }
460
+ ) });
461
+ }
462
+ var PLACE = {
463
+ orangecheck: "sm:col-start-1 sm:row-start-1 lg:row-span-2",
464
+ protocol: "sm:col-start-1 sm:row-start-2 lg:col-start-2 lg:row-start-1 lg:row-span-2",
465
+ app: "sm:col-start-2 sm:row-start-1 lg:col-start-3",
466
+ "public-good": "sm:col-start-2 sm:row-start-2 lg:col-start-3"
467
+ };
468
+ function FamilyList({
469
+ current,
470
+ onNavigate,
471
+ stack = false,
472
+ className
473
+ }) {
474
+ const id = useId();
475
+ return /* @__PURE__ */ jsx(
476
+ "div",
477
+ {
478
+ className: cn(
479
+ "grid grid-cols-1 gap-x-2 gap-y-4",
480
+ // The second desk row takes the slack, so the public goods sit right under the apps.
481
+ !stack && "sm:grid-cols-2 lg:grid-cols-3 lg:grid-rows-[auto_1fr]",
482
+ className
483
+ ),
484
+ children: familyByGroup().map((g) => /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", !stack && PLACE[g.id]), children: [
485
+ /* @__PURE__ */ jsx("p", { id: `${id}-${g.id}`, className: "px-3 pt-1 text-[0.8125rem] text-muted-foreground", children: g.label }),
486
+ /* @__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)) })
487
+ ] }, g.id))
488
+ }
489
+ );
490
+ }
491
+ function FamilyMenu({ current, className }) {
492
+ const [open, setOpen] = useState(false);
493
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
494
+ /* @__PURE__ */ jsx(
495
+ PopoverTrigger,
496
+ {
497
+ "aria-label": "All orangecheck sites",
498
+ className: cn(
499
+ "group inline-flex size-8 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors",
500
+ "hover:bg-accent hover:text-foreground data-[state=open]:bg-accent data-[state=open]:text-foreground",
501
+ className
502
+ ),
503
+ children: /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" })
504
+ }
505
+ ),
506
+ /* @__PURE__ */ jsx(
507
+ PopoverContent,
508
+ {
509
+ align: "start",
510
+ sideOffset: 14,
511
+ collisionPadding: 16,
512
+ 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)]",
513
+ children: /* @__PURE__ */ jsx(FamilyList, { current, onNavigate: () => setOpen(false) })
514
+ }
515
+ )
516
+ ] });
517
+ }
254
518
  function NavLink({ item, className, onNavigate }) {
255
519
  const cls = cn(
256
520
  "rounded-full px-3 py-2 text-[0.9375rem] transition-colors",
@@ -260,42 +524,107 @@ function NavLink({ item, className, onNavigate }) {
260
524
  if (item.external) {
261
525
  return /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: item.label });
262
526
  }
263
- return /* @__PURE__ */ jsx(Link2, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
527
+ return /* @__PURE__ */ jsx(Link3, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: item.label });
528
+ }
529
+ function NavRow({ item, onNavigate }) {
530
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
531
+ /* @__PURE__ */ jsx("span", { className: "text-[0.9375rem] font-medium leading-6 text-foreground", children: item.label }),
532
+ item.description ? /* @__PURE__ */ jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: item.description }) : null
533
+ ] });
534
+ const cls = cn(
535
+ "flex flex-col gap-0.5 rounded-xl px-3 py-2 transition-colors hover:bg-accent",
536
+ item.active && "bg-muted hover:bg-muted dark:bg-white/[0.06]"
537
+ );
538
+ return item.external ? /* @__PURE__ */ jsx("a", { href: item.href, className: cls, rel: "noreferrer", onClick: onNavigate, children: body }) : /* @__PURE__ */ jsx(Link3, { href: item.href, className: cls, "aria-current": item.active ? "page" : void 0, onClick: onNavigate, children: body });
539
+ }
540
+ var seeAll = (item) => typeof item.label === "string" ? `All ${item.label.toLowerCase()}` : "See all";
541
+ function NavDropdown({ item }) {
542
+ const [open, setOpen] = useState(false);
543
+ const active = item.active || item.children?.some((c) => c.active);
544
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
545
+ /* @__PURE__ */ jsxs(
546
+ PopoverTrigger,
547
+ {
548
+ className: cn(
549
+ "group inline-flex items-center gap-1 rounded-full py-2 pl-3 pr-2.5 text-[0.9375rem] transition-colors",
550
+ active ? "text-foreground" : "text-muted-foreground hover:text-foreground data-[state=open]:text-foreground"
551
+ ),
552
+ children: [
553
+ item.label,
554
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-3.5 transition-transform duration-200 group-data-[state=open]:rotate-180" })
555
+ ]
556
+ }
557
+ ),
558
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "center", sideOffset: 10, className: "w-[min(calc(100vw-2rem),26rem)] p-2", children: [
559
+ /* @__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)) }),
560
+ /* @__PURE__ */ jsx("div", { className: "mt-1.5 border-t border-border px-1 pt-1.5", children: /* @__PURE__ */ jsx(
561
+ NavLink,
562
+ {
563
+ item: { ...item, label: seeAll(item), children: void 0 },
564
+ className: "block rounded-xl px-2 py-2 text-[0.875rem]",
565
+ onNavigate: () => setOpen(false)
566
+ }
567
+ ) })
568
+ ] })
569
+ ] });
264
570
  }
265
571
  function SiteHeader({
266
572
  home = "/",
267
573
  brand,
574
+ product,
575
+ family,
268
576
  nav = [],
577
+ search,
269
578
  actions,
579
+ variant = "site",
270
580
  className
271
581
  }) {
272
582
  const [open, setOpen] = useState(false);
583
+ const tool = variant === "tool";
584
+ const size = tool ? 24 : 28;
585
+ const current = typeof family === "string" ? family : void 0;
586
+ const menu = nav.length > 0 || Boolean(family);
587
+ const brandNode = brand ?? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center", children: [
588
+ /* @__PURE__ */ jsx(Lockup, { size }),
589
+ product ? /* @__PURE__ */ jsxs(Fragment, { children: [
590
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "mx-3 h-5 w-px bg-oca-hairline-strong" }),
591
+ /* @__PURE__ */ jsx("span", { className: "font-medium tracking-[-0.01em]", style: { fontSize: size * 0.56 }, children: product })
592
+ ] }) : null
593
+ ] });
594
+ const navigation = nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "hidden items-center gap-1 md:flex", children: nav.map((n) => n.children?.length ? /* @__PURE__ */ jsx(NavDropdown, { item: n }, n.href) : /* @__PURE__ */ jsx(NavLink, { item: n }, n.href)) }) : null;
273
595
  return /* @__PURE__ */ jsx(
274
596
  "header",
275
597
  {
276
598
  className: cn(
277
- "sticky top-0 z-40 w-full border-b border-transparent bg-background/85 backdrop-blur-md supports-[backdrop-filter]:bg-background/70",
599
+ "sticky top-0 z-40 w-full border-b bg-background/95 backdrop-blur-md supports-[backdrop-filter]:bg-background/90",
600
+ tool ? "border-border" : "border-transparent",
278
601
  className
279
602
  ),
280
603
  children: /* @__PURE__ */ jsxs(
281
604
  "div",
282
605
  {
283
606
  className: cn(
284
- "oca-container flex h-16 items-center justify-between gap-4 md:h-[4.5rem]",
607
+ "flex items-center justify-between gap-4",
608
+ tool ? "h-14 px-4 md:px-6" : "oca-container h-16 md:h-[4.5rem]",
285
609
  // Three columns, the outer two each at least their content: the
286
610
  // navigation stays centred whatever the actions hold, so it does
287
611
  // 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)]"
612
+ !tool && nav.length > 0 && "md:grid md:grid-cols-[minmax(max-content,1fr)_auto_minmax(max-content,1fr)]"
289
613
  ),
290
614
  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" })
615
+ /* @__PURE__ */ jsxs("div", { className: cn("flex min-w-0 items-center gap-1", tool ? "md:gap-1" : "justify-self-start"), children: [
616
+ /* @__PURE__ */ jsxs(Link3, { href: home, className: "-ml-1 min-w-0 rounded-lg p-1", children: [
617
+ brandNode,
618
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
619
+ ] }),
620
+ family ? /* @__PURE__ */ jsx(FamilyMenu, { current, className: "max-md:hidden" }) : null,
621
+ tool && navigation ? /* @__PURE__ */ jsx("div", { className: "ml-5", children: navigation }) : null
294
622
  ] }),
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,
623
+ !tool ? navigation : null,
296
624
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-self-end", children: [
625
+ search,
297
626
  actions,
298
- nav.length > 0 ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
627
+ menu ? /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
299
628
  /* @__PURE__ */ jsx(
300
629
  SheetTrigger,
301
630
  {
@@ -306,15 +635,35 @@ function SiteHeader({
306
635
  ),
307
636
  /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "pt-16", children: [
308
637
  /* @__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
- )) })
638
+ nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Main", className: "flex flex-col", children: nav.map(
639
+ (n) => n.children?.length ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col py-2", children: [
640
+ /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: n.label }),
641
+ n.children.map((c) => /* @__PURE__ */ jsx(
642
+ NavLink,
643
+ {
644
+ item: c,
645
+ className: "rounded-xl px-3 py-2.5 text-[1.0625rem]",
646
+ onNavigate: () => setOpen(false)
647
+ },
648
+ c.href
649
+ ))
650
+ ] }, n.href) : /* @__PURE__ */ jsx(
651
+ NavLink,
652
+ {
653
+ item: n,
654
+ className: "rounded-xl px-3 py-3 text-[1.0625rem]",
655
+ onNavigate: () => setOpen(false)
656
+ },
657
+ n.href
658
+ )
659
+ ) }) : null,
660
+ family ? /* @__PURE__ */ jsxs("details", { className: cn("group", nav.length > 0 && "mt-2 border-t border-border pt-4"), children: [
661
+ /* @__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: [
662
+ "All orangecheck sites",
663
+ /* @__PURE__ */ jsx(ChevronDown, { "aria-hidden": true, className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })
664
+ ] }),
665
+ /* @__PURE__ */ jsx(FamilyList, { current, onNavigate: () => setOpen(false), stack: true, className: "mt-2" })
666
+ ] }) : null
318
667
  ] })
319
668
  ] }) : null
320
669
  ] })
@@ -324,48 +673,259 @@ function SiteHeader({
324
673
  }
325
674
  );
326
675
  }
676
+ function SkipLink({ href = "#main-content", children = "Skip to content" }) {
677
+ return /* @__PURE__ */ jsx(
678
+ "a",
679
+ {
680
+ href,
681
+ 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",
682
+ children
683
+ }
684
+ );
685
+ }
686
+ var BANNER_TONE = {
687
+ neutral: "border-border bg-muted",
688
+ brand: "border-[color-mix(in_oklab,var(--oca-orange)_30%,var(--border))] bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--background))]",
689
+ danger: "border-[color-mix(in_oklab,var(--destructive)_35%,var(--border))] bg-[color-mix(in_oklab,var(--destructive)_8%,var(--background))]"
690
+ };
691
+ function SiteBanner({
692
+ tone = "neutral",
693
+ children,
694
+ action,
695
+ className
696
+ }) {
697
+ 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: [
698
+ /* @__PURE__ */ jsxs("p", { className: "flex min-w-0 items-baseline gap-2.5 leading-snug", children: [
699
+ tone !== "neutral" ? /* @__PURE__ */ jsx(
700
+ "span",
701
+ {
702
+ "aria-hidden": true,
703
+ className: cn(
704
+ "size-2 shrink-0 translate-y-[-0.05em] rounded-full",
705
+ tone === "brand" ? "bg-oca-orange" : "bg-destructive"
706
+ )
707
+ }
708
+ ) : null,
709
+ /* @__PURE__ */ jsx("span", { children })
710
+ ] }),
711
+ action ? /* @__PURE__ */ jsx("div", { className: cn("shrink-0 font-medium", tone !== "neutral" && "max-sm:pl-[1.125rem]"), children: action }) : null
712
+ ] }) });
713
+ }
714
+ var FOOT_LINK = "inline-flex min-h-11 items-center transition-colors hover:text-foreground md:min-h-0";
715
+ function LegalRow() {
716
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-x-6 gap-y-2 sm:flex-row sm:items-center sm:justify-between", children: [
717
+ /* @__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)) }) }),
718
+ /* @__PURE__ */ jsxs("p", { children: [
719
+ "\xA9 ",
720
+ (/* @__PURE__ */ new Date()).getFullYear(),
721
+ " OrangeCheck"
722
+ ] })
723
+ ] });
724
+ }
327
725
  function SiteFooter({
328
726
  columns = [],
727
+ family = false,
728
+ legal = false,
729
+ compact = false,
329
730
  fineprint,
330
731
  meta,
331
732
  signature = true,
332
733
  className
333
734
  }) {
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
735
+ if (compact) {
736
+ 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: [
737
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-1", children: [
738
+ /* @__PURE__ */ jsx("a", { href: OCHK_IO, className: "rounded-lg text-foreground", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
739
+ 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
740
  ] }),
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
- ] }),
741
+ 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: [
742
+ legal ? /* @__PURE__ */ jsx(LegalRow, {}) : null,
743
+ meta
744
+ ] }) : null
745
+ ] }) });
746
+ }
747
+ const cols = [
748
+ ...columns,
749
+ ...family ? familyByGroup().map((g) => ({
750
+ // The lockup above already says orangecheck.
751
+ heading: g.id === "orangecheck" ? "Start here" : g.label,
752
+ links: g.sites.map((s) => ({ href: s.href, label: s.label, external: true }))
753
+ })) : []
754
+ ];
755
+ const n = cols.length;
756
+ const inline = n <= 5;
757
+ const grid = {
758
+ "--oca-footer-md": `repeat(${Math.max(1, Math.min(n, 4))}, minmax(0, 1fr))`,
759
+ "--oca-footer-lg": inline ? `minmax(0, 1.3fr) repeat(${Math.max(1, n)}, minmax(0, 1fr))` : `repeat(${Math.min(n, 6)}, minmax(0, 1fr))`
760
+ };
761
+ return /* @__PURE__ */ jsxs("footer", { className: cn("border-t border-border bg-background", className), children: [
762
+ /* @__PURE__ */ jsxs(
763
+ "div",
764
+ {
765
+ style: grid,
766
+ 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)]",
767
+ children: [
768
+ /* @__PURE__ */ jsxs("div", { className: cn("col-span-full flex flex-col gap-4", inline && "lg:col-span-1"), children: [
769
+ /* @__PURE__ */ jsx(Lockup, { size: 26 }),
770
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "max-w-xs text-[0.9375rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
771
+ ] }),
772
+ cols.map((col, i) => {
773
+ const spans = n % 2 === 1 && i === n - 1;
774
+ return /* @__PURE__ */ jsxs(
775
+ "div",
776
+ {
777
+ className: cn("flex min-w-0 flex-col gap-1", spans && "col-span-2 md:col-span-1"),
778
+ children: [
779
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-[0.875rem] font-medium", children: col.heading }),
780
+ /* @__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(
781
+ NavLink,
782
+ {
783
+ item: l,
784
+ className: "-mx-3 py-2.5 text-[0.9375rem] md:py-1.5"
785
+ },
786
+ l.href
787
+ )) })
788
+ ]
789
+ },
790
+ col.heading
791
+ );
792
+ })
793
+ ]
794
+ }
795
+ ),
362
796
  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
797
  /* @__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
798
  /* @__PURE__ */ jsx("span", { children: "orangecheck" })
365
799
  ] }) }) : 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
800
+ 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: [
801
+ legal ? /* @__PURE__ */ jsx(LegalRow, {}) : null,
802
+ meta
803
+ ] }) }) : null
367
804
  ] });
368
805
  }
806
+ function IsoCheck({ size = 360, settle = false, shadow = true, tilt = false, title, className }) {
807
+ const ref = useRef(null);
808
+ useEffect(() => {
809
+ const el = ref.current;
810
+ if (!el || !tilt || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
811
+ let raf = 0;
812
+ let tx = 0;
813
+ let ty = 0;
814
+ let x = 0;
815
+ let y = 0;
816
+ const step = () => {
817
+ x += (tx - x) * 0.08;
818
+ y += (ty - y) * 0.08;
819
+ el.style.setProperty("--rx", `${(-y * 10).toFixed(2)}deg`);
820
+ el.style.setProperty("--ry", `${(x * 14).toFixed(2)}deg`);
821
+ raf = Math.abs(tx - x) + Math.abs(ty - y) > 1e-3 ? requestAnimationFrame(step) : 0;
822
+ };
823
+ const move = (e) => {
824
+ const b = el.getBoundingClientRect();
825
+ tx = Math.max(-1, Math.min(1, (e.clientX - (b.left + b.width / 2)) / (window.innerWidth / 2)));
826
+ ty = Math.max(-1, Math.min(1, (e.clientY - (b.top + b.height / 2)) / (window.innerHeight / 2)));
827
+ if (!raf) raf = requestAnimationFrame(step);
828
+ };
829
+ window.addEventListener("pointermove", move, { passive: true });
830
+ return () => {
831
+ cancelAnimationFrame(raf);
832
+ window.removeEventListener("pointermove", move);
833
+ };
834
+ }, [tilt]);
835
+ return /* @__PURE__ */ jsxs(
836
+ "div",
837
+ {
838
+ ref,
839
+ className: cn("relative inline-block", settle && "oca-animate-settle", className),
840
+ style: { width: size, perspective: tilt ? 900 : void 0 },
841
+ children: [
842
+ tilt ? /* @__PURE__ */ jsx(
843
+ "div",
844
+ {
845
+ "aria-hidden": true,
846
+ 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",
847
+ style: { background: "radial-gradient(closest-side, rgb(255 140 70 / 0.35), transparent)" }
848
+ }
849
+ ) : null,
850
+ /* @__PURE__ */ jsx(
851
+ "div",
852
+ {
853
+ className: "relative z-10 transition-transform duration-300 ease-out",
854
+ style: tilt ? { transform: "rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))", transformStyle: "preserve-3d" } : void 0,
855
+ children: /* @__PURE__ */ jsx(Mark, { size, title, className: "block" })
856
+ }
857
+ ),
858
+ shadow ? /* @__PURE__ */ jsx(
859
+ "div",
860
+ {
861
+ "aria-hidden": true,
862
+ className: "absolute left-[8%] right-[8%] rounded-[50%] opacity-60 blur-xl",
863
+ style: { height: size * 0.08, bottom: -size * 0.04, background: "rgb(234 88 11 / 0.18)" }
864
+ }
865
+ ) : null
866
+ ]
867
+ }
868
+ );
869
+ }
870
+ function SignInFrame({
871
+ title = "Sign in",
872
+ lead,
873
+ children,
874
+ error,
875
+ fineprint,
876
+ brand,
877
+ home = "/",
878
+ back,
879
+ art,
880
+ caption,
881
+ className
882
+ }) {
883
+ return /* @__PURE__ */ jsxs(
884
+ "main",
885
+ {
886
+ id: "main-content",
887
+ className: cn("grid min-h-dvh grid-cols-1 bg-background text-foreground lg:grid-cols-2", className),
888
+ children: [
889
+ /* @__PURE__ */ jsxs("section", { className: "flex flex-col px-4 pb-8 pt-5 sm:px-8 lg:px-14 lg:pt-8", children: [
890
+ /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between gap-4", children: [
891
+ /* @__PURE__ */ jsxs(Link3, { href: home, className: "w-fit rounded-lg", children: [
892
+ brand ?? /* @__PURE__ */ jsx(Lockup, { size: 28 }),
893
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: " home" })
894
+ ] }),
895
+ back === void 0 ? /* @__PURE__ */ jsx(
896
+ Link3,
897
+ {
898
+ href: home,
899
+ className: "text-[0.9375rem] text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
900
+ children: "Back to home"
901
+ }
902
+ ) : back
903
+ ] }),
904
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[25rem] flex-1 flex-col justify-center gap-9 py-12", children: [
905
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
906
+ /* @__PURE__ */ jsx("h1", { className: "oca-display-2", children: title }),
907
+ lead ? /* @__PURE__ */ jsx("p", { className: "oca-lead", children: lead }) : null
908
+ ] }),
909
+ /* @__PURE__ */ jsx("div", { children }),
910
+ error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[0.9375rem] text-destructive", children: error }) : null,
911
+ fineprint ? /* @__PURE__ */ jsx("p", { className: "text-[0.8125rem] leading-relaxed text-muted-foreground", children: fineprint }) : null
912
+ ] })
913
+ ] }),
914
+ /* @__PURE__ */ jsxs(
915
+ "aside",
916
+ {
917
+ "aria-hidden": true,
918
+ 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",
919
+ children: [
920
+ /* @__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" }) }),
921
+ caption ? /* @__PURE__ */ jsx("div", { className: "flex max-w-[24rem] flex-col gap-3", children: caption }) : null
922
+ ]
923
+ }
924
+ )
925
+ ]
926
+ }
927
+ );
928
+ }
369
929
  var ShellContext = createContext({});
370
930
  function useShellPlace() {
371
931
  return useContext(ShellContext);
@@ -374,7 +934,7 @@ function SideNav({ groups, onNavigate }) {
374
934
  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
935
  g.label ? /* @__PURE__ */ jsx("p", { className: "px-3 pb-1 text-[0.8125rem] text-muted-foreground", children: g.label }) : null,
376
936
  g.items.map((it) => /* @__PURE__ */ jsxs(
377
- Link2,
937
+ Link3,
378
938
  {
379
939
  href: it.href,
380
940
  onClick: onNavigate,
@@ -409,7 +969,7 @@ function SectionSwitch({
409
969
  children: sections.map((sec) => {
410
970
  const on = sec.id === current.id;
411
971
  return /* @__PURE__ */ jsx(
412
- Link2,
972
+ Link3,
413
973
  {
414
974
  href: sec.href,
415
975
  onClick: onNavigate,
@@ -439,7 +999,7 @@ function TabBar({ items }) {
439
999
  className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
440
1000
  style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
441
1001
  children: items.map((it) => /* @__PURE__ */ jsxs(
442
- Link2,
1002
+ Link3,
443
1003
  {
444
1004
  href: it.href,
445
1005
  "aria-current": it.active ? "page" : void 0,
@@ -548,7 +1108,7 @@ function AppShell({
548
1108
  footer ? /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
549
1109
  ] })
550
1110
  ] }),
551
- /* @__PURE__ */ jsx(Link2, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
1111
+ /* @__PURE__ */ jsx(Link3, { href: home, "aria-label": "Home", className: "rounded-lg p-1", children: /* @__PURE__ */ jsx(Lockup, { size: 22 }) }),
552
1112
  /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: account })
553
1113
  ] }),
554
1114
  place.page ? /* @__PURE__ */ jsxs(
@@ -571,7 +1131,7 @@ function AppShell({
571
1131
  ] }),
572
1132
  /* @__PURE__ */ jsxs("div", { className: "mx-auto flex w-full max-w-[90rem]", children: [
573
1133
  /* @__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 }) }),
1134
+ /* @__PURE__ */ jsx(Link3, { href: home, className: "px-2", "aria-label": "Home", children: /* @__PURE__ */ jsx(Lockup, { size: 26 }) }),
575
1135
  switcher,
576
1136
  /* @__PURE__ */ jsx(SideNav, { groups }),
577
1137
  /* @__PURE__ */ jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer })
@@ -616,7 +1176,7 @@ function AccountMenu({
616
1176
  ] }),
617
1177
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
618
1178
  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: [
1179
+ (it, i) => it === "separator" ? /* @__PURE__ */ jsx(DropdownMenuSeparator, {}, `sep-${i}`) : it.href ? /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, destructive: it.destructive, children: /* @__PURE__ */ jsxs(Link3, { href: it.href, children: [
620
1180
  it.icon,
621
1181
  it.label
622
1182
  ] }) }, it.label) : /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: it.onSelect, destructive: it.destructive, children: [
@@ -650,6 +1210,6 @@ function ThemeToggle({ className }) {
650
1210
  );
651
1211
  }
652
1212
 
653
- export { AccountMenu, AppShell, ShellContext, SiteFooter, SiteHeader, ThemeToggle, useShellPlace };
1213
+ export { AccountMenu, AppShell, FamilyMenu, ShellContext, SignInFrame, SiteBanner, SiteFooter, SiteHeader, SkipLink, ThemeToggle, useShellPlace };
654
1214
  //# sourceMappingURL=chrome.mjs.map
655
1215
  //# sourceMappingURL=chrome.mjs.map