/* booking-premium.css - La Palme d'Azur
   Design v4 of /reserver. Override sheet loaded AFTER booking-widget / booking-engine / group-configurator /
   offer-modal (booking-intel.css comes after it). Identity = the deployed home: cream #F8F5F0, navy #1B263B,
   coral #E8623D (hover #C24E2A), sea #4A90B8 / #2F5D73, teal #2CA6A4 / pool light #D6EAF2, Cormorant Garamond 400
   for the hero title and the section titles, Plus Jakarta Sans for everything else (cards included, owner 05/09).
   No gold, no legacy card sans, no emoji.
   Two registers (owner 05/09 evening): ROUNDED OBJECTS (the cards 16px, the controls 6px) and STRAIGHT BANDS
   (control bar, information bands, quiet note: radius 0, white, 1px border, no coloured rail, the colour lives
   in a 32px tinted icon disc). The cards are the PROD card (geometry, rhythm, chips, footer rule, CTA size)
   plus the validated deltas only: Jakarta 600 title, one icon family (stroke 2, lpa-amenity-icons.js), unified
   badges (promo + signal or recommendation stacked top-left, viewers bottom-right), 16px card radius, 6px CTA
   radius (white/coral at rest, filled coral on hover and on the recommended card), zero gold.
   Additive: the engine's DOM, prices and CTAs are untouched; every rule here only restyles what exists, plus the
   blocks rendered by booking-premium.js (.be-filters__row, .be-sort, #be-mobile-bar, .be-group-entry__*,
   .be-card__reco-badge, .be-card__facts, .be-card__live-total, .be-note, .be-merged).
   Text colours are AA on white AND cream: ink-2 #4A443F (8.8:1), ink-3 #6F675D (5.1:1), coral text only in
   its dark tone #C24E2A (4.75:1 on white); the light coral #E8623D is kept for fills and eyebrows (identity). */

/* ============================================================
   0. Tokens (the engine's gold token now resolves to sea dark; its muted grey gets the AA tone)
   ============================================================ */
.be-root {
  --be-fb: 'Plus Jakarta Sans', 'Jakarta Fallback', system-ui, sans-serif;
  --be-ft: 'Cormorant Garamond', 'Cormorant Fallback', Georgia, serif;
  --be-gold: #2F5D73;
  --be-muted: #6F675D;
  --be-cta-hover: #C24E2A;
  --be-sea-light: #4A90B8;
  --be-sea-grey: #5E7D8C;
  --be-teal: #2CA6A4;
  --be-terracotta: #B0441F;
  --be-pool-light: #D6EAF2;
  /* Owner 06/09: the VIEW is the one attribute that moves the price from one apartment to the next,
     so its chip is the only coloured one. Two tints, one per view.
     🔴 Contrast MEASURED on the served page, not estimated: sea reads 6.01:1, and the first pool ink
     tried (#1A7A78) came out at 4.33:1 — under the 4.5 that AA asks of a 12px label. Darkened until
     the measurement passed. --be-teal itself (#2CA6A4) is far too light to write on. */
  --be-sea-bg: #E1EDF5;
  --be-pool-bg: #DCF0EF;
  --be-pool-ink: #15645F;
  --be-coral-light: rgba(232, 98, 61, .12);
  --be-line: rgba(27, 38, 59, .12);
  --be-line-soft: rgba(27, 38, 59, .08);
  --be-ink-2: #4A443F;
  --be-ink-3: #6F675D;
  --be-err: #8B2E0F;
  --be-hdr-h: 66px;
  --be-t: .22s ease;
  /* radii (owner 05/09 evening): boxes = the apartment cards and the group configuration cards (16px, overflow
     hidden so the photo follows the corner); panels = control bar, information bands, group footer: STRAIGHT
     (0); controls = buttons, segments, pills, chips (6px). The site header (2px) and the search widget (60px
     pill) are not styled here. One soft shadow for the cards, none for the bands. */
  --be-r-box: 16px;
  --be-r-panel: 0;
  --be-r-ctl: 6px;
  --be-r: var(--be-r-box);
  --be-shadow-1: 0 8px 24px rgba(27, 38, 59, .08);
  --be-shadow-2: 0 14px 36px rgba(27, 38, 59, .12);
}
.be-seo-intro p { font-family: var(--be-fb) !important; color: var(--be-ink-2) !important; font-weight: 300 !important; }
/* the SEO paragraph serves visitors WITHOUT dates (and the crawlers); booking-premium.js sets html.lpa-dated
   as soon as a search has dates (URL, be:gridRendered, bw:datesSelected) */
html.lpa-dated .be-seo-intro { display: none; }

/* ============================================================
   1. Hero (spec 2.1): photo + eyebrow + title + one line + widget, nothing else on the photo
   ============================================================ */
.be-hero__eyebrow { font-weight: 400; font-size: 11px; letter-spacing: .28em; color: rgba(255, 255, 255, .78); margin-bottom: 16px; text-shadow: none; }
.be-hero__title { font-weight: 400; text-shadow: none; font-size: clamp(38px, 5.2vw, 64px); letter-spacing: -.01em; line-height: 1.05; margin-bottom: 12px; }
.be-hero__sub { font-weight: 300; font-size: 15.5px; letter-spacing: 0; text-shadow: none; color: rgba(255, 255, 255, .88); margin-bottom: 32px; }
.be-hero .bw-bar { box-shadow: 0 18px 50px rgba(27, 38, 59, .28); }
.be-hero__bg::after { background: linear-gradient(to bottom, rgba(27, 38, 59, .42) 0%, rgba(27, 38, 59, .22) 45%, rgba(27, 38, 59, .58) 100%); }
@media (max-width: 768px) {
  .be-hero { min-height: 62svh; }
  .be-hero__content { padding: 96px 16px 40px; }
  .be-hero__title { font-size: clamp(32px, 9vw, 40px); }
  .be-hero__sub { font-size: 14.5px; margin-bottom: 24px; }
}
body.lpa-group .be-hero { min-height: 58vh; }
@media (max-width: 768px) { body.lpa-group .be-hero { min-height: 48svh; } }

/* ============================================================
   2. Trust bar (spec 2.2): 4 facts, 18px icons in a pool-light disc; mobile = 2 x 2 grid, 12px, 30px discs
   ============================================================ */
.be-trust-bar { background: #fff; border-bottom: 1px solid var(--be-line-soft); padding: 12px 0; }
.be-trust-bar__inner { gap: 0; }
.be-trust-bar__item { font: 400 13px/1.35 var(--be-fb); color: var(--be-ink-2); gap: 12px; padding: 4px 24px; }
.be-trust-bar__item strong { font-weight: 500; color: var(--be-ink); }
.be-trust-bar__item svg { width: 18px; height: 18px; stroke: var(--be-sea); stroke-width: 1.75; padding: 8px; box-sizing: content-box; border-radius: 50%; background: var(--be-pool-light); }
.be-trust-bar__sep { display: none; }
@media (max-width: 767px) {
  .be-trust-bar { padding: 12px 0; }
  .be-trust-bar__inner { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; padding: 0 16px; overflow: visible; }
  .be-trust-bar__item { display: flex; align-items: center; gap: 8px; padding: 0; font-size: 12px; line-height: 1.3; white-space: normal; }
  .be-trust-bar__item > span { min-width: 0; }
  .be-trust-bar__item svg { width: 16px; height: 16px; padding: 7px; }
}

/* ============================================================
   3. Control bar (spec 2.3): one white sticky STRAIGHT band = stay summary (left) + [segmented filters | sort | view]
   booking-premium.js moves #be-stay-pill INTO .be-filters, wraps the 3 view filters in .be-seg--view and
   groups .be-seg--view + .be-sort + #be-view-toggle in .be-filters__row (one scrolling row on mobile)
   ============================================================ */
.be-sticky { display: none !important; }
.be-filters {
  position: sticky; top: var(--be-hdr-h); z-index: 30;
  display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 8px 12px;
  margin: 0; padding: 12px 16px;
  background: rgba(255, 255, 255, .96); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid var(--be-line-soft); border-radius: var(--be-r-panel); box-shadow: none;
  scroll-margin-top: calc(var(--be-hdr-h) + 16px);
}
.be-filters > #be-stay-pill { margin: 0 auto 0 0; scroll-margin-top: calc(var(--be-hdr-h) + 28px); }
.be-filters__row { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.be-stay-pill { display: none; padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; font: 400 14px/1.3 var(--be-fb); color: var(--be-ink-2); gap: 8px; transform: none; opacity: 1; width: auto; }
.be-stay-pill.visible { display: inline-flex; cursor: pointer; transition: color var(--be-t); }
.be-stay-pill.visible:hover { box-shadow: none; color: var(--be-ink); }
.be-stay-pill.visible:focus-visible { box-shadow: none; outline: 2px solid var(--be-ink); outline-offset: 4px; border-radius: var(--be-r-ctl); }
.be-stay-pill svg { stroke: var(--be-sea); stroke-width: 2; width: 16px; height: 16px; }
.be-stay-pill strong { font-weight: 500; color: var(--be-ink); }
.be-stay-pill__sep { color: var(--be-border); }
.be-stay-pill__arrow { color: var(--be-ink-3); font-weight: 400; }
.be-stay-pill__edit { display: inline-flex; align-items: center; gap: 6px; margin-left: 8px; color: var(--be-cta-hover); }
.be-stay-pill__edit::after { content: 'Modifier'; font: 500 11px/1 var(--be-fb); letter-spacing: .1em; text-transform: uppercase; }
html[lang^="en"] .be-stay-pill__edit::after { content: 'Edit'; }
html[lang^="de"] .be-stay-pill__edit::after { content: 'Ändern'; }
html[lang^="it"] .be-stay-pill__edit::after { content: 'Modifica'; }
html[lang^="nl"] .be-stay-pill__edit::after { content: 'Wijzigen'; }
html[lang^="es"] .be-stay-pill__edit::after { content: 'Modificar'; }
@media (max-width: 480px) { .be-stay-pill__edit { display: inline-flex; } }

/* segmented controls: view filters (engine buttons, wrapped), sort (rendered), view toggle (engine): 40px tall */
.be-seg { display: inline-flex; align-items: stretch; border: 1px solid var(--be-line); border-radius: var(--be-r-ctl); background: #fff; overflow: hidden; }
.be-seg > button { border: 0; border-radius: 0; margin: 0; }
.be-seg > button + button { border-left: 1px solid var(--be-line); }
.be-filters .be-filter { height: 40px; border-radius: 0; border: 0; background: #fff; font: 500 12.5px/1 var(--be-fb); letter-spacing: .02em; color: var(--be-ink-2); padding: 0 16px; margin: 0; transition: background var(--be-t), color var(--be-t); }
.be-filters .be-filter:hover { background: var(--be-bg); color: var(--be-ink); border-color: var(--be-line); }
.be-filters .be-filter.active { background: var(--be-ink); color: #fff; border-color: var(--be-ink); }
.be-filters .be-filter:not(.be-seg > .be-filter) { border: 1px solid var(--be-line); border-radius: var(--be-r-ctl); }
.be-sort { position: relative; display: inline-flex; align-items: center; gap: 8px; }
.be-sort[hidden] { display: none; }
.be-sort::before { content: ''; width: 1px; height: 24px; background: var(--be-line); margin-right: 4px; }
.be-sort__label { font: 400 11px/1 var(--be-fb); color: var(--be-ink-3); letter-spacing: .1em; text-transform: uppercase; }
.be-sort .be-seg button { height: 40px; background: #fff; font: 500 12.5px/1 var(--be-fb); letter-spacing: .02em; color: var(--be-ink-2); padding: 0 14px; cursor: pointer; transition: background var(--be-t), color var(--be-t); }
.be-sort .be-seg button:hover { background: var(--be-bg); color: var(--be-ink); }
.be-sort .be-seg button[aria-pressed="true"] { background: var(--be-ink); color: #fff; }
/* Mobile sort control (markup written by booking-premium.js, never shown on desktop): the 3-button
   segment does not fit next to the 3 view filters under 768px (measured 06/09 at 390px: the row asked
   for 556px in 364px, so "Prix" and "Capacite" were off screen with no affordance at all). Under 768px
   the segment gives way to ONE compact button stating the active mode + a chevron, which opens a small
   listbox anchored under it. No dialog, no overlay, no scroll lock: the panel closes on an outside
   click and on Escape. Desktop (>= 768px) does not move by one pixel. */
.be-sort__btn, .be-sort__menu { display: none; }
#be-view-toggle { border-radius: var(--be-r-ctl); border: 1px solid var(--be-line); margin-left: 0; }
#be-view-toggle button { width: 40px; height: 40px; padding: 0; color: var(--be-ink-3); transition: background var(--be-t), color var(--be-t); }
#be-view-toggle button + button { border-left: 1px solid var(--be-line); }
#be-view-toggle button:hover { color: var(--be-ink); background: var(--be-bg); }
#be-view-toggle button.active { background: var(--be-ink); color: #fff; }
#be-view-toggle svg { stroke-width: 2; }
.be-filters .be-filter:focus-visible, .be-sort .be-seg button:focus-visible, #be-view-toggle button:focus-visible { outline: 2px solid var(--be-ink); outline-offset: -3px; }
@media (max-width: 767px) {
  /* ONE frame at a time (owner 06/09): under 768px the stay summary is the framed object, so the bar
     itself drops its border and becomes a flush white band. Heights: 8 + pill 40 + gap 6 + row 36 + 8
     = 98px, against 112px before. */
  .be-filters { position: static; padding: 8px 12px; gap: 6px 0; justify-content: flex-start; border: 0; }
  /* the stay summary takes the full width, framed (variant A = default, see 3c).
     🔴 FIX 06/09 (owner screenshot, iPhone in English): the edit affordance is taken OUT OF THE FLOW
     and pinned to the right, and the block reserves its width as right padding. The summary text can
     then wrap or shrink without ever pushing the button out of the frame — which is exactly what it
     did in the five non-French languages, where the word overlapped the guest count and spilled past
     the right edge (measured at 390px: es +27px, it +23px, nl +21px, de +17px, en +5px).
     Two independent causes, both fixed: the word (see the ::after rule below) AND the flow. */
  .be-filters > #be-stay-pill.visible {
    position: relative; display: flex; flex: 1 0 100%; flex-wrap: wrap; align-items: center;
    box-sizing: border-box; gap: 6px; font-size: 13px; padding: 3px 40px 3px 9px; min-height: 40px;
  }
  /* 15 -> 17px (owner 06/09) : le calendrier redessiné porte cinq jours, il lui faut la place de
     les montrer. Les DEUX glyphes montent ensemble : n'en grandir qu'un déséquilibre la ligne. */
  .be-stay-pill svg { width: 17px; height: 17px; }
  /* left aligned: the summary inherits justify-content:center, which on a wrapped second line centres
     an orphan word under the first — it reads as a layout accident. */
  .be-filters > #be-stay-pill.visible { justify-content: flex-start; }
  /* the "·" separators are decoration, and they cost 24px of the 286 available at 390px — which is
     exactly what pushed Spanish onto two lines. The gaps already separate the three facts. */
  .be-filters > #be-stay-pill.visible .be-stay-pill__sep { display: none; }
  /* 🪤 `content: none` on the bare class LOSES to `html[lang^="xx"] .be-stay-pill__edit::after`:
     0,2,2 beats 0,1,1, and a media query adds NO specificity. Match it, or French is the only
     language that behaves. On a phone the pencil alone says "edit"; the word returns from 768px. */
  html[lang] .be-stay-pill__edit::after, .be-stay-pill__edit::after { content: none; }
  /* the pencil carries no frame of its own inside an already framed block (frame within a frame at
     small scale): a hairline separates the action from the information, and the tinted square only
     answers on press. The whole summary stays clickable, the pencil just says where to aim. */
  .be-stay-pill__edit {
    position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    width: 34px; height: 34px; margin: 0; padding: 0; justify-content: center;
    border: 0; border-radius: 8px; background: none; color: var(--be-sea);
    transition: background var(--be-t), color var(--be-t);
  }
  .be-stay-pill__edit::before {
    content: ''; position: absolute; left: -5px; top: 6px; bottom: 6px; width: 1px; background: var(--be-line);
  }
  .be-stay-pill.visible:hover .be-stay-pill__edit,
  .be-stay-pill.visible:active .be-stay-pill__edit { background: var(--be-bg); color: var(--be-ink); }
  /* filters then sort: ONE row that always fits. No scroll region any more (the negative margins and
     overflow-x:auto that hid 192px at 390px are gone), no wrap, nothing off screen: the view segment
     keeps its natural width (the filters the visitor uses most stay fully legible) and the sort button
     is the only shrinkable item, its value ellipsising rather than pushing anything out of view. */
  .be-filters__row { flex: 0 0 100%; min-width: 0; margin: 0; padding: 0; overflow: visible; gap: 8px; }
  .be-filters__row > .be-seg--view { flex: 0 0 auto; }
  .be-filters__row > .be-sort { flex: 0 1 auto; min-width: 0; margin-left: auto; }
  .be-filters .be-filter, .be-sort .be-seg button { white-space: nowrap; }
  /* the row really has 342px at 390px (.be-results adds its own 12px), not 366: measured, not assumed.
     FR needs 196 (segment) + 8 (gap) + 128 (button) = 332 of it. */
  .be-filters .be-filter { height: 34px; padding: 0 7px; }
  /* the segment, its "Trier" label and its separator give way to the button + listbox */
  .be-sort__label, .be-sort .be-seg { display: none; }
  .be-sort::before { display: none; }
  .be-sort__btn {
    display: inline-flex; align-items: center; gap: 5px; box-sizing: border-box; min-width: 0; max-width: 100%;
    height: 34px; padding: 0 8px; margin: 0; background: #fff; border: 1px solid var(--be-line); border-radius: var(--be-r-ctl);
    font: 500 12.5px/1 var(--be-fb); letter-spacing: .02em; color: var(--be-ink-2); cursor: pointer;
    transition: background var(--be-t), color var(--be-t), border-color var(--be-t);
  }
  .be-sort__btn:hover, .be-sort__btn[aria-expanded="true"] { background: var(--be-bg); color: var(--be-ink); }
  .be-sort__btn:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; }
  .be-sort__btn svg { flex: none; stroke-width: 2; }
  /* the sort glyph and the word "Trier :" cost 20px and 41px: under 481px the row cannot pay for either
     (see the budget above), so the compact button is the VALUE + the chevron, exactly the "Prix croissant v"
     select every OTA shows on a phone. Both come back from 481px, where the row has room. */
  .be-sort__ico { display: none; width: 14px; height: 14px; color: var(--be-sea); }
  .be-sort__chev { width: 12px; height: 12px; color: var(--be-ink-3); transition: transform var(--be-t); }
  .be-sort__btn[aria-expanded="true"] .be-sort__chev { transform: rotate(180deg); }
  .be-sort__pre { display: none; flex: none; color: var(--be-ink-3); }
  .be-sort__val { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--be-ink); }
  /* the panel: anchored under the button, right aligned, above the bands that follow it in the DOM */
  .be-sort__menu {
    display: block; position: absolute; top: calc(100% + 6px); right: 0; z-index: 40; min-width: 176px; padding: 4px;
    background: #fff; border: 1px solid var(--be-line); border-radius: var(--be-r-ctl); box-shadow: var(--be-shadow-1);
  }
  .be-sort__menu[hidden] { display: none; }
  .be-sort__opt {
    display: flex; align-items: center; gap: 10px; width: 100%; height: 40px; padding: 0 10px; margin: 0;
    border: 0; border-radius: var(--be-r-ctl); background: none; text-align: left; cursor: pointer;
    font: 500 13px/1 var(--be-fb); letter-spacing: .01em; color: var(--be-ink-2);
    transition: background var(--be-t), color var(--be-t);
  }
  .be-sort__opt > span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .be-sort__opt:hover { background: var(--be-bg); color: var(--be-ink); }
  .be-sort__opt:focus-visible { outline: 2px solid var(--be-ink); outline-offset: -2px; }
  .be-sort__opt svg { flex: none; width: 15px; height: 15px; stroke-width: 2; color: var(--be-cta); visibility: hidden; }
  .be-sort__opt[aria-selected="true"] { color: var(--be-ink); font-weight: 600; }
  .be-sort__opt[aria-selected="true"] svg { visibility: visible; }
}
/* from 481px the row has room: the button reads "[icon] Trier : Recommandés  v" */
@media (min-width: 481px) and (max-width: 767px) {
  .be-sort__pre { display: inline; }
  .be-sort__ico { display: inline-block; }
}
@media (max-width: 480px) {
  /* the pencil is already pinned, unframed and word-less for the whole phone range (767px block
     above). Nothing to redefine here: the old rules — 32px bordered square, margin-left:auto,
     and a `content: none` that only French obeyed — are what let the button escape the frame. */
  .be-stay-pill__edit svg { width: 15px; height: 15px; stroke: currentColor; }
}
@media (max-width: 389px) {
  /* under 390px even the trimmed line runs out of room in Spanish (the longest of the six). The
     guests glyph is the first thing to drop: the wording carries the meaning on its own, whereas a
     lone icon stranded at the end of a wrapped line reads as a bug. The calendar glyph stays — it is
     what makes the two dates read as dates at a glance. */
  .be-filters > #be-stay-pill.visible > svg:nth-of-type(2) { display: none; }
  /* and it goes back to 15px here: the two pixels the enlargement added were exactly what tipped
     Spanish onto a second line at 360px (measured 48px instead of 40). The five days stay legible. */
  .be-stay-pill svg { width: 15px; height: 15px; }
}

/* ── 3c. Stay summary frame on mobile — OWNER ARBITRATION 06/09/2026: option A, FROZEN.
   Shown side by side on a 390px phone, three ways to frame the stay summary; the owner picked A.
     A — framed block : white, 1px --be-line, radius 12, full width, 32px pencil square at the right  ← SHIPPED
     B — cream block  : --be-bg, no border            → dropped, barely readable against the white bar
     C — laid card    : white + low soft shadow       → dropped, competes with the apartment cards,
                                                        the only shadowed objects in the house
   The html[data-pill-style] switch that carried B and C is GONE with them. Do not reintroduce a
   switch here: one shipped state, decided.
   The rule this obeys: ONE frame at a time. .be-filters drops its own border under 767px (above),
   so the frame never doubles. Desktop is untouched: nothing here applies over 767px. ── */
@media (max-width: 767px) {
  .be-filters > #be-stay-pill.visible {
    background: #fff; border: 1px solid var(--be-line); border-radius: 12px; box-shadow: none;
  }
  /* the summary is clickable as a whole: the frame answers, never a second border */
  .be-filters > #be-stay-pill.visible:hover { box-shadow: none; }
  .be-filters > #be-stay-pill.visible:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; border-radius: 12px; }
}

/* ── 3d. Stay summary ON DESKTOP — OWNER ARBITRATION 06/09/2026: option 1.
   Until today the summary was a bare sentence floating on the left of a bar whose four controls were
   all framed: the imbalance showed, and nothing said the sentence could be clicked. It now becomes a
   FIELD, the same 40px height and the same radius as the buttons opposite, so the bar reads as one
   row of tools — a field on the left, buttons on the right. Dropped: option 2, which revealed the
   frame on hover only; a visitor who never hovers there would never learn they can change dates.
   No frame within a frame here: the four controls are ALREADY framed inside the bar, so the summary
   is simply joining them at the same rank. The bar keeps its own border on desktop because it is
   sticky while the page scrolls, and that edge is what detaches it from the content passing under. ── */
@media (min-width: 768px) {
  .be-filters > #be-stay-pill.visible {
    height: 40px; padding: 0 14px; background: #fff;
    border: 1px solid var(--be-line); border-radius: var(--be-r-ctl); box-shadow: none;
    transition: border-color var(--be-t), color var(--be-t);
  }
  .be-filters > #be-stay-pill.visible:hover { border-color: var(--be-ink-3); color: var(--be-ink); box-shadow: none; }
  /* the pencil keeps its word here (there is room) and a hairline sets the action apart */
  .be-stay-pill__edit { margin-left: 10px; padding-left: 10px; border-left: 1px solid var(--be-line); }
  /* 16 -> 18px (owner 06/09: "l'icône calendrier est minuscule sur le laptop"). The summary became a
     40px-tall field on this breakpoint, and a 16px glyph floats inside it. The phone got 17px in its
     own block; desktop has the room for one more pixel. */
  .be-stay-pill svg { width: 18px; height: 18px; }
}

/* ── 3e. Narrow desktop and tablet: the compact sort button, borrowed from the phone.
   Measured on 06/09 across 6 languages x 7 widths: the bar already wrapped onto two or three rows
   below 1280px BEFORE today's field (94px in every language at 768-1024, 144px in it/nl/es at 768),
   and the framed field, being wider than a bare sentence, pushed de and it over at 1180 too.
   The three-button sort segment plus its "Trier" label is what costs the room; the compact button
   already built and shipped for the phone gives ~200px back, which is enough from 1180 up.
   From 1280px the full segment returns, because there the row fits — except in Spanish, see below.
   ⚠️ Still wrapping and NOT fixed here: 768-900px, in every language. A tablet cannot hold a 417px
   summary plus the filters and the sort on one row, and the next thing to drop would be the view
   filters themselves, which are the controls visitors actually use. Two clean rows beat a mutilated
   one. Pre-existing (94px there before today), reported to the owner, not silently patched. ── */
/* The LOOK of the compact button and of its panel is declared once for the whole desktop range and
   carries NO `display`: the base rule `.be-sort__btn, .be-sort__menu { display: none }` keeps both
   hidden until one of the two blocks below turns them on. Declaring the look inside a width range
   would leave the Spanish rule past 1280px showing an unstyled button. */
@media (min-width: 768px) {
  .be-sort__btn {
    align-items: center; gap: 6px; box-sizing: border-box; min-width: 0; max-width: 100%;
    height: 40px; padding: 0 12px; margin: 0; background: #fff; border: 1px solid var(--be-line);
    border-radius: var(--be-r-ctl); font: 500 12.5px/1 var(--be-fb); letter-spacing: .02em;
    color: var(--be-ink-2); cursor: pointer;
    transition: background var(--be-t), color var(--be-t), border-color var(--be-t);
  }
  .be-sort__btn:hover, .be-sort__btn[aria-expanded="true"] { background: var(--be-bg); color: var(--be-ink); }
  .be-sort__btn:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; }
  .be-sort__ico { display: inline-block; width: 14px; height: 14px; color: var(--be-sea); }
  .be-sort__pre { display: inline; flex: none; color: var(--be-ink-3); }
  .be-sort__chev { width: 12px; height: 12px; color: var(--be-ink-3); transition: transform var(--be-t); }
  .be-sort__btn[aria-expanded="true"] .be-sort__chev { transform: rotate(180deg); }
  .be-sort__val { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--be-ink); }
  /* 🔴 the panel is styled here but NOT shown: a button that opens nothing is worse than no button,
     so each range block below must turn on `.be-sort__menu` at the same time as `.be-sort__btn`. */
  .be-sort__menu {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 40; min-width: 196px; padding: 4px;
    background: #fff; border: 1px solid var(--be-line); border-radius: var(--be-r-ctl); box-shadow: var(--be-shadow-1);
  }
  .be-sort__menu[hidden] { display: none; }
  .be-sort__opt {
    display: flex; align-items: center; gap: 10px; width: 100%; height: 40px; padding: 0 10px; margin: 0;
    border: 0; border-radius: var(--be-r-ctl); background: none; text-align: left; cursor: pointer;
    font: 500 13px/1 var(--be-fb); letter-spacing: .01em; color: var(--be-ink-2);
    transition: background var(--be-t), color var(--be-t);
  }
  .be-sort__opt > span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .be-sort__opt:hover { background: var(--be-bg); color: var(--be-ink); }
  .be-sort__opt:focus-visible { outline: 2px solid var(--be-ink); outline-offset: -2px; }
  .be-sort__opt svg { flex: none; width: 15px; height: 15px; stroke-width: 2; color: var(--be-cta); visibility: hidden; }
  .be-sort__opt[aria-selected="true"] { color: var(--be-ink); font-weight: 600; }
  .be-sort__opt[aria-selected="true"] svg { visibility: visible; }
}
/* Below 1280px: the compact button replaces the segment, and the list/grid toggle steps aside. */
@media (min-width: 768px) and (max-width: 1279px) {
  /* the toggle is the first thing to go, exactly as it already does on the phone: it was the ONLY
     thing left on the second row at 1024px — one orphan control under a full row reads as a broken
     layout, and the grid is the default nobody switches away from. */
  #be-view-toggle { display: none; }
  .be-sort__label, .be-sort .be-seg { display: none; }
  .be-sort::before { display: none; }
  .be-sort__btn { display: inline-flex; }
  .be-sort__menu { display: block; }
  .be-sort__menu[hidden] { display: none; }
}
/* Spanish is the longest of the six ("Recomendados / Precio / Capacidad" against "Recommandés /
   Prix / Capacité"), and it was the ONE language whose bar wrapped onto two rows at EVERY width,
   1680px included, long before today. It keeps the compact button past 1280px too.
   ⚠️ A language rule is a measurement, not a preference: if a seventh language is added, measure
   `.be-filters` height at 1280 and 1440 before assuming it belongs on either side of this line. */
@media (min-width: 1280px) {
  html[lang^="es"] .be-sort__label, html[lang^="es"] .be-sort .be-seg { display: none; }
  html[lang^="es"] .be-sort::before { display: none; }
  html[lang^="es"] .be-sort__btn { display: inline-flex; }
  html[lang^="es"] .be-sort__menu { display: block; }
  html[lang^="es"] .be-sort__menu[hidden] { display: none; }
}

/* ── 3b. Messages above the grid (owner 05/09 evening): ONE stacked family of STRAIGHT WHITE BANDS, exactly the
      width of the control bar and of the grid. #be-normal-view holds them all as siblings (reserver.html + the
      engine's insertBefore(grid)), so it becomes a flex column: every block stretches to the same left/right,
      `order` fixes the reading order (note > context > offer or merged "arriving tonight" > self check-in >
      counters), one 10px gap. Same padding (14/18 desktop, 12/14 mobile), radius 0, 1px border, plus the 3px
      coloured left rail brought back by the owner on 06/09 (see the rail block below). The meaning is carried
      by that rail AND by the icon in a 32px tinted disc, which is kept as is:
      pool light + sea for context / arrival, coral light + coral for the offer, terracotta light for urgency.
      Same 14px ink typography; the height only follows the content (one line on desktop).
      Gone as bands: #be-scarcity-banner (-> one quiet line .be-note under the control bar, booking-premium.js),
      #be-live-banner (-> viewers chip on the cards), .be-advisor--urgency (same live viewers, as a band). ── */
#be-normal-view { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
#be-normal-view > #be-alt-dates { order: -3; margin: 0; }
#be-normal-view > .be-filters { order: -2; margin: 0; }
#be-normal-view > .be-note { order: -1; }
#be-normal-view > #be-intel { order: 1; margin: 0; max-width: none; }
#be-normal-view > .be-advisor { order: 2; }
#be-normal-view > .be-merged { order: 2; }
#be-normal-view > #be-lastminute-banner { order: 4; }
#be-normal-view > #be-urgency-banner { order: 5; }
#be-normal-view > #be-avail-count { order: 7; }
#be-normal-view > #be-type-notice { order: 8; }
#be-normal-view > .be-grid { order: 10; margin-top: 6px; }
.be-root .be-advisor, .be-root .be-lastminute-banner, .be-root .be-urgency-banner, .be-root .be-merged,
.be-root #be-avail-count, .be-root #be-type-notice {
  box-sizing: border-box; display: flex; align-items: center; gap: 14px;
  margin: 0; padding: 14px 18px; min-height: 48px;
  background: #fff; border: 1px solid var(--be-line-soft); border-radius: 0; box-shadow: none;
  font: 400 14px/1.45 var(--be-fb); color: var(--be-ink); animation: none;
}
/* 3px coloured left rail, BACK at the owner's request (06/09) on a validated before/after. It REPLACES the 1px
   left border of the rule above (border-left-width 3px, never 1+3); top/right/bottom stay 1px --be-line-soft
   and the corners stay square (border-radius 0 is inherited from that rule, nothing re-rounds them here).
   Colour = meaning: coral = the OFFER (#be-merged-banner / .be-advisor), sea = tonight's ARRIVAL
   (#be-lastminute-banner) and, in booking-intel.css, the stay CONTEXT (#be-intel). The tinted icon disc stays.
   padding-left drops 18->16 so the text keeps the exact same x it had with the 1px border.
   Deliberately NO rail: #be-urgency-banner (outside the owner's validated set), .be-note (the quiet scarcity
   line, border:0) and .be-filters (the control bar) — none of them is touched.
   Selectors are CLASSES only, deliberately: #be-merged-banner always carries .be-merged (booking-premium.js
   sets className when it builds the band) and #be-lastminute-banner carries .be-lastminute-banner in the HTML,
   so the classes cover the two ids. Adding the ids here would raise the weight to (1,1,0) and the mobile
   padding override below, at (0,2,0), would silently lose — the merged band then kept an 16px left padding on
   mobile while its neighbours dropped to 12px (measured, 4px off). Staying at (0,2,0), declared AFTER the base
   band rule, is enough to win. booking-intel.css, loaded later, only ever declares #be-intel — no conflict. */
.be-root .be-advisor, .be-root .be-merged { border-left: 3px solid var(--be-cta); padding-left: 16px; }
.be-root .be-lastminute-banner { border-left: 3px solid var(--be-sea); padding-left: 16px; }
.be-root .be-advisor[hidden], .be-root .be-lastminute-banner[hidden], .be-root .be-urgency-banner[hidden], .be-root .be-merged[hidden],
.be-root #be-avail-count[hidden], .be-root #be-type-notice[hidden], .be-root #be-alt-dates[hidden], .be-root .be-note[hidden] { display: none !important; }
/* bands that left the stack (the engine keeps writing them: they feed the note, the merged band and the cards) */
.be-root #be-scarcity-banner, .be-root #be-live-banner, .be-root .be-advisor--validation, .be-root .be-advisor--loading, .be-root .be-advisor--urgency,
.be-root .be-advisor[data-be-merged="1"], .be-root .be-lastminute-banner[data-be-merged="1"] { display: none !important; }
/* the quiet note: no background, no border, 12.5px ink-3, under the control bar */
.be-root .be-note { margin: 8px 0 2px 6px; padding: 0; background: none; border: 0; font: 400 12.5px/1.4 var(--be-fb); color: var(--be-ink-3); }
/* icon disc: 32px, tinted, the only colour of the band (the advisor's text glyphs %, !, i become CSS-masked strokes) */
.be-root .be-advisor__icon, .be-root .be-lastminute-banner__icon, .be-root .be-urgency-banner__icon, .be-root .be-urgency-banner--high .be-urgency-banner__icon, .be-root .be-merged__icon {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 32px; width: 32px; height: 32px;
  border-radius: 50%; border: 0; background: var(--be-pool-light); font-size: 0; line-height: 0; color: var(--be-sea);
}
.be-root .be-advisor--promo .be-advisor__icon, .be-root .be-merged__icon { background: var(--be-coral-light); color: var(--be-cta); }
.be-root .be-urgency-banner__icon, .be-root .be-urgency-banner--high .be-urgency-banner__icon { background: rgba(176, 68, 31, .12); color: var(--be-terracotta); }
.be-root .be-advisor__icon::before { content: ''; width: 18px; height: 18px; background: currentColor; -webkit-mask: var(--be-adv-ico) center / contain no-repeat; mask: var(--be-adv-ico) center / contain no-repeat; }
.be-root .be-advisor__icon { --be-adv-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 16v-4'/%3E%3Cpath d='M12 8h.01'/%3E%3C/svg%3E"); }
.be-root .be-advisor--promo .be-advisor__icon { --be-adv-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 5 5 19'/%3E%3Ccircle cx='6.5' cy='6.5' r='2.5'/%3E%3Ccircle cx='17.5' cy='17.5' r='2.5'/%3E%3C/svg%3E"); }
.be-root .be-lastminute-banner__icon svg, .be-root .be-urgency-banner__icon svg, .be-root .be-merged__icon svg { width: 18px; height: 18px; stroke-width: 2; }
/* text: 14px ink, one baseline row; the strong part 500, the rest ink-2 */
.be-root .be-advisor__content, .be-root .be-merged__content { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.be-root .be-advisor__headline, .be-root .be-merged__title { font: 500 14px/1.45 var(--be-fb); color: var(--be-ink); margin: 0; }
.be-root .be-advisor__body, .be-root .be-merged__sub { font: 400 14px/1.45 var(--be-fb); color: var(--be-ink-2); }
.be-root .be-advisor__dates { display: flex; flex-wrap: wrap; gap: 6px; flex-basis: 100%; margin-top: 6px; }
.be-root .be-advisor__dates:empty { display: none; }
.be-root .be-advisor__date-chip { border-radius: var(--be-r-ctl); font-family: var(--be-fb); font-weight: 500; }
.be-root .be-advisor__pill[class], .be-root .be-merged__pill { margin-left: auto; align-self: center; border-radius: var(--be-r-ctl); font: 600 12px/1 var(--be-fb); letter-spacing: 0; padding: 4px 10px; white-space: nowrap; background: #fff; color: var(--be-cta-hover); border: 1px solid var(--be-cta); }
.be-root .be-merged__pill[hidden] { display: none; }
.be-root .be-advisor__pill::before { display: none; }
.be-root .be-lastminute-banner__text, .be-root .be-urgency-banner__text { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; line-height: 1.45; }
.be-root .be-lastminute-banner__label, .be-root .be-urgency-banner__label { font: 500 14px/1.45 var(--be-fb); color: var(--be-ink); letter-spacing: 0; }
.be-root .be-lastminute-banner__sub, .be-root .be-urgency-banner__sub { font: 400 14px/1.45 var(--be-fb); color: var(--be-ink-2); opacity: 1; margin-top: 0; }
.be-root .be-urgency-banner__close { flex: none; width: 28px; height: 28px; padding: 0; margin: -4px -6px -4px 0; border-radius: var(--be-r-ctl); color: var(--be-ink-3); display: inline-flex; align-items: center; justify-content: center; }
.be-root .be-urgency-banner__close:hover { color: var(--be-ink); background: var(--be-bg); }
.be-root #be-avail-count strong { font-weight: 600; color: var(--be-ink); }
.be-root #be-avail-count::before, .be-root #be-type-notice::before { width: 8px; height: 8px; margin: 0 5px; }
.be-root #be-avail-count::before { background: var(--be-teal); }
.be-root #be-type-notice::before { background: var(--be-sea-grey); }
.be-soldout-sep { font: 500 11px/1 var(--be-fb); letter-spacing: .18em; color: var(--be-ink-3); margin-top: 12px; }
.be-soldout-sep::before, .be-soldout-sep::after { background: var(--be-line); }
@media (max-width: 767px) {
  .be-root .be-advisor, .be-root .be-lastminute-banner, .be-root .be-urgency-banner, .be-root .be-merged,
  .be-root #be-avail-count, .be-root #be-type-notice { padding: 12px 14px; min-height: 44px; gap: 12px; }
  /* same 3px rail on mobile (never reset); the shorthand just above puts the left padding back to 14px, so the
     railed bands restate the -2px compensation. The counters keep 14px: they have no rail. */
  .be-root .be-advisor, .be-root .be-merged, .be-root .be-lastminute-banner { padding-left: 12px; }
  /* icon | text (wraps on its own lines) | pill: the icon never sits alone on a first line */
  .be-root .be-advisor, .be-root .be-merged { flex-wrap: nowrap; align-items: flex-start; }
  .be-root .be-advisor__content, .be-root .be-merged__content { flex: 1 1 0; min-width: 0; }
  .be-root .be-advisor__pill[class], .be-root .be-merged__pill { margin-left: 0; align-self: flex-start; }
  .be-root .be-note { margin: 4px 0 0 4px; font-size: 12px; }
  #be-normal-view > .be-grid { margin-top: 4px; }
}

/* ============================================================
   4. Cards (owner 05/09 evening): the PROD card is the reference. Its geometry, rhythm and language are NOT
   overridden here (booking-engine.css: photo 240 / 185 / 200, body 22/22/16 (18/12 in the dated tiers), name
   19px 600 then description 13px 2 lines (12px margins), chips 16px, footer rule 1px + 16px (12px), CTA 10px
   20px 12px 600 .04em, "See the apartment" link under it). Only the validated deltas:
   - Plus Jakarta Sans everywhere (the --be-fb token), title 600 ink, zero gold (bestseller = quiet chip)
   - one icon family, stroke 2 (lpa-amenity-icons.js): facts, bedding, signals, viewers
   - bedding lines 12.5px with 20px icons (owner 05/09: "a little larger, more premium"), 8px gap, 21px rows
   - LIGHTER BODY (owner 05/09, third round: "reduce the texts a little to reduce the card"): title 18px (17 under
     1024px), description 12.5px / 1.45 on TWO reserved lines, chips 12px with 3px vertical padding (16px icons
     kept), bedding 12.5px / 21px rows (20px icons kept), block margins 14 / 10 instead of 16 / 12. Photo (240),
     price block (28px 700) and CTA (prod size) untouched.
   - ROW ALIGNMENT (owner 05/09, third round): on one grid row every inner block starts at the same height. The
     description is held on 2 lines here (clamp 2 !important beats the engine's inline relaxation to 3-5 lines,
     min-height = 2 lines from 640px); title, facts and bedding are reserved per row by booking-premium.js
     (syncRowAlign, inline min-height); the chips block lays its rows out at flex-start so the reserved height never
     stretches a chip (fourth round, below); the footers stay the engine's (per tier line + per section). content-
     visibility:auto is disabled on the grid cards: 7 cards have nothing to gain from it, a skipped card measures 0
     and its 480px placeholder is wrong anyway (real cards are taller).
   - facts + key amenities as ONE list (.be-card__facts) drawn as prod chips (html.lpa-facts-chips, default: fixed
     28px chips stacked in a natural wrap, facts + 2 niveaux on the duplexes + Wi-Fi, 16px before the bedding,
     owner 05/09 fourth round) or as the Airbnb 2-column list (html.lpa-facts-list); the engine's chips stay in the
     DOM, hidden
   - badges: promo (prod, top-left), ONE signal or "Notre recommandation" stacked UNDER it (or alone top-left),
     viewers chip bottom-right, top-right corner empty, all the same white chip
   - 16px card radius + soft shadow, 6px CTA radius, white/coral at rest, filled coral on hover / focus / active
     and on the recommended card
   ============================================================ */
.be-card { border-radius: var(--be-r-box); border: 1px solid rgba(27, 38, 59, .06); box-shadow: var(--be-shadow-1); overflow: hidden; transition: transform var(--be-t), box-shadow var(--be-t); }
.be-card:hover { transform: translateY(-3px); box-shadow: var(--be-shadow-2); }
.be-card svg { stroke-width: 2; }
/* badges on the photo: promo = prod (top 14 / left 14, radius 6); signal OR recommendation = same white chip,
   stacked under the promo (top 48) or alone at top-left; the top-right corner stays empty */
.be-card__promo-bar { border-radius: var(--be-r-ctl); }
.be-card__promo-bar__label, .be-card__promo-bar__pct { font-family: var(--be-fb); }
.be-card__signal, .be-card__signal--coral, .be-card__signal--reassure, .be-card__signal--neutral, .be-card__signal--rarity, .be-card__reco-badge {
  position: absolute; top: 14px; left: 14px; right: auto; bottom: auto; z-index: 3;
  display: inline-flex; align-items: center; gap: 6px; border-radius: var(--be-r-ctl); padding: 6px 10px; white-space: nowrap; max-width: calc(100% - 28px);
  font: 600 11.5px/1 var(--be-fb); letter-spacing: 0; text-transform: none; color: var(--be-ink); background: rgba(255, 255, 255, .94); box-shadow: 0 1px 6px rgba(0, 0, 0, .14);
}
.be-card__promo-bar ~ .be-card__signal, .be-card__promo-bar ~ .be-card__reco-badge { top: 48px; left: 14px; right: auto; }
.be-card__signal svg, .be-card__reco-badge svg { width: 14px; height: 14px; color: var(--be-sea); stroke: currentColor; flex: none; }
.be-card__signal--rarity svg, .be-card__signal[data-signal-type="coup_de_coeur"] svg, .be-card__signal[data-signal-type="last_minute"] svg, .be-card__reco-badge svg { color: var(--be-cta); }
.be-card__signal span, .be-card__reco-badge span { overflow: hidden; text-overflow: ellipsis; }
/* the recommendation badge REPLACES the engine signal on its card (never two badges in one slot); the body
   node written by booking-intel.js stays in the DOM (the badge is derived from it) but is never shown */
.be-card[data-be-reco="1"] .be-card__signal { display: none; }
.be-card__intel-reco { display: none !important; }
/* "Meilleure vente" (engine, gold pill on the photo): never on the photo, never gold. It becomes a quiet text
   chip next to the name, and disappears when the card carries the recommendation (whose reason already says
   "le plus reserve"). */
.be-card__bestseller { display: none; }
.be-card:has(.be-card__bestseller):not(:has(.be-card__intel-reco)) .be-card__name::after {
  content: 'Le plus réservé'; display: inline-block; vertical-align: 2px; margin-left: 8px;
  font: 600 10px/1 var(--be-fb); letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
  color: var(--be-sea); background: var(--be-pool-light); padding: 4px 6px; border-radius: var(--be-r-ctl);
}
html[lang^="en"] .be-card:has(.be-card__bestseller):not(:has(.be-card__intel-reco)) .be-card__name::after { content: 'Most booked'; }
html[lang^="de"] .be-card:has(.be-card__bestseller):not(:has(.be-card__intel-reco)) .be-card__name::after { content: 'Am häufigsten gebucht'; }
html[lang^="it"] .be-card:has(.be-card__bestseller):not(:has(.be-card__intel-reco)) .be-card__name::after { content: 'Il più prenotato'; }
html[lang^="nl"] .be-card:has(.be-card__bestseller):not(:has(.be-card__intel-reco)) .be-card__name::after { content: 'Meest geboekt'; }
html[lang^="es"] .be-card:has(.be-card__bestseller):not(:has(.be-card__intel-reco)) .be-card__name::after { content: 'El más reservado'; }
.be-card__stock { border-radius: var(--be-r-ctl); border: 0; font: 500 11px/1 var(--be-fb); letter-spacing: .01em; }
/* live viewers (engine per-apartment count, or the page total on the recommended card): white chip, bottom-right,
   eye 14px stroke 2 sea; the carousel dots yield on that card (they would sit under the chip) */
.be-card__live, .be-card__live-total {
  position: absolute; bottom: 12px; right: 12px; left: auto; top: auto; z-index: 3;
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 9px; max-width: calc(100% - 24px);
  border-radius: var(--be-r-ctl); border: 0; -webkit-backdrop-filter: none; backdrop-filter: none;
  font: 500 11.5px/1 var(--be-fb); color: var(--be-ink); background: rgba(255, 255, 255, .92); box-shadow: 0 1px 6px rgba(0, 0, 0, .14); white-space: nowrap;
}
.be-card__live:empty { display: none; }
.be-card__live--active { background: rgba(255, 255, 255, .92); border: 0; }
.be-card__live svg, .be-card__live--active svg, .be-card__live-total svg { width: 14px; height: 14px; stroke-width: 2; color: var(--be-sea); opacity: 1; animation: none; flex: none; }
.be-card__live span, .be-card__live-total span { overflow: hidden; text-overflow: ellipsis; }
.be-card__photo:has(.be-card__live--active:not(:empty), .be-card__live-total) .be-car__dots { display: none; }
/* body: prod geometry (19px, 12px margin); the title is Plus Jakarta Sans 600 ink (owner 05/09: same family as
   the rest of the card, Cormorant stays on the hero and the section titles) */
.be-card__name { font-family: var(--be-fb); font-weight: 600; color: var(--be-ink); letter-spacing: -.005em; }
.be-card__desc { color: var(--be-ink-2); }
/* lighter body + row alignment (owner 05/09, third round), see the section header. The grid cards render for
   real (no content-visibility placeholder): syncRowAlign measures every card, on screen or not. */
#be-grid .be-card { content-visibility: visible; contain-intrinsic-size: auto; }
.be-card .be-card__name { font-size: 18px; margin-bottom: 10px; box-sizing: border-box; }
@media (max-width: 1023px) { .be-card .be-card__name { font-size: 17px; } }
/* description (owner 05/09, FIFTH round): back to 12.5px / 1.45 — "un peu plus grand, en harmonie avec le
   reste". 12.5px is exactly the bedding size, which is what the harmony asks for; 1.45 keeps the two reserved
   lines at 2 x 18.125 = 36.25px (min-height 2.9em). The +2.65px this costs is paid back by the bedding margin
   and the bedding rows below. Never under 12px. */
.be-card:not(.be-card--xchain) .be-card__desc { font-size: 12.5px; line-height: 1.45; margin-bottom: 10px; -webkit-line-clamp: 2 !important; box-sizing: border-box; }
@media (min-width: 640px) { .be-card:not(.be-card--xchain) .be-card__desc { min-height: 2.9em; } }
.be-card .be-card__beds, .be-card .be-card__facts { box-sizing: border-box; }
/* facts + amenities: ONE list (booking-premium.js), the engine's chips hidden once the list exists */
.be-card[data-be-facts="1"] .be-card__chips:not(.be-card__xchips) { display: none; }
.be-card__facts { list-style: none; margin: 0 0 14px; padding: 0; }
.be-grid:not(.be-grid--rows) .be-tier .be-card__facts { margin-bottom: 10px; }
.be-card__fact { display: flex; align-items: center; min-width: 0; }
.be-card__fact svg { flex: none; stroke-width: 2; }
.be-card__fact span { min-width: 0; }
.be-card__fact a { display: inline-flex; align-items: center; gap: inherit; color: inherit; text-decoration: none; min-width: 0; }
.be-card__fact a:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 3px; border-radius: var(--be-r-ctl); }
/* variant A (default) = the prod chips, stacked as they come (owner 05/09, fourth round: natural wrap, width to the
   content, 6px gaps, like prod), with what fixes the defect the owner saw (24px chips here, 40px there): FIXED 28px
   pills, never stretched (the row min-height posed by syncRowAlign lands UNDER the chips: align-content flex-start),
   and 16px (prod) between the block (equalised per row) and the bedding. Content = the engine facts (capacity, m2,
   type, view, air / heating when the engine prints it) + "2 niveaux" on the two duplexes + Wi-Fi; no dishwasher on
   the cards (owner: not a selling point): the CSS hides every other amenity li and the "+N" link (list variant).
   5 to 7 chips per card, 1 to 3 rows, accepted. Bordered pill, icon 16 sea + text 12 ink on one line, ellipsis only
   if a chip were wider than the card. Under 360px the chips take the engine's own narrow values (11px, 8px). */
html.lpa-facts-chips .be-card__facts { display: flex; flex-wrap: wrap; align-content: flex-start; align-items: flex-start; gap: 6px; }
html.lpa-facts-chips .be-card__facts, html.lpa-facts-chips .be-grid:not(.be-grid--rows) .be-tier .be-card__facts { margin-bottom: 16px; }
html.lpa-facts-chips .be-card__fact { box-sizing: border-box; flex: none; height: 28px; max-width: 100%; min-width: 0; overflow: hidden; gap: 6px; background: #F2EDE6; border: 1px solid var(--be-border, #DDD8CF); border-radius: var(--be-r-ctl); padding: 0 10px; font: 400 12px/18px var(--be-fb); color: var(--be-ink); white-space: nowrap; }
html.lpa-facts-chips .be-card__fact span { overflow: hidden; text-overflow: ellipsis; }
html.lpa-facts-chips .be-card__fact svg { width: 16px; height: 16px; stroke: var(--be-sea); color: var(--be-sea); }
html.lpa-facts-chips .be-card__fact--amen:not([data-key="wifi"]), html.lpa-facts-chips .be-card__fact--more { display: none; }
/* duplexes only (owner 05/09, fifth round): "2 salles de bain" enters, Wi-Fi leaves — a bathroom count sells,
   Wi-Fi is a standard. Keyed on the two_bathrooms fact, which only the two duplexes carry (room_amenities), so
   no code is hardcoded here. CHIPS VARIANT ONLY: the list variant (?facts=list) keeps its Wi-Fi row, and the
   "+N" counter is computed in the JS from the amenity keys, which this rule does not touch — the count stays
   honest. Without it those cards would show 8 chips and gain a fourth row. */
html.lpa-facts-chips .be-card__facts:has(> [data-fact="two_bathrooms"]) .be-card__fact--amen[data-key="wifi"] { display: none; }
/* mobile geometry, sixth round (owner 05/09). At 390px the chips block is 320px wide and the FR label
   "2 salles de bain" is the longest chip of the whole set (129.16px; the other languages are short —
   "2 bathrooms" 116.31, "2 Badezimmer", "2 bagni"). Measured on the served TEST build, the row that refuses
   its third chip is capacity + surface + bedrooms: 325.39px needed for 320 available in FR, 327.07 in EN.
   DEFICIT = 7.07px worst case, nothing more. Only the geometry moves, and only the first lever: the chip's
   horizontal padding 10 -> 8px, i.e. 4px per chip, 12px on a three-chip row (4.93px of margin on the worst
   case). Untouched, as decided: the words and their translations, the 28px height, the 12px/18px body, the
   16px icon, the 6px gap between chips and the 6px between the icon and its text, and letter-spacing.
   >= 481px is outside this query: the desktop card does not move by one pixel.
   Measured consequence, stated rather than hidden: the same 12px also lands on 2BRSEAVIEWPAX7, whose own
   binding row was only 3.54px (FR) / 5.21px (EN) short — SMALLER than the duplex deficit. No uniform saving
   can free the duplexes without also compacting that card, which drops from 3 chip rows to 2 (-34px). */
@media (max-width: 480px) { html.lpa-facts-chips .be-card__fact { padding: 0 8px; } }
@media (max-width: 359px) { html.lpa-facts-chips .be-card__fact { font-size: 11px; padding: 0 8px; } }

/* ── The VIEW chip — owner arbitration 06/09/2026 (colour of option B, position of option D).
   ONE chip carries colour, and it is the view: it is the only attribute that moves the price from one
   apartment to the next, and the first a visitor compares. It also takes the FIRST place in the row,
   ahead of capacity and surface — free in pixels, and stronger than colour alone.
   ⚠️ What NOT to do, measured on production: it tints THREE chips out of four (pool view, sea view AND
   air conditioning), in three neighbouring blues. One coloured chip out of six is seen; three are not.
   Air conditioning and Wi-Fi are expected by everyone: colouring them highlights what decides nothing.
   Specificity: `html.lpa-facts-chips .be-card__fact` is 0,2,1 — the plain attribute selector (0,2,0)
   would lose. Hence the parent class in front. ── */
.be-card__facts .be-card__fact[data-fact="sea_view"],
.be-card__facts .be-card__fact[data-fact="pool_view"] { order: -1; }
.be-card__facts .be-card__fact[data-fact="sea_view"] { background: var(--be-sea-bg); border-color: transparent; color: var(--be-sea); }
.be-card__facts .be-card__fact[data-fact="sea_view"] svg { stroke: var(--be-sea); color: var(--be-sea); }
.be-card__facts .be-card__fact[data-fact="pool_view"] { background: var(--be-pool-bg); border-color: transparent; color: var(--be-pool-ink); }
.be-card__facts .be-card__fact[data-fact="pool_view"] svg { stroke: var(--be-pool-ink); color: var(--be-pool-ink); }
/* variant B = the Airbnb list: 2 columns, icon 20 ink + text 14 ink-2, no border, no disc, no background */
html.lpa-facts-list .be-card__facts { display: grid; grid-template-columns: 1fr 1fr; column-gap: 16px; row-gap: 10px; }
html.lpa-facts-list .be-card__fact { gap: 12px; background: none; border: 0; padding: 0; font: 400 14px/1.3 var(--be-fb); color: var(--be-ink-2); }
html.lpa-facts-list .be-card__fact svg { width: 20px; height: 20px; flex: 0 0 20px; stroke: var(--be-ink); color: var(--be-ink); }
html.lpa-facts-list .be-card__fact--more a { color: var(--be-sea); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(47, 93, 115, .35); transition: color var(--be-t); }
html.lpa-facts-list .be-card__fact--more a:hover { color: var(--be-ink); text-decoration-color: currentColor; }
@media (max-width: 639px) {
  html.lpa-facts-list .be-card__fact { font-size: 13px; }
}
@media (max-width: 359px) { html.lpa-facts-list .be-card__facts { grid-template-columns: 1fr; } }
/* bedding (owner 05/09): one line per space, text 12.5px (third round: 13 -> 12.5), its icon (double bed, bunk,
   sofa bed) 20px sea stroke 2 centred on the text, 8px gap, 20px rows (22 -> 21 -> 20); same values in both facts
   variants and in every tier.
   FIFTH round (owner: "reduis l espace vide entre la literie et le trait du pied, pour reduire la carte").
   Two values move here, the icon (20px) and the text (12.5px) staying untouched as decided:
   - rows 21 -> 20px. 20px is the FLOOR, not an arbitrary value: the row is a flex line whose tallest child is
     the 20px icon (the text box is 12.5 x 1.5 = 18.75px), so a min-height under 20 buys nothing and 19px would
     be a lie in the stylesheet. Saves 1px per bedding line, i.e. 4px on the densest card (4 lines).
   - margin under the bedding block 10 -> 4px (the engine's value is 10). The air before the rule is the SUM of
     this margin and the .be-card__spacer floor (8px, owner minimum, untouched): 10 + 8 + 0.9 of line-box
     residue = 19.8px measured, 4 + 8 + 0.9 = 12.9px after. The 8px of air the owner asked for on 30/08 is
     preserved in full — what leaves is the duplicated margin above it.
   The rows layout keeps its own 18px margin (.be-grid--rows .be-tier .be-card__beds, specificity 0,3,0 in
   booking-engine.css beats the 0,2,0 here): the OTA rows are untouched. */
.be-card .be-card__beds { font-size: 12.5px; line-height: 1.5; margin-bottom: 4px; }
.be-card .be-card__beds-line { display: flex; align-items: center; gap: 8px; min-height: 20px; }
/* Owner 06/09 : « agrandir un peu les icônes de literie pour un rendu crystal clear », puis
   « la même taille que les amenities sur Airbnb », puis « pas trop lourd, garder une épaisseur de
   trait et une taille premium ». Réponse : 20 -> 24px (la valeur d'Airbnb) ET trait affiné 2 -> 1,7.

   🔑 CE QUI COMPTE N'EST PAS LE RÉGLAGE, C'EST L'ENCRE À L'ÉCRAN. Le trait est défini dans le
   viewBox du dessin puis mis à l'échelle avec lui : `stroke-width: 2` dans un viewBox de 24 rend
   1,67px sur une icône de 20px, et 2,00px sur une icône de 24px. Agrandir SANS toucher au trait
   ajoutait donc un cinquième d'encre — c'est exactement la lourdeur que l'owner a vue.
   Mesuré :   20px trait 2 -> 1,67px d'encre  ·  24px trait 2 -> 2,00  ·  24px trait 1,7 -> 1,70
   L'icône gagne 20 % de taille et garde son poids d'encre au centième près.
   1,5 essayé et écarté : élégant, mais l'icône s'efface devant le libellé en gras qu'elle annonce.
   ⚠️ Airbnb pose 24px sur un libellé de 16px ; ici le libellé fait 12,5px, donc l'icône pèse déjà
   plus lourd chez nous que chez eux — raison de plus pour ne pas remonter ce trait.
   Coût : bloc literie 43 -> 51px, carte 548 -> 556px sur téléphone. */
.be-card .be-card__beds-line svg { width: 24px; height: 24px; flex: 0 0 24px; stroke: var(--be-sea); stroke-width: 1.7; color: var(--be-sea); display: inline-block; }
.be-card__beds-line em { font-style: normal; font-weight: 600; color: var(--be-ink); }
.be-card--unavailable .be-card__facts { opacity: .6; }
/* footer: prod (rule 1px --be-border, padding-top 16 / 12 in tiers, price left, actions right). The old total
   keeps the prod strike-through scale. */
.be-card__price-orig { font-family: var(--be-fb); }
/* CTA (owner 05/09 evening): the PROD size (10px 20px, 12px 600 .04em, nowrap, inline right of the price block,
   on mobile too), radius 6, white with a 1.5px coral border and coral text at rest, filled coral when the card is
   hovered, on :hover / :focus-visible / :active (darker coral on the button itself), filled from the start on
   the recommended card: one main gesture per screen. Partial-block and split-stay CTAs share the rest state. */
.be-card__cta { background: #fff; color: var(--be-cta); border: 1.5px solid var(--be-cta); border-radius: var(--be-r-ctl); font-family: var(--be-fb); text-transform: none; transition: background .2s ease, color .2s ease, border-color .2s ease, transform .15s ease; }
.be-card:has(:hover) .be-card__cta:not(.be-card__cta--alt):not(.be-card__blk-cta):not(.be-card__split-cta),
.be-card__cta:focus-visible, .be-card__cta:active,
.be-card[data-be-reco="1"] .be-card__cta:not(.be-card__cta--alt) { background: var(--be-cta); border-color: var(--be-cta); color: #fff; }
.be-card__cta:hover, .be-card__cta:active,
.be-card:has(:hover) .be-card__cta:not(.be-card__cta--alt):not(.be-card__blk-cta):not(.be-card__split-cta):hover,
.be-card:has(:hover) .be-card__cta:not(.be-card__cta--alt):not(.be-card__blk-cta):not(.be-card__split-cta):active,
.be-card[data-be-reco="1"] .be-card__cta:not(.be-card__cta--alt):hover { background: var(--be-cta-hover); border-color: var(--be-cta-hover); color: #fff; }
.be-card__cta:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; }
.be-card__cta[disabled] { background: var(--be-border); border-color: var(--be-border); color: #fff; cursor: not-allowed; transform: none; }
.be-card__cta--alt { background: transparent; color: var(--be-ink-3); border-color: var(--be-ink-3); text-transform: none; letter-spacing: .02em; font-weight: 500; }
.be-card__cta--alt:hover, .be-card__cta--alt:active { background: var(--be-ink-3); border-color: var(--be-ink-3); color: #fff; }
.be-card__blk-cta, .be-card__split-cta { text-transform: none; letter-spacing: .02em; font-weight: 600; }
.be-card__know-more { font-family: var(--be-fb); text-underline-offset: 3px; transition: color var(--be-t); }
.be-card__know-more:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 3px; border-radius: var(--be-r-ctl); }
.be-card__pay-hint { font-family: var(--be-fb); }
.be-card__unavail { font: 500 11.5px/1.4 var(--be-fb); letter-spacing: .08em; background: rgba(27, 38, 59, .5); }
.be-card__price-label--nextavail { border-radius: var(--be-r-ctl); border-width: 1px; font-weight: 500; text-transform: none; letter-spacing: 0; }
.be-card__price-label--nextavail:hover, .be-card__price-label--nextavail:focus-visible { transform: none; }
.be-empty__title { font-weight: 400; }
.be-empty__cta { border-radius: var(--be-r-ctl); background: var(--be-ink); font: 600 12px/1 var(--be-fb); letter-spacing: .1em; text-transform: uppercase; padding: 14px 24px; transition: background var(--be-t); }
.be-empty__cta:hover { background: var(--be-cta); }
/* carousel: arrows only on hover (desktop); swipe + dots on touch */
.be-car__nav { width: 32px; height: 32px; background: rgba(255, 255, 255, .94); box-shadow: 0 1px 6px rgba(0, 0, 0, .16); color: var(--be-ink); }
.be-car__dots span { width: 5px; height: 5px; }
@media (max-width: 639px) {
  .be-car__nav { display: none; }
  .be-results { padding: 24px 12px 48px; }
}
/* rows view (engine list toggle): the footer is a right-hand column, untouched */
.be-grid--rows .be-tier .be-card__footer { border-left-color: var(--be-line-soft); }

/* ============================================================
   5. Mobile bar (spec 2.5, mobile): "10 nov. -> 14 nov. · 2 voyageurs  Modifier", shown by booking-premium.js
   once the FIRST CARD has passed under the header. Hidden state = moved above the viewport by its own height
   AND the header height, and visibility:hidden: nothing can show through the transparent header on the hero.
   z-index 890: under the header (900), the mobile menu (1000) and the widget calendar (1100).
   ============================================================ */
#be-mobile-bar {
  position: fixed; top: var(--be-hdr-h); left: 0; right: 0; z-index: 890;
  display: flex; align-items: center; gap: 12px; padding: 8px 16px; min-height: 48px;
  background: rgba(255, 255, 255, .97); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--be-line-soft); box-shadow: 0 2px 12px rgba(27, 38, 59, .08);
  transform: translateY(calc(-100% - var(--be-hdr-h) - 8px)); visibility: hidden; pointer-events: none;
  transition: transform .25s ease, visibility 0s linear .25s;
  font: 400 13px/1.3 var(--be-fb); color: var(--be-ink-2);
}
#be-mobile-bar.is-on { transform: translateY(0); visibility: visible; pointer-events: auto; transition: transform .25s ease, visibility 0s; }
#be-mobile-bar svg { width: 17px; height: 17px; stroke: var(--be-sea); stroke-width: 2; flex: none; }
.be-mbar__text { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.be-mbar__text strong { font-weight: 500; color: var(--be-ink); }
/* the guests glyph sits inside the sentence, so it must ride the baseline like a letter — and it
   needs its own air: the single space around it in the markup collapses against the bold nights. */
#be-mobile-bar .be-mbar__text svg { display: inline-block; vertical-align: -3px; margin: 0 3px 0 5px; }
/* ── Owner 06/09: harmonised with the stay summary. This bar repeats what the summary says, so it
   wears the same clothes: the pencil in a plain square, no frame of its own, a hairline setting the
   action apart from the information, and the tinted square answering only on press. The old bordered
   box with the word in spaced capitals read louder than the sentence it labelled — on a reminder,
   that is backwards. The word survives as aria-label and tooltip (see booking-premium.js). ── */
.be-mbar__btn {
  position: relative; flex: none; width: 34px; height: 34px; padding: 0; margin: 0 0 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: 8px; background: none; color: var(--be-sea); cursor: pointer;
  transition: background var(--be-t), color var(--be-t);
}
.be-mbar__btn::before { content: ''; position: absolute; left: -6px; top: 6px; bottom: 6px; width: 1px; background: var(--be-line); }
/* the drawn square is 34px, which is below the 44px a thumb expects. Here the sentence beside it is
   NOT clickable (unlike the summary, where the whole block is), so the button is the only target:
   an invisible collar brings it to 44 without changing anything on screen. */
.be-mbar__btn::after { content: ''; position: absolute; inset: -5px; }
#be-mobile-bar .be-mbar__btn svg { width: 17px; height: 17px; stroke: currentColor; }
.be-mbar__btn:hover, .be-mbar__btn:active { background: var(--be-bg); color: var(--be-ink); }
.be-mbar__btn:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; }
@media (min-width: 768px) { #be-mobile-bar { display: none; } }

/* ============================================================
   6. Group block under the grid (spec 2.7), rendered by booking-premium.js (ids kept)
   ============================================================ */
.be-group-entry { text-align: center; border-top: 1px solid var(--be-line-soft); margin-top: 48px; padding: 48px 24px 16px; }
.be-group-entry__inner { max-width: 640px; margin: 0 auto; }
.be-group-entry__eyebrow { font: 500 11px/1 var(--be-fb); letter-spacing: .28em; text-transform: uppercase; color: var(--be-cta); margin: 0 0 16px; }
.be-group-entry__title { font: 400 clamp(26px, 3vw, 34px)/1.15 var(--be-ft); color: var(--be-ink); margin: 0 0 8px; }
.be-group-entry__label { font: 300 15px/1.6 var(--be-fb); color: var(--be-ink-2); margin: 0 0 24px; }
.be-group-entry__form { display: flex; align-items: stretch; justify-content: center; gap: 8px; flex-wrap: wrap; }
.be-group-entry__lbl { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.be-group-entry__input { width: 88px; height: 48px; padding: 0 8px; font: 500 16px/1 var(--be-fb); text-align: center; border: 1px solid var(--be-line); border-radius: var(--be-r-ctl); background: #fff; color: var(--be-ink); transition: border-color var(--be-t); }
.be-group-entry__input:focus { outline: none; border-color: var(--be-ink); }
.be-group-entry__input:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; }
.be-group-entry__btn { height: 48px; font: 600 12px/1 var(--be-fb); letter-spacing: .1em; text-transform: uppercase; padding: 0 24px; border-radius: var(--be-r-ctl); border: 1px solid var(--be-cta); background: var(--be-cta); color: #fff; cursor: pointer; transition: background var(--be-t), border-color var(--be-t); }
.be-group-entry__btn:hover { background: var(--be-cta-hover); border-color: var(--be-cta-hover); opacity: 1; }
.be-group-entry__btn:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 3px; }
.be-group-entry__page { display: inline-flex; align-items: center; gap: 8px; margin-top: 16px; font: 500 12px/1 var(--be-fb); letter-spacing: .08em; text-transform: uppercase; color: var(--be-ink); text-decoration: none; border: 1px solid var(--be-ink); border-radius: var(--be-r-ctl); padding: 0 24px; height: 44px; transition: background var(--be-t), color var(--be-t); }
.be-group-entry__page:hover { background: var(--be-ink); color: #fff; }
.be-group-entry__page:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 3px; }
.be-group-entry__page svg { width: 14px; height: 14px; }
.be-group-entry__error { font: 400 13px/1.4 var(--be-fb); color: var(--be-err); margin: 12px 0 0; }
.be-group-entry__note { font: 300 13px/1.6 var(--be-fb); color: var(--be-ink-3); margin: 16px 0 0; }
.be-group-entry__note a { color: var(--be-sea); text-decoration: underline; text-underline-offset: 3px; }
.be-group-entry__note a:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; border-radius: var(--be-r-ctl); }
body.lpa-group #be-group-entry, body.lpa-group .be-seo-intro { display: none; }
/* the chat bubble (chat-widget.js, fixed bottom-right, ~72px) must never cover the last control on mobile */
@media (max-width: 767px) { .be-group-entry { padding-bottom: 96px; } html { scroll-padding-bottom: 96px; } }

/* ============================================================
   7. Group view (configurator, DOM unchanged): identity + meaningful labels written by booking-premium.js
   ============================================================ */
#be-group-view [class^="be-"], #be-group-view [class*=" be-"] { font-family: var(--be-fb); }
.be-group-header { border-bottom: 1px solid var(--be-line-soft); }
.be-group-header__title { font: 400 30px/1.15 var(--be-ft); color: var(--be-ink); }
.be-group-header__back { color: var(--be-sea); font-size: 13px; text-underline-offset: 3px; }
.be-group-header__back:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 2px; border-radius: var(--be-r-ctl); }
.be-group-configs__title { font: 500 11px/1 var(--be-fb); letter-spacing: .18em; color: var(--be-ink-3); }
.be-cfg-card { border-radius: var(--be-r); border: 1px solid var(--be-line-soft); box-shadow: var(--be-shadow-1); transition: box-shadow var(--be-t); }
.be-cfg-card:hover { box-shadow: var(--be-shadow-2); }
.be-cfg-card--recommended, .be-cfg-card--coup { border-color: var(--be-ink); border-width: 1px; }
.be-cfg-card__badge { background: var(--be-ink); color: #fff; font: 500 11px/1 var(--be-fb); letter-spacing: .14em; text-transform: uppercase; padding: 8px 16px; }
.be-cfg-card__badge--alt { background: var(--be-pool-light); color: var(--be-sea); }
.be-cfg-card__coup { border-radius: var(--be-r-ctl); font-weight: 500; }
.be-cfg-card__apt-row { border-radius: var(--be-r-ctl); border-color: var(--be-line-soft); }
.be-cfg-card__apt-count { color: var(--be-ink); font-weight: 600; }
.be-cfg-card__apt-name { font: 600 16px/1.25 var(--be-fb); color: var(--be-ink); letter-spacing: -.005em; }
.be-cfg-card__promo-bar { border-radius: var(--be-r-ctl); font-weight: 600; }
.be-cfg-card__footer { background: #fff; border-top: 1px solid var(--be-line-soft); }
.be-cfg-card__price { font: 600 24px/1 var(--be-fb); color: var(--be-ink); }
.be-cfg-card__cta-quote { border-radius: var(--be-r-ctl); border-color: var(--be-ink); color: var(--be-ink); font: 600 12px/1 var(--be-fb); letter-spacing: .08em; text-transform: uppercase; padding: 14px 16px; transition: background var(--be-t), color var(--be-t); }
.be-cfg-card__cta-quote:hover { background: var(--be-ink); border-color: var(--be-ink); color: #fff; }
.be-cfg-card__cta-book { border-radius: var(--be-r-ctl); font: 600 12px/1 var(--be-fb); letter-spacing: .08em; text-transform: uppercase; padding: 14px 16px; transition: background var(--be-t), border-color var(--be-t); }
.be-cfg-card__cta-book:hover { background: var(--be-cta-hover); border-color: var(--be-cta-hover); opacity: 1; }
.be-cfg-card__cta-quote:focus-visible, .be-cfg-card__cta-book:focus-visible, .be-cfg-more-btn:focus-visible, .be-group-footer__cta-contact:focus-visible { outline: 2px solid var(--be-ink); outline-offset: 3px; }
.be-cfg-card__why { border-radius: var(--be-r-ctl); background: var(--be-bg); border-color: var(--be-line-soft); }
.be-cfg-card__perk { border-radius: var(--be-r-ctl); border-style: solid; border-color: var(--be-line); }
.be-cfg-more-btn { border-radius: var(--be-r-ctl); border-color: var(--be-ink); color: var(--be-ink); font: 600 12px/1 var(--be-fb); letter-spacing: .08em; text-transform: uppercase; transition: background var(--be-t), color var(--be-t); }
.be-cfg-more-btn:hover { background: var(--be-ink); border-color: var(--be-ink); color: #fff; }
.be-group-footer { border-radius: var(--be-r-panel); background: var(--be-bg); }
.be-group-footer__eyebrow { letter-spacing: .28em; font-weight: 500; }
.be-group-footer__title { font: 400 30px/1.15 var(--be-ft); color: var(--be-ink); }
.be-group-footer__profile { border-radius: var(--be-r-ctl); background: #fff; border-color: var(--be-line); }
.be-group-footer__cta-contact { border-radius: var(--be-r-ctl); font: 600 12px/1 var(--be-fb); letter-spacing: .1em; text-transform: uppercase; padding: 14px 24px; transition: background var(--be-t); }
.be-group-footer__cta-contact:hover { background: var(--be-cta-hover); opacity: 1; }

/* ── Lining figures (owner 06/09/2026: "je ne veux pas des chiffres en décalé").
   Cormorant serves old-style figures by default — the 1 reads as an I, the 3 4 5 7 9 drop below the
   baseline. The site-wide fix is one declaration; this file carries the three title selectors that
   apply the display family here.
   🔴 MUST STAY LAST IN THE FILE: the three rules above set the `font:` shorthand, which resets
   font-variant-numeric to `normal`. Placed before them, this line would be wiped with no warning. ── */
.be-group-entry__title, .be-group-header__title, .be-group-footer__title {
  font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1, "onum" 0;
}
.be-group-footer__phone { font-weight: 500; }

/* ============================================================
   8. Motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .be-card, .be-card__photo img, .be-card__photo--car .be-slide, #be-mobile-bar, .be-stay-pill, .be-card__signal, .be-card__reco-badge, .be-cfg-card,
  .be-filters .be-filter, .be-sort .be-seg button, #be-view-toggle button, .be-card__cta, .be-card__know-more, .be-mbar__btn,
  .be-group-entry__btn, .be-group-entry__page, .be-cfg-card__cta-book, .be-cfg-card__cta-quote, .be-cfg-more-btn { transition: none !important; animation: none !important; }
  .be-card:hover { transform: none; }
  html { scroll-behavior: auto; }
}
