diff --git a/src/components/drill/DrillableCell.test.tsx b/src/components/drill/DrillableCell.test.tsx
new file mode 100644
index 0000000..42f7960
--- /dev/null
+++ b/src/components/drill/DrillableCell.test.tsx
@@ -0,0 +1,37 @@
+// @vitest-environment happy-dom
+(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
+
+import { afterEach, describe, it, expect, vi } from "vitest";
+import { cleanup, render, screen, fireEvent } from "@testing-library/react";
+import { DrillableCell } from "@/components/drill/DrillableCell";
+
+// happy-dom keeps `document.body` between tests; without cleanup,
+// `screen.getByRole("button")` finds buttons from earlier renders.
+afterEach(() => cleanup());
+
+describe("DrillableCell", () => {
+ it("renders children, applies hover affordance classes, calls onClick", () => {
+ const onClick = vi.fn();
+ render(
+
+ CLM-114
+ ,
+ );
+ const btn = screen.getByRole("button") as HTMLButtonElement;
+ expect(btn.classList.contains("drillable")).toBe(true);
+ fireEvent.click(btn);
+ expect(onClick).toHaveBeenCalledOnce();
+ });
+
+ it("disabled state hides affordance and blocks click", () => {
+ const onClick = vi.fn();
+ render(
+
+ unavailable
+ ,
+ );
+ const btn = screen.getByRole("button") as HTMLButtonElement;
+ expect(btn.disabled).toBe(true);
+ expect(btn.classList.contains("drillable")).toBe(false);
+ });
+});
diff --git a/src/components/drill/DrillableCell.tsx b/src/components/drill/DrillableCell.tsx
new file mode 100644
index 0000000..f620c05
--- /dev/null
+++ b/src/components/drill/DrillableCell.tsx
@@ -0,0 +1,39 @@
+import type { ReactNode } from "react";
+import { cn } from "@/lib/utils";
+
+interface Props {
+ children: ReactNode;
+ onClick: () => void;
+ disabled?: boolean;
+ /** Optional aria-label; defaults to the visible text content. */
+ ariaLabel?: string;
+}
+
+/**
+ * Wrap any clickable cell with hover-reveal affordance:
+ * cursor: pointer + accent background tint + trailing "›" chevron,
+ * applied via the `drillable` class on hover (see `src/index.css`
+ * in Task 1.4).
+ *
+ * Renders as a