/* Real Estate Monitor — dashboard. Neutral & coherent: almost-white ivory
   canvas, white cards; deep green = brand + primary actions; coral kept RARE
   (newness / one punctual accent); blue = information; yellow = to-study.
   The AI note is the primary reading of the results grid; colour is a light
   accent on the note and verdict only, never a flat over the whole card.
   Every value is a token so light and dark stay in lockstep. */

/* --- Design system ---------------------------------------------------------
   One place where colour, type and spacing are decided; every screen reads
   from here. The direction is a calm professional tool: off-white ground, white
   surfaces, anthracite text, ONE deep blue as the principal colour, terracotta
   used punctually, green reserved for a real confirmation and red for an alert.
   The former direction was "Radar Immo": forest green, warm cream, an
   editorial serif for headings and a humanist sans for the interface.

   Two rules the palette must keep: the accent stays rare (newness, one
   punctual mark), and every ink/ground pair is contrast-checked — a label
   nobody with low vision can read is not a label.
   ------------------------------------------------------------------------ */

:root {
  color-scheme: light;

  /* Grounds: an off-white canvas, white surfaces, one slightly deeper panel.
     The cream is gone: it warmed everything and pushed the whole screen towards
     the green it sat next to. */
  --bg: #F7F8F9;
  --surface: #FFFFFF;
  --surface-2: #F1F3F5;
  --border: #E3E6EA;
  --border-strong: #CFD4DA;

  /* Ink — anthracite, and a soft grey for what is secondary. Both keep ≥ 5:1
     on the three grounds above. */
  --text: #1F2429;
  --text-muted: #5A636C;
  --text-faint: #6B747D;

  /* Deep blue — the single principal colour: brand, navigation, primary
     actions, active states. Quiet enough to carry a whole screen without
     shouting, which is exactly what the green failed to do. */
  --trust: #1B3A5C;
  --trust-hover: #142C46;
  --trust-soft: #E8EDF3;
  --trust-ink: #22415F;
  --on-trust: #FFFFFF;

  /* No second brand colour. The old "working green" is now the same blue: a
     screen does not need two colours to say "this is active". */
  --accent-green: #1B3A5C;
  --accent-green-soft: #E8EDF3;

  /* Terracotta — punctual only: what is new, and nothing else. Never a
     background, never a family of badges. */
  --accent: #A8542F;
  --accent-hover: #8C4527;
  --accent-soft: #F7EAE4;
  --accent-ink: #7A3C21;
  --badge-new-bg: #A8542F;
  --badge-new-ink: #FFFFFF;

  /* Information — a grey-blue that stays behind the principal colour. */
  --info: #4A5A6B;
  --info-soft: #EDF0F3;
  --info-ink: #33414F;

  /* Attention — "à vérifier", partial data. Terracotta's quiet side. */
  --warn: #8C5A2B;
  --warn-soft: #F7EFE6;
  --warn-ink: #6B441F;

  --favorite: #1B3A5C;
  --favorite-soft: #E8EDF3;
  /* Red: alerts and incompatibilities, nothing else. */
  --danger: #9B2C1F;
  --danger-soft: #F7E4E1;
  /* Green: a real confirmation, nothing else. */
  --success: #1E6B4A;
  --success-soft: #E6F1EB;

  /* Natures — discreet markers, drawn from the same palette. Residential no
     longer carries a green of its own: three coloured families competing on one
     screen is what made it read as a technical dashboard. */
  --res: #4A5A6B;  --res-soft: #EDF0F3;  --res-ink: #33414F;
  --pro: #1B3A5C;  --pro-soft: #E8EDF3;  --pro-ink: #22415F;
  --cess: #7A5468; --cess-soft: #F1E9ED; --cess-ink: #563649;

  /* Shape and depth. */
  --radius: 14px;
  --radius-sm: 10px;
  --shadow: 0 1px 2px rgba(23, 37, 29, 0.05), 0 6px 20px rgba(23, 37, 29, 0.07);
  --shadow-sm: 0 1px 2px rgba(23, 37, 29, 0.06);

  /* Type: an editorial serif for what is read, a humanist sans for what is
     operated. Both are system stacks — this interface loads no external font,
     so it renders identically offline and asks nothing of anyone's browser. */
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --sans: "Inter", "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* One spacing scale, so gutters stop being invented per screen. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;

  /* One type scale. */
  --step--1: 0.82rem;
  --step-0: 0.95rem;
  --step-1: 1.1rem;
  --step-2: 1.35rem;
  --step-3: 1.75rem;
  --step-4: 2.3rem;

  /* Reading width: long prose stops before it becomes hard to track. */
  --measure: 68ch;
}

/* Dark = warm anthracite with a green nuance, NOT a monochrome green mass: the
   ground, panels and cards are clearly separated steps; text near white; the
   same meanings as light, darkened and desaturated.

   Written flat rather than as a media query nested inside the selector: the
   nested form is dead weight in any engine that does not implement CSS
   nesting, and a theme that silently fails renders one theme's text on the
   other theme's ground. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #14181D;
    --surface: #1D232B;
    --surface-2: #242C35;
    --border: #333B45;
    --border-strong: #47515D;
    --text: #ECEFF3;
    --text-muted: #A6AFBA;
    --text-faint: #96A0AC;
    --trust: #8FB6DC;
    --trust-hover: #A6C6E6;
    --trust-soft: #1D2A38;
    --trust-ink: #B3CFE9;
    --on-trust: #101820;
    --accent-green: #8FB6DC;
    --accent-green-soft: #1D2A38;
    --accent: #E0A95E;
    --accent-hover: #EFBC70;
    --accent-soft: #33291A;
    --accent-ink: #EFC07A;
    --badge-new-bg: #E0A95E;
    --badge-new-ink: #141A16;
    --info: #8FAEC6;
    --info-soft: #1E2A33;
    --info-ink: #ADC6D8;
    --warn: #E0A95E;
    --warn-soft: #33291A;
    --warn-ink: #EFC07A;
    --favorite: #E0BE6B;
    --favorite-soft: #33291A;
    --danger: #E09385;
    --danger-soft: #33211D;
    --success: #86C2A0;
    --success-soft: #1F3229;
    --res: #86C2A0;  --res-soft: #1F3229;  --res-ink: #A6D6BB;
    --pro: #8FAEC6;  --pro-soft: #1E2A33;  --pro-ink: #ADC6D8;
    --cess: #C79FB6; --cess-soft: #2E2129; --cess-ink: #DCBBCD;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 10px 30px rgba(0, 0, 0, 0.5);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.45);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #141A16;
  --surface: #1D251F;
  --surface-2: #242D26;
  --border: #333D35;
  --border-strong: #47524A;
  --text: #ECEFE7;
  --text-muted: #A8B2A6;
  --text-faint: #97A295;
  --trust: #86C2A0;
  --trust-hover: #9BD0B2;
  --trust-soft: #1F3229;
  --trust-ink: #A6D6BB;
  --on-trust: #10201A;
  --accent-green: #86C2A0;
  --accent-green-soft: #1F3229;
  --accent: #E0A95E;
  --accent-hover: #EFBC70;
  --accent-soft: #33291A;
  --accent-ink: #EFC07A;
  --badge-new-bg: #E0A95E;
  --badge-new-ink: #141A16;
  --info: #8FAEC6;
  --info-soft: #1E2A33;
  --info-ink: #ADC6D8;
  --warn: #E0A95E;
  --warn-soft: #33291A;
  --warn-ink: #EFC07A;
  --favorite: #E0BE6B;
  --favorite-soft: #33291A;
  --danger: #E09385;
  --danger-soft: #33211D;
  --success: #86C2A0;
  --success-soft: #1F3229;
  --res: #86C2A0;  --res-soft: #1F3229;  --res-ink: #A6D6BB;
  --pro: #8FAEC6;  --pro-soft: #1E2A33;  --pro-ink: #ADC6D8;
  --cess: #C79FB6; --cess-soft: #2E2129; --cess-ink: #DCBBCD;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 10px 30px rgba(0, 0, 0, 0.5);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.45);
}

* {
  box-sizing: border-box;
}

/* Off-screen until a keyboard reaches it, then a real, visible target. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.6rem 1rem;
  background: var(--trust);
  color: var(--on-trust);
  border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus {
  left: 0;
}

/* Larger base scale on desktop — the UI reads generously, not miniature. */
html {
  font-size: 17.5px;
}

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.55;
  font-size: var(--step-0);
  /* Kerning and ligatures on: this interface is read for minutes at a time. */
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--trust);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 0.7rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1.25rem;
}
.topbar .brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.12rem;
  letter-spacing: -0.01em;
  color: var(--text);
}
.topbar .brand:hover {
  text-decoration: none;
}
.topbar .brand .mark {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--trust);
  color: var(--on-trust);
  display: grid;
  place-items: center;
}
.topbar .brand .mark svg {
  width: 15px;
  height: 15px;
}
.topbar .spacer {
  margin-left: auto;
}
/* Primary nav — active state uses the structural green, not coral. */
.topnav {
  display: flex;
  gap: 0.25rem;
}
.topnav a {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text-muted);
  padding: 0.4rem 0.75rem;
  border-radius: 999px;
}
.topnav a:hover {
  text-decoration: none;
  background: var(--surface-2);
  color: var(--text);
}
.topnav a.active {
  background: var(--trust);
  color: var(--on-trust);
}
/* The searches menu — a plain <details>, so it works without JavaScript and stays
   keyboard-operable. Its entries are generated from the active scenarios. */
.nav-menu {
  position: relative;
}
.nav-menu > summary {
  list-style: none;
  cursor: pointer;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text-muted);
  padding: 0.4rem 0.75rem;
  border-radius: 999px;
  white-space: nowrap;
}
.nav-menu > summary::-webkit-details-marker {
  display: none;
}
.nav-menu > summary:hover {
  background: var(--surface-2);
  color: var(--text);
}
.nav-menu > summary.active {
  background: var(--trust);
  color: var(--on-trust);
}
.nav-count {
  font-variant-numeric: tabular-nums;
  font-size: 0.75rem;
  /* Hérite de la couleur du lien qui le porte : sur la pastille active, ce lien est blanc
     sur vert foncé, et toute couleur fixe y devient illisible. Mesuré dans les deux thèmes. */
  color: inherit;
}
.nav-menu-items {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.35rem);
  left: 0;
  min-width: 15rem;
  max-height: 70vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 0.35rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.nav-menu-items a {
  border-radius: calc(var(--radius) - 2px);
  padding: 0.45rem 0.6rem;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 2rem 2rem 3.5rem;
}
.topbar {
  padding-left: 2rem;
  padding-right: 2rem;
}

/* Large titles: modern system sans (no serif) - dense and legible. */
/* Headings are the editorial half of the pairing: a serif, set tight, so a
   screen reads as a document rather than as a control panel. */
h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: var(--step-3);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-1);
  text-wrap: balance;
}
h2 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: var(--step-2);
  letter-spacing: -0.005em;
  text-wrap: balance;
  margin: var(--space-5) 0 var(--space-3);
}
.display-title {
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.04;
  text-wrap: balance;
}
.subtitle {
  color: var(--text-muted);
  margin: 0 0 1.25rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 2.4rem;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  border-radius: 999px;
  padding: 0.5rem 1.05rem;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
}
.btn:hover {
  border-color: var(--trust);
  color: var(--trust-ink);
  text-decoration: none;
}
/* Deep green = primary action (never coral). */
.btn-primary {
  background: var(--trust);
  border-color: var(--trust);
  color: var(--on-trust);
  font-weight: 600;
}
.btn-primary:hover {
  background: var(--trust-hover);
  border-color: var(--trust-hover);
  color: white;
}
/* Visible keyboard focus everywhere — and « partout » means every focusable element, not a
   list of the ones we happened to think of: the filter bars use bare <input>/<select> inside
   a <label>, which the previous list missed entirely. The ring is measured at 10,5:1 on the
   page background in the light theme and uses the light green of the dark one. */
a:focus-visible,
.btn:focus-visible,
button:focus-visible,
.topnav a:focus-visible,
summary:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--trust);
  outline-offset: 2px;
  border-radius: 6px;
}
.btn-sm {
  min-height: 2.1rem;
  padding: 0.38rem 0.8rem;
  font-size: 0.84rem;
}
.btn.active-favorite {
  background: var(--favorite-soft);
  border-color: var(--favorite);
  color: var(--favorite);
}
.btn.active-dismiss {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger);
}
.btn.active-seen {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--success);
}
/* What was already decided, and when — the decision itself, not a hint of it. */
.action-state {
  align-self: center;
  font-size: 0.76rem;
  color: var(--text-faint);
}

/* Scenario list */
.scenario-list {
  display: grid;
  gap: 0.75rem;
}
.scenario-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  box-shadow: var(--shadow);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.scenario-row .name {
  font-weight: 600;
  font-size: 1.05rem;
}
.scenario-row .name a {
  color: var(--text);
}
.scenario-stats {
  display: flex;
  gap: 1.25rem;
  color: var(--text-muted);
  font-size: 0.88rem;
  flex-wrap: wrap;
}
.scenario-stats strong {
  color: var(--text);
}
/* Each queue in a search row opens the matching filtered view. */
.scenario-stats a.new-count,
.scenario-stats a.drop-count,
.scenario-stats a.removed-count {
  font-weight: 600;
  color: var(--accent-ink);
}
.scenario-stats a.removed-count {
  color: var(--text-muted);
}
.scenario-actions {
  display: flex;
  gap: 0.4rem;
}

.status-pill {
  display: inline-block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: var(--trust-soft);
  color: var(--trust-ink);
}
.status-pill.paused {
  background: #eee7dc;
  color: var(--text-muted);
}
.status-pill.archived {
  background: #ece9e4;
  color: var(--text-muted);
}

/* Filters */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1.25rem;
}
.filters a,
.filters .filter-group {
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.3rem 0.8rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.filters a.selected {
  background: var(--trust);
  border-color: var(--trust);
  color: var(--on-trust);
}
.filter-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  margin-bottom: 1.25rem;
}
.filter-form label {
  font-size: 0.8rem;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.filter-form input,
.filter-form select {
  font-family: inherit;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.88rem;
}

/* Listing cards */
.listing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
}
.listing-card {
  position: relative; /* anchors the top-right AI score badge */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: opacity 0.15s ease;
}
.listing-card.dismissed {
  opacity: 0.5;
}
/* A card shows exactly one photo: it is scanned, not browsed. A fixed band, and
   the image clipped into it — an unconstrained image used to overflow by up to
   487px and render over the price and the address. */
.listing-photos {
  position: relative;
  height: 160px;
  background: var(--surface-2);
  overflow: hidden;
}
.listing-photos img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.listing-photos.empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.85rem;
  /* Same height as a real photo band: a card without a picture must not be a
     shorter, odd-looking card in the grid. */
  height: 160px;
  /* Neutral placeholder that blends into the card, never a foreign tint. */
  background: var(--surface-2);
}
.listing-photos.empty .photo-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  text-align: center;
  padding: 0 0.75rem;
}
.listing-photos.empty svg {
  width: 26px;
  height: 26px;
  opacity: 0.55;
}
.photo-empty-label {
  font-weight: 600;
}
.photo-empty-place {
  font-size: 0.8rem;
  color: var(--text-muted);
}
/* How many local thumbnails exist, stated only when there is more than one.
   The card shows one; the rest live in the detail view and the full gallery on
   the source's own page. */
.photo-count {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  background: rgba(0, 0, 0, 0.62);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
}
.listing-photos {
  position: relative;
}
.listing-source .source-label {
  text-transform: uppercase;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-right: 0.35rem;
}

.listing-body {
  padding: 0.9rem 1rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 1;
}
.listing-title {
  font-weight: 600;
  font-size: 1rem;
  margin: 0;
}
/* Titles read as content, not coral CTAs; coral only on hover. */
.listing-title a {
  color: var(--text);
}
.listing-title a:hover {
  color: var(--accent);
}
.listing-meta {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin: 0;
}
.listing-price {
  font-weight: 700;
  font-size: 1.05rem;
  margin: 0.1rem 0;
}
.listing-price-change {
  color: var(--text-muted);
  font-size: 0.82rem;
  margin: 0 0 0.2rem;
}
/* Changes other than the price, named rather than hinted at. */
.listing-changed {
  color: var(--info-ink);
  font-size: 0.8rem;
  margin: 0 0 0.2rem;
}
.price-up {
  color: var(--danger);
  font-weight: 600;
}
.price-down {
  color: var(--success);
  font-weight: 600;
}
.price-history-title {
  font-weight: 600;
  margin: 0.6rem 0 0.2rem;
  color: var(--text);
}
.price-history {
  list-style: none;
  margin: 0;
  padding: 0;
}
.price-history li {
  display: flex;
  gap: 0.6rem;
  padding: 0.15rem 0;
  border-bottom: 1px solid var(--border);
}
.price-history li:last-child {
  border-bottom: none;
}
.listing-updated {
  color: var(--text-muted);
  font-size: 0.78rem;
}
.listing-badges {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}
.badge {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: var(--surface-2);
  color: var(--text-muted);
  border: 1px solid var(--border);
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
}
/* Coral is reserved for novelties. */
.badge.new {
  background: var(--badge-new-bg);
  color: var(--badge-new-ink);
  border-color: transparent;
}
.badge.removed {
  background: var(--danger-soft);
  color: var(--danger);
  border-color: transparent;
}
/* --- AI restitution --------------------------------------------------------
   The AI note is the primary reading of the results grid. Each verdict maps to
   three local custom properties (ink / soft background / line) drawn straight
   from the palette tokens, so light and dark stay in lockstep automatically and
   no colour lives outside the palette:
     Très prometteur → deep green   (the most important verdict)
     À étudier       → soft yellow, dark-brown text (never white on yellow)
     Peu adapté      → soft coral, dark-coral text (calm, not alarming)
     En attente / indisponible → neutral grey, no artificial note.
   Colour is a light accent on the score badge and the verdict pill only; the
   card itself stays white and neutral. */
.ai-verdict--very_promising {
  --v-ink: var(--trust-ink);
  --v-bg: var(--trust-soft);
  --v-line: var(--trust);
}
.ai-verdict--to_study {
  --v-ink: var(--warn-ink);
  --v-bg: var(--warn-soft);
  --v-line: var(--warn);
}
.ai-verdict--not_suitable {
  --v-ink: var(--danger);
  --v-bg: var(--danger-soft);
  --v-line: var(--danger);
}
.ai-verdict--none,
.ai-verdict--pending,
.ai-verdict--unavailable {
  --v-ink: var(--text-muted);
  --v-bg: var(--surface-2);
  --v-line: var(--border);
}

/* Hero score badge: fixed at the same top-right spot on every card, over the
   photo. The number dominates; colour is a light accent (border + digits).
   Très prometteur additionally gets a faint green fill so it reads as the most
   important. Unanalyzed / unavailable show a neutral chip, never a number. */
.ai-score-badge {
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  z-index: 3;
  min-width: 3rem;
  padding: 0.28rem 0.5rem 0.24rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  background: var(--surface);
  border: 1.5px solid var(--v-line, var(--border));
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(29, 35, 31, 0.16);
}
.ai-score-badge .v {
  font-size: 1.85rem;
  font-weight: 800;
  color: var(--v-ink, var(--text));
}
.ai-score-badge .u {
  font-size: 0.6rem;
  color: var(--text-faint);
  letter-spacing: 0.02em;
  margin-top: 0.05rem;
}
.ai-score-badge .s {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  padding: 0.12rem 0;
}
.ai-score-badge.ai-verdict--very_promising {
  background: var(--trust-soft);
  border-color: var(--trust);
}
.ai-score-badge.ai-verdict--none {
  background: var(--surface-2);
  border-color: var(--border);
  box-shadow: none;
}

/* Card encart: fully neutral (no background, no spine); the verdict pill and
   the reasons carry the only colour. */
.ai-encart {
  margin: 0.55rem 0 0.4rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
}
.ai-verdict-pill {
  font-size: 0.76rem;
  font-weight: 700;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: var(--v-bg);
  color: var(--v-ink);
}
.ai-reasons {
  margin: 0.15rem 0 0.1rem;
  padding-left: 1.05rem;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.ai-reasons li {
  margin: 0.12rem 0;
}
.ai-full {
  margin-top: 0.15rem;
}
.ai-full > summary {
  cursor: pointer;
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--trust);
  list-style: none;
}
.ai-full > summary::-webkit-details-marker {
  display: none;
}
.ai-full > summary::before {
  content: "▸ ";
}
.ai-full[open] > summary::before {
  content: "▾ ";
}
.ai-full-body {
  margin-top: 0.3rem;
}
.ai-status-label {
  font-weight: 600;
  color: var(--text-muted);
  font-size: 0.9rem;
}
.ai-encart-note {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin: 0.2rem 0 0;
}
.ai-section-title {
  font-weight: 600;
  margin: 0.5rem 0 0.15rem;
  color: var(--text);
  font-size: 0.85rem;
}
.ai-provider {
  color: var(--text-faint);
  font-size: 0.75rem;
  margin: 0.4rem 0 0;
}

/* Scenario-level AI synthesis: light tiles that never out-shout the card
   notes. Neutral "analysées" tile; the verdict tiles take a light verdict fill
   with a coloured number. */
.ai-synthese {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0.4rem 0 1.25rem;
}
.ai-synthese-item {
  flex: 1 1 0;
  min-width: 6.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.7rem;
  text-align: center;
}
.ai-synthese-item.ai-verdict--very_promising,
.ai-synthese-item.ai-verdict--to_study,
.ai-synthese-item.ai-verdict--not_suitable,
.ai-synthese-item.ai-verdict--pending,
.ai-synthese-item.ai-verdict--none {
  background: var(--v-bg);
  border-color: transparent;
}
.ai-synthese-item .n {
  display: block;
  font-size: 1.45rem;
  font-weight: 800;
  line-height: 1;
  color: var(--v-ink, var(--text));
}
.ai-synthese-item .l {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.ai-synthese-item.ai-verdict--very_promising .l,
.ai-synthese-item.ai-verdict--to_study .l,
.ai-synthese-item.ai-verdict--not_suitable .l {
  color: var(--v-ink);
  opacity: 0.9;
}

/* Verdict quick filters: neutral pills with a small verdict dot; when selected
   they adopt their own light verdict colour (or deep green for "Toutes"). */
.quick-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 1rem;
}
.quick-filters-label {
  font-size: 0.75rem;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-right: 0.15rem;
}
.quick-filters .qf {
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 0.3rem 0.8rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.quick-filters .qf.ai-verdict--very_promising::before,
.quick-filters .qf.ai-verdict--to_study::before,
.quick-filters .qf.ai-verdict--not_suitable::before,
.quick-filters .qf.ai-verdict--pending::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--v-line);
  margin-right: 0.4rem;
  vertical-align: baseline;
}
.quick-filters .qf.selected {
  background: var(--v-bg, var(--trust));
  color: var(--v-ink, var(--on-trust));
  border-color: var(--v-line, var(--trust));
  font-weight: 600;
}

.listing-actions {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

.details-block {
  border-top: 1px solid var(--border);
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  font-size: 0.83rem;
  color: var(--text-muted);
}
.details-block dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.6rem;
  margin: 0;
}
.details-block dt {
  color: var(--text-muted);
}
.details-block dd {
  margin: 0;
  color: var(--text);
}
.not-set {
  color: var(--text-muted);
  font-style: italic;
}

.empty-state {
  color: var(--text-muted);
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 2rem;
  text-align: center;
}

/* Form */
.form-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem 1.25rem;
  margin-bottom: 1rem;
  box-shadow: var(--shadow);
}
.form-section h2 {
  margin: 0 0 0.75rem;
  font-size: 0.95rem;
  color: var(--text);
}
.form-section h3 {
  margin: 0 0 0.75rem;
  font-size: 0.95rem;
  color: var(--text);
}
.form-grid {
  display: grid;
  /* `min(200px, 100%)`: on a phone the 200px floor is wider than the column itself, and a
     grid column that cannot shrink pushes the whole form off the screen. */
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: 0.85rem;
}
.form-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}
.form-field label,
.form-field .form-label {
  font-size: 0.82rem;
  color: var(--text-muted);
}
/* A group of checkboxes has a name, not a label: `<label>` may only name one control. */
.form-field .form-label {
  display: block;
}
.form-field input[type="text"],
.form-field input[type="number"],
.form-field select,
.form-field textarea {
  font-family: inherit;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  font-size: 0.92rem;
  background: var(--surface-2);
  color: var(--text);
}
.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible {
  outline: 2px solid var(--trust);
  outline-offset: 1px;
  border-color: var(--trust);
}
.form-field textarea {
  resize: vertical;
  /* Le champ épouse son contenu au lieu de le cacher derrière six lignes. Un cahier des
     charges de 460 px dans une boîte de 120 px transformait le champ en piège à molette :
     340 px de défilement interne, soit quatre crans où la page semblait figée sous le
     curseur. `field-sizing` fait le travail là où il existe ; `min-height` garantit le reste
     partout ailleurs. Aucun plafond de hauteur : mesuré à 390 px de large, un plafond de
     42 rem laissait revenir 266 px de piège, parce que le texte s'y replie sur bien plus de
     lignes. Un champ haut ne coûte qu'un défilement de page ordinaire, qui lui fonctionne ;
     un champ plafonné redevient un piège. */
  field-sizing: content;
  min-height: 17rem;
}
.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
}
.checkbox-group label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.88rem;
  color: var(--text);
}
.market-toggle {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.market-toggle label {
  flex: 1;
  min-width: 130px;
  text-align: center;
  border: 1.5px solid var(--border-strong);
  border-radius: 10px;
  padding: 0.7rem;
  cursor: pointer;
  background: var(--surface-2);
  transition: background 0.14s ease, border-color 0.14s ease;
}
.market-toggle label:hover {
  border-color: var(--trust);
}
.market-toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
/* The technical nature is a structural choice — highlighted in trust green. */
.market-toggle label:has(input:checked) {
  background: var(--trust-soft);
  border-color: var(--trust);
}
.market-toggle input:checked + span {
  color: var(--trust-ink);
  font-weight: 600;
}
.market-toggle input:focus-visible + span {
  outline: 2px solid var(--trust);
  outline-offset: 3px;
  border-radius: 4px;
}
.hint {
  color: var(--text-muted);
  font-size: 0.78rem;
  margin: 0.15rem 0 0;
}
.reserved-note {
  color: var(--text-muted);
  font-size: 0.78rem;
  font-style: italic;
}

details.advanced {
  margin-top: 0.5rem;
}
details.advanced summary {
  cursor: pointer;
  color: var(--trust);
  font-size: 0.88rem;
}

.form-actions {
  display: flex;
  gap: 0.6rem;
  margin-top: 1.25rem;
}

.back-link {
  display: inline-block;
  margin-bottom: 0.75rem;
  font-size: 0.88rem;
}

/* Sources et couverture (étape 10) */
.coverage-table-wrapper {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.coverage-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
  white-space: nowrap;
}
.coverage-table th,
.coverage-table td {
  padding: 0.55rem 0.8rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.coverage-table th {
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.coverage-table tbody tr:last-child td {
  border-bottom: none;
}

/* Technical nature: a neutral colour cue distinguishing the three engine
   paths (résidentiel / professionnel / cession) - never a "profile". */
.nature-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  vertical-align: middle;
  margin-right: 0.4rem;
}
.nature-residential {
  background: var(--res-soft);
  color: var(--res-ink);
}
.nature-professional {
  background: var(--pro-soft);
  color: var(--pro-ink);
}
.nature-transfer {
  background: var(--cess-soft);
  color: var(--cess-ink);
}
/* A quiet coloured left rail so the three natures are visually separable in
   the scenario list without shouting. */
.scenario-row.nature-residential {
  border-left: 3px solid var(--res);
}
.scenario-row.nature-professional {
  border-left: 3px solid var(--pro);
}
.scenario-row.nature-transfer {
  border-left: 3px solid var(--cess);
}
/* AI presence flag — discreet, never coral. */
/* A reader's own pin, carried by their browser — never a state of the shared scenario. */
.pin-flag {
  display: inline-flex;
  align-items: center;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: var(--favorite-soft);
  color: var(--favorite);
}
.ai-flag {
  display: inline-flex;
  align-items: center;
  gap: 0.28rem;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: var(--trust-soft);
  color: var(--trust-ink);
}

/* Scenario detail header + panels */
.scenario-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.scenario-head-title h1 {
  display: inline;
  margin-right: 0.5rem;
}
.scenario-head-title .client-label {
  color: var(--text-muted);
  font-size: 0.9rem;
}
.scenario-head-actions {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.scenario-panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  box-shadow: var(--shadow);
}
.panel h2,
.panel h3 {
  margin: 0 0 0.75rem;
  font-size: 0.95rem;
}
.panel-dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1rem;
  margin: 0;
  font-size: 0.9rem;
}
.panel-dl dt {
  color: var(--text-muted);
  font-weight: 500;
}
.panel-dl dd {
  margin: 0;
  color: var(--text);
}
.panel-empty {
  color: var(--text-muted);
  font-size: 0.9rem;
  margin: 0;
}
.spec-block {
  margin-top: 0.75rem;
  font-size: 0.9rem;
}
.spec-block summary {
  cursor: pointer;
  color: var(--trust);
}
.spec-text {
  white-space: pre-wrap;
  margin: 0.5rem 0 0;
  color: var(--text);
}

/* Form hint text under a section heading */
.form-hint {
  color: var(--text-muted);
  font-size: 0.88rem;
  margin: 0 0 0.75rem;
}

/* ---------- Home (accueil) ----------
   The page opens on the decision queue, not on a hero. The big number is what is waiting
   for a human; the three counters underneath say which kind of waiting it is. */
.home-decisions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem 2rem;
  margin: 0.5rem 0 2rem;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--border);
}
.home-decisions-head {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
}
.home-decisions-title {
  font-size: clamp(1.9rem, 3.6vw, 2.7rem);
  margin: 0;
  max-width: 18ch;
  font-variant-numeric: tabular-nums;
}
.home-decisions-sub {
  color: var(--text-muted);
  font-size: 0.98rem;
  max-width: 52ch;
  margin: 0 0 0.4rem;
}
.decision-queues {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem 2.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.dq {
  display: grid;
  gap: 0.1rem;
}
.dq-n {
  font-family: var(--serif);
  font-size: 2rem;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
}
.dq--live .dq-n { color: var(--accent-ink); }
.dq-l {
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* Elegant "no photo yet" placeholder. */
.photo-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  width: 100%;
  height: 100%;
  color: var(--text-faint);
  font-size: 0.8rem;
  background:
    repeating-linear-gradient(
      -45deg,
      transparent,
      transparent 10px,
      rgba(0, 0, 0, 0.015) 10px,
      rgba(0, 0, 0, 0.015) 20px
    );
}
.photo-empty svg {
  width: 30px;
  height: 30px;
  opacity: 0.55;
}

.section-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 2rem 0 1rem;
}
.section-head h2 {
  margin: 0;
  font-size: 1.2rem;
}
.section-note {
  color: var(--text-faint);
  font-size: 0.85rem;
}
.section-link {
  margin-left: auto;
  font-weight: 600;
  font-size: 0.86rem;
}

.opp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1rem;
}
.opp-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  color: var(--text);
  border-top: 3px solid var(--border);
  transition:
    transform 0.16s ease,
    box-shadow 0.16s ease;
}
.opp-card:hover {
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(38, 33, 26, 0.1), 0 20px 46px rgba(38, 33, 26, 0.08);
}
.opp-card.nature-residential {
  border-top-color: var(--res);
}
.opp-card.nature-professional {
  border-top-color: var(--pro);
}
.opp-card.nature-transfer {
  border-top-color: var(--cess);
}
.opp-photo {
  position: relative;
  height: 150px;
  background: var(--surface-2);
}
.opp-photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.opp-photo.empty {
  display: grid;
  place-items: center;
  color: var(--text-faint);
  font-size: 0.85rem;
}
.opp-photo .badge.new {
  position: absolute;
  top: 0.6rem;
  left: 0.6rem;
}
.opp-body {
  padding: 0.8rem 0.95rem 0.95rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.opp-price {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.3rem;
  font-variant-numeric: tabular-nums;
}
.opp-title {
  font-weight: 600;
  font-size: 0.9rem;
  line-height: 1.35;
}
.opp-meta {
  color: var(--text-muted);
  font-size: 0.82rem;
}
.opp-scenario {
  color: var(--text-faint);
  font-size: 0.78rem;
  margin-top: 0.2rem;
}

/* Scenario rows: roomy, with one primary action (Voir) and the rest grouped
   behind a discreet menu. Action-needing rows get a quiet coral cue. */
.scenario-row {
  padding: 1.15rem 1.5rem;
}
.scenario-row-main {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.45rem 0.75rem;
  flex: 1;
}
.scenario-row .name {
  grid-column: 1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.scenario-tags {
  grid-column: 2;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.scenario-row .scenario-stats {
  grid-column: 1 / -1;
}
.scenario-row.needs-action {
  box-shadow: var(--shadow);
}
.new-count {
  color: var(--accent-ink);
  font-weight: 600;
}

/* Grouped secondary actions (details/summary popover — no JS). */
.row-menu {
  position: relative;
}
.row-menu > summary {
  list-style: none;
  font-size: 1.1rem;
  line-height: 1;
  padding-left: 0.9rem;
  padding-right: 0.9rem;
}
.row-menu > summary::-webkit-details-marker {
  display: none;
}
.row-menu-items {
  position: absolute;
  right: 0;
  top: calc(100% + 0.4rem);
  z-index: 30;
  min-width: 190px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 0.35rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.row-menu-items a,
.row-menu-items button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  padding: 0.55rem 0.65rem;
  border-radius: 8px;
  cursor: pointer;
}
.row-menu-items a:hover,
.row-menu-items button:hover {
  background: var(--surface-2);
  text-decoration: none;
}
.row-menu-items form {
  margin: 0;
}

/* Touch, not width: a tablet in the hand needs the same target size as a phone, and a
   35px-high tab is below what a thumb reliably hits. */
@media (pointer: coarse) {
  .btn,
  .btn-sm,
  .filters a,
  .quick-filters .qf,
  .row-menu-items a,
  .row-menu-items button,
  .nav-menu-items a {
    min-height: 2.75rem;
    display: inline-flex;
    align-items: center;
  }
}

@media (max-width: 860px) {
  .home-decisions {
    flex-direction: column;
    align-items: flex-start;
    gap: 1.25rem;
  }
}

@media (max-width: 720px) {
  /* Larger base text and generous touch targets on phones. */
  html {
    font-size: 17px;
  }
  .container {
    padding: 1.15rem 1.15rem 3rem;
  }
  .btn {
    min-height: 2.75rem;
    font-size: 0.95rem;
  }
  .btn-sm {
    min-height: 2.5rem;
    font-size: 0.9rem;
  }
  .home-decisions-title {
    font-size: clamp(1.7rem, 7.5vw, 2.2rem);
  }
  .decision-queues {
    gap: 0.9rem 1.75rem;
  }
  .dq-n {
    font-size: 1.7rem;
  }
  /* The searches menu spans the width rather than hanging off the left edge. */
  .nav-menu-items {
    left: 0;
    right: 0;
    min-width: 0;
  }
  /* Filter tabs scroll sideways instead of wrapping into four cramped rows. */
  .filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .filters a {
    white-space: nowrap;
    /* A tab is a target before it is a label: 35px was below what a thumb can hit. */
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    padding: 0.3rem 1rem;
  }
  .filters-count {
    white-space: nowrap;
  }
  /* Decision strip: two columns of figures rather than one long ladder. */
  .decision-strip {
    gap: 1rem 1.5rem;
  }
  .decision-strip .ds-item {
    flex: 1 1 40%;
  }
  .decision-strip .ds-note {
    flex-basis: 100%;
  }
  .listing-actions .btn {
    flex: 1 1 auto;
  }
  .coverage-summary__grid {
    grid-template-columns: 1fr;
  }
  .scenario-row {
    flex-direction: column;
    align-items: stretch;
    gap: 0.85rem;
  }
  .scenario-row-main {
    grid-template-columns: 1fr;
  }
  .scenario-tags {
    grid-column: 1;
    justify-self: start;
  }
  .scenario-actions {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.5rem;
  }
  .scenario-actions .btn-primary {
    width: 100%;
  }
  .row-menu-items {
    right: 0;
    left: auto;
  }
  .scenario-head {
    flex-direction: column;
  }
  .scenario-panels {
    grid-template-columns: 1fr;
  }
  .listing-grid,
  .opp-grid {
    grid-template-columns: 1fr;
  }
  /* Synthesis: 3 tiles per row so all five stay legible on a phone. */
  .ai-synthese-item {
    flex-basis: calc(33.333% - 0.4rem);
    min-width: 0;
  }
  /* Bigger touch targets for the verdict quick filters. */
  .quick-filters .qf {
    padding: 0.5rem 0.9rem;
    font-size: 0.9rem;
  }
  /* Keep the hero score badge prominent and readable on phones. */
  .ai-score-badge .v {
    font-size: 2rem;
  }
  .form-grid,
  .row2 {
    grid-template-columns: 1fr;
  }
  .market-toggle {
    flex-direction: column;
  }
  .filter-form {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-form label {
    width: 100%;
  }
  .panel-dl {
    grid-template-columns: 1fr;
    gap: 0.1rem 0;
  }
  .panel-dl dt {
    margin-top: 0.5rem;
  }
  .topbar {
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    padding: 0.7rem 1.15rem;
  }
  .topnav {
    order: 3;
    width: 100%;
  }
  .topbar .spacer {
    display: none;
  }
}

/* Reserved market-analysis slot on a listing (engine not built yet). */
.market-slot {
  margin-top: 0.7rem;
  padding: 0.6rem 0.75rem;
  border: 1px dashed var(--border-strong);
  border-radius: 10px;
  background: var(--surface-2);
}
.market-slot-title {
  margin: 0 0 0.3rem;
  font-weight: 600;
  font-size: 0.82rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.market-slot-title .soon {
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--trust-ink);
  background: var(--trust-soft);
  padding: 0.08rem 0.4rem;
  border-radius: 999px;
}
.market-slot-list {
  margin: 0;
  padding-left: 1.1rem;
  color: var(--text-faint);
  font-size: 0.8rem;
  display: grid;
  gap: 0.15rem;
}

/* Geography G5: "Localisation à vérifier" bucket (LOCATION_UNKNOWN) and its
   quick-filter chips. The unknown listings are surfaced with a neutral watch
   accent, never presented as inside the radius. */
.badge.geo-unknown {
  background: var(--warn-soft);
  color: var(--warn-ink);
  border: 1px solid var(--warn);
}
.qf.geo-bucket--in.selected {
  background: var(--trust-soft);
  color: var(--trust-ink);
  border-color: var(--trust);
}
.qf.geo-bucket--unknown.selected {
  background: var(--warn-soft);
  color: var(--warn-ink);
  border-color: var(--warn);
}
/* Geography G5: guided "Zone de recherche" selector with progressive
   disclosure, plus the light custom multi-select (chips + searchable checkbox
   panel) for departments and regions. No front-end library; native checkboxes
   are the source of truth and store official codes. */
.geo-scope {
  grid-column: 1 / -1;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1rem 1rem;
  background: var(--surface-2);
}
.geo-mode-field {
  margin-bottom: 0.6rem;
}
.geo-mode-select {
  max-width: 26rem;
}
.geo-group[hidden] {
  display: none;
}
.geo-around-row {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 0.75rem;
}
.geo-nationwide-note {
  margin: 0.2rem 0 0;
}

.geo-multi {
  position: relative;
}
.geo-multi-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-bottom: 0.4rem;
}
.geo-multi-chips.empty {
  margin-bottom: 0.3rem;
}
.geo-multi-none {
  color: var(--text-faint);
  font-size: 0.86rem;
}
.geo-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.3rem 0.15rem 0.55rem;
  background: var(--trust-soft);
  color: var(--trust-ink);
  border: 1px solid var(--trust);
  border-radius: 999px;
  font-size: 0.85rem;
  line-height: 1.4;
}
.geo-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15rem;
  height: 1.15rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.geo-chip-remove:hover,
.geo-chip-remove:focus-visible {
  background: var(--trust);
  color: var(--surface);
}
.geo-multi-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.75rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.geo-multi-toggle::after {
  content: "▾";
  color: var(--text-muted);
}
.geo-multi-toggle:hover {
  border-color: var(--trust);
}
.geo-multi-panel {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  margin-top: 0.3rem;
  max-height: 17rem;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.geo-multi-panel[hidden] {
  display: none;
}
.geo-multi-search {
  margin: 0.5rem;
  flex: 0 0 auto;
}
.geo-multi-options {
  list-style: none;
  margin: 0;
  padding: 0 0 0.35rem;
  overflow-y: auto;
}
.geo-multi-option label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.7rem;
  cursor: pointer;
  font-weight: 400;
}
.geo-multi-option label:hover {
  background: var(--surface-2);
}
.geo-multi-option input {
  width: auto;
  margin: 0;
}

@media (max-width: 640px) {
  .geo-around-row {
    grid-template-columns: 1fr;
  }
  /* On mobile the picker is a plain vertical checkbox list (no floating
     panel), so it stays easy to scroll and tap. */
  .geo-multi-panel {
    position: static;
    max-height: none;
    box-shadow: none;
  }
}

/* ------------------------------------------------------------------ *
 * Geographic coverage (G6.4) - honest requested / queryable /
 * observed / blind-spot display. Tri-state badges FULL/PARTIAL/UNKNOWN.
 * All colours come from the shared tokens, so light/dark is automatic.
 * ------------------------------------------------------------------ */
.coverage-list { display: grid; gap: 16px; margin: 12px 0 28px; }
.coverage-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow-sm);
}
.coverage-card__head { margin-bottom: 12px; }
.coverage-card__title { font-size: 1.05rem; margin: 0 0 2px; }
.coverage-card__title a { color: var(--text); text-decoration: none; }
.coverage-card__title a:hover { color: var(--trust); text-decoration: underline; }
.coverage-card__zone { margin: 0; color: var(--text-muted); font-size: 0.9rem; }
.cov-key, .cs-label {
  display: inline-block; text-transform: uppercase; letter-spacing: 0.03em;
  font-size: 0.68rem; font-weight: 700; color: var(--text-faint);
}
.coverage-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 14px; }
.cov-tile {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px; text-align: center;
}
.cov-tile--blind { background: var(--danger-soft); border-color: var(--danger-soft); }
.cov-tile__n { display: block; font-size: 1.5rem; font-weight: 800; color: var(--text); }
.cov-tile--blind .cov-tile__n { color: var(--danger); }
.cov-tile__l { display: block; font-size: 0.76rem; color: var(--text-muted); margin-top: 2px; }
.coverage-block { margin-top: 14px; }
.coverage-h { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-faint); margin: 0 0 6px; }
.coverage-meta { margin: 0 0 8px; font-size: 0.9rem; color: var(--text-muted); }
.coverage-note { margin: 6px 0; font-size: 0.9rem; color: var(--text); }
.coverage-note--warn { color: var(--warn-ink); }
.coverage-block--blind, .coverage-note--blind { color: var(--danger); }
.coverage-block--awaiting, .coverage-note--awaiting { color: var(--text-muted); }
.coverage-caveat { margin: 8px 0 0; font-size: 0.8rem; font-style: italic; color: var(--text-faint); }
.cov-muted { color: var(--text-faint); }

/* tri-state / declared badges */
.cov-badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 0.72rem; font-weight: 700; line-height: 1.5; white-space: nowrap;
}
.cov-badge--full { background: var(--trust-soft); color: var(--trust-ink); }
.cov-badge--partial { background: var(--warn-soft); color: var(--warn-ink); }
.cov-badge--unknown { background: var(--surface-2); color: var(--text-muted); border: 1px dashed var(--border-strong); }
.cov-badge--declared { background: var(--info-soft); color: var(--info-ink); }

.cov-endpoints { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.cov-endpoint {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 8px 10px; background: var(--surface-2); border-radius: var(--radius-sm);
}
/* Le nom d'une source est un nom, pas un identifiant technique : il se lit dans la même
   typographie que le reste de la page. La chasse fixe le faisait passer pour du code. */
.cov-endpoint__key { font-size: 0.88rem; font-weight: 600; color: var(--text); }
.cov-endpoint__meta { font-size: 0.8rem; color: var(--text-muted); margin-left: auto; }
.cov-run { font-size: 0.75rem; font-weight: 700; }
.cov-run--ok { color: var(--trust); }
.cov-run--bad { color: var(--danger); }
.cov-run--warn { color: var(--warn-ink); }
.cov-run--muted { color: var(--text-faint); }
.cov-flag { color: var(--accent-ink); font-weight: 700; }

/* A wide table scrolls inside its own box; it must never widen the page under it. The
   `minmax(0, …)` columns and `min-width: 0` are what actually allow that: a grid or flex item
   refuses to shrink below its content's min-width by default, and one dense table was enough
   to push every page on a phone sideways. */
.cov-table-wrap { overflow-x: auto; min-width: 0; }
.coverage-list { grid-template-columns: minmax(0, 1fr); }
.coverage-card, .coverage-block, .coverage-table-wrapper { min-width: 0; }
.cov-endpoints { grid-template-columns: minmax(0, 1fr); }
.cov-endpoint, .cov-endpoint > * { min-width: 0; overflow-wrap: anywhere; }
/* A scope badge listing a dozen départements is a sentence, not a chip: it has to wrap.
   `nowrap` on it was enough to push the whole page sideways on a phone. */
.cov-endpoint .cov-badge { white-space: normal; }
.cov-table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
.cov-table th, .cov-table td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--border); }
.cov-table th { color: var(--text-faint); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; }
.cov-table tbody tr:last-child td { border-bottom: none; }

/* scenario-screen sober summary */
.coverage-summary {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px 18px; margin: 18px 0; box-shadow: var(--shadow-sm);
}
.coverage-summary__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.cs-item { display: flex; flex-direction: column; gap: 3px; }
.cs-value { font-size: 0.92rem; color: var(--text); }
.cs-badges { display: flex; flex-wrap: wrap; gap: 6px; }
/* The qualifier under each figure. It is not decoration: every one of these four numbers
   means less than it looks like, and the line underneath is where that is said. */
.cs-sub { display: block; margin-top: 2px; font-size: 0.76rem; line-height: 1.35; color: var(--text-faint); }
/* The one statement the figures above cannot make, given the weight of a full-width line. */
.coverage-market {
  margin: 14px 0 0; padding: 10px 12px; font-size: 0.86rem; line-height: 1.45;
  color: var(--text); background: var(--warn-soft);
  border-left: 3px solid var(--warn); border-radius: 0 var(--radius) var(--radius) 0;
}
.coverage-details { margin-top: 12px; }
.coverage-details > summary {
  cursor: pointer; font-size: 0.8rem; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: 0.03em;
}
.coverage-details-body { margin-top: 8px; font-size: 0.86rem; color: var(--text); }
.coverage-details-body p { margin: 6px 0; }
.coverage-details-body .cs-label { display: block; }

@media (max-width: 640px) {
  .coverage-grid { grid-template-columns: 1fr; }
  .cov-endpoint__meta { margin-left: 0; width: 100%; }
}


/* ---- Bandeau de decision (detail d'un scenario) -------------------------
   The page opens on what has to be decided, not on how the collection went. */
.decision-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1.5rem 2rem;
  padding: 0.8rem 1.1rem 0.85rem;
  margin-bottom: 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.ds-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
/* The three actionable counters are links: the number opens the list it counts. They keep
   the strip's typography rather than looking like body links. */
a.ds-item {
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius);
}
a.ds-item:hover .ds-l,
a.ds-item:focus-visible .ds-l {
  color: var(--text);
  text-decoration: underline;
}
.ds-n {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.ds-l {
  font-size: 0.78rem;
  color: var(--text-muted);
}
.ds-primary .ds-n {
  font-size: 2.1rem;
}
/* Attention is carried by weight and a label, never by colour alone. */
.ds-accent .ds-n {
  color: var(--accent-ink);
}
.ds-muted .ds-n {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text-muted);
}
.ds-note {
  flex: 1 1 100%;
  margin: 0.1rem 0 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* ---- Panneau technique replie ------------------------------------------ */
.technical-panel {
  margin-top: 2.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.technical-panel > summary {
  cursor: pointer;
  padding: 0.85rem 1.1rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem;
  list-style: none;
}
.technical-panel > summary::-webkit-details-marker {
  display: none;
}
.technical-panel > summary::before {
  content: "▸";
  color: var(--text-muted);
  font-size: 0.8rem;
}
.technical-panel[open] > summary::before {
  content: "▾";
}
.tp-title {
  font-weight: 600;
}
.tp-hint {
  font-size: 0.78rem;
  color: var(--text-muted);
}
.technical-panel-body {
  padding: 0 1.1rem 1.1rem;
}
.technical-panel-body .scenario-panels {
  margin-top: 0;
}

@media (max-width: 640px) {
  .decision-strip {
    gap: 0.9rem 1.5rem;
  }
  .ds-primary .ds-n {
    font-size: 1.7rem;
  }
  .ds-n {
    font-size: 1.3rem;
  }
}

.filters-count {
  margin-left: auto;
  align-self: center;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* ---- Comparaison des retenues -----------------------------------------
   A table a reader can hold in their head: four columns at most, empty cells left
   empty, and the highlighted cell earned by being the best *known* value. */
.comparison-rule {
  max-width: 68ch;
  color: var(--text-muted);
  font-size: 0.92rem;
  margin: 0 0 1.2rem;
}
.comparison-picker {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  margin-bottom: 1.2rem;
  box-shadow: var(--shadow-sm);
}
.comparison-picker-label {
  margin: 0 0 0.6rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-faint);
}
.comparison-picker-items {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 0.5rem 1.2rem;
  margin-bottom: 0.9rem;
}
.comparison-pick {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  font-size: 0.9rem;
  min-width: 0;
}
.comparison-pick-meta {
  display: block;
  color: var(--text-muted);
  font-size: 0.8rem;
}
.comparison-note {
  color: var(--warn-ink);
  font-size: 0.86rem;
  margin: 0 0 0.9rem;
}
/* Wide tables scroll inside their own box, never the page. */
.comparison-wrap {
  overflow-x: auto;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.comparison-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.comparison-table th,
.comparison-table td {
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
  font-variant-numeric: tabular-nums;
}
.comparison-table thead th {
  font-size: 0.86rem;
  color: var(--text);
  border-bottom: 2px solid var(--border-strong);
}
.comparison-table tbody th {
  color: var(--text-muted);
  font-weight: 600;
  white-space: nowrap;
}
.comparison-table tbody tr:last-child th,
.comparison-table tbody tr:last-child td {
  border-bottom: none;
}
.comparison-table td.cmp-best {
  background: var(--trust-soft);
  color: var(--trust-ink);
  font-weight: 600;
}
.comparison-caveat {
  margin: 0.8rem 0 0;
  font-size: 0.82rem;
  font-style: italic;
  color: var(--text-muted);
  max-width: 72ch;
}
.compare-entry {
  margin: 0 0 1rem;
}

/* ---- Avancement d'une cession -----------------------------------------
   Only a business-transfer scenario shows this: a house is examined, retained or set
   aside, and nothing more. */
.pipeline {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.6rem 0 0.2rem;
  flex-wrap: wrap;
}
.pipeline-label {
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-faint);
}
.pipeline select {
  font-family: inherit;
  font-size: 0.86rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--text);
  min-width: 0;
  max-width: 100%;
}
.badge.stage {
  background: var(--cess-soft);
  color: var(--cess-ink);
  border-color: transparent;
}

/* ---- Pourquoi cette annonce -------------------------------------------
   The deterministic justification: the scenario's criteria against the values the
   source published. Present with or without an AI — which is the point. */
.why {
  margin: 0.6rem 0 0.2rem;
  border-top: 1px solid var(--border);
  padding-top: 0.5rem;
}
.why > summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--text-muted);
}
.why-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.3rem;
}
.why-list li {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  font-size: 0.84rem;
  flex-wrap: wrap;
}
.why-label {
  min-width: 6.5rem;
  color: var(--text-faint);
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.why-detail {
  color: var(--text);
  min-width: 0;
}
.why-met .why-detail { color: var(--trust-ink); }
.why-unmet .why-detail { color: var(--danger); }
.why-unknown .why-detail { color: var(--text-muted); font-style: italic; }
.why-note {
  margin: 0.5rem 0 0;
  font-size: 0.76rem;
  color: var(--text-faint);
}

/* Archived searches: present, quiet, and one click from coming back. */
.archived-block {
  margin-top: 1.5rem;
  border-top: 1px solid var(--border);
  padding-top: 0.8rem;
}
.archived-block > summary {
  cursor: pointer;
  font-size: 0.86rem;
  color: var(--text-muted);
}
.archived-list {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
}
.archived-list li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  font-size: 0.92rem;
}
.archived-note {
  margin: 0.7rem 0 0;
  font-size: 0.8rem;
  color: var(--text-faint);
}

/* ---- Fiche d'une annonce -----------------------------------------------
   La page où une décision se prend : ce que la source publie à gauche, la décision
   à droite, le technique replié. Aucune requête réseau supplémentaire vers la source. */
.listing-page {
  max-width: 1100px;
}
.listing-page-head {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-bottom: 1.1rem;
}
.listing-page-head h1 {
  margin: 0.1rem 0 0;
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  max-width: 40ch;
}
.listing-page-head .nature-badge {
  align-self: flex-start;
}
.listing-page-place {
  margin: 0;
  color: var(--text-muted);
}
.listing-page-price {
  margin: 0.2rem 0 0;
  font-family: var(--serif);
  font-size: 1.9rem;
  font-variant-numeric: tabular-nums;
}
.listing-gallery-grid {
  display: grid;
  /* `auto-fit` collapses the track to the full width when a listing has a single thumbnail,
     and a 480×360 file stretched to 1 140 px is a blurred photograph presented as the real
     one. `auto-fill` keeps the cells at their intended size whatever the count. */
  grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
  gap: 0.6rem;
  margin-bottom: 0.5rem;
  max-width: 46rem;
}
.listing-gallery-grid img {
  width: 100%;
  height: 230px;
  object-fit: contain;
  border-radius: var(--radius);
  background: var(--surface-2);
}
.listing-gallery-note {
  margin: 0 0 1.2rem;
  font-size: 0.84rem;
  color: var(--text-muted);
}
.listing-page-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}
.listing-page-main > section,
.listing-page-side > section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  margin-bottom: 1rem;
  box-shadow: var(--shadow-sm);
}
.listing-page .section-title {
  margin: 0 0 0.7rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
}
.listing-description p {
  margin: 0;
  max-width: 68ch;
  line-height: 1.6;
}
/* On the listing page the justification is open: this is where it is read. */
.why--open {
  border-top: none;
  padding-top: 1rem;
}
.decision-box .listing-actions {
  margin-top: 0.6rem;
}
.decision-box .action-state {
  margin: 0.5rem 0 0;
  font-size: 0.8rem;
  color: var(--text-faint);
}
.price-history-block .price-history {
  margin: 0;
}

@media (max-width: 860px) {
  .listing-page-grid {
    grid-template-columns: 1fr;
  }
}
/* La liste courte : gardée, pas en attente — un ton distinct des files de décision. */
.ds-shortlist .ds-n { color: var(--favorite); }
.scenario-stats a.retained-count {
  font-weight: 600;
  color: var(--favorite);
}

/* --- Aperçu des critères ------------------------------------------------- */
/* A reading aid attached to the form: it must look like an answer, not like a
   result list, so it stays quiet and never competes with the fields above it. */
.criteria-preview__lead {
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
}
.criteria-preview__lead--empty {
  color: var(--text-muted);
}
.criteria-preview__note {
  display: block;
  color: var(--text-muted);
  font-size: 0.82rem;
}
.criteria-preview__costs {
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}
.criteria-preview__costs li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}
.criteria-preview__label {
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.criteria-preview__count {
  font-variant-numeric: tabular-nums;
}
.criteria-preview__unknown {
  color: var(--text-muted);
  font-size: 0.82rem;
}
.criteria-preview__zone {
  margin: 0.4rem 0 0;
  font-size: 0.88rem;
}

/* --- Récapitulatif imprimable -------------------------------------------- */
.print-head h1 {
  margin-bottom: 0.2rem;
}
.print-meta {
  margin: 0.1rem 0;
  color: var(--text-muted);
  font-size: 0.88rem;
}
.print-listing {
  margin: 1.4rem 0;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--border);
}
.print-listing h2 {
  margin: 0 0 0.2rem;
  font-size: 1.15rem;
}
.print-listing h3 {
  margin: 0.9rem 0 0.3rem;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.print-reasons {
  display: grid;
  grid-template-columns: minmax(6rem, max-content) 1fr;
  gap: 0.2rem 0.8rem;
  margin: 0;
}
.print-reasons dt {
  color: var(--text-muted);
  font-size: 0.85rem;
}
.print-reasons dd {
  margin: 0;
}
.print-history {
  margin: 0;
  padding-left: 1.1rem;
  font-variant-numeric: tabular-nums;
}
.print-url {
  margin: 0.6rem 0 0;
  font-size: 0.78rem;
  color: var(--text-muted);
  word-break: break-all;
}
.print-footer {
  margin-top: 1.5rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.8rem;
}

@media print {
  /* Nothing that cannot be acted on from paper survives: menus, buttons, filters, links
     styled as controls. What is left is the content and the reminder at the bottom. */
  .site-header,
  .site-nav,
  .no-print,
  .filters,
  .filter-form,
  .form-actions,
  .btn,
  button,
  details.technical-panel {
    display: none !important;
  }
  body {
    background: #fff;
    color: #000;
  }
  .print-listing {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  /* Repeated on every sheet: a printout gets separated from its first page. */
  .print-footer {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: #fff;
    border-top: 1px solid #999;
  }
  @page {
    margin: 14mm 12mm 22mm;
  }
}

/* --- Données insuffisantes -------------------------------------------------
   Kept, shown apart, never in front of someone as work. */
.insufficient-block {
  margin-top: var(--space-6);
}
.insufficient-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  max-width: var(--measure);
}
.insufficient-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--step--1);
}
.insufficient-source {
  color: var(--text-muted);
}
/* --- Primitives du design system ------------------------------------------
   Written once, used by every screen. Anything a screen needs that is not
   here is a gap in the system, not a licence to invent a local style.
   ------------------------------------------------------------------------ */

/* An eyebrow: the small capitalised label above a value or a block. */
.ds-label {
  display: block;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* A page's leading sentence. Kept to a comfortable reading width — a line of
   140 characters is not read, it is skimmed and lost. */
.ds-lede {
  max-width: var(--measure);
  color: var(--text-muted);
  font-size: var(--step-1);
  line-height: 1.5;
  margin: 0 0 var(--space-5);
}

/* Sections: one rhythm for every screen. */
.ds-section {
  margin: 0 0 var(--space-6);
}
.ds-section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.ds-section__head h2,
.ds-section__head h3 {
  margin: 0;
}

/* A card: the one container. Everything that groups content uses it, so a
   screen never looks like three unrelated widgets stacked. */
.ds-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.ds-card--quiet {
  background: var(--surface-2);
  box-shadow: none;
}

/* Statistic: a number that is meant to be read across the room, with the word
   that gives it meaning underneath. */
.ds-stat {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.ds-stat__value {
  font-family: var(--serif);
  font-size: var(--step-4);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.ds-stat__label {
  font-size: var(--step--1);
  color: var(--text-muted);
}
.ds-stat--attention .ds-stat__value {
  color: var(--accent-ink);
}

/* Badges: one shape, meanings by modifier. Never more than two on a card —
   a row of badges is a decision nobody made. */
.ds-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.02em;
  background: var(--surface-2);
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.ds-badge--new {
  background: var(--badge-new-bg);
  color: var(--badge-new-ink);
  border-color: transparent;
}
.ds-badge--good {
  background: var(--success-soft);
  color: var(--success);
  border-color: transparent;
}
.ds-badge--watch {
  background: var(--warn-soft);
  color: var(--warn-ink);
  border-color: transparent;
}
.ds-badge--info {
  background: var(--info-soft);
  color: var(--info-ink);
  border-color: transparent;
}

/* An empty state is a screen too: it says what is missing and what to do,
   never "no data". */
.ds-empty {
  display: grid;
  gap: var(--space-3);
  justify-items: start;
  padding: var(--space-6);
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  color: var(--text-muted);
  max-width: var(--measure);
}
.ds-empty__title {
  font-family: var(--serif);
  font-size: var(--step-1);
  color: var(--text);
  margin: 0;
}
.ds-empty p {
  margin: 0;
}

/* A folded technical panel: kept, never first. */
.ds-fold > summary {
  cursor: pointer;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: var(--space-2) 0;
}
.ds-fold > summary::marker {
  color: var(--text-faint);
}
.ds-fold[open] > summary {
  margin-bottom: var(--space-3);
}

/* Keyboard focus is visible everywhere, on one ring. */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent-green);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Accueil décisionnel --------------------------------------------------- */
.home-head {
  margin: 0 0 var(--space-6);
}
.home-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.home-alerts ul {
  list-style: none;
  margin: 0;
  padding: var(--space-4) var(--space-5);
  background: var(--warn-soft);
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  color: var(--warn-ink);
  display: grid;
  gap: var(--space-2);
  max-width: var(--measure);
}
.opp-note {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
}

/* Les trois files de décision, sous le titre de l'accueil. Un nombre à zéro reste
   affiché mais s'efface : « rien ici » est une information, pas une case vide. */
.decision-queues {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  list-style: none;
  margin: var(--space-5) 0 0;
  padding: 0;
}

.dq {
  display: flex;
  flex-direction: column;
  gap: 0.15em;
}

.dq-n {
  font-family: var(--serif);
  font-size: var(--step-3);
  line-height: 1;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.dq--live .dq-n {
  color: var(--accent);
}

.dq-l {
  font-size: var(--step--1);
  color: var(--text-muted);
}

/* Ce qui manque à une annonce, dit à côté de ce qu'elle a — jamais en rouge d'alerte :
   une donnée absente n'est pas une erreur du lecteur. */
.listing-quality {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
  color: var(--text-muted);
  font-size: var(--step--1);
}

@media print {
  /* Sur papier, le cadre de défilement n'a plus de raison d'être : ni ombre, ni bordure,
     ni coupe — le tableau doit s'imprimer entier. */
  .comparison-wrap {
    overflow: visible;
    background: none;
    border: 0;
    box-shadow: none;
    border-radius: 0;
  }
}

/* Un texte réservé aux lecteurs d'écran : présent dans le document, hors de l'écran.
   Sert partout où une information n'est portée que par la couleur ou la position. */
.visually-hidden {
  /* Reste dans le flux, exprès. En `position: absolute`, ce texte n'est plus découpé par un
     cadre de défilement dont l'ancêtre n'est pas positionné : placé dans un tableau large, il
     étirait la page entière de 45 px à 390 px de large. Mesuré, puis corrigé ainsi. */
  display: inline-block;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  vertical-align: middle;
}
/* « Affiner » : les trois barres de raffinement sous un seul repli, qui s'ouvre de lui-même
   dès qu'un raffinement est actif — la page ne cache jamais un filtre en train d'agir. */
.refine-block {
  margin: var(--space-3) 0 var(--space-4);
}

.refine-block > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.refine-block .quick-filters {
  margin-top: var(--space-3);
}

.filters-count a {
  color: inherit;
}

/* Un zéro reste lisible et cesse de crier : la file vide est une information, pas une
   nouvelle. Les nombres qui comptent vraiment gardent l'encre. */
.ds-item.ds-zero .ds-n,
.ds-item.ds-zero .ds-l {
  /* Une couleur explicite, jamais une opacité sur du texte : baisser l'opacité fait chuter
     le contraste sans que rien ne le dise. Ce ton est mesuré à 6,2:1 sur la surface. */
  color: var(--text-muted);
}

/* Le repli « Affiner » doit se voir comme un dépliant, pas comme un titre mort. */
.refine-block > summary::after {
  content: "▾";
  font-size: var(--step--1);
  transition: transform 120ms ease;
}

.refine-block[open] > summary::after {
  transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .refine-block > summary::after {
    transition: none;
  }
}

/* ==========================================================================
   RADAR IMMO — le système visuel des maquettes
   Rail vert profond pleine hauteur, surface de travail large, titres serif
   éditoriaux, lignes horizontales généreuses. Tout ce qui suit est préfixé
   `rd-` : aucune collision avec les composants antérieurs.
   ========================================================================== */

:root {
  /* Le rail : un anthracite légèrement bleuté, qui laisse la couleur principale
     au contenu. La masse verte occupait un quart de l'écran en permanence. */
  --rail: #1C2430;
  --rail-2: #232C3A;
  --rail-ink: #EEF1F5;
  --rail-ink-quiet: #A3ACB8;
  --rail-active: rgba(255, 255, 255, 0.11);
  /* Le rail garde sa proportion : sur une fenêtre très large, une largeur fixe le réduit à
     un filet, et le texte de l'interface devient illisible. */
  --rail-w: clamp(268px, 15.5vw, 400px);

  --rd-card: #FFFFFF;
  --rd-line: #E3E6EA;
  --rd-line-soft: #EEF1F4;
  --rd-ink: #1F2429;
  --rd-ink-2: #5A636C;
  --rd-ink-3: #6B747D;
  /* Le nom reste `green` — il est cité 40 fois — mais la couleur est désormais le
     bleu profond, seule couleur principale de l'interface. Renommer 40 usages pour
     une refonte de palette serait du bruit dans la revue. */
  --rd-green: #1B3A5C;
  --rd-green-ink: #22415F;
  --rd-green-pale: #E8EDF3;
  --rd-amber: #A8542F;
  --rd-amber-pale: #F7EAE4;
  --rd-radius: 12px;
  --rd-radius-sm: 8px;
  --rd-shadow: 0 1px 2px rgba(22, 34, 27, 0.04), 0 1px 12px rgba(22, 34, 27, 0.03);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --rd-card: #1B231E;
    --rd-line: #2C3730;
    --rd-line-soft: #232D27;
    --rd-ink: #ECEFE7;
    --rd-ink-2: #A8B2A6;
    --rd-ink-3: #94A093;
    --rd-green: #2C5580;
    --rd-green-ink: #9FC0E0;
    --rd-green-pale: #1D2836;
    --rd-amber: #D08A62;
    --rd-amber-pale: #2E2320;
  }
}

:root[data-theme="dark"] {
  --rd-card: #1B231E;
  --rd-line: #2C3730;
  --rd-line-soft: #232D27;
  --rd-ink: #ECEFE7;
  --rd-ink-2: #A8B2A6;
  --rd-ink-3: #94A093;
  --rd-green: #1E5C3F;
  --rd-green-ink: #8FCBA8;
  --rd-green-pale: #1B3227;
  --rd-amber: #E0B26B;
  --rd-amber-pale: #2E2517;
}

/* Toute l'échelle typographique suit la fenêtre : à 1 500 px on reste à 16 px, à 3 000 px le
   corps grandit au lieu de laisser une interface minuscule au milieu du vide. */
html { font-size: clamp(16px, 0.95vw, 23px); }

/* --- Le shell ------------------------------------------------------------- */

.rd-app {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  min-height: 100vh;
  background: var(--bg);
}

.rd-rail {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 26px 16px 20px;
  /* Couleur d'abord, dégradé ensuite : un fond qui n'existe que dans un dégradé disparaît
     partout où le dégradé ne s'applique pas, et le texte blanc devient illisible. */
  background-color: var(--rail);
  background-image: linear-gradient(180deg, var(--rail) 0%, var(--rail-2) 100%);
  color: var(--rail-ink);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.rd-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 8px 22px;
  color: var(--rail-ink);
}

.rd-brand:hover { text-decoration: none; }

.rd-brand__mark {
  width: 40px;
  height: 40px;
  flex: none;
  color: #C9A24A;
}

.rd-brand__mark svg { width: 100%; height: 100%; }

.rd-brand__name { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.rd-brand__title {
  font-family: var(--serif);
  font-size: 1.24rem;
  line-height: 1.12;
  letter-spacing: 0.035em;
  text-transform: uppercase;
  color: #FFFFFF;
}

.rd-brand__tag {
  font-size: 0.66rem;
  line-height: 1.35;
  color: #C9A24A;
}

.rd-nav { display: flex; flex-direction: column; gap: 3px; }

.rd-nav__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: 10px;
  color: var(--rail-ink);
  font-size: 0.97rem;
  font-weight: 450;
  line-height: 1.25;
}

.rd-nav__item:hover { background: rgba(255, 255, 255, 0.06); text-decoration: none; }

.rd-nav__item.is-active {
  background: var(--rail-active);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.rd-nav__item .rd-i { flex: none; opacity: 0.9; }

/* `flex: none` partout dans le rail, et c'est le correctif : le rail a une hauteur fixe
   (100vh) et `.rd-rail__foot` porte `margin-top: auto`. Quand la liste des recherches dépasse
   la fenêtre, des enfants rétractables se font comprimer — mesuré sur une fenêtre de 600 px :
   le groupe de navigation passait de 392 px à 133 px. Les liens débordaient alors de leur
   boîte comprimée, se peignaient par-dessus la carte « Notre rôle » et sous le bord du rail,
   et `overflow-y: auto` n'offrait que 50 px de défilement pour 259 px de contenu : sept
   entrées sur onze devenaient inatteignables. Des enfants à leur hauteur naturelle rendent
   au rail un vrai défilement. */
.rd-rail > * { flex: none; }

.rd-nav__group { margin-top: 22px; }

.rd-nav__label {
  margin: 0 0 8px 14px;
  font-size: 0.68rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--rail-ink-quiet);
}

.rd-nav__item--sub {
  padding: 8px 14px;
  font-size: 0.9rem;
  color: var(--rail-ink-quiet);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}

.rd-nav__item--sub.is-active { color: #FFFFFF; }

.rd-rail__foot { margin-top: auto; padding-top: 22px; display: grid; gap: 10px; }

.rd-rail__card {
  background: rgba(255, 255, 255, 0.07);
  border-radius: var(--rd-radius);
  padding: 14px 16px;
  font-size: 0.83rem;
  line-height: 1.5;
  color: var(--rail-ink-quiet);
}

.rd-rail__card p { margin: 0; }

.rd-rail__card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px;
  color: #FFFFFF;
  font-weight: 600;
  font-size: 0.9rem;
}

.rd-rail__card a { color: #FFFFFF; }

.rd-nav__item--quiet { color: var(--rail-ink-quiet); font-size: 0.9rem; }

/* --- La surface de travail ------------------------------------------------ */

.rd-main { min-width: 0; display: flex; flex-direction: column; }

.rd-page {
  flex: 1;
  min-width: 0;
  width: 100%;
  /* Aucun plafond de largeur : sur une fenêtre large, un `max-width` fixe produit exactement
     la colonne étroite perdue au milieu du vide que la refonte doit supprimer. Les marges
     grandissent avec la fenêtre, le contenu aussi. */
  padding: clamp(30px, 3vw, 60px) clamp(16px, 3vw, 64px) 80px;
}

.rd-topbar { display: none; }
.rd-scrim { display: none; }
.rd-drawer-toggle { display: none; }

/* --- En-tête d'écran ------------------------------------------------------ */

.rd-head {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 30px;
}

.rd-head__text { min-width: 0; flex: 1 1 420px; }

.rd-title {
  font-family: var(--serif);
  font-size: clamp(2.3rem, 3.2vw, 3.35rem);
  line-height: 1.04;
  letter-spacing: -0.015em;
  color: var(--rd-green-ink);
  margin: 0;
  text-wrap: balance;
}

.rd-subtitle {
  margin: 8px 0 0;
  font-size: 1.06rem;
  color: var(--rd-ink-2);
}

.rd-head__actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }

.rd-head__meta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--rd-ink-2);
  font-size: 0.94rem;
}

/* --- Boutons -------------------------------------------------------------- */

.rd-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 12px 20px;
  border-radius: 10px;
  border: 1px solid var(--rd-line);
  background: var(--rd-card);
  color: var(--rd-ink);
  font-family: var(--sans);
  font-size: 0.97rem;
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  text-align: center;
}

.rd-btn:hover { text-decoration: none; border-color: var(--border-strong); }

.rd-btn--primary {
  background: var(--rd-green);
  border-color: var(--rd-green);
  color: #FFFFFF;
  font-weight: 600;
}

.rd-btn--primary:hover { background: var(--trust-hover); border-color: var(--trust-hover); }

.rd-btn--wide { width: 100%; }

.rd-btn--sm { padding: 8px 14px; font-size: 0.88rem; }

/* --- Cartes et panneaux --------------------------------------------------- */

.rd-card {
  background: var(--rd-card);
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-shadow);
}

.rd-panel { padding: 22px 24px; }

.rd-label {
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rd-ink-3);
  font-weight: 600;
}

.rd-serif { font-family: var(--serif); }

/* --- Badges et puces ------------------------------------------------------ */

.rd-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: 8px;
  border: 1px solid var(--rd-line);
  background: var(--rd-card);
  font-size: 0.85rem;
  color: var(--rd-ink-2);
  white-space: nowrap;
}

.rd-chip--ok { background: var(--rd-green-pale); border-color: transparent; color: var(--rd-green-ink); }
.rd-chip--warn { background: var(--rd-amber-pale); border-color: transparent; color: var(--rd-amber); }
.rd-chip .rd-i { flex: none; }

.rd-tag {
  display: inline-block;
  padding: 5px 10px;
  border: 1px solid var(--rd-line);
  border-radius: 6px;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rd-ink-2);
  font-weight: 600;
}

/* --- Onglets -------------------------------------------------------------- */

.rd-tabs {
  display: flex;
  gap: 34px;
  border-bottom: 1px solid var(--rd-line);
  margin-bottom: 26px;
  overflow-x: auto;
  scrollbar-width: none;
}

.rd-tabs::-webkit-scrollbar { display: none; }

.rd-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 2px 14px;
  color: var(--rd-ink-2);
  font-size: 1.02rem;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
}

.rd-tab:hover { text-decoration: none; color: var(--rd-ink); }

.rd-tab.is-active {
  color: var(--rd-green-ink);
  font-weight: 600;
  border-bottom-color: var(--rd-green-ink);
}

.rd-tab__count {
  font-size: 0.82rem;
  color: var(--rd-ink-3);
  background: var(--rd-line-soft);
  border-radius: 999px;
  padding: 2px 8px;
}

/* --- La ligne d'opportunité, colonne vertébrale des maquettes -------------- */

.rd-rows { display: grid; gap: 14px; }

.rd-row {
  display: grid;
  grid-template-columns: clamp(260px, 22vw, 420px) minmax(0, 1fr) auto;
  align-items: stretch;
  padding: 14px;
  gap: 4px;
  background: var(--rd-card);
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-shadow);
  overflow: hidden;
}

/* `grid-template-rows: minmax(0, 1fr)` n'est pas une coquetterie : une hauteur posée par
   `min-height`/`max-height` seuls laisse la propriété `height` à `auto`, et un `height: 100%`
   d'enfant se résout alors en `auto` lui aussi. L'image reprenait sa hauteur intrinsèque —
   99 px dans un cadre de 96 — et l'`overflow: hidden` la recadrait par la bande : le
   recadrage revenait par la porte de derrière. Une piste de grille explicite donne à l'enfant
   une hauteur définie, et les pourcentages retrouvent un sens. */
.rd-row__photo {
  position: relative;
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  background: var(--rd-line-soft);
  min-height: clamp(190px, 13.5vw, 260px);
  border-radius: 10px;
  overflow: hidden;
}

/* `contain`, jamais `cover`. Une photographie immobilière recadrée perd exactement ce qu'on
   cherchait à voir : la façade sort du cadre, l'entrepôt devient un mur. Le fond neutre
   accueille le ratio qui ne remplit pas la vignette — on préfère une bande grise à une image
   tronquée, et l'image n'est jamais étirée. */
/* `max-height`, et non `height: 100%`. La différence n'est pas cosmétique : la cellule d'une
   ligne dense n'a pas de hauteur définie, donc `height: 100%` se résolvait en `auto`, l'image
   reprenait sa hauteur intrinsèque — 99 px dans une case de 52 — et l'`overflow: hidden` du
   cadre la recadrait par la bande. Le recadrage revenait par la porte de derrière.

   Avec `max-*: 100%` et des dimensions `auto`, l'image entre entière dans le cadre, garde son
   ratio, et n'est jamais étirée. Le fond neutre accueille ce qui reste. */
.rd-row__photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Toute la vignette est cliquable : au clic, la fiche et sa galerie en entier. */
.rd-row__photo-lien {
  display: block;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
}

.rd-row__photo-lien:focus-visible { outline: 2px solid var(--trust); outline-offset: -2px; }

/* Une annonce sans photo garde exactement la même structure et la même hauteur : un aplat
   sobre, une icône discrète, une phrase honnête — jamais un grand rectangle gris dominant. */
.rd-nophoto {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px;
  text-align: center;
  background:
    repeating-linear-gradient(-45deg, var(--rd-line-soft) 0 10px, var(--rd-card) 10px 20px);
  color: var(--rd-ink-3);
  font-size: 0.8rem;
}

.rd-row__body { padding: 8px 24px; display: flex; flex-direction: column; gap: 10px; min-width: 0; }

.rd-row__price {
  font-family: var(--serif);
  font-size: 1.85rem;
  line-height: 1.1;
  color: var(--rd-ink);
  font-variant-numeric: tabular-nums;
  margin: 0;
}

.rd-row__title {
  font-family: var(--serif);
  font-size: 1.3rem;
  line-height: 1.25;
  color: var(--rd-ink);
  margin: 0;
}

.rd-row__title a { color: inherit; }

.rd-facts {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  color: var(--rd-ink-2);
  font-size: 0.95rem;
}

.rd-fact { display: inline-flex; align-items: center; gap: 8px; }
.rd-fact + .rd-fact { border-left: 1px solid var(--rd-line); padding-left: 14px; }
.rd-fact .rd-i { color: var(--rd-ink-3); flex: none; }

.rd-meta { color: var(--rd-ink-2); font-size: 0.92rem; display: flex; gap: 18px; flex-wrap: wrap; }
.rd-meta strong { font-weight: 600; color: var(--rd-ink); }

.rd-note {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  background: var(--rd-green-pale);
  border-radius: 10px;
  padding: 13px 16px;
  color: var(--rd-ink-2);
  font-size: 0.94rem;
  line-height: 1.45;
}

.rd-note .rd-i { color: var(--rd-green-ink); flex: none; margin-top: 1px; }

.rd-row__actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 8px 8px 8px 22px;
  border-left: 1px solid var(--rd-line-soft);
  min-width: 212px;
  justify-content: center;
}

.rd-row__actions form { margin: 0; }
.rd-row__actions .rd-btn { width: 100%; justify-content: flex-start; }
.rd-row__actions .rd-btn--primary { font-weight: 600; justify-content: center; }
/* Sur l'accueil, la flèche part à droite du bouton, comme dans la maquette. */
.rd-row--inbox .rd-row__actions .rd-btn--primary { justify-content: space-between; }

/* --- Cartes de scénario (rangée de l'accueil) ------------------------------ */

.rd-scenarios {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(clamp(178px, 13vw, 260px), 1fr);
  gap: 14px;
  margin-bottom: 26px;
  overflow-x: auto;
  padding-bottom: 4px;
}

.rd-scenario {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 20px 16px 18px;
  min-height: 232px;
  justify-content: space-between;
  background: var(--rd-card);
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  text-align: center;
  color: var(--rd-ink);
  min-width: 0;
}

.rd-scenario:hover { text-decoration: none; border-color: var(--border-strong); }

.rd-scenario__name {
  font-family: var(--serif);
  font-size: 1.02rem;
  line-height: 1.25;
  color: var(--rd-ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.5em;
}

.rd-scenario__art { color: var(--rd-line); }
.rd-scenario__art svg { width: 88px; height: 56px; }

.rd-scenario__n {
  font-family: var(--serif);
  font-size: 1.7rem;
  line-height: 1;
  color: var(--rd-green-ink);
  font-variant-numeric: tabular-nums;
}

.rd-scenario__l { font-size: 0.82rem; color: var(--rd-ink-3); }

/* --- États vides et repli ------------------------------------------------- */

.rd-empty {
  background: var(--rd-card);
  border: 1px dashed var(--border-strong);
  border-radius: var(--rd-radius);
  padding: 44px 32px;
  text-align: center;
  color: var(--rd-ink-2);
}

.rd-empty__title {
  font-family: var(--serif);
  font-size: 1.35rem;
  color: var(--rd-ink);
  margin: 0 0 8px;
}

.rd-fold {
  background: var(--rd-card);
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  margin-top: 26px;
}

.rd-fold > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 22px;
  cursor: pointer;
  font-weight: 500;
  color: var(--rd-ink);
  list-style: none;
}

.rd-fold > summary::-webkit-details-marker { display: none; }
.rd-fold > summary::after { content: "⌄"; margin-left: auto; color: var(--rd-ink-3); font-size: 1.1rem; }
.rd-fold[open] > summary::after { content: "⌃"; }
.rd-fold__body { padding: 0 22px 22px; }

/* --- Mobile : le rail devient un tiroir ------------------------------------ */

@media (max-width: 900px) {
  .rd-app { grid-template-columns: minmax(0, 1fr); }

  .rd-rail {
    position: fixed;
    z-index: 40;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(86vw, 320px);
    transform: translateX(-102%);
    transition: transform 0.22s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.25);
  }

  .rd-drawer-toggle:checked ~ .rd-rail { transform: translateX(0); }

  .rd-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 30;
    background: rgba(12, 20, 15, 0.45);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s ease;
  }

  .rd-drawer-toggle:checked ~ .rd-main .rd-scrim { opacity: 1; pointer-events: auto; }

  .rd-topbar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--rd-card);
    border-bottom: 1px solid var(--rd-line);
    position: sticky;
    top: 0;
    z-index: 20;
  }

  .rd-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    border: 1px solid var(--rd-line);
    color: var(--rd-ink);
    cursor: pointer;
  }

  .rd-topbar__title {
    font-family: var(--serif);
    font-size: 1.05rem;
    color: var(--rd-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .rd-topbar .rd-btn { margin-left: auto; }

  .rd-page { padding: 20px 16px 56px; }

  .rd-row { grid-template-columns: minmax(0, 1fr); }
  .rd-row__photo { min-height: 190px; }
  .rd-row__actions {
    border-left: 0;
    border-top: 1px solid var(--rd-line-soft);
    flex-direction: row;
    flex-wrap: wrap;
    min-width: 0;
  }
  .rd-row__actions .rd-btn { width: auto; flex: 1 1 130px; justify-content: center; }
  .rd-scenarios { grid-auto-columns: minmax(150px, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .rd-rail, .rd-scrim { transition: none; }
}

/* --- Écran de scénario ---------------------------------------------------- */

.rd-listcount {
  margin: -10px 0 18px;
  color: var(--rd-ink-2);
  font-size: 0.94rem;
}

.rd-listcount a { color: inherit; }

/* Les proportions des maquettes : un quart pour la photographie, la moitié pour ce qui
   décide, un cinquième pour la décision elle-même. */
.rd-row--opportunity {
  grid-template-columns: minmax(240px, 25%) minmax(0, 1fr) clamp(200px, 21%, 300px);
}

.rd-fact__l {
  display: block;
  font-size: 0.76rem;
  color: var(--rd-ink-3);
  line-height: 1.2;
}

.rd-fact strong { font-weight: 600; color: var(--rd-ink); }

.rd-meta--quiet { color: var(--rd-ink-3); font-size: 0.9rem; align-items: center; }
.rd-meta--quiet .rd-i { vertical-align: -3px; }
.rd-drop { color: var(--rd-green-ink); }

.rd-chips { display: flex; flex-wrap: wrap; gap: 10px; }
.rd-chips a.rd-chip:hover { text-decoration: none; border-color: var(--border-strong); }

.rd-price-block { text-align: right; margin-bottom: 4px; }
.rd-price-block__l { margin: 0; font-size: 0.86rem; color: var(--rd-ink-2); }
.rd-price-block__n {
  margin: 2px 0 0;
  font-family: var(--serif);
  font-size: 1.6rem;
  line-height: 1.1;
  color: var(--rd-ink);
  font-variant-numeric: tabular-nums;
}
.rd-price-block__s { margin: 2px 0 0; font-size: 0.84rem; color: var(--rd-ink-3); }

.rd-fold--refine { margin: 0 0 22px; }

.rd-target { margin-top: 26px; padding: 20px 24px; }
.rd-target__head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  font-family: var(--serif);
  font-size: 1.1rem;
  color: var(--rd-ink);
}
.rd-target__items { display: flex; flex-wrap: wrap; gap: 14px 34px; }

.rd-row__subtitle {
  margin: 0;
  font-family: var(--serif);
  font-size: 1.06rem;
  font-weight: 400;
  line-height: 1.3;
  color: var(--rd-ink-2);
}

.rd-row__subtitle a { color: inherit; }

.rd-fold__h {
  font-family: var(--serif);
  font-size: 1.05rem;
  color: var(--rd-ink);
  margin: 6px 0 12px;
}

.rd-fold--inner { margin: 18px 0; }

/* La note IA : une pastille à place fixe, en haut à droite de la ligne. */
.rd-row { position: relative; }

.rd-score {
  position: absolute;
  top: 22px;
  right: 22px;
  z-index: 2;
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  padding: 5px 10px;
  border-radius: 8px;
  background: var(--rd-green-pale);
  color: var(--rd-green-ink);
  font-size: 0.82rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.rd-score .v { font-size: 1.05rem; }
.rd-score .u { opacity: 0.8; font-weight: 500; }
.rd-score--none { background: var(--rd-line-soft); color: var(--rd-ink-3); }

.rd-why-fold > summary {
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--rd-green-ink);
  list-style: none;
}

.rd-why-fold > summary::-webkit-details-marker { display: none; }
.rd-why-fold > summary::before { content: "⌄ "; }
.rd-why-fold[open] > summary::before { content: "⌃ "; }

.rd-why-list {
  list-style: none;
  margin: 10px 0 6px;
  padding: 0;
  display: grid;
  gap: 6px;
  font-size: 0.92rem;
}

.rd-why-list li { display: flex; gap: 10px; color: var(--rd-ink-2); }
.rd-why-list__l { min-width: 9rem; color: var(--rd-ink-3); }
.rd-why-list .why-met { color: var(--rd-ink); }
.rd-why-list .why-unmet .rd-why-list__l { color: var(--rd-amber); }

.rd-btn--quiet { border-color: transparent; color: var(--rd-ink-3); background: none; }
.rd-btn--quiet:hover { background: var(--rd-line-soft); }

.rd-pipeline { display: grid; gap: 4px; }
.rd-pipeline select {
  font-family: var(--sans);
  font-size: 0.92rem;
  padding: 9px 10px;
  border: 1px solid var(--rd-line);
  border-radius: 8px;
  background: var(--rd-card);
  color: var(--rd-ink);
  width: 100%;
}

/* --- Accueil : la ligne d'inbox à quatre colonnes -------------------------- */

.rd-row--inbox {
  grid-template-columns:
    clamp(240px, 19vw, 380px) minmax(0, 1.15fr) minmax(0, 1fr) auto;
}

.rd-row__why {
  padding: 8px 24px;
  border-left: 1px solid var(--rd-line-soft);
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.rd-row__why .rd-label { color: var(--rd-green-ink); }

.rd-why__item {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  margin: 0;
  color: var(--rd-ink-2);
  font-size: 0.95rem;
  line-height: 1.45;
}

.rd-why__item .rd-i { flex: none; color: var(--rd-green-ink); margin-top: 2px; }

.rd-alerts .rd-why__item .rd-i { color: var(--rd-amber); }

.rd-fold--flat { margin-top: 18px; }
.rd-fold--flat .rd-fold__body { padding: 18px 22px; }

@media (max-width: 1100px) {
  .rd-row--inbox { grid-template-columns: clamp(220px, 26vw, 340px) minmax(0, 1fr); }
  .rd-row__why { border-left: 0; border-top: 1px solid var(--rd-line-soft); grid-column: 1 / -1; }
  .rd-row__actions { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--rd-line-soft); flex-direction: row; }
  .rd-row__actions .rd-btn { flex: 1 1 150px; justify-content: center; }
}

@media (max-width: 900px) {
  .rd-row--inbox { grid-template-columns: minmax(0, 1fr); }
}

/* --- La fiche d'une annonce ------------------------------------------------ */

.rd-back { margin: 0 0 14px; }
.rd-back a { color: var(--rd-ink-2); font-size: 0.94rem; display: inline-flex; gap: 8px; align-items: center; }
.rd-back .rd-i { transform: rotate(180deg); }

.rd-title--listing { font-size: clamp(2rem, 2.7vw, 2.9rem); }

.rd-detail {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, 0.85fr);
  gap: 22px;
  align-items: start;
}

.rd-detail__main, .rd-detail__side { display: grid; gap: 18px; min-width: 0; }

.rd-gallery { display: grid; gap: 12px; }

.rd-gallery__main {
  position: relative;
  border-radius: var(--rd-radius);
  overflow: hidden;
  background: var(--rd-line-soft);
  aspect-ratio: 16 / 10;
}

/* La galerie de la fiche suit la même règle que la liste : entière, jamais recadrée en
   silence. C'est là qu'on décide d'aller visiter ; y montrer une image amputée serait le
   pire endroit pour le faire. */
.rd-gallery__main img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  background: var(--rd-line-soft);
}

.rd-gallery__main--empty { display: grid; place-items: center; aspect-ratio: 16 / 7; }
.rd-gallery__main--empty .rd-nophoto { position: static; gap: 12px; }
.rd-gallery__detail { max-width: 46ch; }

.rd-gallery__count {
  position: absolute;
  top: 14px;
  left: 14px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: 8px;
  background: rgba(16, 26, 20, 0.72);
  color: #fff;
  font-size: 0.84rem;
}

.rd-gallery__strip { display: flex; gap: 10px; overflow-x: auto; }

.rd-gallery__strip img {
  width: clamp(110px, 12vw, 170px);
  aspect-ratio: 4 / 3;
  object-fit: contain;
  border-radius: 8px;
  border: 2px solid transparent;
  flex: none;
}

.rd-gallery__strip img.is-current { border-color: var(--rd-green); }

.rd-keyinfo { padding: 20px 24px; }
.rd-keyinfo__head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
  font-family: var(--serif);
  font-size: 1.1rem;
}
.rd-keyinfo__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 18px 22px;
}

.rd-prose { margin: 0; max-width: 72ch; color: var(--rd-ink-2); line-height: 1.6; }

.rd-stats { padding: 20px 24px; }
.rd-stats__row { display: flex; gap: 26px; flex-wrap: wrap; }
.rd-stat { flex: 1 1 130px; }
.rd-stat__n {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1.4rem, 1.7vw, 1.9rem);
  line-height: 1.1;
  color: var(--rd-ink);
  font-variant-numeric: tabular-nums;
}
.rd-stat__l { margin: 4px 0 0; font-size: 0.86rem; color: var(--rd-ink-3); }

.rd-history { margin-top: 18px; border-top: 1px solid var(--rd-line-soft); padding-top: 16px; }
.rd-history__head { display: flex; gap: 12px; align-items: flex-start; margin: 0 0 12px; }
.rd-history__icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: var(--rd-green-pale);
  color: var(--rd-green-ink);
  flex: none;
}
.rd-history__points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 22px;
  overflow-x: auto;
}
.rd-history__points li { display: grid; gap: 2px; white-space: nowrap; }
.rd-history__amount { font-weight: 600; font-variant-numeric: tabular-nums; }
.rd-history__date { font-size: 0.82rem; color: var(--rd-ink-3); }

.rd-panel { padding: 20px 24px; }
.rd-panel__title {
  margin: 0 0 14px;
  font-family: var(--serif);
  font-size: 1.15rem;
  color: var(--rd-ink);
}

.rd-reason { display: flex; gap: 12px; align-items: flex-start; margin: 0 0 14px; color: var(--rd-ink-2); }
.rd-reason:last-child { margin-bottom: 0; }
.rd-reason strong { color: var(--rd-ink); font-weight: 600; }
.rd-reason__mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--rd-green);
  color: #fff;
  flex: none;
}
.rd-reason--warn .rd-reason__mark { background: var(--rd-amber-pale); color: var(--rd-amber); }

@media (max-width: 1100px) {
  .rd-detail { grid-template-columns: minmax(0, 1fr); }
}

/* --- Pipeline de cession --------------------------------------------------- */

.rd-steps {
  display: flex;
  gap: 6px;
  margin-bottom: 24px;
  overflow-x: auto;
  padding-bottom: 4px;
}

.rd-step {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 16px 26px 16px 30px;
  background: var(--rd-line-soft);
  color: var(--rd-ink-2);
  font-size: 0.97rem;
  white-space: nowrap;
  flex: 1 1 auto;
  justify-content: center;
  /* La flèche des maquettes : chaque étape pointe vers la suivante. */
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 0 100%, 18px 50%);
}

.rd-step:first-child { clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 0 100%); }
.rd-step:hover { text-decoration: none; color: var(--rd-ink); }

.rd-step.is-active {
  background: var(--rd-green-pale);
  color: var(--rd-green-ink);
  font-weight: 600;
}

.rd-step__n {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  height: 26px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--rd-green);
  color: #fff;
  font-size: 0.84rem;
  font-variant-numeric: tabular-nums;
}

.rd-board { display: grid; gap: 14px; }

.rd-board__head,
.rd-board__row {
  display: grid;
  grid-template-columns:
    minmax(220px, 1.25fr) minmax(200px, 1.1fr) minmax(160px, 0.9fr)
    minmax(150px, 0.8fr) minmax(190px, 0.9fr);
  gap: 22px;
}

.rd-board__head {
  padding: 0 22px;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rd-ink-3);
  font-weight: 600;
}

.rd-board__row {
  background: var(--rd-card);
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-shadow);
  padding: 20px 22px;
  align-items: start;
}

.rd-board__cell { min-width: 0; }
.rd-board__opportunity { display: flex; gap: 14px; }

.rd-board__mark {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  background: var(--rd-green-pale);
  color: var(--rd-green-ink);
  flex: none;
}

.rd-board__title {
  margin: 0 0 4px;
  font-family: var(--serif);
  font-size: 1.08rem;
  line-height: 1.3;
}

.rd-board__title a { color: var(--rd-ink); }

.rd-board__photo {
  margin-top: 10px;
  width: 100%;
  max-width: 240px;
  aspect-ratio: 16 / 10;
  object-fit: contain;
  border-radius: 8px;
}

.rd-board__data { margin: 0; display: grid; grid-template-columns: auto auto; gap: 6px 14px; }
.rd-board__data dt { color: var(--rd-ink-2); font-size: 0.92rem; }
.rd-board__data dd {
  margin: 0;
  text-align: right;
  font-weight: 600;
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
}

.rd-board__missing { margin: 0; padding-left: 18px; color: var(--rd-ink-2); font-size: 0.92rem; }
.rd-board__missing li { margin-bottom: 5px; }

.rd-board__source p { margin: 0 0 4px; font-size: 0.92rem; }
.rd-board__next { display: grid; gap: 10px; }
.rd-listcount--foot { text-align: center; margin: 22px 0 0; }

@media (max-width: 1200px) {
  .rd-board__head { display: none; }
  .rd-board__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

@media (max-width: 700px) {
  .rd-board__row { grid-template-columns: minmax(0, 1fr); }
}

/* --- Comparateur ----------------------------------------------------------- */

.rd-picker__items {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.rd-picker__item { display: flex; gap: 10px; align-items: flex-start; font-size: 0.94rem; }
.rd-picker__item span { display: grid; gap: 2px; }

.rd-matrix-wrap {
  overflow-x: auto;
  background: var(--rd-card);
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-shadow);
}

/* Colonnes de largeur égale, comme la maquette : sinon chaque colonne suit la longueur de
   son texte et les photographies ne s'alignent plus. */
.rd-matrix { width: 100%; border-collapse: collapse; table-layout: fixed; min-width: 760px; }

.rd-matrix thead th {
  padding: 18px 20px;
  vertical-align: top;
  text-align: center;
  border-bottom: 1px solid var(--rd-line);
  min-width: 210px;
}

.rd-matrix thead th:first-child { min-width: 210px; width: 22%; }

.rd-matrix__name {
  display: block;
  font-family: var(--serif);
  font-size: 1.24rem;
  color: var(--rd-green-ink);
  margin-bottom: 12px;
}

.rd-matrix__photo { display: block; border-radius: 10px; overflow: hidden; background: var(--rd-line-soft); }
.rd-matrix__photo img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: contain;
  display: block;
  background: var(--rd-line-soft);
}
.rd-matrix__photo .rd-nophoto { position: static; aspect-ratio: 16 / 10; }

.rd-matrix tbody th {
  text-align: left;
  font-weight: 500;
  color: var(--rd-ink);
  padding: 16px 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--rd-line-soft);
}

.rd-matrix tbody th .rd-i { color: var(--rd-ink-3); flex: none; }

.rd-matrix tbody td {
  padding: 16px 20px;
  border-bottom: 1px solid var(--rd-line-soft);
  border-left: 1px solid var(--rd-line-soft);
  color: var(--rd-ink-2);
  vertical-align: middle;
  position: relative;
}

.rd-matrix tbody tr:last-child th,
.rd-matrix tbody tr:last-child td { border-bottom: 0; }

.rd-matrix td.is-best {
  background: var(--rd-green-pale);
  color: var(--rd-ink);
  font-weight: 600;
  box-shadow: inset 0 0 0 1px var(--rd-green);
}

.rd-matrix__best {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: var(--rd-green);
  color: #fff;
}

.rd-quickread {
  display: grid;
  grid-template-columns: minmax(180px, 0.28fr) minmax(0, 1fr);
  gap: 24px;
  align-items: center;
  margin-top: 20px;
  padding: 24px 28px;
}

.rd-quickread__mark {
  display: grid;
  justify-items: center;
  gap: 10px;
  color: var(--rd-green-ink);
  border-right: 1px solid var(--rd-line);
  padding-right: 20px;
}

.rd-quickread__mark .rd-serif { font-family: var(--serif); font-size: 1.5rem; color: var(--rd-green-ink); text-align: center; }
.rd-quickread__body p { margin: 0 0 8px; color: var(--rd-ink-2); max-width: 78ch; }

.rd-quickread__title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
  font-family: var(--serif);
  font-size: 1.28rem;
  color: var(--rd-ink);
}

.rd-quickread__title .rd-i { color: #fff; background: var(--rd-green); border-radius: 999px; padding: 6px; box-sizing: content-box; }

@media (max-width: 800px) {
  .rd-quickread { grid-template-columns: minmax(0, 1fr); }
  .rd-quickread__mark { border-right: 0; border-bottom: 1px solid var(--rd-line); padding: 0 0 16px; }
}

/* Une carte de projet : la ville, ce qui l'attend, et ses deux natures dessous. */
.rd-scenario--project { gap: 8px; }

.rd-scenario__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: inherit;
  width: 100%;
}

.rd-scenario__link:hover { text-decoration: none; }

.rd-scenario__natures {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding-top: 8px;
  border-top: 1px solid var(--rd-line-soft);
  font-size: 0.8rem;
}

.rd-scenario__natures a {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  color: var(--rd-ink-2);
  min-width: 0;
}

.rd-scenario__natures a > :first-child {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rd-scenario__natures strong { color: var(--rd-ink); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   Pertinence Stimcar, et la vérité sur les photographies.

   Trois niveaux, jamais une note sur cent : les données publiées n'ont pas
   cette précision, et un nombre la ferait croire. Le niveau se lit d'abord, la
   raison ensuite, le reste seulement si l'œil s'y arrête.
   --------------------------------------------------------------------------- */

.st-rel {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.6rem;
  padding: 0.35rem 0 0.5rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.5rem;
}

.st-rel__level {
  font-weight: 650;
  font-size: 0.82rem;
  letter-spacing: 0.01em;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
}

/* Une seule des trois se colore, et sobrement : la couleur sert à trier l'œil,
   pas à décorer trois lignes sur trois. */
.st-rel--tres_pertinent .st-rel__level {
  background: var(--trust-soft);
  color: var(--trust);
}

.st-rel__why {
  color: var(--text-muted);
  font-size: 0.86rem;
}

.st-rel__ok {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.82rem;
  color: var(--text-muted);
}

.st-rel__ok li::before {
  content: "· ";
  color: var(--border-strong);
}

/* Rouge uniquement ici : une incompatibilité publiée, pas une nuance. */
.st-rel__ko {
  margin: 0;
  font-size: 0.82rem;
  color: var(--danger);
}

.st-rel__todo {
  margin: 0;
  font-size: 0.82rem;
  color: var(--warn-ink);
}

/* Une annonce dont l'hébergeur d'images nous refuse la récupération n'est pas
   un bien sans photo : le cadre le dit, et renvoie là où elles sont. Il reste
   compact — deux tiers des lignes sont dans ce cas, un grand aplat vide
   remplirait l'écran de rien. */
.rd-nophoto--ailleurs {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  justify-content: center;
  padding: 0.4rem;
  font-size: 0.74rem;
  line-height: 1.25;
  color: var(--text-muted);
  text-align: center;
}

.st-lien-source {
  color: var(--trust);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--trust-soft);
}

.st-lien-source:hover,
.st-lien-source:focus-visible {
  border-bottom-color: var(--trust);
}

.st-filtres-note {
  margin: 0.4rem 0 0;
  font-size: 0.78rem;
  color: var(--text-faint);
}

.st-filtres-actifs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.st-filtres-actifs span {
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
}

.st-effacer {
  color: var(--trust);
  font-weight: 600;
}

/* Le panneau de filtres : fixe à l'écran, replié par défaut sur mobile, et
   réellement défilable — c'est la liste qui doit bouger sous lui, pas lui qui
   pousse la page. */
@media (min-width: 60rem) {
  .rd-fold--refine {
    position: sticky;
    top: 0.5rem;
    max-height: calc(100vh - 1.5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* Sur mobile la vignette rétrécit encore : une carte sans photo ne doit jamais
   être plus haute qu'une carte illustrée. */
@media (max-width: 40rem) {
  .rd-row__photo {
    max-height: 6rem;
  }

  .rd-nophoto--ailleurs {
    font-size: 0.7rem;
  }
}

/* ---------------------------------------------------------------------------
   Vue liste dense — l'affichage par défaut sur ordinateur.

   Deux tiers des lignes ne peuvent pas être illustrées : leur hébergeur d'images
   nous refuse la récupération. Une grille bâtie autour d'une grande photo
   remplit donc l'écran de rectangles vides, et rend une liste de plusieurs
   centaines de résultats impossible à parcourir. La photo devient une vignette,
   la ligne tient sur une hauteur qu'on balaye, et la pertinence occupe toute la
   largeur au-dessus des faits plutôt qu'une colonne.
   --------------------------------------------------------------------------- */

.rd-row--opportunity {
  grid-template-columns: 132px minmax(0, 1fr) auto;
  gap: 4px 14px;
  padding: 12px 14px;
}

/* La pertinence tient toute la largeur : c'est la première chose qu'on lit, et
   elle ne doit pas rétrécir les faits qu'elle qualifie. */
.rd-row--opportunity > .st-rel {
  grid-column: 1 / -1;
}

.rd-row--opportunity .rd-row__photo {
  min-height: 92px;
  max-height: 108px;
  align-self: start;
}

/* Un aplat vide n'a pas besoin de la hauteur d'une photographie : il n'apporte
   rien à cette hauteur-là. */
.rd-row--opportunity .rd-nophoto {
  font-size: 0.72rem;
  line-height: 1.2;
  padding: 0.35rem;
}

.rd-row--opportunity .rd-nophoto svg {
  width: 18px;
  height: 18px;
}

@media (max-width: 60rem) {
  /* Mobile : carte compacte, vignette en bandeau court — jamais un grand
     emplacement vide quand la photo est indisponible. */
  .rd-row--opportunity {
    grid-template-columns: minmax(0, 1fr);
  }

  .rd-row--opportunity .rd-row__photo {
    min-height: 84px;
    max-height: 96px;
  }
}

/* ---------------------------------------------------------------------------
   Densité réelle : 5 à 8 lignes visibles sur un écran d'ordinateur.

   Une ligne repliée doit suffire à décider d'ouvrir ou non : titre, commune,
   opération, prix, surfaces, pertinence, source, action principale. Tout le
   reste — raisons détaillées, informations manquantes, diffuseurs, opérations
   secondaires — attend le dépliage, qui existe déjà (« Pourquoi cette annonce »,
   « Détails »).

   La contrainte vient du volume : 855 lignes à Bordeaux, 820 à Toulouse. Deux
   lignes par écran font 400 défilements pour un balayage.
   --------------------------------------------------------------------------- */

.rd-row--opportunity {
  padding: 8px 12px;
  gap: 2px 12px;
  align-items: start;
}

.rd-row--opportunity .rd-row__photo {
  min-height: 96px;
  max-height: 96px;
}

.rd-row--opportunity .rd-row__title {
  font-size: 0.98rem;
  line-height: 1.25;
  margin: 0.1rem 0 0.15rem;
}

/* Le type de bien revient dans la ligne de faits : une pastille sur sa propre
   ligne coûtait 28 px par annonce pour trois mots. */
.rd-row--opportunity .rd-tag {
  font-size: 0.68rem;
  padding: 0.05rem 0.4rem;
}

.rd-row--opportunity .rd-row__body > p:first-child {
  margin: 0;
  display: inline-block;
}

.rd-row--opportunity .rd-meta,
.rd-row--opportunity .rd-facts {
  margin: 0.1rem 0;
  font-size: 0.82rem;
}

.rd-row--opportunity .rd-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.1rem 1rem;
}

/* Le bandeau de pertinence tient sur une ligne : le niveau, puis la raison —
   qui porte déjà le premier critère confirmé et le nombre à vérifier. Le détail
   par critère s'ouvre avec la ligne. */
.rd-row--opportunity .st-rel {
  padding: 0.2rem 0 0.3rem;
  margin-bottom: 0.3rem;
}

.rd-row--opportunity .st-rel__ok,
.rd-row--opportunity .st-rel__todo,
.rd-row--opportunity .st-rel__ko {
  display: none;
}

.rd-row--opportunity[open] .st-rel__ok,
.rd-row--opportunity[open] .st-rel__todo,
.rd-row--opportunity[open] .st-rel__ko {
  display: block;
}

/* Le prix garde sa force de repère sans occuper le tiers de la ligne. */
.rd-row--opportunity .rd-row__price,
.rd-row--opportunity .rd-row__actions__price {
  font-size: 1.15rem;
  line-height: 1.2;
}

/* Une seule action visible sur la ligne repliée ; la seconde reste accessible
   dans la fiche. Deux boutons empilés doublaient la hauteur du côté droit. */
.rd-row--opportunity .rd-row__actions > *:nth-child(n + 4) {
  display: none;
}

.rd-row--opportunity .rd-cta,
.rd-row--opportunity .rd-btn {
  padding: 0.4rem 0.7rem;
  font-size: 0.85rem;
}

.rd-row--opportunity .rd-why-fold summary,
.rd-row--opportunity .details-block > summary {
  font-size: 0.78rem;
  padding: 0.1rem 0;
}

/* Second passage sur la densité : la ligne repliée descendait encore à ~380 px,
   soit deux annonces par écran. Ce qui restait était surtout de la redite —
   « Pourquoi cette annonce » répète le bandeau de pertinence, « Changement
   détecté : Nouvelle » répète la pastille, et « Marquer examinée » est une
   action secondaire qui appartient à la fiche. Un seul repli subsiste,
   « Détails », qui porte diffuseurs, opérations et justification complète. */

.rd-row--opportunity .rd-why-fold,
.rd-row--opportunity .rd-row__body > .rd-meta--quiet:last-of-type,
.rd-row--opportunity .rd-row__actions .rd-btn--quiet {
  display: none;
}

.rd-row--opportunity .rd-facts {
  gap: 0.05rem 0.9rem;
  line-height: 1.15;
}

.rd-row--opportunity .rd-fact,
.rd-row--opportunity .rd-facts > * {
  font-size: 0.8rem;
}

.rd-row--opportunity .rd-row__body {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
}

.rd-row--opportunity .details-block {
  margin-top: 0.15rem;
  padding-top: 0.15rem;
}

.rd-row--opportunity .rd-row__actions {
  gap: 0.3rem;
}

/* Troisième et dernier passage : la hauteur ne venait plus du corps mais de la
   colonne de droite, qui étirait toute la ligne à sa propre hauteur — prix,
   deux boutons et une action secondaire empilés. La ligne repliée garde le prix
   et une seule action ; « Marquer examinée » et le sélecteur d'étape
   appartiennent à la fiche, où l'on décide vraiment. */

.rd-row--opportunity {
  align-items: start;
}

.rd-row--opportunity .rd-row__actions {
  display: grid;
  grid-template-columns: auto auto;
  align-items: center;
  gap: 0.2rem 0.6rem;
  justify-items: end;
}

.rd-row--opportunity .rd-row__actions > form:last-of-type,
.rd-row--opportunity .rd-row__actions > .rd-meta--quiet {
  display: none;
}

/* Le lien « Voir le détail » suffit comme action secondaire : il est déjà la
   destination de chaque ligne. */
.rd-row--opportunity .rd-row__actions .rd-btn--search,
.rd-row--opportunity .rd-row__actions > a:first-of-type {
  font-size: 0.8rem;
}

.rd-row--opportunity .details-block {
  align-self: start;
}

/* Passage final sur la densité. Ce qui restait tenait à la grille de faits, qui
   passait à la ligne dès quatre entrées, et aux marges verticales cumulées.
   Objectif tenu : 5 à 8 lignes repliées sur un écran d'ordinateur standard. */

.rd-row--opportunity {
  padding: 6px 12px;
  border-radius: 8px;
}

.rd-row--opportunity .st-rel {
  padding: 0.1rem 0 0.2rem;
  margin-bottom: 0.15rem;
  border-bottom: 0;
}

/* La densité s'était payée sur la vignette : 52 px de haut, où une photographie affichée
   entière tient sur 69 px de large et ne montre plus rien. Le cadre garde une proportion 4/3,
   ce qui reste compact — cinq à huit lignes tiennent toujours à l'écran — mais laisse voir le
   bien sans ouvrir la fiche. */
.rd-row--opportunity .rd-row__photo {
  min-height: 96px;
  max-height: 96px;
}

.rd-row--opportunity .rd-row__title {
  font-size: 0.92rem;
  margin: 0;
}

.rd-row--opportunity .rd-facts {
  flex-wrap: nowrap;
  overflow: hidden;
  gap: 0 0.85rem;
}

/* Les étiquettes des faits ne se répètent pas d'une ligne à l'autre : « Surface
   bâtie », « Terrain », « Hauteur libre » sont les mêmes partout. La valeur
   suffit à la lecture rapide, l'étiquette revient au dépliage. */
.rd-row--opportunity .rd-fact__l,
.rd-row--opportunity .rd-facts svg {
  display: none;
}

.rd-row--opportunity .rd-facts > * {
  white-space: nowrap;
  font-size: 0.78rem;
}

.rd-row--opportunity .rd-meta {
  margin: 0;
  font-size: 0.78rem;
}

.rd-row--opportunity .details-block {
  margin: 0;
  padding: 0;
  border-top: 0;
}

.rd-row--opportunity .rd-row__actions {
  gap: 0.15rem 0.5rem;
}

.rd-row--opportunity .rd-row__actions .rd-price,
.rd-row--opportunity .rd-row__actions > p {
  margin: 0;
}

/* Correction de la passe précédente : masquer les étiquettes rendait la ligne
   illisible — « 1090 m² · À vérifier · À vérifier · À vérifier » ne dit pas
   lequel des trois est le terrain. Elles reviennent, en petit et sur la même
   ligne que leur valeur. Vingt pixels gagnés ne valent pas une ligne qu'on ne
   peut plus lire. */

.rd-row--opportunity .rd-fact__l {
  display: inline;
  font-size: 0.7rem;
  color: var(--text-faint);
  margin-right: 0.2rem;
}

.rd-row--opportunity .rd-facts > * {
  display: inline-flex;
  align-items: baseline;
  gap: 0.15rem;
}

/* ---------------------------------------------------------------------------
   Photographie affichée depuis le site source.

   Le `robots.txt` du CDN d'images interdit à notre collecteur de télécharger ou
   de relayer ces fichiers. Il ne dit rien du navigateur de l'utilisateur, qui
   charge déjà ces mêmes adresses sur la fiche publique — vérifié : pas
   d'authentification, pas de jeton, pas de contrôle de Referer, et aucune clause
   d'incorporation dans les CGU. L'image est donc affichée, jamais récupérée.

   Le repli n'apparaît que si le CDN refuse réellement la requête du navigateur :
   `onerror` retire l'image et pose la classe qui le révèle. Un cadre cassé ne
   dit rien à personne. #} */

.st-photo-origine {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0.08rem 0.25rem;
  font-size: 0.6rem;
  line-height: 1.2;
  text-align: center;
  color: #fff;
  background: rgba(31, 36, 41, 0.66);
}

.rd-nophoto--repli {
  display: none;
}

.rd-photo--distante-ko .st-photo-origine {
  display: none;
}

.rd-photo--distante-ko .rd-nophoto--repli {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  justify-content: center;
  padding: 0.3rem;
  font-size: 0.68rem;
  line-height: 1.2;
  text-align: center;
  color: var(--text-muted);
}

/* ==========================================================================
   La carte du bassin
   ==========================================================================

   Trois règles de lecture, et elles ne se recouvrent jamais :

   * la **couleur** dit la pertinence Stimcar — trois valeurs, pas vingt Sources ;
   * la **forme et le contour** disent la précision géographique — un point creux n'est pas
     une adresse, et se lit comme tel avant même qu'on ait lu la mention ;
   * le **fond** reste anthracite/bleu, discret, parce qu'il situe sans attirer l'œil.

   Aucune tuile, aucune ressource distante : voir `static/map.js`. */

.rd-modes {
  display: flex;
  gap: 6px;
  margin: 0 0 12px;
  flex-wrap: wrap;
}

.rd-mode {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0.34rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 0.85rem;
  text-decoration: none;
}

.rd-mode:hover { border-color: var(--border-strong); color: var(--text); }

.rd-mode.is-active {
  background: var(--trust-soft);
  border-color: var(--trust);
  color: var(--trust-ink);
  font-weight: 600;
}

/* --- La vue fractionnée ------------------------------------------------- */

.rd-split { display: block; }

.rd-split--duo {
  display: grid;
  /* Disposition équilibrée par défaut, ajustable à la poignée (`--rd-split-w`). */
  grid-template-columns: var(--rd-split-w, minmax(360px, 1fr)) 8px minmax(340px, 1fr);
  align-items: start;
  gap: 0;
}

.rd-split--duo > .rd-rows { padding-right: 14px; }

.rd-split--carte > .rd-rows { display: none; }

.rd-split--carte { display: block; }

.rd-split__poignee {
  align-self: stretch;
  width: 8px;
  cursor: col-resize;
  background: linear-gradient(var(--border), var(--border)) center / 2px 100% no-repeat;
  border: 0;
  padding: 0;
}

.rd-split__poignee:hover,
.rd-split__poignee:focus-visible {
  background: linear-gradient(var(--trust), var(--trust)) center / 3px 100% no-repeat;
}

.rd-split__carte {
  /* La carte reste sous les yeux pendant qu'on descend la liste : c'est tout l'intérêt du
     mode fractionné, et sans cela il ne serait qu'une liste plus étroite. */
  position: sticky;
  top: 18px;
  height: calc(100vh - 120px);
  min-height: 420px;
}

.rd-split--carte .rd-split__carte {
  position: static;
  height: calc(100vh - 200px);
}

/* --- Le cadre ----------------------------------------------------------- */

.rd-carte {
  position: relative;
  height: 100%;
  min-height: 380px;
  border: 1px solid var(--border);
  border-radius: var(--rd-radius);
  background: var(--surface-2);
  overflow: hidden;
}

.rd-carte__svg { display: block; width: 100%; height: 100%; touch-action: none; }

.rd-carte--glisse .rd-carte__svg { cursor: grabbing; }

.rd-carte__attente,
.rd-carte__panne {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  margin: 0;
  padding: 1rem;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.88rem;
}

/* --- Le fond de plan ---------------------------------------------------- */

.rd-carte__anneau {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1;
  stroke-dasharray: 3 5;
  opacity: 0.75;
}

/* Les libellés du fond passent sous les marqueurs — ce sont les biens qu'on vient lire, pas
   les repères. Un liseré de la couleur du fond les garde lisibles quand un marqueur les
   croise, sans les faire remonter au-dessus. */
.rd-carte__anneau-l,
.rd-carte__commune-l,
.rd-carte__ville-l {
  paint-order: stroke;
  stroke: var(--surface-2);
  stroke-width: 3px;
  stroke-linejoin: round;
}

.rd-carte__anneau-l {
  fill: var(--text-faint);
  font-size: 10px;
  text-anchor: middle;
  letter-spacing: 0.04em;
}

.rd-carte__commune { fill: var(--border-strong); }

.rd-carte__commune-l {
  fill: var(--text-faint);
  font-size: 10.5px;
}

/* La ville centrale ressort, mais discrètement : elle sert de repère, elle n'est pas le
   sujet. Le sujet, ce sont les biens. */
.rd-carte__ville { fill: var(--trust); }

.rd-carte__ville-l {
  fill: var(--trust-ink);
  font-size: 12.5px;
  font-weight: 650;
  letter-spacing: 0.02em;
}

/* --- Les marqueurs ------------------------------------------------------ */

.rd-marqueur { cursor: pointer; }
.rd-marqueur:focus { outline: none; }

.rd-marqueur__forme {
  fill: var(--text-muted);
  stroke: var(--surface);
  stroke-width: 2;
}

/* Contour interrompu : la position est un centroïde, pas une adresse. */
.rd-marqueur__forme--creux {
  fill: var(--surface);
  stroke-width: 2.4;
  stroke-dasharray: 4 3;
}

.rd-marqueur__halo {
  fill: var(--text-muted);
  opacity: 0.13;
  stroke: none;
}

.rd-marqueur__halo--large { opacity: 0.09; }

.rd-marqueur__n {
  fill: var(--on-trust);
  font-size: 11px;
  font-weight: 700;
  text-anchor: middle;
  pointer-events: none;
}

.rd-marqueur--p-commune .rd-marqueur__n,
.rd-marqueur--p-secteur .rd-marqueur__n { fill: var(--text); }

/* La couleur, et rien d'autre, dit la pertinence. */
.rd-marqueur--tres_pertinent .rd-marqueur__forme,
.rd-marqueur--tres_pertinent .rd-marqueur__halo { fill: var(--trust); }
.rd-marqueur--tres_pertinent .rd-marqueur__forme--creux {
  fill: var(--surface);
  stroke: var(--trust);
}

.rd-marqueur--a_etudier .rd-marqueur__forme,
.rd-marqueur--a_etudier .rd-marqueur__halo { fill: var(--accent); }
.rd-marqueur--a_etudier .rd-marqueur__forme--creux {
  fill: var(--surface);
  stroke: var(--accent);
}

.rd-marqueur--peu_pertinent .rd-marqueur__forme--creux {
  fill: var(--surface);
  stroke: var(--text-muted);
}

/* Un groupe n'est pas un bien : il est dessiné en creux, cerclé d'anthracite, et ne prend
   aucune des trois couleurs de pertinence. Un disque plein bleu foncé se lisait « très
   pertinent » alors qu'il ne disait que « plusieurs ici ». */
.rd-marqueur--groupe .rd-marqueur__forme {
  fill: var(--surface);
  stroke: var(--text);
  stroke-width: 2.2;
  opacity: 1;
}

.rd-marqueur--groupe .rd-marqueur__n { fill: var(--text); }

.rd-marqueur--groupe.is-survol .rd-marqueur__forme,
.rd-marqueur--groupe:focus-visible .rd-marqueur__forme { stroke: var(--trust); }

.rd-marqueur.is-survol .rd-marqueur__forme,
.rd-marqueur:focus-visible .rd-marqueur__forme { stroke: var(--text); stroke-width: 3; }

.rd-marqueur.is-choisi .rd-marqueur__forme {
  stroke: var(--text);
  stroke-width: 3.2;
}

/* --- Légende, compteur, outils ------------------------------------------ */

.rd-carte__legende {
  position: absolute;
  left: 10px;
  bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: var(--rd-radius-sm);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  font-size: 0.72rem;
  color: var(--text-muted);
  pointer-events: none;
}

.rd-carte__legende-bloc {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
}

/* Deux lectures distinctes, et il faut le dire : la couleur ne parle que de pertinence, la
   forme ne parle que de précision. Sans ces deux mots la légende invitait à les confondre. */
.rd-carte__legende-titre {
  color: var(--text-faint);
  font-size: 0.66rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  min-width: 4.6rem;
}


.rd-carte__cle { display: inline-flex; align-items: center; gap: 5px; }

.rd-carte__cle::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--text-muted);
}

.rd-carte__cle--tres_pertinent::before { background: var(--trust); }
.rd-carte__cle--a_etudier::before { background: var(--accent); }

.rd-carte__cle--p-exacte::before { background: var(--text); }

/* Placée après `.rd-carte__cle::before` : à spécificité égale, c'est l'ordre qui tranche, et
   la pastille du groupe doit rester creuse comme le marqueur qu'elle décrit. */
.rd-carte__cle--groupe::before {
  background: var(--surface);
  border: 2px solid var(--text);
}

.rd-carte__cle--p-commune::before {
  background: var(--surface);
  border: 2px dashed var(--text-muted);
}

.rd-carte__cle--p-secteur::before {
  background: var(--surface);
  border: 2px dashed var(--text-muted);
  border-radius: 2px;
  transform: rotate(45deg);
}

.rd-carte__compteur {
  position: absolute;
  left: 10px;
  top: 10px;
  margin: 0;
  padding: 5px 9px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  font-size: 0.76rem;
  color: var(--text-muted);
  pointer-events: none;
}

.rd-carte__outils {
  position: absolute;
  right: 10px;
  top: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.rd-carte__outil {
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}

.rd-carte__outil:hover { border-color: var(--trust); color: var(--trust); }

/* --- Le résumé d'un marqueur -------------------------------------------- */

.rd-carte__resume {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: min(300px, calc(100% - 20px));
  max-height: calc(100% - 60px);
  overflow: auto;
  padding: 12px 13px;
  border: 1px solid var(--border);
  border-radius: var(--rd-radius);
  background: var(--surface);
  box-shadow: var(--rd-shadow);
  font-size: 0.83rem;
}

.rd-resume__fermer {
  position: absolute;
  right: 6px;
  top: 4px;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
}

.rd-resume__photo {
  display: block;
  width: 100%;
  height: 116px;
  object-fit: contain;
  border-radius: var(--rd-radius-sm);
  margin-bottom: 8px;
  background: var(--surface-2);
}

.rd-resume__titre {
  margin: 0 18px 4px 0;
  font-weight: 650;
  color: var(--text);
  line-height: 1.3;
}

/* La mention de précision est permanente pour tout point qui n'est pas une adresse : elle ne
   se replie pas, ne s'estompe pas et ne se survole pas. C'est ce qui empêche de lire un
   centroïde comme un bâtiment. */
.rd-resume__precision {
  margin: 0 0 8px;
  padding: 4px 7px;
  border-radius: var(--rd-radius-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 0.76rem;
  line-height: 1.35;
}

.rd-resume__precision--commune,
.rd-resume__precision--secteur {
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.rd-resume__l {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin: 0 0 3px;
  color: var(--text-muted);
}

.rd-resume__l strong { color: var(--text); text-align: right; font-weight: 600; }

.rd-resume__multi {
  margin-top: 8px;
  padding-top: 7px;
  border-top: 1px solid var(--border);
}

.rd-resume__multi-tete {
  margin: 0 0 4px;
  color: var(--accent-ink);
  font-weight: 600;
  font-size: 0.78rem;
}

.rd-resume__liens { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }

.rd-resume__voir {
  display: inline-block;
  padding: 0.34rem 0.75rem;
  border-radius: 999px;
  background: var(--trust);
  color: var(--on-trust);
  text-decoration: none;
  font-size: 0.8rem;
  font-weight: 600;
}

.rd-resume__pile { display: grid; gap: 4px; margin-top: 6px; }

.rd-resume__pile-item {
  text-align: left;
  padding: 5px 7px;
  border: 1px solid var(--border);
  border-radius: var(--rd-radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: 0.79rem;
  cursor: pointer;
}

.rd-resume__pile-item:hover { border-color: var(--trust); }

/* --- La petite carte de la fiche ---------------------------------------- */

.rd-carte--fiche { height: 260px; min-height: 260px; }

/* La fiche ne montre qu'un point : ni outils de navigation, ni légende, ni compteur — la
   phrase de précision et la distance, juste dessous, disent tout ce qu'il y a à dire. */
.rd-carte--statique .rd-carte__outils,
.rd-carte--statique .rd-carte__legende,
.rd-carte--statique .rd-carte__compteur { display: none; }

/* --- La bascule mobile --------------------------------------------------- */

.rd-carte-bascule { display: none; }

@media (max-width: 1000px) {
  /* Sur une fenêtre étroite, deux colonnes ne sont plus deux colonnes : on montre l'une **ou**
     l'autre, et un bouton fixe fait passer de l'une à l'autre. Le mode choisi dans l'URL
     décide seulement laquelle des deux s'ouvre en premier. */
  .rd-split--duo,
  .rd-split--carte { display: block; }

  .rd-split--duo > .rd-rows { padding-right: 0; }

  .rd-split__poignee { display: none; }

  .rd-split--duo .rd-split__carte,
  .rd-split--carte .rd-split__carte {
    position: static;
    height: calc(100vh - 190px);
    min-height: 340px;
    margin-top: 14px;
    display: none;
  }

  .rd-split--mobile-carte > .rd-rows { display: none; }

  .rd-split--mobile-carte .rd-split__carte {
    display: block;
    margin-top: 0;
  }

  .rd-carte-bascule {
    display: block;
    position: fixed;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%);
    z-index: 30;
    padding: 0.6rem 1.4rem;
    border: 0;
    border-radius: 999px;
    background: var(--trust);
    color: var(--on-trust);
    font-size: 0.9rem;
    font-weight: 650;
    box-shadow: 0 6px 20px rgba(20, 30, 45, 0.28);
    cursor: pointer;
  }
}

/* En mode fractionné, une ligne dispose de la moitié de la largeur : la vignette rétrécit et
   la colonne d'actions passe sous le corps, plutôt que d'écraser le texte. */
@media (min-width: 1001px) {
  .rd-split--duo .rd-row--opportunity {
    grid-template-columns: clamp(116px, 11vw, 172px) minmax(0, 1fr);
  }

  .rd-split--duo .rd-row--opportunity > .rd-row__actions {
    grid-column: 1 / -1;
    flex-direction: row;
    flex-wrap: wrap;
  }
}

/* La situation, sur la fiche : une carte réduite, la précision annoncée, la distance, et le
   chemin vers la carte générale. Rien de plus — la fiche décide, elle n'explore pas. */
.rd-situ .rd-carte--fiche { margin: 4px 0 10px; }

.rd-situ__precision {
  margin: 0 0 6px;
  padding: 5px 8px;
  border-radius: var(--rd-radius-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 0.8rem;
  line-height: 1.35;
}

.rd-situ__precision--commune,
.rd-situ__precision--secteur,
.rd-situ__precision--inconnue {
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.rd-situ__ligne {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 14px;
  margin: 0 0 8px;
  color: var(--text-muted);
  font-size: 0.87rem;
}

.rd-situ__ligne strong { color: var(--text); }

.rd-situ__lien {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--trust);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
}

.rd-situ__lien:hover { text-decoration: underline; }

/* Le nombre de biens porte le poids de la phrase sans passer par `<strong>` : un compteur
   n'est pas une emphase de texte, et un gabarit qui met des balises au milieu d'une phrase
   rend celle-ci illisible pour qui la relit. */
.rd-listcount__n { font-weight: 650; color: var(--text); }

/* Aucune photographie n'est recadrée nulle part : ni la vignette d'une ligne, ni la galerie
   d'une fiche, ni la bande de miniatures, ni le résumé d'un marqueur. Un fond neutre accueille
   le ratio qui ne remplit pas le cadre. C'est la règle, et elle est écrite ici en une fois
   pour qu'un futur composant ne la redécouvre pas à ses dépens. */
.listing-photos img,
.opp-photo img,
.listing-gallery-grid img,
.rd-gallery__strip img,
.rd-board__photo img,
.rd-resume__photo {
  background: var(--rd-line-soft);
}

/* --------------------------------------------------------------------------
   Mobile : une carte compacte, jamais un grand vide

   La vignette occupait toute la largeur sur une hauteur fixe. Résultat : une
   photographie en portrait, affichée entière, laissait deux larges bandes grises de part et
   d'autre — et une annonce sans photographie affichait un bandeau vide de la largeur de
   l'écran. Le vide occupait la place que le prix et la surface auraient dû prendre.

   La vignette redevient donc ce qu'elle est : une miniature, posée à gauche du texte. Elle
   garde le ratio de l'image (jamais recadrée, jamais étirée), et un bien sans photographie
   ne prend qu'une case de la même taille — pas un bandeau. */
@media (max-width: 900px) {
  .rd-row--opportunity {
    grid-template-columns: 112px minmax(0, 1fr);
    column-gap: 12px;
    align-items: start;
  }

  .rd-row--opportunity > .st-rel,
  .rd-row--opportunity > .rd-row__actions,
  .rd-row--opportunity > .rd-doublons {
    grid-column: 1 / -1;
  }

  .rd-row--opportunity .rd-row__photo,
  .rd-row--opportunity .rd-row__photo.rd-photo--distante-ko {
    min-height: 84px;
    max-height: 84px;
  }

  .rd-row--opportunity .rd-row__body { padding: 0; }

  /* La mention « photos sur le site source » ne tient pas dans 112 px : elle passe sous la
     miniature plutôt que de s'y écraser. */
  .rd-row--opportunity .rd-nophoto {
    font-size: 0.68rem;
    padding: 6px;
    gap: 4px;
  }

  /* La phrase seule tient dans 112 px ; la mention « Voir l'annonce » n'y tiendrait pas. Elle
     disparaît **visuellement**, mais la case entière reste un lien vers l'annonce source :
     l'accès aux photographies ne dépend pas de la largeur de l'écran. */
  .rd-row--opportunity .rd-nophoto .st-lien-source {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* La case « photos ailleurs » est un lien : elle doit se comporter comme tel. */
a.rd-nophoto { text-decoration: none; cursor: pointer; }
a.rd-nophoto:hover { color: var(--trust); }
a.rd-nophoto:focus-visible { outline: 2px solid var(--trust); outline-offset: -2px; }

/* Le panneau de filtres : réellement défilable.

   Il compte jusqu'à une trentaine de puces. Sur un portable, ou sur un écran d'ordinateur
   court, les dernières — le formulaire prix/tri, « Filtrer », « Réinitialiser » — se
   retrouvaient sous le pli d'un bloc qui ne défilait pas : elles existaient et restaient
   inatteignables. Le panneau a donc sa propre hauteur maximale et son propre défilement,
   au lieu de compter sur celui de la page. */
.rd-filtres {
  max-height: min(62vh, 560px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* De quoi ne pas coller la dernière puce au bord bas. */
  padding-bottom: 8px;
}

/* Une ombre discrète en haut et en bas dit qu'il reste quelque chose à voir — sans ajouter
   d'élément, et sans effet décoratif. */
.rd-filtres {
  background:
    linear-gradient(var(--surface) 30%, rgba(255, 255, 255, 0)) top / 100% 18px no-repeat,
    linear-gradient(rgba(255, 255, 255, 0), var(--surface) 70%) bottom / 100% 18px no-repeat,
    linear-gradient(rgba(31, 36, 41, 0.06), rgba(255, 255, 255, 0)) top / 100% 7px no-repeat,
    linear-gradient(rgba(255, 255, 255, 0), rgba(31, 36, 41, 0.06)) bottom / 100% 7px no-repeat;
  background-attachment: local, local, scroll, scroll;
}

/* Une puce inerte : la caractéristique existe, mais aucune source de ce scénario ne la
   publie. Elle reste visible — c'est une information sur nos sources — et ne se clique pas. */
.rd-chip--vide {
  opacity: 0.5;
  cursor: default;
  border-style: dashed;
}

/* Le résumé des filtres en vigueur, en toutes lettres, et un seul geste pour tout enlever. */
.st-filtres-actifs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  margin: 0 0 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--rd-radius-sm);
  background: var(--surface-2);
  font-size: 0.8rem;
  color: var(--text-muted);
}

.st-filtres-actifs__t {
  font-size: 0.68rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.st-filtres-actifs > span:not(.st-filtres-actifs__t) {
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--trust-soft);
  color: var(--trust-ink);
}

.st-filtres-actifs .st-effacer {
  margin-left: auto;
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.st-filtres-actifs .st-effacer:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
   Densité de la ligne résidentielle

   Mesuré sur Bouchemaine : une annonce et demie par écran. Le lecteur ne
   voyait donc jamais les lignes 3 à 5 — celles qui portaient les photographies. Une liste
   qu'on ne parcourt pas ne trie rien.

   Trois postes rendaient la hauteur : un encart « Analyse IA en attente » qui annonçait
   qu'il n'y avait rien à annoncer (supprimé), un bandeau répétant l'opération et le type
   déjà lus (supprimé), et des marges verticales calculées pour une carte, pas pour une
   ligne. Objectif tenu : au moins cinq lignes repliées par écran d'ordinateur. */
.rd-rows { gap: 8px; }

.rd-row--opportunity {
  padding: 8px 12px;
  row-gap: 2px;
}

.rd-row--opportunity .rd-row__body {
  gap: 3px;
  padding: 0 16px;
}

.rd-row--opportunity .rd-row__price {
  font-size: 1.12rem;
  margin: 0;
  line-height: 1.2;
}

.rd-row--opportunity .rd-row__subtitle {
  font-size: 0.94rem;
  margin: 0;
  line-height: 1.25;
}

.rd-row--opportunity .rd-meta,
.rd-row--opportunity .rd-meta--quiet {
  margin: 0;
  line-height: 1.3;
  font-size: 0.78rem;
}

/* Les actions tiennent sur une ligne : trois boutons empilés, c'était trois fois la hauteur
   pour un geste qu'on ne fait qu'une fois sur dix annonces. */
.rd-row--opportunity .rd-row__actions {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  gap: 6px;
  padding: 0 0 0 12px;
}

.rd-row--opportunity .rd-row__actions .rd-btn {
  width: auto;
  padding: 0.3rem 0.7rem;
  font-size: 0.82rem;
}

/* Le détail et la justification ne s'ouvrent qu'à la demande : repliés, ils tiennent sur une
   ligne de 0,78 rem, et c'est tout ce qu'ils doivent coûter. */
.rd-row--opportunity .details-block > summary,
.rd-row--opportunity .rd-why-fold > summary,
.rd-row--opportunity .rd-doublons > summary {
  font-size: 0.8rem;
  padding: 1px 0;
}

.rd-row--opportunity .rd-facts { gap: 4px 12px; margin: 0; }

/* Les quatre nombres de l'entête décrivent quatre ensembles différents. Le premier porte le
   poids, les suivants s'effacent : ils précisent, ils ne concurrencent pas. */
.rd-listcount { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px; }

/* Le fond rayé dit « rien à voir ici ». Il n'a donc rien à faire derrière une annonce dont
   les photographies existent et sont à un clic : ce cadre-là n'est pas une absence, c'est un
   renvoi. Il garde un aplat sobre et le bleu du lien. */
.rd-nophoto--ailleurs,
.rd-nophoto--repli {
  background: var(--trust-soft);
  color: var(--trust-ink);
}

.rd-nophoto--ailleurs .st-lien-source,
.rd-nophoto--repli .st-lien-source {
  color: var(--trust);
  font-weight: 600;
  text-decoration: underline;
}

/* L'étiquette de type est passée DANS le titre (voir le gabarit) : elle s'aligne dessus au
   lieu de lui voler une ligne. Sur 1 300 annonces, c'est un écran gagné toutes les six. */
.rd-row--opportunity .rd-row__title .rd-tag,
.rd-row--opportunity .rd-row__subtitle .rd-tag {
  margin-right: 7px;
  vertical-align: 2px;
}

.rd-row--opportunity .rd-row__title,
.rd-row--opportunity .rd-row__subtitle {
  line-height: 1.35;
}

/* La pastille d'origine se pose sur l'image : elle doit tenir sur une ligne et ne pas la
   masquer. Au-delà, elle est tronquée — le nom complet reste dans l'infobulle. */
.st-photo-origine {
  max-width: calc(100% - 8px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --------------------------------------------------------------------------
   Le menu des recherches : des projets, pas huit intitulés tronqués

   Le menu répétait « Implantation automobile — Bordeaux », « Reprise automobile — Bordeaux »,
   huit fois, et l'ellipse mangeait justement la moitié qui les distingue. Les projets sont
   désormais des groupes, et sous chacun deux mots courts. */

.rd-projets {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 10px;
  min-height: 0;
  overflow-y: auto;
}

.rd-projet { border-radius: 8px; }

.rd-projet__tete {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 10px;
  margin: 0;
  border-radius: 8px;
  color: var(--rail-ink, rgba(255, 255, 255, 0.86));
  font-size: 0.9rem;
  font-weight: 600;
}

.rd-projet__tete--simple {
  cursor: default;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.62;
  font-weight: 600;
}

/* La ville active ressort, et elle seule. */
.rd-projet__tete.is-active {
  background: var(--rail-active, rgba(255, 255, 255, 0.11));
}

.rd-projet__client {
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.5;
  font-weight: 500;
}

.rd-projet__liste {
  list-style: none;
  margin: 0 0 4px;
  padding: 0 0 0 10px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.rd-sous {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 10px;
  border-radius: 7px;
  color: var(--rail-ink-2, rgba(255, 255, 255, 0.66));
  font-size: 0.85rem;
  text-decoration: none;
}

.rd-sous:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }

/* La sous-recherche active : un filet à gauche et un fond, pour qu'elle se distingue de la
   ville active sans lui faire concurrence. */
.rd-sous.is-active {
  color: #fff;
  font-weight: 600;
  background: var(--rail-active, rgba(255, 255, 255, 0.11));
  box-shadow: inset 2px 0 0 currentColor;
}

/* Le compteur : discret, et il disparaît quand il n'y a rien à compter. */
.rd-sous__n {
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.55;
}

.rd-sous.is-active .rd-sous__n { opacity: 0.8; }

/* Les outils, séparés de la navigation quotidienne par une ligne et par l'espace. */
.rd-rail__foot {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

@media (max-width: 900px) {
  /* Sur mobile, un sélecteur simple : les projets se replient, et **seul le projet actif**
     s'ouvre. Personne ne doit ouvrir puis refermer quatre villes pour retrouver deux entrées.
     Les `<details>` du gabarit portent déjà `open` sur le projet actif. */
  .rd-projets { max-height: none; overflow: visible; }

  /* Le repli mobile : seul le projet actif montre ses sous-recherches. Il est **ouvert
     d'office** — personne n'a à déplier sa propre ville pour la retrouver. */
  .rd-projet:not(.is-active):not(.rd-projet--simple) .rd-projet__liste { display: none; }

  .rd-projet__tete { padding: 9px 12px; font-size: 0.95rem; }
  .rd-sous { padding: 8px 12px; font-size: 0.92rem; }
}

/* ------------------------------------------------------------------------
   Confirmer un resserrement de perimetre
   Un ecran qui existe pour une seule raison : dire ce que la modification
   **retire**, avant de l'enregistrer. Il emprunte le ton de l'avertissement
   (`--accent`) et non celui de l'erreur : resserrer n'est pas une faute, c'est
   une decision qui doit etre vue.
   ------------------------------------------------------------------------ */
.rd-reduction__intro {
  margin: 0 0 var(--space-4);
  color: var(--text-muted);
}

.rd-reduction__liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin: 0 0 var(--space-5);
  padding: 0;
  list-style: none;
}

.rd-reduction__liste > li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--accent-soft);
}

.rd-reduction__quoi {
  font-weight: 600;
  color: var(--accent-ink);
}

.rd-reduction__chiffres {
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* Les elements nommes, jamais resumes en « 9 communes » : c'est en lisant
   « Mérignac, Pessac, Talence » qu'on voit qu'on est en train de perdre une
   agglomeration entiere. */
.rd-reduction__perdu {
  flex: 1 1 100%;
  color: var(--accent-ink);
  font-size: 0.85rem;
}

.rd-reduction__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

/* ---------------------------------------------------------------------------
   La synthèse du bassin, les trois paliers, la pagination.

   Rien ici n'introduit de couleur : tout se lit sur les jetons --rd-* déjà
   posés, qui portent déjà le clair et le sombre. Un écran de décision se lit
   d'un coup d'œil ; il n'a pas besoin d'un second alphabet chromatique.
   --------------------------------------------------------------------------- */

.st-synth {
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius);
  background: var(--rd-card);
  padding: 18px 20px;
  margin-bottom: 20px;
}

.st-synth__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 16px 24px;
}

.st-synth__item { display: flex; flex-direction: column; gap: 2px; }

.st-synth__n {
  font-size: 1.34rem;
  font-weight: 600;
  color: var(--rd-ink);
  /* Les chiffres d'une même colonne doivent s'aligner : ils se comparent. */
  font-variant-numeric: tabular-nums;
}

.st-synth__k {
  font-size: 0.83rem;
  color: var(--rd-ink-3);
  line-height: 1.3;
}

.st-synth__acteurs {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--rd-line-soft);
  font-size: 0.86rem;
  color: var(--rd-ink-2);
}

/* Les paliers : plus affirmés que les onglets de statut, parce que c'est par eux
   qu'une revue commence. */
.st-paliers {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.st-palier {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 15px;
  border: 1px solid var(--rd-line);
  border-radius: 999px;
  background: var(--rd-card);
  color: var(--rd-ink-2);
  font-size: 0.94rem;
  white-space: nowrap;
}

.st-palier:hover { text-decoration: none; color: var(--rd-ink); border-color: var(--rd-line); }

.st-palier.is-active {
  background: var(--rd-green);
  border-color: var(--rd-green);
  color: #FFFFFF;
  font-weight: 600;
}

.st-palier__n {
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--rd-green-pale);
  color: var(--rd-green-ink);
}

.st-palier.is-active .st-palier__n {
  background: rgba(255, 255, 255, 0.22);
  color: #FFFFFF;
}

.st-palier__dit {
  margin: 0 0 22px;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--rd-ink-3);
  max-width: 76ch;
}

.st-palier__dit strong { color: var(--rd-ink-2); font-weight: 600; }

.st-pages {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--rd-line);
}

.st-pages__pas {
  padding: 8px 14px;
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius-sm);
  color: var(--rd-ink);
  font-size: 0.9rem;
  white-space: nowrap;
}

.st-pages__pas:hover { text-decoration: none; border-color: var(--rd-green); }
.st-pages__pas.is-off { color: var(--rd-ink-3); opacity: 0.55; }

.st-pages__etat {
  font-size: 0.86rem;
  color: var(--rd-ink-3);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 560px) {
  .st-synth { padding: 15px 16px; }
  .st-synth__grid { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 13px 16px; }
  .st-synth__n { font-size: 1.18rem; }
  .st-paliers { gap: 6px; }
  .st-palier { padding: 8px 12px; font-size: 0.88rem; }
  .st-pages { justify-content: center; }
}

/* La synthèse de l'analyse IA : le premier texte que la revue lit, donc lisible
   avant les listes de points qui la suivent. */
.ai-synthesis {
  margin: 8px 0 10px;
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--rd-ink);
  max-width: 78ch;
}

/* Le repère de marché. Aucune couleur d'alerte : un prix au-dessus de la médiane
   n'est pas une faute, et le colorier en rouge déciderait à la place du lecteur. */
.st-marche__head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 14px;
  font-weight: 600;
  color: var(--rd-ink);
}

.st-marche__chiffres {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 16px 24px;
}

.st-marche__item { display: flex; flex-direction: column; gap: 2px; }

.st-marche__n {
  font-size: 1.18rem;
  font-weight: 600;
  color: var(--rd-ink);
  font-variant-numeric: tabular-nums;
}

.st-marche__k { font-size: 0.83rem; color: var(--rd-ink-3); }

.st-marche__limites {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--rd-line-soft);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--rd-ink-3);
  max-width: 78ch;
}

.st-marche__limites strong { color: var(--rd-ink-2); font-weight: 600; }

/* La page de connexion. Volontairement nue : elle n'a qu'une chose à faire, et
   rien à montrer de ce qui se trouve derrière. */
.st-connexion {
  max-width: 24rem;
  margin: 8vh auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.st-connexion__sous { margin: 0; color: var(--rd-ink-3); font-size: 0.92rem; }

.st-connexion__refus {
  margin: 0;
  padding: 11px 14px;
  border-radius: var(--rd-radius-sm);
  background: var(--danger-soft);
  color: var(--danger);
  font-size: 0.9rem;
}

.st-connexion__google { justify-content: center; text-align: center; }

.st-connexion__note {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--rd-ink-3);
}

.st-connexion__ou {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0;
  color: var(--rd-ink-3);
  font-size: 0.82rem;
}

.st-connexion__ou::before,
.st-connexion__ou::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rd-line);
}

.st-connexion__secours summary {
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--rd-ink-2);
}

.st-connexion__form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.st-connexion__form label { font-size: 0.82rem; color: var(--rd-ink-2); }

.st-connexion__form input {
  padding: 9px 11px;
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius-sm);
  background: var(--rd-card);
  color: var(--rd-ink);
  font: inherit;
}

/* L'écran des membres. Une page d'administration reste une page : mêmes jetons,
   même sobriété, aucune couleur d'alerte pour dire « rôle ». */
.st-sous-titre {
  margin: 0 0 14px;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--rd-ink);
}

.st-table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.st-table th {
  text-align: left;
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--rd-ink-3);
  padding: 0 10px 8px 0;
  border-bottom: 1px solid var(--rd-line);
}
.st-table td { padding: 11px 10px 11px 0; border-bottom: 1px solid var(--rd-line-soft); }
.st-table__discret { display: block; font-size: 0.8rem; color: var(--rd-ink-3); }

.st-etiquette {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--rd-green-pale);
  color: var(--rd-green-ink);
  font-size: 0.78rem;
}

.st-etiquette--owner { background: var(--rd-amber-pale); color: var(--rd-amber); }

.st-inline { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

.st-inline input,
.st-inline select {
  padding: 7px 10px;
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius-sm);
  background: var(--rd-card);
  color: var(--rd-ink);
  font: inherit;
}

.rd-btn--sm { padding: 6px 11px; font-size: 0.85rem; }

/* Le lien d'invitation : montré une fois, et l'écran le dit. */
.st-lien { border-color: var(--rd-amber); }
.st-lien__titre { margin: 0 0 6px; font-weight: 600; color: var(--rd-ink); }
.st-lien__note { margin: 0 0 10px; font-size: 0.85rem; line-height: 1.5; color: var(--rd-ink-3); }
.st-lien__champ {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--rd-line);
  border-radius: var(--rd-radius-sm);
  background: var(--rd-card);
  color: var(--rd-ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
}
