/* ============================================================================
 * Command palette — a text box and a ranked list, over a scrim, near the top of
 * the window. Fully token-driven so it re-themes across accents + light/dark.
 * Shares its scrim, its Escape and its focus trap with the drawer and the
 * confirm (see overlay.js), and paints one layer above the drawer and one below
 * the confirm a row opens.
 *
 * Local tokens so the panel and scrim re-theme cleanly:
 *   --cmdk-surface  panel background     --cmdk-shadow  panel elevation
 *   --cmdk-scrim    backdrop colour      --cmdk-w       panel width
 *
 * Two densities, one markup: the default packs a row onto one line, and
 * `.ui-cmdk--roomy` gives the description a line of its own.
 *
 * why: docs/components.md#the-command-palette */

.ui-cmdk {
  /* The floating step; nothing casts. why: docs/foundations.md#elevation */
  --cmdk-surface: var(--bg-elevated);
  --cmdk-scrim: var(--scrim);
  --cmdk-w: 560px;
  --cmdk-top: 12vh;
  --cmdk-list-h: 332px;

  position: fixed;
  inset: 0;
  /* One above the drawer, one below the confirm: a palette is summoned
     deliberately and must be seen, so it paints over a drawer that was already
     open; a confirm is a question about what is under it and paints over both. */
  z-index: calc(var(--z-overlay) + 1);
  pointer-events: none; /* container never blocks; scrim/panel opt back in */

  /* One place owns "is this palette on screen at all", and the scrim and panel
     inherit it. Only the HIDE is transitioned, so the panel is still on screen
     while it fades out; the show is instant (`.is-open` cancels the transition)
     because openCommandPalette() focuses the text box in the same frame it
     opens, and focus() on a hidden element does nothing. `linear` and not
     var(--ease): visibility is discrete, easing a step buys nothing, and a curve
     that leaves [0, 1] would flip it in the middle of the fade. */
  visibility: hidden;
  transition: visibility var(--dur-med) linear;
}
.ui-cmdk.is-open { visibility: visible; transition: none; }

/* Hit-testable only while open. The root stays visible for --dur-med after
   closeCommandPalette() has stopped trapping, and a row still clickable in that
   window runs the caller's command a second time. */
.ui-cmdk.is-open .ui-cmdk__scrim,
.ui-cmdk.is-open .ui-cmdk__panel { pointer-events: auto; }

.ui-cmdk__scrim {
  position: absolute;
  inset: 0;
  background: var(--cmdk-scrim);
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease);
}
.ui-cmdk.is-open .ui-cmdk__scrim { opacity: 1; }

/* Panel — near the top rather than centred: the list grows downward, and a
   centred panel moves the text box every time the number of results changes. */
.ui-cmdk__panel {
  position: absolute;
  top: var(--cmdk-top);
  left: 50%;
  width: min(var(--cmdk-w), calc(100vw - var(--space-8)));
  max-height: min(72vh, calc(100vh - var(--cmdk-top) - var(--space-8)));
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  background: var(--cmdk-surface);
  /* The two-step edge and the drop, through the level's own names: in DARK that is
     --border-strong outside and --border one pixel inside it, then the drop; in LIGHT
     both lines are transparent and the drop carries the whole separation.
     why: docs/foundations.md#elevation */
  border: 1px solid var(--float-edge);
  box-shadow: inset 0 0 0 1px var(--elev-edge, var(--float-edge-inner)), var(--elev-drop);
  border-radius: var(--radius-lg);
  overflow: hidden;
  opacity: 0;
  transform: translate(-50%, -8px);
  transition:
    opacity var(--dur-med) var(--ease),
    transform var(--dur-med) var(--ease);
}
.ui-cmdk.is-open .ui-cmdk__panel { opacity: 1; transform: translate(-50%, 0); }
/* The ring leaves the panel's own elevation alone: it is an outline since #578, so
   the edge and the drop no longer have to be restated here to survive focus.
   why: docs/foundations.md#elevation */
.ui-cmdk__panel:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }

/* -- The text box --------------------------------------------------------- */

.ui-cmdk__search {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0 var(--space-4);
  border-bottom: 1px solid var(--border);
}
.ui-cmdk__search-ic {
  display: inline-flex;
  /* muted-ink: glyph — search icon */ color: var(--muted);
  flex: none;
}
/* 2.2 of a 24 box drawn at 17px = 1.56 CSS px, which is what keeps the mark a
   graphic rather than a smudge. why: docs/foundations.md#icons-and-glyphs */
.ui-cmdk__search-ic svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2.2; }

/* Not .ui-input: this one has no box of its own — the panel is the box — and a
   second border inside a bordered panel reads as a form somebody has to submit. */
.ui-cmdk__input {
  flex: 1;
  min-width: 0;
  /* Literal px, and a line-height it does not inherit: the target-size gate
     reads declarations rather than a laid-out box, and `var()` inside a padding
     shorthand measures as nothing there.
     */
  padding: 16px 0;
  line-height: 1.5;
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: var(--weight-normal);
  color: var(--text);
  background: none;
  border: 0;
  /* The ring goes on the search row, which is this field's box. */
  outline: none;
}
/* The shared field ring, drawn inward because the panel clips. The divider goes
   transparent under it, as a field's border does, so focus has one line.
   why: docs/foundations.md#the-focus-ring */
.ui-cmdk__search:has(.ui-cmdk__input:focus-visible) {
  border-bottom-color: transparent;
  outline: var(--ring-scroll);
  outline-offset: var(--ring-scroll-offset);
}
.ui-cmdk__input::placeholder { /* muted-ink: placeholder — empty command search */ color: var(--muted); }

/* -- The list ------------------------------------------------------------- */

.ui-cmdk__list {
  flex: 1;
  min-height: 0;
  max-height: var(--cmdk-list-h);
  overflow-y: auto;
  padding: var(--space-2);
}
/* Rows are `role="option" tabindex="-1"`, so the LIST takes the keyboard stop. The
   wired palette's Tab trap holds one item and never hands it over; the markup the
   kit publishes as a string, rendered open without the wiring, has no trap and did
   arrive at the native outline. The band is drawn INWARD, on the list: the panel clips
   with `overflow: hidden`, so an outset one is cut off, and the panel is not the box
   that scrolls. The list's own 8px of padding is where it lands.
   why: docs/foundations.md#the-focus-ring */
.ui-cmdk__list:focus-visible { outline: var(--ring-scroll); outline-offset: var(--ring-scroll-offset); }
.ui-cmdk__group + .ui-cmdk__group { margin-top: var(--space-2); }

/* Sentence case at 13px medium — the kit's label role, not a heading and not a
   shout. A group name is the one word the reader scans for. */
.ui-cmdk__group-head {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text);
}

/* Row — [icon] [label + description] [badge] [keys]. A <div role="option">, so
   the reset a button or a link would need is not needed here. */
/* The four declarations after `display` are the reset a row written as a
   <button> needs: the browser gives one a 2px outset border, `font: 400
   13.3333px Arial`, centred text and a shrink-to-fit width, and a consumer who
   needs the row operable from the keyboard should get the row this sheet
   describes rather than that. `font: inherit` comes before the line-height it
   keeps. why: docs/components.md#a-dropdown-row-is-a-div-a-link-or-a-button */
.ui-cmdk__item {
  display: flex;
  border: 0;
  font: inherit;
  text-align: left;
  width: 100%;
  align-items: center;
  gap: var(--space-3);
  padding: 8px 12px;
  line-height: 1.5;
  border-radius: var(--radius-sm);
  color: var(--text);
  cursor: pointer;
  /* The active row is painted, never faded in: the row moves on every arrow
     press and a transition would leave two rows looking half-chosen. */
  background: none;
}
.ui-cmdk__item[hidden] { display: none; } /* motion: still — a row the query no longer answers is gone on the next keystroke */
/* The row Enter would run: its fill, and no edge. The edge was an outline marking a
   selection, which is what the focus band is for (#578 r34). --surface-2, not
   --surface: the panel is --bg-elevated, which --surface matches exactly in light, so
   the edge had been the whole mark there. 1.183:1 in light, 1.234:1 in dark. */
.ui-cmdk__item.is-active { background: var(--surface-2); /* code-bg: inherit — control paint; the containing surface is the ground, for a chip and for a band alike. */ }
.ui-cmdk__item.is-active .ui-cmdk__label { color: var(--strong); }

.ui-cmdk__ic {
  display: inline-flex;
  /* muted-ink: glyph — result icon */ color: var(--dim);
  flex: none;
}
/* 2.3 of a 24 box drawn at 16px = 1.53 CSS px. Same arithmetic as the dropdown's
   row icon next door. why: docs/foundations.md#icons-and-glyphs */
.ui-cmdk__ic svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2.3; }
.ui-cmdk__item.is-active .ui-cmdk__ic { color: var(--accent); }

.ui-cmdk__main {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
  flex: 1;
}
.ui-cmdk__label {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ui-cmdk__desc {
  font-size: var(--text-sm);
  /* Body ink: a row's note is how two rows called INV-4812 and
     INV-4809 are told apart, which is not something a reader may skip.
     why: docs/foundations.md#text-ink */
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.ui-cmdk__badge {
  flex: none;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--text);
}

/* Destructive rows take the kit's danger ink, never the accent, and stay quiet
   until the reader is on them — the same pair .ui-dropdown__item.is-danger
   writes with :hover. A palette row is reached with an arrow key far more often
   than with a pointer, so `.is-active` carries the signal beside :hover: it is
   the same moment, and it is the row Enter would run.
   why: docs/foundations.md#text-ink */
.ui-cmdk__item.is-danger .ui-cmdk__label { color: var(--text); }
.ui-cmdk__item.is-danger:hover .ui-cmdk__label,
.ui-cmdk__item.is-danger.is-active .ui-cmdk__label { color: var(--pink); }
.ui-cmdk__item.is-danger.is-active .ui-cmdk__ic { color: var(--pink); }

/* A disabled row is painted, never faded. It takes --disabled-ink-bare, the ink
   for a control with no box of its own. Disabled rows keep the panel's
   surface and their labels remain readable on that ground without
   adding a grey box behind the text.
   why: docs/foundations.md#text-ink */
.ui-cmdk__item.is-disabled { cursor: default; /* muted-ink: state — unavailable control */ color: var(--disabled-ink-bare); }
.ui-cmdk__item.is-disabled .ui-cmdk__label,
.ui-cmdk__item.is-disabled .ui-cmdk__desc,
.ui-cmdk__item.is-disabled .ui-cmdk__ic { /* muted-ink: state — unavailable control */ color: var(--disabled-ink-bare); }

/* -- Keys, empty state, legend -------------------------------------------- */

.ui-cmdk__keys { display: inline-flex; gap: 4px; flex: none; }
.ui-cmdk__key {
  min-width: 20px;
  padding: 2px 5px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  /* Key caps use an edge on the card surface, keeping the shortcut readable.
     why: docs/foundations.md#elevation */
  background: var(--surface); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  line-height: 1.5;
  color: var(--text);
  text-align: center;
}

.ui-cmdk__empty {
  margin: 0;
  padding: var(--space-6) var(--space-4) var(--space-8);
  text-align: center;
  font-size: var(--text-base);
  color: var(--text);
}

.ui-cmdk__foot {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--text);
}
.ui-cmdk__foot span { display: inline-flex; align-items: center; gap: 5px; }

/* -- Roomy ---------------------------------------------------------------- */
/* The same markup, two lines to a row: the description drops under the label
   and the icon gets a tile of its own. For a palette whose rows need a sentence
   to tell apart — an invoice from an invoice — rather than a list of verbs. */

.ui-cmdk--roomy { --cmdk-w: 640px; --cmdk-list-h: 396px; }
.ui-cmdk--roomy .ui-cmdk__item { padding: 9px 12px; gap: var(--space-3); }
.ui-cmdk--roomy .ui-cmdk__main { display: block; }
.ui-cmdk--roomy .ui-cmdk__label { display: block; }
.ui-cmdk--roomy .ui-cmdk__desc { display: block; margin-top: 1px; }
.ui-cmdk--roomy .ui-cmdk__ic {
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--surface); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */
  border: 1px solid var(--border);
}
.ui-cmdk--roomy .ui-cmdk__item.is-active .ui-cmdk__ic { background: var(--surface); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */ }

/* -- Narrow --------------------------------------------------------------- */
/* At the kit's narrowest step the palette is the page: full width, off the top
   edge, and the key legend goes — there is no keyboard to legend.
   why: docs/foundations.md#breakpoints */
@media (max-width: 560px) {
  .ui-cmdk { --cmdk-top: var(--space-4); --cmdk-list-h: 60vh; }
  .ui-cmdk__panel { width: calc(100vw - var(--space-4)); }
  .ui-cmdk__foot { display: none; }
}

/* Under reduced motion the net gives every element a 0.01ms transition, so a
   child inherits `visible` one tick after the root: the text box
   openCommandPalette() focuses is still hidden in that frame, and focus falls to
   <body> — the arrows and every letter then reach nothing. So an open palette
   carries no transition inside it at all — for as long as it is open, not only
   in the frame it opens — which is what reduced motion asked for anyway: under
   the net nothing inside had longer than 0.01ms to run.
   why: docs/foundations.md#reduced-motion-travels-with-the-stylesheet */
@media (prefers-reduced-motion: reduce) {
  .ui-cmdk.is-open * { transition: none !important; }
}

/* Forced colours replace every author background, so a selected item takes the system
   pair as its fill. `forced-color-adjust: none` is what keeps the pair from sitting on
   Chromium's Canvas backplate, which would leave the label unreadable. Focus keeps its
   own ring, drawn in CanvasText so the fill is never mistaken for it. */
@media (forced-colors: active) {
  .ui-cmdk__item.is-active { forced-color-adjust: none; background: Highlight !important; color: HighlightText !important; --ring: var(--ring-width) solid CanvasText; }
  .ui-cmdk__item.is-active .ui-cmdk__label,
  .ui-cmdk__item.is-active .ui-cmdk__ic,
  .ui-cmdk__item.is-active .ui-cmdk__desc,
  .ui-cmdk__item.is-danger.is-active .ui-cmdk__label,
  .ui-cmdk__item.is-danger.is-active .ui-cmdk__ic { color: HighlightText; }
  .ui-cmdk--roomy .ui-cmdk__item.is-active .ui-cmdk__ic { background: none; }
  .ui-cmdk__item.is-active .ui-cmdk__badge { background: HighlightText; color: Highlight; }
  /* Shortcut caps inherit the adjust, so they take the pair too: the item's ink on its fill, with an ink edge. */
  .ui-cmdk__item.is-active .ui-cmdk__key { background: Highlight; color: HighlightText; border-color: HighlightText; }
}
