<!-- source-hash: 6e8a04ae19bb53e1b3779c86e3a511c1 -->
Scrollable list component that renders a collection of `ChatTicketItem` cards with dynamic edge-fade masking based on scroll position.

## Key Components

- **`ChatTicketList`** — `forwardRef` component that wraps a scrollable ticket list with fade-in/out gradient masks at the top and bottom edges to indicate overflow content
- **`getMask(top, bottom)`** — Pure utility that computes a CSS `linear-gradient` mask string based on whether the scroll container has hidden content above or below
- **`updateFade`** — Scroll handler that compares `scrollTop`, `scrollHeight`, and `clientHeight` to toggle `fadeTop`/`fadeBottom` state, also triggered via `useLayoutEffect` when the ticket count changes

## Props

| Prop | Type | Description |
|------|------|-------------|
| `tickets` | `ChatTicketItemData[]` | Array of ticket data to render |
| `onTicketClick` | `(ticketId: string) => void` | Optional click handler passed to each item |
| `className` | `string` | Additional CSS classes |

## Usage Example

```typescript
import { ChatTicketList } from './chat-ticket-list'

const tickets = [
  { id: 'TKT-001', title: 'VPN not connecting', status: 'open' },
  { id: 'TKT-002', title: 'Printer offline', status: 'pending' },
]

function ChatSidebar() {
  return (
    <ChatTicketList
      tickets={tickets}
      onTicketClick={(id) => console.log('Selected ticket:', id)}
      className="max-h-96"
    />
  )
}
```

> Returns `null` when `tickets` is empty. Border radius and top/bottom borders are conditionally removed at scroll edges to visually blend with the fade mask.