<!-- source-hash: cbe120bea34edef14f05fff077b0b285 -->
A client-side React component that renders a dismissible announcement banner, fetching active announcements from a configured API endpoint with localStorage-based caching and per-announcement dismissal persistence.

## Key Components

| Export/Function | Description |
|----------------|-------------|
| `AnnouncementBar` | Main component — renders the announcement banner or `null` if hidden/dismissed |
| `fetchActiveAnnouncement` | Fetches the active announcement from `announcementsUrl`, updates state and localStorage cache |
| `handleDismiss` | Marks the current announcement as dismissed in localStorage and hides the bar |
| `handleCtaClick` | Navigates to the CTA URL, respecting `_blank` target for new-tab behavior |
| `renderIcon` | Renders either a PNG `<Image>` or an SVG icon based on `announcement.icon_type` |
| `getSvgIcon` | Thin wrapper around `renderSvgIcon` applying size-appropriate Tailwind classes |

## Behavior Notes

- **Instant paint**: On mount, the cached announcement from localStorage is applied synchronously before the API response arrives.
- **Polling**: Refreshes every 5 minutes via `setInterval`; interval restarts if `announcementsUrl` changes.
- **No provider fallback**: When `useEndpointsRuntime` returns no URL, polling is skipped entirely — cached data still renders.
- **Platform-scoped keys**: localStorage keys are prefixed with the platform type (via `getAppType()`) to prevent key collisions across apps.
- **Responsive CTA**: The CTA button is desktop-only; on mobile, tapping the content area triggers `handleCtaClick` directly.

## Usage Example

```typescript
// Wrap your app with the endpoints provider, then drop in the bar:
import { AnnouncementBar } from './announcement-bar';
import { EndpointsRuntimeProvider } from '../contexts/endpoints-runtime-context';

function AppShell() {
  return (
    <EndpointsRuntimeProvider announcementsUrl="/api/announcements/active">
      <AnnouncementBar />
      <main>{/* app content */}</main>
    </EndpointsRuntimeProvider>
  );
}
```

> **Note:** The component renders nothing (`null`) when no active announcement exists, when the fetch URL is unconfigured, or when the user has previously dismissed the current announcement.