{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "subscription-status-card",
  "type": "registry:component",
  "title": "Subscription status card",
  "description": "Subscription overview card showing plan details, status, billing cycle, line item breakdown, discount, scheduled changes, and optional action buttons. Supports single and multi-item subscriptions, past-due alerts, collection mode indicators, and configurable badge position.",
  "dependencies": ["lucide-react"],
  "registryDependencies": [
    "@paddle/paddle-helpers",
    "card",
    "badge",
    "button",
    "separator",
    "alert",
    "skeleton"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/subscription-status-card/components/subscription-status-card.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n  CheckCircle2,\n  Clock,\n  AlertCircle,\n  PauseCircle,\n  MinusCircle,\n  Sparkles,\n  CalendarIcon,\n  CreditCardIcon,\n  FileTextIcon,\n} from \"lucide-react\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\"\nimport { Badge } from \"@/registry/new-york/ui/badge\"\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Separator } from \"@/registry/new-york/ui/separator\"\nimport { Alert, AlertDescription, AlertTitle } from \"@/registry/new-york/ui/alert\"\nimport { Skeleton } from \"@/registry/new-york/ui/skeleton\"\nimport { cn } from \"@/lib/utils\"\nimport type { SubscriptionStatusData } from \"@/registry/new-york/blocks/paddle-helpers/lib/paddle-types\"\nimport {\n  formatMoney,\n  formatDate,\n  formatBillingCycle,\n} from \"@/registry/new-york/blocks/paddle-helpers/lib/paddle-format\"\n\nexport type SubscriptionStatusCardProps = {\n  subscription?: SubscriptionStatusData\n  /** Override the card title. Defaults to the first item's product name (single-item) or \"Subscription\" (multi-item). */\n  title?: string\n  /** Position of the status badge: \"inline\" next to name, or \"end\" aligned to card end */\n  statusBadgePosition?: \"inline\" | \"end\"\n  /**\n   * Called when the user clicks \"Change plan\".\n   * Only rendered when status is not `paused` or `canceled` — paused\n   * subscriptions must be resumed before items can be changed, and canceled\n   * is a terminal state.\n   */\n  onChangePlan?: () => void\n  /**\n   * Called when the user clicks \"Update payment method\".\n   * Only rendered for automatically-collected subscriptions that are not\n   * `paused` or `canceled` — manual subscriptions are invoice-based (no saved\n   * payment method), paused subscriptions have no active billing, and canceled\n   * is terminal.\n   */\n  onUpdatePaymentMethod?: () => void\n  /**\n   * Called when the user clicks \"Manage\". Always rendered when provided —\n   * the action is consumer-defined (portal link, modal, resubscribe flow, etc.)\n   * and not restricted by Paddle subscription status.\n   */\n  onManageSubscription?: () => void\n  className?: string\n}\n\n// --- Status badge ---\n\ntype SubscriptionStatus = \"active\" | \"canceled\" | \"past_due\" | \"paused\" | \"trialing\"\n\nconst STATUS_CONFIG: Record<\n  SubscriptionStatus,\n  { label: string; icon: React.ElementType; className: string }\n> = {\n  active: {\n    label: \"Active\",\n    icon: CheckCircle2,\n    className: \"bg-success/15 text-success-foreground border-success/30\",\n  },\n  trialing: {\n    label: \"Trial\",\n    icon: Sparkles,\n    className: \"bg-info/15 text-info-foreground border-info/30\",\n  },\n  past_due: {\n    label: \"Past due\",\n    icon: AlertCircle,\n    className: \"bg-destructive/15 text-destructive border-destructive/30\",\n  },\n  paused: {\n    label: \"Paused\",\n    icon: PauseCircle,\n    className: \"bg-warning/15 text-warning-foreground border-warning/30\",\n  },\n  canceled: {\n    label: \"Canceled\",\n    icon: MinusCircle,\n    className: \"bg-muted text-muted-foreground border-border\",\n  },\n}\n\nfunction StatusBadge({ status }: { status: SubscriptionStatus }) {\n  const config = STATUS_CONFIG[status] ?? {\n    label: status.replace(/_/g, \" \").replace(/\\b\\w/g, (c) => c.toUpperCase()),\n    icon: AlertCircle,\n    className: \"bg-muted text-muted-foreground border-border\",\n  }\n  const Icon = config.icon\n  return (\n    <Badge variant=\"outline\" className={cn(\"gap-1 font-medium\", config.className)}>\n      <Icon className=\"size-3\" />\n      {config.label}\n    </Badge>\n  )\n}\n\n// --- Scheduled change validity ---\n\n/**\n * Returns the scheduledChange only when it is valid for the given status.\n * Impossible combinations (e.g. resume on active, cancel on paused, any\n * scheduled change on canceled) are suppressed so the component never\n * renders misleading alerts.\n */\nfunction getValidScheduledChange(\n  status: SubscriptionStatus,\n  scheduledChange?: SubscriptionStatusData[\"scheduledChange\"]\n): SubscriptionStatusData[\"scheduledChange\"] | undefined {\n  if (!scheduledChange) return undefined\n  switch (status) {\n    case \"canceled\":\n      return undefined\n    case \"paused\":\n      return scheduledChange.action === \"resume\" ? scheduledChange : undefined\n    default:\n      return scheduledChange.action === \"resume\" ? undefined : scheduledChange\n  }\n}\n\n// --- Footer billing label ---\n\nfunction getNextBillingLabel(\n  status: SubscriptionStatus,\n  scheduledChange?: SubscriptionStatusData[\"scheduledChange\"]\n): string | undefined {\n  if (scheduledChange?.action === \"cancel\" || scheduledChange?.action === \"pause\") {\n    return undefined\n  }\n  switch (status) {\n    case \"trialing\":\n      return \"First billing\"\n    case \"past_due\":\n      return \"Payment due\"\n    case \"active\":\n      return \"Next billing\"\n    default:\n      return undefined\n  }\n}\n\n// --- Button visibility rules ---\n\n/**\n * \"Change plan\" is available for active, trialing, and past_due subscriptions.\n * Paused subscriptions must be resumed before items can be changed.\n * Canceled is a terminal state.\n */\nfunction canShowChangePlan(status: SubscriptionStatus): boolean {\n  return status !== \"paused\" && status !== \"canceled\"\n}\n\n/**\n * \"Update payment method\" requires automatic collection and an active billing\n * relationship. Manual subscriptions are invoice-based — no saved payment\n * method exists. Paused subscriptions have no active billing. Canceled is\n * terminal.\n */\nfunction canShowUpdatePaymentMethod(\n  status: SubscriptionStatus,\n  collectionMode?: \"automatic\" | \"manual\"\n): boolean {\n  return status !== \"canceled\" && status !== \"paused\" && collectionMode !== \"manual\"\n}\n\n// --- Main component ---\n\nexport function SubscriptionStatusCard({\n  subscription,\n  title: titleOverride,\n  statusBadgePosition = \"end\",\n  onChangePlan,\n  onUpdatePaymentMethod,\n  onManageSubscription,\n  className,\n}: SubscriptionStatusCardProps) {\n  if (!subscription) {\n    return <SubscriptionStatusCardSkeleton className={className} />\n  }\n\n  const {\n    items,\n    totalAmount,\n    currency,\n    interval,\n    billingFrequency,\n    status,\n    nextBilledAt,\n    canceledAt,\n    collectionMode,\n    scheduledChange,\n    discount,\n  } = subscription\n\n  const isSingleItem = items.length === 1\n  const primaryItem = items[0]\n  const isPastDue = status === \"past_due\"\n\n  const effectiveScheduledChange = getValidScheduledChange(status, scheduledChange)\n\n  const showChangePlan = !!onChangePlan && canShowChangePlan(status)\n  const showUpdatePayment =\n    !!onUpdatePaymentMethod && canShowUpdatePaymentMethod(status, collectionMode)\n  const showManage = !!onManageSubscription\n  const hasActions = showChangePlan || showUpdatePayment || showManage\n\n  const cardTitle =\n    titleOverride ?? (isSingleItem ? primaryItem?.productName : undefined) ?? \"Subscription\"\n\n  const billingIntervalLabel =\n    formatBillingCycle({ interval, frequency: billingFrequency ?? 1 }) ?? interval\n\n  const scheduledChangeNote = effectiveScheduledChange\n    ? effectiveScheduledChange.action === \"cancel\"\n      ? `Cancels on ${formatDate(effectiveScheduledChange.effectiveAt)}`\n      : effectiveScheduledChange.action === \"pause\"\n        ? `Pauses on ${formatDate(effectiveScheduledChange.effectiveAt)}`\n        : effectiveScheduledChange.action === \"resume\"\n          ? `Resumes on ${formatDate(effectiveScheduledChange.effectiveAt)}`\n          : undefined\n    : undefined\n\n  const nextBillingLabel = getNextBillingLabel(status, effectiveScheduledChange)\n\n  return (\n    <Card\n      className={cn(\"gap-4\", className)}\n      data-status={status}\n      data-past-due={isPastDue || undefined}\n    >\n      <CardHeader>\n        <div className=\"flex items-start justify-between gap-4\">\n          <div className=\"flex-1 min-w-0 space-y-1\">\n            <div className=\"flex flex-wrap items-center gap-2\">\n              <CardTitle className=\"truncate\">{cardTitle}</CardTitle>\n              {statusBadgePosition === \"inline\" && <StatusBadge status={status} />}\n            </div>\n            {isSingleItem && primaryItem?.priceName && (\n              <CardDescription>{primaryItem.priceName}</CardDescription>\n            )}\n          </div>\n          <div className=\"flex items-center gap-2 shrink-0\">\n            {statusBadgePosition === \"end\" && <StatusBadge status={status} />}\n            {isSingleItem && primaryItem?.productImageUrl && (\n              <img\n                src={primaryItem.productImageUrl}\n                alt={primaryItem.productName}\n                className=\"size-12 rounded-md object-cover\"\n              />\n            )}\n          </div>\n        </div>\n      </CardHeader>\n\n      <CardContent className=\"space-y-3\">\n        {isPastDue && (\n          <Alert variant=\"destructive\">\n            <AlertCircle className=\"size-4\" />\n            <AlertTitle>\n              {collectionMode === \"manual\" ? \"Invoice overdue\" : \"Payment required\"}\n            </AlertTitle>\n            <AlertDescription>\n              {collectionMode === \"manual\"\n                ? \"Pay your outstanding invoice to avoid disruption.\"\n                : \"Your subscription is past due. Update your payment method to avoid disruption.\"}\n            </AlertDescription>\n          </Alert>\n        )}\n\n        {scheduledChangeNote && (\n          <Alert>\n            <Clock className=\"size-4\" />\n            <AlertTitle>Scheduled change</AlertTitle>\n            <AlertDescription>{scheduledChangeNote}</AlertDescription>\n          </Alert>\n        )}\n\n        <div className=\"space-y-2\">\n          {items.map((item, index) => (\n            <div\n              key={index}\n              className={cn(\n                \"flex items-center justify-between gap-4\",\n                index > 0 && \"pt-2 border-t\"\n              )}\n            >\n              <div className=\"flex items-center gap-2 min-w-0\">\n                {item.productImageUrl && items.length > 1 && (\n                  <img\n                    src={item.productImageUrl}\n                    alt={item.productName}\n                    className=\"size-6 rounded object-cover shrink-0\"\n                  />\n                )}\n                <div className=\"min-w-0 space-y-0.5\">\n                  <p className=\"text-sm font-medium truncate\">{item.productName}</p>\n                  {item.quantity > 1 && item.unitPrice !== undefined && (\n                    <p className=\"text-sm text-muted-foreground\">\n                      {item.quantity} &times; {formatMoney(item.unitPrice, currency)}\n                    </p>\n                  )}\n                </div>\n              </div>\n              <p className=\"text-sm font-medium shrink-0 tabular-nums\">\n                {formatMoney(item.lineTotal, currency)}\n              </p>\n            </div>\n          ))}\n        </div>\n\n        <Separator />\n\n        <div className=\"space-y-1.5\">\n          {discount && (\n            <div className=\"flex items-center justify-between text-success-foreground\">\n              <span className=\"text-sm flex items-center gap-1.5\">\n                Discount\n                {discount.code && (\n                  <span className=\"text-xs bg-success/10 px-1.5 py-0.5 rounded\">\n                    {discount.code}\n                  </span>\n                )}\n                {discount.endsAt && (\n                  <span className=\"text-xs text-muted-foreground\">\n                    until {formatDate(discount.endsAt)}\n                  </span>\n                )}\n              </span>\n              <span className=\"text-sm tabular-nums\">\n                {discount.description ?? `\\u2212${formatMoney(discount.savingsAmount, currency)}`}\n              </span>\n            </div>\n          )}\n\n          <div className=\"flex items-center justify-between font-medium\">\n            <span className=\"text-sm\">Total</span>\n            <span className=\"text-sm tabular-nums\">\n              {formatMoney(totalAmount, currency)}\n              <span className=\"text-muted-foreground font-normal\"> / {billingIntervalLabel}</span>\n            </span>\n          </div>\n        </div>\n\n        <Separator />\n\n        <div className=\"flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted-foreground\">\n          {nextBilledAt && nextBillingLabel && (\n            <div className=\"flex items-center gap-1.5\">\n              <CalendarIcon className=\"size-3.5\" />\n              <span>\n                {nextBillingLabel} {formatDate(nextBilledAt)}\n              </span>\n            </div>\n          )}\n          {collectionMode && !effectiveScheduledChange && status !== \"past_due\" && (\n            <div className=\"flex items-center gap-1.5\">\n              {collectionMode === \"automatic\" ? (\n                <>\n                  <CreditCardIcon className=\"size-3.5\" />\n                  <span>Auto-renews</span>\n                </>\n              ) : (\n                <>\n                  <FileTextIcon className=\"size-3.5\" />\n                  <span>Invoiced</span>\n                </>\n              )}\n            </div>\n          )}\n          {canceledAt && (\n            <div className=\"flex items-center gap-1.5\">\n              <span>Canceled {formatDate(canceledAt)}</span>\n            </div>\n          )}\n        </div>\n\n        {hasActions && (\n          <div className=\"flex flex-wrap gap-2 pt-1\">\n            {showChangePlan && (\n              <Button onClick={onChangePlan} size=\"sm\">\n                Change plan\n              </Button>\n            )}\n            {showUpdatePayment && (\n              <Button\n                variant={isPastDue ? \"default\" : \"outline\"}\n                size=\"sm\"\n                onClick={onUpdatePaymentMethod}\n              >\n                Update payment method\n              </Button>\n            )}\n            {showManage && (\n              <Button variant=\"outline\" size=\"sm\" onClick={onManageSubscription}>\n                Manage\n              </Button>\n            )}\n          </div>\n        )}\n      </CardContent>\n    </Card>\n  )\n}\n\nfunction SubscriptionStatusCardSkeleton({ className }: { className?: string }) {\n  return (\n    <Card className={cn(\"gap-4\", className)}>\n      <CardHeader>\n        <div className=\"flex items-start justify-between gap-4\">\n          <div className=\"flex-1 space-y-2\">\n            <div className=\"flex items-center gap-2\">\n              <Skeleton className=\"h-6 w-32\" />\n              <Skeleton className=\"h-5 w-16\" />\n            </div>\n            <Skeleton className=\"h-4 w-20\" />\n          </div>\n          <Skeleton className=\"size-12 rounded-md\" />\n        </div>\n      </CardHeader>\n      <CardContent className=\"space-y-3\">\n        <div className=\"space-y-2\">\n          <div className=\"flex items-center justify-between\">\n            <div className=\"space-y-1\">\n              <Skeleton className=\"h-4 w-24\" />\n              <Skeleton className=\"h-4 w-16\" />\n            </div>\n            <Skeleton className=\"h-4 w-16\" />\n          </div>\n        </div>\n        <Separator />\n        <div className=\"space-y-1.5\">\n          <div className=\"flex items-center justify-between\">\n            <Skeleton className=\"h-4 w-12\" />\n            <Skeleton className=\"h-4 w-20\" />\n          </div>\n        </div>\n        <Separator />\n        <div className=\"flex items-center gap-4\">\n          <Skeleton className=\"h-4 w-28\" />\n          <Skeleton className=\"h-4 w-20\" />\n        </div>\n        <div className=\"flex gap-2 pt-1\">\n          <Skeleton className=\"h-8 w-24\" />\n          <Skeleton className=\"h-8 w-20\" />\n        </div>\n      </CardContent>\n    </Card>\n  )\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/new-york/blocks/subscription-status-card/components/paddle-subscription-status-card.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { mapSubscriptionToStatusData } from \"@/registry/new-york/blocks/subscription-status-card/lib/subscription-status-card-utils\"\nimport {\n  SubscriptionStatusCard,\n  type SubscriptionStatusCardProps,\n} from \"./subscription-status-card\"\n\ntype PaddleSubscription = Parameters<typeof mapSubscriptionToStatusData>[0]\ntype RecurringTransactionDetails = Parameters<typeof mapSubscriptionToStatusData>[1]\ntype PaddleDiscount = Parameters<typeof mapSubscriptionToStatusData>[2]\n\nexport type PaddleSubscriptionStatusCardProps = {\n  subscription: PaddleSubscription\n  recurringTransactionDetails: RecurringTransactionDetails\n  discount?: PaddleDiscount\n} & Omit<SubscriptionStatusCardProps, \"subscription\">\n\n/**\n * Paddle-aware wrapper for `SubscriptionStatusCard`.\n *\n * Accepts the raw Paddle subscription entity and `recurringTransactionDetails`\n * (from `GET /subscriptions/{id}?include=recurring_transaction_details`),\n * maps them to `SubscriptionStatusData`, and renders the UI component.\n *\n * Optionally pass a Paddle `Discount` to\n * enrich the discount display with a code and derived description label.\n *\n * All display-only props (`onChangePlan`, `onManageSubscription`, etc.) are\n * passed through directly.\n *\n * @example\n * <PaddleSubscriptionStatusCard\n *   subscription={subscription}\n *   recurringTransactionDetails={subscription.recurringTransactionDetails}\n *   onChangePlan={() => setShowPlanChange(true)}\n * />\n */\nexport function PaddleSubscriptionStatusCard({\n  subscription,\n  recurringTransactionDetails,\n  discount,\n  ...uiProps\n}: PaddleSubscriptionStatusCardProps) {\n  const data = mapSubscriptionToStatusData(subscription, recurringTransactionDetails, discount)\n  return <SubscriptionStatusCard subscription={data} {...uiProps} />\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/new-york/blocks/subscription-status-card/lib/subscription-status-card-utils.ts",
      "content": "import type { SubscriptionStatusData } from \"@/registry/new-york/blocks/paddle-helpers/lib/paddle-types\"\nimport { parseAmount } from \"@/registry/new-york/blocks/paddle-helpers/lib/paddle-format\"\n\n// ---\n// Input shapes — minimal types matching the Paddle Node SDK / API response.\n// Field names use camelCase (Node SDK convention). Pass the raw API response\n// or destructure these fields from your own subscription fetch.\n// ---\n\ntype SubscriptionItem = {\n  product: {\n    name: string\n    description?: string | null\n    imageUrl?: string | null\n  }\n  price?: {\n    name?: string | null\n    unitPrice?: { amount: string; currencyCode: string } | null\n  } | null\n  quantity: number\n}\n\ntype RecurringLineItem = {\n  totals: { subtotal: string; total: string }\n}\n\ntype ScheduledChange = {\n  action: \"cancel\" | \"pause\" | \"resume\"\n  effectiveAt: string\n  resumeAt?: string | null\n} | null\n\n// Matches SDK SubscriptionDiscount — subscription.discount only has id + dates\ntype SubscriptionDiscountField = {\n  id: string\n  startsAt?: string | null\n  endsAt?: string | null\n} | null\n\n// Full Discount catalog entity — fetched separately via paddle.discounts.get(id)\ntype PaddleDiscount = {\n  id: string\n  description: string\n  code?: string | null\n  type: \"flat\" | \"flat_per_seat\" | \"percentage\"\n  amount: string\n}\n\ntype PaddleSubscription = {\n  id: string\n  status: \"active\" | \"canceled\" | \"past_due\" | \"paused\" | \"trialing\"\n  currencyCode: string\n  billingCycle: { interval: string; frequency: number }\n  collectionMode?: \"automatic\" | \"manual\"\n  startedAt: string\n  nextBilledAt?: string | null\n  canceledAt?: string | null\n  scheduledChange?: ScheduledChange\n  discount?: SubscriptionDiscountField\n  items: SubscriptionItem[]\n}\n\ntype RecurringTransactionDetails = {\n  totals: { total: string; discount?: string }\n  lineItems: RecurringLineItem[]\n}\n\n/**\n * Maps a Paddle subscription API response to the `SubscriptionStatusData`\n * display contract consumed by `SubscriptionStatusCard`.\n *\n * Pass the raw Paddle subscription and the\n * `recurring_transaction_details` include (required for accurate totals).\n * Optionally pass a Paddle `Discount` to enrich the discount display\n * with `code` and a derived description label.\n *\n * @param subscription - Paddle Subscription\n * @param recurringTransactionDetails - `subscription.recurringTransactionDetails` from the same response\n * @param discount - Paddle Discount for enriched discount display\n * @returns Mapped status data for `<SubscriptionStatusCard />`\n *\n * @example\n * const data = await paddle.subscriptions.get(subscriptionId, {\n *   include: [\"recurring_transaction_details\"],\n * })\n * const statusData = mapSubscriptionToStatusData(data, data.recurringTransactionDetails)\n */\nexport function mapSubscriptionToStatusData(\n  subscription: PaddleSubscription,\n  recurringTransactionDetails: RecurringTransactionDetails,\n  discount?: PaddleDiscount | null\n): SubscriptionStatusData {\n  const { currencyCode } = subscription\n\n  const items = subscription.items.map((item, i) => ({\n    productName: item.product.name,\n    productDescription: item.product.description ?? undefined,\n    productImageUrl: item.product.imageUrl ?? undefined,\n    priceName: item.price?.name ?? undefined,\n    quantity: item.quantity,\n    unitPrice: item.price?.unitPrice\n      ? parseAmount(item.price.unitPrice.amount, currencyCode)\n      : undefined,\n    lineTotal: parseAmount(\n      recurringTransactionDetails.lineItems[i]?.totals.subtotal ?? \"0\",\n      currencyCode\n    ),\n  }))\n\n  const discountAmount = recurringTransactionDetails.totals.discount\n    ? parseAmount(recurringTransactionDetails.totals.discount, currencyCode)\n    : 0\n\n  // Percentage discounts produce e.g. \"-15%\"; flat discounts leave description\n  // undefined so the component formats it from savingsAmount + currency.\n  const discountDescription =\n    discount?.type === \"percentage\" ? `-${discount.description}` : undefined\n\n  const discountOutput: SubscriptionStatusData[\"discount\"] =\n    subscription.discount && discountAmount > 0\n      ? {\n          savingsAmount: discountAmount,\n          endsAt: subscription.discount.endsAt ?? undefined,\n          code: discount?.code ?? undefined,\n          description: discountDescription,\n        }\n      : undefined\n\n  const scheduledChange: SubscriptionStatusData[\"scheduledChange\"] = subscription.scheduledChange\n    ? {\n        action: subscription.scheduledChange.action,\n        effectiveAt: subscription.scheduledChange.effectiveAt,\n        resumeAt: subscription.scheduledChange.resumeAt ?? undefined,\n      }\n    : undefined\n\n  return {\n    id: subscription.id,\n    items,\n    totalAmount: parseAmount(recurringTransactionDetails.totals.total, currencyCode),\n    currency: currencyCode,\n    interval: subscription.billingCycle.interval,\n    billingFrequency: subscription.billingCycle.frequency,\n    status: subscription.status,\n    collectionMode: subscription.collectionMode,\n    startedAt: subscription.startedAt,\n    nextBilledAt: subscription.nextBilledAt ?? undefined,\n    canceledAt: subscription.canceledAt ?? undefined,\n    scheduledChange,\n    discount: discountOutput,\n  }\n}\n",
      "type": "registry:lib"
    }
  ],
  "cssVars": {
    "light": {
      "success": "oklch(0.723 0.157 150)",
      "success-foreground": "oklch(0.266 0.065 152)",
      "warning": "oklch(0.769 0.163 70)",
      "warning-foreground": "oklch(0.286 0.066 53)",
      "info": "oklch(0.623 0.163 255)",
      "info-foreground": "oklch(0.235 0.063 258)"
    },
    "dark": {
      "success": "oklch(0.423 0.095 152)",
      "success-foreground": "oklch(0.92 0.042 154)",
      "warning": "oklch(0.437 0.096 54)",
      "warning-foreground": "oklch(0.94 0.034 82)",
      "info": "oklch(0.423 0.095 258)",
      "info-foreground": "oklch(0.92 0.042 252)"
    }
  },
  "categories": ["subscription"]
}
