@orangecheck/design 0.18.0 → 0.20.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 (42) hide show
  1. package/dist/chrome.d.mts +1 -1
  2. package/dist/chrome.d.ts +1 -1
  3. package/dist/chrome.js +16 -0
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/chrome.mjs +16 -0
  6. package/dist/chrome.mjs.map +1 -1
  7. package/dist/components.d.mts +1 -1
  8. package/dist/components.d.ts +1 -1
  9. package/dist/components.js +830 -178
  10. package/dist/components.js.map +1 -1
  11. package/dist/components.mjs +780 -143
  12. package/dist/components.mjs.map +1 -1
  13. package/dist/composites.d.mts +142 -1
  14. package/dist/composites.d.ts +142 -1
  15. package/dist/composites.js +641 -3
  16. package/dist/composites.js.map +1 -1
  17. package/dist/composites.mjs +627 -4
  18. package/dist/composites.mjs.map +1 -1
  19. package/dist/index.d.mts +2 -2
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +538 -11
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +522 -13
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/primitives.d.mts +24 -4
  26. package/dist/primitives.d.ts +24 -4
  27. package/dist/primitives.js +123 -11
  28. package/dist/primitives.js.map +1 -1
  29. package/dist/primitives.mjs +121 -13
  30. package/dist/primitives.mjs.map +1 -1
  31. package/dist/styles/fonts/hanken-grotesk-latin-ext.woff2 +0 -0
  32. package/dist/styles/fonts/hanken-grotesk-latin.woff2 +0 -0
  33. package/dist/styles/fonts.css +29 -0
  34. package/dist/styles/theme.css +43 -5
  35. package/dist/styles/themes/ember.css +223 -0
  36. package/dist/styles/themes.css +1 -0
  37. package/dist/styles.css +1 -0
  38. package/dist/tokens.js +6 -0
  39. package/dist/tokens.js.map +1 -1
  40. package/dist/tokens.mjs +6 -0
  41. package/dist/tokens.mjs.map +1 -1
  42. package/package.json +1 -1
@@ -1,14 +1,27 @@
1
1
  import * as Popover from '@radix-ui/react-popover';
2
- import { HelpCircle, Boxes, ChevronDown, Check, CornerDownLeft, Plus, Loader2, Copy, X, Menu, Sun, Moon, Monitor } from 'lucide-react';
2
+ import { ChevronDown, Plus, HelpCircle, X, Check, Boxes, CornerDownLeft, Loader2, Copy, Menu, Sun, Moon, Monitor } from 'lucide-react';
3
3
  import { clsx } from 'clsx';
4
4
  import { twMerge } from 'tailwind-merge';
5
- import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
5
+ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
6
6
  import Link6 from 'next/link';
7
- import * as React from 'react';
7
+ import * as React2 from 'react';
8
8
  import { createContext, Fragment, useState, useRef, useEffect, useId, useContext } from 'react';
9
+ import { Slot } from '@radix-ui/react-slot';
10
+ import { cva } from 'class-variance-authority';
11
+ import '@radix-ui/react-label';
12
+ import '@radix-ui/react-checkbox';
13
+ import '@radix-ui/react-radio-group';
14
+ import '@radix-ui/react-switch';
15
+ import { useTheme } from 'next-themes';
16
+ import '@radix-ui/react-separator';
17
+ import '@radix-ui/react-dialog';
18
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
19
+ import '@radix-ui/react-select';
20
+ import 'sonner';
21
+ import '@radix-ui/react-tabs';
22
+ import 'qrcode';
9
23
  import { useRouter } from 'next/router';
10
24
  import { useOcSession, fetchOcLinkedIdentities } from '@orangecheck/auth-client';
11
- import { useTheme } from 'next-themes';
12
25
 
13
26
  // src/composites/help-hint.tsx
14
27
  function cn(...inputs) {
@@ -165,7 +178,7 @@ function StatTile({ children, ...item }) {
165
178
  function StatBlock({ label, value, sub, delta, tone = "default", className }) {
166
179
  const toneClass = tone === "success" ? "text-success" : tone === "warning" ? "text-warning" : tone === "destructive" ? "text-destructive" : "text-foreground";
167
180
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", className), children: [
168
- /* @__PURE__ */ jsx("span", { className: "label-mono text-[10px]", children: label }),
181
+ /* @__PURE__ */ jsx("span", { className: "label-mono text-muted-foreground text-[10px]", children: label }),
169
182
  /* @__PURE__ */ jsx(
170
183
  "span",
171
184
  {
@@ -263,6 +276,749 @@ function DataRow({ children, meta, action, as, className }) {
263
276
  }
264
277
  );
265
278
  }
279
+ function TwoToneHeading({
280
+ lead,
281
+ muted,
282
+ as,
283
+ tone = "default",
284
+ className
285
+ }) {
286
+ const Tag = as ?? "h2";
287
+ const leadColor = tone === "onBrand" ? "text-primary-foreground" : "text-foreground";
288
+ const mutedColor = tone === "onBrand" ? "text-primary-foreground/60" : "text-foreground/40";
289
+ return /* @__PURE__ */ jsxs(
290
+ Tag,
291
+ {
292
+ className: cn(
293
+ "font-extrabold tracking-[-0.02em] leading-[1.0] text-balance",
294
+ "text-3xl sm:text-4xl md:text-5xl",
295
+ leadColor,
296
+ className
297
+ ),
298
+ children: [
299
+ /* @__PURE__ */ jsx("span", { children: lead }),
300
+ muted ? /* @__PURE__ */ jsxs("span", { className: mutedColor, children: [
301
+ " ",
302
+ muted
303
+ ] }) : null
304
+ ]
305
+ }
306
+ );
307
+ }
308
+ function MarketingHeading({
309
+ eyebrow,
310
+ lead,
311
+ muted,
312
+ body,
313
+ align = "start",
314
+ tone = "default",
315
+ as,
316
+ className
317
+ }) {
318
+ const centered = align === "center";
319
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", centered && "items-center text-center", className), children: [
320
+ eyebrow && /* @__PURE__ */ jsx(
321
+ "p",
322
+ {
323
+ className: cn(
324
+ "label-mono mb-3",
325
+ tone === "onBrand" ? "text-primary-foreground/80" : "text-primary"
326
+ ),
327
+ children: eyebrow
328
+ }
329
+ ),
330
+ /* @__PURE__ */ jsx(
331
+ TwoToneHeading,
332
+ {
333
+ lead,
334
+ muted,
335
+ as,
336
+ tone,
337
+ className: cn("max-w-4xl", centered && "mx-auto")
338
+ }
339
+ ),
340
+ body && /* @__PURE__ */ jsx(
341
+ "p",
342
+ {
343
+ className: cn(
344
+ "mt-4 max-w-2xl text-base sm:text-lg",
345
+ tone === "onBrand" ? "text-primary-foreground/80" : "text-muted-foreground",
346
+ centered && "mx-auto"
347
+ ),
348
+ children: body
349
+ }
350
+ )
351
+ ] });
352
+ }
353
+ var buttonVariants = cva(
354
+ "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
355
+ {
356
+ variants: {
357
+ variant: {
358
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
359
+ destructive: "bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white",
360
+ outline: "bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs",
361
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
362
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
363
+ link: "text-primary underline-offset-4 hover:underline",
364
+ // For CTAs placed ON a saturated brand band or a dark section
365
+ // (e.g. a terracotta hero / footer / a forced-dark block) where
366
+ // the surface is dark+light-text in either mode. A neutral white
367
+ // pill + a translucent-white ghost read on any such surface;
368
+ // hardcoded white is deliberate (cf. destructive's text-white).
369
+ onBrand: "bg-white text-neutral-900 shadow-sm hover:bg-white/90",
370
+ onBrandOutline: "border border-white/40 bg-transparent text-white hover:bg-white/10"
371
+ },
372
+ size: {
373
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
374
+ sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
375
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
376
+ icon: "size-9"
377
+ }
378
+ },
379
+ defaultVariants: {
380
+ variant: "default",
381
+ size: "default"
382
+ }
383
+ }
384
+ );
385
+ function Button({
386
+ className,
387
+ variant,
388
+ size,
389
+ asChild = false,
390
+ ...props
391
+ }) {
392
+ const Comp = asChild ? Slot : "button";
393
+ return /* @__PURE__ */ jsx(
394
+ Comp,
395
+ {
396
+ "data-slot": "button",
397
+ className: cn(buttonVariants({ variant, size, className })),
398
+ ...props
399
+ }
400
+ );
401
+ }
402
+ cva(
403
+ "focus-visible:border-ring focus-visible:ring-ring/50 inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-md border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3",
404
+ {
405
+ variants: {
406
+ variant: {
407
+ default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent",
408
+ secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent",
409
+ destructive: "bg-destructive text-destructive-foreground [a&]:hover:bg-destructive/90 border-transparent",
410
+ warning: "bg-warning text-warning-foreground [a&]:hover:bg-warning/90 border-transparent",
411
+ success: "bg-success text-success-foreground [a&]:hover:bg-success/90 border-transparent",
412
+ info: "bg-info text-info-foreground [a&]:hover:bg-info/90 border-transparent",
413
+ brand: "bg-brand-soft text-accent-foreground border-transparent",
414
+ neutral: "bg-foreground text-background [a&]:hover:bg-foreground/90 border-transparent",
415
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
416
+ }
417
+ },
418
+ defaultVariants: { variant: "default" }
419
+ }
420
+ );
421
+ function Input({ className, type, ...props }) {
422
+ return /* @__PURE__ */ jsx(
423
+ "input",
424
+ {
425
+ type,
426
+ "data-slot": "input",
427
+ className: cn(
428
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input bg-input/30 hover:bg-input/50 dark:bg-input/30 dark:hover:bg-input/50 h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base shadow-xs transition-[color,box-shadow,background-color] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
429
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
430
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
431
+ className
432
+ ),
433
+ ...props
434
+ }
435
+ );
436
+ }
437
+ cva(
438
+ "relative grid w-full grid-cols-[0_1fr] items-start gap-x-0 gap-y-0.5 rounded-md border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
439
+ {
440
+ variants: {
441
+ variant: {
442
+ default: "bg-card text-card-foreground",
443
+ destructive: "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
444
+ success: "text-success bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-success/90",
445
+ warning: "text-warning bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-warning/90"
446
+ }
447
+ },
448
+ defaultVariants: { variant: "default" }
449
+ }
450
+ );
451
+ globalThis.process?.env?.NODE_ENV;
452
+ globalThis.process?.env?.NODE_ENV;
453
+ var TOOLTIP_SURFACE_CLASS = "bg-popover text-popover-foreground border-border rounded-md border p-2.5 shadow-md";
454
+ var TOOLTIP_MOTION_CLASS = "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 origin-(--radix-popover-content-transform-origin) duration-150 ease-out";
455
+ function compose(theirs, ours) {
456
+ return (e) => {
457
+ theirs?.(e);
458
+ ours(e);
459
+ };
460
+ }
461
+ var lastInputWasKeyboard = false;
462
+ var modalityInstalled = false;
463
+ function installModalityTracking() {
464
+ if (modalityInstalled || typeof window === "undefined") return;
465
+ modalityInstalled = true;
466
+ window.addEventListener("keydown", () => lastInputWasKeyboard = true, true);
467
+ window.addEventListener("pointerdown", () => lastInputWasKeyboard = false, true);
468
+ }
469
+ function Tooltip({
470
+ content,
471
+ children,
472
+ side = "bottom",
473
+ align = "start",
474
+ sideOffset = 8,
475
+ collisionPadding = 12,
476
+ openDelay = 300,
477
+ closeDelay = 90,
478
+ disabled = false,
479
+ portal = true,
480
+ zIndexClassName = "z-50",
481
+ contentClassName
482
+ }) {
483
+ const [hovering, setHovering] = React2.useState(false);
484
+ const [focusing, setFocusing] = React2.useState(false);
485
+ const [isFinePointer, setIsFinePointer] = React2.useState(false);
486
+ const openTimer = React2.useRef(null);
487
+ const closeTimer = React2.useRef(null);
488
+ React2.useEffect(() => {
489
+ installModalityTracking();
490
+ const mq = window.matchMedia("(hover: hover) and (pointer: fine)");
491
+ const apply = () => setIsFinePointer(mq.matches);
492
+ apply();
493
+ mq.addEventListener("change", apply);
494
+ return () => mq.removeEventListener("change", apply);
495
+ }, []);
496
+ const clearTimers = React2.useCallback(() => {
497
+ if (openTimer.current) clearTimeout(openTimer.current);
498
+ if (closeTimer.current) clearTimeout(closeTimer.current);
499
+ }, []);
500
+ React2.useEffect(() => clearTimers, [clearTimers]);
501
+ React2.useEffect(() => {
502
+ if (disabled) {
503
+ clearTimers();
504
+ setHovering(false);
505
+ }
506
+ }, [disabled, clearTimers]);
507
+ const handlePointerEnter = () => {
508
+ if (!isFinePointer) return;
509
+ if (closeTimer.current) clearTimeout(closeTimer.current);
510
+ openTimer.current = setTimeout(() => setHovering(true), openDelay);
511
+ };
512
+ const handlePointerLeave = () => {
513
+ if (openTimer.current) clearTimeout(openTimer.current);
514
+ closeTimer.current = setTimeout(() => setHovering(false), closeDelay);
515
+ };
516
+ const handlePointerDown = () => {
517
+ clearTimers();
518
+ setHovering(false);
519
+ setFocusing(false);
520
+ };
521
+ const handleFocus = () => {
522
+ if (lastInputWasKeyboard) {
523
+ clearTimers();
524
+ setFocusing(true);
525
+ }
526
+ };
527
+ const handleBlur = () => {
528
+ clearTimers();
529
+ setFocusing(false);
530
+ };
531
+ const handleKeyDown = (e) => {
532
+ if (e.key === "Escape") {
533
+ clearTimers();
534
+ setHovering(false);
535
+ setFocusing(false);
536
+ }
537
+ };
538
+ const effectiveOpen = !disabled && (isFinePointer && hovering || focusing);
539
+ const extra = {};
540
+ const childProps = children.props;
541
+ extra.onPointerEnter = compose(childProps.onPointerEnter, handlePointerEnter);
542
+ extra.onPointerLeave = compose(childProps.onPointerLeave, handlePointerLeave);
543
+ extra.onPointerDown = compose(childProps.onPointerDown, handlePointerDown);
544
+ extra.onFocus = compose(childProps.onFocus, handleFocus);
545
+ extra.onBlur = compose(childProps.onBlur, handleBlur);
546
+ extra.onKeyDown = compose(childProps.onKeyDown, handleKeyDown);
547
+ const trigger = React2.cloneElement(children, extra);
548
+ const contentEl = /* @__PURE__ */ jsx(
549
+ Popover.Content,
550
+ {
551
+ side,
552
+ align,
553
+ sideOffset,
554
+ collisionPadding,
555
+ "aria-hidden": true,
556
+ onOpenAutoFocus: (e) => e.preventDefault(),
557
+ onCloseAutoFocus: (e) => e.preventDefault(),
558
+ onFocusOutside: (e) => e.preventDefault(),
559
+ className: cn(
560
+ TOOLTIP_SURFACE_CLASS,
561
+ TOOLTIP_MOTION_CLASS,
562
+ "pointer-events-none",
563
+ zIndexClassName,
564
+ contentClassName
565
+ ),
566
+ children: content
567
+ }
568
+ );
569
+ return /* @__PURE__ */ jsxs(
570
+ Popover.Root,
571
+ {
572
+ open: effectiveOpen,
573
+ onOpenChange: (o) => {
574
+ if (!o) {
575
+ clearTimers();
576
+ setHovering(false);
577
+ setFocusing(false);
578
+ }
579
+ },
580
+ modal: false,
581
+ children: [
582
+ /* @__PURE__ */ jsx(Popover.Anchor, { asChild: true, children: trigger }),
583
+ portal ? /* @__PURE__ */ jsx(Popover.Portal, { children: contentEl }) : contentEl
584
+ ]
585
+ }
586
+ );
587
+ }
588
+ var Accordion = AccordionPrimitive.Root;
589
+ var AccordionItem = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(AccordionPrimitive.Item, { ref, className: cn("border-b", className), ...props }));
590
+ AccordionItem.displayName = "AccordionItem";
591
+ var AccordionTrigger = React2.forwardRef(({ className, children, icon = "chevron", ...props }, ref) => /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
592
+ AccordionPrimitive.Trigger,
593
+ {
594
+ ref,
595
+ className: cn(
596
+ "flex flex-1 items-center justify-between gap-4 py-4 text-left font-medium transition-all hover:underline",
597
+ icon === "chevron" ? "[&[data-state=open]>svg]:rotate-180" : "[&[data-state=open]>svg]:rotate-45",
598
+ className
599
+ ),
600
+ ...props,
601
+ children: [
602
+ children,
603
+ icon === "chevron" ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 transition-transform duration-200" }) : /* @__PURE__ */ jsx(Plus, { className: "text-primary h-5 w-5 shrink-0 transition-transform duration-200" })
604
+ ]
605
+ }
606
+ ) }));
607
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
608
+ var AccordionContent = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
609
+ AccordionPrimitive.Content,
610
+ {
611
+ ref,
612
+ className: "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all",
613
+ ...props,
614
+ children: /* @__PURE__ */ jsx("div", { className: cn("pt-0 pb-4", className), children })
615
+ }
616
+ ));
617
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
618
+ var surfaceVariants = cva("rounded-xl transition-colors", {
619
+ variants: {
620
+ tone: {
621
+ /* Crisp panel floating on the page — the default soft card. */
622
+ default: "bg-card text-card-foreground",
623
+ /* Warm-gray recessed panel. */
624
+ muted: "bg-muted text-foreground",
625
+ /* Solid brand fill — small terracotta panel; inverts child text. */
626
+ brand: "bg-brand text-brand-foreground",
627
+ /* High-contrast neutral panel (near-black in light, near-white in dark). */
628
+ contrast: "bg-foreground text-background",
629
+ /* Translucent lightened tile for cards sitting ON a brand band. */
630
+ onBrand: "text-brand-foreground [background:color-mix(in_oklch,white_16%,var(--brand))] [border-color:color-mix(in_oklch,white_24%,transparent)]",
631
+ /* Frame only, transparent fill. */
632
+ outline: "bg-transparent text-foreground"
633
+ },
634
+ elevation: {
635
+ none: "shadow-none",
636
+ sm: "shadow-sm",
637
+ md: "shadow-md",
638
+ lg: "shadow-lg",
639
+ xl: "shadow-xl"
640
+ },
641
+ bordered: {
642
+ true: "border",
643
+ false: ""
644
+ },
645
+ pad: {
646
+ none: "p-0",
647
+ sm: "p-4",
648
+ md: "p-5 sm:p-6",
649
+ lg: "p-6 sm:p-8"
650
+ }
651
+ },
652
+ defaultVariants: {
653
+ tone: "default",
654
+ elevation: "sm",
655
+ bordered: true,
656
+ pad: "md"
657
+ }
658
+ });
659
+ function Surface({
660
+ className,
661
+ tone,
662
+ elevation,
663
+ bordered,
664
+ pad,
665
+ ...props
666
+ }) {
667
+ return /* @__PURE__ */ jsx(
668
+ "div",
669
+ {
670
+ "data-slot": "surface",
671
+ className: cn(surfaceVariants({ tone, elevation, bordered, pad }), className),
672
+ ...props
673
+ }
674
+ );
675
+ }
676
+ var iconBadgeVariants = cva(
677
+ "inline-flex shrink-0 items-center justify-center rounded-md font-semibold [&_svg]:pointer-events-none",
678
+ {
679
+ variants: {
680
+ tone: {
681
+ /* The signature peach tile — soft accent fill, terracotta glyph.
682
+ Auto-swaps to warm-dark + light-peach in dark mode via tokens. */
683
+ peach: "bg-accent text-accent-foreground",
684
+ /* Inverted near-black tile, light glyph ("never do" promises). */
685
+ dark: "bg-foreground text-background",
686
+ /* Solid brand tile. */
687
+ brand: "bg-primary text-primary-foreground",
688
+ /* White tile on a brand band, terracotta glyph (numbered steps). */
689
+ onBrand: "bg-brand-foreground text-primary",
690
+ /* Quiet neutral tile. */
691
+ muted: "bg-muted text-foreground",
692
+ /* Crisp white (card-colored) tile with a terracotta glyph and a
693
+ soft lift — the elevated icon chip on muted/colored cards. */
694
+ surface: "bg-card text-primary shadow-sm"
695
+ },
696
+ size: {
697
+ sm: "size-9 text-xs [&_svg]:size-4",
698
+ md: "size-11 text-sm [&_svg]:size-5",
699
+ lg: "size-12 text-base [&_svg]:size-6",
700
+ xl: "size-14 text-lg [&_svg]:size-7"
701
+ }
702
+ },
703
+ defaultVariants: { tone: "peach", size: "md" }
704
+ }
705
+ );
706
+ function IconBadge({ className, tone, size, children, ...props }) {
707
+ return /* @__PURE__ */ jsx(
708
+ "span",
709
+ {
710
+ "data-slot": "icon-badge",
711
+ className: cn(iconBadgeVariants({ tone, size }), className),
712
+ ...props,
713
+ children
714
+ }
715
+ );
716
+ }
717
+ function FeatureCard({
718
+ icon,
719
+ iconTone = "peach",
720
+ title,
721
+ children,
722
+ orientation = "vertical",
723
+ align = "start",
724
+ tone = "default",
725
+ elevation = "sm",
726
+ className
727
+ }) {
728
+ const horizontal = orientation === "horizontal";
729
+ const centered = !horizontal && align === "center";
730
+ return /* @__PURE__ */ jsxs(
731
+ Surface,
732
+ {
733
+ tone,
734
+ elevation,
735
+ pad: horizontal ? "md" : "lg",
736
+ className: cn(
737
+ "flex h-full",
738
+ horizontal ? "flex-row gap-4" : "flex-col",
739
+ centered && "items-center text-center",
740
+ className
741
+ ),
742
+ children: [
743
+ icon && /* @__PURE__ */ jsx(
744
+ IconBadge,
745
+ {
746
+ tone: iconTone,
747
+ size: "lg",
748
+ className: cn(horizontal ? "shrink-0" : "mb-4"),
749
+ children: icon
750
+ }
751
+ ),
752
+ /* @__PURE__ */ jsxs("div", { className: cn(horizontal && "min-w-0"), children: [
753
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: title }),
754
+ children && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1.5 text-sm leading-relaxed", children })
755
+ ] })
756
+ ]
757
+ }
758
+ );
759
+ }
760
+ var TONE = {
761
+ default: "bg-background text-foreground",
762
+ muted: "bg-muted text-foreground",
763
+ brand: "bg-brand text-brand-foreground",
764
+ // `dark` activates the .dark variant locally so descendant package
765
+ // components render their dark arm even on an otherwise light page.
766
+ dark: "dark bg-background text-foreground"
767
+ };
768
+ var WIDTH = {
769
+ default: "container",
770
+ wide: "mx-auto w-full max-w-screen-2xl px-4 sm:px-6 lg:px-8",
771
+ full: ""
772
+ };
773
+ function Section({
774
+ tone = "default",
775
+ width = "default",
776
+ diagonal,
777
+ id,
778
+ className,
779
+ innerClassName,
780
+ children
781
+ }) {
782
+ const showDiagonal = diagonal ?? tone === "brand";
783
+ return /* @__PURE__ */ jsx(
784
+ "div",
785
+ {
786
+ id,
787
+ className: cn("w-full", TONE[tone], showDiagonal && "oc-diagonal", className),
788
+ children: /* @__PURE__ */ jsx("div", { className: cn("py-16 sm:py-20 md:py-24", WIDTH[width], innerClassName), children })
789
+ }
790
+ );
791
+ }
792
+ function BrandBand(props) {
793
+ return /* @__PURE__ */ jsx(Section, { tone: "brand", ...props });
794
+ }
795
+ function ComparisonTable({ rows, columns, className }) {
796
+ const cols = { feature: "", theirs: "A normal login", ours: "OrangeCheck", ...columns };
797
+ return /* @__PURE__ */ jsx("div", { className: cn("overflow-hidden rounded-xl border", className), children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("div", { className: "min-w-[32rem]", children: [
798
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1.4fr_1fr_1fr]", children: [
799
+ /* @__PURE__ */ jsx("div", { className: "label-mono text-muted-foreground px-4 py-3.5 sm:px-6", children: cols.feature }),
800
+ /* @__PURE__ */ jsx("div", { className: "px-4 py-3.5 font-semibold text-foreground sm:px-6", children: cols.theirs }),
801
+ /* @__PURE__ */ jsx("div", { className: "bg-accent/60 border-border/60 border-l px-4 py-3.5 font-semibold text-primary sm:px-6", children: cols.ours })
802
+ ] }),
803
+ rows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1.4fr_1fr_1fr] border-t", children: [
804
+ /* @__PURE__ */ jsx("div", { className: "px-4 py-3.5 font-medium text-foreground sm:px-6", children: row.label }),
805
+ /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground flex items-center gap-2 px-4 py-3.5 sm:px-6", children: [
806
+ /* @__PURE__ */ jsx(X, { className: "text-muted-foreground/70 size-4" }),
807
+ /* @__PURE__ */ jsx("span", { children: row.theirs })
808
+ ] }),
809
+ /* @__PURE__ */ jsxs("div", { className: "bg-accent/40 border-border/60 flex items-center gap-2 border-l px-4 py-3.5 text-foreground sm:px-6", children: [
810
+ /* @__PURE__ */ jsx(Check, { className: "size-4 text-primary" }),
811
+ /* @__PURE__ */ jsx("span", { children: row.ours })
812
+ ] })
813
+ ] }, i))
814
+ ] }) }) });
815
+ }
816
+ function NumberedStep({
817
+ n,
818
+ title,
819
+ children,
820
+ tone = "default",
821
+ card = false,
822
+ className
823
+ }) {
824
+ const onBrand = tone === "onBrand";
825
+ const body = /* @__PURE__ */ jsxs("div", { className: cn(!card && className), children: [
826
+ /* @__PURE__ */ jsx(IconBadge, { tone: onBrand ? "onBrand" : "peach", size: "sm", children: n }),
827
+ /* @__PURE__ */ jsx("div", { className: "mt-4 text-lg font-semibold", children: title }),
828
+ children && /* @__PURE__ */ jsx(
829
+ "div",
830
+ {
831
+ className: cn(
832
+ "mt-1.5 text-sm leading-relaxed",
833
+ onBrand ? "text-brand-foreground/80" : "text-muted-foreground"
834
+ ),
835
+ children
836
+ }
837
+ )
838
+ ] });
839
+ if (!card) return body;
840
+ return /* @__PURE__ */ jsx(
841
+ Surface,
842
+ {
843
+ tone: onBrand ? "onBrand" : "default",
844
+ elevation: onBrand ? "none" : "sm",
845
+ pad: "md",
846
+ className,
847
+ children: body
848
+ }
849
+ );
850
+ }
851
+ var COLUMNS = {
852
+ 2: "md:grid-cols-2",
853
+ 3: "md:grid-cols-3",
854
+ 4: "md:grid-cols-4"
855
+ };
856
+ function StepList({
857
+ steps,
858
+ variant = "bare",
859
+ tone = "default",
860
+ columns = 3,
861
+ className
862
+ }) {
863
+ return /* @__PURE__ */ jsx("div", { className: cn("grid gap-6 sm:grid-cols-2 sm:gap-8", COLUMNS[columns], className), children: steps.map((step, index) => /* @__PURE__ */ jsx(
864
+ NumberedStep,
865
+ {
866
+ n: index + 1,
867
+ title: step.title,
868
+ tone,
869
+ card: variant === "card",
870
+ children: step.children
871
+ },
872
+ index
873
+ )) });
874
+ }
875
+ function Faq({ items, defaultOpen, className }) {
876
+ return /* @__PURE__ */ jsx(
877
+ Accordion,
878
+ {
879
+ type: "single",
880
+ collapsible: true,
881
+ defaultValue: defaultOpen != null ? String(defaultOpen) : void 0,
882
+ className: cn("w-full", className),
883
+ children: items.map((item, i) => /* @__PURE__ */ jsxs(AccordionItem, { value: String(i), children: [
884
+ /* @__PURE__ */ jsx(
885
+ AccordionTrigger,
886
+ {
887
+ icon: "plusMinus",
888
+ className: "text-foreground text-base font-semibold",
889
+ children: item.q
890
+ }
891
+ ),
892
+ /* @__PURE__ */ jsx(AccordionContent, { className: "text-muted-foreground leading-relaxed", children: item.a })
893
+ ] }, i))
894
+ }
895
+ );
896
+ }
897
+ function EmailCapture({
898
+ action,
899
+ method,
900
+ onSubmit,
901
+ name = "email",
902
+ placeholder = "you@email.com",
903
+ cta = "Join the waitlist",
904
+ note,
905
+ tone = "default",
906
+ className
907
+ }) {
908
+ const onBrand = tone === "onBrand";
909
+ return /* @__PURE__ */ jsxs("form", { action, method, onSubmit, className: cn(className), children: [
910
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center", children: [
911
+ /* @__PURE__ */ jsx(
912
+ Input,
913
+ {
914
+ type: "email",
915
+ name,
916
+ required: true,
917
+ placeholder,
918
+ className: cn(
919
+ "rounded-full text-base md:text-sm",
920
+ onBrand && "[background:color-mix(in_oklch,white_18%,transparent)] placeholder:text-primary-foreground/60 border-transparent text-primary-foreground"
921
+ )
922
+ }
923
+ ),
924
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: onBrand ? "onBrand" : "default", className: "rounded-full", children: cta })
925
+ ] }),
926
+ note && /* @__PURE__ */ jsx(
927
+ "p",
928
+ {
929
+ className: cn(
930
+ "mt-3 text-sm",
931
+ onBrand ? "text-primary-foreground/70" : "text-muted-foreground"
932
+ ),
933
+ children: note
934
+ }
935
+ )
936
+ ] });
937
+ }
938
+ function CheckList({
939
+ items,
940
+ orientation = "horizontal",
941
+ tone = "default",
942
+ className
943
+ }) {
944
+ const glyph = tone === "onBrand" ? "text-brand-foreground" : "text-primary";
945
+ const label = tone === "onBrand" ? "text-brand-foreground/90" : "text-foreground";
946
+ return /* @__PURE__ */ jsx(
947
+ "ul",
948
+ {
949
+ className: cn(
950
+ orientation === "horizontal" ? "flex flex-wrap gap-x-6 gap-y-2 text-sm" : "flex flex-col gap-2 text-sm",
951
+ className
952
+ ),
953
+ children: items.map((item, i) => /* @__PURE__ */ jsxs("li", { className: cn("inline-flex items-center gap-2", label), children: [
954
+ /* @__PURE__ */ jsx(Check, { className: cn("size-4 shrink-0", glyph) }),
955
+ item
956
+ ] }, i))
957
+ }
958
+ );
959
+ }
960
+ function AccentNote({ lead, children, tone = "default", className }) {
961
+ const onBrand = tone === "onBrand";
962
+ return /* @__PURE__ */ jsxs(
963
+ "div",
964
+ {
965
+ className: cn(
966
+ "border-l-2 pl-4 text-sm leading-relaxed",
967
+ onBrand ? "border-primary-foreground/60 text-primary-foreground/80" : "border-primary text-muted-foreground",
968
+ className
969
+ ),
970
+ children: [
971
+ lead && /* @__PURE__ */ jsx(
972
+ "strong",
973
+ {
974
+ className: cn(
975
+ "mr-1.5 font-semibold",
976
+ onBrand ? "text-primary-foreground" : "text-foreground"
977
+ ),
978
+ children: lead
979
+ }
980
+ ),
981
+ children
982
+ ]
983
+ }
984
+ );
985
+ }
986
+ function AccentList({ items, className }) {
987
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", className), children: items.map((item, i) => /* @__PURE__ */ jsxs(
988
+ "div",
989
+ {
990
+ className: cn("border-l-2 py-2 pl-5", item.active ? "border-primary" : "border-border"),
991
+ children: [
992
+ /* @__PURE__ */ jsx(
993
+ "div",
994
+ {
995
+ className: cn(
996
+ "font-semibold",
997
+ item.active ? "text-foreground" : "text-muted-foreground"
998
+ ),
999
+ children: item.title
1000
+ }
1001
+ ),
1002
+ item.active && item.children && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground mt-1 text-sm leading-relaxed", children: item.children })
1003
+ ]
1004
+ },
1005
+ i
1006
+ )) });
1007
+ }
1008
+ function VerifiedChip({ icon, iconTone = "peach", label, className }) {
1009
+ return /* @__PURE__ */ jsxs(
1010
+ Surface,
1011
+ {
1012
+ elevation: "lg",
1013
+ pad: "none",
1014
+ className: cn("inline-flex items-center gap-3 rounded-full px-3 py-2", className),
1015
+ children: [
1016
+ /* @__PURE__ */ jsx(IconBadge, { tone: iconTone, size: "sm", children: icon ?? /* @__PURE__ */ jsx(Check, {}) }),
1017
+ /* @__PURE__ */ jsx("span", { className: "pr-2 text-sm font-semibold text-foreground", children: label })
1018
+ ]
1019
+ }
1020
+ );
1021
+ }
266
1022
  var ENTRIES = [
267
1023
  {
268
1024
  slug: "home",
@@ -299,6 +1055,13 @@ var ENTRIES = [
299
1055
  sub: "message \u2014 encrypted chat",
300
1056
  docsHref: "https://docs.ochk.io/chat"
301
1057
  },
1058
+ {
1059
+ slug: "cosign",
1060
+ href: "https://cosign.ochk.io",
1061
+ label: "oc\xB7cosign",
1062
+ sub: "cofound \u2014 get behind builders",
1063
+ docsHref: "https://docs.ochk.io/cosign"
1064
+ },
302
1065
  {
303
1066
  slug: "attest",
304
1067
  href: "https://attest.ochk.io",
@@ -462,141 +1225,6 @@ function EcosystemSwitcher({
462
1225
  )
463
1226
  ] });
464
1227
  }
465
- var TOOLTIP_SURFACE_CLASS = "bg-popover text-popover-foreground border-border rounded-md border p-2.5 shadow-md";
466
- var TOOLTIP_MOTION_CLASS = "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 origin-(--radix-popover-content-transform-origin) duration-150 ease-out";
467
- function compose(theirs, ours) {
468
- return (e) => {
469
- theirs?.(e);
470
- ours(e);
471
- };
472
- }
473
- var lastInputWasKeyboard = false;
474
- var modalityInstalled = false;
475
- function installModalityTracking() {
476
- if (modalityInstalled || typeof window === "undefined") return;
477
- modalityInstalled = true;
478
- window.addEventListener("keydown", () => lastInputWasKeyboard = true, true);
479
- window.addEventListener("pointerdown", () => lastInputWasKeyboard = false, true);
480
- }
481
- function Tooltip({
482
- content,
483
- children,
484
- side = "bottom",
485
- align = "start",
486
- sideOffset = 8,
487
- collisionPadding = 12,
488
- openDelay = 300,
489
- closeDelay = 90,
490
- disabled = false,
491
- portal = true,
492
- zIndexClassName = "z-50",
493
- contentClassName
494
- }) {
495
- const [hovering, setHovering] = React.useState(false);
496
- const [focusing, setFocusing] = React.useState(false);
497
- const [isFinePointer, setIsFinePointer] = React.useState(false);
498
- const openTimer = React.useRef(null);
499
- const closeTimer = React.useRef(null);
500
- React.useEffect(() => {
501
- installModalityTracking();
502
- const mq = window.matchMedia("(hover: hover) and (pointer: fine)");
503
- const apply = () => setIsFinePointer(mq.matches);
504
- apply();
505
- mq.addEventListener("change", apply);
506
- return () => mq.removeEventListener("change", apply);
507
- }, []);
508
- const clearTimers = React.useCallback(() => {
509
- if (openTimer.current) clearTimeout(openTimer.current);
510
- if (closeTimer.current) clearTimeout(closeTimer.current);
511
- }, []);
512
- React.useEffect(() => clearTimers, [clearTimers]);
513
- React.useEffect(() => {
514
- if (disabled) {
515
- clearTimers();
516
- setHovering(false);
517
- }
518
- }, [disabled, clearTimers]);
519
- const handlePointerEnter = () => {
520
- if (!isFinePointer) return;
521
- if (closeTimer.current) clearTimeout(closeTimer.current);
522
- openTimer.current = setTimeout(() => setHovering(true), openDelay);
523
- };
524
- const handlePointerLeave = () => {
525
- if (openTimer.current) clearTimeout(openTimer.current);
526
- closeTimer.current = setTimeout(() => setHovering(false), closeDelay);
527
- };
528
- const handlePointerDown = () => {
529
- clearTimers();
530
- setHovering(false);
531
- setFocusing(false);
532
- };
533
- const handleFocus = () => {
534
- if (lastInputWasKeyboard) {
535
- clearTimers();
536
- setFocusing(true);
537
- }
538
- };
539
- const handleBlur = () => {
540
- clearTimers();
541
- setFocusing(false);
542
- };
543
- const handleKeyDown = (e) => {
544
- if (e.key === "Escape") {
545
- clearTimers();
546
- setHovering(false);
547
- setFocusing(false);
548
- }
549
- };
550
- const effectiveOpen = !disabled && (isFinePointer && hovering || focusing);
551
- const extra = {};
552
- const childProps = children.props;
553
- extra.onPointerEnter = compose(childProps.onPointerEnter, handlePointerEnter);
554
- extra.onPointerLeave = compose(childProps.onPointerLeave, handlePointerLeave);
555
- extra.onPointerDown = compose(childProps.onPointerDown, handlePointerDown);
556
- extra.onFocus = compose(childProps.onFocus, handleFocus);
557
- extra.onBlur = compose(childProps.onBlur, handleBlur);
558
- extra.onKeyDown = compose(childProps.onKeyDown, handleKeyDown);
559
- const trigger = React.cloneElement(children, extra);
560
- const contentEl = /* @__PURE__ */ jsx(
561
- Popover.Content,
562
- {
563
- side,
564
- align,
565
- sideOffset,
566
- collisionPadding,
567
- "aria-hidden": true,
568
- onOpenAutoFocus: (e) => e.preventDefault(),
569
- onCloseAutoFocus: (e) => e.preventDefault(),
570
- onFocusOutside: (e) => e.preventDefault(),
571
- className: cn(
572
- TOOLTIP_SURFACE_CLASS,
573
- TOOLTIP_MOTION_CLASS,
574
- "pointer-events-none",
575
- zIndexClassName,
576
- contentClassName
577
- ),
578
- children: content
579
- }
580
- );
581
- return /* @__PURE__ */ jsxs(
582
- Popover.Root,
583
- {
584
- open: effectiveOpen,
585
- onOpenChange: (o) => {
586
- if (!o) {
587
- clearTimers();
588
- setHovering(false);
589
- setFocusing(false);
590
- }
591
- },
592
- modal: false,
593
- children: [
594
- /* @__PURE__ */ jsx(Popover.Anchor, { asChild: true, children: trigger }),
595
- portal ? /* @__PURE__ */ jsx(Popover.Portal, { children: contentEl }) : contentEl
596
- ]
597
- }
598
- );
599
- }
600
1228
 
601
1229
  // src/chrome/family-properties.ts
602
1230
  var FAMILY_PROPERTIES = [
@@ -645,6 +1273,15 @@ var FAMILY_PROPERTIES = [
645
1273
  docsHref: "https://docs.ochk.io/chat",
646
1274
  category: "product"
647
1275
  },
1276
+ {
1277
+ slug: "cosign",
1278
+ origin: "https://cosign.ochk.io",
1279
+ hostname: "cosign.ochk.io",
1280
+ label: "oc\xB7cosign",
1281
+ sub: "cofound \u2014 get behind builders",
1282
+ docsHref: "https://docs.ochk.io/cosign",
1283
+ category: "product"
1284
+ },
648
1285
  {
649
1286
  slug: "attest",
650
1287
  origin: "https://attest.ochk.io",
@@ -1022,7 +1659,7 @@ function AppearanceControls({ className }) {
1022
1659
  const activeMode = mounted ? theme ?? "system" : null;
1023
1660
  return /* @__PURE__ */ jsxs("div", { className, children: [
1024
1661
  /* @__PURE__ */ jsx("div", { className: "label-mono text-muted-foreground px-3 pt-3 pb-2", children: "mode" }),
1025
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 px-2 pb-2", children: MODES.map(({ id, label, Icon }) => {
1662
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 px-2 pb-2", children: MODES.map(({ id, label, Icon: Icon2 }) => {
1026
1663
  const active = activeMode === id;
1027
1664
  return /* @__PURE__ */ jsxs(
1028
1665
  "button",
@@ -1036,7 +1673,7 @@ function AppearanceControls({ className }) {
1036
1673
  active ? "border-primary text-foreground bg-accent" : "border-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground"
1037
1674
  ),
1038
1675
  children: [
1039
- /* @__PURE__ */ jsx(Icon, { className: "size-4", "aria-hidden": true }),
1676
+ /* @__PURE__ */ jsx(Icon2, { className: "size-4", "aria-hidden": true }),
1040
1677
  label
1041
1678
  ]
1042
1679
  },
@@ -2295,6 +2932,6 @@ function OcAppBar({
2295
2932
  );
2296
2933
  }
2297
2934
 
2298
- export { AppShell, Callout, DataRow, DefinitionList, EcosystemSwitcher, EmptyState, FAMILY_PROPERTIES, HelpHint, LayoutSubHeader, OcAccountMenu, OcAccountMenuView, OcAppBar, OcDashboardHub, OcDashboardShell, OcLogoDropdown, OcPrimaryNav, SITE_STATE_LABEL, SectionHeader, StatCard, StatGrid, StatTile, findFamilyProperty };
2935
+ export { AccentList, AccentNote, AppShell, BrandBand, Callout, CheckList, ComparisonTable, DataRow, DefinitionList, EcosystemSwitcher, EmailCapture, EmptyState, FAMILY_PROPERTIES, Faq, FeatureCard, HelpHint, LayoutSubHeader, MarketingHeading, NumberedStep, OcAccountMenu, OcAccountMenuView, OcAppBar, OcDashboardHub, OcDashboardShell, OcLogoDropdown, OcPrimaryNav, SITE_STATE_LABEL, Section, SectionHeader, StatCard, StatGrid, StatTile, StepList, TwoToneHeading, VerifiedChip, findFamilyProperty };
2299
2936
  //# sourceMappingURL=components.mjs.map
2300
2937
  //# sourceMappingURL=components.mjs.map