{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "gummy-button",
  "type": "registry:ui",
  "title": "Gummy Button",
  "description": "Accessible fruit-gel Button with chewy press physics and high-transmission finish.",
  "files": [
    {
      "path": "components/ui/gummy-button.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nexport type GummyButtonVariant =\n  | \"primary\"\n  | \"secondary\"\n  | \"success\"\n  | \"warning\"\n  | \"info\";\n\nexport type GummyButtonSize = \"small\" | \"medium\" | \"large\";\nexport type GummyButtonFinish = \"gel\" | \"translucent\";\n\nexport type GummyButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n  /** Fruit-colour treatment. The label remains on an optically stable layer. */\n  variant?: GummyButtonVariant;\n  /** Preserves a 44px minimum touch target at every visual size. */\n  size?: GummyButtonSize;\n  /** Controls optical transmission without changing semantic colour. */\n  finish?: GummyButtonFinish;\n  /** Disables activation, exposes busy state, and shows a non-motion-dependent cue. */\n  loading?: boolean;\n  /** Visible label while loading. */\n  loadingText?: React.ReactNode;\n};\n\nfunction joinClassNames(...values: Array<string | false | null | undefined>) {\n  return values.filter(Boolean).join(\" \");\n}\n\nexport const GummyButton = React.forwardRef<\n  HTMLButtonElement,\n  GummyButtonProps\n>(function GummyButton(\n  {\n    variant = \"primary\",\n    size = \"medium\",\n    finish = \"gel\",\n    loading = false,\n    loadingText = \"Loading\",\n    disabled = false,\n    type = \"button\",\n    className,\n    children,\n    ...buttonProps\n  },\n  ref,\n) {\n  const isDisabled = disabled || loading;\n\n  return (\n    <button\n      {...buttonProps}\n      ref={ref}\n      type={type}\n      className={joinClassNames(\"gummy-button\", className)}\n      data-variant={variant}\n      data-size={size}\n      data-finish={finish}\n      data-loading={loading || undefined}\n      aria-busy={loading || undefined}\n      disabled={isDisabled}\n    >\n      <span className=\"gummy-button__body\">\n        <span className=\"gummy-button__content\">\n          {loading ? (\n            <span className=\"gummy-button__spinner\" aria-hidden=\"true\" />\n          ) : null}\n          <span>{loading ? loadingText : children}</span>\n        </span>\n      </span>\n    </button>\n  );\n});\n\nGummyButton.displayName = \"GummyButton\";\n"
    },
    {
      "path": "app/gummy-button.css",
      "type": "registry:style",
      "content": "/* Canonical Gummy Button -------------------------------------------------- */\n\n.gummy-button {\n  --gummy-light: oklch(0.92 0.1 7);\n  --gummy-core: oklch(0.76 0.21 8);\n  --gummy-rim: oklch(0.63 0.27 8);\n  --gummy-depth: oklch(0.48 0.22 9);\n  --gummy-shadow: oklch(0.62 0.25 8 / 0.3);\n  --gummy-label: oklch(0.2 0.065 309);\n  --gummy-thickness: 5px;\n  --gummy-shadow-y: 13px;\n  position: relative;\n  display: inline-grid;\n  min-width: max-content;\n  min-height: 48px;\n  place-items: center;\n  padding: 0;\n  border: 0;\n  border-radius: 17px 20px 18px 21px / 18px 19px 17px 19px;\n  background: transparent;\n  color: var(--gummy-label);\n  cursor: pointer;\n  font-weight: 720;\n  letter-spacing: -0.018em;\n  line-height: 1;\n  text-align: center;\n  text-rendering: geometricPrecision;\n  touch-action: manipulation;\n  user-select: none;\n  -webkit-user-select: none;\n}\n\n.gummy-button__body {\n  position: relative;\n  isolation: isolate;\n  display: inline-grid;\n  width: 100%;\n  min-height: inherit;\n  place-items: center;\n  border: 1px solid color-mix(in oklch, var(--gummy-rim) 78%, white);\n  border-bottom-color: var(--gummy-depth);\n  border-radius: inherit;\n  background:\n    radial-gradient(ellipse 78% 66% at 50% 38%, color-mix(in oklch, var(--gummy-light) 88%, transparent) 0%, color-mix(in oklch, var(--gummy-core) 72%, transparent) 58%, transparent 78%),\n    linear-gradient(155deg, color-mix(in oklch, var(--gummy-light) 90%, transparent), color-mix(in oklch, var(--gummy-core) 90%, transparent) 52%, var(--gummy-rim));\n  box-shadow:\n    inset 0 1px 1px color-mix(in oklch, white 68%, var(--gummy-light)),\n    inset 4px 6px 10px oklch(1 0 0 / 0.22),\n    inset -4px -7px 11px color-mix(in oklch, var(--gummy-depth) 34%, transparent),\n    0 var(--gummy-thickness) 0 var(--gummy-depth),\n    0 var(--gummy-shadow-y) 22px var(--gummy-shadow);\n  transform: translateY(0) scaleX(1) scaleY(1);\n  transform-origin: center bottom;\n  transition:\n    transform 290ms cubic-bezier(0.18, 1.62, 0.32, 1),\n    border-color 180ms ease,\n    background 180ms ease,\n    box-shadow 240ms ease,\n    filter 180ms ease,\n    opacity 180ms ease;\n  will-change: transform;\n}\n\n.gummy-button__body::before {\n  position: absolute;\n  z-index: -1;\n  inset: 2px;\n  padding: 2px;\n  border-radius: inherit;\n  background: conic-gradient(\n    from 218deg,\n    transparent 0 10%,\n    oklch(1 0 0 / 0.12) 16%,\n    oklch(1 0 0 / 0.88) 25%,\n    oklch(1 0 0 / 0.26) 34%,\n    transparent 45% 100%\n  );\n  content: \"\";\n  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);\n  mask-composite: exclude;\n  pointer-events: none;\n}\n\n.gummy-button__body::after {\n  position: absolute;\n  z-index: -1;\n  top: 8%;\n  left: 12%;\n  width: 22%;\n  height: 18%;\n  border-radius: 50%;\n  background: radial-gradient(ellipse, oklch(1 0 0 / 0.78), oklch(1 0 0 / 0.08) 52%, transparent 72%);\n  content: \"\";\n  filter: blur(0.35px);\n  pointer-events: none;\n  transform: rotate(-5deg);\n}\n\n.gummy-button__content {\n  position: relative;\n  z-index: 1;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  gap: 9px;\n  white-space: nowrap;\n}\n\n.gummy-button[data-size=\"small\"] {\n  min-height: 44px;\n  border-radius: 15px 17px 16px 18px / 16px 17px 15px 17px;\n  font-size: 13px;\n}\n\n.gummy-button[data-size=\"small\"] .gummy-button__body {\n  padding: 10px 17px 11px;\n}\n\n.gummy-button[data-size=\"medium\"] {\n  font-size: 15px;\n}\n\n.gummy-button[data-size=\"medium\"] .gummy-button__body {\n  padding: 13px 23px 14px;\n}\n\n.gummy-button[data-size=\"large\"] {\n  min-height: 56px;\n  border-radius: 19px 23px 20px 24px / 21px 22px 19px 22px;\n  font-size: 17px;\n}\n\n.gummy-button[data-size=\"large\"] .gummy-button__body {\n  padding: 16px 29px 17px;\n}\n\n.gummy-button[data-variant=\"secondary\"] {\n  --gummy-light: oklch(0.9 0.1 303);\n  --gummy-core: oklch(0.76 0.18 302);\n  --gummy-rim: oklch(0.62 0.22 302);\n  --gummy-depth: oklch(0.46 0.18 302);\n  --gummy-shadow: oklch(0.58 0.2 302 / 0.29);\n}\n\n.gummy-button[data-variant=\"success\"] {\n  --gummy-light: oklch(0.97 0.11 126);\n  --gummy-core: oklch(0.89 0.22 126);\n  --gummy-rim: oklch(0.76 0.22 126);\n  --gummy-depth: oklch(0.59 0.17 126);\n  --gummy-shadow: oklch(0.7 0.18 126 / 0.3);\n}\n\n.gummy-button[data-variant=\"warning\"] {\n  --gummy-light: oklch(0.96 0.11 70);\n  --gummy-core: oklch(0.85 0.2 58);\n  --gummy-rim: oklch(0.72 0.2 49);\n  --gummy-depth: oklch(0.56 0.18 45);\n  --gummy-shadow: oklch(0.7 0.2 52 / 0.3);\n}\n\n.gummy-button[data-variant=\"info\"] {\n  --gummy-light: oklch(0.96 0.09 205);\n  --gummy-core: oklch(0.84 0.15 207);\n  --gummy-rim: oklch(0.7 0.17 218);\n  --gummy-depth: oklch(0.52 0.14 226);\n  --gummy-shadow: oklch(0.66 0.16 215 / 0.3);\n}\n\n.gummy-button[data-finish=\"translucent\"] {\n  --gummy-thickness: 2px;\n  --gummy-shadow-y: 10px;\n  min-height: 58px;\n  border-radius: 24px 13px 27px 14px / 19px 14px 25px 16px;\n}\n\n.gummy-button[data-finish=\"translucent\"] .gummy-button__body {\n  overflow: hidden;\n  padding: 16px 31px 17px 28px;\n  border-width: 1.5px;\n  border-color: color-mix(in oklch, var(--gummy-rim) 27%, white);\n  border-bottom-color: color-mix(in oklch, var(--gummy-rim) 32%, white);\n  background:\n    radial-gradient(ellipse 46% 32% at 27% 14%, oklch(1 0 0 / 0.62) 0%, transparent 72%),\n    radial-gradient(ellipse 60% 76% at 91% 96%, color-mix(in oklch, var(--gummy-core) 28%, transparent), color-mix(in oklch, var(--gummy-depth) 15%, transparent) 46%, transparent 78%),\n    linear-gradient(145deg, color-mix(in oklch, var(--gummy-light) 20%, transparent), color-mix(in oklch, var(--gummy-core) 13%, transparent) 50%, color-mix(in oklch, var(--gummy-rim) 28%, transparent));\n  backdrop-filter: blur(10px) saturate(1.28);\n  box-shadow:\n    inset 0 0 0 1.5px oklch(1 0 0 / 0.34),\n    inset 2px 3px 5px oklch(1 0 0 / 0.44),\n    inset 7px 8px 14px oklch(1 0 0 / 0.1),\n    inset -7px -8px 14px color-mix(in oklch, var(--gummy-depth) 9%, transparent),\n    0 7px 18px color-mix(in oklch, var(--gummy-shadow) 16%, transparent);\n}\n\n.gummy-button[data-finish=\"translucent\"] .gummy-button__body::before {\n  z-index: 0;\n  inset: 6px 11px 7px 6px;\n  padding: 0;\n  border: 1px solid oklch(1 0 0 / 0.4);\n  border-radius: 16px 8px 18px 9px / 12px 10px 18px 11px;\n  background:\n    radial-gradient(ellipse 56% 44% at 26% 18%, oklch(1 0 0 / 0.44), transparent 72%),\n    linear-gradient(148deg, oklch(0.99 0.012 208 / 0.52), color-mix(in oklch, var(--gummy-light) 30%, transparent) 58%, color-mix(in oklch, var(--gummy-core) 19%, transparent));\n  box-shadow:\n    inset 2px 2px 4px oklch(1 0 0 / 0.36),\n    inset -4px -4px 8px color-mix(in oklch, var(--gummy-core) 13%, transparent);\n  mask: none;\n  transform-origin: 48% 54%;\n  transition: transform 240ms cubic-bezier(0.2, 0.9, 0.25, 1), border-color 180ms ease;\n}\n\n.gummy-button[data-finish=\"translucent\"] .gummy-button__body::after {\n  z-index: 0;\n  top: auto;\n  right: -5px;\n  bottom: -9px;\n  left: auto;\n  width: 54px;\n  height: 51px;\n  border-radius: 48% 52% 68% 32% / 40% 66% 34% 60%;\n  border: 0;\n  background:\n    radial-gradient(ellipse at 28% 22%, oklch(1 0 0 / 0.58), transparent 52%),\n    radial-gradient(ellipse at 62% 66%, color-mix(in oklch, var(--gummy-core) 36%, transparent), color-mix(in oklch, var(--gummy-rim) 25%, transparent) 62%, transparent 80%);\n  box-shadow:\n    inset 2px 2px 4px oklch(1 0 0 / 0.3),\n    inset -5px -6px 10px color-mix(in oklch, var(--gummy-depth) 8%, transparent);\n  opacity: 0.72;\n  transform: rotate(7deg);\n  transform-origin: 58% 66%;\n  transition: transform 260ms cubic-bezier(0.2, 1.2, 0.28, 1), opacity 180ms ease;\n}\n\n:root[data-theme=\"dark\"] .gummy-button[data-finish=\"translucent\"] .gummy-button__body {\n  border-color: color-mix(in oklch, var(--gummy-rim) 54%, oklch(1 0 0 / 0.24));\n  border-bottom-color: color-mix(in oklch, var(--gummy-depth) 44%, oklch(1 0 0 / 0.2));\n  background:\n    radial-gradient(ellipse 42% 30% at 27% 14%, oklch(1 0 0 / 0.4) 0%, transparent 72%),\n    radial-gradient(ellipse 64% 78% at 91% 96%, color-mix(in oklch, var(--gummy-core) 34%, transparent), color-mix(in oklch, var(--gummy-depth) 22%, transparent) 48%, transparent 79%),\n    linear-gradient(145deg, color-mix(in oklch, var(--gummy-light) 14%, transparent), color-mix(in oklch, var(--gummy-core) 19%, transparent) 50%, color-mix(in oklch, var(--gummy-rim) 36%, transparent));\n  box-shadow:\n    inset 0 0 0 1px oklch(1 0 0 / 0.18),\n    inset 2px 3px 5px oklch(1 0 0 / 0.28),\n    inset 7px 8px 14px oklch(1 0 0 / 0.07),\n    inset -7px -8px 14px color-mix(in oklch, var(--gummy-depth) 16%, transparent),\n    0 7px 18px color-mix(in oklch, var(--gummy-shadow) 24%, transparent);\n}\n\n:root[data-theme=\"dark\"] .gummy-button[data-finish=\"translucent\"] .gummy-button__body::before {\n  border-color: oklch(1 0 0 / 0.26);\n  background:\n    radial-gradient(ellipse 56% 44% at 26% 18%, oklch(1 0 0 / 0.32), transparent 72%),\n    linear-gradient(148deg, oklch(0.94 0.035 208 / 0.46), color-mix(in oklch, var(--gummy-light) 31%, transparent) 58%, color-mix(in oklch, var(--gummy-core) 23%, transparent));\n  box-shadow:\n    inset 2px 2px 4px oklch(1 0 0 / 0.25),\n    inset -4px -4px 8px color-mix(in oklch, var(--gummy-core) 21%, transparent);\n}\n\n:root[data-theme=\"dark\"] .gummy-button[data-finish=\"translucent\"] .gummy-button__body::after {\n  opacity: 0.8;\n}\n\n.gummy-button[data-finish=\"translucent\"] .gummy-button__content {\n  z-index: 2;\n  transform-origin: center;\n  transition: transform 180ms cubic-bezier(0.2, 0.9, 0.25, 1);\n}\n\n@media (hover: hover) and (pointer: fine) {\n  .gummy-button:not(:disabled):hover .gummy-button__body,\n  .gummy-button--preview-hover .gummy-button__body {\n    --gummy-shadow-y: 16px;\n    filter: saturate(1.06) brightness(1.025);\n    transform: translateY(-2px) scaleX(1.012) scaleY(1.012);\n  }\n\n  .gummy-button[data-finish=\"translucent\"]:not(:disabled):hover .gummy-button__body::after {\n    opacity: 0.8;\n    transform: translate(-2px, -1px) rotate(3deg) scale(1.08);\n  }\n}\n\n.gummy-button:not(:disabled):active .gummy-button__body {\n  --gummy-thickness: 1px;\n  --gummy-shadow-y: 5px;\n  box-shadow:\n    inset 0 1px 1px color-mix(in oklch, white 52%, var(--gummy-light)),\n    inset 5px 4px 9px oklch(1 0 0 / 0.17),\n    inset -4px -3px 10px color-mix(in oklch, var(--gummy-depth) 42%, transparent),\n    0 var(--gummy-thickness) 0 var(--gummy-depth),\n    0 var(--gummy-shadow-y) 12px var(--gummy-shadow);\n  filter: saturate(1.07);\n  transform: translateY(5px) scaleX(1.07) scaleY(0.84);\n  transition-duration: 70ms;\n  transition-timing-function: cubic-bezier(0.2, 0, 0.5, 1);\n}\n\n.gummy-button:focus-visible,\n.gummy-button--preview-focus {\n  outline: 3px solid var(--focus);\n  outline-offset: 4px;\n}\n\n.gummy-button:focus-visible .gummy-button__body,\n.gummy-button--preview-focus .gummy-button__body {\n  box-shadow:\n    inset 0 1px 1px color-mix(in oklch, white 68%, var(--gummy-light)),\n    inset 4px 6px 10px oklch(1 0 0 / 0.22),\n    inset -4px -7px 11px color-mix(in oklch, var(--gummy-depth) 34%, transparent),\n    0 var(--gummy-thickness) 0 var(--gummy-depth),\n    0 var(--gummy-shadow-y) 22px var(--gummy-shadow),\n    0 0 0 7px var(--focus-halo);\n}\n\n.gummy-button[data-finish=\"translucent\"]:focus-visible {\n  outline: none;\n}\n\n.gummy-button[data-finish=\"translucent\"]:focus-visible .gummy-button__body {\n  border-color: color-mix(in oklch, var(--gummy-rim) 62%, white);\n  box-shadow:\n    inset 0 0 0 1.5px oklch(1 0 0 / 0.42),\n    inset 2px 3px 5px oklch(1 0 0 / 0.58),\n    inset 7px 8px 14px oklch(1 0 0 / 0.14),\n    inset -7px -8px 14px color-mix(in oklch, var(--gummy-depth) 16%, transparent),\n    0 2px 0 color-mix(in oklch, var(--gummy-depth) 22%, transparent),\n    0 12px 28px color-mix(in oklch, var(--gummy-shadow) 48%, transparent);\n  filter: saturate(1.08) brightness(1.025);\n  transform: translateY(-2px) scaleX(1.012) scaleY(1.018);\n}\n\n.gummy-button[data-finish=\"translucent\"]:focus-visible .gummy-button__body::after {\n  opacity: 0.82;\n  transform: translate(-3px, -1px) rotate(2deg) scale(1.1);\n}\n\n:root[data-theme=\"dark\"] .gummy-button[data-finish=\"translucent\"]:focus-visible .gummy-button__body {\n  border-color: color-mix(in oklch, var(--gummy-rim) 66%, oklch(1 0 0 / 0.28));\n  box-shadow:\n    inset 0 0 0 1px oklch(1 0 0 / 0.22),\n    inset 2px 3px 5px oklch(1 0 0 / 0.34),\n    inset 7px 8px 14px oklch(1 0 0 / 0.08),\n    inset -7px -8px 14px color-mix(in oklch, var(--gummy-depth) 22%, transparent),\n    0 2px 0 color-mix(in oklch, var(--gummy-depth) 22%, transparent),\n    0 10px 24px color-mix(in oklch, var(--gummy-shadow) 38%, transparent);\n}\n\n.gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__body {\n  box-shadow:\n    inset 0 0 0 1.5px oklch(1 0 0 / 0.34),\n    inset 4px 4px 8px oklch(1 0 0 / 0.18),\n    inset -5px -4px 10px color-mix(in oklch, var(--gummy-depth) 18%, transparent),\n    0 1px 0 color-mix(in oklch, var(--gummy-depth) 20%, transparent),\n    0 5px 12px color-mix(in oklch, var(--gummy-shadow) 34%, transparent);\n}\n\n.gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__body::before {\n  transform: translateY(1px) scaleX(1.025) scaleY(0.96);\n  transition-duration: 70ms;\n}\n\n.gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__body::after {\n  opacity: 0.88;\n  transform: translate(-5px, 4px) rotate(12deg) scaleX(1.18) scaleY(0.78);\n  transition-duration: 70ms;\n}\n\n.gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__content {\n  transform: translateY(-1px) scaleX(0.94) scaleY(1.12);\n  transition-duration: 70ms;\n}\n\n:root[data-theme=\"dark\"] .gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__body {\n  box-shadow:\n    inset 0 0 0 1px oklch(1 0 0 / 0.18),\n    inset 4px 4px 8px oklch(1 0 0 / 0.13),\n    inset -5px -4px 10px color-mix(in oklch, var(--gummy-depth) 25%, transparent),\n    0 1px 0 color-mix(in oklch, var(--gummy-depth) 24%, transparent),\n    0 5px 12px color-mix(in oklch, var(--gummy-shadow) 28%, transparent);\n}\n\n.gummy-button:disabled:not([data-loading=\"true\"]) {\n  cursor: not-allowed;\n}\n\n.gummy-button:disabled:not([data-loading=\"true\"]) .gummy-button__body {\n  filter: saturate(0.45);\n  opacity: 0.54;\n  transform: none;\n}\n\n.gummy-button[data-loading=\"true\"] {\n  cursor: wait;\n}\n\n.gummy-button__spinner {\n  width: 16px;\n  height: 16px;\n  border: 2px solid color-mix(in oklch, currentColor 28%, transparent);\n  border-top-color: currentColor;\n  border-radius: 50%;\n  animation: gummy-spin 720ms linear infinite;\n}\n\n@keyframes gummy-spin {\n  to { transform: rotate(360deg); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .gummy-button:not(:disabled):active .gummy-button__body,\n  .gummy-button:not(:disabled):hover .gummy-button__body,\n  .gummy-button--preview-hover .gummy-button__body,\n  .gummy-button[data-finish=\"translucent\"]:not(:disabled):hover .gummy-button__body::after,\n  .gummy-button[data-finish=\"translucent\"]:focus-visible .gummy-button__body::after,\n  .gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__body::before,\n  .gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__body::after,\n  .gummy-button[data-finish=\"translucent\"]:not(:disabled):active .gummy-button__content {\n    transform: none;\n  }\n\n  .gummy-button__spinner {\n    animation: none;\n    border-style: dotted;\n  }\n}\n"
    }
  ]
}
