## Why All images on the site use `loading="lazy"` but render as blank space until the browser finishes downloading them. On slower connections or pages with many cards (homepage has 20+ cards), the user sees empty grey rectangles that pop into view abruptly. Adding a shimmer/skeleton placeholder while images load gives the perception of a faster, more polished page — the same pattern used by LinkedIn, YouTube, and AMP pages. ## What Changes - **Shimmer placeholder for card thumbnails.** The `.card-media` area displays an animated skeleton shimmer while the `` is loading. Once the image loads, it fades in over the shimmer. If the image fails to load, the placeholder remains visible (graceful degradation). - **Shimmer placeholder for blog featured images.** Blog post and page detail pages show the same shimmer treatment on the hero/featured image while it loads. - **Reduced-motion support.** The shimmer animation is suppressed when `prefers-reduced-motion: reduce` is active — the placeholder shows as a static block instead of animating. ## Capabilities ### New Capabilities - `image-lazy-loading`: Shimmer/skeleton placeholder system for images that displays an animated loading state while images download, fades in the image on load, and handles load failures gracefully. ### Modified Capabilities - `card-layout-system`: Card image area gains shimmer placeholder behavior during image loading (visual enhancement, no layout changes). ## Impact - **Components**: `StandardCard.astro` — the `` element needs a wrapper or sibling element for the shimmer, plus a script to detect load/error events. - **Pages**: `blog/post/[slug].astro`, `blog/page/[slug].astro` — featured images get the same shimmer treatment. - **CSS**: `global.css` — new shimmer animation keyframes and placeholder styles. - **JS**: Small inline script to listen for image `load`/`error` events and toggle visibility classes. - **No backend changes.** No data model, ingestion, or caching changes. - **No new dependencies.** Pure CSS animation + vanilla JS event listeners. - **Accessibility**: Shimmer respects `prefers-reduced-motion` (existing global rule covers animation suppression). No content or semantic changes.