/* Command palette (Ctrl-K)
   ────────────────────────────────────────────────────────────────────────
   Modelled on fzf, not on Spotlight. The difference is the point: the search
   field is a shell prompt with a real cursor, the active row is marked with a
   `>` pointer rather than a filled bar, matched characters are highlighted the
   way a fuzzy finder highlights them, and the footer carries the key legend
   and an n/total counter. On a page that is already a terminal transcript, a
   rounded translucent search sheet would be the one element that came from a
   different website.

   Everything here is driven by the palette variables in base.css, so light
   mode (:root.light-theme) needs no rules of its own. */

/* The page behind a modal must not scroll. palette.js compensates for the
   width of the scrollbar this removes, so nothing shifts sideways. */
html.palette-open { overflow: hidden; }

/* Backdrop ──────────────────────────────────────────────────────
   Dim, not blur. A backdrop-filter over the scanline overlay produces a
   smeared moiré on the ASCII art, and the effect costs a compositor layer for
   something nobody looks at. */
.palette-backdrop {
  position: fixed;
  inset: 0;
  /* Above the tab bar (9998) and the scanline overlay (9999): the palette is
     modal, so nothing may sit on top of it. */
  z-index: 10000;
  background: color-mix(in srgb, var(--crust) 90%, transparent);
  display: flex;
  justify-content: center;
  /* Anchored near the top rather than centred: results grow downward, and a
     vertically centred list jumps as it changes length. */
  padding: clamp(56px, 12vh, 140px) 16px 24px;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.16s ease, visibility 0s linear 0.16s;
}

.palette-backdrop.open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.16s ease, visibility 0s;
}

/* Panel ─────────────────────────────────────────────────────── */

.palette {
  width: 100%;
  max-width: 640px;
  /* dvh, not vh: focusing the input raises the on-screen keyboard, which does
     not change vh at all. At 70vh on a 568px phone the panel stayed 398px tall
     while the visible area shrank to ~280px, putting the last rows and the
     whole footer behind the keyboard. dvh tracks the visual viewport. */
  max-height: min(60vh, 520px);
  max-height: min(60dvh, 520px);
  display: flex;
  flex-direction: column;
  background: var(--mantle);
  border: 1px solid var(--surface1);
  border-radius: 6px;
  /* The one place on the site with a real shadow. It has to read as floating
     above the page, and on a dark base a border alone does not do that. */
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  overflow: hidden;
  transform: translateY(-8px);
  transition: transform 0.16s cubic-bezier(0.16, 1, 0.3, 1);
}

.palette-backdrop.open .palette { transform: translateY(0); }

/* Prompt row ────────────────────────────────────────────────
   The input has no border, no background and no placeholder icon: it is the
   text after the `$`, and the caret belongs to the field itself. */

.palette-prompt {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 12px 14px;
  border-bottom: 1px solid var(--surface0);
  background: var(--crust);
  font-size: 0.85rem;
}

.palette-prompt .user   { color: var(--pink); }
.palette-prompt .at     { color: var(--subtext0); }
.palette-prompt .host   { color: var(--blue); }
.palette-prompt .colon  { color: var(--subtext0); }
.palette-prompt .path   { color: var(--mauve); }
.palette-prompt .dollar { color: var(--text); padding: 0 6px 0 2px; }

.palette-input {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  outline: none;
  padding: 0;
  color: var(--text);
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.85rem;
  caret-color: var(--pink);
}

.palette-input::placeholder {
  color: var(--overlay0);
  opacity: 1;
}

/* Results ───────────────────────────────────────────────────── */

.palette-list {
  list-style: none;
  margin: 0;
  padding: 6px 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  flex: 1;
  scrollbar-width: thin;
  scrollbar-color: var(--surface1) transparent;
}

.palette-list::-webkit-scrollbar { width: 8px; }
.palette-list::-webkit-scrollbar-thumb {
  background: var(--surface1);
  border-radius: 4px;
}

.palette-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px 7px 8px;
  /* Touch target. 7px padding gave a 33px row; these are the palette's only
     hit areas and they are stacked with no separation. */
  min-height: 44px;
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--subtext0);
  /* No transition: at 60 rows a colour fade on every arrow keypress reads as
     lag on the keyboard, which is the opposite of what a palette is for. */
}

/* The fzf pointer. A reserved column, so labels do not shift by 10px as the
   selection moves down the list. */
.palette-item::before {
  content: '>';
  width: 10px;
  flex-shrink: 0;
  color: var(--pink);
  opacity: 0;
  font-weight: 700;
}

.palette-item[aria-selected="true"] {
  background: var(--surface0);
  color: var(--text);
}

.palette-item[aria-selected="true"]::before { opacity: 1; }

/* Pointer-driven selection is handled in JS (mousemove sets the same
   aria-selected the keyboard does), so there is deliberately no :hover rule
   here -- two competing highlights is the bug it would create. */

.palette-item .icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--overlay1);
}

.palette-item[aria-selected="true"] .icon { color: var(--teal); }

.palette-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The characters the query actually matched, in the same peach the prompts
   use for arguments. Not bold: at 0.82rem in a monospace face, a weight jump
   shifts the glyph baseline enough to look like a rendering fault. */
.palette-match { color: var(--peach); }

/* Where the result lives. Right-aligned and dim: it is a disambiguator you
   read only when two labels look alike. */
.palette-kind {
  flex-shrink: 0;
  font-size: 0.7rem;
  color: var(--overlay0);
  letter-spacing: 0.04em;
}

.palette-item[aria-selected="true"] .palette-kind { color: var(--overlay1); }

.palette-empty {
  padding: 20px 14px;
  color: var(--overlay1);
  font-size: 0.82rem;
  font-style: italic;
}

/* Footer ────────────────────────────────────────────────────── */

.palette-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 14px;
  border-top: 1px solid var(--surface0);
  background: var(--crust);
  font-size: 0.7rem;
  color: var(--overlay0);
}

.palette-hint {
  display: flex;
  align-items: center;
  gap: 5px;
}

.palette-key {
  color: var(--subtext0);
  background: var(--surface0);
  border-radius: 3px;
  padding: 1px 5px;
}

.palette-count {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Trigger button in the tab bar ─────────────────────────────
   Inherits .tab-actions button; only the shortcut label needs handling. */

#paletteToggle .palette-kbd {
  color: var(--overlay0);
  font-size: 0.68rem;
}

/* Target highlight ──────────────────────────────────────────
   After jumping, the destination pulses once. Without it a scroll to a row in
   the middle of a dense section leaves the reader hunting for what changed. */

@keyframes palette-target-pulse {
  from { background-color: color-mix(in srgb, var(--pink) 22%, transparent); }
  to   { background-color: transparent; }
}

.palette-target {
  animation: palette-target-pulse 1.4s ease-out forwards;
  border-radius: 4px;
}

/* Responsive ────────────────────────────────────────────────── */

@media (max-width: 560px) {
  .palette-backdrop { padding-top: 56px; }

  .palette {
    max-height: 70vh;
    max-height: 70dvh;
  }

  /* 16px exactly. Safari iOS zooms the whole page when a focused input is
     under 16px, and palette.js focuses this field the moment the palette
     opens -- so every Ctrl-K left the reader on a zoomed, panned page that
     `body { overflow-x: hidden }` then made impossible to scroll back. */
  .palette-input {
    font-size: 16px;
  }

  /* The host segment is the first thing to go: on a 360px screen it costs a
     third of the prompt row and says nothing the page does not already. */
  .palette-prompt .at,
  .palette-prompt .host,
  .palette-prompt .colon,
  .palette-prompt .path { display: none; }

  /* Two of the three hints are for keys a touch device does not have. */
  .palette-hint.is-desktop-only { display: none; }

  /* The shortcut label on the trigger, likewise -- unless the icon failed to
     render, in which case the label is the only thing left and hiding it would
     leave a blank button. palette.js sets .is-iconless when the <svg> is
     missing. */
  #paletteToggle:not(.is-iconless) .palette-kbd { display: none; }
}

/* Reduced motion ────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .palette-backdrop,
  .palette {
    transition-duration: 0.001s;
  }
  .palette { transform: none; }
  .palette-target { animation: none; }
}
