# Sync Grid: Redesign

> Three versions of one product's site, built from markup, each scrolling with the clock while the same visitor moves and clicks through it. Drag 2026 onto 2019 and slide the divider: the old and new layouts sit at the same scroll point.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/sync-grid-redesign-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/sync-grid-redesign-demo
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/keyframeui/sync-grid-redesign-demo-light-a4bec8d7418ea51a.png
- Registry item: https://keyframeui.com/r/sync-grid-redesign-demo.json
- Categories: video, comparison, scrubbing, motion
- Listed: 2026-10-14, source last changed 2026-10-15

## Install

```bash
npx shadcn@latest add https://keyframeui.com/r/sync-grid-redesign-demo.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `https://keyframeui.com/r/sync-grid.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/sync-grid#sync-grid-redesign-demo

## Files

### `registry/demos/sync-grid-redesign-demo.tsx`

```tsx
"use client";

import * as React from "react";
import { easeInOut, motion, useTransform, type MotionValue } from "motion/react";

import { SyncGrid, SyncGridItem } from "@/components/ui/sync-grid";

/* Three versions of one product's site, built from markup. Every version
 * keeps its sections on the same grid, so at any moment they're scrolled to
 * the same part of the page, and the same visitor moves and clicks through
 * all three.
 *
 * Sizes are in cqw, so a page scales with its card: a thumbnail in the grid,
 * readable once two are merged to compare.
 *
 *   page     180cqw tall, in a 57cqw window under a 5.5cqw toolbar
 *   0–8      nav
 *   8–62     hero, with the call to action
 *   62–74    customers
 *   74–126   features
 *   126–172  pricing
 *   172–180  footer
 */

const PAGE = 180;
const WINDOW = 57;

// When the visitor clicks, as shares of the clock.
const CLICK = { cta: 0.17, plan: 0.86 };

// How far down the page, over the clock: hero, then features, then pricing.
const SCROLL = { at: [0, 0.24, 0.46, 0.56, 0.8, 1], to: [0, 0, 0.45, 0.45, 1, 1] };

type Point = [x: number, y: number]; // cqw within the window

type Version = {
  year: string;
  page: React.ComponentType<{ progress: MotionValue<number> }>;
  // Where the visitor's targets sit in the window when they're used.
  targets: { cta: Point; feature: Point; plan: Point };
};

const versions: Version[] = [
  { year: "2019", page: Page2019, targets: { cta: [50, 35], feature: [50, 40], plan: [50, 34.5] } },
  { year: "2023", page: Page2023, targets: { cta: [15, 46], feature: [33, 36], plan: [60, 35] } },
  { year: "2026", page: Page2026, targets: { cta: [12, 42], feature: [80, 41], plan: [87, 25] } },
];

export function SyncGridRedesignDemo() {
  return (
    <div className="w-full max-w-4xl">
      <div className="mb-4 flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1">
        <p className="text-sm font-medium text-zinc-900 dark:text-zinc-100">
          tidely.app <span className="font-normal text-zinc-500">· three redesigns, one visit</span>
        </p>
        <p className="text-xs text-zinc-500">Drag 2026 onto 2019 to compare</p>
      </div>
      <SyncGrid columns={3} duration={8} aspect={16 / 10}>
        {versions.map((version) => (
          <SyncGridItem
            key={version.year}
            label={version.year}
            render={(progress) => <Browser progress={progress} version={version} />}
          />
        ))}
      </SyncGrid>
    </div>
  );
}

function Browser({ progress, version }: { progress: MotionValue<number>; version: Version }) {
  const Page = version.page;
  const scroll = useTransform(progress, SCROLL.at, SCROLL.to, { ease: easeInOut });
  const y = useTransform(scroll, (s) => `${-s * (1 - WINDOW / PAGE) * 100}%`);

  return (
    <div className="@container absolute inset-0 overflow-hidden bg-zinc-100 dark:bg-zinc-800">
      <div className="flex h-[5.5cqw] items-center gap-[0.9cqw] px-[2cqw]">
        <span className="size-[1.3cqw] rounded-full bg-zinc-300 dark:bg-zinc-600" />
        <span className="size-[1.3cqw] rounded-full bg-zinc-300 dark:bg-zinc-600" />
        <span className="size-[1.3cqw] rounded-full bg-zinc-300 dark:bg-zinc-600" />
        <span className="mx-auto rounded-full bg-white px-[3cqw] py-[0.5cqw] font-mono text-[1.6cqw] leading-none text-zinc-500 dark:bg-zinc-900 dark:text-zinc-400">
          tidely.app
        </span>
        <span className="w-[5cqw]" />
      </div>
      <div className="absolute inset-x-0 top-[5.5cqw] bottom-0 overflow-hidden">
        <motion.div className="h-[180cqw]" style={{ y }}>
          <Page progress={progress} />
        </motion.div>
        <Cursor progress={progress} targets={version.targets} />
      </div>
    </div>
  );
}

/** The visitor: to the call to action and click, a feature, then a plan and click. */
function Cursor({ progress, targets }: { progress: MotionValue<number>; targets: Version["targets"] }) {
  const { cta, feature, plan } = targets;
  const at = [0, 0.15, CLICK.cta, 0.3, 0.48, 0.6, 0.83, CLICK.plan, 1];
  const xs = [80, cta[0], cta[0], 68, feature[0], 64, plan[0], plan[0], plan[0]];
  const ys = [48, cta[1], cta[1], 24, feature[1], 18, plan[1], plan[1], plan[1]];
  const x = useTransform(progress, at, xs.map((v) => `${v}cqw`), { ease: easeInOut });
  const y = useTransform(progress, at, ys.map((v) => `${v}cqw`), { ease: easeInOut });

  return (
    <motion.div className="pointer-events-none absolute top-0 left-0" style={{ x, y }}>
      <Ripple progress={progress} at={CLICK.cta} />
      <Ripple progress={progress} at={CLICK.plan} />
      <svg viewBox="0 0 24 24" className="relative size-[3.4cqw] -translate-x-[12%] -translate-y-[8%] drop-shadow">
        <path
          d="M4 2.5v16.2l4.3-4.1 2.8 6.3 2.7-1.2-2.8-6.2h6L4 2.5Z"
          fill="white"
          stroke="black"
          strokeWidth="1.4"
          strokeLinejoin="round"
        />
      </svg>
    </motion.div>
  );
}

function Ripple({ progress, at }: { progress: MotionValue<number>; at: number }) {
  const scale = useTransform(progress, [at, at + 0.06], [0.2, 1.6]);
  const opacity = useTransform(progress, [at - 0.001, at, at + 0.06], [0, 0.7, 0]);
  return (
    <motion.span
      className="absolute top-0 left-0 size-[6cqw] -translate-x-1/2 -translate-y-1/2 rounded-full border-[0.5cqw] border-sky-400"
      style={{ scale, opacity }}
    />
  );
}

/** A button that dips when the visitor clicks it. */
function Press({
  progress,
  at,
  className,
  children,
}: {
  progress: MotionValue<number>;
  at: number;
  className?: string;
  children: React.ReactNode;
}) {
  const scale = useTransform(progress, [at - 0.004, at, at + 0.03, at + 0.05], [1, 0.92, 0.92, 1]);
  const brightness = useTransform(progress, [at - 0.004, at, at + 0.03, at + 0.05], [1, 0.85, 0.85, 1]);
  const filter = useTransform(brightness, (b) => `brightness(${b})`);
  return (
    <motion.span className={className} style={{ scale, filter }}>
      {children}
    </motion.span>
  );
}

/** Lights up while the visitor rests on it. */
function useHover(progress: MotionValue<number>) {
  return useTransform(progress, [0.45, 0.49, 0.57, 0.6], [0, 1, 1, 0]);
}

function Lines({ count = 2, className }: { count?: number; className?: string }) {
  return (
    <span className="flex w-full flex-col gap-[0.9cqw]">
      {Array.from({ length: count }, (_, i) => (
        <span key={i} className={className} style={{ width: `${i === count - 1 ? 62 : 100}%` }} />
      ))}
    </span>
  );
}

// ── 2019: the launch site. A blue gradient, centered, a stock product shot ──

function Page2019({ progress }: { progress: MotionValue<number> }) {
  const shadow = useShadow(useHover(progress), "rgb(59 130 246 / 0.35)");
  return (
    <div className="h-full bg-white text-slate-800">
      <div className="flex h-[8cqw] items-center justify-between border-b border-slate-200 px-[5cqw]">
        <span className="flex items-center gap-[1cqw] text-[2.6cqw] font-bold text-slate-900">
          <span className="size-[2.8cqw] rounded-[0.5cqw] bg-blue-600" /> tidely
        </span>
        <span className="flex items-center gap-[3cqw] text-[1.7cqw] text-slate-500">
          <span>Features</span>
          <span>Pricing</span>
          <span>Blog</span>
          <span className="rounded-[0.5cqw] bg-blue-600 px-[1.6cqw] py-[0.7cqw] text-white">Sign up</span>
        </span>
      </div>
      <div className="flex h-[54cqw] flex-col items-center bg-gradient-to-br from-blue-600 to-indigo-700 px-[10cqw] pt-[6cqw] text-center text-white">
        <p className="text-[4.4cqw] leading-[1.15] font-bold">The smarter way to manage your team&apos;s calendar</p>
        <span className="mt-[2cqw] w-[60%]">
          <Lines className="h-[1.3cqw] self-center rounded-full bg-white/40" />
        </span>
        <Press
          progress={progress}
          at={CLICK.cta}
          className="mt-[3cqw] rounded-[0.6cqw] bg-white px-[3.2cqw] py-[1.4cqw] text-[1.9cqw] font-semibold text-blue-700 shadow-lg"
        >
          Start free trial
        </Press>
        <span className="mt-[4cqw] h-[14cqw] w-[56%] rounded-t-[1cqw] border-x-[0.8cqw] border-t-[0.8cqw] border-slate-800 bg-slate-100 p-[1.2cqw]">
          <span className="grid h-full grid-cols-4 gap-[0.8cqw]">
            <span className="col-span-1 rounded-[0.3cqw] bg-blue-200" />
            <span className="col-span-3 rounded-[0.3cqw] bg-white" />
          </span>
        </span>
      </div>
      <div className="flex h-[12cqw] items-center justify-center gap-[5cqw] bg-slate-50">
        {[10, 13, 9, 12, 11].map((w, i) => (
          <span key={i} className="h-[2cqw] rounded-[0.4cqw] bg-slate-300" style={{ width: `${w}cqw` }} />
        ))}
      </div>
      <div className="h-[52cqw] px-[7cqw] pt-[6cqw]">
        <p className="text-center text-[3.2cqw] font-bold text-slate-900">Everything you need</p>
        <div className="mt-[4cqw] grid grid-cols-3 gap-[3cqw]">
          {["bg-blue-500", "bg-emerald-500", "bg-amber-500"].map((color, i) => (
            <motion.span
              key={color}
              className="flex flex-col items-center gap-[1.4cqw] rounded-[0.8cqw] border border-slate-200 p-[2.4cqw] text-center"
              style={i === 1 ? { boxShadow: shadow } : undefined}
            >
              <span className={`size-[6cqw] rounded-full ${color}`} />
              <span className="text-[1.9cqw] font-semibold">{["Smart sync", "Team view", "Reminders"][i]}</span>
              <Lines count={3} className="h-[1cqw] rounded-full bg-slate-200" />
            </motion.span>
          ))}
        </div>
      </div>
      <div className="h-[46cqw] bg-slate-50 px-[7cqw] pt-[5cqw]">
        <p className="text-center text-[3.2cqw] font-bold text-slate-900">Simple pricing</p>
        <div className="mt-[3.5cqw] grid grid-cols-3 items-start gap-[2.5cqw]">
          {["Free", "Team", "Business"].map((plan, i) => (
            <span
              key={plan}
              className={`flex flex-col items-center gap-[1.2cqw] rounded-[0.8cqw] border bg-white p-[2.2cqw] ${i === 1 ? "border-blue-600 shadow-lg" : "border-slate-200"}`}
            >
              <span className="text-[1.8cqw] font-semibold">{plan}</span>
              <span className="text-[3.4cqw] font-bold text-slate-900">${[0, 8, 16][i]}</span>
              <Lines count={2} className="h-[0.9cqw] rounded-full bg-slate-200" />
              {i === 1 ? (
                <Press
                  progress={progress}
                  at={CLICK.plan}
                  className="mt-[0.6cqw] rounded-[0.5cqw] bg-blue-600 px-[2.4cqw] py-[1cqw] text-[1.6cqw] font-semibold text-white"
                >
                  Choose plan
                </Press>
              ) : (
                <span className="mt-[0.6cqw] rounded-[0.5cqw] border border-slate-300 px-[2.4cqw] py-[1cqw] text-[1.6cqw]">
                  Choose plan
                </span>
              )}
            </span>
          ))}
        </div>
      </div>
      <div className="flex h-[8cqw] items-center justify-center bg-slate-900 text-[1.4cqw] text-slate-400">
        © 2019 Tidely Inc.
      </div>
    </div>
  );
}

// ── 2023: the rebrand. Dark, a glow, gradient type, a bento grid ──

function Page2023({ progress }: { progress: MotionValue<number> }) {
  const shadow = useShadow(useHover(progress), "rgb(167 139 250 / 0.45)");
  return (
    <div className="relative h-full overflow-hidden bg-[#09090f] text-white">
      <span className="absolute top-[4cqw] left-[46cqw] size-[46cqw] rounded-full bg-violet-600/45 blur-[10cqw]" />
      <span className="absolute top-[18cqw] left-[66cqw] size-[30cqw] rounded-full bg-cyan-400/30 blur-[9cqw]" />
      <div className="relative flex h-[8cqw] items-center justify-between px-[5cqw]">
        <span className="text-[2.5cqw] font-semibold tracking-tight">tidely</span>
        <span className="flex items-center gap-[1cqw] rounded-full bg-white/[0.06] p-[0.5cqw] text-[1.6cqw] text-white/60 ring-1 ring-white/10">
          <span className="px-[1.4cqw]">Product</span>
          <span className="px-[1.4cqw]">Pricing</span>
          <span className="rounded-full bg-white px-[1.6cqw] py-[0.6cqw] text-[#09090f]">Log in</span>
        </span>
      </div>
      <div className="relative h-[54cqw] px-[7cqw] pt-[6.5cqw]">
        <span className="rounded-full bg-white/[0.07] px-[1.4cqw] py-[0.5cqw] text-[1.4cqw] text-white/70 ring-1 ring-white/10">
          New · AI scheduling
        </span>
        <p className="mt-[2.4cqw] max-w-[62cqw] bg-gradient-to-r from-white via-violet-200 to-cyan-300 bg-clip-text text-[6cqw] leading-[1.02] font-semibold tracking-tight text-transparent">
          Calendars that think ahead
        </p>
        <span className="mt-[2cqw] block w-[42cqw]">
          <Lines className="h-[1.2cqw] rounded-full bg-white/20" />
        </span>
        <span className="mt-[3.4cqw] flex items-center gap-[1.6cqw]">
          <Press
            progress={progress}
            at={CLICK.cta}
            className="rounded-full bg-white px-[3cqw] py-[1.3cqw] text-[1.8cqw] font-semibold text-[#09090f]"
          >
            Get started
          </Press>
          <span className="rounded-full px-[2cqw] py-[1.3cqw] text-[1.8cqw] text-white/70 ring-1 ring-white/15">Watch demo</span>
        </span>
      </div>
      <div className="relative flex h-[12cqw] items-center gap-[5cqw] px-[7cqw] opacity-40">
        {[9, 12, 8, 11, 10].map((w, i) => (
          <span key={i} className="h-[1.8cqw] rounded-full bg-white" style={{ width: `${w}cqw` }} />
        ))}
      </div>
      <div className="relative grid h-[52cqw] grid-cols-3 grid-rows-2 gap-[1.6cqw] px-[7cqw] pt-[2cqw] pb-[4cqw]">
        <motion.span
          className="col-span-2 rounded-[1.6cqw] bg-white/[0.05] p-[2.4cqw] ring-1 ring-white/10"
          style={{ boxShadow: shadow }}
        >
          <span className="block text-[2.2cqw] font-semibold">Auto-schedule</span>
          <span className="mt-[2cqw] grid grid-cols-5 gap-[0.8cqw]">
            {Array.from({ length: 10 }, (_, i) => (
              <span key={i} className={`h-[3cqw] rounded-[0.5cqw] ${i % 3 === 0 ? "bg-violet-500/70" : "bg-white/10"}`} />
            ))}
          </span>
        </motion.span>
        <span className="row-span-2 rounded-[1.6cqw] bg-gradient-to-b from-violet-500/30 to-cyan-400/10 p-[2.4cqw] ring-1 ring-white/10">
          <span className="block text-[2.2cqw] font-semibold">Focus time</span>
          <span className="mt-[2cqw] block w-full">
            <Lines count={4} className="h-[1cqw] rounded-full bg-white/20" />
          </span>
        </span>
        <span className="rounded-[1.6cqw] bg-white/[0.05] p-[2.4cqw] ring-1 ring-white/10">
          <span className="block text-[2cqw] font-semibold">Time zones</span>
        </span>
        <span className="rounded-[1.6cqw] bg-white/[0.05] p-[2.4cqw] ring-1 ring-white/10">
          <span className="block text-[2cqw] font-semibold">Insights</span>
        </span>
      </div>
      <div className="relative grid h-[46cqw] grid-cols-2 gap-[2.4cqw] px-[14cqw] pt-[4cqw]">
        {["Starter", "Team"].map((plan, i) => (
          <span
            key={plan}
            className={`flex h-[34cqw] flex-col rounded-[1.8cqw] p-[2.8cqw] ring-1 ${i === 1 ? "bg-gradient-to-b from-violet-500/25 to-transparent ring-violet-400/50" : "bg-white/[0.04] ring-white/10"}`}
          >
            <span className="text-[1.8cqw] text-white/70">{plan}</span>
            <span className="mt-[1cqw] text-[4.4cqw] font-semibold">${[0, 12][i]}</span>
            <span className="mt-[1.6cqw] w-full">
              <Lines count={3} className="h-[1cqw] rounded-full bg-white/15" />
            </span>
            {i === 1 ? (
              <Press
                progress={progress}
                at={CLICK.plan}
                className="mt-auto self-start rounded-full bg-white px-[2.6cqw] py-[1.1cqw] text-[1.6cqw] font-semibold text-[#09090f]"
              >
                Start trial
              </Press>
            ) : (
              <span className="mt-auto self-start rounded-full px-[2.6cqw] py-[1.1cqw] text-[1.6cqw] ring-1 ring-white/20">
                Get started
              </span>
            )}
          </span>
        ))}
      </div>
      <div className="relative flex h-[8cqw] items-center px-[7cqw] text-[1.4cqw] text-white/35">© 2023 Tidely</div>
    </div>
  );
}

// ── 2026: today. Editorial, warm paper, the product itself as the hero ──

function Page2026({ progress }: { progress: MotionValue<number> }) {
  const tint = useTint(useHover(progress));
  return (
    <div className="h-full bg-[#f6f3ee] text-stone-900 dark:bg-[#16140f] dark:text-stone-100">
      <div className="flex h-[8cqw] items-center justify-between border-b border-stone-900/10 px-[5cqw] dark:border-white/10">
        <span className="font-serif text-[2.8cqw] italic">Tidely</span>
        <span className="flex items-center gap-[3cqw] text-[1.6cqw] text-stone-500">
          <span>Product</span>
          <span>Pricing</span>
          <span className="text-stone-900 dark:text-stone-100">Sign in →</span>
        </span>
      </div>
      <div className="grid h-[54cqw] grid-cols-[1.1fr_1fr] gap-[4cqw] px-[5cqw] pt-[7cqw]">
        <span className="flex flex-col">
          <span className="font-mono text-[1.3cqw] tracking-widest text-orange-600 uppercase">Calendar, rethought</span>
          <span className="mt-[1.6cqw] font-serif text-[6.4cqw] leading-[0.98] tracking-tight">
            Time, held together.
          </span>
          <span className="mt-[2.2cqw] w-[80%]">
            <Lines className="h-[1.1cqw] rounded-full bg-stone-900/15 dark:bg-white/15" />
          </span>
          <Press
            progress={progress}
            at={CLICK.cta}
            className="mt-[3cqw] self-start rounded-full bg-stone-900 px-[2.8cqw] py-[1.3cqw] text-[1.7cqw] font-medium text-[#f6f3ee] dark:bg-[#f6f3ee] dark:text-stone-900"
          >
            Try Tidely
          </Press>
        </span>
        <span className="mt-[1cqw] h-[38cqw] rounded-[1.2cqw] bg-white p-[1.6cqw] shadow-[0_2cqw_5cqw_-2cqw_rgb(0_0_0/0.25)] ring-1 ring-stone-900/10 dark:bg-stone-900 dark:ring-white/10">
          <span className="grid h-full grid-cols-5 gap-[0.6cqw]">
            {Array.from({ length: 5 }, (_, day) => (
              <span key={day} className="relative rounded-[0.4cqw] bg-stone-100 dark:bg-white/[0.04]">
                <span
                  className="absolute inset-x-[10%] rounded-[0.4cqw] bg-orange-400/80"
                  style={{ top: `${[12, 40, 22, 60, 30][day]}%`, height: `${[22, 18, 30, 16, 24][day]}%` }}
                />
                <span
                  className="absolute inset-x-[10%] rounded-[0.4cqw] bg-lime-400/80"
                  style={{ top: `${[56, 8, 66, 20, 70][day]}%`, height: `${[14, 20, 12, 22, 14][day]}%` }}
                />
              </span>
            ))}
          </span>
        </span>
      </div>
      <div className="flex h-[12cqw] items-center gap-[5cqw] border-y border-stone-900/10 px-[5cqw] dark:border-white/10">
        <span className="font-mono text-[1.2cqw] text-stone-500 uppercase">Trusted by</span>
        {[8, 11, 9, 10].map((w, i) => (
          <span key={i} className="h-[1.6cqw] rounded-full bg-stone-900/20 dark:bg-white/20" style={{ width: `${w}cqw` }} />
        ))}
      </div>
      <div className="h-[52cqw] px-[5cqw] pt-[5cqw]">
        <span className="font-serif text-[3.6cqw]">What it does</span>
        <span className="mt-[3cqw] grid grid-cols-3 gap-[3cqw]">
          {["Plans the week", "Guards focus", "Speaks every zone"].map((title, i) => (
            <motion.span
              key={title}
              className="flex flex-col gap-[1.2cqw] rounded-[0.8cqw] border-t border-stone-900/20 pt-[1.6cqw] dark:border-white/20"
              style={i === 2 ? { backgroundColor: tint } : undefined}
            >
              <span className="font-mono text-[1.3cqw] text-orange-600">0{i + 1}</span>
              <span className="text-[2.2cqw] font-medium">{title}</span>
              <Lines count={3} className="h-[1cqw] rounded-full bg-stone-900/10 dark:bg-white/10" />
            </motion.span>
          ))}
        </span>
      </div>
      <div className="h-[46cqw] px-[5cqw] pt-[4cqw]">
        <span className="font-serif text-[3.6cqw]">Pricing</span>
        <span className="mt-[3cqw] grid grid-cols-2 border-t border-stone-900/20 dark:border-white/20">
          {["Personal", "Team"].map((plan, i) => (
            <span
              key={plan}
              className={`flex items-center justify-between py-[3cqw] pr-[2cqw] ${i === 1 ? "border-l border-stone-900/20 pl-[3cqw] dark:border-white/20" : ""}`}
            >
              <span className="flex flex-col">
                <span className="text-[2.2cqw] font-medium">{plan}</span>
                <span className="font-serif text-[4cqw]">{["Free", "$10"][i]}</span>
              </span>
              {i === 1 ? (
                <Press
                  progress={progress}
                  at={CLICK.plan}
                  className="rounded-full bg-orange-500 px-[2.4cqw] py-[1.2cqw] text-[1.6cqw] font-medium text-white"
                >
                  Choose
                </Press>
              ) : null}
            </span>
          ))}
        </span>
      </div>
      <div className="flex h-[8cqw] items-center justify-between px-[5cqw] font-mono text-[1.2cqw] text-stone-500">
        <span>Tidely, 2026</span>
        <span>Made with care</span>
      </div>
    </div>
  );
}

function useShadow(hover: MotionValue<number>, color: string) {
  return useTransform(hover, (h) => `0 0 0 ${h * 0.4}cqw ${color}, 0 ${h * 1.6}cqw ${h * 4}cqw -${h}cqw ${color}`);
}

function useTint(hover: MotionValue<number>) {
  return useTransform(hover, (h) => `rgb(249 115 22 / ${h * 0.12})`);
}
```
