/* ============================================
   Search modal — global site search overlay.

   Architecture:
     - .gs-search          fixed full-viewport overlay container
     - .gs-search__backdrop  blurred dark wash behind the panel
     - .gs-search__panel   centered white card (max 600px wide)
       - __head            input row (lens + input + Esc close)
       - __body            scrollable results area + intro/empty
       - __footer          keyboard hint chips
   ============================================ */

/* ─── Overlay container ────────────────────────────────────── */

.gs-search {
  position: fixed;
  inset: 0;
  z-index: 100;          /* above sticky header (z: 50) + dropdowns (z: 60) */
  display: grid;
  /* Anchor the panel near the top of the viewport — feels more
     command-palette than centered-dialog, and leaves the lower
     half visible so users still see context behind. */
  place-items: start center;
  padding: 8vh 1rem 1rem;
}

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

/* Body scroll lock — applied by JS while modal is open. */
body.gs-search-open {
  overflow: hidden;
}

/* ─── Backdrop ─────────────────────────────────────────────── */

.gs-search__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(2, 19, 36, 0.55);
  /* backdrop-filter is progressive — falls back to a flat dim
     overlay where unsupported. Combined with the dim rgba above,
     never reads as a single flat layer. */
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* ─── Panel — the actual modal card ───────────────────────── */

.gs-search__panel {
  position: relative;
  width: 100%;
  max-width: 600px;
  /* Cap the panel height so the scrollable body never exceeds
     ~80vh — leaves room for backdrop + keeps the footer visible
     without scrolling. */
  max-height: min(80vh, 700px);
  background: var(--color-bg);
  border-radius: 16px;
  box-shadow: 0 24px 64px rgba(2, 19, 36, 0.25),
              0 0 0 1px var(--color-border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ─── Head — input row ────────────────────────────────────── */

.gs-search__head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0 0.5rem 0 1rem;
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}

.gs-search__lens {
  width: 20px;
  height: 20px;
  color: var(--color-fg-muted);
  flex-shrink: 0;
}

.gs-search__input {
  flex: 1;
  background: transparent;
  border: 0;
  padding: 1.1rem 0;
  font: inherit;
  font-size: 1rem;
  color: var(--color-fg);
  outline: none;
}

.gs-search__input::placeholder {
  color: var(--color-fg-muted);
}

/* Strip the WebKit "X" cancel button from <input type="search">
   since we render our own Esc affordance to the right. */
.gs-search__input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.gs-search__close {
  background: transparent;
  border: 0;
  padding: 0.4rem 0.5rem;
  cursor: pointer;
  color: var(--color-fg-muted);
  font: inherit;
  display: inline-flex;
  align-items: center;
  border-radius: 6px;
  transition: background 0.15s ease, color 0.15s ease;
}

.gs-search__close:hover {
  background: var(--color-bg-muted);
  color: var(--color-fg);
}

/* X close icon — shown at every breakpoint (universal close
   affordance). Sized to fit comfortably inside the 0.4rem×0.5rem
   padded close button. */
.gs-search__close-icon {
  width: 16px;
  height: 16px;
  display: block;
}

/* ─── Body — scrollable results / intro / empty states ──── */

.gs-search__body {
  flex: 1;
  overflow-y: auto;
  min-height: 80px;
}

/* Intro + empty states — vertically generous, centered, muted.
   Same shell rendered for two states (intro on empty input,
   empty on input with no matches). */
.gs-search__intro,
.gs-search__empty {
  padding: 2.5rem 1.25rem;
  text-align: center;
  color: var(--color-fg-muted);
  font-size: 0.95rem;
}

.gs-search__intro p,
.gs-search__empty p {
  margin: 0 0 0.5rem;
}

.gs-search__intro p:last-child,
.gs-search__empty p:last-child {
  margin-bottom: 0;
}

.gs-search__intro-hint,
.gs-search__empty-hint {
  font-size: 0.85rem;
  opacity: 0.85;
}

.gs-search__empty span[data-search-query] {
  font-weight: var(--weight-semibold);
  color: var(--color-fg);
}

/* ─── Result groups ────────────────────────────────────────── */

.gs-search__group {
  padding: 0.5rem 0;
}

.gs-search__group + .gs-search__group {
  border-top: 1px solid var(--color-border);
}

.gs-search__group-title {
  font-size: 0.7rem;
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-fg-muted);
  padding: 0.75rem 1.25rem 0.4rem;
  margin: 0;
}

/* ─── Result row ───────────────────────────────────────────── */

.gs-search__result {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.75rem 1rem;
  margin: 0 0.5rem;
  border-radius: 10px;
  text-decoration: none;
  color: var(--color-fg);
  transition: background 0.12s ease;
}

/* Hover + keyboard-selected share the same highlight so mouse and
   arrow-key flows feel identical. JS sets aria-selected="true" on
   the current keyboard-focused row. */
.gs-search__result:hover,
.gs-search__result[aria-selected="true"] {
  background: var(--color-bg-muted);
}

.gs-search__result-title {
  font-weight: var(--weight-medium);
  flex: 1;
  /* Truncate over-long titles instead of breaking the row layout. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gs-search__result-type {
  font-size: 0.7rem;
  font-weight: var(--weight-medium);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  background: rgba(0, 0, 0, 0.04);
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  flex-shrink: 0;
}

/* Selected row's type chip flips to a slightly stronger bg so the
   pill stays legible on top of the row's hover bg. */
.gs-search__result:hover .gs-search__result-type,
.gs-search__result[aria-selected="true"] .gs-search__result-type {
  background: rgba(0, 0, 0, 0.07);
}

/* ─── Footer — keyboard hint chips ─────────────────────────── */

.gs-search__footer {
  display: flex;
  gap: 1.25rem;
  padding: 0.65rem 1rem;
  border-top: 1px solid var(--color-border);
  font-size: 0.75rem;
  color: var(--color-fg-muted);
  flex-shrink: 0;
  background: var(--color-bg-muted);
}

.gs-search__hint {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

/* All <kbd> chips inside the modal share one look — tiny outlined
   pills. Reused for the Esc close button, the footer hints, and
   the ⌘K tip in the intro state. */
.gs-search kbd {
  font-family: inherit;
  font-size: 0.7rem;
  font-weight: var(--weight-medium);
  padding: 0.1rem 0.4rem;
  min-width: 1.1rem;
  text-align: center;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-bg);
  color: var(--color-fg);
  line-height: 1.2;
  display: inline-block;
}

/* ─── Mobile — full-bleed style for narrow viewports ──────── */

/* Keyboard-irrelevant chrome hides at the hamburger breakpoint
   (≤1024px). On tablet + phone widths there's no Esc key or ⌘K
   combo to refer to, so the kbd "Esc" hint next to the X, the
   footer keyboard hints, and the "Tip: ⌘K" intro hint all
   disappear. The X close icon stays visible at every breakpoint. */
@media (max-width: 1024px) {
  .gs-search__footer {
    display: none;
  }
  /* Combined class + element selector to beat the base
     `.gs-search kbd { display: inline-block }` rule on specificity
     (0,0,1,1 vs. just `.gs-search__close-key` at 0,0,1,0). Without
     the kbd qualifier the hide-on-mobile rule loses the cascade. */
  kbd.gs-search__close-key {
    display: none;
  }
  .gs-search__intro-hint {
    display: none;
  }
}

/* Phone — full-bleed modal (chrome-less, fills viewport). Tablet
   keeps the rounded centered card from the desktop default. */
@media (max-width: 600px) {
  .gs-search {
    padding: 0;
    place-items: stretch;
  }
  .gs-search__panel {
    max-width: none;
    max-height: none;
    height: 100%;
    border-radius: 0;
    box-shadow: none;
  }
}
