# Typeahead (autocomplete)

## REST endpoint

```
GET /wp-json/seekmodo/v1/typeahead?q=<query>&vertical=<content|commerce>&max=<n>
```

| Param | Default | Notes |
|---|---|---|
| `q` | _required_ | The query string. ≤ 64 chars enforced server-side. |
| `vertical` | `content`, or `commerce` if Woo is the active context | One of `content|commerce`. |
| `max` | 8 | 1-20. |

Response (content):

```json
{
  "rows": [
    {"id": 4321, "title": "...", "permalink": "https://...", "thumbnail_url": "https://..."}
  ],
  "fallback": false,
  "latency_ms": 84
}
```

Response (commerce):

```json
{
  "rows": [
    {"id": 9821, "title": "Spruce Hoodie", "permalink": "...", "image_url": "...",
     "price": 79.95, "sale_price": null, "on_sale": false, "stock_status": "instock"}
  ],
  "fallback": false,
  "latency_ms": 91
}
```

`fallback: true` means the gateway was unreachable / mode was off /
breaker open / domain locked, and the rows came from a native WP_Query
(`s=` LIKE search). The shape stays identical so theme JS doesn't
need to branch.

## Shortcode

```
[seekmodo_search vertical="content" placeholder="Search trek.ca…"]
```

Renders an `<input type="search">` plus a `<div class="seekmodo-typeahead">`
dropdown, wired to the REST endpoint with debounce 120ms.

## Gutenberg block

`Add Block → Seekmodo Search` for the block editor. Same surface as
the shortcode; supports theme.json color tokens.

## Click attribution

The dropdown rows include `data-seekmodo-pos`, `data-seekmodo-id`, and
`data-seekmodo-surface="typeahead"`. The bundled `seekmodo-beacon.js`
intercepts clicks on those rows and posts to
`/wp-json/seekmodo/v1/click` before navigating. The beacon uses
`navigator.sendBeacon` where supported (zero added latency).

See [`CLICK_ATTRIBUTION.md`](CLICK_ATTRIBUTION.md) for the full event
model.

## Theming gotcha: `a:visited` on the dropdown rows

The connector deliberately ships no CSS for the dropdown — the host
theme owns the popover styling end-to-end. That means when a theme
styles its row anchors with a *single-class* selector like

```css
.my-typeahead__result a { color: var(--black); }
```

it has specificity `(0,1,1)` — exactly the same as a global
`a:visited { color: #fff }` rule that many older themes ship (a
holdover from styling nav links on a dark hero). The browser then
falls back to **source order** to break the tie, and whichever
stylesheet loads later wins. Because the theme's main `style.css` is
almost always enqueued *after* per-feature CSS like `header.css`,
the global `a:visited` wins and any row whose URL is already in the
visitor's history renders as white text on the white popover
background.

The bug is sneaky because it usually only hits the **first** row —
that's the most relevant / most-clicked result, and therefore the
one most likely to be in the user's history. Other rows look fine,
so the popover gets reported as "the first result is invisible
unless I hover it." Hovering "fixes" it because `:hover` /
`:focus` selectors typically have higher specificity.

**Fix (theme side):** make the row anchor selector beat
`a:visited` (0,1,1) by either chaining the link-state pseudo or
prefixing with a second class. Either of these works:

```css
/* Option A — chain :link / :visited so the selector is (0,2,1) */
.my-typeahead__result a,
.my-typeahead__result a:link,
.my-typeahead__result a:visited {
    color: var(--black);
}

/* Option B — wrap inside an opt-in container class for extra reach */
.my-search-popover .my-typeahead__result a { color: var(--black); }
```

The same gotcha applies to the row *hover* / *focus* states — if the
theme's global `a:visited` paints them white, a `:visited:hover`
permutation may be needed too:

```css
.my-typeahead__result a:hover,
.my-typeahead__result a:focus,
.my-typeahead__result a:visited:hover,
.my-typeahead__result a:visited:focus {
    color: var(--accent);
}
```

The reference implementation in `trek.ca`'s `trek-marketing` theme
(`wp-content/themes/trek-marketing/assets/css/header.css`, search
for `.trek-search-nav__result a:visited`) uses Option A. Copy the
pattern into your theme's typeahead stylesheet and you're done.
