/* Catalogue search UI. No build step, no dependencies — everything is in these files.
 *
 * Styled on the Searchnik design system: the values below are its tokens under its own names, so a
 * colour here can be looked up there. The system is light-only and flat — nothing darker than
 * --teal-600, surfaces separated by colour rather than shadow, gold only as an accent on teal — so
 * this page has no dark mode and no drop shadows. */

@font-face {
  font-family: Roboto;
  src: url("roboto-latin-wght-normal.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;

  --teal-600:   #006A6A;
  --teal-300:   #A8CDCD;
  --teal-200:   #C6E1DE;
  --teal-100:   #D3E4DE;
  --teal-050:   #F0F3F3;
  --gold-600:   #C99433;
  --gold-400:   #FFCF7B;
  --gold-300:   #FFDFA4;
  --gold-100:   #FFF5E3;
  --ink-800:    #444444;
  --ink-500:    #777777;
  --ink-400:    #B5B5B5;
  --ink-300:    #CFCFCF;
  --ink-200:    #E5E5E5;
  --ink-050:    #F5F5F5;
  --orange-600: #EF7541;
  --orange-100: #FDE9DF;
  --green-600:  #529276;
  --green-100:  #F1F7EC;
  --blue-600:   #538BE0;
  --blue-100:   #C1E5F5;

  --ring-focus: 0 0 0 2px rgba(0, 106, 106, .35);
  --ease-out:   cubic-bezier(.2, .8, .2, 1);
  --page-pad:   45px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--teal-050);
  color: var(--ink-800);
  font: 14px/1.29 Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial,
        sans-serif;
  -webkit-font-smoothing: antialiased;
}

:focus-visible { outline: none; box-shadow: var(--ring-focus); }

/* ---------------------------------------------------------------- top bar */

/* The app bar of the Searchnik web app: deep teal, the reverse lockup, gold as the only accent. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--teal-600);
}
/* The teal focus ring disappears on a teal ground. */
.topbar :focus-visible { box-shadow: 0 0 0 2px var(--gold-400); }

.topbar__inner {
  max-width: 1512px;
  min-height: 60px;
  margin: 0 auto;
  padding: 10px var(--page-pad);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 32px;
}

.brand {
  display: flex;
  border-radius: 4px;
}
.brand__mark svg { display: block; height: 32px; width: auto; }

.searchbar {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 720px;
  height: 36px;
  padding: 0 2px 0 12px;
  background: #fff;
  border: 1px solid var(--teal-200);
  border-radius: 6px;
}
.searchbar input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  padding: 0;
  background: none;
  color: var(--ink-800);
  font: inherit;
}
/* No ring on the field: the caret marks it. A text input matches :focus-visible on a click too, so
 * the topbar's gold ring would otherwise show on every mouse focus. */
.searchbar input:focus-visible { box-shadow: none; }
.searchbar input::placeholder { color: var(--ink-500); }
.searchbar input::-webkit-search-cancel-button { filter: grayscale(1) opacity(.5); }
/* The design system's search submit: a teal tile set inside the field. It may not get darker on
 * hover — teal-600 is the ceiling — so the glyph turns gold instead. */
.searchbar button {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: var(--teal-600);
  color: #fff;
  cursor: pointer;
  transition: color 120ms var(--ease-out);
}
.searchbar button:hover { color: var(--gold-400); }
.searchbar button:focus-visible { box-shadow: inset 0 0 0 2px var(--gold-400); }
.searchbar button svg { display: block; width: 18px; height: 18px; fill: currentColor; }

/* Groups the engine badge and the Querqy chain into the topbar's third grid column, so both
 * fit beside the brand and search box without adding a fourth grid track. */
.topbar__meta {
  display: flex;
  align-items: center;
  gap: 30px;
}

/* Which engine is behind the proxy — OpenSearch or Solr. app.js fills this in once /api/engine
 * answers; empty until then. */
.engine { display: flex; }
.engine:empty { display: none; }
/* Both marks are dark ink drawn for light grounds, so on the teal bar they sit on a white chip. */
.engine__logo {
  display: block;
  height: 28px;
  width: auto;
  padding: 5px 10px;
  background: #fff;
  border-radius: 5px;
}

/* Querqy rewriter chain — the whole point of this UI, so it sits in the chrome. Laid out like the
 * app bar's own selectors: a small label line above the value. The ids are a pipeline, applied in
 * the order shown, hence the separators. */
.chain {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  row-gap: 2px;
  max-width: 380px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.15;
  color: var(--gold-400);
}
.chain__label {
  flex-basis: 100%;
  font-size: 11px;
  font-weight: 400;
  color: var(--teal-300);
}
.chain__pill { white-space: nowrap; }
.chain__pill + .chain__pill::before {
  content: "›";
  padding: 0 6px;
  color: var(--teal-300);
}
.chain__none {
  font-size: 12px;
  font-weight: 400;
  color: var(--teal-300);
}

/* ----------------------------------------------------------------- layout */

.layout {
  flex: 1 0 auto;
  width: 100%;
  max-width: 1512px;
  margin: 0 auto;
  padding: 24px var(--page-pad) 0;
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  grid-template-areas: "filters results";
  gap: 24px;
  align-items: start;
}
.filters { grid-area: filters; position: sticky; top: 84px; }
.results { grid-area: results; }
/* Nothing to filter on — an error, or before the first answer — so the panel goes and its column
 * stays empty rather than letting the results slide into it. */
.filters:has(> .rail:empty) { display: none; }

/* The design system's Panel: a white card with a mint title tab in its top-left corner and a grey
 * line beside the tab that carries the panel's description. */
.panel {
  background: #fff;
  border-radius: 10px;
}
.panel__head {
  display: flex;
  align-items: stretch;
  min-height: 57px;
}
.panel__tab {
  flex: none;
  min-width: 133px;
  margin: 0;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--teal-100);
  border-radius: 10px 0 10px 0;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--teal-600);
}
.panel__line {
  flex: 1;
  min-width: 0;
  margin-left: 18px;
  padding: 8px 26px 8px 0;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--ink-200);
}
.panel__body { padding: 8px 40px 32px; }

@media (max-width: 900px) {
  :root { --page-pad: 16px; }
  .topbar { position: static; }
  .topbar__inner { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .topbar__meta { flex-wrap: wrap; gap: 12px 30px; }
  .layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "filters" "results";
    gap: 16px;
    padding-top: 16px;
  }
  .filters { position: static; }
  .panel__body { padding: 8px 16px 24px; }
  .debug__summary { padding: 12px 16px; }
  .debug__body { padding: 16px 16px 20px; }
}

/* ------------------------------------------------------------------ facets */

.rail {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 24px;
}
@media (max-width: 900px) { .rail { padding: 16px; } }

.facet__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 10px;
}
/* The design system's eyebrow label, shared with the Querqy rule debug's section labels. */
.facet__title,
.debug__label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--ink-500);
}
.facet__clear {
  border: 0; background: none; padding: 0;
  font: inherit; font-size: 12px; font-weight: 500;
  color: var(--teal-600);
  cursor: pointer;
}
.facet__clear:hover { text-decoration: underline; text-underline-offset: 3px; }
.facet__list { display: flex; flex-direction: column; gap: 2px; }

.facet__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 8px;
  margin: 0 -8px;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 120ms var(--ease-out);
}
.facet__row:hover { background: var(--teal-100); }
/* The design system's checkbox: grey edge, radius 4; checked is solid teal with a white tick. */
.facet__row input {
  appearance: none;
  flex: none;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1px solid var(--ink-300);
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  transition: background-color 120ms var(--ease-out), border-color 120ms var(--ease-out);
}
.facet__row input:checked {
  border-color: var(--teal-600);
  background: var(--teal-600) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / 11px no-repeat;
}
.facet__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.facet__row--on .facet__name { font-weight: 500; color: var(--teal-600); }
.facet__count {
  flex: none;
  font-size: 12px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}

/* ----------------------------------------------------------------- results */

/* Sits on the line beside the Results tab, styled as the design system's compact stat: the figure
 * bold teal, everything after it a muted description. */
.statusline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}
.statusline b {
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  color: var(--teal-600);
}
.statusline .dot { color: var(--ink-300); }

.banner {
  margin-top: 16px;
  padding: 16px 24px;
  border-radius: 8px;
  background: var(--ink-050);
  color: var(--ink-800);
}
.banner--error { background: var(--orange-100); }
.banner--error strong { font-weight: 500; color: var(--orange-600); }
/* The design system sets everything in Roboto, raw JSON included. */
.banner code {
  font: inherit;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Applied filters, as the design system's filter chips: grey, with the remove × in front. */
.chips { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.chips:empty { display: none; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 25px;
  padding: 0 10px 0 7px;
  border: 1px solid var(--ink-050);
  border-radius: 5px;
  background: var(--ink-050);
  font: inherit;
  font-size: 12px;
  line-height: 1;
  color: var(--ink-800);
  cursor: pointer;
  transition: border-color 120ms var(--ease-out);
}
.chip:hover { border-color: var(--teal-600); }
.chip__x {
  order: -1;
  font-size: 15px;
  color: var(--ink-500);
}
.chip:hover .chip__x { color: var(--ink-800); }

/* One short paragraph explaining what the demo is. Dismissable per tab (see initIntro in app.js);
 * its own element rather than #notice, which renderError() clears on every failed search. */
.intro {
  align-items: flex-start;
  gap: 12px;
  margin-top: 16px;
  padding: 14px 14px 14px 24px;
  border-radius: 8px;
  background: var(--teal-100);
  overflow: hidden;
}
/* display:flex has to lose to the [hidden] UA rule, or the hidden attribute app.js relies on
 * for both the initial sessionStorage check and the post-dismiss state does nothing. */
.intro:not([hidden]) { display: flex; }
.intro p { margin: 2px 0 0; line-height: 1.45; }
.intro strong { color: var(--teal-600); }
.intro__dismiss {
  flex: none;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 5px;
  background: none;
  font: inherit;
  font-size: 18px;
  line-height: 1;
  color: var(--ink-500);
  cursor: pointer;
}
.intro__dismiss:hover { color: var(--ink-800); }

/* ------------------------------------------------------------ querqy debug */

/* The Searchnik preview's "Querqy rule debug" panel: a white card closed by default, its header a
 * chevron, the title and the rule count, and on a grey ground once open. A native <details> — see
 * renderDebug() in app.js. */
.debug {
  margin-top: 16px;
  border: 1px solid var(--ink-200);
  border-radius: 8px;
  background: #fff;
  overflow: hidden;
}
.debug__summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 24px;
  list-style: none;
  cursor: pointer;
}
.debug__summary::-webkit-details-marker { display: none; }
/* Inset, or the card's overflow clips the ring. */
.debug__summary:focus-visible { box-shadow: inset var(--ring-focus); }
.debug[open] > .debug__summary { background: var(--ink-050); }
.debug__chevron { flex: none; width: 16px; height: 16px; fill: var(--ink-500); }
.debug[open] .debug__chevron { transform: rotate(90deg); }
.debug__title { font-size: 15px; font-weight: 500; color: var(--ink-800); }
.debug__count { margin-left: auto; font-size: 13px; color: var(--ink-500); }
.debug__count strong { font-weight: 500; color: var(--ink-800); font-variant-numeric: tabular-nums; }

.debug__body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px 24px 20px;
  border-top: 1px solid var(--ink-200);
}
.debug__label { margin-bottom: 8px; }
.debug__empty { margin: 0; font-size: 13px; color: var(--ink-500); }
.debug__muted { font-size: 12px; color: var(--ink-500); white-space: nowrap; }
/* The design system sets everything in Roboto, terms and ids included. */
.debug code {
  font: inherit;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--ink-050);
}

/* Each kind's colours, from the design system's Querqy rule debug palette. Set on the pill of a rule
 * card or a clause, a term in the graph, and the curve leading to it — each takes what it needs. */
.kind--keep    { --kind-bg: #fff;              --kind-fg: var(--ink-800);    --kind-edge: var(--ink-300);  --kind-line: var(--ink-300); }
.kind--synonym { --kind-bg: var(--teal-100);   --kind-fg: var(--teal-600);   --kind-edge: var(--teal-200); --kind-line: var(--teal-600); }
.kind--replace { --kind-bg: var(--gold-100);   --kind-fg: var(--ink-800);    --kind-edge: var(--gold-300); --kind-line: var(--gold-600); }
.kind--delete  { --kind-bg: var(--orange-100); --kind-fg: var(--orange-600); --kind-line: var(--orange-600); }
.kind--up      { --kind-bg: var(--green-100);  --kind-fg: var(--green-600); }
.kind--down    { --kind-bg: var(--gold-100);   --kind-fg: var(--gold-600); }
.kind--filter  { --kind-bg: var(--blue-100);   --kind-fg: var(--blue-600); }
.kind--other   { --kind-bg: var(--ink-050);    --kind-fg: var(--ink-800); }

.debug__chip {
  flex: none;
  padding: 2px 8px;
  border-radius: 50px;
  background: var(--kind-bg);
  font-size: 12px;
  line-height: 16px;
  color: var(--kind-fg);
  white-space: nowrap;
}

/* A rule's number: on its card, and wherever the graph or a clause points back at it. */
.debug__ref {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--teal-600);
  font-size: 10px;
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.debug__refs { margin-left: auto; display: flex; gap: 3px; }

.debug__rules {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.debug__rule {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--ink-200);
  border-radius: 8px;
}
.debug__rule > .debug__ref { margin-top: 1px; }
.debug__rule-body { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.debug__rule-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.debug__effect { font-weight: 500; color: var(--ink-800); overflow-wrap: anywhere; }
.debug__match { font-size: 13px; overflow-wrap: anywhere; }
.debug__dup { font-size: 12px; color: var(--gold-600); }
.debug__source {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-500);
  overflow-wrap: anywhere;
}

/* The input graph. Rows are 34px with 8px between them — ROW and GAP in app.js draw the curves
 * against these two numbers, so change them together. */
.debug__tokens { display: flex; flex-direction: column; gap: 16px; }
.debug__token {
  display: grid;
  grid-template-columns: minmax(72px, auto) 48px minmax(0, 1fr);
  align-items: center;
}
.debug__token svg { display: block; overflow: visible; }
.debug__token path { fill: none; stroke: var(--kind-line); stroke-width: 1.75; }
.debug__token path.kind--keep { stroke-width: 1.25; }
.debug__token path.kind--delete { stroke-dasharray: 3 3; }
.debug__input {
  justify-self: start;
  height: 34px;
  padding: 0 10px;
  border-radius: 5px;
  background: var(--ink-050);
  font-size: 13px;
  line-height: 34px;
  color: var(--ink-800);
  white-space: nowrap;
}
.debug__outputs { min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.debug__output { min-width: 0; height: 34px; display: flex; align-items: center; gap: 8px; }
/* On a narrow screen the kind label and the weight give way well before the term does. */
.debug__output > .debug__muted { flex-shrink: 10; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.debug__term {
  min-width: 0;
  height: 34px;
  padding: 0 10px;
  border: 1px solid var(--kind-edge, transparent);
  border-radius: 5px;
  background: var(--kind-bg);
  font-size: 13px;
  line-height: 32px;
  color: var(--kind-fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.debug__term.kind--delete { text-decoration: line-through; }

.debug__clauses { display: flex; flex-direction: column; gap: 6px; }
.debug__clause { min-width: 0; display: flex; align-items: center; gap: 8px; }
.debug__clause-text {
  min-width: 0;
  font-size: 13px;
  color: var(--ink-800);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.grid {
  margin-top: 16px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 16px;
}

/* A product is a row card turned on its side: grey ground, radius 8, a mint tint on hover, no
 * border, no shadow, no lift. */
.card {
  display: flex;
  flex-direction: column;
  padding: 8px;
  background: var(--ink-050);
  border-radius: 8px;
  transition: background-color 120ms var(--ease-out);
}
.card:hover { background: var(--teal-100); }

/* ESCI images are Amazon CDN cutouts on white, so each sits on a white tile of its own. */
.card__tile {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  padding: 14px;
  background: #fff;
  border-radius: 6px;
  overflow: hidden;
}
.card__tile img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}
.card__tile--empty {
  font-size: 32px;
  font-weight: 700;
  color: var(--teal-300);
}
/* The rank is cut like a panel's title tab, in the tile's corner. */
.card__rank {
  position: absolute;
  top: 0; left: 0;
  padding: 4px 8px;
  background: var(--teal-100);
  border-radius: 6px 0 6px 0;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--teal-600);
  font-variant-numeric: tabular-nums;
}

.card__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 6px 4px;
}
.card__brand {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--ink-500);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.card__title {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  line-height: 18px;
  color: var(--ink-800);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card__meta {
  margin-top: auto;
  padding-top: 6px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.card__price { font-weight: 700; color: var(--teal-600); font-variant-numeric: tabular-nums; }
.card__price--none { font-weight: 400; color: var(--ink-400); }
.card__rating {
  font-size: 12px;
  color: var(--ink-500);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.card__stars { color: var(--gold-600); letter-spacing: -1px; }
.card__asin { font-size: 11px; color: var(--ink-400); }

/* ------------------------------------------------------------------ pager */

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 32px;
  font-size: 12px;
  color: var(--ink-500);
}
.pager:empty { display: none; }
/* The design system's secondary button: white, teal text, mint edge, radius 4. */
.pager button {
  padding: 8px 16px;
  border: 1px solid var(--teal-200);
  border-radius: 4px;
  background: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--teal-600);
  cursor: pointer;
  transition: background-color 200ms var(--ease-out), border-color 200ms var(--ease-out);
}
.pager button:hover:not(:disabled) { border-color: var(--teal-600); background: var(--teal-050); }
.pager button:disabled { opacity: .45; cursor: default; }

body.is-busy .grid { opacity: .5; transition: opacity 200ms var(--ease-out); }

/* ----------------------------------------------------------------- footer */

.footer {
  margin-top: 48px;
  background: var(--teal-600);
  color: rgba(255, 255, 255, .72);
}
.footer :focus-visible { box-shadow: 0 0 0 2px var(--gold-400); }
.footer__inner {
  max-width: 1512px;
  margin: 0 auto;
  padding: 20px var(--page-pad);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  font-size: 12px;
}
.footer__links { display: flex; flex-wrap: wrap; gap: 18px; }
.footer__links a {
  color: inherit;
  text-decoration: none;
  transition: color 120ms var(--ease-out);
}
.footer__links a:hover { color: var(--gold-400); }

/* ------------------------------------------------------------------ motion */

@media (prefers-reduced-motion: no-preference) {
  @keyframes rise-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* Results landing. --i (set in app.js) staggers the cards on the page just rendered. */
  .card {
    animation: rise-in .3s var(--ease-out) both;
    animation-delay: calc(var(--i, 0) * 18ms);
  }

  /* Facet groups are rebuilt wholesale on every search, so this is an entrance, not a resize. */
  .facet { animation: rise-in .2s var(--ease-out) both; }

  /* The Querqy chain changes with every search once rewriters are deployed. */
  .chain__pill, .chain__none { animation: fade-in .2s var(--ease-out) both; }

  .debug__chevron { transition: transform 120ms var(--ease-out); }

  /* The dismiss collapse itself: see .intro--closing and initIntro() in app.js. */
  .intro {
    max-height: 160px;
    transition: max-height .25s var(--ease-out), opacity .2s var(--ease-out),
                padding .25s var(--ease-out), margin .25s var(--ease-out);
  }
  .intro--closing {
    max-height: 0;
    opacity: 0;
    padding-top: 0;
    padding-bottom: 0;
    margin-top: 0;
  }
}
