{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "title": "Select",
  "description": "A form select with a two-layer proximity highlight (selected accent tint + muted hover), drawn check animation, and a trigger label morph on selection change.",
  "dependencies": [
    "motion"
  ],
  "files": [
    {
      "path": "components/ui/select.tsx",
      "type": "registry:ui",
      "content": "'use client'\n\nimport {\n  Children,\n  cloneElement,\n  createContext,\n  forwardRef,\n  isValidElement,\n  useCallback,\n  useContext,\n  useEffect,\n  useId,\n  useLayoutEffect,\n  useMemo,\n  useRef,\n  useState,\n  type HTMLAttributes,\n  type ReactElement,\n  type ReactNode,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { AnimatePresence, motion, useReducedMotion, type MotionValue } from 'motion/react'\nimport { cn } from '@/lib/utils'\nimport { useMounted } from '@/hooks/use-mounted'\nimport { playHoverSound, playClickSound } from '@/lib/sound'\nimport { springs } from '@/lib/motion-tokens'\nimport { useProximityHighlight, ProximityHighlight } from '@/lib/hooks/use-proximity-highlight'\nconst MAX_HEIGHT = 320\nconst SIDE_OFFSET = 8\nconst VIEWPORT_MARGIN = 12\nconst TYPEAHEAD_RESET_MS = 500\ninterface SelectContextValue {\n  value: string\n  setValue: (v: string) => void\n  open: boolean\n  setOpen: (next: boolean) => void\n  disabled: boolean\n  triggerId: string\n  contentId: string\n  labelMap: React.MutableRefObject<Map<string, string>>\n  registerOption: (value: string, label: string) => void\n  openInteractionRef: React.MutableRefObject<'keyboard' | 'pointer'>\n  itemsWidth: number | null\n  setItemsWidth: (w: number | null) => void\n}\n\nconst SelectContext = createContext<SelectContextValue | null>(null)\n\nfunction useSelectCtx(componentName: string) {\n  const ctx = useContext(SelectContext)\n  if (!ctx) throw new Error(`${componentName} must be used within <Select>`)\n  return ctx\n}\ninterface SelectContentContextValue {\n  activeIndex: number | null\n  setActiveIndex: (i: number | null) => void\n  highlightX: ReturnType<typeof import('motion/react').useSpring>\n  highlightSize: MotionValue<number>\n  highlightOpacity: ReturnType<typeof import('motion/react').useSpring>\n  axis: 'x' | 'y'\n  focusedIndex: number\n  setFocusedIndex: (i: number) => void\n  setOpen: (next: boolean) => void\n  registerItem: (index: number, el: HTMLElement | null) => void\n}\n\nconst SelectContentContext = createContext<SelectContentContextValue | null>(null)\n\nfunction useSelectContentCtx(componentName: string) {\n  const ctx = useContext(SelectContentContext)\n  if (!ctx) throw new Error(`${componentName} must be used within <SelectContent>`)\n  return ctx\n}\nfunction normalizeTypeahead(value: string) {\n  return value\n    .normalize('NFKD')\n    .replace(/[\\u0300-\\u036f]/g, '')\n    .toLowerCase()\n    .replace(/\\s+/g, ' ')\n    .trim()\n}\n\nfunction clamp(value: number, min: number, max: number) {\n  return Math.min(Math.max(value, min), max)\n}\nexport interface SelectProps {\n  children: ReactNode\n  value?: string\n  defaultValue?: string\n  onValueChange?: (value: string) => void\n  disabled?: boolean\n  name?: string\n  required?: boolean\n  className?: string\n}\n\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(\n  (\n    {\n      children,\n      value: valueProp,\n      defaultValue = '',\n      onValueChange,\n      disabled = false,\n      name,\n      required = false,\n      className,\n    },\n    ref,\n  ) => {\n    const isControlled = valueProp !== undefined\n    const [internalValue, setInternalValue] = useState(defaultValue)\n    const value = isControlled ? valueProp : internalValue\n\n    const [open, setOpen] = useState(false)\n    const [itemsWidth, setItemsWidth] = useState<number | null>(null)\n    const openInteractionRef = useRef<'keyboard' | 'pointer'>('pointer')\n    const labelMap = useRef(new Map<string, string>())\n    const [options, setOptions] = useState<{ value: string; label: string }[]>([])\n    const registerOption = useCallback((v: string, label: string) => {\n      labelMap.current.set(v, label)\n      setOptions((prev) => {\n        const idx = prev.findIndex((o) => o.value === v)\n        if (idx >= 0) {\n          if (prev[idx].label === label) return prev\n          const next = [...prev]\n          next[idx] = { value: v, label }\n          return next\n        }\n        return [...prev, { value: v, label }]\n      })\n    }, [])\n\n    const reactId = useId()\n    const triggerId = `${reactId}-trigger`\n    const contentId = `${reactId}-content`\n\n    const setValue = useCallback(\n      (v: string) => {\n        if (!isControlled) setInternalValue(v)\n        onValueChange?.(v)\n        setOpen(false)\n        requestAnimationFrame(() => {\n          document.getElementById(triggerId)?.focus()\n        })\n      },\n      [isControlled, onValueChange, triggerId],\n    )\n    useEffect(() => {\n      if (!open) return\n      const handlePointerDown = (e: PointerEvent) => {\n        const target = e.target as Node\n        if ((target as HTMLElement).closest?.('[data-select-trigger]')) return\n        if ((target as HTMLElement).closest?.('[data-select-content]')) return\n        setOpen(false)\n      }\n      document.addEventListener('pointerdown', handlePointerDown)\n      return () => document.removeEventListener('pointerdown', handlePointerDown)\n    }, [open])\n    useEffect(() => {\n      if (!open) return\n      const handleKeyDown = (e: KeyboardEvent) => {\n        if (e.key === 'Escape') {\n          e.preventDefault()\n          setOpen(false)\n          document.getElementById(triggerId)?.focus()\n        }\n      }\n      document.addEventListener('keydown', handleKeyDown as EventListener)\n      return () => document.removeEventListener('keydown', handleKeyDown as EventListener)\n    }, [open, triggerId])\n\n    const ctx = useMemo<SelectContextValue>(\n      () => ({\n        value,\n        setValue,\n        open,\n        setOpen,\n        disabled,\n        triggerId,\n        contentId,\n        labelMap,\n        registerOption,\n        openInteractionRef,\n        itemsWidth,\n        setItemsWidth,\n      }),\n      [value, setValue, open, disabled, triggerId, contentId, registerOption, itemsWidth],\n    )\n\n    return (\n      <SelectContext.Provider value={ctx}>\n        <div className={cn('relative inline-block', className)}>\n          {children}\n\n          <select\n            ref={ref as React.Ref<HTMLSelectElement>}\n            tabIndex={-1}\n            aria-hidden=\"true\"\n            className=\"sr-only\"\n            name={name}\n            required={required}\n            value={value}\n            disabled={disabled}\n            onChange={(e) => setValue(e.target.value)}\n            onFocus={(e) => e.preventDefault()}\n          >\n            <option value=\"\"></option>\n            {options.map((opt) => (\n              <option key={opt.value} value={opt.value}>\n                {opt.label}\n              </option>\n            ))}\n          </select>\n        </div>\n      </SelectContext.Provider>\n    )\n  },\n)\nSelect.displayName = 'Select'\nexport interface SelectTriggerProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'children'> {\n  children?: ReactNode\n  showChevron?: boolean\n  disabled?: boolean\n}\n\nexport const SelectTrigger = forwardRef<HTMLButtonElement, SelectTriggerProps>(\n  (\n    {\n      children,\n      showChevron = true,\n      className,\n      disabled: disabledProp,\n      onClick,\n      onMouseEnter,\n      ...props\n    },\n    ref,\n  ) => {\n    const {\n      open,\n      setOpen,\n      disabled: rootDisabled,\n      triggerId,\n      contentId,\n      openInteractionRef,\n      itemsWidth,\n    } = useSelectCtx('SelectTrigger')\n    const reduceMotion = useReducedMotion()\n    const disabled = disabledProp ?? rootDisabled\n\n    return (\n      <button\n        ref={ref}\n        id={triggerId}\n        type=\"button\"\n        data-select-trigger\n        role=\"combobox\"\n        aria-expanded={open}\n        aria-haspopup=\"listbox\"\n        aria-controls={open ? contentId : undefined}\n        disabled={disabled}\n        style={itemsWidth ? { width: itemsWidth } : undefined}\n        className={cn(\n          'flex min-h-11 w-full items-center justify-between gap-2 border border-(--color-border) bg-(--color-surface) px-4 py-3 text-left text-sm font-medium text-(--color-fg) transition-colors duration-(--motion-dur-fast) motion-reduce:transition-none',\n          'rounded-lg supports-[corner-shape:squircle]:corner-squircle supports-[corner-shape:squircle]:rounded-[11px]',\n          'hover:bg-(--color-surface-2)',\n          'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--color-accent) focus-visible:ring-offset-2 focus-visible:ring-offset-(--color-bg)',\n          'disabled:cursor-not-allowed disabled:opacity-50',\n          className,\n        )}\n        onClick={(e) => {\n          onClick?.(e)\n          if (!disabled) {\n            playClickSound()\n            openInteractionRef.current = 'pointer'\n            setOpen(!open)\n          }\n        }}\n        onKeyDown={(e) => {\n          if (!open && ['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(e.key)) {\n            e.preventDefault()\n            if (!disabled) {\n              openInteractionRef.current = 'keyboard'\n              setOpen(true)\n            }\n          }\n        }}\n        onMouseEnter={(e) => {\n          onMouseEnter?.(e)\n          if (!disabled) playHoverSound()\n        }}\n        {...props}\n      >\n        <span className=\"flex min-w-0 flex-1 items-center gap-2\">{children}</span>\n        {showChevron && (\n          <motion.span\n            className=\"shrink-0 text-(--color-muted)\"\n            aria-hidden=\"true\"\n            animate={{ rotate: open ? 180 : 0 }}\n            transition={reduceMotion ? { duration: 0 } : springs.moderate}\n          >\n            <svg\n              width=\"16\"\n              height=\"16\"\n              viewBox=\"0 0 16 16\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"1.5\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"M4 6l4 4 4-4\" />\n            </svg>\n          </motion.span>\n        )}\n      </button>\n    )\n  },\n)\nSelectTrigger.displayName = 'SelectTrigger'\nexport interface SelectValueProps extends HTMLAttributes<HTMLSpanElement> {\n  placeholder?: string\n}\n\nexport const SelectValue = forwardRef<HTMLSpanElement, SelectValueProps>(\n  ({ placeholder = 'Select…', className, ...props }, ref) => {\n    const { value, labelMap } = useSelectCtx('SelectValue')\n    const reduceMotion = useReducedMotion()\n    const label = value ? (labelMap.current.get(value) ?? value) : undefined\n\n    if (reduceMotion) {\n      return (\n        <span\n          ref={ref}\n          className={cn('min-w-0 truncate', !label && 'text-(--color-muted)', className)}\n          {...props}\n        >\n          {label ?? placeholder}\n        </span>\n      )\n    }\n\n    return (\n      <span\n        ref={ref}\n        className={cn('min-w-0 truncate', !label && 'text-(--color-muted)', className)}\n        {...props}\n      >\n        <AnimatePresence initial={false} mode=\"wait\">\n          {label ? (\n            <motion.span\n              key={label}\n              initial={{ opacity: 0, y: 3 }}\n              animate={{ opacity: 1, y: 0 }}\n              exit={{ opacity: 0, y: -3 }}\n              transition={{\n                ...springs.fast,\n                opacity: { duration: 0.1 },\n              }}\n              className=\"inline-block min-w-0 truncate\"\n            >\n              {label}\n            </motion.span>\n          ) : (\n            <motion.span\n              key=\"placeholder\"\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{ opacity: 0 }}\n              transition={{ duration: 0.06 }}\n              className=\"inline-block min-w-0 truncate\"\n            >\n              {placeholder}\n            </motion.span>\n          )}\n        </AnimatePresence>\n      </span>\n    )\n  },\n)\nSelectValue.displayName = 'SelectValue'\nexport interface SelectContentProps extends HTMLAttributes<HTMLDivElement> {\n  align?: 'start' | 'center' | 'end'\n  side?: 'bottom' | 'top'\n}\n\nexport const SelectContent = forwardRef<HTMLDivElement, SelectContentProps>(\n  ({ align = 'start', side = 'bottom', children, className, ...props }, ref) => {\n    const {\n      open,\n      setOpen,\n      triggerId,\n      contentId,\n      value,\n      openInteractionRef,\n      itemsWidth,\n      setItemsWidth,\n    } = useSelectCtx('SelectContent')\n    const panelRef = useRef<HTMLDivElement | null>(null)\n    const [position, setPosition] = useState({ left: 0, top: 0 })\n    const maxWidthRef = useRef(0)\n    const mounted = useMounted()\n    const {\n      activeIndex,\n      setActiveIndex,\n      registerItem,\n      handlers,\n      highlightX,\n      highlightSize,\n      highlightOpacity,\n      axis,\n    } = useProximityHighlight(panelRef, { axis: 'y' })\n\n    const [focusedIndex, setFocusedIndex] = useState(0)\n    const reduceMotion = useReducedMotion()\n    const initialFocusIndex = useMemo(() => {\n      const values: string[] = []\n      collectSelectItemValues(children, values)\n      const idx = values.indexOf(value)\n      return idx >= 0 ? idx : 0\n    }, [children, value])\n\n    const [prevOpen, setPrevOpen] = useState(open)\n    if (open !== prevOpen) {\n      setPrevOpen(open)\n      if (open) setFocusedIndex(initialFocusIndex)\n    }\n\n    const [focusRect, setFocusRect] = useState<{\n      top: number\n      left: number\n      width: number\n      height: number\n    } | null>(null)\n    const [showFocusRing, setShowFocusRing] = useState(false)\n\n    useEffect(() => {\n      if (open) setShowFocusRing(openInteractionRef.current === 'keyboard')\n    }, [open, openInteractionRef])\n\n    useEffect(() => {\n      const items = open\n        ? panelRef.current?.querySelectorAll<HTMLElement>('[role=\"option\"]')\n        : undefined\n      const el = focusedIndex >= 0 ? items?.[focusedIndex] : undefined\n      if (!el) {\n        setFocusRect(null)\n        return\n      }\n      setFocusRect({\n        top: el.offsetTop,\n        left: el.offsetLeft,\n        width: el.offsetWidth,\n        height: el.offsetHeight,\n      })\n    }, [open, focusedIndex])\n\n    const [selectedRect, setSelectedRect] = useState<{ top: number; height: number } | null>(null)\n\n    useLayoutEffect(() => {\n      const items = open\n        ? panelRef.current?.querySelectorAll<HTMLElement>('[role=\"option\"]')\n        : undefined\n      const el =\n        items && Array.from(items).find((item) => item.getAttribute('data-value') === value)\n      setSelectedRect(el ? { top: el.offsetTop, height: el.offsetHeight } : null)\n    }, [open, value])\n\n    const indexedChildren = useMemo(() => {\n      const counter = { current: 0 }\n      return assignSelectItemIndices(children, counter)\n    }, [children])\n\n    const measureRef = useRef<HTMLDivElement | null>(null)\n    useLayoutEffect(() => {\n      const el = measureRef.current\n      if (!el || typeof ResizeObserver === 'undefined') return\n      const update = () => {\n        const w = el.getBoundingClientRect().width\n        maxWidthRef.current = Math.max(maxWidthRef.current, w)\n        setItemsWidth(maxWidthRef.current)\n      }\n      update()\n      const ro = new ResizeObserver(update)\n      ro.observe(el)\n      return () => ro.disconnect()\n    }, [indexedChildren, setItemsWidth])\n\n    useEffect(() => {\n      if (!open) return\n      const measure = () => {\n        const trigger = document.getElementById(triggerId)\n        const content = panelRef.current\n        if (!trigger || !content) return\n        const triggerRect = trigger.getBoundingClientRect()\n        const contentRect = content.getBoundingClientRect()\n        const vw = window.innerWidth\n        const vh = window.innerHeight\n\n        let left = align === 'end' ? triggerRect.right - contentRect.width : triggerRect.left\n        if (align === 'center')\n          left = triggerRect.left + (triggerRect.width - contentRect.width) / 2\n        left = clamp(left, VIEWPORT_MARGIN, vw - contentRect.width - VIEWPORT_MARGIN)\n\n        let top: number\n        const spaceBelow = vh - triggerRect.bottom - SIDE_OFFSET\n        if (side === 'top' || (side === 'bottom' && spaceBelow < contentRect.height)) {\n          top = triggerRect.top - contentRect.height - SIDE_OFFSET\n        } else {\n          top = triggerRect.bottom + SIDE_OFFSET\n        }\n        setPosition({ left, top })\n        const natural = Math.max(triggerRect.width, contentRect.width)\n        maxWidthRef.current = Math.max(maxWidthRef.current, natural)\n        setItemsWidth(maxWidthRef.current)\n      }\n\n      const frame = requestAnimationFrame(measure)\n      window.addEventListener('resize', measure)\n      window.addEventListener('scroll', measure, true)\n      return () => {\n        cancelAnimationFrame(frame)\n        window.removeEventListener('resize', measure)\n        window.removeEventListener('scroll', measure, true)\n      }\n    }, [open, align, side, triggerId, setItemsWidth])\n    useEffect(() => {\n      if (!open) return\n      let typeaheadQuery = ''\n      let typeaheadTimeout: ReturnType<typeof setTimeout> | null = null\n\n      const handleKeyDown = (e: globalThis.KeyboardEvent) => {\n        if (!panelRef.current?.contains(document.activeElement)) return\n        const items = panelRef.current.querySelectorAll<HTMLElement>(\n          '[role=\"option\"]:not([data-disabled])',\n        )\n        if (!items.length) return\n        const count = items.length\n\n        if (e.key === 'ArrowDown') {\n          e.preventDefault()\n          setShowFocusRing(true)\n          const next = (focusedIndex + 1) % count\n          setFocusedIndex(next)\n          items[next]?.focus()\n        } else if (e.key === 'ArrowUp') {\n          e.preventDefault()\n          setShowFocusRing(true)\n          const next = (focusedIndex - 1 + count) % count\n          setFocusedIndex(next)\n          items[next]?.focus()\n        } else if (e.key === 'Home') {\n          e.preventDefault()\n          setShowFocusRing(true)\n          setFocusedIndex(0)\n          items[0]?.focus()\n        } else if (e.key === 'End') {\n          e.preventDefault()\n          setShowFocusRing(true)\n          setFocusedIndex(count - 1)\n          items[count - 1]?.focus()\n        } else if (e.key === 'Tab') {\n          setOpen(false)\n        } else if (e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey && e.key.trim()) {\n          e.preventDefault()\n          typeaheadQuery += e.key.toLowerCase()\n          if (typeaheadTimeout) clearTimeout(typeaheadTimeout)\n          typeaheadTimeout = setTimeout(() => {\n            typeaheadQuery = ''\n          }, TYPEAHEAD_RESET_MS)\n\n          const normalizedQuery = normalizeTypeahead(typeaheadQuery)\n          const match = Array.from(items).findIndex((el) => {\n            const text = normalizeTypeahead(\n              el.getAttribute('data-text-value') ?? el.textContent ?? '',\n            )\n            return text.startsWith(normalizedQuery)\n          })\n          if (match >= 0) {\n            setShowFocusRing(true)\n            setFocusedIndex(match)\n            items[match]?.focus()\n          }\n        }\n      }\n      document.addEventListener('keydown', handleKeyDown)\n      return () => {\n        document.removeEventListener('keydown', handleKeyDown)\n        if (typeaheadTimeout) clearTimeout(typeaheadTimeout)\n      }\n    }, [open, focusedIndex, setOpen])\n    useEffect(() => {\n      if (!open) return\n      const frame = requestAnimationFrame(() => {\n        const items = panelRef.current?.querySelectorAll<HTMLElement>(\n          '[role=\"option\"]:not([data-disabled])',\n        )\n        if (!items?.length) return\n        const selectedIdx = Array.from(items).findIndex(\n          (el) => el.getAttribute('data-value') === value,\n        )\n        const focusIdx = selectedIdx >= 0 ? selectedIdx : 0\n        setFocusedIndex(focusIdx)\n        items[focusIdx]?.focus()\n      })\n      return () => cancelAnimationFrame(frame)\n    }, [open, value])\n\n    const setRefs = useCallback(\n      (el: HTMLDivElement | null) => {\n        ;(panelRef as React.MutableRefObject<HTMLDivElement | null>).current = el\n        if (typeof ref === 'function') ref(el)\n        else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = el\n      },\n      [ref],\n    )\n\n    const contentCtx = useMemo<SelectContentContextValue>(\n      () => ({\n        activeIndex,\n        setActiveIndex,\n        highlightX,\n        highlightSize,\n        highlightOpacity,\n        axis,\n        focusedIndex,\n        setFocusedIndex,\n        setOpen,\n        registerItem,\n      }),\n      [\n        activeIndex,\n        setActiveIndex,\n        highlightX,\n        highlightSize,\n        highlightOpacity,\n        axis,\n        focusedIndex,\n        setOpen,\n        registerItem,\n      ],\n    )\n\n    if (!mounted) return null\n\n    return createPortal(\n      <SelectContentContext.Provider value={contentCtx}>\n        {!open && (\n          <div\n            ref={measureRef}\n            aria-hidden=\"true\"\n            className={cn(\n              'pointer-events-none invisible fixed top-0 left-0 min-w-48 border border-(--color-border) bg-(--color-bg) p-1.5 **:min-w-max',\n              'rounded-lg supports-[corner-shape:squircle]:corner-squircle supports-[corner-shape:squircle]:rounded-[11px]',\n              className,\n            )}\n          >\n            {indexedChildren}\n          </div>\n        )}\n\n        <AnimatePresence>\n          {open && (\n            <motion.div\n              key=\"select-dropdown\"\n              initial={reduceMotion ? { opacity: 1 } : { opacity: 0, y: -4, scaleY: 0.96 }}\n              animate={reduceMotion ? { opacity: 1 } : { opacity: 1, y: 0, scaleY: 1 }}\n              exit={reduceMotion ? { opacity: 0 } : { opacity: 0, y: -4, scaleY: 0.96 }}\n              transition={\n                reduceMotion ? { duration: 0 } : { ...springs.fast, opacity: { duration: 0.12 } }\n              }\n              style={{\n                position: 'fixed',\n                left: position.left,\n                top: position.top,\n                width: itemsWidth ?? undefined,\n                zIndex: 30,\n                transformOrigin: 'top center',\n                maxWidth: 'calc(100vw - 1.5rem)',\n                maxHeight: MAX_HEIGHT,\n                overflowY: 'auto',\n              }}\n            >\n              <div\n                ref={setRefs}\n                id={contentId}\n                role=\"listbox\"\n                aria-labelledby={triggerId}\n                data-select-content\n                className={cn(\n                  'relative w-full min-w-48 overflow-hidden border border-(--color-border) bg-(--color-bg) p-1.5 outline-none',\n                  'rounded-lg supports-[corner-shape:squircle]:corner-squircle supports-[corner-shape:squircle]:rounded-[11px]',\n                  'shadow-xl',\n                  className,\n                )}\n                tabIndex={-1}\n                {...handlers}\n                onMouseMove={(e) => {\n                  setShowFocusRing(false)\n                  handlers.onMouseMove(e)\n                }}\n                {...props}\n              >\n                <AnimatePresence>\n                  {selectedRect && (\n                    <motion.div\n                      aria-hidden=\"true\"\n                      className=\"pointer-events-none absolute inset-x-1.5 top-0 rounded-md supports-[corner-shape:squircle]:corner-squircle bg-(--color-accent)/15\"\n                      initial={reduceMotion ? { opacity: 1 } : { opacity: 0 }}\n                      animate={{ opacity: 1, y: selectedRect.top, height: selectedRect.height }}\n                      exit={\n                        reduceMotion\n                          ? { opacity: 0 }\n                          : { opacity: 0, transition: { duration: 0.08 } }\n                      }\n                      transition={\n                        reduceMotion\n                          ? { duration: 0 }\n                          : { ...springs.settle, opacity: { duration: 0.1 } }\n                      }\n                    />\n                  )}\n                </AnimatePresence>\n\n                <ProximityHighlight\n                  highlightX={highlightX}\n                  highlightSize={highlightSize}\n                  highlightOpacity={highlightOpacity}\n                  axis={axis}\n                  className=\"mx-1.5 rounded-md supports-[corner-shape:squircle]:corner-squircle bg-(--color-surface-2)\"\n                />\n\n                <AnimatePresence>\n                  {focusRect && showFocusRing && (\n                    <motion.div\n                      aria-hidden=\"true\"\n                      className=\"pointer-events-none z-20 rounded-md supports-[corner-shape:squircle]:corner-squircle border-2 border-(--color-accent)\"\n                      initial={reduceMotion ? { opacity: 1 } : { opacity: 0 }}\n                      animate={{\n                        opacity: 1,\n                        top: focusRect.top - 2,\n                        left: focusRect.left - 2,\n                        width: focusRect.width + 4,\n                        height: focusRect.height + 4,\n                      }}\n                      exit={\n                        reduceMotion\n                          ? { opacity: 0 }\n                          : { opacity: 0, transition: { duration: 0.06 } }\n                      }\n                      transition={\n                        reduceMotion\n                          ? { duration: 0 }\n                          : { ...springs.fast, opacity: { duration: 0.08 } }\n                      }\n                    />\n                  )}\n                </AnimatePresence>\n                {indexedChildren}\n              </div>\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </SelectContentContext.Provider>,\n      document.body,\n    )\n  },\n)\nSelectContent.displayName = 'SelectContent'\nexport interface SelectItemProps extends HTMLAttributes<HTMLDivElement> {\n  children: ReactNode\n  value: string\n  disabled?: boolean\n  textValue?: string\n  index?: number\n}\n\nexport const SelectItem = forwardRef<HTMLDivElement, SelectItemProps>(\n  (\n    {\n      children,\n      value: itemValue,\n      disabled,\n      textValue,\n      index = 0,\n      onClick: onClickProp,\n      className,\n      ...props\n    },\n    ref,\n  ) => {\n    const { value: selectedValue, setValue, registerOption } = useSelectCtx('SelectItem')\n    const { setActiveIndex, focusedIndex, setFocusedIndex, registerItem } =\n      useSelectContentCtx('SelectItem')\n    const reduceMotion = useReducedMotion()\n\n    const itemRef = useRef<HTMLDivElement | null>(null)\n    const isSelected = selectedValue === itemValue\n    useEffect(() => {\n      const label = typeof children === 'string' ? children : itemValue\n      registerOption(itemValue, label)\n    }, [itemValue, children, registerOption])\n    useEffect(() => {\n      const el = itemRef.current\n      if (index < 0 || !el) return\n      registerItem(index, el)\n      return () => registerItem(index, null)\n    }, [index, registerItem])\n\n    const setItemRef = useCallback(\n      (node: HTMLDivElement | null) => {\n        itemRef.current = node\n        if (typeof ref === 'function') ref(node)\n        else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n      },\n      [ref],\n    )\n\n    const resolvedTextValue = textValue ?? (typeof children === 'string' ? children : '')\n\n    return (\n      <div\n        ref={setItemRef}\n        role=\"option\"\n        aria-selected={isSelected}\n        data-value={itemValue}\n        data-proximity-index={index}\n        data-disabled={disabled ? '' : undefined}\n        aria-disabled={disabled || undefined}\n        data-text-value={resolvedTextValue}\n        tabIndex={focusedIndex === index ? 0 : -1}\n        className={cn(\n          'relative flex min-h-11 w-full cursor-default select-none scroll-m-1 items-center justify-between gap-3 px-3 py-2.5 text-left text-sm outline-none transition-colors duration-(--motion-dur-fast) motion-reduce:transition-none',\n          'rounded-md supports-[corner-shape:squircle]:corner-squircle supports-[corner-shape:squircle]:rounded-[9px]',\n          'data-disabled:pointer-events-none data-disabled:opacity-50',\n          isSelected ? 'text-(--color-fg)' : 'text-(--color-muted)',\n          className,\n        )}\n        onPointerDown={(e) => {\n          e.preventDefault()\n        }}\n        onFocus={() => {\n          setFocusedIndex(index)\n          setActiveIndex(index)\n        }}\n        onClick={(e) => {\n          onClickProp?.(e)\n          if (!disabled) {\n            playClickSound()\n            setValue(itemValue)\n          }\n        }}\n        onKeyDown={(e) => {\n          if (e.key === 'Enter' || e.key === ' ') {\n            e.preventDefault()\n            if (!disabled) {\n              playClickSound()\n              setValue(itemValue)\n            }\n          }\n        }}\n        {...props}\n      >\n        <span className=\"relative z-10 flex min-w-0 flex-1 items-center gap-2 truncate\">\n          {children}\n        </span>\n\n        <AnimatePresence>\n          {isSelected && (\n            <motion.svg\n              key=\"check\"\n              width={16}\n              height={16}\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth={2}\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n              className=\"relative z-10 shrink-0 text-(--color-fg)\"\n              initial={{ opacity: 1 }}\n              animate={{ opacity: 1 }}\n              exit={{ opacity: 1 }}\n            >\n              <motion.path\n                d=\"M4 12L9 17L20 6\"\n                initial={{ pathLength: 0 }}\n                animate={{ pathLength: 1 }}\n                transition={reduceMotion ? { duration: 0 } : springs.press}\n              />\n            </motion.svg>\n          )}\n        </AnimatePresence>\n      </div>\n    )\n  },\n)\nSelectItem.displayName = 'SelectItem'\nexport interface SelectGroupProps extends HTMLAttributes<HTMLDivElement> {\n  label?: ReactNode\n  labelClassName?: string\n}\n\nexport const SelectGroup = forwardRef<HTMLDivElement, SelectGroupProps>(\n  ({ label, labelClassName, children, className, ...props }, ref) => (\n    <div ref={ref} role=\"group\" className={cn(label && 'mt-2 first:mt-0', className)} {...props}>\n      {label && (\n        <div\n          className={cn(\n            'px-3 pt-1 pb-1 text-[11px] font-medium uppercase tracking-[0.12em] text-(--color-subtle)',\n            labelClassName,\n          )}\n        >\n          {label}\n        </div>\n      )}\n      {children}\n    </div>\n  ),\n)\nSelectGroup.displayName = 'SelectGroup'\nfunction assignSelectItemIndices(nodes: ReactNode, counter: { current: number }): ReactNode {\n  return Children.map(nodes, (child) => {\n    if (!isValidElement(child)) return child\n    if (child.type === SelectItem) {\n      return cloneElement(child as ReactElement<SelectItemProps>, {\n        index: counter.current++,\n      })\n    }\n    if (child.type === SelectGroup) {\n      const groupProps = child.props as SelectGroupProps\n      return cloneElement(child as ReactElement<SelectGroupProps>, {\n        children: assignSelectItemIndices(groupProps.children, counter),\n      })\n    }\n    return child\n  })\n}\nfunction collectSelectItemValues(nodes: ReactNode, values: string[]): void {\n  Children.forEach(nodes, (child) => {\n    if (!isValidElement(child)) return\n    if (child.type === SelectItem) {\n      values.push((child.props as SelectItemProps).value)\n      return\n    }\n    if (child.type === SelectGroup) {\n      collectSelectItemValues((child.props as SelectGroupProps).children, values)\n    }\n  })\n}\nexport type SelectLabelProps = HTMLAttributes<HTMLDivElement>\n\nexport const SelectLabel = forwardRef<HTMLDivElement, SelectLabelProps>(\n  ({ className, ...props }, ref) => (\n    <div\n      ref={ref}\n      className={cn(\n        'px-3 pt-1 pb-1 text-[11px] font-medium uppercase tracking-[0.12em] text-(--color-subtle)',\n        className,\n      )}\n      {...props}\n    />\n  ),\n)\nSelectLabel.displayName = 'SelectLabel'\nexport type SelectSeparatorProps = HTMLAttributes<HTMLDivElement>\n\nexport const SelectSeparator = forwardRef<HTMLDivElement, SelectSeparatorProps>(\n  ({ className, ...props }, ref) => (\n    <div\n      ref={ref}\n      role=\"separator\"\n      aria-hidden=\"true\"\n      className={cn('my-1 h-px bg-(--color-border)', className)}\n      {...props}\n    />\n  ),\n)\nSelectSeparator.displayName = 'SelectSeparator'\nexport function SelectPreview() {\n  const [value, setValue] = useState('')\n  return (\n    <div\n      className=\"flex h-full w-full items-center justify-center p-6\"\n      style={{ backgroundColor: 'var(--color-surface)' }}\n    >\n      <div className=\"w-56\">\n        <Select value={value} onValueChange={setValue} name=\"size\">\n          <SelectTrigger>\n            <SelectValue placeholder=\"Choose size\" />\n          </SelectTrigger>\n          <SelectContent>\n            <SelectItem value=\"small\">Small</SelectItem>\n            <SelectItem value=\"medium\">Medium</SelectItem>\n            <SelectItem value=\"large\">Large</SelectItem>\n          </SelectContent>\n        </Select>\n      </div>\n    </div>\n  )\n}\n"
    },
    {
      "path": "lib/hooks/use-proximity-highlight.tsx",
      "type": "registry:lib",
      "content": "'use client'\n\nimport { useRef, useState, useCallback, useEffect, type RefObject } from 'react'\nimport {\n  motion,\n  useMotionValue,\n  useReducedMotion,\n  useSpring,\n  type MotionValue,\n  type MotionStyle,\n} from 'motion/react'\nimport { springs } from '@/lib/motion-tokens'\n\nexport interface ItemRect {\n  top: number\n  height: number\n  left: number\n  width: number\n}\n\ninterface UseProximityHighlightOptions {\n  axis?: 'x' | 'y'\n  spring?: { stiffness: number; damping: number; mass: number }\n}\n\ninterface UseProximityHighlightReturn {\n  activeIndex: number | null\n  setActiveIndex: (index: number | null) => void\n  itemRects: ItemRect[]\n  sessionRef: RefObject<number>\n  handlers: {\n    onMouseMove: (e: React.MouseEvent) => void\n    onMouseEnter: () => void\n    onMouseLeave: () => void\n  }\n  registerItem: (index: number, element: HTMLElement | null) => void\n  measureItems: () => void\n  highlightX: ReturnType<typeof useSpring>\n  highlightSize: MotionValue<number>\n  highlightOpacity: ReturnType<typeof useSpring>\n  axis: 'x' | 'y'\n}\n\nexport function useProximityHighlight<T extends HTMLElement>(\n  containerRef: RefObject<T | null>,\n  options: UseProximityHighlightOptions = {},\n): UseProximityHighlightReturn {\n  const { axis = 'y', spring: springConfig } = options\n  const reduceMotion = useReducedMotion()\n\n  const itemsRef = useRef(new Map<number, HTMLElement>())\n  const [activeIndex, setActiveIndexRaw] = useState<number | null>(null)\n  const activeIndexRef = useRef<number | null>(null)\n  const [itemRects, setItemRects] = useState<ItemRect[]>([])\n  const itemRectsRef = useRef<ItemRect[]>([])\n  const sessionRef = useRef(0)\n  const rafIdRef = useRef<number | null>(null)\n  const remeasureRafIdRef = useRef<number | null>(null)\n  const updateHighlightRef = useRef<(index: number | null) => void>(() => {})\n\n  const rawX = useMotionValue(0)\n  const highlightSize = useMotionValue(0)\n  const rawOpacity = useMotionValue(0)\n\n  const springOpts = reduceMotion ? { duration: 0 } : (springConfig ?? springs.settle)\n\n  const highlightX = useSpring(rawX, springOpts)\n  const highlightOpacity = useSpring(rawOpacity, springOpts)\n\n  const measureItems = useCallback(() => {\n    const container = containerRef.current\n    if (!container) return\n    const rects: ItemRect[] = []\n    itemsRef.current.forEach((element, index) => {\n      rects[index] = {\n        top: element.offsetTop,\n        height: element.offsetHeight,\n        left: element.offsetLeft,\n        width: element.offsetWidth,\n      }\n    })\n    itemRectsRef.current = rects\n    setItemRects(rects)\n  }, [containerRef])\n\n  const registerItem = useCallback(\n    (index: number, element: HTMLElement | null) => {\n      if (element) {\n        itemsRef.current.set(index, element)\n      } else {\n        itemsRef.current.delete(index)\n      }\n      if (remeasureRafIdRef.current !== null) {\n        cancelAnimationFrame(remeasureRafIdRef.current)\n      }\n      remeasureRafIdRef.current = requestAnimationFrame(() => {\n        remeasureRafIdRef.current = null\n        measureItems()\n      })\n    },\n    [measureItems],\n  )\n\n  const updateHighlight = useCallback(\n    (index: number | null) => {\n      if (index === null || !itemRectsRef.current[index]) {\n        if (reduceMotion) {\n          rawOpacity.jump(0)\n        } else {\n          rawOpacity.set(0)\n        }\n        return\n      }\n      const r = itemRectsRef.current[index]\n      if (axis === 'y') {\n        if (reduceMotion) {\n          rawX.jump(r.top)\n          highlightSize.jump(r.height)\n          rawOpacity.jump(1)\n        } else {\n          rawX.set(r.top)\n          highlightSize.jump(r.height)\n          rawOpacity.set(1)\n        }\n      } else {\n        if (reduceMotion) {\n          rawX.jump(r.left)\n          highlightSize.jump(r.width)\n          rawOpacity.jump(1)\n        } else {\n          rawX.set(r.left)\n          highlightSize.jump(r.width)\n          rawOpacity.set(1)\n        }\n      }\n    },\n    [axis, reduceMotion, rawX, highlightSize, rawOpacity],\n  )\n\n  useEffect(() => {\n    updateHighlightRef.current = updateHighlight\n  })\n\n  const setActiveIndex = useCallback((index: number | null) => {\n    setActiveIndexRaw(index)\n    updateHighlightRef.current(index)\n  }, [])\n\n  const handleMouseMove = useCallback(\n    (e: React.MouseEvent) => {\n      const mouseX = e.clientX\n      const mouseY = e.clientY\n\n      if (rafIdRef.current !== null) {\n        cancelAnimationFrame(rafIdRef.current)\n      }\n\n      rafIdRef.current = requestAnimationFrame(() => {\n        rafIdRef.current = null\n        const container = containerRef.current\n        if (!container) return\n\n        const containerRect = container.getBoundingClientRect()\n        const mousePos = axis === 'x' ? mouseX : mouseY\n\n        let closestIndex: number | null = null\n        let closestDistance = Infinity\n        let containingIndex: number | null = null\n\n        const rects = itemRectsRef.current\n        const scrollOffset = axis === 'x' ? container.scrollLeft : container.scrollTop\n        const borderOffset = axis === 'x' ? container.clientLeft : container.clientTop\n        const containerEdge = axis === 'x' ? containerRect.left : containerRect.top\n\n        const layoutSize = axis === 'x' ? container.offsetWidth : container.offsetHeight\n        const visualSize = axis === 'x' ? containerRect.width : containerRect.height\n        const scale = layoutSize > 0 ? visualSize / layoutSize : 1\n\n        for (let index = 0; index < rects.length; index++) {\n          const r = rects[index]\n          if (!r) continue\n\n          const contentPos = axis === 'x' ? r.left : r.top\n          const itemStart = containerEdge + (borderOffset + contentPos - scrollOffset) * scale\n          const itemSize = (axis === 'x' ? r.width : r.height) * scale\n          const itemEnd = itemStart + itemSize\n\n          if (mousePos >= itemStart && mousePos <= itemEnd) {\n            containingIndex = index\n          }\n\n          const itemCenter = itemStart + itemSize / 2\n          const distance = Math.abs(mousePos - itemCenter)\n\n          if (distance < closestDistance) {\n            closestDistance = distance\n            closestIndex = index\n          }\n        }\n\n        const next = containingIndex ?? closestIndex\n        if (next !== activeIndexRef.current) {\n          activeIndexRef.current = next\n          setActiveIndex(next)\n        }\n      })\n    },\n    [axis, containerRef, setActiveIndex],\n  )\n\n  const handleMouseEnter = useCallback(() => {\n    sessionRef.current += 1\n  }, [])\n\n  const handleMouseLeave = useCallback(() => {\n    if (rafIdRef.current !== null) {\n      cancelAnimationFrame(rafIdRef.current)\n      rafIdRef.current = null\n    }\n    activeIndexRef.current = null\n    setActiveIndex(null)\n  }, [setActiveIndex])\n\n  useEffect(() => {\n    return () => {\n      if (rafIdRef.current !== null) {\n        cancelAnimationFrame(rafIdRef.current)\n      }\n      if (remeasureRafIdRef.current !== null) {\n        cancelAnimationFrame(remeasureRafIdRef.current)\n      }\n    }\n  }, [])\n\n  return {\n    activeIndex,\n    setActiveIndex,\n    itemRects,\n    sessionRef,\n    handlers: {\n      onMouseMove: handleMouseMove,\n      onMouseEnter: handleMouseEnter,\n      onMouseLeave: handleMouseLeave,\n    },\n    registerItem,\n    measureItems,\n    highlightX,\n    highlightSize,\n    highlightOpacity,\n    axis,\n  }\n}\n\nexport interface ProximityHighlightProps {\n  highlightX: ReturnType<typeof useSpring>\n  highlightSize: MotionValue<number>\n  highlightOpacity: ReturnType<typeof useSpring>\n  axis: 'x' | 'y'\n  className?: string\n  style?: MotionStyle\n}\n\nexport function ProximityHighlight({\n  highlightX,\n  highlightSize,\n  highlightOpacity,\n  axis,\n  className,\n  style,\n}: ProximityHighlightProps) {\n  return (\n    <motion.div\n      aria-hidden=\"true\"\n      className={className}\n      style={{\n        ...style,\n        position: 'absolute',\n        inset: 0,\n        pointerEvents: 'none',\n        ...(axis === 'y'\n          ? { y: highlightX, height: highlightSize }\n          : { x: highlightX, width: highlightSize }),\n        opacity: highlightOpacity,\n      }}\n    />\n  )\n}\n\nexport function useRegisterProximityItem(\n  registerItem: (index: number, element: HTMLElement | null) => void,\n  index: number,\n  ref: RefObject<HTMLElement | null>,\n) {\n  useEffect(() => {\n    registerItem(index, ref.current)\n    return () => registerItem(index, null)\n  }, [index, registerItem, ref])\n}\n"
    },
    {
      "path": "lib/sound.ts",
      "type": "registry:lib",
      "content": "'use client'\n\nconst MUTE_KEY = 'sound-muted'\nconst MUTE_EVENT = 'sound-mute-change'\n\nlet muted = false\nif (typeof window !== 'undefined') {\n  try {\n    muted = localStorage.getItem(MUTE_KEY) === '1'\n  } catch {}\n}\n\nexport function isSoundMuted(): boolean {\n  return muted\n}\n\nexport function setSoundMuted(value: boolean) {\n  muted = value\n  if (typeof window !== 'undefined') {\n    try {\n      localStorage.setItem(MUTE_KEY, value ? '1' : '0')\n    } catch {}\n    window.dispatchEvent(new CustomEvent(MUTE_EVENT))\n  }\n}\n\nexport function toggleSoundMuted(): boolean {\n  setSoundMuted(!muted)\n  return muted\n}\n\nexport function subscribeSoundMuted(callback: () => void) {\n  if (typeof window === 'undefined') return () => {}\n  window.addEventListener(MUTE_EVENT, callback)\n  const onStorage = (e: StorageEvent) => {\n    if (e.key === MUTE_KEY) callback()\n  }\n  window.addEventListener('storage', onStorage)\n  return () => {\n    window.removeEventListener(MUTE_EVENT, callback)\n    window.removeEventListener('storage', onStorage)\n  }\n}\n\nlet audioCtx: AudioContext | null = null\n\nfunction initAudio(): AudioContext | null {\n  if (typeof window === 'undefined') return null\n  if (!audioCtx) {\n    const AudioContextClass =\n      window.AudioContext ||\n      (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext\n    if (AudioContextClass) {\n      audioCtx = new AudioContextClass()\n    }\n  }\n  if (audioCtx && audioCtx.state === 'suspended') {\n    audioCtx.resume().catch(() => {})\n  }\n  return audioCtx\n}\n\nif (typeof window !== 'undefined') {\n  const unlock = () => {\n    initAudio()\n    window.removeEventListener('pointerdown', unlock)\n    window.removeEventListener('keydown', unlock)\n    window.removeEventListener('touchstart', unlock)\n  }\n  window.addEventListener('pointerdown', unlock, { passive: true })\n  window.addEventListener('keydown', unlock, { passive: true })\n  window.addEventListener('touchstart', unlock, { passive: true })\n}\n\nexport function getAudioContext(): AudioContext | null {\n  return initAudio()\n}\n\nexport function playHoverSound(volume = 0.12, pitch = 1.2) {\n  if (muted) return\n  try {\n    const ctx = getAudioContext()\n    if (!ctx) return\n    const now = ctx.currentTime\n\n    const osc = ctx.createOscillator()\n    const gain = ctx.createGain()\n\n    osc.type = 'sine'\n    osc.frequency.setValueAtTime(1400 * pitch, now)\n    osc.frequency.exponentialRampToValueAtTime(350 * pitch, now + 0.012)\n\n    gain.gain.setValueAtTime(volume, now)\n    gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.012)\n\n    osc.connect(gain)\n    gain.connect(ctx.destination)\n\n    osc.start(now)\n    osc.stop(now + 0.012)\n  } catch {}\n}\n\nexport function playClickSound(volume = 0.2, pitch = 1.0) {\n  if (muted) return\n  try {\n    const ctx = getAudioContext()\n    if (!ctx) return\n    const now = ctx.currentTime\n\n    const osc = ctx.createOscillator()\n    const gain = ctx.createGain()\n\n    osc.type = 'triangle'\n    osc.frequency.setValueAtTime(850 * pitch, now)\n    osc.frequency.exponentialRampToValueAtTime(160 * pitch, now + 0.02)\n\n    gain.gain.setValueAtTime(volume, now)\n    gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.02)\n\n    osc.connect(gain)\n    gain.connect(ctx.destination)\n\n    osc.start(now)\n    osc.stop(now + 0.02)\n  } catch {}\n}\n\nexport function playTickSound(volume = 0.1, pitch = 1.5) {\n  if (muted) return\n  try {\n    const ctx = getAudioContext()\n    if (!ctx) return\n    const now = ctx.currentTime\n\n    const osc = ctx.createOscillator()\n    const gain = ctx.createGain()\n\n    osc.type = 'sine'\n    osc.frequency.setValueAtTime(1800 * pitch, now)\n    osc.frequency.exponentialRampToValueAtTime(450 * pitch, now + 0.01)\n\n    gain.gain.setValueAtTime(volume, now)\n    gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.01)\n\n    osc.connect(gain)\n    gain.connect(ctx.destination)\n\n    osc.start(now)\n    osc.stop(now + 0.01)\n  } catch {}\n}\n\nexport function playBounceSound(volume = 0.3, pitch = 1.0) {\n  if (muted) return\n  try {\n    const ctx = getAudioContext()\n    if (!ctx) return\n    const now = ctx.currentTime\n\n    const osc = ctx.createOscillator()\n    const gain = ctx.createGain()\n\n    osc.type = 'sine'\n    osc.frequency.setValueAtTime(260 * pitch, now)\n    osc.frequency.exponentialRampToValueAtTime(650 * pitch, now + 0.04)\n    osc.frequency.exponentialRampToValueAtTime(190 * pitch, now + 0.14)\n\n    gain.gain.setValueAtTime(volume, now)\n    gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.14)\n\n    osc.connect(gain)\n    gain.connect(ctx.destination)\n\n    osc.start(now)\n    osc.stop(now + 0.14)\n\n    const subOsc = ctx.createOscillator()\n    const subGain = ctx.createGain()\n\n    subOsc.type = 'triangle'\n    subOsc.frequency.setValueAtTime(420 * pitch, now)\n    subOsc.frequency.exponentialRampToValueAtTime(120 * pitch, now + 0.05)\n\n    subGain.gain.setValueAtTime(volume * 0.7, now)\n    subGain.gain.exponentialRampToValueAtTime(0.0001, now + 0.05)\n\n    subOsc.connect(subGain)\n    subGain.connect(ctx.destination)\n\n    subOsc.start(now)\n    subOsc.stop(now + 0.05)\n  } catch {}\n}\n"
    }
  ],
  "type": "registry:ui"
}
