/*
 * The left-hand panel: the saved searches, one of which is open.
 *
 * The criteria used to live here on their own while the searches sat in a strip
 * above the columns. Nothing on screen tied a switch to a card — you threw one
 * on the left and a number changed at the top. Opened in place, a card holds
 * its own criteria and the relationship needs no explaining.
 *
 * Only one card is open at a time. Two would put two sets of switches on screen
 * with only a heading to say which search each belongs to, which is the problem
 * this layout exists to remove.
 */

.search-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
}

.search-list__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0 var(--space-2) var(--space-1);
}

.search-list__header b {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.search-list__header span {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* No border, a soft shadow, and a ring when selected — Emilia's card. A border
 * is subtracted from the box; a ring is painted outside it, so a selected card
 * stays exactly the width of an unselected one. */
.search-card {
  border: 0;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: box-shadow 0.15s, background 0.15s;
}

/* Active but folded: the listings on the right belong to this card, and the
 * panel has to keep saying so once the criteria are out of sight. */
.search-card--active {
  box-shadow: var(--ring-selected), var(--shadow);
}

.search-card--open.search-card--active {
  box-shadow: var(--ring-selected), var(--shadow);
}

/* The card's identity: its name and what it found, on one line, ruled off from
 * the specification below. Set larger than anything in the panel — the block
 * underneath deliberately looks like a listing, and without a change of
 * register the two would read as one continuous thing. */
/* Two rows: the name, then the figures. On one row a name of three words
 * wrapped through the funnel printed beside it. */
.search-card__head {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-4) var(--space-3);
  border-bottom: 1px solid var(--line);
}

/* The name and its controls, alone on their line.
 *
 * The figures and the state badge sat here too, and a real name then broke in
 * two: "Nouvelle recherche" wrapped around them. They read underneath now,
 * which is their order anyway — what it is called, then what it holds. */
.search-card__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
}

/* Pushed to the right edge, whatever the name's length. */
.search-card__title .search-card__edit,
.search-card__title .search-card__sweep-form {
  margin-left: auto;
}

.search-card__figures {
  flex: none;
}

.search-card__facts {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* Under the bar, and quieter than it: this says what is being counted, which
 * is context rather than the measurement itself. */
.search-card__progress-legend {
  margin: var(--space-1) var(--space-4) 0;
  font-size: var(--text-xs);
  color: var(--ink-faint);
}

.search-card__progress-legend b {
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

/* Same inner padding as a listing row, so the marks in both columns end at the
 * same distance from their column's right edge — 39px, measured. Four pixels
 * out and the two lines stop reading as one column across the gap. */
.search-card__spec {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
}

/* Spans the full width beneath the name and the control, and the marks sit at
 * the same abscissa as the ones on a listing row so the two can be read down
 * the screen as one column. */
/* The summary spans the card, beneath the name and the control. It is the same
 * component a listing row uses, so nothing here restyles it — that would be the
 * start of the two drifting apart again. */
/* Nothing here restyles the shared summary — that would be the start of the
 * two card kinds drifting apart again. */

/* The whole card selects the search, not just the eight words of its name.
 *
 * Measured: the link covered 171x29 of a 445x172 card — six per cent. It looks
 * like a card, so it gets clicked like a card, and a click anywhere else did
 * nothing and said nothing. The link keeps its own box for the keyboard and for
 * the URL; what spreads is its hit area, laid over the card behind everything
 * that has business being clicked in its own right. */
.search-card {
  position: relative;
}

.search-card__select::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* The controls sit above that sheet: the pencil, the sweep button, and the
 * criteria panel with all its switches.
 *
 * The button and not its form: the form is `display: contents`, so it has no
 * box of its own to stack — z-index on it does nothing, and the sheet covered
 * the button, turning "Rechercher" into "select this search". */
.search-card__edit,
.search-card__sweep,
.search-card__new {
  position: relative;
  z-index: 2;
}

.search-card__select {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  text-decoration: none;
  color: var(--ink);
}

/* Present at rest, emphasised under the pointer.
 *
 * The desktop convention is to reveal this control on hover and it would suit
 * the primary target — but the same page has to work on an iPad, where there is
 * no hover and the control would simply never appear. Hiding it behind
 * `@media (hover: hover)` would solve that and is the right tool when a list is
 * long enough for the noise to matter; with two or three cards it only costs
 * discoverability on both. */
.search-card__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-xl);
  letter-spacing: -0.03em;
  text-wrap: balance;
}

/* Retrieved → still in contention. Two numbers, because one would hide which of
 * the two stages did the narrowing: Immoweb's filters, or ours. */
.search-card__funnel {
  flex: none;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

.search-card__arrow,
.search-card__funnel-label {
  color: var(--ink-faint);
}

/* Says out loud what the absence of a Save button would otherwise leave the
 * reader to guess. Nothing here is destructive, so nothing needs confirming —
 * but that is only obvious once someone has written it down. */
.search-list__add {
  display: contents;
}

.search-card__new {
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  width: 100%;
  padding: var(--space-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  background: none;
  color: var(--ink-muted);
  cursor: pointer;
}

.search-card__new:hover {
  border-color: var(--accent);
  color: var(--accent);
}


/* The pencil: on the active card only, so it appears once rather than beside
 * every search. Quiet at rest, filled while its panel is open. */
.search-card__edit {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  color: var(--ink-faint);
  text-decoration: none;
}

.search-card__edit svg {
  width: 1.05rem;
  height: 1.05rem;
  display: block;
}

.search-card__edit--on {
  background: var(--accent);
  color: var(--accent-contrast);
}

@media (hover: hover) and (pointer: fine) {
  .search-card__edit:hover {
    background: var(--accent-soft);
    color: var(--accent);
  }
}

/* What a sweep is doing. Absent when there is nothing to say — a badge reading
 * "idle" beside every card would be noise standing in for information. */
.search-card__state {
  flex: none;
  /* Room around it. Flush against the funnel it read as one run-on label. */
  margin-left: var(--space-1);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
  font-weight: var(--label-weight);
  padding: 0.15rem var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
}

.search-card__state--blocked,
.search-card__state--failed {
  background: var(--inferred-soft);
  color: var(--inferred);
}

/* How far the running sweep has got.
 *
 * Two states and they say different things. A known fraction fills from the
 * left; an unknown one — a sweep that has not yet counted its pages — sweeps
 * back and forth, because "we are working" and "we are 0 % done" are not the
 * same claim and must not look alike.
 *
 * Two pixels tall: the card already carries a name, a funnel, a state and a
 * button, and this is the one element that has to be read at a glance from
 * across the room rather than studied. */
.search-card__progress {
  height: 2px;
  /* Inset to the card's own padding: the bar sits outside the head, which
     carries it, and flush against the edge it read as a rule rather than as a
     measurement of this card. */
  margin: var(--space-2) var(--space-4) 0;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  overflow: hidden;
}

/* The filled part, and a sheen that travels along it.
 *
 * The bar advances one step per listing, and a listing takes ninety seconds:
 * measured, 0/10 to 1/10 in a minute and a half. Between two steps nothing
 * moved, which is indistinguishable from a bar that has stopped. The fraction
 * stays honest — it only grows when a page has actually been fetched — and the
 * sheen says the machine is still working on the next one. */
.search-card__progress-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: var(--accent);
  background-image: linear-gradient(90deg,
    transparent 0%, rgba(255, 255, 255, 0.55) 50%, transparent 100%);
  background-size: 40% 100%;
  background-repeat: no-repeat;
  animation: search-card-sheen 1.6s linear infinite;
  transition: width 0.4s ease;
}

@keyframes search-card-sheen {
  from { background-position: -40% 0; }
  to { background-position: 140% 0; }
}

.search-card__progress-fill--unknown {
  width: 35%;
  animation: search-card-sweep 1.4s ease-in-out infinite;
}

@keyframes search-card-sweep {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(285%); }
}

/* An animation that never stops is a distraction for a reader who has asked
 * not to be moved. The bar stays, the sweeping stops. */
@media (prefers-reduced-motion: reduce) {
  .search-card__progress-fill--unknown {
    animation: none;
    width: 100%;
    opacity: 0.4;
  }

  .search-card__progress-fill {
    animation: none;
    background-image: none;
    transition: none;
  }
}

/* The fraction, beside the phase it belongs to. */
.search-card__state b {
  margin-left: 0.35em;
  font-variant-numeric: tabular-nums;
}

/* The estimate. Lighter than the count beside it, because one is a fact and
 * the other is a guess, and they should not carry the same weight. */
.search-card__eta {
  margin-left: 0.4em;
  opacity: 0.7;
  text-transform: none;
  letter-spacing: 0;
}

.search-card__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.search-card__sweep-form {
  display: contents;
}

/* The one control in the application that spends requests, so it looks like a
 * decision rather than a link. */
.search-card__sweep {
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  align-self: flex-start;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-contrast);
  cursor: pointer;
}

.search-card__sweep[disabled] {
  border-color: var(--line-strong);
  background: var(--surface-sunken);
  color: var(--ink-faint);
  cursor: not-allowed;
}

.search-card__hint {
  font-size: var(--text-xs);
  color: var(--ink-faint);
}

/* Busy, and nothing more.
 *
 * The same slow beat ../stocks uses beside a live figure: two seconds, opacity
 * only. It says the machine is working — the numbers beside it say how far
 * along, and the bar underneath says the same in proportion. A spinner would
 * claim more attention than a background job deserves. */
.search-card__beat {
  display: inline-block;
  width: 0.4rem;
  height: 0.4rem;
  margin-right: 0.35em;
  border-radius: 50%;
  background: currentColor;
  animation: search-card-beat 2s ease-in-out infinite;
  vertical-align: middle;
}

@keyframes search-card-beat {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* A reader who asked not to be moved gets a steady dot rather than none: the
 * information is "busy", and it survives without the motion. */
@media (prefers-reduced-motion: reduce) {
  .search-card__beat {
    animation: none;
    opacity: 0.6;
  }
}

/* The block a running sweep replaces, on its own so the card around it — its
 * link, its pencil, its active state — is never touched. */

