@lettuceai/crisp 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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/dist/components/Accordion.d.ts +15 -0
  4. package/dist/components/ActionBar.d.ts +25 -0
  5. package/dist/components/Alert.d.ts +19 -0
  6. package/dist/components/AppBar.d.ts +29 -0
  7. package/dist/components/AppShell.d.ts +42 -0
  8. package/dist/components/AudioItem.d.ts +22 -0
  9. package/dist/components/Avatar.d.ts +11 -0
  10. package/dist/components/AvatarGroup.d.ts +17 -0
  11. package/dist/components/AvatarPicker.d.ts +20 -0
  12. package/dist/components/Badge.d.ts +8 -0
  13. package/dist/components/Banner.d.ts +17 -0
  14. package/dist/components/Breadcrumb.d.ts +23 -0
  15. package/dist/components/Button.d.ts +15 -0
  16. package/dist/components/ButtonGroup.d.ts +21 -0
  17. package/dist/components/Card.d.ts +16 -0
  18. package/dist/components/Carousel.d.ts +16 -0
  19. package/dist/components/CharacterCard.d.ts +30 -0
  20. package/dist/components/Chart.d.ts +35 -0
  21. package/dist/components/Checkbox.d.ts +11 -0
  22. package/dist/components/Chip.d.ts +11 -0
  23. package/dist/components/ChoiceCard.d.ts +22 -0
  24. package/dist/components/CodeBlock.d.ts +16 -0
  25. package/dist/components/Collapsible.d.ts +20 -0
  26. package/dist/components/ColorPicker.d.ts +15 -0
  27. package/dist/components/Combobox.d.ts +30 -0
  28. package/dist/components/CommandPalette.d.ts +34 -0
  29. package/dist/components/Composer.d.ts +49 -0
  30. package/dist/components/ContextMenu.d.ts +18 -0
  31. package/dist/components/CopyButton.d.ts +13 -0
  32. package/dist/components/DatePicker.d.ts +23 -0
  33. package/dist/components/Dialog.d.ts +15 -0
  34. package/dist/components/Diff.d.ts +17 -0
  35. package/dist/components/Dock.d.ts +6 -0
  36. package/dist/components/DownloadItem.d.ts +28 -0
  37. package/dist/components/Dropzone.d.ts +21 -0
  38. package/dist/components/EmptyState.d.ts +24 -0
  39. package/dist/components/Field.d.ts +20 -0
  40. package/dist/components/FilterBar.d.ts +21 -0
  41. package/dist/components/Form.d.ts +44 -0
  42. package/dist/components/Highlight.d.ts +14 -0
  43. package/dist/components/HoverCard.d.ts +15 -0
  44. package/dist/components/Icon.d.ts +37 -0
  45. package/dist/components/IconButton.d.ts +14 -0
  46. package/dist/components/ImageViewer.d.ts +16 -0
  47. package/dist/components/InfiniteScroll.d.ts +14 -0
  48. package/dist/components/Input.d.ts +14 -0
  49. package/dist/components/Kbd.d.ts +5 -0
  50. package/dist/components/List.d.ts +25 -0
  51. package/dist/components/Masonry.d.ts +16 -0
  52. package/dist/components/MediaCard.d.ts +23 -0
  53. package/dist/components/MediaTile.d.ts +21 -0
  54. package/dist/components/Menu.d.ts +34 -0
  55. package/dist/components/Message.d.ts +76 -0
  56. package/dist/components/Meter.d.ts +20 -0
  57. package/dist/components/ModelSelect.d.ts +35 -0
  58. package/dist/components/MultiItemDownloadCard.d.ts +39 -0
  59. package/dist/components/NavRail.d.ts +37 -0
  60. package/dist/components/NumberInput.d.ts +19 -0
  61. package/dist/components/Page.d.ts +18 -0
  62. package/dist/components/Pagination.d.ts +10 -0
  63. package/dist/components/Panel.d.ts +18 -0
  64. package/dist/components/PartitionBar.d.ts +39 -0
  65. package/dist/components/Popover.d.ts +45 -0
  66. package/dist/components/Progress.d.ts +9 -0
  67. package/dist/components/Prose.d.ts +13 -0
  68. package/dist/components/Radio.d.ts +19 -0
  69. package/dist/components/ReorderableList.d.ts +21 -0
  70. package/dist/components/Resizable.d.ts +20 -0
  71. package/dist/components/ScrollArea.d.ts +17 -0
  72. package/dist/components/SearchField.d.ts +14 -0
  73. package/dist/components/SecretInput.d.ts +26 -0
  74. package/dist/components/Segmented.d.ts +16 -0
  75. package/dist/components/Select.d.ts +15 -0
  76. package/dist/components/SelectMenu.d.ts +48 -0
  77. package/dist/components/Sheet.d.ts +50 -0
  78. package/dist/components/Shelf.d.ts +17 -0
  79. package/dist/components/Skeleton.d.ts +12 -0
  80. package/dist/components/Slider.d.ts +11 -0
  81. package/dist/components/Spinner.d.ts +13 -0
  82. package/dist/components/StatTile.d.ts +33 -0
  83. package/dist/components/Stepper.d.ts +21 -0
  84. package/dist/components/Surface.d.ts +56 -0
  85. package/dist/components/Switch.d.ts +9 -0
  86. package/dist/components/TabBar.d.ts +12 -0
  87. package/dist/components/Table.d.ts +35 -0
  88. package/dist/components/Tabs.d.ts +31 -0
  89. package/dist/components/TagInput.d.ts +18 -0
  90. package/dist/components/Text.d.ts +293 -0
  91. package/dist/components/ThemeEditor.d.ts +8 -0
  92. package/dist/components/Timeline.d.ts +17 -0
  93. package/dist/components/TitleBar.d.ts +17 -0
  94. package/dist/components/Toast.d.ts +50 -0
  95. package/dist/components/ToggleGroup.d.ts +22 -0
  96. package/dist/components/Toolbar.d.ts +18 -0
  97. package/dist/components/Tooltip.d.ts +15 -0
  98. package/dist/components/Tour.d.ts +22 -0
  99. package/dist/components/Tree.d.ts +21 -0
  100. package/dist/components/VirtualList.d.ts +18 -0
  101. package/dist/components/WindowControls.d.ts +38 -0
  102. package/dist/components/Wizard.d.ts +33 -0
  103. package/dist/components/confirm.d.ts +24 -0
  104. package/dist/components/index.d.ts +103 -0
  105. package/dist/components/nav.d.ts +19 -0
  106. package/dist/components/primitives.d.ts +14 -0
  107. package/dist/index.d.ts +15 -0
  108. package/dist/index.js +8035 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/layout/Box.d.ts +6 -0
  111. package/dist/layout/Center.d.ts +2 -0
  112. package/dist/layout/Container.d.ts +8 -0
  113. package/dist/layout/Divider.d.ts +9 -0
  114. package/dist/layout/Flex.d.ts +16 -0
  115. package/dist/layout/Grid.d.ts +13 -0
  116. package/dist/layout/Spacer.d.ts +4 -0
  117. package/dist/layout/Stack.d.ts +13 -0
  118. package/dist/layout/index.d.ts +8 -0
  119. package/dist/lib/cn.d.ts +2 -0
  120. package/dist/lib/color.d.ts +16 -0
  121. package/dist/lib/format.d.ts +6 -0
  122. package/dist/lib/frame.d.ts +25 -0
  123. package/dist/lib/icon.d.ts +24 -0
  124. package/dist/lib/imageBrightness.d.ts +8 -0
  125. package/dist/lib/motion.d.ts +54 -0
  126. package/dist/lib/polymorphic.d.ts +12 -0
  127. package/dist/lib/tint.d.ts +9 -0
  128. package/dist/lib/useLongPress.d.ts +19 -0
  129. package/dist/lib/useMediaQuery.d.ts +8 -0
  130. package/dist/lib/useModal.d.ts +8 -0
  131. package/dist/theme/ThemeProvider.d.ts +19 -0
  132. package/dist/theme/index.d.ts +2 -0
  133. package/dist/theme/theme.d.ts +36 -0
  134. package/package.json +81 -0
  135. package/src/styles.css +392 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/lib/cn.ts","../src/lib/motion.ts","../src/components/Accordion.tsx","../src/components/Badge.tsx","../src/components/Alert.tsx","../src/components/IconButton.tsx","../src/components/Field.tsx","../src/components/Input.tsx","../src/components/AppBar.tsx","../src/lib/frame.tsx","../src/lib/useMediaQuery.ts","../src/components/Tooltip.tsx","../src/components/TabBar.tsx","../src/components/Dock.tsx","../src/components/NavRail.tsx","../src/components/AppShell.tsx","../src/components/AudioItem.tsx","../src/components/Avatar.tsx","../src/components/AvatarGroup.tsx","../src/components/Banner.tsx","../src/components/Menu.tsx","../src/components/Breadcrumb.tsx","../src/lib/icon.ts","../src/components/Button.tsx","../src/components/ButtonGroup.tsx","../src/components/Card.tsx","../src/components/Carousel.tsx","../src/lib/tint.ts","../src/lib/imageBrightness.ts","../src/components/Surface.tsx","../src/components/Skeleton.tsx","../src/components/CharacterCard.tsx","../src/components/Chart.tsx","../src/components/Checkbox.tsx","../src/components/Chip.tsx","../src/components/CopyButton.tsx","../src/components/ScrollArea.tsx","../src/components/CodeBlock.tsx","../src/components/Collapsible.tsx","../src/components/Popover.tsx","../src/components/ColorPicker.tsx","../src/components/Spinner.tsx","../src/components/Combobox.tsx","../src/components/Highlight.tsx","../src/components/Kbd.tsx","../src/components/CommandPalette.tsx","../src/lib/useLongPress.ts","../src/components/Composer.tsx","../src/lib/useModal.ts","../src/components/Sheet.tsx","../src/components/confirm.tsx","../src/components/ContextMenu.tsx","../src/components/DatePicker.tsx","../src/components/Dialog.tsx","../src/components/Diff.tsx","../src/components/Progress.tsx","../src/components/DownloadItem.tsx","../src/components/Dropzone.tsx","../src/components/EmptyState.tsx","../src/components/FilterBar.tsx","../src/components/Form.tsx","../src/components/HoverCard.tsx","../src/components/Icon.tsx","../src/components/ImageViewer.tsx","../src/components/InfiniteScroll.tsx","../src/components/List.tsx","../src/components/Masonry.tsx","../src/components/MediaCard.tsx","../src/components/MediaTile.tsx","../src/components/Message.tsx","../src/components/Meter.tsx","../src/components/MultiItemDownloadCard.tsx","../src/components/NumberInput.tsx","../src/components/Pagination.tsx","../src/components/Panel.tsx","../src/components/PartitionBar.tsx","../src/components/primitives.tsx","../src/components/Prose.tsx","../src/components/Radio.tsx","../src/components/Resizable.tsx","../src/components/SearchField.tsx","../src/components/Segmented.tsx","../src/components/Select.tsx","../src/components/SelectMenu.tsx","../src/components/Slider.tsx","../src/components/StatTile.tsx","../src/components/Stepper.tsx","../src/components/Switch.tsx","../src/components/Table.tsx","../src/components/Tabs.tsx","../src/components/TagInput.tsx","../src/components/Text.tsx","../src/lib/color.ts","../src/theme/theme.ts","../src/theme/ThemeProvider.tsx","../src/components/ThemeEditor.tsx","../src/components/Timeline.tsx","../src/components/TitleBar.tsx","../src/components/Toast.tsx","../src/components/ToggleGroup.tsx","../src/components/Toolbar.tsx","../src/components/Tour.tsx","../src/components/Tree.tsx","../src/components/VirtualList.tsx","../src/components/WindowControls.tsx","../src/components/ActionBar.tsx","../src/components/ChoiceCard.tsx","../src/components/Shelf.tsx","../src/components/Wizard.tsx","../src/components/SecretInput.tsx","../src/components/ReorderableList.tsx","../src/components/AvatarPicker.tsx","../src/components/Page.tsx","../src/components/ModelSelect.tsx","../src/layout/Box.tsx","../src/layout/Center.tsx","../src/layout/Container.tsx","../src/layout/Divider.tsx","../src/layout/Flex.tsx","../src/layout/Grid.tsx","../src/layout/Spacer.tsx","../src/layout/Stack.tsx","../src/lib/format.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { Transition } from \"framer-motion\";\n\n/**\n * Every animation in Crisp goes through one of these. Before this file there were\n * seven durations and six springs scattered inline — the same drift the app has with\n * fifteen icon sizes, just in milliseconds.\n *\n * Pick by what the motion is *for*, not by how long it should take.\n */\n\n/** Something swapped in place: an icon, a tooltip, a popover, a context menu. */\nexport const instant: Transition = { duration: 0.12 };\n\n/** Something appeared or resolved: a fade, a disclosure, a dialog. */\nexport const quick: Transition = { duration: 0.18 };\n\n/** Something travelled: a progress bar, a large reveal. */\nexport const slow: Transition = { duration: 0.3 };\n\n/** A small control snapping to a new position: a switch knob. */\nexport const snap: Transition = { type: \"spring\", stiffness: 700, damping: 40 };\n\n/** A moving indicator settling: active tab, segmented control, stepper. */\nexport const settle: Transition = { type: \"spring\", stiffness: 500, damping: 40 };\n\n/** A large surface arriving: sheets, panels, spotlight. */\nexport const surface: Transition = { type: \"spring\", stiffness: 420, damping: 42 };\n\n/** Easing for height and layout changes, where a spring would overshoot. */\nexport const easeOut = [0.25, 1, 0.5, 1] as const;\n\n/** Collapsing and expanding, which must not overshoot or the content clips. */\nexport const collapse: Transition = { duration: 0.2, ease: easeOut };\n\n/*\n * Sheets. Written as how long they take to arrive and how far they overshoot, the way\n * the platform describes its own, rather than as stiffness and damping.\n *\n * In and out are different on purpose: a sheet that leaves as slowly as it arrived\n * makes you wait for something you have already dismissed.\n */\n/** A sheet presenting from an edge. Covers the distance quickly, lands without a wobble. */\nexport const sheetIn: Transition = { type: \"spring\", visualDuration: 0.32, bounce: 0 };\n/** A sheet dismissed. Faster than it came, and it never bounces on the way out. */\nexport const sheetOut: Transition = { type: \"spring\", visualDuration: 0.26, bounce: 0 };\n/** A sheet let go short of closing. Returns from the speed it was thrown at, and stops\n at its resting place — an overshoot there would lift it off the edge. */\nexport const sheetSettle: Transition = { type: \"spring\", visualDuration: 0.3, bounce: 0 };\n\n/** A side panel widening or folding back. No overshoot: the content beside it reflows\n with it, and a bounce would shake every line of text twice. */\nexport const sidebar: Transition = { type: \"spring\", visualDuration: 0.3, bounce: 0 };\n\n/** A dragged card letting go and returning to rest. Stiff, so it snaps rather than drifts. */\nexport const rebound: Transition = { type: \"spring\", stiffness: 900, damping: 55, restDelta: 0.5 };\n\n/** A looping ambient cycle — the typing indicator. Not a transition; it never resolves. */\nexport const pulse: Transition = { duration: 1.2, repeat: Infinity, ease: \"easeInOut\" };\n\nexport const motion = { instant, quick, slow, snap, settle, surface, sheetIn, sheetOut, sheetSettle, sidebar, rebound, collapse, pulse, easeOut } as const;\n","import { createContext, useContext, useId, useState, type ReactNode } from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\ninterface AccordionContextValue {\n openItems: Set<string>;\n toggle: (value: string) => void;\n}\n\nconst AccordionContext = createContext<AccordionContextValue | null>(null);\n\nexport interface AccordionProps {\n /** Allow several items open at once. */\n multiple?: boolean;\n defaultOpen?: string[];\n className?: string;\n children: ReactNode;\n}\n\nexport function Accordion({ multiple, defaultOpen = [], className, children }: AccordionProps) {\n const [openItems, setOpenItems] = useState(() => new Set(defaultOpen));\n const toggle = (value: string) => {\n setOpenItems((prev) => {\n const next = new Set(multiple ? prev : []);\n if (prev.has(value)) next.delete(value);\n else next.add(value);\n return next;\n });\n };\n return (\n <AccordionContext.Provider value={{ openItems, toggle }}>\n <div className={cn(\"divide-y divide-line rounded-xl border border-line bg-surface-1\", className)}>{children}</div>\n </AccordionContext.Provider>\n );\n}\n\nexport function AccordionItem({ value, title, description, children }: { value: string; title: ReactNode; description?: ReactNode; children: ReactNode }) {\n const ctx = useContext(AccordionContext);\n if (!ctx) throw new Error(\"AccordionItem must be used inside <Accordion>\");\n const open = ctx.openItems.has(value);\n const id = useId();\n return (\n <div>\n <h3>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={`${id}-panel`}\n id={`${id}-button`}\n onClick={() => ctx.toggle(value)}\n className=\"touch-target flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-fill-2\"\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-base font-medium text-fg\">{title}</span>\n {description && <span className=\"block text-sm text-fg-3\">{description}</span>}\n </span>\n <ChevronDown size={16} className={cn(\"shrink-0 text-fg-3 transition-transform motion-quick\", open && \"rotate-180\")} />\n </button>\n </h3>\n <AnimatePresence initial={false}>\n {open && (\n <motion.div\n id={`${id}-panel`}\n role=\"region\"\n aria-labelledby={`${id}-button`}\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={m.collapse}\n className=\"overflow-hidden\"\n >\n <div className=\"px-4 pb-4 text-base text-fg-2\">{children}</div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n","import type { HTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type BadgeTone = \"neutral\" | \"accent\" | \"danger\" | \"warning\" | \"info\" | \"secondary\";\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n tone?: BadgeTone;\n /** Leading status dot. */\n dot?: boolean;\n}\n\nconst toneClass: Record<BadgeTone, string> = {\n neutral: \"border-line-2 bg-fill-2 text-fg-2\",\n accent: \"border-accent/25 bg-accent/12 text-accent\",\n danger: \"border-danger/25 bg-danger/12 text-danger\",\n warning: \"border-warning/25 bg-warning/12 text-warning\",\n info: \"border-info/25 bg-info/12 text-info\",\n secondary: \"border-secondary/25 bg-secondary/12 text-secondary\",\n};\n\nexport function Badge({ tone = \"neutral\", dot, className, children, ...rest }: BadgeProps) {\n return (\n <span\n className={cn(\n \"inline-flex h-6 items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium\",\n toneClass[tone],\n className,\n )}\n {...rest}\n >\n {dot && <span className=\"h-1.5 w-1.5 rounded-full bg-current\" aria-hidden=\"true\" />}\n {children}\n </span>\n );\n}\n","import { useState, type ReactNode } from \"react\";\nimport { AlertTriangle, CheckCircle2, ChevronDown, Info, X, XCircle } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { Badge } from \"./Badge\";\n\nexport type AlertTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface AlertProps {\n tone?: AlertTone;\n title: ReactNode;\n description?: ReactNode;\n /** Small tag next to the title — an HTTP status, a model name. */\n meta?: ReactNode;\n /** Collapsed by default; raw payloads, stack traces. */\n details?: string;\n action?: ReactNode;\n onDismiss?: () => void;\n className?: string;\n}\n\nconst tone = {\n info: { icon: Info, iconClass: \"text-info\", bar: \"bg-info\" },\n success: { icon: CheckCircle2, iconClass: \"text-accent\", bar: \"bg-accent\" },\n warning: { icon: AlertTriangle, iconClass: \"text-warning\", bar: \"bg-warning\" },\n danger: { icon: XCircle, iconClass: \"text-danger\", bar: \"bg-danger\" },\n};\n\n/**\n * Inline notice. Explains what happened and what to do next, in the interface's voice.\n * Replaces the chat error banner; same information, one type scale.\n */\nexport function Alert({ tone: toneKey = \"info\", title, description, meta, details, action, onDismiss, className }: AlertProps) {\n const [open, setOpen] = useState(false);\n const { icon: Icon, iconClass, bar } = tone[toneKey];\n return (\n <div role={toneKey === \"danger\" || toneKey === \"warning\" ? \"alert\" : \"status\"} className={cn(\"relative overflow-hidden rounded-xl border border-line bg-fill\", className)}>\n <span aria-hidden=\"true\" className={cn(\"absolute inset-y-0 left-0 w-0.5\", bar)} />\n <div className=\"flex items-start gap-3 py-3 pl-4 pr-3\">\n <Icon size={18} className={cn(\"mt-0.5 shrink-0\", iconClass)} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <p className=\"text-base font-medium text-fg\">{title}</p>\n {meta && <Badge className=\"h-5 px-1.5\">{meta}</Badge>}\n </div>\n {description && <p className=\"mt-1 text-sm text-fg-2\">{description}</p>}\n {(details || action) && (\n /* -ml-3 cancels the button padding so actions align with the text above. */\n <div className=\"-ml-3 mt-1 flex flex-wrap items-center gap-1\">\n {action}\n {details && (\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n aria-expanded={open}\n className=\"inline-flex h-8 items-center gap-1.5 rounded-lg px-3 text-sm font-medium text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg-2\"\n >\n <ChevronDown size={14} className={cn(\"transition-transform motion-quick\", open && \"rotate-180\")} />\n {open ? \"Hide details\" : \"Show details\"}\n </button>\n )}\n </div>\n )}\n {details && open && (\n <pre className=\"scrollbar-thin mt-1.5 max-h-40 overflow-auto whitespace-pre-wrap break-words rounded-lg border border-line bg-surface px-3 py-2 text-xs leading-relaxed text-fg-3\">{details}</pre>\n )}\n </div>\n {onDismiss && (\n <button type=\"button\" onClick={onDismiss} aria-label=\"Dismiss\" className=\"-mr-1 -mt-1 shrink-0 rounded-lg p-1.5 text-fg-3 hover:bg-fill-2 hover:text-fg\">\n <X size={14} />\n </button>\n )}\n </div>\n </div>\n );\n}\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type IconButtonVariant = \"ghost\" | \"secondary\" | \"tonal\";\nexport type IconButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n /** Required: icon buttons have no visible text. */\n label: string;\n variant?: IconButtonVariant;\n size?: IconButtonSize;\n /** Round for standalone (close, back); square inside toolbars. */\n shape?: \"square\" | \"round\";\n active?: boolean;\n children: ReactNode;\n}\n\nconst variantClass: Record<IconButtonVariant, string> = {\n ghost: \"text-fg-2 hover:bg-fill-2 hover:text-fg active:bg-fill-3\",\n secondary: \"border border-line bg-fill text-fg-2 hover:border-line-3 hover:bg-fill-2 hover:text-fg active:bg-fill-3\",\n tonal: \"border border-accent/30 bg-accent/15 text-accent hover:border-accent/55 hover:bg-accent/28 active:bg-accent/38\",\n};\n\nconst sizeClass: Record<IconButtonSize, string> = {\n sm: \"control-sm w-8\",\n md: \"control-md w-10\",\n lg: \"control-lg w-11\",\n};\n\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(\n { label, variant = \"ghost\", size = \"md\", shape = \"square\", active, className, disabled, type = \"button\", children, ...rest },\n ref,\n) {\n return (\n <button\n ref={ref}\n type={type}\n aria-label={label}\n title={label}\n aria-pressed={active}\n disabled={disabled}\n className={cn(\n \"touch-target inline-flex shrink-0 select-none items-center justify-center\",\n variant === \"ghost\" ? \"raise-flat\" : \"raise\",\n \"focus-visible:outline-1 focus-visible:outline-offset-2 focus-visible:outline-fg-2\",\n \"disabled:pointer-events-none disabled:opacity-45\",\n shape === \"round\" ? \"rounded-full\" : \"rounded-lg\",\n variantClass[variant],\n sizeClass[size],\n active && \"bg-fill-2 text-fg\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n});\n","import { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\ninterface FieldContextValue {\n id: string;\n describedBy?: string;\n invalid: boolean;\n}\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\n/** Inputs call this to pick up id / aria wiring from the surrounding Field. */\nexport function useFieldContext() {\n return useContext(FieldContext);\n}\n\nexport interface FieldProps {\n label?: ReactNode;\n hint?: ReactNode;\n error?: ReactNode;\n required?: boolean;\n /** Label and control on one row — for switches and compact selects. */\n inline?: boolean;\n className?: string;\n children: ReactNode;\n}\n\nexport function Field({ label, hint, error, required, inline, className, children }: FieldProps) {\n const id = useId();\n const hintId = `${id}-hint`;\n const errorId = `${id}-error`;\n const describedBy = [hint && hintId, error && errorId].filter(Boolean).join(\" \") || undefined;\n\n const labelNode = label && (\n <label htmlFor={id} className=\"block text-sm font-medium text-fg-2\">\n {label}\n {required && (\n <span className=\"ml-0.5 text-danger\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n );\n\n const helpNode = error ? (\n <p id={errorId} role=\"alert\" className=\"text-sm text-danger\">\n {error}\n </p>\n ) : hint ? (\n <p id={hintId} className=\"text-sm text-fg-3\">\n {hint}\n </p>\n ) : null;\n\n return (\n <FieldContext.Provider value={{ id, describedBy, invalid: Boolean(error) }}>\n {inline ? (\n <div className={cn(\"flex items-center justify-between gap-4\", className)}>\n <div className=\"min-w-0 space-y-0.5\">\n {labelNode}\n {helpNode}\n </div>\n <div className=\"shrink-0\">{children}</div>\n </div>\n ) : (\n <div className={cn(\"space-y-1.5\", className)}>\n {labelNode}\n {children}\n {helpNode}\n </div>\n )}\n </FieldContext.Provider>\n );\n}\n","import { forwardRef, useCallback, useLayoutEffect, useRef, type InputHTMLAttributes, type ReactNode, type TextareaHTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\n\nexport const inputSurface = cn(\n \"w-full rounded-xl border border-line bg-fill text-base text-fg placeholder:text-fg-4\",\n \"transition-[border-color,background-color] motion-instant\",\n \"hover:border-line-2 focus:border-accent focus:bg-fill-2 focus:outline-none focus:ring-1 focus:ring-accent/35\",\n \"disabled:cursor-not-allowed disabled:opacity-40\",\n \"aria-invalid:border-danger/60 aria-invalid:focus:border-danger\",\n);\n\nexport interface InputProps extends InputHTMLAttributes<HTMLInputElement> {\n leading?: ReactNode;\n trailing?: ReactNode;\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n { leading, trailing, className, id, ...rest },\n ref,\n) {\n const field = useFieldContext();\n const control = (\n <input\n ref={ref}\n id={id ?? field?.id}\n aria-describedby={rest[\"aria-describedby\"] ?? field?.describedBy}\n aria-invalid={rest[\"aria-invalid\"] ?? (field?.invalid || undefined)}\n className={cn(inputSurface, \"control-md px-3.5\", leading && \"pl-10\", trailing && \"pr-10\", className)}\n {...rest}\n />\n );\n if (!leading && !trailing) return control;\n return (\n <div className=\"relative\">\n {leading && (\n <span className=\"pointer-events-none absolute left-3.5 top-1/2 -translate-y-1/2 text-fg-3\">{leading}</span>\n )}\n {control}\n {trailing && <span className=\"absolute right-2 top-1/2 -translate-y-1/2\">{trailing}</span>}\n </div>\n );\n});\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Grow with the text instead of scrolling inside a fixed box. `rows` is the minimum. */\n autoGrow?: boolean;\n /** With `autoGrow`, stop growing here and scroll. Default 12. */\n maxRows?: number;\n}\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(\n { className, id, rows = 4, autoGrow, maxRows = 12, onChange, ...rest },\n ref,\n) {\n const field = useFieldContext();\n const inner = useRef<HTMLTextAreaElement | null>(null);\n\n const fit = useCallback(() => {\n const el = inner.current;\n if (!el || !autoGrow) return;\n const line = parseFloat(getComputedStyle(el).lineHeight) || 24;\n const pad = el.offsetHeight - el.clientHeight + (parseFloat(getComputedStyle(el).paddingTop) + parseFloat(getComputedStyle(el).paddingBottom));\n el.style.height = \"0px\";\n const max = line * maxRows + pad;\n el.style.height = `${Math.min(el.scrollHeight, max)}px`;\n el.style.overflowY = el.scrollHeight > max ? \"auto\" : \"hidden\";\n }, [autoGrow, maxRows]);\n\n /* Fit on mount and whenever the value is set from outside. */\n useLayoutEffect(fit, [fit, rest.value]);\n\n return (\n <textarea\n ref={(el) => {\n inner.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n }}\n id={id ?? field?.id}\n rows={rows}\n onChange={(e) => { onChange?.(e); fit(); }}\n aria-describedby={rest[\"aria-describedby\"] ?? field?.describedBy}\n aria-invalid={rest[\"aria-invalid\"] ?? (field?.invalid || undefined)}\n className={cn(inputSurface, \"resize-none px-3.5 py-2.5 leading-relaxed\", className)}\n {...rest}\n />\n );\n});\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { ArrowLeft, Search, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { IconButton } from \"./IconButton\";\nimport { Input } from \"./Input\";\n\nexport interface AppBarProps {\n title: ReactNode;\n /** Small text after the title — a count, a status. */\n meta?: ReactNode;\n onBack?: () => void;\n backLabel?: string;\n /** Renders a search field on desktop and a search icon that expands on compact. */\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n searchPlaceholder?: string;\n actions?: ReactNode;\n /** A filter row under the title. */\n filters?: ReactNode;\n /**\n * Shrink the title when the page scrolls. Pass the scrolling element;\n * defaults to the window.\n */\n scrollRef?: React.RefObject<HTMLElement | null>;\n /** Desktop window chrome sits above; leave room for it. */\n inset?: boolean;\n className?: string;\n}\n\n/**\n * The page header. One component for both platforms: on desktop the title is large\n * and search is always visible; on compact it condenses on scroll and search expands\n * from an icon, because a permanent search field costs a third of a phone's width.\n */\nexport function AppBar({\n title, meta, onBack, backLabel = \"Back\", searchValue, onSearchChange, searchPlaceholder = \"Search\",\n actions, filters, scrollRef, inset, className,\n}: AppBarProps) {\n const [condensed, setCondensed] = useState(false);\n const [searchOpen, setSearchOpen] = useState(false);\n const searchRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n const target = scrollRef?.current ?? window;\n const read = () => (scrollRef?.current ? scrollRef.current.scrollTop : window.scrollY);\n const onScroll = () => setCondensed(read() > 12);\n onScroll();\n target.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => target.removeEventListener(\"scroll\", onScroll);\n }, [scrollRef]);\n\n useEffect(() => {\n if (searchOpen) searchRef.current?.focus();\n }, [searchOpen]);\n\n const searchField = onSearchChange && (\n <Input\n ref={searchRef}\n value={searchValue ?? \"\"}\n onChange={(event) => onSearchChange(event.target.value)}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n leading={<Search size={16} />}\n trailing={\n searchValue ? (\n <IconButton label=\"Clear search\" size=\"sm\" onClick={() => onSearchChange(\"\")}>\n <X size={14} />\n </IconButton>\n ) : undefined\n }\n className=\"h-9\"\n />\n );\n\n return (\n <header\n className={cn(\n \"@container sticky top-0 z-30 bg-surface/90 backdrop-blur-md transition-shadow\",\n condensed && \"border-b border-line\",\n inset && \"pt-[var(--safe-top)]\",\n className,\n )}\n >\n <div className=\"px-4 @xl:px-6\">\n {/* Compact: search replaces the row when open, so the title never squeezes. */}\n {searchOpen && onSearchChange ? (\n <div className=\"flex items-center gap-2 py-2.5 @xl:hidden\">\n <div className=\"min-w-0 flex-1\">{searchField}</div>\n <IconButton label=\"Close search\" onClick={() => { setSearchOpen(false); onSearchChange(\"\"); }}>\n <X size={18} />\n </IconButton>\n </div>\n ) : (\n <div className={cn(\"flex items-center gap-2 transition-[padding] motion-quick\", condensed ? \"py-2\" : \"py-3 @xl:py-4\")}>\n {onBack && (\n <IconButton label={backLabel} shape=\"round\" onClick={onBack} className=\"-ml-1 shrink-0\">\n <ArrowLeft size={18} />\n </IconButton>\n )}\n <div className=\"flex min-w-0 flex-1 items-baseline gap-2\">\n <h1\n className={cn(\n \"truncate font-bold tracking-tight text-fg transition-[font-size] motion-quick\",\n condensed ? \"text-lg\" : \"text-xl @xl:text-3xl\",\n )}\n >\n {title}\n </h1>\n {meta && <span className=\"shrink-0 text-sm text-fg-3\">{meta}</span>}\n </div>\n <div className=\"flex shrink-0 items-center gap-1.5\">\n {onSearchChange && (\n <>\n <div className=\"hidden w-64 @xl:block @3xl:w-80\">{searchField}</div>\n <IconButton label=\"Search\" className=\"@xl:hidden\" onClick={() => setSearchOpen(true)}>\n <Search size={18} />\n </IconButton>\n </>\n )}\n {actions}\n </div>\n </div>\n )}\n {filters && <div className=\"pb-3\">{filters}</div>}\n </div>\n </header>\n );\n}\n","import { createContext, useContext, type ReactNode } from \"react\";\n\ninterface FrameValue {\n /** Where overlays portal to. `null` is the document body — the real app. */\n portal: HTMLElement | null;\n /** Force the phone or desktop layout for this subtree, whatever the viewport says. */\n compact?: boolean;\n}\n\nconst FrameContext = createContext<FrameValue>({ portal: null });\n\n/**\n * Runs a piece of the app inside a device frame on the lab page: overlays open inside\n * the frame instead of at the bottom of the browser window, and layout decisions follow\n * the device being simulated rather than the monitor it is being viewed on.\n *\n * The element passed as `portal` must establish a containing block for fixed-position\n * descendants (a `transform` does it), or sheets will still pin to the viewport.\n *\n * The real app never mounts this. Every hook falls back to the document and the\n * viewport, so components written against it behave identically outside a frame.\n */\nexport function FrameProvider({ portal, compact, children }: FrameValue & { children: ReactNode }) {\n return <FrameContext.Provider value={{ portal, compact }}>{children}</FrameContext.Provider>;\n}\n\nexport function useFrame() {\n return useContext(FrameContext);\n}\n\n/** The node overlays should portal into. */\nexport function usePortalTarget(): HTMLElement | null {\n const { portal } = useContext(FrameContext);\n if (portal) return portal;\n return typeof document === \"undefined\" ? null : document.body;\n}\n","import { useSyncExternalStore } from \"react\";\nimport { useFrame } from \"./frame\";\n\n/** Subscribes to a media query. SSR-safe: returns `false` on the server. */\nexport function useMediaQuery(query: string) {\n return useSyncExternalStore(\n (onChange) => {\n if (typeof window === \"undefined\") return () => {};\n const list = window.matchMedia(query);\n list.addEventListener(\"change\", onChange);\n return () => list.removeEventListener(\"change\", onChange);\n },\n () => (typeof window === \"undefined\" ? false : window.matchMedia(query).matches),\n () => false,\n );\n}\n\n/**\n * \"Is this a touch-first, phone-sized viewport?\"\n * Width alone is wrong (a small desktop window still has a mouse) and pointer alone\n * is wrong (a Surface has both), so we ask for narrow OR coarse.\n */\nexport function useCompactLayout() {\n const narrow = useMediaQuery(\"(max-width: 767px)\");\n const coarse = useMediaQuery(\"(pointer: coarse)\");\n const { compact } = useFrame();\n /* Inside a device frame the device decides, not the monitor it is shown on. */\n if (compact !== undefined) return compact;\n return narrow || coarse;\n}\n","import { cloneElement, useId, useState, type ReactElement, type ReactNode } from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\nexport interface TooltipProps {\n content: ReactNode;\n placement?: \"top\" | \"bottom\" | \"left\" | \"right\";\n /** ms before it shows on hover. */\n delay?: number;\n /** Keep it from opening — for a label that is already on screen. The wrapper stays,\n so the trigger is not remounted when this flips. */\n disabled?: boolean;\n /** Classes for the wrapper, which is an inline-flex span by default. */\n className?: string;\n children: ReactElement<Record<string, unknown>>;\n}\n\nconst placementClass = {\n top: \"bottom-full left-1/2 mb-2 -translate-x-1/2\",\n bottom: \"top-full left-1/2 mt-2 -translate-x-1/2\",\n left: \"right-full top-1/2 mr-2 -translate-y-1/2\",\n right: \"left-full top-1/2 ml-2 -translate-y-1/2\",\n};\n\nconst motionOffset = { top: { y: 4 }, bottom: { y: -4 }, left: { x: 4 }, right: { x: -4 } };\n\n/** Hover / focus hint. Never the only place a label lives — icon buttons still need `label`. */\nexport function Tooltip({ content, placement = \"top\", delay = 300, disabled = false, className, children }: TooltipProps) {\n const [open, setOpen] = useState(false);\n const [timer, setTimer] = useState<number | null>(null);\n const id = useId();\n\n const show = () => {\n if (disabled) return;\n if (timer) window.clearTimeout(timer);\n setTimer(window.setTimeout(() => setOpen(true), delay));\n };\n const hide = () => {\n if (timer) window.clearTimeout(timer);\n setTimer(null);\n setOpen(false);\n };\n\n const child = children.props as { onMouseEnter?: (e: unknown) => void; onMouseLeave?: (e: unknown) => void; onFocus?: (e: unknown) => void; onBlur?: (e: unknown) => void };\n const trigger = cloneElement(children, {\n \"aria-describedby\": open ? id : undefined,\n onMouseEnter: (e: unknown) => { child.onMouseEnter?.(e); show(); },\n onMouseLeave: (e: unknown) => { child.onMouseLeave?.(e); hide(); },\n onFocus: (e: unknown) => { child.onFocus?.(e); if (!disabled) setOpen(true); },\n onBlur: (e: unknown) => { child.onBlur?.(e); hide(); },\n });\n\n return (\n <span className={cn(\"relative inline-flex\", className)}>\n {trigger}\n <AnimatePresence>\n {open && !disabled && (\n <motion.span\n id={id}\n role=\"tooltip\"\n initial={{ opacity: 0, ...motionOffset[placement] }}\n animate={{ opacity: 1, x: 0, y: 0 }}\n exit={{ opacity: 0, ...motionOffset[placement] }}\n transition={m.instant}\n className={cn(\n \"pointer-events-none absolute z-50 whitespace-nowrap rounded-lg border border-line bg-surface-2 px-2.5 py-1.5 text-xs text-fg-2 shadow-raised\",\n placementClass[placement],\n )}\n >\n {content}\n </motion.span>\n )}\n </AnimatePresence>\n </span>\n );\n}\n","import { useId } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { Plus } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport type { NavDestination, NavProps } from \"./nav\";\n\n\nexport interface TabBarProps<T extends string> extends NavProps<T> {\n showLabels?: boolean;\n}\n\nexport function NavBadge({ badge }: { badge: number | boolean }) {\n return (\n <span\n className={cn(\n \"absolute -right-1.5 -top-1 flex items-center justify-center rounded-full bg-accent text-on-accent\",\n typeof badge === \"number\" ? \"h-4 min-w-4 px-1 text-2xs font-semibold tabular-nums\" : \"h-2 w-2\",\n )}\n >\n {typeof badge === \"number\" ? (badge > 99 ? \"99+\" : badge) : null}\n </span>\n );\n}\n\n/**\n * Bottom navigation, for touch and narrow windows. Destinations are quiet;\n * the create action is the only accented control on the bar.\n */\nexport function TabBar<T extends string>({\n items, value, onChange, onCreate, createLabel = \"Create\", showLabels = false, className,\n}: TabBarProps<T>) {\n const layoutId = useId();\n const middle = Math.ceil(items.length / 2);\n\n const renderItem = (item: NavDestination<T>) => {\n const active = item.id === value;\n return (\n <button\n key={item.id}\n type=\"button\"\n aria-label={item.label}\n aria-current={active ? \"page\" : undefined}\n onClick={() => onChange(item.id)}\n className={cn(\n \"relative flex h-12 flex-1 flex-col items-center justify-center gap-1 rounded-xl transition-colors motion-instant\",\n active ? \"text-fg\" : \"text-fg-3 hover:text-fg-2\",\n )}\n >\n {active && (\n <motion.span layoutId={layoutId} transition={m.settle} className=\"absolute inset-0 rounded-xl bg-fill-2\" />\n )}\n <span className=\"relative\">\n {item.icon}\n {item.badge ? <NavBadge badge={item.badge} /> : null}\n </span>\n {showLabels ? <span className=\"relative text-2xs font-medium leading-none\">{item.label}</span> : <span className=\"sr-only\">{item.label}</span>}\n </button>\n );\n };\n\n return (\n <nav aria-label=\"Primary\" className={cn(\"border-t border-line bg-nav/95 px-3 pb-[calc(var(--safe-bottom)+8px)] pt-2 backdrop-blur-md\", className)}>\n <div className=\"mx-auto flex max-w-md items-center gap-1\">\n {items.slice(0, middle).map(renderItem)}\n {onCreate && (\n <div className=\"flex flex-1 items-center justify-center\">\n <motion.button\n type=\"button\"\n whileTap={{ scale: 0.94 }}\n onClick={onCreate}\n aria-label={createLabel}\n className={cn(\"flex items-center justify-center rounded-full bg-accent text-on-accent shadow-raised\", showLabels ? \"h-11 w-11\" : \"h-10 w-10\")}\n >\n <Plus size={20} strokeWidth={2.5} />\n </motion.button>\n </div>\n )}\n {items.slice(middle).map(renderItem)}\n </div>\n </nav>\n );\n}\n","import { useId } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { Plus } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { Tooltip } from \"./Tooltip\";\nimport { NavBadge } from \"./TabBar\";\nimport type { NavDestination, NavProps } from \"./nav\";\n\nexport interface DockProps<T extends string> extends NavProps<T> {\n edge?: \"top\" | \"bottom\";\n}\n\n/** A floating pill of destinations. Desktop and tablet; it does not reach the thumb on a phone. */\nexport function Dock<T extends string>({ items, value, onChange, onCreate, createLabel = \"Create\", edge = \"bottom\", className }: DockProps<T>) {\n const layoutId = useId();\n\n const renderItem = (item: NavDestination<T>) => {\n const active = item.id === value;\n return (\n <Tooltip key={item.id} content={item.label} placement={edge === \"bottom\" ? \"top\" : \"bottom\"}>\n <button\n type=\"button\"\n aria-label={item.label}\n aria-current={active ? \"page\" : undefined}\n onClick={() => onChange(item.id)}\n className={cn(\n \"relative flex h-10 w-10 shrink-0 items-center justify-center rounded-full transition-colors motion-instant\",\n active ? \"text-fg\" : \"text-fg-3 hover:text-fg-2\",\n )}\n >\n {active && (\n <motion.span layoutId={layoutId} transition={m.settle} className=\"absolute inset-0 rounded-full bg-fill-2\" />\n )}\n <span className=\"relative\">\n {item.icon}\n {item.badge ? <NavBadge badge={item.badge} /> : null}\n </span>\n </button>\n </Tooltip>\n );\n };\n\n return (\n <nav\n aria-label=\"Primary\"\n className={cn(\"z-30 flex items-center gap-1 rounded-full border border-line bg-nav/95 p-1.5 shadow-raised backdrop-blur-md\", className)}\n >\n {items.map(renderItem)}\n {onCreate && (\n <>\n <span aria-hidden=\"true\" className=\"mx-0.5 h-6 w-px bg-line\" />\n <Tooltip content={createLabel} placement={edge === \"bottom\" ? \"top\" : \"bottom\"}>\n <motion.button\n type=\"button\"\n whileTap={{ scale: 0.94 }}\n onClick={onCreate}\n aria-label={createLabel}\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent transition-colors hover:bg-accent/90\"\n >\n <Plus size={20} strokeWidth={2.5} />\n </motion.button>\n </Tooltip>\n </>\n )}\n </nav>\n );\n}\n","import { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport { PanelLeftClose, Plus } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { Tooltip } from \"./Tooltip\";\nimport { NavBadge } from \"./TabBar\";\nimport type { NavDestination, NavProps } from \"./nav\";\n\nexport interface NavRailProps<T extends string> extends NavProps<T> {\n side?: \"left\" | \"right\";\n /** `rail` is a 64px icon column; `sidebar` is 224px with labels. */\n variant?: \"rail\" | \"sidebar\";\n /** Detach from the edge and float as a rounded pill column. */\n floating?: boolean;\n align?: \"start\" | \"center\" | \"end\";\n /**\n * Content between the destinations and the footer — the recent chats, on a desktop.\n * It takes the leftover height and scrolls on its own, so the destinations and the\n * footer never move.\n */\n section?: ReactNode;\n /** Show a button that switches between the labelled sidebar and the icon rail. */\n onToggle?: () => void;\n}\n\nconst alignClass = { start: \"justify-start\", center: \"justify-center\", end: \"justify-end\" };\n\n/**\n * Desktop navigation. A rail of icons, or a labelled sidebar when there is room.\n * Icon-only items get a tooltip, because an icon on its own is a guess.\n */\nconst NavExpandedContext = createContext(true);\n\n/** Whether the side navigation this sits in is open — for content passed as `section`. */\nexport function useNavExpanded() {\n return useContext(NavExpandedContext);\n}\n\n/** The icon column. Every row keeps its icon in this slot, open or folded. */\nconst SLOT = \"flex w-11 shrink-0 items-center justify-center\";\n\n/**\n * A label that is uncovered rather than moved. It never wraps — a line breaking while\n * the width changes is exactly the shift to avoid — and it fades on the way out at once,\n * and on the way in only once there is room for it.\n */\nexport function NavLabel({ children, className }: { children: ReactNode; className?: string }) {\n const open = useNavExpanded();\n return (\n <span\n className={cn(\n \"relative min-w-0 flex-1 overflow-hidden whitespace-nowrap text-left transition-opacity\",\n \"[mask-image:linear-gradient(to_right,black_calc(100%-14px),transparent)]\",\n open ? \"opacity-100 duration-200 delay-100\" : \"opacity-0 duration-100\",\n className,\n )}\n >\n {children}\n </span>\n );\n}\n\n/**\n * Desktop navigation: an icon rail, or a labelled sidebar — the same element either\n * way. Folding and unfolding animates the width and nothing else. Icons sit in one\n * fixed slot in both states, so they never move; labels are revealed by the width, not\n * laid out again; the section and the footer keep their rows. What changes is how much\n * of each row you can see.\n */\nexport function NavRail<T extends string>(props: NavRailProps<T>) {\n if (props.floating) return <FloatingRail {...props} />;\n return <DockedNav {...props} />;\n}\n\nfunction DockedNav<T extends string>({\n items, value, onChange, onCreate, createLabel = \"Create\", footerItems, side = \"left\",\n variant = \"rail\", section, onToggle, className,\n}: NavRailProps<T>) {\n const layoutId = useId();\n const reduced = useReducedMotion();\n const open = variant === \"sidebar\";\n const width = open ? (section ? 256 : 224) : 64;\n const tip = side === \"left\" ? \"right\" : \"left\";\n\n const row = (item: NavDestination<T>) => {\n const active = item.id === value;\n return (\n <Tooltip key={item.id} content={item.label} placement={tip} disabled={open} className=\"flex w-full\">\n <button\n type=\"button\"\n aria-label={item.label}\n aria-current={active ? \"page\" : undefined}\n onClick={() => onChange(item.id)}\n className={cn(\n \"relative flex h-10 w-full shrink-0 items-center overflow-hidden rounded-xl transition-colors motion-instant\",\n active ? \"text-fg\" : \"text-fg-3 hover:bg-fill hover:text-fg-2\",\n )}\n >\n {active && <motion.span layoutId={layoutId} transition={m.settle} className=\"absolute inset-0 rounded-xl bg-fill-2\" />}\n <span className={cn(SLOT, \"relative\")}>\n {item.icon}\n {item.badge ? <NavBadge badge={item.badge} /> : null}\n </span>\n <NavLabel className=\"text-base font-medium\">{item.label}</NavLabel>\n </button>\n </Tooltip>\n );\n };\n\n const divider = <span aria-hidden=\"true\" className=\"mx-1 my-1 h-px shrink-0 bg-line\" />;\n\n return (\n <NavExpandedContext.Provider value={open}>\n <motion.nav\n aria-label=\"Primary\"\n initial={false}\n animate={{ width }}\n transition={reduced ? { duration: 0 } : m.sidebar}\n className={cn(\n \"z-30 flex h-full shrink-0 flex-col gap-1 bg-nav px-2.5 py-3 text-fg\",\n side === \"left\" ? \"border-r border-line\" : \"border-l border-line\",\n className,\n )}\n >\n {onCreate && (\n <Tooltip content={createLabel} placement={tip} disabled={open} className=\"flex w-full\">\n <motion.button\n type=\"button\"\n whileTap={{ scale: 0.97 }}\n onClick={onCreate}\n aria-label={createLabel}\n className=\"flex h-10 w-full shrink-0 items-center overflow-hidden rounded-xl bg-accent text-on-accent transition-colors hover:bg-accent/90\"\n >\n <span className={SLOT}>\n <Plus size={18} strokeWidth={2.5} />\n </span>\n <NavLabel className=\"text-base font-medium\">{createLabel}</NavLabel>\n </motion.button>\n </Tooltip>\n )}\n {onCreate && divider}\n {items.map(row)}\n\n {/* The section fades in and out rather than popping — a screen that takes the\n recent chats away animates the width at the same moment. While it leaves,\n it and the spacer share the free height, so the footer does not move. */}\n <AnimatePresence initial={false}>\n {section && (\n <motion.div\n key=\"section\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={reduced ? { duration: 0 } : m.quick}\n className=\"-mx-2.5 flex min-h-0 flex-1 flex-col px-2.5\"\n >\n {/* Nothing above it to divide from when the section is all there is. */}\n {(onCreate || items.length > 0) && divider}\n <div className=\"scrollbar-thin -mx-2.5 min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-2.5\">{section}</div>\n </motion.div>\n )}\n </AnimatePresence>\n {!section && <span aria-hidden=\"true\" className=\"flex-1\" />}\n\n {(footerItems?.length || onToggle) && divider}\n {/* The fold sits above the footer: settings is always the last thing in the rail. */}\n {onToggle && (\n <Tooltip content=\"Expand sidebar\" placement={tip} disabled={open} className=\"flex w-full\">\n <button\n type=\"button\"\n onClick={onToggle}\n aria-label={open ? \"Collapse sidebar\" : \"Expand sidebar\"}\n aria-expanded={open}\n className=\"flex h-10 w-full shrink-0 items-center overflow-hidden rounded-xl text-fg-3 transition-colors hover:bg-fill hover:text-fg\"\n >\n <span className={SLOT}>\n {/* One glyph, turned: it points the way the panel will go. */}\n <motion.span animate={{ rotate: open ? 0 : 180 }} transition={reduced ? { duration: 0 } : m.sidebar} className=\"flex\">\n <PanelLeftClose size={18} className={side === \"right\" ? \"-scale-x-100\" : undefined} />\n </motion.span>\n </span>\n <NavLabel className=\"text-base font-medium\">Collapse</NavLabel>\n </button>\n </Tooltip>\n )}\n {footerItems?.map(row)}\n </motion.nav>\n </NavExpandedContext.Provider>\n );\n}\n\nfunction FloatingRail<T extends string>({\n items, value, onChange, onCreate, createLabel = \"Create\", footerItems, side = \"left\",\n variant = \"rail\", floating = false, align = \"start\", className,\n}: NavRailProps<T>) {\n const layoutId = useId();\n const labelled = variant === \"sidebar\";\n\n const renderItem = (item: NavDestination<T>) => {\n const active = item.id === value;\n const button = (\n <button\n key={item.id}\n type=\"button\"\n aria-label={labelled ? undefined : item.label}\n aria-current={active ? \"page\" : undefined}\n onClick={() => onChange(item.id)}\n className={cn(\n \"relative flex shrink-0 items-center transition-colors motion-instant\",\n labelled ? \"h-10 w-full gap-3 rounded-xl px-3\" : \"h-11 w-11 justify-center\",\n !labelled && (floating ? \"rounded-full\" : \"rounded-xl\"),\n active ? \"text-fg\" : \"text-fg-3 hover:text-fg-2\",\n )}\n >\n {active && (\n <motion.span\n layoutId={layoutId}\n transition={m.settle}\n className={cn(\"absolute inset-0 bg-fill-2\", labelled || !floating ? \"rounded-xl\" : \"rounded-full\")}\n />\n )}\n <span className=\"relative shrink-0\">\n {item.icon}\n {item.badge ? <NavBadge badge={item.badge} /> : null}\n </span>\n {labelled && <span className=\"relative min-w-0 flex-1 truncate text-left text-base font-medium\">{item.label}</span>}\n {labelled && item.badge && typeof item.badge === \"number\" && (\n <span className=\"relative shrink-0 rounded-full bg-fill-3 px-1.5 text-2xs font-semibold tabular-nums text-fg-2\">{item.badge}</span>\n )}\n </button>\n );\n return labelled ? button : <Tooltip key={item.id} content={item.label} placement={side === \"left\" ? \"right\" : \"left\"}>{button}</Tooltip>;\n };\n\n const createButton = onCreate && (\n labelled ? (\n <button\n type=\"button\"\n onClick={onCreate}\n className=\"flex h-10 w-full items-center gap-2.5 rounded-xl bg-accent px-3 text-base font-medium text-on-accent transition-colors hover:bg-accent/90\"\n >\n <Plus size={18} strokeWidth={2.5} />\n {createLabel}\n </button>\n ) : (\n <Tooltip content={createLabel} placement={side === \"left\" ? \"right\" : \"left\"}>\n <motion.button\n type=\"button\"\n whileTap={{ scale: 0.94 }}\n onClick={onCreate}\n aria-label={createLabel}\n className={cn(\"flex h-11 w-11 shrink-0 items-center justify-center bg-accent text-on-accent transition-colors hover:bg-accent/90\", floating ? \"rounded-full\" : \"rounded-xl\")}\n >\n <Plus size={20} strokeWidth={2.5} />\n </motion.button>\n </Tooltip>\n )\n );\n\n return (\n <nav\n aria-label=\"Primary\"\n className={cn(\n \"z-30 flex flex-col text-fg\",\n labelled ? \"w-56 gap-1 p-3\" : \"w-16 items-center gap-1.5 py-3\",\n floating\n ? \"gap-1.5 rounded-2xl border border-line bg-nav/95 p-2 shadow-raised backdrop-blur-md\"\n : cn(\"h-full bg-nav\", side === \"left\" ? \"border-r border-line\" : \"border-l border-line\"),\n !floating && alignClass[align],\n className,\n )}\n >\n {createButton}\n {createButton && <span aria-hidden=\"true\" className={cn(\"my-1 h-px bg-line\", labelled ? \"w-full\" : \"w-7\")} />}\n {items.map(renderItem)}\n {footerItems && footerItems.length > 0 && (\n <>\n <span aria-hidden=\"true\" className=\"flex-1\" />\n <span aria-hidden=\"true\" className={cn(\"my-1 h-px bg-line\", labelled ? \"w-full\" : \"w-7\")} />\n {footerItems.map(renderItem)}\n </>\n )}\n </nav>\n );\n}\n","import type { ReactNode, Ref } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { useCompactLayout } from \"../lib/useMediaQuery\";\nimport { Dock } from \"./Dock\";\nimport { NavRail } from \"./NavRail\";\nimport { TabBar } from \"./TabBar\";\nimport type { NavDestination } from \"./nav\";\n\nexport type NavStyle = \"auto\" | \"tabs\" | \"tabsLabelled\" | \"rail\" | \"sidebar\" | \"floatingRail\" | \"dock\" | \"header\";\n\nexport interface AppShellProps<T extends string> {\n items: readonly NavDestination<T>[];\n value: T;\n onChange: (id: T) => void;\n onCreate?: () => void;\n createLabel?: string;\n footerItems?: readonly NavDestination<T>[];\n /**\n * `auto` picks tabs on touch/narrow and a rail on desktop. The others are the\n * user's explicit choice — the app already lets people pick, and a phone-sized\n * window still falls back to tabs so nothing becomes unreachable.\n */\n navStyle?: NavStyle;\n side?: \"left\" | \"right\";\n dockEdge?: \"top\" | \"bottom\";\n /** Desktop window chrome, rendered above everything. */\n titleBar?: ReactNode;\n /** Header inside the content column. */\n header?: ReactNode;\n /** The scrolling content element — for a header that condenses on scroll, or for\n resetting the scroll position when the page's content changes underneath it. */\n mainRef?: Ref<HTMLElement>;\n /** Content under the destinations — recent chats. Shown folded on the rail too, so\n it does not appear and vanish as the sidebar opens and closes. */\n navSection?: ReactNode;\n /** Let the person switch the side navigation between sidebar and rail. */\n onNavToggle?: () => void;\n children: ReactNode;\n className?: string;\n}\n\n/**\n * The application frame. Owns where navigation lives so pages never have to think\n * about it: on a phone the bar is at the bottom, on desktop the rail is at the side,\n * and the content column is the same component either way.\n *\n * It fills its parent (`h-full`). Mounted at the app root, give it a real height —\n * `<AppShell className=\"h-dvh\">` — since #root only sets a min-height.\n */\nexport function AppShell<T extends string>({\n items, value, onChange, onCreate, createLabel, footerItems, navStyle = \"auto\",\n side = \"left\", dockEdge = \"bottom\", titleBar, header, mainRef, navSection, onNavToggle, children, className,\n}: AppShellProps<T>) {\n const compact = useCompactLayout();\n const style: NavStyle = navStyle === \"auto\" ? (compact ? \"tabs\" : \"rail\") : navStyle;\n /* A phone-sized window can't host a rail or a dock; fall back rather than clip. */\n const resolved: NavStyle = compact && (style === \"rail\" || style === \"sidebar\" || style === \"floatingRail\" || style === \"dock\") ? \"tabs\" : style;\n\n const navProps = { items, value, onChange, onCreate, createLabel, footerItems };\n const sideNav = resolved === \"rail\" || resolved === \"sidebar\" || resolved === \"floatingRail\";\n\n return (\n <div className={cn(\"relative flex h-full flex-col overflow-hidden bg-surface text-fg\", className)}>\n {titleBar}\n <div className={cn(\"flex min-h-0 flex-1\", side === \"right\" && \"flex-row-reverse\")}>\n {sideNav &&\n (resolved === \"floatingRail\" ? (\n <div className={cn(\"absolute top-1/2 z-30 -translate-y-1/2\", side === \"left\" ? \"left-4\" : \"right-4\")}>\n <NavRail {...navProps} side={side} floating />\n </div>\n ) : (\n <NavRail\n {...navProps}\n side={side}\n variant={resolved === \"sidebar\" ? \"sidebar\" : \"rail\"}\n section={navSection}\n onToggle={onNavToggle}\n />\n ))}\n\n <div className={cn(\"@container flex min-w-0 flex-1 flex-col\", resolved === \"floatingRail\" && (side === \"left\" ? \"pl-20\" : \"pr-20\"))}>\n {header}\n <main ref={mainRef} className=\"scrollbar-thin min-h-0 flex-1 overflow-y-auto\">{children}</main>\n </div>\n </div>\n\n {resolved === \"dock\" && (\n <div className={cn(\"pointer-events-none absolute inset-x-0 z-30 flex justify-center\", dockEdge === \"bottom\" ? \"bottom-4\" : \"top-4\")}>\n <div className=\"pointer-events-auto\">\n <Dock {...navProps} edge={dockEdge} />\n </div>\n </div>\n )}\n\n {(resolved === \"tabs\" || resolved === \"tabsLabelled\") && (\n <TabBar {...navProps} showLabels={resolved === \"tabsLabelled\"} />\n )}\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { Loader2, Pause, Play } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { Badge, type BadgeTone } from \"./Badge\";\n\nexport interface AudioItemProps {\n title: string;\n /** One line under the title when nothing is playing. */\n description?: ReactNode;\n src?: string | null;\n /** Called the first time play is pressed, to fetch the data lazily. */\n onLoadSrc?: () => Promise<string>;\n badge?: { label: string; tone?: BadgeTone };\n /** Trailing slot — an overflow menu. */\n actions?: ReactNode;\n className?: string;\n}\n\nfunction formatTime(value: number) {\n if (!Number.isFinite(value) || value < 0) value = 0;\n return `${Math.floor(value / 60)}:${String(Math.floor(value % 60)).padStart(2, \"0\")}`;\n}\n\n/**\n * A clip in the audio library. The scrub bar is a real range input, so it is\n * keyboard- and screen-reader-operable — the app's version is a div with onClick.\n */\nexport function AudioItem({ title, description, src: srcProp, onLoadSrc, badge, actions, className }: AudioItemProps) {\n const audioRef = useRef<HTMLAudioElement>(null);\n const wantPlay = useRef(false);\n const [src, setSrc] = useState<string | null>(srcProp ?? null);\n const [loading, setLoading] = useState(false);\n const [playing, setPlaying] = useState(false);\n const [current, setCurrent] = useState(0);\n const [duration, setDuration] = useState(0);\n\n useEffect(() => {\n if (srcProp !== undefined) setSrc(srcProp);\n }, [srcProp]);\n\n const toggle = useCallback(async () => {\n if (!src) {\n if (loading || !onLoadSrc) return;\n wantPlay.current = true;\n setLoading(true);\n try {\n setSrc(await onLoadSrc());\n } catch {\n wantPlay.current = false;\n setLoading(false);\n }\n return;\n }\n const el = audioRef.current;\n if (!el) return;\n if (playing) el.pause();\n else void el.play().catch(() => setPlaying(false));\n }, [src, loading, onLoadSrc, playing]);\n\n const seek = (value: number) => {\n const el = audioRef.current;\n if (!el || !duration) return;\n el.currentTime = value;\n setCurrent(value);\n };\n\n const started = Boolean(src) && duration > 0;\n const fill = duration > 0 ? (current / duration) * 100 : 0;\n\n return (\n <div className={cn(\"flex items-center gap-3 rounded-xl border border-line bg-surface-1 p-3 transition-colors hover:border-line-2\", className)}>\n <audio\n ref={audioRef}\n src={src ?? undefined}\n preload=\"metadata\"\n className=\"hidden\"\n onPlay={() => setPlaying(true)}\n onPause={() => setPlaying(false)}\n onEnded={() => setPlaying(false)}\n onTimeUpdate={(e) => setCurrent(e.currentTarget.currentTime)}\n onLoadedMetadata={(e) => setDuration(e.currentTarget.duration)}\n onCanPlay={() => {\n if (!wantPlay.current) return;\n wantPlay.current = false;\n setLoading(false);\n void audioRef.current?.play().catch(() => setPlaying(false));\n }}\n />\n\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={playing ? `Pause ${title}` : `Play ${title}`}\n className={cn(\n \"touch-target flex h-11 w-11 shrink-0 items-center justify-center rounded-full\",\n \"bg-accent text-on-accent transition-transform motion-instant active:scale-95\",\n )}\n >\n {loading ? <Loader2 size={18} className=\"animate-spin\" /> : playing ? <Pause size={18} fill=\"currentColor\" /> : <Play size={18} fill=\"currentColor\" className=\"ml-0.5\" />}\n </button>\n\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <p className=\"min-w-0 truncate text-base font-medium text-fg\">{title}</p>\n {badge && <Badge tone={badge.tone} className=\"shrink-0\">{badge.label}</Badge>}\n </div>\n {started ? (\n <div className=\"flex items-center gap-2.5\">\n <input\n type=\"range\"\n className=\"slider h-4 min-w-0 flex-1\"\n min={0}\n max={duration}\n step={0.1}\n value={current}\n onChange={(event) => seek(Number(event.target.value))}\n aria-label={`Seek ${title}`}\n aria-valuetext={`${formatTime(current)} of ${formatTime(duration)}`}\n style={{ [\"--slider-fill\" as string]: `${fill}%` }}\n />\n <span className=\"shrink-0 text-2xs tabular-nums text-fg-3\">\n {formatTime(current)} / {formatTime(duration)}\n </span>\n </div>\n ) : (\n description && <p className=\"truncate text-sm text-fg-3\">{description}</p>\n )}\n </div>\n\n {actions && <div className=\"shrink-0\">{actions}</div>}\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface AvatarProps {\n src?: string | null;\n name: string;\n size?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n /** Accent ring — the \"active\" / \"speaking\" state. */\n ring?: boolean;\n className?: string;\n /** Used by AvatarGroup to cut the overlap notch. */\n style?: React.CSSProperties;\n}\n\nconst sizeClass = {\n xs: \"h-6 w-6 text-2xs\",\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-14 w-14 text-lg\",\n xl: \"h-24 w-24 text-2xl\",\n};\n\nfunction initials(name: string) {\n return name\n .trim()\n .split(/\\s+/)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase() ?? \"\")\n .join(\"\");\n}\n\nexport function Avatar({ src, name, size = \"md\", ring, className, style }: AvatarProps) {\n const [broken, setBroken] = useState(false);\n const showImage = Boolean(src) && !broken;\n return (\n <span\n role=\"img\"\n aria-label={name}\n style={style}\n className={cn(\n \"relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full\",\n \"border border-line bg-fill-2 font-semibold text-fg-2\",\n ring && \"ring-2 ring-accent ring-offset-2 ring-offset-surface\",\n sizeClass[size],\n className,\n )}\n >\n {showImage ? (\n <img src={src!} alt=\"\" onError={() => setBroken(true)} className=\"h-full w-full object-cover\" />\n ) : (\n initials(name)\n )}\n </span>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Avatar, type AvatarProps } from \"./Avatar\";\n\nexport interface AvatarGroupProps {\n people: readonly { name: string; src?: string | null }[];\n /** Show at most this many, then a +N counter. Default 4. */\n max?: number;\n size?: AvatarProps[\"size\"];\n /** Hover/focus a face to bring it forward — desktop only, it's decoration. */\n interactive?: boolean;\n /** Replaces the +N chip. */\n overflow?: ReactNode;\n className?: string;\n}\n\n/**\n * Overlapping faces with a count.\n *\n * The gap between faces is cut out of each avatar with a mask, not painted with a ring\n * in the page colour. A ring has to guess the backdrop, and gets it wrong the moment the\n * group sits on a card, a gradient or a photo — which in this app it usually does.\n */\nconst geometry = {\n xs: { size: 24, pull: \"-ml-2\", cx: 28, cut: 14, chip: \"h-6 w-6 text-2xs\" },\n sm: { size: 32, pull: \"-ml-2.5\", cx: 38, cut: 18, chip: \"h-8 w-8 text-2xs\" },\n md: { size: 40, pull: \"-ml-3\", cx: 48, cut: 22, chip: \"h-10 w-10 text-xs\" },\n lg: { size: 56, pull: \"-ml-4\", cx: 68, cut: 30, chip: \"h-14 w-14 text-sm\" },\n xl: { size: 96, pull: \"-ml-6\", cx: 120, cut: 50, chip: \"h-24 w-24 text-lg\" },\n} as const;\n\nexport function AvatarGroup({ people, max = 4, size = \"sm\", interactive, overflow, className }: AvatarGroupProps) {\n const shown = people.slice(0, max);\n const rest = people.length - shown.length;\n const g = geometry[size ?? \"sm\"];\n const hasTrailing = rest > 0 || Boolean(overflow);\n\n /* Cut a notch where the next face will sit, so the real backdrop shows through. */\n const notch = `radial-gradient(circle ${g.cut}px at ${g.cx}px 50%, transparent 100%, black 100%)`;\n\n return (\n <div\n className={cn(\"flex items-center\", className)}\n role=\"group\"\n aria-label={`${people.length} ${people.length === 1 ? \"person\" : \"people\"}`}\n >\n {shown.map((person, index) => {\n const masked = index < shown.length - 1 || hasTrailing;\n return (\n <Avatar\n key={`${person.name}-${index}`}\n name={person.name}\n src={person.src}\n size={size}\n className={cn(index > 0 && g.pull, interactive && \"transition-transform hoverable:hover:-translate-y-0.5 hoverable:hover:z-10\")}\n style={masked ? { maskImage: notch, WebkitMaskImage: notch } : undefined}\n />\n );\n })}\n {rest > 0 &&\n (overflow ?? (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center justify-center rounded-full bg-fill-3 font-medium tabular-nums text-fg-2\",\n g.pull,\n g.chip,\n )}\n >\n +{rest}\n </span>\n ))}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { AlertTriangle, Info, WifiOff, X, XCircle } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport type BannerTone = \"info\" | \"warning\" | \"danger\" | \"offline\";\n\nexport interface BannerProps {\n tone?: BannerTone;\n children: ReactNode;\n action?: ReactNode;\n onDismiss?: () => void;\n /** Stick to the top of the scroll container. */\n sticky?: boolean;\n className?: string;\n}\n\nconst toneClass: Record<BannerTone, string> = {\n info: \"bg-info/15 text-info\",\n warning: \"bg-warning/15 text-warning\",\n danger: \"bg-danger/15 text-danger\",\n offline: \"bg-fill-3 text-fg-2\",\n};\n\nconst toneIcon: Record<BannerTone, ReactNode> = {\n info: <Info size={16} />,\n warning: <AlertTriangle size={16} />,\n danger: <XCircle size={16} />,\n offline: <WifiOff size={16} />,\n};\n\n/**\n * A full-width notice about the whole app or page — you're offline, a migration is\n * running, an update is ready. Alert is about one thing on the page; a Banner is about\n * the page. One line only: if it needs a paragraph, it's an Alert.\n */\nexport function Banner({ tone = \"info\", children, action, onDismiss, sticky, className }: BannerProps) {\n return (\n <div\n role={tone === \"danger\" ? \"alert\" : \"status\"}\n className={cn(\n \"flex items-center gap-2.5 px-4 py-2 text-sm\",\n toneClass[tone],\n sticky && \"sticky top-0 z-30\",\n className,\n )}\n >\n <span className=\"shrink-0\">{toneIcon[tone]}</span>\n <span className=\"min-w-0 flex-1 truncate font-medium\">{children}</span>\n {action && <span className=\"shrink-0\">{action}</span>}\n {onDismiss && (\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"-mr-1 shrink-0 rounded-md p-1 opacity-70 transition-opacity hover:opacity-100\"\n >\n <X size={14} />\n </button>\n )}\n </div>\n );\n}\n","import {\n createContext, useCallback, useContext, useEffect, useId, useRef, useState,\n type KeyboardEvent, type ReactElement, type ReactNode, cloneElement,\n} from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\ninterface MenuContextValue {\n open: boolean;\n setOpen: (open: boolean) => void;\n id: string;\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null);\n\nexport interface MenuProps {\n children: ReactNode;\n}\n\n/**\n * Dropdown menu. Compose: <Menu><MenuTrigger>…</MenuTrigger><MenuContent>…</MenuContent></Menu>\n * Anchored to the trigger; use Sheet on touch when the list is long.\n */\nexport function Menu({ children }: MenuProps) {\n const [open, setOpen] = useState(false);\n const id = useId();\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (event: PointerEvent) => {\n if (!ref.current?.contains(event.target as Node)) setOpen(false);\n };\n const onKeyDown = (event: globalThis.KeyboardEvent) => {\n if (event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open]);\n\n return (\n <MenuContext.Provider value={{ open, setOpen, id }}>\n <div ref={ref} className=\"relative inline-flex\">\n {children}\n </div>\n </MenuContext.Provider>\n );\n}\n\nfunction useMenu() {\n const ctx = useContext(MenuContext);\n if (!ctx) throw new Error(\"Menu parts must be used inside <Menu>\");\n return ctx;\n}\n\nexport function MenuTrigger({ children }: { children: ReactElement<Record<string, unknown>> }) {\n const { open, setOpen, id } = useMenu();\n const child = children.props as { onClick?: (e: unknown) => void };\n return cloneElement(children, {\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": open,\n \"aria-controls\": id,\n onClick: (e: unknown) => { child.onClick?.(e); setOpen(!open); },\n });\n}\n\nexport interface MenuContentProps {\n align?: \"start\" | \"end\";\n side?: \"bottom\" | \"top\";\n className?: string;\n children: ReactNode;\n}\n\nexport function MenuContent({ align = \"start\", side = \"bottom\", className, children }: MenuContentProps) {\n const { open, setOpen, id } = useMenu();\n const listRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (open) listRef.current?.querySelector<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])')?.focus();\n }, [open]);\n\n const onKeyDown = useCallback((event: KeyboardEvent<HTMLDivElement>) => {\n const items = Array.from(listRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])') ?? []);\n const index = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\") { event.preventDefault(); items[(index + 1) % items.length]?.focus(); }\n if (event.key === \"ArrowUp\") { event.preventDefault(); items[(index - 1 + items.length) % items.length]?.focus(); }\n if (event.key === \"Home\") { event.preventDefault(); items[0]?.focus(); }\n if (event.key === \"End\") { event.preventDefault(); items[items.length - 1]?.focus(); }\n if (event.key === \"Tab\") setOpen(false);\n }, [setOpen]);\n\n return (\n <AnimatePresence>\n {open && (\n <motion.div\n ref={listRef}\n id={id}\n role=\"menu\"\n onKeyDown={onKeyDown}\n initial={{ opacity: 0, scale: 0.97, y: side === \"bottom\" ? -4 : 4 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.97, y: side === \"bottom\" ? -4 : 4 }}\n transition={m.instant}\n className={cn(\n \"absolute z-50 min-w-48 rounded-xl border border-line bg-surface-2 p-1 shadow-raised\",\n side === \"bottom\" ? \"top-full mt-1.5\" : \"bottom-full mb-1.5\",\n align === \"start\" ? \"left-0 origin-top-left\" : \"right-0 origin-top-right\",\n className,\n )}\n >\n {children}\n </motion.div>\n )}\n </AnimatePresence>\n );\n}\n\nexport interface MenuItemProps {\n icon?: ReactNode;\n shortcut?: string;\n /** Paint it as destructive. */\n danger?: boolean;\n disabled?: boolean;\n selected?: boolean;\n onSelect?: () => void;\n children: ReactNode;\n}\n\nexport function MenuItem({ icon, shortcut, danger, disabled, selected, onSelect, children }: MenuItemProps) {\n const { setOpen } = useMenu();\n const activate = () => {\n if (disabled) return;\n onSelect?.();\n setOpen(false);\n };\n return (\n <button\n type=\"button\"\n role=\"menuitem\"\n aria-disabled={disabled || undefined}\n tabIndex={-1}\n onClick={activate}\n className={cn(\n \"flex w-full items-center gap-2.5 rounded-lg px-2.5 py-2 text-left text-base outline-none\",\n \"focus-visible:bg-fill-2 hover:bg-fill-2\",\n danger ? \"text-danger\" : \"text-fg\",\n disabled && \"pointer-events-none opacity-40\",\n )}\n >\n {icon && <span className={cn(\"shrink-0\", danger ? \"text-danger\" : \"text-fg-3\")}>{icon}</span>}\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n {selected && <Check size={14} className=\"shrink-0 text-accent\" />}\n {shortcut && <kbd className=\"shrink-0 text-xs text-fg-3\">{shortcut}</kbd>}\n </button>\n );\n}\n\nexport function MenuSeparator() {\n return <div role=\"separator\" className=\"my-1 h-px bg-line\" />;\n}\n\nexport function MenuLabel({ children }: { children: ReactNode }) {\n return <div className=\"px-2.5 pb-1 pt-2 text-2xs font-medium text-fg-3\">{children}</div>;\n}\n","import { Fragment, type ReactNode } from \"react\";\nimport { ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger } from \"./Menu\";\n\nexport interface Crumb {\n label: string;\n icon?: ReactNode;\n /** Omit on the last crumb — the page you are on is not a link. */\n onClick?: () => void;\n href?: string;\n}\n\nexport interface BreadcrumbProps {\n items: readonly Crumb[];\n /**\n * Keep the first crumb and the last `n`; everything between collapses into a menu.\n * Deep settings paths would otherwise wrap or scroll on a phone. Default 1.\n */\n maxVisible?: number;\n className?: string;\n}\n\nfunction CrumbLink({ crumb, current }: { crumb: Crumb; current: boolean }) {\n const content = (\n <>\n {crumb.icon && <span className=\"shrink-0\">{crumb.icon}</span>}\n <span className=\"truncate\">{crumb.label}</span>\n </>\n );\n const shared = \"inline-flex min-w-0 items-center gap-1.5 rounded-md px-1 py-0.5 text-sm\";\n\n if (current) {\n return (\n <span aria-current=\"page\" className={cn(shared, \"font-medium text-fg\")}>\n {content}\n </span>\n );\n }\n if (crumb.href) {\n return (\n <a href={crumb.href} className={cn(shared, \"text-fg-3 transition-colors hover:text-fg\")}>\n {content}\n </a>\n );\n }\n return (\n <button type=\"button\" onClick={crumb.onClick} className={cn(shared, \"text-fg-3 transition-colors hover:text-fg\")}>\n {content}\n </button>\n );\n}\n\n/**\n * Where you are in a nested screen. Desktop shows the whole path; on a narrow\n * viewport the middle collapses into a menu rather than wrapping to a second line.\n * It complements the back button, it does not replace it.\n */\nexport function Breadcrumb({ items, maxVisible = 1, className }: BreadcrumbProps) {\n if (items.length === 0) return null;\n\n const tailCount = Math.max(1, maxVisible);\n const collapses = items.length > tailCount + 2;\n const head = collapses ? items[0] : null;\n const hidden = collapses ? items.slice(1, items.length - tailCount) : [];\n const tail = collapses ? items.slice(items.length - tailCount) : items;\n\n const separator = (\n <ChevronRight size={14} className=\"shrink-0 text-fg-4\" aria-hidden=\"true\" />\n );\n\n return (\n <nav aria-label=\"Breadcrumb\" className={cn(\"flex min-w-0 items-center gap-1\", className)}>\n {head && (\n <>\n <CrumbLink crumb={head} current={false} />\n {separator}\n <Menu>\n <MenuTrigger>\n <button\n type=\"button\"\n aria-label={`${hidden.length} more levels`}\n className=\"tap-target flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg\"\n >\n <MoreHorizontal size={14} />\n </button>\n </MenuTrigger>\n <MenuContent>\n {hidden.map((crumb) => (\n <MenuItem key={crumb.label} icon={crumb.icon} onSelect={crumb.onClick}>\n {crumb.label}\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n {separator}\n </>\n )}\n {tail.map((crumb, index) => (\n <Fragment key={crumb.label}>\n {index > 0 && separator}\n <CrumbLink crumb={crumb} current={index === tail.length - 1} />\n </Fragment>\n ))}\n </nav>\n );\n}\n","/**\n * The icon ladder. Five steps, mapped to what an icon sits next to, so nobody has to\n * pick a number again.\n *\n * Before this file Crisp had eleven sizes in use — 10, 11, 12, 13, 14, 15, 16, 17, 18,\n * 20, 22 — which is the same drift the README criticises the app for. Fifteen next to\n * sixteen is a difference nobody sees and everybody maintains.\n *\n * Type, spacing, radius, density and motion all went through a scale. This is the one\n * axis that never did.\n */\nexport const icon = {\n /** Inline with 11–12px meta: a pin beside a timestamp, a dot in a badge. */\n xs: 12,\n /** Small controls and dense rows — `sm` buttons, chips, clear buttons. */\n sm: 14,\n /** The default. `md` controls, menu items, inputs, a chevron. */\n md: 16,\n /** `lg` controls, the icon tile in a list row, toolbars, nav destinations. */\n lg: 18,\n /** Standing alone with no label: empty states, a composer's primary action. */\n xl: 20,\n} as const;\n\nexport type IconSize = keyof typeof icon;\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\n\nexport type ButtonVariant = \"primary\" | \"tonal\" | \"secondary\" | \"ghost\" | \"danger\";\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n loading?: boolean;\n leading?: ReactNode;\n trailing?: ReactNode;\n /** Fill the width. For two buttons sharing a row, give each `className=\"flex-1\"` instead. */\n block?: boolean;\n children?: ReactNode;\n}\n\nconst variantClass: Record<ButtonVariant, string> = {\n // One per screen. Solid accent with on-accent text is the only high-emphasis surface.\n primary: \"bg-accent text-on-accent hover:bg-accent/82 active:bg-accent/68\",\n // The app's familiar tinted-accent CTA.\n tonal: \"border border-accent/30 bg-accent/15 text-accent hover:border-accent/55 hover:bg-accent/28 active:bg-accent/38\",\n secondary: \"border border-line bg-fill-2 text-fg hover:border-line-3 hover:bg-fill-3 active:bg-line-2\",\n ghost: \"text-fg-2 hover:bg-fill-2 hover:text-fg active:bg-fill-3\",\n danger: \"border border-danger/25 bg-danger/12 text-danger hover:border-danger/55 hover:bg-danger/22 active:bg-danger/32\",\n};\n\n/* The ring has to contrast with what it rings: accent on an accent fill disappears, and\n a green ring around a destructive button contradicts the button. */\nconst focusClass: Record<ButtonVariant, string> = {\n primary: \"focus-visible:outline-fg\",\n tonal: \"focus-visible:outline-accent\",\n secondary: \"focus-visible:outline-fg-2\",\n ghost: \"focus-visible:outline-fg-2\",\n danger: \"focus-visible:outline-danger\",\n};\n\nconst sizeClass: Record<ButtonSize, string> = {\n sm: \"control-sm gap-1.5 rounded-lg px-3 text-sm\",\n md: \"control-md gap-2 rounded-xl px-4 text-base\",\n lg: \"control-lg gap-2 rounded-xl px-5 text-base\",\n};\n\nexport const iconSize: Record<ButtonSize, number> = { sm: icon.sm, md: icon.md, lg: icon.lg };\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n variant = \"secondary\",\n size = \"md\",\n loading = false,\n leading,\n trailing,\n block,\n className,\n children,\n disabled,\n type = \"button\",\n ...rest\n },\n ref,\n) {\n const inert = disabled || loading;\n return (\n <button\n ref={ref}\n type={type}\n disabled={disabled}\n aria-busy={loading || undefined}\n aria-disabled={inert || undefined}\n className={cn(\n \"touch-target relative inline-flex shrink-0 select-none items-center justify-center whitespace-nowrap font-medium\",\n /* Depth comes from CSS, not a JS spring: one less animation to schedule per tap,\n and it survives a webview that is already busy streaming tokens. */\n variant === \"ghost\" ? \"raise-flat\" : \"raise\",\n \"focus-visible:outline-1 focus-visible:outline-offset-2\",\n focusClass[variant],\n \"disabled:opacity-45\",\n /* Loading keeps focus: `disabled` would drop it to the body mid-submit. */\n (loading || disabled) && \"pointer-events-none\",\n variantClass[variant],\n sizeClass[size],\n block && \"w-full\",\n className,\n )}\n {...rest}\n >\n {loading && (\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <Loader2 size={iconSize[size]} className=\"animate-spin\" />\n </span>\n )}\n <span className={cn(\"inline-flex items-center gap-[inherit]\", loading && \"invisible\")}>\n {leading}\n {children}\n {trailing}\n </span>\n </button>\n );\n});\n","import { Children, cloneElement, isValidElement, type ReactElement, type ReactNode } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { Button, type ButtonProps } from \"./Button\";\nimport { Menu, MenuContent, MenuTrigger } from \"./Menu\";\n\nexport interface ButtonGroupProps {\n /** Buttons joined into one control — the inner corners are squared off. */\n attached?: boolean;\n className?: string;\n children: ReactNode;\n}\n\nexport function ButtonGroup({ attached = true, className, children }: ButtonGroupProps) {\n const items = Children.toArray(children).filter(isValidElement) as ReactElement<{ className?: string }>[];\n return (\n <div role=\"group\" className={cn(\"inline-flex\", attached ? \"-space-x-px\" : \"gap-2\", className)}>\n {items.map((child, index) =>\n cloneElement(child, {\n className: cn(\n child.props.className,\n attached && index > 0 && \"rounded-l-none\",\n attached && index < items.length - 1 && \"rounded-r-none\",\n attached && \"relative focus-visible:z-10\",\n ),\n }),\n )}\n </div>\n );\n}\n\nexport interface SplitButtonProps extends Omit<ButtonProps, \"children\"> {\n children: ReactNode;\n /** Menu items for the attached chevron. */\n menu: ReactNode;\n menuLabel?: string;\n}\n\n/**\n * A primary action with alternatives behind a chevron. The composer already does this\n * with hold-to-send-as-system — a gesture nobody discovers. On desktop this is the\n * visible version of the same thing.\n */\nexport function SplitButton({ children, menu, menuLabel = \"More actions\", variant = \"primary\", size = \"md\", ...rest }: SplitButtonProps) {\n return (\n <div className=\"inline-flex -space-x-px\">\n <Button variant={variant} size={size} className=\"rounded-r-none\" {...rest}>\n {children}\n </Button>\n <Menu>\n <MenuTrigger>\n <Button variant={variant} size={size} aria-label={menuLabel} className=\"rounded-l-none px-2\">\n <ChevronDown size={16} />\n </Button>\n </MenuTrigger>\n <MenuContent align=\"end\">{menu}</MenuContent>\n </Menu>\n </div>\n );\n}\n","import { forwardRef, type HTMLAttributes } from \"react\";\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\n/* Elevation does the separating; the hairline is only there to hold an edge against a\n busy backdrop. `bordered={false}` drops it where the lift is enough on its own. */\nconst surface = \"rounded-xl bg-surface-1\";\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** `raised` sits on the page; `overlay` floats above everything. */\n level?: \"raised\" | \"overlay\";\n /** A hairline edge. Off by default — elevation already separates it. */\n bordered?: boolean;\n padding?: \"none\" | \"sm\" | \"md\";\n}\n\nconst paddingClass = { none: \"\", sm: \"p-3\", md: \"p-4\" };\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n { level = \"flat\", padding = \"md\", className, ...rest },\n ref,\n) {\n return (\n <div\n ref={ref}\n className={cn(\n surface,\n level === \"raised\" && \"bg-surface-el shadow-raised\",\n paddingClass[padding],\n className,\n )}\n {...rest}\n />\n );\n});\n\n/** A clickable card is a button, not a div with onClick. */\nexport interface CardButtonProps extends HTMLMotionProps<\"button\"> {\n selected?: boolean;\n padding?: \"none\" | \"sm\" | \"md\";\n}\n\nexport const CardButton = forwardRef<HTMLButtonElement, CardButtonProps>(function CardButton(\n { selected, padding = \"md\", className, type = \"button\", ...rest },\n ref,\n) {\n return (\n <motion.button\n ref={ref}\n type={type}\n aria-pressed={selected}\n whileTap={{ scale: 0.99 }}\n transition={m.instant}\n className={cn(\n surface,\n \"touch-target block w-full text-left transition-[background-color,box-shadow] motion-instant\",\n \"hover:bg-fill-2\",\n /* Chosen, not painted: accent stays the colour of things you act on. */\n selected && \"ring-2 ring-inset ring-fg/30\",\n paddingClass[padding],\n className,\n )}\n {...rest}\n />\n );\n});\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface CarouselProps {\n /** One node per slide. */\n children: ReactNode[];\n /** Dots and arrows. Arrows are hidden where there is no pointer. */\n controls?: boolean;\n \"aria-label\": string;\n className?: string;\n slideClassName?: string;\n}\n\n/**\n * A horizontal pager built on native scroll-snap: swipe on touch, arrows and keys on\n * desktop, and it keeps working with JavaScript busy. Onboarding, feature tours,\n * image variants.\n */\nexport function Carousel({ children, controls = true, className, slideClassName, ...aria }: CarouselProps) {\n const trackRef = useRef<HTMLDivElement>(null);\n const [index, setIndex] = useState(0);\n const count = children.length;\n\n const scrollTo = useCallback((next: number) => {\n const track = trackRef.current;\n if (!track) return;\n const clamped = Math.max(0, Math.min(next, count - 1));\n track.scrollTo({ left: clamped * track.clientWidth, behavior: \"smooth\" });\n }, [count]);\n\n useEffect(() => {\n const track = trackRef.current;\n if (!track) return;\n const onScroll = () => {\n if (track.clientWidth === 0) return;\n setIndex(Math.round(track.scrollLeft / track.clientWidth));\n };\n track.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => track.removeEventListener(\"scroll\", onScroll);\n }, []);\n\n return (\n <div className={cn(\"relative\", className)} role=\"group\" aria-roledescription=\"carousel\" aria-label={aria[\"aria-label\"]}>\n <div\n ref={trackRef}\n tabIndex={0}\n onKeyDown={(event) => {\n if (event.key === \"ArrowRight\") { event.preventDefault(); scrollTo(index + 1); }\n if (event.key === \"ArrowLeft\") { event.preventDefault(); scrollTo(index - 1); }\n }}\n className=\"scrollbar-none flex snap-x snap-mandatory overflow-x-auto rounded-xl outline-none\"\n >\n {children.map((slide, i) => (\n <div\n key={i}\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={`${i + 1} of ${count}`}\n className={cn(\"w-full shrink-0 snap-center\", slideClassName)}\n >\n {slide}\n </div>\n ))}\n </div>\n\n {controls && count > 1 && (\n <>\n <div className=\"mt-3 flex items-center justify-center gap-1.5\">\n {children.map((_, i) => (\n <button\n key={i}\n type=\"button\"\n onClick={() => scrollTo(i)}\n aria-label={`Go to slide ${i + 1}`}\n aria-current={i === index ? \"true\" : undefined}\n className={cn(\"h-1.5 rounded-full transition-all motion-slow\", i === index ? \"w-5 bg-accent\" : \"w-1.5 bg-fill-3 hover:bg-line-3\")}\n />\n ))}\n </div>\n {/* Arrows only where a pointer can reach them; touch has the swipe. */}\n <button\n type=\"button\"\n onClick={() => scrollTo(index - 1)}\n disabled={index === 0}\n aria-label=\"Previous slide\"\n className=\"absolute left-2 top-1/2 hidden h-9 w-9 -translate-y-1/2 items-center justify-center rounded-full border border-line bg-surface-el/90 text-fg-2 backdrop-blur-md transition-colors hover:text-fg disabled:opacity-0 hoverable:flex\"\n >\n <ChevronLeft size={18} />\n </button>\n <button\n type=\"button\"\n onClick={() => scrollTo(index + 1)}\n disabled={index === count - 1}\n aria-label=\"Next slide\"\n className=\"absolute right-2 top-1/2 hidden h-9 w-9 -translate-y-1/2 items-center justify-center rounded-full border border-line bg-surface-el/90 text-fg-2 backdrop-blur-md transition-colors hover:text-fg disabled:opacity-0 hoverable:flex\"\n >\n <ChevronRight size={18} />\n </button>\n </>\n )}\n </div>\n );\n}\n","/**\n * Deterministic tint from a name, used as the backdrop when an item has no image.\n * The app derives this from the avatar's own colours; the fallback only has to be\n * stable, so the same character always looks the same.\n */\nexport function tintFromName(name: string) {\n let hash = 0;\n for (let i = 0; i < name.length; i++) hash = (hash * 31 + name.charCodeAt(i)) | 0;\n const hue = Math.abs(hash) % 360;\n return {\n hue,\n background: `linear-gradient(160deg, oklch(0.42 0.09 ${hue}), oklch(0.22 0.05 ${(hue + 40) % 360}))`,\n };\n}\n","import { useEffect, useState } from \"react\";\n\n/**\n * Mean relative luminance of an image, 0–1. Sampled at 12×12 — enough to tell a lit\n * room from a dark one, cheap enough to run on every background change.\n *\n * Returns `null` while loading, or if the canvas is tainted by a cross-origin image.\n * Callers must treat `null` as \"unknown\" and keep a safe default, never guess bright.\n */\nexport function useImageBrightness(src?: string | null) {\n const [brightness, setBrightness] = useState<number | null>(null);\n\n useEffect(() => {\n if (!src) {\n setBrightness(null);\n return;\n }\n let cancelled = false;\n const image = new Image();\n image.crossOrigin = \"anonymous\";\n image.onload = () => {\n if (cancelled) return;\n try {\n const size = 12;\n const canvas = document.createElement(\"canvas\");\n canvas.width = size;\n canvas.height = size;\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n if (!ctx) return setBrightness(null);\n ctx.drawImage(image, 0, 0, size, size);\n const { data } = ctx.getImageData(0, 0, size, size);\n let total = 0;\n let counted = 0;\n for (let i = 0; i < data.length; i += 4) {\n if (data[i + 3] < 8) continue;\n const channel = (c: number) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);\n };\n total += 0.2126 * channel(data[i]) + 0.7152 * channel(data[i + 1]) + 0.0722 * channel(data[i + 2]);\n counted++;\n }\n setBrightness(counted ? total / counted : null);\n } catch {\n /* Tainted canvas — a remote background without CORS headers. */\n setBrightness(null);\n }\n };\n image.onerror = () => !cancelled && setBrightness(null);\n image.src = src;\n return () => {\n cancelled = true;\n };\n }, [src]);\n\n return brightness;\n}\n","import { createContext, forwardRef, useContext, type CSSProperties, type ElementType, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { useImageBrightness } from \"../lib/imageBrightness\";\n\ninterface SurfaceContextValue {\n /** Something is painted behind the content — chrome above it should frost, not sit flat. */\n hasBackground: boolean;\n /** Whether that something is light or dark, so glass knows which way to tint. */\n tone: \"light\" | \"dark\";\n}\n\nconst SurfaceContext = createContext<SurfaceContextValue>({ hasBackground: false, tone: \"dark\" });\n\n/**\n * \"Am I sitting on a photo or a gradient, and is it light or dark?\" Components use this\n * to switch to glass — a translucent fill plus backdrop-blur — tinted the right way.\n */\nexport function useOnSurface() {\n return useContext(SurfaceContext);\n}\n\nexport interface SurfaceProps {\n /** A background image (data URL or asset URL) painted under the content. */\n image?: string | null;\n /** Which part of the image to keep when it is cropped to fit — `object-position`. */\n imagePosition?: string;\n /** A CSS colour or gradient painted under the content — what useAvatarGradient returns. */\n tint?: string | null;\n /**\n * Foreground colour for everything inside. When a gradient or photo decides the\n * background, it also decides the text colour, so pass what the extractor computed.\n */\n fg?: string | null;\n /** Optional explicit secondary colour; otherwise derived from `fg`. */\n fgMuted?: string | null;\n /**\n * How far to push the art away from the text. The image itself is never blurred —\n * the picture is the point. The chrome above it frosts instead.\n *\n * The veil follows the image: dark art gets a black veil, light art a white one, so\n * a bright photograph does not leave white text sitting on white.\n */\n scrim?: \"none\" | \"soft\" | \"auto\" | \"strong\";\n /**\n * Skip measuring and state the art's tone yourself — the app already computes this\n * when it extracts an avatar's gradient.\n */\n tone?: \"light\" | \"dark\";\n as?: ElementType;\n className?: string;\n style?: CSSProperties;\n children?: ReactNode;\n}\n\nconst scrimClass: Record<\"light\" | \"dark\", Record<\"none\" | \"soft\" | \"auto\" | \"strong\", string | null>> = {\n dark: { none: null, soft: \"bg-black/20\", auto: \"bg-black/40\", strong: \"bg-black/60\" },\n light: { none: null, soft: \"bg-white/25\", auto: \"bg-white/50\", strong: \"bg-white/70\" },\n};\n\n/** Above this mean luminance, text has to go dark. */\nconst LIGHT_THRESHOLD = 0.42;\n\n/**\n * A patch of UI whose background is decided by content — a character's extracted\n * gradient, a chat's background image — rather than by the theme.\n *\n * It rebinds the colour tiers for its subtree, so every Crisp component inside keeps\n * using `text-fg`, `text-fg-3`, `bg-fill`, `border-line` and simply comes out the right\n * colour. Without this, each component ends up carrying its own\n * `style={hasGradient ? { color: textColor } : {}}` — which is what the app does today,\n * four times in one card.\n */\nexport const Surface = forwardRef<HTMLElement, SurfaceProps>(function Surface(\n { image, imagePosition, tint, fg, fgMuted, scrim = \"auto\", tone: toneProp, as, className, style, children },\n ref,\n) {\n const Tag = (as ?? \"div\") as ElementType;\n const painted = Boolean(image || tint);\n const measured = useImageBrightness(toneProp || fg ? null : image);\n /* Unknown stays dark: a wrong guess toward light puts pale text on a pale photo. */\n const tone: \"light\" | \"dark\" = toneProp ?? (measured !== null && measured > LIGHT_THRESHOLD ? \"light\" : \"dark\");\n /* Without an explicit foreground, follow the art rather than the theme. */\n const resolvedFg = fg ?? (image && tone === \"light\" ? \"#111112\" : image ? \"#ffffff\" : null);\n\n /* Tiers are mixed toward transparent, not toward the surface colour: over a photo\n or a gradient there is no flat backdrop to blend into. */\n const vars = resolvedFg\n ? ({\n \"--color-fg\": resolvedFg,\n \"--color-fg-2\": fgMuted ?? `color-mix(in oklab, ${resolvedFg} 78%, transparent)`,\n \"--color-fg-3\": `color-mix(in oklab, ${resolvedFg} 58%, transparent)`,\n \"--color-fg-4\": `color-mix(in oklab, ${resolvedFg} 38%, transparent)`,\n /* Inputs and hover fills go the art's own way rather than lightening it: a\n white haze on a photograph reads as fog. */\n \"--color-fill\": tone === \"light\" ? \"rgb(255 255 255 / 0.45)\" : \"rgb(0 0 0 / 0.35)\",\n \"--color-fill-2\": `color-mix(in oklab, ${resolvedFg} 12%, transparent)`,\n \"--color-fill-3\": `color-mix(in oklab, ${resolvedFg} 18%, transparent)`,\n \"--color-line\": `color-mix(in oklab, ${resolvedFg} 14%, transparent)`,\n \"--color-line-2\": `color-mix(in oklab, ${resolvedFg} 22%, transparent)`,\n \"--color-line-3\": `color-mix(in oklab, ${resolvedFg} 32%, transparent)`,\n /* Cards and sheets inside become glass: a veil in the art's own darkness (or\n lightness), so a Card, an Input or a ListGroup dropped on a photo needs no\n special variant. */\n \"--color-surface-1\": tone === \"light\" ? \"rgb(255 255 255 / 0.55)\" : \"rgb(0 0 0 / 0.45)\",\n \"--color-surface-2\": tone === \"light\" ? \"rgb(255 255 255 / 0.7)\" : \"rgb(0 0 0 / 0.6)\",\n \"--color-surface-el\": tone === \"light\" ? \"rgb(255 255 255 / 0.55)\" : \"rgb(0 0 0 / 0.45)\",\n } as CSSProperties)\n : undefined;\n\n return (\n <SurfaceContext.Provider value={{ hasBackground: painted, tone }}>\n <Tag\n ref={ref}\n className={cn(\"relative isolate\", className)}\n style={{ ...vars, ...(tint && !image ? { background: tint } : undefined), ...style }}\n >\n {image && (\n /* An <img>, not a CSS background: an unquoted url() breaks on any URL\n containing parentheses — which a data URI routinely does — and fails\n silently. It is also never blurred; the picture is the point. */\n <img\n src={image}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0 -z-10 h-full w-full object-cover\"\n style={{ objectPosition: imagePosition, ...(tint ? { backgroundColor: tint } : undefined) }}\n />\n )}\n {painted && scrimClass[tone][scrim] && (\n <span aria-hidden=\"true\" className={cn(\"pointer-events-none absolute inset-0 -z-10\", scrimClass[tone][scrim])} />\n )}\n {children}\n </Tag>\n </SurfaceContext.Provider>\n );\n});\n","import { cn } from \"../lib/cn\";\n\nexport interface SkeletonProps {\n /** Text lines get a line-height-sized bar; circle for avatars; block for images/cards. */\n shape?: \"text\" | \"circle\" | \"block\";\n width?: string | number;\n height?: string | number;\n className?: string;\n}\n\nexport function Skeleton({ shape = \"text\", width, height, className }: SkeletonProps) {\n return (\n <div\n aria-hidden=\"true\"\n className={cn(\n \"skeleton\",\n shape === \"text\" && \"h-3.5 rounded-md\",\n shape === \"circle\" && \"rounded-full\",\n shape === \"block\" && \"rounded-xl\",\n className,\n )}\n style={{ width, height }}\n />\n );\n}\n\n/** Skeleton for a list row: avatar + two lines. */\nexport function SkeletonRow({ className }: { className?: string }) {\n return (\n <div className={cn(\"flex items-center gap-3 px-4 py-3\", className)}>\n <Skeleton shape=\"circle\" width={36} height={36} />\n <div className=\"flex-1 space-y-2\">\n <Skeleton width=\"45%\" />\n <Skeleton width=\"70%\" className=\"h-3\" />\n </div>\n </div>\n );\n}\n","import { forwardRef, useState, type ReactNode } from \"react\";\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { tintFromName } from \"../lib/tint\";\nimport { Surface } from \"./Surface\";\nimport { Skeleton } from \"./Skeleton\";\n\nexport type CharacterCardVariant = \"row\" | \"banner\";\n\nexport interface CharacterCardProps extends Omit<HTMLMotionProps<\"button\">, \"title\"> {\n name: string;\n description?: ReactNode;\n avatar?: string | null;\n /** CSS colour or gradient extracted from the avatar. Falls back to a tint from the name. */\n gradient?: string | null;\n /** Text colours that go with the gradient. */\n fg?: string | null;\n fgMuted?: string | null;\n /** `row` is the horizontal list card; `banner` is the wide cover card. */\n variant?: CharacterCardVariant;\n /** Slot on the trailing edge — a badge, a menu. Replaces the chevron. */\n trailing?: ReactNode;\n selected?: boolean;\n}\n\n/**\n * The home-screen character card, in the app's two shapes. When the avatar yields a\n * gradient, the whole card becomes a Surface and every child re-colours itself —\n * no per-element `style={{ color: textColor }}`.\n *\n * It grows with the column it sits in, not with the window: a container query, so a\n * narrow pane on a wide monitor still gets the phone-sized card.\n */\nexport const CharacterCard = forwardRef<HTMLButtonElement, CharacterCardProps>(function CharacterCard(\n { name, description, avatar, gradient, fg, fgMuted, variant = \"row\", trailing, selected, className, type = \"button\", ...rest },\n ref,\n) {\n const [broken, setBroken] = useState(false);\n const tint = gradient ?? tintFromName(name).background;\n const showAvatar = Boolean(avatar) && !broken;\n\n const shell = cn(\n \"group relative w-full overflow-hidden text-left\",\n \"rounded-2xl @3xl:rounded-3xl\",\n \"ring-1 ring-inset ring-line-2 transition-[box-shadow,transform] motion-instant\",\n selected && \"ring-2 ring-accent\",\n className,\n );\n\n if (variant === \"banner\") {\n return (\n <motion.button ref={ref} type={type} aria-pressed={selected} whileTap={{ scale: 0.99 }} transition={m.instant} className={shell} {...rest}>\n <Surface tint={tint} fg={fg} fgMuted={fgMuted} scrim=\"none\" className=\"flex h-24 w-full @3xl:h-36\">\n {/* The cover fades into the gradient rather than ending on a hard edge. */}\n <span\n aria-hidden=\"true\"\n className=\"absolute inset-y-0 left-0 w-3/5 max-w-[420px] overflow-hidden @3xl:w-1/2\"\n style={{ maskImage: \"linear-gradient(to right, black 55%, transparent)\", WebkitMaskImage: \"linear-gradient(to right, black 55%, transparent)\" }}\n >\n {showAvatar && (\n <img\n src={avatar!}\n alt=\"\"\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => setBroken(true)}\n className=\"h-full w-full scale-[1.14] object-cover transition-transform motion-slow ease-out group-hover:-translate-x-3\"\n />\n )}\n </span>\n <span className=\"relative ml-auto flex w-3/5 flex-col justify-center gap-1 p-4 @3xl:w-1/2 @3xl:p-6\">\n <span className=\"truncate text-lg font-semibold leading-tight text-fg @3xl:text-2xl\">{name}</span>\n {description && <span className=\"line-clamp-2 text-sm leading-snug text-fg-2 @3xl:text-base\">{description}</span>}\n </span>\n {trailing && <span className=\"absolute right-3 top-3\">{trailing}</span>}\n </Surface>\n </motion.button>\n );\n }\n\n return (\n <motion.button ref={ref} type={type} aria-pressed={selected} whileTap={{ scale: 0.99 }} transition={m.instant} className={shell} {...rest}>\n <Surface tint={tint} fg={fg} fgMuted={fgMuted} scrim=\"none\" className=\"flex w-full items-center gap-3.5 p-3.5 @3xl:gap-6 @3xl:p-6\">\n <span className=\"relative h-14 w-14 shrink-0 overflow-hidden rounded-full ring-2 ring-line-3 @3xl:h-24 @3xl:w-24\">\n {showAvatar ? (\n <img src={avatar!} alt=\"\" loading=\"lazy\" decoding=\"async\" onError={() => setBroken(true)} className=\"h-full w-full object-cover\" />\n ) : (\n <span className=\"flex h-full w-full items-center justify-center bg-fill-2 text-lg font-semibold text-fg-2\">\n {name.slice(0, 2).toUpperCase()}\n </span>\n )}\n </span>\n <span className=\"flex min-w-0 flex-1 flex-col gap-0.5 @3xl:gap-1.5\">\n <span className=\"truncate text-base font-semibold leading-tight text-fg @3xl:text-xl\">{name}</span>\n {description && <span className=\"line-clamp-1 text-sm leading-snug text-fg-2 @3xl:line-clamp-2 @3xl:text-base\">{description}</span>}\n </span>\n {trailing ?? <ChevronRight size={20} className=\"shrink-0 text-fg-3 transition-colors group-hover:text-fg-2\" />}\n </Surface>\n </motion.button>\n );\n});\n\nexport function CharacterCardSkeleton({ variant = \"row\" }: { variant?: CharacterCardVariant }) {\n if (variant === \"banner\") return <Skeleton shape=\"block\" className=\"h-24 w-full rounded-2xl @3xl:h-36 @3xl:rounded-3xl\" />;\n return (\n <div className=\"flex w-full items-center gap-3.5 rounded-2xl border border-line p-3.5 @3xl:gap-6 @3xl:rounded-3xl @3xl:p-6\">\n <Skeleton shape=\"circle\" className=\"h-14 w-14 shrink-0 @3xl:h-24 @3xl:w-24\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton width=\"40%\" className=\"h-4\" />\n <Skeleton width=\"70%\" className=\"h-3\" />\n </div>\n </div>\n );\n}\n","import { useId } from \"react\";\nimport {\n Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Line, LineChart,\n ResponsiveContainer, Tooltip, XAxis, YAxis,\n} from \"recharts\";\nimport { cn } from \"../lib/cn\";\n\n/* One categorical ramp, ordered so neighbouring series stay distinguishable.\n Accent first: a single-series chart is about the thing the app is about. */\nexport const CHART_SERIES = [\"var(--color-accent)\", \"var(--color-info)\", \"var(--color-secondary)\", \"var(--color-warning)\", \"var(--color-danger)\"] as const;\n\nexport interface ChartProps<Row extends Record<string, unknown>> {\n data: readonly Row[];\n /** Key holding the category or timestamp. */\n x: string;\n /** One entry per series. */\n series: readonly { key: string; label: string; color?: string }[];\n kind?: \"line\" | \"area\" | \"bar\";\n height?: number;\n /** Formats values in the axis and tooltip. */\n format?: (value: number) => string;\n /** Hide the y axis for a sparkline-sized chart. */\n minimal?: boolean;\n className?: string;\n}\n\nconst axisProps = {\n stroke: \"var(--color-fg-4)\",\n tickLine: false,\n axisLine: false,\n tick: { fontSize: 11, fill: \"var(--color-fg-3)\" },\n} as const;\n\nfunction ChartTooltip({ active, payload, label, format }: any) {\n if (!active || !payload?.length) return null;\n return (\n <div className=\"rounded-lg border border-line bg-surface-el px-2.5 py-2 shadow-raised\">\n <p className=\"mb-1 text-2xs text-fg-3\">{label}</p>\n {payload.map((entry: any) => (\n <p key={entry.dataKey} className=\"flex items-center gap-2 text-sm\">\n <span className=\"h-2 w-2 shrink-0 rounded-full\" style={{ background: entry.color }} />\n <span className=\"text-fg-2\">{entry.name}</span>\n <span className=\"ml-auto font-medium tabular-nums text-fg\">\n {format ? format(entry.value) : entry.value}\n </span>\n </p>\n ))}\n </div>\n );\n}\n\n/**\n * Charts on the token palette, so they follow a custom accent and stay legible on the\n * app's near-black surface. The app pulls in recharts already but styles each chart\n * inline with hard-coded colours.\n */\nexport function Chart<Row extends Record<string, unknown>>({\n data, x, series, kind = \"area\", height = 200, format, minimal, className,\n}: ChartProps<Row>) {\n const id = useId();\n const Root = kind === \"bar\" ? BarChart : kind === \"line\" ? LineChart : AreaChart;\n\n return (\n <div className={cn(\"w-full\", className)} style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <Root data={data as Row[]} margin={{ top: 4, right: 4, bottom: 0, left: minimal ? 0 : -16 }}>\n <defs>\n {series.map((s, i) => (\n <linearGradient key={s.key} id={`${id}-${s.key}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={s.color ?? CHART_SERIES[i % CHART_SERIES.length]} stopOpacity={0.35} />\n <stop offset=\"100%\" stopColor={s.color ?? CHART_SERIES[i % CHART_SERIES.length]} stopOpacity={0} />\n </linearGradient>\n ))}\n </defs>\n {!minimal && <CartesianGrid stroke=\"var(--color-line)\" vertical={false} />}\n <XAxis dataKey={x} {...axisProps} hide={minimal} />\n {!minimal && <YAxis {...axisProps} width={48} tickFormatter={format} />}\n <Tooltip cursor={{ stroke: \"var(--color-line-2)\" }} content={<ChartTooltip format={format} />} />\n {series.map((s, i) => {\n const color = s.color ?? CHART_SERIES[i % CHART_SERIES.length];\n if (kind === \"bar\") return <Bar key={s.key} dataKey={s.key} name={s.label} fill={color} radius={[4, 4, 0, 0]} />;\n if (kind === \"line\") return <Line key={s.key} type=\"monotone\" dataKey={s.key} name={s.label} stroke={color} strokeWidth={2} dot={false} />;\n return <Area key={s.key} type=\"monotone\" dataKey={s.key} name={s.label} stroke={color} strokeWidth={2} fill={`url(#${id}-${s.key})`} />;\n })}\n </Root>\n </ResponsiveContainer>\n </div>\n );\n}\n\nexport interface SparklineProps {\n data: readonly number[];\n color?: string;\n height?: number;\n className?: string;\n}\n\n/** A trend with no axes, sized to sit inside a StatTile. */\nexport function Sparkline({ data, color = \"var(--color-accent)\", height = 32, className }: SparklineProps) {\n const rows = data.map((value, index) => ({ index, value }));\n return (\n <div className={cn(\"w-full\", className)} style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <LineChart data={rows} margin={{ top: 2, right: 0, bottom: 2, left: 0 }}>\n <Line type=\"monotone\" dataKey=\"value\" stroke={color} strokeWidth={1.5} dot={false} isAnimationActive={false} />\n </LineChart>\n </ResponsiveContainer>\n </div>\n );\n}\n\nexport { Cell as ChartCell };\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { useFieldContext } from \"./Field\";\n\nexport interface CheckboxProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\"> {\n checked: boolean;\n onChange: (checked: boolean) => void;\n /** Partially selected (a parent of a mixed list). */\n indeterminate?: boolean;\n /** Inline label. For label + hint layouts wrap in <Field inline>. */\n label?: ReactNode;\n size?: \"sm\" | \"md\";\n}\n\nconst sizeClass = { sm: \"h-4 w-4 rounded-[5px]\", md: \"h-5 w-5 rounded-md\" };\n\nexport const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(function Checkbox(\n { checked, onChange, indeterminate, label, size = \"md\", disabled, className, id, ...rest },\n ref,\n) {\n const field = useFieldContext();\n const on = checked || indeterminate;\n const box = (\n <button\n ref={ref}\n type=\"button\"\n role=\"checkbox\"\n id={id ?? field?.id}\n aria-checked={indeterminate ? \"mixed\" : checked}\n aria-describedby={field?.describedBy}\n disabled={disabled}\n onClick={() => onChange(!checked)}\n className={cn(\n \"inline-flex shrink-0 items-center justify-center border transition-colors motion-instant\",\n sizeClass[size],\n on ? \"border-accent bg-accent text-on-accent\" : \"border-line-3 bg-fill hover:border-fg-3\",\n disabled && !label && \"cursor-not-allowed opacity-40\",\n disabled && \"cursor-not-allowed\",\n className,\n )}\n {...rest}\n >\n <svg viewBox=\"0 0 16 16\" className={size === \"sm\" ? \"h-3 w-3\" : \"h-3.5 w-3.5\"} fill=\"none\" stroke=\"currentColor\" strokeWidth={2.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n {indeterminate ? (\n <motion.path d=\"M4 8h8\" initial={false} animate={{ pathLength: on ? 1 : 0, opacity: on ? 1 : 0 }} transition={m.quick} />\n ) : (\n <motion.path d=\"M3.5 8.5l3 3 6-6.5\" initial={false} animate={{ pathLength: checked ? 1 : 0, opacity: checked ? 1 : 0 }} transition={{ ...m.quick, ease: \"easeOut\" }} />\n )}\n </svg>\n </button>\n );\n if (!label) return box;\n return (\n <label className={cn(\"inline-flex cursor-pointer items-center gap-2.5 text-base text-fg\", disabled && \"cursor-not-allowed opacity-40\")}>\n {box}\n <span>{label}</span>\n </label>\n );\n});\n","import type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface ChipProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onSelect\"> {\n /** Filter chip: toggles. Without `selected` it's a plain tag. */\n selected?: boolean;\n /** Removable tag: renders an × and calls this. */\n onRemove?: () => void;\n icon?: ReactNode;\n children: ReactNode;\n}\n\n/** Tags and filters. Badge is read-only; Chip is something you tap. */\nexport function Chip({ selected, onRemove, icon, className, children, ...rest }: ChipProps) {\n const base = cn(\n \"inline-flex h-8 items-center gap-1.5 rounded-full border px-3 text-sm font-medium transition-colors motion-instant\",\n selected ? \"border-accent/40 bg-accent/15 text-accent\" : \"border-line-2 bg-fill text-fg-2 hover:border-line-3 hover:bg-fill-2 hover:text-fg\",\n className,\n );\n if (onRemove) {\n return (\n <span className={cn(base, \"pr-1\")}>\n {icon}\n {children}\n <button type=\"button\" onClick={onRemove} aria-label=\"Remove\" className=\"tap-target ml-0.5 flex h-5 w-5 items-center justify-center rounded-full hover:bg-fill-3\">\n <X size={12} />\n </button>\n </span>\n );\n }\n return (\n <button type=\"button\" aria-pressed={selected} className={base} {...rest}>\n {icon}\n {children}\n </button>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { Check, Copy } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { Button, type ButtonProps } from \"./Button\";\nimport { IconButton } from \"./IconButton\";\n\nexport interface CopyButtonProps extends Omit<ButtonProps, \"children\" | \"onClick\"> {\n value: string;\n /** Omit for an icon-only button. */\n children?: React.ReactNode;\n label?: string;\n copiedLabel?: string;\n}\n\n/**\n * Copy with a confirmation that lives on the button itself, so the action doesn't need\n * a toast. The app writes this by hand wherever it copies a prompt, an error or an id.\n */\nexport function CopyButton({ value, children, label = \"Copy\", copiedLabel = \"Copied\", className, ...rest }: CopyButtonProps) {\n const [copied, setCopied] = useState(false);\n const timer = useRef<number | null>(null);\n\n useEffect(() => () => { if (timer.current) window.clearTimeout(timer.current); }, []);\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n } catch {\n /* Clipboard can be blocked; the state below still tells the user nothing happened. */\n return;\n }\n setCopied(true);\n if (timer.current) window.clearTimeout(timer.current);\n timer.current = window.setTimeout(() => setCopied(false), 1600);\n };\n\n if (!children) {\n return (\n <IconButton label={copied ? copiedLabel : label} onClick={copy} className={className}>\n {copied ? <Check size={16} className=\"text-accent\" /> : <Copy size={16} />}\n </IconButton>\n );\n }\n\n return (\n <Button\n onClick={copy}\n leading={copied ? <Check size={16} className=\"text-accent\" /> : <Copy size={16} />}\n className={cn(className)}\n {...rest}\n >\n {copied ? copiedLabel : children}\n </Button>\n );\n}\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface ScrollAreaProps {\n /** Which way it scrolls. */\n axis?: \"y\" | \"x\";\n /** Fade the edge that has more content behind it. */\n fade?: boolean;\n /** Show a thin scrollbar instead of hiding it. */\n bar?: boolean;\n className?: string;\n children: ReactNode;\n}\n\nconst FADE = 28;\n\n/**\n * A scroll container that says when there is more. The fade is a mask on the content,\n * not a gradient overlay — an overlay would have to know the parent's background colour,\n * and over a photo or a gradient it never does.\n */\nexport function ScrollArea({ axis = \"y\", fade = true, bar = false, className, children }: ScrollAreaProps) {\n const ref = useRef<HTMLDivElement>(null);\n const [edges, setEdges] = useState({ start: false, end: false });\n\n useEffect(() => {\n const el = ref.current;\n if (!el || !fade) return;\n const measure = () => {\n const pos = axis === \"y\" ? el.scrollTop : el.scrollLeft;\n const max = axis === \"y\" ? el.scrollHeight - el.clientHeight : el.scrollWidth - el.clientWidth;\n setEdges({ start: pos > 4, end: max > 4 && pos < max - 4 });\n };\n measure();\n el.addEventListener(\"scroll\", measure, { passive: true });\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n Array.from(el.children).forEach((child) => observer.observe(child));\n return () => {\n el.removeEventListener(\"scroll\", measure);\n observer.disconnect();\n };\n }, [axis, fade]);\n\n const dir = axis === \"y\" ? \"to bottom\" : \"to right\";\n const mask =\n !fade || (!edges.start && !edges.end)\n ? undefined\n : edges.start && edges.end\n ? `linear-gradient(${dir}, transparent, black ${FADE}px, black calc(100% - ${FADE}px), transparent)`\n : edges.end\n ? `linear-gradient(${dir}, black calc(100% - ${FADE}px), transparent)`\n : `linear-gradient(${dir}, transparent, black ${FADE}px)`;\n\n return (\n <div\n ref={ref}\n className={cn(axis === \"y\" ? \"overflow-y-auto\" : \"overflow-x-auto\", bar ? \"scrollbar-thin\" : \"scrollbar-none\", className)}\n style={mask ? { maskImage: mask, WebkitMaskImage: mask } : undefined}\n >\n {children}\n </div>\n );\n}\n","import { cn } from \"../lib/cn\";\nimport { CopyButton } from \"./CopyButton\";\nimport { ScrollArea } from \"./ScrollArea\";\n\nexport interface CodeBlockProps {\n code: string;\n /** Shown in the header — a filename, a language, \"Response\". */\n label?: string;\n /** Wrap long lines instead of scrolling. Good for prompts, bad for JSON. */\n wrap?: boolean;\n /** Adds a gutter of line numbers. */\n lineNumbers?: boolean;\n maxHeight?: number | string;\n className?: string;\n}\n\n/**\n * Monospace content with a copy button: prompt templates, raw payloads, error bodies.\n * Long lines scroll inside the block, so the page never scrolls sideways because of it.\n */\nexport function CodeBlock({ code, label, wrap, lineNumbers, maxHeight = 320, className }: CodeBlockProps) {\n const lines = code.split(\"\\n\");\n return (\n <div className={cn(\"overflow-hidden rounded-xl border border-line bg-surface-1\", className)}>\n {/* Always drawn: the copy button lives here even when there is no label. */}\n {(\n <div className=\"flex items-center gap-2 border-b border-line bg-surface-1 px-3 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate font-mono text-2xs text-fg-3\">{label}</span>\n <CopyButton value={code} />\n </div>\n )}\n <ScrollArea axis={wrap ? \"y\" : \"x\"} bar className=\"max-w-full\" >\n <pre\n className={cn(\"px-3 py-2.5 font-mono text-xs leading-relaxed text-fg-2\", wrap && \"whitespace-pre-wrap break-words\")}\n style={{ maxHeight }}\n >\n {lineNumbers ? (\n <code className=\"grid grid-cols-[auto_1fr] gap-x-3\">\n {lines.map((line, i) => (\n <span key={i} className=\"contents\">\n <span className=\"select-none text-right tabular-nums text-fg-3\">{i + 1}</span>\n <span>{line || \" \"}</span>\n </span>\n ))}\n </code>\n ) : (\n <code>{code}</code>\n )}\n </pre>\n </ScrollArea>\n </div>\n );\n}\n","import { useId, useState, type ReactNode } from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\nexport interface CollapsibleProps {\n title: ReactNode;\n description?: ReactNode;\n defaultOpen?: boolean;\n /** Controlled mode. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Right of the title — a count, a badge, a switch. */\n trailing?: ReactNode;\n /** `panel` draws a bordered container; `plain` is just the toggle and its content. */\n variant?: \"panel\" | \"plain\";\n className?: string;\n children: ReactNode;\n}\n\n/**\n * A single disclosure. Accordion is for a set that share open/closed state; this is\n * one section that stands alone — advanced settings, a long definition, a raw payload.\n */\nexport function Collapsible({\n title, description, defaultOpen = false, open: openProp, onOpenChange,\n trailing, variant = \"panel\", className, children,\n}: CollapsibleProps) {\n const id = useId();\n const [uncontrolled, setUncontrolled] = useState(defaultOpen);\n const open = openProp ?? uncontrolled;\n const setOpen = (next: boolean) => {\n if (openProp === undefined) setUncontrolled(next);\n onOpenChange?.(next);\n };\n\n return (\n <div className={cn(variant === \"panel\" && \"overflow-hidden rounded-xl border border-line bg-surface-1\", className)}>\n {/* The gutter is for the trailing slot. Reserved when there is nothing in it, the\n toggle's hover fill stops short of the edge and leaves a strip down the side. */}\n <div className={cn(\"flex items-center\", trailing && \"gap-2\", trailing && variant === \"panel\" && \"pr-3\")}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={`${id}-panel`}\n id={`${id}-button`}\n onClick={() => setOpen(!open)}\n className={cn(\n \"touch-target flex min-w-0 flex-1 items-center gap-2.5 text-left transition-colors\",\n variant === \"panel\" ? \"px-4 py-3 hover:bg-fill-2\" : \"-mx-1 rounded-lg px-1 py-1.5 hover:bg-fill\",\n )}\n >\n <ChevronDown size={16} className={cn(\"shrink-0 text-fg-3 transition-transform motion-quick\", open && \"rotate-180\")} />\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"block truncate font-medium\", variant === \"panel\" ? \"text-base text-fg\" : \"text-sm text-fg-2\")}>\n {title}\n </span>\n {description && <span className=\"block truncate text-sm text-fg-3\">{description}</span>}\n </span>\n </button>\n {trailing && <div className=\"shrink-0\">{trailing}</div>}\n </div>\n <AnimatePresence initial={false}>\n {open && (\n <motion.div\n id={`${id}-panel`}\n role=\"region\"\n aria-labelledby={`${id}-button`}\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={m.collapse}\n className=\"overflow-hidden\"\n >\n <div className={cn(variant === \"panel\" ? \"border-t border-line px-4 py-3\" : \"pt-2 pl-6\")}>{children}</div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n","import {\n cloneElement, createContext, useCallback, useContext, useEffect, useId, useLayoutEffect,\n useRef, useState, type ReactElement, type ReactNode,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\nexport type PopoverSide = \"top\" | \"bottom\" | \"left\" | \"right\";\nexport type PopoverAlign = \"start\" | \"center\" | \"end\";\n\ninterface PopoverContextValue {\n open: boolean;\n setOpen: (open: boolean) => void;\n id: string;\n anchorRef: React.MutableRefObject<HTMLElement | null>;\n}\n\nconst PopoverContext = createContext<PopoverContextValue | null>(null);\n\nfunction usePopover() {\n const ctx = useContext(PopoverContext);\n if (!ctx) throw new Error(\"Popover parts must be used inside <Popover>\");\n return ctx;\n}\n\nexport interface PopoverProps {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n children: ReactNode;\n}\n\n/**\n * An anchored floating panel, portalled to the body so it is never clipped by an\n * ancestor's overflow — which is why the app's own pickers live inside their scroll\n * containers and get cut off. Combobox, DatePicker, ColorPicker and HoverCard build on it.\n */\nexport function Popover({ open: openProp, onOpenChange, children }: PopoverProps) {\n const [uncontrolled, setUncontrolled] = useState(false);\n const open = openProp ?? uncontrolled;\n const anchorRef = useRef<HTMLElement | null>(null);\n const id = useId();\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (openProp === undefined) setUncontrolled(next);\n onOpenChange?.(next);\n },\n [openProp, onOpenChange],\n );\n\n return <PopoverContext.Provider value={{ open, setOpen, id, anchorRef }}>{children}</PopoverContext.Provider>;\n}\n\nexport function PopoverTrigger({ children }: { children: ReactElement<Record<string, unknown>> }) {\n const { open, setOpen, id, anchorRef } = usePopover();\n const child = children.props as { onClick?: (e: unknown) => void };\n return cloneElement(children, {\n ref: anchorRef,\n \"aria-haspopup\": \"dialog\",\n \"aria-expanded\": open,\n \"aria-controls\": open ? id : undefined,\n onClick: (event: unknown) => {\n child.onClick?.(event);\n setOpen(!open);\n },\n });\n}\n\n/**\n * The element the panel points at, when opening it is not that element's job — a\n * hover card, or anything that opens on its own. Same anchoring, no click handler.\n */\nexport function PopoverAnchor({ children }: { children: ReactElement<Record<string, unknown>> }) {\n const { anchorRef } = usePopover();\n return cloneElement(children, { ref: anchorRef });\n}\n\n/** Anchors to the trigger and flips to the other side when it would leave the viewport. */\nexport function usePopoverPosition(\n anchorRef: React.MutableRefObject<HTMLElement | null>,\n panelRef: React.RefObject<HTMLElement | null>,\n { open, side, align, offset }: { open: boolean; side: PopoverSide; align: PopoverAlign; offset: number },\n) {\n const [style, setStyle] = useState<{ top: number; left: number; minWidth?: number }>({ top: 0, left: 0 });\n\n useLayoutEffect(() => {\n if (!open) return;\n const place = () => {\n const anchor = anchorRef.current?.getBoundingClientRect();\n const panel = panelRef.current?.getBoundingClientRect();\n if (!anchor || !panel) return;\n const margin = 8;\n let resolved = side;\n\n if (side === \"bottom\" && anchor.bottom + offset + panel.height > window.innerHeight - margin) resolved = \"top\";\n if (side === \"top\" && anchor.top - offset - panel.height < margin) resolved = \"bottom\";\n\n let top = 0;\n let left = 0;\n if (resolved === \"bottom\" || resolved === \"top\") {\n top = resolved === \"bottom\" ? anchor.bottom + offset : anchor.top - offset - panel.height;\n left = align === \"start\" ? anchor.left : align === \"end\" ? anchor.right - panel.width : anchor.left + anchor.width / 2 - panel.width / 2;\n } else {\n left = resolved === \"right\" ? anchor.right + offset : anchor.left - offset - panel.width;\n top = align === \"start\" ? anchor.top : align === \"end\" ? anchor.bottom - panel.height : anchor.top + anchor.height / 2 - panel.height / 2;\n }\n\n setStyle({\n top: Math.max(margin, Math.min(top, window.innerHeight - panel.height - margin)),\n left: Math.max(margin, Math.min(left, window.innerWidth - panel.width - margin)),\n minWidth: anchor.width,\n });\n };\n place();\n window.addEventListener(\"scroll\", place, true);\n window.addEventListener(\"resize\", place);\n return () => {\n window.removeEventListener(\"scroll\", place, true);\n window.removeEventListener(\"resize\", place);\n };\n }, [open, side, align, offset, anchorRef, panelRef]);\n\n return style;\n}\n\nexport interface PopoverContentProps {\n side?: PopoverSide;\n align?: PopoverAlign;\n offset?: number;\n /** Stretch to the trigger's width — what a select-style dropdown wants. */\n matchWidth?: boolean;\n className?: string;\n children: ReactNode;\n}\n\nexport function PopoverContent({ side = \"bottom\", align = \"start\", offset = 6, matchWidth, className, children }: PopoverContentProps) {\n const { open, setOpen, id, anchorRef } = usePopover();\n const panelRef = useRef<HTMLDivElement>(null);\n const position = usePopoverPosition(anchorRef, panelRef, { open, side, align, offset });\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (event: PointerEvent) => {\n const target = event.target as Node;\n if (panelRef.current?.contains(target) || anchorRef.current?.contains(target)) return;\n setOpen(false);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setOpen(false);\n anchorRef.current?.focus();\n }\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open, setOpen, anchorRef]);\n\n return createPortal(\n <AnimatePresence>\n {open && (\n <motion.div\n ref={panelRef}\n id={id}\n role=\"dialog\"\n initial={{ opacity: 0, scale: 0.97 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.97 }}\n transition={m.instant}\n style={{ top: position.top, left: position.left, ...(matchWidth ? { minWidth: position.minWidth } : undefined) }}\n className={cn(\"fixed z-[70] rounded-xl border border-line bg-surface-2 p-1 shadow-raised\", className)}\n >\n {children}\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n );\n}\n","import { useState } from \"react\";\nimport { Check, Pipette } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./Popover\";\n\nexport interface ColorPickerProps {\n value: string;\n onChange: (value: string) => void;\n /** Quick picks shown above the free-form field. */\n swatches?: readonly string[];\n disabled?: boolean;\n id?: string;\n className?: string;\n}\n\nconst DEFAULT_SWATCHES = [\n \"#65c789\", \"#22d3ee\", \"#3b82f6\", \"#a78bfa\", \"#f472b6\",\n \"#ef4444\", \"#f59e0b\", \"#84cc16\", \"#e5e7eb\", \"#71717a\",\n] as const;\n\nfunction normalise(input: string) {\n const v = input.trim().replace(/^#?/, \"\");\n if (/^[0-9a-f]{3}$/i.test(v)) return `#${v[0]}${v[0]}${v[1]}${v[1]}${v[2]}${v[2]}`.toLowerCase();\n if (/^[0-9a-f]{6}$/i.test(v)) return `#${v.toLowerCase()}`;\n return null;\n}\n\n/**\n * A colour swatch that opens a picker. The custom-colour settings page rolls its own\n * inputs; this pairs the native colour input (so the OS picker is available) with a hex\n * field and a preset row, which is how people actually choose.\n */\nexport function ColorPicker({ value, onChange, swatches = DEFAULT_SWATCHES, disabled, id, className }: ColorPickerProps) {\n const field = useFieldContext();\n const [draft, setDraft] = useState(value);\n const [open, setOpen] = useState(false);\n\n const commit = (raw: string) => {\n const hex = normalise(raw);\n if (hex) onChange(hex);\n else setDraft(value);\n };\n\n return (\n <Popover open={open} onOpenChange={(next) => { setOpen(next); if (next) setDraft(value); }}>\n <PopoverTrigger>\n <button\n type=\"button\"\n id={id ?? field?.id}\n disabled={disabled}\n aria-label={`Colour, currently ${value}`}\n className={cn(\n \"control-md flex items-center gap-2.5 rounded-xl border border-line bg-fill px-2.5 transition-colors hover:border-line-2\",\n disabled && \"pointer-events-none opacity-40\",\n className,\n )}\n >\n <span className=\"h-6 w-6 shrink-0 rounded-md ring-1 ring-inset ring-line-3\" style={{ background: value }} />\n <span className=\"font-mono text-sm uppercase text-fg-2\">{value}</span>\n </button>\n </PopoverTrigger>\n\n <PopoverContent className=\"w-60 p-3\">\n <div className=\"grid grid-cols-5 gap-2\">\n {swatches.map((swatch) => (\n <button\n key={swatch}\n type=\"button\"\n onClick={() => { onChange(swatch); setOpen(false); }}\n aria-label={swatch}\n className=\"flex h-8 w-full items-center justify-center rounded-lg ring-1 ring-inset ring-line-3 transition-transform hover:scale-105\"\n style={{ background: swatch }}\n >\n {swatch.toLowerCase() === value.toLowerCase() && (\n <Check size={14} className=\"text-black mix-blend-difference invert\" />\n )}\n </button>\n ))}\n </div>\n\n <div className=\"mt-3 flex items-center gap-2\">\n <label className=\"relative flex h-9 w-9 shrink-0 cursor-pointer items-center justify-center rounded-lg border border-line bg-fill text-fg-3 hover:text-fg\">\n <Pipette size={16} />\n <input\n type=\"color\"\n value={value}\n onChange={(event) => onChange(event.target.value)}\n aria-label=\"Pick a colour\"\n className=\"absolute inset-0 cursor-pointer opacity-0\"\n />\n </label>\n <input\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onBlur={() => commit(draft)}\n onKeyDown={(event) => { if (event.key === \"Enter\") { event.preventDefault(); commit(draft); } }}\n aria-label=\"Hex value\"\n spellCheck={false}\n className=\"h-9 min-w-0 flex-1 rounded-lg border border-line bg-fill px-2.5 font-mono text-sm uppercase text-fg outline-none focus:border-accent focus:ring-1 focus:ring-accent/35\"\n />\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { Loader2 } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface SpinnerProps {\n size?: \"sm\" | \"md\" | \"lg\";\n /** Announced to screen readers; omit only when a sibling already says what's loading. */\n label?: string;\n className?: string;\n}\n\nconst sizeMap = { sm: 14, md: 18, lg: 24 };\n\n/** The one spinner. `animate-spin` appears 302 times in the app; this replaces all of them. */\nexport function Spinner({ size = \"md\", label, className }: SpinnerProps) {\n return (\n <Loader2\n size={sizeMap[size]}\n role={label ? \"status\" : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n className={cn(\"animate-spin text-fg-3\", className)}\n />\n );\n}\n\n/** Centred spinner with a line of copy, for a panel that has nothing to show yet. */\nexport function LoadingState({ label = \"Loading…\", className }: { label?: string; className?: string }) {\n return (\n <div className={cn(\"flex flex-col items-center justify-center gap-3 px-6 py-12\", className)} role=\"status\">\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-fg-3\">{label}</p>\n </div>\n );\n}\n","import { useEffect, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from \"react\";\nimport { Check, ChevronDown, Search, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { inputSurface } from \"./Input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./Popover\";\nimport { Spinner } from \"./Spinner\";\n\nexport interface ComboboxOption<T extends string = string> {\n value: T;\n label: string;\n description?: string;\n icon?: ReactNode;\n group?: string;\n disabled?: boolean;\n}\n\nexport interface ComboboxProps<T extends string> {\n options: readonly ComboboxOption<T>[];\n value: T | null;\n onChange: (value: T | null) => void;\n placeholder?: string;\n searchPlaceholder?: string;\n /** Take over filtering — for a remote list like the HuggingFace catalogue. */\n onSearch?: (query: string) => void;\n loading?: boolean;\n emptyMessage?: string;\n clearable?: boolean;\n disabled?: boolean;\n id?: string;\n className?: string;\n}\n\n/**\n * A select you can type into. The app has four hand-rolled versions of this\n * (PersonaSelector, ReferenceSelector, CharacterSelectorSingle, LoraSelector) and a\n * 5,000-line HuggingFace browser that a native select can't serve.\n */\nexport function Combobox<T extends string>({\n options, value, onChange, placeholder = \"Select…\", searchPlaceholder = \"Search…\",\n onSearch, loading, emptyMessage = \"No matches\", clearable, disabled, id, className,\n}: ComboboxProps<T>) {\n const field = useFieldContext();\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n const [active, setActive] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n const filtered = useMemo(() => {\n if (onSearch || !query.trim()) return options;\n const q = query.toLowerCase();\n return options.filter((o) => o.label.toLowerCase().includes(q) || o.description?.toLowerCase().includes(q));\n }, [options, query, onSearch]);\n\n const grouped = useMemo(() => {\n const map = new Map<string, ComboboxOption<T>[]>();\n for (const option of filtered) {\n const key = option.group ?? \"\";\n const list = map.get(key);\n if (list) list.push(option);\n else map.set(key, [option]);\n }\n return Array.from(map.entries());\n }, [filtered]);\n\n const flat = useMemo(() => grouped.flatMap(([, list]) => list), [grouped]);\n const selected = options.find((o) => o.value === value) ?? null;\n\n useEffect(() => {\n if (open) {\n setQuery(\"\");\n setActive(Math.max(0, flat.findIndex((o) => o.value === value)));\n requestAnimationFrame(() => inputRef.current?.focus());\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n useEffect(() => {\n listRef.current?.querySelector('[data-active=\"true\"]')?.scrollIntoView({ block: \"nearest\" });\n }, [active]);\n\n const commit = (option: ComboboxOption<T>) => {\n if (option.disabled) return;\n onChange(option.value);\n setOpen(false);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n const delta = event.key === \"ArrowDown\" ? 1 : -1;\n setActive((i) => {\n let next = i;\n for (let step = 0; step < flat.length; step++) {\n next = (next + delta + flat.length) % flat.length;\n if (!flat[next]?.disabled) break;\n }\n return next;\n });\n }\n if (event.key === \"Enter\" && flat[active]) {\n event.preventDefault();\n commit(flat[active]);\n }\n if (event.key === \"Home\") { event.preventDefault(); setActive(0); }\n if (event.key === \"End\") { event.preventDefault(); setActive(flat.length - 1); }\n };\n\n let index = -1;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger>\n <button\n type=\"button\"\n id={id ?? field?.id}\n role=\"combobox\"\n aria-expanded={open}\n aria-describedby={field?.describedBy}\n aria-invalid={field?.invalid || undefined}\n disabled={disabled}\n className={cn(inputSurface, \"control-md flex items-center gap-2 pl-3.5 pr-2 text-left\", className)}\n >\n {selected?.icon && <span className=\"shrink-0 text-fg-3\">{selected.icon}</span>}\n <span className={cn(\"min-w-0 flex-1 truncate\", selected ? \"text-fg\" : \"text-fg-4\")}>\n {selected?.label ?? placeholder}\n </span>\n {clearable && selected && (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label=\"Clear\"\n onClick={(event) => { event.stopPropagation(); onChange(null); }}\n className=\"tap-target flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-fg-3 hover:bg-fill-2 hover:text-fg\"\n >\n <X size={14} />\n </span>\n )}\n <ChevronDown size={16} className=\"shrink-0 text-fg-3\" />\n </button>\n </PopoverTrigger>\n\n <PopoverContent matchWidth className=\"p-0\">\n <div className=\"flex items-center gap-2 border-b border-line px-3 py-2\">\n <Search size={16} className=\"shrink-0 text-fg-3\" />\n <input\n ref={inputRef}\n value={query}\n onChange={(event) => { setQuery(event.target.value); setActive(0); onSearch?.(event.target.value); }}\n onKeyDown={onKeyDown}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n className=\"min-w-0 flex-1 bg-transparent text-base text-fg outline-none placeholder:text-fg-4\"\n />\n {loading && <Spinner size=\"sm\" />}\n </div>\n\n <div ref={listRef} role=\"listbox\" className=\"scrollbar-thin max-h-64 overflow-y-auto p-1\">\n {flat.length === 0 && <p className=\"px-2.5 py-6 text-center text-sm text-fg-3\">{emptyMessage}</p>}\n {grouped.map(([group, list]) => (\n <div key={group || \"_\"}>\n {group && <p className=\"px-2.5 pb-1 pt-2 text-2xs font-medium text-fg-3\">{group}</p>}\n {list.map((option) => {\n index += 1;\n const isActive = index === active;\n const isSelected = option.value === value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n data-active={isActive}\n disabled={option.disabled}\n onPointerEnter={() => setActive(flat.indexOf(option))}\n onClick={() => commit(option)}\n className={cn(\n \"flex w-full items-start gap-2.5 rounded-lg px-2.5 py-2 text-left\",\n isActive && \"bg-fill-2\",\n option.disabled && \"pointer-events-none opacity-40\",\n )}\n >\n {option.icon && <span className=\"mt-0.5 shrink-0 text-fg-3\">{option.icon}</span>}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-base text-fg\">{option.label}</span>\n {option.description && <span className=\"block truncate text-sm text-fg-3\">{option.description}</span>}\n </span>\n {isSelected && <Check size={16} className=\"mt-0.5 shrink-0 text-accent\" />}\n </button>\n );\n })}\n </div>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { useMemo, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface HighlightProps {\n children: string;\n /** The search term(s) to mark. Empty renders the text untouched. */\n query: string;\n /** Treat the query as separate words rather than one phrase. */\n words?: boolean;\n className?: string;\n markClassName?: string;\n}\n\nfunction escape(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Marks the matching part of a search result. Uses `<mark>`, so a screen reader\n * announces the match rather than it being colour-only — which is what a span would be.\n */\nexport function Highlight({ children, query, words, className, markClassName }: HighlightProps) {\n const parts = useMemo<ReactNode[]>(() => {\n const trimmed = query.trim();\n if (!trimmed) return [children];\n\n const terms = words ? trimmed.split(/\\s+/).filter(Boolean) : [trimmed];\n const pattern = new RegExp(`(${terms.map(escape).join(\"|\")})`, \"gi\");\n return children.split(pattern).map((piece, index) =>\n index % 2 === 1 ? (\n <mark key={index} className={cn(\"rounded-[3px] bg-accent/25 px-0.5 text-fg\", markClassName)}>\n {piece}\n </mark>\n ) : (\n piece\n ),\n );\n }, [children, query, words, markClassName]);\n\n return <span className={className}>{parts}</span>;\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport function Kbd({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <kbd className={cn(\"inline-flex h-5 min-w-5 items-center justify-center rounded-md border border-line-2 bg-fill px-1.5 font-sans text-2xs font-medium text-fg-2\", className)}>\n {children}\n </kbd>\n );\n}\n","import { useEffect, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { CornerDownLeft, Search } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { Highlight } from \"./Highlight\";\nimport { Kbd } from \"./Kbd\";\nimport { Spinner } from \"./Spinner\";\n\nexport interface Command {\n id: string;\n label: string;\n /** Second line — where it goes, or what it does. */\n description?: string;\n icon?: ReactNode;\n group?: string;\n /** Extra words to match on that aren't in the label. */\n keywords?: string;\n shortcut?: string;\n onRun: () => void;\n}\n\nexport interface CommandPaletteProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n commands: readonly Command[];\n placeholder?: string;\n /** Take over filtering — for searching messages or characters remotely. */\n onQueryChange?: (query: string) => void;\n loading?: boolean;\n emptyMessage?: string;\n}\n\n/**\n * ⌘K. A desktop affordance the app has the data for already — characters, chats,\n * settings and every navigation target are all searchable, just not from one place.\n * It never replaces a visible control; it's a shortcut to ones that exist.\n */\nexport function CommandPalette({\n open, onOpenChange, commands, placeholder = \"Search or jump to…\", onQueryChange, loading, emptyMessage = \"No matches\",\n}: CommandPaletteProps) {\n const [query, setQuery] = useState(\"\");\n const [active, setActive] = useState(0);\n const listRef = useRef<HTMLDivElement>(null);\n const restore = useRef<HTMLElement | null>(null);\n\n const filtered = useMemo(() => {\n if (onQueryChange || !query.trim()) return commands;\n const q = query.toLowerCase();\n return commands.filter((c) =>\n c.label.toLowerCase().includes(q) ||\n c.description?.toLowerCase().includes(q) ||\n c.keywords?.toLowerCase().includes(q),\n );\n }, [commands, query, onQueryChange]);\n\n const grouped = useMemo(() => {\n const map = new Map<string, Command[]>();\n for (const command of filtered) {\n const key = command.group ?? \"\";\n const bucket = map.get(key);\n if (bucket) bucket.push(command);\n else map.set(key, [command]);\n }\n return Array.from(map.entries());\n }, [filtered]);\n\n useEffect(() => {\n if (!open) return;\n restore.current = document.activeElement as HTMLElement | null;\n setQuery(\"\");\n setActive(0);\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = overflow;\n restore.current?.focus?.();\n };\n }, [open]);\n\n useEffect(() => { setActive(0); }, [query]);\n useEffect(() => {\n if (open) listRef.current?.querySelector('[data-active=\"true\"]')?.scrollIntoView({ block: \"nearest\" });\n }, [open, active]);\n\n const run = (command: Command) => {\n onOpenChange(false);\n command.onRun();\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") { event.preventDefault(); onOpenChange(false); }\n if (event.key === \"ArrowDown\") { event.preventDefault(); setActive((i) => (i + 1) % Math.max(1, filtered.length)); }\n if (event.key === \"ArrowUp\") { event.preventDefault(); setActive((i) => (i - 1 + filtered.length) % Math.max(1, filtered.length)); }\n if (event.key === \"Enter\" && filtered[active]) { event.preventDefault(); run(filtered[active]); }\n };\n\n let index = -1;\n\n return createPortal(\n <AnimatePresence>\n {open && (\n <div className=\"fixed inset-0 z-[95] flex items-start justify-center p-4 pt-[12vh]\">\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={m.quick}\n onClick={() => onOpenChange(false)}\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n />\n <motion.div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Command palette\"\n initial={{ opacity: 0, scale: 0.98, y: -8 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.98, y: -8 }}\n transition={m.settle}\n onKeyDown={onKeyDown}\n className=\"relative flex max-h-[60vh] w-full max-w-xl flex-col overflow-hidden rounded-2xl border border-line bg-surface-2 shadow-raised\"\n >\n <div className=\"flex shrink-0 items-center gap-2.5 border-b border-line px-4 py-3\">\n <Search size={18} className=\"shrink-0 text-fg-3\" />\n <input\n autoFocus\n value={query}\n onChange={(event) => { setQuery(event.target.value); onQueryChange?.(event.target.value); }}\n placeholder={placeholder}\n aria-label={placeholder}\n className=\"min-w-0 flex-1 bg-transparent text-lg text-fg outline-none placeholder:text-fg-4\"\n />\n {loading && <Spinner size=\"sm\" />}\n <Kbd>Esc</Kbd>\n </div>\n\n <div ref={listRef} role=\"listbox\" className=\"scrollbar-thin min-h-0 flex-1 overflow-y-auto p-1.5\">\n {filtered.length === 0 && <p className=\"px-3 py-10 text-center text-sm text-fg-3\">{emptyMessage}</p>}\n {grouped.map(([group, list]) => (\n <div key={group || \"_\"}>\n {group && <p className=\"px-2.5 pb-1 pt-2 text-2xs font-medium text-fg-3\">{group}</p>}\n {list.map((command) => {\n index += 1;\n const isActive = index === active;\n return (\n <div\n key={command.id}\n role=\"option\"\n aria-selected={isActive}\n data-active={isActive}\n onPointerEnter={() => setActive(filtered.indexOf(command))}\n onClick={() => run(command)}\n className={cn(\n \"flex cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2\",\n isActive && \"bg-fill-2\",\n )}\n >\n {command.icon && <span className=\"shrink-0 text-fg-3\">{command.icon}</span>}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-base text-fg\">\n <Highlight query={query}>{command.label}</Highlight>\n </span>\n {command.description && (\n <span className=\"block truncate text-sm text-fg-3\">{command.description}</span>\n )}\n </span>\n {command.shortcut && <Kbd>{command.shortcut}</Kbd>}\n {isActive && <CornerDownLeft size={14} className=\"shrink-0 text-fg-4\" />}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n </motion.div>\n </div>\n )}\n </AnimatePresence>,\n document.body,\n );\n}\n\n/** Binds ⌘K / Ctrl+K. Ignores the shortcut while a field is focused. */\nexport function useCommandPalette() {\n const [open, setOpen] = useState(false);\n useEffect(() => {\n const onKeyDown = (event: globalThis.KeyboardEvent) => {\n if (event.key.toLowerCase() !== \"k\" || !(event.metaKey || event.ctrlKey)) return;\n event.preventDefault();\n setOpen((v) => !v);\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, []);\n return { open, setOpen };\n}\n","import { useCallback, useRef } from \"react\";\nimport type { MouseEvent, PointerEvent } from \"react\";\n\n/**\n * Long-press (and right-click) on a button, without swallowing the normal click.\n * Returns handlers to spread on the element.\n */\nexport function useLongPress(onLongPress: (() => void) | undefined, { delay = 450, enabled = true } = {}) {\n const timer = useRef<number | null>(null);\n const fired = useRef(false);\n const origin = useRef<{ x: number; y: number } | null>(null);\n\n const clear = useCallback(() => {\n if (timer.current !== null) window.clearTimeout(timer.current);\n timer.current = null;\n }, []);\n\n const onPointerDown = useCallback(\n (event: PointerEvent<HTMLElement>) => {\n if (!enabled || !onLongPress || event.button !== 0) return;\n clear();\n fired.current = false;\n origin.current = { x: event.clientX, y: event.clientY };\n timer.current = window.setTimeout(() => {\n fired.current = true;\n onLongPress();\n }, delay);\n },\n [clear, delay, enabled, onLongPress],\n );\n\n /* A press that travels is a swipe or a selection, not a hold. Without this the menu\n fires in the middle of a gesture the person is still making. */\n const onPointerMove = useCallback(\n (event: PointerEvent<HTMLElement>) => {\n if (timer.current === null || !origin.current) return;\n const { x, y } = origin.current;\n if (Math.abs(event.clientX - x) > 10 || Math.abs(event.clientY - y) > 10) clear();\n },\n [clear],\n );\n\n const onContextMenu = useCallback(\n (event: MouseEvent<HTMLElement>) => {\n if (!enabled || !onLongPress) return;\n event.preventDefault();\n clear();\n fired.current = true;\n onLongPress();\n },\n [clear, enabled, onLongPress],\n );\n\n /** Wrap the click handler so a completed long-press does not also click. */\n const guardClick = useCallback(\n (handler: () => void) => (event: MouseEvent<HTMLElement>) => {\n clear();\n if (fired.current) {\n event.preventDefault();\n fired.current = false;\n return;\n }\n handler();\n },\n [clear],\n );\n\n return {\n handlers: { onPointerDown, onPointerMove, onPointerUp: clear, onPointerLeave: clear, onPointerCancel: clear, onContextMenu },\n guardClick,\n };\n}\n","import { useEffect, useRef, useState, type KeyboardEvent, type ReactNode } from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { ArrowUp, Check, ChevronsRight, Loader2, Mic, Plus, Square, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { useLongPress } from \"../lib/useLongPress\";\nimport { IconButton } from \"./IconButton\";\n\nexport interface ComposerAttachment {\n id: string;\n /** Image data URL, or undefined for non-image files (shown as a chip). */\n src?: string;\n name?: string;\n}\n\nexport interface ComposerMic {\n active: boolean;\n transcribing?: boolean;\n elapsedMs: number;\n analyser: AnalyserNode | null;\n onStart: () => void;\n onStop: () => void;\n onCancel: () => void;\n disabled?: boolean;\n}\n\nexport interface ComposerProps {\n value: string;\n onChange: (value: string) => void;\n onSend: () => void;\n /** Shown while `sending`; if absent the button just spins. */\n onStop?: () => void;\n /** Empty composer + tap send = let the character continue. */\n onContinue?: () => void;\n /** Long-press / right-click on send. */\n onSendAsSystem?: () => void;\n onAttach?: () => void;\n attachments?: ComposerAttachment[];\n onRemoveAttachment?: (id: string) => void;\n mic?: ComposerMic;\n sending?: boolean;\n disabled?: boolean;\n placeholder?: string;\n /** Enter sends on desktop; on touch, Enter is a newline. */\n enterSends?: boolean;\n /** Rendered above the pill — an <Alert>. */\n notice?: ReactNode;\n /** Slot inside the pill above the input — author's note, quick snippets. */\n topSlot?: ReactNode;\n className?: string;\n}\n\ntype Action = \"stop\" | \"send\" | \"busy\" | \"continue\";\n\nexport function Composer({\n value, onChange, onSend, onStop, onContinue, onSendAsSystem, onAttach, attachments = [], onRemoveAttachment,\n mic, sending = false, disabled = false, placeholder = \"Send a message…\", enterSends = true, notice, topSlot, className,\n}: ComposerProps) {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const hasDraft = value.trim().length > 0;\n const hasContent = hasDraft || attachments.length > 0;\n const recording = Boolean(mic?.active);\n\n const action: Action = sending ? (onStop ? \"stop\" : \"busy\") : hasContent ? \"send\" : \"continue\";\n const actionDisabled = disabled || action === \"busy\" || (action === \"continue\" && !onContinue);\n\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = \"auto\";\n el.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n }, [value]);\n\n const longPress = useLongPress(onSendAsSystem, { enabled: action === \"send\" && !disabled });\n\n const runAction = () => {\n if (action === \"stop\") onStop?.();\n else if (action === \"send\") onSend();\n else if (action === \"continue\") onContinue?.();\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (!enterSends || event.key !== \"Enter\" || event.shiftKey || event.nativeEvent.isComposing) return;\n event.preventDefault();\n if (!sending && !disabled && hasContent) onSend();\n };\n\n const actionStyle: Record<Action, string> = {\n stop: \"bg-danger text-fg\",\n send: \"bg-accent text-on-accent\",\n busy: \"bg-fill-3 text-fg-3\",\n continue: \"border border-accent/30 bg-accent/15 text-accent\",\n };\n const actionLabel: Record<Action, string> = {\n stop: \"Stop generating\",\n send: \"Send message\",\n busy: \"Sending\",\n continue: \"Let the character continue\",\n };\n const actionIcon: Record<Action, ReactNode> = {\n stop: <Square size={14} fill=\"currentColor\" />,\n send: <ArrowUp size={18} strokeWidth={2.5} />,\n busy: <Loader2 size={18} className=\"animate-spin\" />,\n continue: <ChevronsRight size={18} />,\n };\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n {notice}\n <div\n className={cn(\n \"rounded-[26px] border border-line bg-surface-el/85 shadow-raised backdrop-blur-md transition-colors motion-instant\",\n \"focus-within:border-accent focus-within:ring-1 focus-within:ring-accent/35\",\n disabled && \"opacity-60\",\n )}\n >\n {topSlot && <div className=\"border-b border-line px-3 py-2\">{topSlot}</div>}\n\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-2 px-3 pt-3\">\n {attachments.map((attachment) => (\n <div key={attachment.id} className=\"group relative\">\n {attachment.src ? (\n <img src={attachment.src} alt={attachment.name ?? \"Attachment\"} className=\"h-14 w-14 rounded-lg border border-line object-cover\" />\n ) : (\n <span className=\"inline-flex h-9 max-w-48 items-center truncate rounded-lg border border-line bg-fill px-3 text-sm text-fg-2\">{attachment.name ?? \"File\"}</span>\n )}\n {onRemoveAttachment && (\n <button\n type=\"button\"\n onClick={() => onRemoveAttachment(attachment.id)}\n aria-label={`Remove ${attachment.name ?? \"attachment\"}`}\n className=\"tap-target absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full bg-surface/80 text-fg backdrop-blur-sm transition-colors hover:bg-danger\"\n >\n <X size={12} strokeWidth={2.5} />\n </button>\n )}\n </div>\n ))}\n </div>\n )}\n\n <div className=\"composer-row flex items-end gap-1 p-1\">\n {onAttach && (\n <IconButton label=\"Add attachment\" shape=\"round\" size=\"md\" onClick={onAttach} disabled={disabled || sending || recording}>\n <Plus size={18} />\n </IconButton>\n )}\n\n {recording && mic ? (\n <RecordingWave elapsedMs={mic.elapsedMs} analyser={mic.analyser} frozen={mic.transcribing} />\n ) : (\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n rows={1}\n disabled={disabled || sending}\n aria-label=\"Message\"\n /* One line is exactly as tall as the buttons beside it — both read\n --composer-row — so under items-end the text and the icons share a\n centre. At 40px against 44px buttons it sat 2px low. */\n className=\"scrollbar-none min-h-[var(--composer-row)] flex-1 resize-none bg-transparent px-2 py-[calc((var(--composer-row)-1.25rem)/2)] text-base leading-5 text-fg outline-none placeholder:text-fg-3 disabled:cursor-not-allowed\"\n />\n )}\n\n {mic && (\n recording ? (\n <>\n <IconButton label=\"Cancel recording\" shape=\"round\" size=\"md\" onClick={mic.onCancel} disabled={mic.transcribing}>\n <X size={16} />\n </IconButton>\n <motion.button\n type=\"button\"\n whileTap={{ scale: 0.94 }}\n onClick={mic.onStop}\n disabled={mic.transcribing}\n aria-label={mic.transcribing ? \"Transcribing\" : \"Stop and transcribe\"}\n className=\"touch-target control-md flex w-10 shrink-0 items-center justify-center rounded-full bg-accent text-on-accent disabled:opacity-70\"\n >\n {mic.transcribing ? <Loader2 size={18} className=\"animate-spin\" /> : <Check size={18} strokeWidth={2.5} />}\n </motion.button>\n </>\n ) : (\n <IconButton label=\"Record voice\" shape=\"round\" size=\"md\" onClick={mic.onStart} disabled={disabled || sending || mic.disabled}>\n <Mic size={16} />\n </IconButton>\n )\n )}\n\n {!recording && (\n <motion.button\n type=\"button\"\n whileTap={actionDisabled ? undefined : { scale: 0.94 }}\n disabled={actionDisabled}\n aria-label={actionLabel[action]}\n title={action === \"send\" && onSendAsSystem ? \"Send · hold to send as system message\" : actionLabel[action]}\n onClick={longPress.guardClick(runAction)}\n {...longPress.handlers}\n className={cn(\n \"touch-target control-md relative flex w-10 shrink-0 items-center justify-center rounded-full transition-colors motion-instant\",\n \"disabled:cursor-not-allowed disabled:opacity-40\",\n actionStyle[action],\n )}\n >\n <AnimatePresence mode=\"wait\" initial={false}>\n <motion.span\n key={action}\n initial={{ opacity: 0, scale: 0.6 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.6 }}\n transition={m.instant}\n className=\"flex\"\n >\n {actionIcon[action]}\n </motion.span>\n </AnimatePresence>\n </motion.button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction formatElapsed(ms: number) {\n const total = Math.max(0, Math.floor(ms / 1000));\n return `${Math.floor(total / 60)}:${String(total % 60).padStart(2, \"0\")}`;\n}\n\n/** Live waveform while recording. Same sampling as the app; drawn in tokens. */\nexport function RecordingWave({ elapsedMs, analyser, frozen = false }: { elapsedMs: number; analyser: AnalyserNode | null; frozen?: boolean }) {\n const containerRef = useRef<HTMLDivElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const samplesRef = useRef<number[]>([]);\n const dataRef = useRef<Uint8Array | null>(null);\n const [size, setSize] = useState({ w: 0, h: 0 });\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const measure = () => {\n const rect = el.getBoundingClientRect();\n setSize({ w: Math.floor(rect.width), h: Math.floor(rect.height) });\n };\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n measure();\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n samplesRef.current = [];\n dataRef.current = analyser ? new Uint8Array(new ArrayBuffer(analyser.fftSize)) : null;\n }, [analyser]);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || size.w <= 0) return;\n const dpr = window.devicePixelRatio || 1;\n const height = size.h || 20;\n canvas.width = Math.floor(size.w * dpr);\n canvas.height = Math.floor(height * dpr);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n ctx.scale(dpr, dpr);\n const color = getComputedStyle(canvas).color;\n const BAR = 2, GAP = 2, STEP = BAR + GAP, INTERVAL = 50;\n const maxBars = Math.ceil(size.w / STEP) + 4;\n let lastPush = 0;\n let frame = 0;\n\n const draw = (now: number) => {\n if (!frozen && analyser && dataRef.current && now - lastPush >= INTERVAL) {\n analyser.getByteTimeDomainData(dataRef.current as Uint8Array<ArrayBuffer>);\n let sumSq = 0;\n for (const byte of dataRef.current) { const v = (byte - 128) / 128; sumSq += v * v; }\n const rms = Math.sqrt(sumSq / dataRef.current.length);\n samplesRef.current.push(Math.min(1, Math.pow(rms * 18, 0.5)));\n if (samplesRef.current.length > maxBars) samplesRef.current.splice(0, samplesRef.current.length - maxBars);\n lastPush = now;\n }\n ctx.clearRect(0, 0, size.w, height);\n const samples = samplesRef.current;\n for (let i = Math.max(0, samples.length - maxBars); i < samples.length; i++) {\n const age = samples.length - 1 - i;\n const x = size.w - BAR - age * STEP;\n if (x + BAR < 0) break;\n const h = Math.max(3, samples[i] * (height - 2));\n ctx.globalAlpha = 0.95 - (age / Math.max(1, maxBars - 1)) * 0.35;\n ctx.fillStyle = color;\n ctx.fillRect(x, height / 2 - h / 2, BAR, h);\n }\n frame = window.requestAnimationFrame(draw);\n };\n frame = window.requestAnimationFrame(draw);\n return () => window.cancelAnimationFrame(frame);\n }, [analyser, size.w, size.h, frozen]);\n\n return (\n <div className=\"flex min-h-[var(--composer-row)] min-w-0 flex-1 items-center gap-2.5 px-2\" role=\"status\" aria-live=\"polite\" aria-label={frozen ? \"Transcribing\" : `Recording, ${formatElapsed(elapsedMs)}`}>\n <span className=\"relative flex h-2 w-2 shrink-0\" aria-hidden=\"true\">\n {!frozen && <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-danger opacity-60\" />}\n <span className={cn(\"relative inline-flex h-2 w-2 rounded-full\", frozen ? \"bg-fg-3\" : \"bg-danger\")} />\n </span>\n <div\n ref={containerRef}\n className=\"relative h-5 min-w-0 flex-1 overflow-hidden text-fg\"\n style={{\n maskImage: \"linear-gradient(to right, transparent, black 40px)\",\n WebkitMaskImage: \"linear-gradient(to right, transparent, black 40px)\",\n }}\n >\n <span aria-hidden=\"true\" className=\"absolute inset-x-0 top-1/2 h-px -translate-y-1/2 bg-line-2\" />\n <canvas ref={canvasRef} className=\"relative block h-full w-full\" style={{ width: size.w || undefined }} />\n </div>\n <span className=\"shrink-0 text-xs tabular-nums text-fg-2\">{formatElapsed(elapsedMs)}</span>\n </div>\n );\n}\n","import { useEffect, type RefObject } from \"react\";\n\nconst FOCUSABLE = 'input, textarea, select, [data-autofocus], a[href], button:not([data-modal-chrome])';\n\n/**\n * Shared modal behaviour for Sheet and Dialog: Escape closes, body scroll locks,\n * focus moves inside on open and returns to the opener on close.\n */\nexport function useModal(\n open: boolean,\n onClose: () => void,\n panelRef: RefObject<HTMLElement | null>,\n { lockScroll = true }: { lockScroll?: boolean } = {},\n) {\n useEffect(() => {\n if (!open) return;\n const opener = document.activeElement as HTMLElement | null;\n const previousOverflow = document.body.style.overflow;\n if (lockScroll) document.body.style.overflow = \"hidden\";\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n if (event.key === \"Tab\" && panelRef.current) {\n const nodes = Array.from(panelRef.current.querySelectorAll<HTMLElement>(FOCUSABLE + \", [data-modal-chrome]\")).filter(\n (node) => !node.hasAttribute(\"disabled\"),\n );\n if (nodes.length === 0) return;\n const first = nodes[0];\n const last = nodes[nodes.length - 1];\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n\n /* Focus the panel, not the first control. Landing on a control paints a focus ring\n on a row nobody chose — and a bottom menu is usually opened by a thumb, so that\n ring is pure noise. Tab still walks into the content from here. A sheet that\n genuinely wants a cursor in a field marks that field `data-autofocus`. */\n const frame = requestAnimationFrame(() => {\n const panel = panelRef.current;\n /* preventScroll: the panel starts below the edge it slides in from. Focusing it\n normally makes the browser scroll its container to reveal it — overflow:hidden\n does not stop programmatic scrolling — and the whole screen jumps up underneath\n the sheet while it animates. */\n (panel?.querySelector<HTMLElement>(\"[data-autofocus]\") ?? panel)?.focus({ preventScroll: true });\n });\n\n return () => {\n cancelAnimationFrame(frame);\n document.removeEventListener(\"keydown\", onKeyDown);\n if (lockScroll) document.body.style.overflow = previousOverflow;\n opener?.focus?.({ preventScroll: true });\n };\n }, [open, onClose, panelRef, lockScroll]);\n}\n","import { useEffect, useId, useLayoutEffect, useRef, useState, type PointerEvent as ReactPointerEvent, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n animate, AnimatePresence, motion, useMotionValue, usePresence, useReducedMotion, useTransform,\n type AnimationPlaybackControls, type Transition,\n} from \"framer-motion\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { useModal } from \"../lib/useModal\";\nimport { useCompactLayout } from \"../lib/useMediaQuery\";\nimport { useFrame, usePortalTarget } from \"../lib/frame\";\nimport { IconButton } from \"./IconButton\";\n\nexport type SheetPlacement = \"auto\" | \"bottom\" | \"side\" | \"center\";\n\n/** Fractions of the viewport the bottom sheet rests at. Ascending. */\nexport type SheetDetent = number;\n\nexport interface SheetProps {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n description?: ReactNode;\n /** Slot left of the title — a back button when a sheet pushes another. */\n leftAction?: ReactNode;\n /** Slot right of the title, before the close button. */\n rightAction?: ReactNode;\n /**\n * Show the × in the header. Off by default on the bottom menu — the handle, a drag\n * down, a tap on the scrim and Escape all close it, and a fourth way costs the header\n * its room. On by default for side and centre panels, which have no handle. When it\n * is off the button is still there for a keyboard or a screen reader, and appears the\n * moment it takes focus.\n */\n closeButton?: boolean;\n footer?: ReactNode;\n /**\n * `bottom` (default) everywhere — the bottom menu is the app's signature surface and\n * stays that way on desktop too. `auto` opts into a right-side panel on desktop,\n * `side` and `center` force one. Only reach for those when a specific screen earns it.\n */\n placement?: SheetPlacement;\n size?: \"sm\" | \"md\" | \"lg\";\n /**\n * Resting heights for the bottom variant, as fractions of the viewport.\n * Drag between them; dragging below the first one closes.\n *\n * Left off, the sheet is as tall as its content and no taller — which is what a\n * bottom menu wants. Pass detents only for a sheet that browses something and so\n * needs a deliberate resting height.\n */\n detents?: readonly SheetDetent[];\n /** Start at this detent index. Default 0. */\n defaultDetent?: number;\n className?: string;\n children: ReactNode;\n}\n\nconst sideWidth = { sm: \"max-w-sm\", md: \"max-w-md\", lg: \"max-w-xl\" };\nconst centerWidth = { sm: \"max-w-sm\", md: \"max-w-lg\", lg: \"max-w-2xl\" };\nconst bottomWidth = { sm: \"max-w-md\", md: \"max-w-xl\", lg: \"max-w-3xl\" };\n\n/** Where the sheet waits before its first frame: far enough below any screen. */\nconst OFFSCREEN = 4000;\n/** Movement before a press becomes a drag — below it, a tap is still a tap. */\nconst SLOP = 4;\n\n/**\n * Holds its subtree on screen after its owner has let go, until `onExit` settles. The\n * bottom sheet leaves by animating the same value it arrives and is dragged by, so the\n * scrim fades with it — an exit prop would animate the drawn position and leave the\n * scrim behind.\n */\nfunction Leaving({ onExit, children }: { onExit: () => Promise<unknown>; children: ReactNode }) {\n const [present, safeToRemove] = usePresence();\n const stillPresent = useRef(present);\n stillPresent.current = present;\n useEffect(() => {\n if (present) return;\n /* Reopened before it finished leaving: the exit was interrupted, so it must not\n remove the sheet that is now coming back. */\n void onExit().then(() => {\n if (!stillPresent.current) safeToRemove?.();\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [present]);\n return <>{children}</>;\n}\n\ninterface DragState {\n pointerId: number;\n startY: number;\n fromBody: boolean;\n active: boolean;\n /** Where the finger actually is, which the sheet does not follow above its rest. */\n dy: number;\n samples: { t: number; y: number }[];\n}\n\nexport function Sheet({\n open,\n onClose,\n title,\n description,\n leftAction,\n rightAction,\n closeButton,\n footer,\n placement = \"bottom\",\n size = \"md\",\n detents,\n defaultDetent = 0,\n className,\n children,\n}: SheetProps) {\n const titleId = useId();\n const descriptionId = useId();\n const panelRef = useRef<HTMLDivElement>(null);\n const bodyRef = useRef<HTMLDivElement>(null);\n const compact = useCompactLayout();\n const reduced = useReducedMotion();\n const [detent, setDetent] = useState(defaultDetent);\n const portalTarget = usePortalTarget();\n /* Inside a device frame, heights resolve against the frame — `dvh` would measure the\n monitor the lab is open on, not the phone being simulated. */\n const framed = Boolean(useFrame().portal);\n const unit = framed ? \"%\" : \"dvh\";\n\n useModal(open, onClose, panelRef, { lockScroll: !framed });\n useEffect(() => {\n if (open) setDetent(defaultDetent);\n }, [open, defaultDetent]);\n\n const resolved: Exclude<SheetPlacement, \"auto\"> =\n placement === \"auto\" ? (compact ? \"bottom\" : \"side\") : placement;\n const bottom = resolved === \"bottom\";\n\n /* No detents means the sheet hugs its content, capped so it can never swallow the\n screen. A six-row menu is six rows tall. */\n const steps = detents?.length ? detents : null;\n const height = steps ? `${Math.round(steps[Math.min(detent, steps.length - 1)] * 100)}${unit}` : undefined;\n\n /* ── the bottom sheet's motion ──────────────────────────────────────────────\n One number drives everything: `y`, how far the sheet is below where it rests.\n The finger writes it directly while dragging, springs take over on release with\n the speed the finger left behind, and the scrim is derived from it — so it dims\n and clears with the sheet, whether it is animating or being held. Nothing here\n re-renders React while it moves. */\n const y = useMotionValue(0);\n const sheetHeight = useRef(0);\n const running = useRef<AnimationPlaybackControls | null>(null);\n const closing = useRef(false);\n const drag = useRef<DragState | null>(null);\n const [bodyScrolls, setBodyScrolls] = useState(false);\n /* What is drawn is clamped at the rest position: even a spring released with the\n finger still travelling upward can cross its target once, and that one frame would\n be the sheet leaving the edge. */\n const shownY = useTransform(y, (value) => Math.max(0, value));\n const scrim = useTransform(y, (value) => {\n const h = sheetHeight.current;\n return h ? 1 - Math.min(1, Math.max(0, value / h)) : 0;\n });\n\n const run = (to: number, transition: Transition, velocity = 0) => {\n running.current?.stop();\n running.current = animate(y, to, reduced ? { duration: 0 } : { ...transition, velocity });\n return running.current;\n };\n\n /* Park the sheet out of sight before its first frame. Written during render because\n the first paint reads the value synchronously; in an effect it would already have\n flashed fully open for a frame. */\n const wasOpen = useRef(false);\n if (bottom && open && !wasOpen.current) {\n closing.current = false;\n y.jump(OFFSCREEN);\n }\n wasOpen.current = open;\n\n useLayoutEffect(() => {\n if (!open || !bottom) return;\n const panel = panelRef.current;\n if (!panel) return;\n sheetHeight.current = panel.offsetHeight;\n y.jump(sheetHeight.current);\n run(0, m.sheetIn);\n\n /* Content can change while the sheet is up — keep the height the scrim and the\n dismissal measure against current, and know whether the body scrolls. */\n const observer = new ResizeObserver(() => {\n sheetHeight.current = panel.offsetHeight;\n const body = bodyRef.current;\n setBodyScrolls(Boolean(body && body.scrollHeight > body.clientHeight + 1));\n });\n observer.observe(panel);\n if (bodyRef.current) observer.observe(bodyRef.current);\n return () => observer.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, bottom]);\n\n const dismiss = (velocity: number) => {\n closing.current = true;\n /* Finish the throw ourselves, then tell the owner. Handing over mid-flight would\n lose the finger's speed at the seam and the sheet would visibly stall. */\n void run(sheetHeight.current, m.sheetOut, Math.max(0, velocity)).finished.then(() => {\n if (closing.current) onClose();\n });\n };\n\n const onPointerDown = (event: ReactPointerEvent<HTMLElement>, fromBody: boolean) => {\n if (!bottom || event.button !== 0 || closing.current) return;\n /* A press in a text field is selecting text, and one on a slider is moving it —\n neither is a request to move the sheet. `data-no-drag` opts anything else out. */\n if (fromBody && (event.target as HTMLElement).closest(\"input, textarea, select, [contenteditable='true'], [data-no-drag]\")) return;\n drag.current = { pointerId: event.pointerId, startY: event.clientY, fromBody, active: false, dy: 0, samples: [{ t: event.timeStamp, y: event.clientY }] };\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLElement>) => {\n const d = drag.current;\n if (!d || d.pointerId !== event.pointerId) return;\n const dy = event.clientY - d.startY;\n\n if (!d.active) {\n if (Math.abs(dy) < SLOP) return;\n /* From the content, a drag belongs to the sheet only while there is nothing to\n scroll back to — otherwise it is the list's. */\n const body = bodyRef.current;\n if (d.fromBody && bodyScrolls && (dy < 0 || (body?.scrollTop ?? 0) > 0)) {\n drag.current = null;\n return;\n }\n d.active = true;\n running.current?.stop();\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n\n /* Down follows the finger one to one. Up goes nowhere: the sheet is anchored to\n the bottom edge and never rises above where it rests. */\n d.dy = dy;\n y.set(Math.max(0, dy));\n d.samples.push({ t: event.timeStamp, y: event.clientY });\n /* Only the last moment of the gesture counts: a throw is judged by how it ends, not\n by the slow start that preceded it. */\n while (d.samples.length > 2 && event.timeStamp - d.samples[0].t > 60) d.samples.shift();\n };\n\n const onPointerUp = (event: ReactPointerEvent<HTMLElement>) => {\n const d = drag.current;\n drag.current = null;\n if (!d || !d.active || d.pointerId !== event.pointerId) return;\n\n const first = d.samples[0];\n const last = d.samples[d.samples.length - 1];\n const dt = Math.max(1, last.t - first.t);\n const velocity = ((last.y - first.y) / dt) * 1000;\n const offset = y.get();\n const h = sheetHeight.current || 1;\n\n /* A light flick is enough to dismiss — half a screen a second — or a quarter of\n the sheet's height at any speed. Anything less goes back. */\n const flungDown = velocity > 500;\n const flungUp = velocity < -500;\n const farDown = offset > Math.min(h * 0.25, 160);\n\n if (steps && (flungUp || d.dy < -40) && detent < steps.length - 1) {\n setDetent((i) => Math.min(i + 1, steps.length - 1));\n run(0, m.sheetSettle, velocity);\n return;\n }\n if ((flungDown || farDown) && velocity > -200) {\n if (steps && detent > 0) {\n setDetent((i) => Math.max(i - 1, 0));\n run(0, m.sheetSettle, velocity);\n } else {\n dismiss(velocity);\n }\n return;\n }\n run(0, m.sheetSettle, velocity);\n };\n\n const dragHandlers = (fromBody: boolean) =>\n bottom\n ? {\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => onPointerDown(event, fromBody),\n onPointerMove,\n onPointerUp,\n onPointerCancel: onPointerUp,\n }\n : {};\n\n const showClose = closeButton ?? !bottom;\n const shared = \"flex flex-col overflow-hidden border-line bg-surface-2 outline-none\";\n\n const header = (\n <div className={cn(\"shrink-0\", bottom && \"cursor-grab touch-none select-none active:cursor-grabbing\")} {...dragHandlers(false)}>\n {bottom && (\n <div className=\"flex justify-center pb-1 pt-2.5\">\n <span className=\"h-1 w-9 rounded-full bg-line-3\" aria-hidden=\"true\" />\n </div>\n )}\n <div className={cn(\"flex items-start gap-2 px-4\", bottom ? \"pb-3 pt-1.5\" : \"py-4\")}>\n {leftAction && <div className=\"shrink-0 pt-0.5\">{leftAction}</div>}\n <div className=\"min-w-0 flex-1\">\n {title && (\n <h2 id={titleId} className=\"truncate text-lg font-semibold text-fg\">\n {title}\n </h2>\n )}\n {description && (\n <p id={descriptionId} className=\"mt-0.5 text-sm text-fg-3\">\n {description}\n </p>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {rightAction}\n <IconButton\n label=\"Close\"\n shape=\"round\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={onClose}\n data-modal-chrome\n className={cn(!showClose && \"sr-only focus-visible:not-sr-only\")}\n >\n <X size={14} />\n </IconButton>\n </div>\n </div>\n <div className=\"h-px bg-line\" />\n </div>\n );\n\n const body = (\n <div\n ref={bodyRef}\n {...dragHandlers(true)}\n className={cn(\n \"scrollbar-thin min-h-0 overflow-y-auto overscroll-contain px-5 py-4\",\n steps ? \"flex-1\" : \"shrink\",\n /* A body with nothing to scroll is part of the handle: the whole sheet can be\n taken hold of, as on the platform. One that scrolls keeps its pan. Text\n fields keep theirs either way, so a long draft can still be scrolled. */\n bottom && !bodyScrolls && \"touch-none [&_input]:touch-auto [&_textarea]:touch-auto\",\n )}\n >\n {children}\n </div>\n );\n\n const dialogProps = {\n role: \"dialog\" as const,\n \"aria-modal\": true as const,\n \"aria-labelledby\": title ? titleId : undefined,\n \"aria-describedby\": description ? descriptionId : undefined,\n tabIndex: -1,\n };\n\n let content: ReactNode = null;\n if (open && bottom) {\n content = (\n <Leaving key=\"bottom\" onExit={() => run(sheetHeight.current, m.sheetOut).finished}>\n <div className=\"fixed inset-0 z-50\">\n {/* No backdrop blur: blurring the whole page under a moving scrim is the most\n expensive frame a webview can be asked for, and the platform only dims. */}\n <motion.div className=\"absolute inset-0 bg-black/50\" style={{ opacity: scrim }} onClick={onClose} />\n <motion.div\n ref={panelRef}\n {...dialogProps}\n style={{\n y: shownY,\n height,\n /* A skirt of the sheet's own colour below its bottom edge — insurance, so\n no frame of any animation can ever open a gap under it. */\n boxShadow: \"var(--shadow-sheet), 0 120px 0 0 var(--color-surface-2)\",\n transition: steps ? \"height 0.4s cubic-bezier(0.32, 0.72, 0, 1)\" : undefined,\n }}\n className={cn(\n shared,\n \"absolute inset-x-0 bottom-0 mx-auto w-full rounded-t-2xl border border-b-0 will-change-transform\",\n \"pb-[var(--safe-bottom)]\",\n !steps && (framed ? \"max-h-[85%]\" : \"max-h-[85dvh]\"),\n bottomWidth[size],\n className,\n )}\n >\n {header}\n {body}\n {footer && <div className=\"shrink-0 border-t border-line px-5 py-3\">{footer}</div>}\n </motion.div>\n </div>\n </Leaving>\n );\n } else if (open) {\n const side = resolved === \"side\";\n const panel = (\n <motion.div\n ref={panelRef}\n {...dialogProps}\n initial={side ? { x: \"100%\" } : { opacity: 0, scale: 0.97, y: 10 }}\n animate={side ? { x: 0 } : { opacity: 1, scale: 1, y: 0 }}\n exit={side ? { x: \"100%\", transition: m.sheetOut } : { opacity: 0, scale: 0.97, y: 10, transition: m.instant }}\n transition={side ? m.sheetIn : m.settle}\n className={cn(\n shared,\n side\n ? cn(\"fixed inset-y-0 right-0 z-50 w-full border-l shadow-sheet pb-[var(--safe-bottom)]\", sideWidth[size])\n : cn(\"relative z-50 w-full rounded-2xl border shadow-raised\", framed ? \"max-h-[85%]\" : \"max-h-[85dvh]\", centerWidth[size]),\n className,\n )}\n >\n {header}\n {body}\n {footer && <div className=\"shrink-0 border-t border-line px-5 py-3\">{footer}</div>}\n </motion.div>\n );\n content = (\n <motion.div key={resolved} className=\"fixed inset-0 z-50\">\n <motion.div\n className=\"absolute inset-0 bg-black/50\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={m.quick}\n onClick={onClose}\n />\n {side ? panel : <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center p-4 [&>*]:pointer-events-auto\">{panel}</div>}\n </motion.div>\n );\n }\n\n if (!portalTarget) return null;\n return createPortal(<AnimatePresence>{content}</AnimatePresence>, portalTarget);\n}\n\n/**\n * The team's name for this surface. Same component — `BottomMenu` reads better at\n * call sites that are, and always will be, a bottom menu.\n */\nexport const BottomMenu = Sheet;\nexport type BottomMenuProps = SheetProps;\n","import { useEffect, useState, type ReactNode } from \"react\";\nimport { AlertTriangle } from \"lucide-react\";\nimport { Button } from \"./Button\";\nimport { Sheet } from \"./Sheet\";\nimport { Alert } from \"./Alert\";\n\nexport interface ConfirmOptions {\n title: ReactNode;\n /** What actually happens, in plain terms. Say what is lost and whether it can be undone. */\n message?: ReactNode;\n /** Names the action, matching the button that opened it — \"Delete chat\", not \"OK\". */\n confirmLabel?: string;\n cancelLabel?: string;\n /** Paints the confirm button as destructive. */\n destructive?: boolean;\n /** An extra consequence the person should read before confirming. */\n warning?: { title: ReactNode; body: ReactNode };\n}\n\ninterface ConfirmRequest {\n options: ConfirmOptions;\n resolve: (confirmed: boolean) => void;\n}\n\nlet handler: ((request: ConfirmRequest) => void) | null = null;\n\n/**\n * `await confirm({...})` from anywhere — no local open state, no dialog JSX at the\n * call site. Resolves false when nothing is mounted, so a missing host can never\n * silently confirm a destructive action.\n */\nexport function confirm(options: ConfirmOptions): Promise<boolean> {\n return new Promise((resolve) => {\n if (!handler) {\n if (import.meta.env?.DEV) console.warn(\"confirm() called with no <ConfirmHost /> mounted; resolving false.\");\n resolve(false);\n return;\n }\n handler({ options, resolve });\n });\n}\n\n/** Mount once, at the app root, next to <Toaster />. */\nexport function ConfirmHost() {\n const [request, setRequest] = useState<ConfirmRequest | null>(null);\n const [open, setOpen] = useState(false);\n\n useEffect(() => {\n handler = (next) => {\n setRequest(next);\n setOpen(true);\n };\n return () => {\n handler = null;\n };\n }, []);\n\n const close = (confirmed: boolean) => {\n request?.resolve(confirmed);\n setOpen(false);\n };\n\n const options = request?.options;\n\n return (\n <Sheet\n open={open}\n /* Dismissing without choosing is a \"no\". */\n onClose={() => close(false)}\n size=\"sm\"\n title={options?.title ?? \"Are you sure?\"}\n footer={\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"ghost\" onClick={() => close(false)}>\n {options?.cancelLabel ?? \"Cancel\"}\n </Button>\n <Button variant={options?.destructive ? \"danger\" : \"primary\"} onClick={() => close(true)} data-autofocus>\n {options?.confirmLabel ?? \"Confirm\"}\n </Button>\n </div>\n }\n >\n <div className=\"space-y-3 pb-1\">\n {options?.message && <p className=\"text-base leading-relaxed text-fg-2\">{options.message}</p>}\n {options?.warning && (\n <Alert tone=\"warning\" title={options.warning.title} description={options.warning.body} />\n )}\n {!options?.message && !options?.warning && (\n <p className=\"flex items-center gap-2 text-base text-fg-2\">\n <AlertTriangle size={16} className=\"shrink-0 text-warning\" />\n This can't be undone.\n </p>\n )}\n </div>\n </Sheet>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\nexport interface ContextMenuProps {\n /** The menu body — reuse MenuItem / MenuSeparator / MenuLabel. */\n menu: ReactNode;\n /** ms to hold before it opens on touch. Default 450. */\n longPressDelay?: number;\n /** Fires when the menu opens and closes — use it to mark the target as held. */\n onOpenChange?: (open: boolean) => void;\n disabled?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Right-click on desktop, long-press on touch — one component for both, which is what\n * the app writes by hand at every message and library item. Opens at the pointer and\n * flips to stay on screen.\n */\nexport function ContextMenu({ menu, longPressDelay = 450, onOpenChange, disabled, className, children }: ContextMenuProps) {\n const [point, setPoint] = useState<{ x: number; y: number } | null>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const timer = useRef<number | null>(null);\n const origin = useRef<{ x: number; y: number } | null>(null);\n\n const clear = useCallback(() => {\n if (timer.current) window.clearTimeout(timer.current);\n timer.current = null;\n }, []);\n\n useEffect(() => {\n if (!point) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") close();\n };\n /* Capture, so a click inside the menu still closes it after the item handles it. */\n const onPointerDown = (event: PointerEvent) => {\n if (!panelRef.current?.contains(event.target as Node)) close();\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n window.addEventListener(\"scroll\", close, true);\n return () => {\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n window.removeEventListener(\"scroll\", close, true);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [point]);\n\n useEffect(() => clear, [clear]);\n\n const open = (x: number, y: number) => {\n const width = 224;\n const height = 260;\n setPoint({\n x: Math.min(x, window.innerWidth - width - 8),\n y: Math.min(y, window.innerHeight - height - 8),\n });\n onOpenChange?.(true);\n };\n\n const close = () => {\n setPoint(null);\n onOpenChange?.(false);\n };\n\n if (disabled) return <>{children}</>;\n\n return (\n <>\n <div\n className={cn(\"contents\", className)}\n onContextMenu={(event) => {\n event.preventDefault();\n open(event.clientX, event.clientY);\n }}\n onPointerDown={(event) => {\n if (event.pointerType !== \"touch\") return;\n origin.current = { x: event.clientX, y: event.clientY };\n clear();\n timer.current = window.setTimeout(() => open(event.clientX, event.clientY), longPressDelay);\n }}\n onPointerMove={(event) => {\n if (!origin.current) return;\n const moved = Math.hypot(event.clientX - origin.current.x, event.clientY - origin.current.y);\n if (moved > 10) clear();\n }}\n onPointerUp={clear}\n onPointerCancel={clear}\n >\n {children}\n </div>\n {createPortal(\n <AnimatePresence>\n {point && (\n <motion.div\n ref={panelRef}\n role=\"menu\"\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.96 }}\n transition={m.instant}\n style={{ top: point.y, left: point.x }}\n onClick={close}\n className=\"fixed z-[80] min-w-48 origin-top-left rounded-xl border border-line bg-surface-2 p-1 shadow-raised\"\n >\n {menu}\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n )}\n </>\n );\n}\n","import { useMemo, useState } from \"react\";\nimport { CalendarDays, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { inputSurface } from \"./Input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./Popover\";\n\nfunction startOfDay(d: Date) { const x = new Date(d); x.setHours(0, 0, 0, 0); return x; }\nfunction sameDay(a: Date, b: Date) { return startOfDay(a).getTime() === startOfDay(b).getTime(); }\n\nexport interface CalendarProps {\n value: Date | null;\n onChange: (date: Date) => void;\n min?: Date;\n max?: Date;\n /** 0 = Sunday, 1 = Monday. Defaults to the locale's own first day. */\n weekStartsOn?: 0 | 1;\n locale?: string;\n className?: string;\n}\n\n/** The month grid. Uses Intl for day and month names, so it follows the app's 20 locales. */\nexport function Calendar({ value, onChange, min, max, weekStartsOn = 1, locale, className }: CalendarProps) {\n const [cursor, setCursor] = useState(() => startOfDay(value ?? new Date()));\n const today = startOfDay(new Date());\n\n const { days, monthLabel, weekdays } = useMemo(() => {\n const year = cursor.getFullYear();\n const month = cursor.getMonth();\n const first = new Date(year, month, 1);\n const lead = (first.getDay() - weekStartsOn + 7) % 7;\n const total = new Date(year, month + 1, 0).getDate();\n\n const cells: (Date | null)[] = Array.from({ length: lead }, () => null);\n for (let d = 1; d <= total; d++) cells.push(new Date(year, month, d));\n\n const dayFmt = new Intl.DateTimeFormat(locale, { weekday: \"narrow\" });\n const names = Array.from({ length: 7 }, (_, i) => dayFmt.format(new Date(2024, 0, 7 + ((i + weekStartsOn) % 7))));\n\n return {\n days: cells,\n monthLabel: new Intl.DateTimeFormat(locale, { month: \"long\", year: \"numeric\" }).format(first),\n weekdays: names,\n };\n }, [cursor, weekStartsOn, locale]);\n\n const disabled = (date: Date) => (min && date < startOfDay(min)) || (max && date > startOfDay(max));\n\n /* The grid is seven columns wide, so a 44px minimum on the cells has to come from the\n calendar being wider — not from the cells overflowing it. */\n return (\n <div className={cn(\"w-64 select-none [@media(pointer:coarse)]:w-[21rem]\", className)}>\n <div className=\"mb-2 flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() - 1, 1))}\n aria-label=\"Previous month\"\n className=\"touch-target flex h-7 w-7 items-center justify-center rounded-lg text-fg-3 hover:bg-fill-2 hover:text-fg\"\n >\n <ChevronLeft size={16} />\n </button>\n <span aria-live=\"polite\" className=\"flex-1 text-center text-sm font-medium text-fg\">{monthLabel}</span>\n <button\n type=\"button\"\n onClick={() => setCursor(new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1))}\n aria-label=\"Next month\"\n className=\"touch-target flex h-7 w-7 items-center justify-center rounded-lg text-fg-3 hover:bg-fill-2 hover:text-fg\"\n >\n <ChevronRight size={16} />\n </button>\n </div>\n\n <div className=\"grid grid-cols-7 gap-0.5\">\n {weekdays.map((name, i) => (\n <span key={i} className=\"flex h-7 items-center justify-center text-2xs font-medium text-fg-3\">{name}</span>\n ))}\n {days.map((date, i) =>\n date ? (\n <button\n key={i}\n type=\"button\"\n disabled={disabled(date)}\n onClick={() => onChange(date)}\n aria-current={sameDay(date, today) ? \"date\" : undefined}\n aria-pressed={value ? sameDay(date, value) : false}\n className={cn(\n \"flex h-8 items-center justify-center rounded-lg text-sm tabular-nums transition-colors [@media(pointer:coarse)]:h-11\",\n value && sameDay(date, value)\n ? \"bg-accent font-medium text-on-accent\"\n : sameDay(date, today)\n ? \"text-accent hover:bg-fill-2\"\n : \"text-fg-2 hover:bg-fill-2 hover:text-fg\",\n disabled(date) && \"pointer-events-none opacity-25\",\n )}\n >\n {date.getDate()}\n </button>\n ) : (\n <span key={i} />\n ),\n )}\n </div>\n </div>\n );\n}\n\nexport interface DatePickerProps extends Omit<CalendarProps, \"className\"> {\n /** Shown when nothing is chosen. */\n placeholder?: string;\n /** Also offer a time field. */\n withTime?: boolean;\n disabled?: boolean;\n id?: string;\n className?: string;\n}\n\n/** A field that opens a Calendar. The app's DateTimePicker is 323 lines used in one place. */\nexport function DatePicker({\n value, onChange, placeholder = \"Pick a date\", withTime, disabled, id, className, ...calendar\n}: DatePickerProps) {\n const field = useFieldContext();\n const [open, setOpen] = useState(false);\n const label = value\n ? new Intl.DateTimeFormat(calendar.locale, {\n dateStyle: \"medium\",\n ...(withTime ? { timeStyle: \"short\" as const } : {}),\n }).format(value)\n : placeholder;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger>\n <button\n type=\"button\"\n id={id ?? field?.id}\n disabled={disabled}\n aria-describedby={field?.describedBy}\n className={cn(inputSurface, \"control-md flex items-center gap-2.5 px-3.5 text-left\", className)}\n >\n <CalendarDays size={16} className=\"shrink-0 text-fg-3\" />\n <span className={cn(\"min-w-0 flex-1 truncate\", value ? \"text-fg\" : \"text-fg-4\")}>{label}</span>\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"p-3\">\n <Calendar\n value={value}\n onChange={(date) => {\n if (withTime && value) date.setHours(value.getHours(), value.getMinutes());\n onChange(date);\n if (!withTime) setOpen(false);\n }}\n {...calendar}\n />\n {withTime && (\n <div className=\"mt-3 border-t border-line pt-3\">\n <input\n type=\"time\"\n value={value ? `${String(value.getHours()).padStart(2, \"0\")}:${String(value.getMinutes()).padStart(2, \"0\")}` : \"\"}\n onChange={(event) => {\n const [h, m] = event.target.value.split(\":\").map(Number);\n const next = new Date(value ?? new Date());\n next.setHours(h || 0, m || 0, 0, 0);\n onChange(next);\n }}\n aria-label=\"Time\"\n className=\"h-9 w-full rounded-lg border border-line bg-fill px-2.5 text-base tabular-nums text-fg outline-none focus:border-accent focus:ring-1 focus:ring-accent/35\"\n />\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n","import { useId, useRef, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { useModal } from \"../lib/useModal\";\nimport { IconButton } from \"./IconButton\";\n\nexport interface DialogProps {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n description?: ReactNode;\n footer?: ReactNode;\n size?: \"sm\" | \"md\" | \"lg\";\n /** Hide the corner close button — for confirmations where the footer is the only way out. */\n dismissible?: boolean;\n className?: string;\n children?: ReactNode;\n}\n\nconst sizeClass = { sm: \"max-w-sm\", md: \"max-w-md\", lg: \"max-w-2xl\" };\n\n/** Centred modal. Confirmations, short forms, anything that should not feel like a page. */\nexport function Dialog({ open, onClose, title, description, footer, size = \"md\", dismissible = true, className, children }: DialogProps) {\n const titleId = useId();\n const descriptionId = useId();\n const panelRef = useRef<HTMLDivElement>(null);\n useModal(open, onClose, panelRef);\n\n return createPortal(\n <AnimatePresence>\n {open && (\n <div className=\"fixed inset-0 z-50 flex items-end justify-center p-4 sm:items-center\">\n <motion.div\n key=\"overlay\"\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={m.quick}\n onClick={dismissible ? onClose : undefined}\n />\n <motion.div\n key=\"panel\"\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={description ? descriptionId : undefined}\n tabIndex={-1}\n className={cn(\n \"relative flex max-h-[85dvh] w-full flex-col overflow-hidden outline-none\",\n \"rounded-2xl border border-line bg-surface-2 shadow-raised\",\n sizeClass[size],\n className,\n )}\n initial={{ opacity: 0, scale: 0.96, y: 12 }}\n animate={{ opacity: 1, scale: 1, y: 0 }}\n exit={{ opacity: 0, scale: 0.96, y: 12 }}\n transition={m.settle}\n >\n {(title || dismissible) && (\n <div className=\"flex items-start gap-3 px-5 pt-5\">\n <div className=\"min-w-0 flex-1\">\n {title && (\n <h2 id={titleId} className=\"text-lg font-semibold text-fg\">\n {title}\n </h2>\n )}\n {description && (\n <p id={descriptionId} className=\"mt-1 text-sm text-fg-3\">\n {description}\n </p>\n )}\n </div>\n {dismissible && (\n <IconButton label=\"Close\" shape=\"round\" variant=\"secondary\" size=\"sm\" onClick={onClose} className=\"-mr-1 -mt-1\" data-modal-chrome>\n <X size={14} />\n </IconButton>\n )}\n </div>\n )}\n {children && <div className=\"scrollbar-thin min-h-0 flex-1 overflow-y-auto px-5 py-4\">{children}</div>}\n {footer && <div className=\"flex justify-end gap-2 border-t border-line px-5 py-3\">{footer}</div>}\n </motion.div>\n </div>\n )}\n </AnimatePresence>,\n document.body,\n );\n}\n","import { useMemo } from \"react\";\nimport { cn } from \"../lib/cn\";\n\ntype Op = \"same\" | \"add\" | \"remove\";\ninterface Line { op: Op; text: string; a?: number; b?: number }\n\n/** Longest common subsequence, line-wise. Enough for settings and character fields. */\nfunction diffLines(before: string, after: string): Line[] {\n const A = before.split(\"\\n\");\n const B = after.split(\"\\n\");\n const table: number[][] = Array.from({ length: A.length + 1 }, () => Array.from({ length: B.length + 1 }, () => 0));\n for (let i = A.length - 1; i >= 0; i--) {\n for (let j = B.length - 1; j >= 0; j--) {\n table[i][j] = A[i] === B[j] ? table[i + 1][j + 1] + 1 : Math.max(table[i + 1][j], table[i][j + 1]);\n }\n }\n const out: Line[] = [];\n let i = 0;\n let j = 0;\n while (i < A.length && j < B.length) {\n if (A[i] === B[j]) {\n out.push({ op: \"same\", text: A[i], a: i + 1, b: j + 1 });\n i++;\n j++;\n } else if (table[i + 1][j] >= table[i][j + 1]) {\n i++;\n out.push({ op: \"remove\", text: A[i - 1], a: i });\n } else {\n j++;\n out.push({ op: \"add\", text: B[j - 1], b: j });\n }\n }\n while (i < A.length) out.push({ op: \"remove\", text: A[i], a: ++i });\n while (j < B.length) out.push({ op: \"add\", text: B[j], b: ++j });\n return out;\n}\n\nexport interface DiffProps {\n before: string;\n after: string;\n /** Labels for the two sides. */\n beforeLabel?: string;\n afterLabel?: string;\n /** `unified` stacks the changes; `split` shows both sides. Split needs room. */\n view?: \"unified\" | \"split\";\n /** Collapse runs of unchanged lines longer than this. 0 shows everything. */\n context?: number;\n className?: string;\n}\n\nconst opClass: Record<Op, string> = {\n same: \"text-fg-3\",\n add: \"bg-accent/10 text-fg\",\n remove: \"bg-danger/10 text-fg\",\n};\n\n/**\n * What changed between two versions. The sync conflict inbox asks people to choose a\n * side without showing them what differs; this is the missing half.\n */\nexport function Diff({ before, after, beforeLabel = \"Theirs\", afterLabel = \"Yours\", view = \"unified\", context = 3, className }: DiffProps) {\n const lines = useMemo(() => diffLines(before, after), [before, after]);\n\n const visible = useMemo(() => {\n if (!context) return lines.map((line) => ({ line, elided: 0 }));\n const keep = new Set<number>();\n lines.forEach((line, index) => {\n if (line.op === \"same\") return;\n for (let k = index - context; k <= index + context; k++) if (k >= 0 && k < lines.length) keep.add(k);\n });\n const out: { line: Line | null; elided: number }[] = [];\n let run = 0;\n lines.forEach((line, index) => {\n if (keep.has(index)) {\n if (run) { out.push({ line: null, elided: run }); run = 0; }\n out.push({ line, elided: 0 });\n } else run++;\n });\n if (run) out.push({ line: null, elided: run });\n return out;\n }, [lines, context]);\n\n const added = lines.filter((l) => l.op === \"add\").length;\n const removed = lines.filter((l) => l.op === \"remove\").length;\n\n return (\n <div className={cn(\"overflow-hidden rounded-xl border border-line\", className)}>\n <div className=\"flex items-center gap-3 border-b border-line bg-fill px-3 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate text-sm text-fg-3\">\n {view === \"split\" ? `${beforeLabel} → ${afterLabel}` : \"Changes\"}\n </span>\n <span className=\"shrink-0 text-2xs tabular-nums text-accent\">+{added}</span>\n <span className=\"shrink-0 text-2xs tabular-nums text-danger\">−{removed}</span>\n </div>\n\n {view === \"split\" ? (\n <div className=\"grid grid-cols-2 divide-x divide-line\">\n {([\"remove\", \"add\"] as const).map((side) => (\n <div key={side} className=\"scrollbar-thin overflow-x-auto\">\n <p className=\"border-b border-line px-3 py-1 text-2xs font-medium text-fg-3\">\n {side === \"remove\" ? beforeLabel : afterLabel}\n </p>\n {lines.map((line, index) =>\n line.op === \"same\" || line.op === side ? (\n <p key={index} className={cn(\"whitespace-pre px-3 py-0.5 font-mono text-xs\", line.op === \"same\" ? \"text-fg-3\" : opClass[line.op])}>\n {line.text || \" \"}\n </p>\n ) : (\n <p key={index} aria-hidden=\"true\" className=\"px-3 py-0.5 font-mono text-xs opacity-0\">·</p>\n ),\n )}\n </div>\n ))}\n </div>\n ) : (\n <div className=\"scrollbar-thin overflow-x-auto py-1\">\n {visible.map((row, index) =>\n row.line ? (\n <p key={index} className={cn(\"flex gap-3 whitespace-pre px-3 py-0.5 font-mono text-xs\", opClass[row.line.op])}>\n <span aria-hidden=\"true\" className=\"w-3 shrink-0 select-none text-fg-4\">\n {row.line.op === \"add\" ? \"+\" : row.line.op === \"remove\" ? \"−\" : \" \"}\n </span>\n {row.line.text || \" \"}\n </p>\n ) : (\n <p key={index} className=\"px-3 py-1 text-2xs text-fg-3\">⋯ {row.elided} unchanged {row.elided === 1 ? \"line\" : \"lines\"}</p>\n ),\n )}\n </div>\n )}\n </div>\n );\n}\n","import { cn } from \"../lib/cn\";\n\nexport interface ProgressProps {\n /** 0–100. Omit for indeterminate. */\n value?: number;\n size?: \"sm\" | \"md\";\n tone?: \"accent\" | \"info\" | \"warning\" | \"danger\";\n label?: string;\n className?: string;\n}\n\nconst toneClass = { accent: \"bg-accent\", info: \"bg-info\", warning: \"bg-warning\", danger: \"bg-danger\" };\n\nexport function Progress({ value, size = \"md\", tone = \"accent\", label, className }: ProgressProps) {\n const indeterminate = value === undefined;\n return (\n <div\n role=\"progressbar\"\n aria-label={label}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={indeterminate ? undefined : Math.round(value)}\n className={cn(\"relative w-full overflow-hidden rounded-full bg-fill-3\", size === \"sm\" ? \"h-1\" : \"h-1.5\", className)}\n >\n <div\n className={cn(\"h-full rounded-full transition-[width] motion-slow ease-out\", toneClass[tone], indeterminate && \"w-1/3 animate-[indeterminate_1.4s_ease-in-out_infinite]\")}\n style={indeterminate ? undefined : { width: `${Math.max(0, Math.min(100, value))}%` }}\n />\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { AlertTriangle, Check, Download, Pause, Play, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { IconButton } from \"./IconButton\";\nimport { Progress } from \"./Progress\";\nimport { Spinner } from \"./Spinner\";\n\nexport type DownloadStatus = \"queued\" | \"downloading\" | \"paused\" | \"verifying\" | \"done\" | \"failed\";\n\nexport interface DownloadItemProps {\n name: string;\n /** Under the name — the repo, the quantisation, the format. */\n detail?: ReactNode;\n status: DownloadStatus;\n /** 0–1. Omit while queued or verifying. */\n progress?: number;\n /** Bytes per second. */\n speed?: number;\n /** Seconds remaining. */\n eta?: number;\n /** Total bytes, for the \"x of y\" line. */\n size?: number;\n error?: string;\n onPause?: () => void;\n onResume?: () => void;\n onCancel?: () => void;\n onRetry?: () => void;\n className?: string;\n}\n\nfunction bytes(n?: number) {\n if (n === undefined) return \"\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = n <= 0 ? 0 : Math.min(units.length - 1, Math.floor(Math.log(n) / Math.log(1024)));\n const value = n / 1024 ** i;\n return `${value >= 10 || i === 0 ? Math.round(value) : value.toFixed(1)} ${units[i]}`;\n}\n\nfunction duration(seconds?: number) {\n if (seconds === undefined || !Number.isFinite(seconds)) return \"\";\n if (seconds < 60) return `${Math.round(seconds)}s left`;\n if (seconds < 3600) return `${Math.round(seconds / 60)} min left`;\n return `${(seconds / 3600).toFixed(1)} h left`;\n}\n\n/**\n * One download, with everything a person needs to decide whether to wait: how far\n * along, how fast, how long left, and how to stop. The app has four different\n * download UIs and none of them shows all four.\n */\nexport function DownloadItem({\n name, detail, status, progress, speed, eta, size, error,\n onPause, onResume, onCancel, onRetry, className,\n}: DownloadItemProps) {\n const pct = progress === undefined ? undefined : Math.round(progress * 100);\n const done = status === \"done\";\n const failed = status === \"failed\";\n\n const line =\n failed ? error ?? \"Download failed\"\n : done ? bytes(size)\n : status === \"queued\" ? \"Waiting…\"\n : status === \"verifying\" ? \"Verifying…\"\n : status === \"paused\" ? `Paused${size ? ` · ${bytes((progress ?? 0) * size)} of ${bytes(size)}` : \"\"}`\n : [\n size ? `${bytes((progress ?? 0) * size)} of ${bytes(size)}` : undefined,\n speed ? `${bytes(speed)}/s` : undefined,\n duration(eta),\n ].filter(Boolean).join(\" · \");\n\n return (\n <div className={cn(\"flex items-center gap-3 rounded-xl border border-line bg-surface-1 p-3\", className)}>\n <span\n className={cn(\n \"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border\",\n done ? \"border-accent/30 bg-accent/12 text-accent\"\n : failed ? \"border-danger/30 bg-danger/12 text-danger\"\n : \"border-line bg-fill-2 text-fg-3\",\n )}\n >\n {done ? <Check size={18} /> : failed ? <AlertTriangle size={18} /> : status === \"verifying\" ? <Spinner size=\"md\" /> : <Download size={18} />}\n </span>\n\n <div className=\"min-w-0 flex-1 space-y-1.5\">\n <div className=\"flex items-baseline justify-between gap-3\">\n <p className=\"min-w-0 truncate text-base font-medium text-fg\">{name}</p>\n {pct !== undefined && !done && !failed && (\n <span className=\"shrink-0 text-sm tabular-nums text-fg-2\">{pct}%</span>\n )}\n </div>\n {detail && <p className=\"truncate text-sm text-fg-3\">{detail}</p>}\n {!done && !failed && (\n <Progress value={status === \"queued\" || status === \"verifying\" ? undefined : pct} size=\"sm\" />\n )}\n <p className={cn(\"truncate text-sm tabular-nums\", failed ? \"text-danger\" : \"text-fg-3\")}>{line}</p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {status === \"downloading\" && onPause && (\n <IconButton label={`Pause ${name}`} size=\"sm\" onClick={onPause}><Pause size={16} /></IconButton>\n )}\n {status === \"paused\" && onResume && (\n <IconButton label={`Resume ${name}`} size=\"sm\" onClick={onResume}><Play size={16} /></IconButton>\n )}\n {failed && onRetry && (\n <IconButton label={`Retry ${name}`} size=\"sm\" onClick={onRetry}><Download size={16} /></IconButton>\n )}\n {!done && onCancel && (\n <IconButton label={`Cancel ${name}`} size=\"sm\" onClick={onCancel}><X size={16} /></IconButton>\n )}\n </div>\n </div>\n );\n}\n","import { useRef, useState, type DragEvent, type ReactNode } from \"react\";\nimport { Upload } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\n\nexport interface DropzoneProps {\n onFiles: (files: File[]) => void;\n /** An `accept` string, e.g. \"image/*\" or \".png,.webp\". */\n accept?: string;\n multiple?: boolean;\n /** Bytes. Files over this are dropped and reported through `onReject`. */\n maxSize?: number;\n onReject?: (files: File[], reason: \"size\" | \"type\") => void;\n disabled?: boolean;\n /** Replaces the default prompt — a preview, say. */\n children?: ReactNode;\n hint?: ReactNode;\n className?: string;\n}\n\n/**\n * Drop, click or paste a file. Avatars, character cards, background images and audio\n * all get their own picker today; this is the one, and it keeps the keyboard path —\n * the hidden input is focusable, not `display: none`.\n */\nexport function Dropzone({\n onFiles, accept, multiple, maxSize, onReject, disabled, children, hint, className,\n}: DropzoneProps) {\n const field = useFieldContext();\n const inputRef = useRef<HTMLInputElement>(null);\n const [over, setOver] = useState(false);\n\n const accepts = (file: File) => {\n if (!accept) return true;\n return accept.split(\",\").some((rule) => {\n const r = rule.trim();\n if (r.endsWith(\"/*\")) return file.type.startsWith(r.slice(0, -1));\n if (r.startsWith(\".\")) return file.name.toLowerCase().endsWith(r.toLowerCase());\n return file.type === r;\n });\n };\n\n const handle = (list: FileList | null) => {\n if (!list) return;\n const all = Array.from(list);\n const wrongType = all.filter((f) => !accepts(f));\n const rest = all.filter((f) => accepts(f));\n const tooBig = maxSize ? rest.filter((f) => f.size > maxSize) : [];\n const ok = maxSize ? rest.filter((f) => f.size <= maxSize) : rest;\n\n if (wrongType.length) onReject?.(wrongType, \"type\");\n if (tooBig.length) onReject?.(tooBig, \"size\");\n if (ok.length) onFiles(multiple ? ok : ok.slice(0, 1));\n };\n\n const onDrop = (event: DragEvent) => {\n event.preventDefault();\n setOver(false);\n if (!disabled) handle(event.dataTransfer.files);\n };\n\n return (\n <div\n onDragOver={(event) => { event.preventDefault(); if (!disabled) setOver(true); }}\n onDragLeave={() => setOver(false)}\n onDrop={onDrop}\n onPaste={(event) => !disabled && handle(event.clipboardData.files)}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-2 rounded-xl border border-dashed px-6 py-8 text-center transition-colors\",\n over ? \"border-accent bg-accent/8\" : \"border-line-2 bg-surface-1 hover:border-line-3\",\n disabled && \"pointer-events-none opacity-40\",\n className,\n )}\n >\n <input\n ref={inputRef}\n id={field?.id}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n aria-describedby={field?.describedBy}\n onChange={(event) => { handle(event.target.files); event.target.value = \"\"; }}\n /* Invisible but focusable, so the keyboard and screen readers still reach it. */\n className=\"absolute inset-0 cursor-pointer opacity-0\"\n />\n {children ?? (\n <>\n <span className={cn(\"flex h-10 w-10 items-center justify-center rounded-full\", over ? \"bg-accent/20 text-accent\" : \"bg-fill-2 text-fg-3\")}>\n <Upload size={18} />\n </span>\n <p className=\"text-base font-medium text-fg\">\n {over ? \"Drop to add\" : \"Drop a file, or click to choose\"}\n </p>\n {hint && <p className=\"text-sm text-fg-3\">{hint}</p>}\n </>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { AlertTriangle, RotateCcw } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { Button } from \"./Button\";\n\nexport interface EmptyStateProps {\n icon?: ReactNode;\n title: ReactNode;\n /** Say what would put something here. */\n description?: ReactNode;\n action?: ReactNode;\n /** Compact variant for inside cards and sheets. */\n size?: \"sm\" | \"md\";\n className?: string;\n}\n\n/** An empty screen is an invitation to act, not an apology. */\nexport function EmptyState({ icon, title, description, action, size = \"md\", className }: EmptyStateProps) {\n return (\n <div className={cn(\"flex flex-col items-center text-center\", size === \"md\" ? \"px-6 py-14\" : \"px-4 py-8\", className)}>\n {icon && (\n <div className={cn(\"mb-4 flex items-center justify-center rounded-2xl border border-line bg-fill text-fg-3\", size === \"md\" ? \"h-14 w-14\" : \"h-11 w-11\")}>\n {icon}\n </div>\n )}\n <p className={cn(\"font-semibold text-fg\", size === \"md\" ? \"text-lg\" : \"text-base\")}>{title}</p>\n {description && <p className={cn(\"mt-1 max-w-xs text-fg-3\", size === \"md\" ? \"text-base\" : \"text-sm\")}>{description}</p>}\n {action && <div className=\"mt-5\">{action}</div>}\n </div>\n );\n}\n\nexport interface ErrorStateProps {\n title?: ReactNode;\n /** What went wrong and, if it can be helped, what to do. Never an apology. */\n description?: ReactNode;\n onRetry?: () => void;\n retryLabel?: string;\n size?: \"sm\" | \"md\";\n className?: string;\n}\n\n/** Something failed to load. Says what, and offers the one thing that might fix it. */\nexport function ErrorState({ title = \"Couldn't load this\", description, onRetry, retryLabel = \"Try again\", size = \"md\", className }: ErrorStateProps) {\n return (\n <div className={cn(\"flex flex-col items-center text-center\", size === \"md\" ? \"px-6 py-14\" : \"px-4 py-8\", className)}>\n <div className={cn(\"mb-4 flex items-center justify-center rounded-2xl border border-danger/25 bg-danger/10 text-danger\", size === \"md\" ? \"h-14 w-14\" : \"h-11 w-11\")}>\n <AlertTriangle size={size === \"md\" ? icon.xl : icon.lg} />\n </div>\n <p className={cn(\"font-semibold text-fg\", size === \"md\" ? \"text-lg\" : \"text-base\")}>{title}</p>\n {description && <p className={cn(\"mt-1 max-w-xs text-fg-3\", size === \"md\" ? \"text-base\" : \"text-sm\")}>{description}</p>}\n {onRetry && <Button variant=\"secondary\" className=\"mt-5\" leading={<RotateCcw size={icon.sm} />} onClick={onRetry}>{retryLabel}</Button>}\n </div>\n );\n}\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Chip } from \"./Chip\";\n\nexport interface FilterOption<T extends string> {\n value: T;\n label: string;\n count?: number;\n icon?: ReactNode;\n}\n\nexport interface FilterBarProps<T extends string> {\n options: readonly FilterOption<T>[];\n value: T;\n onChange: (value: T) => void;\n \"aria-label\"?: string;\n className?: string;\n}\n\nconst FADE = 28;\n\n/**\n * Horizontal filter row. It narrows one list by a facet; the list stays the same\n * list. When the choice changes what the screen is, that is Tabs, not a filter. Counts sit inside the chip so the row stays one line.\n * The overflow hint is a mask on the scroller, not a gradient overlay — an overlay\n * would have to know the parent's background colour, and it never does.\n */\nexport function FilterBar<T extends string>({ options, value, onChange, className, ...aria }: FilterBarProps<T>) {\n const scrollerRef = useRef<HTMLDivElement>(null);\n const [edges, setEdges] = useState({ start: false, end: false });\n\n useEffect(() => {\n const el = scrollerRef.current;\n if (!el) return;\n const measure = () => {\n const max = el.scrollWidth - el.clientWidth;\n setEdges({ start: el.scrollLeft > 4, end: max > 4 && el.scrollLeft < max - 4 });\n };\n measure();\n el.addEventListener(\"scroll\", measure, { passive: true });\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => {\n el.removeEventListener(\"scroll\", measure);\n observer.disconnect();\n };\n }, [options.length]);\n\n const mask =\n edges.start && edges.end\n ? `linear-gradient(to right, transparent, black ${FADE}px, black calc(100% - ${FADE}px), transparent)`\n : edges.end\n ? `linear-gradient(to right, black calc(100% - ${FADE}px), transparent)`\n : edges.start\n ? `linear-gradient(to right, transparent, black ${FADE}px)`\n : undefined;\n\n return (\n <div\n ref={scrollerRef}\n role=\"radiogroup\"\n aria-label={aria[\"aria-label\"]}\n className={cn(\"scrollbar-none flex gap-2 overflow-x-auto pb-0.5\", className)}\n style={mask ? { maskImage: mask, WebkitMaskImage: mask } : undefined}\n >\n {options.map((option) => {\n const selected = option.value === value;\n return (\n <Chip\n key={option.value}\n role=\"radio\"\n aria-checked={selected}\n selected={selected}\n icon={option.icon}\n onClick={() => onChange(option.value)}\n className=\"shrink-0\"\n >\n {option.label}\n {option.count !== undefined && (\n <span className={cn(\"tabular-nums\", selected ? \"text-accent/70\" : \"text-fg-3\")}>{option.count}</span>\n )}\n </Chip>\n );\n })}\n </div>\n );\n}\n","import {\n createContext, useCallback, useContext, useEffect, useMemo, useRef, useState,\n type FormEvent, type ReactNode,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { confirm } from \"./confirm\";\nimport { Button } from \"./Button\";\n\ninterface FormContextValue<T> {\n values: T;\n initial: T;\n dirty: boolean;\n submitting: boolean;\n errors: Partial<Record<keyof T, string>>;\n set: <K extends keyof T>(key: K, value: T[K]) => void;\n patch: (values: Partial<T>) => void;\n reset: () => void;\n}\n\nconst FormContext = createContext<FormContextValue<Record<string, unknown>> | null>(null);\n\nexport function useForm<T extends Record<string, unknown>>() {\n const ctx = useContext(FormContext);\n if (!ctx) throw new Error(\"useForm must be used inside <Form>\");\n return ctx as unknown as FormContextValue<T>;\n}\n\nexport interface FormProps<T extends Record<string, unknown>> {\n initial: T;\n onSubmit: (values: T) => void | Promise<void>;\n /** Return a message per invalid field. Runs on submit. */\n validate?: (values: T) => Partial<Record<keyof T, string>>;\n /** Warn before the tab closes while there are unsaved edits. */\n guardUnload?: boolean;\n children: ReactNode | ((form: FormContextValue<T>) => ReactNode);\n className?: string;\n}\n\n/**\n * Owns a form's values, dirty state and validation, so pages stop tracking them by\n * hand — the app's editors run to thousands of lines each and the top bar carries a\n * `wasUnsavedRef` of its own.\n */\nexport function Form<T extends Record<string, unknown>>({\n initial, onSubmit, validate, guardUnload = true, children, className,\n}: FormProps<T>) {\n const [values, setValues] = useState<T>(initial);\n const [errors, setErrors] = useState<Partial<Record<keyof T, string>>>({});\n const [submitting, setSubmitting] = useState(false);\n const initialRef = useRef(initial);\n\n const dirty = useMemo(\n () => JSON.stringify(values) !== JSON.stringify(initialRef.current),\n [values],\n );\n\n useEffect(() => {\n if (!guardUnload || !dirty) return;\n const onBeforeUnload = (event: BeforeUnloadEvent) => event.preventDefault();\n window.addEventListener(\"beforeunload\", onBeforeUnload);\n return () => window.removeEventListener(\"beforeunload\", onBeforeUnload);\n }, [guardUnload, dirty]);\n\n const set = useCallback(<K extends keyof T>(key: K, value: T[K]) => {\n setValues((current) => ({ ...current, [key]: value }));\n setErrors((current) => (current[key] ? { ...current, [key]: undefined } : current));\n }, []);\n\n const patch = useCallback((next: Partial<T>) => setValues((current) => ({ ...current, ...next })), []);\n\n const reset = useCallback(() => {\n setValues(initialRef.current);\n setErrors({});\n }, []);\n\n const submit = async (event: FormEvent) => {\n event.preventDefault();\n const found: Partial<Record<keyof T, string>> = validate?.(values) ?? {};\n const invalid = Object.values(found).some(Boolean);\n setErrors(found);\n if (invalid) {\n /* Move to the problem rather than leaving the person to hunt for it. */\n const first = Object.keys(found).find((key) => Boolean(found[key as keyof T]));\n if (first) document.querySelector<HTMLElement>(`[name=\"${first}\"], #${CSS.escape(first)}`)?.focus();\n return;\n }\n setSubmitting(true);\n try {\n await onSubmit(values);\n initialRef.current = values;\n setValues(values);\n } finally {\n setSubmitting(false);\n }\n };\n\n const ctx: FormContextValue<T> = { values, initial: initialRef.current, dirty, submitting, errors, set, patch, reset };\n\n return (\n <FormContext.Provider value={ctx as unknown as FormContextValue<Record<string, unknown>>}>\n <form onSubmit={submit} noValidate className={cn(\"space-y-5\", className)}>\n {typeof children === \"function\" ? children(ctx) : children}\n </form>\n </FormContext.Provider>\n );\n}\n\nexport interface FormActionsProps {\n submitLabel?: string;\n cancelLabel?: string;\n onCancel?: () => void;\n /** Keep the bar visible at the bottom of a long form. */\n sticky?: boolean;\n children?: ReactNode;\n}\n\n/** Save / cancel, disabled until something actually changed. */\nexport function FormActions({ submitLabel = \"Save changes\", cancelLabel = \"Cancel\", onCancel, sticky, children }: FormActionsProps) {\n const { dirty, submitting, reset } = useForm();\n return (\n <div\n className={cn(\n \"flex items-center gap-2 border-t border-line pt-4\",\n sticky && \"sticky bottom-0 -mx-4 mt-0 bg-surface/90 px-4 pb-[calc(var(--safe-bottom)+12px)] backdrop-blur-md\",\n )}\n >\n {dirty && <span className=\"text-sm text-fg-3\">Unsaved changes</span>}\n <span className=\"flex-1\" />\n {children}\n <Button type=\"button\" variant=\"ghost\" disabled={!dirty || submitting} onClick={() => { reset(); onCancel?.(); }}>\n {cancelLabel}\n </Button>\n <Button type=\"submit\" variant=\"primary\" disabled={!dirty} loading={submitting}>\n {submitLabel}\n </Button>\n </div>\n );\n}\n\n/**\n * Ask before leaving a dirty form. Wire it to your router's navigation guard:\n * `const leave = useUnsavedGuard(dirty); if (await leave()) navigate(to);`\n */\nexport function useUnsavedGuard(dirty: boolean) {\n return useCallback(async () => {\n if (!dirty) return true;\n return confirm({\n title: \"Discard your changes?\",\n message: \"You've edited this since you last saved.\",\n confirmLabel: \"Discard\",\n cancelLabel: \"Keep editing\",\n destructive: true,\n });\n }, [dirty]);\n}\n","import { cloneElement, useEffect, useRef, useState, type ReactElement, type ReactNode } from \"react\";\nimport { Popover, PopoverAnchor, PopoverContent } from \"./Popover\";\n\nexport interface HoverCardProps {\n content: ReactNode;\n /** ms before it appears / disappears. */\n openDelay?: number;\n closeDelay?: number;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n children: ReactElement<Record<string, unknown>>;\n}\n\n/**\n * A preview on hover — a character card under a mention, model details under a name.\n * Pointer-only by design: it never opens on touch, so it must never hold anything you\n * can't reach another way.\n */\nexport function HoverCard({ content, openDelay = 400, closeDelay = 150, side = \"top\", children }: HoverCardProps) {\n const [open, setOpen] = useState(false);\n const timer = useRef<number | null>(null);\n\n useEffect(() => () => { if (timer.current) window.clearTimeout(timer.current); }, []);\n\n const schedule = (next: boolean) => {\n if (timer.current) window.clearTimeout(timer.current);\n timer.current = window.setTimeout(() => setOpen(next), next ? openDelay : closeDelay);\n };\n\n const child = children.props as { onPointerEnter?: (e: unknown) => void; onPointerLeave?: (e: unknown) => void };\n const trigger = cloneElement(children, {\n onPointerEnter: (event: React.PointerEvent) => {\n child.onPointerEnter?.(event);\n if (event.pointerType === \"mouse\") schedule(true);\n },\n onPointerLeave: (event: unknown) => {\n child.onPointerLeave?.(event);\n schedule(false);\n },\n });\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n {/* PopoverAnchor, not PopoverTrigger: hovering opens this, clicking does nothing.\n It also has to be the Popover's own anchor ref — a local one of our own never\n reaches the panel, which then has nothing to measure and lands at 0,0. */}\n <PopoverAnchor>{trigger}</PopoverAnchor>\n <PopoverContent\n side={side}\n align=\"center\"\n className=\"w-72 p-0\"\n >\n <div onPointerEnter={() => schedule(true)} onPointerLeave={() => schedule(false)}>\n {content}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { createElement, type ComponentType } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/**\n * Four icon sizes, and only four. The app uses fifteen — from 9px to 36px — in two\n * different notations (`size={14}` and `className=\"h-4 w-4\"`). Going through this\n * component makes that impossible to drift back into.\n */\nexport const ICON_SIZE = {\n /** 14 — inside dense controls, badges, chips. */\n sm: 14,\n /** 16 — buttons, list rows, inline with body text. */\n md: 16,\n /** 18 — icon buttons, toolbars. */\n lg: 18,\n /** 22 — navigation, empty states. */\n xl: 22,\n} as const;\n\nexport type IconSize = keyof typeof ICON_SIZE;\n\nexport interface IconProps {\n /** A lucide icon component. */\n as: ComponentType<{ size?: number; strokeWidth?: number; className?: string; \"aria-hidden\"?: boolean }>;\n size?: IconSize;\n /** Give it a label only when the icon is the sole carrier of meaning. */\n label?: string;\n strokeWidth?: number;\n className?: string;\n}\n\nexport function Icon({ as: Component, size = \"md\", label, strokeWidth = 2, className }: IconProps) {\n return createElement(Component, {\n size: ICON_SIZE[size],\n strokeWidth,\n \"aria-hidden\": label ? undefined : true,\n ...(label ? { role: \"img\", \"aria-label\": label } : {}),\n className: cn(\"shrink-0\", className),\n });\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { ChevronLeft, ChevronRight, X, ZoomIn, ZoomOut } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { IconButton } from \"./IconButton\";\n\nexport interface ViewerImage {\n src: string;\n alt: string;\n caption?: string;\n}\n\nexport interface ImageViewerProps {\n images: readonly ViewerImage[];\n /** Index to show; null closes the viewer. */\n index: number | null;\n onIndexChange: (index: number | null) => void;\n}\n\n/**\n * Full-screen image inspection for the image library and chat attachments. Arrow keys\n * page, Escape closes, +/- zoom, and a zoomed image pans by drag.\n */\nexport function ImageViewer({ images, index, onIndexChange }: ImageViewerProps) {\n const [zoom, setZoom] = useState(1);\n const open = index !== null;\n const image = open ? images[index] : null;\n const restore = useRef<HTMLElement | null>(null);\n\n const step = useCallback(\n (delta: number) => {\n if (index === null) return;\n onIndexChange(Math.min(images.length - 1, Math.max(0, index + delta)));\n setZoom(1);\n },\n [index, images.length, onIndexChange],\n );\n\n useEffect(() => {\n if (!open) return;\n restore.current = document.activeElement as HTMLElement | null;\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onIndexChange(null);\n if (event.key === \"ArrowRight\") step(1);\n if (event.key === \"ArrowLeft\") step(-1);\n if (event.key === \"+\" || event.key === \"=\") setZoom((z) => Math.min(4, z + 0.5));\n if (event.key === \"-\") setZoom((z) => Math.max(1, z - 0.5));\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n restore.current?.focus?.();\n };\n }, [open, onIndexChange, step]);\n\n useEffect(() => { if (!open) setZoom(1); }, [open]);\n\n return createPortal(\n <AnimatePresence>\n {open && image && (\n <motion.div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={image.alt}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={m.quick}\n className=\"fixed inset-0 z-[90] flex flex-col bg-black/90 backdrop-blur-sm\"\n >\n <div className=\"flex shrink-0 items-center gap-2 p-3\">\n <span className=\"min-w-0 flex-1 truncate text-sm text-white/70\">{image.alt}</span>\n <span className=\"shrink-0 text-sm tabular-nums text-white/50\">{index + 1} / {images.length}</span>\n <IconButton label=\"Zoom out\" shape=\"round\" onClick={() => setZoom((z) => Math.max(1, z - 0.5))} className=\"text-white/70 hover:text-white\">\n <ZoomOut size={18} />\n </IconButton>\n <IconButton label=\"Zoom in\" shape=\"round\" onClick={() => setZoom((z) => Math.min(4, z + 0.5))} className=\"text-white/70 hover:text-white\">\n <ZoomIn size={18} />\n </IconButton>\n <IconButton label=\"Close\" shape=\"round\" onClick={() => onIndexChange(null)} className=\"text-white/70 hover:text-white\" data-autofocus>\n <X size={18} />\n </IconButton>\n </div>\n\n <div className=\"relative flex min-h-0 flex-1 items-center justify-center overflow-hidden p-4\">\n <motion.img\n key={image.src}\n src={image.src}\n alt={image.alt}\n drag={zoom > 1}\n dragMomentum={false}\n initial={{ opacity: 0, scale: 0.98 }}\n animate={{ opacity: 1, scale: zoom }}\n transition={m.quick}\n className={cn(\"max-h-full max-w-full object-contain\", zoom > 1 ? \"cursor-grab active:cursor-grabbing\" : \"cursor-zoom-in\")}\n onClick={() => zoom === 1 && setZoom(2)}\n />\n {images.length > 1 && (\n <>\n <IconButton label=\"Previous image\" shape=\"round\" onClick={() => step(-1)} disabled={index === 0} className=\"absolute left-3 text-white/70 hover:text-white\">\n <ChevronLeft size={20} />\n </IconButton>\n <IconButton label=\"Next image\" shape=\"round\" onClick={() => step(1)} disabled={index === images.length - 1} className=\"absolute right-3 text-white/70 hover:text-white\">\n <ChevronRight size={20} />\n </IconButton>\n </>\n )}\n </div>\n\n {image.caption && <p className=\"shrink-0 px-4 pb-4 text-center text-sm text-white/60\">{image.caption}</p>}\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { Spinner } from \"./Spinner\";\n\nexport interface InfiniteScrollProps {\n /** Called when the sentinel comes near the viewport. Guard against re-entry yourself. */\n onLoadMore: () => void;\n /** Stop observing — nothing left, or a request is in flight. */\n disabled?: boolean;\n loading?: boolean;\n /** Shown once there is nothing more to fetch. */\n endMessage?: string;\n /** How far ahead of the viewport to trigger. Default 600px. */\n rootMargin?: string;\n className?: string;\n}\n\n/** Sentinel for \"load the next page\". Pair with VirtualList for very long lists. */\nexport function InfiniteScroll({\n onLoadMore, disabled = false, loading = false, endMessage, rootMargin = \"600px\", className,\n}: InfiniteScrollProps) {\n const ref = useRef<HTMLDivElement>(null);\n const callback = useRef(onLoadMore);\n callback.current = onLoadMore;\n\n useEffect(() => {\n const el = ref.current;\n if (!el || disabled) return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0]?.isIntersecting) callback.current();\n },\n { rootMargin },\n );\n observer.observe(el);\n return () => observer.disconnect();\n }, [disabled, rootMargin]);\n\n return (\n <div className={cn(\"flex items-center justify-center py-6\", className)}>\n <div ref={ref} className=\"h-px w-px\" aria-hidden=\"true\" />\n {loading && <Spinner label=\"Loading more\" />}\n {!loading && disabled && endMessage && <p className=\"text-sm text-fg-3\">{endMessage}</p>}\n </div>\n );\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\nexport interface ListGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Small tracked heading above the group — the app's section-label style, kept to this one role. */\n label?: ReactNode;\n}\n\nexport function ListGroup({ label, className, children, ...rest }: ListGroupProps) {\n return (\n <section className={cn(\"space-y-2\", className)} {...rest}>\n {label && (\n <h3 className=\"px-1 text-2xs font-medium uppercase tracking-[0.18em] text-fg-3\">{label}</h3>\n )}\n <div className=\"divide-y divide-line overflow-hidden rounded-xl border border-line bg-surface-1\">{children}</div>\n </section>\n );\n}\n\ntype Tone = \"neutral\" | \"accent\" | \"danger\" | \"warning\" | \"info\" | \"secondary\";\n\n/* One frame, one icon colour. The tint used to be carried by a filled square behind each\n icon, which read as decoration applied by rote rather than as meaning. */\nconst iconTone: Record<Tone, string> = {\n neutral: \"border-line text-fg-3\",\n accent: \"border-line text-accent\",\n danger: \"border-line text-danger\",\n warning: \"border-line text-warning\",\n info: \"border-line text-info\",\n secondary: \"border-line text-secondary\",\n};\n\ninterface RowContentProps {\n icon?: ReactNode;\n tone?: Tone;\n title: ReactNode;\n description?: ReactNode;\n trailing?: ReactNode;\n chevron?: boolean;\n}\n\nfunction RowContent({ icon, tone = \"neutral\", title, description, trailing, chevron }: RowContentProps) {\n return (\n <>\n {icon && (\n <span\n className={cn(\n \"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border\",\n iconTone[tone],\n )}\n >\n {icon}\n </span>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-base font-medium text-fg\">{title}</span>\n {description && <span className=\"mt-0.5 block text-sm text-fg-3\">{description}</span>}\n </span>\n {trailing && <span className=\"shrink-0 text-sm text-fg-3\">{trailing}</span>}\n {chevron && <ChevronRight size={16} className=\"shrink-0 text-fg-4 transition-colors group-hover:text-fg-2\" />}\n </>\n );\n}\n\nconst rowBase = \"group row-py flex w-full items-center gap-3 px-4 text-left\";\n\n/** Static row (shows a value, hosts a switch, etc.). */\nexport interface ListRowProps extends Omit<HTMLAttributes<HTMLDivElement>, \"title\">, RowContentProps {}\n\nexport function ListRow({ icon, tone, title, description, trailing, chevron, className, ...rest }: ListRowProps) {\n return (\n <div className={cn(rowBase, className)} {...rest}>\n <RowContent icon={icon} tone={tone} title={title} description={description} trailing={trailing} chevron={chevron} />\n </div>\n );\n}\n\n/** Navigational / action row. Chevron on by default. */\nexport interface ListRowButtonProps extends Omit<HTMLMotionProps<\"button\">, \"title\">, RowContentProps {}\n\nexport const ListRowButton = forwardRef<HTMLButtonElement, ListRowButtonProps>(function ListRowButton(\n { icon, tone, title, description, trailing, chevron = true, className, type = \"button\", ...rest },\n ref,\n) {\n return (\n <motion.button\n ref={ref}\n type={type}\n whileTap={{ scale: 0.995 }}\n transition={m.instant}\n className={cn(\n rowBase,\n \"touch-target transition-colors motion-instant hover:bg-fill-2 disabled:pointer-events-none disabled:opacity-40\",\n className,\n )}\n {...rest}\n >\n <RowContent icon={icon} tone={tone} title={title} description={description} trailing={trailing} chevron={chevron} />\n </motion.button>\n );\n});\n","import { Children, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface MasonryProps {\n children: ReactNode;\n /** Smallest acceptable column width; the count follows the container. */\n minColumnWidth?: number;\n /** Hard cap on columns. */\n maxColumns?: number;\n gap?: number;\n className?: string;\n}\n\n/**\n * A column layout for items of uneven height — the image library, where a square grid\n * crops every portrait. Balances by placing each item in the shortest column, which\n * keeps DOM order per column and so keeps tab order sane.\n */\nexport function Masonry({ children, minColumnWidth = 180, maxColumns = 6, gap = 8, className }: MasonryProps) {\n const ref = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(0);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const measure = () => setWidth(el.clientWidth);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n const columnCount = Math.max(1, Math.min(maxColumns, Math.floor((width + gap) / (minColumnWidth + gap)) || 1));\n\n const columns = useMemo(() => {\n const items = Children.toArray(children);\n const buckets: ReactNode[][] = Array.from({ length: columnCount }, () => []);\n items.forEach((item, index) => buckets[index % columnCount].push(item));\n return buckets;\n }, [children, columnCount]);\n\n return (\n <div ref={ref} className={cn(\"flex w-full items-start\", className)} style={{ gap }}>\n {columns.map((column, index) => (\n <div key={index} className=\"flex min-w-0 flex-1 flex-col\" style={{ gap }}>\n {column}\n </div>\n ))}\n </div>\n );\n}\n","import { forwardRef, useState, type ReactNode } from \"react\";\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { tintFromName } from \"../lib/tint\";\nimport { Skeleton } from \"./Skeleton\";\n\nexport type MediaCardTone = \"accent\" | \"info\" | \"warning\" | \"secondary\" | \"neutral\";\n\nexport interface MediaCardProps extends Omit<HTMLMotionProps<\"button\">, \"title\"> {\n title: string;\n description?: ReactNode;\n image?: string | null;\n /** What kind of thing this is — a dot plus a word, only where it disambiguates. */\n kind?: string;\n tone?: MediaCardTone;\n /** Small pill next to the title (a persona's nickname, an entry count). */\n tag?: ReactNode;\n /** Bottom-right corner slot — a count, a duration. */\n meta?: ReactNode;\n selected?: boolean;\n}\n\nconst toneDot: Record<MediaCardTone, string> = {\n accent: \"bg-accent\",\n info: \"bg-info\",\n warning: \"bg-warning\",\n secondary: \"bg-secondary\",\n neutral: \"bg-fg-3\",\n};\n\n/**\n * The poster card: a character, persona or lorebook at a glance.\n * Full-bleed art, one scrim behind the text only, title and one line of description.\n */\nexport const MediaCard = forwardRef<HTMLButtonElement, MediaCardProps>(function MediaCard(\n { title, description, image, kind, tone = \"neutral\", tag, meta, selected, className, type = \"button\", ...rest },\n ref,\n) {\n const [broken, setBroken] = useState(false);\n const tint = tintFromName(title);\n const showImage = Boolean(image) && !broken;\n\n return (\n <motion.button\n ref={ref}\n type={type}\n aria-pressed={selected}\n whileTap={{ scale: 0.985 }}\n transition={m.instant}\n className={cn(\n \"group relative flex aspect-3/4 w-full flex-col justify-end overflow-hidden rounded-2xl text-left\",\n \"border border-line transition-colors motion-instant hover:border-line-3\",\n selected && \"ring-2 ring-inset ring-fg/35\",\n className,\n )}\n style={showImage ? undefined : { background: tint.background }}\n {...rest}\n >\n {showImage ? (\n <img\n src={image!}\n alt=\"\"\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => setBroken(true)}\n className=\"absolute inset-0 h-full w-full object-cover transition-transform motion-slow ease-out group-hover:scale-[1.04]\"\n />\n ) : (\n <span aria-hidden=\"true\" className=\"absolute inset-0 flex items-center justify-center text-4xl font-bold text-fg/25\">\n {title.slice(0, 2).toUpperCase()}\n </span>\n )}\n\n {/* Scrim sits behind the text only, so the art stays readable above it. */}\n <span aria-hidden=\"true\" className=\"absolute inset-x-0 bottom-0 h-2/5 bg-gradient-to-t from-black/85 via-black/45 to-transparent\" />\n\n {kind && (\n <span className=\"absolute left-2.5 top-2.5 z-10 inline-flex items-center gap-1.5 rounded-full border border-white/12 bg-black/55 px-2 py-1 text-2xs font-medium text-white/90 backdrop-blur-md\">\n <span className={cn(\"h-1.5 w-1.5 rounded-full\", toneDot[tone])} />\n {kind}\n </span>\n )}\n {meta && (\n <span className=\"absolute right-2.5 top-2.5 z-10 rounded-full border border-white/12 bg-black/55 px-2 py-1 text-2xs font-medium tabular-nums text-white/90 backdrop-blur-md\">\n {meta}\n </span>\n )}\n\n <span className=\"relative z-10 flex flex-col gap-0.5 p-3\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"min-w-0 flex-1 truncate text-lg font-semibold leading-tight text-white\">{title}</span>\n {tag && (\n <span className=\"shrink-0 rounded-full border border-white/15 bg-white/10 px-1.5 py-0.5 text-2xs font-medium text-white/80\">\n {tag}\n </span>\n )}\n </span>\n {description && <span className=\"line-clamp-2 text-sm leading-snug text-white/70\">{description}</span>}\n </span>\n </motion.button>\n );\n});\n\n/** Matches MediaCard's aspect and radius exactly, so the grid never reflows on load. */\nexport function MediaCardSkeleton() {\n return (\n <div className=\"relative aspect-3/4 w-full overflow-hidden rounded-2xl border border-line\">\n <Skeleton shape=\"block\" className=\"h-full w-full rounded-none\" />\n <div className=\"absolute inset-x-0 bottom-0 space-y-2 p-3\">\n <Skeleton width=\"65%\" className=\"h-4\" />\n <Skeleton width=\"90%\" className=\"h-3\" />\n </div>\n </div>\n );\n}\n","import { forwardRef, useState } from \"react\";\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\nimport { Layers } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { Skeleton } from \"./Skeleton\";\n\nexport interface MediaTileProps extends Omit<HTMLMotionProps<\"button\">, \"title\" | \"variants\"> {\n src: string;\n /** Describes the image for screen readers; also the fallback text. */\n alt: string;\n /** Badge in the corner — \"Avatar\", \"Background\". Omit when it isn't useful. */\n kind?: string;\n /** Number of variants stacked under this one. */\n variantCount?: number;\n selected?: boolean;\n aspect?: \"square\" | \"portrait\";\n}\n\n/**\n * A square image in a grid. Deliberately bare: on a touch screen there is no hover,\n * so metadata that only appears on hover is metadata nobody reads. Size, dimensions\n * and format belong in the detail sheet this tile opens.\n */\nexport const MediaTile = forwardRef<HTMLButtonElement, MediaTileProps>(function MediaTile(\n { src, alt, kind, variantCount, selected, aspect = \"square\", className, type = \"button\", ...rest },\n ref,\n) {\n const [broken, setBroken] = useState(false);\n return (\n <motion.button\n ref={ref}\n type={type}\n aria-label={alt}\n aria-pressed={selected}\n whileTap={{ scale: 0.985 }}\n transition={m.instant}\n className={cn(\n \"group relative w-full overflow-hidden rounded-xl border border-line bg-fill\",\n \"transition-colors motion-instant hover:border-line-3\",\n selected && \"ring-2 ring-inset ring-fg/45\",\n aspect === \"square\" ? \"aspect-square\" : \"aspect-3/4\",\n className,\n )}\n {...rest}\n >\n {broken ? (\n <span className=\"flex h-full w-full items-center justify-center px-2 text-center text-2xs text-fg-3\">{alt}</span>\n ) : (\n <img\n src={src}\n alt=\"\"\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => setBroken(true)}\n className=\"h-full w-full object-cover transition-transform motion-slow ease-out group-hover:scale-[1.04]\"\n />\n )}\n {kind && (\n <span className=\"absolute left-1.5 top-1.5 rounded-md border border-white/12 bg-black/60 px-1.5 py-0.5 text-2xs font-medium text-white/90 backdrop-blur-md\">\n {kind}\n </span>\n )}\n {variantCount && variantCount > 1 && (\n <span className=\"absolute right-1.5 top-1.5 inline-flex items-center gap-1 rounded-md border border-white/12 bg-black/60 px-1.5 py-0.5 text-2xs font-medium tabular-nums text-white/90 backdrop-blur-md\">\n <Layers size={12} />\n {variantCount}\n </span>\n )}\n </motion.button>\n );\n});\n\nexport function MediaTileSkeleton({ aspect = \"square\" }: { aspect?: \"square\" | \"portrait\" }) {\n return <Skeleton shape=\"block\" className={cn(\"w-full rounded-xl\", aspect === \"square\" ? \"aspect-square\" : \"aspect-3/4\")} />;\n}\n","import { useState, type ReactNode } from \"react\";\nimport { AnimatePresence, motion, type PanInfo } from \"framer-motion\";\nimport { Brain, ChevronDown, Clapperboard, Info, Pin } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { Avatar } from \"./Avatar\";\nimport { useOnSurface } from \"./Surface\";\nimport { Sheet } from \"./Sheet\";\nimport { useLongPress } from \"../lib/useLongPress\";\n\nexport type MessageRole = \"user\" | \"assistant\" | \"scene\" | \"system\";\nexport type MessageState = \"idle\" | \"streaming\" | \"typing\";\n\n/** User-facing chat appearance settings. Mirrors what the app already exposes. */\nexport interface MessageAppearance {\n fontSize?: \"small\" | \"medium\" | \"large\" | \"xlarge\";\n lineSpacing?: \"tight\" | \"normal\" | \"relaxed\";\n radius?: \"sharp\" | \"rounded\" | \"pill\";\n maxWidth?: \"compact\" | \"normal\" | \"wide\";\n padding?: \"compact\" | \"normal\" | \"spacious\";\n /** `filled` is a tinted bubble, `bordered` adds a hairline, `minimal` drops the bubble entirely. */\n style?: \"filled\" | \"bordered\" | \"minimal\";\n avatar?: \"circle\" | \"rounded\" | \"hidden\";\n avatarSize?: \"small\" | \"medium\" | \"large\";\n /** Where the byline sits. `below` puts it under the bubble with the timestamp. */\n headerPlacement?: \"below\" | \"outside\" | \"inside\";\n}\n\nexport interface MessageVariants {\n index: number;\n total: number;\n onPrev: () => void;\n onNext: () => void;\n}\n\nexport interface MessageProps {\n role: MessageRole;\n children?: ReactNode;\n author?: { name: string; avatar?: string | null };\n timestamp?: string;\n state?: MessageState;\n /** The model's visible reasoning, collapsed by default. */\n reasoning?: { text: ReactNode; label?: string };\n /** Images and files sent with the message. */\n attachments?: ReactNode;\n /** Regeneration variants. Swipe the bubble sideways to move between them. */\n variants?: MessageVariants;\n /**\n * Where this message sits in a run from the same author.\n * The avatar is drawn once at the top of the run, the byline once at the bottom —\n * so a three-message reply reads as one block instead of three headed cards.\n */\n group?: \"only\" | \"start\" | \"middle\" | \"end\";\n pinned?: boolean;\n /**\n * Everything a person can do to this message, shown in a bottom menu on long-press\n * or right-click. It is the only path, so it is the same path on every platform —\n * no row of icons that a phone can never reveal.\n */\n menu?: ReactNode;\n /** Title for that menu. */\n menuTitle?: ReactNode;\n /**\n * Take the gesture instead of the menu: long-press and right-click call this, and the\n * message draws no sheet of its own. For a screen that keeps one menu for every\n * message — richer than a list of rows, and closed from the screen's own state.\n * Pair with `held` so the bubble shows which message it is for.\n */\n onMenu?: () => void;\n /** Force the held look — for a menu you control yourself. */\n held?: boolean;\n appearance?: MessageAppearance;\n className?: string;\n}\n\nconst fontSize = { small: \"text-sm\", medium: \"text-base\", large: \"text-lg\", xlarge: \"text-xl\" };\nconst lineSpacing = { tight: \"leading-snug\", normal: \"leading-normal\", relaxed: \"leading-relaxed\" };\nconst radiusClass = { sharp: \"rounded-md\", rounded: \"rounded-xl\", pill: \"rounded-2xl\" };\n/*\n * How wide a bubble may grow: the column minus a gutter, capped at a reading measure.\n *\n * A percentage did one of those jobs and wasted the other. 82% keeps a desktop line\n * readable, but a phone's column is already narrow — there it left a third of the\n * screen empty beside every message. Now the gutter decides on a phone (the gap on the\n * far side is what says whose message it is) and the cap decides on a desktop, where\n * 36rem lands within a few pixels of the old 82%.\n */\nconst maxWidth = {\n compact: \"max-w-[min(calc(100%-3rem),30rem)]\",\n normal: \"max-w-[min(calc(100%-1.5rem),36rem)]\",\n wide: \"max-w-[min(100%,44rem)]\",\n};\nconst padding = { compact: \"px-3 py-2\", normal: \"px-4 py-2.5\", spacious: \"px-5 py-3.5\" };\nconst avatarSize = { small: \"xs\", medium: \"sm\", large: \"md\" } as const;\n\nconst DEFAULTS: Required<Omit<MessageAppearance, never>> = {\n fontSize: \"medium\",\n lineSpacing: \"relaxed\",\n radius: \"rounded\",\n maxWidth: \"normal\",\n padding: \"normal\",\n style: \"filled\",\n avatar: \"circle\",\n avatarSize: \"medium\",\n headerPlacement: \"below\",\n};\n\nexport function Message({\n role, children, author, timestamp, state = \"idle\", reasoning, attachments,\n variants, group = \"only\", pinned, held, menu, menuTitle = \"Message\", onMenu, appearance, className,\n}: MessageProps) {\n const a = { ...DEFAULTS, ...appearance };\n const mine = role === \"user\";\n /* On a background image the flat theme fill disappears into the art, so bubbles\n become glass: a stronger translucent fill that blurs what is behind it. */\n const { hasBackground: glass, tone: surfaceTone } = useOnSurface();\n const showsAvatar = group === \"only\" || group === \"start\";\n /* The byline is drawn once per run, at whichever end it sits: below the last bubble\n when it trails the message, above the first when it heads it. Tying it to the last\n message either way put the name over the middle of a block. */\n const showsByline = group === \"only\" || group === (a.headerPlacement === \"below\" ? \"end\" : \"start\");\n const [menuOpen, setMenuOpen] = useState(false);\n const isHeld = held || menuOpen;\n const openMenu = onMenu ?? (menu ? () => setMenuOpen(true) : undefined);\n const longPress = useLongPress(openMenu, { enabled: Boolean(openMenu) });\n\n /* Regenerations are moved through by throwing the bubble sideways — left for the next\n one, right for the previous — with the count in its corner. Arrows beside the byline\n were a second, desktop-only control for something the card itself already does. */\n const swipeable = Boolean(variants && variants.total > 1);\n /* How far the card can travel. Inside this range it tracks the pointer exactly; past\n it the rubber band takes over and it goes almost nowhere. At either end of the run\n the travel is short, so a swipe with nothing behind it says so before you let go. */\n const swipeReach = 176;\n const swipeEdge = 56;\n const onVariantDragEnd = (_: unknown, info: PanInfo) => {\n if (!variants) return;\n const far = Math.abs(info.offset.x) > 40;\n const fast = Math.abs(info.velocity.x) > 320;\n if (!far && !fast) return;\n if (info.offset.x < 0) {\n if (variants.index < variants.total - 1) variants.onNext();\n } else if (variants.index > 0) {\n variants.onPrev();\n }\n };\n\n /* Scene and system are narrated rather than spoken, but they are still messages:\n same row, same bubble, same menu and variants. Only the byline changes. */\n const narration = role === \"scene\" || role === \"system\";\n const byline = author?.name ?? (role === \"scene\" ? \"Scene\" : role === \"system\" ? \"System\" : undefined);\n\n const showAvatar = a.avatar !== \"hidden\" && Boolean(author) && !narration && showsAvatar;\n /* An empty meta line still costs the column gap, so only draw it when it holds something. */\n const hasMeta =\n (showsByline && a.headerPlacement === \"below\" && Boolean(byline || timestamp)) ||\n (Boolean(pinned) && a.headerPlacement === \"below\");\n const header = showsByline && (byline || timestamp) && (\n <div className={cn(\"flex items-baseline gap-2\", mine && \"flex-row-reverse\")}>\n {byline && (\n <span className={cn(\"truncate text-sm font-medium\", narration && !author ? \"text-fg-3\" : \"text-fg-2\")}>\n {byline}\n </span>\n )}\n {timestamp && <span className=\"shrink-0 text-2xs tabular-nums text-fg-3\">{timestamp}</span>}\n {pinned && (\n <span className=\"inline-flex shrink-0 items-center gap-1 text-2xs text-info\" aria-label=\"Pinned\">\n <Pin size={12} />\n Pinned\n </span>\n )}\n </div>\n );\n\n const bubble = (\n <motion.div\n initial={state === \"typing\" ? false : { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={m.quick}\n {...(swipeable\n ? {\n /* The constraints are the travel limit, not a brake: inside them the card\n tracks the pointer one to one. Elasticity only applies past the edge, so\n it stops where it should instead of crawling the whole way. */\n drag: \"x\" as const,\n dragDirectionLock: true,\n dragConstraints: {\n left: variants!.index >= variants!.total - 1 ? -swipeEdge : -swipeReach,\n right: variants!.index <= 0 ? swipeEdge : swipeReach,\n },\n dragElastic: 0.08,\n dragSnapToOrigin: true,\n dragMomentum: false,\n dragTransition: m.rebound,\n whileDrag: { cursor: \"grabbing\" },\n onDragEnd: onVariantDragEnd,\n }\n : {})}\n className={cn(\n \"relative min-w-0\",\n fontSize[a.fontSize],\n lineSpacing[a.lineSpacing],\n /* Narration is a note dropped into the story, not something anybody says: full\n width to its own measure, and a step quieter. It still answers to the bubble\n style — a minimal chat is minimal everywhere, or the setting is a lie. */\n narration\n ? cn(\n /* Sized like a reply, not stretched across the column: a card twice\n the width of the bubbles around it reads as a different kind of page. */\n \"w-fit text-fg-2\",\n maxWidth[a.maxWidth],\n a.style !== \"minimal\" && padding[a.padding],\n /* A system note is bookkeeping — \"three days pass\" — not a line of the\n story. One step down in size and padding, so it marks time without\n taking the room a reply would. A scene keeps body size: it is prose. */\n role === \"system\" && \"text-sm leading-normal\",\n role === \"system\" && a.style !== \"minimal\" && \"px-3 py-2\",\n a.style !== \"minimal\" && radiusClass[a.radius],\n glass && a.style !== \"minimal\" && \"backdrop-blur-md\",\n a.style === \"filled\" &&\n (glass\n ? surfaceTone === \"light\"\n ? \"border border-black/10 bg-white/45\"\n : \"border border-white/10 bg-black/45\"\n : \"border border-line bg-fill\"),\n a.style === \"bordered\" && \"border border-line-2\",\n )\n : cn(\n \"w-fit\",\n maxWidth[a.maxWidth],\n a.style !== \"minimal\" && padding[a.padding],\n a.style !== \"minimal\" && radiusClass[a.radius],\n a.style === \"minimal\" && \"text-fg\",\n a.style === \"filled\" && (mine ? \"bg-accent/22 text-fg\" : \"bg-fill-2 text-fg\"),\n glass && a.style !== \"minimal\" && \"backdrop-blur-md\",\n glass && a.style === \"filled\" && surfaceTone === \"dark\" && (mine ? \"bg-accent/35\" : \"border border-white/10 bg-black/35\"),\n glass && a.style === \"filled\" && surfaceTone === \"light\" && (mine ? \"bg-accent/40\" : \"border border-black/10 bg-white/55\"),\n a.style === \"bordered\" && (mine ? \"border border-accent/40 text-fg\" : \"border border-line-2 text-fg\"),\n mine && \"ml-auto\",\n ),\n /* Room in the corner for the counter, so it never lands on the last line.\n Last in the list so it wins over the padding preset. */\n swipeable && \"pb-6\",\n isHeld && \"ring-2 ring-accent/50\",\n )}\n >\n {a.headerPlacement === \"inside\" && header && <div className=\"mb-1.5\">{header}</div>}\n {attachments && <div className=\"mb-2\">{attachments}</div>}\n\n {state === \"typing\" ? <TypingDots /> : children}\n {state === \"streaming\" && (\n <span aria-hidden=\"true\" className=\"ml-0.5 inline-block h-[1em] w-[2px] translate-y-[0.15em] animate-pulse bg-accent\" />\n )}\n\n {swipeable && (\n <span\n className=\"pointer-events-none absolute bottom-1.5 right-3 text-2xs tabular-nums text-fg-3 select-none\"\n aria-live=\"polite\"\n >\n {variants!.index + 1}/{variants!.total}\n </span>\n )}\n </motion.div>\n );\n\n const row = (\n <div\n /* The gesture sits on the row itself. A wrapper around it — even `display:contents`\n — makes every message the first child of its own wrapper, and `first:mt-0` then\n strips the leading margin from all of them. */\n {...(openMenu ? longPress.handlers : {})}\n className={cn(\n \"group/message flex w-full gap-2\",\n group === \"start\" || group === \"only\" ? \"mt-5 first:mt-0\" : \"mt-1\",\n mine ? \"flex-row-reverse\" : \"flex-row\",\n className,\n )}\n >\n {showAvatar ? (\n <Avatar\n name={author!.name}\n src={author!.avatar}\n size={avatarSize[a.avatarSize]}\n className={cn(\"mt-0.5\", a.avatar === \"rounded\" && \"rounded-lg\")}\n />\n ) : narration && a.avatar !== \"hidden\" && showsAvatar ? (\n /* A mark, not a face — narration is not a person, but it still holds the lane so\n the column of avatars stays unbroken. */\n <span\n aria-hidden=\"true\"\n className={cn(\n \"mt-0.5 flex shrink-0 items-center justify-center border border-line bg-fill text-fg-3\",\n a.avatar === \"rounded\" ? \"rounded-lg\" : \"rounded-full\",\n a.avatarSize === \"small\" ? \"h-6 w-6\" : a.avatarSize === \"large\" ? \"h-10 w-10\" : \"h-8 w-8\",\n )}\n >\n {role === \"scene\" ? <Clapperboard size={14} /> : <Info size={14} />}\n </span>\n ) : (\n a.avatar !== \"hidden\" && (\n <span className={cn(\"shrink-0\", a.avatarSize === \"small\" ? \"w-6\" : a.avatarSize === \"large\" ? \"w-10\" : \"w-8\")} aria-hidden=\"true\" />\n )\n )}\n\n <div className={cn(\"flex min-w-0 flex-1 flex-col gap-0.5\", mine && \"items-end\")}>\n {a.headerPlacement === \"outside\" && header}\n {reasoning && (\n <Reasoning label={reasoning.label} align={mine ? \"end\" : \"start\"}>\n {reasoning.text}\n </Reasoning>\n )}\n {bubble}\n\n {/* Byline, pin and version counter, on one quiet line under the bubble. Nothing\n else lives here — the actions are in the bottom menu, one gesture away. */}\n {hasMeta && (\n <div className={cn(\"flex items-center gap-2\", mine && !narration && \"flex-row-reverse\")}>\n {showsByline && a.headerPlacement === \"below\" && byline && (\n <span className=\"truncate text-2xs text-fg-3\">\n {byline}\n {timestamp && <span className=\"ml-1.5 tabular-nums text-fg-3\">{timestamp}</span>}\n </span>\n )}\n {pinned && (\n <span className=\"inline-flex shrink-0 items-center gap-1 text-2xs text-info\" aria-label=\"Pinned\">\n <Pin size={12} />\n Pinned\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n );\n\n if (!menu || onMenu) return row;\n return (\n <>\n {row}\n {/* Portals to the body, so it takes no place in the message flow. */}\n <Sheet open={menuOpen} onClose={() => setMenuOpen(false)} title={menuTitle} size=\"sm\">\n <div className=\"pb-2\">{menu}</div>\n </Sheet>\n </>\n );\n}\n\n/**\n * The model's reasoning. It sits above the bubble, unboxed: a quiet toggle, and when\n * open, an aside marked by a single rule. A bordered panel here would be a card inside\n * a card, and the reasoning is not the reply.\n */\nfunction Reasoning({\n label = \"Thought process\",\n align = \"start\",\n children,\n}: {\n label?: string;\n align?: \"start\" | \"end\";\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n return (\n <div className={cn(\"flex w-full flex-col\", align === \"end\" ? \"items-end\" : \"items-start\")}>\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n aria-expanded={open}\n className=\"-mx-1 inline-flex items-center gap-1.5 rounded-md px-1 py-0.5 text-sm text-fg-3 transition-colors hover:text-fg-2\"\n >\n <Brain size={14} className=\"shrink-0 text-secondary\" />\n {label}\n <ChevronDown size={14} className={cn(\"shrink-0 transition-transform motion-quick\", open && \"rotate-180\")} />\n </button>\n <AnimatePresence initial={false}>\n {open && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={m.collapse}\n className=\"w-full overflow-hidden\"\n >\n <div\n className={cn(\n \"mt-1 max-w-[min(calc(100%-1.5rem),36rem)] py-0.5 text-sm leading-relaxed text-fg-3\",\n align === \"end\" ? \"ml-auto border-r border-line-2 pr-3 text-right\" : \"border-l border-line-2 pl-3\",\n )}\n >\n {children}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n\nexport function TypingDots({ className }: { className?: string }) {\n return (\n <span className={cn(\"flex items-center gap-1 py-1\", className)} role=\"status\" aria-label=\"Typing\">\n {[0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className=\"h-1.5 w-1.5 rounded-full bg-fg-3\"\n animate={{ opacity: [0.25, 1, 0.25], scale: [0.85, 1.1, 0.85] }}\n transition={{ ...m.pulse, delay: i * 0.18 }}\n />\n ))}\n </span>\n );\n}\n\n/** Date separator between days of conversation. */\nexport function MessageDivider({ children }: { children: ReactNode }) {\n return (\n <div className=\"flex items-center gap-3 py-3\">\n <span className=\"h-px flex-1 bg-line\" />\n <span className=\"shrink-0 text-2xs font-medium text-fg-3\">{children}</span>\n <span className=\"h-px flex-1 bg-line\" />\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface MeterProps {\n value: number;\n max?: number;\n label?: ReactNode;\n /** Right of the label — \"12.4k / 128k\". */\n valueLabel?: ReactNode;\n /** Fractions where the bar changes tone. Default warns at 0.75, alarms at 0.9. */\n thresholds?: { warning: number; danger: number };\n size?: \"sm\" | \"md\";\n className?: string;\n}\n\n/**\n * A budget you are spending: context window, token allowance, disk quota.\n * Progress says \"how far along\"; a Meter says \"how much is left\" and turns as it fills.\n */\nexport function Meter({\n value, max = 100, label, valueLabel, thresholds = { warning: 0.75, danger: 0.9 }, size = \"md\", className,\n}: MeterProps) {\n const ratio = max > 0 ? Math.min(1, Math.max(0, value / max)) : 0;\n const tone = ratio >= thresholds.danger ? \"danger\" : ratio >= thresholds.warning ? \"warning\" : \"accent\";\n const bar = { accent: \"bg-fg-3\", warning: \"bg-warning\", danger: \"bg-danger\" }[tone];\n const text = { accent: \"text-fg-2\", warning: \"text-warning\", danger: \"text-danger\" }[tone];\n\n return (\n <div className={cn(\"space-y-1.5\", className)}>\n {(label || valueLabel) && (\n <div className=\"flex items-baseline justify-between gap-3\">\n {label && <span className=\"min-w-0 truncate text-sm text-fg-3\">{label}</span>}\n {valueLabel && <span className={cn(\"shrink-0 text-sm tabular-nums\", text)}>{valueLabel}</span>}\n </div>\n )}\n <div\n role=\"meter\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={typeof label === \"string\" ? label : undefined}\n className={cn(\"w-full overflow-hidden rounded-full bg-fill-3\", size === \"sm\" ? \"h-1\" : \"h-1.5\")}\n >\n <div className={cn(\"h-full rounded-full transition-[width,background-color] motion-slow\", bar)} style={{ width: `${ratio * 100}%` }} />\n </div>\n </div>\n );\n}\n","import { useMemo, useState, type ReactNode } from \"react\";\nimport { AlertTriangle, Check, ChevronDown, Download, Pause, Play, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { DownloadItem, type DownloadStatus } from \"./DownloadItem\";\nimport { IconButton } from \"./IconButton\";\nimport { Progress } from \"./Progress\";\nimport { Spinner } from \"./Spinner\";\n\nexport interface DownloadGroupItem {\n id: string;\n name: string;\n detail?: ReactNode;\n status: DownloadStatus;\n /** 0–1. */\n progress?: number;\n /** Bytes. Needed for an honest overall percentage. */\n size?: number;\n speed?: number;\n eta?: number;\n error?: string;\n}\n\nexport interface MultiItemDownloadCardProps {\n title: string;\n detail?: ReactNode;\n items: readonly DownloadGroupItem[];\n onPauseAll?: () => void;\n onResumeAll?: () => void;\n onCancelAll?: () => void;\n onItemPause?: (id: string) => void;\n onItemResume?: (id: string) => void;\n onItemCancel?: (id: string) => void;\n onItemRetry?: (id: string) => void;\n defaultExpanded?: boolean;\n className?: string;\n}\n\nfunction bytes(n?: number) {\n if (n === undefined) return \"\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = n <= 0 ? 0 : Math.min(units.length - 1, Math.floor(Math.log(n) / Math.log(1024)));\n const value = n / 1024 ** i;\n return `${value >= 10 || i === 0 ? Math.round(value) : value.toFixed(1)} ${units[i]}`;\n}\n\nfunction duration(seconds?: number) {\n if (seconds === undefined || !Number.isFinite(seconds) || seconds <= 0) return \"\";\n if (seconds < 60) return `${Math.round(seconds)}s left`;\n if (seconds < 3600) return `${Math.round(seconds / 60)} min left`;\n return `${(seconds / 3600).toFixed(1)} h left`;\n}\n\n/**\n * One download made of several files — a model with its shards, tokenizer and config;\n * a voice pack; an image-generation bundle. The parts are what actually transfer, but\n * the bundle is what a person chose, so the card reports the bundle and keeps the parts\n * a disclosure away.\n *\n * The overall figure is weighted by file size, not a mean of percentages: a 16 GB shard\n * at 10% and a 2 KB config at 100% is not \"55% done\".\n */\nexport function MultiItemDownloadCard({\n title, detail, items, onPauseAll, onResumeAll, onCancelAll,\n onItemPause, onItemResume, onItemCancel, onItemRetry, defaultExpanded = false, className,\n}: MultiItemDownloadCardProps) {\n const [open, setOpen] = useState(defaultExpanded);\n\n const summary = useMemo(() => {\n const failed = items.filter((i) => i.status === \"failed\");\n const done = items.filter((i) => i.status === \"done\");\n const active = items.filter((i) => i.status === \"downloading\");\n const paused = items.filter((i) => i.status === \"paused\");\n const verifying = items.filter((i) => i.status === \"verifying\");\n\n const status: DownloadStatus =\n failed.length ? \"failed\"\n : done.length === items.length ? \"done\"\n : active.length ? \"downloading\"\n : verifying.length ? \"verifying\"\n : paused.length && paused.length + done.length === items.length ? \"paused\"\n : \"queued\";\n\n const knownSizes = items.every((i) => i.size !== undefined);\n const total = items.reduce((sum, i) => sum + (i.size ?? 0), 0);\n const transferred = items.reduce(\n (sum, i) => sum + (i.status === \"done\" ? (i.size ?? 0) : (i.progress ?? 0) * (i.size ?? 0)),\n 0,\n );\n /* Without sizes, a mean of percentages is the best available — and it is only fair\n because we then don't claim a byte count either. */\n const progress = knownSizes && total > 0\n ? transferred / total\n : items.reduce((sum, i) => sum + (i.status === \"done\" ? 1 : i.progress ?? 0), 0) / Math.max(1, items.length);\n\n const speed = active.reduce((sum, i) => sum + (i.speed ?? 0), 0);\n const eta = speed > 0 && knownSizes ? (total - transferred) / speed : undefined;\n\n return { status, progress, total, transferred, speed, eta, knownSizes, doneCount: done.length, failedCount: failed.length };\n }, [items]);\n\n const pct = Math.round(summary.progress * 100);\n const isDone = summary.status === \"done\";\n const isFailed = summary.status === \"failed\";\n\n const line = isFailed\n ? `${summary.failedCount} of ${items.length} failed`\n : isDone\n ? `${items.length} files · ${summary.knownSizes ? bytes(summary.total) : \"\"}`.trim()\n : [\n `${summary.doneCount} of ${items.length} files`,\n summary.knownSizes ? `${bytes(summary.transferred)} of ${bytes(summary.total)}` : undefined,\n summary.speed ? `${bytes(summary.speed)}/s` : undefined,\n duration(summary.eta),\n ].filter(Boolean).join(\" · \");\n\n return (\n <div className={cn(\"overflow-hidden rounded-xl border border-line bg-surface-1\", className)}>\n <div className=\"flex items-center gap-3 p-3\">\n <span\n className={cn(\n \"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border\",\n isDone ? \"border-accent/30 bg-accent/12 text-accent\"\n : isFailed ? \"border-danger/30 bg-danger/12 text-danger\"\n : \"border-line bg-fill-2 text-fg-3\",\n )}\n >\n {isDone ? <Check size={18} /> : isFailed ? <AlertTriangle size={18} /> : summary.status === \"verifying\" ? <Spinner size=\"md\" /> : <Download size={18} />}\n </span>\n\n <div className=\"min-w-0 flex-1 space-y-1.5\">\n <div className=\"flex items-baseline justify-between gap-3\">\n <p className=\"min-w-0 truncate text-base font-medium text-fg\">{title}</p>\n {!isDone && !isFailed && <span className=\"shrink-0 text-sm tabular-nums text-fg-2\">{pct}%</span>}\n </div>\n {detail && <p className=\"truncate text-sm text-fg-3\">{detail}</p>}\n {!isDone && !isFailed && (\n <Progress value={summary.status === \"queued\" ? undefined : pct} size=\"sm\" />\n )}\n <p className={cn(\"truncate text-sm tabular-nums\", isFailed ? \"text-danger\" : \"text-fg-3\")}>{line}</p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-1\">\n {summary.status === \"downloading\" && onPauseAll && (\n <IconButton label={`Pause ${title}`} size=\"sm\" onClick={onPauseAll}><Pause size={16} /></IconButton>\n )}\n {summary.status === \"paused\" && onResumeAll && (\n <IconButton label={`Resume ${title}`} size=\"sm\" onClick={onResumeAll}><Play size={16} /></IconButton>\n )}\n {!isDone && onCancelAll && (\n <IconButton label={`Cancel ${title}`} size=\"sm\" onClick={onCancelAll}><X size={16} /></IconButton>\n )}\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n aria-expanded={open}\n className=\"flex w-full items-center gap-1.5 border-t border-line px-3 py-2 text-sm text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg-2\"\n >\n <ChevronDown size={14} className={cn(\"shrink-0 transition-transform motion-quick\", open && \"rotate-180\")} />\n {open ? \"Hide files\" : `Show ${items.length} files`}\n {summary.failedCount > 0 && (\n <span className=\"ml-auto shrink-0 rounded-md bg-danger/12 px-1.5 py-0.5 text-2xs font-medium text-danger\">\n {summary.failedCount} failed\n </span>\n )}\n </button>\n\n <AnimatePresence initial={false}>\n {open && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={m.collapse}\n className=\"overflow-hidden\"\n >\n <div className=\"space-y-1.5 border-t border-line bg-surface/40 p-2\">\n {items.map((item) => (\n <DownloadItem\n key={item.id}\n name={item.name}\n detail={item.detail}\n status={item.status}\n progress={item.progress}\n size={item.size}\n speed={item.speed}\n eta={item.eta}\n error={item.error}\n onPause={onItemPause ? () => onItemPause(item.id) : undefined}\n onResume={onItemResume ? () => onItemResume(item.id) : undefined}\n onCancel={onItemCancel ? () => onItemCancel(item.id) : undefined}\n onRetry={onItemRetry ? () => onItemRetry(item.id) : undefined}\n className=\"border-line/60 bg-fill/60\"\n />\n ))}\n </div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n","import { useRef, type KeyboardEvent } from \"react\";\nimport { Minus, Plus } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { inputSurface } from \"./Input\";\n\nexport interface NumberInputProps {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Decimal places to display. Inferred from `step` when omitted. */\n precision?: number;\n /** Shown after the number — \"tokens\", \"×\", \"s\". */\n suffix?: string;\n disabled?: boolean;\n id?: string;\n className?: string;\n}\n\n/**\n * A number field with real steppers. Arrow keys step, Shift+Arrow steps by ten,\n * and the value is clamped on commit rather than silently accepting nonsense.\n */\nexport function NumberInput({\n value, onChange, min = -Infinity, max = Infinity, step = 1, precision, suffix, disabled, id, className,\n}: NumberInputProps) {\n const field = useFieldContext();\n const inputRef = useRef<HTMLInputElement>(null);\n const decimals = precision ?? (String(step).split(\".\")[1]?.length ?? 0);\n\n const clamp = (n: number) => Math.min(max, Math.max(min, n));\n const commit = (n: number) => {\n if (Number.isNaN(n)) return;\n onChange(Number(clamp(n).toFixed(decimals)));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n const delta = event.key === \"ArrowUp\" ? 1 : event.key === \"ArrowDown\" ? -1 : 0;\n if (!delta) return;\n event.preventDefault();\n commit(value + delta * step * (event.shiftKey ? 10 : 1));\n };\n\n return (\n <div className={cn(inputSurface, \"control-md flex items-center gap-1 px-1\", disabled && \"opacity-40\", className)}>\n <button\n type=\"button\"\n onClick={() => commit(value - step)}\n disabled={disabled || value <= min}\n aria-label=\"Decrease\"\n className=\"touch-target flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg disabled:pointer-events-none disabled:opacity-30\"\n >\n <Minus size={16} />\n </button>\n <input\n ref={inputRef}\n id={id ?? field?.id}\n type=\"text\"\n inputMode=\"decimal\"\n value={value.toFixed(decimals)}\n disabled={disabled}\n aria-describedby={field?.describedBy}\n onChange={(event) => commit(Number(event.target.value.replace(\",\", \".\")))}\n onKeyDown={onKeyDown}\n className=\"min-w-0 flex-1 bg-transparent text-center text-base tabular-nums text-fg outline-none\"\n />\n {suffix && <span className=\"shrink-0 pr-1 text-sm text-fg-3\">{suffix}</span>}\n <button\n type=\"button\"\n onClick={() => commit(value + step)}\n disabled={disabled || value >= max}\n aria-label=\"Increase\"\n className=\"touch-target flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg disabled:pointer-events-none disabled:opacity-30\"\n >\n <Plus size={16} />\n </button>\n </div>\n );\n}\n","import { ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface PaginationProps {\n page: number;\n pageCount: number;\n onChange: (page: number) => void;\n /** How many numbers to show around the current page. */\n siblings?: number;\n className?: string;\n}\n\nfunction range(from: number, to: number) {\n return Array.from({ length: Math.max(0, to - from + 1) }, (_, i) => from + i);\n}\n\n/** Numbered paging, for lists where \"load more\" loses your place — logs, search results. */\nexport function Pagination({ page, pageCount, onChange, siblings = 1, className }: PaginationProps) {\n if (pageCount <= 1) return null;\n\n const start = Math.max(2, page - siblings);\n const end = Math.min(pageCount - 1, page + siblings);\n const items: (number | \"gap\")[] = [\n 1,\n ...(start > 2 ? ([\"gap\"] as const) : []),\n ...range(start, end),\n ...(end < pageCount - 1 ? ([\"gap\"] as const) : []),\n ...(pageCount > 1 ? [pageCount] : []),\n ];\n\n const step = (delta: number) => onChange(Math.min(pageCount, Math.max(1, page + delta)));\n\n return (\n <nav aria-label=\"Pagination\" className={cn(\"flex items-center gap-1\", className)}>\n <button\n type=\"button\"\n onClick={() => step(-1)}\n disabled={page <= 1}\n aria-label=\"Previous page\"\n className=\"touch-target flex h-8 w-8 items-center justify-center rounded-lg text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg disabled:pointer-events-none disabled:opacity-30\"\n >\n <ChevronLeft size={16} />\n </button>\n {items.map((item, index) =>\n item === \"gap\" ? (\n <span key={`gap-${index}`} aria-hidden=\"true\" className=\"px-1 text-sm text-fg-4\">\n …\n </span>\n ) : (\n <button\n key={item}\n type=\"button\"\n onClick={() => onChange(item)}\n aria-current={item === page ? \"page\" : undefined}\n aria-label={`Page ${item}`}\n className={cn(\n \"touch-target h-8 min-w-8 rounded-lg px-2 text-sm tabular-nums transition-colors\",\n item === page ? \"bg-fill-3 font-medium text-fg\" : \"text-fg-3 hover:bg-fill-2 hover:text-fg\",\n )}\n >\n {item}\n </button>\n ),\n )}\n <button\n type=\"button\"\n onClick={() => step(1)}\n disabled={page >= pageCount}\n aria-label=\"Next page\"\n className=\"touch-target flex h-8 w-8 items-center justify-center rounded-lg text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg disabled:pointer-events-none disabled:opacity-30\"\n >\n <ChevronRight size={16} />\n </button>\n </nav>\n );\n}\n","import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type PanelTone = \"neutral\" | \"subtle\" | \"accent\" | \"info\" | \"warning\" | \"danger\" | \"secondary\";\n\nexport interface PanelProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n title?: ReactNode;\n description?: ReactNode;\n tone?: PanelTone;\n /** Right of the title — a switch, a badge, a link. */\n action?: ReactNode;\n /** Raise contrast for use over a photo or gradient. */\n onSurface?: boolean;\n children?: ReactNode;\n}\n\nconst toneClass: Record<PanelTone, string> = {\n neutral: \"border-line bg-surface-1\",\n subtle: \"border-line bg-surface-1/60\",\n accent: \"border-accent/30 bg-accent/8\",\n info: \"border-info/30 bg-info/8\",\n warning: \"border-warning/30 bg-warning/8\",\n danger: \"border-danger/30 bg-danger/8\",\n secondary: \"border-secondary/30 bg-secondary/8\",\n};\n\nconst titleTone: Record<PanelTone, string> = {\n neutral: \"text-fg\",\n subtle: \"text-fg-2\",\n accent: \"text-accent\",\n info: \"text-info\",\n warning: \"text-warning\",\n danger: \"text-danger\",\n secondary: \"text-secondary\",\n};\n\n/**\n * A titled container with a tone. Alert is a notice you read and dismiss; Panel is a\n * region you put things in — the chat widgets, a grouped set of settings, a callout\n * with controls inside.\n */\nexport function Panel({ title, description, tone = \"neutral\", action, onSurface, className, children, ...rest }: PanelProps) {\n return (\n <section\n className={cn(\"flex flex-col gap-2 rounded-xl border px-3.5 py-3\", toneClass[tone], onSurface && \"backdrop-blur-md\", className)}\n {...rest}\n >\n {(title || description || action) && (\n <header className=\"flex items-start gap-2\">\n <div className=\"min-w-0 flex-1 space-y-0.5\">\n {title && <h3 className={cn(\"truncate text-base font-semibold\", titleTone[tone])}>{title}</h3>}\n {description && <p className=\"text-sm leading-snug text-fg-3\">{description}</p>}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </header>\n )}\n {children}\n </section>\n );\n}\n","import { useId, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type PartitionTone = \"accent\" | \"info\" | \"secondary\" | \"warning\" | \"danger\" | \"neutral\";\n\nexport interface Partition {\n id: string;\n label: ReactNode;\n value: number;\n /** A semantic tone, or any CSS colour when the segment stands for something with its own. */\n tone?: PartitionTone;\n color?: string;\n}\n\nexport interface PartitionBarProps {\n segments: readonly Partition[];\n /** Denominator. Defaults to the sum, making the bar a share-of-total. */\n total?: number;\n /** Format each value — bytes, tokens, a currency. Percentages by default. */\n format?: (value: number, share: number) => string;\n /** `below` labels each segment under the bar; `legend` wraps them into rows. */\n labels?: \"below\" | \"legend\" | \"none\";\n /**\n * Under this share, a label is narrower than its own word. `below` falls back to\n * `legend` for the whole row rather than truncating some labels and not others.\n */\n minLabelShare?: number;\n size?: \"sm\" | \"md\" | \"lg\";\n /** Leave the unused remainder visible as an empty track. */\n showRemainder?: boolean;\n \"aria-label\"?: string;\n className?: string;\n}\n\nconst toneVar: Record<PartitionTone, string> = {\n accent: \"var(--color-accent)\",\n info: \"var(--color-info)\",\n secondary: \"var(--color-secondary)\",\n warning: \"var(--color-warning)\",\n danger: \"var(--color-danger)\",\n neutral: \"var(--color-fg-3)\",\n};\n\nconst height = { sm: \"h-1.5\", md: \"h-2.5\", lg: \"h-3.5\" };\n\n/**\n * A bar split into named parts: where storage went, which providers answered, how a\n * context window is spent. Progress answers \"how far\"; a Meter answers \"how much is\n * left\"; this answers \"of what it is made\".\n *\n * Segments are separated by a real gap rather than a border, so two adjacent colours\n * never read as one — and each keeps its own rounded ends, which is what makes the\n * parts legible at 6px tall.\n */\nexport function PartitionBar({\n segments, total, format, labels = \"below\", minLabelShare = 0.12, size = \"md\", showRemainder, className, ...aria\n}: PartitionBarProps) {\n const id = useId();\n const sum = segments.reduce((acc, s) => acc + Math.max(0, s.value), 0);\n const denominator = total ?? sum;\n const share = (value: number) => (denominator > 0 ? Math.max(0, value) / denominator : 0);\n const remainder = Math.max(0, denominator - sum);\n\n /* One truncated label among readable ones looks like a bug; the whole row moving to a\n legend looks like a decision. */\n const tooNarrow = segments.some((s) => share(s.value) > 0 && share(s.value) < minLabelShare);\n const resolvedLabels = labels === \"below\" && tooNarrow ? \"legend\" : labels;\n\n const text = (segment: Partition) =>\n format ? format(segment.value, share(segment.value)) : `${Math.round(share(segment.value) * 100)}%`;\n\n const colourOf = (segment: Partition) => segment.color ?? toneVar[segment.tone ?? \"neutral\"];\n\n return (\n <div className={cn(\"w-full\", className)}>\n <div\n role=\"img\"\n aria-label={\n aria[\"aria-label\"] ??\n segments.map((s) => `${typeof s.label === \"string\" ? s.label : s.id} ${text(s)}`).join(\", \")\n }\n className={cn(\"flex w-full items-stretch gap-1\", height[size])}\n >\n {segments.map((segment) => {\n const fraction = share(segment.value);\n if (fraction <= 0) return null;\n return (\n <div\n key={segment.id}\n className=\"min-w-1 rounded-full\"\n style={{ flexGrow: fraction, flexBasis: 0, background: colourOf(segment) }}\n />\n );\n })}\n {showRemainder && remainder > 0 && (\n <div className=\"min-w-1 rounded-full bg-fill-3\" style={{ flexGrow: share(remainder), flexBasis: 0 }} />\n )}\n </div>\n\n {resolvedLabels === \"below\" && (\n <div className=\"mt-2 flex w-full gap-1\">\n {segments.map((segment) => {\n const fraction = share(segment.value);\n if (fraction <= 0) return null;\n return (\n <div key={`${id}-${segment.id}`} className=\"min-w-0 text-center\" style={{ flexGrow: fraction, flexBasis: 0 }}>\n <p className=\"truncate text-sm font-medium\" style={{ color: colourOf(segment) }}>\n {segment.label}\n </p>\n <p className=\"truncate text-2xs tabular-nums text-fg-3\">{text(segment)}</p>\n </div>\n );\n })}\n {showRemainder && remainder > 0 && (\n <div className=\"min-w-0 text-center\" style={{ flexGrow: share(remainder), flexBasis: 0 }}>\n <p className=\"truncate text-sm font-medium text-fg-3\">Free</p>\n <p className=\"truncate text-2xs tabular-nums text-fg-3\">{format ? format(remainder, share(remainder)) : `${Math.round(share(remainder) * 100)}%`}</p>\n </div>\n )}\n </div>\n )}\n\n {resolvedLabels === \"legend\" && (\n <ul className=\"mt-2.5 flex flex-wrap gap-x-4 gap-y-1.5\">\n {segments.map((segment) => (\n <li key={`${id}-${segment.id}`} className=\"flex min-w-0 items-center gap-1.5\">\n <span className=\"h-2 w-2 shrink-0 rounded-full\" style={{ background: colourOf(segment) }} />\n <span className=\"truncate text-sm text-fg-2\">{segment.label}</span>\n <span className=\"shrink-0 text-sm tabular-nums text-fg-3\">{text(segment)}</span>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n","import { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/**\n * Text for screen readers only. Use it to name a control whose meaning is carried\n * visually — never to hide something a sighted user also needs.\n */\nexport function VisuallyHidden({ children }: { children: ReactNode }) {\n return (\n <span className=\"absolute -m-px h-px w-px overflow-hidden whitespace-nowrap border-0 p-0 [clip:rect(0,0,0,0)]\">\n {children}\n </span>\n );\n}\n\nexport interface AspectRatioProps extends HTMLAttributes<HTMLDivElement> {\n /** width / height. 16/9, 1, 3/4. */\n ratio?: number;\n}\n\n/** Reserves the right shape before an image loads, so the layout never jumps. */\nexport const AspectRatio = forwardRef<HTMLDivElement, AspectRatioProps>(function AspectRatio(\n { ratio = 1, className, style, ...rest },\n ref,\n) {\n return <div ref={ref} className={cn(\"relative w-full overflow-hidden\", className)} style={{ aspectRatio: ratio, ...style }} {...rest} />;\n});\n","import ReactMarkdown from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { cn } from \"../lib/cn\";\nimport { CodeBlock } from \"./CodeBlock\";\n\nexport interface ProseProps {\n children: string;\n /** Message body vs. a full document (README, changelog). */\n size?: \"sm\" | \"md\";\n className?: string;\n}\n\n/**\n * Markdown on our type scale. Replaces the app's MarkdownRenderer, HfReadmeRenderer and\n * the ~90 lines of `.hf-html-block` CSS in App.css — three renderers with three scales.\n *\n * Raw HTML is not enabled: character definitions and remote READMEs are untrusted text.\n */\nexport function Prose({ children, size = \"md\", className }: ProseProps) {\n const base = size === \"sm\" ? \"text-sm\" : \"text-base\";\n return (\n <div className={cn(base, \"leading-relaxed text-fg\", className)}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n h1: ({ children: c }) => <h1 className=\"mb-2 mt-5 text-xl font-bold tracking-tight text-fg first:mt-0\">{c}</h1>,\n h2: ({ children: c }) => <h2 className=\"mb-2 mt-5 text-lg font-semibold tracking-tight text-fg first:mt-0\">{c}</h2>,\n h3: ({ children: c }) => <h3 className=\"mb-1.5 mt-4 text-base font-semibold text-fg first:mt-0\">{c}</h3>,\n p: ({ children: c }) => <p className=\"my-2 first:mt-0 last:mb-0\">{c}</p>,\n em: ({ children: c }) => <em className=\"text-fg-2\">{c}</em>,\n strong: ({ children: c }) => <strong className=\"font-semibold text-fg\">{c}</strong>,\n a: ({ children: c, href }) => (\n <a href={href} target=\"_blank\" rel=\"noreferrer noopener\" className=\"text-accent underline decoration-accent/40 underline-offset-2 hover:decoration-accent\">\n {c}\n </a>\n ),\n ul: ({ children: c }) => <ul className=\"my-2 list-disc space-y-1 pl-5 marker:text-fg-4\">{c}</ul>,\n ol: ({ children: c }) => <ol className=\"my-2 list-decimal space-y-1 pl-5 marker:text-fg-4\">{c}</ol>,\n blockquote: ({ children: c }) => <blockquote className=\"my-3 border-l-2 border-line-2 pl-3 text-fg-2\">{c}</blockquote>,\n hr: () => <hr className=\"my-4 border-line\" />,\n code: ({ className: cls, children: c }) => {\n const text = String(c).replace(/\\n$/, \"\");\n /* A fenced block gets a language class; inline code does not. */\n if (!cls && !text.includes(\"\\n\")) {\n return <code className=\"rounded-md border border-line bg-fill px-1 py-0.5 font-mono text-[0.9em] text-fg-2\">{text}</code>;\n }\n return <CodeBlock code={text} label={cls?.replace(\"language-\", \"\")} className=\"my-3\" />;\n },\n pre: ({ children: c }) => <>{c}</>,\n table: ({ children: c }) => (\n <div className=\"scrollbar-thin my-3 overflow-x-auto rounded-xl border border-line\">\n <table className=\"w-full border-collapse text-left text-sm\">{c}</table>\n </div>\n ),\n thead: ({ children: c }) => <thead className=\"border-b border-line bg-fill\">{c}</thead>,\n th: ({ children: c }) => <th className=\"px-3 py-2 font-medium text-fg-3\">{c}</th>,\n td: ({ children: c }) => <td className=\"border-b border-line px-3 py-2 text-fg-2 last:border-0\">{c}</td>,\n img: ({ src, alt }) => <img src={typeof src === \"string\" ? src : undefined} alt={alt ?? \"\"} className=\"my-3 max-w-full rounded-xl border border-line\" />,\n }}\n >\n {children}\n </ReactMarkdown>\n </div>\n );\n}\n","import { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\ninterface RadioGroupContextValue<T extends string = string> {\n name: string;\n value: T;\n onChange: (value: T) => void;\n disabled?: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport interface RadioGroupProps<T extends string> {\n value: T;\n onChange: (value: T) => void;\n disabled?: boolean;\n orientation?: \"vertical\" | \"horizontal\";\n \"aria-label\"?: string;\n className?: string;\n children: ReactNode;\n}\n\nexport function RadioGroup<T extends string>({ value, onChange, disabled, orientation = \"vertical\", className, children, ...aria }: RadioGroupProps<T>) {\n const name = useId();\n return (\n <RadioGroupContext.Provider value={{ name, value, onChange: onChange as (v: string) => void, disabled }}>\n <div role=\"radiogroup\" aria-label={aria[\"aria-label\"]} className={cn(\"flex\", orientation === \"vertical\" ? \"flex-col gap-2.5\" : \"flex-row flex-wrap gap-4\", className)}>\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n\nexport interface RadioProps {\n value: string;\n label: ReactNode;\n description?: ReactNode;\n disabled?: boolean;\n}\n\n/** Uses a real <input type=\"radio\"> so arrow-key group navigation comes from the browser. */\nexport function Radio({ value, label, description, disabled }: RadioProps) {\n const group = useContext(RadioGroupContext);\n if (!group) throw new Error(\"Radio must be used inside <RadioGroup>\");\n const checked = group.value === value;\n const inert = disabled || group.disabled;\n return (\n <label className={cn(\"flex cursor-pointer items-start gap-2.5\", inert && \"cursor-not-allowed opacity-40\")}>\n <span className=\"relative mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center\">\n <input\n type=\"radio\"\n name={group.name}\n value={value}\n checked={checked}\n disabled={inert}\n onChange={() => group.onChange(value)}\n className=\"peer absolute inset-0 cursor-pointer opacity-0\"\n />\n <span\n aria-hidden=\"true\"\n className={cn(\n \"flex h-5 w-5 items-center justify-center rounded-full border transition-colors motion-instant\",\n \"peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-accent\",\n checked ? \"border-accent\" : \"border-line-3 bg-fill peer-hover:border-fg-3\",\n )}\n >\n <span className={cn(\"h-2.5 w-2.5 rounded-full bg-accent transition-transform motion-instant\", checked ? \"scale-100\" : \"scale-0\")} />\n </span>\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-base text-fg\">{label}</span>\n {description && <span className=\"block text-sm text-fg-3\">{description}</span>}\n </span>\n </label>\n );\n}\n","import { useCallback, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface ResizableProps {\n /** Fixed-size pane. */\n panel: ReactNode;\n /** Fills whatever is left. */\n children: ReactNode;\n side?: \"left\" | \"right\";\n defaultSize?: number;\n minSize?: number;\n maxSize?: number;\n /** Persisted key, so a person's split survives a reload. */\n storageKey?: string;\n className?: string;\n}\n\n/**\n * A draggable split, for desktop screens that pair a list with an inspector — the\n * lorebook trigger preview does this with a hard-coded width. The handle is a real\n * separator: arrow keys resize it, so it isn't mouse-only.\n */\nexport function Resizable({\n panel, children, side = \"left\", defaultSize = 320, minSize = 200, maxSize = 640, storageKey, className,\n}: ResizableProps) {\n const [size, setSize] = useState(() => {\n if (!storageKey || typeof localStorage === \"undefined\") return defaultSize;\n try {\n const stored = Number(localStorage.getItem(storageKey));\n return Number.isFinite(stored) && stored > 0 ? stored : defaultSize;\n } catch {\n return defaultSize;\n }\n });\n const dragging = useRef(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const clamp = useCallback((n: number) => Math.min(maxSize, Math.max(minSize, n)), [minSize, maxSize]);\n\n const commit = useCallback(\n (next: number) => {\n const value = clamp(next);\n setSize(value);\n if (storageKey) {\n try { localStorage.setItem(storageKey, String(value)); } catch { /* private mode */ }\n }\n },\n [clamp, storageKey],\n );\n\n useEffect(() => {\n const onMove = (event: PointerEvent) => {\n if (!dragging.current) return;\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n commit(side === \"left\" ? event.clientX - rect.left : rect.right - event.clientX);\n };\n const onUp = () => {\n dragging.current = false;\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n return () => {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n };\n }, [commit, side]);\n\n const handle = (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-valuenow={size}\n aria-valuemin={minSize}\n aria-valuemax={maxSize}\n aria-label=\"Resize panel\"\n tabIndex={0}\n onPointerDown={() => {\n dragging.current = true;\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n }}\n onKeyDown={(event) => {\n const delta = event.key === \"ArrowRight\" ? 16 : event.key === \"ArrowLeft\" ? -16 : 0;\n if (!delta) return;\n event.preventDefault();\n commit(size + (side === \"left\" ? delta : -delta));\n }}\n onDoubleClick={() => commit(defaultSize)}\n className=\"group relative w-px shrink-0 cursor-col-resize bg-line outline-none\"\n >\n <span className=\"absolute inset-y-0 -left-1.5 -right-1.5\" />\n <span className=\"absolute inset-y-0 left-0 w-px bg-accent opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100\" />\n </div>\n );\n\n return (\n <div ref={containerRef} className={cn(\"flex min-h-0 w-full\", side === \"right\" && \"flex-row-reverse\", className)}>\n <div style={{ width: size }} className=\"min-w-0 shrink-0 overflow-hidden\">\n {panel}\n </div>\n {handle}\n <div className=\"min-w-0 flex-1 overflow-hidden\">{children}</div>\n </div>\n );\n}\n","import { forwardRef, useRef, type InputHTMLAttributes } from \"react\";\nimport { Search, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { Kbd } from \"./Kbd\";\nimport { Spinner } from \"./Spinner\";\n\nexport interface SearchFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"value\" | \"type\" | \"size\"> {\n value: string;\n onChange: (value: string) => void;\n loading?: boolean;\n /** Hint the keyboard shortcut that focuses this field. Hidden once there is text. */\n shortcut?: string;\n size?: \"sm\" | \"md\";\n}\n\n/**\n * Search with a clear button and Escape-to-clear. The app repeats this markup in the\n * page header, the library, discovery and the model browser.\n */\nexport const SearchField = forwardRef<HTMLInputElement, SearchFieldProps>(function SearchField(\n { value, onChange, loading, shortcut, size = \"md\", placeholder = \"Search\", className, ...rest },\n ref,\n) {\n const inner = useRef<HTMLInputElement>(null);\n return (\n <div className=\"relative\">\n <Search size={size === \"sm\" ? 14 : 16} className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-fg-3\" />\n <input\n ref={(node) => {\n inner.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"search\"\n value={value}\n placeholder={placeholder}\n onChange={(event) => onChange(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\" && value) {\n event.preventDefault();\n onChange(\"\");\n }\n }}\n className={cn(\n \"w-full rounded-xl border border-line bg-fill text-fg placeholder:text-fg-4\",\n \"transition-[border-color,background-color] motion-instant\",\n \"hover:border-line-2 focus:border-accent focus:bg-fill-2 focus:outline-none focus:ring-1 focus:ring-accent/35\",\n \"[&::-webkit-search-cancel-button]:hidden\",\n size === \"sm\" ? \"h-8 pl-8 pr-8 text-sm\" : \"h-10 pl-9 pr-9 text-base\",\n className,\n )}\n {...rest}\n />\n {value ? (\n <button\n type=\"button\"\n onClick={() => { onChange(\"\"); inner.current?.focus(); }}\n aria-label=\"Clear search\"\n className=\"tap-target absolute right-1.5 top-1/2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-lg text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg\"\n >\n <X size={14} />\n </button>\n ) : loading ? (\n <span className=\"absolute right-3 top-1/2 -translate-y-1/2\"><Spinner size=\"sm\" /></span>\n ) : shortcut ? (\n <span className=\"absolute right-2 top-1/2 hidden -translate-y-1/2 hoverable:block\"><Kbd>{shortcut}</Kbd></span>\n ) : null}\n </div>\n );\n});\n","import { useId, type KeyboardEvent, type ReactNode } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\nexport interface SegmentedOption<T extends string> {\n value: T;\n label: ReactNode;\n icon?: ReactNode;\n}\n\nexport interface SegmentedProps<T extends string> {\n options: readonly SegmentedOption<T>[];\n value: T;\n onChange: (value: T) => void;\n size?: \"sm\" | \"md\";\n block?: boolean;\n \"aria-label\"?: string;\n className?: string;\n}\n\nexport function Segmented<T extends string>({\n options,\n value,\n onChange,\n size = \"md\",\n block,\n className,\n ...aria\n}: SegmentedProps<T>) {\n const layoutId = useId();\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const index = options.findIndex((option) => option.value === value);\n if (index < 0) return;\n const delta = event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (!delta) return;\n event.preventDefault();\n const next = options[(index + delta + options.length) % options.length];\n onChange(next.value);\n (event.currentTarget.querySelector<HTMLButtonElement>(`[data-value=\"${next.value}\"]`))?.focus();\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={aria[\"aria-label\"]}\n onKeyDown={onKeyDown}\n className={cn(\n \"inline-flex rounded-xl border border-line bg-fill p-1\",\n block && \"flex w-full\",\n className,\n )}\n >\n {options.map((option) => {\n const selected = option.value === value;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n tabIndex={selected ? 0 : -1}\n data-value={option.value}\n onClick={() => onChange(option.value)}\n className={cn(\n \"relative inline-flex items-center justify-center gap-1.5 rounded-lg font-medium transition-colors motion-instant\",\n size === \"sm\" ? \"h-7 px-2.5 text-sm\" : \"h-8 px-3.5 text-sm\",\n block && \"flex-1\",\n selected ? \"text-fg\" : \"text-fg-3 hover:text-fg-2\",\n )}\n >\n {selected && (\n <motion.span\n layoutId={layoutId}\n transition={m.settle}\n className=\"absolute inset-0 rounded-lg bg-fill-3 shadow-sm\"\n />\n )}\n <span className=\"relative inline-flex items-center gap-1.5\">\n {option.icon}\n {option.label}\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n","import { forwardRef, type SelectHTMLAttributes } from \"react\";\nimport { ChevronDown } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { inputSurface } from \"./Input\";\n\nexport interface SelectOption<T extends string = string> {\n value: T;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, \"size\"> {\n options: readonly SelectOption[];\n placeholder?: string;\n}\n\n/**\n * Native select with our surface. On phones this opens the OS picker, which beats any\n * custom listbox for reach and accessibility. Use Menu for command-style lists.\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(\n { options, placeholder, className, id, value, defaultValue, ...rest },\n ref,\n) {\n const field = useFieldContext();\n const empty = (value ?? defaultValue ?? \"\") === \"\";\n return (\n <div className=\"relative\">\n <select\n ref={ref}\n id={id ?? field?.id}\n value={value}\n defaultValue={placeholder && value === undefined && defaultValue === undefined ? \"\" : defaultValue}\n aria-describedby={rest[\"aria-describedby\"] ?? field?.describedBy}\n aria-invalid={rest[\"aria-invalid\"] ?? (field?.invalid || undefined)}\n className={cn(inputSurface, \"control-md appearance-none pl-3.5 pr-10\", empty && placeholder && \"text-fg-4\", className)}\n {...rest}\n >\n {placeholder && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled} className=\"bg-surface-el text-fg\">\n {option.label}\n </option>\n ))}\n </select>\n <ChevronDown size={16} className=\"pointer-events-none absolute right-3.5 top-1/2 -translate-y-1/2 text-fg-3\" />\n </div>\n );\n});\n","import { useCallback, useEffect, useId, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from \"react\";\nimport { Check, ChevronDown, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { inputSurface } from \"./Input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./Popover\";\n\nexport interface SelectMenuOption<T extends string = string> {\n value: T;\n label: string;\n /** Second line under the label. */\n description?: string;\n icon?: ReactNode;\n /** Right-aligned slot — a badge, a size, a shortcut. */\n meta?: ReactNode;\n group?: string;\n disabled?: boolean;\n}\n\ninterface BaseProps<T extends string> {\n options: readonly SelectMenuOption<T>[];\n placeholder?: string;\n /** Show the chosen option's icon in the closed trigger. Default true. */\n triggerIcon?: boolean;\n disabled?: boolean;\n id?: string;\n className?: string;\n /** Width of the open list. Defaults to the trigger's width. */\n menuClassName?: string;\n}\n\nexport interface SingleSelectMenuProps<T extends string> extends BaseProps<T> {\n multiple?: false;\n value: T | null;\n onChange: (value: T | null) => void;\n clearable?: boolean;\n}\n\nexport interface MultiSelectMenuProps<T extends string> extends BaseProps<T> {\n multiple: true;\n value: readonly T[];\n onChange: (value: T[]) => void;\n /** Collapse to \"3 selected\" past this many. Default 2. */\n maxLabels?: number;\n}\n\nexport type SelectMenuProps<T extends string> = SingleSelectMenuProps<T> | MultiSelectMenuProps<T>;\n\n/**\n * Our own select. `Select` stays for the plain cases — it opens the OS picker on a\n * phone, which nothing custom beats for reach. Use this one when the options need\n * icons, descriptions, groups or multi-select.\n *\n * It keeps what a native select gives you for free: typeahead (type \"ge\" to jump to\n * Gemma), Home/End, and the listbox pattern with aria-activedescendant, so focus never\n * leaves the trigger and screen readers announce the active option.\n */\nexport function SelectMenu<T extends string>(props: SelectMenuProps<T>) {\n const {\n options, placeholder = \"Select…\", triggerIcon = true, disabled, id, className, menuClassName,\n } = props;\n const multiple = props.multiple === true;\n const field = useFieldContext();\n const listId = useId();\n const [open, setOpen] = useState(false);\n const [active, setActive] = useState(0);\n const listRef = useRef<HTMLDivElement>(null);\n const typeahead = useRef({ query: \"\", at: 0 });\n\n const selectedValues = useMemo<readonly T[]>(\n () => (multiple ? (props as MultiSelectMenuProps<T>).value : [(props as SingleSelectMenuProps<T>).value].filter(Boolean) as T[]),\n [multiple, props],\n );\n\n const enabled = useMemo(() => options.filter((o) => !o.disabled), [options]);\n const grouped = useMemo(() => {\n const map = new Map<string, SelectMenuOption<T>[]>();\n for (const option of options) {\n const key = option.group ?? \"\";\n const bucket = map.get(key);\n if (bucket) bucket.push(option);\n else map.set(key, [option]);\n }\n return Array.from(map.entries());\n }, [options]);\n\n const select = useCallback(\n (option: SelectMenuOption<T>) => {\n if (option.disabled) return;\n if (multiple) {\n const { value, onChange } = props as MultiSelectMenuProps<T>;\n onChange(value.includes(option.value) ? value.filter((v) => v !== option.value) : [...value, option.value]);\n return;\n }\n (props as SingleSelectMenuProps<T>).onChange(option.value);\n setOpen(false);\n },\n [multiple, props],\n );\n\n useEffect(() => {\n if (!open) return;\n const first = enabled.findIndex((o) => selectedValues.includes(o.value));\n setActive(first < 0 ? 0 : first);\n }, [open, enabled, selectedValues]);\n\n useEffect(() => {\n if (open) listRef.current?.querySelector('[data-active=\"true\"]')?.scrollIntoView({ block: \"nearest\" });\n }, [open, active]);\n\n const move = (delta: number) =>\n setActive((i) => {\n if (enabled.length === 0) return 0;\n return (i + delta + enabled.length) % enabled.length;\n });\n\n const onKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (!open && (event.key === \"ArrowDown\" || event.key === \"Enter\" || event.key === \" \")) {\n event.preventDefault();\n setOpen(true);\n return;\n }\n if (!open) return;\n\n if (event.key === \"ArrowDown\") { event.preventDefault(); move(1); return; }\n if (event.key === \"ArrowUp\") { event.preventDefault(); move(-1); return; }\n if (event.key === \"Home\") { event.preventDefault(); setActive(0); return; }\n if (event.key === \"End\") { event.preventDefault(); setActive(enabled.length - 1); return; }\n if (event.key === \"Enter\" || (event.key === \" \" && !typeahead.current.query)) {\n event.preventDefault();\n if (enabled[active]) select(enabled[active]);\n return;\n }\n if (event.key === \"Tab\") { setOpen(false); return; }\n\n /* Typeahead: printable keys build a prefix that resets after a second, the way a\n native select behaves. Without this, a long model list is only reachable by scroll. */\n if (event.key.length === 1 && !event.metaKey && !event.ctrlKey && !event.altKey) {\n const now = Date.now();\n const state = typeahead.current;\n state.query = now - state.at > 1000 ? event.key : state.query + event.key;\n state.at = now;\n const prefix = state.query.toLowerCase();\n const from = state.query.length === 1 ? active + 1 : active;\n const order = [...enabled.slice(from), ...enabled.slice(0, from)];\n const hit = order.find((o) => o.label.toLowerCase().startsWith(prefix));\n if (hit) setActive(enabled.indexOf(hit));\n }\n };\n\n const selectedOptions = options.filter((o) => selectedValues.includes(o.value));\n const maxLabels = multiple ? (props as MultiSelectMenuProps<T>).maxLabels ?? 2 : 1;\n const triggerLabel =\n selectedOptions.length === 0\n ? placeholder\n : multiple && selectedOptions.length > maxLabels\n ? `${selectedOptions.length} selected`\n : selectedOptions.map((o) => o.label).join(\", \");\n\n let index = -1;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger>\n <button\n type=\"button\"\n id={id ?? field?.id}\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={open ? listId : undefined}\n aria-activedescendant={open && enabled[active] ? `${listId}-${enabled[active].value}` : undefined}\n aria-describedby={field?.describedBy}\n aria-invalid={field?.invalid || undefined}\n disabled={disabled}\n onKeyDown={onKeyDown}\n className={cn(inputSurface, \"control-md flex items-center gap-2 pl-3 pr-2 text-left\", className)}\n >\n {triggerIcon && selectedOptions.length === 1 && selectedOptions[0].icon && (\n <span className=\"shrink-0 text-fg-3\">{selectedOptions[0].icon}</span>\n )}\n <span className={cn(\"min-w-0 flex-1 truncate\", selectedOptions.length ? \"text-fg\" : \"text-fg-4\")}>\n {triggerLabel}\n </span>\n {!multiple && (props as SingleSelectMenuProps<T>).clearable && selectedOptions.length > 0 && (\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label=\"Clear selection\"\n onClick={(event) => { event.stopPropagation(); (props as SingleSelectMenuProps<T>).onChange(null); }}\n className=\"tap-target flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-fg-3 hover:bg-fill-2 hover:text-fg\"\n >\n <X size={14} />\n </span>\n )}\n <ChevronDown size={16} className={cn(\"shrink-0 text-fg-3 transition-transform motion-instant\", open && \"rotate-180\")} />\n </button>\n </PopoverTrigger>\n\n <PopoverContent matchWidth className={cn(\"p-0\", menuClassName)}>\n <div ref={listRef} id={listId} role=\"listbox\" aria-multiselectable={multiple || undefined} className=\"scrollbar-thin max-h-72 overflow-y-auto p-1\">\n {options.length === 0 && <p className=\"px-2.5 py-6 text-center text-sm text-fg-3\">Nothing to choose from</p>}\n {grouped.map(([group, list]) => (\n <div key={group || \"_\"}>\n {group && <p className=\"px-2.5 pb-1 pt-2 text-2xs font-medium text-fg-3\">{group}</p>}\n {list.map((option) => {\n const isSelected = selectedValues.includes(option.value);\n if (!option.disabled) index += 1;\n const isActive = !option.disabled && index === active;\n return (\n <div\n key={option.value}\n id={`${listId}-${option.value}`}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled || undefined}\n data-active={isActive}\n onPointerEnter={() => !option.disabled && setActive(enabled.indexOf(option))}\n onClick={() => select(option)}\n className={cn(\n \"flex cursor-pointer items-start gap-2.5 rounded-lg px-2.5 py-2\",\n isActive && \"bg-fill-2\",\n option.disabled && \"cursor-not-allowed opacity-40\",\n )}\n >\n {option.icon && <span className=\"mt-0.5 shrink-0 text-fg-3\">{option.icon}</span>}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-base text-fg\">{option.label}</span>\n {option.description && <span className=\"block truncate text-sm text-fg-3\">{option.description}</span>}\n </span>\n {option.meta && <span className=\"mt-0.5 shrink-0 text-sm text-fg-3\">{option.meta}</span>}\n {isSelected && <Check size={16} className=\"mt-0.5 shrink-0 text-accent\" />}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { forwardRef, type InputHTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\n\nexport interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\" | \"onChange\"> {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Show the current value at the right. Pass a formatter to add units. */\n showValue?: boolean | ((value: number) => string);\n}\n\nexport const Slider = forwardRef<HTMLInputElement, SliderProps>(function Slider(\n { value, onChange, min = 0, max = 100, step = 1, showValue, className, id, style, ...rest },\n ref,\n) {\n const field = useFieldContext();\n const fill = ((value - min) / (max - min)) * 100;\n const label = typeof showValue === \"function\" ? showValue(value) : showValue ? String(value) : null;\n return (\n <div className={cn(\"flex items-center gap-3\", className)}>\n <input\n ref={ref}\n type=\"range\"\n id={id ?? field?.id}\n aria-describedby={field?.describedBy}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={(event) => onChange(Number(event.target.value))}\n className=\"slider min-w-0 flex-1\"\n style={{ [\"--slider-fill\" as string]: `${fill}%`, ...style }}\n {...rest}\n />\n {label !== null && <span className=\"w-10 shrink-0 text-right text-sm tabular-nums text-fg-2\">{label}</span>}\n </div>\n );\n});\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface StatTileProps {\n label: ReactNode;\n value: ReactNode;\n /** A line under the value — the comparison, the unit, the period. */\n sub?: ReactNode;\n /** Percentage change. `up` is not automatically good; pass `goodDirection`. */\n trend?: { value: number; direction: \"up\" | \"down\" };\n /** Which direction should read as positive. Default \"up\". */\n goodDirection?: \"up\" | \"down\";\n icon?: ReactNode;\n highlight?: boolean;\n className?: string;\n}\n\n/**\n * One number with its label. Usage stats, model details, memory counts.\n * The label is sentence case, not tracked-out uppercase — a stat tile is read, not scanned.\n */\nexport function StatTile({ label, value, sub, trend, goodDirection = \"up\", icon, highlight, className }: StatTileProps) {\n const good = trend ? trend.direction === goodDirection : undefined;\n return (\n <div\n className={cn(\n \"rounded-xl border px-3.5 py-3\",\n highlight ? \"border-accent/30 bg-accent/8\" : \"border-line bg-surface-1\",\n className,\n )}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-sm text-fg-3\">\n {icon && <span className=\"shrink-0\">{icon}</span>}\n <span className=\"truncate\">{label}</span>\n </span>\n {trend && (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center rounded-md px-1.5 py-0.5 text-xs font-semibold tabular-nums\",\n good ? \"bg-accent/12 text-accent\" : \"bg-danger/12 text-danger\",\n )}\n >\n {trend.direction === \"up\" ? \"+\" : \"−\"}\n {Math.abs(trend.value)}%\n </span>\n )}\n </div>\n <p className=\"mt-1 truncate text-2xl font-semibold tabular-nums text-fg\">\n {value}\n </p>\n {sub && <p className=\"mt-0.5 truncate text-sm text-fg-3\">{sub}</p>}\n </div>\n );\n}\n\nexport interface KeyValueProps {\n items: readonly { label: ReactNode; value: ReactNode }[];\n /** `rows` stacks label over value on narrow; `inline` keeps them on one line. */\n layout?: \"inline\" | \"rows\";\n className?: string;\n}\n\n/** Detail lists — model metadata, image properties, request info. */\nexport function KeyValue({ items, layout = \"inline\", className }: KeyValueProps) {\n return (\n <dl className={cn(\"divide-y divide-line\", className)}>\n {items.map((item, index) => (\n <div\n key={index}\n className={cn(\"py-2\", layout === \"inline\" ? \"flex items-baseline justify-between gap-4\" : \"space-y-0.5\")}\n >\n <dt className=\"shrink-0 text-sm text-fg-3\">{item.label}</dt>\n <dd className={cn(\"min-w-0 text-base text-fg\", layout === \"inline\" && \"truncate text-right\")}>{item.value}</dd>\n </div>\n ))}\n </dl>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface Step {\n id: string;\n label: string;\n icon?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: readonly Step[];\n /** Index of the step in progress. Everything before it counts as done. */\n current: number;\n /** Jump back to a completed step. Forward jumps are never offered. */\n onStepClick?: (index: number) => void;\n /** `bar` is a segmented progress strip; `dots` is a compact row for a sheet header. */\n variant?: \"bar\" | \"dots\";\n className?: string;\n}\n\n/**\n * Progress through a flow. Character creation, onboarding, the engine wizard and the\n * lorebook generator each grew their own; this is the one.\n */\nexport function Stepper({ steps, current, onStepClick, variant = \"bar\", className }: StepperProps) {\n const clamped = Math.max(0, Math.min(current, steps.length - 1));\n\n if (variant === \"dots\") {\n return (\n <div className={cn(\"flex items-center gap-1.5\", className)} role=\"group\" aria-label={`Step ${clamped + 1} of ${steps.length}`}>\n {steps.map((step, index) => (\n <span\n key={step.id}\n aria-current={index === clamped ? \"step\" : undefined}\n className={cn(\n \"h-1.5 rounded-full transition-all motion-slow\",\n index === clamped ? \"w-5 bg-accent\" : index < clamped ? \"w-1.5 bg-accent/50\" : \"w-1.5 bg-fill-3\",\n )}\n />\n ))}\n </div>\n );\n }\n\n return (\n <div className={cn(\"space-y-2.5\", className)}>\n <div className=\"flex items-baseline justify-between gap-3\">\n <p className=\"text-sm text-fg-3\">\n Step {clamped + 1} of {steps.length}\n <span className=\"mx-1.5 text-fg-4\">·</span>\n <span className=\"font-medium text-fg-2\">{steps[clamped]?.label}</span>\n </p>\n <span className=\"shrink-0 text-sm tabular-nums text-fg-3\">\n {Math.round((clamped / Math.max(1, steps.length - 1)) * 100)}%\n </span>\n </div>\n <ol className=\"flex gap-1.5\">\n {steps.map((step, index) => {\n const done = index < clamped;\n const active = index === clamped;\n const reachable = done && onStepClick;\n const Tag = reachable ? \"button\" : \"div\";\n return (\n <li key={step.id} className=\"min-w-0 flex-1\">\n <Tag\n {...(reachable ? { type: \"button\" as const, onClick: () => onStepClick(index) } : {})}\n aria-current={active ? \"step\" : undefined}\n aria-label={reachable ? `Back to ${step.label}` : undefined}\n className={cn(\n \"flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left transition-colors\",\n reachable && \"hover:bg-fill-2\",\n )}\n >\n <motion.span\n layout\n className={cn(\n \"flex h-5 w-5 shrink-0 items-center justify-center rounded-full text-2xs font-semibold\",\n done ? \"bg-accent text-on-accent\" : active ? \"bg-accent/20 text-accent\" : \"bg-fill-3 text-fg-4\",\n )}\n >\n {done ? <Check size={12} strokeWidth={3} /> : step.icon ?? index + 1}\n </motion.span>\n <span className={cn(\"hidden min-w-0 truncate text-sm @md:block\", active ? \"font-medium text-fg\" : done ? \"text-fg-2\" : \"text-fg-4\")}>\n {step.label}\n </span>\n </Tag>\n <span\n aria-hidden=\"true\"\n className={cn(\"mt-1 block h-1 rounded-full transition-colors motion-slow\", done || active ? \"bg-accent\" : \"bg-fill-3\")}\n />\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n","import { motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { useFieldContext } from \"./Field\";\n\nexport interface SwitchProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n id?: string;\n \"aria-label\"?: string;\n className?: string;\n}\n\nexport function Switch({ checked, onChange, disabled, id, className, ...aria }: SwitchProps) {\n const field = useFieldContext();\n return (\n <button\n type=\"button\"\n role=\"switch\"\n id={id ?? field?.id}\n aria-checked={checked}\n aria-describedby={field?.describedBy}\n aria-label={aria[\"aria-label\"]}\n disabled={disabled}\n onClick={() => onChange(!checked)}\n className={cn(\n \"relative inline-flex h-6 w-11 shrink-0 items-center rounded-full p-0.5\",\n \"transition-colors motion-quick\",\n checked ? \"bg-accent\" : \"bg-fill-3 hover:bg-line-3\",\n disabled && \"cursor-not-allowed opacity-40\",\n className,\n )}\n >\n <motion.span\n aria-hidden=\"true\"\n layout\n transition={m.snap}\n className={cn(\"block h-5 w-5 rounded-full bg-knob shadow-sm ring-1 ring-inset ring-black/5\", checked && \"ml-auto\")}\n />\n </button>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { ArrowDown, ArrowUp, ArrowUpDown } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { ScrollArea } from \"./ScrollArea\";\n\nexport interface Column<Row> {\n key: string;\n header: ReactNode;\n /** Cell renderer. Keep it a pure read of the row. */\n cell: (row: Row) => ReactNode;\n align?: \"left\" | \"right\";\n /** Numbers line up only if you say so. */\n numeric?: boolean;\n sortable?: boolean;\n width?: string;\n}\n\nexport interface TableProps<Row> {\n columns: readonly Column<Row>[];\n rows: readonly Row[];\n rowKey: (row: Row) => string;\n sort?: { key: string; direction: \"asc\" | \"desc\" };\n onSortChange?: (sort: { key: string; direction: \"asc\" | \"desc\" }) => void;\n onRowClick?: (row: Row) => void;\n /** Rendered in place of the body when there are no rows. */\n empty?: ReactNode;\n caption?: string;\n className?: string;\n}\n\n/**\n * A real table for tabular data — logs, usage, model lists — instead of a grid of divs.\n * It scrolls inside itself so a wide table never makes the page scroll sideways.\n */\nexport function Table<Row>({\n columns, rows, rowKey, sort, onSortChange, onRowClick, empty, caption, className,\n}: TableProps<Row>) {\n const toggleSort = (key: string) => {\n if (!onSortChange) return;\n onSortChange({ key, direction: sort?.key === key && sort.direction === \"asc\" ? \"desc\" : \"asc\" });\n };\n\n return (\n <div className={cn(\"overflow-hidden rounded-xl border border-line\", className)}>\n <ScrollArea axis=\"x\" bar>\n <table className=\"w-full border-collapse text-left\">\n {caption && <caption className=\"sr-only\">{caption}</caption>}\n <thead>\n <tr className=\"border-b border-line bg-surface-1\">\n {columns.map((column) => (\n <th\n key={column.key}\n scope=\"col\"\n style={column.width ? { width: column.width } : undefined}\n aria-sort={sort?.key === column.key ? (sort.direction === \"asc\" ? \"ascending\" : \"descending\") : undefined}\n className={cn(\"px-3 py-2 text-sm font-medium text-fg-3\", column.align === \"right\" && \"text-right\")}\n >\n {column.sortable && onSortChange ? (\n <button\n type=\"button\"\n onClick={() => toggleSort(column.key)}\n className={cn(\"inline-flex items-center gap-1 rounded-md transition-colors hover:text-fg\", column.align === \"right\" && \"flex-row-reverse\")}\n >\n {column.header}\n {sort?.key === column.key ? (\n sort.direction === \"asc\" ? <ArrowUp size={12} /> : <ArrowDown size={12} />\n ) : (\n <ArrowUpDown size={12} className=\"opacity-40\" />\n )}\n </button>\n ) : (\n column.header\n )}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 ? (\n <tr>\n <td colSpan={columns.length} className=\"px-3 py-10 text-center text-sm text-fg-3\">\n {empty ?? \"Nothing to show\"}\n </td>\n </tr>\n ) : (\n rows.map((row) => (\n <tr\n key={rowKey(row)}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n className={cn(\"border-b border-line last:border-0\", onRowClick && \"cursor-pointer transition-colors hover:bg-fill\")}\n >\n {columns.map((column) => (\n <td\n key={column.key}\n className={cn(\n \"px-3 py-2.5 text-base text-fg-2\",\n column.align === \"right\" && \"text-right\",\n column.numeric && \"tabular-nums\",\n )}\n >\n {column.cell(row)}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </ScrollArea>\n </div>\n );\n}\n","import { createContext, useContext, useId, type KeyboardEvent, type ReactNode } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\n\ninterface TabsContextValue {\n value: string;\n onChange: (value: string) => void;\n id: string;\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabs() {\n const ctx = useContext(TabsContext);\n if (!ctx) throw new Error(\"Tabs parts must be used inside <Tabs>\");\n return ctx;\n}\n\nexport interface TabsProps<T extends string> {\n value: T;\n onChange: (value: T) => void;\n className?: string;\n children: ReactNode;\n}\n\n/** Underlined tabs for page-level sections. For 2–4 toggles inside a card, use Segmented. */\n/**\n * Tabs switch between views of one thing (a provider's language and audio lists, a\n * character's details and scenes). For narrowing one list by a facet — kind, tag,\n * status — use FilterBar, whose chips carry counts and scroll; for two or three\n * peer settings, Segmented.\n */\nexport function Tabs<T extends string>({ value, onChange, className, children }: TabsProps<T>) {\n const id = useId();\n return (\n <TabsContext.Provider value={{ value, onChange: onChange as (v: string) => void, id }}>\n <div className={className}>{children}</div>\n </TabsContext.Provider>\n );\n}\n\nexport function TabList({ children, className, \"aria-label\": ariaLabel }: { children: ReactNode; className?: string; \"aria-label\"?: string }) {\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const tabs = Array.from(event.currentTarget.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]'));\n const index = tabs.indexOf(document.activeElement as HTMLButtonElement);\n if (index < 0) return;\n const delta = event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (!delta) return;\n event.preventDefault();\n const next = tabs[(index + delta + tabs.length) % tabs.length];\n next.focus();\n next.click();\n };\n return (\n <div role=\"tablist\" aria-label={ariaLabel} onKeyDown={onKeyDown} className={cn(\"scrollbar-none flex gap-1 overflow-x-auto border-b border-line\", className)}>\n {children}\n </div>\n );\n}\n\nexport function Tab({ value, icon, count, children }: { value: string; icon?: ReactNode; count?: number; children: ReactNode }) {\n const tabs = useTabs();\n const selected = tabs.value === value;\n return (\n <button\n type=\"button\"\n role=\"tab\"\n id={`${tabs.id}-tab-${value}`}\n aria-selected={selected}\n aria-controls={`${tabs.id}-panel-${value}`}\n tabIndex={selected ? 0 : -1}\n onClick={() => tabs.onChange(value)}\n className={cn(\n \"relative -mb-px inline-flex h-10 shrink-0 items-center gap-2 px-3 text-base font-medium transition-colors\",\n selected ? \"text-fg\" : \"text-fg-3 hover:text-fg-2\",\n )}\n >\n {icon}\n {children}\n {count !== undefined && (\n <span className={cn(\"rounded-full px-1.5 py-0.5 text-2xs tabular-nums\", selected ? \"bg-fill-3 text-fg\" : \"bg-fill-2 text-fg-3\")}>{count}</span>\n )}\n {selected && (\n <motion.span layoutId={`${tabs.id}-indicator`} transition={m.settle} className=\"absolute inset-x-1 bottom-0 h-0.5 rounded-full bg-fg\" />\n )}\n </button>\n );\n}\n\nexport function TabPanel({ value, className, children }: { value: string; className?: string; children: ReactNode }) {\n const tabs = useTabs();\n if (tabs.value !== value) return null;\n return (\n <div role=\"tabpanel\" id={`${tabs.id}-panel-${value}`} aria-labelledby={`${tabs.id}-tab-${value}`} tabIndex={0} className={cn(\"pt-4 outline-none\", className)}>\n {children}\n </div>\n );\n}\n","import { useRef, useState, type KeyboardEvent } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { useFieldContext } from \"./Field\";\nimport { inputSurface } from \"./Input\";\n\nexport interface TagInputProps {\n value: string[];\n onChange: (value: string[]) => void;\n placeholder?: string;\n /** Refuse tags past this many. */\n max?: number;\n /** Characters that also commit a tag, besides Enter. Default comma. */\n separators?: readonly string[];\n disabled?: boolean;\n id?: string;\n className?: string;\n}\n\n/**\n * Tags as chips instead of a comma-separated string — character tags are a plain text\n * field today, so \"sci-fi, fantasy\" is one value the app has to split on read.\n * Enter or a separator commits; Backspace on an empty input removes the last one.\n */\nexport function TagInput({\n value, onChange, placeholder = \"Add a tag…\", max, separators = [\",\"], disabled, id, className,\n}: TagInputProps) {\n const field = useFieldContext();\n const inputRef = useRef<HTMLInputElement>(null);\n const [draft, setDraft] = useState(\"\");\n\n const commit = (raw: string) => {\n const tag = raw.trim();\n if (!tag || value.includes(tag)) return setDraft(\"\");\n if (max !== undefined && value.length >= max) return;\n onChange([...value, tag]);\n setDraft(\"\");\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\" || separators.includes(event.key)) {\n event.preventDefault();\n commit(draft);\n return;\n }\n if (event.key === \"Backspace\" && !draft && value.length) {\n event.preventDefault();\n onChange(value.slice(0, -1));\n }\n };\n\n const full = max !== undefined && value.length >= max;\n\n return (\n <div\n onClick={() => inputRef.current?.focus()}\n className={cn(\n inputSurface,\n \"flex min-h-[var(--control-md)] cursor-text flex-wrap items-center gap-1.5 px-2 py-1.5\",\n \"focus-within:border-accent/50 focus-within:bg-fill-2\",\n disabled && \"pointer-events-none opacity-40\",\n className,\n )}\n >\n {value.map((tag) => (\n <span key={tag} className=\"inline-flex h-6 shrink-0 items-center gap-1 rounded-full border border-line-2 bg-fill-2 pl-2.5 pr-1 text-xs font-medium text-fg-2\">\n {tag}\n <button\n type=\"button\"\n onClick={(event) => { event.stopPropagation(); onChange(value.filter((t) => t !== tag)); }}\n aria-label={`Remove ${tag}`}\n className=\"tap-target flex h-4 w-4 items-center justify-center rounded-full text-fg-3 transition-colors hover:bg-fill-3 hover:text-fg\"\n >\n <X size={12} />\n </button>\n </span>\n ))}\n <input\n ref={inputRef}\n id={id ?? field?.id}\n value={draft}\n disabled={disabled || full}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={onKeyDown}\n onBlur={() => commit(draft)}\n placeholder={full ? `Limit of ${max} reached` : value.length ? \"\" : placeholder}\n aria-describedby={field?.describedBy}\n className=\"min-w-24 flex-1 bg-transparent px-1 text-base text-fg outline-none placeholder:text-fg-4\"\n />\n </div>\n );\n}\n","import { createElement, type HTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/**\n * The type roles. Every piece of text in the app should be one of these;\n * if it isn't, that's a new role to add here, not a one-off class.\n */\nexport type TextVariant =\n | \"hero\" // 48–60 bold — a first-run or marketing headline, one per screen\n | \"display\" // 36 bold — a big statement inside the app (an empty home, a wizard's first screen)\n | \"page\" // 28/34 bold — page title\n | \"section\" // 20/26 semibold — section heading\n | \"title\" // 16/22 semibold — card / row / sheet title\n | \"body\" // 14/20 — default\n | \"secondary\" // 14/20 fg-2 — supporting copy\n | \"label\" // 13/18 medium fg-2 — form labels\n | \"hint\" // 13/18 fg-3 — hints, meta\n | \"caption\"; // 11/14 fg-3 — timestamps, counts\n\nconst variantClass: Record<TextVariant, string> = {\n hero: \"text-5xl font-bold leading-[1.05] tracking-[-0.03em] text-fg @3xl:text-6xl\",\n display: \"text-4xl font-bold leading-[1.1] tracking-tight text-fg\",\n page: \"text-3xl font-bold tracking-tight text-fg\",\n section: \"text-xl font-semibold tracking-tight text-fg\",\n title: \"text-lg font-semibold text-fg\",\n body: \"text-base text-fg\",\n secondary: \"text-base text-fg-2\",\n label: \"text-sm font-medium text-fg-2\",\n hint: \"text-sm text-fg-3\",\n caption: \"text-2xs text-fg-3\",\n};\n\nconst defaultTag: Record<TextVariant, keyof HTMLElementTagNameMap> = {\n hero: \"h1\",\n display: \"h1\",\n page: \"h1\",\n section: \"h2\",\n title: \"h3\",\n body: \"p\",\n secondary: \"p\",\n label: \"span\",\n hint: \"p\",\n caption: \"span\",\n};\n\nexport interface TextProps extends HTMLAttributes<HTMLElement> {\n variant?: TextVariant;\n as?: keyof HTMLElementTagNameMap;\n children?: ReactNode;\n}\n\nexport function Text({ variant = \"body\", as, className, ...rest }: TextProps) {\n return createElement(as ?? defaultTag[variant], {\n className: cn(variantClass[variant], className),\n ...rest,\n });\n}\n","/** Colour helpers. Deriving is left to CSS `color-mix`; this is only the maths CSS can't do. */\n\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const v = hex.trim().replace(/^#/, \"\");\n const full = v.length === 3 ? v.split(\"\").map((c) => c + c).join(\"\") : v;\n if (!/^[0-9a-f]{6}$/i.test(full)) return null;\n return {\n r: parseInt(full.slice(0, 2), 16),\n g: parseInt(full.slice(2, 4), 16),\n b: parseInt(full.slice(4, 6), 16),\n };\n}\n\nexport function normaliseHex(input: string): string | null {\n const rgb = hexToRgb(input);\n if (!rgb) return null;\n return `#${[rgb.r, rgb.g, rgb.b].map((c) => c.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** WCAG relative luminance. */\nexport function luminance(hex: string): number {\n const rgb = hexToRgb(hex);\n if (!rgb) return 0;\n const channel = (c: number) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);\n };\n return 0.2126 * channel(rgb.r) + 0.7152 * channel(rgb.g) + 0.0722 * channel(rgb.b);\n}\n\n/** WCAG contrast ratio, 1–21. Body text wants 4.5, large text and UI edges 3. */\nexport function contrastRatio(a: string, b: string): number {\n const la = luminance(a);\n const lb = luminance(b);\n return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);\n}\n\nexport function isLight(hex: string): boolean {\n return luminance(hex) > 0.4;\n}\n\n/** Black or white, whichever is readable on the given background. */\nexport function readableOn(background: string): string {\n return contrastRatio(background, \"#ffffff\") >= contrastRatio(background, \"#000000\") ? \"#ffffff\" : \"#0a0a0a\";\n}\n\n/** Blend two hex colours in sRGB. Used where a literal value is needed, not a var. */\nexport function mixHex(a: string, b: string, amount: number): string {\n const ca = hexToRgb(a);\n const cb = hexToRgb(b);\n if (!ca || !cb) return a;\n const t = Math.min(1, Math.max(0, amount));\n const channel = (x: number, y: number) => Math.round(x + (y - x) * t);\n return `#${[channel(ca.r, cb.r), channel(ca.g, cb.g), channel(ca.b, cb.b)]\n .map((c) => c.toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n}\n","import { isLight, mixHex, readableOn } from \"../lib/color\";\n\n/**\n * A theme is a handful of source colours. Everything else — the four text tiers, the\n * three fills, the three lines, the elevated and nav surfaces — is derived, so changing\n * one value re-colours the whole app consistently instead of leaving half of it behind.\n */\nexport interface ThemeColors {\n /** The page. Decides light vs dark on its own. */\n surface: string;\n /** Text and everything tinted from it: fills, lines, the muted tiers. */\n fg: string;\n accent: string;\n danger: string;\n warning: string;\n info: string;\n secondary: string;\n /** Navigation and title bars. Defaults to the elevated surface. */\n nav?: string;\n}\n\nexport type ThemeRadius = \"sharp\" | \"default\" | \"round\";\nexport type ThemeDensity = \"default\" | \"compact\";\n\nexport interface Theme {\n id: string;\n name: string;\n colors: ThemeColors;\n radius?: ThemeRadius;\n density?: ThemeDensity;\n}\n\nconst RADIUS: Record<ThemeRadius, { sm: string; md: string; lg: string; xl: string; \"2xl\": string }> = {\n sharp: { sm: \"2px\", md: \"3px\", lg: \"4px\", xl: \"6px\", \"2xl\": \"8px\" },\n default: { sm: \"4px\", md: \"6px\", lg: \"8px\", xl: \"12px\", \"2xl\": \"16px\" },\n round: { sm: \"6px\", md: \"10px\", lg: \"14px\", xl: \"18px\", \"2xl\": \"24px\" },\n};\n\n/** Text tier strengths, as a percentage of `fg` mixed toward transparent. */\nconst TIERS = { fg2: 72, fg3: 50, fg4: 34 };\nconst FILLS = { fill: 5, fill2: 8, fill3: 12 };\nconst LINES = { line: 10, line2: 16, line3: 26 };\n\n/**\n * Turns a theme into the CSS custom properties the components read.\n * Tiers mix toward `transparent` rather than the surface colour, so the same formula\n * works on a flat background, over a photo, and inside a gradient card.\n */\nexport function themeToVars(theme: Theme): Record<string, string> {\n const { surface, fg, accent, danger, warning, info, secondary, nav } = theme.colors;\n const light = isLight(surface);\n\n /* Elevation is two visible steps away from the page, both toward the light: lighter on\n a dark theme, white on a light one. The old single step sat 4.5% off the page, which\n is why every container needed a border to be seen at all. */\n const raised = light ? mixHex(surface, \"#ffffff\", 0.6) : mixHex(surface, \"#ffffff\", 0.075);\n const overlay = light ? \"#ffffff\" : mixHex(surface, \"#ffffff\", 0.13);\n const shadowAlpha = light ? 0.12 : 0.45;\n\n const mix = (color: string, pct: number) => `color-mix(in oklab, ${color} ${pct}%, transparent)`;\n\n return {\n \"--color-surface\": surface,\n /* Cards, list groups, panels — anything sitting on the page. */\n \"--color-surface-1\": raised,\n /* Sheets, dialogs, menus, popovers — anything sitting on top of everything. */\n \"--color-surface-2\": overlay,\n /* Kept as an alias of surface-1 so existing call sites keep working. */\n \"--color-surface-el\": raised,\n \"--color-nav\": nav ?? raised,\n \"--color-fg\": fg,\n \"--color-fg-2\": mix(fg, TIERS.fg2),\n \"--color-fg-3\": mix(fg, TIERS.fg3),\n \"--color-fg-4\": mix(fg, TIERS.fg4),\n \"--color-fill\": mix(fg, FILLS.fill),\n \"--color-fill-2\": mix(fg, FILLS.fill2),\n \"--color-fill-3\": mix(fg, FILLS.fill3),\n \"--color-line\": mix(fg, LINES.line),\n \"--color-line-2\": mix(fg, LINES.line2),\n \"--color-line-3\": mix(fg, LINES.line3),\n \"--color-accent\": accent,\n \"--color-danger\": danger,\n \"--color-warning\": warning,\n \"--color-info\": info,\n \"--color-secondary\": secondary,\n /* Solid accent buttons put text on the accent, so it has to be readable on it —\n a pale accent needs dark text, and that is not a decision a call site should make. */\n \"--color-on-accent\": readableOn(accent),\n /* Switch and slider knobs. Always the light end of the palette: a knob is a\n physical thing above its track, and `fg` would turn it black on a light theme. */\n \"--color-knob\": light ? \"#ffffff\" : fg,\n /* Depth for controls. A 1px lip and a hairline of light along the top edge — the\n whole effect is two hard-edged shadows, so it costs nothing to paint. */\n \"--edge-light\": light ? \"rgb(255 255 255 / 0.9)\" : \"rgb(255 255 255 / 0.08)\",\n \"--edge-dark\": light ? \"rgb(0 0 0 / 0.16)\" : \"rgb(0 0 0 / 0.55)\",\n \"--edge-ambient\": light ? \"rgb(0 0 0 / 0.08)\" : \"rgb(0 0 0 / 0.35)\",\n \"--shadow-raised\": `0 8px 24px rgb(0 0 0 / ${shadowAlpha})`,\n \"--shadow-sheet\": `0 -12px 40px rgb(0 0 0 / ${shadowAlpha + 0.1})`,\n ...Object.fromEntries(\n Object.entries(RADIUS[theme.radius ?? \"default\"]).map(([k, v]) => [`--radius-${k}`, v]),\n ),\n };\n}\n\nexport function applyTheme(theme: Theme, target: HTMLElement = document.documentElement) {\n const vars = themeToVars(theme);\n for (const [key, value] of Object.entries(vars)) target.style.setProperty(key, value);\n target.style.colorScheme = isLight(theme.colors.surface) ? \"light\" : \"dark\";\n target.dataset.theme = isLight(theme.colors.surface) ? \"light\" : \"dark\";\n target.dataset.density = theme.density ?? \"default\";\n}\n\nexport const PRESETS: readonly Theme[] = [\n {\n id: \"midnight\",\n name: \"Midnight\",\n colors: {\n surface: \"#050505\", fg: \"#ffffff\", accent: \"#65c789\",\n danger: \"#ef4444\", warning: \"#f59e0b\", info: \"#3b82f6\", secondary: \"#a78bfa\",\n },\n },\n {\n /* BRIEF.md — a cool ink rather than a void, and a white that is not a glare source.\n surface-1, surface-2, the fills and the lines are all derived from these two, so\n the whole ladder picks up the same cast from one value. */\n id: \"ink\",\n name: \"Ink\",\n colors: {\n surface: \"#0b0c11\", fg: \"#eceef4\", accent: \"#65c789\",\n danger: \"#ef4444\", warning: \"#f59e0b\", info: \"#3b82f6\", secondary: \"#a78bfa\",\n },\n },\n {\n /* The same decision in reverse: paper with a trace of warmth, not grey. */\n id: \"vellum\",\n name: \"Vellum\",\n colors: {\n surface: \"#f7f6f3\", fg: \"#141312\", accent: \"#19874d\",\n danger: \"#dc2626\", warning: \"#b45309\", info: \"#2563eb\", secondary: \"#7c3aed\",\n },\n },\n {\n id: \"paper\",\n name: \"Paper\",\n colors: {\n surface: \"#f6f6f5\", fg: \"#111112\", accent: \"#19874d\",\n danger: \"#dc2626\", warning: \"#b45309\", info: \"#2563eb\", secondary: \"#7c3aed\",\n },\n },\n {\n id: \"slate\",\n name: \"Slate\",\n colors: {\n surface: \"#0d1117\", fg: \"#e6edf3\", accent: \"#2dd4bf\",\n danger: \"#f87171\", warning: \"#fbbf24\", info: \"#60a5fa\", secondary: \"#c084fc\",\n },\n },\n {\n id: \"ember\",\n name: \"Ember\",\n colors: {\n surface: \"#100a08\", fg: \"#fdf3ec\", accent: \"#fb923c\",\n danger: \"#f43f5e\", warning: \"#eab308\", info: \"#38bdf8\", secondary: \"#e879f9\",\n },\n },\n];\n\nexport const DEFAULT_THEME = PRESETS[0];\n","import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { applyTheme, DEFAULT_THEME, PRESETS, type Theme, type ThemeColors, type ThemeDensity, type ThemeRadius } from \"./theme\";\n\nconst STORAGE_KEY = \"crisp.theme\";\n\ninterface ThemeContextValue {\n theme: Theme;\n presets: readonly Theme[];\n setTheme: (theme: Theme) => void;\n /** Change one colour and repaint immediately — this is the live-editing path. */\n setColor: (key: keyof ThemeColors, value: string) => void;\n setRadius: (radius: ThemeRadius) => void;\n setDensity: (density: ThemeDensity) => void;\n reset: () => void;\n isCustom: boolean;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nexport function useTheme() {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error(\"useTheme must be used inside <ThemeProvider>\");\n return ctx;\n}\n\nfunction load(): Theme {\n if (typeof localStorage === \"undefined\") return DEFAULT_THEME;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return DEFAULT_THEME;\n const parsed = JSON.parse(raw) as Theme;\n if (!parsed?.colors?.surface || !parsed.colors.fg) return DEFAULT_THEME;\n return parsed;\n } catch {\n return DEFAULT_THEME;\n }\n}\n\nexport function ThemeProvider({ children, initial }: { children: ReactNode; initial?: Theme }) {\n const [theme, setThemeState] = useState<Theme>(() => initial ?? load());\n\n /* Paint before first render so there is no flash of the default palette. */\n useState(() => {\n if (typeof document !== \"undefined\") applyTheme(initial ?? load());\n return null;\n });\n\n useEffect(() => {\n applyTheme(theme);\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(theme));\n } catch {\n /* private mode — the theme still applies, it just won't persist */\n }\n }, [theme]);\n\n const setColor = useCallback((key: keyof ThemeColors, value: string) => {\n setThemeState((current) => ({\n ...current,\n id: \"custom\",\n name: current.id === \"custom\" ? current.name : `${current.name} (edited)`,\n colors: { ...current.colors, [key]: value },\n }));\n }, []);\n\n const setRadius = useCallback((radius: ThemeRadius) => {\n setThemeState((current) => ({ ...current, radius }));\n }, []);\n\n const setDensity = useCallback((density: ThemeDensity) => {\n setThemeState((current) => ({ ...current, density }));\n }, []);\n\n const value = useMemo<ThemeContextValue>(\n () => ({\n theme,\n presets: PRESETS,\n setTheme: setThemeState,\n setColor,\n setRadius,\n setDensity,\n reset: () => setThemeState(DEFAULT_THEME),\n isCustom: theme.id === \"custom\",\n }),\n [theme, setColor, setRadius, setDensity],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n","import { useMemo } from \"react\";\nimport { AlertTriangle, Check, RotateCcw } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { contrastRatio } from \"../lib/color\";\nimport { useTheme, type ThemeColors, type ThemeDensity, type ThemeRadius } from \"../theme\";\nimport { Button } from \"./Button\";\nimport { ColorPicker } from \"./ColorPicker\";\nimport { Segmented } from \"./Segmented\";\nimport { Tooltip } from \"./Tooltip\";\n\nconst SOURCES: { key: keyof ThemeColors; label: string; hint: string }[] = [\n { key: \"surface\", label: \"Surface\", hint: \"The page. Decides light or dark on its own.\" },\n { key: \"fg\", label: \"Foreground\", hint: \"Text, and every fill and line tinted from it.\" },\n { key: \"accent\", label: \"Accent\", hint: \"Actions and selection.\" },\n { key: \"danger\", label: \"Danger\", hint: \"Destructive actions and errors.\" },\n { key: \"warning\", label: \"Warning\", hint: \"Needs attention.\" },\n { key: \"info\", label: \"Info\", hint: \"Neutral notices.\" },\n { key: \"secondary\", label: \"Secondary\", hint: \"Generated and AI-authored things.\" },\n];\n\nconst DERIVED = [\n { var: \"--color-surface-1\", label: \"surface-1\" },\n { var: \"--color-surface-2\", label: \"surface-2\" },\n { var: \"--color-fg-2\", label: \"fg-2\" },\n { var: \"--color-fg-3\", label: \"fg-3\" },\n { var: \"--color-fg-4\", label: \"fg-4\" },\n { var: \"--color-fill\", label: \"fill\" },\n { var: \"--color-fill-2\", label: \"fill-2\" },\n { var: \"--color-fill-3\", label: \"fill-3\" },\n { var: \"--color-line\", label: \"line\" },\n { var: \"--color-line-2\", label: \"line-2\" },\n { var: \"--color-line-3\", label: \"line-3\" },\n { var: \"--color-on-accent\", label: \"on-accent\" },\n];\n\n/** WCAG 4.5 is the floor for body text; 3 is the floor for large text and UI edges. */\nfunction ContrastBadge({ ratio, need = 4.5, label }: { ratio: number; need?: number; label: string }) {\n const pass = ratio >= need;\n return (\n <Tooltip content={`${label}: ${ratio.toFixed(2)}:1 — needs ${need}:1`}>\n <span\n className={cn(\n \"inline-flex h-6 items-center gap-1 rounded-full border px-2 text-2xs font-medium tabular-nums\",\n pass ? \"border-accent/25 bg-accent/12 text-accent\" : \"border-danger/25 bg-danger/12 text-danger\",\n )}\n >\n {pass ? <Check size={12} /> : <AlertTriangle size={12} />}\n {label} {ratio.toFixed(1)}\n </span>\n </Tooltip>\n );\n}\n\n/**\n * Live theme editing. Every change writes straight to the document, so the editor and\n * everything behind it repaint together — there is no preview mode, because the preview\n * is the app.\n */\nexport function ThemeEditor({ className }: { className?: string }) {\n const { theme, presets, setTheme, setColor, setRadius, setDensity, reset, isCustom } = useTheme();\n const { surface, fg, accent } = theme.colors;\n\n /* Contrast is checked against the tier that carries meaning, not the brightest one:\n fg-3 is the last readable tier, so if it passes, everything above it does too. */\n const checks = useMemo(() => {\n const fgOnSurface = contrastRatio(fg, surface);\n return {\n body: fgOnSurface,\n /* fg-3 is fg at 50% over the surface, which halves the effective contrast. */\n muted: (fgOnSurface + 1) / 2,\n accent: contrastRatio(accent, surface),\n };\n }, [fg, surface, accent]);\n\n return (\n <div className={cn(\"space-y-6\", className)}>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Segmented\n aria-label=\"Theme preset\"\n size=\"sm\"\n value={isCustom ? \"custom\" : theme.id}\n onChange={(id) => {\n const preset = presets.find((p) => p.id === id);\n if (preset) setTheme(preset);\n }}\n options={[\n ...presets.map((p) => ({ value: p.id, label: p.name })),\n ...(isCustom ? [{ value: \"custom\", label: \"Custom\" }] : []),\n ]}\n />\n <span className=\"flex-1\" />\n <Segmented\n aria-label=\"Density\"\n size=\"sm\"\n value={theme.density ?? \"default\"}\n onChange={(d) => setDensity(d as ThemeDensity)}\n options={[{ value: \"default\", label: \"Default\" }, { value: \"compact\", label: \"Compact\" }]}\n />\n <Segmented\n aria-label=\"Corner radius\"\n size=\"sm\"\n value={theme.radius ?? \"default\"}\n onChange={(r) => setRadius(r as ThemeRadius)}\n options={[{ value: \"sharp\", label: \"Sharp\" }, { value: \"default\", label: \"Default\" }, { value: \"round\", label: \"Round\" }]}\n />\n <Button size=\"sm\" variant=\"ghost\" leading={<RotateCcw size={16} />} onClick={reset}>\n Reset\n </Button>\n </div>\n\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {SOURCES.map((source) => (\n <div key={source.key} className=\"space-y-1.5\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <label className=\"text-sm font-medium text-fg-2\">{source.label}</label>\n <span className=\"font-mono text-2xs uppercase text-fg-3\">{theme.colors[source.key]}</span>\n </div>\n <ColorPicker\n value={theme.colors[source.key] ?? \"#000000\"}\n onChange={(value) => setColor(source.key, value)}\n className=\"w-full\"\n />\n <p className=\"text-sm text-fg-3\">{source.hint}</p>\n </div>\n ))}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <ContrastBadge ratio={checks.body} label=\"Body\" />\n <ContrastBadge ratio={checks.muted} need={4.5} label=\"Muted\" />\n <ContrastBadge ratio={checks.accent} need={3} label=\"Accent\" />\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-sm font-medium text-fg-2\">Derived</p>\n <p className=\"text-sm text-fg-3\">\n Computed from the values above. Change the foreground and all eleven move with it.\n </p>\n <div className=\"flex flex-wrap gap-2 pt-1\">\n {DERIVED.map((token) => (\n <div key={token.var} className=\"flex items-center gap-2 rounded-lg border border-line bg-fill px-2 py-1.5\">\n <span\n className=\"h-5 w-5 shrink-0 rounded-md ring-1 ring-inset ring-line-2\"\n style={{ background: `var(${token.var})` }}\n />\n <span className=\"font-mono text-2xs text-fg-3\">{token.label}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type TimelineTone = \"neutral\" | \"accent\" | \"info\" | \"warning\" | \"danger\" | \"secondary\";\n\nexport interface TimelineItem {\n id: string;\n title: ReactNode;\n description?: ReactNode;\n time?: ReactNode;\n icon?: ReactNode;\n tone?: TimelineTone;\n /** Still happening — the marker pulses. */\n active?: boolean;\n}\n\nconst toneClass: Record<TimelineTone, string> = {\n neutral: \"border-line-3 bg-fill-2 text-fg-3\",\n accent: \"border-accent/45 bg-accent/18 text-accent\",\n info: \"border-info/40 bg-info/15 text-info\",\n warning: \"border-warning/40 bg-warning/15 text-warning\",\n danger: \"border-danger/40 bg-danger/15 text-danger\",\n secondary: \"border-secondary/40 bg-secondary/15 text-secondary\",\n};\n\n/** An ordered sequence of events: memory updates, sync stages, a generation's history. */\nexport function Timeline({ items, className }: { items: readonly TimelineItem[]; className?: string }) {\n return (\n <ol className={cn(\"relative\", className)}>\n {items.map((item, index) => (\n <li key={item.id} className=\"relative flex gap-3 pb-5 last:pb-0\">\n {index < items.length - 1 && (\n <span aria-hidden=\"true\" className=\"absolute left-3.5 top-8 h-[calc(100%-2rem)] w-px bg-line\" />\n )}\n <span\n className={cn(\n \"relative z-10 flex h-7 w-7 shrink-0 items-center justify-center rounded-full border\",\n toneClass[item.tone ?? \"neutral\"],\n )}\n >\n {item.active && (\n <span aria-hidden=\"true\" className=\"absolute inset-0 animate-ping rounded-full bg-current opacity-25 motion-reduce:hidden\" />\n )}\n {item.icon ?? <span className=\"h-1.5 w-1.5 rounded-full bg-current\" />}\n </span>\n <div className=\"min-w-0 flex-1 pt-0.5\">\n <div className=\"flex items-baseline justify-between gap-3\">\n <p className=\"min-w-0 text-base font-medium text-fg\">{item.title}</p>\n {item.time && <span className=\"shrink-0 text-2xs tabular-nums text-fg-3\">{item.time}</span>}\n </div>\n {item.description && <p className=\"mt-0.5 text-sm text-fg-3\">{item.description}</p>}\n </div>\n </li>\n ))}\n </ol>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Minus, Square, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface TitleBarProps {\n title?: ReactNode;\n /** macOS puts the traffic lights on the left and we leave room; Windows/Linux draw ours on the right. */\n platform?: \"macos\" | \"windows\" | \"linux\";\n onMinimize?: () => void;\n onMaximize?: () => void;\n onClose?: () => void;\n /** Slot in the drag region — a back button, a status chip. */\n children?: ReactNode;\n className?: string;\n}\n\n/**\n * Desktop window chrome. The whole bar is a drag region except the buttons,\n * which opt out with `data-tauri-drag-region=\"false\"`.\n */\nexport function TitleBar({ title, platform = \"linux\", onMinimize, onMaximize, onClose, children, className }: TitleBarProps) {\n const mac = platform === \"macos\";\n return (\n <div\n data-tauri-drag-region\n className={cn(\n \"flex h-9 shrink-0 select-none items-center gap-2 border-b border-line bg-nav px-2 text-fg\",\n mac && \"pl-20\", // room for the system traffic lights\n className,\n )}\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">{children}</div>\n {title && <span className=\"pointer-events-none absolute left-1/2 -translate-x-1/2 text-2xs font-medium text-fg-3\">{title}</span>}\n {!mac && (onMinimize || onMaximize || onClose) && (\n <div data-tauri-drag-region=\"false\" className=\"flex shrink-0 items-center\">\n {onMinimize && (\n <button type=\"button\" onClick={onMinimize} aria-label=\"Minimize\" className=\"flex h-9 w-11 items-center justify-center text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg\">\n <Minus size={14} />\n </button>\n )}\n {onMaximize && (\n <button type=\"button\" onClick={onMaximize} aria-label=\"Maximize\" className=\"flex h-9 w-11 items-center justify-center text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg\">\n <Square size={12} />\n </button>\n )}\n {onClose && (\n <button type=\"button\" onClick={onClose} aria-label=\"Close window\" className=\"flex h-9 w-11 items-center justify-center text-fg-3 transition-colors hover:bg-danger hover:text-fg\">\n <X size={14} />\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { toast as sonner, Toaster as SonnerToaster } from \"sonner\";\nimport { AlertTriangle, CheckCircle2, Info, Loader2, X, XCircle } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\n/**\n * Toasts are sonner underneath, rendered `unstyled` with our own body so they\n * follow the tokens and the four text tiers.\n *\n * The call signature matches the app's existing `toast.*` helpers, so call sites\n * migrate without edits. Tone naming follows the event (`error`), while Alert —\n * which paints a colour — follows the token (`danger`).\n */\n\nexport type ToastTone = \"info\" | \"success\" | \"warning\" | \"error\";\n\nexport interface ToastAction {\n label: string;\n onClick: () => void;\n}\n\nexport interface ToastOptions {\n /** Sits under the text, never beside it. */\n action?: ToastAction;\n secondary?: ToastAction;\n /** ms, or Infinity to keep it until dismissed. Default 5000. */\n duration?: number;\n /** Pass a stable id to update a toast in place instead of stacking a new one. */\n id?: string | number;\n}\n\nconst toneIcon: Record<ToastTone, ReactNode> = {\n info: <Info size={16} className=\"text-info\" />,\n success: <CheckCircle2 size={16} className=\"text-accent\" />,\n warning: <AlertTriangle size={16} className=\"text-warning\" />,\n error: <XCircle size={16} className=\"text-danger\" />,\n};\n\nconst toneBar: Record<ToastTone, string> = {\n info: \"bg-info\",\n success: \"bg-accent\",\n warning: \"bg-warning\",\n error: \"bg-danger\",\n};\n\n/* Neutral surface + a coloured bar, like Alert — a full-strength colour wash\n behind the whole toast makes the description hard to read. */\nconst shell =\n \"pointer-events-auto relative flex w-full items-start gap-3 overflow-hidden rounded-xl border border-line bg-surface-2 py-3 pl-4 pr-3 shadow-raised\";\n\nfunction ToastBody({\n tone,\n title,\n description,\n action,\n secondary,\n onDismiss,\n}: {\n tone: ToastTone;\n title: ReactNode;\n description?: ReactNode;\n action?: ToastAction;\n secondary?: ToastAction;\n onDismiss: () => void;\n}) {\n const runAction = (handler: () => void) => (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n handler();\n onDismiss();\n };\n\n return (\n <>\n <span aria-hidden=\"true\" className={cn(\"absolute inset-y-0 left-0 w-0.5\", toneBar[tone])} />\n <span className=\"mt-0.5 shrink-0\">{toneIcon[tone]}</span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-base font-medium text-fg\">{title}</p>\n {description && <p className=\"mt-0.5 text-sm text-fg-2\">{description}</p>}\n {(action || secondary) && (\n <div className=\"-ml-2 mt-1.5 flex flex-wrap items-center gap-1\">\n {action && (\n <button\n type=\"button\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={runAction(action.onClick)}\n className=\"touch-target inline-flex h-7 items-center rounded-lg px-2 text-sm font-medium text-accent transition-colors hover:bg-accent/10\"\n >\n {action.label}\n </button>\n )}\n {secondary && (\n <button\n type=\"button\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={runAction(secondary.onClick)}\n className=\"touch-target inline-flex h-7 items-center rounded-lg px-2 text-sm font-medium text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg-2\"\n >\n {secondary.label}\n </button>\n )}\n </div>\n )}\n </div>\n <button\n type=\"button\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={(event) => { event.stopPropagation(); onDismiss(); }}\n aria-label=\"Dismiss\"\n className=\"-mr-1 -mt-1 shrink-0 rounded-lg p-1.5 text-fg-3 transition-colors hover:bg-fill-2 hover:text-fg\"\n >\n <X size={14} />\n </button>\n </>\n );\n}\n\nfunction show(tone: ToastTone, title: ReactNode, description?: ReactNode, options?: ToastOptions) {\n return sonner.custom(\n (id) => (\n <div className={shell}>\n <ToastBody\n tone={tone}\n title={title}\n description={description}\n action={options?.action}\n secondary={options?.secondary}\n onDismiss={() => sonner.dismiss(id)}\n />\n </div>\n ),\n { duration: options?.duration ?? 5000, id: options?.id },\n );\n}\n\nexport interface ProgressToastOptions {\n id: string | number;\n title: ReactNode;\n description?: ReactNode;\n /** 0–1. Omit for an indeterminate spinner. */\n progress?: number;\n duration?: number;\n}\n\n/** Long-running work that reports progress — model downloads, indexing. */\nfunction progressToast({ id, title, description, progress, duration }: ProgressToastOptions) {\n const percent = progress === undefined ? undefined : Math.round(Math.min(1, Math.max(0, progress)) * 100);\n return sonner.custom(\n () => (\n <div className={cn(shell, \"items-center\")}>\n <span aria-hidden=\"true\" className=\"absolute inset-y-0 left-0 w-0.5 bg-accent\" />\n <Loader2 size={16} className=\"shrink-0 animate-spin text-fg-3\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-baseline justify-between gap-3\">\n <p className=\"truncate text-base font-medium text-fg\">{title}</p>\n {percent !== undefined && <span className=\"shrink-0 text-sm tabular-nums text-fg-2\">{percent}%</span>}\n </div>\n {description && <p className=\"mt-0.5 truncate text-sm text-fg-3\">{description}</p>}\n <div\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent}\n className=\"mt-2 h-1 w-full overflow-hidden rounded-full bg-fill-3\"\n >\n <div\n className={cn(\"h-full rounded-full bg-accent\", percent === undefined && \"w-1/3 animate-[indeterminate_1.4s_ease-in-out_infinite]\")}\n style={percent === undefined ? undefined : { width: `${percent}%`, transition: \"width 300ms ease-out\" }}\n />\n </div>\n </div>\n </div>\n ),\n { duration: duration ?? Infinity, id },\n );\n}\n\nexport const toast = {\n info: (title: ReactNode, description?: ReactNode, options?: ToastOptions) => show(\"info\", title, description, options),\n success: (title: ReactNode, description?: ReactNode, options?: ToastOptions) => show(\"success\", title, description, options),\n warning: (title: ReactNode, description?: ReactNode, options?: ToastOptions) => show(\"warning\", title, description, options),\n error: (title: ReactNode, description?: ReactNode, options?: ToastOptions) => show(\"error\", title, description, options),\n progress: progressToast,\n dismiss: (id?: string | number) => sonner.dismiss(id),\n isVisible: (id: string | number) => sonner.getToasts().some((entry) => entry.id === id),\n};\n\nexport interface ToasterProps {\n position?: \"top-center\" | \"bottom-center\" | \"top-right\" | \"bottom-right\";\n /** Extra bottom offset on phones — clear the TabBar. */\n bottomInset?: number;\n}\n\n/** Mount once, at the app root. */\nexport function Toaster({ position = \"bottom-center\", bottomInset = 0 }: ToasterProps = {}) {\n return (\n <SonnerToaster\n position={position}\n gap={8}\n visibleToasts={3}\n /* Sonner stacks by default and only expands on hover, which a phone never gets. */\n expand\n offset={{ bottom: `calc(env(safe-area-inset-bottom) + ${16 + bottomInset}px)`, top: 16, left: 16, right: 16 }}\n toastOptions={{ unstyled: true, classNames: { toast: \"w-full\" } }}\n style={{ [\"--width\" as string]: \"384px\" }}\n />\n );\n}\n","import { type KeyboardEvent, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface ToggleOption<T extends string> {\n value: T;\n label: ReactNode;\n icon?: ReactNode;\n disabled?: boolean;\n}\n\nexport interface ToggleGroupProps<T extends string> {\n options: readonly ToggleOption<T>[];\n value: readonly T[];\n onChange: (value: T[]) => void;\n /** Require at least one selection. */\n min?: number;\n size?: \"sm\" | \"md\";\n \"aria-label\": string;\n className?: string;\n}\n\n/**\n * Multi-select toggles. Segmented picks exactly one; this picks any number —\n * text formatting, which sources a filter includes, which providers to query.\n */\nexport function ToggleGroup<T extends string>({ options, value, onChange, min = 0, size = \"md\", className, ...aria }: ToggleGroupProps<T>) {\n const toggle = (option: ToggleOption<T>) => {\n if (option.disabled) return;\n const on = value.includes(option.value);\n if (on && value.length <= min) return;\n onChange(on ? value.filter((v) => v !== option.value) : [...value, option.value]);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const delta = event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (!delta) return;\n const buttons = Array.from(event.currentTarget.querySelectorAll<HTMLButtonElement>(\"button:not([disabled])\"));\n const index = buttons.indexOf(document.activeElement as HTMLButtonElement);\n if (index < 0) return;\n event.preventDefault();\n buttons[(index + delta + buttons.length) % buttons.length]?.focus();\n };\n\n return (\n <div role=\"group\" aria-label={aria[\"aria-label\"]} onKeyDown={onKeyDown} className={cn(\"inline-flex rounded-xl border border-line bg-fill p-1\", className)}>\n {options.map((option) => {\n const on = value.includes(option.value);\n return (\n <button\n key={option.value}\n type=\"button\"\n aria-pressed={on}\n disabled={option.disabled}\n onClick={() => toggle(option)}\n className={cn(\n \"inline-flex items-center justify-center gap-1.5 rounded-lg font-medium transition-colors motion-instant\",\n size === \"sm\" ? \"h-7 px-2.5 text-sm\" : \"h-8 px-3 text-sm\",\n on ? \"bg-fill-3 text-fg\" : \"text-fg-3 hover:text-fg-2\",\n option.disabled && \"pointer-events-none opacity-40\",\n )}\n >\n {option.icon}\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface ToolbarProps {\n \"aria-label\": string;\n /** `bar` sits flush in a layout; `floating` is a rounded pill over content. */\n variant?: \"bar\" | \"floating\";\n className?: string;\n children: ReactNode;\n}\n\n/**\n * A row of icon buttons with dividers. Arrow keys move between the controls, so the\n * whole group is one tab stop instead of nine.\n */\nexport function Toolbar({ variant = \"bar\", className, children, ...aria }: ToolbarProps) {\n const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const delta = event.key === \"ArrowRight\" ? 1 : event.key === \"ArrowLeft\" ? -1 : 0;\n if (!delta) return;\n const items = Array.from(\n event.currentTarget.querySelectorAll<HTMLElement>(\"button:not([disabled]), a[href]\"),\n );\n const index = items.indexOf(document.activeElement as HTMLElement);\n if (index < 0) return;\n event.preventDefault();\n items[(index + delta + items.length) % items.length]?.focus();\n };\n\n return (\n <div\n role=\"toolbar\"\n aria-label={aria[\"aria-label\"]}\n onKeyDown={onKeyDown}\n className={cn(\n \"flex items-center gap-0.5\",\n variant === \"floating\" && \"rounded-full border border-line bg-surface-el/95 p-1 shadow-raised backdrop-blur-md\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nexport function ToolbarSeparator() {\n return <span aria-hidden=\"true\" className=\"mx-1 h-5 w-px shrink-0 bg-line\" />;\n}\n\nexport function ToolbarGroup({ children, className }: { children: ReactNode; className?: string }) {\n return <div className={cn(\"flex items-center gap-0.5\", className)}>{children}</div>;\n}\n","import { motion as m } from \"../lib/motion\";\nimport { useCallback, useEffect, useLayoutEffect, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { X } from \"lucide-react\";\nimport { Button } from \"./Button\";\nimport { Stepper } from \"./Stepper\";\n\nexport interface TourStep {\n /** CSS selector for the element to highlight. Omit for a centred, anchorless step. */\n target?: string;\n title: ReactNode;\n body: ReactNode;\n /** Preferred side; it flips when there isn't room. */\n side?: \"top\" | \"bottom\";\n}\n\nexport interface TourProps {\n steps: readonly TourStep[];\n open: boolean;\n onClose: () => void;\n onFinish?: () => void;\n finishLabel?: string;\n}\n\nconst PAD = 8;\n\n/**\n * Coach marks over the real interface: a cut-out spotlight on the target and a card\n * beside it. Replaces a 1,000-line bespoke tour. It scrolls the target into view and\n * traps Escape, so it can always be left.\n */\nexport function Tour({ steps, open, onClose, onFinish, finishLabel = \"Got it\" }: TourProps) {\n const [index, setIndex] = useState(0);\n const [rect, setRect] = useState<DOMRect | null>(null);\n const step = steps[index];\n\n useEffect(() => { if (open) setIndex(0); }, [open]);\n\n useLayoutEffect(() => {\n if (!open || !step) return;\n const measure = () => {\n if (!step.target) return setRect(null);\n const el = document.querySelector(step.target);\n if (!el) return setRect(null);\n el.scrollIntoView({ block: \"center\", behavior: \"smooth\" });\n setRect(el.getBoundingClientRect());\n };\n measure();\n const id = window.setTimeout(measure, 260);\n window.addEventListener(\"resize\", measure);\n window.addEventListener(\"scroll\", measure, true);\n return () => {\n window.clearTimeout(id);\n window.removeEventListener(\"resize\", measure);\n window.removeEventListener(\"scroll\", measure, true);\n };\n }, [open, step]);\n\n const finish = useCallback(() => { onFinish?.(); onClose(); }, [onFinish, onClose]);\n\n useEffect(() => {\n if (!open) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n if (event.key === \"ArrowRight\") setIndex((i) => Math.min(steps.length - 1, i + 1));\n if (event.key === \"ArrowLeft\") setIndex((i) => Math.max(0, i - 1));\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => document.removeEventListener(\"keydown\", onKeyDown);\n }, [open, onClose, steps.length]);\n\n if (!step) return null;\n\n const below = rect ? rect.bottom + 160 < window.innerHeight || step.side === \"bottom\" : true;\n const cardStyle = rect\n ? {\n top: below ? rect.bottom + PAD * 2 : undefined,\n bottom: below ? undefined : window.innerHeight - rect.top + PAD * 2,\n left: Math.max(12, Math.min(rect.left, window.innerWidth - 332)),\n }\n : { top: \"50%\", left: \"50%\", transform: \"translate(-50%, -50%)\" };\n\n return createPortal(\n <AnimatePresence>\n {open && (\n <>\n {/* The spotlight is a giant ring, so one element cuts a hole in the veil\n without needing an SVG mask or cloning the target. */}\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={m.quick}\n onClick={onClose}\n className=\"fixed inset-0 z-[85]\"\n >\n {rect ? (\n <motion.span\n layout\n transition={m.surface}\n style={{ top: rect.top - PAD, left: rect.left - PAD, width: rect.width + PAD * 2, height: rect.height + PAD * 2 }}\n className=\"absolute rounded-xl shadow-[0_0_0_9999px_rgba(0,0,0,0.72)] ring-2 ring-accent\"\n />\n ) : (\n <span className=\"absolute inset-0 bg-black/72\" />\n )}\n </motion.div>\n\n <motion.div\n role=\"dialog\"\n aria-label=\"Product tour\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 8 }}\n transition={m.quick}\n style={cardStyle}\n className=\"fixed z-[86] w-80 max-w-[calc(100vw-24px)] rounded-xl border border-line bg-surface-2 p-4 shadow-raised\"\n >\n <div className=\"flex items-start gap-2\">\n <h2 className=\"min-w-0 flex-1 text-base font-semibold text-fg\">{step.title}</h2>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Skip tour\"\n className=\"-mr-1 -mt-1 rounded-lg p-1.5 text-fg-3 hover:bg-fill-2 hover:text-fg\"\n >\n <X size={14} />\n </button>\n </div>\n <p className=\"mt-1 text-sm leading-relaxed text-fg-2\">{step.body}</p>\n\n <div className=\"mt-4 flex items-center gap-3\">\n <Stepper steps={steps.map((s, i) => ({ id: String(i), label: String(s.title) }))} current={index} variant=\"dots\" />\n <span className=\"flex-1\" />\n {index > 0 && (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setIndex((i) => i - 1)}>Back</Button>\n )}\n <Button\n size=\"sm\"\n variant=\"primary\"\n onClick={() => (index === steps.length - 1 ? finish() : setIndex((i) => i + 1))}\n >\n {index === steps.length - 1 ? finishLabel : \"Next\"}\n </Button>\n </div>\n </motion.div>\n </>\n )}\n </AnimatePresence>,\n document.body,\n );\n}\n","import { useState, type ReactNode } from \"react\";\nimport { ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface TreeNode {\n id: string;\n label: ReactNode;\n icon?: ReactNode;\n /** Right-aligned slot — a count, a badge, a menu. */\n trailing?: ReactNode;\n children?: readonly TreeNode[];\n}\n\nexport interface TreeProps {\n nodes: readonly TreeNode[];\n selectedId?: string;\n onSelect?: (id: string) => void;\n defaultExpanded?: readonly string[];\n className?: string;\n}\n\n/**\n * A nested list you can collapse — the chat tree, lorebook entries by category,\n * a file bundle. Rows are buttons, so the whole tree is keyboard-operable.\n */\nexport function Tree({ nodes, selectedId, onSelect, defaultExpanded = [], className }: TreeProps) {\n const [expanded, setExpanded] = useState(() => new Set(defaultExpanded));\n const toggle = (id: string) =>\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n\n const render = (list: readonly TreeNode[], depth: number): ReactNode =>\n list.map((node) => {\n const hasChildren = Boolean(node.children?.length);\n const open = expanded.has(node.id);\n return (\n <li key={node.id} role=\"none\">\n <div\n role=\"treeitem\"\n aria-expanded={hasChildren ? open : undefined}\n aria-selected={selectedId === node.id}\n className={cn(\n \"group flex items-center gap-1 rounded-lg pr-1.5 transition-colors\",\n selectedId === node.id ? \"bg-fill-2 text-fg\" : \"text-fg-2 hover:bg-fill\",\n )}\n style={{ paddingLeft: depth * 14 }}\n >\n <button\n type=\"button\"\n onClick={() => hasChildren && toggle(node.id)}\n aria-label={hasChildren ? (open ? \"Collapse\" : \"Expand\") : undefined}\n tabIndex={hasChildren ? 0 : -1}\n className={cn(\"touch-target flex h-7 w-5 shrink-0 items-center justify-center text-fg-3\", !hasChildren && \"invisible\")}\n >\n <ChevronRight size={14} className={cn(\"transition-transform motion-instant\", open && \"rotate-90\")} />\n </button>\n <button\n type=\"button\"\n onClick={() => onSelect?.(node.id)}\n className=\"flex min-w-0 flex-1 items-center gap-2 py-1.5 text-left text-base\"\n >\n {node.icon && <span className=\"shrink-0 text-fg-3\">{node.icon}</span>}\n <span className=\"min-w-0 truncate\">{node.label}</span>\n </button>\n {node.trailing && <span className=\"shrink-0\">{node.trailing}</span>}\n </div>\n {hasChildren && open && (\n <ul role=\"group\" className=\"list-none\">\n {render(node.children!, depth + 1)}\n </ul>\n )}\n </li>\n );\n });\n\n return (\n <ul role=\"tree\" className={cn(\"list-none space-y-px\", className)}>\n {render(nodes, 0)}\n </ul>\n );\n}\n","import { useRef, type ReactNode } from \"react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { cn } from \"../lib/cn\";\n\nexport interface VirtualListProps<T> {\n items: readonly T[];\n /** Rendered per row. Keep it cheap — it runs on every scroll frame. */\n children: (item: T, index: number) => ReactNode;\n /** Estimated row height in px; exact values are measured after mount. */\n estimateSize?: number;\n overscan?: number;\n /** Stable key per row, so React reuses the right nodes. */\n itemKey?: (item: T, index: number) => string | number;\n className?: string;\n}\n\n/**\n * Renders only the rows in view. `@tanstack/react-virtual` is already a dependency but\n * only two of the app's long-list screens use it — chat memories, logs and the model\n * browser all mount every row.\n */\nexport function VirtualList<T>({ items, children, estimateSize = 56, overscan = 8, itemKey, className }: VirtualListProps<T>) {\n const parentRef = useRef<HTMLDivElement>(null);\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => estimateSize,\n overscan,\n getItemKey: itemKey ? (index) => itemKey(items[index], index) : undefined,\n });\n\n return (\n <div ref={parentRef} className={cn(\"scrollbar-thin overflow-y-auto\", className)}>\n <div style={{ height: virtualizer.getTotalSize(), position: \"relative\", width: \"100%\" }}>\n {virtualizer.getVirtualItems().map((row) => (\n <div\n key={row.key}\n ref={virtualizer.measureElement}\n data-index={row.index}\n style={{ position: \"absolute\", top: 0, left: 0, width: \"100%\", transform: `translateY(${row.start}px)` }}\n >\n {children(items[row.index], row.index)}\n </div>\n ))}\n </div>\n </div>\n );\n}\n","import { cn } from \"../lib/cn\";\n\nconst HANDLES = [\n { dir: \"North\", className: \"left-2 right-2 top-0 h-1 cursor-n-resize\" },\n { dir: \"South\", className: \"left-2 right-2 bottom-0 h-1 cursor-s-resize\" },\n { dir: \"West\", className: \"top-2 bottom-2 left-0 w-1 cursor-w-resize\" },\n { dir: \"East\", className: \"top-2 bottom-2 right-0 w-1 cursor-e-resize\" },\n { dir: \"NorthWest\", className: \"left-0 top-0 h-2.5 w-2.5 cursor-nw-resize\" },\n { dir: \"NorthEast\", className: \"right-0 top-0 h-2.5 w-2.5 cursor-ne-resize\" },\n { dir: \"SouthWest\", className: \"bottom-0 left-0 h-2.5 w-2.5 cursor-sw-resize\" },\n { dir: \"SouthEast\", className: \"bottom-0 right-0 h-2.5 w-2.5 cursor-se-resize\" },\n] as const;\n\nexport type ResizeDirection = (typeof HANDLES)[number][\"dir\"];\n\nexport interface WindowResizeHandlesProps {\n /** Start a native window resize — wire to Tauri's `startResizeDragging(dir)`. */\n onResizeStart: (direction: ResizeDirection) => void;\n /** Hidden when the window can't be resized: maximised, full screen, or native chrome. */\n disabled?: boolean;\n}\n\n/**\n * Invisible grab strips around a frameless desktop window. macOS keeps its own chrome,\n * so this is for Windows and Linux when the app draws its own title bar.\n */\nexport function WindowResizeHandles({ onResizeStart, disabled }: WindowResizeHandlesProps) {\n if (disabled) return null;\n return (\n <>\n {HANDLES.map(({ dir, className }) => (\n <div\n key={dir}\n aria-hidden=\"true\"\n data-tauri-drag-region=\"false\"\n onPointerDown={(event) => {\n if (event.button !== 0) return;\n event.preventDefault();\n onResizeStart(dir);\n }}\n className={cn(\"fixed z-[101] select-none\", className)}\n />\n ))}\n </>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { ArrowLeft } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { useCompactLayout } from \"../lib/useMediaQuery\";\nimport { Button } from \"./Button\";\n\nexport interface ActionBarProps {\n /** The one thing to do next. */\n primary?: ReactNode;\n /** Beside it — Skip, Save draft. */\n secondary?: ReactNode;\n /** A Back button on the left; pass the handler. */\n onBack?: () => void;\n backLabel?: string;\n /** Anything else on the left — a count, a hint. */\n leading?: ReactNode;\n /**\n * Pin to the bottom of the screen with the home indicator kept clear. Default: on\n * compact layouts. Off, it is an ordinary row at the end of the content.\n */\n pinned?: boolean;\n className?: string;\n}\n\n/**\n * The row that moves a flow forward: Back on the left, the main action on the right,\n * a secondary beside it if the screen offers one. On the phone it stays put above the\n * home indicator; on the desktop it sits under the content. Every wizard, every\n * multi-step form uses this, so the buttons are in the same place on every screen.\n */\nexport function ActionBar({ primary, secondary, onBack, backLabel = \"Back\", leading, pinned, className }: ActionBarProps) {\n const compact = useCompactLayout();\n const pin = pinned ?? compact;\n return (\n <div\n className={cn(\n \"flex items-center gap-2\",\n pin\n ? \"sticky bottom-0 z-20 border-t border-line bg-surface/90 px-4 pt-3 pb-[calc(var(--safe-bottom,0px)+0.75rem)] backdrop-blur-md\"\n : \"pt-8\",\n className,\n )}\n >\n {onBack && !pin && (\n <Button variant=\"ghost\" leading={<ArrowLeft size={icon.md} />} onClick={onBack}>{backLabel}</Button>\n )}\n {leading}\n <span className=\"flex-1\" />\n {secondary}\n {primary}\n </div>\n );\n}\n","import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { Check } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface ChoiceCardProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n selected: boolean;\n title: ReactNode;\n description?: ReactNode;\n /** Left of the title, in a tile. */\n icon?: ReactNode;\n /** Right of the title — a badge, a price. */\n meta?: ReactNode;\n /** The selection mark: a tick for one-of-many, a box for any-of-many, or none when the border says enough. */\n indicator?: \"radio\" | \"checkbox\" | \"none\";\n /** Below the description — bullet lists, a form that opens once chosen. */\n children?: ReactNode;\n /** `row` puts icon, text and mark on one line; `stack` puts the icon above the text, for grids of equal cards. */\n layout?: \"row\" | \"stack\";\n}\n\n/**\n * One option among a few: a provider, a plan, a memory mode, a character to add to a\n * group. The selected border is the state, the mark confirms it, and every card in\n * a grid is the same height so the row reads as a set.\n */\nexport const ChoiceCard = forwardRef<HTMLButtonElement, ChoiceCardProps>(function ChoiceCard(\n { selected, title, description, icon, meta, indicator = \"radio\", children, layout = \"row\", className, type = \"button\", ...rest },\n ref,\n) {\n const mark =\n indicator === \"none\" ? null : (\n <span\n aria-hidden=\"true\"\n className={cn(\n \"flex h-5 w-5 shrink-0 items-center justify-center border transition-colors motion-instant\",\n indicator === \"radio\" ? \"rounded-full\" : \"rounded-md\",\n selected ? \"border-accent bg-accent text-on-accent\" : \"border-line-3\",\n )}\n >\n {selected && <Check size={12} strokeWidth={3} />}\n </span>\n );\n return (\n <button\n ref={ref}\n type={type}\n aria-pressed={selected}\n className={cn(\n \"flex h-full w-full rounded-2xl border bg-surface-1 p-4 text-left transition-colors motion-instant\",\n \"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent\",\n selected ? \"border-accent bg-accent/8\" : \"border-line hover:border-line-2 hover:bg-fill\",\n layout === \"row\" ? \"flex-col\" : \"flex-col\",\n className,\n )}\n {...rest}\n >\n <span className={cn(\"flex w-full gap-3\", layout === \"row\" ? \"items-start\" : \"flex-col items-start\")}>\n {icon && (\n <span className={cn(\"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl\", selected ? \"bg-accent/15 text-accent\" : \"bg-fill-2 text-fg-2\")}>\n {icon}\n </span>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-center gap-2\">\n <span className=\"min-w-0 flex-1 text-base font-semibold text-fg\">{title}</span>\n {meta}\n {layout === \"row\" && mark}\n </span>\n {description && <span className=\"mt-0.5 block text-sm leading-snug text-fg-2\">{description}</span>}\n </span>\n {layout === \"stack\" && mark && <span className=\"absolute right-4 top-4\">{mark}</span>}\n </span>\n {children && <span className=\"mt-3 block w-full\">{children}</span>}\n </button>\n );\n});\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { IconButton } from \"./IconButton\";\n\nexport interface ShelfProps {\n /** One node per item; each is given the same width. */\n children: ReactNode[];\n /** Item width — a Tailwind width class. */\n itemClassName?: string;\n /** Bleed to the container's edges so the first item starts at the page margin. */\n bleed?: boolean;\n \"aria-label\": string;\n className?: string;\n}\n\n/**\n * A row that scrolls sideways: swipe on touch, arrows where there is a pointer, and\n * the ends fade to say there is more. Discover's shelves, image variants, the guide's\n * screenshots — anything that is a set laid side by side.\n */\nexport function Shelf({ children, itemClassName = \"w-40\", bleed = true, className, ...aria }: ShelfProps) {\n const ref = useRef<HTMLDivElement>(null);\n const [edges, setEdges] = useState({ start: false, end: false });\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const measure = () => setEdges({ start: el.scrollLeft > 4, end: el.scrollLeft + el.clientWidth < el.scrollWidth - 4 });\n measure();\n el.addEventListener(\"scroll\", measure, { passive: true });\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => { el.removeEventListener(\"scroll\", measure); ro.disconnect(); };\n }, [children.length]);\n\n const page = (dir: 1 | -1) => ref.current?.scrollBy({ left: dir * ref.current.clientWidth * 0.8, behavior: \"smooth\" });\n const mask =\n edges.start && edges.end ? \"linear-gradient(90deg, transparent, black 32px, black calc(100% - 32px), transparent)\"\n : edges.start ? \"linear-gradient(90deg, transparent, black 32px)\"\n : edges.end ? \"linear-gradient(90deg, black calc(100% - 32px), transparent)\"\n : undefined;\n\n return (\n <div className={cn(\"group/shelf relative\", className)}>\n <div\n ref={ref}\n role=\"list\"\n aria-label={aria[\"aria-label\"]}\n style={{ maskImage: mask, WebkitMaskImage: mask }}\n className={cn(\"flex snap-x snap-mandatory gap-3 overflow-x-auto pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\", bleed && \"-mx-4 px-4 @xl:-mx-6 @xl:px-6\")}\n >\n {children.map((child, i) => (\n <div key={i} role=\"listitem\" className={cn(\"shrink-0 snap-start\", itemClassName)}>{child}</div>\n ))}\n </div>\n {/* Arrows only where a finger can't swipe. */}\n <div className=\"pointer-events-none absolute inset-y-0 left-0 right-0 hidden items-center justify-between [@media(pointer:fine)]:flex\">\n <IconButton label=\"Scroll back\" variant=\"secondary\" shape=\"round\" className={cn(\"pointer-events-auto -ml-2 shadow-raised transition-opacity\", edges.start ? \"opacity-0 group-hover/shelf:opacity-100\" : \"opacity-0\")} onClick={() => page(-1)} tabIndex={edges.start ? 0 : -1}>\n <ChevronLeft size={icon.lg} />\n </IconButton>\n <IconButton label=\"Scroll forward\" variant=\"secondary\" shape=\"round\" className={cn(\"pointer-events-auto -mr-2 shadow-raised transition-opacity\", edges.end ? \"opacity-0 group-hover/shelf:opacity-100\" : \"opacity-0\")} onClick={() => page(1)} tabIndex={edges.end ? 0 : -1}>\n <ChevronRight size={icon.lg} />\n </IconButton>\n </div>\n </div>\n );\n}\n","import { useState, type ReactNode } from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { motion as m } from \"../lib/motion\";\nimport { Stepper, type Step } from \"./Stepper\";\n\nexport interface WizardState {\n index: number;\n step: Step;\n first: boolean;\n last: boolean;\n next: () => void;\n back: () => void;\n goTo: (index: number) => void;\n}\n\n/** Where you are in a stepped flow, and the two moves. */\nexport function useWizard(steps: readonly Step[], initial = 0): WizardState {\n const [index, setIndex] = useState(initial);\n const clamp = (i: number) => Math.max(0, Math.min(steps.length - 1, i));\n return {\n index,\n step: steps[index],\n first: index === 0,\n last: index === steps.length - 1,\n next: () => setIndex((i) => clamp(i + 1)),\n back: () => setIndex((i) => clamp(i - 1)),\n goTo: (i) => setIndex(clamp(i)),\n };\n}\n\nexport interface WizardProps {\n steps: readonly Step[];\n index: number;\n /** Jump back to a completed step from the stepper. */\n onStepClick?: (index: number) => void;\n /** Shown above the step's content; a title and a lead for this step. */\n title?: ReactNode;\n description?: ReactNode;\n /** The stepper: the labelled bar, the compact dots, or nothing. */\n progress?: \"bar\" | \"dots\" | \"none\";\n className?: string;\n children: ReactNode;\n}\n\n/**\n * The frame around a multi-step flow: the stepper, the step's heading, and the step's\n * content sliding in the direction of travel. Character creation, onboarding, the\n * lorebook generator and the engine wizard each drew their own; this is the one.\n * Pair with `useWizard` for the state and `ActionBar` for the buttons.\n */\nexport function Wizard({ steps, index, onStepClick, title, description, progress = \"bar\", className, children }: WizardProps) {\n const reduced = useReducedMotion();\n const [last, setLast] = useState(index);\n const dir = index >= last ? 1 : -1;\n if (last !== index) setLast(index);\n return (\n <div className={cn(\"space-y-6\", className)}>\n {progress !== \"none\" && <Stepper steps={steps} current={index} onStepClick={onStepClick} variant={progress} />}\n <AnimatePresence mode=\"wait\" initial={false} custom={dir}>\n <motion.div\n key={index}\n custom={dir}\n initial={reduced ? false : { opacity: 0, x: 24 * dir }}\n animate={{ opacity: 1, x: 0 }}\n exit={reduced ? undefined : { opacity: 0, x: -24 * dir }}\n transition={m.settle}\n >\n {(title || description) && (\n <div className=\"mb-6\">\n {title && <h1 className=\"text-2xl font-bold tracking-tight text-fg @2xl:text-3xl\">{title}</h1>}\n {description && <p className=\"mt-2 max-w-xl text-base leading-relaxed text-fg-2\">{description}</p>}\n </div>\n )}\n {children}\n </motion.div>\n </AnimatePresence>\n </div>\n );\n}\n","import { forwardRef, useState, type InputHTMLAttributes, type ReactNode } from \"react\";\nimport { Check, ClipboardPaste, Eye, EyeOff, X } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { useFieldContext } from \"./Field\";\nimport { IconButton } from \"./IconButton\";\nimport { inputSurface } from \"./Input\";\n\nexport type SecretStatus = { state: \"idle\" } | { state: \"checking\" } | { state: \"ok\"; message?: ReactNode } | { state: \"error\"; message: ReactNode };\n\nexport interface SecretInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\" | \"onChange\"> {\n value: string;\n onChange: (value: string) => void;\n /** What a check of the key came back with — drawn under the field. */\n status?: SecretStatus;\n /** Offer a paste button (reads the clipboard on tap). Default on. */\n paste?: boolean;\n}\n\n/**\n * An API key or password: masked by default with a reveal toggle, a paste button\n * where the clipboard is reachable, and room under it for what a connection test\n * said. One field for onboarding, providers and settings alike.\n */\nexport const SecretInput = forwardRef<HTMLInputElement, SecretInputProps>(function SecretInput(\n { value, onChange, status = { state: \"idle\" }, paste = true, className, id, disabled, ...rest },\n ref,\n) {\n const field = useFieldContext();\n const [shown, setShown] = useState(false);\n const canPaste = paste && typeof navigator !== \"undefined\" && Boolean(navigator.clipboard?.readText);\n\n const pasteIn = async () => {\n try {\n const text = (await navigator.clipboard.readText()).trim();\n if (text) onChange(text);\n } catch {\n /* Clipboard read refused: the field is still there to type into. */\n }\n };\n\n return (\n <div>\n <div className=\"relative\">\n <input\n ref={ref}\n id={id ?? field?.id}\n type={shown ? \"text\" : \"password\"}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n disabled={disabled}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n spellCheck={false}\n aria-describedby={rest[\"aria-describedby\"] ?? field?.describedBy}\n aria-invalid={status.state === \"error\" || field?.invalid || undefined}\n className={cn(inputSurface, \"control-md px-3.5 font-mono text-sm tracking-wide\", canPaste ? \"pr-20\" : \"pr-11\", className)}\n {...rest}\n />\n <span className=\"absolute right-1 top-1/2 flex -translate-y-1/2 items-center gap-0.5\">\n {canPaste && !value && (\n <IconButton label=\"Paste\" size=\"sm\" disabled={disabled} onClick={pasteIn}><ClipboardPaste size={icon.sm} /></IconButton>\n )}\n {value && (\n <IconButton label=\"Clear\" size=\"sm\" disabled={disabled} onClick={() => onChange(\"\")}><X size={icon.sm} /></IconButton>\n )}\n <IconButton label={shown ? \"Hide\" : \"Show\"} size=\"sm\" active={shown} disabled={disabled} onClick={() => setShown((s) => !s)}>\n {shown ? <EyeOff size={icon.sm} /> : <Eye size={icon.sm} />}\n </IconButton>\n </span>\n </div>\n {status.state !== \"idle\" && (\n <p role=\"status\" className={cn(\"mt-1.5 flex items-center gap-1.5 text-sm\", status.state === \"ok\" ? \"text-accent\" : status.state === \"error\" ? \"text-danger\" : \"text-fg-3\")}>\n {status.state === \"checking\" && <span className=\"h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent\" />}\n {status.state === \"ok\" && <Check size={icon.sm} />}\n {status.state === \"error\" && <X size={icon.sm} />}\n {status.state === \"checking\" ? \"Checking…\" : status.state === \"ok\" ? (status.message ?? \"Connected\") : status.message}\n </p>\n )}\n </div>\n );\n});\n","import { type KeyboardEvent, type ReactNode } from \"react\";\nimport { Reorder, useDragControls, useReducedMotion } from \"framer-motion\";\nimport { GripVertical } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { motion as m } from \"../lib/motion\";\n\nexport interface ReorderableListProps<T> {\n items: readonly T[];\n onReorder: (items: T[]) => void;\n keyOf: (item: T) => string;\n /** Draw one item. `handle` is the grab handle; put it where the row wants it. */\n children: (item: T, handle: ReactNode, index: number) => ReactNode;\n /** `y` (default) stacks; `x` lays the items in a row. */\n axis?: \"x\" | \"y\";\n /** Only the handle starts a drag. Off, the whole row does. Default on. */\n handleOnly?: boolean;\n \"aria-label\": string;\n className?: string;\n itemClassName?: string;\n}\n\n/**\n * A list whose order is the point: lorebook entries, starting scenes, widgets.\n * Drag by the handle (or the row), or focus the handle and press Alt+↑/↓. The item\n * being dragged lifts; the others slide out of its way.\n */\nexport function ReorderableList<T>({ items, onReorder, keyOf, children, axis = \"y\", handleOnly = true, className, itemClassName, ...aria }: ReorderableListProps<T>) {\n const move = (from: number, to: number) => {\n if (to < 0 || to >= items.length || from === to) return;\n const next = [...items];\n const [item] = next.splice(from, 1);\n next.splice(to, 0, item);\n onReorder(next);\n };\n return (\n <Reorder.Group\n axis={axis}\n values={items as T[]}\n onReorder={onReorder}\n aria-label={aria[\"aria-label\"]}\n className={cn(\"flex\", axis === \"y\" ? \"flex-col gap-2\" : \"flex-row gap-2\", className)}\n >\n {items.map((item, index) => (\n <Item key={keyOf(item)} item={item} index={index} count={items.length} handleOnly={handleOnly} axis={axis} onMove={move} className={itemClassName}>\n {children}\n </Item>\n ))}\n </Reorder.Group>\n );\n}\n\nfunction Item<T>({\n item, index, count, handleOnly, axis, onMove, className, children,\n}: {\n item: T;\n index: number;\n count: number;\n handleOnly: boolean;\n axis: \"x\" | \"y\";\n onMove: (from: number, to: number) => void;\n className?: string;\n children: (item: T, handle: ReactNode, index: number) => ReactNode;\n}) {\n const controls = useDragControls();\n const reduced = useReducedMotion();\n const onKey = (e: KeyboardEvent) => {\n if (!e.altKey) return;\n const back = axis === \"y\" ? \"ArrowUp\" : \"ArrowLeft\";\n const fwd = axis === \"y\" ? \"ArrowDown\" : \"ArrowRight\";\n if (e.key === back) { e.preventDefault(); onMove(index, index - 1); }\n if (e.key === fwd) { e.preventDefault(); onMove(index, index + 1); }\n };\n const handle = (\n <button\n type=\"button\"\n aria-label={`Reorder, item ${index + 1} of ${count}. Alt and arrow keys move it.`}\n onKeyDown={onKey}\n onPointerDown={(e) => controls.start(e)}\n className=\"tap-target flex h-8 w-6 shrink-0 cursor-grab touch-none items-center justify-center rounded-md text-fg-4 hover:bg-fill-2 hover:text-fg-2 active:cursor-grabbing\"\n >\n <GripVertical size={icon.md} />\n </button>\n );\n return (\n <Reorder.Item\n value={item}\n dragListener={!handleOnly}\n dragControls={controls}\n layout\n transition={reduced ? { duration: 0 } : m.settle}\n whileDrag={{ scale: 1.02, boxShadow: \"var(--shadow-raised)\", zIndex: 1 }}\n className={cn(\"relative rounded-2xl\", className)}\n >\n {children(item, handle, index)}\n </Reorder.Item>\n );\n}\n","import { useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from \"react\";\nimport { Camera, Trash2, ZoomIn } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { Avatar, type AvatarProps } from \"./Avatar\";\nimport { Button } from \"./Button\";\nimport { Dialog } from \"./Dialog\";\nimport { Dropzone } from \"./Dropzone\";\nimport { Slider } from \"./Slider\";\n\nexport interface AvatarPickerProps {\n value: string | null;\n /** Called with a square data URL, or null when the picture is removed. */\n onChange: (dataUrl: string | null) => void;\n /** Initials when there's no picture. */\n name?: string;\n size?: AvatarProps[\"size\"];\n /** Pixel size of the square that comes out. Default 512. */\n output?: number;\n /** Skip the crop step and take the picture as it comes. */\n crop?: boolean;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * The avatar as a target: tap or drop to pick, then frame it — drag to move, slide to\n * zoom — and out comes a square. Characters, personas and groups all start here.\n */\nexport function AvatarPicker({ value, onChange, name = \"?\", size = \"xl\", output = 512, crop = true, disabled, className }: AvatarPickerProps) {\n const [pending, setPending] = useState<string | null>(null);\n\n const read = (file: File) => {\n const reader = new FileReader();\n reader.onload = () => (crop ? setPending(String(reader.result)) : onChange(String(reader.result)));\n reader.readAsDataURL(file);\n };\n\n return (\n <>\n <div className={cn(\"relative w-fit\", className)}>\n <Dropzone accept=\"image/*\" disabled={disabled} onFiles={([f]) => f && read(f)} className=\"rounded-full p-0\">\n <div className=\"relative\">\n <Avatar src={value ?? undefined} name={name} size={size} className={cn(size === \"xl\" && \"h-28 w-28 text-3xl\")} />\n <span aria-hidden=\"true\" className=\"absolute -bottom-1 -right-1 flex h-9 w-9 items-center justify-center rounded-full border border-line-2 bg-surface-2 text-fg shadow-raised\">\n <Camera size={icon.md} />\n </span>\n </div>\n </Dropzone>\n {value && !disabled && (\n <button type=\"button\" aria-label=\"Remove picture\" onClick={() => onChange(null)} className=\"absolute -left-1 -top-1 flex h-7 w-7 items-center justify-center rounded-full border border-line-2 bg-surface-2 text-fg-3 shadow-raised hover:text-danger\">\n <Trash2 size={icon.xs} />\n </button>\n )}\n </div>\n <CropDialog src={pending} output={output} onClose={() => setPending(null)} onDone={(url) => { onChange(url); setPending(null); }} />\n </>\n );\n}\n\nconst BOX = 288;\n\nfunction CropDialog({ src, output, onClose, onDone }: { src: string | null; output: number; onClose: () => void; onDone: (url: string) => void }) {\n const [img, setImg] = useState<HTMLImageElement | null>(null);\n const [zoom, setZoom] = useState(1);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const drag = useRef<{ x: number; y: number; px: number; py: number } | null>(null);\n\n useEffect(() => {\n if (!src) { setImg(null); return; }\n const el = new Image();\n el.onload = () => { setImg(el); setZoom(1); setPos({ x: 0, y: 0 }); };\n el.src = src;\n }, [src]);\n\n /* The picture covers the box at zoom 1; zoom scales from there. */\n const base = img ? Math.max(BOX / img.width, BOX / img.height) : 1;\n const scale = base * zoom;\n const w = (img?.width ?? 0) * scale;\n const h = (img?.height ?? 0) * scale;\n const clamp = (p: { x: number; y: number }) => ({\n x: Math.min(Math.max(p.x, BOX - w), 0),\n y: Math.min(Math.max(p.y, BOX - h), 0),\n });\n const shown = clamp({ x: pos.x + (BOX - w) / 2, y: pos.y + (BOX - h) / 2 });\n\n const down = (e: ReactPointerEvent) => {\n drag.current = { x: e.clientX, y: e.clientY, px: pos.x, py: pos.y };\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n };\n const move = (e: ReactPointerEvent) => {\n if (!drag.current) return;\n setPos({ x: drag.current.px + e.clientX - drag.current.x, y: drag.current.py + e.clientY - drag.current.y });\n };\n const up = () => { drag.current = null; };\n\n const done = () => {\n if (!img) return;\n const canvas = document.createElement(\"canvas\");\n canvas.width = output;\n canvas.height = output;\n const ctx = canvas.getContext(\"2d\")!;\n const k = output / BOX;\n ctx.drawImage(img, shown.x * k, shown.y * k, w * k, h * k);\n onDone(canvas.toDataURL(\"image/webp\", 0.9));\n };\n\n return (\n <Dialog\n open={Boolean(src)}\n onClose={onClose}\n title=\"Frame the picture\"\n description=\"Drag to move, slide to zoom. What's in the circle is the avatar.\"\n footer={\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"ghost\" onClick={onClose}>Cancel</Button>\n <Button variant=\"primary\" disabled={!img} onClick={done}>Use picture</Button>\n </div>\n }\n >\n <div className=\"flex flex-col items-center gap-4\">\n <div\n onPointerDown={down}\n onPointerMove={move}\n onPointerUp={up}\n onPointerCancel={up}\n className=\"relative cursor-grab touch-none select-none overflow-hidden rounded-2xl bg-black active:cursor-grabbing\"\n style={{ width: BOX, height: BOX }}\n >\n {img && <img src={img.src} alt=\"\" draggable={false} className=\"absolute max-w-none\" style={{ width: w, height: h, left: shown.x, top: shown.y }} />}\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute inset-0 rounded-2xl shadow-[inset_0_0_0_9999px_rgb(0_0_0/0.5)] [mask-image:radial-gradient(circle_at_center,transparent_49%,black_50%)]\" />\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute inset-0 rounded-full ring-2 ring-white/70\" />\n </div>\n <div className=\"flex w-full items-center gap-3\">\n <ZoomIn size={icon.md} className=\"shrink-0 text-fg-3\" />\n <Slider aria-label=\"Zoom\" value={zoom} onChange={setZoom} min={1} max={3} step={0.01} className=\"flex-1\" />\n </div>\n </div>\n </Dialog>\n );\n}\n","import type { ReactNode, Ref } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport { AppBar, type AppBarProps } from \"./AppBar\";\n\nexport interface PageProps extends AppBarProps {\n /** Pinned under the content — an ActionBar, a composer. */\n footer?: ReactNode;\n /** The scrolling element, for AppBar's condensing title and scroll-to-top. */\n mainRef?: Ref<HTMLElement>;\n /** Padding around the content. `none` for lists that run edge to edge. */\n padding?: \"default\" | \"none\";\n contentClassName?: string;\n children: ReactNode;\n}\n\n/**\n * A screen of its own: the header, a scrolling body and, if there is one, a footer\n * that stays put. On the desktop it sits inside AppShell like any page; on the phone\n * it takes the whole screen — a sub-page has the back arrow, not the tab bar.\n */\nexport function Page({ footer, mainRef, padding = \"default\", contentClassName, className, children, ...bar }: PageProps) {\n return (\n <div className={cn(\"flex h-full min-h-0 flex-col\", className)}>\n <main ref={mainRef} className=\"min-h-0 flex-1 overflow-y-auto\">\n <AppBar scrollRef={mainRef as AppBarProps[\"scrollRef\"]} {...bar} />\n <div className={cn(padding === \"default\" && \"px-4 pb-10 pt-1 @xl:px-6\", contentClassName)}>{children}</div>\n </main>\n {footer}\n </div>\n );\n}\n","import { useMemo, useState, type ReactNode } from \"react\";\nimport { Check, ChevronDown, Cpu, Globe } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\nimport { icon } from \"../lib/icon\";\nimport { useCompactLayout } from \"../lib/useMediaQuery\";\nimport { Badge } from \"./Badge\";\nimport { ListGroup, ListRowButton } from \"./List\";\nimport { SelectMenu } from \"./SelectMenu\";\nimport { Sheet } from \"./Sheet\";\n\nexport interface ModelOption {\n id: string;\n name: string;\n /** Who runs it — the group heading. */\n provider: string;\n /** Runs on this device. */\n local?: boolean;\n vision?: boolean;\n audio?: boolean;\n /** Small text after the name — a size, a price. */\n meta?: string;\n}\n\nexport interface ModelSelectProps {\n models: readonly ModelOption[];\n value: string | null;\n onChange: (id: string | null) => void;\n /** Shown when nothing is picked. Default \"Choose a model\". */\n placeholder?: string;\n /** Which one the app falls back to; drawn as \"Default\" in the list. */\n defaultId?: string | null;\n /** A row at the end — \"Add a model…\". */\n footer?: ReactNode;\n disabled?: boolean;\n id?: string;\n className?: string;\n \"aria-label\"?: string;\n}\n\nconst badges = (mo: ModelOption) => (\n <span className=\"flex items-center gap-1\">\n {mo.vision && <Badge tone=\"info\">Vision</Badge>}\n {mo.audio && <Badge tone=\"secondary\">Audio</Badge>}\n </span>\n);\n\n/**\n * Picking a model, grouped by who runs it, with what it can do on the row. A menu on\n * the desktop; the bottom menu on the phone, where a dropdown would be a thumb's\n * width. The chat header, a character's settings and the default-model setting all\n * ask the same question.\n */\nexport function ModelSelect({ models, value, onChange, placeholder = \"Choose a model\", defaultId, footer, disabled, id, className, ...aria }: ModelSelectProps) {\n const compact = useCompactLayout();\n const [open, setOpen] = useState(false);\n const chosen = models.find((mo) => mo.id === value) ?? null;\n\n const options = useMemo(\n () =>\n models.map((mo) => ({\n value: mo.id,\n label: mo.name,\n description: mo.meta,\n group: mo.provider,\n icon: mo.local ? <Cpu size={icon.md} /> : <Globe size={icon.md} />,\n meta: <span className=\"flex items-center gap-1\">{badges(mo)}{mo.id === defaultId && <Badge tone=\"accent\" dot>Default</Badge>}</span>,\n })),\n [models, defaultId],\n );\n\n if (!compact) {\n return <SelectMenu id={id} options={options} value={value} onChange={onChange} placeholder={placeholder} disabled={disabled} className={className} aria-label={aria[\"aria-label\"]} />;\n }\n\n const groups = [...new Set(models.map((mo) => mo.provider))];\n return (\n <>\n <button\n type=\"button\"\n id={id}\n disabled={disabled}\n aria-haspopup=\"dialog\"\n aria-label={aria[\"aria-label\"]}\n onClick={() => setOpen(true)}\n className={cn(\"control-md flex w-full items-center gap-2.5 rounded-xl border border-line bg-fill px-3.5 text-left text-base text-fg disabled:opacity-40\", className)}\n >\n <span className=\"shrink-0 text-fg-3\">{chosen?.local ? <Cpu size={icon.md} /> : <Globe size={icon.md} />}</span>\n <span className={cn(\"min-w-0 flex-1 truncate\", !chosen && \"text-fg-4\")}>{chosen?.name ?? placeholder}</span>\n {chosen && <span className=\"hidden @sm:flex\">{badges(chosen)}</span>}\n <ChevronDown size={icon.md} className=\"shrink-0 text-fg-3\" />\n </button>\n <Sheet open={open} onClose={() => setOpen(false)} title={aria[\"aria-label\"] ?? \"Model\"} detents={[0.6, 0.92]}>\n <div className=\"space-y-5\">\n {groups.map((g) => (\n <ListGroup key={g} label={g}>\n {models.filter((mo) => mo.provider === g).map((mo) => (\n <ListRowButton\n key={mo.id}\n icon={mo.local ? <Cpu size={icon.lg} /> : <Globe size={icon.lg} />}\n tone={mo.local ? \"accent\" : \"info\"}\n title={mo.name}\n description={<span className=\"flex flex-wrap items-center gap-1.5\">{mo.meta}{badges(mo)}{mo.id === defaultId && <Badge tone=\"accent\" dot>Default</Badge>}</span>}\n chevron={false}\n trailing={mo.id === value ? <Check size={icon.md} className=\"text-accent\" /> : undefined}\n onClick={() => { onChange(mo.id); setOpen(false); }}\n />\n ))}\n </ListGroup>\n ))}\n {footer}\n </div>\n </Sheet>\n </>\n );\n}\n","import { forwardRef, type ElementType, type ForwardedRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport type { PolymorphicComponent, PolymorphicProps } from \"../lib/polymorphic\";\n\n/**\n * The root primitive. A `div` by default; `as` swaps the element, `className` styles it.\n * Styling is Tailwind classes, not style props — that keeps one styling language across the codebase.\n */\nexport const Box = forwardRef(function Box<C extends ElementType = \"div\">(\n { as, className, ...rest }: PolymorphicProps<C>,\n ref: ForwardedRef<unknown>,\n) {\n const Tag = (as ?? \"div\") as ElementType;\n return <Tag ref={ref} className={cn(className)} {...rest} />;\n}) as PolymorphicComponent<\"div\">;\n","import { forwardRef, type ElementType, type ForwardedRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport type { PolymorphicComponent, PolymorphicProps } from \"../lib/polymorphic\";\n\nexport const Center = forwardRef(function Center<C extends ElementType = \"div\">(\n { as, className, ...rest }: PolymorphicProps<C>,\n ref: ForwardedRef<unknown>,\n) {\n const Tag = (as ?? \"div\") as ElementType;\n return <Tag ref={ref} className={cn(\"flex items-center justify-center\", className)} {...rest} />;\n}) as PolymorphicComponent<\"div\">;\n","import { forwardRef, type ElementType, type ForwardedRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport type { PolymorphicComponent, PolymorphicProps } from \"../lib/polymorphic\";\n\nexport interface ContainerOwnProps {\n /** sm 640 · md 768 · lg 1024 · xl 1280 · prose 65ch (reading column) */\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"prose\";\n /** Drop the horizontal padding — for containers nested in something already padded. */\n flush?: boolean;\n}\n\nconst sizeClass = { sm: \"max-w-screen-sm\", md: \"max-w-screen-md\", lg: \"max-w-screen-lg\", xl: \"max-w-screen-xl\", prose: \"max-w-prose\" };\n\nexport const Container = forwardRef(function Container<C extends ElementType = \"div\">(\n { as, size = \"lg\", flush, className, ...rest }: PolymorphicProps<C, ContainerOwnProps>,\n ref: ForwardedRef<unknown>,\n) {\n const Tag = (as ?? \"div\") as ElementType;\n return <Tag ref={ref} className={cn(\"mx-auto w-full\", sizeClass[size], !flush && \"px-4 sm:px-6\", className)} {...rest} />;\n}) as PolymorphicComponent<\"div\", ContainerOwnProps>;\n","import { forwardRef, type HTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface DividerProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n orientation?: \"horizontal\" | \"vertical\";\n /** Text set into the line — \"or\", a date, a section name. */\n label?: ReactNode;\n /** Vertical rhythm around a horizontal divider. */\n spacing?: \"none\" | \"sm\" | \"md\" | \"lg\";\n}\n\nconst spacingClass = { none: \"\", sm: \"my-2\", md: \"my-4\", lg: \"my-8\" };\n\nexport const Divider = forwardRef<HTMLDivElement, DividerProps>(function Divider(\n { orientation = \"horizontal\", label, spacing = \"none\", className, ...rest },\n ref,\n) {\n if (orientation === \"vertical\") {\n return <div ref={ref} role=\"separator\" aria-orientation=\"vertical\" className={cn(\"w-px self-stretch bg-line\", className)} {...rest} />;\n }\n if (!label) {\n return <div ref={ref} role=\"separator\" className={cn(\"h-px w-full bg-line\", spacingClass[spacing], className)} {...rest} />;\n }\n return (\n <div ref={ref} role=\"separator\" className={cn(\"flex items-center gap-3\", spacingClass[spacing], className)} {...rest}>\n <span className=\"h-px flex-1 bg-line\" />\n <span className=\"shrink-0 text-xs text-fg-3\">{label}</span>\n <span className=\"h-px flex-1 bg-line\" />\n </div>\n );\n});\n","import { forwardRef, type ElementType, type ForwardedRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport type { PolymorphicComponent, PolymorphicProps } from \"../lib/polymorphic\";\n\nexport type Gap = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16;\nexport type Align = \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\";\nexport type Justify = \"start\" | \"center\" | \"end\" | \"between\" | \"around\" | \"evenly\";\n\n/* Static maps: Tailwind only ships classes it can see in source. */\nexport const gapClass: Record<Gap, string> = {\n 0: \"gap-0\", 0.5: \"gap-0.5\", 1: \"gap-1\", 1.5: \"gap-1.5\", 2: \"gap-2\", 2.5: \"gap-2.5\", 3: \"gap-3\",\n 4: \"gap-4\", 5: \"gap-5\", 6: \"gap-6\", 8: \"gap-8\", 10: \"gap-10\", 12: \"gap-12\", 16: \"gap-16\",\n};\nexport const alignClass: Record<Align, string> = {\n start: \"items-start\", center: \"items-center\", end: \"items-end\", stretch: \"items-stretch\", baseline: \"items-baseline\",\n};\nexport const justifyClass: Record<Justify, string> = {\n start: \"justify-start\", center: \"justify-center\", end: \"justify-end\",\n between: \"justify-between\", around: \"justify-around\", evenly: \"justify-evenly\",\n};\n\nexport interface FlexOwnProps {\n direction?: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\";\n align?: Align;\n justify?: Justify;\n wrap?: boolean;\n gap?: Gap;\n inline?: boolean;\n}\n\nconst directionClass = {\n row: \"flex-row\", column: \"flex-col\", \"row-reverse\": \"flex-row-reverse\", \"column-reverse\": \"flex-col-reverse\",\n};\n\nexport const Flex = forwardRef(function Flex<C extends ElementType = \"div\">(\n { as, direction = \"row\", align, justify, wrap, gap, inline, className, ...rest }: PolymorphicProps<C, FlexOwnProps>,\n ref: ForwardedRef<unknown>,\n) {\n const Tag = (as ?? \"div\") as ElementType;\n return (\n <Tag\n ref={ref}\n className={cn(\n inline ? \"inline-flex\" : \"flex\",\n directionClass[direction],\n align && alignClass[align],\n justify && justifyClass[justify],\n wrap && \"flex-wrap\",\n gap !== undefined && gapClass[gap],\n className,\n )}\n {...rest}\n />\n );\n}) as PolymorphicComponent<\"div\", FlexOwnProps>;\n","import { forwardRef, type ElementType, type ForwardedRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport type { PolymorphicComponent, PolymorphicProps } from \"../lib/polymorphic\";\nimport { gapClass, type Gap } from \"./Flex\";\n\nexport type Columns = 1 | 2 | 3 | 4 | 5 | 6 | 12;\nexport type Breakpoint = \"base\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type ResponsiveColumns = Columns | Partial<Record<Breakpoint, Columns>>;\n\nconst colsClass: Record<Breakpoint, Record<Columns, string>> = {\n base: { 1: \"grid-cols-1\", 2: \"grid-cols-2\", 3: \"grid-cols-3\", 4: \"grid-cols-4\", 5: \"grid-cols-5\", 6: \"grid-cols-6\", 12: \"grid-cols-12\" },\n sm: { 1: \"sm:grid-cols-1\", 2: \"sm:grid-cols-2\", 3: \"sm:grid-cols-3\", 4: \"sm:grid-cols-4\", 5: \"sm:grid-cols-5\", 6: \"sm:grid-cols-6\", 12: \"sm:grid-cols-12\" },\n md: { 1: \"md:grid-cols-1\", 2: \"md:grid-cols-2\", 3: \"md:grid-cols-3\", 4: \"md:grid-cols-4\", 5: \"md:grid-cols-5\", 6: \"md:grid-cols-6\", 12: \"md:grid-cols-12\" },\n lg: { 1: \"lg:grid-cols-1\", 2: \"lg:grid-cols-2\", 3: \"lg:grid-cols-3\", 4: \"lg:grid-cols-4\", 5: \"lg:grid-cols-5\", 6: \"lg:grid-cols-6\", 12: \"lg:grid-cols-12\" },\n xl: { 1: \"xl:grid-cols-1\", 2: \"xl:grid-cols-2\", 3: \"xl:grid-cols-3\", 4: \"xl:grid-cols-4\", 5: \"xl:grid-cols-5\", 6: \"xl:grid-cols-6\", 12: \"xl:grid-cols-12\" },\n};\n\nexport interface GridOwnProps {\n /** A number, or per-breakpoint: `{ base: 1, sm: 2, lg: 3 }`. */\n columns?: ResponsiveColumns;\n gap?: Gap;\n /** Auto-fit columns with a minimum track width — for card grids that should just flow. */\n minChildWidth?: string;\n}\n\nexport const Grid = forwardRef(function Grid<C extends ElementType = \"div\">(\n { as, columns, gap = 4, minChildWidth, className, style, ...rest }: PolymorphicProps<C, GridOwnProps>,\n ref: ForwardedRef<unknown>,\n) {\n const Tag = (as ?? \"div\") as ElementType;\n const columnClasses =\n columns === undefined\n ? null\n : typeof columns === \"number\"\n ? colsClass.base[columns]\n : (Object.entries(columns) as [Breakpoint, Columns][]).map(([bp, n]) => colsClass[bp][n]);\n return (\n <Tag\n ref={ref}\n className={cn(\"grid\", gapClass[gap], columnClasses, className)}\n style={minChildWidth ? { gridTemplateColumns: `repeat(auto-fit, minmax(min(${minChildWidth}, 100%), 1fr))`, ...style } : style}\n {...rest}\n />\n );\n}) as PolymorphicComponent<\"div\", GridOwnProps>;\n","import { cn } from \"../lib/cn\";\n\n/** Fills the free space in a Flex/HStack so siblings push to the edges. */\nexport function Spacer({ className }: { className?: string }) {\n return <div aria-hidden=\"true\" className={cn(\"flex-1\", className)} />;\n}\n","import { forwardRef, type ElementType, type ForwardedRef } from \"react\";\nimport { cn } from \"../lib/cn\";\nimport type { PolymorphicComponent, PolymorphicProps } from \"../lib/polymorphic\";\nimport { alignClass, gapClass, justifyClass, type Align, type Gap, type Justify } from \"./Flex\";\n\nexport interface StackOwnProps {\n gap?: Gap;\n align?: Align;\n justify?: Justify;\n wrap?: boolean;\n}\n\nfunction makeStack(name: string, direction: \"row\" | \"column\", defaults: Required<Pick<StackOwnProps, \"gap\">> & Partial<StackOwnProps>) {\n const Component = forwardRef(function Stack<C extends ElementType = \"div\">(\n { as, gap = defaults.gap, align = defaults.align, justify, wrap, className, ...rest }: PolymorphicProps<C, StackOwnProps>,\n ref: ForwardedRef<unknown>,\n ) {\n const Tag = (as ?? \"div\") as ElementType;\n return (\n <Tag\n ref={ref}\n className={cn(\n \"flex\",\n direction === \"column\" ? \"flex-col\" : \"flex-row\",\n gapClass[gap],\n align && alignClass[align],\n justify && justifyClass[justify],\n wrap && \"flex-wrap\",\n className,\n )}\n {...rest}\n />\n );\n }) as PolymorphicComponent<\"div\", StackOwnProps>;\n (Component as unknown as { displayName: string }).displayName = name;\n return Component;\n}\n\n/** Vertical rhythm. Children stretch to full width. */\nexport const Stack = makeStack(\"Stack\", \"column\", { gap: 4 });\nexport const VStack = Stack;\n/** Horizontal row with vertically centred children. */\nexport const HStack = makeStack(\"HStack\", \"row\", { gap: 3, align: \"center\" });\n","/** \"Just now\", \"4 min ago\", \"Yesterday\", \"3 wk ago\" — how a list says when. */\nexport function relativeTime(when: Date | number, now: Date | number = Date.now()): string {\n const ms = +now - +when;\n const min = Math.round(ms / 60_000);\n if (min < 1) return \"Just now\";\n if (min < 60) return `${min} min ago`;\n const h = Math.floor(min / 60);\n if (h < 24) return `${h} h ago`;\n const d = Math.floor(h / 24);\n if (d === 1) return \"Yesterday\";\n if (d < 7) return `${d} days ago`;\n if (d < 30) return `${Math.floor(d / 7)} wk ago`;\n if (d < 365) return `${Math.floor(d / 30)} mo ago`;\n return `${Math.floor(d / 365)} yr ago`;\n}\n\n/** 950 → \"950\", 1 240 → \"1.2k\", 18 300 → \"18k\", 2 140 000 → \"2.1M\". */\nexport function compactNumber(n: number): string {\n const abs = Math.abs(n);\n if (abs < 1000) return String(n);\n const units: [number, string][] = [[1e9, \"B\"], [1e6, \"M\"], [1e3, \"k\"]];\n for (const [size, suffix] of units) {\n if (abs >= size) {\n const v = n / size;\n return `${v >= 10 ? Math.round(v) : v.toFixed(1).replace(/\\.0$/, \"\")}${suffix}`;\n }\n }\n return String(n);\n}\n\n/** 1 536 000 → \"1.5 MB\". */\nexport function fileSize(bytes: number): string {\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let i = 0;\n let v = bytes;\n while (v >= 1024 && i < units.length - 1) { v /= 1024; i++; }\n return `${i === 0 ? v : v.toFixed(v >= 10 ? 0 : 1)} ${units[i]}`;\n}\n"],"mappings":"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"}