/**
 * Instant search: one component, two shells.
 *
 * Its own `pasia-search-*` namespace rather than the mockup's `.search-*`
 * one: components.css already carries a ported `.search-overlay` block whose
 * `.search-results` and `.search-empty` rules collide with the markup
 * search.php renders. A second consumer of those names would make the collision
 * load-bearing. The visual language below is that block's, unchanged, panel
 * width and drop, row rhythm, thumbnail size, hover fill.
 *
 * Motion, backdrop and dialog conventions match assets/js/main.js's drawer
 * so the two overlays read as one system. Tokens only: hairlines use the `thin`
 * keyword, fixed dimensions use rem.
 *
 * ONE COMPONENT, TWO SHELLS, NOT TWO COMPONENTS.
 *
 *   .pasia-search        + .pasia-search-panel   the modal, opened from the
 *                                                header control, one per page
 *   .pasia-search-inline + .pasia-search-drop    the inline band, rendered in
 *                                                the page by a template, any
 *                                                number per page
 *
 * Everything between those two shells is the same class in both: the bar, the
 * input, the region, the listbox, the group labels, every row, the empty state
 * and the live region. That is not a coincidence to be tidied away later, it is
 * the shape the mock-up already had, where `.sf-inline` was five rules that
 * reused `.sf-modal`'s internals wholesale (_mockups/css/site.css 208-219).
 *
 * The reason it MUST be one component: assets/js/search-overlay.js builds every
 * result row itself, in code, with class names written into buildOption(). Two
 * components would mean either two renderers or one renderer carrying a
 * per-mode class map, which is a switch in the one place a switch is most
 * expensive. The shells differ because a fixed dialog and an absolutely
 * positioned drop are genuinely different boxes; the rows do not differ at all.
 *
 * The internals were already shell-independent when this file was written for
 * the modal alone, because every rule below is a flat class selector and only
 * four are scoped to `.pasia-search`. Adding the second shell therefore changed
 * one existing declaration (see `outline: none` below) and added a block. It
 * did not touch the modal's rendering.
 *
 * REPORTED, NOT FIXED HERE, because the file is not this component's:
 * assets/css/base.css line 102 lists `.pasia-search :focus-visible` among the
 * surfaces that recolour the focus outline to `--gold-bright`. Every other
 * entry in that list is a dark band. The modal's panel is `--surface`, where
 * `--gold-bright` measures 2.01:1, so the dialog cannot be given its focus ring
 * back until that selector is dropped from the list. The inline shell is not
 * matched by it and is unaffected.
 */

/* --- Shell ---------------------------------------------------------------- */

.pasia-search {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
}

.pasia-search[hidden] {
  display: none;
}

.pasia-search-backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--brand-primary) 35%, transparent);
  backdrop-filter: blur(0.1875rem);
  opacity: 0;
  transition: opacity var(--duration-normal) var(--ease-out);
}

.pasia-search.is-open .pasia-search-backdrop {
  opacity: 1;
}

.pasia-search-panel {
  position: relative;
  width: min(47.5rem, calc(100% - 2 * var(--space-gutter)));
  max-height: min(72vh, 41.25rem);
  margin: clamp(2.5rem, 9vh, 6.875rem) auto 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  opacity: 0;
  transform: translateY(-0.75rem);
  transition:
    opacity var(--duration-normal) var(--ease-out),
    transform var(--duration-normal) var(--ease-out);
}

.pasia-search.is-open .pasia-search-panel {
  opacity: 1;
  transform: none;
}

.pasia-search-panel:focus {
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .pasia-search-panel,
  .pasia-search-backdrop {
    transition: none;
  }
}

/* Background scroll lock while the overlay is open. */
.pasia-search-lock {
  overflow: hidden;
}

/* --- Search bar ----------------------------------------------------------- */

.pasia-search-bar {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  padding: var(--space-s) var(--space-m);
  border-bottom: thin solid var(--hairline);
}

.pasia-search-bar > .icon {
  flex-shrink: 0;
  font-size: 1.625rem;
  color: var(--brand-primary);
}

.pasia-search-input {
  flex: 1;
  /* min-width:0 defeats the flexbox `min-width:auto` trap. Without it an
     <input> refuses to shrink below its intrinsic (size-attribute) width of
     about 238px, which overflows a narrow container at 320px. The mock-up's
     own `.sf-input` carries the same comment and the same fix, and the inline
     shell below is the narrow container that would have found it again. */
  min-width: 0;
  border: none;
  background: none;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--text-h3);
  color: var(--ink);
  appearance: none;
}

/* `outline: none` is scoped to the MODAL shell rather than sitting on the
   shared class. On the inline band the field is the primary control on the
   page, so it keeps the token focus ring from tokens.css (--gold-deep, 5.72:1
   on --surface, measured). Inside the dialog the ring is suppressed as it was
   before; see the note in the header about the base.css rule that has to move
   before it can be restored there too. */
.pasia-search .pasia-search-input {
  outline: none;
}

.pasia-search-input::placeholder {
  color: var(--ink-muted);
  font-weight: 500;
}

.pasia-search-input::-webkit-search-cancel-button {
  appearance: none;
}

.pasia-search-close {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-pill);
  color: var(--ink-muted);
  transition:
    background var(--duration-fast),
    color var(--duration-fast);
}

.pasia-search-close:hover {
  background: var(--surface-alt);
  color: var(--ink);
}

/* --- Region --------------------------------------------------------------- */

.pasia-search-region {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-2xs) var(--space-s) var(--space-s);
  transition: opacity var(--duration-fast);
}

.pasia-search-region.is-busy {
  opacity: 0.55;
}

.pasia-search-meta {
  padding: var(--space-2xs) var(--space-s);
  font-size: var(--text-small);
  color: var(--ink-muted);
}

/* --- Groups and rows ------------------------------------------------------ */

.pasia-search-group + .pasia-search-group {
  margin-top: var(--space-xs);
  padding-top: var(--space-xs);
  border-top: thin solid var(--hairline);
}

.pasia-search-group-label {
  display: block;
  padding: var(--space-3xs) var(--space-s) var(--space-2xs);
  font-size: var(--text-eyebrow);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.pasia-search-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-s);
  padding: var(--space-2xs) var(--space-s);
  border-radius: var(--radius-md);
  transition: background var(--duration-fast);
}

/* The mock-up's `.sf-item` states this too. base.css already leaves anchors
   undecorated, but the inline shell stands INSIDE page content, and a template
   that drops a band into a prose container hands every row the underline that
   container gives its links: `.page-plain-body a` in base.css is exactly that
   rule and it outranks a bare `.pasia-search-item`. A result row is a list
   item, not a sentence, so this is matched on the element it always is. */
a.pasia-search-item {
  text-decoration: none;
}

.pasia-search-item:hover,
.pasia-search-item.is-active {
  background: var(--surface-alt);
  box-shadow: inset 0.1875rem 0 0 var(--brand-primary);
  outline: none;
}

.pasia-search-thumb {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  flex-shrink: 0;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--brand-tint-soft);
  color: var(--brand-primary);
}

.pasia-search-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pasia-search-thumb .icon {
  font-size: 1.375rem;
}

.pasia-search-item-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs);
  min-width: 0;
}

.pasia-search-item-name {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-small);
  line-height: 1.3;
  color: var(--brand-primary);
}

.pasia-search-item-name mark {
  background: var(--brand-tint-soft);
  color: inherit;
  border-radius: var(--radius-sm);
}

.pasia-search-item-meta {
  font-size: var(--text-small);
  color: var(--ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Idle and empty states ------------------------------------------------ */

/* `display: flex` below outranks the user-agent's `[hidden] { display: none }`,
   so the hidden state has to be restated. Without this the suggestion chips
   stay in the tab order underneath a full set of results. */
.pasia-search-idle[hidden],
.pasia-search-empty[hidden],
.pasia-search-foot[hidden] {
  display: none;
}

.pasia-search-idle {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  padding: var(--space-s) var(--space-s) var(--space-xs);
}

.pasia-search-idle-note {
  font-size: var(--text-small);
  color: var(--ink-muted);
  max-width: 46ch;
}

.pasia-search-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
}

.pasia-search-chips button {
  padding: var(--space-3xs) var(--space-xs);
  border-radius: var(--radius-pill);
  background: var(--brand-tint-soft);
  color: var(--brand-primary);
  font-size: var(--text-small);
  font-weight: 600;
  transition:
    background var(--duration-fast),
    color var(--duration-fast);
}

.pasia-search-chips button:hover,
.pasia-search-chips button:focus-visible {
  background: var(--brand-tint);
  color: var(--ink);
}

.pasia-search-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xs);
  text-align: center;
  padding: var(--space-l) var(--space-m);
}

.pasia-search-empty > .icon {
  width: 2.75rem;
  height: 2.75rem;
  /* --brand-tint is a translucent forest WASH, not an ink. On paper it renders
     as a pale tint that reads as a rendering fault rather than an icon. */
  color: var(--sage);
}

.pasia-search-empty-title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-h4);
  color: var(--ink);
}

.pasia-search-empty-note {
  font-size: var(--text-small);
  color: var(--ink-muted);
  max-width: 36ch;
}

/* --- Footer --------------------------------------------------------------- */

.pasia-search-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-s);
  flex-wrap: wrap;
  padding: var(--space-xs) var(--space-m);
  border-top: thin solid var(--hairline);
  background: var(--white);
}

/* The one place terracotta appears in this overlay: the single forward action
   out of it. Everything else stays inside the Deep Ocean / Pebble band. */
.pasia-search-all {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-width: 0;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--text-small);
  color: var(--brand-primary);
  transition: color var(--duration-fast);
}

.pasia-search-all span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pasia-search-all .icon {
  flex-shrink: 0;
  font-size: 1.125rem;
  color: var(--brand-accent);
  transition: transform var(--duration-fast) var(--ease-out);
}

.pasia-search-all:hover,
.pasia-search-all:focus-visible {
  color: var(--brand-accent-hover);
}

.pasia-search-all:hover .icon {
  transform: translateX(var(--space-3xs));
}

@media (prefers-reduced-motion: reduce) {
  .pasia-search-all .icon {
    transition: none;
  }

  .pasia-search-all:hover .icon {
    transform: none;
  }
}

.pasia-search-keys {
  display: flex;
  align-items: center;
  gap: var(--space-3xs);
  font-size: var(--text-eyebrow);
  color: var(--ink-muted);
}

.pasia-search-keys kbd {
  padding: var(--space-3xs) var(--space-2xs);
  border: thin solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-family: var(--font-body);
  font-size: var(--text-eyebrow);
  line-height: 1;
}

/* --- Small screens -------------------------------------------------------- */

@media (max-width: 767px) {
  .pasia-search-panel {
    max-height: min(84vh, 41.25rem);
    margin-top: var(--space-s);
  }

  .pasia-search-bar {
    padding: var(--space-xs) var(--space-s);
    gap: var(--space-2xs);
  }

  .pasia-search-foot {
    padding: var(--space-xs) var(--space-s);
  }

  /* Not a keyboard, and the row would wrap into a second line of chrome. */
  .pasia-search-keys {
    display: none;
  }

  .pasia-search-item {
    gap: var(--space-2xs);
    padding-inline: var(--space-2xs);
  }

  .pasia-search-thumb {
    width: 2.75rem;
    height: 2.75rem;
  }
}

/* ==========================================================================
   THE INLINE BAND, the second shell
   ==========================================================================

   Rendered in the page by pasia_the_search_band() in inc/search-overlay.php.
   Three templates use it: archive-helper.php (the search hero),
   search.php and 404.php.

   The whole band is a real <form method="get"> around a real
   <input type="search" name="s"> and a real submit button, so with JavaScript
   off it submits and routes exactly like any other form on the site. The drop
   below it is the enhancement, and it is invisible until the script adds
   `.is-open`, which is why nothing here needs a `@media (scripting: none)`
   fallback: closed IS the rendered state.

   The band pins its own ground on both sides, `--surface` on the bar and
   `--surface` on the drop, so every contrast figure measured for it holds
   whatever band a template drops it onto. The mock-up puts it half over a
   forest hero on find-a-helper.html, so this matters here rather than in
   theory. Measured, composited, on that pinned ground:

     input text        --ink on --surface                        16.28:1
     placeholder       --ink-muted on --surface                   8.18:1
     group label, meta --ink-muted on --surface                   8.18:1
     row meta          --ink-muted on --surface-alt (hover)       7.45:1
     row title         --brand-primary on --surface              11.61:1
     row title         --brand-primary on --surface-alt (hover)  10.57:1
     <mark>            --brand-primary on tint-soft over surface  9.72:1
     <mark>            --brand-primary on tint-soft over alt      8.88:1
     submit label      --deep-forest on --gold (.btn-gold)        5.65:1
     focus ring        --gold-deep on --surface                   5.72:1
     magnifier         --brand-primary on --surface (non-text)   11.61:1
     empty-state mark  --sage on --surface (non-text)             3.34:1

   The resting hairline (--input-border on --surface, 1.32:1) and the
   :focus-within gold border (--input-border-focus, 2.56:1) are decoration, not
   the focus indicator. The indicator is the token :focus-visible ring at
   5.72:1, which is why `outline: none` was scoped off this input above. Those
   two figures are properties of the theme's shared --input-border pair and
   every form field on the site carries them; they are recorded here rather
   than worked around locally.
   ========================================================================== */

.pasia-search-inline {
  position: relative;
  display: block;
}

/* --- The bar -------------------------------------------------------------- */

/* The modal's bar is the top edge of a panel and carries one hairline
   underneath. Standing on its own it is a field, so it takes the theme's input
   tokens: the same border, the same focus border and the same ring every other
   form control on the site uses. */
.pasia-search-inline .pasia-search-bar {
  gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-2xs) var(--space-2xs) var(--space-m);
  border: thin solid var(--input-border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition:
    border-color var(--duration-fast),
    box-shadow var(--duration-fast);
}

.pasia-search-inline .pasia-search-bar:focus-within {
  border-color: var(--input-border-focus);
  box-shadow: var(--input-ring);
}

@media (prefers-reduced-motion: reduce) {
  .pasia-search-inline .pasia-search-bar {
    transition: none;
  }
}

/* 1.625rem is the dialog's, where the input is --text-h3. Here it sits beside
   --text-lead and would out-shout it. */
.pasia-search-inline .pasia-search-bar > .icon {
  font-size: 1.3125rem;
}

.pasia-search-inline .pasia-search-input {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--text-lead);
}

/* .btn lifts 2px on hover. Inside a bordered pill that reads as the button
   escaping the field rather than as a button responding. */
.pasia-search-submit {
  flex-shrink: 0;
}

.pasia-search-submit:hover {
  transform: none;
}

/* --- The drop ------------------------------------------------------------- */

/* --z-raised, not --z-sticky. The drop scrolls with the page, so it should
   pass UNDER the sticky header rather than over it, and it only has to clear
   the content that follows it in the same section. It is also the tier the
   mock-up itself put the band's wrapper on: `.srp-searchband` is
   `position: relative; z-index: var(--z-raised)`.

   FOR THE TEMPLATE THAT WRAPS THIS, and it is the one thing that can break the
   drop from outside: the drop is absolutely positioned, so ANY ancestor with
   `overflow: hidden` clips it. `.pg-hero` has `overflow: hidden` because of its
   ridge SVG. Both mock-up pages that float the band over the hero therefore put
   it in the NEXT section and pull it up with a negative margin, rather than
   nesting it inside the hero. `_mockups/search-results.html` says so in as many
   words above `.srp-searchband`. Keep that arrangement. */
.pasia-search-drop {
  position: absolute;
  inset-inline: 0;
  top: calc(100% + var(--space-2xs));
  z-index: var(--z-raised);
  display: flex;
  flex-direction: column;
  max-height: min(60vh, 26rem);
  background: var(--surface);
  border: thin solid var(--hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-0.375rem);
  transition:
    opacity var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out),
    visibility var(--duration-fast);
}

.pasia-search-inline.is-open .pasia-search-drop {
  opacity: 1;
  visibility: visible;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .pasia-search-drop {
    transition: none;
  }
}

/* No `overflow: hidden` on the drop, deliberately. The rounded corners are
   kept clear by the region's own padding instead, because a clipping box
   around a focusable child is how a focus indicator gets erased. Nothing
   inside the drop is focusable today either: rows are `tabindex="-1"` listbox
   options driven by aria-activedescendant, and unlike the dialog this shell
   carries no chips and no footer link. Both guards, so that adding a link in
   here later does not silently cost the ring. */
.pasia-search-drop .pasia-search-region {
  padding-block: var(--space-2xs);
}

/* The dialog's empty state is a full panel's worth of air. In a drop that is
   most of the available height. */
.pasia-search-drop .pasia-search-empty {
  padding: var(--space-m) var(--space-s);
}

.pasia-search-drop .pasia-search-empty > .icon {
  width: 2rem;
  height: 2rem;
}

/* --- Small screens -------------------------------------------------------- */

@media (max-width: 767px) {
  .pasia-search-inline .pasia-search-bar {
    padding-left: var(--space-s);
  }

  .pasia-search-drop {
    max-height: min(60vh, 21rem);
  }
}

/* At this width the field and a nowrap button cannot share a line and leave
   the field usable, so the button takes its own row. The pill loses its
   radius when it does: a two-line pill reads as a rendering fault. */
@media (max-width: 560px) {
  .pasia-search-inline .pasia-search-bar {
    flex-wrap: wrap;
    padding: var(--space-2xs);
    border-radius: var(--radius-md);
  }

  .pasia-search-submit {
    flex: 1 0 100%;
    justify-content: center;
  }
}
