# Gasser GSAP Route Transition + Hero Asset Cleanup

Session-derived pattern for Astro local-business sites using a homepage logo intro plus client-side route transitions.

## Problem observed

- The direct homepage logo intro worked, but the internal page-transition animation was missing/intermittent.
- The transition overlay was appended to `document.body`; Astro ClientRouter swaps can replace the body during navigation, so the overlay can disappear exactly when it should be visible.
- Older hero drawing layers (`bleistiftzeichnung.png`, `bleistiftzeichnung_weiss.png`, `bleistiftzeichnung_bw.png`) were still reachable/loaded through hero markup, metadata, or built output, causing stale visual flashes after returning to the homepage.

## Durable fix pattern

1. **Keep direct homepage intro and route transition separate**
   - Direct `/` first-view intro: large, full-screen brand moment, gated by `sessionStorage.gasserIntroSeen` and root classes.
   - Internal navigation: shorter/dezenter route transition, even when target is `/`.
   - Never replay the large homepage intro on internal navigation unless explicitly requested.

2. **Append route-transition overlay to `document.documentElement`, not `body`**
   - `document.documentElement.appendChild(overlay)` survives Astro body swaps better than `document.body.appendChild(overlay)`.
   - Ensure styles are injected before each run.

3. **Start route transition on captured internal-link click**
   - Determine whether the link is same-origin, non-download, non-mail/tel, and a real navigation.
   - Start the transition immediately in the captured click handler.
   - Do not rely only on `astro:before-preparation`; that hook may be too late or can coincide with DOM swaps.

4. **Suppress homepage intro during swaps**
   - On internal navigation, remove `has-pending-gasser-intro`, add `has-seen-gasser-intro`, and kill any homepage intro timeline.
   - After `astro:after-swap`, keep homepage intro suppressed and let only the route transition complete.

5. **Clean old hero assets completely**
   - Remove unused image tags and CSS keyframes, not only opacity settings.
   - Search both `src/` and `dist/` after build for stale paths/keyframes.
   - If an old image is no longer desired, delete it from `public/` so stale references fail during QA instead of silently loading.

## Verification checklist

- Build passes: `npm run build`.
- Search source and built output for stale names, e.g.:
  - `bleistiftzeichnung_weiss`
  - `bleistiftzeichnung_bw`
  - `/images/hero/bleistiftzeichnung.png`
  - old custom session keys such as `gasserHeroIntroSeen`
  - old transition class prefixes such as `page-transition__`
  - old extreme scales such as `scale(74)`, `scale(54)`, `scale(32)`
- In browser QA, click through all main routes:
  - `/leistungen/`
  - `/referenzen/`
  - `/ueber-uns/`
  - `/aktuelles/`
  - `/kontakt/`
  - `/projekt-anfrage/`
  - `/`
  - `/faq/`
- For each internal navigation, verify the route overlay becomes `.is-running` at least briefly and is appended under `document.documentElement`.
- On return to `/`, verify `.site-intro` remains `display: none` while the route transition runs.
- On homepage after transition, inspect actual DOM/resource entries for hero images; only intended current assets should load.

## Key implementation hints

```ts
function ensureRouteOverlay(): HTMLDivElement {
  const existing = document.querySelector<HTMLDivElement>('.gasser-route-intro');
  if (existing) return existing;

  const element = document.createElement('div');
  element.className = 'gasser-route-intro';
  element.setAttribute('aria-hidden', 'true');
  element.innerHTML = `...`;
  document.documentElement.appendChild(element);
  return element;
}
```

```ts
document.addEventListener('click', (event) => {
  const link = (event.target as HTMLElement | null)?.closest?.('a[href]') as HTMLAnchorElement | null;
  if (!link || !isNavigableInternalLink(link)) return;
  suppressHomepageIntro();
  runRouteLogoTransition();
}, { capture: true });
```

Keep transforms scoped to the logo/transition overlay. Do not transform `.hero`, hero background layers, or page shell; otherwise the hero can appear to change zoom level after navigation.
