{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "b-progress",
  "type": "registry:ui",
  "registryDependencies": [],
  "dependencies": ["@base-ui/react", "motion"],
  "devDependencies": [],
  "files": [
    {
      "path": "b-progress.tsx",
      "content": "\"use client\";\n\nimport { Progress as ProgressPrimitive } from \"@base-ui/react/progress\";\nimport {\n  type MotionValue,\n  motion,\n  useMotionValue,\n  useSpring,\n  useTransform,\n} from \"motion/react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst componentThemeClassName =\n  \"[--ic-background:#ffffff] [--ic-foreground:#111111] [--ic-primary:#111111] [--ic-secondary:#646b75] [--ic-surface-border:#e9edf2] [--ic-border:#e3e7ec] [--ic-card:#ffffff] [--ic-card-foreground:#111111] [--ic-muted:#f5f7fa] [--ic-muted-foreground:#6d7480] [--ic-accent:#f3f5f8] [--color-accent:var(--ic-accent)] [--color-accent-foreground:var(--ic-accent-foreground)] [--ic-accent-foreground:#111111] [--ic-input:#e3e7ec] [--ic-ring:rgba(17,17,17,0.16)] [--ic-destructive:#dc2626] [--ic-paper:#fcfcfd] [--ic-popover-foreground:#111111] [--ic-brand:#0ea5e9] [--ic-brand-soft:#bae6fd] [--ic-shadow-soft:0_18px_38px_-24px_rgba(15,23,42,0.35)] [--ic-chart-1:oklch(0.52_0.19_254)] [--ic-chart-2:oklch(0.74_0.11_232)] [--ic-chart-3:oklch(0.42_0.16_262)] [--ic-chart-4:oklch(0.84_0.07_228)] [--ic-chart-5:oklch(0.62_0.14_240)] [--color-background:var(--ic-background)] [--color-foreground:var(--ic-foreground)] [--color-primary:var(--ic-primary)] [--color-secondary:var(--ic-secondary)] [--color-border:var(--ic-border)] [--color-card:var(--ic-card)] [--color-card-foreground:var(--ic-card-foreground)] [--color-muted:var(--ic-muted)] [--color-muted-foreground:var(--ic-muted-foreground)] [--color-accent:var(--ic-accent)] [--color-accent-foreground:var(--ic-accent-foreground)] [--color-input:var(--ic-input)] [--color-ring:var(--ic-ring)] [--color-destructive:var(--ic-destructive)] [--color-paper:var(--ic-paper)] [--color-popover-foreground:var(--ic-popover-foreground)] [--color-brand:var(--ic-brand)] [--color-brand-soft:var(--ic-brand-soft)] [--color-chart-1:var(--ic-chart-1)] [--color-chart-2:var(--ic-chart-2)] [--color-chart-3:var(--ic-chart-3)] [--color-chart-4:var(--ic-chart-4)] [--color-chart-5:var(--ic-chart-5)] dark:[--ic-background:#111111] dark:[--ic-foreground:#f6f3ec] dark:[--ic-primary:#f6f3ec] dark:[--ic-secondary:#cbc6bb] dark:[--ic-surface-border:#2a2a25] dark:[--ic-border:#2b2a25] dark:[--ic-card:#111111] dark:[--ic-card-foreground:#f6f3ec] dark:[--ic-muted:#171716] dark:[--ic-muted-foreground:#9a958a] dark:[--ic-accent:#1a1a18] [--color-accent:var(--ic-accent)] [--color-accent-foreground:var(--ic-accent-foreground)] dark:[--ic-accent-foreground:#f6f3ec] dark:[--ic-input:#2b2a25] dark:[--ic-ring:rgba(246,243,236,0.18)] dark:[--ic-destructive:#f87171] dark:[--ic-paper:#171716] dark:[--ic-popover-foreground:#f6f3ec] dark:[--ic-brand:#38bdf8] dark:[--ic-brand-soft:#0c4a6e] dark:[--ic-shadow-soft:0_20px_44px_-28px_rgba(0,0,0,0.6)] dark:[--ic-chart-1:oklch(0.68_0.17_250)] dark:[--ic-chart-2:oklch(0.82_0.09_225)] dark:[--ic-chart-3:oklch(0.58_0.15_260)] dark:[--ic-chart-4:oklch(0.75_0.12_235)] dark:[--ic-chart-5:oklch(0.88_0.06_220)]\";\n\nconst fillSpring = {\n  type: \"spring\" as const,\n  stiffness: 84,\n  damping: 18,\n  mass: 1.14,\n  restDelta: 0.001,\n};\n\nconst shellSpring = {\n  type: \"spring\" as const,\n  stiffness: 260,\n  damping: 24,\n  mass: 0.78,\n};\n\nconst indeterminateTransition = {\n  duration: 1.55,\n  ease: [0.24, 0.04, 0.2, 1] as const,\n  repeat: Number.POSITIVE_INFINITY,\n};\n\nexport type ProgressSize = \"sm\" | \"md\" | \"lg\";\nexport type ProgressTone = \"default\" | \"brand\" | \"destructive\" | \"success\";\nexport type ProgressVariant = \"default\" | \"circular\";\n\nconst progressTrackSizes: Record<ProgressSize, string> = {\n  sm: \"h-1.5\",\n  md: \"h-2.5\",\n  lg: \"h-4\",\n};\n\nconst progressRingContainerSizes: Record<ProgressSize, string> = {\n  sm: \"size-28\",\n  md: \"size-32\",\n  lg: \"size-40\",\n};\n\nconst progressRingLabelSizes: Record<ProgressSize, string> = {\n  sm: \"text-lg\",\n  md: \"text-xl\",\n  lg: \"text-2xl\",\n};\n\nconst progressIndicatorTones: Record<ProgressTone, string> = {\n  default: \"bg-[var(--color-foreground)] dark:bg-white\",\n  brand: \"bg-[var(--color-brand)]\",\n  destructive: \"bg-[var(--color-destructive)]\",\n  success: \"bg-emerald-500 dark:bg-emerald-400\",\n};\n\nconst progressGaugePrimaryColors: Record<ProgressTone, string> = {\n  default: \"var(--color-foreground)\",\n  brand: \"var(--color-brand)\",\n  destructive: \"var(--color-destructive)\",\n  success: \"#10b981\",\n};\n\nconst progressGaugeSecondaryColors: Record<ProgressTone, string> = {\n  default: \"color-mix(in oklab, var(--color-foreground) 14%, transparent)\",\n  brand: \"color-mix(in oklab, var(--color-brand) 18%, transparent)\",\n  destructive: \"color-mix(in oklab, var(--color-destructive) 18%, transparent)\",\n  success: \"color-mix(in oklab, #10b981 18%, transparent)\",\n};\n\nconst circularGaugeRadius = 45;\nconst circularGaugeCircumference = 2 * Math.PI * circularGaugeRadius;\nconst circularGaugePercentPx = circularGaugeCircumference / 100;\n\nexport interface ProgressProps\n  extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"children\"> {\n  ariaLabel?: string;\n  formatValue?: (value: number, percent: number) => string;\n  getValueLabel?: (value: number, percent: number) => string;\n  headerClassName?: string;\n  helper?: string;\n  indeterminateLabel?: string;\n  indicatorClassName?: string;\n  label?: string;\n  max?: number;\n  min?: number;\n  showValue?: boolean;\n  size?: ProgressSize;\n  tone?: ProgressTone;\n  trackClassName?: string;\n  value?: number | null;\n  variant?: ProgressVariant;\n}\n\nfunction clamp(value: number, min: number, max: number) {\n  return Math.min(Math.max(value, min), max);\n}\n\nfunction resolveBounds(min: number, max: number) {\n  return {\n    min: Math.min(min, max),\n    max: Math.max(min, max),\n  };\n}\n\nfunction toPercent(value: number, min: number, max: number) {\n  const range = max - min;\n  if (range <= 0) {\n    return value >= max ? 100 : 0;\n  }\n\n  return clamp(((value - min) / range) * 100, 0, 100);\n}\n\nfunction normalizeNumericValue(\n  value: number | null | undefined,\n  bounds: { min: number; max: number }\n) {\n  if (value === null) {\n    return null;\n  }\n\n  const numeric = value ?? 0;\n  if (!Number.isFinite(numeric)) {\n    return bounds.min;\n  }\n\n  return clamp(numeric, bounds.min, bounds.max);\n}\n\nfunction resolveDisplayValue(\n  actualValue: number,\n  percent: number,\n  formatValue?: (value: number, percent: number) => string\n) {\n  if (formatValue) {\n    return formatValue(actualValue, percent);\n  }\n\n  return `${Math.round(percent)}%`;\n}\n\nfunction resolveAriaValueText(\n  actualValue: number | null,\n  percent: number,\n  indeterminateLabel: string,\n  getValueLabel?: (value: number, percent: number) => string,\n  formatValue?: (value: number, percent: number) => string\n) {\n  if (actualValue === null) {\n    return indeterminateLabel;\n  }\n\n  if (getValueLabel) {\n    return getValueLabel(actualValue, percent);\n  }\n\n  return resolveDisplayValue(actualValue, percent, formatValue);\n}\n\nfunction ProgressHeader({\n  displayValue,\n  headerClassName,\n  helper,\n  helperId,\n  label,\n  labelId,\n  showValue,\n}: {\n  displayValue: string | MotionValue<string>;\n  headerClassName?: string;\n  helper?: string;\n  helperId: string;\n  label?: string;\n  labelId: string;\n  showValue: boolean;\n}) {\n  if (!(label || helper || showValue)) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\"flex items-end justify-between gap-4\", headerClassName)}\n    >\n      <div className=\"space-y-1\">\n        {label ? (\n          <span\n            className=\"font-medium text-[12px] text-foreground/90 tracking-[-0.02em] sm:text-[13px]\"\n            id={labelId}\n          >\n            {label}\n          </span>\n        ) : null}\n        {helper ? (\n          <p\n            className=\"max-w-xl text-[12px] text-muted-foreground leading-5 sm:text-[13px]\"\n            id={helperId}\n          >\n            {helper}\n          </p>\n        ) : null}\n      </div>\n\n      {showValue ? (\n        <motion.span\n          animate={{ opacity: 1, y: 0 }}\n          className=\"shrink-0 font-medium text-[12px] text-muted-foreground tabular-nums tracking-[-0.02em] sm:text-[13px]\"\n          transition={shellSpring}\n        >\n          {displayValue}\n        </motion.span>\n      ) : null}\n    </div>\n  );\n}\n\nfunction DeterminateFill({\n  fillScale,\n  indicatorClassName,\n  tone,\n}: {\n  fillScale: MotionValue<number>;\n  indicatorClassName?: string;\n  tone: ProgressTone;\n}) {\n  return (\n    <ProgressPrimitive.Indicator\n      render={(props) => (\n        <motion.div\n          className={cn(\n            \"absolute inset-y-0 left-0 h-full w-full origin-left rounded-full will-change-transform\",\n            progressIndicatorTones[tone],\n            indicatorClassName,\n            props.className\n          )}\n          ref={props.ref}\n          style={{ ...props.style, width: \"100%\", scaleX: fillScale }}\n        />\n      )}\n    />\n  );\n}\n\nfunction IndeterminateFill({ tone }: { tone: ProgressTone }) {\n  const toneClassName =\n    tone === \"default\"\n      ? \"[--progress-indeterminate-core:color-mix(in_srgb,var(--ic-foreground)_16%,transparent)] [--progress-indeterminate-soft:color-mix(in_srgb,var(--ic-foreground)_8%,transparent)] dark:[--progress-indeterminate-core:color-mix(in_srgb,var(--ic-foreground)_14%,transparent)] dark:[--progress-indeterminate-soft:color-mix(in_srgb,var(--ic-foreground)_7%,transparent)]\"\n      : tone === \"brand\"\n        ? \"[--progress-indeterminate-core:color-mix(in_srgb,var(--ic-brand)_72%,transparent)] [--progress-indeterminate-soft:color-mix(in_srgb,var(--ic-brand)_36%,transparent)]\"\n        : tone === \"destructive\"\n          ? \"[--progress-indeterminate-core:color-mix(in_srgb,var(--ic-destructive)_72%,transparent)] [--progress-indeterminate-soft:color-mix(in_srgb,var(--ic-destructive)_36%,transparent)]\"\n          : \"[--progress-indeterminate-core:color-mix(in_srgb,#10b981_72%,transparent)] [--progress-indeterminate-soft:color-mix(in_srgb,#10b981_36%,transparent)]\";\n\n  return (\n    <div aria-hidden className=\"absolute inset-0 overflow-hidden rounded-full\">\n      <motion.div\n        animate={{\n          opacity: [0, 0.92, 0.92, 0],\n          scaleX: [0.94, 1, 0.96],\n          x: [\"-44%\", \"238%\"],\n        }}\n        className={cn(\n          \"absolute inset-y-0 left-0 w-[38%] rounded-full\",\n          toneClassName\n        )}\n        style={{\n          backgroundImage:\n            \"linear-gradient(90deg, transparent 0%, var(--progress-indeterminate-soft) 16%, var(--progress-indeterminate-core) 50%, var(--progress-indeterminate-soft) 84%, transparent 100%)\",\n        }}\n        transition={{\n          ...indeterminateTransition,\n          times: [0, 0.14, 0.84, 1],\n        }}\n      />\n    </div>\n  );\n}\n\nfunction CircularCenterValue({\n  currentPercent,\n  displayValue,\n  size,\n}: {\n  currentPercent: number;\n  displayValue: string | MotionValue<string>;\n  size: ProgressSize;\n}) {\n  const className = cn(\n    \"pointer-events-none absolute inset-0 m-auto flex size-fit max-w-[78%] items-center justify-center truncate text-center font-semibold tabular-nums\",\n    progressRingLabelSizes[size]\n  );\n\n  if (typeof displayValue === \"string\") {\n    return (\n      <span className={className} data-current-value={currentPercent}>\n        {displayValue}\n      </span>\n    );\n  }\n\n  return (\n    <motion.span className={className} data-current-value={currentPercent}>\n      {displayValue}\n    </motion.span>\n  );\n}\n\nfunction CircularProgressVisual({\n  clampedValue,\n  currentPercent,\n  displayValue,\n  indeterminateLabel,\n  indicatorClassName,\n  showValue,\n  size,\n  tone,\n  trackClassName,\n}: {\n  clampedValue: number | null;\n  currentPercent: number;\n  displayValue: string | MotionValue<string>;\n  indeterminateLabel: string;\n  indicatorClassName?: string;\n  showValue: boolean;\n  size: ProgressSize;\n  tone: ProgressTone;\n  trackClassName?: string;\n}) {\n  const gaugePrimaryColor = progressGaugePrimaryColors[tone];\n  const gaugeSecondaryColor = progressGaugeSecondaryColors[tone];\n  const gaugeStyle = {\n    \"--circle-size\": \"100px\",\n    \"--circumference\": circularGaugeCircumference,\n    \"--percent-to-px\": `${circularGaugePercentPx}px`,\n    \"--gap-percent\": \"5\",\n    \"--offset-factor\": \"0\",\n    \"--transition-length\": \"1s\",\n    \"--transition-step\": \"200ms\",\n    \"--delay\": \"0s\",\n    \"--percent-to-deg\": \"3.6deg\",\n    transform: \"translateZ(0)\",\n  } as React.CSSProperties;\n\n  if (clampedValue === null) {\n    return (\n      <div\n        className={cn(\n          \"relative shrink-0 font-semibold\",\n          progressRingContainerSizes[size],\n          trackClassName\n        )}\n        style={gaugeStyle}\n      >\n        <motion.svg\n          animate={{ rotate: 360 }}\n          aria-hidden\n          className=\"size-full\"\n          fill=\"none\"\n          transition={{\n            duration: 1.15,\n            ease: \"linear\",\n            repeat: Number.POSITIVE_INFINITY,\n          }}\n          viewBox=\"0 0 100 100\"\n        >\n          <circle\n            cx=\"50\"\n            cy=\"50\"\n            fill=\"none\"\n            r={circularGaugeRadius}\n            stroke={gaugeSecondaryColor}\n            strokeWidth=\"10\"\n          />\n          <circle\n            className={indicatorClassName}\n            cx=\"50\"\n            cy=\"50\"\n            fill=\"none\"\n            r={circularGaugeRadius}\n            stroke={gaugePrimaryColor}\n            strokeDasharray={`${circularGaugeCircumference * 0.28} ${circularGaugeCircumference * 0.72}`}\n            strokeLinecap=\"round\"\n            strokeWidth=\"10\"\n          />\n        </motion.svg>\n        {showValue ? (\n          <CircularCenterValue\n            currentPercent={0}\n            displayValue={indeterminateLabel}\n            size={size}\n          />\n        ) : null}\n      </div>\n    );\n  }\n\n  return (\n    <div\n      className={cn(\n        \"relative shrink-0 font-semibold\",\n        progressRingContainerSizes[size],\n        trackClassName\n      )}\n      style={gaugeStyle}\n    >\n      <svg\n        aria-hidden\n        className=\"size-full\"\n        fill=\"none\"\n        strokeWidth=\"2\"\n        viewBox=\"0 0 100 100\"\n      >\n        {currentPercent <= 90 && currentPercent >= 0 ? (\n          <circle\n            className=\"opacity-100\"\n            cx=\"50\"\n            cy=\"50\"\n            fill=\"none\"\n            r={circularGaugeRadius}\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            strokeWidth=\"10\"\n            style={\n              {\n                stroke: gaugeSecondaryColor,\n                \"--stroke-percent\": 90 - currentPercent,\n                \"--offset-factor-secondary\": \"calc(1 - var(--offset-factor))\",\n                strokeDasharray:\n                  \"calc(var(--stroke-percent) * var(--percent-to-px)) var(--circumference)\",\n                transform:\n                  \"rotate(calc(1turn - 90deg - (var(--gap-percent) * var(--percent-to-deg) * var(--offset-factor-secondary)))) scaleY(-1)\",\n                transition: \"all var(--transition-length) ease var(--delay)\",\n                transformOrigin:\n                  \"calc(var(--circle-size) / 2) calc(var(--circle-size) / 2)\",\n              } as React.CSSProperties\n            }\n          />\n        ) : null}\n        <circle\n          className={cn(\"opacity-100\", indicatorClassName)}\n          cx=\"50\"\n          cy=\"50\"\n          fill=\"none\"\n          r={circularGaugeRadius}\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          strokeWidth=\"10\"\n          style={\n            {\n              stroke: gaugePrimaryColor,\n              \"--stroke-percent\": currentPercent,\n              strokeDasharray:\n                \"calc(var(--stroke-percent) * var(--percent-to-px)) var(--circumference)\",\n              transition:\n                \"var(--transition-length) ease var(--delay),stroke var(--transition-length) ease var(--delay)\",\n              transitionProperty: \"stroke-dasharray,transform\",\n              transform:\n                \"rotate(calc(-90deg + var(--gap-percent) * var(--offset-factor) * var(--percent-to-deg)))\",\n              transformOrigin:\n                \"calc(var(--circle-size) / 2) calc(var(--circle-size) / 2)\",\n            } as React.CSSProperties\n          }\n        />\n      </svg>\n      {showValue ? (\n        <CircularCenterValue\n          currentPercent={currentPercent}\n          displayValue={displayValue}\n          size={size}\n        />\n      ) : null}\n    </div>\n  );\n}\n\nexport const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(\n  function Progress(\n    {\n      ariaLabel,\n      className,\n      formatValue,\n      getValueLabel,\n      headerClassName,\n      helper,\n      id,\n      indeterminateLabel = \"In progress\",\n      indicatorClassName,\n      label,\n      max = 100,\n      min = 0,\n      showValue = true,\n      size = \"md\",\n      tone = \"default\",\n      trackClassName,\n      value = 0,\n      variant = \"default\",\n      ...props\n    },\n    ref\n  ) {\n    const labelId = React.useId();\n    const helperId = React.useId();\n    const isCircular = variant === \"circular\";\n    const bounds = resolveBounds(min, max);\n    const clampedValue = normalizeNumericValue(value, bounds);\n    const progress =\n      clampedValue === null\n        ? 0\n        : toPercent(clampedValue, bounds.min, bounds.max);\n    const progressTargetMV = useMotionValue(progress);\n    const smoothProgressMV = useSpring(progressTargetMV, fillSpring);\n    const formatValueRef = React.useRef(formatValue);\n    formatValueRef.current = formatValue;\n    const fillScale = useTransform(smoothProgressMV, (currentProgress) => {\n      return currentProgress / 100;\n    });\n    const displayValue = useTransform(smoothProgressMV, (currentProgress) => {\n      const actualValue =\n        bounds.min + ((bounds.max - bounds.min) * currentProgress) / 100;\n\n      return resolveDisplayValue(\n        actualValue,\n        currentProgress,\n        formatValueRef.current\n      );\n    });\n    const hasInitializedMotion = React.useRef(false);\n\n    React.useEffect(() => {\n      if (clampedValue === null) {\n        progressTargetMV.jump(progress);\n        smoothProgressMV.jump(progress);\n        hasInitializedMotion.current = true;\n        return;\n      }\n\n      if (!hasInitializedMotion.current) {\n        progressTargetMV.jump(progress);\n        smoothProgressMV.jump(progress);\n        hasInitializedMotion.current = true;\n        return;\n      }\n\n      progressTargetMV.set(progress);\n    }, [clampedValue, progress, progressTargetMV, smoothProgressMV]);\n\n    const renderedValue =\n      clampedValue === null ? indeterminateLabel : displayValue;\n    const currentPercent = clamp(Math.round(progress), 0, 100);\n    const circularCenterValue =\n      clampedValue === null\n        ? indeterminateLabel\n        : formatValue\n          ? renderedValue\n          : String(currentPercent);\n\n    return (\n      <div\n        className={cn(\n          componentThemeClassName,\n          isCircular\n            ? \"inline-flex w-auto flex-col items-center gap-3\"\n            : \"w-full space-y-3\",\n          className\n        )}\n        id={id}\n        ref={ref}\n        {...props}\n      >\n        <ProgressHeader\n          displayValue={renderedValue}\n          headerClassName={cn(isCircular && \"w-full min-w-0\", headerClassName)}\n          helper={helper}\n          helperId={helperId}\n          label={label}\n          labelId={labelId}\n          showValue={showValue && !isCircular}\n        />\n\n        <ProgressPrimitive.Root\n          aria-describedby={helper ? helperId : undefined}\n          aria-label={ariaLabel ?? (label ? undefined : \"Progress\")}\n          aria-labelledby={label ? labelId : undefined}\n          className={cn(isCircular && \"inline-flex shrink-0\")}\n          getAriaValueText={(_, actualValue) => {\n            const currentPercentValue =\n              actualValue === null\n                ? 0\n                : clamp(\n                    Math.round(toPercent(actualValue, bounds.min, bounds.max)),\n                    0,\n                    100\n                  );\n            return resolveAriaValueText(\n              actualValue,\n              currentPercentValue,\n              indeterminateLabel,\n              getValueLabel,\n              formatValue\n            );\n          }}\n          max={bounds.max}\n          min={bounds.min}\n          value={clampedValue}\n        >\n          {isCircular ? (\n            <CircularProgressVisual\n              clampedValue={clampedValue}\n              currentPercent={currentPercent}\n              displayValue={circularCenterValue}\n              indeterminateLabel={indeterminateLabel}\n              indicatorClassName={indicatorClassName}\n              showValue={showValue}\n              size={size}\n              tone={tone}\n              trackClassName={trackClassName}\n            />\n          ) : (\n            <ProgressPrimitive.Track\n              className={cn(\n                \"relative overflow-hidden rounded-full bg-foreground/8 dark:bg-white/[0.08]\",\n                progressTrackSizes[size],\n                trackClassName\n              )}\n            >\n              {clampedValue === null ? (\n                <IndeterminateFill tone={tone} />\n              ) : (\n                <DeterminateFill\n                  fillScale={fillScale}\n                  indicatorClassName={indicatorClassName}\n                  tone={tone}\n                />\n              )}\n            </ProgressPrimitive.Track>\n          )}\n        </ProgressPrimitive.Root>\n      </div>\n    );\n  }\n);\n\nProgress.displayName = \"Progress\";\n\nexport { Progress as progress };\n",
      "type": "registry:ui"
    }
  ],
  "title": "Progress (Base UI)",
  "description": "Progress bar with the same Iconiq API layered over Base UI primitives, preserving the spring-smoothed fill, restrained inline readout, and quiet indeterminate motion."
}
