# Dropdown Teleport Pattern

## Problem

The `#service-search-results` dropdown lives inside `#services-content`, an accordion section with `overflow: hidden`. Even with `z-index: 99999 !important`, it's clipped by the parent stacking context and hidden behind the Quote Summary section.

## Fix: Teleport to `#dropdown-root`

Every page has a `<div id="dropdown-root"></div>` at the end of `<body>`. When the dropdown opens, move it there and position it with `position: fixed` + `getBoundingClientRect()`.

### In `renderServiceResults()` (both `main.js` and `quote-tab-manager.js`):

```js
// Teleport to dropdown-root to escape stacking context clipping
const dropdownRoot = document.getElementById('dropdown-root');
const serviceSearchInput = document.getElementById('service-search-input');
if (dropdownRoot && serviceSearchResults.parentElement !== dropdownRoot) {
    dropdownRoot.appendChild(serviceSearchResults);
}
// Position relative to the input
if (serviceSearchInput) {
    const rect = serviceSearchInput.getBoundingClientRect();
    serviceSearchResults.style.position = 'fixed';
    serviceSearchResults.style.top = (rect.bottom + 4) + 'px';
    serviceSearchResults.style.left = rect.left + 'px';
    serviceSearchResults.style.width = rect.width + 'px';
}
```

### Scroll/resize repositioning (in `initializeServiceSearch` / `attachMainEventListeners`):

```js
const repositionDropdown = () => {
    if (serviceSearchResults.classList.contains('hidden')) return;
    const rect = serviceSearchInput.getBoundingClientRect();
    serviceSearchResults.style.top = (rect.bottom + 4) + 'px';
    serviceSearchResults.style.left = rect.left + 'px';
    serviceSearchResults.style.width = rect.width + 'px';
};
window.addEventListener('scroll', repositionDropdown, { passive: true });
window.addEventListener('resize', repositionDropdown);
```

## Files Modified

- `main.js` — `renderServiceResults()` + `attachMainEventListeners()`
- `quote-tab-manager.js` — `renderServiceResults()` + `initializeServiceSearch()`
